diff --git a/.github/workflows/build.yml.in b/.github/build.in.yml similarity index 96% rename from .github/workflows/build.yml.in rename to .github/build.in.yml index 37ec2538a43ce..1151b959d0691 100644 --- a/.github/workflows/build.yml.in +++ b/.github/build.in.yml @@ -1,3 +1,4 @@ +# This is the master file for autogenerating `.github/workflows/{bors, build_fork, build }.yml`. jobs: # Cancels previous runs of jobs in this file @@ -148,8 +149,10 @@ jobs: - name: get cache id: get run: | - lake exe cache clean - lake exe cache get + 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" - name: build mathlib id: build @@ -316,7 +319,7 @@ jobs: - if: contains(steps.PR.outputs.pr_labels, 'auto-merge-after-CI') name: If `auto-merge-after-CI` is present, add a `bors merge` comment. - uses: GrantBirki/comment@v2.0.1 + uses: GrantBirki/comment@v2 with: token: ${{ secrets.AUTO_MERGE_TOKEN }} issue-number: ${{ steps.PR.outputs.number }} diff --git a/.github/workflows/add_label_from_comment.yml b/.github/workflows/add_label_from_comment.yml index 12e9585a4639d..dd2a1835b0a1f 100644 --- a/.github/workflows/add_label_from_comment.yml +++ b/.github/workflows/add_label_from_comment.yml @@ -7,7 +7,7 @@ on: jobs: add_ready_to_merge_label: name: Add ready-to-merge label - if: (toJSON(github.event.issue.pull_request) != 'null') && (startsWith(github.event.comment.body, 'bors r+') || contains(toJSON(github.event.comment.body), '\r\nbors r+') || startsWith(github.event.comment.body, 'bors merge') || contains(toJSON(github.event.comment.body), '\r\nbors merge')) + if: github.event.issue.pull_request && (startsWith(github.event.comment.body, 'bors r+') || contains(toJSON(github.event.comment.body), '\nbors r+') || startsWith(github.event.comment.body, 'bors merge') || contains(toJSON(github.event.comment.body), '\nbors merge')) runs-on: ubuntu-latest steps: - uses: octokit/request-action@v2.x @@ -74,7 +74,7 @@ jobs: add_delegated_label: name: Add delegated label - if: (toJSON(github.event.issue.pull_request) != 'null') && (startsWith(github.event.comment.body, 'bors d') || contains(toJSON(github.event.comment.body), '\r\nbors d')) + if: github.event.issue.pull_request && (startsWith(github.event.comment.body, 'bors d') || contains(toJSON(github.event.comment.body), '\nbors d')) runs-on: ubuntu-latest steps: - uses: octokit/request-action@v2.x diff --git a/.github/workflows/add_label_from_review.yml b/.github/workflows/add_label_from_review.yml index 62f047b912236..345d1889e2a18 100644 --- a/.github/workflows/add_label_from_review.yml +++ b/.github/workflows/add_label_from_review.yml @@ -7,7 +7,7 @@ on: jobs: add_ready_to_merge_label: name: Add ready-to-merge label - if: (startsWith(github.event.review.body, 'bors r+') || contains(toJSON(github.event.review.body), '\r\nbors r+') || startsWith(github.event.review.body, 'bors merge') || contains(toJSON(github.event.review.body), '\r\nbors merge')) + if: (startsWith(github.event.review.body, 'bors r+') || contains(toJSON(github.event.review.body), '\nbors r+') || startsWith(github.event.review.body, 'bors merge') || contains(toJSON(github.event.review.body), '\nbors merge')) runs-on: ubuntu-latest steps: - uses: octokit/request-action@v2.x @@ -74,7 +74,7 @@ jobs: add_delegated_label: name: Add delegated label - if: (startsWith(github.event.review.body, 'bors d') || contains(toJSON(github.event.review.body), '\r\nbors d')) + if: (startsWith(github.event.review.body, 'bors d') || contains(toJSON(github.event.review.body), '\nbors d')) runs-on: ubuntu-latest steps: - uses: octokit/request-action@v2.x diff --git a/.github/workflows/bors.yml b/.github/workflows/bors.yml index c5a421e26f3ef..41eca3afd4043 100644 --- a/.github/workflows/bors.yml +++ b/.github/workflows/bors.yml @@ -1,7 +1,7 @@ # DO NOT EDIT THIS FILE!!! # This file is automatically generated by mk_build_yml.sh -# Edit build.yml.in instead and run mk_build_yml.sh to update. +# Edit .github/build.in.yml instead and run mk_build_yml.sh to update. # Forks of mathlib and other projects should be able to use build_fork.yml directly # The jobs in this file run on self-hosted workers and will not be run from external forks @@ -162,8 +162,10 @@ jobs: - name: get cache id: get run: | - lake exe cache clean - lake exe cache get + 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" - name: build mathlib id: build @@ -330,7 +332,7 @@ jobs: - if: contains(steps.PR.outputs.pr_labels, 'auto-merge-after-CI') name: If `auto-merge-after-CI` is present, add a `bors merge` comment. - uses: GrantBirki/comment@v2.0.1 + uses: GrantBirki/comment@v2 with: token: ${{ secrets.AUTO_MERGE_TOKEN }} issue-number: ${{ steps.PR.outputs.number }} diff --git a/.github/workflows/bot_fix_style_comment.yaml b/.github/workflows/bot_fix_style_comment.yaml new file mode 100644 index 0000000000000..4414eb4b576b5 --- /dev/null +++ b/.github/workflows/bot_fix_style_comment.yaml @@ -0,0 +1,93 @@ +name: bot fix style (comment) + +on: + issue_comment: + types: [created, edited] + +jobs: + fix_style: + name: Fix style issues from lint + if: (github.event.issue.pull_request) && (startsWith(github.event.comment.body, 'bot fix style') || contains(toJSON(github.event.comment.body), '\nbot fix style')) + runs-on: ubuntu-latest + steps: + - id: user_permission + uses: actions-cool/check-user-permission@v2 + with: + require: 'write' + + - name: Add reaction + if: steps.user_permission.outputs.require-result == 'true' + uses: peter-evans/create-or-update-comment@v4 + with: + comment-id: ${{ github.event.comment.id }} + reactions: rocket + + - name: cleanup + if: steps.user_permission.outputs.require-result == 'true' + run: | + find . -name . -o -prune -exec rm -rf -- {} + + + - uses: actions/checkout@v4 + if: steps.user_permission.outputs.require-result == 'true' + with: + token: ${{ secrets.BOT_FIX_STYLE_TOKEN }} + + - name: Checkout PR branch + if: steps.user_permission.outputs.require-result == 'true' + run: | + gh pr checkout ${{ github.event.issue.number }} + env: + GH_TOKEN: ${{ secrets.BOT_FIX_STYLE_TOKEN }} + + - name: install Python + if: steps.user_permission.outputs.require-result == 'true' + uses: actions/setup-python@v4 + with: + python-version: 3.8 + + - name: install elan + if: steps.user_permission.outputs.require-result == 'true' + 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}" + + # run the same linting steps as in lint_and_suggest_pr.yaml + + - name: lint + if: steps.user_permission.outputs.require-result == 'true' + run: | + lake exe lint-style --fix + + - name: Install bibtool + if: steps.user_permission.outputs.require-result == 'true' + run: | + sudo apt-get update + sudo apt-get install -y bibtool + + - name: lint references.bib + if: steps.user_permission.outputs.require-result == 'true' + run: | + # ignoring the return code allows the following `reviewdog` step to add GitHub suggestions + ./scripts/lint-bib.sh || true + + - name: update {Mathlib, Tactic, Counterexamples, Archive}.lean + if: steps.user_permission.outputs.require-result == 'true' + run: | + # ignoring the return code allows the following `reviewdog` step to add GitHub suggestions + lake exe mk_all || true + + - name: Commit and push changes + if: steps.user_permission.outputs.require-result == 'true' + run: | + # cleanup junk from build + rm elan-init + rm docs/references.bib.old + # setup commit and push + git config user.name "leanprover-community-mathlib4-bot" + git config user.email "leanprover-community-mathlib4-bot@users.noreply.github.com" + git add . + # Don't fail if there's nothing to commit + git commit -m "commit changes from style linters" || true + git push origin HEAD diff --git a/.github/workflows/bot_fix_style_review.yaml b/.github/workflows/bot_fix_style_review.yaml new file mode 100644 index 0000000000000..99fa4ae9a7dab --- /dev/null +++ b/.github/workflows/bot_fix_style_review.yaml @@ -0,0 +1,99 @@ +name: bot fix style (review) + +on: + pull_request_review: + # triggers on a review, whether or not it is accompanied by a comment + types: [submitted] + +jobs: + fix_style: + name: Fix style issues from lint + if: (startsWith(github.event.review.body, 'bot fix style') || contains(toJSON(github.event.review.body), '\nbot fix style')) + runs-on: ubuntu-latest + steps: + - id: user_permission + uses: actions-cool/check-user-permission@v2 + with: + require: 'write' + + # Maybe no API exists for this yet? + # - name: Add reaction + # if: steps.user_permission.outputs.require-result == 'true' + # run: | + # gh api --method POST \ + # -H "Accept: application/vnd.github+json" \ + # -H "X-GitHub-Api-Version: 2022-11-28" \ + # /repos/${{ github.repository_owner }}/${{ github.event.repository.name }}/pulls/${{ github.event.pull_request.number }}/reviews/${{ github.event.review.id }}/reactions \ + # -f "content=rocket" + # env: + # GH_TOKEN: ${{ secrets.BOT_FIX_STYLE_TOKEN }} + + - name: cleanup + if: steps.user_permission.outputs.require-result == 'true' + run: | + find . -name . -o -prune -exec rm -rf -- {} + + + - uses: actions/checkout@v4 + if: steps.user_permission.outputs.require-result == 'true' + with: + token: ${{ secrets.BOT_FIX_STYLE_TOKEN }} + + - name: Checkout PR branch + if: steps.user_permission.outputs.require-result == 'true' + run: | + gh pr checkout ${{ github.event.pull_request.number }} + env: + GH_TOKEN: ${{ secrets.BOT_FIX_STYLE_TOKEN }} + + - name: install Python + if: steps.user_permission.outputs.require-result == 'true' + uses: actions/setup-python@v4 + with: + python-version: 3.8 + + - name: install elan + if: steps.user_permission.outputs.require-result == 'true' + 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}" + + # run the same linting steps as in lint_and_suggest_pr.yaml + + - name: lint + if: steps.user_permission.outputs.require-result == 'true' + run: | + lake exe lint-style --fix + + - name: Install bibtool + if: steps.user_permission.outputs.require-result == 'true' + run: | + sudo apt-get update + sudo apt-get install -y bibtool + + - name: lint references.bib + if: steps.user_permission.outputs.require-result == 'true' + run: | + # ignoring the return code allows the following `reviewdog` step to add GitHub suggestions + ./scripts/lint-bib.sh || true + + - name: update {Mathlib, Tactic, Counterexamples, Archive}.lean + if: steps.user_permission.outputs.require-result == 'true' + run: | + # ignoring the return code allows the following `reviewdog` step to add GitHub suggestions + lake exe mk_all || true + + - name: Commit and push changes + if: steps.user_permission.outputs.require-result == 'true' + run: | + # cleanup junk from build + rm elan-init + rm docs/references.bib.old + # setup commit and push + git config user.name "leanprover-community-mathlib4-bot" + git config user.email "leanprover-community-mathlib4-bot@users.noreply.github.com" + git add . + # Don't fail if there's nothing to commit + git commit -m "commit changes from style linters" || true + git push origin HEAD diff --git a/.github/workflows/bot_fix_style_review_comment.yaml b/.github/workflows/bot_fix_style_review_comment.yaml new file mode 100644 index 0000000000000..097b24ba35954 --- /dev/null +++ b/.github/workflows/bot_fix_style_review_comment.yaml @@ -0,0 +1,97 @@ +name: bot fix style (review comment) + +on: + pull_request_review_comment: + types: [created, edited] + +jobs: + fix_style: + name: Fix style issues from lint + if: (startsWith(github.event.comment.body, 'bot fix style') || contains(toJSON(github.event.comment.body), '\nbot fix style')) + runs-on: ubuntu-latest + steps: + - id: user_permission + uses: actions-cool/check-user-permission@v2 + with: + require: 'write' + + - name: Add reaction + if: steps.user_permission.outputs.require-result == 'true' + run: | + gh api --method POST \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + /repos/${{ github.repository_owner }}/${{ github.event.repository.name }}/pulls/comments/${{ github.event.comment.id }}/reactions \ + -f "content=rocket" + env: + GH_TOKEN: ${{ secrets.BOT_FIX_STYLE_TOKEN }} + + - name: cleanup + if: steps.user_permission.outputs.require-result == 'true' + run: | + find . -name . -o -prune -exec rm -rf -- {} + + + - uses: actions/checkout@v4 + if: steps.user_permission.outputs.require-result == 'true' + with: + token: ${{ secrets.BOT_FIX_STYLE_TOKEN }} + + - name: Checkout PR branch + if: steps.user_permission.outputs.require-result == 'true' + run: | + gh pr checkout ${{ github.event.pull_request.number }} + env: + GH_TOKEN: ${{ secrets.BOT_FIX_STYLE_TOKEN }} + + - name: install Python + if: steps.user_permission.outputs.require-result == 'true' + uses: actions/setup-python@v4 + with: + python-version: 3.8 + + - name: install elan + if: steps.user_permission.outputs.require-result == 'true' + 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}" + + # run the same linting steps as in lint_and_suggest_pr.yaml + + - name: lint + if: steps.user_permission.outputs.require-result == 'true' + run: | + lake exe lint-style --fix + + - name: Install bibtool + if: steps.user_permission.outputs.require-result == 'true' + run: | + sudo apt-get update + sudo apt-get install -y bibtool + + - name: lint references.bib + if: steps.user_permission.outputs.require-result == 'true' + run: | + # ignoring the return code allows the following `reviewdog` step to add GitHub suggestions + ./scripts/lint-bib.sh || true + + - name: update {Mathlib, Tactic, Counterexamples, Archive}.lean + if: steps.user_permission.outputs.require-result == 'true' + run: | + # ignoring the return code allows the following `reviewdog` step to add GitHub suggestions + lake exe mk_all || true + + - name: Commit and push changes + if: steps.user_permission.outputs.require-result == 'true' + run: | + # cleanup junk from build + rm elan-init + rm docs/references.bib.old + # setup commit and push + git config user.name "leanprover-community-mathlib4-bot" + git config user.email "leanprover-community-mathlib4-bot@users.noreply.github.com" + git add . + # Don't fail if there's nothing to commit + git commit -m "commit changes from style linters" || true + git push origin HEAD diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bbeef2b24530e..51161130cfb33 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,7 +1,7 @@ # DO NOT EDIT THIS FILE!!! # This file is automatically generated by mk_build_yml.sh -# Edit build.yml.in instead and run mk_build_yml.sh to update. +# Edit .github/build.in.yml instead and run mk_build_yml.sh to update. # Forks of mathlib and other projects should be able to use build_fork.yml directly # The jobs in this file run on self-hosted workers and will not be run from external forks @@ -169,8 +169,10 @@ jobs: - name: get cache id: get run: | - lake exe cache clean - lake exe cache get + 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" - name: build mathlib id: build @@ -337,7 +339,7 @@ jobs: - if: contains(steps.PR.outputs.pr_labels, 'auto-merge-after-CI') name: If `auto-merge-after-CI` is present, add a `bors merge` comment. - uses: GrantBirki/comment@v2.0.1 + uses: GrantBirki/comment@v2 with: token: ${{ secrets.AUTO_MERGE_TOKEN }} issue-number: ${{ steps.PR.outputs.number }} diff --git a/.github/workflows/build_fork.yml b/.github/workflows/build_fork.yml index 0a2c6fe778dfc..f441af18b5045 100644 --- a/.github/workflows/build_fork.yml +++ b/.github/workflows/build_fork.yml @@ -1,7 +1,7 @@ # DO NOT EDIT THIS FILE!!! # This file is automatically generated by mk_build_yml.sh -# Edit build.yml.in instead and run mk_build_yml.sh to update. +# Edit .github/build.in.yml instead and run mk_build_yml.sh to update. # Forks of mathlib and other projects should be able to use build_fork.yml directly # The jobs in this file run on GitHub-hosted workers and will only be run from external forks @@ -166,8 +166,10 @@ jobs: - name: get cache id: get run: | - lake exe cache clean - lake exe cache get + 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" - name: build mathlib id: build @@ -334,7 +336,7 @@ jobs: - if: contains(steps.PR.outputs.pr_labels, 'auto-merge-after-CI') name: If `auto-merge-after-CI` is present, add a `bors merge` comment. - uses: GrantBirki/comment@v2.0.1 + uses: GrantBirki/comment@v2 with: token: ${{ secrets.AUTO_MERGE_TOKEN }} issue-number: ${{ steps.PR.outputs.number }} diff --git a/.github/workflows/dependent-issues.yml b/.github/workflows/dependent-issues.yml index 682c5311f52b0..a73285496116b 100644 --- a/.github/workflows/dependent-issues.yml +++ b/.github/workflows/dependent-issues.yml @@ -18,7 +18,7 @@ jobs: check: runs-on: ubuntu-latest steps: - - uses: z0al/dependent-issues@v1 + - uses: z0al/dependent-issues@75d554cd9494b6e1766bc9d08a81c26444ad5c5a env: # (Required) The token to use to make API calls to GitHub. GITHUB_TOKEN: ${{ secrets.DEPENDENT_ISSUES_TOKEN }} diff --git a/.github/workflows/labels_from_comment.yml b/.github/workflows/labels_from_comment.yml index 5b62e2ce226d6..b40b8d4c4daf6 100644 --- a/.github/workflows/labels_from_comment.yml +++ b/.github/workflows/labels_from_comment.yml @@ -10,7 +10,7 @@ on: jobs: update-label: - if: github.event.issue.pull_request != null && (contains(github.event.comment.body, 'awaiting-author') || contains(github.event.comment.body, 'WIP')) + if: github.event.issue.pull_request && (contains(github.event.comment.body, 'awaiting-author') || contains(github.event.comment.body, 'WIP')) runs-on: ubuntu-latest steps: @@ -20,7 +20,7 @@ jobs: github-token: ${{ secrets.GITHUB_TOKEN }} script: | const { owner, repo, number: issue_number } = context.issue; - const commentLines = context.payload.comment.body.split('\r\n'); + const commentLines = context.payload.comment.body.split(/\r?\n/); const awaitingAuthor = commentLines.includes('awaiting-author'); const wip = commentLines.includes('WIP'); diff --git a/.github/workflows/lean4checker.yml b/.github/workflows/lean4checker.yml index 3152d364350df..fdde8c185c5f9 100644 --- a/.github/workflows/lean4checker.yml +++ b/.github/workflows/lean4checker.yml @@ -69,7 +69,7 @@ jobs: run: | git clone https://github.com/leanprover/lean4checker cd lean4checker - git checkout v4.11.0-rc1 + git checkout v4.12.0-rc1 # 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/lint_and_suggest_pr.yml b/.github/workflows/lint_and_suggest_pr.yml index 52888f7128e32..409e78ebc223e 100644 --- a/.github/workflows/lint_and_suggest_pr.yml +++ b/.github/workflows/lint_and_suggest_pr.yml @@ -28,30 +28,31 @@ jobs: ./elan-init -y --default-toolchain none echo "$HOME/.elan/bin" >> "${GITHUB_PATH}" + # if you update this step (or its dependencies), please also update them in bot_fix_style_comment.yaml - name: lint - continue-on-error: true # allows the following `reviewdog` step to add GitHub suggestions run: | lake exe lint-style --fix - name: suggester / lint-style uses: reviewdog/action-suggester@v1 with: - tool_name: lint-style + tool_name: lint-style (comment with "bot fix style" to have the bot commit all style suggestions) - name: Install bibtool run: | sudo apt-get update sudo apt-get install -y bibtool + # if you update this step (or its dependencies), please also update them in bot_fix_style_comment.yaml - name: lint references.bib - continue-on-error: true # allows the following `reviewdog` step to add GitHub suggestions run: | - ./scripts/lint-bib.sh + # ignoring the return code allows the following `reviewdog` step to add GitHub suggestions + ./scripts/lint-bib.sh || true - name: suggester / lint-bib uses: reviewdog/action-suggester@v1 with: - tool_name: lint-bib + tool_name: lint-bib (comment with "bot fix style" to have the bot commit all style suggestions) check_imported: if: github.repository == 'leanprover-community/mathlib4' && github.event.pull_request.draft == false @@ -71,11 +72,13 @@ jobs: ./elan-init -y --default-toolchain none echo "$HOME/.elan/bin" >> "${GITHUB_PATH}" + # if you update this step (or its dependencies), please also update them in bot_fix_style_comment.yaml - name: update {Mathlib, Tactic, Counterexamples, Archive}.lean - continue-on-error: true # allows the following `reviewdog` step to add GitHub suggestions - run: lake exe mk_all + run: + # ignoring the return code allows the following `reviewdog` step to add GitHub suggestions + lake exe mk_all || true - name: suggester / import list uses: reviewdog/action-suggester@v1 with: - tool_name: imports + tool_name: imports (comment with "bot fix style" to have the bot commit all style suggestions) diff --git a/.github/workflows/maintainer_merge_comment.yml b/.github/workflows/maintainer_merge_comment.yml index 61d41d9ac1375..db769c6592ab6 100644 --- a/.github/workflows/maintainer_merge_comment.yml +++ b/.github/workflows/maintainer_merge_comment.yml @@ -7,7 +7,7 @@ on: jobs: ping_zulip: name: Ping maintainers on Zulip - if: (github.event.issue.pull_request != 'null') && (startsWith(github.event.comment.body, 'maintainer merge') || contains(toJSON(github.event.comment.body), '\nmaintainer merge')) + if: github.event.issue.pull_request && (startsWith(github.event.comment.body, 'maintainer merge') || contains(toJSON(github.event.comment.body), '\nmaintainer merge')) runs-on: ubuntu-latest steps: - name: Check whether user is part of mathlib-reviewers team @@ -20,6 +20,17 @@ jobs: # This feature is only applicable in an issue (or PR) context exit: true # optional. If the action should exit if the user is not part of the team. Defaults to true. + - uses: actions/checkout@v4 + with: + ref: master + - name: Determine Zulip topic + id: determine_topic + run: | + ./scripts/get_tlabel.sh "${PR}" >> "$GITHUB_OUTPUT" + env: + PR: /repos/leanprover-community/mathlib4/issues/${{ github.event.issue.number }} + GH_TOKEN: ${{secrets.GITHUB_TOKEN}} + - name: Send message on Zulip uses: zulip/github-actions-zulip/send-message@v1 with: @@ -28,14 +39,14 @@ jobs: organization-url: 'https://leanprover.zulipchat.com' to: 'mathlib reviewers' type: 'stream' - topic: 'maintainer merge' + topic: ${{ steps.determine_topic.outputs.topic }} content: | ${{ format('{0} requested a maintainer merge from comment on PR [#{1}]({2}):', github.event.comment.user.login, github.event.issue.number, github.event.issue.html_url ) }} > ${{ github.event.issue.title }} - name: Add comment to PR - uses: GrantBirki/comment@v2.0.1 + uses: GrantBirki/comment@v2 with: issue-number: ${{ github.event.issue.number }} body: | diff --git a/.github/workflows/maintainer_merge_review.yml b/.github/workflows/maintainer_merge_review.yml index aaefc4ecbdcb2..c7d8357bbfa64 100644 --- a/.github/workflows/maintainer_merge_review.yml +++ b/.github/workflows/maintainer_merge_review.yml @@ -19,6 +19,17 @@ jobs: token: ${{ secrets.MATHLIB_REVIEWERS_TEAM_KEY }} # required. Personal Access Token with the `read:org` permission exit: true # optional. If the action should exit if the user is not part of the team. Defaults to true. + - uses: actions/checkout@v4 + with: + ref: master + - name: Determine Zulip topic + id: determine_topic + run: | + ./scripts/get_tlabel.sh "${PR}" >> "$GITHUB_OUTPUT" + env: + PR: /repos/leanprover-community/mathlib4/issues/${{ github.event.pull_request.number }} + GH_TOKEN: ${{secrets.GITHUB_TOKEN}} + - name: Send message on Zulip uses: zulip/github-actions-zulip/send-message@v1 with: @@ -27,14 +38,14 @@ jobs: organization-url: 'https://leanprover.zulipchat.com' to: 'mathlib reviewers' type: 'stream' - topic: 'maintainer merge' + topic: ${{ steps.determine_topic.outputs.topic }} content: | ${{ format('{0} requested a maintainer merge from review on PR [#{1}]({2}):', github.event.review.user.login, github.event.pull_request.number, github.event.pull_request.html_url ) }} > ${{ github.event.pull_request.title }} - name: Add comment to PR - uses: GrantBirki/comment@v2.0.1 + uses: GrantBirki/comment@v2 with: issue-number: ${{ github.event.pull_request.number }} body: | diff --git a/.github/workflows/maintainer_merge_review_comment.yml b/.github/workflows/maintainer_merge_review_comment.yml index 48ccc466ac1ea..79a5ea176d9d9 100644 --- a/.github/workflows/maintainer_merge_review_comment.yml +++ b/.github/workflows/maintainer_merge_review_comment.yml @@ -18,6 +18,17 @@ jobs: token: ${{ secrets.MATHLIB_REVIEWERS_TEAM_KEY }} # required. Personal Access Token with the `read:org` permission exit: true # optional. If the action should exit if the user is not part of the team. Defaults to true. + - uses: actions/checkout@v4 + with: + ref: master + - name: Determine Zulip topic + id: determine_topic + run: | + ./scripts/get_tlabel.sh "${PR}" >> "$GITHUB_OUTPUT" + env: + PR: /repos/leanprover-community/mathlib4/issues/${{ github.event.pull_request.number }} + GH_TOKEN: ${{secrets.GITHUB_TOKEN}} + - name: Send message on Zulip uses: zulip/github-actions-zulip/send-message@v1 with: @@ -26,14 +37,14 @@ jobs: organization-url: 'https://leanprover.zulipchat.com' to: 'mathlib reviewers' type: 'stream' - topic: 'maintainer merge' + topic: ${{ steps.determine_topic.outputs.topic }} content: | ${{ format('{0} requested a maintainer merge from review comment on PR [#{1}]({2}):', github.event.comment.user.login, github.event.pull_request.number, github.event.pull_request.html_url ) }} > ${{ github.event.pull_request.title }} - name: Add comment to PR - uses: GrantBirki/comment@v2.0.1 + uses: GrantBirki/comment@v2 with: issue-number: ${{ github.event.pull_request.number }} body: | diff --git a/.github/workflows/mk_build_yml.sh b/.github/workflows/mk_build_yml.sh index 96cf301b33a26..c47d00142438a 100755 --- a/.github/workflows/mk_build_yml.sh +++ b/.github/workflows/mk_build_yml.sh @@ -7,7 +7,7 @@ header() { # DO NOT EDIT THIS FILE!!! # This file is automatically generated by mk_build_yml.sh -# Edit build.yml.in instead and run mk_build_yml.sh to update. +# Edit .github/build.in.yml instead and run mk_build_yml.sh to update. # Forks of mathlib and other projects should be able to use build_fork.yml directly EOF @@ -76,7 +76,8 @@ include() { s/MAIN_OR_FORK/$3/g; s/JOB_NAME/$4/g; s/STYLE_LINT_RUNNER/$5/g; - " build.yml.in + /^#.*autogenerating/d + " ../build.in.yml } build_yml > build.yml diff --git a/.github/workflows/nolints.yml b/.github/workflows/nolints.yml index ed9b666b0d7eb..76f3590e4f585 100644 --- a/.github/workflows/nolints.yml +++ b/.github/workflows/nolints.yml @@ -25,6 +25,9 @@ jobs: echo "$HOME/.elan/bin" >> "${GITHUB_PATH}" - uses: actions/checkout@v4 + with: + ## fetch the whole repository, as we want to push to it later + fetch-depth: 0 - name: print lean and lake versions run: | @@ -53,15 +56,14 @@ jobs: run: | bash -o pipefail -c "env LEAN_ABORT_ON_PANIC=1 lake build --wfail -KCI" - - name: update nolints.json and style-exceptions.txt + - name: update nolints.json shell: bash run: | env LEAN_ABORT_ON_PANIC=1 lake exe runLinter --update Mathlib - lake exe lint-style --update - name: configure git setup run: | - git remote add origin-bot "https://leanprover-community-bot:${{ secrets.UPDATE_NOLINTS_TOKEN }}@github.com/leanprover-community/mathlib.git" + git remote add origin-bot "https://leanprover-community-bot:${{ secrets.UPDATE_NOLINTS_TOKEN }}@github.com/leanprover-community/mathlib4.git" git config user.email "leanprover.community@gmail.com" git config user.name "leanprover-community-bot" @@ -70,7 +72,7 @@ jobs: # github using a different username. git config --unset http.https://github.com/.extraheader - - name: file a new PR to update nolints.json and style-exceptions.txt + - name: file a new PR to update nolints.json run: ./scripts/update_nolints_CI.sh env: DEPLOY_GITHUB_TOKEN: ${{ secrets.UPDATE_NOLINTS_TOKEN }} diff --git a/.github/workflows/update_dependencies.yml b/.github/workflows/update_dependencies.yml index 885bef03a2be2..02779cf664eca 100644 --- a/.github/workflows/update_dependencies.yml +++ b/.github/workflows/update_dependencies.yml @@ -19,25 +19,46 @@ jobs: uses: actions/checkout@v4 with: fetch-depth: 0 - token: "${{ secrets.NIGHTLY_TESTING }}" + token: "${{ secrets.UPDATE_DEPENDENCIES_TOKEN }}" + + - name: Get sha of branch + id: sha + run: | + echo "sha=$(git rev-parse --verify origin/update-dependencies-bot-use-only)" >> "$GITHUB_OUTPUT" + + - name: Get PR and labels + if: ${{ steps.sha.outputs.sha }} + id: PR # all the steps below are skipped if 'ready-to-merge' is in the list of labels found here + uses: 8BitJonny/gh-get-current-pr@3.0.0 + # TODO: this may not work properly if the same commit is pushed to multiple branches: + # https://github.com/8BitJonny/gh-get-current-pr/issues/8 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + sha: ${{ steps.sha.outputs.sha }} + # Only return if PR is still open + filterOutClosed: true - name: Configure Git User + if: ${{ !contains(steps.PR.outputs.pr_labels, 'ready-to-merge') }} run: | git config user.name "leanprover-community-mathlib4-bot" git config user.email "leanprover-community-mathlib4-bot@users.noreply.github.com" - name: Update dependencies + if: ${{ !contains(steps.PR.outputs.pr_labels, 'ready-to-merge') }} run: lake update - name: Generate PR title + if: ${{ !contains(steps.PR.outputs.pr_labels, 'ready-to-merge') }} run: | echo "timestamp=$(date -u +"%Y-%m-%d-%H-%M")" >> "$GITHUB_ENV" echo "pr_title=chore: update Mathlib dependencies $(date -u +"%Y-%m-%d")" >> "$GITHUB_ENV" - name: Create Pull Request + if: ${{ !contains(steps.PR.outputs.pr_labels, 'ready-to-merge') }} uses: peter-evans/create-pull-request@v6 with: - token: "${{ secrets.NIGHTLY_TESTING }}" + token: "${{ secrets.UPDATE_DEPENDENCIES_TOKEN }}" commit-message: "chore: update Mathlib dependencies ${{ env.timestamp }}" # this branch is referenced in update_dependencies_zulip.yml branch: "update-dependencies-bot-use-only" diff --git a/.github/workflows/update_dependencies_zulip.yml b/.github/workflows/update_dependencies_zulip.yml index 466b06668f31f..1f8a3b507374b 100644 --- a/.github/workflows/update_dependencies_zulip.yml +++ b/.github/workflows/update_dependencies_zulip.yml @@ -1,7 +1,5 @@ name: Monitor Dependency Update Failures -# This action currently uses the NIGHTLY_TESTING secret, but could be moved to a separate secret. - on: workflow_run: workflows: ["continuous integration"] @@ -20,7 +18,7 @@ jobs: uses: actions/github-script@v7 id: construct_message with: - github-token: ${{ secrets.NIGHTLY_TESTING }} + github-token: ${{ secrets.UPDATE_DEPENDENCIES_TOKEN }} result-encoding: string script: | const owner = context.repo.owner, repo = context.repo.repo; diff --git a/Archive.lean b/Archive.lean index df1f30db3e121..2804883c9b27e 100644 --- a/Archive.lean +++ b/Archive.lean @@ -9,6 +9,7 @@ import Archive.Imo.Imo1959Q1 import Archive.Imo.Imo1959Q2 import Archive.Imo.Imo1960Q1 import Archive.Imo.Imo1960Q2 +import Archive.Imo.Imo1961Q3 import Archive.Imo.Imo1962Q1 import Archive.Imo.Imo1962Q4 import Archive.Imo.Imo1964Q1 diff --git a/Archive/Arithcc.lean b/Archive/Arithcc.lean index 45f394d134fee..34d7291daf17c 100644 --- a/Archive/Arithcc.lean +++ b/Archive/Arithcc.lean @@ -3,7 +3,6 @@ Copyright (c) 2020 Xi Wang. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Xi Wang -/ -import Mathlib.Init.Data.Nat.Lemmas import Mathlib.Data.Nat.Defs import Mathlib.Order.Basic import Mathlib.Tactic.Common @@ -145,9 +144,9 @@ def outcome : List Instruction → State → State @[simp] theorem outcome_append (p₁ p₂ : List Instruction) (η : State) : outcome (p₁ ++ p₂) η = outcome p₂ (outcome p₁ η) := by - revert η - induction' p₁ with _ _ p₁_ih <;> intros <;> simp - apply p₁_ih + induction p₁ generalizing η with + | nil => simp + | cons _ _ p₁_ih => simp [p₁_ih] end Target diff --git a/Archive/Examples/IfNormalization/Result.lean b/Archive/Examples/IfNormalization/Result.lean index 38de9bc64bc79..ef69269689c77 100644 --- a/Archive/Examples/IfNormalization/Result.lean +++ b/Archive/Examples/IfNormalization/Result.lean @@ -15,8 +15,6 @@ import Mathlib.Tactic.Recall See `Statement.lean` for background. -/ -set_option autoImplicit true - macro "◾" : tactic => `(tactic| aesop) macro "◾" : term => `(term| by aesop) @@ -30,17 +28,19 @@ attribute [local simp] normalized hasNestedIf hasConstantIf hasRedundantIf disjo attribute [local simp] apply_ite ite_eq_iff' +variable {b : Bool} {f : ℕ → Bool} {i : ℕ} {t e : IfExpr} + /-! Simp lemmas for `eval`. We don't want a `simp` lemma for `(ite i t e).eval` in general, only once we know the shape of `i`. -/ -@[simp] theorem eval_lit : (lit b).eval f = b := rfl -@[simp] theorem eval_var : (var i).eval f = f i := rfl +@[simp] theorem eval_lit : (lit b).eval f = b := rfl +@[simp] theorem eval_var : (var i).eval f = f i := rfl @[simp] theorem eval_ite_lit : (ite (.lit b) t e).eval f = bif b then t.eval f else e.eval f := rfl @[simp] theorem eval_ite_var : (ite (.var i) t e).eval f = bif f i then t.eval f else e.eval f := rfl -@[simp] theorem eval_ite_ite : +@[simp] theorem eval_ite_ite {a b c d e : IfExpr} : (ite (ite a b c) d e).eval f = (ite a (ite b d e) (ite c d e)).eval f := by cases h : eval f a <;> simp_all [eval] diff --git a/Archive/Examples/IfNormalization/WithoutAesop.lean b/Archive/Examples/IfNormalization/WithoutAesop.lean index 88aa07ae46917..13d0eb001998c 100644 --- a/Archive/Examples/IfNormalization/WithoutAesop.lean +++ b/Archive/Examples/IfNormalization/WithoutAesop.lean @@ -17,14 +17,12 @@ In this variant we eschew the use of `aesop`, and instead write out the proofs. we put primes on the declarations in the file.) -/ -set_option autoImplicit true - namespace IfExpr attribute [local simp] eval normalized hasNestedIf hasConstantIf hasRedundantIf disjoint vars List.disjoint max_add_add_right max_mul_mul_left Nat.lt_add_one_iff le_add_of_le_right -theorem eval_ite_ite' : +theorem eval_ite_ite' {a b c d e : IfExpr} {f : ℕ → Bool} : (ite (ite a b c) d e).eval f = (ite a (ite b d e) (ite c d e)).eval f := by cases h : eval f a <;> simp_all @@ -95,14 +93,12 @@ def normalize' (l : AList (fun _ : ℕ => Bool)) : · 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, imp_false] + AList.lookup_insert_eq_none, ne_eq, AList.lookup_insert] obtain ⟨⟨⟨tn, tc⟩, tr⟩, td⟩ := ht₂ split <;> rename_i h' · subst h' simp_all - · simp_all? says simp_all only [hasNestedIf, Bool.or_self, hasConstantIf, and_self, - hasRedundantIf, Bool.or_false, beq_eq_false_iff_ne, ne_eq, not_false_eq_true, - disjoint, List.disjoint, decide_True, Bool.and_self] + · simp_all · have := ht₃ w have := he₃ w by_cases h : w = v diff --git a/Archive/Imo/Imo1959Q2.lean b/Archive/Imo/Imo1959Q2.lean index 2af72963993eb..0325f5e80b580 100644 --- a/Archive/Imo/Imo1959Q2.lean +++ b/Archive/Imo/Imo1959Q2.lean @@ -93,7 +93,7 @@ theorem isGood_iff_of_sqrt_two_lt (hA : sqrt 2 < A) : IsGood x A ↔ x = (A / 2) constructor · intro h have hx : 1 < x := by rwa [h.sqrt_two_lt_iff_one_lt] at hA - rw [isGood_iff_eq_sqrt hx, eq_comm, sqrt_eq_iff_sq_eq] at h <;> linarith + rw [isGood_iff_eq_sqrt hx, eq_comm, sqrt_eq_iff_eq_sq] at h <;> linarith · rintro rfl rw [isGood_iff_eq_sqrt] · conv_lhs => rw [← sqrt_sq this.le] diff --git a/Archive/Imo/Imo1960Q2.lean b/Archive/Imo/Imo1960Q2.lean index 577c0adeee430..60faf4c5c5d66 100644 --- a/Archive/Imo/Imo1960Q2.lean +++ b/Archive/Imo/Imo1960Q2.lean @@ -51,7 +51,7 @@ theorem isGood_iff {x} : IsGood x ↔ x ∈ Ico (-1/2) (45/8) \ {0} := by -- Now, if `x ≥ -1/2`, `x ≠ 0`, then the expression is well-defined. have hx2' : 0 ≤ 2 * x + 1 := by linarith have H : 1 - sqrt (2 * x + 1) ≠ 0 := by - rw [sub_ne_zero, ne_comm, ne_eq, sqrt_eq_iff_sq_eq hx2' zero_le_one] + rw [sub_ne_zero, ne_comm, ne_eq, sqrt_eq_iff_eq_sq hx2' zero_le_one] simpa calc -- Note that the fraction in the LHS is equal to `(1 + sqrt (2 * x + 1)) ^ 2` diff --git a/Archive/Imo/Imo1961Q3.lean b/Archive/Imo/Imo1961Q3.lean new file mode 100644 index 0000000000000..0651cf539ec5f --- /dev/null +++ b/Archive/Imo/Imo1961Q3.lean @@ -0,0 +1,74 @@ +/- +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.Analysis.SpecialFunctions.Trigonometric.Complex + +/-! +# IMO 1961 Q3 + +Solve the equation + +$\cos^n x - \sin^n x = 1$, + +where $n$ is a given positive integer. + +The solution is based on the one at the +[Art of Problem Solving](https://artofproblemsolving.com/wiki/index.php/1961_IMO_Problems/Problem_3) +website. +-/ + +open Real + +theorem Imo1961Q3 {n : ℕ} {x : ℝ} (h₀ : n ≠ 0) : + (cos x) ^ n - (sin x) ^ n = 1 ↔ + (∃ k : ℤ, k * π = x) ∧ Even n ∨ (∃ k : ℤ, k * (2 * π) = x) ∧ Odd n ∨ + (∃ k : ℤ, -(π / 2) + k * (2 * π) = x) ∧ Odd n := by + constructor + · intro h + rcases eq_or_ne (sin x) 0 with hsinx | hsinx + · rw [hsinx, zero_pow h₀, sub_zero, pow_eq_one_iff_of_ne_zero h₀, cos_eq_one_iff, + cos_eq_neg_one_iff] at h + rcases h with ⟨k, rfl⟩ | ⟨⟨k, rfl⟩, hn⟩ + · cases n.even_or_odd with + | inl hn => refine .inl ⟨⟨k * 2, ?_⟩, hn⟩; simp [mul_assoc] + | inr hn => exact .inr <| .inl ⟨⟨_, rfl⟩, hn⟩ + · exact .inl ⟨⟨2 * k + 1, by push_cast; ring⟩, hn⟩ + · rcases eq_or_ne (cos x) 0 with hcosx | hcosx + · right; right + rw [hcosx, zero_pow h₀, zero_sub, ← neg_inj, neg_neg, pow_eq_neg_one_iff, + sin_eq_neg_one_iff] at h + simpa only [eq_comm] using h + · have hcos1 : |cos x| < 1 := by + rw [abs_cos_eq_sqrt_one_sub_sin_sq, sqrt_lt' one_pos] + simp [sq_pos_of_ne_zero hsinx] + have hsin1 : |sin x| < 1 := by + rw [abs_sin_eq_sqrt_one_sub_cos_sq, sqrt_lt' one_pos] + simp [sq_pos_of_ne_zero hcosx] + match n with + | 1 => + rw [pow_one, pow_one, sub_eq_iff_eq_add] at h + have : 2 * sin x * cos x = 0 := by + simpa [h, add_sq, add_assoc, ← two_mul, mul_add, mul_assoc, ← sq] + using cos_sq_add_sin_sq x + simp [hsinx, hcosx] at this + | 2 => + rw [← cos_sq_add_sin_sq x, sub_eq_add_neg, add_right_inj, neg_eq_self ℝ] at h + exact absurd (pow_eq_zero h) hsinx + | (n + 1 + 2) => + set m := n + 1 + refine absurd ?_ h.not_lt + calc + (cos x) ^ (m + 2) - (sin x) ^ (m + 2) ≤ |cos x| ^ (m + 2) + |sin x| ^ (m + 2) := by + simp only [← abs_pow, sub_eq_add_neg] + gcongr + exacts [le_abs_self _, neg_le_abs _] + _ = |cos x| ^ m * cos x ^ 2 + |sin x| ^ m * sin x ^ 2 := by simp [pow_add] + _ < 1 ^ m * cos x ^ 2 + 1 ^ m * sin x ^ 2 := by gcongr + _ = 1 := by simp + · rintro (⟨⟨k, rfl⟩, hn⟩ | ⟨⟨k, rfl⟩, -⟩ | ⟨⟨k, rfl⟩, hn⟩) + · rw [sin_int_mul_pi, zero_pow h₀, sub_zero, ← hn.pow_abs, abs_cos_int_mul_pi, one_pow] + · have : sin (k * (2 * π)) = 0 := by simpa [mul_assoc] using sin_int_mul_pi (k * 2) + simp [h₀, this] + · simp [hn.neg_pow, h₀] diff --git a/Archive/Imo/Imo1972Q5.lean b/Archive/Imo/Imo1972Q5.lean index 288c9e77dabdf..f96965f9d6a75 100644 --- a/Archive/Imo/Imo1972Q5.lean +++ b/Archive/Imo/Imo1972Q5.lean @@ -58,7 +58,7 @@ theorem imo1972_q5 (f g : ℝ → ℝ) (hf1 : ∀ x, ∀ y, f (x + y) + f (x - y have h₁ : ∃ x : ℝ, x ∈ S := by use ‖f 0‖; exact Set.mem_range_self 0 have h₂ : ∀ x, ‖f x‖ ≤ k' := by intro x - rw [le_div_iff] + rw [le_div_iff₀] · apply (mul_le_mul_left zero_lt_two).mp (hk₂ x) · exact zero_lt_one.trans hneg apply csSup_le h₁ @@ -92,7 +92,7 @@ theorem imo1972_q5' (f g : ℝ → ℝ) (hf1 : ∀ x, ∀ y, f (x + y) + f (x - suffices ∀ x, ‖f x‖ ≤ k / ‖g y‖ from ciSup_le this intro x suffices 2 * (‖f x‖ * ‖g y‖) ≤ 2 * k by - rwa [le_div_iff hgy, ← mul_le_mul_left (zero_lt_two : (0 : ℝ) < 2)] + rwa [le_div_iff₀ hgy, ← mul_le_mul_left (zero_lt_two : (0 : ℝ) < 2)] calc 2 * (‖f x‖ * ‖g y‖) = ‖2 * f x * g y‖ := by simp [abs_mul, mul_assoc] _ = ‖f (x + y) + f (x - y)‖ := by rw [hf1] diff --git a/Archive/Imo/Imo1986Q5.lean b/Archive/Imo/Imo1986Q5.lean index 9c265680eb14f..6789efcbb837d 100644 --- a/Archive/Imo/Imo1986Q5.lean +++ b/Archive/Imo/Imo1986Q5.lean @@ -26,7 +26,7 @@ Formalization is based on with minor modifications. -/ -open Set NNReal Classical +open NNReal namespace Imo1986Q5 @@ -51,12 +51,12 @@ theorem map_eq_zero : f x = 0 ↔ 2 ≤ x := by theorem map_ne_zero_iff : f x ≠ 0 ↔ x < 2 := by simp [hf.map_eq_zero] theorem map_of_lt_two (hx : x < 2) : f x = 2 / (2 - x) := by - have hx' : 2 - x ≠ 0 := (tsub_pos_of_lt hx).ne' + 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 [NNReal.le_div_iff hx', ← NNReal.le_div_iff' hfx, tsub_le_iff_right, ← hf.map_eq_zero, + · rw [le_div_iff₀ hx', ← NNReal.le_div_iff' hfx, tsub_le_iff_right, ← hf.map_eq_zero, hf.map_add, div_mul_cancel₀ _ hfx, hf.map_two, zero_mul] - · rw [NNReal.div_le_iff' hx', ← hf.map_eq_zero] + · rw [div_le_iff₀' hx', ← hf.map_eq_zero] refine (mul_eq_zero.1 ?_).resolve_right hfx rw [hf.map_add_rev, hf.map_eq_zero, tsub_add_cancel_of_le hx.le] diff --git a/Archive/Imo/Imo1987Q1.lean b/Archive/Imo/Imo1987Q1.lean index 717900655234a..36d3caf4a519e 100644 --- a/Archive/Imo/Imo1987Q1.lean +++ b/Archive/Imo/Imo1987Q1.lean @@ -46,8 +46,15 @@ def fixedPointsEquiv : { σx : α × Perm α // σx.2 σx.1 = σx.1 } ≃ Σ x : theorem card_fixed_points : card { σx : α × Perm α // σx.2 σx.1 = σx.1 } = card α * (card α - 1)! := by - simp [card_congr (fixedPointsEquiv α), card_perm, Finset.filter_not, Finset.card_sdiff, - Finset.filter_eq', Finset.card_univ] + simp only [card_congr (fixedPointsEquiv α), card_sigma, card_perm] + conv_lhs => + congr + next => skip + intro + rw [card_ofFinset (s := Finset.filter (· ∈ _) Finset.univ)] + simp only [Set.mem_compl_iff, Set.mem_singleton_iff, Finset.filter_not, Finset.filter_eq', + Finset.mem_univ, ↓reduceIte, Finset.subset_univ, Finset.card_sdiff, Finset.card_univ, + Finset.card_singleton, sum_const, smul_eq_mul] /-- Given `α : Type*` and `k : ℕ`, `fiber α k` is the set of permutations of `α` with exactly `k` fixed points. -/ diff --git a/Archive/Imo/Imo1988Q6.lean b/Archive/Imo/Imo1988Q6.lean index 290391027845f..b2790eea1cb9d 100644 --- a/Archive/Imo/Imo1988Q6.lean +++ b/Archive/Imo/Imo1988Q6.lean @@ -45,7 +45,7 @@ under the following conditions: with `x < y` then there exists a “smaller” point on `H`: a point `(x',y')` with `x' < y' ≤ x`. For reasons of usability, the hyperbola `H` is implemented as an arbitrary predicate. -(In question 6 of IMO1988, where this proof technique was first developped, +(In question 6 of IMO1988, where this proof technique was first developed, the predicate `claim` would be `∃ (d : ℕ), d ^ 2 = k` for some natural number `k`, and the predicate `H` would be `fun a b ↦ a * a + b * b = (a * b + 1) * k`.) diff --git a/Archive/Imo/Imo2006Q3.lean b/Archive/Imo/Imo2006Q3.lean index b774659da30e3..94b15273531b6 100644 --- a/Archive/Imo/Imo2006Q3.lean +++ b/Archive/Imo/Imo2006Q3.lean @@ -42,7 +42,7 @@ theorem lhs_ineq {x y : ℝ} (hxy : 0 ≤ x * y) : theorem four_pow_four_pos : (0 : ℝ) < 4 ^ 4 := by norm_num theorem mid_ineq {s t : ℝ} : s * t ^ 3 ≤ (3 * t + s) ^ 4 / 4 ^ 4 := by - rw [le_div_iff four_pow_four_pos] + rw [le_div_iff₀ four_pow_four_pos] have : 0 ≤ (s - t) ^ 2 * ((s + 7 * t) ^ 2 + 2 * (4 * t) ^ 2) := by positivity linarith @@ -78,7 +78,7 @@ theorem subst_wlog {x y z s : ℝ} (hxy : 0 ≤ x * y) (hxyz : x + y + z = 0) : theorem subst_proof₁ (x y z s : ℝ) (hxyz : x + y + z = 0) : |x * y * z * s| ≤ sqrt 2 / 32 * (x ^ 2 + y ^ 2 + z ^ 2 + s ^ 2) ^ 2 := by wlog h' : 0 ≤ x * y generalizing x y z; swap - · rw [div_mul_eq_mul_div, le_div_iff' zero_lt_32] + · rw [div_mul_eq_mul_div, le_div_iff₀' zero_lt_32] exact subst_wlog h' hxyz cases' (mul_nonneg_of_three x y z).resolve_left h' with h h · convert this y z x _ h using 2 <;> linarith @@ -103,7 +103,7 @@ theorem proof₂ (M : ℝ) let c := 2 + 3 * α calc _ = 18 ^ 2 * 2 * α / 48 ^ 2 := by ring _ ≤ M := ?_ - rw [div_le_iff (by positivity)] + rw [div_le_iff₀ (by positivity)] calc 18 ^ 2 * 2 * α = 18 ^ 2 * α ^ 2 * α := by linear_combination -324 * α * hα _ = abs (-(18 ^ 2 * α ^ 2 * α)) := by rw [abs_neg, abs_of_nonneg]; positivity diff --git a/Archive/Imo/Imo2024Q1.lean b/Archive/Imo/Imo2024Q1.lean index cf6f08b6fa937..0e94469d1e0d9 100644 --- a/Archive/Imo/Imo2024Q1.lean +++ b/Archive/Imo/Imo2024Q1.lean @@ -8,6 +8,7 @@ import Mathlib.Algebra.BigOperators.Ring import Mathlib.Algebra.Order.ToIntervalMod import Mathlib.Data.Real.Archimedean import Mathlib.Tactic.Peel +import Mathlib.Tactic.Recall /-! # IMO 2024 Q1 @@ -19,9 +20,9 @@ Determine all real numbers $\alpha$ such that, for every positive integer $n$, t is a multiple of~$n$. We follow Solution 3 from the -[official solutions](https://www.imo2024.uk/s/IMO-2024-Paper-1-Solutions.pdf). First reducing -modulo 2, any answer that is not a multiple of 2 is inductively shown to be contained in a -decreasing sequence of intervals, with empty intersection. +[official solutions](https://www.imo2024.uk/s/IMO-2024-Paper-1-Solutions.pdf). +First reducing modulo 2, any answer that is not a multiple of 2 is inductively shown to be +contained in a decreasing sequence of intervals, with empty intersection. -/ @@ -30,6 +31,9 @@ namespace Imo2024Q1 /-- The condition of the problem. -/ def Condition (α : ℝ) : Prop := (∀ n : ℕ, 0 < n → (n : ℤ) ∣ ∑ i ∈ Finset.Icc 1 n, ⌊i * α⌋) +/-- This is to be determined by the solver of the original problem. -/ +def solutionSet : Set ℝ := {α : ℝ | ∃ m : ℤ, α = 2 * m} + lemma condition_two_mul_int (m : ℤ) : Condition (2 * m) := by rintro n - suffices (n : ℤ) ∣ ∑ i ∈ Finset.Icc 0 n, ⌊((i * (2 * m) : ℤ) : ℝ)⌋ by @@ -37,14 +41,13 @@ lemma condition_two_mul_int (m : ℤ) : Condition (2 * m) := by exact_mod_cast this simp_rw [Int.floor_intCast, ← Finset.sum_mul, ← Nat.Ico_succ_right, ← Finset.range_eq_Ico, ← mul_assoc] - refine dvd_mul_of_dvd_left ?_ _ + apply dvd_mul_of_dvd_left rw [← Nat.cast_sum, ← Nat.cast_ofNat (n := 2), ← Nat.cast_mul, Finset.sum_range_id_mul_two] simp lemma condition_sub_two_mul_int_iff {α : ℝ} (m : ℤ) : Condition (α - 2 * m) ↔ Condition α := by - unfold Condition peel with n hn - refine dvd_iff_dvd_of_dvd_sub ?_ + apply dvd_iff_dvd_of_dvd_sub simp_rw [← Finset.sum_sub_distrib, mul_sub] norm_cast simp_rw [Int.floor_sub_int, sub_sub_cancel_left] @@ -69,31 +72,31 @@ lemma mem_Ico_one_of_mem_Ioo (h : α ∈ Set.Ioo 0 2) : α ∈ Set.Ico 1 2 := by have hr : 1 < ⌈α⁻¹⌉₊ := by rw [Nat.lt_ceil] exact_mod_cast one_lt_inv h0 hn - replace hc := hc ⌈α⁻¹⌉₊ (zero_lt_one.trans hr) - refine hr.ne' ?_ + apply hr.ne' suffices ⌈α⁻¹⌉₊ = (1 : ℤ) from mod_cast this - refine Int.eq_one_of_dvd_one (Int.zero_le_ofNat _) ?_ - convert hc + apply Int.eq_one_of_dvd_one (Int.zero_le_ofNat _) + convert hc ⌈α⁻¹⌉₊ (zero_lt_one.trans hr) rw [← Finset.add_sum_Ico_eq_sum_Icc hr.le] convert (add_zero _).symm · rw [Int.floor_eq_iff] - refine ⟨?_, ?_⟩ + constructor · rw [Int.cast_one] calc 1 ≤ α⁻¹ * α := by simp [h0.ne'] - _ ≤ ⌈α⁻¹⌉₊ * α := by gcongr; exact Nat.le_ceil _ - · calc ⌈α⁻¹⌉₊ * α < (α⁻¹ + 1) * α := by gcongr; exact Nat.ceil_lt_add_one (inv_nonneg.2 h0.le) + _ ≤ ⌈α⁻¹⌉₊ * α := by gcongr; exact Nat.le_ceil α⁻¹ + · calc ⌈α⁻¹⌉₊ * α + _ < (α⁻¹ + 1) * α := by gcongr; exact Nat.ceil_lt_add_one (inv_nonneg.2 h0.le) _ = 1 + α := by field_simp [h0.ne'] _ ≤ (1 : ℕ) + 1 := by gcongr; norm_cast - · refine Finset.sum_eq_zero ?_ + · apply Finset.sum_eq_zero intro x hx rw [Int.floor_eq_zero_iff] refine ⟨by positivity, ?_⟩ rw [Finset.mem_Ico, Nat.lt_ceil] at hx calc x * α < α⁻¹ * α := by gcongr; exact hx.2 - _ ≤ 1 := by simp [h0.ne'] + _ = 1 := by simp [h0.ne'] -lemma mem_Ico_n_of_mem_Ioo (h : α ∈ Set.Ioo 0 2) - {n : ℕ} (hn : 0 < n) : α ∈ Set.Ico ((2 * n - 1) / n : ℝ) 2 := by +lemma mem_Ico_n_of_mem_Ioo (h : α ∈ Set.Ioo 0 2) {n : ℕ} (hn : 0 < n) : + α ∈ Set.Ico ((2 * n - 1) / n : ℝ) 2 := by suffices ∑ i ∈ Finset.Icc 1 n, ⌊i * α⌋ = n ^ 2 ∧ α ∈ Set.Ico ((2 * n - 1) / n : ℝ) 2 from this.2 induction' n, hn using Nat.le_induction with k kpos hk · obtain ⟨h1, h2⟩ := hc.mem_Ico_one_of_mem_Ioo h @@ -107,37 +110,33 @@ lemma mem_Ico_n_of_mem_Ioo (h : α ∈ Set.Ioo 0 2) rw [Finset.mem_Icc] omega rw [← Nat.Icc_insert_succ_right (Nat.le_add_left 1 k), Finset.sum_insert hn11, hks] - replace hc := hc (k + 1) k.succ_pos + specialize hc (k + 1) k.succ_pos rw [hs] at hc ⊢ have hkl' : 2 * k ≤ ⌊(k + 1 : ℕ) * α⌋ := by rw [Int.le_floor] calc ((2 * k : ℤ) : ℝ) = ((2 * k : ℤ) : ℝ) + 0 := (add_zero _).symm _ ≤ ((2 * k : ℤ) : ℝ) + (k - 1) / k := by gcongr; norm_cast; positivity - _ = (k + 1 : ℕ) * ((2 * (k : ℕ) - 1) / ((k : ℕ) : ℝ) : ℝ) := by - field_simp - ring + _ = (k + 1 : ℕ) * ((2 * (k : ℕ) - 1) / ((k : ℕ) : ℝ)) := by field_simp; ring _ ≤ (k + 1 : ℕ) * α := by gcongr have hk2' : ⌊(k + 1 : ℕ) * α⌋ < (k + 1 : ℕ) * 2 := by rw [Int.floor_lt] push_cast gcongr - have hk : ⌊(k + 1 : ℕ) * α⌋ = 2 * k ∨ ⌊(k + 1 : ℕ) * α⌋ = 2 * k + 1 := by omega have hk' : ⌊(k + 1 : ℕ) * α⌋ = 2 * k + 1 := by - rcases hk with hk | hk - · rw [hk] at hc - have hc' : ((k + 1 : ℕ) : ℤ) ∣ ((k + 1 : ℕ) : ℤ) * ((k + 1 : ℕ) : ℤ) - 1 := by - convert hc using 1 - push_cast - ring - rw [dvd_sub_right (dvd_mul_right _ _), ← isUnit_iff_dvd_one, Int.isUnit_iff] at hc' - omega - · exact hk + by_contra + rw [show ⌊(k + 1 : ℕ) * α⌋ = 2 * k by omega] at hc + have hc' : ((k + 1 : ℕ) : ℤ) ∣ ((k + 1 : ℕ) : ℤ) * ((k + 1 : ℕ) : ℤ) - 1 := by + convert hc using 1 + push_cast + ring + rw [dvd_sub_right (dvd_mul_right _ _), ← isUnit_iff_dvd_one, Int.isUnit_iff] at hc' + omega rw [hk'] refine ⟨?_, ?_, h.2⟩ · push_cast ring · rw [Int.floor_eq_iff] at hk' - rw [div_le_iff (by norm_cast; omega), mul_comm α] + rw [div_le_iff₀ (by norm_cast; omega), mul_comm α] convert hk'.1 push_cast ring @@ -159,17 +158,17 @@ lemma not_condition_of_mem_Ioo {α : ℝ} (h : α ∈ Set.Ioo 0 2) : ¬Condition exact_mod_cast Nat.lt_floor_add_one (_ : ℝ) lemma condition_iff_of_mem_Ico {α : ℝ} (h : α ∈ Set.Ico 0 2) : Condition α ↔ α = 0 := by - refine ⟨?_, ?_⟩ + constructor · intro hc - rcases Set.eq_left_or_mem_Ioo_of_mem_Ico h with rfl | ho - · rfl - · exact False.elim (not_condition_of_mem_Ioo ho hc) + cases Set.eq_left_or_mem_Ioo_of_mem_Ico h with + | inl h => exact h + | inr ho => exact False.elim (not_condition_of_mem_Ioo ho hc) · rintro rfl convert condition_two_mul_int 0 norm_num -/-- This is to be determined by the solver of the original problem. -/ -def solutionSet : Set ℝ := {α : ℝ | ∃ m : ℤ, α = 2 * m} +recall Imo2024Q1.Condition (α : ℝ) := (∀ n : ℕ, 0 < n → (n : ℤ) ∣ ∑ i ∈ Finset.Icc 1 n, ⌊i * α⌋) +recall Imo2024Q1.solutionSet := {α : ℝ | ∃ m : ℤ, α = 2 * m} theorem result (α : ℝ) : Condition α ↔ α ∈ solutionSet := by refine ⟨fun h ↦ ?_, ?_⟩ diff --git a/Archive/MiuLanguage/DecisionNec.lean b/Archive/MiuLanguage/DecisionNec.lean index ba3cc0bc34669..694b599ac899d 100644 --- a/Archive/MiuLanguage/DecisionNec.lean +++ b/Archive/MiuLanguage/DecisionNec.lean @@ -67,18 +67,24 @@ is 1 or 2 modulo 3. theorem count_equiv_one_or_two_mod3_of_derivable (en : Miustr) : Derivable en → count I en % 3 = 1 ∨ count I en % 3 = 2 := by intro h - induction' h with _ _ h_ih _ _ h_ih _ _ _ h_ih _ _ _ h_ih - · left; rfl - any_goals apply mod3_eq_1_or_mod3_eq_2 h_ih - -- Porting note: `simp_rw [count_append]` usually doesn't work - · left; rw [count_append, count_append]; rfl - · right; simp_rw [count_append, count_cons, beq_iff_eq, ite_false, add_zero, two_mul] - · left; rw [count_append, count_append, count_append] - simp_rw [count_cons_self, count_nil, count_cons, beq_iff_eq, ite_false, add_right_comm, - add_mod_right] + induction h with + | mk => left; rfl + | r1 _ h_ih => + apply mod3_eq_1_or_mod3_eq_2 h_ih; left + rw [count_append, count_append]; rfl + | r2 _ h_ih => + apply mod3_eq_1_or_mod3_eq_2 h_ih; right + simp_rw [count_append, count_cons, beq_iff_eq, reduceCtorEq, ite_false, add_zero, two_mul] + | r3 _ h_ih => + apply mod3_eq_1_or_mod3_eq_2 h_ih; left + rw [count_append, count_append, count_append] + simp_rw [count_cons_self, count_nil, count_cons, beq_iff_eq, reduceCtorEq, ite_false, + add_right_comm, add_mod_right] simp - · left; rw [count_append, count_append, count_append] - simp only [ne_eq, not_false_eq_true, count_cons_of_ne, count_nil, add_zero] + | r4 _ h_ih => + apply mod3_eq_1_or_mod3_eq_2 h_ih; left + rw [count_append, count_append, count_append] + simp only [ne_eq, not_false_eq_true, count_cons_of_ne, count_nil, add_zero, reduceCtorEq] /-- Using the above theorem, we solve the MU puzzle, showing that `"MU"` is not derivable. Once we have proved that `Derivable` is an instance of `DecidablePred`, this will follow @@ -128,7 +134,7 @@ theorem goodm_of_rule1 (xs : Miustr) (h₁ : Derivable (xs ++ ↑[I])) (h₂ : G exact mhead · change ¬M ∈ tail (xs ++ ↑([I] ++ [U])) rw [← append_assoc, tail_append_singleton_of_ne_nil] - · simp_rw [mem_append, mem_singleton, or_false]; exact nmtail + · simp_rw [mem_append, mem_singleton, reduceCtorEq, or_false]; exact nmtail · exact append_ne_nil_of_left_ne_nil this _ theorem goodm_of_rule2 (xs : Miustr) (_ : Derivable (M :: xs)) (h₂ : Goodm (M :: xs)) : diff --git a/Archive/MiuLanguage/DecisionSuf.lean b/Archive/MiuLanguage/DecisionSuf.lean index 10eaa8e26942b..161e777bc7f34 100644 --- a/Archive/MiuLanguage/DecisionSuf.lean +++ b/Archive/MiuLanguage/DecisionSuf.lean @@ -94,7 +94,7 @@ theorem der_of_der_append_replicate_U_even {z : Miustr} {m : ℕ} rwa [append_nil, append_assoc] /-! -In fine-tuning my application of `simp`, I issued the following commend to determine which lemmas +In fine-tuning my application of `simp`, I issued the following command to determine which lemmas `simp` uses. `set_option trace.simplify.rewrite true` @@ -231,7 +231,7 @@ example (c : ℕ) (h : c % 3 = 1 ∨ c % 3 = 2) : Derivable (M :: replicate c I) /-! ### `Decstr` is a sufficient condition -The remainder of this file sets up the proof that `Decstr en` is sufficent to ensure +The remainder of this file sets up the proof that `Decstr en` is sufficient to ensure `Derivable en`. Decidability of `Derivable en` is an easy consequence. The proof proceeds by induction on the `count U` of `en`. @@ -256,7 +256,8 @@ theorem count_I_eq_length_of_count_U_zero_and_neg_mem {ys : Miustr} (hu : count · simpa only [count] · rw [mem_cons, not_or] at hm; exact hm.2 · -- case `x = U` gives a contradiction. - exfalso; simp only [count, countP_cons_of_pos (· == U) _ (rfl : U == U)] at hu + exfalso + simp only [count, countP_cons_of_pos (· == U) _ (rfl : U == U), reduceCtorEq] at hu /-- `base_case_suf` is the base case of the sufficiency result. -/ @@ -264,7 +265,8 @@ theorem base_case_suf (en : Miustr) (h : Decstr en) (hu : count U en = 0) : Deri rcases h with ⟨⟨mhead, nmtail⟩, hi⟩ have : en ≠ nil := by intro k - simp only [k, count, countP, countP.go, if_false, zero_mod, zero_ne_one, false_or_iff] at hi + simp only [k, count, countP, countP.go, if_false, zero_mod, zero_ne_one, false_or_iff, + reduceCtorEq] at hi rcases exists_cons_of_ne_nil this with ⟨y, ys, rfl⟩ rcases mhead rsuffices ⟨c, rfl, hc⟩ : ∃ c, replicate c I = ys ∧ (c % 3 = 1 ∨ c % 3 = 2) @@ -308,16 +310,17 @@ theorem ind_hyp_suf (k : ℕ) (ys : Miustr) (hu : count U ys = succ k) (hdec : D refine ⟨rfl, ?_, ?_, ?_⟩ · -- Porting note: `simp_rw [count_append]` didn't work rw [count_append] at hu - simp_rw [count_cons, beq_self_eq_true, if_true, add_succ, beq_iff_eq, reduceIte, add_zero, - succ_inj'] at hu + simp_rw [count_cons, beq_self_eq_true, if_true, add_succ, beq_iff_eq, reduceCtorEq, reduceIte, + add_zero, succ_inj'] at hu rwa [count_append, count_append] · apply And.intro rfl rw [cons_append, cons_append] dsimp [tail] at nmtail ⊢ rw [mem_append] at nmtail - simpa only [append_assoc, cons_append, nil_append, mem_append, mem_cons, false_or] using nmtail + simpa only [append_assoc, cons_append, nil_append, mem_append, mem_cons, reduceCtorEq, + false_or] using nmtail · rw [count_append, count_append]; rw [← cons_append, count_append] at hic - simp only [count_cons_self, count_nil, count_cons, if_false] at hic ⊢ + simp only [count_cons_self, count_nil, count_cons, if_false, reduceCtorEq] at hic ⊢ rw [add_right_comm, add_mod_right]; exact hic /-- `der_of_decstr` states that `Derivable en` follows from `Decstr en`. diff --git a/Archive/OxfordInvariants/Summer2021/Week3P1.lean b/Archive/OxfordInvariants/Summer2021/Week3P1.lean index 36d9e899fdf80..d14d56211fd18 100644 --- a/Archive/OxfordInvariants/Summer2021/Week3P1.lean +++ b/Archive/OxfordInvariants/Summer2021/Week3P1.lean @@ -110,7 +110,7 @@ theorem OxfordInvariants.Week3P1 (n : ℕ) (a : ℕ → ℕ) (a_pos : ∀ i ≤ have ha₀ : a 0 ≤ a n * b := by -- Needing this is an artifact of `ℕ`-subtraction. rw [← @Nat.cast_le α, Nat.cast_mul, hb, ← - div_le_iff' (a_pos _ <| n.le_succ.trans <| Nat.le_succ _), ← + div_le_iff₀' (a_pos _ <| n.le_succ.trans <| Nat.le_succ _), ← mul_div_mul_right _ _ (a_pos _ <| Nat.le_succ _).ne'] suffices h : ∀ i, i ∈ Finset.range (n + 1) → 0 ≤ (a 0 : α) * a (n + 1) / (a i * a (i + 1)) from Finset.single_le_sum h (Finset.self_mem_range_succ n) diff --git a/Archive/Sensitivity.lean b/Archive/Sensitivity.lean index af363c85fc5cc..3ebec47f3b7d6 100644 --- a/Archive/Sensitivity.lean +++ b/Archive/Sensitivity.lean @@ -33,14 +33,11 @@ The project was developed at https://github.com/leanprover-community/lean-sensit archived at https://github.com/leanprover-community/mathlib/blob/master/archive/sensitivity.lean -/ - - namespace Sensitivity /-! The next two lines assert we do not want to give a constructive proof, but rather use classical logic. -/ noncomputable section -open scoped Classical local notation "√" => Real.sqrt @@ -194,6 +191,7 @@ noncomputable def ε : ∀ {n : ℕ}, Q n → V n →ₗ[ℝ] ℝ variable {n : ℕ} +open Classical in theorem duality (p q : Q n) : ε p (e q) = if p = q then 1 else 0 := by induction' n with n IH · rw [show p = q from Subsingleton.elim (α := Q 0) p q] @@ -225,10 +223,12 @@ theorem epsilon_total {v : V n} (h : ∀ p : Q n, (ε p) v = 0) : v = 0 := by open Module +open Classical in /-- `e` and `ε` are dual families of vectors. It implies that `e` is indeed a basis and `ε` computes coefficients of decompositions of vectors on that basis. -/ theorem dualBases_e_ε (n : ℕ) : DualBases (@e n) (@ε n) where - eval := duality + eval_same := by simp [duality] + eval_of_ne _ _ h := by simp [duality, h] total := @epsilon_total _ /-! We will now derive the dimension of `V`, first as a cardinal in `dim_V` and, @@ -237,9 +237,11 @@ since this cardinal is finite, as a natural number in `finrank_V` -/ theorem dim_V : Module.rank ℝ (V n) = 2 ^ n := by have : Module.rank ℝ (V n) = (2 ^ n : ℕ) := by + classical rw [rank_eq_card_basis (dualBases_e_ε _).basis, Q.card] assumption_mod_cast +open Classical in instance : FiniteDimensional ℝ (V n) := FiniteDimensional.of_fintype_basis (dualBases_e_ε _).basis @@ -277,15 +279,16 @@ is necessary since otherwise `n • v` refers to the multiplication defined using only the addition of `V`. -/ -theorem f_squared : ∀ v : V n, (f n) (f n v) = (n : ℝ) • v := by - induction' n with n IH _ <;> intro v - · simp only [Nat.cast_zero, zero_smul]; rfl - · cases v; rw [f_succ_apply, f_succ_apply]; simp [IH, add_smul (n : ℝ) 1, add_assoc, V]; abel +theorem f_squared (v : V n) : (f n) (f n v) = (n : ℝ) • v := by + induction n with + | zero => simp only [Nat.cast_zero, zero_smul, f_zero, zero_apply] + | succ n IH => + cases v; rw [f_succ_apply, f_succ_apply]; simp [IH, add_smul (n : ℝ) 1, add_assoc, V]; abel /-! We now compute the matrix of `f` in the `e` basis (`p` is the line index, `q` the column index). -/ - +open Classical in theorem f_matrix : ∀ p q : Q n, |ε q (f n (e p))| = if p ∈ q.adjacent then 1 else 0 := by induction' n with n IH · intro p q @@ -360,7 +363,7 @@ local notation "Card " X:70 => Finset.card (Set.toFinset X) equipped with their subspace structures. The notations come from the general theory of lattices, with inf and sup (also known as meet and join). -/ - +open Classical in /-- If a subset `H` of `Q (m+1)` has cardinal at least `2^m + 1` then the subspace of `V (m+1)` spanned by the corresponding basis vectors non-trivially intersects the range of `g m`. -/ @@ -395,6 +398,7 @@ theorem exists_eigenvalue (H : Set (Q m.succ)) (hH : Card H ≥ 2 ^ m + 1) : rw [Set.toFinset_card] at hH linarith +open Classical in /-- **Huang sensitivity theorem** also known as the **Huang degree theorem** -/ theorem huang_degree_theorem (H : Set (Q m.succ)) (hH : Card H ≥ 2 ^ m + 1) : ∃ q, q ∈ H ∧ √ (m + 1) ≤ Card H ∩ q.adjacent := by @@ -421,7 +425,8 @@ theorem huang_degree_theorem (H : Set (Q m.succ)) (hH : Card H ≥ 2 ^ m + 1) : _ = |(coeffs y).sum fun (i : Q m.succ) (a : ℝ) => a • (ε q ∘ f m.succ ∘ fun i : Q m.succ => e i) i| := by - erw [(f m.succ).map_finsupp_total, (ε q).map_finsupp_total, Finsupp.total_apply] + erw [(f m.succ).map_finsupp_linearCombination, (ε q).map_finsupp_linearCombination, + Finsupp.linearCombination_apply] _ ≤ ∑ p ∈ (coeffs y).support, |coeffs y p * (ε q <| f m.succ <| e p)| := (norm_sum_le _ fun p => coeffs y p * _) _ = ∑ p ∈ (coeffs y).support, |coeffs y p| * ite (p ∈ q.adjacent) 1 0 := by diff --git a/Archive/Wiedijk100Theorems/AscendingDescendingSequences.lean b/Archive/Wiedijk100Theorems/AscendingDescendingSequences.lean index c58d39203d5df..19e2a5834b237 100644 --- a/Archive/Wiedijk100Theorems/AscendingDescendingSequences.lean +++ b/Archive/Wiedijk100Theorems/AscendingDescendingSequences.lean @@ -21,13 +21,10 @@ https://en.wikipedia.org/wiki/Erdos-Szekeres_theorem#Pigeonhole_principle. sequences, increasing, decreasing, Ramsey, Erdos-Szekeres, Erdős–Szekeres, Erdős-Szekeres -/ - variable {α : Type*} [LinearOrder α] {β : Type*} open Function Finset -open scoped Classical - namespace Theorems100 /-- **Erdős–Szekeres Theorem**: Given a sequence of more than `r * s` distinct values, there is an diff --git a/Archive/Wiedijk100Theorems/BallotProblem.lean b/Archive/Wiedijk100Theorems/BallotProblem.lean index 56bcc026d1228..79a0cf487315f 100644 --- a/Archive/Wiedijk100Theorems/BallotProblem.lean +++ b/Archive/Wiedijk100Theorems/BallotProblem.lean @@ -52,7 +52,7 @@ theorem staysPositive_cons {x : ℤ} {l : List ℤ} : theorem sum_nonneg_of_staysPositive : ∀ {l : List ℤ}, l ∈ staysPositive → 0 ≤ l.sum | [], _ => le_rfl - | (_::_), h => (h _ (List.cons_ne_nil _ _) (List.suffix_refl _)).le + | (_::_), h => (h _ (List.cons_ne_nil _ _) List.suffix_rfl).le theorem staysPositive_cons_pos (x : ℤ) (hx : 0 < x) (l : List ℤ) : (x::l) ∈ staysPositive ↔ l ∈ staysPositive := by @@ -252,7 +252,7 @@ theorem ballot_edge (p : ℕ) : condCount (countedSequence (p + 1) 0) staysPosit rw [counted_right_zero] refine condCount_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 (List.mem_of_mem_suffix hx hl₂)] + rw [List.eq_of_mem_replicate (hl₂.mem hx)] norm_num theorem countedSequence_int_pos_counted_succ_succ (p q : ℕ) : @@ -345,10 +345,7 @@ theorem ballot_problem' : linarith field_simp [h₄, h₅, h₆] at * ring - all_goals - refine (ENNReal.mul_lt_top ?_ ?_).ne - · exact (measure_lt_top _ _).ne - · simp [Ne, ENNReal.div_eq_top] + all_goals exact ENNReal.mul_ne_top (measure_ne_top _ _) (by simp [Ne, ENNReal.div_eq_top]) /-- The ballot problem. -/ theorem ballot_problem : diff --git a/Archive/Wiedijk100Theorems/BuffonsNeedle.lean b/Archive/Wiedijk100Theorems/BuffonsNeedle.lean index fafebe0649917..e27b8be9851f2 100644 --- a/Archive/Wiedijk100Theorems/BuffonsNeedle.lean +++ b/Archive/Wiedijk100Theorems/BuffonsNeedle.lean @@ -308,7 +308,7 @@ lemma integral_zero_to_arcsin_min : have hθ_mem : θ ∈ Set.Ioc (-(π / 2)) (π / 2) := by exact ⟨lt_of_lt_of_le (neg_lt_zero.mpr (div_pos Real.pi_pos two_pos)) hθ₁, le_trans hθ₂ (d / l).arcsin_mem_Icc.right⟩ - simp_rw [min_eq_right ((le_div_iff hl).mp ((Real.le_arcsin_iff_sin_le' hθ_mem).mp hθ₂))] + simp_rw [min_eq_right ((le_div_iff₀ hl).mp ((Real.le_arcsin_iff_sin_le' hθ_mem).mp hθ₂))] rw [intervalIntegral.integral_congr this, intervalIntegral.integral_mul_const, integral_sin, Real.cos_zero, Real.cos_arcsin] @@ -328,7 +328,7 @@ lemma integral_arcsin_to_pi_div_two_min (h : d ≤ l) : max_eq_right (d / l).arcsin_le_pi_div_two] at hθ₁ hθ₂ have hθ_mem : θ ∈ Set.Ico (-(π / 2)) (π / 2) := by exact ⟨le_trans (Real.arcsin_mem_Icc (d / l)).left hθ₁, lt_of_le_of_ne hθ₂ hθ_ne_pi_div_two⟩ - simp_rw [min_eq_left ((div_le_iff hl).mp ((Real.arcsin_le_iff_le_sin' hθ_mem).mp hθ₁))] + simp_rw [min_eq_left ((div_le_iff₀ hl).mp ((Real.arcsin_le_iff_le_sin' hθ_mem).mp hθ₁))] rw [intervalIntegral.integral_congr this, intervalIntegral.integral_const, smul_eq_mul] include hd hBₘ hB hl in diff --git a/Archive/Wiedijk100Theorems/CubingACube.lean b/Archive/Wiedijk100Theorems/CubingACube.lean index f2710670e0f47..05b1712152b67 100644 --- a/Archive/Wiedijk100Theorems/CubingACube.lean +++ b/Archive/Wiedijk100Theorems/CubingACube.lean @@ -181,7 +181,7 @@ theorem shiftUp_bottom_subset_bottoms (hc : (cs i).xm ≠ 1) : (cs i).shiftUp.bottom ⊆ ⋃ i : ι, (cs i).bottom := by intro p hp; cases' hp with hp0 hps; rw [tail_shiftUp] at hps have : p ∈ (unitCube : Cube (n + 1)).toSet := by - simp only [toSet, forall_fin_succ, hp0, side_unitCube, mem_setOf_eq, mem_Ico, head_shiftUp] + simp only [toSet, forall_iff_succ, hp0, side_unitCube, mem_setOf_eq, mem_Ico, head_shiftUp] refine ⟨⟨?_, ?_⟩, ?_⟩ · rw [← zero_add (0 : ℝ)]; apply add_le_add · apply zero_le_b h @@ -225,7 +225,7 @@ theorem valley_unitCube [Nontrivial ι] (h : Correct cs) : Valley cs unitCube := intro h0 hv have : v ∈ (unitCube : Cube (n + 1)).toSet := by dsimp only [toSet, unitCube, mem_setOf_eq] - rw [forall_fin_succ, h0]; constructor + rw [forall_iff_succ, h0]; constructor · norm_num [side, unitCube] · exact hv rw [← h.2, mem_iUnion] at this; rcases this with ⟨i, hi⟩ @@ -408,14 +408,14 @@ theorem mi_not_onBoundary (j : Fin n) : ¬OnBoundary (mi_mem_bcubes : mi h v ∈ have i'_i'' : i' ≠ i'' := by rintro ⟨⟩ have : (cs i).b ∈ (cs i').toSet := by - simp only [toSet, forall_fin_succ, hi.1, bottom_mem_side h2i', true_and_iff, mem_setOf_eq] + simp only [toSet, forall_iff_succ, hi.1, bottom_mem_side h2i', true_and_iff, mem_setOf_eq] intro j₂; by_cases hj₂ : j₂ = j · simpa [p', side_tail, hj'.symm, hj₂] using hi''.2 j · simpa [p, hj₂] using hi'.2 j₂ apply not_disjoint_iff.mpr ⟨(cs i).b, (cs i).b_mem_toSet, this⟩ (h.1 i_i') have i_i'' : i ≠ i'' := by intro h; induction h; simpa [p', hx'.2] using hi''.2 j' apply Not.elim _ (h.1 i'_i'') - simp_rw [onFun, comp, toSet_disjoint, not_exists, not_disjoint_iff, forall_fin_succ] + simp_rw [onFun, comp, toSet_disjoint, not_exists, not_disjoint_iff, forall_iff_succ] refine ⟨⟨c.b 0, bottom_mem_side h2i', bottom_mem_side h2i''⟩, ?_⟩ intro j₂ by_cases hj₂ : j₂ = j @@ -480,9 +480,9 @@ theorem valley_mi : Valley cs (cs (mi h v)).shiftUp := by have h3i'' : (cs i).w < (cs i'').w := by apply mi_strict_minimal _ h2i''; rintro rfl; apply h2p3; convert hi''.2 let p' := @cons n (fun _ => ℝ) (cs i).xm p3 - have hp' : p' ∈ (cs i').toSet := by simpa [p', toSet, forall_fin_succ, hi'.symm] using h1p3 + have hp' : p' ∈ (cs i').toSet := by simpa [p', toSet, forall_iff_succ, hi'.symm] using h1p3 have h2p' : p' ∈ (cs i'').toSet := by - simp only [p', toSet, forall_fin_succ, cons_succ, cons_zero, mem_setOf_eq] + simp only [p', toSet, forall_iff_succ, cons_succ, cons_zero, mem_setOf_eq] refine ⟨?_, by simpa [toSet] using hi''.2⟩ have : (cs i).b 0 = (cs i'').b 0 := by rw [hi.1, h2i''.1] simp [side, hw', xm, this, h3i''] diff --git a/Archive/Wiedijk100Theorems/FriendshipGraphs.lean b/Archive/Wiedijk100Theorems/FriendshipGraphs.lean index a25f296a01c50..30ac6b66643fd 100644 --- a/Archive/Wiedijk100Theorems/FriendshipGraphs.lean +++ b/Archive/Wiedijk100Theorems/FriendshipGraphs.lean @@ -38,7 +38,6 @@ be phrased in terms of counting walks. -/ - open scoped Classical namespace Theorems100 @@ -82,8 +81,10 @@ include hG in theorem adjMatrix_sq_of_ne {v w : V} (hvw : v ≠ w) : (G.adjMatrix R ^ 2 : Matrix V V R) v w = 1 := by rw [sq, ← Nat.cast_one, ← hG hvw] - simp [commonNeighbors, neighborFinset_eq_filter, Finset.filter_filter, and_comm, - ← neighborFinset_def] + simp only [mul_adjMatrix_apply, neighborFinset_eq_filter, adjMatrix_apply, + sum_boole, filter_filter, and_comm, commonNeighbors, + Fintype.card_ofFinset (s := filter (fun x ↦ x ∈ G.neighborSet v ∩ G.neighborSet w) univ), + Set.mem_inter_iff, mem_neighborSet] include hG in /-- This calculation amounts to counting the number of length 3 walks between nonadjacent vertices. diff --git a/Archive/Wiedijk100Theorems/Konigsberg.lean b/Archive/Wiedijk100Theorems/Konigsberg.lean index 93d5c585639da..80eff930911c5 100644 --- a/Archive/Wiedijk100Theorems/Konigsberg.lean +++ b/Archive/Wiedijk100Theorems/Konigsberg.lean @@ -73,7 +73,7 @@ lemma not_even_degree_iff (w : Verts) : ¬Even (degree w) ↔ w = V1 ∨ w = V2 lemma setOf_odd_degree_eq : {v | Odd (graph.degree v)} = {Verts.V1, Verts.V2, Verts.V3, Verts.V4} := by ext w - simp [not_even_degree_iff] + simp [not_even_degree_iff, ← Nat.not_even_iff_odd] /-- The Königsberg graph is not Eulerian. -/ theorem not_isEulerian {u v : Verts} (p : graph.Walk u v) (h : p.IsEulerian) : False := by @@ -81,6 +81,6 @@ theorem not_isEulerian {u v : Verts} (p : graph.Walk u v) (h : p.IsEulerian) : F have h' := setOf_odd_degree_eq apply_fun Fintype.card at h' rw [h'] at h - norm_num at h + simp at h end Konigsberg diff --git a/Archive/Wiedijk100Theorems/Partition.lean b/Archive/Wiedijk100Theorems/Partition.lean index 38232baf5bdab..5895ebcb7fdd8 100644 --- a/Archive/Wiedijk100Theorems/Partition.lean +++ b/Archive/Wiedijk100Theorems/Partition.lean @@ -127,7 +127,7 @@ theorem num_series' [Field α] (i : ℕ) : | zero => simp [mul_sub, zero_pow, constantCoeff_indicator] | succ n => simp only [coeff_one, if_false, mul_sub, mul_one, coeff_indicator, - LinearMap.map_sub] + LinearMap.map_sub, reduceCtorEq] simp_rw [coeff_mul, coeff_X_pow, coeff_indicator, @boole_mul _ _ _ _] erw [sum_ite, sum_ite] simp_rw [@filter_filter _ _ _ _ _, sum_const_zero, add_zero, sum_const, nsmul_eq_mul, mul_one, @@ -314,10 +314,9 @@ theorem partialDistinctGF_prop [CommSemiring α] (n m : ℕ) : convert partialGF_prop α n ((range m).map ⟨Nat.succ, Nat.succ_injective⟩) _ (fun _ => {0, 1}) (fun _ _ => Or.inl rfl) using 2 - · congr - congr! with p + · congr! with p rw [Multiset.nodup_iff_count_le_one] - congr! with i + congr! 1 with i rcases Multiset.count i p.parts with (_ | _ | ms) <;> simp · simp_rw [Finset.prod_map, two_series] congr with i diff --git a/Archive/Wiedijk100Theorems/PerfectNumbers.lean b/Archive/Wiedijk100Theorems/PerfectNumbers.lean index fcca5aa780ae0..e23628d48b3e3 100644 --- a/Archive/Wiedijk100Theorems/PerfectNumbers.lean +++ b/Archive/Wiedijk100Theorems/PerfectNumbers.lean @@ -29,9 +29,6 @@ https://en.wikipedia.org/wiki/Euclid%E2%80%93Euler_theorem namespace Theorems100 -theorem odd_mersenne_succ (k : ℕ) : ¬2 ∣ mersenne (k + 1) := by - simp [← even_iff_two_dvd, ← Nat.even_add_one, parity_simps] - namespace Nat open ArithmeticFunction Finset @@ -43,10 +40,9 @@ theorem sigma_two_pow_eq_mersenne_succ (k : ℕ) : σ 1 (2 ^ k) = mersenne (k + /-- Euclid's theorem that Mersenne primes induce perfect numbers -/ theorem perfect_two_pow_mul_mersenne_of_prime (k : ℕ) (pr : (mersenne (k + 1)).Prime) : Nat.Perfect (2 ^ k * mersenne (k + 1)) := by - rw [Nat.perfect_iff_sum_divisors_eq_two_mul, ← mul_assoc, ← pow_succ', - ← sigma_one_apply, mul_comm, - isMultiplicative_sigma.map_mul_of_coprime - (Nat.prime_two.coprime_pow_of_not_dvd (odd_mersenne_succ _)), + rw [Nat.perfect_iff_sum_divisors_eq_two_mul, ← mul_assoc, ← pow_succ', ← sigma_one_apply, + mul_comm, + isMultiplicative_sigma.map_mul_of_coprime ((Odd.coprime_two_right (by simp)).pow_right _), sigma_two_pow_eq_mersenne_succ] · simp [pr, Nat.prime_two, sigma_one_apply] · positivity @@ -81,9 +77,8 @@ theorem eq_two_pow_mul_prime_mersenne_of_even_perfect {n : ℕ} (ev : Even n) (p rw [Nat.perfect_iff_sum_divisors_eq_two_mul hpos, ← sigma_one_apply, isMultiplicative_sigma.map_mul_of_coprime (Nat.prime_two.coprime_pow_of_not_dvd hm).symm, sigma_two_pow_eq_mersenne_succ, ← mul_assoc, ← pow_succ'] at perf - rcases Nat.Coprime.dvd_of_dvd_mul_left - (Nat.prime_two.coprime_pow_of_not_dvd (odd_mersenne_succ _)) (Dvd.intro _ perf) with - ⟨j, rfl⟩ + obtain ⟨j, rfl⟩ := ((Odd.coprime_two_right (by simp)).pow_right _).dvd_of_dvd_mul_left + (Dvd.intro _ perf) rw [← mul_assoc, mul_comm _ (mersenne _), mul_assoc] at perf have h := mul_left_cancel₀ (by positivity) perf rw [sigma_one_apply, Nat.sum_divisors_eq_sum_properDivisors_add_self, ← succ_mersenne, add_mul, diff --git a/Archive/Wiedijk100Theorems/SumOfPrimeReciprocalsDiverges.lean b/Archive/Wiedijk100Theorems/SumOfPrimeReciprocalsDiverges.lean index 31e32ae2f76a7..74017293ce14b 100644 --- a/Archive/Wiedijk100Theorems/SumOfPrimeReciprocalsDiverges.lean +++ b/Archive/Wiedijk100Theorems/SumOfPrimeReciprocalsDiverges.lean @@ -38,10 +38,6 @@ The formalization follows Erdős's proof by upper and lower estimates. https://en.wikipedia.org/wiki/Divergence_of_the_sum_of_the_reciprocals_of_the_primes -/ - - -open scoped Classical - open Filter Finset namespace Theorems100 @@ -57,6 +53,7 @@ of `p`, i.e., those `e < x` for which there is a prime `p ∈ (k, x]` that divid def U (x k : ℕ) := Finset.biUnion (P x k) (fun p => Finset.filter (fun e => p ∣ e + 1) (range x)) +open Classical in /-- Those `e < x` for which `e + 1` is a product of powers of primes smaller than or equal to `k`. -/ noncomputable def M (x k : ℕ) := @@ -217,6 +214,7 @@ theorem Real.tendsto_sum_one_div_prime_atTop : -- This is indeed a partition, so `|U| + |M| = |range x| = x`. have h2 : x = card U' + card M' := by rw [← card_range x, hU', hM', ← range_sdiff_eq_biUnion] + classical exact (card_sdiff_add_card_eq_card (Finset.filter_subset _ _)).symm -- But for the `x` we have chosen above, both `|U|` and `|M|` are less than or equal to `x / 2`, -- and for U, the inequality is strict. diff --git a/Archive/ZagierTwoSquares.lean b/Archive/ZagierTwoSquares.lean index 894cf667b4e0c..f4846d4fea64c 100644 --- a/Archive/ZagierTwoSquares.lean +++ b/Archive/ZagierTwoSquares.lean @@ -50,7 +50,7 @@ lemma zagierSet_lower_bound {x y z : ℕ} (h : (x, y, z) ∈ zagierSet k) : 0 < cases' (Nat.dvd_prime hk.out).1 (dvd_of_mul_left_eq _ h) with e e all_goals simp only [e, self_eq_add_left, ne_eq, add_eq_zero, and_false, not_false_eq_true, - mul_eq_left₀] at h + mul_eq_left₀, reduceCtorEq] at h simp only [h, zero_add] at hk exact Nat.not_prime_one hk.out @@ -148,7 +148,7 @@ theorem eq_of_mem_fixedPoints {t : zagierSet k} (mem : t ∈ fixedPoints (comple split_ifs at mem with less more <;> -- less (completely handled by the pre-applied `simp_all only`) simp_all only [not_lt, Prod.mk.injEq, add_right_eq_self, mul_eq_zero, false_or, - lt_self_iff_false] + lt_self_iff_false, reduceCtorEq] · -- more obtain ⟨_, _, _⟩ := mem; simp_all · -- middle (the one fixed point falls under this case) @@ -161,7 +161,7 @@ theorem eq_of_mem_fixedPoints {t : zagierSet k} (mem : t ∈ fixedPoints (comple cases' (Nat.dvd_prime hk.out).1 (dvd_of_mul_left_eq _ h) with e e · rw [e, mul_one] at h simp_all [h, show z = 0 by linarith [e]] - · simp only [e, mul_left_eq_self₀, add_eq_zero, and_false, or_false] at h + · simp only [e, mul_left_eq_self₀, add_eq_zero, and_false, or_false, reduceCtorEq] at h simp only [h, true_and] linarith [e] diff --git a/Cache/IO.lean b/Cache/IO.lean index 850ce0a414f8c..a2c34ef9a0e7e 100644 --- a/Cache/IO.lean +++ b/Cache/IO.lean @@ -10,7 +10,7 @@ import Lean.Data.RBTree import Lean.Data.Json.Printer import Lean.Data.Json.Parser -set_option autoImplicit true +variable {α : Type} /-- Removes a parent path from the beginning of a path -/ def System.FilePath.withoutParent (path parent : FilePath) : FilePath := diff --git a/Cache/Requests.lean b/Cache/Requests.lean index 3e022f97e0853..5c4c6038aecaa 100644 --- a/Cache/Requests.lean +++ b/Cache/Requests.lean @@ -6,8 +6,6 @@ Authors: Arthur Paulino import Lean.Data.Json.Parser import Cache.Hashing -set_option autoImplicit true - namespace Cache.Requests -- FRO cache is flaky so disable until we work out the kinks: https://leanprover.zulipchat.com/#narrow/stream/113488-general/topic/The.20cache.20doesn't.20work/near/411058849 @@ -255,7 +253,7 @@ def QueryType.prefix : QueryType → String | commits => "&prefix=c/" | all => default -def formatError : IO α := +def formatError {α : Type} : IO α := throw <| IO.userError "Invalid format for curl return" def QueryType.desc : QueryType → String diff --git a/Counterexamples/CanonicallyOrderedCommSemiringTwoMul.lean b/Counterexamples/CanonicallyOrderedCommSemiringTwoMul.lean index fef5690af55aa..832f9e8bef97d 100644 --- a/Counterexamples/CanonicallyOrderedCommSemiringTwoMul.lean +++ b/Counterexamples/CanonicallyOrderedCommSemiringTwoMul.lean @@ -134,14 +134,14 @@ theorem mul_L {a b : ℕ × ZMod 2} (ha : a ≠ (0, 1)) (hb : b ≠ (0, 1)) : a rcases a with ⟨a, a2⟩ rcases b with ⟨b, b2⟩ cases b - · rcases mem_zmod_2 b2 with (rfl | rfl) <;> rcases mem_zmod_2 a2 with (rfl | rfl) <;> simp - -- while this looks like a non-terminal `simp`, it (almost) isn't: there is only one goal where - -- it does not finish the proof and on that goal it asks to prove `false` + · rcases mem_zmod_2 b2 with (rfl | rfl) <;> rcases mem_zmod_2 a2 with (rfl | rfl) <;> + simp only [Prod.mk_mul_mk, mul_zero, mul_one, ne_eq, Prod.mk.injEq, zero_ne_one, and_false, + not_false_eq_true, not_true_eq_false] exact hb rfl cases a - · rcases mem_zmod_2 b2 with (rfl | rfl) <;> rcases mem_zmod_2 a2 with (rfl | rfl) <;> simp - -- while this looks like a non-terminal `simp`, it (almost) isn't: there is only one goal where - -- it does not finish the proof and on that goal it asks to prove `false` + · rcases mem_zmod_2 b2 with (rfl | rfl) <;> rcases mem_zmod_2 a2 with (rfl | rfl) <;> + simp only [Prod.mk_mul_mk, mul_zero, zero_mul, mul_one, ne_eq, Prod.mk.injEq, zero_ne_one, + and_false, not_false_eq_true, not_true_eq_false] exact ha rfl · simp [mul_ne_zero _ _, Nat.succ_ne_zero _] diff --git a/Counterexamples/CliffordAlgebraNotInjective.lean b/Counterexamples/CliffordAlgebraNotInjective.lean index b84245b0d53cc..c924cfe15c215 100644 --- a/Counterexamples/CliffordAlgebraNotInjective.lean +++ b/Counterexamples/CliffordAlgebraNotInjective.lean @@ -52,7 +52,7 @@ theorem mem_kIdeal_iff (x : MvPolynomial (Fin 3) (ZMod 2)) : have : kIdeal = Ideal.span ((monomial · (1 : ZMod 2)) '' Set.range (Finsupp.single · 2)) := by simp_rw [kIdeal, X, monomial_mul, one_mul, ← Finsupp.single_add, ← Set.range_comp, - Function.comp] + Function.comp_def] rw [this, mem_ideal_span_monomial_image] simp @@ -132,7 +132,7 @@ theorem sq_zero_of_αβγ_mul {x : K} : α * β * γ * x = 0 → x * x = 0 := by rw [Ideal.Quotient.eq_zero_iff_mem, Ideal.Quotient.eq_zero_iff_mem] exact mul_self_mem_kIdeal_of_X0_X1_X2_mul_mem -/-- Though `αβγ` is not itself zero-/ +/-- Though `αβγ` is not itself zero -/ theorem αβγ_ne_zero : α * β * γ ≠ 0 := fun h => X0_X1_X2_not_mem_kIdeal <| Ideal.Quotient.eq_zero_iff_mem.1 h diff --git a/Counterexamples/Girard.lean b/Counterexamples/Girard.lean index 2109c68505664..2045588c13e53 100644 --- a/Counterexamples/Girard.lean +++ b/Counterexamples/Girard.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ import Mathlib.Logic.Basic -import Mathlib.Init.Set +import Mathlib.Data.Set.Defs /-! # Girard's paradox diff --git a/Counterexamples/MonicNonRegular.lean b/Counterexamples/MonicNonRegular.lean index 80b870310e2b9..954e6c22a84c6 100644 --- a/Counterexamples/MonicNonRegular.lean +++ b/Counterexamples/MonicNonRegular.lean @@ -88,7 +88,8 @@ theorem monic_X_add_two : Monic (X + C 2 : N₃[X]) := by unfold Monic leadingCoeff nontriviality rw [natDegree_X_add_C 2] - simp only [natDegree_X_add_C 2, coeff_C, coeff_add, coeff_X_one, ite_false, add_zero] + simp only [natDegree_X_add_C 2, coeff_C, coeff_add, coeff_X_one, ite_false, add_zero, + reduceCtorEq] theorem not_isLeftRegular_X_add_two : ¬ IsLeftRegular (X + C 2 : N₃[X]) := by intro h diff --git a/Counterexamples/Phillips.lean b/Counterexamples/Phillips.lean index 0f73a13e843b5..755cb6b94dd69 100644 --- a/Counterexamples/Phillips.lean +++ b/Counterexamples/Phillips.lean @@ -269,7 +269,7 @@ theorem exists_discrete_support_nonpos (f : BoundedAdditiveMeasure α) : refine ⟨t, fun u => ?_⟩ calc f (↑u \ ↑s) ≤ S := le_ciSup B _ - _ ≤ 2 * f (↑t \ ↑s) := (div_le_iff' two_pos).1 ht.le + _ ≤ 2 * f (↑t \ ↑s) := (div_le_iff₀' two_pos).1 ht.le choose! F hF using this -- iterate the above construction, by adding at each step a set with measure close to maximal in -- the complement of already chosen points. This is the set `s n` at step `n`. @@ -283,7 +283,7 @@ theorem exists_discrete_support_nonpos (f : BoundedAdditiveMeasure α) : have ε_pos : 0 < ε := ht have I1 : ∀ n, ε / 2 ≤ f (↑(s (n + 1)) \ ↑(s n)) := by intro n - rw [div_le_iff' (show (0 : ℝ) < 2 by norm_num), hε] + rw [div_le_iff₀' (show (0 : ℝ) < 2 by norm_num), hε] convert hF (s n) u using 2 · dsimp ext x @@ -296,8 +296,7 @@ theorem exists_discrete_support_nonpos (f : BoundedAdditiveMeasure α) : induction n with | zero => simp only [s, BoundedAdditiveMeasure.empty, id, Nat.cast_zero, zero_mul, - Function.iterate_zero, Subtype.coe_mk] - rfl + Function.iterate_zero, Subtype.coe_mk, le_rfl] | succ n IH => have : (s (n + 1)).1 = (s (n + 1)).1 \ (s n).1 ∪ (s n).1 := by simpa only [s, Function.iterate_succ', union_diff_self] @@ -309,7 +308,7 @@ theorem exists_discrete_support_nonpos (f : BoundedAdditiveMeasure α) : _ ≤ f (↑(s (n + 1 : ℕ)) \ ↑(s n)) + f ↑(s n) := add_le_add (I1 n) IH rcases exists_nat_gt (f.C / (ε / 2)) with ⟨n, hn⟩ have : (n : ℝ) ≤ f.C / (ε / 2) := by - rw [le_div_iff (half_pos ε_pos)]; exact (I2 n).trans (f.le_bound _) + rw [le_div_iff₀ (half_pos ε_pos)]; exact (I2 n).trans (f.le_bound _) exact lt_irrefl _ (this.trans_lt hn) theorem exists_discrete_support (f : BoundedAdditiveMeasure α) : diff --git a/Counterexamples/SorgenfreyLine.lean b/Counterexamples/SorgenfreyLine.lean index 6015b4d98307e..746700b0769de 100644 --- a/Counterexamples/SorgenfreyLine.lean +++ b/Counterexamples/SorgenfreyLine.lean @@ -129,7 +129,7 @@ theorem map_toReal_nhds (a : ℝₗ) : map toReal (𝓝 a) = 𝓝[≥] toReal a simpa only [toReal.image_eq_preimage] using nhdsWithin_Ici_basis_Ico (toReal a) theorem nhds_eq_map (a : ℝₗ) : 𝓝 a = map toReal.symm (𝓝[≥] (toReal a)) := by - simp_rw [← map_toReal_nhds, map_map, (· ∘ ·), toReal.symm_apply_apply, map_id'] + simp_rw [← map_toReal_nhds, map_map, Function.comp_def, toReal.symm_apply_apply, map_id'] theorem nhds_eq_comap (a : ℝₗ) : 𝓝 a = comap toReal (𝓝[≥] (toReal a)) := by rw [← map_toReal_nhds, comap_map toReal.injective] diff --git a/LongestPole/SpeedCenterJson.lean b/LongestPole/SpeedCenterJson.lean index 89bfb54a07ffa..63cf423acecec 100644 --- a/LongestPole/SpeedCenterJson.lean +++ b/LongestPole/SpeedCenterJson.lean @@ -47,7 +47,7 @@ structure RunResponse where run : Run deriving ToJson, FromJson -/-- The error response-/ +/-- The error response -/ structure ErrorMessage where repo_id : String message : String diff --git a/Mathlib.lean b/Mathlib.lean index 7227416de3c6a..ae067f576d7d7 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -21,6 +21,7 @@ import Mathlib.Algebra.Algebra.RestrictScalars import Mathlib.Algebra.Algebra.Spectrum import Mathlib.Algebra.Algebra.Subalgebra.Basic import Mathlib.Algebra.Algebra.Subalgebra.Directed +import Mathlib.Algebra.Algebra.Subalgebra.IsSimpleOrder import Mathlib.Algebra.Algebra.Subalgebra.MulOpposite import Mathlib.Algebra.Algebra.Subalgebra.Operations import Mathlib.Algebra.Algebra.Subalgebra.Order @@ -41,6 +42,7 @@ import Mathlib.Algebra.BigOperators.Finsupp import Mathlib.Algebra.BigOperators.Group.Finset import Mathlib.Algebra.BigOperators.Group.List import Mathlib.Algebra.BigOperators.Group.Multiset +import Mathlib.Algebra.BigOperators.GroupWithZero.Action import Mathlib.Algebra.BigOperators.GroupWithZero.Finset import Mathlib.Algebra.BigOperators.Intervals import Mathlib.Algebra.BigOperators.Module @@ -171,6 +173,7 @@ import Mathlib.Algebra.ContinuedFractions.TerminatedStable import Mathlib.Algebra.ContinuedFractions.Translations import Mathlib.Algebra.CubicDiscriminant import Mathlib.Algebra.DirectLimit +import Mathlib.Algebra.DirectSum.AddChar import Mathlib.Algebra.DirectSum.Algebra import Mathlib.Algebra.DirectSum.Basic import Mathlib.Algebra.DirectSum.Decomposition @@ -259,6 +262,7 @@ import Mathlib.Algebra.Group.Opposite import Mathlib.Algebra.Group.PNatPowAssoc import Mathlib.Algebra.Group.Pi.Basic import Mathlib.Algebra.Group.Pi.Lemmas +import Mathlib.Algebra.Group.Pointwise.Set import Mathlib.Algebra.Group.Prod import Mathlib.Algebra.Group.Semiconj.Basic import Mathlib.Algebra.Group.Semiconj.Defs @@ -311,6 +315,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.Prod import Mathlib.Algebra.GroupWithZero.Semiconj import Mathlib.Algebra.GroupWithZero.ULift @@ -322,6 +327,7 @@ import Mathlib.Algebra.HierarchyDesign import Mathlib.Algebra.Homology.Additive import Mathlib.Algebra.Homology.Augment import Mathlib.Algebra.Homology.Bifunctor +import Mathlib.Algebra.Homology.BifunctorAssociator import Mathlib.Algebra.Homology.BifunctorFlip import Mathlib.Algebra.Homology.BifunctorHomotopy import Mathlib.Algebra.Homology.BifunctorShift @@ -331,7 +337,8 @@ import Mathlib.Algebra.Homology.ComplexShapeSigns import Mathlib.Algebra.Homology.ConcreteCategory import Mathlib.Algebra.Homology.DerivedCategory.Basic import Mathlib.Algebra.Homology.DerivedCategory.ExactFunctor -import Mathlib.Algebra.Homology.DerivedCategory.Ext +import Mathlib.Algebra.Homology.DerivedCategory.Ext.Basic +import Mathlib.Algebra.Homology.DerivedCategory.Ext.ExtClass import Mathlib.Algebra.Homology.DerivedCategory.HomologySequence import Mathlib.Algebra.Homology.DerivedCategory.ShortExact import Mathlib.Algebra.Homology.DerivedCategory.SingleTriangle @@ -549,12 +556,12 @@ import Mathlib.Algebra.Order.Field.Pi import Mathlib.Algebra.Order.Field.Power import Mathlib.Algebra.Order.Field.Rat import Mathlib.Algebra.Order.Field.Subfield -import Mathlib.Algebra.Order.Field.Unbundled.Basic import Mathlib.Algebra.Order.Floor import Mathlib.Algebra.Order.Floor.Div import Mathlib.Algebra.Order.Floor.Prime import Mathlib.Algebra.Order.Group.Abs 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.Cone @@ -577,7 +584,9 @@ import Mathlib.Algebra.Order.Group.Unbundled.Abs import Mathlib.Algebra.Order.Group.Unbundled.Basic import Mathlib.Algebra.Order.Group.Unbundled.Int import Mathlib.Algebra.Order.Group.Units +import Mathlib.Algebra.Order.GroupWithZero.Action.Synonym 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.WithZero @@ -645,6 +654,8 @@ import Mathlib.Algebra.Order.Ring.Unbundled.Basic import Mathlib.Algebra.Order.Ring.Unbundled.Nonneg import Mathlib.Algebra.Order.Ring.Unbundled.Rat import Mathlib.Algebra.Order.Ring.WithTop +import Mathlib.Algebra.Order.Star.Basic +import Mathlib.Algebra.Order.Star.Conjneg import Mathlib.Algebra.Order.Sub.Basic import Mathlib.Algebra.Order.Sub.Defs import Mathlib.Algebra.Order.Sub.Prod @@ -743,6 +754,7 @@ import Mathlib.Algebra.Ring.NegOnePow import Mathlib.Algebra.Ring.Opposite import Mathlib.Algebra.Ring.Parity import Mathlib.Algebra.Ring.Pi +import Mathlib.Algebra.Ring.Pointwise.Set import Mathlib.Algebra.Ring.Prod import Mathlib.Algebra.Ring.Rat import Mathlib.Algebra.Ring.Regular @@ -769,11 +781,11 @@ import Mathlib.Algebra.Star.BigOperators import Mathlib.Algebra.Star.CHSH import Mathlib.Algebra.Star.Center import Mathlib.Algebra.Star.CentroidHom +import Mathlib.Algebra.Star.Conjneg import Mathlib.Algebra.Star.Free import Mathlib.Algebra.Star.Module import Mathlib.Algebra.Star.NonUnitalSubalgebra import Mathlib.Algebra.Star.NonUnitalSubsemiring -import Mathlib.Algebra.Star.Order import Mathlib.Algebra.Star.Pi import Mathlib.Algebra.Star.Pointwise import Mathlib.Algebra.Star.Prod @@ -812,6 +824,7 @@ import Mathlib.AlgebraicGeometry.Morphisms.Affine import Mathlib.AlgebraicGeometry.Morphisms.Basic import Mathlib.AlgebraicGeometry.Morphisms.ClosedImmersion import Mathlib.AlgebraicGeometry.Morphisms.Constructors +import Mathlib.AlgebraicGeometry.Morphisms.FinitePresentation import Mathlib.AlgebraicGeometry.Morphisms.FiniteType import Mathlib.AlgebraicGeometry.Morphisms.IsIso import Mathlib.AlgebraicGeometry.Morphisms.OpenImmersion @@ -914,6 +927,7 @@ import Mathlib.Analysis.BoxIntegral.Partition.Tagged import Mathlib.Analysis.CStarAlgebra.Basic import Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Basic import Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Instances +import Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Integral import Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.NonUnital import Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Order import Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Restrict @@ -923,6 +937,7 @@ import Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Unitary import Mathlib.Analysis.CStarAlgebra.Exponential import Mathlib.Analysis.CStarAlgebra.GelfandDuality import Mathlib.Analysis.CStarAlgebra.Matrix +import Mathlib.Analysis.CStarAlgebra.Module.Constructions import Mathlib.Analysis.CStarAlgebra.Module.Defs import Mathlib.Analysis.CStarAlgebra.Module.Synonym import Mathlib.Analysis.CStarAlgebra.Multiplier @@ -1019,6 +1034,7 @@ import Mathlib.Analysis.Complex.Conformal import Mathlib.Analysis.Complex.Convex import Mathlib.Analysis.Complex.Hadamard import Mathlib.Analysis.Complex.HalfPlane +import Mathlib.Analysis.Complex.IsIntegral import Mathlib.Analysis.Complex.Isometry import Mathlib.Analysis.Complex.Liouville import Mathlib.Analysis.Complex.LocallyUniformLimit @@ -1111,6 +1127,7 @@ import Mathlib.Analysis.InnerProductSpace.ConformalLinearMap import Mathlib.Analysis.InnerProductSpace.Dual import Mathlib.Analysis.InnerProductSpace.EuclideanDist import Mathlib.Analysis.InnerProductSpace.GramSchmidtOrtho +import Mathlib.Analysis.InnerProductSpace.JointEigenspace import Mathlib.Analysis.InnerProductSpace.LaxMilgram import Mathlib.Analysis.InnerProductSpace.LinearPMap import Mathlib.Analysis.InnerProductSpace.MeanErgodic @@ -1124,6 +1141,7 @@ import Mathlib.Analysis.InnerProductSpace.ProdL2 import Mathlib.Analysis.InnerProductSpace.Projection import Mathlib.Analysis.InnerProductSpace.Rayleigh import Mathlib.Analysis.InnerProductSpace.Spectrum +import Mathlib.Analysis.InnerProductSpace.StarOrder import Mathlib.Analysis.InnerProductSpace.Symmetric import Mathlib.Analysis.InnerProductSpace.TwoDim import Mathlib.Analysis.InnerProductSpace.WeakOperatorTopology @@ -1158,6 +1176,7 @@ import Mathlib.Analysis.Normed.Algebra.Unitization import Mathlib.Analysis.Normed.Algebra.UnitizationL1 import Mathlib.Analysis.Normed.Field.Basic import Mathlib.Analysis.Normed.Field.InfiniteSum +import Mathlib.Analysis.Normed.Field.Lemmas import Mathlib.Analysis.Normed.Field.UnitBall import Mathlib.Analysis.Normed.Group.AddCircle import Mathlib.Analysis.Normed.Group.AddTorsor @@ -1256,6 +1275,7 @@ import Mathlib.Analysis.RCLike.Lemmas import Mathlib.Analysis.Seminorm import Mathlib.Analysis.SpecialFunctions.Arsinh import Mathlib.Analysis.SpecialFunctions.Bernstein +import Mathlib.Analysis.SpecialFunctions.BinaryEntropy import Mathlib.Analysis.SpecialFunctions.CompareExp import Mathlib.Analysis.SpecialFunctions.Complex.Analytic import Mathlib.Analysis.SpecialFunctions.Complex.Arctan @@ -1351,13 +1371,15 @@ import Mathlib.CategoryTheory.Adjunction.Basic import Mathlib.CategoryTheory.Adjunction.Comma import Mathlib.CategoryTheory.Adjunction.Evaluation import Mathlib.CategoryTheory.Adjunction.FullyFaithful -import Mathlib.CategoryTheory.Adjunction.Lifting +import Mathlib.CategoryTheory.Adjunction.Lifting.Left +import Mathlib.CategoryTheory.Adjunction.Lifting.Right import Mathlib.CategoryTheory.Adjunction.Limits import Mathlib.CategoryTheory.Adjunction.Mates import Mathlib.CategoryTheory.Adjunction.Opposites import Mathlib.CategoryTheory.Adjunction.Over import Mathlib.CategoryTheory.Adjunction.Reflective import Mathlib.CategoryTheory.Adjunction.Restrict +import Mathlib.CategoryTheory.Adjunction.Triple import Mathlib.CategoryTheory.Adjunction.Unique import Mathlib.CategoryTheory.Adjunction.Whiskering import Mathlib.CategoryTheory.Balanced @@ -1400,6 +1422,7 @@ import Mathlib.CategoryTheory.Category.RelCat import Mathlib.CategoryTheory.Category.TwoP import Mathlib.CategoryTheory.Category.ULift import Mathlib.CategoryTheory.ChosenFiniteProducts +import Mathlib.CategoryTheory.ChosenFiniteProducts.Cat import Mathlib.CategoryTheory.ChosenFiniteProducts.FunctorCategory import Mathlib.CategoryTheory.Closed.Cartesian import Mathlib.CategoryTheory.Closed.Functor @@ -1452,6 +1475,7 @@ import Mathlib.CategoryTheory.EssentiallySmall import Mathlib.CategoryTheory.Extensive import Mathlib.CategoryTheory.FiberedCategory.BasedCategory import Mathlib.CategoryTheory.FiberedCategory.Cartesian +import Mathlib.CategoryTheory.FiberedCategory.Cocartesian import Mathlib.CategoryTheory.FiberedCategory.HomLift import Mathlib.CategoryTheory.Filtered.Basic import Mathlib.CategoryTheory.Filtered.Connected @@ -1547,7 +1571,9 @@ import Mathlib.CategoryTheory.Limits.FinallySmall import Mathlib.CategoryTheory.Limits.FintypeCat import Mathlib.CategoryTheory.Limits.Fubini import Mathlib.CategoryTheory.Limits.FullSubcategory -import Mathlib.CategoryTheory.Limits.FunctorCategory +import Mathlib.CategoryTheory.Limits.FunctorCategory.Basic +import Mathlib.CategoryTheory.Limits.FunctorCategory.EpiMono +import Mathlib.CategoryTheory.Limits.FunctorCategory.Finite import Mathlib.CategoryTheory.Limits.FunctorToTypes import Mathlib.CategoryTheory.Limits.HasLimits import Mathlib.CategoryTheory.Limits.IndYoneda @@ -1657,6 +1683,7 @@ import Mathlib.CategoryTheory.Monad.Adjunction import Mathlib.CategoryTheory.Monad.Algebra import Mathlib.CategoryTheory.Monad.Basic import Mathlib.CategoryTheory.Monad.Coequalizer +import Mathlib.CategoryTheory.Monad.Comonadicity import Mathlib.CategoryTheory.Monad.Equalizer import Mathlib.CategoryTheory.Monad.EquivMon import Mathlib.CategoryTheory.Monad.Kleisli @@ -1698,6 +1725,7 @@ import Mathlib.CategoryTheory.Monoidal.OfHasFiniteProducts import Mathlib.CategoryTheory.Monoidal.Opposite import Mathlib.CategoryTheory.Monoidal.Preadditive import Mathlib.CategoryTheory.Monoidal.Rigid.Basic +import Mathlib.CategoryTheory.Monoidal.Rigid.Braided import Mathlib.CategoryTheory.Monoidal.Rigid.FunctorCategory import Mathlib.CategoryTheory.Monoidal.Rigid.OfEquivalence import Mathlib.CategoryTheory.Monoidal.Skeleton @@ -1713,6 +1741,7 @@ import Mathlib.CategoryTheory.MorphismProperty.Concrete import Mathlib.CategoryTheory.MorphismProperty.Factorization import Mathlib.CategoryTheory.MorphismProperty.IsInvertedBy import Mathlib.CategoryTheory.MorphismProperty.Limits +import Mathlib.CategoryTheory.MorphismProperty.Representable import Mathlib.CategoryTheory.NatIso import Mathlib.CategoryTheory.NatTrans import Mathlib.CategoryTheory.Noetherian @@ -1768,6 +1797,7 @@ import Mathlib.CategoryTheory.SingleObj import Mathlib.CategoryTheory.Sites.Abelian import Mathlib.CategoryTheory.Sites.Adjunction import Mathlib.CategoryTheory.Sites.Canonical +import Mathlib.CategoryTheory.Sites.CartesianClosed import Mathlib.CategoryTheory.Sites.Closed import Mathlib.CategoryTheory.Sites.Coherent.Basic import Mathlib.CategoryTheory.Sites.Coherent.CoherentSheaves @@ -1792,7 +1822,6 @@ import Mathlib.CategoryTheory.Sites.CoverPreserving import Mathlib.CategoryTheory.Sites.Coverage import Mathlib.CategoryTheory.Sites.CoversTop import Mathlib.CategoryTheory.Sites.DenseSubsite -import Mathlib.CategoryTheory.Sites.Discrete import Mathlib.CategoryTheory.Sites.EffectiveEpimorphic import Mathlib.CategoryTheory.Sites.EpiMono import Mathlib.CategoryTheory.Sites.EqualizerSheafCondition @@ -1878,6 +1907,7 @@ import Mathlib.Combinatorics.Configuration import Mathlib.Combinatorics.Derangements.Basic import Mathlib.Combinatorics.Derangements.Exponential import Mathlib.Combinatorics.Derangements.Finite +import Mathlib.Combinatorics.Digraph.Basic import Mathlib.Combinatorics.Enumerative.Catalan import Mathlib.Combinatorics.Enumerative.Composition import Mathlib.Combinatorics.Enumerative.DoubleCounting @@ -1908,6 +1938,7 @@ import Mathlib.Combinatorics.SetFamily.FourFunctions import Mathlib.Combinatorics.SetFamily.HarrisKleitman import Mathlib.Combinatorics.SetFamily.Intersecting import Mathlib.Combinatorics.SetFamily.Kleitman +import Mathlib.Combinatorics.SetFamily.KruskalKatona import Mathlib.Combinatorics.SetFamily.LYM import Mathlib.Combinatorics.SetFamily.Shadow import Mathlib.Combinatorics.SetFamily.Shatter @@ -1978,15 +2009,18 @@ import Mathlib.Computability.TMComputable import Mathlib.Computability.TMToPartrec import Mathlib.Computability.TuringMachine import Mathlib.Condensed.Basic +import Mathlib.Condensed.CartesianClosed import Mathlib.Condensed.Discrete.Basic import Mathlib.Condensed.Epi import Mathlib.Condensed.Equivalence import Mathlib.Condensed.Explicit import Mathlib.Condensed.Functors import Mathlib.Condensed.Light.Basic +import Mathlib.Condensed.Light.CartesianClosed import Mathlib.Condensed.Light.Epi import Mathlib.Condensed.Light.Explicit import Mathlib.Condensed.Light.Functors +import Mathlib.Condensed.Light.Limits import Mathlib.Condensed.Light.Module import Mathlib.Condensed.Light.TopCatAdjunction import Mathlib.Condensed.Light.TopComparison @@ -2192,6 +2226,7 @@ import Mathlib.Data.Int.Log import Mathlib.Data.Int.ModEq import Mathlib.Data.Int.NatPrime import Mathlib.Data.Int.Notation +import Mathlib.Data.Int.Order.Basic import Mathlib.Data.Int.Order.Lemmas import Mathlib.Data.Int.Order.Units import Mathlib.Data.Int.Range @@ -2303,6 +2338,7 @@ import Mathlib.Data.Multiset.Sym import Mathlib.Data.NNRat.BigOperators import Mathlib.Data.NNRat.Defs import Mathlib.Data.NNRat.Lemmas +import Mathlib.Data.NNRat.Order import Mathlib.Data.NNReal.Basic import Mathlib.Data.NNReal.Star import Mathlib.Data.Nat.BitIndices @@ -2370,6 +2406,7 @@ import Mathlib.Data.Nat.Prime.Defs import Mathlib.Data.Nat.PrimeFin import Mathlib.Data.Nat.Set import Mathlib.Data.Nat.Size +import Mathlib.Data.Nat.Sqrt import Mathlib.Data.Nat.Squarefree import Mathlib.Data.Nat.SuccPred import Mathlib.Data.Nat.Totient @@ -2475,10 +2512,10 @@ import Mathlib.Data.Set.MemPartition import Mathlib.Data.Set.MulAntidiagonal import Mathlib.Data.Set.NAry import Mathlib.Data.Set.Notation +import Mathlib.Data.Set.Operations import Mathlib.Data.Set.Opposite import Mathlib.Data.Set.Pairwise.Basic import Mathlib.Data.Set.Pairwise.Lattice -import Mathlib.Data.Set.Pointwise.Basic import Mathlib.Data.Set.Pointwise.BigOperators import Mathlib.Data.Set.Pointwise.BoundedMul import Mathlib.Data.Set.Pointwise.Finite @@ -2573,6 +2610,7 @@ import Mathlib.Dynamics.Minimal import Mathlib.Dynamics.Newton import Mathlib.Dynamics.OmegaLimit import Mathlib.Dynamics.PeriodicPts +import Mathlib.Dynamics.TopologicalEntropy.CoverEntropy import Mathlib.Dynamics.TopologicalEntropy.DynamicalEntourage import Mathlib.FieldTheory.AbelRuffini import Mathlib.FieldTheory.AbsoluteGaloisGroup @@ -2588,7 +2626,8 @@ import Mathlib.FieldTheory.Finite.Trace import Mathlib.FieldTheory.Finiteness import Mathlib.FieldTheory.Fixed import Mathlib.FieldTheory.Galois -import Mathlib.FieldTheory.IntermediateField +import Mathlib.FieldTheory.IntermediateField.Algebraic +import Mathlib.FieldTheory.IntermediateField.Basic import Mathlib.FieldTheory.IsAlgClosed.AlgebraicClosure import Mathlib.FieldTheory.IsAlgClosed.Basic import Mathlib.FieldTheory.IsAlgClosed.Classification @@ -2731,7 +2770,6 @@ import Mathlib.GroupTheory.FreeGroup.Basic import Mathlib.GroupTheory.FreeGroup.IsFreeGroup import Mathlib.GroupTheory.FreeGroup.NielsenSchreier import Mathlib.GroupTheory.GroupAction.Basic -import Mathlib.GroupTheory.GroupAction.BigOperators import Mathlib.GroupTheory.GroupAction.Blocks import Mathlib.GroupTheory.GroupAction.CardCommute import Mathlib.GroupTheory.GroupAction.ConjAct @@ -2740,7 +2778,6 @@ import Mathlib.GroupTheory.GroupAction.DomAct.Basic import Mathlib.GroupTheory.GroupAction.Embedding import Mathlib.GroupTheory.GroupAction.FixedPoints import Mathlib.GroupTheory.GroupAction.FixingSubgroup -import Mathlib.GroupTheory.GroupAction.Group import Mathlib.GroupTheory.GroupAction.Hom import Mathlib.GroupTheory.GroupAction.IterateAct import Mathlib.GroupTheory.GroupAction.Period @@ -2807,14 +2844,8 @@ import Mathlib.GroupTheory.Transfer import Mathlib.InformationTheory.Hamming import Mathlib.Init import Mathlib.Init.Algebra.Classes -import Mathlib.Init.Data.Int.Order -import Mathlib.Init.Data.List.Lemmas import Mathlib.Init.Data.Nat.Lemmas -import Mathlib.Init.Data.Quot import Mathlib.Init.Logic -import Mathlib.Init.Order.LinearOrder -import Mathlib.Init.Quot -import Mathlib.Init.Set import Mathlib.Lean.CoreM import Mathlib.Lean.Elab.Tactic.Basic import Mathlib.Lean.Elab.Term @@ -2883,6 +2914,7 @@ import Mathlib.LinearAlgebra.CliffordAlgebra.Fold import Mathlib.LinearAlgebra.CliffordAlgebra.Grading import Mathlib.LinearAlgebra.CliffordAlgebra.Inversion import Mathlib.LinearAlgebra.CliffordAlgebra.Prod +import Mathlib.LinearAlgebra.CliffordAlgebra.SpinGroup import Mathlib.LinearAlgebra.CliffordAlgebra.Star import Mathlib.LinearAlgebra.Coevaluation import Mathlib.LinearAlgebra.Contraction @@ -3220,6 +3252,7 @@ import Mathlib.MeasureTheory.MeasurableSpace.Defs import Mathlib.MeasureTheory.MeasurableSpace.Embedding import Mathlib.MeasureTheory.MeasurableSpace.Instances import Mathlib.MeasureTheory.MeasurableSpace.Invariants +import Mathlib.MeasureTheory.MeasurableSpace.NCard import Mathlib.MeasureTheory.Measure.AEDisjoint import Mathlib.MeasureTheory.Measure.AEMeasurable import Mathlib.MeasureTheory.Measure.AddContent @@ -3283,6 +3316,7 @@ import Mathlib.MeasureTheory.SetAlgebra import Mathlib.MeasureTheory.SetSemiring import Mathlib.ModelTheory.Algebra.Field.Basic import Mathlib.ModelTheory.Algebra.Field.CharP +import Mathlib.ModelTheory.Algebra.Field.IsAlgClosed import Mathlib.ModelTheory.Algebra.Ring.Basic import Mathlib.ModelTheory.Algebra.Ring.FreeCommRing import Mathlib.ModelTheory.Basic @@ -3349,6 +3383,7 @@ import Mathlib.NumberTheory.Harmonic.EulerMascheroni import Mathlib.NumberTheory.Harmonic.GammaDeriv import Mathlib.NumberTheory.Harmonic.Int import Mathlib.NumberTheory.Harmonic.ZetaAsymp +import Mathlib.NumberTheory.JacobiSum.Basic import Mathlib.NumberTheory.KummerDedekind import Mathlib.NumberTheory.LSeries.AbstractFuncEq import Mathlib.NumberTheory.LSeries.Basic @@ -3356,6 +3391,7 @@ import Mathlib.NumberTheory.LSeries.Convergence import Mathlib.NumberTheory.LSeries.Convolution import Mathlib.NumberTheory.LSeries.Deriv import Mathlib.NumberTheory.LSeries.Dirichlet +import Mathlib.NumberTheory.LSeries.DirichletContinuation import Mathlib.NumberTheory.LSeries.HurwitzZeta import Mathlib.NumberTheory.LSeries.HurwitzZetaEven import Mathlib.NumberTheory.LSeries.HurwitzZetaOdd @@ -3363,6 +3399,7 @@ import Mathlib.NumberTheory.LSeries.HurwitzZetaValues import Mathlib.NumberTheory.LSeries.Linearity import Mathlib.NumberTheory.LSeries.MellinEqDirichlet import Mathlib.NumberTheory.LSeries.RiemannZeta +import Mathlib.NumberTheory.LSeries.ZMod import Mathlib.NumberTheory.LegendreSymbol.AddCharacter import Mathlib.NumberTheory.LegendreSymbol.Basic import Mathlib.NumberTheory.LegendreSymbol.GaussEisensteinLemmas @@ -3415,7 +3452,8 @@ import Mathlib.NumberTheory.Padics.Hensel import Mathlib.NumberTheory.Padics.PadicIntegers import Mathlib.NumberTheory.Padics.PadicNorm import Mathlib.NumberTheory.Padics.PadicNumbers -import Mathlib.NumberTheory.Padics.PadicVal +import Mathlib.NumberTheory.Padics.PadicVal.Basic +import Mathlib.NumberTheory.Padics.PadicVal.Defs import Mathlib.NumberTheory.Padics.RingHoms import Mathlib.NumberTheory.Pell import Mathlib.NumberTheory.PellMatiyasevic @@ -3619,6 +3657,7 @@ import Mathlib.Order.SupClosed import Mathlib.Order.SupIndep import Mathlib.Order.SymmDiff import Mathlib.Order.Synonym +import Mathlib.Order.TypeTags import Mathlib.Order.ULift import Mathlib.Order.UpperLower.Basic import Mathlib.Order.UpperLower.Hom @@ -3744,6 +3783,7 @@ import Mathlib.RingTheory.DedekindDomain.PID import Mathlib.RingTheory.DedekindDomain.SInteger import Mathlib.RingTheory.DedekindDomain.SelmerGroup import Mathlib.RingTheory.Derivation.Basic +import Mathlib.RingTheory.Derivation.DifferentialRing import Mathlib.RingTheory.Derivation.Lie import Mathlib.RingTheory.Derivation.ToSquareZero import Mathlib.RingTheory.DiscreteValuationRing.Basic @@ -3765,6 +3805,7 @@ import Mathlib.RingTheory.Flat.CategoryTheory import Mathlib.RingTheory.Flat.EquationalCriterion import Mathlib.RingTheory.Flat.Stability import Mathlib.RingTheory.FractionalIdeal.Basic +import Mathlib.RingTheory.FractionalIdeal.Extended import Mathlib.RingTheory.FractionalIdeal.Norm import Mathlib.RingTheory.FractionalIdeal.Operations import Mathlib.RingTheory.FreeCommRing @@ -3949,15 +3990,18 @@ import Mathlib.RingTheory.TensorProduct.MvPolynomial import Mathlib.RingTheory.Trace.Basic import Mathlib.RingTheory.Trace.Defs import Mathlib.RingTheory.TwoSidedIdeal.Basic +import Mathlib.RingTheory.TwoSidedIdeal.Instances import Mathlib.RingTheory.TwoSidedIdeal.Lattice import Mathlib.RingTheory.UniqueFactorizationDomain import Mathlib.RingTheory.Unramified.Basic import Mathlib.RingTheory.Unramified.Derivations import Mathlib.RingTheory.Unramified.Finite +import Mathlib.RingTheory.Valuation.AlgebraInstances import Mathlib.RingTheory.Valuation.Basic import Mathlib.RingTheory.Valuation.ExtendToLocalization import Mathlib.RingTheory.Valuation.Integers import Mathlib.RingTheory.Valuation.Integral +import Mathlib.RingTheory.Valuation.Minpoly import Mathlib.RingTheory.Valuation.PrimeMultiplicity import Mathlib.RingTheory.Valuation.Quotient import Mathlib.RingTheory.Valuation.RamificationGroup @@ -4142,7 +4186,9 @@ import Mathlib.Tactic.Linarith.Parsing import Mathlib.Tactic.Linarith.Preprocessing import Mathlib.Tactic.Linarith.Verification import Mathlib.Tactic.LinearCombination +import Mathlib.Tactic.LinearCombination' import Mathlib.Tactic.Linter +import Mathlib.Tactic.Linter.AdmitLinter import Mathlib.Tactic.Linter.GlobalAttributeIn import Mathlib.Tactic.Linter.HashCommandLinter import Mathlib.Tactic.Linter.HaveLetLinter @@ -4227,6 +4273,7 @@ import Mathlib.Tactic.Simps.NotationClass import Mathlib.Tactic.SlimCheck import Mathlib.Tactic.SplitIfs import Mathlib.Tactic.Spread +import Mathlib.Tactic.StacksAttribute import Mathlib.Tactic.Subsingleton import Mathlib.Tactic.Substs import Mathlib.Tactic.SuccessIfFailWithMsg @@ -4332,6 +4379,7 @@ import Mathlib.Topology.Algebra.ProperConstSMul import Mathlib.Topology.Algebra.Ring.Basic import Mathlib.Topology.Algebra.Ring.Ideal import Mathlib.Topology.Algebra.Semigroup +import Mathlib.Topology.Algebra.SeparationQuotient import Mathlib.Topology.Algebra.Star import Mathlib.Topology.Algebra.StarSubalgebra import Mathlib.Topology.Algebra.UniformConvergence @@ -4362,12 +4410,14 @@ import Mathlib.Topology.Category.CompHaus.Projective import Mathlib.Topology.Category.CompHausLike.Basic import Mathlib.Topology.Category.CompHausLike.EffectiveEpi import Mathlib.Topology.Category.CompHausLike.Limits +import Mathlib.Topology.Category.CompHausLike.SigmaComparison import Mathlib.Topology.Category.CompactlyGenerated import Mathlib.Topology.Category.Compactum import Mathlib.Topology.Category.FinTopCat import Mathlib.Topology.Category.LightProfinite.AsLimit import Mathlib.Topology.Category.LightProfinite.Basic import Mathlib.Topology.Category.LightProfinite.EffectiveEpi +import Mathlib.Topology.Category.LightProfinite.Extend import Mathlib.Topology.Category.LightProfinite.Limits import Mathlib.Topology.Category.LightProfinite.Sequence import Mathlib.Topology.Category.Locale @@ -4375,6 +4425,7 @@ import Mathlib.Topology.Category.Profinite.AsLimit import Mathlib.Topology.Category.Profinite.Basic import Mathlib.Topology.Category.Profinite.CofilteredLimit import Mathlib.Topology.Category.Profinite.EffectiveEpi +import Mathlib.Topology.Category.Profinite.Extend import Mathlib.Topology.Category.Profinite.Limits import Mathlib.Topology.Category.Profinite.Nobeling import Mathlib.Topology.Category.Profinite.Product @@ -4608,6 +4659,7 @@ import Mathlib.Topology.Sheaves.Init import Mathlib.Topology.Sheaves.Limits import Mathlib.Topology.Sheaves.LocalPredicate import Mathlib.Topology.Sheaves.LocallySurjective +import Mathlib.Topology.Sheaves.MayerVietoris import Mathlib.Topology.Sheaves.Operations import Mathlib.Topology.Sheaves.PUnit import Mathlib.Topology.Sheaves.Presheaf @@ -4655,6 +4707,7 @@ import Mathlib.Topology.VectorBundle.Constructions import Mathlib.Topology.VectorBundle.Hom import Mathlib.Util.AddRelatedDecl import Mathlib.Util.AssertExists +import Mathlib.Util.AssertExistsExt import Mathlib.Util.AssertNoSorry import Mathlib.Util.AtomM import Mathlib.Util.CompileInductive @@ -4674,6 +4727,5 @@ import Mathlib.Util.Superscript import Mathlib.Util.SynthesizeUsing import Mathlib.Util.Tactic import Mathlib.Util.TermBeta -import Mathlib.Util.Time import Mathlib.Util.WhatsNew import Mathlib.Util.WithWeakNamespace diff --git a/Mathlib/Algebra/AddConstMap/Basic.lean b/Mathlib/Algebra/AddConstMap/Basic.lean index cf6f7d5f8a91a..9bed6eb4e7ecd 100644 --- a/Mathlib/Algebra/AddConstMap/Basic.lean +++ b/Mathlib/Algebra/AddConstMap/Basic.lean @@ -21,7 +21,7 @@ such that $\tilde f(x + 1) = \tilde f(x)+1$ for all `x`. In this file we define a structure and a typeclass for bundled maps satisfying `f (x + a) = f x + b`. -We use parameters `a` and `b` instead of `1` to accomodate for two use cases: +We use parameters `a` and `b` instead of `1` to accommodate for two use cases: - maps between circles of different lengths; - self-maps $f\colon S^1\to S^1$ of degree other than one, diff --git a/Mathlib/Algebra/Algebra/Basic.lean b/Mathlib/Algebra/Algebra/Basic.lean index 96aac9668dc57..95c18defa9bdb 100644 --- a/Mathlib/Algebra/Algebra/Basic.lean +++ b/Mathlib/Algebra/Algebra/Basic.lean @@ -336,7 +336,7 @@ theorem NoZeroSMulDivisors.trans (R A M : Type*) [CommRing R] [Ring A] [IsDomain [NoZeroSMulDivisors A M] : NoZeroSMulDivisors R M := by refine ⟨fun {r m} h => ?_⟩ rw [algebra_compatible_smul A r m] at h - cases' smul_eq_zero.1 h with H H + rcases smul_eq_zero.1 h with H | H · have : Function.Injective (algebraMap R A) := NoZeroSMulDivisors.iff_algebraMap_injective.1 inferInstance left diff --git a/Mathlib/Algebra/Algebra/Equiv.lean b/Mathlib/Algebra/Algebra/Equiv.lean index ce14bc0b72a3c..1336dd54b5ede 100644 --- a/Mathlib/Algebra/Algebra/Equiv.lean +++ b/Mathlib/Algebra/Algebra/Equiv.lean @@ -304,9 +304,7 @@ theorem invFun_eq_symm {e : A₁ ≃ₐ[R] A₂} : e.invFun = e.symm := rfl @[simp] -theorem symm_symm (e : A₁ ≃ₐ[R] A₂) : e.symm.symm = e := by - ext - rfl +theorem symm_symm (e : A₁ ≃ₐ[R] A₂) : e.symm.symm = e := rfl theorem symm_bijective : Function.Bijective (symm : (A₁ ≃ₐ[R] A₂) → A₂ ≃ₐ[R] A₁) := Function.bijective_iff_has_inverse.mpr ⟨_, symm_symm, symm_symm⟩ @@ -316,7 +314,7 @@ theorem mk_coe' (e : A₁ ≃ₐ[R] A₂) (f h₁ h₂ h₃ h₄ h₅) : (⟨⟨f, e, h₁, h₂⟩, h₃, h₄, h₅⟩ : A₂ ≃ₐ[R] A₁) = e.symm := symm_bijective.injective <| ext fun _ => rfl -/-- Auxilliary definition to avoid looping in `dsimp` with `AlgEquiv.symm_mk`. -/ +/-- Auxiliary definition to avoid looping in `dsimp` with `AlgEquiv.symm_mk`. -/ protected def symm_mk.aux (f f') (h₁ h₂ h₃ h₄ h₅) := (⟨⟨f, f', h₁, h₂⟩, h₃, h₄, h₅⟩ : A₁ ≃ₐ[R] A₂).symm @@ -405,21 +403,18 @@ theorem arrowCongr_comp (e₁ : A₁ ≃ₐ[R] A₁') (e₂ : A₂ ≃ₐ[R] A exact (e₂.symm_apply_apply _).symm @[simp] -theorem arrowCongr_refl : arrowCongr AlgEquiv.refl AlgEquiv.refl = Equiv.refl (A₁ →ₐ[R] A₂) := by - ext +theorem arrowCongr_refl : arrowCongr AlgEquiv.refl AlgEquiv.refl = Equiv.refl (A₁ →ₐ[R] A₂) := rfl @[simp] theorem arrowCongr_trans (e₁ : A₁ ≃ₐ[R] A₂) (e₁' : A₁' ≃ₐ[R] A₂') (e₂ : A₂ ≃ₐ[R] A₃) (e₂' : A₂' ≃ₐ[R] A₃') : - arrowCongr (e₁.trans e₂) (e₁'.trans e₂') = (arrowCongr e₁ e₁').trans (arrowCongr e₂ e₂') := by - ext + arrowCongr (e₁.trans e₂) (e₁'.trans e₂') = (arrowCongr e₁ e₁').trans (arrowCongr e₂ e₂') := rfl @[simp] theorem arrowCongr_symm (e₁ : A₁ ≃ₐ[R] A₁') (e₂ : A₂ ≃ₐ[R] A₂') : - (arrowCongr e₁ e₂).symm = arrowCongr e₁.symm e₂.symm := by - ext + (arrowCongr e₁ e₂).symm = arrowCongr e₁.symm e₂.symm := rfl /-- If `A₁` is equivalent to `A₂` and `A₁'` is equivalent to `A₂'`, then the type of maps @@ -438,8 +433,7 @@ def equivCongr (e : A₁ ≃ₐ[R] A₂) (e' : A₁' ≃ₐ[R] A₂') : (A₁ simp_rw [trans_apply, apply_symm_apply] @[simp] -theorem equivCongr_refl : equivCongr AlgEquiv.refl AlgEquiv.refl = Equiv.refl (A₁ ≃ₐ[R] A₁') := by - ext +theorem equivCongr_refl : equivCongr AlgEquiv.refl AlgEquiv.refl = Equiv.refl (A₁ ≃ₐ[R] A₁') := rfl @[simp] @@ -466,7 +460,7 @@ def ofAlgHom (f : A₁ →ₐ[R] A₂) (g : A₂ →ₐ[R] A₁) (h₁ : f.comp theorem coe_algHom_ofAlgHom (f : A₁ →ₐ[R] A₂) (g : A₂ →ₐ[R] A₁) (h₁ h₂) : ↑(ofAlgHom f g h₁ h₂) = f := - AlgHom.ext fun _ => rfl + rfl @[simp] theorem ofAlgHom_coe_algHom (f : A₁ ≃ₐ[R] A₂) (g : A₂ →ₐ[R] A₁) (h₁ h₂) : @@ -558,7 +552,7 @@ def ofLinearEquiv : A₁ ≃ₐ[R] A₂ := map_mul' := map_mul commutes' := (AlgHom.ofLinearMap l map_one map_mul : A₁ →ₐ[R] A₂).commutes } -/-- Auxilliary definition to avoid looping in `dsimp` with `AlgEquiv.ofLinearEquiv_symm`. -/ +/-- Auxiliary definition to avoid looping in `dsimp` with `AlgEquiv.ofLinearEquiv_symm`. -/ protected def ofLinearEquiv_symm.aux := (ofLinearEquiv l map_one map_mul).symm @[simp] @@ -571,13 +565,11 @@ theorem ofLinearEquiv_symm : @[simp] theorem ofLinearEquiv_toLinearEquiv (map_mul) (map_one) : - ofLinearEquiv e.toLinearEquiv map_mul map_one = e := by - ext + ofLinearEquiv e.toLinearEquiv map_mul map_one = e := rfl @[simp] -theorem toLinearEquiv_ofLinearEquiv : toLinearEquiv (ofLinearEquiv l map_one map_mul) = l := by - ext +theorem toLinearEquiv_ofLinearEquiv : toLinearEquiv (ofLinearEquiv l map_one map_mul) = l := rfl end OfLinearEquiv @@ -633,9 +625,7 @@ def autCongr (ϕ : A₁ ≃ₐ[R] A₂) : (A₁ ≃ₐ[R] A₁) ≃* A₂ ≃ₐ simp only [mul_apply, trans_apply, symm_apply_apply] @[simp] -theorem autCongr_refl : autCongr AlgEquiv.refl = MulEquiv.refl (A₁ ≃ₐ[R] A₁) := by - ext - rfl +theorem autCongr_refl : autCongr AlgEquiv.refl = MulEquiv.refl (A₁ ≃ₐ[R] A₁) := rfl @[simp] theorem autCongr_symm (ϕ : A₁ ≃ₐ[R] A₂) : (autCongr ϕ).symm = autCongr ϕ.symm := diff --git a/Mathlib/Algebra/Algebra/Hom.lean b/Mathlib/Algebra/Algebra/Hom.lean index e82539f2a9c02..d15f9fc46298b 100644 --- a/Mathlib/Algebra/Algebra/Hom.lean +++ b/Mathlib/Algebra/Algebra/Hom.lean @@ -39,7 +39,7 @@ infixr:25 " →ₐ " => AlgHom _ notation:25 A " →ₐ[" R "] " B => AlgHom R A B /-- `AlgHomClass F R A B` asserts `F` is a type of bundled algebra homomorphisms -from `A` to `B`. -/ +from `A` to `B`. -/ class AlgHomClass (F : Type*) (R A B : outParam Type*) [CommSemiring R] [Semiring A] [Semiring B] [Algebra R A] [Algebra R B] [FunLike F A B] extends RingHomClass F A B : Prop where @@ -192,7 +192,7 @@ theorem ext {φ₁ φ₂ : A →ₐ[R] B} (H : ∀ x, φ₁ x = φ₂ x) : φ₁ @[simp] theorem mk_coe {f : A →ₐ[R] B} (h₁ h₂ h₃ h₄ h₅) : (⟨⟨⟨⟨f, h₁⟩, h₂⟩, h₃, h₄⟩, h₅⟩ : A →ₐ[R] B) = f := - ext fun _ => rfl + rfl @[simp] theorem commutes (r : R) : φ (algebraMap R A r) = algebraMap R B r := @@ -285,15 +285,15 @@ theorem comp_toRingHom (φ₁ : B →ₐ[R] C) (φ₂ : A →ₐ[R] B) : @[simp] theorem comp_id : φ.comp (AlgHom.id R A) = φ := - ext fun _x => rfl + rfl @[simp] theorem id_comp : (AlgHom.id R B).comp φ = φ := - ext fun _x => rfl + rfl theorem comp_assoc (φ₁ : C →ₐ[R] D) (φ₂ : B →ₐ[R] C) (φ₃ : A →ₐ[R] B) : (φ₁.comp φ₂).comp φ₃ = φ₁.comp (φ₂.comp φ₃) := - ext fun _x => rfl + rfl /-- R-Alg ⥤ R-Mod -/ def toLinearMap : A →ₗ[R] B where @@ -316,7 +316,7 @@ theorem comp_toLinearMap (f : A →ₐ[R] B) (g : B →ₐ[R] C) : @[simp] theorem toLinearMap_id : toLinearMap (AlgHom.id R A) = LinearMap.id := - LinearMap.ext fun _ => rfl + rfl /-- Promote a `LinearMap` to an `AlgHom` by supplying proofs about the behavior on `1` and `*`. -/ @[simps] @@ -330,20 +330,18 @@ def ofLinearMap (f : A →ₗ[R] B) (map_one : f 1 = 1) (map_mul : ∀ x y, f (x @[simp] theorem ofLinearMap_toLinearMap (map_one) (map_mul) : - ofLinearMap φ.toLinearMap map_one map_mul = φ := by - ext + ofLinearMap φ.toLinearMap map_one map_mul = φ := rfl @[simp] theorem toLinearMap_ofLinearMap (f : A →ₗ[R] B) (map_one) (map_mul) : - toLinearMap (ofLinearMap f map_one map_mul) = f := by - ext + toLinearMap (ofLinearMap f map_one map_mul) = f := rfl @[simp] theorem ofLinearMap_id (map_one) (map_mul) : ofLinearMap LinearMap.id map_one map_mul = AlgHom.id R A := - ext fun _ => rfl + rfl theorem map_smul_of_tower {R'} [SMul R' A] [SMul R' B] [LinearMap.CompatibleSMul A B R' R] (r : R') (x : A) : φ (r • x) = r • φ x := @@ -358,8 +356,8 @@ instance End : Monoid (A →ₐ[R] A) where mul := comp mul_assoc ϕ ψ χ := rfl one := AlgHom.id R A - one_mul ϕ := ext fun x => rfl - mul_one ϕ := ext fun x => rfl + one_mul ϕ := rfl + mul_one ϕ := rfl @[simp] theorem one_apply (x : A) : (1 : A →ₐ[R] A) x = x := @@ -458,11 +456,11 @@ theorem ext_id (f g : R →ₐ[R] A) : f = g := Subsingleton.elim _ _ section MulDistribMulAction instance : MulDistribMulAction (A →ₐ[R] A) Aˣ where - smul := fun f => Units.map f - one_smul := fun x => by ext; rfl - mul_smul := fun x y z => by ext; rfl - smul_mul := fun x y z => by ext; exact map_mul _ _ _ - smul_one := fun x => by ext; exact map_one _ + smul f := Units.map f + one_smul _ := by ext; rfl + mul_smul _ _ _ := by ext; rfl + smul_mul _ _ _ := by ext; exact map_mul _ _ _ + smul_one _ := by ext; exact map_one _ @[simp] theorem smul_units_def (f : A →ₐ[R] A) (x : Aˣ) : diff --git a/Mathlib/Algebra/Algebra/NonUnitalHom.lean b/Mathlib/Algebra/Algebra/NonUnitalHom.lean index 5df753173fa61..34a5518dc4de3 100644 --- a/Mathlib/Algebra/Algebra/NonUnitalHom.lean +++ b/Mathlib/Algebra/Algebra/NonUnitalHom.lean @@ -64,7 +64,7 @@ notation:25 A " →ₙₐ[" R "] " B => NonUnitalAlgHom (MonoidHom.id R) A B attribute [nolint docBlame] NonUnitalAlgHom.toMulHom /-- `NonUnitalAlgSemiHomClass F φ A B` asserts `F` is a type of bundled algebra homomorphisms -from `A` to `B` which are equivariant with respect to `φ`. -/ +from `A` to `B` which are equivariant with respect to `φ`. -/ class NonUnitalAlgSemiHomClass (F : Type*) {R S : outParam Type*} [Monoid R] [Monoid S] (φ : outParam (R →* S)) (A B : outParam Type*) [NonUnitalNonAssocSemiring A] [NonUnitalNonAssocSemiring B] @@ -383,7 +383,7 @@ variable [DistribMulAction R C] @[simps] def prod (f : A →ₙₐ[R] B) (g : A →ₙₐ[R] C) : A →ₙₐ[R] B × C where toFun := Pi.prod f g - map_zero' := by simp only [Pi.prod, Prod.zero_eq_mk, map_zero] + map_zero' := by simp only [Pi.prod, Prod.mk_zero_zero, map_zero] map_add' x y := by simp only [Pi.prod, Prod.mk_add_mk, map_add] map_mul' x y := by simp only [Pi.prod, Prod.mk_mul_mk, map_mul] map_smul' c x := by simp only [Pi.prod, map_smul, MonoidHom.id_apply, id_eq, Prod.smul_mk] @@ -483,7 +483,7 @@ variable (R : Type*) {S A B : Type*} [Monoid R] [Monoid S] [IsScalarTower R S A] [IsScalarTower R S B] /-- If a monoid `R` acts on another monoid `S`, then a non-unital algebra homomorphism -over `S` can be viewed as a non-unital algebra homomorphism over `R`. -/ +over `S` can be viewed as a non-unital algebra homomorphism over `R`. -/ def restrictScalars (f : A →ₙₐ[S] B) : A →ₙₐ[R] B := { (f : A →ₙ+* B) with map_smul' := fun r x ↦ by have := map_smul f (r • 1) x; simpa } diff --git a/Mathlib/Algebra/Algebra/NonUnitalSubalgebra.lean b/Mathlib/Algebra/Algebra/NonUnitalSubalgebra.lean index 1bc3dc1438938..ce534b664d2fa 100644 --- a/Mathlib/Algebra/Algebra/NonUnitalSubalgebra.lean +++ b/Mathlib/Algebra/Algebra/NonUnitalSubalgebra.lean @@ -458,7 +458,7 @@ def codRestrict (f : F) (S : NonUnitalSubalgebra R B) (hf : ∀ x, f x ∈ S) : @[simp] theorem subtype_comp_codRestrict (f : F) (S : NonUnitalSubalgebra R B) (hf : ∀ x : A, f x ∈ S) : (NonUnitalSubalgebraClass.subtype S).comp (NonUnitalAlgHom.codRestrict f S hf) = f := - NonUnitalAlgHom.ext fun _ => rfl + rfl @[simp] theorem coe_codRestrict (f : F) (S : NonUnitalSubalgebra R B) (hf : ∀ x, f x ∈ S) (x : A) : @@ -906,7 +906,7 @@ theorem inclusion_injective {S T : NonUnitalSubalgebra R A} (h : S ≤ T) : @[simp] theorem inclusion_self {S : NonUnitalSubalgebra R A} : inclusion (le_refl S) = NonUnitalAlgHom.id R S := - NonUnitalAlgHom.ext fun _ => Subtype.ext rfl + rfl @[simp] theorem inclusion_mk {S T : NonUnitalSubalgebra R A} (h : S ≤ T) (x : A) (hx : x ∈ S) : diff --git a/Mathlib/Algebra/Algebra/Operations.lean b/Mathlib/Algebra/Algebra/Operations.lean index d0bb76295683d..7b9e15a2ac242 100644 --- a/Mathlib/Algebra/Algebra/Operations.lean +++ b/Mathlib/Algebra/Algebra/Operations.lean @@ -359,12 +359,12 @@ theorem mul_smul_mul_eq_smul_mul_smul (x y : R) : (x * y) • (M * N) = (x • M · rintro ⟨_, hx, rfl⟩ rw [DistribMulAction.toLinearMap_apply] refine Submodule.mul_induction_on hx (fun m hm n hn ↦ ?_) (fun _ _ hn hm ↦ ?_) - · rw [← smul_mul_smul x y m n] + · rw [mul_smul_mul_comm] exact mul_mem_mul (smul_mem_pointwise_smul m x M hm) (smul_mem_pointwise_smul n y N hn) · rw [smul_add] exact Submodule.add_mem _ hn hm · rintro _ ⟨m, hm, rfl⟩ _ ⟨n, hn, rfl⟩ - erw [smul_mul_smul x y m n] + erw [smul_mul_smul_comm x m y n] exact smul_mem_pointwise_smul _ _ _ (mul_mem_mul hm hn) /-- Sub-R-modules of an R-algebra form an idempotent semiring. -/ diff --git a/Mathlib/Algebra/Algebra/Spectrum.lean b/Mathlib/Algebra/Algebra/Spectrum.lean index 2919c52895656..2b7e28f8e2c29 100644 --- a/Mathlib/Algebra/Algebra/Spectrum.lean +++ b/Mathlib/Algebra/Algebra/Spectrum.lean @@ -53,7 +53,7 @@ local notation "↑ₐ" => algebraMap R A -- definition and basic properties /-- Given a commutative ring `R` and an `R`-algebra `A`, the *resolvent set* of `a : A` is the `Set R` consisting of those `r : R` for which `r•1 - a` is a unit of the -algebra `A`. -/ +algebra `A`. -/ def resolventSet (a : A) : Set R := {r : R | IsUnit (↑ₐ r - a)} @@ -61,7 +61,7 @@ def resolventSet (a : A) : Set R := is the `Set R` consisting of those `r : R` for which `r•1 - a` is not a unit of the algebra `A`. -The spectrum is simply the complement of the resolvent set. -/ +The spectrum is simply the complement of the resolvent set. -/ def spectrum (a : A) : Set R := (resolventSet R a)ᶜ @@ -113,6 +113,10 @@ theorem zero_not_mem_iff {a : A} : (0 : R) ∉ σ a ↔ IsUnit a := by alias ⟨isUnit_of_zero_not_mem, zero_not_mem⟩ := spectrum.zero_not_mem_iff +@[simp] +lemma _root_.Units.zero_not_mem_spectrum (a : Aˣ) : 0 ∉ spectrum R (a : A) := + spectrum.zero_not_mem R a.isUnit + lemma subset_singleton_zero_compl {a : A} (ha : IsUnit a) : spectrum R a ⊆ {0}ᶜ := Set.subset_compl_singleton_iff.mpr <| spectrum.zero_not_mem R ha diff --git a/Mathlib/Algebra/Algebra/Subalgebra/Basic.lean b/Mathlib/Algebra/Algebra/Subalgebra/Basic.lean index a76d7cd9d500a..854c9922cd13d 100644 --- a/Mathlib/Algebra/Algebra/Subalgebra/Basic.lean +++ b/Mathlib/Algebra/Algebra/Subalgebra/Basic.lean @@ -802,7 +802,7 @@ variable (S : Subalgebra R A) This is the algebra version of `Submodule.topEquiv`. -/ @[simps!] def topEquiv : (⊤ : Subalgebra R A) ≃ₐ[R] A := - AlgEquiv.ofAlgHom (Subalgebra.val ⊤) toTop rfl <| AlgHom.ext fun _ => Subtype.ext rfl + AlgEquiv.ofAlgHom (Subalgebra.val ⊤) toTop rfl rfl instance subsingleton_of_subsingleton [Subsingleton A] : Subsingleton (Subalgebra R A) := ⟨fun B C => ext fun x => by simp only [Subsingleton.elim x 0, zero_mem B, zero_mem C]⟩ @@ -1127,10 +1127,10 @@ section Equalizer namespace AlgHom variable {R A B : Type*} [CommSemiring R] [Semiring A] [Algebra R A] [Semiring B] [Algebra R B] -variable {F : Type*} [FunLike F A B] [AlgHomClass F R A B] +variable {F : Type*} /-- The equalizer of two R-algebra homomorphisms -/ -def equalizer (ϕ ψ : F) : Subalgebra R A where +def equalizer (ϕ ψ : F) [FunLike F A B] [AlgHomClass F R A B] : Subalgebra R A where carrier := { a | ϕ a = ψ a } zero_mem' := by simp only [Set.mem_setOf_eq, map_zero] one_mem' := by simp only [Set.mem_setOf_eq, map_one] @@ -1141,6 +1141,8 @@ def equalizer (ϕ ψ : F) : Subalgebra R A where algebraMap_mem' x := by simp only [Set.mem_setOf_eq, AlgHomClass.commutes] +variable [FunLike F A B] [AlgHomClass F R A B] + @[simp] theorem mem_equalizer (φ ψ : F) (x : A) : x ∈ equalizer φ ψ ↔ φ x = ψ x := Iff.rfl diff --git a/Mathlib/Algebra/Algebra/Subalgebra/IsSimpleOrder.lean b/Mathlib/Algebra/Algebra/Subalgebra/IsSimpleOrder.lean new file mode 100644 index 0000000000000..468781008d3b8 --- /dev/null +++ b/Mathlib/Algebra/Algebra/Subalgebra/IsSimpleOrder.lean @@ -0,0 +1,33 @@ +/- +Copyright (c) 2020 Kenny Lau. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Kenny Lau +-/ +import Mathlib.LinearAlgebra.FiniteDimensional.Defs +import Mathlib.LinearAlgebra.Dimension.FreeAndStrongRankCondition +import Mathlib.LinearAlgebra.FreeModule.StrongRankCondition + +/-! +If `A` is a domain, and a finite-dimensional algebra over a field `F`, with prime dimension, +then there are no non-trivial `F`-subalgebras. +-/ + +open FiniteDimensional 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) := + { toNontrivial := + ⟨⟨⊥, ⊤, fun he => + Nat.not_prime_one ((Subalgebra.bot_eq_top_iff_finrank_eq_one.1 he).subst hp)⟩⟩ + eq_bot_or_eq_top := fun K => by + haveI : FiniteDimensional _ _ := .of_finrank_pos hp.pos + letI := divisionRingOfFiniteDimensional F K + refine (hp.eq_one_or_self_of_dvd _ ⟨_, (finrank_mul_finrank F K A).symm⟩).imp ?_ fun h => ?_ + · exact fun h' => Subalgebra.eq_bot_of_finrank_one h' + · exact + Algebra.toSubmodule_eq_top.1 (eq_top_of_finrank_eq <| K.finrank_toSubmodule.trans h) } +-- TODO: `IntermediateField` version + +@[deprecated (since := "2024-08-11")] +alias FiniteDimensional.Subalgebra.is_simple_order_of_finrank_prime := + Subalgebra.isSimpleOrder_of_finrank_prime diff --git a/Mathlib/Algebra/Algebra/Subalgebra/Operations.lean b/Mathlib/Algebra/Algebra/Subalgebra/Operations.lean index 8d05a87504817..b28a1c2c1dc76 100644 --- a/Mathlib/Algebra/Algebra/Subalgebra/Operations.lean +++ b/Mathlib/Algebra/Algebra/Subalgebra/Operations.lean @@ -67,7 +67,7 @@ theorem mem_of_finset_sum_eq_one_of_pow_smul_mem exact ⟨⟨_, hn i⟩, rfl⟩ theorem mem_of_span_eq_top_of_smul_pow_mem - (s : Set S) (l : s →₀ S) (hs : Finsupp.total s S S (↑) l = 1) + (s : Set S) (l : s →₀ S) (hs : Finsupp.linearCombination S ((↑) : s → S) l = 1) (hs' : s ⊆ S') (hl : ∀ i, l i ∈ S') (x : S) (H : ∀ r : s, ∃ n : ℕ, (r : S) ^ n • x ∈ S') : x ∈ S' := mem_of_finset_sum_eq_one_of_pow_smul_mem S' l.support (↑) l hs (fun x => hs' x.2) hl x H diff --git a/Mathlib/Algebra/Algebra/Subalgebra/Pointwise.lean b/Mathlib/Algebra/Algebra/Subalgebra/Pointwise.lean index 2bdc15557b29d..6328cb01ad700 100644 --- a/Mathlib/Algebra/Algebra/Subalgebra/Pointwise.lean +++ b/Mathlib/Algebra/Algebra/Subalgebra/Pointwise.lean @@ -49,7 +49,7 @@ theorem mul_toSubmodule {R : Type*} {A : Type*} [CommSemiring R] [CommSemiring A refine Algebra.adjoin_induction hx (fun x hx => ?_) (fun r => ?_) (fun _ _ => Submodule.add_mem _) fun x y hx hy => ?_ - · cases' hx with hxS hxT + · rcases hx with hxS | hxT · rw [← mul_one x] exact Submodule.mul_mem_mul hxS (show (1 : A) ∈ T from one_mem T) · rw [← one_mul x] diff --git a/Mathlib/Algebra/Algebra/Subalgebra/Unitization.lean b/Mathlib/Algebra/Algebra/Subalgebra/Unitization.lean index f8a6bb3e6e61e..2cacd22757a8c 100644 --- a/Mathlib/Algebra/Algebra/Subalgebra/Unitization.lean +++ b/Mathlib/Algebra/Algebra/Subalgebra/Unitization.lean @@ -148,14 +148,15 @@ theorem _root_.AlgHomClass.unitization_injective' {F R S A : Type*} [CommRing R] [FunLike F (Unitization R s) A] [AlgHomClass F R (Unitization R s) A] (f : F) (hf : ∀ x : s, f x = x) : Function.Injective f := by refine (injective_iff_map_eq_zero f).mpr fun x hx => ?_ - induction' x with r a - simp_rw [map_add, hf, ← Unitization.algebraMap_eq_inl, AlgHomClass.commutes] at hx - rw [add_eq_zero_iff_eq_neg] at hx ⊢ - by_cases hr : r = 0 - · ext - · simp [hr] - · simpa [hr] using hx - · exact (h r hr <| hx ▸ (neg_mem a.property)).elim + induction x with + | inl_add_inr r a => + simp_rw [map_add, hf, ← Unitization.algebraMap_eq_inl, AlgHomClass.commutes] at hx + rw [add_eq_zero_iff_eq_neg] at hx ⊢ + by_cases hr : r = 0 + · ext + · simp [hr] + · simpa [hr] using hx + · exact (h r hr <| hx ▸ (neg_mem a.property)).elim /-- This is a generic version which allows us to prove both `NonUnitalSubalgebra.unitization_injective` and `NonUnitalStarSubalgebra.unitization_injective`. -/ diff --git a/Mathlib/Algebra/Algebra/Unitization.lean b/Mathlib/Algebra/Algebra/Unitization.lean index 886c96c934125..410c45a19b938 100644 --- a/Mathlib/Algebra/Algebra/Unitization.lean +++ b/Mathlib/Algebra/Algebra/Unitization.lean @@ -561,14 +561,16 @@ variable (S R A : Type*) [CommSemiring S] [CommSemiring R] [NonUnitalSemiring A] instance instAlgebra : Algebra S (Unitization R A) := { (Unitization.inlRingHom R A).comp (algebraMap S R) with commutes' := fun s x => by - induction' x with r a - show inl (algebraMap S R s) * _ = _ * inl (algebraMap S R s) - rw [mul_add, add_mul, inl_mul_inl, inl_mul_inl, inl_mul_inr, inr_mul_inl, mul_comm] + induction x with + | inl_add_inr => + show inl (algebraMap S R s) * _ = _ * inl (algebraMap S R s) + rw [mul_add, add_mul, inl_mul_inl, inl_mul_inl, inl_mul_inr, inr_mul_inl, mul_comm] smul_def' := fun s x => by - induction' x with r a - show _ = inl (algebraMap S R s) * _ - rw [mul_add, smul_add,Algebra.algebraMap_eq_smul_one, inl_mul_inl, inl_mul_inr, smul_one_mul, - inl_smul, inr_smul, smul_one_smul] } + induction x with + | inl_add_inr => + show _ = inl (algebraMap S R s) * _ + rw [mul_add, smul_add,Algebra.algebraMap_eq_smul_one, inl_mul_inl, inl_mul_inr, + smul_one_mul, inl_smul, inr_smul, smul_one_smul] } theorem algebraMap_eq_inl_comp : ⇑(algebraMap S (Unitization R A)) = inl ∘ algebraMap S R := rfl @@ -668,20 +670,24 @@ def _root_.NonUnitalAlgHom.toAlgHom (φ : A →ₙₐ[R] C) : Unitization R A toFun := fun x => algebraMap R C x.fst + φ x.snd map_one' := by simp only [fst_one, map_one, snd_one, φ.map_zero, add_zero] map_mul' := fun x y => by - induction' x with x_r x_a - induction' y with y_r y_a - simp only [fst_mul, fst_add, fst_inl, fst_inr, snd_mul, snd_add, snd_inl, snd_inr, add_zero, - map_mul, zero_add, map_add, map_smul φ] - rw [add_mul, mul_add, mul_add] - rw [← Algebra.commutes _ (φ x_a)] - simp only [Algebra.algebraMap_eq_smul_one, smul_one_mul, add_assoc] + induction x with + | inl_add_inr x_r x_a => + induction y with + | inl_add_inr => + simp only [fst_mul, fst_add, fst_inl, fst_inr, snd_mul, snd_add, snd_inl, snd_inr, add_zero, + map_mul, zero_add, map_add, map_smul φ] + rw [add_mul, mul_add, mul_add] + rw [← Algebra.commutes _ (φ x_a)] + simp only [Algebra.algebraMap_eq_smul_one, smul_one_mul, add_assoc] map_zero' := by simp only [fst_zero, map_zero, snd_zero, φ.map_zero, add_zero] map_add' := fun x y => by - induction' x with x_r x_a - induction' y with y_r y_a - simp only [fst_add, fst_inl, fst_inr, add_zero, map_add, snd_add, snd_inl, snd_inr, - zero_add, φ.map_add] - rw [add_add_add_comm] + induction x with + | inl_add_inr => + induction y with + | inl_add_inr => + simp only [fst_add, fst_inl, fst_inr, add_zero, map_add, snd_add, snd_inl, snd_inr, + zero_add, φ.map_add] + rw [add_add_add_comm] commutes' := fun r => by simp only [algebraMap_eq_inl, fst_inl, snd_inl, φ.map_zero, add_zero] diff --git a/Mathlib/Algebra/Associated/Basic.lean b/Mathlib/Algebra/Associated/Basic.lean index 9ff65fedb0e76..70a806de2380a 100644 --- a/Mathlib/Algebra/Associated/Basic.lean +++ b/Mathlib/Algebra/Associated/Basic.lean @@ -79,7 +79,7 @@ theorem dvd_of_dvd_pow {a : α} {n : ℕ} (h : p ∣ a ^ n) : p ∣ a := by contradiction | succ n ih => rw [pow_succ'] at h - cases' dvd_or_dvd hp h with dvd_a dvd_pow + rcases dvd_or_dvd hp h with dvd_a | dvd_pow · assumption · exact ih dvd_pow @@ -146,7 +146,7 @@ theorem Prime.pow_dvd_of_dvd_mul_right [CancelCommMonoidWithZero α] {p a b : α theorem Prime.dvd_of_pow_dvd_pow_mul_pow_of_square_not_dvd [CancelCommMonoidWithZero α] {p a b : α} {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`. - cases' hp.dvd_or_dvd ((dvd_pow_self p (Nat.succ_ne_zero n)).trans hpow) with H hbdiv + rcases hp.dvd_or_dvd ((dvd_pow_self p (Nat.succ_ne_zero n)).trans hpow) with H | hbdiv · exact hp.dvd_of_dvd_pow H obtain ⟨x, rfl⟩ := hp.dvd_of_dvd_pow hbdiv obtain ⟨y, hy⟩ := hpow @@ -165,13 +165,13 @@ theorem prime_pow_succ_dvd_mul {α : Type*} [CancelCommMonoidWithZero α] {p x y {i : ℕ} (hxy : p ^ (i + 1) ∣ x * y) : p ^ (i + 1) ∣ x ∨ p ∣ y := by rw [or_iff_not_imp_right] intro hy - induction' i with i ih generalizing x - · rw [pow_one] at hxy ⊢ - exact (h.dvd_or_dvd hxy).resolve_right hy - rw [pow_succ'] at hxy ⊢ - obtain ⟨x', rfl⟩ := (h.dvd_or_dvd (dvd_of_mul_right_dvd hxy)).resolve_right hy - rw [mul_assoc] at hxy - exact mul_dvd_mul_left p (ih ((mul_dvd_mul_iff_left h.ne_zero).mp hxy)) + induction i generalizing x with + | zero => rw [pow_one] at hxy ⊢; exact (h.dvd_or_dvd hxy).resolve_right hy + | succ i ih => + rw [pow_succ'] at hxy ⊢ + obtain ⟨x', rfl⟩ := (h.dvd_or_dvd (dvd_of_mul_right_dvd hxy)).resolve_right hy + rw [mul_assoc] at hxy + exact mul_dvd_mul_left p (ih ((mul_dvd_mul_iff_left h.ne_zero).mp hxy)) /-- `Irreducible p` states that `p` is non-unit and only factors into units. @@ -587,7 +587,7 @@ lemma prime_pow_iff [CancelCommMonoidWithZero α] {p : α} {n : ℕ} : Prime (p ^ n) ↔ Prime p ∧ n = 1 := by refine ⟨fun hp ↦ ?_, fun ⟨hp, hn⟩ ↦ by simpa [hn]⟩ suffices n = 1 by aesop - cases' n with n + rcases n with - | n · simp at hp · rw [Nat.succ.injEq] rw [pow_succ', prime_mul_iff] at hp @@ -1106,7 +1106,7 @@ section CancelCommMonoidWithZero theorem isUnit_of_associated_mul [CancelCommMonoidWithZero α] {p b : α} (h : Associated (p * b) p) (hp : p ≠ 0) : IsUnit b := by - cases' h with a ha + obtain ⟨a, ha⟩ := h refine isUnit_of_mul_eq_one b a ((mul_right_inj' hp).mp ?_) rwa [← mul_assoc, mul_one] diff --git a/Mathlib/Algebra/BigOperators/Associated.lean b/Mathlib/Algebra/BigOperators/Associated.lean index fd06fc15dc080..b8b8178cc0aa7 100644 --- a/Mathlib/Algebra/BigOperators/Associated.lean +++ b/Mathlib/Algebra/BigOperators/Associated.lean @@ -68,7 +68,7 @@ theorem exists_associated_mem_of_dvd_prod [CancelCommMonoidWithZero α] {p : α} {s : Multiset α} : (∀ r ∈ s, Prime r) → p ∣ s.prod → ∃ q ∈ s, p ~ᵤ q := Multiset.induction_on s (by simp [mt isUnit_iff_dvd_one.2 hp.not_unit]) fun a s ih hs hps => by rw [Multiset.prod_cons] at hps - cases' hp.dvd_or_dvd hps with h h + rcases hp.dvd_or_dvd hps with h | h · have hap := hs a (Multiset.mem_cons.2 (Or.inl rfl)) exact ⟨a, Multiset.mem_cons_self a _, hp.associated_of_dvd hap h⟩ · rcases ih (fun r hr => hs _ (Multiset.mem_cons.2 (Or.inr hr))) h with ⟨q, hq₁, hq₂⟩ @@ -77,9 +77,10 @@ theorem exists_associated_mem_of_dvd_prod [CancelCommMonoidWithZero α] {p : α} theorem Multiset.prod_primes_dvd [CancelCommMonoidWithZero α] [∀ a : α, DecidablePred (Associated a)] {s : Multiset α} (n : α) (h : ∀ a ∈ s, Prime a) (div : ∀ a ∈ s, a ∣ n) (uniq : ∀ a, s.countP (Associated a) ≤ 1) : s.prod ∣ n := by - induction' s using Multiset.induction_on with a s induct n primes divs generalizing n - · simp only [Multiset.prod_zero, one_dvd] - · rw [Multiset.prod_cons] + induction s using Multiset.induction_on generalizing n with + | empty => simp only [Multiset.prod_zero, one_dvd] + | cons a s induct => + rw [Multiset.prod_cons] obtain ⟨k, rfl⟩ : a ∣ n := div a (Multiset.mem_cons_self a s) apply mul_dvd_mul_left a refine induct _ (fun a ha => h a (Multiset.mem_cons_of_mem ha)) (fun b b_in_s => ?_) diff --git a/Mathlib/Algebra/BigOperators/Fin.lean b/Mathlib/Algebra/BigOperators/Fin.lean index 0e4e828ea9f8a..f336a553c7f57 100644 --- a/Mathlib/Algebra/BigOperators/Fin.lean +++ b/Mathlib/Algebra/BigOperators/Fin.lean @@ -86,11 +86,16 @@ theorem prod_univ_get' [CommMonoid β] (l : List α) (f : α → β) : ∏ i : Fin l.length, f l[i.1] = (l.map f).prod := by simp [Finset.prod_eq_multiset_prod] -@[to_additive] +@[to_additive (attr := simp)] theorem prod_cons [CommMonoid β] {n : ℕ} (x : β) (f : Fin n → β) : (∏ i : Fin n.succ, (cons x f : Fin n.succ → β) i) = x * ∏ i : Fin n, f i := by simp_rw [prod_univ_succ, cons_zero, cons_succ] +@[to_additive (attr := simp)] +theorem prod_snoc [CommMonoid β] {n : ℕ} (x : β) (f : Fin n → β) : + (∏ i : Fin n.succ, (snoc f x : Fin n.succ → β) i) = (∏ i : Fin n, f i) * x := by + simp [prod_univ_castSucc] + @[to_additive sum_univ_one] theorem prod_univ_one [CommMonoid β] (f : Fin 1 → β) : ∏ i, f i = f 0 := by simp @@ -210,7 +215,7 @@ theorem partialProd_left_inv {G : Type*} [Group G] (f : Fin (n + 1) → G) : @[to_additive] theorem partialProd_right_inv {G : Type*} [Group G] (f : Fin n → G) (i : Fin n) : (partialProd f (Fin.castSucc i))⁻¹ * partialProd f i.succ = f i := by - cases' i with i hn + obtain ⟨i, hn⟩ := i induction i with | zero => simp [-Fin.succ_mk, partialProd_succ] | succ i hi => @@ -274,9 +279,9 @@ def finFunctionFinEquiv {m n : ℕ} : (Fin n → Fin m) ≃ Fin (m ^ n) := (Fin.is_le _)).trans_eq ?_ rw [← one_add_mul (_ : ℕ), add_comm, pow_succ']⟩) (fun a b => ⟨a / m ^ (b : ℕ) % m, by - cases' n with n + rcases n with - | n · exact b.elim0 - cases' m with m + rcases m with - | m · rw [zero_pow n.succ_ne_zero] at a exact a.elim0 · exact Nat.mod_lt _ m.succ_pos⟩) @@ -308,8 +313,9 @@ theorem finFunctionFinEquiv_single {m n : ℕ} [NeZero m] (i : Fin n) (j : Fin m def finPiFinEquiv {m : ℕ} {n : Fin m → ℕ} : (∀ i : Fin m, Fin (n i)) ≃ Fin (∏ i : Fin m, n i) := Equiv.ofRightInverseOfCardLE (le_of_eq <| by simp_rw [Fintype.card_pi, Fintype.card_fin]) (fun f => ⟨∑ i, f i * ∏ j, n (Fin.castLE i.is_lt.le j), by - induction' m with m ih - · simp + induction m with + | zero => simp + | succ m ih => rw [Fin.prod_univ_castSucc, Fin.sum_univ_castSucc] suffices ∀ (n : Fin m → ℕ) (nn : ℕ) (f : ∀ i : Fin m, Fin (n i)) (fn : Fin nn), @@ -328,7 +334,7 @@ def finPiFinEquiv {m : ℕ} {n : Fin m → ℕ} : (∀ i : Fin m, Fin (n i)) ≃ (fun a b => ⟨(a / ∏ j : Fin b, n (Fin.castLE b.is_lt.le j)) % n b, by cases m · exact b.elim0 - cases' h : n b with nb + rcases h : n b with nb | nb · rw [prod_eq_zero (Finset.mem_univ _) h] at a exact isEmptyElim a exact Nat.mod_lt _ nb.succ_pos⟩) diff --git a/Mathlib/Algebra/BigOperators/Finprod.lean b/Mathlib/Algebra/BigOperators/Finprod.lean index 9a2dc40b1b77f..751e627de3492 100644 --- a/Mathlib/Algebra/BigOperators/Finprod.lean +++ b/Mathlib/Algebra/BigOperators/Finprod.lean @@ -750,7 +750,7 @@ theorem finprod_mem_insert_one (h : f a = 1) : ∏ᶠ i ∈ insert a s, f i = finprod_mem_insert_of_eq_one_if_not_mem fun _ => h /-- If the multiplicative support of `f` is finite, then for every `x` in the domain of `f`, `f x` -divides `finprod f`. -/ +divides `finprod f`. -/ theorem finprod_mem_dvd {f : α → N} (a : α) (hf : (mulSupport f).Finite) : f a ∣ finprod f := by by_cases ha : a ∈ mulSupport f · rw [finprod_eq_prod_of_mulSupport_toFinset_subset f hf (Set.Subset.refl _)] diff --git a/Mathlib/Algebra/BigOperators/Finsupp.lean b/Mathlib/Algebra/BigOperators/Finsupp.lean index b828486c30166..25a6ab9d28063 100644 --- a/Mathlib/Algebra/BigOperators/Finsupp.lean +++ b/Mathlib/Algebra/BigOperators/Finsupp.lean @@ -268,9 +268,10 @@ theorem support_sum [DecidableEq β] [Zero M] [AddCommMonoid N] {f : α →₀ M theorem support_finset_sum [DecidableEq β] [AddCommMonoid M] {s : Finset α} {f : α → β →₀ M} : (Finset.sum s f).support ⊆ s.biUnion fun x => (f x).support := by rw [← Finset.sup_eq_biUnion] - induction' s using Finset.cons_induction_on with a s ha ih - · rfl - · rw [Finset.sum_cons, Finset.sup_cons] + induction s using Finset.cons_induction_on with + | h₁ => rfl + | h₂ _ ih => + rw [Finset.sum_cons, Finset.sup_cons] exact support_add.trans (Finset.union_subset_union (Finset.Subset.refl _) ih) @[simp] @@ -347,7 +348,7 @@ def liftAddHom [AddZeroClass M] [AddCommMonoid N] : (α → M →+ N) ≃+ ((α right_inv F := by -- Porting note: This was `ext` and used the wrong lemma apply Finsupp.addHom_ext' - simp [singleAddHom, AddMonoidHom.comp, Function.comp] + simp [singleAddHom, AddMonoidHom.comp, Function.comp_def] map_add' F G := by ext x exact sum_add diff --git a/Mathlib/Algebra/BigOperators/Group/Finset.lean b/Mathlib/Algebra/BigOperators/Group/Finset.lean index db06873e55a04..84b2a9a1ee80b 100644 --- a/Mathlib/Algebra/BigOperators/Group/Finset.lean +++ b/Mathlib/Algebra/BigOperators/Group/Finset.lean @@ -214,7 +214,7 @@ macro_rules (kind := bigprodin) | `(∏ $x:ident : $t in $s, $r) => `(∏ $x:ident ∈ ($s : Finset $t), $r) open Lean Meta Parser.Term PrettyPrinter.Delaborator SubExpr -open Batteries.ExtendedBinder +open scoped Batteries.ExtendedBinder /-- Delaborator for `Finset.prod`. The `pp.piBinderTypes` option controls whether to show the domain type when the product is over `Finset.univ`. -/ @@ -540,7 +540,7 @@ theorem prod_biUnion [DecidableEq α] {s : Finset γ} {t : γ → Finset α} rw [← disjiUnion_eq_biUnion _ _ hs, prod_disjiUnion] /-- Product over a sigma type equals the product of fiberwise products. For rewriting -in the reverse direction, use `Finset.prod_sigma'`. -/ +in the reverse direction, use `Finset.prod_sigma'`. -/ @[to_additive "Sum over a sigma type equals the sum of fiberwise sums. For rewriting in the reverse direction, use `Finset.sum_sigma'`"] theorem prod_sigma {σ : α → Type*} (s : Finset α) (t : ∀ a, Finset (σ a)) (f : Sigma σ → β) : @@ -1310,16 +1310,16 @@ theorem eventually_constant_prod {u : ℕ → β} {N : ℕ} (hu : ∀ n ≥ N, u (∏ k ∈ range n, u k) = ∏ k ∈ range N, u k := by obtain ⟨m, rfl : n = N + m⟩ := Nat.exists_eq_add_of_le hn clear hn - induction' m with m hm - · simp - · simp [← add_assoc, prod_range_succ, hm, hu] + induction m with + | zero => simp + | succ m hm => simp [← add_assoc, prod_range_succ, hm, hu] @[to_additive] theorem prod_range_add (f : ℕ → β) (n m : ℕ) : (∏ x ∈ range (n + m), f x) = (∏ x ∈ range n, f x) * ∏ x ∈ range m, f (n + x) := by - induction' m with m hm - · simp - · erw [Nat.add_succ, prod_range_succ, prod_range_succ, hm, mul_assoc] + induction m with + | zero => simp + | succ m hm => rw [Nat.add_succ, prod_range_succ, prod_range_succ, hm, mul_assoc] @[to_additive] theorem prod_range_add_div_prod_range {α : Type*} [CommGroup α] (f : ℕ → α) (n m : ℕ) : @@ -1338,7 +1338,9 @@ open List @[to_additive] theorem prod_list_map_count [DecidableEq α] (l : List α) {M : Type*} [CommMonoid M] (f : α → M) : (l.map f).prod = ∏ m ∈ l.toFinset, f m ^ l.count m := by - induction' l with a s IH; · simp only [map_nil, prod_nil, count_nil, pow_zero, prod_const_one] + induction l with + | nil => simp only [map_nil, prod_nil, count_nil, pow_zero, prod_const_one] + | cons a s IH => simp only [List.map, List.prod_cons, toFinset_cons, IH] by_cases has : a ∈ s.toFinset · rw [insert_eq_of_mem has, ← insert_erase has, prod_insert (not_mem_erase _ _), @@ -1492,7 +1494,7 @@ theorem prod_pow (s : Finset α) (n : ℕ) (f : α → β) : ∏ x ∈ s, f x ^ Multiset.prod_map_pow @[to_additive sum_nsmul_assoc] -lemma prod_pow_eq_pow_sum (s : Finset ι) (f : ι → ℕ) (a : β) : +lemma prod_pow_eq_pow_sum (s : Finset ι) (f : ι → ℕ) (a : β) : ∏ i ∈ s, a ^ f i = a ^ ∑ i ∈ s, f i := cons_induction (by simp) (fun _ _ _ _ ↦ by simp [prod_cons, sum_cons, pow_add, *]) s @@ -1521,17 +1523,17 @@ lemma prod_involution (g : ∀ a ∈ s, α) (hg₁ : ∀ a ha, f a * f (g a ha) (g_mem : ∀ a ha, g a ha ∈ s) (hg₄ : ∀ a ha, g (g a ha) (g_mem a ha) = a) : ∏ x ∈ s, f x = 1 := by classical - induction' s using Finset.strongInduction with s ih + induction s using Finset.strongInduction with | H s ih => ?_ obtain rfl | ⟨x, hx⟩ := s.eq_empty_or_nonempty · simp have : {x, g x hx} ⊆ s := by simp [insert_subset_iff, hx, g_mem] suffices h : ∏ x ∈ s \ {x, g x hx}, f x = 1 by rw [← prod_sdiff this, h, one_mul] - rcases eq_or_ne (g x hx) x - case inl hx' => simpa [hx'] using hg₃ x hx - case inr hx' => rw [prod_pair hx'.symm, hg₁] - suffices h₃ : ∀ a (ha : a ∈ s \ {x, g x hx}), g a (sdiff_subset ha) ∈ s \ {x, g x hx} by - exact ih (s \ {x, g x hx}) (ssubset_iff.2 ⟨x, by simp [insert_subset_iff, hx]⟩) _ + cases eq_or_ne (g x hx) x with + | inl hx' => simpa [hx'] using hg₃ x hx + | inr hx' => rw [prod_pair hx'.symm, hg₁] + suffices h₃ : ∀ a (ha : a ∈ s \ {x, g x hx}), g a (sdiff_subset ha) ∈ s \ {x, g x hx} from + ih (s \ {x, g x hx}) (ssubset_iff.2 ⟨x, by simp [insert_subset_iff, hx]⟩) _ (by simp [hg₁]) (fun _ _ => hg₃ _ _) h₃ (fun _ _ => hg₄ _ _) simp only [mem_sdiff, mem_insert, mem_singleton, not_or, g_mem, true_and] rintro a ⟨ha₁, ha₂, ha₃⟩ @@ -1637,7 +1639,7 @@ theorem eq_of_card_le_one_of_prod_eq {s : Finset α} (hc : s.card ≤ 1) {f : α · exact False.elim (card_ne_zero_of_mem hx hc0) · have h1 : s.card = 1 := le_antisymm hc (Nat.one_le_of_lt (Nat.pos_of_ne_zero hc0)) rw [card_eq_one] at h1 - cases' h1 with x2 hx2 + obtain ⟨x2, hx2⟩ := h1 rw [hx2, mem_singleton] at hx simp_rw [hx2] at h rw [hx] @@ -1716,9 +1718,11 @@ theorem prod_pow_boole [DecidableEq α] (s : Finset α) (f : α → β) (a : α) theorem prod_dvd_prod_of_dvd {S : Finset α} (g1 g2 : α → β) (h : ∀ a ∈ S, g1 a ∣ g2 a) : S.prod g1 ∣ S.prod g2 := by classical - induction' S using Finset.induction_on' with a T _haS _hTS haT IH - · simp - · rw [Finset.prod_insert haT, prod_insert haT] + induction S using Finset.induction_on' with + | h₁ => simp + | h₂ _haS _hTS haT IH => + rename_i a T + rw [Finset.prod_insert haT, prod_insert haT] exact mul_dvd_mul (h a <| T.mem_insert_self a) <| IH fun b hb ↦ h b <| mem_insert_of_mem hb theorem prod_dvd_prod_of_subset {ι M : Type*} [CommMonoid M] (s t : Finset ι) (f : ι → M) @@ -2065,9 +2069,11 @@ namespace Multiset theorem disjoint_list_sum_left {a : Multiset α} {l : List (Multiset α)} : Multiset.Disjoint l.sum a ↔ ∀ b ∈ l, Multiset.Disjoint b a := by - induction' l with b bs ih - · simp only [zero_disjoint, List.not_mem_nil, IsEmpty.forall_iff, forall_const, List.sum_nil] - · simp_rw [List.sum_cons, disjoint_add_left, List.mem_cons, forall_eq_or_imp] + induction l with + | nil => + simp only [zero_disjoint, List.not_mem_nil, IsEmpty.forall_iff, forall_const, List.sum_nil] + | cons b bs ih => + simp_rw [List.sum_cons, disjoint_add_left, List.mem_cons, forall_eq_or_imp] simp [and_congr_left_iff, iff_self_iff, ih] theorem disjoint_list_sum_right {a : Multiset α} {l : List (Multiset α)} : @@ -2095,7 +2101,7 @@ theorem disjoint_finset_sum_right {β : Type*} {i : Finset β} {f : β → Multi @[simp] lemma mem_sum {s : Finset ι} {m : ι → Multiset α} : a ∈ ∑ i ∈ s, m i ↔ ∃ i ∈ s, a ∈ m i := by - induction' s using Finset.cons_induction <;> simp [*] + induction s using Finset.cons_induction <;> simp [*] variable [DecidableEq α] @@ -2141,9 +2147,10 @@ theorem toFinset_prod_dvd_prod [CommMonoid α] (S : Multiset α) : S.toFinset.pr theorem prod_sum {α : Type*} {ι : Type*} [CommMonoid α] (f : ι → Multiset α) (s : Finset ι) : (∑ x ∈ s, f x).prod = ∏ x ∈ s, (f x).prod := by classical - induction' s using Finset.induction_on with a t hat ih - · rw [Finset.sum_empty, Finset.prod_empty, Multiset.prod_zero] - · rw [Finset.sum_insert hat, Finset.prod_insert hat, Multiset.prod_add, ih] + induction s using Finset.induction_on with + | empty => rw [Finset.sum_empty, Finset.prod_empty, Multiset.prod_zero] + | insert hat ih => + rw [Finset.sum_insert hat, Finset.prod_insert hat, Multiset.prod_add, ih] end Multiset @@ -2155,9 +2162,10 @@ theorem Units.coe_prod {M : Type*} [CommMonoid M] (f : α → Mˣ) (s : Finset theorem nat_abs_sum_le {ι : Type*} (s : Finset ι) (f : ι → ℤ) : (∑ i ∈ s, f i).natAbs ≤ ∑ i ∈ s, (f i).natAbs := by classical - induction' s using Finset.induction_on with i s his IH - · simp only [Finset.sum_empty, Int.natAbs_zero, le_refl] - · simp only [his, Finset.sum_insert, not_false_iff] + induction s using Finset.induction_on with + | empty => simp only [Finset.sum_empty, Int.natAbs_zero, le_refl] + | insert his IH => + simp only [his, Finset.sum_insert, not_false_iff] exact (Int.natAbs_add_le _ _).trans (Nat.add_le_add_left IH _) /-! ### `Additive`, `Multiplicative` -/ @@ -2252,3 +2260,5 @@ theorem Finset.sum_sym2_filter_not_isDiag {ι α} [LinearOrder ι] [AddCommMonoi simp [and_assoc] · rintro ⟨⟨i₁, j₁⟩, hij₁⟩ simp + +set_option linter.style.longFile 2400 diff --git a/Mathlib/Algebra/BigOperators/Group/List.lean b/Mathlib/Algebra/BigOperators/Group/List.lean index b283972626cff..8f96d4c7f7dbb 100644 --- a/Mathlib/Algebra/BigOperators/Group/List.lean +++ b/Mathlib/Algebra/BigOperators/Group/List.lean @@ -12,6 +12,7 @@ import Mathlib.Data.List.Perm import Mathlib.Data.List.ProdSigma import Mathlib.Data.List.Range import Mathlib.Data.List.Rotate +import Mathlib.Data.List.Pairwise /-! # Sums and products from lists @@ -90,11 +91,12 @@ theorem prod_cons : (a :: l).prod = a * l.prod := lemma prod_induction (p : M → Prop) (hom : ∀ a b, p a → p b → p (a * b)) (unit : p 1) (base : ∀ x ∈ l, p x) : p l.prod := by - induction' l with a l ih - · simpa - rw [List.prod_cons] - simp only [Bool.not_eq_true, List.mem_cons, forall_eq_or_imp] at base - exact hom _ _ (base.1) (ih base.2) + induction l with + | nil => simpa + | cons a l ih => + rw [List.prod_cons] + simp only [Bool.not_eq_true, List.mem_cons, forall_eq_or_imp] at base + exact hom _ _ (base.1) (ih base.2) @[to_additive (attr := simp)] theorem prod_append : (l₁ ++ l₂).prod = l₁.prod * l₂.prod := @@ -175,10 +177,11 @@ theorem prod_isUnit : ∀ {L : List M}, (∀ m ∈ L, IsUnit m) → IsUnit L.pro theorem prod_isUnit_iff {α : Type*} [CommMonoid α] {L : List α} : IsUnit L.prod ↔ ∀ m ∈ L, IsUnit m := by refine ⟨fun h => ?_, prod_isUnit⟩ - induction' L with m L ih - · exact fun m' h' => False.elim (not_mem_nil m' h') - rw [prod_cons, IsUnit.mul_iff] at h - 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 + induction L with + | nil => exact fun m' h' => False.elim (not_mem_nil m' h') + | cons m L ih => + rw [prod_cons, IsUnit.mul_iff] at h + 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 @@ -244,9 +247,10 @@ theorem headI_mul_tail_prod_of_ne_nil [Inhabited M] (l : List M) (h : l ≠ []) @[to_additive] theorem _root_.Commute.list_prod_right (l : List M) (y : M) (h : ∀ x ∈ l, Commute y x) : Commute y l.prod := by - induction' l with z l IH - · simp - · rw [List.forall_mem_cons] at h + induction l with + | nil => simp + | cons z l IH => + rw [List.forall_mem_cons] at h rw [List.prod_cons] exact Commute.mul_right h.1 (IH h.2) @@ -269,9 +273,11 @@ lemma prod_range_succ' (f : ℕ → M) (n : ℕ) : rw [List.prod_range_succ, hd, mul_assoc, ← List.prod_range_succ] @[to_additive] lemma prod_eq_one (hl : ∀ x ∈ l, x = 1) : l.prod = 1 := by - induction' l with i l hil - · rfl - rw [List.prod_cons, hil fun x hx ↦ hl _ (mem_cons_of_mem i hx), hl _ (mem_cons_self i l), one_mul] + induction l with + | nil => rfl + | cons i l hil => + rw [List.prod_cons, hil fun x hx ↦ hl _ (mem_cons_of_mem i hx), + hl _ (mem_cons_self i l), one_mul] @[to_additive] lemma exists_mem_ne_one_of_prod_ne_one (h : l.prod ≠ 1) : ∃ x ∈ l, x ≠ (1 : M) := by simpa only [not_forall, exists_prop] using mt prod_eq_one h @@ -279,20 +285,22 @@ lemma prod_range_succ' (f : ℕ → M) (n : ℕ) : @[to_additive] lemma prod_erase_of_comm [DecidableEq M] (ha : a ∈ l) (comm : ∀ x ∈ l, ∀ y ∈ l, x * y = y * x) : a * (l.erase a).prod = l.prod := by - induction' l with b l ih - · simp only [not_mem_nil] at ha - obtain rfl | ⟨ne, h⟩ := List.eq_or_ne_mem_of_mem ha - · simp only [erase_cons_head, prod_cons] - rw [List.erase, beq_false_of_ne ne.symm, List.prod_cons, List.prod_cons, ← mul_assoc, - comm a ha b (l.mem_cons_self b), mul_assoc, - ih h fun x hx y hy ↦ comm _ (List.mem_cons_of_mem b hx) _ (List.mem_cons_of_mem b hy)] + induction l with + | nil => simp only [not_mem_nil] at ha + | cons b l ih => + obtain rfl | ⟨ne, h⟩ := List.eq_or_ne_mem_of_mem ha + · simp only [erase_cons_head, prod_cons] + rw [List.erase, beq_false_of_ne ne.symm, List.prod_cons, List.prod_cons, ← mul_assoc, + comm a ha b (l.mem_cons_self b), mul_assoc, + ih h fun x hx y hy ↦ comm _ (List.mem_cons_of_mem b hx) _ (List.mem_cons_of_mem b hy)] @[to_additive] lemma prod_map_eq_pow_single [DecidableEq α] {l : List α} (a : α) (f : α → M) (hf : ∀ a', a' ≠ a → a' ∈ l → f a' = 1) : (l.map f).prod = f a ^ l.count a := by - induction' l with a' as h generalizing a - · rw [map_nil, prod_nil, count_nil, _root_.pow_zero] - · specialize h a fun a' ha' hfa' => hf a' ha' (mem_cons_of_mem _ hfa') + induction l generalizing a with + | nil => rw [map_nil, prod_nil, count_nil, _root_.pow_zero] + | cons a' as h => + specialize h a fun a' ha' hfa' => hf a' ha' (mem_cons_of_mem _ hfa') rw [List.map_cons, List.prod_cons, count_cons, h] simp only [beq_iff_eq] split_ifs with ha' @@ -414,8 +422,8 @@ theorem prod_reverse_noncomm : ∀ L : List G, L.reverse.prod = (L.map fun x => theorem prod_drop_succ : ∀ (L : List G) (i : ℕ) (p : i < L.length), (L.drop (i + 1)).prod = L[i]⁻¹ * (L.drop i).prod | [], i, p => False.elim (Nat.not_lt_zero _ p) - | x :: xs, 0, _ => by simp - | x :: xs, i + 1, p => prod_drop_succ xs i _ + | _ :: _, 0, _ => by simp + | _ :: xs, i + 1, p => prod_drop_succ xs i (Nat.lt_of_succ_lt_succ p) /-- Cancellation of a telescoping product. -/ @[to_additive "Cancellation of a telescoping sum."] @@ -424,7 +432,7 @@ theorem prod_range_div' (n : ℕ) (f : ℕ → G) : induction n with | zero => exact (div_self' (f 0)).symm | succ n h => - rw [range_succ, map_append, map_singleton, prod_append, prod_singleton, h, div_mul_div_cancel'] + rw [range_succ, map_append, map_singleton, prod_append, prod_singleton, h, div_mul_div_cancel] lemma prod_rotate_eq_one_of_prod_eq_one : ∀ {l : List G} (_ : l.prod = 1) (n : ℕ), (l.rotate n).prod = 1 @@ -546,14 +554,16 @@ theorem alternatingProd_cons (a : α) (l : List α) : end Alternating lemma sum_nat_mod (l : List ℕ) (n : ℕ) : l.sum % n = (l.map (· % n)).sum % n := by - induction' l with a l ih - · simp only [Nat.zero_mod, map_nil] - · simpa only [map_cons, sum_cons, Nat.mod_add_mod, Nat.add_mod_mod] using congr((a + $ih) % n) + induction l with + | nil => simp only [Nat.zero_mod, map_nil] + | cons a l ih => + simpa only [map_cons, sum_cons, Nat.mod_add_mod, Nat.add_mod_mod] using congr((a + $ih) % n) lemma prod_nat_mod (l : List ℕ) (n : ℕ) : l.prod % n = (l.map (· % n)).prod % n := by - induction' l with a l ih - · simp only [Nat.zero_mod, map_nil] - · simpa only [prod_cons, map_cons, Nat.mod_mul_mod, Nat.mul_mod_mod] using congr((a * $ih) % n) + induction l with + | nil => simp only [Nat.zero_mod, map_nil] + | cons a l ih => + simpa only [prod_cons, map_cons, Nat.mod_mul_mod, Nat.mul_mod_mod] using congr((a * $ih) % n) lemma sum_int_mod (l : List ℤ) (n : ℤ) : l.sum % n = (l.map (· % n)).sum % n := by induction l <;> simp [Int.add_emod, *] @@ -566,9 +576,10 @@ variable [DecidableEq α] /-- Summing the count of `x` over a list filtered by some `p` is just `countP` applied to `p` -/ theorem sum_map_count_dedup_filter_eq_countP (p : α → Bool) (l : List α) : ((l.dedup.filter p).map fun x => l.count x).sum = l.countP p := by - induction' l with a as h - · simp - · simp_rw [List.countP_cons, List.count_cons, List.sum_map_add] + induction l with + | nil => simp + | cons a as h => + simp_rw [List.countP_cons, List.count_cons, List.sum_map_add] congr 1 · refine _root_.trans ?_ h by_cases ha : a ∈ as @@ -585,7 +596,7 @@ theorem sum_map_count_dedup_filter_eq_countP (p : α → Bool) (l : List α) : obtain ⟨a', ha'⟩ := List.mem_map.1 hn split_ifs at ha' with ha · simp only [ha.symm, mem_filter, mem_dedup, find?, mem_cons, true_or, hp, - and_false, false_and] at ha' + and_false, false_and, reduceCtorEq] at ha' · exact ha'.2.symm theorem sum_map_count_dedup_eq_length (l : List α) : @@ -686,9 +697,11 @@ theorem neg_one_mem_of_prod_eq_neg_one {l : List ℤ} (h : l.prod = -1) : (-1 : /-- If all elements in a list are bounded below by `1`, then the length of the list is bounded by the sum of the elements. -/ theorem length_le_sum_of_one_le (L : List ℕ) (h : ∀ i ∈ L, 1 ≤ i) : L.length ≤ L.sum := by - induction' L with j L IH h; · simp - rw [sum_cons, length, add_comm] - exact Nat.add_le_add (h _ (mem_cons_self _ _)) (IH fun i hi => h i (mem_cons.2 (Or.inr hi))) + induction L with + | nil => simp + | cons j L IH => + rw [sum_cons, length, add_comm] + exact Nat.add_le_add (h _ (mem_cons_self _ _)) (IH fun i hi => h i (mem_cons.2 (Or.inr hi))) theorem dvd_prod [CommMonoid M] {a} {l : List M} (ha : a ∈ l) : a ∣ l.prod := by let ⟨s, t, h⟩ := append_of_mem ha @@ -754,13 +767,4 @@ lemma unop_map_list_prod {F : Type*} [FunLike F M Nᵐᵒᵖ] [MonoidHomClass F (f l.prod).unop = (l.map (MulOpposite.unop ∘ f)).reverse.prod := by rw [map_list_prod f l, MulOpposite.unop_list_prod, List.map_map] -namespace MonoidHom - -/-- A morphism into the opposite monoid acts on the product by acting on the reversed elements. -/ -@[deprecated _root_.unop_map_list_prod (since := "2023-01-10")] -protected theorem unop_map_list_prod (f : M →* Nᵐᵒᵖ) (l : List M) : - (f l.prod).unop = (l.map (MulOpposite.unop ∘ f)).reverse.prod := - unop_map_list_prod f l - -end MonoidHom end MonoidHom diff --git a/Mathlib/Algebra/BigOperators/Group/Multiset.lean b/Mathlib/Algebra/BigOperators/Group/Multiset.lean index b2d09816f2c5b..0d5d2fc6e95ea 100644 --- a/Mathlib/Algebra/BigOperators/Group/Multiset.lean +++ b/Mathlib/Algebra/BigOperators/Group/Multiset.lean @@ -106,18 +106,17 @@ theorem prod_replicate (n : ℕ) (a : α) : (replicate n a).prod = a ^ n := by @[to_additive] theorem prod_map_eq_pow_single [DecidableEq ι] (i : ι) (hf : ∀ i' ≠ i, i' ∈ m → f i' = 1) : (m.map f).prod = f i ^ m.count i := by - induction' m using Quotient.inductionOn with l + induction m using Quotient.inductionOn simp [List.prod_map_eq_pow_single i f hf] @[to_additive] theorem prod_eq_pow_single [DecidableEq α] (a : α) (h : ∀ a' ≠ a, a' ∈ s → a' = 1) : s.prod = a ^ s.count a := by - induction' s using Quotient.inductionOn with l - simp [List.prod_eq_pow_single a h] + induction s using Quotient.inductionOn; simp [List.prod_eq_pow_single a h] @[to_additive] lemma prod_eq_one (h : ∀ x ∈ s, x = (1 : α)) : s.prod = 1 := by - induction' s using Quotient.inductionOn with l; simp [List.prod_eq_one h] + induction s using Quotient.inductionOn; simp [List.prod_eq_one h] @[to_additive] theorem pow_count [DecidableEq α] (a : α) : a ^ s.count a = (s.filter (Eq a)).prod := by @@ -178,13 +177,14 @@ theorem prod_induction (p : α → Prop) (s : Multiset α) (p_mul : ∀ a b, p a theorem prod_induction_nonempty (p : α → Prop) (p_mul : ∀ a b, p a → p b → p (a * b)) (hs : s ≠ ∅) (p_s : ∀ a ∈ s, p a) : p s.prod := by -- Porting note: used to be `refine' Multiset.induction _ _` - induction' s using Multiset.induction_on with a s hsa - · simp at hs - rw [prod_cons] - by_cases hs_empty : s = ∅ - · simp [hs_empty, p_s a] - have hps : ∀ x, x ∈ s → p x := fun x hxs => p_s x (mem_cons_of_mem hxs) - exact p_mul a s.prod (p_s a (mem_cons_self a s)) (hsa hs_empty hps) + induction s using Multiset.induction_on with + | empty => simp at hs + | cons a s hsa => + rw [prod_cons] + by_cases hs_empty : s = ∅ + · simp [hs_empty, p_s a] + have hps : ∀ x, x ∈ s → p x := fun x hxs => p_s x (mem_cons_of_mem hxs) + exact p_mul a s.prod (p_s a (mem_cons_self a s)) (hsa hs_empty hps) theorem prod_dvd_prod_of_le (h : s ≤ t) : s.prod ∣ t.prod := by obtain ⟨z, rfl⟩ := exists_add_of_le h diff --git a/Mathlib/GroupTheory/GroupAction/BigOperators.lean b/Mathlib/Algebra/BigOperators/GroupWithZero/Action.lean similarity index 82% rename from Mathlib/GroupTheory/GroupAction/BigOperators.lean rename to Mathlib/Algebra/BigOperators/GroupWithZero/Action.lean index 4ab2659b3a283..7ad7cb7f697d9 100644 --- a/Mathlib/GroupTheory/GroupAction/BigOperators.lean +++ b/Mathlib/Algebra/BigOperators/GroupWithZero/Action.lean @@ -7,6 +7,7 @@ import Mathlib.Algebra.BigOperators.Group.Finset import Mathlib.Algebra.GroupWithZero.Action.Defs import Mathlib.Data.Finset.Basic import Mathlib.Data.Multiset.Basic +import Mathlib.Algebra.BigOperators.Finprod /-! # Lemmas about group actions on big operators @@ -59,4 +60,10 @@ theorem Finset.smul_prod {r : α} {f : γ → β} {s : Finset γ} : (r • ∏ x ∈ s, f x) = ∏ x ∈ s, r • f x := map_prod (MulDistribMulAction.toMonoidHom β r) f s +theorem smul_finprod {ι : Sort*} [Finite ι] {f : ι → β} (r : α) : + r • ∏ᶠ x : ι, f x = ∏ᶠ x : ι, r • (f x) := by + cases nonempty_fintype (PLift ι) + simp only [finprod_eq_prod_plift_of_mulSupport_subset (s := Finset.univ) (by simp), + finprod_eq_prod_of_fintype, Finset.smul_prod] + end diff --git a/Mathlib/Algebra/BigOperators/GroupWithZero/Finset.lean b/Mathlib/Algebra/BigOperators/GroupWithZero/Finset.lean index ecc383eb492cf..6031d188022c6 100644 --- a/Mathlib/Algebra/BigOperators/GroupWithZero/Finset.lean +++ b/Mathlib/Algebra/BigOperators/GroupWithZero/Finset.lean @@ -43,9 +43,9 @@ variable [Nontrivial M₀] [NoZeroDivisors M₀] lemma prod_eq_zero_iff : ∏ x ∈ s, f x = 0 ↔ ∃ a ∈ s, f a = 0 := by classical - induction' s using Finset.induction_on with a s ha ih - · exact ⟨Not.elim one_ne_zero, fun ⟨_, H, _⟩ => by simp at H⟩ - · rw [prod_insert ha, mul_eq_zero, exists_mem_insert, ih] + induction s using Finset.induction_on with + | empty => exact ⟨Not.elim one_ne_zero, fun ⟨_, H, _⟩ => by simp at H⟩ + | insert ha ih => rw [prod_insert ha, mul_eq_zero, exists_mem_insert, ih] lemma prod_ne_zero_iff : ∏ x ∈ s, f x ≠ 0 ↔ ∀ a ∈ s, f a ≠ 0 := by rw [Ne, prod_eq_zero_iff] diff --git a/Mathlib/Algebra/BigOperators/Intervals.lean b/Mathlib/Algebra/BigOperators/Intervals.lean index af96f697d0ba2..fffc916fc80ef 100644 --- a/Mathlib/Algebra/BigOperators/Intervals.lean +++ b/Mathlib/Algebra/BigOperators/Intervals.lean @@ -193,7 +193,7 @@ theorem prod_Ico_reflect (f : ℕ → M) (k : ℕ) {m n : ℕ} (h : m ≤ n + 1) have : ∀ i < m, i ≤ n := by intro i hi exact (add_le_add_iff_right 1).1 (le_trans (Nat.lt_iff_add_one_le.1 hi) h) - cases' lt_or_le k m with hkm hkm + rcases lt_or_le k m with hkm | hkm · rw [← Nat.Ico_image_const_sub_eq_Ico (this _ hkm)] refine (prod_image ?_).symm simp only [mem_Ico] diff --git a/Mathlib/Algebra/BigOperators/Ring.lean b/Mathlib/Algebra/BigOperators/Ring.lean index 71bf64045aeca..0cf28cc97f8a8 100644 --- a/Mathlib/Algebra/BigOperators/Ring.lean +++ b/Mathlib/Algebra/BigOperators/Ring.lean @@ -109,10 +109,11 @@ variable [DecidableEq ι] lemma prod_sum (s : Finset ι) (t : ∀ i, Finset (κ i)) (f : ∀ i, κ i → α) : ∏ a ∈ s, ∑ b ∈ t a, f a b = ∑ p ∈ s.pi t, ∏ x ∈ s.attach, f x.1 (p x.1 x.2) := by classical - induction' s using Finset.induction with a s ha ih - · rw [pi_empty, sum_singleton] - rfl - · have h₁ : ∀ x ∈ t a, ∀ y ∈ t a, x ≠ y → + induction s using Finset.induction with + | empty => rw [pi_empty, sum_singleton]; rfl + | insert ha ih => + rename_i a s + have h₁ : ∀ x ∈ t a, ∀ y ∈ t a, x ≠ y → Disjoint (image (Pi.cons s a x) (pi s t)) (image (Pi.cons s a y) (pi s t)) := by intro x _ y _ h simp only [disjoint_iff_ne, mem_image] @@ -168,7 +169,7 @@ theorem prod_add (f g : ι → α) (s : Finset ι) : (by simp) (by simp [Classical.em]) (by simp_rw [mem_filter, Function.funext_iff, eq_iff_iff, mem_pi, mem_insert]; tauto) - (by simp_rw [ext_iff, @mem_filter _ _ (id _), mem_powerset]; tauto) + (by simp_rw [Finset.ext_iff, @mem_filter _ _ (id _), mem_powerset]; tauto) (fun a _ ↦ by simp only [prod_ite, filter_attach', prod_map, Function.Embedding.coeFn_mk, Subtype.map_coe, id_eq, prod_attach, filter_congr_decidable] @@ -238,7 +239,7 @@ lemma prod_sub_ordered [LinearOrder ι] (s : Finset ι) (f g : ι → α) : simp /-- `∏ i, (1 - f i) = 1 - ∑ i, f i * (∏ j < i, 1 - f j)`. This formula is useful in construction of -a partition of unity from a collection of “bump” functions. -/ +a partition of unity from a collection of “bump” functions. -/ theorem prod_one_sub_ordered [LinearOrder ι] (s : Finset ι) (f : ι → α) : ∏ i ∈ s, (1 - f i) = 1 - ∑ i ∈ s, f i * ∏ j ∈ s.filter (· < i), (1 - f j) := by rw [prod_sub_ordered] diff --git a/Mathlib/Algebra/BigOperators/Ring/List.lean b/Mathlib/Algebra/BigOperators/Ring/List.lean index 55d9be58b9004..5825782ff4ddb 100644 --- a/Mathlib/Algebra/BigOperators/Ring/List.lean +++ b/Mathlib/Algebra/BigOperators/Ring/List.lean @@ -24,9 +24,10 @@ namespace Commute variable [NonUnitalNonAssocSemiring R] lemma list_sum_right (a : R) (l : List R) (h : ∀ b ∈ l, Commute a b) : Commute a l.sum := by - induction' l with x xs ih - · exact Commute.zero_right _ - · rw [List.sum_cons] + induction l with + | nil => exact Commute.zero_right _ + | cons x xs ih => + rw [List.sum_cons] exact (h _ <| mem_cons_self _ _).add_right (ih fun j hj ↦ h _ <| mem_cons_of_mem _ hj) lemma list_sum_left (b : R) (l : List R) (h : ∀ a ∈ l, Commute a b) : Commute l.sum b := @@ -55,7 +56,7 @@ lemma prod_eq_zero : ∀ {l : List M₀}, (0 : M₀) ∈ l → l.prod = 0 -- | absurd h (not_mem_nil _) | a :: l, h => by rw [prod_cons] - cases' mem_cons.1 h with ha hl + rcases mem_cons.1 h with ha | hl exacts [mul_eq_zero_of_left ha.symm _, mul_eq_zero_of_right _ (prod_eq_zero hl)] variable [Nontrivial M₀] [NoZeroDivisors M₀] @@ -82,9 +83,10 @@ lemma sum_map_mul_right : (l.map fun b ↦ f b * r).sum = (l.map f).sum * r := end NonUnitalNonAssocSemiring lemma dvd_sum [NonUnitalSemiring R] {a} {l : List R} (h : ∀ x ∈ l, a ∣ x) : a ∣ l.sum := by - induction' l with x l ih - · exact dvd_zero _ - · rw [List.sum_cons] + induction l with + | nil => exact dvd_zero _ + | cons x l ih => + rw [List.sum_cons] exact dvd_add (h _ (mem_cons_self _ _)) (ih fun x hx ↦ h x (mem_cons_of_mem _ hx)) @[simp] lemma sum_zipWith_distrib_left [Semiring R] (f : ι → κ → R) (a : R) : diff --git a/Mathlib/Algebra/BigOperators/Ring/Nat.lean b/Mathlib/Algebra/BigOperators/Ring/Nat.lean index 1b3759dd9bbe0..935c47b1fec02 100644 --- a/Mathlib/Algebra/BigOperators/Ring/Nat.lean +++ b/Mathlib/Algebra/BigOperators/Ring/Nat.lean @@ -22,11 +22,11 @@ lemma even_sum_iff_even_card_odd {s : Finset ι} (f : ι → ℕ) : rw [← Finset.sum_filter_add_sum_filter_not _ (fun x ↦ Even (f x)), Nat.even_add] simp only [Finset.mem_filter, and_imp, imp_self, implies_true, Finset.even_sum, true_iff] rw [Nat.even_iff, Finset.sum_nat_mod, Finset.sum_filter] - simp (config := { contextual := true }) only [← Nat.odd_iff_not_even, Nat.odd_iff.mp] + simp (config := { contextual := true }) only [Nat.not_even_iff_odd, Nat.odd_iff.mp] simp_rw [← Finset.sum_filter, ← Nat.even_iff, Finset.card_eq_sum_ones] lemma odd_sum_iff_odd_card_odd {s : Finset ι} (f : ι → ℕ) : Odd (∑ i ∈ s, f i) ↔ Odd (s.filter fun x ↦ Odd (f x)).card := by - simp only [Nat.odd_iff_not_even, even_sum_iff_even_card_odd] + simp only [← Nat.not_even_iff_odd, even_sum_iff_even_card_odd] end Finset diff --git a/Mathlib/Algebra/BigOperators/WithTop.lean b/Mathlib/Algebra/BigOperators/WithTop.lean index 5defb21c328a8..17d569cd5b075 100644 --- a/Mathlib/Algebra/BigOperators/WithTop.lean +++ b/Mathlib/Algebra/BigOperators/WithTop.lean @@ -24,27 +24,36 @@ variable [AddCommMonoid α] {s : Finset ι} {f : ι → WithTop α} ∑ i ∈ s, f i = ∑ i ∈ s, (f i : WithTop α) := map_sum addHom f s /-- A sum is infinite iff one term is infinite. -/ -lemma sum_eq_top_iff : ∑ i ∈ s, f i = ⊤ ↔ ∃ i ∈ s, f i = ⊤ := by +@[simp] lemma sum_eq_top : ∑ i ∈ s, f i = ⊤ ↔ ∃ i ∈ s, f i = ⊤ := by induction s using Finset.cons_induction <;> simp [*] +/-- A sum is finite iff all terms are finite. -/ +lemma sum_ne_top : ∑ i ∈ s, f i ≠ ⊤ ↔ ∀ i ∈ s, f i ≠ ⊤ := by simp + variable [LT α] /-- A sum is finite iff all terms are finite. -/ -lemma sum_lt_top_iff : ∑ i ∈ s, f i < ⊤ ↔ ∀ i ∈ s, f i < ⊤ := by - simp only [WithTop.lt_top_iff_ne_top, ne_eq, sum_eq_top_iff, not_exists, not_and] +@[simp] lemma sum_lt_top : ∑ i ∈ s, f i < ⊤ ↔ ∀ i ∈ s, f i < ⊤ := by + simp [WithTop.lt_top_iff_ne_top] -/-- A sum of finite terms is finite. -/ -lemma sum_lt_top (h : ∀ i ∈ s, f i ≠ ⊤) : ∑ i ∈ s, f i < ⊤ := - sum_lt_top_iff.2 fun i hi ↦ WithTop.lt_top_iff_ne_top.2 (h i hi) +@[deprecated (since := "2024-08-25")] alias sum_eq_top_iff := sum_eq_top +@[deprecated (since := "2024-08-25")] alias sum_lt_top_iff := sum_lt_top end AddCommMonoid +section CommMonoidWithZero +variable [CommMonoidWithZero α] [NoZeroDivisors α] [Nontrivial α] [DecidableEq α] + {s : Finset ι} {f : ι → WithTop α} + +/-- A product of finite terms is finite. -/ +lemma prod_ne_top (h : ∀ i ∈ s, f i ≠ ⊤) : ∏ i ∈ s, f i ≠ ⊤ := + prod_induction f (· ≠ ⊤) (fun _ _ ↦ mul_ne_top) coe_ne_top h + /-- A product of finite terms is finite. -/ -lemma prod_lt_top [CommMonoidWithZero α] [NoZeroDivisors α] [Nontrivial α] [DecidableEq α] [LT α] - {s : Finset ι} {f : ι → WithTop α} (h : ∀ i ∈ s, f i ≠ ⊤) : ∏ i ∈ s, f i < ⊤ := - prod_induction f (· < ⊤) (fun _ _ h₁ h₂ ↦ mul_lt_top' h₁ h₂) (coe_lt_top 1) - fun a ha ↦ WithTop.lt_top_iff_ne_top.2 (h a ha) +lemma prod_lt_top [LT α] (h : ∀ i ∈ s, f i < ⊤) : ∏ i ∈ s, f i < ⊤ := + prod_induction f (· < ⊤) (fun _ _ ↦ mul_lt_top) (coe_lt_top _) h +end CommMonoidWithZero end WithTop namespace WithBot @@ -70,10 +79,25 @@ lemma sum_lt_bot (h : ∀ i ∈ s, f i ≠ ⊥) : ⊥ < ∑ i ∈ s, f i := end AddCommMonoid +section CommMonoidWithZero +variable [CommMonoidWithZero α] [NoZeroDivisors α] [Nontrivial α] [DecidableEq α] + {s : Finset ι} {f : ι → WithBot α} + +/-- A product of finite terms is finite. -/ +lemma prod_ne_bot (h : ∀ i ∈ s, f i ≠ ⊥) : ∏ i ∈ s, f i ≠ ⊥ := + prod_induction f (· ≠ ⊥) (fun _ _ ↦ mul_ne_bot) coe_ne_bot h + +/-- A product of finite terms is finite. -/ +lemma bot_lt_prod [LT α] (h : ∀ i ∈ s, ⊥ < f i) : ⊥ < ∏ i ∈ s, f i := + prod_induction f (⊥ < ·) (fun _ _ ↦ bot_lt_mul) (bot_lt_coe _) h + +end CommMonoidWithZero + /-- A product of finite terms is finite. -/ +@[deprecated bot_lt_prod (since := "2024-08-25")] lemma prod_lt_bot [CommMonoidWithZero α] [NoZeroDivisors α] [Nontrivial α] [DecidableEq α] [LT α] {s : Finset ι} {f : ι → WithBot α} (h : ∀ i ∈ s, f i ≠ ⊥) : ⊥ < ∏ i ∈ s, f i := - prod_induction f (⊥ < ·) (fun _ _ h₁ h₂ ↦ bot_lt_mul' h₁ h₂) (bot_lt_coe 1) + prod_induction f (⊥ < ·) (fun _ _ h₁ h₂ ↦ bot_lt_mul h₁ h₂) (bot_lt_coe 1) fun a ha ↦ WithBot.bot_lt_iff_ne_bot.2 (h a ha) end WithBot diff --git a/Mathlib/Algebra/Bounds.lean b/Mathlib/Algebra/Bounds.lean index 95219c22b4fa9..8c9ff1cb53079 100644 --- a/Mathlib/Algebra/Bounds.lean +++ b/Mathlib/Algebra/Bounds.lean @@ -3,11 +3,11 @@ 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.Data.Set.Pointwise.Basic +import Mathlib.Algebra.Order.Monoid.Unbundled.OrderDual import Mathlib.Order.Bounds.OrderIso import Mathlib.Order.ConditionallyCompleteLattice.Basic -import Mathlib.Algebra.Order.Monoid.Unbundled.OrderDual /-! # Upper/lower bounds in ordered monoids and groups diff --git a/Mathlib/Algebra/Category/AlgebraCat/Monoidal.lean b/Mathlib/Algebra/Category/AlgebraCat/Monoidal.lean index 48be5957eed6d..cd040c2eefb18 100644 --- a/Mathlib/Algebra/Category/AlgebraCat/Monoidal.lean +++ b/Mathlib/Algebra/Category/AlgebraCat/Monoidal.lean @@ -79,12 +79,12 @@ noncomputable instance instMonoidalCategory : MonoidalCategory (AlgebraCat.{u} R εIso := Iso.refl _ associator_eq := fun X Y Z => by dsimp only [forget₂_module_obj, forget₂_map_associator_hom] - simp only [eqToIso_refl, Iso.refl_trans, Iso.refl_symm, Iso.trans_hom, tensorIso_hom, - Iso.refl_hom, MonoidalCategory.tensor_id] + simp only [eqToIso_refl, Iso.refl_trans, Iso.refl_symm, Iso.trans_hom, + MonoidalCategory.tensorIso_hom, Iso.refl_hom, MonoidalCategory.tensor_id] erw [Category.id_comp, Category.comp_id, MonoidalCategory.tensor_id, Category.id_comp] leftUnitor_eq := fun X => by dsimp only [forget₂_module_obj, forget₂_module_map, Iso.refl_symm, Iso.trans_hom, - Iso.refl_hom, tensorIso_hom] + Iso.refl_hom, MonoidalCategory.tensorIso_hom] erw [Category.id_comp, MonoidalCategory.tensor_id, Category.id_comp] rfl rightUnitor_eq := fun X => by diff --git a/Mathlib/Algebra/Category/CoalgebraCat/ComonEquivalence.lean b/Mathlib/Algebra/Category/CoalgebraCat/ComonEquivalence.lean index 7fe43405b8530..9936f06b55a0f 100644 --- a/Mathlib/Algebra/Category/CoalgebraCat/ComonEquivalence.lean +++ b/Mathlib/Algebra/Category/CoalgebraCat/ComonEquivalence.lean @@ -19,7 +19,7 @@ coalgebras defined in `Mathlib.RingTheory.Coalgebra.TensorProduct` in #11975. ## Implementation notes -We make the definiton `CoalgebraCat.instMonoidalCategoryAux` in this file, which is the +We make the definition `CoalgebraCat.instMonoidalCategoryAux` in this file, which is the monoidal structure on `CoalgebraCat` induced by the equivalence with `Comon(R-Mod)`. We use this to show the comultiplication and counit on a tensor product of coalgebras satisfy the coalgebra axioms, but our actual `MonoidalCategory` instance on `CoalgebraCat` is diff --git a/Mathlib/Algebra/Category/Grp/Adjunctions.lean b/Mathlib/Algebra/Category/Grp/Adjunctions.lean index 18557f976c125..0ae1a7d27e135 100644 --- a/Mathlib/Algebra/Category/Grp/Adjunctions.lean +++ b/Mathlib/Algebra/Category/Grp/Adjunctions.lean @@ -78,6 +78,9 @@ instance : free.{u}.IsLeftAdjoint := instance : (forget AddCommGrp.{u}).IsRightAdjoint := ⟨_, ⟨adj⟩⟩ +instance : AddCommGrp.free.{u}.IsLeftAdjoint := + ⟨_, ⟨adj⟩⟩ + /-- As an example, we now give a high-powered proof that the monomorphisms in `AddCommGroup` are just the injective functions. diff --git a/Mathlib/Algebra/Category/Grp/EquivalenceGroupAddGroup.lean b/Mathlib/Algebra/Category/Grp/EquivalenceGroupAddGroup.lean index c0ffb41f10b80..ba62f49de2a29 100644 --- a/Mathlib/Algebra/Category/Grp/EquivalenceGroupAddGroup.lean +++ b/Mathlib/Algebra/Category/Grp/EquivalenceGroupAddGroup.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Jujian Zhang -/ import Mathlib.Algebra.Category.Grp.Basic -import Mathlib.Algebra.Group.Equiv.TypeTags /-! # Equivalence between `Group` and `AddGroup` @@ -71,14 +70,18 @@ end AddCommGrp /-- The equivalence of categories between `Grp` and `AddGrp` -/ -def groupAddGroupEquivalence : Grp ≌ AddGrp := - CategoryTheory.Equivalence.mk Grp.toAddGrp AddGrp.toGrp - (NatIso.ofComponents fun X => MulEquiv.toGrpIso (MulEquiv.multiplicativeAdditive X)) - (NatIso.ofComponents fun X => AddEquiv.toAddGrpIso (AddEquiv.additiveMultiplicative X)) +@[simps] +def groupAddGroupEquivalence : Grp ≌ AddGrp where + functor := Grp.toAddGrp + inverse := AddGrp.toGrp + unitIso := Iso.refl _ + counitIso := Iso.refl _ /-- The equivalence of categories between `CommGrp` and `AddCommGrp`. -/ -def commGroupAddCommGroupEquivalence : CommGrp ≌ AddCommGrp := - CategoryTheory.Equivalence.mk CommGrp.toAddCommGrp AddCommGrp.toCommGrp - (NatIso.ofComponents fun X => MulEquiv.toCommGrpIso (MulEquiv.multiplicativeAdditive X)) - (NatIso.ofComponents fun X => AddEquiv.toAddCommGrpIso (AddEquiv.additiveMultiplicative X)) +@[simps] +def commGroupAddCommGroupEquivalence : CommGrp ≌ AddCommGrp where + functor := CommGrp.toAddCommGrp + inverse := AddCommGrp.toCommGrp + unitIso := Iso.refl _ + counitIso := Iso.refl _ diff --git a/Mathlib/Algebra/Category/Grp/FilteredColimits.lean b/Mathlib/Algebra/Category/Grp/FilteredColimits.lean index fe2f4bcd125da..b79cc51e0f2ed 100644 --- a/Mathlib/Algebra/Category/Grp/FilteredColimits.lean +++ b/Mathlib/Algebra/Category/Grp/FilteredColimits.lean @@ -58,7 +58,7 @@ abbrev G.mk : (Σ j, F.obj j) → G.{v, u} F := theorem G.mk_eq (x y : Σ j, F.obj j) (h : ∃ (k : J) (f : x.1 ⟶ k) (g : y.1 ⟶ k), F.map f x.2 = F.map g y.2) : G.mk.{v, u} F x = G.mk F y := - Quot.EqvGen_sound (Types.FilteredColimit.eqvGen_quot_rel_of_rel (F ⋙ forget Grp) x y h) + Quot.eqvGen_sound (Types.FilteredColimit.eqvGen_quot_rel_of_rel (F ⋙ forget Grp) x y h) /-- The "unlifted" version of taking inverses in the colimit. -/ @[to_additive "The \"unlifted\" version of negation in the colimit."] @@ -94,7 +94,7 @@ noncomputable instance colimitGroup : Group (G.{v, u} F) := { colimitInv.{v, u} F, (G.{v, u} F).str with inv_mul_cancel := fun x => by refine Quot.inductionOn x ?_; clear x; intro x - cases' x with j x + obtain ⟨j, x⟩ := x erw [colimit_inv_mk_eq, colimit_mul_mk_eq (F ⋙ forget₂ Grp MonCat.{max v u}) ⟨j, _⟩ ⟨j, _⟩ j (𝟙 j) (𝟙 j), colimit_one_eq (F ⋙ forget₂ Grp MonCat.{max v u}) j] diff --git a/Mathlib/Algebra/Category/Grp/Limits.lean b/Mathlib/Algebra/Category/Grp/Limits.lean index f605284f69e1f..1f73a158c1bf6 100644 --- a/Mathlib/Algebra/Category/Grp/Limits.lean +++ b/Mathlib/Algebra/Category/Grp/Limits.lean @@ -126,7 +126,7 @@ instance hasLimit : HasLimit F := end /-- A functor `F : J ⥤ Grp.{u}` has a limit iff `(F ⋙ forget Grp).sections` is -`u`-small. -/ +`u`-small. -/ @[to_additive "A functor `F : J ⥤ AddGrp.{u}` has a limit iff `(F ⋙ forget AddGrp).sections` is `u`-small."] lemma hasLimit_iff_small_sections : @@ -281,7 +281,7 @@ instance hasLimit : HasLimit F := end /-- A functor `F : J ⥤ CommGrp.{u}` has a limit iff `(F ⋙ forget CommGrp).sections` is -`u`-small. -/ +`u`-small. -/ @[to_additive "A functor `F : J ⥤ AddCommGrp.{u}` has a limit iff `(F ⋙ forget AddCommGrp).sections` is `u`-small."] lemma hasLimit_iff_small_sections : diff --git a/Mathlib/Algebra/Category/ModuleCat/ChangeOfRings.lean b/Mathlib/Algebra/Category/ModuleCat/ChangeOfRings.lean index c747c278eb8b7..0417f8ed023f7 100644 --- a/Mathlib/Algebra/Category/ModuleCat/ChangeOfRings.lean +++ b/Mathlib/Algebra/Category/ModuleCat/ChangeOfRings.lean @@ -143,15 +143,18 @@ def semilinearMapAddEquiv {R : Type u₁} {S : Type u₂} [Ring R] [Ring S] (f : section -variable {R : Type u₁} [Ring R] (f : R →+* R) (hf : f = RingHom.id R) +variable {R : Type u₁} [Ring R] (f : R →+* R) /-- For a `R`-module `M`, the restriction of scalars of `M` by the identity morphisms identifies to `M`. -/ -def restrictScalarsId'App (M : ModuleCat R) : (restrictScalars f).obj M ≅ M := +def restrictScalarsId'App (hf : f = RingHom.id R) (M : ModuleCat R) : + (restrictScalars f).obj M ≅ M := LinearEquiv.toModuleIso' <| @AddEquiv.toLinearEquiv _ _ _ _ _ _ (((restrictScalars f).obj M).isModule) _ (by rfl) (fun r x ↦ by subst hf; rfl) +variable (hf : f = RingHom.id R) + lemma restrictScalarsId'App_hom_apply (M : ModuleCat R) (x : M) : (restrictScalarsId'App f hf M).hom x = x := rfl @@ -189,14 +192,16 @@ end section variable {R₁ : Type u₁} {R₂ : Type u₂} {R₃ : Type u₃} [Ring R₁] [Ring R₂] [Ring R₃] - (f : R₁ →+* R₂) (g : R₂ →+* R₃) (gf : R₁ →+* R₃) (hgf : gf = g.comp f) + (f : R₁ →+* R₂) (g : R₂ →+* R₃) (gf : R₁ →+* R₃) /-- For each `R₃`-module `M`, restriction of scalars of `M` by a composition of ring morphisms identifies to successively restricting scalars. -/ -def restrictScalarsComp'App (M : ModuleCat R₃) : +def restrictScalarsComp'App (hgf : gf = g.comp f) (M : ModuleCat R₃) : (restrictScalars gf).obj M ≅ (restrictScalars f).obj ((restrictScalars g).obj M) := (AddEquiv.toLinearEquiv (by rfl) (fun r x ↦ by subst hgf; rfl)).toModuleIso' +variable (hgf : gf = g.comp f) + lemma restrictScalarsComp'App_hom_apply (M : ModuleCat R₃) (x : M) : (restrictScalarsComp'App f g gf hgf M).hom x = x := rfl @@ -286,22 +291,21 @@ def map' {M1 M2 : ModuleCat.{v} R} (l : M1 ⟶ M2) : obj' f M1 ⟶ obj' f M2 := theorem map'_id {M : ModuleCat.{v} R} : map' f (𝟙 M) = 𝟙 _ := LinearMap.ext fun x : obj' f M => by dsimp only [map'] - -- Porting note: this got put in the dsimp by mathport - rw [ModuleCat.id_apply] - induction' x using TensorProduct.induction_on with _ _ m s ihx ihy - · rw [map_zero] -- Porting note: simp only [map_zero] failed - · -- Porting note: issues with synthesizing Algebra R S + rw [ModuleCat.id_apply] -- Porting note: this got put in the dsimp by mathport + induction x using TensorProduct.induction_on with + | zero => rw [map_zero] + | tmul => -- Porting note: issues with synthesizing Algebra R S erw [@LinearMap.baseChange_tmul R S M M _ _ (_), ModuleCat.id_apply] - · rw [map_add, ihx, ihy] + | add _ _ ihx ihy => rw [map_add, ihx, ihy] theorem map'_comp {M₁ M₂ M₃ : ModuleCat.{v} R} (l₁₂ : M₁ ⟶ M₂) (l₂₃ : M₂ ⟶ M₃) : map' f (l₁₂ ≫ l₂₃) = map' f l₁₂ ≫ map' f l₂₃ := LinearMap.ext fun x : obj' f M₁ => by dsimp only [map'] - induction' x using TensorProduct.induction_on with _ _ x y ihx ihy - · rfl - · rfl - · rw [map_add, map_add, ihx, ihy] -- Porting note: simp again failing where rw succeeds + induction x using TensorProduct.induction_on with + | zero => rfl + | tmul => rfl + | add _ _ ihx ihy => rw [map_add, map_add, ihx, ihy] end ExtendScalars @@ -660,14 +664,15 @@ def HomEquiv.fromExtendScalars {X Y} (g : X ⟶ (restrictScalars f).obj Y) : rw [map_add] · intro s z change lift _ (s • z) = s • lift _ z - induction' z using TensorProduct.induction_on with s' x x y ih1 ih2 - · rw [smul_zero, map_zero, smul_zero] - · rw [LinearMap.coe_mk, ExtendScalars.smul_tmul] + induction z using TensorProduct.induction_on with + | zero => rw [smul_zero, map_zero, smul_zero] + | tmul s' x => + rw [LinearMap.coe_mk, ExtendScalars.smul_tmul] erw [lift.tmul, lift.tmul] set s' : S := s' change (s * s') • (g x) = s • s' • (g x) rw [mul_smul] - · rw [smul_add, map_add, ih1, ih2, map_add, smul_add] + | add _ _ ih1 ih2 => rw [smul_add, map_add, ih1, ih2, map_add, smul_add] /-- Given `R`-module X and `S`-module Y, `S`-linear linear maps `(extendScalars f).obj X ⟶ Y` bijectively correspond to `R`-linear maps `X ⟶ (restrictScalars f).obj Y`. @@ -680,15 +685,16 @@ def homEquiv {X Y} : left_inv g := by letI m1 : Module R S := Module.compHom S f; letI m2 : Module R Y := Module.compHom Y f apply LinearMap.ext; intro z - induction' z using TensorProduct.induction_on with x s z1 z2 ih1 ih2 - · rw [map_zero, map_zero] - · erw [TensorProduct.lift.tmul] + induction z using TensorProduct.induction_on with + | zero => rw [map_zero, map_zero] + | tmul x s => + erw [TensorProduct.lift.tmul] simp only [LinearMap.coe_mk] change S at x dsimp erw [← LinearMap.map_smul, ExtendScalars.smul_tmul, mul_one x] rfl - · rw [map_add, map_add, ih1, ih2] + | add _ _ ih1 ih2 => rw [map_add, map_add, ih1, ih2] right_inv g := by letI m1 : Module R S := Module.compHom S f; letI m2 : Module R Y := Module.compHom Y f apply LinearMap.ext; intro x @@ -744,14 +750,15 @@ def Counit.map {Y} : (restrictScalars f ⋙ extendScalars f).obj Y ⟶ Y where letI m1 : Module R S := Module.compHom S f letI m2 : Module R Y := Module.compHom Y f dsimp only - induction' z using TensorProduct.induction_on with s' y z1 z2 ih1 ih2 - · rw [smul_zero, map_zero, smul_zero] - · rw [ExtendScalars.smul_tmul, LinearMap.coe_mk] + induction z using TensorProduct.induction_on with + | zero => rw [smul_zero, map_zero, smul_zero] + | tmul s' y => + rw [ExtendScalars.smul_tmul, LinearMap.coe_mk] erw [TensorProduct.lift.tmul, TensorProduct.lift.tmul] set s' : S := s' change (s * s') • y = s • s' • y rw [mul_smul] - · rw [smul_add, map_add, map_add, ih1, ih2, smul_add] + | add _ _ ih1 ih2 => rw [smul_add, map_add, map_add, ih1, ih2, smul_add] -- Porting note: this file has to probably be reworked when -- coercions and instance synthesis are fixed for concrete categories @@ -770,9 +777,10 @@ def counit : restrictScalars.{max v u₂,u₁,u₂} f ⋙ extendScalars f ⟶ letI m2 : Module R Y := Module.compHom Y f letI m2 : Module R Y' := Module.compHom Y' f apply LinearMap.ext; intro z - induction' z using TensorProduct.induction_on with s' y z₁ z₂ ih₁ ih₂ - · rw [map_zero, map_zero] - · dsimp + induction z using TensorProduct.induction_on with + | zero => rw [map_zero, map_zero] + | tmul s' y => + dsimp rw [ModuleCat.coe_comp, ModuleCat.coe_comp, Function.comp_apply, Function.comp_apply, ExtendScalars.map_tmul, restrictScalars.map_apply] -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644 @@ -781,8 +789,7 @@ def counit : restrictScalars.{max v u₂,u₁,u₂} f ⋙ extendScalars f ⟶ set s' : S := s' change s' • g y = g (s' • y) rw [map_smul] - · rw [map_add,map_add] - congr 1 + | add _ _ ih₁ ih₂ => rw [map_add, map_add]; congr 1 end ExtendRestrictScalarsAdj /-- Given commutative rings `R, S` and a ring hom `f : R →+* S`, the extension and restriction of @@ -802,9 +809,10 @@ def extendRestrictScalarsAdj {R : Type u₁} {S : Type u₂} [CommRing R] [CommR -- Porting note: once again reminding Lean of the instances letI m1 : Module R S := Module.compHom S f letI m2 : Module R Y := Module.compHom Y f - induction' x using TensorProduct.induction_on with s x _ _ _ _ - · rw [map_zero, map_zero] - · rw [ExtendRestrictScalarsAdj.homEquiv_symm_apply] + induction x using TensorProduct.induction_on with + | zero => rw [map_zero, map_zero] + | tmul => + rw [ExtendRestrictScalarsAdj.homEquiv_symm_apply] -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644 erw [ModuleCat.coe_comp] rw [Function.comp_apply, ExtendRestrictScalarsAdj.counit_app] @@ -813,8 +821,7 @@ def extendRestrictScalarsAdj {R : Type u₁} {S : Type u₂} [CommRing R] [CommR set_option tactic.skipAssignedInstances false in dsimp rw [TensorProduct.lift.tmul] rfl - · rw [map_add,map_add] - congr 1 + | add => rw [map_add, map_add]; congr 1 instance {R : Type u₁} {S : Type u₂} [CommRing R] [CommRing S] (f : R →+* S) : (extendScalars.{u₁, u₂, max u₂ w} f).IsLeftAdjoint := diff --git a/Mathlib/Algebra/Category/ModuleCat/Differentials/Presheaf.lean b/Mathlib/Algebra/Category/ModuleCat/Differentials/Presheaf.lean index 1c06b0681c172..b826d73a22b10 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Differentials/Presheaf.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Differentials/Presheaf.lean @@ -143,15 +143,17 @@ lemma app_apply (d : M.Derivation' φ') {X : Dᵒᵖ} (b : R.obj X) : section variable (d : ∀ (X : Dᵒᵖ), (M.obj X).Derivation (φ'.app X)) - (d_map : ∀ ⦃X Y : Dᵒᵖ⦄ (f : X ⟶ Y) (x : R.obj X), - (d Y).d ((R.map f) x) = (M.map f) ((d X).d x)) /-- Given a morphism of presheaves of commutative rings `φ'`, this is the in derivation `M.Derivation' φ'` that is given by a compatible family of derivations with values in the modules `M.obj X` for all `X`. -/ -def mk : M.Derivation' φ' where +def mk (d_map : ∀ ⦃X Y : Dᵒᵖ⦄ (f : X ⟶ Y) (x : R.obj X), + (d Y).d ((R.map f) x) = (M.map f) ((d X).d x)) : M.Derivation' φ' where d {X} := AddMonoidHom.mk' (d X).d (by simp) +variable (d_map : ∀ ⦃X Y : Dᵒᵖ⦄ (f : X ⟶ Y) (x : R.obj X), + (d Y).d ((R.map f) x) = (M.map f) ((d X).d x)) + @[simp] lemma mk_app (X : Dᵒᵖ) : (mk d d_map).app X = d X := rfl diff --git a/Mathlib/Algebra/Category/ModuleCat/FilteredColimits.lean b/Mathlib/Algebra/Category/ModuleCat/FilteredColimits.lean index 5beb3d1633472..16abcd3247283 100644 --- a/Mathlib/Algebra/Category/ModuleCat/FilteredColimits.lean +++ b/Mathlib/Algebra/Category/ModuleCat/FilteredColimits.lean @@ -51,7 +51,7 @@ abbrev M.mk : (Σ j, F.obj j) → M F := theorem M.mk_eq (x y : Σ j, F.obj j) (h : ∃ (k : J) (f : x.1 ⟶ k) (g : y.1 ⟶ k), F.map f x.2 = F.map g y.2) : M.mk F x = M.mk F y := - Quot.EqvGen_sound (Types.FilteredColimit.eqvGen_quot_rel_of_rel (F ⋙ forget (ModuleCat R)) x y h) + Quot.eqvGen_sound (Types.FilteredColimit.eqvGen_quot_rel_of_rel (F ⋙ forget (ModuleCat R)) x y h) /-- The "unlifted" version of scalar multiplication in the colimit. -/ def colimitSMulAux (r : R) (x : Σ j, F.obj j) : M F := @@ -80,7 +80,7 @@ theorem colimit_smul_mk_eq (r : R) (x : Σ j, F.obj j) : r • M.mk F x = M.mk F rfl private theorem colimitModule.one_smul (x : (M F)) : (1 : R) • x = x := by - refine Quot.inductionOn x ?_; clear x; intro x; cases' x with j x + refine Quot.inductionOn x ?_; clear x; intro x; obtain ⟨j, x⟩ := x erw [colimit_smul_mk_eq F 1 ⟨j, x⟩] simp rfl @@ -88,11 +88,11 @@ private theorem colimitModule.one_smul (x : (M F)) : (1 : R) • x = x := by -- Porting note (#11083): writing directly the `Module` instance makes things very slow. instance colimitMulAction : MulAction R (M F) where one_smul x := by - refine Quot.inductionOn x ?_; clear x; intro x; cases' x with j x + refine Quot.inductionOn x ?_; clear x; intro x; obtain ⟨j, x⟩ := x erw [colimit_smul_mk_eq F 1 ⟨j, x⟩, one_smul] rfl mul_smul r s x := by - refine Quot.inductionOn x ?_; clear x; intro x; cases' x with j x + refine Quot.inductionOn x ?_; clear x; intro x; obtain ⟨j, x⟩ := x erw [colimit_smul_mk_eq F (r * s) ⟨j, x⟩, colimit_smul_mk_eq F s ⟨j, x⟩, colimit_smul_mk_eq F r ⟨j, _⟩, mul_smul] @@ -102,12 +102,12 @@ instance colimitSMulWithZero : SMulWithZero R (M F) := erw [colimit_zero_eq _ (IsFiltered.nonempty.some : J), colimit_smul_mk_eq, smul_zero] rfl zero_smul := fun x => by - refine Quot.inductionOn x ?_; clear x; intro x; cases' x with j x + refine Quot.inductionOn x ?_; clear x; intro x; obtain ⟨j, x⟩ := x erw [colimit_smul_mk_eq, zero_smul, colimit_zero_eq _ j] rfl } private theorem colimitModule.add_smul (r s : R) (x : (M F)) : (r + s) • x = r • x + s • x := by - refine Quot.inductionOn x ?_; clear x; intro x; cases' x with j x + refine Quot.inductionOn x ?_; clear x; intro x; obtain ⟨j, x⟩ := x erw [colimit_smul_mk_eq, _root_.add_smul, colimit_smul_mk_eq, colimit_smul_mk_eq, colimit_add_mk_eq _ ⟨j, _⟩ ⟨j, _⟩ j (𝟙 j) (𝟙 j)] simp only [Functor.comp_obj, forget₂_obj, Functor.comp_map, CategoryTheory.Functor.map_id, @@ -118,7 +118,7 @@ instance colimitModule : Module R (M F) := { colimitMulAction F, colimitSMulWithZero F with smul_add := fun r x y => by - refine Quot.induction_on₂ x y ?_; clear x y; intro x y; cases' x with i x; cases' y with j y + refine Quot.induction_on₂ x y ?_; clear x y; intro x y; obtain ⟨i, x⟩ := x; obtain ⟨j, y⟩ := y erw [colimit_add_mk_eq _ ⟨i, _⟩ ⟨j, _⟩ (max' i j) (IsFiltered.leftToMax i j) (IsFiltered.rightToMax i j), colimit_smul_mk_eq, smul_add, colimit_smul_mk_eq, colimit_smul_mk_eq, colimit_add_mk_eq _ ⟨i, _⟩ ⟨j, _⟩ (max' i j) (IsFiltered.leftToMax i j) @@ -154,7 +154,7 @@ def colimitDesc (t : Cocone F) : colimit F ⟶ t.pt := (F ⋙ forget₂ (ModuleCatMax.{v, u} R) AddCommGrp.{max v u})).desc ((forget₂ (ModuleCat R) AddCommGrp.{max v u}).mapCocone t) with map_smul' := fun r x => by - refine Quot.inductionOn x ?_; clear x; intro x; cases' x with j x + refine Quot.inductionOn x ?_; clear x; intro x; obtain ⟨j, x⟩ := x erw [colimit_smul_mk_eq] exact LinearMap.map_smul (t.ι.app j) r x } diff --git a/Mathlib/Algebra/Category/ModuleCat/Free.lean b/Mathlib/Algebra/Category/ModuleCat/Free.lean index 7c67bb3e86b4f..ce028e860756f 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Free.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Free.lean @@ -14,12 +14,12 @@ This file proves results about linear independence and span in exact sequences o ## Main theorems * `linearIndependent_shortExact`: Given a short exact sequence `0 ⟶ X₁ ⟶ X₂ ⟶ X₃ ⟶ 0` of - `R`-modules and linearly independent families `v : ι → X₁` and `w : ι' → X₃`, we get a linearly + `R`-modules and linearly independent families `v : ι → X₁` and `w : ι' → X₃`, we get a linearly independent family `ι ⊕ ι' → X₂` * `span_rightExact`: Given an exact sequence `X₁ ⟶ X₂ ⟶ X₃ ⟶ 0` of `R`-modules and spanning - families `v : ι → X₁` and `w : ι' → X₃`, we get a spanning family `ι ⊕ ι' → X₂` + families `v : ι → X₁` and `w : ι' → X₃`, we get a spanning family `ι ⊕ ι' → X₂` * Using `linearIndependent_shortExact` and `span_rightExact`, we prove `free_shortExact`: In a - short exact sequence `0 ⟶ X₁ ⟶ X₂ ⟶ X₃ ⟶ 0` where `X₁` and `X₃` are free, `X₂` is free as well. + short exact sequence `0 ⟶ X₁ ⟶ X₂ ⟶ X₃ ⟶ 0` where `X₁` and `X₃` are free, `X₂` is free as well. ## Tags linear algebra, module, free @@ -61,8 +61,8 @@ include hv hm in v| u| w| ι → ι ⊕ ι' ← ι' ``` -where the top row is an exact sequence of modules and the maps on the bottom are `Sum.inl` and -`Sum.inr`. If `u` is injective and `v` and `w` are linearly independent, then `u` is linearly +where the top row is an exact sequence of modules and the maps on the bottom are `Sum.inl` and +`Sum.inr`. If `u` is injective and `v` and `w` are linearly independent, then `u` is linearly independent. -/ theorem linearIndependent_leftExact : LinearIndependent R u := by rw [linearIndependent_sum] @@ -76,7 +76,7 @@ end include hS' hv in /-- Given a short exact sequence `0 ⟶ X₁ ⟶ X₂ ⟶ X₃ ⟶ 0` of `R`-modules and linearly independent - families `v : ι → N` and `w : ι' → P`, we get a linearly independent family `ι ⊕ ι' → M` -/ + families `v : ι → N` and `w : ι' → P`, we get a linearly independent family `ι ⊕ ι' → M` -/ theorem linearIndependent_shortExact {w : ι' → S.X₃} (hw : LinearIndependent R w) : LinearIndependent R (Sum.elim (S.f ∘ v) (S.g.toFun.invFun ∘ w)) := by apply linearIndependent_leftExact hS'.exact hv _ hS'.mono_f rfl @@ -98,8 +98,8 @@ include hS in v| u| w| ι → ι ⊕ ι' ← ι' ``` -where the top row is an exact sequence of modules and the maps on the bottom are `Sum.inl` and -`Sum.inr`. If `v` spans `X₁` and `w` spans `X₃`, then `u` spans `X₂`. -/ +where the top row is an exact sequence of modules and the maps on the bottom are `Sum.inl` and +`Sum.inr`. If `v` spans `X₁` and `w` spans `X₃`, then `u` spans `X₂`. -/ theorem span_exact {β : Type*} {u : ι ⊕ β → S.X₂} (huv : u ∘ Sum.inl = S.f ∘ v) (hv : ⊤ ≤ span R (range v)) (hw : ⊤ ≤ span R (range (S.g ∘ u ∘ Sum.inr))) : @@ -135,7 +135,7 @@ theorem span_exact {β : Type*} {u : ι ⊕ β → S.X₂} (huv : u ∘ Sum.inl include hS in /-- Given an exact sequence `X₁ ⟶ X₂ ⟶ X₃ ⟶ 0` of `R`-modules and spanning - families `v : ι → X₁` and `w : ι' → X₃`, we get a spanning family `ι ⊕ ι' → X₂` -/ + families `v : ι → X₁` and `w : ι' → X₃`, we get a spanning family `ι ⊕ ι' → X₂` -/ theorem span_rightExact {w : ι' → S.X₃} (hv : ⊤ ≤ span R (range v)) (hw : ⊤ ≤ span R (range w)) (hE : Epi S.g) : ⊤ ≤ span R (range (Sum.elim (S.f ∘ v) (S.g.toFun.invFun ∘ w))) := by @@ -149,8 +149,8 @@ theorem span_rightExact {w : ι' → S.X₃} (hv : ⊤ ≤ span R (range v)) end Span -/-- In a short exact sequence `0 ⟶ X₁ ⟶ X₂ ⟶ X₃ ⟶ 0`, given bases for `X₁` and `X₃` -indexed by `ι` and `ι'` respectively, we get a basis for `X₂` indexed by `ι ⊕ ι'`. -/ +/-- In a short exact sequence `0 ⟶ X₁ ⟶ X₂ ⟶ X₃ ⟶ 0`, given bases for `X₁` and `X₃` +indexed by `ι` and `ι'` respectively, we get a basis for `X₂` indexed by `ι ⊕ ι'`. -/ noncomputable def Basis.ofShortExact (bN : Basis ι R S.X₁) (bP : Basis ι' R S.X₃) : Basis (ι ⊕ ι') R S.X₂ := @@ -159,7 +159,7 @@ def Basis.ofShortExact include hS' -/-- In a short exact sequence `0 ⟶ X₁ ⟶ X₂ ⟶ X₃ ⟶ 0`, if `X₁` and `X₃` are free, +/-- In a short exact sequence `0 ⟶ X₁ ⟶ X₂ ⟶ X₃ ⟶ 0`, if `X₁` and `X₃` are free, then `X₂` is free. -/ theorem free_shortExact [Module.Free R S.X₁] [Module.Free R S.X₃] : Module.Free R S.X₂ := diff --git a/Mathlib/Algebra/Category/ModuleCat/Monoidal/Basic.lean b/Mathlib/Algebra/Category/ModuleCat/Monoidal/Basic.lean index 8644e70e9cf72..666c67174d69b 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Monoidal/Basic.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Monoidal/Basic.lean @@ -256,21 +256,21 @@ open Opposite -- Porting note: simp wasn't firing but rw was, annoying instance : MonoidalPreadditive (ModuleCat.{u} R) := by refine ⟨?_, ?_, ?_, ?_⟩ - · dsimp only [autoParam]; intros + · intros refine TensorProduct.ext (LinearMap.ext fun x => LinearMap.ext fun y => ?_) simp only [LinearMap.compr₂_apply, TensorProduct.mk_apply] rw [LinearMap.zero_apply] -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644 erw [MonoidalCategory.whiskerLeft_apply] rw [LinearMap.zero_apply, TensorProduct.tmul_zero] - · dsimp only [autoParam]; intros + · intros refine TensorProduct.ext (LinearMap.ext fun x => LinearMap.ext fun y => ?_) simp only [LinearMap.compr₂_apply, TensorProduct.mk_apply] rw [LinearMap.zero_apply] -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644 erw [MonoidalCategory.whiskerRight_apply] rw [LinearMap.zero_apply, TensorProduct.zero_tmul] - · dsimp only [autoParam]; intros + · intros refine TensorProduct.ext (LinearMap.ext fun x => LinearMap.ext fun y => ?_) simp only [LinearMap.compr₂_apply, TensorProduct.mk_apply] rw [LinearMap.add_apply] @@ -278,7 +278,7 @@ instance : MonoidalPreadditive (ModuleCat.{u} R) := by erw [MonoidalCategory.whiskerLeft_apply, MonoidalCategory.whiskerLeft_apply] erw [MonoidalCategory.whiskerLeft_apply] rw [LinearMap.add_apply, TensorProduct.tmul_add] - · dsimp only [autoParam]; intros + · intros refine TensorProduct.ext (LinearMap.ext fun x => LinearMap.ext fun y => ?_) simp only [LinearMap.compr₂_apply, TensorProduct.mk_apply] rw [LinearMap.add_apply] @@ -290,14 +290,14 @@ instance : MonoidalPreadditive (ModuleCat.{u} R) := by -- Porting note: simp wasn't firing but rw was, annoying instance : MonoidalLinear R (ModuleCat.{u} R) := by refine ⟨?_, ?_⟩ - · dsimp only [autoParam]; intros + · intros refine TensorProduct.ext (LinearMap.ext fun x => LinearMap.ext fun y => ?_) simp only [LinearMap.compr₂_apply, TensorProduct.mk_apply] rw [LinearMap.smul_apply] -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644 erw [MonoidalCategory.whiskerLeft_apply, MonoidalCategory.whiskerLeft_apply] rw [LinearMap.smul_apply, TensorProduct.tmul_smul] - · dsimp only [autoParam]; intros + · intros refine TensorProduct.ext (LinearMap.ext fun x => LinearMap.ext fun y => ?_) simp only [LinearMap.compr₂_apply, TensorProduct.mk_apply] rw [LinearMap.smul_apply] diff --git a/Mathlib/Algebra/Category/ModuleCat/Presheaf.lean b/Mathlib/Algebra/Category/ModuleCat/Presheaf.lean index 622c9e6a838a6..5a9b76b43035b 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Presheaf.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Presheaf.lean @@ -292,7 +292,7 @@ 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 X Y f => by ext x; apply naturality } + naturality := fun _ _ f => AddCommGrp.ext (naturality f) } map_smul X := (app X).map_smul @[simp] diff --git a/Mathlib/Algebra/Category/ModuleCat/Presheaf/Abelian.lean b/Mathlib/Algebra/Category/ModuleCat/Presheaf/Abelian.lean index 80d80075b9e8a..42747bed79af5 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Presheaf/Abelian.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Presheaf/Abelian.lean @@ -22,7 +22,7 @@ namespace PresheafOfModules variable {C : Type u₁} [Category.{v₁} C] (R : Cᵒᵖ ⥤ RingCat.{u}) noncomputable instance : NormalEpiCategory (PresheafOfModules.{v} R) where - normalEpiOfEpi p _ := NormalEpi.mk _ (kernel.ι p) (kernel.condition _) + normalEpiOfEpi p _ := NormalEpi.mk _ (kernel.ι p) (kernel.condition _) (evaluationJointlyReflectsColimits _ _ (fun _ => Abelian.isColimitMapCoconeOfCokernelCoforkOfπ _ _)) diff --git a/Mathlib/Algebra/Category/ModuleCat/Presheaf/Limits.lean b/Mathlib/Algebra/Category/ModuleCat/Presheaf/Limits.lean index 4fd891084e89b..d547a5c07236e 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Presheaf/Limits.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Presheaf/Limits.lean @@ -6,7 +6,7 @@ Authors: Joël Riou import Mathlib.Algebra.Category.ModuleCat.Presheaf import Mathlib.Algebra.Category.ModuleCat.ChangeOfRings import Mathlib.CategoryTheory.Limits.Preserves.Limits -import Mathlib.CategoryTheory.Limits.FunctorCategory +import Mathlib.CategoryTheory.Limits.FunctorCategory.Basic /-! # Limits in categories of presheaves of modules diff --git a/Mathlib/Algebra/Category/ModuleCat/Presheaf/Sheafify.lean b/Mathlib/Algebra/Category/ModuleCat/Presheaf/Sheafify.lean index 69db169f3d58c..0d10d6d1547c9 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Presheaf/Sheafify.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Presheaf/Sheafify.lean @@ -362,13 +362,12 @@ variable {M₀' : PresheafOfModules.{v} R₀} {A' : Sheaf J AddCommGrp.{v}} (φ' : M₀'.presheaf ⟶ A'.val) [Presheaf.IsLocallyInjective J φ'] [Presheaf.IsLocallySurjective J φ'] (τ₀ : M₀ ⟶ M₀') (τ : A ⟶ A') - (fac : τ₀.hom ≫ φ' = φ ≫ τ.val) /-- The morphism of sheaves of modules `sheafify α φ ⟶ sheafify α φ'` induced by morphisms `τ₀ : M₀ ⟶ M₀'` and `τ : A ⟶ A'` which satisfy `τ₀.hom ≫ φ' = φ ≫ τ.val`. -/ @[simps] -def sheafifyMap : sheafify α φ ⟶ sheafify α φ' where +def sheafifyMap (fac : τ₀.hom ≫ φ' = φ ≫ τ.val) : sheafify α φ ⟶ sheafify α φ' where val := { hom := τ.val map_smul := by diff --git a/Mathlib/Algebra/Category/ModuleCat/Projective.lean b/Mathlib/Algebra/Category/ModuleCat/Projective.lean index 80b2ec54bb07d..cb26babea2730 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Projective.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Projective.lean @@ -59,11 +59,11 @@ instance moduleCat_enoughProjectives : EnoughProjectives (ModuleCat.{max u v} R) f := Finsupp.basisSingleOne.constr ℕ _root_.id epi := (epi_iff_range_eq_top _).mpr (range_eq_top.2 fun m => ⟨Finsupp.single m (1 : R), by - -- Porting note: simp [Finsupp.total_single] fails but rw succeeds + -- Porting note: simp [Finsupp.linearCombination_single] fails but rw succeeds dsimp [Basis.constr] simp only [Finsupp.lmapDomain_id, comp_id] -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644 - erw [Finsupp.total_single] + erw [Finsupp.linearCombination_single] rw [one_smul] rfl ⟩) }⟩ diff --git a/Mathlib/Algebra/Category/ModuleCat/Sheaf/ChangeOfRings.lean b/Mathlib/Algebra/Category/ModuleCat/Sheaf/ChangeOfRings.lean index e40d0e818c4af..906a646c6048c 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Sheaf/ChangeOfRings.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Sheaf/ChangeOfRings.lean @@ -43,12 +43,12 @@ end SheafOfModules namespace PresheafOfModules variable {R R' : Cᵒᵖ ⥤ RingCat.{u}} (α : R ⟶ R') - {M₁ M₂ : PresheafOfModules.{v} R'} (hM₂ : Presheaf.IsSheaf J M₂.presheaf) - [Presheaf.IsLocallySurjective J α] + {M₁ M₂ : PresheafOfModules.{v} R'} /-- The functor `PresheafOfModules.restrictScalars α` induces bijection on morphisms if `α` is locally surjective and the target presheaf is a sheaf. -/ -noncomputable def restrictHomEquivOfIsLocallySurjective : +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 := diff --git a/Mathlib/Algebra/Category/MonCat/Colimits.lean b/Mathlib/Algebra/Category/MonCat/Colimits.lean index 87b46212fbf27..98bd6071b109b 100644 --- a/Mathlib/Algebra/Category/MonCat/Colimits.lean +++ b/Mathlib/Algebra/Category/MonCat/Colimits.lean @@ -212,14 +212,17 @@ def colimitIsColimit : IsColimit (colimitCocone F) where desc s := descMorphism F s uniq s m w := by ext x - induction' x using Quot.inductionOn with x - induction' x with j x x y hx hy - · change _ = s.ι.app j _ + induction x using Quot.inductionOn with | h x => ?_ + induction x with + | of j => + change _ = s.ι.app j _ rw [← w j] rfl - · rw [quot_one, map_one] + | one => + rw [quot_one, map_one] rfl - · rw [quot_mul, map_mul, hx, hy] + | mul x y hx hy => + rw [quot_mul, map_mul, hx, hy] dsimp [descMorphism, DFunLike.coe, descFun] simp only [← quot_mul, descFunLift] diff --git a/Mathlib/Algebra/Category/MonCat/FilteredColimits.lean b/Mathlib/Algebra/Category/MonCat/FilteredColimits.lean index 8ef1a354bfcd7..9624ff56fed29 100644 --- a/Mathlib/Algebra/Category/MonCat/FilteredColimits.lean +++ b/Mathlib/Algebra/Category/MonCat/FilteredColimits.lean @@ -56,7 +56,7 @@ noncomputable abbrev M.mk : (Σ j, F.obj j) → M.{v, u} F := theorem M.mk_eq (x y : Σ j, F.obj j) (h : ∃ (k : J) (f : x.1 ⟶ k) (g : y.1 ⟶ k), F.map f x.2 = F.map g y.2) : M.mk.{v, u} F x = M.mk F y := - Quot.EqvGen_sound (Types.FilteredColimit.eqvGen_quot_rel_of_rel (F ⋙ forget MonCat) x y h) + Quot.eqvGen_sound (Types.FilteredColimit.eqvGen_quot_rel_of_rel (F ⋙ forget MonCat) x y h) variable [IsFiltered J] @@ -99,7 +99,7 @@ noncomputable def colimitMulAux (x y : Σ j, F.obj j) : M.{v, u} F := theorem colimitMulAux_eq_of_rel_left {x x' y : Σ j, F.obj j} (hxx' : Types.FilteredColimit.Rel (F ⋙ forget MonCat) x x') : colimitMulAux.{v, u} F x y = colimitMulAux.{v, u} F x' y := by - cases' x with j₁ x; cases' y with j₂ y; cases' x' with j₃ x' + obtain ⟨j₁, x⟩ := x; obtain ⟨j₂, y⟩ := y; obtain ⟨j₃, x'⟩ := x' obtain ⟨l, f, g, hfg⟩ := hxx' simp? at hfg says simp only [Functor.comp_obj, Functor.comp_map, forget_map] at hfg obtain ⟨s, α, β, γ, h₁, h₂, h₃⟩ := @@ -122,7 +122,7 @@ theorem colimitMulAux_eq_of_rel_left {x x' y : Σ j, F.obj j} theorem colimitMulAux_eq_of_rel_right {x y y' : Σ j, F.obj j} (hyy' : Types.FilteredColimit.Rel (F ⋙ forget MonCat) y y') : colimitMulAux.{v, u} F x y = colimitMulAux.{v, u} F x y' := by - cases' y with j₁ y; cases' x with j₂ x; cases' y' with j₃ y' + obtain ⟨j₁, y⟩ := y; obtain ⟨j₂, x⟩ := x; obtain ⟨j₃, y'⟩ := y' obtain ⟨l, f, g, hfg⟩ := hyy' simp only [Functor.comp_obj, Functor.comp_map, forget_map] at hfg obtain ⟨s, α, β, γ, h₁, h₂, h₃⟩ := @@ -164,7 +164,7 @@ using a custom object `k` and morphisms `f : x.1 ⟶ k` and `g : y.1 ⟶ k`. `x` and `y`, using a custom object `k` and morphisms `f : x.1 ⟶ k` and `g : y.1 ⟶ k`."] theorem colimit_mul_mk_eq (x y : Σ j, F.obj j) (k : J) (f : x.1 ⟶ k) (g : y.1 ⟶ k) : M.mk.{v, u} F x * M.mk F y = M.mk F ⟨k, F.map f x.2 * F.map g y.2⟩ := by - cases' x with j₁ x; cases' y with j₂ y + obtain ⟨j₁, x⟩ := x; obtain ⟨j₂, y⟩ := y obtain ⟨s, α, β, h₁, h₂⟩ := IsFiltered.bowtie (IsFiltered.leftToMax j₁ j₂) f (IsFiltered.rightToMax j₁ j₂) g refine M.mk_eq F _ _ ?_ @@ -183,7 +183,7 @@ noncomputable instance colimitMulOneClass : MulOneClass (M.{v, u} F) := one_mul := fun x => by refine Quot.inductionOn x ?_ intro x - cases' x with j x + obtain ⟨j, x⟩ := x rw [colimit_one_eq F j, colimit_mul_mk_eq F ⟨j, 1⟩ ⟨j, x⟩ j (𝟙 j) (𝟙 j), MonoidHom.map_one, one_mul, F.map_id] -- Porting note: `id_apply` does not work here, but the two sides are def-eq @@ -191,7 +191,7 @@ noncomputable instance colimitMulOneClass : MulOneClass (M.{v, u} F) := mul_one := fun x => by refine Quot.inductionOn x ?_ intro x - cases' x with j x + obtain ⟨j, x⟩ := x rw [colimit_one_eq F j, colimit_mul_mk_eq F ⟨j, x⟩ ⟨j, 1⟩ j (𝟙 j) (𝟙 j), MonoidHom.map_one, mul_one, F.map_id] -- Porting note: `id_apply` does not work here, but the two sides are def-eq @@ -204,9 +204,9 @@ noncomputable instance colimitMonoid : Monoid (M.{v, u} F) := refine Quot.induction_on₃ x y z ?_ clear x y z intro x y z - cases' x with j₁ x - cases' y with j₂ y - cases' z with j₃ z + obtain ⟨j₁, x⟩ := x + obtain ⟨j₂, y⟩ := y + obtain ⟨j₃, z⟩ := z change M.mk F _ * M.mk F _ * M.mk F _ = M.mk F _ * M.mk F _ dsimp rw [colimit_mul_mk_eq F ⟨j₁, x⟩ ⟨j₂, y⟩ (IsFiltered.max j₁ (IsFiltered.max j₂ j₃)) @@ -272,8 +272,8 @@ def colimitDesc (t : Cocone F) : colimit.{v, u} F ⟶ t.pt where refine Quot.induction_on₂ x y ?_ clear x y intro x y - cases' x with i x - cases' y with j y + obtain ⟨i, x⟩ := x + obtain ⟨j, y⟩ := y rw [colimit_mul_mk_eq F ⟨i, x⟩ ⟨j, y⟩ (max' i j) (IsFiltered.leftToMax i j) (IsFiltered.rightToMax i j)] dsimp [Types.TypeMax.colimitCoconeIsColimit] diff --git a/Mathlib/Algebra/Category/Ring/FilteredColimits.lean b/Mathlib/Algebra/Category/Ring/FilteredColimits.lean index 99fcc64a9f41a..9b383c982cbde 100644 --- a/Mathlib/Algebra/Category/Ring/FilteredColimits.lean +++ b/Mathlib/Algebra/Category/Ring/FilteredColimits.lean @@ -62,7 +62,7 @@ instance colimitSemiring : Semiring.{max v u} <| R.{v, u} F := (F ⋙ forget₂ SemiRingCat AddCommMonCat.{max v u}) with mul_zero := fun x => by refine Quot.inductionOn x ?_; clear x; intro x - cases' x with j x + obtain ⟨j, x⟩ := x erw [colimit_zero_eq _ j, colimit_mul_mk_eq _ ⟨j, _⟩ ⟨j, _⟩ j (𝟙 j) (𝟙 j)] rw [CategoryTheory.Functor.map_id] dsimp @@ -70,7 +70,7 @@ instance colimitSemiring : Semiring.{max v u} <| R.{v, u} F := rfl zero_mul := fun x => by refine Quot.inductionOn x ?_; clear x; intro x - cases' x with j x + obtain ⟨j, x⟩ := x erw [colimit_zero_eq _ j, colimit_mul_mk_eq _ ⟨j, _⟩ ⟨j, _⟩ j (𝟙 j) (𝟙 j)] rw [CategoryTheory.Functor.map_id] dsimp @@ -78,7 +78,7 @@ instance colimitSemiring : Semiring.{max v u} <| R.{v, u} F := rfl left_distrib := fun x y z => by refine Quot.induction_on₃ x y z ?_; clear x y z; intro x y z - cases' x with j₁ x; cases' y with j₂ y; cases' z with j₃ z + obtain ⟨j₁, x⟩ := x; obtain ⟨j₂, y⟩ := y; obtain ⟨j₃, z⟩ := z let k := IsFiltered.max₃ j₁ j₂ j₃ let f := IsFiltered.firstToMax₃ j₁ j₂ j₃ let g := IsFiltered.secondToMax₃ j₁ j₂ j₃ @@ -91,7 +91,7 @@ instance colimitSemiring : Semiring.{max v u} <| R.{v, u} F := rfl right_distrib := fun x y z => by refine Quot.induction_on₃ x y z ?_; clear x y z; intro x y z - cases' x with j₁ x; cases' y with j₂ y; cases' z with j₃ z + obtain ⟨j₁, x⟩ := x; obtain ⟨j₂, y⟩ := y; obtain ⟨j₃, z⟩ := z let k := IsFiltered.max₃ j₁ j₂ j₃ let f := IsFiltered.firstToMax₃ j₁ j₂ j₃ let g := IsFiltered.secondToMax₃ j₁ j₂ j₃ diff --git a/Mathlib/Algebra/CharP/ExpChar.lean b/Mathlib/Algebra/CharP/ExpChar.lean index ef45c8099756c..3c3955406e021 100644 --- a/Mathlib/Algebra/CharP/ExpChar.lean +++ b/Mathlib/Algebra/CharP/ExpChar.lean @@ -55,12 +55,12 @@ instance (S : Type*) [Semiring S] (p) [ExpChar R p] [ExpChar S p] : ExpChar (R variable {R} in /-- The exponential characteristic is unique. -/ theorem ExpChar.eq {p q : ℕ} (hp : ExpChar R p) (hq : ExpChar R q) : p = q := by - cases' hp with hp _ hp' hp - · cases' hq with hq _ hq' hq - exacts [rfl, False.elim (Nat.not_prime_zero (CharP.eq R hq (CharP.ofCharZero R) ▸ hq'))] - · cases' hq with hq _ hq' hq - exacts [False.elim (Nat.not_prime_zero (CharP.eq R hp (CharP.ofCharZero R) ▸ hp')), - CharP.eq R hp hq] + rcases hp with ⟨hp⟩ | ⟨hp'⟩ + · rcases hq with hq | hq' + exacts [rfl, False.elim (Nat.not_prime_zero (CharP.eq R ‹_› (CharP.ofCharZero R) ▸ hq'))] + · rcases hq with hq | hq' + exacts [False.elim (Nat.not_prime_zero (CharP.eq R ‹_› (CharP.ofCharZero R) ▸ hp')), + CharP.eq R ‹_› ‹_›] theorem ExpChar.congr {p : ℕ} (q : ℕ) [hq : ExpChar R q] (h : q = p) : ExpChar R p := h ▸ hq @@ -68,7 +68,7 @@ theorem ExpChar.congr {p : ℕ} (q : ℕ) [hq : ExpChar R q] (h : q = p) : ExpCh noncomputable def ringExpChar (R : Type*) [NonAssocSemiring R] : ℕ := max (ringChar R) 1 theorem ringExpChar.eq (q : ℕ) [h : ExpChar R q] : ringExpChar R = q := by - cases' h with _ _ h _ + rcases h with _ | h · haveI := CharP.ofCharZero R rw [ringExpChar, ringChar.eq R 0]; rfl rw [ringExpChar, ringChar.eq R q] @@ -80,16 +80,16 @@ theorem ringExpChar.eq_one (R : Type*) [NonAssocSemiring R] [CharZero R] : ringE /-- The exponential characteristic is one if the characteristic is zero. -/ theorem expChar_one_of_char_zero (q : ℕ) [hp : CharP R 0] [hq : ExpChar R q] : q = 1 := by - cases' hq with q hq_one hq_prime hq_hchar + rcases hq with q | hq_prime · rfl - · exact False.elim <| hq_prime.ne_zero <| hq_hchar.eq R hp + · exact False.elim <| hq_prime.ne_zero <| ‹CharP R q›.eq R hp /-- The characteristic equals the exponential characteristic iff the former is prime. -/ theorem char_eq_expChar_iff (p q : ℕ) [hp : CharP R p] [hq : ExpChar R q] : p = q ↔ p.Prime := by - cases' hq with q hq_one hq_prime hq_hchar + rcases hq with q | hq_prime · rw [(CharP.eq R hp inferInstance : p = 0)] decide - · exact ⟨fun hpq => hpq.symm ▸ hq_prime, fun _ => CharP.eq R hp hq_hchar⟩ + · exact ⟨fun hpq => hpq.symm ▸ hq_prime, fun _ => CharP.eq R hp ‹CharP R q›⟩ /-- The exponential characteristic is a prime number or one. See also `CharP.char_is_prime_or_zero`. -/ @@ -138,7 +138,7 @@ variable [NoZeroDivisors R] /-- A helper lemma: the characteristic is prime if it is non-zero. -/ theorem char_prime_of_ne_zero {p : ℕ} [hp : CharP R p] (p_ne_zero : p ≠ 0) : Nat.Prime p := by - cases' CharP.char_is_prime_or_zero R p with h h + rcases CharP.char_is_prime_or_zero R p with h | h · exact h · contradiction @@ -173,7 +173,7 @@ as `R`. -/ theorem expChar_of_injective_ringHom {R A : Type*} [Semiring R] [Semiring A] {f : R →+* A} (h : Function.Injective f) (q : ℕ) [hR : ExpChar R q] : ExpChar A q := by - cases' hR with _ _ hprime _ + rcases hR with _ | hprime · haveI := charZero_of_injective_ringHom h; exact .zero haveI := charP_of_injective_ringHom h q; exact .prime hprime @@ -199,61 +199,61 @@ theorem expChar_of_injective_algebraMap {R A : Type*} theorem add_pow_expChar_of_commute [Semiring R] {q : ℕ} [hR : ExpChar R q] (x y : R) (h : Commute x y) : (x + y) ^ q = x ^ q + y ^ q := by - cases' hR with _ _ hprime _ + rcases hR with _ | hprime · simp only [pow_one] haveI := Fact.mk hprime; exact add_pow_char_of_commute R x y h theorem add_pow_expChar_pow_of_commute [Semiring R] {q : ℕ} [hR : ExpChar R q] {n : ℕ} (x y : R) (h : Commute x y) : (x + y) ^ q ^ n = x ^ q ^ n + y ^ q ^ n := by - cases' hR with _ _ hprime _ + rcases hR with _ | hprime · simp only [one_pow, pow_one] haveI := Fact.mk hprime; exact add_pow_char_pow_of_commute R x y h theorem sub_pow_expChar_of_commute [Ring R] {q : ℕ} [hR : ExpChar R q] (x y : R) (h : Commute x y) : (x - y) ^ q = x ^ q - y ^ q := by - cases' hR with _ _ hprime _ + rcases hR with _ | hprime · simp only [pow_one] haveI := Fact.mk hprime; exact sub_pow_char_of_commute R x y h theorem sub_pow_expChar_pow_of_commute [Ring R] {q : ℕ} [hR : ExpChar R q] {n : ℕ} (x y : R) (h : Commute x y) : (x - y) ^ q ^ n = x ^ q ^ n - y ^ q ^ n := by - cases' hR with _ _ hprime _ + rcases hR with _ | hprime · simp only [one_pow, pow_one] haveI := Fact.mk hprime; exact sub_pow_char_pow_of_commute R x y h theorem add_pow_expChar [CommSemiring R] {q : ℕ} [hR : ExpChar R q] (x y : R) : (x + y) ^ q = x ^ q + y ^ q := by - cases' hR with _ _ hprime _ + rcases hR with _ | hprime · simp only [pow_one] haveI := Fact.mk hprime; exact add_pow_char R x y theorem add_pow_expChar_pow [CommSemiring R] {q : ℕ} [hR : ExpChar R q] {n : ℕ} (x y : R) : (x + y) ^ q ^ n = x ^ q ^ n + y ^ q ^ n := by - cases' hR with _ _ hprime _ + rcases hR with _ | hprime · simp only [one_pow, pow_one] haveI := Fact.mk hprime; exact add_pow_char_pow R x y theorem sub_pow_expChar [CommRing R] {q : ℕ} [hR : ExpChar R q] (x y : R) : (x - y) ^ q = x ^ q - y ^ q := by - cases' hR with _ _ hprime _ + rcases hR with _ | hprime · simp only [pow_one] haveI := Fact.mk hprime; exact sub_pow_char R x y theorem sub_pow_expChar_pow [CommRing R] {q : ℕ} [hR : ExpChar R q] {n : ℕ} (x y : R) : (x - y) ^ q ^ n = x ^ q ^ n - y ^ q ^ n := by - cases' hR with _ _ hprime _ + rcases hR with _ | hprime · simp only [one_pow, pow_one] haveI := Fact.mk hprime; exact sub_pow_char_pow R x y theorem ExpChar.neg_one_pow_expChar [Ring R] (q : ℕ) [hR : ExpChar R q] : (-1 : R) ^ q = -1 := by - cases' hR with _ _ hprime _ + rcases hR with _ | hprime · simp only [pow_one] haveI := Fact.mk hprime; exact CharP.neg_one_pow_char R q theorem ExpChar.neg_one_pow_expChar_pow [Ring R] (q n : ℕ) [hR : ExpChar R q] : (-1 : R) ^ q ^ n = -1 := by - cases' hR with _ _ hprime _ + rcases hR with _ | hprime · simp only [one_pow, pow_one] haveI := Fact.mk hprime; exact CharP.neg_one_pow_char_pow R q n diff --git a/Mathlib/Algebra/CharP/IntermediateField.lean b/Mathlib/Algebra/CharP/IntermediateField.lean index 9854b6a841e48..a577f00bd38d8 100644 --- a/Mathlib/Algebra/CharP/IntermediateField.lean +++ b/Mathlib/Algebra/CharP/IntermediateField.lean @@ -3,8 +3,9 @@ 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.FieldTheory.IntermediateField import Mathlib.Algebra.CharP.ExpChar +import Mathlib.FieldTheory.IntermediateField.Basic +import Mathlib.Algebra.EuclideanDomain.Field /-! diff --git a/Mathlib/Algebra/CharP/LocalRing.lean b/Mathlib/Algebra/CharP/LocalRing.lean index adc445b11a41a..645df7bf14817 100644 --- a/Mathlib/Algebra/CharP/LocalRing.lean +++ b/Mathlib/Algebra/CharP/LocalRing.lean @@ -30,7 +30,7 @@ theorem charP_zero_or_prime_power (R : Type*) [CommRing R] [LocalRing R] (q : let r := ringChar K let n := q.factorization r -- `r := char(R/m)` is either prime or zero: - cases' CharP.char_is_prime_or_zero K r with r_prime r_zero + rcases CharP.char_is_prime_or_zero K r with r_prime | r_zero · let a := q / r ^ n -- If `r` is prime, we can write it as `r = a * q^n` ... have q_eq_a_mul_rn : q = r ^ n * a := by rw [Nat.mul_div_cancel' (Nat.ord_proj_dvd q r)] @@ -47,7 +47,6 @@ theorem charP_zero_or_prime_power (R : Type*) [CommRing R] [LocalRing R] (q : have r_dvd_a := (ringChar.spec K a).1 a_cast_zero exact absurd r_dvd_a r_ne_dvd_a -- Let `b` be the inverse of `a`. - cases' a_unit.exists_left_inv with a_inv h_inv_mul_a have rn_cast_zero : ↑(r ^ n) = (0 : R) := by rw [← @mul_one R _ ↑(r ^ n), mul_comm, ← Classical.choose_spec a_unit.exists_left_inv, mul_assoc, ← Nat.cast_mul, ← q_eq_a_mul_rn, CharP.cast_eq_zero R q] diff --git a/Mathlib/Algebra/CharZero/Defs.lean b/Mathlib/Algebra/CharZero/Defs.lean index c583ee8ed3603..8f2cf74d4cef2 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.Tactic.Cases import Mathlib.Algebra.NeZero import Mathlib.Logic.Function.Basic @@ -47,16 +46,12 @@ variable {R : Type*} theorem charZero_of_inj_zero [AddGroupWithOne R] (H : ∀ n : ℕ, (n : R) = 0 → n = 0) : CharZero R := ⟨@fun m n h => by - induction' m with m ih generalizing n - · rw [H n] - rw [← h, Nat.cast_zero] - - cases' n with n - · apply H - rw [h, Nat.cast_zero] - - simp only [Nat.cast_succ, add_right_cancel_iff] at h - rwa [ih]⟩ + induction m generalizing n with + | zero => rw [H n]; rw [← h, Nat.cast_zero] + | succ m ih => + cases n + · apply H; rw [h, Nat.cast_zero] + · simp only [Nat.cast_succ, add_right_cancel_iff] at h; rwa [ih]⟩ namespace Nat diff --git a/Mathlib/Algebra/ContinuedFractions/Basic.lean b/Mathlib/Algebra/ContinuedFractions/Basic.lean index cdf31ebeb15da..6a34dbcebe789 100644 --- a/Mathlib/Algebra/ContinuedFractions/Basic.lean +++ b/Mathlib/Algebra/ContinuedFractions/Basic.lean @@ -41,7 +41,7 @@ numerics, number theory, approximations, fractions -- Fix a carrier `α`. variable (α : Type*) -/-!### Definitions-/ +/-!### Definitions -/ -- Porting note: Originally `protected structure GenContFract.Pair` /-- We collect a partial numerator `aᵢ` and partial denominator `bᵢ` in a pair `⟨aᵢ, bᵢ⟩`. -/ diff --git a/Mathlib/Algebra/ContinuedFractions/Computation/ApproximationCorollaries.lean b/Mathlib/Algebra/ContinuedFractions/Computation/ApproximationCorollaries.lean index 22eed92dcfa54..34d81f490bea6 100644 --- a/Mathlib/Algebra/ContinuedFractions/Computation/ApproximationCorollaries.lean +++ b/Mathlib/Algebra/ContinuedFractions/Computation/ApproximationCorollaries.lean @@ -37,11 +37,9 @@ Moreover, we show the convergence of the continued fractions computations, that convergence, fractions -/ - variable {K : Type*} (v : K) [LinearOrderedField K] [FloorRing K] open GenContFract (of) -open GenContFract open scoped Topology namespace GenContFract @@ -79,7 +77,7 @@ theorem of_convergence_epsilon : exists N intro n n_ge_N let g := of v - cases' Decidable.em (g.TerminatedAt n) with terminatedAt_n not_terminatedAt_n + rcases Decidable.em (g.TerminatedAt n) with terminatedAt_n | not_terminatedAt_n · have : v = g.convs n := of_correctness_of_terminatedAt terminatedAt_n have : v - g.convs n = 0 := sub_eq_zero.mpr this rw [this] diff --git a/Mathlib/Algebra/ContinuedFractions/Computation/Approximations.lean b/Mathlib/Algebra/ContinuedFractions/Computation/Approximations.lean index 31e49bd225ba9..be6b7195e1964 100644 --- a/Mathlib/Algebra/ContinuedFractions/Computation/Approximations.lean +++ b/Mathlib/Algebra/ContinuedFractions/Computation/Approximations.lean @@ -111,7 +111,7 @@ theorem succ_nth_stream_b_le_nth_stream_fr_inv {ifp_n ifp_succ_n : IntFractPair (succ_nth_stream_eq : IntFractPair.stream v (n + 1) = some ifp_succ_n) : (ifp_succ_n.b : K) ≤ ifp_n.fr⁻¹ := by suffices (⌊ifp_n.fr⁻¹⌋ : K) ≤ ifp_n.fr⁻¹ by - cases' ifp_n with _ ifp_n_fr + obtain ⟨_, ifp_n_fr⟩ := ifp_n have : ifp_n_fr ≠ 0 := by intro h simp [h, IntFractPair.stream, nth_stream_eq] at succ_nth_stream_eq @@ -264,9 +264,9 @@ theorem zero_le_of_contsAux_b : 0 ≤ ((of v).contsAux n).b := by induction n with | zero => rfl | succ n IH => - cases' Decidable.em <| g.TerminatedAt (n - 1) with terminated not_terminated + rcases Decidable.em <| g.TerminatedAt (n - 1) with terminated | not_terminated · -- terminating case - cases' n with n + rcases n with - | n · simp [zero_le_one] · have : g.contsAux (n + 2) = g.contsAux (n + 1) := contsAux_stable_step_of_terminated terminated @@ -299,7 +299,7 @@ theorem le_of_succ_get?_den {b : K} /-- Shows that the sequence of denominators is monotone, that is `Bₙ ≤ Bₙ₊₁`. -/ theorem of_den_mono : (of v).dens n ≤ (of v).dens (n + 1) := by let g := of v - cases' Decidable.em <| g.partDens.TerminatedAt n with terminated not_terminated + rcases Decidable.em <| g.partDens.TerminatedAt n with terminated | not_terminated · have : g.partDens.get? n = none := by rwa [Stream'.Seq.TerminatedAt] at terminated have : g.TerminatedAt n := terminatedAt_iff_partDen_none.2 (by rwa [Stream'.Seq.TerminatedAt] at terminated) @@ -361,7 +361,7 @@ theorem sub_convs_eq {ifp : IntFractPair K} rwa [g_finite_correctness] -- To continue, we need use the determinant equality. So let's derive the needed hypothesis. have n_eq_zero_or_not_terminatedAt_pred_n : n = 0 ∨ ¬g.TerminatedAt (n - 1) := by - cases' n with n' + rcases n with - | n' · simp · have : IntFractPair.stream v (n' + 1) ≠ none := by simp [stream_nth_eq] have : ¬g.TerminatedAt n' := @@ -373,13 +373,13 @@ theorem sub_convs_eq {ifp : IntFractPair K} -- however, for this, we first have to derive quite a few tedious inequalities. have pB_ineq : (fib n : K) ≤ pB := haveI : n ≤ 1 ∨ ¬g.TerminatedAt (n - 2) := by - cases' n_eq_zero_or_not_terminatedAt_pred_n with n_eq_zero not_terminatedAt_pred_n + rcases n_eq_zero_or_not_terminatedAt_pred_n with n_eq_zero | not_terminatedAt_pred_n · simp [n_eq_zero] · exact Or.inr <| mt (terminated_stable (n - 1).pred_le) not_terminatedAt_pred_n fib_le_of_contsAux_b this have B_ineq : (fib (n + 1) : K) ≤ B := haveI : n + 1 ≤ 1 ∨ ¬g.TerminatedAt (n + 1 - 2) := by - cases' n_eq_zero_or_not_terminatedAt_pred_n with n_eq_zero not_terminatedAt_pred_n + rcases n_eq_zero_or_not_terminatedAt_pred_n with n_eq_zero | not_terminatedAt_pred_n · simp [n_eq_zero, le_refl] · exact Or.inr not_terminatedAt_pred_n fib_le_of_contsAux_b this diff --git a/Mathlib/Algebra/ContinuedFractions/Computation/CorrectnessTerminating.lean b/Mathlib/Algebra/ContinuedFractions/Computation/CorrectnessTerminating.lean index 2f4ac3f34ae67..a0117d970346f 100644 --- a/Mathlib/Algebra/ContinuedFractions/Computation/CorrectnessTerminating.lean +++ b/Mathlib/Algebra/ContinuedFractions/Computation/CorrectnessTerminating.lean @@ -99,14 +99,13 @@ theorem compExactValue_correctness_of_stream_eq_some : induction n with | zero => intro ifp_zero stream_zero_eq - -- Nat.zero - have : IntFractPair.of v = ifp_zero := by + obtain rfl : IntFractPair.of v = ifp_zero := by have : IntFractPair.stream v 0 = some (IntFractPair.of v) := rfl simpa only [this, Option.some.injEq] using stream_zero_eq - cases this - cases' Decidable.em (Int.fract v = 0) with fract_eq_zero fract_ne_zero - -- Int.fract v = 0; we must then have `v = ⌊v⌋` - · suffices v = ⌊v⌋ by + cases eq_or_ne (Int.fract v) 0 with + | inl fract_eq_zero => + -- Int.fract v = 0; we must then have `v = ⌊v⌋` + suffices v = ⌊v⌋ by -- Porting note: was `simpa [contsAux, fract_eq_zero, compExactValue]` field_simp [nextConts, nextNum, nextDen, compExactValue] have : (IntFractPair.of v).fr = Int.fract v := rfl @@ -114,14 +113,14 @@ theorem compExactValue_correctness_of_stream_eq_some : calc v = Int.fract v + ⌊v⌋ := by rw [Int.fract_add_floor] _ = ⌊v⌋ := by simp [fract_eq_zero] - -- Int.fract v ≠ 0; the claim then easily follows by unfolding a single computation step - · field_simp [contsAux, nextConts, nextNum, nextDen, of_h_eq_floor, compExactValue] + | inr fract_ne_zero => + -- Int.fract v ≠ 0; the claim then easily follows by unfolding a single computation step + field_simp [contsAux, nextConts, nextNum, nextDen, of_h_eq_floor, compExactValue] -- Porting note: this and the if_neg rewrite are needed have : (IntFractPair.of v).fr = Int.fract v := rfl rw [this, if_neg fract_ne_zero, Int.floor_add_fract] | succ n IH => intro ifp_succ_n succ_nth_stream_eq - -- Nat.succ obtain ⟨ifp_n, nth_stream_eq, nth_fract_ne_zero, -⟩ : ∃ ifp_n, IntFractPair.stream v n = some ifp_n ∧ ifp_n.fr ≠ 0 ∧ IntFractPair.of ifp_n.fr⁻¹ = ifp_succ_n := @@ -130,9 +129,10 @@ theorem compExactValue_correctness_of_stream_eq_some : let conts := g.contsAux (n + 2) set pconts := g.contsAux (n + 1) with pconts_eq set ppconts := g.contsAux n with ppconts_eq - cases' Decidable.em (ifp_succ_n.fr = 0) with ifp_succ_n_fr_eq_zero ifp_succ_n_fr_ne_zero - -- ifp_succ_n.fr = 0 - · suffices v = conts.a / conts.b by simpa [compExactValue, ifp_succ_n_fr_eq_zero] + cases eq_or_ne ifp_succ_n.fr 0 with + | inl ifp_succ_n_fr_eq_zero => + -- ifp_succ_n.fr = 0 + suffices v = conts.a / conts.b by simpa [compExactValue, ifp_succ_n_fr_eq_zero] -- use the IH and the fact that ifp_n.fr⁻¹ = ⌊ifp_n.fr⁻¹⌋ to prove this case obtain ⟨ifp_n', nth_stream_eq', ifp_n_fract_inv_eq_floor⟩ : ∃ ifp_n, IntFractPair.stream v n = some ifp_n ∧ ifp_n.fr⁻¹ = ⌊ifp_n.fr⁻¹⌋ := @@ -145,8 +145,9 @@ theorem compExactValue_correctness_of_stream_eq_some : suffices v = compExactValue ppconts pconts ifp_n.fr by simpa [conts, contsAux, s_nth_eq, compExactValue, nth_fract_ne_zero] using this exact IH nth_stream_eq - -- ifp_succ_n.fr ≠ 0 - · -- use the IH to show that the following equality suffices + | inr ifp_succ_n_fr_ne_zero => + -- ifp_succ_n.fr ≠ 0 + -- use the IH to show that the following equality suffices suffices compExactValue ppconts pconts ifp_n.fr = compExactValue pconts conts ifp_succ_n.fr by have : v = compExactValue ppconts pconts ifp_n.fr := IH nth_stream_eq @@ -214,14 +215,14 @@ theorem of_correctness_of_nth_stream_eq_none (nth_stream_eq_none : IntFractPair. | succ n IH => let g := of v change v = g.convs n - have : + obtain ⟨nth_stream_eq_none⟩ | ⟨ifp_n, nth_stream_eq, nth_stream_fr_eq_zero⟩ : IntFractPair.stream v n = none ∨ ∃ ifp, IntFractPair.stream v n = some ifp ∧ ifp.fr = 0 := IntFractPair.succ_nth_stream_eq_none_iff.1 nth_stream_eq_none - rcases this with (⟨nth_stream_eq_none⟩ | ⟨ifp_n, nth_stream_eq, nth_stream_fr_eq_zero⟩) - · cases' n with n' - · contradiction - -- IntFractPair.stream v 0 ≠ none - · have : g.TerminatedAt n' := + · cases n with + | zero => contradiction + | succ n' => + -- IntFractPair.stream v 0 ≠ none + have : g.TerminatedAt n' := of_terminatedAt_n_iff_succ_nth_intFractPair_stream_eq_none.2 nth_stream_eq_none have : g.convs (n' + 1) = g.convs n' := diff --git a/Mathlib/Algebra/ContinuedFractions/Computation/TerminatesIffRat.lean b/Mathlib/Algebra/ContinuedFractions/Computation/TerminatesIffRat.lean index 8170aa40b0814..29595521c11a7 100644 --- a/Mathlib/Algebra/ContinuedFractions/Computation/TerminatesIffRat.lean +++ b/Mathlib/Algebra/ContinuedFractions/Computation/TerminatesIffRat.lean @@ -73,9 +73,9 @@ nonrec theorem exists_gcf_pair_rat_eq_of_nth_contsAux : use Pair.mk ⌊v⌋ 1 simp [g] -- 2 ≤ n - · cases' IH (n + 1) <| lt_add_one (n + 1) with pred_conts pred_conts_eq + · obtain ⟨pred_conts, pred_conts_eq⟩ := IH (n + 1) <| lt_add_one (n + 1) -- invoke the IH - cases' s_ppred_nth_eq : g.s.get? n with gp_n + rcases s_ppred_nth_eq : g.s.get? n with gp_n | gp_n -- option.none · use pred_conts have : g.contsAux (n + 2) = g.contsAux (n + 1) := @@ -83,8 +83,8 @@ nonrec theorem exists_gcf_pair_rat_eq_of_nth_contsAux : simp only [this, pred_conts_eq] -- option.some · -- invoke the IH a second time - cases' IH n <| lt_of_le_of_lt n.le_succ <| lt_add_one <| n + 1 with ppred_conts - ppred_conts_eq + obtain ⟨ppred_conts, ppred_conts_eq⟩ := + IH n <| lt_of_le_of_lt n.le_succ <| lt_add_one <| n + 1 obtain ⟨a_eq_one, z, b_eq_z⟩ : gp_n.a = 1 ∧ ∃ z : ℤ, gp_n.b = (z : K) := of_partNum_eq_one_and_exists_int_partDen_eq s_ppred_nth_eq -- finally, unfold the recurrence to obtain the required rational value. @@ -171,8 +171,8 @@ theorem coe_stream_nth_rat_eq (v_eq_q : v = (↑q : K)) (n : ℕ) : cases stream_q_nth_eq : IntFractPair.stream q n with | none => simp [IntFractPair.stream, IH.symm, v_eq_q, stream_q_nth_eq] | some ifp_n => - cases' ifp_n with b fr - cases' Decidable.em (fr = 0) with fr_zero fr_ne_zero + obtain ⟨b, fr⟩ := ifp_n + rcases Decidable.em (fr = 0) with fr_zero | fr_ne_zero · simp [IntFractPair.stream, IH.symm, v_eq_q, stream_q_nth_eq, fr_zero] · replace IH : some (IntFractPair.mk b (fr : K)) = IntFractPair.stream (↑q) n := by rwa [stream_q_nth_eq] at IH @@ -210,7 +210,7 @@ theorem coe_of_s_rat_eq (v_eq_q : v = (↑q : K)) : /-- Given `(v : K), (q : ℚ), and v = q`, we have that `of q = of v` -/ theorem coe_of_rat_eq (v_eq_q : v = (↑q : K)) : (⟨(of q).h, (of q).s.map (Pair.map (↑))⟩ : GenContFract K) = of v := by - cases' gcf_v_eq : of v with h s; subst v + rcases gcf_v_eq : of v with ⟨h, s⟩; subst v -- Porting note: made coercion target explicit obtain rfl : ↑⌊(q : K)⌋ = h := by injection gcf_v_eq -- Porting note: was @@ -220,7 +220,7 @@ theorem coe_of_rat_eq (v_eq_q : v = (↑q : K)) : theorem of_terminates_iff_of_rat_terminates {v : K} {q : ℚ} (v_eq_q : v = (q : K)) : (of v).Terminates ↔ (of q).Terminates := by - constructor <;> intro h <;> cases' h with n h <;> use n <;> + constructor <;> intro h <;> obtain ⟨n, h⟩ := h <;> use n <;> simp only [Stream'.Seq.TerminatedAt, (coe_of_s_get?_rat_eq v_eq_q n).symm] at h ⊢ <;> cases h' : (of q).s.get? n <;> simp only [h'] at h <;> -- Porting note: added @@ -267,7 +267,7 @@ theorem stream_succ_nth_fr_num_lt_nth_fr_num_rat {ifp_n ifp_succ_n : IntFractPai have : ifp_n = ifp_n' := by injection Eq.trans stream_nth_eq.symm stream_nth_eq' cases this rw [← IntFractPair.of_eq_ifp_succ_n] - cases' nth_stream_fr_nonneg_lt_one stream_nth_eq with zero_le_ifp_n_fract ifp_n_fract_lt_one + obtain ⟨zero_le_ifp_n_fract, _⟩ := nth_stream_fr_nonneg_lt_one stream_nth_eq have : 0 < ifp_n.fr := lt_of_le_of_ne zero_le_ifp_n_fract <| ifp_n_fract_ne_zero.symm exact of_inv_fr_num_lt_num_of_pos this @@ -292,7 +292,7 @@ theorem stream_nth_fr_num_le_fr_num_sub_n_rat : theorem exists_nth_stream_eq_none_of_rat (q : ℚ) : ∃ n : ℕ, IntFractPair.stream q n = none := by let fract_q_num := (Int.fract q).num; let n := fract_q_num.natAbs + 1 - cases' stream_nth_eq : IntFractPair.stream q n with ifp + rcases stream_nth_eq : IntFractPair.stream q n with ifp | ifp · use n, stream_nth_eq · -- arrive at a contradiction since the numerator decreased num + 1 times but every fractional -- value is nonnegative. diff --git a/Mathlib/Algebra/ContinuedFractions/Computation/Translations.lean b/Mathlib/Algebra/ContinuedFractions/Computation/Translations.lean index 771e16a57a2bb..d732ff25b6a7a 100644 --- a/Mathlib/Algebra/ContinuedFractions/Computation/Translations.lean +++ b/Mathlib/Algebra/ContinuedFractions/Computation/Translations.lean @@ -63,7 +63,7 @@ variable {n : ℕ} theorem stream_eq_none_of_fr_eq_zero {ifp_n : IntFractPair K} (stream_nth_eq : IntFractPair.stream v n = some ifp_n) (nth_fr_eq_zero : ifp_n.fr = 0) : IntFractPair.stream v (n + 1) = none := by - cases' ifp_n with _ fr + obtain ⟨_, fr⟩ := ifp_n change fr = 0 at nth_fr_eq_zero simp [IntFractPair.stream, stream_nth_eq, nth_fr_eq_zero] @@ -249,7 +249,7 @@ theorem of_s_head_aux (v : K) : (of v).s.get? 0 = (IntFractPair.stream v 1).bind rw [of, IntFractPair.seq1] simp only [of, Stream'.Seq.map_tail, Stream'.Seq.map, Stream'.Seq.tail, Stream'.Seq.head, Stream'.Seq.get?, Stream'.map] - rw [← Stream'.get_succ, Stream'.get, Option.map] + rw [← Stream'.get_succ, Stream'.get, Option.map.eq_def] split <;> simp_all only [Option.some_bind, Option.none_bind, Function.comp_apply] /-- This gives the first pair of coefficients of the continued fraction of a non-integer `v`. diff --git a/Mathlib/Algebra/ContinuedFractions/ConvergentsEquiv.lean b/Mathlib/Algebra/ContinuedFractions/ConvergentsEquiv.lean index 2ffc624d496a8..2adf582909701 100644 --- a/Mathlib/Algebra/ContinuedFractions/ConvergentsEquiv.lean +++ b/Mathlib/Algebra/ContinuedFractions/ConvergentsEquiv.lean @@ -136,7 +136,7 @@ theorem squashSeq_succ_n_tail_eq_squashSeq_tail_n : s.ge_stable (n + 1).le_succ s_succ_succ_nth_eq -- apply extensionality with `m` and continue by cases `m = n`. ext1 m - cases' Decidable.em (m = n) with m_eq_n m_ne_n + rcases Decidable.em (m = n) with m_eq_n | m_ne_n · simp [*, squashSeq] · cases s_succ_mth_eq : s.get? (m + 1) · simp only [*, squashSeq, Stream'.Seq.get?_tail, Stream'.Seq.get?_zipWith, @@ -227,12 +227,12 @@ theorem contsAux_eq_contsAux_squashGCF_of_le {m : ℕ} : (by clear m intro m IH m_le_n - cases' m with m' + rcases m with - | m' · rfl - · cases' n with n' + · rcases n with - | n' · exact (m'.not_succ_le_zero m_le_n).elim -- 1 ≰ 0 - · cases' m' with m'' + · rcases m' with - | m'' · rfl · -- get some inequalities to instantiate the IH for m'' and m'' + 1 have m'_lt_n : m'' + 1 < n' + 1 := m_le_n @@ -250,7 +250,7 @@ at the squashed position is not zero. -/ theorem succ_nth_conv_eq_squashGCF_nth_conv [Field K] (nth_partDen_ne_zero : ∀ {b : K}, g.partDens.get? n = some b → b ≠ 0) : g.convs (n + 1) = (squashGCF g n).convs n := by - cases' Decidable.em (g.TerminatedAt n) with terminatedAt_n not_terminatedAt_n + rcases Decidable.em (g.TerminatedAt n) with terminatedAt_n | not_terminatedAt_n · have : squashGCF g n = g := squashGCF_eq_self_of_terminated terminatedAt_n simp only [this, convs_stable_of_terminated n.le_succ terminatedAt_n] · obtain ⟨⟨a, b⟩, s_nth_eq⟩ : ∃ gp_n, g.s.get? n = some gp_n := @@ -335,7 +335,7 @@ theorem convs_eq_convs' [LinearOrderedField K] -- first replace the rhs with the squashed computation suffices g.convs (n + 1) = g'.convs' n by rwa [succ_nth_conv'_eq_squashGCF_nth_conv'] - cases' Decidable.em (TerminatedAt g n) with terminatedAt_n not_terminatedAt_n + rcases Decidable.em (TerminatedAt g n) with terminatedAt_n | not_terminatedAt_n · have g'_eq_g : g' = g := squashGCF_eq_self_of_terminated terminatedAt_n rw [convs_stable_of_terminated n.le_succ terminatedAt_n, g'_eq_g, IH _] intro _ _ m_lt_n s_mth_eq @@ -345,7 +345,7 @@ theorem convs_eq_convs' [LinearOrderedField K] rwa [← IH] intro gp' m m_lt_n s_mth_eq' -- case distinction on m + 1 = n or m + 1 < n - cases' m_lt_n with n succ_m_lt_n + rcases m_lt_n with n | succ_m_lt_n · -- the difficult case at the squashed position: we first obtain the values from -- the sequence obtain ⟨gp_succ_m, s_succ_mth_eq⟩ : ∃ gp_succ_m, g.s.get? (m + 1) = some gp_succ_m := diff --git a/Mathlib/Algebra/DirectLimit.lean b/Mathlib/Algebra/DirectLimit.lean index 993dcaec82950..f1aa6c7623464 100644 --- a/Mathlib/Algebra/DirectLimit.lean +++ b/Mathlib/Algebra/DirectLimit.lean @@ -137,20 +137,20 @@ protected theorem induction_on [Nonempty ι] [IsDirected ι (· ≤ ·)] {C : Di let ⟨i, x, h⟩ := exists_of z h ▸ ih i x -variable {P : Type u₁} [AddCommGroup P] [Module R P] (g : ∀ i, G i →ₗ[R] P) -variable (Hg : ∀ i j hij x, g j (f i j hij x) = g i x) -variable (R ι G f) +variable {P : Type u₁} [AddCommGroup P] [Module R P] +variable (R ι G f) in /-- The universal property of the direct limit: maps from the components to another module that respect the directed system structure (i.e. make some diagram commute) give rise to a unique map out of the direct limit. -/ -def lift : DirectLimit G f →ₗ[R] P := +def lift (g : ∀ i, G i →ₗ[R] P) (Hg : ∀ i j hij x, g j (f i j hij x) = g i x) : + DirectLimit G f →ₗ[R] P := liftQ _ (DirectSum.toModule R ι P g) (span_le.2 fun a ⟨i, j, hij, x, hx⟩ => by rw [← hx, SetLike.mem_coe, LinearMap.sub_mem_ker_iff, DirectSum.toModule_lof, DirectSum.toModule_lof, Hg]) -variable {R ι G f} +variable (g : ∀ i, G i →ₗ[R] P) (Hg : ∀ i j hij x, g j (f i j hij x) = g i x) theorem lift_of {i} (x) : lift R ι G f g Hg (of R ι G f i x) = g i x := DirectSum.toModule_lof R _ _ @@ -170,9 +170,10 @@ lemma lift_injective [IsDirected ι (· ≤ ·)] · apply Function.injective_of_subsingleton simp_rw [injective_iff_map_eq_zero] at injective ⊢ intros z hz - induction' z using DirectLimit.induction_on with _ g - rw [lift_of] at hz - rw [injective _ g hz, _root_.map_zero] + induction z using DirectLimit.induction_on with + | ih _ g => + rw [lift_of] at hz + rw [injective _ g hz, _root_.map_zero] section functorial @@ -429,9 +430,8 @@ lemma lift_injective [IsDirected ι (· ≤ ·)] · apply Function.injective_of_subsingleton simp_rw [injective_iff_map_eq_zero] at injective ⊢ intros z hz - induction' z using DirectLimit.induction_on with _ g - rw [lift_of] at hz - rw [injective _ g hz, _root_.map_zero] + induction z using DirectLimit.induction_on with + | ih _ g => rw [lift_of] at hz; rw [injective _ g hz, _root_.map_zero] section functorial @@ -790,18 +790,16 @@ theorem of_injective [IsDirected ι (· ≤ ·)] [DirectedSystem G fun i j h => rw [hfx, (f' i j hij).map_zero] variable (P : Type u₁) [CommRing P] -variable (g : ∀ i, G i →+* P) -variable (Hg : ∀ i j hij x, g j (f i j hij x) = g i x) open FreeCommRing -variable (G f) - +variable (G f) in /-- The universal property of the direct limit: maps from the components to another ring that respect the directed system structure (i.e. make some diagram commute) give rise to a unique map out of the direct limit. -/ -def lift : DirectLimit G f →+* P := +def lift (g : ∀ i, G i →+* P) (Hg : ∀ i j hij x, g j (f i j hij x) = g i x) : + DirectLimit G f →+* P := Ideal.Quotient.lift _ (FreeCommRing.lift fun x : Σi, G i => g x.1 x.2) (by suffices Ideal.span _ ≤ @@ -815,7 +813,7 @@ def lift : DirectLimit G f →+* P := simp only [RingHom.map_sub, lift_of, Hg, RingHom.map_one, RingHom.map_add, RingHom.map_mul, (g i).map_one, (g i).map_add, (g i).map_mul, sub_self]) -variable {G f} +variable (g : ∀ i, G i →+* P) (Hg : ∀ i j hij x, g j (f i j hij x) = g i x) -- Porting note: the @[simp] attribute would trigger a `simpNF` linter error: -- failed to synthesize CommMonoidWithZero (Ring.DirectLimit G f) @@ -836,9 +834,8 @@ lemma lift_injective [Nonempty ι] [IsDirected ι (· ≤ ·)] Function.Injective (lift G f P g Hg) := by simp_rw [injective_iff_map_eq_zero] at injective ⊢ intros z hz - induction' z using DirectLimit.induction_on with _ g - rw [lift_of] at hz - rw [injective _ g hz, _root_.map_zero] + induction z using DirectLimit.induction_on with + | ih _ g => rw [lift_of] at hz; rw [injective _ g hz, _root_.map_zero] section functorial @@ -975,7 +972,9 @@ protected noncomputable abbrev field [DirectedSystem G fun i j h => f' i j h] : mul_inv_cancel := fun p => DirectLimit.mul_inv_cancel G fun i j h => f' i j h inv_zero := dif_pos rfl nnqsmul := _ + nnqsmul_def := fun q a => rfl qsmul := _ + qsmul_def := fun q a => rfl end diff --git a/Mathlib/Algebra/DirectSum/AddChar.lean b/Mathlib/Algebra/DirectSum/AddChar.lean new file mode 100644 index 0000000000000..a9a6296c82833 --- /dev/null +++ b/Mathlib/Algebra/DirectSum/AddChar.lean @@ -0,0 +1,35 @@ +/- +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.DirectSum.Basic +import Mathlib.Algebra.Group.AddChar + +/-! +# Direct sum of additive characters + +This file defines the direct sum of additive characters. +-/ + +open Function +open scoped DirectSum + +variable {ι R : Type*} {G : ι → Type*} [DecidableEq ι] [∀ i, AddCommGroup (G i)] [CommMonoid R] + +namespace AddChar +section DirectSum + +/-- Direct sum of additive characters. -/ +@[simps!] +def directSum (ψ : ∀ i, AddChar (G i) R) : AddChar (⨁ i, G i) R := + toAddMonoidHomEquiv.symm <| DirectSum.toAddMonoid fun i ↦ toAddMonoidHomEquiv (ψ i) + +lemma directSum_injective : + Injective (directSum : (∀ i, AddChar (G i) R) → AddChar (⨁ i, G i) R) := by + refine toAddMonoidHomEquiv.symm.injective.comp <| DirectSum.toAddMonoid_injective.comp ?_ + rintro ψ χ h + simpa [funext_iff] using h + +end DirectSum +end AddChar diff --git a/Mathlib/Algebra/DirectSum/Decomposition.lean b/Mathlib/Algebra/DirectSum/Decomposition.lean index 45f344b63d1ae..68b4f5db83e65 100644 --- a/Mathlib/Algebra/DirectSum/Decomposition.lean +++ b/Mathlib/Algebra/DirectSum/Decomposition.lean @@ -57,8 +57,8 @@ class Decomposition where /-- `DirectSum.Decomposition` instances, while carrying data, are always equal. -/ instance : Subsingleton (Decomposition ℳ) := ⟨fun x y ↦ by - cases' x with x xl xr - cases' y with y yl yr + obtain ⟨_, _, xr⟩ := x + obtain ⟨_, yl, _⟩ := y congr exact Function.LeftInverse.eq_rightInverse xr yl⟩ diff --git a/Mathlib/Algebra/DirectSum/LinearMap.lean b/Mathlib/Algebra/DirectSum/LinearMap.lean index 24dc43c284d75..c3b5c570dd966 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) [IsNoetherian R M] +lemma trace_eq_zero_of_mapsTo_ne (h : IsInternal N) [hn : 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 - (wellFounded_submodule_gt R M) h.submodule_independent + hn.wf 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) @@ -112,8 +112,8 @@ lemma trace_comp_eq_zero_of_commute_of_trace_restrict_eq_zero 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 - (isNoetherian_iff_wellFounded.mp inferInstance) f.independent_genEigenspace + CompleteLattice.WellFounded.finite_ne_bot_of_independent IsWellFounded.wf + f.independent_genEigenspace 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 μ)) diff --git a/Mathlib/Algebra/DirectSum/Module.lean b/Mathlib/Algebra/DirectSum/Module.lean index 5d0336e5ed1e4..bda16093f4ab9 100644 --- a/Mathlib/Algebra/DirectSum/Module.lean +++ b/Mathlib/Algebra/DirectSum/Module.lean @@ -28,7 +28,7 @@ universe u v w u₁ namespace DirectSum -open DirectSum +open DirectSum Finsupp section General @@ -335,7 +335,7 @@ theorem IsInternal.collectedBasis_coe (h : IsInternal A) {α : ι → Type*} -- Porting note: was -- simp only [IsInternal.collectedBasis, toModule, coeLinearMap, Basis.coe_ofRepr, -- Basis.repr_symm_apply, DFinsupp.lsum_apply_apply, DFinsupp.mapRange.linearEquiv_apply, - -- DFinsupp.mapRange.linearEquiv_symm, DFinsupp.mapRange_single, Finsupp.total_single, + -- DFinsupp.mapRange.linearEquiv_symm, DFinsupp.mapRange_single, linearCombination_single, -- LinearEquiv.ofBijective_apply, LinearEquiv.symm_symm, LinearEquiv.symm_trans_apply, one_smul, -- sigmaFinsuppAddEquivDFinsupp_apply, sigmaFinsuppEquivDFinsupp_single, -- sigmaFinsuppLequivDFinsupp_apply] @@ -346,7 +346,7 @@ theorem IsInternal.collectedBasis_coe (h : IsInternal A) {α : ι → Type*} sigmaFinsuppAddEquivDFinsupp_apply] rw [DFinsupp.mapRange.linearEquiv_symm] erw [DFinsupp.mapRange.linearEquiv_apply] - simp only [DFinsupp.mapRange_single, Basis.repr_symm_apply, Finsupp.total_single, one_smul, + simp only [DFinsupp.mapRange_single, Basis.repr_symm_apply, linearCombination_single, one_smul, toModule] erw [DFinsupp.lsum_single] simp only [Submodule.coeSubtype] diff --git a/Mathlib/Algebra/DirectSum/Ring.lean b/Mathlib/Algebra/DirectSum/Ring.lean index 52f4424409e6e..adc80f5bfe07a 100644 --- a/Mathlib/Algebra/DirectSum/Ring.lean +++ b/Mathlib/Algebra/DirectSum/Ring.lean @@ -273,10 +273,10 @@ theorem ofPow {i} (a : A i) (n : ℕ) : theorem ofList_dProd {α} (l : List α) (fι : α → ι) (fA : ∀ a, A (fι a)) : of A _ (l.dProd fι fA) = (l.map fun a => of A (fι a) (fA a)).prod := by - induction' l with head tail - · simp only [List.map_nil, List.prod_nil, List.dProd_nil] - rfl - · rename_i ih + induction l with + | nil => simp only [List.map_nil, List.prod_nil, List.dProd_nil]; rfl + | cons head tail => + rename_i ih simp only [List.map_cons, List.prod_cons, List.dProd_cons, ← ih] rw [DirectSum.of_mul_of (fA head)] rfl diff --git a/Mathlib/Algebra/EuclideanDomain/Basic.lean b/Mathlib/Algebra/EuclideanDomain/Basic.lean index 92b8a34c4f9ba..a91e02383e95b 100644 --- a/Mathlib/Algebra/EuclideanDomain/Basic.lean +++ b/Mathlib/Algebra/EuclideanDomain/Basic.lean @@ -237,7 +237,7 @@ theorem lcm_dvd {x y z : R} (hxz : x ∣ z) (hyz : y ∣ z) : lcm x y ∣ z := b rwa [hxy.1] at hxz rcases gcd_dvd x y with ⟨⟨r, hr⟩, ⟨s, hs⟩⟩ suffices x * y ∣ z * gcd x y by - cases' this with p hp + obtain ⟨p, hp⟩ := this use p generalize gcd x y = g at hxy hs hp ⊢ subst hs diff --git a/Mathlib/Algebra/EuclideanDomain/Defs.lean b/Mathlib/Algebra/EuclideanDomain/Defs.lean index 81b62ab8bf111..8a0022c6dee04 100644 --- a/Mathlib/Algebra/EuclideanDomain/Defs.lean +++ b/Mathlib/Algebra/EuclideanDomain/Defs.lean @@ -67,7 +67,7 @@ universe u satisfying `b * (a / b) + a % b = a`. The definition of a Euclidean domain usually includes a valuation function `R → ℕ`. This definition is slightly generalised to include a well founded relation - `r` with the property that `r (a % b) b`, instead of a valuation. -/ + `r` with the property that `r (a % b) b`, instead of a valuation. -/ class EuclideanDomain (R : Type u) extends CommRing R, Nontrivial R where /-- A division function (denoted `/`) on `R`. This satisfies the property `b * (a / b) + a % b = a`, where `%` denotes `remainder`. -/ diff --git a/Mathlib/Algebra/Field/Power.lean b/Mathlib/Algebra/Field/Power.lean index 8f85d4bef98a9..b59970a8b25f1 100644 --- a/Mathlib/Algebra/Field/Power.lean +++ b/Mathlib/Algebra/Field/Power.lean @@ -22,7 +22,7 @@ section DivisionRing variable [DivisionRing α] {n : ℤ} theorem Odd.neg_zpow (h : Odd n) (a : α) : (-a) ^ n = -a ^ n := by - have hn : n ≠ 0 := by rintro rfl; exact Int.odd_iff_not_even.1 h even_zero + have hn : n ≠ 0 := by rintro rfl; exact Int.not_even_iff_odd.2 h even_zero obtain ⟨k, rfl⟩ := h simp_rw [zpow_add' (.inr (.inl hn)), zpow_one, zpow_mul, zpow_two, neg_mul_neg, neg_mul_eq_mul_neg] diff --git a/Mathlib/Algebra/Field/Subfield.lean b/Mathlib/Algebra/Field/Subfield.lean index b304f131e2f96..8d57654e441ac 100644 --- a/Mathlib/Algebra/Field/Subfield.lean +++ b/Mathlib/Algebra/Field/Subfield.lean @@ -320,7 +320,7 @@ instance toDivisionRing (s : Subfield K) : DivisionRing s := 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) (fun _ _ => rfl) (fun _ _ => rfl) (by intros; rfl) (fun _ => rfl) (fun _ => rfl) (by intros; rfl) fun _ => rfl @[simp, norm_cast] diff --git a/Mathlib/Algebra/Free.lean b/Mathlib/Algebra/Free.lean index 68fa9ba945b69..1b0f927525cca 100644 --- a/Mathlib/Algebra/Free.lean +++ b/Mathlib/Algebra/Free.lean @@ -244,10 +244,10 @@ instance : LawfulTraversable FreeMagma.{u} := rw [traverse_mul, ih1, ih2, mul_map_seq] comp_traverse := fun f g x ↦ FreeMagma.recOnPure x - (fun x ↦ by simp only [(· ∘ ·), traverse_pure, traverse_pure', functor_norm]) + (fun x ↦ by simp only [Function.comp_def, traverse_pure, traverse_pure', functor_norm]) (fun x y ih1 ih2 ↦ by rw [traverse_mul, ih1, ih2, traverse_mul] - simp [Functor.Comp.map_mk, Functor.map_map, (· ∘ ·), Comp.seq_mk, seq_map_assoc, + simp [Functor.Comp.map_mk, Functor.map_map, Function.comp_def, Comp.seq_mk, seq_map_assoc, map_seq, traverse_mul]) naturality := fun η α β f x ↦ FreeMagma.recOnPure x @@ -592,7 +592,7 @@ theorem traverse_mul (x y : FreeSemigroup α) : (fun hd tl ih x ↦ show (· * ·) <$> pure <$> F x <*> traverse F (mk hd tl * mk y L2) = (· * ·) <$> ((· * ·) <$> pure <$> F x <*> traverse F (mk hd tl)) <*> traverse F (mk y L2) - by rw [ih]; simp only [(· ∘ ·), (mul_assoc _ _ _).symm, functor_norm]) + by rw [ih]; simp only [Function.comp_def, (mul_assoc _ _ _).symm, functor_norm]) x @[to_additive (attr := simp)] @@ -618,9 +618,10 @@ instance : LawfulTraversable FreeSemigroup.{u} := FreeSemigroup.recOnMul x (fun x ↦ rfl) fun x y ih1 ih2 ↦ by rw [traverse_mul, ih1, ih2, mul_map_seq] comp_traverse := fun f g x ↦ - recOnPure x (fun x ↦ by simp only [traverse_pure, functor_norm, (· ∘ ·)]) - fun x y ih1 ih2 ↦ by (rw [traverse_mul, ih1, ih2, - traverse_mul, Functor.Comp.map_mk]; simp only [Function.comp, functor_norm, traverse_mul]) + recOnPure x (fun x ↦ by simp only [traverse_pure, functor_norm, Function.comp_def]) + fun x y ih1 ih2 ↦ by + rw [traverse_mul, ih1, ih2, traverse_mul, Functor.Comp.map_mk] + simp only [Function.comp_def, functor_norm, traverse_mul] naturality := fun η α β f x ↦ recOnPure x (fun x ↦ by simp only [traverse_pure, functor_norm, Function.comp]) (fun x y ih1 ih2 ↦ by simp only [traverse_mul, functor_norm, ih1, ih2]) diff --git a/Mathlib/Algebra/FreeAlgebra.lean b/Mathlib/Algebra/FreeAlgebra.lean index 9c12c522bad65..09f5906b663fa 100644 --- a/Mathlib/Algebra/FreeAlgebra.lean +++ b/Mathlib/Algebra/FreeAlgebra.lean @@ -151,7 +151,7 @@ namespace FreeAlgebra attribute [local instance] Pre.hasCoeGenerator Pre.hasCoeSemiring Pre.hasMul Pre.hasAdd Pre.hasZero Pre.hasOne Pre.hasSMul -/-! Define the basic operations-/ +/-! Define the basic operations -/ instance instSMul {A} [CommSemiring A] [Algebra R A] : SMul R (FreeAlgebra A X) where smul r := Quot.map (HMul.hMul (algebraMap R A r : Pre A X)) fun _ _ ↦ Rel.mul_compat_right @@ -294,7 +294,7 @@ variable {A : Type*} [Semiring A] [Algebra R A] private def liftAux (f : X → A) : FreeAlgebra R X →ₐ[R] A where toFun a := Quot.liftOn a (liftFun _ _ f) fun a b h ↦ by - induction' h + induction h · exact (algebraMap R A).map_add _ _ · exact (algebraMap R A).map_mul _ _ · apply Algebra.commutes @@ -526,7 +526,7 @@ namespace FreeAlgebra /-- An induction principle for the free algebra. If `C` holds for the `algebraMap` of `r : R` into `FreeAlgebra R X`, the `ι` of `x : X`, and is -preserved under addition and muliplication, then it holds for all of `FreeAlgebra R X`. +preserved under addition and multiplication, then it holds for all of `FreeAlgebra R X`. -/ @[elab_as_elim, induction_eliminator] theorem induction {C : FreeAlgebra R X → Prop} @@ -567,7 +567,7 @@ variable {A : Type*} [Semiring A] [Algebra R A] theorem _root_.Algebra.adjoin_range_eq_range_freeAlgebra_lift (f : X → A) : Algebra.adjoin R (Set.range f) = (FreeAlgebra.lift R f).range := by simp only [← Algebra.map_top, ← adjoin_range_ι, AlgHom.map_adjoin, ← Set.range_comp, - (· ∘ ·), lift_ι_apply] + Function.comp_def, lift_ι_apply] /-- Noncommutative version of `Algebra.adjoin_range_eq_range`. -/ theorem _root_.Algebra.adjoin_eq_range_freeAlgebra_lift (s : Set A) : diff --git a/Mathlib/Algebra/GCDMonoid/Basic.lean b/Mathlib/Algebra/GCDMonoid/Basic.lean index 6442ad5f441a8..e7ff47b1fe976 100644 --- a/Mathlib/Algebra/GCDMonoid/Basic.lean +++ b/Mathlib/Algebra/GCDMonoid/Basic.lean @@ -478,7 +478,7 @@ theorem dvd_mul_gcd_iff_dvd_mul [GCDMonoid α] {m n k : α} : k ∣ m * gcd k n Note: In general, this representation is highly non-unique. -See `Nat.prodDvdAndDvdOfDvdProd` for a constructive version on `ℕ`. -/ +See `Nat.prodDvdAndDvdOfDvdProd` for a constructive version on `ℕ`. -/ instance [h : Nonempty (GCDMonoid α)] : DecompositionMonoid α where primal k m n H := by cases h @@ -510,13 +510,13 @@ theorem gcd_pow_right_dvd_pow_gcd [GCDMonoid α] {a b : α} {k : ℕ} : exact (gcd_zero_left' (0 ^ k : α)).dvd.trans (pow_dvd_pow_of_dvd (gcd_zero_left' (0 : α)).symm.dvd _) - · induction' k with k hk - · rw [pow_zero, pow_zero] - exact (gcd_one_right' a).dvd - rw [pow_succ', pow_succ'] - trans gcd a b * gcd a (b ^ k) - · exact gcd_mul_dvd_mul_gcd a b (b ^ k) - · exact (mul_dvd_mul_iff_left hg).mpr hk + · induction k with + | zero => rw [pow_zero, pow_zero]; exact (gcd_one_right' a).dvd + | succ k hk => + rw [pow_succ', pow_succ'] + trans gcd a b * gcd a (b ^ k) + · exact gcd_mul_dvd_mul_gcd a b (b ^ k) + · exact (mul_dvd_mul_iff_left hg).mpr hk theorem gcd_pow_left_dvd_pow_gcd [GCDMonoid α] {a b : α} {k : ℕ} : gcd (a ^ k) b ∣ gcd a b ^ k := calc @@ -855,8 +855,8 @@ instance subsingleton_gcdMonoid_of_unique_units : Subsingleton (GCDMonoid α) := instance subsingleton_normalizedGCDMonoid_of_unique_units : Subsingleton (NormalizedGCDMonoid α) := ⟨by intro a b - cases' a with a_norm a_gcd - cases' b with b_norm b_gcd + cases a; rename_i a_norm a_gcd _ _ + cases b; rename_i b_norm b_gcd _ _ have := Subsingleton.elim a_gcd b_gcd subst this have := Subsingleton.elim a_norm b_norm diff --git a/Mathlib/Algebra/GCDMonoid/Finset.lean b/Mathlib/Algebra/GCDMonoid/Finset.lean index 306e3162d1017..89d7b6ca4f3ef 100644 --- a/Mathlib/Algebra/GCDMonoid/Finset.lean +++ b/Mathlib/Algebra/GCDMonoid/Finset.lean @@ -97,7 +97,7 @@ theorem lcm_mono (h : s₁ ⊆ s₂) : s₁.lcm f ∣ s₂.lcm f := theorem lcm_image [DecidableEq β] {g : γ → β} (s : Finset γ) : (s.image g).lcm f = s.lcm (f ∘ g) := by - classical induction' s using Finset.induction with c s _ ih <;> simp [*] + classical induction s using Finset.induction <;> simp [*] theorem lcm_eq_lcm_image [DecidableEq α] : s.lcm f = (s.image f).lcm id := Eq.symm <| lcm_image _ @@ -170,7 +170,7 @@ theorem gcd_mono (h : s₁ ⊆ s₂) : s₂.gcd f ∣ s₁.gcd f := theorem gcd_image [DecidableEq β] {g : γ → β} (s : Finset γ) : (s.image g).gcd f = s.gcd (f ∘ g) := by - classical induction' s using Finset.induction with c s _ ih <;> simp [*] + classical induction s using Finset.induction <;> simp [*] theorem gcd_eq_gcd_image [DecidableEq α] : s.gcd f = (s.image f).gcd id := Eq.symm <| gcd_image _ diff --git a/Mathlib/Algebra/GCDMonoid/Multiset.lean b/Mathlib/Algebra/GCDMonoid/Multiset.lean index bb77c1ff32a3f..ea5a208bda10a 100644 --- a/Mathlib/Algebra/GCDMonoid/Multiset.lean +++ b/Mathlib/Algebra/GCDMonoid/Multiset.lean @@ -73,9 +73,9 @@ theorem normalize_lcm (s : Multiset α) : normalize s.lcm = s.lcm := @[simp] nonrec theorem lcm_eq_zero_iff [Nontrivial α] (s : Multiset α) : s.lcm = 0 ↔ (0 : α) ∈ s := by - induction' s using Multiset.induction_on with a s ihs - · simp only [lcm_zero, one_ne_zero, not_mem_zero] - · simp only [mem_cons, lcm_cons, lcm_eq_zero_iff, ihs, @eq_comm _ a] + induction s using Multiset.induction_on with + | empty => simp only [lcm_zero, one_ne_zero, not_mem_zero] + | cons a s ihs => simp only [mem_cons, lcm_cons, lcm_eq_zero_iff, ihs, @eq_comm _ a] variable [DecidableEq α] diff --git a/Mathlib/Algebra/GCDMonoid/Nat.lean b/Mathlib/Algebra/GCDMonoid/Nat.lean index c5dadae8f727c..11c7bd9c63679 100644 --- a/Mathlib/Algebra/GCDMonoid/Nat.lean +++ b/Mathlib/Algebra/GCDMonoid/Nat.lean @@ -4,8 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl, Jens Wagemaker, Aaron Anderson -/ import Mathlib.Algebra.GCDMonoid.Basic -import Mathlib.Algebra.Order.Group.Abs -import Mathlib.Algebra.Order.Ring.Int +import Mathlib.Algebra.Order.Group.Unbundled.Int +import Mathlib.Algebra.Ring.Int import Mathlib.Data.Int.GCD /-! @@ -23,6 +23,8 @@ import Mathlib.Data.Int.GCD natural numbers, integers, normalization monoid, gcd monoid, greatest common divisor -/ +assert_not_exists OrderedCommMonoid + /-- `ℕ` is a gcd_monoid. -/ instance : GCDMonoid ℕ where gcd := Nat.gcd @@ -54,10 +56,10 @@ instance normalizationMonoid : NormalizationMonoid ℤ where normUnit a := if 0 ≤ a then 1 else -1 normUnit_zero := if_pos le_rfl normUnit_mul {a b} hna hnb := by - cases' hna.lt_or_lt with ha ha <;> cases' hnb.lt_or_lt with hb hb <;> - simp [mul_nonneg_iff, ha.le, ha.not_le, hb.le, hb.not_le] + rcases hna.lt_or_lt with ha | ha <;> rcases hnb.lt_or_lt with hb | hb <;> + simp [Int.mul_nonneg_iff, ha.le, ha.not_le, hb.le, hb.not_le] normUnit_coe_units u := - (units_eq_one_or u).elim (fun eq => eq.symm ▸ if_pos zero_le_one) fun eq => + (units_eq_one_or u).elim (fun eq => eq.symm ▸ if_pos Int.one_nonneg) fun eq => eq.symm ▸ if_neg (not_le_of_gt <| show (-1 : ℤ) < 0 by decide) -- Porting note: added @@ -76,10 +78,14 @@ theorem normalize_coe_nat (n : ℕ) : normalize (n : ℤ) = n := normalize_of_nonneg (ofNat_le_ofNat_of_le <| Nat.zero_le n) theorem abs_eq_normalize (z : ℤ) : |z| = normalize z := by - cases le_total 0 z <;> simp [-normalize_apply, normalize_of_nonneg, normalize_of_nonpos, *] + cases le_total 0 z <;> + simp [-normalize_apply, abs_of_nonneg, abs_of_nonpos, normalize_of_nonneg, normalize_of_nonpos, *] -theorem nonneg_of_normalize_eq_self {z : ℤ} (hz : normalize z = z) : 0 ≤ z := - abs_eq_self.1 <| by rw [abs_eq_normalize, hz] +theorem nonneg_of_normalize_eq_self {z : ℤ} (hz : normalize z = z) : 0 ≤ z := by + by_cases h : 0 ≤ z + · exact h + · rw [normalize_of_nonpos (le_of_not_le h)] at hz + omega theorem nonneg_iff_normalize_eq_self (z : ℤ) : normalize z = z ↔ 0 ≤ z := ⟨nonneg_of_normalize_eq_self, normalize_of_nonneg⟩ @@ -125,7 +131,7 @@ theorem natAbs_lcm (i j : ℤ) : natAbs (GCDMonoid.lcm i j) = Int.lcm i j := end GCDMonoid theorem exists_unit_of_abs (a : ℤ) : ∃ (u : ℤ) (_ : IsUnit u), (Int.natAbs a : ℤ) = u * a := by - cases' natAbs_eq a with h h + rcases natAbs_eq a with h | h · use 1, isUnit_one rw [← h, one_mul] · use -1, isUnit_one.neg diff --git a/Mathlib/Algebra/GeomSum.lean b/Mathlib/Algebra/GeomSum.lean index 1a833ffa86faf..62bd098ce1152 100644 --- a/Mathlib/Algebra/GeomSum.lean +++ b/Mathlib/Algebra/GeomSum.lean @@ -123,7 +123,7 @@ theorem neg_one_geom_sum [Ring α] {n : ℕ} : simp only [geom_sum_succ', Nat.even_add_one, hk] split_ifs with h · rw [h.neg_one_pow, add_zero] - · rw [(Nat.odd_iff_not_even.2 h).neg_one_pow, neg_add_cancel] + · rw [(Nat.not_even_iff_odd.1 h).neg_one_pow, neg_add_cancel] theorem geom_sum₂_self {α : Type*} [CommRing α] (x : α) (n : ℕ) : ∑ i ∈ range n, x ^ i * x ^ (n - 1 - i) = n * x ^ (n - 1) := @@ -282,7 +282,7 @@ protected theorem Commute.geom_sum₂_succ_eq {α : Type u} [Ring α] {x y : α} (h.symm.pow_right _).eq, mul_assoc, ← pow_succ'] refine sum_congr rfl fun i hi => ?_ suffices n - 1 - i + 1 = n - i by rw [this] - cases' n with n + rcases n with - | n · exact absurd (List.mem_range.mp hi) i.not_lt_zero · rw [tsub_add_eq_add_tsub (Nat.le_sub_one_of_lt (List.mem_range.mp hi)), tsub_add_cancel_of_le (Nat.succ_le_iff.mpr n.succ_pos)] @@ -393,7 +393,7 @@ theorem Nat.pred_mul_geom_sum_le (a b n : ℕ) : theorem Nat.geom_sum_le {b : ℕ} (hb : 2 ≤ b) (a n : ℕ) : ∑ i ∈ range n, a / b ^ i ≤ a * b / (b - 1) := by refine (Nat.le_div_iff_mul_le <| tsub_pos_of_lt hb).2 ?_ - cases' n with n + rcases n with - | n · rw [sum_range_zero, zero_mul] exact Nat.zero_le _ rw [mul_comm] @@ -401,7 +401,7 @@ theorem Nat.geom_sum_le {b : ℕ} (hb : 2 ≤ b) (a n : ℕ) : theorem Nat.geom_sum_Ico_le {b : ℕ} (hb : 2 ≤ b) (a n : ℕ) : ∑ i ∈ Ico 1 n, a / b ^ i ≤ a / (b - 1) := by - cases' n with n + rcases n with - | n · rw [Ico_eq_empty_of_le (zero_le_one' ℕ), sum_empty] exact Nat.zero_le _ rw [← add_le_add_iff_left a] @@ -484,7 +484,7 @@ theorem Odd.geom_sum_pos [LinearOrderedRing α] (h : Odd n) : 0 < ∑ i ∈ rang rcases n with (_ | _ | k) · exact ((show ¬Odd 0 by decide) h).elim · simp only [zero_add, range_one, sum_singleton, pow_zero, zero_lt_one] - rw [Nat.odd_iff_not_even] at h + rw [← Nat.not_even_iff_odd] at h rcases lt_trichotomy (x + 1) 0 with (hx | hx | hx) · have := geom_sum_alternating_of_lt_neg_one hx k.one_lt_succ_succ simp only [h, if_false] at this @@ -495,7 +495,7 @@ theorem Odd.geom_sum_pos [LinearOrderedRing α] (h : Odd n) : 0 < ∑ i ∈ rang theorem geom_sum_pos_iff [LinearOrderedRing α] (hn : n ≠ 0) : (0 < ∑ i ∈ range n, x ^ i) ↔ Odd n ∨ 0 < x + 1 := by refine ⟨fun h => ?_, ?_⟩ - · rw [or_iff_not_imp_left, ← not_le, ← Nat.even_iff_not_odd] + · rw [or_iff_not_imp_left, ← not_le, Nat.not_odd_iff_even] refine fun hn hx => h.not_le ?_ simpa [if_pos hn] using geom_sum_alternating_of_le_neg_one hx n · rintro (hn | hx') @@ -520,7 +520,7 @@ theorem geom_sum_eq_zero_iff_neg_one [LinearOrderedRing α] (hn : n ≠ 0) : refine ⟨fun h => ?_, @fun ⟨h, hn⟩ => by simp only [h, hn, neg_one_geom_sum, if_true]⟩ contrapose! h have hx := eq_or_ne x (-1) - cases' hx with hx hx + rcases hx with hx | hx · rw [hx, neg_one_geom_sum] simp only [h hx, ite_false, ne_eq, one_ne_zero, not_false_eq_true] · exact geom_sum_ne_zero hx hn @@ -528,7 +528,7 @@ theorem geom_sum_eq_zero_iff_neg_one [LinearOrderedRing α] (hn : n ≠ 0) : theorem geom_sum_neg_iff [LinearOrderedRing α] (hn : n ≠ 0) : ∑ i ∈ range n, x ^ i < 0 ↔ Even n ∧ x + 1 < 0 := by rw [← not_iff_not, not_lt, le_iff_lt_or_eq, eq_comm, - or_congr (geom_sum_pos_iff hn) (geom_sum_eq_zero_iff_neg_one hn), Nat.odd_iff_not_even, ← + or_congr (geom_sum_pos_iff hn) (geom_sum_eq_zero_iff_neg_one hn), ← Nat.not_even_iff_odd, ← add_eq_zero_iff_eq_neg, not_and, not_lt, le_iff_lt_or_eq, eq_comm, ← imp_iff_not_or, or_comm, and_comm, Decidable.and_or_imp, or_comm] diff --git a/Mathlib/Algebra/Group/Action/Defs.lean b/Mathlib/Algebra/Group/Action/Defs.lean index 220aa2d2f5e5c..91a530d0f239f 100644 --- a/Mathlib/Algebra/Group/Action/Defs.lean +++ b/Mathlib/Algebra/Group/Action/Defs.lean @@ -354,6 +354,24 @@ lemma smul_smul_smul_comm [SMul α β] [SMul α γ] [SMul β δ] [SMul α δ] [S [IsScalarTower α β δ] [IsScalarTower α γ δ] [SMulCommClass β γ δ] (a : α) (b : β) (c : γ) (d : δ) : (a • b) • c • d = (a • c) • b • d := by rw [smul_assoc, smul_assoc, smul_comm b] +/-- Note that the `IsScalarTower α β β` and `SMulCommClass α β β` typeclass arguments are usually +satisfied by `Algebra α β`. -/ +@[to_additive] +lemma smul_mul_smul_comm [Mul α] [Mul β] [SMul α β] [IsScalarTower α β β] + [IsScalarTower α α β] [SMulCommClass α β β] (a : α) (b : β) (c : α) (d : β) : + (a • b) * (c • d) = (a * c) • (b * d) := by + have : SMulCommClass β α β := .symm ..; exact smul_smul_smul_comm a b c d + +@[to_additive (attr := deprecated (since := "2024-08-29"))] +alias smul_mul_smul := smul_mul_smul_comm + +/-- Note that the `IsScalarTower α β β` and `SMulCommClass α β β` typeclass arguments are usually +satisfied by `Algebra α β`. -/ +@[to_additive] +lemma mul_smul_mul_comm [Mul α] [Mul β] [SMul α β] [IsScalarTower α β β] + [IsScalarTower α α β] [SMulCommClass α β β] (a b : α) (c d : β) : + (a * b) • (c * d) = (a • c) * (b • d) := smul_smul_smul_comm a b c d + variable [SMul M α] @[to_additive] @@ -444,19 +462,12 @@ instance IsScalarTower.left : IsScalarTower M M α where variable {M} -/-- Note that the `IsScalarTower M α α` and `SMulCommClass M α α` typeclass arguments are -usually satisfied by `Algebra M α`. -/ -@[to_additive] -- Porting note: nolint to_additive_doc -lemma smul_mul_smul [Mul α] (r s : M) (x y : α) [IsScalarTower M α α] [SMulCommClass M α α] : - r • x * s • y = (r * s) • (x * y) := by - rw [smul_mul_assoc, mul_smul_comm, ← smul_assoc, smul_eq_mul] - section Monoid variable [Monoid N] [MulAction M N] [IsScalarTower M N N] [SMulCommClass M N N] lemma smul_pow (r : M) (x : N) : ∀ n, (r • x) ^ n = r ^ n • x ^ n | 0 => by simp - | n + 1 => by rw [pow_succ', smul_pow _ _ n, smul_mul_smul, ← pow_succ', ← pow_succ'] + | n + 1 => by rw [pow_succ', smul_pow _ _ n, smul_mul_smul_comm, ← pow_succ', ← pow_succ'] end Monoid @@ -489,7 +500,7 @@ end Mul variable [Group H] [MulAction G H] [SMulCommClass G H H] [IsScalarTower G H H] lemma smul_inv (g : G) (a : H) : (g • a)⁻¹ = g⁻¹ • a⁻¹ := - inv_eq_of_mul_eq_one_right <| by rw [smul_mul_smul, mul_inv_cancel, mul_inv_cancel, one_smul] + inv_eq_of_mul_eq_one_right <| by rw [smul_mul_smul_comm, mul_inv_cancel, mul_inv_cancel, one_smul] lemma smul_zpow (g : G) (a : H) (n : ℤ) : (g • a) ^ n = g ^ n • a ^ n := by cases n <;> simp [smul_pow, smul_inv] diff --git a/Mathlib/Algebra/Group/Action/Prod.lean b/Mathlib/Algebra/Group/Action/Prod.lean index 0ce4d03aff4d1..e753d630bb914 100644 --- a/Mathlib/Algebra/Group/Action/Prod.lean +++ b/Mathlib/Algebra/Group/Action/Prod.lean @@ -132,7 +132,7 @@ section BundledSMul def smulMulHom [Monoid α] [Mul β] [MulAction α β] [IsScalarTower α β β] [SMulCommClass α β β] : α × β →ₙ* β where toFun a := a.1 • a.2 - map_mul' _ _ := (smul_mul_smul _ _ _ _).symm + map_mul' _ _ := (smul_mul_smul_comm _ _ _ _).symm /-- Scalar multiplication as a monoid homomorphism. -/ @[simps] diff --git a/Mathlib/Algebra/Group/Action/Units.lean b/Mathlib/Algebra/Group/Action/Units.lean index d7ad6e43cfdf4..b1b817a1fb920 100644 --- a/Mathlib/Algebra/Group/Action/Units.lean +++ b/Mathlib/Algebra/Group/Action/Units.lean @@ -69,8 +69,8 @@ instance mulAction' [Group G] [Monoid M] [MulAction G M] [SMulCommClass G M M] [IsScalarTower G M M] : MulAction G Mˣ where smul g m := ⟨g • (m : M), (g⁻¹ • ((m⁻¹ : Mˣ) : M)), - by rw [smul_mul_smul, Units.mul_inv, mul_inv_cancel, one_smul], - by rw [smul_mul_smul, Units.inv_mul, inv_mul_cancel, one_smul]⟩ + by rw [smul_mul_smul_comm, Units.mul_inv, mul_inv_cancel, one_smul], + by rw [smul_mul_smul_comm, Units.inv_mul, inv_mul_cancel, one_smul]⟩ one_smul m := Units.ext <| one_smul _ _ mul_smul g₁ g₂ m := Units.ext <| mul_smul _ _ _ diff --git a/Mathlib/Algebra/Group/AddChar.lean b/Mathlib/Algebra/Group/AddChar.lean index a8bb7908842b0..66268350d8718 100644 --- a/Mathlib/Algebra/Group/AddChar.lean +++ b/Mathlib/Algebra/Group/AddChar.lean @@ -23,6 +23,15 @@ We also include some constructions specific to the case when `A = R` is a ring; For more refined results of a number-theoretic nature (primitive characters, Gauss sums, etc) see `Mathlib.NumberTheory.LegendreSymbol.AddCharacter`. +# Implementation notes + +Due to their role as the dual of an additive group, additive characters must themselves be an +additive group. This contrasts to their pointwise operations which make them a multiplicative group. +We simply define both the additive and multiplicative group structures and prove them equal. + +For more information on this design decision, see the following zulip thread: +https://leanprover.zulipchat.com/#narrow/stream/116395-maths/topic/Additive.20characters + ## Tags additive character @@ -33,6 +42,8 @@ additive character -/ open Function Multiplicative +open Finset hiding card +open Fintype (card) section AddCharDef @@ -171,11 +182,18 @@ lemma coe_toAddMonoidHomEquiv (ψ : AddChar A M) : @[simp] lemma toAddMonoidHomEquiv_symm_apply (ψ : A →+ Additive M) (a : A) : toAddMonoidHomEquiv.symm ψ a = Additive.toMul (ψ a) := rfl -/-- The trivial additive character (sending everything to `1`) is `(1 : AddChar A M).` -/ +/-- The trivial additive character (sending everything to `1`). -/ instance instOne : One (AddChar A M) := toMonoidHomEquiv.one +/-- The trivial additive character (sending everything to `1`). -/ +instance instZero : Zero (AddChar A M) := ⟨1⟩ + @[simp, norm_cast] lemma coe_one : ⇑(1 : AddChar A M) = 1 := rfl +@[simp, norm_cast] lemma coe_zero : ⇑(0 : AddChar A M) = 1 := rfl @[simp] lemma one_apply (a : A) : (1 : AddChar A M) a = 1 := rfl +@[simp] lemma zero_apply (a : A) : (0 : AddChar A M) a = 1 := rfl + +lemma one_eq_zero : (1 : AddChar A M) = (0 : AddChar A M) := rfl instance instInhabited : Inhabited (AddChar A M) := ⟨1⟩ @@ -220,7 +238,9 @@ lemma compAddMonoidHom_injective_right (ψ : AddChar B M) (hψ : Injective ψ) : rw [DFunLike.ext'_iff] at h ⊢; exact hψ.comp_left h lemma eq_one_iff : ψ = 1 ↔ ∀ x, ψ x = 1 := DFunLike.ext_iff +lemma eq_zero_iff : ψ = 0 ↔ ∀ x, ψ x = 1 := DFunLike.ext_iff lemma ne_one_iff : ψ ≠ 1 ↔ ∃ x, ψ x ≠ 1 := DFunLike.ne_iff +lemma ne_zero_iff : ψ ≠ 0 ↔ ∃ x, ψ x ≠ 1 := DFunLike.ne_iff /-- An additive character is *nontrivial* if it takes a value `≠ 1`. -/ @[deprecated (since := "2024-06-06")] @@ -236,15 +256,40 @@ end Basic section toCommMonoid -variable {A M : Type*} [AddMonoid A] [CommMonoid M] +variable {ι A M : Type*} [AddMonoid A] [CommMonoid M] /-- When `M` is commutative, `AddChar A M` is a commutative monoid. -/ instance instCommMonoid : CommMonoid (AddChar A M) := toMonoidHomEquiv.commMonoid +/-- When `M` is commutative, `AddChar A M` is an additive commutative monoid. -/ +instance instAddCommMonoid : AddCommMonoid (AddChar A M) := Additive.addCommMonoid @[simp, norm_cast] lemma coe_mul (ψ χ : AddChar A M) : ⇑(ψ * χ) = ψ * χ := rfl +@[simp, norm_cast] lemma coe_add (ψ χ : AddChar A M) : ⇑(ψ + χ) = ψ * χ := rfl @[simp, norm_cast] lemma coe_pow (ψ : AddChar A M) (n : ℕ) : ⇑(ψ ^ n) = ψ ^ n := rfl -@[simp, norm_cast] lemma mul_apply (ψ φ : AddChar A M) (a : A) : (ψ * φ) a = ψ a * φ a := rfl -@[simp, norm_cast] lemma pow_apply (ψ : AddChar A M) (n : ℕ) (a : A) : (ψ ^ n) a = (ψ a) ^ n := rfl +@[simp, norm_cast] lemma coe_nsmul (n : ℕ) (ψ : AddChar A M) : ⇑(n • ψ) = ψ ^ n := rfl + +@[simp, norm_cast] +lemma coe_prod (s : Finset ι) (ψ : ι → AddChar A M) : ∏ i in s, ψ i = ∏ i in s, ⇑(ψ i) := by + induction s using Finset.cons_induction <;> simp [*] + +@[simp, norm_cast] +lemma coe_sum (s : Finset ι) (ψ : ι → AddChar A M) : ∑ i in s, ψ i = ∏ i in s, ⇑(ψ i) := by + induction s using Finset.cons_induction <;> simp [*] + +@[simp] lemma mul_apply (ψ φ : AddChar A M) (a : A) : (ψ * φ) a = ψ a * φ a := rfl +@[simp] lemma add_apply (ψ φ : AddChar A M) (a : A) : (ψ + φ) a = ψ a * φ a := rfl +@[simp] lemma pow_apply (ψ : AddChar A M) (n : ℕ) (a : A) : (ψ ^ n) a = (ψ a) ^ n := rfl +@[simp] lemma nsmul_apply (ψ : AddChar A M) (n : ℕ) (a : A) : (n • ψ) a = (ψ a) ^ n := rfl + +lemma prod_apply (s : Finset ι) (ψ : ι → AddChar A M) (a : A) : + (∏ i in s, ψ i) a = ∏ i in s, ψ i a := by rw [coe_prod, Finset.prod_apply] + +lemma sum_apply (s : Finset ι) (ψ : ι → AddChar A M) (a : A) : + (∑ i in s, ψ i) a = ∏ i in s, ψ i a := by rw [coe_sum, Finset.prod_apply] + +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 /-- The natural equivalence to `(Multiplicative A →* M)` is a monoid isomorphism. -/ def toMonoidHomMulEquiv : AddChar A M ≃* (Multiplicative A →* M) := @@ -255,8 +300,39 @@ def toMonoidHomMulEquiv : AddChar A M ≃* (Multiplicative A →* M) := def toAddMonoidAddEquiv : Additive (AddChar A M) ≃+ (A →+ Additive M) := { toAddMonoidHomEquiv with map_add' := fun φ ψ ↦ by rfl } +/-- The double dual embedding. -/ +def doubleDualEmb : A →+ AddChar (AddChar A M) M where + toFun a := { toFun := fun ψ ↦ ψ a + map_zero_eq_one' := by simp + map_add_eq_mul' := by simp } + map_zero' := by ext; simp + map_add' _ _ := by ext; simp [map_add_eq_mul] + +@[simp] lemma doubleDualEmb_apply (a : A) (ψ : AddChar A M) : doubleDualEmb a ψ = ψ a := rfl + end toCommMonoid +section CommSemiring +variable {A R : Type*} [AddGroup A] [Fintype A] [CommSemiring R] [IsDomain R] + [DecidableEq (AddChar A R)] {ψ : AddChar A R} + +lemma sum_eq_ite (ψ : AddChar A R) : ∑ a, ψ a = if ψ = 0 then ↑(card A) else 0 := by + split_ifs with h + · simp [h, card_univ] + obtain ⟨x, hx⟩ := ne_one_iff.1 h + refine eq_zero_of_mul_eq_self_left hx ?_ + rw [Finset.mul_sum] + exact Fintype.sum_equiv (Equiv.addLeft x) _ _ fun y ↦ (map_add_eq_mul ..).symm + +variable [CharZero R] + +lemma sum_eq_zero_iff_ne_zero : ∑ x, ψ x = 0 ↔ ψ ≠ 0 := by + rw [sum_eq_ite, Ne.ite_eq_right_iff]; exact Nat.cast_ne_zero.2 Fintype.card_ne_zero + +lemma sum_ne_zero_iff_eq_zero : ∑ x, ψ x ≠ 0 ↔ ψ = 0 := sum_eq_zero_iff_ne_zero.not_left + +end CommSemiring + /-! ## Additive characters of additive abelian groups -/ @@ -273,7 +349,13 @@ instance instCommGroup : CommGroup (AddChar A M) := inv := fun ψ ↦ ψ.compAddMonoidHom negAddMonoidHom inv_mul_cancel := fun ψ ↦ by ext1 x; simp [negAddMonoidHom, ← map_add_eq_mul]} -@[simp] lemma inv_apply (ψ : AddChar A M) (x : A) : ψ⁻¹ x = ψ (-x) := rfl +/-- The additive characters on a commutative additive group form a commutative group. -/ +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 end fromAddCommGroup @@ -307,7 +389,14 @@ section fromAddGrouptoDivisionCommMonoid variable {A M : Type*} [AddCommGroup A] [DivisionCommMonoid M] -lemma inv_apply' (ψ : AddChar A M) (x : A) : ψ⁻¹ x = (ψ x)⁻¹ := by rw [inv_apply, map_neg_eq_inv] +lemma inv_apply' (ψ : AddChar A M) (a : A) : ψ⁻¹ a = (ψ a)⁻¹ := by rw [inv_apply, map_neg_eq_inv] +lemma neg_apply' (ψ : AddChar A M) (a : A) : (-ψ) a = (ψ a)⁻¹ := map_neg_eq_inv _ _ + +lemma div_apply' (ψ χ : AddChar A M) (a : A) : (ψ / χ) a = ψ a / χ a := by + rw [div_apply, map_neg_eq_inv, div_eq_mul_inv] + +lemma sub_apply' (ψ χ : AddChar A M) (a : A) : (ψ - χ) a = ψ a / χ a := by + rw [sub_apply, map_neg_eq_inv, div_eq_mul_inv] lemma map_sub_eq_div (ψ : AddChar A M) (a b : A) : ψ (a - b) = ψ a / ψ b := ψ.toMonoidHom.map_div _ _ @@ -317,6 +406,14 @@ lemma injective_iff {ψ : AddChar A M} : Injective ψ ↔ ∀ ⦃x⦄, ψ x = 1 end fromAddGrouptoDivisionCommMonoid +section MonoidWithZero +variable {A M₀ : Type*} [AddGroup A] [MonoidWithZero M₀] [Nontrivial M₀] + +@[simp] lemma coe_ne_zero (ψ : AddChar A M₀) : (ψ : A → M₀) ≠ 0 := + ne_iff.2 ⟨0, fun h ↦ by simpa only [h, Pi.zero_apply, zero_ne_one] using map_zero_eq_one ψ⟩ + +end MonoidWithZero + /-! ## Additive characters of rings -/ diff --git a/Mathlib/Algebra/Group/Aut.lean b/Mathlib/Algebra/Group/Aut.lean index cb169b83f1a64..567b51be95470 100644 --- a/Mathlib/Algebra/Group/Aut.lean +++ b/Mathlib/Algebra/Group/Aut.lean @@ -17,7 +17,7 @@ The definition of multiplication in the automorphism groups agrees with function multiplication in `Equiv.Perm`, and multiplication in `CategoryTheory.End`, but not with `CategoryTheory.comp`. -This file is kept separate from `Data/Equiv/MulAdd` so that `GroupTheory.Perm` is free to use +This file is kept separate from `Algebra/Group/Equiv/*` so that `GroupTheory.Perm` is free to use equivalences (and other files that use them) before the group structure is defined. ## Tags diff --git a/Mathlib/Algebra/Group/Basic.lean b/Mathlib/Algebra/Group/Basic.lean index 9bd58b84c981b..8c68d20cf55f8 100644 --- a/Mathlib/Algebra/Group/Basic.lean +++ b/Mathlib/Algebra/Group/Basic.lean @@ -8,7 +8,6 @@ import Mathlib.Algebra.Group.Defs import Mathlib.Data.Nat.Defs import Mathlib.Data.Int.Defs import Mathlib.Logic.Function.Basic -import Mathlib.Tactic.Cases import Mathlib.Tactic.SimpRw import Mathlib.Tactic.SplitIfs @@ -91,7 +90,7 @@ section Semigroup variable [Semigroup α] @[to_additive] -instance Semigroup.to_isAssociative : Std.Associative (α := α) (· * ·) := ⟨mul_assoc⟩ +instance Semigroup.to_isAssociative : Std.Associative (α := α) (· * ·) := ⟨mul_assoc⟩ /-- Composing two multiplications on the left by `y` then `x` is equal to a multiplication on the left by `x * y`. @@ -524,6 +523,8 @@ theorem div_eq_inv_mul : a / b = b⁻¹ * a := by simp @[to_additive] theorem inv_mul_eq_div : a⁻¹ * b = b / a := by simp +@[to_additive] lemma inv_div_comm (a b : α) : a⁻¹ / b = b⁻¹ / a := by simp + @[to_additive] theorem inv_mul' : (a * b)⁻¹ = a⁻¹ / b := by simp @@ -727,13 +728,15 @@ theorem div_left_inj : b / a = c / a ↔ b = c := by rw [div_eq_mul_inv, div_eq_mul_inv] exact mul_left_inj _ -@[to_additive (attr := simp) sub_add_sub_cancel] -theorem div_mul_div_cancel' (a b c : G) : a / b * (b / c) = a / c := by +@[to_additive (attr := simp)] +theorem div_mul_div_cancel (a b c : G) : a / b * (b / c) = a / c := by rw [← mul_div_assoc, div_mul_cancel] -@[to_additive (attr := simp) sub_sub_sub_cancel_right] -theorem div_div_div_cancel_right' (a b c : G) : a / c / (b / c) = a / b := by - rw [← inv_div c b, div_inv_eq_mul, div_mul_div_cancel'] +@[to_additive (attr := simp)] +theorem div_div_div_cancel_right (a b c : G) : a / c / (b / c) = a / b := by + rw [← inv_div c b, div_inv_eq_mul, div_mul_div_cancel] + +@[deprecated (since := "2024-08-24")] alias div_div_div_cancel_right' := div_div_div_cancel_right @[to_additive] theorem div_eq_one : a / b = 1 ↔ a = b := @@ -832,6 +835,18 @@ lemma mul_zpow_self (a : G) (n : ℤ) : a ^ n * a = a ^ (n + 1) := (zpow_add_one @[to_additive sub_zsmul] lemma zpow_sub (a : G) (m n : ℤ) : a ^ (m - n) = a ^ m * (a ^ n)⁻¹ := by rw [Int.sub_eq_add_neg, zpow_add, zpow_neg] +@[to_additive natCast_sub_natCast_zsmul] +lemma zpow_natCast_sub_natCast (a : G) (m n : ℕ) : a ^ (m - n : ℤ) = a ^ m / a ^ n := by + simpa [div_eq_mul_inv] using zpow_sub a m n + +@[to_additive natCast_sub_one_zsmul] +lemma zpow_natCast_sub_one (a : G) (n : ℕ) : a ^ (n - 1 : ℤ) = a ^ n / a := by + simpa [div_eq_mul_inv] using zpow_sub a n 1 + +@[to_additive one_sub_natCast_zsmul] +lemma zpow_one_sub_natCast (a : G) (n : ℕ) : a ^ (1 - n : ℤ) = a / a ^ n := by + simpa [div_eq_mul_inv] using zpow_sub a 1 n + @[to_additive] lemma zpow_mul_comm (a : G) (m n : ℤ) : a ^ m * a ^ n = a ^ n * a ^ m := by rw [← zpow_add, Int.add_comm, zpow_add] @@ -949,9 +964,11 @@ theorem mul_mul_div_cancel (a b c : G) : a * c * (b / c) = a * b := by theorem div_mul_mul_cancel (a b c : G) : a / c * (b * c) = a * b := by rw [mul_left_comm, div_mul_cancel, mul_comm] -@[to_additive (attr := simp) sub_add_sub_cancel'] -theorem div_mul_div_cancel'' (a b c : G) : a / b * (c / a) = c / b := by - rw [mul_comm]; apply div_mul_div_cancel' +@[to_additive (attr := simp)] +theorem div_mul_div_cancel' (a b c : G) : a / b * (c / a) = c / b := by + rw [mul_comm]; apply div_mul_div_cancel + +@[deprecated (since := "2024-08-24")] alias div_mul_div_cancel'' := div_mul_div_cancel' @[to_additive (attr := simp)] theorem mul_div_div_cancel (a b c : G) : a * b / (a / c) = b * c := by @@ -959,7 +976,7 @@ theorem mul_div_div_cancel (a b c : G) : a * b / (a / c) = b * c := by @[to_additive (attr := simp)] theorem div_div_div_cancel_left (a b c : G) : c / a / (c / b) = b / a := by - rw [← inv_div b c, div_inv_eq_mul, mul_comm, div_mul_div_cancel'] + rw [← inv_div b c, div_inv_eq_mul, mul_comm, div_mul_div_cancel] @[to_additive] theorem div_eq_div_iff_mul_eq_mul : a / b = c / d ↔ a * d = c * b := by diff --git a/Mathlib/Algebra/Group/Commute/Defs.lean b/Mathlib/Algebra/Group/Commute/Defs.lean index f7933b6cd9c28..b7bcb09ff56a4 100644 --- a/Mathlib/Algebra/Group/Commute/Defs.lean +++ b/Mathlib/Algebra/Group/Commute/Defs.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Neil Strickland, Yury Kudryashov -/ import Mathlib.Algebra.Group.Semiconj.Defs -import Mathlib.Init.Algebra.Classes +import Mathlib.Order.Defs /-! # Commuting pairs of elements in monoids diff --git a/Mathlib/Algebra/Group/Conj.lean b/Mathlib/Algebra/Group/Conj.lean index 77426efb55ff3..3dbb4606b7541 100644 --- a/Mathlib/Algebra/Group/Conj.lean +++ b/Mathlib/Algebra/Group/Conj.lean @@ -99,7 +99,7 @@ theorem conj_pow {i : ℕ} {a b : α} : (a * b * a⁻¹) ^ i = a * b ^ i * a⁻ @[simp] theorem conj_zpow {i : ℤ} {a b : α} : (a * b * a⁻¹) ^ i = a * b ^ i * a⁻¹ := by - induction' i + induction i · change (a * b * a⁻¹) ^ (_ : ℤ) = a * b ^ (_ : ℤ) * a⁻¹ simp [zpow_natCast] · simp only [zpow_negSucc, conj_pow, mul_inv_rev, inv_inv] diff --git a/Mathlib/Algebra/Group/Defs.lean b/Mathlib/Algebra/Group/Defs.lean index e166aa22f3016..d1d9eaf700eef 100644 --- a/Mathlib/Algebra/Group/Defs.lean +++ b/Mathlib/Algebra/Group/Defs.lean @@ -332,7 +332,7 @@ class LeftCancelSemigroup (G : Type u) extends Semigroup G where library_note "lower cancel priority" /-- We lower the priority of inheriting from cancellative structures. -This attemts to avoid expensive checks involving bundling and unbundling with the `IsDomain` class. +This attempts to avoid expensive checks involving bundling and unbundling with the `IsDomain` class. since `IsDomain` already depends on `Semiring`, we can synthesize that one first. Zulip discussion: https://leanprover.zulipchat.com/#narrow/stream/113488-general/topic/Why.20is.20.60simpNF.60.20complaining.20here.3F -/ @@ -1031,7 +1031,7 @@ There is also a division operation `/` such that `a / b = a * b⁻¹`, with a default so that `a / b = a * b⁻¹` holds by definition. Use `Group.ofLeftAxioms` or `Group.ofRightAxioms` to define a group structure -on a type with the minumum proof obligations. +on a type with the minimum proof obligations. -/ class Group (G : Type u) extends DivInvMonoid G where protected inv_mul_cancel : ∀ a : G, a⁻¹ * a = 1 @@ -1042,7 +1042,7 @@ There is also a binary operation `-` such that `a - b = a + -b`, with a default so that `a - b = a + -b` holds by definition. Use `AddGroup.ofLeftAxioms` or `AddGroup.ofRightAxioms` to define an -additive group structure on a type with the minumum proof obligations. +additive group structure on a type with the minimum proof obligations. -/ class AddGroup (A : Type u) extends SubNegMonoid A where protected neg_add_cancel : ∀ a : A, -a + a = 0 diff --git a/Mathlib/Algebra/Group/Hom/Basic.lean b/Mathlib/Algebra/Group/Hom/Basic.lean index e1a97f26ed9b8..bac422e61797b 100644 --- a/Mathlib/Algebra/Group/Hom/Basic.lean +++ b/Mathlib/Algebra/Group/Hom/Basic.lean @@ -101,7 +101,7 @@ section Group variable [Group G] [CommGroup H] /-- 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'`. -/ +For the iff statement on the triviality of the kernel, see `injective_iff_map_eq_one'`. -/ @[to_additive "A homomorphism from an additive group to an additive monoid is injective iff its kernel is trivial. For the iff statement on the triviality of the kernel, diff --git a/Mathlib/Algebra/Group/Indicator.lean b/Mathlib/Algebra/Group/Indicator.lean index 68214b8258570..ccb3633809bca 100644 --- a/Mathlib/Algebra/Group/Indicator.lean +++ b/Mathlib/Algebra/Group/Indicator.lean @@ -41,7 +41,7 @@ section One variable [One M] [One N] {s t : Set α} {f g : α → M} {a : α} -/-- `Set.mulIndicator s f a` is `f a` if `a ∈ s`, `1` otherwise. -/ +/-- `Set.mulIndicator s f a` is `f a` if `a ∈ s`, `1` otherwise. -/ @[to_additive "`Set.indicator s f a` is `f a` if `a ∈ s`, `0` otherwise."] noncomputable def mulIndicator (s : Set α) (f : α → M) (x : α) : M := haveI := Classical.decPred (· ∈ s) diff --git a/Mathlib/Algebra/Group/InjSurj.lean b/Mathlib/Algebra/Group/InjSurj.lean index 41d0dd27c0297..a47bbde22c75a 100644 --- a/Mathlib/Algebra/Group/InjSurj.lean +++ b/Mathlib/Algebra/Group/InjSurj.lean @@ -26,7 +26,7 @@ And there are versions for (additive) (commutative) semigroups/monoids. ## Implementation note -The `nsmul` and `zsmul` assumptions on any tranfer definition for an algebraic structure involving +The `nsmul` and `zsmul` assumptions on any transfer definition for an algebraic structure involving both addition and multiplication (eg `AddMonoidWithOne`) is `∀ n x, f (n • x) = n • f x`, which is what we would expect. However, we cannot do the same for transfer definitions built using `to_additive` (eg `AddMonoid`) diff --git a/Mathlib/Algebra/Group/Nat.lean b/Mathlib/Algebra/Group/Nat.lean index c9678bda255d1..8ccb770e633d4 100644 --- a/Mathlib/Algebra/Group/Nat.lean +++ b/Mathlib/Algebra/Group/Nat.lean @@ -5,6 +5,7 @@ Authors: Floris van Doorn, Leonardo de Moura, Jeremy Avigad, Mario Carneiro -/ import Mathlib.Algebra.Group.Even import Mathlib.Algebra.Group.Units +import Mathlib.Data.Nat.Sqrt /-! # The natural numbers form a monoid @@ -96,7 +97,7 @@ lemma not_even_iff : ¬ Even n ↔ n % 2 = 1 := by rw [even_iff, mod_two_ne_zero @[simp] lemma not_even_one : ¬Even 1 := by simp [even_iff] @[parity_simps] lemma even_add : Even (m + n) ↔ (Even m ↔ Even n) := by - cases' mod_two_eq_zero_or_one m with h₁ h₁ <;> cases' mod_two_eq_zero_or_one n with h₂ h₂ <;> + rcases mod_two_eq_zero_or_one m with h₁ | h₁ <;> rcases mod_two_eq_zero_or_one n with h₂ | h₂ <;> simp [even_iff, h₁, h₂, Nat.add_mod] @[parity_simps] lemma even_add_one : Even (n + 1) ↔ ¬Even n := by simp [even_add] @@ -117,7 +118,7 @@ lemma two_not_dvd_two_mul_sub_one : ∀ {n}, 0 < n → ¬2 ∣ 2 * n - 1 by_cases h : Even n <;> simp [h] @[parity_simps] lemma even_mul : Even (m * n) ↔ Even m ∨ Even n := by - cases' mod_two_eq_zero_or_one m with h₁ h₁ <;> cases' mod_two_eq_zero_or_one n with h₂ h₂ <;> + rcases mod_two_eq_zero_or_one m with h₁ | h₁ <;> rcases mod_two_eq_zero_or_one n with h₂ | h₂ <;> simp [even_iff, h₁, h₂, Nat.mul_mod] /-- If `m` and `n` are natural numbers, then the natural number `m^n` is even diff --git a/Mathlib/Algebra/Group/NatPowAssoc.lean b/Mathlib/Algebra/Group/NatPowAssoc.lean index edb971427d8ac..0c97d42dd642b 100644 --- a/Mathlib/Algebra/Group/NatPowAssoc.lean +++ b/Mathlib/Algebra/Group/NatPowAssoc.lean @@ -116,9 +116,9 @@ instance Monoid.PowAssoc : NatPowAssoc M where @[simp, norm_cast] theorem Nat.cast_npow (R : Type*) [NonAssocSemiring R] [Pow R ℕ] [NatPowAssoc R] (n m : ℕ) : (↑(n ^ m) : R) = (↑n : R) ^ m := by - induction' m with m ih - · simp only [pow_zero, Nat.cast_one, npow_zero] - · rw [npow_add, npow_add, Nat.cast_mul, ih, npow_one, npow_one] + induction m with + | zero => simp only [pow_zero, Nat.cast_one, npow_zero] + | succ m ih => rw [npow_add, npow_add, Nat.cast_mul, ih, npow_one, npow_one] @[simp, norm_cast] theorem Int.cast_npow (R : Type*) [NonAssocRing R] [Pow R ℕ] [NatPowAssoc R] diff --git a/Mathlib/Data/Set/Pointwise/Basic.lean b/Mathlib/Algebra/Group/Pointwise/Set.lean similarity index 93% rename from Mathlib/Data/Set/Pointwise/Basic.lean rename to Mathlib/Algebra/Group/Pointwise/Set.lean index 81be1a2ed1658..6106467593c54 100644 --- a/Mathlib/Data/Set/Pointwise/Basic.lean +++ b/Mathlib/Algebra/Group/Pointwise/Set.lean @@ -6,10 +6,7 @@ Authors: Johan Commelin, Floris van Doorn import Mathlib.Algebra.Group.Equiv.Basic import Mathlib.Algebra.Group.Units.Hom import Mathlib.Algebra.Opposites -import Mathlib.Algebra.Ring.Defs -import Mathlib.Algebra.GroupWithZero.Basic import Mathlib.Data.Set.Lattice -import Mathlib.Tactic.Common /-! # Pointwise operations of sets @@ -50,7 +47,7 @@ set multiplication, set addition, pointwise addition, pointwise multiplication, pointwise subtraction -/ - +assert_not_exists MonoidWithZero assert_not_exists OrderedAddCommMonoid library_note "pointwise nat action"/-- @@ -707,10 +704,9 @@ scoped[Pointwise] attribute [instance] Set.monoid Set.addMonoid @[to_additive] theorem pow_mem_pow (ha : a ∈ s) : ∀ n : ℕ, a ^ n ∈ s ^ n | 0 => by - rw [pow_zero] - exact one_mem_one + simp only [pow_zero, mem_one] | n + 1 => by - rw [pow_succ] + simp only [pow_succ] exact mul_mem_mul (pow_mem_pow ha _) ha @[to_additive] @@ -726,9 +722,10 @@ theorem pow_subset_pow (hst : s ⊆ t) : ∀ n : ℕ, s ^ n ⊆ t ^ n theorem pow_subset_pow_of_one_mem (hs : (1 : α) ∈ s) (hn : m ≤ n) : s ^ m ⊆ s ^ n := by -- Porting note: `Nat.le_induction` didn't work as an induction principle in mathlib3, this was -- `refine Nat.le_induction ...` - induction' n, hn using Nat.le_induction with _ _ ih - · exact Subset.rfl - · dsimp only + induction n, hn using Nat.le_induction with + | base => exact Subset.rfl + | succ _ _ ih => + dsimp only rw [pow_succ'] exact ih.trans (subset_mul_right _ hs) @@ -828,56 +825,6 @@ protected noncomputable def divisionCommMonoid [DivisionCommMonoid α] : DivisionCommMonoid (Set α) := { Set.divisionMonoid, Set.commSemigroup with } -/-- `Set α` has distributive negation if `α` has. -/ -protected noncomputable def hasDistribNeg [Mul α] [HasDistribNeg α] : HasDistribNeg (Set α) := - { Set.involutiveNeg with - neg_mul := fun _ _ => by - simp_rw [← image_neg] - exact image2_image_left_comm neg_mul - mul_neg := fun _ _ => by - simp_rw [← image_neg] - exact image_image2_right_comm mul_neg } - -scoped[Pointwise] - attribute [instance] Set.divisionCommMonoid Set.subtractionCommMonoid Set.hasDistribNeg - -section Distrib - -variable [Distrib α] (s t u : Set α) - -/-! -Note that `Set α` is not a `Distrib` because `s * t + s * u` has cross terms that `s * (t + u)` -lacks. --/ - - -theorem mul_add_subset : s * (t + u) ⊆ s * t + s * u := - image2_distrib_subset_left mul_add - -theorem add_mul_subset : (s + t) * u ⊆ s * u + t * u := - image2_distrib_subset_right add_mul - -end Distrib - -section MulZeroClass - -variable [MulZeroClass α] {s t : Set α} - -/-! Note that `Set` is not a `MulZeroClass` because `0 * ∅ ≠ 0`. -/ - - -theorem mul_zero_subset (s : Set α) : s * 0 ⊆ 0 := by simp [subset_def, mem_mul] - -theorem zero_mul_subset (s : Set α) : 0 * s ⊆ 0 := by simp [subset_def, mem_mul] - -theorem Nonempty.mul_zero (hs : s.Nonempty) : s * 0 = 0 := - s.mul_zero_subset.antisymm <| by simpa [mem_mul] using hs - -theorem Nonempty.zero_mul (hs : s.Nonempty) : 0 * s = 0 := - s.zero_mul_subset.antisymm <| by simpa [mem_mul] using hs - -end MulZeroClass - section Group variable [Group α] {s t : Set α} {a b : α} @@ -958,22 +905,6 @@ theorem univ_mul (ht : t.Nonempty) : (univ : Set α) * t = univ := end Group -section GroupWithZero - -variable [GroupWithZero α] {s t : Set α} - -theorem div_zero_subset (s : Set α) : s / 0 ⊆ 0 := by simp [subset_def, mem_div] - -theorem zero_div_subset (s : Set α) : 0 / s ⊆ 0 := by simp [subset_def, mem_div] - -theorem Nonempty.div_zero (hs : s.Nonempty) : s / 0 = 0 := - s.div_zero_subset.antisymm <| by simpa [mem_div] using hs - -theorem Nonempty.zero_div (hs : s.Nonempty) : 0 / s = 0 := - s.zero_div_subset.antisymm <| by simpa [mem_div] using hs - -end GroupWithZero - section Mul variable [Mul α] [Mul β] [FunLike F α β] [MulHomClass F α β] (m : F) {s t : Set α} diff --git a/Mathlib/Algebra/Group/Prod.lean b/Mathlib/Algebra/Group/Prod.lean index d1a779b29708d..50077030df988 100644 --- a/Mathlib/Algebra/Group/Prod.lean +++ b/Mathlib/Algebra/Group/Prod.lean @@ -89,6 +89,9 @@ theorem snd_one [One M] [One N] : (1 : M × N).2 = 1 := theorem one_eq_mk [One M] [One N] : (1 : M × N) = (1, 1) := rfl +@[to_additive (attr := simp)] +theorem mk_one_one [One M] [One N] : ((1 : M), (1 : N)) = 1 := rfl + @[to_additive (attr := simp)] theorem mk_eq_one [One M] [One N] {x : M} {y : N} : (x, y) = 1 ↔ x = 1 ∧ y = 1 := mk.inj_iff diff --git a/Mathlib/Algebra/Group/Semiconj/Defs.lean b/Mathlib/Algebra/Group/Semiconj/Defs.lean index 460a09c83cf47..83e158027c671 100644 --- a/Mathlib/Algebra/Group/Semiconj/Defs.lean +++ b/Mathlib/Algebra/Group/Semiconj/Defs.lean @@ -7,7 +7,6 @@ Some proofs and docs came from mathlib3 `src/algebra/commute.lean` (c) Neil Stri -/ import Mathlib.Algebra.Group.Defs import Mathlib.Init.Logic -import Mathlib.Tactic.Cases /-! # Semiconjugate elements of a semigroup diff --git a/Mathlib/Algebra/Group/Subgroup/Basic.lean b/Mathlib/Algebra/Group/Subgroup/Basic.lean index 5ca49efc06b4f..6dac44cd315aa 100644 --- a/Mathlib/Algebra/Group/Subgroup/Basic.lean +++ b/Mathlib/Algebra/Group/Subgroup/Basic.lean @@ -86,7 +86,7 @@ assert_not_exists Multiset assert_not_exists Ring open Function -open Int +open scoped Int variable {G G' G'' : Type*} [Group G] [Group G'] [Group G''] variable {A : Type*} [AddGroup A] @@ -583,8 +583,8 @@ theorem coe_pow (x : H) (n : ℕ) : ((x ^ n : H) : G) = (x : G) ^ n := theorem coe_zpow (x : H) (n : ℤ) : ((x ^ n : H) : G) = (x : G) ^ n := rfl -@[to_additive] -- This can be proved by `Submonoid.mk_eq_one` -theorem mk_eq_one {g : G} {h} : (⟨g, h⟩ : H) = 1 ↔ g = 1 := by simp +@[to_additive (attr := simp)] -- This can be proved by `Submonoid.mk_eq_one` +theorem mk_eq_one {g : G} {h} : (⟨g, h⟩ : H) = 1 ↔ g = 1 := Submonoid.mk_eq_one .. /-- A subgroup of a group inherits a group structure. -/ @[to_additive "An `AddSubgroup` of an `AddGroup` inherits an `AddGroup` structure."] @@ -892,7 +892,7 @@ theorem closure_induction {p : G → Prop} {x} (h : x ∈ closure k) (mem : ∀ (mul : ∀ x y, p x → p y → p (x * y)) (inv : ∀ x, p x → p x⁻¹) : p x := (@closure_le _ _ ⟨⟨⟨setOf p, fun {x y} ↦ mul x y⟩, one⟩, fun {x} ↦ inv x⟩ k).2 mem h -/-- A dependent version of `Subgroup.closure_induction`. -/ +/-- A dependent version of `Subgroup.closure_induction`. -/ @[to_additive (attr := elab_as_elim) "A dependent version of `AddSubgroup.closure_induction`. "] theorem closure_induction' {p : ∀ x, x ∈ closure k → Prop} (mem : ∀ (x) (h : x ∈ k), p x (subset_closure h)) (one : p 1 (one_mem _)) @@ -1076,7 +1076,7 @@ theorem toAddSubgroup_comap {G₂ : Type*} [Group G₂] (f : G →* G₂) (s : S @[simp] theorem _root_.AddSubgroup.toSubgroup_comap {A A₂ : Type*} [AddGroup A] [AddGroup A₂] - (f : A →+ A₂) (s : AddSubgroup A₂) : + (f : A →+ A₂) (s : AddSubgroup A₂) : s.toSubgroup.comap (AddMonoidHom.toMultiplicative f) = AddSubgroup.toSubgroup (s.comap f) := rfl @[to_additive (attr := simp)] @@ -1366,7 +1366,7 @@ theorem top_prod_top : (⊤ : Subgroup G).prod (⊤ : Subgroup N) = ⊤ := @[to_additive] theorem bot_prod_bot : (⊥ : Subgroup G).prod (⊥ : Subgroup N) = ⊥ := - SetLike.coe_injective <| by simp [coe_prod, Prod.one_eq_mk] + SetLike.coe_injective <| by simp [coe_prod] @[to_additive le_prod_iff] theorem le_prod_iff {H : Subgroup G} {K : Subgroup N} {J : Subgroup (G × N)} : @@ -1709,7 +1709,7 @@ def _root_.NormalizerCondition := variable {G} /-- Alternative phrasing of the normalizer condition: Only the full group is self-normalizing. -This may be easier to work with, as it avoids inequalities and negations. -/ +This may be easier to work with, as it avoids inequalities and negations. -/ theorem _root_.normalizerCondition_iff_only_full_group_self_normalizing : NormalizerCondition G ↔ ∀ H : Subgroup G, H.normalizer = H → H = ⊤ := by apply forall_congr'; intro H @@ -1770,7 +1770,7 @@ instance subgroupOf_isCommutative [H.IsCommutative] : (H.subgroupOf K).IsCommuta @[to_additive] lemma mul_comm_of_mem_isCommutative [H.IsCommutative] {a b : G} (ha : a ∈ H) (hb : b ∈ H) : a * b = b * a := by - simpa only [Submonoid.mk_mul_mk, Subtype.mk.injEq] using mul_comm (⟨a, ha⟩ : H) (⟨b, hb⟩ : H) + simpa only [MulMemClass.mk_mul_mk, Subtype.mk.injEq] using mul_comm (⟨a, ha⟩ : H) (⟨b, hb⟩ : H) end Subgroup @@ -2912,3 +2912,5 @@ def noncenter (G : Type*) [Monoid G] : Set (ConjClasses G) := g ∈ noncenter G ↔ g.carrier.Nontrivial := Iff.rfl end ConjClasses + +set_option linter.style.longFile 3000 diff --git a/Mathlib/Algebra/Group/Subgroup/Finite.lean b/Mathlib/Algebra/Group/Subgroup/Finite.lean index 14f53f72374fd..b4dc8b267698d 100644 --- a/Mathlib/Algebra/Group/Subgroup/Finite.lean +++ b/Mathlib/Algebra/Group/Subgroup/Finite.lean @@ -102,26 +102,24 @@ theorem card_top : Nat.card (⊤ : Subgroup G) = Nat.card G := Nat.card_congr Subgroup.topEquiv.toEquiv @[to_additive] -theorem eq_top_of_card_eq [Finite H] (h : Nat.card H = Nat.card G) : - H = ⊤ := by - have : Nonempty H := ⟨1, one_mem H⟩ - have h' : Nat.card H ≠ 0 := Nat.card_pos.ne' - have : Finite G := (Nat.finite_of_card_ne_zero (h ▸ h')) - have : Fintype G := Fintype.ofFinite G - have : Fintype H := Fintype.ofFinite H - rw [Nat.card_eq_fintype_card, Nat.card_eq_fintype_card] at h - rw [SetLike.ext'_iff, coe_top, ← Finset.coe_univ, ← (H : Set G).coe_toFinset, Finset.coe_inj, ← - Finset.card_eq_iff_eq_univ, ← h, Set.toFinset_card] - congr +theorem eq_of_le_of_card_ge {H K : Subgroup G} [Finite K] (hle : H ≤ K) + (hcard : Nat.card K ≤ Nat.card H) : + H = K := + SetLike.coe_injective <| Set.Finite.eq_of_subset_of_card_le (Set.toFinite _) hle hcard + +@[to_additive] +theorem eq_top_of_le_card [Finite G] (h : Nat.card G ≤ Nat.card H) : H = ⊤ := + eq_of_le_of_card_ge le_top (Nat.card_congr (Equiv.Set.univ G) ▸ h) + +@[to_additive] +theorem eq_top_of_card_eq [Finite H] (h : Nat.card H = Nat.card G) : H = ⊤ := by + have : Finite G := Nat.finite_of_card_ne_zero (h ▸ Nat.card_pos.ne') + exact eq_top_of_le_card _ (Nat.le_of_eq h.symm) @[to_additive (attr := simp)] theorem card_eq_iff_eq_top [Finite H] : Nat.card H = Nat.card G ↔ H = ⊤ := Iff.intro (eq_top_of_card_eq H) (fun h ↦ by simpa only [h] using card_top) -@[to_additive] -theorem eq_top_of_le_card [Finite G] (h : Nat.card G ≤ Nat.card H) : H = ⊤ := - eq_top_of_card_eq H (le_antisymm (Nat.card_le_card_of_injective H.subtype H.subtype_injective) h) - @[to_additive] theorem eq_bot_of_card_le [Finite H] (h : Nat.card H ≤ 1) : H = ⊥ := let _ := Finite.card_le_one_iff_subsingleton.mp h @@ -147,6 +145,10 @@ theorem one_lt_card_iff_ne_bot [Finite H] : 1 < Nat.card H ↔ H ≠ ⊥ := theorem card_le_card_group [Finite G] : Nat.card H ≤ Nat.card G := Nat.card_le_card_of_injective _ Subtype.coe_injective +@[to_additive] +theorem card_le_of_le {H K : Subgroup G} [Finite K] (h : H ≤ K) : Nat.card H ≤ Nat.card K := + Nat.card_le_card_of_injective _ (Subgroup.inclusion_injective h) + end Subgroup namespace Subgroup @@ -161,11 +163,14 @@ variable {η : Type*} {f : η → Type*} [∀ i, Group (f i)] theorem pi_mem_of_mulSingle_mem_aux [DecidableEq η] (I : Finset η) {H : Subgroup (∀ i, f i)} (x : ∀ i, f i) (h1 : ∀ i, i ∉ I → x i = 1) (h2 : ∀ i, i ∈ I → Pi.mulSingle i (x i) ∈ H) : x ∈ H := by - induction' I using Finset.induction_on with i I hnmem ih generalizing x - · convert one_mem H + 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 = Function.update x i 1 * Pi.mulSingle i (x i) := by + | insert hnmem ih => + rename_i i I + have : x = Function.update x i 1 * Pi.mulSingle i (x i) := by ext j by_cases heq : j = i · subst heq @@ -195,7 +200,7 @@ theorem pi_mem_of_mulSingle_mem [Finite η] [DecidableEq η] {H : Subgroup (∀ cases nonempty_fintype η exact pi_mem_of_mulSingle_mem_aux Finset.univ x (by simp) fun i _ => h i -/-- For finite index types, the `Subgroup.pi` is generated by the embeddings of the groups. -/ +/-- For finite index types, the `Subgroup.pi` is generated by the embeddings of the groups. -/ @[to_additive "For finite index types, the `Subgroup.pi` is generated by the embeddings of the additive groups."] theorem pi_le_iff [DecidableEq η] [Finite η] {H : ∀ i, Subgroup (f i)} {J : Subgroup (∀ i, f i)} : diff --git a/Mathlib/Algebra/Group/Subgroup/MulOpposite.lean b/Mathlib/Algebra/Group/Subgroup/MulOpposite.lean index a7a48a1eb4d46..23411262639fa 100644 --- a/Mathlib/Algebra/Group/Subgroup/MulOpposite.lean +++ b/Mathlib/Algebra/Group/Subgroup/MulOpposite.lean @@ -15,7 +15,6 @@ subgroup, subgroups -/ - variable {ι : Sort*} {G : Type*} [Group G] namespace Subgroup @@ -29,6 +28,10 @@ protected def op (H : Subgroup G) : Subgroup Gᵐᵒᵖ where mul_mem' ha hb := H.mul_mem hb ha inv_mem' := H.inv_mem +#adaptation_note /-- After lean4#5020, some instances need to be copied to obtain the correct +discrimination tree key. -/ +@[to_additive] instance instSMul (H : Subgroup G) : SMul H.op G := Submonoid.smul .. + @[to_additive (attr := simp)] theorem mem_op {x : Gᵐᵒᵖ} {S : Subgroup G} : x ∈ S.op ↔ x.unop ∈ S := Iff.rfl @@ -86,17 +89,41 @@ def opEquiv : Subgroup G ≃o Subgroup Gᵐᵒᵖ where right_inv := op_unop map_rel_iff' := op_le_op_iff +@[to_additive] +theorem op_injective : (@Subgroup.op G _).Injective := opEquiv.injective + +@[to_additive] +theorem unop_injective : (@Subgroup.unop G _).Injective := opEquiv.symm.injective + +@[to_additive (attr := simp)] +theorem op_inj {S T : Subgroup G} : S.op = T.op ↔ S = T := opEquiv.eq_iff_eq + +@[to_additive (attr := simp)] +theorem unop_inj {S T : Subgroup Gᵐᵒᵖ} : S.unop = T.unop ↔ S = T := opEquiv.symm.eq_iff_eq + @[to_additive (attr := simp)] theorem op_bot : (⊥ : Subgroup G).op = ⊥ := opEquiv.map_bot +@[to_additive (attr := simp)] +theorem op_eq_bot {S : Subgroup G} : S.op = ⊥ ↔ S = ⊥ := op_injective.eq_iff' op_bot + @[to_additive (attr := simp)] theorem unop_bot : (⊥ : Subgroup Gᵐᵒᵖ).unop = ⊥ := opEquiv.symm.map_bot @[to_additive (attr := simp)] -theorem op_top : (⊤ : Subgroup G).op = ⊤ := opEquiv.map_top +theorem unop_eq_bot {S : Subgroup Gᵐᵒᵖ} : S.unop = ⊥ ↔ S = ⊥ := unop_injective.eq_iff' unop_bot + +@[to_additive (attr := simp)] +theorem op_top : (⊤ : Subgroup G).op = ⊤ := rfl + +@[to_additive (attr := simp)] +theorem op_eq_top {S : Subgroup G} : S.op = ⊤ ↔ S = ⊤ := op_injective.eq_iff' op_top + +@[to_additive (attr := simp)] +theorem unop_top : (⊤ : Subgroup Gᵐᵒᵖ).unop = ⊤ := rfl @[to_additive (attr := simp)] -theorem unop_top : (⊤ : Subgroup Gᵐᵒᵖ).unop = ⊤ := opEquiv.symm.map_top +theorem unop_eq_top {S : Subgroup Gᵐᵒᵖ} : S.unop = ⊤ ↔ S = ⊤ := unop_injective.eq_iff' unop_top @[to_additive] theorem op_sup (S₁ S₂ : Subgroup G) : (S₁ ⊔ S₂).op = S₁.op ⊔ S₂.op := @@ -107,11 +134,10 @@ theorem unop_sup (S₁ S₂ : Subgroup Gᵐᵒᵖ) : (S₁ ⊔ S₂).unop = S₁ opEquiv.symm.map_sup _ _ @[to_additive] -theorem op_inf (S₁ S₂ : Subgroup G) : (S₁ ⊓ S₂).op = S₁.op ⊓ S₂.op := opEquiv.map_inf _ _ +theorem op_inf (S₁ S₂ : Subgroup G) : (S₁ ⊓ S₂).op = S₁.op ⊓ S₂.op := rfl @[to_additive] -theorem unop_inf (S₁ S₂ : Subgroup Gᵐᵒᵖ) : (S₁ ⊓ S₂).unop = S₁.unop ⊓ S₂.unop := - opEquiv.symm.map_inf _ _ +theorem unop_inf (S₁ S₂ : Subgroup Gᵐᵒᵖ) : (S₁ ⊓ S₂).unop = S₁.unop ⊓ S₂.unop := rfl @[to_additive] theorem op_sSup (S : Set (Subgroup G)) : (sSup S).op = sSup (.unop ⁻¹' S) := @@ -151,9 +177,8 @@ theorem op_closure (s : Set G) : (closure s).op = closure (MulOpposite.unop ⁻ @[to_additive] theorem unop_closure (s : Set Gᵐᵒᵖ) : (closure s).unop = closure (MulOpposite.op ⁻¹' s) := by - simp_rw [closure, unop_sInf, Set.preimage_setOf_eq, Subgroup.op_coe] - congr with a - exact MulOpposite.op_surjective.forall + rw [← op_inj, op_unop, op_closure] + rfl /-- Bijection between a subgroup `H` and its opposite. -/ @[to_additive (attr := simps!) "Bijection between an additive subgroup `H` and its opposite."] @@ -173,4 +198,31 @@ theorem smul_opposite_mul {H : Subgroup G} (x g : G) (h : H.op) : h • (g * x) = g * h • x := mul_assoc _ _ _ +@[to_additive] +theorem op_normalizer (H : Subgroup G) : H.normalizer.op = H.op.normalizer := by + ext x + simp [mem_normalizer_iff', MulOpposite.op_surjective.forall, iff_comm] + +@[to_additive] +theorem unop_normalizer (H : Subgroup Gᵐᵒᵖ) : H.normalizer.unop = H.unop.normalizer := by + rw [← op_inj, op_unop, op_normalizer, op_unop] + +@[to_additive (attr := simp)] +theorem normal_op {H : Subgroup G} : H.op.Normal ↔ H.Normal := by + simp only [← normalizer_eq_top, ← op_normalizer, op_eq_top] + +@[to_additive] alias ⟨Normal.of_op, Normal.op⟩ := normal_op + +@[to_additive] +instance op.instNormal {H : Subgroup G} [H.Normal] : H.op.Normal := .op ‹_› + +@[to_additive (attr := simp)] +theorem normal_unop {H : Subgroup Gᵐᵒᵖ} : H.unop.Normal ↔ H.Normal := by + rw [← normal_op, op_unop] + +@[to_additive] alias ⟨Normal.of_unop, Normal.unop⟩ := normal_unop + +@[to_additive] +instance unop.instNormal {H : Subgroup Gᵐᵒᵖ} [H.Normal] : H.unop.Normal := .unop ‹_› + end Subgroup diff --git a/Mathlib/Algebra/Group/Subgroup/Pointwise.lean b/Mathlib/Algebra/Group/Subgroup/Pointwise.lean index 71e4f17ffc5ea..c340d58d2eccf 100644 --- a/Mathlib/Algebra/Group/Subgroup/Pointwise.lean +++ b/Mathlib/Algebra/Group/Subgroup/Pointwise.lean @@ -242,6 +242,16 @@ instance sup_normal (H K : Subgroup G) [hH : H.Normal] [hK : K.Normal] : (H ⊔ refine ⟨g * h * g⁻¹, hH.conj_mem h hh g, g * k * g⁻¹, hK.conj_mem k hk g, ?_⟩ simp only [mul_assoc, inv_mul_cancel_left] +@[to_additive] +theorem smul_mem_of_mem_closure_of_mem {X : Type*} [MulAction G X] {s : Set G} {t : Set X} + (hs : ∀ g ∈ s, g⁻¹ ∈ s) (hst : ∀ᵉ (g ∈ s) (x ∈ t), g • x ∈ t) {g : G} + (hg : g ∈ Subgroup.closure s) {x : X} (hx : x ∈ t) : g • x ∈ t := by + induction hg using Subgroup.closure_induction'' generalizing x with + | one => simpa + | mem g' hg' => exact hst g' hg' x hx + | inv_mem g' hg' => exact hst g'⁻¹ (hs g' hg') x hx + | mul _ _ _ _ h₁ h₂ => rw [mul_smul]; exact h₁ (h₂ hx) + @[to_additive] theorem smul_opposite_image_mul_preimage' (g : G) (h : Gᵐᵒᵖ) (s : Set G) : (fun y => h • y) '' ((g * ·) ⁻¹' s) = (g * ·) ⁻¹' ((fun y => h • y) '' s) := by diff --git a/Mathlib/Algebra/Group/Submonoid/Basic.lean b/Mathlib/Algebra/Group/Submonoid/Basic.lean index 35c066cced16e..ddb7f8577ed46 100644 --- a/Mathlib/Algebra/Group/Submonoid/Basic.lean +++ b/Mathlib/Algebra/Group/Submonoid/Basic.lean @@ -376,7 +376,7 @@ theorem closure_induction {p : M → Prop} {x} (h : x ∈ closure s) (mem : ∀ (mul : ∀ x y, p x → p y → p (x * y)) : p x := (@closure_le _ _ _ ⟨⟨p, mul _ _⟩, one⟩).2 mem h -/-- A dependent version of `Submonoid.closure_induction`. -/ +/-- A dependent version of `Submonoid.closure_induction`. -/ @[to_additive (attr := elab_as_elim) "A dependent version of `AddSubmonoid.closure_induction`. "] theorem closure_induction' (s : Set M) {p : ∀ x, x ∈ closure s → Prop} (mem : ∀ (x) (h : x ∈ s), p x (subset_closure h)) (one : p 1 (one_mem _)) @@ -387,7 +387,7 @@ theorem closure_induction' (s : Set M) {p : ∀ x, x ∈ closure s → Prop} closure_induction hx (fun x hx => ⟨_, mem x hx⟩) ⟨_, one⟩ fun x y ⟨hx', hx⟩ ⟨hy', hy⟩ => ⟨_, mul _ _ _ _ hx hy⟩ -/-- An induction principle for closure membership for predicates with two arguments. -/ +/-- An induction principle for closure membership for predicates with two arguments. -/ @[to_additive (attr := elab_as_elim) "An induction principle for additive closure membership for predicates with two arguments."] theorem closure_induction₂ {p : M → M → Prop} {x} {y : M} (hx : x ∈ closure s) (hy : y ∈ closure s) diff --git a/Mathlib/Algebra/Group/Submonoid/Membership.lean b/Mathlib/Algebra/Group/Submonoid/Membership.lean index 8c8595e52f624..e1ec1fb022a46 100644 --- a/Mathlib/Algebra/Group/Submonoid/Membership.lean +++ b/Mathlib/Algebra/Group/Submonoid/Membership.lean @@ -131,7 +131,7 @@ theorem multiset_prod_mem {M} [CommMonoid M] (S : Submonoid M) (m : Multiset M) @[to_additive] theorem multiset_noncommProd_mem (S : Submonoid M) (m : Multiset M) (comm) (h : ∀ x ∈ m, x ∈ S) : m.noncommProd comm ∈ S := by - induction' m using Quotient.inductionOn with l + induction m using Quotient.inductionOn with | h l => ?_ simp only [Multiset.quot_mk_to_coe, Multiset.noncommProd_coe] exact Submonoid.list_prod_mem _ h @@ -293,7 +293,7 @@ variable {S : Submonoid M} [Fintype S] open Fintype /- curly brackets `{}` are used here instead of instance brackets `[]` because - the instance in a goal is often not the same as the one inferred by type class inference. -/ + the instance in a goal is often not the same as the one inferred by type class inference. -/ @[to_additive] theorem card_bot {_ : Fintype (⊥ : Submonoid M)} : card (⊥ : Submonoid M) = 1 := card_eq_one_iff.2 @@ -356,9 +356,10 @@ theorem closure_induction_left {s : Set M} {p : (m : M) → m ∈ closure s → p x h := by simp_rw [closure_eq_mrange] at h obtain ⟨l, rfl⟩ := h - induction' l with x y ih - · exact one - · simp only [map_mul, FreeMonoid.lift_eval_of] + induction l with + | h0 => exact one + | ih x y ih => + simp only [map_mul, FreeMonoid.lift_eval_of] refine mul_left _ x.prop (FreeMonoid.lift Subtype.val y) _ (ih ?_) simp only [closure_eq_mrange, mem_mrange, exists_apply_eq_apply] diff --git a/Mathlib/Algebra/Group/Submonoid/MulOpposite.lean b/Mathlib/Algebra/Group/Submonoid/MulOpposite.lean index 3a6e6f07ce8ba..ce69dc1d1759d 100644 --- a/Mathlib/Algebra/Group/Submonoid/MulOpposite.lean +++ b/Mathlib/Algebra/Group/Submonoid/MulOpposite.lean @@ -75,17 +75,41 @@ def opEquiv : Submonoid M ≃o Submonoid Mᵐᵒᵖ where right_inv := op_unop map_rel_iff' := op_le_op_iff +@[to_additive] +theorem op_injective : (@Submonoid.op M _).Injective := opEquiv.injective + +@[to_additive] +theorem unop_injective : (@Submonoid.unop M _).Injective := opEquiv.symm.injective + +@[to_additive (attr := simp)] +theorem op_inj {S T : Submonoid M} : S.op = T.op ↔ S = T := opEquiv.eq_iff_eq + +@[to_additive (attr := simp)] +theorem unop_inj {S T : Submonoid Mᵐᵒᵖ} : S.unop = T.unop ↔ S = T := opEquiv.symm.eq_iff_eq + @[to_additive (attr := simp)] theorem op_bot : (⊥ : Submonoid M).op = ⊥ := opEquiv.map_bot +@[to_additive (attr := simp)] +theorem op_eq_bot {S : Submonoid M} : S.op = ⊥ ↔ S = ⊥ := op_injective.eq_iff' op_bot + @[to_additive (attr := simp)] theorem unop_bot : (⊥ : Submonoid Mᵐᵒᵖ).unop = ⊥ := opEquiv.symm.map_bot @[to_additive (attr := simp)] -theorem op_top : (⊤ : Submonoid M).op = ⊤ := opEquiv.map_top +theorem unop_eq_bot {S : Submonoid Mᵐᵒᵖ} : S.unop = ⊥ ↔ S = ⊥ := unop_injective.eq_iff' unop_bot + +@[to_additive (attr := simp)] +theorem op_top : (⊤ : Submonoid M).op = ⊤ := rfl + +@[to_additive (attr := simp)] +theorem op_eq_top {S : Submonoid M} : S.op = ⊤ ↔ S = ⊤ := op_injective.eq_iff' op_top + +@[to_additive (attr := simp)] +theorem unop_top : (⊤ : Submonoid Mᵐᵒᵖ).unop = ⊤ := rfl @[to_additive (attr := simp)] -theorem unop_top : (⊤ : Submonoid Mᵐᵒᵖ).unop = ⊤ := opEquiv.symm.map_top +theorem unop_eq_top {S : Submonoid Mᵐᵒᵖ} : S.unop = ⊤ ↔ S = ⊤ := unop_injective.eq_iff' unop_top @[to_additive] theorem op_sup (S₁ S₂ : Submonoid M) : (S₁ ⊔ S₂).op = S₁.op ⊔ S₂.op := @@ -96,11 +120,10 @@ theorem unop_sup (S₁ S₂ : Submonoid Mᵐᵒᵖ) : (S₁ ⊔ S₂).unop = S opEquiv.symm.map_sup _ _ @[to_additive] -theorem op_inf (S₁ S₂ : Submonoid M) : (S₁ ⊓ S₂).op = S₁.op ⊓ S₂.op := opEquiv.map_inf _ _ +theorem op_inf (S₁ S₂ : Submonoid M) : (S₁ ⊓ S₂).op = S₁.op ⊓ S₂.op := rfl @[to_additive] -theorem unop_inf (S₁ S₂ : Submonoid Mᵐᵒᵖ) : (S₁ ⊓ S₂).unop = S₁.unop ⊓ S₂.unop := - opEquiv.symm.map_inf _ _ +theorem unop_inf (S₁ S₂ : Submonoid Mᵐᵒᵖ) : (S₁ ⊓ S₂).unop = S₁.unop ⊓ S₂.unop := rfl @[to_additive] theorem op_sSup (S : Set (Submonoid M)) : (sSup S).op = sSup (.unop ⁻¹' S) := @@ -140,9 +163,8 @@ theorem op_closure (s : Set M) : (closure s).op = closure (MulOpposite.unop ⁻ @[to_additive] theorem unop_closure (s : Set Mᵐᵒᵖ) : (closure s).unop = closure (MulOpposite.op ⁻¹' s) := by - simp_rw [closure, unop_sInf, Set.preimage_setOf_eq, Submonoid.op_coe] - congr with a - exact MulOpposite.op_surjective.forall + rw [← op_inj, op_unop, op_closure] + rfl /-- Bijection between a submonoid `H` and its opposite. -/ @[to_additive (attr := simps!) "Bijection between an additive submonoid `H` and its opposite."] diff --git a/Mathlib/Algebra/Group/Submonoid/Operations.lean b/Mathlib/Algebra/Group/Submonoid/Operations.lean index 213f451a27df5..04c31e0b2686f 100644 --- a/Mathlib/Algebra/Group/Submonoid/Operations.lean +++ b/Mathlib/Algebra/Group/Submonoid/Operations.lean @@ -531,8 +531,6 @@ protected theorem pow_mem {M : Type*} [Monoid M] (S : Submonoid M) {x : M} (hx : x ^ n ∈ S := pow_mem hx n --- Porting note: coe_pow removed, syntactic tautology - /-- A submonoid of a monoid inherits a monoid structure. -/ @[to_additive "An `AddSubmonoid` of an `AddMonoid` inherits an `AddMonoid` structure."] instance toMonoid {M : Type*} [Monoid M] (S : Submonoid M) : Monoid S := @@ -581,8 +579,9 @@ theorem coe_equivMapOfInjective_apply (f : M →* N) (hf : Function.Injective f) theorem closure_closure_coe_preimage {s : Set M} : closure (((↑) : closure s → M) ⁻¹' s) = ⊤ := eq_top_iff.2 fun x => Subtype.recOn x fun x hx _ => by - refine closure_induction' (p := fun y hy ↦ ⟨y, hy⟩ ∈ closure (((↑) : closure s → M) ⁻¹' s)) - (fun g hg => subset_closure hg) ?_ (fun g₁ g₂ hg₁ hg₂ => ?_) hx + 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 · exact Submonoid.one_mem _ · exact Submonoid.mul_mem _ @@ -626,7 +625,7 @@ theorem top_prod_top : (⊤ : Submonoid M).prod (⊤ : Submonoid N) = ⊤ := @[to_additive bot_prod_bot] theorem bot_prod_bot : (⊥ : Submonoid M).prod (⊥ : Submonoid N) = ⊥ := - SetLike.coe_injective <| by simp [coe_prod, Prod.one_eq_mk] + SetLike.coe_injective <| by simp [coe_prod] -- Porting note: to_additive translated the name incorrectly in mathlib 3. /-- The product of submonoids is isomorphic to their product as monoids. -/ @@ -829,6 +828,11 @@ def codRestrict {S} [SetLike S N] [SubmonoidClass S N] (f : M →* N) (s : S) (h map_one' := Subtype.eq f.map_one map_mul' x y := Subtype.eq (f.map_mul x y) +@[to_additive (attr := simp)] +lemma injective_codRestrict {S} [SetLike S N] [SubmonoidClass S N] (f : M →* N) (s : S) + (h : ∀ x, f x ∈ s) : Function.Injective (f.codRestrict s h) ↔ Function.Injective f := + ⟨fun H _ _ hxy ↦ H <| Subtype.eq hxy, fun H _ _ hxy ↦ H (congr_arg Subtype.val hxy)⟩ + /-- Restriction of a monoid hom to its range interpreted as a submonoid. -/ @[to_additive "Restriction of an `AddMonoid` hom to its range interpreted as a submonoid."] def mrangeRestrict {N} [MulOneClass N] (f : M →* N) : M →* (mrange f) := diff --git a/Mathlib/Algebra/Group/Submonoid/Units.lean b/Mathlib/Algebra/Group/Submonoid/Units.lean index 2754d556e4588..96ce6d155d1e4 100644 --- a/Mathlib/Algebra/Group/Submonoid/Units.lean +++ b/Mathlib/Algebra/Group/Submonoid/Units.lean @@ -40,13 +40,13 @@ variable {M : Type*} [Monoid M] open Units open Pointwise in -/-- The units of `S`, packaged as a subgroup of `Mˣ`. -/ +/-- The units of `S`, packaged as a subgroup of `Mˣ`. -/ @[to_additive " The additive units of `S`, packaged as an additive subgroup of `AddUnits M`. "] def Submonoid.units (S : Submonoid M) : Subgroup Mˣ where toSubmonoid := S.comap (coeHom M) ⊓ (S.comap (coeHom M))⁻¹ inv_mem' ha := ⟨ha.2, ha.1⟩ -/-- A subgroup of units represented as a submonoid of `M`. -/ +/-- A subgroup of units represented as a submonoid of `M`. -/ @[to_additive " A additive subgroup of additive units represented as a additive submonoid of `M`. "] def Subgroup.ofUnits (S : Subgroup Mˣ) : Submonoid M := S.toSubmonoid.map (coeHom M) @@ -327,6 +327,6 @@ lemma val_mem_ofUnits_iff_mem (H : Subgroup Gˣ) (x : Gˣ) : (x : G) ∈ H.ofUni @[to_additive " The equivalence between the greatest subgroup of additive units contained within `T` and `T` itself. "] def unitsEquivSelf (H : Subgroup G) : H.units ≃* H := - H.unitsEquivUnitsType.trans toUnits.symm + H.unitsEquivUnitsType.trans (toUnits (G := H)).symm end Subgroup diff --git a/Mathlib/Algebra/Group/Subsemigroup/Basic.lean b/Mathlib/Algebra/Group/Subsemigroup/Basic.lean index eb038acc2f5ba..f65687e5782d3 100644 --- a/Mathlib/Algebra/Group/Subsemigroup/Basic.lean +++ b/Mathlib/Algebra/Group/Subsemigroup/Basic.lean @@ -298,7 +298,7 @@ theorem closure_induction {p : M → Prop} {x} (h : x ∈ closure s) (mem : ∀ (mul : ∀ x y, p x → p y → p (x * y)) : p x := (@closure_le _ _ _ ⟨p, mul _ _⟩).2 mem h -/-- A dependent version of `Subsemigroup.closure_induction`. -/ +/-- A dependent version of `Subsemigroup.closure_induction`. -/ @[to_additive (attr := elab_as_elim) "A dependent version of `AddSubsemigroup.closure_induction`. "] theorem closure_induction' (s : Set M) {p : ∀ x, x ∈ closure s → Prop} (mem : ∀ (x) (h : x ∈ s), p x (subset_closure h)) @@ -309,7 +309,7 @@ theorem closure_induction' (s : Set M) {p : ∀ x, x ∈ closure s → Prop} closure_induction hx (fun x hx => ⟨_, mem x hx⟩) fun x y ⟨hx', hx⟩ ⟨hy', hy⟩ => ⟨_, mul _ _ _ _ hx hy⟩ -/-- An induction principle for closure membership for predicates with two arguments. -/ +/-- An induction principle for closure membership for predicates with two arguments. -/ @[to_additive (attr := elab_as_elim) "An induction principle for additive closure membership for predicates with two arguments."] theorem closure_induction₂ {p : M → M → Prop} {x} {y : M} (hx : x ∈ closure s) (hy : y ∈ closure s) diff --git a/Mathlib/Algebra/Group/Subsemigroup/Operations.lean b/Mathlib/Algebra/Group/Subsemigroup/Operations.lean index 0c804659e191b..e7642c410820d 100644 --- a/Mathlib/Algebra/Group/Subsemigroup/Operations.lean +++ b/Mathlib/Algebra/Group/Subsemigroup/Operations.lean @@ -301,14 +301,15 @@ theorem map_id (S : Subsemigroup M) : S.map (MulHom.id M) = S := section GaloisCoinsertion -variable {ι : Type*} {f : M →ₙ* N} (hf : Function.Injective f) -include hf +variable {ι : Type*} {f : M →ₙ* N} /-- `map f` and `comap f` form a `GaloisCoinsertion` when `f` is injective. -/ @[to_additive " `map f` and `comap f` form a `GaloisCoinsertion` when `f` is injective. "] -def gciMapComap : GaloisCoinsertion (map f) (comap f) := +def gciMapComap (hf : Function.Injective f) : GaloisCoinsertion (map f) (comap f) := (gc_map_comap f).toGaloisCoinsertion fun S x => by simp [mem_comap, mem_map, hf.eq_iff] +variable (hf : Function.Injective f) +include hf @[to_additive] theorem comap_map_eq_of_injective (S : Subsemigroup M) : (S.map f).comap f = S := @@ -488,9 +489,9 @@ theorem coe_equivMapOfInjective_apply (f : M →ₙ* N) (hf : Function.Injective theorem closure_closure_coe_preimage {s : Set M} : closure ((Subtype.val : closure s → M) ⁻¹' s) = ⊤ := eq_top_iff.2 fun x => - Subtype.recOn x fun _ hx _ => - closure_induction' (p := fun y hy ↦ ⟨y, hy⟩ ∈ closure (((↑) : closure s → M) ⁻¹' s)) - (fun _ hg => subset_closure hg) (fun _ _ _ _ => Subsemigroup.mul_mem _) hx + 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' /-- Given `Subsemigroup`s `s`, `t` of semigroups `M`, `N` respectively, `s × t` as a subsemigroup of `M × N`. -/ @@ -530,7 +531,7 @@ theorem top_prod_top : (⊤ : Subsemigroup M).prod (⊤ : Subsemigroup N) = ⊤ @[to_additive bot_prod_bot] theorem bot_prod_bot : (⊥ : Subsemigroup M).prod (⊥ : Subsemigroup N) = ⊥ := - SetLike.coe_injective <| by simp [coe_prod, Prod.one_eq_mk] + SetLike.coe_injective <| by simp [coe_prod] /-- The product of subsemigroups is isomorphic to their product as semigroups. -/ @[to_additive prodEquiv diff --git a/Mathlib/Algebra/Group/Units.lean b/Mathlib/Algebra/Group/Units.lean index 7ae26582ac369..a42617a760e41 100644 --- a/Mathlib/Algebra/Group/Units.lean +++ b/Mathlib/Algebra/Group/Units.lean @@ -464,6 +464,72 @@ theorem val_div_eq_divp (u₁ u₂ : αˣ) : ↑(u₁ / u₂) = ↑u₁ /ₚ u end Monoid +namespace LeftCancelMonoid + +variable [LeftCancelMonoid α] [Subsingleton αˣ] {a b : α} + +@[to_additive] +protected theorem eq_one_of_mul_right (h : a * b = 1) : a = 1 := + congr_arg Units.inv <| Subsingleton.elim (Units.mk _ _ (by + rw [← mul_left_cancel_iff (a := a), ← mul_assoc, h, one_mul, mul_one]) h) 1 + +@[to_additive] +protected theorem eq_one_of_mul_left (h : a * b = 1) : b = 1 := by + rwa [LeftCancelMonoid.eq_one_of_mul_right h, one_mul] at h + +@[to_additive (attr := simp)] +protected theorem mul_eq_one : a * b = 1 ↔ a = 1 ∧ b = 1 := + ⟨fun h => ⟨LeftCancelMonoid.eq_one_of_mul_right h, LeftCancelMonoid.eq_one_of_mul_left h⟩, by + rintro ⟨rfl, rfl⟩ + exact mul_one _⟩ + +@[to_additive] +protected theorem mul_ne_one : a * b ≠ 1 ↔ a ≠ 1 ∨ b ≠ 1 := by rw [not_iff_comm]; simp + +end LeftCancelMonoid + +namespace RightCancelMonoid + +variable [RightCancelMonoid α] [Subsingleton αˣ] {a b : α} + +@[to_additive] +protected theorem eq_one_of_mul_right (h : a * b = 1) : a = 1 := + congr_arg Units.inv <| Subsingleton.elim (Units.mk _ _ (by + rw [← mul_right_cancel_iff (a := b), mul_assoc, h, one_mul, mul_one]) h) 1 + +@[to_additive] +protected theorem eq_one_of_mul_left (h : a * b = 1) : b = 1 := by + rwa [RightCancelMonoid.eq_one_of_mul_right h, one_mul] at h + +@[to_additive (attr := simp)] +protected theorem mul_eq_one : a * b = 1 ↔ a = 1 ∧ b = 1 := + ⟨fun h => ⟨RightCancelMonoid.eq_one_of_mul_right h, RightCancelMonoid.eq_one_of_mul_left h⟩, by + rintro ⟨rfl, rfl⟩ + exact mul_one _⟩ + +@[to_additive] +protected theorem mul_ne_one : a * b ≠ 1 ↔ a ≠ 1 ∨ b ≠ 1 := by rw [not_iff_comm]; simp + +end RightCancelMonoid + +section CancelMonoid + +variable [CancelMonoid α] [Subsingleton αˣ] {a b : α} + +@[to_additive] +theorem eq_one_of_mul_right' (h : a * b = 1) : a = 1 := LeftCancelMonoid.eq_one_of_mul_right h + +@[to_additive] +theorem eq_one_of_mul_left' (h : a * b = 1) : b = 1 := LeftCancelMonoid.eq_one_of_mul_left h + +@[to_additive] +theorem mul_eq_one' : a * b = 1 ↔ a = 1 ∧ b = 1 := LeftCancelMonoid.mul_eq_one + +@[to_additive] +theorem mul_ne_one' : a * b ≠ 1 ↔ a ≠ 1 ∨ b ≠ 1 := LeftCancelMonoid.mul_ne_one + +end CancelMonoid + section CommMonoid variable [CommMonoid α] @@ -498,6 +564,8 @@ theorem mul_eq_one : a * b = 1 ↔ a = 1 ∧ b = 1 := rintro ⟨rfl, rfl⟩ exact mul_one _⟩ +@[to_additive] theorem mul_ne_one : a * b ≠ 1 ↔ a ≠ 1 ∨ b ≠ 1 := by rw [not_iff_comm]; simp + end CommMonoid /-! diff --git a/Mathlib/Algebra/GroupWithZero/Action/Defs.lean b/Mathlib/Algebra/GroupWithZero/Action/Defs.lean index a2e67fb1c2e12..28a7f1306d857 100644 --- a/Mathlib/Algebra/GroupWithZero/Action/Defs.lean +++ b/Mathlib/Algebra/GroupWithZero/Action/Defs.lean @@ -3,11 +3,9 @@ Copyright (c) 2018 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes, Yury Kudryashov -/ -import Mathlib.Algebra.Group.Action.Defs -import Mathlib.Algebra.Group.Hom.Defs -import Mathlib.Algebra.Group.TypeTags -import Mathlib.Algebra.Opposites -import Mathlib.Logic.Embedding.Basic +import Mathlib.Algebra.Group.Action.Units +import Mathlib.Algebra.Group.Equiv.Basic +import Mathlib.Algebra.GroupWithZero.Units.Basic /-! # Definitions of group actions @@ -45,10 +43,49 @@ More sophisticated lemmas belong in `GroupTheory.GroupAction`. group action -/ +assert_not_exists Equiv.Perm.equivUnitsEnd +assert_not_exists Prod.fst_mul +assert_not_exists Ring -variable {M N G A B α β γ δ : Type*} +open Function -open Function (Injective Surjective) +variable {R R' M M' N G A B α β : Type*} + +/-- `Monoid.toMulAction` is faithful on nontrivial cancellative monoids with zero. -/ +instance CancelMonoidWithZero.faithfulSMul [CancelMonoidWithZero α] [Nontrivial α] : + FaithfulSMul α α where eq_of_smul_eq_smul h := mul_left_injective₀ one_ne_zero (h 1) + +section GroupWithZero +variable [GroupWithZero α] [MulAction α β] {a : α} + +@[simp] lemma inv_smul_smul₀ (ha : a ≠ 0) (x : β) : a⁻¹ • a • x = x := + inv_smul_smul (Units.mk0 a ha) x + +@[simp] +lemma smul_inv_smul₀ (ha : a ≠ 0) (x : β) : a • a⁻¹ • x = x := smul_inv_smul (Units.mk0 a ha) x + +lemma inv_smul_eq_iff₀ (ha : a ≠ 0) {x y : β} : a⁻¹ • x = y ↔ x = a • y := + inv_smul_eq_iff (g := Units.mk0 a ha) + +lemma eq_inv_smul_iff₀ (ha : a ≠ 0) {x y : β} : x = a⁻¹ • y ↔ a • x = y := + eq_inv_smul_iff (g := Units.mk0 a ha) + +@[simp] +lemma Commute.smul_right_iff₀ [Mul β] [SMulCommClass α β β] [IsScalarTower α β β] {x y : β} + (ha : a ≠ 0) : Commute x (a • y) ↔ Commute x y := Commute.smul_right_iff (g := Units.mk0 a ha) + +@[simp] +lemma Commute.smul_left_iff₀ [Mul β] [SMulCommClass α β β] [IsScalarTower α β β] {x y : β} + (ha : a ≠ 0) : Commute (a • x) y ↔ Commute x y := Commute.smul_left_iff (g := Units.mk0 a ha) + +/-- Right scalar multiplication as an order isomorphism. -/ +@[simps] def Equiv.smulRight (ha : a ≠ 0) : β ≃ β where + toFun b := a • b + invFun b := a⁻¹ • b + left_inv := inv_smul_smul₀ ha + right_inv := smul_inv_smul₀ ha + +end GroupWithZero /-- Typeclass for scalar multiplication that preserves `0` on the right. -/ class SMulZeroClass (M A : Type*) [Zero A] extends SMul M A where @@ -391,3 +428,24 @@ theorem AddMonoid.End.smul_def [AddMonoid α] (f : AddMonoid.End α) (a : α) : instance AddMonoid.End.applyFaithfulSMul [AddMonoid α] : FaithfulSMul (AddMonoid.End α) α := ⟨fun {_ _ h} => AddMonoidHom.ext h⟩ + +/-- Each non-zero element of a `GroupWithZero` defines an additive monoid isomorphism of an +`AddMonoid` on which it acts distributively. +This is a stronger version of `DistribMulAction.toAddMonoidHom`. -/ +def DistribMulAction.toAddEquiv₀ {α : Type*} (β : Type*) [GroupWithZero α] [AddMonoid β] + [DistribMulAction α β] (x : α) (hx : x ≠ 0) : β ≃+ β := + { DistribMulAction.toAddMonoidHom β x with + invFun := fun b ↦ x⁻¹ • b + left_inv := fun b ↦ inv_smul_smul₀ hx b + right_inv := fun b ↦ smul_inv_smul₀ hx b } + +section Group +variable [Group α] [AddMonoid β] [DistribMulAction α β] + +lemma smul_eq_zero_iff_eq (a : α) {x : β} : a • x = 0 ↔ x = 0 := + ⟨fun h => by rw [← inv_smul_smul a x, h, smul_zero], fun h => h.symm ▸ smul_zero _⟩ + +lemma smul_ne_zero_iff_ne (a : α) {x : β} : a • x ≠ 0 ↔ x ≠ 0 := + not_congr <| smul_eq_zero_iff_eq a + +end Group diff --git a/Mathlib/Algebra/GroupWithZero/Action/Opposite.lean b/Mathlib/Algebra/GroupWithZero/Action/Opposite.lean index d6555ef552eb7..e78af0c456d38 100644 --- a/Mathlib/Algebra/GroupWithZero/Action/Opposite.lean +++ b/Mathlib/Algebra/GroupWithZero/Action/Opposite.lean @@ -6,6 +6,7 @@ Authors: Eric Wieser import Mathlib.Algebra.Group.Action.Opposite import Mathlib.Algebra.GroupWithZero.Action.Defs import Mathlib.Algebra.GroupWithZero.NeZero +import Mathlib.Algebra.SMulWithZero /-! # Scalar actions on and by `Mᵐᵒᵖ` @@ -33,9 +34,20 @@ variable {R M N α : Type*} Actions on the opposite type just act on the underlying type. -/ - namespace MulOpposite +instance instSMulZeroClass [AddMonoid α] [SMulZeroClass M α] : SMulZeroClass M αᵐᵒᵖ where + smul_zero _ := unop_injective <| smul_zero _ + +instance instSMulWithZero [MonoidWithZero M] [AddMonoid α] [SMulWithZero M α] : + SMulWithZero M αᵐᵒᵖ where + zero_smul _ := unop_injective <| zero_smul _ _ + +instance instMulActionWithZero [MonoidWithZero M] [AddMonoid α] [MulActionWithZero M α] : + MulActionWithZero M αᵐᵒᵖ where + smul_zero _ := unop_injective <| smul_zero _ + zero_smul _ := unop_injective <| zero_smul _ _ + instance instDistribMulAction [Monoid M] [AddMonoid α] [DistribMulAction M α] : DistribMulAction M αᵐᵒᵖ where smul_add _ _ _ := unop_injective <| smul_add _ _ _ diff --git a/Mathlib/Algebra/GroupWithZero/Action/Prod.lean b/Mathlib/Algebra/GroupWithZero/Action/Prod.lean index 5d43252e1d1a7..d523dffe4f80d 100644 --- a/Mathlib/Algebra/GroupWithZero/Action/Prod.lean +++ b/Mathlib/Algebra/GroupWithZero/Action/Prod.lean @@ -18,7 +18,7 @@ This file defines instances for `MulActionWithZero` and related structures on ` * `Algebra.GroupWithZero.Action.Units` -/ -assert_not_exists MonoidWithZero +assert_not_exists Ring variable {M N α β : Type*} diff --git a/Mathlib/Algebra/GroupWithZero/Action/Units.lean b/Mathlib/Algebra/GroupWithZero/Action/Units.lean index e56fe65a0de40..c517ff3399f1e 100644 --- a/Mathlib/Algebra/GroupWithZero/Action/Units.lean +++ b/Mathlib/Algebra/GroupWithZero/Action/Units.lean @@ -61,3 +61,10 @@ instance mulDistribMulAction' [Group G] [Monoid M] [MulDistribMulAction G M] [SM smul_mul := fun _ _ _ => Units.ext <| smul_mul' _ _ _ } end Units + +section Monoid +variable [Monoid G] [AddMonoid M] [DistribMulAction G M] {u : G} {x : M} + +@[simp] lemma IsUnit.smul_eq_zero (hu : IsUnit u) : u • x = 0 ↔ x = 0 := smul_eq_zero_iff_eq hu.unit + +end Monoid diff --git a/Mathlib/Algebra/GroupWithZero/Pointwise/Set.lean b/Mathlib/Algebra/GroupWithZero/Pointwise/Set.lean new file mode 100644 index 0000000000000..653b0ea020618 --- /dev/null +++ b/Mathlib/Algebra/GroupWithZero/Pointwise/Set.lean @@ -0,0 +1,59 @@ +/- +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.GroupWithZero.Basic + +/-! +# Pointwise operations of sets in a group with zero + +This file proves properties of pointwise operations of sets in a group with zero. + +## Tags + +set multiplication, set addition, pointwise addition, pointwise multiplication, +pointwise subtraction +-/ + +assert_not_exists OrderedAddCommMonoid +assert_not_exists Ring + +open Function +open scoped Pointwise + +variable {F α β γ : Type*} + +namespace Set + +section MulZeroClass +variable [MulZeroClass α] {s t : Set α} + +/-! Note that `Set` is not a `MulZeroClass` because `0 * ∅ ≠ 0`. -/ + +lemma mul_zero_subset (s : Set α) : s * 0 ⊆ 0 := by simp [subset_def, mem_mul] +lemma zero_mul_subset (s : Set α) : 0 * s ⊆ 0 := by simp [subset_def, mem_mul] + +lemma Nonempty.mul_zero (hs : s.Nonempty) : s * 0 = 0 := + s.mul_zero_subset.antisymm <| by simpa [mem_mul] using hs + +lemma Nonempty.zero_mul (hs : s.Nonempty) : 0 * s = 0 := + s.zero_mul_subset.antisymm <| by simpa [mem_mul] using hs + +end MulZeroClass + +section GroupWithZero +variable [GroupWithZero α] {s t : Set α} + +lemma div_zero_subset (s : Set α) : s / 0 ⊆ 0 := by simp [subset_def, mem_div] +lemma zero_div_subset (s : Set α) : 0 / s ⊆ 0 := by simp [subset_def, mem_div] + +lemma Nonempty.div_zero (hs : s.Nonempty) : s / 0 = 0 := + s.div_zero_subset.antisymm <| by simpa [mem_div] using hs + +lemma Nonempty.zero_div (hs : s.Nonempty) : 0 / s = 0 := + s.zero_div_subset.antisymm <| by simpa [mem_div] using hs + +end GroupWithZero +end Set diff --git a/Mathlib/Algebra/GroupWithZero/Units/Basic.lean b/Mathlib/Algebra/GroupWithZero/Units/Basic.lean index c7f47fc71a812..a32ad81fb22e8 100644 --- a/Mathlib/Algebra/GroupWithZero/Units/Basic.lean +++ b/Mathlib/Algebra/GroupWithZero/Units/Basic.lean @@ -322,11 +322,11 @@ lemma mul_div_mul_right (a b : G₀) (hc : c ≠ 0) : a * c / (b * c) = a / b := -- TODO: Duplicate of `mul_inv_cancel_right₀` lemma mul_mul_div (a : G₀) (hb : b ≠ 0) : a = a * b * (1 / b) := (hb.isUnit.mul_mul_div _).symm -lemma div_div_div_cancel_right (a : G₀) (hc : c ≠ 0) : a / c / (b / c) = a / b := by +lemma div_div_div_cancel_right₀ (hc : c ≠ 0) (a b : G₀) : a / c / (b / c) = a / b := by rw [div_div_eq_mul_div, div_mul_cancel₀ _ hc] -lemma div_mul_div_cancel (a : G₀) (hc : c ≠ 0) : a / c * (c / b) = a / b := by - rw [← mul_div_assoc, div_mul_cancel₀ _ hc] +lemma div_mul_div_cancel₀ (hb : b ≠ 0) : a / b * (b / c) = a / c := by + rw [← mul_div_assoc, div_mul_cancel₀ _ hb] lemma div_mul_cancel_of_imp (h : b = 0 → a = 0) : a / b * b = a := by obtain rfl | hb := eq_or_ne b 0 <;> simp [*] @@ -355,6 +355,15 @@ lemma inv_pow_sub_of_lt (a : G₀) (h : n < m) : a⁻¹ ^ (m - n) = (a ^ m)⁻¹ lemma zpow_sub₀ (ha : a ≠ 0) (m n : ℤ) : a ^ (m - n) = a ^ m / a ^ n := by rw [Int.sub_eq_add_neg, zpow_add₀ ha, zpow_neg, div_eq_mul_inv] +lemma zpow_natCast_sub_natCast₀ (ha : a ≠ 0) (m n : ℕ) : a ^ (m - n : ℤ) = a ^ m / a ^ n := by + simpa using zpow_sub₀ ha m n + +lemma zpow_natCast_sub_one₀ (ha : a ≠ 0) (n : ℕ) : a ^ (n - 1 : ℤ) = a ^ n / a := by + simpa using zpow_sub₀ ha n 1 + +lemma zpow_one_sub_natCast₀ (ha : a ≠ 0) (n : ℕ) : a ^ (1 - n : ℤ) = a / a ^ n := by + simpa using zpow_sub₀ ha 1 n + lemma zpow_ne_zero {a : G₀} : ∀ n : ℤ, a ≠ 0 → a ^ n ≠ 0 | (_ : ℕ) => by rw [zpow_natCast]; exact pow_ne_zero _ | .negSucc n => fun ha ↦ by rw [zpow_negSucc]; exact inv_ne_zero (pow_ne_zero _ ha) @@ -450,6 +459,9 @@ lemma div_helper (b : G₀) (h : a ≠ 0) : 1 / (a * b) * a = 1 / b := by lemma div_div_div_cancel_left' (a b : G₀) (hc : c ≠ 0) : c / a / (c / b) = b / a := by rw [div_div_div_eq, mul_comm, mul_div_mul_right _ _ hc] +@[simp] lemma div_mul_div_cancel₀' (ha : a ≠ 0) (b c : G₀) : a / b * (c / a) = c / b := by + rw [mul_comm, div_mul_div_cancel₀ ha] + end CommGroupWithZero section NoncomputableDefs diff --git a/Mathlib/Algebra/Homology/BifunctorAssociator.lean b/Mathlib/Algebra/Homology/BifunctorAssociator.lean new file mode 100644 index 0000000000000..70f0ff7943445 --- /dev/null +++ b/Mathlib/Algebra/Homology/BifunctorAssociator.lean @@ -0,0 +1,192 @@ +/- +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.CategoryTheory.GradedObject.Associator +import Mathlib.CategoryTheory.Preadditive.AdditiveFunctor +import Mathlib.Algebra.Homology.Bifunctor + +/-! +# The associator for actions of bifunctors on homological complexes + +In this file, we shall adapt (TODO) the results of the file +`CategoryTheory.GradedObject.Associator` to the case of homological complexes. +Given functors `F₁₂ : C₁ ⥤ C₂ ⥤ C₁₂`, `G : C₁₂ ⥤ C₃ ⥤ C₄`, +`F : C₁ ⥤ C₂₃ ⥤ C₄`, `G₂₃ : C₂ ⥤ C₃ ⥤ C₂₃` equipped with an isomorphism +`associator : bifunctorComp₁₂ F₁₂ G ≅ bifunctorComp₂₃ F G₂₃` (which informally means +that we have natural isomorphisms `G(F₁₂(X₁, X₂), X₃) ≅ F(X₁, G₂₃(X₂, X₃))`), +we shall define an isomorphism `mapBifunctorAssociator` from +`mapBifunctor (mapBifunctor K₁ K₂ F₁₂ c₁₂) K₃ G c₄` to +`mapBifunctor K₁ (mapBifunctor K₂ K₃ G₂₃ c₂₃) F c₄` when +we have three homological complexes `K₁ : HomologicalComplex C₁ c₁`, +`K₂ : HomologicalComplex C₂ c₂` and `K₃ : HomologicalComplex C₃ c₃`, +assumptions `TotalComplexShape c₁ c₂ c₁₂`, `TotalComplexShape c₁₂ c₃ c₄`, +`TotalComplexShape c₂ c₃ c₂₃`, `TotalComplexShape c₁ c₂₃ c₄`, +and `ComplexShape.Associative c₁ c₂ c₃ c₁₂ c₂₃ c₄` about the complex +shapes, and technical assumptions +`[HasGoodTrifunctor₁₂Obj F₁₂ G K₁ K₂ K₃ c₁₂ c₄]` and +`[HasGoodTrifunctor₂₃Obj F G₂₃ K₁ K₂ K₃ c₁₂ c₂₃ c₄]` about the +commutation of certain functors to certain coproducts. + +The main application of these results shall be the construction of +the associator for the monoidal category structure on homological complexes (TODO). + +-/ + +open CategoryTheory Category Limits + +namespace HomologicalComplex + +variable {C₁ C₂ C₁₂ C₂₃ C₃ C₄ : Type*} + [Category C₁] [Category C₂] [Category C₃] [Category C₄] [Category C₁₂] [Category C₂₃] + [HasZeroMorphisms C₁] [HasZeroMorphisms C₂] [HasZeroMorphisms C₃] + [Preadditive C₁₂] [Preadditive C₂₃] [Preadditive C₄] + {F₁₂ : C₁ ⥤ C₂ ⥤ C₁₂} {G : C₁₂ ⥤ C₃ ⥤ C₄} + {F : C₁ ⥤ C₂₃ ⥤ C₄} {G₂₃ : C₂ ⥤ C₃ ⥤ C₂₃} + [F₁₂.PreservesZeroMorphisms] [∀ (X₁ : C₁), (F₁₂.obj X₁).PreservesZeroMorphisms] + [G.Additive] [∀ (X₁₂ : C₁₂), (G.obj X₁₂).PreservesZeroMorphisms] + [G₂₃.PreservesZeroMorphisms] [∀ (X₂ : C₂), (G₂₃.obj X₂).PreservesZeroMorphisms] + [F.PreservesZeroMorphisms] [∀ (X₁ : C₁), (F.obj X₁).Additive] + (associator : bifunctorComp₁₂ F₁₂ G ≅ bifunctorComp₂₃ F G₂₃) + {ι₁ ι₂ ι₃ ι₁₂ ι₂₃ ι₄ : Type*} + [DecidableEq ι₁₂] [DecidableEq ι₂₃] [DecidableEq ι₄] + {c₁ : ComplexShape ι₁} {c₂ : ComplexShape ι₂} {c₃ : ComplexShape ι₃} + (K₁ : HomologicalComplex C₁ c₁) (K₂ : HomologicalComplex C₂ c₂) + (K₃ : HomologicalComplex C₃ c₃) + (c₁₂ : ComplexShape ι₁₂) (c₂₃ : ComplexShape ι₂₃) (c₄ : ComplexShape ι₄) + [TotalComplexShape c₁ c₂ c₁₂] [TotalComplexShape c₁₂ c₃ c₄] + [TotalComplexShape c₂ c₃ c₂₃] [TotalComplexShape c₁ c₂₃ c₄] + [HasMapBifunctor K₁ K₂ F₁₂ c₁₂] [HasMapBifunctor (mapBifunctor K₁ K₂ F₁₂ c₁₂) K₃ G c₄] + [HasMapBifunctor K₂ K₃ G₂₃ c₂₃] [HasMapBifunctor K₁ (mapBifunctor K₂ K₃ G₂₃ c₂₃) F c₄] + [ComplexShape.Associative c₁ c₂ c₃ c₁₂ c₂₃ c₄] + +variable (F₁₂ G) in +/-- Given bifunctors `F₁₂ : C₁ ⥤ C₂ ⥤ C₁₂`, `G : C₁₂ ⥤ C₃ ⥤ C₄`, homological complexes +`K₁ : HomologicalComplex C₁ c₁`, `K₂ : HomologicalComplex C₂ c₂` and +`K₃ : HomologicalComplex C₃ c₃`, and complexes shapes `c₁₂`, `c₄`, this asserts +that for all `i₁₂ : ι₁₂` and `i₃ : ι₃`, the functor `G(-, K₃.X i₃)` commutes with +the coproducts of the `F₁₂(X₁ i₁, X₂ i₂)` such that `π c₁ c₂ c₁₂ ⟨i₁, i₂⟩ = i₁₂`. -/ +abbrev HasGoodTrifunctor₁₂Obj := + GradedObject.HasGoodTrifunctor₁₂Obj F₁₂ G + (ComplexShape.ρ₁₂ c₁ c₂ c₃ c₁₂ c₄) K₁.X K₂.X K₃.X + +variable (F G₂₃) in +/-- Given bifunctors `F : C₁ ⥤ C₂₃ ⥤ C₄`, `G₂₃ : C₂ ⥤ C₃ ⥤ C₂₃`, homological complexes +`K₁ : HomologicalComplex C₁ c₁`, `K₂ : HomologicalComplex C₂ c₂` and +`K₃ : HomologicalComplex C₃ c₃`, and complexes shapes `c₁₂`, `c₂₃`, `c₄` +with `ComplexShape.Associative c₁ c₂ c₃ c₁₂ c₂₃ c₄`, this asserts that for +all `i₁ : ι₁` and `i₂₃ : ι₂₃`, the functor `F(K₁.X i₁, _)` commutes with +the coproducts of the `G₂₃(K₂.X i₂, K₃.X i₃)` +such that `π c₂ c₃ c₂₃ ⟨i₂, i₃⟩ = i₂₃`. -/ +abbrev HasGoodTrifunctor₂₃Obj := + GradedObject.HasGoodTrifunctor₂₃Obj F G₂₃ + (ComplexShape.ρ₂₃ c₁ c₂ c₃ c₁₂ c₂₃ c₄) K₁.X K₂.X K₃.X + +instance : + (((GradedObject.mapBifunctor F₁₂ ι₁ ι₂).obj K₁.X).obj K₂.X).HasMap + (ComplexShape.π c₁ c₂ c₁₂) := + inferInstanceAs (HasMapBifunctor K₁ K₂ F₁₂ c₁₂) + +instance : + (((GradedObject.mapBifunctor G ι₁₂ ι₃).obj (GradedObject.mapBifunctorMapObj F₁₂ + (ComplexShape.π c₁ c₂ c₁₂) K₁.X K₂.X)).obj K₃.X).HasMap + (ComplexShape.π c₁₂ c₃ c₄) := + inferInstanceAs (HasMapBifunctor (mapBifunctor K₁ K₂ F₁₂ c₁₂) K₃ G c₄) + +instance : + (((GradedObject.mapBifunctor F ι₁ ι₂₃).obj K₁.X).obj + (GradedObject.mapBifunctorMapObj G₂₃ + (ComplexShape.π c₂ c₃ c₂₃) K₂.X K₃.X)).HasMap (ComplexShape.π c₁ c₂₃ c₄) := + inferInstanceAs (HasMapBifunctor K₁ (mapBifunctor K₂ K₃ G₂₃ c₂₃) F c₄) + +/-- The associator isomorphism for the action of bifunctors +on homological complexes, in each degree. -/ +noncomputable def mapBifunctorAssociatorX + [H₁₂ : HasGoodTrifunctor₁₂Obj F₁₂ G K₁ K₂ K₃ c₁₂ c₄] + [H₂₃ : HasGoodTrifunctor₂₃Obj F G₂₃ K₁ K₂ K₃ c₁₂ c₂₃ c₄](j : ι₄) : + (mapBifunctor (mapBifunctor K₁ K₂ F₁₂ c₁₂) K₃ G c₄).X j ≅ + (mapBifunctor K₁ (mapBifunctor K₂ K₃ G₂₃ c₂₃) F c₄).X j := + (GradedObject.eval j).mapIso + (GradedObject.mapBifunctorAssociator (associator := associator) + (H₁₂ := H₁₂) (H₂₃ := H₂₃)) + +namespace mapBifunctor₁₂ + +section + +variable (F₁₂ G) + +/-- The inclusion of a summand in `mapBifunctor (mapBifunctor K₁ K₂ F₁₂ c₁₂) K₃ G c₄`. -/ +noncomputable def ι (i₁ : ι₁) (i₂ : ι₂) (i₃ : ι₃) (j : ι₄) + (h : ComplexShape.r c₁ c₂ c₃ c₁₂ c₄ (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 := + GradedObject.ιMapBifunctor₁₂BifunctorMapObj _ _ (ComplexShape.ρ₁₂ c₁ c₂ c₃ c₁₂ c₄) _ _ _ _ _ _ _ h + +lemma ι_eq (i₁ : ι₁) (i₂ : ι₂) (i₃ : ι₃) (i₁₂ : ι₁₂) (j : ι₄) + (h₁₂ : ComplexShape.π c₁ c₂ c₁₂ ⟨i₁, i₂⟩ = i₁₂) + (h : ComplexShape.π c₁₂ c₃ c₄ (i₁₂, i₃) = j) : + ι F₁₂ G K₁ K₂ K₃ c₁₂ c₄ i₁ i₂ i₃ j (by rw [← h, ← h₁₂]; rfl) = + (G.map (ιMapBifunctor K₁ K₂ F₁₂ c₁₂ i₁ i₂ i₁₂ h₁₂)).app (K₃.X i₃) ≫ + ιMapBifunctor (mapBifunctor K₁ K₂ F₁₂ c₁₂) K₃ G c₄ i₁₂ i₃ j h := by + subst h₁₂ + rfl + +/-- The inclusion of a summand in `mapBifunctor (mapBifunctor K₁ K₂ F₁₂ c₁₂) K₃ G c₄`, +or zero. -/ +noncomputable def ιOrZero (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 := + if h : ComplexShape.r c₁ c₂ c₃ c₁₂ c₄ (i₁, i₂, i₃) = j then + ι F₁₂ G K₁ K₂ K₃ c₁₂ c₄ i₁ i₂ i₃ j h + else 0 + +lemma ιOrZero_eq (i₁ : ι₁) (i₂ : ι₂) (i₃ : ι₃) (j : ι₄) + (h : ComplexShape.r c₁ c₂ c₃ c₁₂ c₄ (i₁, i₂, i₃) = j) : + ιOrZero F₁₂ G K₁ K₂ K₃ c₁₂ c₄ i₁ i₂ i₃ j = + ι F₁₂ G K₁ K₂ K₃ c₁₂ c₄ i₁ i₂ i₃ j h := dif_pos h + +lemma ιOrZero_eq_zero (i₁ : ι₁) (i₂ : ι₂) (i₃ : ι₃) (j : ι₄) + (h : ComplexShape.r c₁ c₂ c₃ c₁₂ c₄ (i₁, i₂, i₃) ≠ j) : + ιOrZero F₁₂ G K₁ K₂ K₃ c₁₂ c₄ i₁ i₂ i₃ j = 0 := dif_neg h + +variable {F₁₂ G K₁ K₂ K₃ c₁₂ c₄} in +@[ext] +lemma hom_ext + [HasGoodTrifunctor₁₂Obj F₁₂ G K₁ K₂ K₃ c₁₂ c₄] {j : ι₄} {A : C₄} + {f g : (mapBifunctor (mapBifunctor K₁ K₂ F₁₂ c₁₂) K₃ G c₄).X j ⟶ A} + (hfg : ∀ (i₁ : ι₁) (i₂ : ι₂) (i₃ : ι₃) + (h : ComplexShape.r c₁ c₂ c₃ c₁₂ c₄ (i₁, i₂, i₃) = j), + ι F₁₂ G K₁ K₂ K₃ c₁₂ c₄ i₁ i₂ i₃ j h ≫ f = + ι F₁₂ G K₁ K₂ K₃ c₁₂ c₄ i₁ i₂ i₃ j h ≫ g) : + f = g := + GradedObject.mapBifunctor₁₂BifunctorMapObj_ext hfg + +end + +section + +variable {K₁ K₂ K₃ c₁₂ c₄} +variable [HasGoodTrifunctor₁₂Obj F₁₂ G K₁ K₂ K₃ c₁₂ c₄] {j : ι₄} {A : C₄} + (f : ∀ (i₁ : ι₁) (i₂ : ι₂) (i₃ : ι₃) (_ : ComplexShape.r c₁ c₂ c₃ c₁₂ c₄ (i₁, i₂, i₃) = j), + (G.obj ((F₁₂.obj (K₁.X i₁)).obj (K₂.X i₂))).obj (K₃.X i₃) ⟶ A) + +/-- Constructor for morphisms from +`(mapBifunctor (mapBifunctor K₁ K₂ F₁₂ c₁₂) K₃ G c₄).X j`. -/ +noncomputable def mapBifunctor₁₂Desc : + (mapBifunctor (mapBifunctor K₁ K₂ F₁₂ c₁₂) K₃ G c₄).X j ⟶ A := + GradedObject.mapBifunctor₁₂BifunctorDesc (ρ₁₂ := ComplexShape.ρ₁₂ c₁ c₂ c₃ c₁₂ c₄) f + +@[reassoc (attr := simp)] +lemma ι_mapBifunctor₁₂Desc (i₁ : ι₁) (i₂ : ι₂) (i₃ : ι₃) + (h : ComplexShape.r c₁ c₂ c₃ c₁₂ c₄ (i₁, i₂, i₃) = j) : + ι F₁₂ G K₁ K₂ K₃ c₁₂ c₄ i₁ i₂ i₃ j h ≫ mapBifunctor₁₂Desc f = + f i₁ i₂ i₃ h := by + apply GradedObject.ι_mapBifunctor₁₂BifunctorDesc + +end + +end mapBifunctor₁₂ + +end HomologicalComplex diff --git a/Mathlib/Algebra/Homology/ComplexShape.lean b/Mathlib/Algebra/Homology/ComplexShape.lean index 217da35df2a5d..e4da8ba92cfdf 100644 --- a/Mathlib/Algebra/Homology/ComplexShape.lean +++ b/Mathlib/Algebra/Homology/ComplexShape.lean @@ -86,9 +86,7 @@ def symm (c : ComplexShape ι) : ComplexShape ι where prev_eq w w' := c.next_eq w w' @[simp] -theorem symm_symm (c : ComplexShape ι) : c.symm.symm = c := by - ext - simp +theorem symm_symm (c : ComplexShape ι) : c.symm.symm = c := rfl theorem symm_bijective : Function.Bijective (ComplexShape.symm : ComplexShape ι → ComplexShape ι) := diff --git a/Mathlib/Algebra/Homology/ComplexShapeSigns.lean b/Mathlib/Algebra/Homology/ComplexShapeSigns.lean index aa22deaab5726..224aa9d155bb6 100644 --- a/Mathlib/Algebra/Homology/ComplexShapeSigns.lean +++ b/Mathlib/Algebra/Homology/ComplexShapeSigns.lean @@ -33,7 +33,7 @@ variable {I₁ I₂ I₃ I₁₂ I₂₃ J : Type*} of a total complex functor `HomologicalComplex₂ C c₁ c₂ ⥤ HomologicalComplex C c₁₂` which sends `K` to a complex which in degree `i₁₂ : I₁₂` consists of the coproduct of the `(K.X i₁).X i₂` such that `π ⟨i₁, i₂⟩ = i₁₂`. -/ -class TotalComplexShape where +class TotalComplexShape where /-- a map on indices -/ π : I₁ × I₂ → I₁₂ /-- the sign of the horizontal differential in the total complex -/ diff --git a/Mathlib/Algebra/Homology/DerivedCategory/Basic.lean b/Mathlib/Algebra/Homology/DerivedCategory/Basic.lean index c04665c5b4098..da302f9893e1b 100644 --- a/Mathlib/Algebra/Homology/DerivedCategory/Basic.lean +++ b/Mathlib/Algebra/Homology/DerivedCategory/Basic.lean @@ -253,4 +253,23 @@ noncomputable def singleFunctorsPostcompQIso : SingleFunctors.postcompIsoOfIso (CochainComplex.singleFunctors C) (quotientCompQhIso C) +lemma singleFunctorsPostcompQIso_hom_hom (n : ℤ) : + (singleFunctorsPostcompQIso C).hom.hom n = 𝟙 _ := by + ext X + dsimp [singleFunctorsPostcompQIso, HomotopyCategory.singleFunctorsPostcompQuotientIso, + quotientCompQhIso, HomologicalComplexUpToQuasiIso.quotientCompQhIso] + rw [CategoryTheory.Functor.map_id, SingleFunctors.id_hom, NatTrans.id_app] + erw [Category.id_comp, Category.id_comp] + rfl + +lemma singleFunctorsPostcompQIso_inv_hom (n : ℤ) : + (singleFunctorsPostcompQIso C).inv.hom n = 𝟙 _ := by + ext X + dsimp [singleFunctorsPostcompQIso, HomotopyCategory.singleFunctorsPostcompQuotientIso, + quotientCompQhIso, HomologicalComplexUpToQuasiIso.quotientCompQhIso] + erw [CategoryTheory.Functor.map_id] + rw [SingleFunctors.id_hom, NatTrans.id_app] + erw [Category.id_comp, Category.id_comp] + rfl + end DerivedCategory diff --git a/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean b/Mathlib/Algebra/Homology/DerivedCategory/Ext/Basic.lean similarity index 89% rename from Mathlib/Algebra/Homology/DerivedCategory/Ext.lean rename to Mathlib/Algebra/Homology/DerivedCategory/Ext/Basic.lean index cc231f472e59d..781e2de9cf31f 100644 --- a/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean +++ b/Mathlib/Algebra/Homology/DerivedCategory/Ext/Basic.lean @@ -36,8 +36,8 @@ sheaves over `X` shall be in `Type u`. ## TODO * compute `Ext X Y 0` -* define the class in `Ext S.X₃ S.X₁ 1` of a short exact short complex `S` -* construct the long exact sequences of `Ext`. +* construct the covariant long exact sequences of `Ext`. +* construct the contravariant long exact sequences of `Ext`. -/ @@ -47,7 +47,7 @@ namespace CategoryTheory variable (C : Type u) [Category.{v} C] [Abelian C] -open Localization Limits ZeroObject +open Localization Limits ZeroObject DerivedCategory Pretriangulated /-- The property that morphisms between single complexes in arbitrary degrees are `w`-small in the derived category. -/ @@ -58,14 +58,14 @@ abbrev HasExt : Prop := -- TODO: when the canonical t-structure is formalized, replace `n : ℤ` by `n : ℕ` lemma hasExt_iff [HasDerivedCategory.{w'} C] : HasExt.{w} C ↔ ∀ (X Y : C) (n : ℤ), Small.{w} - ((DerivedCategory.singleFunctor C 0).obj X ⟶ - (((DerivedCategory.singleFunctor C 0).obj Y)⟦n⟧)) := by + ((singleFunctor C 0).obj X ⟶ + (((singleFunctor C 0).obj Y)⟦n⟧)) := by dsimp [HasExt] - simp only [hasSmallLocalizedShiftedHom_iff _ _ DerivedCategory.Q] + simp only [hasSmallLocalizedShiftedHom_iff _ _ Q] constructor · intro h X Y n exact (small_congr ((shiftFunctorZero _ ℤ).app - ((DerivedCategory.singleFunctor C 0).obj X)).homFromEquiv).1 (h X Y 0 n) + ((singleFunctor C 0).obj X)).homFromEquiv).1 (h X Y 0 n) · intro h X Y a b refine (small_congr ?_).1 (h X Y (b - a)) exact (Functor.FullyFaithful.ofFullyFaithful @@ -103,6 +103,22 @@ lemma comp_assoc {a₁ a₂ a₃ a₁₂ a₂₃ a : ℕ} (α : Ext X Y a₁) ( α.comp (β.comp γ h₂₃) (by omega) := SmallShiftedHom.comp_assoc _ _ _ _ _ _ (by omega) +@[simp] +lemma comp_assoc_of_second_deg_zero + {a₁ a₃ a₁₃ : ℕ} (α : Ext X Y a₁) (β : Ext Y Z 0) (γ : Ext Z T a₃) + (h₁₃ : a₁ + a₃ = a₁₃) : + (α.comp β (add_zero _)).comp γ h₁₃ = α.comp (β.comp γ (zero_add _)) h₁₃ := by + apply comp_assoc + omega + +@[simp] +lemma comp_assoc_of_third_deg_zero + {a₁ a₂ a₁₂ : ℕ} (α : Ext X Y a₁) (β : Ext Y Z a₂) (γ : Ext Z T 0) + (h₁₂ : a₁ + a₂ = a₁₂) : + (α.comp β h₁₂).comp γ (add_zero _) = α.comp (β.comp γ (add_zero _)) h₁₂ := by + apply comp_assoc + omega + section variable [HasDerivedCategory.{w'} C] @@ -110,14 +126,13 @@ variable [HasDerivedCategory.{w'} C] /-- When an instance of `[HasDerivedCategory.{w'} C]` is available, this is the bijection between `Ext.{w} X Y n` and a type of morphisms in the derived category. -/ noncomputable def homEquiv {n : ℕ} : - Ext.{w} X Y n ≃ ShiftedHom ((DerivedCategory.singleFunctor C 0).obj X) - ((DerivedCategory.singleFunctor C 0).obj Y) (n : ℤ) := - SmallShiftedHom.equiv (HomologicalComplex.quasiIso C (ComplexShape.up ℤ)) DerivedCategory.Q + Ext.{w} X Y n ≃ ShiftedHom ((singleFunctor C 0).obj X) + ((singleFunctor C 0).obj Y) (n : ℤ) := + SmallShiftedHom.equiv (HomologicalComplex.quasiIso C (ComplexShape.up ℤ)) Q /-- The morphism in the derived category which corresponds to an element in `Ext X Y a`. -/ noncomputable abbrev hom {a : ℕ} (α : Ext X Y a) : - ShiftedHom ((DerivedCategory.singleFunctor C 0).obj X) - ((DerivedCategory.singleFunctor C 0).obj Y) (a : ℤ) := + ShiftedHom ((singleFunctor C 0).obj X) ((singleFunctor C 0).obj Y) (a : ℤ) := homEquiv α @[simp] @@ -137,7 +152,7 @@ noncomputable def mk₀ (f : X ⟶ Y) : Ext X Y 0 := SmallShiftedHom.mk₀ _ _ ( @[simp] lemma mk₀_hom [HasDerivedCategory.{w'} C] (f : X ⟶ Y) : - (mk₀ f).hom = ShiftedHom.mk₀ _ (by simp) ((DerivedCategory.singleFunctor C 0).map f) := by + (mk₀ f).hom = ShiftedHom.mk₀ _ (by simp) ((singleFunctor C 0).map f) := by apply SmallShiftedHom.equiv_mk₀ @[simp 1100] @@ -172,8 +187,7 @@ only in order to prove properties of the abelian group structure on `Ext`-groups Do not use this definition: use the more general `hom` instead. -/ noncomputable abbrev hom' (α : Ext X Y n) : letI := HasDerivedCategory.standard C - ShiftedHom ((DerivedCategory.singleFunctor C 0).obj X) - ((DerivedCategory.singleFunctor C 0).obj Y) (n : ℤ) := + ShiftedHom ((singleFunctor C 0).obj X) ((singleFunctor C 0).obj Y) (n : ℤ) := letI := HasDerivedCategory.standard C α.hom @@ -247,7 +261,7 @@ lemma biprod_ext {X₁ X₂ : C} {α β : Ext (X₁ ⊞ X₂) Y n} rw [Ext.ext_iff] at h₁ h₂ ⊢ simp only [comp_hom, mk₀_hom, ShiftedHom.mk₀_comp] at h₁ h₂ apply BinaryCofan.IsColimit.hom_ext - (isBinaryBilimitOfPreserves (DerivedCategory.singleFunctor C 0) + (isBinaryBilimitOfPreserves (singleFunctor C 0) (BinaryBiproduct.isBilimit X₁ X₂)).isColimit all_goals assumption @@ -289,8 +303,8 @@ lemma neg_hom (α : Ext X Y n) : (-α).hom = -α.hom := by /-- When an instance of `[HasDerivedCategory.{w'} C]` is available, this is the additive bijection between `Ext.{w} X Y n` and a type of morphisms in the derived category. -/ noncomputable def homAddEquiv {n : ℕ} : - Ext.{w} X Y n ≃+ ShiftedHom ((DerivedCategory.singleFunctor C 0).obj X) - ((DerivedCategory.singleFunctor C 0).obj Y) (n : ℤ) where + Ext.{w} X Y n ≃+ + ShiftedHom ((singleFunctor C 0).obj X) ((singleFunctor C 0).obj Y) (n : ℤ) where toEquiv := homEquiv map_add' := by simp diff --git a/Mathlib/Algebra/Homology/DerivedCategory/Ext/ExtClass.lean b/Mathlib/Algebra/Homology/DerivedCategory/Ext/ExtClass.lean new file mode 100644 index 0000000000000..9a636124ff714 --- /dev/null +++ b/Mathlib/Algebra/Homology/DerivedCategory/Ext/ExtClass.lean @@ -0,0 +1,106 @@ +/- +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.Homology.DerivedCategory.Ext.Basic +import Mathlib.Algebra.Homology.DerivedCategory.SingleTriangle + +/-! +# The Ext class of a short exact sequence + +In this file, given a short exact short complex `S : ShortComplex C` +in an abelian category, we construct the associated class in +`Ext S.X₃ S.X₁ 1`. + +-/ + +universe w' w v u + +namespace CategoryTheory + +variable {C : Type u} [Category.{v} C] [Abelian C] [HasExt.{w} C] + +open Localization Limits ZeroObject DerivedCategory Pretriangulated + +open Abelian + +namespace ShortComplex + +variable (S : ShortComplex C) + +namespace ShortExact + +variable {S} +variable (hS : S.ShortExact) + +section + +local notation "W" => HomologicalComplex.quasiIso C (ComplexShape.up ℤ) +local notation "S'" => S.map (CochainComplex.singleFunctor C 0) +local notation "hS'" => hS.map_of_exact (HomologicalComplex.single _ _ _) +local notation "K" => CochainComplex.mappingCone (ShortComplex.f S') +local notation "qis" => CochainComplex.mappingCone.descShortComplex S' +local notation "hqis" => CochainComplex.mappingCone.quasiIso_descShortComplex hS' +local notation "δ" => Triangle.mor₃ (CochainComplex.mappingCone.triangle (ShortComplex.f S')) + +instance : HasSmallLocalizedShiftedHom.{w} W ℤ (S').X₃ (S').X₁ := by + dsimp + infer_instance + +include hS in +private lemma hasSmallLocalizedHom_S'_X₃_K : + HasSmallLocalizedHom.{w} W (S').X₃ K := by + rw [Localization.hasSmallLocalizedHom_iff_target W (S').X₃ qis hqis] + dsimp + apply Localization.hasSmallLocalizedHom_of_hasSmallLocalizedShiftedHom₀ (M := ℤ) + +include hS in +private lemma hasSmallLocalizedShiftedHom_K_S'_X₁ : + HasSmallLocalizedShiftedHom.{w} W ℤ K (S').X₁ := by + rw [Localization.hasSmallLocalizedShiftedHom_iff_source.{w} W ℤ qis hqis (S').X₁] + infer_instance + +/-- The class in `Ext S.X₃ S.X₁ 1` that is attached to a short exact +short complex `S` in an abelian category. -/ +noncomputable def extClass : Ext.{w} S.X₃ S.X₁ 1 := by + have := hS.hasSmallLocalizedHom_S'_X₃_K + have := hS.hasSmallLocalizedShiftedHom_K_S'_X₁ + change SmallHom W (S').X₃ ((S').X₁⟦(1 : ℤ)⟧) + exact (SmallHom.mkInv qis hqis).comp (SmallHom.mk W δ) + +@[simp] +lemma extClass_hom [HasDerivedCategory.{w'} C] : hS.extClass.hom = hS.singleδ := by + change SmallShiftedHom.equiv W Q hS.extClass = _ + dsimp [extClass, SmallShiftedHom.equiv] + erw [SmallHom.equiv_comp, Iso.homToEquiv_apply] + rw [SmallHom.equiv_mkInv, SmallHom.equiv_mk] + dsimp [singleδ, triangleOfSESδ] + rw [Category.assoc, Category.assoc, Category.assoc, + singleFunctorsPostcompQIso_hom_hom, singleFunctorsPostcompQIso_inv_hom] + erw [Category.id_comp, Functor.map_id, Category.comp_id] + rfl + +end + +@[simp] +lemma comp_extClass : (Ext.mk₀ S.g).comp hS.extClass (zero_add 1) = 0 := by + letI := HasDerivedCategory.standard C + ext + simp only [Ext.comp_hom, Ext.mk₀_hom, extClass_hom, Ext.zero_hom, + ShiftedHom.mk₀_comp] + exact comp_distTriang_mor_zero₂₃ _ hS.singleTriangle_distinguished + +@[simp] +lemma extClass_comp : hS.extClass.comp (Ext.mk₀ S.f) (add_zero 1) = 0 := by + letI := HasDerivedCategory.standard C + ext + simp only [Ext.comp_hom, Ext.mk₀_hom, extClass_hom, Ext.zero_hom, + ShiftedHom.comp_mk₀] + exact comp_distTriang_mor_zero₃₁ _ hS.singleTriangle_distinguished + +end ShortExact + +end ShortComplex + +end CategoryTheory diff --git a/Mathlib/Algebra/Homology/DerivedCategory/HomologySequence.lean b/Mathlib/Algebra/Homology/DerivedCategory/HomologySequence.lean index 454e664b1fd81..2df568198c70f 100644 --- a/Mathlib/Algebra/Homology/DerivedCategory/HomologySequence.lean +++ b/Mathlib/Algebra/Homology/DerivedCategory/HomologySequence.lean @@ -45,7 +45,7 @@ instance (n : ℤ) : (homologyFunctor C n).IsHomological := (homologyFunctor C n) _ (homologyFunctorFactorsh C n) /-- The functors `homologyFunctor C n : DerivedCategory C ⥤ C` for all `n : ℤ` are part -of a "shift sequence", i.e. they satisfy compatiblities with shifts. -/ +of a "shift sequence", i.e. they satisfy compatibilities with shifts. -/ noncomputable instance : (homologyFunctor C 0).ShiftSequence ℤ := Functor.ShiftSequence.induced (homologyFunctorFactorsh C 0) ℤ (homologyFunctor C) (homologyFunctorFactorsh C) @@ -54,15 +54,14 @@ variable {C} namespace HomologySequence -variable (T : Triangle (DerivedCategory C)) (hT : T ∈ distTriang _) - (n₀ n₁ : ℤ) (h : n₀ + 1 = n₁) -include hT - /-- The connecting homomorphism on the homology sequence attached to a distinguished triangle in the derived category. -/ -noncomputable def δ : (homologyFunctor C n₀).obj T.obj₃ ⟶ (homologyFunctor C n₁).obj T.obj₁ := +noncomputable def δ (T : Triangle (DerivedCategory C)) + (n₀ n₁ : ℤ) (h : n₀ + 1 = n₁) : + (homologyFunctor C n₀).obj T.obj₃ ⟶ (homologyFunctor C n₁).obj T.obj₁ := (homologyFunctor C 0).shiftMap T.mor₃ n₀ n₁ (by rw [add_comm 1, h]) +variable (T : Triangle (DerivedCategory C)) (hT : T ∈ distTriang _) (n₀ n₁ : ℤ) (h : n₀ + 1 = n₁) include hT @[reassoc (attr := simp)] diff --git a/Mathlib/Algebra/Homology/Embedding/Basic.lean b/Mathlib/Algebra/Homology/Embedding/Basic.lean index 38d9eed123c27..5408a2e292f45 100644 --- a/Mathlib/Algebra/Homology/Embedding/Basic.lean +++ b/Mathlib/Algebra/Homology/Embedding/Basic.lean @@ -52,7 +52,7 @@ namespace ComplexShape /-- An embedding of a complex shape `c : ComplexShape ι` into a complex shape `c' : ComplexShape ι'` consists of a injective map `f : ι → ι'` which satisfies -a compatiblity with respect to the relations `c.Rel` and `c'.Rel`. -/ +a compatibility with respect to the relations `c.Rel` and `c'.Rel`. -/ structure Embedding where /-- the map between the underlying types of indices -/ f : ι → ι' diff --git a/Mathlib/Algebra/Homology/Embedding/TruncGE.lean b/Mathlib/Algebra/Homology/Embedding/TruncGE.lean index 3cfeee56bada8..c0c9a8b3cbd18 100644 --- a/Mathlib/Algebra/Homology/Embedding/TruncGE.lean +++ b/Mathlib/Algebra/Homology/Embedding/TruncGE.lean @@ -110,8 +110,8 @@ noncomputable def truncGE'XIsoOpcycles {i : ι} {i' : ι'} (hi' : e.f i = i') (h (K.truncGE' e).X i ≅ K.opcycles i' := (truncGE'.XIsoOpcycles K e hi) ≪≫ eqToIso (by subst hi'; rfl) -lemma truncGE'_d_eq {i j : ι} (hij : c.Rel i j) {i' j' : ι'} - (hi' : e.f i = i') (hj' : e.f j = j') (hi : ¬ e.BoundaryGE i) : +lemma truncGE'_d_eq {i j : ι} (hij : c.Rel i j) {i' j' : ι'} + (hi' : e.f i = i') (hj' : e.f j = j') (hi : ¬ e.BoundaryGE i) : (K.truncGE' e).d i j = (K.truncGE'XIso e hi' hi).hom ≫ K.d i' j' ≫ (K.truncGE'XIso e hj' (e.not_boundaryGE_next hij)).inv := by dsimp [truncGE', truncGE'.d] diff --git a/Mathlib/Algebra/Homology/ExactSequence.lean b/Mathlib/Algebra/Homology/ExactSequence.lean index 0afb27611c949..bf8559ea76f1a 100644 --- a/Mathlib/Algebra/Homology/ExactSequence.lean +++ b/Mathlib/Algebra/Homology/ExactSequence.lean @@ -159,7 +159,7 @@ lemma exact_iff_of_iso {S₁ S₂ : ComposableArrows C n} (e : S₁ ≅ S₂) : lemma exact₀ (S : ComposableArrows C 0) : S.Exact where toIsComplex := S.isComplex₀ -- See https://github.com/leanprover/lean4/issues/2862 - exact i hi := by simp [autoParam] at hi + exact i hi := by simp at hi lemma exact₁ (S : ComposableArrows C 1) : S.Exact where toIsComplex := S.isComplex₁ diff --git a/Mathlib/Algebra/Homology/HomologySequence.lean b/Mathlib/Algebra/Homology/HomologySequence.lean index 7a54cb2191c0a..6a325db2f53a9 100644 --- a/Mathlib/Algebra/Homology/HomologySequence.lean +++ b/Mathlib/Algebra/Homology/HomologySequence.lean @@ -230,7 +230,8 @@ obtained by applying the functors `homologyFunctor C c i`, `opcyclesFunctor C c `cyclesFunctor C c j`, `homologyFunctor C c j` to `S`. Applying the snake lemma to this gives the homology sequence of `S`. -/ @[simps] -noncomputable def snakeInput : ShortComplex.SnakeInput C where +noncomputable def snakeInput (hS : S.ShortExact) (i j : ι) (hij : c.Rel i j) : + ShortComplex.SnakeInput C where L₀ := (homologyFunctor C c i).mapShortComplex.obj S L₁ := (opcyclesFunctor C c i).mapShortComplex.obj S L₂ := (cyclesFunctor C c j).mapShortComplex.obj S @@ -282,7 +283,7 @@ namespace ShortComplex namespace ShortExact /-- The connecting homoomorphism `S.X₃.homology i ⟶ S.X₁.homology j` for a short exact -short complex `S`. -/ +short complex `S`. -/ noncomputable def δ : S.X₃.homology i ⟶ S.X₁.homology j := (snakeInput hS i j hij).δ @[reassoc (attr := simp)] diff --git a/Mathlib/Algebra/Homology/Homotopy.lean b/Mathlib/Algebra/Homology/Homotopy.lean index bc2fd8fdf31ef..4ee6bcba875ef 100644 --- a/Mathlib/Algebra/Homology/Homotopy.lean +++ b/Mathlib/Algebra/Homology/Homotopy.lean @@ -101,7 +101,7 @@ theorem dNext_nat (C D : ChainComplex V ℕ) (i : ℕ) (f : ∀ i j, C.X i ⟶ D dsimp [dNext] cases i · simp only [shape, ChainComplex.next_nat_zero, ComplexShape.down_Rel, Nat.one_ne_zero, - not_false_iff, zero_comp] + not_false_iff, zero_comp, reduceCtorEq] · congr <;> simp theorem prevD_nat (C D : CochainComplex V ℕ) (i : ℕ) (f : ∀ i j, C.X i ⟶ D.X j) : @@ -109,7 +109,7 @@ theorem prevD_nat (C D : CochainComplex V ℕ) (i : ℕ) (f : ∀ i j, C.X i ⟶ dsimp [prevD] cases i · simp only [shape, CochainComplex.prev_nat_zero, ComplexShape.up_Rel, Nat.one_ne_zero, - not_false_iff, comp_zero] + not_false_iff, comp_zero, reduceCtorEq] · congr <;> simp -- Porting note(#5171): removed @[has_nonempty_instance] diff --git a/Mathlib/Algebra/Homology/HomotopyCategory/MappingCone.lean b/Mathlib/Algebra/Homology/HomotopyCategory/MappingCone.lean index 41a763809646d..42704741a95dc 100644 --- a/Mathlib/Algebra/Homology/HomotopyCategory/MappingCone.lean +++ b/Mathlib/Algebra/Homology/HomotopyCategory/MappingCone.lean @@ -51,7 +51,7 @@ open HomComplex /-- The left inclusion in the mapping cone, as a cochain of degree `-1`. -/ noncomputable def inl : Cochain F (mappingCone φ) (-1) := - Cochain.mk (fun p q hpq => homotopyCofiber.inlX φ p q (by dsimp; omega)) + Cochain.mk (fun p q hpq => homotopyCofiber.inlX φ p q (by dsimp; omega)) /-- The right inclusion in the mapping cone. -/ noncomputable def inr : G ⟶ mappingCone φ := homotopyCofiber.inr φ @@ -286,14 +286,16 @@ lemma δ_snd : section -variable {K : CochainComplex C ℤ} {n m : ℤ} (α : Cochain F K m) - (β : Cochain G K n) (h : m + 1 = n) +variable {K : CochainComplex C ℤ} {n m : ℤ} /-- Given `φ : F ⟶ G`, this is the cochain in `Cochain (mappingCone φ) K n` that is constructed from two cochains `α : Cochain F K m` (with `m + 1 = n`) and `β : Cochain F K n`. -/ -noncomputable def descCochain : Cochain (mappingCone φ) K n := +noncomputable def descCochain (α : Cochain F K m) (β : Cochain G K n) (h : m + 1 = n) : + Cochain (mappingCone φ) K n := (fst φ).1.comp α (by rw [← h, add_comm]) + (snd φ).comp β (zero_add n) +variable (α : Cochain F K m) (β : Cochain G K n) (h : m + 1 = n) + @[simp] lemma inl_descCochain : (inl φ).comp (descCochain φ α β h) (by omega) = α := by @@ -346,15 +348,17 @@ noncomputable def descCocycle {K : CochainComplex C ℤ} {n m : ℤ} section -variable {K : CochainComplex C ℤ} (α : Cochain F K (-1)) (β : G ⟶ K) - (eq : δ (-1) 0 α = Cochain.ofHom (φ ≫ β)) +variable {K : CochainComplex C ℤ} /-- Given `φ : F ⟶ G`, this is the morphism `mappingCone φ ⟶ K` that is constructed from a cochain `α : Cochain F K (-1)` and a morphism `β : G ⟶ K` such that `δ (-1) 0 α = Cochain.ofHom (φ ≫ β)`. -/ -noncomputable def desc : mappingCone φ ⟶ K := +noncomputable def desc (α : Cochain F K (-1)) (β : G ⟶ K) + (eq : δ (-1) 0 α = Cochain.ofHom (φ ≫ β)) : mappingCone φ ⟶ K := Cocycle.homOf (descCocycle φ α (Cocycle.ofHom β) (neg_add_cancel 1) (by simp [eq])) +variable (α : Cochain F K (-1)) (β : G ⟶ K) (eq : δ (-1) 0 α = Cochain.ofHom (φ ≫ β)) + @[simp] lemma ofHom_desc : Cochain.ofHom (desc φ α β eq) = descCochain φ α (Cochain.ofHom β) (neg_add_cancel 1) := by @@ -400,13 +404,15 @@ noncomputable def descHomotopy {K : CochainComplex C ℤ} (f₁ f₂ : mappingCo section variable {K : CochainComplex C ℤ} {n m : ℤ} - (α : Cochain K F m) (β : Cochain K G n) (h : n + 1 = m) /-- Given `φ : F ⟶ G`, this is the cochain in `Cochain (mappingCone φ) K n` that is constructed from two cochains `α : Cochain F K m` (with `m + 1 = n`) and `β : Cochain F K n`. -/ -noncomputable def liftCochain : Cochain K (mappingCone φ) n := +noncomputable def liftCochain (α : Cochain K F m) (β : Cochain K G n) (h : n + 1 = m) : + Cochain K (mappingCone φ) n := α.comp (inl φ) (by omega) + β.comp (Cochain.ofHom (inr φ)) (add_zero n) +variable (α : Cochain K F m) (β : Cochain K G n) (h : n + 1 = m) + @[simp] lemma liftCochain_fst : (liftCochain φ α β h).comp (fst φ).1 h = α := by diff --git a/Mathlib/Algebra/Homology/HomotopyCategory/Pretriangulated.lean b/Mathlib/Algebra/Homology/HomotopyCategory/Pretriangulated.lean index 0ad80b275377d..d5e210fe2d0c1 100644 --- a/Mathlib/Algebra/Homology/HomotopyCategory/Pretriangulated.lean +++ b/Mathlib/Algebra/Homology/HomotopyCategory/Pretriangulated.lean @@ -125,14 +125,15 @@ end mapOfHomotopy section map variable {K₁ L₁ K₂ L₂ K₃ L₃ : CochainComplex C ℤ} (φ₁ : K₁ ⟶ L₁) (φ₂ : K₂ ⟶ L₂) (φ₃ : K₃ ⟶ L₃) - (a : K₁ ⟶ K₂) (b : L₁ ⟶ L₂) (comm : φ₁ ≫ b = a ≫ φ₂) - (a' : K₂ ⟶ K₃) (b' : L₂ ⟶ L₃) (comm' : φ₂ ≫ b' = a' ≫ φ₃) + (a : K₁ ⟶ K₂) (b : L₁ ⟶ L₂) /-- The morphism `mappingCone φ₁ ⟶ mappingCone φ₂` that is induced by a commutative square. -/ -noncomputable def map : mappingCone φ₁ ⟶ mappingCone φ₂ := +noncomputable def map (comm : φ₁ ≫ b = a ≫ φ₂) : mappingCone φ₁ ⟶ mappingCone φ₂ := desc φ₁ ((Cochain.ofHom a).comp (inl φ₂) (zero_add _)) (b ≫ inr φ₂) (by simp [reassoc_of% comm]) +variable (comm : φ₁ ≫ b = a ≫ φ₂) + lemma map_eq_mapOfHomotopy : map φ₁ φ₂ a b comm = mapOfHomotopy (Homotopy.ofEq comm) := by simp [map, mapOfHomotopy] @@ -140,9 +141,12 @@ lemma map_id : map φ φ (𝟙 _) (𝟙 _) (by rw [id_comp, comp_id]) = 𝟙 _ : ext n simp [ext_from_iff _ (n + 1) n rfl, map] +variable (a' : K₂ ⟶ K₃) (b' : L₂ ⟶ L₃) + @[reassoc] -lemma map_comp : map φ₁ φ₃ (a ≫ a') (b ≫ b') (by rw [reassoc_of% comm, comm', assoc]) = - map φ₁ φ₂ a b comm ≫ map φ₂ φ₃ a' b' comm' := by +lemma map_comp (comm' : φ₂ ≫ b' = a' ≫ φ₃) : + map φ₁ φ₃ (a ≫ a') (b ≫ b') (by rw [reassoc_of% comm, comm', assoc]) = + map φ₁ φ₂ a b comm ≫ map φ₂ φ₃ a' b' comm' := by ext n simp [ext_from_iff _ (n+1) n rfl, map] diff --git a/Mathlib/Algebra/Homology/HomotopyCofiber.lean b/Mathlib/Algebra/Homology/HomotopyCofiber.lean index 88c9ce69aaee4..dfbe3a72907ca 100644 --- a/Mathlib/Algebra/Homology/HomotopyCofiber.lean +++ b/Mathlib/Algebra/Homology/HomotopyCofiber.lean @@ -240,10 +240,8 @@ noncomputable def inr : G ⟶ homotopyCofiber φ where section -variable (hc : ∀ j, ∃ i, c.Rel i j) - /-- The composition `φ ≫ mappingCone.inr φ` is homotopic to `0`. -/ -noncomputable def inrCompHomotopy : +noncomputable def inrCompHomotopy (hc : ∀ j, ∃ i, c.Rel i j) : Homotopy (φ ≫ inr φ) 0 where hom i j := if hij : c.Rel j i then inlX φ i j hij else 0 @@ -258,6 +256,8 @@ noncomputable def inrCompHomotopy : · rw [dNext_eq_zero _ _ hj, zero_add, zero_f, add_zero, homotopyCofiber_d, inlX_d' _ _ _ _ hj, comp_f, inr_f] +variable (hc : ∀ j, ∃ i, c.Rel i j) + lemma inrCompHomotopy_hom (i j : ι) (hij : c.Rel j i) : (inrCompHomotopy φ hc).hom i j = inlX φ i j hij := dif_pos hij diff --git a/Mathlib/Algebra/Homology/ShortComplex/LeftHomology.lean b/Mathlib/Algebra/Homology/ShortComplex/LeftHomology.lean index 1d91f59bef1b9..1022a52c7ab90 100644 --- a/Mathlib/Algebra/Homology/ShortComplex/LeftHomology.lean +++ b/Mathlib/Algebra/Homology/ShortComplex/LeftHomology.lean @@ -388,10 +388,10 @@ section variable (S) variable [S.HasLeftHomology] -/-- The left homology of a short complex, given by the `H` field of a chosen left homology data. -/ +/-- The left homology of a short complex, given by the `H` field of a chosen left homology data. -/ noncomputable def leftHomology : C := S.leftHomologyData.H -/-- The cycles of a short complex, given by the `K` field of a chosen left homology data. -/ +/-- The cycles of a short complex, given by the `K` field of a chosen left homology data. -/ noncomputable def cycles : C := S.leftHomologyData.K /-- The "homology class" map `S.cycles ⟶ S.leftHomology`. -/ diff --git a/Mathlib/Algebra/Homology/ShortComplex/Preadditive.lean b/Mathlib/Algebra/Homology/ShortComplex/Preadditive.lean index dee25030965f5..8d23c46c9a207 100644 --- a/Mathlib/Algebra/Homology/ShortComplex/Preadditive.lean +++ b/Mathlib/Algebra/Homology/ShortComplex/Preadditive.lean @@ -451,7 +451,7 @@ def add (h : Homotopy φ₁ φ₂) (h' : Homotopy φ₃ φ₄) : Homotopy (φ₁ comm₂ := by rw [add_τ₂, add_τ₂, h.comm₂, h'.comm₂, comp_add, add_comp]; abel comm₃ := by rw [add_τ₃, add_τ₃, h.comm₃, h'.comm₃, add_comp]; abel -/-- Homotopy between morphisms of short complexes is compatible with substraction. -/ +/-- Homotopy between morphisms of short complexes is compatible with subtraction. -/ @[simps] def sub (h : Homotopy φ₁ φ₂) (h' : Homotopy φ₃ φ₄) : Homotopy (φ₁ - φ₃) (φ₂ - φ₄) where h₀ := h.h₀ - h'.h₀ @@ -508,7 +508,7 @@ def op (h : Homotopy φ₁ φ₂) : Homotopy (opMap φ₁) (opMap φ₂) where /-- The homotopy between morphisms in `ShortComplex C` that is induced by a homotopy between morphisms in `ShortComplex Cᵒᵖ`. -/ @[simps] -def unop {S₁ S₂ : ShortComplex Cᵒᵖ} {φ₁ φ₂ : S₁ ⟶ S₂} (h : Homotopy φ₁ φ₂) : +def unop {S₁ S₂ : ShortComplex Cᵒᵖ} {φ₁ φ₂ : S₁ ⟶ S₂} (h : Homotopy φ₁ φ₂) : Homotopy (unopMap φ₁) (unopMap φ₂) where h₀ := h.h₃.unop h₁ := h.h₂.unop diff --git a/Mathlib/Algebra/Homology/ShortComplex/RightHomology.lean b/Mathlib/Algebra/Homology/ShortComplex/RightHomology.lean index 5a62395fcb632..865ffa00b94fb 100644 --- a/Mathlib/Algebra/Homology/ShortComplex/RightHomology.lean +++ b/Mathlib/Algebra/Homology/ShortComplex/RightHomology.lean @@ -1004,7 +1004,7 @@ variable (φ : S₁ ⟶ S₂) (h : RightHomologyData S₁) [Epi φ.τ₁] [IsIso /-- If `φ : S₁ ⟶ S₂` is a morphism of short complexes such that `φ.τ₁` is epi, `φ.τ₂` is an iso and `φ.τ₃` is mono, then a right homology data for `S₁` induces a right homology data for `S₂` with the same `Q` and `H` fields. This is obtained by dualising `LeftHomologyData.ofEpiOfIsIsoOfMono'`. -The inverse construction is `ofEpiOfIsIsoOfMono'`. -/ +The inverse construction is `ofEpiOfIsIsoOfMono'`. -/ noncomputable def ofEpiOfIsIsoOfMono : RightHomologyData S₂ := by haveI : Epi (opMap φ).τ₁ := by dsimp; infer_instance haveI : IsIso (opMap φ).τ₂ := by dsimp; infer_instance @@ -1032,7 +1032,7 @@ variable (φ : S₁ ⟶ S₂) (h : RightHomologyData S₂) [Epi φ.τ₁] [IsIso /-- If `φ : S₁ ⟶ S₂` is a morphism of short complexes such that `φ.τ₁` is epi, `φ.τ₂` is an iso and `φ.τ₃` is mono, then a right homology data for `S₂` induces a right homology data for `S₁` with the same `Q` and `H` fields. This is obtained by dualising `LeftHomologyData.ofEpiOfIsIsoOfMono`. -The inverse construction is `ofEpiOfIsIsoOfMono`. -/ +The inverse construction is `ofEpiOfIsIsoOfMono`. -/ noncomputable def ofEpiOfIsIsoOfMono' : RightHomologyData S₁ := by haveI : Epi (opMap φ).τ₁ := by dsimp; infer_instance haveI : IsIso (opMap φ).τ₂ := by dsimp; infer_instance diff --git a/Mathlib/Algebra/Jordan/Basic.lean b/Mathlib/Algebra/Jordan/Basic.lean index edd1a4df00c40..b6e455cab6209 100644 --- a/Mathlib/Algebra/Jordan/Basic.lean +++ b/Mathlib/Algebra/Jordan/Basic.lean @@ -82,12 +82,12 @@ class IsJordan [Mul A] : Prop where lmul_comm_rmul_rmul : ∀ a b : A, a * b * (a * a) = a * (b * (a * a)) rmul_comm_rmul_rmul : ∀ a b : A, b * a * (a * a) = b * (a * a) * a -/-- A commutative Jordan multipication -/ +/-- A commutative Jordan multiplication -/ class IsCommJordan [CommMagma A] : Prop where lmul_comm_rmul_rmul : ∀ a b : A, a * b * (a * a) = a * (b * (a * a)) -- see Note [lower instance priority] -/-- A (commutative) Jordan multiplication is also a Jordan multipication -/ +/-- A (commutative) Jordan multiplication is also a Jordan multiplication -/ instance (priority := 100) IsCommJordan.toIsJordan [CommMagma A] [IsCommJordan A] : IsJordan A where lmul_comm_rmul a b := by rw [mul_comm, mul_comm a b] lmul_lmul_comm_lmul a b := by @@ -101,7 +101,7 @@ instance (priority := 100) IsCommJordan.toIsJordan [CommMagma A] [IsCommJordan A rw [mul_comm b a, IsCommJordan.lmul_comm_rmul_rmul, mul_comm] -- see Note [lower instance priority] -/-- Semigroup multiplication satisfies the (non-commutative) Jordan axioms-/ +/-- Semigroup multiplication satisfies the (non-commutative) Jordan axioms -/ instance (priority := 100) Semigroup.isJordan [Semigroup A] : IsJordan A where lmul_comm_rmul a b := by rw [mul_assoc] lmul_lmul_comm_lmul a b := by rw [mul_assoc, mul_assoc] diff --git a/Mathlib/Algebra/Lie/BaseChange.lean b/Mathlib/Algebra/Lie/BaseChange.lean index 6ad77f8f9d079..232b3327a85d3 100644 --- a/Mathlib/Algebra/Lie/BaseChange.lean +++ b/Mathlib/Algebra/Lie/BaseChange.lean @@ -169,10 +169,10 @@ def baseChange : LieSubmodule A (A ⊗[R] L) (A ⊗[R] M) := intro x m hm simp only [AddSubsemigroup.mem_carrier, AddSubmonoid.mem_toSubsemigroup, Submodule.mem_toAddSubmonoid] at hm ⊢ - obtain ⟨c, rfl⟩ := (Finsupp.mem_span_iff_total _ _ _).mp hm + obtain ⟨c, rfl⟩ := (Finsupp.mem_span_iff_linearCombination _ _ _).mp hm refine x.induction_on (by simp) (fun a y ↦ ?_) (fun y z hy hz ↦ ?_) · change toEnd A (A ⊗[R] L) (A ⊗[R] M) _ _ ∈ _ - simp_rw [Finsupp.total_apply, Finsupp.sum, map_sum, map_smul, toEnd_apply_apply] + simp_rw [Finsupp.linearCombination_apply, Finsupp.sum, map_sum, map_smul, toEnd_apply_apply] suffices ∀ n : (N : Submodule R M).map (TensorProduct.mk R A M 1), ⁅a ⊗ₜ[R] y, (n : A ⊗[R] M)⁆ ∈ (N : Submodule R M).baseChange A by exact Submodule.sum_mem _ fun n _ ↦ Submodule.smul_mem _ _ (this n) diff --git a/Mathlib/Algebra/Lie/Basic.lean b/Mathlib/Algebra/Lie/Basic.lean index c8a7cd3805a7b..40207bffb861a 100644 --- a/Mathlib/Algebra/Lie/Basic.lean +++ b/Mathlib/Algebra/Lie/Basic.lean @@ -385,13 +385,11 @@ theorem coe_linearMap_comp (f : L₂ →ₗ⁅R⁆ L₃) (g : L₁ →ₗ⁅R⁆ rfl @[simp] -theorem comp_id (f : L₁ →ₗ⁅R⁆ L₂) : f.comp (id : L₁ →ₗ⁅R⁆ L₁) = f := by - ext +theorem comp_id (f : L₁ →ₗ⁅R⁆ L₂) : f.comp (id : L₁ →ₗ⁅R⁆ L₁) = f := rfl @[simp] -theorem id_comp (f : L₁ →ₗ⁅R⁆ L₂) : (id : L₂ →ₗ⁅R⁆ L₂).comp f = f := by - ext +theorem id_comp (f : L₁ →ₗ⁅R⁆ L₂) : (id : L₂ →ₗ⁅R⁆ L₂).comp f = f := rfl /-- The inverse of a bijective morphism is a morphism. -/ @@ -538,9 +536,7 @@ def symm (e : L₁ ≃ₗ⁅R⁆ L₂) : L₂ ≃ₗ⁅R⁆ L₁ := { LieHom.inverse e.toLieHom e.invFun e.left_inv e.right_inv, e.toLinearEquiv.symm with } @[simp] -theorem symm_symm (e : L₁ ≃ₗ⁅R⁆ L₂) : e.symm.symm = e := by - ext - rfl +theorem symm_symm (e : L₁ ≃ₗ⁅R⁆ L₂) : e.symm.symm = e := rfl theorem symm_bijective : Function.Bijective (LieEquiv.symm : (L₁ ≃ₗ⁅R⁆ L₂) → L₂ ≃ₗ⁅R⁆ L₁) := Function.bijective_iff_has_inverse.mpr ⟨_, symm_symm, symm_symm⟩ @@ -941,8 +937,7 @@ theorem apply_eq_iff_eq_symm_apply {m : M} {n : N} (e : M ≃ₗ⁅R,L⁆ N) : (e : M ≃ N).apply_eq_iff_eq_symm_apply @[simp] -theorem symm_symm (e : M ≃ₗ⁅R,L⁆ N) : e.symm.symm = e := by - rfl +theorem symm_symm (e : M ≃ₗ⁅R,L⁆ N) : e.symm.symm = e := rfl theorem symm_bijective : Function.Bijective (LieModuleEquiv.symm : (M ≃ₗ⁅R,L⁆ N) → N ≃ₗ⁅R,L⁆ M) := diff --git a/Mathlib/Algebra/Lie/CartanExists.lean b/Mathlib/Algebra/Lie/CartanExists.lean index 2a91aa8017dfa..bbdbc280d8416 100644 --- a/Mathlib/Algebra/Lie/CartanExists.lean +++ b/Mathlib/Algebra/Lie/CartanExists.lean @@ -164,6 +164,13 @@ 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`. diff --git a/Mathlib/Algebra/Lie/CartanSubalgebra.lean b/Mathlib/Algebra/Lie/CartanSubalgebra.lean index acf506d5862cc..f5d08788b2163 100644 --- a/Mathlib/Algebra/Lie/CartanSubalgebra.lean +++ b/Mathlib/Algebra/Lie/CartanSubalgebra.lean @@ -59,9 +59,9 @@ theorem normalizer_eq_self_of_isCartanSubalgebra (H : LieSubalgebra R L) [H.IsCa @[simp] theorem ucs_eq_self_of_isCartanSubalgebra (H : LieSubalgebra R L) [H.IsCartanSubalgebra] (k : ℕ) : H.toLieSubmodule.ucs k = H.toLieSubmodule := by - induction' k with k ih - · simp - · simp [ih] + induction k with + | zero => simp + | succ k ih => simp [ih] theorem isCartanSubalgebra_iff_isUcsLimit : H.IsCartanSubalgebra ↔ H.toLieSubmodule.IsUcsLimit := by constructor diff --git a/Mathlib/Algebra/Lie/Classical.lean b/Mathlib/Algebra/Lie/Classical.lean index 23b88270b6e03..cc6d16181296e 100644 --- a/Mathlib/Algebra/Lie/Classical.lean +++ b/Mathlib/Algebra/Lie/Classical.lean @@ -329,7 +329,7 @@ theorem indefiniteDiagonal_assoc : Sum.elim_inl, if_true, eq_self_iff_true, Matrix.one_apply_eq, Matrix.fromBlocks_apply₁₁, DMatrix.zero_apply, Equiv.sumAssoc_apply_inl_inr, if_false, Matrix.fromBlocks_apply₁₂, Matrix.fromBlocks_apply₂₁, Matrix.fromBlocks_apply₂₂, Equiv.sumAssoc_apply_inr, - Sum.elim_inr, Sum.inl_injective.eq_iff, Sum.inr_injective.eq_iff] <;> + Sum.elim_inr, Sum.inl_injective.eq_iff, Sum.inr_injective.eq_iff, reduceCtorEq] <;> congr 1 /-- An equivalence between two possible definitions of the classical Lie algebra of type B. -/ diff --git a/Mathlib/Algebra/Lie/Derivation/Killing.lean b/Mathlib/Algebra/Lie/Derivation/Killing.lean index e6c9325939168..f7aca54a214c2 100644 --- a/Mathlib/Algebra/Lie/Derivation/Killing.lean +++ b/Mathlib/Algebra/Lie/Derivation/Killing.lean @@ -87,6 +87,14 @@ 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 _ /-- The range of the adjoint action on a finite-dimensional Killing Lie algebra is full. -/ diff --git a/Mathlib/Algebra/Lie/DirectSum.lean b/Mathlib/Algebra/Lie/DirectSum.lean index 7d4a6efc56417..f4d73a8802ef0 100644 --- a/Mathlib/Algebra/Lie/DirectSum.lean +++ b/Mathlib/Algebra/Lie/DirectSum.lean @@ -229,10 +229,20 @@ 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/Engel.lean b/Mathlib/Algebra/Lie/Engel.lean index 7dff375e7f62d..4b96b9ada30d7 100644 --- a/Mathlib/Algebra/Lie/Engel.lean +++ b/Mathlib/Algebra/Lie/Engel.lean @@ -109,11 +109,13 @@ theorem lcs_le_lcs_of_is_nilpotent_span_sup_eq_top {n i j : ℕ} (I.lcs M (j + 1) : Submodule R M) by simpa only [bot_sup_eq, LieIdeal.incl_coe, Submodule.map_zero, hxn] using this n intro l - induction' l with l ih - · simp only [add_zero, LieIdeal.lcs_succ, pow_zero, LinearMap.one_eq_id, + induction l with + | zero => + simp only [add_zero, LieIdeal.lcs_succ, pow_zero, LinearMap.one_eq_id, Submodule.map_id] exact le_sup_of_le_left hIM - · simp only [LieIdeal.lcs_succ, i.add_succ l, lie_top_eq_of_span_sup_eq_top hxI, sup_le_iff] + | succ l ih => + simp only [LieIdeal.lcs_succ, i.add_succ l, lie_top_eq_of_span_sup_eq_top hxI, sup_le_iff] refine ⟨(Submodule.map_mono ih).trans ?_, le_sup_of_le_right ?_⟩ · rw [Submodule.map_sup, ← Submodule.map_comp, ← LinearMap.mul_eq_comp, ← pow_succ', ← I.lcs_succ] @@ -131,9 +133,9 @@ theorem isNilpotentOfIsNilpotentSpanSupEqTop (hnp : IsNilpotent <| toEnd R L M x use k * n simpa [hk'] using this k intro l - induction' l with l ih - · simp - · exact (l.succ_mul n).symm ▸ lcs_le_lcs_of_is_nilpotent_span_sup_eq_top hxI hn ih + induction l with + | zero => simp + | succ l ih => exact (l.succ_mul n).symm ▸ lcs_le_lcs_of_is_nilpotent_span_sup_eq_top hxI hn ih end LieSubmodule @@ -198,7 +200,9 @@ theorem LieAlgebra.exists_engelian_lieSubalgebra_of_lt_normalizer {K : LieSubalg have hI₂ : (R ∙ (⟨x, hxK'⟩ : K')) ⊔ (LieSubmodule.toSubmodule I) = ⊤ := by rw [← LieIdeal.coe_to_lieSubalgebra_to_submodule R K' I, hI₁] apply Submodule.map_injective_of_injective (K' : Submodule R L).injective_subtype - simp + simp only [LieSubalgebra.coe_ofLe, Submodule.map_sup, Submodule.map_subtype_range_inclusion, + Submodule.map_top, Submodule.range_subtype] + rw [Submodule.map_subtype_span_singleton] have e : K ≃ₗ⁅R⁆ I := (LieSubalgebra.equivOfLe hKK').trans (LieEquiv.ofEq _ _ ((LieSubalgebra.coe_set_eq _ _).mpr hI₁.symm)) @@ -258,7 +262,7 @@ theorem LieAlgebra.isEngelian_of_isNoetherian [IsNoetherian R L] : LieAlgebra.Is refine isNoetherian_of_surjective L (LieHom.rangeRestrict (toEnd R L M)) ?_ simp only [LieHom.range_coeSubmodule, LieHom.coe_toLinearMap, LinearMap.range_eq_top] exact LieHom.surjective_rangeRestrict (toEnd R L M) - obtain ⟨K, hK₁, hK₂⟩ := (LieSubalgebra.wellFounded_of_noetherian R L').has_min s hs + obtain ⟨K, hK₁, hK₂⟩ := (LieSubalgebra.wellFoundedGT_of_noetherian R L').wf.has_min s hs have hK₃ : K = ⊤ := by by_contra contra obtain ⟨K', hK'₁, hK'₂⟩ := this K hK₁ contra diff --git a/Mathlib/Algebra/Lie/EngelSubalgebra.lean b/Mathlib/Algebra/Lie/EngelSubalgebra.lean index 73ab3ad4f7c2b..031da676554e7 100644 --- a/Mathlib/Algebra/Lie/EngelSubalgebra.lean +++ b/Mathlib/Algebra/Lie/EngelSubalgebra.lean @@ -113,6 +113,12 @@ 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) @@ -127,7 +133,8 @@ lemma normalizer_eq_self_of_engel_le [IsArtinian R L] clear hk; revert hy generalize k+1 = k induction k generalizing y with - | zero => cases y; intro hy; simpa using hy + | zero => cases y; intro hy; simp only [pow_zero, LinearMap.one_apply]; exact + (AddSubmonoid.mk_eq_zero N.toAddSubmonoid).mp hy | succ k ih => simp only [pow_succ, LinearMap.mem_ker, LinearMap.mul_apply] at ih ⊢; apply ih · rw [← Submodule.map_le_iff_le_comap] apply le_sup_of_le_right diff --git a/Mathlib/Algebra/Lie/IdealOperations.lean b/Mathlib/Algebra/Lie/IdealOperations.lean index 0c18a9d49f2d5..99a95d581f6e3 100644 --- a/Mathlib/Algebra/Lie/IdealOperations.lean +++ b/Mathlib/Algebra/Lie/IdealOperations.lean @@ -213,6 +213,12 @@ 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) : diff --git a/Mathlib/Algebra/Lie/InvariantForm.lean b/Mathlib/Algebra/Lie/InvariantForm.lean index ba8b199d8e77c..dea6e6da8c49d 100644 --- a/Mathlib/Algebra/Lie/InvariantForm.lean +++ b/Mathlib/Algebra/Lie/InvariantForm.lean @@ -61,14 +61,12 @@ lemma _root_.LinearMap.BilinForm.lieInvariant_iff [LieAlgebra R L] [LieModule R LinearMap.zero_apply, sub_eq_zero] at h simp [← h] -variable (hΦ_inv : Φ.lieInvariant L) - /-- The orthogonal complement of a Lie submodule `N` with respect to an invariant bilinear form `Φ` is the Lie submodule of elements `y` such that `Φ x y = 0` for all `x ∈ N`. -/ @[simps!] -def orthogonal (N : LieSubmodule R L M) : LieSubmodule R L M where +def orthogonal (hΦ_inv : Φ.lieInvariant L) (N : LieSubmodule R L M) : LieSubmodule R L M where __ := Φ.orthogonal N lie_mem {x y} := by suffices (∀ n ∈ N, Φ n y = 0) → ∀ n ∈ N, Φ n ⁅x, y⁆ = 0 by @@ -79,6 +77,8 @@ def orthogonal (N : LieSubmodule R L M) : LieSubmodule R L M where rw [← neg_eq_zero, ← hΦ_inv] exact H _ <| N.lie_mem ha +variable (hΦ_inv : Φ.lieInvariant L) + @[simp] lemma orthogonal_toSubmodule (N : LieSubmodule R L M) : (orthogonal Φ hΦ_inv N).toSubmodule = Φ.orthogonal N.toSubmodule := rfl diff --git a/Mathlib/Algebra/Lie/Nilpotent.lean b/Mathlib/Algebra/Lie/Nilpotent.lean index 2216a2f250436..fd18eb25f5cf4 100644 --- a/Mathlib/Algebra/Lie/Nilpotent.lean +++ b/Mathlib/Algebra/Lie/Nilpotent.lean @@ -64,9 +64,9 @@ theorem lcs_succ : N.lcs (k + 1) = ⁅(⊤ : LieIdeal R L), N.lcs k⁆ := @[simp] lemma lcs_sup {N₁ N₂ : LieSubmodule R L M} {k : ℕ} : (N₁ ⊔ N₂).lcs k = N₁.lcs k ⊔ N₂.lcs k := by - induction' k with k ih - · simp - · simp only [LieSubmodule.lcs_succ, ih, LieSubmodule.lie_sup] + induction k with + | zero => simp + | succ k ih => simp only [LieSubmodule.lcs_succ, ih, LieSubmodule.lie_sup] end LieSubmodule @@ -94,17 +94,19 @@ namespace LieSubmodule open LieModule theorem lcs_le_self : N.lcs k ≤ N := by - induction' k with k ih - · simp - · simp only [lcs_succ] + induction k with + | zero => simp + | succ k ih => + simp only [lcs_succ] exact (LieSubmodule.mono_lie_right ⊤ ih).trans (N.lie_le_right ⊤) variable [LieModule R L M] theorem lowerCentralSeries_eq_lcs_comap : lowerCentralSeries R L N k = (N.lcs k).comap N.incl := by - induction' k with k ih - · simp - · simp only [lcs_succ, lowerCentralSeries_succ] at ih ⊢ + induction k with + | zero => simp + | succ k ih => + simp only [lcs_succ, lowerCentralSeries_succ] at ih ⊢ have : N.lcs k ≤ N.incl.range := by rw [N.range_incl] apply lcs_le_self @@ -123,19 +125,21 @@ variable (R L M) theorem antitone_lowerCentralSeries : Antitone <| lowerCentralSeries R L M := by intro l k - induction' k with k ih generalizing l <;> intro h - · exact (Nat.le_zero.mp h).symm ▸ le_rfl - · rcases Nat.of_le_succ h with (hk | hk) + induction k generalizing l with + | zero => exact fun h ↦ (Nat.le_zero.mp h).symm ▸ le_rfl + | succ k ih => + intro h + rcases Nat.of_le_succ h with (hk | hk) · rw [lowerCentralSeries_succ] exact (LieSubmodule.mono_lie_right ⊤ (ih hk)).trans (LieSubmodule.lie_le_right _ _) · exact hk.symm ▸ le_rfl theorem eventually_iInf_lowerCentralSeries_eq [IsArtinian R M] : ∀ᶠ l in Filter.atTop, ⨅ k, lowerCentralSeries R L M k = lowerCentralSeries R L M l := by - have h_wf : WellFounded ((· > ·) : (LieSubmodule R L M)ᵒᵈ → (LieSubmodule R L M)ᵒᵈ → Prop) := - LieSubmodule.wellFounded_of_isArtinian R L M + have h_wf : WellFoundedGT (LieSubmodule R L M)ᵒᵈ := + LieSubmodule.wellFoundedLT_of_isArtinian R L M obtain ⟨n, hn : ∀ m, n ≤ m → lowerCentralSeries R L M n = lowerCentralSeries R L M m⟩ := - WellFounded.monotone_chain_condition.mp h_wf ⟨_, antitone_lowerCentralSeries R L M⟩ + WellFounded.monotone_chain_condition.mp h_wf.wf ⟨_, antitone_lowerCentralSeries R L M⟩ refine Filter.eventually_atTop.mpr ⟨n, fun l hl ↦ le_antisymm (iInf_le _ _) (le_iInf fun m ↦ ?_)⟩ rcases le_or_lt l m with h | h · rw [← hn _ hl, ← hn _ (hl.trans h)] @@ -156,38 +160,43 @@ variable [LieModule R L M] theorem iterate_toEnd_mem_lowerCentralSeries (x : L) (m : M) (k : ℕ) : (toEnd R L M x)^[k] m ∈ lowerCentralSeries R L M k := by - induction' k with k ih - · simp only [Function.iterate_zero, lowerCentralSeries_zero, LieSubmodule.mem_top] - · simp only [lowerCentralSeries_succ, Function.comp_apply, Function.iterate_succ', + induction k with + | zero => simp only [Function.iterate_zero, lowerCentralSeries_zero, LieSubmodule.mem_top] + | succ k ih => + simp only [lowerCentralSeries_succ, Function.comp_apply, Function.iterate_succ', toEnd_apply_apply] exact LieSubmodule.lie_mem_lie (LieSubmodule.mem_top x) ih theorem iterate_toEnd_mem_lowerCentralSeries₂ (x y : L) (m : M) (k : ℕ) : (toEnd R L M x ∘ₗ toEnd R L M y)^[k] m ∈ lowerCentralSeries R L M (2 * k) := by - induction' k with k ih - · simp - have hk : 2 * k.succ = (2 * k + 1) + 1 := rfl - simp only [lowerCentralSeries_succ, Function.comp_apply, Function.iterate_succ', hk, + induction k with + | zero => simp + | succ k ih => + have hk : 2 * k.succ = (2 * k + 1) + 1 := rfl + simp only [lowerCentralSeries_succ, Function.comp_apply, Function.iterate_succ', hk, toEnd_apply_apply, LinearMap.coe_comp, toEnd_apply_apply] - refine LieSubmodule.lie_mem_lie (LieSubmodule.mem_top x) ?_ - exact LieSubmodule.lie_mem_lie (LieSubmodule.mem_top y) ih + refine LieSubmodule.lie_mem_lie (LieSubmodule.mem_top x) ?_ + exact LieSubmodule.lie_mem_lie (LieSubmodule.mem_top y) ih variable {R L M} theorem map_lowerCentralSeries_le (f : M →ₗ⁅R,L⁆ M₂) : (lowerCentralSeries R L M k).map f ≤ lowerCentralSeries R L M₂ k := by - induction' k with k ih - · simp only [lowerCentralSeries_zero, le_top] - · simp only [LieModule.lowerCentralSeries_succ, LieSubmodule.map_bracket_eq] + induction k with + | zero => simp only [lowerCentralSeries_zero, le_top] + | succ k ih => + simp only [LieModule.lowerCentralSeries_succ, LieSubmodule.map_bracket_eq] exact LieSubmodule.mono_lie_right ⊤ ih lemma map_lowerCentralSeries_eq {f : M →ₗ⁅R,L⁆ M₂} (hf : Function.Surjective f) : (lowerCentralSeries R L M k).map f = lowerCentralSeries R L M₂ k := by apply le_antisymm (map_lowerCentralSeries_le k f) - induction' k with k ih - · rwa [lowerCentralSeries_zero, lowerCentralSeries_zero, top_le_iff, f.map_top, f.range_eq_top] - · simp only [lowerCentralSeries_succ, LieSubmodule.map_bracket_eq] + induction k with + | zero => + rwa [lowerCentralSeries_zero, lowerCentralSeries_zero, top_le_iff, f.map_top, f.range_eq_top] + | succ => + simp only [lowerCentralSeries_succ, LieSubmodule.map_bracket_eq] apply LieSubmodule.mono_lie_right assumption @@ -197,9 +206,10 @@ open LieAlgebra theorem derivedSeries_le_lowerCentralSeries (k : ℕ) : derivedSeries R L k ≤ lowerCentralSeries R L L k := by - induction' k with k h - · rw [derivedSeries_def, derivedSeriesOfIdeal_zero, lowerCentralSeries_zero] - · have h' : derivedSeries R L k ≤ ⊤ := by simp only [le_top] + induction k with + | zero => rw [derivedSeries_def, derivedSeriesOfIdeal_zero, lowerCentralSeries_zero] + | succ k h => + have h' : derivedSeries R L k ≤ ⊤ := by simp only [le_top] rw [derivedSeries_def, derivedSeriesOfIdeal_succ, lowerCentralSeries_succ] exact LieSubmodule.mono_lie h' h @@ -402,6 +412,13 @@ 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] : @@ -413,9 +430,10 @@ theorem nontrivial_max_triv_of_isNilpotent [Nontrivial M] [IsNilpotent R L M] : theorem coe_lcs_range_toEnd_eq (k : ℕ) : (lowerCentralSeries R (toEnd R L M).range M k : Submodule R M) = lowerCentralSeries R L M k := by - induction' k with k ih - · simp - · simp only [lowerCentralSeries_succ, LieSubmodule.lieIdeal_oper_eq_linear_span', ← + induction k with + | zero => simp + | succ k ih => + simp only [lowerCentralSeries_succ, LieSubmodule.lieIdeal_oper_eq_linear_span', ← (lowerCentralSeries R (toEnd R L M).range M k).mem_coeSubmodule, ih] congr ext m @@ -459,15 +477,16 @@ theorem ucs_add (k l : ℕ) : N.ucs (k + l) = (N.ucs l).ucs k := @[gcongr, mono] theorem ucs_mono (k : ℕ) (h : N₁ ≤ N₂) : N₁.ucs k ≤ N₂.ucs k := by - induction' k with k ih - · simpa - simp only [ucs_succ] - gcongr + induction k with + | zero => simpa + | succ k ih => + simp only [ucs_succ] + gcongr theorem ucs_eq_self_of_normalizer_eq_self (h : N₁.normalizer = N₁) (k : ℕ) : N₁.ucs k = N₁ := by - induction' k with k ih - · simp - · rwa [ucs_succ, ih] + induction k with + | zero => simp + | succ k ih => rwa [ucs_succ, ih] /-- If a Lie module `M` contains a self-normalizing Lie submodule `N`, then all terms of the upper central series of `M` are contained in `N`. @@ -481,9 +500,10 @@ theorem ucs_le_of_normalizer_eq_self (h : N₁.normalizer = N₁) (k : ℕ) : simp theorem lcs_add_le_iff (l k : ℕ) : N₁.lcs (l + k) ≤ N₂ ↔ N₁.lcs l ≤ N₂.ucs k := by - induction' k with k ih generalizing l - · simp - rw [(by abel : l + (k + 1) = l + 1 + k), ih, ucs_succ, lcs_succ, top_lie_le_iff_le_normalizer] + induction k generalizing l with + | zero => simp + | succ k ih => + rw [(by abel : l + (k + 1) = l + 1 + k), ih, ucs_succ, lcs_succ, top_lie_le_iff_le_normalizer] theorem lcs_le_iff (k : ℕ) : N₁.lcs k ≤ N₂ ↔ N₁ ≤ N₂.ucs k := by -- Porting note: `convert` needed type annotations @@ -504,9 +524,9 @@ theorem _root_.LieModule.isNilpotent_iff_exists_ucs_eq_top : theorem ucs_comap_incl (k : ℕ) : ((⊥ : LieSubmodule R L M).ucs k).comap N.incl = (⊥ : LieSubmodule R L N).ucs k := by - induction' k with k ih - · exact N.ker_incl - · simp [← ih] + induction k with + | zero => exact N.ker_incl + | succ k ih => simp [← ih] theorem isNilpotent_iff_exists_self_le_ucs : LieModule.IsNilpotent R L N ↔ ∃ k, N ≤ (⊥ : LieSubmodule R L M).ucs k := by @@ -530,9 +550,10 @@ variable (hf : Surjective f) (hg : Surjective g) (hfg : ∀ x m, ⁅f x, g m⁆ include hf hg hfg in theorem Function.Surjective.lieModule_lcs_map_eq (k : ℕ) : (lowerCentralSeries R L M k : Submodule R M).map g = lowerCentralSeries R L₂ M₂ k := by - induction' k with k ih - · simpa [LinearMap.range_eq_top] - · suffices + induction k with + | zero => simpa [LinearMap.range_eq_top] + | succ k ih => + suffices g '' {m | ∃ (x : L) (n : _), n ∈ lowerCentralSeries R L M k ∧ ⁅x, n⁆ = m} = {m | ∃ (x : L₂) (n : _), n ∈ lowerCentralSeries R L M k ∧ ⁅x, g n⁆ = m} by simp only [← LieSubmodule.mem_coeSubmodule] at this @@ -574,7 +595,18 @@ 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 @@ -620,10 +652,12 @@ morphisms between Lie modules over different Lie algebras. -/ theorem coe_lowerCentralSeries_ideal_quot_eq {I : LieIdeal R L} (k : ℕ) : LieSubmodule.toSubmodule (lowerCentralSeries R L (L ⧸ I) k) = LieSubmodule.toSubmodule (lowerCentralSeries R (L ⧸ I) (L ⧸ I) k) := by - induction' k with k ih - · simp only [LieModule.lowerCentralSeries_zero, LieSubmodule.top_coeSubmodule, + induction k with + | zero => + simp only [LieModule.lowerCentralSeries_zero, LieSubmodule.top_coeSubmodule, LieIdeal.top_coe_lieSubalgebra, LieSubalgebra.top_coe_submodule] - · simp only [LieModule.lowerCentralSeries_succ, LieSubmodule.lieIdeal_oper_eq_linear_span] + | succ k ih => + simp only [LieModule.lowerCentralSeries_succ, LieSubmodule.lieIdeal_oper_eq_linear_span] congr ext x constructor @@ -639,9 +673,10 @@ theorem coe_lowerCentralSeries_ideal_quot_eq {I : LieIdeal R L} (k : ℕ) : -- Porting note: added `LieSubmodule.toSubmodule` in the statement theorem LieModule.coe_lowerCentralSeries_ideal_le {I : LieIdeal R L} (k : ℕ) : LieSubmodule.toSubmodule (lowerCentralSeries R I I k) ≤ lowerCentralSeries R L I k := by - induction' k with k ih - · simp - · simp only [LieModule.lowerCentralSeries_succ, LieSubmodule.lieIdeal_oper_eq_linear_span] + induction k with + | zero => simp + | succ k ih => + simp only [LieModule.lowerCentralSeries_succ, LieSubmodule.lieIdeal_oper_eq_linear_span] apply Submodule.span_mono rintro x ⟨⟨y, -⟩, ⟨z, hz⟩, rfl : ⁅y, z⁆ = x⟩ exact ⟨⟨y.val, LieSubmodule.mem_top _⟩, ⟨z, ih hz⟩, rfl⟩ @@ -661,9 +696,10 @@ theorem LieAlgebra.non_trivial_center_of_isNilpotent [Nontrivial L] [IsNilpotent theorem LieIdeal.map_lowerCentralSeries_le (k : ℕ) {f : L →ₗ⁅R⁆ L'} : LieIdeal.map f (lowerCentralSeries R L L k) ≤ lowerCentralSeries R L' L' k := by - induction' k with k ih - · simp only [LieModule.lowerCentralSeries_zero, le_top] - · simp only [LieModule.lowerCentralSeries_succ] + induction k with + | zero => simp only [LieModule.lowerCentralSeries_zero, le_top] + | succ k ih => + simp only [LieModule.lowerCentralSeries_succ] exact le_trans (LieIdeal.map_bracket_le f) (LieSubmodule.mono_lie le_top ih) theorem LieIdeal.lowerCentralSeries_map_eq (k : ℕ) {f : L →ₗ⁅R⁆ L'} (h : Function.Surjective f) : @@ -671,9 +707,9 @@ theorem LieIdeal.lowerCentralSeries_map_eq (k : ℕ) {f : L →ₗ⁅R⁆ L'} (h have h' : (⊤ : LieIdeal R L).map f = ⊤ := by rw [← f.idealRange_eq_map] exact f.idealRange_eq_top_of_surjective h - induction' k with k ih - · simp only [LieModule.lowerCentralSeries_zero]; exact h' - · simp only [LieModule.lowerCentralSeries_succ, LieIdeal.map_bracket_eq f h, ih, h'] + induction k with + | zero => simp only [LieModule.lowerCentralSeries_zero]; exact h' + | succ k ih => simp only [LieModule.lowerCentralSeries_succ, LieIdeal.map_bracket_eq f h, ih, h'] theorem Function.Injective.lieAlgebra_isNilpotent [h₁ : IsNilpotent R L'] {f : L →ₗ⁅R⁆ L'} (h₂ : Function.Injective f) : IsNilpotent R L := @@ -750,9 +786,10 @@ theorem lcs_top : (⊤ : LieIdeal R L).lcs M k = lowerCentralSeries R L M k := -- Porting note: added `LieSubmodule.toSubmodule` in the statement theorem coe_lcs_eq [LieModule R L M] : LieSubmodule.toSubmodule (I.lcs M k) = lowerCentralSeries R I M k := by - induction' k with k ih - · simp - · simp_rw [lowerCentralSeries_succ, lcs_succ, LieSubmodule.lieIdeal_oper_eq_linear_span', ← + induction k with + | zero => simp + | succ k ih => + simp_rw [lowerCentralSeries_succ, lcs_succ, LieSubmodule.lieIdeal_oper_eq_linear_span', ← (I.lcs M k).mem_coeSubmodule, ih, LieSubmodule.mem_coeSubmodule, LieSubmodule.mem_top, true_and, (I : LieSubalgebra R L).coe_bracket_of_module] congr @@ -804,9 +841,9 @@ variable (R A L M : Type*) [CommRing R] [LieRing L] [LieAlgebra R L] lemma LieSubmodule.lowerCentralSeries_tensor_eq_baseChange (k : ℕ) : lowerCentralSeries A (A ⊗[R] L) (A ⊗[R] M) k = (lowerCentralSeries R L M k).baseChange A := by - induction' k with k ih - · simp - simp only [lowerCentralSeries_succ, ih, ← baseChange_top, lie_baseChange] + induction k with + | zero => simp + | succ k ih => simp only [lowerCentralSeries_succ, ih, ← baseChange_top, lie_baseChange] instance LieModule.instIsNilpotentTensor [IsNilpotent R L M] : IsNilpotent A (A ⊗[R] L) (A ⊗[R] M) := by diff --git a/Mathlib/Algebra/Lie/OfAssociative.lean b/Mathlib/Algebra/Lie/OfAssociative.lean index 363b9a3da015a..fbf65f369ddf6 100644 --- a/Mathlib/Algebra/Lie/OfAssociative.lean +++ b/Mathlib/Algebra/Lie/OfAssociative.lean @@ -300,7 +300,7 @@ 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 [LinearMap.restrict_apply] + ext; simp only [LinearMap.restrict_apply, toEnd_apply_apply]; 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/Semisimple/Basic.lean b/Mathlib/Algebra/Lie/Semisimple/Basic.lean index 4768863c8499a..7768d66b3c772 100644 --- a/Mathlib/Algebra/Lie/Semisimple/Basic.lean +++ b/Mathlib/Algebra/Lie/Semisimple/Basic.lean @@ -11,7 +11,7 @@ import Mathlib.Order.BooleanGenerators The famous Cartan-Dynkin-Killing classification of semisimple Lie algebras renders them one of the most important classes of Lie algebras. In this file we prove basic results -abot simple and semisimple Lie algebras. +about simple and semisimple Lie algebras. ## Main declarations @@ -276,6 +276,7 @@ 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 @@ -301,7 +302,15 @@ theorem subsingleton_of_hasTrivialRadical_lie_abelian [HasTrivialRadical R L] [h theorem abelian_radical_of_hasTrivialRadical [HasTrivialRadical R L] : IsLieAbelian (radical R L) := by - rw [HasTrivialRadical.radical_eq_bot]; infer_instance + #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 to be reductive. diff --git a/Mathlib/Algebra/Lie/Solvable.lean b/Mathlib/Algebra/Lie/Solvable.lean index 987fd1ca9889f..6e125fbedd552 100644 --- a/Mathlib/Algebra/Lie/Solvable.lean +++ b/Mathlib/Algebra/Lie/Solvable.lean @@ -131,11 +131,12 @@ variable {R L} theorem derivedSeries_eq_derivedSeriesOfIdeal_comap (k : ℕ) : derivedSeries R I k = (derivedSeriesOfIdeal R L k I).comap I.incl := by - induction' k with k ih - · simp only [derivedSeries_def, comap_incl_self, derivedSeriesOfIdeal_zero] - · simp only [derivedSeries_def, derivedSeriesOfIdeal_succ] at ih ⊢; rw [ih] - exact comap_bracket_incl_of_le I - (derivedSeriesOfIdeal_le_self I k) (derivedSeriesOfIdeal_le_self I k) + induction k with + | zero => simp only [derivedSeries_def, comap_incl_self, derivedSeriesOfIdeal_zero] + | succ k ih => + simp only [derivedSeries_def, derivedSeriesOfIdeal_succ] at ih ⊢; rw [ih] + exact comap_bracket_incl_of_le I (derivedSeriesOfIdeal_le_self I k) + (derivedSeriesOfIdeal_le_self I k) theorem derivedSeries_eq_derivedSeriesOfIdeal_map (k : ℕ) : (derivedSeries R I k).map I.incl = derivedSeriesOfIdeal R L k I := by @@ -156,18 +157,20 @@ theorem derivedSeries_add_eq_bot {k l : ℕ} {I J : LieIdeal R L} (hI : derivedS _ ≤ ⊥ := by rw [hI, hJ]; simp theorem derivedSeries_map_le (k : ℕ) : (derivedSeries R L' k).map f ≤ derivedSeries R L k := by - induction' k with k ih - · simp only [derivedSeries_def, derivedSeriesOfIdeal_zero, le_top] - · simp only [derivedSeries_def, derivedSeriesOfIdeal_succ] at ih ⊢ + induction k with + | zero => simp only [derivedSeries_def, derivedSeriesOfIdeal_zero, le_top] + | succ k ih => + simp only [derivedSeries_def, derivedSeriesOfIdeal_succ] at ih ⊢ exact le_trans (map_bracket_le f) (LieSubmodule.mono_lie ih ih) theorem derivedSeries_map_eq (k : ℕ) (h : Function.Surjective f) : (derivedSeries R L' k).map f = derivedSeries R L k := by - induction' k with k ih - · change (⊤ : LieIdeal R L').map f = ⊤ + induction k with + | zero => + change (⊤ : LieIdeal R L').map f = ⊤ rw [← f.idealRange_eq_map] exact f.idealRange_eq_top_of_surjective h - · simp only [derivedSeries_def, map_bracket_eq f h, ih, derivedSeriesOfIdeal_succ] + | succ k ih => simp only [derivedSeries_def, map_bracket_eq f h, ih, derivedSeriesOfIdeal_succ] theorem derivedSeries_succ_eq_top_iff (n : ℕ) : derivedSeries R L (n + 1) = ⊤ ↔ derivedSeries R L 1 = ⊤ := by @@ -195,11 +198,11 @@ namespace LieAlgebra class IsSolvable : Prop where solvable : ∃ k, derivedSeries R L k = ⊥ -instance isSolvableBot : IsSolvable R (↥(⊥ : LieIdeal R L)) := +instance isSolvableBot : IsSolvable R ((⊥ : LieIdeal R L)) := ⟨⟨0, Subsingleton.elim _ ⊥⟩⟩ instance isSolvableAdd {I J : LieIdeal R L} [hI : IsSolvable R I] [hJ : IsSolvable R J] : - IsSolvable R (↥(I + J)) := by + IsSolvable R (I + J) := by obtain ⟨k, hk⟩ := id hI; obtain ⟨l, hl⟩ := id hJ exact ⟨⟨k + l, LieIdeal.derivedSeries_add_eq_bot hk hl⟩⟩ @@ -263,7 +266,7 @@ 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.wellFounded_of_noetherian R L L + have hwf := (LieSubmodule.wellFoundedGT_of_noetherian R L L).wf rw [← CompleteLattice.isSupClosedCompact_iff_wellFounded] at hwf refine hwf { I : LieIdeal R L | IsSolvable R I } ⟨⊥, ?_⟩ fun I hI J hJ => ?_ · exact LieAlgebra.isSolvableBot R L @@ -284,7 +287,12 @@ instance [IsSolvable R L] : IsSolvable R (⊤ : LieSubalgebra R L) := by @[simp] lemma radical_eq_top_of_isSolvable [IsSolvable R L] : radical R L = ⊤ := by - rw [eq_top_iff]; exact le_sSup <| inferInstanceAs (IsSolvable R (⊤ : LieIdeal R L)) + #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 /-- Given a solvable Lie ideal `I` with derived series `I = D₀ ≥ D₁ ≥ ⋯ ≥ Dₖ = ⊥`, this is the natural number `k` (the number of inclusions). @@ -334,7 +342,7 @@ theorem abelian_derivedAbelianOfIdeal (I : LieIdeal R L) : IsLieAbelian (derivedAbelianOfIdeal I) := by dsimp only [derivedAbelianOfIdeal] cases' h : derivedLengthOfIdeal R L I with k - · infer_instance + · dsimp; infer_instance · rw [derivedSeries_of_derivedLength_succ] at h; exact h.1 theorem derivedLength_zero (I : LieIdeal R L) [hI : IsSolvable R I] : diff --git a/Mathlib/Algebra/Lie/Subalgebra.lean b/Mathlib/Algebra/Lie/Subalgebra.lean index f5b3887358c7b..37990704ca9da 100644 --- a/Mathlib/Algebra/Lie/Subalgebra.lean +++ b/Mathlib/Algebra/Lie/Subalgebra.lean @@ -220,7 +220,8 @@ variable [Module R M] /-- Given a Lie algebra `L` containing a Lie subalgebra `L' ⊆ L`, together with a Lie module `M` of `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 simp only [coe_bracket_of_module, smul_lie, Submodule.coe_smul_of_tower] + smul_lie t x m := by + rw [coe_bracket_of_module]; erw [smul_lie]; simp only [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 @@ -500,21 +501,16 @@ theorem eq_bot_iff : K = ⊥ ↔ ∀ x : L, x ∈ K → x = 0 := by instance subsingleton_of_bot : Subsingleton (LieSubalgebra R (⊥ : LieSubalgebra R L)) := by apply subsingleton_of_bot_eq_top ext ⟨x, hx⟩; change x ∈ ⊥ at hx; rw [LieSubalgebra.mem_bot] at hx; subst hx - simp only [true_iff_iff, eq_self_iff_true, Submodule.mk_eq_zero, mem_bot, mem_top] + simp only [mem_bot, mem_top, iff_true] + rfl theorem subsingleton_bot : Subsingleton (⊥ : LieSubalgebra R L) := show Subsingleton ((⊥ : LieSubalgebra R L) : Set L) by simp variable (R L) -theorem wellFounded_of_noetherian [IsNoetherian R L] : - WellFounded ((· > ·) : LieSubalgebra R L → LieSubalgebra R L → Prop) := - let f : - ((· > ·) : LieSubalgebra R L → LieSubalgebra R L → Prop) →r - ((· > ·) : Submodule R L → Submodule R L → Prop) := - { toFun := (↑) - map_rel' := @fun _ _ h ↦ h } - RelHomClass.wellFounded f (isNoetherian_iff_wellFounded.mp inferInstance) +instance wellFoundedGT_of_noetherian [IsNoetherian R L] : WellFoundedGT (LieSubalgebra R L) := + RelHomClass.isWellFounded (⟨toSubmodule, @fun _ _ h ↦ h⟩ : _ →r (· > ·)) variable {R L K K' f} @@ -561,7 +557,7 @@ theorem coe_ofLe : (ofLe h : Submodule R K') = LinearMap.range (Submodule.inclus rfl /-- Given nested Lie subalgebras `K ⊆ K'`, there is a natural equivalence from `K` to its image in -`K'`. -/ +`K'`. -/ noncomputable def equivOfLe : K ≃ₗ⁅R⁆ ofLe h := (inclusion h).equivRangeOfInjective (inclusion_injective h) diff --git a/Mathlib/Algebra/Lie/Submodule.lean b/Mathlib/Algebra/Lie/Submodule.lean index 08978bd95d8ba..9a496ce1a3f1e 100644 --- a/Mathlib/Algebra/Lie/Submodule.lean +++ b/Mathlib/Algebra/Lie/Submodule.lean @@ -79,8 +79,6 @@ instance instCanLiftSubmoduleLieSubmodule : CanLift (Submodule R M) (LieSubmodul (fun N ↦ ∀ {x : L} {m : M}, m ∈ N → ⁅x, m⁆ ∈ N) where prf N hN := ⟨⟨N, hN⟩, rfl⟩ --- Syntactic tautology - @[norm_cast] theorem coe_toSubmodule : ((N : Submodule R M) : Set M) = N := rfl @@ -190,7 +188,9 @@ theorem coe_smul (t : R) (m : N) : (↑(t • m) : M) = t • (m : M) := rfl @[simp, norm_cast] -theorem coe_bracket (x : L) (m : N) : (↑⁅x, m⁆ : M) = ⁅x, ↑m⁆ := +theorem coe_bracket (x : L) (m : N) : + letI : Bracket L N := LieRingModule.toBracket + (↑⁅x, m⁆ : M) = ⁅x, ↑m⁆ := rfl variable [LieAlgebra R L] [LieModule R L M] @@ -248,7 +248,9 @@ 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) : ⁅x, m⁆ = ⁅(↑x : L), m⁆ := + (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 /-- Transfer the `LieModule` instance from the coercion `LieIdeal → LieSubalgebra`. -/ @@ -436,10 +438,13 @@ instance : SupSet (LieSubmodule R L M) where obtain ⟨s, hs, hsm⟩ := Submodule.mem_sSup_iff_exists_finset.mp hm clear hm classical - induction' s using Finset.induction_on with q t hqt ih generalizing m - · replace hsm : m = 0 := by simpa using hsm + induction s using Finset.induction_on generalizing m with + | empty => + replace hsm : m = 0 := by simpa using hsm simp [hsm] - · rw [Finset.iSup_insert] at hsm + | insert hqt ih => + rename_i q t + rw [Finset.iSup_insert] at hsm obtain ⟨m', hm', u, hu, rfl⟩ := Submodule.mem_sup.mp hsm rw [lie_add] refine add_mem ?_ (ih (Subset.trans (by simp) hs) hu) @@ -560,18 +565,14 @@ variable (R L M) inj' := coeSubmodule_injective map_rel_iff' := Iff.rfl } -theorem wellFounded_of_noetherian [IsNoetherian R M] : - WellFounded ((· > ·) : LieSubmodule R L M → LieSubmodule R L M → Prop) := - RelHomClass.wellFounded (toSubmodule_orderEmbedding R L M).dual.ltEmbedding <| - isNoetherian_iff_wellFounded.mp inferInstance +instance wellFoundedGT_of_noetherian [IsNoetherian R M] : WellFoundedGT (LieSubmodule R L M) := + RelHomClass.isWellFounded (toSubmodule_orderEmbedding R L M).dual.ltEmbedding -theorem wellFounded_of_isArtinian [IsArtinian R M] : - WellFounded ((· < ·) : LieSubmodule R L M → LieSubmodule R L M → Prop) := - RelHomClass.wellFounded (toSubmodule_orderEmbedding R L M).ltEmbedding <| - IsArtinian.wellFounded_submodule_lt R M +theorem wellFoundedLT_of_isArtinian [IsArtinian R M] : WellFoundedLT (LieSubmodule R L M) := + RelHomClass.isWellFounded (toSubmodule_orderEmbedding R L M).ltEmbedding instance [IsArtinian R M] : IsAtomic (LieSubmodule R L M) := - isAtomic_of_orderBot_wellFounded_lt <| wellFounded_of_isArtinian R L M + isAtomic_of_orderBot_wellFounded_lt <| (wellFoundedLT_of_isArtinian R L M).wf @[simp] theorem subsingleton_iff : Subsingleton (LieSubmodule R L M) ↔ Subsingleton M := @@ -1292,7 +1293,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 + map_lie' {x m} := by ext; simp; rfl @[simp] lemma codRestrict_apply (P : LieSubmodule R L N) (f : M →ₗ⁅R,L⁆ N) (h : ∀ m, f m ∈ P) (m : M) : diff --git a/Mathlib/Algebra/Lie/TensorProduct.lean b/Mathlib/Algebra/Lie/TensorProduct.lean index 9d5d16473476a..c44b1b7b2474c 100644 --- a/Mathlib/Algebra/Lie/TensorProduct.lean +++ b/Mathlib/Algebra/Lie/TensorProduct.lean @@ -195,7 +195,7 @@ applying the action of `L` on `M`, we obtain morphism of Lie modules `f : I ⊗ This lemma states that `⁅I, N⁆ = range f`. -/ theorem lieIdeal_oper_eq_tensor_map_range : - ⁅I, N⁆ = ((toModuleHom R L M).comp (mapIncl I N : (↥I) ⊗[R] (↥N) →ₗ⁅R,L⁆ L ⊗[R] M)).range := by + ⁅I, N⁆ = ((toModuleHom R L M).comp (mapIncl I N : I ⊗[R] N →ₗ⁅R,L⁆ L ⊗[R] M)).range := by rw [← coe_toSubmodule_eq_iff, lieIdeal_oper_eq_linear_span, LieModuleHom.coeSubmodule_range, LieModuleHom.coe_linearMap_comp, LinearMap.range_comp, mapIncl_def, coe_linearMap_map, TensorProduct.map_range_eq_span_tmul, Submodule.map_span] diff --git a/Mathlib/Algebra/Lie/TraceForm.lean b/Mathlib/Algebra/Lie/TraceForm.lean index 0837cc5f32d0f..06be6aac63a94 100644 --- a/Mathlib/Algebra/Lie/TraceForm.lean +++ b/Mathlib/Algebra/Lie/TraceForm.lean @@ -127,10 +127,12 @@ lemma traceForm_genWeightSpace_eq [Module.Free R M] lemma traceForm_eq_zero_if_mem_lcs_of_mem_ucs {x y : L} (k : ℕ) (hx : x ∈ (⊤ : LieIdeal R L).lcs L k) (hy : y ∈ (⊥ : LieIdeal R L).ucs k) : traceForm R L M x y = 0 := by - induction' k with k ih generalizing x y - · replace hy : y = 0 := by simpa using hy + induction k generalizing x y with + | zero => + replace hy : y = 0 := by simpa using hy simp [hy] - · rw [LieSubmodule.ucs_succ, LieSubmodule.mem_normalizer] at hy + | succ k ih => + rw [LieSubmodule.ucs_succ, LieSubmodule.mem_normalizer] at hy simp_rw [LieIdeal.lcs_succ, ← LieSubmodule.mem_coeSubmodule, LieSubmodule.lieIdeal_oper_eq_linear_span', LieSubmodule.mem_top, true_and] at hx refine Submodule.span_induction hx ?_ ?_ (fun z w hz hw ↦ ?_) (fun t z hz ↦ ?_) @@ -322,6 +324,12 @@ lemma traceForm_eq_zero_of_isTrivial [LieModule.IsTrivial I N] : simp [this, N.trace_eq_trace_restrict_of_le_idealizer I h x hy] ext 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 diff --git a/Mathlib/Algebra/Lie/UniversalEnveloping.lean b/Mathlib/Algebra/Lie/UniversalEnveloping.lean index 2d6a8ff9c4a7d..7f8985b6da9ee 100644 --- a/Mathlib/Algebra/Lie/UniversalEnveloping.lean +++ b/Mathlib/Algebra/Lie/UniversalEnveloping.lean @@ -96,7 +96,7 @@ def lift : (L →ₗ⁅R⁆ A) ≃ (UniversalEnvelopingAlgebra R L →ₐ[R] A) toFun f := RingQuot.liftAlgHom R ⟨TensorAlgebra.lift R (f : L →ₗ[R] A), by - intro a b h; induction' h with x y + intro a b h; induction h simp only [LieRing.of_associative_ring_bracket, map_add, TensorAlgebra.lift_ι_apply, LieHom.coe_toLinearMap, LieHom.map_lie, map_mul, sub_add_cancel]⟩ invFun F := (F : UniversalEnvelopingAlgebra R L →ₗ⁅R⁆ A).comp (ι R) diff --git a/Mathlib/Algebra/Lie/Weights/Basic.lean b/Mathlib/Algebra/Lie/Weights/Basic.lean index 24ac8b5a7f5c9..5652899b49468 100644 --- a/Mathlib/Algebra/Lie/Weights/Basic.lean +++ b/Mathlib/Algebra/Lie/Weights/Basic.lean @@ -50,8 +50,7 @@ variable {K R L M : Type*} [CommRing R] [LieRing L] [LieAlgebra R L] namespace LieModule -open Set Function LieAlgebra TensorProduct TensorProduct.LieModule -open scoped TensorProduct +open Set Function TensorProduct LieModule section notation_genWeightSpaceOf @@ -220,6 +219,13 @@ 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] @@ -408,10 +414,11 @@ lemma mem_posFittingCompOf (x : L) (m : M) : obtain ⟨n, rfl⟩ := (mem_posFittingCompOf R x m).mp hm k exact this n k intro m l - induction' l with l ih - · simp - simp only [lowerCentralSeries_succ, pow_succ', LinearMap.mul_apply] - exact LieSubmodule.lie_mem_lie (LieSubmodule.mem_top x) ih + induction l with + | zero => simp + | succ l ih => + simp only [lowerCentralSeries_succ, pow_succ', LinearMap.mul_apply] + exact LieSubmodule.lie_mem_lie (LieSubmodule.mem_top x) ih @[simp] lemma posFittingCompOf_eq_bot_of_isNilpotent [IsNilpotent R L M] (x : L) : @@ -583,7 +590,12 @@ 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] - infer_instance + #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 · set M₀ₓ := genWeightSpaceOf M (0 : R) x set M₁ₓ := posFittingCompOf R M x set M₀ₓ₀ := genWeightSpace M₀ₓ (0 : L → R) @@ -613,7 +625,7 @@ lemma isCompl_genWeightSpace_zero_posFittingComp : let e := LieModuleEquiv.ofTop R L M rw [← map_genWeightSpace_eq e, ← map_posFittingComp_eq e] exact (LieSubmodule.orderIsoMapComap e).isCompl_iff.mp this - refine (LieSubmodule.wellFounded_of_isArtinian R L M).induction (C := P) _ fun N hN ↦ ?_ + refine (LieSubmodule.wellFoundedLT_of_isArtinian R L M).induction (C := P) _ fun N hN ↦ ?_ refine isCompl_genWeightSpace_zero_posFittingComp_aux R L N fun N' hN' ↦ ?_ suffices IsCompl (genWeightSpace (N'.map N.incl) 0) (posFittingComp R L (N'.map N.incl)) by let e := LieSubmodule.equivMapOfInjective N' N.injective_incl @@ -651,8 +663,10 @@ lemma independent_genWeightSpace [NoZeroSMulDivisors R M] : simpa only [CompleteLattice.independent_iff_supIndep_of_injOn (injOn_genWeightSpace R L M), Finset.supIndep_iff_disjoint_erase] using fun s χ _ ↦ this _ _ (s.not_mem_erase χ) intro χ₁ s - induction' s using Finset.induction_on with χ₂ s _ ih - · simp + induction s using Finset.induction_on with + | empty => simp + | insert _n ih => + rename_i χ₂ s intro hχ₁₂ obtain ⟨hχ₁₂ : χ₁ ≠ χ₂, hχ₁ : χ₁ ∉ s⟩ := by rwa [Finset.mem_insert, not_or] at hχ₁₂ specialize ih hχ₁ @@ -698,12 +712,12 @@ 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 - (LieSubmodule.wellFounded_of_noetherian R L M) (independent_genWeightSpaceOf R L M x) + IsWellFounded.wf (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 - (LieSubmodule.wellFounded_of_noetherian R L M) (independent_genWeightSpace R L M) + IsWellFounded.wf (independent_genWeightSpace R L M) instance Weight.instFinite [NoZeroSMulDivisors R M] [IsNoetherian R M] : Finite (Weight R L M) := by @@ -768,7 +782,8 @@ 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 - induction' h_dim : finrank K M using Nat.strong_induction_on with n ih generalizing M + 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' diff --git a/Mathlib/Algebra/Lie/Weights/Cartan.lean b/Mathlib/Algebra/Lie/Weights/Cartan.lean index 6dbc65cb2e75f..152536e842483 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 [LieSubmodule.coe_add, lie_add]; rfl + map_add' := fun m n => by simp only [Submodule.coe_add, lie_add, AddMemClass.mk_add_mk] map_smul' := fun t m => by dsimp only conv_lhs => @@ -97,8 +97,8 @@ def rootSpaceWeightSpaceProductAux {χ₁ χ₂ χ₃ : H → R} (hχ : χ₁ + rfl } map_add' x y := by ext m - simp only [AddSubmonoid.coe_add, Submodule.coe_toAddSubmonoid, add_lie, LinearMap.coe_mk, - AddHom.coe_mk, LinearMap.add_apply, AddSubmonoid.mk_add_mk] + simp only [Submodule.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] ext m @@ -115,9 +115,10 @@ def rootSpaceWeightSpaceProduct (χ₁ χ₂ χ₃ : H → R) (hχ : χ₁ + χ { toLinearMap := rootSpaceWeightSpaceProductAux R L H M hχ map_lie' := fun {x y} => by ext m - simp only [rootSpaceWeightSpaceProductAux, LieSubmodule.coe_bracket, - LieSubalgebra.coe_bracket_of_module, lie_lie, LinearMap.coe_mk, AddHom.coe_mk, - Subtype.coe_mk, LieHom.lie_apply, LieSubmodule.coe_sub] } + simp only [rootSpaceWeightSpaceProductAux] + dsimp + repeat rw [LieSubmodule.coe_bracket] + simp only [LieSubalgebra.coe_bracket_of_module, lie_lie] } @[simp] theorem coe_rootSpaceWeightSpaceProduct_tmul (χ₁ χ₂ χ₃ : H → R) (hχ : χ₁ + χ₂ = χ₃) @@ -293,7 +294,8 @@ lemma mem_corootSpace' {x : H} : 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⟩⟩ - convert (rootSpaceProduct R L H α (-α) 0 (add_neg_cancel α) (⟨y, hy⟩ ⊗ₜ[R] ⟨z, hz⟩)).property + convert + (rootSpaceProduct R L H α (-α) 0 (add_neg_cancel α) (⟨y, hy⟩ ⊗ₜ[R] ⟨z, hz⟩)).property using 0 simp [hyz] end LieAlgebra diff --git a/Mathlib/Algebra/Lie/Weights/Chain.lean b/Mathlib/Algebra/Lie/Weights/Chain.lean index e8a85aaf3e5ea..4207a1056e76d 100644 --- a/Mathlib/Algebra/Lie/Weights/Chain.lean +++ b/Mathlib/Algebra/Lie/Weights/Chain.lean @@ -127,8 +127,9 @@ lemma lie_mem_genWeightSpaceChain_of_genWeightSpace_eq_bot_right [LieAlgebra.IsN {y : M} (hy : y ∈ genWeightSpaceChain M α χ p q) : ⁅x, y⁆ ∈ genWeightSpaceChain M α χ p q := by rw [genWeightSpaceChain, iSup_subtype'] at hy - induction' hy using LieSubmodule.iSup_induction' with k z hz z₁ z₂ _ _ hz₁ hz₂ - · obtain ⟨k, hk⟩ := k + induction hy using LieSubmodule.iSup_induction' with + | hN k z hz => + obtain ⟨k, hk⟩ := k suffices genWeightSpace M ((k + 1) • α + χ) ≤ genWeightSpaceChain M α χ p q by apply this simpa using (rootSpaceWeightSpaceProduct R L H M α (k • α + χ) ((k + 1) • α + χ) @@ -137,9 +138,8 @@ lemma lie_mem_genWeightSpaceChain_of_genWeightSpace_eq_bot_right [LieAlgebra.IsN rcases eq_or_ne (k + 1) q with rfl | hk'; · simp only [hq, bot_le] replace hk' : k + 1 ∈ Ioo p q := ⟨by linarith [hk.1], lt_of_le_of_ne hk.2 hk'⟩ exact le_biSup (fun k ↦ genWeightSpace M (k • α + χ)) hk' - · simp - · rw [lie_add] - exact add_mem hz₁ hz₂ + | h0 => simp + | hadd _ _ _ _ hz₁ hz₂ => rw [lie_add]; exact add_mem hz₁ hz₂ lemma lie_mem_genWeightSpaceChain_of_genWeightSpace_eq_bot_left [LieAlgebra.IsNilpotent R H] (hp : genWeightSpace M (p • α + χ) = ⊥) @@ -173,7 +173,11 @@ lemma trace_toEnd_genWeightSpaceChain_eq_zero lie_mem_genWeightSpaceChain_of_genWeightSpace_eq_bot_left M α χ p q hp hz hm⟩ map_add' := fun _ _ ↦ by simp map_smul' := fun t m ↦ by simp } - have hfg : toEnd R H _ u = ⁅f, g⁆ := by ext; simp [f, g, ← hyz] + have hfg : toEnd R H _ u = ⁅f, g⁆ := by + ext + rw [toEnd_apply_apply, LieSubmodule.coe_bracket, LieSubalgebra.coe_bracket_of_module, ← hyz] + simp only [lie_lie, LieHom.lie_apply, LinearMap.coe_mk, AddHom.coe_mk, Module.End.lie_apply, + AddSubgroupClass.coe_sub, f, g] simp [hfg] · simp · simp_all @@ -210,6 +214,7 @@ lemma exists_forall_mem_corootSpace_smul_add_eq_zero 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₃] + dsimp [N] simp_rw [LieSubmodule.toEnd_restrict_eq_toEnd, trace_toEnd_genWeightSpace, Pi.add_apply, Pi.smul_apply, smul_add, ← smul_assoc, Finset.sum_add_distrib, ← Finset.sum_smul, natCast_zsmul] diff --git a/Mathlib/Algebra/Lie/Weights/Killing.lean b/Mathlib/Algebra/Lie/Weights/Killing.lean index 03e0421bfd2dc..30db9a4835dcf 100644 --- a/Mathlib/Algebra/Lie/Weights/Killing.lean +++ b/Mathlib/Algebra/Lie/Weights/Killing.lean @@ -146,7 +146,9 @@ Over a perfect field a much stronger result is true, see `LieAlgebra.IsKilling.isSemisimple_ad_of_mem_isCartanSubalgebra`. -/ lemma eq_zero_of_isNilpotent_ad_of_mem_isCartanSubalgebra {x : L} (hx : x ∈ H) (hx' : _root_.IsNilpotent (ad K L x)) : x = 0 := by - suffices ⟨x, hx⟩ ∈ LinearMap.ker (traceForm K H L) by simpa using this + suffices ⟨x, hx⟩ ∈ LinearMap.ker (traceForm K H L) by + simp at this + exact (AddSubmonoid.mk_eq_zero H.toAddSubmonoid).mp this simp only [LinearMap.mem_ker] ext y have comm : Commute (toEnd K H L ⟨x, hx⟩) (toEnd K H L y) := by @@ -340,7 +342,8 @@ lemma coe_corootSpace_eq_span_singleton' (α : Weight K H L) : rw [Submodule.mem_span_singleton] at this ⊢ obtain ⟨t, rfl⟩ := this use t - simp [Subtype.ext_iff] + simp only [Subtype.ext_iff] + rw [Submodule.coe_smul_of_tower] · simp only [Submodule.span_singleton_le_iff_mem, LieSubmodule.mem_coeSubmodule] exact cartanEquivDual_symm_apply_mem_corootSpace α @@ -484,7 +487,9 @@ lemma exists_isSl2Triple_of_weight_isNonZero {α : Weight K H L} (hα : α.IsNon have hef := lie_eq_killingForm_smul_of_mem_rootSpace_of_mem_rootSpace_neg heα hfα let h : H := ⟨⁅e, f'⁆, hef ▸ Submodule.smul_mem _ _ (Submodule.coe_mem _)⟩ have hh : α h ≠ 0 := by - have : h = killingForm K L e f' • (cartanEquivDual H).symm α := by simp [Subtype.ext_iff, hef] + have : h = killingForm K L e f' • (cartanEquivDual H).symm α := by + simp only [Subtype.ext_iff, hef] + rw [Submodule.coe_smul_of_tower] rw [this, map_smul, smul_eq_mul, ne_eq, mul_eq_zero, not_or] exact ⟨hf, root_apply_cartanEquivDual_symm_ne_zero hα⟩ let f := (2 * (α h)⁻¹) • f' @@ -517,7 +522,8 @@ lemma _root_.IsSl2Triple.h_eq_coroot {α : Weight K H L} (hα : α.IsNonZero) rwa [this, one_smul] at hs set α' := (cartanEquivDual H).symm α with hα' have h_eq : h = killingForm K L e f • α' := by - simp only [hα', Subtype.ext_iff, Submodule.coe_smul_of_tower, ← ht.lie_e_f, hef] + simp only [hα', Subtype.ext_iff, ← ht.lie_e_f, hef] + rw [Submodule.coe_smul_of_tower] use (2 • (α α')⁻¹) * (killingForm K L e f)⁻¹ have hef₀ : killingForm K L e f ≠ 0 := by have := ht.h_ne_zero diff --git a/Mathlib/Algebra/Lie/Weights/Linear.lean b/Mathlib/Algebra/Lie/Weights/Linear.lean index dc963d3db3a9c..a1acd2a519eaa 100644 --- a/Mathlib/Algebra/Lie/Weights/Linear.lean +++ b/Mathlib/Algebra/Lie/Weights/Linear.lean @@ -184,6 +184,7 @@ instance : LieRingModule L (shiftedGenWeightSpace R L M χ) where abel @[simp] lemma coe_lie_shiftedGenWeightSpace_apply (x : L) (m : shiftedGenWeightSpace R L M χ) : + letI : Bracket L (shiftedGenWeightSpace R L M χ) := LieRingModule.toBracket ⁅x, m⁆ = ⁅x, (m : M)⁆ - χ x • m := rfl @@ -191,13 +192,17 @@ instance : LieModule R L (shiftedGenWeightSpace R L M χ) where smul_lie t x m := by nontriviality shiftedGenWeightSpace R L M χ apply Subtype.ext - simp only [coe_lie_shiftedGenWeightSpace_apply, smul_lie, - LinearWeights.map_smul χ (aux R L M χ), smul_assoc t, SetLike.val_smul, smul_sub] + rw [coe_lie_shiftedGenWeightSpace_apply] + simp only [smul_lie, LinearWeights.map_smul χ (aux R L M χ), smul_assoc t, SetLike.val_smul] + rw [← smul_sub] + congr lie_smul t x m := by nontriviality shiftedGenWeightSpace R L M χ apply Subtype.ext - simp only [coe_lie_shiftedGenWeightSpace_apply, SetLike.val_smul, lie_smul, smul_sub, - smul_comm t] + rw [coe_lie_shiftedGenWeightSpace_apply] + simp only [SetLike.val_smul, lie_smul] + rw [smul_comm (χ x), ← smul_sub] + congr /-- Forgetting the action of `L`, the spaces `genWeightSpace M χ` and `shiftedGenWeightSpace R L M χ` are equivalent. -/ @@ -206,7 +211,14 @@ the spaces `genWeightSpace M χ` and `shiftedGenWeightSpace R L M χ` are equiva lemma toEnd_eq (x : L) : toEnd R L (shiftedGenWeightSpace R L M χ) x = (shift R L M χ).conj (toEnd R L (genWeightSpace M χ) x - χ x • LinearMap.id) := by - ext; simp [LinearEquiv.conj_apply] + ext + simp only [toEnd_apply_apply, map_sub, LinearEquiv.conj_apply, map_smul, LinearMap.comp_id, + LinearEquiv.comp_coe, LinearEquiv.symm_trans_self, LinearEquiv.refl_toLinearMap, + LinearMap.sub_apply, LinearMap.coe_comp, LinearEquiv.coe_coe, Function.comp_apply, + shift_symm_apply, shift_apply, LinearMap.smul_apply, LinearMap.id_coe, id_eq, + AddSubgroupClass.coe_sub, SetLike.val_smul] + rw [LieSubmodule.coe_bracket] + rfl /-- By Engel's theorem, if `M` is Noetherian, the shifted action `⁅x, m⁆ - χ x • m` makes the `χ`-weight space into a nilpotent Lie module. -/ @@ -215,6 +227,7 @@ instance [IsNoetherian R M] : IsNilpotent R L (shiftedGenWeightSpace R L M χ) : end shiftedGenWeightSpace +open shiftedGenWeightSpace in /-- Given a Lie module `M` of a Lie algebra `L` with coefficients in `R`, if a function `χ : L → R` has a simultaneous generalized eigenvector for the action of `L` then it has a simultaneous true eigenvector, provided `M` is Noetherian and has linear weights. -/ @@ -225,8 +238,10 @@ lemma exists_forall_lie_eq_smul [LinearWeights R L M] [IsNoetherian R M] (χ : W 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, - shiftedGenWeightSpace.coe_lie_shiftedGenWeightSpace_apply, - ZeroMemClass.coe_zero, sub_eq_zero] at hm₁ - exact ⟨m, by simpa using hm₂, hm₁⟩ + ZeroMemClass.coe_zero] at hm₁ + refine ⟨m, by simpa using hm₂, ?_⟩ + intro x + have := hm₁ x + rwa [coe_lie_shiftedGenWeightSpace_apply, sub_eq_zero] at this end LieModule diff --git a/Mathlib/Algebra/Module/Basic.lean b/Mathlib/Algebra/Module/Basic.lean index 91e832b7f7568..2e3fb20b33d35 100644 --- a/Mathlib/Algebra/Module/Basic.lean +++ b/Mathlib/Algebra/Module/Basic.lean @@ -3,11 +3,10 @@ Copyright (c) 2015 Nathaniel Thomas. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Nathaniel Thomas, Jeremy Avigad, Johannes Hölzl, Mario Carneiro -/ +import Mathlib.Algebra.Field.Basic import Mathlib.Algebra.Group.Action.Pi import Mathlib.Algebra.Group.Indicator import Mathlib.Algebra.Module.Defs -import Mathlib.Algebra.Field.Basic -import Mathlib.GroupTheory.GroupAction.Group /-! # Further basic results about modules. diff --git a/Mathlib/Algebra/Module/BigOperators.lean b/Mathlib/Algebra/Module/BigOperators.lean index 0799ce0c60156..6c34557954a88 100644 --- a/Mathlib/Algebra/Module/BigOperators.lean +++ b/Mathlib/Algebra/Module/BigOperators.lean @@ -3,9 +3,9 @@ Copyright (c) 2018 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes, Yury Kudryashov, Yaël Dillies -/ +import Mathlib.Algebra.BigOperators.GroupWithZero.Action import Mathlib.Algebra.Module.Defs import Mathlib.Data.Fintype.BigOperators -import Mathlib.GroupTheory.GroupAction.BigOperators /-! # Finite sums over modules over a ring diff --git a/Mathlib/Algebra/Module/Defs.lean b/Mathlib/Algebra/Module/Defs.lean index f509b6a113bc5..a80f140f53d26 100644 --- a/Mathlib/Algebra/Module/Defs.lean +++ b/Mathlib/Algebra/Module/Defs.lean @@ -95,11 +95,6 @@ variable (R) -- Porting note: this is the letter of the mathlib3 version, but not really the spirit theorem two_smul : (2 : R) • x = x + x := by rw [← one_add_one_eq_two, add_smul, one_smul] -set_option linter.deprecated false in -@[deprecated (since := "2022-12-31")] -theorem two_smul' : (2 : R) • x = (2 : ℕ) • x := by - rw [two_smul, two_nsmul] - @[simp] theorem invOf_two_smul_add_invOf_two_smul [Invertible (2 : R)] (x : M) : (⅟ 2 : R) • x + (⅟ 2 : R) • x = x := @@ -576,7 +571,7 @@ theorem NoZeroSMulDivisors.int_of_charZero NoZeroSMulDivisors ℤ M := ⟨fun {z x} h ↦ by simpa [← smul_one_smul R z x] using h⟩ -/-- Only a ring of characteristic zero can can have a non-trivial module without additive or +/-- Only a ring of characteristic zero can have a non-trivial module without additive or scalar torsion. -/ theorem CharZero.of_noZeroSMulDivisors [Nontrivial M] [NoZeroSMulDivisors ℤ M] : CharZero R := by refine ⟨fun {n m h} ↦ ?_⟩ diff --git a/Mathlib/Algebra/Module/Equiv/Basic.lean b/Mathlib/Algebra/Module/Equiv/Basic.lean index 1197686e29602..3d210451cac46 100644 --- a/Mathlib/Algebra/Module/Equiv/Basic.lean +++ b/Mathlib/Algebra/Module/Equiv/Basic.lean @@ -403,23 +403,23 @@ end Subsingleton section Uncurry -variable [Semiring R] [Semiring R₂] [Semiring R₃] -variable [AddCommMonoid M] [AddCommMonoid M₂] [AddCommMonoid M₃] -variable (V V₂ R) +variable [Semiring R] +variable [AddCommMonoid M] [Module R M] +variable (V V₂ R M) /-- Linear equivalence between a curried and uncurried function. Differs from `TensorProduct.curry`. -/ -protected def curry : (V × V₂ → R) ≃ₗ[R] V → V₂ → R := +protected def curry : (V × V₂ → M) ≃ₗ[R] V → V₂ → M := { Equiv.curry _ _ _ with map_add' := fun _ _ ↦ rfl map_smul' := fun _ _ ↦ rfl } @[simp] -theorem coe_curry : ⇑(LinearEquiv.curry R V V₂) = curry := +theorem coe_curry : ⇑(LinearEquiv.curry R M V V₂) = curry := rfl @[simp] -theorem coe_curry_symm : ⇑(LinearEquiv.curry R V V₂).symm = uncurry := +theorem coe_curry_symm : ⇑(LinearEquiv.curry R M V V₂).symm = uncurry := rfl end Uncurry diff --git a/Mathlib/Algebra/Module/Equiv/Defs.lean b/Mathlib/Algebra/Module/Equiv/Defs.lean index 1513cc839f617..9a5d7dcbdfd0d 100644 --- a/Mathlib/Algebra/Module/Equiv/Defs.lean +++ b/Mathlib/Algebra/Module/Equiv/Defs.lean @@ -449,9 +449,7 @@ theorem map_ne_zero_iff {x : M} : e x ≠ 0 ↔ x ≠ 0 := e.toAddEquiv.map_ne_zero_iff @[simp] -theorem symm_symm (e : M ≃ₛₗ[σ] M₂) : e.symm.symm = e := by - cases e - rfl +theorem symm_symm (e : M ≃ₛₗ[σ] M₂) : e.symm.symm = e := rfl theorem symm_bijective [Module R M] [Module S M₂] [RingHomInvPair σ' σ] [RingHomInvPair σ σ'] : Function.Bijective (symm : (M ≃ₛₗ[σ] M₂) → M₂ ≃ₛₗ[σ'] M) := @@ -462,7 +460,7 @@ theorem mk_coe' (f h₁ h₂ h₃ h₄) : (LinearEquiv.mk ⟨⟨f, h₁⟩, h₂⟩ (⇑e) h₃ h₄ : M₂ ≃ₛₗ[σ'] M) = e.symm := symm_bijective.injective <| ext fun _ ↦ rfl -/-- Auxilliary definition to avoid looping in `dsimp` with `LinearEquiv.symm_mk`. -/ +/-- Auxiliary definition to avoid looping in `dsimp` with `LinearEquiv.symm_mk`. -/ protected def symm_mk.aux (f h₁ h₂ h₃ h₄) := (⟨⟨⟨e, h₁⟩, h₂⟩, f, h₃, h₄⟩ : M ≃ₛₗ[σ] M₂).symm @[simp] diff --git a/Mathlib/Algebra/Module/FinitePresentation.lean b/Mathlib/Algebra/Module/FinitePresentation.lean index 0ea4c4bf7fa0c..024751ec3f4b5 100644 --- a/Mathlib/Algebra/Module/FinitePresentation.lean +++ b/Mathlib/Algebra/Module/FinitePresentation.lean @@ -48,6 +48,8 @@ For finitely presented algebras, see `Algebra.FinitePresentation` in file `Mathlib.RingTheory.FinitePresentation`. -/ +open Finsupp + section Semiring variable (R M) [Semiring R] [AddCommMonoid M] [Module R M] @@ -57,7 +59,7 @@ and the kernel of the presentation `Rˢ → M` is also finitely generated. -/ class Module.FinitePresentation : Prop where out : ∃ (s : Finset M), Submodule.span R (s : Set M) = ⊤ ∧ - (LinearMap.ker (Finsupp.total s M R Subtype.val)).FG + (LinearMap.ker (Finsupp.linearCombination R ((↑) : s → M))).FG instance (priority := 100) [h : Module.FinitePresentation R M] : Module.Finite R M := by obtain ⟨s, hs₁, _⟩ := h @@ -78,10 +80,10 @@ theorem Module.FinitePresentation.equiv_quotient [fp : Module.FinitePresentation Module.Free R L ∧ Module.Finite R L ∧ K.FG := by obtain ⟨ι, ⟨hι₁, hι₂⟩⟩ := fp use ι →₀ R, inferInstance, inferInstance - use LinearMap.ker (Finsupp.total { x // x ∈ ι } M R Subtype.val) + use LinearMap.ker (Finsupp.linearCombination R Subtype.val) refine ⟨(LinearMap.quotKerEquivOfSurjective _ ?_).symm, inferInstance, inferInstance, hι₂⟩ apply LinearMap.range_eq_top.mp - simpa only [Finsupp.range_total, Subtype.range_coe_subtype, Finset.setOf_mem] + simpa only [Finsupp.range_linearCombination, Subtype.range_coe_subtype, Finset.setOf_mem] -- Ideally this should be an instance but it makes mathlib much slower. lemma Module.finitePresentation_of_finite [IsNoetherianRing R] [h : Module.Finite R M] : @@ -119,12 +121,12 @@ lemma Module.finitePresentation_of_free_of_surjective [Module.Free R M] [Module. constructor · intro hx refine ⟨b.repr.symm (x.mapDomain σ), ?_, ?_⟩ - · simp [Finsupp.apply_total, hσ₂, hx] + · simp [Finsupp.apply_linearCombination, hσ₂, hx] · simp only [f, LinearMap.comp_apply, b.repr.apply_symm_apply, LinearEquiv.coe_toLinearMap, Finsupp.lmapDomain_apply] rw [← Finsupp.mapDomain_comp, hσ₁, Finsupp.mapDomain_id] · rintro ⟨y, hy, rfl⟩ - simp [f, hπ, ← Finsupp.apply_total, hy] + simp [f, hπ, ← Finsupp.apply_linearCombination, hy] -- Ideally this should be an instance but it makes mathlib much slower. variable (R M) in @@ -145,12 +147,12 @@ lemma Module.finitePresentation_of_surjective [h : Module.FinitePresentation R M classical obtain ⟨s, hs, hs'⟩ := h obtain ⟨t, ht⟩ := hl' - have H : Function.Surjective (Finsupp.total s M R Subtype.val) := - LinearMap.range_eq_top.mp (by rw [Finsupp.range_total, Subtype.range_val, ← hs]; rfl) - apply Module.finitePresentation_of_free_of_surjective (l ∘ₗ Finsupp.total s M R Subtype.val) + have H : Function.Surjective (Finsupp.linearCombination R ((↑) : s → M)) := + LinearMap.range_eq_top.mp (by rw [range_linearCombination, Subtype.range_val, ← hs]; rfl) + apply Module.finitePresentation_of_free_of_surjective (l ∘ₗ linearCombination R Subtype.val) (hl.comp H) choose σ hσ using (show _ from H) - have : Finsupp.total s M R Subtype.val '' (σ '' t) = t := by + have : Finsupp.linearCombination R Subtype.val '' (σ '' t) = t := by simp only [Set.image_image, hσ, Set.image_id'] rw [LinearMap.ker_comp, ← ht, ← this, ← Submodule.map_span, Submodule.comap_map_eq, ← Finset.coe_image] @@ -161,11 +163,11 @@ lemma Module.FinitePresentation.fg_ker [Module.Finite R M] (LinearMap.ker l).FG := by classical obtain ⟨s, hs, hs'⟩ := h - have H : Function.Surjective (Finsupp.total s N R Subtype.val) := - LinearMap.range_eq_top.mp (by rw [Finsupp.range_total, Subtype.range_val, ← hs]; rfl) - obtain ⟨f, hf⟩ : ∃ f : (s →₀ R) →ₗ[R] M, l ∘ₗ f = (Finsupp.total s N R Subtype.val) := by + have H : Function.Surjective (Finsupp.linearCombination R ((↑) : s → N)) := + LinearMap.range_eq_top.mp (by rw [range_linearCombination, Subtype.range_val, ← hs]; rfl) + obtain ⟨f, hf⟩ : ∃ f : (s →₀ R) →ₗ[R] M, l ∘ₗ f = (Finsupp.linearCombination R Subtype.val) := by choose f hf using show _ from hl - exact ⟨Finsupp.total s M R (fun i ↦ f i), by ext; simp [hf]⟩ + exact ⟨Finsupp.linearCombination R (fun i ↦ f i), by ext; simp [hf]⟩ have : (LinearMap.ker l).map (LinearMap.range f).mkQ = ⊤ := by rw [← top_le_iff] rintro x - @@ -192,9 +194,9 @@ lemma Module.finitePresentation_of_ker [Module.FinitePresentation R N] · rw [Submodule.map_top, LinearMap.range_eq_top.mpr hl]; exact Module.Finite.out · rw [top_inf_eq, ← Submodule.fg_top]; exact Module.Finite.out refine ⟨s, hs, ?_⟩ - let π := Finsupp.total s M R Subtype.val + let π := Finsupp.linearCombination R ((↑) : s → M) have H : Function.Surjective π := - LinearMap.range_eq_top.mp (by rw [Finsupp.range_total, Subtype.range_val, ← hs]; rfl) + LinearMap.range_eq_top.mp (by rw [range_linearCombination, Subtype.range_val, ← hs]; rfl) have inst : Module.Finite R (LinearMap.ker (l ∘ₗ π)) := by constructor rw [Submodule.fg_top]; exact Module.FinitePresentation.fg_ker _ (hl.comp H) @@ -227,23 +229,24 @@ lemma Module.FinitePresentation.exists_lift_of_isLocalizedModule [h : Module.FinitePresentation R M] (g : M →ₗ[R] N') : ∃ (h : M →ₗ[R] N) (s : S), f ∘ₗ h = s • g := by obtain ⟨σ, hσ, τ, hτ⟩ := h - let π := Finsupp.total σ M R Subtype.val + let π := Finsupp.linearCombination R ((↑) : σ → M) have hπ : Function.Surjective π := - LinearMap.range_eq_top.mp (by rw [Finsupp.range_total, Subtype.range_val, ← hσ]; rfl) + LinearMap.range_eq_top.mp (by rw [range_linearCombination, Subtype.range_val, ← hσ]; rfl) classical choose s hs using IsLocalizedModule.surj S f let i : σ → N := fun x ↦ (∏ j ∈ σ.erase x.1, (s (g j)).2) • (s (g x)).1 let s₀ := ∏ j ∈ σ, (s (g j)).2 - have hi : f ∘ₗ Finsupp.total σ N R i = (s₀ • g) ∘ₗ π := by + have hi : f ∘ₗ Finsupp.linearCombination R i = (s₀ • g) ∘ₗ π := by ext j - simp only [LinearMap.coe_comp, Function.comp_apply, Finsupp.lsingle_apply, Finsupp.total_single, - one_smul, LinearMap.map_smul_of_tower, ← hs, LinearMap.smul_apply, i, s₀, π] + simp only [LinearMap.coe_comp, Function.comp_apply, Finsupp.lsingle_apply, + linearCombination_single, one_smul, LinearMap.map_smul_of_tower, ← hs, LinearMap.smul_apply, + i, s₀, π] rw [← mul_smul, Finset.prod_erase_mul] exact j.prop - have : ∀ x : τ, ∃ s : S, s • (Finsupp.total σ N R i x) = 0 := by + have : ∀ x : τ, ∃ s : S, s • (Finsupp.linearCombination R i x) = 0 := by intros x - convert_to ∃ s : S, s • (Finsupp.total σ N R i x) = s • 0 + convert_to ∃ s : S, s • (Finsupp.linearCombination R i x) = s • 0 · simp only [smul_zero] apply IsLocalizedModule.exists_of_eq (S := S) (f := f) rw [← LinearMap.comp_apply, map_zero, hi, LinearMap.comp_apply] @@ -252,7 +255,7 @@ lemma Module.FinitePresentation.exists_lift_of_isLocalizedModule exact Submodule.subset_span x.prop choose s' hs' using this let s₁ := ∏ i : τ, s' i - have : LinearMap.ker π ≤ LinearMap.ker (s₁ • Finsupp.total σ N R i) := by + have : LinearMap.ker π ≤ LinearMap.ker (s₁ • Finsupp.linearCombination R i) := by rw [← hτ, Submodule.span_le] intro x hxσ simp only [s₁] diff --git a/Mathlib/Algebra/Module/Hom.lean b/Mathlib/Algebra/Module/Hom.lean index 2550ee8e60c98..19bee131fe2dd 100644 --- a/Mathlib/Algebra/Module/Hom.lean +++ b/Mathlib/Algebra/Module/Hom.lean @@ -120,7 +120,7 @@ instance applyModule [AddCommMonoid A] : Module (AddMonoid.End A) A where end AddMonoid.End -/-! ### Miscelaneous morphisms -/ +/-! ### Miscellaneous morphisms -/ namespace AddMonoidHom diff --git a/Mathlib/Algebra/Module/Injective.lean b/Mathlib/Algebra/Module/Injective.lean index 536a41a974e42..9462f04c45e08 100644 --- a/Mathlib/Algebra/Module/Injective.lean +++ b/Mathlib/Algebra/Module/Injective.lean @@ -249,7 +249,7 @@ variable (f) def ExtensionOfMaxAdjoin.ideal (y : N) : Ideal R := (extensionOfMax i f).domain.comap ((LinearMap.id : R →ₗ[R] R).smulRight y) -/-- A linear map `I ⟶ Q` by `x ↦ f' (x • y)` where `f'` is the maximal extension-/ +/-- A linear map `I ⟶ Q` by `x ↦ f' (x • y)` where `f'` is the maximal extension -/ def ExtensionOfMaxAdjoin.idealTo (y : N) : ExtensionOfMaxAdjoin.ideal i f y →ₗ[R] Q where toFun (z : { x // x ∈ ideal i f y }) := (extensionOfMax i f).toLinearPMap ⟨(↑z : R) • y, z.prop⟩ map_add' (z1 z2 : { x // x ∈ ideal i f y }) := by diff --git a/Mathlib/Algebra/Module/LinearMap/Defs.lean b/Mathlib/Algebra/Module/LinearMap/Defs.lean index 4d7974c2e677b..e442944e3cb7b 100644 --- a/Mathlib/Algebra/Module/LinearMap/Defs.lean +++ b/Mathlib/Algebra/Module/LinearMap/Defs.lean @@ -323,7 +323,7 @@ protected theorem congr_fun (h : f = g) (x : M) : f x = g x := @[simp] theorem mk_coe (f : M →ₛₗ[σ] M₃) (h) : (LinearMap.mk f h : M →ₛₗ[σ] M₃) = f := - ext fun _ ↦ rfl + rfl variable (fₗ gₗ f g) @@ -503,11 +503,11 @@ theorem coe_comp : (f.comp g : M₁ → M₃) = f ∘ g := @[simp] theorem comp_id : f.comp id = f := - LinearMap.ext fun _ ↦ rfl + rfl @[simp] theorem id_comp : id.comp f = f := - LinearMap.ext fun _ ↦ rfl + rfl theorem comp_assoc {R₄ M₄ : Type*} [Semiring R₄] [AddCommMonoid M₄] [Module R₄ M₄] @@ -881,7 +881,7 @@ def toAddMonoidHom' : (M →ₛₗ[σ₁₂] M₂) →+ M →+ M₂ where map_zero' := by ext; rfl map_add' := by intros; ext; rfl -/-- If `M` is the zero module, then the identity map of `M` is the zero map. -/ +/-- If `M` is the zero module, then the identity map of `M` is the zero map. -/ @[simp] theorem identityMapOfZeroModuleIsZero [Subsingleton M] : id (R := R₁) (M := M) = 0 := Subsingleton.eq_zero id diff --git a/Mathlib/Algebra/Module/LinearMap/End.lean b/Mathlib/Algebra/Module/LinearMap/End.lean index 20e40bb532f29..0c0b70a638554 100644 --- a/Mathlib/Algebra/Module/LinearMap/End.lean +++ b/Mathlib/Algebra/Module/LinearMap/End.lean @@ -138,9 +138,9 @@ theorem commute_pow_left_of_commute [Semiring R₂] [AddCommMonoid M₂] [Module R₂ M₂] {σ₁₂ : R →+* R₂} {f : M →ₛₗ[σ₁₂] M₂} {g : Module.End R M} {g₂ : Module.End R₂ M₂} (h : g₂.comp f = f.comp g) (k : ℕ) : (g₂ ^ k).comp f = f.comp (g ^ k) := by - induction' k with k ih - · simp only [pow_zero, one_eq_id, id_comp, comp_id] - · rw [pow_succ', pow_succ', LinearMap.mul_eq_comp, LinearMap.comp_assoc, ih, + induction k with + | zero => simp only [pow_zero, one_eq_id, id_comp, comp_id] + | succ k ih => rw [pow_succ', pow_succ', LinearMap.mul_eq_comp, LinearMap.comp_assoc, ih, ← LinearMap.comp_assoc, h, LinearMap.comp_assoc, LinearMap.mul_eq_comp] @[simp] diff --git a/Mathlib/Algebra/Module/Projective.lean b/Mathlib/Algebra/Module/Projective.lean index 3a0613a2f353f..ea72b33e221e7 100644 --- a/Mathlib/Algebra/Module/Projective.lean +++ b/Mathlib/Algebra/Module/Projective.lean @@ -72,7 +72,7 @@ open Finsupp definitions. -/ class Module.Projective (R : Type*) [Semiring R] (P : Type*) [AddCommMonoid P] [Module R P] : Prop where - out : ∃ s : P →ₗ[R] P →₀ R, Function.LeftInverse (Finsupp.total P P R id) s + out : ∃ s : P →ₗ[R] P →₀ R, Function.LeftInverse (Finsupp.linearCombination R id) s namespace Module @@ -82,11 +82,11 @@ variable {R : Type*} [Semiring R] {P : Type*} [AddCommMonoid P] [Module R P] {M [AddCommMonoid M] [Module R M] {N : Type*} [AddCommMonoid N] [Module R N] theorem projective_def : - Projective R P ↔ ∃ s : P →ₗ[R] P →₀ R, Function.LeftInverse (Finsupp.total P P R id) s := + Projective R P ↔ ∃ s : P →ₗ[R] P →₀ R, Function.LeftInverse (linearCombination R id) s := ⟨fun h => h.1, fun h => ⟨h⟩⟩ theorem projective_def' : - Projective R P ↔ ∃ s : P →ₗ[R] P →₀ R, Finsupp.total P P R id ∘ₗ s = .id := by + Projective R P ↔ ∃ s : P →ₗ[R] P →₀ R, Finsupp.linearCombination R id ∘ₗ s = .id := by simp_rw [projective_def, DFunLike.ext_iff, Function.LeftInverse, comp_apply, id_apply] /-- A projective R-module has the property that maps from it lift along surjections. -/ @@ -95,20 +95,20 @@ theorem projective_lifting_property [h : Projective R P] (f : M →ₗ[R] N) (g /- Here's the first step of the proof. Recall that `X →₀ R` is Lean's way of talking about the free `R`-module - on a type `X`. The universal property `Finsupp.total` says that to a map + on a type `X`. The universal property `Finsupp.linearCombination` says that to a map `X → N` from a type to an `R`-module, we get an associated R-module map `(X →₀ R) →ₗ N`. Apply this to a (noncomputable) map `P → M` coming from the map `P →ₗ N` and a random splitting of the surjection `M →ₗ N`, and we get a map `φ : (P →₀ R) →ₗ M`. -/ - let φ : (P →₀ R) →ₗ[R] M := Finsupp.total _ _ _ fun p => Function.surjInv hf (g p) + let φ : (P →₀ R) →ₗ[R] M := Finsupp.linearCombination _ fun p => Function.surjInv hf (g p) -- By projectivity we have a map `P →ₗ (P →₀ R)`; cases' h.out with s hs -- Compose to get `P →ₗ M`. This works. use φ.comp s ext p conv_rhs => rw [← hs p] - simp [φ, Finsupp.total_apply, Function.surjInv_eq hf, map_finsupp_sum] + simp [φ, Finsupp.linearCombination_apply, Function.surjInv_eq hf, map_finsupp_sum] /-- A module which satisfies the universal property is projective: If all surjections of `R`-modules `(P →₀ R) →ₗ[R] P` have `R`-linear left inverse maps, then `P` is @@ -117,8 +117,8 @@ theorem Projective.of_lifting_property'' {R : Type u} [Semiring R] {P : Type v} [Module R P] (huniv : ∀ (f : (P →₀ R) →ₗ[R] P), Function.Surjective f → ∃ h : P →ₗ[R] (P →₀ R), f.comp h = .id) : Projective R P := - projective_def'.2 <| huniv (Finsupp.total P P R (id : P → P)) - (total_surjective _ Function.surjective_id) + projective_def'.2 <| huniv (Finsupp.linearCombination R (id : P → P)) + (linearCombination_surjective _ Function.surjective_id) variable {Q : Type*} [AddCommMonoid Q] [Module R Q] @@ -152,9 +152,9 @@ theorem Projective.of_basis {ι : Type*} (b : Basis ι R P) : Projective R P := -- get it from `ι → (P →₀ R)` coming from `b`. use b.constr ℕ fun i => Finsupp.single (b i) (1 : R) intro m - simp only [b.constr_apply, mul_one, id, Finsupp.smul_single', Finsupp.total_single, + simp only [b.constr_apply, mul_one, id, Finsupp.smul_single', Finsupp.linearCombination_single, map_finsupp_sum] - exact b.total_repr m + exact b.linearCombination_repr m instance (priority := 100) Projective.of_free [Module.Free R P] : Module.Projective R P := .of_basis <| Module.Free.chooseBasis R P @@ -164,7 +164,7 @@ variable [IsScalarTower R₀ R M] [AddCommGroup N] [Module R₀ N] theorem Projective.of_split [Module.Projective R M] (i : P →ₗ[R] M) (s : M →ₗ[R] P) (H : s.comp i = LinearMap.id) : Module.Projective R P := by - obtain ⟨g, hg⟩ := projective_lifting_property (Finsupp.total P P R id) s + obtain ⟨g, hg⟩ := projective_lifting_property (Finsupp.linearCombination R id) s (fun x ↦ ⟨Finsupp.single x 1, by simp⟩) refine ⟨g.comp i, fun x ↦ ?_⟩ rw [LinearMap.comp_apply, ← LinearMap.comp_apply, hg, @@ -178,7 +178,7 @@ theorem Projective.of_equiv [Module.Projective R M] theorem Projective.iff_split : Module.Projective R P ↔ ∃ (M : Type max u v) (_ : AddCommGroup M) (_ : Module R M) (_ : Module.Free R M) (i : P →ₗ[R] M) (s : M →ₗ[R] P), s.comp i = LinearMap.id := - ⟨fun ⟨i, hi⟩ ↦ ⟨P →₀ R, _, _, inferInstance, i, Finsupp.total P P R id, LinearMap.ext hi⟩, + ⟨fun ⟨i, hi⟩ ↦ ⟨P →₀ R, _, _, inferInstance, i, Finsupp.linearCombination R id, LinearMap.ext hi⟩, fun ⟨_, _, _, _, i, s, H⟩ ↦ Projective.of_split i s H⟩ /-- A quotient of a projective module is projective iff it is a direct summand. -/ @@ -197,11 +197,11 @@ instance Projective.tensorProduct [hM : Module.Projective R M] [hN : Module.Proj fapply Projective.of_split (R := R) (M := ((M →₀ R) ⊗[R₀] (N →₀ R₀))) · exact (AlgebraTensorModule.map sM (LinearMap.id (R := R₀) (M := N →₀ R₀))) · exact (AlgebraTensorModule.map - (Finsupp.total M M R id) (LinearMap.id (R := R₀) (M := N →₀ R₀))) + (Finsupp.linearCombination R id) (LinearMap.id (R := R₀) (M := N →₀ R₀))) · ext; simp [hsM _] fapply Projective.of_split (R := R) (M := (M ⊗[R₀] (N →₀ R₀))) · exact (AlgebraTensorModule.map (LinearMap.id (R := R) (M := M)) sN) - · exact (AlgebraTensorModule.map (LinearMap.id (R := R) (M := M)) (Finsupp.total N N R₀ id)) + · exact (AlgebraTensorModule.map (LinearMap.id (R := R) (M := M)) (linearCombination R₀ id)) · ext; simp [hsN _] end Ring diff --git a/Mathlib/Algebra/Module/Rat.lean b/Mathlib/Algebra/Module/Rat.lean index fa255570c0b86..c0ed84a4366ed 100644 --- a/Mathlib/Algebra/Module/Rat.lean +++ b/Mathlib/Algebra/Module/Rat.lean @@ -5,6 +5,7 @@ Authors: Nathaniel Thomas, Jeremy Avigad, Johannes Hölzl, Mario Carneiro -/ import Mathlib.Algebra.Module.Basic import Mathlib.Algebra.Field.Rat +import Mathlib.Algebra.Order.Field.Rat /-! # Basic results about modules over the rationals. @@ -14,6 +15,13 @@ universe u v variable {M M₂ : Type*} +theorem map_nnratCast_smul [AddCommMonoid M] [AddCommMonoid M₂] {F : Type*} [FunLike F M M₂] + [AddMonoidHomClass F M M₂] (f : F) (R S : Type*) [DivisionSemiring R] [DivisionSemiring S] + [Module R M] [Module S M₂] (c : ℚ≥0) (x : M) : + f ((c : R) • x) = (c : S) • f x := by + rw [NNRat.cast_def, NNRat.cast_def, div_eq_mul_inv, div_eq_mul_inv, mul_smul, mul_smul, + map_natCast_smul f R S, map_inv_natCast_smul f R S] + theorem map_ratCast_smul [AddCommGroup M] [AddCommGroup M₂] {F : Type*} [FunLike F M M₂] [AddMonoidHomClass F M M₂] (f : F) (R S : Type*) [DivisionRing R] [DivisionRing S] [Module R M] [Module S M₂] (c : ℚ) (x : M) : @@ -24,17 +32,34 @@ theorem map_ratCast_smul [AddCommGroup M] [AddCommGroup M₂] {F : Type*} [FunLi @[deprecated (since := "2024-04-17")] alias map_rat_cast_smul := map_ratCast_smul +theorem map_nnrat_smul [AddCommMonoid M] [AddCommMonoid M₂] + [_instM : Module ℚ≥0 M] [_instM₂ : Module ℚ≥0 M₂] + {F : Type*} [FunLike F M M₂] [AddMonoidHomClass F M M₂] + (f : F) (c : ℚ≥0) (x : M) : f (c • x) = c • f x := + map_nnratCast_smul f ℚ≥0 ℚ≥0 c x + theorem map_rat_smul [AddCommGroup M] [AddCommGroup M₂] [_instM : Module ℚ M] [_instM₂ : Module ℚ M₂] {F : Type*} [FunLike F M M₂] [AddMonoidHomClass F M M₂] (f : F) (c : ℚ) (x : M) : f (c • x) = c • f x := map_ratCast_smul f ℚ ℚ c x +/-- There can be at most one `Module ℚ≥0 E` structure on an additive commutative monoid. -/ +instance subsingleton_nnrat_module (E : Type*) [AddCommMonoid E] : Subsingleton (Module ℚ≥0 E) := + ⟨fun P Q => (Module.ext' P Q) fun r x => + map_nnrat_smul (_instM := P) (_instM₂ := Q) (AddMonoidHom.id E) r x⟩ + /-- There can be at most one `Module ℚ E` structure on an additive commutative group. -/ instance subsingleton_rat_module (E : Type*) [AddCommGroup E] : Subsingleton (Module ℚ E) := ⟨fun P Q => (Module.ext' P Q) fun r x => map_rat_smul (_instM := P) (_instM₂ := Q) (AddMonoidHom.id E) r x⟩ +/-- If `E` is a vector space over two division semirings `R` and `S`, then scalar multiplications +agree on non-negative rational numbers in `R` and `S`. -/ +theorem nnratCast_smul_eq {E : Type*} (R S : Type*) [AddCommMonoid E] [DivisionSemiring R] + [DivisionSemiring S] [Module R E] [Module S E] (r : ℚ≥0) (x : E) : (r : R) • x = (r : S) • x := + map_nnratCast_smul (AddMonoidHom.id E) R S r x + /-- If `E` is a vector space over two division rings `R` and `S`, then scalar multiplications agree on rational numbers in `R` and `S`. -/ theorem ratCast_smul_eq {E : Type*} (R S : Type*) [AddCommGroup E] [DivisionRing R] @@ -44,22 +69,41 @@ theorem ratCast_smul_eq {E : Type*} (R S : Type*) [AddCommGroup E] [DivisionRing @[deprecated (since := "2024-04-17")] alias rat_cast_smul_eq := ratCast_smul_eq +instance IsScalarTower.nnrat {R : Type u} {M : Type v} [Semiring R] [AddCommMonoid M] [Module R M] + [Module ℚ≥0 R] [Module ℚ≥0 M] : IsScalarTower ℚ≥0 R M where + smul_assoc r x y := map_nnrat_smul ((smulAddHom R M).flip y) r x + instance IsScalarTower.rat {R : Type u} {M : Type v} [Ring R] [AddCommGroup M] [Module R M] [Module ℚ R] [Module ℚ M] : IsScalarTower ℚ R M where smul_assoc r x y := map_rat_smul ((smulAddHom R M).flip y) r x -instance SMulCommClass.rat {R : Type u} {M : Type v} [Semiring R] [AddCommGroup M] [Module R M] - [Module ℚ M] : SMulCommClass ℚ R M where - smul_comm r x y := (map_rat_smul (smulAddHom R M x) r y).symm +section +variable {α : Type u} {M : Type v} -instance SMulCommClass.rat' {R : Type u} {M : Type v} [Semiring R] [AddCommGroup M] [Module R M] - [Module ℚ M] : SMulCommClass R ℚ M := +instance SMulCommClass.nnrat [Monoid α] [AddCommMonoid M] [DistribMulAction α M] [Module ℚ≥0 M] : + SMulCommClass ℚ≥0 α M where + smul_comm r x y := (map_nnrat_smul (DistribMulAction.toAddMonoidHom M x) r y).symm + +instance SMulCommClass.rat [Monoid α] [AddCommGroup M] [DistribMulAction α M] [Module ℚ M] : + SMulCommClass ℚ α M where + smul_comm r x y := (map_rat_smul (DistribMulAction.toAddMonoidHom M x) r y).symm + +instance SMulCommClass.nnrat' [Monoid α] [AddCommMonoid M] [DistribMulAction α M] [Module ℚ≥0 M] : + SMulCommClass α ℚ≥0 M := + SMulCommClass.symm _ _ _ + +instance SMulCommClass.rat' [Monoid α] [AddCommGroup M] [DistribMulAction α M] [Module ℚ M] : + SMulCommClass α ℚ M := SMulCommClass.symm _ _ _ +end + +-- see note [lower instance priority] +instance (priority := 100) NNRatModule.noZeroSMulDivisors [AddCommMonoid M] [Module ℚ≥0 M] : + NoZeroSMulDivisors ℕ M := + ⟨fun {k} {x : M} h => by simpa [← Nat.cast_smul_eq_nsmul ℚ≥0 k x] using h⟩ + -- see note [lower instance priority] instance (priority := 100) RatModule.noZeroSMulDivisors [AddCommGroup M] [Module ℚ M] : NoZeroSMulDivisors ℤ M := - ⟨fun {k} {x : M} h => by - simpa only [← Int.cast_smul_eq_zsmul ℚ k x, smul_eq_zero, Rat.zero_iff_num_zero] using h⟩ - -- Porting note: old proof was: - --⟨fun {k x} h => by simpa [zsmul_eq_smul_cast ℚ k x] using h⟩ + ⟨fun {k} {x : M} h => by simpa [← Int.cast_smul_eq_zsmul ℚ k x] using h⟩ diff --git a/Mathlib/Algebra/Module/Submodule/Basic.lean b/Mathlib/Algebra/Module/Submodule/Basic.lean index 6c89784c098f8..3958ed075e9fb 100644 --- a/Mathlib/Algebra/Module/Submodule/Basic.lean +++ b/Mathlib/Algebra/Module/Submodule/Basic.lean @@ -152,7 +152,7 @@ variable [Semiring R] [AddCommMonoid M] [Module R M] {A : Type*} [SetLike A M] [AddSubmonoidClass A M] [SMulMemClass A R M] (S' : A) -- Prefer subclasses of `Module` over `SMulMemClass`. -/-- A submodule of a `Module` is a `Module`. -/ +/-- A submodule of a `Module` is a `Module`. -/ instance (priority := 75) toModule : Module R S' := Subtype.coe_injective.module R (AddSubmonoidClass.subtype S') (SetLike.val_smul S') @@ -236,6 +236,7 @@ instance isCentralScalar [SMul S R] [SMul S M] [IsScalarTower S R M] [SMul Sᵐ protected theorem nonempty : (p : Set M).Nonempty := ⟨0, p.zero_mem⟩ +@[simp] theorem mk_eq_zero {x} (h : x ∈ p) : (⟨x, h⟩ : p) = 0 ↔ x = 0 := Subtype.ext_iff_val diff --git a/Mathlib/Algebra/Module/Submodule/Bilinear.lean b/Mathlib/Algebra/Module/Submodule/Bilinear.lean index 8f1e0b93e8437..bacd3bc47d6b5 100644 --- a/Mathlib/Algebra/Module/Submodule/Bilinear.lean +++ b/Mathlib/Algebra/Module/Submodule/Bilinear.lean @@ -37,7 +37,7 @@ variable [Module R M] [Module R N] [Module R P] /-- Map a pair of submodules under a bilinear map. -This is the submodule version of `Set.image2`. -/ +This is the submodule version of `Set.image2`. -/ def map₂ (f : M →ₗ[R] N →ₗ[R] P) (p : Submodule R M) (q : Submodule R N) : Submodule R P := ⨆ s : p, q.map (f s) diff --git a/Mathlib/Algebra/Module/Submodule/Equiv.lean b/Mathlib/Algebra/Module/Submodule/Equiv.lean index df3250cb70e1e..f5de6d41357b8 100644 --- a/Mathlib/Algebra/Module/Submodule/Equiv.lean +++ b/Mathlib/Algebra/Module/Submodule/Equiv.lean @@ -186,6 +186,11 @@ theorem ofBijective_symm_apply_apply [RingHomInvPair σ₁₂ σ₂₁] [RingHom (ofBijective f h).symm (f x) = x := by simp [LinearEquiv.symm_apply_eq] +@[simp] +theorem apply_ofBijective_symm_apply [RingHomInvPair σ₁₂ σ₂₁] [RingHomInvPair σ₂₁ σ₁₂] {h} + (x : M₂) : f ((ofBijective f h).symm x) = x := by + rw [← ofBijective_apply f ((ofBijective f h).symm x), apply_symm_apply] + end end AddCommMonoid diff --git a/Mathlib/Algebra/Module/Submodule/Ker.lean b/Mathlib/Algebra/Module/Submodule/Ker.lean index 6eefd47994bea..e329b35726b80 100644 --- a/Mathlib/Algebra/Module/Submodule/Ker.lean +++ b/Mathlib/Algebra/Module/Submodule/Ker.lean @@ -192,11 +192,11 @@ theorem ker_eq_bot {f : M →ₛₗ[τ₁₂] M₂} : ker f = ⊥ ↔ Injective · intro x ⟨hx, h'x⟩ have : ⟨x, hx⟩ ∈ LinearMap.ker (LinearMap.domRestrict f S) := by simpa using h'x rw [h] at this - simpa using this + simpa [mk_eq_zero] using this · rintro ⟨x, hx⟩ h'x have : x ∈ S ⊓ LinearMap.ker f := ⟨hx, h'x⟩ rw [h] at this - simpa using this + simpa [mk_eq_zero] using this @[simp] theorem injective_restrict_iff_disjoint {p : Submodule R M} {f : M →ₗ[R] M} (hf : ∀ x ∈ p, f x ∈ p) : diff --git a/Mathlib/Algebra/Module/Submodule/Map.lean b/Mathlib/Algebra/Module/Submodule/Map.lean index e6d75f1363cf8..eaf5c011557e5 100644 --- a/Mathlib/Algebra/Module/Submodule/Map.lean +++ b/Mathlib/Algebra/Module/Submodule/Map.lean @@ -191,9 +191,9 @@ theorem comap_mono {f : F} {q q' : Submodule R₂ M₂} : q ≤ q' → comap f q theorem le_comap_pow_of_le_comap (p : Submodule R M) {f : M →ₗ[R] M} (h : p ≤ p.comap f) (k : ℕ) : p ≤ p.comap (f ^ k) := by - induction' k with k ih - · simp [LinearMap.one_eq_id] - · simp [LinearMap.iterate_succ, comap_comp, h.trans (comap_mono ih)] + induction k with + | zero => simp [LinearMap.one_eq_id] + | succ k ih => simp [LinearMap.iterate_succ, comap_comp, h.trans (comap_mono ih)] section @@ -409,6 +409,10 @@ lemma comap_neg {f : M →ₗ[R] M₂} {p : Submodule R M₂} : p.comap (-f) = p.comap f := by ext; simp +lemma map_toAddSubgroup (f : M →ₗ[R] M₂) (p : Submodule R M) : + (p.map f).toAddSubgroup = p.toAddSubgroup.map (f : M →+ M₂) := + rfl + end AddCommGroup end Submodule diff --git a/Mathlib/Algebra/Module/Submodule/Pointwise.lean b/Mathlib/Algebra/Module/Submodule/Pointwise.lean index 99e50eaa44e68..031be85372fc7 100644 --- a/Mathlib/Algebra/Module/Submodule/Pointwise.lean +++ b/Mathlib/Algebra/Module/Submodule/Pointwise.lean @@ -416,12 +416,10 @@ lemma set_smul_eq_map [SMulCommClass R R N] : apply set_smul_eq_of_le · intro r n hr hn 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, LinearMap.coe_mk, - AddHom.coe_mk, Function.comp_apply, AddSubmonoid.coe_finset_sum, coe_toAddSubmonoid, - SetLike.val_smul] + simp only [LinearMap.coe_comp, coeSubtype, 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 rw [mem_set_smul_def, Submodule.mem_sInf] @@ -442,10 +440,9 @@ lemma mem_set_smul (x : M) [SMulCommClass R R N] : rw [set_smul_eq_map] at h obtain ⟨c, hc, rfl⟩ := h exact ⟨c, hc, rfl⟩ - · rw [mem_set_smul_def, Submodule.mem_sInf] rintro ⟨c, hc1, rfl⟩ p hp - simp only [Finsupp.sum, AddSubmonoid.coe_finset_sum, coe_toAddSubmonoid, SetLike.val_smul] + rw [Finsupp.sum, AddSubmonoid.coe_finset_sum] exact Submodule.sum_mem _ fun r hr ↦ hp (hc1 hr) (c _).2 @[simp] lemma empty_set_smul : (∅ : Set S) • N = ⊥ := by @@ -496,8 +493,8 @@ protected def pointwiseSetMulAction [SMulCommClass R R M] : (set_smul_le _ _ _ fun r m hr hm ↦ by have : SMulCommClass R R x := ⟨fun r s m => Subtype.ext <| smul_comm _ _ _⟩ obtain ⟨c, hc1, rfl⟩ := mem_set_smul _ _ _ |>.mp hm - simp only [Finsupp.sum, AddSubmonoid.coe_finset_sum, coe_toAddSubmonoid, SetLike.val_smul, - Finset.smul_sum, smul_smul] + rw [Finsupp.sum, AddSubmonoid.coe_finset_sum] + simp only [SetLike.val_smul, Finset.smul_sum, smul_smul] exact Submodule.sum_mem _ fun r' hr' ↦ mem_set_smul_of_mem_mem (Set.mul_mem_mul hr (hc1 hr')) (c _).2) @@ -533,11 +530,12 @@ lemma coe_span_smul {R' M' : Type*} [CommSemiring R'] [AddCommMonoid M'] [Module (Ideal.span s : Set R') • N = s • N := set_smul_eq_of_le _ _ _ (by rintro r n hr hn - induction' hr using Submodule.span_induction' with r h _ _ _ _ ihr ihs r r' hr hr' - · exact mem_set_smul_of_mem_mem h hn - · rw [zero_smul]; exact Submodule.zero_mem _ - · rw [add_smul]; exact Submodule.add_mem _ ihr ihs - · rw [mem_span_set] at hr + induction hr using Submodule.span_induction' with + | mem _ h => exact mem_set_smul_of_mem_mem h hn + | zero => rw [zero_smul]; exact Submodule.zero_mem _ + | add _ _ _ _ ihr ihs => rw [add_smul]; exact Submodule.add_mem _ ihr ihs + | smul _ _ hr => + rw [mem_span_set] at hr obtain ⟨c, hc, rfl⟩ := hr rw [Finsupp.sum, Finset.smul_sum, Finset.sum_smul] refine Submodule.sum_mem _ fun i hi => ?_ diff --git a/Mathlib/Algebra/Module/Torsion.lean b/Mathlib/Algebra/Module/Torsion.lean index 4fe308cff7cb6..4fddfa53bfe70 100644 --- a/Mathlib/Algebra/Module/Torsion.lean +++ b/Mathlib/Algebra/Module/Torsion.lean @@ -3,13 +3,10 @@ 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.Algebra.DirectSum.Module -import Mathlib.Algebra.Module.BigOperators import Mathlib.LinearAlgebra.Isomorphisms import Mathlib.GroupTheory.Torsion import Mathlib.RingTheory.Coprime.Ideal -import Mathlib.RingTheory.Finiteness -import Mathlib.Data.Set.Lattice +import Mathlib.Data.ZMod.Module /-! # Torsion submodules @@ -363,9 +360,7 @@ theorem iSup_torsionBySet_ideal_eq_torsionBySet_iInf (hp : (S : Set ι).Pairwise fun i j => p i ⊔ p j = ⊤) : ⨆ i ∈ S, torsionBySet R M (p i) = torsionBySet R M ↑(⨅ i ∈ S, p i) := by rcases S.eq_empty_or_nonempty with h | h - · simp only [h] - -- Porting note: converts were not cooperating - convert iSup_emptyset (f := fun i => torsionBySet R M (p i)) <;> simp + · simp [h] apply le_antisymm · apply iSup_le _ intro i @@ -861,6 +856,46 @@ theorem isTorsion_iff_isTorsion_int [AddCommGroup M] : end AddMonoid +namespace AddSubgroup + +variable (A : Type*) [AddCommGroup A] (n : ℤ) + +/-- The additive `n`-torsion subgroup for an integer `n`. -/ +@[reducible] +def torsionBy : AddSubgroup A := + (Submodule.torsionBy ℤ A n).toAddSubgroup + +@[inherit_doc] +scoped notation:max (priority := high) A"["n"]" => torsionBy A n + +lemma torsionBy.neg : A[-n] = A[n] := by + ext a + simp + +variable {A} {n : ℕ} + +@[simp] +lemma torsionBy.nsmul (x : A[n]) : n • x = 0 := + Nat.cast_smul_eq_nsmul ℤ n x ▸ Submodule.smul_torsionBy .. + +lemma torsionBy.nsmul_iff {x : A} : + x ∈ A[n] ↔ n • x = 0 := + Nat.cast_smul_eq_nsmul ℤ n x ▸ Submodule.mem_torsionBy_iff .. + +lemma torsionBy.mod_self_nsmul (s : ℕ) (x : A[n]) : + s • x = (s % n) • x := + nsmul_eq_mod_nsmul s (torsionBy.nsmul x) + +lemma torsionBy.mod_self_nsmul' (s : ℕ) {x : A} (h : x ∈ A[n]) : + s • x = (s % n) • x := + nsmul_eq_mod_nsmul s (torsionBy.nsmul_iff.mp h) + +/-- For a natural number `n`, the `n`-torsion subgroup of `A` is a `ZMod n` module. -/ +def torsionBy.zmodModule : Module (ZMod n) A[n] := + AddCommGroup.zmodModule torsionBy.nsmul + +end AddSubgroup + section InfiniteRange @[simp] diff --git a/Mathlib/Algebra/Module/Zlattice/Basic.lean b/Mathlib/Algebra/Module/Zlattice/Basic.lean index c26f3cf544512..c3614a576ee4a 100644 --- a/Mathlib/Algebra/Module/Zlattice/Basic.lean +++ b/Mathlib/Algebra/Module/Zlattice/Basic.lean @@ -200,11 +200,13 @@ variable [Unique ι] @[simp] theorem coe_floor_self (k : K) : (floor (Basis.singleton ι K) k : K) = ⌊k⌋ := - Basis.ext_elem _ fun _ => by rw [repr_floor_apply, Basis.singleton_repr, Basis.singleton_repr] + Basis.ext_elem (Basis.singleton ι K) fun _ => by + rw [repr_floor_apply, Basis.singleton_repr, Basis.singleton_repr] @[simp] theorem coe_fract_self (k : K) : (fract (Basis.singleton ι K) k : K) = Int.fract k := - Basis.ext_elem _ fun _ => by rw [repr_fract_apply, Basis.singleton_repr, Basis.singleton_repr] + Basis.ext_elem (Basis.singleton ι K) fun _ => by + rw [repr_fract_apply, Basis.singleton_repr, Basis.singleton_repr] end Unique diff --git a/Mathlib/Algebra/MonoidAlgebra/Basic.lean b/Mathlib/Algebra/MonoidAlgebra/Basic.lean index 4022f37abb36e..23c0fabadf6c7 100644 --- a/Mathlib/Algebra/MonoidAlgebra/Basic.lean +++ b/Mathlib/Algebra/MonoidAlgebra/Basic.lean @@ -656,7 +656,7 @@ def liftMagma [Module k A] [IsScalarTower k A A] [SMulCommClass k A A] : intros rw [← add_smul] -- Porting note: `reducible` cannot be `local` so proof gets long. - simp_rw [Finsupp.mul_sum, Finsupp.sum_mul, smul_mul_smul, ← f.map_mul, mul_def, + simp_rw [Finsupp.mul_sum, Finsupp.sum_mul, smul_mul_smul_comm, ← f.map_mul, mul_def, sum_comm a₂ a₁] rw [sum_sum_index h₁ h₂]; congr; ext rw [sum_sum_index h₁ h₂]; congr; ext @@ -1966,3 +1966,5 @@ def AddMonoidAlgebra.toMultiplicativeAlgEquiv [Semiring k] [Algebra R k] [AddMon def MonoidAlgebra.toAdditiveAlgEquiv [Semiring k] [Algebra R k] [Monoid G] : MonoidAlgebra k G ≃ₐ[R] AddMonoidAlgebra k (Additive G) := { MonoidAlgebra.toAdditive k G with commutes' := fun r => by simp [MonoidAlgebra.toAdditive] } + +set_option linter.style.longFile 2100 diff --git a/Mathlib/Algebra/MonoidAlgebra/ToDirectSum.lean b/Mathlib/Algebra/MonoidAlgebra/ToDirectSum.lean index 197cf5eb69847..111fe27da2293 100644 --- a/Mathlib/Algebra/MonoidAlgebra/ToDirectSum.lean +++ b/Mathlib/Algebra/MonoidAlgebra/ToDirectSum.lean @@ -8,7 +8,7 @@ import Mathlib.Algebra.MonoidAlgebra.Basic import Mathlib.Data.Finsupp.ToDFinsupp /-! -# Conversion between `AddMonoidAlgebra` and homogenous `DirectSum` +# Conversion between `AddMonoidAlgebra` and homogeneous `DirectSum` This module provides conversions between `AddMonoidAlgebra` and `DirectSum`. The latter is essentially a dependent version of the former. @@ -64,7 +64,7 @@ open DirectSum section Defs -/-- Interpret an `AddMonoidAlgebra` as a homogenous `DirectSum`. -/ +/-- Interpret an `AddMonoidAlgebra` as a homogeneous `DirectSum`. -/ def AddMonoidAlgebra.toDirectSum [Semiring M] (f : AddMonoidAlgebra M ι) : ⨁ _ : ι, M := Finsupp.toDFinsupp f @@ -79,7 +79,7 @@ theorem AddMonoidAlgebra.toDirectSum_single (i : ι) (m : M) : variable [∀ m : M, Decidable (m ≠ 0)] -/-- Interpret a homogenous `DirectSum` as an `AddMonoidAlgebra`. -/ +/-- Interpret a homogeneous `DirectSum` as an `AddMonoidAlgebra`. -/ def DirectSum.toAddMonoidAlgebra (f : ⨁ _ : ι, M) : AddMonoidAlgebra M ι := DFinsupp.toFinsupp f @@ -191,7 +191,7 @@ def addMonoidAlgebraEquivDirectSum [DecidableEq ι] [Semiring M] [∀ m : M, Dec toFun := AddMonoidAlgebra.toDirectSum invFun := DirectSum.toAddMonoidAlgebra } -/-- The additive version of `AddMonoidAlgebra.addMonoidAlgebraEquivDirectSum`. -/ +/-- The additive version of `AddMonoidAlgebra.addMonoidAlgebraEquivDirectSum`. -/ @[simps (config := .asFn)] def addMonoidAlgebraAddEquivDirectSum [DecidableEq ι] [Semiring M] [∀ m : M, Decidable (m ≠ 0)] : AddMonoidAlgebra M ι ≃+ ⨁ _ : ι, M := @@ -200,7 +200,7 @@ def addMonoidAlgebraAddEquivDirectSum [DecidableEq ι] [Semiring M] [∀ m : M, invFun := DirectSum.toAddMonoidAlgebra map_add' := AddMonoidAlgebra.toDirectSum_add } -/-- The ring version of `AddMonoidAlgebra.addMonoidAlgebraEquivDirectSum`. -/ +/-- The ring version of `AddMonoidAlgebra.addMonoidAlgebraEquivDirectSum`. -/ @[simps (config := .asFn)] def addMonoidAlgebraRingEquivDirectSum [DecidableEq ι] [AddMonoid ι] [Semiring M] [∀ m : M, Decidable (m ≠ 0)] : AddMonoidAlgebra M ι ≃+* ⨁ _ : ι, M := diff --git a/Mathlib/Algebra/MvPolynomial/Basic.lean b/Mathlib/Algebra/MvPolynomial/Basic.lean index 90a2b3d0d0db8..db1846108e926 100644 --- a/Mathlib/Algebra/MvPolynomial/Basic.lean +++ b/Mathlib/Algebra/MvPolynomial/Basic.lean @@ -461,7 +461,7 @@ theorem linearMap_ext {M : Type*} [AddCommMonoid M] [Module R M] {f g : MvPolyno section Support -/-- The finite set of all `m : σ →₀ ℕ` such that `X^m` has a non-zero coefficient. -/ +/-- The finite set of all `m : σ →₀ ℕ` such that `X^m` has a non-zero coefficient. -/ def support (p : MvPolynomial σ R) : Finset (σ →₀ ℕ) := Finsupp.support p @@ -1437,7 +1437,7 @@ variable (R) theorem _root_.Algebra.adjoin_range_eq_range_aeval : Algebra.adjoin R (Set.range f) = (MvPolynomial.aeval f).range := by simp only [← Algebra.map_top, ← MvPolynomial.adjoin_range_X, AlgHom.map_adjoin, ← Set.range_comp, - (· ∘ ·), MvPolynomial.aeval_X] + Function.comp_def, MvPolynomial.aeval_X] theorem _root_.Algebra.adjoin_eq_range (s : Set S₁) : Algebra.adjoin R s = (MvPolynomial.aeval ((↑) : s → S₁)).range := by @@ -1539,3 +1539,5 @@ end EvalMem end CommSemiring end MvPolynomial + +set_option linter.style.longFile 1700 diff --git a/Mathlib/Algebra/MvPolynomial/Division.lean b/Mathlib/Algebra/MvPolynomial/Division.lean index eafbfef36254a..73946aa78f7a6 100644 --- a/Mathlib/Algebra/MvPolynomial/Division.lean +++ b/Mathlib/Algebra/MvPolynomial/Division.lean @@ -213,7 +213,7 @@ theorem X_dvd_X [Nontrivial R] {i j : σ} : (X i : MvPolynomial σ R) ∣ (X j : MvPolynomial σ R) ↔ i = j := by refine monomial_one_dvd_monomial_one.trans ?_ simp_rw [Finsupp.single_le_iff, Nat.one_le_iff_ne_zero, Finsupp.single_apply_ne_zero, - ne_eq, not_false_eq_true, and_true] + ne_eq, reduceCtorEq,not_false_eq_true, and_true] @[simp] theorem X_dvd_monomial {i : σ} {j : σ →₀ ℕ} {r : R} : diff --git a/Mathlib/Algebra/MvPolynomial/Equiv.lean b/Mathlib/Algebra/MvPolynomial/Equiv.lean index 1e2e8a1a44450..a6350e2e62a69 100644 --- a/Mathlib/Algebra/MvPolynomial/Equiv.lean +++ b/Mathlib/Algebra/MvPolynomial/Equiv.lean @@ -377,7 +377,7 @@ theorem eval_eq_eval_mv_eval' (s : Fin n → R) (y : R) (f : MvPolynomial (Fin ( (Polynomial.aeval y).comp (φ.comp (finSuccEquiv R n).toAlgHom) f congr 2 apply MvPolynomial.algHom_ext - rw [Fin.forall_fin_succ] + rw [Fin.forall_iff_succ] simp only [φ, aeval_X, Fin.cons_zero, AlgEquiv.toAlgHom_eq_coe, AlgHom.coe_comp, Polynomial.coe_aeval_eq_eval, Polynomial.map_C, AlgHom.coe_mk, RingHom.toFun_eq_coe, Polynomial.coe_mapRingHom, comp_apply, finSuccEquiv_apply, eval₂Hom_X', diff --git a/Mathlib/Algebra/MvPolynomial/Expand.lean b/Mathlib/Algebra/MvPolynomial/Expand.lean index 142256c94fc0d..8b06a208a6ea6 100644 --- a/Mathlib/Algebra/MvPolynomial/Expand.lean +++ b/Mathlib/Algebra/MvPolynomial/Expand.lean @@ -68,7 +68,7 @@ theorem map_expand (f : R →+* S) (p : ℕ) (φ : MvPolynomial σ R) : @[simp] theorem rename_expand (f : σ → τ) (p : ℕ) (φ : MvPolynomial σ R) : rename f (expand p φ) = expand p (rename f φ) := by - simp [expand, bind₁_rename, rename_bind₁, Function.comp] + simp [expand, bind₁_rename, rename_bind₁, Function.comp_def] @[simp] theorem rename_comp_expand (f : σ → τ) (p : ℕ) : diff --git a/Mathlib/Algebra/MvPolynomial/Rename.lean b/Mathlib/Algebra/MvPolynomial/Rename.lean index 3043309529923..eda39a1e51a4b 100644 --- a/Mathlib/Algebra/MvPolynomial/Rename.lean +++ b/Mathlib/Algebra/MvPolynomial/Rename.lean @@ -72,7 +72,7 @@ theorem rename_rename (f : σ → τ) (g : τ → α) (p : MvPolynomial σ R) : -- Porting note: the Lean 3 proof of this was very fragile and included a nonterminal `simp`. -- Hopefully this is less prone to breaking rw [eval₂_comp_left (eval₂Hom (algebraMap R (MvPolynomial α R)) (X ∘ g)) C (X ∘ f) p] - simp only [(· ∘ ·), eval₂Hom_X'] + simp only [comp_def, eval₂Hom_X'] refine eval₂Hom_congr ?_ rfl rfl ext1; simp only [comp_apply, RingHom.coe_comp, eval₂Hom_C] @@ -246,7 +246,7 @@ theorem exists_fin_rename (p : MvPolynomial σ R) : let e := Fintype.equivFin { x // x ∈ s } refine ⟨n, (↑) ∘ e.symm, Subtype.val_injective.comp e.symm.injective, rename e q, ?_⟩ rw [← rename_rename, rename_rename e] - simp only [Function.comp, Equiv.symm_apply_apply, rename_rename] + simp only [Function.comp_def, Equiv.symm_apply_apply, rename_rename] end Rename diff --git a/Mathlib/Algebra/MvPolynomial/Variables.lean b/Mathlib/Algebra/MvPolynomial/Variables.lean index f431fe8b5f796..2c49de4e57ad4 100644 --- a/Mathlib/Algebra/MvPolynomial/Variables.lean +++ b/Mathlib/Algebra/MvPolynomial/Variables.lean @@ -272,7 +272,7 @@ theorem eval₂Hom_congr' {f₁ f₂ : R →+* S} {g₁ g₂ : σ → S} {p₁ p /-- If `f₁` and `f₂` are ring homs out of the polynomial ring and `p₁` and `p₂` are polynomials, then `f₁ p₁ = f₂ p₂` if `p₁ = p₂` and `f₁` and `f₂` are equal on `R` and on the variables - of `p₁`. -/ + of `p₁`. -/ theorem hom_congr_vars {f₁ f₂ : MvPolynomial σ R →+* S} {p₁ p₂ : MvPolynomial σ R} (hC : f₁.comp C = f₂.comp C) (hv : ∀ i, i ∈ p₁.vars → i ∈ p₂.vars → f₁ (X i) = f₂ (X i)) (hp : p₁ = p₂) : f₁ p₁ = f₂ p₂ := diff --git a/Mathlib/Algebra/NeZero.lean b/Mathlib/Algebra/NeZero.lean index 5851e7c4e2cef..aaa15d8a6209e 100644 --- a/Mathlib/Algebra/NeZero.lean +++ b/Mathlib/Algebra/NeZero.lean @@ -19,7 +19,7 @@ We create a typeclass `NeZero n` which carries around the fact that `(n : R) ≠ variable {R : Type*} [Zero R] -/-- A type-class version of `n ≠ 0`. -/ +/-- A type-class version of `n ≠ 0`. -/ class NeZero (n : R) : Prop where /-- The proposition that `n` is not zero. -/ out : n ≠ 0 diff --git a/Mathlib/Algebra/Order/Antidiag/Pi.lean b/Mathlib/Algebra/Order/Antidiag/Pi.lean index 2573fd6a28d1f..92206333ffa94 100644 --- a/Mathlib/Algebra/Order/Antidiag/Pi.lean +++ b/Mathlib/Algebra/Order/Antidiag/Pi.lean @@ -164,7 +164,7 @@ lemma pairwiseDisjoint_piAntidiag_map_addRightEmbedding (hi : i ∉ s) (n : μ) rintro hfg _ f rfl - rfl g rfl - hgf exact hfg <| by simpa [sum_add_distrib, hi] using congr_arg (∑ j ∈ s, · j) hgf.symm -lemma piAntidiag_cons (hi : i ∉ s) (n : μ) : +lemma piAntidiag_cons (hi : i ∉ s) (n : μ) : piAntidiag (cons i s hi) n = (antidiagonal n).disjiUnion (fun p : μ × μ ↦ (piAntidiag s p.snd).map (addRightEmbedding fun t ↦ if t = i then p.fst else 0)) (pairwiseDisjoint_piAntidiag_map_addRightEmbedding hi _) := by diff --git a/Mathlib/Algebra/Order/Archimedean/Basic.lean b/Mathlib/Algebra/Order/Archimedean/Basic.lean index 8bef3b5929f73..c0968b4ac7e37 100644 --- a/Mathlib/Algebra/Order/Archimedean/Basic.lean +++ b/Mathlib/Algebra/Order/Archimedean/Basic.lean @@ -19,6 +19,8 @@ number `n` such that `x ≤ n • y`. * `Archimedean` is a typeclass for an ordered additive commutative monoid to have the archimedean property. +* `MulArchimedean` is a typeclass for an ordered commutative monoid to have the "mul-archimedean + property" where for `x` and `y > 1`, there exists a natural number `n` such that `x ≤ y ^ n`. * `Archimedean.floorRing` defines a floor function on an archimedean linearly ordered ring making it into a `floorRing`. @@ -38,74 +40,104 @@ class Archimedean (α) [OrderedAddCommMonoid α] : Prop where such that `x ≤ n • y`. -/ arch : ∀ (x : α) {y : α}, 0 < y → ∃ n : ℕ, x ≤ n • y -instance OrderDual.archimedean [OrderedAddCommGroup α] [Archimedean α] : Archimedean αᵒᵈ := - ⟨fun x y hy => - let ⟨n, hn⟩ := Archimedean.arch (-ofDual x) (neg_pos.2 hy) - ⟨n, by rwa [neg_nsmul, neg_le_neg_iff] at hn⟩⟩ +section MulArchimedean -variable {M : Type*} +/-- An ordered commutative monoid is called `MulArchimedean` if for any two elements `x`, `y` +such that `1 < y`, there exists a natural number `n` such that `x ≤ y ^ n`. -/ +@[to_additive Archimedean] +class MulArchimedean (α) [OrderedCommMonoid α] : Prop where + /-- For any two elements `x`, `y` such that `1 < y`, there exists a natural number `n` + such that `x ≤ y ^ n`. -/ + arch : ∀ (x : α) {y : α}, 1 < y → ∃ n : ℕ, x ≤ y ^ n -theorem exists_lt_nsmul [OrderedAddCommMonoid M] [Archimedean M] - [CovariantClass M M (· + ·) (· < ·)] {a : M} (ha : 0 < a) (b : M) : - ∃ n : ℕ, b < n • a := - let ⟨k, hk⟩ := Archimedean.arch b ha - ⟨k + 1, hk.trans_lt <| nsmul_lt_nsmul_left ha k.lt_succ_self⟩ +end MulArchimedean -section LinearOrderedAddCommGroup +@[to_additive] +instance OrderDual.instMulArchimedean [OrderedCommGroup α] [MulArchimedean α] : + MulArchimedean αᵒᵈ := + ⟨fun x y hy => + let ⟨n, hn⟩ := MulArchimedean.arch (ofDual x)⁻¹ (inv_lt_one_iff_one_lt.2 hy) + ⟨n, by rwa [inv_pow, inv_le_inv_iff] at hn⟩⟩ -variable [LinearOrderedAddCommGroup α] [Archimedean α] +instance Additive.instArchimedean [OrderedCommGroup α] [MulArchimedean α] : + Archimedean (Additive α) := + ⟨fun x _ hy ↦ MulArchimedean.arch (toMul x) hy⟩ -/-- An archimedean decidable linearly ordered `AddCommGroup` has a version of the floor: for -`a > 0`, any `g` in the group lies between some two consecutive multiples of `a`. -/ -theorem existsUnique_zsmul_near_of_pos {a : α} (ha : 0 < a) (g : α) : - ∃! k : ℤ, k • a ≤ g ∧ g < (k + 1) • a := by - let s : Set ℤ := { n : ℤ | n • a ≤ g } - obtain ⟨k, hk : -g ≤ k • a⟩ := Archimedean.arch (-g) ha - have h_ne : s.Nonempty := ⟨-k, by simpa [s] using neg_le_neg hk⟩ - obtain ⟨k, hk⟩ := Archimedean.arch g ha +instance Multiplicative.instMulArchimedean [OrderedAddCommGroup α] [Archimedean α] : + MulArchimedean (Multiplicative α) := + ⟨fun x _ hy ↦ Archimedean.arch (toAdd x) hy⟩ + +variable {M : Type*} + +@[to_additive] +theorem exists_lt_pow [OrderedCommMonoid M] [MulArchimedean M] + [CovariantClass M M (· * ·) (· < ·)] {a : M} (ha : 1 < a) (b : M) : + ∃ n : ℕ, b < a ^ n := + let ⟨k, hk⟩ := MulArchimedean.arch b ha + ⟨k + 1, hk.trans_lt <| pow_lt_pow_right' ha k.lt_succ_self⟩ + +section LinearOrderedCommGroup + +variable [LinearOrderedCommGroup α] [MulArchimedean α] + +/-- An archimedean decidable linearly ordered `CommGroup` has a version of the floor: for +`a > 1`, any `g` in the group lies between some two consecutive powers of `a`. -/ +@[to_additive "An archimedean decidable linearly ordered `AddCommGroup` has a version of the floor: +for `a > 0`, any `g` in the group lies between some two consecutive multiples of `a`. -/"] +theorem existsUnique_zpow_near_of_one_lt {a : α} (ha : 1 < a) (g : α) : + ∃! k : ℤ, a ^ k ≤ g ∧ g < a ^ (k + 1) := by + let s : Set ℤ := { n : ℤ | a ^ n ≤ g } + obtain ⟨k, hk : g⁻¹ ≤ a ^ k⟩ := MulArchimedean.arch g⁻¹ ha + have h_ne : s.Nonempty := ⟨-k, by simpa [s] using inv_le_inv' hk⟩ + obtain ⟨k, hk⟩ := MulArchimedean.arch g ha have h_bdd : ∀ n ∈ s, n ≤ (k : ℤ) := by intro n hn - apply (zsmul_le_zsmul_iff ha).mp - rw [← natCast_zsmul] at hk + apply (zpow_le_zpow_iff ha).mp + rw [← zpow_natCast] at hk exact le_trans hn hk obtain ⟨m, hm, hm'⟩ := Int.exists_greatest_of_bdd ⟨k, h_bdd⟩ h_ne - have hm'' : g < (m + 1) • a := by + have hm'' : g < a ^ (m + 1) := by contrapose! hm' exact ⟨m + 1, hm', lt_add_one _⟩ refine ⟨m, ⟨hm, hm''⟩, fun n hn => (hm' n hn.1).antisymm <| Int.le_of_lt_add_one ?_⟩ - rw [← zsmul_lt_zsmul_iff ha] + rw [← zpow_lt_zpow_iff ha] exact lt_of_le_of_lt hm hn.2 -theorem existsUnique_zsmul_near_of_pos' {a : α} (ha : 0 < a) (g : α) : - ∃! k : ℤ, 0 ≤ g - k • a ∧ g - k • a < a := by - simpa only [sub_nonneg, add_zsmul, one_zsmul, sub_lt_iff_lt_add'] using - existsUnique_zsmul_near_of_pos ha g - -theorem existsUnique_sub_zsmul_mem_Ico {a : α} (ha : 0 < a) (b c : α) : - ∃! m : ℤ, b - m • a ∈ Set.Ico c (c + a) := by - simpa only [mem_Ico, le_sub_iff_add_le, zero_add, add_comm c, sub_lt_iff_lt_add', add_assoc] using - existsUnique_zsmul_near_of_pos' ha (b - c) - -theorem existsUnique_add_zsmul_mem_Ico {a : α} (ha : 0 < a) (b c : α) : - ∃! m : ℤ, b + m • a ∈ Set.Ico c (c + a) := +@[to_additive] +theorem existsUnique_zpow_near_of_one_lt' {a : α} (ha : 1 < a) (g : α) : + ∃! k : ℤ, 1 ≤ g / a ^ k ∧ g / a ^ k < a := by + simpa only [one_le_div', zpow_add_one, div_lt_iff_lt_mul'] using + existsUnique_zpow_near_of_one_lt ha g + +@[to_additive] +theorem existsUnique_div_zpow_mem_Ico {a : α} (ha : 1 < a) (b c : α) : + ∃! m : ℤ, b / a ^ m ∈ Set.Ico c (c * a) := by + simpa only [mem_Ico, le_div_iff_mul_le, one_mul, mul_comm c, div_lt_iff_lt_mul, mul_assoc] using + existsUnique_zpow_near_of_one_lt' ha (b / c) + +@[to_additive] +theorem existsUnique_mul_zpow_mem_Ico {a : α} (ha : 1 < a) (b c : α) : + ∃! m : ℤ, b * a ^ m ∈ Set.Ico c (c * a) := (Equiv.neg ℤ).bijective.existsUnique_iff.2 <| by - simpa only [Equiv.neg_apply, mem_Ico, neg_zsmul, ← sub_eq_add_neg, le_sub_iff_add_le, zero_add, - add_comm c, sub_lt_iff_lt_add', add_assoc] using existsUnique_zsmul_near_of_pos' ha (b - c) + simpa only [Equiv.neg_apply, mem_Ico, zpow_neg, ← div_eq_mul_inv, le_div_iff_mul_le, one_mul, + mul_comm c, div_lt_iff_lt_mul, mul_assoc] using existsUnique_zpow_near_of_one_lt' ha (b / c) -theorem existsUnique_add_zsmul_mem_Ioc {a : α} (ha : 0 < a) (b c : α) : - ∃! m : ℤ, b + m • a ∈ Set.Ioc c (c + a) := +@[to_additive] +theorem existsUnique_add_zpow_mem_Ioc {a : α} (ha : 1 < a) (b c : α) : + ∃! m : ℤ, b * a ^ m ∈ Set.Ioc c (c * a) := (Equiv.addRight (1 : ℤ)).bijective.existsUnique_iff.2 <| by - simpa only [add_zsmul, sub_lt_iff_lt_add', le_sub_iff_add_le', ← add_assoc, and_comm, mem_Ioc, - Equiv.coe_addRight, one_zsmul, add_le_add_iff_right] using - existsUnique_zsmul_near_of_pos ha (c - b) + simpa only [zpow_add_one, div_lt_iff_lt_mul', le_div_iff_mul_le', ← mul_assoc, and_comm, + mem_Ioc, Equiv.coe_addRight, mul_le_mul_iff_right] using + existsUnique_zpow_near_of_one_lt ha (c / b) -theorem existsUnique_sub_zsmul_mem_Ioc {a : α} (ha : 0 < a) (b c : α) : - ∃! m : ℤ, b - m • a ∈ Set.Ioc c (c + a) := +@[to_additive] +theorem existsUnique_sub_zpow_mem_Ioc {a : α} (ha : 1 < a) (b c : α) : + ∃! m : ℤ, b / a ^ m ∈ Set.Ioc c (c * a) := (Equiv.neg ℤ).bijective.existsUnique_iff.2 <| by - simpa only [Equiv.neg_apply, neg_zsmul, sub_neg_eq_add] using - existsUnique_add_zsmul_mem_Ioc ha b c + simpa only [Equiv.neg_apply, zpow_neg, div_inv_eq_mul] using + existsUnique_add_zpow_mem_Ioc ha b c -end LinearOrderedAddCommGroup +end LinearOrderedCommGroup theorem exists_nat_ge [OrderedSemiring α] [Archimedean α] (x : α) : ∃ n : ℕ, x ≤ n := by nontriviality α @@ -370,13 +402,18 @@ instance : Archimedean ℤ := instance : Archimedean ℚ := archimedean_iff_rat_le.2 fun q => ⟨q, by rw [Rat.cast_id]⟩ -instance Nonneg.archimedean [OrderedAddCommMonoid α] [Archimedean α] : +instance Nonneg.instArchimedean [OrderedAddCommMonoid α] [Archimedean α] : Archimedean { x : α // 0 ≤ x } := ⟨fun x y hy => let ⟨n, hr⟩ := Archimedean.arch (x : α) (hy : (0 : α) < y) ⟨n, show (x : α) ≤ (n • y : { x : α // 0 ≤ x }) by simp [*, -nsmul_eq_mul, nsmul_coe]⟩⟩ -instance : Archimedean NNRat := Nonneg.archimedean +instance Nonneg.instMulArchimedean [StrictOrderedCommSemiring α] [Archimedean α] [ExistsAddOfLE α] : + MulArchimedean { x : α // 0 ≤ x } := + ⟨fun x _ hy ↦ (pow_unbounded_of_one_lt x hy).imp fun _ h ↦ h.le⟩ + +instance : Archimedean NNRat := Nonneg.instArchimedean +instance : MulArchimedean NNRat := Nonneg.instMulArchimedean /-- A linear ordered archimedean ring is a floor ring. This is not an `instance` because in some cases we have a computable `floor` function. -/ diff --git a/Mathlib/Algebra/Order/BigOperators/Group/Multiset.lean b/Mathlib/Algebra/Order/BigOperators/Group/Multiset.lean index 19dc75bdf2115..52ae9a3e331ce 100644 --- a/Mathlib/Algebra/Order/BigOperators/Group/Multiset.lean +++ b/Mathlib/Algebra/Order/BigOperators/Group/Multiset.lean @@ -47,9 +47,10 @@ lemma all_one_of_le_one_le_of_prod_eq_one : @[to_additive] lemma prod_le_prod_of_rel_le (h : s.Rel (· ≤ ·) t) : s.prod ≤ t.prod := by - induction' h with _ _ _ _ rh _ rt - · rfl - · rw [prod_cons, prod_cons] + induction h with + | zero => rfl + | cons rh _ rt => + rw [prod_cons, prod_cons] exact mul_le_mul' rh rt @[to_additive] diff --git a/Mathlib/Algebra/Order/BigOperators/Ring/Finset.lean b/Mathlib/Algebra/Order/BigOperators/Ring/Finset.lean index f0d1340dfdcd1..9f305603865f6 100644 --- a/Mathlib/Algebra/Order/BigOperators/Ring/Finset.lean +++ b/Mathlib/Algebra/Order/BigOperators/Ring/Finset.lean @@ -82,6 +82,22 @@ lemma prod_lt_prod_of_nonempty (hf : ∀ i ∈ s, 0 < f i) (hfg : ∀ i ∈ s, f end PosMulStrictMono end CommMonoidWithZero +section OrderedSemiring + +variable [OrderedSemiring R] {f : ι → R} {s : Finset ι} + +lemma sum_sq_le_sq_sum_of_nonneg (hf : ∀ i ∈ s, 0 ≤ f i) : + ∑ i ∈ s, f i ^ 2 ≤ (∑ i ∈ s, f i) ^ 2 := by + simp only [sq, sum_mul_sum] + refine sum_le_sum fun i hi ↦ ?_ + rw [← mul_sum] + gcongr + · exact hf i hi + · exact single_le_sum hf hi + + +end OrderedSemiring + section OrderedCommSemiring variable [OrderedCommSemiring R] {f g : ι → R} {s t : Finset ι} diff --git a/Mathlib/Algebra/Order/Field/Basic.lean b/Mathlib/Algebra/Order/Field/Basic.lean index 2dee94a512441..10cb8d1525691 100644 --- a/Mathlib/Algebra/Order/Field/Basic.lean +++ b/Mathlib/Algebra/Order/Field/Basic.lean @@ -9,7 +9,6 @@ import Mathlib.Algebra.Order.Ring.Abs import Mathlib.Order.Bounds.OrderIso import Mathlib.Tactic.Bound.Attribute import Mathlib.Tactic.Positivity.Core -import Mathlib.Algebra.Order.Field.Unbundled.Basic /-! # Lemmas about linear ordered (semi)fields @@ -38,43 +37,13 @@ def OrderIso.mulRight₀ (a : α) (ha : 0 < a) : α ≃o α := ### Relating one division with another term. -/ - -theorem le_div_iff (hc : 0 < c) : a ≤ b / c ↔ a * c ≤ b := - ⟨fun h => div_mul_cancel₀ b (ne_of_lt hc).symm ▸ mul_le_mul_of_nonneg_right h hc.le, fun h => - calc - a = a * c * (1 / c) := mul_mul_div a (ne_of_lt hc).symm - _ ≤ b * (1 / c) := mul_le_mul_of_nonneg_right h (one_div_pos (α := α) |>.2 hc).le - _ = b / c := (div_eq_mul_one_div b c).symm - ⟩ - -theorem le_div_iff' (hc : 0 < c) : a ≤ b / c ↔ c * a ≤ b := by rw [mul_comm, le_div_iff hc] - -theorem div_le_iff (hb : 0 < b) : a / b ≤ c ↔ a ≤ c * b := - ⟨fun h => - calc - a = a / b * b := by rw [div_mul_cancel₀ _ (ne_of_lt hb).symm] - _ ≤ c * b := mul_le_mul_of_nonneg_right h hb.le - , - fun h => - calc - a / b = a * (1 / b) := div_eq_mul_one_div a b - _ ≤ c * b * (1 / b) := mul_le_mul_of_nonneg_right h (one_div_pos (α := α) |>.2 hb).le - _ = c * b / b := (div_eq_mul_one_div (c * b) b).symm - _ = c := by refine (div_eq_iff (ne_of_gt hb)).mpr rfl - ⟩ - -theorem div_le_iff' (hb : 0 < b) : a / b ≤ c ↔ a ≤ b * c := by rw [mul_comm, div_le_iff hb] - -lemma div_le_comm₀ (hb : 0 < b) (hc : 0 < c) : a / b ≤ c ↔ a / c ≤ b := by - rw [div_le_iff hb, div_le_iff' hc] - theorem lt_div_iff (hc : 0 < c) : a < b / c ↔ a * c < b := - lt_iff_lt_of_le_iff_le <| div_le_iff hc + 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] theorem div_lt_iff (hc : 0 < c) : b / c < a ↔ b < a * c := - lt_iff_lt_of_le_iff_le (le_div_iff hc) + lt_iff_lt_of_le_iff_le (le_div_iff₀ hc) theorem div_lt_iff' (hc : 0 < c) : b / c < a ↔ b < c * a := by rw [mul_comm, div_lt_iff hc] @@ -83,7 +52,7 @@ lemma div_lt_comm₀ (hb : 0 < b) (hc : 0 < c) : a / b < c ↔ a / c < b := by 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 + exact div_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] @@ -106,11 +75,11 @@ theorem mul_inv_lt_iff' (h : 0 < b) : a * b⁻¹ < c ↔ a < c * b := by rw [mul 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 + exact div_le_iff₀ 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 + exact div_le_iff₀' ha theorem inv_pos_lt_iff_one_lt_mul (ha : 0 < a) : a⁻¹ < b ↔ 1 < b * a := by rw [inv_eq_one_div] @@ -124,13 +93,13 @@ theorem inv_pos_lt_iff_one_lt_mul' (ha : 0 < a) : a⁻¹ < b ↔ 1 < a * b := by 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'] + · rwa [div_le_iff₀ hb'] /-- 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 + · rwa [le_div_iff₀ hc] at h @[bound] theorem div_le_one_of_le (h : a ≤ b) (hb : 0 ≤ b) : a / b ≤ 1 := @@ -150,22 +119,22 @@ lemma inv_mul_le_one_of_le (h : a ≤ b) (hb : 0 ≤ b) : b⁻¹ * a ≤ 1 := by @[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] + rwa [← one_div a, le_div_iff₀' ha, ← div_eq_mul_inv, div_le_iff₀ (ha.trans_le h), one_mul] /-- 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] + rw [← one_div, div_le_iff₀ ha, ← div_eq_inv_mul, le_div_iff₀ hb, one_mul] /-- 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] + rw [← inv_le_inv hb (inv_pos.2 ha), inv_inv] 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 + (inv_le ha ((inv_pos.2 ha).trans_le h)).1 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] + rw [← inv_le_inv (inv_pos.2 hb) ha, inv_inv] /-- 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 := @@ -181,7 +150,7 @@ theorem inv_lt (ha : 0 < a) (hb : 0 < b) : a⁻¹ < b ↔ b⁻¹ < a := lt_iff_lt_of_le_iff_le (le_inv hb ha) 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 + (inv_lt ha ((inv_pos.2 ha).trans h)).1 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) @@ -200,15 +169,15 @@ theorem one_le_inv (h₁ : 0 < a) (h₂ : a ≤ 1) : 1 ≤ a⁻¹ := by rwa [le_inv (@zero_lt_one α _ _ _ _ _) h₁, inv_one] 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⟩ + ⟨fun h₁ => inv_inv a ▸ one_lt_inv (inv_pos.2 h₀) h₁, inv_lt_one⟩ 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 [ha, (inv_nonpos.2 ha).trans_lt zero_lt_one] · simp only [ha.not_le, false_or_iff, inv_lt_one_iff_of_pos ha] theorem one_lt_inv_iff : 1 < a⁻¹ ↔ 0 < a ∧ a < 1 := - ⟨fun h => ⟨inv_pos (α := α) |>.1 (zero_lt_one.trans h), + ⟨fun h => ⟨inv_pos.1 (zero_lt_one.trans h), inv_inv a ▸ inv_lt_one h⟩, and_imp.2 one_lt_inv⟩ theorem inv_le_one_iff : a⁻¹ ≤ 1 ↔ a ≤ 0 ∨ 1 ≤ a := by @@ -217,7 +186,7 @@ theorem inv_le_one_iff : a⁻¹ ≤ 1 ↔ a ≤ 0 ∨ 1 ≤ a := by · simp only [Ne.le_iff_lt (Ne.symm ha), Ne.le_iff_lt (mt inv_eq_one.1 ha), inv_lt_one_iff] theorem one_le_inv_iff : 1 ≤ a⁻¹ ↔ 0 < a ∧ a ≤ 1 := - ⟨fun h => ⟨inv_pos (α := α) |>.1 (zero_lt_one.trans_le h), + ⟨fun h => ⟨inv_pos.1 (zero_lt_one.trans_le h), inv_inv a ▸ inv_le_one h⟩, and_imp.2 one_le_inv⟩ /-! @@ -228,12 +197,12 @@ theorem one_le_inv_iff : 1 ≤ a⁻¹ ↔ 0 < a ∧ a ≤ 1 := @[mono, gcongr, bound] lemma div_le_div_of_nonneg_right (hab : a ≤ b) (hc : 0 ≤ c) : a / c ≤ b / c := by rw [div_eq_mul_one_div a c, div_eq_mul_one_div b c] - exact mul_le_mul_of_nonneg_right hab (one_div_nonneg (α := α) |>.2 hc) + exact mul_le_mul_of_nonneg_right hab (one_div_nonneg.2 hc) @[gcongr, bound] lemma div_lt_div_of_pos_right (h : a < b) (hc : 0 < c) : a / c < b / c := by rw [div_eq_mul_one_div a c, div_eq_mul_one_div b c] - exact mul_lt_mul_of_pos_right h (one_div_pos (α := α) |>.2 hc) + exact mul_lt_mul_of_pos_right h (one_div_pos.2 hc) -- Not a `mono` lemma b/c `div_le_div` is strictly more general @[gcongr] @@ -271,7 +240,7 @@ theorem div_lt_div_iff (b0 : 0 < b) (d0 : 0 < d) : a / b < c / d ↔ a * d < c * 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] + rw [le_div_iff₀ d0, div_mul_eq_mul_div, div_le_iff₀ b0] @[mono, gcongr, bound] theorem div_le_div (hc : 0 ≤ c) (hac : a ≤ c) (hd : 0 < d) (hbd : d ≤ b) : a / b ≤ c / d := by @@ -302,9 +271,9 @@ theorem div_lt_self (ha : 0 < a) (hb : 1 < b) : a / b < a := by theorem le_div_self (ha : 0 ≤ a) (hb₀ : 0 < b) (hb₁ : b ≤ 1) : a ≤ a / b := by simpa only [div_one] using div_le_div_of_nonneg_left ha hb₀ hb₁ -theorem one_le_div (hb : 0 < b) : 1 ≤ a / b ↔ b ≤ a := by rw [le_div_iff hb, one_mul] +theorem one_le_div (hb : 0 < b) : 1 ≤ a / b ↔ b ≤ a := by rw [le_div_iff₀ hb, one_mul] -theorem div_le_one (hb : 0 < b) : a / b ≤ 1 ↔ a ≤ b := by rw [div_le_iff hb, one_mul] +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] @@ -368,7 +337,7 @@ theorem one_half_pos : (0 : α) < 1 / 2 := @[simp] theorem half_le_self_iff : a / 2 ≤ a ↔ 0 ≤ a := by - rw [div_le_iff (zero_lt_two' α), mul_two, le_add_iff_nonneg_left] + rw [div_le_iff₀ (zero_lt_two' α), mul_two, le_add_iff_nonneg_left] @[simp] theorem half_lt_self_iff : a / 2 < a ↔ 0 < a := by @@ -402,16 +371,16 @@ theorem add_thirds (a : α) : a / 3 + a / 3 + a / 3 = a := by simp only [div_eq_mul_inv, mul_pos_iff_of_pos_left ha, inv_pos] @[simp] lemma div_pos_iff_of_pos_right (hb : 0 < b) : 0 < a / b ↔ 0 < a := by - simp only [div_eq_mul_inv, mul_pos_iff_of_pos_right (inv_pos (α := α) |>.2 hb)] + simp only [div_eq_mul_inv, mul_pos_iff_of_pos_right (inv_pos.2 hb)] theorem mul_le_mul_of_mul_div_le (h : a * (b / c) ≤ d) (hc : 0 < c) : b * a ≤ d * c := by rw [← mul_div_assoc] at h - rwa [mul_comm b, ← div_le_iff hc] + rwa [mul_comm b, ← div_le_iff₀ hc] theorem div_mul_le_div_mul_of_div_le_div (h : a / b ≤ c / d) (he : 0 ≤ e) : a / (b * e) ≤ c / (d * e) := by rw [div_mul_eq_div_mul_one_div, div_mul_eq_div_mul_one_div] - exact mul_le_mul_of_nonneg_right h (one_div_nonneg (α := α) |>.2 he) + exact mul_le_mul_of_nonneg_right h (one_div_nonneg.2 he) 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)) @@ -421,7 +390,7 @@ theorem exists_pos_mul_lt {a : α} (h : 0 < a) (b : α) : ∃ c : α, 0 < c ∧ 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 @@ -434,7 +403,7 @@ theorem Monotone.div_const {β : Type*} [Preorder β] {f : β → α} (hf : Mono theorem StrictMono.div_const {β : Type*} [Preorder β] {f : β → α} (hf : StrictMono f) {c : α} (hc : 0 < c) : StrictMono fun x => f x / c := by - simpa only [div_eq_mul_inv] using hf.mul_const (inv_pos (α := α) |>.2 hc) + simpa only [div_eq_mul_inv] using hf.mul_const (inv_pos.2 hc) -- see Note [lower instance priority] instance (priority := 100) LinearOrderedSemiField.toDenselyOrdered : DenselyOrdered α where @@ -543,7 +512,7 @@ theorem div_le_iff_of_neg (hc : c < 0) : b / c ≤ a ↔ a * c ≤ b := ⟨fun h => div_mul_cancel₀ b (ne_of_lt hc) ▸ mul_le_mul_of_nonpos_right h hc.le, fun h => calc a = a * c * (1 / c) := mul_mul_div a (ne_of_lt hc) - _ ≥ b * (1 / c) := mul_le_mul_of_nonpos_right h (one_div_neg (α := α) |>.2 hc).le + _ ≥ b * (1 / c) := mul_le_mul_of_nonpos_right h (one_div_neg.2 hc).le _ = b / c := (div_eq_mul_one_div b c).symm ⟩ @@ -551,7 +520,7 @@ theorem div_le_iff_of_neg' (hc : c < 0) : b / c ≤ a ↔ c * a ≤ b := by rw [mul_comm, div_le_iff_of_neg hc] theorem le_div_iff_of_neg (hc : c < 0) : a ≤ b / c ↔ b ≤ a * c := by - rw [← neg_neg c, mul_neg, div_neg, le_neg, div_le_iff (neg_pos.2 hc), neg_mul] + rw [← neg_neg c, mul_neg, div_neg, le_neg, div_le_iff₀ (neg_pos.2 hc), neg_mul] theorem le_div_iff_of_neg' (hc : c < 0) : a ≤ b / c ↔ b ≤ c * a := by rw [mul_comm, le_div_iff_of_neg hc] @@ -578,10 +547,10 @@ theorem inv_le_inv_of_neg (ha : a < 0) (hb : b < 0) : a⁻¹ ≤ b⁻¹ ↔ b rw [← one_div, div_le_iff_of_neg ha, ← div_eq_inv_mul, div_le_iff_of_neg hb, one_mul] theorem inv_le_of_neg (ha : a < 0) (hb : b < 0) : a⁻¹ ≤ b ↔ b⁻¹ ≤ a := by - rw [← inv_le_inv_of_neg hb (inv_lt_zero (α := α) |>.2 ha), inv_inv] + rw [← inv_le_inv_of_neg hb (inv_lt_zero.2 ha), inv_inv] theorem le_inv_of_neg (ha : a < 0) (hb : b < 0) : a ≤ b⁻¹ ↔ b ≤ a⁻¹ := by - rw [← inv_le_inv_of_neg (inv_lt_zero (α := α) |>.2 hb) ha, inv_inv] + rw [← inv_le_inv_of_neg (inv_lt_zero.2 hb) ha, inv_inv] theorem inv_lt_inv_of_neg (ha : a < 0) (hb : b < 0) : a⁻¹ < b⁻¹ ↔ b < a := lt_iff_lt_of_le_iff_le (inv_le_inv_of_neg hb ha) @@ -644,11 +613,11 @@ theorem inv_antitoneOn_Icc_left (hb : b < 0) : theorem div_le_div_of_nonpos_of_le (hc : c ≤ 0) (h : b ≤ a) : a / c ≤ b / c := by rw [div_eq_mul_one_div a c, div_eq_mul_one_div b c] - exact mul_le_mul_of_nonpos_right h (one_div_nonpos (α := α) |>.2 hc) + exact mul_le_mul_of_nonpos_right h (one_div_nonpos.2 hc) theorem div_lt_div_of_neg_of_lt (hc : c < 0) (h : b < a) : a / c < b / c := by rw [div_eq_mul_one_div a c, div_eq_mul_one_div b c] - exact mul_lt_mul_of_neg_right h (one_div_neg (α := α) |>.2 hc) + exact mul_lt_mul_of_neg_right h (one_div_neg.2 hc) theorem div_le_div_right_of_neg (hc : c < 0) : a / c ≤ b / c ↔ b ≤ a := ⟨le_imp_le_of_lt_imp_lt <| div_lt_div_of_neg_of_lt hc, div_le_div_of_nonpos_of_le <| hc.le⟩ @@ -754,7 +723,7 @@ 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_le_inv_of_le (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`. diff --git a/Mathlib/Algebra/Order/Field/Power.lean b/Mathlib/Algebra/Order/Field/Power.lean index 8cb0dc8de386a..8dfd3676717c3 100644 --- a/Mathlib/Algebra/Order/Field/Power.lean +++ b/Mathlib/Algebra/Order/Field/Power.lean @@ -133,7 +133,7 @@ protected lemma Odd.zpow_nonneg_iff (hn : Odd n) : 0 ≤ a ^ n ↔ 0 ≤ a := theorem Odd.zpow_nonpos_iff (hn : Odd n) : a ^ n ≤ 0 ↔ a ≤ 0 := by rw [le_iff_lt_or_eq, le_iff_lt_or_eq, hn.zpow_neg_iff, zpow_eq_zero_iff] rintro rfl - exact Int.odd_iff_not_even.1 hn even_zero + exact Int.not_even_iff_odd.2 hn even_zero lemma Odd.zpow_pos_iff (hn : Odd n) : 0 < a ^ n ↔ 0 < a := lt_iff_lt_of_le_iff_le hn.zpow_nonpos_iff @@ -148,7 +148,7 @@ theorem Even.zpow_abs {p : ℤ} (hp : Even p) (a : α) : |a| ^ p = a ^ p := by /-- Bernoulli's inequality reformulated to estimate `(n : α)`. -/ theorem Nat.cast_le_pow_sub_div_sub (H : 1 < a) (n : ℕ) : (n : α) ≤ (a ^ n - 1) / (a - 1) := - (le_div_iff (sub_pos.2 H)).2 <| + (le_div_iff₀ (sub_pos.2 H)).2 <| le_sub_left_of_add_le <| one_add_mul_sub_le_pow ((neg_le_self zero_le_one).trans H.le) _ /-- For any `a > 1` and a natural `n` we have `n ≤ a ^ n / (a - 1)`. See also diff --git a/Mathlib/Algebra/Order/Field/Unbundled/Basic.lean b/Mathlib/Algebra/Order/Field/Unbundled/Basic.lean deleted file mode 100644 index 19f180e9e1699..0000000000000 --- a/Mathlib/Algebra/Order/Field/Unbundled/Basic.lean +++ /dev/null @@ -1,63 +0,0 @@ -/- -Copyright (c) 2014 Robert Y. Lewis. All rights reserved. -Released under Apache 2.0 license as described in the file LICENSE. -Authors: Robert Y. Lewis, Leonardo de Moura, Mario Carneiro, Floris van Doorn --/ -import Mathlib.Algebra.Field.Defs -import Mathlib.Algebra.GroupWithZero.Basic -import Mathlib.Algebra.Order.Ring.Unbundled.Basic - -/-! -# Basic facts for unbundled linear ordered (semi)fields - --/ - --- Guard against import creep. -assert_not_exists OrderedCommMonoid -assert_not_exists MonoidHom - -variable {α : Type*} - -variable [Semifield α] [LinearOrder α] [PosMulReflectLT α] [ZeroLEOneClass α] {a b : α} - -@[simp] lemma inv_pos : 0 < a⁻¹ ↔ 0 < a := - suffices ∀ a : α, 0 < a → 0 < a⁻¹ from ⟨fun h ↦ inv_inv a ▸ this _ h, this a⟩ - fun a ha ↦ flip lt_of_mul_lt_mul_left ha.le <| by simp [ne_of_gt ha, zero_lt_one] - -alias ⟨_, inv_pos_of_pos⟩ := inv_pos - -@[simp] lemma inv_nonneg : 0 ≤ a⁻¹ ↔ 0 ≤ a := by simp only [le_iff_eq_or_lt, inv_pos, zero_eq_inv] - -alias ⟨_, inv_nonneg_of_nonneg⟩ := inv_nonneg - -@[simp] lemma inv_lt_zero : 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] - -lemma one_div_pos : 0 < 1 / a ↔ 0 < a := inv_eq_one_div a ▸ inv_pos - -lemma one_div_neg : 1 / a < 0 ↔ a < 0 := inv_eq_one_div a ▸ inv_lt_zero - -lemma one_div_nonneg : 0 ≤ 1 / a ↔ 0 ≤ a := inv_eq_one_div a ▸ inv_nonneg - -lemma one_div_nonpos : 1 / a ≤ 0 ↔ a ≤ 0 := inv_eq_one_div a ▸ inv_nonpos - -lemma div_pos [PosMulStrictMono α] (ha : 0 < a) (hb : 0 < b) : 0 < a / b := by - rw [div_eq_mul_inv]; exact mul_pos ha (inv_pos.2 hb) - -lemma div_nonneg [PosMulMono α] (ha : 0 ≤ a) (hb : 0 ≤ b) : 0 ≤ a / b := by - rw [div_eq_mul_inv]; exact mul_nonneg ha (inv_nonneg.2 hb) - -lemma div_nonpos_of_nonpos_of_nonneg [MulPosMono α] (ha : a ≤ 0) (hb : 0 ≤ b) : a / b ≤ 0 := by - rw [div_eq_mul_inv]; exact mul_nonpos_of_nonpos_of_nonneg ha (inv_nonneg.2 hb) - -lemma div_nonpos_of_nonneg_of_nonpos [PosMulMono α] (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) - -lemma zpow_nonneg [PosMulMono α] (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 α] (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 _ diff --git a/Mathlib/Algebra/Order/Floor.lean b/Mathlib/Algebra/Order/Floor.lean index fd12802ad8138..0431b57d759fd 100644 --- a/Mathlib/Algebra/Order/Floor.lean +++ b/Mathlib/Algebra/Order/Floor.lean @@ -9,7 +9,6 @@ import Mathlib.Algebra.Group.Int import Mathlib.Data.Int.Lemmas import Mathlib.Data.Nat.Cast.Order.Field import Mathlib.Data.Set.Subsingleton -import Mathlib.Init.Data.Nat.Lemmas import Mathlib.Order.GaloisConnection import Mathlib.Tactic.Abel import Mathlib.Tactic.Linarith @@ -151,6 +150,7 @@ theorem floor_le (ha : 0 ≤ a) : (⌊a⌋₊ : α) ≤ a := theorem lt_succ_floor (a : α) : a < ⌊a⌋₊.succ := lt_of_floor_lt <| Nat.lt_succ_self _ +@[bound] theorem lt_floor_add_one (a : α) : a < ⌊a⌋₊ + 1 := by simpa using lt_succ_floor a @[simp] @@ -183,7 +183,7 @@ theorem floor_mono : Monotone (floor : α → ℕ) := fun a b h => by exact Nat.zero_le _ · exact le_floor ((floor_le ha).trans h) -@[gcongr] lemma floor_le_floor (hab : a ≤ b) : ⌊a⌋₊ ≤ ⌊b⌋₊ := floor_mono hab +@[gcongr, bound] lemma floor_le_floor (hab : a ≤ b) : ⌊a⌋₊ ≤ ⌊b⌋₊ := floor_mono hab theorem le_floor_iff' (hn : n ≠ 0) : n ≤ ⌊a⌋₊ ↔ (n : α) ≤ a := by obtain ha | ha := le_total a 0 @@ -259,10 +259,12 @@ theorem add_one_le_ceil_iff : n + 1 ≤ ⌈a⌉₊ ↔ (n : α) < a := by theorem one_le_ceil_iff : 1 ≤ ⌈a⌉₊ ↔ 0 < a := by rw [← zero_add 1, Nat.add_one_le_ceil_iff, Nat.cast_zero] +@[bound] theorem ceil_le_floor_add_one (a : α) : ⌈a⌉₊ ≤ ⌊a⌋₊ + 1 := by rw [ceil_le, Nat.cast_add, Nat.cast_one] exact (lt_floor_add_one a).le +@[bound] theorem le_ceil (a : α) : a ≤ ⌈a⌉₊ := ceil_le.1 le_rfl @@ -280,7 +282,7 @@ theorem ceil_natCast (n : ℕ) : ⌈(n : α)⌉₊ = n := theorem ceil_mono : Monotone (ceil : α → ℕ) := gc_ceil_coe.monotone_l -@[gcongr] lemma ceil_le_ceil (hab : a ≤ b) : ⌈a⌉₊ ≤ ⌈b⌉₊ := ceil_mono hab +@[gcongr, bound] lemma ceil_le_ceil (hab : a ≤ b) : ⌈a⌉₊ ≤ ⌈b⌉₊ := ceil_mono hab @[simp] theorem ceil_zero : ⌈(0 : α)⌉₊ = 0 := by rw [← Nat.cast_zero, ceil_natCast] @@ -304,6 +306,7 @@ theorem lt_of_ceil_lt (h : ⌈a⌉₊ < n) : a < n := theorem le_of_ceil_le (h : ⌈a⌉₊ ≤ n) : a ≤ n := (le_ceil a).trans (Nat.cast_le.2 h) +@[bound] theorem floor_le_ceil (a : α) : ⌊a⌋₊ ≤ ⌈a⌉₊ := by obtain ha | ha := le_total a 0 · rw [floor_of_nonpos ha] @@ -446,6 +449,7 @@ theorem ceil_add_ofNat (ha : 0 ≤ a) (n : ℕ) [n.AtLeastTwo] : theorem ceil_lt_add_one (ha : 0 ≤ a) : (⌈a⌉₊ : α) < a + 1 := lt_ceil.1 <| (Nat.lt_succ_self _).trans_le (ceil_add_one ha).ge +@[bound] theorem ceil_add_le (a b : α) : ⌈a + b⌉₊ ≤ ⌈a⌉₊ + ⌈b⌉₊ := by rw [ceil_le, Nat.cast_add] exact _root_.add_le_add (le_ceil _) (le_ceil _) @@ -456,6 +460,7 @@ section LinearOrderedRing variable [LinearOrderedRing α] [FloorSemiring α] +@[bound] theorem sub_one_lt_floor (a : α) : a - 1 < ⌊a⌋₊ := sub_lt_iff_lt_add.2 <| lt_floor_add_one a @@ -607,6 +612,7 @@ theorem le_floor : z ≤ ⌊a⌋ ↔ (z : α) ≤ a := theorem floor_lt : ⌊a⌋ < z ↔ a < z := lt_iff_lt_of_le_iff_le le_floor +@[bound] theorem floor_le (a : α) : (⌊a⌋ : α) ≤ a := gc_coe_floor.l_u_le a @@ -619,6 +625,7 @@ theorem floor_le_sub_one_iff : ⌊a⌋ ≤ z - 1 ↔ a < z := by rw [← floor_l theorem floor_le_neg_one_iff : ⌊a⌋ ≤ -1 ↔ a < 0 := by rw [← zero_sub (1 : ℤ), floor_le_sub_one_iff, cast_zero] +@[bound] theorem floor_nonpos (ha : a ≤ 0) : ⌊a⌋ ≤ 0 := by rw [← @cast_le α, Int.cast_zero] exact (floor_le a).trans ha @@ -626,11 +633,11 @@ theorem floor_nonpos (ha : a ≤ 0) : ⌊a⌋ ≤ 0 := by theorem lt_succ_floor (a : α) : a < ⌊a⌋.succ := floor_lt.1 <| Int.lt_succ_self _ -@[simp] +@[simp, bound] theorem lt_floor_add_one (a : α) : a < ⌊a⌋ + 1 := by simpa only [Int.succ, Int.cast_add, Int.cast_one] using lt_succ_floor a -@[simp] +@[simp, bound] theorem sub_one_lt_floor (a : α) : a - 1 < ⌊a⌋ := sub_lt_iff_lt_add.2 (lt_floor_add_one a) @@ -656,7 +663,7 @@ theorem floor_one : ⌊(1 : α)⌋ = 1 := by rw [← cast_one, floor_intCast] theorem floor_mono : Monotone (floor : α → ℤ) := gc_coe_floor.monotone_u -@[gcongr] lemma floor_le_floor (hab : a ≤ b) : ⌊a⌋ ≤ ⌊b⌋ := floor_mono hab +@[gcongr, bound] lemma floor_le_floor (hab : a ≤ b) : ⌊a⌋ ≤ ⌊b⌋ := floor_mono hab theorem floor_pos : 0 < ⌊a⌋ ↔ 1 ≤ a := by -- Porting note: broken `convert le_floor` @@ -672,10 +679,12 @@ theorem floor_add_one (a : α) : ⌊a + 1⌋ = ⌊a⌋ + 1 := by -- Porting note: broken `convert floor_add_int a 1` rw [← cast_one, floor_add_int] +@[bound] theorem le_floor_add (a b : α) : ⌊a⌋ + ⌊b⌋ ≤ ⌊a + b⌋ := by rw [le_floor, Int.cast_add] exact add_le_add (floor_le _) (floor_le _) +@[bound] theorem le_floor_add_floor (a b : α) : ⌊a + b⌋ - 1 ≤ ⌊a⌋ + ⌊b⌋ := by rw [← sub_le_iff_le_add, le_floor, Int.cast_sub, sub_le_comm, Int.cast_sub, Int.cast_one] refine le_trans ?_ (sub_one_lt_floor _).le @@ -972,7 +981,7 @@ theorem fract_div_mul_self_add_zsmul_eq (a b : k) (ha : a ≠ 0) : rw [zsmul_eq_mul, ← add_mul, fract_add_floor, div_mul_cancel₀ b ha] theorem sub_floor_div_mul_nonneg (a : k) (hb : 0 < b) : 0 ≤ a - ⌊a / b⌋ * b := - sub_nonneg_of_le <| (le_div_iff hb).1 <| floor_le _ + sub_nonneg_of_le <| (le_div_iff₀ hb).1 <| floor_le _ theorem sub_floor_div_mul_lt (a : k) (hb : 0 < b) : a - ⌊a / b⌋ * b < b := sub_lt_iff_lt_add.2 <| by @@ -1010,7 +1019,7 @@ theorem fract_div_intCast_eq_div_intCast_mod {m : ℤ} {n : ℕ} : let q := ⌈↑m₀ / (n : k)⌉ let m₁ := q * ↑n - (↑m₀ : ℤ) have hm₁ : 0 ≤ m₁ := by - simpa [m₁, ← @cast_le k, ← div_le_iff hn] using FloorRing.gc_ceil_coe.le_u_l _ + simpa [m₁, ← @cast_le k, ← div_le_iff₀ hn] using FloorRing.gc_ceil_coe.le_u_l _ calc fract ((Int.cast (-(m₀ : ℤ)) : k) / (n : k)) -- Porting note: the `rw [cast_neg, cast_natCast]` was `push_cast` @@ -1052,6 +1061,7 @@ theorem add_one_le_ceil_iff : z + 1 ≤ ⌈a⌉ ↔ (z : α) < a := by rw [← l theorem one_le_ceil_iff : 1 ≤ ⌈a⌉ ↔ 0 < a := by rw [← zero_add (1 : ℤ), add_one_le_ceil_iff, cast_zero] +@[bound] theorem ceil_le_floor_add_one (a : α) : ⌈a⌉ ≤ ⌊a⌋ + 1 := by rw [ceil_le, Int.cast_add, Int.cast_one] exact (lt_floor_add_one a).le @@ -1075,7 +1085,7 @@ theorem ceil_ofNat (n : ℕ) [n.AtLeastTwo] : ⌈(no_index (OfNat.ofNat n : α)) theorem ceil_mono : Monotone (ceil : α → ℤ) := gc_ceil_coe.monotone_l -@[gcongr] lemma ceil_le_ceil (hab : a ≤ b) : ⌈a⌉ ≤ ⌈b⌉ := ceil_mono hab +@[gcongr, bound] lemma ceil_le_ceil (hab : a ≤ b) : ⌈a⌉ ≤ ⌈b⌉ := ceil_mono hab @[simp] theorem ceil_add_int (a : α) (z : ℤ) : ⌈a + z⌉ = ⌈a⌉ + z := by @@ -1114,14 +1124,17 @@ theorem ceil_sub_ofNat (a : α) (n : ℕ) [n.AtLeastTwo] : ⌈a - (no_index (OfNat.ofNat n))⌉ = ⌈a⌉ - OfNat.ofNat n := ceil_sub_nat a n +@[bound] theorem ceil_lt_add_one (a : α) : (⌈a⌉ : α) < a + 1 := by rw [← lt_ceil, ← Int.cast_one, ceil_add_int] apply lt_add_one +@[bound] theorem ceil_add_le (a b : α) : ⌈a + b⌉ ≤ ⌈a⌉ + ⌈b⌉ := by rw [ceil_le, Int.cast_add] exact add_le_add (le_ceil _) (le_ceil _) +@[bound] theorem ceil_add_ceil_le (a b : α) : ⌈a⌉ + ⌈b⌉ ≤ ⌈a + b⌉ + 1 := by rw [← le_sub_iff_add_le, ceil_le, Int.cast_sub, Int.cast_add, Int.cast_one, le_sub_comm] refine (ceil_lt_add_one _).le.trans ?_ @@ -1137,6 +1150,7 @@ theorem ceil_zero : ⌈(0 : α)⌉ = 0 := by rw [← cast_zero, ceil_intCast] @[simp] theorem ceil_one : ⌈(1 : α)⌉ = 1 := by rw [← cast_one, ceil_intCast] +@[bound] theorem ceil_nonneg (ha : 0 ≤ a) : 0 ≤ ⌈a⌉ := mod_cast ha.trans (le_ceil a) theorem ceil_eq_iff : ⌈a⌉ = z ↔ ↑z - 1 < a ∧ a ≤ z := by @@ -1152,9 +1166,11 @@ theorem ceil_eq_on_Ioc (z : ℤ) : ∀ a ∈ Set.Ioc (z - 1 : α) z, ⌈a⌉ = z theorem ceil_eq_on_Ioc' (z : ℤ) : ∀ a ∈ Set.Ioc (z - 1 : α) z, (⌈a⌉ : α) = z := fun a ha => mod_cast ceil_eq_on_Ioc z a ha +@[bound] theorem floor_le_ceil (a : α) : ⌊a⌋ ≤ ⌈a⌉ := cast_le.1 <| (floor_le _).trans <| le_ceil _ +@[bound] theorem floor_lt_ceil_of_lt {a b : α} (h : a < b) : ⌊a⌋ < ⌈b⌉ := cast_lt.1 <| (floor_le a).trans_lt <| h.trans_le <| le_ceil b @@ -1391,10 +1407,12 @@ theorem abs_sub_round_div_natCast_eq {m n : ℕ} : rw [abs_sub_round_eq_min, Nat.cast_min, ← min_div_div_right hn'.le, fract_div_natCast_eq_div_natCast_mod, Nat.cast_sub (m.mod_lt hn).le, sub_div, div_self hn'.ne'] +@[bound] theorem sub_half_lt_round (x : α) : x - 1 / 2 < round x := by rw [round_eq x, show x - 1 / 2 = x + 1 / 2 - 1 by nlinarith] exact Int.sub_one_lt_floor (x + 1 / 2) +@[bound] theorem round_le_add_half (x : α) : round x ≤ x + 1 / 2 := by rw [round_eq x] exact Int.floor_le (x + 1 / 2) @@ -1492,26 +1510,20 @@ theorem Nat.ceil_int : (Nat.ceil : ℤ → ℕ) = Int.toNat := variable {a : α} -theorem Int.ofNat_floor_eq_floor (ha : 0 ≤ a) : (⌊a⌋₊ : ℤ) = ⌊a⌋ := by +theorem Int.natCast_floor_eq_floor (ha : 0 ≤ a) : (⌊a⌋₊ : ℤ) = ⌊a⌋ := by rw [← Int.floor_toNat, Int.toNat_of_nonneg (Int.floor_nonneg.2 ha)] -theorem Int.ofNat_ceil_eq_ceil (ha : 0 ≤ a) : (⌈a⌉₊ : ℤ) = ⌈a⌉ := by +theorem Int.natCast_ceil_eq_ceil (ha : 0 ≤ a) : (⌈a⌉₊ : ℤ) = ⌈a⌉ := by rw [← Int.ceil_toNat, Int.toNat_of_nonneg (Int.ceil_nonneg ha)] theorem natCast_floor_eq_intCast_floor (ha : 0 ≤ a) : (⌊a⌋₊ : α) = ⌊a⌋ := by - rw [← Int.ofNat_floor_eq_floor ha, Int.cast_natCast] + rw [← Int.natCast_floor_eq_floor ha, Int.cast_natCast] -theorem natCast_ceil_eq_intCast_ceil (ha : 0 ≤ a) : (⌈a⌉₊ : α) = ⌈a⌉ := by - rw [← Int.ofNat_ceil_eq_ceil ha, Int.cast_natCast] +theorem natCast_ceil_eq_intCast_ceil (ha : 0 ≤ a) : (⌈a⌉₊ : α) = ⌈a⌉ := by + rw [← Int.natCast_ceil_eq_ceil ha, Int.cast_natCast] -@[deprecated (since := "2024-02-14")] alias Nat.cast_floor_eq_int_floor := Int.ofNat_floor_eq_floor -@[deprecated (since := "2024-02-14")] alias Nat.cast_ceil_eq_int_ceil := Int.ofNat_ceil_eq_ceil - -@[deprecated (since := "2024-02-14")] -alias Nat.cast_floor_eq_cast_int_floor := natCast_floor_eq_intCast_floor - -@[deprecated (since := "2024-02-14")] -alias Nat.cast_ceil_eq_cast_int_ceil := natCast_ceil_eq_intCast_ceil +@[deprecated (since := "2024-08-20")] alias Int.ofNat_floor_eq_floor := natCast_floor_eq_floor +@[deprecated (since := "2024-08-20")] alias Int.ofNat_ceil_eq_ceil := natCast_ceil_eq_ceil end FloorRingToSemiring @@ -1587,3 +1599,5 @@ def evalIntCeil : PositivityExt where eval {u α} _zα _pα e := do | _, _, _ => throwError "failed to match on Int.ceil application" end Mathlib.Meta.Positivity + +set_option linter.style.longFile 1700 diff --git a/Mathlib/Algebra/Order/Group/Action/Synonym.lean b/Mathlib/Algebra/Order/Group/Action/Synonym.lean new file mode 100644 index 0000000000000..9a2ab42258ab9 --- /dev/null +++ b/Mathlib/Algebra/Order/Group/Action/Synonym.lean @@ -0,0 +1,88 @@ +/- +Copyright (c) 2021 Yaël Dillies. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yaël Dillies +-/ +import Mathlib.Algebra.Group.Action.Defs +import Mathlib.Algebra.Order.Group.Synonym + +/-! +# Actions by and on order synonyms + +This PR transfers group action instances from a type `α` to `αᵒᵈ` and `Lex α`. + +## See also + +* `Mathlib.Algebra.Order.GroupWithZero.Action.Synonym` +* `Mathlib.Algebra.Order.Module.Synonym` +-/ + +variable {M N α : Type*} + +namespace OrderDual + +@[to_additive] +instance instMulAction [Monoid M] [MulAction M α] : MulAction Mᵒᵈ α := ‹MulAction M α› + +@[to_additive] +instance instMulAction' [Monoid M] [MulAction M α] : MulAction M αᵒᵈ := ‹MulAction M α› + +@[to_additive] +instance instSMulCommClass [SMul M α] [SMul N α] [SMulCommClass M N α] : SMulCommClass Mᵒᵈ N α := + ‹SMulCommClass M N α› + +@[to_additive] +instance instSMulCommClass' [SMul M α] [SMul N α] [SMulCommClass M N α] : SMulCommClass M Nᵒᵈ α := + ‹SMulCommClass M N α› + +@[to_additive] +instance instSMulCommClass'' [SMul M α] [SMul N α] [SMulCommClass M N α] : SMulCommClass M N αᵒᵈ := + ‹SMulCommClass M N α› + +@[to_additive instVAddAssocClass] +instance instIsScalarTower [SMul M N] [SMul M α] [SMul N α] [IsScalarTower M N α] : + IsScalarTower Mᵒᵈ N α := ‹IsScalarTower M N α› + +@[to_additive instVAddAssocClass'] +instance instIsScalarTower' [SMul M N] [SMul M α] [SMul N α] [IsScalarTower M N α] : + IsScalarTower M Nᵒᵈ α := ‹IsScalarTower M N α› + +@[to_additive instVAddAssocClass''] +instance instIsScalarTower'' [SMul M N] [SMul M α] [SMul N α] [IsScalarTower M N α] : + IsScalarTower M N αᵒᵈ := ‹IsScalarTower M N α› + +end OrderDual + +namespace Lex + +@[to_additive] +instance instMulAction [Monoid M] [MulAction M α] : MulAction (Lex M) α := ‹MulAction M α› + +@[to_additive] +instance instMulAction' [Monoid M] [MulAction M α] : MulAction M (Lex α) := ‹MulAction M α› + +@[to_additive] +instance instSMulCommClass [SMul M α] [SMul N α] [SMulCommClass M N α] : + SMulCommClass (Lex M) N α := ‹SMulCommClass M N α› + +@[to_additive] +instance instSMulCommClass' [SMul M α] [SMul N α] [SMulCommClass M N α] : + SMulCommClass M (Lex N) α := ‹SMulCommClass M N α› + +@[to_additive] +instance instSMulCommClass'' [SMul M α] [SMul N α] [SMulCommClass M N α] : + SMulCommClass M N (Lex α) := ‹SMulCommClass M N α› + +@[to_additive instVAddAssocClass] +instance instIsScalarTower [SMul M N] [SMul M α] [SMul N α] [IsScalarTower M N α] : + IsScalarTower (Lex M) N α := ‹IsScalarTower M N α› + +@[to_additive instVAddAssocClass'] +instance instIsScalarTower' [SMul M N] [SMul M α] [SMul N α] [IsScalarTower M N α] : + IsScalarTower M (Lex N) α := ‹IsScalarTower M N α› + +@[to_additive instVAddAssocClass''] +instance instIsScalarTower'' [SMul M N] [SMul M α] [SMul N α] [IsScalarTower M N α] : + IsScalarTower M N (Lex α) := ‹IsScalarTower M N α› + +end Lex diff --git a/Mathlib/Algebra/Order/Group/Basic.lean b/Mathlib/Algebra/Order/Group/Basic.lean index a5778d8524f10..da2cd7d995442 100644 --- a/Mathlib/Algebra/Order/Group/Basic.lean +++ b/Mathlib/Algebra/Order/Group/Basic.lean @@ -102,4 +102,27 @@ lemma zpow_left_inj (hn : n ≠ 0) : a ^ n = b ^ n ↔ a = b := (zpow_left_injec `zsmul_lt_zsmul_iff'`."] lemma zpow_eq_zpow_iff' (hn : n ≠ 0) : a ^ n = b ^ n ↔ a = b := zpow_left_inj hn +variable (α) in +/-- A nontrivial densely linear ordered commutative group can't be a cyclic group. -/ +@[to_additive + "A nontrivial densely linear ordered additive commutative group can't be a cyclic group."] +theorem not_isCyclic_of_denselyOrdered [DenselyOrdered α] [Nontrivial α] : ¬IsCyclic α := by + intro h + rcases exists_zpow_surjective α with ⟨a, ha⟩ + rcases lt_trichotomy a 1 with hlt | rfl | hlt + · rcases exists_between hlt with ⟨b, hab, hb⟩ + rcases ha b with ⟨k, rfl⟩ + suffices 0 < k ∧ k < 1 by omega + rw [← one_lt_inv'] at hlt + simp_rw [← zpow_lt_zpow_iff hlt] + simp_all + · rcases exists_ne (1 : α) with ⟨b, hb⟩ + simpa [hb.symm] using ha b + · rcases exists_between hlt with ⟨b, hb, hba⟩ + rcases ha b with ⟨k, rfl⟩ + suffices 0 < k ∧ k < 1 by omega + simp_rw [← zpow_lt_zpow_iff hlt] + simp_all + end LinearOrderedCommGroup + diff --git a/Mathlib/Algebra/Order/Group/Defs.lean b/Mathlib/Algebra/Order/Group/Defs.lean index c486a4984cd8a..a47229cb3489f 100644 --- a/Mathlib/Algebra/Order/Group/Defs.lean +++ b/Mathlib/Algebra/Order/Group/Defs.lean @@ -170,7 +170,7 @@ end LinearOrderedCommGroup section NormNumLemmas /- The following lemmas are stated so that the `norm_num` tactic can use them with the -expected signatures. -/ +expected signatures. -/ variable [OrderedCommGroup α] {a b : α} @[to_additive (attr := gcongr) neg_le_neg] diff --git a/Mathlib/Algebra/Order/GroupWithZero/Action/Synonym.lean b/Mathlib/Algebra/Order/GroupWithZero/Action/Synonym.lean new file mode 100644 index 0000000000000..bd2d126a778f8 --- /dev/null +++ b/Mathlib/Algebra/Order/GroupWithZero/Action/Synonym.lean @@ -0,0 +1,78 @@ +/- +Copyright (c) 2021 Yaël Dillies. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yaël Dillies +-/ +import Mathlib.Algebra.Order.GroupWithZero.Synonym +import Mathlib.Algebra.SMulWithZero +import Mathlib.Tactic.Common + +/-! +# Actions by and on order synonyms + +This PR transfers group action with zero instances from a type `α` to `αᵒᵈ` and `Lex α`. Note that +the `SMul` instances are already defined in `Mathlib.Algebra.Order.Group.Synonym`. + +## See also + +* `Mathlib.Algebra.Order.Group.Action.Synonym` +* `Mathlib.Algebra.Order.Module.Synonym` +-/ + +variable {G₀ M₀ : Type*} + +namespace OrderDual + +instance instSMulWithZero [Zero G₀] [Zero M₀] [SMulWithZero G₀ M₀] : SMulWithZero G₀ᵒᵈ M₀ := + ‹SMulWithZero G₀ M₀› + +instance instSMulWithZero' [Zero G₀] [Zero M₀] [SMulWithZero G₀ M₀] : SMulWithZero G₀ M₀ᵒᵈ := + ‹SMulWithZero G₀ M₀› + +instance instDistribSMul [AddZeroClass M₀] [DistribSMul G₀ M₀] : DistribSMul G₀ᵒᵈ M₀ := + ‹DistribSMul G₀ M₀› + +instance instDistribSMul' [AddZeroClass M₀] [DistribSMul G₀ M₀] : DistribSMul G₀ M₀ᵒᵈ := + ‹DistribSMul G₀ M₀› + +instance instDistribMulAction [Monoid G₀] [AddMonoid M₀] [DistribMulAction G₀ M₀] : + DistribMulAction G₀ᵒᵈ M₀ := ‹DistribMulAction G₀ M₀› + +instance instDistribMulAction' [Monoid G₀] [AddMonoid M₀] [DistribMulAction G₀ M₀] : + DistribMulAction G₀ M₀ᵒᵈ := ‹DistribMulAction G₀ M₀› + +instance instMulActionWithZero [MonoidWithZero G₀] [AddMonoid M₀] [MulActionWithZero G₀ M₀] : + MulActionWithZero G₀ᵒᵈ M₀ := ‹MulActionWithZero G₀ M₀› + +instance instMulActionWithZero' [MonoidWithZero G₀] [AddMonoid M₀] [MulActionWithZero G₀ M₀] : + MulActionWithZero G₀ M₀ᵒᵈ := ‹MulActionWithZero G₀ M₀› + +end OrderDual + +namespace Lex + +instance instSMulWithZero [Zero G₀] [Zero M₀] [SMulWithZero G₀ M₀] : SMulWithZero (Lex G₀) M₀ := + ‹SMulWithZero G₀ M₀› + +instance instSMulWithZero' [Zero G₀] [Zero M₀] [SMulWithZero G₀ M₀] : SMulWithZero G₀ (Lex M₀) := + ‹SMulWithZero G₀ M₀› + +instance instDistribSMul [AddZeroClass M₀] [DistribSMul G₀ M₀] : DistribSMul (Lex G₀) M₀ := + ‹DistribSMul G₀ M₀› + +instance instDistribSMul' [AddZeroClass M₀] [DistribSMul G₀ M₀] : DistribSMul G₀ (Lex M₀) := + ‹DistribSMul G₀ M₀› + +instance instDistribMulAction [Monoid G₀] [AddMonoid M₀] [DistribMulAction G₀ M₀] : + DistribMulAction (Lex G₀) M₀ := ‹DistribMulAction G₀ M₀› + +instance instDistribMulAction' [Monoid G₀] [AddMonoid M₀] [DistribMulAction G₀ M₀] : + DistribMulAction G₀ (Lex M₀) := ‹DistribMulAction G₀ M₀› + +instance instMulActionWithZero [MonoidWithZero G₀] [AddMonoid M₀] [MulActionWithZero G₀ M₀] : + MulActionWithZero (Lex G₀) M₀ := ‹MulActionWithZero G₀ M₀› + +instance instMulActionWithZero' [MonoidWithZero G₀] [AddMonoid M₀] [MulActionWithZero G₀ M₀] : + MulActionWithZero G₀ (Lex M₀) := ‹MulActionWithZero G₀ M₀› + +end Lex diff --git a/Mathlib/Algebra/Order/GroupWithZero/Canonical.lean b/Mathlib/Algebra/Order/GroupWithZero/Canonical.lean index 3984c64e8056f..d7eab9e094013 100644 --- a/Mathlib/Algebra/Order/GroupWithZero/Canonical.lean +++ b/Mathlib/Algebra/Order/GroupWithZero/Canonical.lean @@ -3,17 +3,16 @@ Copyright (c) 2020 Kenny Lau. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kenny Lau, Johan Commelin, Patrick Massot -/ -import Mathlib.Algebra.Group.WithOne.Defs import Mathlib.Algebra.GroupWithZero.InjSurj import Mathlib.Algebra.GroupWithZero.Units.Equiv import Mathlib.Algebra.GroupWithZero.WithZero +import Mathlib.Algebra.Order.AddGroupWithTop import Mathlib.Algebra.Order.Group.Units import Mathlib.Algebra.Order.GroupWithZero.Synonym +import Mathlib.Algebra.Order.GroupWithZero.Unbundled import Mathlib.Algebra.Order.Monoid.Basic -import Mathlib.Algebra.Order.AddGroupWithTop import Mathlib.Algebra.Order.Monoid.OrderDual import Mathlib.Algebra.Order.Monoid.TypeTags -import Mathlib.Algebra.Order.ZeroLEOne /-! # Linearly ordered commutative groups and monoids with a zero element adjoined @@ -99,41 +98,60 @@ end LinearOrderedCommMonoidWithZero section LinearOrderedCommGroupWithZero variable [LinearOrderedCommGroupWithZero α] {a b c d : α} {m n : ℕ} --- TODO: Do we really need the following two? +-- See note [lower instance priority] +instance (priority := 100) LinearOrderedCommGroupWithZero.toMulPosMono : MulPosMono α where + elim _a _b _c hbc := mul_le_mul_right' hbc _ + +-- See note [lower instance priority] +instance (priority := 100) LinearOrderedCommGroupWithZero.toPosMulMono : PosMulMono α where + elim _a _b _c hbc := mul_le_mul_left' hbc _ + +-- See note [lower instance priority] +instance (priority := 100) LinearOrderedCommGroupWithZero.toPosMulReflectLE : + PosMulReflectLE α where + elim a b c hbc := by simpa [a.2.ne'] using mul_le_mul_left' hbc a⁻¹ + +-- See note [lower instance priority] +instance (priority := 100) LinearOrderedCommGroupWithZero.toMulPosReflectLE : + MulPosReflectLE α where + elim a b c hbc := by simpa [a.2.ne'] using mul_le_mul_right' hbc a⁻¹ + +-- See note [lower instance priority] +instance (priority := 100) LinearOrderedCommGroupWithZero.toPosMulReflectLT : + PosMulReflectLT α where elim _a _b _c := lt_of_mul_lt_mul_left' + +-- See note [lower instance priority] +instance (priority := 100) LinearOrderedCommGroupWithZero.toPosMulStrictMono : + PosMulStrictMono α where + elim a b c hbc := by by_contra! h; exact hbc.not_le <| (mul_le_mul_left a.2).1 h + +-- See note [lower instance priority] +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 := one_le_mul ha hb -theorem le_of_le_mul_right (h : c ≠ 0) (hab : a * c ≤ b * c) : a ≤ b := by - simpa only [mul_inv_cancel_right₀ h] using mul_le_mul_right' hab c⁻¹ +@[deprecated mul_le_mul_right (since := "2024-08-21")] +theorem le_of_le_mul_right (h : c ≠ 0) (hab : a * c ≤ b * c) : a ≤ b := + (mul_le_mul_right (zero_lt_iff.2 h)).1 hab +@[deprecated le_mul_inv_iff₀ (since := "2024-08-21")] theorem le_mul_inv_of_mul_le (h : c ≠ 0) (hab : a * c ≤ b) : a ≤ b * c⁻¹ := - le_of_le_mul_right h (by simpa [h] using hab) + (le_mul_inv_iff₀ (zero_lt_iff.2 h)).2 hab theorem mul_inv_le_of_le_mul (hab : a ≤ b * c) : a * c⁻¹ ≤ b := by by_cases h : c = 0 · simp [h] - · exact le_of_le_mul_right h (by simpa [h] using hab) - -theorem inv_le_one₀ (ha : a ≠ 0) : a⁻¹ ≤ 1 ↔ 1 ≤ a := - inv_le_one' (a := Units.mk0 a ha) - -theorem one_le_inv₀ (ha : a ≠ 0) : 1 ≤ a⁻¹ ↔ a ≤ 1 := - one_le_inv' (a := Units.mk0 a ha) - -theorem le_mul_inv_iff₀ (hc : c ≠ 0) : a ≤ b * c⁻¹ ↔ a * c ≤ b := - ⟨fun h ↦ inv_inv c ▸ mul_inv_le_of_le_mul h, le_mul_inv_of_mul_le hc⟩ - -theorem mul_inv_le_iff₀ (hc : c ≠ 0) : a * c⁻¹ ≤ b ↔ a ≤ b * c := - ⟨fun h ↦ inv_inv c ▸ le_mul_inv_of_mul_le (inv_ne_zero hc) h, mul_inv_le_of_le_mul⟩ - -theorem div_le_div₀ (a b c d : α) (hb : b ≠ 0) (hd : d ≠ 0) : - a * b⁻¹ ≤ c * d⁻¹ ↔ a * d ≤ c * b := by - rw [mul_inv_le_iff₀ hb, mul_right_comm, le_mul_inv_iff₀ hd] + · exact (mul_le_mul_right (zero_lt_iff.2 h)).1 (by simpa [h] using hab) @[simp] theorem Units.zero_lt (u : αˣ) : (0 : α) < u := @@ -163,9 +181,9 @@ theorem inv_mul_lt_of_lt_mul₀ (h : a < b * c) : b⁻¹ * a < c := by rw [mul_comm] at * exact mul_inv_lt_of_lt_mul₀ h -theorem mul_lt_right₀ (c : α) (h : a < b) (hc : c ≠ 0) : a * c < b * c := by - contrapose! h - exact le_of_le_mul_right hc h +@[deprecated mul_lt_mul_of_pos_right (since := "2024-08-21")] +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) @@ -189,31 +207,26 @@ theorem lt_of_mul_lt_mul_of_le₀ (h : a * b < c * d) (hc : 0 < c) (hh : c ≤ a 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 +@[deprecated mul_le_mul_right (since := "2024-08-21")] theorem mul_le_mul_right₀ (hc : c ≠ 0) : a * c ≤ b * c ↔ a ≤ b := - ⟨le_of_le_mul_right hc, fun hab ↦ mul_le_mul_right' hab _⟩ + mul_le_mul_right (zero_lt_iff.2 hc) -theorem mul_le_mul_left₀ (ha : a ≠ 0) : a * b ≤ a * c ↔ b ≤ c := by - simp only [mul_comm a] - exact mul_le_mul_right₀ ha +@[deprecated mul_le_mul_left (since := "2024-08-21")] +theorem mul_le_mul_left₀ (ha : a ≠ 0) : a * b ≤ a * c ↔ b ≤ c := + mul_le_mul_left (zero_lt_iff.2 ha) 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₀ (inv_ne_zero hc)] + 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₀ ha, inv_le_inv₀ hb hc] - -theorem le_div_iff₀ (hc : c ≠ 0) : a ≤ b / c ↔ a * c ≤ b := by - rw [div_eq_mul_inv, le_mul_inv_iff₀ hc] - -theorem div_le_iff₀ (hc : c ≠ 0) : a / c ≤ b ↔ a ≤ b * c := by - rw [div_eq_mul_inv, mul_inv_le_iff₀ hc] + simp only [div_eq_mul_inv, mul_le_mul_left (zero_lt_iff.2 ha), inv_le_inv₀ hb hc] /-- `Equiv.mulLeft₀` as an `OrderIso` on a `LinearOrderedCommGroupWithZero.`. Note that `OrderIso.mulLeft₀` refers to the `LinearOrderedField` version. -/ @[simps! (config := { simpRhs := true }) apply toEquiv] def OrderIso.mulLeft₀' {a : α} (ha : a ≠ 0) : α ≃o α := - { Equiv.mulLeft₀ a ha with map_rel_iff' := mul_le_mul_left₀ ha } + { Equiv.mulLeft₀ a ha with map_rel_iff' := mul_le_mul_left (zero_lt_iff.2 ha) } theorem OrderIso.mulLeft₀'_symm {a : α} (ha : a ≠ 0) : (OrderIso.mulLeft₀' ha).symm = OrderIso.mulLeft₀' (inv_ne_zero ha) := by @@ -225,7 +238,7 @@ theorem OrderIso.mulLeft₀'_symm {a : α} (ha : a ≠ 0) : Note that `OrderIso.mulRight₀` refers to the `LinearOrderedField` version. -/ @[simps! (config := { simpRhs := true }) apply toEquiv] def OrderIso.mulRight₀' {a : α} (ha : a ≠ 0) : α ≃o α := - { Equiv.mulRight₀ a ha with map_rel_iff' := mul_le_mul_right₀ ha } + { Equiv.mulRight₀ a ha with map_rel_iff' := mul_le_mul_right (zero_lt_iff.2 ha) } theorem OrderIso.mulRight₀'_symm {a : α} (ha : a ≠ 0) : (OrderIso.mulRight₀' ha).symm = OrderIso.mulRight₀' (inv_ne_zero ha) := by @@ -245,7 +258,7 @@ instance : LinearOrderedAddCommGroupWithTop (Additive αᵒᵈ) := lemma pow_lt_pow_succ (ha : 1 < a) : a ^ n < a ^ n.succ := by rw [← one_mul (a ^ n), pow_succ'] - exact mul_lt_right₀ _ ha (pow_ne_zero _ (zero_lt_one.trans ha).ne') + exact mul_lt_mul_of_pos_right ha (pow_pos (zero_lt_one.trans ha) _) 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)] diff --git a/Mathlib/Algebra/Order/GroupWithZero/Submonoid.lean b/Mathlib/Algebra/Order/GroupWithZero/Submonoid.lean new file mode 100644 index 0000000000000..c3b553bb0ca38 --- /dev/null +++ b/Mathlib/Algebra/Order/GroupWithZero/Submonoid.lean @@ -0,0 +1,27 @@ +/- +Copyright (c) 2021 Chris Birkbeck. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Chris Birkbeck +-/ +import Mathlib.Algebra.Group.Submonoid.Basic +import Mathlib.Algebra.Order.GroupWithZero.Unbundled + +/-! +# The submonoid of positive elements +-/ + +namespace Submonoid +variable (α) [MulZeroOneClass α] [PartialOrder α] [PosMulStrictMono α] [ZeroLEOneClass α] + [NeZero (1 : α)] {a : α} + +/-- The submonoid of positive elements. -/ +@[simps] def pos : Submonoid α where + carrier := Set.Ioi 0 + one_mem' := zero_lt_one + mul_mem' := mul_pos + +variable {α} + +@[simp] lemma mem_pos : a ∈ pos α ↔ 0 < a := Iff.rfl + +end Submonoid diff --git a/Mathlib/Algebra/Order/GroupWithZero/Unbundled.lean b/Mathlib/Algebra/Order/GroupWithZero/Unbundled.lean index 3fdf5f2d9d810..29e087b5c4728 100644 --- a/Mathlib/Algebra/Order/GroupWithZero/Unbundled.lean +++ b/Mathlib/Algebra/Order/GroupWithZero/Unbundled.lean @@ -3,9 +3,12 @@ Copyright (c) 2022 Damiano Testa. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Damiano Testa, Yuyang Zhao -/ -import Mathlib.Algebra.GroupWithZero.Defs +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.GCongr.Core +import Mathlib.Tactic.Nontriviality /-! # Monotonicity of multiplication by positive elements @@ -80,7 +83,7 @@ for a discussion about this notation, and whether to enable it globally (note th currently global but broken, hence actually only works locally). -/ -variable (α : Type*) +variable {M₀ G₀ : Type*} (α : Type*) set_option quotPrecheck false in /-- Local notation for the nonnegative elements of a type `α`. TODO: actually make local. -/ @@ -617,6 +620,17 @@ variable [Preorder α] /-! Lemmas of the form `a ≤ a * b ↔ 1 ≤ b` and `a * b ≤ a ↔ b ≤ 1`, which assume left covariance. -/ +lemma one_lt_of_lt_mul_left₀ [PosMulReflectLT α] (ha : 0 ≤ a) (h : a < a * b) : 1 < b := + lt_of_mul_lt_mul_left (by simpa) ha + +lemma one_lt_of_lt_mul_right₀ [MulPosReflectLT α] (hb : 0 ≤ b) (h : b < a * b) : 1 < a := + lt_of_mul_lt_mul_right (by simpa) hb + +lemma one_le_of_le_mul_left₀ [PosMulReflectLE α] (ha : 0 < a) (h : a ≤ a * b) : 1 ≤ b := + le_of_mul_le_mul_left (by simpa) ha + +lemma one_le_of_le_mul_right₀ [MulPosReflectLE α] (hb : 0 < b) (h : b ≤ a * b) : 1 ≤ a := + le_of_mul_le_mul_right (by simpa) hb @[simp] lemma le_mul_iff_one_le_right [PosMulMono α] [PosMulReflectLE α] (a0 : 0 < a) : a ≤ a * b ↔ 1 ≤ b := @@ -917,6 +931,144 @@ end LinearOrder end MulOneClass +section MonoidWithZero +variable [MonoidWithZero M₀] + +section Preorder +variable [Preorder M₀] {a b c d : 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 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 + | _, _, Nat.le.step h => by + rw [pow_succ'] + exact (mul_le_of_le_one_left (pow_nonneg ha₀ _) ha₁).trans <| pow_le_pow_of_le_one ha₀ ha₁ h + +lemma pow_le_of_le_one [ZeroLEOneClass M₀] [PosMulMono M₀] [MulPosMono M₀] (h₀ : 0 ≤ a) (h₁ : a ≤ 1) + (hn : n ≠ 0) : a ^ n ≤ a := + (pow_one a).subst (pow_le_pow_of_le_one h₀ h₁ (Nat.pos_of_ne_zero hn)) + +lemma sq_le [ZeroLEOneClass M₀] [PosMulMono M₀] [MulPosMono M₀] (h₀ : 0 ≤ a) (h₁ : a ≤ 1) : + a ^ 2 ≤ a := pow_le_of_le_one h₀ h₁ two_ne_zero + +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 + +lemma one_lt_mul_of_lt_of_le [ZeroLEOneClass M₀] [PosMulMono M₀] (ha : 1 < a) (hb : 1 ≤ b) : + 1 < a * b := ha.trans_le <| le_mul_of_one_le_right (zero_le_one.trans ha.le) hb + +alias one_lt_mul := one_lt_mul_of_le_of_lt + +lemma mul_lt_one_of_nonneg_of_lt_one_left [PosMulMono M₀] (ha₀ : 0 ≤ a) (ha : a < 1) (hb : b ≤ 1) : + a * b < 1 := (mul_le_of_le_one_right ha₀ hb).trans_lt ha + +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 + +variable [Preorder α] {f g : α → M₀} + +lemma monotone_mul_left_of_nonneg [PosMulMono M₀] (ha : 0 ≤ a) : Monotone fun x ↦ a * x := + fun _ _ h ↦ mul_le_mul_of_nonneg_left h ha + +lemma monotone_mul_right_of_nonneg [MulPosMono M₀] (ha : 0 ≤ a) : Monotone fun x ↦ x * a := + fun _ _ h ↦ mul_le_mul_of_nonneg_right h ha + +lemma Monotone.mul_const [MulPosMono M₀] (hf : Monotone f) (ha : 0 ≤ a) : + Monotone fun x ↦ f x * a := (monotone_mul_right_of_nonneg ha).comp hf + +lemma Monotone.const_mul [PosMulMono M₀] (hf : Monotone f) (ha : 0 ≤ a) : + Monotone fun x ↦ a * f x := (monotone_mul_left_of_nonneg ha).comp hf + +lemma Antitone.mul_const [MulPosMono M₀] (hf : Antitone f) (ha : 0 ≤ a) : + Antitone fun x ↦ f x * a := (monotone_mul_right_of_nonneg ha).comp_antitone hf + +lemma Antitone.const_mul [PosMulMono M₀] (hf : Antitone f) (ha : 0 ≤ a) : + Antitone fun x ↦ a * f x := (monotone_mul_left_of_nonneg ha).comp_antitone hf + +lemma Monotone.mul [PosMulMono M₀] [MulPosMono M₀] (hf : Monotone f) (hg : Monotone g) + (hf₀ : ∀ x, 0 ≤ f x) (hg₀ : ∀ x, 0 ≤ g x) : Monotone (f * g) := + fun _ _ h ↦ mul_le_mul (hf h) (hg h) (hg₀ _) (hf₀ _) + +end Preorder + + +section PartialOrder +variable [PartialOrder M₀] {a b c d : M₀} + +@[simp] lemma pow_pos [ZeroLEOneClass M₀] [PosMulStrictMono M₀] (ha : 0 < a) : ∀ n, 0 < a ^ n + | 0 => by nontriviality; rw [pow_zero]; exact zero_lt_one + | n + 1 => pow_succ a _ ▸ mul_pos (pow_pos ha _) ha + +lemma mul_self_lt_mul_self [PosMulStrictMono M₀] [MulPosMono M₀] (ha : 0 ≤ a) (hab : a < b) : + a * a < b * b := mul_lt_mul' hab.le hab ha <| ha.trans_lt hab + +-- In the next lemma, we used to write `Set.Ici 0` instead of `{x | 0 ≤ x}`. +-- As this lemma is not used outside this file, +-- and the import for `Set.Ici` is not otherwise needed until later, +-- we choose not to use it here. +lemma strictMonoOn_mul_self [PosMulStrictMono M₀] [MulPosMono M₀] : + StrictMonoOn (fun x ↦ x * x) {x : M₀ | 0 ≤ x} := fun _ hx _ _ hxy ↦ mul_self_lt_mul_self hx hxy + +-- See Note [decidable namespace] +protected lemma Decidable.mul_lt_mul'' [PosMulMono M₀] [PosMulStrictMono M₀] [MulPosStrictMono M₀] + [@DecidableRel M₀ (· ≤ ·)] (h1 : a < c) (h2 : b < d) + (h3 : 0 ≤ a) (h4 : 0 ≤ b) : a * b < c * d := + h4.lt_or_eq_dec.elim (fun b0 ↦ mul_lt_mul h1 h2.le b0 <| h3.trans h1.le) fun b0 ↦ by + rw [← b0, mul_zero]; exact mul_pos (h3.trans_lt h1) (h4.trans_lt h2) + +lemma lt_mul_left [MulPosStrictMono M₀] (ha : 0 < a) (hb : 1 < b) : a < b * a := by + simpa using mul_lt_mul_of_pos_right hb ha + +lemma lt_mul_right [PosMulStrictMono M₀] (ha : 0 < a) (hb : 1 < b) : a < a * b := by + simpa using mul_lt_mul_of_pos_left hb ha + +lemma lt_mul_self [ZeroLEOneClass M₀] [MulPosStrictMono M₀] (ha : 1 < a) : a < a * a := + lt_mul_left (ha.trans_le' zero_le_one) ha + +variable [Preorder α] {f g : α → M₀} + +lemma strictMono_mul_left_of_pos [PosMulStrictMono M₀] (ha : 0 < a) : + StrictMono fun x ↦ a * x := fun _ _ b_lt_c ↦ mul_lt_mul_of_pos_left b_lt_c ha + +lemma strictMono_mul_right_of_pos [MulPosStrictMono M₀] (ha : 0 < a) : + StrictMono fun x ↦ x * a := fun _ _ b_lt_c ↦ mul_lt_mul_of_pos_right b_lt_c ha + +lemma StrictMono.mul_const [MulPosStrictMono M₀] (hf : StrictMono f) (ha : 0 < a) : + StrictMono fun x ↦ f x * a := (strictMono_mul_right_of_pos ha).comp hf + +lemma StrictMono.const_mul [PosMulStrictMono M₀] (hf : StrictMono f) (ha : 0 < a) : + StrictMono fun x ↦ a * f x := (strictMono_mul_left_of_pos ha).comp hf + +lemma StrictAnti.mul_const [MulPosStrictMono M₀] (hf : StrictAnti f) (ha : 0 < a) : + StrictAnti fun x ↦ f x * a := (strictMono_mul_right_of_pos ha).comp_strictAnti hf + +lemma StrictAnti.const_mul [PosMulStrictMono M₀] (hf : StrictAnti f) (ha : 0 < a) : + StrictAnti fun x ↦ a * f x := (strictMono_mul_left_of_pos ha).comp_strictAnti hf + +lemma StrictMono.mul_monotone [PosMulMono M₀] [MulPosStrictMono M₀] (hf : StrictMono f) + (hg : Monotone g) (hf₀ : ∀ x, 0 ≤ f x) (hg₀ : ∀ x, 0 < g x) : + StrictMono (f * g) := fun _ _ h ↦ mul_lt_mul (hf h) (hg h.le) (hg₀ _) (hf₀ _) + +lemma Monotone.mul_strictMono [PosMulStrictMono M₀] [MulPosMono M₀] (hf : Monotone f) + (hg : StrictMono g) (hf₀ : ∀ x, 0 < f x) (hg₀ : ∀ x, 0 ≤ g x) : + StrictMono (f * g) := fun _ _ h ↦ mul_lt_mul' (hf h.le) (hg h) (hg₀ _) (hf₀ _) + +lemma StrictMono.mul [PosMulStrictMono M₀] [MulPosStrictMono M₀] (hf : StrictMono f) + (hg : StrictMono g) (hf₀ : ∀ x, 0 ≤ f x) (hg₀ : ∀ x, 0 ≤ g x) : + StrictMono (f * g) := fun _ _ h ↦ mul_lt_mul'' (hf h) (hg h) (hf₀ _) (hg₀ _) + +end MonoidWithZero.PartialOrder + section CancelMonoidWithZero variable [CancelMonoidWithZero α] @@ -958,6 +1110,103 @@ end PartialOrder end CancelMonoidWithZero +section GroupWithZero +variable [GroupWithZero G₀] + +section PartialOrder +variable [PartialOrder G₀] [ZeroLEOneClass G₀] [PosMulReflectLT G₀] {a b c d : 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⟩ + fun a ha ↦ flip lt_of_mul_lt_mul_left ha.le <| by simp [ne_of_gt ha, zero_lt_one] + +alias ⟨_, inv_pos_of_pos⟩ := inv_pos + +@[simp] lemma inv_nonneg : 0 ≤ a⁻¹ ↔ 0 ≤ a := by simp only [le_iff_eq_or_lt, inv_pos, zero_eq_inv] + +alias ⟨_, inv_nonneg_of_nonneg⟩ := inv_nonneg + +lemma one_div_pos : 0 < 1 / a ↔ 0 < a := one_div a ▸ inv_pos +lemma one_div_nonneg : 0 ≤ 1 / a ↔ 0 ≤ a := one_div a ▸ inv_nonneg + +lemma div_pos [PosMulStrictMono G₀] (ha : 0 < a) (hb : 0 < b) : 0 < a / b := by + rw [div_eq_mul_inv]; exact mul_pos ha (inv_pos.2 hb) + +lemma div_nonneg [PosMulMono G₀] (ha : 0 ≤ a) (hb : 0 ≤ b) : 0 ≤ a / b := by + rw [div_eq_mul_inv]; exact mul_nonneg ha (inv_nonneg.2 hb) + +lemma div_nonpos_of_nonpos_of_nonneg [MulPosMono G₀] (ha : a ≤ 0) (hb : 0 ≤ b) : a / b ≤ 0 := by + rw [div_eq_mul_inv]; exact mul_nonpos_of_nonpos_of_nonneg ha (inv_nonneg.2 hb) + +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 + | (n : ℕ) => by rw [zpow_natCast]; exact pow_pos ha _ + |-(n + 1 : ℕ) => by rw [zpow_neg, inv_pos, zpow_natCast]; exact pow_pos ha _ + +section PosMulMono +variable [PosMulMono G₀] + +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) + +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) + +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] + +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) + +end PosMulMono + +section MulPosMono +variable [MulPosMono G₀] + +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) + +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) + +lemma le_div_iff₀ (hc : 0 < c) : a ≤ b / c ↔ a * c ≤ b := by + rw [div_eq_mul_inv, le_mul_inv_iff₀ hc] + +lemma div_le_iff₀ (hc : 0 < c) : b / c ≤ a ↔ b ≤ a * c := by + rw [div_eq_mul_inv, mul_inv_le_iff₀ hc] + +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] + +@[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 MulPosMono +end PartialOrder + +section LinearOrder +variable [LinearOrder G₀] [ZeroLEOneClass G₀] [PosMulReflectLT G₀] {a b c : 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] + +alias inv_lt_zero := inv_neg'' + +lemma one_div_neg : 1 / a < 0 ↔ a < 0 := one_div a ▸ inv_neg'' +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) + +end GroupWithZero.LinearOrder + section CommSemigroupHasZero variable [Mul α] [IsSymmOp α α (· * ·)] [Zero α] [Preorder α] @@ -975,3 +1224,25 @@ theorem posMulReflectLE_iff_mulPosReflectLE : PosMulReflectLE α ↔ MulPosRefle simp only [PosMulReflectLE, MulPosReflectLE, IsSymmOp.symm_op] end CommSemigroupHasZero + +section CommGroupWithZero +variable [CommGroupWithZero G₀] +variable [PartialOrder G₀] [ZeroLEOneClass G₀] [PosMulReflectLT G₀] [MulPosMono G₀] {a b c d : G₀} + +lemma div_le_div₀ (hb : 0 < b) (hd : 0 < d) : + a / b ≤ c / d ↔ a * d ≤ c * b := by + 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] + +lemma le_div_comm₀ (ha : 0 < a) (hc : 0 < c) : a ≤ b / c ↔ c ≤ b / a := by + 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 + 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 CommGroupWithZero diff --git a/Mathlib/Algebra/Order/Hom/Basic.lean b/Mathlib/Algebra/Order/Hom/Basic.lean index 584713f30f610..dbcb880887ff3 100644 --- a/Mathlib/Algebra/Order/Hom/Basic.lean +++ b/Mathlib/Algebra/Order/Hom/Basic.lean @@ -126,12 +126,12 @@ theorem le_map_add_map_div [Group α] [AddCommSemigroup β] [LE β] [MulLEAddHom @[to_additive] theorem le_map_div_mul_map_div [Group α] [CommSemigroup β] [LE β] [SubmultiplicativeHomClass F α β] (f : F) (a b c : α) : f (a / c) ≤ f (a / b) * f (b / c) := by - simpa only [div_mul_div_cancel'] using map_mul_le_mul f (a / b) (b / c) + simpa only [div_mul_div_cancel] using map_mul_le_mul f (a / b) (b / c) @[to_additive existing] theorem le_map_div_add_map_div [Group α] [AddCommSemigroup β] [LE β] [MulLEAddHomClass F α β] (f : F) (a b c : α) : f (a / c) ≤ f (a / b) + f (b / c) := by - simpa only [div_mul_div_cancel'] using map_mul_le_add f (a / b) (b / c) + simpa only [div_mul_div_cancel] using map_mul_le_add f (a / b) (b / c) namespace Mathlib.Meta.Positivity diff --git a/Mathlib/Algebra/Order/Hom/Monoid.lean b/Mathlib/Algebra/Order/Hom/Monoid.lean index d212b514c3cc4..89356b58c0ecf 100644 --- a/Mathlib/Algebra/Order/Hom/Monoid.lean +++ b/Mathlib/Algebra/Order/Hom/Monoid.lean @@ -18,12 +18,17 @@ This file defines morphisms between (additive) ordered monoids. * `OrderAddMonoidHom`: Ordered additive monoid homomorphisms. * `OrderMonoidHom`: Ordered monoid homomorphisms. * `OrderMonoidWithZeroHom`: Ordered monoid with zero homomorphisms. +* `OrderAddMonoidIso`: Ordered additive monoid isomorphisms. +* `OrderMonoidIso`: Ordered monoid isomorphisms. ## Notation -* `→+o`: Bundled ordered additive monoid homs. Also use for additive groups homs. -* `→*o`: Bundled ordered monoid homs. Also use for groups homs. -* `→*₀o`: Bundled ordered monoid with zero homs. Also use for groups with zero homs. +* `→+o`: Bundled ordered additive monoid homs. Also use for additive group homs. +* `→*o`: Bundled ordered monoid homs. Also use for group homs. +* `→*₀o`: Bundled ordered monoid with zero homs. Also use for group with zero homs. +* `≃+o`: Bundled ordered additive monoid isos. Also use for additive group isos. +* `≃*o`: Bundled ordered monoid isos. Also use for group isos. +* `≃*₀o`: Bundled ordered monoid with zero isos. Also use for group with zero isos. ## Implementation notes @@ -66,9 +71,8 @@ structure. `OrderAddMonoidHom` is also used for ordered group homomorphisms. When possible, instead of parametrizing results over `(f : α →+o β)`, -you should parametrize over `(F : Type*) [OrderAddMonoidHomClass F α β] (f : F)`. - -When you extend this structure, make sure to extend `OrderAddMonoidHomClass`. -/ +you should parametrize over +`(F : Type*) [FunLike F M N] [MonoidHomClass F M N] [OrderHomClass F M N] (f : F)`. -/ structure OrderAddMonoidHom (α β : Type*) [Preorder α] [Preorder β] [AddZeroClass α] [AddZeroClass β] extends α →+ β where /-- An `OrderAddMonoidHom` is a monotone function. -/ @@ -77,6 +81,22 @@ structure OrderAddMonoidHom (α β : Type*) [Preorder α] [Preorder β] [AddZero /-- Infix notation for `OrderAddMonoidHom`. -/ infixr:25 " →+o " => OrderAddMonoidHom +/-- `α ≃+o β` is the type of monotone isomorphisms `α ≃ β` that preserve the `OrderedAddCommMonoid` +structure. + +`OrderAddMonoidIso` is also used for ordered group isomorphisms. + +When possible, instead of parametrizing results over `(f : α ≃+o β)`, +you should parametrize over +`(F : Type*) [FunLike F M N] [AddEquivClass F M N] [OrderIsoClass F M N] (f : F)`. -/ +structure OrderAddMonoidIso (α β : Type*) [Preorder α] [Preorder β] [AddZeroClass α] + [AddZeroClass β] extends α ≃+ β where + /-- An `OrderAddMonoidIso` respects `≤`. -/ + map_le_map_iff' {a b : α} : toFun a ≤ toFun b ↔ a ≤ b + +/-- Infix notation for `OrderAddMonoidIso`. -/ +infixr:25 " ≃+o " => OrderAddMonoidIso + -- Instances and lemmas are defined below through `@[to_additive]`. end AddMonoid @@ -87,9 +107,8 @@ section Monoid `OrderMonoidHom` is also used for ordered group homomorphisms. When possible, instead of parametrizing results over `(f : α →*o β)`, -you should parametrize over `(F : Type*) [OrderMonoidHomClass F α β] (f : F)`. - -When you extend this structure, make sure to extend `OrderMonoidHomClass`. -/ +you should parametrize over +`(F : Type*) [FunLike F M N] [MonoidHomClass F M N] [OrderHomClass F M N] (f : F)`. -/ @[to_additive] structure OrderMonoidHom (α β : Type*) [Preorder α] [Preorder β] [MulOneClass α] [MulOneClass β] extends α →* β where @@ -104,8 +123,9 @@ variable [Preorder α] [Preorder β] [MulOneClass α] [MulOneClass β] [FunLike /-- Turn an element of a type `F` satisfying `OrderHomClass F α β` and `MonoidHomClass F α β` into an actual `OrderMonoidHom`. This is declared as the default coercion from `F` to `α →*o β`. -/ @[to_additive (attr := coe) - "Turn an element of a type `F` satisfying `OrderAddMonoidHomClass F α β` into an actual - `OrderAddMonoidHom`. This is declared as the default coercion from `F` to `α →+o β`."] + "Turn an element of a type `F` satisfying `OrderHomClass F α β` and `AddMonoidHomClass F α β` + into an actual `OrderAddMonoidHom`. + This is declared as the default coercion from `F` to `α →+o β`."] def OrderMonoidHomClass.toOrderMonoidHom [OrderHomClass F α β] [MonoidHomClass F α β] (f : F) : α →*o β := { (f : α →* β) with monotone' := OrderHomClass.monotone f } @@ -117,6 +137,49 @@ def OrderMonoidHomClass.toOrderMonoidHom [OrderHomClass F α β] [MonoidHomClass instance [OrderHomClass F α β] [MonoidHomClass F α β] : CoeTC F (α →*o β) := ⟨OrderMonoidHomClass.toOrderMonoidHom⟩ +/-- `α ≃*o β` is the type of isomorphisms `α ≃ β` that preserve the `OrderedCommMonoid` structure. + +`OrderMonoidIso` is also used for ordered group isomorphisms. + +When possible, instead of parametrizing results over `(f : α ≃*o β)`, +you should parametrize over +`(F : Type*) [FunLike F M N] [MulEquivClass F M N] [OrderIsoClass F M N] (f : F)`. -/ +@[to_additive] +structure OrderMonoidIso (α β : Type*) [Preorder α] [Preorder β] [MulOneClass α] + [MulOneClass β] extends α ≃* β where + /-- An `OrderMonoidIso` respects `≤`. -/ + map_le_map_iff' {a b : α} : toFun a ≤ toFun b ↔ a ≤ b + +/-- Infix notation for `OrderMonoidIso`. -/ +infixr:25 " ≃*o " => OrderMonoidIso + +variable [Preorder α] [Preorder β] [MulOneClass α] [MulOneClass β] [FunLike F α β] + +/-- Turn an element of a type `F` satisfying `OrderIsoClass F α β` and `MulEquivClass F α β` +into an actual `OrderMonoidIso`. This is declared as the default coercion from `F` to `α ≃*o β`. -/ +@[to_additive (attr := coe) + "Turn an element of a type `F` satisfying `OrderIsoClass F α β` and `AddEquivClass F α β` + into an actual `OrderAddMonoidIso`. + This is declared as the default coercion from `F` to `α ≃+o β`."] +def OrderMonoidIsoClass.toOrderMonoidIso [EquivLike F α β] [OrderIsoClass F α β] + [MulEquivClass F α β] (f : F) : + α ≃*o β := + { (f : α ≃* β) with map_le_map_iff' := OrderIsoClass.map_le_map_iff f } + +/-- Any type satisfying `OrderMonoidHomClass` can be cast into `OrderMonoidHom` via + `OrderMonoidHomClass.toOrderMonoidHom`. -/ +@[to_additive "Any type satisfying `OrderAddMonoidHomClass` can be cast into `OrderAddMonoidHom` via + `OrderAddMonoidHomClass.toOrderAddMonoidHom`"] +instance [OrderHomClass F α β] [MonoidHomClass F α β] : CoeTC F (α →*o β) := + ⟨OrderMonoidHomClass.toOrderMonoidHom⟩ + +/-- Any type satisfying `OrderMonoidIsoClass` can be cast into `OrderMonoidIso` via + `OrderMonoidIsoClass.toOrderMonoidIso`. -/ +@[to_additive "Any type satisfying `OrderAddMonoidIsoClass` can be cast into `OrderAddMonoidIso` via + `OrderAddMonoidIsoClass.toOrderAddMonoidIso`"] +instance [EquivLike F α β] [OrderIsoClass F α β] [MulEquivClass F α β] : CoeTC F (α ≃*o β) := + ⟨OrderMonoidIsoClass.toOrderMonoidIso⟩ + end Monoid section MonoidWithZero @@ -129,9 +192,8 @@ the `MonoidWithZero` structure. `OrderMonoidWithZeroHom` is also used for group homomorphisms. When possible, instead of parametrizing results over `(f : α →+ β)`, -you should parametrize over `(F : Type*) [OrderMonoidWithZeroHomClass F α β] (f : F)`. - -When you extend this structure, make sure to extend `OrderMonoidWithZeroHomClass`. -/ +you should parameterize over +`(F : Type*) [FunLike F M N] [MonoidWithZeroHomClass F M N] [OrderHomClass F M N] (f : F)`. -/ structure OrderMonoidWithZeroHom (α β : Type*) [Preorder α] [Preorder β] [MulZeroOneClass α] [MulZeroOneClass β] extends α →*₀ β where /-- An `OrderMonoidWithZeroHom` is a monotone function. -/ @@ -446,6 +508,172 @@ end OrderedCommGroup end OrderMonoidHom +namespace OrderMonoidIso + +section Preorder + +variable [Preorder α] [Preorder β] [Preorder γ] [Preorder δ] [MulOneClass α] [MulOneClass β] + [MulOneClass γ] [MulOneClass δ] {f g : α ≃*o β} + +@[to_additive] +instance : EquivLike (α ≃*o β) α β 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 + obtain ⟨⟨⟨_, _⟩⟩, _⟩ := f + obtain ⟨⟨⟨_, _⟩⟩, _⟩ := g + congr + +@[to_additive] +instance : OrderIsoClass (α ≃*o β) α β where + map_le_map_iff f := f.map_le_map_iff' + +@[to_additive] +instance : MulEquivClass (α ≃*o β) α β where + map_mul f := map_mul f.toMulEquiv + +-- Other lemmas should be accessed through the `FunLike` API +@[to_additive (attr := ext)] +theorem ext (h : ∀ a, f a = g a) : f = g := + DFunLike.ext f g h + +@[to_additive] +theorem toFun_eq_coe (f : α ≃*o β) : f.toFun = (f : α → β) := + rfl + +@[to_additive (attr := simp)] +theorem coe_mk (f : α ≃* β) (h) : (OrderMonoidIso.mk f h : α → β) = f := + rfl + +@[to_additive (attr := simp)] +theorem mk_coe (f : α ≃*o β) (h) : OrderMonoidIso.mk (f : α ≃* β) h = f := rfl + +/-- Reinterpret an ordered monoid isomorphism as an order isomorphism. -/ +@[to_additive "Reinterpret an ordered additive monoid isomomorphism as an order isomomorphism."] +def toOrderIso (f : α ≃*o β) : α ≃o β := + { f with + map_rel_iff' := map_le_map_iff f } + +@[to_additive (attr := simp)] +theorem coe_mulEquiv (f : α ≃*o β) : ((f : α ≃* β) : α → β) = f := + rfl + +@[to_additive (attr := simp)] +theorem coe_orderIso (f : α ≃*o β) : ((f : α →o β) : α → β) = f := + rfl + +@[to_additive] +theorem toMulEquiv_injective : Injective (toMulEquiv : _ → α ≃* β) := fun f g h => + ext <| by convert DFunLike.ext_iff.1 h using 0 + +@[to_additive] +theorem toOrderIso_injective : Injective (toOrderIso : _ → α ≃o β) := fun f g h => + ext <| by convert DFunLike.ext_iff.1 h using 0 + +variable (α) + +/-- The identity map as an ordered monoid isomorphism. -/ +@[to_additive "The identity map as an ordered additive monoid isomorphism."] +protected def refl : α ≃*o α := + { MulEquiv.refl α with map_le_map_iff' := by simp } + +@[to_additive (attr := simp)] +theorem coe_refl : ⇑(OrderMonoidIso.refl α) = id := + rfl + +@[to_additive] +instance : Inhabited (α ≃*o α) := + ⟨OrderMonoidIso.refl α⟩ + +variable {α} + +/-- Transitivity of multiplication-preserving order isomorphisms -/ +@[to_additive (attr := trans) "Transitivity of addition-preserving order isomorphisms"] +def trans (f : α ≃*o β) (g : β ≃*o γ) : α ≃*o γ := + { (f : α ≃* β).trans g with map_le_map_iff' := by simp } + +@[to_additive (attr := simp)] +theorem coe_trans (f : α ≃*o β) (g : β ≃*o γ) : (f.trans g : α → γ) = g ∘ f := + rfl + +@[to_additive (attr := simp)] +theorem trans_apply (f : α ≃*o β) (g : β ≃*o γ) (a : α) : (f.trans g) a = g (f a) := + rfl + +@[to_additive] +theorem coe_trans_mulEquiv (f : α ≃*o β) (g : β ≃*o γ) : + (f.trans g : α ≃* γ) = (f : α ≃* β).trans g := + rfl + +@[to_additive] +theorem coe_trans_orderIso (f : α ≃*o β) (g : β ≃*o γ) : + (f.trans g : α ≃o γ) = (f : α ≃o β).trans g := + rfl + +@[to_additive (attr := simp)] +theorem trans_assoc (f : α ≃*o β) (g : β ≃*o γ) (h : γ ≃*o δ) : + (f.trans g).trans h = f.trans (g.trans h) := + rfl + +@[to_additive (attr := simp)] +theorem trans_refl (f : α ≃*o β) : f.trans (OrderMonoidIso.refl β) = f := + rfl + +@[to_additive (attr := simp)] +theorem refl_trans (f : α ≃*o β) : (OrderMonoidIso.refl α).trans f = f := + rfl + +@[to_additive (attr := simp)] +theorem cancel_right {g₁ g₂ : α ≃*o β} {f : β ≃*o γ} (hf : Function.Injective f) : + g₁.trans f = g₂.trans f ↔ g₁ = g₂ := + ⟨fun h => ext fun a => hf <| by rw [← trans_apply, h, trans_apply], by rintro rfl; rfl⟩ + +@[to_additive (attr := simp)] +theorem cancel_left {g : α ≃*o β} {f₁ f₂ : β ≃*o γ} (hg : Function.Surjective g) : + g.trans f₁ = g.trans f₂ ↔ f₁ = f₂ := + ⟨fun h => ext <| hg.forall.2 <| DFunLike.ext_iff.1 h, fun _ => by congr⟩ + +@[to_additive (attr := simp)] +theorem toMulEquiv_eq_coe (f : α ≃*o β) : f.toMulEquiv = f := + rfl + +@[to_additive (attr := simp)] +theorem toOrderIso_eq_coe (f : α ≃*o β) : f.toOrderIso = f := + rfl + +variable (f) + +@[to_additive] +protected lemma strictMono : StrictMono f := + strictMono_of_le_iff_le fun _ _ ↦ (map_le_map_iff _).symm + +@[to_additive] +protected lemma strictMono_symm : StrictMono f.symm := + strictMono_of_le_iff_le <| fun a b ↦ by + rw [← map_le_map_iff f] + convert Iff.rfl <;> + exact f.toEquiv.apply_symm_apply _ + +end Preorder + +section OrderedCommGroup + +variable {hα : OrderedCommGroup α} {hβ : OrderedCommGroup β} + +/-- Makes an ordered group isomorphism from a proof that the map preserves multiplication. -/ +@[to_additive + "Makes an ordered additive group isomorphism from a proof that the map preserves + addition."] +def mk' (f : α ≃ β) (hf : ∀ {a b}, f a ≤ f b ↔ a ≤ b) (map_mul : ∀ a b : α, f (a * b) = f a * f b) : + α ≃*o β := + { MulEquiv.mk' f map_mul with map_le_map_iff' := hf } + +end OrderedCommGroup + +end OrderMonoidIso + namespace OrderMonoidWithZeroHom section Preorder diff --git a/Mathlib/Algebra/Order/Hom/Ring.lean b/Mathlib/Algebra/Order/Hom/Ring.lean index 72c23ef5ca89e..fd1d21c0b1a1f 100644 --- a/Mathlib/Algebra/Order/Hom/Ring.lean +++ b/Mathlib/Algebra/Order/Hom/Ring.lean @@ -388,8 +388,7 @@ def Simps.symm_apply (e : α ≃+*o β) : β → α := e.symm @[simp] -theorem symm_symm (e : α ≃+*o β) : e.symm.symm = e := - ext fun _ => rfl +theorem symm_symm (e : α ≃+*o β) : e.symm.symm = e := rfl /-- Composition of `OrderRingIso`s as an `OrderRingIso`. -/ @[trans] diff --git a/Mathlib/Algebra/Order/Interval/Basic.lean b/Mathlib/Algebra/Order/Interval/Basic.lean index 005379a7fa950..53c70afe40a7b 100644 --- a/Mathlib/Algebra/Order/Interval/Basic.lean +++ b/Mathlib/Algebra/Order/Interval/Basic.lean @@ -3,8 +3,8 @@ Copyright (c) 2022 Yaël Dillies. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies -/ +import Mathlib.Algebra.Group.Pointwise.Set import Mathlib.Algebra.Order.BigOperators.Group.Finset -import Mathlib.Data.Set.Pointwise.Basic import Mathlib.Order.Interval.Basic /-! diff --git a/Mathlib/Algebra/Order/Kleene.lean b/Mathlib/Algebra/Order/Kleene.lean index 4a57e54379465..064a1499bf6bf 100644 --- a/Mathlib/Algebra/Order/Kleene.lean +++ b/Mathlib/Algebra/Order/Kleene.lean @@ -4,11 +4,10 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Siddhartha Prasad, Yaël Dillies -/ import Mathlib.Algebra.Order.Monoid.Canonical.Defs -import Mathlib.Algebra.Ring.Pi import Mathlib.Algebra.Ring.InjSurj -import Mathlib.Tactic.Monotonicity.Attr +import Mathlib.Algebra.Ring.Pi import Mathlib.Algebra.Ring.Prod -import Mathlib.Algebra.Order.Monoid.Canonical.Defs +import Mathlib.Tactic.Monotonicity.Attr /-! # Kleene Algebras diff --git a/Mathlib/Algebra/Order/Module/Defs.lean b/Mathlib/Algebra/Order/Module/Defs.lean index 00394f272ebbe..fbf1c3d4a4b3b 100644 --- a/Mathlib/Algebra/Order/Module/Defs.lean +++ b/Mathlib/Algebra/Order/Module/Defs.lean @@ -3,12 +3,10 @@ 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.Module.Defs import Mathlib.Algebra.Order.Field.Defs -import Mathlib.Algebra.Order.GroupWithZero.Unbundled -import Mathlib.Algebra.Order.Module.Synonym -import Mathlib.GroupTheory.GroupAction.Group +import Mathlib.Algebra.Order.GroupWithZero.Action.Synonym import Mathlib.Tactic.Positivity.Core -import Mathlib.Algebra.Order.Field.Unbundled.Basic /-! # Monotonicity of scalar multiplication by positive elements @@ -954,13 +952,13 @@ variable [LinearOrderedSemifield α] [AddCommGroup β] [PartialOrder β] instance (priority := 100) PosSMulMono.toPosSMulReflectLE [MulAction α β] [PosSMulMono α β] : PosSMulReflectLE α β where elim _a ha b₁ b₂ h := by - simpa [ha.ne'] using smul_le_smul_of_nonneg_left h <| inv_nonneg (α := α) |>.2 ha.le + simpa [ha.ne'] using smul_le_smul_of_nonneg_left h <| inv_nonneg.2 ha.le -- See note [lower instance priority] instance (priority := 100) PosSMulStrictMono.toPosSMulReflectLT [MulActionWithZero α β] [PosSMulStrictMono α β] : PosSMulReflectLT α β := PosSMulReflectLT.of_pos fun a ha b₁ b₂ h ↦ by - simpa [ha.ne'] using smul_lt_smul_of_pos_left h <| inv_pos (α := α) |>.2 ha + simpa [ha.ne'] using smul_lt_smul_of_pos_left h <| inv_pos.2 ha end LinearOrderedSemifield @@ -1165,7 +1163,7 @@ end NoZeroSMulDivisors open Lean.Meta Qq -/-- Positivity extension for HSMul, i.e. (_ • _). -/ +/-- Positivity extension for HSMul, i.e. (_ • _). -/ @[positivity HSMul.hSMul _ _] def evalHSMul : PositivityExt where eval {_u α} zα pα (e : Q($α)) := do let .app (.app (.app (.app (.app (.app diff --git a/Mathlib/Algebra/Order/Module/OrderedSMul.lean b/Mathlib/Algebra/Order/Module/OrderedSMul.lean index 92fdcb6c87df6..bf1439508f708 100644 --- a/Mathlib/Algebra/Order/Module/OrderedSMul.lean +++ b/Mathlib/Algebra/Order/Module/OrderedSMul.lean @@ -3,6 +3,7 @@ Copyright (c) 2020 Frédéric Dupuis. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Frédéric Dupuis -/ +import Mathlib.Algebra.Group.Action.Basic import Mathlib.Algebra.Module.Pi import Mathlib.Algebra.Module.Prod import Mathlib.Algebra.Order.Module.Defs diff --git a/Mathlib/Algebra/Order/Module/Synonym.lean b/Mathlib/Algebra/Order/Module/Synonym.lean index 543be50af4709..bca6dfe28edc1 100644 --- a/Mathlib/Algebra/Order/Module/Synonym.lean +++ b/Mathlib/Algebra/Order/Module/Synonym.lean @@ -4,83 +4,25 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies -/ import Mathlib.Algebra.Module.Defs -import Mathlib.Algebra.Order.GroupWithZero.Synonym +import Mathlib.Algebra.Order.GroupWithZero.Action.Synonym import Mathlib.Algebra.Order.Ring.Synonym /-! # Action instances for `OrderDual` -This file provides instances of algebraic actions for `OrderDual`. Note that the `SMul` instances -are already defined in `Mathlib.Algebra.Order.Group.Synonym`. + +This PR transfers group action with zero instances from a type `α` to `αᵒᵈ` and `Lex α`. Note that +the `SMul` instances are already defined in `Mathlib.Algebra.Order.Group.Synonym`. ## See also -* `Mathlib.Algebra.Order.Group.Synonym` -* `Mathlib.Algebra.Order.Ring.Synonym` +* `Mathlib.Algebra.Order.Group.Action.Synonym` +* `Mathlib.Algebra.Order.GroupWithZero.Action.Synonym` -/ -namespace OrderDual -variable {α β γ : Type*} - -instance instSMulWithZero [Zero α] [Zero β] [SMulWithZero α β] : SMulWithZero αᵒᵈ β where - zero_smul := zero_smul α - smul_zero := smul_zero (M := α) - -instance instSMulWithZero' [Zero α] [Zero β] [SMulWithZero α β] : SMulWithZero α βᵒᵈ where - zero_smul := zero_smul _ (M := β) - smul_zero := smul_zero (A := β) - -@[to_additive] -instance instMulAction [Monoid α] [MulAction α β] : MulAction αᵒᵈ β where - one_smul := one_smul α - mul_smul := mul_smul (α := α) - -@[to_additive] -instance instMulAction' [Monoid α] [MulAction α β] : MulAction α βᵒᵈ where - one_smul := one_smul _ (α := β) - mul_smul := mul_smul (β := β) - -@[to_additive] -instance instSMulCommClass [SMul β γ] [SMul α γ] [SMulCommClass α β γ] : SMulCommClass αᵒᵈ β γ := - ‹SMulCommClass α β γ› - -@[to_additive] -instance instSMulCommClass' [SMul β γ] [SMul α γ] [SMulCommClass α β γ] : SMulCommClass α βᵒᵈ γ := - ‹SMulCommClass α β γ› - -@[to_additive] -instance instSMulCommClass'' [SMul β γ] [SMul α γ] [SMulCommClass α β γ] : SMulCommClass α β γᵒᵈ := - ‹SMulCommClass α β γ› - -@[to_additive instVAddAssocClass] -instance instIsScalarTower [SMul α β] [SMul β γ] [SMul α γ] [IsScalarTower α β γ] : - IsScalarTower αᵒᵈ β γ := ‹IsScalarTower α β γ› +variable {α β : Type*} -@[to_additive instVAddAssocClass'] -instance instIsScalarTower' [SMul α β] [SMul β γ] [SMul α γ] [IsScalarTower α β γ] : - IsScalarTower α βᵒᵈ γ := ‹IsScalarTower α β γ› - -@[to_additive instVAddAssocClass''] -instance instIsScalarTower'' [SMul α β] [SMul β γ] [SMul α γ] [IsScalarTower α β γ] : - IsScalarTower α β γᵒᵈ := ‹IsScalarTower α β γ› - -instance instMulActionWithZero [MonoidWithZero α] [AddMonoid β] [MulActionWithZero α β] : - MulActionWithZero αᵒᵈ β := - { OrderDual.instMulAction, OrderDual.instSMulWithZero with } - -instance instMulActionWithZero' [MonoidWithZero α] [AddMonoid β] [MulActionWithZero α β] : - MulActionWithZero α βᵒᵈ := - { OrderDual.instMulAction', OrderDual.instSMulWithZero' with } - -instance instDistribMulAction [MonoidWithZero α] [AddMonoid β] [DistribMulAction α β] : - DistribMulAction αᵒᵈ β where - smul_add := smul_add (M := α) - smul_zero := smul_zero (M := α) - -instance instDistribMulAction' [MonoidWithZero α] [AddMonoid β] [DistribMulAction α β] : - DistribMulAction α βᵒᵈ where - smul_add := smul_add (A := β) - smul_zero := smul_zero (A := β) +namespace OrderDual instance instModule [Semiring α] [AddCommMonoid β] [Module α β] : Module αᵒᵈ β where add_smul := add_smul (R := α) @@ -91,3 +33,13 @@ instance instModule' [Semiring α] [AddCommMonoid β] [Module α β] : Module α zero_smul := zero_smul _ end OrderDual + +namespace Lex + +instance instModule [Semiring α] [AddCommMonoid β] [Module α β] : Module (Lex α) β := + ‹Module α β› + +instance instModule' [Semiring α] [AddCommMonoid β] [Module α β] : Module α (Lex β) := + ‹Module α β› + +end Lex diff --git a/Mathlib/Algebra/Order/Monoid/Canonical/Defs.lean b/Mathlib/Algebra/Order/Monoid/Canonical/Defs.lean index 87f6d53965914..6e2104c91ef78 100644 --- a/Mathlib/Algebra/Order/Monoid/Canonical/Defs.lean +++ b/Mathlib/Algebra/Order/Monoid/Canonical/Defs.lean @@ -128,6 +128,10 @@ theorem one_lt_iff_ne_one : 1 < a ↔ a ≠ 1 := @[to_additive] theorem eq_one_or_one_lt (a : α) : a = 1 ∨ 1 < a := (one_le a).eq_or_lt.imp_left Eq.symm +@[to_additive] +lemma one_not_mem_iff {s : Set α} : 1 ∉ s ↔ ∀ x ∈ s, 1 < x := + bot_eq_one (α := α) ▸ bot_not_mem_iff + @[to_additive (attr := simp) add_pos_iff] theorem one_lt_mul_iff : 1 < a * b ↔ 1 < a ∨ 1 < b := by simp only [one_lt_iff_ne_one, Ne, mul_eq_one, not_and_or] diff --git a/Mathlib/Algebra/Order/Monoid/Submonoid.lean b/Mathlib/Algebra/Order/Monoid/Submonoid.lean index 6aa9c7927f6b2..d88dd033520c1 100644 --- a/Mathlib/Algebra/Order/Monoid/Submonoid.lean +++ b/Mathlib/Algebra/Order/Monoid/Submonoid.lean @@ -3,16 +3,15 @@ Copyright (c) 2021 Damiano Testa. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Damiano Testa -/ - import Mathlib.Algebra.Group.Submonoid.Operations -import Mathlib.Algebra.Order.GroupWithZero.Unbundled import Mathlib.Algebra.Order.Monoid.Basic -import Mathlib.Algebra.Order.ZeroLEOne /-! # Ordered instances on submonoids -/ +assert_not_exists MonoidWithZero + namespace SubmonoidClass variable {M S : Type*} [SetLike S M] @@ -103,21 +102,4 @@ variable {M} @[to_additive (attr := simp) mem_nonneg] lemma mem_oneLE : a ∈ oneLE M ↔ 1 ≤ a := Iff.rfl end Preorder - -section MulZeroClass -variable (α) [MulZeroOneClass α] [PartialOrder α] [PosMulStrictMono α] [ZeroLEOneClass α] - [NeZero (1 : α)] {a : α} - -/-- The submonoid of positive elements. -/ -@[simps] def pos : Submonoid α where - carrier := Set.Ioi 0 - one_mem' := zero_lt_one - mul_mem' := mul_pos - -variable {α} - -@[simp] lemma mem_pos : a ∈ pos α ↔ 0 < a := Iff.rfl - -end MulZeroClass - end Submonoid diff --git a/Mathlib/Algebra/Order/Monoid/Unbundled/Defs.lean b/Mathlib/Algebra/Order/Monoid/Unbundled/Defs.lean index 4cd50c3dca94c..a86ce7532c9ee 100644 --- a/Mathlib/Algebra/Order/Monoid/Unbundled/Defs.lean +++ b/Mathlib/Algebra/Order/Monoid/Unbundled/Defs.lean @@ -117,6 +117,142 @@ class ContravariantClass : Prop where `r` also holds for the pair `(n₁, n₂)`. -/ protected elim : Contravariant M N μ r +/-- Typeclass for monotonicity of multiplication on the left, +namely `b₁ ≤ b₂ → a * b₁ ≤ a * b₂`. + +You should usually not use this very granular typeclass directly, but rather a typeclass like +`OrderedCommMonoid`. -/ +abbrev MulLeftMono [Mul M] [LE M] : Prop := + CovariantClass M M (· * ·) (· ≤ ·) + +/-- Typeclass for monotonicity of multiplication on the right, +namely `a₁ ≤ a₂ → a₁ * b ≤ a₂ * b`. + +You should usually not use this very granular typeclass directly, but rather a typeclass like +`OrderedCommMonoid`. -/ +abbrev MulRightMono [Mul M] [LE M] : Prop := + CovariantClass M M (swap (· * ·)) (· ≤ ·) + +/-- Typeclass for monotonicity of addition on the left, +namely `b₁ ≤ b₂ → a + b₁ ≤ a + b₂`. + +You should usually not use this very granular typeclass directly, but rather a typeclass like +`OrderedAddCommMonoid`. -/ +abbrev AddLeftMono [Add M] [LE M] : Prop := + CovariantClass M M (· + ·) (· ≤ ·) + +/-- Typeclass for monotonicity of addition on the right, +namely `a₁ ≤ a₂ → a₁ + b ≤ a₂ + b`. + +You should usually not use this very granular typeclass directly, but rather a typeclass like +`OrderedAddCommMonoid`. -/ +abbrev AddRightMono [Add M] [LE M] : Prop := + CovariantClass M M (swap (· + ·)) (· ≤ ·) + +attribute [to_additive existing] MulLeftMono MulRightMono + +/-- Typeclass for monotonicity of multiplication on the left, +namely `b₁ < b₂ → a * b₁ < a * b₂`. + +You should usually not use this very granular typeclass directly, but rather a typeclass like +`OrderedCommGroup`. -/ +abbrev MulLeftStrictMono [Mul M] [LT M] : Prop := + CovariantClass M M (· * ·) (· < ·) + +/-- Typeclass for monotonicity of multiplication on the right, +namely `a₁ < a₂ → a₁ * b < a₂ * b`. + +You should usually not use this very granular typeclass directly, but rather a typeclass like +`OrderedCommGroup`. -/ +abbrev MulRightStrictMono [Mul M] [LT M] : Prop := + CovariantClass M M (swap (· * ·)) (· < ·) + +/-- Typeclass for monotonicity of addition on the left, +namely `b₁ < b₂ → a + b₁ < a + b₂`. + +You should usually not use this very granular typeclass directly, but rather a typeclass like +`OrderedAddCommGroup`. -/ +abbrev AddLeftStrictMono [Add M] [LT M] : Prop := + CovariantClass M M (· + ·) (· < ·) + +/-- Typeclass for monotonicity of addition on the right, +namely `a₁ < a₂ → a₁ + b < a₂ + b`. + +You should usually not use this very granular typeclass directly, but rather a typeclass like +`OrderedAddCommGroup`. -/ +abbrev AddRightStrictMono [Add M] [LT M] : Prop := + CovariantClass M M (swap (· + ·)) (· < ·) + +attribute [to_additive existing] MulLeftStrictMono MulRightStrictMono + +/-- Typeclass for strict reverse monotonicity of multiplication on the left, +namely `a * b₁ < a * b₂ → b₁ < b₂`. + +You should usually not use this very granular typeclass directly, but rather a typeclass like +`OrderedCommGroup`. -/ +abbrev MulLeftReflectLT [Mul M] [LT M] : Prop := + ContravariantClass M M (· * ·) (· < ·) + +/-- Typeclass for strict reverse monotonicity of multiplication on the right, +namely `a₁ * b < a₂ * b → a₁ < a₂`. + +You should usually not use this very granular typeclass directly, but rather a typeclass like +`OrderedCommGroup`. -/ +abbrev MulRightReflectLT [Mul M] [LT M] : Prop := + ContravariantClass M M (swap (· * ·)) (· < ·) + +/-- Typeclass for strict reverse monotonicity of addition on the left, +namely `a + b₁ < a + b₂ → b₁ < b₂`. + +You should usually not use this very granular typeclass directly, but rather a typeclass like +`OrderedAddCommGroup`. -/ +abbrev AddLeftReflectLT [Add M] [LT M] : Prop := + ContravariantClass M M (· + ·) (· < ·) + +/-- Typeclass for strict reverse monotonicity of addition on the right, +namely `a₁ * b < a₂ * b → a₁ < a₂`. + +You should usually not use this very granular typeclass directly, but rather a typeclass like +`OrderedAddCommGroup`. -/ +abbrev AddRightReflectLT [Add M] [LT M] : Prop := + ContravariantClass M M (swap (· + ·)) (· < ·) + +attribute [to_additive existing] MulLeftReflectLT MulRightReflectLT + +/-- Typeclass for reverse monotonicity of multiplication on the left, +namely `a * b₁ ≤ a * b₂ → b₁ ≤ b₂`. + +You should usually not use this very granular typeclass directly, but rather a typeclass like +`OrderedCancelCommMonoid`. -/ +abbrev MulLeftReflectLE [Mul M] [LE M] : Prop := + ContravariantClass M M (· * ·) (· ≤ ·) + +/-- Typeclass for reverse monotonicity of multiplication on the right, +namely `a₁ * b ≤ a₂ * b → a₁ ≤ a₂`. + +You should usually not use this very granular typeclass directly, but rather a typeclass like +`OrderedCancelCommMonoid`. -/ +abbrev MulRightReflectLE [Mul M] [LE M] : Prop := + ContravariantClass M M (swap (· * ·)) (· ≤ ·) + +/-- Typeclass for reverse monotonicity of addition on the left, +namely `a + b₁ ≤ a + b₂ → b₁ ≤ b₂`. + +You should usually not use this very granular typeclass directly, but rather a typeclass like +`OrderedCancelAddCommMonoid`. -/ +abbrev AddLeftReflectLE [Add M] [LE M] : Prop := + ContravariantClass M M (· + ·) (· ≤ ·) + +/-- Typeclass for reverse monotonicity of addition on the right, +namely `a₁ + b ≤ a₂ + b → a₁ ≤ a₂`. + +You should usually not use this very granular typeclass directly, but rather a typeclass like +`OrderedCancelAddCommMonoid`. -/ +abbrev AddRightReflectLE [Add M] [LE M] : Prop := + ContravariantClass M M (swap (· + ·)) (· ≤ ·) + +attribute [to_additive existing] MulLeftReflectLE MulRightReflectLE + theorem rel_iff_cov [CovariantClass M N μ r] [ContravariantClass M N μ r] (m : M) {a b : N} : r (μ m a) (μ m b) ↔ r a b := ⟨ContravariantClass.elim _, CovariantClass.elim _⟩ @@ -154,6 +290,16 @@ instance (priority := 100) Group.covconv [Group N] [CovariantClass N N (· * ·) ContravariantClass N N (· * ·) r := ⟨Group.covariant_iff_contravariant.mp CovariantClass.elim⟩ +@[to_additive] +theorem Group.mulLeftReflectLE_of_mulLeftMono [Group N] [LE N] + [MulLeftMono N] : MulLeftReflectLE N := + inferInstance + +@[to_additive] +theorem Group.mulLeftReflectLT_of_mulLeftStrictMono [Group N] [LT N] + [MulLeftStrictMono N] : MulLeftReflectLT N := + inferInstance + @[to_additive] theorem Group.covariant_swap_iff_contravariant_swap [Group N] : Covariant N N (swap (· * ·)) r ↔ Contravariant N N (swap (· * ·)) r := by @@ -169,6 +315,16 @@ instance (priority := 100) Group.covconv_swap [Group N] [CovariantClass N N (swa ContravariantClass N N (swap (· * ·)) r := ⟨Group.covariant_swap_iff_contravariant_swap.mp CovariantClass.elim⟩ +@[to_additive] +theorem Group.mulRightReflectLE_of_mulRightMono [Group N] [LE N] + [MulRightMono N] : MulRightReflectLE N := + inferInstance + +@[to_additive] +theorem Group.mulRightReflectLT_of_mulRightStrictMono [Group N] [LT N] + [MulRightStrictMono N] : MulRightReflectLT N := + inferInstance + section Trans @@ -263,6 +419,14 @@ theorem covariant_le_of_covariant_lt [PartialOrder N] : theorem covariantClass_le_of_lt [PartialOrder N] [CovariantClass M N μ (· < ·)] : CovariantClass M N μ (· ≤ ·) := ⟨covariant_le_of_covariant_lt _ _ _ CovariantClass.elim⟩ +@[to_additive] +theorem mulLeftMono_of_mulLeftStrictMono (M) [Mul M] [PartialOrder M] [MulLeftStrictMono M] : + MulLeftMono M := covariantClass_le_of_lt _ _ _ + +@[to_additive] +theorem mulRightMono_of_mulRightStrictMono (M) [Mul M] [PartialOrder M] [MulRightStrictMono M] : + MulRightMono M := covariantClass_le_of_lt _ _ _ + theorem contravariant_le_iff_contravariant_lt_and_eq [PartialOrder N] : Contravariant M N μ (· ≤ ·) ↔ Contravariant M N μ (· < ·) ∧ Contravariant M N μ (· = ·) := by refine ⟨fun h ↦ ⟨fun a b c bc ↦ ?_, fun a b c bc ↦ ?_⟩, fun h ↦ fun a b c bc ↦ ?_⟩ @@ -296,20 +460,60 @@ instance contravariant_lt_of_covariant_le [LinearOrder N] [CovariantClass N N mu (· ≤ ·)] : ContravariantClass N N mu (· < ·) where elim := (covariant_le_iff_contravariant_lt N N mu).mp CovariantClass.elim +@[to_additive] +theorem mulLeftReflectLT_of_mulLeftMono [Mul N] [LinearOrder N] [MulLeftMono N] : + MulLeftReflectLT N := + inferInstance + +@[to_additive] +theorem mulRightReflectLT_of_mulRightMono [Mul N] [LinearOrder N] [MulRightMono N] : + MulRightReflectLT N := + inferInstance + instance covariant_lt_of_contravariant_le [LinearOrder N] [ContravariantClass N N mu (· ≤ ·)] : CovariantClass N N mu (· < ·) where elim := (covariant_lt_iff_contravariant_le N N mu).mpr ContravariantClass.elim +@[to_additive] +theorem mulLeftStrictMono_of_mulLeftReflectLE [Mul N] [LinearOrder N] [MulLeftReflectLE N] : + MulLeftStrictMono N := + inferInstance + +@[to_additive] +theorem mulRightStrictMono_of_mulRightReflectLE [Mul N] [LinearOrder N] [MulRightReflectLE N] : + MulRightStrictMono N := + inferInstance + @[to_additive] instance covariant_swap_mul_of_covariant_mul [CommSemigroup N] [CovariantClass N N (· * ·) r] : CovariantClass N N (swap (· * ·)) r where elim := (covariant_flip_iff N r (· * ·)).mpr CovariantClass.elim +@[to_additive] +theorem mulRightMono_of_mulLeftMono [CommSemigroup N] [LE N] [MulLeftMono N] : + MulRightMono N := + inferInstance + +@[to_additive] +theorem mulRightStrictMono_of_mulLeftStrictMono [CommSemigroup N] [LT N] [MulLeftStrictMono N] : + MulRightStrictMono N := + inferInstance + @[to_additive] instance contravariant_swap_mul_of_contravariant_mul [CommSemigroup N] [ContravariantClass N N (· * ·) r] : ContravariantClass N N (swap (· * ·)) r where elim := (contravariant_flip_iff N r (· * ·)).mpr ContravariantClass.elim +@[to_additive] +theorem mulRightReflectLE_of_mulLeftReflectLE [CommSemigroup N] [LE N] [MulLeftReflectLE N] : + MulRightReflectLE N := + inferInstance + +@[to_additive] +theorem mulRightReflectLT_of_mulLeftReflectLT [CommSemigroup N] [LT N] [MulLeftReflectLT N] : + MulRightReflectLT N := + inferInstance + theorem covariant_lt_of_covariant_le_of_contravariant_eq [ContravariantClass M N μ (· = ·)] [PartialOrder N] [CovariantClass M N μ (· ≤ ·)] : CovariantClass M N μ (· < ·) where elim a _ _ bc := (CovariantClass.elim a bc.le).lt_of_ne (bc.ne ∘ ContravariantClass.elim _) diff --git a/Mathlib/Algebra/Order/Monoid/Unbundled/ExistsOfLE.lean b/Mathlib/Algebra/Order/Monoid/Unbundled/ExistsOfLE.lean index 6823941784225..da6e069dc2d22 100644 --- a/Mathlib/Algebra/Order/Monoid/Unbundled/ExistsOfLE.lean +++ b/Mathlib/Algebra/Order/Monoid/Unbundled/ExistsOfLE.lean @@ -1,27 +1,23 @@ /- -Copyright (c) 2016 Jeremy Avigad. All rights reserved. +Copyright (c) 2021 Peter Nelson. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Jeremy Avigad, Leonardo de Moura, Mario Carneiro, Johannes Hölzl +Authors: Peter Nelson, Yaël Dillies -/ import Mathlib.Algebra.Order.Monoid.Unbundled.Basic import Mathlib.Order.MinMax /-! # Unbundled and weaker forms of canonically ordered monoids + +This file provides a Prop-valued mixin for monoids satisfying a one-sided cancellativity property, +namely that there is some `c` such that `b = a + c` if `a ≤ b`. This is particularly useful for +generalising statements from groups/rings/fields that don't mention negation or subtraction to +monoids/semirings/semifields. -/ universe u - - variable {α : Type u} -/-- An `OrderedCommMonoid` with one-sided 'division' in the sense that -if `a ≤ b`, there is some `c` for which `a * c = b`. This is a weaker version -of the condition on canonical orderings defined by `CanonicallyOrderedCommMonoid`. -/ -class ExistsMulOfLE (α : Type u) [Mul α] [LE α] : Prop where - /-- For `a ≤ b`, `a` left divides `b` -/ - exists_mul_of_le : ∀ {a b : α}, a ≤ b → ∃ c : α, b = a * c - /-- An `OrderedAddCommMonoid` with one-sided 'subtraction' in the sense that if `a ≤ b`, then there is some `c` for which `a + c = b`. This is a weaker version of the condition on canonical orderings defined by `CanonicallyOrderedAddCommMonoid`. -/ @@ -29,10 +25,15 @@ class ExistsAddOfLE (α : Type u) [Add α] [LE α] : Prop where /-- For `a ≤ b`, there is a `c` so `b = a + c`. -/ exists_add_of_le : ∀ {a b : α}, a ≤ b → ∃ c : α, b = a + c -attribute [to_additive] ExistsMulOfLE +/-- An `OrderedCommMonoid` with one-sided 'division' in the sense that +if `a ≤ b`, there is some `c` for which `a * c = b`. This is a weaker version +of the condition on canonical orderings defined by `CanonicallyOrderedCommMonoid`. -/ +@[to_additive] +class ExistsMulOfLE (α : Type u) [Mul α] [LE α] : Prop where + /-- For `a ≤ b`, `a` left divides `b` -/ + exists_mul_of_le : ∀ {a b : α}, a ≤ b → ∃ c : α, b = a * c export ExistsMulOfLE (exists_mul_of_le) - export ExistsAddOfLE (exists_add_of_le) -- See note [lower instance priority] @@ -41,14 +42,23 @@ instance (priority := 100) Group.existsMulOfLE (α : Type u) [Group α] [LE α] ⟨fun {a b} _ => ⟨a⁻¹ * b, (mul_inv_cancel_left _ _).symm⟩⟩ section MulOneClass +variable [MulOneClass α] [Preorder α] [ExistsMulOfLE α] {a b : α} -variable [MulOneClass α] [Preorder α] [ContravariantClass α α (· * ·) (· < ·)] [ExistsMulOfLE α] - {a b : α} +@[to_additive] lemma exists_one_le_mul_of_le [ContravariantClass α α (· * ·) (· ≤ ·)] (h : a ≤ b) : + ∃ c, 1 ≤ c ∧ a * c = b := by + obtain ⟨c, rfl⟩ := exists_mul_of_le h; exact ⟨c, one_le_of_le_mul_right h, rfl⟩ -@[to_additive] -theorem exists_one_lt_mul_of_lt' (h : a < b) : ∃ c, 1 < c ∧ a * c = b := by - obtain ⟨c, rfl⟩ := exists_mul_of_le h.le - exact ⟨c, one_lt_of_lt_mul_right h, rfl⟩ +@[to_additive] lemma exists_one_lt_mul_of_lt' [ContravariantClass α α (· * ·) (· < ·)] (h : a < b) : + ∃ c, 1 < c ∧ a * c = b := by + obtain ⟨c, rfl⟩ := exists_mul_of_le h.le; exact ⟨c, one_lt_of_lt_mul_right h, rfl⟩ + +@[to_additive] lemma le_iff_exists_one_le_mul [CovariantClass α α (· * ·) (· ≤ ·)] + [ContravariantClass α α (· * ·) (· ≤ ·)] : a ≤ b ↔ ∃ c, 1 ≤ c ∧ a * c = b := + ⟨exists_one_le_mul_of_le, by rintro ⟨c, hc, rfl⟩; exact le_mul_of_one_le_right' hc⟩ + +@[to_additive] lemma lt_iff_exists_one_lt_mul [CovariantClass α α (· * ·) (· < ·)] + [ContravariantClass α α (· * ·) (· < ·)] : a < b ↔ ∃ c, 1 < c ∧ a * c = b := + ⟨exists_one_lt_mul_of_lt', by rintro ⟨c, hc, rfl⟩; exact lt_mul_of_one_lt_right' _ hc⟩ end MulOneClass @@ -72,5 +82,3 @@ theorem le_iff_forall_one_lt_lt_mul' : a ≤ b ↔ ∀ ε, 1 < ε → a < b * ε ⟨fun h _ => lt_mul_of_le_of_one_lt h, le_of_forall_one_lt_lt_mul'⟩ end ExistsMulOfLE - - diff --git a/Mathlib/Algebra/Order/Monoid/Unbundled/MinMax.lean b/Mathlib/Algebra/Order/Monoid/Unbundled/MinMax.lean index 35fb12d567968..b509125489cc7 100644 --- a/Mathlib/Algebra/Order/Monoid/Unbundled/MinMax.lean +++ b/Mathlib/Algebra/Order/Monoid/Unbundled/MinMax.lean @@ -21,7 +21,7 @@ section CommSemigroup variable [LinearOrder α] [CommSemigroup β] @[to_additive] -lemma fn_min_mul_fn_max (f : α → β) (a b : α) : f (min a b) * f (max a b) = f a * f b := by +lemma fn_min_mul_fn_max (f : α → β) (a b : α) : f (min a b) * f (max a b) = f a * f b := by obtain h | h := le_total a b <;> simp [h, mul_comm] @[to_additive] @@ -108,7 +108,7 @@ theorem mul_lt_mul_iff_of_le_of_le [CovariantClass α α (· * ·) (· ≤ ·)] [CovariantClass α α (Function.swap (· * ·)) (· < ·)] {a₁ a₂ b₁ b₂ : α} (ha : a₁ ≤ a₂) (hb : b₁ ≤ b₂) : a₁ * b₁ < a₂ * b₂ ↔ a₁ < a₂ ∨ b₁ < b₂ := by refine ⟨lt_or_lt_of_mul_lt_mul, fun h => ?_⟩ - cases' h with ha' hb' + rcases h with ha' | hb' · exact mul_lt_mul_of_lt_of_le ha' hb · exact mul_lt_mul_of_le_of_lt ha hb' diff --git a/Mathlib/Algebra/Order/Monoid/Unbundled/Pow.lean b/Mathlib/Algebra/Order/Monoid/Unbundled/Pow.lean index ca33dfd14cedd..877d5f5f47c07 100644 --- a/Mathlib/Algebra/Order/Monoid/Unbundled/Pow.lean +++ b/Mathlib/Algebra/Order/Monoid/Unbundled/Pow.lean @@ -62,10 +62,9 @@ theorem pow_le_pow_right_of_le_one' {a : M} {n m : ℕ} (ha : a ≤ 1) (h : n theorem one_lt_pow' {a : M} (ha : 1 < a) {k : ℕ} (hk : k ≠ 0) : 1 < a ^ k := by rcases Nat.exists_eq_succ_of_ne_zero hk with ⟨l, rfl⟩ clear hk - induction' l with l IH - · rw [pow_succ]; simpa using ha - · rw [pow_succ] - exact one_lt_mul'' IH ha + induction l with + | zero => rw [pow_succ]; simpa using ha + | succ l IH => rw [pow_succ]; exact one_lt_mul'' IH ha @[to_additive nsmul_neg] theorem pow_lt_one' {a : M} (ha : a < 1) {k : ℕ} (hk : k ≠ 0) : a ^ k < 1 := diff --git a/Mathlib/Algebra/Order/Monoid/Unbundled/WithTop.lean b/Mathlib/Algebra/Order/Monoid/Unbundled/WithTop.lean index ff3e96790de20..7d7bdb4f2ff25 100644 --- a/Mathlib/Algebra/Order/Monoid/Unbundled/WithTop.lean +++ b/Mathlib/Algebra/Order/Monoid/Unbundled/WithTop.lean @@ -305,9 +305,9 @@ instance addMonoidWithOne : AddMonoidWithOne (WithTop α) := @[simp, norm_cast] lemma coe_natCast (n : ℕ) : ((n : α) : WithTop α) = n := rfl -@[simp] lemma natCast_ne_top (n : ℕ) : (n : WithTop α) ≠ ⊤ := coe_ne_top - @[simp] lemma top_ne_natCast (n : ℕ) : (⊤ : WithTop α) ≠ n := top_ne_coe +@[simp] lemma natCast_ne_top (n : ℕ) : (n : WithTop α) ≠ ⊤ := coe_ne_top +@[simp] lemma natCast_lt_top [LT α] (n : ℕ) : (n : WithTop α) < ⊤ := coe_lt_top _ @[deprecated (since := "2024-04-05")] alias coe_nat := coe_natCast @[deprecated (since := "2024-04-05")] alias nat_ne_top := natCast_ne_top diff --git a/Mathlib/Algebra/Order/Monovary.lean b/Mathlib/Algebra/Order/Monovary.lean index ae10daf0e8d58..f742a97bcf60e 100644 --- a/Mathlib/Algebra/Order/Monovary.lean +++ b/Mathlib/Algebra/Order/Monovary.lean @@ -6,6 +6,7 @@ Authors: Yaël Dillies import Mathlib.Algebra.Order.Field.Basic import Mathlib.Algebra.Order.Group.Instances import Mathlib.Algebra.Order.Module.OrderedSMul +import Mathlib.Algebra.Order.Module.Synonym import Mathlib.Algebra.Order.Monoid.Unbundled.MinMax import Mathlib.Order.Monotone.Monovary diff --git a/Mathlib/Algebra/Order/Nonneg/Field.lean b/Mathlib/Algebra/Order/Nonneg/Field.lean index ccefe4dce40fa..d69aaf2a8dc28 100644 --- a/Mathlib/Algebra/Order/Nonneg/Field.lean +++ b/Mathlib/Algebra/Order/Nonneg/Field.lean @@ -6,7 +6,6 @@ Authors: Floris van Doorn import Mathlib.Algebra.Order.Field.Canonical.Defs import Mathlib.Algebra.Order.Field.InjSurj import Mathlib.Algebra.Order.Nonneg.Ring -import Mathlib.Algebra.Order.Field.Unbundled.Basic import Mathlib.Data.Nat.Cast.Order.Ring /-! @@ -46,7 +45,7 @@ section LinearOrderedSemifield variable [LinearOrderedSemifield α] {x y : α} instance inv : Inv { x : α // 0 ≤ x } := - ⟨fun x => ⟨x⁻¹, inv_nonneg (α := α) |>.2 x.2⟩⟩ + ⟨fun x => ⟨x⁻¹, inv_nonneg.2 x.2⟩⟩ @[simp, norm_cast] protected theorem coe_inv (a : { x : α // 0 ≤ x }) : ((a⁻¹ : { x : α // 0 ≤ x }) : α) = (a : α)⁻¹ := @@ -54,7 +53,7 @@ protected theorem coe_inv (a : { x : α // 0 ≤ x }) : ((a⁻¹ : { x : α // 0 @[simp] theorem inv_mk (hx : 0 ≤ x) : - (⟨x, hx⟩ : { x : α // 0 ≤ x })⁻¹ = ⟨x⁻¹, inv_nonneg (α := α) |>.2 hx⟩ := + (⟨x, hx⟩ : { x : α // 0 ≤ x })⁻¹ = ⟨x⁻¹, inv_nonneg.2 hx⟩ := rfl instance div : Div { x : α // 0 ≤ x } := diff --git a/Mathlib/Algebra/Order/Nonneg/Ring.lean b/Mathlib/Algebra/Order/Nonneg/Ring.lean index 46375d95d4a1d..87af067c65378 100644 --- a/Mathlib/Algebra/Order/Nonneg/Ring.lean +++ b/Mathlib/Algebra/Order/Nonneg/Ring.lean @@ -78,12 +78,24 @@ instance orderedCommSemiring [OrderedCommSemiring α] : OrderedCommSemiring { x (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) fun _ => rfl +instance orderedCommMonoid [OrderedCommSemiring α] : OrderedCommMonoid { x : α // 0 ≤ x } where + mul_le_mul_left a _ h c := mul_le_mul le_rfl h a.prop c.prop + instance strictOrderedCommSemiring [StrictOrderedCommSemiring α] : StrictOrderedCommSemiring { x : α // 0 ≤ x } := Subtype.coe_injective.strictOrderedCommSemiring _ Nonneg.coe_zero Nonneg.coe_one (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) fun _ => rfl +instance existsAddOfLE [StrictOrderedCommSemiring α] [ExistsAddOfLE α] : + ExistsAddOfLE { x : α // 0 ≤ x } := + ⟨fun {a b} h ↦ by + rw [← Subtype.coe_le_coe] at h + obtain ⟨c, hc⟩ := exists_add_of_le h + refine ⟨⟨c, ?_⟩, by simp [Subtype.ext_iff, hc]⟩ + rw [← add_zero a.val, hc] at h + exact le_of_add_le_add_left h⟩ + instance nontrivial [LinearOrderedSemiring α] : Nontrivial { x : α // 0 ≤ x } := ⟨⟨0, 1, fun h => zero_ne_one (congr_arg Subtype.val h)⟩⟩ @@ -93,7 +105,7 @@ instance linearOrderedSemiring [LinearOrderedSemiring α] : (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ => rfl) (fun _ _ => rfl) fun _ _ => rfl -instance linearOrderedCommMonoidWithZero [LinearOrderedCommRing α] : +instance linearOrderedCommMonoidWithZero [LinearOrderedCommSemiring α] : LinearOrderedCommMonoidWithZero { x : α // 0 ≤ x } := { Nonneg.linearOrderedSemiring, Nonneg.orderedCommSemiring with mul_le_mul_left := fun _ _ h c ↦ mul_le_mul_of_nonneg_left h c.prop } diff --git a/Mathlib/Algebra/Order/Pi.lean b/Mathlib/Algebra/Order/Pi.lean index b89f80e5f895b..be50955c5d5ae 100644 --- a/Mathlib/Algebra/Order/Pi.lean +++ b/Mathlib/Algebra/Order/Pi.lean @@ -6,7 +6,6 @@ Authors: Simon Hudon, Patrick Massot import Mathlib.Algebra.Order.Monoid.Canonical.Defs import Mathlib.Algebra.Order.Ring.Defs import Mathlib.Algebra.Ring.Pi -import Mathlib.Algebra.Order.Monoid.Canonical.Defs /-! # Pi instances for ordered groups and monoids diff --git a/Mathlib/Algebra/Order/Pointwise.lean b/Mathlib/Algebra/Order/Pointwise.lean index 2bda973451012..43396523eb326 100644 --- a/Mathlib/Algebra/Order/Pointwise.lean +++ b/Mathlib/Algebra/Order/Pointwise.lean @@ -170,7 +170,7 @@ theorem smul_Icc : r • Icc a b = Icc (r • a) (r • b) := by · 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⟩, ?_⟩ + 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 @@ -183,7 +183,7 @@ theorem smul_Ico : r • Ico a b = Ico (r • a) (r • b) := by · 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⟩, ?_⟩ + 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 @@ -196,7 +196,7 @@ theorem smul_Ioc : r • Ioc a b = Ioc (r • a) (r • b) := by · 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⟩, ?_⟩ + 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 @@ -232,7 +232,7 @@ theorem smul_Ici : r • Ici a = Ici (r • a) := by · rintro h use x / r constructor - · exact (le_div_iff' hr).mpr h + · 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 @@ -244,7 +244,7 @@ theorem smul_Iic : r • Iic a = Iic (r • a) := by · rintro h use x / r constructor - · exact (div_le_iff' hr).mpr h + · 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 8178078ac60be..3a053adc33a18 100644 --- a/Mathlib/Algebra/Order/Positive/Field.lean +++ b/Mathlib/Algebra/Order/Positive/Field.lean @@ -5,7 +5,6 @@ Authors: Yury Kudryashov -/ import Mathlib.Algebra.Order.Field.Defs import Mathlib.Algebra.Order.Positive.Ring -import Mathlib.Algebra.Order.Field.Unbundled.Basic /-! # Algebraic structures on the set of positive numbers @@ -19,8 +18,7 @@ variable {K : Type*} [LinearOrderedField K] namespace Positive -instance Subtype.inv : Inv { x : K // 0 < x } := - ⟨fun x => ⟨x⁻¹, inv_pos (α := K)|>.2 x.2⟩⟩ +instance Subtype.inv : Inv { x : K // 0 < x } := ⟨fun x => ⟨x⁻¹, inv_pos.2 x.2⟩⟩ @[simp] theorem coe_inv (x : { x : K // 0 < x }) : ↑x⁻¹ = (x⁻¹ : K) := diff --git a/Mathlib/Algebra/Order/Rearrangement.lean b/Mathlib/Algebra/Order/Rearrangement.lean index 4966d47669fd9..6643fbdac7eec 100644 --- a/Mathlib/Algebra/Order/Rearrangement.lean +++ b/Mathlib/Algebra/Order/Rearrangement.lean @@ -4,8 +4,9 @@ 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.Module.OrderedSMul import Mathlib.Algebra.Order.Group.Instances +import Mathlib.Algebra.Order.Module.OrderedSMul +import Mathlib.Algebra.Order.Module.Synonym import Mathlib.Data.Prod.Lex import Mathlib.Data.Set.Image import Mathlib.GroupTheory.Perm.Support diff --git a/Mathlib/Algebra/Order/Ring/Abs.lean b/Mathlib/Algebra/Order/Ring/Abs.lean index a7a48f42842b7..7d11531e4a537 100644 --- a/Mathlib/Algebra/Order/Ring/Abs.lean +++ b/Mathlib/Algebra/Order/Ring/Abs.lean @@ -196,7 +196,7 @@ lemma pow_eq_one_iff_cases : a ^ n = 1 ↔ n = 0 ∨ a = 1 ∨ a = -1 ∧ Even n lemma pow_eq_neg_pow_iff (hb : b ≠ 0) : a ^ n = -b ^ n ↔ a = -b ∧ Odd n := match n.even_or_odd with | .inl he => - suffices a ^ n > -b ^ n by simpa [he] using this.ne' + suffices a ^ n > -b ^ n by simpa [he, not_odd_iff_even.2 he] using this.ne' lt_of_lt_of_le (by simp [he.pow_pos hb]) (he.pow_nonneg _) | .inr ho => by simp only [ho, and_true, ← ho.neg_pow, (ho.strictMono_pow (R := R)).injective.eq_iff] @@ -226,7 +226,7 @@ lemma Even.mod_even (hn : Even n) (ha : Even a) : Even (n % a) := (Even.mod_even_iff ha).mpr hn lemma Odd.of_dvd_nat (hn : Odd n) (hm : m ∣ n) : Odd m := - odd_iff_not_even.2 <| mt hm.even (odd_iff_not_even.1 hn) + not_even_iff_odd.1 <| mt hm.even (not_even_iff_odd.2 hn) /-- `2` is not a factor of an odd natural number. -/ lemma Odd.ne_two_of_dvd_nat {m n : ℕ} (hn : Odd n) (hm : m ∣ n) : m ≠ 2 := by diff --git a/Mathlib/Algebra/Order/Ring/Basic.lean b/Mathlib/Algebra/Order/Ring/Basic.lean index 84c8ec4672fa0..b6456438e50c3 100644 --- a/Mathlib/Algebra/Order/Ring/Basic.lean +++ b/Mathlib/Algebra/Order/Ring/Basic.lean @@ -43,9 +43,10 @@ theorem zero_pow_le_one : ∀ n : ℕ, (0 : R) ^ n ≤ 1 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 k ih - · simp only [zero_add, pow_one, le_refl] - · let n := k.succ + induction k with + | zero => simp only [zero_add, pow_one, le_refl] + | succ k ih => + let n := k.succ have h1 := add_nonneg (mul_nonneg hx (pow_nonneg hy n)) (mul_nonneg hy (pow_nonneg hx n)) have h2 := add_nonneg hx hy calc diff --git a/Mathlib/Algebra/Order/Ring/Int.lean b/Mathlib/Algebra/Order/Ring/Int.lean index 19de25e7f6877..6cebdbab75355 100644 --- a/Mathlib/Algebra/Order/Ring/Int.lean +++ b/Mathlib/Algebra/Order/Ring/Int.lean @@ -51,7 +51,7 @@ instance instOrderedRing : OrderedRing ℤ := StrictOrderedRing.toOrderedRing' /-! ### Miscellaneous lemmas -/ lemma isCompl_even_odd : IsCompl { n : ℤ | Even n } { n | Odd n } := by - simp [← Set.compl_setOf, isCompl_compl] + simp [← not_even_iff_odd, ← Set.compl_setOf, isCompl_compl] lemma _root_.Nat.cast_natAbs {α : Type*} [AddGroupWithOne α] (n : ℤ) : (n.natAbs : α) = |n| := by rw [← natCast_natAbs, Int.cast_natCast] diff --git a/Mathlib/Algebra/Order/Ring/Nat.lean b/Mathlib/Algebra/Order/Ring/Nat.lean index ed74130a665a2..3b3be2c922c0a 100644 --- a/Mathlib/Algebra/Order/Ring/Nat.lean +++ b/Mathlib/Algebra/Order/Ring/Nat.lean @@ -8,7 +8,6 @@ import Mathlib.Algebra.Order.GroupWithZero.Canonical import Mathlib.Algebra.Order.Ring.Canonical import Mathlib.Algebra.Ring.Nat import Mathlib.Data.Set.Basic -import Mathlib.Init.Data.Nat.Lemmas /-! # The natural numbers form an ordered semiring @@ -41,7 +40,7 @@ instance instCanonicallyOrderedCommSemiring : CanonicallyOrderedCommSemiring ℕ __ := instLinearOrderedCommSemiring exists_add_of_le h := (Nat.le.dest h).imp fun _ => Eq.symm le_self_add := Nat.le_add_right - eq_zero_or_eq_zero_of_mul_eq_zero := Nat.eq_zero_of_mul_eq_zero + eq_zero_or_eq_zero_of_mul_eq_zero := Nat.mul_eq_zero.mp /-! ### Extra instances to short-circuit type class resolution @@ -59,6 +58,6 @@ instance instOrderedCommSemiring : OrderedCommSemiring ℕ := /-! ### Miscellaneous lemmas -/ lemma isCompl_even_odd : IsCompl { n : ℕ | Even n } { n | Odd n } := by - simp only [← Set.compl_setOf, isCompl_compl, odd_iff_not_even] + simp only [← Set.compl_setOf, isCompl_compl, ← not_even_iff_odd] end Nat diff --git a/Mathlib/Algebra/Order/Ring/Star.lean b/Mathlib/Algebra/Order/Ring/Star.lean index da189507528bc..06f3ffa17e0cc 100644 --- a/Mathlib/Algebra/Order/Ring/Star.lean +++ b/Mathlib/Algebra/Order/Ring/Star.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Jireh Loreaux -/ import Mathlib.Algebra.Order.Ring.Defs -import Mathlib.Algebra.Star.Order +import Mathlib.Algebra.Order.Star.Basic /-! # Commutative star-ordered rings are ordered rings @@ -23,7 +23,7 @@ namespace StarOrderedRing /- This example shows that nonnegative elements in a ordered semiring which is also star-ordered must commute. We provide this only as an example as opposed to a lemma because we never expect the -type class assumptions to be satisfied without a `CommSemiring` intance already in scope; not that +type class assumptions to be satisfied without a `CommSemiring` instance already in scope; not that it is impossible, only that it shouldn't occur in practice. -/ example {R : Type*} [OrderedSemiring R] [StarRing R] [StarOrderedRing R] {x y : R} (hx : 0 ≤ x) (hy : 0 ≤ y) : x * y = y * x := by diff --git a/Mathlib/Algebra/Order/Ring/Unbundled/Basic.lean b/Mathlib/Algebra/Order/Ring/Unbundled/Basic.lean index 91e49342408c0..68c19b0c396c3 100644 --- a/Mathlib/Algebra/Order/Ring/Unbundled/Basic.lean +++ b/Mathlib/Algebra/Order/Ring/Unbundled/Basic.lean @@ -136,31 +136,6 @@ section OrderedSemiring variable [Semiring α] [Preorder α] {a b c d : α} -@[simp] -theorem pow_nonneg [ZeroLEOneClass α] [PosMulMono α] - (H : 0 ≤ a) : ∀ n : ℕ, 0 ≤ a ^ n - | 0 => by - rw [pow_zero] - exact zero_le_one - | n + 1 => by - rw [pow_succ] - exact mul_nonneg (pow_nonneg H _) H - -lemma pow_le_pow_of_le_one [ZeroLEOneClass α] [PosMulMono α] [MulPosMono α] - (ha₀ : 0 ≤ a) (ha₁ : a ≤ 1) : ∀ {m n : ℕ}, m ≤ n → a ^ n ≤ a ^ m - | _, _, Nat.le.refl => le_rfl - | _, _, Nat.le.step h => by - rw [pow_succ'] - exact (mul_le_of_le_one_left (pow_nonneg ha₀ _) ha₁).trans <| pow_le_pow_of_le_one ha₀ ha₁ h - -lemma pow_le_of_le_one [ZeroLEOneClass α] [PosMulMono α] [MulPosMono α] - (h₀ : 0 ≤ a) (h₁ : a ≤ 1) {n : ℕ} (hn : n ≠ 0) : a ^ n ≤ a := - (pow_one a).subst (pow_le_pow_of_le_one h₀ h₁ (Nat.pos_of_ne_zero hn)) - -lemma sq_le [ZeroLEOneClass α] [PosMulMono α] [MulPosMono α] - (h₀ : 0 ≤ a) (h₁ : a ≤ 1) : a ^ 2 ≤ a := - pow_le_of_le_one h₀ h₁ two_ne_zero - -- Porting note: it's unfortunate we need to write `(@one_le_two α)` here. theorem add_le_mul_two_add [ZeroLEOneClass α] [MulPosMono α] [CovariantClass α α (· + ·) (· ≤ ·)] (a2 : 2 ≤ a) (b0 : 0 ≤ b) : a + (2 + b) ≤ a * (2 + b) := @@ -169,68 +144,6 @@ theorem add_le_mul_two_add [ZeroLEOneClass α] [MulPosMono α] [CovariantClass add_le_add_left (add_le_add a2 <| le_mul_of_one_le_left b0 <| (@one_le_two α).trans a2) a _ ≤ a * (2 + b) := by rw [mul_add, mul_two, add_assoc] -theorem one_le_mul_of_one_le_of_one_le [ZeroLEOneClass α] [PosMulMono α] - (ha : 1 ≤ a) (hb : 1 ≤ b) : (1 : α) ≤ a * b := - Left.one_le_mul_of_le_of_le ha hb <| zero_le_one.trans ha - -section Monotone - -variable [Preorder β] {f g : β → α} - -theorem monotone_mul_left_of_nonneg [PosMulMono α] - (ha : 0 ≤ a) : Monotone fun x => a * x := fun _ _ h => - mul_le_mul_of_nonneg_left h ha - -theorem monotone_mul_right_of_nonneg [MulPosMono α] - (ha : 0 ≤ a) : Monotone fun x => x * a := fun _ _ h => - mul_le_mul_of_nonneg_right h ha - -theorem Monotone.mul_const [MulPosMono α] - (hf : Monotone f) (ha : 0 ≤ a) : Monotone fun x => f x * a := - (monotone_mul_right_of_nonneg ha).comp hf - -theorem Monotone.const_mul [PosMulMono α] - (hf : Monotone f) (ha : 0 ≤ a) : Monotone fun x => a * f x := - (monotone_mul_left_of_nonneg ha).comp hf - -theorem Antitone.mul_const [MulPosMono α] - (hf : Antitone f) (ha : 0 ≤ a) : Antitone fun x => f x * a := - (monotone_mul_right_of_nonneg ha).comp_antitone hf - -theorem Antitone.const_mul [PosMulMono α] - (hf : Antitone f) (ha : 0 ≤ a) : Antitone fun x => a * f x := - (monotone_mul_left_of_nonneg ha).comp_antitone hf - -theorem Monotone.mul [PosMulMono α] [MulPosMono α] - (hf : Monotone f) (hg : Monotone g) (hf₀ : ∀ x, 0 ≤ f x) (hg₀ : ∀ x, 0 ≤ g x) : - Monotone (f * g) := - fun _ _ h => mul_le_mul (hf h) (hg h) (hg₀ _) (hf₀ _) - -end Monotone - -theorem mul_le_one [ZeroLEOneClass α] [PosMulMono α] [MulPosMono α] - (ha : a ≤ 1) (hb' : 0 ≤ b) (hb : b ≤ 1) : a * b ≤ 1 := - one_mul (1 : α) ▸ mul_le_mul ha hb hb' zero_le_one - -theorem one_lt_mul_of_le_of_lt [ZeroLEOneClass α] [MulPosMono α] - (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 - -theorem one_lt_mul_of_lt_of_le [ZeroLEOneClass α] [PosMulMono α] - (ha : 1 < a) (hb : 1 ≤ b) : 1 < a * b := - ha.trans_le <| le_mul_of_one_le_right (zero_le_one.trans ha.le) hb - -alias one_lt_mul := one_lt_mul_of_le_of_lt - -theorem mul_lt_one_of_nonneg_of_lt_one_left [PosMulMono α] - (ha₀ : 0 ≤ a) (ha : a < 1) (hb : b ≤ 1) : a * b < 1 := - (mul_le_of_le_one_right ha₀ hb).trans_lt ha - -theorem mul_lt_one_of_nonneg_of_lt_one_right [MulPosMono α] - (ha : a ≤ 1) (hb₀ : 0 ≤ b) (hb : b < 1) : a * b < 1 := - (mul_le_of_le_one_left hb₀ ha).trans_lt hb - - theorem mul_le_mul_of_nonpos_left [ExistsAddOfLE α] [PosMulMono α] [CovariantClass α α (swap (· + ·)) (· ≤ ·)] [ContravariantClass α α (swap (· + ·)) (· ≤ ·)] (h : b ≤ a) (hc : c ≤ 0) : c * a ≤ c * b := by @@ -286,7 +199,7 @@ theorem mul_le_mul_of_nonpos_of_nonpos' [ExistsAddOfLE α] [PosMulMono α] [MulP (hca : c ≤ a) (hdb : d ≤ b) (ha : a ≤ 0) (hd : d ≤ 0) : a * b ≤ c * d := (mul_le_mul_of_nonpos_left hdb ha).trans <| mul_le_mul_of_nonpos_right hca hd -/-- Variant of `mul_le_of_le_one_left` for `b` non-positive instead of non-negative. -/ +/-- Variant of `mul_le_of_le_one_left` for `b` non-positive instead of non-negative. -/ theorem le_mul_of_le_one_left [ExistsAddOfLE α] [MulPosMono α] [CovariantClass α α (swap (· + ·)) (· ≤ ·)] [ContravariantClass α α (swap (· + ·)) (· ≤ ·)] (hb : b ≤ 0) (h : a ≤ 1) : b ≤ a * b := by @@ -362,16 +275,6 @@ theorem Antitone.mul [ExistsAddOfLE α] [PosMulMono α] [MulPosMono α] Monotone (f * g) := fun _ _ h => mul_le_mul_of_nonpos_of_nonpos (hf h) (hg h) (hf₀ _) (hg₀ _) end Monotone - -lemma le_iff_exists_nonneg_add - [ExistsAddOfLE α] [ContravariantClass α α (· + ·) (· ≤ ·)] [CovariantClass α α (· + ·) (· ≤ ·)] - (a b : α) : a ≤ b ↔ ∃ c ≥ 0, b = a + c := by - refine ⟨fun h ↦ ?_, ?_⟩ - · obtain ⟨c, rfl⟩ := exists_add_of_le h - exact ⟨c, nonneg_of_le_add_right h, rfl⟩ - · rintro ⟨c, hc, rfl⟩ - exact le_add_of_nonneg_right hc - end OrderedSemiring section OrderedCommRing @@ -380,95 +283,6 @@ section StrictOrderedSemiring variable [Semiring α] [PartialOrder α] {a b c d : α} -@[simp] -theorem pow_pos [ZeroLEOneClass α] [PosMulStrictMono α] - (H : 0 < a) : ∀ n : ℕ, 0 < a ^ n - | 0 => by - nontriviality - rw [pow_zero] - exact zero_lt_one - | n + 1 => by - rw [pow_succ] - exact mul_pos (pow_pos H _) H - -theorem mul_self_lt_mul_self [PosMulStrictMono α] [MulPosMono α] - (h1 : 0 ≤ a) (h2 : a < b) : a * a < b * b := - mul_lt_mul' h2.le h2 h1 <| h1.trans_lt h2 - --- In the next lemma, we used to write `Set.Ici 0` instead of `{x | 0 ≤ x}`. --- As this lemma is not used outside this file, --- and the import for `Set.Ici` is not otherwise needed until later, --- we choose not to use it here. -theorem strictMonoOn_mul_self [PosMulStrictMono α] [MulPosMono α] : - StrictMonoOn (fun x : α => x * x) { x | 0 ≤ x } := - fun _ hx _ _ hxy => mul_self_lt_mul_self hx hxy - --- See Note [decidable namespace] -protected theorem Decidable.mul_lt_mul'' [PosMulMono α] [PosMulStrictMono α] [MulPosStrictMono α] - [@DecidableRel α (· ≤ ·)] (h1 : a < c) (h2 : b < d) - (h3 : 0 ≤ a) (h4 : 0 ≤ b) : a * b < c * d := - h4.lt_or_eq_dec.elim (fun b0 => mul_lt_mul h1 h2.le b0 <| h3.trans h1.le) fun b0 => by - rw [← b0, mul_zero]; exact mul_pos (h3.trans_lt h1) (h4.trans_lt h2) - -theorem lt_mul_left [MulPosStrictMono α] - (hn : 0 < a) (hm : 1 < b) : a < b * a := by - convert mul_lt_mul_of_pos_right hm hn - rw [one_mul] - -theorem lt_mul_right [PosMulStrictMono α] - (hn : 0 < a) (hm : 1 < b) : a < a * b := by - convert mul_lt_mul_of_pos_left hm hn - rw [mul_one] - -theorem lt_mul_self [ZeroLEOneClass α] [MulPosStrictMono α] - (hn : 1 < a) : a < a * a := - lt_mul_left (hn.trans_le' zero_le_one) hn - -section Monotone - -variable [Preorder β] {f g : β → α} - -theorem strictMono_mul_left_of_pos [PosMulStrictMono α] - (ha : 0 < a) : StrictMono fun x => a * x := fun _ _ b_lt_c => - mul_lt_mul_of_pos_left b_lt_c ha - -theorem strictMono_mul_right_of_pos [MulPosStrictMono α] - (ha : 0 < a) : StrictMono fun x => x * a := fun _ _ b_lt_c => - mul_lt_mul_of_pos_right b_lt_c ha - -theorem StrictMono.mul_const [MulPosStrictMono α] - (hf : StrictMono f) (ha : 0 < a) : StrictMono fun x => f x * a := - (strictMono_mul_right_of_pos ha).comp hf - -theorem StrictMono.const_mul [PosMulStrictMono α] - (hf : StrictMono f) (ha : 0 < a) : StrictMono fun x => a * f x := - (strictMono_mul_left_of_pos ha).comp hf - -theorem StrictAnti.mul_const [MulPosStrictMono α] - (hf : StrictAnti f) (ha : 0 < a) : StrictAnti fun x => f x * a := - (strictMono_mul_right_of_pos ha).comp_strictAnti hf - -theorem StrictAnti.const_mul [PosMulStrictMono α] - (hf : StrictAnti f) (ha : 0 < a) : StrictAnti fun x => a * f x := - (strictMono_mul_left_of_pos ha).comp_strictAnti hf - -theorem StrictMono.mul_monotone [PosMulMono α] [MulPosStrictMono α] - (hf : StrictMono f) (hg : Monotone g) (hf₀ : ∀ x, 0 ≤ f x) - (hg₀ : ∀ x, 0 < g x) : StrictMono (f * g) := fun _ _ h => - mul_lt_mul (hf h) (hg h.le) (hg₀ _) (hf₀ _) - -theorem Monotone.mul_strictMono [PosMulStrictMono α] [MulPosMono α] - (hf : Monotone f) (hg : StrictMono g) (hf₀ : ∀ x, 0 < f x) - (hg₀ : ∀ x, 0 ≤ g x) : StrictMono (f * g) := fun _ _ h => - mul_lt_mul' (hf h.le) (hg h) (hg₀ _) (hf₀ _) - -theorem StrictMono.mul [PosMulStrictMono α] [MulPosStrictMono α] - (hf : StrictMono f) (hg : StrictMono g) (hf₀ : ∀ x, 0 ≤ f x) - (hg₀ : ∀ x, 0 ≤ g x) : StrictMono (f * g) := fun _ _ h => - mul_lt_mul'' (hf h) (hg h) (hf₀ _) (hg₀ _) - -end Monotone - theorem lt_two_mul_self [ZeroLEOneClass α] [MulPosStrictMono α] [NeZero (R := α) 1] [CovariantClass α α (· + ·) (· < ·)] (ha : 0 < a) : a < 2 * a := lt_mul_of_one_lt_left ha one_lt_two @@ -563,9 +377,9 @@ lemma mul_add_mul_le_mul_add_mul [ExistsAddOfLE α] [MulPosMono α] [CovariantClass α α (· + ·) (· ≤ ·)] [ContravariantClass α α (· + ·) (· ≤ ·)] (hab : a ≤ b) (hcd : c ≤ d) : a * d + b * c ≤ a * c + b * d := by obtain ⟨b, rfl⟩ := exists_add_of_le hab - obtain ⟨d, rfl⟩ := exists_add_of_le hcd + obtain ⟨d, hd, rfl⟩ := exists_nonneg_add_of_le hcd rw [mul_add, add_right_comm, mul_add, ← add_assoc] - exact add_le_add_left (mul_le_mul_of_nonneg_right hab <| (le_add_iff_nonneg_right _).1 hcd) _ + exact add_le_add_left (mul_le_mul_of_nonneg_right hab hd) _ /-- Binary **rearrangement inequality**. -/ lemma mul_add_mul_le_mul_add_mul' [ExistsAddOfLE α] [MulPosMono α] @@ -580,9 +394,9 @@ lemma mul_add_mul_lt_mul_add_mul [ExistsAddOfLE α] [MulPosStrictMono α] [CovariantClass α α (· + ·) (· < ·)] (hab : a < b) (hcd : c < d) : a * d + b * c < a * c + b * d := by obtain ⟨b, rfl⟩ := exists_add_of_le hab.le - obtain ⟨d, rfl⟩ := exists_add_of_le hcd.le + obtain ⟨d, hd, rfl⟩ := exists_pos_add_of_lt' hcd rw [mul_add, add_right_comm, mul_add, ← add_assoc] - exact add_lt_add_left (mul_lt_mul_of_pos_right hab <| (lt_add_iff_pos_right _).1 hcd) _ + exact add_lt_add_left (mul_lt_mul_of_pos_right hab hd) _ /-- Binary **rearrangement inequality**. -/ lemma mul_add_mul_lt_mul_add_mul' [ExistsAddOfLE α] [MulPosStrictMono α] @@ -856,7 +670,7 @@ theorem mul_self_pos [ExistsAddOfLE α] [PosMulStrictMono α] [MulPosStrictMono rw [mul_zero] at h exact h.false · intro h - cases' h.lt_or_lt with h h + rcases h.lt_or_lt with h | h exacts [mul_pos_of_neg_of_neg h h, mul_pos h h] theorem nonneg_of_mul_nonpos_left [ExistsAddOfLE α] [MulPosStrictMono α] diff --git a/Mathlib/Algebra/Order/Ring/Unbundled/Rat.lean b/Mathlib/Algebra/Order/Ring/Unbundled/Rat.lean index 8b5c91a55c468..b2ad2a602b376 100644 --- a/Mathlib/Algebra/Order/Ring/Unbundled/Rat.lean +++ b/Mathlib/Algebra/Order/Ring/Unbundled/Rat.lean @@ -6,15 +6,15 @@ Authors: Johannes Hölzl, Mario Carneiro import Mathlib.Algebra.Order.Group.Unbundled.Abs import Mathlib.Algebra.Order.Group.Unbundled.Basic import Mathlib.Algebra.Ring.Rat -import Mathlib.Init.Data.Int.Order +import Mathlib.Data.Int.Order.Basic /-! # The rational numbers possess a linear order This file constructs the order on `ℚ` and proves various facts relating the order to -ring structure on `ℚ`. This only used unbundled type classes relating the order structure -and algebra structure on `ℚ`. For the bundled `LinearOrderedCommRing` instance on `Q`, -see `Algebra.Order.Ring.Rat`. +ring structure on `ℚ`. This only uses unbundled type classes, eg `CovariantClass`, +relating the order structure and algebra structure on `ℚ`. +For the bundled `LinearOrderedCommRing` instance on `ℚ`, see `Algebra.Order.Ring.Rat`. ## Tags @@ -95,7 +95,7 @@ protected theorem le_iff_sub_nonneg (a b : ℚ) : a ≤ b ↔ 0 ≤ b - a := decide_eq_false_iff_not, not_lt, ite_eq_left_iff, not_and, not_le, ← num_nonneg] split_ifs with h h' · rw [Rat.sub_def] - simp only [false_iff, not_le] + simp only [false_iff, not_le, reduceCtorEq] simp only [normalize_eq] apply Int.ediv_neg' · rw [sub_neg] diff --git a/Mathlib/Algebra/Order/Ring/WithTop.lean b/Mathlib/Algebra/Order/Ring/WithTop.lean index 8cea38308e3b5..3ee35faa46055 100644 --- a/Mathlib/Algebra/Order/Ring/WithTop.lean +++ b/Mathlib/Algebra/Order/Ring/WithTop.lean @@ -73,12 +73,14 @@ lemma coe_mul_eq_bind {a : α} (ha : a ≠ 0) : ∀ b, (a * b : WithTop α) = b. induction b; · rw [mul_top ha, untop'_top, mul_zero] rw [← coe_mul, untop'_coe, untop'_coe, untop'_coe] -theorem mul_lt_top' [LT α] {a b : WithTop α} (ha : a < ⊤) (hb : b < ⊤) : a * b < ⊤ := by +theorem mul_ne_top {a b : WithTop α} (ha : a ≠ ⊤) (hb : b ≠ ⊤) : a * b ≠ ⊤ := by + simp [mul_eq_top_iff, *] + +theorem mul_lt_top [LT α] {a b : WithTop α} (ha : a < ⊤) (hb : b < ⊤) : a * b < ⊤ := by rw [WithTop.lt_top_iff_ne_top] at * - simp only [Ne, mul_eq_top_iff, *, and_false, false_and, or_self, not_false_eq_true] + exact mul_ne_top ha hb -theorem mul_lt_top [LT α] {a b : WithTop α} (ha : a ≠ ⊤) (hb : b ≠ ⊤) : a * b < ⊤ := - mul_lt_top' (WithTop.lt_top_iff_ne_top.2 ha) (WithTop.lt_top_iff_ne_top.2 hb) +@[deprecated (since := "2024-08-25")] alias mul_lt_top' := mul_lt_top instance instNoZeroDivisors [NoZeroDivisors α] : NoZeroDivisors (WithTop α) := by refine ⟨fun h₁ => Decidable.by_contradiction fun h₂ => ?_⟩ @@ -242,12 +244,14 @@ lemma unbot'_zero_mul (a b : WithBot α) : (a * b).unbot' 0 = a.unbot' 0 * b.unb induction b; · rw [mul_bot ha, unbot'_bot, mul_zero] rw [← coe_mul, unbot'_coe, unbot'_coe, unbot'_coe] -theorem bot_lt_mul' [LT α] {a b : WithBot α} (ha : ⊥ < a) (hb : ⊥ < b) : ⊥ < a * b := - WithTop.mul_lt_top' (α := αᵒᵈ) ha hb +theorem mul_ne_bot {a b : WithBot α} (ha : a ≠ ⊥) (hb : b ≠ ⊥) : a * b ≠ ⊥ := + WithTop.mul_ne_top (α := αᵒᵈ) ha hb -theorem bot_lt_mul [LT α] {a b : WithBot α} (ha : a ≠ ⊥) (hb : b ≠ ⊥) : ⊥ < a * b := +theorem bot_lt_mul [LT α] {a b : WithBot α} (ha : ⊥ < a) (hb : ⊥ < b) : ⊥ < a * b := WithTop.mul_lt_top (α := αᵒᵈ) ha hb +@[deprecated (since := "2024-08-25")] alias bot_lt_mul' := bot_lt_mul + instance instNoZeroDivisors [NoZeroDivisors α] : NoZeroDivisors (WithBot α) := WithTop.instNoZeroDivisors diff --git a/Mathlib/Algebra/Star/Order.lean b/Mathlib/Algebra/Order/Star/Basic.lean similarity index 94% rename from Mathlib/Algebra/Star/Order.lean rename to Mathlib/Algebra/Order/Star/Basic.lean index 3d1200121de45..055ffe59379d4 100644 --- a/Mathlib/Algebra/Star/Order.lean +++ b/Mathlib/Algebra/Order/Star/Basic.lean @@ -7,6 +7,7 @@ import Mathlib.Algebra.Group.Submonoid.Operations import Mathlib.Algebra.Star.SelfAdjoint import Mathlib.Algebra.Star.StarRingHom import Mathlib.Algebra.Regular.Basic +import Mathlib.Tactic.ContinuousFunctionalCalculus /-! # Star ordered rings @@ -137,12 +138,26 @@ section NonUnitalSemiring variable [NonUnitalSemiring R] [PartialOrder R] [StarRing R] [StarOrderedRing R] +lemma IsSelfAdjoint.mono {x y : R} (h : x ≤ y) (hx : IsSelfAdjoint x) : IsSelfAdjoint y := by + rw [StarOrderedRing.le_iff] at h + obtain ⟨d, hd, rfl⟩ := h + rw [IsSelfAdjoint, star_add, hx.star_eq] + congr + refine AddMonoidHom.eqOn_closureM (f := starAddEquiv (R := R)) (g := .id R) ?_ hd + rintro - ⟨s, rfl⟩ + simp + +@[aesop 10% apply] +lemma IsSelfAdjoint.of_nonneg {x : R} (hx : 0 ≤ x) : IsSelfAdjoint x := + .mono hx <| .zero R + theorem star_mul_self_nonneg (r : R) : 0 ≤ star r * r := StarOrderedRing.nonneg_iff.mpr <| AddSubmonoid.subset_closure ⟨r, rfl⟩ theorem mul_star_self_nonneg (r : R) : 0 ≤ r * star r := by simpa only [star_star] using star_mul_self_nonneg (star r) +@[aesop safe apply] theorem conjugate_nonneg {a : R} (ha : 0 ≤ a) (c : R) : 0 ≤ star c * a * c := by rw [StarOrderedRing.nonneg_iff] at ha refine AddSubmonoid.closure_induction ha (fun x hx => ?_) @@ -155,9 +170,19 @@ theorem conjugate_nonneg {a : R} (ha : 0 ≤ a) (c : R) : 0 ≤ star c * a * c : _ ≤ star c * x * c + star c * y * c := add_le_add_left hy _ _ ≤ _ := by rw [mul_add, add_mul] +@[aesop safe apply] theorem conjugate_nonneg' {a : R} (ha : 0 ≤ a) (c : R) : 0 ≤ c * a * star c := by simpa only [star_star] using conjugate_nonneg ha (star c) +@[aesop 90% apply (rule_sets := [CStarAlgebra])] +protected theorem IsSelfAdjoint.conjugate_nonneg {a : R} (ha : 0 ≤ a) {c : R} + (hc : IsSelfAdjoint c) : 0 ≤ c * a * c := by + nth_rewrite 2 [← hc]; exact conjugate_nonneg' ha c + +theorem conjugate_nonneg_of_nonneg {a : R} (ha : 0 ≤ a) {c : R} (hc : 0 ≤ c) : + 0 ≤ c * a * c := + IsSelfAdjoint.of_nonneg hc |>.conjugate_nonneg ha + theorem conjugate_le_conjugate {a b : R} (hab : a ≤ b) (c : R) : star c * a * c ≤ star c * b * c := by rw [StarOrderedRing.le_iff] at hab ⊢ @@ -169,6 +194,14 @@ theorem conjugate_le_conjugate' {a b : R} (hab : a ≤ b) (c : R) : c * a * star c ≤ c * b * star c := by simpa only [star_star] using conjugate_le_conjugate hab (star c) +protected theorem IsSelfAdjoint.conjugate_le_conjugate {a b : R} (hab : a ≤ b) {c : R} + (hc : IsSelfAdjoint c) : c * a * c ≤ c * b * c := by + simpa only [hc.star_eq] using conjugate_le_conjugate hab c + +theorem conjugate_le_conjugate_of_nonneg {a b : R} (hab : a ≤ b) {c : R} (hc : 0 ≤ c) : + c * a * c ≤ c * b * c := + IsSelfAdjoint.of_nonneg hc |>.conjugate_le_conjugate hab + @[simp] lemma star_le_star_iff {x y : R} : star x ≤ star y ↔ x ≤ y := by suffices ∀ x y, x ≤ y → star x ≤ star y from @@ -207,19 +240,6 @@ lemma star_pos_iff {x : R} : 0 < star x ↔ 0 < x := by lemma star_neg_iff {x : R} : star x < 0 ↔ x < 0 := by simpa using star_lt_star_iff (x := x) (y := 0) -lemma IsSelfAdjoint.mono {x y : R} (h : x ≤ y) (hx : IsSelfAdjoint x) : IsSelfAdjoint y := by - rw [StarOrderedRing.le_iff] at h - obtain ⟨d, hd, rfl⟩ := h - rw [IsSelfAdjoint, star_add, hx.star_eq] - congr - refine AddMonoidHom.eqOn_closureM (f := starAddEquiv (R := R)) (g := .id R) ?_ hd - rintro - ⟨s, rfl⟩ - simp - -@[aesop 10% apply] -lemma IsSelfAdjoint.of_nonneg {x : R} (hx : 0 ≤ x) : IsSelfAdjoint x := - .mono hx <| .zero R - theorem conjugate_lt_conjugate {a b : R} (hab : a < b) {c : R} (hc : IsRegular c) : star c * a * c < star c * b * c := by rw [(conjugate_le_conjugate hab.le _).lt_iff_ne, hc.right.ne_iff, hc.star.left.ne_iff] @@ -294,7 +314,7 @@ lemma StarModule.smul_lt_smul_of_pos {a b : A} {c : R} (hab : a < b) (hc : 0 < c obtain ⟨y, hy⟩ := hx apply AddSubmonoid.subset_closure refine ⟨z • y, ?_⟩ - simp only [star_smul, smul_mul_smul, hz, hy] + simp only [star_smul, smul_mul_smul_comm, hz, hy] case zeroc => simpa only [zero_smul] using zero_mem _ case addc => exact fun c' d ↦ by simpa only [add_smul] using add_mem case zero => simpa only [smul_zero] using zero_mem _ diff --git a/Mathlib/Algebra/Order/Star/Conjneg.lean b/Mathlib/Algebra/Order/Star/Conjneg.lean new file mode 100644 index 0000000000000..091da606b1727 --- /dev/null +++ b/Mathlib/Algebra/Order/Star/Conjneg.lean @@ -0,0 +1,38 @@ +/- +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.Pi +import Mathlib.Algebra.Order.Star.Basic +import Mathlib.Algebra.Star.Conjneg + +/-! +# Order properties of conjugation-negation +-/ + +open scoped ComplexConjugate + +variable {ι G R : Type*} [AddGroup G] + +section OrderedCommSemiring +variable [OrderedCommSemiring R] [StarRing R] [StarOrderedRing R] {f : G → R} + +@[simp] lemma conjneg_nonneg : 0 ≤ conjneg f ↔ 0 ≤ f := + (Equiv.neg _).forall_congr' <| by simp [starRingEnd_apply] + +@[simp] lemma conjneg_pos : 0 < conjneg f ↔ 0 < f := by + simp_rw [lt_iff_le_and_ne, ne_comm, conjneg_nonneg, conjneg_ne_zero] + +end OrderedCommSemiring + +section OrderedCommRing +variable [OrderedCommRing R] [StarRing R] [StarOrderedRing R] {f : G → R} + +@[simp] lemma conjneg_nonpos : conjneg f ≤ 0 ↔ f ≤ 0 := by + simp_rw [← neg_nonneg, ← conjneg_neg, conjneg_nonneg] + +@[simp] lemma conjneg_neg' : conjneg f < 0 ↔ f < 0 := by + simp_rw [← neg_pos, ← conjneg_neg, conjneg_pos] + +end OrderedCommRing diff --git a/Mathlib/Algebra/Periodic.lean b/Mathlib/Algebra/Periodic.lean index d3f5025d9b640..995e7e734029d 100644 --- a/Mathlib/Algebra/Periodic.lean +++ b/Mathlib/Algebra/Periodic.lean @@ -66,9 +66,10 @@ protected theorem Periodic.div [Add α] [Div β] (hf : Periodic f c) (hg : Perio @[to_additive] theorem _root_.List.periodic_prod [Add α] [Monoid β] (l : List (α → β)) (hl : ∀ f ∈ l, Periodic f c) : Periodic l.prod c := by - induction' l with g l ih hl - · simp - · rw [List.forall_mem_cons] at hl + induction l with + | nil => simp + | cons g l ih => + rw [List.forall_mem_cons] at hl simpa only [List.prod_cons] using hl.1.mul (ih hl.2) @[to_additive] @@ -182,7 +183,7 @@ theorem Periodic.nat_mul_sub_eq [Ring α] (h : Periodic f c) (n : ℕ) : f (n * simpa only [sub_eq_neg_add] using h.nat_mul n (-x) protected theorem Periodic.zsmul [AddGroup α] (h : Periodic f c) (n : ℤ) : Periodic f (n • c) := by - cases' n with n n + rcases n with n | n · simpa only [Int.ofNat_eq_coe, natCast_zsmul] using h.nsmul n · simpa only [negSucc_zsmul] using (h.nsmul (n + 1)).neg diff --git a/Mathlib/Algebra/Polynomial/AlgebraMap.lean b/Mathlib/Algebra/Polynomial/AlgebraMap.lean index 488fbdbe25fad..9f4745493a802 100644 --- a/Mathlib/Algebra/Polynomial/AlgebraMap.lean +++ b/Mathlib/Algebra/Polynomial/AlgebraMap.lean @@ -384,7 +384,7 @@ instance instCommSemiringAdjoinSingleton : { mul_comm := fun ⟨p, hp⟩ ⟨q, hq⟩ ↦ by obtain ⟨p', rfl⟩ := Algebra.adjoin_singleton_eq_range_aeval R x ▸ hp obtain ⟨q', rfl⟩ := Algebra.adjoin_singleton_eq_range_aeval R x ▸ hq - simp only [AlgHom.toRingHom_eq_coe, RingHom.coe_coe, Submonoid.mk_mul_mk, ← map_mul, + simp only [AlgHom.toRingHom_eq_coe, RingHom.coe_coe, MulMemClass.mk_mul_mk, ← map_mul, mul_comm p' q'] } instance instCommRingAdjoinSingleton {R A : Type*} [CommRing R] [Ring A] [Algebra R A] (x : A) : diff --git a/Mathlib/Algebra/Polynomial/Basic.lean b/Mathlib/Algebra/Polynomial/Basic.lean index fdb174e68d4da..dc5582e2148d6 100644 --- a/Mathlib/Algebra/Polynomial/Basic.lean +++ b/Mathlib/Algebra/Polynomial/Basic.lean @@ -49,8 +49,6 @@ equivalence is also registered as a ring equiv in `Polynomial.toFinsuppIso`. The in general not be used once the basic API for polynomials is constructed. -/ - - noncomputable section /-- `Polynomial R` is the type of univariate polynomials over `R`. @@ -66,8 +64,6 @@ open AddMonoidAlgebra open Finsupp hiding single open Function hiding Commute -open Polynomial - namespace Polynomial universe u @@ -402,9 +398,9 @@ theorem monomial_mul_monomial (n m : ℕ) (r s : R) : @[simp] theorem monomial_pow (n : ℕ) (r : R) (k : ℕ) : monomial n r ^ k = monomial (n * k) (r ^ k) := by - induction' k with k ih - · simp [pow_zero, monomial_zero_one] - · simp [pow_succ, ih, monomial_mul_monomial, mul_add, add_comm] + induction k with + | zero => simp [pow_zero, monomial_zero_one] + | succ k ih => simp [pow_succ, ih, monomial_mul_monomial, mul_add, add_comm] theorem smul_monomial {S} [SMulZeroClass S R] (a : S) (n : ℕ) (b : R) : a • monomial n b = monomial n (a • b) := @@ -539,9 +535,9 @@ theorem monomial_mul_X (n : ℕ) (r : R) : monomial n r * X = monomial (n + 1) r @[simp] theorem monomial_mul_X_pow (n : ℕ) (r : R) (k : ℕ) : monomial n r * X ^ k = monomial (n + k) r := by - induction' k with k ih - · simp - · simp [ih, pow_succ, ← mul_assoc, add_assoc] + induction k with + | zero => simp + | succ k ih => simp [ih, pow_succ, ← mul_assoc, add_assoc] @[simp] theorem X_mul_monomial (n : ℕ) (r : R) : X * monomial n r = monomial (n + 1) r := by @@ -934,7 +930,7 @@ section Update /-- Replace the coefficient of a `p : R[X]` at a given degree `n : ℕ` by a given value `a : R`. If `a = 0`, this is equal to `p.erase n` -If `p.natDegree < n` and `a ≠ 0`, this increases the degree to `n`. -/ +If `p.natDegree < n` and `a ≠ 0`, this increases the degree to `n`. -/ def update (p : R[X]) (n : ℕ) (a : R) : R[X] := Polynomial.ofFinsupp (p.toFinsupp.update n a) diff --git a/Mathlib/Algebra/Polynomial/Bivariate.lean b/Mathlib/Algebra/Polynomial/Bivariate.lean index 24034be6c2820..a78e8ffa4e2c8 100644 --- a/Mathlib/Algebra/Polynomial/Bivariate.lean +++ b/Mathlib/Algebra/Polynomial/Bivariate.lean @@ -41,15 +41,96 @@ abbrev CC (r : R) : R[X][Y] := C (C r) lemma evalEval_C (x y : R) (p : R[X]) : (C p).evalEval x y = p.eval x := by rw [evalEval, eval_C] +@[simp] +lemma evalEval_CC (x y : R) (p : R) : (CC p).evalEval x y = p := by + rw [evalEval_C, eval_C] + +@[simp] +lemma evalEval_zero (x y : R) : (0 : R[X][Y]).evalEval x y = 0 := by + simp only [evalEval, eval_zero] + +@[simp] +lemma evalEval_one (x y : R) : (1 : R[X][Y]).evalEval x y = 1 := by + simp only [evalEval, eval_one] + +@[simp] +lemma evalEval_natCast (x y : R) (n : ℕ) : (n : R[X][Y]).evalEval x y = n := by + simp only [evalEval, eval_natCast] + +@[simp] lemma evalEval_X (x y : R) : X.evalEval x y = y := by rw [evalEval, eval_X, eval_C] +@[simp] +lemma evalEval_add (x y : R) (p q : R[X][Y]) : + (p + q).evalEval x y = p.evalEval x y + q.evalEval x y := by + simp only [evalEval, eval_add] + +lemma evalEval_sum (x y : R) (p : R[X]) (f : ℕ → R → R[X][Y]) : + (p.sum f).evalEval x y = p.sum fun n a => (f n a).evalEval x y := by + simp only [evalEval, eval, eval₂_sum] + +lemma evalEval_finset_sum {ι : Type*} (s : Finset ι) (x y : R) (f : ι → R[X][Y]) : + (∑ i ∈ s, f i).evalEval x y = ∑ i ∈ s, (f i).evalEval x y := by + simp only [evalEval, eval_finset_sum] + +@[simp] +lemma evalEval_smul [Monoid S] [DistribMulAction S R] [IsScalarTower S R R] (x y : R) (s : S) + (p : R[X][Y]) : (s • p).evalEval x y = s • p.evalEval x y := by + simp only [evalEval, eval_smul] + +lemma evalEval_surjective (x y : R) : Function.Surjective <| evalEval x y := + fun y => ⟨CC y, evalEval_CC ..⟩ + end Semiring +section Ring + +variable [Ring R] + +@[simp] +lemma evalEval_neg (x y : R) (p : R[X][Y]) : (-p).evalEval x y = -p.evalEval x y := by + simp only [evalEval, eval_neg] + +@[simp] +lemma evalEval_sub (x y : R) (p q : R[X][Y]) : + (p - q).evalEval x y = p.evalEval x y - q.evalEval x y := by + simp only [evalEval, eval_sub] + +@[simp] +lemma evalEval_intCast (x y : R) (n : ℤ) : (n : R[X][Y]).evalEval x y = n := by + simp only [evalEval, eval_intCast] + +end Ring + section CommSemiring variable [CommSemiring R] +@[simp] +lemma evalEval_mul (x y : R) (p q : R[X][Y]) : + (p * q).evalEval x y = p.evalEval x y * q.evalEval x y := by + simp only [evalEval, eval_mul] + +lemma evalEval_prod {ι : Type*} (s : Finset ι) (x y : R) (p : ι → R[X][Y]) : + (∏ j ∈ s, p j).evalEval x y = ∏ j ∈ s, (p j).evalEval x y := by + simp only [evalEval, eval_prod] + +lemma evalEval_list_prod (x y : R) (l : List R[X][Y]) : + l.prod.evalEval x y = (l.map <| evalEval x y).prod := by + simpa only [evalEval, eval_list_prod, List.map_map] using by rfl + +lemma evalEval_multiset_prod (x y : R) (l : Multiset R[X][Y]) : + l.prod.evalEval x y = (l.map <| evalEval x y).prod := by + simpa only [evalEval, eval_multiset_prod, Multiset.map_map] using by rfl + +@[simp] +lemma evalEval_pow (x y : R) (p : R[X][Y]) (n : ℕ) : (p ^ n).evalEval x y = p.evalEval x y ^ n := by + simp only [evalEval, eval_pow] + +lemma evalEval_dvd (x y : R) {p q : R[X][Y]} : p ∣ q → p.evalEval x y ∣ q.evalEval x y := + eval_dvd ∘ eval_dvd + lemma coe_algebraMap_eq_CC : algebraMap R R[X][Y] = CC (R := R) := rfl /-- `evalEval x y` as a ring homomorphism. -/ @@ -58,12 +139,10 @@ lemma coe_algebraMap_eq_CC : algebraMap R R[X][Y] = CC (R := R) := rfl lemma coe_evalEvalRingHom (x y : R) : evalEvalRingHom x y = evalEval x y := rfl -lemma evalEvalRingHom_eq (x : R) : - evalEvalRingHom x = eval₂RingHom (evalRingHom x) := by +lemma evalEvalRingHom_eq (x : R) : evalEvalRingHom x = eval₂RingHom (evalRingHom x) := by ext <;> simp -lemma eval₂_evalRingHom (x : R) : - eval₂ (evalRingHom x) = evalEval x := by +lemma eval₂_evalRingHom (x : R) : eval₂ (evalRingHom x) = evalEval x := by ext1; rw [← coe_evalEvalRingHom, evalEvalRingHom_eq, coe_eval₂RingHom] lemma map_evalRingHom_eval (x y : R) (p : R[X][Y]) : diff --git a/Mathlib/Algebra/Polynomial/Coeff.lean b/Mathlib/Algebra/Polynomial/Coeff.lean index 78b1608e661ac..b2747d4680f9f 100644 --- a/Mathlib/Algebra/Polynomial/Coeff.lean +++ b/Mathlib/Algebra/Polynomial/Coeff.lean @@ -99,7 +99,7 @@ lemma coeff_list_sum (l : List R[X]) (n : ℕ) : lemma coeff_list_sum_map {ι : Type*} (l : List ι) (f : ι → R[X]) (n : ℕ) : (l.map f).sum.coeff n = (l.map (fun a => (f a).coeff n)).sum := by - simp_rw [coeff_list_sum, List.map_map, Function.comp, lcoeff_apply] + simp_rw [coeff_list_sum, List.map_map, Function.comp_def, lcoeff_apply] theorem coeff_sum [Semiring S] (n : ℕ) (f : ℕ → R → S[X]) : coeff (p.sum f) n = p.sum fun a b => coeff (f a b) n := by @@ -119,6 +119,11 @@ theorem coeff_mul (p q : R[X]) (n : ℕ) : @[simp] theorem mul_coeff_zero (p q : R[X]) : coeff (p * q) 0 = coeff p 0 * coeff q 0 := by simp [coeff_mul] +theorem mul_coeff_one (p q : R[X]) : + coeff (p * q) 1 = coeff p 0 * coeff q 1 + coeff p 1 * coeff q 0 := by + rw [coeff_mul, Nat.antidiagonal_eq_map] + simp [sum_range_succ] + /-- `constantCoeff p` returns the constant term of the polynomial `p`, defined as `coeff p 0`. This is a ring homomorphism. -/ @[simps] diff --git a/Mathlib/Algebra/Polynomial/Degree/Definitions.lean b/Mathlib/Algebra/Polynomial/Degree/Definitions.lean index 68a3c4f053f61..c1bc0023501f9 100644 --- a/Mathlib/Algebra/Polynomial/Degree/Definitions.lean +++ b/Mathlib/Algebra/Polynomial/Degree/Definitions.lean @@ -614,13 +614,21 @@ theorem degree_add_eq_left_of_degree_lt (h : degree q < degree p) : degree (p + theorem degree_add_eq_right_of_degree_lt (h : degree p < degree q) : degree (p + q) = degree q := by rw [add_comm, degree_add_eq_left_of_degree_lt h] +theorem natDegree_add_eq_left_of_degree_lt (h : degree q < degree p) : + natDegree (p + q) = natDegree p := + natDegree_eq_of_degree_eq (degree_add_eq_left_of_degree_lt h) + theorem natDegree_add_eq_left_of_natDegree_lt (h : natDegree q < natDegree p) : natDegree (p + q) = natDegree p := - natDegree_eq_of_degree_eq (degree_add_eq_left_of_degree_lt (degree_lt_degree h)) + natDegree_add_eq_left_of_degree_lt (degree_lt_degree h) + +theorem natDegree_add_eq_right_of_degree_lt (h : degree p < degree q) : + natDegree (p + q) = natDegree q := + natDegree_eq_of_degree_eq (degree_add_eq_right_of_degree_lt h) theorem natDegree_add_eq_right_of_natDegree_lt (h : natDegree p < natDegree q) : natDegree (p + q) = natDegree q := - natDegree_eq_of_degree_eq (degree_add_eq_right_of_degree_lt (degree_lt_degree h)) + natDegree_add_eq_right_of_degree_lt (degree_lt_degree h) theorem degree_add_C (hp : 0 < degree p) : degree (p + C a) = degree p := add_comm (C a) p ▸ degree_add_eq_right_of_degree_lt <| lt_of_le_of_lt degree_C_le hp diff --git a/Mathlib/Algebra/Polynomial/Degree/Lemmas.lean b/Mathlib/Algebra/Polynomial/Degree/Lemmas.lean index 9683ab124fc69..d3cc2b29e0004 100644 --- a/Mathlib/Algebra/Polynomial/Degree/Lemmas.lean +++ b/Mathlib/Algebra/Polynomial/Degree/Lemmas.lean @@ -58,6 +58,13 @@ theorem natDegree_comp_le : natDegree (p.comp q) ≤ natDegree p * natDegree q : mul_le_mul_of_nonneg_right (le_natDegree_of_ne_zero (mem_support_iff.1 hn)) (Nat.zero_le _) +theorem natDegree_comp_eq_of_mul_ne_zero (h : p.leadingCoeff * q.leadingCoeff ^ p.natDegree ≠ 0) : + natDegree (p.comp q) = natDegree p * natDegree q := by + by_cases hq : natDegree q = 0 + · exact le_antisymm natDegree_comp_le (by simp [hq]) + apply natDegree_eq_of_le_of_coeff_ne_zero natDegree_comp_le + rwa [coeff_comp_degree_mul_degree hq] + theorem degree_pos_of_root {p : R[X]} (hp : p ≠ 0) (h : IsRoot p a) : 0 < degree p := lt_of_not_ge fun hlt => by have := eq_C_of_degree_le_zero hlt @@ -345,16 +352,15 @@ theorem natDegree_comp : natDegree (p.comp q) = natDegree p * natDegree q := by natDegree_C, mul_zero] · by_cases p0 : p = 0 · simp only [p0, zero_comp, natDegree_zero, zero_mul] - refine le_antisymm natDegree_comp_le (le_natDegree_of_ne_zero ?_) - simp only [coeff_comp_degree_mul_degree q0, p0, mul_eq_zero, leadingCoeff_eq_zero, or_self_iff, - ne_zero_of_natDegree_gt (Nat.pos_of_ne_zero q0), pow_ne_zero, Ne, not_false_iff] + · simp only [Ne, mul_eq_zero, leadingCoeff_eq_zero, p0, natDegree_comp_eq_of_mul_ne_zero, + ne_zero_of_natDegree_gt (Nat.pos_of_ne_zero q0), not_false_eq_true, pow_ne_zero, or_self] @[simp] theorem natDegree_iterate_comp (k : ℕ) : (p.comp^[k] q).natDegree = p.natDegree ^ k * q.natDegree := by - induction' k with k IH - · simp - · rw [Function.iterate_succ_apply', natDegree_comp, IH, pow_succ', mul_assoc] + induction k with + | zero => simp + | succ k IH => rw [Function.iterate_succ_apply', natDegree_comp, IH, pow_succ', mul_assoc] theorem leadingCoeff_comp (hq : natDegree q ≠ 0) : leadingCoeff (p.comp q) = leadingCoeff p * leadingCoeff q ^ natDegree p := by diff --git a/Mathlib/Algebra/Polynomial/Derivative.lean b/Mathlib/Algebra/Polynomial/Derivative.lean index d61d10d525aa9..e4eb94abf7e30 100644 --- a/Mathlib/Algebra/Polynomial/Derivative.lean +++ b/Mathlib/Algebra/Polynomial/Derivative.lean @@ -134,9 +134,9 @@ theorem derivative_smul {S : Type*} [Monoid S] [DistribMulAction S R] [IsScalarT @[simp] theorem iterate_derivative_smul {S : Type*} [Monoid S] [DistribMulAction S R] [IsScalarTower S R R] (s : S) (p : R[X]) (k : ℕ) : derivative^[k] (s • p) = s • derivative^[k] p := by - induction' k with k ih generalizing p - · simp - · simp [ih] + induction k generalizing p with + | zero => simp + | succ k ih => simp [ih] @[simp] theorem iterate_derivative_C_mul (a : R) (p : R[X]) (k : ℕ) : @@ -420,9 +420,11 @@ theorem dvd_iterate_derivative_pow (f : R[X]) (n : ℕ) {m : ℕ} (c : R) (hm : 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 k ih - · erw [Function.iterate_zero_apply, tsub_zero, Nat.descFactorial_zero, Nat.cast_one, one_mul] - · rw [Function.iterate_succ_apply', ih, derivative_natCast_mul, derivative_X_pow, C_eq_natCast, + induction k with + | zero => + erw [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] simp [mul_comm, mul_assoc, mul_left_comm] diff --git a/Mathlib/Algebra/Polynomial/Div.lean b/Mathlib/Algebra/Polynomial/Div.lean index 61c5825557e4d..7533319d50143 100644 --- a/Mathlib/Algebra/Polynomial/Div.lean +++ b/Mathlib/Algebra/Polynomial/Div.lean @@ -167,7 +167,7 @@ theorem zero_modByMonic (p : R[X]) : 0 %ₘ p = 0 := by unfold modByMonic divModByMonicAux dsimp by_cases hp : Monic p - · rw [dif_pos hp, if_neg (mt And.right (not_not_intro rfl))] + · rw [dif_pos hp, if_neg (mt And.right (not_not_intro rfl)), Prod.snd_zero] · rw [dif_neg hp] @[simp] @@ -176,7 +176,7 @@ theorem zero_divByMonic (p : R[X]) : 0 /ₘ p = 0 := by unfold divByMonic divModByMonicAux dsimp by_cases hp : Monic p - · rw [dif_pos hp, if_neg (mt And.right (not_not_intro rfl))] + · rw [dif_pos hp, if_neg (mt And.right (not_not_intro rfl)), Prod.fst_zero] · rw [dif_neg hp] @[simp] diff --git a/Mathlib/Algebra/Polynomial/EraseLead.lean b/Mathlib/Algebra/Polynomial/EraseLead.lean index 8697d21e6eb6a..7f0f5dd10d6e4 100644 --- a/Mathlib/Algebra/Polynomial/EraseLead.lean +++ b/Mathlib/Algebra/Polynomial/EraseLead.lean @@ -150,29 +150,40 @@ theorem eraseLead_C_mul_X_pow (r : R) (n : ℕ) : eraseLead (C r * X ^ n) = 0 := @[simp] lemma eraseLead_C_mul_X (r : R) : eraseLead (C r * X) = 0 := by simpa using eraseLead_C_mul_X_pow _ 1 -theorem eraseLead_add_of_natDegree_lt_left {p q : R[X]} (pq : q.natDegree < p.natDegree) : +theorem eraseLead_add_of_degree_lt_left {p q : R[X]} (pq : q.degree < p.degree) : (p + q).eraseLead = p.eraseLead + q := by ext n by_cases nd : n = p.natDegree - · rw [nd, eraseLead_coeff, if_pos (natDegree_add_eq_left_of_natDegree_lt pq).symm] - simpa using (coeff_eq_zero_of_natDegree_lt pq).symm + · rw [nd, eraseLead_coeff, if_pos (natDegree_add_eq_left_of_degree_lt pq).symm] + simpa using (coeff_eq_zero_of_degree_lt (lt_of_lt_of_le pq degree_le_natDegree)).symm · rw [eraseLead_coeff, coeff_add, coeff_add, eraseLead_coeff, if_neg, if_neg nd] rintro rfl - exact nd (natDegree_add_eq_left_of_natDegree_lt pq) + exact nd (natDegree_add_eq_left_of_degree_lt pq) -theorem eraseLead_add_of_natDegree_lt_right {p q : R[X]} (pq : p.natDegree < q.natDegree) : +theorem eraseLead_add_of_natDegree_lt_left {p q : R[X]} (pq : q.natDegree < p.natDegree) : + (p + q).eraseLead = p.eraseLead + q := + eraseLead_add_of_degree_lt_left (degree_lt_degree pq) + +theorem eraseLead_add_of_degree_lt_right {p q : R[X]} (pq : p.degree < q.degree) : (p + q).eraseLead = p + q.eraseLead := by ext n by_cases nd : n = q.natDegree - · rw [nd, eraseLead_coeff, if_pos (natDegree_add_eq_right_of_natDegree_lt pq).symm] - simpa using (coeff_eq_zero_of_natDegree_lt pq).symm + · rw [nd, eraseLead_coeff, if_pos (natDegree_add_eq_right_of_degree_lt pq).symm] + simpa using (coeff_eq_zero_of_degree_lt (lt_of_lt_of_le pq degree_le_natDegree)).symm · rw [eraseLead_coeff, coeff_add, coeff_add, eraseLead_coeff, if_neg, if_neg nd] rintro rfl - exact nd (natDegree_add_eq_right_of_natDegree_lt pq) + exact nd (natDegree_add_eq_right_of_degree_lt pq) + +theorem eraseLead_add_of_natDegree_lt_right {p q : R[X]} (pq : p.natDegree < q.natDegree) : + (p + q).eraseLead = p + q.eraseLead := + eraseLead_add_of_degree_lt_right (degree_lt_degree pq) theorem eraseLead_degree_le : (eraseLead f).degree ≤ f.degree := f.degree_erase_le _ +theorem degree_eraseLead_lt (hf : f ≠ 0) : (eraseLead f).degree < f.degree := + f.degree_erase_lt hf + theorem eraseLead_natDegree_le_aux : (eraseLead f).natDegree ≤ f.natDegree := natDegree_le_natDegree eraseLead_degree_le diff --git a/Mathlib/Algebra/Polynomial/Eval.lean b/Mathlib/Algebra/Polynomial/Eval.lean index e05c9576c8836..13fd989d6ed3c 100644 --- a/Mathlib/Algebra/Polynomial/Eval.lean +++ b/Mathlib/Algebra/Polynomial/Eval.lean @@ -400,9 +400,9 @@ theorem eval_mul_X : (p * X).eval x = p.eval x * x := by @[simp] theorem eval_mul_X_pow {k : ℕ} : (p * X ^ k).eval x = p.eval x * x ^ k := by - induction' k with k ih - · simp - · simp [pow_succ, ← mul_assoc, ih] + induction k with + | zero => simp + | succ k ih => simp [pow_succ, ← mul_assoc, ih] theorem eval_sum (p : R[X]) (f : ℕ → R → R[X]) (x : R) : (p.sum f).eval x = p.sum fun n a => (f n a).eval x := @@ -511,15 +511,15 @@ theorem mul_X_comp : (p * X).comp r = p.comp r * r := by @[simp] theorem X_pow_comp {k : ℕ} : (X ^ k).comp p = p ^ k := by - induction' k with k ih - · simp - · simp [pow_succ, mul_X_comp, ih] + induction k with + | zero => simp + | succ k ih => simp [pow_succ, mul_X_comp, ih] @[simp] theorem mul_X_pow_comp {k : ℕ} : (p * X ^ k).comp r = p.comp r * r ^ k := by - induction' k with k ih - · simp - · simp [ih, pow_succ, ← mul_assoc, mul_X_comp] + induction k with + | zero => simp + | succ k ih => simp [ih, pow_succ, ← mul_assoc, mul_X_comp] @[simp] theorem C_mul_comp : (C a * p).comp r = C a * p.comp r := by @@ -898,9 +898,9 @@ theorem eval₂_comp {x : S} : eval₂ f x (p.comp q) = eval₂ f (eval₂ f x q @[simp] theorem iterate_comp_eval₂ (k : ℕ) (t : S) : eval₂ f t (p.comp^[k] q) = (fun x => eval₂ f x p)^[k] (eval₂ f t q) := by - induction' k with k IH - · simp - · rw [Function.iterate_succ_apply', Function.iterate_succ_apply', eval₂_comp, IH] + induction k with + | zero => simp + | succ k IH => rw [Function.iterate_succ_apply', Function.iterate_succ_apply', eval₂_comp, IH] end diff --git a/Mathlib/Algebra/Polynomial/Induction.lean b/Mathlib/Algebra/Polynomial/Induction.lean index 3e3fdb290f72c..242facc658dde 100644 --- a/Mathlib/Algebra/Polynomial/Induction.lean +++ b/Mathlib/Algebra/Polynomial/Induction.lean @@ -75,7 +75,7 @@ theorem span_le_of_C_coeff_mem (cf : ∀ i : ℕ, C (f.coeff i) ∈ I) : theorem mem_span_C_coeff : f ∈ Ideal.span { g : R[X] | ∃ i : ℕ, g = C (coeff f i) } := by let p := Ideal.span { g : R[X] | ∃ i : ℕ, g = C (coeff f i) } - nth_rw 1 [(sum_C_mul_X_pow_eq f).symm] + nth_rw 2 [(sum_C_mul_X_pow_eq f).symm] refine Submodule.sum_mem _ fun n _hn => ?_ dsimp have : C (coeff f n) ∈ p := by diff --git a/Mathlib/Algebra/Polynomial/Laurent.lean b/Mathlib/Algebra/Polynomial/Laurent.lean index 7368130e5cb45..c5523266588fe 100644 --- a/Mathlib/Algebra/Polynomial/Laurent.lean +++ b/Mathlib/Algebra/Polynomial/Laurent.lean @@ -542,10 +542,10 @@ lemma involutive_invert : Involutive (invert (R := R)) := fun _ ↦ by ext; simp lemma toLaurent_reverse (p : R[X]) : toLaurent p.reverse = invert (toLaurent p) * (T p.natDegree) := by nontriviality R - induction' p using Polynomial.recOnHorner with p t _ _ ih p hp ih - · simp - · simp [add_mul, ← ih] - · simpa [natDegree_mul_X hp] + induction p using Polynomial.recOnHorner with + | M0 => simp + | MC _ _ _ _ ih => simp [add_mul, ← ih] + | MX _ hp => simpa [natDegree_mul_X hp] end Inversion diff --git a/Mathlib/Algebra/Polynomial/Module/AEval.lean b/Mathlib/Algebra/Polynomial/Module/AEval.lean index 101d2de77a9a8..daa261800b354 100644 --- a/Mathlib/Algebra/Polynomial/Module/AEval.lean +++ b/Mathlib/Algebra/Polynomial/Module/AEval.lean @@ -110,8 +110,7 @@ lemma annihilator_top_eq_ker_aeval [FaithfulSMul A M] : section Submodule -variable {p : Submodule R M} (hp : p ≤ p.comap (Algebra.lsmul R R M a)) - {q : Submodule R[X] <| AEval R M a} +variable {p : Submodule R M} {q : Submodule R[X] <| AEval R M a} variable (R M) in /-- We can turn an `R[X]`-submodule into an `R`-submodule by forgetting the action of `X`. -/ @@ -132,7 +131,7 @@ def comapSubmodule : /-- An `R`-submodule which is stable under the action of `a` can be promoted to an `R[X]`-submodule. -/ -def mapSubmodule : Submodule R[X] <| AEval R M a := +def mapSubmodule (hp : p ≤ p.comap (Algebra.lsmul R R M a)) : Submodule R[X] <| AEval R M a := { toAddSubmonoid := p.toAddSubmonoid.map (of R M a) smul_mem' := by rintro f - ⟨m : M, h : m ∈ p, rfl⟩ @@ -140,6 +139,8 @@ def mapSubmodule : Submodule R[X] <| AEval R M a := Submodule.mem_toAddSubmonoid] exact ⟨aeval a f • m, aeval_apply_smul_mem_of_le_comap' h f a hp, of_aeval_smul a f m⟩ } +variable (hp : p ≤ p.comap (Algebra.lsmul R R M a)) + @[simp] lemma mem_mapSubmodule {m : AEval R M a} : m ∈ mapSubmodule a hp ↔ (of R M a).symm m ∈ p := ⟨fun ⟨_, hm, hm'⟩ ↦ hm'.symm ▸ hm, fun hm ↦ ⟨(of R M a).symm m, hm, rfl⟩⟩ diff --git a/Mathlib/Algebra/Polynomial/Module/Basic.lean b/Mathlib/Algebra/Polynomial/Module/Basic.lean index 4beded12152cd..c5e69f5e9a19f 100644 --- a/Mathlib/Algebra/Polynomial/Module/Basic.lean +++ b/Mathlib/Algebra/Polynomial/Module/Basic.lean @@ -66,7 +66,7 @@ theorem add_apply (g₁ g₂ : PolynomialModule R M) (a : ℕ) : (g₁ + g₂) a Finsupp.add_apply g₁ g₂ a /-- The monomial `m * x ^ i`. This is defeq to `Finsupp.singleAddHom`, and is redefined here -so that it has the desired type signature. -/ +so that it has the desired type signature. -/ noncomputable def single (i : ℕ) : M →+ PolynomialModule R M := Finsupp.singleAddHom i @@ -177,10 +177,11 @@ noncomputable def equivPolynomialSelf : PolynomialModule R R ≃ₗ[R[X]] R[X] : map_smul' := fun r x => by dsimp rw [← RingEquiv.coe_toEquiv_symm, RingEquiv.coe_toEquiv] - induction' x using induction_linear with _ _ hp hq n a - · rw [smul_zero, map_zero, mul_zero] - · rw [smul_add, map_add, map_add, mul_add, hp, hq] - · ext i + induction x using induction_linear with + | h0 => rw [smul_zero, map_zero, mul_zero] + | hadd _ _ hp hq => rw [smul_add, map_add, map_add, mul_add, hp, hq] + | hsingle n a => + ext i simp only [coeff_ofFinsupp, smul_single_apply, toFinsuppIso_symm_apply, coeff_ofFinsupp, single_apply, smul_eq_mul, Polynomial.coeff_mul, mul_ite, mul_zero] split_ifs with hn @@ -240,10 +241,10 @@ theorem map_smul (f : M →ₗ[R] M') (p : R[X]) (q : PolynomialModule R M) : · intro f g e₁ e₂ rw [smul_add, map_add, e₁, e₂, map_add, smul_add] intro i m - induction' p using Polynomial.induction_on' with _ _ e₁ e₂ - · rw [add_smul, map_add, e₁, e₂, Polynomial.map_add, add_smul] - · rw [monomial_smul_single, map_single, Polynomial.map_monomial, map_single, monomial_smul_single, - f.map_smul, algebraMap_smul] + induction p using Polynomial.induction_on' with + | h_add _ _ e₁ e₂ => rw [add_smul, map_add, e₁, e₂, Polynomial.map_add, add_smul] + | h_monomial => rw [monomial_smul_single, map_single, Polynomial.map_monomial, map_single, + monomial_smul_single, f.map_smul, algebraMap_smul] /-- Evaluate a polynomial `p : PolynomialModule R M` at `r : R`. -/ @[simps! (config := .lemmasOnly)] @@ -273,10 +274,10 @@ theorem eval_smul (p : R[X]) (q : PolynomialModule R M) (r : R) : · intro f g e₁ e₂ rw [smul_add, map_add, e₁, e₂, map_add, smul_add] intro i m - induction' p using Polynomial.induction_on' with _ _ e₁ e₂ - · rw [add_smul, map_add, Polynomial.eval_add, e₁, e₂, add_smul] - · rw [monomial_smul_single, eval_single, Polynomial.eval_monomial, eval_single, smul_comm, ← - smul_smul, pow_add, mul_smul] + 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] @[simp] theorem eval_map (f : M →ₗ[R] M') (q : PolynomialModule R M) (r : R) : @@ -305,7 +306,7 @@ lemma aeval_equivPolynomial {S : Type*} [CommRing S] [Algebra S R] rw [equivPolynomial_single, aeval_monomial, mul_comm, map_single, Algebra.linearMap_apply, eval_single, smul_eq_mul] -/-- `comp p q` is the composition of `p : R[X]` and `q : M[X]` as `q(p(x))`. -/ +/-- `comp p q` is the composition of `p : R[X]` and `q : M[X]` as `q(p(x))`. -/ @[simps!] noncomputable def comp (p : R[X]) : PolynomialModule R M →ₗ[R] PolynomialModule R M := LinearMap.comp ((eval p).restrictScalars R) (map R[X] (lsingle R 0)) diff --git a/Mathlib/Algebra/Polynomial/Monic.lean b/Mathlib/Algebra/Polynomial/Monic.lean index 60c51bbad7bce..9ab637bcebdd6 100644 --- a/Mathlib/Algebra/Polynomial/Monic.lean +++ b/Mathlib/Algebra/Polynomial/Monic.lean @@ -83,16 +83,15 @@ theorem monic_of_degree_le (n : ℕ) (H1 : degree p ≤ n) (H2 : coeff p n = 1) fun H : ¬degree p < n => by rwa [Monic, Polynomial.leadingCoeff, natDegree, (lt_or_eq_of_le H1).resolve_left H] -theorem monic_X_pow_add {n : ℕ} (H : degree p ≤ n) : Monic (X ^ (n + 1) + p) := - have H1 : degree p < (n + 1 : ℕ) := lt_of_le_of_lt H (WithBot.coe_lt_coe.2 (Nat.lt_succ_self n)) - monic_of_degree_le (n + 1) - (le_trans (degree_add_le _ _) (max_le (degree_X_pow_le _) (le_of_lt H1))) - (by rw [coeff_add, coeff_X_pow, if_pos rfl, coeff_eq_zero_of_degree_lt H1, add_zero]) +theorem monic_X_pow_add {n : ℕ} (H : degree p < n) : Monic (X ^ n + p) := + monic_of_degree_le n + (le_trans (degree_add_le _ _) (max_le (degree_X_pow_le _) (le_of_lt H))) + (by rw [coeff_add, coeff_X_pow, if_pos rfl, coeff_eq_zero_of_degree_lt H, add_zero]) variable (a) in -theorem monic_X_pow_add_C {n : ℕ} (h : n ≠ 0) : (X ^ n + C a).Monic := by - obtain ⟨k, rfl⟩ := Nat.exists_eq_succ_of_ne_zero h - exact monic_X_pow_add <| degree_C_le.trans Nat.WithBot.coe_nonneg +theorem monic_X_pow_add_C {n : ℕ} (h : n ≠ 0) : (X ^ n + C a).Monic := + monic_X_pow_add <| (lt_of_le_of_lt degree_C_le + (by simp only [Nat.cast_pos, Nat.pos_iff_ne_zero, ne_eq, h, not_false_eq_true])) theorem monic_X_add_C (x : R) : Monic (X + C x) := pow_one (X : R[X]) ▸ monic_X_pow_add_C x one_ne_zero @@ -184,9 +183,7 @@ theorem nextCoeff_mul (hp : Monic p) (hq : Monic q) : nextCoeff (p * q) = nextCoeff p + nextCoeff q := by nontriviality simp only [← coeff_one_reverse] - rw [reverse_mul] <;> - simp [coeff_mul, antidiagonal, hp.leadingCoeff, hq.leadingCoeff, add_comm, - show Nat.succ 0 = 1 from rfl] + rw [reverse_mul] <;> simp [hp.leadingCoeff, hq.leadingCoeff, mul_coeff_one, add_comm] theorem nextCoeff_pow (hp : p.Monic) (n : ℕ) : (p ^ n).nextCoeff = n • p.nextCoeff := by induction n with @@ -340,8 +337,8 @@ variable [Ring R] {p : R[X]} theorem monic_X_sub_C (x : R) : Monic (X - C x) := by simpa only [sub_eq_add_neg, C_neg] using monic_X_add_C (-x) -theorem monic_X_pow_sub {n : ℕ} (H : degree p ≤ n) : Monic (X ^ (n + 1) - p) := by - simpa [sub_eq_add_neg] using monic_X_pow_add (show degree (-p) ≤ n by rwa [← degree_neg p] at H) +theorem monic_X_pow_sub {n : ℕ} (H : degree p < n) : Monic (X ^ n - p) := by + simpa [sub_eq_add_neg] using monic_X_pow_add (show degree (-p) < n by rwa [← degree_neg p] at H) /-- `X ^ n - a` is monic. -/ theorem monic_X_pow_sub_C {R : Type u} [Ring R] (a : R) {n : ℕ} (h : n ≠ 0) : diff --git a/Mathlib/Algebra/Polynomial/Reverse.lean b/Mathlib/Algebra/Polynomial/Reverse.lean index 788dcb3ce0de2..2dba679853097 100644 --- a/Mathlib/Algebra/Polynomial/Reverse.lean +++ b/Mathlib/Algebra/Polynomial/Reverse.lean @@ -86,7 +86,7 @@ In other words, the terms with exponent `[0, ..., N]` now have exponent `[N, ... In practice, `reflect` is only used when `N` is at least as large as the degree of `f`. -Eventually, it will be used with `N` exactly equal to the degree of `f`. -/ +Eventually, it will be used with `N` exactly equal to the degree of `f`. -/ noncomputable def reflect (N : ℕ) : R[X] → R[X] | ⟨f⟩ => ⟨Finsupp.embDomain (revAt N) f⟩ diff --git a/Mathlib/Algebra/Polynomial/RingDivision.lean b/Mathlib/Algebra/Polynomial/RingDivision.lean index c3fd1bd83e3f6..e4e14ccf3d644 100644 --- a/Mathlib/Algebra/Polynomial/RingDivision.lean +++ b/Mathlib/Algebra/Polynomial/RingDivision.lean @@ -27,6 +27,26 @@ universe u v w z variable {R : Type u} {S : Type v} {T : Type w} {a b : R} {n : ℕ} +section Semiring + +variable [Semiring R] {p q : R[X]} + +theorem Monic.comp (hp : p.Monic) (hq : q.Monic) (h : q.natDegree ≠ 0) : (p.comp q).Monic := by + nontriviality R + have : (p.comp q).natDegree = p.natDegree * q.natDegree := by + apply natDegree_comp_eq_of_mul_ne_zero + simp [hp.leadingCoeff, hq.leadingCoeff] + rw [Monic.def, Polynomial.leadingCoeff, this, coeff_comp_degree_mul_degree h, hp.leadingCoeff, + hq.leadingCoeff, one_pow, mul_one] + +theorem Monic.comp_X_add_C (hp : p.Monic) (r : R) : (p.comp (X + C r)).Monic := by + nontriviality R + refine hp.comp (monic_X_add_C _) fun ha => ?_ + rw [natDegree_X_add_C] at ha + exact one_ne_zero ha + +end Semiring + section CommRing variable [CommRing R] {p q : R[X]} @@ -210,8 +230,6 @@ theorem not_isUnit_of_natDegree_pos (p : R[X]) (hpl : 0 < p.natDegree) : ¬ IsUnit p := not_isUnit_of_degree_pos _ (natDegree_pos_iff_degree_pos.mp hpl) -variable [CharZero R] - end NoZeroDivisors section NoZeroDivisors @@ -527,6 +545,9 @@ theorem rootMultiplicity_mul' {p q : R[X]} {x : R} simp_rw [eval_divByMonic_eq_trailingCoeff_comp] at hpq simp_rw [rootMultiplicity_eq_natTrailingDegree, mul_comp, natTrailingDegree_mul' hpq] +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) + variable [IsDomain R] {p q : R[X]} @[simp] @@ -654,17 +675,6 @@ theorem natDegree_multiset_prod_X_sub_C_eq_card (s : Multiset R) : mul_one] · exact Multiset.forall_mem_map_iff.2 fun a _ => monic_X_sub_C a -theorem Monic.comp (hp : p.Monic) (hq : q.Monic) (h : q.natDegree ≠ 0) : (p.comp q).Monic := by - rw [Monic.def, leadingCoeff_comp h, Monic.def.1 hp, Monic.def.1 hq, one_pow, one_mul] - -theorem Monic.comp_X_add_C (hp : p.Monic) (r : R) : (p.comp (X + C r)).Monic := by - refine hp.comp (monic_X_add_C _) fun ha => ?_ - rw [natDegree_X_add_C] at ha - exact one_ne_zero ha - -theorem Monic.comp_X_sub_C (hp : p.Monic) (r : R) : (p.comp (X - C r)).Monic := by - simpa using hp.comp_X_add_C (-r) - theorem units_coeff_zero_smul (c : R[X]ˣ) (p : R[X]) : (c : R[X]).coeff 0 • p = c * p := by rw [← Polynomial.C_mul', ← Polynomial.eq_C_of_degree_eq_zero (degree_coe_units c)] diff --git a/Mathlib/Algebra/Quandle.lean b/Mathlib/Algebra/Quandle.lean index aa9218bc51e55..a3921e4072e72 100644 --- a/Mathlib/Algebra/Quandle.lean +++ b/Mathlib/Algebra/Quandle.lean @@ -93,7 +93,7 @@ The binary operation is regarded as a left action of the type on itself. class Shelf (α : Type u) where /-- The action of the `Shelf` over `α`-/ act : α → α → α - /-- A verification that `act` is self-distributive-/ + /-- A verification that `act` is self-distributive -/ self_distrib : ∀ {x y z : α}, act x (act y z) = act (act x y) (act x z) /-- @@ -111,7 +111,7 @@ This is also the notion of rack and quandle homomorphisms. structure ShelfHom (S₁ : Type*) (S₂ : Type*) [Shelf S₁] [Shelf S₂] where /-- The function under the Shelf Homomorphism -/ toFun : S₁ → S₂ - /-- The homomorphism property of a Shelf Homomorphism-/ + /-- The homomorphism property of a Shelf Homomorphism -/ map_act' : ∀ {x y : S₁}, toFun (Shelf.act x y) = Shelf.act (toFun x) (toFun y) /-- A *rack* is an automorphic set (a set with an action on itself by @@ -129,13 +129,13 @@ class Rack (α : Type u) extends Shelf α where /-- Proof of right inverse -/ right_inv : ∀ x, Function.RightInverse (invAct x) (act x) -/-- Action of a Shelf-/ +/-- Action of a Shelf -/ scoped[Quandles] infixr:65 " ◃ " => Shelf.act -/-- Inverse Action of a Rack-/ +/-- Inverse Action of a Rack -/ scoped[Quandles] infixr:65 " ◃⁻¹ " => Rack.invAct -/-- Shelf Homomorphism-/ +/-- Shelf Homomorphism -/ scoped[Quandles] infixr:25 " →◃ " => ShelfHom open Quandles @@ -372,7 +372,7 @@ theorem fix_inv {x : Q} : x ◃⁻¹ x = x := by instance oppositeQuandle : Quandle Qᵐᵒᵖ where fix := by intro x - induction' x + induction x simp /-- The conjugation quandle of a group. Each element of the group acts by @@ -679,16 +679,18 @@ def toEnvelGroup.map {R : Type*} [Rack R] {G : Type*} [Group G] : right_inv F := MonoidHom.ext fun x => Quotient.inductionOn x fun x => by - induction' x with _ x y ih_x ih_y x ih_x - · exact F.map_one.symm - · rfl - · have hm : ⟦x.mul y⟧ = @Mul.mul (EnvelGroup R) _ ⟦x⟧ ⟦y⟧ := rfl + induction x with + | unit => exact F.map_one.symm + | incl => rfl + | mul x y ih_x ih_y => + have hm : ⟦x.mul y⟧ = @Mul.mul (EnvelGroup R) _ ⟦x⟧ ⟦y⟧ := rfl simp only [MonoidHom.coe_mk, OneHom.coe_mk, Quotient.lift_mk] suffices ∀ x y, F (Mul.mul x y) = F (x) * F (y) by simp_all only [MonoidHom.coe_mk, OneHom.coe_mk, Quotient.lift_mk, hm] rw [← ih_x, ← ih_y, mapAux] exact F.map_mul - · have hm : ⟦x.inv⟧ = @Inv.inv (EnvelGroup R) _ ⟦x⟧ := rfl + | inv x ih_x => + have hm : ⟦x.inv⟧ = @Inv.inv (EnvelGroup R) _ ⟦x⟧ := rfl rw [hm, F.map_inv, MonoidHom.map_inv, ih_x] /-- Given a homomorphism from a rack to a group, it factors through the enveloping group. diff --git a/Mathlib/Algebra/Quaternion.lean b/Mathlib/Algebra/Quaternion.lean index 56d78e1cdaf61..a063ebfdef089 100644 --- a/Mathlib/Algebra/Quaternion.lean +++ b/Mathlib/Algebra/Quaternion.lean @@ -296,7 +296,7 @@ variable [Ring R] * `i * j = k`, `j * i = -k`; * `k * k = -c₁ * c₂`; * `i * k = c₁ * j`, `k * i = -c₁ * j`; -* `j * k = -c₂ * i`, `k * j = c₂ * i`. -/ +* `j * k = -c₂ * i`, `k * j = c₂ * i`. -/ instance : Mul ℍ[R,c₁,c₂] := ⟨fun a b => ⟨a.1 * b.1 + c₁ * a.2 * b.2 + c₂ * a.3 * b.3 - c₁ * c₂ * a.4 * b.4, diff --git a/Mathlib/Algebra/Ring/Action/Group.lean b/Mathlib/Algebra/Ring/Action/Group.lean index 4317fba7f1f4a..428c3c34e2ae9 100644 --- a/Mathlib/Algebra/Ring/Action/Group.lean +++ b/Mathlib/Algebra/Ring/Action/Group.lean @@ -11,7 +11,7 @@ import Mathlib.Algebra.Ring.Equiv # If a group acts multiplicatively on a semiring, each group element acts by a ring automorphism. This result is split out from `Mathlib.Algebra.Ring.Action.Basic` -to avoid needing the import of `Mathlib.GroupTheory.GroupAction.Group`. +to avoid needing the import of `Mathlib.Algebra.GroupWithZero.Action.Basic`. -/ section Semiring diff --git a/Mathlib/Algebra/Ring/Aut.lean b/Mathlib/Algebra/Ring/Aut.lean index 881e53ba2eaeb..79289b53c66ec 100644 --- a/Mathlib/Algebra/Ring/Aut.lean +++ b/Mathlib/Algebra/Ring/Aut.lean @@ -18,7 +18,7 @@ The definition of multiplication in the automorphism group agrees with function multiplication in `Equiv.Perm`, and multiplication in `CategoryTheory.End`, but not with `CategoryTheory.comp`. -This file is kept separate from `Data/Equiv/Ring` so that `GroupTheory.Perm` is free to use +This file is kept separate from `Algebra/Ring/Equiv.lean` so that `GroupTheory.Perm` is free to use equivalences (and other files that use them) before the group structure is defined. ## Tags diff --git a/Mathlib/Algebra/Ring/CentroidHom.lean b/Mathlib/Algebra/Ring/CentroidHom.lean index 68eb72c1e0691..25857d52638e5 100644 --- a/Mathlib/Algebra/Ring/CentroidHom.lean +++ b/Mathlib/Algebra/Ring/CentroidHom.lean @@ -475,8 +475,9 @@ def centerToCentroidCenter : simp only [ZeroMemClass.coe_zero, map_zero] exact rfl map_add' := fun _ _ => by - simp only [AddSubmonoid.coe_add, NonUnitalSubsemiring.coe_toAddSubmonoid, map_add] - exact rfl + dsimp + simp only [map_add] + rfl map_mul' z₁ z₂ := by ext a; exact (z₁.prop.left_assoc z₂ a).symm instance : FunLike (Subsemiring.center (CentroidHom α)) α α where diff --git a/Mathlib/Algebra/Ring/CompTypeclasses.lean b/Mathlib/Algebra/Ring/CompTypeclasses.lean index 4a9a7a943c8b9..e6fce8299f6a4 100644 --- a/Mathlib/Algebra/Ring/CompTypeclasses.lean +++ b/Mathlib/Algebra/Ring/CompTypeclasses.lean @@ -122,7 +122,7 @@ theorem of_ringEquiv (e : R₁ ≃+* R₂) : RingHomInvPair (↑e : R₁ →+* R /-- Swap the direction of a `RingHomInvPair`. This is not an instance as it would loop, and better -instances are often available and may often be preferrable to using this one. Indeed, this +instances are often available and may often be preferable to using this one. Indeed, this declaration is not currently used in mathlib. -/ theorem symm (σ₁₂ : R₁ →+* R₂) (σ₂₁ : R₂ →+* R₁) [RingHomInvPair σ₁₂ σ₂₁] : diff --git a/Mathlib/Algebra/Ring/Equiv.lean b/Mathlib/Algebra/Ring/Equiv.lean index f08987f2fa38f..246dcd9e49330 100644 --- a/Mathlib/Algebra/Ring/Equiv.lean +++ b/Mathlib/Algebra/Ring/Equiv.lean @@ -246,8 +246,7 @@ theorem invFun_eq_symm (f : R ≃+* S) : EquivLike.inv f = f.symm := rfl @[simp] -theorem symm_symm (e : R ≃+* S) : e.symm.symm = e := - ext fun _ => rfl +theorem symm_symm (e : R ≃+* S) : e.symm.symm = e := rfl @[simp] theorem symm_refl : (RingEquiv.refl R).symm = RingEquiv.refl R := @@ -265,7 +264,7 @@ theorem mk_coe' (e : R ≃+* S) (f h₁ h₂ h₃ h₄) : (⟨⟨f, ⇑e, h₁, h₂⟩, h₃, h₄⟩ : S ≃+* R) = e.symm := symm_bijective.injective <| ext fun _ => rfl -/-- Auxilliary definition to avoid looping in `dsimp` with `RingEquiv.symm_mk`. -/ +/-- Auxiliary definition to avoid looping in `dsimp` with `RingEquiv.symm_mk`. -/ protected def symm_mk.aux (f : R → S) (g h₁ h₂ h₃ h₄) := (mk ⟨f, g, h₁, h₂⟩ h₃ h₄).symm @[simp] diff --git a/Mathlib/Algebra/Ring/Int.lean b/Mathlib/Algebra/Ring/Int.lean index f299cce6dcf91..68823fef425a9 100644 --- a/Mathlib/Algebra/Ring/Int.lean +++ b/Mathlib/Algebra/Ring/Int.lean @@ -97,19 +97,24 @@ 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_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] + +@[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] -@[simp] lemma odd_iff_not_even : Odd n ↔ ¬Even n := by rw [not_even_iff, odd_iff] +@[deprecated not_even_iff_odd (since := "2024-08-21")] +lemma odd_iff_not_even : Odd n ↔ ¬Even n := by rw [not_even_iff, odd_iff] -lemma even_or_odd (n : ℤ) : Even n ∨ Odd n := Or.imp_right odd_iff_not_even.2 <| em <| Even n +lemma even_or_odd (n : ℤ) : Even n ∨ Odd n := Or.imp_right not_even_iff_odd.1 <| em <| Even n lemma even_or_odd' (n : ℤ) : ∃ k, n = 2 * k ∨ n = 2 * k + 1 := by simpa only [two_mul, exists_or, Odd, Even] using even_or_odd n lemma even_xor'_odd (n : ℤ) : Xor' (Even n) (Odd n) := by cases even_or_odd n with - | inl h => exact Or.inl ⟨h, even_iff_not_odd.mp h⟩ - | inr h => exact Or.inr ⟨h, odd_iff_not_even.mp h⟩ + | inl h => exact Or.inl ⟨h, not_odd_iff_even.2 h⟩ + | inr h => exact Or.inr ⟨h, not_even_iff_odd.2 h⟩ lemma even_xor'_odd' (n : ℤ) : ∃ k, Xor' (n = 2 * k) (n = 2 * k + 1) := by rcases even_or_odd n with (⟨k, rfl⟩ | ⟨k, rfl⟩) <;> use k @@ -118,45 +123,40 @@ lemma even_xor'_odd' (n : ℤ) : ∃ k, Xor' (n = 2 * k) (n = 2 * k + 1) := by · simp only [Xor', add_right_eq_self, false_or_iff, eq_self_iff_true, not_true, not_false_iff, one_ne_zero, and_self_iff] -instance : DecidablePred (Odd : ℤ → Prop) := fun _ => decidable_of_iff _ odd_iff_not_even.symm +instance : DecidablePred (Odd : ℤ → Prop) := fun _ => decidable_of_iff _ not_even_iff_odd lemma even_add' : Even (m + n) ↔ (Odd m ↔ Odd n) := by - rw [even_add, even_iff_not_odd, even_iff_not_odd, not_iff_not] - -set_option linter.deprecated false in - -@[simp, deprecated (since := "2023-01-26")] -lemma not_even_bit1 (n : ℤ) : ¬Even (2 * n + 1) := by simp [parity_simps] + rw [even_add, ← not_odd_iff_even, ← not_odd_iff_even, not_iff_not] lemma not_even_two_mul_add_one (n : ℤ) : ¬ Even (2 * n + 1) := - odd_iff_not_even.1 <| odd_two_mul_add_one n + not_even_iff_odd.2 <| odd_two_mul_add_one n lemma even_sub' : Even (m - n) ↔ (Odd m ↔ Odd n) := by - rw [even_sub, even_iff_not_odd, even_iff_not_odd, not_iff_not] + rw [even_sub, ← not_odd_iff_even, ← not_odd_iff_even, not_iff_not] -lemma odd_mul : Odd (m * n) ↔ Odd m ∧ Odd n := by simp [not_or, parity_simps] +lemma odd_mul : Odd (m * n) ↔ Odd m ∧ Odd n := by simp [← not_even_iff_odd, not_or, parity_simps] lemma Odd.of_mul_left (h : Odd (m * n)) : Odd m := (odd_mul.mp h).1 lemma Odd.of_mul_right (h : Odd (m * n)) : Odd n := (odd_mul.mp h).2 @[parity_simps] lemma odd_pow {n : ℕ} : Odd (m ^ n) ↔ Odd m ∨ n = 0 := by - rw [← not_iff_not, ← even_iff_not_odd, not_or, ← even_iff_not_odd, even_pow] + rw [← not_iff_not, not_odd_iff_even, not_or, not_odd_iff_even, even_pow] lemma odd_pow' {n : ℕ} (h : n ≠ 0) : Odd (m ^ n) ↔ Odd m := odd_pow.trans <| or_iff_left h @[parity_simps] lemma odd_add : Odd (m + n) ↔ (Odd m ↔ Even n) := by - rw [odd_iff_not_even, even_add, not_iff, odd_iff_not_even] + rw [← not_even_iff_odd, even_add, not_iff, ← not_even_iff_odd] lemma odd_add' : Odd (m + n) ↔ (Odd n ↔ Even m) := by rw [add_comm, odd_add] -lemma ne_of_odd_add (h : Odd (m + n)) : m ≠ n := fun hnot ↦ by simp [hnot, parity_simps] at h +lemma ne_of_odd_add (h : Odd (m + n)) : m ≠ n := by rintro rfl; simp [← not_even_iff_odd] at h @[parity_simps] lemma odd_sub : Odd (m - n) ↔ (Odd m ↔ Even n) := by - rw [odd_iff_not_even, even_sub, not_iff, odd_iff_not_even] + rw [← not_even_iff_odd, even_sub, not_iff, ← not_even_iff_odd] lemma odd_sub' : Odd (m - n) ↔ (Odd n ↔ Even m) := by - rw [odd_iff_not_even, even_sub, not_iff, not_iff_comm, odd_iff_not_even] + rw [← not_even_iff_odd, even_sub, not_iff, not_iff_comm, ← not_even_iff_odd] lemma even_mul_succ_self (n : ℤ) : Even (n * (n + 1)) := by simpa [even_mul, parity_simps] using n.even_or_odd @@ -166,7 +166,7 @@ lemma even_mul_pred_self (n : ℤ) : Even (n * (n - 1)) := by -- Porting note (#10618): was simp. simp can prove this. @[norm_cast] lemma odd_coe_nat (n : ℕ) : Odd (n : ℤ) ↔ Odd n := by - rw [odd_iff_not_even, Nat.odd_iff_not_even, even_coe_nat] + rw [← not_even_iff_odd, ← Nat.not_even_iff_odd, even_coe_nat] @[simp] lemma natAbs_even : Even n.natAbs ↔ Even n := by simp [even_iff_two_dvd, dvd_natAbs, natCast_dvd.symm] @@ -174,7 +174,7 @@ lemma even_mul_pred_self (n : ℤ) : Even (n * (n - 1)) := by -- Porting note (#10618): was simp. simp can prove this. --@[simp] lemma natAbs_odd : Odd n.natAbs ↔ Odd n := by - rw [odd_iff_not_even, Nat.odd_iff_not_even, natAbs_even] + rw [← not_even_iff_odd, ← Nat.not_even_iff_odd, natAbs_even] alias ⟨_, _root_.Even.natAbs⟩ := natAbs_even diff --git a/Mathlib/Algebra/Ring/NegOnePow.lean b/Mathlib/Algebra/Ring/NegOnePow.lean index 0ad5c85f38899..6696881dcbf2e 100644 --- a/Mathlib/Algebra/Ring/NegOnePow.lean +++ b/Mathlib/Algebra/Ring/NegOnePow.lean @@ -55,7 +55,7 @@ lemma negOnePow_two_mul_add_one (n : ℤ) : (2 * n + 1).negOnePow = -1 := lemma negOnePow_eq_one_iff (n : ℤ) : n.negOnePow = 1 ↔ Even n := by constructor · intro h - rw [Int.even_iff_not_odd] + rw [← Int.not_odd_iff_even] intro h' simp only [negOnePow_odd _ h'] at h contradiction @@ -64,7 +64,7 @@ lemma negOnePow_eq_one_iff (n : ℤ) : n.negOnePow = 1 ↔ Even n := by lemma negOnePow_eq_neg_one_iff (n : ℤ) : n.negOnePow = -1 ↔ Odd n := by constructor · intro h - rw [Int.odd_iff_not_even] + rw [← Int.not_even_iff_odd] intro h' rw [negOnePow_even _ h'] at h contradiction @@ -92,9 +92,9 @@ lemma negOnePow_eq_iff (n₁ n₂ : ℤ) : by_cases h₂ : Even n₂ · rw [negOnePow_even _ h₂, Int.even_sub, negOnePow_eq_one_iff] tauto - · rw [← Int.odd_iff_not_even] at h₂ + · rw [Int.not_even_iff_odd] at h₂ rw [negOnePow_odd _ h₂, Int.even_sub, negOnePow_eq_neg_one_iff, - Int.even_iff_not_odd, Int.even_iff_not_odd] + ← Int.not_odd_iff_even, ← Int.not_odd_iff_even] tauto @[simp] diff --git a/Mathlib/Algebra/Ring/Parity.lean b/Mathlib/Algebra/Ring/Parity.lean index ef9ba083a8241..94a1d21b3a889 100644 --- a/Mathlib/Algebra/Ring/Parity.lean +++ b/Mathlib/Algebra/Ring/Parity.lean @@ -5,7 +5,7 @@ Authors: Damiano Testa -/ import Mathlib.Data.Nat.Cast.Basic import Mathlib.Data.Nat.Cast.Commute -import Mathlib.Data.Set.Defs +import Mathlib.Data.Set.Operations import Mathlib.Logic.Function.Iterate /-! @@ -211,15 +211,20 @@ instance : DecidablePred (Odd : ℕ → Prop) := fun _ ↦ decidable_of_iff _ od 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] + +@[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] -@[simp] lemma odd_iff_not_even : Odd n ↔ ¬Even n := by rw [not_even_iff, odd_iff] +@[deprecated not_even_iff_odd (since := "2024-08-21")] +lemma odd_iff_not_even : Odd n ↔ ¬Even n := by rw [not_even_iff, odd_iff] lemma _root_.Odd.not_two_dvd_nat (h : Odd n) : ¬(2 ∣ n) := by - rwa [← even_iff_two_dvd, ← odd_iff_not_even] + rwa [← even_iff_two_dvd, not_even_iff_odd] lemma even_xor_odd (n : ℕ) : Xor' (Even n) (Odd n) := by - simp [Xor', odd_iff_not_even, Decidable.em (Even n)] + simp [Xor', ← not_even_iff_odd, Decidable.em (Even n)] lemma even_or_odd (n : ℕ) : Even n ∨ Odd n := (even_xor_odd n).or @@ -242,16 +247,16 @@ lemma mod_two_add_add_odd_mod_two (m : ℕ) {n : ℕ} (hn : Odd n) : m % 2 + (m rw [add_comm, mod_two_add_succ_mod_two] lemma even_add' : Even (m + n) ↔ (Odd m ↔ Odd n) := by - rw [even_add, even_iff_not_odd, even_iff_not_odd, not_iff_not] + rw [even_add, ← not_odd_iff_even, ← not_odd_iff_even, not_iff_not] set_option linter.deprecated false in @[simp] lemma not_even_bit1 (n : ℕ) : ¬Even (2 * n + 1) := by simp [parity_simps] lemma not_even_two_mul_add_one (n : ℕ) : ¬ Even (2 * n + 1) := - odd_iff_not_even.1 <| odd_two_mul_add_one n + not_even_iff_odd.2 <| odd_two_mul_add_one n lemma even_sub' (h : n ≤ m) : Even (m - n) ↔ (Odd m ↔ Odd n) := by - rw [even_sub h, even_iff_not_odd, even_iff_not_odd, not_iff_not] + rw [even_sub h, ← not_odd_iff_even, ← not_odd_iff_even, not_iff_not] lemma Odd.sub_odd (hm : Odd m) (hn : Odd n) : Even (m - n) := (le_total n m).elim (fun h ↦ by simp only [even_sub' h, *]) fun h ↦ by @@ -259,7 +264,7 @@ lemma Odd.sub_odd (hm : Odd m) (hn : Odd n) : Even (m - n) := alias _root_.Odd.tsub_odd := Nat.Odd.sub_odd -lemma odd_mul : Odd (m * n) ↔ Odd m ∧ Odd n := by simp [not_or, even_mul] +lemma odd_mul : Odd (m * n) ↔ Odd m ∧ Odd n := by simp [not_or, even_mul, ← not_even_iff_odd] lemma Odd.of_mul_left (h : Odd (m * n)) : Odd m := (odd_mul.mp h).1 @@ -271,20 +276,20 @@ lemma even_div : Even (m / n) ↔ m % (2 * n) / n = 0 := by rw [even_iff_two_dvd, dvd_iff_mod_eq_zero, ← Nat.mod_mul_right_div_self, mul_comm] @[parity_simps] lemma odd_add : Odd (m + n) ↔ (Odd m ↔ Even n) := by - rw [odd_iff_not_even, even_add, not_iff, odd_iff_not_even] + rw [← not_even_iff_odd, even_add, not_iff, ← not_even_iff_odd] lemma odd_add' : Odd (m + n) ↔ (Odd n ↔ Even m) := by rw [add_comm, odd_add] -lemma ne_of_odd_add (h : Odd (m + n)) : m ≠ n := fun hnot ↦ by simp [hnot] at h +lemma ne_of_odd_add (h : Odd (m + n)) : m ≠ n := by rintro rfl; simp [← not_even_iff_odd] at h @[parity_simps] lemma odd_sub (h : n ≤ m) : Odd (m - n) ↔ (Odd m ↔ Even n) := by - rw [odd_iff_not_even, even_sub h, not_iff, odd_iff_not_even] + rw [← not_even_iff_odd, even_sub h, not_iff, ← not_even_iff_odd] lemma Odd.sub_even (h : n ≤ m) (hm : Odd m) (hn : Even n) : Odd (m - n) := (odd_sub h).mpr <| iff_of_true hm hn lemma odd_sub' (h : n ≤ m) : Odd (m - n) ↔ (Odd n ↔ Even m) := by - rw [odd_iff_not_even, even_sub h, not_iff, not_iff_comm, odd_iff_not_even] + rw [← not_even_iff_odd, even_sub h, not_iff, not_iff_comm, ← not_even_iff_odd] lemma Even.sub_odd (h : n ≤ m) (hm : Even m) (hn : Odd n) : Odd (m - n) := (odd_sub' h).mpr <| iff_of_true hn hm @@ -342,16 +347,16 @@ lemma iterate_odd (hf : Involutive f) (hn : Odd n) : f^[n] = f := by rw [iterate_add, hf.iterate_two_mul, id_comp, iterate_one] lemma iterate_eq_self (hf : Involutive f) (hne : f ≠ id) : f^[n] = f ↔ Odd n := - ⟨fun H ↦ odd_iff_not_even.2 fun hn ↦ hne <| by rwa [hf.iterate_even hn, eq_comm] at H, + ⟨fun H ↦ not_even_iff_odd.1 fun hn ↦ hne <| by rwa [hf.iterate_even hn, eq_comm] at H, hf.iterate_odd⟩ lemma iterate_eq_id (hf : Involutive f) (hne : f ≠ id) : f^[n] = id ↔ Even n := - ⟨fun H ↦ even_iff_not_odd.2 fun hn ↦ hne <| by rwa [hf.iterate_odd hn] at H, hf.iterate_even⟩ + ⟨fun H ↦ not_odd_iff_even.1 fun hn ↦ hne <| by rwa [hf.iterate_odd hn] at H, hf.iterate_even⟩ end Involutive end Function lemma neg_one_pow_eq_one_iff_even {R : Type*} [Monoid R] [HasDistribNeg R] {n : ℕ} (h : (-1 : R) ≠ 1) : (-1 : R) ^ n = 1 ↔ Even n where - mp h' := of_not_not fun hn ↦ h <| (Odd.neg_one_pow <| odd_iff_not_even.mpr hn).symm.trans h' + mp h' := of_not_not fun hn ↦ h <| (not_even_iff_odd.1 hn).neg_one_pow.symm.trans h' mpr := Even.neg_one_pow diff --git a/Mathlib/Algebra/Ring/Pointwise/Set.lean b/Mathlib/Algebra/Ring/Pointwise/Set.lean new file mode 100644 index 0000000000000..4da48ed12ad44 --- /dev/null +++ b/Mathlib/Algebra/Ring/Pointwise/Set.lean @@ -0,0 +1,50 @@ +/- +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.Ring.Defs + +/-! +# Pointwise operations of sets in a ring + +This file proves properties of pointwise operations of sets in a ring. + +## Tags + +set multiplication, set addition, pointwise addition, pointwise multiplication, +pointwise subtraction +-/ + +assert_not_exists OrderedAddCommMonoid + +open Function +open scoped Pointwise + +variable {F α β γ : Type*} + +namespace Set + +/-- `Set α` has distributive negation if `α` has. -/ +protected noncomputable def hasDistribNeg [Mul α] [HasDistribNeg α] : HasDistribNeg (Set α) where + __ := Set.involutiveNeg + 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 + +section Distrib +variable [Distrib α] (s t u : Set α) + +/-! +Note that `Set α` is not a `Distrib` because `s * t + s * u` has cross terms that `s * (t + u)` +lacks. +-/ + +lemma mul_add_subset : s * (t + u) ⊆ s * t + s * u := image2_distrib_subset_left mul_add +lemma add_mul_subset : (s + t) * u ⊆ s * u + t * u := image2_distrib_subset_right add_mul + +end Distrib +end Set diff --git a/Mathlib/Algebra/Ring/Subring/Basic.lean b/Mathlib/Algebra/Ring/Subring/Basic.lean index 365272a227add..c93d933e50864 100644 --- a/Mathlib/Algebra/Ring/Subring/Basic.lean +++ b/Mathlib/Algebra/Ring/Subring/Basic.lean @@ -433,6 +433,9 @@ theorem coe_top : ((⊤ : Subring R) : Set R) = Set.univ := def topEquiv : (⊤ : Subring R) ≃+* R := Subsemiring.topEquiv +instance {R : Type*} [Ring R] [Fintype R] : Fintype (⊤ : Subring R) := + inferInstanceAs (Fintype (⊤ : Set R)) + theorem card_top (R) [Ring R] [Fintype R] : Fintype.card (⊤ : Subring R) = Fintype.card R := Fintype.card_congr topEquiv.toEquiv @@ -819,7 +822,7 @@ theorem mem_closure_iff {s : Set R} {x} : mul_mem hx hy) (zero_mem _) (fun x y hx hy => add_mem hx hy) fun x hx => neg_mem hx⟩ -/-- If all elements of `s : Set A` commute pairwise, then `closure s` is a commutative ring. -/ +/-- If all elements of `s : Set A` commute pairwise, then `closure s` is a commutative ring. -/ def closureCommRingOfComm {s : Set R} (hcomm : ∀ a ∈ s, ∀ b ∈ s, a * b = b * a) : CommRing (closure s) := { (closure s).toRing with diff --git a/Mathlib/Algebra/Ring/Subring/MulOpposite.lean b/Mathlib/Algebra/Ring/Subring/MulOpposite.lean index 0d8ca74d4eab5..77448007af326 100644 --- a/Mathlib/Algebra/Ring/Subring/MulOpposite.lean +++ b/Mathlib/Algebra/Ring/Subring/MulOpposite.lean @@ -73,17 +73,34 @@ def opEquiv : Subring R ≃o Subring Rᵐᵒᵖ where right_inv := op_unop map_rel_iff' := op_le_op_iff +theorem op_injective : (@Subring.op R _).Injective := opEquiv.injective +theorem unop_injective : (@Subring.unop R _).Injective := opEquiv.symm.injective +@[simp] theorem op_inj {S T : Subring R} : S.op = T.op ↔ S = T := opEquiv.eq_iff_eq +@[simp] theorem unop_inj {S T : Subring Rᵐᵒᵖ} : S.unop = T.unop ↔ S = T := opEquiv.symm.eq_iff_eq + @[simp] theorem op_bot : (⊥ : Subring R).op = ⊥ := opEquiv.map_bot +@[simp] +theorem op_eq_bot {S : Subring R} : S.op = ⊥ ↔ S = ⊥ := op_injective.eq_iff' op_bot + @[simp] theorem unop_bot : (⊥ : Subring Rᵐᵒᵖ).unop = ⊥ := opEquiv.symm.map_bot @[simp] -theorem op_top : (⊤ : Subring R).op = ⊤ := opEquiv.map_top +theorem unop_eq_bot {S : Subring Rᵐᵒᵖ} : S.unop = ⊥ ↔ S = ⊥ := unop_injective.eq_iff' unop_bot + +@[simp] +theorem op_top : (⊤ : Subring R).op = ⊤ := rfl @[simp] -theorem unop_top : (⊤ : Subring Rᵐᵒᵖ).unop = ⊤ := opEquiv.symm.map_top +theorem op_eq_top {S : Subring R} : S.op = ⊤ ↔ S = ⊤ := op_injective.eq_iff' op_top + +@[simp] +theorem unop_top : (⊤ : Subring Rᵐᵒᵖ).unop = ⊤ := rfl + +@[simp] +theorem unop_eq_top {S : Subring Rᵐᵒᵖ} : S.unop = ⊤ ↔ S = ⊤ := unop_injective.eq_iff' unop_top theorem op_sup (S₁ S₂ : Subring R) : (S₁ ⊔ S₂).op = S₁.op ⊔ S₂.op := opEquiv.map_sup _ _ @@ -91,10 +108,9 @@ theorem op_sup (S₁ S₂ : Subring R) : (S₁ ⊔ S₂).op = S₁.op ⊔ S₂.o theorem unop_sup (S₁ S₂ : Subring Rᵐᵒᵖ) : (S₁ ⊔ S₂).unop = S₁.unop ⊔ S₂.unop := opEquiv.symm.map_sup _ _ -theorem op_inf (S₁ S₂ : Subring R) : (S₁ ⊓ S₂).op = S₁.op ⊓ S₂.op := opEquiv.map_inf _ _ +theorem op_inf (S₁ S₂ : Subring R) : (S₁ ⊓ S₂).op = S₁.op ⊓ S₂.op := rfl -theorem unop_inf (S₁ S₂ : Subring Rᵐᵒᵖ) : (S₁ ⊓ S₂).unop = S₁.unop ⊓ S₂.unop := - opEquiv.symm.map_inf _ _ +theorem unop_inf (S₁ S₂ : Subring Rᵐᵒᵖ) : (S₁ ⊓ S₂).unop = S₁.unop ⊓ S₂.unop := rfl theorem op_sSup (S : Set (Subring R)) : (sSup S).op = sSup (.unop ⁻¹' S) := opEquiv.map_sSup_eq_sSup_symm_preimage _ @@ -124,9 +140,8 @@ theorem op_closure (s : Set R) : (closure s).op = closure (MulOpposite.unop ⁻ exact MulOpposite.unop_surjective.forall theorem unop_closure (s : Set Rᵐᵒᵖ) : (closure s).unop = closure (MulOpposite.op ⁻¹' s) := by - simp_rw [closure, unop_sInf, Set.preimage_setOf_eq, op_coe] - congr with a - exact MulOpposite.op_surjective.forall + rw [← op_inj, op_unop, op_closure] + rfl /-- Bijection between a subring `S` and its opposite. -/ @[simps!] diff --git a/Mathlib/Algebra/Ring/Subring/Pointwise.lean b/Mathlib/Algebra/Ring/Subring/Pointwise.lean index 8dd52f6efdb1b..b472910f34900 100644 --- a/Mathlib/Algebra/Ring/Subring/Pointwise.lean +++ b/Mathlib/Algebra/Ring/Subring/Pointwise.lean @@ -6,7 +6,6 @@ Authors: Eric Wieser import Mathlib.Algebra.Group.Subgroup.Pointwise import Mathlib.Algebra.Ring.Subring.Basic import Mathlib.Algebra.Ring.Subsemiring.Pointwise -import Mathlib.Data.Set.Pointwise.Basic /-! # Pointwise instances on `Subring`s diff --git a/Mathlib/Algebra/Ring/Subring/Units.lean b/Mathlib/Algebra/Ring/Subring/Units.lean index 76b3f05824db9..157cdab1d1c19 100644 --- a/Mathlib/Algebra/Ring/Subring/Units.lean +++ b/Mathlib/Algebra/Ring/Subring/Units.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Birkbeck -/ import Mathlib.Algebra.Group.Subgroup.Basic -import Mathlib.Algebra.Order.Monoid.Submonoid +import Mathlib.Algebra.Order.GroupWithZero.Submonoid import Mathlib.Algebra.Order.Ring.Defs /-! diff --git a/Mathlib/Algebra/Ring/Subsemiring/MulOpposite.lean b/Mathlib/Algebra/Ring/Subsemiring/MulOpposite.lean index d6a315451f032..ca90d5e223c98 100644 --- a/Mathlib/Algebra/Ring/Subsemiring/MulOpposite.lean +++ b/Mathlib/Algebra/Ring/Subsemiring/MulOpposite.lean @@ -76,17 +76,37 @@ def opEquiv : Subsemiring R ≃o Subsemiring Rᵐᵒᵖ where right_inv := op_unop map_rel_iff' := op_le_op_iff +theorem op_injective : (@Subsemiring.op R _).Injective := opEquiv.injective +theorem unop_injective : (@Subsemiring.unop R _).Injective := opEquiv.symm.injective + +@[simp] theorem op_inj {S T : Subsemiring R} : S.op = T.op ↔ S = T := opEquiv.eq_iff_eq + +@[simp] +theorem unop_inj {S T : Subsemiring Rᵐᵒᵖ} : S.unop = T.unop ↔ S = T := opEquiv.symm.eq_iff_eq + @[simp] theorem op_bot : (⊥ : Subsemiring R).op = ⊥ := opEquiv.map_bot +@[simp] +theorem op_eq_bot {S : Subsemiring R} : S.op = ⊥ ↔ S = ⊥ := op_injective.eq_iff' op_bot + @[simp] theorem unop_bot : (⊥ : Subsemiring Rᵐᵒᵖ).unop = ⊥ := opEquiv.symm.map_bot @[simp] -theorem op_top : (⊤ : Subsemiring R).op = ⊤ := opEquiv.map_top +theorem unop_eq_bot {S : Subsemiring Rᵐᵒᵖ} : S.unop = ⊥ ↔ S = ⊥ := unop_injective.eq_iff' unop_bot @[simp] -theorem unop_top : (⊤ : Subsemiring Rᵐᵒᵖ).unop = ⊤ := opEquiv.symm.map_top +theorem op_top : (⊤ : Subsemiring R).op = ⊤ := rfl + +@[simp] +theorem op_eq_top {S : Subsemiring R} : S.op = ⊤ ↔ S = ⊤ := op_injective.eq_iff' op_top + +@[simp] +theorem unop_top : (⊤ : Subsemiring Rᵐᵒᵖ).unop = ⊤ := rfl + +@[simp] +theorem unop_eq_top {S : Subsemiring Rᵐᵒᵖ} : S.unop = ⊤ ↔ S = ⊤ := unop_injective.eq_iff' unop_top theorem op_sup (S₁ S₂ : Subsemiring R) : (S₁ ⊔ S₂).op = S₁.op ⊔ S₂.op := opEquiv.map_sup _ _ @@ -94,10 +114,9 @@ theorem op_sup (S₁ S₂ : Subsemiring R) : (S₁ ⊔ S₂).op = S₁.op ⊔ S theorem unop_sup (S₁ S₂ : Subsemiring Rᵐᵒᵖ) : (S₁ ⊔ S₂).unop = S₁.unop ⊔ S₂.unop := opEquiv.symm.map_sup _ _ -theorem op_inf (S₁ S₂ : Subsemiring R) : (S₁ ⊓ S₂).op = S₁.op ⊓ S₂.op := opEquiv.map_inf _ _ +theorem op_inf (S₁ S₂ : Subsemiring R) : (S₁ ⊓ S₂).op = S₁.op ⊓ S₂.op := rfl -theorem unop_inf (S₁ S₂ : Subsemiring Rᵐᵒᵖ) : (S₁ ⊓ S₂).unop = S₁.unop ⊓ S₂.unop := - opEquiv.symm.map_inf _ _ +theorem unop_inf (S₁ S₂ : Subsemiring Rᵐᵒᵖ) : (S₁ ⊓ S₂).unop = S₁.unop ⊓ S₂.unop := rfl theorem op_sSup (S : Set (Subsemiring R)) : (sSup S).op = sSup (.unop ⁻¹' S) := opEquiv.map_sSup_eq_sSup_symm_preimage _ @@ -127,9 +146,8 @@ theorem op_closure (s : Set R) : (closure s).op = closure (MulOpposite.unop ⁻ exact MulOpposite.unop_surjective.forall theorem unop_closure (s : Set Rᵐᵒᵖ) : (closure s).unop = closure (MulOpposite.op ⁻¹' s) := by - simp_rw [closure, unop_sInf, Set.preimage_setOf_eq, op_coe] - congr with a - exact MulOpposite.op_surjective.forall + rw [← op_inj, op_unop, op_closure] + rfl /-- Bijection between a subsemiring `S` and its opposite. -/ @[simps!] diff --git a/Mathlib/Algebra/Ring/Subsemiring/Pointwise.lean b/Mathlib/Algebra/Ring/Subsemiring/Pointwise.lean index 842883e8a4b0b..250d388ca8b0a 100644 --- a/Mathlib/Algebra/Ring/Subsemiring/Pointwise.lean +++ b/Mathlib/Algebra/Ring/Subsemiring/Pointwise.lean @@ -6,7 +6,6 @@ Authors: Eric Wieser import Mathlib.Algebra.Group.Submonoid.Pointwise import Mathlib.Algebra.Ring.Action.Basic import Mathlib.Algebra.Ring.Subsemiring.Basic -import Mathlib.Data.Set.Pointwise.Basic /-! # Pointwise instances on `Subsemiring`s diff --git a/Mathlib/Algebra/RingQuot.lean b/Mathlib/Algebra/RingQuot.lean index f0e0f3bcd667b..65dc7e05fcf81 100644 --- a/Mathlib/Algebra/RingQuot.lean +++ b/Mathlib/Algebra/RingQuot.lean @@ -75,42 +75,42 @@ theorem Rel.smul {r : A → A → Prop} (k : S) ⦃a b : A⦄ (h : Rel r a b) : /-- `EqvGen (RingQuot.Rel r)` is a ring congruence. -/ def ringCon (r : R → R → Prop) : RingCon R where - r := EqvGen (Rel r) - iseqv := EqvGen.is_equivalence _ + r := Relation.EqvGen (Rel r) + iseqv := Relation.EqvGen.is_equivalence _ add' {a b c d} hab hcd := by induction hab generalizing c d with | rel _ _ hab => - refine (EqvGen.rel _ _ hab.add_left).trans _ _ _ ?_ + refine (Relation.EqvGen.rel _ _ hab.add_left).trans _ _ _ ?_ induction hcd with - | rel _ _ hcd => exact EqvGen.rel _ _ hcd.add_right - | refl => exact EqvGen.refl _ + | rel _ _ hcd => exact Relation.EqvGen.rel _ _ hcd.add_right + | refl => exact Relation.EqvGen.refl _ | symm _ _ _ h => exact h.symm _ _ | trans _ _ _ _ _ h h' => exact h.trans _ _ _ h' | refl => induction hcd with - | rel _ _ hcd => exact EqvGen.rel _ _ hcd.add_right - | refl => exact EqvGen.refl _ + | rel _ _ hcd => exact Relation.EqvGen.rel _ _ hcd.add_right + | refl => exact Relation.EqvGen.refl _ | symm _ _ _ h => exact h.symm _ _ | trans _ _ _ _ _ h h' => exact h.trans _ _ _ h' | symm x y _ hxy => exact (hxy hcd.symm).symm - | trans x y z _ _ h h' => exact (h hcd).trans _ _ _ (h' <| EqvGen.refl _) + | trans x y z _ _ h h' => exact (h hcd).trans _ _ _ (h' <| Relation.EqvGen.refl _) mul' {a b c d} hab hcd := by induction hab generalizing c d with | rel _ _ hab => - refine (EqvGen.rel _ _ hab.mul_left).trans _ _ _ ?_ + refine (Relation.EqvGen.rel _ _ hab.mul_left).trans _ _ _ ?_ induction hcd with - | rel _ _ hcd => exact EqvGen.rel _ _ hcd.mul_right - | refl => exact EqvGen.refl _ + | rel _ _ hcd => exact Relation.EqvGen.rel _ _ hcd.mul_right + | refl => exact Relation.EqvGen.refl _ | symm _ _ _ h => exact h.symm _ _ | trans _ _ _ _ _ h h' => exact h.trans _ _ _ h' | refl => induction hcd with - | rel _ _ hcd => exact EqvGen.rel _ _ hcd.mul_right - | refl => exact EqvGen.refl _ + | rel _ _ hcd => exact Relation.EqvGen.rel _ _ hcd.mul_right + | refl => exact Relation.EqvGen.refl _ | symm _ _ _ h => exact h.symm _ _ | trans _ _ _ _ _ h h' => exact h.trans _ _ _ h' | symm x y _ hxy => exact (hxy hcd.symm).symm - | trans x y z _ _ h h' => exact (h hcd).trans _ _ _ (h' <| EqvGen.refl _) + | trans x y z _ _ h h' => exact (h hcd).trans _ _ _ (h' <| Relation.EqvGen.refl _) -theorem eqvGen_rel_eq (r : R → R → Prop) : EqvGen (Rel r) = RingConGen.Rel r := by +theorem eqvGen_rel_eq (r : R → R → Prop) : Relation.EqvGen (Rel r) = RingConGen.Rel r := by ext x₁ x₂ constructor · intro h @@ -125,7 +125,7 @@ theorem eqvGen_rel_eq (r : R → R → Prop) : EqvGen (Rel r) = RingConGen.Rel r | trans => exact RingConGen.Rel.trans ‹_› ‹_› · intro h induction h with - | of => exact EqvGen.rel _ _ (Rel.of ‹_›) + | of => exact Relation.EqvGen.rel _ _ (Rel.of ‹_›) | refl => exact (RingQuot.ringCon r).refl _ | symm => exact (RingQuot.ringCon r).symm ‹_› | trans => exact (RingQuot.ringCon r).trans ‹_› ‹_› diff --git a/Mathlib/Algebra/SMulWithZero.lean b/Mathlib/Algebra/SMulWithZero.lean index 3ef4bb96b5b9f..1eba1392560bd 100644 --- a/Mathlib/Algebra/SMulWithZero.lean +++ b/Mathlib/Algebra/SMulWithZero.lean @@ -196,7 +196,7 @@ theorem smul_inv₀ [SMulCommClass α β β] [IsScalarTower α β β] (c : α) ( obtain rfl | hx := eq_or_ne x 0 · simp only [inv_zero, smul_zero] · refine inv_eq_of_mul_eq_one_left ?_ - rw [smul_mul_smul, inv_mul_cancel₀ hc, inv_mul_cancel₀ hx, one_smul] + rw [smul_mul_smul_comm, inv_mul_cancel₀ hc, inv_mul_cancel₀ hx, one_smul] end GroupWithZero diff --git a/Mathlib/Algebra/Star/Basic.lean b/Mathlib/Algebra/Star/Basic.lean index c592e1abb4297..35276edb14891 100644 --- a/Mathlib/Algebra/Star/Basic.lean +++ b/Mathlib/Algebra/Star/Basic.lean @@ -111,7 +111,7 @@ theorem star_eq_iff_star_eq [InvolutiveStar R] {r s : R} : star r = s ↔ star s /-- Typeclass for a trivial star operation. This is mostly meant for `ℝ`. -/ class TrivialStar (R : Type u) [Star R] : Prop where - /-- Condition that star is trivial-/ + /-- Condition that star is trivial -/ star_trivial : ∀ r : R, star r = r export TrivialStar (star_trivial) @@ -221,7 +221,7 @@ theorem star_id_of_comm {R : Type*} [CommSemiring R] {x : R} : star x = x := end /-- A `*`-additive monoid `R` is an additive monoid with an involutive `star` operation which -preserves addition. -/ +preserves addition. -/ class StarAddMonoid (R : Type u) [AddMonoid R] extends InvolutiveStar R where /-- `star` commutes with addition -/ star_add : ∀ r s : R, star (r + s) = star r + star s @@ -261,16 +261,16 @@ theorem star_sub [AddGroup R] [StarAddMonoid R] (r s : R) : star (r - s) = star (starAddEquiv : R ≃+ R).map_sub _ _ @[simp] -theorem star_nsmul [AddMonoid R] [StarAddMonoid R] (x : R) (n : ℕ) : star (n • x) = n • star x := +theorem star_nsmul [AddMonoid R] [StarAddMonoid R] (n : ℕ) (x : R) : star (n • x) = n • star x := (starAddEquiv : R ≃+ R).toAddMonoidHom.map_nsmul _ _ @[simp] -theorem star_zsmul [AddGroup R] [StarAddMonoid R] (x : R) (n : ℤ) : star (n • x) = n • star x := +theorem star_zsmul [AddGroup R] [StarAddMonoid R] (n : ℤ) (x : R) : star (n • x) = n • star x := (starAddEquiv : R ≃+ R).toAddMonoidHom.map_zsmul _ _ /-- A `*`-ring `R` is a non-unital, non-associative (semi)ring with an involutive `star` operation which is additive which makes `R` with its multiplicative structure into a `*`-multiplication -(i.e. `star (r * s) = star s * star r`). -/ +(i.e. `star (r * s) = star s * star r`). -/ class StarRing (R : Type u) [NonUnitalNonAssocSemiring R] extends StarMul R where /-- `star` commutes with addition -/ star_add : ∀ r s : R, star (r + s) = star r + star s @@ -415,13 +415,16 @@ attribute [simp] star_smul instance StarMul.toStarModule [CommMonoid R] [StarMul R] : StarModule R R := ⟨star_mul'⟩ -instance StarAddMonoid.toStarModuleNat {α} [AddCommMonoid α] [StarAddMonoid α] : StarModule ℕ α := - ⟨fun n a ↦ by rw [star_nsmul, star_trivial n]⟩ +instance StarAddMonoid.toStarModuleNat {α} [AddCommMonoid α] [StarAddMonoid α] : + StarModule ℕ α where star_smul := star_nsmul + +instance StarAddMonoid.toStarModuleInt {α} [AddCommGroup α] [StarAddMonoid α] : StarModule ℤ α where + star_smul := star_zsmul namespace RingHomInvPair /-- Instance needed to define star-linear maps over a commutative star ring -(ex: conjugate-linear maps when R = ℂ). -/ +(ex: conjugate-linear maps when R = ℂ). -/ instance [CommSemiring R] [StarRing R] : RingHomInvPair (starRingEnd R) (starRingEnd R) := ⟨RingHom.ext star_star, RingHom.ext star_star⟩ diff --git a/Mathlib/Algebra/Star/CHSH.lean b/Mathlib/Algebra/Star/CHSH.lean index 72b30f5ea9329..6d92b8ca15050 100644 --- a/Mathlib/Algebra/Star/CHSH.lean +++ b/Mathlib/Algebra/Star/CHSH.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Morrison -/ import Mathlib.Algebra.CharP.Invertible -import Mathlib.Algebra.Star.Order +import Mathlib.Algebra.Order.Star.Basic import Mathlib.Data.Real.Sqrt import Mathlib.Tactic.Polyrith diff --git a/Mathlib/Algebra/Star/Conjneg.lean b/Mathlib/Algebra/Star/Conjneg.lean new file mode 100644 index 0000000000000..1fb96695c6371 --- /dev/null +++ b/Mathlib/Algebra/Star/Conjneg.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.BigOperators.Pi +import Mathlib.Algebra.Group.Pointwise.Set +import Mathlib.Algebra.Star.Pi + +/-! +# Conjugation-negation operator + +This file defines the conjugation-negation operator, useful in Fourier analysis. + +The way this operator enters the picture is that the adjoint of convolution with a function `f` is +convolution with `conjneg f`. +-/ + +open Function +open scoped ComplexConjugate + +variable {ι G R : Type*} [AddGroup G] + +section CommSemiring +variable [CommSemiring R] [StarRing R] {f g : G → R} + +/-- Conjugation-negation. Sends `f` to `fun x ↦ conj (f (-x))`. -/ +def conjneg (f : G → R) : G → R := conj fun x ↦ f (-x) + +@[simp] lemma conjneg_apply (f : G → R) (x : G) : conjneg f x = conj (f (-x)) := rfl +@[simp] lemma conjneg_conjneg (f : G → R) : conjneg (conjneg f) = f := by ext; simp + +lemma conjneg_involutive : Involutive (conjneg : (G → R) → G → R) := conjneg_conjneg +lemma conjneg_bijective : Bijective (conjneg : (G → R) → G → R) := conjneg_involutive.bijective +lemma conjneg_injective : Injective (conjneg : (G → R) → G → R) := conjneg_involutive.injective +lemma conjneg_surjective : Surjective (conjneg : (G → R) → G → R) := conjneg_involutive.surjective + +@[simp] lemma conjneg_inj : conjneg f = conjneg g ↔ f = g := conjneg_injective.eq_iff +lemma conjneg_ne_conjneg : conjneg f ≠ conjneg g ↔ f ≠ g := conjneg_injective.ne_iff + +@[simp] lemma conjneg_conj (f : G → R) : conjneg (conj f) = conj (conjneg f) := rfl + +@[simp] lemma conjneg_zero : conjneg (0 : G → R) = 0 := by ext; simp +@[simp] lemma conjneg_one : conjneg (1 : G → R) = 1 := by ext; simp +@[simp] lemma conjneg_add (f g : G → R) : conjneg (f + g) = conjneg f + conjneg g := by ext; simp +@[simp] lemma conjneg_mul (f g : G → R) : conjneg (f * g) = conjneg f * conjneg g := by ext; simp + +@[simp] lemma conjneg_sum (s : Finset ι) (f : ι → G → R) : + conjneg (∑ i ∈ s, f i) = ∑ i ∈ s, conjneg (f i) := by ext; simp + +@[simp] lemma conjneg_prod (s : Finset ι) (f : ι → G → R) : + conjneg (∏ i ∈ s, f i) = ∏ i ∈ s, conjneg (f i) := by ext; simp + +@[simp] lemma conjneg_eq_zero : conjneg f = 0 ↔ f = 0 := by + rw [← conjneg_inj, conjneg_conjneg, conjneg_zero] + +@[simp] lemma conjneg_eq_one : conjneg f = 1 ↔ f = 1 := by + rw [← conjneg_inj, conjneg_conjneg, conjneg_one] + +lemma conjneg_ne_zero : conjneg f ≠ 0 ↔ f ≠ 0 := conjneg_eq_zero.not +lemma conjneg_ne_one : conjneg f ≠ 1 ↔ f ≠ 1 := conjneg_eq_one.not + +lemma sum_conjneg [Fintype G] (f : G → R) : ∑ a, conjneg f a = ∑ a, conj (f a) := + Fintype.sum_equiv (Equiv.neg _) _ _ fun _ ↦ rfl + +@[simp] lemma support_conjneg (f : G → R) : support (conjneg f) = -support f := by + ext; simp [starRingEnd_apply] + +/-- `conjneg` bundled as a ring homomorphism. -/ +@[simps] def conjnegRingHom : (G → R) →+* (G → R) where + toFun := conjneg + map_zero' := conjneg_zero + map_one' := conjneg_one + map_add' := conjneg_add + map_mul' := conjneg_mul + +end CommSemiring + +section CommRing +variable [CommRing R] [StarRing R] + +@[simp] lemma conjneg_sub (f g : G → R) : conjneg (f - g) = conjneg f - conjneg g := by ext; simp +@[simp] lemma conjneg_neg (f : G → R) : conjneg (-f) = -conjneg f := by ext; simp + +end CommRing diff --git a/Mathlib/Algebra/Star/Pointwise.lean b/Mathlib/Algebra/Star/Pointwise.lean index 7594743c491d5..58c6df130b0b7 100644 --- a/Mathlib/Algebra/Star/Pointwise.lean +++ b/Mathlib/Algebra/Star/Pointwise.lean @@ -3,9 +3,9 @@ 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.Star.Basic import Mathlib.Data.Set.Finite -import Mathlib.Data.Set.Pointwise.Basic /-! # Pointwise star operation on sets diff --git a/Mathlib/Algebra/Star/SelfAdjoint.lean b/Mathlib/Algebra/Star/SelfAdjoint.lean index f123298542131..a7886d8e0bfd2 100644 --- a/Mathlib/Algebra/Star/SelfAdjoint.lean +++ b/Mathlib/Algebra/Star/SelfAdjoint.lean @@ -156,6 +156,10 @@ theorem conjugate {x : R} (hx : IsSelfAdjoint x) (z : R) : IsSelfAdjoint (z * x theorem conjugate' {x : R} (hx : IsSelfAdjoint x) (z : R) : IsSelfAdjoint (star z * x * z) := by simp only [isSelfAdjoint_iff, star_mul, star_star, mul_assoc, hx.star_eq] +@[aesop 90% apply] +theorem conjugate_self {x : R} (hx : IsSelfAdjoint x) {z : R} (hz : IsSelfAdjoint z) : + IsSelfAdjoint (z * x * z) := by nth_rewrite 2 [← hz]; exact conjugate hx z + @[aesop 10% apply] theorem isStarNormal {x : R} (hx : IsSelfAdjoint x) : IsStarNormal x := ⟨by simp only [Commute, SemiconjBy, hx.star_eq]⟩ diff --git a/Mathlib/Algebra/Star/StarAlgHom.lean b/Mathlib/Algebra/Star/StarAlgHom.lean index b8748b3c4d8b7..53f42e18c47a9 100644 --- a/Mathlib/Algebra/Star/StarAlgHom.lean +++ b/Mathlib/Algebra/Star/StarAlgHom.lean @@ -263,7 +263,7 @@ variable (R : Type*) {S A B : Type*} [Monoid R] [Monoid S] [Star A] [Star B] [IsScalarTower R S A] [IsScalarTower R S B] /-- If a monoid `R` acts on another monoid `S`, then a non-unital star algebra homomorphism -over `S` can be viewed as a non-unital star algebra homomorphism over `R`. -/ +over `S` can be viewed as a non-unital star algebra homomorphism over `R`. -/ def restrictScalars (f : A →⋆ₙₐ[S] B) : A →⋆ₙₐ[R] B := { (f : A →ₙₐ[S] B).restrictScalars R with map_star' := map_star f } @@ -807,9 +807,7 @@ theorem invFun_eq_symm {e : A ≃⋆ₐ[R] B} : EquivLike.inv e = e.symm := rfl @[simp] -theorem symm_symm (e : A ≃⋆ₐ[R] B) : e.symm.symm = e := by - ext - rfl +theorem symm_symm (e : A ≃⋆ₐ[R] B) : e.symm.symm = e := rfl theorem symm_bijective : Function.Bijective (symm : (A ≃⋆ₐ[R] B) → B ≃⋆ₐ[R] A) := Function.bijective_iff_has_inverse.mpr ⟨_, symm_symm, symm_symm⟩ @@ -821,7 +819,7 @@ theorem coe_mk (e h₁ h₂) : ⇑(⟨e, h₁, h₂⟩ : A ≃⋆ₐ[R] B) = e : theorem mk_coe (e : A ≃⋆ₐ[R] B) (e' h₁ h₂ h₃ h₄ h₅ h₆) : (⟨⟨⟨e, e', h₁, h₂⟩, h₃, h₄⟩, h₅, h₆⟩ : A ≃⋆ₐ[R] B) = e := ext fun _ => rfl -/-- Auxilliary definition to avoid looping in `dsimp` with `StarAlgEquiv.symm_mk`. -/ +/-- Auxiliary definition to avoid looping in `dsimp` with `StarAlgEquiv.symm_mk`. -/ protected def symm_mk.aux (f f') (h₁ h₂ h₃ h₄ h₅ h₆) := (⟨⟨⟨f, f', h₁, h₂⟩, h₃, h₄⟩, h₅, h₆⟩ : A ≃⋆ₐ[R] B).symm diff --git a/Mathlib/Algebra/Star/StarRingHom.lean b/Mathlib/Algebra/Star/StarRingHom.lean index cdf64f59320dc..8d5fac3954d7d 100644 --- a/Mathlib/Algebra/Star/StarRingHom.lean +++ b/Mathlib/Algebra/Star/StarRingHom.lean @@ -354,9 +354,7 @@ theorem invFun_eq_symm {e : A ≃⋆+* B} : EquivLike.inv e = e.symm := rfl @[simp] -theorem symm_symm (e : A ≃⋆+* B) : e.symm.symm = e := by - ext - rfl +theorem symm_symm (e : A ≃⋆+* B) : e.symm.symm = e := rfl theorem symm_bijective : Function.Bijective (symm : (A ≃⋆+* B) → B ≃⋆+* A) := Function.bijective_iff_has_inverse.mpr ⟨_, symm_symm, symm_symm⟩ @@ -367,7 +365,7 @@ theorem coe_mk (e h₁) : ⇑(⟨e, h₁⟩ : A ≃⋆+* B) = e := rfl theorem mk_coe (e : A ≃⋆+* B) (e' h₁ h₂ h₃ h₄ h₅) : (⟨⟨⟨e, e', h₁, h₂⟩, h₃, h₄⟩, h₅⟩ : A ≃⋆+* B) = e := ext fun _ => rfl -/-- Auxilliary definition to avoid looping in `dsimp` with `StarRingEquiv.symm_mk`. -/ +/-- Auxiliary definition to avoid looping in `dsimp` with `StarRingEquiv.symm_mk`. -/ protected def symm_mk.aux (f f') (h₁ h₂ h₃ h₄ h₅) := (⟨⟨⟨f, f', h₁, h₂⟩, h₃, h₄⟩, h₅⟩ : A ≃⋆+* B).symm diff --git a/Mathlib/Algebra/TrivSqZeroExt.lean b/Mathlib/Algebra/TrivSqZeroExt.lean index ed6277acc897f..0e976107f9917 100644 --- a/Mathlib/Algebra/TrivSqZeroExt.lean +++ b/Mathlib/Algebra/TrivSqZeroExt.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Kenny Lau, Eric Wieser -/ import Mathlib.Algebra.Algebra.Defs -import Mathlib.GroupTheory.GroupAction.BigOperators +import Mathlib.Algebra.BigOperators.GroupWithZero.Action import Mathlib.LinearAlgebra.Prod /-! @@ -624,7 +624,7 @@ instance monoid [Monoid R] [AddMonoid M] [DistribMulAction R M] [DistribMulActio · simp [List.range_succ] rw [List.sum_range_succ'] simp only [pow_zero, op_one, Nat.sub_zero, one_smul, Nat.succ_sub_succ_eq_sub, fst_pow, - Nat.pred_succ, List.smul_sum, List.map_map, Function.comp] + Nat.pred_succ, List.smul_sum, List.map_map, Function.comp_def] simp_rw [← smul_comm (_ : R) (_ : Rᵐᵒᵖ), smul_smul, pow_succ] rfl) } @@ -643,12 +643,13 @@ theorem snd_list_prod [Semiring R] [AddCommMonoid M] [Module R M] [Module Rᵐ l.prod.snd = (l.enum.map fun x : ℕ × tsze R M => ((l.map fst).take x.1).prod •> x.snd.snd <• ((l.map fst).drop x.1.succ).prod).sum := by - induction' l with x xs ih - · simp - · rw [List.enum_cons, ← List.map_fst_add_enum_eq_enumFrom] - simp_rw [List.map_cons, List.map_map, Function.comp, Prod.map_snd, Prod.map_fst, id, - List.take_zero, List.take_cons, List.prod_nil, List.prod_cons, snd_mul, one_smul, List.drop, - mul_smul, List.sum_cons, fst_list_prod, ih, List.smul_sum, List.map_map, + induction l with + | nil => simp + | cons x xs ih => + rw [List.enum_cons, ← List.map_fst_add_enum_eq_enumFrom] + simp_rw [List.map_cons, List.map_map, Function.comp_def, Prod.map_snd, Prod.map_fst, id, + List.take_zero, List.take_succ_cons, List.prod_nil, List.prod_cons, snd_mul, one_smul, + List.drop, mul_smul, List.sum_cons, fst_list_prod, ih, List.smul_sum, List.map_map, ← smul_comm (_ : R) (_ : Rᵐᵒᵖ)] exact add_comm _ _ @@ -872,7 +873,7 @@ def lift (f : R →ₐ[S] A) (g : M →ₗ[S] A) (TrivSqZeroExt.ind fun r₁ m₁ => TrivSqZeroExt.ind fun r₂ m₂ => by dsimp - simp only [add_zero, zero_add, add_mul, mul_add, smul_mul_smul, hg, smul_zero, + simp only [add_zero, zero_add, add_mul, mul_add, smul_mul_smul_comm, hg, smul_zero, op_smul_eq_smul] rw [← map_mul, LinearMap.map_add, add_comm (g _), add_assoc, hfg, hgf]) diff --git a/Mathlib/AlgebraicGeometry/AffineScheme.lean b/Mathlib/AlgebraicGeometry/AffineScheme.lean index fd1b6a8831da4..6476a026dec9c 100644 --- a/Mathlib/AlgebraicGeometry/AffineScheme.lean +++ b/Mathlib/AlgebraicGeometry/AffineScheme.lean @@ -31,7 +31,7 @@ We also define predicates about affine schemes and affine open sets. -/ --- Explicit universe annotations were used in this file to improve perfomance #12737 +-- Explicit universe annotations were used in this file to improve performance #12737 noncomputable section @@ -417,7 +417,7 @@ theorem exists_basicOpen_le {V : X.Opens} (x : V) (h : ↑x ∈ U) : ∃ f : Γ(X, U), X.basicOpen f ≤ V ∧ ↑x ∈ X.basicOpen f := by have : IsAffine _ := hU obtain ⟨_, ⟨_, ⟨r, rfl⟩, rfl⟩, h₁, h₂⟩ := - (isBasis_basicOpen U).exists_subset_of_mem_open (x.2 : ⟨x, h⟩ ∈ _) + (isBasis_basicOpen U).exists_subset_of_mem_open (x.2 : (⟨x, h⟩ : U) ∈ _) ((Opens.map U.inclusion).obj V).isOpen have : U.ι ''ᵁ (U.toScheme.basicOpen r) = @@ -578,7 +578,7 @@ def _root_.AlgebraicGeometry.Scheme.affineBasicOpen include hU in /-- In an affine open set `U`, a family of basic open covers `U` iff the sections span `Γ(X, U)`. -See `iSup_basicOpen_of_span_eq_top` for the inverse direction without the affine-ness assuption. +See `iSup_basicOpen_of_span_eq_top` for the inverse direction without the affine-ness assumption. -/ theorem basicOpen_union_eq_self_iff (s : Set Γ(X, U)) : ⨆ f : s, X.basicOpen (f : Γ(X, U)) = U ↔ Ideal.span s = ⊤ := by diff --git a/Mathlib/AlgebraicGeometry/Cover/Open.lean b/Mathlib/AlgebraicGeometry/Cover/Open.lean index 20acd2442916a..959dc19b68c73 100644 --- a/Mathlib/AlgebraicGeometry/Cover/Open.lean +++ b/Mathlib/AlgebraicGeometry/Cover/Open.lean @@ -92,7 +92,7 @@ theorem OpenCover.iSup_opensRange {X : Scheme.{u}} (𝒰 : X.OpenCover) : Opens.ext <| by rw [Opens.coe_iSup]; exact 𝒰.iUnion_range /-- Given an open cover `{ Uᵢ }` of `X`, and for each `Uᵢ` an open cover, we may combine these -open covers to form an open cover of `X`. -/ +open covers to form an open cover of `X`. -/ @[simps! J obj map] def OpenCover.bind (f : ∀ x : 𝒰.J, OpenCover (𝒰.obj x)) : OpenCover X where J := Σ i : 𝒰.J, (f i).J diff --git a/Mathlib/AlgebraicGeometry/EllipticCurve/Group.lean b/Mathlib/AlgebraicGeometry/EllipticCurve/Group.lean index c87f5ce1c0540..cbb5edf60ed85 100644 --- a/Mathlib/AlgebraicGeometry/EllipticCurve/Group.lean +++ b/Mathlib/AlgebraicGeometry/EllipticCurve/Group.lean @@ -179,8 +179,9 @@ lemma smul_basis_mul_Y (p q : R[X]) : (p • (1 : W.CoordinateRing) + q • mk W /-- The ring homomorphism `R[W] →+* S[W.map f]` induced by a ring homomorphism `f : R →+* S`. -/ noncomputable def map : W.CoordinateRing →+* (W.map f).toAffine.CoordinateRing := - AdjoinRoot.lift ((AdjoinRoot.of _).comp <| mapRingHom f) _ <| by - rw [← eval₂_map, ← map_polynomial, AdjoinRoot.eval₂_root] + AdjoinRoot.lift ((AdjoinRoot.of _).comp <| mapRingHom f) + ((AdjoinRoot.root (WeierstrassCurve.map W f).toAffine.polynomial)) <| by + rw [← eval₂_map, ← map_polynomial, AdjoinRoot.eval₂_root] lemma map_mk (x : R[X][Y]) : map W f (mk W x) = mk (W.map f) (x.map <| mapRingHom f) := by rw [map, AdjoinRoot.lift_mk, ← eval₂_map] diff --git a/Mathlib/AlgebraicGeometry/EllipticCurve/Jacobian.lean b/Mathlib/AlgebraicGeometry/EllipticCurve/Jacobian.lean index 6042ae7f510d6..b3f2eea5ac125 100644 --- a/Mathlib/AlgebraicGeometry/EllipticCurve/Jacobian.lean +++ b/Mathlib/AlgebraicGeometry/EllipticCurve/Jacobian.lean @@ -359,8 +359,8 @@ variable (W') in /-- The proposition that a point representative $(x, y, z)$ in `W'` is nonsingular. In other words, either $W_X(x, y, z) \ne 0$, $W_Y(x, y, z) \ne 0$, or $W_Z(x, y, z) \ne 0$. -Note that this definition is only mathematically accurate for fields. -TODO: generalise this definition to be mathematically accurate for a larger class of rings. -/ +Note that this definition is only mathematically accurate for fields. -/ +-- TODO: generalise this definition to be mathematically accurate for a larger class of rings. def Nonsingular (P : Fin 3 → R) : Prop := W'.Equation P ∧ (eval P W'.polynomialX ≠ 0 ∨ eval P W'.polynomialY ≠ 0 ∨ eval P W'.polynomialZ ≠ 0) @@ -1619,3 +1619,5 @@ end WeierstrassCurve.Jacobian abbrev WeierstrassCurve.Affine.Point.toJacobian {R : Type u} [CommRing R] [Nontrivial R] {W : Affine R} (P : W.Point) : W.toJacobian.Point := Jacobian.Point.fromAffine P + +set_option linter.style.longFile 1700 diff --git a/Mathlib/AlgebraicGeometry/EllipticCurve/Projective.lean b/Mathlib/AlgebraicGeometry/EllipticCurve/Projective.lean index f1314e4735540..e010653a6a29e 100644 --- a/Mathlib/AlgebraicGeometry/EllipticCurve/Projective.lean +++ b/Mathlib/AlgebraicGeometry/EllipticCurve/Projective.lean @@ -3,9 +3,10 @@ Copyright (c) 2023 David Kurniadi Angdinata. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: David Kurniadi Angdinata -/ -import Mathlib.AlgebraicGeometry.EllipticCurve.Affine import Mathlib.Algebra.MvPolynomial.CommRing import Mathlib.Algebra.MvPolynomial.PDeriv +import Mathlib.AlgebraicGeometry.EllipticCurve.Affine +import Mathlib.Data.Fin.Tuple.Reflection /-! # Projective coordinates for Weierstrass curves @@ -18,7 +19,7 @@ condition. Let `W` be a Weierstrass curve over a field `F`. A point on the projective plane is an equivalence class of triples $[x:y:z]$ with coordinates in `F` such that $(x, y, z) \sim (x', y', z')$ precisely -if there is some unit $u$ of `F` such that $(x, y, z) = (ux', uy', uz')$, with an extra condition +if there is some unit `u` of `F` such that $(x, y, z) = (ux', uy', uz')$, with an extra condition that $(x, y, z) \ne (0, 0, 0)$. As described in `Mathlib.AlgebraicGeometry.EllipticCurve.Affine`, a rational point is a point on the projective plane satisfying a homogeneous Weierstrass equation, and being nonsingular means the partial derivatives $W_X(X, Y, Z)$, $W_Y(X, Y, Z)$, and $W_Z(X, Y, Z)$ @@ -42,11 +43,11 @@ given by a tuple consisting of $[x:y:z]$ and the nonsingular condition on any re A point representative is implemented as a term `P` of type `Fin 3 → R`, which allows for the vector notation `![x, y, z]`. However, `P` is not definitionally equivalent to the expanded vector -`![P x, P y, P z]`, so the auxiliary lemma `fin3_def` can be used to convert between the two forms. -The equivalence of two point representatives `P` and `Q` is implemented as an equivalence of orbits -of the action of `Rˣ`, or equivalently that there is some unit `u` of `R` such that `P = u • Q`. -However, `u • Q` is again not definitionally equal to `![u * Q x, u * Q y, u * Q z]`, so the -auxiliary lemmas `smul_fin3` and `smul_fin3_ext` can be used to convert between the two forms. +`![P x, P y, P z]`, so the lemmas `fin3_def` and `fin3_def_ext` can be used to convert between the +two forms. The equivalence of two point representatives `P` and `Q` is implemented as an equivalence +of orbits of the action of `Rˣ`, or equivalently that there is some unit `u` of `R` such that +`P = u • Q`. However, `u • Q` is not definitionally equal to `![u * Q x, u * Q y, u * Q z]`, so the +lemmas `smul_fin3` and `smul_fin3_ext` can be used to convert between the two forms. ## References @@ -57,23 +58,27 @@ auxiliary lemmas `smul_fin3` and `smul_fin3_ext` can be used to convert between elliptic curve, rational point, projective coordinates -/ -local notation "x" => 0 +local notation3 "x" => (0 : Fin 3) -local notation "y" => 1 +local notation3 "y" => (1 : Fin 3) -local notation "z" => 2 +local notation3 "z" => (2 : Fin 3) local macro "matrix_simp" : tactic => `(tactic| simp only [Matrix.head_cons, Matrix.tail_cons, Matrix.smul_empty, Matrix.smul_cons, Matrix.cons_val_zero, Matrix.cons_val_one, Matrix.cons_val_two]) -universe u +universe u v /-! ## Weierstrass curves -/ /-- An abbreviation for a Weierstrass curve in projective coordinates. -/ -abbrev WeierstrassCurve.Projective := - WeierstrassCurve +abbrev WeierstrassCurve.Projective (R : Type u) : Type u := + WeierstrassCurve R + +/-- The coercion to a Weierstrass curve in projective coordinates. -/ +abbrev WeierstrassCurve.toProjective {R : Type u} (W : WeierstrassCurve R) : Projective R := + W namespace WeierstrassCurve.Projective @@ -85,231 +90,360 @@ local macro "eval_simp" : tactic => local macro "pderiv_simp" : tactic => `(tactic| simp only [map_ofNat, map_neg, map_add, map_sub, map_mul, pderiv_mul, pderiv_pow, pderiv_C, pderiv_X_self, pderiv_X_of_ne one_ne_zero, pderiv_X_of_ne one_ne_zero.symm, - pderiv_X_of_ne (by decide : (2 : Fin 3) ≠ 0), pderiv_X_of_ne (by decide : (0 : Fin 3) ≠ 2), - pderiv_X_of_ne (by decide : (2 : Fin 3) ≠ 1), pderiv_X_of_ne (by decide : (1 : Fin 3) ≠ 2)]) + pderiv_X_of_ne (by decide : z ≠ x), pderiv_X_of_ne (by decide : x ≠ z), + pderiv_X_of_ne (by decide : z ≠ y), pderiv_X_of_ne (by decide : y ≠ z)]) + +variable {R : Type u} {W' : Projective R} {F : Type v} [Field F] {W : Projective F} -variable {R : Type u} [CommRing R] (W : Projective R) +section Projective -lemma fin3_def {R : Type u} (P : Fin 3 → R) : P = ![P x, P y, P z] := by +/-! ### Projective coordinates -/ + +lemma fin3_def (P : Fin 3 → R) : ![P x, P y, P z] = P := by ext n; fin_cases n <;> rfl -lemma smul_fin3 {R : Type u} [CommRing R] (P : Fin 3 → R) (u : Rˣ) : - u • P = ![u * P x, u * P y, u * P z] := by - rw [fin3_def P] - matrix_simp - simp only [Units.smul_def, smul_eq_mul] +lemma fin3_def_ext (X Y Z : R) : ![X, Y, Z] x = X ∧ ![X, Y, Z] y = Y ∧ ![X, Y, Z] z = Z := + ⟨rfl, rfl, rfl⟩ + +lemma comp_fin3 {S} (f : R → S) (X Y Z : R) : f ∘ ![X, Y, Z] = ![f X, f Y, f Z] := + (FinVec.map_eq _ _).symm + +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_ext {R : Type u} [CommRing R] (P : Fin 3 → R) (u : Rˣ) : - (u • P) x = u * P x ∧ (u • P) y = u * P y ∧ (u • P) z = u * P z := by - refine ⟨?_, ?_, ?_⟩ <;> simp only [Units.smul_def, Pi.smul_apply, smul_eq_mul] +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 := + ⟨rfl, rfl, rfl⟩ /-- The equivalence setoid for a point representative. -/ scoped instance instSetoidPoint : Setoid <| Fin 3 → R := MulAction.orbitRel Rˣ <| Fin 3 → R +variable (R) in /-- The equivalence class of a point representative. -/ -abbrev PointClass (R : Type u) [CommRing R] : Type u := +abbrev PointClass : Type u := MulAction.orbitRel.Quotient Rˣ <| Fin 3 → R +lemma smul_equiv (P : Fin 3 → R) {u : R} (hu : IsUnit u) : u • P ≈ P := + ⟨hu.unit, rfl⟩ + +@[simp] +lemma smul_eq (P : Fin 3 → R) {u : R} (hu : IsUnit u) : (⟦u • P⟧ : PointClass R) = ⟦P⟧ := + Quotient.eq.mpr <| smul_equiv P hu + +variable (W') in /-- The coercion to a Weierstrass curve in affine coordinates. -/ abbrev toAffine : Affine R := - W + W' + +lemma equiv_iff_eq_of_Z_eq' {P Q : Fin 3 → R} (hz : P z = Q z) (mem : Q z ∈ nonZeroDivisors R) : + P ≈ Q ↔ P = Q := by + refine ⟨?_, by rintro rfl; exact Setoid.refl _⟩ + rintro ⟨u, rfl⟩ + rw [← one_mul (Q z)] at hz + simp_rw [Units.smul_def, (mul_cancel_right_mem_nonZeroDivisors mem).mp hz, one_smul] + +lemma equiv_iff_eq_of_Z_eq [NoZeroDivisors R] {P Q : Fin 3 → R} (hz : P z = Q z) (hQz : Q z ≠ 0) : + P ≈ Q ↔ P = Q := + equiv_iff_eq_of_Z_eq' hz (mem_nonZeroDivisors_of_ne_zero hQz) + +lemma Z_eq_zero_of_equiv {P Q : Fin 3 → R} (h : P ≈ Q) : P z = 0 ↔ Q z = 0 := by + rcases h with ⟨_, rfl⟩ + simp only [Units.smul_def, smul_fin3_ext, Units.mul_right_eq_zero] + +lemma X_eq_of_equiv {P Q : Fin 3 → R} (h : P ≈ Q) : P x * Q z = Q x * P z := by + rcases h with ⟨u, rfl⟩ + simp only [Units.smul_def, smul_fin3_ext] + ring1 + +lemma Y_eq_of_equiv {P Q : Fin 3 → R} (h : P ≈ Q) : P y * Q z = Q y * P z := by + rcases h with ⟨u, rfl⟩ + simp only [Units.smul_def, smul_fin3_ext] + ring1 + +lemma not_equiv_of_Z_eq_zero_left {P Q : Fin 3 → R} (hPz : P z = 0) (hQz : Q z ≠ 0) : ¬P ≈ Q := + fun h => hQz <| (Z_eq_zero_of_equiv h).mp hPz + +lemma not_equiv_of_Z_eq_zero_right {P Q : Fin 3 → R} (hPz : P z ≠ 0) (hQz : Q z = 0) : ¬P ≈ Q := + fun h => hPz <| (Z_eq_zero_of_equiv h).mpr hQz + +lemma not_equiv_of_X_ne {P Q : Fin 3 → R} (hx : P x * Q z ≠ Q x * P z) : ¬P ≈ Q := + hx.comp X_eq_of_equiv + +lemma not_equiv_of_Y_ne {P Q : Fin 3 → R} (hy : P y * Q z ≠ Q y * P z) : ¬P ≈ Q := + hy.comp Y_eq_of_equiv + +lemma equiv_of_X_eq_of_Y_eq {P Q : Fin 3 → F} (hPz : P z ≠ 0) (hQz : Q z ≠ 0) + (hx : P x * Q z = Q x * P z) (hy : P y * Q z = Q y * P z) : P ≈ Q := by + use Units.mk0 _ hPz / Units.mk0 _ hQz + simp only [Units.smul_def, smul_fin3, Units.val_div_eq_div_val, Units.val_mk0, mul_comm, mul_div, + ← hx, ← hy, mul_div_cancel_right₀ _ hQz, fin3_def] + +lemma equiv_some_of_Z_ne_zero {P : Fin 3 → F} (hPz : P z ≠ 0) : P ≈ ![P x / P z, P y / P z, 1] := + equiv_of_X_eq_of_Y_eq hPz one_ne_zero + (by linear_combination (norm := (matrix_simp; ring1)) -P x * div_self hPz) + (by linear_combination (norm := (matrix_simp; ring1)) -P y * div_self hPz) + +lemma X_eq_iff {P Q : Fin 3 → F} (hPz : P z ≠ 0) (hQz : Q z ≠ 0) : + P x * Q z = Q x * P z ↔ P x / P z = Q x / Q z := + (div_eq_div_iff hPz hQz).symm + +lemma Y_eq_iff {P Q : Fin 3 → F} (hPz : P z ≠ 0) (hQz : Q z ≠ 0) : + P y * Q z = Q y * P z ↔ P y / P z = Q y / Q z := + (div_eq_div_iff hPz hQz).symm + +end Projective + +variable [CommRing R] section Equation -/-! ### Equations and nonsingularity -/ +/-! ### Weierstrass equations -/ +variable (W') in /-- The polynomial $W(X, Y, Z) := Y^2Z + a_1XYZ + a_3YZ^2 - (X^3 + a_2X^2Z + a_4XZ^2 + a_6Z^3)$ -associated to a Weierstrass curve `W` over `R`. This is represented as a term of type +associated to a Weierstrass curve `W'` over `R`. This is represented as a term of type `MvPolynomial (Fin 3) R`, where `X 0`, `X 1`, and `X 2` represent $X$, $Y$, and $Z$ respectively. -/ noncomputable def polynomial : MvPolynomial (Fin 3) R := - X 1 ^ 2 * X 2 + C W.a₁ * X 0 * X 1 * X 2 + C W.a₃ * X 1 * X 2 ^ 2 - - (X 0 ^ 3 + C W.a₂ * X 0 ^ 2 * X 2 + C W.a₄ * X 0 * X 2 ^ 2 + C W.a₆ * X 2 ^ 3) + X 1 ^ 2 * X 2 + C W'.a₁ * X 0 * X 1 * X 2 + C W'.a₃ * X 1 * X 2 ^ 2 + - (X 0 ^ 3 + C W'.a₂ * X 0 ^ 2 * X 2 + C W'.a₄ * X 0 * X 2 ^ 2 + C W'.a₆ * X 2 ^ 3) -lemma eval_polynomial (P : Fin 3 → R) : eval P W.polynomial = - P y ^ 2 * P z + W.a₁ * P x * P y * P z + W.a₃ * P y * P z ^ 2 - - (P x ^ 3 + W.a₂ * P x ^ 2 * P z + W.a₄ * P x * P z ^ 2 + W.a₆ * P z ^ 3) := by +lemma eval_polynomial (P : Fin 3 → R) : eval P W'.polynomial = + P y ^ 2 * P z + W'.a₁ * P x * P y * P z + W'.a₃ * P y * P z ^ 2 + - (P x ^ 3 + W'.a₂ * P x ^ 2 * P z + W'.a₄ * P x * P z ^ 2 + W'.a₆ * P z ^ 3) := by rw [polynomial] eval_simp -/-- The proposition that a point representative $(x, y, z)$ lies in `W`. +lemma eval_polynomial_of_Z_ne_zero {P : Fin 3 → F} (hPz : P z ≠ 0) : eval P W.polynomial / P z ^ 3 = + W.toAffine.polynomial.evalEval (P x / P z) (P y / P z) := by + linear_combination (norm := (rw [eval_polynomial, Affine.evalEval_polynomial]; ring1)) + P y ^ 2 / P z ^ 2 * div_self hPz + W.a₁ * P x * P y / P z ^ 2 * div_self hPz + + W.a₃ * P y / P z * div_self (pow_ne_zero 2 hPz) - W.a₂ * P x ^ 2 / P z ^ 2 * div_self hPz + - W.a₄ * P x / P z * div_self (pow_ne_zero 2 hPz) - W.a₆ * div_self (pow_ne_zero 3 hPz) + +variable (W') in +/-- The proposition that a point representative $(x, y, z)$ lies in `W'`. In other words, $W(x, y, z) = 0$. -/ def Equation (P : Fin 3 → R) : Prop := - eval P W.polynomial = 0 + eval P W'.polynomial = 0 -lemma equation_iff (P : Fin 3 → R) : W.Equation P ↔ - P y ^ 2 * P z + W.a₁ * P x * P y * P z + W.a₃ * P y * P z ^ 2 - = P x ^ 3 + W.a₂ * P x ^ 2 * P z + W.a₄ * P x * P z ^ 2 + W.a₆ * P z ^ 3 := by +lemma equation_iff (P : Fin 3 → R) : W'.Equation P ↔ + P y ^ 2 * P z + W'.a₁ * P x * P y * P z + W'.a₃ * P y * P z ^ 2 + - (P x ^ 3 + W'.a₂ * P x ^ 2 * P z + W'.a₄ * P x * P z ^ 2 + W'.a₆ * P z ^ 3) = 0 := by rw [Equation, eval_polynomial, sub_eq_zero] -lemma equation_zero (Y : R) : W.Equation ![0, Y, 0] := - (W.equation_iff ![0, Y, 0]).mpr <| by matrix_simp; ring1 +lemma equation_smul (P : Fin 3 → R) {u : R} (hu : IsUnit u) : W'.Equation (u • P) ↔ W'.Equation P := + have (u : R) {P : Fin 3 → R} (hP : W'.Equation P) : W'.Equation <| u • P := by + rw [equation_iff] at hP ⊢ + linear_combination (norm := (simp only [smul_fin3_ext]; ring1)) u ^ 3 * hP + ⟨fun h => by convert this hu.unit.inv h; erw [smul_smul, hu.val_inv_mul, one_smul], this u⟩ + +lemma equation_of_equiv {P Q : Fin 3 → R} (h : P ≈ Q) : W'.Equation P ↔ W'.Equation Q := by + rcases h with ⟨u, rfl⟩ + exact equation_smul Q u.isUnit + +lemma equation_of_Z_eq_zero {P : Fin 3 → R} (hPz : P z = 0) : W'.Equation P ↔ P x ^ 3 = 0 := by + simp only [equation_iff, hPz, add_zero, zero_sub, mul_zero, zero_pow <| OfNat.ofNat_ne_zero _, + neg_eq_zero] + +lemma equation_zero : W'.Equation ![0, 1, 0] := by + simp only [equation_of_Z_eq_zero, fin3_def_ext, zero_pow three_ne_zero] + +lemma equation_some (X Y : R) : W'.Equation ![X, Y, 1] ↔ W'.toAffine.Equation X Y := by + simp only [equation_iff, Affine.equation_iff', fin3_def_ext, one_pow, mul_one] -lemma equation_some (X Y : R) : W.Equation ![X, Y, 1] ↔ W.toAffine.Equation X Y := by - rw [equation_iff, W.toAffine.equation_iff] - congr! 1 <;> matrix_simp <;> ring1 +lemma equation_of_Z_ne_zero {P : Fin 3 → F} (hPz : P z ≠ 0) : + W.Equation P ↔ W.toAffine.Equation (P x / P z) (P y / P z) := + (equation_of_equiv <| equiv_some_of_Z_ne_zero hPz).trans <| equation_some .. -lemma equation_smul_iff (P : Fin 3 → R) (u : Rˣ) : W.Equation (u • P) ↔ W.Equation P := - have (u : Rˣ) {P : Fin 3 → R} (h : W.Equation P) : W.Equation <| u • P := by - rw [equation_iff] at h ⊢ - linear_combination (norm := (simp only [smul_fin3_ext]; ring1)) (u : R) ^ 3 * h - ⟨fun h => by convert this u⁻¹ h; rw [inv_smul_smul], this u⟩ +lemma X_eq_zero_of_Z_eq_zero [NoZeroDivisors R] {P : Fin 3 → R} (hP : W'.Equation P) + (hPz : P z = 0) : P x = 0 := + pow_eq_zero <| (equation_of_Z_eq_zero hPz).mp hP + +end Equation +section Nonsingular + +/-! ### Nonsingular Weierstrass equations -/ + +variable (W') in /-- The partial derivative $W_X(X, Y, Z)$ of $W(X, Y, Z)$ with respect to $X$. -/ noncomputable def polynomialX : MvPolynomial (Fin 3) R := - pderiv x W.polynomial + pderiv x W'.polynomial -lemma polynomialX_eq : W.polynomialX = - C W.a₁ * X 1 * X 2 - (C 3 * X 0 ^ 2 + C (2 * W.a₂) * X 0 * X 2 + C W.a₄ * X 2 ^ 2) := by +lemma polynomialX_eq : W'.polynomialX = + C W'.a₁ * X 1 * X 2 - (C 3 * X 0 ^ 2 + C (2 * W'.a₂) * X 0 * X 2 + C W'.a₄ * X 2 ^ 2) := by rw [polynomialX, polynomial] pderiv_simp ring1 -lemma eval_polynomialX (P : Fin 3 → R) : eval P W.polynomialX = - W.a₁ * P y * P z - (3 * P x ^ 2 + 2 * W.a₂ * P x * P z + W.a₄ * P z ^ 2) := by +lemma eval_polynomialX (P : Fin 3 → R) : eval P W'.polynomialX = + W'.a₁ * P y * P z - (3 * P x ^ 2 + 2 * W'.a₂ * P x * P z + W'.a₄ * P z ^ 2) := by rw [polynomialX_eq] eval_simp +lemma eval_polynomialX_of_Z_ne_zero {P : Fin 3 → F} (hPz : P z ≠ 0) : + eval P W.polynomialX / P z ^ 2 = W.toAffine.polynomialX.evalEval (P x / P z) (P y / P z) := by + linear_combination (norm := (rw [eval_polynomialX, Affine.evalEval_polynomialX]; ring1)) + W.a₁ * P y / P z * div_self hPz - 2 * W.a₂ * P x / P z * div_self hPz + - W.a₄ * div_self (pow_ne_zero 2 hPz) + +variable (W') in /-- The partial derivative $W_Y(X, Y, Z)$ of $W(X, Y, Z)$ with respect to $Y$. -/ noncomputable def polynomialY : MvPolynomial (Fin 3) R := - pderiv y W.polynomial + pderiv y W'.polynomial -lemma polynomialY_eq : W.polynomialY = - C 2 * X 1 * X 2 + C W.a₁ * X 0 * X 2 + C W.a₃ * X 2 ^ 2 := by +lemma polynomialY_eq : W'.polynomialY = + C 2 * X 1 * X 2 + C W'.a₁ * X 0 * X 2 + C W'.a₃ * X 2 ^ 2 := by rw [polynomialY, polynomial] pderiv_simp ring1 lemma eval_polynomialY (P : Fin 3 → R) : - eval P W.polynomialY = 2 * P y * P z + W.a₁ * P x * P z + W.a₃ * P z ^ 2 := by + eval P W'.polynomialY = 2 * P y * P z + W'.a₁ * P x * P z + W'.a₃ * P z ^ 2 := by rw [polynomialY_eq] eval_simp +lemma eval_polynomialY_of_Z_ne_zero {P : Fin 3 → F} (hPz : P z ≠ 0) : + eval P W.polynomialY / P z ^ 2 = W.toAffine.polynomialY.evalEval (P x / P z) (P y / P z) := by + linear_combination (norm := (rw [eval_polynomialY, Affine.evalEval_polynomialY]; ring1)) + 2 * P y / P z * div_self hPz + W.a₁ * P x / P z * div_self hPz + + W.a₃ * div_self (pow_ne_zero 2 hPz) + +variable (W') in /-- The partial derivative $W_Z(X, Y, Z)$ of $W(X, Y, Z)$ with respect to $Z$. -/ noncomputable def polynomialZ : MvPolynomial (Fin 3) R := - pderiv z W.polynomial + pderiv z W'.polynomial -lemma polynomialZ_eq : W.polynomialZ = - X 1 ^ 2 + C W.a₁ * X 0 * X 1 + C (2 * W.a₃) * X 1 * X 2 - - (C W.a₂ * X 0 ^ 2 + C (2 * W.a₄) * X 0 * X 2 + C (3 * W.a₆) * X 2 ^ 2) := by +lemma polynomialZ_eq : W'.polynomialZ = + X 1 ^ 2 + C W'.a₁ * X 0 * X 1 + C (2 * W'.a₃) * X 1 * X 2 + - (C W'.a₂ * X 0 ^ 2 + C (2 * W'.a₄) * X 0 * X 2 + C (3 * W'.a₆) * X 2 ^ 2) := by rw [polynomialZ, polynomial] pderiv_simp ring1 -lemma eval_polynomialZ (P : Fin 3 → R) : eval P W.polynomialZ = - P y ^ 2 + W.a₁ * P x * P y + 2 * W.a₃ * P y * P z - - (W.a₂ * P x ^ 2 + 2 * W.a₄ * P x * P z + 3 * W.a₆ * P z ^ 2) := by +lemma eval_polynomialZ (P : Fin 3 → R) : eval P W'.polynomialZ = + P y ^ 2 + W'.a₁ * P x * P y + 2 * W'.a₃ * P y * P z + - (W'.a₂ * P x ^ 2 + 2 * W'.a₄ * P x * P z + 3 * W'.a₆ * P z ^ 2) := by rw [polynomialZ_eq] eval_simp /-- Euler's homogeneous function theorem. -/ -theorem polynomial_relation (P : Fin 3 → R) : 3 * eval P W.polynomial = - P x * eval P W.polynomialX + P y * eval P W.polynomialY + P z * eval P W.polynomialZ := by +theorem polynomial_relation (P : Fin 3 → R) : 3 * eval P W'.polynomial = + P x * eval P W'.polynomialX + P y * eval P W'.polynomialY + P z * eval P W'.polynomialZ := by rw [eval_polynomial, eval_polynomialX, eval_polynomialY, eval_polynomialZ] ring1 -/-- The proposition that a point representative $(x, y, z)$ in `W` is nonsingular. -In other words, either $W_X(x, y, z) \ne 0$, $W_Y(x, y, z) \ne 0$, or $W_Z(x, y, z) \ne 0$. -/ -def Nonsingular (P : Fin 3 → R) : Prop := - W.Equation P ∧ (eval P W.polynomialX ≠ 0 ∨ eval P W.polynomialY ≠ 0 ∨ eval P W.polynomialZ ≠ 0) - -lemma nonsingular_iff (P : Fin 3 → R) : W.Nonsingular P ↔ W.Equation P ∧ - (W.a₁ * P y * P z ≠ 3 * P x ^ 2 + 2 * W.a₂ * P x * P z + W.a₄ * P z ^ 2 ∨ - P y * P z ≠ -P y * P z - W.a₁ * P x * P z - W.a₃ * P z ^ 2 ∨ - P y ^ 2 + W.a₁ * P x * P y + 2 * W.a₃ * P y * P z - ≠ W.a₂ * P x ^ 2 + 2 * W.a₄ * P x * P z + 3 * W.a₆ * P z ^ 2) := by - rw [Nonsingular, eval_polynomialX, eval_polynomialY, eval_polynomialZ, sub_ne_zero, sub_ne_zero, - ← sub_ne_zero (a := P y * P z)] - congr! 4 - ring1 - -lemma nonsingular_zero [Nontrivial R] : W.Nonsingular ![0, 1, 0] := - (W.nonsingular_iff ![0, 1, 0]).mpr ⟨W.equation_zero 1, by simp⟩ +variable (W') in +/-- The proposition that a point representative $(x, y, z)$ in `W'` is nonsingular. +In other words, either $W_X(x, y, z) \ne 0$, $W_Y(x, y, z) \ne 0$, or $W_Z(x, y, z) \ne 0$. -lemma nonsingular_zero' [NoZeroDivisors R] {Y : R} (hy : Y ≠ 0) : W.Nonsingular ![0, Y, 0] := - (W.nonsingular_iff ![0, Y, 0]).mpr ⟨W.equation_zero Y, by simpa⟩ - -lemma nonsingular_some (X Y : R) : W.Nonsingular ![X, Y, 1] ↔ W.toAffine.Nonsingular X Y := by - rw [nonsingular_iff] - matrix_simp - simp only [W.toAffine.nonsingular_iff, equation_some, and_congr_right_iff, - W.toAffine.equation_iff, ← not_and_or, not_iff_not, one_pow, mul_one, Iff.comm, iff_self_and] - intro h hX hY - linear_combination (norm := ring1) 3 * h - X * hX - Y * hY - -lemma nonsingular_smul_iff (P : Fin 3 → R) (u : Rˣ) : W.Nonsingular (u • P) ↔ W.Nonsingular P := - have (u : Rˣ) {P : Fin 3 → R} (h : W.Nonsingular <| u • P) : W.Nonsingular P := by - rcases (W.nonsingular_iff _).mp h with ⟨h, h'⟩ - refine (W.nonsingular_iff P).mpr ⟨(W.equation_smul_iff P u).mp h, ?_⟩ - contrapose! h' +Note that this definition is only mathematically accurate for fields. -/ +-- TODO: generalise this definition to be mathematically accurate for a larger class of rings. +def Nonsingular (P : Fin 3 → R) : Prop := + W'.Equation P ∧ + (eval P W'.polynomialX ≠ 0 ∨ eval P W'.polynomialY ≠ 0 ∨ eval P W'.polynomialZ ≠ 0) + +lemma nonsingular_iff (P : Fin 3 → R) : W'.Nonsingular P ↔ W'.Equation P ∧ + (W'.a₁ * P y * P z - (3 * P x ^ 2 + 2 * W'.a₂ * P x * P z + W'.a₄ * P z ^ 2) ≠ 0 ∨ + 2 * P y * P z + W'.a₁ * P x * P z + W'.a₃ * P z ^ 2 ≠ 0 ∨ + P y ^ 2 + W'.a₁ * P x * P y + 2 * W'.a₃ * P y * P z + - (W'.a₂ * P x ^ 2 + 2 * W'.a₄ * P x * P z + 3 * W'.a₆ * P z ^ 2) ≠ 0) := by + rw [Nonsingular, eval_polynomialX, eval_polynomialY, eval_polynomialZ] + +lemma nonsingular_smul (P : Fin 3 → R) {u : R} (hu : IsUnit u) : + W'.Nonsingular (u • P) ↔ W'.Nonsingular P := + have {u : R} (hu : IsUnit u) {P : Fin 3 → R} (hP : W'.Nonsingular <| u • P) : + W'.Nonsingular P := by + rcases (nonsingular_iff _).mp hP with ⟨hP, hP'⟩ + refine (nonsingular_iff P).mpr ⟨(equation_smul P hu).mp hP, ?_⟩ + contrapose! hP' simp only [smul_fin3_ext] - exact ⟨by linear_combination (norm := ring1) (u : R) ^ 2 * h'.left, - by linear_combination (norm := ring1) (u : R) ^ 2 * h'.right.left, - by linear_combination (norm := ring1) (u : R) ^ 2 * h'.right.right⟩ - ⟨this u, fun h => this u⁻¹ <| by rwa [inv_smul_smul]⟩ + exact ⟨by linear_combination (norm := ring1) u ^ 2 * hP'.left, + by linear_combination (norm := ring1) u ^ 2 * hP'.right.left, + by linear_combination (norm := ring1) u ^ 2 * hP'.right.right⟩ + ⟨this hu, fun h => this hu.unit⁻¹.isUnit <| by rwa [smul_smul, hu.val_inv_mul, one_smul]⟩ -lemma nonsingular_of_equiv {P Q : Fin 3 → R} (h : P ≈ Q) : W.Nonsingular P ↔ W.Nonsingular Q := by +lemma nonsingular_of_equiv {P Q : Fin 3 → R} (h : P ≈ Q) : W'.Nonsingular P ↔ W'.Nonsingular Q := by rcases h with ⟨u, rfl⟩ - exact W.nonsingular_smul_iff Q u - -/-- The proposition that a point class on `W` is nonsingular. If `P` is a point representative, -then `W.NonsingularLift ⟦P⟧` is definitionally equivalent to `W.Nonsingular P`. -/ -def NonsingularLift (P : PointClass R) : Prop := - P.lift W.Nonsingular fun _ _ => propext ∘ W.nonsingular_of_equiv - -@[simp] -lemma nonsingularLift_iff (P : Fin 3 → R) : W.NonsingularLift ⟦P⟧ ↔ W.Nonsingular P := - Iff.rfl + exact nonsingular_smul Q u.isUnit + +lemma nonsingular_of_Z_eq_zero {P : Fin 3 → R} (hPz : P z = 0) : + W'.Nonsingular P ↔ + W'.Equation P ∧ (3 * P x ^ 2 ≠ 0 ∨ P y ^ 2 + W'.a₁ * P x * P y - W'.a₂ * P x ^ 2 ≠ 0) := by + simp only [nonsingular_iff, hPz, add_zero, sub_zero, zero_sub, mul_zero, + zero_pow <| OfNat.ofNat_ne_zero _, neg_ne_zero, ne_self_iff_false, false_or] + +lemma nonsingular_zero [Nontrivial R] : W'.Nonsingular ![0, 1, 0] := by + simp only [nonsingular_of_Z_eq_zero, equation_zero, true_and, fin3_def_ext, ← not_and_or] + exact fun h => one_ne_zero <| by linear_combination (norm := ring1) h.right + +lemma nonsingular_some (X Y : R) : W'.Nonsingular ![X, Y, 1] ↔ W'.toAffine.Nonsingular X Y := by + simp_rw [nonsingular_iff, equation_some, fin3_def_ext, Affine.nonsingular_iff', + Affine.equation_iff', and_congr_right_iff, ← not_and_or, not_iff_not, one_pow, mul_one, + and_congr_right_iff, Iff.comm, iff_self_and] + intro h hX hY + linear_combination (norm := ring1) 3 * h - X * hX - Y * hY -lemma nonsingularLift_zero [Nontrivial R] : W.NonsingularLift ⟦![0, 1, 0]⟧ := - W.nonsingular_zero +lemma nonsingular_of_Z_ne_zero {P : Fin 3 → F} (hPz : P z ≠ 0) : + W.Nonsingular P ↔ W.toAffine.Nonsingular (P x / P z) (P y / P z) := + (nonsingular_of_equiv <| equiv_some_of_Z_ne_zero hPz).trans <| nonsingular_some .. -lemma nonsingularLift_zero' [NoZeroDivisors R] {Y : R} (hy : Y ≠ 0) : - W.NonsingularLift ⟦![0, Y, 0]⟧ := - W.nonsingular_zero' hy +lemma nonsingular_iff_of_Z_ne_zero {P : Fin 3 → F} (hPz : P z ≠ 0) : + W.Nonsingular P ↔ W.Equation P ∧ (eval P W.polynomialX ≠ 0 ∨ eval P W.polynomialY ≠ 0) := by + rw [nonsingular_of_Z_ne_zero hPz, Affine.Nonsingular, ← equation_of_Z_ne_zero hPz, + ← eval_polynomialX_of_Z_ne_zero hPz, div_ne_zero_iff, and_iff_left <| pow_ne_zero 2 hPz, + ← eval_polynomialY_of_Z_ne_zero hPz, div_ne_zero_iff, and_iff_left <| pow_ne_zero 2 hPz] -lemma nonsingularLift_some (X Y : R) : - W.NonsingularLift ⟦![X, Y, 1]⟧ ↔ W.toAffine.Nonsingular X Y := - W.nonsingular_some X Y +lemma Y_ne_zero_of_Z_eq_zero [NoZeroDivisors R] {P : Fin 3 → R} (hP : W'.Nonsingular P) + (hPz : P z = 0) : P y ≠ 0 := by + intro hPy + simp only [nonsingular_of_Z_eq_zero hPz, X_eq_zero_of_Z_eq_zero hP.left hPz, hPy, add_zero, + sub_zero, mul_zero, zero_pow two_ne_zero, or_self, ne_self_iff_false, and_false] at hP -variable {F : Type u} [Field F] {W : Projective F} +lemma isUnit_Y_of_Z_eq_zero {P : Fin 3 → F} (hP : W.Nonsingular P) (hPz : P z = 0) : IsUnit (P y) := + (Y_ne_zero_of_Z_eq_zero hP hPz).isUnit lemma equiv_of_Z_eq_zero {P Q : Fin 3 → F} (hP : W.Nonsingular P) (hQ : W.Nonsingular Q) (hPz : P z = 0) (hQz : Q z = 0) : P ≈ Q := by - rw [fin3_def P, hPz] at hP ⊢ - rw [fin3_def Q, hQz] at hQ ⊢ - simp? [nonsingular_iff, equation_iff] at hP hQ says - simp only [Nat.succ_eq_add_one, Nat.reduceAdd, Fin.isValue, nonsingular_iff, - equation_iff, Matrix.cons_val_one, Matrix.head_cons, Matrix.cons_val_two, Matrix.tail_cons, - mul_zero, Matrix.cons_val_zero, add_zero, ne_eq, OfNat.ofNat_ne_zero, not_false_eq_true, - zero_pow, zero_eq_mul, pow_eq_zero_iff, not_or, sub_self, not_true_eq_false, false_or] - at hP hQ - simp? [pow_eq_zero hP.left.symm, pow_eq_zero hQ.left.symm] at * says - simp only [Fin.isValue, pow_eq_zero hP.left.symm, ne_eq, OfNat.ofNat_ne_zero, - not_false_eq_true, zero_pow, not_true_eq_false, and_false, mul_zero, zero_mul, add_zero, - pow_eq_zero_iff, false_or, true_and, pow_eq_zero hQ.left.symm, Nat.succ_eq_add_one, - Nat.reduceAdd] at * - exact ⟨Units.mk0 (P y / Q y) <| div_ne_zero hP hQ, by simp [div_mul_cancel₀ _ hQ]⟩ - -lemma equiv_zero_of_Z_eq_zero {P : Fin 3 → F} (h : W.Nonsingular P) (hPz : P z = 0) : - P ≈ ![0, 1, 0] := - equiv_of_Z_eq_zero h W.nonsingular_zero hPz rfl + use (isUnit_Y_of_Z_eq_zero hP hPz).unit / (isUnit_Y_of_Z_eq_zero hQ hQz).unit + simp only [Units.smul_def, smul_fin3, X_eq_zero_of_Z_eq_zero hQ.left hQz, hQz, mul_zero, + Units.val_div_eq_div_val, IsUnit.unit_spec, (isUnit_Y_of_Z_eq_zero hQ hQz).div_mul_cancel] + conv_rhs => rw [← fin3_def P, X_eq_zero_of_Z_eq_zero hP.left hPz, hPz] -lemma equiv_some_of_Z_ne_zero {P : Fin 3 → F} (hPz : P z ≠ 0) : P ≈ ![P x / P z, P y / P z, 1] := - ⟨Units.mk0 _ hPz, by simp [← fin3_def P, mul_div_cancel₀ _ hPz]⟩ +lemma equiv_zero_of_Z_eq_zero {P : Fin 3 → F} (hP : W.Nonsingular P) (hPz : P z = 0) : + P ≈ ![0, 1, 0] := + equiv_of_Z_eq_zero hP nonsingular_zero hPz rfl -lemma nonsingular_iff_affine_of_Z_ne_zero {P : Fin 3 → F} (hPz : P z ≠ 0) : - W.Nonsingular P ↔ W.toAffine.Nonsingular (P x / P z) (P y / P z) := - (W.nonsingular_of_equiv <| equiv_some_of_Z_ne_zero hPz).trans <| W.nonsingular_some .. +variable (W') in +/-- The proposition that a point class on `W'` is nonsingular. If `P` is a point representative, +then `W.NonsingularLift ⟦P⟧` is definitionally equivalent to `W.Nonsingular P`. -/ +def NonsingularLift (P : PointClass R) : Prop := + P.lift W'.Nonsingular fun _ _ => propext ∘ nonsingular_of_equiv -lemma nonsingular_of_affine_of_Z_ne_zero {P : Fin 3 → F} - (h : W.toAffine.Nonsingular (P x / P z) (P y / P z)) (hPz : P z ≠ 0) : W.Nonsingular P := - (nonsingular_iff_affine_of_Z_ne_zero hPz).mpr h +lemma nonsingularLift_iff (P : Fin 3 → R) : W'.NonsingularLift ⟦P⟧ ↔ W'.Nonsingular P := + Iff.rfl -lemma nonsingular_affine_of_Z_ne_zero {P : Fin 3 → F} (h : W.Nonsingular P) (hPz : P z ≠ 0) : - W.toAffine.Nonsingular (P x / P z) (P y / P z) := - (nonsingular_iff_affine_of_Z_ne_zero hPz).mp h +lemma nonsingularLift_zero [Nontrivial R] : W'.NonsingularLift ⟦![0, 1, 0]⟧ := + nonsingular_zero -end Equation +lemma nonsingularLift_some (X Y : R) : + W'.NonsingularLift ⟦![X, Y, 1]⟧ ↔ W'.toAffine.Nonsingular X Y := + nonsingular_some X Y + +end Nonsingular + +@[deprecated (since := "2024-08-27")] alias equation_smul_iff := equation_smul +@[deprecated (since := "2024-08-27")] alias nonsingularLift_zero' := nonsingularLift_zero +@[deprecated (since := "2024-08-27")] +alias nonsingular_affine_of_Z_ne_zero := nonsingular_of_Z_ne_zero +@[deprecated (since := "2024-08-27")] +alias nonsingular_iff_affine_of_Z_ne_zero := nonsingular_of_Z_ne_zero +@[deprecated (since := "2024-08-27")] +alias nonsingular_of_affine_of_Z_ne_zero := nonsingular_of_Z_ne_zero +@[deprecated (since := "2024-08-27")] alias nonsingular_smul_iff := nonsingular_smul +@[deprecated (since := "2024-08-27")] alias nonsingular_zero' := nonsingular_zero end WeierstrassCurve.Projective diff --git a/Mathlib/AlgebraicGeometry/FunctionField.lean b/Mathlib/AlgebraicGeometry/FunctionField.lean index 91aaaac6fed72..da34fe72ff8b1 100644 --- a/Mathlib/AlgebraicGeometry/FunctionField.lean +++ b/Mathlib/AlgebraicGeometry/FunctionField.lean @@ -17,7 +17,7 @@ This is a field when the scheme is integral. function field. This map is injective. -/ --- Explicit universe annotations were used in this file to improve perfomance #12737 +-- Explicit universe annotations were used in this file to improve performance #12737 universe u v diff --git a/Mathlib/AlgebraicGeometry/GammaSpecAdjunction.lean b/Mathlib/AlgebraicGeometry/GammaSpecAdjunction.lean index 298135400e8a8..807cd5593bbde 100644 --- a/Mathlib/AlgebraicGeometry/GammaSpecAdjunction.lean +++ b/Mathlib/AlgebraicGeometry/GammaSpecAdjunction.lean @@ -30,7 +30,7 @@ case the unit and the counit would switch to each other. -/ --- Explicit universe annotations were used in this file to improve perfomance #12737 +-- Explicit universe annotations were used in this file to improve performance #12737 noncomputable section diff --git a/Mathlib/AlgebraicGeometry/Morphisms/Basic.lean b/Mathlib/AlgebraicGeometry/Morphisms/Basic.lean index e92624a6197d0..7d7bc17702e37 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/Basic.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/Basic.lean @@ -108,7 +108,7 @@ Also see `IsLocalAtTarget.mk'` for a convenient constructor. class IsLocalAtTarget (P : MorphismProperty Scheme) : Prop where /-- `P` respects isomorphisms. -/ respectsIso : P.RespectsIso := by infer_instance - /-- `P` holds for `f ∣_ U` for an open cover `U` of `Y` if and only if `P` holds for `f`. -/ + /-- `P` holds for `f ∣_ U` for an open cover `U` of `Y` if and only if `P` holds for `f`. -/ iff_of_openCover' : ∀ {X Y : Scheme.{u}} (f : X ⟶ Y) (𝒰 : Scheme.OpenCover.{u} Y), P f ↔ ∀ i, P (𝒰.pullbackHom f i) @@ -186,7 +186,7 @@ Also see `IsLocalAtSource.mk'` for a convenient constructor. class IsLocalAtSource (P : MorphismProperty Scheme) : Prop where /-- `P` respects isomorphisms. -/ respectsIso : P.RespectsIso := by infer_instance - /-- `P` holds for `f ∣_ U` for an open cover `U` of `Y` if and only if `P` holds for `f`. -/ + /-- `P` holds for `f ∣_ U` for an open cover `U` of `Y` if and only if `P` holds for `f`. -/ iff_of_openCover' : ∀ {X Y : Scheme.{u}} (f : X ⟶ Y) (𝒰 : Scheme.OpenCover.{u} X), P f ↔ ∀ i, P (𝒰.map i ≫ f) diff --git a/Mathlib/AlgebraicGeometry/Morphisms/FinitePresentation.lean b/Mathlib/AlgebraicGeometry/Morphisms/FinitePresentation.lean new file mode 100644 index 0000000000000..384a722407c6d --- /dev/null +++ b/Mathlib/AlgebraicGeometry/Morphisms/FinitePresentation.lean @@ -0,0 +1,62 @@ +/- +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.AlgebraicGeometry.Morphisms.RingHomProperties +import Mathlib.RingTheory.RingHom.FinitePresentation + +/-! + +# Morphisms of finite presentation + +A morphism of schemes `f : X ⟶ Y` is locally of finite presentation if for each affine `U ⊆ Y` and +`V ⊆ f ⁻¹' U`, The induced map `Γ(Y, U) ⟶ Γ(X, V)` is of finite presentation. + +A morphism of schemes is of finite presentation if it is both locally of finite presentation and +quasi-compact. We do not provide a separate declaration for this, instead simply assume both +conditions. + +We show that these properties are local, and are stable under compositions. + +-/ + + +noncomputable section + +open CategoryTheory + +universe v u + +namespace AlgebraicGeometry + +variable {X Y : Scheme.{u}} (f : X ⟶ Y) + +/-- A morphism of schemes `f : X ⟶ Y` is locally of finite presentation if for each affine `U ⊆ Y` +and `V ⊆ f ⁻¹' U`, The induced map `Γ(Y, U) ⟶ Γ(X, V)` is of finite presentation. -/ +@[mk_iff] +class LocallyOfFinitePresentation : Prop where + finitePresentation_of_affine_subset : + ∀ (U : Y.affineOpens) (V : X.affineOpens) (e : V.1 ≤ f ⁻¹ᵁ U.1), + (f.appLE U V e).FinitePresentation + +instance : HasRingHomProperty @LocallyOfFinitePresentation RingHom.FinitePresentation where + isLocal_ringHomProperty := RingHom.finitePresentation_isLocal + eq_affineLocally' := by + ext X Y f + rw [locallyOfFinitePresentation_iff, affineLocally_iff_affineOpens_le] + +instance (priority := 900) locallyOfFinitePresentation_of_isOpenImmersion [IsOpenImmersion f] : + LocallyOfFinitePresentation f := + HasRingHomProperty.of_isOpenImmersion + +instance locallyOfFinitePresentation_comp {X Y Z : Scheme.{u}} (f : X ⟶ Y) (g : Y ⟶ Z) + [hf : LocallyOfFinitePresentation f] [hg : LocallyOfFinitePresentation g] : + LocallyOfFinitePresentation (f ≫ g) := + MorphismProperty.comp_mem _ f g hf hg + +lemma locallyOfFinitePresentation_stableUnderBaseChange : + MorphismProperty.StableUnderBaseChange @LocallyOfFinitePresentation := + HasRingHomProperty.stableUnderBaseChange RingHom.finitePresentation_stableUnderBaseChange + +end AlgebraicGeometry diff --git a/Mathlib/AlgebraicGeometry/Morphisms/RingHomProperties.lean b/Mathlib/AlgebraicGeometry/Morphisms/RingHomProperties.lean index 855fcc83a8aa2..3ed0b2cf6b132 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/RingHomProperties.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/RingHomProperties.lean @@ -55,7 +55,7 @@ We also provide the instances `P.IsMultiplicative`, `P.IsStableUnderComposition` -/ --- Explicit universe annotations were used in this file to improve perfomance #12737 +-- Explicit universe annotations were used in this file to improve performance #12737 universe u @@ -281,7 +281,7 @@ instance : IsLocalAtSource P := by simp_rw [← HasAffineProperty.iff_of_isAffine (P := P), iff_of_source_openCover 𝒰.affineRefinement.openCover, fun i ↦ iff_of_source_openCover (P := P) (f := 𝒰.map i ≫ f) (𝒰.obj i).affineCover] - simp [Scheme.OpenCover.affineRefinement] + simp [Scheme.OpenCover.affineRefinement, Sigma.forall] instance : P.ContainsIdentities where id_mem X := by diff --git a/Mathlib/AlgebraicGeometry/OpenImmersion.lean b/Mathlib/AlgebraicGeometry/OpenImmersion.lean index 17d4f6c368e33..0a6b512618e52 100644 --- a/Mathlib/AlgebraicGeometry/OpenImmersion.lean +++ b/Mathlib/AlgebraicGeometry/OpenImmersion.lean @@ -12,7 +12,7 @@ import Mathlib.CategoryTheory.Limits.Shapes.Pullback.CommSq -/ --- Explicit universe annotations were used in this file to improve perfomance #12737 +-- Explicit universe annotations were used in this file to improve performance #12737 noncomputable section diff --git a/Mathlib/AlgebraicGeometry/PrimeSpectrum/Basic.lean b/Mathlib/AlgebraicGeometry/PrimeSpectrum/Basic.lean index fbd5e0acc99f5..34df4b8d2c4b9 100644 --- a/Mathlib/AlgebraicGeometry/PrimeSpectrum/Basic.lean +++ b/Mathlib/AlgebraicGeometry/PrimeSpectrum/Basic.lean @@ -391,7 +391,7 @@ def primeSpectrumProdHomeo : refine ((primeSpectrumProd R S).symm.toHomeomorphOfInducing ?_).symm refine (closedEmbedding_of_continuous_injective_closed ?_ (Equiv.injective _) ?_).toInducing · rw [continuous_sum_dom] - simp only [Function.comp, primeSpectrumProd_symm_inl, primeSpectrumProd_symm_inr] + simp only [Function.comp_def, primeSpectrumProd_symm_inl, primeSpectrumProd_symm_inr] exact ⟨(comap _).2, (comap _).2⟩ · rw [isClosedMap_sum] constructor @@ -622,7 +622,7 @@ lemma vanishingIdeal_irreducibleComponents : rw [irreducibleComponents_eq_maximals_closed, minimalPrimes_eq_minimals, image_antitone_setOf_maximal (fun s t hs _ ↦ (vanishingIdeal_anti_mono_iff hs.1).symm), ← funext (@Set.mem_setOf_eq _ · Ideal.IsPrime), ← vanishingIdeal_isClosed_isIrreducible] - simp only [Set.mem_image, Set.mem_setOf] + rfl lemma zeroLocus_minimalPrimes : zeroLocus ∘ (↑) '' minimalPrimes R = diff --git a/Mathlib/AlgebraicGeometry/PrimeSpectrum/Noetherian.lean b/Mathlib/AlgebraicGeometry/PrimeSpectrum/Noetherian.lean index 8e58796b933e2..1e92a49a98670 100644 --- a/Mathlib/AlgebraicGeometry/PrimeSpectrum/Noetherian.lean +++ b/Mathlib/AlgebraicGeometry/PrimeSpectrum/Noetherian.lean @@ -21,9 +21,7 @@ variable (R : Type u) [CommRing R] [IsNoetherianRing R] instance : NoetherianSpace (PrimeSpectrum R) := by apply ((noetherianSpace_TFAE <| PrimeSpectrum R).out 0 1).mpr - have H := ‹IsNoetherianRing R› - rw [isNoetherianRing_iff, isNoetherian_iff_wellFounded] at H - exact (closedsEmbedding R).dual.wellFounded H + exact (closedsEmbedding R).dual.wellFounded IsWellFounded.wf 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 02c18404835ab..139077e8ace13 100644 --- a/Mathlib/AlgebraicGeometry/ProjectiveSpectrum/Scheme.lean +++ b/Mathlib/AlgebraicGeometry/ProjectiveSpectrum/Scheme.lean @@ -159,7 +159,7 @@ open Ideal -- So for any `x` in `Proj| (pbo f)`, we need some point in `Spec A⁰_f`, i.e. a prime ideal, -- and we need this correspondence to be continuous in their Zariski topology. variable {𝒜} -variable {f : A} {m : ℕ} (f_deg : f ∈ 𝒜 m) (x : Proj| (pbo f)) +variable {f : A} {m : ℕ} (x : Proj| (pbo f)) /-- For any `x` in `Proj| (pbo f)`, the corresponding ideal in `Spec A⁰_f`. This fact that this ideal @@ -263,12 +263,13 @@ The set `{a | aᵢᵐ/fⁱ ∈ q}` * is prime, as proved in `carrier.asIdeal.prime`; * is relevant, as proved in `carrier.relevant`. -/ -def carrier (q : Spec.T A⁰_ f) : Set A := - {a | ∀ i, (HomogeneousLocalization.mk ⟨m * i, ⟨proj 𝒜 i a ^ m, by mem_tac⟩, +def carrier (f_deg : f ∈ 𝒜 m) (q : Spec.T A⁰_ f) : Set A := + {a | ∀ i, (HomogeneousLocalization.mk ⟨m * i, ⟨proj 𝒜 i a ^ m, by rw [← smul_eq_mul]; mem_tac⟩, ⟨f ^ i, by rw [mul_comm]; mem_tac⟩, ⟨_, rfl⟩⟩ : A⁰_ f) ∈ q.1} theorem mem_carrier_iff (q : Spec.T A⁰_ f) (a : A) : - a ∈ carrier f_deg q ↔ ∀ i, (HomogeneousLocalization.mk ⟨m * i, ⟨proj 𝒜 i a ^ m, by mem_tac⟩, + a ∈ carrier f_deg q ↔ ∀ i, (HomogeneousLocalization.mk ⟨m * i, ⟨proj 𝒜 i a ^ m, by + rw [← smul_eq_mul]; mem_tac⟩, ⟨f ^ i, by rw [mul_comm]; mem_tac⟩, ⟨_, rfl⟩⟩ : A⁰_ f) ∈ q.1 := Iff.rfl @@ -290,7 +291,7 @@ theorem mem_carrier_iff_of_mem (hm : 0 < m) (q : Spec.T A⁰_ f) (a : A) {n} (hn a ∈ carrier f_deg q ↔ (HomogeneousLocalization.mk ⟨m * n, ⟨a ^ m, pow_mem_graded m hn⟩, ⟨f ^ n, by rw [mul_comm]; mem_tac⟩, ⟨_, rfl⟩⟩ : A⁰_ f) ∈ q.asIdeal := by - trans (HomogeneousLocalization.mk ⟨m * n, ⟨proj 𝒜 n a ^ m, by mem_tac⟩, + trans (HomogeneousLocalization.mk ⟨m * n, ⟨proj 𝒜 n a ^ m, by rw [← smul_eq_mul]; mem_tac⟩, ⟨f ^ n, by rw [mul_comm]; mem_tac⟩, ⟨_, rfl⟩⟩ : A⁰_ f) ∈ q.asIdeal · refine ⟨fun h ↦ h n, fun h i ↦ if hi : i = n then hi ▸ h else ?_⟩ convert zero_mem q.asIdeal @@ -337,12 +338,12 @@ theorem carrier.add_mem (q : Spec.T A⁰_ f) {a b : A} (ha : a ∈ carrier f_deg ⟨m * i, ⟨proj 𝒜 i a ^ j * proj 𝒜 i b ^ (m - j), ?_⟩, ⟨_, by rw [mul_comm]; mem_tac⟩, ⟨i, rfl⟩⟩ letI r : A⁰_ f := HomogeneousLocalization.mk - ⟨m * i, ⟨proj 𝒜 i b ^ m, by mem_tac⟩, + ⟨m * i, ⟨proj 𝒜 i b ^ m, by rw [← smul_eq_mul]; mem_tac⟩, ⟨_, by rw [mul_comm]; mem_tac⟩, ⟨i, rfl⟩⟩ l * r else letI l : A⁰_ f := HomogeneousLocalization.mk - ⟨m * i, ⟨proj 𝒜 i a ^ m, by mem_tac⟩, + ⟨m * i, ⟨proj 𝒜 i a ^ m, by rw [← smul_eq_mul]; mem_tac⟩, ⟨_, by rw [mul_comm]; mem_tac⟩, ⟨i, rfl⟩⟩ letI r : A⁰_ f := HomogeneousLocalization.mk ⟨m * i, ⟨proj 𝒜 i a ^ (j - m) * proj 𝒜 i b ^ (m + m - j), ?_⟩, @@ -522,14 +523,15 @@ end fromSpecToSpec namespace toSpec variable {f : A} {m : ℕ} (f_deg : f ∈ 𝒜 m) (hm : 0 < m) -include hm +include hm f_deg variable {𝒜} in lemma image_basicOpen_eq_basicOpen (a : A) (i : ℕ) : toSpec 𝒜 f '' (Subtype.val ⁻¹' (pbo (decompose 𝒜 a i) : Set (ProjectiveSpectrum 𝒜))) = (PrimeSpectrum.basicOpen (R := A⁰_ f) <| HomogeneousLocalization.mk - ⟨m * i, ⟨decompose 𝒜 a i ^ m, SetLike.pow_mem_graded _ (Submodule.coe_mem _)⟩, + ⟨m * i, ⟨decompose 𝒜 a i ^ m, + (smul_eq_mul ℕ) ▸ SetLike.pow_mem_graded _ (Submodule.coe_mem _)⟩, ⟨f^i, by rw [mul_comm]; exact SetLike.pow_mem_graded _ f_deg⟩, ⟨i, rfl⟩⟩).1 := Set.preimage_injective.mpr (toSpec_surjective 𝒜 f_deg hm) <| Set.preimage_image_eq _ (toSpec_injective 𝒜 f_deg hm) ▸ by diff --git a/Mathlib/AlgebraicGeometry/ProjectiveSpectrum/Topology.lean b/Mathlib/AlgebraicGeometry/ProjectiveSpectrum/Topology.lean index 85a2d1adb6373..634828aaafdef 100644 --- a/Mathlib/AlgebraicGeometry/ProjectiveSpectrum/Topology.lean +++ b/Mathlib/AlgebraicGeometry/ProjectiveSpectrum/Topology.lean @@ -11,7 +11,7 @@ import Mathlib.Data.Set.Subsingleton /-! # Projective spectrum of a graded ring -The projective spectrum of a graded commutative ring is the subtype of all homogenous ideals that +The projective spectrum of a graded commutative ring is the subtype of all homogeneous ideals that are prime and do not contain the irrelevant ideal. It is naturally endowed with a topology: the Zariski topology. @@ -45,7 +45,7 @@ variable [CommSemiring R] [CommRing A] [Algebra R A] variable (𝒜 : ℕ → Submodule R A) [GradedAlgebra 𝒜] -- porting note (#5171): removed @[nolint has_nonempty_instance] -/-- The projective spectrum of a graded commutative ring is the subtype of all homogenous ideals +/-- The projective spectrum of a graded commutative ring is the subtype of all homogeneous ideals that are prime and do not contain the irrelevant ideal. -/ @[ext] structure ProjectiveSpectrum where @@ -126,7 +126,7 @@ theorem gc_set : @GaloisConnection (Set A) (Set (ProjectiveSpectrum 𝒜))ᵒᵈ _ _ (fun s => zeroLocus 𝒜 s) fun t => vanishingIdeal t := by have ideal_gc : GaloisConnection Ideal.span _ := (Submodule.gi A _).gc - simpa [zeroLocus_span, Function.comp] using GaloisConnection.compose ideal_gc (gc_ideal 𝒜) + simpa [zeroLocus_span, Function.comp_def] using GaloisConnection.compose ideal_gc (gc_ideal 𝒜) theorem gc_homogeneousIdeal : @GaloisConnection (HomogeneousIdeal 𝒜) (Set (ProjectiveSpectrum 𝒜))ᵒᵈ _ _ diff --git a/Mathlib/AlgebraicGeometry/Properties.lean b/Mathlib/AlgebraicGeometry/Properties.lean index 472fdb1fdecb5..d4cb9d574a2c2 100644 --- a/Mathlib/AlgebraicGeometry/Properties.lean +++ b/Mathlib/AlgebraicGeometry/Properties.lean @@ -22,7 +22,7 @@ We provide some basic properties of schemes -/ --- Explicit universe annotations were used in this file to improve perfomance #12737 +-- Explicit universe annotations were used in this file to improve performance #12737 universe u diff --git a/Mathlib/AlgebraicGeometry/Restrict.lean b/Mathlib/AlgebraicGeometry/Restrict.lean index f1bb6aca5465c..07a9eb9cfa1e3 100644 --- a/Mathlib/AlgebraicGeometry/Restrict.lean +++ b/Mathlib/AlgebraicGeometry/Restrict.lean @@ -17,7 +17,7 @@ import Mathlib.AlgebraicGeometry.Cover.Open -/ --- Explicit universe annotations were used in this file to improve perfomance #12737 +-- Explicit universe annotations were used in this file to improve performance #12737 noncomputable section @@ -480,7 +480,7 @@ def morphismRestrictRestrict {X Y : Scheme.{u}} (f : X ⟶ Y) (U : Y.Opens) (V : Scheme.restrictRestrict_hom_restrict, morphismRestrict_ι_assoc, morphismRestrict_ι] -/-- Restricting a morphism twice onto a basic open set is isomorphic to one restriction. -/ +/-- Restricting a morphism twice onto a basic open set is isomorphic to one restriction. -/ def morphismRestrictRestrictBasicOpen {X Y : Scheme.{u}} (f : X ⟶ Y) (U : Y.Opens) (r : Γ(Y, U)) : Arrow.mk (f ∣_ U ∣_ U.toScheme.basicOpen (Y.presheaf.map (eqToHom U.openEmbedding_obj_top).op r)) ≅ diff --git a/Mathlib/AlgebraicGeometry/Scheme.lean b/Mathlib/AlgebraicGeometry/Scheme.lean index 93d4ae918f332..fab17a4f32795 100644 --- a/Mathlib/AlgebraicGeometry/Scheme.lean +++ b/Mathlib/AlgebraicGeometry/Scheme.lean @@ -18,7 +18,7 @@ A morphism of schemes is just a morphism of the underlying locally ringed spaces -/ --- Explicit universe annotations were used in this file to improve perfomance #12737 +-- Explicit universe annotations were used in this file to improve performance #12737 universe u diff --git a/Mathlib/AlgebraicGeometry/Spec.lean b/Mathlib/AlgebraicGeometry/Spec.lean index eac3cfe696a30..b60cff5c8de99 100644 --- a/Mathlib/AlgebraicGeometry/Spec.lean +++ b/Mathlib/AlgebraicGeometry/Spec.lean @@ -33,7 +33,7 @@ The adjunction `Γ ⊣ Spec` is constructed in `Mathlib/AlgebraicGeometry/GammaS -/ --- Explicit universe annotations were used in this file to improve perfomance #12737 +-- Explicit universe annotations were used in this file to improve performance #12737 noncomputable section @@ -269,7 +269,7 @@ section SpecΓ open AlgebraicGeometry.LocallyRingedSpace -/-- The counit morphism `R ⟶ Γ(Spec R)` given by `AlgebraicGeometry.StructureSheaf.toOpen`. -/ +/-- The counit morphism `R ⟶ Γ(Spec R)` given by `AlgebraicGeometry.StructureSheaf.toOpen`. -/ @[simps!] def toSpecΓ (R : CommRingCat.{u}) : R ⟶ Γ.obj (op (Spec.toLocallyRingedSpace.obj (op R))) := StructureSheaf.toOpen R ⊤ diff --git a/Mathlib/AlgebraicGeometry/StructureSheaf.lean b/Mathlib/AlgebraicGeometry/StructureSheaf.lean index a145948515d7c..692b54e2ecf76 100644 --- a/Mathlib/AlgebraicGeometry/StructureSheaf.lean +++ b/Mathlib/AlgebraicGeometry/StructureSheaf.lean @@ -799,9 +799,9 @@ theorem toBasicOpen_surjective (f : R) : Function.Surjective (toBasicOpen R f) : apply PrimeSpectrum.vanishingIdeal_anti_mono ht_cover exact PrimeSpectrum.subset_vanishingIdeal_zeroLocus {f} (Set.mem_singleton f) replace hn := Ideal.mul_mem_right f _ hn - erw [← pow_succ, Finsupp.mem_span_image_iff_total] at hn + erw [← pow_succ, Finsupp.mem_span_image_iff_linearCombination] at hn rcases hn with ⟨b, b_supp, hb⟩ - rw [Finsupp.total_apply_of_mem_supported R b_supp] at hb + rw [Finsupp.linearCombination_apply_of_mem_supported R b_supp] at hb dsimp at hb -- Finally, we have all the ingredients. -- We claim that our preimage is given by `(∑ (i : ι) ∈ t, b i * a i) / f ^ (n+1)` diff --git a/Mathlib/AlgebraicTopology/DoldKan/Degeneracies.lean b/Mathlib/AlgebraicTopology/DoldKan/Degeneracies.lean index dd949cbd7cb71..ac8cbcf733f76 100644 --- a/Mathlib/AlgebraicTopology/DoldKan/Degeneracies.lean +++ b/Mathlib/AlgebraicTopology/DoldKan/Degeneracies.lean @@ -49,7 +49,7 @@ theorem HigherFacesVanish.comp_σ {Y : C} {X : SimplicialObject C} {n b q : ℕ} linarith · intro hj' simp only [hnbq, add_comm b, add_assoc, hj', Fin.val_zero, zero_add, add_le_iff_nonpos_right, - nonpos_iff_eq_zero, add_eq_zero, false_and] at hj + nonpos_iff_eq_zero, add_eq_zero, false_and, reduceCtorEq] at hj theorem σ_comp_P_eq_zero (X : SimplicialObject C) {n q : ℕ} (i : Fin (n + 1)) (hi : n + 1 ≤ i + q) : X.σ i ≫ (P q).f (n + 1) = 0 := by diff --git a/Mathlib/AlgebraicTopology/DoldKan/Equivalence.lean b/Mathlib/AlgebraicTopology/DoldKan/Equivalence.lean index 59cf4f6cf84aa..72a3b619b766a 100644 --- a/Mathlib/AlgebraicTopology/DoldKan/Equivalence.lean +++ b/Mathlib/AlgebraicTopology/DoldKan/Equivalence.lean @@ -62,7 +62,7 @@ we define the functor in the other direction extension of a functor `Γ₀ : ChainComplex C ℕ ⥤ SimplicialObject C` which is defined similarly as in [*Simplicial Homotopy Theory* by Goerss-Jardine][goerss-jardine-2009]. In `Degeneracies.lean`, we show that `PInfty` vanishes on the image of degeneracy -operators, which is one of the key properties that makes it possible to contruct +operators, which is one of the key properties that makes it possible to construct the isomorphism `N₂Γ₂ : Γ₂ ⋙ N₂ ≅ 𝟭 (Karoubi (ChainComplex C ℕ))`. The rest of the proof follows the strategy in the [original paper by Dold][dold1958]. We show diff --git a/Mathlib/AlgebraicTopology/DoldKan/Faces.lean b/Mathlib/AlgebraicTopology/DoldKan/Faces.lean index a232a8b12caaf..845dd32f779d1 100644 --- a/Mathlib/AlgebraicTopology/DoldKan/Faces.lean +++ b/Mathlib/AlgebraicTopology/DoldKan/Faces.lean @@ -155,7 +155,7 @@ theorem comp_Hσ_eq_zero {Y : C} {n q : ℕ} {φ : Y ⟶ X _[n + 1]} (v : Higher omega · intro h simp only [Fin.pred, Fin.subNat, Fin.ext_iff, Nat.succ_add_sub_one, - Fin.val_zero, add_eq_zero, false_and] at h + Fin.val_zero, add_eq_zero, false_and, reduceCtorEq] at h · simp only [Fin.pred, Fin.subNat, Nat.pred_eq_sub_one, Nat.succ_add_sub_one] omega diff --git a/Mathlib/AlgebraicTopology/DoldKan/FunctorGamma.lean b/Mathlib/AlgebraicTopology/DoldKan/FunctorGamma.lean index 72511e140c0f6..67d99a2628ff5 100644 --- a/Mathlib/AlgebraicTopology/DoldKan/FunctorGamma.lean +++ b/Mathlib/AlgebraicTopology/DoldKan/FunctorGamma.lean @@ -148,7 +148,7 @@ theorem mapMono_comp (i' : Δ'' ⟶ Δ') (i : Δ' ⟶ Δ) [Mono i'] [Mono i] : have eq : Δ.len = Δ''.len + (k + k' + 2) := by omega rw [mapMono_eq_zero K (i' ≫ i) _ _]; rotate_left · by_contra h - simp only [self_eq_add_right, h, add_eq_zero, and_false] at eq + simp only [self_eq_add_right, h, add_eq_zero, and_false, reduceCtorEq] at eq · by_contra h simp only [h.1, add_right_inj] at eq omega diff --git a/Mathlib/AlgebraicTopology/DoldKan/HomotopyEquivalence.lean b/Mathlib/AlgebraicTopology/DoldKan/HomotopyEquivalence.lean index f90156e668cfe..ef91e2c166c8a 100644 --- a/Mathlib/AlgebraicTopology/DoldKan/HomotopyEquivalence.lean +++ b/Mathlib/AlgebraicTopology/DoldKan/HomotopyEquivalence.lean @@ -62,7 +62,7 @@ def homotopyPInftyToId : Homotopy (PInfty : K[X] ⟶ _) (𝟙 _) where · simpa only [Homotopy.dNext_zero_chainComplex, Homotopy.prevD_chainComplex, PInfty_f, P_f_0_eq, zero_add] using (homotopyPToId X 2).comm 0 · simp only [Homotopy.dNext_succ_chainComplex, Homotopy.prevD_chainComplex, - HomologicalComplex.id_f, PInfty_f, ← P_is_eventually_constant (rfl.le : n + 1 ≤ n + 1)] + HomologicalComplex.id_f, PInfty_f, ← P_is_eventually_constant (le_refl <| n + 1)] -- Porting note(lean4/2146): remaining proof was -- `simpa only [homotopyPToId_eventually_constant X (lt_add_one (Nat.succ n))] -- using (homotopyPToId X (n + 2)).comm (n + 1)`; diff --git a/Mathlib/AlgebraicTopology/DoldKan/Normalized.lean b/Mathlib/AlgebraicTopology/DoldKan/Normalized.lean index d458777633750..43aa24e304f15 100644 --- a/Mathlib/AlgebraicTopology/DoldKan/Normalized.lean +++ b/Mathlib/AlgebraicTopology/DoldKan/Normalized.lean @@ -124,10 +124,13 @@ def N₁_iso_normalizedMooreComplex_comp_toKaroubi : N₁ ≅ normalizedMooreCom comm := by erw [inclusionOfMooreComplexMap_comp_PInfty, id_comp] } naturality := fun X Y f => by ext - simp only [Functor.comp_map, normalizedMooreComplex_map, Karoubi.comp_f, toKaroubi_map_f, - HomologicalComplex.comp_f, NormalizedMooreComplex.map_f, - inclusionOfMooreComplexMap_f, factorThru_arrow, N₁_map_f, - inclusionOfMooreComplexMap_comp_PInfty_assoc, AlternatingFaceMapComplex.map_f] } + simp only [Functor.comp_obj, normalizedMooreComplex_obj, toKaroubi_obj_X, + NormalizedMooreComplex.obj_X, N₁_obj_X, AlternatingFaceMapComplex.obj_X, Functor.comp_map, + normalizedMooreComplex_map, Karoubi.comp_f, toKaroubi_map_f, HomologicalComplex.comp_f, + NormalizedMooreComplex.map_f, inclusionOfMooreComplexMap_f, NormalizedMooreComplex.objX, + factorThru_arrow, N₁_map_f, inclusionOfMooreComplexMap_comp_PInfty_assoc, + AlternatingFaceMapComplex.map_f] + } hom_inv_id := by ext X : 3 simp only [PInftyToNormalizedMooreComplex_comp_inclusionOfMooreComplexMap, diff --git a/Mathlib/AlgebraicTopology/DoldKan/PInfty.lean b/Mathlib/AlgebraicTopology/DoldKan/PInfty.lean index 3ca7762569ccb..f9d67b69c0cf5 100644 --- a/Mathlib/AlgebraicTopology/DoldKan/PInfty.lean +++ b/Mathlib/AlgebraicTopology/DoldKan/PInfty.lean @@ -33,10 +33,11 @@ variable {C : Type*} [Category C] [Preadditive C] {X : SimplicialObject C} theorem P_is_eventually_constant {q n : ℕ} (hqn : n ≤ q) : ((P (q + 1)).f n : X _[n] ⟶ _) = (P q).f n := by - rcases n with (_|n) - · simp only [P_f_0_eq] - · simp only [P_succ, add_right_eq_self, comp_add, HomologicalComplex.comp_f, - HomologicalComplex.add_f_apply, comp_id] + cases n with + | zero => simp only [P_f_0_eq] + | succ n => + simp only [P_succ, comp_add, comp_id, HomologicalComplex.add_f_apply, HomologicalComplex.comp_f, + add_right_eq_self] exact (HigherFacesVanish.of_P q n).comp_Hσ_eq_zero (Nat.succ_le_iff.mp hqn) theorem Q_is_eventually_constant {q n : ℕ} (hqn : n ≤ q) : diff --git a/Mathlib/AlgebraicTopology/ExtraDegeneracy.lean b/Mathlib/AlgebraicTopology/ExtraDegeneracy.lean index 4c1705a39ed6d..4610e95420a71 100644 --- a/Mathlib/AlgebraicTopology/ExtraDegeneracy.lean +++ b/Mathlib/AlgebraicTopology/ExtraDegeneracy.lean @@ -153,7 +153,7 @@ theorem shiftFun_succ {n : ℕ} {X : Type*} [Zero X] (f : Fin n → X) (i : Fin dsimp [shiftFun] split_ifs with h · exfalso - simp only [Fin.ext_iff, Fin.val_succ, Fin.val_zero, add_eq_zero, and_false] at h + simp only [Fin.ext_iff, Fin.val_succ, Fin.val_zero, add_eq_zero, and_false, reduceCtorEq] at h · simp only [Fin.pred_succ] /-- The shift of a morphism `f : [n] → Δ` in `SimplexCategory` corresponds to @@ -282,7 +282,7 @@ theorem ExtraDegeneracy.s_comp_π_succ (n : ℕ) (i : Fin (n + 1)) : dsimp [ExtraDegeneracy.s] simp only [WidePullback.lift_π] split_ifs with h - · simp only [Fin.ext_iff, Fin.val_succ, Fin.val_zero, add_eq_zero, and_false] at h + · simp only [Fin.ext_iff, Fin.val_succ, Fin.val_zero, add_eq_zero, and_false, reduceCtorEq] at h · simp only [Fin.pred_succ] -- Porting note (#11119): @[simp] removed as the linter complains the LHS is not in normal form diff --git a/Mathlib/AlgebraicTopology/FundamentalGroupoid/PUnit.lean b/Mathlib/AlgebraicTopology/FundamentalGroupoid/PUnit.lean index 8dbe4c0998411..354d877aad6f4 100644 --- a/Mathlib/AlgebraicTopology/FundamentalGroupoid/PUnit.lean +++ b/Mathlib/AlgebraicTopology/FundamentalGroupoid/PUnit.lean @@ -33,12 +33,11 @@ instance {x y : FundamentalGroupoid PUnit} : Subsingleton (x ⟶ y) := by apply Quotient.instSubsingletonQuotient /-- Equivalence of groupoids between fundamental groupoid of punit and punit -/ -def punitEquivDiscretePUnit : FundamentalGroupoid PUnit.{u + 1} ≌ Discrete PUnit.{v + 1} := - CategoryTheory.Equivalence.mk - (Functor.star _) - ((CategoryTheory.Functor.const _).obj ⟨PUnit.unit⟩) - -- Porting note: was `by decide` - (NatIso.ofComponents fun _ => eqToIso (by simp)) - (Functor.punitExt _ _) +@[simps] +def punitEquivDiscretePUnit : FundamentalGroupoid PUnit.{u + 1} ≌ Discrete PUnit.{v + 1} where + functor := Functor.star _ + inverse := (CategoryTheory.Functor.const _).obj ⟨PUnit.unit⟩ + unitIso := NatIso.ofComponents (fun _ => Iso.refl _) + counitIso := Iso.refl _ end FundamentalGroupoid diff --git a/Mathlib/AlgebraicTopology/SimplexCategory.lean b/Mathlib/AlgebraicTopology/SimplexCategory.lean index 3003a0457ca57..1f52cf7037c0b 100644 --- a/Mathlib/AlgebraicTopology/SimplexCategory.lean +++ b/Mathlib/AlgebraicTopology/SimplexCategory.lean @@ -520,7 +520,7 @@ theorem epi_iff_surjective {n m : SimplexCategory} {f : n ⟶ m} : simp only [skeletalFunctor_obj, skeletalFunctor_map, NonemptyFinLinOrd.epi_iff_surjective, NonemptyFinLinOrd.coe_of] -/-- A monomorphism in `SimplexCategory` must increase lengths-/ +/-- A monomorphism in `SimplexCategory` must increase lengths -/ theorem len_le_of_mono {x y : SimplexCategory} {f : x ⟶ y} : Mono f → x.len ≤ y.len := by intro hyp_f_mono have f_inj : Function.Injective f.toOrderHom.toFun := mono_iff_injective.1 hyp_f_mono @@ -529,7 +529,7 @@ theorem len_le_of_mono {x y : SimplexCategory} {f : x ⟶ y} : Mono f → x.len theorem le_of_mono {n m : ℕ} {f : ([n] : SimplexCategory) ⟶ [m]} : CategoryTheory.Mono f → n ≤ m := len_le_of_mono -/-- An epimorphism in `SimplexCategory` must decrease lengths-/ +/-- An epimorphism in `SimplexCategory` must decrease lengths -/ theorem len_le_of_epi {x y : SimplexCategory} {f : x ⟶ y} : Epi f → y.len ≤ x.len := by intro hyp_f_epi have f_surj : Function.Surjective f.toOrderHom.toFun := epi_iff_surjective.1 hyp_f_epi diff --git a/Mathlib/AlgebraicTopology/SimplicialObject.lean b/Mathlib/AlgebraicTopology/SimplicialObject.lean index ac55809d6b622..4d65c1b5fcf57 100644 --- a/Mathlib/AlgebraicTopology/SimplicialObject.lean +++ b/Mathlib/AlgebraicTopology/SimplicialObject.lean @@ -5,7 +5,7 @@ Authors: Johan Commelin, Scott Morrison, Adam Topaz -/ import Mathlib.AlgebraicTopology.SimplexCategory import Mathlib.CategoryTheory.Comma.Arrow -import Mathlib.CategoryTheory.Limits.FunctorCategory +import Mathlib.CategoryTheory.Limits.FunctorCategory.Basic import Mathlib.CategoryTheory.Opposites /-! @@ -776,14 +776,15 @@ def cosimplicialToSimplicialAugmented : objects and augmented cosimplicial objects in the opposite category. -/ @[simps! functor inverse] def simplicialCosimplicialAugmentedEquiv : - (SimplicialObject.Augmented C)ᵒᵖ ≌ CosimplicialObject.Augmented Cᵒᵖ := - Equivalence.mk (simplicialToCosimplicialAugmented _) (cosimplicialToSimplicialAugmented _) - (NatIso.ofComponents (fun X => X.unop.rightOpLeftOpIso.op) fun f => by + (SimplicialObject.Augmented C)ᵒᵖ ≌ CosimplicialObject.Augmented Cᵒᵖ where + functor := simplicialToCosimplicialAugmented _ + inverse := cosimplicialToSimplicialAugmented _ + unitIso := NatIso.ofComponents (fun X => X.unop.rightOpLeftOpIso.op) fun f => by dsimp rw [← f.op_unop] simp_rw [← op_comp] congr 1 - aesop_cat) - (NatIso.ofComponents fun X => X.leftOpRightOpIso) + aesop_cat + counitIso := NatIso.ofComponents fun X => X.leftOpRightOpIso end CategoryTheory diff --git a/Mathlib/AlgebraicTopology/SplitSimplicialObject.lean b/Mathlib/AlgebraicTopology/SplitSimplicialObject.lean index c3a4875c7d176..447b1a9770800 100644 --- a/Mathlib/AlgebraicTopology/SplitSimplicialObject.lean +++ b/Mathlib/AlgebraicTopology/SplitSimplicialObject.lean @@ -208,14 +208,14 @@ structure Splitting (X : SimplicialObject C) where /-- The "inclusion" `N n ⟶ X _[n]` for all `n : ℕ`. -/ ι : ∀ n, N n ⟶ X _[n] /-- For each `Δ`, `X.obj Δ` identifies to the coproduct of the objects `N A.1.unop.len` - for all `A : IndexSet Δ`. -/ + for all `A : IndexSet Δ`. -/ isColimit' : ∀ Δ : SimplexCategoryᵒᵖ, IsColimit (Splitting.cofan' N X ι Δ) namespace Splitting variable {X Y : SimplicialObject C} (s : Splitting X) -/-- The cofan for `summand s.N Δ` induced by a splitting of a simplicial object. -/ +/-- The cofan for `summand s.N Δ` induced by a splitting of a simplicial object. -/ def cofan (Δ : SimplexCategoryᵒᵖ) : Cofan (summand s.N Δ) := Cofan.mk (X.obj Δ) (fun A => s.ι A.1.unop.len ≫ X.map A.e.op) diff --git a/Mathlib/Analysis/Analytic/Basic.lean b/Mathlib/Analysis/Analytic/Basic.lean index 2321dfb012dfd..9caab40add1e5 100644 --- a/Mathlib/Analysis/Analytic/Basic.lean +++ b/Mathlib/Analysis/Analytic/Basic.lean @@ -3,7 +3,7 @@ Copyright (c) 2020 Sébastien Gouëzel. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Sébastien Gouëzel, Yury Kudryashov -/ -import Mathlib.Algebra.Star.Order +import Mathlib.Algebra.Order.Star.Basic import Mathlib.Analysis.Calculus.FormalMultilinearSeries import Mathlib.Analysis.SpecificLimits.Normed import Mathlib.Logic.Equiv.Fin @@ -223,7 +223,7 @@ theorem lt_radius_of_isBigO (h₀ : r ≠ 0) {a : ℝ} (ha : a ∈ Ioo (-1 : ℝ norm_cast at this rw [← ENNReal.coe_lt_coe] at this refine this.trans_le (p.le_radius_of_bound C fun n => ?_) - rw [NNReal.coe_div, div_pow, ← mul_div_assoc, div_le_iff (pow_pos ha.1 n)] + rw [NNReal.coe_div, div_pow, ← mul_div_assoc, div_le_iff₀ (pow_pos ha.1 n)] exact (le_abs_self _).trans (hp n) /-- For `r` strictly smaller than the radius of `p`, then `‖pₙ‖ rⁿ` is bounded. -/ @@ -236,7 +236,7 @@ theorem norm_mul_pow_le_of_lt_radius (p : FormalMultilinearSeries 𝕜 E F) {r : theorem norm_le_div_pow_of_pos_of_lt_radius (p : FormalMultilinearSeries 𝕜 E F) {r : ℝ≥0} (h0 : 0 < r) (h : (r : ℝ≥0∞) < p.radius) : ∃ C > 0, ∀ n, ‖p n‖ ≤ C / (r : ℝ) ^ n := let ⟨C, hC, hp⟩ := p.norm_mul_pow_le_of_lt_radius h - ⟨C, hC, fun n => Iff.mpr (le_div_iff (pow_pos h0 _)) (hp n)⟩ + ⟨C, hC, fun n => Iff.mpr (le_div_iff₀ (pow_pos h0 _)) (hp n)⟩ /-- For `r` strictly smaller than the radius of `p`, then `‖pₙ‖ rⁿ` is bounded. -/ theorem nnnorm_mul_pow_le_of_lt_radius (p : FormalMultilinearSeries 𝕜 E F) {r : ℝ≥0} @@ -696,7 +696,7 @@ theorem HasFPowerSeriesOnBall.isBigO_image_sub_image_sub_deriv_principal obtain ⟨a, ha, C, hC : 0 < C, hp⟩ : ∃ a ∈ Ioo (0 : ℝ) 1, ∃ C > 0, ∀ n : ℕ, ‖p n‖ * (r' : ℝ) ^ n ≤ C * a ^ n := p.norm_mul_pow_le_mul_pow_of_lt_radius (hr.trans_le hf.r_le) - simp only [← le_div_iff (pow_pos (NNReal.coe_pos.2 hr'0) _)] at hp + simp only [← le_div_iff₀ (pow_pos (NNReal.coe_pos.2 hr'0) _)] at hp set L : E × E → ℝ := fun y => C * (a / r') ^ 2 * (‖y - (x, x)‖ * ‖y.1 - y.2‖) * (a / (1 - a) ^ 2 + 2 / (1 - a)) have hL : ∀ y ∈ EMetric.ball (x, x) r', ‖f y.1 - f y.2 - p 1 fun _ => y.1 - y.2‖ ≤ L y := by @@ -807,7 +807,7 @@ theorem HasFPowerSeriesOnBall.tendstoUniformlyOn' {r' : ℝ≥0} (hf : HasFPower (h : (r' : ℝ≥0∞) < r) : TendstoUniformlyOn (fun n y => p.partialSum n (y - x)) f atTop (Metric.ball (x : E) r') := by convert (hf.tendstoUniformlyOn h).comp fun y => y - x using 1 - · simp [(· ∘ ·)] + · simp [Function.comp_def] · ext z simp [dist_eq_norm] @@ -964,7 +964,7 @@ theorem HasFPowerSeriesAt.eq_zero {p : FormalMultilinearSeries 𝕜 𝕜 E} {x : /-- One-dimensional formal multilinear series representing the same function are equal. -/ theorem HasFPowerSeriesAt.eq_formalMultilinearSeries {p₁ p₂ : FormalMultilinearSeries 𝕜 𝕜 E} {f : 𝕜 → E} {x : 𝕜} (h₁ : HasFPowerSeriesAt f p₁ x) (h₂ : HasFPowerSeriesAt f p₂ x) : p₁ = p₂ := - sub_eq_zero.mp (HasFPowerSeriesAt.eq_zero (by simpa only [sub_self] using h₁.sub h₂)) + sub_eq_zero.mp (HasFPowerSeriesAt.eq_zero (x := x) (by simpa only [sub_self] using h₁.sub h₂)) theorem HasFPowerSeriesAt.eq_formalMultilinearSeries_of_eventually {p q : FormalMultilinearSeries 𝕜 𝕜 E} {f g : 𝕜 → E} {x : 𝕜} (hp : HasFPowerSeriesAt f p x) @@ -1041,10 +1041,10 @@ The definition is such that `p.changeOriginSeriesTerm k l s hs (fun _ ↦ x) (fu 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 := by + 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]) - exact a (p (k + l)) + a (p (k + l)) theorem changeOriginSeriesTerm_apply (k l : ℕ) (s : Finset (Fin (k + l))) (hs : s.card = l) (x y : E) : diff --git a/Mathlib/Analysis/Analytic/CPolynomial.lean b/Mathlib/Analysis/Analytic/CPolynomial.lean index 0fab892e09d2e..355c4baaf830d 100644 --- a/Mathlib/Analysis/Analytic/CPolynomial.lean +++ b/Mathlib/Analysis/Analytic/CPolynomial.lean @@ -42,10 +42,8 @@ We develop the basic properties of these notions, notably: variable {𝕜 E F G : Type*} [NontriviallyNormedField 𝕜] [NormedAddCommGroup E] [NormedSpace 𝕜 E] [NormedAddCommGroup F] [NormedSpace 𝕜 F] [NormedAddCommGroup G] [NormedSpace 𝕜 G] -open scoped Classical -open Topology NNReal Filter ENNReal - -open Set Filter Asymptotics +open scoped Classical Topology +open Set Filter Asymptotics NNReal ENNReal variable {f g : E → F} {p pf pg : FormalMultilinearSeries 𝕜 E F} {x : E} {r r' : ℝ≥0∞} {n m : ℕ} @@ -347,7 +345,8 @@ protected theorem FormalMultilinearSeries.sum_of_finite (p : FormalMultilinearSe protected theorem FormalMultilinearSeries.hasSum_of_finite (p : FormalMultilinearSeries 𝕜 E F) {n : ℕ} (hn : ∀ m, n ≤ m → p m = 0) (x : E) : HasSum (fun n : ℕ => p n fun _ => x) (p.sum x) := - summable_of_ne_finset_zero (fun m hm ↦ by rw [Finset.mem_range, not_lt] at hm; rw [hn m hm]; rfl) + summable_of_ne_finset_zero (s := .range n) + (fun m hm ↦ by rw [Finset.mem_range, not_lt] at hm; rw [hn m hm]; rfl) |>.hasSum /-- The sum of a finite power series `p` admits `p` as a power series. -/ @@ -382,7 +381,7 @@ main point is that the new series `p.changeOrigin x` is still finite, with the s variable (p : FormalMultilinearSeries 𝕜 E F) {x y : E} {r R : ℝ≥0} /-- If `p` is a formal multilinear series such that `p m = 0` for `n ≤ m`, then -`p.changeOriginSeriesTerm k l = 0` for `n ≤ k + l`. -/ +`p.changeOriginSeriesTerm k l = 0` for `n ≤ k + l`. -/ lemma changeOriginSeriesTerm_bound (p : FormalMultilinearSeries 𝕜 E F) {n : ℕ} (hn : ∀ (m : ℕ), n ≤ m → p m = 0) (k l : ℕ) {s : Finset (Fin (k + l))} (hs : s.card = l) (hkl : n ≤ k + l) : @@ -394,7 +393,7 @@ lemma changeOriginSeriesTerm_bound (p : FormalMultilinearSeries 𝕜 E F) {n : /-- If `p` is a finite formal multilinear series, then so is `p.changeOriginSeries k` for every `k` in `ℕ`. More precisely, if `p m = 0` for `n ≤ m`, then `p.changeOriginSeries k m = 0` for -`n ≤ k + m`. -/ +`n ≤ k + m`. -/ lemma changeOriginSeries_finite_of_finite (p : FormalMultilinearSeries 𝕜 E F) {n : ℕ} (hn : ∀ (m : ℕ), n ≤ m → p m = 0) (k : ℕ) : ∀ {m : ℕ}, n ≤ k + m → p.changeOriginSeries k m = 0 := by @@ -414,7 +413,7 @@ lemma changeOriginSeries_sum_eq_partialSum_of_finite (p : FormalMultilinearSerie ContinuousMultilinearMap.zero_apply] /-- If `p` is a formal multilinear series such that `p m = 0` for `n ≤ m`, then -`p.changeOrigin x k = 0` for `n ≤ k`. -/ +`p.changeOrigin x k = 0` for `n ≤ k`. -/ lemma changeOrigin_finite_of_finite (p : FormalMultilinearSeries 𝕜 E F) {n : ℕ} (hn : ∀ (m : ℕ), n ≤ m → p m = 0) {k : ℕ} (hk : n ≤ k) : p.changeOrigin x k = 0 := by diff --git a/Mathlib/Analysis/Analytic/Composition.lean b/Mathlib/Analysis/Analytic/Composition.lean index 5cf9bd1117d0b..2267a001aa658 100644 --- a/Mathlib/Analysis/Analytic/Composition.lean +++ b/Mathlib/Analysis/Analytic/Composition.lean @@ -419,7 +419,7 @@ theorem id_comp (p : FormalMultilinearSeries 𝕜 E F) (h : p 0 = 0) : (id 𝕜 rfl · simp -/-! ### Summability properties of the composition of formal power series-/ +/-! ### Summability properties of the composition of formal power series -/ section @@ -856,7 +856,7 @@ where `v' = (v_l, v_{l+1}, ..., v_{m-1})`. Therefore, we get r.comp (q.comp p) n v = ∑_{c : Composition n} ∑_{d₀ : Composition (c.blocksFun 0), ..., d_{c.length - 1} : Composition (c.blocksFun (c.length - 1))} - r c.length (λ i, q dᵢ.length (applyComposition p dᵢ v'ᵢ)) + r c.length (fun i ↦ q dᵢ.length (applyComposition p dᵢ v'ᵢ)) ``` To show that these terms coincide, we need to explain how to reindex the sums to put them in bijection (and then the terms we are summing will correspond to each other). Suppose we have a @@ -1029,7 +1029,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 @@ -1086,7 +1086,7 @@ def sigmaEquivSigmaPi (n : ℕ) : -- but we need to massage it to take care of the dependent setting. rintro ⟨c, d⟩ have : map List.sum (ofFn fun i : Fin (Composition.length c) => (d i).blocks) = c.blocks := by - simp [map_ofFn, (· ∘ ·), Composition.blocks_sum, Composition.ofFn_blocksFun] + simp [map_ofFn, Function.comp_def, Composition.blocks_sum, Composition.ofFn_blocksFun] rw [sigma_pi_composition_eq_iff] dsimp congr! 1 diff --git a/Mathlib/Analysis/Analytic/Constructions.lean b/Mathlib/Analysis/Analytic/Constructions.lean index 9f74981f7a02e..b66134ef40759 100644 --- a/Mathlib/Analysis/Analytic/Constructions.lean +++ b/Mathlib/Analysis/Analytic/Constructions.lean @@ -19,10 +19,8 @@ We show that the following are analytic: noncomputable section -open scoped Classical -open Topology NNReal Filter ENNReal - -open Set Filter Asymptotics +open scoped Classical Topology +open Filter Asymptotics ENNReal NNReal variable {α : Type*} variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] diff --git a/Mathlib/Analysis/Analytic/Inverse.lean b/Mathlib/Analysis/Analytic/Inverse.lean index 704910afccb1c..ccd47d8263a54 100644 --- a/Mathlib/Analysis/Analytic/Inverse.lean +++ b/Mathlib/Analysis/Analytic/Inverse.lean @@ -137,7 +137,7 @@ theorem leftInv_comp (p : FormalMultilinearSeries 𝕜 E F) (i : E ≃L[𝕜] F) ext c congr ext k - simp [h, Function.comp] + simp [h, Function.comp_def] simp [FormalMultilinearSeries.comp, show n + 2 ≠ 1 by omega, A, Finset.sum_union B, applyComposition_ones, C, D, -Set.toFinset_setOf] diff --git a/Mathlib/Analysis/Analytic/IsolatedZeros.lean b/Mathlib/Analysis/Analytic/IsolatedZeros.lean index 720708a18aa23..5646e3721fa72 100644 --- a/Mathlib/Analysis/Analytic/IsolatedZeros.lean +++ b/Mathlib/Analysis/Analytic/IsolatedZeros.lean @@ -105,7 +105,7 @@ theorem locally_ne_zero (hp : HasFPowerSeriesAt f p z₀) (h : p ≠ 0) : ∀ᶠ simpa [e1, e2, e3] using pow_ne_zero p.order (sub_ne_zero.mpr e3) theorem locally_zero_iff (hp : HasFPowerSeriesAt f p z₀) : (∀ᶠ z in 𝓝 z₀, f z = 0) ↔ p = 0 := - ⟨fun hf => hp.eq_zero_of_eventually hf, fun h => eventually_eq_zero (by rwa [h] at hp)⟩ + ⟨fun hf => hp.eq_zero_of_eventually hf, fun h => eventually_eq_zero (𝕜 := 𝕜) (by rwa [h] at hp)⟩ end HasFPowerSeriesAt diff --git a/Mathlib/Analysis/Analytic/Linear.lean b/Mathlib/Analysis/Analytic/Linear.lean index f7afb9b160fc2..6bd87d9e23035 100644 --- a/Mathlib/Analysis/Analytic/Linear.lean +++ b/Mathlib/Analysis/Analytic/Linear.lean @@ -12,7 +12,6 @@ In this file we prove that a `ContinuousLinearMap` defines an analytic function the formal power series `f x = f a + f (x - a)`. We also prove similar results for multilinear maps. -/ - variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] {F : Type*} [NormedAddCommGroup F] [NormedSpace 𝕜 F] {G : Type*} [NormedAddCommGroup G] [NormedSpace 𝕜 G] diff --git a/Mathlib/Analysis/Analytic/Meromorphic.lean b/Mathlib/Analysis/Analytic/Meromorphic.lean index 12ec5f6379e2c..ff3b72d9bc1a5 100644 --- a/Mathlib/Analysis/Analytic/Meromorphic.lean +++ b/Mathlib/Analysis/Analytic/Meromorphic.lean @@ -142,6 +142,23 @@ lemma zpow {f : 𝕜 → 𝕜} {x : 𝕜} (hf : MeromorphicAt f x) (n : ℤ) : M | ofNat m => simpa only [Int.ofNat_eq_coe, zpow_natCast] using hf.pow m | negSucc m => simpa only [zpow_negSucc, inv_iff] using hf.pow (m + 1) +theorem eventually_analyticAt [CompleteSpace E] {f : 𝕜 → E} {x : 𝕜} + (h : MeromorphicAt f x) : ∀ᶠ y in 𝓝[≠] x, AnalyticAt 𝕜 f y := by + rw [MeromorphicAt] at h + obtain ⟨n, h⟩ := h + apply AnalyticAt.eventually_analyticAt at h + refine (h.filter_mono ?_).mp ?_ + · simp [nhdsWithin] + · rw [eventually_nhdsWithin_iff] + apply Filter.Eventually.of_forall + intro y hy hf + rw [Set.mem_compl_iff, Set.mem_singleton_iff] at hy + have := (((analyticAt_id 𝕜 y).sub analyticAt_const).pow n).inv + (pow_ne_zero _ (sub_ne_zero_of_ne hy)) + apply (this.smul hf).congr ∘ (eventually_ne_nhds hy).mono + intro z hz + simp [smul_smul, hz, sub_eq_zero] + /-- The order of vanishing of a meromorphic function, as an element of `ℤ ∪ ∞` (to include the case of functions identically 0 near `x`). -/ noncomputable def order {f : 𝕜 → E} {x : 𝕜} (hf : MeromorphicAt f x) : WithTop ℤ := @@ -281,4 +298,14 @@ lemma congr (h_eq : Set.EqOn f g U) (hu : IsOpen U) : MeromorphicOn g U := by refine fun x hx ↦ (hf x hx).congr (EventuallyEq.filter_mono ?_ nhdsWithin_le_nhds) exact eventually_of_mem (hu.mem_nhds hx) h_eq +theorem eventually_codiscreteWithin_analyticAt + [CompleteSpace E] (f : 𝕜 → E) (h : MeromorphicOn f U) : + ∀ᶠ (y : 𝕜) in codiscreteWithin U, AnalyticAt 𝕜 f y := by + rw [eventually_iff, mem_codiscreteWithin] + intro x hx + rw [disjoint_principal_right] + apply Filter.mem_of_superset ((h x hx).eventually_analyticAt) + intro x hx + simp [hx] + end MeromorphicOn diff --git a/Mathlib/Analysis/Analytic/Within.lean b/Mathlib/Analysis/Analytic/Within.lean index a35cbce9538cf..d8c30c30b6b97 100644 --- a/Mathlib/Analysis/Analytic/Within.lean +++ b/Mathlib/Analysis/Analytic/Within.lean @@ -9,7 +9,7 @@ import Mathlib.Analysis.Calculus.FDeriv.Analytic /-! # Properties of analyticity restricted to a set -From `Mathlib.Analysis.Analytic.Basic`, we have the definitons +From `Mathlib.Analysis.Analytic.Basic`, we have the definitions 1. `AnalyticWithinAt 𝕜 f s x` means a power series at `x` converges to `f` on `𝓝[s] x`, and `f` is continuous within `s` at `x`. diff --git a/Mathlib/Analysis/Asymptotics/Asymptotics.lean b/Mathlib/Analysis/Asymptotics/Asymptotics.lean index f97d8a1772783..47518d245fd96 100644 --- a/Mathlib/Analysis/Asymptotics/Asymptotics.lean +++ b/Mathlib/Analysis/Asymptotics/Asymptotics.lean @@ -3,6 +3,7 @@ Copyright (c) 2019 Jeremy Avigad. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad, Yury Kudryashov -/ +import Mathlib.Analysis.Normed.Group.Bounded import Mathlib.Analysis.Normed.Group.InfiniteSum import Mathlib.Analysis.Normed.MulAction import Mathlib.Topology.Algebra.Order.LiminfLimsup @@ -44,11 +45,8 @@ it suffices to assume that `f` is zero wherever `g` is. (This generalization is the Fréchet derivative.) -/ - -open Filter Set - open scoped Classical -open Topology Filter NNReal +open Set Topology Filter NNReal namespace Asymptotics @@ -236,7 +234,7 @@ theorem IsBigO.exists_mem_basis {ι} {p : ι → Prop} {s : ι → Set α} (h : simpa only [isBigOWith_iff, hb.eventually_iff, exists_prop] using h theorem isBigOWith_inv (hc : 0 < c) : IsBigOWith c⁻¹ l f g ↔ ∀ᶠ x in l, c * ‖f x‖ ≤ ‖g x‖ := by - simp only [IsBigOWith_def, ← div_eq_inv_mul, le_div_iff' hc] + simp only [IsBigOWith_def, ← div_eq_inv_mul, le_div_iff₀' hc] -- We prove this lemma with strange assumptions to get two lemmas below automatically theorem isLittleO_iff_nat_mul_le_aux (h₀ : (∀ x, 0 ≤ ‖f x‖) ∨ ∀ x, 0 ≤ ‖g x‖) : @@ -823,6 +821,46 @@ theorem IsLittleO.prod_rightr (h : f =o[l] g') : f =o[l] fun x => (f' x, g' x) : end +section + +variable {f : α × β → E} {g : α × β → F} {l' : Filter β} + +protected theorem IsBigO.fiberwise_right : + f =O[l ×ˢ l'] g → ∀ᶠ a in l, (f ⟨a, ·⟩) =O[l'] (g ⟨a, ·⟩) := by + simp only [isBigO_iff, eventually_iff, mem_prod_iff] + rintro ⟨c, t₁, ht₁, t₂, ht₂, ht⟩ + exact mem_of_superset ht₁ fun _ ha ↦ ⟨c, mem_of_superset ht₂ fun _ hb ↦ ht ⟨ha, hb⟩⟩ + +protected theorem IsBigO.fiberwise_left : + f =O[l ×ˢ l'] g → ∀ᶠ b in l', (f ⟨·, b⟩) =O[l] (g ⟨·, b⟩) := by + simp only [isBigO_iff, eventually_iff, mem_prod_iff] + rintro ⟨c, t₁, ht₁, t₂, ht₂, ht⟩ + exact mem_of_superset ht₂ fun _ hb ↦ ⟨c, mem_of_superset ht₁ fun _ ha ↦ ht ⟨ha, hb⟩⟩ + +end + +section + +variable (l' : Filter β) + +protected theorem IsBigO.comp_fst : f =O[l] g → (f ∘ Prod.fst) =O[l ×ˢ l'] (g ∘ Prod.fst) := by + simp only [isBigO_iff, eventually_prod_iff] + exact fun ⟨c, hc⟩ ↦ ⟨c, _, hc, fun _ ↦ True, eventually_true l', fun {_} h {_} _ ↦ h⟩ + +protected theorem IsBigO.comp_snd : f =O[l] g → (f ∘ Prod.snd) =O[l' ×ˢ l] (g ∘ Prod.snd) := by + simp only [isBigO_iff, eventually_prod_iff] + exact fun ⟨c, hc⟩ ↦ ⟨c, fun _ ↦ True, eventually_true l', _, hc, fun _ ↦ id⟩ + +protected theorem IsLittleO.comp_fst : f =o[l] g → (f ∘ Prod.fst) =o[l ×ˢ l'] (g ∘ Prod.fst) := by + simp only [isLittleO_iff, eventually_prod_iff] + exact fun h _ hc ↦ ⟨_, h hc, fun _ ↦ True, eventually_true l', fun {_} h {_} _ ↦ h⟩ + +protected theorem IsLittleO.comp_snd : f =o[l] g → (f ∘ Prod.snd) =o[l' ×ˢ l] (g ∘ Prod.snd) := by + simp only [isLittleO_iff, eventually_prod_iff] + exact fun h _ hc ↦ ⟨fun _ ↦ True, eventually_true l', _, h hc, fun _ ↦ id⟩ + +end + theorem IsBigOWith.prod_left_same (hf : IsBigOWith c l f' k') (hg : IsBigOWith c l g' k') : IsBigOWith c l (fun x => (f' x, g' x)) k' := by rw [isBigOWith_iff] at *; filter_upwards [hf, hg] with x using max_le @@ -1190,7 +1228,7 @@ theorem isBigO_iff_isBoundedUnder_le_div (h : ∀ᶠ x in l, g'' x ≠ 0) : simp only [isBigO_iff, IsBoundedUnder, IsBounded, eventually_map] exact exists_congr fun c => - eventually_congr <| h.mono fun x hx => (div_le_iff <| norm_pos_iff.2 hx).symm + eventually_congr <| h.mono fun x hx => (div_le_iff₀ <| norm_pos_iff.2 hx).symm /-- `(fun x ↦ c) =O[l] f` if and only if `f` is bounded away from zero. -/ theorem isBigO_const_left_iff_pos_le_norm {c : E''} (hc : c ≠ 0) : @@ -1199,7 +1237,7 @@ theorem isBigO_const_left_iff_pos_le_norm {c : E''} (hc : c ≠ 0) : · intro h rcases h.exists_pos with ⟨C, hC₀, hC⟩ refine ⟨‖c‖ / C, div_pos (norm_pos_iff.2 hc) hC₀, ?_⟩ - exact hC.bound.mono fun x => (div_le_iff' hC₀).2 + exact hC.bound.mono fun x => (div_le_iff₀' hC₀).2 · rintro ⟨b, hb₀, hb⟩ refine IsBigO.of_bound (‖c‖ / b) (hb.mono fun x hx => ?_) rw [div_mul_eq_mul_div, mul_div_assoc] @@ -1410,7 +1448,7 @@ theorem IsBigOWith.inv_rev {f : α → 𝕜} {g : α → 𝕜'} (h : IsBigOWith · 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 - simpa only [norm_inv, mul_inv, ← div_eq_inv_mul, div_le_iff hc] using 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) (h₀ : ∀ᶠ x in l, f x = 0 → g x = 0) : (fun x => (g x)⁻¹) =O[l] fun x => (f x)⁻¹ := @@ -1714,7 +1752,7 @@ theorem isBigO_iff_div_isBoundedUnder {α : Type*} {l : Filter α} {f g : α → refine IsBigO.of_bound c (hc.mp <| hgf.mono fun x hx₁ hx₂ => ?_) by_cases hgx : g x = 0 · simp [hx₁ hgx, hgx] - · exact (div_le_iff (norm_pos_iff.2 hgx)).mp hx₂ + · exact (div_le_iff₀ (norm_pos_iff.2 hgx)).mp hx₂ theorem isBigO_of_div_tendsto_nhds {α : Type*} {l : Filter α} {f g : α → 𝕜} (hgf : ∀ᶠ x in l, g x = 0 → f x = 0) (c : 𝕜) (H : Filter.Tendsto (f / g) l (𝓝 c)) : @@ -1775,7 +1813,7 @@ theorem IsBigOWith.right_le_sub_of_lt_one {f₁ f₂ : α → E'} (h : IsBigOWit IsBigOWith.of_bound <| mem_of_superset h.bound fun x hx => by simp only [mem_setOf_eq] at hx ⊢ - rw [mul_comm, one_div, ← div_eq_mul_inv, _root_.le_div_iff, mul_sub, mul_one, mul_comm] + rw [mul_comm, one_div, ← div_eq_mul_inv, le_div_iff₀, mul_sub, mul_one, mul_comm] · exact le_trans (sub_le_sub_left hx _) (norm_sub_norm_le _ _) · exact sub_pos.2 hc @@ -1812,7 +1850,7 @@ theorem bound_of_isBigO_cofinite (h : f =O[cofinite] g'') : have : ∀ x, C * ‖g'' x‖ < ‖f x‖ → ‖f x‖ / ‖g'' x‖ ≤ C' := by simpa using hC' refine ⟨max C C', lt_max_iff.2 (Or.inl C₀), fun x h₀ => ?_⟩ rw [max_mul_of_nonneg _ _ (norm_nonneg _), le_max_iff, or_iff_not_imp_left, not_le] - exact fun hx => (div_le_iff (norm_pos_iff.2 h₀)).1 (this _ hx) + exact fun hx => (div_le_iff₀ (norm_pos_iff.2 h₀)).1 (this _ hx) theorem isBigO_cofinite_iff (h : ∀ x, g'' x = 0 → f'' x = 0) : f'' =O[cofinite] g'' ↔ ∃ C, ∀ x, ‖f'' x‖ ≤ C * ‖g'' x‖ := @@ -1952,3 +1990,52 @@ theorem isLittleO_congr (e : α ≃ₜ β) {b : β} {f : β → E} {g : β → F exact forall₂_congr fun c _hc => e.isBigOWith_congr end Homeomorph + +namespace ContinuousOn + +variable {α E F : Type*} [TopologicalSpace α] {s : Set α} {f : α → E} {c : F} + +section IsBigO + +variable [SeminormedAddGroup E] [Norm F] + +protected theorem isBigOWith_principal + (hf : ContinuousOn f s) (hs : IsCompact s) (hc : ‖c‖ ≠ 0) : + IsBigOWith (sSup (Norm.norm '' (f '' s)) / ‖c‖) (𝓟 s) f fun _ => c := by + rw [isBigOWith_principal, div_mul_cancel₀ _ hc] + exact fun x hx ↦ hs.image_of_continuousOn hf |>.image continuous_norm + |>.isLUB_sSup (Set.image_nonempty.mpr <| Set.image_nonempty.mpr ⟨x, hx⟩) + |>.left <| Set.mem_image_of_mem _ <| Set.mem_image_of_mem _ hx + +protected theorem isBigO_principal (hf : ContinuousOn f s) (hs : IsCompact s) + (hc : ‖c‖ ≠ 0) : f =O[𝓟 s] fun _ => c := + (hf.isBigOWith_principal hs hc).isBigO + +end IsBigO + +section IsBigORev + +variable [NormedAddGroup E] [SeminormedAddGroup F] + +protected theorem isBigOWith_rev_principal + (hf : ContinuousOn f s) (hs : IsCompact s) (hC : ∀ i ∈ s, f i ≠ 0) (c : F) : + IsBigOWith (‖c‖ / sInf (Norm.norm '' (f '' s))) (𝓟 s) (fun _ => c) f := by + refine isBigOWith_principal.mpr fun x hx ↦ ?_ + rw [mul_comm_div] + replace hs := hs.image_of_continuousOn hf |>.image continuous_norm + have h_sInf := hs.isGLB_sInf <| Set.image_nonempty.mpr <| Set.image_nonempty.mpr ⟨x, hx⟩ + refine le_mul_of_one_le_right (norm_nonneg c) <| (one_le_div ?_).mpr <| + h_sInf.1 <| Set.mem_image_of_mem _ <| Set.mem_image_of_mem _ hx + obtain ⟨_, ⟨x, hx, hCx⟩, hnormCx⟩ := hs.sInf_mem h_sInf.nonempty + rw [← hnormCx, ← hCx] + exact (norm_ne_zero_iff.mpr (hC x hx)).symm.lt_of_le (norm_nonneg _) + +protected theorem isBigO_rev_principal (hf : ContinuousOn f s) + (hs : IsCompact s) (hC : ∀ i ∈ s, f i ≠ 0) (c : F) : (fun _ => c) =O[𝓟 s] f := + (hf.isBigOWith_rev_principal hs hC c).isBigO + +end IsBigORev + +end ContinuousOn + +set_option linter.style.longFile 2200 diff --git a/Mathlib/Analysis/Asymptotics/SpecificAsymptotics.lean b/Mathlib/Analysis/Asymptotics/SpecificAsymptotics.lean index a0281a8808ecb..200ac13ef97fb 100644 --- a/Mathlib/Analysis/Asymptotics/SpecificAsymptotics.lean +++ b/Mathlib/Analysis/Asymptotics/SpecificAsymptotics.lean @@ -27,7 +27,7 @@ theorem Filter.IsBoundedUnder.isLittleO_sub_self_inv {𝕜 E : Type*} [NormedFie {f : 𝕜 → E} (h : IsBoundedUnder (· ≤ ·) (𝓝[≠] a) (norm ∘ f)) : f =o[𝓝[≠] a] fun x => (x - a)⁻¹ := by refine (h.isBigO_const (one_ne_zero' ℝ)).trans_isLittleO (isLittleO_const_left.2 <| Or.inr ?_) - simp only [(· ∘ ·), norm_inv] + simp only [Function.comp_def, norm_inv] exact (tendsto_norm_sub_self_punctured_nhds a).inv_tendsto_zero end NormedField diff --git a/Mathlib/Analysis/Asymptotics/Theta.lean b/Mathlib/Analysis/Asymptotics/Theta.lean index ab9b0e2af090e..7b78a91770b61 100644 --- a/Mathlib/Analysis/Asymptotics/Theta.lean +++ b/Mathlib/Analysis/Asymptotics/Theta.lean @@ -131,6 +131,9 @@ instance : Trans (α := α → E) (β := α → E) (γ := α → F) (EventuallyE lemma _root_.Filter.EventuallyEq.isTheta {f g : α → E} (h : f =ᶠ[l] g) : f =Θ[l] g := h.trans_isTheta isTheta_rfl +@[simp] +theorem isTheta_bot : f =Θ[⊥] g := by simp [IsTheta] + @[simp] theorem isTheta_norm_left : (fun x ↦ ‖f' x‖) =Θ[l] g ↔ f' =Θ[l] g := by simp [IsTheta] @@ -185,7 +188,8 @@ theorem IsTheta.tendsto_zero_iff (h : f'' =Θ[l] g'') : theorem IsTheta.tendsto_norm_atTop_iff (h : f' =Θ[l] g') : Tendsto (norm ∘ f') l atTop ↔ Tendsto (norm ∘ g') l atTop := by - simp only [Function.comp, ← isLittleO_const_left_of_ne (one_ne_zero' ℝ), h.isLittleO_congr_right] + simp only [Function.comp_def, ← isLittleO_const_left_of_ne (one_ne_zero' ℝ), + h.isLittleO_congr_right] theorem IsTheta.isBoundedUnder_le_iff (h : f' =Θ[l] g') : IsBoundedUnder (· ≤ ·) l (norm ∘ f') ↔ IsBoundedUnder (· ≤ ·) l (norm ∘ g') := by @@ -280,4 +284,46 @@ lemma IsLittleO.add_isTheta {f₁ f₂ : α → E'} {g : α → F} (ho : f₁ =o[l] g) (hΘ : f₂ =Θ[l] g) : (f₁ + f₂) =Θ[l] g := add_comm f₁ f₂ ▸ hΘ.add_isLittleO ho +section + +variable {f : α × β → E} {g : α × β → F} {l' : Filter β} + +protected theorem IsTheta.fiberwise_right : + f =Θ[l ×ˢ l'] g → ∀ᶠ x in l, (f ⟨x, ·⟩) =Θ[l'] (g ⟨x, ·⟩) := by + simp only [IsTheta, eventually_and] + exact fun ⟨h₁, h₂⟩ ↦ ⟨h₁.fiberwise_right, h₂.fiberwise_right⟩ + +protected theorem IsTheta.fiberwise_left : + f =Θ[l ×ˢ l'] g → ∀ᶠ y in l', (f ⟨·, y⟩) =Θ[l] (g ⟨·, y⟩) := by + simp only [IsTheta, eventually_and] + exact fun ⟨h₁, h₂⟩ ↦ ⟨h₁.fiberwise_left, h₂.fiberwise_left⟩ + +end + +section + +variable (l' : Filter β) + +protected theorem IsTheta.comp_fst : f =Θ[l] g → (f ∘ Prod.fst) =Θ[l ×ˢ l'] (g ∘ Prod.fst) := by + simp only [IsTheta, eventually_and] + exact fun ⟨h₁, h₂⟩ ↦ ⟨h₁.comp_fst l', h₂.comp_fst l'⟩ + +protected theorem IsTheta.comp_snd : f =Θ[l] g → (f ∘ Prod.snd) =Θ[l' ×ˢ l] (g ∘ Prod.snd) := by + simp only [IsTheta, eventually_and] + exact fun ⟨h₁, h₂⟩ ↦ ⟨h₁.comp_snd l', h₂.comp_snd l'⟩ + +end + end Asymptotics + +namespace ContinuousOn + +variable {α E F : Type*} [NormedAddGroup E] [SeminormedAddGroup F] [TopologicalSpace α] + {s : Set α} {f : α → E} {c : F} + +protected theorem isTheta_principal + (hf : ContinuousOn f s) (hs : IsCompact s) (hc : ‖c‖ ≠ 0) (hC : ∀ i ∈ s, f i ≠ 0) : + f =Θ[𝓟 s] fun _ => c := + ⟨hf.isBigO_principal hs hc, hf.isBigO_rev_principal hs hC c⟩ + +end ContinuousOn diff --git a/Mathlib/Analysis/BoundedVariation.lean b/Mathlib/Analysis/BoundedVariation.lean index fb2d9051dd7aa..dd6942a44733b 100644 --- a/Mathlib/Analysis/BoundedVariation.lean +++ b/Mathlib/Analysis/BoundedVariation.lean @@ -192,7 +192,7 @@ protected theorem lowerSemicontinuous (s : Set α) : simpa only [UniformOnFun.tendsto_iff_tendstoUniformlyOn, mem_image, forall_exists_index, and_imp, forall_apply_eq_imp_iff₂, tendstoUniformlyOn_singleton_iff_tendsto] using @tendsto_id _ (𝓝 f) -/-- The map `(eVariationOn · s)` is lower semicontinuous for uniform convergence on `s`. -/ +/-- The map `(eVariationOn · s)` is lower semicontinuous for uniform convergence on `s`. -/ theorem lowerSemicontinuous_uniformOn (s : Set α) : LowerSemicontinuous fun f : α →ᵤ[{s}] E => eVariationOn f s := fun f ↦ by apply @lowerSemicontinuous_aux _ _ _ _ (UniformOnFun α E {s}) id (𝓝 f) f s _ @@ -766,12 +766,12 @@ theorem LipschitzOnWith.comp_locallyBoundedVariationOn {f : E → F} {C : ℝ≥ theorem LipschitzWith.comp_boundedVariationOn {f : E → F} {C : ℝ≥0} (hf : LipschitzWith C f) {g : α → E} {s : Set α} (h : BoundedVariationOn g s) : BoundedVariationOn (f ∘ g) s := - (hf.lipschitzOnWith univ).comp_boundedVariationOn (mapsTo_univ _ _) h + hf.lipschitzOnWith.comp_boundedVariationOn (mapsTo_univ _ _) h theorem LipschitzWith.comp_locallyBoundedVariationOn {f : E → F} {C : ℝ≥0} (hf : LipschitzWith C f) {g : α → E} {s : Set α} (h : LocallyBoundedVariationOn g s) : LocallyBoundedVariationOn (f ∘ g) s := - (hf.lipschitzOnWith univ).comp_locallyBoundedVariationOn (mapsTo_univ _ _) h + hf.lipschitzOnWith.comp_locallyBoundedVariationOn (mapsTo_univ _ _) h theorem LipschitzOnWith.locallyBoundedVariationOn {f : ℝ → E} {C : ℝ≥0} {s : Set ℝ} (hf : LipschitzOnWith C f s) : LocallyBoundedVariationOn f s := @@ -780,7 +780,7 @@ theorem LipschitzOnWith.locallyBoundedVariationOn {f : ℝ → E} {C : ℝ≥0} theorem LipschitzWith.locallyBoundedVariationOn {f : ℝ → E} {C : ℝ≥0} (hf : LipschitzWith C f) (s : Set ℝ) : LocallyBoundedVariationOn f s := - (hf.lipschitzOnWith s).locallyBoundedVariationOn + hf.lipschitzOnWith.locallyBoundedVariationOn end LipschitzOnWith diff --git a/Mathlib/Analysis/BoxIntegral/Basic.lean b/Mathlib/Analysis/BoxIntegral/Basic.lean index 1cb018280092e..e9d54c402baef 100644 --- a/Mathlib/Analysis/BoxIntegral/Basic.lean +++ b/Mathlib/Analysis/BoxIntegral/Basic.lean @@ -184,7 +184,7 @@ theorem hasIntegral_iff : HasIntegral I l f vol y ↔ simp [@forall_swap ℝ≥0 (TaggedPrepartition I)] /-- Quite often it is more natural to prove an estimate of the form `a * ε`, not `ε` in the RHS of -`BoxIntegral.hasIntegral_iff`, so we provide this auxiliary lemma. -/ +`BoxIntegral.hasIntegral_iff`, so we provide this auxiliary lemma. -/ theorem HasIntegral.of_mul (a : ℝ) (h : ∀ ε : ℝ, 0 < ε → ∃ r : ℝ≥0 → ℝⁿ → Ioi (0 : ℝ), (∀ c, l.RCond (r c)) ∧ ∀ c π, l.MemBaseSet I c (r c) π → IsPartition π → dist (integralSum f vol π) y ≤ a * ε) : @@ -391,7 +391,7 @@ additional distortion estimates if `BoxIntegral.IntegrationParams.bDistortion l corresponding integral sum is `ε`-close to the integral. If `BoxIntegral.IntegrationParams.bRiemann = true`, then `r c x` does not depend on `x`. If -`ε ≤ 0`, then we use `r c x = 1`. -/ +`ε ≤ 0`, then we use `r c x = 1`. -/ def convergenceR (h : Integrable I l f vol) (ε : ℝ) : ℝ≥0 → ℝⁿ → Ioi (0 : ℝ) := if hε : 0 < ε then (hasIntegral_iff.1 h.hasIntegral ε hε).choose else fun _ _ => ⟨1, Set.mem_Ioi.2 zero_lt_one⟩ @@ -447,7 +447,7 @@ theorem dist_integralSum_le_of_memBaseSet (h : Integrable I l f vol) (hpos₁ : /-- If `f` is integrable on `I` along `l`, then for two sufficiently fine tagged prepartitions (in the sense of the filter `BoxIntegral.IntegrationParams.toFilter l I`) such that they cover -the same part of `I`, the integral sums of `f` over `π₁` and `π₂` are very close to each other. -/ +the same part of `I`, the integral sums of `f` over `π₁` and `π₂` are very close to each other. -/ theorem tendsto_integralSum_toFilter_prod_self_inf_iUnion_eq_uniformity (h : Integrable I l f vol) : Tendsto (fun π : TaggedPrepartition I × TaggedPrepartition I => (integralSum f vol π.1, integralSum f vol π.2)) @@ -779,7 +779,7 @@ theorem HasIntegral.of_bRiemann_eq_false_of_forall_isLittleO (hl : l.bRiemann = choose! δ₂ Hδ₂ using H₂ have ε0' := half_pos ε0; have H0 : 0 < (2 : ℝ) ^ Fintype.card ι := pow_pos zero_lt_two _ rcases hs.exists_pos_forall_sum_le (div_pos ε0' H0) with ⟨εs, hεs0, hεs⟩ - simp only [le_div_iff' H0, mul_sum] at hεs + simp only [le_div_iff₀' H0, mul_sum] at hεs rcases exists_pos_mul_lt ε0' (B I) with ⟨ε', ε'0, hεI⟩ classical set δ : ℝ≥0 → ℝⁿ → Ioi (0 : ℝ) := fun c x => if x ∈ s then δ₁ c x (εs x) else (δ₂ c) x ε' diff --git a/Mathlib/Analysis/BoxIntegral/Box/Basic.lean b/Mathlib/Analysis/BoxIntegral/Box/Basic.lean index 957bfe293bc0b..91269631ab2c4 100644 --- a/Mathlib/Analysis/BoxIntegral/Box/Basic.lean +++ b/Mathlib/Analysis/BoxIntegral/Box/Basic.lean @@ -51,13 +51,11 @@ that returns the box `⟨l, u, _⟩` if it is nonempty and `⊥` otherwise. rectangular box -/ - open Set Function Metric Filter noncomputable section -open scoped Classical -open NNReal Topology +open scoped Classical NNReal Topology namespace BoxIntegral @@ -92,7 +90,7 @@ theorem lower_ne_upper (i) : I.lower i ≠ I.upper i := (I.lower_lt_upper i).ne instance : Membership (ι → ℝ) (Box ι) := - ⟨fun x I ↦ ∀ i, x i ∈ Ioc (I.lower i) (I.upper i)⟩ + ⟨fun I x ↦ ∀ i, x i ∈ Ioc (I.lower i) (I.upper i)⟩ -- Porting note: added /-- The set of points in this box: this is the product of half-open intervals `(lower i, upper i]`, @@ -277,7 +275,7 @@ theorem withBotCoe_inj {I J : WithBot (Box ι)} : (I : Set (ι → ℝ)) = J ↔ /-- Make a `WithBot (Box ι)` from a pair of corners `l u : ι → ℝ`. If `l i < u i` for all `i`, then the result is `⟨l, u, _⟩ : Box ι`, otherwise it is `⊥`. In any case, the result interpreted -as a set in `ι → ℝ` is the set `{x : ι → ℝ | ∀ i, x i ∈ Ioc (l i) (u i)}`. -/ +as a set in `ι → ℝ` is the set `{x : ι → ℝ | ∀ i, x i ∈ Ioc (l i) (u i)}`. -/ def mk' (l u : ι → ℝ) : WithBot (Box ι) := if h : ∀ i, l i < u i then ↑(⟨l, u, h⟩ : Box ι) else ⊥ @@ -453,7 +451,7 @@ theorem distortion_eq_of_sub_eq_div {I J : Box ι} {r : ℝ} rw [← h] at this exact this.not_lt (sub_pos.2 <| I.lower_lt_upper i) have hn0 := (map_ne_zero Real.nnabs).2 this.ne' - simp_rw [NNReal.finset_sup_div, div_div_div_cancel_right _ hn0] + simp_rw [NNReal.finset_sup_div, div_div_div_cancel_right₀ hn0] theorem nndist_le_distortion_mul (I : Box ι) (i : ι) : nndist I.lower I.upper ≤ I.distortion * nndist (I.lower i) (I.upper i) := diff --git a/Mathlib/Analysis/BoxIntegral/DivergenceTheorem.lean b/Mathlib/Analysis/BoxIntegral/DivergenceTheorem.lean index 79429fdb79725..9c979a7202bd1 100644 --- a/Mathlib/Analysis/BoxIntegral/DivergenceTheorem.lean +++ b/Mathlib/Analysis/BoxIntegral/DivergenceTheorem.lean @@ -77,7 +77,7 @@ theorem norm_volume_sub_integral_face_upper_sub_lower_smul_le {f : (Fin (n + 1) `f y - a - f' (y - x)` over each of these faces is less than or equal to `ε * c * vol I`. We integrate a function of the norm `≤ ε * diam I.Icc` over a box of volume `∏ j ≠ i, (I.upper j - I.lower j)`. Since `diam I.Icc ≤ c * (I.upper i - I.lower i)`, we get the - required estimate. -/ + required estimate. -/ have Hl : I.lower i ∈ Icc (I.lower i) (I.upper i) := Set.left_mem_Icc.2 (I.lower_le_upper i) have Hu : I.upper i ∈ Icc (I.lower i) (I.upper i) := Set.right_mem_Icc.2 (I.lower_le_upper i) have Hi : ∀ x ∈ Icc (I.lower i) (I.upper i), diff --git a/Mathlib/Analysis/BoxIntegral/Integrability.lean b/Mathlib/Analysis/BoxIntegral/Integrability.lean index 12a2a1c87c00d..9cd4c5108bd04 100644 --- a/Mathlib/Analysis/BoxIntegral/Integrability.lean +++ b/Mathlib/Analysis/BoxIntegral/Integrability.lean @@ -152,7 +152,7 @@ theorem HasIntegral.of_aeEq_zero {l : IntegrationParams} {I : Box ι} {f : (ι exact (mul_le_mul_left' this.le _).trans ENNReal.mul_div_le /-- If `f` has integral `y` on a box `I` with respect to a locally finite measure `μ` and `g` is -a.e. equal to `f` on `I`, then `g` has the same integral on `I`. -/ +a.e. equal to `f` on `I`, then `g` has the same integral on `I`. -/ theorem HasIntegral.congr_ae {l : IntegrationParams} {I : Box ι} {y : E} {f g : (ι → ℝ) → E} {μ : Measure (ι → ℝ)} [IsLocallyFiniteMeasure μ] (hf : HasIntegral.{u, v, v} I l f μ.toBoxAdditive.toSMul y) (hfg : f =ᵐ[μ.restrict I] g) @@ -191,7 +191,7 @@ end SimpleFunc open TopologicalSpace /-- If `f : ℝⁿ → E` is Bochner integrable w.r.t. a locally finite measure `μ` on a rectangular box -`I`, then it is McShane integrable on `I` with the same integral. -/ +`I`, then it is McShane integrable on `I` with the same integral. -/ theorem IntegrableOn.hasBoxIntegral [CompleteSpace E] {f : (ι → ℝ) → E} {μ : Measure (ι → ℝ)} [IsLocallyFiniteMeasure μ] {I : Box ι} (hf : IntegrableOn f I μ) (l : IntegrationParams) (hl : l.bRiemann = false) : diff --git a/Mathlib/Analysis/BoxIntegral/Partition/Additive.lean b/Mathlib/Analysis/BoxIntegral/Partition/Additive.lean index e7a53933badbc..a82e54fd54bb5 100644 --- a/Mathlib/Analysis/BoxIntegral/Partition/Additive.lean +++ b/Mathlib/Analysis/BoxIntegral/Partition/Additive.lean @@ -26,7 +26,6 @@ In this file we define box-additive functions and prove that a function such tha rectangular box, additive function -/ - noncomputable section open scoped Classical @@ -191,7 +190,7 @@ def upperSubLower.{u} {G : Type u} [AddCommGroup G] (I₀ : Box (Fin (n + 1))) ( rw [WithTop.coe_le_coe] at hJ refine i.succAboveCases (fun hx => ?_) (fun j hx => ?_) j · simp only [Box.splitLower_def hx, Box.splitUpper_def hx, update_same, ← WithBot.some_eq_coe, - Option.elim', Box.face, (· ∘ ·), update_noteq (Fin.succAbove_ne _ _)] + Option.elim', Box.face, Function.comp_def, update_noteq (Fin.succAbove_ne _ _)] abel · have : (J.face i : WithTop (Box (Fin n))) ≤ I₀.face i := WithTop.coe_le_coe.2 (face_mono hJ i) diff --git a/Mathlib/Analysis/BoxIntegral/Partition/Basic.lean b/Mathlib/Analysis/BoxIntegral/Partition/Basic.lean index f9b75b2ded3d5..a596f5d3c17d9 100644 --- a/Mathlib/Analysis/BoxIntegral/Partition/Basic.lean +++ b/Mathlib/Analysis/BoxIntegral/Partition/Basic.lean @@ -36,11 +36,8 @@ We also define a `SemilatticeInf` structure on `BoxIntegral.Prepartition I` for rectangular box, partition -/ - open Set Finset Function - -open scoped Classical -open NNReal +open scoped Classical NNReal noncomputable section @@ -63,7 +60,7 @@ namespace Prepartition variable {I J J₁ J₂ : Box ι} (π : Prepartition I) {π₁ π₂ : Prepartition I} {x : ι → ℝ} instance : Membership (Box ι) (Prepartition I) := - ⟨fun J π => J ∈ π.boxes⟩ + ⟨fun π J => J ∈ π.boxes⟩ @[simp] theorem mem_boxes : J ∈ π.boxes ↔ J ∈ π := Iff.rfl @@ -544,7 +541,8 @@ theorem filter_true : (π.filter fun _ => True) = π := theorem iUnion_filter_not (π : Prepartition I) (p : Box ι → Prop) : (π.filter fun J => ¬p J).iUnion = π.iUnion \ (π.filter p).iUnion := by simp only [Prepartition.iUnion] - convert (@Set.biUnion_diff_biUnion_eq (ι → ℝ) (Box ι) π.boxes (π.filter p).boxes (↑) _).symm + convert + (@Set.biUnion_diff_biUnion_eq (ι → ℝ) (Box ι) π.boxes (π.filter p).boxes (↑) _).symm using 4 · simp (config := { contextual := true }) · rw [Set.PairwiseDisjoint] convert π.pairwiseDisjoint diff --git a/Mathlib/Analysis/BoxIntegral/Partition/Filter.lean b/Mathlib/Analysis/BoxIntegral/Partition/Filter.lean index bd77ed4ea788e..3a2ae15d2bd93 100644 --- a/Mathlib/Analysis/BoxIntegral/Partition/Filter.lean +++ b/Mathlib/Analysis/BoxIntegral/Partition/Filter.lean @@ -163,11 +163,8 @@ prepartition (and consider the special case `π = ⊥` separately if needed). integral, rectangular box, partition, filter -/ - open Set Function Filter Metric Finset Bool - -open scoped Classical -open Topology Filter NNReal +open scoped Classical Topology Filter NNReal noncomputable section diff --git a/Mathlib/Analysis/BoxIntegral/Partition/Split.lean b/Mathlib/Analysis/BoxIntegral/Partition/Split.lean index 50bc2ecd32943..fa8553041f1e2 100644 --- a/Mathlib/Analysis/BoxIntegral/Partition/Split.lean +++ b/Mathlib/Analysis/BoxIntegral/Partition/Split.lean @@ -35,12 +35,9 @@ is available as `BoxIntegral.Prepartition.compl`. rectangular box, partition, hyperplane -/ - noncomputable section open scoped Classical -open Filter - open Function Set Filter namespace BoxIntegral @@ -247,7 +244,7 @@ theorem inf_splitMany {I : Box ι} (π : Prepartition I) (s : Finset (ι × ℝ) /-- Let `s : Finset (ι × ℝ)` be a set of hyperplanes `{x : ι → ℝ | x i = r}` in `ι → ℝ` encoded as pairs `(i, r)`. Suppose that this set contains all faces of a box `J`. The hyperplanes of `s` split a box `I` into subboxes. Let `Js` be one of them. If `J` and `Js` have nonempty intersection, then -`Js` is a subbox of `J`. -/ +`Js` is a subbox of `J`. -/ theorem not_disjoint_imp_le_of_subset_of_mem_splitMany {I J Js : Box ι} {s : Finset (ι × ℝ)} (H : ∀ i, {(i, J.lower i), (i, J.upper i)} ⊆ s) (HJs : Js ∈ splitMany I s) (Hn : ¬Disjoint (J : WithBot (Box ι)) Js) : Js ≤ J := by diff --git a/Mathlib/Analysis/BoxIntegral/Partition/Tagged.lean b/Mathlib/Analysis/BoxIntegral/Partition/Tagged.lean index 71fea77c5b71a..967500dc84169 100644 --- a/Mathlib/Analysis/BoxIntegral/Partition/Tagged.lean +++ b/Mathlib/Analysis/BoxIntegral/Partition/Tagged.lean @@ -49,7 +49,7 @@ namespace TaggedPrepartition variable {I J J₁ J₂ : Box ι} (π : TaggedPrepartition I) {x : ι → ℝ} instance : Membership (Box ι) (TaggedPrepartition I) := - ⟨fun J π => J ∈ π.boxes⟩ + ⟨fun π J => J ∈ π.boxes⟩ @[simp] theorem mem_toPrepartition {π : TaggedPrepartition I} : J ∈ π.toPrepartition ↔ J ∈ π := Iff.rfl diff --git a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Basic.lean b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Basic.lean index a475c96675c2d..073d532f7a479 100644 --- a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Basic.lean +++ b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Basic.lean @@ -90,7 +90,7 @@ theorem elementalStarAlgebra.bijective_characterSpaceToSpectrum : ContinuousMap.coe_mk] using h · rintro ⟨z, hz⟩ have hz' := (StarSubalgebra.spectrum_eq (hS := elementalStarAlgebra.isClosed ℂ a) - (a := ⟨a, self_mem ℂ a⟩).symm.subst hz) + (a := ⟨a, self_mem ℂ a⟩) ▸ hz) rw [CharacterSpace.mem_spectrum_iff_exists] at hz' obtain ⟨φ, rfl⟩ := hz' exact ⟨φ, rfl⟩ diff --git a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Instances.lean b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Instances.lean index d401e7f3e4c6d..4430a3345b71d 100644 --- a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Instances.lean +++ b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Instances.lean @@ -215,13 +215,11 @@ lemma QuasispectrumRestricts.isSelfAdjoint (a : A) (ha : QuasispectrumRestricts [IsStarNormal a] : IsSelfAdjoint a := isSelfAdjoint_iff_isStarNormal_and_quasispectrumRestricts.mpr ⟨‹_›, ha⟩ -instance IsSelfAdjoint.instNonUnitalContinuousFunctionalCalculus - [∀ x : A, CompactSpace (σₙ ℂ x)] : +instance IsSelfAdjoint.instNonUnitalContinuousFunctionalCalculus : NonUnitalContinuousFunctionalCalculus ℝ (IsSelfAdjoint : A → Prop) := QuasispectrumRestricts.cfc (q := IsStarNormal) (p := IsSelfAdjoint) Complex.reCLM Complex.isometry_ofReal.uniformEmbedding (.zero _) (fun _ ↦ isSelfAdjoint_iff_isStarNormal_and_quasispectrumRestricts) - (fun _ _ ↦ inferInstance) end SelfAdjointNonUnital @@ -263,12 +261,16 @@ lemma SpectrumRestricts.isSelfAdjoint (a : A) (ha : SpectrumRestricts a Complex. [IsStarNormal a] : IsSelfAdjoint a := isSelfAdjoint_iff_isStarNormal_and_spectrumRestricts.mpr ⟨‹_›, ha⟩ -instance IsSelfAdjoint.instContinuousFunctionalCalculus [∀ x : A, CompactSpace (spectrum ℂ x)] : +instance IsSelfAdjoint.instContinuousFunctionalCalculus : ContinuousFunctionalCalculus ℝ (IsSelfAdjoint : A → Prop) := SpectrumRestricts.cfc (q := IsStarNormal) (p := IsSelfAdjoint) Complex.reCLM Complex.isometry_ofReal.uniformEmbedding (.zero _) (fun _ ↦ isSelfAdjoint_iff_isStarNormal_and_spectrumRestricts) - (fun _ _ ↦ inferInstance) + +lemma IsSelfAdjoint.spectrum_nonempty {A : Type*} [Ring A] [StarRing A] + [TopologicalSpace A] [Algebra ℝ A] [ContinuousFunctionalCalculus ℝ (IsSelfAdjoint : A → Prop)] + [Nontrivial A] {a : A} (ha : IsSelfAdjoint a) : (σ ℝ a).Nonempty := + CFC.spectrum_nonempty ℝ a ha end SelfAdjointUnital @@ -308,12 +310,17 @@ lemma nonneg_iff_isSelfAdjoint_and_quasispectrumRestricts {a : A} : simpa [sq, hx.star_eq] using star_mul_self_nonneg x open NNReal in -instance Nonneg.instNonUnitalContinuousFunctionalCalculus [∀ a : A, CompactSpace (σₙ ℝ a)] : +instance Nonneg.instNonUnitalContinuousFunctionalCalculus : NonUnitalContinuousFunctionalCalculus ℝ≥0 (fun x : A ↦ 0 ≤ x) := QuasispectrumRestricts.cfc (q := IsSelfAdjoint) ContinuousMap.realToNNReal uniformEmbedding_subtype_val le_rfl (fun _ ↦ nonneg_iff_isSelfAdjoint_and_quasispectrumRestricts) - (fun _ _ ↦ inferInstance) + +open NNReal in +lemma NNReal.spectrum_nonempty {A : Type*} [Ring A] [StarRing A] [PartialOrder A] + [TopologicalSpace A] [Algebra ℝ≥0 A] [ContinuousFunctionalCalculus ℝ≥0 (fun x : A ↦ 0 ≤ x)] + [Nontrivial A] {a : A} (ha : 0 ≤ a) : (spectrum ℝ≥0 a).Nonempty := + CFC.spectrum_nonempty ℝ≥0 a ha end Nonneg @@ -349,11 +356,10 @@ lemma nonneg_iff_isSelfAdjoint_and_spectrumRestricts {a : A} : simpa [sq, hx.star_eq] using star_mul_self_nonneg x open NNReal in -instance Nonneg.instContinuousFunctionalCalculus [∀ a : A, CompactSpace (spectrum ℝ a)] : +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) - (fun _ _ ↦ inferInstance) end Nonneg @@ -595,19 +601,15 @@ section RealEqComplex variable {A : Type*} [TopologicalSpace A] [Ring A] [StarRing A] [Algebra ℂ A] [ContinuousFunctionalCalculus ℂ (IsStarNormal : A → Prop)] - [ContinuousFunctionalCalculus ℝ (IsSelfAdjoint : A → Prop)] [UniqueContinuousFunctionalCalculus ℝ A] - [UniqueContinuousFunctionalCalculus ℂ A] lemma cfcHom_real_eq_restrict {a : A} (ha : IsSelfAdjoint a) : cfcHom ha = ha.spectrumRestricts.starAlgHom (cfcHom ha.isStarNormal) (f := Complex.reCLM) := - have := UniqueContinuousFunctionalCalculus.compactSpace_spectrum a (R := ℂ) ha.spectrumRestricts.cfcHom_eq_restrict Complex.isometry_ofReal.uniformEmbedding 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 - have := UniqueContinuousFunctionalCalculus.compactSpace_spectrum a (R := ℂ) 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 @@ -627,12 +629,10 @@ 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 - have := UniqueContinuousFunctionalCalculus.compactSpace_spectrum a (R := ℝ) apply (SpectrumRestricts.nnreal_of_nonneg ha).cfcHom_eq_restrict uniformEmbedding_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 - have := UniqueContinuousFunctionalCalculus.compactSpace_spectrum a (R := ℝ) 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) diff --git a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Integral.lean b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Integral.lean new file mode 100644 index 0000000000000..f56a3cf3d1927 --- /dev/null +++ b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Integral.lean @@ -0,0 +1,147 @@ +/- +Copyright (c) 2024 Frédéric Dupuis. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Frédéric Dupuis +-/ + +import Mathlib.Analysis.Normed.Algebra.Spectrum +import Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Unital +import Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.NonUnital +import Mathlib.MeasureTheory.Integral.SetIntegral + +/-! +# Integrals and the continuous functional calculus + +This file gives results about integrals of the form `∫ x, cfc (f x) a`. Most notably, we show +that the integral commutes with the continuous functional calculus under appropriate conditions. + +## Main declarations + ++ `cfc_integral`: given a function `f : X → 𝕜 → 𝕜`, we have that + `cfc (fun r => ∫ x, f x r ∂μ) a = ∫ x, cfc (f x) a ∂μ` + under appropriate conditions ++ `cfcₙ_integral`: given a function `f : X → 𝕜 → 𝕜`, we have that + `cfcₙ (fun r => ∫ x, f x r ∂μ) a = ∫ x, cfcₙ (f x) a ∂μ` + under appropriate conditions + +## TODO + ++ Lift this to the case where the CFC is over `ℝ≥0` ++ Use this to prove operator monotonicity and concavity/convexity of `rpow` and `log` +-/ + +open MeasureTheory +open scoped ContinuousMapZero + +section unital + +variable {X : Type*} {𝕜 : Type*} {A : Type*} {p : A → Prop} [RCLike 𝕜] + [MeasurableSpace X] {μ : Measure X} + [NormedRing A] [StarRing A] [NormedAlgebra 𝕜 A] [NormedAlgebra ℝ A] [CompleteSpace A] + [ContinuousFunctionalCalculus 𝕜 p] + +lemma cfcL_integral (a : A) (f : X → C(spectrum 𝕜 a, 𝕜)) (hf₁ : Integrable f μ) + (ha : p a := by cfc_tac) : + ∫ x, cfcL (a := a) ha (f x) ∂μ = cfcL (a := a) ha (∫ x, f x ∂μ) := by + rw [ContinuousLinearMap.integral_comp_comm _ hf₁] + +lemma cfcHom_integral (a : A) (f : X → C(spectrum 𝕜 a, 𝕜)) (hf₁ : Integrable f μ) + (ha : p a := by cfc_tac) : + ∫ x, cfcHom (a := a) ha (f x) ∂μ = cfcHom (a := a) ha (∫ x, f x ∂μ) := + cfcL_integral a f hf₁ ha + +open ContinuousMap in +/-- The continuous functional calculus commutes with integration. -/ +lemma cfc_integral [TopologicalSpace X] [OpensMeasurableSpace X] (f : X → 𝕜 → 𝕜) + (bound : X → ℝ) (a : A) [SecondCountableTopologyEither X C(spectrum 𝕜 a, 𝕜)] + (hf₁ : ∀ x, ContinuousOn (f x) (spectrum 𝕜 a)) + (hf₂ : Continuous (fun x ↦ (⟨_, hf₁ x |>.restrict⟩ : C(spectrum 𝕜 a, 𝕜)))) + (hbound : ∀ x, ∀ z ∈ spectrum 𝕜 a, ‖f x z‖ ≤ ‖bound x‖) + (hbound_finite_integral : HasFiniteIntegral bound μ) (ha : p a := by cfc_tac) : + cfc (fun r => ∫ x, f x r ∂μ) a = ∫ x, cfc (f x) a ∂μ := by + let fc : X → C(spectrum 𝕜 a, 𝕜) := fun x => ⟨_, (hf₁ x).restrict⟩ + have fc_integrable : Integrable fc μ := by + refine ⟨hf₂.aestronglyMeasurable, ?_⟩ + refine hbound_finite_integral.mono <| .of_forall fun x ↦ ?_ + rw [norm_le _ (norm_nonneg (bound x))] + exact fun z ↦ hbound x z.1 z.2 + have h_int_fc : (spectrum 𝕜 a).restrict (∫ x, f x · ∂μ) = ∫ x, fc x ∂μ := by + ext; simp [integral_apply fc_integrable, fc] + have hcont₂ : ContinuousOn (fun r => ∫ x, f x r ∂μ) (spectrum 𝕜 a) := by + rw [continuousOn_iff_continuous_restrict] + convert map_continuous (∫ x, fc x ∂μ) + rw [integral_congr_ae (.of_forall fun _ ↦ cfc_apply ..), cfc_apply .., + cfcHom_integral _ _ fc_integrable] + congr + +/-- The continuous functional calculus commutes with integration. -/ +lemma cfc_integral' [TopologicalSpace X] [OpensMeasurableSpace X] (f : X → 𝕜 → 𝕜) + (bound : X → ℝ) (a : A) [SecondCountableTopologyEither X C(spectrum 𝕜 a, 𝕜)] + (hf : Continuous (fun x => (spectrum 𝕜 a).restrict (f x)).uncurry) + (hbound : ∀ x, ∀ z ∈ spectrum 𝕜 a, ‖f x z‖ ≤ ‖bound x‖) + (hbound_finite_integral : HasFiniteIntegral bound μ) (ha : p a := by cfc_tac) : + cfc (fun r => ∫ x, f x r ∂μ) a = ∫ x, cfc (f x) a ∂μ := by + refine cfc_integral f bound a ?_ ?_ hbound hbound_finite_integral + · exact (continuousOn_iff_continuous_restrict.mpr <| hf.uncurry_left ·) + · exact ContinuousMap.curry ⟨_, hf⟩ |>.continuous + +end unital + +section nonunital + +variable {X : Type*} {𝕜 : Type*} {A : Type*} {p : A → Prop} [RCLike 𝕜] + [MeasurableSpace X] {μ : Measure X} [NonUnitalNormedRing A] [StarRing A] [CompleteSpace A] + [NormedSpace 𝕜 A] [NormedSpace ℝ A] [IsScalarTower 𝕜 A A] [SMulCommClass 𝕜 A A] + [NonUnitalContinuousFunctionalCalculus 𝕜 p] + +lemma cfcₙL_integral (a : A) (f : X → C(quasispectrum 𝕜 a, 𝕜)₀) (hf₁ : Integrable f μ) + (ha : p a := by cfc_tac) : + ∫ x, cfcₙL (a := a) ha (f x) ∂μ = cfcₙL (a := a) ha (∫ x, f x ∂μ) := by + rw [ContinuousLinearMap.integral_comp_comm _ hf₁] + +lemma cfcₙHom_integral (a : A) (f : X → C(quasispectrum 𝕜 a, 𝕜)₀) (hf₁ : Integrable f μ) + (ha : p a := by cfc_tac) : + ∫ x, cfcₙHom (a := a) ha (f x) ∂μ = cfcₙHom (a := a) ha (∫ x, f x ∂μ) := + cfcₙL_integral a f hf₁ ha + +open ContinuousMapZero in +/-- The non-unital continuous functional calculus commutes with integration. -/ +lemma cfcₙ_integral [TopologicalSpace X] [OpensMeasurableSpace X] (f : X → 𝕜 → 𝕜) + (bound : X → ℝ) (a : A) [SecondCountableTopologyEither X C(quasispectrum 𝕜 a, 𝕜)₀] + (hf₁ : ∀ x, ContinuousOn (f x) (quasispectrum 𝕜 a)) + (hf₂ : ∀ x, f x 0 = 0) + (hf₃ : Continuous (fun x ↦ (⟨⟨_, hf₁ x |>.restrict⟩, hf₂ x⟩ : C(quasispectrum 𝕜 a, 𝕜)₀))) + (hbound : ∀ x, ∀ z ∈ quasispectrum 𝕜 a, ‖f x z‖ ≤ ‖bound x‖) + (hbound_finite_integral : HasFiniteIntegral bound μ) (ha : p a := by cfc_tac) : + cfcₙ (fun r => ∫ x, f x r ∂μ) a = ∫ x, cfcₙ (f x) a ∂μ := by + let fc : X → C(quasispectrum 𝕜 a, 𝕜)₀ := fun x => ⟨⟨_, (hf₁ x).restrict⟩, hf₂ x⟩ + have fc_integrable : Integrable fc μ := by + refine ⟨hf₃.aestronglyMeasurable, ?_⟩ + refine hbound_finite_integral.mono <| .of_forall fun x ↦ ?_ + change ‖(fc x : C(quasispectrum 𝕜 a, 𝕜))‖ ≤ ‖bound x‖ + rw [ContinuousMap.norm_le _ (norm_nonneg (bound x))] + exact fun z ↦ hbound x z.1 z.2 + have h_int_fc : (quasispectrum 𝕜 a).restrict (∫ x, f x · ∂μ) = ∫ x, fc x ∂μ := by + ext; simp [integral_apply fc_integrable, fc] + have hcont₂ : ContinuousOn (fun r => ∫ x, f x r ∂μ) (quasispectrum 𝕜 a) := by + rw [continuousOn_iff_continuous_restrict] + convert map_continuous (∫ x, fc x ∂μ) + rw [integral_congr_ae (.of_forall fun _ ↦ cfcₙ_apply ..), cfcₙ_apply .., + cfcₙHom_integral _ _ fc_integrable] + congr + +/-- The non-unital continuous functional calculus commutes with integration. -/ +lemma cfcₙ_integral' [TopologicalSpace X] [OpensMeasurableSpace X] (f : X → 𝕜 → 𝕜) + (bound : X → ℝ) (a : A) [SecondCountableTopologyEither X C(quasispectrum 𝕜 a, 𝕜)₀] + (hf : Continuous (fun x => (quasispectrum 𝕜 a).restrict (f x)).uncurry) + (hf₂ : ∀ x, f x 0 = 0) + (hbound : ∀ x, ∀ z ∈ quasispectrum 𝕜 a, ‖f x z‖ ≤ ‖bound x‖) + (hbound_finite_integral : HasFiniteIntegral bound μ) (ha : p a := by cfc_tac) : + cfcₙ (fun r => ∫ x, f x r ∂μ) a = ∫ x, cfcₙ (f x) a ∂μ := by + refine cfcₙ_integral f bound a ?_ hf₂ ?_ hbound hbound_finite_integral + · exact (continuousOn_iff_continuous_restrict.mpr <| hf.uncurry_left ·) + · let g := ((↑) : C(quasispectrum 𝕜 a, 𝕜)₀ → C(quasispectrum 𝕜 a, 𝕜)) + refine (Inducing.continuous_iff (g := g) ((inducing_iff g).mpr rfl)).mpr ?_ + exact ContinuousMap.curry ⟨_, hf⟩ |>.continuous + +end nonunital diff --git a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/NonUnital.lean b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/NonUnital.lean index dfb187b624e62..9ab7ac681635d 100644 --- a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/NonUnital.lean +++ b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/NonUnital.lean @@ -170,6 +170,17 @@ theorem cfcₙHom_comp [UniqueNonUnitalContinuousFunctionalCalculus R A] (f : C( end cfcₙHom +section cfcₙL + +/-- `cfcₙHom` bundled as a continuous linear map. -/ +@[simps apply] +noncomputable def cfcₙL {a : A} (ha : p a) : C(σₙ R a, R)₀ →L[R] A := + { cfcₙHom ha with + toFun := cfcₙHom ha + map_smul' := map_smul _ + cont := (cfcₙHom_closedEmbedding ha).continuous } + +end cfcₙL section CFCn @@ -458,6 +469,7 @@ lemma CFC.quasispectrum_zero_eq : σₙ R (0 : A) = {0} := by simpa [CFC.quasispectrum_zero_eq] · exact cfcₙ_apply_of_not_map_zero _ hf0 +@[simp] instance IsStarNormal.cfcₙ_map (f : R → R) (a : A) : IsStarNormal (cfcₙ f a) where star_comm_self := by refine cfcₙ_cases (fun x ↦ Commute (star x) x) _ _ (Commute.zero_right _) fun _ _ _ ↦ ?_ @@ -466,6 +478,19 @@ instance IsStarNormal.cfcₙ_map (f : R → R) (a : A) : IsStarNormal (cfcₙ f congr! 2 exact mul_comm _ _ +-- The following two lemmas are just `cfcₙ_predicate`, but specific enough for the `@[simp]` tag. +@[simp] +protected lemma IsSelfAdjoint.cfcₙ + [NonUnitalContinuousFunctionalCalculus R (IsSelfAdjoint : A → Prop)] {f : R → R} {a : A} : + IsSelfAdjoint (cfcₙ f a) := + cfcₙ_predicate _ _ + +@[simp] +lemma cfcₙ_nonneg_of_predicate [PartialOrder A] + [NonUnitalContinuousFunctionalCalculus R (fun (a : A) => 0 ≤ a)] {f : R → R} {a : A} : + 0 ≤ cfcₙ f a := + cfcₙ_predicate _ _ + end CFCn end Main @@ -662,10 +687,6 @@ lemma closedEmbedding_cfcₙHom_of_cfcHom {a : A} (ha : p a) : ClosedEmbedding (cfcₙHom_of_cfcHom R ha) := by let f : C(spectrum R a, σₙ R a) := ⟨_, continuous_inclusion <| spectrum_subset_quasispectrum R a⟩ - have h_cpct' : CompactSpace (σₙ R a) := by - specialize h_cpct a - simp_rw [← isCompact_iff_compactSpace, quasispectrum_eq_spectrum_union_zero] at h_cpct ⊢ - exact h_cpct.union isCompact_singleton refine (cfcHom_closedEmbedding ha).comp <| (UniformInducing.uniformEmbedding ⟨?_⟩).toClosedEmbedding have := uniformSpace_eq_inf_precomp_of_cover (β := R) f (0 : C(Unit, σₙ R a)) diff --git a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Order.lean b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Order.lean index 2bebd79a58986..b1a6a94c4d085 100644 --- a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Order.lean +++ b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Order.lean @@ -5,8 +5,9 @@ Authors: Frédéric Dupuis -/ import Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Instances -import Mathlib.Topology.ContinuousFunction.StarOrdered import Mathlib.Analysis.CStarAlgebra.Unitization +import Mathlib.Analysis.SpecialFunctions.ContinuousFunctionalCalculus.Rpow +import Mathlib.Topology.ContinuousFunction.StarOrdered /-! # Facts about star-ordered rings that depend on the continuous functional calculus @@ -27,6 +28,7 @@ the spectral order. `‖a‖ ≤ ‖b‖`. * `CStarRing.conjugate_le_norm_smul`: in a non-unital C⋆-algebra, we have that `star a * b * a ≤ ‖b‖ • (star a * a)` (and a primed version for the `a * b * star a` case). +* `CStarRing.inv_le_inv_iff`: in a unital C⋆-algebra, `b⁻¹ ≤ a⁻¹` iff `a ≤ b`. ## Tags @@ -64,6 +66,39 @@ lemma inr_nonneg_iff {a : A} : 0 ≤ (a : Unitization ℂ A) ↔ 0 ≤ a := by end Unitization +/-- `cfc_le_iff` only applies to a scalar ring where `R` is an actual `Ring`, and not a `Semiring`. +However, this theorem still holds for `ℝ≥0` as long as the algebra `A` itself is an `ℝ`-algebra. -/ +lemma cfc_nnreal_le_iff {A : Type*} [TopologicalSpace A] [Ring A] [StarRing A] [PartialOrder A] + [StarOrderedRing A] [Algebra ℝ A] [TopologicalRing A] [NonnegSpectrumClass ℝ A] + [ContinuousFunctionalCalculus ℝ (IsSelfAdjoint : A → Prop)] + [UniqueContinuousFunctionalCalculus ℝ A] + (f : ℝ≥0 → ℝ≥0) (g : ℝ≥0 → ℝ≥0) (a : A) + (ha_spec : SpectrumRestricts a ContinuousMap.realToNNReal) + (hf : ContinuousOn f (spectrum ℝ≥0 a) := by cfc_cont_tac) + (hg : ContinuousOn g (spectrum ℝ≥0 a) := by cfc_cont_tac) + (ha : 0 ≤ a := by cfc_tac) : + cfc f a ≤ cfc g a ↔ ∀ x ∈ spectrum ℝ≥0 a, f x ≤ g x := by + have hf' := hf.ofReal_map_toNNReal <| ha_spec.image ▸ Set.mapsTo_image .. + have hg' := hg.ofReal_map_toNNReal <| ha_spec.image ▸ Set.mapsTo_image .. + rw [cfc_nnreal_eq_real, cfc_nnreal_eq_real, cfc_le_iff ..] + simp [NNReal.coe_le_coe, ← ha_spec.image] + +/-- In a unital `ℝ`-algebra `A` with a continuous functional calculus, an element `a : A` is larger +than some `algebraMap ℝ A r` if and only if every element of the `ℝ`-spectrum is nonnegative. -/ +lemma CFC.exists_pos_algebraMap_le_iff {A : Type*} [TopologicalSpace A] [Ring A] [StarRing A] + [PartialOrder A] [StarOrderedRing A] [Algebra ℝ A] [NonnegSpectrumClass ℝ A] + [ContinuousFunctionalCalculus ℝ (IsSelfAdjoint : A → Prop)] + {a : A} [CompactSpace (spectrum ℝ a)] + (h_non : (spectrum ℝ a).Nonempty) (ha : IsSelfAdjoint a := by cfc_tac) : + (∃ r > 0, algebraMap ℝ A r ≤ a) ↔ (∀ x ∈ spectrum ℝ a, 0 < x) := by + have h_cpct : IsCompact (spectrum ℝ a) := isCompact_iff_compactSpace.mpr inferInstance + simp_rw [algebraMap_le_iff_le_spectrum (a := a)] + refine ⟨?_, fun h ↦ ?_⟩ + · rintro ⟨r, hr, hr_le⟩ + exact (hr.trans_le <| hr_le · ·) + · obtain ⟨r, hr, hr_min⟩ := h_cpct.exists_isMinOn h_non continuousOn_id + exact ⟨r, h _ hr, hr_min⟩ + section CStar_unital variable {A : Type*} [NormedRing A] [StarRing A] [CStarRing A] [CompleteSpace A] @@ -103,7 +138,9 @@ lemma IsSelfAdjoint.toReal_spectralRadius_eq_norm {a : A} (ha : IsSelfAdjoint a) (spectralRadius ℝ a).toReal = ‖a‖ := by simp [ha.spectrumRestricts.spectralRadius_eq, ha.spectralRadius_eq_nnnorm] -lemma CStarRing.norm_or_neg_norm_mem_spectrum [Nontrivial A] {a : A} +namespace CStarRing + +lemma norm_or_neg_norm_mem_spectrum [Nontrivial A] {a : A} (ha : IsSelfAdjoint a := by cfc_tac) : ‖a‖ ∈ spectrum ℝ a ∨ -‖a‖ ∈ spectrum ℝ a := by have ha' : SpectrumRestricts a Complex.reCLM := ha.spectrumRestricts rw [← ha.toReal_spectralRadius_eq_norm] @@ -111,16 +148,164 @@ lemma CStarRing.norm_or_neg_norm_mem_spectrum [Nontrivial A] {a : A} variable [PartialOrder A] [StarOrderedRing A] -lemma CStarRing.nnnorm_mem_spectrum_of_nonneg [Nontrivial A] {a : A} (ha : 0 ≤ a := by cfc_tac) : +lemma nnnorm_mem_spectrum_of_nonneg [Nontrivial A] {a : A} (ha : 0 ≤ a := by cfc_tac) : ‖a‖₊ ∈ spectrum ℝ≥0 a := by have : IsSelfAdjoint a := .of_nonneg ha convert NNReal.spectralRadius_mem_spectrum (a := a) ?_ (.nnreal_of_nonneg ha) · simp [this.spectrumRestricts.spectralRadius_eq, this.spectralRadius_eq_nnnorm] · exact this.spectrumRestricts.image ▸ (spectrum.nonempty a).image _ -lemma CStarRing.norm_mem_spectrum_of_nonneg [Nontrivial A] {a : A} (ha : 0 ≤ a := by cfc_tac) : +lemma norm_mem_spectrum_of_nonneg [Nontrivial A] {a : A} (ha : 0 ≤ a := by cfc_tac) : ‖a‖ ∈ spectrum ℝ a := by - simpa using spectrum.algebraMap_mem ℝ <| CStarRing.nnnorm_mem_spectrum_of_nonneg ha + simpa using spectrum.algebraMap_mem ℝ <| nnnorm_mem_spectrum_of_nonneg ha + +lemma norm_le_iff_le_algebraMap (a : A) {r : ℝ} (hr : 0 ≤ r) (ha : 0 ≤ a := by cfc_tac) : + ‖a‖ ≤ r ↔ a ≤ algebraMap ℝ A r := by + rw [le_algebraMap_iff_spectrum_le] + obtain (h | _) := subsingleton_or_nontrivial A + · simp [Subsingleton.elim a 0, hr] + · exact ⟨fun h x hx ↦ Real.le_norm_self x |>.trans (spectrum.norm_le_norm_of_mem hx) |>.trans h, + fun h ↦ h ‖a‖ <| norm_mem_spectrum_of_nonneg⟩ + +lemma nnnorm_le_iff_of_nonneg (a : A) (r : ℝ≥0) (ha : 0 ≤ a := by cfc_tac) : + ‖a‖₊ ≤ r ↔ a ≤ algebraMap ℝ≥0 A r := by + rw [← NNReal.coe_le_coe] + exact norm_le_iff_le_algebraMap a r.2 + +lemma norm_le_one_iff_of_nonneg (a : A) (ha : 0 ≤ a := by cfc_tac) : + ‖a‖ ≤ 1 ↔ a ≤ 1 := by + simpa using norm_le_iff_le_algebraMap a zero_le_one + +lemma nnnorm_le_one_iff_of_nonneg (a : A) (ha : 0 ≤ a := by cfc_tac) : + ‖a‖₊ ≤ 1 ↔ a ≤ 1 := by + rw [← NNReal.coe_le_coe] + exact norm_le_one_iff_of_nonneg a + +lemma norm_le_natCast_iff_of_nonneg (a : A) (n : ℕ) (ha : 0 ≤ a := by cfc_tac) : + ‖a‖ ≤ n ↔ a ≤ n := by + simpa using norm_le_iff_le_algebraMap a n.cast_nonneg + +lemma nnnorm_le_natCast_iff_of_nonneg (a : A) (n : ℕ) (ha : 0 ≤ a := by cfc_tac) : + ‖a‖₊ ≤ n ↔ a ≤ n := by + simpa using nnnorm_le_iff_of_nonneg a n + +end CStarRing + +section Inv + +open CFC + +variable [PartialOrder A] [StarOrderedRing A] + +-- TODO : relate everything in this section to strict positivity + +lemma CFC.conjugate_rpow_neg_one_half {a : A} (h₀ : IsUnit a) (ha : 0 ≤ a := by cfc_tac) : + a ^ (-(1 / 2) : ℝ) * a * a ^ (-(1 / 2) : ℝ) = 1 := by + lift a to Aˣ using h₀ + nth_rw 2 [← rpow_one (a : A)] + simp only [← rpow_add (a.zero_not_mem_spectrum ℝ≥0)] + norm_num + exact rpow_zero _ + +/-- In a unital C⋆-algebra, if `a` is nonnegative and invertible, and `a ≤ b`, then `b` is +invertible. -/ +lemma CStarRing.isUnit_of_le {a b : A} (h₀ : IsUnit a) (ha : 0 ≤ a := by cfc_tac) + (hab : a ≤ b) : IsUnit b := by + rw [← spectrum.zero_not_mem_iff ℝ≥0] at h₀ ⊢ + nontriviality A + have hb := (show 0 ≤ a from ha).trans hab + have ha' := IsSelfAdjoint.of_nonneg ha |>.spectrum_nonempty + have hb' := IsSelfAdjoint.of_nonneg hb |>.spectrum_nonempty + rw [zero_not_mem_iff, SpectrumRestricts.nnreal_lt_iff (.nnreal_of_nonneg ‹_›), + NNReal.coe_zero, ← CFC.exists_pos_algebraMap_le_iff ‹_›] at h₀ ⊢ + peel h₀ with r hr _ + exact this.trans hab + +lemma le_iff_norm_sqrt_mul_rpow {a b : A} (hbu : IsUnit b) (ha : 0 ≤ a) (hb : 0 ≤ (b : A)) : + a ≤ b ↔ ‖sqrt a * (b : A) ^ (-(1 / 2) : ℝ)‖ ≤ 1 := by + lift b to Aˣ using hbu + have hbab : 0 ≤ (b : A) ^ (-(1 / 2) : ℝ) * a * (b : A) ^ (-(1 / 2) : ℝ) := + conjugate_nonneg_of_nonneg ha rpow_nonneg + conv_rhs => + rw [← sq_le_one_iff (norm_nonneg _), sq, ← CStarRing.norm_star_mul_self, star_mul, + IsSelfAdjoint.of_nonneg sqrt_nonneg, IsSelfAdjoint.of_nonneg rpow_nonneg, + ← mul_assoc, mul_assoc _ _ (sqrt a), sqrt_mul_sqrt_self a, + CStarRing.norm_le_one_iff_of_nonneg _ hbab] + refine ⟨fun h ↦ ?_, fun h ↦ ?_⟩ + · calc + _ ≤ ↑b ^ (-(1 / 2) : ℝ) * (b : A) * ↑b ^ (-(1 / 2) : ℝ) := + IsSelfAdjoint.of_nonneg rpow_nonneg |>.conjugate_le_conjugate h + _ = 1 := conjugate_rpow_neg_one_half b.isUnit + · calc + a = (sqrt ↑b * ↑b ^ (-(1 / 2) : ℝ)) * a * (↑b ^ (-(1 / 2) : ℝ) * sqrt ↑b) := by + simp only [CFC.sqrt_eq_rpow .., ← CFC.rpow_add (b.zero_not_mem_spectrum ℝ≥0)] + norm_num + simp [CFC.rpow_zero (b : A)] + _ = sqrt ↑b * (↑b ^ (-(1 / 2) : ℝ) * a * ↑b ^ (-(1 / 2) : ℝ)) * sqrt ↑b := by + simp only [mul_assoc] + _ ≤ b := conjugate_le_conjugate_of_nonneg h sqrt_nonneg |>.trans <| by + simp [CFC.sqrt_mul_sqrt_self (b : A)] + +lemma le_iff_norm_sqrt_mul_sqrt_inv {a : A} {b : Aˣ} (ha : 0 ≤ a) (hb : 0 ≤ (b : A)) : + a ≤ b ↔ ‖sqrt a * sqrt (↑b⁻¹ : A)‖ ≤ 1 := by + rw [CFC.sqrt_eq_rpow (a := (↑b⁻¹ : A)), ← CFC.rpow_neg_one_eq_inv b, + CFC.rpow_rpow (b : A) _ _ (by simp) (by norm_num), le_iff_norm_sqrt_mul_rpow b.isUnit ha hb] + norm_num + +/-- In a unital C⋆-algebra, if `0 ≤ a ≤ b` and `a` and `b` are units, then `b⁻¹ ≤ a⁻¹`. -/ +protected lemma CStarRing.inv_le_inv {a b : Aˣ} (ha : 0 ≤ (a : A)) + (hab : (a : A) ≤ b) : (↑b⁻¹ : A) ≤ a⁻¹ := by + have hb := ha.trans hab + have hb_inv : (0 : A) ≤ b⁻¹ := inv_nonneg_of_nonneg b hb + have ha_inv : (0 : A) ≤ a⁻¹ := inv_nonneg_of_nonneg a ha + rw [le_iff_norm_sqrt_mul_sqrt_inv ha hb, ← sq_le_one_iff (norm_nonneg _), sq, + ← CStarRing.norm_star_mul_self] at hab + rw [le_iff_norm_sqrt_mul_sqrt_inv hb_inv ha_inv, inv_inv, ← sq_le_one_iff (norm_nonneg _), sq, + ← CStarRing.norm_self_mul_star] + rwa [star_mul, IsSelfAdjoint.of_nonneg sqrt_nonneg, + IsSelfAdjoint.of_nonneg sqrt_nonneg] at hab ⊢ + +/-- In a unital C⋆-algebra, if `0 ≤ a` and `0 ≤ b` and `a` and `b` are units, then `a⁻¹ ≤ b⁻¹` +if and only if `b ≤ a`. -/ +protected lemma CStarRing.inv_le_inv_iff {a b : Aˣ} (ha : 0 ≤ (a : A)) (hb : 0 ≤ (b : A)) : + (↑a⁻¹ : A) ≤ b⁻¹ ↔ (b : A) ≤ a := + ⟨CStarRing.inv_le_inv (inv_nonneg_of_nonneg a ha), CStarRing.inv_le_inv hb⟩ + +lemma CStarRing.inv_le_iff {a b : Aˣ} (ha : 0 ≤ (a : A)) (hb : 0 ≤ (↑b : A)) : + (↑a⁻¹ : A) ≤ b ↔ (↑b⁻¹ : A) ≤ a := by + simpa using CStarRing.inv_le_inv_iff ha (inv_nonneg_of_nonneg b hb) + +lemma CStarRing.le_inv_iff {a b : Aˣ} (ha : 0 ≤ (a : A)) (hb : 0 ≤ (↑b : A)) : + a ≤ (↑b⁻¹ : A) ↔ b ≤ (↑a⁻¹ : A) := by + simpa using CStarRing.inv_le_inv_iff (inv_nonneg_of_nonneg a ha) hb + +lemma CStarRing.one_le_inv_iff_le_one {a : Aˣ} (ha : 0 ≤ (a : A)) : + 1 ≤ (↑a⁻¹ : A) ↔ a ≤ 1 := by + simpa using CStarRing.le_inv_iff (a := 1) (by simp) ha + +lemma CStarRing.inv_le_one_iff_one_le {a : Aˣ} (ha : 0 ≤ (a : A)) : + (↑a⁻¹ : A) ≤ 1 ↔ 1 ≤ a := by + simpa using CStarRing.inv_le_iff ha (b := 1) (by simp) + +lemma CStarRing.inv_le_one {a : Aˣ} (ha : 1 ≤ a) : (↑a⁻¹ : A) ≤ 1 := + CStarRing.inv_le_one_iff_one_le (zero_le_one.trans ha) |>.mpr ha + +lemma CStarRing.le_one_of_one_le_inv {a : Aˣ} (ha : 1 ≤ (↑a⁻¹ : A)) : (a : A) ≤ 1 := by + simpa using CStarRing.inv_le_one ha + +lemma CStarRing.rpow_neg_one_le_rpow_neg_one {a b : A} (ha : 0 ≤ a) (hab : a ≤ b) (hau : IsUnit a) : + b ^ (-1 : ℝ) ≤ a ^ (-1 : ℝ) := by + lift b to Aˣ using isUnit_of_le hau ha hab + lift a to Aˣ using hau + rw [rpow_neg_one_eq_inv a ha, rpow_neg_one_eq_inv b (ha.trans hab)] + exact CStarRing.inv_le_inv ha hab + +lemma CStarRing.rpow_neg_one_le_one {a : A} (ha : 1 ≤ a) : a ^ (-1 : ℝ) ≤ 1 := by + lift a to Aˣ using isUnit_of_le isUnit_one zero_le_one ha + rw [rpow_neg_one_eq_inv a (zero_le_one.trans ha)] + exact inv_le_one ha + +end Inv end CStar_unital @@ -130,13 +315,15 @@ variable {A : Type*} [NonUnitalNormedRing A] [CompleteSpace A] [PartialOrder A] [StarOrderedRing A] [CStarRing A] [NormedSpace ℂ A] [StarModule ℂ A] [SMulCommClass ℂ A A] [IsScalarTower ℂ A A] +namespace CStarRing + open ComplexOrder in -instance CStarRing.instNonnegSpectrumClassComplexNonUnital : NonnegSpectrumClass ℂ A where +instance instNonnegSpectrumClassComplexNonUnital : NonnegSpectrumClass ℂ A where quasispectrum_nonneg_of_nonneg a ha x hx := by rw [Unitization.quasispectrum_eq_spectrum_inr' ℂ ℂ a] at hx exact spectrum_nonneg_of_nonneg (Unitization.inr_nonneg_iff.mpr ha) hx -lemma CStarRing.norm_le_norm_of_nonneg_of_le {a b : A} (ha : 0 ≤ a := by cfc_tac) (hab : a ≤ b) : +lemma norm_le_norm_of_nonneg_of_le {a b : A} (ha : 0 ≤ a := by cfc_tac) (hab : a ≤ b) : ‖a‖ ≤ ‖b‖ := by suffices ∀ a b : Unitization ℂ A, 0 ≤ a → a ≤ b → ‖a‖ ≤ ‖b‖ by have hb := ha.trans hab @@ -156,7 +343,7 @@ lemma CStarRing.norm_le_norm_of_nonneg_of_le {a b : A} (ha : 0 ≤ a := by cfc_t rw [cfc_le_iff id (fun _ => ‖b‖) a] at h₂ exact h₂ ‖a‖ <| norm_mem_spectrum_of_nonneg ha -lemma CStarRing.conjugate_le_norm_smul {a b : A} (hb : IsSelfAdjoint b := by cfc_tac) : +lemma conjugate_le_norm_smul {a b : A} (hb : IsSelfAdjoint b := by cfc_tac) : star a * b * a ≤ ‖b‖ • (star a * a) := by suffices ∀ a b : Unitization ℂ A, IsSelfAdjoint b → star a * b * a ≤ ‖b‖ • (star a * a) by rw [← Unitization.inr_le_iff _ _ (by aesop) ((IsSelfAdjoint.all _).smul (.star_mul_self a))] @@ -167,11 +354,27 @@ lemma CStarRing.conjugate_le_norm_smul {a b : A} (hb : IsSelfAdjoint b := by cfc conjugate_le_conjugate hb.le_algebraMap_norm_self _ _ = ‖b‖ • (star a * a) := by simp [Algebra.algebraMap_eq_smul_one] -lemma CStarRing.conjugate_le_norm_smul' {a b : A} (hb : IsSelfAdjoint b := by cfc_tac) : +lemma conjugate_le_norm_smul' {a b : A} (hb : IsSelfAdjoint b := by cfc_tac) : a * b * star a ≤ ‖b‖ • (a * star a) := by have h₁ : a * b * star a = star (star a) * b * star a := by simp have h₂ : a * star a = star (star a) * star a := by simp simp only [h₁, h₂] exact conjugate_le_norm_smul +/-- The set of nonnegative elements in a C⋆-algebra is closed. -/ +lemma isClosed_nonneg : IsClosed {a : A | 0 ≤ a} := by + suffices IsClosed {a : Unitization ℂ A | 0 ≤ a} by + rw [Unitization.isometry_inr (𝕜 := ℂ) |>.closedEmbedding.closed_iff_image_closed] + convert this.inter <| (Unitization.isometry_inr (𝕜 := ℂ)).closedEmbedding.isClosed_range + ext a + simp only [Set.mem_image, Set.mem_setOf_eq, Set.mem_inter_iff, Set.mem_range, ← exists_and_left] + congr! 2 with x + exact and_congr_left fun h ↦ by simp [← h] + simp only [nonneg_iff_isSelfAdjoint_and_spectrumRestricts, + and_congr_right (SpectrumRestricts.nnreal_iff_nnnorm · le_rfl), Set.setOf_and] + refine isClosed_eq ?_ ?_ |>.inter <| isClosed_le ?_ ?_ + all_goals fun_prop + +end CStarRing + end CStar_nonunital diff --git a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Restrict.lean b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Restrict.lean index b3720734734ab..9a2bf73293ea6 100644 --- a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Restrict.lean +++ b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Restrict.lean @@ -3,7 +3,7 @@ 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.Analysis.Normed.Algebra.Spectrum +import Mathlib.Topology.Algebra.Algebra import Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.NonUnital /-! # Restriction of the continuous functional calculus to a scalar subring @@ -84,9 +84,8 @@ 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)) [CompactSpace (spectrum S a)] : + (halg : UniformEmbedding (algebraMap R S)) : ClosedEmbedding (h.starAlgHom φ) := - have := h.compactSpace hφ.comp <| UniformEmbedding.toClosedEmbedding <| .comp (ContinuousMap.uniformEmbedding_comp _ halg) (UniformEquiv.arrowCongr h.homeomorph.symm (.refl _) |>.uniformEmbedding) @@ -96,14 +95,13 @@ characterized by: `q a` and the spectrum of `a` restricts to the scalar subring `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) - (h : ∀ a, p a ↔ q a ∧ SpectrumRestricts a f) (h_cpct : ∀ a, q a → CompactSpace (spectrum S a)) : + (h : ∀ a, p a ↔ q a ∧ SpectrumRestricts a f) : ContinuousFunctionalCalculus R p where predicate_zero := h0 exists_cfc_of_predicate a ha := by refine ⟨((h a).mp ha).2.starAlgHom (cfcHom ((h a).mp ha).1 (R := S)), ?hom_closedEmbedding, ?hom_id, ?hom_map_spectrum, ?predicate_hom⟩ case hom_closedEmbedding => - have := h_cpct a ((h a).mp ha).1 exact ((h a).mp ha).2.closedEmbedding_starAlgHom (cfcHom_closedEmbedding ((h a).mp ha).1) halg case hom_id => exact ((h a).mp ha).2.starAlgHom_id <| cfcHom_id ((h a).mp ha).1 @@ -136,14 +134,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)) - {a : A} (hpa : p a) (hqa : q a) (h : SpectrumRestricts a f) [CompactSpace (spectrum S a)] : + {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) - (hqa : q a) (h : SpectrumRestricts a f) [CompactSpace (spectrum S a)] (g : R → R) : + (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) · rw [cfc_apply g a, cfcHom_eq_restrict f halg hpa hqa h, SpectrumRestricts.starAlgHom_apply, @@ -154,7 +152,7 @@ lemma cfc_eq_restrict (f : C(S, R)) (halg : UniformEmbedding (algebraMap R S)) { · have : ¬ ContinuousOn (fun x ↦ algebraMap R S (g (f x)) : S → S) (spectrum S a) := by refine fun hg' ↦ hg ?_ rw [halg.embedding.continuousOn_iff] - simpa [halg.embedding.continuousOn_iff, Function.comp, h.left_inv _] using + simpa [halg.embedding.continuousOn_iff, Function.comp_def, h.left_inv _] using hg'.comp halg.embedding.continuous.continuousOn (fun _ : R ↦ spectrum.algebraMap_mem S) rw [cfc_apply_of_not_continuousOn a hg, cfc_apply_of_not_continuousOn a this] @@ -220,9 +218,8 @@ 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)) [h_cpct : CompactSpace (σₙ S a)] : + (halg : UniformEmbedding (algebraMap R S)) : ClosedEmbedding (h.nonUnitalStarAlgHom φ) := by - have := h.compactSpace have : h.homeomorph.symm 0 = 0 := Subtype.ext (map_zero <| algebraMap _ _) refine hφ.comp <| UniformEmbedding.toClosedEmbedding <| .comp (ContinuousMapZero.uniformEmbedding_comp _ halg) @@ -235,7 +232,7 @@ characterized by: `q a` and the quasispectrum of `a` restricts to the scalar sub `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) - (h : ∀ a, p a ↔ q a ∧ QuasispectrumRestricts a f) (h_cpct : ∀ a, q a → CompactSpace (σₙ S a)) : + (h : ∀ a, p a ↔ q a ∧ QuasispectrumRestricts a f) : NonUnitalContinuousFunctionalCalculus R p where predicate_zero := h0 exists_cfc_of_predicate a ha := by @@ -243,7 +240,7 @@ protected theorem cfc (f : C(S, R)) (halg : UniformEmbedding (algebraMap R S)) ( ?hom_closedEmbedding, ?hom_id, ?hom_map_spectrum, ?predicate_hom⟩ case hom_closedEmbedding => exact ((h a).mp ha).2.closedEmbedding_nonUnitalStarAlgHom - (cfcₙHom_closedEmbedding ((h a).mp ha).1) halg (h_cpct := h_cpct a ((h a).mp ha).1) + (cfcₙHom_closedEmbedding ((h a).mp ha).1) halg case hom_id => exact ((h a).mp ha).2.nonUnitalStarAlgHom_id <| cfcₙHom_id ((h a).mp ha).1 case hom_map_spectrum => intro g @@ -279,14 +276,14 @@ variable [NonUnitalContinuousFunctionalCalculus R p] variable [UniqueNonUnitalContinuousFunctionalCalculus R A] lemma cfcₙHom_eq_restrict (f : C(S, R)) (halg : UniformEmbedding (algebraMap R S)) {a : A} - (hpa : p a) (hqa : q a) (h : QuasispectrumRestricts a f) [CompactSpace (σₙ S 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) [CompactSpace (σₙ S a)] (g : R → R) : + (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 @@ -300,7 +297,7 @@ lemma cfcₙ_eq_restrict (f : C(S, R)) (halg : UniformEmbedding (algebraMap R S) · have : ¬ ContinuousOn (fun x ↦ algebraMap R S (g (f x)) : S → S) (σₙ S a) := by refine fun hg' ↦ hg ?_ rw [halg.embedding.continuousOn_iff] - simpa [halg.embedding.continuousOn_iff, Function.comp, h.left_inv _] using + simpa [halg.embedding.continuousOn_iff, Function.comp_def, h.left_inv _] using hg'.comp halg.embedding.continuous.continuousOn (fun _ : R ↦ quasispectrum.algebraMap_mem S) rw [cfcₙ_apply_of_not_continuousOn a hg, cfcₙ_apply_of_not_continuousOn a this] diff --git a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Unital.lean b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Unital.lean index 796456e6c6588..5356a80d18bdf 100644 --- a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Unital.lean +++ b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Unital.lean @@ -5,7 +5,7 @@ Authors: Jireh Loreaux -/ import Mathlib.Algebra.Algebra.Quasispectrum import Mathlib.Algebra.Algebra.Spectrum -import Mathlib.Algebra.Star.Order +import Mathlib.Algebra.Order.Star.Basic import Mathlib.Topology.Algebra.Polynomial import Mathlib.Topology.ContinuousFunction.Algebra import Mathlib.Tactic.ContinuousFunctionalCalculus @@ -107,7 +107,7 @@ b = cfc id b = cfc (NNReal.sqrt ∘ (· ^ 2)) b = + `cfc : (R → R) → A → A`: an unbundled version of `cfcHom` which takes the junk value `0` when `cfcHom` is not defined. + `cfcUnits`: builds a unit from `cfc f a` when `f` is nonzero and continuous on the - specturm of `a`. + spectrum of `a`. ## Main theorems @@ -260,6 +260,18 @@ theorem cfcHom_comp [UniqueContinuousFunctionalCalculus R A] (f : C(spectrum R a end cfcHom +section cfcL + +/-- `cfcHom` bundled as a continuous linear map. -/ +@[simps apply] +noncomputable def cfcL {a : A} (ha : p a) : C(spectrum R a, R) →L[R] A := + { cfcHom ha with + toFun := cfcHom ha + map_smul' := map_smul _ + cont := (cfcHom_closedEmbedding ha).continuous } + +end cfcL + section CFC open scoped Classical in @@ -310,6 +322,10 @@ lemma cfcHom_eq_cfc_extend {a : A} (g : R → R) (ha : p a) (f : C(spectrum R a, rw [cfc_apply ..] congr! +lemma cfc_eq_cfcL {a : A} {f : R → R} (ha : p a) (hf : ContinuousOn f (spectrum R a)) : + cfc f a = cfcL ha ⟨_, hf.restrict⟩ := by + rw [cfc_def, dif_pos ⟨ha, hf⟩, cfcL_apply] + lemma cfc_cases (P : A → Prop) (a : A) (f : R → R) (h₀ : P 0) (haf : (hf : ContinuousOn f (spectrum R a)) → (ha : p a) → P (cfcHom ha ⟨_, hf.restrict⟩)) : P (cfc f a) := by @@ -564,7 +580,7 @@ lemma cfc_comp_smul {S : Type*} [SMul S R] [ContinuousConstSMul S R] [SMulZeroCl rw [cfc_comp' .., cfc_smul_id ..] lemma cfc_comp_const_mul (r : R) (f : R → R) (a : A) - (hf : ContinuousOn f ((r * ·) '' (spectrum R a)) := by cfc_cont_tac) (ha : p a := by cfc_tac) : + (hf : ContinuousOn f ((r * ·) '' (spectrum R a)) := by cfc_cont_tac) (ha : p a := by cfc_tac) : cfc (f <| r * ·) a = cfc f (r • a) := by rw [cfc_comp' .., cfc_const_mul_id ..] @@ -637,6 +653,7 @@ lemma cfc_algebraMap (r : R) (f : R → R) : cfc f (algebraMap R A r) = algebraM @[simp] lemma cfc_apply_one {f : R → R} : cfc f (1 : A) = algebraMap R A (f 1) := by simpa using cfc_algebraMap (A := A) 1 f +@[simp] instance IsStarNormal.cfc_map (f : R → R) (a : A) : IsStarNormal (cfc f a) where star_comm_self := by rw [Commute, SemiconjBy] @@ -646,6 +663,27 @@ instance IsStarNormal.cfc_map (f : R → R) (a : A) : IsStarNormal (cfc f a) whe exact mul_comm _ _ · simp [cfc_apply_of_not_continuousOn a h] +-- The following two lemmas are just `cfc_predicate`, but specific enough for the `@[simp]` tag. +@[simp] +protected lemma IsSelfAdjoint.cfc [ContinuousFunctionalCalculus R (IsSelfAdjoint : A → Prop)] + {f : R → R} {a : A} : IsSelfAdjoint (cfc f a) := + cfc_predicate _ _ + +@[simp] +lemma cfc_nonneg_of_predicate [PartialOrder A] + [ContinuousFunctionalCalculus R (fun (a : A) => 0 ≤ a)] {f : R → R} {a : A} : 0 ≤ cfc f a := + cfc_predicate _ _ + +variable (R) in +/-- In an `R`-algebra with a continuous functional calculus, every element satisfying the predicate +has nonempty `R`-spectrum. -/ +lemma CFC.spectrum_nonempty [Nontrivial A] (a : A) (ha : p a := by cfc_tac) : + (spectrum R a).Nonempty := by + by_contra! h + apply one_ne_zero (α := A) + rw [← cfc_one R a, ← cfc_zero R a] + exact cfc_congr fun x hx ↦ by simp_all + end CFC end Basic @@ -882,6 +920,14 @@ lemma one_le_cfc (f : R → R) (a : A) (h : ∀ x ∈ spectrum R a, 1 ≤ f x) 1 ≤ cfc f a := by simpa using algebraMap_le_cfc f 1 a h +lemma CFC.le_one {a : A} (h : ∀ x ∈ spectrum R a, x ≤ 1) (ha : p a := by cfc_tac) : + a ≤ 1 := by + simpa using le_algebraMap_of_spectrum_le h + +lemma CFC.one_le {a : A} (h : ∀ x ∈ spectrum R a, 1 ≤ x) (ha : p a := by cfc_tac) : + 1 ≤ a := by + simpa using algebraMap_le_of_le_spectrum h + end Semiring section NNReal @@ -905,7 +951,7 @@ variable {R A : Type*} {p : A → Prop} [OrderedCommRing R] [StarRing R] variable [MetricSpace R] [TopologicalRing R] [ContinuousStar R] variable [∀ (α) [TopologicalSpace α], StarOrderedRing C(α, R)] variable [TopologicalSpace A] [Ring A] [StarRing A] [PartialOrder A] [StarOrderedRing A] -variable [Algebra R A] [ContinuousFunctionalCalculus R p] +variable [Algebra R A] [instCFC : ContinuousFunctionalCalculus R p] variable [NonnegSpectrumClass R A] lemma cfcHom_le_iff {a : A} (ha : p a) {f g : C(spectrum R a, R)} : @@ -923,6 +969,44 @@ lemma cfc_nonpos_iff (f : R → R) (a : A) (hf : ContinuousOn f (spectrum R a) : simp_rw [← neg_nonneg, ← cfc_neg] exact cfc_nonneg_iff (fun x ↦ -f x) a +lemma cfc_le_algebraMap_iff (f : R → R) (r : R) (a : A) + (hf : ContinuousOn f (spectrum R a) := by cfc_cont_tac) (ha : p a := by cfc_tac) : + cfc f a ≤ algebraMap R A r ↔ ∀ x ∈ spectrum R a, f x ≤ r := by + rw [← cfc_const r a, cfc_le_iff ..] + +lemma algebraMap_le_cfc_iff (f : R → R) (r : R) (a : A) + (hf : ContinuousOn f (spectrum R a) := by cfc_cont_tac) (ha : p a := by cfc_tac) : + algebraMap R A r ≤ cfc f a ↔ ∀ x ∈ spectrum R a, r ≤ f x := by + rw [← cfc_const r a, cfc_le_iff ..] + +lemma le_algebraMap_iff_spectrum_le {r : R} {a : A} (ha : p a := by cfc_tac) : + a ≤ algebraMap R A r ↔ ∀ x ∈ spectrum R a, x ≤ r := by + nth_rw 1 [← cfc_id R a] + exact cfc_le_algebraMap_iff id r a + +lemma algebraMap_le_iff_le_spectrum {r : R} {a : A} (ha : p a := by cfc_tac) : + algebraMap R A r ≤ a ↔ ∀ x ∈ spectrum R a, r ≤ x:= by + nth_rw 1 [← cfc_id R a] + exact algebraMap_le_cfc_iff id r a + +lemma cfc_le_one_iff (f : R → R) (a : A) + (hf : ContinuousOn f (spectrum R a) := by cfc_cont_tac) (ha : p a := by cfc_tac) : + cfc f a ≤ 1 ↔ ∀ x ∈ spectrum R a, f x ≤ 1 := by + simpa using cfc_le_algebraMap_iff f 1 a + +lemma one_le_cfc_iff (f : R → R) (a : A) + (hf : ContinuousOn f (spectrum R a) := by cfc_cont_tac) (ha : p a := by cfc_tac) : + 1 ≤ cfc f a ↔ ∀ x ∈ spectrum R a, 1 ≤ f x := by + simpa using algebraMap_le_cfc_iff f 1 a + +lemma CFC.le_one_iff (a : A) (ha : p a := by cfc_tac) : + a ≤ 1 ↔ ∀ x ∈ spectrum R a, x ≤ 1 := by + simpa using le_algebraMap_iff_spectrum_le (r := (1 : R)) (a := a) + +lemma CFC.one_le_iff (a : A) (ha : p a := by cfc_tac) : + 1 ≤ a ↔ ∀ x ∈ spectrum R a, 1 ≤ x := by + simpa using algebraMap_le_iff_le_spectrum (r := (1 : R)) (a := a) + end Ring end Order diff --git a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Unitary.lean b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Unitary.lean index d39bee3d59145..3ff6426b45606 100644 --- a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Unitary.lean +++ b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Unitary.lean @@ -43,8 +43,7 @@ lemma unitary_iff_isStarNormal_and_spectrum_subset_unitary {u : A} : refine and_congr_right fun hu ↦ ?_ nth_rw 1 [← cfc_id ℂ u] rw [cfc_unitary_iff id u, Set.subset_def] - congr! with x - - simp [unitary.mem_iff_star_mul_self] + simp only [id_eq, RCLike.star_def, SetLike.mem_coe, unitary.mem_iff_star_mul_self] lemma mem_unitary_of_spectrum_subset_unitary {u : A} [IsStarNormal u] (hu : spectrum ℂ u ⊆ unitary ℂ) : u ∈ unitary A := diff --git a/Mathlib/Analysis/CStarAlgebra/Matrix.lean b/Mathlib/Analysis/CStarAlgebra/Matrix.lean index 2a7915775d319..49e853c8a1438 100644 --- a/Mathlib/Analysis/CStarAlgebra/Matrix.lean +++ b/Mathlib/Analysis/CStarAlgebra/Matrix.lean @@ -125,14 +125,14 @@ lemma piLp_equiv_toEuclideanCLM (A : Matrix n n 𝕜) (x : EuclideanSpace 𝕜 n rfl /-- An auxiliary definition used only to construct the true `NormedAddCommGroup` (and `Metric`) -structure provided by `Matrix.instMetricSpaceL2Op` and `Matrix.instNormedAddCommGroupL2Op`. -/ +structure provided by `Matrix.instMetricSpaceL2Op` and `Matrix.instNormedAddCommGroupL2Op`. -/ def l2OpNormedAddCommGroupAux : NormedAddCommGroup (Matrix m n 𝕜) := @NormedAddCommGroup.induced ((Matrix m n 𝕜) ≃ₗ[𝕜] (EuclideanSpace 𝕜 n →L[𝕜] EuclideanSpace 𝕜 m)) _ _ _ _ ContinuousLinearMap.toNormedAddCommGroup.toNormedAddGroup _ _ <| (toEuclideanLin.trans toContinuousLinearMap).injective /-- An auxiliary definition used only to construct the true `NormedRing` (and `Metric`) structure -provided by `Matrix.instMetricSpaceL2Op` and `Matrix.instNormedRingL2Op`. -/ +provided by `Matrix.instMetricSpaceL2Op` and `Matrix.instNormedRingL2Op`. -/ def l2OpNormedRingAux : NormedRing (Matrix n n 𝕜) := @NormedRing.induced ((Matrix n n 𝕜) ≃⋆ₐ[𝕜] (EuclideanSpace 𝕜 n →L[𝕜] EuclideanSpace 𝕜 n)) _ _ _ _ ContinuousLinearMap.toNormedRing _ _ toEuclideanCLM.injective diff --git a/Mathlib/Analysis/CStarAlgebra/Module/Constructions.lean b/Mathlib/Analysis/CStarAlgebra/Module/Constructions.lean new file mode 100644 index 0000000000000..7fb42a09b19aa --- /dev/null +++ b/Mathlib/Analysis/CStarAlgebra/Module/Constructions.lean @@ -0,0 +1,345 @@ +/- +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.Analysis.CStarAlgebra.Module.Defs +import Mathlib.Analysis.CStarAlgebra.Module.Synonym +import Mathlib.Topology.MetricSpace.Bilipschitz + +/-! # Constructions of Hilbert C⋆-modules + +In this file we define the following constructions of `CStarModule`s where `A` denotes a C⋆-algebra. +For some of the types listed below, the instance is declared on the type synonym `WithCStarModule E` +(with the notation `C⋆ᵐᵒᵈ E`), instead of on `E` itself; we explain the reasoning behind each +decision below. + +1. `A` as a `CStarModule` over itself. +2. `C⋆ᵐᵒᵈ (E × F)` as a `CStarModule` over `A`, when `E` and `F` are themselves `CStarModule`s over + `A`. +3. `C⋆ᵐᵒᵈ (Π i : ι, E i)` as a `CStarModule` over `A`, when each `E i` is a `CStarModule` over `A` + and `ι` is a `Fintype`. +4. `E` as a `CStarModule` over `ℂ`, when `E` is an `InnerProductSpace` over `ℂ`. + +For `E × F` and `Π i : ι, E i`, we are required to declare the instance on a type synonym rather +than on the product or pi-type itself because the existing norm on these types does not agree with +the one induced by the C⋆-module structure. Moreover, the norm induced by the C⋆-module structure +doesn't agree with any other natural norm on these types (e.g., `WithLp 2 (E × F)` unless `A := ℂ`), +so we need a new synonym. + +On `A` (a C⋆-algebra) and `E` (an inner product space), we declare the instances on the types +themselves to ease the use of the C⋆-module structure. This does have the potential to cause +inconvenience (as sometimes Lean will see terms of type `A` and apply lemmas pertaining to +C⋆-modules to those terms, when the lemmas were actually intended for terms of some other +C⋆-module in context, say `F`, in which case the arguments must be provided explicitly; see for +instance the application of `CStarModule.norm_eq_sqrt_norm_inner_self` in the proof of +`WithCStarModule.max_le_prod_norm` below). However, we believe that this, hopefully rare, +inconvenience is outweighed by avoiding translating between type synonyms where possible. + +For more details on the importance of the `WithCStarModule` type synonym, see the module +documentation for `Analysis.CStarAlgebra.Module.Synonym`. + +## Implementation notes + +When `A := ℂ` and `E := ℂ`, then `ℂ` is both a C⋆-algebra (so it inherits a `CStarModule` instance +via (1) above) and an inner product space (so it inherits a `CStarModule` instance via (4) above). +We provide a sanity check ensuring that these two instances are definitionally equal. We also ensure +that the `Inner ℂ ℂ` instance from `InnerProductSpace` is definitionally equal to the one inherited +from the `CStarModule` instances. + +Note that `C⋆ᵐᵒᵈ E` is *already* equipped with a bornology and uniformity whenever `E` is (namely, +the pullback of the respective structures through `WithCStarModule.equiv`), so in each of the above +cases, it is necessary to temporarily instantiate `C⋆ᵐᵒᵈ E` with `CStarModule.normedAddCommGroup`, +show the resulting type is bilipschitz equivalent to `E` via `WithCStarModule.equiv` (in the first +and last case, this map is actually trivially an isometry), and then replace the uniformity and +bornology with the correct ones. + +-/ + +open CStarModule CStarRing + +namespace WithCStarModule + +variable {A : Type*} [NonUnitalNormedRing A] [StarRing A] [NormedSpace ℂ A] [PartialOrder A] + +/-! ## A C⋆-algebra as a C⋆-module over itself -/ + +section Self + +variable [CStarRing A] [StarOrderedRing A] [SMulCommClass ℂ A A] + +/-- Reinterpret a C⋆-algebra `A` as a `CStarModule` over itself. -/ +instance : CStarModule A A where + inner x y := star x * y + inner_add_right := mul_add .. + inner_self_nonneg := star_mul_self_nonneg _ + inner_self := CStarRing.star_mul_self_eq_zero_iff _ + inner_op_smul_right := mul_assoc .. |>.symm + inner_smul_right_complex := mul_smul_comm .. + star_inner x y := by simp + norm_eq_sqrt_norm_inner_self {x} := by + rw [← sq_eq_sq (norm_nonneg _) (by positivity)] + simpa [sq] using Eq.symm <| CStarRing.norm_star_mul_self + +lemma inner_def (x y : A) : ⟪x, y⟫_A = star x * y := rfl + +end Self + +/-! ## Products of C⋆-modules -/ + +section Prod + +variable {E F : Type*} +variable [NormedAddCommGroup E] [Module ℂ E] [SMul Aᵐᵒᵖ E] +variable [NormedAddCommGroup F] [Module ℂ F] [SMul Aᵐᵒᵖ F] +variable [CStarModule A E] [CStarModule A F] + +noncomputable instance : Norm (C⋆ᵐᵒᵈ (E × F)) where + norm x := √‖⟪x.1, x.1⟫_A + ⟪x.2, x.2⟫_A‖ + +lemma prod_norm (x : C⋆ᵐᵒᵈ (E × F)) : ‖x‖ = √‖⟪x.1, x.1⟫_A + ⟪x.2, x.2⟫_A‖ := rfl + +lemma prod_norm_sq (x : C⋆ᵐᵒᵈ (E × F)) : ‖x‖ ^ 2 = ‖⟪x.1, x.1⟫_A + ⟪x.2, x.2⟫_A‖ := by + simp [prod_norm] + +lemma prod_norm_le_norm_add (x : C⋆ᵐᵒᵈ (E × F)) : ‖x‖ ≤ ‖x.1‖ + ‖x.2‖ := by + refine abs_le_of_sq_le_sq' ?_ (by positivity) |>.2 + calc ‖x‖ ^ 2 ≤ ‖⟪x.1, x.1⟫_A‖ + ‖⟪x.2, x.2⟫_A‖ := prod_norm_sq x ▸ norm_add_le _ _ + _ = ‖x.1‖ ^ 2 + 0 + ‖x.2‖ ^ 2 := by simp [norm_sq_eq] + _ ≤ ‖x.1‖ ^ 2 + 2 * ‖x.1‖ * ‖x.2‖ + ‖x.2‖ ^ 2 := by gcongr; positivity + _ = (‖x.1‖ + ‖x.2‖) ^ 2 := by ring + +variable [StarModule ℂ A] [StarOrderedRing A] + +noncomputable instance : CStarModule A (C⋆ᵐᵒᵈ (E × F)) where + inner x y := inner x.1 y.1 + inner x.2 y.2 + inner_add_right {x y z} := by simpa using add_add_add_comm .. + inner_self_nonneg := add_nonneg CStarModule.inner_self_nonneg CStarModule.inner_self_nonneg + inner_self {x} := by + refine ⟨fun h ↦ ?_, fun h ↦ by simp [h, CStarModule.inner_zero_left]⟩ + apply equiv (E × F) |>.injective + ext + · refine inner_self.mp <| le_antisymm ?_ inner_self_nonneg + exact le_add_of_nonneg_right CStarModule.inner_self_nonneg |>.trans_eq h + · refine inner_self.mp <| le_antisymm ?_ inner_self_nonneg + exact le_add_of_nonneg_left CStarModule.inner_self_nonneg |>.trans_eq h + inner_op_smul_right := by simp [add_mul] + inner_smul_right_complex := by simp [smul_add] + star_inner x y := by simp + norm_eq_sqrt_norm_inner_self {x} := by with_reducible_and_instances rfl + +lemma prod_inner (x y : C⋆ᵐᵒᵈ (E × F)) : ⟪x, y⟫_A = ⟪x.1, y.1⟫_A + ⟪x.2, y.2⟫_A := rfl + +variable [CStarRing A] [SMulCommClass ℂ A A] [IsScalarTower ℂ A A] [CompleteSpace A] + +lemma max_le_prod_norm (x : C⋆ᵐᵒᵈ (E × F)) : max ‖x.1‖ ‖x.2‖ ≤ ‖x‖ := by + rw [prod_norm] + simp only [equiv_fst, norm_eq_sqrt_norm_inner_self (E := E), + norm_eq_sqrt_norm_inner_self (E := F), equiv_snd, max_le_iff, norm_nonneg, + Real.sqrt_le_sqrt_iff] + constructor + all_goals + apply norm_le_norm_of_nonneg_of_le + all_goals + aesop (add safe apply CStarModule.inner_self_nonneg) + +lemma norm_equiv_le_norm_prod (x : C⋆ᵐᵒᵈ (E × F)) : ‖equiv (E × F) x‖ ≤ ‖x‖ := + max_le_prod_norm x + +section Aux + +-- We temporarily disable the uniform space and bornology on `C⋆ᵐᵒᵈ A` while proving +-- that those induced by the new norm are equal to the old ones. +attribute [-instance] WithCStarModule.instUniformSpace WithCStarModule.instBornology +attribute [local instance] CStarModule.normedAddCommGroup + +open Filter Uniformity Bornology + +private lemma antilipschitzWith_two_equiv_prod_aux : AntilipschitzWith 2 (equiv (E × F)) := + AddMonoidHomClass.antilipschitz_of_bound (linearEquiv ℂ (E × F)) fun x ↦ by + apply prod_norm_le_norm_add x |>.trans + simp only [NNReal.coe_ofNat, linearEquiv_apply, two_mul] + gcongr + · exact norm_fst_le x + · exact norm_snd_le x + +private lemma lipschitzWith_one_equiv_prod_aux : LipschitzWith 1 (equiv (E × F)) := + AddMonoidHomClass.lipschitz_of_bound_nnnorm (linearEquiv ℂ (E × F)) 1 <| by + simpa using norm_equiv_le_norm_prod + +private lemma uniformity_prod_eq_aux : + 𝓤[(inferInstance : UniformSpace (E × F)).comap <| equiv _] = 𝓤 (C⋆ᵐᵒᵈ (E × F)) := + uniformity_eq_of_bilipschitz antilipschitzWith_two_equiv_prod_aux lipschitzWith_one_equiv_prod_aux + +private lemma isBounded_prod_iff_aux (s : Set (C⋆ᵐᵒᵈ (E × F))) : + @IsBounded _ (induced <| equiv (E × F)) s ↔ IsBounded s := + isBounded_iff_of_bilipschitz antilipschitzWith_two_equiv_prod_aux + lipschitzWith_one_equiv_prod_aux s + +end Aux + +noncomputable instance : NormedAddCommGroup (C⋆ᵐᵒᵈ (E × F)) := + .ofCoreReplaceAll normedSpaceCore uniformity_prod_eq_aux isBounded_prod_iff_aux + +instance : NormedSpace ℂ (C⋆ᵐᵒᵈ (E × F)) := .ofCore normedSpaceCore + +end Prod + +/-! ## Pi-types of C⋆-modules -/ + +section Pi + +variable {ι : Type*} {E : ι → Type*} [Fintype ι] +variable [∀ i, NormedAddCommGroup (E i)] [∀ i, Module ℂ (E i)] [∀ i, SMul Aᵐᵒᵖ (E i)] +variable [∀ i, CStarModule A (E i)] + +noncomputable instance : Norm (C⋆ᵐᵒᵈ (Π i, E i)) where + norm x := √‖∑ i, ⟪x i, x i⟫_A‖ + +lemma pi_norm (x : C⋆ᵐᵒᵈ (Π i, E i)) : ‖x‖ = √‖∑ i, ⟪x i, x i⟫_A‖ := by + with_reducible_and_instances rfl + +lemma pi_norm_sq (x : C⋆ᵐᵒᵈ (Π i, E i)) : ‖x‖ ^ 2 = ‖∑ i, ⟪x i, x i⟫_A‖ := by + simp [pi_norm] + +open Finset in +lemma pi_norm_le_sum_norm (x : C⋆ᵐᵒᵈ (Π i, E i)) : ‖x‖ ≤ ∑ i, ‖x i‖ := by + refine abs_le_of_sq_le_sq' ?_ (by positivity) |>.2 + calc ‖x‖ ^ 2 ≤ ∑ i, ‖⟪x i, x i⟫_A‖ := pi_norm_sq x ▸ norm_sum_le _ _ + _ = ∑ i, ‖x i‖ ^ 2 := by simp only [norm_sq_eq] + _ ≤ (∑ i, ‖x i‖) ^ 2 := sum_sq_le_sq_sum_of_nonneg (fun _ _ ↦ norm_nonneg _) + +variable [StarModule ℂ A] [StarOrderedRing A] + +open Finset in +noncomputable instance : CStarModule A (C⋆ᵐᵒᵈ (Π i, E i)) where + inner x y := ∑ i, inner (x i) (y i) + inner_add_right {x y z} := by simp [inner_sum_right, sum_add_distrib] + inner_self_nonneg := sum_nonneg <| fun _ _ ↦ CStarModule.inner_self_nonneg + inner_self {x} := by + refine ⟨fun h ↦ ?_, fun h ↦ by simp [h, CStarModule.inner_zero_left]⟩ + ext i + refine inner_self.mp <| le_antisymm (le_of_le_of_eq ?_ h) inner_self_nonneg + exact single_le_sum (fun i _ ↦ CStarModule.inner_self_nonneg (x := x i)) (mem_univ _) + inner_op_smul_right := by simp [sum_mul] + inner_smul_right_complex := by simp [smul_sum] + star_inner x y := by simp + norm_eq_sqrt_norm_inner_self {x} := by with_reducible_and_instances rfl + +lemma pi_inner (x y : C⋆ᵐᵒᵈ (Π i, E i)) : ⟪x, y⟫_A = ∑ i, ⟪x i, y i⟫_A := rfl + +@[simp] +lemma inner_single_left [DecidableEq ι] (x : C⋆ᵐᵒᵈ (Π i, E i)) {i : ι} (y : E i) : + ⟪equiv _ |>.symm <| Pi.single i y, x⟫_A = ⟪y, x i⟫_A := by + simp only [pi_inner, equiv_symm_pi_apply] + rw [Finset.sum_eq_single i] + all_goals simp_all + +@[simp] +lemma inner_single_right [DecidableEq ι] (x : C⋆ᵐᵒᵈ (Π i, E i)) {i : ι} (y : E i) : + ⟪x, equiv _ |>.symm <| Pi.single i y⟫_A = ⟪x i, y⟫_A := by + simp only [pi_inner, equiv_symm_pi_apply] + rw [Finset.sum_eq_single i] + all_goals simp_all + +variable [CStarRing A] [SMulCommClass ℂ A A] [IsScalarTower ℂ A A] [CompleteSpace A] + +@[simp] +lemma norm_single [DecidableEq ι] (i : ι) (y : E i) : + ‖equiv _ |>.symm <| Pi.single i y‖ = ‖y‖ := by + let _ : NormedAddCommGroup (C⋆ᵐᵒᵈ (Π i, E i)) := normedAddCommGroup + rw [← sq_eq_sq (by positivity) (by positivity)] + simp [norm_sq_eq] + +lemma norm_apply_le_norm (x : C⋆ᵐᵒᵈ (Π i, E i)) (i : ι) : ‖x i‖ ≤ ‖x‖ := by + let _ : NormedAddCommGroup (C⋆ᵐᵒᵈ (Π i, E i)) := normedAddCommGroup + refine abs_le_of_sq_le_sq' ?_ (by positivity) |>.2 + rw [pi_norm_sq, norm_sq_eq] + refine norm_le_norm_of_nonneg_of_le inner_self_nonneg ?_ + exact Finset.single_le_sum (fun j _ ↦ inner_self_nonneg (x := x j)) (Finset.mem_univ i) + +open Finset in +lemma norm_equiv_le_norm_pi (x : C⋆ᵐᵒᵈ (Π i, E i)) : ‖equiv _ x‖ ≤ ‖x‖ := by + let _ : NormedAddCommGroup (C⋆ᵐᵒᵈ (Π i, E i)) := normedAddCommGroup + rw [pi_norm_le_iff_of_nonneg (by positivity)] + simpa using norm_apply_le_norm x + +section Aux + +-- We temporarily disable the uniform space and bornology on `C⋆ᵐᵒᵈ A` while proving +-- that those induced by the new norm are equal to the old ones. +attribute [-instance] WithCStarModule.instUniformSpace WithCStarModule.instBornology +attribute [local instance] CStarModule.normedAddCommGroup + +open Uniformity Bornology + +private lemma antilipschitzWith_card_equiv_pi_aux : + AntilipschitzWith (Fintype.card ι) (equiv (Π i, E i)) := + AddMonoidHomClass.antilipschitz_of_bound (linearEquiv ℂ (Π i, E i)) fun x ↦ by + simp only [NNReal.coe_natCast, linearEquiv_apply] + calc ‖x‖ ≤ ∑ i, ‖x i‖ := pi_norm_le_sum_norm x + _ ≤ ∑ _, ‖⇑x‖ := Finset.sum_le_sum fun _ _ ↦ norm_le_pi_norm .. + _ ≤ Fintype.card ι * ‖⇑x‖ := by simp + +private lemma lipschitzWith_one_equiv_pi_aux : LipschitzWith 1 (equiv (Π i, E i)) := + AddMonoidHomClass.lipschitz_of_bound_nnnorm (linearEquiv ℂ (Π i, E i)) 1 <| by + simpa using norm_equiv_le_norm_pi + +private lemma uniformity_pi_eq_aux : + 𝓤[(inferInstance : UniformSpace (Π i, E i)).comap <| equiv _] = 𝓤 (C⋆ᵐᵒᵈ (Π i, E i)) := + uniformity_eq_of_bilipschitz antilipschitzWith_card_equiv_pi_aux lipschitzWith_one_equiv_pi_aux + +private lemma isBounded_pi_iff_aux (s : Set (C⋆ᵐᵒᵈ (Π i, E i))) : + @IsBounded _ (induced <| equiv (Π i, E i)) s ↔ IsBounded s := + isBounded_iff_of_bilipschitz antilipschitzWith_card_equiv_pi_aux lipschitzWith_one_equiv_pi_aux s + +end Aux + +noncomputable instance : NormedAddCommGroup (C⋆ᵐᵒᵈ (Π i, E i)) := + .ofCoreReplaceAll normedSpaceCore uniformity_pi_eq_aux isBounded_pi_iff_aux + +instance : NormedSpace ℂ (C⋆ᵐᵒᵈ (Π i, E i)) := .ofCore normedSpaceCore + +end Pi + +/-! ## Inner product spaces as C⋆-modules -/ + +section InnerProductSpace + +open ComplexOrder + +variable {E : Type*} +variable [NormedAddCommGroup E] [InnerProductSpace ℂ E] +variable [instSMulOp : SMul ℂᵐᵒᵖ E] [instCentral : IsCentralScalar ℂ E] + +/-- Reinterpret an inner product space `E` over `ℂ` as a `CStarModule` over `ℂ`. + +Note: this instance requires `SMul ℂᵐᵒᵖ E` and `IsCentralScalar ℂ E` instances to exist on `E`, +which is unlikely to occur in practice. However, in practice one could either add those instances +to the type `E` in question, or else supply them to this instance manually, which is reason behind +the naming of these two instance arguments. -/ +instance instCStarModuleComplex : CStarModule ℂ E where + inner x y := ⟪x, y⟫_ℂ + inner_add_right := _root_.inner_add_right .. + inner_self_nonneg {x} := by + simp only + rw [← inner_self_ofReal_re, RCLike.ofReal_nonneg] + exact inner_self_nonneg + inner_self := inner_self_eq_zero + inner_op_smul_right := by simp [inner_smul_right, mul_comm] + inner_smul_right_complex := inner_smul_right .. + star_inner _ _ := inner_conj_symm .. + norm_eq_sqrt_norm_inner_self {x} := by + simpa only [← inner_self_re_eq_norm] using norm_eq_sqrt_inner x + +-- Ensures that the two ways to obtain `CStarModule ℂ ℂ` are definitionally equal. +example : instCStarModule (A := ℂ) = instCStarModuleComplex := by with_reducible_and_instances rfl + +/- Ensures that the two `Inner ℂ ℂ` instances are definitionally equal. Note that this cannot be at +reducible and instances transparency because the one from `InnerProductSpace` uses `StarRingEnd` +whereas `WithCStarModule.instCStarModule.toInner` uses `star` since `A` may not be commutative. -/ +example : (toInner : Inner ℂ ℂ) = WithCStarModule.instCStarModule.toInner := rfl + +end InnerProductSpace + +end WithCStarModule diff --git a/Mathlib/Analysis/CStarAlgebra/Module/Defs.lean b/Mathlib/Analysis/CStarAlgebra/Module/Defs.lean index daf2909a3ed1a..1c4045a1ebb24 100644 --- a/Mathlib/Analysis/CStarAlgebra/Module/Defs.lean +++ b/Mathlib/Analysis/CStarAlgebra/Module/Defs.lean @@ -168,7 +168,7 @@ lemma norm_sq_eq {x : E} : ‖x‖ ^ 2 = ‖⟪x, x⟫‖ := by simp [norm_eq_sq section include A -protected lemma norm_nonneg {x : E} : 0 ≤ ‖x‖ := by simp [norm_eq_sqrt_norm_inner_self]; positivity +protected lemma norm_nonneg {x : E} : 0 ≤ ‖x‖ := by simp [norm_eq_sqrt_norm_inner_self] protected lemma norm_pos {x : E} (hx : x ≠ 0) : 0 < ‖x‖ := by simp only [norm_eq_sqrt_norm_inner_self, Real.sqrt_pos, norm_pos_iff] diff --git a/Mathlib/Analysis/CStarAlgebra/Module/Synonym.lean b/Mathlib/Analysis/CStarAlgebra/Module/Synonym.lean index e98ec70042e6b..afee7eea2b49e 100644 --- a/Mathlib/Analysis/CStarAlgebra/Module/Synonym.lean +++ b/Mathlib/Analysis/CStarAlgebra/Module/Synonym.lean @@ -16,10 +16,8 @@ this reason, we create a type synonym `WithCStarModule` which is endowed with th The common use cases are, when `A` is a C⋆-algebra: -+ `A` itself over `A` + `E × F` where `E` and `F` are `CStarModule`s over `A` + `Π i, E i` where `E i` is a `CStarModule` over `A` and `i : ι` with `ι` a `Fintype` -+ `E` where `E` is an `InnerProductSpace` over `ℂ` In this way, the set up is very similar to the `WithLp` type synonym, although there is no way to reuse `WithLp` because the norms *do not* coincide in general. @@ -31,9 +29,9 @@ C⋆-algebra, then so is `A × A`, and therefore we may consider both `A` and `A over themselves, respectively. However, we may *also* consider `A × A` as a `CStarModule` over `A`. However, by utilizing the type synonym, these actually correspond to *different types*, namely: -+ `A` as a `CStarModule` over `A` corresponds to `C⋆ᵐᵒᵈ A` -+ `A × A` as a `CStarModule` over `A × A` corresponds to `C⋆ᵐᵒᵈ (A × A)` -+ `A × A` as a `CStarModule` over `A` corresponds to `C⋆ᵐᵒᵈ (C⋆ᵐᵒᵈ A × C⋆ᵐᵒᵈ A)` ++ `A` as a `CStarModule` over `A` corresponds to `A` ++ `A × A` as a `CStarModule` over `A × A` corresponds to `A × A` ++ `A × A` as a `CStarModule` over `A` corresponds to `C⋆ᵐᵒᵈ (A × A)` ## Main definitions diff --git a/Mathlib/Analysis/CStarAlgebra/Unitization.lean b/Mathlib/Analysis/CStarAlgebra/Unitization.lean index 0ccc38b7262f0..d664e50c7c219 100644 --- a/Mathlib/Analysis/CStarAlgebra/Unitization.lean +++ b/Mathlib/Analysis/CStarAlgebra/Unitization.lean @@ -129,7 +129,7 @@ instance Unitization.instCStarRing : CStarRing (Unitization 𝕜 E) where norm_mul_self_le x := by -- rewrite both sides as a `⊔` simp only [Unitization.norm_def, Prod.norm_def, ← sup_eq_max] - -- Show that `(Unitization.splitMul 𝕜 E x).snd` satisifes the C⋆-property, in two stages: + -- Show that `(Unitization.splitMul 𝕜 E x).snd` satisfies the C⋆-property, in two stages: have h₁ : ∀ x : Unitization 𝕜 E, ‖(Unitization.splitMul 𝕜 E x).snd‖ ≤ ‖(Unitization.splitMul 𝕜 E (star x)).snd‖ := by simp only [add_zero, Unitization.splitMul_apply, Unitization.snd_star, Unitization.fst_star] diff --git a/Mathlib/Analysis/Calculus/BumpFunction/FiniteDimension.lean b/Mathlib/Analysis/Calculus/BumpFunction/FiniteDimension.lean index d2928d8ac311c..314fbbe3fa861 100644 --- a/Mathlib/Analysis/Calculus/BumpFunction/FiniteDimension.lean +++ b/Mathlib/Analysis/Calculus/BumpFunction/FiniteDimension.lean @@ -412,7 +412,7 @@ theorem y_pos_of_mem_ball {D : ℝ} {x : E} (Dpos : 0 < D) (D_lt_one : D < 1) · apply ball_subset_ball' _ hy simp only [hz, norm_smul, abs_of_nonneg Dpos.le, abs_of_nonneg B.le, dist_zero_right, Real.norm_eq_abs, abs_div] - simp only [div_le_iff B, field_simps] + simp only [div_le_iff₀ B, field_simps] ring_nf rfl · have ID : ‖D / (1 + D) - 1‖ = 1 / (1 + D) := by @@ -425,7 +425,7 @@ theorem y_pos_of_mem_ball {D : ℝ} {x : E} (Dpos : 0 < D) (D_lt_one : D < 1) rw [← mem_closedBall_iff_norm'] apply closedBall_subset_closedBall' _ (ball_subset_closedBall hy) rw [← one_smul ℝ x, dist_eq_norm, hz, ← sub_smul, one_smul, norm_smul, ID] - simp only [B.ne', div_le_iff B, field_simps] + simp only [B.ne', div_le_iff₀ B, field_simps] nlinarith only [hx, D_lt_one] apply lt_of_lt_of_le _ (measure_mono C) apply measure_ball_pos diff --git a/Mathlib/Analysis/Calculus/BumpFunction/Normed.lean b/Mathlib/Analysis/Calculus/BumpFunction/Normed.lean index fb8c29c0c7405..1846ced215ae9 100644 --- a/Mathlib/Analysis/Calculus/BumpFunction/Normed.lean +++ b/Mathlib/Analysis/Calculus/BumpFunction/Normed.lean @@ -124,7 +124,7 @@ theorem measure_closedBall_div_le_integral [IsAddHaarMeasure μ] (K : ℝ) (h : have K_pos : 0 < K := by simpa [f.rIn_pos, not_lt.2 f.rIn_pos.le] using mul_pos_iff.1 (f.rOut_pos.trans_le h) apply le_trans _ (f.measure_closedBall_le_integral μ) - rw [div_le_iff (pow_pos K_pos _), addHaar_closedBall' _ _ f.rIn_pos.le, + rw [div_le_iff₀ (pow_pos K_pos _), addHaar_closedBall' _ _ f.rIn_pos.le, addHaar_closedBall' _ _ f.rOut_pos.le, ENNReal.toReal_mul, ENNReal.toReal_mul, ENNReal.toReal_ofReal (pow_nonneg f.rOut_pos.le _), ENNReal.toReal_ofReal (pow_nonneg f.rIn_pos.le _), mul_assoc, mul_comm _ (K ^ _), ← mul_assoc, @@ -142,7 +142,7 @@ theorem normed_le_div_measure_closedBall_rOut [IsAddHaarMeasure μ] (K : ℝ) (h · exact f.integral_pos.le · exact f.le_one apply this.trans - rw [div_le_div_iff f.integral_pos, one_mul, ← div_le_iff' (pow_pos K_pos _)] + rw [div_le_div_iff f.integral_pos, one_mul, ← div_le_iff₀' (pow_pos K_pos _)] · exact f.measure_closedBall_div_le_integral μ K h · exact ENNReal.toReal_pos (measure_closedBall_pos _ _ f.rOut_pos).ne' measure_closedBall_lt_top.ne diff --git a/Mathlib/Analysis/Calculus/Conformal/NormedSpace.lean b/Mathlib/Analysis/Calculus/Conformal/NormedSpace.lean index b64a5bf2e5cc8..5e7a4a62baea7 100644 --- a/Mathlib/Analysis/Calculus/Conformal/NormedSpace.lean +++ b/Mathlib/Analysis/Calculus/Conformal/NormedSpace.lean @@ -63,7 +63,7 @@ theorem conformalAt_const_smul {c : ℝ} (h : c ≠ 0) (x : X) : ConformalAt (fu theorem Subsingleton.conformalAt [Subsingleton X] (f : X → Y) (x : X) : ConformalAt f x := ⟨0, hasFDerivAt_of_subsingleton _ _, isConformalMap_of_subsingleton _⟩ -/-- A function is a conformal map if and only if its differential is a conformal linear map-/ +/-- A function is a conformal map if and only if its differential is a conformal linear map -/ theorem conformalAt_iff_isConformalMap_fderiv {f : X → Y} {x : X} : ConformalAt f x ↔ IsConformalMap (fderiv ℝ f x) := by constructor diff --git a/Mathlib/Analysis/Calculus/ContDiff/Basic.lean b/Mathlib/Analysis/Calculus/ContDiff/Basic.lean index bc047658d41d0..5f5e8ede6c4c1 100644 --- a/Mathlib/Analysis/Calculus/ContDiff/Basic.lean +++ b/Mathlib/Analysis/Calculus/ContDiff/Basic.lean @@ -299,7 +299,7 @@ point in a domain. -/ theorem ContinuousLinearEquiv.comp_contDiffWithinAt_iff (e : F ≃L[𝕜] G) : ContDiffWithinAt 𝕜 n (e ∘ f) s x ↔ ContDiffWithinAt 𝕜 n f s x := ⟨fun H => by - simpa only [(· ∘ ·), e.symm.coe_coe, e.symm_apply_apply] using + simpa only [Function.comp_def, e.symm.coe_coe, e.symm_apply_apply] using H.continuousLinearMap_comp (e.symm : G →L[𝕜] F), fun H => H.continuousLinearMap_comp (e : F →L[𝕜] G)⟩ @@ -432,7 +432,7 @@ theorem ContinuousLinearEquiv.contDiffWithinAt_comp_iff (e : G ≃L[𝕜] E) : ContDiffWithinAt 𝕜 n (f ∘ e) (e ⁻¹' s) (e.symm x) ↔ ContDiffWithinAt 𝕜 n f s x := by constructor · intro H - simpa [← preimage_comp, (· ∘ ·)] using H.comp_continuousLinearMap (e.symm : E →L[𝕜] G) + simpa [← preimage_comp, Function.comp_def] using H.comp_continuousLinearMap (e.symm : E →L[𝕜] G) · intro H rw [← e.apply_symm_apply x, ← e.coe_coe] at H exact H.comp_continuousLinearMap _ @@ -448,8 +448,8 @@ theorem ContinuousLinearEquiv.contDiffAt_comp_iff (e : G ≃L[𝕜] E) : domains. -/ theorem ContinuousLinearEquiv.contDiffOn_comp_iff (e : G ≃L[𝕜] E) : ContDiffOn 𝕜 n (f ∘ e) (e ⁻¹' s) ↔ ContDiffOn 𝕜 n f s := - ⟨fun H => by simpa [(· ∘ ·)] using H.comp_continuousLinearMap (e.symm : E →L[𝕜] G), fun H => - H.comp_continuousLinearMap (e : G →L[𝕜] E)⟩ + ⟨fun H => by simpa [Function.comp_def] using H.comp_continuousLinearMap (e.symm : E →L[𝕜] G), + fun H => H.comp_continuousLinearMap (e : G →L[𝕜] E)⟩ /-- Composition by continuous linear equivs on the right respects higher differentiability. -/ theorem ContinuousLinearEquiv.contDiff_comp_iff (e : G ≃L[𝕜] E) : @@ -882,7 +882,7 @@ then there is a function `f' : E → F →L[𝕜] G` that is `C^n` at `x₀` wit sufficiently close to `x₀` within `s ∪ {x₀}` the function `y ↦ f x y` has derivative `f' x` at `g x` within `t ⊆ F`. For convenience, we return an explicit set of `x`'s where this holds that is a subset of `s ∪ {x₀}`. We need one additional condition, namely that `t` is a neighborhood of -`g(x₀)` within `g '' s`. -/ +`g(x₀)` within `g '' s`. -/ theorem ContDiffWithinAt.hasFDerivWithinAt_nhds {f : E → F → G} {g : E → F} {t : Set F} {n : ℕ} {x₀ : E} (hf : ContDiffWithinAt 𝕜 (n + 1) (uncurry f) (insert x₀ s ×ˢ t) (x₀, g x₀)) (hg : ContDiffWithinAt 𝕜 n g s x₀) (hgt : t ∈ 𝓝[g '' s] g x₀) : @@ -1042,7 +1042,7 @@ continuous. -/ theorem ContDiffOn.continuousOn_fderivWithin_apply (hf : ContDiffOn 𝕜 n f s) (hs : UniqueDiffOn 𝕜 s) (hn : 1 ≤ n) : ContinuousOn (fun p : E × E => (fderivWithin 𝕜 f s p.1 : E → F) p.2) (s ×ˢ univ) := - (contDiffOn_fderivWithin_apply hf hs <| by rwa [zero_add]).continuousOn + (contDiffOn_fderivWithin_apply (m := 0) hf hs hn).continuousOn /-- The bundled derivative of a `C^{n+1}` function is `C^n`. -/ theorem ContDiff.contDiff_fderiv_apply {f : E → F} (hf : ContDiff 𝕜 n f) (hmn : m + 1 ≤ n) : @@ -1948,3 +1948,5 @@ theorem ContDiff.restrict_scalars (h : ContDiff 𝕜' n f) : ContDiff 𝕜 n f : contDiff_iff_contDiffAt.2 fun _ => h.contDiffAt.restrict_scalars _ end RestrictScalars + +set_option linter.style.longFile 2100 diff --git a/Mathlib/Analysis/Calculus/ContDiff/Defs.lean b/Mathlib/Analysis/Calculus/ContDiff/Defs.lean index 1bde1bf2752a2..07eb8aa5454b7 100644 --- a/Mathlib/Analysis/Calculus/ContDiff/Defs.lean +++ b/Mathlib/Analysis/Calculus/ContDiff/Defs.lean @@ -1598,3 +1598,5 @@ theorem ContDiff.continuous_fderiv_apply (h : ContDiff 𝕜 n f) (hn : 1 ≤ n) have B : Continuous fun p : E × E => (fderiv 𝕜 f p.1, p.2) := ((h.continuous_fderiv hn).comp continuous_fst).prod_mk continuous_snd A.comp B + +set_option linter.style.longFile 1700 diff --git a/Mathlib/Analysis/Calculus/Deriv/Add.lean b/Mathlib/Analysis/Calculus/Deriv/Add.lean index d49ad898b452c..6f51814995811 100644 --- a/Mathlib/Analysis/Calculus/Deriv/Add.lean +++ b/Mathlib/Analysis/Calculus/Deriv/Add.lean @@ -23,9 +23,9 @@ derivative universe u v w open scoped Classical -open Topology Filter ENNReal +open scoped Topology Filter ENNReal -open Filter Asymptotics Set +open Asymptotics Set variable {𝕜 : Type u} [NontriviallyNormedField 𝕜] variable {F : Type v} [NormedAddCommGroup F] [NormedSpace 𝕜 F] diff --git a/Mathlib/Analysis/Calculus/Deriv/Comp.lean b/Mathlib/Analysis/Calculus/Deriv/Comp.lean index 0bd8b9fd5f895..bb0e4bdc37b52 100644 --- a/Mathlib/Analysis/Calculus/Deriv/Comp.lean +++ b/Mathlib/Analysis/Calculus/Deriv/Comp.lean @@ -34,8 +34,7 @@ derivative, chain rule universe u v w -open scoped Classical -open Topology Filter ENNReal +open scoped Classical Topology Filter ENNReal open Filter Asymptotics Set diff --git a/Mathlib/Analysis/Calculus/Deriv/Inv.lean b/Mathlib/Analysis/Calculus/Deriv/Inv.lean index 0c5de84efda13..ffa6762826f8e 100644 --- a/Mathlib/Analysis/Calculus/Deriv/Inv.lean +++ b/Mathlib/Analysis/Calculus/Deriv/Inv.lean @@ -23,9 +23,7 @@ derivative universe u v w -open scoped Classical -open Topology Filter ENNReal - +open scoped Classical Topology ENNReal open Filter Asymptotics Set open ContinuousLinearMap (smulRight smulRight_one_eq_iff) diff --git a/Mathlib/Analysis/Calculus/Deriv/Inverse.lean b/Mathlib/Analysis/Calculus/Deriv/Inverse.lean index d2524c850858d..424877d8f983b 100644 --- a/Mathlib/Analysis/Calculus/Deriv/Inverse.lean +++ b/Mathlib/Analysis/Calculus/Deriv/Inverse.lean @@ -24,9 +24,7 @@ derivative, inverse function universe u v w -open scoped Classical -open Topology Filter ENNReal - +open scoped Classical Topology ENNReal open Filter Asymptotics Set variable {𝕜 : Type u} [NontriviallyNormedField 𝕜] diff --git a/Mathlib/Analysis/Calculus/Deriv/Slope.lean b/Mathlib/Analysis/Calculus/Deriv/Slope.lean index 3b9f51dde30cf..6ffd40c200519 100644 --- a/Mathlib/Analysis/Calculus/Deriv/Slope.lean +++ b/Mathlib/Analysis/Calculus/Deriv/Slope.lean @@ -76,7 +76,7 @@ theorem hasDerivAt_iff_tendsto_slope_zero : HasDerivAt f f' x ↔ Tendsto (fun t ↦ t⁻¹ • (f (x + t) - f x)) (𝓝[≠] 0) (𝓝 f') := by have : 𝓝[≠] x = Filter.map (fun t ↦ x + t) (𝓝[≠] 0) := by simp [nhdsWithin, map_add_left_nhds_zero x, Filter.map_inf, add_right_injective x] - simp [hasDerivAt_iff_tendsto_slope, this, slope, Function.comp] + simp [hasDerivAt_iff_tendsto_slope, this, slope, Function.comp_def] alias ⟨HasDerivAt.tendsto_slope_zero, _⟩ := hasDerivAt_iff_tendsto_slope_zero diff --git a/Mathlib/Analysis/Calculus/Deriv/ZPow.lean b/Mathlib/Analysis/Calculus/Deriv/ZPow.lean index c8b4e4b0dd3f7..73cd119155a71 100644 --- a/Mathlib/Analysis/Calculus/Deriv/ZPow.lean +++ b/Mathlib/Analysis/Calculus/Deriv/ZPow.lean @@ -46,7 +46,7 @@ theorem hasStrictDerivAt_zpow (m : ℤ) (x : 𝕜) (h : x ≠ 0 ∨ 0 ≤ m) : · have hx : x ≠ 0 := h.resolve_right hm.not_le have := (hasStrictDerivAt_inv ?_).scomp _ (this (-m) (neg_pos.2 hm)) <;> [skip; exact zpow_ne_zero _ hx] - simp only [(· ∘ ·), zpow_neg, one_div, inv_inv, smul_eq_mul] at this + simp only [Function.comp_def, zpow_neg, one_div, inv_inv, smul_eq_mul] at this convert this using 1 rw [sq, mul_inv, inv_inv, Int.cast_neg, neg_mul, neg_mul_neg, ← zpow_add₀ hx, mul_assoc, ← zpow_add₀ hx] diff --git a/Mathlib/Analysis/Calculus/FDeriv/Analytic.lean b/Mathlib/Analysis/Calculus/FDeriv/Analytic.lean index 982fb6e51c423..791e3537c7217 100644 --- a/Mathlib/Analysis/Calculus/FDeriv/Analytic.lean +++ b/Mathlib/Analysis/Calculus/FDeriv/Analytic.lean @@ -463,7 +463,7 @@ private theorem factorial_smul' {n : ℕ} : ∀ {F : Type max u v} [NormedAddCom [NormedSpace 𝕜 F] [CompleteSpace F] {p : FormalMultilinearSeries 𝕜 E F} {f : E → F}, HasFPowerSeriesOnBall f p x r → n ! • p n (fun _ ↦ y) = iteratedFDeriv 𝕜 n f x (fun _ ↦ y) := by - induction' n with n ih <;> intro F _ _ _ p f h + induction n with | zero => _ | succ n ih => _ <;> intro F _ _ _ p f h · rw [factorial_zero, one_smul, h.iteratedFDeriv_zero_apply_diag] · rw [factorial_succ, mul_comm, mul_smul, ← derivSeries_apply_diag, ← smul_apply, ih h.fderiv, iteratedFDeriv_succ_apply_right] diff --git a/Mathlib/Analysis/Calculus/FDeriv/Basic.lean b/Mathlib/Analysis/Calculus/FDeriv/Basic.lean index 7da598a12bd5b..f156437148642 100644 --- a/Mathlib/Analysis/Calculus/FDeriv/Basic.lean +++ b/Mathlib/Analysis/Calculus/FDeriv/Basic.lean @@ -306,7 +306,7 @@ theorem hasFDerivAt_iff_tendsto : theorem hasFDerivAt_iff_isLittleO_nhds_zero : HasFDerivAt f f' x ↔ (fun h : E => f (x + h) - f x - f' h) =o[𝓝 0] fun h => h := by rw [HasFDerivAt, hasFDerivAtFilter_iff_isLittleO, ← map_add_left_nhds_zero x, isLittleO_map] - simp [(· ∘ ·)] + simp [Function.comp_def] /-- Converse to the mean value inequality: if `f` is differentiable at `x₀` and `C`-lipschitz on a neighborhood of `x₀` then its derivative at `x₀` has norm bounded by `C`. This version diff --git a/Mathlib/Analysis/Calculus/FDeriv/Bilinear.lean b/Mathlib/Analysis/Calculus/FDeriv/Bilinear.lean index 9505419593904..b5afecc0aa536 100644 --- a/Mathlib/Analysis/Calculus/FDeriv/Bilinear.lean +++ b/Mathlib/Analysis/Calculus/FDeriv/Bilinear.lean @@ -69,7 +69,7 @@ theorem IsBoundedBilinearMap.hasStrictFDerivAt (h : IsBoundedBilinearMap 𝕜 b) refine (isBigO_refl _ _).mul_isLittleO ((isLittleO_one_iff _).2 ?_) -- TODO: `continuity` fails exact (continuous_snd.fst.prod_mk continuous_fst.snd).norm.tendsto' _ _ (by simp) - _ = _ := by simp [(· ∘ ·)] + _ = _ := by simp [Function.comp_def] @[fun_prop] theorem IsBoundedBilinearMap.hasFDerivAt (h : IsBoundedBilinearMap 𝕜 b) (p : E × F) : diff --git a/Mathlib/Analysis/Calculus/FDeriv/Measurable.lean b/Mathlib/Analysis/Calculus/FDeriv/Measurable.lean index d201d59948dd7..5623962121150 100644 --- a/Mathlib/Analysis/Calculus/FDeriv/Measurable.lean +++ b/Mathlib/Analysis/Calculus/FDeriv/Measurable.lean @@ -174,7 +174,7 @@ theorem norm_sub_le_of_mem_A {c : 𝕜} (hc : 1 < ‖c‖) {r ε : ℝ} (hε : 0 {L₁ L₂ : E →L[𝕜] F} (h₁ : x ∈ A f L₁ r ε) (h₂ : x ∈ A f L₂ r ε) : ‖L₁ - L₂‖ ≤ 4 * ‖c‖ * ε := by refine opNorm_le_of_shell (half_pos hr) (by positivity) hc ?_ intro y ley ylt - rw [div_div, div_le_iff' (mul_pos (by norm_num : (0 : ℝ) < 2) (zero_lt_one.trans hc))] at ley + rw [div_div, div_le_iff₀' (mul_pos (by norm_num : (0 : ℝ) < 2) (zero_lt_one.trans hc))] at ley calc ‖(L₁ - L₂) y‖ = ‖f (x + y) - f x - L₂ (x + y - x) - (f (x + y) - f x - L₁ (x + y - x))‖ := by simp diff --git a/Mathlib/Analysis/Calculus/FDeriv/Symmetric.lean b/Mathlib/Analysis/Calculus/FDeriv/Symmetric.lean index b24d6c6e85fe1..1835d8c1d6fa5 100644 --- a/Mathlib/Analysis/Calculus/FDeriv/Symmetric.lean +++ b/Mathlib/Analysis/Calculus/FDeriv/Symmetric.lean @@ -167,7 +167,7 @@ theorem Convex.taylor_approx_two_segment {v w : E} (hv : x + v ∈ interior s) convert I using 1 · congr 1 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] + 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] diff --git a/Mathlib/Analysis/Calculus/InverseFunctionTheorem/ApproximatesLinearOn.lean b/Mathlib/Analysis/Calculus/InverseFunctionTheorem/ApproximatesLinearOn.lean index 454b00502e126..56145cc2bf428 100644 --- a/Mathlib/Analysis/Calculus/InverseFunctionTheorem/ApproximatesLinearOn.lean +++ b/Mathlib/Analysis/Calculus/InverseFunctionTheorem/ApproximatesLinearOn.lean @@ -193,7 +193,7 @@ theorem surjOn_closedBall_of_nonlinearRightInverse have C : ∀ (n : ℕ) (w : E), dist w b ≤ f'symm.nnnorm * (1 - ((c : ℝ) * f'symm.nnnorm) ^ n) / (1 - c * f'symm.nnnorm) * dist (f b) y → w ∈ closedBall b ε := fun n w hw ↦ by apply hw.trans - rw [div_mul_eq_mul_div, div_le_iff]; swap; · linarith + rw [div_mul_eq_mul_div, div_le_iff₀]; swap; · linarith calc (f'symm.nnnorm : ℝ) * (1 - ((c : ℝ) * f'symm.nnnorm) ^ n) * dist (f b) y = f'symm.nnnorm * dist (f b) y * (1 - ((c : ℝ) * f'symm.nnnorm) ^ n) := by diff --git a/Mathlib/Analysis/Calculus/InverseFunctionTheorem/FDeriv.lean b/Mathlib/Analysis/Calculus/InverseFunctionTheorem/FDeriv.lean index 82d6364c31eb6..43a83ae9b58a1 100644 --- a/Mathlib/Analysis/Calculus/InverseFunctionTheorem/FDeriv.lean +++ b/Mathlib/Analysis/Calculus/InverseFunctionTheorem/FDeriv.lean @@ -186,7 +186,7 @@ theorem to_localInverse (hf : HasStrictFDerivAt f (f' : E →L[𝕜] F) a) : and `g (f x) = x` in a neighborhood of `a`, then `g` has derivative `f'.symm` at `f a`. For a version assuming `f (g y) = y` and continuity of `g` at `f a` but not `[CompleteSpace E]` -see `of_local_left_inverse`. -/ +see `of_local_left_inverse`. -/ theorem to_local_left_inverse (hf : HasStrictFDerivAt f (f' : E →L[𝕜] F) a) {g : F → E} (hg : ∀ᶠ x in 𝓝 a, g (f x) = x) : HasStrictFDerivAt g (f'.symm : F →L[𝕜] E) (f a) := hf.to_localInverse.congr_of_eventuallyEq <| (hf.localInverse_unique hg).mono fun _ => Eq.symm diff --git a/Mathlib/Analysis/Calculus/LineDeriv/Basic.lean b/Mathlib/Analysis/Calculus/LineDeriv/Basic.lean index eb08a5c169706..c3b79965c35ff 100644 --- a/Mathlib/Analysis/Calculus/LineDeriv/Basic.lean +++ b/Mathlib/Analysis/Calculus/LineDeriv/Basic.lean @@ -499,7 +499,7 @@ theorem HasLineDerivWithinAt.smul (h : HasLineDerivWithinAt 𝕜 f f' s x v) (c have A : HasDerivAt g c 0 := by simpa using (hasDerivAt_id (0 : 𝕜)).const_smul c have B : HasDerivWithinAt (fun t ↦ f (x + t • v)) f' s' (g 0) := by simpa [g] using h have Z := B.scomp (0 : 𝕜) A.hasDerivWithinAt (mapsTo_preimage g s') - simp only [g, s', Function.comp, smul_eq_mul, mul_comm c, ← smul_smul] at Z + simp only [g, s', Function.comp_def, smul_eq_mul, mul_comm c, ← smul_smul] at Z convert Z ext t simp [← smul_smul] diff --git a/Mathlib/Analysis/Calculus/LineDeriv/IntegrationByParts.lean b/Mathlib/Analysis/Calculus/LineDeriv/IntegrationByParts.lean index e46ccfaeb5601..6d2876fdc8402 100644 --- a/Mathlib/Analysis/Calculus/LineDeriv/IntegrationByParts.lean +++ b/Mathlib/Analysis/Calculus/LineDeriv/IntegrationByParts.lean @@ -134,9 +134,9 @@ theorem integral_bilinear_hasLineDerivAt_right_eq_neg_left_of_integrable simpa [this, hL.integral_map] using H have L_emb : MeasurableEmbedding L := L.toHomeomorph.measurableEmbedding apply integral_bilinear_hasLineDerivAt_right_eq_neg_left_of_integrable_aux2 - · simpa [L_emb.integrable_map_iff, Function.comp] using hf'g - · simpa [L_emb.integrable_map_iff, Function.comp] using hfg' - · simpa [L_emb.integrable_map_iff, Function.comp] using hfg + · simpa [L_emb.integrable_map_iff, Function.comp_def] using hf'g + · simpa [L_emb.integrable_map_iff, Function.comp_def] using hfg' + · simpa [L_emb.integrable_map_iff, Function.comp_def] using hfg · intro x have : f = (f ∘ L.symm) ∘ (L : E →ₗ[ℝ] (E' × ℝ)) := by ext y; simp specialize hf (L.symm x) diff --git a/Mathlib/Analysis/Calculus/LocalExtr/Polynomial.lean b/Mathlib/Analysis/Calculus/LocalExtr/Polynomial.lean index 1aa1c46474630..062cf3b3b7880 100644 --- a/Mathlib/Analysis/Calculus/LocalExtr/Polynomial.lean +++ b/Mathlib/Analysis/Calculus/LocalExtr/Polynomial.lean @@ -3,7 +3,7 @@ Copyright (c) 2021 Benjamin Davidson. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Benjamin Davidson, Yury Kudryashov -/ -import Mathlib.Algebra.Star.Order +import Mathlib.Algebra.Order.Star.Basic import Mathlib.Analysis.Calculus.LocalExtr.Rolle import Mathlib.Analysis.Calculus.Deriv.Polynomial import Mathlib.Topology.Algebra.Polynomial diff --git a/Mathlib/Analysis/Calculus/LocalExtr/Rolle.lean b/Mathlib/Analysis/Calculus/LocalExtr/Rolle.lean index dbaffb564b895..bd4dace2f8094 100644 --- a/Mathlib/Analysis/Calculus/LocalExtr/Rolle.lean +++ b/Mathlib/Analysis/Calculus/LocalExtr/Rolle.lean @@ -58,7 +58,7 @@ theorem exists_deriv_eq_zero (hab : a < b) (hfc : ContinuousOn f (Icc a b)) (hfI /-- **Rolle's Theorem**, a version for a function on an open interval: if `f` has derivative `f'` on `(a, b)` and has the same limit `l` at `𝓝[>] a` and `𝓝[<] b`, then `f' c = 0` -for some `c ∈ (a, b)`. -/ +for some `c ∈ (a, b)`. -/ theorem exists_hasDerivAt_eq_zero' (hab : a < b) (hfa : Tendsto f (𝓝[>] a) (𝓝 l)) (hfb : Tendsto f (𝓝[<] b) (𝓝 l)) (hff' : ∀ x ∈ Ioo a b, HasDerivAt f (f' x) x) : ∃ c ∈ Ioo a b, f' c = 0 := diff --git a/Mathlib/Analysis/Calculus/MeanValue.lean b/Mathlib/Analysis/Calculus/MeanValue.lean index d28d3e874e5b0..707218f441f7c 100644 --- a/Mathlib/Analysis/Calculus/MeanValue.lean +++ b/Mathlib/Analysis/Calculus/MeanValue.lean @@ -917,7 +917,7 @@ theorem Convex.mul_sub_le_image_sub_of_le_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'_ge _ (hxyD' a_mem) - exact (le_div_iff (sub_pos.2 hxy')).1 this + exact (le_div_iff₀ (sub_pos.2 hxy')).1 this /-- Let `f : ℝ → ℝ` be a differentiable function. If `C ≤ f'`, then `f` grows at least as fast as `C * x`, i.e., `C * (y - x) ≤ f y - f x` whenever `x ≤ y`. -/ diff --git a/Mathlib/Analysis/Calculus/ParametricIntervalIntegral.lean b/Mathlib/Analysis/Calculus/ParametricIntervalIntegral.lean index a6d43de3221c4..fa25dfa3f5ee9 100644 --- a/Mathlib/Analysis/Calculus/ParametricIntervalIntegral.lean +++ b/Mathlib/Analysis/Calculus/ParametricIntervalIntegral.lean @@ -10,7 +10,7 @@ import Mathlib.MeasureTheory.Integral.IntervalIntegral # Derivatives of interval integrals depending on parameters In this file we restate theorems about derivatives of integrals depending on parameters for interval -integrals. -/ +integrals. -/ open TopologicalSpace MeasureTheory Filter Metric diff --git a/Mathlib/Analysis/Complex/AbelLimit.lean b/Mathlib/Analysis/Complex/AbelLimit.lean index 0e14c1272df17..d00d00856facc 100644 --- a/Mathlib/Analysis/Complex/AbelLimit.lean +++ b/Mathlib/Analysis/Complex/AbelLimit.lean @@ -268,6 +268,5 @@ theorem tendsto_tsum_powerSeries_nhdsWithin_lt convert h simp_rw [Function.comp_apply, dist_eq_norm] norm_cast - rw [norm_real] end Real diff --git a/Mathlib/Analysis/Complex/AbsMax.lean b/Mathlib/Analysis/Complex/AbsMax.lean index 8c266e5611fc5..0d367d1d608d3 100644 --- a/Mathlib/Analysis/Complex/AbsMax.lean +++ b/Mathlib/Analysis/Complex/AbsMax.lean @@ -128,7 +128,7 @@ theorem norm_max_aux₁ [CompleteSpace F] {f : ℂ → F} {z w : ℂ} exact fun ζ hζ => sub_ne_zero.2 (ne_of_mem_sphere hζ hr.ne') · show ∀ ζ ∈ sphere z r, ‖(ζ - z)⁻¹ • f ζ‖ ≤ ‖f z‖ / r rintro ζ (hζ : abs (ζ - z) = r) - rw [le_div_iff hr, norm_smul, norm_inv, norm_eq_abs, hζ, mul_comm, mul_inv_cancel_left₀ hr.ne'] + rw [le_div_iff₀ hr, norm_smul, norm_inv, norm_eq_abs, hζ, mul_comm, mul_inv_cancel_left₀ hr.ne'] exact hz (hsub hζ) show ‖(w - z)⁻¹ • f w‖ < ‖f z‖ / r rw [norm_smul, norm_inv, norm_eq_abs, ← div_eq_inv_mul] @@ -143,8 +143,8 @@ theorem norm_max_aux₂ {f : ℂ → F} {z w : ℂ} (hd : DiffContOnCl ℂ f (ba set e : F →L[ℂ] F̂ := UniformSpace.Completion.toComplL have he : ∀ x, ‖e x‖ = ‖x‖ := UniformSpace.Completion.norm_coe replace hz : IsMaxOn (norm ∘ e ∘ f) (closedBall z (dist w z)) z := by - simpa only [IsMaxOn, (· ∘ ·), he] using hz - simpa only [he, (· ∘ ·)] + simpa only [IsMaxOn, Function.comp_def, he] using hz + simpa only [he, Function.comp_def] using norm_max_aux₁ (e.differentiable.comp_diffContOnCl hd) hz /-! @@ -172,7 +172,7 @@ Finally, we generalize the theorem from a disk in `ℂ` to a closed ball in any /-- **Maximum modulus principle** on a closed ball: if `f : E → F` is continuous on a closed ball, is complex differentiable on the corresponding open ball, and the norm `‖f w‖` takes its maximum -value on the open ball at its center, then the norm `‖f w‖` is constant on the closed ball. -/ +value on the open ball at its center, then the norm `‖f w‖` is constant on the closed ball. -/ theorem norm_eqOn_closedBall_of_isMaxOn {f : E → F} {z : E} {r : ℝ} (hd : DiffContOnCl ℂ f (ball z r)) (hz : IsMaxOn (norm ∘ f) (ball z r) z) : EqOn (norm ∘ f) (const E ‖f z‖) (closedBall z r) := by @@ -306,7 +306,7 @@ normed complex space to a strictly convex normed complex space has the following - it is complex differentiable on the corresponding open ball; - the norm `‖f w‖` takes its maximum value on the open ball at its center. -Then `f` is a constant on the closed ball. -/ +Then `f` is a constant on the closed ball. -/ theorem eqOn_closedBall_of_isMaxOn_norm {f : E → F} {z : E} {r : ℝ} (hd : DiffContOnCl ℂ f (ball z r)) (hz : IsMaxOn (norm ∘ f) (ball z r) z) : EqOn f (const E (f z)) (closedBall z r) := fun _x hx => diff --git a/Mathlib/Analysis/Complex/Angle.lean b/Mathlib/Analysis/Complex/Angle.lean index 95b1c80bb289e..e7031e3748729 100644 --- a/Mathlib/Analysis/Complex/Angle.lean +++ b/Mathlib/Analysis/Complex/Angle.lean @@ -96,7 +96,7 @@ lemma norm_sub_mem_Icc_angle (hx : ‖x‖ = 1) (hy : ‖y‖ = 1) : calc _ = 2 * (1 - (1 - 2 / π ^ 2 * θ ^ 2)) := by ring _ ≤ 2 * (1 - θ.cos) := by - gcongr; exact Real.cos_quadratic_upper_bound <| abs_le.2 <| Ioc_subset_Icc_self hθ + gcongr; exact Real.cos_le_one_sub_mul_cos_sq <| abs_le.2 <| Ioc_subset_Icc_self hθ _ = _ := by linear_combination -θ.cos_sq_add_sin_sq · rw [Real.sqrt_le_left (by positivity), ← _root_.abs_pow, abs_sq] calc @@ -116,6 +116,6 @@ lemma mul_angle_le_norm_sub (hx : ‖x‖ = 1) (hy : ‖y‖ = 1) : 2 / π * ang /-- Arc-length is always less than a multiple of chord-length. -/ lemma angle_le_mul_norm_sub (hx : ‖x‖ = 1) (hy : ‖y‖ = 1) : angle x y ≤ π / 2 * ‖x - y‖ := by - rw [← div_le_iff' <| by positivity, div_eq_inv_mul, inv_div]; exact mul_angle_le_norm_sub hx hy + rw [← div_le_iff₀' <| by positivity, div_eq_inv_mul, inv_div]; exact mul_angle_le_norm_sub hx hy end Complex diff --git a/Mathlib/Analysis/Complex/Basic.lean b/Mathlib/Analysis/Complex/Basic.lean index 5cce5c3e7eeb1..492769068a2f2 100644 --- a/Mathlib/Analysis/Complex/Basic.lean +++ b/Mathlib/Analysis/Complex/Basic.lean @@ -92,6 +92,8 @@ instance (priority := 900) _root_.NormedAlgebra.complexToReal {A : Type*} [Semin [NormedAlgebra ℂ A] : NormedAlgebra ℝ A := NormedAlgebra.restrictScalars ℝ ℂ A +@[simp] lemma nnnorm_I : ‖I‖₊ = 1 := by simp [nnnorm] + theorem dist_eq (z w : ℂ) : dist z w = abs (z - w) := rfl @@ -138,23 +140,38 @@ theorem nndist_self_conj (z : ℂ) : nndist z (conj z) = 2 * Real.nnabs z.im := theorem comap_abs_nhds_zero : comap abs (𝓝 0) = 𝓝 0 := comap_norm_nhds_zero -theorem norm_real (r : ℝ) : ‖(r : ℂ)‖ = ‖r‖ := - abs_ofReal _ +@[simp 1100, norm_cast] lemma norm_real (r : ℝ) : ‖(r : ℂ)‖ = ‖r‖ := abs_ofReal _ +@[simp, norm_cast] lemma nnnorm_real (r : ℝ) : ‖(r : ℂ)‖₊ = ‖r‖₊ := by ext; exact norm_real _ -@[simp 1100] -theorem norm_rat (r : ℚ) : ‖(r : ℂ)‖ = |(r : ℝ)| := by - rw [← ofReal_ratCast] - exact norm_real _ +@[simp 1100, norm_cast] lemma norm_natCast (n : ℕ) : ‖(n : ℂ)‖ = n := abs_natCast _ +@[simp 1100, norm_cast] lemma norm_intCast (n : ℤ) : ‖(n : ℂ)‖ = |(n : ℝ)| := abs_intCast n +@[simp 1100, norm_cast] lemma norm_ratCast (q : ℚ) : ‖(q : ℂ)‖ = |(q : ℝ)| := norm_real _ -@[simp 1100] -theorem norm_nat (n : ℕ) : ‖(n : ℂ)‖ = n := - abs_natCast _ +@[simp 1100, norm_cast] lemma nnnorm_natCast (n : ℕ) : ‖(n : ℂ)‖₊ = n := Subtype.ext <| by simp +@[simp 1100, norm_cast] lemma nnnorm_intCast (n : ℤ) : ‖(n : ℂ)‖₊ = ‖n‖₊ := by + ext; exact norm_intCast n +@[simp 1100, norm_cast] lemma nnnorm_ratCast (q : ℚ) : ‖(q : ℂ)‖₊ = ‖(q : ℝ)‖₊ := nnnorm_real q -@[simp 1100] -lemma norm_int {n : ℤ} : ‖(n : ℂ)‖ = |(n : ℝ)| := abs_intCast n +@[simp 1100] lemma norm_ofNat (n : ℕ) [n.AtLeastTwo] : + ‖(no_index (OfNat.ofNat n) : ℂ)‖ = OfNat.ofNat n := norm_natCast n + +@[simp 1100] lemma nnnorm_ofNat (n : ℕ) [n.AtLeastTwo] : + ‖(no_index (OfNat.ofNat n) : ℂ)‖₊ = OfNat.ofNat n := nnnorm_natCast n + +@[deprecated (since := "2024-08-25")] alias norm_nat := norm_natCast +@[deprecated (since := "2024-08-25")] alias norm_int := norm_intCast +@[deprecated (since := "2024-08-25")] alias norm_rat := norm_ratCast +@[deprecated (since := "2024-08-25")] alias nnnorm_nat := nnnorm_natCast +@[deprecated (since := "2024-08-25")] alias nnnorm_int := nnnorm_intCast + +@[simp 1100, norm_cast] +lemma norm_nnratCast (q : ℚ≥0) : ‖(q : ℂ)‖ = q := abs_of_nonneg q.cast_nonneg + +@[simp 1100, norm_cast] +lemma nnnorm_nnratCast (q : ℚ≥0) : ‖(q : ℂ)‖₊ = q := by simp [nnnorm, -norm_eq_abs] theorem norm_int_of_nonneg {n : ℤ} (hn : 0 ≤ n) : ‖(n : ℂ)‖ = n := by - rw [norm_int, ← Int.cast_abs, _root_.abs_of_nonneg hn] + rw [norm_intCast, ← Int.cast_abs, _root_.abs_of_nonneg hn] lemma normSq_eq_norm_sq (z : ℂ) : normSq z = ‖z‖ ^ 2 := by rw [normSq_eq_abs, norm_eq_abs] @@ -167,17 +184,6 @@ theorem continuous_abs : Continuous abs := theorem continuous_normSq : Continuous normSq := by simpa [← normSq_eq_abs] using continuous_abs.pow 2 -@[simp, norm_cast] -theorem nnnorm_real (r : ℝ) : ‖(r : ℂ)‖₊ = ‖r‖₊ := - Subtype.ext <| norm_real r - -@[simp, norm_cast] -theorem nnnorm_nat (n : ℕ) : ‖(n : ℂ)‖₊ = n := - Subtype.ext <| by simp - -@[simp, norm_cast] -theorem nnnorm_int (n : ℤ) : ‖(n : ℂ)‖₊ = ‖n‖₊ := - Subtype.ext norm_int theorem nnnorm_eq_one_of_pow_eq_one {ζ : ℂ} {n : ℕ} (h : ζ ^ n = 1) (hn : n ≠ 0) : ‖ζ‖₊ = 1 := (pow_left_inj zero_le' zero_le' hn).1 <| by rw [← nnnorm_pow, h, nnnorm_one, one_pow] diff --git a/Mathlib/Analysis/Complex/CauchyIntegral.lean b/Mathlib/Analysis/Complex/CauchyIntegral.lean index 23f031e5b652c..adda35554977c 100644 --- a/Mathlib/Analysis/Complex/CauchyIntegral.lean +++ b/Mathlib/Analysis/Complex/CauchyIntegral.lean @@ -466,7 +466,7 @@ theorem two_pi_I_inv_smul_circleIntegral_sub_inv_smul_of_differentiable_on_off_c rcases mem_nhds_iff_exists_Ioo_subset.1 (this <| inter_mem ht <| isOpen_ball.mem_nhds hw) with ⟨l, u, hlu₀, hlu_sub⟩ obtain ⟨x, hx⟩ : (Ioo l u \ g ⁻¹' s).Nonempty := by - refine nonempty_diff.2 fun hsub => ?_ + refine diff_nonempty.2 fun hsub => ?_ have : (Ioo l u).Countable := (hs.preimage ((add_right_injective w).comp ofReal_injective)).mono hsub rw [← Cardinal.le_aleph0_iff_set_countable, Cardinal.mk_Ioo_real (hlu₀.1.trans hlu₀.2)] at this diff --git a/Mathlib/Analysis/Complex/Circle.lean b/Mathlib/Analysis/Complex/Circle.lean index aab56f8eec106..bda86fd651ad1 100644 --- a/Mathlib/Analysis/Complex/Circle.lean +++ b/Mathlib/Analysis/Complex/Circle.lean @@ -34,7 +34,7 @@ is the kernel of the homomorphism `Complex.normSq` from `ℂ` to `ℝ`. noncomputable section -open Complex Metric +open Complex Function Metric open ComplexConjugate @@ -60,16 +60,26 @@ def Circle : Type := Submonoid.unitSphere ℂ deriving TopologicalSpace namespace Circle +variable {x y : Circle} instance instCoeOut : CoeOut Circle ℂ := subtypeCoe instance instCommGroup : CommGroup Circle := Metric.sphere.commGroup instance instMetricSpace : MetricSpace Circle := Subtype.metricSpace +@[ext] lemma ext : (x : ℂ) = y → x = y := Subtype.ext + +lemma coe_injective : Injective ((↑) : Circle → ℂ) := fun _ _ ↦ ext + +-- Not simp because `SetLike.coe_eq_coe` already proves it +lemma coe_inj : (x : ℂ) = y ↔ x = y := coe_injective.eq_iff + @[simp] lemma abs_coe (z : Circle) : abs z = 1 := mem_sphere_zero_iff_norm.1 z.2 @[simp] lemma normSq_coe (z : Circle) : normSq z = 1 := by simp [normSq_eq_abs] @[simp] lemma coe_ne_zero (z : Circle) : (z : ℂ) ≠ 0 := ne_zero_of_mem_unit_sphere z @[simp, norm_cast] lemma coe_one : ↑(1 : Circle) = (1 : ℂ) := rfl +-- Not simp because `OneMemClass.coe_eq_one` already proves it +@[norm_cast] lemma coe_eq_one : (x : ℂ) = 1 ↔ x = 1 := by rw [← coe_inj, coe_one] @[simp, norm_cast] lemma coe_mul (z w : Circle) : ↑(z * w) = (z : ℂ) * w := rfl @[simp, norm_cast] lemma coe_inv (z : Circle) : ↑z⁻¹ = (z : ℂ)⁻¹ := rfl lemma coe_inv_eq_conj (z : Circle) : ↑z⁻¹ = conj (z : ℂ) := by @@ -117,17 +127,17 @@ def exp : C(ℝ, Circle) where continuous_toFun := Continuous.subtype_mk (by fun_prop) (by simp [Submonoid.unitSphere, exp_mul_I, abs_cos_add_sin_mul_I]) -@[simp] -theorem exp_apply (t : ℝ) : ↑(exp t) = Complex.exp (t * Complex.I) := rfl +@[simp, norm_cast] +theorem coe_exp (t : ℝ) : exp t = Complex.exp (t * Complex.I) := rfl @[simp] theorem exp_zero : exp 0 = 1 := - Subtype.ext <| by rw [exp_apply, ofReal_zero, zero_mul, Complex.exp_zero, coe_one] + Subtype.ext <| by rw [coe_exp, ofReal_zero, zero_mul, Complex.exp_zero, coe_one] @[simp] theorem exp_add (x y : ℝ) : exp (x + y) = exp x * exp y := Subtype.ext <| by - simp only [exp_apply, Submonoid.coe_mul, ofReal_add, add_mul, Complex.exp_add, coe_mul] + simp only [coe_exp, Submonoid.coe_mul, ofReal_add, add_mul, Complex.exp_add, coe_mul] /-- The map `fun t => exp (t * I)` from `ℝ` to the unit circle in `ℂ`, considered as a homomorphism of groups. -/ @@ -170,7 +180,7 @@ protected lemma norm_smul {E : Type*} [SeminormedAddCommGroup E] [NormedSpace rw [Submonoid.smul_def, norm_smul, norm_eq_of_mem_sphere, one_mul] @[deprecated (since := "2024-07-24")] noncomputable alias _root_.expMapCircle := exp -@[deprecated (since := "2024-07-24")] noncomputable alias _root_.expMapCircle_apply := exp_apply +@[deprecated (since := "2024-07-24")] noncomputable alias _root_.expMapCircle_apply := coe_exp @[deprecated (since := "2024-07-24")] noncomputable alias _root_.expMapCircle_zero := exp_zero @[deprecated (since := "2024-07-24")] noncomputable alias _root_.expMapCircle_sub := exp_sub @[deprecated (since := "2024-07-24")] noncomputable alias _root_.norm_circle_smul := diff --git a/Mathlib/Analysis/Complex/IsIntegral.lean b/Mathlib/Analysis/Complex/IsIntegral.lean new file mode 100644 index 0000000000000..939434a7a666d --- /dev/null +++ b/Mathlib/Analysis/Complex/IsIntegral.lean @@ -0,0 +1,27 @@ +/- +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.Analysis.Complex.Basic +import Mathlib.RingTheory.IntegralClosure.IsIntegral.Basic + +/-! +# Integral elements of ℂ + +This file proves that `Complex.I` is integral over ℤ and ℚ. +-/ + +open Polynomial + +namespace Complex + +theorem isIntegral_int_I : IsIntegral ℤ I := by + refine ⟨X ^ 2 + C 1, monic_X_pow_add_C _ two_ne_zero, ?_⟩ + rw [eval₂_add, eval₂_X_pow, eval₂_C, I_sq, eq_intCast, Int.cast_one, neg_add_cancel] + +theorem isIntegral_rat_I : IsIntegral ℚ I := + isIntegral_int_I.tower_top + +end Complex diff --git a/Mathlib/Analysis/Complex/PhragmenLindelof.lean b/Mathlib/Analysis/Complex/PhragmenLindelof.lean index c08ca1fd6b87e..e172dd9cfe031 100644 --- a/Mathlib/Analysis/Complex/PhragmenLindelof.lean +++ b/Mathlib/Analysis/Complex/PhragmenLindelof.lean @@ -282,8 +282,8 @@ theorem vertical_strip (hfd : DiffContOnCl ℂ f (re ⁻¹' Ioo a b)) have : Tendsto (· * -I) (comap (|re ·|) atTop ⊓ 𝓟 (im ⁻¹' Ioo a b)) (comap (|im ·|) atTop ⊓ 𝓟 (re ⁻¹' Ioo a b)) := by refine (tendsto_comap_iff.2 ?_).inf H.tendsto - simpa [(· ∘ ·)] using tendsto_comap - simpa [(· ∘ ·)] using hO.comp_tendsto this + simpa [Function.comp_def] using tendsto_comap + simpa [Function.comp_def] using hO.comp_tendsto this all_goals simpa /-- **Phragmen-Lindelöf principle** in a strip `U = {z : ℂ | a < re z < b}`. @@ -453,7 +453,7 @@ theorem quadrant_II (hd : DiffContOnCl ℂ f (Iio 0 ×ℂ Ioi 0)) rcases hB with ⟨c, hc, B, hO⟩ refine quadrant_I (hd.comp (differentiable_id.mul_const _).diffContOnCl H) ⟨c, hc, B, ?_⟩ him (fun x hx => ?_) hz_im hz_re - · simpa only [(· ∘ ·), map_mul, abs_I, mul_one] + · simpa only [Function.comp_def, map_mul, abs_I, mul_one] using hO.comp_tendsto ((tendsto_mul_right_cobounded I_ne_zero).inf H.tendsto) · rw [comp_apply, mul_assoc, I_mul_I, mul_neg_one, ← ofReal_neg] exact hre _ (neg_nonpos.2 hx) @@ -518,7 +518,7 @@ theorem quadrant_III (hd : DiffContOnCl ℂ f (Iio 0 ×ℂ Iio 0)) hz_re hz_im · rcases hB with ⟨c, hc, B, hO⟩ refine ⟨c, hc, B, ?_⟩ - simpa only [(· ∘ ·), Complex.abs.map_neg] + simpa only [Function.comp_def, Complex.abs.map_neg] using hO.comp_tendsto (tendsto_neg_cobounded.inf H.tendsto) · rw [comp_apply, ← ofReal_neg] exact hre (-x) (neg_nonpos.2 hx) @@ -582,7 +582,7 @@ theorem quadrant_IV (hd : DiffContOnCl ℂ f (Ioi 0 ×ℂ Iio 0)) (hd.comp differentiable_neg.diffContOnCl H) ?_ (fun x hx => ?_) (fun x hx => ?_) hz_re hz_im · rcases hB with ⟨c, hc, B, hO⟩ refine ⟨c, hc, B, ?_⟩ - simpa only [(· ∘ ·), Complex.abs.map_neg] + simpa only [Function.comp_def, Complex.abs.map_neg] using hO.comp_tendsto (tendsto_neg_cobounded.inf H.tendsto) · rw [comp_apply, ← ofReal_neg] exact hre (-x) (neg_nonneg.2 hx) diff --git a/Mathlib/Analysis/Complex/Polynomial/Basic.lean b/Mathlib/Analysis/Complex/Polynomial/Basic.lean index 145fa099c8971..82e38a8adc578 100644 --- a/Mathlib/Analysis/Complex/Polynomial/Basic.lean +++ b/Mathlib/Analysis/Complex/Polynomial/Basic.lean @@ -128,7 +128,7 @@ theorem galActionHom_bijective_of_prime_degree {p : ℚ[X]} (p_irr : Irreducible let conj' := restrict p ℂ (Complex.conjAe.restrictScalars ℚ) refine ⟨galActionHom_injective p ℂ, fun x => - (congr_arg (Membership.mem x) (show (galActionHom p ℂ).range = ⊤ from ?_)).mpr + (congr_arg (x ∈ ·) (show (galActionHom p ℂ).range = ⊤ from ?_)).mpr (Subgroup.mem_top x)⟩ apply Equiv.Perm.subgroup_eq_top_of_swap_mem · rwa [h1] diff --git a/Mathlib/Analysis/Complex/Schwarz.lean b/Mathlib/Analysis/Complex/Schwarz.lean index cf851529fbf6f..4c91fb9c0f890 100644 --- a/Mathlib/Analysis/Complex/Schwarz.lean +++ b/Mathlib/Analysis/Complex/Schwarz.lean @@ -149,7 +149,7 @@ theorem dist_le_div_mul_dist_of_mapsTo_ball (hd : DifferentiableOn ℂ f (ball c rcases eq_or_ne z c with (rfl | hne) · simp only [dist_self, mul_zero, le_rfl] simpa only [dslope_of_ne _ hne, slope_def_module, norm_smul, norm_inv, ← div_eq_inv_mul, ← - dist_eq_norm, div_le_iff (dist_pos.2 hne)] using norm_dslope_le_div_of_mapsTo_ball hd h_maps hz + dist_eq_norm, div_le_iff₀ (dist_pos.2 hne)] using norm_dslope_le_div_of_mapsTo_ball hd h_maps hz end Space diff --git a/Mathlib/Analysis/Complex/TaylorSeries.lean b/Mathlib/Analysis/Complex/TaylorSeries.lean index 90a8b74ad8c80..dbd3037467b3a 100644 --- a/Mathlib/Analysis/Complex/TaylorSeries.lean +++ b/Mathlib/Analysis/Complex/TaylorSeries.lean @@ -11,7 +11,7 @@ import Mathlib.Analysis.Complex.CauchyIntegral We show that the Taylor series around some point `c : ℂ` of a function `f` that is complex differentiable on the open ball of radius `r` around `c` converges to `f` on that open ball; see `Complex.hasSum_taylorSeries_on_ball` and `Complex.taylorSeries_eq_on_ball` for versions -(in terms of `HasSum` and `tsum`, repsectively) for functions to a complete normed +(in terms of `HasSum` and `tsum`, respectively) for functions to a complete normed space over `ℂ`, and `Complex.taylorSeries_eq_on_ball'` for a variant when `f : ℂ → ℂ`. There are corresponding statements for `EMEtric.ball`s; see @@ -24,16 +24,24 @@ see `Complex.hasSum_taylorSeries_of_entire`, `Complex.taylorSeries_eq_of_entire` `Complex.taylorSeries_eq_of_entire'`. -/ +#adaptation_note +/-- +Due to https://github.com/leanprover/lean4/issues/5126, we've had to change all +the `⦃⦄` stricit implicit variable statements in this file to normal `{}` implicit variables. + +Once this issue is fixed, we should change them back. For now it doesn't break anything downstream. +-/ + namespace Complex open Nat -variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] [CompleteSpace E] ⦃f : ℂ → E⦄ +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] [CompleteSpace E] {f : ℂ → E} section ball -variable ⦃c : ℂ⦄ ⦃r : ℝ⦄ (hf : DifferentiableOn ℂ f (Metric.ball c r)) -variable ⦃z : ℂ⦄ (hz : z ∈ Metric.ball c r) +variable {c : ℂ} {r : ℝ} (hf : DifferentiableOn ℂ f (Metric.ball c r)) +variable {z : ℂ} (hz : z ∈ Metric.ball c r) include hf hz in /-- A function that is complex differentiable on the open ball of radius `r` around `c` @@ -74,8 +82,8 @@ end ball section emetric -variable ⦃c : ℂ⦄ ⦃r : ENNReal⦄ (hf : DifferentiableOn ℂ f (EMetric.ball c r)) -variable ⦃z : ℂ⦄ (hz : z ∈ EMetric.ball c r) +variable {c : ℂ} {r : ENNReal} (hf : DifferentiableOn ℂ f (EMetric.ball c r)) +variable {z : ℂ} (hz : z ∈ EMetric.ball c r) include hf hz in /-- A function that is complex differentiable on the open ball of radius `r ≤ ∞` around `c` @@ -108,7 +116,7 @@ end emetric section entire -variable ⦃f : ℂ → E⦄ (hf : Differentiable ℂ f) (c z : ℂ) +variable {f : ℂ → E} (hf : Differentiable ℂ f) (c z : ℂ) include hf in /-- A function that is complex differentiable on the complex plane is given by evaluating diff --git a/Mathlib/Analysis/Complex/UpperHalfPlane/Metric.lean b/Mathlib/Analysis/Complex/UpperHalfPlane/Metric.lean index 1ec268788ba90..dec00ac0e5457 100644 --- a/Mathlib/Analysis/Complex/UpperHalfPlane/Metric.lean +++ b/Mathlib/Analysis/Complex/UpperHalfPlane/Metric.lean @@ -93,7 +93,7 @@ theorem dist_eq_iff_eq_sq_sinh (hr : 0 ≤ r) : all_goals positivity protected theorem dist_triangle (a b c : ℍ) : dist a c ≤ dist a b + dist b c := by - rw [dist_le_iff_le_sinh, sinh_half_dist_add_dist, div_mul_eq_div_div _ _ (dist _ _), le_div_iff, + rw [dist_le_iff_le_sinh, sinh_half_dist_add_dist, div_mul_eq_div_div _ _ (dist _ _), le_div_iff₀, div_mul_eq_mul_div] · gcongr exact EuclideanGeometry.mul_dist_le_mul_dist_add_mul_dist (a : ℂ) b c (conj (b : ℂ)) @@ -218,11 +218,11 @@ theorem dist_log_im_le (z w : ℍ) : dist (log z.im) (log w.im) ≤ dist z w := simpa [sqrt_sq_eq_abs] using Complex.abs_im_le_abs (z - w) theorem im_le_im_mul_exp_dist (z w : ℍ) : z.im ≤ w.im * Real.exp (dist z w) := by - rw [← div_le_iff' w.im_pos, ← exp_log z.im_pos, ← exp_log w.im_pos, ← Real.exp_sub, exp_le_exp] + rw [← div_le_iff₀' w.im_pos, ← exp_log z.im_pos, ← exp_log w.im_pos, ← Real.exp_sub, exp_le_exp] exact (le_abs_self _).trans (dist_log_im_le z w) theorem im_div_exp_dist_le (z w : ℍ) : z.im / Real.exp (dist z w) ≤ w.im := - (div_le_iff (exp_pos _)).2 (im_le_im_mul_exp_dist z w) + (div_le_iff₀ (exp_pos _)).2 (im_le_im_mul_exp_dist z w) /-- An upper estimate on the complex distance between two points in terms of the hyperbolic distance and the imaginary part of one of the points. -/ diff --git a/Mathlib/Analysis/Complex/UpperHalfPlane/Topology.lean b/Mathlib/Analysis/Complex/UpperHalfPlane/Topology.lean index 794141a06f371..3c32e2e099f23 100644 --- a/Mathlib/Analysis/Complex/UpperHalfPlane/Topology.lean +++ b/Mathlib/Analysis/Complex/UpperHalfPlane/Topology.lean @@ -127,8 +127,32 @@ scoped notation "↑ₕ" f => f ∘ ofComplex lemma ofComplex_apply (z : ℍ) : ofComplex (z : ℂ) = z := OpenEmbedding.toPartialHomeomorph_left_inv .. -lemma comp_ofComplex (f : ℍ → ℂ) (z : ℍ) : (↑ₕ f) z = f z := by - rw [Function.comp_apply, ofComplex_apply] +lemma ofComplex_apply_eq_ite (w : ℂ) : + ofComplex w = if hw : 0 < w.im then ⟨w, hw⟩ else Classical.choice inferInstance := by + split_ifs with hw + · exact ofComplex_apply ⟨w, hw⟩ + · change (Function.invFunOn UpperHalfPlane.coe Set.univ w) = _ + simp only [invFunOn, dite_eq_right_iff, mem_univ, true_and] + rintro ⟨a, rfl⟩ + exact (a.prop.not_le (by simpa using hw)).elim + +lemma ofComplex_apply_of_im_nonpos {w : ℂ} (hw : w.im ≤ 0) : + ofComplex w = Classical.choice inferInstance := by + simp [ofComplex_apply_eq_ite w, hw] + +lemma ofComplex_apply_eq_of_im_nonpos {w w' : ℂ} (hw : w.im ≤ 0) (hw' : w'.im ≤ 0) : + ofComplex w = ofComplex w' := by + simp [ofComplex_apply_of_im_nonpos, hw, hw'] + +lemma comp_ofComplex (f : ℍ → ℂ) (z : ℍ) : (↑ₕ f) z = f z := + congrArg _ <| ofComplex_apply z + +lemma comp_ofComplex_of_im_pos (f : ℍ → ℂ) (z : ℂ) (hz : 0 < z.im) : (↑ₕ f) z = f ⟨z, hz⟩ := + congrArg _ <| ofComplex_apply ⟨z, hz⟩ + +lemma comp_ofComplex_of_im_le_zero (f : ℍ → ℂ) (z z' : ℂ) (hz : z.im ≤ 0) (hz' : z'.im ≤ 0) : + (↑ₕ f) z = (↑ₕ f) z' := by + simp [ofComplex_apply_of_im_nonpos, hz, hz'] end UpperHalfPlane diff --git a/Mathlib/Analysis/ConstantSpeed.lean b/Mathlib/Analysis/ConstantSpeed.lean index 48b06bbe4565c..268a8fb396472 100644 --- a/Mathlib/Analysis/ConstantSpeed.lean +++ b/Mathlib/Analysis/ConstantSpeed.lean @@ -232,9 +232,7 @@ theorem edist_naturalParameterization_eq_zero {f : α → E} {s : Set α} edist (naturalParameterization f s a (variationOnFromTo f s a b)) (f b) = 0 := by dsimp only [naturalParameterization] haveI : Nonempty α := ⟨a⟩ - obtain ⟨cs, hc⟩ := - @Function.invFunOn_pos _ _ _ s (variationOnFromTo f s a) (variationOnFromTo f s a b) - ⟨b, bs, rfl⟩ + obtain ⟨cs, hc⟩ := Function.invFunOn_pos (b := variationOnFromTo f s a b) ⟨b, bs, rfl⟩ rw [variationOnFromTo.eq_left_iff hf as cs bs] at hc apply variationOnFromTo.edist_zero_of_eq_zero hf cs bs hc diff --git a/Mathlib/Analysis/Convex/Basic.lean b/Mathlib/Analysis/Convex/Basic.lean index 24f8e44ef54c4..f07e88d57f245 100644 --- a/Mathlib/Analysis/Convex/Basic.lean +++ b/Mathlib/Analysis/Convex/Basic.lean @@ -5,6 +5,7 @@ Authors: Alexander Bentkamp, Yury Kudryashov, Yaël Dillies -/ import Mathlib.Algebra.Order.BigOperators.Ring.Finset import Mathlib.Algebra.Order.Module.OrderedSMul +import Mathlib.Algebra.Order.Module.Synonym import Mathlib.Analysis.Convex.Star import Mathlib.LinearAlgebra.AffineSpace.AffineSubspace diff --git a/Mathlib/Analysis/Convex/Body.lean b/Mathlib/Analysis/Convex/Body.lean index 334349d6395d4..ab8c493ff10c3 100644 --- a/Mathlib/Analysis/Convex/Body.lean +++ b/Mathlib/Analysis/Convex/Body.lean @@ -153,14 +153,14 @@ instance : Module ℝ≥0 (ConvexBody V) where theorem smul_le_of_le (K : ConvexBody V) (h_zero : 0 ∈ K) {a b : ℝ≥0} (h : a ≤ b) : a • K ≤ b • K := by rw [← SetLike.coe_subset_coe, coe_smul', coe_smul'] - by_cases ha : a = 0 - · rw [ha, Set.zero_smul_set K.nonempty, Set.zero_subset] + obtain rfl | ha := eq_zero_or_pos a + · rw [Set.zero_smul_set K.nonempty, Set.zero_subset] exact Set.mem_smul_set.mpr ⟨0, h_zero, smul_zero _⟩ · intro x hx obtain ⟨y, hy, rfl⟩ := Set.mem_smul_set.mp hx - rw [← Set.mem_inv_smul_set_iff₀ ha, smul_smul] - exact Convex.mem_smul_of_zero_mem K.convex h_zero hy - (by rwa [← NNReal.mul_le_iff_le_inv ha, mul_one] : 1 ≤ a⁻¹ * b) + rw [← Set.mem_inv_smul_set_iff₀ ha.ne', smul_smul] + refine Convex.mem_smul_of_zero_mem K.convex h_zero hy (?_ : 1 ≤ a⁻¹ * b) + rwa [le_inv_mul_iff₀ ha, mul_one] end TVS diff --git a/Mathlib/Analysis/Convex/Caratheodory.lean b/Mathlib/Analysis/Convex/Caratheodory.lean index 350831d128c98..75f0b5f68dfeb 100644 --- a/Mathlib/Analysis/Convex/Caratheodory.lean +++ b/Mathlib/Analysis/Convex/Caratheodory.lean @@ -79,7 +79,7 @@ theorem mem_convexHull_erase [DecidableEq E] {t : Finset E} (h : ¬AffineIndepen · have hge : 0 < g e := by rw [mem_filter] at hes exact hes.2 - rw [← le_div_iff hge] + rw [← le_div_iff₀ hge] exact w _ hes · calc _ ≤ 0 := by @@ -95,14 +95,16 @@ theorem mem_convexHull_erase [DecidableEq E] {t : Finset E} (h : ¬AffineIndepen simp only [sub_smul, mul_smul, sum_sub_distrib, ← smul_sum, gcombo, smul_zero, sub_zero, centerMass, fsum, inv_one, one_smul, id] -variable {s : Set E} {x : E} (hx : x ∈ convexHull 𝕜 s) +variable {s : Set E} {x : E} /-- Given a point `x` in the convex hull of a set `s`, this is a finite subset of `s` of minimum cardinality, whose convex hull contains `x`. -/ -noncomputable def minCardFinsetOfMemConvexHull : Finset E := +noncomputable def minCardFinsetOfMemConvexHull (hx : x ∈ convexHull 𝕜 s) : Finset E := Function.argminOn Finset.card Nat.lt_wfRel.2 { t | ↑t ⊆ s ∧ x ∈ convexHull 𝕜 (t : Set E) } <| by simpa only [convexHull_eq_union_convexHull_finite_subsets s, exists_prop, mem_iUnion] using hx +variable (hx : x ∈ convexHull 𝕜 s) + theorem minCardFinsetOfMemConvexHull_subseteq : ↑(minCardFinsetOfMemConvexHull hx) ⊆ s := (Function.argminOn_mem _ _ { t : Finset E | ↑t ⊆ s ∧ x ∈ convexHull 𝕜 (t : Set E) } _).1 diff --git a/Mathlib/Analysis/Convex/Combination.lean b/Mathlib/Analysis/Convex/Combination.lean index 20fcc69a29fb2..b851e544f9998 100644 --- a/Mathlib/Analysis/Convex/Combination.lean +++ b/Mathlib/Analysis/Convex/Combination.lean @@ -481,7 +481,7 @@ theorem Set.Finite.convexHull_eq_image {s : Set E} (hs : s.Finite) : convexHull letI := hs.fintype rw [← convexHull_basis_eq_stdSimplex, LinearMap.image_convexHull, ← Set.range_comp] apply congr_arg - simp_rw [Function.comp] + simp_rw [Function.comp_def] convert Subtype.range_coe.symm simp [LinearMap.sum_apply, ite_smul, Finset.filter_eq, Finset.mem_univ] diff --git a/Mathlib/Analysis/Convex/Cone/InnerDual.lean b/Mathlib/Analysis/Convex/Cone/InnerDual.lean index 555882971d866..63d49213b6aba 100644 --- a/Mathlib/Analysis/Convex/Cone/InnerDual.lean +++ b/Mathlib/Analysis/Convex/Cone/InnerDual.lean @@ -181,7 +181,7 @@ theorem ConvexCone.hyperplane_separation_of_nonempty_of_isClosed_of_nmem (K : Co _ = ⟪b - z, b - z + z⟫_ℝ := (inner_add_right _ _ _).symm _ = ⟪b - z, b⟫_ℝ := by rw [sub_add_cancel] -/-- The inner dual of inner dual of a non-empty, closed convex cone is itself. -/ +/-- The inner dual of inner dual of a non-empty, closed convex cone is itself. -/ theorem ConvexCone.innerDualCone_of_innerDualCone_eq_self (K : ConvexCone ℝ H) (ne : (K : Set H).Nonempty) (hc : IsClosed (K : Set H)) : ((K : Set H).innerDualCone : Set H).innerDualCone = K := by diff --git a/Mathlib/Analysis/Convex/Gauge.lean b/Mathlib/Analysis/Convex/Gauge.lean index 84b136c6fc755..b73b52f91006a 100644 --- a/Mathlib/Analysis/Convex/Gauge.lean +++ b/Mathlib/Analysis/Convex/Gauge.lean @@ -67,7 +67,7 @@ private theorem gauge_set_bddBelow : BddBelow { r : ℝ | 0 < r ∧ x ∈ r • ⟨0, fun _ hr => hr.1.le⟩ /-- If the given subset is `Absorbent` then the set we take an infimum over in `gauge` is nonempty, -which is useful for proving many properties about the gauge. -/ +which is useful for proving many properties about the gauge. -/ theorem Absorbent.gauge_set_nonempty (absorbs : Absorbent ℝ s) : { r : ℝ | 0 < r ∧ x ∈ r • s }.Nonempty := let ⟨r, hr₁, hr₂⟩ := (absorbs x).exists_pos @@ -359,12 +359,12 @@ theorem gauge_lt_one_eq_self_of_isOpen (hs₁ : Convex ℝ s) (hs₀ : (0 : E) convert interior_subset_gauge_lt_one s exact hs₂.interior_eq.symm --- Porting note: droped unneeded assumptions +-- Porting note: dropped unneeded assumptions theorem gauge_lt_one_of_mem_of_isOpen (hs₂ : IsOpen s) {x : E} (hx : x ∈ s) : gauge s x < 1 := interior_subset_gauge_lt_one s <| by rwa [hs₂.interior_eq] --- Porting note: droped unneeded assumptions +-- Porting note: dropped unneeded assumptions theorem gauge_lt_of_mem_smul (x : E) (ε : ℝ) (hε : 0 < ε) (hs₂ : IsOpen s) (hx : x ∈ ε • s) : gauge s x < ε := by have : ε⁻¹ • x ∈ s := by rwa [← mem_smul_set_iff_inv_smul_mem₀ hε.ne'] @@ -538,10 +538,6 @@ theorem gauge_ball (hr : 0 ≤ r) (x : E) : gauge (ball (0 : E) r) x = ‖x‖ / simp_rw [mem_ball_zero_iff, norm_neg] exact fun _ => id -@[deprecated gauge_ball (since := "2023-07-24")] -theorem gauge_ball' (hr : 0 < r) (x : E) : gauge (ball (0 : E) r) x = ‖x‖ / r := - gauge_ball hr.le x - @[simp] theorem gauge_closure_zero : gauge (closure (0 : Set E)) = 0 := funext fun x ↦ by simp only [← singleton_zero, gauge_def', mem_closure_zero_iff_norm, norm_smul, mul_eq_zero, @@ -570,7 +566,7 @@ theorem gauge_closedBall (hr : 0 ≤ r) (x : E) : gauge (closedBall (0 : E) r) x theorem mul_gauge_le_norm (hs : Metric.ball (0 : E) r ⊆ s) : r * gauge s x ≤ ‖x‖ := by obtain hr | hr := le_or_lt r 0 · exact (mul_nonpos_of_nonpos_of_nonneg hr <| gauge_nonneg _).trans (norm_nonneg _) - rw [mul_comm, ← le_div_iff hr, ← gauge_ball hr.le] + rw [mul_comm, ← le_div_iff₀ hr, ← gauge_ball hr.le] exact gauge_mono (absorbent_ball_zero hr) hs x theorem Convex.lipschitzWith_gauge {r : ℝ≥0} (hc : Convex ℝ s) (hr : 0 < r) diff --git a/Mathlib/Analysis/Convex/GaugeRescale.lean b/Mathlib/Analysis/Convex/GaugeRescale.lean index 76930a882f4c9..5355e87f1273a 100644 --- a/Mathlib/Analysis/Convex/GaugeRescale.lean +++ b/Mathlib/Analysis/Convex/GaugeRescale.lean @@ -79,7 +79,7 @@ theorem gaugeRescale_gaugeRescale {s t u : Set E} (hta : Absorbent ℝ t) (htb : (x : E) : gaugeRescale t u (gaugeRescale s t x) = gaugeRescale s u x := by rcases eq_or_ne x 0 with rfl | hx; · simp rw [gaugeRescale_def s t x, gaugeRescale_smul, gaugeRescale, gaugeRescale, smul_smul, - div_mul_div_cancel] + div_mul_div_cancel₀] exacts [((gauge_pos hta htb).2 hx).ne', div_nonneg (gauge_nonneg _) (gauge_nonneg _)] /-- `gaugeRescale` bundled as an `Equiv`. -/ @@ -115,7 +115,7 @@ theorem continuous_gaugeRescale {s t : Set E} (hs : Convex ℝ s) (hs₀ : s ∈ rcases eq_or_ne x 0 with rfl | hx · rw [ContinuousAt, gaugeRescale_zero] nth_rewrite 2 [← comap_gauge_nhds_zero htb ht₀] - simp only [tendsto_comap_iff, (· ∘ ·), gauge_gaugeRescale _ hta htb] + simp only [tendsto_comap_iff, Function.comp_def, gauge_gaugeRescale _ hta htb] exact tendsto_gauge_nhds_zero hs₀ · exact ((continuousAt_gauge hs hs₀).div (continuousAt_gauge ht ht₀) ((gauge_pos hta htb).2 hx).ne').smul continuousAt_id diff --git a/Mathlib/Analysis/Convex/Intrinsic.lean b/Mathlib/Analysis/Convex/Intrinsic.lean index 7e5b5e4ee2e13..d05235e251337 100644 --- a/Mathlib/Analysis/Convex/Intrinsic.lean +++ b/Mathlib/Analysis/Convex/Intrinsic.lean @@ -96,6 +96,24 @@ 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] @@ -105,6 +123,15 @@ 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, @@ -116,8 +143,8 @@ alias ⟨Set.Nonempty.ofIntrinsicClosure, Set.Nonempty.intrinsicClosure⟩ := in @[simp] theorem intrinsicInterior_singleton (x : P) : intrinsicInterior 𝕜 ({x} : Set P) = {x} := by - simpa only [intrinsicInterior, preimage_coe_affineSpan_singleton, interior_univ, image_univ, - Subtype.range_coe] using coe_affineSpan_singleton _ _ _ + simp only [intrinsicInterior, preimage_coe_affineSpan_singleton, interior_univ, image_univ, + Subtype.range_coe_subtype, mem_affineSpan_singleton, setOf_eq_eq_singleton] @[simp] theorem intrinsicFrontier_singleton (x : P) : intrinsicFrontier 𝕜 ({x} : Set P) = ∅ := by @@ -125,8 +152,8 @@ theorem intrinsicFrontier_singleton (x : P) : intrinsicFrontier 𝕜 ({x} : Set @[simp] theorem intrinsicClosure_singleton (x : P) : intrinsicClosure 𝕜 ({x} : Set P) = {x} := by - simpa only [intrinsicClosure, preimage_coe_affineSpan_singleton, closure_univ, image_univ, - Subtype.range_coe] using coe_affineSpan_singleton _ _ _ + simp only [intrinsicClosure, preimage_coe_affineSpan_singleton, closure_univ, image_univ, + Subtype.range_coe_subtype, mem_affineSpan_singleton, setOf_eq_eq_singleton] /-! Note that neither `intrinsicInterior` nor `intrinsicFrontier` is monotone. diff --git a/Mathlib/Analysis/Convex/Jensen.lean b/Mathlib/Analysis/Convex/Jensen.lean index cbfbf7d8bf46b..20e5b017a492d 100644 --- a/Mathlib/Analysis/Convex/Jensen.lean +++ b/Mathlib/Analysis/Convex/Jensen.lean @@ -244,25 +244,31 @@ end Jensen section MaximumPrinciple variable [LinearOrderedField 𝕜] [AddCommGroup E] [LinearOrderedAddCommGroup β] [Module 𝕜 E] - [Module 𝕜 β] [OrderedSMul 𝕜 β] {s : Set E} {f : E → β} {t : Finset ι} {w : ι → 𝕜} {p : ι → E} + [Module 𝕜 β] [OrderedSMul 𝕜 β] {s : Set E} {f : E → β} {w : ι → 𝕜} {p : ι → E} {x y z : E} -theorem le_sup_of_mem_convexHull {s : Finset E} (hf : ConvexOn 𝕜 (convexHull 𝕜 (s : Set E)) f) - (hx : x ∈ convexHull 𝕜 (s : Set E)) : - f x ≤ s.sup' (coe_nonempty.1 <| convexHull_nonempty_iff.1 ⟨x, hx⟩) f := by +theorem ConvexOn.le_sup_of_mem_convexHull {t : Finset E} (hf : ConvexOn 𝕜 s f) (hts : ↑t ⊆ s) + (hx : x ∈ convexHull 𝕜 (t : Set E)) : + f x ≤ t.sup' (coe_nonempty.1 <| convexHull_nonempty_iff.1 ⟨x, hx⟩) f := by obtain ⟨w, hw₀, hw₁, rfl⟩ := mem_convexHull.1 hx - exact (hf.map_centerMass_le hw₀ (by positivity) <| subset_convexHull _ _).trans + exact (hf.map_centerMass_le hw₀ (by positivity) hts).trans (centerMass_le_sup hw₀ <| by positivity) -theorem inf_le_of_mem_convexHull {s : Finset E} (hf : ConcaveOn 𝕜 (convexHull 𝕜 (s : Set E)) f) - (hx : x ∈ convexHull 𝕜 (s : Set E)) : - s.inf' (coe_nonempty.1 <| convexHull_nonempty_iff.1 ⟨x, hx⟩) f ≤ f x := - le_sup_of_mem_convexHull hf.dual hx +theorem ConvexOn.inf_le_of_mem_convexHull {t : Finset E} (hf : ConcaveOn 𝕜 s f) (hts : ↑t ⊆ s) + (hx : x ∈ convexHull 𝕜 (t : Set E)) : + t.inf' (coe_nonempty.1 <| convexHull_nonempty_iff.1 ⟨x, hx⟩) f ≤ f x := + hf.dual.le_sup_of_mem_convexHull hts hx + +@[deprecated (since := "2024-08-25")] +alias le_sup_of_mem_convexHull := ConvexOn.le_sup_of_mem_convexHull + +@[deprecated (since := "2024-08-25")] +alias inf_le_of_mem_convexHull := ConvexOn.inf_le_of_mem_convexHull /-- If a function `f` is convex on `s`, then the value it takes at some center of mass of points of `s` is less than the value it takes on one of those points. -/ -theorem ConvexOn.exists_ge_of_centerMass (h : ConvexOn 𝕜 s f) (hw₀ : ∀ i ∈ t, 0 ≤ w i) - (hw₁ : 0 < ∑ i ∈ t, w i) (hp : ∀ i ∈ t, p i ∈ s) : +lemma ConvexOn.exists_ge_of_centerMass {t : Finset ι} (h : ConvexOn 𝕜 s f) + (hw₀ : ∀ i ∈ t, 0 ≤ w i) (hw₁ : 0 < ∑ i ∈ t, w i) (hp : ∀ i ∈ t, p i ∈ s) : ∃ i ∈ t, f (t.centerMass w p) ≤ f (p i) := by set y := t.centerMass w p -- TODO: can `rsuffices` be used to write the `exact` first, then the proof of this obtain? @@ -277,49 +283,57 @@ theorem ConvexOn.exists_ge_of_centerMass (h : ConvexOn 𝕜 s f) (hw₀ : ∀ i /-- If a function `f` is concave on `s`, then the value it takes at some center of mass of points of `s` is greater than the value it takes on one of those points. -/ -theorem ConcaveOn.exists_le_of_centerMass (h : ConcaveOn 𝕜 s f) (hw₀ : ∀ i ∈ t, 0 ≤ w i) - (hw₁ : 0 < ∑ i ∈ t, w i) (hp : ∀ i ∈ t, p i ∈ s) : ∃ i ∈ t, f (p i) ≤ f (t.centerMass w p) := - ConvexOn.exists_ge_of_centerMass (β := βᵒᵈ) h hw₀ hw₁ hp +lemma ConcaveOn.exists_le_of_centerMass {t : Finset ι} (h : ConcaveOn 𝕜 s f) + (hw₀ : ∀ i ∈ t, 0 ≤ w i) (hw₁ : 0 < ∑ i ∈ t, w i) (hp : ∀ i ∈ t, p i ∈ s) : + ∃ i ∈ t, f (p i) ≤ f (t.centerMass w p) := h.dual.exists_ge_of_centerMass hw₀ hw₁ hp /-- **Maximum principle** for convex functions. If a function `f` is convex on the convex hull of `s`, then the eventual maximum of `f` on `convexHull 𝕜 s` lies in `s`. -/ -theorem ConvexOn.exists_ge_of_mem_convexHull (hf : ConvexOn 𝕜 (convexHull 𝕜 s) f) {x} - (hx : x ∈ convexHull 𝕜 s) : ∃ y ∈ s, f x ≤ f y := by +lemma ConvexOn.exists_ge_of_mem_convexHull {t : Set E} (hf : ConvexOn 𝕜 s f) (hts : t ⊆ s) + (hx : x ∈ convexHull 𝕜 t) : ∃ y ∈ t, f x ≤ f y := by rw [_root_.convexHull_eq] at hx obtain ⟨α, t, w, p, hw₀, hw₁, hp, rfl⟩ := hx - rcases hf.exists_ge_of_centerMass hw₀ (hw₁.symm ▸ zero_lt_one) fun i hi => - subset_convexHull 𝕜 s (hp i hi) with - ⟨i, hit, Hi⟩ + obtain ⟨i, hit, Hi⟩ := hf.exists_ge_of_centerMass hw₀ (hw₁.symm ▸ zero_lt_one) + fun i hi ↦ hts (hp i hi) exact ⟨p i, hp i hit, Hi⟩ /-- **Minimum principle** for concave functions. If a function `f` is concave on the convex hull of `s`, then the eventual minimum of `f` on `convexHull 𝕜 s` lies in `s`. -/ -theorem ConcaveOn.exists_le_of_mem_convexHull (hf : ConcaveOn 𝕜 (convexHull 𝕜 s) f) {x} - (hx : x ∈ convexHull 𝕜 s) : ∃ y ∈ s, f y ≤ f x := - ConvexOn.exists_ge_of_mem_convexHull (β := βᵒᵈ) hf hx +lemma ConcaveOn.exists_le_of_mem_convexHull {t : Set E} (hf : ConcaveOn 𝕜 s f) (hts : t ⊆ s) + (hx : x ∈ convexHull 𝕜 t) : ∃ y ∈ t, f y ≤ f x := hf.dual.exists_ge_of_mem_convexHull hts hx /-- **Maximum principle** for convex functions on a segment. If a function `f` is convex on the segment `[x, y]`, then the eventual maximum of `f` on `[x, y]` is at `x` or `y`. -/ -lemma ConvexOn.le_max_of_mem_segment (hf : ConvexOn 𝕜 [x -[𝕜] y] f) (hz : z ∈ [x -[𝕜] y]) : - f z ≤ max (f x) (f y) := by - rw [← convexHull_pair] at hf hz; simpa using hf.exists_ge_of_mem_convexHull hz +lemma ConvexOn.le_max_of_mem_segment (hf : ConvexOn 𝕜 s f) (hx : x ∈ s) (hy : y ∈ s) + (hz : z ∈ [x -[𝕜] y]) : f z ≤ max (f x) (f y) := by + rw [← convexHull_pair] at hz; simpa using hf.exists_ge_of_mem_convexHull (pair_subset hx hy) hz /-- **Minimum principle** for concave functions on a segment. If a function `f` is concave on the segment `[x, y]`, then the eventual minimum of `f` on `[x, y]` is at `x` or `y`. -/ -lemma ConcaveOn.min_le_of_mem_segment (hf : ConcaveOn 𝕜 [x -[𝕜] y] f) (hz : z ∈ [x -[𝕜] y]) : - min (f x) (f y) ≤ f z := by - rw [← convexHull_pair] at hf hz; simpa using hf.exists_le_of_mem_convexHull hz +lemma ConcaveOn.min_le_of_mem_segment (hf : ConcaveOn 𝕜 s f) (hx : x ∈ s) (hy : y ∈ s) + (hz : z ∈ [x -[𝕜] y]) : min (f x) (f y) ≤ f z := hf.dual.le_max_of_mem_segment hx hy hz /-- **Maximum principle** for convex functions on an interval. If a function `f` is convex on the interval `[x, y]`, then the eventual maximum of `f` on `[x, y]` is at `x` or `y`. -/ -lemma ConvexOn.le_max_of_mem_Icc {f : 𝕜 → β} {x y z : 𝕜} (hf : ConvexOn 𝕜 (Icc x y) f) - (hz : z ∈ Icc x y) : f z ≤ max (f x) (f y) := by - rw [← segment_eq_Icc (hz.1.trans hz.2)] at hf hz; exact hf.le_max_of_mem_segment hz +lemma ConvexOn.le_max_of_mem_Icc {s : Set 𝕜} {f : 𝕜 → β} {x y z : 𝕜} (hf : ConvexOn 𝕜 s f) + (hx : x ∈ s) (hy : y ∈ s) (hz : z ∈ Icc x y) : f z ≤ max (f x) (f y) := by + rw [← segment_eq_Icc (hz.1.trans hz.2)] at hz; exact hf.le_max_of_mem_segment hx hy hz /-- **Minimum principle** for concave functions on an interval. If a function `f` is concave on the interval `[x, y]`, then the eventual minimum of `f` on `[x, y]` is at `x` or `y`. -/ -lemma ConcaveOn.min_le_of_mem_Icc {f : 𝕜 → β} {x y z : 𝕜} (hf : ConcaveOn 𝕜 (Icc x y) f) - (hz : z ∈ Icc x y) : min (f x) (f y) ≤ f z := by - rw [← segment_eq_Icc (hz.1.trans hz.2)] at hf hz; exact hf.min_le_of_mem_segment hz +lemma ConcaveOn.min_le_of_mem_Icc {s : Set 𝕜} {f : 𝕜 → β} {x y z : 𝕜} (hf : ConcaveOn 𝕜 s f) + (hx : x ∈ s) (hy : y ∈ s) (hz : z ∈ Icc x y) : min (f x) (f y) ≤ f z := + hf.dual.le_max_of_mem_Icc hx hy hz + +lemma ConvexOn.bddAbove_convexHull {s t : Set E} (hst : s ⊆ t) (hf : ConvexOn 𝕜 t f) : + BddAbove (f '' s) → BddAbove (f '' convexHull 𝕜 s) := by + rintro ⟨b, hb⟩ + refine ⟨b, ?_⟩ + rintro _ ⟨x, hx, rfl⟩ + obtain ⟨y, hy, hxy⟩ := hf.exists_ge_of_mem_convexHull hst hx + exact hxy.trans <| hb <| mem_image_of_mem _ hy + +lemma ConcaveOn.bddBelow_convexHull {s t : Set E} (hst : s ⊆ t) (hf : ConcaveOn 𝕜 t f) : + BddBelow (f '' s) → BddBelow (f '' convexHull 𝕜 s) := hf.dual.bddAbove_convexHull hst end MaximumPrinciple diff --git a/Mathlib/Analysis/Convex/Measure.lean b/Mathlib/Analysis/Convex/Measure.lean index 6dec1b9d305d3..d8b9b78be2d4b 100644 --- a/Mathlib/Analysis/Convex/Measure.lean +++ b/Mathlib/Analysis/Convex/Measure.lean @@ -59,7 +59,7 @@ theorem addHaar_frontier (hs : Convex ℝ s) : μ (frontier s) = 0 := by `μ (closure s) ≤ μ (interior s)`. -/ replace hb : μ (interior s) ≠ ∞ := (hb.subset interior_subset).measure_lt_top.ne suffices μ (closure s) ≤ μ (interior s) by - rwa [frontier, measure_diff interior_subset_closure isOpen_interior.measurableSet hb, + rwa [frontier, measure_diff interior_subset_closure isOpen_interior.nullMeasurableSet hb, tsub_eq_zero_iff_le] /- 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)`, diff --git a/Mathlib/Analysis/Convex/Normed.lean b/Mathlib/Analysis/Convex/Normed.lean index 2359391cb0ece..2cb4a8b2db0d7 100644 --- a/Mathlib/Analysis/Convex/Normed.lean +++ b/Mathlib/Analysis/Convex/Normed.lean @@ -8,6 +8,7 @@ import Mathlib.Analysis.Convex.Jensen import Mathlib.Analysis.Convex.Topology import Mathlib.Analysis.Normed.Group.Pointwise import Mathlib.Analysis.Normed.Affine.AddTorsor +import Mathlib.Analysis.Normed.Affine.AddTorsorBases /-! # Topological and metric properties of convex sets in normed spaces @@ -26,9 +27,10 @@ We prove the following facts: variable {ι : Type*} {E P : Type*} -open Metric Set -open scoped Convex +open AffineBasis FiniteDimensional Metric Set +open scoped Convex Pointwise Topology +section SeminormedAddCommGroup variable [SeminormedAddCommGroup E] [NormedSpace ℝ E] [PseudoMetricSpace P] [NormedAddTorsor E P] variable {s t : Set E} @@ -74,7 +76,7 @@ theorem Convex.cthickening (hs : Convex ℝ s) (δ : ℝ) : Convex ℝ (cthicken of `s` at distance at least `dist x y` from `y`. -/ theorem convexHull_exists_dist_ge {s : Set E} {x : E} (hx : x ∈ convexHull ℝ s) (y : E) : ∃ x' ∈ s, dist x y ≤ dist x' y := - (convexOn_dist y (convex_convexHull ℝ _)).exists_ge_of_mem_convexHull hx + (convexOn_dist y (convex_convexHull ℝ _)).exists_ge_of_mem_convexHull (subset_convexHull ..) hx /-- Given a point `x` in the convex hull of `s` and a point `y` in the convex hull of `t`, there exist points `x' ∈ s` and `y' ∈ t` at distance at least `dist x y`. -/ @@ -133,3 +135,56 @@ theorem isConnected_setOf_sameRay_and_ne_zero {x : E} (hx : x ≠ 0) : IsConnected { y | SameRay ℝ x y ∧ y ≠ 0 } := by simp_rw [← exists_pos_left_iff_sameRay_and_ne_zero hx] exact isConnected_Ioi.image _ (continuous_id.smul continuous_const).continuousOn + +end SeminormedAddCommGroup + +section NormedAddCommGroup +variable [NormedAddCommGroup E] [NormedSpace ℝ E] [FiniteDimensional ℝ E] {s : Set E} {x : E} + +/-- We can intercalate a simplex between a point and one of its neighborhoods. -/ +lemma exists_mem_interior_convexHull_affineBasis (hs : s ∈ 𝓝 x) : + ∃ b : AffineBasis (Fin (finrank ℝ E + 1)) ℝ E, + x ∈ interior (convexHull ℝ (range b)) ∧ convexHull ℝ (range b) ⊆ s := by + classical + -- By translating, WLOG `x` is the origin. + wlog hx : x = 0 + · obtain ⟨b, hb⟩ := this (s := -x +ᵥ s) (by simpa using vadd_mem_nhds_vadd (-x) hs) rfl + use x +ᵥ b + simpa [subset_set_vadd_iff, mem_vadd_set_iff_neg_vadd_mem, convexHull_vadd, interior_vadd, + Pi.vadd_def, -vadd_eq_add, vadd_eq_add (a := -x), ← Set.vadd_set_range] using hb + subst hx + -- The strategy is now to find an arbitrary maximal spanning simplex (aka an affine basis)... + obtain ⟨b⟩ := exists_affineBasis_of_finiteDimensional + (ι := Fin (finrank ℝ E + 1)) (k := ℝ) (P := E) (by simp) + -- ... translate it to contain the origin... + set c : AffineBasis (Fin (finrank ℝ E + 1)) ℝ E := -Finset.univ.centroid ℝ b +ᵥ b + have hc₀ : 0 ∈ interior (convexHull ℝ (range c) : Set E) := by + simpa [c, convexHull_vadd, interior_vadd, range_add, Pi.vadd_def, mem_vadd_set_iff_neg_vadd_mem] + using b.centroid_mem_interior_convexHull + set cnorm := Finset.univ.sup' Finset.univ_nonempty (fun i ↦ ‖c i‖) + have hcnorm : range c ⊆ closedBall 0 (cnorm + 1) := by + simpa only [cnorm, subset_def, Finset.mem_coe, mem_closedBall, dist_zero_right, + ← sub_le_iff_le_add, Finset.le_sup'_iff, forall_mem_range] using fun i ↦ ⟨i, by simp⟩ + -- ... and finally scale it to fit inside the neighborhood `s`. + obtain ⟨ε, hε, hεs⟩ := Metric.mem_nhds_iff.1 hs + set ε' : ℝ := ε / 2 / (cnorm + 1) + have hc' : 0 < cnorm + 1 := by + have : 0 ≤ cnorm := Finset.le_sup'_of_le _ (Finset.mem_univ 0) (norm_nonneg _) + positivity + have hε' : 0 < ε' := by positivity + set d : AffineBasis (Fin (finrank ℝ E + 1)) ℝ E := Units.mk0 ε' hε'.ne' • c + have hε₀ : 0 < ε / 2 := by positivity + have hdnorm : (range d : Set E) ⊆ closedBall 0 (ε / 2) := by + simp [d, Set.set_smul_subset_iff₀ hε'.ne', hε₀.le, _root_.smul_closedBall, abs_of_nonneg hε'.le, + range_subset_iff, norm_smul] + simpa [ε', hε₀.ne', range_subset_iff, ← mul_div_right_comm (ε / 2), div_le_iff₀ hc', + mul_le_mul_left hε₀] using hcnorm + refine ⟨d, ?_, ?_⟩ + · simpa [d, Pi.smul_def, range_smul, interior_smul₀, convexHull_smul, zero_mem_smul_set_iff, + hε'.ne'] + · calc + convexHull ℝ (range d) ⊆ closedBall 0 (ε / 2) := convexHull_min hdnorm (convex_closedBall ..) + _ ⊆ ball 0 ε := closedBall_subset_ball (by linarith) + _ ⊆ s := hεs + +end NormedAddCommGroup diff --git a/Mathlib/Analysis/Convex/SimplicialComplex/Basic.lean b/Mathlib/Analysis/Convex/SimplicialComplex/Basic.lean index b1f12fdb8b073..41111c8c7ea85 100644 --- a/Mathlib/Analysis/Convex/SimplicialComplex/Basic.lean +++ b/Mathlib/Analysis/Convex/SimplicialComplex/Basic.lean @@ -72,7 +72,7 @@ variable {K : SimplicialComplex 𝕜 E} {s t : Finset E} {x : E} /-- A `Finset` belongs to a `SimplicialComplex` if it's a face of it. -/ instance : Membership (Finset E) (SimplicialComplex 𝕜 E) := - ⟨fun s K => s ∈ K.faces⟩ + ⟨fun K s => s ∈ K.faces⟩ /-- The underlying space of a simplicial complex is the union of its faces. -/ def space (K : SimplicialComplex 𝕜 E) : Set E := @@ -166,7 +166,7 @@ theorem face_subset_face_iff (hs : s ∈ K.faces) (ht : t ∈ K.faces) : ⟨fun h _ hxs => (vertex_mem_convexHull_iff (K.down_closed hs (Finset.singleton_subset_iff.2 hxs) <| singleton_ne_empty _) ht).1 - (h (subset_convexHull 𝕜 (↑s) hxs)), + (h (subset_convexHull 𝕜 (E := E) s hxs)), convexHull_mono⟩ /-! ### Facets -/ diff --git a/Mathlib/Analysis/Convex/Slope.lean b/Mathlib/Analysis/Convex/Slope.lean index 4bfa3fe7e4643..ea7ca88a2e853 100644 --- a/Mathlib/Analysis/Convex/Slope.lean +++ b/Mathlib/Analysis/Convex/Slope.lean @@ -113,7 +113,7 @@ theorem convexOn_of_slope_mono_adjacent (hs : Convex 𝕜 s) simp_rw [div_eq_iff hxz.ne', ← hab] ring rwa [sub_mul, sub_mul, sub_le_iff_le_add', ← add_sub_assoc, le_sub_iff_add_le, ← mul_add, - sub_add_sub_cancel, ← le_div_iff hxz, add_div, mul_div_assoc, mul_div_assoc, mul_comm (f x), + sub_add_sub_cancel, ← le_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 @@ -221,7 +221,7 @@ theorem ConvexOn.secant_mono_aux1 (hf : ConvexOn 𝕜 s f) {x y z : 𝕜} (hx : have hxy' : 0 < y - x := by linarith have hyz' : 0 < z - y := by linarith have hxz' : 0 < z - x := by linarith - rw [← le_div_iff' hxz'] + rw [← le_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/Star.lean b/Mathlib/Analysis/Convex/Star.lean index f85ffeac0a9fe..44f1a60ccabfb 100644 --- a/Mathlib/Analysis/Convex/Star.lean +++ b/Mathlib/Analysis/Convex/Star.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies -/ import Mathlib.Algebra.Module.LinearMap.Prod +import Mathlib.Algebra.Order.Module.Synonym import Mathlib.Algebra.Order.Group.Instances import Mathlib.Analysis.Convex.Segment import Mathlib.Tactic.GCongr diff --git a/Mathlib/Analysis/Convex/StoneSeparation.lean b/Mathlib/Analysis/Convex/StoneSeparation.lean index 3a0fdf9701a5f..4f746cd1909fd 100644 --- a/Mathlib/Analysis/Convex/StoneSeparation.lean +++ b/Mathlib/Analysis/Convex/StoneSeparation.lean @@ -46,7 +46,9 @@ 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, add_comm, ← mul_smul, ← mul_smul] + 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] @@ -63,8 +65,8 @@ theorem not_disjoint_segment_convexHull_triple {p q u v x y z : E} (hz : z ∈ s mul_assoc, ← mul_add, mul_comm av, ← add_mul, ← mul_add, add_comm bu, add_comm bv, habu, habv, one_mul, mul_one] 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 + 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] diff --git a/Mathlib/Analysis/Convex/Uniform.lean b/Mathlib/Analysis/Convex/Uniform.lean index a5ad07edba1ae..c57da9a0c876f 100644 --- a/Mathlib/Analysis/Convex/Uniform.lean +++ b/Mathlib/Analysis/Convex/Uniform.lean @@ -117,7 +117,7 @@ theorem exists_forall_closed_ball_dist_add_le_two_mul_sub (hε : 0 < ε) (r : rw [← div_le_one hr, div_eq_inv_mul, ← norm_smul_of_nonneg (inv_nonneg.2 hr.le)] at hx hy have := h hx hy simp_rw [← smul_add, ← smul_sub, norm_smul_of_nonneg (inv_nonneg.2 hr.le), ← div_eq_inv_mul, - div_le_div_right hr, div_le_iff hr, sub_mul] at this + div_le_div_right hr, div_le_iff₀ hr, sub_mul] at this exact this hxy end SeminormedAddCommGroup diff --git a/Mathlib/Analysis/Distribution/AEEqOfIntegralContDiff.lean b/Mathlib/Analysis/Distribution/AEEqOfIntegralContDiff.lean index 8919c573b7372..530b964dfa9a1 100644 --- a/Mathlib/Analysis/Distribution/AEEqOfIntegralContDiff.lean +++ b/Mathlib/Analysis/Distribution/AEEqOfIntegralContDiff.lean @@ -112,6 +112,8 @@ theorem ae_eq_zero_of_integral_smooth_smul_eq_zero [SigmaCompactSpace M] simpa [g_supp] using vK n simpa [this] using L +-- An instance with keys containing `Opens` +instance (U : Opens M) : BorelSpace U := inferInstanceAs (BorelSpace (U : Set M)) /-- If a function `f` locally integrable on an open subset `U` of a finite-dimensional real manifold has zero integral when multiplied by any smooth function compactly supported diff --git a/Mathlib/Analysis/Distribution/SchwartzSpace.lean b/Mathlib/Analysis/Distribution/SchwartzSpace.lean index c8404661ec6dc..73c009395f7d1 100644 --- a/Mathlib/Analysis/Distribution/SchwartzSpace.lean +++ b/Mathlib/Analysis/Distribution/SchwartzSpace.lean @@ -138,7 +138,7 @@ theorem isBigO_cocompact_zpow_neg_nat (k : ℕ) : simp_rw [Asymptotics.IsBigO, Asymptotics.IsBigOWith] 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'] + 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) _] theorem isBigO_cocompact_rpow [ProperSpace E] (s : ℝ) : @@ -380,7 +380,7 @@ end Module section Seminorms -/-! ### Seminorms on Schwartz space-/ +/-! ### Seminorms on Schwartz space -/ variable [NormedField 𝕜] [NormedSpace 𝕜 F] [SMulCommClass ℝ 𝕜 F] @@ -480,7 +480,7 @@ end Seminorms section Topology -/-! ### The topology on the Schwartz space-/ +/-! ### The topology on the Schwartz space -/ variable [NormedField 𝕜] [NormedSpace 𝕜 F] [SMulCommClass ℝ 𝕜 F] @@ -860,7 +860,7 @@ def compCLM {g : D → E} (hg : g.HasTemperateGrowth) ∀ i, i ≤ n → ‖iteratedFDeriv ℝ i f (g x)‖ ≤ 2 ^ k' * seminorm_f / (1 + ‖g x‖) ^ k' := by intro i hi have hpos : 0 < (1 + ‖g x‖) ^ k' := by positivity - rw [le_div_iff' hpos] + rw [le_div_iff₀' hpos] change i ≤ (k', n).snd at hi exact one_add_le_sup_seminorm_apply le_rfl hi _ _ have hgrowth' : ∀ N : ℕ, 1 ≤ N → N ≤ n → @@ -886,7 +886,7 @@ def compCLM {g : D → E} (hg : g.HasTemperateGrowth) ring rw [rearrange] have hgxk' : 0 < (1 + ‖g x‖) ^ k' := by positivity - rw [← div_le_iff hgxk'] at hg_upper'' + rw [← div_le_iff₀ hgxk'] at hg_upper'' have hpos : (0 : ℝ) ≤ (C + 1) ^ n * n ! * 2 ^ k' * seminorm_f := by have : 0 ≤ seminorm_f := apply_nonneg _ _ positivity @@ -1089,7 +1089,7 @@ def integralCLM : 𝓢(D, V) →L[𝕜] V := have h' : ∀ x, ‖f x‖ ≤ (1 + ‖x‖) ^ (-(n : ℝ)) * (2 ^ n * ((Finset.Iic m).sup (fun m' => SchwartzMap.seminorm 𝕜 m'.1 m'.2) f)) := by intro x - rw [rpow_neg (by positivity), ← div_eq_inv_mul, le_div_iff' (by positivity), rpow_natCast] + rw [rpow_neg (by positivity), ← div_eq_inv_mul, le_div_iff₀' (by positivity), rpow_natCast] simpa using one_add_le_sup_seminorm_apply (m := m) (k := n) (n := 0) le_rfl le_rfl f x apply (integral_mono (by simpa using f.integrable_pow_mul μ 0) _ h').trans · rw [integral_mul_right, ← mul_assoc, mul_comm (2 ^ n)] @@ -1189,7 +1189,7 @@ instance instZeroAtInftyContinuousMapClass : ZeroAtInftyContinuousMapClass 𝓢( simp only [hxzero, norm_zero, zero_mul, ← not_le] at hx exact hx (apply_nonneg (SchwartzMap.seminorm ℝ 1 0) f) have := norm_pow_mul_le_seminorm ℝ f 1 x - rw [pow_one, ← le_div_iff' hxpos] at this + rw [pow_one, ← le_div_iff₀' hxpos] at this apply lt_of_le_of_lt this rwa [div_lt_iff' hxpos] diff --git a/Mathlib/Analysis/Fourier/AddCircle.lean b/Mathlib/Analysis/Fourier/AddCircle.lean index 17dac62db0a31..86ac394b06e8d 100644 --- a/Mathlib/Analysis/Fourier/AddCircle.lean +++ b/Mathlib/Analysis/Fourier/AddCircle.lean @@ -111,7 +111,7 @@ theorem fourier_apply {n : ℤ} {x : AddCircle T} : fourier n x = toCircle (n theorem fourier_coe_apply {n : ℤ} {x : ℝ} : fourier n (x : AddCircle T) = Complex.exp (2 * π * Complex.I * n * x / T) := by rw [fourier_apply, ← QuotientAddGroup.mk_zsmul, toCircle, Function.Periodic.lift_coe, - Circle.exp_apply, Complex.ofReal_mul, Complex.ofReal_div, Complex.ofReal_mul, zsmul_eq_mul, + Circle.coe_exp, Complex.ofReal_mul, Complex.ofReal_div, Complex.ofReal_mul, zsmul_eq_mul, Complex.ofReal_mul, Complex.ofReal_intCast] norm_num congr 1; ring @@ -173,7 +173,7 @@ theorem fourier_add_half_inv_index {n : ℤ} (hn : n ≠ 0) (hT : 0 < T) (x : Ad rw [fourier_apply, zsmul_add, ← QuotientAddGroup.mk_zsmul, toCircle_add, coe_mul_unitSphere] have : (n : ℂ) ≠ 0 := by simpa using hn have : (@toCircle T (n • (T / 2 / n) : ℝ) : ℂ) = -1 := by - rw [zsmul_eq_mul, toCircle, Function.Periodic.lift_coe, Circle.exp_apply] + rw [zsmul_eq_mul, toCircle, Function.Periodic.lift_coe, Circle.coe_exp] replace hT := Complex.ofReal_ne_zero.mpr hT.ne' convert Complex.exp_pi_mul_I using 3 field_simp; ring diff --git a/Mathlib/Analysis/Fourier/FourierTransform.lean b/Mathlib/Analysis/Fourier/FourierTransform.lean index 562e533a3b0f4..8a1b83c8d5e3e 100644 --- a/Mathlib/Analysis/Fourier/FourierTransform.lean +++ b/Mathlib/Analysis/Fourier/FourierTransform.lean @@ -78,15 +78,11 @@ def fourierIntegral (e : AddChar 𝕜 𝕊) (μ : Measure V) (L : V →ₗ[𝕜] (w : W) : E := ∫ v, e (-L v w) • f v ∂μ -theorem fourierIntegral_smul_const (e : AddChar 𝕜 𝕊) (μ : Measure V) +theorem fourierIntegral_const_smul (e : AddChar 𝕜 𝕊) (μ : Measure V) (L : V →ₗ[𝕜] W →ₗ[𝕜] 𝕜) (f : V → E) (r : ℂ) : fourierIntegral e μ L (r • f) = r • fourierIntegral e μ L f := by ext1 w - -- Porting note: was - -- simp only [Pi.smul_apply, fourierIntegral, smul_comm _ r, integral_smul] - simp only [Pi.smul_apply, fourierIntegral, ← integral_smul] - congr 1 with v - rw [smul_comm] + simp only [Pi.smul_apply, fourierIntegral, smul_comm _ r, integral_smul] /-- The uniform norm of the Fourier integral of `f` is bounded by the `L¹` norm of `f`. -/ theorem norm_fourierIntegral_le_integral_norm (e : AddChar 𝕜 𝕊) (μ : Measure V) @@ -145,7 +141,7 @@ alias fourier_integral_convergent_iff := VectorFourier.fourierIntegral_convergen theorem fourierIntegral_add (he : Continuous e) (hL : Continuous fun p : V × W ↦ L p.1 p.2) {f g : V → E} (hf : Integrable f μ) (hg : Integrable g μ) : - fourierIntegral e μ L f + fourierIntegral e μ L g = fourierIntegral e μ L (f + g) := by + fourierIntegral e μ L (f + g) = fourierIntegral e μ L f + fourierIntegral e μ L g := by ext1 w dsimp only [Pi.add_apply, fourierIntegral] simp_rw [smul_add] @@ -281,9 +277,9 @@ theorem fourierIntegral_def (e : AddChar 𝕜 𝕊) (μ : Measure 𝕜) (f : fourierIntegral e μ f w = ∫ v : 𝕜, e (-(v * w)) • f v ∂μ := rfl -theorem fourierIntegral_smul_const (e : AddChar 𝕜 𝕊) (μ : Measure 𝕜) (f : 𝕜 → E) (r : ℂ) : +theorem fourierIntegral_const_smul (e : AddChar 𝕜 𝕊) (μ : Measure 𝕜) (f : 𝕜 → E) (r : ℂ) : fourierIntegral e μ (r • f) = r • fourierIntegral e μ f := - VectorFourier.fourierIntegral_smul_const _ _ _ _ _ + VectorFourier.fourierIntegral_const_smul _ _ _ _ _ /-- The uniform norm of the Fourier transform of `f` is bounded by the `L¹` norm of `f`. -/ theorem norm_fourierIntegral_le_integral_norm (e : AddChar 𝕜 𝕊) (μ : Measure 𝕜) diff --git a/Mathlib/Analysis/Fourier/RiemannLebesgueLemma.lean b/Mathlib/Analysis/Fourier/RiemannLebesgueLemma.lean index 9d6a346e16240..e3095be779ad6 100644 --- a/Mathlib/Analysis/Fourier/RiemannLebesgueLemma.lean +++ b/Mathlib/Analysis/Fourier/RiemannLebesgueLemma.lean @@ -9,7 +9,6 @@ import Mathlib.Analysis.InnerProductSpace.EuclideanDist import Mathlib.MeasureTheory.Function.ContinuousMapDense import Mathlib.MeasureTheory.Group.Integral import Mathlib.MeasureTheory.Integral.SetIntegral -import Mathlib.MeasureTheory.Measure.Haar.NormedSpace import Mathlib.Topology.EMetricSpace.Paracompact import Mathlib.MeasureTheory.Measure.Haar.Unique @@ -262,41 +261,11 @@ theorem tendsto_integral_exp_smul_cocompact (μ : Measure V) [μ.IsAddHaarMeasur borelize V' -- various equivs derived from A let Aₘ : MeasurableEquiv V V' := A.toHomeomorph.toMeasurableEquiv - -- isomorphism between duals derived from A -- need to do continuity as a separate step in order - -- to apply `LinearMap.continuous_of_finiteDimensional`. - let Adualₗ : (V →L[ℝ] ℝ) ≃ₗ[ℝ] V' →L[ℝ] ℝ := - { toFun := fun t => t.comp A.symm.toContinuousLinearMap - invFun := fun t => t.comp A.toContinuousLinearMap - map_add' := by - intro t s - ext1 v - simp only [ContinuousLinearMap.coe_comp', Function.comp_apply, - ContinuousLinearMap.add_apply] - map_smul' := by - intro x f - ext1 v - simp only [RingHom.id_apply, ContinuousLinearMap.coe_comp', Function.comp_apply, - ContinuousLinearMap.smul_apply] - left_inv := by - intro w - ext1 v - simp only [ContinuousLinearMap.coe_comp', - ContinuousLinearEquiv.coe_coe, Function.comp_apply, - ContinuousLinearEquiv.symm_apply_apply] - right_inv := by - intro w - ext1 v - simp only [ContinuousLinearMap.coe_comp', - ContinuousLinearEquiv.coe_coe, Function.comp_apply, - ContinuousLinearEquiv.apply_symm_apply] } - let Adual : (V →L[ℝ] ℝ) ≃L[ℝ] V' →L[ℝ] ℝ := - { Adualₗ with - continuous_toFun := Adualₗ.toLinearMap.continuous_of_finiteDimensional - continuous_invFun := Adualₗ.symm.toLinearMap.continuous_of_finiteDimensional } - have : (μ.map Aₘ).IsAddHaarMeasure := Measure.MapContinuousLinearEquiv.isAddHaarMeasure _ A - convert - (tendsto_integral_exp_smul_cocompact_of_inner_product (f ∘ A.symm) (μ.map Aₘ)).comp - Adual.toHomeomorph.toCocompactMap.cocompact_tendsto' with w + -- isomorphism between duals derived from A + let Adual : (V →L[ℝ] ℝ) ≃L[ℝ] V' →L[ℝ] ℝ := A.arrowCongrSL (.refl _ _) + have : (μ.map Aₘ).IsAddHaarMeasure := A.isAddHaarMeasure_map _ + convert (tendsto_integral_exp_smul_cocompact_of_inner_product (f ∘ A.symm) (μ.map Aₘ)).comp + Adual.toHomeomorph.toCocompactMap.cocompact_tendsto' with w rw [Function.comp_apply, integral_map_equiv] congr 1 with v : 1 congr diff --git a/Mathlib/Analysis/Fourier/ZMod.lean b/Mathlib/Analysis/Fourier/ZMod.lean index f93cc4bef7da1..e817057d937c2 100644 --- a/Mathlib/Analysis/Fourier/ZMod.lean +++ b/Mathlib/Analysis/Fourier/ZMod.lean @@ -10,42 +10,174 @@ import Mathlib.NumberTheory.DirichletCharacter.GaussSum /-! # Fourier theory on `ZMod N` -Basic definitions and properties of the discrete Fourier transform for functions on `ZMod N`. +Basic definitions and properties of the discrete Fourier transform for functions on `ZMod N` +(taking values in an arbitrary `ℂ`-vector space). ### Main definitions and results -* `ZMod.dft`: the Fourier transform with respect to the standard additive character +* `ZMod.dft`: the Fourier transform, with respect to the standard additive character `ZMod.stdAddChar` (mapping `j mod N` to `exp (2 * π * I * j / N)`). The notation `𝓕`, scoped in namespace `ZMod`, is available for this. +* `ZMod.dft_dft`: the Fourier inversion formula. * `DirichletCharacter.fourierTransform_eq_inv_mul_gaussSum`: the discrete Fourier transform of a primitive Dirichlet character `χ` is a Gauss sum times `χ⁻¹`. -/ -open scoped Real - -open MeasureTheory +open MeasureTheory Finset AddChar ZMod namespace ZMod -variable {N : ℕ} [NeZero N] +variable {N : ℕ} [NeZero N] {E : Type*} [AddCommGroup E] [Module ℂ E] + +section private_defs +/- +It doesn't _quite_ work to define the Fourier transform as a `LinearEquiv` in one go, because that +leads to annoying repetition between the proof fields. So we set up a private definition first, +prove a minimal set of lemmas about it, and then define the `LinearEquiv` using that. + +**Do not add more lemmas about `auxDFT`**: it should be invisible to end-users. +-/ -/-- The discrete Fourier transform on `ℤ / N ℤ` (with the counting measure) -/ -noncomputable def dft (Φ : ZMod N → ℂ) (k : ZMod N) : ℂ := - Fourier.fourierIntegral toCircle Measure.count Φ k +/-- +The discrete Fourier transform on `ℤ / N ℤ` (with the counting measure). This definition is +private because it is superseded by the bundled `LinearEquiv` version. +-/ +private noncomputable def auxDFT (Φ : ZMod N → E) (k : ZMod N) : E := + ∑ j : ZMod N, stdAddChar (-(j * k)) • Φ j + +private lemma auxDFT_neg (Φ : ZMod N → E) : auxDFT (fun j ↦ Φ (-j)) = fun k ↦ auxDFT Φ (-k) := by + ext1 k; simpa only [auxDFT] using + Fintype.sum_equiv (Equiv.neg _) _ _ (fun j ↦ by rw [Equiv.neg_apply, neg_mul_neg]) + +/-- Fourier inversion formula, discrete case. -/ +private lemma auxDFT_auxDFT (Φ : ZMod N → E) : auxDFT (auxDFT Φ) = fun j ↦ (N : ℂ) • Φ (-j) := by + ext1 j + simp only [auxDFT, mul_comm _ j, smul_sum, ← smul_assoc, smul_eq_mul, ← map_add_eq_mul, ← + neg_add, ← add_mul] + rw [sum_comm] + simp only [← sum_smul, ← neg_mul] + have h1 (t : ZMod N) : ∑ i, stdAddChar (t * i) = if t = 0 then ↑N else 0 := by + split_ifs with h + · simp only [h, zero_mul, map_zero_eq_one, sum_const, card_univ, card, + nsmul_eq_mul, mul_one] + · exact sum_eq_zero_of_ne_one (isPrimitive_stdAddChar N h) + have h2 (x j : ZMod N) : -(j + x) = 0 ↔ x = -j := by + rw [neg_add, add_comm, add_eq_zero_iff_neg_eq, neg_neg] + simp only [h1, h2, ite_smul, zero_smul, sum_ite_eq', mem_univ, ite_true] + +private lemma auxDFT_smul (c : ℂ) (Φ : ZMod N → E) : + auxDFT (c • Φ) = c • auxDFT Φ := by + ext; simp only [Pi.smul_def, auxDFT, smul_sum, smul_comm c] + +end private_defs + +section defs + +/-- +The discrete Fourier transform on `ℤ / N ℤ` (with the counting measure), bundled as a linear +equivalence. +-/ +noncomputable def dft : (ZMod N → E) ≃ₗ[ℂ] (ZMod N → E) where + toFun := auxDFT + map_add' Φ₁ Φ₂ := by + ext; simp only [auxDFT, Pi.add_def, smul_add, sum_add_distrib] + map_smul' c Φ := by + ext; simp only [auxDFT, Pi.smul_apply, RingHom.id_apply, smul_sum, smul_comm c] + invFun Φ k := (N : ℂ)⁻¹ • auxDFT Φ (-k) + left_inv Φ := by + simp only [auxDFT_auxDFT, neg_neg, ← mul_smul, inv_mul_cancel₀ (NeZero.ne _), one_smul] + right_inv Φ := by + ext1 j + simp only [← Pi.smul_def, auxDFT_smul, auxDFT_neg, auxDFT_auxDFT, neg_neg, ← mul_smul, + inv_mul_cancel₀ (NeZero.ne _), one_smul] @[inherit_doc] scoped notation "𝓕" => dft -lemma dft_apply (Φ : ZMod N → ℂ) (k : ZMod N) : - 𝓕 Φ k = ∑ j : ZMod N, toCircle (-(j * k)) • Φ j := by - simp only [dft, Fourier.fourierIntegral_def, integral_countable' <| .of_finite .., - Measure.count_singleton, ENNReal.one_toReal, one_smul, tsum_fintype] +/-- The inverse Fourier transform on `ZMod N`. -/ +scoped notation "𝓕⁻" => LinearEquiv.symm dft -lemma dft_def (Φ : ZMod N → ℂ) : 𝓕 Φ = fun k ↦ ∑ j : ZMod N, toCircle (-(j * k)) • Φ j := - funext (dft_apply Φ) +lemma dft_apply (Φ : ZMod N → E) (k : ZMod N) : + 𝓕 Φ k = ∑ j : ZMod N, stdAddChar (-(j * k)) • Φ j := + rfl -end ZMod +lemma dft_def (Φ : ZMod N → E) : + 𝓕 Φ = fun k ↦ ∑ j : ZMod N, stdAddChar (-(j * k)) • Φ j := + rfl + +lemma invDFT_apply (Ψ : ZMod N → E) (k : ZMod N) : + 𝓕⁻ Ψ k = (N : ℂ)⁻¹ • ∑ j : ZMod N, stdAddChar (j * k) • Ψ j := by + simp only [dft, LinearEquiv.coe_symm_mk, auxDFT, mul_neg, neg_neg] + +lemma invDFT_def (Ψ : ZMod N → E) : + 𝓕⁻ Ψ = fun k ↦ (N : ℂ)⁻¹ • ∑ j : ZMod N, stdAddChar (j * k) • Ψ j := + funext <| invDFT_apply Ψ + +lemma invDFT_apply' (Ψ : ZMod N → E) (k : ZMod N) : 𝓕⁻ Ψ k = (N : ℂ)⁻¹ • 𝓕 Ψ (-k) := + rfl + +lemma invDFT_def' (Ψ : ZMod N → E) : 𝓕⁻ Ψ = fun k ↦ (N : ℂ)⁻¹ • 𝓕 Ψ (-k) := + rfl + +lemma dft_apply_zero (Φ : ZMod N → E) : 𝓕 Φ 0 = ∑ j, Φ j := by + simp only [dft_apply, mul_zero, neg_zero, map_zero_eq_one, one_smul] + +/-- +The discrete Fourier transform agrees with the general one (assuming the target space is a complete +normed space). +-/ +lemma dft_eq_fourier {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] [CompleteSpace E] + (Φ : ZMod N → E) (k : ZMod N) : + 𝓕 Φ k = Fourier.fourierIntegral toCircle Measure.count Φ k := by + simp only [dft_apply, stdAddChar_apply, Fourier.fourierIntegral_def, Circle.smul_def, + integral_countable' <| .of_finite .., Measure.count_singleton, ENNReal.one_toReal, one_smul, + tsum_fintype] + +end defs -open ZMod +section arith +/-! +## Compatibility with scalar multiplication + +These lemmas are more general than `LinearEquiv.map_mul` etc, since they allow any scalars that +commute with the `ℂ`-action, rather than just `ℂ` itself. +-/ + +lemma dft_const_smul {R : Type*} [DistribSMul R E] [SMulCommClass R ℂ E] (r : R) (Φ : ZMod N → E) : + 𝓕 (r • Φ) = r • 𝓕 Φ := by + simp only [Pi.smul_def, dft_def, smul_sum, smul_comm] + +lemma dft_smul_const {R : Type*} [Ring R] [Module ℂ R] [Module R E] [IsScalarTower ℂ R E] + (Φ : ZMod N → R) (e : E) : + 𝓕 (fun j ↦ Φ j • e) = fun k ↦ 𝓕 Φ k • e := by + simp only [dft_def, sum_smul, smul_assoc] + +lemma dft_const_mul {R : Type*} [Ring R] [Algebra ℂ R] (r : R) (Φ : ZMod N → R) : + 𝓕 (fun j ↦ r * Φ j) = fun k ↦ r * 𝓕 Φ k := + dft_const_smul r Φ + +lemma dft_mul_const {R : Type*} [Ring R] [Algebra ℂ R] (Φ : ZMod N → R) (r : R) : + 𝓕 (fun j ↦ Φ j * r) = fun k ↦ 𝓕 Φ k * r := + dft_smul_const Φ r + +end arith + +section inversion + +lemma dft_comp_neg (Φ : ZMod N → E) : 𝓕 (fun j ↦ Φ (-j)) = fun k ↦ 𝓕 Φ (-k) := + auxDFT_neg .. + +/-- Fourier inversion formula, discrete case. -/ +lemma dft_dft (Φ : ZMod N → E) : 𝓕 (𝓕 Φ) = fun j ↦ (N : ℂ) • Φ (-j) := + auxDFT_auxDFT .. + +end inversion + +lemma dft_comp_unitMul (Φ : ZMod N → E) (u : (ZMod N)ˣ) (k : ZMod N) : + 𝓕 (fun j ↦ Φ (u.val * j)) k = 𝓕 Φ (u⁻¹.val * k) := by + refine Fintype.sum_equiv u.mulLeft _ _ fun x ↦ ?_ + simp only [mul_comm u.val, u.mulLeft_apply, ← mul_assoc, u.mul_inv_cancel_right] + +end ZMod namespace DirichletCharacter @@ -53,10 +185,9 @@ variable {N : ℕ} [NeZero N] (χ : DirichletCharacter ℂ N) lemma fourierTransform_eq_gaussSum_mulShift (k : ZMod N) : 𝓕 χ k = gaussSum χ (stdAddChar.mulShift (-k)) := by - simp only [dft_def] + simp only [dft_apply, smul_eq_mul] congr 1 with j - rw [AddChar.mulShift_apply, mul_comm j, Submonoid.smul_def, smul_eq_mul, neg_mul, - stdAddChar_apply, mul_comm (χ _)] + rw [mulShift_apply, mul_comm j, neg_mul, stdAddChar_apply, mul_comm (χ _)] /-- For a primitive Dirichlet character `χ`, the Fourier transform of `χ` is a constant multiple of `χ⁻¹` (and the constant is essentially the Gauss sum). -/ diff --git a/Mathlib/Analysis/FunctionalSpaces/SobolevInequality.lean b/Mathlib/Analysis/FunctionalSpaces/SobolevInequality.lean index 786527166c2b3..6ed55ca9b6ddf 100644 --- a/Mathlib/Analysis/FunctionalSpaces/SobolevInequality.lean +++ b/Mathlib/Analysis/FunctionalSpaces/SobolevInequality.lean @@ -634,7 +634,7 @@ theorem eLpNorm_le_eLpNorm_fderiv_of_eq [FiniteDimensional ℝ F] (fderiv ℝ e (u x)).opNorm_comp_le (fderiv ℝ u x) _ = C₂ * ‖fderiv ℝ u x‖ := by simp_rw [e.fderiv, C₂, coe_nnnorm] calc eLpNorm u p' μ - = eLpNorm (e.symm ∘ v) p' μ := by simp_rw [v, Function.comp, e.symm_apply_apply] + = eLpNorm (e.symm ∘ v) p' μ := by simp_rw [v, Function.comp_def, e.symm_apply_apply] _ ≤ C₁ • eLpNorm v p' μ := by apply eLpNorm_le_nnreal_smul_eLpNorm_of_ae_le_mul exact Eventually.of_forall (fun x ↦ (e.symm : F' →L[ℝ] F).le_opNNNorm _) diff --git a/Mathlib/Analysis/Hofer.lean b/Mathlib/Analysis/Hofer.lean index b008d74901b49..3224c5efddfd7 100644 --- a/Mathlib/Analysis/Hofer.lean +++ b/Mathlib/Analysis/Hofer.lean @@ -28,7 +28,7 @@ theorem hofer {X : Type*} [MetricSpace X] [CompleteSpace X] (x : X) (ε : ℝ) ( by_contra H have reformulation : ∀ (x') (k : ℕ), ε * ϕ x ≤ ε / 2 ^ k * ϕ x' ↔ 2 ^ k * ϕ x ≤ ϕ x' := by intro x' k - rw [div_mul_eq_mul_div, le_div_iff, mul_assoc, mul_le_mul_left ε_pos, mul_comm] + rw [div_mul_eq_mul_div, le_div_iff₀, mul_assoc, mul_le_mul_left ε_pos, mul_comm] positivity -- Now let's specialize to `ε/2^k` replace H : ∀ k : ℕ, ∀ x', d x' x ≤ 2 * ε ∧ 2 ^ k * ϕ x ≤ ϕ x' → diff --git a/Mathlib/Analysis/InnerProductSpace/Adjoint.lean b/Mathlib/Analysis/InnerProductSpace/Adjoint.lean index c4a1bcd72f1b5..d70316a5027b3 100644 --- a/Mathlib/Analysis/InnerProductSpace/Adjoint.lean +++ b/Mathlib/Analysis/InnerProductSpace/Adjoint.lean @@ -564,7 +564,7 @@ lemma Matrix.toLin_conjTranspose (A : Matrix m n 𝕜) : orthonormal_iff_ite.mp v₁.orthonormal, orthonormal_iff_ite.mp v₂.orthonormal] /-- The matrix associated to the adjoint of a linear map corresponding to two orthonormal bases -is the conjugate tranpose of the matrix associated to the linear map. -/ +is the conjugate transpose of the matrix associated to the linear map. -/ lemma LinearMap.toMatrix_adjoint (f : E →ₗ[𝕜] F) : toMatrix v₂.toBasis v₁.toBasis (adjoint f) = (toMatrix v₁.toBasis v₂.toBasis f)ᴴ := toLin v₂.toBasis v₁.toBasis |>.injective <| by simp [toLin_conjTranspose] diff --git a/Mathlib/Analysis/InnerProductSpace/Basic.lean b/Mathlib/Analysis/InnerProductSpace/Basic.lean index 51f6fe6c16b82..f2d58902381c5 100644 --- a/Mathlib/Analysis/InnerProductSpace/Basic.lean +++ b/Mathlib/Analysis/InnerProductSpace/Basic.lean @@ -68,7 +68,7 @@ noncomputable section open RCLike Real Filter -open Topology ComplexConjugate +open Topology ComplexConjugate Finsupp open LinearMap (BilinForm) @@ -591,26 +591,26 @@ theorem inner_sum {ι : Type*} (s : Finset ι) (f : ι → E) (x : E) : map_sum (LinearMap.flip sesqFormOfInner x) _ _ /-- An inner product with a sum on the left, `Finsupp` version. -/ -theorem Finsupp.sum_inner {ι : Type*} (l : ι →₀ 𝕜) (v : ι → E) (x : E) : +protected theorem Finsupp.sum_inner {ι : Type*} (l : ι →₀ 𝕜) (v : ι → E) (x : E) : ⟪l.sum fun (i : ι) (a : 𝕜) => a • v i, x⟫ = l.sum fun (i : ι) (a : 𝕜) => conj a • ⟪v i, x⟫ := by - convert _root_.sum_inner (𝕜 := 𝕜) l.support (fun a => l a • v a) x + convert sum_inner (𝕜 := 𝕜) l.support (fun a => l a • v a) x simp only [inner_smul_left, Finsupp.sum, smul_eq_mul] /-- An inner product with a sum on the right, `Finsupp` version. -/ -theorem Finsupp.inner_sum {ι : Type*} (l : ι →₀ 𝕜) (v : ι → E) (x : E) : +protected theorem Finsupp.inner_sum {ι : Type*} (l : ι →₀ 𝕜) (v : ι → E) (x : E) : ⟪x, l.sum fun (i : ι) (a : 𝕜) => a • v i⟫ = l.sum fun (i : ι) (a : 𝕜) => a • ⟪x, v i⟫ := by - convert _root_.inner_sum (𝕜 := 𝕜) l.support (fun a => l a • v a) x + convert inner_sum (𝕜 := 𝕜) l.support (fun a => l a • v a) x simp only [inner_smul_right, Finsupp.sum, smul_eq_mul] -theorem DFinsupp.sum_inner {ι : Type*} [DecidableEq ι] {α : ι → Type*} +protected theorem DFinsupp.sum_inner {ι : Type*} [DecidableEq ι] {α : ι → Type*} [∀ i, AddZeroClass (α i)] [∀ (i) (x : α i), Decidable (x ≠ 0)] (f : ∀ i, α i → E) (l : Π₀ i, α i) (x : E) : ⟪l.sum f, x⟫ = l.sum fun i a => ⟪f i a, x⟫ := by - simp (config := { contextual := true }) only [DFinsupp.sum, _root_.sum_inner, smul_eq_mul] + simp (config := { contextual := true }) only [DFinsupp.sum, sum_inner, smul_eq_mul] -theorem DFinsupp.inner_sum {ι : Type*} [DecidableEq ι] {α : ι → Type*} +protected theorem DFinsupp.inner_sum {ι : Type*} [DecidableEq ι] {α : ι → Type*} [∀ i, AddZeroClass (α i)] [∀ (i) (x : α i), Decidable (x ≠ 0)] (f : ∀ i, α i → E) (l : Π₀ i, α i) (x : E) : ⟪x, l.sum f⟫ = l.sum fun i a => ⟪x, f i a⟫ := by - simp (config := { contextual := true }) only [DFinsupp.sum, _root_.inner_sum, smul_eq_mul] + simp (config := { contextual := true }) only [DFinsupp.sum, inner_sum, smul_eq_mul] @[simp] theorem inner_zero_left (x : E) : ⟪0, x⟫ = 0 := by @@ -634,7 +634,7 @@ theorem real_inner_self_nonneg {x : F} : 0 ≤ ⟪x, x⟫_ℝ := @[simp] theorem inner_self_ofReal_re (x : E) : (re ⟪x, x⟫ : 𝕜) = ⟪x, x⟫ := - ((RCLike.is_real_TFAE (⟪x, x⟫ : 𝕜)).out 2 3).2 (inner_self_im _) + ((RCLike.is_real_TFAE (⟪x, x⟫ : 𝕜)).out 2 3).2 (inner_self_im (𝕜 := 𝕜) x) theorem inner_self_eq_norm_sq_to_K (x : E) : ⟪x, x⟫ = (‖x‖ : 𝕜) ^ 2 := by rw [← inner_self_ofReal_re, ← norm_sq_eq_inner, ofReal_pow] @@ -829,9 +829,9 @@ theorem orthonormal_subtype_iff_ite [DecidableEq E] {s : Set E} : /-- The inner product of a linear combination of a set of orthonormal vectors with one of those vectors picks out the coefficient of that vector. -/ theorem Orthonormal.inner_right_finsupp {v : ι → E} (hv : Orthonormal 𝕜 v) (l : ι →₀ 𝕜) (i : ι) : - ⟪v i, Finsupp.total ι E 𝕜 v l⟫ = l i := by + ⟪v i, linearCombination 𝕜 v l⟫ = l i := by classical - simpa [Finsupp.total_apply, Finsupp.inner_sum, orthonormal_iff_ite.mp hv] using Eq.symm + simpa [linearCombination_apply, Finsupp.inner_sum, orthonormal_iff_ite.mp hv] using Eq.symm /-- The inner product of a linear combination of a set of orthonormal vectors with one of those vectors picks out the coefficient of that vector. -/ @@ -849,7 +849,7 @@ theorem Orthonormal.inner_right_fintype [Fintype ι] {v : ι → E} (hv : Orthon /-- The inner product of a linear combination of a set of orthonormal vectors with one of those vectors picks out the coefficient of that vector. -/ theorem Orthonormal.inner_left_finsupp {v : ι → E} (hv : Orthonormal 𝕜 v) (l : ι →₀ 𝕜) (i : ι) : - ⟪Finsupp.total ι E 𝕜 v l, v i⟫ = conj (l i) := by rw [← inner_conj_symm, hv.inner_right_finsupp] + ⟪linearCombination 𝕜 v l, v i⟫ = conj (l i) := by rw [← inner_conj_symm, hv.inner_right_finsupp] /-- The inner product of a linear combination of a set of orthonormal vectors with one of those vectors picks out the coefficient of that vector. -/ @@ -868,19 +868,20 @@ theorem Orthonormal.inner_left_fintype [Fintype ι] {v : ι → E} (hv : Orthono /-- The inner product of two linear combinations of a set of orthonormal vectors, expressed as a sum over the first `Finsupp`. -/ theorem Orthonormal.inner_finsupp_eq_sum_left {v : ι → E} (hv : Orthonormal 𝕜 v) (l₁ l₂ : ι →₀ 𝕜) : - ⟪Finsupp.total ι E 𝕜 v l₁, Finsupp.total ι E 𝕜 v l₂⟫ = l₁.sum fun i y => conj y * l₂ i := by - simp only [l₁.total_apply _, Finsupp.sum_inner, hv.inner_right_finsupp, smul_eq_mul] + ⟪linearCombination 𝕜 v l₁, linearCombination 𝕜 v l₂⟫ = l₁.sum fun i y => conj y * l₂ i := by + simp only [l₁.linearCombination_apply _, Finsupp.sum_inner, hv.inner_right_finsupp, smul_eq_mul] /-- The inner product of two linear combinations of a set of orthonormal vectors, expressed as a sum over the second `Finsupp`. -/ theorem Orthonormal.inner_finsupp_eq_sum_right {v : ι → E} (hv : Orthonormal 𝕜 v) (l₁ l₂ : ι →₀ 𝕜) : - ⟪Finsupp.total ι E 𝕜 v l₁, Finsupp.total ι E 𝕜 v l₂⟫ = l₂.sum fun i y => conj (l₁ i) * y := by - simp only [l₂.total_apply _, Finsupp.inner_sum, hv.inner_left_finsupp, mul_comm, smul_eq_mul] + ⟪linearCombination 𝕜 v l₁, linearCombination 𝕜 v l₂⟫ = l₂.sum fun i y => conj (l₁ i) * y := by + simp only [l₂.linearCombination_apply _, Finsupp.inner_sum, hv.inner_left_finsupp, mul_comm, + smul_eq_mul] /-- The inner product of two linear combinations of a set of orthonormal vectors, expressed as a sum. -/ -theorem Orthonormal.inner_sum {v : ι → E} (hv : Orthonormal 𝕜 v) (l₁ l₂ : ι → 𝕜) (s : Finset ι) : - ⟪∑ i ∈ s, l₁ i • v i, ∑ i ∈ s, l₂ i • v i⟫ = ∑ i ∈ s, conj (l₁ i) * l₂ i := by +protected theorem Orthonormal.inner_sum {v : ι → E} (hv : Orthonormal 𝕜 v) (l₁ l₂ : ι → 𝕜) + (s : Finset ι) : ⟪∑ i ∈ s, l₁ i • v i, ∑ i ∈ s, l₂ i • v i⟫ = ∑ i ∈ s, conj (l₁ i) * l₂ i := by simp_rw [sum_inner, inner_smul_left] refine Finset.sum_congr rfl fun i hi => ?_ rw [hv.inner_right_sum l₂ hi] @@ -900,7 +901,7 @@ theorem Orthonormal.linearIndependent {v : ι → E} (hv : Orthonormal 𝕜 v) : rw [linearIndependent_iff] intro l hl ext i - have key : ⟪v i, Finsupp.total ι E 𝕜 v l⟫ = ⟪v i, 0⟫ := by rw [hl] + have key : ⟪v i, Finsupp.linearCombination 𝕜 v l⟫ = ⟪v i, 0⟫ := by rw [hl] simpa only [hv.inner_right_finsupp, inner_zero_right] using key /-- A subfamily of an orthonormal family (i.e., a composition with an injective map) is an @@ -932,7 +933,7 @@ theorem Orthonormal.toSubtypeRange {v : ι → E} (hv : Orthonormal 𝕜 v) : set. -/ theorem Orthonormal.inner_finsupp_eq_zero {v : ι → E} (hv : Orthonormal 𝕜 v) {s : Set ι} {i : ι} (hi : i ∉ s) {l : ι →₀ 𝕜} (hl : l ∈ Finsupp.supported 𝕜 𝕜 s) : - ⟪Finsupp.total ι E 𝕜 v l, v i⟫ = 0 := by + ⟪Finsupp.linearCombination 𝕜 v l, v i⟫ = 0 := by rw [Finsupp.mem_supported'] at hl simp only [hv.inner_left_finsupp, hl i hi, map_zero] @@ -1321,7 +1322,8 @@ theorem Orthonormal.mapLinearIsometryEquiv {v : Basis ι 𝕜 E} (hv : Orthonorm def LinearMap.isometryOfOrthonormal (f : E →ₗ[𝕜] E') {v : Basis ι 𝕜 E} (hv : Orthonormal 𝕜 v) (hf : Orthonormal 𝕜 (f ∘ v)) : E →ₗᵢ[𝕜] E' := f.isometryOfInner fun x y => by - classical rw [← v.total_repr x, ← v.total_repr y, Finsupp.apply_total, Finsupp.apply_total, + classical rw [← v.linearCombination_repr x, ← v.linearCombination_repr y, + Finsupp.apply_linearCombination, Finsupp.apply_linearCombination, hv.inner_finsupp_eq_sum_left, hf.inner_finsupp_eq_sum_left] @[simp] @@ -1341,8 +1343,9 @@ def LinearEquiv.isometryOfOrthonormal (f : E ≃ₗ[𝕜] E') {v : Basis ι 𝕜 (hf : Orthonormal 𝕜 (f ∘ v)) : E ≃ₗᵢ[𝕜] E' := f.isometryOfInner fun x y => by rw [← LinearEquiv.coe_coe] at hf - classical rw [← v.total_repr x, ← v.total_repr y, ← LinearEquiv.coe_coe f, Finsupp.apply_total, - Finsupp.apply_total, hv.inner_finsupp_eq_sum_left, hf.inner_finsupp_eq_sum_left] + classical rw [← v.linearCombination_repr x, ← v.linearCombination_repr y, + ← LinearEquiv.coe_coe f, Finsupp.apply_linearCombination, + Finsupp.apply_linearCombination, hv.inner_finsupp_eq_sum_left, hf.inner_finsupp_eq_sum_left] @[simp] theorem LinearEquiv.coe_isometryOfOrthonormal (f : E ≃ₗ[𝕜] E') {v : Basis ι 𝕜 E} @@ -1414,8 +1417,8 @@ theorem norm_add_sq_eq_norm_sq_add_norm_sq_iff_real_inner_eq_zero (x y : F) : /-- Pythagorean theorem, if-and-if vector inner product form using square roots. -/ theorem norm_add_eq_sqrt_iff_real_inner_eq_zero {x y : F} : ‖x + y‖ = √(‖x‖ * ‖x‖ + ‖y‖ * ‖y‖) ↔ ⟪x, y⟫_ℝ = 0 := by - rw [← norm_add_sq_eq_norm_sq_add_norm_sq_iff_real_inner_eq_zero, eq_comm, - sqrt_eq_iff_mul_self_eq (add_nonneg (mul_self_nonneg _) (mul_self_nonneg _)) (norm_nonneg _)] + rw [← norm_add_sq_eq_norm_sq_add_norm_sq_iff_real_inner_eq_zero, eq_comm, sqrt_eq_iff_mul_self_eq, + eq_comm] <;> positivity /-- Pythagorean theorem, vector inner product form. -/ theorem norm_add_sq_eq_norm_sq_add_norm_sq_of_inner_eq_zero (x y : E) (h : ⟪x, y⟫ = 0) : @@ -1441,8 +1444,8 @@ theorem norm_sub_sq_eq_norm_sq_add_norm_sq_iff_real_inner_eq_zero (x y : F) : roots. -/ theorem norm_sub_eq_sqrt_iff_real_inner_eq_zero {x y : F} : ‖x - y‖ = √(‖x‖ * ‖x‖ + ‖y‖ * ‖y‖) ↔ ⟪x, y⟫_ℝ = 0 := by - rw [← norm_sub_sq_eq_norm_sq_add_norm_sq_iff_real_inner_eq_zero, eq_comm, - sqrt_eq_iff_mul_self_eq (add_nonneg (mul_self_nonneg _) (mul_self_nonneg _)) (norm_nonneg _)] + rw [← norm_sub_sq_eq_norm_sq_add_norm_sq_iff_real_inner_eq_zero, eq_comm, sqrt_eq_iff_mul_self_eq, + eq_comm] <;> positivity /-- Pythagorean theorem, subtracting vectors, vector inner product form. -/ @@ -1813,7 +1816,7 @@ theorem inner_sum_smul_sum_smul_of_sum_eq_zero {ι₁ : Type*} {s₁ : Finset ι variable (𝕜) /-- `innerSL` is an isometry. Note that the associated `LinearIsometry` is defined in -`InnerProductSpace.Dual` as `toDualMap`. -/ +`InnerProductSpace.Dual` as `toDualMap`. -/ @[simp] theorem innerSL_apply_norm (x : E) : ‖innerSL 𝕜 x‖ = ‖x‖ := by refine @@ -1880,7 +1883,7 @@ theorem Orthonormal.sum_inner_products_le {s : Finset ι} (hv : Orthonormal 𝕜 rw [← sub_nonneg, ← hbf] simp only [norm_nonneg, pow_nonneg] rw [@norm_sub_sq 𝕜, sub_add] - simp only [@InnerProductSpace.norm_sq_eq_inner 𝕜, _root_.inner_sum, _root_.sum_inner] + simp only [@InnerProductSpace.norm_sq_eq_inner 𝕜, inner_sum, sum_inner] simp only [inner_smul_right, two_mul, inner_smul_left, inner_conj_symm, ← mul_assoc, h₂, add_sub_cancel_right, sub_right_inj] simp only [map_sum, ← inner_conj_symm x, ← h₃] @@ -2036,12 +2039,12 @@ theorem OrthogonalFamily.inner_right_fintype [Fintype ι] (l : ∀ i, G i) (i : _ = ⟪v, l i⟫ := by simp only [Finset.sum_ite_eq, Finset.mem_univ, (V i).inner_map_map, if_true] -theorem OrthogonalFamily.inner_sum (l₁ l₂ : ∀ i, G i) (s : Finset ι) : +nonrec theorem OrthogonalFamily.inner_sum (l₁ l₂ : ∀ i, G i) (s : Finset ι) : ⟪∑ i ∈ s, V i (l₁ i), ∑ j ∈ s, V j (l₂ j)⟫ = ∑ i ∈ s, ⟪l₁ i, l₂ i⟫ := by classical calc ⟪∑ i ∈ s, V i (l₁ i), ∑ j ∈ s, V j (l₂ j)⟫ = ∑ j ∈ s, ∑ i ∈ s, ⟪V i (l₁ i), V j (l₂ j)⟫ := by - simp only [_root_.sum_inner, _root_.inner_sum] + simp only [sum_inner, inner_sum] _ = ∑ j ∈ s, ∑ i ∈ s, ite (i = j) ⟪V i (l₁ i), V j (l₂ j)⟫ 0 := by congr with i congr with j @@ -2413,3 +2416,5 @@ instance innerProductSpace : InnerProductSpace 𝕜 (Completion E) where end UniformSpace.Completion end UniformSpace.Completion + +set_option linter.style.longFile 2500 diff --git a/Mathlib/Analysis/InnerProductSpace/GramSchmidtOrtho.lean b/Mathlib/Analysis/InnerProductSpace/GramSchmidtOrtho.lean index dc8c71696a394..a3c9277c121f4 100644 --- a/Mathlib/Analysis/InnerProductSpace/GramSchmidtOrtho.lean +++ b/Mathlib/Analysis/InnerProductSpace/GramSchmidtOrtho.lean @@ -137,7 +137,7 @@ theorem gramSchmidt_mem_span (f : ι → E) : (Submodule.sum_mem _ fun k hk => ?_) let hkj : k < j := (Finset.mem_Iio.1 hk).trans_le hij exact smul_mem _ _ - (span_mono (image_subset f <| Iic_subset_Iic.2 hkj.le) <| gramSchmidt_mem_span _ le_rfl) + (span_mono (image_subset f <| Set.Iic_subset_Iic.2 hkj.le) <| gramSchmidt_mem_span _ le_rfl) termination_by j => j theorem span_gramSchmidt_Iic (f : ι → E) (c : ι) : diff --git a/Mathlib/Analysis/InnerProductSpace/JointEigenspace.lean b/Mathlib/Analysis/InnerProductSpace/JointEigenspace.lean new file mode 100644 index 0000000000000..868496a0b3462 --- /dev/null +++ b/Mathlib/Analysis/InnerProductSpace/JointEigenspace.lean @@ -0,0 +1,113 @@ +/- +Copyright (c) 2024 Jon Bannon. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Jon Bannon, Jack Cheverton, Samyak Dhar Tuladhar +-/ + +import Mathlib.Analysis.InnerProductSpace.Spectrum +import Mathlib.Analysis.InnerProductSpace.Projection +import Mathlib.Order.CompleteLattice +import Mathlib.LinearAlgebra.Eigenspace.Basic + +/-! # Joint eigenspaces of a commuting pair of symmetric operators + +This file collects various decomposition results for joint eigenspaces of a commuting pair +of symmetric operators on a finite-dimensional inner product space. + +# Main Result + +* `LinearMap.IsSymmetric.directSum_isInternal_of_commute` establishes that + if `{A B : E →ₗ[𝕜] E}`, then `IsSymmetric A`, `IsSymmetric B` and `A ∘ₗ B = B ∘ₗ A` imply that + `E` decomposes as an internal direct sum of the pairwise orthogonal spaces + `eigenspace B μ ⊓ eigenspace A ν` + +## TODO + +Develop a `Diagonalization` structure for linear maps and / or matrices which consists of a basis, +and a proof obligation that the basis vectors are eigenvectors. + +## Tags + +self-adjoint operator, simultaneous eigenspaces, joint eigenspaces + +-/ + +variable {𝕜 E : Type*} [RCLike 𝕜] +variable [NormedAddCommGroup E] [InnerProductSpace 𝕜 E] + +open Module.End + +namespace LinearMap + +namespace IsSymmetric + +section Pair + +variable {α : 𝕜} {A B : E →ₗ[𝕜] E} + +/--If a pair of operators commute, then the eigenspaces of one are invariant under the other.-/ +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, + 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 +`OrthogonalFamily`.-/ +theorem orthogonalFamily_eigenspace_inf_eigenspace (hA : A.IsSymmetric) (hB : B.IsSymmetric) : + OrthogonalFamily 𝕜 (fun (i : 𝕜 × 𝕜) => (eigenspace A i.2 ⊓ eigenspace B i.1 : Submodule 𝕜 E)) + (fun i => (eigenspace A i.2 ⊓ eigenspace B i.1).subtypeₗᵢ) := + OrthogonalFamily.of_pairwise fun i j hij v ⟨hv1 , hv2⟩ ↦ by + obtain (h₁ | h₂) : i.1 ≠ j.1 ∨ i.2 ≠ j.2 := by rwa [Ne.eq_def, Prod.ext_iff, not_and_or] at hij + all_goals intro w ⟨hw1, hw2⟩ + · exact hB.orthogonalFamily_eigenspaces.pairwise h₁ hv2 w hw2 + · exact hA.orthogonalFamily_eigenspaces.pairwise h₂ hv1 w hw1 + +open Submodule in + +/-- The intersection of eigenspaces of commuting selfadjoint operators is equal to the eigenspace of +one operator restricted to the eigenspace of the other, which is an invariant subspace because the +operators commute. -/ +theorem eigenspace_inf_eigenspace + (hAB : A ∘ₗ B = B ∘ₗ A) (γ : 𝕜) : + eigenspace A α ⊓ eigenspace B γ = map (Submodule.subtype (eigenspace A α)) + (eigenspace (B.restrict (eigenspace_invariant_of_commute hAB α)) γ) := + (eigenspace A α).inf_genEigenspace _ _ (k := 1) + +variable [FiniteDimensional 𝕜 E] + +/-- If A and B are commuting symmetric operators on a finite dimensional inner product space +then the eigenspaces of the restriction of B to any eigenspace of A exhaust that eigenspace.-/ +theorem iSup_eigenspace_inf_eigenspace (hB : B.IsSymmetric) + (hAB : A ∘ₗ B = B ∘ₗ A): + (⨆ γ, eigenspace A α ⊓ eigenspace B γ) = eigenspace A α := by + conv_rhs => rw [← (eigenspace A α).map_subtype_top] + simp only [eigenspace_inf_eigenspace hAB, ← Submodule.map_iSup] + congr 1 + rw [← Submodule.orthogonal_eq_bot_iff] + exact orthogonalComplement_iSup_eigenspaces_eq_bot <| + hB.restrict_invariant <| eigenspace_invariant_of_commute hAB α + +/-- If A and B are commuting symmetric operators acting on a finite dimensional inner product space, +then the simultaneous eigenspaces of A and B exhaust the space. -/ +theorem iSup_iSup_eigenspace_inf_eigenspace_eq_top (hA : A.IsSymmetric) (hB : B.IsSymmetric) + (hAB : A ∘ₗ B = B ∘ₗ A) : + (⨆ α, ⨆ γ, eigenspace A α ⊓ eigenspace B γ) = ⊤ := by + simpa [iSup_eigenspace_inf_eigenspace hB hAB] using + Submodule.orthogonal_eq_bot_iff.mp <| hA.orthogonalComplement_iSup_eigenspaces_eq_bot + +/-- Given a commuting pair of symmetric linear operators on a finite dimensional inner product +space, the space decomposes as an internal direct sum of simultaneous eigenspaces of these +operators. -/ +theorem directSum_isInteral_of_commute (hA : A.IsSymmetric) (hB : B.IsSymmetric) + (hAB : A ∘ₗ B = B ∘ₗ A) : + DirectSum.IsInternal (fun (i : 𝕜 × 𝕜) ↦ (eigenspace A i.2 ⊓ eigenspace B i.1)):= by + apply (orthogonalFamily_eigenspace_inf_eigenspace hA hB).isInternal_iff.mpr + rw [Submodule.orthogonal_eq_bot_iff, iSup_prod, iSup_comm] + exact iSup_iSup_eigenspace_inf_eigenspace_eq_top hA hB hAB + +end Pair + +end IsSymmetric + +end LinearMap diff --git a/Mathlib/Analysis/InnerProductSpace/LaxMilgram.lean b/Mathlib/Analysis/InnerProductSpace/LaxMilgram.lean index 4cc1814eab7a9..7ac440395d2e8 100644 --- a/Mathlib/Analysis/InnerProductSpace/LaxMilgram.lean +++ b/Mathlib/Analysis/InnerProductSpace/LaxMilgram.lean @@ -44,7 +44,7 @@ namespace IsCoercive variable {V : Type u} [NormedAddCommGroup V] [InnerProductSpace ℝ V] [CompleteSpace V] variable {B : V →L[ℝ] V →L[ℝ] ℝ} -local postfix:1024 "♯" => @continuousLinearMapOfBilin ℝ V _ _ _ _ +local postfix:1024 "♯" => continuousLinearMapOfBilin (𝕜 := ℝ) theorem bounded_below (coercive : IsCoercive B) : ∃ C, 0 < C ∧ ∀ v, C * ‖v‖ ≤ ‖B♯ v‖ := by rcases coercive with ⟨C, C_ge_0, coercivity⟩ diff --git a/Mathlib/Analysis/InnerProductSpace/PiL2.lean b/Mathlib/Analysis/InnerProductSpace/PiL2.lean index 4629fbeeaa6c4..b157563aab735 100644 --- a/Mathlib/Analysis/InnerProductSpace/PiL2.lean +++ b/Mathlib/Analysis/InnerProductSpace/PiL2.lean @@ -136,7 +136,7 @@ theorem EuclideanSpace.sphere_zero_eq {n : Type*} [Fintype n] (r : ℝ) (hr : 0 ext x have : (0 : ℝ) ≤ ∑ i, x i ^ 2 := Finset.sum_nonneg fun _ _ => sq_nonneg _ simp_rw [mem_setOf, mem_sphere_zero_iff_norm, norm_eq, norm_eq_abs, sq_abs, - Real.sqrt_eq_iff_sq_eq this hr, eq_comm] + Real.sqrt_eq_iff_eq_sq this hr] section diff --git a/Mathlib/Analysis/InnerProductSpace/Positive.lean b/Mathlib/Analysis/InnerProductSpace/Positive.lean index c874c7b049ac5..d3c5fef5c6c27 100644 --- a/Mathlib/Analysis/InnerProductSpace/Positive.lean +++ b/Mathlib/Analysis/InnerProductSpace/Positive.lean @@ -99,6 +99,31 @@ theorem IsPositive.orthogonalProjection_comp {T : E →L[𝕜] E} (hT : T.IsPosi have := hT.conj_adjoint (orthogonalProjection U : E →L[𝕜] U) rwa [U.adjoint_orthogonalProjection] at this +open scoped NNReal + +lemma antilipschitz_of_forall_le_inner_map {H : Type*} [NormedAddCommGroup H] + [InnerProductSpace 𝕜 H] (f : H →L[𝕜] H) {c : ℝ≥0} (hc : 0 < c) + (h : ∀ x, ‖x‖ ^ 2 * c ≤ ‖⟪f x, x⟫_𝕜‖) : AntilipschitzWith c⁻¹ f := by + refine f.antilipschitz_of_bound (K := c⁻¹) fun x ↦ ?_ + rw [NNReal.coe_inv, inv_mul_eq_div, le_div_iff₀ (by exact_mod_cast hc)] + simp_rw [sq, mul_assoc] at h + by_cases hx0 : x = 0 + · simp [hx0] + · apply (map_le_map_iff <| OrderIso.mulLeft₀ ‖x‖ (norm_pos_iff'.mpr hx0)).mp + exact (h x).trans <| (norm_inner_le_norm _ _).trans <| (mul_comm _ _).le + +lemma isUnit_of_forall_le_norm_inner_map (f : E →L[𝕜] E) {c : ℝ≥0} (hc : 0 < c) + (h : ∀ x, ‖x‖ ^ 2 * c ≤ ‖⟪f x, x⟫_𝕜‖) : IsUnit f := by + rw [isUnit_iff_bijective, bijective_iff_dense_range_and_antilipschitz] + have h_anti : AntilipschitzWith c⁻¹ f := antilipschitz_of_forall_le_inner_map f hc h + refine ⟨?_, ⟨_, h_anti⟩⟩ + have _inst := h_anti.completeSpace_range_clm + rw [Submodule.topologicalClosure_eq_top_iff, Submodule.eq_bot_iff] + intro x hx + have : ‖x‖ ^ 2 * c = 0 := le_antisymm (by simpa only [hx (f x) ⟨x, rfl⟩, norm_zero] using h x) + (by positivity) + aesop + section Complex variable {E' : Type*} [NormedAddCommGroup E'] [InnerProductSpace ℂ E'] [CompleteSpace E'] diff --git a/Mathlib/Analysis/InnerProductSpace/Projection.lean b/Mathlib/Analysis/InnerProductSpace/Projection.lean index 16736b2f40a3e..3adbca1522567 100644 --- a/Mathlib/Analysis/InnerProductSpace/Projection.lean +++ b/Mathlib/Analysis/InnerProductSpace/Projection.lean @@ -46,7 +46,7 @@ open RCLike Real Filter open LinearMap (ker range) -open Topology +open Topology Finsupp variable {𝕜 E F : Type*} [RCLike 𝕜] variable [NormedAddCommGroup E] [NormedAddCommGroup F] @@ -332,7 +332,7 @@ theorem norm_eq_iInf_iff_inner_eq_zero {u : E} {v : E} (hv : v ∈ K) : · intro H have A : ∀ w ∈ K, re ⟪u - v, w⟫ = 0 := (norm_eq_iInf_iff_real_inner_eq_zero K' hv).1 H intro w hw - apply ext + apply RCLike.ext · simp [A w hw] · symm calc @@ -347,7 +347,7 @@ theorem norm_eq_iInf_iff_inner_eq_zero {u : E} {v : E} (hv : v ∈ K) : exact zero_re' exact (norm_eq_iInf_iff_real_inner_eq_zero K' hv).2 this -/-- A subspace `K : Submodule 𝕜 E` has an orthogonal projection if evey vector `v : E` admits an +/-- A subspace `K : Submodule 𝕜 E` has an orthogonal projection if every vector `v : E` admits an orthogonal projection to `K`. -/ class HasOrthogonalProjection (K : Submodule 𝕜 E) : Prop where exists_orthogonal (v : E) : ∃ w ∈ K, v - w ∈ Kᗮ @@ -471,13 +471,13 @@ theorem orthogonalProjectionFn_eq (v : E) : orthogonalProjectionFn K v = (orthogonalProjection K v : E) := rfl -/-- The characterization of the orthogonal projection. -/ +/-- The characterization of the orthogonal projection. -/ @[simp] theorem orthogonalProjection_inner_eq_zero (v : E) : ∀ w ∈ K, ⟪v - orthogonalProjection K v, w⟫ = 0 := orthogonalProjectionFn_inner_eq_zero v -/-- The difference of `v` from its orthogonal projection onto `K` is in `Kᗮ`. -/ +/-- The difference of `v` from its orthogonal projection onto `K` is in `Kᗮ`. -/ @[simp] theorem sub_orthogonalProjection_mem_orthogonal (v : E) : v - orthogonalProjection K v ∈ Kᗮ := by intro w hw @@ -780,7 +780,7 @@ is the topological closure of `K`. Note that the completeness assumption is necessary. Let `E` be the space `ℕ →₀ ℝ` with inner space structure inherited from `PiLp 2 (fun _ : ℕ ↦ ℝ)`. Let `K` be the subspace of sequences with the sum -of all elements equal to zero. Then `Kᗮ = ⊥`, `Kᗮᗮ = ⊤`. -/ +of all elements equal to zero. Then `Kᗮ = ⊥`, `Kᗮᗮ = ⊤`. -/ theorem Submodule.orthogonal_orthogonal_eq_closure [CompleteSpace E] : Kᗮᗮ = K.topologicalClosure := by refine le_antisymm ?_ ?_ @@ -1329,8 +1329,8 @@ theorem maximal_orthonormal_iff_orthogonalComplement_eq_bot (hv : Orthonormal intro hxv y hy have hxv' : (⟨x, hxu⟩ : u) ∉ ((↑) ⁻¹' v : Set u) := by simp [huv, hxv] obtain ⟨l, hl, rfl⟩ : - ∃ l ∈ Finsupp.supported 𝕜 𝕜 ((↑) ⁻¹' v : Set u), (Finsupp.total (↥u) E 𝕜 (↑)) l = y := by - rw [← Finsupp.mem_span_image_iff_total] + ∃ l ∈ supported 𝕜 𝕜 ((↑) ⁻¹' v : Set u), (linearCombination 𝕜 ((↑) : u → E)) l = y := by + rw [← Finsupp.mem_span_image_iff_linearCombination] simp [huv, inter_eq_self_of_subset_right, hy] exact hu.inner_finsupp_eq_zero hxv' hl diff --git a/Mathlib/Analysis/InnerProductSpace/StarOrder.lean b/Mathlib/Analysis/InnerProductSpace/StarOrder.lean new file mode 100644 index 0000000000000..2dc91976a43c2 --- /dev/null +++ b/Mathlib/Analysis/InnerProductSpace/StarOrder.lean @@ -0,0 +1,76 @@ +/- +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.Analysis.InnerProductSpace.Positive +import Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Instances + +/-! +# Continuous linear maps on a Hilbert space are a `StarOrderedRing` + +In this file we show that the continuous linear maps on a complex Hilbert space form a +`StarOrderedRing`. Note that they are already equipped with the Loewner partial order. We also +prove that, with respect to this partial order, a map is positive if every element of the +real spectrum is nonnegative. Consequently, when `H` is a Hilbert space, then `H →L[ℂ] H` is +equipped with all the usual instances of the continuous functional calculus. + + -/ + +namespace ContinuousLinearMap + +open RCLike +open scoped NNReal + +variable {𝕜 H : Type*} [RCLike 𝕜] [NormedAddCommGroup H] [InnerProductSpace 𝕜 H] [CompleteSpace H] +variable [Algebra ℝ (H →L[𝕜] H)] [IsScalarTower ℝ 𝕜 (H →L[𝕜] H)] + +lemma IsPositive.spectrumRestricts {f : H →L[𝕜] H} (hf : f.IsPositive) : + SpectrumRestricts f ContinuousMap.realToNNReal := by + rw [SpectrumRestricts.nnreal_iff] + intro c hc + contrapose! hc + rw [spectrum.not_mem_iff, IsUnit.sub_iff, sub_eq_add_neg, ← map_neg] + rw [← neg_pos] at hc + set c := -c + exact isUnit_of_forall_le_norm_inner_map _ (c := ⟨c, hc.le⟩) hc fun x ↦ calc + ‖x‖ ^ 2 * c = re ⟪algebraMap ℝ (H →L[𝕜] H) c x, x⟫_𝕜 := by + rw [Algebra.algebraMap_eq_smul_one, ← algebraMap_smul 𝕜 c (1 : (H →L[𝕜] H)), coe_smul', + Pi.smul_apply, one_apply, inner_smul_left, RCLike.algebraMap_eq_ofReal, conj_ofReal, + re_ofReal_mul, inner_self_eq_norm_sq, mul_comm] + _ ≤ re ⟪(f + (algebraMap ℝ (H →L[𝕜] H)) c) x, x⟫_𝕜 := by + simpa only [add_apply, inner_add_left, map_add, le_add_iff_nonneg_left] + using hf.inner_nonneg_left x + _ ≤ ‖⟪(f + (algebraMap ℝ (H →L[𝕜] H)) c) x, x⟫_𝕜‖ := RCLike.re_le_norm _ + +instance : NonnegSpectrumClass ℝ (H →L[𝕜] H) where + quasispectrum_nonneg_of_nonneg f hf := + QuasispectrumRestricts.nnreal_iff.mp <| sub_zero f ▸ hf.spectrumRestricts + +/-- Because this takes `ContinuousFunctionalCalculus ℝ IsSelfAdjoint` as an argument, and for +the moment we only have this for `𝕜 := ℂ`, this is not registered as an instance. -/ +lemma instStarOrderedRingRCLike + [ContinuousFunctionalCalculus ℝ (IsSelfAdjoint : (H →L[𝕜] H) → Prop)] : + StarOrderedRing (H →L[𝕜] H) where + le_iff f g := by + constructor + · intro h + rw [le_def] at h + obtain ⟨p, hp₁, -, hp₃⟩ := + CFC.exists_sqrt_of_isSelfAdjoint_of_spectrumRestricts h.1 h.spectrumRestricts + refine ⟨p ^ 2, ?_, by symm; rwa [add_comm, ← eq_sub_iff_add_eq]⟩ + exact AddSubmonoid.subset_closure ⟨p, by simp only [hp₁.star_eq, sq]⟩ + · rintro ⟨p, hp, rfl⟩ + rw [le_def, add_sub_cancel_left] + induction hp using AddSubmonoid.closure_induction' with + | mem _ hf => + obtain ⟨f, rfl⟩ := hf + simpa using ContinuousLinearMap.IsPositive.adjoint_conj isPositive_one f + | one => exact isPositive_zero + | mul f _ g _ hf hg => exact hf.add hg + +instance instStarOrderedRing {H : Type*} [NormedAddCommGroup H] + [InnerProductSpace ℂ H] [CompleteSpace H] : StarOrderedRing (H →L[ℂ] H) := + instStarOrderedRingRCLike + +end ContinuousLinearMap diff --git a/Mathlib/Analysis/InnerProductSpace/l2Space.lean b/Mathlib/Analysis/InnerProductSpace/l2Space.lean index 4b30cfc401477..9eb925f593b03 100644 --- a/Mathlib/Analysis/InnerProductSpace/l2Space.lean +++ b/Mathlib/Analysis/InnerProductSpace/l2Space.lean @@ -187,7 +187,7 @@ protected theorem summable_of_lp (f : lp G 2) : /-- A mutually orthogonal family of subspaces of `E` induce a linear isometry from `lp 2` of the subspaces into `E`. -/ -protected def linearIsometry : lp G 2 →ₗᵢ[𝕜] E where +protected def linearIsometry (hV : OrthogonalFamily 𝕜 G V) : lp G 2 →ₗᵢ[𝕜] E where toFun f := ∑' i, V i (f i) map_add' f g := by simp only [tsum_add (hV.summable_of_lp f) (hV.summable_of_lp g), lp.coeFn_add, Pi.add_apply, diff --git a/Mathlib/Analysis/LocallyConvex/BalancedCoreHull.lean b/Mathlib/Analysis/LocallyConvex/BalancedCoreHull.lean index c5cb5452393dd..5667478982a21 100644 --- a/Mathlib/Analysis/LocallyConvex/BalancedCoreHull.lean +++ b/Mathlib/Analysis/LocallyConvex/BalancedCoreHull.lean @@ -139,7 +139,7 @@ end SeminormedRing section NormedField -variable [NormedField 𝕜] [AddCommGroup E] [Module 𝕜 E] {s t : Set E} +variable [NormedDivisionRing 𝕜] [AddCommGroup E] [Module 𝕜 E] {s t : Set E} @[simp] theorem balancedCoreAux_empty : balancedCoreAux 𝕜 (∅ : Set E) = ∅ := by @@ -181,9 +181,9 @@ theorem balancedCore_eq_iInter (hs : (0 : E) ∈ s) : theorem subset_balancedCore (ht : (0 : E) ∈ t) (hst : ∀ a : 𝕜, ‖a‖ ≤ 1 → a • s ⊆ t) : s ⊆ balancedCore 𝕜 t := by rw [balancedCore_eq_iInter ht] - refine subset_iInter₂ fun a ha => ?_ - rw [← smul_inv_smul₀ (norm_pos_iff.mp <| zero_lt_one.trans_le ha) s] - refine smul_set_mono (hst _ ?_) + refine subset_iInter₂ fun a ha ↦ ?_ + 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 @@ -196,7 +196,7 @@ end balancedHull section Topology -variable [NontriviallyNormedField 𝕜] [AddCommGroup E] [Module 𝕜 E] [TopologicalSpace E] +variable [NormedDivisionRing 𝕜] [AddCommGroup E] [Module 𝕜 E] [TopologicalSpace E] [ContinuousSMul 𝕜 E] {U : Set E} protected theorem IsClosed.balancedCore (hU : IsClosed U) : IsClosed (balancedCore 𝕜 U) := by @@ -213,6 +213,9 @@ protected theorem IsClosed.balancedCore (hU : IsClosed U) : IsClosed (balancedCo rw [this] exact isClosed_empty +-- We don't have a `NontriviallyNormedDivisionRing`, so we use a `NeBot` assumption instead +variable [NeBot (𝓝[≠] (0 : 𝕜))] + theorem balancedCore_mem_nhds_zero (hU : U ∈ 𝓝 (0 : E)) : balancedCore 𝕜 U ∈ 𝓝 (0 : E) := by -- Getting neighborhoods of the origin for `0 : 𝕜` and `0 : E` obtain ⟨r, V, hr, hV, hrVU⟩ : ∃ (r : ℝ) (V : Set E), @@ -221,8 +224,9 @@ theorem balancedCore_mem_nhds_zero (hU : U ∈ 𝓝 (0 : E)) : balancedCore 𝕜 continuous_smul.tendsto' (0, 0) _ (smul_zero _) simpa only [← Prod.exists', ← Prod.forall', ← and_imp, ← and_assoc, exists_prop] using h.basis_left (NormedAddCommGroup.nhds_zero_basis_norm_lt.prod_nhds (𝓝 _).basis_sets) U hU - rcases NormedField.exists_norm_lt 𝕜 hr with ⟨y, hy₀, hyr⟩ - rw [norm_pos_iff] at hy₀ + obtain ⟨y, hyr, hy₀⟩ : ∃ y : 𝕜, ‖y‖ < r ∧ y ≠ 0 := + Filter.nonempty_of_mem <| + (nhdsWithin_hasBasis NormedAddCommGroup.nhds_zero_basis_norm_lt {0}ᶜ).mem_of_mem hr have : y • V ∈ 𝓝 (0 : E) := (set_smul_mem_nhds_zero_iff hy₀).mpr hV -- It remains to show that `y • V ⊆ balancedCore 𝕜 U` refine Filter.mem_of_superset this (subset_balancedCore (mem_of_mem_nhds hU) fun a ha => ?_) diff --git a/Mathlib/Analysis/LocallyConvex/Barrelled.lean b/Mathlib/Analysis/LocallyConvex/Barrelled.lean index 18409cff2a2f8..f01f4a9bb0e81 100644 --- a/Mathlib/Analysis/LocallyConvex/Barrelled.lean +++ b/Mathlib/Analysis/LocallyConvex/Barrelled.lean @@ -179,7 +179,8 @@ is a *continuous* linear map as well. This actually works for any *countably generated* filter instead of `atTop : Filter ℕ`, but the proof ultimately goes back to sequences. -/ -protected def continuousLinearMapOfTendsto [T2Space F] {l : Filter α} [l.IsCountablyGenerated] +protected def continuousLinearMapOfTendsto (hq : WithSeminorms q) + [T2Space F] {l : Filter α} [l.IsCountablyGenerated] [l.NeBot] (g : α → E →SL[σ₁₂] F) {f : E → F} (h : Tendsto (fun n x ↦ g n x) l (𝓝 f)) : E →SL[σ₁₂] F where toLinearMap := linearMapOfTendsto _ _ h diff --git a/Mathlib/Analysis/LocallyConvex/Basic.lean b/Mathlib/Analysis/LocallyConvex/Basic.lean index c5bf0dfa6a4e3..03bfae8efd21d 100644 --- a/Mathlib/Analysis/LocallyConvex/Basic.lean +++ b/Mathlib/Analysis/LocallyConvex/Basic.lean @@ -190,11 +190,11 @@ theorem Balanced.smul_mem_mono [SMulCommClass 𝕝 𝕜 E] (hs : Balanced 𝕝 s rcases eq_or_ne a 0 with rfl | ha₀ · simp_all · calc - b • x = (a⁻¹ • b) • a • x := by rw [smul_comm, smul_assoc, smul_inv_smul₀ ha₀] - _ ∈ s := by + (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 _) + (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 rw [← @norm_one 𝕜] at ha; simpa using hA.smul_mono ha diff --git a/Mathlib/Analysis/LocallyConvex/Bounded.lean b/Mathlib/Analysis/LocallyConvex/Bounded.lean index 66eed51d7bf1e..e1d8921b60a53 100644 --- a/Mathlib/Analysis/LocallyConvex/Bounded.lean +++ b/Mathlib/Analysis/LocallyConvex/Bounded.lean @@ -180,7 +180,7 @@ lemma isVonNBounded_pi_iff {𝕜 ι : Type*} {E : ι → Type*} [NormedDivisionR [∀ i, AddCommGroup (E i)] [∀ i, Module 𝕜 (E i)] [∀ i, TopologicalSpace (E i)] {S : Set (∀ i, E i)} : IsVonNBounded 𝕜 S ↔ ∀ i, IsVonNBounded 𝕜 (eval i '' S) := by simp_rw [isVonNBounded_iff_tendsto_smallSets_nhds, nhds_pi, Filter.pi, smallSets_iInf, - smallSets_comap_eq_comap_image, tendsto_iInf, tendsto_comap_iff, Function.comp, + smallSets_comap_eq_comap_image, tendsto_iInf, tendsto_comap_iff, Function.comp_def, ← image_smul, image_image, eval, Pi.smul_apply, Pi.zero_apply] section Image diff --git a/Mathlib/Analysis/LocallyConvex/Polar.lean b/Mathlib/Analysis/LocallyConvex/Polar.lean index 3dda893c0ca9e..e0235090926dc 100644 --- a/Mathlib/Analysis/LocallyConvex/Polar.lean +++ b/Mathlib/Analysis/LocallyConvex/Polar.lean @@ -91,10 +91,15 @@ theorem polar_empty : B.polar ∅ = Set.univ := B.polar_gc.l_bot @[simp] +theorem polar_singleton {a : E} : B.polar {a} = { y | ‖B a y‖ ≤ 1 } := le_antisymm + (fun _ hy => hy _ rfl) + (fun y hy => (polar_mem_iff _ _ _).mp (fun _ hb => by rw [Set.mem_singleton_iff.mp hb]; exact hy)) + +theorem mem_polar_singleton {x : E} (y : F) : y ∈ B.polar {x} ↔ ‖B x y‖ ≤ 1 := by + simp only [polar_singleton, Set.mem_setOf_eq] + theorem polar_zero : B.polar ({0} : Set E) = Set.univ := by - refine Set.eq_univ_iff_forall.mpr fun y x hx => ?_ - rw [Set.mem_singleton_iff.mp hx, map_zero, LinearMap.zero_apply, norm_zero] - exact zero_le_one + simp only [polar_singleton, map_zero, zero_apply, norm_zero, zero_le_one, Set.setOf_true] theorem subset_bipolar (s : Set E) : s ⊆ B.flip.polar (B.polar s) := fun x hx y hy => by rw [B.flip_apply] @@ -111,6 +116,13 @@ theorem polar_weak_closed (s : Set E) : IsClosed[WeakBilin.instTopologicalSpace refine isClosed_iInter fun x => isClosed_iInter fun _ => ?_ exact isClosed_le (WeakBilin.eval_continuous B.flip x).norm continuous_const +theorem sInter_polar_finite_subset_eq_polar (s : Set E) : + ⋂₀ (B.polar '' { F | F.Finite ∧ F ⊆ s }) = B.polar s := by + ext x + simp only [Set.sInter_image, Set.mem_setOf_eq, Set.mem_iInter, and_imp] + refine ⟨fun hx a ha ↦ ?_, fun hx F _ hF₂ => polar_antitone _ hF₂ hx⟩ + simpa [mem_polar_singleton] using hx _ (Set.finite_singleton a) (Set.singleton_subset_iff.mpr ha) + end NormedRing section NontriviallyNormedField @@ -140,8 +152,8 @@ theorem polar_subMulAction {S : Type*} [SetLike S E] [SMulMemClass S 𝕜 E] (m · intro hy x hx obtain ⟨r, hr⟩ := NormedField.exists_lt_norm 𝕜 ‖B x y‖⁻¹ contrapose! hr - rw [← one_div, le_div_iff (norm_pos_iff.2 hr)] - simpa using hy _ (SMulMemClass.smul_mem r hx) + rw [← one_div, le_div_iff₀ (norm_pos_iff.2 hr)] + simpa using hy _ (SMulMemClass.smul_mem r hx) · intro h x hx simp [h x hx] diff --git a/Mathlib/Analysis/LocallyConvex/WeakDual.lean b/Mathlib/Analysis/LocallyConvex/WeakDual.lean index ff5b801a83d03..455453490b735 100644 --- a/Mathlib/Analysis/LocallyConvex/WeakDual.lean +++ b/Mathlib/Analysis/LocallyConvex/WeakDual.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Moritz Doll -/ import Mathlib.Topology.Algebra.Module.WeakDual -import Mathlib.Analysis.Normed.Field.Basic +import Mathlib.Analysis.Normed.Field.Lemmas import Mathlib.Analysis.LocallyConvex.WithSeminorms /-! diff --git a/Mathlib/Analysis/LocallyConvex/WithSeminorms.lean b/Mathlib/Analysis/LocallyConvex/WithSeminorms.lean index dc3db6a84bb37..c562e61f2eae3 100644 --- a/Mathlib/Analysis/LocallyConvex/WithSeminorms.lean +++ b/Mathlib/Analysis/LocallyConvex/WithSeminorms.lean @@ -766,7 +766,7 @@ lemma bound_of_continuous_normedSpace (q : Seminorm 𝕜 F) exact le_of_eq (map_eq_zero_of_norm_zero q hq hx) · refine (normSeminorm 𝕜 F).bound_of_shell q ε_pos hc (fun x hle hlt ↦ ?_) hx refine (le_of_lt <| show q x < _ from hε hlt).trans ?_ - rwa [← div_le_iff' this, one_div_div] + rwa [← div_le_iff₀' this, one_div_div] /-- Let `E` be a topological vector space (over a `NontriviallyNormedField`) whose topology is generated by some family of seminorms `p`, and let `q` be a seminorm on `E`. If `q` is continuous, diff --git a/Mathlib/Analysis/MeanInequalities.lean b/Mathlib/Analysis/MeanInequalities.lean index 521077e3726ed..6f0c79f037af0 100644 --- a/Mathlib/Analysis/MeanInequalities.lean +++ b/Mathlib/Analysis/MeanInequalities.lean @@ -330,7 +330,7 @@ end Real namespace NNReal /-- **Young's inequality**, `ℝ≥0` version. We use `{p q : ℝ≥0}` in order to avoid constructing -witnesses of `0 ≤ p` and `0 ≤ q` for the denominators. -/ +witnesses of `0 ≤ p` and `0 ≤ q` for the denominators. -/ theorem young_inequality (a b : ℝ≥0) {p q : ℝ≥0} (hpq : p.IsConjExponent q) : a * b ≤ a ^ (p : ℝ) / p + b ^ (q : ℝ) / q := Real.young_inequality_of_nonneg a.coe_nonneg b.coe_nonneg hpq.coe @@ -373,17 +373,15 @@ namespace NNReal private theorem inner_le_Lp_mul_Lp_of_norm_le_one (f g : ι → ℝ≥0) {p q : ℝ} (hpq : p.IsConjExponent q) (hf : ∑ i ∈ s, f i ^ p ≤ 1) (hg : ∑ i ∈ s, g i ^ q ≤ 1) : ∑ i ∈ s, f i * g i ≤ 1 := by - have hp_ne_zero : Real.toNNReal p ≠ 0 := (zero_lt_one.trans hpq.toNNReal.one_lt).ne.symm - have hq_ne_zero : Real.toNNReal q ≠ 0 := (zero_lt_one.trans hpq.toNNReal.symm.one_lt).ne.symm + have hp : 0 < p.toNNReal := zero_lt_one.trans hpq.toNNReal.one_lt + have hq : 0 < q.toNNReal := zero_lt_one.trans hpq.toNNReal.symm.one_lt calc ∑ i ∈ s, f i * g i ≤ ∑ i ∈ s, (f i ^ p / Real.toNNReal p + g i ^ q / Real.toNNReal q) := Finset.sum_le_sum fun i _ => young_inequality_real (f i) (g i) hpq _ = (∑ i ∈ s, f i ^ p) / Real.toNNReal p + (∑ i ∈ s, g i ^ q) / Real.toNNReal q := by rw [sum_add_distrib, sum_div, sum_div] _ ≤ 1 / Real.toNNReal p + 1 / Real.toNNReal q := by - refine add_le_add ?_ ?_ - · rwa [div_le_iff hp_ne_zero, div_mul_cancel₀ _ hp_ne_zero] - · rwa [div_le_iff hq_ne_zero, div_mul_cancel₀ _ hq_ne_zero] + refine add_le_add ?_ ?_ <;> rwa [div_le_iff₀, div_mul_cancel₀] <;> positivity _ = 1 := by simp_rw [one_div, hpq.toNNReal.inv_add_inv_conj] private theorem inner_le_Lp_mul_Lp_of_norm_eq_zero (f g : ι → ℝ≥0) {p q : ℝ} @@ -401,31 +399,28 @@ private theorem inner_le_Lp_mul_Lp_of_norm_eq_zero (f g : ι → ℝ≥0) {p q : with `ℝ≥0`-valued functions. -/ theorem inner_le_Lp_mul_Lq (f g : ι → ℝ≥0) {p q : ℝ} (hpq : p.IsConjExponent q) : ∑ i ∈ s, f i * g i ≤ (∑ i ∈ s, f i ^ p) ^ (1 / p) * (∑ i ∈ s, g i ^ q) ^ (1 / q) := by - by_cases hF_zero : ∑ i ∈ s, f i ^ p = 0 - · exact inner_le_Lp_mul_Lp_of_norm_eq_zero s f g hpq hF_zero - by_cases hG_zero : ∑ i ∈ s, g i ^ q = 0 + obtain hf | hf := eq_zero_or_pos (∑ i ∈ s, f i ^ p) + · exact inner_le_Lp_mul_Lp_of_norm_eq_zero s f g hpq hf + obtain hg | hg := eq_zero_or_pos (∑ i ∈ s, g i ^ q) · calc ∑ i ∈ s, f i * g i = ∑ i ∈ s, g i * f i := by congr with i rw [mul_comm] _ ≤ (∑ i ∈ s, g i ^ q) ^ (1 / q) * (∑ i ∈ s, f i ^ p) ^ (1 / p) := - (inner_le_Lp_mul_Lp_of_norm_eq_zero s g f hpq.symm hG_zero) + (inner_le_Lp_mul_Lp_of_norm_eq_zero s g f hpq.symm hg) _ = (∑ i ∈ s, f i ^ p) ^ (1 / p) * (∑ i ∈ s, g i ^ q) ^ (1 / q) := mul_comm _ _ let f' i := f i / (∑ i ∈ s, f i ^ p) ^ (1 / p) let g' i := g i / (∑ i ∈ s, g i ^ q) ^ (1 / q) suffices (∑ i ∈ s, f' i * g' i) ≤ 1 by simp_rw [f', g', div_mul_div_comm, ← sum_div] at this - rwa [div_le_iff, one_mul] at this - refine mul_ne_zero ?_ ?_ - · rw [Ne, rpow_eq_zero_iff, not_and_or] - exact Or.inl hF_zero - · rw [Ne, rpow_eq_zero_iff, not_and_or] - exact Or.inl hG_zero + rwa [div_le_iff₀, one_mul] at this + -- TODO: We are missing a positivity extension here + exact mul_pos (rpow_pos hf) (rpow_pos hg) refine inner_le_Lp_mul_Lp_of_norm_le_one s f' g' hpq (le_of_eq ?_) (le_of_eq ?_) · simp_rw [f', div_rpow, ← sum_div, ← rpow_mul, one_div, inv_mul_cancel₀ hpq.ne_zero, rpow_one, - div_self hF_zero] + div_self hf.ne'] · simp_rw [g', div_rpow, ← sum_div, ← rpow_mul, one_div, inv_mul_cancel₀ hpq.symm.ne_zero, - rpow_one, div_self hG_zero] + rpow_one, div_self hg.ne'] /-- **Weighted Hölder inequality**. -/ lemma inner_le_weight_mul_Lp (s : Finset ι) {p : ℝ} (hp : 1 ≤ p) (w f : ι → ℝ≥0) : @@ -481,7 +476,7 @@ theorem inner_le_Lp_mul_Lq_tsum' {f g : ι → ℝ≥0} {p q : ℝ} (hpq : p.IsC /-- **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 `NNReal`-valued functions. For an alternative version, convenient if the infinite sums are not already expressed as -`p`-th powers, see `inner_le_Lp_mul_Lq_tsum`. -/ +`p`-th powers, see `inner_le_Lp_mul_Lq_tsum`. -/ theorem inner_le_Lp_mul_Lq_hasSum {f g : ι → ℝ≥0} {A B : ℝ≥0} {p q : ℝ} (hpq : p.IsConjExponent q) (hf : HasSum (fun i => f i ^ p) (A ^ p)) (hg : HasSum (fun i => g i ^ q) (B ^ q)) : ∃ C, C ≤ A * B ∧ HasSum (fun i => f i * g i) C := by @@ -517,17 +512,17 @@ theorem isGreatest_Lp (f : ι → ℝ≥0) {p q : ℝ} (hpq : p.IsConjExponent q ((∑ i ∈ s, f i ^ p) ^ (1 / p)) := by constructor · use fun i => f i ^ p / f i / (∑ i ∈ s, f i ^ p) ^ (1 / q) - by_cases hf : ∑ i ∈ s, f i ^ p = 0 + obtain hf | hf := eq_zero_or_pos (∑ i ∈ s, f i ^ p) · simp [hf, hpq.ne_zero, hpq.symm.ne_zero] · have A : p + q - q ≠ 0 := by simp [hpq.ne_zero] have B : ∀ y : ℝ≥0, y * y ^ p / y = y ^ p := by refine fun y => mul_div_cancel_left_of_imp fun h => ?_ simp [h, hpq.ne_zero] simp only [Set.mem_setOf_eq, div_rpow, ← sum_div, ← rpow_mul, - div_mul_cancel₀ _ hpq.symm.ne_zero, rpow_one, div_le_iff hf, one_mul, hpq.mul_eq_add, ← + div_mul_cancel₀ _ hpq.symm.ne_zero, rpow_one, div_le_iff₀ hf, one_mul, hpq.mul_eq_add, ← rpow_sub' _ A, add_sub_cancel_right, le_refl, true_and_iff, ← mul_div_assoc, B] - rw [div_eq_iff, ← rpow_add hf, one_div, one_div, hpq.inv_add_inv_conj, rpow_one] - simpa [hpq.symm.ne_zero] using hf + rw [div_eq_iff, ← rpow_add hf.ne', one_div, one_div, hpq.inv_add_inv_conj, rpow_one] + simpa [hpq.symm.ne_zero] using hf.ne' · rintro _ ⟨g, hg, rfl⟩ apply le_trans (inner_le_Lp_mul_Lq s f g hpq) simpa only [mul_one] using @@ -589,7 +584,7 @@ theorem Lp_add_le_tsum' {f g : ι → ℝ≥0} {p : ℝ} (hp : 1 ≤ p) (hf : Su /-- **Minkowski inequality**: the `L_p` seminorm of the infinite sum of two vectors is less than or equal to the infinite sum of the `L_p`-seminorms of the summands, if these infinite sums both exist. A version for `NNReal`-valued functions. For an alternative version, convenient if the -infinite sums are not already expressed as `p`-th powers, see `Lp_add_le_tsum_of_nonneg`. -/ +infinite sums are not already expressed as `p`-th powers, see `Lp_add_le_tsum_of_nonneg`. -/ theorem Lp_add_le_hasSum {f g : ι → ℝ≥0} {A B : ℝ≥0} {p : ℝ} (hp : 1 ≤ p) (hf : HasSum (fun i => f i ^ p) (A ^ p)) (hg : HasSum (fun i => g i ^ p) (B ^ p)) : ∃ C, C ≤ A + B ∧ HasSum (fun i => (f i + g i) ^ p) (C ^ p) := by @@ -693,7 +688,7 @@ theorem inner_le_Lp_mul_Lq_tsum_of_nonneg' (hpq : p.IsConjExponent q) (hf : ∀ /-- **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 `NNReal`-valued functions. For an alternative version, convenient if the infinite sums are not already expressed as -`p`-th powers, see `inner_le_Lp_mul_Lq_tsum_of_nonneg`. -/ +`p`-th powers, see `inner_le_Lp_mul_Lq_tsum_of_nonneg`. -/ theorem inner_le_Lp_mul_Lq_hasSum_of_nonneg (hpq : p.IsConjExponent q) {A B : ℝ} (hA : 0 ≤ A) (hB : 0 ≤ B) (hf : ∀ i, 0 ≤ f i) (hg : ∀ i, 0 ≤ g i) (hf_sum : HasSum (fun i => f i ^ p) (A ^ p)) (hg_sum : HasSum (fun i => g i ^ q) (B ^ q)) : @@ -797,7 +792,7 @@ theorem inner_le_Lp_mul_Lq (hpq : p.IsConjExponent q) : · cases' H' with H' H' <;> simp [H', -one_div, -sum_eq_zero_iff, -rpow_eq_zero_iff, H] replace H' : (∀ i ∈ s, f i ≠ ⊤) ∧ ∀ i ∈ s, g i ≠ ⊤ := by simpa [ENNReal.rpow_eq_top_iff, asymm hpq.pos, asymm hpq.symm.pos, hpq.pos, hpq.symm.pos, - ENNReal.sum_eq_top_iff, not_or] using H' + ENNReal.sum_eq_top, not_or] using H' have := ENNReal.coe_le_coe.2 (@NNReal.inner_le_Lp_mul_Lq _ s (fun i => ENNReal.toNNReal (f i)) (fun i => ENNReal.toNNReal (g i)) _ _ hpq) simp [← ENNReal.coe_rpow_of_nonneg, le_of_lt hpq.pos, le_of_lt hpq.one_div_pos, @@ -822,7 +817,7 @@ lemma inner_le_weight_mul_Lp_of_nonneg (s : Finset ι) {p : ℝ} (hp : 1 ≤ p) by_cases H' : (∑ i ∈ s, w i) ^ (1 - p⁻¹) = ⊤ ∨ (∑ i ∈ s, w i * f i ^ p) ^ p⁻¹ = ⊤ · cases' H' with H' H' <;> simp [H', -one_div, -sum_eq_zero_iff, -rpow_eq_zero_iff, H] replace H' : (∀ i ∈ s, w i ≠ ⊤) ∧ ∀ i ∈ s, w i * f i ^ p ≠ ⊤ := by - simpa [rpow_eq_top_iff,hp₀, hp₁, hp₀.not_lt, hp₁.not_lt, sum_eq_top_iff, not_or] using H' + simpa [rpow_eq_top_iff,hp₀, hp₁, hp₀.not_lt, hp₁.not_lt, sum_eq_top, not_or] using H' have := coe_le_coe.2 <| NNReal.inner_le_weight_mul_Lp s hp.le (fun i ↦ ENNReal.toNNReal (w i)) fun i ↦ ENNReal.toNNReal (f i) rw [coe_mul] at this @@ -864,7 +859,7 @@ theorem Lp_add_le (hp : 1 ≤ p) : · cases' H' with H' H' <;> simp [H', -one_div] have pos : 0 < p := lt_of_lt_of_le zero_lt_one hp replace H' : (∀ i ∈ s, f i ≠ ⊤) ∧ ∀ i ∈ s, g i ≠ ⊤ := by - simpa [ENNReal.rpow_eq_top_iff, asymm pos, pos, ENNReal.sum_eq_top_iff, not_or] using H' + simpa [ENNReal.rpow_eq_top_iff, asymm pos, pos, ENNReal.sum_eq_top, not_or] using H' have := ENNReal.coe_le_coe.2 (@NNReal.Lp_add_le _ s (fun i => ENNReal.toNNReal (f i)) (fun i => ENNReal.toNNReal (g i)) _ diff --git a/Mathlib/Analysis/MeanInequalitiesPow.lean b/Mathlib/Analysis/MeanInequalitiesPow.lean index bd0833e79f889..7fcc0ddceed9a 100644 --- a/Mathlib/Analysis/MeanInequalitiesPow.lean +++ b/Mathlib/Analysis/MeanInequalitiesPow.lean @@ -69,7 +69,7 @@ theorem pow_sum_div_card_le_sum_pow {f : ι → ℝ} (n : ℕ) (hf : ∀ a ∈ s · 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 + 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 => @@ -219,7 +219,7 @@ theorem rpow_arith_mean_le_arith_mean_rpow (w z : ι → ℝ≥0∞) (hw' : ∑ simp [ENNReal.mul_eq_top, hp_pos, hp_nonneg, hp_not_neg] refine le_of_top_imp_top_of_toNNReal_le ?_ ?_ · -- first, prove `(∑ i ∈ s, w i * z i) ^ p = ⊤ → ∑ i ∈ s, (w i * z i ^ p) = ⊤` - rw [rpow_eq_top_iff, sum_eq_top_iff, sum_eq_top_iff] + rw [rpow_eq_top_iff, sum_eq_top, sum_eq_top] intro h simp only [and_false_iff, hp_not_neg, false_or_iff] at h rcases h.left with ⟨a, H, ha⟩ diff --git a/Mathlib/Analysis/MellinTransform.lean b/Mathlib/Analysis/MellinTransform.lean index 95ff3017bcc71..6712829f036dc 100644 --- a/Mathlib/Analysis/MellinTransform.lean +++ b/Mathlib/Analysis/MellinTransform.lean @@ -256,7 +256,7 @@ theorem mellin_convergent_of_isBigO_scalar {a b : ℝ} {f : ℝ → ℝ} {s : rw [this, integrableOn_union, integrableOn_union] refine ⟨⟨hc2', integrableOn_Icc_iff_integrableOn_Ioc.mp ?_⟩, hc1'⟩ refine - (hfc.continuousOn_mul ?_ isOpen_Ioi).integrableOn_compact_subset + (hfc.continuousOn_mul ?_ isOpen_Ioi.isLocallyClosed).integrableOn_compact_subset (fun t ht => (hc2.trans_le ht.1 : 0 < t)) isCompact_Icc exact ContinuousAt.continuousOn fun t ht => continuousAt_rpow_const _ _ <| Or.inl <| ne_of_gt ht @@ -327,7 +327,8 @@ theorem mellin_hasDerivAt_of_isBigO_rpow [NormedSpace ℂ E] {a b : ℝ} exact mellinConvergent_of_isBigO_rpow hfc hf_top hs_top hf_bot hs_bot have h3 : AEStronglyMeasurable (F' s) (volume.restrict <| Ioi 0) := by apply LocallyIntegrableOn.aestronglyMeasurable - refine hfc.continuousOn_smul isOpen_Ioi ((ContinuousAt.continuousOn fun t ht => ?_).mul ?_) + refine hfc.continuousOn_smul isOpen_Ioi.isLocallyClosed + ((ContinuousAt.continuousOn fun t ht => ?_).mul ?_) · exact continuousAt_ofReal_cpow_const _ _ (Or.inr <| ne_of_gt ht) · refine continuous_ofReal.comp_continuousOn ?_ exact continuousOn_log.mono (subset_compl_singleton_iff.mpr not_mem_Ioi_self) @@ -362,7 +363,7 @@ theorem mellin_hasDerivAt_of_isBigO_rpow [NormedSpace ℂ E] {a b : ℝ} obtain ⟨w', hw1', hw2'⟩ := exists_between hj' refine mellin_convergent_of_isBigO_scalar ?_ ?_ hw1' ?_ hw2 · simp_rw [mul_comm] - refine hfc.norm.mul_continuousOn ?_ isOpen_Ioi + refine hfc.norm.mul_continuousOn ?_ isOpen_Ioi.isLocallyClosed refine Continuous.comp_continuousOn _root_.continuous_abs (continuousOn_log.mono ?_) exact subset_compl_singleton_iff.mpr not_mem_Ioi_self · refine (isBigO_rpow_top_log_smul hw2' hf_top).norm_left.congr_left fun t ↦ ?_ diff --git a/Mathlib/Analysis/Normed/Affine/Isometry.lean b/Mathlib/Analysis/Normed/Affine/Isometry.lean index 737521f2a9dec..f0545ea11cc87 100644 --- a/Mathlib/Analysis/Normed/Affine/Isometry.lean +++ b/Mathlib/Analysis/Normed/Affine/Isometry.lean @@ -447,8 +447,7 @@ theorem symm_apply_apply (x : P) : e.symm (e x) = x := e.toAffineEquiv.symm_apply_apply x @[simp] -theorem symm_symm : e.symm.symm = e := - ext fun _ => rfl +theorem symm_symm : e.symm.symm = e := rfl @[simp] theorem toAffineEquiv_symm : e.toAffineEquiv.symm = e.symm.toAffineEquiv := @@ -675,15 +674,13 @@ theorem pointReflection_symm (x : P) : (pointReflection 𝕜 x).symm = pointRefl theorem dist_pointReflection_fixed (x y : P) : dist (pointReflection 𝕜 x y) x = dist y x := by rw [← (pointReflection 𝕜 x).dist_map y x, pointReflection_self] -set_option linter.deprecated false in theorem dist_pointReflection_self' (x y : P) : dist (pointReflection 𝕜 x y) y = ‖2 • (x -ᵥ y)‖ := by rw [pointReflection_apply, dist_eq_norm_vsub V, vadd_vsub_assoc, two_nsmul] -set_option linter.deprecated false in theorem dist_pointReflection_self (x y : P) : dist (pointReflection 𝕜 x y) y = ‖(2 : 𝕜)‖ * dist x y := by - rw [dist_pointReflection_self', ← two_smul' 𝕜 (x -ᵥ y), norm_smul, ← dist_eq_norm_vsub V] + rw [dist_pointReflection_self', two_nsmul, ← two_smul 𝕜, norm_smul, ← dist_eq_norm_vsub V] theorem pointReflection_fixed_iff [Invertible (2 : 𝕜)] {x y : P} : pointReflection 𝕜 x y = y ↔ y = x := diff --git a/Mathlib/Analysis/Normed/Affine/MazurUlam.lean b/Mathlib/Analysis/Normed/Affine/MazurUlam.lean index 0ccabea54df9c..b3a9fcf2d073a 100644 --- a/Mathlib/Analysis/Normed/Affine/MazurUlam.lean +++ b/Mathlib/Analysis/Normed/Affine/MazurUlam.lean @@ -74,7 +74,7 @@ theorem midpoint_fixed {x y : PE} : have : c ≤ c / 2 := by apply ciSup_le rintro ⟨e, he⟩ - simp only [Subtype.coe_mk, le_div_iff' (zero_lt_two' ℝ), ← hf_dist] + simp only [Subtype.coe_mk, le_div_iff₀' (zero_lt_two' ℝ), ← hf_dist] exact le_ciSup h_bdd ⟨f e, hf_maps_to he⟩ replace : c ≤ 0 := by linarith refine fun e hx hy => dist_le_zero.1 (le_trans ?_ this) diff --git a/Mathlib/Analysis/Normed/Algebra/Exponential.lean b/Mathlib/Analysis/Normed/Algebra/Exponential.lean index f95b688f0ee8b..1e8094ecb6331 100644 --- a/Mathlib/Analysis/Normed/Algebra/Exponential.lean +++ b/Mathlib/Analysis/Normed/Algebra/Exponential.lean @@ -154,6 +154,7 @@ theorem star_exp [T2Space 𝔸] [StarRing 𝔸] [ContinuousStar 𝔸] (x : 𝔸) variable (𝕂) +@[aesop safe apply] theorem _root_.IsSelfAdjoint.exp [T2Space 𝔸] [StarRing 𝔸] [ContinuousStar 𝔸] {x : 𝔸} (h : IsSelfAdjoint x) : IsSelfAdjoint (exp 𝕂 x) := (star_exp x).trans <| h.symm ▸ rfl @@ -269,7 +270,7 @@ theorem exp_add_of_commute_of_mem_ball [CharZero 𝕂] {x y : 𝔸} (hxy : Commu ext rw [hxy.add_pow' _, Finset.smul_sum] refine tsum_congr fun n => Finset.sum_congr rfl fun kl hkl => ?_ - rw [← Nat.cast_smul_eq_nsmul 𝕂, smul_smul, smul_mul_smul, ← Finset.mem_antidiagonal.mp hkl, + rw [← Nat.cast_smul_eq_nsmul 𝕂, smul_smul, smul_mul_smul_comm, ← Finset.mem_antidiagonal.mp hkl, Nat.cast_add_choose, Finset.mem_antidiagonal.mp hkl] congr 1 have : (n ! : 𝕂) ≠ 0 := Nat.cast_ne_zero.mpr n.factorial_ne_zero @@ -512,7 +513,7 @@ theorem _root_.Prod.snd_exp [CompleteSpace 𝔹] (x : 𝔸 × 𝔹) : (exp 𝕂 map_exp _ (RingHom.snd 𝔸 𝔹) continuous_snd x @[simp] -theorem _root_.Pi.exp_apply {ι : Type*} {𝔸 : ι → Type*} [Finite ι] [∀ i, NormedRing (𝔸 i)] +theorem _root_.Pi.coe_exp {ι : Type*} {𝔸 : ι → Type*} [Finite ι] [∀ i, NormedRing (𝔸 i)] [∀ i, NormedAlgebra 𝕂 (𝔸 i)] [∀ i, CompleteSpace (𝔸 i)] (x : ∀ i, 𝔸 i) (i : ι) : exp 𝕂 x i = exp 𝕂 (x i) := let ⟨_⟩ := nonempty_fintype ι @@ -521,7 +522,7 @@ theorem _root_.Pi.exp_apply {ι : Type*} {𝔸 : ι → Type*} [Finite ι] [∀ theorem _root_.Pi.exp_def {ι : Type*} {𝔸 : ι → Type*} [Finite ι] [∀ i, NormedRing (𝔸 i)] [∀ i, NormedAlgebra 𝕂 (𝔸 i)] [∀ i, CompleteSpace (𝔸 i)] (x : ∀ i, 𝔸 i) : exp 𝕂 x = fun i => exp 𝕂 (x i) := - funext <| Pi.exp_apply 𝕂 x + funext <| Pi.coe_exp 𝕂 x theorem _root_.Function.update_exp {ι : Type*} {𝔸 : ι → Type*} [Finite ι] [DecidableEq ι] [∀ i, NormedRing (𝔸 i)] [∀ i, NormedAlgebra 𝕂 (𝔸 i)] [∀ i, CompleteSpace (𝔸 i)] (x : ∀ i, 𝔸 i) diff --git a/Mathlib/Analysis/Normed/Algebra/Spectrum.lean b/Mathlib/Analysis/Normed/Algebra/Spectrum.lean index d74a1d6c50562..e6e984888bc72 100644 --- a/Mathlib/Analysis/Normed/Algebra/Spectrum.lean +++ b/Mathlib/Analysis/Normed/Algebra/Spectrum.lean @@ -740,6 +740,26 @@ lemma real_iff [Algebra ℂ A] {a : A} : simp · exact .of_subset_range_algebraMap Complex.ofReal_re fun x hx ↦ ⟨x.re, (h x hx).symm⟩ +lemma nnreal_le_iff [Algebra ℝ A] {a : A} + (ha : SpectrumRestricts a ContinuousMap.realToNNReal) {r : ℝ≥0} : + (∀ x ∈ spectrum ℝ≥0 a, r ≤ x) ↔ ∀ x ∈ spectrum ℝ a, r ≤ x := by + simp [← ha.algebraMap_image] + +lemma nnreal_lt_iff [Algebra ℝ A] {a : A} + (ha : SpectrumRestricts a ContinuousMap.realToNNReal) {r : ℝ≥0} : + (∀ x ∈ spectrum ℝ≥0 a, r < x) ↔ ∀ x ∈ spectrum ℝ a, r < x := by + simp [← ha.algebraMap_image] + +lemma le_nnreal_iff [Algebra ℝ A] {a : A} + (ha : SpectrumRestricts a ContinuousMap.realToNNReal) {r : ℝ≥0} : + (∀ x ∈ spectrum ℝ≥0 a, x ≤ r) ↔ ∀ x ∈ spectrum ℝ a, x ≤ r := by + simp [← ha.algebraMap_image] + +lemma lt_nnreal_iff [Algebra ℝ A] {a : A} + (ha : SpectrumRestricts a ContinuousMap.realToNNReal) {r : ℝ≥0} : + (∀ x ∈ spectrum ℝ≥0 a, x < r) ↔ ∀ x ∈ spectrum ℝ a, x < r := by + simp [← ha.algebraMap_image] + lemma nnreal_iff_spectralRadius_le [Algebra ℝ A] {a : A} {t : ℝ≥0} (ht : spectralRadius ℝ a ≤ t) : SpectrumRestricts a ContinuousMap.realToNNReal ↔ spectralRadius ℝ (algebraMap ℝ A t - a) ≤ t := by @@ -817,6 +837,16 @@ lemma real_iff [Module ℂ A] [IsScalarTower ℂ A A] [SMulCommClass ℂ A A] {a rw [quasispectrumRestricts_iff_spectrumRestricts_inr, Unitization.quasispectrum_eq_spectrum_inr' _ ℂ, SpectrumRestricts.real_iff] +lemma le_nnreal_iff [Module ℝ A] [IsScalarTower ℝ A A] [SMulCommClass ℝ A A] {a : A} + (ha : QuasispectrumRestricts a ContinuousMap.realToNNReal) {r : ℝ≥0} : + (∀ x ∈ quasispectrum ℝ≥0 a, x ≤ r) ↔ ∀ x ∈ quasispectrum ℝ a, x ≤ r := by + simp [← ha.algebraMap_image] + +lemma lt_nnreal_iff [Module ℝ A] [IsScalarTower ℝ A A] [SMulCommClass ℝ A A] {a : A} + (ha : QuasispectrumRestricts a ContinuousMap.realToNNReal) {r : ℝ≥0} : + (∀ x ∈ quasispectrum ℝ≥0 a, x < r) ↔ ∀ x ∈ quasispectrum ℝ a, x < r := by + simp [← ha.algebraMap_image] + end QuasispectrumRestricts variable {A : Type*} [Ring A] [PartialOrder A] diff --git a/Mathlib/Analysis/Normed/Algebra/Unitization.lean b/Mathlib/Analysis/Normed/Algebra/Unitization.lean index 789e764e8c4e0..90fcffffc0c67 100644 --- a/Mathlib/Analysis/Normed/Algebra/Unitization.lean +++ b/Mathlib/Analysis/Normed/Algebra/Unitization.lean @@ -213,7 +213,7 @@ theorem uniformEmbedding_addEquiv {𝕜} [NontriviallyNormedField 𝕜] : comap_uniformity := rfl inj := (addEquiv 𝕜 A).injective -/-- `Unitization 𝕜 A` is complete whenever `𝕜` and `A` are also. -/ +/-- `Unitization 𝕜 A` is complete whenever `𝕜` and `A` are also. -/ instance instCompleteSpace [CompleteSpace 𝕜] [CompleteSpace A] : CompleteSpace (Unitization 𝕜 A) := (completeSpace_congr uniformEmbedding_addEquiv).mpr CompleteSpace.prod diff --git a/Mathlib/Analysis/Normed/Field/Basic.lean b/Mathlib/Analysis/Normed/Field/Basic.lean index c0e8c5ba1564c..02d24cb406d37 100644 --- a/Mathlib/Analysis/Normed/Field/Basic.lean +++ b/Mathlib/Analysis/Normed/Field/Basic.lean @@ -5,15 +5,9 @@ Authors: Patrick Massot, Johannes Hölzl -/ import Mathlib.Algebra.Algebra.NonUnitalSubalgebra import Mathlib.Algebra.Algebra.Subalgebra.Basic -import Mathlib.Algebra.Order.Ring.Finset -import Mathlib.Analysis.Normed.Group.Bounded import Mathlib.Analysis.Normed.Group.Constructions -import Mathlib.Analysis.Normed.Group.Rat import Mathlib.Analysis.Normed.Group.Submodule -import Mathlib.Analysis.Normed.Group.Uniform -import Mathlib.GroupTheory.OrderOfElement -import Mathlib.Topology.Instances.NNReal -import Mathlib.Topology.MetricSpace.DilationEquiv +import Mathlib.Data.Set.Pointwise.Interval /-! # Normed fields @@ -23,12 +17,20 @@ definitions. -/ -- Guard against import creep. +assert_not_exists AddChar +assert_not_exists comap_norm_atTop +assert_not_exists DilationEquiv +assert_not_exists Finset.sup_mul_le_mul_sup_of_nonneg +assert_not_exists IsOfFinOrder +assert_not_exists Isometry.norm_map_of_map_one +assert_not_exists NNReal.isOpen_Ico_zero +assert_not_exists Rat.norm_cast_real assert_not_exists RestrictScalars -variable {α : Type*} {β : Type*} {γ : Type*} {ι : Type*} +variable {α : Type*} {β : Type*} {ι : Type*} -open Filter Metric Bornology -open scoped Topology NNReal ENNReal uniformity Pointwise +open Filter +open scoped Topology NNReal /-- A non-unital seminormed ring is a not-necessarily-unital ring endowed with a seminorm which satisfies the inequality `‖x y‖ ≤ ‖x‖ ‖y‖`. -/ @@ -223,17 +225,6 @@ theorem one_le_norm_one (β) [NormedRing β] [Nontrivial β] : 1 ≤ ‖(1 : β) theorem one_le_nnnorm_one (β) [NormedRing β] [Nontrivial β] : 1 ≤ ‖(1 : β)‖₊ := one_le_norm_one β -theorem Filter.Tendsto.zero_mul_isBoundedUnder_le {f g : ι → α} {l : Filter ι} - (hf : Tendsto f l (𝓝 0)) (hg : IsBoundedUnder (· ≤ ·) l ((‖·‖) ∘ g)) : - Tendsto (fun x => f x * g x) l (𝓝 0) := - hf.op_zero_isBoundedUnder_le hg (· * ·) norm_mul_le - -theorem Filter.isBoundedUnder_le_mul_tendsto_zero {f g : ι → α} {l : Filter ι} - (hf : IsBoundedUnder (· ≤ ·) l (norm ∘ f)) (hg : Tendsto g l (𝓝 0)) : - Tendsto (fun x => f x * g x) l (𝓝 0) := - hg.op_zero_isBoundedUnder_le hf (flip (· * ·)) fun x y => - (norm_mul_le y x).trans_eq (mul_comm _ _) - /-- In a seminormed ring, the left-multiplication `AddMonoidHom` is bounded. -/ theorem mulLeft_bound (x : α) : ∀ y : α, ‖AddMonoidHom.mulLeft x y‖ ≤ ‖x‖ * ‖y‖ := norm_mul_le x @@ -244,7 +235,7 @@ theorem mulRight_bound (x : α) : ∀ y : α, ‖AddMonoidHom.mulRight x y‖ exact norm_mul_le y x /-- A non-unital subalgebra of a non-unital seminormed ring is also a non-unital seminormed ring, -with the restriction of the norm. -/ +with the restriction of the norm. -/ instance NonUnitalSubalgebra.nonUnitalSeminormedRing {𝕜 : Type*} [CommRing 𝕜] {E : Type*} [NonUnitalSeminormedRing E] [Module 𝕜 E] (s : NonUnitalSubalgebra 𝕜 E) : NonUnitalSeminormedRing s := @@ -252,7 +243,7 @@ instance NonUnitalSubalgebra.nonUnitalSeminormedRing {𝕜 : Type*} [CommRing norm_mul := fun a b => norm_mul_le a.1 b.1 } /-- A non-unital subalgebra of a non-unital seminormed ring is also a non-unital seminormed ring, -with the restriction of the norm. -/ +with the restriction of the norm. -/ -- necessary to require `SMulMemClass S 𝕜 E` so that `𝕜` can be determined as an `outParam` @[nolint unusedArguments] instance (priority := 75) NonUnitalSubalgebraClass.nonUnitalSeminormedRing {S 𝕜 E : Type*} @@ -263,14 +254,14 @@ instance (priority := 75) NonUnitalSubalgebraClass.nonUnitalSeminormedRing {S norm_mul := fun a b => norm_mul_le a.1 b.1 } /-- A non-unital subalgebra of a non-unital normed ring is also a non-unital normed ring, with the -restriction of the norm. -/ +restriction of the norm. -/ instance NonUnitalSubalgebra.nonUnitalNormedRing {𝕜 : Type*} [CommRing 𝕜] {E : Type*} [NonUnitalNormedRing E] [Module 𝕜 E] (s : NonUnitalSubalgebra 𝕜 E) : NonUnitalNormedRing s := { s.nonUnitalSeminormedRing with eq_of_dist_eq_zero := eq_of_dist_eq_zero } /-- A non-unital subalgebra of a non-unital normed ring is also a non-unital normed ring, -with the restriction of the norm. -/ +with the restriction of the norm. -/ instance (priority := 75) NonUnitalSubalgebraClass.nonUnitalNormedRing {S 𝕜 E : Type*} [CommRing 𝕜] [NonUnitalNormedRing E] [Module 𝕜 E] [SetLike S E] [NonUnitalSubringClass S E] [SMulMemClass S 𝕜 E] (s : S) : @@ -300,21 +291,6 @@ instance Prod.nonUnitalSeminormedRing [NonUnitalSeminormedRing β] : _ = ‖x‖ * ‖y‖ := rfl } -/-- Non-unital seminormed ring structure on the product of finitely many non-unital seminormed -rings, using the sup norm. -/ -instance Pi.nonUnitalSeminormedRing {π : ι → Type*} [Fintype ι] - [∀ i, NonUnitalSeminormedRing (π i)] : NonUnitalSeminormedRing (∀ i, π i) := - { Pi.seminormedAddCommGroup, Pi.nonUnitalRing with - norm_mul := fun x y => - NNReal.coe_mono <| - calc - (Finset.univ.sup fun i => ‖x i * y i‖₊) ≤ - Finset.univ.sup ((fun i => ‖x i‖₊) * fun i => ‖y i‖₊) := - Finset.sup_mono_fun fun _ _ => norm_mul_le _ _ - _ ≤ (Finset.univ.sup fun i => ‖x i‖₊) * Finset.univ.sup fun i => ‖y i‖₊ := - Finset.sup_mul_le_mul_sup_of_nonneg _ (fun _ _ => zero_le _) fun _ _ => zero_le _ - } - instance MulOpposite.instNonUnitalSeminormedRing : NonUnitalSeminormedRing αᵐᵒᵖ where __ := instNonUnitalRing __ := instSeminormedAddCommGroup @@ -325,7 +301,7 @@ end NonUnitalSeminormedRing section SeminormedRing -variable [SeminormedRing α] +variable [SeminormedRing α] {a b c : α} /-- A subalgebra of a seminormed ring is also a seminormed ring, with the restriction of the norm. -/ @@ -358,6 +334,7 @@ instance (priority := 75) SubalgebraClass.normedRing {S 𝕜 E : Type*} [CommRin { seminormedRing s with eq_of_dist_eq_zero := eq_of_dist_eq_zero } + theorem Nat.norm_cast_le : ∀ n : ℕ, ‖(n : α)‖ ≤ n * ‖(1 : α)‖ | 0 => by simp | n + 1 => by @@ -436,16 +413,33 @@ instance ULift.seminormedRing : SeminormedRing (ULift α) := instance Prod.seminormedRing [SeminormedRing β] : SeminormedRing (α × β) := { nonUnitalSeminormedRing, instRing with } -/-- Seminormed ring structure on the product of finitely many seminormed rings, - using the sup norm. -/ -instance Pi.seminormedRing {π : ι → Type*} [Fintype ι] [∀ i, SeminormedRing (π i)] : - SeminormedRing (∀ i, π i) := - { Pi.nonUnitalSeminormedRing, Pi.ring with } - instance MulOpposite.instSeminormedRing : SeminormedRing αᵐᵒᵖ where __ := instRing __ := instNonUnitalSeminormedRing +/-- This inequality is particularly useful when `c = 1` and `‖a‖ = ‖b‖ = 1` as it then shows that +chord length is a metric on the unit complex numbers. -/ +lemma norm_sub_mul_le (ha : ‖a‖ ≤ 1) : ‖c - a * b‖ ≤ ‖c - a‖ + ‖1 - b‖ := + calc + _ ≤ ‖c - a‖ + ‖a * (1 - b)‖ := by + simpa [mul_one_sub] using norm_sub_le_norm_sub_add_norm_sub c a (a * b) + _ ≤ ‖c - a‖ + ‖a‖ * ‖1 - b‖ := by gcongr; exact norm_mul_le .. + _ ≤ ‖c - a‖ + 1 * ‖1 - b‖ := by gcongr + _ = ‖c - a‖ + ‖1 - b‖ := by simp + +/-- This inequality is particularly useful when `c = 1` and `‖a‖ = ‖b‖ = 1` as it then shows that +chord length is a metric on the unit complex numbers. -/ +lemma norm_sub_mul_le' (hb : ‖b‖ ≤ 1) : ‖c - a * b‖ ≤ ‖1 - a‖ + ‖c - b‖ := by + rw [add_comm]; exact norm_sub_mul_le (α := αᵐᵒᵖ) hb + +/-- This inequality is particularly useful when `c = 1` and `‖a‖ = ‖b‖ = 1` as it then shows that +chord length is a metric on the unit complex numbers. -/ +lemma nnnorm_sub_mul_le (ha : ‖a‖₊ ≤ 1) : ‖c - a * b‖₊ ≤ ‖c - a‖₊ + ‖1 - b‖₊ := norm_sub_mul_le ha + +/-- This inequality is particularly useful when `c = 1` and `‖a‖ = ‖b‖ = 1` as it then shows that +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 + end SeminormedRing section NonUnitalNormedRing @@ -460,12 +454,6 @@ using the sup norm. -/ instance Prod.nonUnitalNormedRing [NonUnitalNormedRing β] : NonUnitalNormedRing (α × β) := { Prod.nonUnitalSeminormedRing, Prod.normedAddCommGroup with } -/-- Normed ring structure on the product of finitely many non-unital normed rings, using the sup -norm. -/ -instance Pi.nonUnitalNormedRing {π : ι → Type*} [Fintype ι] [∀ i, NonUnitalNormedRing (π i)] : - NonUnitalNormedRing (∀ i, π i) := - { Pi.nonUnitalSeminormedRing, Pi.normedAddCommGroup with } - instance MulOpposite.instNonUnitalNormedRing : NonUnitalNormedRing αᵐᵒᵖ where __ := instNonUnitalRing __ := instNonUnitalSeminormedRing @@ -490,11 +478,6 @@ instance ULift.normedRing : NormedRing (ULift α) := instance Prod.normedRing [NormedRing β] : NormedRing (α × β) := { nonUnitalNormedRing, instRing with } -/-- Normed ring structure on the product of finitely many normed rings, using the sup norm. -/ -instance Pi.normedRing {π : ι → Type*} [Fintype ι] [∀ i, NormedRing (π i)] : - NormedRing (∀ i, π i) := - { Pi.seminormedRing, Pi.normedAddCommGroup with } - instance MulOpposite.instNormedRing : NormedRing αᵐᵒᵖ where __ := instRing __ := instSeminormedRing @@ -515,12 +498,6 @@ instance Prod.nonUnitalSeminormedCommRing [NonUnitalSeminormedCommRing β] : NonUnitalSeminormedCommRing (α × β) := { nonUnitalSeminormedRing, instNonUnitalCommRing with } -/-- Non-unital seminormed commutative ring structure on the product of finitely many non-unital -seminormed commutative rings, using the sup norm. -/ -instance Pi.nonUnitalSeminormedCommRing {π : ι → Type*} [Fintype ι] - [∀ i, NonUnitalSeminormedCommRing (π i)] : NonUnitalSeminormedCommRing (∀ i, π i) := - { Pi.nonUnitalSeminormedRing, Pi.nonUnitalCommRing with } - instance MulOpposite.instNonUnitalSeminormedCommRing : NonUnitalSeminormedCommRing αᵐᵒᵖ where __ := instNonUnitalSeminormedRing __ := instNonUnitalCommRing @@ -532,14 +509,14 @@ section NonUnitalNormedCommRing variable [NonUnitalNormedCommRing α] /-- A non-unital subalgebra of a non-unital seminormed commutative ring is also a non-unital -seminormed commutative ring, with the restriction of the norm. -/ +seminormed commutative ring, with the restriction of the norm. -/ instance NonUnitalSubalgebra.nonUnitalSeminormedCommRing {𝕜 : Type*} [CommRing 𝕜] {E : Type*} [NonUnitalSeminormedCommRing E] [Module 𝕜 E] (s : NonUnitalSubalgebra 𝕜 E) : NonUnitalSeminormedCommRing s := { s.nonUnitalSeminormedRing, s.toNonUnitalCommRing with } /-- A non-unital subalgebra of a non-unital normed commutative ring is also a non-unital normed -commutative ring, with the restriction of the norm. -/ +commutative ring, with the restriction of the norm. -/ instance NonUnitalSubalgebra.nonUnitalNormedCommRing {𝕜 : Type*} [CommRing 𝕜] {E : Type*} [NonUnitalNormedCommRing E] [Module 𝕜 E] (s : NonUnitalSubalgebra 𝕜 E) : NonUnitalNormedCommRing s := @@ -554,12 +531,6 @@ instance Prod.nonUnitalNormedCommRing [NonUnitalNormedCommRing β] : NonUnitalNormedCommRing (α × β) := { Prod.nonUnitalSeminormedCommRing, Prod.normedAddCommGroup with } -/-- Normed commutative ring structure on the product of finitely many non-unital normed -commutative rings, using the sup norm. -/ -instance Pi.nonUnitalNormedCommRing {π : ι → Type*} [Fintype ι] - [∀ i, NonUnitalNormedCommRing (π i)] : NonUnitalNormedCommRing (∀ i, π i) := - { Pi.nonUnitalSeminormedCommRing, Pi.normedAddCommGroup with } - instance MulOpposite.instNonUnitalNormedCommRing : NonUnitalNormedCommRing αᵐᵒᵖ where __ := instNonUnitalNormedRing __ := instNonUnitalSeminormedCommRing @@ -578,12 +549,6 @@ instance ULift.seminormedCommRing : SeminormedCommRing (ULift α) := instance Prod.seminormedCommRing [SeminormedCommRing β] : SeminormedCommRing (α × β) := { Prod.nonUnitalSeminormedCommRing, instCommRing with } -/-- Seminormed commutative ring structure on the product of finitely many seminormed commutative -rings, using the sup norm. -/ -instance Pi.seminormedCommRing {π : ι → Type*} [Fintype ι] [∀ i, SeminormedCommRing (π i)] : - SeminormedCommRing (∀ i, π i) := - { Pi.nonUnitalSeminormedCommRing, Pi.ring with } - instance MulOpposite.instSeminormedCommRing : SeminormedCommRing αᵐᵒᵖ where __ := instSeminormedRing __ := instNonUnitalSeminormedCommRing @@ -593,13 +558,13 @@ end SeminormedCommRing section NormedCommRing /-- A subalgebra of a seminormed commutative ring is also a seminormed commutative ring, with the -restriction of the norm. -/ +restriction of the norm. -/ instance Subalgebra.seminormedCommRing {𝕜 : Type*} [CommRing 𝕜] {E : Type*} [SeminormedCommRing E] [Algebra 𝕜 E] (s : Subalgebra 𝕜 E) : SeminormedCommRing s := { s.seminormedRing, s.toCommRing with } /-- A subalgebra of a normed commutative ring is also a normed commutative ring, with the -restriction of the norm. -/ +restriction of the norm. -/ instance Subalgebra.normedCommRing {𝕜 : Type*} [CommRing 𝕜] {E : Type*} [NormedCommRing E] [Algebra 𝕜 E] (s : Subalgebra 𝕜 E) : NormedCommRing s := { s.seminormedCommRing, s.normedRing with } @@ -614,48 +579,12 @@ norm. -/ instance Prod.normedCommRing [NormedCommRing β] : NormedCommRing (α × β) := { nonUnitalNormedRing, instCommRing with } -/-- Normed commutative ring structure on the product of finitely many normed commutative rings, -using the sup norm. -/ -instance Pi.normedCommutativeRing {π : ι → Type*} [Fintype ι] [∀ i, NormedCommRing (π i)] : - NormedCommRing (∀ i, π i) := - { Pi.seminormedCommRing, Pi.normedAddCommGroup with } - instance MulOpposite.instNormedCommRing : NormedCommRing αᵐᵒᵖ where __ := instNormedRing __ := instSeminormedCommRing end NormedCommRing --- see Note [lower instance priority] -instance (priority := 100) semi_normed_ring_top_monoid [NonUnitalSeminormedRing α] : - ContinuousMul α := - ⟨continuous_iff_continuousAt.2 fun x => - tendsto_iff_norm_sub_tendsto_zero.2 <| by - have : ∀ e : α × α, - ‖e.1 * e.2 - x.1 * x.2‖ ≤ ‖e.1‖ * ‖e.2 - x.2‖ + ‖e.1 - x.1‖ * ‖x.2‖ := by - intro e - calc - ‖e.1 * e.2 - x.1 * x.2‖ ≤ ‖e.1 * (e.2 - x.2) + (e.1 - x.1) * x.2‖ := by - rw [_root_.mul_sub, _root_.sub_mul, sub_add_sub_cancel] - -- Porting note: `ENNReal.{mul_sub, sub_mul}` should be protected - _ ≤ ‖e.1‖ * ‖e.2 - x.2‖ + ‖e.1 - x.1‖ * ‖x.2‖ := - norm_add_le_of_le (norm_mul_le _ _) (norm_mul_le _ _) - refine squeeze_zero (fun e => norm_nonneg _) this ?_ - convert - ((continuous_fst.tendsto x).norm.mul - ((continuous_snd.tendsto x).sub tendsto_const_nhds).norm).add - (((continuous_fst.tendsto x).sub tendsto_const_nhds).norm.mul _) - -- Porting note: `show` used to select a goal to work on - rotate_right - · show Tendsto _ _ _ - exact tendsto_const_nhds - · simp⟩ - --- see Note [lower instance priority] -/-- A seminormed ring is a topological ring. -/ -instance (priority := 100) semi_normed_top_ring [NonUnitalSeminormedRing α] : - TopologicalRing α where - section NormedDivisionRing variable [NormedDivisionRing α] {a : α} @@ -740,114 +669,6 @@ theorem nndist_inv_inv₀ {z w : α} (hz : z ≠ 0) (hw : w ≠ 0) : nndist z⁻¹ w⁻¹ = nndist z w / (‖z‖₊ * ‖w‖₊) := NNReal.eq <| dist_inv_inv₀ hz hw -lemma antilipschitzWith_mul_left {a : α} (ha : a ≠ 0) : AntilipschitzWith (‖a‖₊⁻¹) (a * ·) := - AntilipschitzWith.of_le_mul_dist fun _ _ ↦ by simp [dist_eq_norm, ← _root_.mul_sub, ha] - -lemma antilipschitzWith_mul_right {a : α} (ha : a ≠ 0) : AntilipschitzWith (‖a‖₊⁻¹) (· * a) := - AntilipschitzWith.of_le_mul_dist fun _ _ ↦ by - simp [dist_eq_norm, ← _root_.sub_mul, ← mul_comm (‖a‖), ha] - -/-- Multiplication by a nonzero element `a` on the left -as a `DilationEquiv` of a normed division ring. -/ -@[simps!] -def DilationEquiv.mulLeft (a : α) (ha : a ≠ 0) : α ≃ᵈ α where - toEquiv := Equiv.mulLeft₀ a ha - edist_eq' := ⟨‖a‖₊, nnnorm_ne_zero_iff.2 ha, fun x y ↦ by - simp [edist_nndist, nndist_eq_nnnorm, ← mul_sub]⟩ - -/-- Multiplication by a nonzero element `a` on the right -as a `DilationEquiv` of a normed division ring. -/ -@[simps!] -def DilationEquiv.mulRight (a : α) (ha : a ≠ 0) : α ≃ᵈ α where - toEquiv := Equiv.mulRight₀ a ha - edist_eq' := ⟨‖a‖₊, nnnorm_ne_zero_iff.2 ha, fun x y ↦ by - simp [edist_nndist, nndist_eq_nnnorm, ← sub_mul, ← mul_comm (‖a‖₊)]⟩ - -namespace Filter - -@[simp] -lemma comap_mul_left_cobounded {a : α} (ha : a ≠ 0) : - comap (a * ·) (cobounded α) = cobounded α := - Dilation.comap_cobounded (DilationEquiv.mulLeft a ha) - -@[simp] -lemma map_mul_left_cobounded {a : α} (ha : a ≠ 0) : - map (a * ·) (cobounded α) = cobounded α := - DilationEquiv.map_cobounded (DilationEquiv.mulLeft a ha) - -@[simp] -lemma comap_mul_right_cobounded {a : α} (ha : a ≠ 0) : - comap (· * a) (cobounded α) = cobounded α := - Dilation.comap_cobounded (DilationEquiv.mulRight a ha) - -@[simp] -lemma map_mul_right_cobounded {a : α} (ha : a ≠ 0) : - map (· * a) (cobounded α) = cobounded α := - DilationEquiv.map_cobounded (DilationEquiv.mulRight a ha) - -/-- Multiplication on the left by a nonzero element of a normed division ring tends to infinity at -infinity. -/ -theorem tendsto_mul_left_cobounded {a : α} (ha : a ≠ 0) : - Tendsto (a * ·) (cobounded α) (cobounded α) := - (map_mul_left_cobounded ha).le - -/-- Multiplication on the right by a nonzero element of a normed division ring tends to infinity at -infinity. -/ -theorem tendsto_mul_right_cobounded {a : α} (ha : a ≠ 0) : - Tendsto (· * a) (cobounded α) (cobounded α) := - (map_mul_right_cobounded ha).le - -@[simp] -lemma inv_cobounded₀ : (cobounded α)⁻¹ = 𝓝[≠] 0 := by - rw [← comap_norm_atTop, ← Filter.comap_inv, ← comap_norm_nhdsWithin_Ioi_zero, - ← inv_atTop₀, ← Filter.comap_inv] - simp only [comap_comap, (· ∘ ·), norm_inv] - -@[simp] -lemma inv_nhdsWithin_ne_zero : (𝓝[≠] (0 : α))⁻¹ = cobounded α := by - rw [← inv_cobounded₀, inv_inv] - -lemma tendsto_inv₀_cobounded' : Tendsto Inv.inv (cobounded α) (𝓝[≠] 0) := - inv_cobounded₀.le - -theorem tendsto_inv₀_cobounded : Tendsto Inv.inv (cobounded α) (𝓝 0) := - tendsto_inv₀_cobounded'.mono_right inf_le_left - -lemma tendsto_inv₀_nhdsWithin_ne_zero : Tendsto Inv.inv (𝓝[≠] 0) (cobounded α) := - inv_nhdsWithin_ne_zero.le - -end Filter - --- see Note [lower instance priority] -instance (priority := 100) NormedDivisionRing.to_hasContinuousInv₀ : HasContinuousInv₀ α := by - refine ⟨fun r r0 => tendsto_iff_norm_sub_tendsto_zero.2 ?_⟩ - have r0' : 0 < ‖r‖ := norm_pos_iff.2 r0 - rcases exists_between r0' with ⟨ε, ε0, εr⟩ - have : ∀ᶠ e in 𝓝 r, ‖e⁻¹ - r⁻¹‖ ≤ ‖r - e‖ / ‖r‖ / ε := by - filter_upwards [(isOpen_lt continuous_const continuous_norm).eventually_mem εr] with e he - have e0 : e ≠ 0 := norm_pos_iff.1 (ε0.trans he) - calc - ‖e⁻¹ - r⁻¹‖ = ‖r‖⁻¹ * ‖r - e‖ * ‖e‖⁻¹ := by - rw [← norm_inv, ← norm_inv, ← norm_mul, ← norm_mul, _root_.mul_sub, _root_.sub_mul, - mul_assoc _ e, inv_mul_cancel₀ r0, mul_inv_cancel₀ e0, one_mul, mul_one] - -- Porting note: `ENNReal.{mul_sub, sub_mul}` should be `protected` - _ = ‖r - e‖ / ‖r‖ / ‖e‖ := by field_simp [mul_comm] - _ ≤ ‖r - e‖ / ‖r‖ / ε := by gcongr - refine squeeze_zero' (Eventually.of_forall fun _ => norm_nonneg _) this ?_ - refine (((continuous_const.sub continuous_id).norm.div_const _).div_const _).tendsto' _ _ ?_ - simp - --- see Note [lower instance priority] -/-- A normed division ring is a topological division ring. -/ -instance (priority := 100) NormedDivisionRing.to_topologicalDivisionRing : - TopologicalDivisionRing α where - -protected lemma IsOfFinOrder.norm_eq_one (ha : IsOfFinOrder a) : ‖a‖ = 1 := - ((normHom : α →*₀ ℝ).toMonoidHom.isOfFinOrder ha).eq_one <| norm_nonneg _ - -example [Monoid β] (φ : β →* α) {x : β} {k : ℕ+} (h : x ^ (k : ℕ) = 1) : - ‖φ x‖ = 1 := (φ.isOfFinOrder <| isOfFinOrder_iff_pow_eq_one.2 ⟨_, k.2, h⟩).norm_eq_one - end NormedDivisionRing /-- A normed field is a field with a norm satisfying ‖x y‖ = ‖x‖ ‖y‖. -/ @@ -960,11 +781,6 @@ instance denselyOrdered_range_nnnorm : DenselyOrdered (Set.range (nnnorm : α let ⟨z, h⟩ := exists_lt_nnnorm_lt α hxy exact ⟨⟨‖z‖₊, z, rfl⟩, h⟩ -theorem denseRange_nnnorm : DenseRange (nnnorm : α → ℝ≥0) := - dense_of_exists_between fun _ _ hr => - let ⟨x, h⟩ := exists_lt_nnnorm_lt α hr - ⟨‖x‖₊, ⟨x, rfl⟩, h⟩ - end Densely end NormedField @@ -1017,14 +833,6 @@ theorem norm_eq (x : ℝ≥0) : ‖(x : ℝ)‖ = x := by rw [Real.norm_eq_abs, theorem nnnorm_eq (x : ℝ≥0) : ‖(x : ℝ)‖₊ = x := NNReal.eq <| Real.norm_of_nonneg x.2 -lemma lipschitzWith_sub : LipschitzWith 2 (fun (p : ℝ≥0 × ℝ≥0) ↦ p.1 - p.2) := by - rw [← isometry_subtype_coe.lipschitzWith_iff] - have : Isometry (Prod.map ((↑) : ℝ≥0 → ℝ) ((↑) : ℝ≥0 → ℝ)) := - isometry_subtype_coe.prod_map isometry_subtype_coe - convert (((LipschitzWith.prod_fst.comp this.lipschitz).sub - (LipschitzWith.prod_snd.comp this.lipschitz)).max_const 0) - norm_num - end NNReal @[simp 1001] -- Porting note: increase priority so that the LHS doesn't simplify @@ -1049,24 +857,6 @@ theorem NormedAddCommGroup.tendsto_atTop' [Nonempty α] [SemilatticeSup α] [NoM 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]) -instance Int.instNormedCommRing : NormedCommRing ℤ where - __ := instCommRing - __ := instNormedAddCommGroup - norm_mul m n := by simp only [norm, Int.cast_mul, abs_mul, le_rfl] - -instance Int.instNormOneClass : NormOneClass ℤ := - ⟨by simp [← Int.norm_cast_real]⟩ - -instance Rat.instNormedField : NormedField ℚ where - __ := instField - __ := instNormedAddCommGroup - norm_mul' a b := by simp only [norm, Rat.cast_mul, abs_mul] - -instance Rat.instDenselyNormedField : DenselyNormedField ℚ where - lt_norm_lt r₁ r₂ h₀ hr := - let ⟨q, h⟩ := exists_rat_btwn hr - ⟨q, by rwa [← Rat.norm_cast_real, Real.norm_eq_abs, abs_of_pos (h₀.trans_lt h.1)]⟩ - section RingHomIsometric variable {R₁ : Type*} {R₂ : Type*} {R₃ : Type*} diff --git a/Mathlib/Analysis/Normed/Field/InfiniteSum.lean b/Mathlib/Analysis/Normed/Field/InfiniteSum.lean index 4defadc79c84a..720c5451551ec 100644 --- a/Mathlib/Analysis/Normed/Field/InfiniteSum.lean +++ b/Mathlib/Analysis/Normed/Field/InfiniteSum.lean @@ -3,7 +3,7 @@ Copyright (c) 2021 Anatole Dedecker. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Anatole Dedecker -/ -import Mathlib.Analysis.Normed.Field.Basic +import Mathlib.Analysis.Normed.Field.Lemmas import Mathlib.Analysis.Normed.Group.InfiniteSum import Mathlib.Topology.Algebra.InfiniteSum.Real @@ -21,9 +21,9 @@ We first establish results about arbitrary index types, `ι` and `ι'`, and then variable {R : Type*} {ι : Type*} {ι' : Type*} [NormedRing R] -open scoped Classical +open scoped Topology -open Finset +open Finset Filter /-! ### Arbitrary index types -/ @@ -43,13 +43,35 @@ theorem summable_mul_of_summable_norm [CompleteSpace R] {f : ι → R} {g : ι' Summable fun x : ι × ι' => f x.1 * g x.2 := (hf.mul_norm hg).of_norm -/-- Product of two infinites sums indexed by arbitrary types. - See also `tsum_mul_tsum` if `f` and `g` are *not* absolutely summable. -/ +theorem summable_mul_of_summable_norm' {f : ι → R} {g : ι' → R} + (hf : Summable fun x => ‖f x‖) (h'f : Summable f) + (hg : Summable fun x => ‖g x‖) (h'g : Summable g) : + Summable fun x : ι × ι' => f x.1 * g x.2 := by + classical + suffices HasSum (fun x : ι × ι' => f x.1 * g x.2) ((∑' i, f i) * (∑' j, g j)) from this.summable + let s : Finset ι × Finset ι' → Finset (ι × ι') := fun p ↦ p.1 ×ˢ p.2 + apply hasSum_of_subseq_of_summable (hf.mul_norm hg) tendsto_finset_prod_atTop + rw [← prod_atTop_atTop_eq] + have := Tendsto.prod_map h'f.hasSum h'g.hasSum + rw [← nhds_prod_eq] at this + convert ((continuous_mul (M := R)).continuousAt + (x := (∑' (i : ι), f i, ∑' (j : ι'), g j))).tendsto.comp this with p + simp [s, sum_product, ← mul_sum, ← sum_mul] + +/-- Product of two infinite sums indexed by arbitrary types. + See also `tsum_mul_tsum` if `f` and `g` are *not* absolutely summable, and + `tsum_mul_tsum_of_summable_norm'` when the space is not complete. -/ theorem tsum_mul_tsum_of_summable_norm [CompleteSpace R] {f : ι → R} {g : ι' → R} (hf : Summable fun x => ‖f x‖) (hg : Summable fun x => ‖g x‖) : ((∑' x, f x) * ∑' y, g y) = ∑' z : ι × ι', f z.1 * g z.2 := tsum_mul_tsum hf.of_norm hg.of_norm (summable_mul_of_summable_norm hf hg) +theorem tsum_mul_tsum_of_summable_norm' {f : ι → R} {g : ι' → R} + (hf : Summable fun x => ‖f x‖) (h'f : Summable f) + (hg : Summable fun x => ‖g x‖) (h'g : Summable g) : + ((∑' x, f x) * ∑' y, g y) = ∑' z : ι × ι', f z.1 * g z.2 := + tsum_mul_tsum h'f h'g (summable_mul_of_summable_norm' hf h'f hg h'g) + /-! ### `ℕ`-indexed families (Cauchy product) We prove two versions of the Cauchy product formula. The first one is @@ -76,28 +98,69 @@ theorem summable_norm_sum_mul_antidiagonal_of_summable_norm {f g : ℕ → R} norm_sum_le _ _ _ ≤ ∑ kl ∈ antidiagonal n, ‖f kl.1‖ * ‖g kl.2‖ := by gcongr; apply norm_mul_le +theorem summable_sum_mul_antidiagonal_of_summable_norm' {f g : ℕ → R} + (hf : Summable fun x => ‖f x‖) (h'f : Summable f) + (hg : Summable fun x => ‖g x‖) (h'g : Summable g) : + Summable fun n => ∑ kl ∈ antidiagonal n, f kl.1 * g kl.2 := + summable_sum_mul_antidiagonal_of_summable_mul (summable_mul_of_summable_norm' hf h'f hg h'g) + /-- The Cauchy product formula for the product of two infinite sums indexed by `ℕ`, expressed by summing on `Finset.antidiagonal`. See also `tsum_mul_tsum_eq_tsum_sum_antidiagonal` if `f` and `g` are - *not* absolutely summable. -/ + *not* absolutely summable, and `tsum_mul_tsum_eq_tsum_sum_antidiagonal_of_summable_norm'` + when the space is not complete. -/ theorem tsum_mul_tsum_eq_tsum_sum_antidiagonal_of_summable_norm [CompleteSpace R] {f g : ℕ → R} (hf : Summable fun x => ‖f x‖) (hg : Summable fun x => ‖g x‖) : ((∑' n, f n) * ∑' n, g n) = ∑' n, ∑ kl ∈ antidiagonal n, f kl.1 * g kl.2 := tsum_mul_tsum_eq_tsum_sum_antidiagonal hf.of_norm hg.of_norm (summable_mul_of_summable_norm hf hg) +theorem tsum_mul_tsum_eq_tsum_sum_antidiagonal_of_summable_norm' {f g : ℕ → R} + (hf : Summable fun x => ‖f x‖) (h'f : Summable f) + (hg : Summable fun x => ‖g x‖) (h'g : Summable g) : + ((∑' n, f n) * ∑' n, g n) = ∑' n, ∑ kl ∈ antidiagonal n, f kl.1 * g kl.2 := + tsum_mul_tsum_eq_tsum_sum_antidiagonal h'f h'g (summable_mul_of_summable_norm' hf h'f hg h'g) + theorem summable_norm_sum_mul_range_of_summable_norm {f g : ℕ → R} (hf : Summable fun x => ‖f x‖) (hg : Summable fun x => ‖g x‖) : Summable fun n => ‖∑ k ∈ range (n + 1), f k * g (n - k)‖ := by simp_rw [← sum_antidiagonal_eq_sum_range_succ fun k l => f k * g l] exact summable_norm_sum_mul_antidiagonal_of_summable_norm hf hg +theorem summable_sum_mul_range_of_summable_norm' {f g : ℕ → R} + (hf : Summable fun x => ‖f x‖) (h'f : Summable f) + (hg : Summable fun x => ‖g x‖) (h'g : Summable g) : + Summable fun n => ∑ k ∈ range (n + 1), f k * g (n - k) := by + simp_rw [← sum_antidiagonal_eq_sum_range_succ fun k l => f k * g l] + exact summable_sum_mul_antidiagonal_of_summable_norm' hf h'f hg h'g + /-- The Cauchy product formula for the product of two infinite sums indexed by `ℕ`, expressed by summing on `Finset.range`. See also `tsum_mul_tsum_eq_tsum_sum_range` if `f` and `g` are - *not* absolutely summable. -/ + *not* absolutely summable, and `tsum_mul_tsum_eq_tsum_sum_range_of_summable_norm'` when the + space is not complete. -/ theorem tsum_mul_tsum_eq_tsum_sum_range_of_summable_norm [CompleteSpace R] {f g : ℕ → R} (hf : Summable fun x => ‖f x‖) (hg : Summable fun x => ‖g x‖) : ((∑' n, f n) * ∑' n, g n) = ∑' n, ∑ k ∈ range (n + 1), f k * g (n - k) := by simp_rw [← sum_antidiagonal_eq_sum_range_succ fun k l => f k * g l] exact tsum_mul_tsum_eq_tsum_sum_antidiagonal_of_summable_norm hf hg +theorem hasSum_sum_range_mul_of_summable_norm [CompleteSpace R] {f g : ℕ → R} + (hf : Summable fun x => ‖f x‖) (hg : Summable fun x => ‖g x‖) : + HasSum (fun n ↦ ∑ k ∈ range (n + 1), f k * g (n - k)) ((∑' n, f n) * ∑' n, g n) := by + convert (summable_norm_sum_mul_range_of_summable_norm hf hg).of_norm.hasSum + exact tsum_mul_tsum_eq_tsum_sum_range_of_summable_norm hf hg + +theorem tsum_mul_tsum_eq_tsum_sum_range_of_summable_norm' {f g : ℕ → R} + (hf : Summable fun x => ‖f x‖) (h'f : Summable f) + (hg : Summable fun x => ‖g x‖) (h'g : Summable g) : + ((∑' n, f n) * ∑' n, g n) = ∑' n, ∑ k ∈ range (n + 1), f k * g (n - k) := by + simp_rw [← sum_antidiagonal_eq_sum_range_succ fun k l => f k * g l] + exact tsum_mul_tsum_eq_tsum_sum_antidiagonal_of_summable_norm' hf h'f hg h'g + +theorem hasSum_sum_range_mul_of_summable_norm' {f g : ℕ → R} + (hf : Summable fun x => ‖f x‖) (h'f : Summable f) + (hg : Summable fun x => ‖g x‖) (h'g : Summable g) : + HasSum (fun n ↦ ∑ k ∈ range (n + 1), f k * g (n - k)) ((∑' n, f n) * ∑' n, g n) := by + convert (summable_sum_mul_range_of_summable_norm' hf h'f hg h'g).hasSum + exact tsum_mul_tsum_eq_tsum_sum_range_of_summable_norm' hf h'f hg h'g + end Nat diff --git a/Mathlib/Analysis/Normed/Field/Lemmas.lean b/Mathlib/Analysis/Normed/Field/Lemmas.lean new file mode 100644 index 0000000000000..f56d61465db91 --- /dev/null +++ b/Mathlib/Analysis/Normed/Field/Lemmas.lean @@ -0,0 +1,335 @@ +/- +Copyright (c) 2018 Patrick Massot. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Patrick Massot, Johannes Hölzl +-/ + +import Mathlib.Algebra.Group.AddChar +import Mathlib.Algebra.Order.Ring.Finset +import Mathlib.Analysis.Normed.Field.Basic +import Mathlib.Analysis.Normed.Group.Bounded +import Mathlib.Analysis.Normed.Group.Rat +import Mathlib.Analysis.Normed.Group.Uniform +import Mathlib.Topology.Instances.NNReal +import Mathlib.Topology.MetricSpace.DilationEquiv + +/-! +# Normed fields + +In this file we continue building the theory of (semi)normed rings and fields. +-/ + +-- Guard against import creep. +assert_not_exists RestrictScalars + +variable {α : Type*} {β : Type*} {ι : Type*} + +open Filter Bornology +open scoped Topology NNReal Pointwise + +section NonUnitalSeminormedRing + +variable [NonUnitalSeminormedRing α] + +theorem Filter.Tendsto.zero_mul_isBoundedUnder_le {f g : ι → α} {l : Filter ι} + (hf : Tendsto f l (𝓝 0)) (hg : IsBoundedUnder (· ≤ ·) l ((‖·‖) ∘ g)) : + Tendsto (fun x => f x * g x) l (𝓝 0) := + hf.op_zero_isBoundedUnder_le hg (· * ·) norm_mul_le + +theorem Filter.isBoundedUnder_le_mul_tendsto_zero {f g : ι → α} {l : Filter ι} + (hf : IsBoundedUnder (· ≤ ·) l (norm ∘ f)) (hg : Tendsto g l (𝓝 0)) : + Tendsto (fun x => f x * g x) l (𝓝 0) := + hg.op_zero_isBoundedUnder_le hf (flip (· * ·)) fun x y => + (norm_mul_le y x).trans_eq (mul_comm _ _) + +/-- Non-unital seminormed ring structure on the product of finitely many non-unital seminormed +rings, using the sup norm. -/ +instance Pi.nonUnitalSeminormedRing {π : ι → Type*} [Fintype ι] + [∀ i, NonUnitalSeminormedRing (π i)] : NonUnitalSeminormedRing (∀ i, π i) := + { Pi.seminormedAddCommGroup, Pi.nonUnitalRing with + norm_mul := fun x y => + NNReal.coe_mono <| + calc + (Finset.univ.sup fun i => ‖x i * y i‖₊) ≤ + Finset.univ.sup ((fun i => ‖x i‖₊) * fun i => ‖y i‖₊) := + Finset.sup_mono_fun fun _ _ => norm_mul_le _ _ + _ ≤ (Finset.univ.sup fun i => ‖x i‖₊) * Finset.univ.sup fun i => ‖y i‖₊ := + Finset.sup_mul_le_mul_sup_of_nonneg _ (fun _ _ => zero_le _) fun _ _ => zero_le _ + } + +end NonUnitalSeminormedRing + +section SeminormedRing + +variable [SeminormedRing α] + +/-- Seminormed ring structure on the product of finitely many seminormed rings, + using the sup norm. -/ +instance Pi.seminormedRing {π : ι → Type*} [Fintype ι] [∀ i, SeminormedRing (π i)] : + SeminormedRing (∀ i, π i) := + { Pi.nonUnitalSeminormedRing, Pi.ring with } + +end SeminormedRing + +section NonUnitalNormedRing + +variable [NonUnitalNormedRing α] + +/-- Normed ring structure on the product of finitely many non-unital normed rings, using the sup +norm. -/ +instance Pi.nonUnitalNormedRing {π : ι → Type*} [Fintype ι] [∀ i, NonUnitalNormedRing (π i)] : + NonUnitalNormedRing (∀ i, π i) := + { Pi.nonUnitalSeminormedRing, Pi.normedAddCommGroup with } + +end NonUnitalNormedRing + +section NormedRing + +variable [NormedRing α] + +/-- Normed ring structure on the product of finitely many normed rings, using the sup norm. -/ +instance Pi.normedRing {π : ι → Type*} [Fintype ι] [∀ i, NormedRing (π i)] : + NormedRing (∀ i, π i) := + { Pi.seminormedRing, Pi.normedAddCommGroup with } + +end NormedRing + +section NonUnitalSeminormedCommRing + +variable [NonUnitalSeminormedCommRing α] + +/-- Non-unital seminormed commutative ring structure on the product of finitely many non-unital +seminormed commutative rings, using the sup norm. -/ +instance Pi.nonUnitalSeminormedCommRing {π : ι → Type*} [Fintype ι] + [∀ i, NonUnitalSeminormedCommRing (π i)] : NonUnitalSeminormedCommRing (∀ i, π i) := + { Pi.nonUnitalSeminormedRing, Pi.nonUnitalCommRing with } + +end NonUnitalSeminormedCommRing + +section NonUnitalNormedCommRing + +variable [NonUnitalNormedCommRing α] + +/-- Normed commutative ring structure on the product of finitely many non-unital normed +commutative rings, using the sup norm. -/ +instance Pi.nonUnitalNormedCommRing {π : ι → Type*} [Fintype ι] + [∀ i, NonUnitalNormedCommRing (π i)] : NonUnitalNormedCommRing (∀ i, π i) := + { Pi.nonUnitalSeminormedCommRing, Pi.normedAddCommGroup with } + +end NonUnitalNormedCommRing + +section SeminormedCommRing + +variable [SeminormedCommRing α] + +/-- Seminormed commutative ring structure on the product of finitely many seminormed commutative +rings, using the sup norm. -/ +instance Pi.seminormedCommRing {π : ι → Type*} [Fintype ι] [∀ i, SeminormedCommRing (π i)] : + SeminormedCommRing (∀ i, π i) := + { Pi.nonUnitalSeminormedCommRing, Pi.ring with } + +end SeminormedCommRing + +section NormedCommRing + +variable [NormedCommRing α] + +/-- Normed commutative ring structure on the product of finitely many normed commutative rings, +using the sup norm. -/ +instance Pi.normedCommutativeRing {π : ι → Type*} [Fintype ι] [∀ i, NormedCommRing (π i)] : + NormedCommRing (∀ i, π i) := + { Pi.seminormedCommRing, Pi.normedAddCommGroup with } + +end NormedCommRing + +-- see Note [lower instance priority] +instance (priority := 100) semi_normed_ring_top_monoid [NonUnitalSeminormedRing α] : + ContinuousMul α := + ⟨continuous_iff_continuousAt.2 fun x => + tendsto_iff_norm_sub_tendsto_zero.2 <| by + have : ∀ e : α × α, + ‖e.1 * e.2 - x.1 * x.2‖ ≤ ‖e.1‖ * ‖e.2 - x.2‖ + ‖e.1 - x.1‖ * ‖x.2‖ := by + intro e + calc + ‖e.1 * e.2 - x.1 * x.2‖ ≤ ‖e.1 * (e.2 - x.2) + (e.1 - x.1) * x.2‖ := by + rw [_root_.mul_sub, _root_.sub_mul, sub_add_sub_cancel] + -- Porting note: `ENNReal.{mul_sub, sub_mul}` should be protected + _ ≤ ‖e.1‖ * ‖e.2 - x.2‖ + ‖e.1 - x.1‖ * ‖x.2‖ := + norm_add_le_of_le (norm_mul_le _ _) (norm_mul_le _ _) + refine squeeze_zero (fun e => norm_nonneg _) this ?_ + convert + ((continuous_fst.tendsto x).norm.mul + ((continuous_snd.tendsto x).sub tendsto_const_nhds).norm).add + (((continuous_fst.tendsto x).sub tendsto_const_nhds).norm.mul _) + -- Porting note: `show` used to select a goal to work on + rotate_right + · show Tendsto _ _ _ + exact tendsto_const_nhds + · simp⟩ + +-- see Note [lower instance priority] +/-- A seminormed ring is a topological ring. -/ +instance (priority := 100) semi_normed_top_ring [NonUnitalSeminormedRing α] : + TopologicalRing α where + +section NormedDivisionRing + +variable [NormedDivisionRing α] {a : α} + +lemma antilipschitzWith_mul_left {a : α} (ha : a ≠ 0) : AntilipschitzWith (‖a‖₊⁻¹) (a * ·) := + AntilipschitzWith.of_le_mul_dist fun _ _ ↦ by simp [dist_eq_norm, ← _root_.mul_sub, ha] + +lemma antilipschitzWith_mul_right {a : α} (ha : a ≠ 0) : AntilipschitzWith (‖a‖₊⁻¹) (· * a) := + AntilipschitzWith.of_le_mul_dist fun _ _ ↦ by + simp [dist_eq_norm, ← _root_.sub_mul, ← mul_comm (‖a‖), ha] + +/-- Multiplication by a nonzero element `a` on the left +as a `DilationEquiv` of a normed division ring. -/ +@[simps!] +def DilationEquiv.mulLeft (a : α) (ha : a ≠ 0) : α ≃ᵈ α where + toEquiv := Equiv.mulLeft₀ a ha + edist_eq' := ⟨‖a‖₊, nnnorm_ne_zero_iff.2 ha, fun x y ↦ by + simp [edist_nndist, nndist_eq_nnnorm, ← mul_sub]⟩ + +/-- Multiplication by a nonzero element `a` on the right +as a `DilationEquiv` of a normed division ring. -/ +@[simps!] +def DilationEquiv.mulRight (a : α) (ha : a ≠ 0) : α ≃ᵈ α where + toEquiv := Equiv.mulRight₀ a ha + edist_eq' := ⟨‖a‖₊, nnnorm_ne_zero_iff.2 ha, fun x y ↦ by + simp [edist_nndist, nndist_eq_nnnorm, ← sub_mul, ← mul_comm (‖a‖₊)]⟩ + +namespace Filter + +@[simp] +lemma comap_mul_left_cobounded {a : α} (ha : a ≠ 0) : + comap (a * ·) (cobounded α) = cobounded α := + Dilation.comap_cobounded (DilationEquiv.mulLeft a ha) + +@[simp] +lemma map_mul_left_cobounded {a : α} (ha : a ≠ 0) : + map (a * ·) (cobounded α) = cobounded α := + DilationEquiv.map_cobounded (DilationEquiv.mulLeft a ha) + +@[simp] +lemma comap_mul_right_cobounded {a : α} (ha : a ≠ 0) : + comap (· * a) (cobounded α) = cobounded α := + Dilation.comap_cobounded (DilationEquiv.mulRight a ha) + +@[simp] +lemma map_mul_right_cobounded {a : α} (ha : a ≠ 0) : + map (· * a) (cobounded α) = cobounded α := + DilationEquiv.map_cobounded (DilationEquiv.mulRight a ha) + +/-- Multiplication on the left by a nonzero element of a normed division ring tends to infinity at +infinity. -/ +theorem tendsto_mul_left_cobounded {a : α} (ha : a ≠ 0) : + Tendsto (a * ·) (cobounded α) (cobounded α) := + (map_mul_left_cobounded ha).le + +/-- Multiplication on the right by a nonzero element of a normed division ring tends to infinity at +infinity. -/ +theorem tendsto_mul_right_cobounded {a : α} (ha : a ≠ 0) : + Tendsto (· * a) (cobounded α) (cobounded α) := + (map_mul_right_cobounded ha).le + +@[simp] +lemma inv_cobounded₀ : (cobounded α)⁻¹ = 𝓝[≠] 0 := by + rw [← comap_norm_atTop, ← Filter.comap_inv, ← comap_norm_nhdsWithin_Ioi_zero, + ← inv_atTop₀, ← Filter.comap_inv] + simp only [comap_comap, Function.comp_def, norm_inv] + +@[simp] +lemma inv_nhdsWithin_ne_zero : (𝓝[≠] (0 : α))⁻¹ = cobounded α := by + rw [← inv_cobounded₀, inv_inv] + +lemma tendsto_inv₀_cobounded' : Tendsto Inv.inv (cobounded α) (𝓝[≠] 0) := + inv_cobounded₀.le + +theorem tendsto_inv₀_cobounded : Tendsto Inv.inv (cobounded α) (𝓝 0) := + tendsto_inv₀_cobounded'.mono_right inf_le_left + +lemma tendsto_inv₀_nhdsWithin_ne_zero : Tendsto Inv.inv (𝓝[≠] 0) (cobounded α) := + inv_nhdsWithin_ne_zero.le + +end Filter + +-- see Note [lower instance priority] +instance (priority := 100) NormedDivisionRing.to_hasContinuousInv₀ : HasContinuousInv₀ α := by + refine ⟨fun r r0 => tendsto_iff_norm_sub_tendsto_zero.2 ?_⟩ + have r0' : 0 < ‖r‖ := norm_pos_iff.2 r0 + rcases exists_between r0' with ⟨ε, ε0, εr⟩ + have : ∀ᶠ e in 𝓝 r, ‖e⁻¹ - r⁻¹‖ ≤ ‖r - e‖ / ‖r‖ / ε := by + filter_upwards [(isOpen_lt continuous_const continuous_norm).eventually_mem εr] with e he + have e0 : e ≠ 0 := norm_pos_iff.1 (ε0.trans he) + calc + ‖e⁻¹ - r⁻¹‖ = ‖r‖⁻¹ * ‖r - e‖ * ‖e‖⁻¹ := by + rw [← norm_inv, ← norm_inv, ← norm_mul, ← norm_mul, _root_.mul_sub, _root_.sub_mul, + mul_assoc _ e, inv_mul_cancel₀ r0, mul_inv_cancel₀ e0, one_mul, mul_one] + -- Porting note: `ENNReal.{mul_sub, sub_mul}` should be `protected` + _ = ‖r - e‖ / ‖r‖ / ‖e‖ := by field_simp [mul_comm] + _ ≤ ‖r - e‖ / ‖r‖ / ε := by gcongr + refine squeeze_zero' (Eventually.of_forall fun _ => norm_nonneg _) this ?_ + refine (((continuous_const.sub continuous_id).norm.div_const _).div_const _).tendsto' _ _ ?_ + simp + +-- see Note [lower instance priority] +/-- A normed division ring is a topological division ring. -/ +instance (priority := 100) NormedDivisionRing.to_topologicalDivisionRing : + TopologicalDivisionRing α where + +protected lemma IsOfFinOrder.norm_eq_one (ha : IsOfFinOrder a) : ‖a‖ = 1 := + ((normHom : α →*₀ ℝ).toMonoidHom.isOfFinOrder ha).eq_one <| norm_nonneg _ + +example [Monoid β] (φ : β →* α) {x : β} {k : ℕ+} (h : x ^ (k : ℕ) = 1) : + ‖φ x‖ = 1 := (φ.isOfFinOrder <| isOfFinOrder_iff_pow_eq_one.2 ⟨_, k.2, h⟩).norm_eq_one + +@[simp] lemma AddChar.norm_apply {G : Type*} [AddLeftCancelMonoid G] [Finite G] (ψ : AddChar G α) + (x : G) : ‖ψ x‖ = 1 := (ψ.toMonoidHom.isOfFinOrder <| isOfFinOrder_of_finite _).norm_eq_one + +end NormedDivisionRing + +namespace NormedField + +section Densely + +variable (α) [DenselyNormedField α] + +theorem denseRange_nnnorm : DenseRange (nnnorm : α → ℝ≥0) := + dense_of_exists_between fun _ _ hr => + let ⟨x, h⟩ := exists_lt_nnnorm_lt α hr + ⟨‖x‖₊, ⟨x, rfl⟩, h⟩ + +end Densely + +end NormedField + +namespace NNReal + +lemma lipschitzWith_sub : LipschitzWith 2 (fun (p : ℝ≥0 × ℝ≥0) ↦ p.1 - p.2) := by + rw [← isometry_subtype_coe.lipschitzWith_iff] + have : Isometry (Prod.map ((↑) : ℝ≥0 → ℝ) ((↑) : ℝ≥0 → ℝ)) := + isometry_subtype_coe.prod_map isometry_subtype_coe + convert (((LipschitzWith.prod_fst.comp this.lipschitz).sub + (LipschitzWith.prod_snd.comp this.lipschitz)).max_const 0) + norm_num + +end NNReal + +instance Int.instNormedCommRing : NormedCommRing ℤ where + __ := instCommRing + __ := instNormedAddCommGroup + norm_mul m n := by simp only [norm, Int.cast_mul, abs_mul, le_rfl] + +instance Int.instNormOneClass : NormOneClass ℤ := + ⟨by simp [← Int.norm_cast_real]⟩ + +instance Rat.instNormedField : NormedField ℚ where + __ := instField + __ := instNormedAddCommGroup + norm_mul' a b := by simp only [norm, Rat.cast_mul, abs_mul] + +instance Rat.instDenselyNormedField : DenselyNormedField ℚ where + lt_norm_lt r₁ r₂ h₀ hr := + let ⟨q, h⟩ := exists_rat_btwn hr + ⟨q, by rwa [← Rat.norm_cast_real, Real.norm_eq_abs, abs_of_pos (h₀.trans_lt h.1)]⟩ diff --git a/Mathlib/Analysis/Normed/Field/UnitBall.lean b/Mathlib/Analysis/Normed/Field/UnitBall.lean index 8652d79164427..2817b533b7761 100644 --- a/Mathlib/Analysis/Normed/Field/UnitBall.lean +++ b/Mathlib/Analysis/Normed/Field/UnitBall.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 Yury Kudryashov. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov, Heather Macbeth -/ -import Mathlib.Analysis.Normed.Field.Basic +import Mathlib.Analysis.Normed.Field.Lemmas import Mathlib.Analysis.Normed.Group.BallSphere /-! diff --git a/Mathlib/Analysis/Normed/Group/Basic.lean b/Mathlib/Analysis/Normed/Group/Basic.lean index efa5924c33e43..bde983756cf20 100644 --- a/Mathlib/Analysis/Normed/Group/Basic.lean +++ b/Mathlib/Analysis/Normed/Group/Basic.lean @@ -544,7 +544,7 @@ theorem norm_lt_of_mem_ball' (h : b ∈ ball a r) : ‖b‖ < ‖a‖ + r := @[to_additive] theorem norm_div_sub_norm_div_le_norm_div (u v w : E) : ‖u / w‖ - ‖v / w‖ ≤ ‖u / v‖ := by - simpa only [div_div_div_cancel_right'] using norm_sub_norm_le' (u / w) (v / w) + simpa only [div_div_div_cancel_right] using norm_sub_norm_le' (u / w) (v / w) @[to_additive (attr := simp 1001) mem_sphere_iff_norm] -- Porting note: increase priority so the left-hand side doesn't reduce @@ -1152,24 +1152,26 @@ theorem norm_of_nonpos (hr : r ≤ 0) : ‖r‖ = -r := theorem le_norm_self (r : ℝ) : r ≤ ‖r‖ := le_abs_self r --- Porting note (#10618): `simp` can prove this -theorem norm_natCast (n : ℕ) : ‖(n : ℝ)‖ = n := - abs_of_nonneg n.cast_nonneg - -@[simp] -theorem nnnorm_natCast (n : ℕ) : ‖(n : ℝ)‖₊ = n := - NNReal.eq <| norm_natCast _ +@[simp 1100] lemma norm_natCast (n : ℕ) : ‖(n : ℝ)‖ = n := abs_of_nonneg n.cast_nonneg +@[simp 1100] lemma nnnorm_natCast (n : ℕ) : ‖(n : ℝ)‖₊ = n := NNReal.eq <| norm_natCast _ @[deprecated (since := "2024-04-05")] alias norm_coe_nat := norm_natCast @[deprecated (since := "2024-04-05")] alias nnnorm_coe_nat := nnnorm_natCast --- Porting note (#10618): `simp` can prove this -theorem norm_two : ‖(2 : ℝ)‖ = 2 := - abs_of_pos zero_lt_two +@[simp 1100] lemma norm_ofNat (n : ℕ) [n.AtLeastTwo] : + ‖(no_index (OfNat.ofNat n) : ℝ)‖ = OfNat.ofNat n := norm_natCast n -@[simp] -theorem nnnorm_two : ‖(2 : ℝ)‖₊ = 2 := - NNReal.eq <| by simp +@[simp 1100] lemma nnnorm_ofNat (n : ℕ) [n.AtLeastTwo] : + ‖(no_index (OfNat.ofNat n) : ℝ)‖₊ = OfNat.ofNat n := nnnorm_natCast n + +lemma norm_two : ‖(2 : ℝ)‖ = 2 := abs_of_pos zero_lt_two +lemma nnnorm_two : ‖(2 : ℝ)‖₊ = 2 := NNReal.eq <| by simp + +@[simp 1100, norm_cast] +lemma norm_nnratCast (q : ℚ≥0) : ‖(q : ℝ)‖ = q := norm_of_nonneg q.cast_nonneg + +@[simp 1100, norm_cast] +lemma nnnorm_nnratCast (q : ℚ≥0) : ‖(q : ℝ)‖₊ = q := by simp [nnnorm, -norm_eq_abs] theorem nnnorm_of_nonneg (hr : 0 ≤ r) : ‖r‖₊ = ⟨r, hr⟩ := NNReal.eq <| norm_of_nonneg hr diff --git a/Mathlib/Analysis/Normed/Group/Bounded.lean b/Mathlib/Analysis/Normed/Group/Bounded.lean index 9a4c7dac9e078..329d2bfa734ce 100644 --- a/Mathlib/Analysis/Normed/Group/Bounded.lean +++ b/Mathlib/Analysis/Normed/Group/Bounded.lean @@ -59,7 +59,7 @@ lemma tendsto_norm_cocompact_atTop' [ProperSpace E] : Tendsto norm (cocompact E) @[to_additive (attr := simp)] lemma Filter.inv_cobounded : (cobounded E)⁻¹ = cobounded E := by - simp only [← comap_norm_atTop', ← Filter.comap_inv, comap_comap, (· ∘ ·), norm_inv'] + simp only [← comap_norm_atTop', ← Filter.comap_inv, comap_comap, Function.comp_def, norm_inv'] /-- In a (semi)normed group, inversion `x ↦ x⁻¹` tends to infinity at infinity. -/ @[to_additive "In a (semi)normed group, negation `x ↦ -x` tends to infinity at infinity."] diff --git a/Mathlib/Analysis/Normed/Group/Completeness.lean b/Mathlib/Analysis/Normed/Group/Completeness.lean index 6390ce5cd3cc9..8fee862ad3d6d 100644 --- a/Mathlib/Analysis/Normed/Group/Completeness.lean +++ b/Mathlib/Analysis/Normed/Group/Completeness.lean @@ -51,7 +51,7 @@ section Normed variable {E : Type*} [NormedAddCommGroup E] /-- A normed additive group is complete if any absolutely convergent series converges in the -space. -/ +space. -/ lemma NormedAddCommGroup.completeSpace_of_summable_imp_tendsto (h : ∀ u : ℕ → E, Summable (‖u ·‖) → ∃ a, Tendsto (fun n => ∑ i ∈ range n, u i) atTop (𝓝 a)) : @@ -73,14 +73,14 @@ lemma NormedAddCommGroup.completeSpace_of_summable_imp_tendsto simpa only [sub_add_cancel] using h₁ /-- In a complete normed additive group, every absolutely convergent series converges in the -space. -/ +space. -/ lemma NormedAddCommGroup.summable_imp_tendsto_of_complete [CompleteSpace E] (u : ℕ → E) (hu : Summable (‖u ·‖)) : ∃ a, Tendsto (fun n => ∑ i ∈ range n, u i) atTop (𝓝 a) := by refine cauchySeq_tendsto_of_complete <| cauchySeq_of_summable_dist ?_ simp [dist_eq_norm, sum_range_succ, hu] /-- In a normed additive group, every absolutely convergent series converges in the -space iff the space is complete. -/ +space iff the space is complete. -/ lemma NormedAddCommGroup.summable_imp_tendsto_iff_completeSpace : (∀ u : ℕ → E, Summable (‖u ·‖) → ∃ a, Tendsto (fun n => ∑ i ∈ range n, u i) atTop (𝓝 a)) ↔ CompleteSpace E := diff --git a/Mathlib/Analysis/Normed/Group/Hom.lean b/Mathlib/Analysis/Normed/Group/Hom.lean index 50127f79f7499..9f1984fa88764 100644 --- a/Mathlib/Analysis/Normed/Group/Hom.lean +++ b/Mathlib/Analysis/Normed/Group/Hom.lean @@ -208,8 +208,8 @@ theorem le_opNorm (x : V₁) : ‖f x‖ ≤ ‖f‖ * ‖x‖ := by · rwa [h, mul_zero] at hC ⊢ have hlt : 0 < ‖x‖ := lt_of_le_of_ne (norm_nonneg x) (Ne.symm h) exact - (div_le_iff hlt).mp - (le_csInf bounds_nonempty fun c ⟨_, hc⟩ => (div_le_iff hlt).mpr <| by apply hc) + (div_le_iff₀ hlt).mp + (le_csInf bounds_nonempty fun c ⟨_, hc⟩ => (div_le_iff₀ hlt).mpr <| by apply hc) theorem le_opNorm_of_le {c : ℝ} {x} (h : ‖x‖ ≤ c) : ‖f x‖ ≤ ‖f‖ * c := le_trans (f.le_opNorm x) (by gcongr; exact f.opNorm_nonneg) @@ -532,7 +532,7 @@ instance toNormedAddCommGroup {V₁ V₂ : Type*} [NormedAddCommGroup V₁] [Nor add_le' := opNorm_add_le eq_zero_of_map_eq_zero' := fun _f => opNorm_zero_iff.1 } -/-- Coercion of a `NormedAddGroupHom` is an `AddMonoidHom`. Similar to `AddMonoidHom.coeFn`. -/ +/-- Coercion of a `NormedAddGroupHom` is an `AddMonoidHom`. Similar to `AddMonoidHom.coeFn`. -/ @[simps] def coeAddHom : NormedAddGroupHom V₁ V₂ →+ V₁ → V₂ where toFun := DFunLike.coe @@ -656,7 +656,7 @@ theorem mem_ker (v : V₁) : v ∈ f.ker ↔ f v = 0 := by @[simps] def ker.lift (h : g.comp f = 0) : NormedAddGroupHom V₁ g.ker where toFun v := ⟨f v, by rw [g.mem_ker, ← comp_apply g f, h, zero_apply]⟩ - map_add' v w := by simp only [map_add, AddSubmonoid.mk_add_mk] + map_add' v w := by simp only [map_add, AddMemClass.mk_add_mk] bound' := f.bound' @[simp] diff --git a/Mathlib/Analysis/Normed/Group/Pointwise.lean b/Mathlib/Analysis/Normed/Group/Pointwise.lean index dc38a34ea6770..ae8862a8aa948 100644 --- a/Mathlib/Analysis/Normed/Group/Pointwise.lean +++ b/Mathlib/Analysis/Normed/Group/Pointwise.lean @@ -67,8 +67,8 @@ theorem infEdist_inv (x : E) (s : Set E) : infEdist x⁻¹ s = infEdist x s⁻¹ @[to_additive] theorem ediam_mul_le (x y : Set E) : EMetric.diam (x * y) ≤ EMetric.diam x + EMetric.diam y := (LipschitzOnWith.ediam_image2_le (· * ·) _ _ - (fun _ _ => (isometry_mul_right _).lipschitz.lipschitzOnWith _) fun _ _ => - (isometry_mul_left _).lipschitz.lipschitzOnWith _).trans_eq <| + (fun _ _ => (isometry_mul_right _).lipschitz.lipschitzOnWith) fun _ _ => + (isometry_mul_left _).lipschitz.lipschitzOnWith).trans_eq <| by simp only [ENNReal.coe_one, one_mul] end EMetric diff --git a/Mathlib/Analysis/Normed/Group/Quotient.lean b/Mathlib/Analysis/Normed/Group/Quotient.lean index 7406b8e2cf248..085dab581687e 100644 --- a/Mathlib/Analysis/Normed/Group/Quotient.lean +++ b/Mathlib/Analysis/Normed/Group/Quotient.lean @@ -213,7 +213,7 @@ theorem quotient_nhd_basis (S : AddSubgroup M) : refine fun ε ↦ Set.ext <| forall_mk.2 fun x ↦ ?_ rw [ball_zero_eq, mem_setOf_eq, norm_lt_iff, mem_image] exact exists_congr fun _ ↦ and_comm - rw [← mk_zero, nhds_eq, ← funext this] + rw [← QuotientAddGroup.mk_zero, nhds_eq, ← funext this] exact .map _ Metric.nhds_basis_ball /-- The seminormed group structure on the quotient by an additive subgroup. -/ diff --git a/Mathlib/Analysis/Normed/Group/SemiNormedGrp/Kernels.lean b/Mathlib/Analysis/Normed/Group/SemiNormedGrp/Kernels.lean index 13db71e0908f2..1f32d6b23b009 100644 --- a/Mathlib/Analysis/Normed/Group/SemiNormedGrp/Kernels.lean +++ b/Mathlib/Analysis/Normed/Group/SemiNormedGrp/Kernels.lean @@ -124,7 +124,7 @@ instance hasLimit_parallelPair {V W : SemiNormedGrp.{u}} (f g : V ⟶ W) : show NormedAddGroupHom.compHom (f - g) c.ι = 0 by rw [AddMonoidHom.map_sub, AddMonoidHom.sub_apply, sub_eq_zero]; exact c.condition) (fun c => NormedAddGroupHom.ker.incl_comp_lift _ _ _) fun c g h => by - -- Porting note: the `simp_rw` was was `rw [← h]` but motive is not type correct in mathlib4 + -- Porting note: the `simp_rw` was `rw [← h]` but motive is not type correct in mathlib4 ext x; dsimp; simp_rw [← h]; rfl} instance : Limits.HasEqualizers.{u, u + 1} SemiNormedGrp := diff --git a/Mathlib/Analysis/Normed/Group/Uniform.lean b/Mathlib/Analysis/Normed/Group/Uniform.lean index 5a5962ff3c7b7..42621d3976ca7 100644 --- a/Mathlib/Analysis/Normed/Group/Uniform.lean +++ b/Mathlib/Analysis/Normed/Group/Uniform.lean @@ -258,28 +258,65 @@ lemma lipschitzOnWith_inv_iff : LipschitzOnWith K f⁻¹ s ↔ LipschitzOnWith K lemma locallyLipschitz_inv_iff : LocallyLipschitz f⁻¹ ↔ LocallyLipschitz f := by simp [LocallyLipschitz] +@[to_additive (attr := simp)] +lemma locallyLipschitzOn_inv_iff : LocallyLipschitzOn s f⁻¹ ↔ LocallyLipschitzOn s f := by + simp [LocallyLipschitzOn] + @[to_additive] alias ⟨LipschitzWith.of_inv, LipschitzWith.inv⟩ := lipschitzWith_inv_iff @[to_additive] alias ⟨AntilipschitzWith.of_inv, AntilipschitzWith.inv⟩ := antilipschitzWith_inv_iff @[to_additive] alias ⟨LipschitzOnWith.of_inv, LipschitzOnWith.inv⟩ := lipschitzOnWith_inv_iff @[to_additive] alias ⟨LocallyLipschitz.of_inv, LocallyLipschitz.inv⟩ := locallyLipschitz_inv_iff +@[to_additive] +alias ⟨LocallyLipschitzOn.of_inv, LocallyLipschitzOn.inv⟩ := locallyLipschitzOn_inv_iff -namespace LipschitzWith - -@[to_additive add] -theorem mul' (hf : LipschitzWith Kf f) (hg : LipschitzWith Kg g) : - LipschitzWith (Kf + Kg) fun x => f x * g x := fun x y => +@[to_additive] +lemma LipschitzOnWith.mul (hf : LipschitzOnWith Kf f s) (hg : LipschitzOnWith Kg g s) : + LipschitzOnWith (Kf + Kg) (fun x ↦ f x * g x) s := fun x hx y hy ↦ calc edist (f x * g x) (f y * g y) ≤ edist (f x) (f y) + edist (g x) (g y) := edist_mul_mul_le _ _ _ _ - _ ≤ Kf * edist x y + Kg * edist x y := add_le_add (hf x y) (hg x y) + _ ≤ Kf * edist x y + Kg * edist x y := add_le_add (hf hx hy) (hg hx hy) _ = (Kf + Kg) * edist x y := (add_mul _ _ _).symm @[to_additive] -theorem div (hf : LipschitzWith Kf f) (hg : LipschitzWith Kg g) : +lemma LipschitzWith.mul (hf : LipschitzWith Kf f) (hg : LipschitzWith Kg g) : + LipschitzWith (Kf + Kg) fun x ↦ f x * g x := by + simpa [← lipschitzOnWith_univ] using hf.lipschitzOnWith.mul hg.lipschitzOnWith + +@[deprecated (since := "2024-08-25")] alias LipschitzWith.mul' := LipschitzWith.mul + +@[to_additive] +lemma LocallyLipschitzOn.mul (hf : LocallyLipschitzOn s f) (hg : LocallyLipschitzOn s g) : + LocallyLipschitzOn s fun x ↦ f x * g x := fun x hx ↦ by + obtain ⟨Kf, t, ht, hKf⟩ := hf hx + obtain ⟨Kg, u, hu, hKg⟩ := hg hx + exact ⟨Kf + Kg, t ∩ u, inter_mem ht hu, + (hKf.mono Set.inter_subset_left).mul (hKg.mono Set.inter_subset_right)⟩ + +@[to_additive] +lemma LocallyLipschitz.mul (hf : LocallyLipschitz f) (hg : LocallyLipschitz g) : + LocallyLipschitz fun x ↦ f x * g x := by + simpa [← locallyLipschitzOn_univ] using hf.locallyLipschitzOn.mul hg.locallyLipschitzOn + +@[to_additive] +lemma LipschitzOnWith.div (hf : LipschitzOnWith Kf f s) (hg : LipschitzOnWith Kg g s) : + LipschitzOnWith (Kf + Kg) (fun x ↦ f x / g x) s := by + simpa only [div_eq_mul_inv] using hf.mul hg.inv + +@[to_additive] +theorem LipschitzWith.div (hf : LipschitzWith Kf f) (hg : LipschitzWith Kg g) : LipschitzWith (Kf + Kg) fun x => f x / g x := by - simpa only [div_eq_mul_inv] using hf.mul' hg.inv + simpa only [div_eq_mul_inv] using hf.mul hg.inv + +@[to_additive] +lemma LocallyLipschitzOn.div (hf : LocallyLipschitzOn s f) (hg : LocallyLipschitzOn s g) : + LocallyLipschitzOn s fun x ↦ f x / g x := by + simpa only [div_eq_mul_inv] using hf.mul hg.inv -end LipschitzWith +@[to_additive] +lemma LocallyLipschitz.div (hf : LocallyLipschitz f) (hg : LocallyLipschitz g) : + LocallyLipschitz fun x ↦ f x / g x := by + simpa only [div_eq_mul_inv] using hf.mul hg.inv namespace AntilipschitzWith @@ -289,7 +326,7 @@ theorem mul_lipschitzWith (hf : AntilipschitzWith Kf f) (hg : LipschitzWith Kg g letI : PseudoMetricSpace α := PseudoEMetricSpace.toPseudoMetricSpace hf.edist_ne_top refine AntilipschitzWith.of_le_mul_dist fun x y => ?_ rw [NNReal.coe_inv, ← _root_.div_eq_inv_mul] - rw [le_div_iff (NNReal.coe_pos.2 <| tsub_pos_iff_lt.2 hK)] + rw [le_div_iff₀ (NNReal.coe_pos.2 <| tsub_pos_iff_lt.2 hK)] rw [mul_comm, NNReal.coe_sub hK.le, _root_.sub_mul] -- Porting note: `ENNReal.sub_mul` should be `protected`? calc @@ -312,7 +349,7 @@ end PseudoEMetricSpace -- See note [lower instance priority] @[to_additive] instance (priority := 100) SeminormedCommGroup.to_lipschitzMul : LipschitzMul E := - ⟨⟨1 + 1, LipschitzWith.prod_fst.mul' LipschitzWith.prod_snd⟩⟩ + ⟨⟨1 + 1, LipschitzWith.prod_fst.mul LipschitzWith.prod_snd⟩⟩ -- See note [lower instance priority] /-- A seminormed group is a uniform group, i.e., multiplication and division are uniformly diff --git a/Mathlib/Analysis/Normed/Lp/LpEquiv.lean b/Mathlib/Analysis/Normed/Lp/LpEquiv.lean index d43a285b86665..8be09ea3634f1 100644 --- a/Mathlib/Analysis/Normed/Lp/LpEquiv.lean +++ b/Mathlib/Analysis/Normed/Lp/LpEquiv.lean @@ -72,7 +72,7 @@ theorem coe_equiv_lpPiLp_symm (f : PiLp p E) : (Equiv.lpPiLp.symm f : ∀ i, E i def AddEquiv.lpPiLp : lp E p ≃+ PiLp p E := { Equiv.lpPiLp with map_add' := fun _f _g ↦ rfl } -theorem coe_addEquiv_lpPiLp (f : lp E p) : AddEquiv.lpPiLp f = ⇑f := +theorem coe_addEquiv_lpPiLp (f : lp E p) : AddEquiv.lpPiLp f = ⇑f := rfl theorem coe_addEquiv_lpPiLp_symm (f : PiLp p E) : diff --git a/Mathlib/Analysis/Normed/Lp/PiLp.lean b/Mathlib/Analysis/Normed/Lp/PiLp.lean index a1f0fe08603c7..aed43fb34f51d 100644 --- a/Mathlib/Analysis/Normed/Lp/PiLp.lean +++ b/Mathlib/Analysis/Normed/Lp/PiLp.lean @@ -342,11 +342,8 @@ abbrev pseudoMetricAux : PseudoMetricSpace (PiLp p α) := rcases p.dichotomy with (rfl | h) · exact iSup_edist_ne_top_aux f g · rw [edist_eq_sum (zero_lt_one.trans_le h)] - exact - ENNReal.rpow_ne_top_of_nonneg (one_div_nonneg.2 (zero_le_one.trans h)) - (ne_of_lt <| - ENNReal.sum_lt_top fun i hi => - ENNReal.rpow_ne_top_of_nonneg (zero_le_one.trans h) (edist_ne_top _ _))) + exact ENNReal.rpow_ne_top_of_nonneg (by positivity) <| ENNReal.sum_ne_top.2 fun _ _ ↦ + ENNReal.rpow_ne_top_of_nonneg (by positivity) (edist_ne_top _ _)) fun f g => by rcases p.dichotomy with (rfl | h) · rw [edist_eq_iSup, dist_eq_iSup] @@ -643,7 +640,7 @@ variable (p 𝕜) variable (E : Type*) [SeminormedAddCommGroup E] [Module 𝕜 E] /-- An equivalence of finite domains induces a linearly isometric equivalence of finitely supported -functions-/ +functions -/ def _root_.LinearIsometryEquiv.piLpCongrLeft (e : ι ≃ ι') : (PiLp p fun _ : ι => E) ≃ₗᵢ[𝕜] PiLp p fun _ : ι' => E where toLinearEquiv := LinearEquiv.piCongrLeft' 𝕜 (fun _ : ι => E) e @@ -666,13 +663,8 @@ theorem _root_.LinearIsometryEquiv.piLpCongrLeft_apply (e : ι ≃ ι') (v : PiL theorem _root_.LinearIsometryEquiv.piLpCongrLeft_symm (e : ι ≃ ι') : (LinearIsometryEquiv.piLpCongrLeft p 𝕜 E e).symm = LinearIsometryEquiv.piLpCongrLeft p 𝕜 E e.symm := - LinearIsometryEquiv.ext fun z => by -- Porting note: was `rfl` - simp only [LinearIsometryEquiv.piLpCongrLeft, LinearIsometryEquiv.symm, - LinearIsometryEquiv.coe_mk] - unfold PiLp WithLp - ext - simp only [LinearEquiv.piCongrLeft'_symm_apply, eq_rec_constant, - LinearEquiv.piCongrLeft'_apply, Equiv.symm_symm_apply] + LinearIsometryEquiv.ext fun z ↦ -- Porting note: was `rfl` + congr_arg (Equiv.toFun · z) (Equiv.piCongrLeft'_symm _ _) @[simp high] theorem _root_.LinearIsometryEquiv.piLpCongrLeft_single [DecidableEq ι] [DecidableEq ι'] @@ -944,7 +936,7 @@ nonrec theorem basis_toMatrix_basisFun_mul [Fintype ι] Matrix.of fun i j => b.repr ((WithLp.equiv _ _).symm (Aᵀ j)) i := by have := basis_toMatrix_basisFun_mul (b.map (WithLp.linearEquiv _ 𝕜 _)) A simp_rw [← PiLp.basisFun_map p, Basis.map_repr, LinearEquiv.trans_apply, - WithLp.linearEquiv_symm_apply, Basis.toMatrix_map, Function.comp, Basis.map_apply, + WithLp.linearEquiv_symm_apply, Basis.toMatrix_map, Function.comp_def, Basis.map_apply, LinearEquiv.symm_apply_apply] at this exact this diff --git a/Mathlib/Analysis/Normed/Lp/ProdLp.lean b/Mathlib/Analysis/Normed/Lp/ProdLp.lean index 6d23a952e2391..2a1f93a89b099 100644 --- a/Mathlib/Analysis/Normed/Lp/ProdLp.lean +++ b/Mathlib/Analysis/Normed/Lp/ProdLp.lean @@ -325,7 +325,7 @@ def prodPseudoEMetricAux [PseudoEMetricSpace α] [PseudoEMetricSpace β] : (if · = 0 then edist f.fst g.fst else edist f.snd g.snd) (if · = 0 then edist g.fst h.fst else edist g.snd h.snd) hp simp only [Finset.mem_singleton, not_false_eq_true, Finset.sum_insert, - Finset.sum_singleton] at this + Finset.sum_singleton, reduceCtorEq] at this exact this attribute [local instance] WithLp.prodPseudoEMetricAux diff --git a/Mathlib/Analysis/Normed/Lp/WithLp.lean b/Mathlib/Analysis/Normed/Lp/WithLp.lean index b636322d0d7e8..d921359dcb5a5 100644 --- a/Mathlib/Analysis/Normed/Lp/WithLp.lean +++ b/Mathlib/Analysis/Normed/Lp/WithLp.lean @@ -46,7 +46,7 @@ instance, on `Prod` and finite `Pi` types). -/ @[nolint unusedArguments] def WithLp (_p : ℝ≥0∞) (V : Type uV) : Type uV := V -variable (p : ℝ≥0∞) (K : Type uK) (K' : Type uK') (V : Type uV) +variable (p : ℝ≥0∞) (K : Type uK) (K' : Type uK') (V : Type uV) namespace WithLp diff --git a/Mathlib/Analysis/Normed/Lp/lpSpace.lean b/Mathlib/Analysis/Normed/Lp/lpSpace.lean index 8bfe697508229..dfe8bef80fdec 100644 --- a/Mathlib/Analysis/Normed/Lp/lpSpace.lean +++ b/Mathlib/Analysis/Normed/Lp/lpSpace.lean @@ -595,7 +595,7 @@ theorem norm_const_smul_le (hp : p ≠ 0) (c : 𝕜) (f : lp E p) : ‖c • f · simp [lp.eq_zero' f] have hcf := lp.isLUB_norm (c • f) have hfc := (lp.isLUB_norm f).mul_left (norm_nonneg c) - simp_rw [← Set.range_comp, Function.comp] at hfc + simp_rw [← Set.range_comp, Function.comp_def] at hfc -- TODO: some `IsLUB` API should make it a one-liner from here. refine hcf.right ?_ have := hfc.left diff --git a/Mathlib/Analysis/Normed/Module/Basic.lean b/Mathlib/Analysis/Normed/Module/Basic.lean index 4541f328011b9..a14d459bc6280 100644 --- a/Mathlib/Analysis/Normed/Module/Basic.lean +++ b/Mathlib/Analysis/Normed/Module/Basic.lean @@ -8,7 +8,7 @@ import Mathlib.Algebra.Algebra.Prod import Mathlib.Algebra.Algebra.Rat import Mathlib.Algebra.Algebra.RestrictScalars import Mathlib.Algebra.Module.Rat -import Mathlib.Analysis.Normed.Field.Basic +import Mathlib.Analysis.Normed.Field.Lemmas import Mathlib.Analysis.Normed.MulAction /-! @@ -455,8 +455,10 @@ Please consider using `IsScalarTower` and/or `RestrictScalars 𝕜 𝕜' E` inst This definition allows the `RestrictScalars.normedSpace` instance to be put directly on `E` rather on `RestrictScalars 𝕜 𝕜' E`. This would be a very bad instance; both because `𝕜'` cannot be inferred, and because it is likely to create instance diamonds. + +See Note [reducible non-instances]. -/ -def NormedSpace.restrictScalars : NormedSpace 𝕜 E := +abbrev NormedSpace.restrictScalars : NormedSpace 𝕜 E := RestrictScalars.normedSpace _ 𝕜' E end NormedSpace @@ -488,8 +490,10 @@ Please consider using `IsScalarTower` and/or `RestrictScalars 𝕜 𝕜' E` inst This definition allows the `RestrictScalars.normedAlgebra` instance to be put directly on `E` rather on `RestrictScalars 𝕜 𝕜' E`. This would be a very bad instance; both because `𝕜'` cannot be inferred, and because it is likely to create instance diamonds. + +See Note [reducible non-instances]. -/ -def NormedAlgebra.restrictScalars : NormedAlgebra 𝕜 E := +abbrev NormedAlgebra.restrictScalars : NormedAlgebra 𝕜 E := RestrictScalars.normedAlgebra _ 𝕜' _ end NormedAlgebra diff --git a/Mathlib/Analysis/Normed/Module/Completion.lean b/Mathlib/Analysis/Normed/Module/Completion.lean index 4e50f3b1130b0..451aed37e833c 100644 --- a/Mathlib/Analysis/Normed/Module/Completion.lean +++ b/Mathlib/Analysis/Normed/Module/Completion.lean @@ -6,6 +6,7 @@ Authors: Yury Kudryashov import Mathlib.Analysis.Normed.Group.Completion import Mathlib.Analysis.NormedSpace.OperatorNorm.NormedSpace import Mathlib.Topology.Algebra.UniformRing +import Mathlib.Topology.Algebra.UniformField /-! # Normed space structure on the completion of a normed space @@ -100,6 +101,13 @@ instance [SeminormedCommRing A] [NormedAlgebra 𝕜 A] [UniformContinuousConstSM simp only [← coe_smul, norm_coe] exact norm_smul_le r x } +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) + norm_mul' x y := induction_on₂ x y (isClosed_eq (by fun_prop) (by fun_prop)) (by simp [← coe_mul]) + end Algebra end Completion diff --git a/Mathlib/Analysis/Normed/Module/Dual.lean b/Mathlib/Analysis/Normed/Module/Dual.lean index de23a0957c44e..91bfbe1dc1f82 100644 --- a/Mathlib/Analysis/Normed/Module/Dual.lean +++ b/Mathlib/Analysis/Normed/Module/Dual.lean @@ -6,6 +6,7 @@ Authors: Heather Macbeth import Mathlib.Analysis.NormedSpace.HahnBanach.Extension import Mathlib.Analysis.NormedSpace.RCLike import Mathlib.Analysis.LocallyConvex.Polar +import Mathlib.Data.Set.Finite /-! # The topological dual of a normed space @@ -28,9 +29,13 @@ theory for `SeminormedAddCommGroup` and we specialize to `NormedAddCommGroup` wh * `polar 𝕜 s` is the subset of `Dual 𝕜 E` consisting of those functionals `x'` for which `‖x' z‖ ≤ 1` for every `z ∈ s`. +## References + +* [Conway, John B., A course in functional analysis][conway1990] + ## Tags -dual +dual, polar -/ @@ -224,6 +229,23 @@ theorem polar_closedBall {𝕜 E : Type*} [RCLike 𝕜] [NormedAddCommGroup E] [ refine ContinuousLinearMap.opNorm_le_of_ball hr (inv_nonneg.mpr hr.le) fun z _ => ?_ simpa only [one_div] using LinearMap.bound_of_ball_bound' hr 1 x'.toLinearMap h z +theorem polar_ball {𝕜 E : Type*} [RCLike 𝕜] [NormedAddCommGroup E] [NormedSpace 𝕜 E] {r : ℝ} + (hr : 0 < r) : polar 𝕜 (ball (0 : E) r) = closedBall (0 : Dual 𝕜 E) r⁻¹ := by + apply le_antisymm + · intro x hx + rw [mem_closedBall_zero_iff] + apply le_of_forall_le_of_dense + 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)))] + 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 + · rw [← polar_closedBall hr] + exact LinearMap.polar_antitone _ ball_subset_closedBall + /-- Given a neighborhood `s` of the origin in a normed space `E`, the dual norms of all elements of the polar `polar 𝕜 s` are bounded by a constant. -/ theorem isBounded_polar_of_mem_nhds_zero {s : Set E} (s_nhd : s ∈ 𝓝 (0 : E)) : @@ -234,6 +256,20 @@ theorem isBounded_polar_of_mem_nhds_zero {s : Set E} (s_nhd : s ∈ 𝓝 (0 : E) (((dualPairing 𝕜 E).flip.polar_antitone r_ball).trans <| polar_ball_subset_closedBall_div ha r_pos) +@[simp] +theorem polar_singleton {a : E} : polar 𝕜 {a} = { x | ‖x a‖ ≤ 1 } := by + simp only [polar, LinearMap.polar_singleton, LinearMap.flip_apply, dualPairing_apply] + +theorem mem_polar_singleton {a : E} (y : Dual 𝕜 E) : y ∈ polar 𝕜 {a} ↔ ‖y a‖ ≤ 1 := by + simp only [polar_singleton, mem_setOf_eq] + +theorem sInter_polar_eq_closedBall {𝕜 E : Type*} [RCLike 𝕜] [NormedAddCommGroup E] [NormedSpace 𝕜 E] + {r : ℝ} (hr : 0 < r) : + ⋂₀ (polar 𝕜 '' { F | F.Finite ∧ F ⊆ closedBall (0 : E) r⁻¹ }) = closedBall 0 r := by + conv_rhs => rw [← inv_inv r] + rw [← polar_closedBall (inv_pos_of_pos hr), polar, + (dualPairing 𝕜 E).flip.sInter_polar_finite_subset_eq_polar (closedBall (0 : E) r⁻¹)] + end PolarSets end NormedSpace diff --git a/Mathlib/Analysis/Normed/MulAction.lean b/Mathlib/Analysis/Normed/MulAction.lean index 618fab80dff3f..1c42cc236b1e9 100644 --- a/Mathlib/Analysis/Normed/MulAction.lean +++ b/Mathlib/Analysis/Normed/MulAction.lean @@ -3,8 +3,8 @@ Copyright (c) 2023 Eric Wieser. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Eric Wieser -/ -import Mathlib.Topology.MetricSpace.Algebra import Mathlib.Analysis.Normed.Field.Basic +import Mathlib.Topology.MetricSpace.Algebra /-! # Lemmas for `BoundedSMul` over normed additive groups diff --git a/Mathlib/Analysis/Normed/Operator/Banach.lean b/Mathlib/Analysis/Normed/Operator/Banach.lean index 5d6eca063bbe1..8561d451ba771 100644 --- a/Mathlib/Analysis/Normed/Operator/Banach.lean +++ b/Mathlib/Analysis/Normed/Operator/Banach.lean @@ -531,7 +531,7 @@ section BijectivityCriteria namespace ContinuousLinearMap -variable {σ : 𝕜 →+* 𝕜'} {σ' : 𝕜' →+* 𝕜} [RingHomInvPair σ σ'] {f : E →SL[σ] F} +variable {σ : 𝕜 →+* 𝕜'} {σ' : 𝕜' →+* 𝕜} [RingHomInvPair σ σ'] {f : E →SL[σ] F} variable {F : Type u_4} [NormedAddCommGroup F] [NormedSpace 𝕜' F] variable [CompleteSpace E] diff --git a/Mathlib/Analysis/Normed/Operator/BoundedLinearMaps.lean b/Mathlib/Analysis/Normed/Operator/BoundedLinearMaps.lean index 439ff7a017041..114bd3205cea4 100644 --- a/Mathlib/Analysis/Normed/Operator/BoundedLinearMaps.lean +++ b/Mathlib/Analysis/Normed/Operator/BoundedLinearMaps.lean @@ -315,8 +315,8 @@ def IsBoundedBilinearMap.toContinuousLinearMap (hf : IsBoundedBilinearMap 𝕜 f protected theorem IsBoundedBilinearMap.isBigO (h : IsBoundedBilinearMap 𝕜 f) : f =O[⊤] fun p : E × F => ‖p.1‖ * ‖p.2‖ := - let ⟨C, Cpos, hC⟩ := h.bound - Asymptotics.IsBigO.of_bound _ <| + let ⟨C, _, hC⟩ := h.bound + Asymptotics.IsBigO.of_bound C <| Filter.Eventually.of_forall fun ⟨x, y⟩ => by simpa [mul_assoc] using hC x y theorem IsBoundedBilinearMap.isBigO_comp {α : Type*} (H : IsBoundedBilinearMap 𝕜 f) {g : α → E} diff --git a/Mathlib/Analysis/Normed/Operator/ContinuousLinearMap.lean b/Mathlib/Analysis/Normed/Operator/ContinuousLinearMap.lean index da7b7a93c50c0..eedbaba72b905 100644 --- a/Mathlib/Analysis/Normed/Operator/ContinuousLinearMap.lean +++ b/Mathlib/Analysis/Normed/Operator/ContinuousLinearMap.lean @@ -3,8 +3,9 @@ Copyright (c) 2019 Jan-David Salchow. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jan-David Salchow, Sébastien Gouëzel, Jean Lo -/ -import Mathlib.Topology.Algebra.Module.Basic +import Mathlib.Analysis.Normed.Group.Uniform import Mathlib.Analysis.Normed.MulAction +import Mathlib.Topology.Algebra.Module.Basic /-! # Constructions of continuous linear maps between (semi-)normed spaces diff --git a/Mathlib/Analysis/Normed/Operator/LinearIsometry.lean b/Mathlib/Analysis/Normed/Operator/LinearIsometry.lean index dcba3cf3c238e..578fd81859e6d 100644 --- a/Mathlib/Analysis/Normed/Operator/LinearIsometry.lean +++ b/Mathlib/Analysis/Normed/Operator/LinearIsometry.lean @@ -640,8 +640,7 @@ theorem map_eq_zero_iff {x : E} : e x = 0 ↔ x = 0 := e.toLinearEquiv.map_eq_zero_iff @[simp] -theorem symm_symm : e.symm.symm = e := - ext fun _ => rfl +theorem symm_symm : e.symm.symm = e := rfl @[simp] theorem toLinearEquiv_symm : e.toLinearEquiv.symm = e.symm.toLinearEquiv := diff --git a/Mathlib/Analysis/Normed/Operator/WeakOperatorTopology.lean b/Mathlib/Analysis/Normed/Operator/WeakOperatorTopology.lean index b7a5ea7136815..45dfa1892cbcc 100644 --- a/Mathlib/Analysis/Normed/Operator/WeakOperatorTopology.lean +++ b/Mathlib/Analysis/Normed/Operator/WeakOperatorTopology.lean @@ -85,7 +85,7 @@ variable (𝕜) (E) (F) unseal ContinuousLinearMapWOT in /-- The linear equivalence that sends a continuous linear map to the type copy endowed with the -weak operator topology. -/ +weak operator topology. -/ def _root_.ContinuousLinearMap.toWOT : (E →L[𝕜] F) ≃ₗ[𝕜] (E →WOT[𝕜] F) := LinearEquiv.refl 𝕜 _ variable {𝕜} {E} {F} @@ -211,7 +211,7 @@ end Topology section Seminorms /-- The family of seminorms that induce the weak operator topology, namely `‖y (A x)‖` for -all `x` and `y`. -/ +all `x` and `y`. -/ def seminorm (x : E) (y : F⋆) : Seminorm 𝕜 (E →WOT[𝕜] F) where toFun A := ‖y (A x)‖ map_zero' := by simp @@ -221,7 +221,7 @@ def seminorm (x : E) (y : F⋆) : Seminorm 𝕜 (E →WOT[𝕜] F) where variable (𝕜) (E) (F) in /-- The family of seminorms that induce the weak operator topology, namely `‖y (A x)‖` for -all `x` and `y`. -/ +all `x` and `y`. -/ def seminormFamily : SeminormFamily 𝕜 (E →WOT[𝕜] F) (E × F⋆) := fun ⟨x, y⟩ => seminorm x y diff --git a/Mathlib/Analysis/Normed/Order/Basic.lean b/Mathlib/Analysis/Normed/Order/Basic.lean index d78be19a7ae1f..e3f1e8a5b1e77 100644 --- a/Mathlib/Analysis/Normed/Order/Basic.lean +++ b/Mathlib/Analysis/Normed/Order/Basic.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Anatole Dedecker, Yaël Dillies -/ import Mathlib.Algebra.Order.Group.TypeTags -import Mathlib.Analysis.Normed.Field.Basic +import Mathlib.Analysis.Normed.Field.Lemmas /-! # Ordered normed spaces diff --git a/Mathlib/Analysis/Normed/Ring/Seminorm.lean b/Mathlib/Analysis/Normed/Ring/Seminorm.lean index 9d88d4bb64e68..2f18c14fb0172 100644 --- a/Mathlib/Analysis/Normed/Ring/Seminorm.lean +++ b/Mathlib/Analysis/Normed/Ring/Seminorm.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 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, Yaël Dillies -/ -import Mathlib.Analysis.Normed.Field.Basic +import Mathlib.Analysis.Normed.Field.Lemmas import Mathlib.Analysis.SpecialFunctions.Pow.Real /-! @@ -298,7 +298,7 @@ instance : Inhabited (MulRingNorm R) := variable {R : Type*} [Ring R] /-- Two multiplicative ring norms `f, g` on `R` are equivalent if there exists a positive constant - `c` such that for all `x ∈ R`, `(f x)^c = g x`. -/ + `c` such that for all `x ∈ R`, `(f x)^c = g x`. -/ def equiv (f : MulRingNorm R) (g : MulRingNorm R) := ∃ c : ℝ, 0 < c ∧ (fun x => (f x) ^ c) = g diff --git a/Mathlib/Analysis/Normed/Ring/SeminormFromBounded.lean b/Mathlib/Analysis/Normed/Ring/SeminormFromBounded.lean index 2797ff18c5b52..a98f45db8cc03 100644 --- a/Mathlib/Analysis/Normed/Ring/SeminormFromBounded.lean +++ b/Mathlib/Analysis/Normed/Ring/SeminormFromBounded.lean @@ -97,7 +97,7 @@ theorem seminormFromBounded_aux (f_nonneg : 0 ≤ f) replace f_nonneg : 0 ≤ f 1 := f_nonneg 1 rcases f_nonneg.eq_or_gt with h1 | h1 · linarith [show (1 : ℝ) ≤ 0 by simpa [h1] using f_mul] - · rw [← div_le_iff h1] at f_mul + · rw [← div_le_iff₀ h1] at f_mul linarith [one_div_pos.mpr h1] positivity @@ -110,7 +110,7 @@ theorem seminormFromBounded_bddAbove_range (f_nonneg : 0 ≤ f) rintro r ⟨y, rfl⟩ rcases (f_nonneg y).eq_or_gt with hy0 | hy0 · simpa [hy0] using seminormFromBounded_aux f_nonneg f_mul x - · simpa [div_le_iff hy0] using f_mul x y + · simpa [div_le_iff₀ hy0] using f_mul x y /-- If `f : R → ℝ` is a nonnegative, multiplicatively bounded function, then for every `x : R`, `seminormFromBounded' f x` is bounded above by some multiple of `f x`. -/ @@ -120,7 +120,7 @@ theorem seminormFromBounded_le (f_nonneg : 0 ≤ f) refine ciSup_le (fun y ↦ ?_) rcases (f_nonneg y).eq_or_gt with hy | hy · simpa [hy] using seminormFromBounded_aux f_nonneg f_mul x - · rw [div_le_iff hy] + · rw [div_le_iff₀ hy] apply f_mul /-- If `f : R → ℝ` is a nonnegative, multiplicatively bounded function, then for every `x : R`, @@ -133,7 +133,7 @@ theorem seminormFromBounded_ge (f_nonneg : 0 ≤ f) rw [mul_one, h1, mul_zero] at f_mul have hx0 : f x = 0 := f_mul.antisymm (f_nonneg _) rw [hx0, h1, zero_mul] - · rw [mul_comm, ← div_le_iff (lt_of_le_of_ne' (f_nonneg _) h1)] + · rw [mul_comm, ← div_le_iff₀ (lt_of_le_of_ne' (f_nonneg _) h1)] conv_lhs => rw [← mul_one x] exact le_ciSup (seminormFromBounded_bddAbove_range f_nonneg f_mul x) (1 : R) @@ -153,11 +153,11 @@ theorem seminormFromBounded_eq_zero_iff (f_nonneg : 0 ≤ f) refine ⟨fun h ↦ ?_, fun h ↦ ?_⟩ · have hf := seminormFromBounded_ge f_nonneg f_mul x rw [h, mul_zero] at hf - exact hf.antisymm (f_nonneg _) + exact hf.antisymm (f_nonneg _) · have hf : seminormFromBounded' f x ≤ c * f x := seminormFromBounded_le f_nonneg f_mul x rw [h, mul_zero] at hf - exact hf.antisymm (seminormFromBounded_nonneg f_nonneg f_mul x) + exact hf.antisymm (seminormFromBounded_nonneg f_nonneg f_mul x) /-- If `f` is invariant under negation of `x`, then so is `seminormFromBounded'`.-/ theorem seminormFromBounded_neg (f_neg : ∀ x : R, f (-x) = f x) (x : R) : @@ -180,9 +180,9 @@ theorem seminormFromBounded_mul (f_nonneg : 0 ≤ f) exact mul_nonneg (seminormFromBounded_nonneg f_nonneg f_mul x) (seminormFromBounded_nonneg f_nonneg f_mul y) · intro z - rw [← div_le_iff (lt_of_le_of_ne' (seminormFromBounded_nonneg f_nonneg f_mul _) hy)] + rw [← div_le_iff₀ (lt_of_le_of_ne' (seminormFromBounded_nonneg f_nonneg f_mul _) hy)] apply le_ciSup_of_le (seminormFromBounded_bddAbove_range f_nonneg f_mul x) z - rw [div_le_iff (lt_of_le_of_ne' (seminormFromBounded_nonneg f_nonneg f_mul _) hy), + rw [div_le_iff₀ (lt_of_le_of_ne' (seminormFromBounded_nonneg f_nonneg f_mul _) hy), div_mul_eq_mul_div] by_cases hz : f z = 0 · have hxyz : f (z * (x * y)) = 0 := map_mul_zero_of_map_zero f_nonneg f_mul hz _ @@ -193,7 +193,7 @@ theorem seminormFromBounded_mul (f_nonneg : 0 ≤ f) by_cases hxz : f (x * z) = 0 · rw [mul_comm x y, mul_assoc, mul_comm y, map_mul_zero_of_map_zero f_nonneg f_mul hxz y] exact mul_nonneg (seminormFromBounded_nonneg f_nonneg f_mul y) (f_nonneg _) - · rw [← div_le_iff (lt_of_le_of_ne' (f_nonneg _) hxz)] + · rw [← div_le_iff₀ (lt_of_le_of_ne' (f_nonneg _) hxz)] apply le_ciSup_of_le (seminormFromBounded_bddAbove_range f_nonneg f_mul y) (x * z) rw [div_le_div_right (lt_of_le_of_ne' (f_nonneg _) hxz), mul_comm x y, mul_assoc] @@ -305,7 +305,7 @@ theorem seminormFromBounded_of_mul_le (f_nonneg : 0 ≤ f) {x : R} · refine ciSup_le (fun y ↦ ?_) by_cases hy : f y = 0 · rw [hy, div_zero]; exact f_nonneg _ - · rw [div_le_iff (lt_of_le_of_ne' (f_nonneg _) hy)]; exact hx _ + · rw [div_le_iff₀ (lt_of_le_of_ne' (f_nonneg _) hy)]; exact hx _ · have h_bdd : BddAbove (Set.range fun y ↦ f (x * y) / f y) := by use f x rintro r ⟨y, rfl⟩ @@ -313,7 +313,7 @@ theorem seminormFromBounded_of_mul_le (f_nonneg : 0 ≤ f) {x : R} · simp only [hy0, div_zero] exact f_nonneg _ · rw [← mul_one (f x), ← div_self hy0, ← mul_div_assoc, - div_le_iff (lt_of_le_of_ne' (f_nonneg _) hy0), mul_div_assoc, div_self hy0, mul_one] + div_le_iff₀ (lt_of_le_of_ne' (f_nonneg _) hy0), mul_div_assoc, div_self hy0, mul_one] exact hx y convert le_ciSup h_bdd (1 : R) by_cases h0 : f x = 0 diff --git a/Mathlib/Analysis/Normed/Ring/Units.lean b/Mathlib/Analysis/Normed/Ring/Units.lean index c46b35e61a4d4..a99777748c99d 100644 --- a/Mathlib/Analysis/Normed/Ring/Units.lean +++ b/Mathlib/Analysis/Normed/Ring/Units.lean @@ -36,7 +36,7 @@ variable {R : Type*} [NormedRing R] [CompleteSpace R] namespace Units /-- In a complete normed ring, a perturbation of `1` by an element `t` of distance less than `1` -from `1` is a unit. Here we construct its `Units` structure. -/ +from `1` is a unit. Here we construct its `Units` structure. -/ @[simps val] def oneSub (t : R) (h : ‖t‖ < 1) : Rˣ where val := 1 - t @@ -197,7 +197,7 @@ theorem inverse_continuousAt (x : Rˣ) : ContinuousAt inverse (x : R) := by refine tendsto_zero_iff_norm_tendsto_zero.mpr ?_ exact tendsto_iff_norm_sub_tendsto_zero.mp tendsto_id rw [ContinuousAt, tendsto_iff_norm_sub_tendsto_zero, inverse_unit] - simpa [(· ∘ ·)] using h_is_o.norm_left.tendsto_div_nhds_zero.comp h_lim + simpa [Function.comp_def] using h_is_o.norm_left.tendsto_div_nhds_zero.comp h_lim end NormedRing diff --git a/Mathlib/Analysis/NormedSpace/ENorm.lean b/Mathlib/Analysis/NormedSpace/ENorm.lean index fbbb8c726b3ad..48c17b7994ce9 100644 --- a/Mathlib/Analysis/NormedSpace/ENorm.lean +++ b/Mathlib/Analysis/NormedSpace/ENorm.lean @@ -182,7 +182,7 @@ def finiteSubspace : Subspace 𝕜 V where smul_mem' c x (hx : _ < _) := calc e (c • x) = ‖c‖₊ * e x := e.map_smul c x - _ < ⊤ := ENNReal.mul_lt_top ENNReal.coe_ne_top hx.ne + _ < ⊤ := ENNReal.mul_lt_top ENNReal.coe_lt_top hx /-- Metric space structure on `e.finiteSubspace`. We use `EMetricSpace.toMetricSpace` to ensure that this definition agrees with `e.emetricSpace`. -/ diff --git a/Mathlib/Analysis/NormedSpace/Int.lean b/Mathlib/Analysis/NormedSpace/Int.lean index fe43e855c5bea..b08f55039887a 100644 --- a/Mathlib/Analysis/NormedSpace/Int.lean +++ b/Mathlib/Analysis/NormedSpace/Int.lean @@ -3,7 +3,7 @@ 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.Analysis.Normed.Field.Basic +import Mathlib.Analysis.Normed.Field.Lemmas /-! # The integers as normed ring diff --git a/Mathlib/Analysis/NormedSpace/Multilinear/Basic.lean b/Mathlib/Analysis/NormedSpace/Multilinear/Basic.lean index c3efa1e0e4436..e7d06672107a6 100644 --- a/Mathlib/Analysis/NormedSpace/Multilinear/Basic.lean +++ b/Mathlib/Analysis/NormedSpace/Multilinear/Basic.lean @@ -160,7 +160,7 @@ theorem exists_bound_of_continuous (hf : Continuous f) : refine ⟨_, this, ?_⟩ refine f.bound_of_shell_of_continuous hf (fun _ => ε0) (fun _ => hc) fun m hcm hm => ?_ refine (hε m ((pi_norm_lt_iff ε0).2 hm)).le.trans ?_ - rw [← div_le_iff' this, one_div, ← inv_pow, inv_div, Fintype.card, ← prod_const] + rw [← div_le_iff₀' this, one_div, ← inv_pow, inv_div, Fintype.card, ← prod_const] exact prod_le_prod (fun _ _ => div_nonneg ε0.le (norm_nonneg _)) fun i _ => hcm i /-- If `f` satisfies a boundedness property around `0`, one can deduce a bound on `f m₁ - f m₂` @@ -796,11 +796,11 @@ theorem nnnorm_smulRight (f : ContinuousMultilinearMap 𝕜 E 𝕜) (z : G) : rw [mul_right_comm] gcongr exact le_opNNNorm _ _ - · obtain hz | hz := eq_or_ne ‖z‖₊ 0 + · obtain hz | hz := eq_zero_or_pos ‖z‖₊ · simp [hz] - rw [← NNReal.le_div_iff hz, opNNNorm_le_iff] + rw [← le_div_iff₀ hz, opNNNorm_le_iff] intro m - rw [div_mul_eq_mul_div, NNReal.le_div_iff hz] + rw [div_mul_eq_mul_div, le_div_iff₀ hz] refine le_trans ?_ ((f.smulRight z).le_opNNNorm m) rw [smulRight_apply, nnnorm_smul] diff --git a/Mathlib/Analysis/NormedSpace/OperatorNorm/Basic.lean b/Mathlib/Analysis/NormedSpace/OperatorNorm/Basic.lean index cb8d792f631d6..7c3c4398246cc 100644 --- a/Mathlib/Analysis/NormedSpace/OperatorNorm/Basic.lean +++ b/Mathlib/Analysis/NormedSpace/OperatorNorm/Basic.lean @@ -277,7 +277,7 @@ theorem opNorm_le_of_unit_norm [NormedSpace ℝ E] [NormedSpace ℝ F] {f : E refine opNorm_le_bound' f hC fun x hx => ?_ have H₁ : ‖‖x‖⁻¹ • x‖ = 1 := by rw [norm_smul, norm_inv, norm_norm, inv_mul_cancel₀ hx] have H₂ := hf _ H₁ - rwa [map_smul, norm_smul, norm_inv, norm_norm, ← div_eq_inv_mul, _root_.div_le_iff] at H₂ + rwa [map_smul, norm_smul, norm_inv, norm_norm, ← div_eq_inv_mul, div_le_iff₀] at H₂ exact (norm_nonneg x).lt_of_ne' hx @[deprecated (since := "2024-02-02")] alias op_norm_le_of_unit_norm := opNorm_le_of_unit_norm @@ -325,7 +325,7 @@ private lemma uniformity_eq_seminorm : simpa [NormedSpace.isVonNBounded_closedBall, closedBall_mem_nhds, subset_def] using this intro f hf refine opNorm_le_of_shell (f := f) one_pos (norm_nonneg c) hc fun x hcx hx ↦ ?_ - exact (hf x hx.le).trans ((div_le_iff' <| one_pos.trans hc).1 hcx) + exact (hf x hx.le).trans ((div_le_iff₀' <| one_pos.trans hc).1 hcx) · rcases (NormedSpace.isVonNBounded_iff' _).1 hs with ⟨ε, hε⟩ rcases exists_pos_mul_lt hr ε with ⟨δ, hδ₀, hδ⟩ refine ⟨δ, hδ₀, fun f hf x hx ↦ ?_⟩ diff --git a/Mathlib/Analysis/NormedSpace/OperatorNorm/Bilinear.lean b/Mathlib/Analysis/NormedSpace/OperatorNorm/Bilinear.lean index 07c05d0a62e73..1d70cb3750159 100644 --- a/Mathlib/Analysis/NormedSpace/OperatorNorm/Bilinear.lean +++ b/Mathlib/Analysis/NormedSpace/OperatorNorm/Bilinear.lean @@ -382,7 +382,7 @@ variable {𝕜₁' : Type*} {𝕜₂' : Type*} [NontriviallyNormedField 𝕜₁' [RingHomIsometric σ₂₃] [RingHomIsometric σ₁₃'] [RingHomIsometric σ₂₃'] /-- Compose a bilinear map `E →SL[σ₁₃] F →SL[σ₂₃] G` with two linear maps -`E' →SL[σ₁'] E` and `F' →SL[σ₂'] F`. -/ +`E' →SL[σ₁'] E` and `F' →SL[σ₂'] F`. -/ def bilinearComp (f : E →SL[σ₁₃] F →SL[σ₂₃] G) (gE : E' →SL[σ₁'] E) (gF : F' →SL[σ₂'] F) : E' →SL[σ₁₃'] F' →SL[σ₂₃'] G := ((f.comp gE).flip.comp gF).flip diff --git a/Mathlib/Analysis/NormedSpace/OperatorNorm/Completeness.lean b/Mathlib/Analysis/NormedSpace/OperatorNorm/Completeness.lean index 03c7738155ba1..b4e87ed65eb32 100644 --- a/Mathlib/Analysis/NormedSpace/OperatorNorm/Completeness.lean +++ b/Mathlib/Analysis/NormedSpace/OperatorNorm/Completeness.lean @@ -184,7 +184,7 @@ section variable (h_e : UniformInducing 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ₗ`. -/ +complete normed space, along a uniform and dense embedding `e : E →L[𝕜] Fₗ`. -/ def extend : Fₗ →SL[σ₁₂] F := -- extension of `f` is continuous have cont := (uniformContinuous_uniformly_extend h_e h_dense f.uniformContinuous).continuous diff --git a/Mathlib/Analysis/NormedSpace/OperatorNorm/NormedSpace.lean b/Mathlib/Analysis/NormedSpace/OperatorNorm/NormedSpace.lean index c57a94705a314..d07b5ac33cae4 100644 --- a/Mathlib/Analysis/NormedSpace/OperatorNorm/NormedSpace.lean +++ b/Mathlib/Analysis/NormedSpace/OperatorNorm/NormedSpace.lean @@ -59,7 +59,7 @@ theorem bound_of_ball_bound {r : ℝ} (r_pos : 0 < r) (c : ℝ) (f : E →ₗ[ _ ≤ c * (‖x‖ * ‖k‖ / r) := le_mul_of_one_le_right ?_ ?_ _ = _ := by ring · exact le_trans (norm_nonneg _) (h 0 (by simp [r_pos])) - · rw [div_le_iff (zero_lt_one.trans hk)] at hko + · rw [div_le_iff₀ (zero_lt_one.trans hk)] at hko exact (one_le_div r_pos).mpr hko theorem antilipschitz_of_comap_nhds_le [h : RingHomIsometric σ₁₂] (f : E →ₛₗ[σ₁₂] F) @@ -213,9 +213,9 @@ theorem norm_smulRight_apply (c : E →L[𝕜] 𝕜) (f : Fₗ) : ‖smulRight c · by_cases h : f = 0 · simp [h] · have : 0 < ‖f‖ := norm_pos_iff.2 h - rw [← le_div_iff this] + rw [← le_div_iff₀ this] refine opNorm_le_bound _ (div_nonneg (norm_nonneg _) (norm_nonneg f)) fun x => ?_ - rw [div_mul_eq_mul_div, le_div_iff this] + rw [div_mul_eq_mul_div, le_div_iff₀ this] calc ‖c x‖ * ‖f‖ = ‖c x • f‖ := (norm_smul _ _).symm _ = ‖smulRight c f x‖ := rfl diff --git a/Mathlib/Analysis/NormedSpace/PiTensorProduct/InjectiveSeminorm.lean b/Mathlib/Analysis/NormedSpace/PiTensorProduct/InjectiveSeminorm.lean index a31afd3501b4f..1ddd022c490b2 100644 --- a/Mathlib/Analysis/NormedSpace/PiTensorProduct/InjectiveSeminorm.lean +++ b/Mathlib/Analysis/NormedSpace/PiTensorProduct/InjectiveSeminorm.lean @@ -179,12 +179,13 @@ theorem norm_eval_le_injectiveSeminorm (f : ContinuousMultilinearMap 𝕜 E F) ( set f' := MultilinearMap.mkContinuous f'₀ ‖f‖ hf'₀ have hnorm : ‖f'‖ ≤ ‖f‖ := (f'.opNorm_le_iff (norm_nonneg f)).mpr hf'₀ have heq : e (lift f'.toMultilinearMap x) = lift f.toMultilinearMap x := by - induction' x using PiTensorProduct.induction_on with a m _ _ hx hy - · simp only [lift_symm, map_smul, lift.tprod, ContinuousMultilinearMap.coe_coe, + induction x using PiTensorProduct.induction_on with + | smul_tprod => + simp only [lift_symm, map_smul, lift.tprod, ContinuousMultilinearMap.coe_coe, MultilinearMap.coe_mkContinuous, LinearMap.compMultilinearMap_apply, LinearMap.coe_comp, LinearEquiv.coe_coe, Function.comp_apply, LinearEquiv.apply_symm_apply, SetLike.val_smul, LinearMap.codRestrict_apply, f', f'₀] - · simp only [map_add, AddSubmonoid.coe_add, Submodule.coe_toAddSubmonoid, hx, hy] + | add _ _ hx hy => simp only [map_add, Submodule.coe_add, hx, hy] suffices h : ‖lift f'.toMultilinearMap x‖ ≤ ‖f'‖ * injectiveSeminorm x by change ‖(e (lift f'.toMultilinearMap x)).1‖ ≤ _ at h rw [heq] at h @@ -343,11 +344,12 @@ theorem mapL_coe : (mapL f).toLinearMap = map (fun i ↦ (f i).toLinearMap) := b @[simp] theorem mapL_apply (x : ⨂[𝕜] i, E i) : mapL f x = map (fun i ↦ (f i).toLinearMap) x := by - induction' x using PiTensorProduct.induction_on with _ _ _ _ hx hy - · simp only [mapL, map_smul, liftIsometry_apply_apply, lift.tprod, + induction x using PiTensorProduct.induction_on with + | smul_tprod => + simp only [mapL, map_smul, liftIsometry_apply_apply, lift.tprod, ContinuousMultilinearMap.coe_coe, ContinuousMultilinearMap.compContinuousLinearMap_apply, tprodL_toFun, map_tprod, ContinuousLinearMap.coe_coe] - · simp only [map_add, hx, hy] + | add _ _ hx hy => simp only [map_add, hx, hy] /-- Given submodules `pᵢ ⊆ Eᵢ`, this is the natural map: `⨂[𝕜] i, pᵢ → ⨂[𝕜] i, Eᵢ`. This is the continuous version of `PiTensorProduct.mapIncl`. diff --git a/Mathlib/Analysis/ODE/Gronwall.lean b/Mathlib/Analysis/ODE/Gronwall.lean index 243e6fdc3e392..f45756db1a781 100644 --- a/Mathlib/Analysis/ODE/Gronwall.lean +++ b/Mathlib/Analysis/ODE/Gronwall.lean @@ -175,7 +175,7 @@ theorem dist_le_of_approx_trajectories_ODE (ha : dist (f a) (g a) ≤ δ) : ∀ t ∈ Icc a b, dist (f t) (g t) ≤ gronwallBound δ K (εf + εg) (t - a) := have hfs : ∀ t ∈ Ico a b, f t ∈ @univ E := fun _ _ => trivial - dist_le_of_approx_trajectories_ODE_of_mem (fun t => (hv t).lipschitzOnWith _) hf hf' + dist_le_of_approx_trajectories_ODE_of_mem (fun t => (hv t).lipschitzOnWith) hf hf' f_bound hfs hg hg' g_bound (fun _ _ => trivial) ha include hv in @@ -213,7 +213,7 @@ theorem dist_le_of_trajectories_ODE (ha : dist (f a) (g a) ≤ δ) : ∀ t ∈ Icc a b, dist (f t) (g t) ≤ δ * exp (K * (t - a)) := have hfs : ∀ t ∈ Ico a b, f t ∈ @univ E := fun _ _ => trivial - dist_le_of_trajectories_ODE_of_mem (fun t => (hv t).lipschitzOnWith _) hf hf' hfs hg + dist_le_of_trajectories_ODE_of_mem (fun t => (hv t).lipschitzOnWith) hf hf' hfs hg hg' (fun _ _ => trivial) ha include hv in @@ -354,5 +354,5 @@ theorem ODE_solution_unique (ha : f a = g a) : EqOn f g (Icc a b) := have hfs : ∀ t ∈ Ico a b, f t ∈ @univ E := fun _ _ => trivial - ODE_solution_unique_of_mem_Icc_right (fun t => (hv t).lipschitzOnWith _) hf hf' hfs hg hg' + ODE_solution_unique_of_mem_Icc_right (fun t => (hv t).lipschitzOnWith) hf hf' hfs hg hg' (fun _ _ => trivial) ha diff --git a/Mathlib/Analysis/ODE/PicardLindelof.lean b/Mathlib/Analysis/ODE/PicardLindelof.lean index cb09d82fa6836..a1db140c6f1f2 100644 --- a/Mathlib/Analysis/ODE/PicardLindelof.lean +++ b/Mathlib/Analysis/ODE/PicardLindelof.lean @@ -80,7 +80,7 @@ instance : Inhabited (PicardLindelof E) := ⟨⟨0, 0, 0, ⟨0, le_rfl, le_rfl⟩, 0, 0, 0, 0, { ht₀ := by rw [Subtype.coe_mk, Icc_self]; exact mem_singleton _ hR := le_rfl - lipschitz := fun t _ => (LipschitzWith.const 0).lipschitzOnWith _ + lipschitz := fun t _ => (LipschitzWith.const 0).lipschitzOnWith cont := fun _ _ => by simpa only [Pi.zero_apply] using continuousOn_const norm_le := fun t _ x _ => norm_zero.le C_mul_le_R := (zero_mul _).le }⟩⟩ @@ -284,7 +284,7 @@ variable [CompleteSpace E] theorem hasDerivWithinAt_next (t : Icc v.tMin v.tMax) : HasDerivWithinAt (f.next ∘ v.proj) (v t (f t)) (Icc v.tMin v.tMax) t := by haveI : Fact ((t : ℝ) ∈ Icc v.tMin v.tMax) := ⟨t.2⟩ - simp only [(· ∘ ·), next_apply] + simp only [Function.comp_def, next_apply] refine HasDerivWithinAt.const_add _ ?_ have : HasDerivWithinAt (∫ τ in v.t₀..·, f.vComp τ) (f.vComp t) (Icc v.tMin v.tMax) t := integral_hasDerivWithinAt_right (f.intervalIntegrable_vComp _ _) diff --git a/Mathlib/Analysis/PSeries.lean b/Mathlib/Analysis/PSeries.lean index eca94e33eea6e..6b1fde6df52ee 100644 --- a/Mathlib/Analysis/PSeries.lean +++ b/Mathlib/Analysis/PSeries.lean @@ -198,7 +198,7 @@ theorem summable_schlomilch_iff {C : ℕ} {u : ℕ → ℕ} {f : ℕ → ℝ≥0 simpa [add_eq_top, mul_ne_top, mul_eq_top, hC_nonzero] using eq_top_mono hC h · replace hf : ∀ m n, 0 < m → m ≤ n → (f n : ℝ≥0∞) ≤ f m := fun m n hm hmn => ENNReal.coe_le_coe.2 (hf hm hmn) - have : ∑ k ∈ range (u 0), (f k : ℝ≥0∞) ≠ ∞ := (sum_lt_top fun a _ => coe_ne_top).ne + have : ∑ k ∈ range (u 0), (f k : ℝ≥0∞) ≠ ∞ := sum_ne_top.2 fun a _ => coe_ne_top simpa [h, add_eq_top, this] using le_tsum_schlomilch hf h_pos hu_strict open ENNReal in diff --git a/Mathlib/Analysis/RCLike/Basic.lean b/Mathlib/Analysis/RCLike/Basic.lean index 8031b85a253d9..c90ea8c4d556d 100644 --- a/Mathlib/Analysis/RCLike/Basic.lean +++ b/Mathlib/Analysis/RCLike/Basic.lean @@ -3,12 +3,11 @@ Copyright (c) 2020 Frédéric Dupuis. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Frédéric Dupuis -/ -import Mathlib.Algebra.Star.Order +import Mathlib.Algebra.Algebra.Field +import Mathlib.Algebra.Order.Star.Basic import Mathlib.Analysis.CStarAlgebra.Basic import Mathlib.Analysis.Normed.Operator.ContinuousLinearMap -import Mathlib.Analysis.Normed.Module.Basic import Mathlib.Data.Real.Sqrt -import Mathlib.Algebra.Algebra.Field /-! # `RCLike`: a typeclass for ℝ or ℂ @@ -40,12 +39,12 @@ 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 + section local notation "𝓚" => algebraMap ℝ _ -open ComplexConjugate - /-- This typeclass captures properties shared by ℝ and ℂ, with an API that closely matches that of ℂ. -/ @@ -82,8 +81,6 @@ variable {K E : Type*} [RCLike K] namespace RCLike -open ComplexConjugate - /-- Coercion from `ℝ` to an `RCLike` field. -/ @[coe] abbrev ofReal : ℝ → K := Algebra.cast @@ -233,7 +230,7 @@ theorem norm_ofReal (r : ℝ) : ‖(r : K)‖ = |r| := /-! ### Characteristic zero -/ -- see Note [lower instance priority] -/-- ℝ and ℂ are both of characteristic zero. -/ +/-- ℝ and ℂ are both of characteristic zero. -/ instance (priority := 100) charZero_rclike : CharZero K := (RingHom.charZero_iff (algebraMap ℝ K).injective).1 inferInstance @@ -333,7 +330,9 @@ theorem is_real_TFAE (z : K) : TFAE [conj z = z, ∃ r : ℝ, (r : K) = z, ↑(r tfae_finish theorem conj_eq_iff_real {z : K} : conj z = z ↔ ∃ r : ℝ, z = (r : K) := - ((is_real_TFAE z).out 0 1).trans <| by simp only [eq_comm] + calc + _ ↔ ∃ r : ℝ, (r : K) = z := (is_real_TFAE z).out 0 1 + _ ↔ _ := by simp only [eq_comm] theorem conj_eq_iff_re {z : K} : conj z = z ↔ (re z : K) = z := (is_real_TFAE z).out 0 2 @@ -503,11 +502,13 @@ theorem normSq_inv (z : K) : normSq z⁻¹ = (normSq z)⁻¹ := theorem normSq_div (z w : K) : normSq (z / w) = normSq z / normSq w := map_div₀ normSq z w -@[rclike_simps] -- porting note (#10618): was `simp` -theorem norm_conj {z : K} : ‖conj z‖ = ‖z‖ := by simp only [← sqrt_normSq_eq_norm, normSq_conj] +@[simp 1100, rclike_simps] +theorem norm_conj (z : K) : ‖conj z‖ = ‖z‖ := by simp only [← sqrt_normSq_eq_norm, normSq_conj] + +@[simp, rclike_simps] lemma nnnorm_conj (z : K) : ‖conj z‖₊ = ‖z‖₊ := by simp [nnnorm] instance (priority := 100) : CStarRing K where - norm_mul_self_le x := le_of_eq <| ((norm_mul _ _).trans <| congr_arg (· * ‖x‖) norm_conj).symm + norm_mul_self_le x := le_of_eq <| ((norm_mul _ _).trans <| congr_arg (· * ‖x‖) (norm_conj _)).symm /-! ### Cast lemmas -/ @@ -515,6 +516,9 @@ instance (priority := 100) : CStarRing K where theorem ofReal_natCast (n : ℕ) : ((n : ℝ) : K) = n := map_natCast (algebraMap ℝ K) n +@[rclike_simps, norm_cast] +lemma ofReal_nnratCast (q : ℚ≥0) : ((q : ℝ) : K) = q := map_nnratCast (algebraMap ℝ K) _ + @[simp, rclike_simps] -- Porting note: removed `norm_cast` theorem natCast_re (n : ℕ) : re (n : K) = n := by rw [← ofReal_natCast, ofReal_re] @@ -575,21 +579,46 @@ theorem norm_natCast (n : ℕ) : ‖(n : K)‖ = n := by rw [← ofReal_natCast] exact norm_of_nonneg (Nat.cast_nonneg n) +@[simp, rclike_simps, norm_cast] lemma nnnorm_natCast (n : ℕ) : ‖(n : K)‖₊ = n := by simp [nnnorm] + @[simp, rclike_simps] theorem norm_ofNat (n : ℕ) [n.AtLeastTwo] : ‖(no_index (OfNat.ofNat n) : K)‖ = OfNat.ofNat n := norm_natCast n +@[simp, rclike_simps] +lemma nnnorm_ofNat (n : ℕ) [n.AtLeastTwo] : ‖(no_index (OfNat.ofNat n) : K)‖₊ = OfNat.ofNat n := + nnnorm_natCast n + +lemma norm_two : ‖(2 : K)‖ = 2 := norm_ofNat 2 +lemma nnnorm_two : ‖(2 : K)‖₊ = 2 := nnnorm_ofNat 2 + +@[simp, rclike_simps, norm_cast] +lemma norm_nnratCast (q : ℚ≥0) : ‖(q : K)‖ = q := by + rw [← ofReal_nnratCast]; exact norm_of_nonneg q.cast_nonneg + +@[simp, rclike_simps, norm_cast] +lemma nnnorm_nnratCast (q : ℚ≥0) : ‖(q : K)‖₊ = q := by simp [nnnorm] + variable (K) in lemma norm_nsmul [NormedAddCommGroup E] [NormedSpace K E] (n : ℕ) (x : E) : ‖n • x‖ = n • ‖x‖ := by - rw [← Nat.cast_smul_eq_nsmul K, norm_smul, RCLike.norm_natCast, nsmul_eq_mul] + simpa [Nat.cast_smul_eq_nsmul] using norm_smul (n : K) x + +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 + +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 + +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 theorem mul_self_norm (z : K) : ‖z‖ * ‖z‖ = normSq z := by rw [normSq_eq_def', sq] attribute [rclike_simps] norm_zero norm_one norm_eq_zero abs_norm norm_inv norm_div --- Porting note: removed @[simp, rclike_simps], b/c generalized to `norm_ofNat` -theorem norm_two : ‖(2 : K)‖ = 2 := norm_ofNat 2 - theorem abs_re_le_norm (z : K) : |re z| ≤ ‖z‖ := by rw [mul_self_le_mul_self_iff (abs_nonneg _) (norm_nonneg _), abs_mul_abs_self, mul_self_norm] apply re_sq_le_normSq @@ -666,7 +695,7 @@ end RCLike section Instances -noncomputable instance Real.RCLike : RCLike ℝ where +noncomputable instance Real.instRCLike : RCLike ℝ where re := AddMonoidHom.id ℝ im := 0 I := 0 @@ -803,7 +832,7 @@ theorem toOrderedSMul : OrderedSMul ℝ K := scoped[ComplexOrder] attribute [instance] RCLike.toOrderedSMul -/-- A star algebra over `K` has a scalar multiplication that respects the order. -/ +/-- A star algebra over `K` has a scalar multiplication that respects the order. -/ lemma _root_.StarModule.instOrderedSMul {A : Type*} [NonUnitalRing A] [StarRing A] [PartialOrder A] [StarOrderedRing A] [Module K A] [StarModule K A] [IsScalarTower K A A] [SMulCommClass K A A] : OrderedSMul K A where @@ -822,8 +851,6 @@ scoped[ComplexOrder] attribute [instance] StarModule.instOrderedSMul end Order -open ComplexConjugate - section CleanupLemmas local notation "reR" => @RCLike.re ℝ _ @@ -924,7 +951,7 @@ theorem conjAe_coe : (conjAe : K → K) = conj := /-- Conjugate as a linear isometry -/ noncomputable def conjLIE : K ≃ₗᵢ[ℝ] K := - ⟨conjAe.toLinearEquiv, fun _ => norm_conj⟩ + ⟨conjAe.toLinearEquiv, norm_conj⟩ @[simp, rclike_simps] theorem conjLIE_apply : (conjLIE : K → K) = conj := @@ -1020,3 +1047,14 @@ noncomputable def realLinearIsometryEquiv (h : I = (0 : K)) : K ≃ₗᵢ[ℝ] end CaseSpecific end RCLike + +namespace AddChar +variable {G : Type*} [Finite G] + +lemma inv_apply_eq_conj [AddLeftCancelMonoid G] (ψ : AddChar G K) (x : G) : (ψ x)⁻¹ = conj (ψ x) := + RCLike.inv_eq_conj <| norm_apply _ _ + +lemma map_neg_eq_conj [AddCommGroup G] (ψ : AddChar G K) (x : G) : ψ (-x) = conj (ψ x) := by + rw [map_neg_eq_inv, inv_apply_eq_conj] + +end AddChar diff --git a/Mathlib/Analysis/Seminorm.lean b/Mathlib/Analysis/Seminorm.lean index 99aa49d8ceb0b..46659a1b853cf 100644 --- a/Mathlib/Analysis/Seminorm.lean +++ b/Mathlib/Analysis/Seminorm.lean @@ -664,7 +664,7 @@ theorem closedBall_smul (p : Seminorm 𝕜 E) {c : NNReal} (hc : 0 < c) (r : ℝ (c • p).closedBall x r = p.closedBall x (r / c) := by ext rw [mem_closedBall, mem_closedBall, smul_apply, NNReal.smul_def, smul_eq_mul, mul_comm, - le_div_iff (NNReal.coe_pos.mpr hc)] + le_div_iff₀ (NNReal.coe_pos.mpr hc)] theorem ball_sup (p : Seminorm 𝕜 E) (q : Seminorm 𝕜 E) (e : E) (r : ℝ) : ball (p ⊔ q) e r = ball p e r ∩ ball q e r := by @@ -1188,10 +1188,10 @@ lemma rescale_to_shell_zpow (p : Seminorm 𝕜 E) {c : 𝕜} (hc : 1 < ‖c‖) norm_zpow] 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), + 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] - exact (le_div_iff εpos).1 hn.1 + one_mul, ← div_eq_inv_mul, le_div_iff₀ (zpow_pos_of_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 rw [zpow_neg, norm_inv, inv_inv, norm_zpow, zpow_add₀ (ne_of_gt cpos), zpow_one, this, @@ -1255,7 +1255,7 @@ lemma bddAbove_of_absorbent {ι : Sort*} {p : ι → Seminorm 𝕜 E} {s : Set E obtain ⟨c, hc₀, hc⟩ : ∃ c ≠ 0, (c : 𝕜) • x ∈ s := (eventually_mem_nhdsWithin.and (hs.eventually_nhdsWithin_zero x)).exists rcases h _ hc with ⟨M, hM⟩ - refine ⟨M / ‖c‖, forall_mem_range.mpr fun i ↦ (le_div_iff' (norm_pos_iff.2 hc₀)).2 ?_⟩ + refine ⟨M / ‖c‖, forall_mem_range.mpr fun i ↦ (le_div_iff₀' (norm_pos_iff.2 hc₀)).2 ?_⟩ exact hM ⟨i, map_smul_eq_mul ..⟩ end NontriviallyNormedField diff --git a/Mathlib/Analysis/SpecialFunctions/Bernstein.lean b/Mathlib/Analysis/SpecialFunctions/Bernstein.lean index 5cfa043e78334..66d2388a494f1 100644 --- a/Mathlib/Analysis/SpecialFunctions/Bernstein.lean +++ b/Mathlib/Analysis/SpecialFunctions/Bernstein.lean @@ -92,7 +92,7 @@ def z {n : ℕ} (k : Fin (n + 1)) : I := · norm_num · have h₁ : 0 < (n.succ : ℝ) := mod_cast Nat.succ_pos _ have h₂ : ↑k ≤ n.succ := mod_cast Fin.le_last k - rw [Set.mem_Icc, le_div_iff h₁, div_le_iff h₁] + rw [Set.mem_Icc, le_div_iff₀ h₁, div_le_iff₀ h₁] norm_cast simp [h₂]⟩ diff --git a/Mathlib/Analysis/SpecialFunctions/BinaryEntropy.lean b/Mathlib/Analysis/SpecialFunctions/BinaryEntropy.lean new file mode 100644 index 0000000000000..765ed994e7883 --- /dev/null +++ b/Mathlib/Analysis/SpecialFunctions/BinaryEntropy.lean @@ -0,0 +1,449 @@ +/- +Copyright (c) 2023 Adomas Baliuka. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Adomas Baliuka +-/ +import Mathlib.Analysis.SpecialFunctions.Log.NegMulLog +import Mathlib.Analysis.Convex.SpecificFunctions.Basic + +/-! +# Properties of Shannon q-ary entropy and binary entropy functions + +The [binary entropy function](https://en.wikipedia.org/wiki/Binary_entropy_function) +`binEntropy p := - p * log p - (1 - p) * log (1 - p)` +is the Shannon entropy of a Bernoulli random variable with success probability `p`. + +More generally, the q-ary entropy function is the Shannon entropy of the random variable +with possible outcomes `{1, ..., q}`, where outcome `1` has probability `1 - p` +and all other outcomes are equally likely. + +`qaryEntropy (q : ℕ) (p : ℝ) := p * log (q - 1) - p * log p - (1 - p) * log (1 - p)` + +This file assumes that entropy is measured in Nats, hence the use of natural logarithms. +Most lemmas are also valid using a logarithm in a different base. + +## Main declarations + +* `Real.binEntropy`: the binary entropy function +* `Real.qaryEntropy`: the `q`-ary entropy function + +## Main results + +The functions are also defined outside the interval `Icc 0 1` due to `log x = log |x|`. + +* They are continuous everywhere (`binEntropy_continuous` and `qaryEntropy_continuous`). +* They are differentiable everywhere except at points `0` or `1` + (`hasDerivAt_binEntropy` and `hasDerivAt_qaryEntropy`). + In addition, due to junk values, `deriv binEntropy p = log (1 - p) - log p` + holds everywhere (`deriv_binEntropy`). +* they are strictly increasing on `Icc 0 (1 - 1/q))` + (`qaryEntropy_strictMonoOn`, `binEntropy_strictMonoOn`) + and strictly decreasing on `Icc (1 - 1/q) 1` + (`binEntropy_strictAntiOn` and `qaryEntropy_strictAntiOn`). +* they are strictly concave on `Icc 0 1` + (`strictConcaveOn_qaryEntropy` and `strictConcave_binEntropy`). + +## Tags + +entropy, Shannon, binary, nit, nepit +-/ + +namespace Real +variable {q : ℕ} {p : ℝ} + +/-! ### Binary entropy -/ + +/-- The [binary entropy function](https://en.wikipedia.org/wiki/Binary_entropy_function) +`binEntropy p := - p * log p - (1-p) * log (1 - p)` +is the Shannon entropy of a Bernoulli random variable with success probability `p`. -/ +@[pp_nodot] noncomputable def binEntropy (p : ℝ) : ℝ := p * log p⁻¹ + (1 - p) * log (1 - p)⁻¹ + +@[simp] lemma binEntropy_zero : binEntropy 0 = 0 := by simp [binEntropy] +@[simp] lemma binEntropy_one : binEntropy 1 = 0 := by simp [binEntropy] +@[simp] lemma binEntropy_two_inv : binEntropy 2⁻¹ = log 2 := by norm_num [binEntropy]; simp; ring + +lemma binEntropy_eq_negMulLog_add_negMulLog_one_sub (p : ℝ) : + binEntropy p = negMulLog p + negMulLog (1 - p) := by simp [binEntropy, negMulLog, ← neg_mul] + +lemma binEntropy_eq_negMulLog_add_negMulLog_one_sub' : + binEntropy = fun p ↦ negMulLog p + negMulLog (1 - p) := + funext binEntropy_eq_negMulLog_add_negMulLog_one_sub + +/-- `binEntropy` is symmetric about 1/2. -/ +@[simp] lemma binEntropy_one_sub (p : ℝ) : binEntropy (1 - p) = binEntropy p := by + simp [binEntropy, add_comm] + +/-- `binEntropy` is symmetric about 1/2. -/ +lemma binEntropy_two_inv_add (p : ℝ) : binEntropy (2⁻¹ + p) = binEntropy (2⁻¹ - p) := by + rw [← binEntropy_one_sub]; ring_nf + +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₀) + positivity + +lemma binEntropy_nonneg (hp₀ : 0 ≤ p) (hp₁ : p ≤ 1) : 0 ≤ binEntropy p := by + obtain rfl | hp₀ := hp₀.eq_or_lt + · simp + obtain rfl | hp₁ := hp₁.eq_or_lt + · simp + exact (binEntropy_pos hp₀ hp₁).le + +/-- Outside the usual range of `binEntropy`, it is negative. This is due to `log p = log |p|`. -/ +lemma binEntropy_neg_of_neg (hp : p < 0) : binEntropy p < 0 := by + rw [binEntropy, log_inv, log_inv] + suffices -p * log p < (1 - p) * log (1 - p) by linarith + by_cases hp' : p < -1 + · have : log p < log (1 - p) := by + rw [← log_neg_eq_log] + exact log_lt_log (Left.neg_pos_iff.mpr hp) (by linarith) + nlinarith [log_pos_of_lt_neg_one hp'] + · have : -p * log p ≤ 0 := by + wlog h : -1 < p + · simp only [show p = -1 by linarith, log_neg_eq_log, log_one, le_refl, mul_zero] + · nlinarith [log_neg_of_lt_zero hp h] + nlinarith [(log_pos (by linarith) : 0 < log (1 - p))] + +/-- Outside the usual range of `binEntropy`, it is negative. This is due to `log p = log |p|`. -/ +lemma binEntropy_nonpos_of_nonpos (hp : p ≤ 0) : binEntropy p ≤ 0 := by + obtain rfl | hp := hp.eq_or_lt + · simp + · exact (binEntropy_neg_of_neg hp).le + +/-- Outside the usual range of `binEntropy`, it is negative. This is due to `log p = log |p|` -/ +lemma binEntropy_neg_of_one_lt (hp : 1 < p) : binEntropy p < 0 := by + rw [← binEntropy_one_sub]; exact binEntropy_neg_of_neg (sub_neg.2 hp) + +/-- Outside the usual range of `binEntropy`, it is negative. This is due to `log p = log |p|` -/ +lemma binEntropy_nonpos_of_one_le (hp : 1 ≤ p) : binEntropy p ≤ 0 := by + rw [← binEntropy_one_sub]; exact binEntropy_nonpos_of_nonpos (sub_nonpos.2 hp) + +lemma binEntropy_eq_zero : binEntropy p = 0 ↔ p = 0 ∨ p = 1 := by + refine ⟨fun h ↦ ?_, by rintro (rfl | rfl) <;> simp⟩ + contrapose! h + obtain hp₀ | hp₀ := h.1.lt_or_lt + · exact (binEntropy_neg_of_neg hp₀).ne + obtain hp₁ | hp₁ := h.2.lt_or_lt.symm + · exact (binEntropy_neg_of_one_lt hp₁).ne + · exact (binEntropy_pos hp₀ hp₁).ne' + +/-- For probability `p ≠ 0.5`, `binEntropy p < log 2`. -/ +lemma binEntropy_lt_log_two : binEntropy p < log 2 ↔ p ≠ 2⁻¹ := by + refine ⟨?_, fun h ↦ ?_⟩ + · rintro h rfl + simp at h + wlog hp : p < 2⁻¹ + · have hp : 1 - p < 2⁻¹ := by + rw [sub_lt_comm]; norm_num at *; linarith (config := { splitNe := true }) + rw [← binEntropy_one_sub] + exact this hp.ne hp + obtain hp₀ | hp₀ := le_or_lt p 0 + · exact (binEntropy_nonpos_of_nonpos hp₀).trans_lt <| log_pos <| by norm_num + have hp₁ : 0 < 1 - p := sub_pos.2 <| hp.trans <| by norm_num + calc + _ < log (p * p⁻¹ + (1 - p) * (1 - p)⁻¹) := + strictConcaveOn_log_Ioi.2 (inv_pos.2 hp₀) (inv_pos.2 hp₁) + (by simpa [eq_sub_iff_add_eq, ← two_mul, mul_comm, mul_eq_one_iff_eq_inv₀]) hp₀ hp₁ (by simp) + _ = log 2 := by rw [mul_inv_cancel₀, mul_inv_cancel₀, one_add_one_eq_two] <;> positivity + +lemma binEntropy_le_log_two : binEntropy p ≤ log 2 := by + obtain rfl | hp := eq_or_ne p 2⁻¹ + · simp + · exact (binEntropy_lt_log_two.2 hp).le + +lemma binEntropy_eq_log_two : binEntropy p = log 2 ↔ p = 2⁻¹ := by + rw [binEntropy_le_log_two.eq_iff_not_lt, binEntropy_lt_log_two, not_ne_iff] + +/-- Binary entropy is continuous everywhere. +This is due to definition of `Real.log` for negative numbers. -/ +@[fun_prop] lemma binEntropy_continuous : Continuous binEntropy := by + rw [binEntropy_eq_negMulLog_add_negMulLog_one_sub']; fun_prop + +@[fun_prop] lemma differentiableAt_binEntropy (hp₀ : p ≠ 0) (hp₁ : p ≠ 1) : + DifferentiableAt ℝ binEntropy p := by + rw [ne_comm, ← sub_ne_zero] at hp₁ + unfold binEntropy + simp only [log_inv, mul_neg] + fun_prop (disch := assumption) + +set_option push_neg.use_distrib true in +lemma differentiableAt_binEntropy_iff_ne_zero_one : + DifferentiableAt ℝ binEntropy p ↔ p ≠ 0 ∧ p ≠ 1 := by + refine ⟨fun h ↦ ⟨?_, ?_⟩, fun h ↦ differentiableAt_binEntropy h.1 h.2⟩ + <;> rintro rfl <;> unfold binEntropy at h + · rw [DifferentiableAt.add_iff_left] at h + simp [log_inv, mul_neg, ← neg_mul, ← negMulLog_def, differentiableAt_negMulLog_iff] at h + fun_prop (disch := simp) + · rw [DifferentiableAt.add_iff_right, differentiableAt_iff_comp_const_sub (b := 1)] at h + simp [log_inv, mul_neg, ← neg_mul, ← negMulLog_def, differentiableAt_negMulLog_iff] at h + fun_prop (disch := simp) + +set_option push_neg.use_distrib true in +/-- Binary entropy has derivative `log (1 - p) - log p`. +It's not differentiable at `0` or `1` but the junk values of `deriv` and `log` coincide there. -/ +lemma deriv_binEntropy (p : ℝ) : deriv binEntropy p = log (1 - p) - log p := by + by_cases hp : p ≠ 0 ∧ p ≠ 1 + · obtain ⟨hp₀, hp₁⟩ := hp + rw [ne_comm, ← sub_ne_zero] at hp₁ + rw [binEntropy_eq_negMulLog_add_negMulLog_one_sub', deriv_add, deriv_comp_const_sub, + deriv_negMulLog hp₀, deriv_negMulLog hp₁] + ring + all_goals fun_prop (disch := assumption) + -- pathological case where `deriv = 0` since `binEntropy` is not differentiable there + · rw [deriv_zero_of_not_differentiableAt (differentiableAt_binEntropy_iff_ne_zero_one.not.2 hp)] + push_neg at hp + obtain rfl | rfl := hp <;> simp + +/-! ### `q`-ary entropy -/ + +/-- Shannon q-ary Entropy function (measured in Nats, i.e., using natural logs). + +It's the Shannon entropy of a random variable with possible outcomes {1, ..., q} +where outcome `1` has probability `1 - p` and all other outcomes are equally likely. + +The usual domain of definition is p ∈ [0,1], i.e., input is a probability. + +This is a generalization of the binary entropy function `binEntropy`. -/ +@[pp_nodot] noncomputable def qaryEntropy (q : ℕ) (p : ℝ) : ℝ := p * log (q - 1 : ℤ) + binEntropy p + +@[simp] lemma qaryEntropy_zero (q : ℕ) : qaryEntropy q 0 = 0 := by simp [qaryEntropy] +@[simp] lemma qaryEntropy_one (q : ℕ) : qaryEntropy q 1 = log (q - 1 : ℤ) := by simp [qaryEntropy] +@[simp] lemma qaryEntropy_two : qaryEntropy 2 = binEntropy := by ext; simp [qaryEntropy] + +lemma qaryEntropy_pos (hp₀ : 0 < p) (hp₁ : p < 1) : 0 < qaryEntropy q p := by + unfold qaryEntropy + have := binEntropy_pos hp₀ hp₁ + positivity + +lemma qaryEntropy_nonneg (hp₀ : 0 ≤ p) (hp₁ : p ≤ 1) : 0 ≤ qaryEntropy q p := by + obtain rfl | hp₀ := hp₀.eq_or_lt + · simp + obtain rfl | hp₁ := hp₁.eq_or_lt + · simpa [qaryEntropy, -Int.cast_sub] using log_intCast_nonneg _ + exact (qaryEntropy_pos hp₀ hp₁).le + +/-- Outside the usual range of `qaryEntropy`, it is negative. This is due to `log p = log |p|`. -/ +lemma qaryEntropy_neg_of_neg (hp : p < 0) : qaryEntropy q p < 0 := + add_neg_of_nonpos_of_neg (mul_nonpos_of_nonpos_of_nonneg hp.le (log_intCast_nonneg _)) + (binEntropy_neg_of_neg hp) + +/-- Outside the usual range of `qaryEntropy`, it is negative. This is due to `log p = log |p|`. -/ +lemma qaryEntropy_nonpos_of_nonpos (hp : p ≤ 0) : qaryEntropy q p ≤ 0 := + add_nonpos (mul_nonpos_of_nonpos_of_nonneg hp (log_intCast_nonneg _)) + (binEntropy_nonpos_of_nonpos hp) + +/-- The q-ary entropy function is continuous everywhere. +This is due to definition of `Real.log` for negative numbers. -/ +@[fun_prop] lemma qaryEntropy_continuous : Continuous (qaryEntropy q) := by + unfold qaryEntropy; fun_prop + +@[fun_prop] lemma differentiableAt_qaryEntropy (hp₀ : p ≠ 0) (hp₁ : p ≠ 1) : + DifferentiableAt ℝ (qaryEntropy q) p := by unfold qaryEntropy; fun_prop (disch := assumption) + +lemma deriv_qaryEntropy (hp₀ : p ≠ 0) (hp₁ : p ≠ 1) : + deriv (qaryEntropy q) p = log (q - 1) + log (1 - p) - log p := by + unfold qaryEntropy + rw [deriv_add] + simp only [Int.cast_sub, Int.cast_natCast, Int.cast_one, differentiableAt_id', deriv_mul_const, + deriv_id'', one_mul, deriv_binEntropy, add_sub_assoc] + all_goals fun_prop (disch := assumption) + +/-- Binary entropy has derivative `log (1 - p) - log p`. -/ +lemma hasDerivAt_binEntropy (hp₀ : p ≠ 0) (hp₁ : p ≠ 1) : + HasDerivAt binEntropy (log (1 - p) - log p) p := + deriv_binEntropy _ ▸ (differentiableAt_binEntropy hp₀ hp₁).hasDerivAt + +lemma hasDerivAt_qaryEntropy (hp₀ : p ≠ 0) (hp₁ : p ≠ 1) : + HasDerivAt (qaryEntropy q) (log (q - 1) + log (1 - p) - log p) p := + deriv_qaryEntropy hp₀ hp₁ ▸ (differentiableAt_qaryEntropy hp₀ hp₁).hasDerivAt + +open Filter Topology Set + +private lemma tendsto_log_one_sub_sub_log_nhdsWithin_atAtop : + Tendsto (fun p ↦ log (1 - p) - log p) (𝓝[>] 0) atTop := by + apply Filter.tendsto_atTop_add_left_of_le' (𝓝[>] 0) (log (1/2) : ℝ) + · have h₁ : (0 : ℝ) < 1 / 2 := by norm_num + filter_upwards [Ioc_mem_nhdsWithin_Ioi' h₁] with p hx + gcongr + linarith [hx.2] + · apply tendsto_neg_atTop_iff.mpr tendsto_log_nhdsWithin_zero_right + +private lemma tendsto_log_one_sub_sub_log_nhdsWithin_one_atBot : + Tendsto (fun p ↦ log (1 - p) - log p) (𝓝[<] 1) atBot := by + apply Filter.tendsto_atBot_add_right_of_ge' (𝓝[<] 1) (-log (1 - 2⁻¹)) + · have : Tendsto log (𝓝[>] 0) atBot := Real.tendsto_log_nhdsWithin_zero_right + apply Tendsto.comp (f := (1 - ·)) (g := log) this + have contF : Continuous ((1 : ℝ) - ·) := continuous_sub_left 1 + have : MapsTo ((1 : ℝ) - ·) (Iio 1) (Ioi 0) := by + intro p hx + simp_all only [mem_Iio, mem_Ioi, sub_pos] + convert ContinuousWithinAt.tendsto_nhdsWithin (x :=(1 : ℝ)) contF.continuousWithinAt this + exact Eq.symm (sub_eq_zero_of_eq rfl) + · have h₁ : (1 : ℝ) - (2 : ℝ)⁻¹ < 1 := by norm_num + filter_upwards [Ico_mem_nhdsWithin_Iio' h₁] with p hx + gcongr + exact hx.1 + +lemma not_continuousAt_deriv_qaryEntropy_one : + ¬ContinuousAt (deriv (qaryEntropy q)) 1 := by + have tendstoBot : Tendsto (fun p ↦ log (q - 1) + log (1 - p) - log p) (𝓝[<] 1) atBot := by + have : (fun p ↦ log (q - 1) + log (1 - p) - log p) + = (fun p ↦ log (q - 1) + (log (1 - p) - log p)) := by + ext + ring + rw [this] + apply tendsto_atBot_add_const_left + exact tendsto_log_one_sub_sub_log_nhdsWithin_one_atBot + apply not_continuousAt_of_tendsto (Filter.Tendsto.congr' _ tendstoBot) nhdsWithin_le_nhds + simp only [disjoint_nhds_atBot_iff, not_isBot, not_false_eq_true] + filter_upwards [Ioo_mem_nhdsWithin_Iio' (show 1 - 2⁻¹ < (1 : ℝ) by norm_num)] + intros + apply (deriv_qaryEntropy _ _).symm + simp_all only [mem_Ioo, ne_eq] + · linarith [show (1 : ℝ) = 2⁻¹ + 2⁻¹ by norm_num] + · simp_all only [mem_Ioo, ne_eq] + linarith [two_inv_lt_one (α := ℝ)] + +lemma not_continuousAt_deriv_qaryEntropy_zero : + ¬ContinuousAt (deriv (qaryEntropy q)) 0 := by + have tendstoTop : Tendsto (fun p ↦ log (q - 1) + log (1 - p) - log p) (𝓝[>] 0) atTop := by + have : (fun p ↦ log (q - 1) + log (1 - p) - log p) + = (fun p ↦ log (q - 1) + (log (1 - p) - log p)) := by ext; ring + rw [this] + exact tendsto_atTop_add_const_left _ _ tendsto_log_one_sub_sub_log_nhdsWithin_atAtop + apply not_continuousAt_of_tendsto (Filter.Tendsto.congr' _ tendstoTop) nhdsWithin_le_nhds + simp only [disjoint_nhds_atTop_iff, not_isTop, not_false_eq_true] + filter_upwards [Ioo_mem_nhdsWithin_Ioi' (show (0 : ℝ) < 2⁻¹ by norm_num)] + intros + apply (deriv_qaryEntropy _ _).symm + simp_all only [zero_add, mem_Ioo, ne_eq] + · linarith + · simp_all only [zero_add, mem_Ioo, ne_eq] + linarith [two_inv_lt_one (α := ℝ)] + +/-- Second derivative of q-ary entropy. -/ +lemma deriv2_qaryEntropy : + deriv^[2] (qaryEntropy q) p = -1 / (p * (1 - p)) := by + simp only [Function.iterate_succ, Function.iterate_zero, Function.id_comp, Function.comp_apply] + by_cases is_x_where_nondiff : p ≠ 0 ∧ p ≠ 1 -- normal case + · obtain ⟨xne0, xne1⟩ := is_x_where_nondiff + suffices ∀ᶠ y in (𝓝 p), + deriv (fun p ↦ (qaryEntropy q) p) y = log (q - 1) + log (1 - y) - log y by + refine (Filter.EventuallyEq.deriv_eq this).trans ?_ + rw [deriv_sub ?_ (differentiableAt_log xne0)] + · rw [deriv.log differentiableAt_id' xne0] + simp only [deriv_id'', one_div] + · have {q : ℝ} (p : ℝ) : DifferentiableAt ℝ (fun p => q - p) p := by fun_prop + have d_oneminus (p : ℝ) : deriv (fun (y : ℝ) ↦ 1 - y) p = -1 := by + rw [deriv_const_sub 1, deriv_id''] + field_simp [sub_ne_zero_of_ne xne1.symm, this, d_oneminus] + ring + · apply DifferentiableAt.add + simp only [ne_eq, differentiableAt_const] + exact DifferentiableAt.log (by fun_prop) (sub_ne_zero.mpr xne1.symm) + filter_upwards [eventually_ne_nhds xne0, eventually_ne_nhds xne1] + with y xne0 h2 using deriv_qaryEntropy xne0 h2 + -- Pathological case where we use junk value (because function not differentiable) + · have : p = 0 ∨ p = 1 := Decidable.or_iff_not_and_not.mpr is_x_where_nondiff + rw [deriv_zero_of_not_differentiableAt] + · simp_all only [ne_eq, not_and, Decidable.not_not] + cases this <;> simp_all only [ + mul_zero, one_ne_zero, zero_ne_one, sub_zero, mul_one, div_zero, sub_self] + · intro h + have contAt := h.continuousAt + cases this <;> simp_all [ + not_continuousAt_deriv_qaryEntropy_zero, not_continuousAt_deriv_qaryEntropy_one, contAt] + +lemma deriv2_binEntropy : deriv^[2] binEntropy p = -1 / (p * (1 - p)) := + qaryEntropy_two ▸ deriv2_qaryEntropy + +/-! ### Strict monotonicity of entropy -/ + +/-- Qary entropy is strictly increasing in the interval [0, 1 - q⁻¹]. -/ +lemma qaryEntropy_strictMonoOn (qLe2 : 2 ≤ q) : + StrictMonoOn (qaryEntropy q) (Icc 0 (1 - 1/q)) := by + intro p1 hp1 p2 hp2 p1le2 + apply strictMonoOn_of_deriv_pos (convex_Icc 0 (1 - 1/(q : ℝ))) _ _ hp1 hp2 p1le2 + · exact qaryEntropy_continuous.continuousOn + · intro p hp + have : 2 ≤ (q : ℝ) := Nat.ofNat_le_cast.mpr qLe2 + have zero_le_qinv : 0 < (q : ℝ)⁻¹ := by positivity + have : 0 < 1 - p := by + simp only [sub_pos, hp.2] + have p_lt_1_minus_qinv : p < 1 - (q : ℝ)⁻¹ := by + simp_all only [inv_pos, interior_Icc, mem_Ioo, one_div] + linarith + simp only [one_div, interior_Icc, mem_Ioo] at hp + rw [deriv_qaryEntropy (by linarith)] + · field_simp + rw [← log_mul (by linarith) (by linarith)] + apply Real.strictMonoOn_log (mem_Ioi.mpr hp.1) + · simp_all only [mem_Ioi, mul_pos_iff_of_pos_left, show 0 < (q : ℝ) - 1 by linarith] + · have qpos : 0 < (q : ℝ) := by positivity + have : q * p < q - 1 := by + convert (mul_lt_mul_left qpos).2 hp.2 using 1 + simp only [mul_sub, mul_one, isUnit_iff_ne_zero, ne_eq, ne_of_gt qpos, not_false_eq_true, + IsUnit.mul_inv_cancel] + linarith + exact (ne_of_gt (lt_add_neg_iff_lt.mp this : p < 1)).symm + +/-- Qary entropy is strictly decreasing in the interval [1 - q⁻¹, 1]. -/ +lemma qaryEntropy_strictAntiOn (qLe2 : 2 ≤ q) : + StrictAntiOn (qaryEntropy q) (Icc (1 - 1/q) 1) := by + intro p1 hp1 p2 hp2 p1le2 + apply strictAntiOn_of_deriv_neg (convex_Icc (1 - 1/(q : ℝ)) 1) _ _ hp1 hp2 p1le2 + · 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 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)] + · field_simp + rw [← log_mul (by linarith) (by linarith)] + apply Real.strictMonoOn_log (mem_Ioi.mpr (show 0 < (↑q - 1) * (1 - p) by nlinarith)) + · simp_all only [mem_Ioi, mul_pos_iff_of_pos_left] + linarith + · have qpos : 0 < (q : ℝ) := by positivity + ring_nf + simp only [add_lt_iff_neg_right, neg_add_lt_iff_lt_add, add_zero, gt_iff_lt] + have : (q : ℝ) - 1 < p * q := by + have tmp := mul_lt_mul_of_pos_right hp.1 qpos + simp at tmp + have : (q : ℝ) ≠ 0 := (ne_of_lt qpos).symm + have asdfasfd : (1 - (q : ℝ)⁻¹) * ↑q = q - 1 := by calc (1 - (q : ℝ)⁻¹) * ↑q + _ = q - (q : ℝ)⁻¹ * (q : ℝ) := by ring + _ = q - 1 := by simp_all only [ne_eq, isUnit_iff_ne_zero, Rat.cast_eq_zero, + not_false_eq_true, IsUnit.inv_mul_cancel] + rwa [asdfasfd] at tmp + nlinarith + exact (ne_of_gt (lt_add_neg_iff_lt.mp zero_lt_1_sub_p : p < 1)).symm + +/-- Binary entropy is strictly increasing in interval [0, 1/2]. -/ +lemma binEntropy_strictMonoOn : StrictMonoOn binEntropy (Icc 0 2⁻¹) := by + rw [show Icc (0 : ℝ) 2⁻¹ = Icc 0 (1 - 1/2) by norm_num, ← qaryEntropy_two] + exact qaryEntropy_strictMonoOn (by rfl) + +/-- Binary entropy is strictly decreasing in interval [1/2, 1]. -/ +lemma binEntropy_strictAntiOn : StrictAntiOn binEntropy (Icc 2⁻¹ 1) := by + rw [show (Icc (2⁻¹ : ℝ) 1) = Icc (1/2) 1 by norm_num, ← qaryEntropy_two] + convert qaryEntropy_strictAntiOn (by rfl) using 1 + norm_num + +/-! ### Strict concavity of entropy -/ + +lemma strictConcaveOn_qaryEntropy : StrictConcaveOn ℝ (Icc 0 1) (qaryEntropy q) := by + apply strictConcaveOn_of_deriv2_neg (convex_Icc 0 1) qaryEntropy_continuous.continuousOn + intro p hp + rw [deriv2_qaryEntropy] + · simp_all only [interior_Icc, mem_Ioo] + apply div_neg_of_neg_of_pos + norm_num [show 0 < log 2 by positivity] + simp_all only [gt_iff_lt, mul_pos_iff_of_pos_left, sub_pos, hp] + +lemma strictConcave_binEntropy : StrictConcaveOn ℝ (Icc 0 1) binEntropy := + qaryEntropy_two ▸ strictConcaveOn_qaryEntropy + +end Real diff --git a/Mathlib/Analysis/SpecialFunctions/Complex/Arctan.lean b/Mathlib/Analysis/SpecialFunctions/Complex/Arctan.lean index 352fd5d5ee08d..d9d625ead931a 100644 --- a/Mathlib/Analysis/SpecialFunctions/Complex/Arctan.lean +++ b/Mathlib/Analysis/SpecialFunctions/Complex/Arctan.lean @@ -74,7 +74,7 @@ theorem arctan_tan {z : ℂ} (h₀ : z ≠ π / 2) (h₁ : -(π / 2) < z.re) (h 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 [← le_div_iff' two_pos] + · rwa [← le_div_iff₀' two_pos] @[simp, norm_cast] theorem ofReal_arctan (x : ℝ) : (Real.arctan x : ℂ) = arctan x := by diff --git a/Mathlib/Analysis/SpecialFunctions/Complex/Arg.lean b/Mathlib/Analysis/SpecialFunctions/Complex/Arg.lean index 57b6747ca5744..94901e3540e4f 100644 --- a/Mathlib/Analysis/SpecialFunctions/Complex/Arg.lean +++ b/Mathlib/Analysis/SpecialFunctions/Complex/Arg.lean @@ -154,7 +154,7 @@ theorem arg_nonneg_iff {z : ℂ} : 0 ≤ arg z ↔ 0 ≤ z.im := by contrapose! intro h exact Real.sin_neg_of_neg_of_neg_pi_lt h (neg_pi_lt_arg _)⟩ - _ ↔ _ := by rw [sin_arg, le_div_iff (abs.pos h₀), zero_mul] + _ ↔ _ := by rw [sin_arg, le_div_iff₀ (abs.pos h₀), zero_mul] @[simp] theorem arg_neg_iff {z : ℂ} : arg z < 0 ↔ z.im < 0 := @@ -192,7 +192,7 @@ theorem arg_neg_I : arg (-I) = -(π / 2) := by simp [arg, le_refl] theorem tan_arg (x : ℂ) : Real.tan (arg x) = x.im / x.re := by by_cases h : x = 0 · simp only [h, zero_div, Complex.zero_im, Complex.arg_zero, Real.tan_zero, Complex.zero_re] - rw [Real.tan_eq_sin_div_cos, sin_arg, cos_arg h, div_div_div_cancel_right _ (abs.ne_zero h)] + rw [Real.tan_eq_sin_div_cos, sin_arg, cos_arg h, div_div_div_cancel_right₀ (abs.ne_zero h)] theorem arg_ofReal_of_nonneg {x : ℝ} (hx : 0 ≤ x) : arg x = 0 := by simp [arg, hx] diff --git a/Mathlib/Analysis/SpecialFunctions/Complex/Circle.lean b/Mathlib/Analysis/SpecialFunctions/Complex/Circle.lean index 0b7ee63908505..6ff1439a9f28c 100644 --- a/Mathlib/Analysis/SpecialFunctions/Complex/Circle.lean +++ b/Mathlib/Analysis/SpecialFunctions/Complex/Circle.lean @@ -29,7 +29,7 @@ theorem arg_eq_arg {z w : Circle} : arg z = arg w ↔ z = w := injective_arg.eq_iff theorem arg_exp {x : ℝ} (h₁ : -π < x) (h₂ : x ≤ π) : arg (exp x) = x := by - rw [exp_apply, exp_mul_I, arg_cos_add_sin_mul_I ⟨h₁, h₂⟩] + rw [coe_exp, exp_mul_I, arg_cos_add_sin_mul_I ⟨h₁, h₂⟩] @[simp] theorem exp_arg (z : Circle) : exp (arg z) = z := @@ -64,7 +64,7 @@ lemma invOn_arg_exp : InvOn (arg ∘ (↑)) exp (Ioc (-π) π) univ := argPartia lemma surjOn_exp_neg_pi_pi : SurjOn exp (Ioc (-π) π) univ := argPartialEquiv.symm.surjOn lemma exp_eq_exp {x y : ℝ} : exp x = exp y ↔ ∃ m : ℤ, x = y + m * (2 * π) := by - rw [Subtype.ext_iff, exp_apply, exp_apply, exp_eq_exp_iff_exists_int] + rw [Subtype.ext_iff, coe_exp, coe_exp, exp_eq_exp_iff_exists_int] refine exists_congr fun n => ?_ rw [← mul_assoc, ← add_mul, mul_left_inj' I_ne_zero] norm_cast @@ -73,6 +73,16 @@ lemma periodic_exp : Periodic exp (2 * π) := fun z ↦ exp_eq_exp.2 ⟨1, by rw @[simp] lemma exp_two_pi : exp (2 * π) = 1 := periodic_exp.eq.trans exp_zero +lemma exp_int_mul_two_pi (n : ℤ) : exp (n * (2 * π)) = 1 := + ext <| by simpa [mul_assoc] using Complex.exp_int_mul_two_pi_mul_I n + +lemma exp_two_pi_mul_int (n : ℤ) : exp (2 * π * n) = 1 := by + simpa only [mul_comm] using exp_int_mul_two_pi n + +lemma exp_eq_one {r : ℝ} : exp r = 1 ↔ ∃ n : ℤ, r = n * (2 * π) := by + simp [Circle.ext_iff, Complex.exp_eq_one_iff, ← mul_assoc, Complex.I_ne_zero, + ← Complex.ofReal_inj] + lemma exp_sub_two_pi (x : ℝ) : exp (x - 2 * π) = exp x := periodic_exp.sub_eq x lemma exp_add_two_pi (x : ℝ) : exp (x + 2 * π) = exp x := periodic_exp x @@ -115,7 +125,7 @@ lemma coe_toCircle (θ : Angle) : (θ.toCircle : ℂ) = θ.cos + θ.sin * I := b @[simp] lemma arg_toCircle (θ : Real.Angle) : (arg θ.toCircle : Angle) = θ := by induction θ using Real.Angle.induction_on - rw [toCircle_coe, Circle.exp_apply, exp_mul_I, ← ofReal_cos, ← ofReal_sin, ← + rw [toCircle_coe, Circle.coe_exp, exp_mul_I, ← ofReal_cos, ← ofReal_sin, ← Real.Angle.cos_coe, ← Real.Angle.sin_coe, arg_cos_add_sin_mul_I_coe_angle] @[deprecated (since := "2024-07-25")] alias expMapCircle := toCircle diff --git a/Mathlib/Analysis/SpecialFunctions/Complex/CircleAddChar.lean b/Mathlib/Analysis/SpecialFunctions/Complex/CircleAddChar.lean index 02804c44f2602..b00a93b87b285 100644 --- a/Mathlib/Analysis/SpecialFunctions/Complex/CircleAddChar.lean +++ b/Mathlib/Analysis/SpecialFunctions/Complex/CircleAddChar.lean @@ -47,7 +47,7 @@ noncomputable def toCircle : AddChar (ZMod N) Circle := lemma toCircle_intCast (j : ℤ) : toCircle (j : ZMod N) = exp (2 * π * I * j / N) := by rw [toCircle, AddChar.compAddMonoidHom_apply, toCircle_addChar, AddChar.coe_mk, - AddCircle.toCircle, toAddCircle_intCast, Function.Periodic.lift_coe, Circle.exp_apply] + AddCircle.toCircle, toAddCircle_intCast, Function.Periodic.lift_coe, Circle.coe_exp] push_cast ring_nf diff --git a/Mathlib/Analysis/SpecialFunctions/Complex/Log.lean b/Mathlib/Analysis/SpecialFunctions/Complex/Log.lean index 97e787098b93d..ad7f981e284ec 100644 --- a/Mathlib/Analysis/SpecialFunctions/Complex/Log.lean +++ b/Mathlib/Analysis/SpecialFunctions/Complex/Log.lean @@ -243,3 +243,69 @@ theorem _root_.Continuous.clog {f : α → ℂ} (h₁ : Continuous f) continuous_iff_continuousAt.2 fun x => h₁.continuousAt.clog (h₂ x) end LogDeriv + +section tsum_tprod + +variable {α ι: Type*} + +open Real + +lemma Real.HasSum_rexp_HasProd (f : ι → α → ℝ) (hfn : ∀ x n, 0 < f n x) + (hf : ∀ x : α, HasSum (fun n => log (f n x)) (∑' i, log (f i x))) (a : α) : + HasProd (fun b ↦ f b a) (∏' n : ι, (f n a)) := by + have : HasProd (fun b ↦ f b a) ((rexp ∘ fun a ↦ ∑' (n : ι), log (f n a)) a) := by + apply ((hf a).rexp).congr + intro _ + congr + exact funext fun x ↦ exp_log (hfn a x) + rwa [HasProd.tprod_eq this] + + +/--The exponential of a infinite sum of real logs (which converges absolutely) is an infinite +product.-/ +lemma Real.rexp_tsum_eq_tprod (f : ι → α → ℝ) (hfn : ∀ x n, 0 < f n x) + (hf : ∀ x : α, Summable fun n => log ((f n x))) : + (rexp ∘ (fun a : α => (∑' n : ι, log (f n a)))) = (fun a : α => ∏' n : ι, (f n a)) := by + ext a + apply (HasProd.tprod_eq ?_).symm + apply ((hf a).hasSum.rexp).congr + intro _ + congr + exact funext fun x ↦ exp_log (hfn a x) + +lemma Real.summable_cexp_multipliable (f : ι → α → ℝ) (hfn : ∀ x n, 0 < f n x) + (hf : ∀ x : α, Summable fun n => log (f n x)) (a : α): Multipliable fun b ↦ f b a := by + have := (Real.HasSum_rexp_HasProd f hfn fun a => (hf a).hasSum) a + use (∏' n : ι, (f n a)) + +open Complex + +lemma Complex.HasSum_cexp_HasProd (f : ι → α → ℂ) (hfn : ∀ x n, f n x ≠ 0) + (hf : ∀ x : α, HasSum (fun n => log (f n x)) (∑' i, log (f i x))) (a : α) : + HasProd (fun b ↦ f b a) (∏' n : ι, (f n a)) := by + have : HasProd (fun b ↦ f b a) ((cexp ∘ fun a ↦ ∑' (n : ι), log (f n a)) a) := by + apply ((hf a).cexp).congr + intro _ + congr + exact funext fun x ↦ exp_log (hfn a x) + rwa [HasProd.tprod_eq this] + +lemma Complex.summable_cexp_multipliable (f : ι → α → ℂ) (hfn : ∀ x n, f n x ≠ 0) + (hf : ∀ x : α, Summable fun n => log (f n x)) (a : α): + Multipliable fun b ↦ f b a := by + have := (Complex.HasSum_cexp_HasProd f hfn fun a => (hf a).hasSum) a + use (∏' n : ι, (f n a)) + +/--The exponential of a infinite sum of comples logs (which converges absolutely) is an infinite +product.-/ +lemma Complex.cexp_tsum_eq_tprod (f : ι → α → ℂ) (hfn : ∀ x n, f n x ≠ 0) + (hf : ∀ x : α, Summable fun n => log (f n x)) : + (cexp ∘ (fun a : α => (∑' n : ι, log (f n a)))) = (fun a : α => ∏' n : ι, ((f n a))) := by + ext a + apply (HasProd.tprod_eq ?_).symm + apply ((hf a).hasSum.cexp).congr + intro _ + congr + exact funext fun x ↦ exp_log (hfn a x) + +end tsum_tprod diff --git a/Mathlib/Analysis/SpecialFunctions/Complex/LogBounds.lean b/Mathlib/Analysis/SpecialFunctions/Complex/LogBounds.lean index 695b5f7943f0f..7d994e5d897af 100644 --- a/Mathlib/Analysis/SpecialFunctions/Complex/LogBounds.lean +++ b/Mathlib/Analysis/SpecialFunctions/Complex/LogBounds.lean @@ -60,7 +60,7 @@ def logTaylor (n : ℕ) : ℂ → ℂ := fun z ↦ ∑ j ∈ Finset.range n, (-1 lemma logTaylor_zero : logTaylor 0 = fun _ ↦ 0 := by funext - simp only [logTaylor, Finset.range_zero, Nat.odd_iff_not_even, Int.cast_pow, Int.cast_neg, + simp only [logTaylor, Finset.range_zero, ← Nat.not_even_iff_odd, Int.cast_pow, Int.cast_neg, Int.cast_one, Finset.sum_empty] lemma logTaylor_succ (n : ℕ) : @@ -79,10 +79,10 @@ lemma hasDerivAt_logTaylor (n : ℕ) (z : ℂ) : | zero => simp [logTaylor_succ, logTaylor_zero, Pi.add_def, hasDerivAt_const] | succ n ih => rw [logTaylor_succ] - simp only [cpow_natCast, Nat.cast_add, Nat.cast_one, Nat.odd_iff_not_even, + simp only [cpow_natCast, Nat.cast_add, Nat.cast_one, ← Nat.not_even_iff_odd, Finset.sum_range_succ, (show (-1) ^ (n + 1 + 1) = (-1) ^ n by ring)] refine HasDerivAt.add ih ?_ - simp only [Nat.odd_iff_not_even, Int.cast_pow, Int.cast_neg, Int.cast_one, mul_div_assoc] + simp only [← Nat.not_even_iff_odd, Int.cast_pow, Int.cast_neg, Int.cast_one, mul_div_assoc] have : HasDerivAt (fun x : ℂ ↦ (x ^ (n + 1) / (n + 1))) (z ^ n) z := by simp_rw [div_eq_mul_inv] convert HasDerivAt.mul_const (hasDerivAt_pow (n + 1) z) (((n : ℂ) + 1)⁻¹) using 1 @@ -188,7 +188,7 @@ lemma norm_log_one_add_le {z : ℂ} (hz : ‖z‖ < 1) : lemma norm_log_one_add_half_le_self {z : ℂ} (hz : ‖z‖ ≤ 1/2) : ‖(log (1 + z))‖ ≤ (3/2) * ‖z‖ := by apply le_trans (norm_log_one_add_le (lt_of_le_of_lt hz one_half_lt_one)) have hz3 : (1 - ‖z‖)⁻¹ ≤ 2 := by - rw [inv_eq_one_div, div_le_iff] + rw [inv_eq_one_div, div_le_iff₀] · linarith · linarith have hz4 : ‖z‖^2 * (1 - ‖z‖)⁻¹ / 2 ≤ ‖z‖/2 * 2 / 2 := by @@ -227,7 +227,7 @@ lemma hasSum_taylorSeries_log {z : ℂ} (hz : ‖z‖ < 1) : refine (hasSum_iff_tendsto_nat_of_summable_norm ?_).mpr ?_ · refine (summable_geometric_of_norm_lt_one hz).norm.of_nonneg_of_le (fun _ ↦ norm_nonneg _) ?_ intro n - simp only [norm_div, norm_mul, norm_pow, norm_neg, norm_one, one_pow, one_mul, norm_nat] + simp only [norm_div, norm_mul, norm_pow, norm_neg, norm_one, one_pow, one_mul, norm_natCast] rcases n.eq_zero_or_pos with rfl | hn · simp conv => enter [2]; rw [← div_one (‖z‖ ^ n)] diff --git a/Mathlib/Analysis/SpecialFunctions/ContinuousFunctionalCalculus/ExpLog.lean b/Mathlib/Analysis/SpecialFunctions/ContinuousFunctionalCalculus/ExpLog.lean index 4879f5d427b76..2986597856fcc 100644 --- a/Mathlib/Analysis/SpecialFunctions/ContinuousFunctionalCalculus/ExpLog.lean +++ b/Mathlib/Analysis/SpecialFunctions/ContinuousFunctionalCalculus/ExpLog.lean @@ -7,6 +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 /-! # The exponential and logarithm based on the continuous functional calculus @@ -74,14 +75,21 @@ end RCLikeNormed section RealNormed -variable {A : Type*} {p : A → Prop} [NormedRing A] [StarRing A] +variable {A : Type*} [NormedRing A] [StarRing A] [TopologicalRing A] [NormedAlgebra ℝ A] [CompleteSpace A] - [ContinuousFunctionalCalculus ℝ p] + [ContinuousFunctionalCalculus ℝ (IsSelfAdjoint : A → Prop)] -lemma real_exp_eq_normedSpace_exp {a : A} (ha : p a := by cfc_tac) : +lemma real_exp_eq_normedSpace_exp {a : A} (ha : IsSelfAdjoint a := by cfc_tac) : cfc Real.exp a = exp ℝ a := Real.exp_eq_exp_ℝ ▸ exp_eq_normedSpace_exp ha +@[aesop safe apply (rule_sets := [CStarAlgebra])] +lemma _root_.IsSelfAdjoint.exp_nonneg {𝕜 : Type*} [Field 𝕜] [Algebra 𝕜 A] + [PartialOrder A] [StarOrderedRing A] {a : A} (ha : IsSelfAdjoint a) : + 0 ≤ exp 𝕜 a := by + rw [exp_eq_exp 𝕜 ℝ, ← real_exp_eq_normedSpace_exp] + exact cfc_nonneg fun x _ => Real.exp_nonneg x + end RealNormed section ComplexNormed diff --git a/Mathlib/Analysis/SpecialFunctions/Exp.lean b/Mathlib/Analysis/SpecialFunctions/Exp.lean index 89a73b0dcb128..d9317023529a2 100644 --- a/Mathlib/Analysis/SpecialFunctions/Exp.lean +++ b/Mathlib/Analysis/SpecialFunctions/Exp.lean @@ -162,7 +162,7 @@ lemma exp_sub_sum_range_isBigO_pow (n : ℕ) : (fun x ↦ exp x - ∑ i ∈ Finset.range n, x ^ i / i !) =O[𝓝 0] (· ^ n) := by have := (Complex.exp_sub_sum_range_isBigO_pow n).comp_tendsto (Complex.continuous_ofReal.tendsto' 0 0 rfl) - simp only [(· ∘ ·)] at this + simp only [Function.comp_def] at this norm_cast at this lemma exp_sub_sum_range_succ_isLittleO_pow (n : ℕ) : @@ -213,7 +213,7 @@ namespace Real variable {α : Type*} {x y z : ℝ} {l : Filter α} theorem exp_half (x : ℝ) : exp (x / 2) = √(exp x) := by - rw [eq_comm, sqrt_eq_iff_sq_eq, sq, ← exp_add, add_halves] <;> exact (exp_pos _).le + rw [eq_comm, sqrt_eq_iff_eq_sq, sq, ← exp_add, add_halves] <;> exact (exp_pos _).le /-- The real exponential function tends to `+∞` at `+∞`. -/ theorem tendsto_exp_atTop : Tendsto exp atTop atTop := by @@ -267,7 +267,7 @@ theorem tendsto_exp_div_pow_atTop (n : ℕ) : Tendsto (fun x => exp x / x ^ n) a refine ⟨N, trivial, fun x hx => ?_⟩ rw [Set.mem_Ioi] at hx have hx₀ : 0 < x := (Nat.cast_nonneg N).trans_lt hx - rw [Set.mem_Ici, le_div_iff (pow_pos hx₀ _), ← le_div_iff' hC₀] + rw [Set.mem_Ici, le_div_iff₀ (pow_pos hx₀ _), ← le_div_iff₀' hC₀] calc x ^ n ≤ ⌈x⌉₊ ^ n := mod_cast pow_le_pow_left hx₀.le (Nat.le_ceil _) _ _ ≤ exp ⌈x⌉₊ / (exp 1 * C) := mod_cast (hN _ (Nat.lt_ceil.2 hx).le).le @@ -315,8 +315,8 @@ theorem tendsto_div_pow_mul_exp_add_atTop (b c : ℝ) (n : ℕ) (hb : 0 ≠ b) : def expOrderIso : ℝ ≃o Ioi (0 : ℝ) := StrictMono.orderIsoOfSurjective _ (exp_strictMono.codRestrict exp_pos) <| (continuous_exp.subtype_mk _).surjective - (by simp only [tendsto_Ioi_atTop, Subtype.coe_mk, tendsto_exp_atTop]) - (by simp [tendsto_exp_atBot_nhdsWithin]) + (by rw [tendsto_Ioi_atTop]; simp only [tendsto_exp_atTop]) + (by rw [tendsto_Ioi_atBot]; simp only [tendsto_exp_atBot_nhdsWithin]) @[simp] theorem coe_expOrderIso_apply (x : ℝ) : (expOrderIso x : ℝ) = exp x := @@ -456,14 +456,14 @@ namespace Complex theorem comap_exp_cobounded : comap exp (cobounded ℂ) = comap re atTop := calc comap exp (cobounded ℂ) = comap re (comap Real.exp atTop) := by - simp only [← comap_norm_atTop, Complex.norm_eq_abs, comap_comap, (· ∘ ·), abs_exp] + simp only [← comap_norm_atTop, Complex.norm_eq_abs, comap_comap, Function.comp_def, abs_exp] _ = comap re atTop := by rw [Real.comap_exp_atTop] @[simp] theorem comap_exp_nhds_zero : comap exp (𝓝 0) = comap re atBot := calc comap exp (𝓝 0) = comap re (comap Real.exp (𝓝 0)) := by - simp only [comap_comap, ← comap_abs_nhds_zero, (· ∘ ·), abs_exp] + simp only [comap_comap, ← comap_abs_nhds_zero, Function.comp_def, abs_exp] _ = comap re atBot := by rw [Real.comap_exp_nhds_zero] theorem comap_exp_nhdsWithin_zero : comap exp (𝓝[≠] 0) = comap re atBot := by diff --git a/Mathlib/Analysis/SpecialFunctions/Gamma/Basic.lean b/Mathlib/Analysis/SpecialFunctions/Gamma/Basic.lean index d07803c56bc15..c12393d6b86df 100644 --- a/Mathlib/Analysis/SpecialFunctions/Gamma/Basic.lean +++ b/Mathlib/Analysis/SpecialFunctions/Gamma/Basic.lean @@ -461,7 +461,7 @@ end GammaHasDeriv theorem tendsto_self_mul_Gamma_nhds_zero : Tendsto (fun z : ℂ => z * Gamma z) (𝓝[≠] 0) (𝓝 1) := by rw [show 𝓝 (1 : ℂ) = 𝓝 (Gamma (0 + 1)) by simp only [zero_add, Complex.Gamma_one]] convert (Tendsto.mono_left _ nhdsWithin_le_nhds).congr' - (eventuallyEq_of_mem self_mem_nhdsWithin Complex.Gamma_add_one) + (eventuallyEq_of_mem self_mem_nhdsWithin Complex.Gamma_add_one) using 1 refine ContinuousAt.comp (g := Gamma) ?_ (continuous_id.add continuous_const).continuousAt refine (Complex.differentiableAt_Gamma _ fun m => ?_).continuousAt rw [zero_add, ← ofReal_natCast, ← ofReal_neg, ← ofReal_one, Ne, ofReal_inj] diff --git a/Mathlib/Analysis/SpecialFunctions/Gamma/Beta.lean b/Mathlib/Analysis/SpecialFunctions/Gamma/Beta.lean index 674fd91181743..5b9cac12afe16 100644 --- a/Mathlib/Analysis/SpecialFunctions/Gamma/Beta.lean +++ b/Mathlib/Analysis/SpecialFunctions/Gamma/Beta.lean @@ -123,7 +123,7 @@ theorem betaIntegral_scaled (s t : ℂ) {a : ℝ} (ha : 0 < a) : push_cast rw [mul_sub, mul_one, mul_div_cancel₀ _ ha'] -/-- Relation between Beta integral and Gamma function. -/ +/-- Relation between Beta integral and Gamma function. -/ theorem Gamma_mul_Gamma_eq_betaIntegral {s t : ℂ} (hs : 0 < re s) (ht : 0 < re t) : Gamma s * Gamma t = Gamma (s + t) * betaIntegral s t := by -- Note that we haven't proved (yet) that the Gamma function has no zeroes, so we can't formulate @@ -270,7 +270,7 @@ theorem GammaSeq_eq_approx_Gamma_integral {s : ℂ} (hs : 0 < re s) {n : ℕ} (h mul_cpow_ofReal_nonneg hx.1.le (Nat.cast_pos.mpr (Nat.pos_of_ne_zero hn)).le] rw [A, B, cpow_natCast]; ring -/-- The main techical lemma for `GammaSeq_tendsto_Gamma`, expressing the integral defining the +/-- The main technical lemma for `GammaSeq_tendsto_Gamma`, expressing the integral defining the Gamma function for `0 < re s` as the limit of a sequence of integrals over finite intervals. -/ theorem approx_Gamma_integral_tendsto_Gamma_integral {s : ℂ} (hs : 0 < re s) : Tendsto (fun n : ℕ => ∫ x : ℝ in (0)..n, ((1 - x / n) ^ n : ℝ) * (x : ℂ) ^ (s - 1)) atTop diff --git a/Mathlib/Analysis/SpecialFunctions/Gamma/BohrMollerup.lean b/Mathlib/Analysis/SpecialFunctions/Gamma/BohrMollerup.lean index 7e05c6ddf0bc7..f3bd9a9a2e9a4 100644 --- a/Mathlib/Analysis/SpecialFunctions/Gamma/BohrMollerup.lean +++ b/Mathlib/Analysis/SpecialFunctions/Gamma/BohrMollerup.lean @@ -185,7 +185,7 @@ theorem f_add_nat_ge (hf_conv : ConvexOn ℝ (Ioi 0) f) -- nth_rw_rhs 1 [(by ring : (n : ℝ) = ↑n - 1 + 1)] -- rw [hf_feq npos, add_sub_cancel] rw [eq_sub_iff_add_eq, ← hf_feq npos, sub_add_cancel] - rwa [this, le_div_iff hx, sub_sub_cancel, le_sub_iff_add_le, mul_comm _ x, add_comm] at c + rwa [this, le_div_iff₀ hx, sub_sub_cancel, le_sub_iff_add_le, mul_comm _ x, add_comm] at c theorem logGammaSeq_add_one (x : ℝ) (n : ℕ) : logGammaSeq (x + 1) n = logGammaSeq x (n + 1) + log x - (x + 1) * (log (n + 1) - log n) := by diff --git a/Mathlib/Analysis/SpecialFunctions/Gamma/Deligne.lean b/Mathlib/Analysis/SpecialFunctions/Gamma/Deligne.lean index 817d564da1c98..d21123c3a6d31 100644 --- a/Mathlib/Analysis/SpecialFunctions/Gamma/Deligne.lean +++ b/Mathlib/Analysis/SpecialFunctions/Gamma/Deligne.lean @@ -28,7 +28,6 @@ This file defines these functions, and proves some elementary properties, includ formula which is an important input in functional equations of (un-completed) Dirichlet L-functions. -/ - open Filter Topology Asymptotics Real Set MeasureTheory open Complex hiding abs_of_nonneg diff --git a/Mathlib/Analysis/SpecialFunctions/Gaussian/FourierTransform.lean b/Mathlib/Analysis/SpecialFunctions/Gaussian/FourierTransform.lean index a60fa19f4171c..ea572b4ce3c4e 100644 --- a/Mathlib/Analysis/SpecialFunctions/Gaussian/FourierTransform.lean +++ b/Mathlib/Analysis/SpecialFunctions/Gaussian/FourierTransform.lean @@ -41,7 +41,7 @@ namespace GaussianFourier variable {b : ℂ} /-- The integral of the Gaussian function over the vertical edges of a rectangle -with vertices at `(±T, 0)` and `(±T, c)`. -/ +with vertices at `(±T, 0)` and `(±T, c)`. -/ def verticalIntegral (b : ℂ) (c T : ℝ) : ℂ := ∫ y : ℝ in (0 : ℝ)..c, I * (cexp (-b * (T + y * I) ^ 2) - cexp (-b * (T - y * I) ^ 2)) diff --git a/Mathlib/Analysis/SpecialFunctions/Gaussian/GaussianIntegral.lean b/Mathlib/Analysis/SpecialFunctions/Gaussian/GaussianIntegral.lean index 121367c2358ac..163d700eb16bb 100644 --- a/Mathlib/Analysis/SpecialFunctions/Gaussian/GaussianIntegral.lean +++ b/Mathlib/Analysis/SpecialFunctions/Gaussian/GaussianIntegral.lean @@ -109,7 +109,7 @@ theorem integrable_rpow_mul_exp_neg_mul_sq {b : ℝ} (hb : 0 < b) {s : ℝ} (hs refine ⟨?_, integrableOn_rpow_mul_exp_neg_mul_sq hb hs⟩ rw [← (Measure.measurePreserving_neg (volume : Measure ℝ)).integrableOn_comp_preimage (Homeomorph.neg ℝ).measurableEmbedding] - simp only [Function.comp, neg_sq, neg_preimage, preimage_neg_Iio, neg_neg, neg_zero] + simp only [Function.comp_def, neg_sq, neg_preimage, preimage_neg_Iio, neg_neg, neg_zero] apply Integrable.mono' (integrableOn_rpow_mul_exp_neg_mul_sq hb hs) · apply Measurable.aestronglyMeasurable exact (measurable_id'.neg.pow measurable_const).mul @@ -185,7 +185,7 @@ theorem integral_mul_cexp_neg_mul_sq {b : ℂ} (hb : 0 < b.re) : convert integral_Ioi_of_hasDerivAt_of_tendsto' (fun x _ => (A ↑x).comp_ofReal) (integrable_mul_cexp_neg_mul_sq hb).integrableOn B using 1 simp only [mul_zero, ofReal_zero, zero_pow, Ne, Nat.one_ne_zero, - not_false_iff, Complex.exp_zero, mul_one, sub_neg_eq_add, zero_add] + not_false_iff, Complex.exp_zero, mul_one, sub_neg_eq_add, zero_add, reduceCtorEq] /-- The *square* of the Gaussian integral `∫ x:ℝ, exp (-b * x^2)` is equal to `π / b`. -/ theorem integral_gaussian_sq_complex {b : ℂ} (hb : 0 < b.re) : diff --git a/Mathlib/Analysis/SpecialFunctions/JapaneseBracket.lean b/Mathlib/Analysis/SpecialFunctions/JapaneseBracket.lean index e596ded463560..79be49beb847d 100644 --- a/Mathlib/Analysis/SpecialFunctions/JapaneseBracket.lean +++ b/Mathlib/Analysis/SpecialFunctions/JapaneseBracket.lean @@ -119,7 +119,7 @@ theorem finite_integral_one_add_norm {r : ℝ} (hnr : (finrank ℝ E : ℝ) < r) rw [setLIntegral_congr_fun measurableSet_Ioc (ae_of_all _ h_int'), lintegral_mul_const' _ _ measure_ball_lt_top.ne] exact ENNReal.mul_lt_top - (finite_integral_rpow_sub_one_pow_aux (finrank ℝ E) hnr).ne measure_ball_lt_top.ne + (finite_integral_rpow_sub_one_pow_aux (finrank ℝ E) hnr) measure_ball_lt_top · -- The integral from 1 to ∞ is zero: have h_int'' : ∀ t ∈ Ioi (1 : ℝ), f t = 0 := fun t ht => by simp only [f, closedBall_rpow_sub_one_eq_empty_aux E hr ht, measure_empty] diff --git a/Mathlib/Analysis/SpecialFunctions/Log/Base.lean b/Mathlib/Analysis/SpecialFunctions/Log/Base.lean index 5c8d9e5532473..e537e8132736f 100644 --- a/Mathlib/Analysis/SpecialFunctions/Log/Base.lean +++ b/Mathlib/Analysis/SpecialFunctions/Log/Base.lean @@ -89,7 +89,7 @@ theorem logb_div_base {a b : ℝ} (h₁ : a ≠ 0) (h₂ : b ≠ 0) (c : ℝ) : theorem mul_logb {a b c : ℝ} (h₁ : b ≠ 0) (h₂ : b ≠ 1) (h₃ : b ≠ -1) : logb a b * logb b c = logb a c := by unfold logb - rw [mul_comm, div_mul_div_cancel _ (log_ne_zero.mpr ⟨h₁, h₂, h₃⟩)] + rw [mul_comm, div_mul_div_cancel₀ (log_ne_zero.mpr ⟨h₁, h₂, h₃⟩)] theorem div_logb {a b c : ℝ} (h₁ : c ≠ 0) (h₂ : c ≠ 1) (h₃ : c ≠ -1) : logb a c / logb b c = logb a b := diff --git a/Mathlib/Analysis/SpecialFunctions/Log/Basic.lean b/Mathlib/Analysis/SpecialFunctions/Log/Basic.lean index ffe83425fd545..4698f6d30f954 100644 --- a/Mathlib/Analysis/SpecialFunctions/Log/Basic.lean +++ b/Mathlib/Analysis/SpecialFunctions/Log/Basic.lean @@ -124,7 +124,7 @@ theorem log_le_log_iff (h : 0 < x) (h₁ : 0 < y) : log x ≤ log y ↔ x ≤ y lemma log_le_log (hx : 0 < x) (hxy : x ≤ y) : log x ≤ log y := (log_le_log_iff hx (hx.trans_le hxy)).2 hxy -@[gcongr] +@[gcongr, bound] theorem log_lt_log (hx : 0 < x) (h : x < y) : log x < log y := by rwa [← exp_lt_exp, exp_log hx, exp_log (lt_trans hx h)] @@ -143,6 +143,7 @@ theorem log_pos_iff (hx : 0 < x) : 0 < log x ↔ 1 < x := by rw [← log_one] exact log_lt_log_iff zero_lt_one hx +@[bound] theorem log_pos (hx : 1 < x) : 0 < log x := (log_pos_iff (lt_trans zero_lt_one hx)).2 hx @@ -155,6 +156,7 @@ theorem log_neg_iff (h : 0 < x) : log x < 0 ↔ x < 1 := by rw [← log_one] exact log_lt_log_iff h zero_lt_one +@[bound] theorem log_neg (h0 : 0 < x) (h1 : x < 1) : log x < 0 := (log_neg_iff h0).2 h1 @@ -177,6 +179,7 @@ theorem log_nonpos_iff' (hx : 0 ≤ x) : log x ≤ 0 ↔ x ≤ 1 := by · simp [le_refl, zero_le_one] exact log_nonpos_iff hx +@[bound] theorem log_nonpos (hx : 0 ≤ x) (h'x : x ≤ 1) : log x ≤ 0 := (log_nonpos_iff' hx).2 h'x @@ -275,6 +278,9 @@ theorem log_le_sub_one_of_pos {x : ℝ} (hx : 0 < x) : log x ≤ x - 1 := by convert add_one_le_exp (log x) rw [exp_log hx] +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) + /-- 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 diff --git a/Mathlib/Analysis/SpecialFunctions/Log/Deriv.lean b/Mathlib/Analysis/SpecialFunctions/Log/Deriv.lean index 7817f8158e5eb..958e650ae3268 100644 --- a/Mathlib/Analysis/SpecialFunctions/Log/Deriv.lean +++ b/Mathlib/Analysis/SpecialFunctions/Log/Deriv.lean @@ -47,7 +47,7 @@ theorem hasStrictDerivAt_log (hx : x ≠ 0) : HasStrictDerivAt log x⁻¹ x := b theorem hasDerivAt_log (hx : x ≠ 0) : HasDerivAt log x⁻¹ x := (hasStrictDerivAt_log hx).hasDerivAt -theorem differentiableAt_log (hx : x ≠ 0) : DifferentiableAt ℝ log x := +@[fun_prop] theorem differentiableAt_log (hx : x ≠ 0) : DifferentiableAt ℝ log x := (hasDerivAt_log hx).differentiableAt theorem differentiableOn_log : DifferentiableOn ℝ log {0}ᶜ := fun _x hx => @@ -140,7 +140,7 @@ theorem DifferentiableWithinAt.log (hf : DifferentiableWithinAt ℝ f s x) (hx : DifferentiableWithinAt ℝ (fun x => log (f x)) s x := (hf.hasFDerivWithinAt.log hx).differentiableWithinAt -@[simp] +@[simp, fun_prop] theorem DifferentiableAt.log (hf : DifferentiableAt ℝ f x) (hx : f x ≠ 0) : DifferentiableAt ℝ (fun x => log (f x)) x := (hf.hasFDerivAt.log hx).differentiableAt @@ -160,10 +160,11 @@ theorem ContDiff.log {n} (hf : ContDiff ℝ n f) (h : ∀ x, f x ≠ 0) : ContDiff ℝ n fun x => log (f x) := contDiff_iff_contDiffAt.2 fun x => hf.contDiffAt.log (h x) +@[fun_prop] theorem DifferentiableOn.log (hf : DifferentiableOn ℝ f s) (hx : ∀ x ∈ s, f x ≠ 0) : DifferentiableOn ℝ (fun x => log (f x)) s := fun x h => (hf x h).log (hx x h) -@[simp] +@[simp, fun_prop] theorem Differentiable.log (hf : Differentiable ℝ f) (hx : ∀ x, f x ≠ 0) : Differentiable ℝ fun x => log (f x) := fun x => (hf x).log (hx x) @@ -191,7 +192,7 @@ theorem tendsto_mul_log_one_plus_div_atTop (t : ℝ) : (((hasDerivAt_id (0 : ℝ)).const_mul t).const_add 1).log (by simp) have h₂ : Tendsto (fun x : ℝ => x⁻¹) atTop (𝓝[≠] 0) := tendsto_inv_atTop_zero'.mono_right (nhdsWithin_mono _ fun x hx => (Set.mem_Ioi.mp hx).ne') - simpa only [(· ∘ ·), inv_inv] using h₁.comp h₂ + simpa only [Function.comp_def, inv_inv] using h₁.comp h₂ /-- A crude lemma estimating the difference between `log (1-x)` and its Taylor series at `0`, where the main point of the bound is that it tends to `0`. The goal is to deduce the series diff --git a/Mathlib/Analysis/SpecialFunctions/Log/Monotone.lean b/Mathlib/Analysis/SpecialFunctions/Log/Monotone.lean index 7242d130a008d..c7eaabb0c3580 100644 --- a/Mathlib/Analysis/SpecialFunctions/Log/Monotone.lean +++ b/Mathlib/Analysis/SpecialFunctions/Log/Monotone.lean @@ -41,8 +41,8 @@ theorem log_div_self_antitoneOn : AntitoneOn (fun x : ℝ => log x / x) { x | ex have x_pos : 0 < x := (exp_pos 1).trans_le hex have y_pos : 0 < y := (exp_pos 1).trans_le hey have hlogx : 1 ≤ log x := by rwa [le_log_iff_exp_le x_pos] - have hyx : 0 ≤ y / x - 1 := by rwa [le_sub_iff_add_le, le_div_iff x_pos, zero_add, one_mul] - rw [div_le_iff y_pos, ← sub_le_sub_iff_right (log x)] + have hyx : 0 ≤ y / x - 1 := by rwa [le_sub_iff_add_le, le_div_iff₀ x_pos, zero_add, one_mul] + rw [div_le_iff₀ y_pos, ← sub_le_sub_iff_right (log x)] calc log y - log x = log (y / x) := by rw [log_div y_pos.ne' x_pos.ne'] _ ≤ y / x - 1 := log_le_sub_one_of_pos (div_pos y_pos x_pos) diff --git a/Mathlib/Analysis/SpecialFunctions/Log/NegMulLog.lean b/Mathlib/Analysis/SpecialFunctions/Log/NegMulLog.lean index 66773834ae8aa..681792d6a3f5e 100644 --- a/Mathlib/Analysis/SpecialFunctions/Log/NegMulLog.lean +++ b/Mathlib/Analysis/SpecialFunctions/Log/NegMulLog.lean @@ -23,6 +23,7 @@ open scoped Topology namespace Real +@[fun_prop] lemma continuous_mul_log : Continuous fun x ↦ x * log x := by rw [continuous_iff_continuousAt] intro x @@ -39,6 +40,10 @@ lemma continuous_mul_log : Continuous fun x ↦ x * log x := by · convert tendsto_pure_nhds (fun x ↦ log x * x) 0 simp +@[fun_prop] +lemma Continuous.mul_log {α : Type*} [TopologicalSpace α] {f : α → ℝ} (hf : Continuous f) : + Continuous fun a ↦ f a * log (f a) := continuous_mul_log.comp hf + lemma differentiableOn_mul_log : DifferentiableOn ℝ (fun x ↦ x * log x) {0}ᶜ := differentiable_id'.differentiableOn.mul differentiableOn_log @@ -131,7 +136,7 @@ lemma negMulLog_mul (x y : ℝ) : negMulLog (x * y) = y * negMulLog x + x * negM rw [log_mul hx hy] ring -lemma continuous_negMulLog : Continuous negMulLog := by +@[fun_prop] lemma continuous_negMulLog : Continuous negMulLog := by simpa only [negMulLog_eq_neg] using continuous_mul_log.neg lemma differentiableOn_negMulLog : DifferentiableOn ℝ negMulLog {0}ᶜ := by @@ -151,6 +156,8 @@ lemma differentiableAt_negMulLog_iff {x : ℝ} : DifferentiableAt ℝ negMulLog <;> simp_all only [ne_eq, Set.mem_compl_iff, Set.mem_singleton_iff, not_false_eq_true, compl_singleton_mem_nhds_iff] +@[fun_prop] alias ⟨_, differentiableAt_negMulLog⟩ := differentiableAt_negMulLog_iff + lemma deriv_negMulLog {x : ℝ} (hx : x ≠ 0) : deriv negMulLog x = - log x - 1 := by rw [negMulLog_eq_neg, deriv.neg, deriv_mul_log hx] ring diff --git a/Mathlib/Analysis/SpecialFunctions/Pow/Complex.lean b/Mathlib/Analysis/SpecialFunctions/Pow/Complex.lean index 0560cfa53a183..9a2469906a661 100644 --- a/Mathlib/Analysis/SpecialFunctions/Pow/Complex.lean +++ b/Mathlib/Analysis/SpecialFunctions/Pow/Complex.lean @@ -176,7 +176,7 @@ lemma pow_cpow_nat_inv {x : ℂ} {n : ℕ} (h₀ : n ≠ 0) (hlt : -(π / n) < x (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 [← le_div_iff' (Nat.cast_pos.2 h₀.bot_lt)] + · 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) (hle : x.arg ≤ π / OfNat.ofNat n) : diff --git a/Mathlib/Analysis/SpecialFunctions/Pow/Continuity.lean b/Mathlib/Analysis/SpecialFunctions/Pow/Continuity.lean index d62254dfce817..5e4589e68a99a 100644 --- a/Mathlib/Analysis/SpecialFunctions/Pow/Continuity.lean +++ b/Mathlib/Analysis/SpecialFunctions/Pow/Continuity.lean @@ -299,7 +299,7 @@ theorem continuousAt_cpow_zero_of_re_pos {z : ℂ} (hz : 0 < z.re) : (continuous_fst.norm.tendsto ((0 : ℂ), z)).rpow ((continuous_re.comp continuous_snd).tendsto _) _ <;> simp [hz, Real.zero_rpow hz.ne'] - · simp only [Function.comp, Real.norm_eq_abs, abs_of_pos (Real.exp_pos _)] + · simp only [Function.comp_def, Real.norm_eq_abs, abs_of_pos (Real.exp_pos _)] rcases exists_gt |im z| with ⟨C, hC⟩ refine ⟨Real.exp (π * C), eventually_map.2 ?_⟩ refine diff --git a/Mathlib/Analysis/SpecialFunctions/Pow/NNReal.lean b/Mathlib/Analysis/SpecialFunctions/Pow/NNReal.lean index eeb41c187e3b7..e114e6562e484 100644 --- a/Mathlib/Analysis/SpecialFunctions/Pow/NNReal.lean +++ b/Mathlib/Analysis/SpecialFunctions/Pow/NNReal.lean @@ -600,7 +600,7 @@ theorem prod_rpow_of_ne_top {ι} {s : Finset ι} {f : ι → ℝ≥0∞} (hf : | @insert i s hi ih => have h2f : ∀ i ∈ s, f i ≠ ∞ := fun i hi ↦ hf i <| mem_insert_of_mem hi rw [prod_insert hi, prod_insert hi, ih h2f, ← mul_rpow_of_ne_top <| hf i <| mem_insert_self ..] - apply prod_lt_top h2f |>.ne + apply prod_ne_top h2f theorem prod_rpow_of_nonneg {ι} {s : Finset ι} {f : ι → ℝ≥0∞} {r : ℝ} (hr : 0 ≤ r) : ∏ i ∈ s, f i ^ r = (∏ i ∈ s, f i) ^ r := by diff --git a/Mathlib/Analysis/SpecialFunctions/Pow/Real.lean b/Mathlib/Analysis/SpecialFunctions/Pow/Real.lean index f36e3a7733dc3..6a7ea43f88beb 100644 --- a/Mathlib/Analysis/SpecialFunctions/Pow/Real.lean +++ b/Mathlib/Analysis/SpecialFunctions/Pow/Real.lean @@ -372,37 +372,46 @@ theorem rpow_mul {x : ℝ} (hx : 0 ≤ x) (y z : ℝ) : x ^ (y * z) = (x ^ y) ^ simp only [(Complex.ofReal_mul _ _).symm, (Complex.ofReal_log hx).symm, Complex.ofReal_im, neg_lt_zero, pi_pos, le_of_lt pi_pos] -theorem rpow_add_int {x : ℝ} (hx : x ≠ 0) (y : ℝ) (n : ℤ) : x ^ (y + n) = x ^ y * x ^ n := by +lemma rpow_add_intCast {x : ℝ} (hx : x ≠ 0) (y : ℝ) (n : ℤ) : x ^ (y + n) = x ^ y * x ^ n := by rw [rpow_def, rpow_def, Complex.ofReal_add, Complex.cpow_add _ _ (Complex.ofReal_ne_zero.mpr hx), Complex.ofReal_intCast, Complex.cpow_intCast, ← Complex.ofReal_zpow, mul_comm, Complex.re_ofReal_mul, mul_comm] -theorem rpow_add_nat {x : ℝ} (hx : x ≠ 0) (y : ℝ) (n : ℕ) : x ^ (y + n) = x ^ y * x ^ n := by - simpa using rpow_add_int hx y n +lemma rpow_add_natCast {x : ℝ} (hx : x ≠ 0) (y : ℝ) (n : ℕ) : x ^ (y + n) = x ^ y * x ^ n := by + simpa using rpow_add_intCast hx y n -theorem rpow_sub_int {x : ℝ} (hx : x ≠ 0) (y : ℝ) (n : ℕ) : x ^ (y - n) = x ^ y / x ^ n := by - simpa using rpow_add_int hx y (-n) +lemma rpow_sub_intCast {x : ℝ} (hx : x ≠ 0) (y : ℝ) (n : ℕ) : x ^ (y - n) = x ^ y / x ^ n := by + simpa using rpow_add_intCast hx y (-n) -theorem rpow_sub_nat {x : ℝ} (hx : x ≠ 0) (y : ℝ) (n : ℕ) : x ^ (y - n) = x ^ y / x ^ n := by - simpa using rpow_sub_int hx y n +lemma rpow_sub_natCast {x : ℝ} (hx : x ≠ 0) (y : ℝ) (n : ℕ) : x ^ (y - n) = x ^ y / x ^ n := by + simpa using rpow_sub_intCast hx y n -lemma rpow_add_int' (hx : 0 ≤ x) {n : ℤ} (h : y + n ≠ 0) : x ^ (y + n) = x ^ y * x ^ n := by +lemma rpow_add_intCast' (hx : 0 ≤ x) {n : ℤ} (h : y + n ≠ 0) : x ^ (y + n) = x ^ y * x ^ n := by rw [rpow_add' hx h, rpow_intCast] -lemma rpow_add_nat' (hx : 0 ≤ x) (h : y + n ≠ 0) : x ^ (y + n) = x ^ y * x ^ n := by +lemma rpow_add_natCast' (hx : 0 ≤ x) (h : y + n ≠ 0) : x ^ (y + n) = x ^ y * x ^ n := by rw [rpow_add' hx h, rpow_natCast] -lemma rpow_sub_int' (hx : 0 ≤ x) {n : ℤ} (h : y - n ≠ 0) : x ^ (y - n) = x ^ y / x ^ n := by +lemma rpow_sub_intCast' (hx : 0 ≤ x) {n : ℤ} (h : y - n ≠ 0) : x ^ (y - n) = x ^ y / x ^ n := by rw [rpow_sub' hx h, rpow_intCast] -lemma rpow_sub_nat' (hx : 0 ≤ x) (h : y - n ≠ 0) : x ^ (y - n) = x ^ y / x ^ n := by +lemma rpow_sub_natCast' (hx : 0 ≤ x) (h : y - n ≠ 0) : x ^ (y - n) = x ^ y / x ^ n := by rw [rpow_sub' hx h, rpow_natCast] +@[deprecated (since := "2024-08-28")] alias rpow_add_int := rpow_add_intCast +@[deprecated (since := "2024-08-28")] alias rpow_add_nat := rpow_add_natCast +@[deprecated (since := "2024-08-28")] alias rpow_sub_int := rpow_sub_intCast +@[deprecated (since := "2024-08-28")] alias rpow_sub_nat := rpow_sub_natCast +@[deprecated (since := "2024-08-28")] alias rpow_add_int' := rpow_add_intCast' +@[deprecated (since := "2024-08-28")] alias rpow_add_nat' := rpow_add_natCast' +@[deprecated (since := "2024-08-28")] alias rpow_sub_int' := rpow_sub_intCast' +@[deprecated (since := "2024-08-28")] alias rpow_sub_nat' := rpow_sub_natCast' + theorem rpow_add_one {x : ℝ} (hx : x ≠ 0) (y : ℝ) : x ^ (y + 1) = x ^ y * x := by - simpa using rpow_add_nat hx y 1 + simpa using rpow_add_natCast hx y 1 theorem rpow_sub_one {x : ℝ} (hx : x ≠ 0) (y : ℝ) : x ^ (y - 1) = x ^ y / x := by - simpa using rpow_sub_nat hx y 1 + simpa using rpow_sub_natCast hx y 1 lemma rpow_add_one' (hx : 0 ≤ x) (h : y + 1 ≠ 0) : x ^ (y + 1) = x ^ y * x := by rw [rpow_add' hx h, rpow_one] @@ -694,23 +703,103 @@ lemma rpow_inv_eq (hx : 0 ≤ x) (hy : 0 ≤ y) (hz : z ≠ 0) : x ^ z⁻¹ = y lemma eq_rpow_inv (hx : 0 ≤ x) (hy : 0 ≤ y) (hz : z ≠ 0) : x = y ^ z⁻¹ ↔ x ^ z = y := by rw [← rpow_left_inj hx _ hz, rpow_inv_rpow hy hz]; positivity -theorem le_rpow_iff_log_le (hx : 0 < x) (hy : 0 < y) : x ≤ y ^ z ↔ Real.log x ≤ z * Real.log y := by - rw [← Real.log_le_log_iff hx (Real.rpow_pos_of_pos hy z), Real.log_rpow hy] +theorem le_rpow_iff_log_le (hx : 0 < x) (hy : 0 < y) : x ≤ y ^ z ↔ log x ≤ z * log y := by + rw [← log_le_log_iff hx (rpow_pos_of_pos hy z), log_rpow hy] + +lemma le_pow_iff_log_le (hx : 0 < x) (hy : 0 < y) : x ≤ y ^ n ↔ log x ≤ n * log y := + rpow_natCast _ _ ▸ le_rpow_iff_log_le hx hy -theorem le_rpow_of_log_le (hx : 0 ≤ x) (hy : 0 < y) (h : Real.log x ≤ z * Real.log y) : - x ≤ y ^ z := by - obtain hx | rfl := hx.lt_or_eq +lemma le_zpow_iff_log_le {n : ℤ} (hx : 0 < x) (hy : 0 < y) : x ≤ y ^ n ↔ log x ≤ n * log y := + rpow_intCast _ _ ▸ le_rpow_iff_log_le hx hy + +lemma le_rpow_of_log_le (hy : 0 < y) (h : log x ≤ z * log y) : x ≤ y ^ z := by + obtain hx | hx := le_or_lt x 0 + · exact hx.trans (rpow_pos_of_pos hy _).le · exact (le_rpow_iff_log_le hx hy).2 h - exact (Real.rpow_pos_of_pos hy z).le -theorem lt_rpow_iff_log_lt (hx : 0 < x) (hy : 0 < y) : x < y ^ z ↔ Real.log x < z * Real.log y := by - rw [← Real.log_lt_log_iff hx (Real.rpow_pos_of_pos hy z), Real.log_rpow hy] +lemma le_pow_of_log_le (hy : 0 < y) (h : log x ≤ n * log y) : x ≤ y ^ n := + rpow_natCast _ _ ▸ le_rpow_of_log_le hy h + +lemma le_zpow_of_log_le {n : ℤ} (hy : 0 < y) (h : log x ≤ n * log y) : x ≤ y ^ n := + rpow_intCast _ _ ▸ le_rpow_of_log_le hy h -theorem lt_rpow_of_log_lt (hx : 0 ≤ x) (hy : 0 < y) (h : Real.log x < z * Real.log y) : - x < y ^ z := by - obtain hx | rfl := hx.lt_or_eq +theorem lt_rpow_iff_log_lt (hx : 0 < x) (hy : 0 < y) : x < y ^ z ↔ log x < z * log y := by + rw [← log_lt_log_iff hx (rpow_pos_of_pos hy z), log_rpow hy] + +lemma lt_pow_iff_log_lt (hx : 0 < x) (hy : 0 < y) : x < y ^ n ↔ log x < n * log y := + rpow_natCast _ _ ▸ lt_rpow_iff_log_lt hx hy + +lemma lt_zpow_iff_log_lt {n : ℤ} (hx : 0 < x) (hy : 0 < y) : x < y ^ n ↔ log x < n * log y := + rpow_intCast _ _ ▸ lt_rpow_iff_log_lt hx hy + +lemma lt_rpow_of_log_lt (hy : 0 < y) (h : log x < z * log y) : x < y ^ z := by + obtain hx | hx := le_or_lt x 0 + · exact hx.trans_lt (rpow_pos_of_pos hy _) · exact (lt_rpow_iff_log_lt hx hy).2 h - exact Real.rpow_pos_of_pos hy z + +lemma lt_pow_of_log_lt (hy : 0 < y) (h : log x < n * log y) : x < y ^ n := + rpow_natCast _ _ ▸ lt_rpow_of_log_lt hy h + +lemma lt_zpow_of_log_lt {n : ℤ} (hy : 0 < y) (h : log x < n * log y) : x < y ^ n := + rpow_intCast _ _ ▸ lt_rpow_of_log_lt hy h + +lemma rpow_le_iff_le_log (hx : 0 < x) (hy : 0 < y) : x ^ z ≤ y ↔ z * log x ≤ log y := by + rw [← log_le_log_iff (rpow_pos_of_pos hx _) hy, log_rpow hx] + +lemma pow_le_iff_le_log (hx : 0 < x) (hy : 0 < y) : x ^ n ≤ y ↔ n * log x ≤ log y := by + rw [← rpow_le_iff_le_log hx hy, rpow_natCast] + +lemma zpow_le_iff_le_log {n : ℤ} (hx : 0 < x) (hy : 0 < y) : x ^ n ≤ y ↔ n * log x ≤ log y := by + rw [← rpow_le_iff_le_log hx hy, rpow_intCast] + +lemma le_log_of_rpow_le (hx : 0 < x) (h : x ^ z ≤ y) : z * log x ≤ log y := + log_rpow hx _ ▸ log_le_log (by positivity) h + +lemma le_log_of_pow_le (hx : 0 < x) (h : x ^ n ≤ y) : n * log x ≤ log y := + le_log_of_rpow_le hx (rpow_natCast _ _ ▸ h) + +lemma le_log_of_zpow_le {n : ℤ} (hx : 0 < x) (h : x ^ n ≤ y) : n * log x ≤ log y := + le_log_of_rpow_le hx (rpow_intCast _ _ ▸ h) + +lemma rpow_le_of_le_log (hy : 0 < y) (h : log x ≤ z * log y) : x ≤ y ^ z := by + obtain hx | hx := le_or_lt x 0 + · exact hx.trans (rpow_pos_of_pos hy _).le + · exact (le_rpow_iff_log_le hx hy).2 h + +lemma pow_le_of_le_log (hy : 0 < y) (h : log x ≤ n * log y) : x ≤ y ^ n := + rpow_natCast _ _ ▸ rpow_le_of_le_log hy h + +lemma zpow_le_of_le_log {n : ℤ} (hy : 0 < y) (h : log x ≤ n * log y) : x ≤ y ^ n := + rpow_intCast _ _ ▸ rpow_le_of_le_log hy h + +lemma rpow_lt_iff_lt_log (hx : 0 < x) (hy : 0 < y) : x ^ z < y ↔ z * log x < log y := by + rw [← log_lt_log_iff (rpow_pos_of_pos hx _) hy, log_rpow hx] + +lemma pow_lt_iff_lt_log (hx : 0 < x) (hy : 0 < y) : x ^ n < y ↔ n * log x < log y := by + rw [← rpow_lt_iff_lt_log hx hy, rpow_natCast] + +lemma zpow_lt_iff_lt_log {n : ℤ} (hx : 0 < x) (hy : 0 < y) : x ^ n < y ↔ n * log x < log y := by + rw [← rpow_lt_iff_lt_log hx hy, rpow_intCast] + +lemma lt_log_of_rpow_lt (hx : 0 < x) (h : x ^ z < y) : z * log x < log y := + log_rpow hx _ ▸ log_lt_log (by positivity) h + +lemma lt_log_of_pow_lt (hx : 0 < x) (h : x ^ n < y) : n * log x < log y := + lt_log_of_rpow_lt hx (rpow_natCast _ _ ▸ h) + +lemma lt_log_of_zpow_lt {n : ℤ} (hx : 0 < x) (h : x ^ n < y) : n * log x < log y := + lt_log_of_rpow_lt hx (rpow_intCast _ _ ▸ h) + +lemma rpow_lt_of_lt_log (hy : 0 < y) (h : log x < z * log y) : x < y ^ z := by + obtain hx | hx := le_or_lt x 0 + · exact hx.trans_lt (rpow_pos_of_pos hy _) + · exact (lt_rpow_iff_log_lt hx hy).2 h + +lemma pow_lt_of_lt_log (hy : 0 < y) (h : log x < n * log y) : x < y ^ n := + rpow_natCast _ _ ▸ rpow_lt_of_lt_log hy h + +lemma zpow_lt_of_lt_log {n : ℤ} (hy : 0 < y) (h : log x < n * log y) : x < y ^ n := + rpow_intCast _ _ ▸ rpow_lt_of_lt_log hy h theorem rpow_le_one_iff_of_pos (hx : 0 < x) : x ^ y ≤ 1 ↔ 1 ≤ x ∧ y ≤ 0 ∨ x ≤ 1 ∧ 0 ≤ y := by rw [rpow_def_of_pos hx, exp_le_one_iff, mul_nonpos_iff, log_nonneg_iff hx, log_nonpos_iff hx] @@ -726,7 +815,7 @@ theorem abs_log_mul_self_rpow_lt (x t : ℝ) (h1 : 0 < x) (h2 : x ≤ 1) (ht : 0 lemma log_le_rpow_div {x ε : ℝ} (hx : 0 ≤ x) (hε : 0 < ε) : log x ≤ x ^ ε / ε := by rcases hx.eq_or_lt with rfl | h · rw [log_zero, zero_rpow hε.ne', zero_div] - rw [le_div_iff' hε] + rw [le_div_iff₀' hε] exact (log_rpow h ε).symm.trans_le <| (log_le_sub_one_of_pos <| rpow_pos_of_pos h ε).trans (sub_one_lt _).le diff --git a/Mathlib/Analysis/SpecialFunctions/Trigonometric/Angle.lean b/Mathlib/Analysis/SpecialFunctions/Trigonometric/Angle.lean index 6dd45e6fe5610..806f844aeaaeb 100644 --- a/Mathlib/Analysis/SpecialFunctions/Trigonometric/Angle.lean +++ b/Mathlib/Analysis/SpecialFunctions/Trigonometric/Angle.lean @@ -555,7 +555,7 @@ theorem nsmul_toReal_eq_mul {n : ℕ} (h : n ≠ 0) {θ : Angle} : 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', - le_div_iff' h'] + le_div_iff₀' h'] theorem two_nsmul_toReal_eq_two_mul {θ : Angle} : ((2 : ℕ) • θ).toReal = 2 * θ.toReal ↔ θ.toReal ∈ Set.Ioc (-π / 2) (π / 2) := @@ -597,7 +597,7 @@ theorem two_nsmul_toReal_eq_two_mul_add_two_pi {θ : Angle} : rw [← coe_nsmul, two_nsmul, ← two_mul, toReal_coe_eq_self_add_two_pi_iff, Set.mem_Ioc] refine ⟨fun h => by linarith, fun h => - ⟨by linarith [pi_pos, neg_pi_lt_toReal θ], (le_div_iff' (zero_lt_two' ℝ)).1 h⟩⟩ + ⟨by linarith [pi_pos, neg_pi_lt_toReal θ], (le_div_iff₀' (zero_lt_two' ℝ)).1 h⟩⟩ theorem two_zsmul_toReal_eq_two_mul_add_two_pi {θ : Angle} : ((2 : ℤ) • θ).toReal = 2 * θ.toReal + 2 * π ↔ θ.toReal ≤ -π / 2 := by diff --git a/Mathlib/Analysis/SpecialFunctions/Trigonometric/Arctan.lean b/Mathlib/Analysis/SpecialFunctions/Trigonometric/Arctan.lean index 47d4af9b30a03..2ea81c6afbe95 100644 --- a/Mathlib/Analysis/SpecialFunctions/Trigonometric/Arctan.lean +++ b/Mathlib/Analysis/SpecialFunctions/Trigonometric/Arctan.lean @@ -72,7 +72,7 @@ theorem continuousOn_tan_Ioo : ContinuousOn tan (Ioo (-(π / 2)) (π / 2)) := by rw [hxr_eq, ← one_mul (π / 2), mul_div_assoc, ge_iff_le, neg_mul_eq_neg_mul, mul_le_mul_right (half_pos pi_pos)] have hr_le : r ≤ -1 := by rwa [Int.lt_iff_add_one_le, ← le_neg_iff_add_nonpos_right] at h - rw [← le_sub_iff_add_le, mul_comm, ← le_div_iff] + rw [← le_sub_iff_add_le, mul_comm, ← le_div_iff₀] · norm_num rw [← Int.cast_one, ← Int.cast_neg]; norm_cast · exact zero_lt_two diff --git a/Mathlib/Analysis/SpecialFunctions/Trigonometric/Basic.lean b/Mathlib/Analysis/SpecialFunctions/Trigonometric/Basic.lean index c9617df307a4e..c31a03b44e31f 100644 --- a/Mathlib/Analysis/SpecialFunctions/Trigonometric/Basic.lean +++ b/Mathlib/Analysis/SpecialFunctions/Trigonometric/Basic.lean @@ -301,6 +301,10 @@ theorem cos_antiperiodic : Function.Antiperiodic cos π := by simp [cos_add] theorem cos_periodic : Function.Periodic cos (2 * π) := cos_antiperiodic.periodic_two_mul +@[simp] +theorem abs_cos_int_mul_pi (k : ℤ) : |cos (k * π)| = 1 := by + simp [abs_cos_eq_sqrt_one_sub_sin_sq] + @[simp] theorem cos_add_pi (x : ℝ) : cos (x + π) = -cos x := cos_antiperiodic x @@ -679,7 +683,7 @@ theorem sin_sq_pi_over_two_pow_succ (n : ℕ) : @[simp] theorem sin_pi_over_two_pow_succ (n : ℕ) : sin (π / 2 ^ (n + 2)) = √(2 - sqrtTwoAddSeries 0 n) / 2 := by - rw [eq_div_iff_mul_eq two_ne_zero, eq_comm, sqrt_eq_iff_sq_eq, mul_pow, + rw [eq_div_iff_mul_eq two_ne_zero, eq_comm, sqrt_eq_iff_eq_sq, mul_pow, sin_sq_pi_over_two_pow_succ, sub_mul] · congr <;> norm_num · rw [sub_nonneg] diff --git a/Mathlib/Analysis/SpecialFunctions/Trigonometric/Bounds.lean b/Mathlib/Analysis/SpecialFunctions/Trigonometric/Bounds.lean index a67d9921c5ba3..e0595d589e11d 100644 --- a/Mathlib/Analysis/SpecialFunctions/Trigonometric/Bounds.lean +++ b/Mathlib/Analysis/SpecialFunctions/Trigonometric/Bounds.lean @@ -1,8 +1,9 @@ /- Copyright (c) 2022 David Loeffler. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: David Loeffler, Yaël Dillies +Authors: David Loeffler, Yaël Dillies, Bhavik Mehta -/ +import Mathlib.Analysis.Convex.SpecificFunctions.Deriv import Mathlib.Analysis.SpecialFunctions.Trigonometric.ArctanDeriv /-! @@ -54,79 +55,94 @@ lemma sin_le (hx : 0 ≤ x) : sin x ≤ x := by lemma lt_sin (hx : x < 0) : x < sin x := by simpa using sin_lt <| neg_pos.2 hx lemma le_sin (hx : x ≤ 0) : x ≤ sin x := by simpa using sin_le <| neg_nonneg.2 hx -lemma one_sub_sq_div_two_le_cos : 1 - x ^ 2 / 2 ≤ cos x := by +theorem lt_sin_mul {x : ℝ} (hx : 0 < x) (hx' : x < 1) : x < sin (π / 2 * x) := by + simpa [mul_comm x] using + strictConcaveOn_sin_Icc.2 ⟨le_rfl, pi_pos.le⟩ ⟨pi_div_two_pos.le, half_le_self pi_pos.le⟩ + pi_div_two_pos.ne (sub_pos.2 hx') hx + +theorem le_sin_mul {x : ℝ} (hx : 0 ≤ x) (hx' : x ≤ 1) : x ≤ sin (π / 2 * x) := by + simpa [mul_comm x] using + strictConcaveOn_sin_Icc.concaveOn.2 ⟨le_rfl, pi_pos.le⟩ + ⟨pi_div_two_pos.le, half_le_self pi_pos.le⟩ (sub_nonneg.2 hx') hx + +theorem mul_lt_sin {x : ℝ} (hx : 0 < x) (hx' : x < π / 2) : 2 / π * x < sin x := by + rw [← inv_div] + simpa [-inv_div, mul_inv_cancel_left₀ pi_div_two_pos.ne'] using @lt_sin_mul ((π / 2)⁻¹ * x) + (mul_pos (inv_pos.2 pi_div_two_pos) hx) (by rwa [← div_eq_inv_mul, div_lt_one pi_div_two_pos]) + +/-- One half of **Jordan's inequality**. + +In the range `[0, π / 2]`, we have a linear lower bound on `sin`. The other half is given by +`Real.sin_le`. +-/ +theorem mul_le_sin {x : ℝ} (hx : 0 ≤ x) (hx' : x ≤ π / 2) : 2 / π * x ≤ sin x := by + rw [← inv_div] + simpa [-inv_div, mul_inv_cancel_left₀ pi_div_two_pos.ne'] using @le_sin_mul ((π / 2)⁻¹ * x) + (mul_nonneg (inv_nonneg.2 pi_div_two_pos.le) hx) + (by rwa [← div_eq_inv_mul, div_le_one pi_div_two_pos]) + +/-- Half of **Jordan's inequality** for negative values. -/ +lemma sin_le_mul (hx : -(π / 2) ≤ x) (hx₀ : x ≤ 0) : sin x ≤ 2 / π * x := by + simpa using mul_le_sin (neg_nonneg.2 hx₀) (neg_le.2 hx) + +/-- Half of **Jordan's inequality** for absolute values. -/ +lemma mul_abs_le_abs_sin (hx : |x| ≤ π / 2) : 2 / π * |x| ≤ |sin x| := by wlog hx₀ : 0 ≤ x - · simpa using this <| neg_nonneg.2 <| le_of_not_le hx₀ - suffices MonotoneOn (fun x ↦ cos x + x ^ 2 / 2) (Ici 0) by - simpa using this left_mem_Ici hx₀ hx₀ - refine monotoneOn_of_hasDerivWithinAt_nonneg - (convex_Ici _) (by fun_prop) - (fun x _ ↦ ((hasDerivAt_cos ..).add <| (hasDerivAt_pow ..).div_const _).hasDerivWithinAt) - fun x hx ↦ ?_ - simpa [mul_div_cancel_left₀] using sin_le <| interior_subset hx - -/-- **Jordan's inequality**. -/ -lemma two_div_pi_mul_le_sin (hx₀ : 0 ≤ x) (hx : x ≤ π / 2) : 2 / π * x ≤ sin x := by - rw [← sub_nonneg] - suffices ConcaveOn ℝ (Icc 0 (π / 2)) (fun x ↦ sin x - 2 / π * x) by - refine (le_min ?_ ?_).trans <| this.min_le_of_mem_Icc ⟨hx₀, hx⟩ <;> field_simp - exact concaveOn_of_hasDerivWithinAt2_nonpos (convex_Icc ..) - (Continuous.continuousOn <| by fun_prop) - (fun x _ ↦ ((hasDerivAt_sin ..).sub <| (hasDerivAt_id ..).const_mul (2 / π)).hasDerivWithinAt) - (fun x _ ↦ (hasDerivAt_cos ..).hasDerivWithinAt.sub_const _) - fun x hx ↦ neg_nonpos.2 <| sin_nonneg_of_mem_Icc <| Icc_subset_Icc_right (by linarith) <| - interior_subset hx - -/-- **Jordan's inequality** for negative values. -/ -lemma sin_le_two_div_pi_mul (hx : -(π / 2) ≤ x) (hx₀ : x ≤ 0) : sin x ≤ 2 / π * x := by - simpa using two_div_pi_mul_le_sin (neg_nonneg.2 hx₀) (neg_le.2 hx) - -/-- **Jordan's inequality** for `cos`. -/ -lemma one_sub_two_div_pi_mul_le_cos (hx₀ : 0 ≤ x) (hx : x ≤ π / 2) : 1 - 2 / π * x ≤ cos x := by - simpa [sin_pi_div_two_sub, mul_sub, div_mul_div_comm, mul_comm π, div_self two_pi_pos.ne'] - using two_div_pi_mul_le_sin (x := π / 2 - x) (by simpa) (by simpa) - -lemma cos_quadratic_upper_bound (hx : |x| ≤ π) : cos x ≤ 1 - 2 / π ^ 2 * x ^ 2 := by + case inr => simpa using this (by rwa [abs_neg]) <| neg_nonneg.2 <| le_of_not_le hx₀ + rw [abs_of_nonneg hx₀] at hx ⊢ + exact (mul_le_sin hx₀ hx).trans (le_abs_self _) + +lemma sin_sq_lt_sq (hx : x ≠ 0) : sin x ^ 2 < x ^ 2 := by + wlog hx₀ : 0 < x + case inr => + simpa using this (neg_ne_zero.2 hx) <| neg_pos_of_neg <| hx.lt_of_le <| le_of_not_lt hx₀ + rcases le_or_lt x 1 with hxπ | hxπ + case inl => + exact pow_lt_pow_left (sin_lt hx₀) + (sin_nonneg_of_nonneg_of_le_pi hx₀.le (by linarith [two_le_pi])) (by simp) + case inr => + exact (sin_sq_le_one _).trans_lt (by rwa [one_lt_sq_iff hx₀.le]) + +lemma sin_sq_le_sq : sin x ^ 2 ≤ x ^ 2 := by + rcases eq_or_ne x 0 with rfl | hx + case inl => simp + case inr => exact (sin_sq_lt_sq hx).le + +lemma abs_sin_lt_abs (hx : x ≠ 0) : |sin x| < |x| := sq_lt_sq.1 (sin_sq_lt_sq hx) +lemma abs_sin_le_abs : |sin x| ≤ |x| := sq_le_sq.1 sin_sq_le_sq + +lemma one_sub_sq_div_two_lt_cos (hx : x ≠ 0) : 1 - x ^ 2 / 2 < cos x := by + have := (sin_sq_lt_sq (by positivity)).trans_eq' (sin_sq_eq_half_sub (x / 2)).symm + ring_nf at this + linarith + +lemma one_sub_sq_div_two_le_cos : 1 - x ^ 2 / 2 ≤ cos x := by + rcases eq_or_ne x 0 with rfl | hx + case inl => simp + case inr => exact (one_sub_sq_div_two_lt_cos hx).le + +/-- Half of **Jordan's inequality** for `cos`. -/ +lemma one_sub_mul_le_cos (hx₀ : 0 ≤ x) (hx : x ≤ π / 2) : 1 - 2 / π * x ≤ cos x := by + simpa [sin_pi_div_two_sub, mul_sub, div_mul_div_comm, mul_comm π, pi_pos.ne'] + using mul_le_sin (x := π / 2 - x) (by simpa) (by simpa) + +/-- Half of **Jordan's inequality** for `cos` and negative values. -/ +lemma one_add_mul_le_cos (hx₀ : -(π / 2) ≤ x) (hx : x ≤ 0) : 1 + 2 / π * x ≤ cos x := by + simpa using one_sub_mul_le_cos (x := -x) (by linarith) (by linarith) + +lemma cos_le_one_sub_mul_cos_sq (hx : |x| ≤ π) : cos x ≤ 1 - 2 / π ^ 2 * x ^ 2 := by wlog hx₀ : 0 ≤ x - · simpa using this (by rwa [abs_neg]) <| neg_nonneg.2 <| le_of_not_le hx₀ + case inr => simpa using this (by rwa [abs_neg]) <| neg_nonneg.2 <| le_of_not_le hx₀ rw [abs_of_nonneg hx₀] at hx - -- TODO: `compute_deriv` tactic? - have hderiv (x) : HasDerivAt (fun x ↦ 1 - 2 / π ^ 2 * x ^ 2 - cos x) _ x := - (((hasDerivAt_pow ..).const_mul _).const_sub _).sub <| hasDerivAt_cos _ - simp only [Nat.cast_ofNat, Nat.succ_sub_succ_eq_sub, tsub_zero, pow_one, ← neg_sub', neg_sub, - ← mul_assoc] at hderiv - have hmono : MonotoneOn (fun x ↦ 1 - 2 / π ^ 2 * x ^ 2 - cos x) (Icc 0 (π / 2)) := by - -- Compiles without this option, but somewhat slower. - set_option tactic.skipAssignedInstances false in - refine monotoneOn_of_hasDerivWithinAt_nonneg - (convex_Icc ..) - (Continuous.continuousOn <| by fun_prop) - (fun x _ ↦ (hderiv _).hasDerivWithinAt) - fun x hx ↦ sub_nonneg.2 ?_ - have ⟨hx₀, hx⟩ := interior_subset hx - calc 2 / π ^ 2 * 2 * x - = 2 / π * (2 / π * x) := by ring - _ ≤ 1 * sin x := by - gcongr; exacts [div_le_one_of_le two_le_pi (by positivity), two_div_pi_mul_le_sin hx₀ hx] - _ = sin x := one_mul _ - have hconc : ConcaveOn ℝ (Icc (π / 2) π) (fun x ↦ 1 - 2 / π ^ 2 * x ^ 2 - cos x) := by - -- Compiles without this option, but somewhat slower. - set_option tactic.skipAssignedInstances false in - refine concaveOn_of_hasDerivWithinAt2_nonpos (convex_Icc ..) - (Continuous.continuousOn <| by fun_prop) (fun x _ ↦ (hderiv _).hasDerivWithinAt) - (fun x _ ↦ ((hasDerivAt_sin ..).sub <| (hasDerivAt_id ..).const_mul _).hasDerivWithinAt) - fun x hx ↦ ?_ - have ⟨hx, hx'⟩ := interior_subset hx - calc - _ ≤ (0 : ℝ) - 0 := by - gcongr - · exact cos_nonpos_of_pi_div_two_le_of_le hx <| hx'.trans <| by linarith - · positivity - _ = 0 := sub_zero _ - rw [← sub_nonneg] - obtain hx' | hx' := le_total x (π / 2) - · simpa using hmono (left_mem_Icc.2 <| by positivity) ⟨hx₀, hx'⟩ hx₀ - · refine (le_min ?_ ?_).trans <| hconc.min_le_of_mem_Icc ⟨hx', hx⟩ <;> field_simp <;> norm_num + have : x / π ≤ sin (x / 2) := by simpa using mul_le_sin (x := x / 2) (by positivity) (by linarith) + have := (pow_le_pow_left (by positivity) this 2).trans_eq (sin_sq_eq_half_sub _) + ring_nf at this ⊢ + linarith + +@[deprecated (since := "2024-08-29")] alias two_div_pi_mul_le_sin := mul_le_sin +@[deprecated (since := "2024-08-29")] alias sin_le_two_div_pi_mul := sin_le_mul +@[deprecated (since := "2024-08-29")] alias one_sub_two_div_pi_mul_le_cos := one_sub_mul_le_cos +@[deprecated (since := "2024-08-29")] alias cos_quadratic_upper_bound := cos_le_one_sub_mul_cos_sq /-- For 0 < x ≤ 1 we have x - x ^ 3 / 4 < sin x. diff --git a/Mathlib/Analysis/SpecialFunctions/Trigonometric/Complex.lean b/Mathlib/Analysis/SpecialFunctions/Trigonometric/Complex.lean index b4ed209b1d7de..ece140bac4b05 100644 --- a/Mathlib/Analysis/SpecialFunctions/Trigonometric/Complex.lean +++ b/Mathlib/Analysis/SpecialFunctions/Trigonometric/Complex.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes, Abhimanyu Pallavi Sudhir, Jean Lo, Calle Sönne, Benjamin Davidson -/ import Mathlib.Algebra.QuadraticDiscriminant -import Mathlib.Analysis.Convex.SpecificFunctions.Deriv import Mathlib.Analysis.SpecialFunctions.Pow.Complex /-! @@ -59,7 +58,7 @@ theorem sin_ne_zero_iff {θ : ℂ} : sin θ ≠ 0 ↔ ∀ k : ℤ, θ ≠ k * π iff this number is equal to `k * π / 2` for an integer `k`. Note that this lemma takes into account that we use zero as the junk value for division by zero. -See also `Complex.tan_eq_zero_iff'`. -/ +See also `Complex.tan_eq_zero_iff'`. -/ theorem tan_eq_zero_iff {θ : ℂ} : tan θ = 0 ↔ ∃ k : ℤ, k * π / 2 = θ := by rw [tan, div_eq_zero_iff, ← mul_eq_zero, ← mul_right_inj' two_ne_zero, mul_zero, ← mul_assoc, ← sin_two_mul, sin_eq_zero_iff] @@ -118,8 +117,7 @@ theorem tan_add {x y : ℂ} tan (x + y) = (tan x + tan y) / (1 - tan x * tan y) := by rcases h with (⟨h1, h2⟩ | ⟨⟨k, rfl⟩, ⟨l, rfl⟩⟩) · rw [tan, sin_add, cos_add, ← - div_div_div_cancel_right (sin x * cos y + cos x * sin y) - (mul_ne_zero (cos_ne_zero_iff.mpr h1) (cos_ne_zero_iff.mpr h2)), + div_div_div_cancel_right₀ (mul_ne_zero (cos_ne_zero_iff.mpr h1) (cos_ne_zero_iff.mpr h2)), add_div, sub_div] simp only [← div_mul_div_comm, tan, mul_one, one_mul, div_self (cos_ne_zero_iff.mpr h1), div_self (cos_ne_zero_iff.mpr h2)] @@ -237,27 +235,4 @@ theorem tan_eq_zero_iff' {θ : ℝ} (hθ : cos θ ≠ 0) : tan θ = 0 ↔ ∃ k theorem tan_ne_zero_iff {θ : ℝ} : tan θ ≠ 0 ↔ ∀ k : ℤ, k * π / 2 ≠ θ := mod_cast @Complex.tan_ne_zero_iff θ -theorem lt_sin_mul {x : ℝ} (hx : 0 < x) (hx' : x < 1) : x < sin (π / 2 * x) := by - simpa [mul_comm x] using - strictConcaveOn_sin_Icc.2 ⟨le_rfl, pi_pos.le⟩ ⟨pi_div_two_pos.le, half_le_self pi_pos.le⟩ - pi_div_two_pos.ne (sub_pos.2 hx') hx - -theorem le_sin_mul {x : ℝ} (hx : 0 ≤ x) (hx' : x ≤ 1) : x ≤ sin (π / 2 * x) := by - simpa [mul_comm x] using - strictConcaveOn_sin_Icc.concaveOn.2 ⟨le_rfl, pi_pos.le⟩ - ⟨pi_div_two_pos.le, half_le_self pi_pos.le⟩ (sub_nonneg.2 hx') hx - -theorem mul_lt_sin {x : ℝ} (hx : 0 < x) (hx' : x < π / 2) : 2 / π * x < sin x := by - rw [← inv_div] - simpa [-inv_div, mul_inv_cancel_left₀ pi_div_two_pos.ne'] using @lt_sin_mul ((π / 2)⁻¹ * x) - (mul_pos (inv_pos.2 pi_div_two_pos) hx) (by rwa [← div_eq_inv_mul, div_lt_one pi_div_two_pos]) - -/-- In the range `[0, π / 2]`, we have a linear lower bound on `sin`. This inequality forms one half -of Jordan's inequality, the other half is `Real.sin_lt` -/ -theorem mul_le_sin {x : ℝ} (hx : 0 ≤ x) (hx' : x ≤ π / 2) : 2 / π * x ≤ sin x := by - rw [← inv_div] - simpa [-inv_div, mul_inv_cancel_left₀ pi_div_two_pos.ne'] using @le_sin_mul ((π / 2)⁻¹ * x) - (mul_nonneg (inv_nonneg.2 pi_div_two_pos.le) hx) - (by rwa [← div_eq_inv_mul, div_le_one pi_div_two_pos]) - end Real diff --git a/Mathlib/Analysis/SpecialFunctions/Trigonometric/ComplexDeriv.lean b/Mathlib/Analysis/SpecialFunctions/Trigonometric/ComplexDeriv.lean index 6d74a3ace85b2..e414b1421381a 100644 --- a/Mathlib/Analysis/SpecialFunctions/Trigonometric/ComplexDeriv.lean +++ b/Mathlib/Analysis/SpecialFunctions/Trigonometric/ComplexDeriv.lean @@ -4,6 +4,7 @@ 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.Analysis.SpecialFunctions.Trigonometric.Complex +import Mathlib.Analysis.SpecialFunctions.Trigonometric.Deriv /-! # Complex trigonometric functions diff --git a/Mathlib/Analysis/SpecialFunctions/Trigonometric/EulerSineProd.lean b/Mathlib/Analysis/SpecialFunctions/Trigonometric/EulerSineProd.lean index 7b8d099c1e98a..fc6711228b07f 100644 --- a/Mathlib/Analysis/SpecialFunctions/Trigonometric/EulerSineProd.lean +++ b/Mathlib/Analysis/SpecialFunctions/Trigonometric/EulerSineProd.lean @@ -141,7 +141,7 @@ theorem integral_sin_mul_sin_mul_cos_pow_eq (hn : 2 ≤ n) (hz : z ≠ 0) : · apply Continuous.intervalIntegrable exact Complex.continuous_sin.comp (continuous_const.mul Complex.continuous_ofReal) -/-- Note this also holds for `z = 0`, but we do not need this case for `sin_pi_mul_eq`. -/ +/-- Note this also holds for `z = 0`, but we do not need this case for `sin_pi_mul_eq`. -/ theorem integral_cos_mul_cos_pow (hn : 2 ≤ n) (hz : z ≠ 0) : (((1 : ℂ) - (4 : ℂ) * z ^ 2 / (n : ℂ) ^ 2) * ∫ x in (0 : ℝ)..π / 2, Complex.cos (2 * z * x) * (cos x : ℂ) ^ n) = diff --git a/Mathlib/Analysis/SpecificLimits/Basic.lean b/Mathlib/Analysis/SpecificLimits/Basic.lean index 1292f0573acdb..5b3478e93056c 100644 --- a/Mathlib/Analysis/SpecificLimits/Basic.lean +++ b/Mathlib/Analysis/SpecificLimits/Basic.lean @@ -258,7 +258,7 @@ protected theorem ENNReal.tendsto_pow_atTop_nhds_top_iff {r : ℝ≥0∞} : simp only [ENNReal.tendsto_pow_atTop_nhds_zero_iff, inv_zero] at obs simpa [← ENNReal.inv_pow] using obs <| ENNReal.inv_lt_one.mpr r_gt_one -/-! ### Geometric series-/ +/-! ### Geometric series -/ section Geometric @@ -654,12 +654,12 @@ theorem tendsto_nat_floor_mul_div_atTop {a : R} (ha : 0 ≤ a) : rw [sub_zero] at A apply tendsto_of_tendsto_of_tendsto_of_le_of_le' A tendsto_const_nhds · refine eventually_atTop.2 ⟨1, fun x hx ↦ ?_⟩ - simp only [le_div_iff (zero_lt_one.trans_le hx), _root_.sub_mul, + simp only [le_div_iff₀ (zero_lt_one.trans_le hx), _root_.sub_mul, inv_mul_cancel₀ (zero_lt_one.trans_le hx).ne'] have := Nat.lt_floor_add_one (a * x) linarith · refine eventually_atTop.2 ⟨1, fun x hx ↦ ?_⟩ - rw [div_le_iff (zero_lt_one.trans_le hx)] + rw [div_le_iff₀ (zero_lt_one.trans_le hx)] simp [Nat.floor_le (mul_nonneg ha (zero_le_one.trans hx))] theorem tendsto_nat_floor_div_atTop : Tendsto (fun x ↦ (⌊x⌋₊ : R) / x) atTop (𝓝 1) := by @@ -672,10 +672,10 @@ theorem tendsto_nat_ceil_mul_div_atTop {a : R} (ha : 0 ≤ a) : rw [add_zero] at A apply tendsto_of_tendsto_of_tendsto_of_le_of_le' tendsto_const_nhds A · refine eventually_atTop.2 ⟨1, fun x hx ↦ ?_⟩ - rw [le_div_iff (zero_lt_one.trans_le hx)] + rw [le_div_iff₀ (zero_lt_one.trans_le hx)] exact Nat.le_ceil _ · refine eventually_atTop.2 ⟨1, fun x hx ↦ ?_⟩ - simp [div_le_iff (zero_lt_one.trans_le hx), inv_mul_cancel₀ (zero_lt_one.trans_le hx).ne', + simp [div_le_iff₀ (zero_lt_one.trans_le hx), inv_mul_cancel₀ (zero_lt_one.trans_le hx).ne', (Nat.ceil_lt_add_one (mul_nonneg ha (zero_le_one.trans hx))).le, add_mul] theorem tendsto_nat_ceil_div_atTop : Tendsto (fun x ↦ (⌈x⌉₊ : R) / x) atTop (𝓝 1) := by diff --git a/Mathlib/Analysis/SpecificLimits/FloorPow.lean b/Mathlib/Analysis/SpecificLimits/FloorPow.lean index 1000c3b72484d..0916d04a949a1 100644 --- a/Mathlib/Analysis/SpecificLimits/FloorPow.lean +++ b/Mathlib/Analysis/SpecificLimits/FloorPow.lean @@ -212,7 +212,7 @@ theorem tendsto_div_of_monotone_of_tendsto_div_floor_pow (u : ℕ → ℝ) (l : field_simp [(zero_lt_one.trans (cone k)).ne', (H n).ne'] ring filter_upwards [(tendsto_order.1 B).2 a hk] with n hn - exact (div_le_iff (H n)).1 hn.le + exact (div_le_iff₀ (H n)).1 hn.le /-- The sum of `1/(c^i)^2` above a threshold `j` is comparable to `1/j^2`, up to a multiplicative constant. -/ @@ -296,7 +296,7 @@ theorem sum_div_nat_floor_pow_sq_le_div_sq (N : ℕ) {j : ℝ} (hj : 0 < j) {c : · exact sq_pos_of_pos (pow_pos cpos _) rw [one_mul, ← mul_pow] gcongr - rw [← div_eq_inv_mul, le_div_iff A, mul_comm] + rw [← div_eq_inv_mul, le_div_iff₀ A, mul_comm] exact mul_pow_le_nat_floor_pow hc i _ ≤ (1 - c⁻¹)⁻¹ ^ 2 * (c ^ 3 * (c - 1)⁻¹) / j ^ 2 := by rw [← mul_sum, ← mul_div_assoc'] diff --git a/Mathlib/Analysis/SpecificLimits/Normed.lean b/Mathlib/Analysis/SpecificLimits/Normed.lean index 549efc80b228a..c46af42ab84e6 100644 --- a/Mathlib/Analysis/SpecificLimits/Normed.lean +++ b/Mathlib/Analysis/SpecificLimits/Normed.lean @@ -5,11 +5,15 @@ Authors: Anatole Dedecker, Sébastien Gouëzel, Yury Kudryashov, Dylan MacKenzie -/ import Mathlib.Algebra.BigOperators.Module import Mathlib.Algebra.Order.Field.Basic -import Mathlib.Order.Filter.ModEq import Mathlib.Analysis.Asymptotics.Asymptotics +import Mathlib.Analysis.Normed.Field.InfiniteSum +import Mathlib.Analysis.Normed.Module.Basic import Mathlib.Analysis.SpecificLimits.Basic import Mathlib.Data.List.TFAE -import Mathlib.Analysis.Normed.Module.Basic +import Mathlib.Data.Nat.Choose.Bounds +import Mathlib.Order.Filter.ModEq +import Mathlib.RingTheory.Polynomial.Pochhammer +import Mathlib.Tactic.NoncommRing /-! # A collection of specific limit computations @@ -258,7 +262,7 @@ theorem tendsto_pow_atTop_nhds_zero_of_abs_lt_one {r : ℝ} (h : |r| < 1) : @[deprecated (since := "2024-01-31")] alias tendsto_pow_atTop_nhds_0_of_abs_lt_1 := tendsto_pow_atTop_nhds_zero_of_abs_lt_one -/-! ### Geometric series-/ +/-! ### Geometric series -/ section Geometric @@ -327,54 +331,144 @@ end Geometric section MulGeometric +theorem summable_norm_mul_geometric_of_norm_lt_one {R : Type*} [NormedRing R] {k : ℕ} {r : R} + (hr : ‖r‖ < 1) {u : ℕ → ℕ} (hu : (fun n ↦ (u n : ℝ)) =O[atTop] (fun n ↦ (↑(n ^ k) : ℝ))) : + Summable fun n : ℕ ↦ ‖(u n * r ^ n : R)‖ := by + rcases exists_between hr with ⟨r', hrr', h⟩ + rw [← norm_norm] at hrr' + apply summable_of_isBigO_nat (summable_geometric_of_lt_one ((norm_nonneg _).trans hrr'.le) h) + calc + fun n ↦ ‖↑(u n) * r ^ n‖ + _ =O[atTop] fun n ↦ u n * ‖r‖ ^ n := by + apply (IsBigOWith.of_bound (c := ‖(1 : R)‖) ?_).isBigO + filter_upwards [eventually_norm_pow_le r] with n hn + simp only [norm_norm, norm_mul, Real.norm_eq_abs, abs_cast, norm_pow, abs_norm] + apply (norm_mul_le _ _).trans + have : ‖(u n : R)‖ * ‖r ^ n‖ ≤ (u n * ‖(1 : R)‖) * ‖r‖ ^ n := by + gcongr; exact norm_cast_le (u n) + exact this.trans_eq (by ring) + _ =O[atTop] fun n ↦ ↑(n ^ k) * ‖r‖ ^ n := hu.mul (isBigO_refl _ _) + _ =O[atTop] fun n ↦ r' ^ n := by + simp only [cast_pow] + exact (isLittleO_pow_const_mul_const_pow_const_pow_of_norm_lt k hrr').isBigO + theorem summable_norm_pow_mul_geometric_of_norm_lt_one {R : Type*} [NormedRing R] (k : ℕ) {r : R} (hr : ‖r‖ < 1) : Summable fun n : ℕ ↦ ‖((n : R) ^ k * r ^ n : R)‖ := by - rcases exists_between hr with ⟨r', hrr', h⟩ - exact summable_of_isBigO_nat (summable_geometric_of_lt_one ((norm_nonneg _).trans hrr'.le) h) - (isLittleO_pow_const_mul_const_pow_const_pow_of_norm_lt _ hrr').isBigO.norm_left + simp only [← cast_pow] + exact summable_norm_mul_geometric_of_norm_lt_one (k := k) (u := fun n ↦ n ^ k) hr + (isBigO_refl _ _) + +theorem summable_norm_geometric_of_norm_lt_one {R : Type*} [NormedRing R] {r : R} + (hr : ‖r‖ < 1) : Summable fun n : ℕ ↦ ‖(r ^ n : R)‖ := by + simpa using summable_norm_pow_mul_geometric_of_norm_lt_one 0 hr @[deprecated (since := "2024-01-31")] alias summable_norm_pow_mul_geometric_of_norm_lt_1 := summable_norm_pow_mul_geometric_of_norm_lt_one -theorem summable_pow_mul_geometric_of_norm_lt_one {R : Type*} [NormedRing R] [CompleteSpace R] - (k : ℕ) {r : R} (hr : ‖r‖ < 1) : Summable (fun n ↦ (n : R) ^ k * r ^ n : ℕ → R) := - .of_norm <| summable_norm_pow_mul_geometric_of_norm_lt_one _ hr +variable {𝕜 : Type*} [NormedDivisionRing 𝕜] + +/-- The sum of `(n+k).choose k * r^n` is `1/(1-r)^{k+1}`. +See also `PowerSeries.invOneSubPow_val_eq_mk_choose_add` for the corresponding statement in formal +power series, without summability arguments. -/ +lemma hasSum_choose_mul_geometric_of_norm_lt_one + (k : ℕ) {r : 𝕜} (hr : ‖r‖ < 1) : + HasSum (fun n ↦ (n + k).choose k * r ^ n) (1 / (1 - r) ^ (k + 1)) := by + induction k with + | zero => simpa using hasSum_geometric_of_norm_lt_one hr + | succ k ih => + have I1 : Summable (fun (n : ℕ) ↦ ‖(n + k).choose k * r ^ n‖) := by + apply summable_norm_mul_geometric_of_norm_lt_one (k := k) hr + apply isBigO_iff.2 ⟨2 ^ k, ?_⟩ + filter_upwards [Ioi_mem_atTop k] with n (hn : k < n) + simp only [Real.norm_eq_abs, abs_cast, cast_pow, norm_pow] + norm_cast + calc (n + k).choose k + _ ≤ (2 * n).choose k := choose_le_choose k (by omega) + _ ≤ (2 * n) ^ k := Nat.choose_le_pow _ _ + _ = 2 ^ k * n ^ k := Nat.mul_pow 2 n k + convert hasSum_sum_range_mul_of_summable_norm' I1 ih.summable + (summable_norm_geometric_of_norm_lt_one hr) (summable_geometric_of_norm_lt_one hr) using 1 + · ext n + have : ∑ i ∈ Finset.range (n + 1), ↑((i + k).choose k) * r ^ i * r ^ (n - i) = + ∑ i ∈ Finset.range (n + 1), ↑((i + k).choose k) * r ^ n := by + apply Finset.sum_congr rfl (fun i hi ↦ ?_) + simp only [Finset.mem_range] at hi + rw [mul_assoc, ← pow_add, show i + (n - i) = n by omega] + simp_rw [this, ← sum_mul, ← Nat.cast_sum, sum_range_add_choose n k, add_assoc] + · rw [ih.tsum_eq, (hasSum_geometric_of_norm_lt_one hr).tsum_eq, pow_succ] + simp only [one_div, ← mul_inv_rev, ← pow_succ, ← _root_.pow_succ'] + +lemma summable_choose_mul_geometric_of_norm_lt_one (k : ℕ) {r : 𝕜} (hr : ‖r‖ < 1) : + Summable (fun n ↦ (n + k).choose k * r ^ n) := + (hasSum_choose_mul_geometric_of_norm_lt_one k hr).summable + +lemma tsum_choose_mul_geometric_of_norm_lt_one (k : ℕ) {r : 𝕜} (hr : ‖r‖ < 1) : + ∑' n, (n + k).choose k * r ^ n = 1 / (1 - r) ^ (k + 1) := + (hasSum_choose_mul_geometric_of_norm_lt_one k hr).tsum_eq + +lemma summable_descFactorial_mul_geometric_of_norm_lt_one (k : ℕ) {r : 𝕜} (hr : ‖r‖ < 1) : + Summable (fun n ↦ (n + k).descFactorial k * r ^ n) := by + convert (summable_choose_mul_geometric_of_norm_lt_one k hr).mul_left (k.factorial : 𝕜) + using 2 with n + simp [← mul_assoc, descFactorial_eq_factorial_mul_choose (n + k) k] + +open Polynomial in +theorem summable_pow_mul_geometric_of_norm_lt_one (k : ℕ) {r : 𝕜} (hr : ‖r‖ < 1) : + Summable (fun n ↦ (n : 𝕜) ^ k * r ^ n : ℕ → 𝕜) := by + refine Nat.strong_induction_on k fun k hk => ?_ + obtain ⟨a, ha⟩ : ∃ (a : ℕ → ℕ), ∀ n, (n + k).descFactorial k + = n ^ k + ∑ i ∈ range k, a i * n ^ i := by + let P : Polynomial ℕ := (ascPochhammer ℕ k).comp (Polynomial.X + C 1) + refine ⟨fun i ↦ P.coeff i, fun n ↦ ?_⟩ + have mP : Monic P := Monic.comp_X_add_C (monic_ascPochhammer ℕ k) _ + have dP : P.natDegree = k := by + simp only [P, natDegree_comp, ascPochhammer_natDegree, mul_one, natDegree_X_add_C] + have A : (n + k).descFactorial k = P.eval n := by + have : n + 1 + k - 1 = n + k := by omega + simp [P, ascPochhammer_nat_eq_descFactorial, this] + conv_lhs => rw [A, mP.as_sum, dP] + simp [eval_finset_sum] + have : Summable (fun n ↦ (n + k).descFactorial k * r ^ n + - ∑ i ∈ range k, a i * n ^ (i : ℕ) * r ^ n) := by + apply (summable_descFactorial_mul_geometric_of_norm_lt_one k hr).sub + apply summable_sum (fun i hi ↦ ?_) + simp_rw [mul_assoc] + simp only [Finset.mem_range] at hi + exact (hk _ hi).mul_left _ + convert this using 1 + ext n + simp [ha n, add_mul, sum_mul] @[deprecated (since := "2024-01-31")] alias summable_pow_mul_geometric_of_norm_lt_1 := summable_pow_mul_geometric_of_norm_lt_one /-- If `‖r‖ < 1`, then `∑' n : ℕ, n * r ^ n = r / (1 - r) ^ 2`, `HasSum` version. -/ -theorem hasSum_coe_mul_geometric_of_norm_lt_one {𝕜 : Type*} [NormedDivisionRing 𝕜] [CompleteSpace 𝕜] +theorem hasSum_coe_mul_geometric_of_norm_lt_one {r : 𝕜} (hr : ‖r‖ < 1) : HasSum (fun n ↦ n * r ^ n : ℕ → 𝕜) (r / (1 - r) ^ 2) := by - have A : Summable (fun n ↦ (n : 𝕜) * r ^ n : ℕ → 𝕜) := by - simpa only [pow_one] using summable_pow_mul_geometric_of_norm_lt_one 1 hr - have B : HasSum (r ^ · : ℕ → 𝕜) (1 - r)⁻¹ := hasSum_geometric_of_norm_lt_one hr - refine A.hasSum_iff.2 ?_ - have hr' : r ≠ 1 := by - rintro rfl - simp [lt_irrefl] at hr - set s : 𝕜 := ∑' n : ℕ, n * r ^ n - have : Commute (1 - r) s := - .tsum_right _ fun _ => - .sub_left (.one_left _) (.mul_right (Nat.commute_cast _ _) (.pow_right (.refl _) _)) - calc - s = s * (1 - r) / (1 - r) := (mul_div_cancel_right₀ _ (sub_ne_zero.2 hr'.symm)).symm - _ = (1 - r) * s / (1 - r) := by rw [this.eq] - _ = (s - r * s) / (1 - r) := by rw [_root_.sub_mul, one_mul] - _ = (((0 : ℕ) * r ^ 0 + ∑' n : ℕ, (n + 1 : ℕ) * r ^ (n + 1)) - r * s) / (1 - r) := by - rw [← tsum_eq_zero_add A] - _ = ((r * ∑' n : ℕ, ↑(n + 1) * r ^ n) - r * s) / (1 - r) := by - simp only [cast_zero, pow_zero, mul_one, _root_.pow_succ', (Nat.cast_commute _ r).left_comm, - _root_.tsum_mul_left, zero_add] + have A : HasSum (fun (n : ℕ) ↦ (n + 1) * r ^ n) (1 / (1 - r) ^ 2) := by + convert hasSum_choose_mul_geometric_of_norm_lt_one 1 hr with n + simp + have B : HasSum (fun (n : ℕ) ↦ r ^ n) ((1 - r) ⁻¹) := hasSum_geometric_of_norm_lt_one hr + convert A.sub B using 1 + · ext n + simp [add_mul] + · symm + calc 1 / (1 - r) ^ 2 - (1 - r) ⁻¹ + _ = 1 / (1 - r) ^ 2 - ((1 - r) * (1 - r) ⁻¹) * (1 - r) ⁻¹ := by + rw [mul_inv_cancel₀, one_mul] + intro h + simp only [sub_eq_zero] at h + simp [← h] at hr _ = r / (1 - r) ^ 2 := by - simp [add_mul, tsum_add A B.summable, mul_add, B.tsum_eq, ← div_eq_mul_inv, sq, - div_mul_eq_div_div_swap] + simp only [one_div, mul_assoc, ← mul_inv_rev] + rw [inv_eq_one_div, inv_eq_one_div, ← pow_two, _root_.sub_mul, one_mul, mul_div, mul_one] + abel @[deprecated (since := "2024-01-31")] alias hasSum_coe_mul_geometric_of_norm_lt_1 := hasSum_coe_mul_geometric_of_norm_lt_one /-- If `‖r‖ < 1`, then `∑' n : ℕ, n * r ^ n = r / (1 - r) ^ 2`. -/ -theorem tsum_coe_mul_geometric_of_norm_lt_one {𝕜 : Type*} [NormedDivisionRing 𝕜] [CompleteSpace 𝕜] +theorem tsum_coe_mul_geometric_of_norm_lt_one {r : 𝕜} (hr : ‖r‖ < 1) : (∑' n : ℕ, n * r ^ n : 𝕜) = r / (1 - r) ^ 2 := (hasSum_coe_mul_geometric_of_norm_lt_one hr).tsum_eq @@ -548,7 +642,7 @@ theorem summable_of_ratio_test_tendsto_lt_one {α : Type*} [NormedAddCommGroup rcases exists_between hl₁ with ⟨r, hr₀, hr₁⟩ refine summable_of_ratio_norm_eventually_le hr₁ ?_ filter_upwards [eventually_le_of_tendsto_lt hr₀ h, hf] with _ _ h₁ - rwa [← div_le_iff (norm_pos_iff.mpr h₁)] + rwa [← div_le_iff₀ (norm_pos_iff.mpr h₁)] theorem not_summable_of_ratio_norm_eventually_ge {α : Type*} [SeminormedAddCommGroup α] {f : ℕ → α} {r : ℝ} (hr : 1 < r) (hf : ∃ᶠ n in atTop, ‖f n‖ ≠ 0) @@ -581,7 +675,7 @@ theorem not_summable_of_ratio_test_tendsto_gt_one {α : Type*} [SeminormedAddCom rcases exists_between hl with ⟨r, hr₀, hr₁⟩ refine not_summable_of_ratio_norm_eventually_ge hr₀ key.frequently ?_ filter_upwards [eventually_ge_of_tendsto_gt hr₁ h, key] with _ _ h₁ - rwa [← le_div_iff (lt_of_le_of_ne (norm_nonneg _) h₁.symm)] + rwa [← le_div_iff₀ (lt_of_le_of_ne (norm_nonneg _) h₁.symm)] section NormedDivisionRing @@ -597,7 +691,7 @@ theorem summable_powerSeries_of_norm_lt {w z : α} refine cauchySeq_finset_of_geometric_bound (r := ‖z‖ / ‖w‖) (C := C) ((div_lt_one hw).mpr hz) (fun n ↦ ?_) rw [norm_mul, norm_pow, div_pow, ← mul_comm_div] - conv at hC => enter [n]; rw [norm_mul, norm_pow, ← _root_.le_div_iff (by positivity)] + conv at hC => enter [n]; rw [norm_mul, norm_pow, ← _root_.le_div_iff₀ (by positivity)] exact mul_le_mul_of_nonneg_right (hC n) (pow_nonneg (norm_nonneg z) n) /-- If a power series converges at 1, it converges absolutely at all `z` of smaller norm. -/ diff --git a/Mathlib/Analysis/Subadditive.lean b/Mathlib/Analysis/Subadditive.lean index 00d92dc291067..10867220bdf25 100644 --- a/Mathlib/Analysis/Subadditive.lean +++ b/Mathlib/Analysis/Subadditive.lean @@ -67,7 +67,7 @@ theorem eventually_div_lt_of_div_lt {L : ℝ} {n : ℕ} (hn : n ≠ 0) (hL : u n have B : Tendsto (fun x => (x * u n + u r) / (x * n + r)) atTop (𝓝 (u n / n)) := by rw [add_zero, add_zero] at A refine A.congr' <| (eventually_ne_atTop 0).mono fun x hx => ?_ - simp only [(· ∘ ·), add_div' _ _ _ hx, div_div_div_cancel_right _ hx, mul_comm] + simp only [(· ∘ ·), add_div' _ _ _ hx, div_div_div_cancel_right₀ hx, mul_comm] refine ((B.comp tendsto_natCast_atTop_atTop).eventually (gt_mem_nhds hL)).mono fun k hk => ?_ /- Finally, we use an upper estimate on `u (k * n + r)` to get an estimate on `u (k * n + r) / (k * n + r)`. -/ diff --git a/Mathlib/Analysis/SumOverResidueClass.lean b/Mathlib/Analysis/SumOverResidueClass.lean index 92432ccab72a0..d0109a33064e6 100644 --- a/Mathlib/Analysis/SumOverResidueClass.lean +++ b/Mathlib/Analysis/SumOverResidueClass.lean @@ -3,9 +3,9 @@ Copyright (c) 2024 Michael Stoll. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Michael Stoll -/ +import Mathlib.Analysis.Normed.Field.Basic import Mathlib.Data.ZMod.Basic import Mathlib.Topology.Instances.ENNReal -import Mathlib.Analysis.Normed.Field.Basic /-! # Sums over residue classes @@ -92,3 +92,14 @@ lemma summable_indicator_mod_iff {m : ℕ} [NeZero m] {f : ℕ → ℝ} (hf : An convert summable_sum (s := Finset.univ) fun a _ ↦ summable_indicator_mod_iff_summable_indicator_mod hf a H simp only [Finset.sum_apply] + +open ZMod + +/-- If `f` is a summable function on `ℕ`, and `0 < N`, then we may compute `∑' n : ℕ, f n` by +summing each residue class mod `N` separately. -/ +lemma Nat.sumByResidueClasses {R : Type*} [AddCommGroup R] [UniformSpace R] [UniformAddGroup R] + [CompleteSpace R] [T0Space R] {f : ℕ → R} (hf : Summable f) (N : ℕ) [NeZero N] : + ∑' n, f n = ∑ j : ZMod N, ∑' m, f (j.val + N * m) := by + rw [← (residueClassesEquiv N).symm.tsum_eq f, tsum_prod, tsum_fintype, residueClassesEquiv, + Equiv.coe_fn_symm_mk] + exact hf.comp_injective (residueClassesEquiv N).symm.injective diff --git a/Mathlib/CategoryTheory/Abelian/Exact.lean b/Mathlib/CategoryTheory/Abelian/Exact.lean index cfc118215dd0f..85352b81dbb61 100644 --- a/Mathlib/CategoryTheory/Abelian/Exact.lean +++ b/Mathlib/CategoryTheory/Abelian/Exact.lean @@ -240,14 +240,14 @@ theorem preservesMonomorphisms_of_map_exact : L.PreservesMonomorphisms where preserves f hf := by apply ((Abelian.tfae_mono (L.map f) (L.obj 0)).out 2 0).mp refine ShortComplex.exact_of_iso ?_ (hL _ (((tfae_mono f 0).out 0 2).mp hf)) - exact ShortComplex.isoMk (Iso.refl _) (Iso.refl _) (Iso.refl _) + exact ShortComplex.isoMk (Iso.refl _) (Iso.refl _) (Iso.refl _) /-- A functor which preserves exactness preserves epimorphisms. -/ theorem preservesEpimorphisms_of_map_exact : L.PreservesEpimorphisms where preserves f hf := by apply ((Abelian.tfae_epi (L.map f) (L.obj 0)).out 2 0).mp refine ShortComplex.exact_of_iso ?_ (hL _ (((tfae_epi f 0).out 0 2).mp hf)) - exact ShortComplex.isoMk (Iso.refl _) (Iso.refl _) (Iso.refl _) + exact ShortComplex.isoMk (Iso.refl _) (Iso.refl _) (Iso.refl _) /-- A functor which preserves the exactness of short complexes preserves homology. -/ def preservesHomologyOfMapExact : L.PreservesHomology where diff --git a/Mathlib/CategoryTheory/Abelian/Transfer.lean b/Mathlib/CategoryTheory/Abelian/Transfer.lean index 1948ebfb7f9a6..9e05999b3184a 100644 --- a/Mathlib/CategoryTheory/Abelian/Transfer.lean +++ b/Mathlib/CategoryTheory/Abelian/Transfer.lean @@ -128,7 +128,7 @@ def coimageIsoImage (i : F ⋙ G ≅ 𝟭 C) (adj : G ⊣ F) {X Y : C} (f : X _ ≅ Abelian.image f := Iso.refl _ -- The account of this proof in the Stacks project omits this calculation. -theorem coimageIsoImage_hom (i : F ⋙ G ≅ 𝟭 C) (adj : G ⊣ F) {X Y : C} (f : X ⟶ Y) : +theorem coimageIsoImage_hom (i : F ⋙ G ≅ 𝟭 C) (adj : G ⊣ F) {X Y : C} (f : X ⟶ Y) : (coimageIsoImage F G i adj f).hom = Abelian.coimageImageComparison f := by dsimp [coimageIsoImage, cokernelIso, cokernelEpiComp, cokernelCompIsIso_inv, coimageIsoImageAux, kernelCompMono] diff --git a/Mathlib/CategoryTheory/Adjunction/AdjointFunctorTheorems.lean b/Mathlib/CategoryTheory/Adjunction/AdjointFunctorTheorems.lean index 64158bfaf6b47..3d5e083b0ab9b 100644 --- a/Mathlib/CategoryTheory/Adjunction/AdjointFunctorTheorems.lean +++ b/Mathlib/CategoryTheory/Adjunction/AdjointFunctorTheorems.lean @@ -6,7 +6,7 @@ Authors: Bhavik Mehta import Mathlib.CategoryTheory.Generator import Mathlib.CategoryTheory.Limits.ConeCategory import Mathlib.CategoryTheory.Limits.Constructions.WeaklyInitial -import Mathlib.CategoryTheory.Limits.FunctorCategory +import Mathlib.CategoryTheory.Limits.FunctorCategory.Basic import Mathlib.CategoryTheory.Subobject.Comma /-! @@ -62,7 +62,7 @@ section GeneralAdjointFunctorTheorem variable {D : Type u} [Category.{v} D] variable (G : D ⥤ C) -/-- If `G : D ⥤ C` is a right adjoint it satisfies the solution set condition. -/ +/-- If `G : D ⥤ C` is a right adjoint it satisfies the solution set condition. -/ theorem solutionSetCondition_of_isRightAdjoint [G.IsRightAdjoint] : SolutionSetCondition G := by intro A refine diff --git a/Mathlib/CategoryTheory/Adjunction/Basic.lean b/Mathlib/CategoryTheory/Adjunction/Basic.lean index ad3d1b46c9181..6bb76fb19fe02 100644 --- a/Mathlib/CategoryTheory/Adjunction/Basic.lean +++ b/Mathlib/CategoryTheory/Adjunction/Basic.lean @@ -52,7 +52,7 @@ constructors `mkOfHomEquiv` or `mkOfUnitCounit`. To construct a left adjoint, there are also constructors `leftAdjointOfEquiv` and `adjunctionOfEquivLeft` (as well as their duals) which can be simpler in practice. -Uniqueness of adjoints is shown in `CategoryTheory.Adjunction.Opposites`. +Uniqueness of adjoints is shown in `CategoryTheory.Adjunction.Unique`. See . -/ @@ -63,11 +63,9 @@ structure Adjunction (F : C ⥤ D) (G : D ⥤ C) where unit : 𝟭 C ⟶ F.comp G /-- The counit of an adjunction -/ counit : G.comp F ⟶ 𝟭 D - -- Porting note: It's strange that this `Prop` is being flagged by the `docBlame` linter - /-- Naturality of the unit of an adjunction -/ - homEquiv_unit : ∀ {X Y f}, (homEquiv X Y) f = (unit : _ ⟶ _).app X ≫ G.map f := by aesop_cat - -- Porting note: It's strange that this `Prop` is being flagged by the `docBlame` linter - /-- Naturality of the counit of an adjunction -/ + /-- The relationship between the unit and hom set equivalence of an adjunction -/ + homEquiv_unit : ∀ {X Y f}, (homEquiv X Y) f = unit.app X ≫ G.map f := by aesop_cat + /-- The relationship between the counit and hom set equivalence of an adjunction -/ homEquiv_counit : ∀ {X Y g}, (homEquiv X Y).symm g = F.map g ≫ counit.app Y := by aesop_cat /-- The notation `F ⊣ G` stands for `Adjunction F G` representing that `F` is left adjoint to `G` -/ @@ -105,11 +103,6 @@ noncomputable def Adjunction.ofIsRightAdjoint (right : C ⥤ D) [right.IsRightAd namespace Adjunction --- Porting note: Workaround not needed in Lean 4 --- restate_axiom homEquiv_unit' - --- restate_axiom homEquiv_counit' - attribute [simp] homEquiv_unit homEquiv_counit section @@ -132,35 +125,23 @@ theorem homEquiv_id (X : C) : adj.homEquiv X _ (𝟙 _) = adj.unit.app X := by s theorem homEquiv_symm_id (X : D) : (adj.homEquiv _ X).symm (𝟙 _) = adj.counit.app X := by simp -/- -Porting note: `nolint simpNF` as the linter was complaining that this was provable using `simp` -but it is in fact not. Also the `docBlame` linter expects a docstring even though this is `Prop` -valued --/ -@[simp, nolint simpNF] theorem homEquiv_naturality_left_symm (f : X' ⟶ X) (g : X ⟶ G.obj Y) : (adj.homEquiv X' Y).symm (f ≫ g) = F.map f ≫ (adj.homEquiv X Y).symm g := by - rw [homEquiv_counit, F.map_comp, assoc, adj.homEquiv_counit.symm] + simp --- Porting note: Same as above -@[simp, nolint simpNF] theorem homEquiv_naturality_left (f : X' ⟶ X) (g : F.obj X ⟶ Y) : (adj.homEquiv X' Y) (F.map f ≫ g) = f ≫ (adj.homEquiv X Y) g := by rw [← Equiv.eq_symm_apply] - simp only [Equiv.symm_apply_apply,eq_self_iff_true,homEquiv_naturality_left_symm] + simp only [Equiv.symm_apply_apply, eq_self_iff_true, homEquiv_naturality_left_symm] --- Porting note: Same as above -@[simp, nolint simpNF] theorem homEquiv_naturality_right (f : F.obj X ⟶ Y) (g : Y ⟶ Y') : (adj.homEquiv X Y') (f ≫ g) = (adj.homEquiv X Y) f ≫ G.map g := by - rw [homEquiv_unit, G.map_comp, ← assoc, ← homEquiv_unit] + simp --- Porting note: Same as above -@[simp, nolint simpNF] theorem homEquiv_naturality_right_symm (f : X ⟶ G.obj Y) (g : Y ⟶ Y') : (adj.homEquiv X Y').symm (f ≫ G.map g) = (adj.homEquiv X Y).symm f ≫ g := by rw [Equiv.symm_apply_eq] - simp only [homEquiv_naturality_right,eq_self_iff_true,Equiv.apply_symm_apply] + simp only [homEquiv_naturality_right, eq_self_iff_true, Equiv.apply_symm_apply] @[reassoc] theorem homEquiv_naturality_left_square (f : X' ⟶ X) (g : F.obj X ⟶ Y') @@ -193,13 +174,13 @@ theorem homEquiv_naturality_right_square_iff (f : X' ⟶ X) (g : X ⟶ G.obj Y') @[simp] theorem left_triangle : whiskerRight adj.unit F ≫ whiskerLeft F adj.counit = 𝟙 _ := by ext; dsimp - erw [← adj.homEquiv_counit, Equiv.symm_apply_eq, adj.homEquiv_unit] + rw [← adj.homEquiv_counit, Equiv.symm_apply_eq, adj.homEquiv_unit] simp @[simp] theorem right_triangle : whiskerLeft G adj.unit ≫ whiskerRight adj.counit G = 𝟙 _ := by ext; dsimp - erw [← adj.homEquiv_unit, ← Equiv.eq_symm_apply, adj.homEquiv_counit] + rw [← adj.homEquiv_unit, ← Equiv.eq_symm_apply, adj.homEquiv_counit] simp variable (X Y) @@ -270,31 +251,14 @@ structure CoreHomEquiv (F : C ⥤ D) (G : D ⥤ C) where namespace CoreHomEquiv --- Porting note: Workaround not needed in Lean 4. --- restate_axiom homEquiv_naturality_left_symm' - --- restate_axiom homEquiv_naturality_right' - attribute [simp] homEquiv_naturality_left_symm homEquiv_naturality_right variable {F : C ⥤ D} {G : D ⥤ C} (adj : CoreHomEquiv F G) {X' X : C} {Y Y' : D} -@[simp] -theorem homEquiv_naturality_left_aux (f : X' ⟶ X) (g : F.obj X ⟶ Y) : - (adj.homEquiv X' (F.obj X)) (F.map f) ≫ G.map g = f ≫ (adj.homEquiv X Y) g := by - rw [← homEquiv_naturality_right, ← Equiv.eq_symm_apply]; simp - --- @[simp] -- Porting note: LHS simplifies, added aux lemma above theorem homEquiv_naturality_left (f : X' ⟶ X) (g : F.obj X ⟶ Y) : (adj.homEquiv X' Y) (F.map f ≫ g) = f ≫ (adj.homEquiv X Y) g := by rw [← Equiv.eq_symm_apply]; simp -@[simp] -theorem homEquiv_naturality_right_symm_aux (f : X ⟶ G.obj Y) (g : Y ⟶ Y') : - F.map f ≫ (adj.homEquiv (G.obj Y) Y').symm (G.map g) = (adj.homEquiv X Y).symm f ≫ g := by - rw [← homEquiv_naturality_left_symm, Equiv.symm_apply_eq]; simp - --- @[simp] -- Porting note: LHS simplifies, added aux lemma above theorem homEquiv_naturality_right_symm (f : X ⟶ G.obj Y) (g : Y ⟶ Y') : (adj.homEquiv X Y').symm (f ≫ G.map g) = (adj.homEquiv X Y).symm f ≫ g := by rw [Equiv.symm_apply_eq]; simp @@ -337,23 +301,19 @@ variable {F : C ⥤ D} {G : D ⥤ C} `F.obj X ⟶ Y` and `X ⟶ G.obj Y`. -/ @[simps] def mkOfHomEquiv (adj : CoreHomEquiv F G) : F ⊣ G := - -- See note [dsimp, simp]. { adj with unit := { app := fun X => (adj.homEquiv X (F.obj X)) (𝟙 (F.obj X)) naturality := by intros - erw [← adj.homEquiv_naturality_left, ← adj.homEquiv_naturality_right] - dsimp; simp } + simp [← adj.homEquiv_naturality_left, ← adj.homEquiv_naturality_right] } counit := { app := fun Y => (adj.homEquiv _ _).invFun (𝟙 (G.obj Y)) naturality := by intros - erw [← adj.homEquiv_naturality_left_symm, ← adj.homEquiv_naturality_right_symm] - dsimp; simp } - homEquiv_unit := @fun X Y f => by erw [← adj.homEquiv_naturality_right]; simp - homEquiv_counit := @fun X Y f => by erw [← adj.homEquiv_naturality_left_symm]; simp - } + simp [← adj.homEquiv_naturality_left_symm, ← adj.homEquiv_naturality_right_symm] } + homEquiv_unit := @fun X Y f => by simp [← adj.homEquiv_naturality_right] + homEquiv_counit := @fun X Y f => by simp [← adj.homEquiv_naturality_left_symm] } /-- Construct an adjunction between functors `F` and `G` given a unit and counit for the adjunction satisfying the triangle identities. -/ @@ -381,11 +341,6 @@ def mkOfUnitCounit (adj : CoreUnitCounit F G) : F ⊣ G := simp only [id_comp] at t exact t } } -/- Porting note: simpNF linter claims these are solved by simp but that -is not true -/ -attribute [nolint simpNF] CategoryTheory.Adjunction.mkOfUnitCounit_homEquiv_symm_apply -attribute [nolint simpNF] CategoryTheory.Adjunction.mkOfUnitCounit_homEquiv_apply - /-- The adjunction between the identity functor on a category and itself. -/ def id : 𝟭 C ⊣ 𝟭 C where homEquiv X Y := Equiv.refl _ @@ -488,12 +443,7 @@ def adjunctionOfEquivLeft : leftAdjointOfEquiv e he ⊣ G := have {X : C} {Y Y' : D} (f : X ⟶ G.obj Y) (g : Y ⟶ Y') : (e X Y').symm (f ≫ G.map g) = (e X Y).symm f ≫ g := by rw [Equiv.symm_apply_eq, he]; simp - erw [← this, ← Equiv.apply_eq_iff_eq (e X' Y)] - simp only [leftAdjointOfEquiv_obj, Equiv.apply_symm_apply, assoc] - congr - rw [← he] - simp - } + simp [← this, ← Equiv.apply_eq_iff_eq (e X' Y), ← he] } end ConstructLeft @@ -530,10 +480,10 @@ def adjunctionOfEquivRight (he : ∀ X' X Y f g, e X' Y (F.map f ≫ g) = f ≫ mkOfHomEquiv { homEquiv := e homEquiv_naturality_left_symm := by - intro X X' Y f g; rw [Equiv.symm_apply_eq]; dsimp; rw [he]; simp + intro X X' Y f g; rw [Equiv.symm_apply_eq]; simp [he] homEquiv_naturality_right := by intro X Y Y' g h - erw [← he, Equiv.apply_eq_iff_eq, ← assoc, he'' e he, comp_id, Equiv.symm_apply_apply] } + simp [← he, reassoc_of% (he'' e)] } end ConstructRight @@ -570,16 +520,7 @@ variable (e : C ≌ D) simply use `e.symm.toAdjunction`. -/ @[simps! unit counit] def toAdjunction : e.functor ⊣ e.inverse := - mkOfUnitCounit - ⟨e.unit, e.counit, by - ext - dsimp - simp only [id_comp] - exact e.functor_unit_comp _, by - ext - dsimp - simp only [id_comp] - exact e.unit_inverse_comp _⟩ + mkOfUnitCounit ⟨e.unit, e.counit, by ext; simp, by ext; simp⟩ lemma isLeftAdjoint_functor : e.functor.IsLeftAdjoint where exists_rightAdjoint := ⟨_, ⟨e.toAdjunction⟩⟩ diff --git a/Mathlib/CategoryTheory/Adjunction/Evaluation.lean b/Mathlib/CategoryTheory/Adjunction/Evaluation.lean index 4109f1e41211b..9fa052e5ca51b 100644 --- a/Mathlib/CategoryTheory/Adjunction/Evaluation.lean +++ b/Mathlib/CategoryTheory/Adjunction/Evaluation.lean @@ -73,7 +73,9 @@ def evaluationAdjunctionRight (c : C) : evaluationLeftAdjoint D c ⊣ (evaluatio instance evaluationIsRightAdjoint (c : C) : ((evaluation _ D).obj c).IsRightAdjoint := ⟨_, ⟨evaluationAdjunctionRight _ _⟩⟩ -theorem NatTrans.mono_iff_mono_app {F G : C ⥤ D} (η : F ⟶ G) : Mono η ↔ ∀ c, Mono (η.app c) := by +/-- See also the file `CategoryTheory.Limits.FunctorCategoryEpiMono` +for a similar result under a `HasPullbacks` assumption. -/ +theorem NatTrans.mono_iff_mono_app' {F G : C ⥤ D} (η : F ⟶ G) : Mono η ↔ ∀ c, Mono (η.app c) := by constructor · intro h c exact (inferInstance : Mono (((evaluation _ _).obj c).map η)) @@ -128,7 +130,10 @@ def evaluationAdjunctionLeft (c : C) : (evaluation _ _).obj c ⊣ evaluationRigh instance evaluationIsLeftAdjoint (c : C) : ((evaluation _ D).obj c).IsLeftAdjoint := ⟨_, ⟨evaluationAdjunctionLeft _ _⟩⟩ -theorem NatTrans.epi_iff_epi_app {F G : C ⥤ D} (η : F ⟶ G) : Epi η ↔ ∀ c, Epi (η.app c) := by + +/-- See also the file `CategoryTheory.Limits.FunctorCategoryEpiMono` +for a similar result under a `HasPushouts` assumption. -/ +theorem NatTrans.epi_iff_epi_app' {F G : C ⥤ D} (η : F ⟶ G) : Epi η ↔ ∀ c, Epi (η.app c) := by constructor · intro h c exact (inferInstance : Epi (((evaluation _ _).obj c).map η)) diff --git a/Mathlib/CategoryTheory/Adjunction/Lifting.lean b/Mathlib/CategoryTheory/Adjunction/Lifting/Left.lean similarity index 86% rename from Mathlib/CategoryTheory/Adjunction/Lifting.lean rename to Mathlib/CategoryTheory/Adjunction/Lifting/Left.lean index d175dc78fa3e1..e4d139ca0cb2b 100644 --- a/Mathlib/CategoryTheory/Adjunction/Lifting.lean +++ b/Mathlib/CategoryTheory/Adjunction/Lifting/Left.lean @@ -3,8 +3,6 @@ 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.CategoryTheory.Limits.Shapes.Equalizers -import Mathlib.CategoryTheory.Limits.Shapes.Reflexive import Mathlib.CategoryTheory.Monad.Adjunction import Mathlib.CategoryTheory.Monad.Coequalizer @@ -13,23 +11,26 @@ import Mathlib.CategoryTheory.Monad.Coequalizer This file gives two constructions for building left adjoints: the adjoint triangle theorem and the adjoint lifting theorem. + The adjoint triangle theorem concerns a functor `U : B ⥤ C` with a left adjoint `F` such that `ε_X : FUX ⟶ X` is a regular epi. Then for any category `A` with coequalizers of reflexive pairs, a functor `R : A ⥤ B` has a left adjoint if (and only if) the composite `R ⋙ U` does. Note that the condition on `U` regarding `ε_X` is automatically satisfied in the case when `U` is -a monadic functor, giving the corollary: `monadicAdjointTriangleLift`, i.e. if `U` is monadic, -`A` has reflexive coequalizers then `R : A ⥤ B` has a left adjoint provided `R ⋙ U` does. +a monadic functor, giving the corollary: `isRightAdjoint_triangle_lift_monadic`, i.e. if `U` is +monadic, `A` has reflexive coequalizers then `R : A ⥤ B` has a left adjoint provided `R ⋙ U` does. The adjoint lifting theorem says that given a commutative square of functors (up to isomorphism): +``` Q A → B U ↓ ↓ V C → D R +``` -where `U` and `V` are monadic and `A` has reflexive coequalizers, then if `R` has a left adjoint -then `Q` has a left adjoint. +where `V` is monadic, `U` has a left adjoint, and `A` has reflexive coequalizers, then if `R` has a +left adjoint then `Q` has a left adjoint. ## Implementation @@ -38,10 +39,14 @@ than just a functor known to be a right adjoint. In docstrings, we write `(η, and counit of the adjunction `adj₁ : F ⊣ U` and `(ι, δ)` for the unit and counit of the adjunction `adj₂ : F' ⊣ R ⋙ U`. +This file has been adapted to `Mathlib.CategoryTheory.Adjunction.Lifting.Right`. +Please try to keep them in sync. + ## TODO -Dualise to lift right adjoints through comonads (by reversing 1-cells) and dualise to lift right -adjoints through monads (by reversing 2-cells), and the combination. +- Dualise to lift right adjoints through monads (by reversing 2-cells). +- Investigate whether it is possible to give a more explicit description of the lifted adjoint, + especially in the case when the isomorphism `comm` is `Iso.refl _` ## References * https://ncatlab.org/nlab/show/adjoint+triangle+theorem @@ -61,7 +66,7 @@ variable {A : Type u₁} {B : Type u₂} {C : Type u₃} variable [Category.{v₁} A] [Category.{v₂} B] [Category.{v₃} C] -- Hide implementation details in this namespace -namespace LiftAdjoint +namespace LiftLeftAdjoint variable {U : B ⥤ C} {F : C ⥤ B} (R : A ⥤ B) (F' : C ⥤ A) variable (adj₁ : F ⊣ U) (adj₂ : F' ⊣ R ⋙ U) @@ -96,7 +101,7 @@ def otherMap (X) : F'.obj (U.obj (F.obj (U.obj X))) ⟶ F'.obj (U.obj X) := F'.map (U.map (F.map (adj₂.unit.app _) ≫ adj₁.counit.app _)) ≫ adj₂.counit.app _ /-- `(F'Uε_X, otherMap X)` is a reflexive pair: in particular if `A` has reflexive coequalizers then -it has a coequalizer. +this pair has a coequalizer. -/ instance (X : B) : IsReflexivePair (F'.map (U.map (adj₁.counit.app X))) (otherMap _ _ adj₁ adj₂ X) := @@ -159,7 +164,7 @@ noncomputable def constructLeftAdjoint [∀ X : B, RegularEpi (adj₁.counit.app -- This used to be `simp`, but we need `aesop_cat` after leanprover/lean4#2644 aesop_cat -end LiftAdjoint +end LiftLeftAdjoint /-- The adjoint triangle theorem: Suppose `U : B ⥤ C` has a left adjoint `F` such that each counit `ε_X : FUX ⟶ X` is a regular epimorphism. Then if a category `A` has coequalizers of reflexive @@ -168,18 +173,18 @@ pairs, then a functor `R : A ⥤ B` has a left adjoint if the composite `R ⋙ U Note the converse is true (with weaker assumptions), by `Adjunction.comp`. See https://ncatlab.org/nlab/show/adjoint+triangle+theorem -/ -lemma adjointTriangleLift {U : B ⥤ C} {F : C ⥤ B} (R : A ⥤ B) (adj₁ : F ⊣ U) +lemma isRightAdjoint_triangle_lift {U : B ⥤ C} {F : C ⥤ B} (R : A ⥤ B) (adj₁ : F ⊣ U) [∀ X : B, RegularEpi (adj₁.counit.app X)] [HasReflexiveCoequalizers A] [(R ⋙ U).IsRightAdjoint ] : R.IsRightAdjoint where exists_leftAdjoint := - ⟨LiftAdjoint.constructLeftAdjoint R _ adj₁ (Adjunction.ofIsRightAdjoint _), + ⟨LiftLeftAdjoint.constructLeftAdjoint R _ adj₁ (Adjunction.ofIsRightAdjoint _), ⟨Adjunction.adjunctionOfEquivLeft _ _⟩⟩ /-- If `R ⋙ U` has a left adjoint, the domain of `R` has reflexive coequalizers and `U` is a monadic functor, then `R` has a left adjoint. -This is a special case of `adjointTriangleLift` which is often more useful in practice. +This is a special case of `isRightAdjoint_triangle_lift` which is often more useful in practice. -/ -lemma monadicAdjointTriangleLift (U : B ⥤ C) [MonadicRightAdjoint U] {R : A ⥤ B} +lemma isRightAdjoint_triangle_lift_monadic (U : B ⥤ C) [MonadicRightAdjoint U] {R : A ⥤ B} [HasReflexiveCoequalizers A] [(R ⋙ U).IsRightAdjoint] : R.IsRightAdjoint := by let R' : A ⥤ _ := R ⋙ Monad.comparison (monadicAdjunction U) rsuffices : R'.IsRightAdjoint @@ -195,18 +200,20 @@ lemma monadicAdjointTriangleLift (U : B ⥤ C) [MonadicRightAdjoint U] {R : A intro X simp only [Monad.adj_counit] exact ⟨_, _, _, _, Monad.beckAlgebraCoequalizer X⟩ - exact adjointTriangleLift R' (Monad.adj _) + exact isRightAdjoint_triangle_lift R' (Monad.adj _) variable {D : Type u₄} variable [Category.{v₄} D] /-- Suppose we have a commutative square of functors +``` Q A → B U ↓ ↓ V C → D R +``` where `U` has a left adjoint, `A` has reflexive coequalizers and `V` has a left adjoint such that each component of the counit is a regular epi. @@ -214,30 +221,32 @@ Then `Q` has a left adjoint if `R` has a left adjoint. See https://ncatlab.org/nlab/show/adjoint+lifting+theorem -/ -lemma adjointSquareLift (Q : A ⥤ B) (V : B ⥤ D) (U : A ⥤ C) (R : C ⥤ D) +lemma isRightAdjoint_square_lift (Q : A ⥤ B) (V : B ⥤ D) (U : A ⥤ C) (R : C ⥤ D) (comm : U ⋙ R ≅ Q ⋙ V) [U.IsRightAdjoint] [V.IsRightAdjoint] [R.IsRightAdjoint] [∀ X, RegularEpi ((Adjunction.ofIsRightAdjoint V).counit.app X)] [HasReflexiveCoequalizers A] : Q.IsRightAdjoint := have := ((Adjunction.ofIsRightAdjoint (U ⋙ R)).ofNatIsoRight comm).isRightAdjoint - adjointTriangleLift Q (Adjunction.ofIsRightAdjoint V) + isRightAdjoint_triangle_lift Q (Adjunction.ofIsRightAdjoint V) /-- Suppose we have a commutative square of functors +``` Q A → B U ↓ ↓ V C → D R +``` where `U` has a left adjoint, `A` has reflexive coequalizers and `V` is monadic. Then `Q` has a left adjoint if `R` has a left adjoint. See https://ncatlab.org/nlab/show/adjoint+lifting+theorem -/ -lemma monadicAdjointSquareLift (Q : A ⥤ B) (V : B ⥤ D) (U : A ⥤ C) (R : C ⥤ D) +lemma isRightAdjoint_square_lift_monadic (Q : A ⥤ B) (V : B ⥤ D) (U : A ⥤ C) (R : C ⥤ D) (comm : U ⋙ R ≅ Q ⋙ V) [U.IsRightAdjoint] [MonadicRightAdjoint V] [R.IsRightAdjoint] [HasReflexiveCoequalizers A] : Q.IsRightAdjoint := have := ((Adjunction.ofIsRightAdjoint (U ⋙ R)).ofNatIsoRight comm).isRightAdjoint - monadicAdjointTriangleLift V + isRightAdjoint_triangle_lift_monadic V end CategoryTheory diff --git a/Mathlib/CategoryTheory/Adjunction/Lifting/Right.lean b/Mathlib/CategoryTheory/Adjunction/Lifting/Right.lean new file mode 100644 index 0000000000000..3d3893abeac50 --- /dev/null +++ b/Mathlib/CategoryTheory/Adjunction/Lifting/Right.lean @@ -0,0 +1,245 @@ +/- +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.Monad.Adjunction +import Mathlib.CategoryTheory.Monad.Equalizer + +/-! +# Adjoint lifting + +This file gives two constructions for building right adjoints: the adjoint triangle theorem and the +adjoint lifting theorem. + +The adjoint triangle theorem concerns a functor `F : B ⥤ A` with a right adjoint `U` such +that `η_X : X ⟶ UFX` is a regular mono. Then for any category `C` with equalizers of coreflexive +pairs, a functor `L : C ⥤ B` has a right adjoint if (and only if) the composite `L ⋙ F` does. +Note that the condition on `F` regarding `η_X` is automatically satisfied in the case when `F` is +a comonadic functor, giving the corollary: `isLeftAdjoint_triangle_lift_comonadic`, i.e. if `F` is +comonadic, `C` has coreflexive equalizers then `L : C ⥤ B` has a right adjoint provided `L ⋙ F` +does. + +The adjoint lifting theorem says that given a commutative square of functors (up to isomorphism): + +``` + Q + A → B + U ↓ ↓ V + C → D + L +``` + +where `V` is comonadic, `U` has a right adjoint, and `A` has coreflexive equalizers, then if `L` has +a right adjoint then `Q` has a right adjoint. + +## Implementation + +It is more convenient to prove this theorem by assuming we are given the explicit adjunction rather +than just a functor known to be a right adjoint. In docstrings, we write `(η, ε)` for the unit +and counit of the adjunction `adj₁ : F ⊣ U` and `(ι, δ)` for the unit and counit of the adjunction +`adj₂ : L ⋙ F ⊣ U'`. + +This file has been adapted from `Mathlib.CategoryTheory.Adjunction.Lifting.Left`. +Please try to keep them in sync. + +## TODO + +- Dualise to lift left adjoints through comonads (by reversing 2-cells). +- Investigate whether it is possible to give a more explicit description of the lifted adjoint, + especially in the case when the isomorphism `comm` is `Iso.refl _` + +## References +* https://ncatlab.org/nlab/show/adjoint+triangle+theorem +* https://ncatlab.org/nlab/show/adjoint+lifting+theorem +* Adjoint Lifting Theorems for Categories of Algebras (PT Johnstone, 1975) +* A unified approach to the lifting of adjoints (AJ Power, 1988) +-/ + + +namespace CategoryTheory + +open Category Limits + +universe v₁ v₂ v₃ v₄ u₁ u₂ u₃ u₄ + +variable {A : Type u₁} {B : Type u₂} {C : Type u₃} +variable [Category.{v₁} A] [Category.{v₂} B] [Category.{v₃} C] + +-- Hide implementation details in this namespace +namespace LiftRightAdjoint + +variable {U : A ⥤ B} {F : B ⥤ A} (L : C ⥤ B) (U' : A ⥤ C) +variable (adj₁ : F ⊣ U) (adj₂ : L ⋙ F ⊣ U') + +/-- To show that `η_X` is an equalizer for `(UFη_X, η_UFX)`, it suffices to assume it's always an +equalizer of something (i.e. a regular mono). +-/ +def unitEqualises [∀ X : B, RegularMono (adj₁.unit.app X)] (X : B) : + IsLimit (Fork.ofι (adj₁.unit.app X) (adj₁.unit_naturality _)) := + Fork.IsLimit.mk' _ fun s => by + refine ⟨(RegularMono.lift' (adj₁.unit.app X) s.ι ?_).1, ?_, ?_⟩ + · rw [← cancel_mono (adj₁.unit.app (RegularMono.Z (adj₁.unit.app X)))] + rw [assoc, ← adj₁.unit_naturality RegularMono.left] + dsimp only [Functor.comp_obj] + erw [← assoc, ← s.condition, assoc, ← U.map_comp, ← F.map_comp, RegularMono.w, F.map_comp, + U.map_comp, s.condition_assoc, assoc, ← adj₁.unit_naturality RegularMono.right] + rfl + · apply (RegularMono.lift' (adj₁.unit.app X) s.ι _).2 + · intro m hm + rw [← cancel_mono (adj₁.unit.app X)] + apply hm.trans (RegularMono.lift' (adj₁.unit.app X) s.ι _).2.symm + +/-- (Implementation) +To construct the right adjoint, we use the equalizer of `U' F η_X` with the composite + +`U' F X ⟶ U' F L U' F X ⟶ U' F U F L U' F X ⟶ U' F U F X` + +where the first morphism is `ι_U'FX`, the second is `U' F η_LU'FX` and the third is `U' F U δ_FX`. +We will show that this equalizer exists and that it forms the object map for a right adjoint to `L`. +-/ +def otherMap (X : B) : U'.obj (F.obj X) ⟶ U'.obj (F.obj (U.obj (F.obj X))) := + adj₂.unit.app _ ≫ U'.map (F.map (adj₁.unit.app _ ≫ (U.map (adj₂.counit.app _)))) + +/-- `(U'Fη_X, otherMap X)` is a coreflexive pair: in particular if `C` has coreflexive equalizers +then this pair has an equalizer. +-/ +instance (X : B) : + IsCoreflexivePair (U'.map (F.map (adj₁.unit.app X))) (otherMap _ _ adj₁ adj₂ X) := + IsCoreflexivePair.mk' (U'.map (adj₁.counit.app (F.obj X))) + (by simp [← Functor.map_comp]) + (by simp only [otherMap, assoc, ← Functor.map_comp]; simp) + +variable [HasCoreflexiveEqualizers C] + +/-- Construct the object part of the desired right adjoint as the equalizer of `U'Fη_Y` with +`otherMap`. +-/ +noncomputable def constructRightAdjointObj (Y : B) : C := + equalizer (U'.map (F.map (adj₁.unit.app Y))) (otherMap _ _ adj₁ adj₂ Y) + +/-- The homset equivalence which helps show that `L` is a left adjoint. -/ +@[simps!] +noncomputable def constructRightAdjointEquiv [∀ X : B, RegularMono (adj₁.unit.app X)] (Y : C) + (X : B) : (Y ⟶ constructRightAdjointObj _ _ adj₁ adj₂ X) ≃ (L.obj Y ⟶ X) := + calc + (Y ⟶ constructRightAdjointObj _ _ adj₁ adj₂ X) ≃ + { f : Y ⟶ U'.obj (F.obj X) // + f ≫ U'.map (F.map (adj₁.unit.app X)) = f ≫ (otherMap _ _ adj₁ adj₂ X) } := + Fork.IsLimit.homIso (limit.isLimit _) _ + _ ≃ { g : F.obj (L.obj Y) ⟶ F.obj X // F.map (adj₁.unit.app _≫ U.map g) = + g ≫ F.map (adj₁.unit.app _) } := by + apply (adj₂.homEquiv _ _).symm.subtypeEquiv _ + intro f + rw [← (adj₂.homEquiv _ _).injective.eq_iff, eq_comm, otherMap, + ← adj₂.homEquiv_naturality_right_symm, adj₂.homEquiv_unit, ← adj₂.unit_naturality_assoc, + adj₂.homEquiv_counit] + simp + _ ≃ { z : L.obj Y ⟶ U.obj (F.obj X) // + z ≫ U.map (F.map (adj₁.unit.app X)) = z ≫ adj₁.unit.app (U.obj (F.obj X)) } := by + apply (adj₁.homEquiv _ _).subtypeEquiv + intro g + rw [← (adj₁.homEquiv _ _).injective.eq_iff, adj₁.homEquiv_unit, + adj₁.homEquiv_unit, adj₁.homEquiv_unit, eq_comm] + simp + _ ≃ (L.obj Y ⟶ X) := (Fork.IsLimit.homIso (unitEqualises adj₁ X) _).symm + +/-- Construct the right adjoint to `L`, with object map `constructRightAdjointObj`. -/ +noncomputable def constructRightAdjoint [∀ X : B, RegularMono (adj₁.unit.app X)] : B ⥤ C := by + refine Adjunction.rightAdjointOfEquiv + (fun X Y => (constructRightAdjointEquiv L _ adj₁ adj₂ X Y).symm) ?_ + intro X Y Y' g h + rw [constructRightAdjointEquiv_symm_apply, constructRightAdjointEquiv_symm_apply, + Equiv.symm_apply_eq, Subtype.ext_iff] + dsimp + erw [Fork.IsLimit.homIso_natural, Fork.IsLimit.homIso_natural] + simp only [Fork.ofι_pt, Functor.map_comp, assoc, limit.cone_x] + erw [adj₂.homEquiv_naturality_left, Equiv.rightInverse_symm] + simp + +end LiftRightAdjoint + +/-- The adjoint triangle theorem: Suppose `U : A ⥤ B` has a left adjoint `F` such that each unit +`η_X : X ⟶ UFX` is a regular monomorphism. Then if a category `C` has equalizers of coreflexive +pairs, then a functor `L : C ⥤ B` has a right adjoint if the composite `L ⋙ F` does. + +Note the converse is true (with weaker assumptions), by `Adjunction.comp`. +See https://ncatlab.org/nlab/show/adjoint+triangle+theorem +-/ +lemma isLeftAdjoint_triangle_lift {U : A ⥤ B} {F : B ⥤ A} (L : C ⥤ B) (adj₁ : F ⊣ U) + [∀ X, RegularMono (adj₁.unit.app X)] [HasCoreflexiveEqualizers C] + [(L ⋙ F).IsLeftAdjoint ] : L.IsLeftAdjoint where + exists_rightAdjoint := + ⟨LiftRightAdjoint.constructRightAdjoint L _ adj₁ (Adjunction.ofIsLeftAdjoint _), + ⟨Adjunction.adjunctionOfEquivRight _ _⟩⟩ + +/-- If `L ⋙ F` has a right adjoint, the domain of `L` has coreflexive equalizers and `F` is a +comonadic functor, then `L` has a right adjoint. +This is a special case of `isLeftAdjoint_triangle_lift` which is often more useful in practice. +-/ +lemma isLeftAdjoint_triangle_lift_comonadic (F : B ⥤ A) [ComonadicLeftAdjoint F] {L : C ⥤ B} + [HasCoreflexiveEqualizers C] [(L ⋙ F).IsLeftAdjoint] : L.IsLeftAdjoint := by + let L' : _ ⥤ _ := L ⋙ Comonad.comparison (comonadicAdjunction F) + rsuffices : L'.IsLeftAdjoint + · let this : (L' ⋙ (Comonad.comparison (comonadicAdjunction F)).inv).IsLeftAdjoint := by + infer_instance + refine ((Adjunction.ofIsLeftAdjoint + (L' ⋙ (Comonad.comparison (comonadicAdjunction F)).inv)).ofNatIsoLeft ?_).isLeftAdjoint + exact isoWhiskerLeft L (Comonad.comparison _).asEquivalence.unitIso.symm ≪≫ L.leftUnitor + let this : (L' ⋙ Comonad.forget (comonadicAdjunction F).toComonad).IsLeftAdjoint := by + refine ((Adjunction.ofIsLeftAdjoint (L ⋙ F)).ofNatIsoLeft ?_).isLeftAdjoint + exact isoWhiskerLeft L (Comonad.comparisonForget (comonadicAdjunction F)).symm + let this : ∀ X, RegularMono ((Comonad.adj (comonadicAdjunction F).toComonad).unit.app X) := by + intro X + simp only [Comonad.adj_unit] + exact ⟨_, _, _, _, Comonad.beckCoalgebraEqualizer X⟩ + exact isLeftAdjoint_triangle_lift L' (Comonad.adj _) + +variable {D : Type u₄} +variable [Category.{v₄} D] + +/-- Suppose we have a commutative square of functors + +``` + Q + A → B + U ↓ ↓ V + C → D + R +``` + +where `U` has a right adjoint, `A` has coreflexive equalizers and `V` has a right adjoint such that +each component of the counit is a regular mono. +Then `Q` has a right adjoint if `L` has a right adjoint. + +See https://ncatlab.org/nlab/show/adjoint+lifting+theorem +-/ +lemma isLeftAdjoint_square_lift (Q : A ⥤ B) (V : B ⥤ D) (U : A ⥤ C) (L : C ⥤ D) + (comm : U ⋙ L ≅ Q ⋙ V) [U.IsLeftAdjoint] [V.IsLeftAdjoint] [L.IsLeftAdjoint] + [∀ X, RegularMono ((Adjunction.ofIsLeftAdjoint V).unit.app X)] [HasCoreflexiveEqualizers A] : + Q.IsLeftAdjoint := + have := ((Adjunction.ofIsLeftAdjoint (U ⋙ L)).ofNatIsoLeft comm).isLeftAdjoint + isLeftAdjoint_triangle_lift Q (Adjunction.ofIsLeftAdjoint V) + +/-- Suppose we have a commutative square of functors + +``` + Q + A → B + U ↓ ↓ V + C → D + R +``` + +where `U` has a right adjoint, `A` has reflexive equalizers and `V` is comonadic. +Then `Q` has a right adjoint if `L` has a right adjoint. + +See https://ncatlab.org/nlab/show/adjoint+lifting+theorem +-/ +lemma isLeftAdjoint_square_lift_comonadic (Q : A ⥤ B) (V : B ⥤ D) (U : A ⥤ C) (L : C ⥤ D) + (comm : U ⋙ L ≅ Q ⋙ V) [U.IsLeftAdjoint] [ComonadicLeftAdjoint V] [L.IsLeftAdjoint] + [HasCoreflexiveEqualizers A] : Q.IsLeftAdjoint := + have := ((Adjunction.ofIsLeftAdjoint (U ⋙ L)).ofNatIsoLeft comm).isLeftAdjoint + isLeftAdjoint_triangle_lift_comonadic V + +end CategoryTheory diff --git a/Mathlib/CategoryTheory/Adjunction/Mates.lean b/Mathlib/CategoryTheory/Adjunction/Mates.lean index cacbc727a8ab8..2e15c2012bd9e 100644 --- a/Mathlib/CategoryTheory/Adjunction/Mates.lean +++ b/Mathlib/CategoryTheory/Adjunction/Mates.lean @@ -45,8 +45,8 @@ open Category Functor Adjunction NatTrans section mateEquiv -variable {C : Type u₁} {D : Type u₂}{E : Type u₃} {F : Type u₄} -variable [Category.{v₁} C] [Category.{v₂} D][Category.{v₃} E] [Category.{v₄} F] +variable {C : Type u₁} {D : Type u₂} {E : Type u₃} {F : Type u₄} +variable [Category.{v₁} C] [Category.{v₂} D] [Category.{v₃} E] [Category.{v₄} F] variable {G : C ⥤ E} {H : D ⥤ F} {L₁ : C ⥤ D} {R₁ : D ⥤ C} {L₂ : E ⥤ F} {R₂ : F ⥤ E} variable (adj₁ : L₁ ⊣ R₁) (adj₂ : L₂ ⊣ R₂) @@ -119,9 +119,7 @@ theorem unit_mateEquiv (α : G ⋙ L₂ ⟶ L₁ ⋙ H) (c : C) : rw [← R₂.map_comp, ← Functor.comp_map G L₂, α.naturality] rw [R₂.map_comp] slice_lhs 3 4 => - { - rw [← R₂.map_comp, Functor.comp_map L₁ H, ← H.map_comp, left_triangle_components] - } + rw [← R₂.map_comp, Functor.comp_map L₁ H, ← H.map_comp, left_triangle_components] simp only [comp_obj, map_id, comp_id] /-- A component of a transposed version of the inverse mates correspondence. -/ @@ -136,10 +134,10 @@ end mateEquiv section mateEquivVComp variable {A : Type u₁} {B : Type u₂} {C : Type u₃} {D : Type u₄} {E : Type u₅} {F : Type u₆} -variable [Category.{v₁} A] [Category.{v₂} B][Category.{v₃} C] -variable [Category.{v₄} D] [Category.{v₅} E][Category.{v₆} F] -variable {G₁ : A ⥤ C}{G₂ : C ⥤ E}{H₁ : B ⥤ D}{H₂ : D ⥤ F} -variable {L₁ : A ⥤ B}{R₁ : B ⥤ A} {L₂ : C ⥤ D}{R₂ : D ⥤ C}{L₃ : E ⥤ F}{R₃ : F ⥤ E} +variable [Category.{v₁} A] [Category.{v₂} B] [Category.{v₃} C] +variable [Category.{v₄} D] [Category.{v₅} E] [Category.{v₆} F] +variable {G₁ : A ⥤ C} {G₂ : C ⥤ E} {H₁ : B ⥤ D} {H₂ : D ⥤ F} +variable {L₁ : A ⥤ B} {R₁ : B ⥤ A} {L₂ : C ⥤ D} {R₂ : D ⥤ C} {L₃ : E ⥤ F} {R₃ : F ⥤ E} variable (adj₁ : L₁ ⊣ R₁) (adj₂ : L₂ ⊣ R₂) (adj₃ : L₃ ⊣ R₃) /-- Squares between left adjoints can be composed "vertically" by pasting. -/ @@ -162,32 +160,21 @@ theorem mateEquiv_vcomp simp only [comp_obj, Equiv.coe_fn_mk, whiskerLeft_comp, whiskerLeft_twice, whiskerRight_comp, assoc, comp_app, whiskerLeft_app, whiskerRight_app, id_obj, Functor.comp_map, whiskerRight_twice] - slice_rhs 1 4 => - { - rw [← assoc, ← assoc, ← unit_naturality (adj₃)] - } + slice_rhs 1 4 => rw [← assoc, ← assoc, ← unit_naturality (adj₃)] rw [L₃.map_comp, R₃.map_comp] slice_rhs 2 4 => - { - rw [← R₃.map_comp, ← R₃.map_comp, ← assoc, ← L₃.map_comp, ← G₂.map_comp, ← G₂.map_comp] - rw [← Functor.comp_map G₂ L₃, β.naturality] - } + rw [← R₃.map_comp, ← R₃.map_comp, ← assoc, ← L₃.map_comp, ← G₂.map_comp, ← G₂.map_comp] + rw [← Functor.comp_map G₂ L₃, β.naturality] rw [(L₂ ⋙ H₂).map_comp, R₃.map_comp, R₃.map_comp] slice_rhs 4 5 => - { - rw [← R₃.map_comp, Functor.comp_map L₂ _, ← Functor.comp_map _ L₂, ← H₂.map_comp] - rw [adj₂.counit.naturality] - } + rw [← R₃.map_comp, Functor.comp_map L₂ _, ← Functor.comp_map _ L₂, ← H₂.map_comp] + rw [adj₂.counit.naturality] simp only [comp_obj, Functor.comp_map, map_comp, id_obj, Functor.id_map, assoc] slice_rhs 4 5 => - { - rw [← R₃.map_comp, ← H₂.map_comp, ← Functor.comp_map _ L₂, adj₂.counit.naturality] - } + rw [← R₃.map_comp, ← H₂.map_comp, ← Functor.comp_map _ L₂, adj₂.counit.naturality] simp only [comp_obj, id_obj, Functor.id_map, map_comp, assoc] slice_rhs 3 4 => - { - rw [← R₃.map_comp, ← H₂.map_comp, left_triangle_components] - } + rw [← R₃.map_comp, ← H₂.map_comp, left_triangle_components] simp only [map_id, id_comp] end mateEquivVComp @@ -195,11 +182,11 @@ end mateEquivVComp section mateEquivHComp variable {A : Type u₁} {B : Type u₂} {C : Type u₃} {D : Type u₄} {E : Type u₅} {F : Type u₆} -variable [Category.{v₁} A] [Category.{v₂} B][Category.{v₃} C] -variable [Category.{v₄} D] [Category.{v₅} E][Category.{v₆} F] -variable {G : A ⥤ D}{H : B ⥤ E}{K : C ⥤ F} -variable {L₁ : A ⥤ B}{R₁ : B ⥤ A} {L₂ : D ⥤ E}{R₂ : E ⥤ D} -variable {L₃ : B ⥤ C}{R₃ : C ⥤ B} {L₄ : E ⥤ F}{R₄ : F ⥤ E} +variable [Category.{v₁} A] [Category.{v₂} B] [Category.{v₃} C] +variable [Category.{v₄} D] [Category.{v₅} E] [Category.{v₆} F] +variable {G : A ⥤ D} {H : B ⥤ E} {K : C ⥤ F} +variable {L₁ : A ⥤ B} {R₁ : B ⥤ A} {L₂ : D ⥤ E} {R₂ : E ⥤ D} +variable {L₃ : B ⥤ C} {R₃ : C ⥤ B} {L₄ : E ⥤ F} {R₄ : F ⥤ E} variable (adj₁ : L₁ ⊣ R₁) (adj₂ : L₂ ⊣ R₂) (adj₃ : L₃ ⊣ R₃) (adj₄ : L₄ ⊣ R₄) /-- Squares between left adjoints can be composed "horizontally" by pasting. -/ @@ -223,14 +210,10 @@ theorem mateEquiv_hcomp Equiv.coe_fn_mk, comp_app, whiskerLeft_app, whiskerRight_app, id_obj, associator_inv_app, Functor.comp_map, associator_hom_app, map_id, id_comp, whiskerRight_twice] slice_rhs 2 4 => - { - rw [← R₂.map_comp, ← R₂.map_comp, ← assoc, ← unit_naturality (adj₄)] - } + rw [← R₂.map_comp, ← R₂.map_comp, ← assoc, ← unit_naturality (adj₄)] rw [R₂.map_comp, L₄.map_comp, R₄.map_comp, R₂.map_comp] slice_rhs 4 5 => - { - rw [← R₂.map_comp, ← R₄.map_comp, ← Functor.comp_map _ L₄ , β.naturality] - } + rw [← R₂.map_comp, ← R₄.map_comp, ← Functor.comp_map _ L₄ , β.naturality] simp only [comp_obj, Functor.comp_map, map_comp, assoc] end mateEquivHComp @@ -240,9 +223,9 @@ section mateEquivSquareComp variable {A : Type u₁} {B : Type u₂} {C : Type u₃} variable {D : Type u₄} {E : Type u₅} {F : Type u₆} variable {X : Type u₇} {Y : Type u₈} {Z : Type u₉} -variable [Category.{v₁} A] [Category.{v₂} B][Category.{v₃} C] -variable [Category.{v₄} D] [Category.{v₅} E][Category.{v₆} F] -variable [Category.{v₇} X] [Category.{v₈} Y][Category.{v₉} Z] +variable [Category.{v₁} A] [Category.{v₂} B] [Category.{v₃} C] +variable [Category.{v₄} D] [Category.{v₅} E] [Category.{v₆} F] +variable [Category.{v₇} X] [Category.{v₈} Y] [Category.{v₉} Z] variable {G₁ : A ⥤ D} {H₁ : B ⥤ E} {K₁ : C ⥤ F} {G₂ : D ⥤ X} {H₂ : E ⥤ Y} {K₂ : F ⥤ Z} variable {L₁ : A ⥤ B} {R₁ : B ⥤ A} {L₂ : B ⥤ C} {R₂ : C ⥤ B} {L₃ : D ⥤ E} {R₃ : E ⥤ D} variable {L₄ : E ⥤ F} {R₄ : F ⥤ E} {L₅ : X ⥤ Y} {R₅ : Y ⥤ X} {L₆ : Y ⥤ Z} {R₆ : Z ⥤ Y} @@ -275,9 +258,7 @@ theorem leftAdjointSquare.comp_hvcomp ext a simp only [comp_obj, comp_app, map_comp, assoc] slice_rhs 2 3 => - { - rw [← Functor.comp_map _ L₆, δ.naturality] - } + rw [← Functor.comp_map _ L₆, δ.naturality] simp only [comp_obj, Functor.comp_map, assoc] /-- Squares of squares between right adjoints can be composed by iterating vertical and horizontal @@ -306,9 +287,7 @@ theorem rightAdjointSquare.comp_hvcomp ext c simp only [comp_obj, comp_app, map_comp, assoc] slice_rhs 2 3 => - { - rw [← Functor.comp_map _ R₅, ← γ.naturality] - } + rw [← Functor.comp_map _ R₅, ← γ.naturality] simp only [comp_obj, Functor.comp_map, assoc] /-- The mates equivalence commutes with composition of squares of squares. These results form the @@ -445,7 +424,7 @@ theorem conjugateEquiv_comm {α : L₂ ⟶ L₁} {β : L₁ ⟶ L₂} (βα : β conjugateEquiv adj₁ adj₂ α ≫ conjugateEquiv adj₂ adj₁ β = 𝟙 _ := by rw [conjugateEquiv_comp, βα, conjugateEquiv_id] -theorem conjugateEquiv_symm_comm {α : R₁ ⟶ R₂}{β : R₂ ⟶ R₁} (αβ : α ≫ β = 𝟙 _) : +theorem conjugateEquiv_symm_comm {α : R₁ ⟶ R₂} {β : R₂ ⟶ R₁} (αβ : α ≫ β = 𝟙 _) : (conjugateEquiv adj₂ adj₁).symm β ≫ (conjugateEquiv adj₁ adj₂).symm α = 𝟙 _ := by rw [conjugateEquiv_symm_comp, αβ, conjugateEquiv_symm_id] @@ -503,11 +482,11 @@ noncomputable def conjugateIsoEquiv : (L₂ ≅ L₁) ≃ (R₁ ≅ R₂) where end ConjugateIsomorphism section IteratedmateEquiv -variable {A : Type u₁} {B : Type u₂}{C : Type u₃} {D : Type u₄} -variable [Category.{v₁} A] [Category.{v₂} B][Category.{v₃} C] [Category.{v₄} D] -variable {F₁ : A ⥤ C}{U₁ : C ⥤ A} {F₂ : B ⥤ D} {U₂ : D ⥤ B} +variable {A : Type u₁} {B : Type u₂} {C : Type u₃} {D : Type u₄} +variable [Category.{v₁} A] [Category.{v₂} B] [Category.{v₃} C] [Category.{v₄} D] +variable {F₁ : A ⥤ C} {U₁ : C ⥤ A} {F₂ : B ⥤ D} {U₂ : D ⥤ B} variable {L₁ : A ⥤ B} {R₁ : B ⥤ A} {L₂ : C ⥤ D} {R₂ : D ⥤ C} -variable (adj₁ : L₁ ⊣ R₁) (adj₂ : L₂ ⊣ R₂) (adj₃ : F₁ ⊣ U₁)(adj₄ : F₂ ⊣ U₂) +variable (adj₁ : L₁ ⊣ R₁) (adj₂ : L₂ ⊣ R₂) (adj₃ : F₁ ⊣ U₁) (adj₄ : F₂ ⊣ U₂) /-- When all four functors in a sequare are left adjoints, the mates operation can be iterated: @@ -542,11 +521,11 @@ end IteratedmateEquiv section mateEquivconjugateEquivVComp -variable {A : Type u₁} {B : Type u₂} {C : Type u₃}{D : Type u₄} -variable [Category.{v₁} A] [Category.{v₂} B][Category.{v₃} C] +variable {A : Type u₁} {B : Type u₂} {C : Type u₃} {D : Type u₄} +variable [Category.{v₁} A] [Category.{v₂} B] [Category.{v₃} C] variable [Category.{v₄} D] variable {G : A ⥤ C} {H : B ⥤ D} -variable {L₁ : A ⥤ B} {R₁ : B ⥤ A} {L₂ : C ⥤ D} {R₂ : D ⥤ C} {L₃ : C ⥤ D}{R₃ : D ⥤ C} +variable {L₁ : A ⥤ B} {R₁ : B ⥤ A} {L₂ : C ⥤ D} {R₂ : D ⥤ C} {L₃ : C ⥤ D} {R₃ : D ⥤ C} variable (adj₁ : L₁ ⊣ R₁) (adj₂ : L₂ ⊣ R₂) (adj₃ : L₃ ⊣ R₃) /-- Composition of a squares between left adjoints with a conjugate square. -/ @@ -581,8 +560,8 @@ end mateEquivconjugateEquivVComp section conjugateEquivmateEquivVComp -variable {A : Type u₁} {B : Type u₂} {C : Type u₃}{D : Type u₄} -variable [Category.{v₁} A] [Category.{v₂} B][Category.{v₃} C] +variable {A : Type u₁} {B : Type u₂} {C : Type u₃} {D : Type u₄} +variable [Category.{v₁} A] [Category.{v₂} B] [Category.{v₃} C] variable [Category.{v₄} D] variable {G : A ⥤ C} {H : B ⥤ D} variable {L₁ : A ⥤ B} {R₁ : B ⥤ A} {L₂ : A ⥤ B} {R₂ : B ⥤ A} {L₃ : C ⥤ D} {R₃ : D ⥤ C} diff --git a/Mathlib/CategoryTheory/Adjunction/Opposites.lean b/Mathlib/CategoryTheory/Adjunction/Opposites.lean index 9cbae02e88e30..b757cf23557da 100644 --- a/Mathlib/CategoryTheory/Adjunction/Opposites.lean +++ b/Mathlib/CategoryTheory/Adjunction/Opposites.lean @@ -28,10 +28,6 @@ variable {C : Type u₁} [Category.{v₁} C] {D : Type u₂} [Category.{v₂} D] namespace CategoryTheory.Adjunction /-- If `G.op` is adjoint to `F.op` then `F` is adjoint to `G`. -/ --- Porting note: in mathlib3 we generated all the default `simps` lemmas. --- However the `simpNF` linter correctly flags some of these as unsuitable simp lemmas. --- `unit_app` and `counit_app` appear to suffice (tested in mathlib3). --- See also the porting note on opAdjointOpOfAdjoint @[simps! unit_app counit_app] def adjointOfOpAdjointOp (F : C ⥤ D) (G : D ⥤ C) (h : G.op ⊣ F.op) : F ⊣ G := Adjunction.mkOfHomEquiv { @@ -69,30 +65,20 @@ def unopAdjointUnopOfAdjoint (F : Cᵒᵖ ⥤ Dᵒᵖ) (G : Dᵒᵖ ⥤ Cᵒᵖ) /-- If `G` is adjoint to `F` then `F.op` is adjoint to `G.op`. -/ @[simps! unit_app counit_app] --- Porting note: in mathlib3 we generated all the default `simps` lemmas. --- However the `simpNF` linter correctly flags some of these as unsuitable simp lemmas. --- `unit_app` and `counit_app` appear to suffice (tested in mathlib3). --- See also the porting note on adjointOfOpAdjointOp def opAdjointOpOfAdjoint (F : C ⥤ D) (G : D ⥤ C) (h : G ⊣ F) : F.op ⊣ G.op := Adjunction.mkOfHomEquiv { homEquiv := fun X Y => (opEquiv _ Y).trans ((h.homEquiv _ _).symm.trans (opEquiv X (Opposite.op _)).symm) homEquiv_naturality_left_symm := by - -- Porting note: This proof was handled by `obviously` in mathlib3. - intros X' X Y f g - dsimp [opEquiv] - -- Porting note: Why is `erw` needed here? - -- https://github.com/leanprover-community/mathlib4/issues/5164 - erw [homEquiv_unit, homEquiv_unit] - simp + -- Porting note: This proof was handled by `obviously` in mathlib3. The only obstruction to + -- automation fully kicking in here is that the `@[simps]` lemmas of `opEquiv` aren't firing. + intros + simp [opEquiv] homEquiv_naturality_right := by - -- Porting note: This proof was handled by `obviously` in mathlib3. - intros X' X Y f g - dsimp [opEquiv] - -- Porting note: Why is `erw` needed here? - -- https://github.com/leanprover-community/mathlib4/issues/5164 - erw [homEquiv_counit, homEquiv_counit] - simp } + -- Porting note: This proof was handled by `obviously` in mathlib3. The only obstruction to + -- automation fully kicking in here is that the `@[simps]` lemmas of `opEquiv` aren't firing. + intros + simp [opEquiv] } /-- If `G` is adjoint to `F.unop` then `F` is adjoint to `G.op`. -/ def adjointOpOfAdjointUnop (F : Cᵒᵖ ⥤ Dᵒᵖ) (G : D ⥤ C) (h : G ⊣ F.unop) : F ⊣ G.op := diff --git a/Mathlib/CategoryTheory/Adjunction/Triple.lean b/Mathlib/CategoryTheory/Adjunction/Triple.lean new file mode 100644 index 0000000000000..d8b28fd060834 --- /dev/null +++ b/Mathlib/CategoryTheory/Adjunction/Triple.lean @@ -0,0 +1,55 @@ +/- +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.Adjunction.Unique +import Mathlib.CategoryTheory.Monad.Adjunction +/-! + +# Adjoint triples + +This file concerns adjoint triples `F ⊣ G ⊣ H` of functors `F H : C ⥤ D`, `G : D ⥤ C`. + +Currently, the only result is that `F` is fully faithful if and only if `H` is fully faithful. +-/ + +namespace CategoryTheory.Adjunction + +variable {C D : Type*} [Category C] [Category D] +variable {F H : C ⥤ D} {G : D ⥤ C} +variable (adj₁ : F ⊣ G) (adj₂ : G ⊣ H) + +lemma isIso_unit_iff_isIso_counit : IsIso adj₁.unit ↔ IsIso adj₂.counit := by + let adj : F ⋙ G ⊣ H ⋙ G := adj₁.comp adj₂ + constructor + · intro h + let idAdj : 𝟭 C ⊣ H ⋙ G := adj.ofNatIsoLeft (asIso adj₁.unit).symm + exact adj₂.isIso_counit_of_iso (idAdj.rightAdjointUniq id) + · intro h + let adjId : F ⋙ G ⊣ 𝟭 C := adj.ofNatIsoRight (asIso adj₂.counit) + exact adj₁.isIso_unit_of_iso (adjId.leftAdjointUniq id) + +/-- +Given an adjoint triple `F ⊣ G ⊣ H`, the left adjoint `F` is fully faithful if and only if the +right adjoint `H` is fully faithful. +-/ +noncomputable def fullyFaithfulEquiv : F.FullyFaithful ≃ H.FullyFaithful where + toFun h := + haveI := h.full + haveI := h.faithful + haveI : IsIso adj₂.counit := by + rw [← adj₁.isIso_unit_iff_isIso_counit adj₂] + infer_instance + adj₂.fullyFaithfulROfIsIsoCounit + invFun h := + haveI := h.full + haveI := h.faithful + haveI : IsIso adj₁.unit := by + rw [adj₁.isIso_unit_iff_isIso_counit adj₂] + infer_instance + adj₁.fullyFaithfulLOfIsIsoUnit + left_inv _ := Subsingleton.elim _ _ + right_inv _ := Subsingleton.elim _ _ + +end CategoryTheory.Adjunction diff --git a/Mathlib/CategoryTheory/Adjunction/Unique.lean b/Mathlib/CategoryTheory/Adjunction/Unique.lean index e89f8f0cac695..e911b3e4dcb59 100644 --- a/Mathlib/CategoryTheory/Adjunction/Unique.lean +++ b/Mathlib/CategoryTheory/Adjunction/Unique.lean @@ -11,8 +11,8 @@ 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)`. +* `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 @@ -20,6 +20,13 @@ 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 @@ -29,7 +36,7 @@ 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 +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] @@ -92,7 +99,7 @@ lemma natTransEquiv_comp_symm {F F' F'' : C ⥤ D} {G G' G'' : D ⥤ C} simp /-- -If `F ⊣ G` and `F' ⊣ G'` are adjunctions, then giving a natural isomorphism `G ≅ G'` is the +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] diff --git a/Mathlib/CategoryTheory/Bicategory/Coherence.lean b/Mathlib/CategoryTheory/Bicategory/Coherence.lean index acb01f1bd07bb..8721c45df98f3 100644 --- a/Mathlib/CategoryTheory/Bicategory/Coherence.lean +++ b/Mathlib/CategoryTheory/Bicategory/Coherence.lean @@ -204,11 +204,11 @@ def normalizeUnitIso (a b : FreeBicategory B) : def normalizeEquiv (a b : B) : Hom a b ≌ Discrete (Path.{v + 1} a b) := Equivalence.mk ((normalize _).mapFunctor a b) (inclusionPath a b) (normalizeUnitIso a b) (Discrete.natIso fun f => eqToIso (by - induction' f with f - induction' f with _ _ _ _ ih - -- Porting note: `tidy` closes the goal in mathlib3 but `aesop` doesn't here. - · rfl - · ext1 + obtain ⟨f⟩ := f + induction f with + | nil => rfl + | cons _ _ ih => + ext1 -- Porting note: `tidy` closes the goal in mathlib3 but `aesop` doesn't here. injection ih with ih conv_rhs => rw [← ih] rfl)) diff --git a/Mathlib/CategoryTheory/Bicategory/Free.lean b/Mathlib/CategoryTheory/Bicategory/Free.lean index 2063a717cc38f..e423dd24b31be 100644 --- a/Mathlib/CategoryTheory/Bicategory/Free.lean +++ b/Mathlib/CategoryTheory/Bicategory/Free.lean @@ -334,19 +334,16 @@ def lift : Pseudofunctor (FreeBicategory B) C where -- in mathlib3 `tidy` did these inductions for us. map₂_comp := by intros a b f g h η θ - apply Quot.rec _ _ η - · intro η - apply Quot.rec _ _ θ - · intro θ; rfl - · intros; rfl - · intros; rfl + induction η using Quot.rec + · induction θ using Quot.rec <;> rfl + · rfl -- Porting note: still borked from here. The infoview doesn't update properly for me. map₂_whisker_left := by intro a b c f g h η - apply Quot.rec _ _ η - · intros; aesop_cat - · intros; rfl - map₂_whisker_right := by intro _ _ _ _ _ η h; dsimp; apply Quot.rec _ _ η <;> aesop_cat + induction η using Quot.rec + · aesop_cat + · rfl + map₂_whisker_right := by intro _ _ _ _ _ η h; dsimp; induction η using Quot.rec <;> aesop_cat end diff --git a/Mathlib/CategoryTheory/Bicategory/Functor/Lax.lean b/Mathlib/CategoryTheory/Bicategory/Functor/Lax.lean index 616625791af23..6c70477096688 100644 --- a/Mathlib/CategoryTheory/Bicategory/Functor/Lax.lean +++ b/Mathlib/CategoryTheory/Bicategory/Functor/Lax.lean @@ -58,24 +58,24 @@ structure LaxFunctor (B: Type u₁) [Bicategory.{w₁, v₁} B] (C : Type u₂) mapId (a : B) : 𝟙 (obj a) ⟶ map (𝟙 a) /-- The 2-morphism underlying the lax functoriality constraint. -/ mapComp {a b c : B} (f : a ⟶ b) (g : b ⟶ c) : map f ≫ map g ⟶ map (f ≫ g) - /-- Naturality of the lax functoriality constraight, on the left. -/ + /-- Naturality of the lax functoriality constraint, on the left. -/ mapComp_naturality_left : ∀ {a b c : B} {f f' : a ⟶ b} (η : f ⟶ f') (g : b ⟶ c), mapComp f g ≫ map₂ (η ▷ g) = map₂ η ▷ map g ≫ mapComp f' g:= by aesop_cat - /-- Naturality of the lax functoriality constraight, on the right. -/ + /-- Naturality of the lax functoriality constraint, on the right. -/ mapComp_naturality_right : ∀ {a b c : B} (f : a ⟶ b) {g g' : b ⟶ c} (η : g ⟶ g'), mapComp f g ≫ map₂ (f ◁ η) = map f ◁ map₂ η ≫ mapComp f g' := by aesop_cat - /-- Lax associativity -/ + /-- Lax associativity. -/ map₂_associator : ∀ {a b c d : B} (f : a ⟶ b) (g : b ⟶ c) (h : c ⟶ d), mapComp f g ▷ map h ≫ mapComp (f ≫ g) h ≫ map₂ (α_ f g h).hom = (α_ (map f) (map g) (map h)).hom ≫ map f ◁ mapComp g h ≫ mapComp f (g ≫ h) := by aesop_cat - /-- Lax left unity -/ + /-- Lax left unity. -/ map₂_leftUnitor : ∀ {a b : B} (f : a ⟶ b), map₂ (λ_ f).inv = (λ_ (map f)).inv ≫ mapId a ▷ map f ≫ mapComp (𝟙 a) f := by aesop_cat - /-- Lax right unity -/ + /-- Lax right unity. -/ map₂_rightUnitor : ∀ {a b : B} (f : a ⟶ b), map₂ (ρ_ f).inv = (ρ_ (map f)).inv ≫ map f ◁ mapId b ≫ mapComp f (𝟙 b) := by aesop_cat @@ -166,17 +166,16 @@ def comp {D : Type u₃} [Bicategory.{w₃, v₃} D] (F : LaxFunctor B C) (G : L See `Pseudofunctor.mkOfLax`. -/ structure PseudoCore (F : LaxFunctor B C) where + /-- The isomorphism giving rise to the lax unity constraint -/ mapIdIso (a : B) : F.map (𝟙 a) ≅ 𝟙 (F.obj a) + /-- The isomorphism giving rise to the lax functoriality constraint -/ mapCompIso {a b c : B} (f : a ⟶ b) (g : b ⟶ c) : F.map (f ≫ g) ≅ F.map f ≫ F.map g + /-- `mapIdIso` gives rise to the lax unity constraint -/ mapIdIso_inv {a : B} : (mapIdIso a).inv = F.mapId a := by aesop_cat + /-- `mapCompIso` gives rise to the lax functoriality constraint -/ mapCompIso_inv {a b c : B} (f : a ⟶ b) (g : b ⟶ c) : (mapCompIso f g).inv = F.mapComp f g := by aesop_cat -attribute [nolint docBlame] CategoryTheory.LaxFunctor.PseudoCore.mapIdIso - CategoryTheory.LaxFunctor.PseudoCore.mapCompIso - CategoryTheory.LaxFunctor.PseudoCore.mapIdIso_inv - CategoryTheory.LaxFunctor.PseudoCore.mapCompIso_inv - attribute [simp] PseudoCore.mapIdIso_inv PseudoCore.mapCompIso_inv end LaxFunctor diff --git a/Mathlib/CategoryTheory/Bicategory/Functor/Oplax.lean b/Mathlib/CategoryTheory/Bicategory/Functor/Oplax.lean index bc1c66a21dae8..9ac27f09df99a 100644 --- a/Mathlib/CategoryTheory/Bicategory/Functor/Oplax.lean +++ b/Mathlib/CategoryTheory/Bicategory/Functor/Oplax.lean @@ -36,17 +36,6 @@ section variable {B : Type u₁} [Bicategory.{w₁, v₁} B] {C : Type u₂} [Bicategory.{w₂, v₂} C] variable {D : Type u₃} [Bicategory.{w₃, v₃} D] --- Porting note: in Lean 3 the below auxiliary definition was only used once, in the definition --- of oplax functor, with a comment that it had to be used to fix a timeout. The timeout is --- not present in Lean 4, however Lean 4 is not as good at seeing through the definition, --- meaning that `simp` wasn't functioning as well as it should. I have hence removed --- the auxiliary definition. ---@[simp] ---def OplaxFunctor.Map₂AssociatorAux (obj : B → C) (map : ∀ {X Y : B}, (X ⟶ Y) → (obj X ⟶ obj Y)) --- (map₂ : ∀ {a b : B} {f g : a ⟶ b}, (f ⟶ g) → (map f ⟶ map g)) --- (map_comp : ∀ {a b c : B} (f : a ⟶ b) (g : b ⟶ c), map (f ≫ g) ⟶ map f ≫ map g) {a b c d : B} --- (f : a ⟶ b) (g : b ⟶ c) (h : c ⟶ d) : Prop := ... - /-- An oplax functor `F` between bicategories `B` and `C` consists of a function between objects `F.obj`, a function between 1-morphisms `F.map`, and a function between 2-morphisms `F.map₂`. @@ -60,28 +49,32 @@ of 2-morphisms. -/ structure OplaxFunctor (B : Type u₁) [Bicategory.{w₁, v₁} B] (C : Type u₂) [Bicategory.{w₂, v₂} C] extends PrelaxFunctor B C where + /-- The 2-morphism underlying the oplax unity constraint. -/ mapId (a : B) : map (𝟙 a) ⟶ 𝟙 (obj a) + /-- The 2-morphism underlying the oplax functoriality constraint. -/ mapComp {a b c : B} (f : a ⟶ b) (g : b ⟶ c) : map (f ≫ g) ⟶ map f ≫ map g + /-- Naturality of the oplax functoriality constraint, on the left. -/ mapComp_naturality_left : ∀ {a b c : B} {f f' : a ⟶ b} (η : f ⟶ f') (g : b ⟶ c), map₂ (η ▷ g) ≫ mapComp f' g = mapComp f g ≫ map₂ η ▷ map g := by aesop_cat + /-- Naturality of the lax functoriality constraight, on the right. -/ mapComp_naturality_right : ∀ {a b c : B} (f : a ⟶ b) {g g' : b ⟶ c} (η : g ⟶ g'), map₂ (f ◁ η) ≫ mapComp f g' = mapComp f g ≫ map f ◁ map₂ η := by aesop_cat - -- Porting note: `map₂_associator_aux` was used here in lean 3, but this was a hack - -- to avoid a timeout; we revert this hack here (because it was causing other problems - -- and was not necessary in lean 4) + /-- Oplax associativity. -/ map₂_associator : ∀ {a b c d : B} (f : a ⟶ b) (g : b ⟶ c) (h : c ⟶ d), map₂ (α_ f g h).hom ≫ mapComp f (g ≫ h) ≫ map f ◁ mapComp g h = mapComp (f ≫ g) h ≫ mapComp f g ▷ map h ≫ (α_ (map f) (map g) (map h)).hom := by aesop_cat + /-- Oplax left unity. -/ map₂_leftUnitor : ∀ {a b : B} (f : a ⟶ b), map₂ (λ_ f).hom = mapComp (𝟙 a) f ≫ mapId a ▷ map f ≫ (λ_ (map f)).hom := by aesop_cat + /-- Oplax right unity. -/ map₂_rightUnitor : ∀ {a b : B} (f : a ⟶ b), map₂ (ρ_ f).hom = mapComp f (𝟙 b) ≫ map f ◁ mapId b ≫ (ρ_ (map f)).hom := by @@ -100,14 +93,6 @@ section /-- The underlying prelax functor. -/ add_decl_doc OplaxFunctor.toPrelaxFunctor -attribute [nolint docBlame] CategoryTheory.OplaxFunctor.mapId - CategoryTheory.OplaxFunctor.mapComp - CategoryTheory.OplaxFunctor.mapComp_naturality_left - CategoryTheory.OplaxFunctor.mapComp_naturality_right - CategoryTheory.OplaxFunctor.map₂_associator - CategoryTheory.OplaxFunctor.map₂_leftUnitor - CategoryTheory.OplaxFunctor.map₂_rightUnitor - variable (F : OplaxFunctor B C) @[reassoc] @@ -115,7 +100,7 @@ lemma mapComp_assoc_right {a b c d : B} (f : a ⟶ b) (g : b ⟶ c) (h : c ⟶ d F.mapComp f (g ≫ h) ≫ F.map f ◁ F.mapComp g h = F.map₂ (α_ f g h).inv ≫ F.mapComp (f ≫ g) h ≫ F.mapComp f g ▷ F.map h ≫ (α_ (F.map f) (F.map g) (F.map h)).hom := by - rw [← @map₂_associator, ← F.map₂_comp_assoc] + rw [← F.map₂_associator, ← F.map₂_comp_assoc] simp @[reassoc] @@ -125,15 +110,6 @@ lemma mapComp_assoc_left {a b c d : B} (f : a ⟶ b) (g : b ⟶ c) (h : c ⟶ d) ≫ (α_ (F.map f) (F.map g) (F.map h)).inv := by simp --- Porting note: `to_prelax_eq_coe` and `to_prelaxFunctor_obj` are --- syntactic tautologies in lean 4 - --- Porting note: removed lemma `to_prelaxFunctor_map` relating the now --- nonexistent `PrelaxFunctor.map` and `OplaxFunctor.map` - --- Porting note: removed lemma `to_prelaxFunctor_map₂` relating --- `PrelaxFunctor.map₂` to nonexistent `OplaxFunctor.map₂` - /-- The identity oplax functor. -/ @[simps] def id (B : Type u₁) [Bicategory.{w₁, v₁} B] : OplaxFunctor B B where @@ -161,8 +137,6 @@ def comp (F : OplaxFunctor B C) (G : OplaxFunctor C D) : OplaxFunctor B D where mapComp_naturality_right, assoc] map₂_associator := fun f g h => by dsimp - -- Porting note: if you use the `map₂_associator_aux` hack in the definition of - -- `map₂_associator` then the `simp only` call below does not seem to apply `map₂_associator` simp only [map₂_associator, ← PrelaxFunctor.map₂_comp_assoc, ← mapComp_naturality_right_assoc, whiskerLeft_comp, assoc] simp only [map₂_associator, PrelaxFunctor.map₂_comp, mapComp_naturality_left_assoc, @@ -177,24 +151,21 @@ def comp (F : OplaxFunctor B C) (G : OplaxFunctor C D) : OplaxFunctor B D where whiskerLeft_comp, assoc] /-- A structure on an oplax functor that promotes an oplax functor to a pseudofunctor. -See `Pseudofunctor.mkOfOplax`. --/ + +See `Pseudofunctor.mkOfOplax`. -/ -- Porting note(#5171): linter not ported yet -- @[nolint has_nonempty_instance] --- Porting note: removing primes in structure name because --- my understanding is that they're no longer needed structure PseudoCore (F : OplaxFunctor B C) where + /-- The isomorphism giving rise to the oplax unity constraint -/ mapIdIso (a : B) : F.map (𝟙 a) ≅ 𝟙 (F.obj a) + /-- The isomorphism giving rise to the oplax functoriality constraint -/ mapCompIso {a b c : B} (f : a ⟶ b) (g : b ⟶ c) : F.map (f ≫ g) ≅ F.map f ≫ F.map g + /-- `mapIdIso` gives rise to the oplax unity constraint -/ mapIdIso_hom : ∀ {a : B}, (mapIdIso a).hom = F.mapId a := by aesop_cat + /-- `mapCompIso` gives rise to the oplax functoriality constraint -/ mapCompIso_hom : ∀ {a b c : B} (f : a ⟶ b) (g : b ⟶ c), (mapCompIso f g).hom = F.mapComp f g := by aesop_cat -attribute [nolint docBlame] CategoryTheory.OplaxFunctor.PseudoCore.mapIdIso - CategoryTheory.OplaxFunctor.PseudoCore.mapCompIso - CategoryTheory.OplaxFunctor.PseudoCore.mapIdIso_hom - CategoryTheory.OplaxFunctor.PseudoCore.mapCompIso_hom - attribute [simp] PseudoCore.mapIdIso_hom PseudoCore.mapCompIso_hom end diff --git a/Mathlib/CategoryTheory/Bicategory/LocallyDiscrete.lean b/Mathlib/CategoryTheory/Bicategory/LocallyDiscrete.lean index 4bce6d2322466..3ddbc22d951aa 100644 --- a/Mathlib/CategoryTheory/Bicategory/LocallyDiscrete.lean +++ b/Mathlib/CategoryTheory/Bicategory/LocallyDiscrete.lean @@ -106,6 +106,9 @@ instance locallyDiscreteBicategory.strict : Strict (LocallyDiscrete C) where comp_id f := Discrete.ext (Category.comp_id _) assoc f g h := Discrete.ext (Category.assoc _ _ _) +attribute [local simp] + Strict.leftUnitor_eqToIso Strict.rightUnitor_eqToIso Strict.associator_eqToIso + variable {I : Type u₁} [Category.{v₁} I] {B : Type u₂} [Bicategory.{w₂, v₂} B] [Strict B] /-- diff --git a/Mathlib/CategoryTheory/Bicategory/NaturalTransformation/Strong.lean b/Mathlib/CategoryTheory/Bicategory/NaturalTransformation/Strong.lean index ae37a41743113..28d84af3a9c06 100644 --- a/Mathlib/CategoryTheory/Bicategory/NaturalTransformation/Strong.lean +++ b/Mathlib/CategoryTheory/Bicategory/NaturalTransformation/Strong.lean @@ -116,7 +116,7 @@ variable (F : OplaxFunctor B C) /-- The identity strong natural transformation. -/ @[simps!] def id : StrongOplaxNatTrans F F := - mkOfOplax (OplaxNatTrans.id F) { naturality := λ f ↦ (ρ_ (F.map f)) ≪≫ (λ_ (F.map f)).symm } + mkOfOplax (OplaxNatTrans.id F) { naturality := fun f ↦ (ρ_ (F.map f)) ≪≫ (λ_ (F.map f)).symm } @[simp] lemma id.toOplax : (id F).toOplax = OplaxNatTrans.id F := @@ -183,7 +183,7 @@ end @[simps!] def vcomp (η : StrongOplaxNatTrans F G) (θ : StrongOplaxNatTrans G H) : StrongOplaxNatTrans F H := mkOfOplax (OplaxNatTrans.vcomp η.toOplax θ.toOplax) - { naturality := λ {a b} f ↦ + { naturality := fun {a b} f ↦ (α_ _ _ _).symm ≪≫ whiskerRightIso (η.naturality f) (θ.app b) ≪≫ (α_ _ _ _) ≪≫ whiskerLeftIso (η.app a) (θ.naturality f) ≪≫ (α_ _ _ _).symm } end diff --git a/Mathlib/CategoryTheory/Bicategory/Strict.lean b/Mathlib/CategoryTheory/Bicategory/Strict.lean index 7e0bd006126ab..1edfaa816f646 100644 --- a/Mathlib/CategoryTheory/Bicategory/Strict.lean +++ b/Mathlib/CategoryTheory/Bicategory/Strict.lean @@ -50,15 +50,6 @@ class Bicategory.Strict : Prop where ∀ {a b c d : B} (f : a ⟶ b) (g : b ⟶ c) (h : c ⟶ d), α_ f g h = eqToIso (assoc f g h) := by aesop_cat --- Porting note: not adding simp to: --- Bicategory.Strict.id_comp --- Bicategory.Strict.comp_id --- Bicategory.Strict.assoc -attribute [simp] - Bicategory.Strict.leftUnitor_eqToIso - Bicategory.Strict.rightUnitor_eqToIso - Bicategory.Strict.associator_eqToIso - -- see Note [lower instance priority] /-- Category structure on a strict bicategory -/ instance (priority := 100) StrictBicategory.category [Bicategory.Strict B] : Category B where diff --git a/Mathlib/CategoryTheory/Category/Bipointed.lean b/Mathlib/CategoryTheory/Category/Bipointed.lean index ec8c5cb5122de..d6bd45ad2304f 100644 --- a/Mathlib/CategoryTheory/Category/Bipointed.lean +++ b/Mathlib/CategoryTheory/Category/Bipointed.lean @@ -93,14 +93,11 @@ def swap : Bipointed ⥤ Bipointed where /-- The equivalence between `Bipointed` and itself induced by `Prod.swap` both ways. -/ @[simps!] -def swapEquiv : Bipointed ≌ Bipointed := - CategoryTheory.Equivalence.mk swap swap - (NatIso.ofComponents fun X => - { hom := ⟨id, rfl, rfl⟩ - inv := ⟨id, rfl, rfl⟩ }) - (NatIso.ofComponents fun X => - { hom := ⟨id, rfl, rfl⟩ - inv := ⟨id, rfl, rfl⟩ }) +def swapEquiv : Bipointed ≌ Bipointed where + functor := swap + inverse := swap + unitIso := Iso.refl _ + counitIso := Iso.refl _ @[simp] theorem swapEquiv_symm : swapEquiv.symm = swapEquiv := diff --git a/Mathlib/CategoryTheory/Category/Cat.lean b/Mathlib/CategoryTheory/Category/Cat.lean index 480b844a54dda..3d4788b016f0d 100644 --- a/Mathlib/CategoryTheory/Category/Cat.lean +++ b/Mathlib/CategoryTheory/Category/Cat.lean @@ -74,6 +74,10 @@ instance bicategory.strict : Bicategory.Strict Cat.{v, u} where instance category : LargeCategory.{max v u} Cat.{v, u} := StrictBicategory.category Cat.{v, u} +@[simp] +theorem id_obj {C : Cat} (X : C) : (𝟙 C : C ⥤ C).obj X = X := + rfl + @[simp] theorem id_map {C : Cat} {X Y : C} (f : X ⟶ Y) : (𝟙 C : C ⥤ C).map f = f := rfl @@ -87,6 +91,13 @@ theorem comp_map {C D E : Cat} (F : C ⟶ D) (G : D ⟶ E) {X Y : C} (f : X ⟶ (F ≫ G).map f = G.map (F.map f) := rfl +@[simp] +theorem id_app {C D : Cat} (F : C ⟶ D) (X : C) : (𝟙 F : F ⟶ F).app X = 𝟙 (F.obj X) := rfl + +@[simp] +theorem comp_app {C D : Cat} {F G H : C ⟶ D} (α : F ⟶ G) (β : G ⟶ H) (X : C) : + (α ≫ β).app X = α.app X ≫ β.app X := rfl + @[simp] lemma whiskerLeft_app {C D E : Cat} (F : C ⟶ D) {G H : D ⟶ E} (η : G ⟶ H) (X : C) : (F ◁ η).app X = η.app (F.obj X) := @@ -97,6 +108,11 @@ lemma whiskerRight_app {C D E : Cat} {F G : C ⟶ D} (H : D ⟶ E) (η : F ⟶ G (η ▷ H).app X = H.map (η.app X) := rfl +@[simp] +theorem eqToHom_app {C D : Cat} (F G : C ⟶ D) (h : F = G) (X : C) : + (eqToHom h).app X = eqToHom (Functor.congr_obj h X) := + CategoryTheory.eqToHom_app h X + lemma leftUnitor_hom_app {B C : Cat} (F : B ⟶ C) (X : B) : (λ_ F).hom.app X = eqToHom (by simp) := rfl diff --git a/Mathlib/CategoryTheory/Category/Cat/Adjunction.lean b/Mathlib/CategoryTheory/Category/Cat/Adjunction.lean index 8d930249e4120..55e17bc93bec4 100644 --- a/Mathlib/CategoryTheory/Category/Cat/Adjunction.lean +++ b/Mathlib/CategoryTheory/Category/Cat/Adjunction.lean @@ -52,11 +52,9 @@ def typeToCatObjectsAdj : typeToCat ⊣ Cat.objects where /-- The connected components functor -/ def connectedComponents : Cat.{v, u} ⥤ Type u where obj C := ConnectedComponents C - map F := - Quotient.lift (Quotient.mk (Zigzag.setoid _) ∘ F.obj) - (fun _ _ ↦ Quot.sound ∘ zigzag_obj_of_zigzag F) - map_id _ := funext fun x ↦ (Quotient.exists_rep x).elim (fun _ h ↦ by simp [<- h]; rfl) - map_comp _ _ := funext fun x ↦ (Quotient.exists_rep x).elim (fun _ h => by simp [<- h]) + map F := Functor.mapConnectedComponents F + map_id _ := funext fun x ↦ (Quotient.exists_rep x).elim (fun _ h ↦ by subst h; rfl) + map_comp _ _ := funext fun x ↦ (Quotient.exists_rep x).elim (fun _ h => by subst h; rfl) /-- `typeToCat : Type ⥤ Cat` is right adjoint to `connectedComponents : Cat ⥤ Type` -/ def connectedComponentsTypeToCatAdj : connectedComponents ⊣ typeToCat where diff --git a/Mathlib/CategoryTheory/Category/Pairwise.lean b/Mathlib/CategoryTheory/Category/Pairwise.lean index ec1161abbddc2..a8e795bdc19ac 100644 --- a/Mathlib/CategoryTheory/Category/Pairwise.lean +++ b/Mathlib/CategoryTheory/Category/Pairwise.lean @@ -109,15 +109,11 @@ def diagramMap : ∀ {o₁ o₂ : Pairwise ι} (_ : o₁ ⟶ o₂), diagramObj U | _, _, left _ _ => homOfLE inf_le_left | _, _, right _ _ => homOfLE inf_le_right --- Porting note: the fields map_id and map_comp were filled by hand, as generating them by `aesop` --- causes a PANIC. /-- Given a function `U : ι → α` for `[SemilatticeInf α]`, we obtain a functor `Pairwise ι ⥤ α`, sending `single i` to `U i` and `pair i j` to `U i ⊓ U j`, and the morphisms to the obvious inequalities. -/ --- Porting note: We want `@[simps]` here, but this causes a PANIC in the linter. --- (Which, worryingly, does not cause a linter failure!) --- @[simps] +@[simps] def diagram : Pairwise ι ⥤ α where obj := diagramObj U map := diagramMap U diff --git a/Mathlib/CategoryTheory/Category/PartialFun.lean b/Mathlib/CategoryTheory/Category/PartialFun.lean index 099e4390c830c..0ed2b108fb523 100644 --- a/Mathlib/CategoryTheory/Category/PartialFun.lean +++ b/Mathlib/CategoryTheory/Category/PartialFun.lean @@ -46,8 +46,6 @@ instance : CoeSort PartialFun Type* := def of : Type* → PartialFun := id --- Porting note: removed this lemma which is useless because of the expansion of coercions - instance : Inhabited PartialFun := ⟨Type*⟩ @@ -82,6 +80,7 @@ def typeToPartialFun : Type u ⥤ PartialFun where instance : typeToPartialFun.Faithful where map_injective {_ _} := PFun.lift_injective +-- b ∈ PFun.toSubtype (fun x ↦ x ≠ X.point) Subtype.val a ↔ b ∈ Part.some a /-- The functor which deletes the point of a pointed type. In return, this makes the maps partial. This is the computable part of the equivalence `PartialFunEquivPointed`. -/ @[simps obj map] @@ -89,7 +88,8 @@ def pointedToPartialFun : Pointed.{u} ⥤ PartialFun where obj X := { x : X // x ≠ X.point } map f := PFun.toSubtype _ f.toFun ∘ Subtype.val map_id X := - PFun.ext fun a b => PFun.mem_toSubtype_iff.trans (Subtype.coe_inj.trans Part.mem_some_iff.symm) + PFun.ext fun a b => + PFun.mem_toSubtype_iff (b := b).trans (Subtype.coe_inj.trans Part.mem_some_iff.symm) map_comp f g := by -- Porting note: the proof was changed because the original mathlib3 proof no longer works apply PFun.ext _ @@ -119,9 +119,10 @@ noncomputable def partialFunToPointed : PartialFun ⥤ Pointed := by /-- The equivalence induced by `PartialFunToPointed` and `PointedToPartialFun`. `Part.equivOption` made functorial. -/ @[simps!] -noncomputable def partialFunEquivPointed : PartialFun.{u} ≌ Pointed := - CategoryTheory.Equivalence.mk partialFunToPointed pointedToPartialFun - (NatIso.ofComponents (fun X => PartialFun.Iso.mk +noncomputable def partialFunEquivPointed : PartialFun.{u} ≌ Pointed where + functor := partialFunToPointed + inverse := pointedToPartialFun + unitIso := NatIso.ofComponents (fun X => PartialFun.Iso.mk { toFun := fun a => ⟨some a, some_ne_none a⟩ invFun := fun a => Option.get _ (Option.ne_none_iff_isSome.1 a.2) left_inv := fun a => Option.get_some _ _ @@ -145,13 +146,19 @@ noncomputable def partialFunEquivPointed : PartialFun.{u} ≌ Pointed := · intro h split_ifs at h with ha rw [some_inj] at h - exact ⟨b, ⟨ha, h.symm⟩, rfl⟩) <| + exact ⟨b, ⟨ha, h.symm⟩, rfl⟩ + counitIso := NatIso.ofComponents (fun X ↦ Pointed.Iso.mk (by classical exact Equiv.optionSubtypeNe X.point) (by rfl)) fun {X Y} f ↦ Pointed.Hom.ext <| funext fun a ↦ by obtain _ | ⟨a, ha⟩ := a · exact f.map_point.symm simp_all [Option.casesOn'_eq_elim, Part.elim_toOption] + functor_unitIso_comp X := by + ext (_ | x) + · rfl + · simp + rfl /-- Forgetting that maps are total and making them total again by adding a point is the same as just adding a point. -/ diff --git a/Mathlib/CategoryTheory/Category/Preorder.lean b/Mathlib/CategoryTheory/Category/Preorder.lean index e1c432d48fc49..f46afa90197a5 100644 --- a/Mathlib/CategoryTheory/Category/Preorder.lean +++ b/Mathlib/CategoryTheory/Category/Preorder.lean @@ -85,14 +85,7 @@ theorem leOfHom {x y : X} (h : x ⟶ y) : x ≤ y := @[nolint defLemma, inherit_doc leOfHom] abbrev _root_.Quiver.Hom.le := @leOfHom --- Porting note: why does this lemma exist? With proof irrelevance, we don't need to simplify proofs --- @[simp] -theorem leOfHom_homOfLE {x y : X} (h : x ≤ y) : h.hom.le = h := - rfl - --- Porting note: linter gives: "Left-hand side does not simplify, when using the simp lemma on --- itself. This usually means that it will never apply." removing simp? It doesn't fire --- @[simp] +@[simp] theorem homOfLE_leOfHom {x y : X} (h : x ⟶ y) : h.le.hom = h := rfl diff --git a/Mathlib/CategoryTheory/Category/TwoP.lean b/Mathlib/CategoryTheory/Category/TwoP.lean index a866c977c18f0..9a4f129f06e4e 100644 --- a/Mathlib/CategoryTheory/Category/TwoP.lean +++ b/Mathlib/CategoryTheory/Category/TwoP.lean @@ -77,14 +77,11 @@ noncomputable def swap : TwoP ⥤ TwoP where /-- The equivalence between `TwoP` and itself induced by `Prod.swap` both ways. -/ @[simps!] -noncomputable def swapEquiv : TwoP ≌ TwoP := - CategoryTheory.Equivalence.mk swap swap - (NatIso.ofComponents fun X => - { hom := ⟨id, rfl, rfl⟩ - inv := ⟨id, rfl, rfl⟩ }) - (NatIso.ofComponents fun X => - { hom := ⟨id, rfl, rfl⟩ - inv := ⟨id, rfl, rfl⟩ }) +noncomputable def swapEquiv : TwoP ≌ TwoP where + functor := swap + inverse := swap + unitIso := Iso.refl _ + counitIso := Iso.refl _ @[simp] theorem swapEquiv_symm : swapEquiv.symm = swapEquiv := diff --git a/Mathlib/CategoryTheory/ChosenFiniteProducts/Cat.lean b/Mathlib/CategoryTheory/ChosenFiniteProducts/Cat.lean new file mode 100644 index 0000000000000..b78443a4100e4 --- /dev/null +++ b/Mathlib/CategoryTheory/ChosenFiniteProducts/Cat.lean @@ -0,0 +1,98 @@ +/- +Copyright (c) 2024 Nicolas Rolland. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Nicolas Rolland +-/ +import Mathlib.CategoryTheory.ChosenFiniteProducts +/-! +# Chosen finite products in `Cat` + +This file proves that the cartesian product of a pair of categories agrees with the +product in `Cat`, and provides the associated `ChosenFiniteProducts` instance. +-/ + +universe v u + +namespace CategoryTheory + +namespace Cat + +open Limits + +/-- The chosen terminal object in `Cat`. -/ +abbrev chosenTerminal : Cat := Cat.of (ULift (ULiftHom (Discrete Unit))) + +/-- The chosen terminal object in `Cat` is terminal. -/ +def chosenTerminalIsTerminal : IsTerminal chosenTerminal := + IsTerminal.ofUniqueHom (fun _ ↦ (Functor.const _).obj ⟨⟨⟨⟩⟩⟩) fun _ _ ↦ rfl + +/-- The chosen product of categories `C × D` yields a product cone in `Cat`. -/ +def prodCone (C D : Cat.{v,u}) : BinaryFan C D := + .mk (P := .of (C × D)) (Prod.fst _ _) (Prod.snd _ _) + +/-- The product cone in `Cat` is indeed a product. -/ +def isLimitProdCone (X Y : Cat) : IsLimit (prodCone X Y) := BinaryFan.isLimitMk + (fun S => S.fst.prod' S.snd) (fun _ => rfl) (fun _ => rfl) (fun _ _ h1 h2 => + Functor.hext + (fun _ ↦ Prod.ext (by simp [← h1]) (by simp [← h2])) + (fun _ _ _ ↦ by dsimp; rw [← h1, ← h2]; rfl)) + +instance : ChosenFiniteProducts Cat where + product (X Y : Cat) := { isLimit := isLimitProdCone X Y } + terminal := { isLimit := chosenTerminalIsTerminal } + +/-- A monoidal instance for Cat is provided through monoidalOfChosenFiniteProducts -/ +example : MonoidalCategory Cat := by infer_instance + +/-- A symmetric monoidal instance for Cat is provided through symmetricOfChosenFiniteProducts -/ +example : SymmetricCategory Cat := by infer_instance + +end Cat + +namespace Monoidal + +open MonoidalCategory + +lemma tensorObj (C : Cat) (D : Cat) : C ⊗ D = Cat.of (C × D) := rfl + +lemma whiskerLeft (X : Cat) {A : Cat} {B : Cat} (f : A ⟶ B) : + X ◁ f = (𝟭 X).prod f := rfl + +lemma whiskerLeft_fst (X : Cat) {A : Cat} {B : Cat} (f : A ⟶ B) : + (X ◁ f) ⋙ Prod.fst _ _ = Prod.fst _ _ := rfl + +lemma whiskerLeft_snd (X : Cat) {A : Cat} {B : Cat} (f : A ⟶ B) : + (X ◁ f) ⋙ Prod.snd _ _ = Prod.snd _ _ ⋙ f := rfl + +lemma whiskerRight {A : Cat} {B : Cat} (f : A ⟶ B) (X : Cat) : + f ▷ X = f.prod (𝟭 X) := rfl + +lemma whiskerRight_fst {A : Cat} {B : Cat} (f : A ⟶ B) (X : Cat) : + (f ▷ X) ⋙ Prod.fst _ _ = Prod.fst _ _ ⋙ f := rfl + +lemma whiskerRight_snd {A : Cat} {B : Cat} (f : A ⟶ B) (X : Cat) : + (f ▷ X) ⋙ Prod.snd _ _ = Prod.snd _ _ := rfl + +lemma tensorHom {A : Cat} {B : Cat} (f : A ⟶ B) {X : Cat} {Y : Cat} (g : X ⟶ Y) : + f ⊗ g = f.prod g := rfl + +lemma tensorUnit : 𝟙_ Cat = Cat.chosenTerminal := rfl + +lemma associator_hom (X : Cat) (Y : Cat) (Z : Cat) : + (associator X Y Z).hom = Functor.prod' (Prod.fst (X × Y) Z ⋙ Prod.fst X Y) + ((Functor.prod' ((Prod.fst (X × Y) Z ⋙ Prod.snd X Y)) + (Prod.snd (X × Y) Z : (X × Y) × Z ⥤ Z))) := rfl + +lemma associator_inv (X : Cat) (Y : Cat) (Z : Cat) : + (associator X Y Z).inv = Functor.prod' (Functor.prod' (Prod.fst X (Y × Z) : X × (Y × Z) ⥤ X) + (Prod.snd X (Y × Z) ⋙ Prod.fst Y Z)) (Prod.snd X (Y × Z) ⋙ Prod.snd Y Z) := rfl + +lemma leftUnitor_hom (C : Cat) : (λ_ C).hom = Prod.snd _ _ := rfl + +lemma leftUnitor_inv (C : Cat) : (λ_ C).inv = Prod.sectr ⟨⟨⟨⟩⟩⟩ _ := rfl + +lemma rightUnitor_hom (C : Cat) : (ρ_ C).hom = Prod.fst _ _ := rfl + +lemma rightUnitor_inv (C : Cat) : (ρ_ C).inv = Prod.sectl _ ⟨⟨⟨⟩⟩⟩ := rfl + +end CategoryTheory.Monoidal diff --git a/Mathlib/CategoryTheory/ChosenFiniteProducts/FunctorCategory.lean b/Mathlib/CategoryTheory/ChosenFiniteProducts/FunctorCategory.lean index e50ed06042114..c95c9da1f310e 100644 --- a/Mathlib/CategoryTheory/ChosenFiniteProducts/FunctorCategory.lean +++ b/Mathlib/CategoryTheory/ChosenFiniteProducts/FunctorCategory.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Joël Riou -/ import Mathlib.CategoryTheory.ChosenFiniteProducts -import Mathlib.CategoryTheory.Limits.FunctorCategory +import Mathlib.CategoryTheory.Limits.FunctorCategory.Basic /-! # Functor categories have chosen finite products diff --git a/Mathlib/CategoryTheory/Closed/Cartesian.lean b/Mathlib/CategoryTheory/Closed/Cartesian.lean index 4253d1f338112..cc3a110baa215 100644 --- a/Mathlib/CategoryTheory/Closed/Cartesian.lean +++ b/Mathlib/CategoryTheory/Closed/Cartesian.lean @@ -31,7 +31,7 @@ for closed monoidal categories, and these could be generalised. -/ -universe v u u₂ +universe v v₂ u u₂ noncomputable section @@ -308,7 +308,7 @@ def powZero {I : C} (t : IsInitial I) [CartesianClosed C] : I ⟹ B ≅ ⊤_ C w rw [← curry_natural_left, curry_eq_iff, ← cancel_epi (mulZero t).inv] apply t.hom_ext --- TODO: Generalise the below to its commutated variants. +-- TODO: Generalise the below to its commuted variants. -- TODO: Define a distributive category, so that zero_mul and friends can be derived from this. /-- In a CCC with binary coproducts, the distribution morphism is an isomorphism. -/ def prodCoprodDistrib [HasBinaryCoproducts C] [CartesianClosed C] (X Y Z : C) : @@ -353,7 +353,7 @@ theorem initial_mono {I : C} (B : C) (t : IsInitial I) [CartesianClosed C] : Mon instance Initial.mono_to [HasInitial C] (B : C) [CartesianClosed C] : Mono (initial.to B) := initial_mono B initialIsInitial -variable {D : Type u₂} [Category.{v} D] +variable {D : Type u₂} [Category.{v₂} D] section Functor diff --git a/Mathlib/CategoryTheory/Closed/Types.lean b/Mathlib/CategoryTheory/Closed/Types.lean index 3a05fc2cb4c52..e1b0ffa01b4f2 100644 --- a/Mathlib/CategoryTheory/Closed/Types.lean +++ b/Mathlib/CategoryTheory/Closed/Types.lean @@ -40,19 +40,10 @@ def Types.binaryProductAdjunction (X : Type v₁) : instance (X : Type v₁) : (Types.binaryProductFunctor.obj X).IsLeftAdjoint := ⟨_, ⟨Types.binaryProductAdjunction X⟩⟩ --- Porting note: this instance should be moved to a higher file. -instance : HasFiniteProducts (Type v₁) := - hasFiniteProducts_of_hasProducts.{v₁} _ - instance : CartesianClosed (Type v₁) := CartesianClosed.mk _ (fun X => Exponentiable.mk _ _ ((Types.binaryProductAdjunction X).ofNatIsoLeft (Types.binaryProductIsoProd.app X))) --- Porting note: in mathlib3, the assertion was for `(C ⥤ Type u₁)`, but then Lean4 was --- confused with universes. It makes no harm to relax the universe assumptions here. -instance {C : Type u₁} [Category.{v₁} C] : HasFiniteProducts (C ⥤ Type u₂) := - hasFiniteProducts_of_hasProducts _ - instance {C : Type v₁} [SmallCategory C] : CartesianClosed (C ⥤ Type v₁) := CartesianClosed.mk _ (fun F => by @@ -60,6 +51,31 @@ instance {C : Type v₁} [SmallCategory C] : CartesianClosed (C ⥤ Type v₁) : have := Presheaf.isLeftAdjoint_of_preservesColimits (prod.functor.obj F) exact Exponentiable.mk _ _ (Adjunction.ofIsLeftAdjoint (prod.functor.obj F))) +-- TODO: once we have `MonoidalClosed` instances for functor categories into general monoidal +-- closed categories, replace this with that, as it will be a more explicit construction. +/-- This is not a good instance because of the universe levels. Below is the instance where the +target category is `Type (max u₁ v₁)`. -/ +def cartesianClosedFunctorToTypes {C : Type u₁} [Category.{v₁} C] : + CartesianClosed (C ⥤ Type (max u₁ v₁ u₂)) := + let e : (ULiftHom.{max u₁ v₁ u₂} (ULift.{max u₁ v₁ u₂} C)) ⥤ Type (max u₁ v₁ u₂) ≌ + C ⥤ Type (max u₁ v₁ u₂) := + Functor.asEquivalence ((whiskeringLeft _ _ _).obj + (ULift.equivalence.trans ULiftHom.equiv).functor) + cartesianClosedOfEquiv e + +-- TODO: once we have `MonoidalClosed` instances for functor categories into general monoidal +-- closed categories, replace this with that, as it will be a more explicit construction. +instance {C : Type u₁} [Category.{v₁} C] : CartesianClosed (C ⥤ Type (max u₁ v₁)) := + cartesianClosedFunctorToTypes + +-- TODO: once we have `MonoidalClosed` instances for functor categories into general monoidal +-- closed categories, replace this with that, as it will be a more explicit construction. +instance {C : Type u₁} [Category.{v₁} C] [EssentiallySmall.{v₁} C] : + CartesianClosed (C ⥤ Type v₁) := + let e : (SmallModel C) ⥤ Type v₁ ≌ C ⥤ Type v₁ := + Functor.asEquivalence ((whiskeringLeft _ _ _).obj (equivSmallModel _).functor) + cartesianClosedOfEquiv e + end CartesianClosed end diff --git a/Mathlib/CategoryTheory/Closed/Zero.lean b/Mathlib/CategoryTheory/Closed/Zero.lean index 4c6d8edac4a37..459ba941f8d89 100644 --- a/Mathlib/CategoryTheory/Closed/Zero.lean +++ b/Mathlib/CategoryTheory/Closed/Zero.lean @@ -54,13 +54,14 @@ attribute [local instance] uniqueHomsetOfZero /-- A cartesian closed category with a zero object is equivalent to the category with one object and one morphism. -/ -def equivPUnit [HasZeroObject C] : C ≌ Discrete PUnit.{w + 1} := - Equivalence.mk (Functor.star C) (Functor.fromPUnit 0) - (NatIso.ofComponents +def equivPUnit [HasZeroObject C] : C ≌ Discrete PUnit.{w + 1} where + functor := Functor.star C + inverse := Functor.fromPUnit 0 + unitIso := NatIso.ofComponents (fun X => { hom := default inv := default }) - fun f => Subsingleton.elim _ _) - (Functor.punitExt _ _) + fun f => Subsingleton.elim _ _ + counitIso := Functor.punitExt _ _ end CategoryTheory diff --git a/Mathlib/CategoryTheory/Comma/Arrow.lean b/Mathlib/CategoryTheory/Comma/Arrow.lean index 1f396ae0ab27c..972c94b207848 100644 --- a/Mathlib/CategoryTheory/Comma/Arrow.lean +++ b/Mathlib/CategoryTheory/Comma/Arrow.lean @@ -34,7 +34,7 @@ variable (T) def Arrow := Comma.{v, v, v} (𝟭 T) (𝟭 T) -/- Porting note: could not derive `Category` above so this instance works in its place-/ +/- Porting note: could not derive `Category` above so this instance works in its place -/ instance : Category (Arrow T) := commaCategory -- Satisfying the inhabited linter diff --git a/Mathlib/CategoryTheory/Comma/Basic.lean b/Mathlib/CategoryTheory/Comma/Basic.lean index 23c4e18177717..892745edf3a95 100644 --- a/Mathlib/CategoryTheory/Comma/Basic.lean +++ b/Mathlib/CategoryTheory/Comma/Basic.lean @@ -60,7 +60,7 @@ variable {B' : Type u₅} [Category.{v₅} B'] variable {T' : Type u₆} [Category.{v₆} T'] /-- The objects of the comma category are triples of an object `left : A`, an object - `right : B` and a morphism `hom : L.obj left ⟶ R.obj right`. -/ + `right : B` and a morphism `hom : L.obj left ⟶ R.obj right`. -/ structure Comma (L : A ⥤ T) (R : B ⥤ T) : Type max u₁ u₂ v₃ where left : A right : B @@ -313,10 +313,11 @@ def mapLeftEq (l l' : L₁ ⟶ L₂) (h : l = l') : mapLeft R l ≅ mapLeft R l' /-- A natural isomorphism `L₁ ≅ L₂` induces an equivalence of categories `Comma L₁ R ≌ Comma L₂ R`. -/ @[simps!] -def mapLeftIso (i : L₁ ≅ L₂) : Comma L₁ R ≌ Comma L₂ R := - Equivalence.mk (mapLeft _ i.inv) (mapLeft _ i.hom) - ((mapLeftId _ _).symm ≪≫ mapLeftEq _ _ _ i.hom_inv_id.symm ≪≫ mapLeftComp _ _ _) - ((mapLeftComp _ _ _).symm ≪≫ mapLeftEq _ _ _ i.inv_hom_id ≪≫ mapLeftId _ _) +def mapLeftIso (i : L₁ ≅ L₂) : Comma L₁ R ≌ Comma L₂ R where + functor := mapLeft _ i.inv + inverse := mapLeft _ i.hom + unitIso := (mapLeftId _ _).symm ≪≫ mapLeftEq _ _ _ i.hom_inv_id.symm ≪≫ mapLeftComp _ _ _ + counitIso := (mapLeftComp _ _ _).symm ≪≫ mapLeftEq _ _ _ i.inv_hom_id ≪≫ mapLeftId _ _ /-- A natural transformation `R₁ ⟶ R₂` induces a functor `Comma L R₁ ⥤ Comma L R₂`. -/ @[simps] @@ -352,10 +353,11 @@ def mapRightEq (r r' : R₁ ⟶ R₂) (h : r = r') : mapRight L r ≅ mapRight L /-- A natural isomorphism `R₁ ≅ R₂` induces an equivalence of categories `Comma L R₁ ≌ Comma L R₂`. -/ @[simps!] -def mapRightIso (i : R₁ ≅ R₂) : Comma L R₁ ≌ Comma L R₂ := - Equivalence.mk (mapRight _ i.hom) (mapRight _ i.inv) - ((mapRightId _ _).symm ≪≫ mapRightEq _ _ _ i.hom_inv_id.symm ≪≫ mapRightComp _ _ _) - ((mapRightComp _ _ _).symm ≪≫ mapRightEq _ _ _ i.inv_hom_id ≪≫ mapRightId _ _) +def mapRightIso (i : R₁ ≅ R₂) : Comma L R₁ ≌ Comma L R₂ where + functor := mapRight _ i.hom + inverse := mapRight _ i.inv + unitIso := (mapRightId _ _).symm ≪≫ mapRightEq _ _ _ i.hom_inv_id.symm ≪≫ mapRightComp _ _ _ + counitIso := (mapRightComp _ _ _).symm ≪≫ mapRightEq _ _ _ i.inv_hom_id ≪≫ mapRightId _ _ end @@ -453,10 +455,11 @@ def fromProd (L : A ⥤ Discrete PUnit) (R : B ⥤ Discrete PUnit) : is equivalent to their product. -/ @[simps!] def equivProd (L : A ⥤ Discrete PUnit) (R : B ⥤ Discrete PUnit) : - Comma L R ≌ A × B := - Equivalence.mk ((fst L R).prod' (snd L R)) (fromProd L R) - { hom := 𝟙 _, inv := 𝟙 _ } - { hom := 𝟙 _, inv := 𝟙 _ } + Comma L R ≌ A × B where + functor := (fst L R).prod' (snd L R) + inverse := fromProd L R + unitIso := Iso.refl _ + counitIso := Iso.refl _ /-- Taking the comma category of a functor into `A ⥤ Discrete PUnit` and the identity `Discrete PUnit ⥤ Discrete PUnit` results in a category equivalent to `A`. -/ diff --git a/Mathlib/CategoryTheory/Comma/Over.lean b/Mathlib/CategoryTheory/Comma/Over.lean index a1d85c11217fa..7a62b01614f0a 100644 --- a/Mathlib/CategoryTheory/Comma/Over.lean +++ b/Mathlib/CategoryTheory/Comma/Over.lean @@ -29,6 +29,7 @@ universe v₁ v₂ u₁ u₂ -- morphism levels before object levels. See note [CategoryTheory universes]. variable {T : Type u₁} [Category.{v₁} T] +variable {D : Type u₂} [Category.{v₂} D] /-- The over category has as objects arrows in `T` with codomain `X` and as morphisms commutative triangles. @@ -311,10 +312,6 @@ theorem iteratedSliceBackward_forget_forget : end IteratedSlice -section - -variable {D : Type u₂} [Category.{v₂} D] - /-- A functor `F : T ⥤ D` induces a functor `Over X ⥤ Over (F.obj X)` in the obvious way. -/ @[simps] def post (F : T ⥤ D) : Over X ⥤ Over (F.obj X) where @@ -322,14 +319,10 @@ def post (F : T ⥤ D) : Over X ⥤ Over (F.obj X) where map f := Over.homMk (F.map f.left) (by simp only [Functor.id_obj, mk_left, Functor.const_obj_obj, mk_hom, ← F.map_comp, w]) -end - end Over namespace CostructuredArrow -variable {D : Type u₂} [Category.{v₂} D] - /-- Reinterpreting an `F`-costructured arrow `F.obj d ⟶ X` as an arrow over `X` induces a functor `CostructuredArrow F X ⥤ Over X`. -/ @[simps!] @@ -572,10 +565,6 @@ instance epi_right_of_epi {f g : Under X} (k : f ⟶ g) [Epi k] : Epi k.right := suffices l' = (homMk m : g ⟶ mk (g.hom ≫ m)) by apply congrArg CommaMorphism.right this rw [← cancel_epi k]; ext; apply a -section - -variable {D : Type u₂} [Category.{v₂} D] - /-- A functor `F : T ⥤ D` induces a functor `Under X ⥤ Under (F.obj X)` in the obvious way. -/ @[simps] def post {X : T} (F : T ⥤ D) : Under X ⥤ Under (F.obj X) where @@ -583,8 +572,6 @@ def post {X : T} (F : T ⥤ D) : Under X ⥤ Under (F.obj X) where map f := Under.homMk (F.map f.right) (by simp only [Functor.id_obj, Functor.const_obj_obj, mk_right, mk_hom, ← F.map_comp, w]) -end - end Under namespace StructuredArrow @@ -638,7 +625,7 @@ lemma toOver_comp_forget (F : S ⥤ T) (X : T) (f : (Y : S) → F.obj Y ⟶ X) /-- Given `X : T`, to upgrade a functor `F : S ⥤ T` to a functor `S ⥤ Under X`, it suffices to provide maps `X ⟶ F.obj Y` for all `Y` making the obvious triangles involving all `F.map g` - commute. -/ + commute. -/ @[simps! obj_right map_right] def toUnder (F : S ⥤ T) (X : T) (f : (Y : S) → X ⟶ F.obj Y) (h : ∀ {Y Z : S} (g : Y ⟶ Z), f Y ≫ F.map g = f Z) : S ⥤ Under X := @@ -657,4 +644,136 @@ lemma toUnder_comp_forget (F : S ⥤ T) (X : T) (f : (Y : S) → X ⟶ F.obj Y) end Functor +namespace StructuredArrow + +/-- A functor from the structured arrow category on the projection functor for any structured +arrow category. -/ +@[simps!] +def ofStructuredArrowProjEquivalence.functor (F : D ⥤ T) (Y : T) (X : D) : + StructuredArrow X (StructuredArrow.proj Y F) ⥤ StructuredArrow Y (Under.forget X ⋙ F) := + Functor.toStructuredArrow + (Functor.toUnder (StructuredArrow.proj X _ ⋙ StructuredArrow.proj Y _) _ + (fun g => by exact g.hom) (fun m => by have := m.w; aesop_cat)) _ _ + (fun f => f.right.hom) (by simp) + +/-- The inverse functor of `ofStructuredArrowProjEquivalence.functor`. -/ +@[simps!] +def ofStructuredArrowProjEquivalence.inverse (F : D ⥤ T) (Y : T) (X : D) : + StructuredArrow Y (Under.forget X ⋙ F) ⥤ StructuredArrow X (StructuredArrow.proj Y F) := + Functor.toStructuredArrow + (Functor.toStructuredArrow (StructuredArrow.proj Y _ ⋙ Under.forget X) _ _ + (fun g => by exact g.hom) (fun m => by have := m.w; aesop_cat)) _ _ + (fun f => f.right.hom) (by simp) + +/-- Characterization of the structured arrow category on the projection functor of any +structured arrow category. -/ +def ofStructuredArrowProjEquivalence (F : D ⥤ T) (Y : T) (X : D) : + StructuredArrow X (StructuredArrow.proj Y F) ≌ StructuredArrow Y (Under.forget X ⋙ F) where + functor := ofStructuredArrowProjEquivalence.functor F Y X + inverse := ofStructuredArrowProjEquivalence.inverse F Y X + unitIso := NatIso.ofComponents (fun _ => Iso.refl _) (by simp) + 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`. -/ +@[simps!] +def ofDiagEquivalence.functor (X : T × T) : + StructuredArrow X (Functor.diag _) ⥤ StructuredArrow X.2 (Under.forget X.1) := + Functor.toStructuredArrow + (Functor.toUnder (StructuredArrow.proj X _) _ + (fun f => by exact f.hom.1) (fun m => by have := m.w; aesop_cat)) _ _ + (fun f => f.hom.2) (fun m => by have := m.w; aesop_cat) + +/-- The inverse functor of `ofDiagEquivalence.functor`. -/ +@[simps!] +def ofDiagEquivalence.inverse (X : T × T) : + StructuredArrow X.2 (Under.forget X.1) ⥤ StructuredArrow X (Functor.diag _) := + Functor.toStructuredArrow (StructuredArrow.proj _ _ ⋙ Under.forget _) _ _ + (fun f => (f.right.hom, f.hom)) (fun m => by have := m.w; aesop_cat) + +/-- Characterization of the structured arrow category on the diagonal functor `T ⥤ T × T`. -/ +def ofDiagEquivalence (X : T × T) : + StructuredArrow X (Functor.diag _) ≌ StructuredArrow X.2 (Under.forget X.1) where + functor := ofDiagEquivalence.functor X + inverse := ofDiagEquivalence.inverse X + unitIso := NatIso.ofComponents (fun _ => Iso.refl _) (by simp) + counitIso := NatIso.ofComponents (fun _ => Iso.refl _) (by aesop_cat) + +/-- A version of `StructuredArrow.ofDiagEquivalence` with the roles of the first and second +projection swapped. -/ +def ofDiagEquivalence' (X : T × T) : + StructuredArrow X (Functor.diag _) ≌ StructuredArrow X.1 (Under.forget X.2) := + (ofDiagEquivalence X).trans <| + (ofStructuredArrowProjEquivalence (𝟭 T) X.1 X.2).trans <| + StructuredArrow.mapNatIso (Under.forget X.2).rightUnitor + +end StructuredArrow + +namespace CostructuredArrow + +/-- A functor from the costructured arrow category on the projection functor for any costructured +arrow category. -/ +@[simps!] +def ofCostructuredArrowProjEquivalence.functor (F : T ⥤ D) (Y : D) (X : T) : + CostructuredArrow (CostructuredArrow.proj F Y) X ⥤ CostructuredArrow (Over.forget X ⋙ F) Y := + Functor.toCostructuredArrow + (Functor.toOver (CostructuredArrow.proj _ X ⋙ CostructuredArrow.proj F Y) _ + (fun g => by exact g.hom) (fun m => by have := m.w; aesop_cat)) _ _ + (fun f => f.left.hom) (by simp) + +/-- The inverse functor of `ofCostructuredArrowProjEquivalence.functor`. -/ +@[simps!] +def ofCostructuredArrowProjEquivalence.inverse (F : T ⥤ D) (Y : D) (X : T) : + CostructuredArrow (Over.forget X ⋙ F) Y ⥤ CostructuredArrow (CostructuredArrow.proj F Y) X := + Functor.toCostructuredArrow + (Functor.toCostructuredArrow (CostructuredArrow.proj _ Y ⋙ Over.forget X) _ _ + (fun g => by exact g.hom) (fun m => by have := m.w; aesop_cat)) _ _ + (fun f => f.left.hom) (by simp) + +/-- Characterization of the costructured arrow category on the projection functor of any +costructured arrow category. -/ +def ofCostructuredArrowProjEquivalence (F : T ⥤ D) (Y : D) (X : T) : + CostructuredArrow (CostructuredArrow.proj F Y) X + ≌ CostructuredArrow (Over.forget X ⋙ F) Y where + functor := ofCostructuredArrowProjEquivalence.functor F Y X + inverse := ofCostructuredArrowProjEquivalence.inverse F Y X + unitIso := NatIso.ofComponents (fun _ => Iso.refl _) (by simp) + 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`. -/ +@[simps!] +def ofDiagEquivalence.functor (X : T × T) : + CostructuredArrow (Functor.diag _) X ⥤ CostructuredArrow (Over.forget X.1) X.2 := + Functor.toCostructuredArrow + (Functor.toOver (CostructuredArrow.proj _ X) _ + (fun g => by exact g.hom.1) (fun m => by have := congrArg (·.1) m.w; aesop_cat)) + _ _ + (fun f => f.hom.2) (fun m => by have := congrArg (·.2) m.w; aesop_cat) + +/-- The inverse functor of `ofDiagEquivalence.functor`. -/ +@[simps!] +def ofDiagEquivalence.inverse (X : T × T) : + CostructuredArrow (Over.forget X.1) X.2 ⥤ CostructuredArrow (Functor.diag _) X := + Functor.toCostructuredArrow (CostructuredArrow.proj _ _ ⋙ Over.forget _) _ X + (fun f => (f.left.hom, f.hom)) (fun m => by have := m.w; aesop_cat) + +/-- Characterization of the costructured arrow category on the diagonal functor `T ⥤ T × T`. -/ +def ofDiagEquivalence (X : T × T) : + CostructuredArrow (Functor.diag _) X ≌ CostructuredArrow (Over.forget X.1) X.2 where + functor := ofDiagEquivalence.functor X + inverse := ofDiagEquivalence.inverse X + unitIso := NatIso.ofComponents (fun _ => Iso.refl _) (by simp) + counitIso := NatIso.ofComponents (fun _ => Iso.refl _) (by aesop_cat) + +/-- A version of `CostructuredArrow.ofDiagEquivalence` with the roles of the first and second +projection swapped. -/ +def ofDiagEquivalence' (X : T × T) : + CostructuredArrow (Functor.diag _) X ≌ CostructuredArrow (Over.forget X.2) X.1 := + (ofDiagEquivalence X).trans <| + (ofCostructuredArrowProjEquivalence (𝟭 T) X.1 X.2).trans <| + CostructuredArrow.mapNatIso (Over.forget X.2).rightUnitor + +end CostructuredArrow + end CategoryTheory diff --git a/Mathlib/CategoryTheory/Comma/StructuredArrow.lean b/Mathlib/CategoryTheory/Comma/StructuredArrow.lean index e59aa9a52ccbd..9dff431f80860 100644 --- a/Mathlib/CategoryTheory/Comma/StructuredArrow.lean +++ b/Mathlib/CategoryTheory/Comma/StructuredArrow.lean @@ -111,7 +111,7 @@ def homMk {f f' : StructuredArrow S T} (g : f.right ⟶ f'.right) simpa using w.symm /- Porting note: it appears the simp lemma is not getting generated but the linter -picks up on it (seems like a bug). Either way simp solves it. -/ +picks up on it (seems like a bug). Either way simp solves it. -/ attribute [-simp, nolint simpNF] homMk_left theorem homMk_surjective {f f' : StructuredArrow S T} (φ : f ⟶ f') : @@ -120,7 +120,7 @@ theorem homMk_surjective {f f' : StructuredArrow S T} (φ : f ⟶ f') : ⟨φ.right, StructuredArrow.w φ, rfl⟩ /-- Given a structured arrow `X ⟶ T(Y)`, and an arrow `Y ⟶ Y'`, we can construct a morphism of - structured arrows given by `(X ⟶ T(Y)) ⟶ (X ⟶ T(Y) ⟶ T(Y'))`. -/ + structured arrows given by `(X ⟶ T(Y)) ⟶ (X ⟶ T(Y) ⟶ T(Y'))`. -/ @[simps] def homMk' (f : StructuredArrow S T) (g : f.right ⟶ Y') : f ⟶ mk (f.hom ≫ T.map g) where left := 𝟙 _ @@ -856,37 +856,37 @@ end CostructuredArrow is contravariantly equivalent to the category of costructured arrows `F.op.obj c ⟶ op d`. -/ def structuredArrowOpEquivalence (F : C ⥤ D) (d : D) : - (StructuredArrow d F)ᵒᵖ ≌ CostructuredArrow F.op (op d) := - Equivalence.mk (StructuredArrow.toCostructuredArrow F d) - (CostructuredArrow.toStructuredArrow' F d).rightOp - (NatIso.ofComponents + (StructuredArrow d F)ᵒᵖ ≌ CostructuredArrow F.op (op d) where + functor := StructuredArrow.toCostructuredArrow F d + inverse := (CostructuredArrow.toStructuredArrow' F d).rightOp + unitIso := NatIso.ofComponents (fun X => (StructuredArrow.isoMk (Iso.refl _)).op) fun {X Y} f => Quiver.Hom.unop_inj <| by apply CommaMorphism.ext <;> - dsimp [StructuredArrow.isoMk, Comma.isoMk,StructuredArrow.homMk]; simp) - (NatIso.ofComponents + dsimp [StructuredArrow.isoMk, Comma.isoMk,StructuredArrow.homMk]; simp + counitIso := NatIso.ofComponents (fun X => CostructuredArrow.isoMk (Iso.refl _)) fun {X Y} f => by apply CommaMorphism.ext <;> - dsimp [CostructuredArrow.isoMk, Comma.isoMk, CostructuredArrow.homMk]; simp) + dsimp [CostructuredArrow.isoMk, Comma.isoMk, CostructuredArrow.homMk]; simp /-- For a functor `F : C ⥤ D` and an object `d : D`, the category of costructured arrows `F.obj c ⟶ d` is contravariantly equivalent to the category of structured arrows `op d ⟶ F.op.obj c`. -/ def costructuredArrowOpEquivalence (F : C ⥤ D) (d : D) : - (CostructuredArrow F d)ᵒᵖ ≌ StructuredArrow (op d) F.op := - Equivalence.mk (CostructuredArrow.toStructuredArrow F d) - (StructuredArrow.toCostructuredArrow' F d).rightOp - (NatIso.ofComponents + (CostructuredArrow F d)ᵒᵖ ≌ StructuredArrow (op d) F.op where + functor := CostructuredArrow.toStructuredArrow F d + inverse := (StructuredArrow.toCostructuredArrow' F d).rightOp + unitIso := NatIso.ofComponents (fun X => (CostructuredArrow.isoMk (Iso.refl _)).op) fun {X Y} f => Quiver.Hom.unop_inj <| by apply CommaMorphism.ext <;> - dsimp [CostructuredArrow.isoMk, CostructuredArrow.homMk, Comma.isoMk]; simp) - (NatIso.ofComponents + dsimp [CostructuredArrow.isoMk, CostructuredArrow.homMk, Comma.isoMk]; simp + counitIso := NatIso.ofComponents (fun X => StructuredArrow.isoMk (Iso.refl _)) fun {X Y} f => by apply CommaMorphism.ext <;> - dsimp [StructuredArrow.isoMk, StructuredArrow.homMk, Comma.isoMk]; simp) + dsimp [StructuredArrow.isoMk, StructuredArrow.homMk, Comma.isoMk]; simp end CategoryTheory diff --git a/Mathlib/CategoryTheory/ConcreteCategory/Basic.lean b/Mathlib/CategoryTheory/ConcreteCategory/Basic.lean index 6482fc883f061..8ee159d8afb77 100644 --- a/Mathlib/CategoryTheory/ConcreteCategory/Basic.lean +++ b/Mathlib/CategoryTheory/ConcreteCategory/Basic.lean @@ -84,8 +84,6 @@ attribute [local instance] ConcreteCategory.hasCoeToSort variable {C : Type u} [Category.{v} C] [ConcreteCategory.{w} C] --- Porting note: forget_obj_eq_coe has become a syntactic tautology. - /-- In any concrete category, `(forget C).map` is injective. -/ abbrev ConcreteCategory.instFunLike {X Y : C} : FunLike (X ⟶ Y) X Y where coe f := (forget C).map f diff --git a/Mathlib/CategoryTheory/ConnectedComponents.lean b/Mathlib/CategoryTheory/ConnectedComponents.lean index 6f018d34805a0..cc86ae90a2167 100644 --- a/Mathlib/CategoryTheory/ConnectedComponents.lean +++ b/Mathlib/CategoryTheory/ConnectedComponents.lean @@ -7,6 +7,7 @@ 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 @@ -36,6 +37,16 @@ variable {J : Type u₁} [Category.{v₁} J] def ConnectedComponents (J : Type u₁) [Category.{v₁} J] : Type u₁ := Quotient (Zigzag.setoid J) +/-- The map `ConnectedComponents J → ConnectedComponents K` induced by a functor `J ⥤ K`. -/ +def Functor.mapConnectedComponents {K : Type u₂} [Category.{v₂} K] (F : J ⥤ K) + (x : ConnectedComponents J) : ConnectedComponents K := + x |> Quotient.lift (Quotient.mk (Zigzag.setoid _) ∘ F.obj) + (fun _ _ ↦ Quot.sound ∘ zigzag_obj_of_zigzag F) + +@[simp] +lemma Functor.mapConnectedComponents_mk {K : Type u₂} [Category.{v₂} K] (F : J ⥤ K) (j : J) : + F.mapConnectedComponents (Quotient.mk _ j) = Quotient.mk _ (F.obj j) := rfl + instance [Inhabited J] : Inhabited (ConnectedComponents J) := ⟨Quotient.mk'' default⟩ @@ -46,7 +57,7 @@ def ConnectedComponents.functorToDiscrete (X : Type*) map g := Discrete.eqToHom (congrArg f (Quotient.sound (Zigzag.of_hom g))) /-- Every functor to a discrete category gives a function from connected components -/ -def ConnectedComponents.liftFunctor (J) [Category J] {X : Type*} (F :J ⥤ Discrete X) : +def ConnectedComponents.liftFunctor (J) [Category J] {X : Type*} (F :J ⥤ Discrete X) : (ConnectedComponents J → X) := Quotient.lift (fun c => (F.obj c).as) (fun _ _ h => eq_of_zigzag X (zigzag_obj_of_zigzag F h)) @@ -106,7 +117,7 @@ instance (j : ConnectedComponents J) : IsConnected (Component j) := by -- Everything in our chosen zigzag from `j₁` to `j₂` has a zigzag to `j₂`. have hf : ∀ a : J, a ∈ l → Zigzag a j₂ := by intro i hi - apply List.Chain.induction (fun t => Zigzag t j₂) _ hl₁ hl₂ _ _ _ (List.mem_of_mem_tail hi) + apply hl₁.backwards_induction (fun t => Zigzag t j₂) _ hl₂ _ _ _ (List.mem_of_mem_tail hi) · intro j k apply Relation.ReflTransGen.head · apply Relation.ReflTransGen.refl @@ -114,7 +125,7 @@ instance (j : ConnectedComponents J) : IsConnected (Component j) := by refine ⟨l.pmap f hf, ?_, ?_⟩ · refine @List.chain_pmap_of_chain _ _ _ _ _ f (fun x y _ _ h => ?_) _ _ hl₁ h₁₂ _ exact zag_of_zag_obj (Component.ι _) h - · erw [List.getLast_pmap _ f (j₁ :: l) (by simpa [h₁₂] using hf) (List.cons_ne_nil _ _)] + · erw [List.getLast_pmap f (j₁ :: l) (by simpa [h₁₂] using hf) (List.cons_ne_nil _ _)] exact FullSubcategory.ext hl₂ /-- The disjoint union of `J`s connected components, written explicitly as a sigma-type with the diff --git a/Mathlib/CategoryTheory/DifferentialObject.lean b/Mathlib/CategoryTheory/DifferentialObject.lean index ffd8546c41068..324755f59b43d 100644 --- a/Mathlib/CategoryTheory/DifferentialObject.lean +++ b/Mathlib/CategoryTheory/DifferentialObject.lean @@ -181,8 +181,8 @@ def mapDifferentialObject (F : C ⥤ D) slice_lhs 2 3 => rw [← Functor.comp_map F (shiftFunctor D (1 : S)), ← η.naturality f.f] slice_lhs 1 2 => rw [Functor.comp_map, ← F.map_comp, f.comm, F.map_comp] rw [Category.assoc] } - map_id := by intros; ext; simp [autoParam] - map_comp := by intros; ext; simp [autoParam] + map_id := by intros; ext; simp + map_comp := by intros; ext; simp end Functor diff --git a/Mathlib/CategoryTheory/DiscreteCategory.lean b/Mathlib/CategoryTheory/DiscreteCategory.lean index 480c69f86cce5..3c5a2e2c0acd1 100644 --- a/Mathlib/CategoryTheory/DiscreteCategory.lean +++ b/Mathlib/CategoryTheory/DiscreteCategory.lean @@ -270,9 +270,10 @@ open Opposite @[simps! functor_obj_as inverse_obj] protected def opposite (α : Type u₁) : (Discrete α)ᵒᵖ ≌ Discrete α := let F : Discrete α ⥤ (Discrete α)ᵒᵖ := Discrete.functor fun x => op (Discrete.mk x) - Equivalence.mk F.leftOp F - (NatIso.ofComponents fun ⟨X⟩ => Iso.refl _) - (Discrete.natIso fun ⟨X⟩ => Iso.refl _) + { functor := F.leftOp + inverse := F + unitIso := NatIso.ofComponents fun ⟨X⟩ => Iso.refl _ + counitIso := Discrete.natIso fun ⟨X⟩ => Iso.refl _ } variable {C : Type u₂} [Category.{v₂} C] diff --git a/Mathlib/CategoryTheory/EffectiveEpi/Basic.lean b/Mathlib/CategoryTheory/EffectiveEpi/Basic.lean index 6291d2e13bde1..4259ae6bf495b 100644 --- a/Mathlib/CategoryTheory/EffectiveEpi/Basic.lean +++ b/Mathlib/CategoryTheory/EffectiveEpi/Basic.lean @@ -24,7 +24,7 @@ then these definitions are equivalent, see the file `CategoryTheory/EffectiveEpi/RegularEpi.lean` See [nlab: *Effective Epimorphism*](https://ncatlab.org/nlab/show/effective+epimorphism) and [Stacks 00WP](https://stacks.math.columbia.edu/tag/00WP) for the standard definitions. Note that -our notion of `EffectiveEpi` is often called "strict epi" in the literature. +our notion of `EffectiveEpi` is often called "strict epi" in the literature. ## References - [Elephant]: *Sketches of an Elephant*, P. T. Johnstone: C2.1, Example 2.1.12. @@ -45,7 +45,7 @@ This structure encodes the data required for a morphism to be an effective epimo structure EffectiveEpiStruct {X Y : C} (f : Y ⟶ X) where /-- For every `W` with a morphism `e : Y ⟶ W` that coequalizes every pair of morphisms - `g₁ g₂ : Z ⟶ Y` which `f` coequalizes, `desc e h` is a morphism `X ⟶ W`...  + `g₁ g₂ : Z ⟶ Y` which `f` coequalizes, `desc e h` is a morphism `X ⟶ W`... -/ desc : ∀ {W : C} (e : Y ⟶ W), (∀ {Z : C} (g₁ g₂ : Z ⟶ Y), g₁ ≫ f = g₂ ≫ f → g₁ ≫ e = g₂ ≫ e) → (X ⟶ W) @@ -65,7 +65,7 @@ If `f` has a kernel pair, then this is equivalent to showing that the correspond a colimit. -/ class EffectiveEpi {X Y : C} (f : Y ⟶ X) : Prop where - /-- `f` is an effective epimorphism if there exists an `EffectiveEpiStruct` for `f`. -/ + /-- `f` is an effective epimorphism if there exists an `EffectiveEpiStruct` for `f`. -/ effectiveEpi : Nonempty (EffectiveEpiStruct f) /-- Some chosen `EffectiveEpiStruct` associated to an effective epi. -/ @@ -107,7 +107,7 @@ structure EffectiveEpiFamilyStruct {B : C} {α : Type*} /-- For every `W` with a family of morphisms `e a : Y a ⟶ W` that coequalizes every pair of morphisms `g₁ : Z ⟶ Y a₁`, `g₂ : Z ⟶ Y a₂` which the family `π` coequalizes, `desc e h` is a morphism - `X ⟶ W`...  + `X ⟶ W`... -/ desc : ∀ {W} (e : (a : α) → (X a ⟶ W)), (∀ {Z : C} (a₁ a₂ : α) (g₁ : Z ⟶ X a₁) (g₂ : Z ⟶ X a₂), @@ -129,7 +129,7 @@ provided that the `π a` exhibit `B` as a colimit of the diagram of all "relatio `R → X a₁`, `R ⟶ X a₂` for all `a₁ a₂ : α`. -/ class EffectiveEpiFamily {B : C} {α : Type*} (X : α → C) (π : (a : α) → (X a ⟶ B)) : Prop where - /-- `π` is an effective epimorphic family if there exists an `EffectiveEpiFamilyStruct` for `π` -/ + /-- `π` is an effective epimorphic family if there exists an `EffectiveEpiFamilyStruct` for `π` -/ effectiveEpiFamily : Nonempty (EffectiveEpiFamilyStruct X π) /-- Some chosen `EffectiveEpiFamilyStruct` associated to an effective epi family. -/ @@ -186,7 +186,7 @@ instance {B X : C} (f : X ⟶ B) [EffectiveEpi f] : EffectiveEpiFamily (fun () ⟨⟨effectiveEpiFamilyStructSingletonOfEffectiveEpi f⟩⟩ /-- -A single element `EffectiveEpiFamily` constists of an `EffectiveEpi` +A single element `EffectiveEpiFamily` consists of an `EffectiveEpi` -/ noncomputable def effectiveEpiStructOfEffectiveEpiFamilySingleton {B X : C} (f : X ⟶ B) diff --git a/Mathlib/CategoryTheory/EffectiveEpi/Comp.lean b/Mathlib/CategoryTheory/EffectiveEpi/Comp.lean index 94fd3321440d7..a8b4353556eb6 100644 --- a/Mathlib/CategoryTheory/EffectiveEpi/Comp.lean +++ b/Mathlib/CategoryTheory/EffectiveEpi/Comp.lean @@ -8,7 +8,7 @@ import Mathlib.CategoryTheory.EffectiveEpi.Basic # Composition of effective epimorphisms -This file provides `EffectiveEpi` instances for certain compositions. +This file provides `EffectiveEpi` instances for certain compositions. -/ diff --git a/Mathlib/CategoryTheory/EffectiveEpi/Coproduct.lean b/Mathlib/CategoryTheory/EffectiveEpi/Coproduct.lean index 85b4dfd1e7fc3..80a53351c358d 100644 --- a/Mathlib/CategoryTheory/EffectiveEpi/Coproduct.lean +++ b/Mathlib/CategoryTheory/EffectiveEpi/Coproduct.lean @@ -56,7 +56,7 @@ example {B : C} {α : Type*} (X : α → C) (π : (a : α) → (X a ⟶ B)) [Eff /-- This is an auxiliary lemma used twice in the definition of `EffectiveEpiFamilyOfEffectiveEpiDesc`. -It is the `h` hypothesis of `EffectiveEpi.desc` and `EffectiveEpi.fac`.  +It is the `h` hypothesis of `EffectiveEpi.desc` and `EffectiveEpi.fac`. -/ theorem effectiveEpiFamilyStructOfEffectiveEpiDesc_aux {B : C} {α : Type*} {X : α → C} {π : (a : α) → X a ⟶ B} [HasCoproduct X] diff --git a/Mathlib/CategoryTheory/EffectiveEpi/Enough.lean b/Mathlib/CategoryTheory/EffectiveEpi/Enough.lean index 1c4b96149fb57..dc7f679ddd6fb 100644 --- a/Mathlib/CategoryTheory/EffectiveEpi/Enough.lean +++ b/Mathlib/CategoryTheory/EffectiveEpi/Enough.lean @@ -8,7 +8,7 @@ import Mathlib.CategoryTheory.EffectiveEpi.Basic # Effectively enough objects in the image of a functor -We define the class `F.EffectivelyEnough` on a functor `F : C ⥤ D` which says that for every object +We define the class `F.EffectivelyEnough` on a functor `F : C ⥤ D` which says that for every object in `D`, there exists an effective epi to it from an object in the image of `F`. -/ @@ -21,11 +21,11 @@ variable {C D : Type*} [Category C] [Category D] (F : C ⥤ D) namespace Functor /-- -An effective presentation of an object `X` with respect to a functor `F` is the data of an effective +An effective presentation of an object `X` with respect to a functor `F` is the data of an effective epimorphism of the form `F.obj p ⟶ X`. -/ structure EffectivePresentation (X : D) where - /-- The object of `C` giving the source of the effective epi -/ + /-- The object of `C` giving the source of the effective epi -/ p : C /-- The morphism `F.obj p ⟶ X` -/ f : F.obj p ⟶ X @@ -33,11 +33,11 @@ structure EffectivePresentation (X : D) where effectiveEpi : EffectiveEpi f /-- -`D` has *effectively enough objects with respect to the functor `F` if every object has an +`D` has *effectively enough objects with respect to the functor `F` if every object has an effective presentation. -/ class EffectivelyEnough : Prop where - /-- For every `X : D`, there exists an object `p` of `C` with an effective epi `F.obj p ⟶ X`. -/ + /-- For every `X : D`, there exists an object `p` of `C` with an effective epi `F.obj p ⟶ X`. -/ presentation : ∀ (X : D), Nonempty (F.EffectivePresentation X) variable [F.EffectivelyEnough] diff --git a/Mathlib/CategoryTheory/EffectiveEpi/Extensive.lean b/Mathlib/CategoryTheory/EffectiveEpi/Extensive.lean index 433f695391d2d..00ace33a89767 100644 --- a/Mathlib/CategoryTheory/EffectiveEpi/Extensive.lean +++ b/Mathlib/CategoryTheory/EffectiveEpi/Extensive.lean @@ -11,7 +11,7 @@ import Mathlib.CategoryTheory.Limits.Preserves.Finite # Preserving and reflecting effective epis on extensive categories -We prove that a functor between `FinitaryPreExtensive` categories preserves (resp. reflects) finite +We prove that a functor between `FinitaryPreExtensive` categories preserves (resp. reflects) finite effective epi families if it preserves (resp. reflects) effective epis. -/ diff --git a/Mathlib/CategoryTheory/EffectiveEpi/RegularEpi.lean b/Mathlib/CategoryTheory/EffectiveEpi/RegularEpi.lean index 8f471641e5b1f..9272c878d3ca1 100644 --- a/Mathlib/CategoryTheory/EffectiveEpi/RegularEpi.lean +++ b/Mathlib/CategoryTheory/EffectiveEpi/RegularEpi.lean @@ -19,7 +19,7 @@ open Limits RegularEpi variable {C : Type*} [Category C] -/-- The data of an `EffectiveEpi` structure on a `RegularEpi`. -/ +/-- The data of an `EffectiveEpi` structure on a `RegularEpi`. -/ def effectiveEpiStructOfRegularEpi {B X : C} (f : X ⟶ B) [RegularEpi f] : EffectiveEpiStruct f where desc _ h := Cofork.IsColimit.desc isColimit _ (h _ _ w) diff --git a/Mathlib/CategoryTheory/Elements.lean b/Mathlib/CategoryTheory/Elements.lean index 35d3b67264029..d5fda0bbb9e35 100644 --- a/Mathlib/CategoryTheory/Elements.lean +++ b/Mathlib/CategoryTheory/Elements.lean @@ -64,6 +64,18 @@ instance categoryOfElements (F : C ⥤ Type w) : Category.{v} F.Elements where id p := ⟨𝟙 p.1, by aesop_cat⟩ comp {X Y Z} f g := ⟨f.val ≫ g.val, by simp [f.2, g.2]⟩ +/-- Natural transformations are mapped to functors between category of elements -/ +@[simps] +def NatTrans.mapElements {F G : C ⥤ Type w} (φ : F ⟶ G) : F.Elements ⥤ G.Elements where + obj := fun ⟨X, x⟩ ↦ ⟨_, φ.app X x⟩ + map {p q} := fun ⟨f, h⟩ ↦ ⟨f, by have hb := congrFun (φ.naturality f) p.2; aesop_cat⟩ + +/-- The functor mapping functors `C ⥤ Type w` to their category of elements -/ +@[simps] +def Functor.elementsFunctor : (C ⥤ Type w) ⥤ Cat where + obj F := Cat.of F.Elements + map n := NatTrans.mapElements n + namespace CategoryOfElements /-- Constructor for morphisms in the category of elements of a functor to types. -/ @@ -89,6 +101,13 @@ theorem id_val {F : C ⥤ Type w} {p : F.Elements} : (𝟙 p : p ⟶ p).val = theorem map_snd {F : C ⥤ Type w} {p q : F.Elements} (f : p ⟶ q) : (F.map f.val) p.2 = q.2 := f.property +/-- Constructor for isomorphisms in the category of elements of a functor to types. -/ +@[simps] +def isoMk {F : C ⥤ Type w} (x y : F.Elements) (e : x.1 ≅ y.1) (he : F.map e.hom x.snd = y.snd) : + x ≅ y where + hom := homMk x y e.hom he + inv := homMk y x e.inv (by rw [← he, FunctorToTypes.map_inv_map_hom_apply]) + end CategoryOfElements instance groupoidOfElements {G : Type u} [Groupoid.{v} G] (F : G ⥤ Type w) : @@ -169,12 +188,12 @@ theorem fromStructuredArrow_map {X Y} (f : X ⟶ Y) : /-- The equivalence between the category of elements `F.Elements` and the comma category `(*, F)`. -/ -@[simps! functor_obj functor_map inverse_obj inverse_map unitIso_hom - unitIso_inv counitIso_hom counitIso_inv] -def structuredArrowEquivalence : F.Elements ≌ StructuredArrow PUnit F := - Equivalence.mk (toStructuredArrow F) (fromStructuredArrow F) - (NatIso.ofComponents fun X => eqToIso (by aesop_cat)) - (NatIso.ofComponents fun X => StructuredArrow.isoMk (Iso.refl _)) +@[simps] +def structuredArrowEquivalence : F.Elements ≌ StructuredArrow PUnit F where + functor := toStructuredArrow F + inverse := fromStructuredArrow F + unitIso := Iso.refl _ + counitIso := Iso.refl _ open Opposite @@ -213,46 +232,18 @@ theorem fromCostructuredArrow_obj_mk (F : Cᵒᵖ ⥤ Type v) {X : C} (f : yoned (fromCostructuredArrow F).obj (op (CostructuredArrow.mk f)) = ⟨op X, yonedaEquiv.1 f⟩ := rfl -/-- The unit of the equivalence `F.Elementsᵒᵖ ≅ (yoneda, F)` is indeed iso. -/ -theorem from_toCostructuredArrow_eq (F : Cᵒᵖ ⥤ Type v) : - (toCostructuredArrow F).rightOp ⋙ fromCostructuredArrow F = 𝟭 _ := by - refine Functor.ext ?_ ?_ - · intro X - exact Functor.Elements.ext _ _ rfl (by simp [yonedaEquiv]) - · intro X Y f - have : ∀ {a b : F.Elements} (H : a = b), - (eqToHom H).1 = eqToHom (show a.fst = b.fst by cases H; rfl) := by - rintro _ _ rfl - simp - ext - simp [this] - -/-- The counit of the equivalence `F.Elementsᵒᵖ ≅ (yoneda, F)` is indeed iso. -/ -theorem to_fromCostructuredArrow_eq (F : Cᵒᵖ ⥤ Type v) : - (fromCostructuredArrow F).rightOp ⋙ toCostructuredArrow F = 𝟭 _ := by - refine Functor.ext ?_ ?_ - · intro X - cases' X with X_left X_right X_hom - cases X_right - simp only [Functor.id_obj, Functor.rightOp_obj, toCostructuredArrow_obj, Functor.comp_obj, - CostructuredArrow.mk] - congr - ext x f - convert congr_fun (X_hom.naturality f.op).symm (𝟙 X_left) - simp - · aesop - /-- The equivalence `F.Elementsᵒᵖ ≅ (yoneda, F)` given by yoneda lemma. -/ -@[simps! functor_obj functor_map inverse_obj inverse_map unitIso_inv counitIso_hom counitIso_inv] +@[simps] def costructuredArrowYonedaEquivalence (F : Cᵒᵖ ⥤ Type v) : - F.Elementsᵒᵖ ≌ CostructuredArrow yoneda F := - Equivalence.mk (toCostructuredArrow F) (fromCostructuredArrow F).rightOp - (NatIso.op (eqToIso (from_toCostructuredArrow_eq F))) (eqToIso <| to_fromCostructuredArrow_eq F) - --- Porting note: --- Running `@[simps! unitIso_hom]` is mysteriously slow. --- We separate it out to avoid needing to increase the maxHeartbeats. -attribute [simps! unitIso_hom] costructuredArrowYonedaEquivalence + F.Elementsᵒᵖ ≌ CostructuredArrow yoneda F where + functor := toCostructuredArrow F + inverse := (fromCostructuredArrow F).rightOp + unitIso := + NatIso.ofComponents + (fun X ↦ Iso.op (CategoryOfElements.isoMk _ _ (Iso.refl _) (by simp))) (by + rintro ⟨x⟩ ⟨y⟩ ⟨f : y ⟶ x⟩ + exact Quiver.Hom.unop_inj (by ext; simp)) + counitIso := NatIso.ofComponents (fun X ↦ CostructuredArrow.isoMk (Iso.refl _)) /-- The equivalence `(-.Elements)ᵒᵖ ≅ (yoneda, -)` of is actually a natural isomorphism of functors. -/ @@ -265,7 +256,7 @@ theorem costructuredArrow_yoneda_equivalence_naturality {F₁ F₂ : Cᵒᵖ ⥤ congr ext _ f simpa using congr_fun (α.naturality f.op).symm (unop X).snd - · simp [autoParam] + · simp /-- The equivalence `F.elementsᵒᵖ ≌ (yoneda, F)` is compatible with the forgetful functors. -/ @[simps!] diff --git a/Mathlib/CategoryTheory/EssentiallySmall.lean b/Mathlib/CategoryTheory/EssentiallySmall.lean index 6be51da1c9899..88de842c58417 100644 --- a/Mathlib/CategoryTheory/EssentiallySmall.lean +++ b/Mathlib/CategoryTheory/EssentiallySmall.lean @@ -61,6 +61,9 @@ noncomputable def equivSmallModel (C : Type u) [Category.{v} C] [EssentiallySmal Nonempty.some (Classical.choose_spec (Classical.choose_spec (@EssentiallySmall.equiv_smallCategory C _ _))) +instance (C : Type u) [Category.{v} C] [EssentiallySmall.{w} C] : EssentiallySmall.{w} Cᵒᵖ := + EssentiallySmall.mk' (equivSmallModel C).op + theorem essentiallySmall_congr {C : Type u} [Category.{v} C] {D : Type u'} [Category.{v'} D] (e : C ≌ D) : EssentiallySmall.{w} C ↔ EssentiallySmall.{w} D := by fconstructor @@ -164,11 +167,12 @@ noncomputable def inverse : ShrinkHoms C ⥤ C where /-- The categorical equivalence between `C` and `ShrinkHoms C`, when `C` is locally small. -/ -@[simps!] -noncomputable def equivalence : C ≌ ShrinkHoms C := - Equivalence.mk (functor C) (inverse C) - (NatIso.ofComponents fun X => Iso.refl X) - (NatIso.ofComponents fun X => Iso.refl X) +@[simps] +noncomputable def equivalence : C ≌ ShrinkHoms C where + functor := functor C + inverse := inverse C + unitIso := NatIso.ofComponents (fun _ ↦ Iso.refl _) + counitIso := NatIso.ofComponents (fun _ ↦ Iso.refl _) end ShrinkHoms diff --git a/Mathlib/CategoryTheory/Extensive.lean b/Mathlib/CategoryTheory/Extensive.lean index b4f9a69604b9d..887e41f0debb8 100644 --- a/Mathlib/CategoryTheory/Extensive.lean +++ b/Mathlib/CategoryTheory/Extensive.lean @@ -7,7 +7,7 @@ import Mathlib.CategoryTheory.Limits.Shapes.Pullback.CommSq import Mathlib.CategoryTheory.Limits.Shapes.StrictInitial import Mathlib.CategoryTheory.Limits.Shapes.Types import Mathlib.Topology.Category.TopCat.Limits.Pullbacks -import Mathlib.CategoryTheory.Limits.FunctorCategory +import Mathlib.CategoryTheory.Limits.FunctorCategory.Basic import Mathlib.CategoryTheory.Limits.Constructions.FiniteProductsOfBinaryProducts import Mathlib.CategoryTheory.Limits.VanKampen @@ -79,7 +79,7 @@ and binary coproducts are universal. -/ class FinitaryPreExtensive (C : Type u) [Category.{v} C] : Prop where [hasFiniteCoproducts : HasFiniteCoproducts C] [hasPullbacksOfInclusions : HasPullbacksOfInclusions C] - /-- In a finitary extensive category, all coproducts are van Kampen-/ + /-- In a finitary extensive category, all coproducts are van Kampen -/ universal' : ∀ {X Y : C} (c : BinaryCofan X Y), IsColimit c → IsUniversalColimit c attribute [instance] FinitaryPreExtensive.hasFiniteCoproducts @@ -90,7 +90,7 @@ and binary coproducts are van Kampen. -/ class FinitaryExtensive (C : Type u) [Category.{v} C] : Prop where [hasFiniteCoproducts : HasFiniteCoproducts C] [hasPullbacksOfInclusions : HasPullbacksOfInclusions C] - /-- In a finitary extensive category, all coproducts are van Kampen-/ + /-- In a finitary extensive category, all coproducts are van Kampen -/ van_kampen' : ∀ {X Y : C} (c : BinaryCofan X Y), IsColimit c → IsVanKampenColimit c attribute [instance] FinitaryExtensive.hasFiniteCoproducts diff --git a/Mathlib/CategoryTheory/FiberedCategory/BasedCategory.lean b/Mathlib/CategoryTheory/FiberedCategory/BasedCategory.lean index 59aa7b055409e..bfcd82955db95 100644 --- a/Mathlib/CategoryTheory/FiberedCategory/BasedCategory.lean +++ b/Mathlib/CategoryTheory/FiberedCategory/BasedCategory.lean @@ -14,7 +14,7 @@ import Mathlib.CategoryTheory.Functor.ReflectsIso In this file we define the type `BasedCategory 𝒮`, and give it the structure of a strict bicategory. Given a category `𝒮`, we define the type `BasedCategory 𝒮` as the type of categories -`𝒳` equiped with a functor `𝒳.p : 𝒳 ⥤ 𝒮`. +`𝒳` equipped with a functor `𝒳.p : 𝒳 ⥤ 𝒮`. We also define a type of functors between based categories `𝒳` and `𝒴`, which we call `BasedFunctor 𝒳 𝒴` and denote as `𝒳 ⥤ᵇ 𝒴`. These are defined as functors between the underlying @@ -222,7 +222,7 @@ def id (F : 𝒳 ⥤ᵇ 𝒴) : F ≅ F where variable {F G : 𝒳 ⥤ᵇ 𝒴} -/-- The inverse of a based natural transformation whose underlying natural tranformation is an +/-- The inverse of a based natural transformation whose underlying natural transformation is an isomorphism. -/ def mkNatIso (α : F.toFunctor ≅ G.toFunctor) (isHomLift' : ∀ a : 𝒳.obj, IsHomLift 𝒴.p (𝟙 (𝒳.p.obj a)) (α.hom.app a)) : F ≅ G where diff --git a/Mathlib/CategoryTheory/FiberedCategory/Cartesian.lean b/Mathlib/CategoryTheory/FiberedCategory/Cartesian.lean index 9f1ffd4abcba6..c2f4a20e934c0 100644 --- a/Mathlib/CategoryTheory/FiberedCategory/Cartesian.lean +++ b/Mathlib/CategoryTheory/FiberedCategory/Cartesian.lean @@ -12,6 +12,8 @@ import Mathlib.CategoryTheory.FiberedCategory.HomLift This file defines cartesian resp. strongly cartesian morphisms with respect to a functor `p : 𝒳 ⥤ 𝒮`. +This file has been adapted to `FiberedCategory/Cocartesian`, please try to change them in sync. + ## Main definitions `IsCartesian p f φ` expresses that `φ` is a cartesian morphism lying over `f` with respect to `p` in @@ -46,18 +48,26 @@ section variable {R S : 𝒮} {a b : 𝒳} (f : R ⟶ S) (φ : a ⟶ b) -/-- The proposition that a morphism `φ : a ⟶ b` in `𝒳` lying over `f : R ⟶ S` in `𝒮` is a -cartesian morphism. +/-- A morphism `φ : a ⟶ b` in `𝒳` lying over `f : R ⟶ S` in `𝒮` is cartesian if for all +morphisms `φ' : a' ⟶ b`, also lying over `f`, there exists a unique morphism `χ : a' ⟶ a` lifting +`𝟙 R` such that `φ' = χ ≫ φ`. See SGA 1 VI 5.1. -/ class IsCartesian extends IsHomLift p f φ : Prop where universal_property {a' : 𝒳} (φ' : a' ⟶ b) [IsHomLift p f φ'] : ∃! χ : a' ⟶ a, IsHomLift p (𝟙 R) χ ∧ χ ≫ φ = φ' -/-- The proposition that a morphism `φ : a ⟶ b` in `𝒳` lying over `f : R ⟶ S` in `𝒮` is a -strongly cartesian morphism. +/-- A morphism `φ : a ⟶ b` in `𝒳` lying over `f : R ⟶ S` in `𝒮` is strongly cartesian if for +all morphisms `φ' : a' ⟶ b` and all diagrams of the form +``` +a' a --φ--> b +| | | +v v v +R' --g--> R --f--> S +``` +such that `φ'` lifts `g ≫ f`, there exists a lift `χ` of `g` such that `φ' = χ ≫ φ`. -See -/ +See . -/ class IsStronglyCartesian extends IsHomLift p f φ : Prop where universal_property' {a' : 𝒳} (g : p.obj a' ⟶ R) (φ' : a' ⟶ b) [IsHomLift p (g ≫ f) φ'] : ∃! χ : a' ⟶ a, IsHomLift p g χ ∧ χ ≫ φ = φ' @@ -222,16 +232,31 @@ lemma map_self : map p f φ (id_comp f).symm φ = 𝟙 a := by apply map_uniq simp only [id_comp] -/-- When its possible to compare the two, the composition of two `IsCocartesian.map` will also be -given by a `IsCocartesian.map`. In other words, given diagrams +/-- When its possible to compare the two, the composition of two `IsStronglyCartesian.map` will also +be given by a `IsStronglyCartesian.map`. In other words, given diagrams +``` +a'' a' a --φ--> b +| | | | +v v v v +R'' --g'--> R' --g--> R --f--> S +``` +and +``` +a' --φ'--> b +| | +v v +R' --f'--> S +``` +and ``` -a'' a' a --φ--> b a' --φ'--> b a'' --φ''--> b -| | | | and | | and | | -v v v v v v v v -R'' --g'--> R' --g--> R --f--> S R' --f'--> S R'' --f''--> S +a'' --φ''--> b +| | +v v +R'' --f''--> S ``` -such that `φ` and `φ'` are strongly cartesian morphisms. Then composing the induced map from -`a'' ⟶ a'` with the induced map from `a' ⟶ a` gives the induced map from `a'' ⟶ a`. -/ +such that `φ` and `φ'` are strongly cartesian morphisms, and such that `f' = g ≫ f` and +`f'' = g' ≫ f'`. Then composing the induced map from `a'' ⟶ a'` with the induced map from +`a' ⟶ a` gives the induced map from `a'' ⟶ a`. -/ @[reassoc (attr := simp)] lemma map_comp_map {R' R'' : 𝒮} {a' a'' : 𝒳} {f' : R' ⟶ S} {f'' : R'' ⟶ S} {g : R' ⟶ R} {g' : R'' ⟶ R'} (H : f' = g ≫ f) (H' : f'' = g' ≫ f') (φ' : a' ⟶ b) (φ'' : a'' ⟶ b) diff --git a/Mathlib/CategoryTheory/FiberedCategory/Cocartesian.lean b/Mathlib/CategoryTheory/FiberedCategory/Cocartesian.lean new file mode 100644 index 0000000000000..d2e2b408959c9 --- /dev/null +++ b/Mathlib/CategoryTheory/FiberedCategory/Cocartesian.lean @@ -0,0 +1,364 @@ +/- +Copyright (c) 2024 Calle Sönne. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Calle Sönne +-/ + +import Mathlib.CategoryTheory.FiberedCategory.HomLift + +/-! +# Cocartesian morphisms + +This file defines cocartesian resp. strongly cocartesian morphisms with respect to a functor +`p : 𝒳 ⥤ 𝒮`. + +This file has been adapted from `FiberedCategory/Cartesian`, please try to change them in sync. + +## Main definitions + +`IsCocartesian p f φ` expresses that `φ` is a cocartesian morphism lying over `f : R ⟶ S` with +respect to `p`. This means that for any morphism `φ' : a ⟶ b'` lying over `f` there +is a unique morphism `τ : b ⟶ b'` lying over `𝟙 S`, such that `φ' = φ ≫ τ`. + +`IsStronglyCocartesian p f φ` expresses that `φ` is a strongly cocartesian morphism lying over `f` +with respect to `p`. + +## Implementation + +The constructor of `IsStronglyCocartesian` has been named `universal_property'`, and is mainly +intended to be used for constructing instances of this class. To use the universal property, we +generally recommended to use the lemma `IsStronglyCocartesian.universal_property` instead. The +difference between the two is that the latter is more flexible with respect to non-definitional +equalities. + +-/ + +universe v₁ v₂ u₁ u₂ + +open CategoryTheory Functor Category IsHomLift + +namespace CategoryTheory.Functor + +variable {𝒮 : Type u₁} {𝒳 : Type u₂} [Category.{v₁} 𝒮] [Category.{v₂} 𝒳] (p : 𝒳 ⥤ 𝒮) + +section + +variable {R S : 𝒮} {a b : 𝒳} (f : R ⟶ S) (φ : a ⟶ b) + +/-- A morphism `φ : a ⟶ b` in `𝒳` lying over `f : R ⟶ S` in `𝒮` is cocartesian if for all +morphisms `φ' : a ⟶ b'`, also lying over `f`, there exists a unique morphism `χ : b ⟶ b'` lifting +`𝟙 S` such that `φ' = φ ≫ χ`. -/ +class IsCocartesian extends IsHomLift p f φ : Prop where + universal_property {b' : 𝒳} (φ' : a ⟶ b') [IsHomLift p f φ'] : + ∃! χ : b ⟶ b', IsHomLift p (𝟙 S) χ ∧ φ ≫ χ = φ' + +/-- A morphism `φ : a ⟶ b` in `𝒳` lying over `f : R ⟶ S` in `𝒮` is strongly cocartesian if for +all morphisms `φ' : a ⟶ b'` and all diagrams of the form +``` +a --φ--> b b' +| | | +v v v +R --f--> S --g--> S' +``` +such that `φ'` lifts `f ≫ g`, there exists a lift `χ` of `g` such that `φ' = χ ≫ φ`. + +See . -/ +class IsStronglyCocartesian extends IsHomLift p f φ : Prop where + universal_property' {b' : 𝒳} (g : S ⟶ p.obj b') (φ' : a ⟶ b') [IsHomLift p (f ≫ g) φ'] : + ∃! χ : b ⟶ b', IsHomLift p g χ ∧ φ ≫ χ = φ' + +end + +namespace IsCocartesian + +variable {R S : 𝒮} {a b : 𝒳} (f : R ⟶ S) (φ : a ⟶ b) [IsCocartesian p f φ] + +section + +variable {b' : 𝒳} (φ' : a ⟶ b') [IsHomLift p f φ'] + +/-- Given a cocartesian morphism `φ : a ⟶ b` lying over `f : R ⟶ S` in `𝒳`, and another morphism +`φ' : a ⟶ b'` which also lifts `f`, then `IsCocartesian.map f φ φ'` is the morphism `b ⟶ b'` lying +over `𝟙 S` obtained from the universal property of `φ`. -/ +protected noncomputable def map : b ⟶ b' := + Classical.choose <| IsCocartesian.universal_property (p:=p) (f:=f) (φ:=φ) φ' + +instance map_isHomLift : IsHomLift p (𝟙 S) (IsCocartesian.map p f φ φ') := + (Classical.choose_spec <| IsCocartesian.universal_property (p:=p) (f:=f) (φ:=φ) φ').1.1 + +@[reassoc (attr := simp)] +lemma fac : φ ≫ IsCocartesian.map p f φ φ' = φ' := + (Classical.choose_spec <| IsCocartesian.universal_property (p:=p) (f:=f) (φ:=φ) φ').1.2 + +/-- Given a cocartesian morphism `φ : a ⟶ b` lying over `f : R ⟶ S` in `𝒳`, and another morphism +`φ' : a ⟶ b'` which also lifts `f`. Then any morphism `ψ : b ⟶ b'` lifting `𝟙 S` such that +`g ≫ ψ = φ'` must equal the map induced by the universal property of `φ`. -/ +lemma map_uniq (ψ : b ⟶ b') [IsHomLift p (𝟙 S) ψ] (hψ : φ ≫ ψ = φ') : + ψ = IsCocartesian.map p f φ φ' := + (Classical.choose_spec <| IsCocartesian.universal_property (p:=p) (f:=f) (φ:=φ) φ').2 + ψ ⟨inferInstance, hψ⟩ + +end + +/-- Given a cocartesian morphism `φ : a ⟶ b` lying over `f : R ⟶ S` in `𝒳`, and two morphisms +`ψ ψ' : b ⟶ b'` lifting `𝟙 S` such that `φ ≫ ψ = φ ≫ ψ'`. Then we must have `ψ = ψ'`. -/ +protected lemma ext (φ : a ⟶ b) [IsCocartesian p f φ] {b' : 𝒳} (ψ ψ' : b ⟶ b') + [IsHomLift p (𝟙 S) ψ] [IsHomLift p (𝟙 S) ψ'] (h : φ ≫ ψ = φ ≫ ψ') : ψ = ψ' := by + rw [map_uniq p f φ (φ ≫ ψ) ψ rfl, map_uniq p f φ (φ ≫ ψ) ψ' h.symm] + +@[simp] +lemma map_self : IsCocartesian.map p f φ φ = 𝟙 b := by + subst_hom_lift p f φ; symm + apply map_uniq + simp only [comp_id] + +/-- The canonical isomorphism between the codomains of two cocartesian morphisms +lying over the same object. -/ +noncomputable def codomainUniqueUpToIso {b' : 𝒳} (φ' : a ⟶ b') [IsCocartesian p f φ'] : + b ≅ b' where + hom := IsCocartesian.map p f φ φ' + inv := IsCocartesian.map p f φ' φ + hom_inv_id := by + subst_hom_lift p f φ + apply IsCocartesian.ext p (p.map φ) φ + simp only [fac_assoc, fac, comp_id] + inv_hom_id := by + subst_hom_lift p f φ' + apply IsCocartesian.ext p (p.map φ') φ' + simp only [fac_assoc, fac, comp_id] + +/-- Postcomposing a cocartesian morphism with an isomorphism lifting the identity is cocartesian. -/ +instance of_comp_iso {b' : 𝒳} (φ' : b ≅ b') [IsHomLift p (𝟙 S) φ'.hom] : + IsCocartesian p f (φ ≫ φ'.hom) where + universal_property := by + intro c ψ hψ + use φ'.inv ≫ IsCocartesian.map p f φ ψ + refine ⟨⟨inferInstance, by simp⟩, ?_⟩ + rintro τ ⟨hτ₁, hτ₂⟩ + rw [Iso.eq_inv_comp] + apply map_uniq + exact ((assoc φ _ _) ▸ hτ₂) + +/-- Precomposing a cocartesian morphism with an isomorphism lifting the identity is cocartesian. -/ +instance of_iso_comp {a' : 𝒳} (φ' : a' ≅ a) [IsHomLift p (𝟙 R) φ'.hom] : + IsCocartesian p f (φ'.hom ≫ φ) where + universal_property := by + intro c ψ hψ + use IsCocartesian.map p f φ (φ'.inv ≫ ψ) + refine ⟨⟨inferInstance, by simp⟩, ?_⟩ + rintro τ ⟨hτ₁, hτ₂⟩ + apply map_uniq + simp only [Iso.eq_inv_comp, ← assoc, hτ₂] + +end IsCocartesian + +namespace IsStronglyCocartesian + +section + +variable {R S : 𝒮} {a b : 𝒳} (f : R ⟶ S) (φ : a ⟶ b) [IsStronglyCocartesian p f φ] + +/-- The universal property of a strongly cocartesian morphism. + +This lemma is more flexible with respect to non-definitional equalities than the field +`universal_property'` of `IsStronglyCocartesian`. -/ +lemma universal_property {S' : 𝒮} {b' : 𝒳} (g : S ⟶ S') (f' : R ⟶ S') (hf' : f' = f ≫ g) + (φ' : a ⟶ b') [IsHomLift p f' φ'] : ∃! χ : b ⟶ b', IsHomLift p g χ ∧ φ ≫ χ = φ' := by + subst_hom_lift p f' φ'; clear a b R S + have : p.IsHomLift (f ≫ g) φ' := (hf' ▸ inferInstance) + apply IsStronglyCocartesian.universal_property' f + +instance isCocartesian_of_isStronglyCocartesian [p.IsStronglyCocartesian f φ] : + p.IsCocartesian f φ where + universal_property := fun φ' => universal_property p f φ (𝟙 S) f (comp_id f).symm φ' + +section + +variable {S' : 𝒮} {b' : 𝒳} {g : S ⟶ S'} {f' : R ⟶ S'} (hf' : f' = f ≫ g) (φ' : a ⟶ b') + [IsHomLift p f' φ'] + +/-- Given a diagram +``` +a --φ--> b b' +| | | +v v v +R --f--> S --g--> S' +``` +such that `φ` is strongly cocartesian, and a morphism `φ' : a ⟶ b'`. Then `map` is the map +`b ⟶ b'` lying over `g` obtained from the universal property of `φ`. -/ +noncomputable def map : b ⟶ b' := + Classical.choose <| universal_property p f φ _ _ hf' φ' + +instance map_isHomLift : IsHomLift p g (map p f φ hf' φ') := + (Classical.choose_spec <| universal_property p f φ _ _ hf' φ').1.1 + +@[reassoc (attr := simp)] +lemma fac : φ ≫ (map p f φ hf' φ') = φ' := + (Classical.choose_spec <| universal_property p f φ _ _ hf' φ').1.2 + + +/-- Given a diagram +``` +a --φ--> b b' +| | | +v v v +R --f--> S --g--> S' +``` +such that `φ` is strongly cocartesian, and morphisms `φ' : a ⟶ b'`, `ψ : b ⟶ b'` such that +`g ≫ ψ = φ'`. Then `ψ` is the map induced by the universal property. -/ +lemma map_uniq (ψ : b ⟶ b') [IsHomLift p g ψ] (hψ : φ ≫ ψ = φ') : ψ = map p f φ hf' φ' := + (Classical.choose_spec <| universal_property p f φ _ _ hf' φ').2 ψ ⟨inferInstance, hψ⟩ + +end + +/-- Given a diagram +``` +a --φ--> b b' +| | | +v v v +R --f--> S --g--> S' +``` +such that `φ` is strongly cocartesian, and morphisms `ψ ψ' : b ⟶ b'` such that +`g ≫ ψ = φ' = g ≫ ψ'`. Then we have that `ψ = ψ'`. -/ +protected lemma ext (φ : a ⟶ b) [IsStronglyCocartesian p f φ] {S' : 𝒮} {b' : 𝒳} (g : S ⟶ S') + {ψ ψ' : b ⟶ b'} [IsHomLift p g ψ] [IsHomLift p g ψ'] (h : φ ≫ ψ = φ ≫ ψ') : ψ = ψ' := by + rw [map_uniq p f φ (g := g) rfl (φ ≫ ψ) ψ rfl, map_uniq p f φ (g := g) rfl (φ ≫ ψ) ψ' h.symm] + +@[simp] +lemma map_self : map p f φ (comp_id f).symm φ = 𝟙 b := by + subst_hom_lift p f φ; symm + apply map_uniq + simp only [comp_id] + +/-- When its possible to compare the two, the composition of two `IsStronglyCocartesian.map` will +also be given by a `IsStronglyCocartesian.map`. In other words, given diagrams +``` +a --φ--> b b' b'' +| | | | +v v v v +R --f--> S --g--> S' --g'--> S' +``` +and +``` +a --φ'--> b' +| | +v v +R --f'--> S' + +``` +and +``` +a --φ''--> b'' +| | +v v +R --f''--> S'' +``` +such that `φ` and `φ'` are strongly cocartesian morphisms, and such that `f' = f ≫ g` and +`f'' = f' ≫ g'`. Then composing the induced map from `b ⟶ b'` with the induced map from +`b' ⟶ b''` gives the induced map from `b ⟶ b''`. -/ +@[reassoc (attr := simp)] +lemma map_comp_map {S' S'' : 𝒮} {b' b'' : 𝒳} {f' : R ⟶ S'} {f'' : R ⟶ S''} {g : S ⟶ S'} + {g' : S' ⟶ S''} (H : f' = f ≫ g) (H' : f'' = f' ≫ g') (φ' : a ⟶ b') (φ'' : a ⟶ b'') + [IsStronglyCocartesian p f' φ'] [IsHomLift p f'' φ''] : + map p f φ H φ' ≫ map p f' φ' H' φ'' = + map p f φ (show f'' = f ≫ (g ≫ g') by rwa [← assoc, ← H]) φ'' := by + apply map_uniq p f φ + simp only [fac_assoc, fac] + +end + +section + +variable {R S T : 𝒮} {a b c : 𝒳} {f : R ⟶ S} {g : S ⟶ T} {φ : a ⟶ b} {ψ : b ⟶ c} + +/-- Given two strongly cocartesian morphisms `φ`, `ψ` as follows +``` +a --φ--> b --ψ--> c +| | | +v v v +R --f--> S --g--> T +``` +Then the composite `φ ≫ ψ` is also strongly cocartesian. -/ +instance comp [IsStronglyCocartesian p f φ] [IsStronglyCocartesian p g ψ] : + IsStronglyCocartesian p (f ≫ g) (φ ≫ ψ) where + universal_property' := by + intro c' h τ hτ + use map p g ψ (f' := g ≫ h) rfl <| map p f φ (assoc f g h) τ + refine ⟨⟨inferInstance, ?_⟩, ?_⟩ + · simp only [assoc, fac] + · intro π' ⟨hπ'₁, hπ'₂⟩ + apply map_uniq + apply map_uniq + simp only [← hπ'₂, assoc] + +/-- Given two commutative squares +``` +a --φ--> b --ψ--> c +| | | +v v v +R --f--> S --g--> T +``` +such that `φ ≫ ψ` and `φ` are strongly cocartesian, then so is `ψ`. -/ +protected lemma of_comp [IsStronglyCocartesian p f φ] [IsStronglyCocartesian p (f ≫ g) (φ ≫ ψ)] + [IsHomLift p g ψ] : IsStronglyCocartesian p g ψ where + universal_property' := by + intro c' h τ hτ + have h₁ : IsHomLift p (f ≫ g ≫ h) (φ ≫ τ) := by simpa using IsHomLift.comp p f (g ≫ h) φ τ + /- We get a morphism `π : c ⟶ c'` such that `(φ ≫ ψ) ≫ π = φ ≫ τ` from the universal property + of `φ ≫ ψ`. This will be the morphism induced by `φ`. -/ + use map p (f ≫ g) (φ ≫ ψ) (f' := f ≫ g ≫ h) (assoc f g h).symm (φ ≫ τ) + refine ⟨⟨inferInstance, ?_⟩, ?_⟩ + /- The fact that `ψ ≫ π = τ` follows from `φ ≫ ψ ≫ π = φ ≫ τ` and the universal property of + `φ`. -/ + · apply IsStronglyCocartesian.ext p f φ (g ≫ h) <| by simp only [← assoc, fac] + -- Finally, uniqueness of `π` comes from the universal property of `φ ≫ ψ`. + · intro π' ⟨hπ'₁, hπ'₂⟩ + apply map_uniq + simp [hπ'₂.symm] + +end + +section + +variable {R S : 𝒮} {a b : 𝒳} (f : R ⟶ S) + +instance of_iso (φ : a ≅ b) [IsHomLift p f φ.hom] : IsStronglyCocartesian p f φ.hom where + universal_property' := by + intro b' g τ hτ + use φ.inv ≫ τ + refine ⟨?_, by aesop_cat⟩ + simpa [← assoc] using (IsHomLift.comp p (isoOfIsoLift p f φ).inv (f ≫ g) φ.inv τ) + +instance of_isIso (φ : a ⟶ b) [IsHomLift p f φ] [IsIso φ] : IsStronglyCocartesian p f φ := + @IsStronglyCocartesian.of_iso _ _ _ _ p _ _ _ _ f (asIso φ) (by aesop) + +/-- A strongly cocartesian arrow lying over an isomorphism is an isomorphism. -/ +lemma isIso_of_base_isIso (φ : a ⟶ b) [IsStronglyCocartesian p f φ] [IsIso f] : IsIso φ := by + subst_hom_lift p f φ; clear a b R S + -- Let `φ'` be the morphism induced by applying universal property to `𝟙 a` lying over `f ≫ f⁻¹`. + let φ' := map p (p.map φ) φ (IsIso.hom_inv_id (p.map φ)).symm (𝟙 a) + use φ' + -- `φ ≫ φ' = 𝟙 a` follows immediately from the universal property. + have inv_hom : φ ≫ φ' = 𝟙 a := fac p (p.map φ) φ _ (𝟙 a) + refine ⟨inv_hom, ?_⟩ + -- We will now show that `φ' ≫ φ = 𝟙 b` by showing that `φ ≫ (φ' ≫ φ) = φ ≫ 𝟙 b`. + have h₁ : IsHomLift p (𝟙 (p.obj b)) (φ' ≫ φ) := by + rw [← IsIso.inv_hom_id (p.map φ)] + apply IsHomLift.comp + apply IsStronglyCocartesian.ext p (p.map φ) φ (𝟙 (p.obj b)) + simp only [← assoc, inv_hom, comp_id, id_comp] + +end + +/-- The canonical isomorphism between the codomains of two strongly cocartesian arrows lying over +isomorphic objects. -/ +noncomputable def codomainIsoOfBaseIso {R S S' : 𝒮} {a b b' : 𝒳} {f : R ⟶ S} {f' : R ⟶ S'} + {g : S ≅ S'} (h : f' = f ≫ g.hom) (φ : a ⟶ b) (φ' : a ⟶ b') [IsStronglyCocartesian p f φ] + [IsStronglyCocartesian p f' φ'] : b ≅ b' where + hom := map p f φ h φ' + inv := @map _ _ _ _ p _ _ _ _ f' φ' _ _ _ _ _ (congrArg (· ≫ g.inv) h.symm) φ + (by simp; infer_instance) + +end IsStronglyCocartesian + +end CategoryTheory.Functor diff --git a/Mathlib/CategoryTheory/FiberedCategory/HomLift.lean b/Mathlib/CategoryTheory/FiberedCategory/HomLift.lean index d8ac3d794f3a7..f98c7a397dccd 100644 --- a/Mathlib/CategoryTheory/FiberedCategory/HomLift.lean +++ b/Mathlib/CategoryTheory/FiberedCategory/HomLift.lean @@ -18,7 +18,7 @@ does not make sense when the domain and/or codomain of `φ` and `f` are not defi ## Main definition Given morphism `φ : a ⟶ b` in `𝒳` and `f : R ⟶ S` in `𝒮`, `p.IsHomLift f φ` is a class, defined -using the auxillary inductive type `IsHomLiftAux` which expresses the fact that `f = p(φ)`. +using the auxiliary inductive type `IsHomLiftAux` which expresses the fact that `f = p(φ)`. We also define a macro `subst_hom_lift p f φ` which can be used to substitute `f` with `p(φ)` in a goal, this tactic is just short for `obtain ⟨⟩ := Functor.IsHomLift.cond (p:=p) (f:=f) (φ:=φ)`, and diff --git a/Mathlib/CategoryTheory/Filtered/Small.lean b/Mathlib/CategoryTheory/Filtered/Small.lean index 7948241296129..5206fd8c67956 100644 --- a/Mathlib/CategoryTheory/Filtered/Small.lean +++ b/Mathlib/CategoryTheory/Filtered/Small.lean @@ -56,11 +56,11 @@ namespace FilteredClosureSmall in `C`. This would require some kind of inductive-recursive definition, which Lean does not allow. Our solution is to define a function `ℕ → Σ t : Type (max v w), t → C` by (strong) induction and then take the union over all natural numbers, mimicking what one would do in a - set-theoretic setting. -/ + set-theoretic setting. -/ /-- One step of the inductive procedure consists of adjoining all maxima and coequalizers of all objects and morphisms obtained so far. This is quite redundant, picking up many objects which we - already hit in earlier iterations, but this is easier to work with later. -/ + already hit in earlier iterations, but this is easier to work with later. -/ private inductive InductiveStep (n : ℕ) (X : ∀ (k : ℕ), k < n → Σ t : Type (max v w), t → C) : Type (max v w) | max : {k k' : ℕ} → (hk : k < n) → (hk' : k' < n) → (X _ hk).1 → (X _ hk').1 → InductiveStep n X @@ -78,7 +78,7 @@ private noncomputable def inductiveStepRealization (n : ℕ) as a function of `ℕ`. The function is defined by well-founded recursion, but we really want to use its - definitional equalities in the proofs below, so lets make it semireducible. -/ + definitional equalities in the proofs below, so lets make it semireducible. -/ @[semireducible] private noncomputable def bundledAbstractFilteredClosure : ℕ → Σ t : Type (max v w), t → C | 0 => ⟨ULift.{v} α, f ∘ ULift.down⟩ @@ -211,7 +211,7 @@ private noncomputable def inductiveStepRealization (n : ℕ) `EssentiallySmall.{max v w} (FullSubcategory (CofilteredClosure f))`. The function is defined by well-founded recursion, but we really want to use its - definitional equalities in the proofs below, so lets make it semireducible. -/ + definitional equalities in the proofs below, so lets make it semireducible. -/ @[semireducible] private noncomputable def bundledAbstractCofilteredClosure : ℕ → Σ t : Type (max v w), t → C | 0 => ⟨ULift.{v} α, f ∘ ULift.down⟩ diff --git a/Mathlib/CategoryTheory/FinCategory/AsType.lean b/Mathlib/CategoryTheory/FinCategory/AsType.lean index 714344cab1db2..9d42330a17b22 100644 --- a/Mathlib/CategoryTheory/FinCategory/AsType.lean +++ b/Mathlib/CategoryTheory/FinCategory/AsType.lean @@ -61,10 +61,11 @@ noncomputable def objAsTypeToAsType : ObjAsType α ⥤ AsType α where map {X Y} := Fintype.equivFin _ /-- The constructed category (`AsType α`) is equivalent to `ObjAsType α`. -/ -noncomputable def asTypeEquivObjAsType : AsType α ≌ ObjAsType α := - Equivalence.mk (asTypeToObjAsType α) (objAsTypeToAsType α) - (NatIso.ofComponents Iso.refl) - (NatIso.ofComponents Iso.refl) +noncomputable def asTypeEquivObjAsType : AsType α ≌ ObjAsType α where + functor := asTypeToObjAsType α + inverse := objAsTypeToAsType α + unitIso := NatIso.ofComponents Iso.refl + counitIso := NatIso.ofComponents Iso.refl noncomputable instance asTypeFinCategory : FinCategory (AsType α) where fintypeHom := fun _ _ => show Fintype (Fin _) from inferInstance diff --git a/Mathlib/CategoryTheory/FullSubcategory.lean b/Mathlib/CategoryTheory/FullSubcategory.lean index 49bfb77d86356..8aa58d273b2d2 100644 --- a/Mathlib/CategoryTheory/FullSubcategory.lean +++ b/Mathlib/CategoryTheory/FullSubcategory.lean @@ -97,9 +97,9 @@ See . We do not define 'strictly full -/ @[ext] structure FullSubcategory where - /-- The category of which this is a full subcategory-/ + /-- The category of which this is a full subcategory -/ obj : C - /-- The predicate satisfied by all objects in this subcategory-/ + /-- The predicate satisfied by all objects in this subcategory -/ property : Z obj instance FullSubcategory.category : Category.{v} (FullSubcategory Z) := diff --git a/Mathlib/CategoryTheory/Functor/Currying.lean b/Mathlib/CategoryTheory/Functor/Currying.lean index c5a8da1caf5d5..caa5be9b7f6d8 100644 --- a/Mathlib/CategoryTheory/Functor/Currying.lean +++ b/Mathlib/CategoryTheory/Functor/Currying.lean @@ -76,12 +76,16 @@ def curry : (C × D ⥤ E) ⥤ C ⥤ D ⥤ E where /-- The equivalence of functor categories given by currying/uncurrying. -/ @[simps!] -def currying : C ⥤ D ⥤ E ≌ C × D ⥤ E := - Equivalence.mk uncurry curry - (NatIso.ofComponents fun F => - NatIso.ofComponents fun X => NatIso.ofComponents fun Y => Iso.refl _) - (NatIso.ofComponents fun F => NatIso.ofComponents (fun X => eqToIso (by simp)) - (by intros X Y f; cases X; cases Y; cases f; dsimp at *; rw [← F.map_comp]; simp)) +def currying : C ⥤ D ⥤ E ≌ C × D ⥤ E where + functor := uncurry + inverse := curry + unitIso := NatIso.ofComponents (fun _ ↦ NatIso.ofComponents + (fun _ ↦ NatIso.ofComponents (fun _ ↦ Iso.refl _))) + counitIso := NatIso.ofComponents + (fun F ↦ NatIso.ofComponents (fun _ ↦ Iso.refl _) (by + rintro ⟨X₁, X₂⟩ ⟨Y₁, Y₂⟩ ⟨f₁, f₂⟩ + dsimp at f₁ f₂ ⊢ + simp only [← F.map_comp, prod_comp, Category.comp_id, Category.id_comp])) /-- `F.flip` is isomorphic to uncurrying `F`, swapping the variables, and currying. -/ @[simps!] diff --git a/Mathlib/CategoryTheory/Functor/Derived/RightDerived.lean b/Mathlib/CategoryTheory/Functor/Derived/RightDerived.lean index c926a1b32013f..8acc96f8e2d2d 100644 --- a/Mathlib/CategoryTheory/Functor/Derived/RightDerived.lean +++ b/Mathlib/CategoryTheory/Functor/Derived/RightDerived.lean @@ -97,7 +97,7 @@ lemma rightDerived_ext (G : D ⥤ H) (γ₁ γ₂ : RF ⟶ G) RF.hom_ext_of_isLeftKanExtension α γ₁ γ₂ hγ /-- The natural transformation `RF ⟶ RF'` on right derived functors that is -induced by a natural transformation `F ⟶ F'`. -/ +induced by a natural transformation `F ⟶ F'`. -/ noncomputable def rightDerivedNatTrans (τ : F ⟶ F') : RF ⟶ RF' := RF.rightDerivedDesc α W RF' (τ ≫ α') @@ -128,7 +128,7 @@ lemma rightDerivedNatTrans_comp (τ : F ⟶ F') (τ' : F' ⟶ F'') : rightDerived_ext RF α W _ _ _ (by aesop_cat) /-- The natural isomorphism `RF ≅ RF'` on right derived functors that is -induced by a natural isomorphism `F ≅ F'`. -/ +induced by a natural isomorphism `F ≅ F'`. -/ @[simps] noncomputable def rightDerivedNatIso (τ : F ≅ F') : RF ≅ RF' where diff --git a/Mathlib/CategoryTheory/Functor/FullyFaithful.lean b/Mathlib/CategoryTheory/Functor/FullyFaithful.lean index a637719323dad..cbc95c08b955f 100644 --- a/Mathlib/CategoryTheory/Functor/FullyFaithful.lean +++ b/Mathlib/CategoryTheory/Functor/FullyFaithful.lean @@ -171,6 +171,15 @@ lemma full : F.Full where lemma faithful : F.Faithful where map_injective := hF.map_injective +instance : Subsingleton F.FullyFaithful where + allEq h₁ h₂ := by + have := h₁.faithful + cases h₁ with | mk f₁ hf₁ _ => cases h₂ with | mk f₂ hf₂ _ => + simp only [Functor.FullyFaithful.mk.injEq] + ext + apply F.map_injective + rw [hf₁, hf₂] + /-- The unique isomorphism `X ≅ Y` which induces an isomorphism `F.obj X ≅ F.obj Y` when `hF : F.FullyFaithful`. -/ @[simps] @@ -240,7 +249,7 @@ variable {D : Type u₂} [Category.{v₂} D] {E : Type u₃} [Category.{v₃} E] variable (F F' : C ⥤ D) (G : D ⥤ E) instance Faithful.comp [F.Faithful] [G.Faithful] : - (F ⋙ G).Faithful where map_injective p := F.map_injective (G.map_injective p) + (F ⋙ G).Faithful where map_injective p := F.map_injective (G.map_injective p) theorem Faithful.of_comp [(F ⋙ G).Faithful] : F.Faithful := -- Porting note: (F ⋙ G).map_injective.of_comp has the incorrect type diff --git a/Mathlib/CategoryTheory/Galois/GaloisObjects.lean b/Mathlib/CategoryTheory/Galois/GaloisObjects.lean index 1ceed246f266d..5196d8d135625 100644 --- a/Mathlib/CategoryTheory/Galois/GaloisObjects.lean +++ b/Mathlib/CategoryTheory/Galois/GaloisObjects.lean @@ -83,7 +83,7 @@ theorem isGalois_iff_pretransitive (X : C) [IsConnected X] : rw [isGalois_iff_aux, Equiv.nonempty_congr <| quotientByAutTerminalEquivUniqueQuotient F X] exact (MulAction.pretransitive_iff_unique_quotient_of_nonempty (Aut X) (F.obj X)).symm -/-- If `X` is Galois, the quotient `X / Aut X` is terminal. -/ +/-- If `X` is Galois, the quotient `X / Aut X` is terminal. -/ noncomputable def isTerminalQuotientOfIsGalois (X : C) [IsGalois X] : IsTerminal <| colimit <| SingleObj.functor <| Aut.toEnd X := Nonempty.some IsGalois.quotientByAutTerminal diff --git a/Mathlib/CategoryTheory/Galois/Prorepresentability.lean b/Mathlib/CategoryTheory/Galois/Prorepresentability.lean index f8261a14065e9..ad4a6eb3b3032 100644 --- a/Mathlib/CategoryTheory/Galois/Prorepresentability.lean +++ b/Mathlib/CategoryTheory/Galois/Prorepresentability.lean @@ -6,7 +6,7 @@ Authors: Christian Merten import Mathlib.Algebra.Category.Grp.Limits import Mathlib.CategoryTheory.CofilteredSystem import Mathlib.CategoryTheory.Galois.Decomposition -import Mathlib.CategoryTheory.Limits.FunctorCategory +import Mathlib.CategoryTheory.Limits.FunctorCategory.Basic import Mathlib.CategoryTheory.Limits.IndYoneda import Mathlib.CategoryTheory.Limits.Preserves.Ulift @@ -189,7 +189,7 @@ noncomputable def autGaloisSystem : PointedGaloisObject F ⥤ Grp.{u₂} where ext (σ : Aut A.obj) simp -/-- The limit of `autGaloisSystem`. -/ +/-- The limit of `autGaloisSystem`. -/ noncomputable def AutGalois : Type (max u₁ u₂) := (autGaloisSystem F ⋙ forget _).sections @@ -246,7 +246,7 @@ We first establish the isomorphism between `End F` and `AutGalois F`, from which - `endEquivSectionsFibers : End F ≅ (incl F ⋙ F').sections`: the endomorphisms of `F` are isomorphic to the limit over `F.obj A` for all Galois objects `A`. - This is obtained as the composition (slighty simplified): + This is obtained as the composition (slightly simplified): `End F ≅ (colimit ((incl F).op ⋙ coyoneda) ⟶ F) ≅ (incl F ⋙ F).sections` diff --git a/Mathlib/CategoryTheory/Generator.lean b/Mathlib/CategoryTheory/Generator.lean index c6219a587e428..f4689ea78b469 100644 --- a/Mathlib/CategoryTheory/Generator.lean +++ b/Mathlib/CategoryTheory/Generator.lean @@ -310,7 +310,8 @@ theorem wellPowered_of_isDetecting [HasPullbacks C] {𝒢 : Set C} [Small.{v₁} (h𝒢 : IsDetecting 𝒢) : WellPowered C := ⟨fun X => @small_of_injective _ _ _ (fun P : Subobject X => { f : ΣG : 𝒢, G.1 ⟶ X | P.Factors f.2 }) - fun P Q h => Subobject.eq_of_isDetecting h𝒢 _ _ (by simpa [Set.ext_iff] using h)⟩ + fun P Q h => Subobject.eq_of_isDetecting h𝒢 _ _ + (by simpa [Set.ext_iff, Sigma.forall] using h)⟩ end WellPowered diff --git a/Mathlib/CategoryTheory/GradedObject/Monoidal.lean b/Mathlib/CategoryTheory/GradedObject/Monoidal.lean index 88a32f2bf3bcd..917484d456465 100644 --- a/Mathlib/CategoryTheory/GradedObject/Monoidal.lean +++ b/Mathlib/CategoryTheory/GradedObject/Monoidal.lean @@ -292,7 +292,14 @@ lemma associator_naturality (f₁ : X₁ ⟶ Y₁) (f₂ : X₂ ⟶ Y₂) (f₃ [HasGoodTensor₁₂Tensor X₁ X₂ X₃] [HasGoodTensorTensor₂₃ X₁ X₂ X₃] [HasGoodTensor₁₂Tensor Y₁ Y₂ Y₃] [HasGoodTensorTensor₂₃ Y₁ Y₂ Y₃] : tensorHom (tensorHom f₁ f₂) f₃ ≫ (associator Y₁ Y₂ Y₃).hom = - (associator X₁ X₂ X₃).hom ≫ tensorHom f₁ (tensorHom f₂ f₃) := by aesop_cat + (associator X₁ X₂ X₃).hom ≫ tensorHom f₁ (tensorHom f₂ f₃) := by + #adaptation_note + /-- this used to be aesop_cat, but that broke with + https://github.com/leanprover/lean4/pull/4154 -/ + ext x i₁ i₂ i₃ h : 2 + simp only [categoryOfGradedObjects_comp, ιTensorObj₃'_tensorHom_assoc, + associator_conjugation, ιTensorObj₃'_associator_hom, assoc, Iso.inv_hom_id_assoc, + ιTensorObj₃'_associator_hom_assoc, ιTensorObj₃_tensorHom] end @@ -399,10 +406,10 @@ lemma pentagon_inv : tensorHom (associator X₁ X₂ X₃).inv (𝟙 X₄) = (associator X₁ X₂ (tensorObj X₃ X₄)).inv ≫ (associator (tensorObj X₁ X₂) X₃ X₄).inv := by ext j i₁ i₂ i₃ i₄ h - dsimp + dsimp only [categoryOfGradedObjects_comp] conv_lhs => rw [ιTensorObj₄_eq X₁ X₂ X₃ X₄ i₁ i₂ i₃ i₄ j h _ rfl, assoc, ι_tensorHom_assoc] - dsimp + dsimp only [categoryOfGradedObjects_id, id_eq, eq_mpr_eq_cast, cast_eq] rw [id_tensorHom, ← MonoidalCategory.whiskerLeft_comp_assoc, ιTensorObj₃_associator_inv, ιTensorObj₃'_eq X₂ X₃ X₄ i₂ i₃ i₄ _ rfl _ rfl, MonoidalCategory.whiskerLeft_comp_assoc, MonoidalCategory.whiskerLeft_comp_assoc, @@ -410,7 +417,7 @@ lemma pentagon_inv : (by simp only [← add_assoc, h]) _ rfl, ιTensorObj₃_associator_inv_assoc, ιTensorObj₃'_eq_assoc X₁ (tensorObj X₂ X₃) X₄ i₁ (i₂ + i₃) i₄ j (by simp only [← add_assoc, h]) (i₁ + i₂ + i₃) (by rw [add_assoc]), ι_tensorHom] - dsimp + dsimp only [id_eq, eq_mpr_eq_cast, categoryOfGradedObjects_id] rw [tensorHom_id, whisker_assoc_symm_assoc, Iso.hom_inv_id_assoc, ← MonoidalCategory.comp_whiskerRight_assoc, ← MonoidalCategory.comp_whiskerRight_assoc, ← ιTensorObj₃_eq X₁ X₂ X₃ i₁ i₂ i₃ _ rfl _ rfl, ιTensorObj₃_associator_inv, diff --git a/Mathlib/CategoryTheory/GradedObject/Trifunctor.lean b/Mathlib/CategoryTheory/GradedObject/Trifunctor.lean index fa00a95c23594..1c901601ac535 100644 --- a/Mathlib/CategoryTheory/GradedObject/Trifunctor.lean +++ b/Mathlib/CategoryTheory/GradedObject/Trifunctor.lean @@ -215,13 +215,17 @@ noncomputable def mapTrifunctorMapFunctorObj (X₁ : GradedObject I₁ C₁) NatTrans.id_app, categoryOfGradedObjects_comp, Functor.map_comp, NatTrans.comp_app, id_comp, assoc, ι_mapTrifunctorMapMap_assoc] +#adaptation_note +/-- +At nightly-2024-08-08 we needed to significantly increase the maxHeartbeats here. +-/ +set_option maxHeartbeats 800000 in /-- Given a trifunctor `F : C₁ ⥤ C₂ ⥤ C₃ ⥤ C₄` and a map `p : I₁ × I₂ × I₃ → J`, this is the functor `GradedObject I₁ C₁ ⥤ GradedObject I₂ C₂ ⥤ GradedObject I₃ C₃ ⥤ GradedObject J C₄` sending `X₁ : GradedObject I₁ C₁`, `X₂ : GradedObject I₂ C₂` and `X₃ : GradedObject I₃ C₃` to the `J`-graded object sending `j` to the coproduct of `((F.obj (X₁ i₁)).obj (X₂ i₂)).obj (X₃ i₃)` for `p ⟨i₁, i₂, i₃⟩ = j`. -/ -@[simps] noncomputable def mapTrifunctorMap [∀ X₁ X₂ X₃, HasMap ((((mapTrifunctor F I₁ I₂ I₃).obj X₁).obj X₂).obj X₃) p] : GradedObject I₁ C₁ ⥤ GradedObject I₂ C₂ ⥤ GradedObject I₃ C₃ ⥤ GradedObject J C₄ where @@ -243,6 +247,8 @@ noncomputable def mapTrifunctorMap NatTrans.id_app, ι_mapTrifunctorMapMap, id_comp, NatTrans.naturality_app_assoc] } +attribute [simps] mapTrifunctorMap + end section @@ -268,7 +274,7 @@ variable {r} (ρ₁₂ : BifunctorComp₁₂IndexData r) /-- Given bifunctors `F₁₂ : C₁ ⥤ C₂ ⥤ C₁₂`, `G : C₁₂ ⥤ C₃ ⥤ C₄`, graded objects `X₁ : GradedObject I₁ C₁`, `X₂ : GradedObject I₂ C₂`, `X₃ : GradedObject I₃ C₃` and `ρ₁₂ : BifunctorComp₁₂IndexData r`, this asserts that for all `i₁₂ : ρ₁₂.I₁₂` and `i₃ : I₃`, -the functor `G(-, X₃ i₃)` commutes wich the coproducts of the `F₁₂(X₁ i₁, X₂ i₂)` +the functor `G(-, X₃ i₃)` commutes with the coproducts of the `F₁₂(X₁ i₁, X₂ i₂)` such that `ρ₁₂.p ⟨i₁, i₂⟩ = i₁₂`. -/ abbrev HasGoodTrifunctor₁₂Obj := ∀ (i₁₂ : ρ₁₂.I₁₂) (i₃ : I₃), PreservesColimit @@ -361,7 +367,7 @@ section variable [HasMap ((((mapTrifunctor (bifunctorComp₁₂ F₁₂ G) I₁ I₂ I₃).obj X₁).obj X₂).obj X₃) r] /-- The action on graded objects of a trifunctor obtained by composition of two -bifunctors can be computed as a composition of the actions of these two bifunctors. -/ +bifunctors can be computed as a composition of the actions of these two bifunctors. -/ noncomputable def mapBifunctorComp₁₂MapObjIso : mapTrifunctorMapObj (bifunctorComp₁₂ F₁₂ G) r X₁ X₂ X₃ ≅ mapBifunctorMapObj G ρ₁₂.q (mapBifunctorMapObj F₁₂ ρ₁₂.p X₁ X₂) X₃ := @@ -448,7 +454,7 @@ variable {r} (ρ₂₃ : BifunctorComp₂₃IndexData r) /-- Given bifunctors `F : C₁ ⥤ C₂₃ ⥤ C₄`, `G₂₃ : C₂ ⥤ C₃ ⥤ C₂₃`, graded objects `X₁ : GradedObject I₁ C₁`, `X₂ : GradedObject I₂ C₂`, `X₃ : GradedObject I₃ C₃` and `ρ₂₃ : BifunctorComp₂₃IndexData r`, this asserts that for all `i₁ : I₁` and `i₂₃ : ρ₂₃.I₂₃`, -the functor `F(X₁ i₁, _)` commutes wich the coproducts of the `G₂₃(X₂ i₂, X₃ i₃)` +the functor `F(X₁ i₁, _)` commutes with the coproducts of the `G₂₃(X₂ i₂, X₃ i₃)` such that `ρ₂₃.p ⟨i₂, i₃⟩ = i₂₃`. -/ abbrev HasGoodTrifunctor₂₃Obj := ∀ (i₁ : I₁) (i₂₃ : ρ₂₃.I₂₃), PreservesColimit (Discrete.functor @@ -539,7 +545,7 @@ section variable [HasMap ((((mapTrifunctor (bifunctorComp₂₃ F G₂₃) I₁ I₂ I₃).obj X₁).obj X₂).obj X₃) r] /-- The action on graded objects of a trifunctor obtained by composition of two -bifunctors can be computed as a composition of the actions of these two bifunctors. -/ +bifunctors can be computed as a composition of the actions of these two bifunctors. -/ noncomputable def mapBifunctorComp₂₃MapObjIso : mapTrifunctorMapObj (bifunctorComp₂₃ F G₂₃) r X₁ X₂ X₃ ≅ mapBifunctorMapObj F ρ₂₃.q X₁ (mapBifunctorMapObj G₂₃ ρ₂₃.p X₂ X₃) := diff --git a/Mathlib/CategoryTheory/Grothendieck.lean b/Mathlib/CategoryTheory/Grothendieck.lean index a4c2ef1ad1a44..60f2b56671b81 100644 --- a/Mathlib/CategoryTheory/Grothendieck.lean +++ b/Mathlib/CategoryTheory/Grothendieck.lean @@ -166,18 +166,13 @@ def map (α : F ⟶ G) : Grothendieck F ⥤ Grothendieck G where map {X Y} f := { base := f.base fiber := (eqToHom (α.naturality f.base).symm).app X.fiber ≫ (α.app Y.base).map f.fiber } - map_id X := by - simp only [Cat.comp_obj, id_fiber', eqToHom_map] - congr 1 - rw [eqToHom_app, eqToHom_trans] + map_id X := by simp only [Cat.eqToHom_app, id_fiber', eqToHom_map, eqToHom_trans]; rfl map_comp {X Y Z} f g := by dsimp congr 1 simp only [comp_fiber' f g, ← Category.assoc, Functor.map_comp, eqToHom_map] congr 1 - simp only [Cat.comp_obj, eqToHom_trans, eqToHom_map, Cat.comp_map, eqToHom_trans_assoc, - Category.assoc] - rw [eqToHom_app, eqToHom_app, eqToHom_app] + simp only [Cat.eqToHom_app, Cat.comp_obj, eqToHom_trans, eqToHom_map, Category.assoc] erw [Functor.congr_hom (α.naturality g.base).symm f.fiber] simp @@ -198,9 +193,7 @@ theorem map_id_eq : map (𝟙 F) = 𝟙 (Cat.of <| Grothendieck <| F) := by rfl · intro X Y f simp [map_map] - congr - rw [NatTrans.id_app] - simp + rfl /-- Making the equality of functors into an isomorphism. Note: we should avoid equality of functors if possible, and we should prefer `map_id_iso` to `map_id_eq` whenever we can. -/ @@ -218,9 +211,7 @@ theorem map_comp_eq (α : F ⟶ G) (β : G ⟶ H) : eqToHom_refl, Functor.comp_map, Functor.map_comp, Category.comp_id, Category.id_comp] fapply Grothendieck.ext · rfl - · simp only [eqToHom_refl, Category.id_comp] - erw [eqToHom_app, eqToHom_app, eqToHom_app, eqToHom_map] - simp only [Cat.comp_obj, eqToHom_trans_assoc] + · simp /-- Making the equality of functors into an isomorphism. Note: we should avoid equality of functors if possible, and we should prefer `map_comp_iso` to `map_comp_eq` whenever we can. -/ diff --git a/Mathlib/CategoryTheory/Groupoid/FreeGroupoid.lean b/Mathlib/CategoryTheory/Groupoid/FreeGroupoid.lean index 2521a5e952967..eb29d47f63cd5 100644 --- a/Mathlib/CategoryTheory/Groupoid/FreeGroupoid.lean +++ b/Mathlib/CategoryTheory/Groupoid/FreeGroupoid.lean @@ -80,10 +80,11 @@ theorem congr_reverse {X Y : Paths <| Quiver.Symmetrify V} (p q : X ⟶ Y) : Quiver.Path.reverse_comp, Quiver.reverse_reverse, Quiver.Path.reverse_toPath, Quiver.Path.comp_assoc] using this +open Relation in theorem congr_comp_reverse {X Y : Paths <| Quiver.Symmetrify V} (p : X ⟶ Y) : Quot.mk (@Quotient.CompClosure _ _ redStep _ _) (p ≫ p.reverse) = Quot.mk (@Quotient.CompClosure _ _ redStep _ _) (𝟙 X) := by - apply Quot.EqvGen_sound + apply Quot.eqvGen_sound induction' p with a b q f ih · apply EqvGen.refl · simp only [Quiver.Path.reverse] diff --git a/Mathlib/CategoryTheory/Groupoid/Subgroupoid.lean b/Mathlib/CategoryTheory/Groupoid/Subgroupoid.lean index b2efc306cfa42..808563792a9e3 100644 --- a/Mathlib/CategoryTheory/Groupoid/Subgroupoid.lean +++ b/Mathlib/CategoryTheory/Groupoid/Subgroupoid.lean @@ -139,7 +139,7 @@ theorem coe_inv_coe' {c d : S.objs} (p : c ⟶ d) : (CategoryTheory.inv p).val = CategoryTheory.inv p.val := by simp only [← inv_eq_inv, coe_inv_coe] -/-- The embedding of the coerced subgroupoid to its parent-/ +/-- The embedding of the coerced subgroupoid to its parent -/ def hom : S.objs ⥤ C where obj c := c.val map f := f.val @@ -292,7 +292,7 @@ theorem IsWide.id_mem {S : Subgroupoid C} (Sw : S.IsWide) (c : C) : 𝟙 c ∈ S theorem IsWide.eqToHom_mem {S : Subgroupoid C} (Sw : S.IsWide) {c d : C} (h : c = d) : eqToHom h ∈ S.arrows c d := by cases h; simp only [eqToHom_refl]; apply Sw.id_mem c -/-- A subgroupoid is normal if it is wide and satisfies the expected stability under conjugacy. -/ +/-- A subgroupoid is normal if it is wide and satisfies the expected stability under conjugacy. -/ structure IsNormal extends IsWide S : Prop where conj : ∀ {c d} (p : c ⟶ d) {γ : c ⟶ c}, γ ∈ S.arrows c c → Groupoid.inv p ≫ γ ≫ p ∈ S.arrows d d diff --git a/Mathlib/CategoryTheory/Idempotents/FunctorCategories.lean b/Mathlib/CategoryTheory/Idempotents/FunctorCategories.lean index ebcbb63e295ad..b1b1f5f30c036 100644 --- a/Mathlib/CategoryTheory/Idempotents/FunctorCategories.lean +++ b/Mathlib/CategoryTheory/Idempotents/FunctorCategories.lean @@ -58,7 +58,7 @@ instance functor_category_isIdempotentComplete [IsIdempotentComplete C] : have hC := (isIdempotentComplete_iff_hasEqualizer_of_id_and_idempotent C).mp inferInstance haveI : ∀ j : J, HasEqualizer (𝟙 _) (p.app j) := fun j => hC _ _ (congr_app hp j) /- We construct the direct factor `Y` associated to `p : F ⟶ F` by computing - the equalizer of the identity and `p.app j` on each object `(j : J)`. -/ + the equalizer of the identity and `p.app j` on each object `(j : J)`. -/ let Y : J ⥤ C := { obj := fun j => Limits.equalizer (𝟙 _) (p.app j) map := fun {j j'} φ => diff --git a/Mathlib/CategoryTheory/Idempotents/FunctorExtension.lean b/Mathlib/CategoryTheory/Idempotents/FunctorExtension.lean index 0fbbb2cf5e249..4c4de5bce5d99 100644 --- a/Mathlib/CategoryTheory/Idempotents/FunctorExtension.lean +++ b/Mathlib/CategoryTheory/Idempotents/FunctorExtension.lean @@ -106,8 +106,12 @@ def functorExtension₁CompWhiskeringLeftToKaroubiIso : (fun {X Y} f => by aesop_cat)) (by aesop_cat) +#adaptation_note +/-- +At nightly-2024-08-08 we needed to increase the maxHeartbeats here. +-/ +set_option maxHeartbeats 400000 in /-- The counit isomorphism of the equivalence `(C ⥤ Karoubi D) ≌ (Karoubi C ⥤ Karoubi D)`. -/ -@[simps!] def KaroubiUniversal₁.counitIso : (whiskeringLeft C (Karoubi C) (Karoubi D)).obj (toKaroubi C) ⋙ functorExtension₁ C D ≅ 𝟭 _ := NatIso.ofComponents @@ -144,6 +148,8 @@ def KaroubiUniversal₁.counitIso : simp only [Functor.map_comp, comp_f, assoc] rfl) +attribute [simps!] KaroubiUniversal₁.counitIso + /-- The equivalence of categories `(C ⥤ Karoubi D) ≌ (Karoubi C ⥤ Karoubi D)`. -/ @[simps] def karoubiUniversal₁ : C ⥤ Karoubi D ≌ Karoubi C ⥤ Karoubi D where diff --git a/Mathlib/CategoryTheory/Iso.lean b/Mathlib/CategoryTheory/Iso.lean index 77a86f6d853df..5294a89d8becb 100644 --- a/Mathlib/CategoryTheory/Iso.lean +++ b/Mathlib/CategoryTheory/Iso.lean @@ -100,7 +100,7 @@ theorem symm_mk {X Y : C} (hom : X ⟶ Y) (inv : Y ⟶ X) (hom_inv_id) (inv_hom_ rfl @[simp] -theorem symm_symm_eq {X Y : C} (α : X ≅ Y) : α.symm.symm = α := by cases α; rfl +theorem symm_symm_eq {X Y : C} (α : X ≅ Y) : α.symm.symm = α := rfl @[simp] theorem symm_eq_iff {X Y : C} {α β : X ≅ Y} : α.symm = β.symm ↔ α = β := diff --git a/Mathlib/CategoryTheory/Limits/ColimitLimit.lean b/Mathlib/CategoryTheory/Limits/ColimitLimit.lean index 39aab04c6e510..2628945db2029 100644 --- a/Mathlib/CategoryTheory/Limits/ColimitLimit.lean +++ b/Mathlib/CategoryTheory/Limits/ColimitLimit.lean @@ -5,7 +5,7 @@ Authors: Scott Morrison -/ import Mathlib.CategoryTheory.Limits.Types import Mathlib.CategoryTheory.Functor.Currying -import Mathlib.CategoryTheory.Limits.FunctorCategory +import Mathlib.CategoryTheory.Limits.FunctorCategory.Basic /-! # The morphism comparing a colimit of limits with the corresponding limit of colimits. diff --git a/Mathlib/CategoryTheory/Limits/ConeCategory.lean b/Mathlib/CategoryTheory/Limits/ConeCategory.lean index 11acfcd801749..dd971c3b5c792 100644 --- a/Mathlib/CategoryTheory/Limits/ConeCategory.lean +++ b/Mathlib/CategoryTheory/Limits/ConeCategory.lean @@ -138,20 +138,14 @@ def Cone.fromCostructuredArrow (F : J ⥤ C) : CostructuredArrow (const J) F ⥤ dsimp simp } -/- -Porting note: -`simps!` alone generated lemmas of the form `_ = _` where `_` are proofs of some proposition. -This caused the simpNF linter to complain. -We therefore explicitly tell simps! to avoid applying projections for `PLift` and `ULift`. -Similarly for `Cocone.equivStructuredArrow`. --/ /-- The category of cones on `F` is just the comma category `(Δ ↓ F)`, where `Δ` is the constant functor. -/ -@[simps! (config := { notRecursive := [`PLift, `ULift] })] -def Cone.equivCostructuredArrow (F : J ⥤ C) : Cone F ≌ CostructuredArrow (const J) F := - Equivalence.mk (Cone.toCostructuredArrow F) (Cone.fromCostructuredArrow F) - (NatIso.ofComponents Cones.eta) - (NatIso.ofComponents fun c => (CostructuredArrow.eta _).symm) +@[simps] +def Cone.equivCostructuredArrow (F : J ⥤ C) : Cone F ≌ CostructuredArrow (const J) F where + functor := Cone.toCostructuredArrow F + inverse := Cone.fromCostructuredArrow F + unitIso := NatIso.ofComponents Cones.eta + counitIso := NatIso.ofComponents fun c => (CostructuredArrow.eta _).symm /-- A cone is a limit cone iff it is terminal. -/ def Cone.isLimitEquivIsTerminal {F : J ⥤ C} (c : Cone F) : IsLimit c ≃ IsTerminal c := @@ -305,11 +299,12 @@ def Cocone.fromStructuredArrow (F : J ⥤ C) : StructuredArrow F (const J) ⥤ C /-- The category of cocones on `F` is just the comma category `(F ↓ Δ)`, where `Δ` is the constant functor. -/ -@[simps! (config := { notRecursive := [`PLift, `ULift] })] -def Cocone.equivStructuredArrow (F : J ⥤ C) : Cocone F ≌ StructuredArrow F (const J) := - Equivalence.mk (Cocone.toStructuredArrow F) (Cocone.fromStructuredArrow F) - (NatIso.ofComponents Cocones.eta) - (NatIso.ofComponents fun c => (StructuredArrow.eta _).symm) +@[simps] +def Cocone.equivStructuredArrow (F : J ⥤ C) : Cocone F ≌ StructuredArrow F (const J) where + functor := Cocone.toStructuredArrow F + inverse := Cocone.fromStructuredArrow F + unitIso := NatIso.ofComponents Cocones.eta + counitIso := NatIso.ofComponents fun c => (StructuredArrow.eta _).symm /-- A cocone is a colimit cocone iff it is initial. -/ def Cocone.isColimitEquivIsInitial {F : J ⥤ C} (c : Cocone F) : IsColimit c ≃ IsInitial c := diff --git a/Mathlib/CategoryTheory/Limits/Cones.lean b/Mathlib/CategoryTheory/Limits/Cones.lean index 1d468d8221bd1..84e7ebc84d72c 100644 --- a/Mathlib/CategoryTheory/Limits/Cones.lean +++ b/Mathlib/CategoryTheory/Limits/Cones.lean @@ -668,7 +668,7 @@ def mapCone (c : Cone F) : Cone (F ⋙ H) := def mapCocone (c : Cocone F) : Cocone (F ⋙ H) := (Cocones.functoriality F H).obj c -/-- Given a cone morphism `c ⟶ c'`, construct a cone morphism on the mapped cones functorially. -/ +/-- Given a cone morphism `c ⟶ c'`, construct a cone morphism on the mapped cones functorially. -/ def mapConeMorphism {c c' : Cone F} (f : c ⟶ c') : H.mapCone c ⟶ H.mapCone c' := (Cones.functoriality F H).map f diff --git a/Mathlib/CategoryTheory/Limits/Constructions/FiniteProductsOfBinaryProducts.lean b/Mathlib/CategoryTheory/Limits/Constructions/FiniteProductsOfBinaryProducts.lean index a194496163cb3..83fd7abbab1b6 100644 --- a/Mathlib/CategoryTheory/Limits/Constructions/FiniteProductsOfBinaryProducts.lean +++ b/Mathlib/CategoryTheory/Limits/Constructions/FiniteProductsOfBinaryProducts.lean @@ -157,12 +157,12 @@ def preservesShapeFinOfPreservesBinaryAndTerminal (n : ℕ) : apply preservesLimitOfIsoDiagram F that /-- If `F` preserves the terminal object and binary products then it preserves finite products. -/ -def preservesFiniteProductsOfPreservesBinaryAndTerminal (J : Type) [Fintype J] : +def preservesFiniteProductsOfPreservesBinaryAndTerminal (J : Type*) [Fintype J] : PreservesLimitsOfShape (Discrete J) F := by classical let e := Fintype.equivFin J haveI := preservesShapeFinOfPreservesBinaryAndTerminal F (Fintype.card J) - apply preservesLimitsOfShapeOfEquiv.{0, 0} (Discrete.equivalence e).symm + apply preservesLimitsOfShapeOfEquiv (Discrete.equivalence e).symm end Preserves @@ -288,12 +288,12 @@ def preservesShapeFinOfPreservesBinaryAndInitial (n : ℕ) : apply preservesColimitOfIsoDiagram F that /-- If `F` preserves the initial object and binary coproducts then it preserves finite products. -/ -def preservesFiniteCoproductsOfPreservesBinaryAndInitial (J : Type) [Fintype J] : +def preservesFiniteCoproductsOfPreservesBinaryAndInitial (J : Type*) [Fintype J] : PreservesColimitsOfShape (Discrete J) F := by classical let e := Fintype.equivFin J haveI := preservesShapeFinOfPreservesBinaryAndInitial F (Fintype.card J) - apply preservesColimitsOfShapeOfEquiv.{0, 0} (Discrete.equivalence e).symm + apply preservesColimitsOfShapeOfEquiv (Discrete.equivalence e).symm end Preserves diff --git a/Mathlib/CategoryTheory/Limits/Final.lean b/Mathlib/CategoryTheory/Limits/Final.lean index 70bc2fb14a714..96c97533ba899 100644 --- a/Mathlib/CategoryTheory/Limits/Final.lean +++ b/Mathlib/CategoryTheory/Limits/Final.lean @@ -358,7 +358,7 @@ variable {C : Type v} [Category.{v} C] {D : Type u₁} [Category.{v} D] (F : C namespace Final theorem zigzag_of_eqvGen_quot_rel {F : C ⥤ D} {d : D} {f₁ f₂ : ΣX, d ⟶ F.obj X} - (t : EqvGen (Types.Quot.Rel.{v, v} (F ⋙ coyoneda.obj (op d))) f₁ f₂) : + (t : Relation.EqvGen (Types.Quot.Rel.{v, v} (F ⋙ coyoneda.obj (op d))) f₁ f₂) : Zigzag (StructuredArrow.mk f₁.2) (StructuredArrow.mk f₂.2) := by induction t with | rel x y r => diff --git a/Mathlib/CategoryTheory/Limits/Final/ParallelPair.lean b/Mathlib/CategoryTheory/Limits/Final/ParallelPair.lean index b75d801a67a5d..938e98c7e64e6 100644 --- a/Mathlib/CategoryTheory/Limits/Final/ParallelPair.lean +++ b/Mathlib/CategoryTheory/Limits/Final/ParallelPair.lean @@ -6,10 +6,10 @@ Authors: Dagur Asgeirsson, Joël Riou import Mathlib.CategoryTheory.Limits.Final /-! -# Conditions for `parallelPair` to be initial +# Conditions for `parallelPair` to be initial -In this file we give sufficient conditions on a category `C` and parallel morphisms `f g : X ⟶ Y`  -in `C` so that `parallelPair f g` becomes an initial functor. +In this file we give sufficient conditions on a category `C` and parallel morphisms `f g : X ⟶ Y` +in `C` so that `parallelPair f g` becomes an initial functor. The conditions are that there is a morphism out of `X` to every object of `C` and that any two parallel morphisms out of `X` factor through the parallel pair `f`, `g` diff --git a/Mathlib/CategoryTheory/Limits/Fubini.lean b/Mathlib/CategoryTheory/Limits/Fubini.lean index 0af28f9325260..3bd7d06ef9472 100644 --- a/Mathlib/CategoryTheory/Limits/Fubini.lean +++ b/Mathlib/CategoryTheory/Limits/Fubini.lean @@ -368,7 +368,7 @@ theorem limitFlipCompLimIsoLimitCompLim_hom_π_π (j) (k) : (limitFlipCompLimIsoLimitCompLim F).hom ≫ limit.π _ j ≫ limit.π _ k = (limit.π _ k ≫ limit.π _ j : limit (_ ⋙ lim) ⟶ _) := by dsimp [limitFlipCompLimIsoLimitCompLim] - simp + simp [Equivalence.counit] -- Porting note: Added type annotation `limit (_ ⋙ lim) ⟶ _` -- See note [dsimp, simp] @@ -402,7 +402,7 @@ theorem colimitFlipCompColimIsoColimitCompColim_ι_ι_hom (j) (k) : (colimit.ι _ k ≫ colimit.ι (F ⋙ colim) j : _ ⟶ colimit (F⋙ colim)) := by dsimp [colimitFlipCompColimIsoColimitCompColim] slice_lhs 1 3 => simp only [] - simp + simp [Equivalence.unit] @[simp, reassoc] theorem colimitFlipCompColimIsoColimitCompColim_ι_ι_inv (k) (j) : @@ -411,7 +411,7 @@ theorem colimitFlipCompColimIsoColimitCompColim_ι_ι_inv (k) (j) : (colimit.ι _ j ≫ colimit.ι (F.flip ⋙ colim) k : _ ⟶ colimit (F.flip ⋙ colim)) := by dsimp [colimitFlipCompColimIsoColimitCompColim] slice_lhs 1 3 => simp only [] - simp + simp [Equivalence.counitInv] end @@ -507,15 +507,11 @@ noncomputable def limitCurrySwapCompLimIsoLimitCurryCompLim : theorem limitCurrySwapCompLimIsoLimitCurryCompLim_hom_π_π {j} {k} : (limitCurrySwapCompLimIsoLimitCurryCompLim G).hom ≫ limit.π _ j ≫ limit.π _ k = (limit.π _ k ≫ limit.π _ j : limit (_ ⋙ lim) ⟶ _) := by - dsimp [limitCurrySwapCompLimIsoLimitCurryCompLim] - simp only [Iso.refl_hom, Prod.braiding_counitIso_hom_app, Limits.HasLimit.isoOfEquivalence_hom_π, - Iso.refl_inv, limitIsoLimitCurryCompLim_hom_π_π, eqToIso_refl, Category.assoc] - erw [NatTrans.id_app] - -- Why can't `simp` do this? - dsimp - -- Porting note: the original proof only had `simp`. - -- However, now `CategoryTheory.Bifunctor.map_id` does not get used by `simp` - rw [CategoryTheory.Bifunctor.map_id] + dsimp [limitCurrySwapCompLimIsoLimitCurryCompLim, Equivalence.counit] + rw [Category.assoc, Category.assoc, limitIsoLimitCurryCompLim_hom_π_π, + HasLimit.isoOfEquivalence_hom_π] + dsimp [Equivalence.counit] + rw [← prod_id, G.map_id] simp -- Porting note: Added type annotation `limit (_ ⋙ lim) ⟶ _` @@ -523,12 +519,7 @@ theorem limitCurrySwapCompLimIsoLimitCurryCompLim_hom_π_π {j} {k} : theorem limitCurrySwapCompLimIsoLimitCurryCompLim_inv_π_π {j} {k} : (limitCurrySwapCompLimIsoLimitCurryCompLim G).inv ≫ limit.π _ k ≫ limit.π _ j = (limit.π _ j ≫ limit.π _ k : limit (_ ⋙ lim) ⟶ _) := by - dsimp [limitCurrySwapCompLimIsoLimitCurryCompLim] - simp only [Iso.refl_hom, Prod.braiding_counitIso_hom_app, Limits.HasLimit.isoOfEquivalence_inv_π, - Iso.refl_inv, limitIsoLimitCurryCompLim_hom_π_π, eqToIso_refl, Category.assoc] - erw [NatTrans.id_app] - -- Porting note (#10618): `simp` can do this in lean 4. - simp + simp [limitCurrySwapCompLimIsoLimitCurryCompLim] end @@ -567,11 +558,9 @@ theorem colimitCurrySwapCompColimIsoColimitCurryCompColim_ι_ι_inv {j} {k} : _ ⟶ colimit (curry.obj (Prod.swap K J ⋙ G) ⋙ colim)) := by dsimp [colimitCurrySwapCompColimIsoColimitCurryCompColim] slice_lhs 1 3 => simp only [] - simp only [colimitIsoColimitCurryCompColim_ι_ι_inv, HasColimit.isoOfEquivalence_inv_π, - Functor.id_obj, Functor.comp_obj, Prod.braiding_inverse_obj, Prod.braiding_functor_obj, - Prod.braiding_counitIso_inv_app, Prod.swap_obj, Iso.refl_hom, NatTrans.id_app, Category.id_comp, - Category.assoc, colimitIsoColimitCurryCompColim_ι_hom, curry_obj_obj_obj] - erw [CategoryTheory.Bifunctor.map_id] + rw [colimitIsoColimitCurryCompColim_ι_ι_inv, HasColimit.isoOfEquivalence_inv_π] + dsimp [Equivalence.counitInv] + rw [CategoryTheory.Bifunctor.map_id] simp end diff --git a/Mathlib/CategoryTheory/Limits/FunctorCategory.lean b/Mathlib/CategoryTheory/Limits/FunctorCategory/Basic.lean similarity index 100% rename from Mathlib/CategoryTheory/Limits/FunctorCategory.lean rename to Mathlib/CategoryTheory/Limits/FunctorCategory/Basic.lean diff --git a/Mathlib/CategoryTheory/Limits/FunctorCategory/EpiMono.lean b/Mathlib/CategoryTheory/Limits/FunctorCategory/EpiMono.lean new file mode 100644 index 0000000000000..c7af38879846e --- /dev/null +++ b/Mathlib/CategoryTheory/Limits/FunctorCategory/EpiMono.lean @@ -0,0 +1,61 @@ +/- +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.CategoryTheory.Limits.Constructions.EpiMono +import Mathlib.CategoryTheory.Limits.FunctorCategory.Basic + +/-! +# Monomorphisms and epimorphisms in functor categories + +A natural transformation `f : F ⟶ G` between functors `K ⥤ C` +is a mono (resp. epi) iff for all `k : K`, `f.app k` is, +at least when `C` has pullbacks (resp. pushouts), +see `NatTrans.mono_iff_mono_app` and `NatTrans.epi_iff_epi_app`. + +-/ + +universe v v' v'' u u' u'' + +namespace CategoryTheory + +open Limits + +variable {K : Type u} [Category.{v} K] {C : Type u'} [Category.{v'} C] + {D : Type u''} [Category.{v''} D] {F G : K ⥤ C} (f : F ⟶ G) +section + +variable [HasPullbacks C] + +instance [Mono f] (k : K) : Mono (f.app k) := + inferInstanceAs (Mono (((evaluation K C).obj k).map f)) + +lemma NatTrans.mono_iff_mono_app : Mono f ↔ ∀ (k : K), Mono (f.app k) := + ⟨fun _ ↦ inferInstance, fun _ ↦ mono_of_mono_app _⟩ + +instance [Mono f] (H : C ⥤ D) [H.PreservesMonomorphisms] : + Mono (whiskerRight f H) := by + have : ∀ X, Mono ((whiskerRight f H).app X) := by intros; dsimp; infer_instance + apply NatTrans.mono_of_mono_app + +end + +section + +variable [HasPushouts C] + +instance [Epi f] (k : K) : Epi (f.app k) := + inferInstanceAs (Epi (((evaluation K C).obj k).map f)) + +lemma NatTrans.epi_iff_epi_app : Epi f ↔ ∀ (k : K), Epi (f.app k) := + ⟨fun _ ↦ inferInstance, fun _ ↦ epi_of_epi_app _⟩ + +instance [Epi f] (H : C ⥤ D) [H.PreservesEpimorphisms] : + Epi (whiskerRight f H) := by + have : ∀ X, Epi ((whiskerRight f H).app X) := by intros; dsimp; infer_instance + apply NatTrans.epi_of_epi_app + +end + +end CategoryTheory diff --git a/Mathlib/CategoryTheory/Limits/FunctorCategory/Finite.lean b/Mathlib/CategoryTheory/Limits/FunctorCategory/Finite.lean new file mode 100644 index 0000000000000..d1be7bb8d6da3 --- /dev/null +++ b/Mathlib/CategoryTheory/Limits/FunctorCategory/Finite.lean @@ -0,0 +1,28 @@ +/- +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.Limits.FunctorCategory.Basic +import Mathlib.CategoryTheory.Limits.Shapes.FiniteProducts +/-! + +# Functor categories have finite limits when the target category does + +These declarations cannot be in the file `Mathlib.CategoryTheory.Limits.FunctorCategory` because +that file shouldn't import `Mathlib.CategoryTheory.Limits.Shapes.FiniteProducts`. +-/ + +namespace CategoryTheory.Limits + +variable {C : Type*} [Category C] {K : Type*} [Category K] + +instance [HasFiniteLimits C] : HasFiniteLimits (K ⥤ C) := ⟨fun _ ↦ inferInstance⟩ + +instance [HasFiniteProducts C] : HasFiniteProducts (K ⥤ C) := ⟨inferInstance⟩ + +instance [HasFiniteColimits C] : HasFiniteColimits (K ⥤ C) := ⟨fun _ ↦ inferInstance⟩ + +instance [HasFiniteCoproducts C] : HasFiniteCoproducts (K ⥤ C) := ⟨inferInstance⟩ + +end CategoryTheory.Limits diff --git a/Mathlib/CategoryTheory/Limits/FunctorToTypes.lean b/Mathlib/CategoryTheory/Limits/FunctorToTypes.lean index e6121ee7bfd64..62eb96c6be392 100644 --- a/Mathlib/CategoryTheory/Limits/FunctorToTypes.lean +++ b/Mathlib/CategoryTheory/Limits/FunctorToTypes.lean @@ -3,7 +3,7 @@ Copyright (c) 2024 Markus Himmel. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Markus Himmel -/ -import Mathlib.CategoryTheory.Limits.FunctorCategory +import Mathlib.CategoryTheory.Limits.FunctorCategory.Basic import Mathlib.CategoryTheory.Limits.Types /-! diff --git a/Mathlib/CategoryTheory/Limits/HasLimits.lean b/Mathlib/CategoryTheory/Limits/HasLimits.lean index a2ac485b93211..866e9a9ee1602 100644 --- a/Mathlib/CategoryTheory/Limits/HasLimits.lean +++ b/Mathlib/CategoryTheory/Limits/HasLimits.lean @@ -489,7 +489,7 @@ def limYoneda : lim ⋙ yoneda ⋙ (whiskeringRight _ _ _).obj uliftFunctor.{u₁} ≅ CategoryTheory.cones J C := NatIso.ofComponents fun F => NatIso.ofComponents fun W => limit.homIso F (unop W) -/-- The constant functor and limit functor are adjoint to each other-/ +/-- The constant functor and limit functor are adjoint to each other -/ def constLimAdj : (const J : C ⥤ J ⥤ C) ⊣ lim where homEquiv c g := { toFun := fun f => limit.lift _ ⟨c, f⟩ diff --git a/Mathlib/CategoryTheory/Limits/IsConnected.lean b/Mathlib/CategoryTheory/Limits/IsConnected.lean index 7dcd61474ff13..a0e0dd26b49f2 100644 --- a/Mathlib/CategoryTheory/Limits/IsConnected.lean +++ b/Mathlib/CategoryTheory/Limits/IsConnected.lean @@ -85,7 +85,7 @@ noncomputable def colimitConstPUnitIsoPUnit [IsConnected C] : /-- Let `F` be a `Type`-valued functor. If two elements `a : F c` and `b : F d` represent the same element of `colimit F`, then `c` and `d` are related by a `Zigzag`. -/ theorem zigzag_of_eqvGen_quot_rel (F : C ⥤ Type w) (c d : Σ j, F.obj j) - (h : EqvGen (Quot.Rel F) c d) : Zigzag c.1 d.1 := by + (h : Relation.EqvGen (Quot.Rel F) c d) : Zigzag c.1 d.1 := by induction h with | rel _ _ h => exact Zigzag.of_hom <| Exists.choose h | refl _ => exact Zigzag.refl _ diff --git a/Mathlib/CategoryTheory/Limits/IsLimit.lean b/Mathlib/CategoryTheory/Limits/IsLimit.lean index c8f15dd3b038b..ff385b709488f 100644 --- a/Mathlib/CategoryTheory/Limits/IsLimit.lean +++ b/Mathlib/CategoryTheory/Limits/IsLimit.lean @@ -60,9 +60,6 @@ structure IsLimit (t : Cone F) where uniq : ∀ (s : Cone F) (m : s.pt ⟶ t.pt) (_ : ∀ j : J, m ≫ t.π.app j = s.π.app j), m = lift s := by aesop_cat --- Porting note (#10618): simp can prove this. Linter complains it still exists -attribute [-simp, nolint simpNF] IsLimit.mk.injEq - attribute [reassoc (attr := simp)] IsLimit.fac namespace IsLimit @@ -516,9 +513,6 @@ structure IsColimit (t : Cocone F) where attribute [reassoc (attr := simp)] IsColimit.fac --- Porting note (#10618): simp can prove this. Linter claims it still is tagged with simp -attribute [-simp, nolint simpNF] IsColimit.mk.injEq - namespace IsColimit instance subsingleton {t : Cocone F} : Subsingleton (IsColimit t) := diff --git a/Mathlib/CategoryTheory/Limits/Opposites.lean b/Mathlib/CategoryTheory/Limits/Opposites.lean index fab462149abac..55f267f9bdae5 100644 --- a/Mathlib/CategoryTheory/Limits/Opposites.lean +++ b/Mathlib/CategoryTheory/Limits/Opposites.lean @@ -322,11 +322,11 @@ instance : HasProduct (op <| Z ·) := hasLimitOfIso (Discrete.opposite α).inverse ⋙ (Discrete.functor Z).op ≅ Discrete.functor (op <| Z ·)) -/-- A `Cofan` gives a `Fan` in the opposite category. -/ +/-- A `Cofan` gives a `Fan` in the opposite category. -/ @[simp] def Cofan.op (c : Cofan Z) : Fan (op <| Z ·) := Fan.mk _ (fun a ↦ (c.inj a).op) -/-- If a `Cofan` is colimit, then its opposite is limit. -/ +/-- If a `Cofan` is colimit, then its opposite is limit. -/ def Cofan.IsColimit.op {c : Cofan Z} (hc : IsColimit c) : IsLimit c.op := by let e : Discrete.functor (Opposite.op <| Z ·) ≅ (Discrete.opposite α).inverse ⋙ (Discrete.functor Z).op := Discrete.natIso (fun _ ↦ Iso.refl _) @@ -422,7 +422,7 @@ instance : HasCoproduct (op <| Z ·) := hasColimitOfIso @[simp] def Fan.op (f : Fan Z) : Cofan (op <| Z ·) := Cofan.mk _ (fun a ↦ (f.proj a).op) -/-- If a `Fan` is limit, then its opposite is colimit. -/ +/-- If a `Fan` is limit, then its opposite is colimit. -/ def Fan.IsLimit.op {f : Fan Z} (hf : IsLimit f) : IsColimit f.op := by let e : Discrete.functor (Opposite.op <| Z ·) ≅ (Discrete.opposite α).inverse ⋙ (Discrete.functor Z).op := Discrete.natIso (fun _ ↦ Iso.refl _) diff --git a/Mathlib/CategoryTheory/Limits/Preserves/FunctorCategory.lean b/Mathlib/CategoryTheory/Limits/Preserves/FunctorCategory.lean index f595d3f9ba751..4b4cde050f773 100644 --- a/Mathlib/CategoryTheory/Limits/Preserves/FunctorCategory.lean +++ b/Mathlib/CategoryTheory/Limits/Preserves/FunctorCategory.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 -/ -import Mathlib.CategoryTheory.Limits.FunctorCategory +import Mathlib.CategoryTheory.Limits.FunctorCategory.Basic import Mathlib.CategoryTheory.Limits.Preserves.Shapes.BinaryProducts import Mathlib.CategoryTheory.Limits.Yoneda import Mathlib.CategoryTheory.Limits.Presheaf diff --git a/Mathlib/CategoryTheory/Limits/Preserves/Shapes/Biproducts.lean b/Mathlib/CategoryTheory/Limits/Preserves/Shapes/Biproducts.lean index c5f4f3bd95437..c3d4d473c6c16 100644 --- a/Mathlib/CategoryTheory/Limits/Preserves/Shapes/Biproducts.lean +++ b/Mathlib/CategoryTheory/Limits/Preserves/Shapes/Biproducts.lean @@ -224,7 +224,7 @@ theorem ι_biproductComparison' (j : J) : variable [PreservesZeroMorphisms F] /-- The composition in the opposite direction is equal to the identity if and only if `F` preserves - the biproduct, see `preservesBiproduct_of_monoBiproductComparison`. -/ + the biproduct, see `preservesBiproduct_of_monoBiproductComparison`. -/ @[reassoc (attr := simp)] theorem biproductComparison'_comp_biproductComparison : biproductComparison' F f ≫ biproductComparison F f = 𝟙 (⨁ F.obj ∘ f) := by diff --git a/Mathlib/CategoryTheory/Limits/Preserves/Shapes/Kernels.lean b/Mathlib/CategoryTheory/Limits/Preserves/Shapes/Kernels.lean index e273955285c7a..9a602e80dbec1 100644 --- a/Mathlib/CategoryTheory/Limits/Preserves/Shapes/Kernels.lean +++ b/Mathlib/CategoryTheory/Limits/Preserves/Shapes/Kernels.lean @@ -176,7 +176,7 @@ def isColimitMapCoconeEquiv : /-- A colimit cokernel cofork is mapped to a colimit cokernel cofork by a functor `G` when this functor preserves the corresponding colimit. -/ -def mapIsColimit (hc : IsColimit c) (G : C ⥤ D) +def mapIsColimit (hc : IsColimit c) (G : C ⥤ D) [Functor.PreservesZeroMorphisms G] [PreservesColimit (parallelPair f 0) G] : IsColimit (c.map G) := c.isColimitMapCoconeEquiv G (isColimitOfPreserves G hc) diff --git a/Mathlib/CategoryTheory/Limits/Preserves/Ulift.lean b/Mathlib/CategoryTheory/Limits/Preserves/Ulift.lean index 9bab8cb39bdb4..e11c09ddc138d 100644 --- a/Mathlib/CategoryTheory/Limits/Preserves/Ulift.lean +++ b/Mathlib/CategoryTheory/Limits/Preserves/Ulift.lean @@ -23,8 +23,8 @@ universe v w w' u namespace CategoryTheory.Limits.Types /-- -The equivalence between `K.sections` and `(K ⋙ uliftFunctor.{v, u}).sections`. This is used to show -that `uliftFunctor` preserves limits that are potentially too large to exist in the source +The equivalence between `K.sections` and `(K ⋙ uliftFunctor.{v, u}).sections`. This is used to show +that `uliftFunctor` preserves limits that are potentially too large to exist in the source category. -/ def sectionsEquiv {J : Type*} [Category J] (K : J ⥤ Type u) : diff --git a/Mathlib/CategoryTheory/Limits/Presheaf.lean b/Mathlib/CategoryTheory/Limits/Presheaf.lean index e6f648acb64ad..659bf465adea6 100644 --- a/Mathlib/CategoryTheory/Limits/Presheaf.lean +++ b/Mathlib/CategoryTheory/Limits/Presheaf.lean @@ -8,7 +8,7 @@ import Mathlib.CategoryTheory.Elements import Mathlib.CategoryTheory.Functor.KanExtension.Adjunction import Mathlib.CategoryTheory.Limits.ConeCategory import Mathlib.CategoryTheory.Limits.Final -import Mathlib.CategoryTheory.Limits.FunctorCategory +import Mathlib.CategoryTheory.Limits.FunctorCategory.Basic import Mathlib.CategoryTheory.Limits.Over import Mathlib.CategoryTheory.Limits.Shapes.Terminal import Mathlib.CategoryTheory.Limits.Types diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Biproducts.lean b/Mathlib/CategoryTheory/Limits/Shapes/Biproducts.lean index ecb6dfd87d021..a079c16da2b22 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Biproducts.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Biproducts.lean @@ -386,7 +386,7 @@ theorem hasBiproductsOfShape_of_equiv {K : Type w'} [HasBiproductsOfShape K C] ( let ⟨⟨h⟩⟩ := HasBiproductsOfShape.has_biproduct (F ∘ e.symm) let ⟨c, hc⟩ := h HasBiproduct.mk <| by - simpa only [(· ∘ ·), e.symm_apply_apply] using + simpa only [Function.comp_def, e.symm_apply_apply] using LimitBicone.mk (c.whisker e) ((c.whiskerIsBilimitIff _).2 hc)⟩ instance (priority := 100) hasBiproductsOfShape_finite [HasFiniteBiproducts C] [Finite J] : @@ -640,6 +640,7 @@ lemma biproduct.whiskerEquiv_inv_eq_lift {f : J → C} {g : K → C} (e : J ≃ · rintro rfl simp at h +attribute [local simp] Sigma.forall in instance {ι} (f : ι → Type*) (g : (i : ι) → (f i) → C) [∀ i, HasBiproduct (g i)] [HasBiproduct fun i => ⨁ g i] : HasBiproduct fun p : Σ i, f i => g p.1 p.2 where @@ -1275,7 +1276,7 @@ abbrev toBinaryBicone {X Y : C} (b : Bicone (pairFunction X Y)) : BinaryBicone X toBinaryBiconeFunctor.obj b /-- A bicone over a pair is a limit cone if and only if the corresponding binary bicone is a limit - cone. -/ + cone. -/ def toBinaryBiconeIsLimit {X Y : C} (b : Bicone (pairFunction X Y)) : IsLimit b.toBinaryBicone.toCone ≃ IsLimit b.toCone := IsLimit.equivIsoLimit <| Cones.ext (Iso.refl _) fun j => by rcases j with ⟨⟨⟩⟩ <;> simp @@ -1761,7 +1762,7 @@ def biprod.fstKernelFork : KernelFork (biprod.fst : X ⊞ Y ⟶ X) := theorem biprod.fstKernelFork_ι : Fork.ι (biprod.fstKernelFork X Y) = (biprod.inr : Y ⟶ X ⊞ Y) := rfl -/-- The fork `biprod.fstKernelFork` is indeed a limit. -/ +/-- The fork `biprod.fstKernelFork` is indeed a limit. -/ def biprod.isKernelFstKernelFork : IsLimit (biprod.fstKernelFork X Y) := BinaryBicone.isLimitFstKernelFork (BinaryBiproduct.isLimit _ _) @@ -1774,7 +1775,7 @@ def biprod.sndKernelFork : KernelFork (biprod.snd : X ⊞ Y ⟶ Y) := theorem biprod.sndKernelFork_ι : Fork.ι (biprod.sndKernelFork X Y) = (biprod.inl : X ⟶ X ⊞ Y) := rfl -/-- The fork `biprod.sndKernelFork` is indeed a limit. -/ +/-- The fork `biprod.sndKernelFork` is indeed a limit. -/ def biprod.isKernelSndKernelFork : IsLimit (biprod.sndKernelFork X Y) := BinaryBicone.isLimitSndKernelFork (BinaryBiproduct.isLimit _ _) @@ -1787,7 +1788,7 @@ def biprod.inlCokernelCofork : CokernelCofork (biprod.inl : X ⟶ X ⊞ Y) := theorem biprod.inlCokernelCofork_π : Cofork.π (biprod.inlCokernelCofork X Y) = biprod.snd := rfl -/-- The cofork `biprod.inlCokernelFork` is indeed a colimit. -/ +/-- The cofork `biprod.inlCokernelFork` is indeed a colimit. -/ def biprod.isCokernelInlCokernelFork : IsColimit (biprod.inlCokernelCofork X Y) := BinaryBicone.isColimitInlCokernelCofork (BinaryBiproduct.isColimit _ _) @@ -1800,7 +1801,7 @@ def biprod.inrCokernelCofork : CokernelCofork (biprod.inr : Y ⟶ X ⊞ Y) := theorem biprod.inrCokernelCofork_π : Cofork.π (biprod.inrCokernelCofork X Y) = biprod.fst := rfl -/-- The cofork `biprod.inrCokernelFork` is indeed a colimit. -/ +/-- The cofork `biprod.inrCokernelFork` is indeed a colimit. -/ def biprod.isCokernelInrCokernelFork : IsColimit (biprod.inrCokernelCofork X Y) := BinaryBicone.isColimitInrCokernelCofork (BinaryBiproduct.isColimit _ _) @@ -1996,3 +1997,5 @@ theorem isIso_right_of_isIso_biprod_map {W X Y Z : C} (f : W ⟶ Y) (g : X ⟶ Z isIso_left_of_isIso_biprod_map g f end CategoryTheory + +set_option linter.style.longFile 2100 diff --git a/Mathlib/CategoryTheory/Limits/Shapes/CombinedProducts.lean b/Mathlib/CategoryTheory/Limits/Shapes/CombinedProducts.lean index 1d6c74aed120e..4563605f05c24 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/CombinedProducts.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/CombinedProducts.lean @@ -41,7 +41,7 @@ abbrev combPairHoms : (i : ι₁ ⊕ ι₂) → bc.pt ⟶ Sum.elim f₁ f₂ i variable {c₁ c₂ bc} /-- If `c₁` and `c₂` are limit fans and `bc` is a limit binary fan on their cone -points, then the fan constructed from `combPairHoms` is a limit cone. -/ +points, then the fan constructed from `combPairHoms` is a limit cone. -/ def combPairIsLimit : IsLimit (Fan.mk bc.pt (combPairHoms c₁ c₂ bc)) := mkFanLimit _ (fun s ↦ Fan.IsLimit.desc h <| fun i ↦ by @@ -76,7 +76,7 @@ abbrev combPairHoms : (i : ι₁ ⊕ ι₂) → Sum.elim f₁ f₂ i ⟶ bc.pt variable {c₁ c₂ bc} /-- If `c₁` and `c₂` are colimit cofans and `bc` is a colimit binary cofan on their cocone -points, then the cofan constructed from `combPairHoms` is a colimit cocone. -/ +points, then the cofan constructed from `combPairHoms` is a colimit cocone. -/ def combPairIsColimit : IsColimit (Cofan.mk bc.pt (combPairHoms c₁ c₂ bc)) := mkCofanColimit _ (fun s ↦ Cofan.IsColimit.desc h <| fun i ↦ by diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Countable.lean b/Mathlib/CategoryTheory/Limits/Shapes/Countable.lean index 4893ab194160b..a50342b46d933 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Countable.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Countable.lean @@ -17,7 +17,7 @@ limits, see `sequentialFunctor_initial`. ## Projects -* There is a series of `proof_wanted` at the bottom of this file, implying that all cofiltered +* There is a series of `proof_wanted` at the bottom of this file, implying that all cofiltered limits over countable categories are isomorphic to sequential limits. * Prove the dual result for filtered colimits. @@ -36,7 +36,7 @@ instance and `J : Type` has a limit. -/ class HasCountableLimits : Prop where /-- `C` has all limits over any type `J` whose objects and morphisms lie in the same universe - and which has countably many objects and morphisms-/ + and which has countably many objects and morphisms -/ out (J : Type) [SmallCategory J] [CountableCategory J] : HasLimitsOfShape J C instance (priority := 100) hasFiniteLimits_of_hasCountableLimits [HasCountableLimits C] : @@ -58,7 +58,7 @@ instance and `J : Type` has a colimit. -/ class HasCountableColimits : Prop where /-- `C` has all limits over any type `J` whose objects and morphisms lie in the same universe - and which has countably many objects and morphisms-/ + and which has countably many objects and morphisms -/ out (J : Type) [SmallCategory J] [CountableCategory J] : HasColimitsOfShape J C instance (priority := 100) hasFiniteColimits_of_hasCountableColimits [HasCountableColimits C] : @@ -102,10 +102,10 @@ noncomputable def sequentialFunctor : ℕᵒᵖ ⥤ J where theorem sequentialFunctor_initial_aux (j : J) : ∃ (n : ℕ), sequentialFunctor_obj J n ≤ j := by obtain ⟨m, h⟩ := (exists_surjective_nat _).choose_spec j refine ⟨m + 1, ?_⟩ - simpa [h] using leOfHom (IsCofilteredOrEmpty.cone_objs ((exists_surjective_nat _).choose m) + simpa only [h] using leOfHom (IsCofilteredOrEmpty.cone_objs ((exists_surjective_nat _).choose m) (sequentialFunctor_obj J m)).choose_spec.choose -instance sequentialFunctor_initial : (sequentialFunctor J).Initial where +instance sequentialFunctor_initial : (sequentialFunctor J).Initial where out d := by obtain ⟨n, (g : (sequentialFunctor J).obj ⟨n⟩ ≤ d)⟩ := sequentialFunctor_initial_aux J d have : Nonempty (CostructuredArrow (sequentialFunctor J) d) := @@ -113,7 +113,7 @@ instance sequentialFunctor_initial : (sequentialFunctor J).Initial where apply isConnected_of_zigzag refine fun i j ↦ ⟨[j], ?_⟩ simp only [List.chain_cons, Zag, List.Chain.nil, and_true, ne_eq, not_false_eq_true, - List.getLast_cons, not_true_eq_false, List.getLast_singleton'] + List.getLast_cons, not_true_eq_false, List.getLast_singleton', reduceCtorEq] clear! C wlog h : (unop i.left) ≤ (unop j.left) · exact or_comm.1 (this J d n g inferInstance j i (le_of_lt (not_le.mp h))) @@ -127,7 +127,7 @@ proof_wanted preorder_of_cofiltered (J : Type*) [Category J] [IsCofiltered J] : ∃ (I : Type*) (_ : Preorder I) (_ : IsCofiltered I) (F : I ⥤ J), F.Initial /-- -The proof of `preorder_of_cofiltered` should give a countable `I` in the case that `J` is a +The proof of `preorder_of_cofiltered` should give a countable `I` in the case that `J` is a countable category. -/ proof_wanted preorder_of_cofiltered_countable diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Equalizers.lean b/Mathlib/CategoryTheory/Limits/Shapes/Equalizers.lean index bb067d0c9eef4..499e8ff5ad36b 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Equalizers.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Equalizers.lean @@ -925,7 +925,7 @@ variable {f g} def idCofork (h : f = g) : Cofork f g := Cofork.ofπ (𝟙 Y) <| h ▸ rfl -/-- The identity on `Y` is a coequalizer of `(f, g)`, where `f = g`. -/ +/-- The identity on `Y` is a coequalizer of `(f, g)`, where `f = g`. -/ def isColimitIdCofork (h : f = g) : IsColimit (idCofork h) := Cofork.IsColimit.mk _ (fun s => Cofork.π s) (fun s => Category.id_comp _) fun s m h => by convert h diff --git a/Mathlib/CategoryTheory/Limits/Shapes/FiniteLimits.lean b/Mathlib/CategoryTheory/Limits/Shapes/FiniteLimits.lean index 154159c993a8c..9cb33fc51bcc3 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/FiniteLimits.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/FiniteLimits.lean @@ -36,7 +36,7 @@ This is often called 'finitely complete'. -/ class HasFiniteLimits : Prop where /-- `C` has all limits over any type `J` whose objects and morphisms lie in the same universe - and which has `FinType` objects and morphisms-/ + and which has `FinType` objects and morphisms -/ out (J : Type) [𝒥 : SmallCategory J] [@FinCategory J 𝒥] : @HasLimitsOfShape J 𝒥 C _ instance (priority := 100) hasLimitsOfShape_of_hasFiniteLimits (J : Type w) [SmallCategory J] @@ -85,7 +85,7 @@ This is often called 'finitely cocomplete'. -/ class HasFiniteColimits : Prop where /-- `C` has all colimits over any type `J` whose objects and morphisms lie in the same universe - and which has `Fintype` objects and morphisms-/ + and which has `Fintype` objects and morphisms -/ out (J : Type) [𝒥 : SmallCategory J] [@FinCategory J 𝒥] : @HasColimitsOfShape J 𝒥 C _ instance (priority := 100) hasColimitsOfShape_of_hasFiniteColimits (J : Type w) [SmallCategory J] diff --git a/Mathlib/CategoryTheory/Limits/Shapes/FunctorCategory.lean b/Mathlib/CategoryTheory/Limits/Shapes/FunctorCategory.lean index c3548f395baed..113f2c55cc2c3 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/FunctorCategory.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/FunctorCategory.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Morrison -/ import Mathlib.CategoryTheory.Limits.Shapes.FiniteLimits -import Mathlib.CategoryTheory.Limits.FunctorCategory +import Mathlib.CategoryTheory.Limits.FunctorCategory.Basic /-! # If `D` has finite (co)limits, so do the functor categories `C ⥤ D`. diff --git a/Mathlib/CategoryTheory/Limits/Shapes/FunctorToTypes.lean b/Mathlib/CategoryTheory/Limits/Shapes/FunctorToTypes.lean index 50c0f9fd9c4df..a369f31f98a9d 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/FunctorToTypes.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/FunctorToTypes.lean @@ -3,7 +3,7 @@ Copyright (c) 2024 Jack McKoen. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jack McKoen -/ -import Mathlib.CategoryTheory.Limits.FunctorCategory +import Mathlib.CategoryTheory.Limits.FunctorCategory.Basic import Mathlib.CategoryTheory.Limits.Types /-! diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Products.lean b/Mathlib/CategoryTheory/Limits/Shapes/Products.lean index 35398449274fd..a614b5d85405d 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Products.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Products.lean @@ -258,7 +258,7 @@ instance {f : β → C} [HasCoproduct f] : IsIso (Sigma.desc (fun a ↦ Sigma.ι ext simp -/-- A version of `Cocones.ext` for `Cofan`s. -/ +/-- A version of `Cocones.ext` for `Cofan`s. -/ @[simps!] def Cofan.ext {f : β → C} {c₁ c₂ : Cofan f} (e : c₁.pt ≅ c₂.pt) (w : ∀ (b : β), c₁.inj b ≫ e.hom = c₂.inj b := by aesop_cat) : c₁ ≅ c₂ := @@ -507,7 +507,8 @@ instance {ι : Type*} (f : ι → Type*) (g : (i : ι) → (f i) → C) exists_limit := Nonempty.intro { cone := Fan.mk (∏ᶜ fun i => ∏ᶜ g i) (fun X => Pi.π (fun i => ∏ᶜ g i) X.1 ≫ Pi.π (g X.1) X.2) isLimit := mkFanLimit _ (fun s => Pi.lift fun b => Pi.lift fun c => s.proj ⟨b, c⟩) - (by aesop_cat) (by intro s m w; simp only [Fan.mk_pt]; symm; ext i x; simp_all) } + (by aesop_cat) + (by intro s m w; simp only [Fan.mk_pt]; symm; ext i x; simp_all [Sigma.forall]) } /-- An iterated product is a product over a sigma type. -/ @[simps] @@ -527,7 +528,8 @@ instance {ι : Type*} (f : ι → Type*) (g : (i : ι) → (f i) → C) (fun X => Sigma.ι (g X.1) X.2 ≫ Sigma.ι (fun i => ∐ g i) X.1) isColimit := mkCofanColimit _ (fun s => Sigma.desc fun b => Sigma.desc fun c => s.inj ⟨b, c⟩) - (by aesop_cat) (by intro s m w; simp only [Cofan.mk_pt]; symm; ext i x; simp_all) } + (by aesop_cat) + (by intro s m w; simp only [Cofan.mk_pt]; symm; ext i x; simp_all [Sigma.forall]) } /-- An iterated coproduct is a coproduct over a sigma type. -/ @[simps] diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Pullback/HasPullback.lean b/Mathlib/CategoryTheory/Limits/Shapes/Pullback/HasPullback.lean index a2698096b0e00..d832ed2573d16 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Pullback/HasPullback.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Pullback/HasPullback.lean @@ -16,7 +16,7 @@ pullacks. express the fact that a given pair of morphisms has a pullback. * `HasPullbacks`: expresses the fact that `C` admits all pullbacks, it is implemented as an - abbrevation for `HasLimitsOfShape WalkingCospan C` + abbreviation for `HasLimitsOfShape WalkingCospan C` * `pullback f g`: Given a `HasPullback f g` instance, this function returns the choice of a limit object corresponding to the pullback of `f` and `g`. It fits into the following diagram: @@ -33,7 +33,7 @@ pullback.snd f g g * `HasPushout f g`: this is an abbreviation for `HasColimit (span f g)`, and is a typeclass used to express the fact that a given pair of morphisms has a pushout. * `HasPushouts`: expresses the fact that `C` admits all pushouts, it is implemented as an -abbrevation for `HasColimitsOfShape WalkingSpan C` +abbreviation for `HasColimitsOfShape WalkingSpan C` * `pushout f g`: Given a `HasPushout f g` instance, this function returns the choice of a colimit object corresponding to the pushout of `f` and `g`. It fits into the following diagram: ``` diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Pullback/Mono.lean b/Mathlib/CategoryTheory/Limits/Shapes/Pullback/Mono.lean index 17d8d712cac9a..87a404f00fcb9 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Pullback/Mono.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Pullback/Mono.lean @@ -79,7 +79,7 @@ theorem mono_of_isLimitMkIdId (f : X ⟶ Y) (t : IsLimit (mk (𝟙 X) (𝟙 X) r /-- Suppose `f` and `g` are two morphisms with a common codomain and `s` is a limit cone over the diagram formed by `f` and `g`. Suppose `f` and `g` both factor through a monomorphism `h` via `x` and `y`, respectively. Then `s` is also a limit cone over the diagram formed by `x` and - `y`. -/ + `y`. -/ def isLimitOfFactors (f : X ⟶ Z) (g : Y ⟶ Z) (h : W ⟶ Z) [Mono h] (x : X ⟶ W) (y : Y ⟶ W) (hxh : x ≫ h = f) (hyh : y ≫ h = g) (s : PullbackCone f g) (hs : IsLimit s) : IsLimit @@ -250,7 +250,7 @@ theorem epi_of_isColimitMkIdId (f : X ⟶ Y) /-- Suppose `f` and `g` are two morphisms with a common domain and `s` is a colimit cocone over the diagram formed by `f` and `g`. Suppose `f` and `g` both factor through an epimorphism `h` via `x` and `y`, respectively. Then `s` is also a colimit cocone over the diagram formed by `x` and - `y`. -/ + `y`. -/ def isColimitOfFactors (f : X ⟶ Y) (g : X ⟶ Z) (h : X ⟶ W) [Epi h] (x : W ⟶ Y) (y : W ⟶ Z) (hhx : h ≫ x = f) (hhy : h ≫ y = g) (s : PushoutCocone f g) (hs : IsColimit s) : have reassoc₁ : h ≫ x ≫ inl s = f ≫ inl s := by -- Porting note: working around reassoc diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Pullback/Pasting.lean b/Mathlib/CategoryTheory/Limits/Shapes/Pullback/Pasting.lean index adb760c265945..ddf8657ecc188 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Pullback/Pasting.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Pullback/Pasting.lean @@ -55,19 +55,22 @@ where `t₁` denotes the cone corresponding to the left square, and `t₂` denot corresponding to the right square. -/ -variable {X₃ Y₁ Y₂ Y₃ : C} {g₁ : Y₁ ⟶ Y₂} {g₂ : Y₂ ⟶ Y₃} {i₃ : X₃ ⟶ Y₃} (t₂ : PullbackCone g₂ i₃) -variable {i₂ : t₂.pt ⟶ Y₂} (t₁ : PullbackCone g₁ i₂) (hi₂ : i₂ = t₂.fst) +variable {X₃ Y₁ Y₂ Y₃ : C} {g₁ : Y₁ ⟶ Y₂} {g₂ : Y₂ ⟶ Y₃} {i₃ : X₃ ⟶ Y₃} + +/-- The `PullbackCone` obtained by pasting two `PullbackCone`'s horizontally -/ +abbrev PullbackCone.pasteHoriz + (t₂ : PullbackCone g₂ i₃) {i₂ : t₂.pt ⟶ Y₂} (t₁ : PullbackCone g₁ i₂) (hi₂ : i₂ = t₂.fst) : + PullbackCone (g₁ ≫ g₂) i₃ := + PullbackCone.mk t₁.fst (t₁.snd ≫ t₂.snd) + (by rw [reassoc_of% t₁.condition, Category.assoc, ← t₂.condition, ← hi₂]) + +variable (t₂ : PullbackCone g₂ i₃) {i₂ : t₂.pt ⟶ Y₂} (t₁ : PullbackCone g₁ i₂) (hi₂ : i₂ = t₂.fst) local notation "f₂" => t₂.snd local notation "X₁" => t₁.pt local notation "i₁" => t₁.fst local notation "f₁" => t₁.snd -/-- The `PullbackCone` obtained by pasting two `PullbackCone`'s horizontally -/ -abbrev PullbackCone.pasteHoriz : PullbackCone (g₁ ≫ g₂) i₃ := - PullbackCone.mk i₁ (f₁ ≫ f₂) - (by rw [reassoc_of% t₁.condition, Category.assoc, ← t₂.condition, ← hi₂]) - variable {t₁} {t₂} /-- Given @@ -154,8 +157,15 @@ to the top square. -/ variable {X₁ X₂ X₃ Y₁ : C} {f₁ : X₂ ⟶ X₁} {f₂ : X₃ ⟶ X₂} {i₁ : Y₁ ⟶ X₁} -variable (t₁ : PullbackCone i₁ f₁) {i₂ : t₁.pt ⟶ X₂} (t₂ : PullbackCone i₂ f₂) - (hi₂ : i₂ = t₁.snd) + +/-- The `PullbackCone` obtained by pasting two `PullbackCone`'s vertically -/ +abbrev PullbackCone.pasteVert + (t₁ : PullbackCone i₁ f₁) {i₂ : t₁.pt ⟶ X₂} (t₂ : PullbackCone i₂ f₂) (hi₂ : i₂ = t₁.snd) : + PullbackCone i₁ (f₂ ≫ f₁) := + PullbackCone.mk (t₂.fst ≫ t₁.fst) t₂.snd + (by rw [← reassoc_of% t₂.condition, Category.assoc, t₁.condition, ← hi₂]) + +variable (t₁ : PullbackCone i₁ f₁) {i₂ : t₁.pt ⟶ X₂} (t₂ : PullbackCone i₂ f₂) (hi₂ : i₂ = t₁.snd) local notation "Y₂" => t₁.pt local notation "g₁" => t₁.fst @@ -164,11 +174,6 @@ local notation "Y₃" => t₂.pt local notation "g₂" => t₂.fst local notation "i₃" => t₂.snd -/-- The `PullbackCone` obtained by pasting two `PullbackCone`'s vertically -/ -abbrev PullbackCone.pasteVert : PullbackCone i₁ (f₂ ≫ f₁) := - PullbackCone.mk (g₂ ≫ g₁) i₃ - (by rw [← reassoc_of% t₂.condition, Category.assoc, t₁.condition, ← hi₂]) - /-- Pasting two pullback cones vertically is isomorphic to the pullback cone obtained by flipping them, pasting horizontally, and then flipping the result again. -/ def PullbackCone.pasteVertFlip : (t₁.pasteVert t₂ hi₂).flip ≅ (t₁.flip.pasteHoriz t₂.flip hi₂) := @@ -237,8 +242,15 @@ Y₁ - g₁ -> Y₂ - g₂ -> Y₃ where `t₁` denotes the left pushout cocone, and `t₂` denotes the right pushout cocone. -/ variable {X₁ X₂ X₃ Y₁ : C} {f₁ : X₁ ⟶ X₂} {f₂ : X₂ ⟶ X₃} {i₁ : X₁ ⟶ Y₁} -variable (t₁ : PushoutCocone i₁ f₁) {i₂ : X₂ ⟶ t₁.pt} (t₂ : PushoutCocone i₂ f₂) -variable (hi₂ : i₂ = t₁.inr) + +/-- The pushout cocone obtained by pasting two pushout cocones horizontally. -/ +abbrev PushoutCocone.pasteHoriz + (t₁ : PushoutCocone i₁ f₁) {i₂ : X₂ ⟶ t₁.pt} (t₂ : PushoutCocone i₂ f₂) (hi₂ : i₂ = t₁.inr) : + PushoutCocone i₁ (f₁ ≫ f₂) := + PushoutCocone.mk (t₁.inl ≫ t₂.inl) t₂.inr + (by rw [reassoc_of% t₁.condition, Category.assoc, ← t₂.condition, ← hi₂]) + +variable (t₁ : PushoutCocone i₁ f₁) {i₂ : X₂ ⟶ t₁.pt} (t₂ : PushoutCocone i₂ f₂) (hi₂ : i₂ = t₁.inr) local notation "Y₂" => t₁.pt local notation "g₁" => t₁.inl @@ -247,11 +259,6 @@ local notation "Y₃" => t₂.pt local notation "g₂" => t₂.inl local notation "i₃" => t₂.inr -/-- The pushout cocone obtained by pasting two pushout cocones horizontally. -/ -abbrev PushoutCocone.pasteHoriz : PushoutCocone i₁ (f₁ ≫ f₂) := - PushoutCocone.mk (g₁ ≫ g₂) i₃ - (by rw [reassoc_of% t₁.condition, Category.assoc, ← t₂.condition, ← hi₂]) - variable {t₁} {t₂} /-- Given @@ -343,6 +350,13 @@ variable {Y₃ Y₂ Y₁ X₃ : C} {g₂ : Y₃ ⟶ Y₂} {g₁ : Y₂ ⟶ Y₁} variable (t₁ : PushoutCocone g₂ i₃) {i₂ : Y₂ ⟶ t₁.pt} (t₂ : PushoutCocone g₁ i₂) (hi₂ : i₂ = t₁.inl) +/-- The `PullbackCone` obtained by pasting two `PullbackCone`'s vertically -/ +abbrev PushoutCocone.pasteVert + (t₁ : PushoutCocone g₂ i₃) {i₂ : Y₂ ⟶ t₁.pt} (t₂ : PushoutCocone g₁ i₂) (hi₂ : i₂ = t₁.inl) : + PushoutCocone (g₂ ≫ g₁) i₃ := + PushoutCocone.mk t₂.inl (t₁.inr ≫ t₂.inr) + (by rw [← reassoc_of% t₁.condition, Category.assoc, t₂.condition, ← hi₂]) + local notation "X₂" => t₁.pt local notation "f₂" => t₁.inr local notation "i₂" => t₁.inl @@ -350,11 +364,6 @@ local notation "X₁" => t₂.pt local notation "f₁" => t₂.inr local notation "i₁" => t₂.inl -/-- The `PullbackCone` obtained by pasting two `PullbackCone`'s vertically -/ -abbrev PushoutCocone.pasteVert : PushoutCocone (g₂ ≫ g₁) i₃ := - PushoutCocone.mk i₁ (f₂ ≫ f₁) - (by rw [← reassoc_of% t₁.condition, Category.assoc, t₂.condition, ← hi₂]) - /-- Pasting two pushout cocones vertically is isomorphic to the pushout cocone obtained by flipping them, pasting horizontally, and then flipping the result again. -/ def PushoutCocone.pasteVertFlip : (t₁.pasteVert t₂ hi₂).flip ≅ (t₁.flip.pasteHoriz t₂.flip hi₂) := diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Pullback/PullbackCone.lean b/Mathlib/CategoryTheory/Limits/Shapes/Pullback/PullbackCone.lean index f56d21c18f129..5c57de436f965 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Pullback/PullbackCone.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Pullback/PullbackCone.lean @@ -23,7 +23,7 @@ t.pt ---t.snd---> Y v v X -----f------> Z ``` -The type `PullbackCone f g` is implemented as an abbrevation for `Cone (cospan f g)`, so general +The type `PullbackCone f g` is implemented as an abbreviation for `Cone (cospan f g)`, so general results about cones are also available for `PullbackCone f g`. * `PushoutCone f g`: Given morphisms `f : X ⟶ Y` and `g : X ⟶ Z`, a term `t : PushoutCone f g` diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Pullback/Square.lean b/Mathlib/CategoryTheory/Limits/Shapes/Pullback/Square.lean index 1584c6cc90a0d..2564e52fc6070 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Pullback/Square.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Pullback/Square.lean @@ -3,6 +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 -/ +import Mathlib.CategoryTheory.MorphismProperty.Limits import Mathlib.CategoryTheory.Square import Mathlib.CategoryTheory.Limits.Shapes.Pullback.CommSq @@ -11,7 +12,9 @@ import Mathlib.CategoryTheory.Limits.Shapes.Pullback.CommSq In this file, we translate the `IsPushout` and `IsPullback` API for the objects of the category `Square C` of commutative -squares in a category `C`. +squares in a category `C`. We also obtain lemmas which states +in this language that a pullback of a monomorphism is +a monomorphism (and similarly for pushouts of epimorphisms). -/ @@ -105,6 +108,40 @@ lemma IsPullback.op {sq : Square C} (h : sq.IsPullback) : sq.op.IsPushout := lemma IsPullback.unop {sq : Square Cᵒᵖ} (h : sq.IsPullback) : sq.unop.IsPushout := CategoryTheory.IsPullback.unop h.flip +namespace IsPullback + +variable (h : sq.IsPullback) + +include h + +lemma flip : sq.flip.IsPullback := CategoryTheory.IsPullback.flip h + +lemma mono_f₁₃ [Mono sq.f₂₄] : Mono sq.f₁₃ := + (MorphismProperty.StableUnderBaseChange.monomorphisms C) h (by assumption) + +lemma mono_f₁₂ [Mono sq.f₃₄] : Mono sq.f₁₂ := by + have : Mono sq.flip.f₂₄ := by dsimp; infer_instance + exact h.flip.mono_f₁₃ + +end IsPullback + +namespace IsPushout + +variable (h : sq.IsPushout) + +include h + +lemma flip : sq.flip.IsPushout := CategoryTheory.IsPushout.flip h + +lemma epi_f₂₄ [Epi sq.f₁₃] : Epi sq.f₂₄ := + (MorphismProperty.StableUnderCobaseChange.epimorphisms C) h (by assumption) + +lemma epi_f₃₄ [Epi sq.f₁₂] : Epi sq.f₃₄ := by + have : Epi sq.flip.f₁₃ := by dsimp; infer_instance + exact h.flip.epi_f₂₄ + +end IsPushout + end Square end CategoryTheory diff --git a/Mathlib/CategoryTheory/Limits/Shapes/SingleObj.lean b/Mathlib/CategoryTheory/Limits/Shapes/SingleObj.lean index 5168baa185fa4..e501871d0f757 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/SingleObj.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/SingleObj.lean @@ -72,7 +72,7 @@ section Colimits variable {G : Type v} [Group G] (J : SingleObj G ⥤ Type u) /-- The relation used to construct colimits in types for `J : SingleObj G ⥤ Type u` is -equivalent to the `MulAction.orbitRel` equivalence relation on `J.obj (SingleObj.star G)`. -/ +equivalent to the `MulAction.orbitRel` equivalence relation on `J.obj (SingleObj.star G)`. -/ lemma Types.Quot.Rel.iff_orbitRel (x y : J.obj (SingleObj.star G)) : Types.Quot.Rel J ⟨SingleObj.star G, x⟩ ⟨SingleObj.star G, y⟩ ↔ Setoid.Rel (MulAction.orbitRel G (J.obj (SingleObj.star G))) x y := by diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Types.lean b/Mathlib/CategoryTheory/Limits/Shapes/Types.lean index 80021b7b4364e..7718d1bc251fd 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Types.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Types.lean @@ -553,7 +553,7 @@ theorem coequalizer_preimage_image_eq_of_preimage_eq (π : Y ⟶ Z) (e : f ≫ (mono_iff_injective (h.coconePointUniqueUpToIso (coequalizerColimit f g).isColimit).inv).mp inferInstance e' - exact (eqv.eqvGen_iff.mp (EqvGen.mono lem (Quot.exact _ e'))).mp hy + exact (eqv.eqvGen_iff.mp (Relation.EqvGen.mono lem (Quot.eqvGen_exact e'))).mp hy · exact fun hx => ⟨_, hx, rfl⟩ /-- The categorical coequalizer in `Type u` is the quotient by `f g ~ g x`. -/ @@ -585,8 +585,8 @@ instance : HasPullbacks.{u} (Type u) := instance : HasPushouts.{u} (Type u) := hasPushouts_of_hasWidePushouts.{u} (Type u) -variable {X Y Z : Type u} -variable (f : X ⟶ Z) (g : Y ⟶ Z) +variable {X Y Z : Type u} {X' Y' Z' : Type v} +variable (f : X ⟶ Z) (g : Y ⟶ Z) (f' : X' ⟶ Z') (g' : Y' ⟶ Z') -- porting note (#5171): removed @[nolint has_nonempty_instance] /-- The usual explicit pullback in the category of types, as a subtype of the product. diff --git a/Mathlib/CategoryTheory/Limits/Shapes/WideEqualizers.lean b/Mathlib/CategoryTheory/Limits/Shapes/WideEqualizers.lean index c39731729d5e1..6193cbb5c6587 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/WideEqualizers.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/WideEqualizers.lean @@ -138,7 +138,7 @@ def diagramIsoParallelFamily (F : WalkingParallelFamily J ⥤ C) : rintro _ _ (_|_) <;> aesop_cat /-- `WalkingParallelPair` as a category is equivalent to a special case of -`WalkingParallelFamily`. -/ +`WalkingParallelFamily`. -/ @[simps!] def walkingParallelFamilyEquivWalkingParallelPair : WalkingParallelFamily.{w} (ULift Bool) ≌ WalkingParallelPair where diff --git a/Mathlib/CategoryTheory/Limits/Types.lean b/Mathlib/CategoryTheory/Limits/Types.lean index 1b69256ba80da..a5e6378568b97 100644 --- a/Mathlib/CategoryTheory/Limits/Types.lean +++ b/Mathlib/CategoryTheory/Limits/Types.lean @@ -548,7 +548,7 @@ theorem colimit_sound' {j j' : J} {x : F.obj j} {x' : F.obj j'} {j'' : J} variable {F} in theorem colimit_eq {j j' : J} {x : F.obj j} {x' : F.obj j'} (w : colimit.ι F j x = colimit.ι F j' x') : - EqvGen (Quot.Rel F) ⟨j, x⟩ ⟨j', x'⟩ := by + Relation.EqvGen (Quot.Rel F) ⟨j, x⟩ ⟨j', x'⟩ := by apply Quot.eq.1 simpa using congr_arg (colimitEquivQuot F) w diff --git a/Mathlib/CategoryTheory/Limits/TypesFiltered.lean b/Mathlib/CategoryTheory/Limits/TypesFiltered.lean index 48b2c53fe834a..3a9fd3a30e941 100644 --- a/Mathlib/CategoryTheory/Limits/TypesFiltered.lean +++ b/Mathlib/CategoryTheory/Limits/TypesFiltered.lean @@ -27,7 +27,7 @@ attribute [local instance] small_quot_of_hasColimit /- For filtered colimits of types, we can give an explicit description of the equivalence relation generated by the relation used to form - the colimit. -/ + the colimit. -/ /-- An alternative relation on `Σ j, F.obj j`, which generates the same equivalence relation as we use to define the colimit in `Type` above, @@ -44,10 +44,10 @@ theorem rel_of_quot_rel (x y : Σ j, F.obj j) : fun ⟨f, h⟩ => ⟨y.1, f, 𝟙 y.1, by rw [← h, FunctorToTypes.map_id_apply]⟩ theorem eqvGen_quot_rel_of_rel (x y : Σ j, F.obj j) : - FilteredColimit.Rel.{v, u} F x y → EqvGen (Quot.Rel F) x y := fun ⟨k, f, g, h⟩ => by - refine EqvGen.trans _ ⟨k, F.map f x.2⟩ _ ?_ ?_ - · exact (EqvGen.rel _ _ ⟨f, rfl⟩) - · exact (EqvGen.symm _ _ (EqvGen.rel _ _ ⟨g, h⟩)) + FilteredColimit.Rel.{v, u} F x y → Relation.EqvGen (Quot.Rel F) x y := fun ⟨k, f, g, h⟩ => by + refine Relation.EqvGen.trans _ ⟨k, F.map f x.2⟩ _ ?_ ?_ + · exact (Relation.EqvGen.rel _ _ ⟨f, rfl⟩) + · exact (Relation.EqvGen.symm _ _ (Relation.EqvGen.rel _ _ ⟨g, h⟩)) /-- Recognizing filtered colimits of types. -/ noncomputable def isColimitOf (t : Cocone F) (hsurj : ∀ x : t.pt, ∃ i xi, x = t.ι.app i xi) @@ -92,12 +92,12 @@ protected theorem rel_equiv : _root_.Equivalence (FilteredColimit.Rel.{v, u} F) _ = F.map (g' ≫ gl ≫ n) z.2 := by simp⟩ protected theorem rel_eq_eqvGen_quot_rel : - FilteredColimit.Rel.{v, u} F = EqvGen (Quot.Rel F) := by + FilteredColimit.Rel.{v, u} F = Relation.EqvGen (Quot.Rel F) := by ext ⟨j, x⟩ ⟨j', y⟩ constructor · apply eqvGen_quot_rel_of_rel · rw [← (FilteredColimit.rel_equiv F).eqvGen_iff] - exact EqvGen.mono (rel_of_quot_rel F) + exact Relation.EqvGen.mono (rel_of_quot_rel F) variable [HasColimit F] diff --git a/Mathlib/CategoryTheory/Limits/VanKampen.lean b/Mathlib/CategoryTheory/Limits/VanKampen.lean index 783314187e22d..fc1ab0865d6d2 100644 --- a/Mathlib/CategoryTheory/Limits/VanKampen.lean +++ b/Mathlib/CategoryTheory/Limits/VanKampen.lean @@ -7,7 +7,7 @@ import Mathlib.CategoryTheory.Adjunction.FullyFaithful import Mathlib.CategoryTheory.Adjunction.Limits import Mathlib.CategoryTheory.Limits.Shapes.Pullback.CommSq import Mathlib.CategoryTheory.Limits.Shapes.StrictInitial -import Mathlib.CategoryTheory.Limits.FunctorCategory +import Mathlib.CategoryTheory.Limits.FunctorCategory.Basic import Mathlib.CategoryTheory.Limits.Constructions.FiniteProductsOfBinaryProducts /-! diff --git a/Mathlib/CategoryTheory/Limits/Yoneda.lean b/Mathlib/CategoryTheory/Limits/Yoneda.lean index 1e0a5bb19da0e..8f2956bb7a8ef 100644 --- a/Mathlib/CategoryTheory/Limits/Yoneda.lean +++ b/Mathlib/CategoryTheory/Limits/Yoneda.lean @@ -3,7 +3,7 @@ Copyright (c) 2020 Scott Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Morrison, Bhavik Mehta -/ -import Mathlib.CategoryTheory.Limits.FunctorCategory +import Mathlib.CategoryTheory.Limits.FunctorCategory.Basic import Mathlib.CategoryTheory.Limits.Types import Mathlib.Util.AssertExists diff --git a/Mathlib/CategoryTheory/Linear/FunctorCategory.lean b/Mathlib/CategoryTheory/Linear/FunctorCategory.lean index 5ecd51cc0413a..ed03809f158c5 100644 --- a/Mathlib/CategoryTheory/Linear/FunctorCategory.lean +++ b/Mathlib/CategoryTheory/Linear/FunctorCategory.lean @@ -21,6 +21,11 @@ open CategoryTheory.Limits Linear variable {R : Type*} [Semiring R] variable {C D : Type*} [Category C] [Category D] [Preadditive D] [Linear R D] +#adaptation_note +/-- +At nightly-2024-08-08 we needed to significantly increase the maxHeartbeats here. +-/ +set_option maxHeartbeats 800000 in instance functorCategoryLinear : Linear R (C ⥤ D) where homModule F G := { smul := fun r α => diff --git a/Mathlib/CategoryTheory/Localization/CalculusOfFractions.lean b/Mathlib/CategoryTheory/Localization/CalculusOfFractions.lean index b6cc4f0377426..a46ca7ab8e22f 100644 --- a/Mathlib/CategoryTheory/Localization/CalculusOfFractions.lean +++ b/Mathlib/CategoryTheory/Localization/CalculusOfFractions.lean @@ -226,7 +226,7 @@ lemma LeftFraction.rightFraction_fac [W.HasRightCalculusOfFractions] {X Y : C} /-- The equivalence relation on left fractions for a morphism property `W`. -/ def LeftFractionRel {X Y : C} (z₁ z₂ : W.LeftFraction X Y) : Prop := - ∃ (Z : C) (t₁ : z₁.Y' ⟶ Z) (t₂ : z₂.Y' ⟶ Z) (_ : z₁.s ≫ t₁ = z₂.s ≫ t₂) + ∃ (Z : C) (t₁ : z₁.Y' ⟶ Z) (t₂ : z₂.Y' ⟶ Z) (_ : z₁.s ≫ t₁ = z₂.s ≫ t₂) (_ : z₁.f ≫ t₁ = z₂.f ≫ t₂), W (z₁.s ≫ t₁) namespace LeftFractionRel @@ -877,7 +877,7 @@ instance (W : MorphismProperty Cᵒᵖ) [h : W.HasRightCalculusOfFractions] : /-- The equivalence relation on right fractions for a morphism property `W`. -/ def RightFractionRel {X Y : C} (z₁ z₂ : W.RightFraction X Y) : Prop := - ∃ (Z : C) (t₁ : Z ⟶ z₁.X') (t₂ : Z ⟶ z₂.X') (_ : t₁ ≫ z₁.s = t₂ ≫ z₂.s) + ∃ (Z : C) (t₁ : Z ⟶ z₁.X') (t₂ : Z ⟶ z₂.X') (_ : t₁ ≫ z₁.s = t₂ ≫ z₂.s) (_ : t₁ ≫ z₁.f = t₂ ≫ z₂.f), W (t₁ ≫ z₁.s) lemma RightFractionRel.op {X Y : C} {z₁ z₂ : W.RightFraction X Y} diff --git a/Mathlib/CategoryTheory/Localization/CalculusOfFractions/Fractions.lean b/Mathlib/CategoryTheory/Localization/CalculusOfFractions/Fractions.lean index bf5ec2d0d65aa..465d603552c31 100644 --- a/Mathlib/CategoryTheory/Localization/CalculusOfFractions/Fractions.lean +++ b/Mathlib/CategoryTheory/Localization/CalculusOfFractions/Fractions.lean @@ -87,7 +87,7 @@ variable {W} for a morphism property `W`. The fact it is an equivalence relation is not formalized, but it would follow easily from `LeftFraction₂.map_eq_iff`. -/ def LeftFraction₂Rel {X Y : C} (z₁ z₂ : W.LeftFraction₂ X Y) : Prop := - ∃ (Z : C) (t₁ : z₁.Y' ⟶ Z) (t₂ : z₂.Y' ⟶ Z) (_ : z₁.s ≫ t₁ = z₂.s ≫ t₂) + ∃ (Z : C) (t₁ : z₁.Y' ⟶ Z) (t₂ : z₂.Y' ⟶ Z) (_ : z₁.s ≫ t₁ = z₂.s ≫ t₂) (_ : z₁.f ≫ t₁ = z₂.f ≫ t₂) (_ : z₁.f' ≫ t₁ = z₂.f' ≫ t₂), W (z₁.s ≫ t₁) namespace LeftFraction₂ diff --git a/Mathlib/CategoryTheory/Localization/DerivabilityStructure/Constructor.lean b/Mathlib/CategoryTheory/Localization/DerivabilityStructure/Constructor.lean index 916c45adea7b8..2adefbca8f183 100644 --- a/Mathlib/CategoryTheory/Localization/DerivabilityStructure/Constructor.lean +++ b/Mathlib/CategoryTheory/Localization/DerivabilityStructure/Constructor.lean @@ -87,7 +87,7 @@ lemma isConnected : refine ⟨RightResolution.mk ρ.w.left ρ.hw.1, ?_⟩ have := zigzag_obj_of_zigzag (fromRightResolution Φ L x ⋙ w.costructuredArrowDownwardsPrecomp x y g fac) - (isPreconnected_zigzag (RightResolution.mk (𝟙 _) (W₂.id_mem _)) + (isPreconnected_zigzag (RightResolution.mk (𝟙 _) (W₂.id_mem _)) (RightResolution.mk ρ.w.right ρ.hw.2)) refine Zigzag.trans ?_ (Zigzag.trans this ?_) · exact Zigzag.of_hom (eqToHom (by aesop)) diff --git a/Mathlib/CategoryTheory/Localization/HasLocalization.lean b/Mathlib/CategoryTheory/Localization/HasLocalization.lean index 4078cb38e28f0..76deb68f57da1 100644 --- a/Mathlib/CategoryTheory/Localization/HasLocalization.lean +++ b/Mathlib/CategoryTheory/Localization/HasLocalization.lean @@ -46,7 +46,7 @@ variable (W : MorphismProperty C) namespace MorphismProperty /-- The data of a localized category with a given universe -for the morphisms. -/ +for the morphisms. -/ class HasLocalization where /-- the objects of the localized category. -/ {D : Type u} diff --git a/Mathlib/CategoryTheory/Localization/Predicate.lean b/Mathlib/CategoryTheory/Localization/Predicate.lean index 0b955a5df9ff8..dd06454204670 100644 --- a/Mathlib/CategoryTheory/Localization/Predicate.lean +++ b/Mathlib/CategoryTheory/Localization/Predicate.lean @@ -369,7 +369,7 @@ lemma compLeft_iso (W) (F : D ⥤ E) : Localization.Lifting.iso L W (L ⋙ F) F /-- Given a localization functor `L : C ⥤ D` for `W : MorphismProperty C`, if `F₁' : D ⥤ E` lifts a functor `F₁ : C ⥤ D`, then a functor `F₂'` which -is isomorphic to `F₁'` also lifts a functor `F₂` that is isomorphic to `F₁`. -/ +is isomorphic to `F₁'` also lifts a functor `F₂` that is isomorphic to `F₁`. -/ @[simps] def ofIsos {F₁ F₂ : C ⥤ E} {F₁' F₂' : D ⥤ E} (e : F₁ ≅ F₂) (e' : F₁' ≅ F₂') [Lifting L W F₁ F₁'] : Lifting L W F₂ F₂' := diff --git a/Mathlib/CategoryTheory/Localization/Prod.lean b/Mathlib/CategoryTheory/Localization/Prod.lean index a5cffe4cf9a59..adb58aa11fea4 100644 --- a/Mathlib/CategoryTheory/Localization/Prod.lean +++ b/Mathlib/CategoryTheory/Localization/Prod.lean @@ -128,7 +128,7 @@ variable [W₁.ContainsIdentities] [W₂.ContainsIdentities] /-- If `L₁ : C₁ ⥤ D₁` and `L₂ : C₂ ⥤ D₂` are localization functors for `W₁ : MorphismProperty C₁` and `W₂ : MorphismProperty C₂` respectively, -and if both `W₁` and `W₂` contain identites, then the product +and if both `W₁` and `W₂` contain identities, then the product functor `L₁.prod L₂ : C₁ × C₂ ⥤ D₁ × D₂` is a localization functor for `W₁.prod W₂`. -/ instance prod [L₁.IsLocalization W₁] [L₂.IsLocalization W₂] : (L₁.prod L₂).IsLocalization (W₁.prod W₂) := by diff --git a/Mathlib/CategoryTheory/Localization/Resolution.lean b/Mathlib/CategoryTheory/Localization/Resolution.lean index 8afa0c3016b5f..33a2ffe3bd749 100644 --- a/Mathlib/CategoryTheory/Localization/Resolution.lean +++ b/Mathlib/CategoryTheory/Localization/Resolution.lean @@ -19,7 +19,7 @@ A right resolution consists of an object `X₁ : C₁` and a morphism The type of right resolutions `Φ.RightResolution X₂` is endowed with a category structure when the morphism property `W₁` is multiplicative. -Similiar definitions are done from left resolutions. +Similar definitions are done from left resolutions. ## Future works diff --git a/Mathlib/CategoryTheory/Localization/SmallHom.lean b/Mathlib/CategoryTheory/Localization/SmallHom.lean index 4f7063c5ba725..aa27e2567dea6 100644 --- a/Mathlib/CategoryTheory/Localization/SmallHom.lean +++ b/Mathlib/CategoryTheory/Localization/SmallHom.lean @@ -71,6 +71,17 @@ lemma hasSmallLocalizedHom_iff_of_isos {X' Y' : C} (e : X ≅ X') (e' : Y ≅ Y' simp only [hasSmallLocalizedHom_iff W W.Q] exact small_congr (Iso.homCongr (W.Q.mapIso e) (W.Q.mapIso e')) +variable (X) in +lemma hasSmallLocalizedHom_iff_target {Y Y' : C} (f : Y ⟶ Y') (hf : W f): + HasSmallLocalizedHom.{w} W X Y ↔ HasSmallLocalizedHom.{w} W X Y' := by + simp only [hasSmallLocalizedHom_iff W W.Q] + exact small_congr (Iso.homCongr (Iso.refl _) (Localization.isoOfHom W.Q W f hf)) + +lemma hasSmallLocalizedHom_iff_source {X' : C} (f : X ⟶ X') (hf : W f) (Y : C) : + HasSmallLocalizedHom.{w} W X Y ↔ HasSmallLocalizedHom.{w} W X' Y := by + simp only [hasSmallLocalizedHom_iff W W.Q] + exact small_congr (Iso.homCongr (Localization.isoOfHom W.Q W f hf) (Iso.refl _)) + end /-- The type of morphisms from `X` to `Y` in the localized category diff --git a/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean b/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean index 378b267f05134..0b4eb64c1f24f 100644 --- a/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean +++ b/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean @@ -36,15 +36,14 @@ namespace Localization section variable (X Y : C) +variable (M) -variable (M) in /-- Given objects `X` and `Y` in a category `C`, this is the property that all the types of morphisms from `X⟦a⟧` to `Y⟦b⟧` are `w`-small in the localized category with respect to a class of morphisms `W`. -/ abbrev HasSmallLocalizedShiftedHom : Prop := ∀ (a b : M), HasSmallLocalizedHom.{w} W (X⟦a⟧) (Y⟦b⟧) -variable (M) in lemma hasSmallLocalizedShiftedHom_iff (L : C ⥤ D) [L.IsLocalization W] [L.CommShift M] (X Y : C) : HasSmallLocalizedShiftedHom.{w} W M X Y ↔ @@ -55,15 +54,30 @@ lemma hasSmallLocalizedShiftedHom_iff dsimp at eq simp only [hasSmallLocalizedHom_iff _ L, eq] +variable {Y} in +lemma hasSmallLocalizedShiftedHom_iff_target [W.IsCompatibleWithShift M] + {Y' : C} (f : Y ⟶ Y') (hf : W f) : + HasSmallLocalizedShiftedHom.{w} W M X Y ↔ HasSmallLocalizedShiftedHom.{w} W M X Y' := + forall_congr' (fun a ↦ forall_congr' (fun b ↦ + hasSmallLocalizedHom_iff_target W (X⟦a⟧) (f⟦b⟧') (W.shift hf b))) + +variable {X} in +lemma hasSmallLocalizedShiftedHom_iff_source [W.IsCompatibleWithShift M] + {X' : C} (f : X ⟶ X') (hf : W f) (Y : C) : + HasSmallLocalizedShiftedHom.{w} W M X Y ↔ HasSmallLocalizedShiftedHom.{w} W M X' Y := + forall_congr' (fun a ↦ forall_congr' (fun b ↦ + hasSmallLocalizedHom_iff_source W (f⟦a⟧') (W.shift hf a) (Y⟦b⟧))) + variable [HasSmallLocalizedShiftedHom.{w} W M X Y] include M in -variable (M) in lemma hasSmallLocalizedHom_of_hasSmallLocalizedShiftedHom₀ : HasSmallLocalizedHom.{w} W X Y := (hasSmallLocalizedHom_iff_of_isos W ((shiftFunctorZero C M).app X) ((shiftFunctorZero C M).app Y)).1 inferInstance +variable {M} + instance (m : M) : HasSmallLocalizedHom.{w} W X (Y⟦m⟧) := (hasSmallLocalizedHom_iff_of_isos W ((shiftFunctorZero C M).app X) (Iso.refl (Y⟦m⟧))).1 inferInstance diff --git a/Mathlib/CategoryTheory/Monad/Adjunction.lean b/Mathlib/CategoryTheory/Monad/Adjunction.lean index ca2bf35b6796b..fa27fe0d27eff 100644 --- a/Mathlib/CategoryTheory/Monad/Adjunction.lean +++ b/Mathlib/CategoryTheory/Monad/Adjunction.lean @@ -73,7 +73,7 @@ def toComonad (h : L ⊣ R) : Comonad D where rw [← L.map_comp] simp -/-- The monad induced by the Eilenberg-Moore adjunction is the original monad. -/ +/-- The monad induced by the Eilenberg-Moore adjunction is the original monad. -/ @[simps!] def adjToMonadIso (T : Monad C) : T.adj.toMonad ≅ T := MonadIso.mk (NatIso.ofComponents fun X => Iso.refl _) @@ -84,7 +84,7 @@ def adjToComonadIso (G : Comonad C) : G.adj.toComonad ≅ G := ComonadIso.mk (NatIso.ofComponents fun X => Iso.refl _) /-- -Given an adjunction `L ⊣ R`, if `L ⋙ R` is abstractly isomorphic to the identity functor, then the +Given an adjunction `L ⊣ R`, if `L ⋙ R` is abstractly isomorphic to the identity functor, then the unit is an isomorphism. -/ def unitAsIsoOfIso (adj : L ⊣ R) (i : L ⋙ R ≅ 𝟭 C) : 𝟭 C ≅ L ⋙ R where @@ -100,11 +100,11 @@ def unitAsIsoOfIso (adj : L ⊣ R) (i : L ⋙ R ≅ 𝟭 C) : 𝟭 C ≅ L ⋙ R ext X exact (adj.toMonad.transport i).right_unit X -lemma isIso_unit_of_iso (adj : L ⊣ R) (i : L ⋙ R ≅ 𝟭 C) : IsIso adj.unit := +lemma isIso_unit_of_iso (adj : L ⊣ R) (i : L ⋙ R ≅ 𝟭 C) : IsIso adj.unit := (inferInstanceAs (IsIso (unitAsIsoOfIso adj i).hom)) /-- -Given an adjunction `L ⊣ R`, if `L ⋙ R` is isomorphic to the identity functor, then `L` is +Given an adjunction `L ⊣ R`, if `L ⋙ R` is isomorphic to the identity functor, then `L` is fully faithful. -/ noncomputable def fullyFaithfulLOfCompIsoId (adj : L ⊣ R) (i : L ⋙ R ≅ 𝟭 C) : L.FullyFaithful := @@ -112,7 +112,7 @@ noncomputable def fullyFaithfulLOfCompIsoId (adj : L ⊣ R) (i : L ⋙ R ≅ adj.fullyFaithfulLOfIsIsoUnit /-- -Given an adjunction `L ⊣ R`, if `R ⋙ L` is abstractly isomorphic to the identity functor, then the +Given an adjunction `L ⊣ R`, if `R ⋙ L` is abstractly isomorphic to the identity functor, then the counit is an isomorphism. -/ def counitAsIsoOfIso (adj : L ⊣ R) (j : R ⋙ L ≅ 𝟭 D) : R ⋙ L ≅ 𝟭 D where @@ -132,7 +132,7 @@ lemma isIso_counit_of_iso (adj : L ⊣ R) (j : R ⋙ L ≅ 𝟭 D) : IsIso adj.c inferInstanceAs (IsIso (counitAsIsoOfIso adj j).hom) /-- -Given an adjunction `L ⊣ R`, if `R ⋙ L` is isomorphic to the identity functor, then `R` is +Given an adjunction `L ⊣ R`, if `R ⋙ L` is isomorphic to the identity functor, then `R` is fully faithful. -/ noncomputable def fullyFaithfulROfCompIsoId (adj : L ⊣ R) (j : R ⋙ L ≅ 𝟭 D) : R.FullyFaithful := @@ -268,7 +268,7 @@ from `C` to the category of Eilenberg-Moore algebras for the adjunction is an eq class ComonadicLeftAdjoint (L : C ⥤ D) where /-- a choice of right adjoint for `L` -/ R : D ⥤ C - /-- `L` is a right adjoint -/ + /-- `L` is a left adjoint -/ adj : L ⊣ R eqv : (Comonad.comparison adj).IsEquivalence diff --git a/Mathlib/CategoryTheory/Monad/Basic.lean b/Mathlib/CategoryTheory/Monad/Basic.lean index 911f458280a80..d50e030211dde 100644 --- a/Mathlib/CategoryTheory/Monad/Basic.lean +++ b/Mathlib/CategoryTheory/Monad/Basic.lean @@ -250,7 +250,7 @@ variable {C} -/ /- Porting note: removed `@[simps (config := { rhsMd := semireducible })]` -and replaced with `@[simps]` in the two declarations below-/ +and replaced with `@[simps]` in the two declarations below -/ @[simps!] def MonadIso.toNatIso {M N : Monad C} (h : M ≅ N) : (M : C ⥤ C) ≅ N := (monadToFunctor C).mapIso h diff --git a/Mathlib/CategoryTheory/Monad/Comonadicity.lean b/Mathlib/CategoryTheory/Monad/Comonadicity.lean new file mode 100644 index 0000000000000..7aeb43cea5361 --- /dev/null +++ b/Mathlib/CategoryTheory/Monad/Comonadicity.lean @@ -0,0 +1,399 @@ +/- +Copyright (c) 2024 Jack McKoen. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Jack McKoen +-/ +import Mathlib.CategoryTheory.Limits.Preserves.Shapes.Equalizers +import Mathlib.CategoryTheory.Limits.Shapes.Reflexive +import Mathlib.CategoryTheory.Monad.Equalizer +import Mathlib.CategoryTheory.Monad.Limits + +/-! +# Comonadicity theorems + +We prove comonadicity theorems which can establish a given functor is comonadic. In particular, we +show three versions of Beck's comonadicity theorem, and the coreflexive (crude) +comonadicity theorem: + +`F` is a comonadic left adjoint if it has a right adjoint, and: + +* `C` has, `F` preserves and reflects `F`-split equalizers, see + `CategoryTheory.Monad.comonadicOfHasPreservesReflectsFSplitEqualizers` +* `F` creates `F`-split coequalizers, see + `CategoryTheory.Monad.comonadicOfCreatesFSplitEqualizers` + (The converse of this is also shown, see + `CategoryTheory.Monad.createsFSplitEqualizersOfComonadic`) +* `C` has and `F` preserves `F`-split equalizers, and `F` reflects isomorphisms, see + `CategoryTheory.Monad.comonadicOfHasPreservesFSplitEqualizersOfReflectsIsomorphisms` +* `C` has and `F` preserves coreflexive equalizers, and `F` reflects isomorphisms, see + `CategoryTheory.Monad.comonadicOfHasPreservesCoreflexiveEqualizersOfReflectsIsomorphisms` + +This file has been adapted from `Mathlib.CategoryTheory.Monad.Monadicity`. +Please try to keep them in sync. + +## Tags + +Beck, comonadicity, descent + +-/ + +universe v₁ v₂ u₁ u₂ + +namespace CategoryTheory + +namespace Comonad + +open Limits + +noncomputable section + +-- Hide the implementation details in this namespace. +namespace ComonadicityInternal + +variable {C : Type u₁} {D : Type u₂} +variable [Category.{v₁} C] [Category.{v₁} D] +variable {F : C ⥤ D} {G : D ⥤ C} (adj : F ⊣ G) + +/-- The "main pair" for a coalgebra `(A, α)` is the pair of morphisms `(G α, η_GA)`. It is always a +coreflexive pair, and will be used to construct the left adjoint to the comparison functor and show +it is an equivalence. +-/ +instance main_pair_coreflexive (A : adj.toComonad.Coalgebra) : + IsCoreflexivePair (G.map A.a) (adj.unit.app (G.obj A.A)) := by + apply IsCoreflexivePair.mk' (G.map (adj.counit.app _)) _ _ + · rw [← G.map_comp, ← G.map_id] + exact congr_arg G.map A.counit + · rw [adj.right_triangle_components] + rfl + +/-- The "main pair" for a coalgebra `(A, α)` is the pair of morphisms `(G α, η_GA)`. It is always a +`G`-cosplit pair, and will be used to construct the right adjoint to the comparison functor and show +it is an equivalence. +-/ +instance main_pair_F_cosplit (A : adj.toComonad.Coalgebra) : + F.IsCosplitPair (G.map A.a) + (adj.unit.app (G.obj A.A)) where + splittable := ⟨_, _, ⟨beckSplitEqualizer A⟩⟩ + +/-- The object function for the right adjoint to the comparison functor. -/ +def comparisonRightAdjointObj (A : adj.toComonad.Coalgebra) + [HasEqualizer (G.map A.a) (adj.unit.app _)] : C := + equalizer (G.map A.a) (adj.unit.app _) + +/-- +We have a bijection of homsets which will be used to construct the right adjoint to the comparison +functor. +-/ +@[simps!] +def comparisonRightAdjointHomEquiv (A : adj.toComonad.Coalgebra) (B : C) + [HasEqualizer (G.map A.a) (adj.unit.app (G.obj A.A))] : + ((comparison adj).obj B ⟶ A) ≃ (B ⟶ comparisonRightAdjointObj adj A) where + toFun f := by + refine equalizer.lift (adj.homEquiv _ _ f.f) ?_ + simp only [Adjunction.toComonad_coe, Functor.comp_obj, Adjunction.homEquiv_unit, + Functor.id_obj, Category.assoc, ← G.map_comp, ← f.h, comparison_obj_A, comparison_obj_a] + rw [Functor.comp_map, Functor.map_comp, Adjunction.unit_naturality_assoc, + Adjunction.unit_naturality] + invFun f := by + refine ⟨(adj.homEquiv _ _).symm (f ≫ (equalizer.ι _ _)), (adj.homEquiv _ _).injective ?_⟩ + simp only [Adjunction.toComonad_coe, Functor.comp_obj, comparison_obj_A, comparison_obj_a, + Adjunction.homEquiv_counit, Functor.id_obj, Functor.map_comp, Category.assoc, + Functor.comp_map, Adjunction.homEquiv_unit, Adjunction.unit_naturality_assoc, + Adjunction.unit_naturality, Adjunction.right_triangle_components_assoc] + congr 1 + exact (equalizer.condition _ _).symm + left_inv f := by aesop + right_inv f := by apply equalizer.hom_ext; simp + +/-- Construct the adjunction to the comparison functor. +-/ +def rightAdjointComparison + [∀ A : adj.toComonad.Coalgebra, HasEqualizer (G.map A.a) + (adj.unit.app (G.obj A.A))] : + adj.toComonad.Coalgebra ⥤ C := by + refine + Adjunction.rightAdjointOfEquiv (F := comparison adj) + (G_obj := fun A => comparisonRightAdjointObj adj A) (fun A B => ?_) ?_ + · apply comparisonRightAdjointHomEquiv + · intro A B B' g h + apply equalizer.hom_ext + simp + +/-- Provided we have the appropriate equalizers, we have an adjunction to the comparison functor. +-/ +@[simps! counit] +def comparisonAdjunction + [∀ A : adj.toComonad.Coalgebra, HasEqualizer (G.map A.a) + (adj.unit.app (G.obj A.A))] : + comparison adj ⊣ rightAdjointComparison adj := + Adjunction.adjunctionOfEquivRight _ _ + +variable {adj} + +theorem comparisonAdjunction_counit_f_aux + [∀ A : adj.toComonad.Coalgebra, HasEqualizer (G.map A.a) + (adj.unit.app (G.obj A.A))] + (A : adj.toComonad.Coalgebra) : + ((comparisonAdjunction adj).counit.app A).f = + (adj.homEquiv _ A.A).symm (equalizer.ι (G.map A.a) (adj.unit.app (G.obj A.A))) := + congr_arg (adj.homEquiv _ _).symm (Category.id_comp _) + +/-- This is a fork which is helpful for establishing comonadicity: the morphism from this fork to +the Beck equalizer is the counit for the adjunction on the comparison functor. +-/ +@[simps! pt] +def counitFork (A : adj.toComonad.Coalgebra) + [HasEqualizer (G.map A.a) (adj.unit.app (G.obj A.A))] : + Fork (F.map (G.map A.a)) (F.map (adj.unit.app (G.obj A.A))) := + Fork.ofι (F.map (equalizer.ι (G.map A.a) (adj.unit.app (G.obj A.A)))) + (by + change _ = F.map _ ≫ _ + rw [← F.map_comp, equalizer.condition, F.map_comp]) + +@[simp] +theorem unitFork_ι (A : adj.toComonad.Coalgebra) + [HasEqualizer (G.map A.a) (adj.unit.app (G.obj A.A))] : + (counitFork A).ι = F.map (equalizer.ι (G.map A.a) (adj.unit.app (G.obj A.A))) := + rfl + +theorem comparisonAdjunction_counit_f + [∀ A : adj.toComonad.Coalgebra, HasEqualizer (G.map A.a) + (adj.unit.app (G.obj A.A))] + (A : adj.toComonad.Coalgebra) : + ((comparisonAdjunction adj).counit.app A).f = (beckEqualizer A).lift (counitFork A) := by + simp + +variable (adj) + +/-- The fork which describes the unit of the adjunction: the morphism from this fork to the +the equalizer of this pair is the unit. +-/ +@[simps!] +def unitFork (B : C) : + Fork (G.map (F.map (adj.unit.app B))) + (adj.unit.app (G.obj (F.obj B))) := + Fork.ofι (adj.unit.app B) (adj.unit_naturality _) + +variable {adj} in +/-- The counit fork is a limit provided `F` preserves it. -/ +def counitLimitOfPreservesEqualizer (A : adj.toComonad.Coalgebra) + [HasEqualizer (G.map A.a) (adj.unit.app (G.obj A.A))] + [PreservesLimit (parallelPair (G.map A.a) (adj.unit.app (G.obj A.A))) F] : + IsLimit (counitFork (G := G) A) := + isLimitOfHasEqualizerOfPreservesLimit F _ _ + +/-- The unit fork is a limit provided `F` coreflects it. -/ +def unitEqualizerOfCoreflectsEqualizer (B : C) + [ReflectsLimit (parallelPair (G.map (F.map (adj.unit.app B))) + (adj.unit.app (G.obj (F.obj B)))) F] : + IsLimit (unitFork (adj := adj) B) := + isLimitOfIsLimitForkMap F _ (beckEqualizer ((comparison adj).obj B)) + +instance + [∀ A : adj.toComonad.Coalgebra, HasEqualizer (G.map A.a) (adj.unit.app (G.obj A.A))] + (B : C) : HasLimit (parallelPair + (G.map (F.map (NatTrans.app adj.unit B))) + (NatTrans.app adj.unit (G.obj (F.obj B)))) := + inferInstanceAs <| HasEqualizer + (G.map ((comparison adj).obj B).a) + (adj.unit.app (G.obj ((comparison adj).obj B).A)) + +theorem comparisonAdjunction_unit_app + [∀ A : adj.toComonad.Coalgebra, HasEqualizer (G.map A.a) (adj.unit.app (G.obj A.A))] (B : C) : + (comparisonAdjunction adj).unit.app B = limit.lift _ (unitFork adj B) := by + apply equalizer.hom_ext + change + equalizer.lift ((adj.homEquiv B _) (𝟙 _)) _ ≫ equalizer.ι _ _ = + equalizer.lift _ _ ≫ equalizer.ι _ _ + simp + +end ComonadicityInternal + +open CategoryTheory Adjunction Comonad ComonadicityInternal + +variable {C : Type u₁} {D : Type u₂} +variable [Category.{v₁} C] [Category.{v₁} D] +variable {F : C ⥤ D} {G : D ⥤ C} (adj : F ⊣ G) + +variable (G) in +/-- +If `F` is comonadic, it creates limits of `F`-cosplit pairs. This is the "boring" direction of +Beck's comonadicity theorem, the converse is given in `comonadicOfCreatesFSplitEqualizers`. +-/ +def createsFSplitEqualizersOfComonadic [ComonadicLeftAdjoint F] ⦃A B⦄ (f g : A ⟶ B) + [F.IsCosplitPair f g] : CreatesLimit (parallelPair f g) F := by + apply (config := {allowSynthFailures := true}) comonadicCreatesLimitOfPreservesLimit + · apply @preservesLimitOfIsoDiagram _ _ _ _ _ _ _ _ _ (diagramIsoParallelPair.{v₁} _).symm ?_ + dsimp + infer_instance + · apply @preservesLimitOfIsoDiagram _ _ _ _ _ _ _ _ _ (diagramIsoParallelPair.{v₁} _).symm ?_ + dsimp + infer_instance + +section BeckComonadicity + +/-- Dual to `Monad.HasCoequalizerOfIsSplitPair`. -/ +class HasEqualizerOfIsCosplitPair (F : C ⥤ D) : Prop where + /-- If `f, g` is an `F`-cosplit pair, then they have an equalizer. -/ + out : ∀ {A B} (f g : A ⟶ B) [F.IsCosplitPair f g], HasEqualizer f g + +instance [HasEqualizerOfIsCosplitPair F] : ∀ (A : Coalgebra adj.toComonad), + HasEqualizer (G.map A.a) + (adj.unit.app (G.obj A.A)) := + fun _ => HasEqualizerOfIsCosplitPair.out F _ _ + +/-- Dual to `Monad.PreservesColimitOfIsSplitPair`. -/ +class PreservesLimitOfIsCosplitPair (F : C ⥤ D) where + /-- If `f, g` is an `F`-cosplit pair, then `F` preserves limits of `parallelPair f g`. -/ + out : ∀ {A B} (f g : A ⟶ B) [F.IsCosplitPair f g], PreservesLimit (parallelPair f g) F + +instance {A B} (f g : A ⟶ B) [F.IsCosplitPair f g] [PreservesLimitOfIsCosplitPair F] : + PreservesLimit (parallelPair f g) F := PreservesLimitOfIsCosplitPair.out f g + +instance [PreservesLimitOfIsCosplitPair F] : ∀ (A : Coalgebra adj.toComonad), + PreservesLimit (parallelPair (G.map A.a) + (NatTrans.app adj.unit (G.obj A.A))) F := + fun _ => PreservesLimitOfIsCosplitPair.out _ _ + +/-- Dual to `Monad.ReflectsColimitOfIsSplitPair`. -/ +class ReflectsLimitOfIsCosplitPair (F : C ⥤ D) where + /-- If `f, g` is an `F`-cosplit pair, then `F` reflects limits for `parallelPair f g`. -/ + out : ∀ {A B} (f g : A ⟶ B) [F.IsCosplitPair f g], ReflectsLimit (parallelPair f g) F + +instance {A B} (f g : A ⟶ B) [F.IsCosplitPair f g] [ReflectsLimitOfIsCosplitPair F] : + ReflectsLimit (parallelPair f g) F := ReflectsLimitOfIsCosplitPair.out f g + +instance [ReflectsLimitOfIsCosplitPair F] : ∀ (A : Coalgebra adj.toComonad), + ReflectsLimit (parallelPair (G.map A.a) + (NatTrans.app adj.unit (G.obj A.A))) F := + fun _ => ReflectsLimitOfIsCosplitPair.out _ _ + +/-- To show `F` is a comonadic left adjoint, we can show it preserves and reflects `F`-split +equalizers, and `C` has them. +-/ +def comonadicOfHasPreservesReflectsFSplitEqualizers [HasEqualizerOfIsCosplitPair F] + [PreservesLimitOfIsCosplitPair F] [ReflectsLimitOfIsCosplitPair F] : + ComonadicLeftAdjoint F where + adj := adj + eqv := by + have : ∀ (X : Coalgebra adj.toComonad), IsIso ((comparisonAdjunction adj).counit.app X) := by + intro X + apply @isIso_of_reflects_iso _ _ _ _ _ _ _ (Comonad.forget adj.toComonad) ?_ _ + · change IsIso ((comparisonAdjunction adj).counit.app X).f + rw [comparisonAdjunction_counit_f] + change + IsIso + (IsLimit.conePointUniqueUpToIso (beckEqualizer X) + (counitLimitOfPreservesEqualizer X)).inv + exact (IsLimit.conePointUniqueUpToIso _ _).isIso_inv + have : ∀ (Y : C), IsIso ((comparisonAdjunction adj).unit.app Y) := by + intro Y + rw [comparisonAdjunction_unit_app] + change IsIso (IsLimit.conePointUniqueUpToIso _ ?_).inv + infer_instance + apply @unitEqualizerOfCoreflectsEqualizer _ _ _ _ _ _ _ _ ?_ + letI _ : + F.IsCosplitPair (G.map (F.map (adj.unit.app Y))) + (adj.unit.app (G.obj (F.obj Y))) := + ComonadicityInternal.main_pair_F_cosplit _ ((comparison adj).obj Y) + infer_instance + exact (comparisonAdjunction adj).toEquivalence.symm.isEquivalence_inverse + +/-- Dual to `Monad.CreatesColimitOfIsSplitPair`. -/ +class CreatesLimitOfIsCosplitPair (F : C ⥤ D) where + /-- If `f, g` is an `F`-cosplit pair, then `F` creates limits of `parallelPair f g`. -/ + out : ∀ {A B} (f g : A ⟶ B) [F.IsCosplitPair f g], CreatesLimit (parallelPair f g) F + +instance {A B} (f g : A ⟶ B) [F.IsCosplitPair f g] [CreatesLimitOfIsCosplitPair F] : + CreatesLimit (parallelPair f g) F := CreatesLimitOfIsCosplitPair.out f g + +instance [CreatesLimitOfIsCosplitPair F] : ∀ (A : Coalgebra adj.toComonad), + CreatesLimit (parallelPair (G.map A.a) + (NatTrans.app adj.unit (G.obj A.A))) F := + fun _ => CreatesLimitOfIsCosplitPair.out _ _ + +/-- +Beck's comonadicity theorem. If `F` has a right adjoint and creates equalizers of `F`-cosplit pairs, +then it is comonadic. +This is the converse of `createsFSplitEqualizersOfComonadic`. +-/ +def comonadicOfCreatesFSplitEqualizers [CreatesLimitOfIsCosplitPair F] : + ComonadicLeftAdjoint F := by + let I {A B} (f g : A ⟶ B) [F.IsCosplitPair f g] : HasLimit (parallelPair f g ⋙ F) := by + apply @hasLimitOfIso _ _ _ _ _ _ ?_ (diagramIsoParallelPair.{v₁} _).symm + exact inferInstanceAs <| HasEqualizer (F.map f) (F.map g) + have : HasEqualizerOfIsCosplitPair F := ⟨fun _ _ => hasLimit_of_created (parallelPair _ _) F⟩ + have : PreservesLimitOfIsCosplitPair F := ⟨by intros; infer_instance⟩ + have : ReflectsLimitOfIsCosplitPair F := ⟨by intros; infer_instance⟩ + exact comonadicOfHasPreservesReflectsFSplitEqualizers adj + +/-- An alternate version of Beck's comonadicity theorem. If `F` reflects isomorphisms, preserves +equalizers of `F`-cosplit pairs and `C` has equalizers of `F`-cosplit pairs, then it is comonadic. +-/ +def comonadicOfHasPreservesFSplitEqualizersOfReflectsIsomorphisms [F.ReflectsIsomorphisms] + [HasEqualizerOfIsCosplitPair F] [PreservesLimitOfIsCosplitPair F] : + ComonadicLeftAdjoint F := by + have : ReflectsLimitOfIsCosplitPair F := ⟨fun f g _ => by + have := HasEqualizerOfIsCosplitPair.out F f g + apply reflectsLimitOfReflectsIsomorphisms⟩ + apply comonadicOfHasPreservesReflectsFSplitEqualizers adj + +end BeckComonadicity + +section CoreflexiveComonadicity + +variable [HasCoreflexiveEqualizers C] [F.ReflectsIsomorphisms] + +/-- Dual to `Monad.PreservesColimitOfIsReflexivePair`. -/ +class PreservesLimitOfIsCoreflexivePair (F : C ⥤ D) where + /-- `f, g` is a coreflexive pair, then `F` preserves limits of `parallelPair f g`. -/ + out : ∀ ⦃A B⦄ (f g : A ⟶ B) [IsCoreflexivePair f g], PreservesLimit (parallelPair f g) F + +instance {A B} (f g : A ⟶ B) [IsCoreflexivePair f g] [PreservesLimitOfIsCoreflexivePair F] : + PreservesLimit (parallelPair f g) F := PreservesLimitOfIsCoreflexivePair.out f g + +instance [PreservesLimitOfIsCoreflexivePair F] : ∀ X : Coalgebra adj.toComonad, + PreservesLimit (parallelPair (G.map X.a) + (NatTrans.app adj.unit (G.obj X.A))) F := + fun _ => PreservesLimitOfIsCoreflexivePair.out _ _ + +variable [PreservesLimitOfIsCoreflexivePair F] + +/-- Coreflexive (crude) comonadicity theorem. If `F` has a right adjoint, `C` has and `F` preserves +coreflexive equalizers and `F` reflects isomorphisms, then `F` is comonadic. +-/ +def comonadicOfHasPreservesCoreflexiveEqualizersOfReflectsIsomorphisms : + ComonadicLeftAdjoint F where + adj := adj + eqv := by + have : ∀ (X : adj.toComonad.Coalgebra), IsIso ((comparisonAdjunction adj).counit.app X) := by + intro X + apply + @isIso_of_reflects_iso _ _ _ _ _ _ _ (Comonad.forget adj.toComonad) ?_ _ + · change IsIso ((comparisonAdjunction adj).counit.app X).f + rw [comparisonAdjunction_counit_f] + exact (IsLimit.conePointUniqueUpToIso (beckEqualizer X) + (counitLimitOfPreservesEqualizer X)).isIso_inv + have : ∀ (Y : C), IsIso ((comparisonAdjunction adj).unit.app Y) := by + intro Y + rw [comparisonAdjunction_unit_app] + change IsIso (IsLimit.conePointUniqueUpToIso _ ?_).inv + infer_instance + have : IsCoreflexivePair (G.map (F.map (adj.unit.app Y))) + (adj.unit.app (G.obj (F.obj Y))) := by + apply IsCoreflexivePair.mk' (G.map (adj.counit.app _)) _ _ + · rw [← G.map_comp, ← G.map_id] + exact congr_arg G.map (adj.left_triangle_components Y) + · rw [← G.map_id] + simp + apply @unitEqualizerOfCoreflectsEqualizer _ _ _ _ _ _ _ _ ?_ + apply reflectsLimitOfReflectsIsomorphisms + exact (comparisonAdjunction adj).toEquivalence.symm.isEquivalence_inverse + +end CoreflexiveComonadicity + +end + +end Comonad + +end CategoryTheory diff --git a/Mathlib/CategoryTheory/Monad/Monadicity.lean b/Mathlib/CategoryTheory/Monad/Monadicity.lean index 00f33ae1bf954..5dbca1937d5e9 100644 --- a/Mathlib/CategoryTheory/Monad/Monadicity.lean +++ b/Mathlib/CategoryTheory/Monad/Monadicity.lean @@ -14,7 +14,7 @@ import Mathlib.CategoryTheory.Monad.Limits We prove monadicity theorems which can establish a given functor is monadic. In particular, we show three versions of Beck's monadicity theorem, and the reflexive (crude) monadicity theorem: -`G` is a monadic right adjoint if it has a right adjoint, and: +`G` is a monadic right adjoint if it has a left adjoint, and: * `D` has, `G` preserves and reflects `G`-split coequalizers, see `CategoryTheory.Monad.monadicOfHasPreservesReflectsGSplitCoequalizers` @@ -27,13 +27,13 @@ show three versions of Beck's monadicity theorem, and the reflexive (crude) mona * `D` has and `G` preserves reflexive coequalizers, and `G` reflects isomorphisms, see `CategoryTheory.Monad.monadicOfHasPreservesReflexiveCoequalizersOfReflectsIsomorphisms` +This file has been adapted to `Mathlib.CategoryTheory.Monad.Comonadicity`. +Please try to keep them in sync. + ## Tags Beck, monadicity, descent -## TODO - -Dualise to show comonadicity theorems. -/ universe v₁ v₂ u₁ u₂ @@ -187,7 +187,7 @@ def counitCofork (B : D) : Cofork.ofπ (adj.counit.app B) (adj.counit_naturality _) variable {adj} in -/-- The unit cofork is a colimit provided `G` preserves it. -/ +/-- The unit cofork is a colimit provided `G` preserves it. -/ def unitColimitOfPreservesCoequalizer (A : adj.toMonad.Algebra) [HasCoequalizer (F.map A.a) (adj.counit.app (F.obj A.A))] [PreservesColimit (parallelPair (F.map A.a) (adj.counit.app (F.obj A.A))) G] : @@ -288,7 +288,7 @@ instance [ReflectsColimitOfIsSplitPair G] : ∀ (A : Algebra adj.toMonad), fun _ => ReflectsColimitOfIsSplitPair.out _ _ /-- To show `G` is a monadic right adjoint, we can show it preserves and reflects `G`-split -coequalizers, and `C` has them. +coequalizers, and `D` has them. -/ def monadicOfHasPreservesReflectsGSplitCoequalizers [HasCoequalizerOfIsSplitPair G] [PreservesColimitOfIsSplitPair G] [ReflectsColimitOfIsSplitPair G] : @@ -334,9 +334,9 @@ instance [CreatesColimitOfIsSplitPair G] : ∀ (A : Algebra adj.toMonad), fun _ => CreatesColimitOfIsSplitPair.out _ _ /-- -Beck's monadicity theorem. If `G` has a right adjoint and creates coequalizers of `G`-split pairs, +Beck's monadicity theorem. If `G` has a left adjoint and creates coequalizers of `G`-split pairs, then it is monadic. -This is the converse of `createsGSplitOfMonadic`. +This is the converse of `createsGSplitCoequalizersOfMonadic`. -/ def monadicOfCreatesGSplitCoequalizers [CreatesColimitOfIsSplitPair G] : MonadicRightAdjoint G := by diff --git a/Mathlib/CategoryTheory/Monoidal/Category.lean b/Mathlib/CategoryTheory/Monoidal/Category.lean index 53371440fcf7e..19ccf8685ca18 100644 --- a/Mathlib/CategoryTheory/Monoidal/Category.lean +++ b/Mathlib/CategoryTheory/Monoidal/Category.lean @@ -279,15 +279,6 @@ theorem tensorHom_def' {X₁ Y₁ X₂ Y₂ : C} (f : X₁ ⟶ Y₁) (g : X₂ f ⊗ g = X₁ ◁ g ≫ f ▷ Y₂ := whisker_exchange f g ▸ tensorHom_def f g -end MonoidalCategory - -open scoped MonoidalCategory -open MonoidalCategory - -variable {C : Type u} [𝒞 : Category.{v} C] [MonoidalCategory C] - -namespace MonoidalCategory - @[reassoc (attr := simp)] theorem whiskerLeft_hom_inv (X : C) {Y Z : C} (f : Y ≅ Z) : X ◁ f.hom ≫ X ◁ f.inv = 𝟙 (X ⊗ Y) := by @@ -384,11 +375,9 @@ lemma whiskerRightIso_trans {X Y Z : C} (f : X ≅ Y) (g : Y ≅ Z) (W : C) : lemma whiskerRightIso_symm {X Y : C} (f : X ≅ Y) (W : C) : (whiskerRightIso f W).symm = whiskerRightIso f.symm W := rfl -end MonoidalCategory - /-- The tensor product of two isomorphisms is an isomorphism. -/ @[simps] -def tensorIso {C : Type u} {X Y X' Y' : C} [Category.{v} C] [MonoidalCategory.{v} C] (f : X ≅ Y) +def tensorIso {X Y X' Y' : C} (f : X ≅ Y) (g : X' ≅ Y') : X ⊗ X' ≅ Y ⊗ Y' where hom := f.hom ⊗ g.hom inv := f.inv ⊗ g.inv @@ -398,11 +387,13 @@ def tensorIso {C : Type u} {X Y X' Y' : C} [Category.{v} C] [MonoidalCategory.{v /-- Notation for `tensorIso`, the tensor product of isomorphisms -/ infixr:70 " ⊗ " => tensorIso -namespace MonoidalCategory +theorem tensorIso_def {X Y X' Y' : C} (f : X ≅ Y) (g : X' ≅ Y') : + f ⊗ g = whiskerRightIso f X' ≪≫ whiskerLeftIso Y g := + Iso.ext (tensorHom_def f.hom g.hom) -section - -variable {C : Type u} [Category.{v} C] [MonoidalCategory.{v} C] +theorem tensorIso_def' {X Y X' Y' : C} (f : X ≅ Y) (g : X' ≅ Y') : + f ⊗ g = whiskerLeftIso X g ≪≫ whiskerRightIso f Y' := + Iso.ext (tensorHom_def' f.hom g.hom) instance tensor_isIso {W X Y Z : C} (f : W ⟶ X) [IsIso f] (g : Y ⟶ Z) [IsIso g] : IsIso (f ⊗ g) := (asIso f ⊗ asIso g).isIso_hom @@ -759,8 +750,6 @@ theorem tensor_left_iff {X Y : C} (f g : X ⟶ Y) : 𝟙 (𝟙_ C) ⊗ f = 𝟙 theorem tensor_right_iff {X Y : C} (f g : X ⟶ Y) : f ⊗ 𝟙 (𝟙_ C) = g ⊗ 𝟙 (𝟙_ C) ↔ f = g := by simp -end - section variable (C) diff --git a/Mathlib/CategoryTheory/Monoidal/Free/Coherence.lean b/Mathlib/CategoryTheory/Monoidal/Free/Coherence.lean index 4752b8432ea1e..267ea5f8e51c9 100644 --- a/Mathlib/CategoryTheory/Monoidal/Free/Coherence.lean +++ b/Mathlib/CategoryTheory/Monoidal/Free/Coherence.lean @@ -185,7 +185,7 @@ def normalizeIsoApp : | tensor X a, n => (α_ _ _ _).symm ≪≫ whiskerRightIso (normalizeIsoApp X n) a ≪≫ normalizeIsoApp _ _ -/-- Almost non-definitionally equall to `normalizeIsoApp`, but has a better definitional property +/-- Almost non-definitionally equal to `normalizeIsoApp`, but has a better definitional property in the proof of `normalize_naturality`. -/ @[simp] def normalizeIsoApp' : diff --git a/Mathlib/CategoryTheory/Monoidal/Rigid/Braided.lean b/Mathlib/CategoryTheory/Monoidal/Rigid/Braided.lean new file mode 100644 index 0000000000000..be429c98c1740 --- /dev/null +++ b/Mathlib/CategoryTheory/Monoidal/Rigid/Braided.lean @@ -0,0 +1,101 @@ +/- +Copyright (c) 2024 Gareth Ma. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Gareth Ma +-/ +import Mathlib.CategoryTheory.Monoidal.Rigid.Basic +import Mathlib.CategoryTheory.Monoidal.Braided.Basic + +/-! +# Deriving `RigidCategory` instance for braided and left/right rigid categories. +-/ + +open CategoryTheory Category BraidedCategory MonoidalCategory + +variable {C : Type*} [Category C] [MonoidalCategory C] [BraidedCategory C] {X Y : C} + +namespace CategoryTheory.BraidedCategory + +/-- coevaluation_evaluation' field of `ExactPairing Y X` in a braided category -/ +private theorem coevaluation_evaluation_braided' [inst : ExactPairing X Y] : + X ◁ (η_ X Y ≫ (β_ Y X).inv) ≫ (α_ X Y X).inv ≫ ((β_ X Y).hom ≫ ε_ X Y) ▷ X + = (ρ_ X).hom ≫ (λ_ X).inv := by + /- Rearrange into _ = 𝟙 _ -/ + rw [Iso.eq_comp_inv, ← Iso.inv_comp_eq_id] + /- Whitney trick transcribed: https://mathoverflow.net/a/162729/493261 -/ + calc + _ = 𝟙 X ⊗≫ X ◁ η_ X Y ⊗≫ (X ◁ (β_ Y X).inv ⊗≫ (β_ X Y).hom ▷ X) ⊗≫ ε_ X Y ▷ X ⊗≫ 𝟙 X := by + coherence + _ = 𝟙 X ⊗≫ X ◁ η_ X Y ⊗≫ (𝟙 (X ⊗ X ⊗ Y) ⊗≫ (β_ X X).hom ▷ Y ⊗≫ X ◁ (β_ X Y).hom + ⊗≫ (β_ Y X).inv ▷ X ⊗≫ Y ◁ (β_ X X).inv ⊗≫ 𝟙 ((Y ⊗ X) ⊗ X)) ⊗≫ ε_ X Y ▷ X ⊗≫ 𝟙 X := by + congr 3 + simp only [monoidalComp, MonoidalCoherence.assoc'_hom, MonoidalCoherence.whiskerRight_hom, + MonoidalCoherence.refl_hom, whiskerRight_tensor, id_whiskerRight, id_comp, Iso.inv_hom_id, + MonoidalCoherence.assoc_hom, comp_id] + rw [← IsIso.eq_inv_comp] + repeat rw [← assoc] + iterate 5 rw [← IsIso.comp_inv_eq] + simpa using yang_baxter X Y X + _ = 𝟙 X ⊗≫ (X ◁ η_ X Y ≫ (β_ X (X ⊗ Y)).hom) ⊗≫ ((β_ (Y ⊗ X) X).inv ≫ ε_ X Y ▷ X) ⊗≫ 𝟙 X := by + simp [monoidalComp, braiding_tensor_right, braiding_inv_tensor_left] + _ = _ := by + rw [braiding_naturality_right, ← braiding_inv_naturality_right] + simp [monoidalComp] + +/-- evaluation_coevaluation' field of `ExactPairing Y X` in a braided category -/ +private theorem evaluation_coevaluation_braided' [inst : ExactPairing X Y] : + (η_ X Y ≫ (β_ Y X).inv) ▷ Y ≫ (α_ Y X Y).hom ≫ Y ◁ ((β_ X Y).hom ≫ ε_ X Y) = + (λ_ Y).hom ≫ (ρ_ Y).inv := by + rw [Iso.eq_comp_inv, ← Iso.inv_comp_eq_id] + calc + _ = 𝟙 Y ⊗≫ η_ X Y ▷ Y ⊗≫ ((β_ Y X).inv ▷ Y ⊗≫ Y ◁ (β_ X Y).hom) ≫ Y ◁ ε_ X Y ⊗≫ 𝟙 Y := by + coherence + _ = 𝟙 Y ⊗≫ η_ X Y ▷ Y ⊗≫ (𝟙 ((X ⊗ Y) ⊗ Y) ⊗≫ X ◁ (β_ Y Y).hom ⊗≫ (β_ X Y).hom ▷ Y + ⊗≫ Y ◁ (β_ Y X).inv ⊗≫ (β_ Y Y).inv ▷ X ⊗≫ 𝟙 (Y ⊗ Y ⊗ X)) ⊗≫ Y ◁ ε_ X Y ⊗≫ 𝟙 Y := by + congr 3 + all_goals simp [monoidalComp] + iterate 2 rw [← IsIso.eq_inv_comp] + repeat rw [← assoc] + iterate 4 rw [← IsIso.comp_inv_eq] + simpa using (yang_baxter Y X Y).symm + _ = 𝟙 Y ⊗≫ (η_ X Y ▷ Y ≫ (β_ (X ⊗ Y) Y).hom) ⊗≫ ((β_ Y (Y ⊗ X)).inv ≫ Y ◁ ε_ X Y) ⊗≫ 𝟙 Y := by + simp [monoidalComp, braiding_tensor_left, braiding_inv_tensor_right] + _ = _ := by + rw [braiding_naturality_left, ← braiding_inv_naturality_left] + simp [monoidalComp] + +/-- If `X` and `Y` forms an exact pairing in a braided category, then so does `Y` and `X` +by composing the coevaluation and evaluation morphisms with associators. -/ +def exactPairing_swap (X Y : C) [ExactPairing X Y] : ExactPairing Y X where + coevaluation' := η_ X Y ≫ (β_ Y X).inv + evaluation' := (β_ X Y).hom ≫ ε_ X Y + coevaluation_evaluation' := coevaluation_evaluation_braided' + evaluation_coevaluation' := evaluation_coevaluation_braided' + +/-- If `X` has a right dual in a braided category, then it has a left dual. -/ +def hasLeftDualOfHasRightDual [HasRightDual X] : HasLeftDual X where + leftDual := Xᘁ + exact := exactPairing_swap X Xᘁ + +/-- If `X` has a left dual in a braided category, then it has a right dual. -/ +def hasRightDualOfHasLeftDual [HasLeftDual X] : HasRightDual X where + rightDual := ᘁX + exact := exactPairing_swap ᘁX X + +instance leftRigidCategoryOfRightRigidCategory [RightRigidCategory C] : LeftRigidCategory C where + leftDual X := hasLeftDualOfHasRightDual (X := X) + +instance rightRigidCategoryOfLeftRigidCategory [LeftRigidCategory C] : RightRigidCategory C where + rightDual X := hasRightDualOfHasLeftDual (X := X) + +/-- If `C` is a braided and right rigid category, then it is a rigid category. --/ +instance rigidCategoryOfRightRigidCategory [RightRigidCategory C] : RigidCategory C where + rightDual := inferInstance + leftDual := inferInstance + +/-- If `C` is a braided and left rigid category, then it is a rigid category. --/ +instance rigidCategoryOfLeftRigidCategory [LeftRigidCategory C] : RigidCategory C where + rightDual := inferInstance + leftDual := inferInstance + +end CategoryTheory.BraidedCategory diff --git a/Mathlib/CategoryTheory/Monoidal/Types/Basic.lean b/Mathlib/CategoryTheory/Monoidal/Types/Basic.lean index 0d62b9cef4f8b..77a4726af04a5 100644 --- a/Mathlib/CategoryTheory/Monoidal/Types/Basic.lean +++ b/Mathlib/CategoryTheory/Monoidal/Types/Basic.lean @@ -101,6 +101,6 @@ of a type to the image of that type, tensored with the image of the nth cartesia noncomputable def MonoidalFunctor.mapPi {C : Type*} [Category C] [MonoidalCategory C] (F : MonoidalFunctor (Type _) C) (n : ℕ) (β : Type*) : F.obj (Fin (n + 1) → β) ≅ F.obj β ⊗ F.obj (Fin n → β) := - Functor.mapIso _ (Equiv.piFinSucc n β).toIso ≪≫ (asIso (F.μ β (Fin n → β))).symm + Functor.mapIso _ (Fin.consEquiv _).symm.toIso ≪≫ (asIso (F.μ β (Fin n → β))).symm end CategoryTheory diff --git a/Mathlib/CategoryTheory/MorphismProperty/Basic.lean b/Mathlib/CategoryTheory/MorphismProperty/Basic.lean index 2590d4b476d56..8ec29dea73803 100644 --- a/Mathlib/CategoryTheory/MorphismProperty/Basic.lean +++ b/Mathlib/CategoryTheory/MorphismProperty/Basic.lean @@ -83,7 +83,7 @@ lemma inverseImage_iff (P : MorphismProperty D) (F : C ⥤ D) {X Y : C} (f : X /-- The image (up to isomorphisms) of a `MorphismProperty C` by a functor `C ⥤ D` -/ def map (P : MorphismProperty C) (F : C ⥤ D) : MorphismProperty D := fun _ _ f => - ∃ (X' Y' : C) (f' : X' ⟶ Y') (_ : P f'), Nonempty (Arrow.mk (F.map f') ≅ Arrow.mk f) + ∃ (X' Y' : C) (f' : X' ⟶ Y') (_ : P f'), Nonempty (Arrow.mk (F.map f') ≅ Arrow.mk f) lemma map_mem_map (P : MorphismProperty C) (F : C ⥤ D) {X Y : C} (f : X ⟶ Y) (hf : P f) : (P.map F) (F.map f) := ⟨X, Y, f, hf, ⟨Iso.refl _⟩⟩ diff --git a/Mathlib/CategoryTheory/MorphismProperty/Limits.lean b/Mathlib/CategoryTheory/MorphismProperty/Limits.lean index 67abe688058ef..e41f911a77318 100644 --- a/Mathlib/CategoryTheory/MorphismProperty/Limits.lean +++ b/Mathlib/CategoryTheory/MorphismProperty/Limits.lean @@ -52,6 +52,19 @@ theorem StableUnderBaseChange.mk {P : MorphismProperty C} [HasPullbacks C] [Resp rw [← P.cancel_left_of_respectsIso e.inv, sq.flip.isoPullback_inv_fst] exact hP₂ _ _ _ f g hg +variable (C) in +lemma StableUnderBaseChange.monomorphisms : + (monomorphisms C).StableUnderBaseChange := by + intro X Y Y' S f g f' g' h hg + have : Mono g := hg + constructor + intro Z f₁ f₂ h₁₂ + apply PullbackCone.IsLimit.hom_ext h.isLimit + · rw [← cancel_mono g] + dsimp + simp only [Category.assoc, h.w, reassoc_of% h₁₂] + · exact h₁₂ + theorem StableUnderBaseChange.respectsIso {P : MorphismProperty C} (hP : StableUnderBaseChange P) : RespectsIso P := by apply RespectsIso.of_respects_arrow_iso @@ -112,6 +125,19 @@ theorem StableUnderCobaseChange.mk {P : MorphismProperty C} [HasPushouts C] [Res rw [← P.cancel_right_of_respectsIso _ e.hom, sq.flip.inr_isoPushout_hom] exact hP₂ _ _ _ f g hf +variable (C) in +lemma StableUnderCobaseChange.epimorphisms : + (epimorphisms C).StableUnderCobaseChange := by + intro X Y Y' S f g f' g' h hf + have : Epi f := hf + constructor + intro Z f₁ f₂ h₁₂ + apply PushoutCocone.IsColimit.hom_ext h.isColimit + · exact h₁₂ + · rw [← cancel_epi f] + dsimp + simp only [← reassoc_of% h.w, h₁₂] + theorem StableUnderCobaseChange.respectsIso {P : MorphismProperty C} (hP : StableUnderCobaseChange P) : RespectsIso P := RespectsIso.of_respects_arrow_iso _ fun _ _ e => hP (IsPushout.of_horiz_isIso (CommSq.mk e.hom.w)) diff --git a/Mathlib/CategoryTheory/MorphismProperty/Representable.lean b/Mathlib/CategoryTheory/MorphismProperty/Representable.lean new file mode 100644 index 0000000000000..8bef529600a1b --- /dev/null +++ b/Mathlib/CategoryTheory/MorphismProperty/Representable.lean @@ -0,0 +1,254 @@ +/- +Copyright (c) 2024 Calle Sönne. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Calle Sönne, Joël Riou, Ravi Vakil +-/ + +import Mathlib.CategoryTheory.Limits.Shapes.Pullback.CommSq + +/-! + +# Relatively representable morphisms + +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 +`g : yoneda.obj X ⟶ G`, there exists a pullback square of the following form +``` + yoneda.obj Y --yoneda.map snd--> yoneda.obj X + | | + fst g + | | + v v + F ------------ f --------------> G +``` + +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`. + + + +## Main definitions +Throughout this file, `F : C ⥤ D` is a functor between categories `C` and `D`. + +* We define `relativelyRepresentable` as a `MorphsimProperty`. A morphism `f : X ⟶ Y` in `D` is + said to be relatively representable 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 + | | + fst g + | | + v v + X ------- f --------> Y +``` + +## API + +Given `hf : relativelyRepresentable f`, with `f : X ⟶ Y` and `g : F.obj a ⟶ Y`, we provide: +* `hf.pullback g` which is the object in `C` such that `F.obj (hf.pullback g)` is a + pullback of `f` and `g`. +* `hf.snd g` is the morphism `hf.pullback g ⟶ F.obj a` +* `hf.fst g` is the morphism `F.obj (hf.pullback g) ⟶ X` +* If `F` is full, and `f` is of type `F.obj c ⟶ G`, we also have `hf.fst' g : hf.pullback g ⟶ X` +which is the preimage under `F` of `hf.fst g`. +* `hom_ext`, `hom_ext'`, `lift`, `lift'` are variants of the universal property of + `F.obj (hf.pullback g)`, where as much as possible has been formulated internally to `C`. + For these theorems we also need that `F` is full and/or faithful. +* `symmetry` and `symmetryIso` are variants of the fact that pullbacks are symmetric for + representable morphisms, formulated internally to `C`. We assume that `F` is fully faithful here. + +-/ + +namespace CategoryTheory + +open Category Limits + +universe v₁ v₂ u₁ u₂ + +variable {C : Type u₁} [Category.{v₁} C] {D : Type u₂} [Category.{v₂} D] (F : C ⥤ D) + +/-- A morphism `f : X ⟶ Y` in `D` is said to be relatively representable 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 + | | + fst g + | | + v v + X ------- f --------> Y +``` +-/ +def Functor.relativelyRepresentable : MorphismProperty D := + fun X Y f ↦ ∀ ⦃a : C⦄ (g : F.obj a ⟶ Y), ∃ (b : C) (snd : b ⟶ a) + (fst : F.obj b ⟶ X), IsPullback fst (F.map snd) f g + +namespace Functor.relativelyRepresentable + +section + +variable {F} +variable {X Y : D} {f : X ⟶ Y} (hf : F.relativelyRepresentable f) + {b : C} {f' : F.obj b ⟶ Y} (hf' : F.relativelyRepresentable f') + {a : C} (g : F.obj a ⟶ Y) (hg : F.relativelyRepresentable g) + +/-- Let `f : X ⟶ Y` be a relatively representable morphism in `D`. Then, for any +`g : F.obj a ⟶ Y`, `hf.pullback g` denotes the (choice of) a corresponding object in `C` such that +there is a pullback square of the following form +``` +hf.pullback g --F.map snd--> F.obj a + | | + fst g + | | + v v + X ---------- f ----------> Y +``` -/ +noncomputable def pullback : C := + (hf g).choose + +/-- Given a representable morphism `f : X ⟶ Y`, then for any `g : F.obj a ⟶ Y`, `hf.snd g` +denotes the morphism in `C` giving rise to the following diagram +``` +hf.pullback g --F.map (hf.snd g)--> F.obj a + | | + fst g + | | + v v + X -------------- f -------------> Y +``` -/ +noncomputable abbrev snd : hf.pullback g ⟶ a := + (hf g).choose_spec.choose + +/-- Given a relatively representable morphism `f : X ⟶ Y`, then for any `g : F.obj a ⟶ Y`, +`hf.fst g` denotes the first projection in the following diagram, given by the defining property +of `f` being relatively representable +``` +hf.pullback g --F.map (hf.snd g)--> F.obj a + | | +hf.fst g g + | | + v v + X -------------- f -------------> Y +``` -/ +noncomputable abbrev fst : F.obj (hf.pullback g) ⟶ X := + (hf g).choose_spec.choose_spec.choose + +/-- When `F` is full, given a representable morphism `f' : F.obj b ⟶ Y`, then `hf'.fst' g` denotes +the preimage of `hf'.fst g` under `F`. -/ +noncomputable abbrev fst' [Full F] : hf'.pullback g ⟶ b := + F.preimage (hf'.fst g) + +lemma map_fst' [Full F] : F.map (hf'.fst' g) = hf'.fst g := + F.map_preimage _ + +lemma isPullback : IsPullback (hf.fst g) (F.map (hf.snd g)) f g := + (hf g).choose_spec.choose_spec.choose_spec + +@[reassoc] +lemma w : hf.fst g ≫ f = F.map (hf.snd g) ≫ g := (hf.isPullback g).w + +/-- Variant of the pullback square when `F` is full, and given `f' : F.obj b ⟶ Y`. -/ +lemma isPullback' [Full F] : IsPullback (F.map (hf'.fst' g)) (F.map (hf'.snd g)) f' g := + (hf'.map_fst' _) ▸ hf'.isPullback g + +@[reassoc] +lemma w' {X Y Z : C} {f : X ⟶ Z} (hf : F.relativelyRepresentable (F.map f)) (g : Y ⟶ Z) + [Full F] [Faithful F] : hf.fst' (F.map g) ≫ f = hf.snd (F.map g) ≫ g := + F.map_injective <| by simp [(hf.w (F.map g))] + +lemma isPullback_of_map {X Y Z : C} {f : X ⟶ Z} (hf : F.relativelyRepresentable (F.map f)) + (g : Y ⟶ Z) [Full F] [Faithful F] : + IsPullback (hf.fst' (F.map g)) (hf.snd (F.map g)) f g := + IsPullback.of_map F (hf.w' g) (hf.isPullback' (F.map g)) + +variable {g} + +/-- Two morphisms `a b : c ⟶ hf.pullback g` are equal if +* Their compositions (in `C`) with `hf.snd g : hf.pullback ⟶ X` are equal. +* The compositions of `F.map a` and `F.map b` with `hf.fst g` are equal. -/ +@[ext 100] +lemma hom_ext [Faithful F] {c : C} {a b : c ⟶ hf.pullback g} + (h₁ : F.map a ≫ hf.fst g = F.map b ≫ hf.fst g) + (h₂ : a ≫ hf.snd g = b ≫ hf.snd g) : a = b := + F.map_injective <| + PullbackCone.IsLimit.hom_ext (hf.isPullback g).isLimit h₁ (by simpa using F.congr_map h₂) + +/-- In the case of a representable morphism `f' : F.obj Y ⟶ G`, whose codomain lies +in the image of `F`, we get that two morphism `a b : Z ⟶ hf.pullback g` are equal if +* Their compositions (in `C`) with `hf'.snd g : hf.pullback ⟶ X` are equal. +* Their compositions (in `C`) with `hf'.fst' g : hf.pullback ⟶ Y` are equal. -/ +@[ext] +lemma hom_ext' [Full F] [Faithful F] {c : C} {a b : c ⟶ hf'.pullback g} + (h₁ : a ≫ hf'.fst' g = b ≫ hf'.fst' g) + (h₂ : a ≫ hf'.snd g = b ≫ hf'.snd g) : a = b := + hf'.hom_ext (by simpa [map_fst'] using F.congr_map h₁) h₂ + +section + +variable {c : C} (i : F.obj c ⟶ X) (h : c ⟶ a) (hi : i ≫ f = F.map h ≫ g) + +/-- The lift (in `C`) obtained from the universal property of `F.obj (hf.pullback g)`, in the +case when the cone point is in the image of `F.obj`. -/ +noncomputable def lift [Full F] : c ⟶ hf.pullback g := + F.preimage <| PullbackCone.IsLimit.lift (hf.isPullback g).isLimit _ _ hi + +@[reassoc (attr := simp)] +lemma lift_fst [Full F] : F.map (hf.lift i h hi) ≫ hf.fst g = i := by + simpa [lift] using PullbackCone.IsLimit.lift_fst _ _ _ _ + +@[reassoc (attr := simp)] +lemma lift_snd [Full F] [Faithful F] : hf.lift i h hi ≫ hf.snd g = h := + F.map_injective <| by simpa [lift] using PullbackCone.IsLimit.lift_snd _ _ _ _ + +end + +section + +variable {c : C} (i : c ⟶ b) (h : c ⟶ a) (hi : F.map i ≫ f' = F.map h ≫ g) + +/-- Variant of `lift` in the case when the domain of `f` lies in the image of `F.obj`. Thus, +in this case, one can obtain the lift directly by giving two morphisms in `C`. -/ +noncomputable def lift' [Full F] : c ⟶ hf'.pullback g := hf'.lift _ _ hi + +@[reassoc (attr := simp)] +lemma lift'_fst [Full F] [Faithful F] : hf'.lift' i h hi ≫ hf'.fst' g = i := + F.map_injective (by simp [map_fst', lift']) + +@[reassoc (attr := simp)] +lemma lift'_snd [Full F] [Faithful F] : hf'.lift' i h hi ≫ hf'.snd g = h := by + simp [lift'] + +end + +/-- Given two representable morphisms `f' : F.obj b ⟶ Y` and `g : F.obj a ⟶ Y`, we +obtain an isomorphism `hf'.pullback g ⟶ hg.pullback f'`. -/ +noncomputable def symmetry [Full F] : hf'.pullback g ⟶ hg.pullback f' := + hg.lift' (hf'.snd g) (hf'.fst' g) (hf'.isPullback' _).w.symm + +@[reassoc (attr := simp)] +lemma symmetry_fst [Full F] [Faithful F] : hf'.symmetry hg ≫ hg.fst' f' = hf'.snd g := by + simp [symmetry] + +@[reassoc (attr := simp)] +lemma symmetry_snd [Full F] [Faithful F] : hf'.symmetry hg ≫ hg.snd f' = hf'.fst' g := by + simp [symmetry] + +@[reassoc (attr := simp)] +lemma symmetry_symmetry [Full F] [Faithful F] : hf'.symmetry hg ≫ hg.symmetry hf' = 𝟙 _ := + hom_ext' hf' (by simp) (by simp) + +/-- The isomorphism given by `Presheaf.representable.symmetry`. -/ +@[simps] +noncomputable def symmetryIso [Full F] [Faithful F] : hf'.pullback g ≅ hg.pullback f' where + hom := hf'.symmetry hg + inv := hg.symmetry hf' + +instance [Full F] [Faithful F] : IsIso (hf'.symmetry hg) := + (hf'.symmetryIso hg).isIso_hom + +end + +end Functor.relativelyRepresentable + +end CategoryTheory diff --git a/Mathlib/CategoryTheory/Opposites.lean b/Mathlib/CategoryTheory/Opposites.lean index 8f3c692708837..901fde4a2fdcc 100644 --- a/Mathlib/CategoryTheory/Opposites.lean +++ b/Mathlib/CategoryTheory/Opposites.lean @@ -102,7 +102,7 @@ def unopUnop : Cᵒᵖᵒᵖ ⥤ C where obj X := unop (unop X) map f := f.unop.unop -/-- The functor from a category to its double-opposite. -/ +/-- The functor from a category to its double-opposite. -/ @[simps] def opOp : C ⥤ Cᵒᵖᵒᵖ where obj X := op (op X) diff --git a/Mathlib/CategoryTheory/PathCategory.lean b/Mathlib/CategoryTheory/PathCategory.lean index e27f6b40b20c9..126b988e6f0c5 100644 --- a/Mathlib/CategoryTheory/PathCategory.lean +++ b/Mathlib/CategoryTheory/PathCategory.lean @@ -59,10 +59,12 @@ def lift {C} [Category C] (φ : V ⥤q C) : Paths V ⥤ C where (fun _ f ihp => ihp ≫ φ.map f) Y f map_id X := rfl map_comp f g := by - induction' g with _ _ g' p ih _ _ _ - · rw [Category.comp_id] + induction g with + | nil => + rw [Category.comp_id] rfl - · have : f ≫ Quiver.Path.cons g' p = (f ≫ g').cons p := by apply Quiver.Path.comp_cons + | cons g' p ih => + have : f ≫ Quiver.Path.cons g' p = (f ≫ g').cons p := by apply Quiver.Path.comp_cons rw [this] simp only at ih ⊢ rw [ih, Category.assoc] @@ -98,10 +100,12 @@ theorem lift_unique {C} [Category C] (φ : V ⥤q C) (Φ : Paths V ⥤ C) rfl · rintro X Y f dsimp [lift] - induction' f with _ _ p f' ih - · simp only [Category.comp_id] + induction f with + | nil => + simp only [Category.comp_id] apply Functor.map_id - · simp only [Category.comp_id, Category.id_comp] at ih ⊢ + | cons p f' ih => + simp only [Category.comp_id, Category.id_comp] at ih ⊢ -- Porting note: Had to do substitute `p.cons f'` and `f'.toPath` by their fully qualified -- versions in this `have` clause (elsewhere too). have : Φ.map (Quiver.Path.cons p f') = Φ.map p ≫ Φ.map (Quiver.Hom.toPath f') := by diff --git a/Mathlib/CategoryTheory/Preadditive/Biproducts.lean b/Mathlib/CategoryTheory/Preadditive/Biproducts.lean index 2ea69885313e3..095fb3ea4d5cf 100644 --- a/Mathlib/CategoryTheory/Preadditive/Biproducts.lean +++ b/Mathlib/CategoryTheory/Preadditive/Biproducts.lean @@ -195,7 +195,7 @@ section HasBiproduct variable {J : Type} [Fintype J] {f : J → C} [HasBiproduct f] -/-- In any preadditive category, any biproduct satsifies +/-- In any preadditive category, any biproduct satisfies `∑ j : J, biproduct.π f j ≫ biproduct.ι f j = 𝟙 (⨁ f)` -/ @[simp] @@ -415,7 +415,7 @@ section variable {X Y : C} [HasBinaryBiproduct X Y] -/-- In any preadditive category, any binary biproduct satsifies +/-- In any preadditive category, any binary biproduct satisfies `biprod.fst ≫ biprod.inl + biprod.snd ≫ biprod.inr = 𝟙 (X ⊞ Y)`. -/ @[simp] diff --git a/Mathlib/CategoryTheory/Preadditive/Projective.lean b/Mathlib/CategoryTheory/Preadditive/Projective.lean index 8059a72c9ca40..6cf35147c2231 100644 --- a/Mathlib/CategoryTheory/Preadditive/Projective.lean +++ b/Mathlib/CategoryTheory/Preadditive/Projective.lean @@ -6,9 +6,8 @@ Authors: Markus Himmel, Scott Morrison import Mathlib.CategoryTheory.Adjunction.FullyFaithful import Mathlib.CategoryTheory.Adjunction.Limits import Mathlib.CategoryTheory.Limits.Constructions.EpiMono -import Mathlib.CategoryTheory.Limits.Shapes.Biproducts import Mathlib.CategoryTheory.Limits.Preserves.Finite -import Mathlib.CategoryTheory.Limits.Constructions.EpiMono +import Mathlib.CategoryTheory.Limits.Shapes.Biproducts /-! # Projective objects and categories with enough projectives diff --git a/Mathlib/CategoryTheory/Preadditive/Schur.lean b/Mathlib/CategoryTheory/Preadditive/Schur.lean index b8b9cfef7f7c0..5e012592ab269 100644 --- a/Mathlib/CategoryTheory/Preadditive/Schur.lean +++ b/Mathlib/CategoryTheory/Preadditive/Schur.lean @@ -66,7 +66,9 @@ noncomputable instance [HasKernels C] {X : C} [Simple X] : DivisionRing (End X) haveI := isIso_of_hom_simple hf exact IsIso.inv_hom_id f nnqsmul := _ + nnqsmul_def := fun q a => rfl qsmul := _ + qsmul_def := fun q a => rfl open FiniteDimensional diff --git a/Mathlib/CategoryTheory/Products/Associator.lean b/Mathlib/CategoryTheory/Products/Associator.lean index 1505c70e6c3bd..232fe7f3c5ea2 100644 --- a/Mathlib/CategoryTheory/Products/Associator.lean +++ b/Mathlib/CategoryTheory/Products/Associator.lean @@ -35,10 +35,12 @@ def inverseAssociator : C × D × E ⥤ (C × D) × E where /-- The equivalence of categories expressing associativity of products of categories. -/ -def associativity : (C × D) × E ≌ C × D × E := - Equivalence.mk (associator C D E) (inverseAssociator C D E) - (NatIso.ofComponents fun X => eqToIso (by simp)) - (NatIso.ofComponents fun X => eqToIso (by simp)) +@[simps] +def associativity : (C × D) × E ≌ C × D × E where + functor := associator C D E + inverse := inverseAssociator C D E + unitIso := Iso.refl _ + counitIso := Iso.refl _ instance associatorIsEquivalence : (associator C D E).IsEquivalence := (by infer_instance : (associativity C D E).functor.IsEquivalence) diff --git a/Mathlib/CategoryTheory/Products/Basic.lean b/Mathlib/CategoryTheory/Products/Basic.lean index 9d7207874a88a..449595eab85d3 100644 --- a/Mathlib/CategoryTheory/Products/Basic.lean +++ b/Mathlib/CategoryTheory/Products/Basic.lean @@ -147,11 +147,12 @@ def symmetry : swap C D ⋙ swap D C ≅ 𝟭 (C × D) where /-- The equivalence, given by swapping factors, between `C × D` and `D × C`. -/ -@[simps!] -def braiding : C × D ≌ D × C := - Equivalence.mk (swap C D) (swap D C) - (NatIso.ofComponents fun X => eqToIso (by simp)) - (NatIso.ofComponents fun X => eqToIso (by simp)) +@[simps] +def braiding : C × D ≌ D × C where + functor := swap C D + inverse := swap D C + unitIso := Iso.refl _ + counitIso := Iso.refl _ instance swapIsEquivalence : (swap C D).IsEquivalence := (by infer_instance : (braiding C D).functor.IsEquivalence) @@ -263,6 +264,12 @@ def prod {F G : A ⥤ B} {H I : C ⥤ D} (α : F ⟶ G) (β : H ⟶ I) : F.prod use instead `α.prod β` or `NatTrans.prod α β`. -/ end NatTrans +/-- The cartesian product functor between functor categories -/ +@[simps] +def prodFunctor : (A ⥤ B) × (C ⥤ D) ⥤ A × C ⥤ B × D where + obj FG := FG.1.prod FG.2 + map nm := NatTrans.prod nm.1 nm.2 + namespace NatIso /-- The cartesian product of two natural isomorphisms. -/ diff --git a/Mathlib/CategoryTheory/Products/Unitor.lean b/Mathlib/CategoryTheory/Products/Unitor.lean index f436f1074f993..7cb26c8bc22cf 100644 --- a/Mathlib/CategoryTheory/Products/Unitor.lean +++ b/Mathlib/CategoryTheory/Products/Unitor.lean @@ -42,7 +42,7 @@ def rightInverseUnitor : C ⥤ C × Discrete (PUnit : Type w) where obj X := ⟨X, ⟨PUnit.unit⟩⟩ map f := ⟨f, 𝟙 _⟩ -/-- The equivalence of categories expressing left unity of products of categories. -/ +/-- The equivalence of categories expressing left unity of products of categories. -/ @[simps] def leftUnitorEquivalence : Discrete (PUnit : Type w) × C ≌ C where functor := leftUnitor C @@ -50,7 +50,7 @@ def leftUnitorEquivalence : Discrete (PUnit : Type w) × C ≌ C where unitIso := Iso.refl _ counitIso := Iso.refl _ -/-- The equivalence of categories expressing right unity of products of categories. -/ +/-- The equivalence of categories expressing right unity of products of categories. -/ @[simps] def rightUnitorEquivalence : C × Discrete (PUnit : Type w) ≌ C where functor := rightUnitor C diff --git a/Mathlib/CategoryTheory/Shift/Localization.lean b/Mathlib/CategoryTheory/Shift/Localization.lean index ddedbb2626916..5e9f9b7a925b5 100644 --- a/Mathlib/CategoryTheory/Shift/Localization.lean +++ b/Mathlib/CategoryTheory/Shift/Localization.lean @@ -53,6 +53,10 @@ lemma shiftFunctor_comp_inverts (a : A) : end IsCompatibleWithShift +variable {A} in +lemma shift {X Y : C} {f : X ⟶ Y} (hf : W f) (a : A) : W (f⟦a⟧') := by + simpa only [IsCompatibleWithShift.iff W f a] using hf + variable {A} in /-- The morphism of localizer from `W` to `W` given by the functor `shiftFunctor C a` when `a : A` and `W` is compatible with the shift by `A`. -/ @@ -86,7 +90,7 @@ noncomputable def Functor.CommShift.localized : attribute [irreducible] HasShift.localized Functor.CommShift.localized -/-- The localized category `W.Localization` is endowed with the induced shift. -/ +/-- The localized category `W.Localization` is endowed with the induced shift. -/ noncomputable instance HasShift.localization : HasShift W.Localization A := HasShift.localized W.Q W A @@ -100,7 +104,7 @@ attribute [irreducible] HasShift.localization MorphismProperty.commShift_Q variable [W.HasLocalization] -/-- The localized category `W.Localization'` is endowed with the induced shift. -/ +/-- The localized category `W.Localization'` is endowed with the induced shift. -/ noncomputable instance HasShift.localization' : HasShift W.Localization' A := HasShift.localized W.Q' W A @@ -161,7 +165,7 @@ end commShiftOfLocalization /-- In the context of localization of categories, if a functor is induced by a functor which commutes with the shift, then -this functor commutes with the shift. -/ +this functor commutes with the shift. -/ noncomputable def commShiftOfLocalization : F'.CommShift A where iso := commShiftOfLocalization.iso L W F F' zero := by diff --git a/Mathlib/CategoryTheory/Shift/Quotient.lean b/Mathlib/CategoryTheory/Shift/Quotient.lean index 0aa245c4e4247..d029cd486c714 100644 --- a/Mathlib/CategoryTheory/Shift/Quotient.lean +++ b/Mathlib/CategoryTheory/Shift/Quotient.lean @@ -17,7 +17,7 @@ for all `a : A`), then the quotient category `Quotient r` is equipped with a shift. The condition `r.IsCompatibleWithShift A` on the relation `r` is a class so that -the shift can be automatically infered on the quotient category. +the shift can be automatically inferred on the quotient category. -/ diff --git a/Mathlib/CategoryTheory/Shift/ShiftedHom.lean b/Mathlib/CategoryTheory/Shift/ShiftedHom.lean index 9df10e3410095..09bea544345c6 100644 --- a/Mathlib/CategoryTheory/Shift/ShiftedHom.lean +++ b/Mathlib/CategoryTheory/Shift/ShiftedHom.lean @@ -28,7 +28,7 @@ variable {C : Type*} [Category C] {D : Type*} [Category D] {E : Type*} [Category {M : Type*} [AddMonoid M] [HasShift C M] [HasShift D M] [HasShift E M] /-- In a category `C` equipped with a shift by an additive monoid, -this is the type of morphisms `X ⟶ (Y⟦n⟧)` for `m : M`. -/ +this is the type of morphisms `X ⟶ (Y⟦n⟧)` for `m : M`. -/ def ShiftedHom (X Y : C) (m : M) : Type _ := X ⟶ (Y⟦m⟧) instance [Preadditive C] (X Y : C) (n : M) : AddCommGroup (ShiftedHom X Y n) := by diff --git a/Mathlib/CategoryTheory/SingleObj.lean b/Mathlib/CategoryTheory/SingleObj.lean index b7e8e14ddffd6..a3e3ca9146610 100644 --- a/Mathlib/CategoryTheory/SingleObj.lean +++ b/Mathlib/CategoryTheory/SingleObj.lean @@ -242,7 +242,7 @@ def toCat : MonCat ⥤ Cat where obj x := Cat.of (SingleObj x) map {x y} f := SingleObj.mapHom x y f -instance toCat_full : toCat.Full where +instance toCat_full : toCat.Full where map_surjective := (SingleObj.mapHom _ _).surjective instance toCat_faithful : toCat.Faithful where diff --git a/Mathlib/CategoryTheory/Sites/Adjunction.lean b/Mathlib/CategoryTheory/Sites/Adjunction.lean index a2aa3e4aa6b95..a3eb2ee7ed1ea 100644 --- a/Mathlib/CategoryTheory/Sites/Adjunction.lean +++ b/Mathlib/CategoryTheory/Sites/Adjunction.lean @@ -80,7 +80,6 @@ def adjunction [HasWeakSheafify J D] [HasSheafCompose J F] (adj : G ⊣ F) : ext dsimp [composeEquiv] erw [Adjunction.homEquiv_unit, Adjunction.homEquiv_unit] - dsimp simp } instance [HasWeakSheafify J D] [F.IsRightAdjoint] : (sheafCompose J F).IsRightAdjoint := diff --git a/Mathlib/CategoryTheory/Sites/Canonical.lean b/Mathlib/CategoryTheory/Sites/Canonical.lean index 756cf0d75719f..9c6a4291a3191 100644 --- a/Mathlib/CategoryTheory/Sites/Canonical.lean +++ b/Mathlib/CategoryTheory/Sites/Canonical.lean @@ -80,11 +80,7 @@ theorem isSheafFor_bind (P : Cᵒᵖ ⥤ Type v) (U : Sieve X) (B : ∀ ⦃Y⦄ intro Y l hl apply (hB' hf (l ≫ h)).ext intro M m hm - have : bind U B (m ≫ l ≫ h ≫ f) := by - -- Porting note: had to make explicit the parameter `((m ≫ l ≫ h) ≫ f)` and - -- using `by exact` - have : bind U B ((m ≫ l ≫ h) ≫ f) := by exact Presieve.bind_comp f hf hm - simpa using this + have : bind U B (m ≫ l ≫ h ≫ f) := by simpa using (Presieve.bind_comp f hf hm : bind U B _) trans s (m ≫ l ≫ h ≫ f) this · have := ht (U.downward_closed hf h) _ ((B _).downward_closed hl m) rw [op_comp, FunctorToTypes.map_comp_apply] at this diff --git a/Mathlib/CategoryTheory/Sites/CartesianClosed.lean b/Mathlib/CategoryTheory/Sites/CartesianClosed.lean new file mode 100644 index 0000000000000..130f67e3c181c --- /dev/null +++ b/Mathlib/CategoryTheory/Sites/CartesianClosed.lean @@ -0,0 +1,25 @@ +/- +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.Closed.Ideal +import Mathlib.CategoryTheory.Limits.FunctorCategory.Finite +import Mathlib.CategoryTheory.Sites.Limits +/-! + +# Sheaf categories are cartesian closed + +...if the underlying presheaf category is cartesian closed, the target category has finite products, +and there exists a sheafification functor. +-/ + +noncomputable section + +open CategoryTheory Limits + +variable {C : Type*} [Category C] (J : GrothendieckTopology C) (A : Type*) [Category A] + +instance [HasSheafify J A] [HasFiniteProducts A] [CartesianClosed (Cᵒᵖ ⥤ A)] : + CartesianClosed (Sheaf J A) := + cartesianClosedOfReflective (sheafToPresheaf _ _) diff --git a/Mathlib/CategoryTheory/Sites/Coherent/CoherentSheaves.lean b/Mathlib/CategoryTheory/Sites/Coherent/CoherentSheaves.lean index 9a132e3a51e8b..3525e9600b95a 100644 --- a/Mathlib/CategoryTheory/Sites/Coherent/CoherentSheaves.lean +++ b/Mathlib/CategoryTheory/Sites/Coherent/CoherentSheaves.lean @@ -15,8 +15,8 @@ This file characterises sheaves for the coherent topology ## Main result * `isSheaf_coherent`: a presheaf of types for the is a sheaf for the coherent topology if and only - if it satisfies the sheaf condition with respect to every presieve consiting of a finite effective - epimorphic family. + if it satisfies the sheaf condition with respect to every presieve consisting of a finite + effective epimorphic family. -/ namespace CategoryTheory diff --git a/Mathlib/CategoryTheory/Sites/Coherent/CoherentTopology.lean b/Mathlib/CategoryTheory/Sites/Coherent/CoherentTopology.lean index bd53932b0ed07..e3d81579f0701 100644 --- a/Mathlib/CategoryTheory/Sites/Coherent/CoherentTopology.lean +++ b/Mathlib/CategoryTheory/Sites/Coherent/CoherentTopology.lean @@ -29,7 +29,7 @@ Note: This is one direction of `mem_sieves_iff_hasEffectiveEpiFamily`, but is ne theorem coherentTopology.mem_sieves_of_hasEffectiveEpiFamily (S : Sieve X) : (∃ (α : Type) (_ : Finite α) (Y : α → C) (π : (a : α) → (Y a ⟶ X)), EffectiveEpiFamily Y π ∧ (∀ a : α, (S.arrows) (π a)) ) → - (S ∈ GrothendieckTopology.sieves (coherentTopology C) X) := by + (S ∈ (coherentTopology C) X) := by intro ⟨α, _, Y, π, hπ⟩ apply (coherentCoverage C).mem_toGrothendieck_sieves_of_superset (R := Presieve.ofArrows Y π) · exact fun _ _ h ↦ by cases h; exact hπ.2 _ @@ -49,7 +49,7 @@ theorem EffectiveEpiFamily.transitive_of_finite {α : Type} [Finite α] {Y : α (fun (c : Σ a, β a) => Y_n c.fst c.snd) (fun c => π_n c.fst c.snd ≫ π c.fst) := by rw [← Sieve.effectiveEpimorphic_family] suffices h₂ : (Sieve.generate (Presieve.ofArrows (fun (⟨a, b⟩ : Σ _, β _) => Y_n a b) - (fun ⟨a,b⟩ => π_n a b ≫ π a))) ∈ GrothendieckTopology.sieves (coherentTopology C) X by + (fun ⟨a,b⟩ => π_n a b ≫ π a))) ∈ (coherentTopology C) X by change Nonempty _ rw [← Sieve.forallYonedaIsSheaf_iff_colimit] exact fun W => coherentTopology.isSheaf_yoneda_obj W _ h₂ @@ -80,18 +80,21 @@ A sieve belongs to the coherent topology if and only if it contains a finite `EffectiveEpiFamily`. -/ theorem coherentTopology.mem_sieves_iff_hasEffectiveEpiFamily (S : Sieve X) : - (S ∈ GrothendieckTopology.sieves (coherentTopology C) X) ↔ + (S ∈ (coherentTopology C) X) ↔ (∃ (α : Type) (_ : Finite α) (Y : α → C) (π : (a : α) → (Y a ⟶ X)), EffectiveEpiFamily Y π ∧ (∀ a : α, (S.arrows) (π a)) ) := by constructor · intro h - induction' h with Y T hS Y Y R S _ _ a b - · obtain ⟨a, h, Y', π, h', _⟩ := hS + induction h with + | of Y T hS => + obtain ⟨a, h, Y', π, h', _⟩ := hS refine ⟨a, h, Y', π, inferInstance, fun a' ↦ ?_⟩ obtain ⟨rfl, _⟩ := h' exact ⟨Y' a', 𝟙 Y' a', π a', Presieve.ofArrows.mk a', by simp⟩ - · exact ⟨Unit, inferInstance, fun _ => Y, fun _ => (𝟙 Y), inferInstance, by simp⟩ - · obtain ⟨α, w, Y₁, π, ⟨h₁,h₂⟩⟩ := a + | top Y => + exact ⟨Unit, inferInstance, fun _ => Y, fun _ => (𝟙 Y), inferInstance, by simp⟩ + | transitive Y R S _ _ a b => + obtain ⟨α, w, Y₁, π, ⟨h₁,h₂⟩⟩ := a choose β _ Y_n π_n H using fun a => b (h₂ a) exact ⟨(Σ a, β a), inferInstance, fun ⟨a,b⟩ => Y_n a b, fun ⟨a, b⟩ => (π_n a b) ≫ (π a), EffectiveEpiFamily.transitive_of_finite _ h₁ _ (fun a => (H a).1), diff --git a/Mathlib/CategoryTheory/Sites/Coherent/Comparison.lean b/Mathlib/CategoryTheory/Sites/Coherent/Comparison.lean index 7c93c78272de3..f0f439fb8e122 100644 --- a/Mathlib/CategoryTheory/Sites/Coherent/Comparison.lean +++ b/Mathlib/CategoryTheory/Sites/Coherent/Comparison.lean @@ -78,9 +78,9 @@ theorem extensive_regular_generate_coherent [Preregular C] [FinitaryPreExtensive Set.mem_setOf_eq] exact Or.inr ⟨_, Sigma.desc f, ⟨rfl, inferInstance⟩⟩ · rintro R g ⟨W, ψ, σ, ⟨⟩, rfl⟩ - change _ ∈ sieves ((extensiveCoverage C) ⊔ (regularCoverage C)).toGrothendieck _ + change _ ∈ ((extensiveCoverage C) ⊔ (regularCoverage C)).toGrothendieck _ R rw [Sieve.pullback_comp] - apply pullback_stable' + apply pullback_stable have : generate (Presieve.ofArrows X fun (i : I) ↦ Sigma.ι X i) ≤ (generate (Presieve.ofArrows X f)).pullback (Sigma.desc f) := by rintro Q q ⟨E, e, r, ⟨hq, rfl⟩⟩ diff --git a/Mathlib/CategoryTheory/Sites/Coherent/Equivalence.lean b/Mathlib/CategoryTheory/Sites/Coherent/Equivalence.lean index e66a91cfd4c63..edc55d2e3f01e 100644 --- a/Mathlib/CategoryTheory/Sites/Coherent/Equivalence.lean +++ b/Mathlib/CategoryTheory/Sites/Coherent/Equivalence.lean @@ -9,7 +9,7 @@ import Mathlib.CategoryTheory.Sites.Equivalence # Coherence and equivalence of categories -This file proves that the coherent and regular topologies transfer nicely along equivalences of +This file proves that the coherent and regular topologies transfer nicely along equivalences of categories. -/ @@ -27,7 +27,7 @@ section Coherent variable [Precoherent C] -/-- `Precoherent` is preserved by equivalence of categories. -/ +/-- `Precoherent` is preserved by equivalence of categories. -/ theorem precoherent (e : C ≌ D) : Precoherent D := e.inverse.reflects_precoherent instance [EssentiallySmall C] : @@ -75,7 +75,7 @@ section Regular variable [Preregular C] -/-- `Preregular` is preserved by equivalence of categories. -/ +/-- `Preregular` is preserved by equivalence of categories. -/ theorem preregular (e : C ≌ D) : Preregular D := e.inverse.reflects_preregular instance [EssentiallySmall C] : diff --git a/Mathlib/CategoryTheory/Sites/Coherent/ExtensiveSheaves.lean b/Mathlib/CategoryTheory/Sites/Coherent/ExtensiveSheaves.lean index 4030384a506a2..ae209ddc24c1e 100644 --- a/Mathlib/CategoryTheory/Sites/Coherent/ExtensiveSheaves.lean +++ b/Mathlib/CategoryTheory/Sites/Coherent/ExtensiveSheaves.lean @@ -62,7 +62,7 @@ instance {α : Type} [Finite α] (Z : α → C) : (ofArrows Z (fun i ↦ Sigma. /-- Every Yoneda-presheaf is a sheaf for the extensive topology. -/ theorem extensiveTopology.isSheaf_yoneda_obj (W : C) : Presieve.IsSheaf (extensiveTopology C) (yoneda.obj W) := by - erw [isSheaf_coverage] + rw [extensiveTopology, isSheaf_coverage] intro X R ⟨Y, α, Z, π, hR, hi⟩ have : IsIso (Sigma.desc (Cofan.inj (Cofan.mk X π))) := hi have : R.Extensive := ⟨Y, α, Z, π, hR, ⟨Cofan.isColimitOfIsIsoSigmaDesc (Cofan.mk X π)⟩⟩ @@ -75,19 +75,19 @@ theorem extensiveTopology.subcanonical : Sheaf.Subcanonical (extensiveTopology C variable [FinitaryExtensive C] /-- -A presheaf of sets on a category which is `FinitaryExtensive` is a sheaf iff it preserves finite +A presheaf of sets on a category which is `FinitaryExtensive` is a sheaf iff it preserves finite products. -/ theorem Presieve.isSheaf_iff_preservesFiniteProducts (F : Cᵒᵖ ⥤ Type w) : Presieve.IsSheaf (extensiveTopology C) F ↔ Nonempty (PreservesFiniteProducts F) := by refine ⟨fun hF ↦ ⟨⟨fun α _ ↦ ⟨fun {K} ↦ ?_⟩⟩⟩, fun hF ↦ ?_⟩ - · erw [Presieve.isSheaf_coverage] at hF + · rw [extensiveTopology, isSheaf_coverage] at hF let Z : α → C := fun i ↦ unop (K.obj ⟨i⟩) - have : (Presieve.ofArrows Z (Cofan.mk (∐ Z) (Sigma.ι Z)).inj).hasPullbacks := - (inferInstance : (Presieve.ofArrows Z (Sigma.ι Z)).hasPullbacks) + have : (ofArrows Z (Cofan.mk (∐ Z) (Sigma.ι Z)).inj).hasPullbacks := + inferInstanceAs (ofArrows Z (Sigma.ι Z)).hasPullbacks have : ∀ (i : α), Mono (Cofan.inj (Cofan.mk (∐ Z) (Sigma.ι Z)) i) := - (inferInstance : ∀ (i : α), Mono (Sigma.ι Z i)) + inferInstanceAs <| ∀ (i : α), Mono (Sigma.ι Z i) let i : K ≅ Discrete.functor (fun i ↦ op (Z i)) := Discrete.natIsoFunctor let _ : PreservesLimit (Discrete.functor (fun i ↦ op (Z i))) F := Presieve.preservesProductOfIsSheafFor F ?_ initialIsInitial _ (coproductIsCoproduct Z) @@ -104,14 +104,14 @@ theorem Presieve.isSheaf_iff_preservesFiniteProducts (F : Cᵒᵖ ⥤ Type w) : ext simp · let _ := hF.some - erw [Presieve.isSheaf_coverage] + rw [extensiveTopology, Presieve.isSheaf_coverage] intro X R ⟨Y, α, Z, π, hR, hi⟩ have : IsIso (Sigma.desc (Cofan.inj (Cofan.mk X π))) := hi have : R.Extensive := ⟨Y, α, Z, π, hR, ⟨Cofan.isColimitOfIsIsoSigmaDesc (Cofan.mk X π)⟩⟩ exact isSheafFor_extensive_of_preservesFiniteProducts R F /-- -A presheaf on a category which is `FinitaryExtensive` is a sheaf iff it preserves finite products. +A presheaf on a category which is `FinitaryExtensive` is a sheaf iff it preserves finite products. -/ theorem Presheaf.isSheaf_iff_preservesFiniteProducts (F : Cᵒᵖ ⥤ D) : IsSheaf (extensiveTopology C) F ↔ Nonempty (PreservesFiniteProducts F) := by diff --git a/Mathlib/CategoryTheory/Sites/Coherent/ExtensiveTopology.lean b/Mathlib/CategoryTheory/Sites/Coherent/ExtensiveTopology.lean index 5a8be00569068..1f7872d648175 100644 --- a/Mathlib/CategoryTheory/Sites/Coherent/ExtensiveTopology.lean +++ b/Mathlib/CategoryTheory/Sites/Coherent/ExtensiveTopology.lean @@ -24,7 +24,7 @@ variable {C : Type*} [Category C] [FinitaryPreExtensive C] namespace CategoryTheory lemma extensiveTopology.mem_sieves_iff_contains_colimit_cofan {X : C} (S : Sieve X) : - S ∈ (extensiveTopology C).sieves X ↔ + S ∈ (extensiveTopology C) X ↔ (∃ (α : Type) (_ : Finite α) (Y : α → C) (π : (a : α) → (Y a ⟶ X)), Nonempty (IsColimit (Cofan.mk X π)) ∧ (∀ a : α, (S.arrows) (π a))) := by constructor @@ -53,7 +53,8 @@ lemma extensiveTopology.mem_sieves_iff_contains_colimit_cofan {X : C} (S : Sieve apply (extensiveCoverage C).mem_toGrothendieck_sieves_of_superset (R := Presieve.ofArrows Y π) · exact fun _ _ hh ↦ by cases hh; exact h' _ · refine ⟨α, inferInstance, Y, π, rfl, ?_⟩ - erw [Limits.Cofan.isColimit_iff_isIso_sigmaDesc (c := Cofan.mk X π)] + rw [show IsIso (Sigma.desc π) ↔ _ from + Limits.Cofan.isColimit_iff_isIso_sigmaDesc (c := Cofan.mk X π)] exact h end CategoryTheory diff --git a/Mathlib/CategoryTheory/Sites/Coherent/LocallySurjective.lean b/Mathlib/CategoryTheory/Sites/Coherent/LocallySurjective.lean index ef1204a732163..3a79842c88fc9 100644 --- a/Mathlib/CategoryTheory/Sites/Coherent/LocallySurjective.lean +++ b/Mathlib/CategoryTheory/Sites/Coherent/LocallySurjective.lean @@ -16,14 +16,14 @@ and extensive topologies. ## Main results * `regularTopology.isLocallySurjective_iff` A morphism of presheaves `f : F ⟶ G` is locally - surjective for the regular topology iff for every object `X` of `C`, and every `y : G(X)`, there - is an effective epimorphism `φ : X' ⟶ X` and an `x : F(X)` such that `f_{X'}(x) = G(φ)(y)`. + surjective for the regular topology iff for every object `X` of `C`, and every `y : G(X)`, there + is an effective epimorphism `φ : X' ⟶ X` and an `x : F(X)` such that `f_{X'}(x) = G(φ)(y)`. * `coherentTopology.isLocallySurjective_iff` a morphism of sheaves for the coherent topology on a preregular finitary extensive category is locally surjective if and only if it is locally surjective for the regular topology. -* `extensiveTopology.isLocallySurjective_iff` a morphism of sheaves for the extensive topology on a +* `extensiveTopology.isLocallySurjective_iff` a morphism of sheaves for the extensive topology on a finitary extensive category is locally surjective iff it is objectwise surjective. -/ @@ -78,9 +78,9 @@ lemma extensiveTopology.surjective_of_isLocallySurjective_sheafOfTypes [Finitary Cofan.mk_ι_app] have : f.app ⟨Y a⟩ (y a) = G.map (π a).op x := (h' a).choose_spec change _ = G.map (π a).op x - erw [← this, ← NatTrans.naturality_apply (φ := f)] - apply congrArg - change (i.hom ≫ F.map (π a).op) y = _ + rw [← this] + erw [← NatTrans.naturality_apply (φ := f)] + change f.app _ ((i.hom ≫ F.map (π a).op) y) = _ erw [IsLimit.map_π] rfl diff --git a/Mathlib/CategoryTheory/Sites/Coherent/ReflectsPrecoherent.lean b/Mathlib/CategoryTheory/Sites/Coherent/ReflectsPrecoherent.lean index a42e9b7bca302..54bc130f05abb 100644 --- a/Mathlib/CategoryTheory/Sites/Coherent/ReflectsPrecoherent.lean +++ b/Mathlib/CategoryTheory/Sites/Coherent/ReflectsPrecoherent.lean @@ -11,8 +11,8 @@ import Mathlib.CategoryTheory.Sites.Coherent.CoherentTopology # Reflecting the property of being precoherent We prove that given a fully faithful functor `F : C ⥤ D` which preserves and reflects finite -effective epimorphic families, such that for every object `X` of `D` there exists an object `W` of -`C` with an effective epi `π : F.obj W ⟶ X`, the category `C` is `Precoherent` whenever `D` is. +effective epimorphic families, such that for every object `X` of `D` there exists an object `W` of +`C` with an effective epi `π : F.obj W ⟶ X`, the category `C` is `Precoherent` whenever `D` is. -/ namespace CategoryTheory diff --git a/Mathlib/CategoryTheory/Sites/Coherent/ReflectsPreregular.lean b/Mathlib/CategoryTheory/Sites/Coherent/ReflectsPreregular.lean index 9b3784170505c..58eef6dd8e4c3 100644 --- a/Mathlib/CategoryTheory/Sites/Coherent/ReflectsPreregular.lean +++ b/Mathlib/CategoryTheory/Sites/Coherent/ReflectsPreregular.lean @@ -11,8 +11,8 @@ import Mathlib.CategoryTheory.Sites.Coherent.RegularTopology # Reflecting the property of being preregular We prove that given a fully faithful functor `F : C ⥤ D`, with `Preregular D`, such that for every -object `X` of `D` there exists an object `W` of `C` with an effective epi `π : F.obj W ⟶ X`, the -category `C` is `Preregular`. +object `X` of `D` there exists an object `W` of `C` with an effective epi `π : F.obj W ⟶ X`, the +category `C` is `Preregular`. -/ namespace CategoryTheory diff --git a/Mathlib/CategoryTheory/Sites/Coherent/RegularSheaves.lean b/Mathlib/CategoryTheory/Sites/Coherent/RegularSheaves.lean index 0fe6215a09392..e310d8b283782 100644 --- a/Mathlib/CategoryTheory/Sites/Coherent/RegularSheaves.lean +++ b/Mathlib/CategoryTheory/Sites/Coherent/RegularSheaves.lean @@ -17,7 +17,7 @@ This file characterises sheaves for the regular topology. ## Main results -* `equalizerCondition_iff_isSheaf`: In a preregular category with pullbacks, the sheaves for the +* `equalizerCondition_iff_isSheaf`: In a preregular category with pullbacks, the sheaves for the regular topology are precisely the presheaves satisfying an equaliser condition with respect to effective epimorphisms. @@ -46,7 +46,7 @@ lemma equalizerCondition_w (P : Cᵒᵖ ⥤ D) {X B : C} {π : X ⟶ B} (c : Pul simp only [← Functor.map_comp, ← op_comp, c.condition] /-- -A contravariant functor on `C` satisifies `SingleEqualizerCondition` with respect to a morphism `π` +A contravariant functor on `C` satisfies `SingleEqualizerCondition` with respect to a morphism `π` if it takes its kernel pair to an equalizer diagram. -/ def SingleEqualizerCondition (P : Cᵒᵖ ⥤ D) ⦃X B : C⦄ (π : X ⟶ B) : Prop := @@ -54,7 +54,7 @@ def SingleEqualizerCondition (P : Cᵒᵖ ⥤ D) ⦃X B : C⦄ (π : X ⟶ B) : Nonempty (IsLimit (Fork.ofι (P.map π.op) (equalizerCondition_w P c))) /-- -A contravariant functor on `C` satisfies `EqualizerCondition` if it takes kernel pairs of effective +A contravariant functor on `C` satisfies `EqualizerCondition` if it takes kernel pairs of effective epimorphisms to equalizer diagrams. -/ def EqualizerCondition (P : Cᵒᵖ ⥤ D) : Prop := @@ -148,7 +148,7 @@ theorem equalizerCondition_iff_isIso_lift (P : Cᵒᵖ ⥤ Type*) : EqualizerCon rw [mapToEqualizer_eq_comp, ← isIso_iff_bijective] infer_instance -/-- `P` satisfies the equalizer condition iff its precomposition by an equivalence does. -/ +/-- `P` satisfies the equalizer condition iff its precomposition by an equivalence does. -/ theorem equalizerCondition_iff_of_equivalence (P : Cᵒᵖ ⥤ D) (e : C ≌ E) : EqualizerCondition P ↔ EqualizerCondition (e.op.inverse ⋙ P) := ⟨fun h ↦ equalizerCondition_precomp_of_preservesPullback P e.inverse h, fun h ↦ @@ -177,7 +177,7 @@ theorem parallelPair_pullback_initial {X B : C} (π : X ⟶ B) all_goals exact Comma.hom_ext _ _ (by erw [Over.comp_left]; simp [ij]) rfl /-- -Given a limiting pullback cone, the fork in `SingleEqualizerCondition` is limiting iff the diagram +Given a limiting pullback cone, the fork in `SingleEqualizerCondition` is limiting iff the diagram in `Presheaf.isSheaf_iff_isLimit_coverage` is limiting. -/ noncomputable def isLimit_forkOfι_equiv (P : Cᵒᵖ ⥤ D) {X B : C} (π : X ⟶ B) diff --git a/Mathlib/CategoryTheory/Sites/Coherent/RegularTopology.lean b/Mathlib/CategoryTheory/Sites/Coherent/RegularTopology.lean index f15935efeb4dc..7d62dc4654e53 100644 --- a/Mathlib/CategoryTheory/Sites/Coherent/RegularTopology.lean +++ b/Mathlib/CategoryTheory/Sites/Coherent/RegularTopology.lean @@ -28,7 +28,7 @@ regular topology. Note: This is one direction of `mem_sieves_iff_hasEffectiveEpi`, but is needed for the proof. -/ theorem mem_sieves_of_hasEffectiveEpi (S : Sieve X) : - (∃ (Y : C) (π : Y ⟶ X), EffectiveEpi π ∧ S.arrows π) → (S ∈ (regularTopology C).sieves X) := by + (∃ (Y : C) (π : Y ⟶ X), EffectiveEpi π ∧ S.arrows π) → (S ∈ (regularTopology C) X) := by rintro ⟨Y, π, h⟩ have h_le : Sieve.generate (Presieve.ofArrows (fun () ↦ Y) (fun _ ↦ π)) ≤ S := by rw [Sieve.generate_le_iff (Presieve.ofArrows _ _) S] @@ -44,8 +44,7 @@ theorem mem_sieves_of_hasEffectiveEpi (S : Sieve X) : instance {Y Y' : C} (π : Y ⟶ X) [EffectiveEpi π] (π' : Y' ⟶ Y) [EffectiveEpi π'] : EffectiveEpi (π' ≫ π) := by rw [effectiveEpi_iff_effectiveEpiFamily, ← Sieve.effectiveEpimorphic_family] - suffices h₂ : (Sieve.generate (Presieve.ofArrows _ _)) ∈ - GrothendieckTopology.sieves (regularTopology C) X by + suffices h₂ : (Sieve.generate (Presieve.ofArrows _ _)) ∈ (regularTopology C) X by change Nonempty _ rw [← Sieve.forallYonedaIsSheaf_iff_colimit] exact fun W => regularTopology.isSheaf_yoneda_obj W _ h₂ @@ -62,17 +61,19 @@ instance {Y Y' : C} (π : Y ⟶ X) [EffectiveEpi π] /-- A sieve is a cover for the regular topology if and only if it contains an `EffectiveEpi`. -/ theorem mem_sieves_iff_hasEffectiveEpi (S : Sieve X) : - (S ∈ (regularTopology C).sieves X) ↔ + (S ∈ (regularTopology C) X) ↔ ∃ (Y : C) (π : Y ⟶ X), EffectiveEpi π ∧ (S.arrows π) := by constructor · intro h - induction' h with Y T hS Y Y R S _ _ a b - · rcases hS with ⟨Y', π, h'⟩ + induction h with + | of Y T hS => + rcases hS with ⟨Y', π, h'⟩ refine ⟨Y', π, h'.2, ?_⟩ rcases h' with ⟨rfl, _⟩ exact ⟨Y', 𝟙 Y', π, Presieve.ofArrows.mk (), (by simp)⟩ - · exact ⟨Y, (𝟙 Y), inferInstance, by simp only [Sieve.top_apply, forall_const]⟩ - · rcases a with ⟨Y₁, π, ⟨h₁,h₂⟩⟩ + | top Y => exact ⟨Y, (𝟙 Y), inferInstance, by simp only [Sieve.top_apply, forall_const]⟩ + | transitive Y R S _ _ a b => + rcases a with ⟨Y₁, π, ⟨h₁,h₂⟩⟩ choose Y' π' _ H using b h₂ exact ⟨Y', π' ≫ π, inferInstance, (by simpa using H)⟩ · exact regularTopology.mem_sieves_of_hasEffectiveEpi S diff --git a/Mathlib/CategoryTheory/Sites/Coherent/SheafComparison.lean b/Mathlib/CategoryTheory/Sites/Coherent/SheafComparison.lean index 330fcdfb5f49f..7f2817071b11a 100644 --- a/Mathlib/CategoryTheory/Sites/Coherent/SheafComparison.lean +++ b/Mathlib/CategoryTheory/Sites/Coherent/SheafComparison.lean @@ -14,15 +14,15 @@ import Mathlib.CategoryTheory.Sites.Whiskering # Categories of coherent sheaves Given a fully faithful functor `F : C ⥤ D` into a precoherent category, which preserves and reflects -finite effective epi families, and satisfies the property `F.EffectivelyEnough` (meaning that to +finite effective epi families, and satisfies the property `F.EffectivelyEnough` (meaning that to every object in `C` there is an effective epi from an object in the image of `F`), the categories -of coherent sheaves on `C` and `D` are equivalent (see +of coherent sheaves on `C` and `D` are equivalent (see `CategoryTheory.coherentTopology.equivalence`). The main application of this equivalence is the characterisation of condensed sets as coherent sheaves on either `CompHaus`, `Profinite` or `Stonean`. See the file `Condensed/Equivalence.lean` -We give the corresonding result for the regular topology as well (see +We give the corresponding result for the regular topology as well (see `CategoryTheory.regularTopology.equivalence`). -/ @@ -101,7 +101,7 @@ variable {C : Type u₁} {D : Type u₂} [Category.{v₁} C] [Category.{v₂} D] /-- The equivalence from coherent sheaves on `C` to coherent sheaves on `D`, given a fully faithful -functor `F : C ⥤ D` to a precoherent category, which preserves and reflects effective epimorphic +functor `F : C ⥤ D` to a precoherent category, which preserves and reflects effective epimorphic families, and satisfies `F.EffectivelyEnough`. -/ noncomputable @@ -124,7 +124,7 @@ variable {C : Type u₁} {D : Type u₂} [Category.{v₁} C] [Category.{v₂} D] /-- The equivalence from coherent sheaves on `C` to coherent sheaves on `D`, given a fully faithful -functor `F : C ⥤ D` to an extensive preregular category, which preserves and reflects effective +functor `F : C ⥤ D` to an extensive preregular category, which preserves and reflects effective epimorphisms and satisfies `F.EffectivelyEnough`. -/ noncomputable @@ -197,7 +197,7 @@ variable {C : Type u₁} {D : Type u₂} [Category.{v₁} C] [Category.{v₂} D] /-- The equivalence from regular sheaves on `C` to regular sheaves on `D`, given a fully faithful -functor `F : C ⥤ D` to a preregular category, which preserves and reflects effective +functor `F : C ⥤ D` to a preregular category, which preserves and reflects effective epimorphisms and satisfies `F.EffectivelyEnough`. -/ noncomputable @@ -246,7 +246,7 @@ theorem isSheaf_iff_extensiveSheaf_of_projective [Preregular C] [FinitaryExtensi rw [isSheaf_iff_preservesFiniteProducts_of_projective, isSheaf_iff_preservesFiniteProducts] /-- -The categories of coherent sheaves and extensive sheaves on `C` are equivalent if `C` is +The categories of coherent sheaves and extensive sheaves on `C` are equivalent if `C` is preregular, finitary extensive, and every object is projective. -/ @[simps] diff --git a/Mathlib/CategoryTheory/Sites/CompatiblePlus.lean b/Mathlib/CategoryTheory/Sites/CompatiblePlus.lean index df5b4c90f4608..602fb9363514a 100644 --- a/Mathlib/CategoryTheory/Sites/CompatiblePlus.lean +++ b/Mathlib/CategoryTheory/Sites/CompatiblePlus.lean @@ -96,7 +96,7 @@ def plusCompIso : J.plusObj P ⋙ F ≅ J.plusObj (P ⋙ F) := ext dsimp simp only [Category.assoc] - erw [Multiequalizer.lift_ι, diagramCompIso_hom_ι, diagramCompIso_hom_ι, ← F.map_comp, + rw [Multiequalizer.lift_ι, diagramCompIso_hom_ι, diagramCompIso_hom_ι, ← F.map_comp, Multiequalizer.lift_ι]) @[reassoc (attr := simp)] diff --git a/Mathlib/CategoryTheory/Sites/CompatibleSheafification.lean b/Mathlib/CategoryTheory/Sites/CompatibleSheafification.lean index d611090b676e6..ad79a0ec8cdd5 100644 --- a/Mathlib/CategoryTheory/Sites/CompatibleSheafification.lean +++ b/Mathlib/CategoryTheory/Sites/CompatibleSheafification.lean @@ -29,9 +29,6 @@ variable {D : Type w₁} [Category.{max v u} D] variable {E : Type w₂} [Category.{max v u} E] variable (F : D ⥤ E) --- Porting note: Removed this and made whatever necessary noncomputable --- noncomputable section - variable [∀ (α β : Type max v u) (fst snd : β → α), HasLimitsOfShape (WalkingMulticospan fst snd) D] variable [∀ (α β : Type max v u) (fst snd : β → α), HasLimitsOfShape (WalkingMulticospan fst snd) E] variable [∀ X : C, HasColimitsOfShape (J.Cover X)ᵒᵖ D] diff --git a/Mathlib/CategoryTheory/Sites/ConcreteSheafification.lean b/Mathlib/CategoryTheory/Sites/ConcreteSheafification.lean index 3f6ecdafd76ae..8d46116dc8326 100644 --- a/Mathlib/CategoryTheory/Sites/ConcreteSheafification.lean +++ b/Mathlib/CategoryTheory/Sites/ConcreteSheafification.lean @@ -153,7 +153,8 @@ theorem res_mk_eq_mk_pullback {Y X : C} {P : Cᵒᵖ ⥤ D} {S : J.Cover X} (x : ext i simp only [Functor.op_obj, unop_op, pullback_obj, diagram_obj, Functor.comp_obj, diagramPullback_app, Meq.equiv_apply, Meq.pullback_apply] - erw [← comp_apply, Multiequalizer.lift_ι, Meq.equiv_symm_eq_apply] + rw [← comp_apply, Multiequalizer.lift_ι] + erw [Meq.equiv_symm_eq_apply] cases i; rfl theorem toPlus_mk {X : C} {P : Cᵒᵖ ⥤ D} (S : J.Cover X) (x : P.obj (op X)) : @@ -162,7 +163,8 @@ theorem toPlus_mk {X : C} {P : Cᵒᵖ ⥤ D} (S : J.Cover X) (x : P.obj (op X)) let e : S ⟶ ⊤ := homOfLE (OrderTop.le_top _) rw [← colimit.w _ e.op] delta Cover.toMultiequalizer - erw [comp_apply, comp_apply] + rw [comp_apply] + erw [comp_apply] apply congr_arg dsimp [diagram] apply Concrete.multiequalizer_ext @@ -347,7 +349,7 @@ theorem exists_of_sep (P : Cᵒᵖ ⥤ D) use mk w ext I dsimp [Meq.mk] - erw [ht, res_mk_eq_mk_pullback] + rw [ht, res_mk_eq_mk_pullback] -- Use the separatedness of `P⁺` to prove that this is indeed a gluing of our -- original local sections. apply sep P (T I) @@ -369,7 +371,7 @@ theorem exists_of_sep (P : Cᵒᵖ ⥤ D) ⟨I.Y, _, _, I.hf, Sieve.downward_closed _ II.hf _, rfl⟩⟩ let IB : S.Arrow := IA.fromMiddle let IC : (T IB).Arrow := IA.toMiddle - let ID : (T I).Arrow := ⟨IV.Y, IV.f ≫ II.f, Sieve.downward_closed (T I).sieve II.hf IV.f⟩ + let ID : (T I).Arrow := ⟨IV.Y, IV.f ≫ II.f, Sieve.downward_closed (T I).1 II.hf IV.f⟩ change t IB IC = t I ID apply inj IV.Y erw [toPlus_apply (T I) (t I) ID, toPlus_apply (T IB) (t IB) IC, ← ht, ← ht] @@ -589,12 +591,4 @@ instance presheaf_mono_of_mono {F G : Sheaf J D} (f : F ⟶ G) [Mono f] : Mono f theorem Sheaf.Hom.mono_iff_presheaf_mono {F G : Sheaf J D} (f : F ⟶ G) : Mono f ↔ Mono f.1 := ⟨fun m => by infer_instance, fun m => by exact Sheaf.Hom.mono_of_presheaf_mono J D f⟩ --- Porting note: added to ease the port of CategoryTheory.Sites.LeftExact --- in mathlib, this was `by refl`, but here it would timeout -@[simps! hom_app inv_app] -noncomputable -def GrothendieckTopology.sheafificationIsoPresheafToSheafCompSheafToPreasheaf : - J.sheafification D ≅ plusPlusSheaf J D ⋙ sheafToPresheaf J D := - NatIso.ofComponents fun P => Iso.refl _ - end CategoryTheory diff --git a/Mathlib/CategoryTheory/Sites/ConstantSheaf.lean b/Mathlib/CategoryTheory/Sites/ConstantSheaf.lean index 1fa5ab155f92b..6e0ca7b270af8 100644 --- a/Mathlib/CategoryTheory/Sites/ConstantSheaf.lean +++ b/Mathlib/CategoryTheory/Sites/ConstantSheaf.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Dagur Asgeirsson -/ import Mathlib.CategoryTheory.Sites.Sheafification - +import Mathlib.CategoryTheory.Sites.DenseSubsite /-! # The constant sheaf @@ -12,16 +12,37 @@ import Mathlib.CategoryTheory.Sites.Sheafification We define the constant sheaf functor (the sheafification of the constant presheaf) `constantSheaf : D ⥤ Sheaf J D` and prove that it is left adjoint to evaluation at a terminal object (see `constantSheafAdj`). + +We also define a predicate on sheaves, `Sheaf.IsConstant`, saying that a sheaf is in the +essential image of the constant sheaf functor. + +## Main results + +* `Sheaf.isConstant_iff_isIso_counit_app`: Provided that the constant sheaf functor is fully +faithful, a sheaf is constant if and only if the counit of the constant sheaf adjunction applied to +it is an isomorphism. + +* `Sheaf.isConstant_iff_of_equivalence` : The property of a sheaf of being constant is invariant +under equivalence of sheaf categories. + +* `Sheaf.isConstant_iff_forget` : Given a "forgetful" functor `U : D ⥤ B` a sheaf `F : Sheaf J D` is +constant if and only if the sheaf given by postcomposition with `U` is constant. + +## Future work + +* (Dagur) Use `Sheaf.isConstant_iff_forget` to prove that a condensed module is discrete if and +only if its underlying condensed set is discrete. -/ namespace CategoryTheory -open Limits Opposite Category Functor Sheaf +open Limits Opposite Category Functor Sheaf Adjunction variable {C : Type*} [Category C] (J : GrothendieckTopology C) variable (D : Type*) [Category D] /-- The constant presheaf functor is left adjoint to evaluation at a terminal object. -/ +@[simps! unit_app counit_app_app] noncomputable def constantPresheafAdj {T : C} (hT : IsTerminal T) : Functor.const Cᵒᵖ ⊣ (evaluation Cᵒᵖ D).obj (op T) := Adjunction.mkOfUnitCounit { @@ -39,28 +60,177 @@ noncomputable def constantPresheafAdj {T : C} (hT : IsTerminal T) : variable [HasWeakSheafify J D] /-- -The functor which maps an object of `D` to the constant sheaf at that object, i.e. the +The functor which maps an object of `D` to the constant sheaf at that object, i.e. the sheafification of the constant presheaf. -/ noncomputable def constantSheaf : D ⥤ Sheaf J D := Functor.const Cᵒᵖ ⋙ (presheafToSheaf J D) /-- The constant sheaf functor is left adjoint to evaluation at a terminal object. -/ +@[simps! counit_app] noncomputable def constantSheafAdj {T : C} (hT : IsTerminal T) : constantSheaf J D ⊣ (sheafSections J D).obj (op T) := (constantPresheafAdj D hT).comp (sheafificationAdjunction J D) -lemma constantSheafAdj_counit_app {T : C} (hT : IsTerminal T) (F : Sheaf J D) : - (constantSheafAdj J D hT).counit.app F = - (presheafToSheaf J D).map ((constantPresheafAdj D hT).counit.app F.val) ≫ - (sheafificationAdjunction J D).counit.app F := by +variable {D} + +namespace Sheaf + +/-- +A sheaf is constant if it is in the essential image of the constant sheaf functor. +-/ +class IsConstant (F : Sheaf J D) : Prop where + mem_essImage : F ∈ (constantSheaf J D).essImage + +lemma mem_essImage_of_isConstant (F : Sheaf J D) [IsConstant J F] : + F ∈ (constantSheaf J D).essImage := + IsConstant.mem_essImage + +lemma isConstant_congr {F G : Sheaf J D} (i : F ≅ G) [IsConstant J F] : IsConstant J G where + mem_essImage := essImage.ofIso i F.mem_essImage_of_isConstant + +lemma isConstant_of_iso {F : Sheaf J D} {X : D} (i : F ≅ (constantSheaf J D).obj X) : + IsConstant J F := ⟨_, ⟨i.symm⟩⟩ + +lemma isConstant_iff_mem_essImage {L : D ⥤ Sheaf J D} {T : C} (hT : IsTerminal T) + (adj : L ⊣ (sheafSections J D).obj ⟨T⟩) + (F : Sheaf J D) : IsConstant J F ↔ F ∈ L.essImage := by + rw [essImage_eq_of_natIso (adj.leftAdjointUniq (constantSheafAdj J D hT))] + exact ⟨fun ⟨h⟩ ↦ h, fun h ↦ ⟨h⟩⟩ + +lemma isConstant_of_isIso_counit_app (F : Sheaf J D) [HasTerminal C] + [IsIso <| (constantSheafAdj J D terminalIsTerminal).counit.app F] : IsConstant J F where + mem_essImage := ⟨_, ⟨asIso <| (constantSheafAdj J D terminalIsTerminal).counit.app F⟩⟩ + +instance [(constantSheaf J D).Faithful] [(constantSheaf J D).Full] (F : Sheaf J D) + [IsConstant J F] {T : C} (hT : IsTerminal T) : + IsIso ((constantSheafAdj J D hT).counit.app F) := by + rw [isIso_counit_app_iff_mem_essImage] + exact F.mem_essImage_of_isConstant + +/-- +If the constant sheaf functor is fully faithful, then a sheaf is constant if and only if the +counit of the constant sheaf adjunction applied to it is an isomorphism. +-/ +lemma isConstant_iff_isIso_counit_app [(constantSheaf J D).Faithful] [(constantSheaf J D).Full] + (F : Sheaf J D) {T : C} (hT : IsTerminal T) : + IsConstant J F ↔ (IsIso <| (constantSheafAdj J D hT).counit.app F) := + ⟨fun _ ↦ inferInstance, fun _ ↦ ⟨_, ⟨asIso <| (constantSheafAdj J D hT).counit.app F⟩⟩⟩ + +/-- +A variant of `isConstant_iff_isIso_counit_app` for a general left adjoint to evaluation at a +terminal object. +-/ +lemma isConstant_iff_isIso_counit_app' {L : D ⥤ Sheaf J D} {T : C} (hT : IsTerminal T) + (adj : L ⊣ (sheafSections J D).obj ⟨T⟩) + [L.Faithful] [L.Full] (F : Sheaf J D) : IsConstant J F ↔ IsIso (adj.counit.app F) := + (isConstant_iff_mem_essImage J hT adj F).trans (isIso_counit_app_iff_mem_essImage adj).symm + +end Sheaf + +section Equivalence +variable {C' : Type*} [Category C'] (K : GrothendieckTopology C') [HasWeakSheafify K D] +variable (G : C ⥤ C') [∀ (X : (C')ᵒᵖ), HasLimitsOfShape (StructuredArrow X G.op) D] + [G.IsDenseSubsite J K] {T : C} (hT : IsTerminal T) (hT' : IsTerminal (G.obj T)) + +open IsDenseSubsite + +variable (D) in +/-- +The constant sheaf functor commutes up to isomorphism the equivalence of sheaf categories induced +by a dense subsite. +-/ +noncomputable def equivCommuteConstant : + constantSheaf J D ⋙ (sheafEquiv G J K D).functor ≅ constantSheaf K D := + ((constantSheafAdj J D hT).comp (sheafEquiv G J K D).toAdjunction).leftAdjointUniq + (constantSheafAdj K D hT') + +variable (D) in +/-- +The constant sheaf functor commutes up to isomorphism the inverse equivalence of sheaf categories +induced by a dense subsite. +-/ +noncomputable def equivCommuteConstant' : + constantSheaf J D ≅ constantSheaf K D ⋙ (sheafEquiv G J K D).inverse := + isoWhiskerLeft (constantSheaf J D) (sheafEquiv G J K D).unitIso ≪≫ + isoWhiskerRight (equivCommuteConstant J D K G hT hT') (sheafEquiv G J K D).inverse + +/- TODO: find suitable assumptions for proving generalizations of `equivCommuteConstant` and +`equivCommuteConstant'` above, to commute `constantSheaf` with pullback/pushforward of sheaves. -/ + +include hT hT' in +/-- +The property of a sheaf of being constant is invariant under equivalence of sheaf +categories. +-/ +lemma Sheaf.isConstant_iff_of_equivalence (F : Sheaf K D) : + ((sheafEquiv G J K D).inverse.obj F).IsConstant J ↔ IsConstant K F := by + constructor + · exact fun ⟨Y, ⟨i⟩⟩ ↦ ⟨_, ⟨(equivCommuteConstant J D K G hT hT').symm.app _ ≪≫ + (sheafEquiv G J K D).functor.mapIso i ≪≫ (sheafEquiv G J K D).counitIso.app _⟩⟩ + · exact fun ⟨Y, ⟨i⟩⟩ ↦ ⟨_, ⟨(equivCommuteConstant' J D K G hT hT').app _ ≪≫ + (sheafEquiv G J K D).inverse.mapIso i⟩⟩ + +end Equivalence + +section Forget + +variable {B : Type*} [Category B] (U : D ⥤ B) [HasWeakSheafify J B] + [J.PreservesSheafification U] [J.HasSheafCompose U] (F : Sheaf J D) + +/-- +The constant sheaf functor commutes with `sheafCompose J U` up to isomorphism, provided that `U`  +preserves sheafification. +-/ +noncomputable def constantCommuteCompose : + constantSheaf J D ⋙ sheafCompose J U ≅ U ⋙ constantSheaf J B := + (isoWhiskerLeft (const Cᵒᵖ) + (sheafComposeNatIso J U (sheafificationAdjunction J D) (sheafificationAdjunction J B)).symm) ≪≫ + isoWhiskerRight (compConstIso _ _).symm _ + +lemma constantCommuteCompose_hom_app_val (X : D) : ((constantCommuteCompose J U).hom.app X).val = + (sheafifyComposeIso J U ((const Cᵒᵖ).obj X)).inv ≫ sheafifyMap J (constComp Cᵒᵖ X U).hom := rfl + +/-- The counit of `constantSheafAdj` factors through the isomorphism `constantCommuteCompose`. -/ +lemma constantSheafAdj_counit_w {T : C} (hT : IsTerminal T) : + ((constantCommuteCompose J U).hom.app (F.val.obj ⟨T⟩)) ≫ + ((constantSheafAdj J B hT).counit.app ((sheafCompose J U).obj F)) = + ((sheafCompose J U).map ((constantSheafAdj J D hT).counit.app F)) := by apply Sheaf.hom_ext - apply sheafify_hom_ext _ _ _ F.cond - simp only [flip_obj_obj, sheafToPresheaf_obj, comp_obj, id_obj, constantSheafAdj, Adjunction.comp, - evaluation_obj_obj, constantPresheafAdj, Opposite.op_unop, Adjunction.mkOfUnitCounit_unit, - Adjunction.mkOfUnitCounit_counit, NatTrans.comp_app, associator_hom_app, whiskerLeft_app, - whiskerRight_app, instCategorySheaf_comp_val, instCategorySheaf_id_val, - sheafificationAdjunction_counit_app_val, sheafifyMap_sheafifyLift, comp_id, - toSheafify_sheafifyLift] - erw [id_comp, toSheafify_sheafifyLift] + rw [instCategorySheaf_comp_val, constantCommuteCompose_hom_app_val, assoc, Iso.inv_comp_eq] + apply sheafify_hom_ext _ _ _ ((sheafCompose J U).obj F).cond + ext + simp? says simp only [comp_obj, const_obj_obj, sheafCompose_obj_val, id_obj, + constantSheafAdj_counit_app, instCategorySheaf_comp_val, + sheafificationAdjunction_counit_app_val, sheafifyMap_sheafifyLift, comp_id, + toSheafify_sheafifyLift, NatTrans.comp_app, constComp_hom_app, + constantPresheafAdj_counit_app_app, Functor.comp_map, id_comp, flip_obj_obj, + sheafToPresheaf_obj, map_comp, sheafCompose_map_val, sheafComposeIso_hom_fac_assoc, + whiskerRight_app] + simp [← map_comp, ← NatTrans.comp_app] + +lemma Sheaf.isConstant_of_forget [constantSheaf J D |>.Faithful] [constantSheaf J D |>.Full] + [constantSheaf J B |>.Faithful] [constantSheaf J B |>.Full] + [(sheafCompose J U).ReflectsIsomorphisms] [((sheafCompose J U).obj F).IsConstant J] + {T : C} (hT : IsTerminal T) : F.IsConstant J := by + have : IsIso ((sheafCompose J U).map ((constantSheafAdj J D hT).counit.app F)) := by + rw [← constantSheafAdj_counit_w] + infer_instance + rw [F.isConstant_iff_isIso_counit_app (hT := hT)] + exact isIso_of_reflects_iso _ (sheafCompose J U) + +instance [h : F.IsConstant J] : ((sheafCompose J U).obj F).IsConstant J := by + obtain ⟨Y, ⟨i⟩⟩ := h + exact ⟨U.obj Y, ⟨(fullyFaithfulSheafToPresheaf _ _).preimageIso + (((sheafifyComposeIso J U ((const Cᵒᵖ).obj Y)).symm ≪≫ + (presheafToSheaf J B ⋙ sheafToPresheaf J B).mapIso (constComp Cᵒᵖ Y U)).symm ≪≫ + (sheafToPresheaf _ _).mapIso ((sheafCompose J U).mapIso i))⟩⟩ + +lemma Sheaf.isConstant_iff_forget [constantSheaf J D |>.Faithful] [constantSheaf J D |>.Full] + [constantSheaf J B |>.Faithful] [constantSheaf J B |>.Full] + [(sheafCompose J U).ReflectsIsomorphisms] {T : C} (hT : IsTerminal T) : + F.IsConstant J ↔ ((sheafCompose J U).obj F).IsConstant J := + ⟨fun _ ↦ inferInstance, fun _ ↦ Sheaf.isConstant_of_forget _ U F hT⟩ + +end Forget end CategoryTheory diff --git a/Mathlib/CategoryTheory/Sites/CoverLifting.lean b/Mathlib/CategoryTheory/Sites/CoverLifting.lean index fc2152f710887..14f0ea6ecb8c6 100644 --- a/Mathlib/CategoryTheory/Sites/CoverLifting.lean +++ b/Mathlib/CategoryTheory/Sites/CoverLifting.lean @@ -133,9 +133,8 @@ lemma liftAux_map {Y : C} (f : G.obj Y ⟶ X) {W : C} (g : W ⟶ Y) (i : S.Arrow liftAux hF α s f ≫ F.map g.op = s.ι i ≫ R.map h.op ≫ α.app _ := (Multifork.IsLimit.fac (hF.isLimitMultifork ⟨_, G.cover_lift J K (K.pullback_stable f S.2)⟩) _ _ - ⟨W, g, by simpa only [GrothendieckTopology.Cover.sieve, - Sieve.functorPullback_apply, functorPullback_mem, Sieve.pullback_apply, ← w] - using S.1.downward_closed i.hf h⟩).trans (by + ⟨W, g, by simpa only [Sieve.functorPullback_apply, functorPullback_mem, + Sieve.pullback_apply, ← w] using S.1.downward_closed i.hf h⟩).trans (by dsimp simp only [← Category.assoc] congr 1 diff --git a/Mathlib/CategoryTheory/Sites/Coverage.lean b/Mathlib/CategoryTheory/Sites/Coverage.lean index 8077b8d450f7f..648975e7b07ec 100644 --- a/Mathlib/CategoryTheory/Sites/Coverage.lean +++ b/Mathlib/CategoryTheory/Sites/Coverage.lean @@ -309,7 +309,7 @@ Any sieve that contains a covering presieve for a coverage is a covering sieve f Grothendieck topology. -/ theorem mem_toGrothendieck_sieves_of_superset (K : Coverage C) {X : C} {S : Sieve X} - {R : Presieve X} (h : R ≤ S) (hR : R ∈ K.covering X) : S ∈ (K.toGrothendieck C).sieves X := + {R : Presieve X} (h : R ≤ S) (hR : R ∈ K.covering X) : S ∈ (K.toGrothendieck C) X := K.saturate_of_superset ((Sieve.generate_le_iff _ _).mpr h) (Coverage.Saturate.of X _ hR) end Coverage diff --git a/Mathlib/CategoryTheory/Sites/DenseSubsite.lean b/Mathlib/CategoryTheory/Sites/DenseSubsite.lean index f689c95f03d54..21ae0858e76d2 100644 --- a/Mathlib/CategoryTheory/Sites/DenseSubsite.lean +++ b/Mathlib/CategoryTheory/Sites/DenseSubsite.lean @@ -173,16 +173,10 @@ theorem naturality [G.IsLocallyFull K] {X Y : C} (i : G.obj X ⟶ G.obj Y) : /-- (Implementation). Given a section of `ℱ` on `X`, we can obtain a family of elements valued in `ℱ'` that is defined on a cover generated by the images of `G`. -/ --- Porting note: removed `@[simp, nolint unused_arguments]` noncomputable def pushforwardFamily {X} (x : ℱ.obj (op X)) : FamilyOfElements ℱ'.val (coverByImage G X) := fun _ _ hf => ℱ'.val.map hf.some.lift.op <| α.app (op _) (ℱ.map hf.some.map.op x : _) --- Porting note: there are various `include` and `omit`s in this file (e.g. one is removed here), --- none of which are needed in Lean 4. - --- Porting note: `pushforward_family` was tagged `@[simp]` in Lean 3 so we add the --- equation lemma @[simp] theorem pushforwardFamily_def {X} (x : ℱ.obj (op X)) : pushforwardFamily α x = fun _ _ hf => ℱ'.val.map hf.some.lift.op <| α.app (op _) (ℱ.map hf.some.map.op x : _) := rfl @@ -266,7 +260,6 @@ noncomputable def presheafHom (α : G.op ⋙ ℱ ⟶ G.op ⋙ ℱ'.val) : ℱ apply Functor.IsCoverDense.ext G intro Y' f' simp only [appHom_restrict, types_comp_apply, ← FunctorToTypes.map_comp_apply] - -- Porting note: Lean 3 proof continued with a rewrite but we're done here /-- Given a natural isomorphism `G ⋙ ℱ ≅ G ⋙ ℱ'` between presheaves of types, @@ -360,17 +353,12 @@ noncomputable def presheafIso {ℱ ℱ' : Sheaf K A} (i : G.op ⋙ ℱ.val ≅ G ℱ.val ≅ ℱ'.val := by have : ∀ X : Dᵒᵖ, IsIso ((sheafHom i.hom).app X) := by intro X - -- Porting note: somehow `apply` in Lean 3 is leaving a typeclass goal, - -- perhaps due to elaboration order. The corresponding `apply` in Lean 4 fails - -- because the instance can't yet be synthesized. I hence reorder the proof. - suffices IsIso (yoneda.map ((sheafHom i.hom).app X)) by - apply isIso_of_reflects_iso _ yoneda + rw [← isIso_iff_of_reflects_iso _ yoneda] use (sheafYonedaHom i.inv).app X constructor <;> ext x : 2 <;> simp only [sheafHom, NatTrans.comp_app, NatTrans.id_app, Functor.map_preimage] · exact ((Types.presheafIso (isoOver i (unop x))).app X).hom_inv_id · exact ((Types.presheafIso (isoOver i (unop x))).app X).inv_hom_id - -- Porting note: Lean 4 proof is finished, Lean 3 needed `inferInstance` haveI : IsIso (sheafHom i.hom) := by apply NatIso.isIso_of_isIso_app apply asIso (sheafHom i.hom) @@ -396,8 +384,7 @@ theorem sheafHom_restrict_eq (α : G.op ⋙ ℱ ⟶ G.op ⋙ ℱ'.val) : ext X apply yoneda.map_injective ext U - -- Porting note: didn't need to provide the input to `map_preimage` in Lean 3 - erw [yoneda.map_preimage ((sheafYonedaHom α).app (G.op.obj X))] + erw [yoneda.map_preimage] symm change (show (ℱ'.val ⋙ coyoneda.obj (op (unop U))).obj (op (G.obj (unop X))) from _) = _ apply sheaf_eq_amalgamation ℱ' (G.is_cover_of_isCoverDense _ _) @@ -423,10 +410,8 @@ then the result `sheaf_hom (whisker_left G.op α)` is equal to `α`. theorem sheafHom_eq (α : ℱ ⟶ ℱ'.val) : sheafHom (whiskerLeft G.op α) = α := by ext X apply yoneda.map_injective - -- Porting note: deleted next line as it's not needed in Lean 4 ext U - -- Porting note: Lean 3 didn't need to be told the explicit input to map_preimage - erw [yoneda.map_preimage ((sheafYonedaHom (whiskerLeft G.op α)).app X)] + erw [yoneda.map_preimage] symm change (show (ℱ'.val ⋙ coyoneda.obj (op (unop U))).obj (op (unop X)) from _) = _ apply sheaf_eq_amalgamation ℱ' (G.is_cover_of_isCoverDense _ _) diff --git a/Mathlib/CategoryTheory/Sites/Discrete.lean b/Mathlib/CategoryTheory/Sites/Discrete.lean deleted file mode 100644 index 6998b9657e496..0000000000000 --- a/Mathlib/CategoryTheory/Sites/Discrete.lean +++ /dev/null @@ -1,283 +0,0 @@ -/- -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.Adjunction.FullyFaithful -import Mathlib.CategoryTheory.Sites.ConstantSheaf -import Mathlib.CategoryTheory.Sites.DenseSubsite -import Mathlib.CategoryTheory.Sites.PreservesSheafification -/-! - -# Discrete objects in sheaf categories. - -This file defines the notion of a discrete object in a sheaf category. A discrete sheaf in this -context is a sheaf `F` such that the counit `(F(*))^cst ⟶ F` is an isomorphism. Here `*` denotes -a particular chosen terminal object of the defining site, and `cst` denotes the constant sheaf. - -It is convenient to take an arbitrary terminal object; one might want to use this construction to -talk about discrete sheaves on a site which has a particularly convenient terminal object, such as -the one element space in `CompHaus`. - -## Main results - -* `isDiscrete_iff_mem_essImage` : A sheaf is discrete if and only if it is in the essential image -of the constant sheaf functor. -* `isDiscrete_iff_of_equivalence` : The property of a sheaf of being discrete is invariant under -equivalence of sheaf categories. -* `isDiscrete_iff_forget` : Given a "forgetful" functor `U : A ⥤ B` a sheaf `F : Sheaf J A` is -discrete if and only if the sheaf given by postcomposition with `U` is discrete. - -## Future work - -* Use `isDiscrete_iff_forget` to prove that a condensed module is discrete if and only if its -underlying condensed set is discrete. --/ - -open CategoryTheory Limits Functor Adjunction Opposite Category Functor - -namespace CategoryTheory.Sheaf - -variable {C : Type*} [Category C] (J : GrothendieckTopology C) {A : Type*} [Category A] - [HasWeakSheafify J A] {t : C} (ht : IsTerminal t) - -section -variable [(constantSheaf J A).Faithful] [(constantSheaf J A).Full] - -/-- -A sheaf is discrete if it is a discrete object of the "underlying object" functor from the sheaf -category to the target category. --/ -abbrev IsDiscrete (F : Sheaf J A) : Prop := IsIso ((constantSheafAdj J A ht).counit.app F) - -lemma isDiscrete_of_iso {F : Sheaf J A} {X : A} - (i : F ≅ (constantSheaf J A).obj X) : IsDiscrete J ht F := - isIso_counit_app_of_iso _ i - -lemma isDiscrete_iff_mem_essImage (F : Sheaf J A) : - F.IsDiscrete J ht ↔ F ∈ (constantSheaf J A).essImage := - (constantSheafAdj J A ht).isIso_counit_app_iff_mem_essImage - -lemma isDiscrete_iff_mem_essImage' {L : A ⥤ Sheaf J A} (adj : L ⊣ (sheafSections J A).obj ⟨t⟩) - (F : Sheaf J A) : - IsDiscrete J ht F ↔ F ∈ L.essImage := by - let e : L ≅ constantSheaf J A := adj.leftAdjointUniq (constantSheafAdj _ _ ht) - refine ⟨fun h ↦ ⟨F.val.obj ⟨t⟩, ⟨?_⟩⟩, fun ⟨Y, ⟨i⟩⟩ ↦ ?_⟩ - · exact e.app _ ≪≫ asIso ((constantSheafAdj _ _ ht).counit.app _) - · rw [isDiscrete_iff_mem_essImage] - exact ⟨Y, ⟨e.symm.app _ ≪≫ i⟩⟩ - -lemma isDiscrete_iff_isIso_counit_app {L : A ⥤ Sheaf J A} (adj : L ⊣ (sheafSections J A).obj ⟨t⟩) - (F : Sheaf J A) : - IsDiscrete J ht F ↔ IsIso (adj.counit.app F) := by - have : L.Faithful := Functor.Faithful.of_iso (adj.leftAdjointUniq (constantSheafAdj _ _ ht)).symm - have : L.Full := Functor.Full.of_iso (adj.leftAdjointUniq (constantSheafAdj _ _ ht)).symm - rw [isIso_counit_app_iff_mem_essImage] - exact isDiscrete_iff_mem_essImage' _ _ adj _ - -section Equivalence - -variable {D : Type*} [Category D] (K : GrothendieckTopology D) [HasWeakSheafify K A] -variable (G : C ⥤ D) - [∀ (X : Dᵒᵖ), HasLimitsOfShape (StructuredArrow X G.op) A] - [G.IsDenseSubsite J K] (ht' : IsTerminal (G.obj t)) - -open Functor.IsDenseSubsite - -noncomputable example : - let e : Sheaf J A ≌ Sheaf K A := - sheafEquiv G J K A - e.inverse ⋙ (sheafSections J A).obj (op t) ≅ (sheafSections K A).obj (op (G.obj t)) := - Iso.refl _ - -variable (A) in -/-- -The constant sheaf functor commutes up to isomorphism with any equivalence of sheaf categories. - -This is an auxiliary definition used to prove `Sheaf.isDiscrete_iff_of_equivalence` below, which -says that the property of a sheaf of being a discrete object is invariant under equivalence of -sheaf categories. --/ -noncomputable def equivCommuteConstant : - let e : Sheaf J A ≌ Sheaf K A := - sheafEquiv G J K A - constantSheaf J A ⋙ e.functor ≅ constantSheaf K A := - let e : Sheaf J A ≌ Sheaf K A := - sheafEquiv G J K A - (Adjunction.leftAdjointUniq ((constantSheafAdj J A ht).comp e.toAdjunction) - (constantSheafAdj K A ht')) - -variable (A) in -/-- -The constant sheaf functor commutes up to isomorphism with any equivalence of sheaf categories. - -This is an auxiliary definition used to prove `Sheaf.isDiscrete_iff_of_equivalence` below, which -says that the property of a sheaf of being a discrete object is invariant under equivalence of -sheaf categories. --/ -noncomputable def equivCommuteConstant' : - let e : Sheaf J A ≌ Sheaf K A := - sheafEquiv G J K A - constantSheaf J A ≅ constantSheaf K A ⋙ e.inverse := - let e : Sheaf J A ≌ Sheaf K A := - sheafEquiv G J K A - isoWhiskerLeft (constantSheaf J A) e.unitIso ≪≫ - isoWhiskerRight (equivCommuteConstant J A ht K G ht') e.inverse - -/-- -The property of a sheaf of being a discrete object is invariant under equivalence of sheaf -categories. --/ -lemma isDiscrete_iff_of_equivalence (F : Sheaf K A) : - let e : Sheaf J A ≌ Sheaf K A := - sheafEquiv G J K A - haveI : (constantSheaf K A).Faithful := - Functor.Faithful.of_iso (equivCommuteConstant J A ht K G ht') - haveI : (constantSheaf K A).Full := - Functor.Full.of_iso (equivCommuteConstant J A ht K G ht') - (e.inverse.obj F).IsDiscrete J ht ↔ IsDiscrete K ht' F := by - intro e - have : (constantSheaf K A).Faithful := - Functor.Faithful.of_iso (equivCommuteConstant J A ht K G ht') - have : (constantSheaf K A).Full := - Functor.Full.of_iso (equivCommuteConstant J A ht K G ht') - simp only [isDiscrete_iff_mem_essImage] - constructor - · intro ⟨Y, ⟨i⟩⟩ - let j : (constantSheaf K A).obj Y ≅ F := - (equivCommuteConstant J A ht K G ht').symm.app _ ≪≫ e.functor.mapIso i ≪≫ e.counitIso.app _ - exact ⟨_, ⟨j⟩⟩ - · intro ⟨Y, ⟨i⟩⟩ - let j : (constantSheaf J A).obj Y ≅ e.inverse.obj F := - (equivCommuteConstant' J A ht K G ht').app _ ≪≫ e.inverse.mapIso i - exact ⟨_, ⟨j⟩⟩ - -end Equivalence - -end - -section Forget - -variable {B : Type*} [Category B] (U : A ⥤ B) [HasWeakSheafify J B] - [J.PreservesSheafification U] [J.HasSheafCompose U] (F : Sheaf J A) - -open Limits - -/-- The constant sheaf functor commutes with `sheafCompose` up to isomorphism. -/ -@[simps!] -noncomputable def constantCommuteCompose : - constantSheaf J A ⋙ sheafCompose J U ≅ U ⋙ constantSheaf J B := - (isoWhiskerLeft (const Cᵒᵖ) - (sheafComposeNatIso J U (sheafificationAdjunction J A) (sheafificationAdjunction J B)).symm) ≪≫ - isoWhiskerRight (compConstIso _ _).symm _ - -lemma sheafComposeNatIso_app_counit (P : Sheaf J A) : - (sheafComposeNatIso J U (sheafificationAdjunction J A) - (sheafificationAdjunction J B)).hom.app _ ≫ (sheafCompose J U).map - ((sheafificationAdjunction J A).counit.app P) = - (sheafificationAdjunction J B).counit.app ((sheafCompose J U).obj P) := by - simp only [sheafToPresheaf_obj, Functor.comp_obj, whiskeringRight_obj_obj, Functor.id_obj, - sheafComposeNatIso, sheafComposeNatTrans, sheafCompose_obj_val, - sheafificationAdjunction_unit_app, asIso_hom] - erw [Adjunction.homEquiv_counit] - apply Sheaf.hom_ext - apply sheafify_hom_ext _ _ _ ((sheafCompose J U).obj P).cond - simp [← whiskerRight_comp] - -lemma constantCommuteComposeApp_comp_counit (F : Sheaf J A) : - ((constantCommuteCompose J U).app _).hom ≫ - (constantSheafAdj J B ht).counit.app ((sheafCompose J U).obj F) = - (sheafCompose J U).map ((constantSheafAdj J A ht).counit.app F) := by - simp only [← Iso.eq_inv_comp, constantSheafAdj_counit_app, - constantCommuteCompose, flip_obj_obj, sheafToPresheaf_obj, id_obj, NatIso.trans_app, comp_obj, - whiskeringRight_obj_obj, Iso.trans_inv, Iso.app_inv, isoWhiskerRight_inv, Iso.symm_inv, - whiskerRight_app, isoWhiskerLeft_inv, whiskerLeft_app, evaluation_obj_obj, Functor.map_comp, - assoc, sheafCompose_obj_val, ← sheafComposeNatIso_app_counit] - simp only [← assoc] - congr 1 - have : (compConstIso Cᵒᵖ U).hom.app (F.val.obj ⟨t⟩) ≫ - { app := fun Y ↦ (F.val ⋙ U).map (ht.from _).op - naturality := by intros; simp; rw [← Functor.map_comp, ← Functor.map_comp]; congr; simp } = - ((constantPresheafAdj B ht).counit.app (F.val ⋙ U)) := by ext; simp [constantPresheafAdj] - simp only [← this, assoc, Functor.map_comp] - congr 1 - apply Sheaf.hom_ext - apply sheafify_hom_ext _ _ _ ((sheafCompose J U).obj ((presheafToSheaf J A).obj F.val)).cond - simp only [sheafCompose_obj_val, instCategorySheaf_comp_val, sheafCompose_map_val, comp_obj, - whiskeringRight_obj_obj, Functor.comp_map] - erw [← toSheafify_naturality_assoc, sheafComposeIso_hom_fac, sheafComposeIso_hom_fac_assoc] - ext - simp only [comp_obj, const_obj_obj, NatTrans.comp_app, whiskerRight_app, ← Functor.map_comp] - congr 1 - simp only [constantPresheafAdj, comp_obj, evaluation_obj_obj, id_obj, Opposite.op_unop, - Adjunction.mkOfUnitCounit_counit, NatTrans.naturality] - erw [← NatTrans.comp_app, ← toSheafify_naturality] - simp only [NatTrans.comp_app, const_obj_obj, NatTrans.naturality] - -/-- Auxiliary lemma for `sheafCompose_reflects_discrete`. -/ -private lemma sheafifyComposeIso_comp_sheafCompose_map_constantSheafAdj_counit : - (sheafifyComposeIso J U ((const Cᵒᵖ).obj (F.val.obj { unop := t }))).hom ≫ - ((sheafCompose J U).map ((constantSheafAdj J A ht).counit.app F)).val = - ((presheafToSheaf J B ⋙ sheafToPresheaf J B).mapIso (constComp Cᵒᵖ _ U)).hom ≫ - ((constantSheafAdj J B ht).counit.app ((sheafCompose J U).obj F)).val := by - apply sheafify_hom_ext _ _ _ ((sheafCompose J U).obj F).cond - simp only [sheafCompose_obj_val, id_obj, comp_obj, flip_obj_obj, sheafToPresheaf_obj, - sheafComposeIso_hom_fac_assoc, mapIso_hom, Functor.comp_map, sheafToPresheaf_map] - erw [Adjunction.unit_naturality_assoc] - simp only [const_obj_obj, const_obj_map, id_obj, constComp, comp_obj, sheafToPresheaf_obj, - sheafificationAdjunction_unit_app] - ext - simp only [comp_obj, const_obj_obj, NatTrans.comp_app, whiskerRight_app, Category.id_comp, - comp_obj, flip_obj_obj, sheafToPresheaf_obj, id_obj, constantSheafAdj, - Adjunction.comp, evaluation_obj_obj, NatTrans.comp_app, associator_hom_app, whiskerLeft_app, - whiskerRight_app, map_comp, instCategorySheaf_comp_val, sheafCompose_obj_val, - sheafCompose_map_val, instCategorySheaf_id_val, sheafificationAdjunction_counit_app_val, - NatTrans.id_app, sheafifyMap_sheafifyLift, Category.comp_id, Category.id_comp] - erw [Functor.map_id, Category.id_comp, ← NatTrans.comp_app] - simp only [toSheafify_sheafifyLift, ← Functor.map_comp, ← NatTrans.comp_app, - sheafifyMap_sheafifyLift, Category.comp_id, - constantPresheafAdj, comp_obj, evaluation_obj_obj, id_obj, op_unop, - mkOfUnitCounit_counit, Functor.comp_map] - -/-- Auxiliary lemma for `sheafCompose_reflects_discrete`. -/ -private lemma constantSheafAdj_counit_w : - ((sheafifyComposeIso J U ((const Cᵒᵖ).obj (F.val.obj ⟨t⟩))).symm ≪≫ - (presheafToSheaf J B ⋙ sheafToPresheaf J B).mapIso (constComp Cᵒᵖ (F.val.obj ⟨t⟩) U)).hom ≫ - ((constantSheafAdj J B ht).counit.app ((sheafCompose J U).obj F)).val = - ((sheafCompose J U).map ((constantSheafAdj J A ht).counit.app F)).val := by - rw [← Iso.eq_inv_comp] - simp only [comp_obj, flip_obj_obj, sheafToPresheaf_obj, sheafCompose_obj_val, id_obj, - Iso.trans_inv, mapIso_inv, Functor.comp_map, sheafToPresheaf_map, - Iso.symm_inv, Category.assoc, sheafifyComposeIso_comp_sheafCompose_map_constantSheafAdj_counit, - mapIso_hom, ← instCategorySheaf_comp_val, Iso.map_inv_hom_id_assoc] - -lemma sheafCompose_reflects_discrete [(sheafCompose J U).ReflectsIsomorphisms] - [((sheafCompose J U).obj F).IsDiscrete J ht] : - F.IsDiscrete J ht := by - let f := (sheafCompose J U).map ((constantSheafAdj J A ht).counit.app F) - have : IsIso ((sheafToPresheaf J B).map f) := by - simp only [comp_obj, flip_obj_obj, sheafToPresheaf_obj, sheafCompose_obj_val, id_obj, - sheafToPresheaf_map, f, ← constantSheafAdj_counit_w] - exact inferInstanceAs (IsIso (_ ≫ ((sheafToPresheaf J B).map - ((constantSheafAdj J B ht).counit.app ((sheafCompose J U).obj F))))) - have := isIso_of_reflects_iso f (sheafToPresheaf J B) - exact isIso_of_reflects_iso _ (sheafCompose J U) - -variable [(constantSheaf J A).Full] [(constantSheaf J A).Faithful] - [(constantSheaf J B).Full] [(constantSheaf J B).Faithful] - -instance [h : F.IsDiscrete J ht] : ((sheafCompose J U).obj F).IsDiscrete J ht := by - rw [isDiscrete_iff_mem_essImage] at h ⊢ - obtain ⟨Y, ⟨i⟩⟩ := h - exact ⟨U.obj Y, ⟨(fullyFaithfulSheafToPresheaf _ _).preimageIso - (((sheafifyComposeIso J U ((const Cᵒᵖ).obj Y)).symm ≪≫ - (presheafToSheaf J B ⋙ sheafToPresheaf J B).mapIso (constComp Cᵒᵖ Y U)).symm ≪≫ - (sheafToPresheaf _ _).mapIso ((sheafCompose J U).mapIso i))⟩⟩ - -lemma isDiscrete_iff_forget [(sheafCompose J U).ReflectsIsomorphisms] : F.IsDiscrete J ht ↔ - ((sheafCompose J U).obj F).IsDiscrete J ht := - ⟨fun _ ↦ inferInstance, fun _ ↦ sheafCompose_reflects_discrete _ _ U F⟩ - -end Forget - -end CategoryTheory.Sheaf diff --git a/Mathlib/CategoryTheory/Sites/EqualizerSheafCondition.lean b/Mathlib/CategoryTheory/Sites/EqualizerSheafCondition.lean index 1466ccb25979a..44e39a7bba0c9 100644 --- a/Mathlib/CategoryTheory/Sites/EqualizerSheafCondition.lean +++ b/Mathlib/CategoryTheory/Sites/EqualizerSheafCondition.lean @@ -10,7 +10,7 @@ import Mathlib.Tactic.ApplyFun /-! # The equalizer diagram sheaf condition for a presieve -In `Mathlib/CategoryTheory/Sites/IsSheafFor.lean` it is defined what it means for a presheaf to be a +In `Mathlib/CategoryTheory/Sites/IsSheafFor.lean` it is defined what it means for a presheaf to be a sheaf *for* a particular presieve. In this file we provide equivalent conditions in terms of equalizer diagrams. @@ -228,8 +228,8 @@ theorem compatible_iff (x : FirstObj P R) : See . -/ theorem sheaf_condition : R.IsSheafFor P ↔ Nonempty (IsLimit (Fork.ofι _ (w P R))) := by - rw [Types.type_equalizer_iff_unique] - erw [← Equiv.forall_congr_right (firstObjEqFamily P R).toEquiv.symm] + rw [Types.type_equalizer_iff_unique, + ← Equiv.forall_congr_right (firstObjEqFamily P R).toEquiv.symm] simp_rw [← compatible_iff, ← Iso.toEquiv_fun, Equiv.apply_symm_apply] apply forall₂_congr intro x _ @@ -252,7 +252,7 @@ open Presieve variable {B : C} {I : Type} (X : I → C) (π : (i : I) → X i ⟶ B) [(Presieve.ofArrows X π).hasPullbacks] --- TODO: allow `I : Type w`  +-- TODO: allow `I : Type w` /-- The middle object of the fork diagram of . diff --git a/Mathlib/CategoryTheory/Sites/Equivalence.lean b/Mathlib/CategoryTheory/Sites/Equivalence.lean index 742f549874445..2408d76270ca3 100644 --- a/Mathlib/CategoryTheory/Sites/Equivalence.lean +++ b/Mathlib/CategoryTheory/Sites/Equivalence.lean @@ -63,7 +63,8 @@ instance (priority := 900) [G.IsEquivalence] : IsCoverDense G J where instance : e.functor.IsDenseSubsite J (e.inverse.inducedTopology J) := by have : J = e.functor.inducedTopology (e.inverse.inducedTopology J) := by ext X S - erw [← GrothendieckTopology.pullback_mem_iff_of_isIso (i := e.unit.app X)] + rw [show S ∈ (e.functor.inducedTopology (e.inverse.inducedTopology J)) X ↔ _ + from (GrothendieckTopology.pullback_mem_iff_of_isIso (i := e.unit.app X)).symm] congr!; ext Y f; simp nth_rw 1 [this] infer_instance @@ -71,7 +72,7 @@ instance : e.functor.IsDenseSubsite J (e.inverse.inducedTopology J) := by lemma eq_inducedTopology_of_isDenseSubsite [e.inverse.IsDenseSubsite K J] : K = e.inverse.inducedTopology J := by ext - simp [e.inverse.functorPushforward_mem_iff K J] + exact (e.inverse.functorPushforward_mem_iff K J).symm variable [e.inverse.IsDenseSubsite K J] diff --git a/Mathlib/CategoryTheory/Sites/Grothendieck.lean b/Mathlib/CategoryTheory/Sites/Grothendieck.lean index faa04b5947877..3e453496f9a9d 100644 --- a/Mathlib/CategoryTheory/Sites/Grothendieck.lean +++ b/Mathlib/CategoryTheory/Sites/Grothendieck.lean @@ -86,8 +86,9 @@ structure GrothendieckTopology where namespace GrothendieckTopology -instance : CoeFun (GrothendieckTopology C) fun _ => ∀ X : C, Set (Sieve X) := - ⟨sieves⟩ +instance : DFunLike (GrothendieckTopology C) C (fun X ↦ Set (Sieve X)) where + coe J X := sieves J X + coe_injective' J₁ J₂ h := by cases J₁; cases J₂; congr variable {C} variable {X Y : C} {S R : Sieve X} @@ -98,18 +99,12 @@ We prove this explicitly rather than deriving it so that it is in terms of the c the projection `.sieves`. -/ @[ext] -theorem ext {J₁ J₂ : GrothendieckTopology C} (h : (J₁ : ∀ X : C, Set (Sieve X)) = J₂) : - J₁ = J₂ := by - cases J₁ - cases J₂ - congr +theorem ext {J₁ J₂ : GrothendieckTopology C} (h : (J₁ : ∀ X : C, Set (Sieve X)) = J₂) : J₁ = J₂ := + DFunLike.coe_injective h -/- -Porting note: This is now a syntactic tautology. @[simp] theorem mem_sieves_iff_coe : S ∈ J.sieves X ↔ S ∈ J X := Iff.rfl --/ /-- Also known as the maximality axiom. -/ @[simp] @@ -380,44 +375,11 @@ namespace Cover variable {J} -/- -Porting note: Lean complains that this is a dangerous instance. -I'm commenting this out since the `CoeFun` instance below is what we -use 99% of the time anyway. - -instance : Coe (J.Cover X) (Sieve X) := - ⟨fun S => S.1⟩ --/ - -/- -Porting note (#11445): Added this def as a replacement for the "dangerous" `Coe` above. --/ -/-- The sieve associated to a term of `J.Cover X`. -/ -def sieve (S : J.Cover X) : Sieve X := S.1 - -/- -Porting note: This somehow yields different behavior than the better instance below. Why?! +instance : CoeOut (J.Cover X) (Sieve X) := ⟨fun S => S.1⟩ -With this instance, we have to write `S _ f` but with the uncommented one, we can write `S f` -as expected. - -instance : CoeFun (J.Cover X) fun _ => ∀ ⦃Y⦄ (_ : Y ⟶ X), Prop := - ⟨fun S _ f => (S : Sieve X) f⟩ --/ - -instance : CoeFun (J.Cover X) fun _ => ∀ ⦃Y⦄ (_ : Y ⟶ X), Prop := - ⟨fun S => S.sieve⟩ - -/- -Porting note: This is now a syntactic tautology. - -@[simp] -theorem coe_fun_coe (S : J.Cover X) (f : Y ⟶ X) : S.sieve f = S f := - rfl --/ +instance : CoeFun (J.Cover X) fun _ => ∀ ⦃Y⦄ (_ : Y ⟶ X), Prop := ⟨fun S => (S : Sieve X)⟩ -theorem condition (S : J.Cover X) : S.sieve ∈ J X := - S.2 +theorem condition (S : J.Cover X) : (S : Sieve X) ∈ J X := S.2 @[ext] theorem ext (S T : J.Cover X) (h : ∀ ⦃Y⦄ (f : Y ⟶ X), S f ↔ T f) : S = T := @@ -430,8 +392,7 @@ instance : OrderTop (J.Cover X) := instance : SemilatticeInf (J.Cover X) := { (inferInstance : Preorder _) with - inf := fun S T => ⟨S.sieve ⊓ T.sieve, - J.intersection_covering S.condition T.condition⟩ + inf := fun S T => ⟨S ⊓ T, J.intersection_covering S.condition T.condition⟩ le_antisymm := fun S T h1 h2 => ext _ _ fun {Y} f => ⟨by apply h1, by apply h2⟩ inf_le_left := fun S T Y f hf => hf.1 inf_le_right := fun S T Y f hf => hf.2 @@ -494,7 +455,7 @@ def Arrow.Relation.map {S T : J.Cover X} {I₁ I₂ : S.Arrow} /-- Pull back a cover along a morphism. -/ def pullback (S : J.Cover X) (f : Y ⟶ X) : J.Cover Y := - ⟨Sieve.pullback f S.sieve, J.pullback_stable _ S.condition⟩ + ⟨Sieve.pullback f S, J.pullback_stable _ S.condition⟩ /-- An arrow of `S.pullback f` gives rise to an arrow of `S`. -/ @[simps] @@ -525,8 +486,8 @@ def pullbackComp {X Y Z : C} (S : J.Cover X) (f : Z ⟶ Y) (g : Y ⟶ X) : /-- Combine a family of covers over a cover. -/ def bind {X : C} (S : J.Cover X) (T : ∀ I : S.Arrow, J.Cover I.Y) : J.Cover X := - ⟨Sieve.bind S.sieve fun Y f hf => (T ⟨Y, f, hf⟩).sieve, - J.bind_covering S.condition fun _ _ _ => (T _).condition⟩ + ⟨Sieve.bind S fun Y f hf => T ⟨Y, f, hf⟩, + J.bind_covering S.condition fun _ _ _ => (T { Y := _, f := _, hf := _ }).condition⟩ /-- The canonical morphism from `S.bind T` to `T`. -/ def bindToBase {X : C} (S : J.Cover X) (T : ∀ I : S.Arrow, J.Cover I.Y) : S.bind T ⟶ S := diff --git a/Mathlib/CategoryTheory/Sites/InducedTopology.lean b/Mathlib/CategoryTheory/Sites/InducedTopology.lean index 8c1aae2362041..718bea16efa74 100644 --- a/Mathlib/CategoryTheory/Sites/InducedTopology.lean +++ b/Mathlib/CategoryTheory/Sites/InducedTopology.lean @@ -100,7 +100,7 @@ def inducedTopology : GrothendieckTopology C where @[simp] lemma mem_inducedTopology_sieves_iff {X : C} (S : Sieve X) : - S ∈ (G.inducedTopology K).sieves X ↔ (S.functorPushforward G) ∈ K.sieves (G.obj X) := + S ∈ (G.inducedTopology K) X ↔ (S.functorPushforward G) ∈ K (G.obj X) := Iff.rfl /-- `G` is cover-lifting wrt the induced topology. -/ diff --git a/Mathlib/CategoryTheory/Sites/IsSheafFor.lean b/Mathlib/CategoryTheory/Sites/IsSheafFor.lean index ccd585a8efb58..136e553138ef3 100644 --- a/Mathlib/CategoryTheory/Sites/IsSheafFor.lean +++ b/Mathlib/CategoryTheory/Sites/IsSheafFor.lean @@ -123,7 +123,7 @@ In special cases, this condition can be simplified, see `pullbackCompatible_iff` This is referred to as a "compatible family" in Definition C2.1.2 of [Elephant], and on nlab: https://ncatlab.org/nlab/show/sheaf#GeneralDefinitionInComponents -For a more explicit version in the case where `R` is of the form `Presieve.ofArrows`, see +For a more explicit version in the case where `R` is of the form `Presieve.ofArrows`, see `CategoryTheory.Presieve.Arrows.Compatible`. -/ def FamilyOfElements.Compatible (x : FamilyOfElements P R) : Prop := @@ -142,7 +142,7 @@ Equation (5). Viewing the type `FamilyOfElements` as the middle object of the fo https://stacks.math.columbia.edu/tag/00VM, this condition expresses that `pr₀* (x) = pr₁* (x)`, using the notation defined there. -For a more explicit version in the case where `R` is of the form `Presieve.ofArrows`, see +For a more explicit version in the case where `R` is of the form `Presieve.ofArrows`, see `CategoryTheory.Presieve.Arrows.PullbackCompatible`. -/ def FamilyOfElements.PullbackCompatible (x : FamilyOfElements P R) [R.hasPullbacks] : Prop := @@ -663,7 +663,7 @@ section Arrows variable {B : C} {I : Type*} {X : I → C} (π : (i : I) → X i ⟶ B) (P) /-- -A more explicit version of `FamilyOfElements.Compatible` for a `Presieve.ofArrows`. +A more explicit version of `FamilyOfElements.Compatible` for a `Presieve.ofArrows`. -/ def Arrows.Compatible (x : (i : I) → P.obj (op (X i))) : Prop := ∀ i j Z (gi : Z ⟶ X i) (gj : Z ⟶ X j), gi ≫ π i = gj ≫ π j → @@ -720,7 +720,7 @@ theorem isSheafFor_arrows_iff : (ofArrows X π).IsSheafFor P ↔ variable [(ofArrows X π).hasPullbacks] /-- -A more explicit version of `FamilyOfElements.PullbackCompatible` for a `Presieve.ofArrows`. +A more explicit version of `FamilyOfElements.PullbackCompatible` for a `Presieve.ofArrows`. -/ def Arrows.PullbackCompatible (x : (i : I) → P.obj (op (X i))) : Prop := ∀ i j, P.map (pullback.fst (π i) (π j)).op (x i) = diff --git a/Mathlib/CategoryTheory/Sites/LeftExact.lean b/Mathlib/CategoryTheory/Sites/LeftExact.lean index 4538829b60709..d12346e4674e9 100644 --- a/Mathlib/CategoryTheory/Sites/LeftExact.lean +++ b/Mathlib/CategoryTheory/Sites/LeftExact.lean @@ -245,11 +245,7 @@ instance preservesLimitsOfShape_presheafToSheaf : apply isLimitOfReflects (sheafToPresheaf J D) have : ReflectsLimitsOfShape (AsSmall.{max v u} (FinCategory.AsType K)) (forget D) := reflectsLimitsOfShapeOfReflectsIsomorphisms - -- Porting note: the mathlib proof was by `apply is_limit_of_preserves (J.sheafification D) hS` - have : PreservesLimitsOfShape (AsSmall.{max v u} (FinCategory.AsType K)) - (plusPlusSheaf J D ⋙ sheafToPresheaf J D) := - preservesLimitsOfShapeOfNatIso (J.sheafificationIsoPresheafToSheafCompSheafToPreasheaf D) - exact isLimitOfPreserves (plusPlusSheaf J D ⋙ sheafToPresheaf J D) hS + apply isLimitOfPreserves (J.sheafification D) hS instance preservesfiniteLimits_presheafToSheaf [HasFiniteLimits D] : PreservesFiniteLimits (plusPlusSheaf J D) := by @@ -259,15 +255,15 @@ instance preservesfiniteLimits_presheafToSheaf [HasFiniteLimits D] : variable (J D) -/-- `plusPlusSheaf` is isomorphic to an arbitrary choice of left adjoint. -/ +/-- `plusPlusSheaf` is isomorphic to an arbitrary choice of left adjoint. -/ def plusPlusSheafIsoPresheafToSheaf : plusPlusSheaf J D ≅ presheafToSheaf J D := (plusPlusAdjunction J D).leftAdjointUniq (sheafificationAdjunction J D) -/-- `plusPlusFunctor` is isomorphic to `sheafification`. -/ +/-- `plusPlusFunctor` is isomorphic to `sheafification`. -/ def plusPlusFunctorIsoSheafification : J.sheafification D ≅ sheafification J D := isoWhiskerRight (plusPlusSheafIsoPresheafToSheaf J D) (sheafToPresheaf J D) -/-- `plusPlus` is isomorphic to `sheafify`. -/ +/-- `plusPlus` is isomorphic to `sheafify`. -/ def plusPlusIsoSheafify (P : Cᵒᵖ ⥤ D) : J.sheafify P ≅ sheafify J P := (sheafToPresheaf J D).mapIso ((plusPlusSheafIsoPresheafToSheaf J D).app P) diff --git a/Mathlib/CategoryTheory/Sites/Limits.lean b/Mathlib/CategoryTheory/Sites/Limits.lean index d85824a7edd78..1c38d0e033185 100644 --- a/Mathlib/CategoryTheory/Sites/Limits.lean +++ b/Mathlib/CategoryTheory/Sites/Limits.lean @@ -107,7 +107,7 @@ def isLimitMultiforkOfIsLimit (F : K ⥤ Sheaf J D) (E : Cone (F ⋙ sheafToPres erw [(isLimitOfPreserves ((evaluation Cᵒᵖ D).obj (op X)) hE).fac (multiforkEvaluationCone F E X W S)] dsimp [multiforkEvaluationCone, Presheaf.isLimitOfIsSheaf] - erw [Presheaf.IsSheaf.amalgamate_map] + rw [Presheaf.IsSheaf.amalgamate_map] rfl) (by intro S m hm diff --git a/Mathlib/CategoryTheory/Sites/LocallyInjective.lean b/Mathlib/CategoryTheory/Sites/LocallyInjective.lean index a537edefc713a..782d1b84f0591 100644 --- a/Mathlib/CategoryTheory/Sites/LocallyInjective.lean +++ b/Mathlib/CategoryTheory/Sites/LocallyInjective.lean @@ -115,7 +115,7 @@ lemma isLocallyInjective_iff_equalizerSieve_mem_imp : · intro Y f hf refine J.superset_covering (Sieve.le_pullback_bind S.1 T _ hf) (equalizerSieve_mem J φ _ _ ?_) - erw [NatTrans.naturality_apply, NatTrans.naturality_apply] + rw [NatTrans.naturality_apply, NatTrans.naturality_apply] exact hf · intro hφ exact ⟨fun {X} x y h => hφ x y (by simp [h])⟩ @@ -179,7 +179,7 @@ open GrothendieckTopology.Plus instance isLocallyInjective_toPlus (P : Cᵒᵖ ⥤ Type max u v) : IsLocallyInjective J (J.toPlus P) where equalizerSieve_mem {X} x y h := by - erw [toPlus_eq_mk, toPlus_eq_mk, eq_mk_iff_exists] at h + rw [toPlus_eq_mk, toPlus_eq_mk, eq_mk_iff_exists] at h obtain ⟨W, h₁, h₂, eq⟩ := h exact J.superset_covering (fun Y f hf => congr_fun (congr_arg Subtype.val eq) ⟨Y, f, hf⟩) W.2 diff --git a/Mathlib/CategoryTheory/Sites/MayerVietorisSquare.lean b/Mathlib/CategoryTheory/Sites/MayerVietorisSquare.lean index c0bacd71db3d6..c36e6664261b4 100644 --- a/Mathlib/CategoryTheory/Sites/MayerVietorisSquare.lean +++ b/Mathlib/CategoryTheory/Sites/MayerVietorisSquare.lean @@ -3,6 +3,8 @@ 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.Category.Grp.Adjunctions +import Mathlib.CategoryTheory.Sites.Adjunction import Mathlib.CategoryTheory.Limits.Preserves.Shapes.Square import Mathlib.CategoryTheory.Limits.Shapes.Types import Mathlib.CategoryTheory.Sites.Sheafification @@ -39,9 +41,6 @@ Given a Mayer-Vietoris square `S` and a presheaf `P` on `C`, we introduce a sheaf condition `S.SheafCondition P` and show that it is indeed satisfied by sheaves. -## TODO -* provide constructors for `MayerVietorisSquare` - ## References * https://stacks.math.columbia.edu/tag/08GL @@ -52,10 +51,29 @@ namespace CategoryTheory open Limits Opposite +variable {C : Type u} [Category.{v} C] + {J : GrothendieckTopology C} [HasWeakSheafify J (Type v)] + +@[simp] +lemma Sheaf.isPullback_square_op_map_yoneda_presheafToSheaf_yoneda_iff + (F : Sheaf J (Type v)) (sq : Square C) : + (sq.op.map ((yoneda ⋙ presheafToSheaf J _).op ⋙ yoneda.obj F)).IsPullback ↔ + (sq.op.map F.val).IsPullback := by + refine Square.IsPullback.iff_of_equiv _ _ + (((sheafificationAdjunction J (Type v)).homEquiv _ _).trans yonedaEquiv) + (((sheafificationAdjunction J (Type v)).homEquiv _ _).trans yonedaEquiv) + (((sheafificationAdjunction J (Type v)).homEquiv _ _).trans yonedaEquiv) + (((sheafificationAdjunction J (Type v)).homEquiv _ _).trans yonedaEquiv) ?_ ?_ ?_ ?_ + all_goals + ext x + dsimp + rw [yonedaEquiv_naturality] + erw [Adjunction.homEquiv_naturality_left] + rfl + namespace GrothendieckTopology -variable {C : Type u} [Category.{v} C] - (J : GrothendieckTopology C) [HasWeakSheafify J (Type v)] +variable (J) /-- A Mayer-Vietoris square in a category `C` equipped with a Grothendieck topology consists of a commutative square `f₁₂ ≫ f₂₄ = f₁₃ ≫ f₃₄` in `C` @@ -69,8 +87,62 @@ structure MayerVietorisSquare extends Square C where namespace MayerVietorisSquare variable {J} + +/-- Constructor for Mayer-Vietoris squares taking as an input +a square `sq` such that `sq.f₂₄` is a mono and that for every +sheaf of types `F`, the square `sq.op.map F.val` is a pullback square. -/ +@[simps toSquare] +noncomputable def mk' (sq : Square C) [Mono sq.f₁₃] + (H : ∀ (F : Sheaf J (Type v)), (sq.op.map F.val).IsPullback) : + J.MayerVietorisSquare where + toSquare := sq + isPushout := by + rw [Square.isPushout_iff_op_map_yoneda_isPullback] + intro F + exact (F.isPullback_square_op_map_yoneda_presheafToSheaf_yoneda_iff sq).2 (H F) + +/-- Constructor for Mayer-Vietoris squares taking as an input +a pullback square `sq` such that `sq.f₂₄` and `sq.f₃₄` are two monomorphisms +which form a covering of `S.X₄`. -/ +@[simps! toSquare] +noncomputable def mk_of_isPullback (sq : Square C) [Mono sq.f₂₄] [Mono sq.f₃₄] + (h₁ : sq.IsPullback) (h₂ : Sieve.ofTwoArrows sq.f₂₄ sq.f₃₄ ∈ J sq.X₄) : + J.MayerVietorisSquare := + have : Mono sq.f₁₃ := h₁.mono_f₁₃ + mk' sq (fun F ↦ by + apply Square.IsPullback.mk + refine PullbackCone.IsLimit.mk _ + (fun s ↦ F.2.amalgamateOfArrows _ h₂ + (fun j ↦ WalkingPair.casesOn j s.fst s.snd) + (fun W ↦ by + rintro (_|_) (_|_) a b fac + · obtain rfl : a = b := by simpa only [← cancel_mono sq.f₂₄] using fac + rfl + · obtain ⟨φ, rfl, rfl⟩ := PullbackCone.IsLimit.lift' h₁.isLimit _ _ fac + simpa using s.condition =≫ F.val.map φ.op + · obtain ⟨φ, rfl, rfl⟩ := PullbackCone.IsLimit.lift' h₁.isLimit _ _ fac.symm + simpa using s.condition.symm =≫ F.val.map φ.op + · obtain rfl : a = b := by simpa only [← cancel_mono sq.f₃₄] using fac + rfl)) (fun _ ↦ ?_) (fun _ ↦ ?_) (fun s m hm₁ hm₂ ↦ ?_) + · exact F.2.amalgamateOfArrows_map _ _ _ _ WalkingPair.left + · exact F.2.amalgamateOfArrows_map _ _ _ _ WalkingPair.right + · apply F.2.hom_ext_ofArrows _ h₂ + rintro (_|_) + · rw [F.2.amalgamateOfArrows_map _ _ _ _ WalkingPair.left] + exact hm₁ + · rw [F.2.amalgamateOfArrows_map _ _ _ _ WalkingPair.right] + exact hm₂) + variable (S : J.MayerVietorisSquare) +lemma isPushoutAddCommGrpFreeSheaf [HasWeakSheafify J AddCommGrp.{v}] : + (S.map (yoneda ⋙ (whiskeringRight _ _ _).obj AddCommGrp.free ⋙ + presheafToSheaf J _)).IsPushout := + (S.isPushout.map (Sheaf.composeAndSheafify J AddCommGrp.free)).of_iso + ((Square.mapFunctor.mapIso + (presheafToSheafCompComposeAndSheafifyIso J AddCommGrp.free)).app + (S.map yoneda)) + /-- The condition that a Mayer-Vietoris square becomes a pullback square when we evaluate a presheaf on it. --/ def SheafCondition {A : Type u'} [Category.{v'} A] (P : Cᵒᵖ ⥤ A) : Prop := @@ -126,26 +198,13 @@ lemma map_f₃₄_op_glue : P.map S.f₃₄.op (h.glue u v huv) = v := end SheafCondition -private lemma sheafCondition_of_sheaf' (F : Sheaf J (Type v)) : - S.SheafCondition F.val := by - refine (S.isPushout.op.map (yoneda.obj F)).of_equiv - (((sheafificationAdjunction J (Type v)).homEquiv _ _).trans yonedaEquiv) - (((sheafificationAdjunction J (Type v)).homEquiv _ _).trans yonedaEquiv) - (((sheafificationAdjunction J (Type v)).homEquiv _ _).trans yonedaEquiv) - (((sheafificationAdjunction J (Type v)).homEquiv _ _).trans yonedaEquiv) ?_ ?_ ?_ ?_ - all_goals - ext x - dsimp - rw [yonedaEquiv_naturality] - erw [Adjunction.homEquiv_naturality_left] - rfl - lemma sheafCondition_of_sheaf {A : Type u'} [Category.{v} A] (F : Sheaf J A) : S.SheafCondition F.val := by rw [sheafCondition_iff_comp_coyoneda] intro X - exact S.sheafCondition_of_sheaf' - ⟨_, (isSheaf_iff_isSheaf_of_type _ _).2 (F.cond X.unop)⟩ + exact (Sheaf.isPullback_square_op_map_yoneda_presheafToSheaf_yoneda_iff _ S.toSquare).1 + (S.isPushout.op.map + (yoneda.obj ⟨_, (isSheaf_iff_isSheaf_of_type _ _).2 (F.cond X.unop)⟩)) end MayerVietorisSquare diff --git a/Mathlib/CategoryTheory/Sites/Plus.lean b/Mathlib/CategoryTheory/Sites/Plus.lean index f8755d25759dd..9fe18afba43ba 100644 --- a/Mathlib/CategoryTheory/Sites/Plus.lean +++ b/Mathlib/CategoryTheory/Sites/Plus.lean @@ -67,24 +67,20 @@ theorem diagramNatTrans_id (X : C) (P : Cᵒᵖ ⥤ D) : J.diagramNatTrans (𝟙 P) X = 𝟙 (J.diagram P X) := by ext : 2 refine Multiequalizer.hom_ext _ _ _ (fun i => ?_) - dsimp - simp only [limit.lift_π, Multifork.ofι_pt, Multifork.ofι_π_app, Category.id_comp] - erw [Category.comp_id] + simp @[simp] theorem diagramNatTrans_zero [Preadditive D] (X : C) (P Q : Cᵒᵖ ⥤ D) : J.diagramNatTrans (0 : P ⟶ Q) X = 0 := by ext : 2 refine Multiequalizer.hom_ext _ _ _ (fun i => ?_) - dsimp - rw [zero_comp, Multiequalizer.lift_ι, comp_zero] + simp @[simp] theorem diagramNatTrans_comp {P Q R : Cᵒᵖ ⥤ D} (η : P ⟶ Q) (γ : Q ⟶ R) (X : C) : J.diagramNatTrans (η ≫ γ) X = J.diagramNatTrans η X ≫ J.diagramNatTrans γ X := by ext : 2 refine Multiequalizer.hom_ext _ _ _ (fun i => ?_) - dsimp simp variable (D) @@ -110,7 +106,7 @@ def plusObj : Cᵒᵖ ⥤ D where simp only [diagramPullback_app, colimit.ι_pre, ι_colimMap_assoc, Category.comp_id] let e := S.unop.pullbackId dsimp only [Functor.op, pullback_obj] - erw [← colimit.w _ e.inv.op, ← Category.assoc] + rw [← colimit.w _ e.inv.op, ← Category.assoc] convert Category.id_comp (colimit.ι (diagram J P (unop X)) S) refine Multiequalizer.hom_ext _ _ _ (fun I => ?_) dsimp @@ -127,7 +123,7 @@ def plusObj : Cᵒᵖ ⥤ D where Category.assoc] let e := S.unop.pullbackComp g.unop f.unop dsimp only [Functor.op, pullback_obj] - erw [← colimit.w _ e.inv.op, ← Category.assoc, ← Category.assoc] + rw [← colimit.w _ e.inv.op, ← Category.assoc, ← Category.assoc] congr 1 refine Multiequalizer.hom_ext _ _ _ (fun I => ?_) dsimp diff --git a/Mathlib/CategoryTheory/Sites/Preserves.lean b/Mathlib/CategoryTheory/Sites/Preserves.lean index 3c64ca614f34f..233115606bae5 100644 --- a/Mathlib/CategoryTheory/Sites/Preserves.lean +++ b/Mathlib/CategoryTheory/Sites/Preserves.lean @@ -18,14 +18,14 @@ preserve "the corresponding products". More precisely, given a presheaf `F : Cᵒᵖ ⥤ Type*`, we have: * If `F` satisfies the sheaf condition with respect to the empty sieve on the initial object of `C`, - then `F` preserves terminal objects. + then `F` preserves terminal objects. See `preservesTerminalOfIsSheafForEmpty`. -* If `F` furthermore satisfies the sheaf condition with respect to the presieve consisting of the - inclusion arrows in a coproduct in `C`, then `F` preserves the corresponding product. +* If `F` furthermore satisfies the sheaf condition with respect to the presieve consisting of the + inclusion arrows in a coproduct in `C`, then `F` preserves the corresponding product. See `preservesProductOfIsSheafFor`. -* If `F` preserves a product, then it satisfies the sheaf condition with respect to the +* If `F` preserves a product, then it satisfies the sheaf condition with respect to the corresponding presieve of arrows. See `isSheafFor_of_preservesProduct`. -/ @@ -44,8 +44,8 @@ section Terminal variable (I) in /-- -If `F` is a presheaf which satisfies the sheaf condition with respect to the empty presieve on any -object, then `F` takes that object to the terminal object. +If `F` is a presheaf which satisfies the sheaf condition with respect to the empty presieve on any +object, then `F` takes that object to the terminal object. -/ noncomputable def isTerminal_of_isSheafFor_empty_presieve : IsTerminal (F.obj (op I)) := by @@ -54,8 +54,8 @@ def isTerminal_of_isSheafFor_empty_presieve : IsTerminal (F.obj (op I)) := by exact ⟨⟨fun _ ↦ t⟩, fun a ↦ by ext; exact h.2 _ (by tauto)⟩ /-- -If `F` is a presheaf which satisfies the sheaf condition with respect to the empty presieve on the -initial object, then `F` preserves terminal objects. +If `F` is a presheaf which satisfies the sheaf condition with respect to the empty presieve on the +initial object, then `F` preserves terminal objects. -/ noncomputable def preservesTerminalOfIsSheafForEmpty (hI : IsInitial I) : PreservesLimit (Functor.empty Cᵒᵖ) F := @@ -92,7 +92,7 @@ variable [(ofArrows X c.inj).hasPullbacks] include hc in /-- -If `F` preserves a particular product, then it `IsSheafFor` the corresponging presieve of arrows. +If `F` preserves a particular product, then it `IsSheafFor` the corresponding presieve of arrows. -/ theorem isSheafFor_of_preservesProduct [PreservesLimit (Discrete.functor (fun x ↦ op (X x))) F] : (ofArrows X c.inj).IsSheafFor F := by diff --git a/Mathlib/CategoryTheory/Sites/Pullback.lean b/Mathlib/CategoryTheory/Sites/Pullback.lean index 967d59f82e891..335206084917e 100644 --- a/Mathlib/CategoryTheory/Sites/Pullback.lean +++ b/Mathlib/CategoryTheory/Sites/Pullback.lean @@ -37,11 +37,6 @@ variable {C : Type v₁} [SmallCategory C] {D : Type v₁} [SmallCategory D] (G variable (A : Type u₁) [Category.{v₁} A] variable (J : GrothendieckTopology C) (K : GrothendieckTopology D) --- Porting note: there was an explicit call to --- CategoryTheory.Sheaf.CategoryTheory.SheafToPresheaf.CategoryTheory.createsLimits.{u₁, v₁, v₁} --- but it is not necessary (it was not either in mathlib) -instance [HasLimits A] : CreatesLimits (sheafToPresheaf J A) := inferInstance - -- The assumptions so that we have sheafification variable [ConcreteCategory.{v₁} A] [PreservesLimits (forget A)] [HasColimits A] [HasLimits A] variable [PreservesFilteredColimits (forget A)] [(forget A).ReflectsIsomorphisms] diff --git a/Mathlib/CategoryTheory/Sites/Sheaf.lean b/Mathlib/CategoryTheory/Sites/Sheaf.lean index 14f206f8513f1..80f0edcd7ebfb 100644 --- a/Mathlib/CategoryTheory/Sites/Sheaf.lean +++ b/Mathlib/CategoryTheory/Sites/Sheaf.lean @@ -148,7 +148,7 @@ theorem isLimit_iff_isSheafFor : rw [Classical.nonempty_pi]; constructor · intro hu E x hx specialize hu hx.cone - erw [(homEquivAmalgamation hx).uniqueCongr.nonempty_congr] at hu + rw [(homEquivAmalgamation hx).uniqueCongr.nonempty_congr] at hu exact (unique_subtype_iff_exists_unique _).1 hu · rintro h ⟨E, π⟩ let eqv := conesEquivSieveCompatibleFamily P S (op E) @@ -575,7 +575,6 @@ theorem isSheaf_iff_multiequalizer [∀ (X : C) (S : J.Cover X), HasMultiequaliz · intro a symm erw [IsIso.inv_comp_eq] - dsimp simp end MultiequalizerConditions diff --git a/Mathlib/CategoryTheory/Sites/SheafCohomology/Basic.lean b/Mathlib/CategoryTheory/Sites/SheafCohomology/Basic.lean index ba6a5261a40ff..630cf7424298a 100644 --- a/Mathlib/CategoryTheory/Sites/SheafCohomology/Basic.lean +++ b/Mathlib/CategoryTheory/Sites/SheafCohomology/Basic.lean @@ -5,7 +5,7 @@ Authors: Joël Riou -/ import Mathlib.Algebra.Category.Grp.Abelian import Mathlib.Algebra.Category.Grp.Adjunctions -import Mathlib.Algebra.Homology.DerivedCategory.Ext +import Mathlib.Algebra.Homology.DerivedCategory.Ext.Basic import Mathlib.CategoryTheory.Sites.Abelian import Mathlib.CategoryTheory.Sites.ConstantSheaf diff --git a/Mathlib/CategoryTheory/Sites/SheafHom.lean b/Mathlib/CategoryTheory/Sites/SheafHom.lean index aeec15f07d717..196eeab7477ac 100644 --- a/Mathlib/CategoryTheory/Sites/SheafHom.lean +++ b/Mathlib/CategoryTheory/Sites/SheafHom.lean @@ -82,7 +82,7 @@ def presheafHomSectionsEquiv : (presheafHom F G).sections ≃ (F ⟶ G) where dsimp refine Eq.trans ?_ ((s.1 ⟨X₁⟩).naturality (Over.homMk f : Over.mk f ⟶ Over.mk (𝟙 X₁)).op) - erw [← s.2 f.op, presheafHom_map_app_op_mk_id] + rw [← s.2 f.op, presheafHom_map_app_op_mk_id] rfl } invFun f := ⟨fun X => whiskerLeft _ f, fun _ => rfl⟩ left_inv s := by @@ -174,7 +174,7 @@ lemma presheafHom_isSheafFor : rintro ⟨Z : Over Y₂.left, hZ⟩ dsimp rw [assoc, assoc, app_cond hG x hx Y₂.hom Z.hom hZ, ← G.map_comp, ← op_comp] - erw [app_cond hG x hx Y₁.hom (Z.hom ≫ φ.left) (by simpa using hZ), + rw [app_cond hG x hx Y₁.hom (Z.hom ≫ φ.left) (by simpa using hZ), ← F.map_comp_assoc, op_comp] congr 3 simp }, ?_⟩ diff --git a/Mathlib/CategoryTheory/Sites/SheafOfTypes.lean b/Mathlib/CategoryTheory/Sites/SheafOfTypes.lean index db8d37ff2bf28..c2d7b20d409ae 100644 --- a/Mathlib/CategoryTheory/Sites/SheafOfTypes.lean +++ b/Mathlib/CategoryTheory/Sites/SheafOfTypes.lean @@ -13,7 +13,7 @@ Defines the notion of a sheaf of types (usually called a sheaf of sets by mathem on a category equipped with a Grothendieck topology, as well as a range of equivalent conditions useful in different situations. -In `Mathlib/CategoryTheory/Sites/IsSheafFor.lean` it is defined what it means for a presheaf to be a +In `Mathlib/CategoryTheory/Sites/IsSheafFor.lean` it is defined what it means for a presheaf to be a sheaf *for* a particular sieve. Given a Grothendieck topology `J`, `P` is a sheaf if it is a sheaf for every sieve in the topology. See `IsSheaf`. diff --git a/Mathlib/CategoryTheory/Sites/Sheafification.lean b/Mathlib/CategoryTheory/Sites/Sheafification.lean index 62cb3cf8a3dec..409605999eeb7 100644 --- a/Mathlib/CategoryTheory/Sites/Sheafification.lean +++ b/Mathlib/CategoryTheory/Sites/Sheafification.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Dagur Asgeirsson -/ import Mathlib.CategoryTheory.Adjunction.Unique -import Mathlib.CategoryTheory.Adjunction.FullyFaithful +import Mathlib.CategoryTheory.Adjunction.Reflective import Mathlib.CategoryTheory.Sites.Sheaf import Mathlib.CategoryTheory.Limits.Preserves.Finite /-! @@ -14,7 +14,7 @@ import Mathlib.CategoryTheory.Limits.Preserves.Finite Given a site `(C, J)` we define a typeclass `HasSheafify J A` saying that the inclusion functor from `A`-valued sheaves on `C` to presheaves admits a left exact left adjoint (sheafification). -Note: to access the `HasSheafify` instance for suitable concrete categories, import the file +Note: to access the `HasSheafify` instance for suitable concrete categories, import the file `Mathlib.CategoryTheory.Sites.LeftExact`. -/ @@ -37,7 +37,7 @@ abbrev HasWeakSheafify : Prop := (sheafToPresheaf J A).IsRightAdjoint left adjiont (sheafification). Given a finite limit preserving functor `F : (Cᵒᵖ ⥤ A) ⥤ Sheaf J A` and an adjunction -`adj : F ⊣ sheafToPresheaf J A`, use `HasSheafify.mk'` to construct a `HasSheafify` instance. +`adj : F ⊣ sheafToPresheaf J A`, use `HasSheafify.mk'` to construct a `HasSheafify` instance. -/ class HasSheafify : Prop where isRightAdjoint : HasWeakSheafify J A @@ -72,6 +72,12 @@ def sheafificationAdjunction [HasWeakSheafify J A] : instance [HasWeakSheafify J A] : (presheafToSheaf J A).IsLeftAdjoint := ⟨_, ⟨sheafificationAdjunction J A⟩⟩ +instance [HasWeakSheafify J A] : Reflective (sheafToPresheaf J A) where + adj := sheafificationAdjunction _ _ + +instance [HasSheafify J A] : PreservesFiniteLimits (reflector (sheafToPresheaf J A)) := + inferInstanceAs (PreservesFiniteLimits (presheafToSheaf _ _)) + end variable {D : Type*} [Category D] [HasWeakSheafify J D] @@ -135,7 +141,8 @@ theorem isIso_toSheafify {P : Cᵒᵖ ⥤ D} (hP : Presheaf.IsSheaf J P) : IsIso rfl · change (sheafToPresheaf _ _).map _ ≫ _ = _ change _ ≫ (sheafificationAdjunction J D).unit.app ((sheafToPresheaf J D).obj ⟨P, hP⟩) = _ - erw [← (sheafificationAdjunction J D).inv_counit_map (X := ⟨P, hP⟩), comp_inv_eq_id] + rw [← (sheafificationAdjunction J D).inv_counit_map (X := ⟨P, hP⟩)] + simp /-- If `P` is a sheaf, then `P` is isomorphic to `sheafify J P`. -/ noncomputable def isoSheafify {P : Cᵒᵖ ⥤ D} (hP : Presheaf.IsSheaf J P) : P ≅ sheafify J P := diff --git a/Mathlib/CategoryTheory/Sites/Sieves.lean b/Mathlib/CategoryTheory/Sites/Sieves.lean index d745ad87d9aed..0c06b432214bf 100644 --- a/Mathlib/CategoryTheory/Sites/Sieves.lean +++ b/Mathlib/CategoryTheory/Sites/Sieves.lean @@ -82,11 +82,11 @@ theorem bind_comp {S : Presieve X} {R : ∀ ⦃Y : C⦄ ⦃f : Y ⟶ X⦄, S f -- Porting note: it seems the definition of `Presieve` must be unfolded in order to define -- this inductive type, it was thus renamed `singleton'` -- Note we can't make this into `HasSingleton` because of the out-param. -/-- The singleton presieve. -/ +/-- The singleton presieve. -/ inductive singleton' : ⦃Y : C⦄ → (Y ⟶ X) → Prop | mk : singleton' f -/-- The singleton presieve. -/ +/-- The singleton presieve. -/ def singleton : Presieve X := singleton' f lemma singleton.mk {f : Y ⟶ X} : singleton f f := singleton'.mk @@ -438,6 +438,9 @@ lemma mem_ofArrows_iff {I : Type*} {X : C} (Y : I → C) (f : ∀ i, Y i ⟶ X) · rintro ⟨i, a, rfl⟩ apply downward_closed _ (ofArrows_mk Y f i) +/-- The sieve generated by two morphisms. -/ +abbrev ofTwoArrows {U V X : C} (i : U ⟶ X) (j : V ⟶ X) : Sieve X := + Sieve.ofArrows (Y := pairFunction U V) (fun k ↦ WalkingPair.casesOn k i j) /-- The sieve of `X : C` that is generated by a family of objects `Y : I → C`: it consists of morphisms to `X` which factor through at least one of the `Y i`. -/ diff --git a/Mathlib/CategoryTheory/Sites/Subsheaf.lean b/Mathlib/CategoryTheory/Sites/Subsheaf.lean index a58fe64c5db0c..3731eadbee58d 100644 --- a/Mathlib/CategoryTheory/Sites/Subsheaf.lean +++ b/Mathlib/CategoryTheory/Sites/Subsheaf.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Andrew Yang -/ import Mathlib.CategoryTheory.Elementwise -import Mathlib.CategoryTheory.Adjunction.Evaluation +import Mathlib.CategoryTheory.Limits.FunctorCategory.EpiMono import Mathlib.Tactic.CategoryTheory.Elementwise import Mathlib.CategoryTheory.Adhesive import Mathlib.CategoryTheory.Sites.ConcreteSheafification @@ -252,7 +252,7 @@ theorem Subpresheaf.sheafify_sheafify (h : Presieve.IsSheaf J F) : (G.sheafify J).sheafify J = G.sheafify J := ((Subpresheaf.eq_sheafify_iff _ h).mpr <| G.sheafify_isSheaf h).symm -/-- The lift of a presheaf morphism onto the sheafification subpresheaf. -/ +/-- The lift of a presheaf morphism onto the sheafification subpresheaf. -/ noncomputable def Subpresheaf.sheafifyLift (f : G.toPresheaf ⟶ F') (h : Presieve.IsSheaf J F') : (G.sheafify J).toPresheaf ⟶ F' where app U s := (h (G.sieveOfSection s.1) s.prop).amalgamate @@ -269,12 +269,10 @@ noncomputable def Subpresheaf.sheafifyLift (f : G.toPresheaf ⟶ F') (h : Presie change _ = F'.map (j ≫ i.unop).op _ refine Eq.trans ?_ (Presieve.IsSheafFor.valid_glue (h _ s.2) ((G.family_of_elements_compatible s.1).compPresheafMap f) (j ≫ i.unop) ?_).symm - swap -- Porting note: need to swap two goals otherwise the first goal needs to be proven - -- inside the second goal any way - · dsimp [Presieve.FamilyOfElements.compPresheafMap] at hj ⊢ - rwa [FunctorToTypes.map_comp_apply] · dsimp [Presieve.FamilyOfElements.compPresheafMap] exact congr_arg _ (Subtype.ext (FunctorToTypes.map_comp_apply _ _ _ _).symm) + · dsimp [Presieve.FamilyOfElements.compPresheafMap] at hj ⊢ + rwa [FunctorToTypes.map_comp_apply] theorem Subpresheaf.to_sheafifyLift (f : G.toPresheaf ⟶ F') (h : Presieve.IsSheaf J F') : Subpresheaf.homOfLe (G.le_sheafify J) ≫ G.sheafifyLift f h = f := by @@ -294,7 +292,7 @@ theorem Subpresheaf.to_sheafify_lift_unique (h : Presieve.IsSheaf J F') apply (h _ hs).isSeparatedFor.ext rintro V i hi dsimp at hi - erw [← FunctorToTypes.naturality, ← FunctorToTypes.naturality] + rw [← FunctorToTypes.naturality, ← FunctorToTypes.naturality] exact (congr_fun (congr_app e <| op V) ⟨_, hi⟩ : _) theorem Subpresheaf.sheafify_le (h : G ≤ G') (hF : Presieve.IsSheaf J F) @@ -307,7 +305,7 @@ theorem Subpresheaf.sheafify_le (h : G ≤ G') (hF : Presieve.IsSheaf J F) congr_arg (fun f : G.toPresheaf ⟶ G'.toPresheaf => (NatTrans.app f (op V) ⟨_, hi⟩).1) (G.to_sheafifyLift (Subpresheaf.homOfLe h) hG') convert this.symm - erw [← Subpresheaf.nat_trans_naturality] + rw [← Subpresheaf.nat_trans_naturality] rfl section Image @@ -351,14 +349,14 @@ theorem toImagePresheaf_ι (f : F' ⟶ F) : toImagePresheaf f ≫ (imagePresheaf theorem imagePresheaf_comp_le (f₁ : F ⟶ F') (f₂ : F' ⟶ F'') : imagePresheaf (f₁ ≫ f₂) ≤ imagePresheaf f₂ := fun U _ hx => ⟨f₁.app U hx.choose, hx.choose_spec⟩ -instance isIso_toImagePresheaf {F F' : Cᵒᵖ ⥤ TypeMax.{v, w}} (f : F ⟶ F') [hf : Mono f] : +instance isIso_toImagePresheaf {F F' : Cᵒᵖ ⥤ (Type (max v w))} (f : F ⟶ F') [hf : Mono f] : IsIso (toImagePresheaf f) := by have : ∀ (X : Cᵒᵖ), IsIso ((toImagePresheaf f).app X) := by intro X rw [isIso_iff_bijective] constructor · intro x y e - have := (NatTrans.mono_iff_mono_app _ _).mp hf X + have := (NatTrans.mono_iff_mono_app f).mp hf X rw [mono_iff_injective] at this exact this (congr_arg Subtype.val e : _) · rintro ⟨_, ⟨x, rfl⟩⟩ @@ -417,13 +415,12 @@ def imageMonoFactorization {F F' : Sheaf J (Type w)} (f : F ⟶ F') : Limits.Mon e := toImageSheaf f /-- The mono factorization given by `image_sheaf` for a morphism is an image. -/ -noncomputable def imageFactorization {F F' : Sheaf J TypeMax.{v, u}} (f : F ⟶ F') : +noncomputable def imageFactorization {F F' : Sheaf J (Type (max v u))} (f : F ⟶ F') : Limits.ImageFactorisation f where F := imageMonoFactorization f isImage := { lift := fun I => by - -- Porting note: need to specify the target category (TypeMax.{v, u}) for this to work. - haveI M := (Sheaf.Hom.mono_iff_presheaf_mono J TypeMax.{v, u} _).mp I.m_mono + haveI M := (Sheaf.Hom.mono_iff_presheaf_mono J (Type (max v u)) _).mp I.m_mono haveI := isIso_toImagePresheaf I.m.1 refine ⟨Subpresheaf.homOfLe ?_ ≫ inv (toImagePresheaf I.m.1)⟩ apply Subpresheaf.sheafify_le diff --git a/Mathlib/CategoryTheory/Sites/Types.lean b/Mathlib/CategoryTheory/Sites/Types.lean index 3e4363a236d3d..fca7e5d973986 100644 --- a/Mathlib/CategoryTheory/Sites/Types.lean +++ b/Mathlib/CategoryTheory/Sites/Types.lean @@ -20,8 +20,6 @@ universe u namespace CategoryTheory ---open scoped CategoryTheory.Type -- Porting note: unknown namespace - /-- A Grothendieck topology associated to the category of all types. A sieve is a covering iff it is jointly surjective. -/ def typesGrothendieckTopology : GrothendieckTopology (Type u) where @@ -140,19 +138,25 @@ theorem eval_app (S₁ S₂ : SheafOfTypes.{u} typesGrothendieckTopology) (f : S /-- `yoneda'` induces an equivalence of category between `Type u` and `SheafOfTypes typesGrothendieckTopology`. -/ @[simps!] -noncomputable def typeEquiv : Type u ≌ SheafOfTypes typesGrothendieckTopology := - Equivalence.mk yoneda' (sheafOfTypesToPresheaf _ ⋙ (evaluation _ _).obj (op PUnit)) - (NatIso.ofComponents +noncomputable def typeEquiv : Type u ≌ SheafOfTypes typesGrothendieckTopology where + functor := yoneda' + inverse := sheafOfTypesToPresheaf _ ⋙ (evaluation _ _).obj (op PUnit) + unitIso := NatIso.ofComponents (fun _α => -- α ≅ PUnit ⟶ α { hom := fun x _ => x inv := fun f => f PUnit.unit hom_inv_id := funext fun _ => rfl inv_hom_id := funext fun _ => funext fun y => PUnit.casesOn y rfl }) - fun _ => rfl) - (Iso.symm <| + fun _ => rfl + counitIso := Iso.symm <| NatIso.ofComponents (fun S => equivYoneda' S) fun {S₁ S₂} f => SheafOfTypes.Hom.ext <| NatTrans.ext <| - funext fun α => funext fun s => funext fun x => eval_app S₁ S₂ f (unop α) s x) + funext fun α => funext fun s => funext fun x => eval_app S₁ S₂ f (unop α) s x + functor_unitIso_comp X := by + ext1 + apply yonedaEquiv.injective + dsimp [yoneda', yonedaEquiv, evalEquiv] + erw [typesGlue_eval] theorem subcanonical_typesGrothendieckTopology : Sheaf.Subcanonical typesGrothendieckTopology.{u} := Sheaf.Subcanonical.of_yoneda_isSheaf _ fun _ => isSheaf_yoneda' diff --git a/Mathlib/CategoryTheory/Sites/Whiskering.lean b/Mathlib/CategoryTheory/Sites/Whiskering.lean index f80010696a0b9..17685ddf1e50a 100644 --- a/Mathlib/CategoryTheory/Sites/Whiskering.lean +++ b/Mathlib/CategoryTheory/Sites/Whiskering.lean @@ -129,10 +129,10 @@ instance hasSheafCompose_of_preservesMulticospan (F : A ⥤ B) exact ⟨Limits.IsLimit.postcomposeHomEquiv (S.multicospanComp F P) _ h⟩ /-- -Composing a sheaf with a functor preserving limits of the same size as the hom sets in `C` yields a +Composing a sheaf with a functor preserving limits of the same size as the hom sets in `C` yields a functor between sheaf categories. -Note: the size of the limit that `F` is required to preserve in +Note: the size of the limit that `F` is required to preserve in `hasSheafCompose_of_preservesMulticospan` is in general larger than this. -/ instance hasSheafCompose_of_preservesLimitsOfSize [PreservesLimitsOfSize.{v₁, max u₁ v₁} F] : diff --git a/Mathlib/CategoryTheory/SmallObject/Construction.lean b/Mathlib/CategoryTheory/SmallObject/Construction.lean index 808c18354da20..fe1e1fa4599e9 100644 --- a/Mathlib/CategoryTheory/SmallObject/Construction.lean +++ b/Mathlib/CategoryTheory/SmallObject/Construction.lean @@ -143,7 +143,7 @@ lemma ιFunctorObj_πFunctorObj : ιFunctorObj f πX ≫ πFunctorObj f πX = π /-- The canonical morphism `∐ (functorObjSrcFamily f πX) ⟶ ∐ (functorObjSrcFamily f πY)` induced by a morphism in `φ : X ⟶ Y` such that `φ ≫ πX = πY`. -/ -noncomputable def functorMapSrc (hφ : φ ≫ πY = πX) : +noncomputable def functorMapSrc (hφ : φ ≫ πY = πX) : ∐ (functorObjSrcFamily f πX) ⟶ ∐ functorObjSrcFamily f πY := Sigma.map' (fun x => FunctorObjIndex.mk x.i (x.t ≫ φ) x.b (by simp [hφ])) (fun _ => 𝟙 _) @@ -168,7 +168,7 @@ lemma functorMapSrc_functorObjTop : /-- The canonical morphism `∐ functorObjTgtFamily f πX ⟶ ∐ functorObjTgtFamily f πY` induced by a morphism in `φ : X ⟶ Y` such that `φ ≫ πX = πY`. -/ -noncomputable def functorMapTgt (hφ : φ ≫ πY = πX) : +noncomputable def functorMapTgt (hφ : φ ≫ πY = πX) : ∐ functorObjTgtFamily f πX ⟶ ∐ functorObjTgtFamily f πY := Sigma.map' (fun x => FunctorObjIndex.mk x.i (x.t ≫ φ) x.b (by simp [hφ])) (fun _ => 𝟙 _) diff --git a/Mathlib/CategoryTheory/Square.lean b/Mathlib/CategoryTheory/Square.lean index 3db04feeca7ef..1286c1bd87b9b 100644 --- a/Mathlib/CategoryTheory/Square.lean +++ b/Mathlib/CategoryTheory/Square.lean @@ -26,7 +26,7 @@ We define the flip functor, and two equivalences with the category `Arrow (Arrow C)`, depending on whether we consider a commutative square as a horizontal morphism between two vertical maps (`arrowArrowEquivalence`) -or a vertical morphism betwen two horizontal +or a vertical morphism between two horizontal maps (`arrowArrowEquivalence'`). -/ @@ -326,6 +326,8 @@ def map (sq : Square C) (F : C ⥤ D) : Square D where end Square +variable {C} + namespace Functor /-- The functor `Square C ⥤ Square D` induced by a functor `C ⥤ D`. -/ @@ -344,4 +346,21 @@ def mapSquare (F : C ⥤ D) : Square C ⥤ Square D where end Functor +/-- The natural transformation `F.mapSquare ⟶ G.mapSquare` induces +by a natural transformation `F ⟶ G`. -/ +@[simps] +def NatTrans.mapSquare {F G : C ⥤ D} (τ : F ⟶ G) : + F.mapSquare ⟶ G.mapSquare where + app sq := + { τ₁ := τ.app _ + τ₂ := τ.app _ + τ₃ := τ.app _ + τ₄ := τ.app _ } + +/-- The functor `(C ⥤ D) ⥤ Square C ⥤ Square D`. -/ +@[simps] +def Square.mapFunctor : (C ⥤ D) ⥤ Square C ⥤ Square D where + obj F := F.mapSquare + map τ := NatTrans.mapSquare τ + end CategoryTheory diff --git a/Mathlib/CategoryTheory/Subobject/Lattice.lean b/Mathlib/CategoryTheory/Subobject/Lattice.lean index ac8612b0e93bd..757a945d39a57 100644 --- a/Mathlib/CategoryTheory/Subobject/Lattice.lean +++ b/Mathlib/CategoryTheory/Subobject/Lattice.lean @@ -379,18 +379,19 @@ theorem inf_arrow_factors_right {B : C} (X Y : Subobject B) : Y.Factors (X ⊓ Y theorem finset_inf_factors {I : Type*} {A B : C} {s : Finset I} {P : I → Subobject B} (f : A ⟶ B) : (s.inf P).Factors f ↔ ∀ i ∈ s, (P i).Factors f := by classical - induction' s using Finset.induction_on with _ _ _ ih - · simp [top_factors] - · simp [ih] + induction s using Finset.induction_on with + | empty => simp [top_factors] + | insert _ ih => simp [ih] -- `i` is explicit here because often we'd like to defer a proof of `m` theorem finset_inf_arrow_factors {I : Type*} {B : C} (s : Finset I) (P : I → Subobject B) (i : I) (m : i ∈ s) : (P i).Factors (s.inf P).arrow := by classical revert i m - induction' s using Finset.induction_on with _ _ _ ih - · rintro _ ⟨⟩ - · intro _ m + induction s using Finset.induction_on with + | empty => rintro _ ⟨⟩ + | insert _ ih => + intro _ m rw [Finset.inf_insert] simp only [Finset.mem_insert] at m rcases m with (rfl | m) @@ -472,9 +473,10 @@ theorem finset_sup_factors {I : Type*} {A B : C} {s : Finset I} {P : I → Subob (h : ∃ i ∈ s, (P i).Factors f) : (s.sup P).Factors f := by classical revert h - induction' s using Finset.induction_on with _ _ _ ih - · rintro ⟨_, ⟨⟨⟩, _⟩⟩ - · rintro ⟨j, ⟨m, h⟩⟩ + induction s using Finset.induction_on with + | empty => rintro ⟨_, ⟨⟨⟩, _⟩⟩ + | insert _ ih => + rintro ⟨j, ⟨m, h⟩⟩ simp only [Finset.sup_insert] simp only [Finset.mem_insert] at m rcases m with (rfl | m) diff --git a/Mathlib/CategoryTheory/Sums/Associator.lean b/Mathlib/CategoryTheory/Sums/Associator.lean index 884c130af1617..214fda16c81c1 100644 --- a/Mathlib/CategoryTheory/Sums/Associator.lean +++ b/Mathlib/CategoryTheory/Sums/Associator.lean @@ -112,14 +112,14 @@ theorem inverseAssociator_map_inr_inr {X Y : E} (f : inr (inr X) ⟶ inr (inr Y) /-- The equivalence of categories expressing associativity of sums of categories. -/ -def associativity : (C ⊕ D) ⊕ E ≌ C ⊕ (D ⊕ E) := - Equivalence.mk (associator C D E) (inverseAssociator C D E) - (NatIso.ofComponents (fun X => eqToIso - (by rcases X with ((_|_)|_) <;> rfl)) -- Porting note: aesop_cat fails - (by rintro ((_|_)|_) ((_|_)|_) f <;> first | cases f | aesop_cat)) - (NatIso.ofComponents (fun X => eqToIso - (by rcases X with (_|(_|_)) <;> rfl)) -- Porting note: aesop_cat fails - (by rintro (_|(_|_)) (_|(_|_)) f <;> first | cases f | aesop_cat)) +@[simps functor inverse] +def associativity : (C ⊕ D) ⊕ E ≌ C ⊕ (D ⊕ E) where + functor := associator C D E + inverse := inverseAssociator C D E + unitIso := NatIso.ofComponents (by rintro ((_ | _) | _) <;> exact Iso.refl _) (by + rintro ((_ | _) | _) ((_ | _) | _) f <;> first | cases f | aesop_cat) + counitIso := NatIso.ofComponents (by rintro (_ | (_ | _)) <;> exact Iso.refl _) (by + rintro (_ | (_ | _)) (_ | (_ | _)) f <;> first | cases f | aesop_cat) instance associatorIsEquivalence : (associator C D E).IsEquivalence := (by infer_instance : (associativity C D E).functor.IsEquivalence) diff --git a/Mathlib/CategoryTheory/Sums/Basic.lean b/Mathlib/CategoryTheory/Sums/Basic.lean index aaf7e878026f5..91a569cf79a16 100644 --- a/Mathlib/CategoryTheory/Sums/Basic.lean +++ b/Mathlib/CategoryTheory/Sums/Basic.lean @@ -3,7 +3,7 @@ Copyright (c) 2019 Scott Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Morrison -/ -import Mathlib.CategoryTheory.EqToHom +import Mathlib.CategoryTheory.Equivalence /-! # Binary disjoint unions of categories @@ -31,7 +31,7 @@ section variable (C : Type u₁) [Category.{v₁} C] (D : Type u₁) [Category.{v₁} D] -/- Porting note: `aesop_cat` not firing on `assoc` where autotac in Lean 3 did-/ +/- Porting note: `aesop_cat` not firing on `assoc` where autotac in Lean 3 did -/ /-- `sum C D` gives the direct sum of two categories. -/ @@ -129,10 +129,12 @@ theorem swap_map_inr {X Y : D} {f : inr X ⟶ inr Y} : (swap C D).map f = f := namespace Swap /-- `swap` gives an equivalence between `C ⊕ D` and `D ⊕ C`. -/ -def equivalence : C ⊕ D ≌ D ⊕ C := - Equivalence.mk (swap C D) (swap D C) - (NatIso.ofComponents (fun X => eqToIso (by cases X <;> rfl))) - (NatIso.ofComponents (fun X => eqToIso (by cases X <;> rfl))) +@[simps functor inverse] +def equivalence : C ⊕ D ≌ D ⊕ C where + functor := swap C D + inverse := swap D C + unitIso := NatIso.ofComponents (by rintro (_|_) <;> exact Iso.refl _) + counitIso := NatIso.ofComponents (by rintro (_|_) <;> exact Iso.refl _) instance isEquivalence : (swap C D).IsEquivalence := (by infer_instance : (equivalence C D).functor.IsEquivalence) diff --git a/Mathlib/CategoryTheory/Triangulated/Functor.lean b/Mathlib/CategoryTheory/Triangulated/Functor.lean index 230768841d930..d78ec3c589a8f 100644 --- a/Mathlib/CategoryTheory/Triangulated/Functor.lean +++ b/Mathlib/CategoryTheory/Triangulated/Functor.lean @@ -71,8 +71,12 @@ section Additive variable [Preadditive C] [Preadditive D] [F.Additive] +#adaptation_note +/-- +At nightly-2024-08-08 we needed to increase the maxHeartbeats here. +-/ +set_option maxHeartbeats 400000 in /-- The functor `F.mapTriangle` commutes with the shift. -/ -@[simps!] noncomputable def mapTriangleCommShiftIso (n : ℤ) : Triangle.shiftFunctor C n ⋙ F.mapTriangle ≅ F.mapTriangle ⋙ Triangle.shiftFunctor D n := NatIso.ofComponents (fun T => Triangle.isoMk _ _ @@ -85,6 +89,8 @@ noncomputable def mapTriangleCommShiftIso (n : ℤ) : simp only [comp_obj, assoc, Iso.inv_hom_id_app_assoc, ← Functor.map_comp, Iso.inv_hom_id_app, map_id, comp_id])) (by aesop_cat) +attribute [simps!] mapTriangleCommShiftIso + attribute [local simp] map_zsmul comp_zsmul zsmul_comp commShiftIso_zero commShiftIso_add commShiftIso_comp_hom_app shiftFunctorAdd'_eq_shiftFunctorAdd diff --git a/Mathlib/CategoryTheory/Triangulated/Yoneda.lean b/Mathlib/CategoryTheory/Triangulated/Yoneda.lean index 3d97552da7183..39ec3c60ebdb1 100644 --- a/Mathlib/CategoryTheory/Triangulated/Yoneda.lean +++ b/Mathlib/CategoryTheory/Triangulated/Yoneda.lean @@ -17,14 +17,20 @@ functors `preadditiveCoyoneda.obj A : C ⥤ AddCommGrp` for `A : Cᵒᵖ` and -/ +open CategoryTheory Limits + +variable {C : Type*} [Category C] [Preadditive C] [HasShift C ℤ] + namespace CategoryTheory open Limits Pretriangulated.Opposite namespace Pretriangulated -variable {C : Type*} [Category C] [Preadditive C] [HasZeroObject C] [HasShift C ℤ] - [∀ (n : ℤ), (shiftFunctor C n).Additive] [Pretriangulated C] +section + +variable [HasZeroObject C] [∀ (n : ℤ), (shiftFunctor C n).Additive] + [Pretriangulated C] instance (A : Cᵒᵖ) : (preadditiveCoyoneda.obj A).IsHomological where exact T hT := by @@ -45,12 +51,13 @@ lemma preadditiveYoneda_map_distinguished ((shortComplexOfDistTriangle T hT).op.map (preadditiveYoneda.obj B)).Exact := (preadditiveYoneda.obj B).map_distinguished_op_exact T hT +end + noncomputable instance (A : Cᵒᵖ) : (preadditiveCoyoneda.obj A).ShiftSequence ℤ := Functor.ShiftSequence.tautological _ _ lemma preadditiveCoyoneda_homologySequenceδ_apply - {C : Type*} [Category C] [Preadditive C] [HasShift C ℤ] - (A : Cᵒᵖ) (T : Triangle C) (n₀ n₁ : ℤ) (h : n₀ + 1 = n₁) (x : A.unop ⟶ T.obj₃⟦n₀⟧) : + (T : Triangle C) (n₀ n₁ : ℤ) (h : n₀ + 1 = n₁) {A : Cᵒᵖ} (x : A.unop ⟶ T.obj₃⟦n₀⟧) : (preadditiveCoyoneda.obj A).homologySequenceδ T n₀ n₁ h x = x ≫ T.mor₃⟦n₀⟧' ≫ (shiftFunctorAdd' C 1 n₀ n₁ (by omega)).inv.app _ := by apply Category.assoc diff --git a/Mathlib/CategoryTheory/Types.lean b/Mathlib/CategoryTheory/Types.lean index 900107d6da37e..b7cab7670d304 100644 --- a/Mathlib/CategoryTheory/Types.lean +++ b/Mathlib/CategoryTheory/Types.lean @@ -6,7 +6,7 @@ Authors: Stephen Morgan, Scott Morrison, Johannes Hölzl import Mathlib.CategoryTheory.EpiMono import Mathlib.CategoryTheory.Functor.FullyFaithful import Mathlib.Tactic.PPWithUniv -import Mathlib.Data.Set.Defs +import Mathlib.Data.Set.Operations /-! # The category `Type`. diff --git a/Mathlib/CategoryTheory/Widesubcategory.lean b/Mathlib/CategoryTheory/Widesubcategory.lean index 9f60d4fe54f36..e225caffbde77 100644 --- a/Mathlib/CategoryTheory/Widesubcategory.lean +++ b/Mathlib/CategoryTheory/Widesubcategory.lean @@ -83,7 +83,7 @@ Structure for wide subcategories. Objects ignore the morphism property. -/ @[ext, nolint unusedArguments] structure WideSubcategory (_P : MorphismProperty C) [IsMultiplicative _P] where - /-- The category of which this is a wide subcategory-/ + /-- The category of which this is a wide subcategory -/ obj : C instance WideSubcategory.category : Category.{v₁} (WideSubcategory P) := diff --git a/Mathlib/CategoryTheory/WithTerminal.lean b/Mathlib/CategoryTheory/WithTerminal.lean index ddf52325b64cf..3c35d0efb590e 100644 --- a/Mathlib/CategoryTheory/WithTerminal.lean +++ b/Mathlib/CategoryTheory/WithTerminal.lean @@ -70,6 +70,7 @@ def Hom : WithTerminal C → WithTerminal C → Type v | of X, of Y => X ⟶ Y | star, of _ => PEmpty | _, star => PUnit +attribute [nolint simpNF] Hom.eq_3 /-- Identity morphisms for `WithTerminal C`. -/ @[simp] @@ -85,6 +86,8 @@ def comp : ∀ {X Y Z : WithTerminal C}, Hom X Y → Hom Y Z → Hom X Z | star, of _X, _ => fun f _g => PEmpty.elim f | _, star, of _Y => fun _f g => PEmpty.elim g | star, star, star => fun _ _ => PUnit.unit +attribute [nolint simpNF] comp.eq_3 +attribute [nolint simpNF] comp.eq_4 instance : Category.{v} (WithTerminal C) where Hom X Y := Hom X Y @@ -371,6 +374,7 @@ def Hom : WithInitial C → WithInitial C → Type v | of X, of Y => X ⟶ Y | of _, _ => PEmpty | star, _ => PUnit +attribute [nolint simpNF] Hom.eq_2 /-- Identity morphisms for `WithInitial C`. -/ @[simp] @@ -386,6 +390,8 @@ def comp : ∀ {X Y Z : WithInitial C}, Hom X Y → Hom Y Z → Hom X Z | _, of _X, star => fun _f g => PEmpty.elim g | of _Y, star, _ => fun f _g => PEmpty.elim f | star, star, star => fun _ _ => PUnit.unit +attribute [nolint simpNF] comp.eq_3 +attribute [nolint simpNF] comp.eq_4 instance : Category.{v} (WithInitial C) where Hom X Y := Hom X Y @@ -448,7 +454,7 @@ def mapComp {D E : Type*} [Category D] [Category E] (F : C ⥤ D) (G : D ⥤ E) | of x => Iso.refl _ | star => Iso.refl _) (by aesop_cat) -/-- From a natrual transformation of functors `C ⥤ D`, the induced natural transformation +/-- From a natural transformation of functors `C ⥤ D`, the induced natural transformation of functors `WithInitial C ⥤ WithInitial D`. -/ @[simps] def map₂ {D : Type*} [Category D] {F G : C ⥤ D} (η : F ⟶ G) : map F ⟶ map G where diff --git a/Mathlib/Combinatorics/Additive/AP/Three/Behrend.lean b/Mathlib/Combinatorics/Additive/AP/Three/Behrend.lean index ad0a9bc39e113..9b660a299371d 100644 --- a/Mathlib/Combinatorics/Additive/AP/Three/Behrend.lean +++ b/Mathlib/Combinatorics/Additive/AP/Three/Behrend.lean @@ -278,12 +278,12 @@ theorem log_two_mul_two_le_sqrt_log_eight : log 2 * 2 ≤ √(log 8) := by apply le_sqrt_of_sq_le rw [mul_pow, sq (log 2), mul_assoc, mul_comm] refine mul_le_mul_of_nonneg_right ?_ (log_nonneg one_le_two) - rw [← le_div_iff] + rw [← le_div_iff₀] on_goal 1 => apply log_two_lt_d9.le.trans all_goals norm_num1 theorem two_div_one_sub_two_div_e_le_eight : 2 / (1 - 2 / exp 1) ≤ 8 := by - rw [div_le_iff, mul_sub, mul_one, mul_div_assoc', le_sub_comm, div_le_iff (exp_pos _)] + rw [div_le_iff₀, mul_sub, mul_one, mul_div_assoc', le_sub_comm, div_le_iff₀ (exp_pos _)] · have : 16 < 6 * (2.7182818283 : ℝ) := by norm_num linarith [exp_one_gt_d9] rw [sub_pos, div_lt_one] <;> exact exp_one_gt_d9.trans' (by norm_num) @@ -304,7 +304,7 @@ theorem le_sqrt_log (hN : 4096 ≤ N) : log (2 / (1 - 2 / exp 1)) * (69 / 50) apply le_sqrt_of_sq_le (le_trans _ this) rw [mul_right_comm, mul_pow, sq (log 2), ← mul_assoc] apply mul_le_mul_of_nonneg_right _ (log_nonneg one_le_two) - rw [← le_div_iff'] + rw [← le_div_iff₀'] · exact log_two_lt_d9.le.trans (by norm_num1) exact sq_pos_of_ne_zero (by norm_num1) @@ -315,7 +315,7 @@ theorem exp_neg_two_mul_le {x : ℝ} (hx : 0 < x) : exp (-2 * x) < exp (2 - ⌈x _ ≤ exp (1 - x) / (x + 1) := ?_ _ ≤ exp (2 - ⌈x⌉₊) / (x + 1) := by gcongr _ < _ := by gcongr - rw [le_div_iff (add_pos hx zero_lt_one), ← le_div_iff' (exp_pos _), ← exp_sub, neg_mul, + rw [le_div_iff₀ (add_pos hx zero_lt_one), ← le_div_iff₀' (exp_pos _), ← exp_sub, neg_mul, sub_neg_eq_add, two_mul, sub_add_add_cancel, add_comm _ x] exact le_trans (le_add_of_nonneg_right zero_le_one) (add_one_le_exp _) @@ -325,7 +325,7 @@ theorem div_lt_floor {x : ℝ} (hx : 2 / (1 - 2 / exp 1) ≤ x) : x / exp 1 < ( rw [sub_pos, div_lt_one (exp_pos _)] exact lt_of_le_of_lt (by norm_num) exp_one_gt_d9 rwa [le_sub_comm, div_eq_mul_one_div x, div_eq_mul_one_div x, ← mul_sub, div_sub', ← - div_eq_mul_one_div, mul_div_assoc', one_le_div, ← div_le_iff this] + div_eq_mul_one_div, mul_div_assoc', one_le_div, ← div_le_iff₀ this] · exact zero_lt_two · exact two_ne_zero @@ -363,7 +363,7 @@ theorem three_le_nValue (hN : 64 ≤ N) : 3 ≤ nValue N := by theorem dValue_pos (hN₃ : 8 ≤ N) : 0 < dValue N := by have hN₀ : 0 < (N : ℝ) := cast_pos.2 (succ_pos'.trans_le hN₃) rw [dValue, floor_pos, ← log_le_log_iff zero_lt_one, log_one, log_div _ two_ne_zero, log_rpow hN₀, - inv_mul_eq_div, sub_nonneg, le_div_iff] + inv_mul_eq_div, sub_nonneg, le_div_iff₀] · have : (nValue N : ℝ) ≤ 2 * √(log N) := by apply (ceil_lt_add_one <| sqrt_nonneg _).le.trans rw [two_mul, add_le_add_iff_left] @@ -371,7 +371,7 @@ theorem dValue_pos (hN₃ : 8 ≤ N) : 0 < dValue N := by rw [one_pow, le_log_iff_exp_le hN₀] exact (exp_one_lt_d9.le.trans <| by norm_num).trans (cast_le.2 hN₃) apply (mul_le_mul_of_nonneg_left this <| log_nonneg one_le_two).trans _ - rw [← mul_assoc, ← le_div_iff (Real.sqrt_pos.2 <| log_pos <| one_lt_cast.2 _), div_sqrt] + rw [← mul_assoc, ← le_div_iff₀ (Real.sqrt_pos.2 <| log_pos <| one_lt_cast.2 _), div_sqrt] · apply log_two_mul_two_le_sqrt_log_eight.trans apply Real.sqrt_le_sqrt exact log_le_log (by norm_num) (mod_cast hN₃) @@ -391,7 +391,7 @@ theorem le_N (hN : 2 ≤ N) : (2 * dValue N - 1) ^ nValue N ≤ N := by rw [← rpow_mul (cast_nonneg _), inv_mul_cancel₀, rpow_one] rw [cast_ne_zero] apply (nValue_pos hN).ne' - rw [← le_div_iff'] + rw [← le_div_iff₀'] · exact floor_le (div_nonneg (rpow_nonneg (cast_nonneg _) _) zero_le_two) apply zero_lt_two @@ -399,7 +399,7 @@ theorem bound (hN : 4096 ≤ N) : (N : ℝ) ^ (nValue N : ℝ)⁻¹ / exp 1 < dV apply div_lt_floor _ rw [← log_le_log_iff, log_rpow, mul_comm, ← div_eq_mul_inv] · apply le_trans _ (div_le_div_of_nonneg_left _ _ (ceil_lt_mul _).le) - · rw [mul_comm, ← div_div, div_sqrt, le_div_iff] + · rw [mul_comm, ← div_div, div_sqrt, le_div_iff₀] · norm_num; exact le_sqrt_log hN · norm_num1 · apply log_nonneg @@ -414,7 +414,7 @@ theorem bound (hN : 4096 ≤ N) : (N : ℝ) ^ (nValue N : ℝ)⁻¹ / exp 1 < dV rw [← log_rpow zero_lt_two, rpow_natCast] exact log_le_log (by positivity) (mod_cast hN) refine le_trans ?_ this - rw [← div_le_iff'] + rw [← div_le_iff₀'] · exact log_two_gt_d9.le.trans' (by norm_num1) · norm_num1 · rw [cast_pos] @@ -448,8 +448,8 @@ theorem roth_lower_bound_explicit (hN : 4096 ≤ N) : rw [this] refine mul_le_mul ?_ (exp_neg_two_mul_le <| Real.sqrt_pos.2 <| log_pos ?_).le (exp_pos _).le <| rpow_nonneg (cast_nonneg _) _ - · rw [← le_log_iff_exp_le (rpow_pos_of_pos hN₀ _), log_rpow hN₀, ← le_div_iff, mul_div_assoc, - div_sqrt, neg_mul, neg_le_neg_iff, div_mul_eq_mul_div, div_le_iff hn] + · rw [← le_log_iff_exp_le (rpow_pos_of_pos hN₀ _), log_rpow hN₀, ← le_div_iff₀, mul_div_assoc, + div_sqrt, neg_mul, neg_le_neg_iff, div_mul_eq_mul_div, div_le_iff₀ hn] · exact mul_le_mul_of_nonneg_left (le_ceil _) zero_le_two refine Real.sqrt_pos.2 (log_pos ?_) rw [one_lt_cast] @@ -474,7 +474,7 @@ theorem lower_bound_le_one' (hN : 2 ≤ N) (hN' : N ≤ 4096) : rw [← log_le_log_iff (mul_pos (cast_pos.2 (zero_lt_two.trans_le hN)) (exp_pos _)) zero_lt_one, log_one, log_mul (cast_pos.2 (zero_lt_two.trans_le hN)).ne' (exp_pos _).ne', log_exp, neg_mul, ← sub_eq_add_neg, sub_nonpos, ← - div_le_iff (Real.sqrt_pos.2 <| log_pos <| one_lt_cast.2 <| one_lt_two.trans_le hN), div_sqrt, + div_le_iff₀ (Real.sqrt_pos.2 <| log_pos <| one_lt_cast.2 <| one_lt_two.trans_le hN), div_sqrt, sqrt_le_left zero_le_four, log_le_iff_le_exp (cast_pos.2 (zero_lt_two.trans_le hN))] norm_num1 apply le_trans _ four_zero_nine_six_lt_exp_sixteen.le diff --git a/Mathlib/Combinatorics/Additive/Dissociation.lean b/Mathlib/Combinatorics/Additive/Dissociation.lean index bfb19d5419f00..d7dfe231cee32 100644 --- a/Mathlib/Combinatorics/Additive/Dissociation.lean +++ b/Mathlib/Combinatorics/Additive/Dissociation.lean @@ -4,9 +4,9 @@ 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.Units.Equiv import Mathlib.Data.Fintype.Card -import Mathlib.Data.Set.Pointwise.Basic /-! # Dissociation and span diff --git a/Mathlib/Combinatorics/Additive/Energy.lean b/Mathlib/Combinatorics/Additive/Energy.lean index 341b4509c4465..02b6197b5c3cb 100644 --- a/Mathlib/Combinatorics/Additive/Energy.lean +++ b/Mathlib/Combinatorics/Additive/Energy.lean @@ -164,7 +164,7 @@ variable [CommMonoid α] @[to_additive] lemma mulEnergy_comm (s t : Finset α) : Eₘ[s, t] = Eₘ[t, s] := by rw [mulEnergy, ← Finset.card_map (Equiv.prodComm _ _).toEmbedding, map_filter] - simp [-Finset.card_map, eq_comm, mulEnergy, mul_comm, map_eq_image, Function.comp] + simp [-Finset.card_map, eq_comm, mulEnergy, mul_comm, map_eq_image, Function.comp_def] end CommMonoid diff --git a/Mathlib/Combinatorics/Additive/FreimanHom.lean b/Mathlib/Combinatorics/Additive/FreimanHom.lean index ceb7bc28e54f4..e3069dafec32a 100644 --- a/Mathlib/Combinatorics/Additive/FreimanHom.lean +++ b/Mathlib/Combinatorics/Additive/FreimanHom.lean @@ -5,9 +5,9 @@ Authors: Yaël Dillies -/ import Mathlib.Algebra.BigOperators.Ring import Mathlib.Algebra.CharP.Defs +import Mathlib.Algebra.Group.Pointwise.Set import Mathlib.Algebra.Order.BigOperators.Group.Multiset import Mathlib.Data.ZMod.Defs -import Mathlib.Data.Set.Pointwise.Basic /-! # Freiman homomorphisms diff --git a/Mathlib/Combinatorics/Additive/PluenneckeRuzsa.lean b/Mathlib/Combinatorics/Additive/PluenneckeRuzsa.lean index c959973f91a54..125742993fc6a 100644 --- a/Mathlib/Combinatorics/Additive/PluenneckeRuzsa.lean +++ b/Mathlib/Combinatorics/Additive/PluenneckeRuzsa.lean @@ -46,7 +46,7 @@ theorem ruzsa_triangle_inequality_div_div_div (A B C : Finset α) : · obtain ⟨a, ha, c, hc, rfl⟩ := mem_div.1 hx refine card_le_card_of_injOn (fun b ↦ (a / b, b / c)) (fun b hb ↦ ?_) fun b₁ _ b₂ _ h ↦ ?_ · rw [mem_bipartiteAbove] - exact ⟨mk_mem_product (div_mem_div ha hb) (div_mem_div hb hc), div_mul_div_cancel' _ _ _⟩ + exact ⟨mk_mem_product (div_mem_div ha hb) (div_mem_div hb hc), div_mul_div_cancel _ _ _⟩ · exact div_right_injective (Prod.ext_iff.1 h).1 · exact ((mem_bipartiteBelow _).1 hv).2 @@ -129,14 +129,14 @@ theorem ruzsa_triangle_inequality_mul_mul_mul (A B C : Finset α) : rw [mem_erase, mem_powerset, ← nonempty_iff_ne_empty] at hU refine cast_le.1 (?_ : (_ : ℚ≥0) ≤ _) push_cast - refine (le_div_iff <| cast_pos.2 hB.card_pos).1 ?_ + refine (le_div_iff₀ <| cast_pos.2 hB.card_pos).1 ?_ rw [mul_div_right_comm, mul_comm _ B] refine (Nat.cast_le.2 <| card_le_card_mul_left _ hU.1).trans ?_ refine le_trans ?_ (mul_le_mul (hUA _ hB') (cast_le.2 <| card_le_card <| mul_subset_mul_right hU.2) (zero_le _) (zero_le _)) rw [← mul_div_right_comm, ← mul_assoc] - refine (le_div_iff <| cast_pos.2 hU.1.card_pos).2 ?_ + refine (le_div_iff₀ <| cast_pos.2 hU.1.card_pos).2 ?_ exact mod_cast pluennecke_petridis_inequality_mul C (mul_aux hU.1 hU.2 hUA) /-- **Ruzsa's triangle inequality**. Mul-div-div version. -/ @@ -169,7 +169,7 @@ private lemma card_mul_pow_le (hAB : ∀ A' ⊆ A, (A * B).card * A'.card ≤ (A induction' n with n ih · simp rw [_root_.pow_succ', ← mul_assoc, _root_.pow_succ', @mul_assoc ℚ≥0, ← mul_div_right_comm, - le_div_iff, ← cast_mul] + le_div_iff₀, ← cast_mul] swap · exact cast_pos.2 hA.card_pos refine (Nat.cast_le.2 <| pluennecke_petridis_inequality_mul _ hAB).trans ?_ diff --git a/Mathlib/Combinatorics/Colex.lean b/Mathlib/Combinatorics/Colex.lean index 1f8a439741e9c..0d59516a64ae1 100644 --- a/Mathlib/Combinatorics/Colex.lean +++ b/Mathlib/Combinatorics/Colex.lean @@ -197,7 +197,7 @@ lemma toColex_lt_singleton : toColex s < toColex {a} ↔ ∀ b ∈ s, b < a := b · refine h.2 <| eq_singleton_iff_unique_mem.2 ⟨hb, fun c hc ↦ (h.1 _ hc).2 hb⟩ · simp at h -/-- `{a} ≤ s` in colex iff `s` contains an element greated than or equal to `a`. -/ +/-- `{a} ≤ s` in colex iff `s` contains an element greater than or equal to `a`. -/ lemma singleton_le_toColex : (toColex {a} : Colex α) ≤ toColex s ↔ ∃ x ∈ s, a ≤ x := by simp [toColex_le_toColex]; by_cases a ∈ s <;> aesop diff --git a/Mathlib/Combinatorics/Configuration.lean b/Mathlib/Combinatorics/Configuration.lean index d680b794a0d30..1937c08a8c032 100644 --- a/Mathlib/Combinatorics/Configuration.lean +++ b/Mathlib/Combinatorics/Configuration.lean @@ -57,7 +57,7 @@ instance [h : Fintype P] : Fintype (Dual P) := -- Porting note (#11215): TODO: figure out if this is needed. set_option synthInstance.checkSynthOrder false in instance : Membership (Dual L) (Dual P) := - ⟨Function.swap (Membership.mem : P → L → Prop)⟩ + ⟨Function.swap (Membership.mem : L → P → Prop)⟩ /-- A configuration is nondegenerate if: 1) there does not exist a line that passes through all of the points, @@ -196,9 +196,8 @@ theorem HasLines.pointCount_le_lineCount [HasLines P L] {p : P} {l : L} (h : p exact Fintype.card_le_of_injective (fun p' => ⟨mkLine (this p'), (mkLine_ax (this p')).1⟩) fun p₁ p₂ hp => - Subtype.ext - ((eq_or_eq p₁.2 p₂.2 (mkLine_ax (this p₁)).2 - ((congr_arg _ (Subtype.ext_iff.mp hp)).mpr (mkLine_ax (this p₂)).2)).resolve_right + Subtype.ext ((eq_or_eq p₁.2 p₂.2 (mkLine_ax (this p₁)).2 + ((congr_arg (_ ∈ ·) (Subtype.ext_iff.mp hp)).mpr (mkLine_ax (this p₂)).2)).resolve_right fun h' => (congr_arg (¬p ∈ ·) h').mp h (mkLine_ax (this p₁)).1) theorem HasPoints.lineCount_le_pointCount [HasPoints P L] {p : P} {l : L} (h : p ∉ l) @@ -301,13 +300,12 @@ noncomputable def HasLines.hasPoints [HasLines P L] [Fintype P] [Fintype L] let f : { q : P // q ∈ l₂ } → { l : L // p ∈ l } := fun q => ⟨mkLine (this q), (mkLine_ax (this q)).1⟩ have hf : Function.Injective f := fun q₁ q₂ hq => - Subtype.ext - ((eq_or_eq q₁.2 q₂.2 (mkLine_ax (this q₁)).2 - ((congr_arg _ (Subtype.ext_iff.mp hq)).mpr (mkLine_ax (this q₂)).2)).resolve_right + Subtype.ext ((eq_or_eq q₁.2 q₂.2 (mkLine_ax (this q₁)).2 + ((congr_arg (_ ∈ ·) (Subtype.ext_iff.mp hq)).mpr (mkLine_ax (this q₂)).2)).resolve_right fun h => (congr_arg (¬p ∈ ·) h).mp hl₂ (mkLine_ax (this q₁)).1) have key' := ((Fintype.bijective_iff_injective_and_card f).mpr ⟨hf, key'⟩).2 obtain ⟨q, hq⟩ := key' ⟨l₁, hl₁⟩ - exact ⟨q, (congr_arg _ (Subtype.ext_iff.mp hq)).mp (mkLine_ax (this q)).2, q.2⟩ + exact ⟨q, (congr_arg (_ ∈ ·) (Subtype.ext_iff.mp hq)).mp (mkLine_ax (this q)).2, q.2⟩ { ‹HasLines P L› with mkPoint := fun {l₁ l₂} hl => Classical.choose (this l₁ l₂ hl) mkPoint_ax := fun {l₁ l₂} hl => Classical.choose_spec (this l₁ l₂ hl) } @@ -368,7 +366,7 @@ theorem lineCount_eq_lineCount [Finite P] [Finite L] (p q : P) : lineCount L p = or_not.elim (fun h₂ => ?_) fun h₂ => (HasLines.lineCount_eq_pointCount h h₂).trans hl₂ refine or_not.elim (fun h₃ => ?_) fun h₃ => (HasLines.lineCount_eq_pointCount h h₃).trans hl₃ rw [(eq_or_eq h₂ h₂₂ h₃ h₂₃).resolve_right fun h => - h₃₃ ((congr_arg (Membership.mem p₃) h).mp h₃₂)] + h₃₃ ((congr_arg (p₃ ∈ ·) h).mp h₃₂)] variable (P) {L} @@ -414,7 +412,7 @@ theorem one_lt_order [Finite P] [Finite L] : 1 < order P L := by rw [← add_lt_add_iff_right 1, ← pointCount_eq _ l₂, pointCount, Nat.card_eq_fintype_card, Fintype.two_lt_card_iff] simp_rw [Ne, Subtype.ext_iff] - have h := mkPoint_ax fun h => h₂₁ ((congr_arg _ h).mpr h₂₂) + have h := mkPoint_ax (P := P) (L := L) fun h => h₂₁ ((congr_arg (p₂ ∈ ·) h).mpr h₂₂) exact ⟨⟨mkPoint _, h.2⟩, ⟨p₂, h₂₂⟩, ⟨p₃, h₃₂⟩, ne_of_mem_of_not_mem h.1 h₂₁, ne_of_mem_of_not_mem h.1 h₃₁, ne_of_mem_of_not_mem h₂₃ h₃₃⟩ diff --git a/Mathlib/Combinatorics/Derangements/Finite.lean b/Mathlib/Combinatorics/Derangements/Finite.lean index 31ea036e767de..210773f9903ec 100644 --- a/Mathlib/Combinatorics/Derangements/Finite.lean +++ b/Mathlib/Combinatorics/Derangements/Finite.lean @@ -42,12 +42,14 @@ theorem card_derangements_invariant {α β : Type*} [Fintype α] [DecidableEq α theorem card_derangements_fin_add_two (n : ℕ) : card (derangements (Fin (n + 2))) = (n + 1) * card (derangements (Fin n)) + (n + 1) * card (derangements (Fin (n + 1))) := by - -- get some basic results about the size of fin (n+1) plus or minus an element + -- get some basic results about the size of Fin (n+1) plus or minus an element have h1 : ∀ a : Fin (n + 1), card ({a}ᶜ : Set (Fin (n + 1))) = card (Fin n) := by intro a - simp only [Fintype.card_fin, Finset.card_fin, Fintype.card_ofFinset, Finset.filter_ne' _ a, - Set.mem_compl_singleton_iff, Finset.card_erase_of_mem (Finset.mem_univ a), - add_tsub_cancel_right] + simp only + [card_ofFinset (s := Finset.filter (fun x => x ∈ ({a}ᶜ : Set (Fin (n + 1)))) Finset.univ), + Set.mem_compl_singleton_iff, Finset.filter_ne' _ a, + Finset.card_erase_of_mem (Finset.mem_univ a), Finset.card_fin, add_tsub_cancel_right, + card_fin] have h2 : card (Fin (n + 2)) = card (Option (Fin (n + 1))) := by simp only [card_fin, card_option] -- rewrite the LHS and substitute in our fintype-level equivalence simp only [card_derangements_invariant h2, diff --git a/Mathlib/Combinatorics/Digraph/Basic.lean b/Mathlib/Combinatorics/Digraph/Basic.lean new file mode 100644 index 0000000000000..b6c97992885be --- /dev/null +++ b/Mathlib/Combinatorics/Digraph/Basic.lean @@ -0,0 +1,239 @@ +/- +Copyright (c) 2024 Kyle Miller, Jack Cheverton. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Kyle Miller, Jack Cheverton, Jeremy Tan +-/ +import Mathlib.Order.CompleteBooleanAlgebra +import Mathlib.Data.Fintype.Pi + +/-! +# Digraphs + +This module defines directed graphs on a vertex type `V`, +which is the same notion as a relation `V → V → Prop`. +While this might be too simple of a notion to deserve the grandeur of a new definition, +the intention here is to develop relations using the language of graph theory. + +Note that in this treatment, a digraph may have self loops. + +The type `Digraph V` is structurally equivalent to `Quiver.{0} V`, +but a difference between these is that `Quiver` is a class — +its purpose is to attach a quiver structure to a particular type `V`. +In contrast, for `Digraph V` we are interested in working with the entire lattice +of digraphs on `V`. + +## Main definitions + +* `Digraph` is a structure for relations. Unlike `SimpleGraph`, the relation does not need to be + symmetric or irreflexive. + +* `CompleteAtomicBooleanAlgebra` instance: Under the subgraph relation, `Digraph` forms a + `CompleteAtomicBooleanAlgebra`. In other words, this is the complete lattice of spanning subgraphs + of the complete graph. +-/ + +open Finset Function + +/-- +A digraph is a relation `Adj` on a vertex type `V`. +The relation describes which pairs of vertices are adjacent. + +In this treatment, a digraph may have self-loops. +-/ +@[ext] +structure Digraph (V : Type*) where + /-- The adjacency relation of a digraph. -/ + Adj : V → V → Prop + +/-- +Constructor for digraphs using a boolean function. +This is useful for creating a digraph with a decidable `Adj` relation, +and it's used in the construction of the `Fintype (Digraph V)` instance. +-/ +@[simps] +def Digraph.mk' {V : Type*} : (V → V → Bool) ↪ Digraph V where + toFun x := ⟨fun v w ↦ x v w⟩ + inj' adj adj' := by + simp_rw [mk.injEq] + intro h + funext v w + simpa only [eq_iff_iff, Bool.coe_iff_coe] using congr($h v w) + +instance {V : Type*} (adj : V → V → Bool) : DecidableRel (Digraph.mk' adj).Adj := + inferInstanceAs <| DecidableRel (fun v w ↦ adj v w) + +instance {V : Type*} [DecidableEq V] [Fintype V] : Fintype (Digraph V) := + Fintype.ofBijective Digraph.mk' <| by + classical + refine ⟨Embedding.injective _, ?_⟩ + intro G + use fun v w ↦ G.Adj v w + ext v w + simp + +namespace Digraph + +/-- +The complete digraph on a type `V` (denoted by `⊤`) +is the digraph whose vertices are all adjacent. +Note that every vertex is adjacent to itself in `⊤`. +-/ +protected def completeDigraph (V : Type*) : Digraph V where Adj := ⊤ + +/-- +The empty digraph on a type `V` (denoted by `⊥`) +is the digraph such that no pairs of vertices are adjacent. +Note that `⊥` is called the empty digraph because it has no edges. +-/ +protected def emptyDigraph (V : Type*) : Digraph V where Adj _ _ := False + +/-- +Two vertices are adjacent in the complete bipartite digraph on two vertex types +if and only if they are not from the same side. +Any bipartite digraph may be regarded as a subgraph of one of these. +-/ +@[simps] +def completeBipartiteGraph (V W : Type*) : Digraph (Sum V W) where + Adj v w := v.isLeft ∧ w.isRight ∨ v.isRight ∧ w.isLeft + +variable {ι : Sort*} {V W X : Type*} (G : Digraph V) (G' : Digraph W) {a b c u v w : V} + +theorem adj_injective : Injective (Adj : Digraph V → V → V → Prop) := fun _ _ ↦ Digraph.ext + +@[simp] theorem adj_inj {G H : Digraph V} : G.Adj = H.Adj ↔ G = H := Digraph.ext_iff.symm + +section Order + +/-- +The relation that one `Digraph` is a spanning subgraph of another. +Note that `Digraph.IsSubgraph G H` should be spelled `G ≤ H`. +-/ +protected def IsSubgraph (x y : Digraph V) : Prop := + ∀ ⦃v w : V⦄, x.Adj v w → y.Adj v w + +instance : LE (Digraph V) := ⟨Digraph.IsSubgraph⟩ + +@[simp] +theorem isSubgraph_eq_le : (Digraph.IsSubgraph : Digraph V → Digraph V → Prop) = (· ≤ ·) := rfl + +/-- The supremum of two digraphs `x ⊔ y` has edges where either `x` or `y` have edges. -/ +instance : Sup (Digraph V) where + sup x y := { Adj := x.Adj ⊔ y.Adj } + +@[simp] +theorem sup_adj (x y : Digraph V) (v w : V) : (x ⊔ y).Adj v w ↔ x.Adj v w ∨ y.Adj v w := Iff.rfl + +/-- The infimum of two digraphs `x ⊓ y` has edges where both `x` and `y` have edges. -/ +instance : Inf (Digraph V) where + inf x y := { Adj := x.Adj ⊓ y.Adj } + +@[simp] +theorem inf_adj (x y : Digraph V) (v w : V) : (x ⊓ y).Adj v w ↔ x.Adj v w ∧ y.Adj v w := Iff.rfl + +/-- We define `Gᶜ` to be the `Digraph V` such that no two adjacent vertices in `G` +are adjacent in the complement, and every nonadjacent pair of vertices is adjacent. -/ +instance hasCompl : HasCompl (Digraph V) where + compl G := { Adj := fun v w ↦ ¬G.Adj v w } + +@[simp] theorem compl_adj (G : Digraph V) (v w : V) : Gᶜ.Adj v w ↔ ¬G.Adj v w := Iff.rfl + +/-- The difference of two digraphs `x \ y` has the edges of `x` with the edges of `y` removed. -/ +instance sdiff : SDiff (Digraph V) where + sdiff x y := { Adj := x.Adj \ y.Adj } + +@[simp] +theorem sdiff_adj (x y : Digraph V) (v w : V) : (x \ y).Adj v w ↔ x.Adj v w ∧ ¬y.Adj v w := Iff.rfl + +instance supSet : SupSet (Digraph V) where + sSup s := { Adj := fun a b ↦ ∃ G ∈ s, Adj G a b } + +instance infSet : InfSet (Digraph V) where + sInf s := { Adj := fun a b ↦ (∀ ⦃G⦄, G ∈ s → Adj G a b) } + +@[simp] +theorem sSup_adj {s : Set (Digraph V)} : (sSup s).Adj a b ↔ ∃ G ∈ s, Adj G a b := Iff.rfl + +@[simp] +theorem sInf_adj {s : Set (Digraph V)} : (sInf s).Adj a b ↔ ∀ G ∈ s, Adj G a b := Iff.rfl + +@[simp] +theorem iSup_adj {f : ι → Digraph V} : (⨆ i, f i).Adj a b ↔ ∃ i, (f i).Adj a b := by simp [iSup] + +@[simp] +theorem iInf_adj {f : ι → Digraph V} : (⨅ i, f i).Adj a b ↔ (∀ i, (f i).Adj a b) := by simp [iInf] + +/-- For digraphs `G`, `H`, `G ≤ H` iff `∀ a b, G.Adj a b → H.Adj a b`. -/ +instance distribLattice : DistribLattice (Digraph V) := + { adj_injective.distribLattice Digraph.Adj (fun _ _ ↦ rfl) fun _ _ ↦ rfl with + le := fun G H ↦ ∀ ⦃a b⦄, G.Adj a b → H.Adj a b } + +instance completeAtomicBooleanAlgebra : CompleteAtomicBooleanAlgebra (Digraph V) := + { Digraph.distribLattice with + le := (· ≤ ·) + sup := (· ⊔ ·) + inf := (· ⊓ ·) + compl := HasCompl.compl + sdiff := (· \ ·) + top := Digraph.completeDigraph V + bot := Digraph.emptyDigraph V + le_top := fun x v w _ ↦ trivial + bot_le := fun x v w h ↦ h.elim + sdiff_eq := fun x y ↦ rfl + inf_compl_le_bot := fun G v w h ↦ absurd h.1 h.2 + top_le_sup_compl := fun G v w _ ↦ by tauto + sSup := sSup + le_sSup := fun s G hG a b hab ↦ ⟨G, hG, hab⟩ + sSup_le := fun s G hG a b ↦ by + rintro ⟨H, hH, hab⟩ + exact hG _ hH hab + sInf := sInf + sInf_le := fun s G hG a b hab ↦ hab hG + le_sInf := fun s G hG a b hab ↦ fun H hH ↦ hG _ hH hab + iInf_iSup_eq := fun f ↦ by ext; simp [Classical.skolem] } + +@[simp] theorem top_adj (v w : V) : (⊤ : Digraph V).Adj v w := trivial + +@[simp] theorem bot_adj (v w : V) : (⊥ : Digraph V).Adj v w ↔ False := Iff.rfl + +@[simp] theorem completeDigraph_eq_top (V : Type*) : Digraph.completeDigraph V = ⊤ := rfl + +@[simp] theorem emptyDigraph_eq_bot (V : Type*) : Digraph.emptyDigraph V = ⊥ := rfl + +@[simps] instance (V : Type*) : Inhabited (Digraph V) := ⟨⊥⟩ + +instance [IsEmpty V] : Unique (Digraph V) where + default := ⊥ + uniq G := by ext1; congr! + +instance [Nonempty V] : Nontrivial (Digraph V) := by + use ⊥, ⊤ + have v := Classical.arbitrary V + exact ne_of_apply_ne (·.Adj v v) (by simp) + +section Decidable + +variable (V) (H : Digraph V) [DecidableRel G.Adj] [DecidableRel H.Adj] + +instance Bot.adjDecidable : DecidableRel (⊥ : Digraph V).Adj := + inferInstanceAs <| DecidableRel fun _ _ ↦ False + +instance Sup.adjDecidable : DecidableRel (G ⊔ H).Adj := + inferInstanceAs <| DecidableRel fun v w ↦ G.Adj v w ∨ H.Adj v w + +instance Inf.adjDecidable : DecidableRel (G ⊓ H).Adj := + inferInstanceAs <| DecidableRel fun v w ↦ G.Adj v w ∧ H.Adj v w + +instance SDiff.adjDecidable : DecidableRel (G \ H).Adj := + inferInstanceAs <| DecidableRel fun v w ↦ G.Adj v w ∧ ¬H.Adj v w + +instance Top.adjDecidable : DecidableRel (⊤ : Digraph V).Adj := + inferInstanceAs <| DecidableRel fun _ _ ↦ True + +instance Compl.adjDecidable : DecidableRel (Gᶜ.Adj) := + inferInstanceAs <| DecidableRel fun v w ↦ ¬G.Adj v w + +end Decidable + +end Order + +end Digraph diff --git a/Mathlib/Combinatorics/Enumerative/Composition.lean b/Mathlib/Combinatorics/Enumerative/Composition.lean index cbe6dc1551920..cf2bebdc3109c 100644 --- a/Mathlib/Combinatorics/Enumerative/Composition.lean +++ b/Mathlib/Combinatorics/Enumerative/Composition.lean @@ -112,7 +112,7 @@ structure CompositionAsSet (n : ℕ) where boundaries : Finset (Fin n.succ) /-- Proof that `0` is a member of `boundaries`-/ zero_mem : (0 : Fin n.succ) ∈ boundaries - /-- Last element of the composition-/ + /-- Last element of the composition -/ getLast_mem : Fin.last n ∈ boundaries instance {n : ℕ} : Inhabited (CompositionAsSet n) := @@ -759,7 +759,7 @@ def compositionAsSetEquiv (n : ℕ) : CompositionAsSet n ≃ Finset (Fin (n - 1) exact (zero_le i.val).trans_lt (i.2.trans_le (Nat.sub_le n 1)) simp only [add_comm, Fin.ext_iff, Fin.val_zero, Fin.val_last, exists_prop, Set.toFinset_setOf, Finset.mem_univ, forall_true_left, Finset.mem_filter, add_eq_zero, and_false, - add_left_inj, false_or, true_and] + add_left_inj, false_or, true_and, reduceCtorEq] erw [Set.mem_setOf_eq] simp only [Finset.mem_val] constructor diff --git a/Mathlib/Combinatorics/Enumerative/DoubleCounting.lean b/Mathlib/Combinatorics/Enumerative/DoubleCounting.lean index abb6a33ac4f24..542deff1911e1 100644 --- a/Mathlib/Combinatorics/Enumerative/DoubleCounting.lean +++ b/Mathlib/Combinatorics/Enumerative/DoubleCounting.lean @@ -3,8 +3,8 @@ Copyright (c) 2022 Yaël Dillies. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies -/ +import Mathlib.Algebra.BigOperators.Ring import Mathlib.Algebra.Order.BigOperators.Group.Finset -import Mathlib.Data.Set.Subsingleton /-! # Double countings @@ -30,7 +30,7 @@ and `t`. open Finset Function Relator -variable {α β : Type*} +variable {R α β : Type*} /-! ### Bipartite graph -/ @@ -71,21 +71,98 @@ theorem sum_card_bipartiteAbove_eq_sum_card_bipartiteBelow [∀ a b, Decidable ( simp_rw [card_eq_sum_ones, bipartiteAbove, bipartiteBelow, sum_filter] exact sum_comm -/-- Double counting argument. Considering `r` as a bipartite graph, the LHS is a lower bound on the -number of edges while the RHS is an upper bound. -/ -theorem card_mul_le_card_mul [∀ a b, Decidable (r a b)] +section OrderedSemiring +variable [OrderedSemiring R] [DecidablePred (r a)] [∀ a, Decidable (r a b)] {m n : R} + +/-- **Double counting** argument. + +Considering `r` as a bipartite graph, the LHS is a lower bound on the number of edges while the RHS +is an upper bound. -/ +theorem card_nsmul_le_card_nsmul [∀ a b, Decidable (r a b)] (hm : ∀ a ∈ s, m ≤ (t.bipartiteAbove r a).card) - (hn : ∀ b ∈ t, (s.bipartiteBelow r b).card ≤ n) : s.card * m ≤ t.card * n := + (hn : ∀ b ∈ t, (s.bipartiteBelow r b).card ≤ n) : s.card • m ≤ t.card • n := + calc + _ ≤ ∑ a in s, ((t.bipartiteAbove r a).card : R) := s.card_nsmul_le_sum _ _ hm + _ = ∑ b in t, ((s.bipartiteBelow r b).card : R) := by + norm_cast; rw [sum_card_bipartiteAbove_eq_sum_card_bipartiteBelow] + _ ≤ _ := t.sum_le_card_nsmul _ _ hn + +/-- **Double counting** argument. + +Considering `r` as a bipartite graph, the LHS is a lower bound on the number of edges while the RHS +is an upper bound. -/ +theorem card_nsmul_le_card_nsmul' [∀ a b, Decidable (r a b)] + (hn : ∀ b ∈ t, n ≤ (s.bipartiteBelow r b).card) + (hm : ∀ a ∈ s, (t.bipartiteAbove r a).card ≤ m) : t.card • n ≤ s.card • m := + card_nsmul_le_card_nsmul (swap r) hn hm + +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} + +/-- **Double counting** argument. + +Considering `r` as a bipartite graph, the LHS is a strict lower bound on the number of edges while +the RHS is an upper bound. -/ +theorem card_nsmul_lt_card_nsmul_of_lt_of_le [∀ a b, Decidable (r a b)] (hs : s.Nonempty) + (hm : ∀ a ∈ s, m < (t.bipartiteAbove r a).card) + (hn : ∀ b ∈ t, (s.bipartiteBelow r b).card ≤ n) : s.card • m < t.card • n := calc - _ ≤ ∑ a ∈ s, (t.bipartiteAbove r a).card := s.card_nsmul_le_sum _ _ hm - _ = ∑ b ∈ t, (s.bipartiteBelow r b).card := - sum_card_bipartiteAbove_eq_sum_card_bipartiteBelow _ + _ = ∑ _a ∈ s, m := by rw [sum_const] + _ < ∑ a ∈ s, ((t.bipartiteAbove r a).card : R) := sum_lt_sum_of_nonempty hs hm + _ = ∑ b in t, ((s.bipartiteBelow r b).card : R) := by + norm_cast; rw [sum_card_bipartiteAbove_eq_sum_card_bipartiteBelow] _ ≤ _ := t.sum_le_card_nsmul _ _ hn +/-- **Double counting** argument. + +Considering `r` as a bipartite graph, the LHS is a lower bound on the number of edges while the RHS +is a strict upper bound. -/ +theorem card_nsmul_lt_card_nsmul_of_le_of_lt [∀ a b, Decidable (r a b)] (ht : t.Nonempty) + (hm : ∀ a ∈ s, m ≤ (t.bipartiteAbove r a).card) + (hn : ∀ b ∈ t, (s.bipartiteBelow r b).card < n) : s.card • m < t.card • n := + calc + _ ≤ ∑ a in s, ((t.bipartiteAbove r a).card : R) := s.card_nsmul_le_sum _ _ hm + _ = ∑ b in t, ((s.bipartiteBelow r b).card : R) := by + norm_cast; rw [sum_card_bipartiteAbove_eq_sum_card_bipartiteBelow] + _ < ∑ _b ∈ t, n := sum_lt_sum_of_nonempty ht hn + _ = _ := sum_const _ + +/-- **Double counting** argument. + +Considering `r` as a bipartite graph, the LHS is a strict lower bound on the number of edges while +the RHS is an upper bound. -/ +theorem card_nsmul_lt_card_nsmul_of_lt_of_le' [∀ a b, Decidable (r a b)] (ht : t.Nonempty) + (hn : ∀ b ∈ t, n < (s.bipartiteBelow r b).card) + (hm : ∀ a ∈ s, (t.bipartiteAbove r a).card ≤ m) : t.card • n < s.card • m := + card_nsmul_lt_card_nsmul_of_lt_of_le (swap r) ht hn hm + +/-- **Double counting** argument. + +Considering `r` as a bipartite graph, the LHS is a lower bound on the number of edges while the RHS +is a strict upper bound. -/ +theorem card_nsmul_lt_card_nsmul_of_le_of_lt' [∀ a b, Decidable (r a b)] (hs : s.Nonempty) + (hn : ∀ b ∈ t, n ≤ (s.bipartiteBelow r b).card) + (hm : ∀ a ∈ s, (t.bipartiteAbove r a).card < m) : t.card • n < s.card • m := + card_nsmul_lt_card_nsmul_of_le_of_lt (swap r) hs hn hm + +end StrictOrderedSemiring + +/-- **Double counting** argument. + +Considering `r` as a bipartite graph, the LHS is a lower bound on the number of edges while the RHS +is an upper bound. -/ +theorem card_mul_le_card_mul [∀ a b, Decidable (r a b)] + (hm : ∀ a ∈ s, m ≤ (t.bipartiteAbove r a).card) + (hn : ∀ b ∈ t, (s.bipartiteBelow r b).card ≤ n) : s.card * m ≤ t.card * n := + card_nsmul_le_card_nsmul _ hm hn + theorem card_mul_le_card_mul' [∀ a b, Decidable (r a b)] (hn : ∀ b ∈ t, n ≤ (s.bipartiteBelow r b).card) (hm : ∀ a ∈ s, (t.bipartiteAbove r a).card ≤ m) : t.card * n ≤ s.card * m := - card_mul_le_card_mul (swap r) hn hm + card_nsmul_le_card_nsmul' _ hn hm theorem card_mul_eq_card_mul [∀ a b, Decidable (r a b)] (hm : ∀ a ∈ s, (t.bipartiteAbove r a).card = m) diff --git a/Mathlib/Combinatorics/Enumerative/DyckWord.lean b/Mathlib/Combinatorics/Enumerative/DyckWord.lean index c7ccaf3c8c5ca..ab393d095b11c 100644 --- a/Mathlib/Combinatorics/Enumerative/DyckWord.lean +++ b/Mathlib/Combinatorics/Enumerative/DyckWord.lean @@ -3,8 +3,9 @@ Copyright (c) 2024 Jeremy Tan. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Tan -/ -import Mathlib.Algebra.Order.Ring.Nat -import Mathlib.Data.List.Nodup +import Batteries.Data.List.Count +import Mathlib.Combinatorics.Enumerative.Catalan +import Mathlib.Tactic.Positivity /-! # Dyck words @@ -15,21 +16,29 @@ If the symbols are `(` and `)` the latter restriction is equivalent to balanced if they are `U = (1, 1)` and `D = (1, -1)` the sequence is a lattice path from `(0, 0)` to `(0, 2n)` and the restriction requires the path to never go below the x-axis. +This file defines Dyck words and constructs their bijection with rooted binary trees, +one consequence being that the number of Dyck words with length `2 * n` is `catalan n`. + ## Main definitions * `DyckWord`: a list of `U`s and `D`s with as many `U`s as `D`s and with every prefix having at least as many `U`s as `D`s. * `DyckWord.semilength`: semilength (half the length) of a Dyck word. +* `DyckWord.firstReturn`: for a nonempty word, the index of the `D` matching the initial `U`. + +## Main results + +* `DyckWord.equivTree`: equivalence between Dyck words and rooted binary trees. + See the docstrings of `DyckWord.equivTreeToFun` and `DyckWord.equivTreeInvFun` for details. +* `DyckWord.equivTreesOfNumNodesEq`: equivalence between Dyck words of length `2 * n` and + rooted binary trees with `n` internal nodes. +* `DyckWord.card_dyckWord_semilength_eq_catalan`: + there are `catalan n` Dyck words of length `2 * n` or semilength `n`. ## Implementation notes While any two-valued type could have been used for `DyckStep`, a new enumerated type is used here to emphasise that the definition of a Dyck word does not depend on that underlying type. - -## TODO - -* Prove the bijection between Dyck words and rooted binary trees -(https://github.com/leanprover-community/mathlib4/pull/9781). -/ open List @@ -68,21 +77,36 @@ instance : Add DyckWord where instance : Zero DyckWord := ⟨[], by simp, by simp⟩ -/-- Dyck words form an additive monoid under concatenation, with the empty word as 0. -/ -instance : AddMonoid DyckWord where +/-- Dyck words form an additive cancellative monoid under concatenation, +with the empty word as 0. -/ +instance : AddCancelMonoid DyckWord where add_zero p := by ext1; exact append_nil _ zero_add p := by ext1; rfl add_assoc p q r := by ext1; apply append_assoc nsmul := nsmulRec + add_left_cancel p q r h := by rw [DyckWord.ext_iff] at *; exact append_cancel_left h + add_right_cancel p q r h := by rw [DyckWord.ext_iff] at *; exact append_cancel_right h namespace DyckWord -variable (p q : DyckWord) +variable {p q : DyckWord} lemma toList_eq_nil : p.toList = [] ↔ p = 0 := by rw [DyckWord.ext_iff]; rfl +lemma toList_ne_nil : p.toList ≠ [] ↔ p ≠ 0 := toList_eq_nil.ne + +/-- The only Dyck word that is an additive unit is the empty word. -/ +instance : Unique (AddUnits DyckWord) where + uniq p := by + obtain ⟨a, b, h, -⟩ := p + obtain ⟨ha, hb⟩ := append_eq_nil.mp (toList_eq_nil.mpr h) + congr + · exact toList_eq_nil.mp ha + · exact toList_eq_nil.mp hb + +variable (h : p ≠ 0) /-- The first element of a nonempty Dyck word is `U`. -/ -lemma head_eq_U (h : p.toList ≠ []) : p.toList.head h = U := by +lemma head_eq_U (p : DyckWord) (h) : p.toList.head h = U := by rcases p with - | s; · tauto rw [head_cons] by_contra f @@ -90,30 +114,33 @@ lemma head_eq_U (h : p.toList ≠ []) : p.toList.head h = U := by simpa [s.dichotomy.resolve_left f] using nonneg 1 /-- The last element of a nonempty Dyck word is `D`. -/ -lemma getLast_eq_D (h : p.toList ≠ []) : p.toList.getLast h = D := by +lemma getLast_eq_D (p : DyckWord) (h) : p.toList.getLast h = D := by by_contra f; have s := p.count_U_eq_count_D rw [← dropLast_append_getLast h, (dichotomy _).resolve_right f] at s - simp_rw [dropLast_eq_take, count_append, count_singleton', ite_true, ite_false] at s + simp_rw [dropLast_eq_take, count_append, count_singleton', ite_true, reduceCtorEq, ite_false] at s have := p.count_D_le_count_U (p.toList.length - 1); omega -lemma cons_tail_dropLast_concat (h : p.toList ≠ []) : - U :: p.toList.dropLast.tail ++ [D] = p := by - have : p.toList.dropLast.take 1 = [p.toList.head h] := by +include h in +lemma cons_tail_dropLast_concat : U :: p.toList.dropLast.tail ++ [D] = p := by + have h' := toList_ne_nil.mpr h + have : p.toList.dropLast.take 1 = [p.toList.head h'] := by rcases p with - | ⟨s, ⟨- | ⟨t, r⟩⟩⟩ · tauto · rename_i bal _ cases s <;> simp at bal · tauto - nth_rw 2 [← p.toList.dropLast_append_getLast h, ← p.toList.dropLast.take_append_drop 1] - rw [p.getLast_eq_D, drop_one, this, p.head_eq_U] + nth_rw 2 [← p.toList.dropLast_append_getLast h', ← p.toList.dropLast.take_append_drop 1] + rw [getLast_eq_D, drop_one, this, head_eq_U] rfl +variable (p) in /-- Prefix of a Dyck word as a Dyck word, given that the count of `U`s and `D`s in it are equal. -/ def take (i : ℕ) (hi : (p.toList.take i).count U = (p.toList.take i).count D) : DyckWord where toList := p.toList.take i count_U_eq_count_D := hi count_D_le_count_U k := by rw [take_take]; exact p.count_D_le_count_U (min k i) +variable (p) in /-- Suffix of a Dyck word as a Dyck word, given that the count of `U`s and `D`s in the prefix are equal. -/ def drop (i : ℕ) (hi : (p.toList.take i).count U = (p.toList.take i).count D) : DyckWord where @@ -128,6 +155,7 @@ def drop (i : ℕ) (hi : (p.toList.take i).count U = (p.toList.take i).count D) ← count_append, hi, ← count_append, take_append_drop] exact p.count_D_le_count_U _ +variable (p) in /-- Nest `p` in one pair of brackets, i.e. `x` becomes `(x)`. -/ def nest : DyckWord where toList := [U] ++ p ++ [D] @@ -138,20 +166,36 @@ def nest : DyckWord where apply add_le_add _ (p.count_D_le_count_U _) rcases i.eq_zero_or_pos with hi | hi; · simp [hi] rw [take_of_length_le (show [U].length ≤ i by rwa [length_singleton]), count_singleton'] - simp only [ite_true, ite_false] + simp only [reduceCtorEq, ite_true, ite_false] rw [add_comm] exact add_le_add (zero_le _) ((count_le_length _ _).trans (by simp)) -/-- Denest `p`, i.e. `(x)` becomes `x`, given that `p` is strictly positive in its interior -(this ensures that `x` is a Dyck word). -/ -def denest (h : p.toList ≠ []) (pos : ∀ i, 0 < i → i < p.toList.length → - (p.toList.take i).count D < (p.toList.take i).count U) : DyckWord where +@[simp] lemma nest_ne_zero : p.nest ≠ 0 := by simp [← toList_ne_nil, nest] + +variable (p) in +/-- A property stating that `p` is nonempty and strictly positive in its interior, +i.e. is of the form `(x)` with `x` a Dyck word. -/ +def IsNested : Prop := + p ≠ 0 ∧ ∀ ⦃i⦄, 0 < i → i < p.toList.length → (p.toList.take i).count D < (p.toList.take i).count U + +protected lemma IsNested.nest : p.nest.IsNested := ⟨nest_ne_zero, fun i lb ub ↦ by + simp_rw [nest, length_append, length_singleton] at ub ⊢ + rw [take_append_of_le_length (by rw [singleton_append, length_cons]; omega), + take_append_eq_append_take, take_of_length_le (by rw [length_singleton]; omega), + length_singleton, singleton_append, count_cons_of_ne (by simp), count_cons_self, + Nat.lt_add_one_iff] + exact p.count_D_le_count_U _⟩ + +variable (p) in +/-- Denest `p`, i.e. `(x)` becomes `x`, given that `p.IsNested`. -/ +def denest (hn : p.IsNested) : DyckWord where toList := p.toList.dropLast.tail count_U_eq_count_D := by have := p.count_U_eq_count_D - rw [← p.cons_tail_dropLast_concat h, count_append, count_cons] at this + rw [← cons_tail_dropLast_concat hn.1, count_append, count_cons] at this simpa using this count_D_le_count_U i := by + replace h := toList_ne_nil.mpr hn.1 have l1 : p.toList.take 1 = [p.toList.head h] := by rcases p with - | - <;> tauto have l3 : p.toList.length - 1 = p.toList.length - 1 - 1 + 1 := by rcases p with - | ⟨s, ⟨- | ⟨t, r⟩⟩⟩ @@ -164,19 +208,24 @@ def denest (h : p.toList ≠ []) (pos : ∀ i, 0 < i → i < p.toList.length → (min_le_right _ p.toList.length.pred).trans_lt (Nat.pred_lt ((length_pos.mpr h).ne')) have lb : 0 < min (1 + i) (p.toList.length - 1) := by rw [l3, add_comm, min_add_add_right]; omega - have eq := pos _ lb ub + have eq := hn.2 lb ub set j := min (1 + i) (p.toList.length - 1) rw [← (p.toList.take j).take_append_drop 1, count_append, count_append, take_take, - min_eq_left (by omega), l1, p.head_eq_U] at eq + min_eq_left (by omega), l1, head_eq_U] at eq simp only [count_singleton', ite_true, ite_false] at eq omega -lemma denest_nest (h : p.toList ≠ []) (pos : ∀ i, 0 < i → i < p.toList.length → - (p.toList.take i).count D < (p.toList.take i).count U) : (p.denest h pos).nest = p := by - simpa [DyckWord.ext_iff] using p.cons_tail_dropLast_concat h +variable (p) in +lemma nest_denest (hn) : (p.denest hn).nest = p := by + simpa [DyckWord.ext_iff] using p.cons_tail_dropLast_concat hn.1 + +variable (p) in +lemma denest_nest : p.nest.denest .nest = p := by + simp_rw [nest, denest, DyckWord.ext_iff, dropLast_concat]; rfl section Semilength +variable (p) in /-- The semilength of a Dyck word is half of the number of `DyckStep`s in it, or equivalently its number of `U`s. -/ def semilength : ℕ := p.toList.count U @@ -196,4 +245,346 @@ lemma two_mul_semilength_eq_length : 2 * p.semilength = p.toList.length := by end Semilength +section FirstReturn + +variable (p) in +/-- `p.firstReturn` is 0 if `p = 0` and the index of the `D` matching the initial `U` otherwise. -/ +def firstReturn : ℕ := + (range p.toList.length).findIdx fun i ↦ + (p.toList.take (i + 1)).count U = (p.toList.take (i + 1)).count D + +@[simp] lemma firstReturn_zero : firstReturn 0 = 0 := rfl + +include h in +lemma firstReturn_pos : 0 < p.firstReturn := by + by_contra! f + rw [Nat.le_zero, firstReturn, findIdx_eq] at f + #adaptation_note + /-- + If we don't swap, then the second goal is dropped after completing the first goal. + What's going on? + -/ + swap + · rw [length_range, length_pos] + exact toList_ne_nil.mpr h + · rw [getElem_range] at f + simp at f + rw [← p.cons_tail_dropLast_concat h] at f + simp at f + +include h in +lemma firstReturn_lt_length : p.firstReturn < p.toList.length := by + have lp := length_pos_of_ne_nil (toList_ne_nil.mpr h) + rw [← length_range p.toList.length] + apply findIdx_lt_length_of_exists + simp only [mem_range, decide_eq_true_eq] + use p.toList.length - 1 + exact ⟨by omega, by rw [Nat.sub_add_cancel lp, take_of_length_le (le_refl _), + p.count_U_eq_count_D]⟩ + +include h in +lemma count_take_firstReturn_add_one : + (p.toList.take (p.firstReturn + 1)).count U = (p.toList.take (p.firstReturn + 1)).count D := by + have := findIdx_getElem (w := (length_range p.toList.length).symm ▸ firstReturn_lt_length h) + simpa using this + +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 + exact lt_of_le_of_ne (p.count_D_le_count_U (i + 1)) ne.symm + +@[simp] +lemma firstReturn_add : (p + q).firstReturn = if p = 0 then q.firstReturn else p.firstReturn := by + split_ifs with h; · simp [h] + have u : (p + q).toList = p.toList ++ q.toList := rfl + rw [firstReturn, findIdx_eq] + · simp_rw [u, decide_eq_true_eq, getElem_range] + have v := firstReturn_lt_length h + constructor + · rw [take_append_eq_append_take, show p.firstReturn + 1 - p.toList.length = 0 by omega, + take_zero, append_nil, count_take_firstReturn_add_one h] + · 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' + · rw [length_range, u, length_append] + exact Nat.lt_add_right _ (firstReturn_lt_length h) + +@[simp] +lemma firstReturn_nest : p.nest.firstReturn = p.toList.length + 1 := by + have u : p.nest.toList = U :: p.toList ++ [D] := rfl + rw [firstReturn, findIdx_eq] + · simp_rw [u, decide_eq_true_eq, getElem_range] + constructor + · rw [take_of_length_le (by simp), ← u, p.nest.count_U_eq_count_D] + · intro j hj + simp_rw [cons_append, take_succ_cons, count_cons, beq_self_eq_true, ite_true, + 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 + omega + · simp_rw [length_range, u, length_append, length_cons] + exact Nat.lt_add_one _ + +variable (p) in +/-- The left part of the Dyck word decomposition, +inside the `U, D` pair that `firstReturn` refers to. `insidePart 0 = 0`. -/ +def insidePart : DyckWord := + if h : p = 0 then 0 else + (p.take (p.firstReturn + 1) (count_take_firstReturn_add_one h)).denest + ⟨by rw [← toList_ne_nil, take]; simpa using toList_ne_nil.mpr h, fun i lb ub ↦ by + simp only [take, length_take, lt_min_iff] at ub ⊢ + replace ub := ub.1 + rw [take_take, min_eq_left ub.le] + rw [show i = i - 1 + 1 by omega] at ub ⊢ + rw [Nat.add_lt_add_iff_right] at ub + exact count_D_lt_count_U_of_lt_firstReturn ub⟩ + +variable (p) in +/-- The right part of the Dyck word decomposition, +outside the `U, D` pair that `firstReturn` refers to. `outsidePart 0 = 0`. -/ +def outsidePart : DyckWord := + if h : p = 0 then 0 else p.drop (p.firstReturn + 1) (count_take_firstReturn_add_one h) + +@[simp] lemma insidePart_zero : insidePart 0 = 0 := by simp [insidePart] +@[simp] lemma outsidePart_zero : outsidePart 0 = 0 := by simp [outsidePart] + +include h in +@[simp] +lemma insidePart_add : (p + q).insidePart = p.insidePart := by + simp_rw [insidePart, firstReturn_add, add_eq_zero', h, false_and, dite_false, ite_false, + DyckWord.ext_iff, take] + congr 3 + exact take_append_of_le_length (firstReturn_lt_length h) + +include h in +@[simp] +lemma outsidePart_add : (p + q).outsidePart = p.outsidePart + q := by + simp_rw [outsidePart, firstReturn_add, add_eq_zero', h, false_and, dite_false, ite_false, + DyckWord.ext_iff, drop] + exact drop_append_of_le_length (firstReturn_lt_length h) + +@[simp] +lemma insidePart_nest : p.nest.insidePart = p := by + simp_rw [insidePart, nest_ne_zero, dite_false, firstReturn_nest] + convert p.denest_nest; rw [DyckWord.ext_iff]; apply take_of_length_le + simp_rw [nest, length_append, length_singleton]; omega + +@[simp] +lemma outsidePart_nest : p.nest.outsidePart = 0 := by + simp_rw [outsidePart, nest_ne_zero, dite_false, firstReturn_nest] + rw [DyckWord.ext_iff]; apply drop_of_length_le + simp_rw [nest, length_append, length_singleton]; omega + +include h in +@[simp] +theorem nest_insidePart_add_outsidePart : p.insidePart.nest + p.outsidePart = p := by + simp_rw [insidePart, outsidePart, h, dite_false, nest_denest, DyckWord.ext_iff] + apply take_append_drop + +include h in +lemma semilength_insidePart_add_semilength_outsidePart_add_one : + p.insidePart.semilength + p.outsidePart.semilength + 1 = p.semilength := by + rw [← congrArg semilength (nest_insidePart_add_outsidePart h), semilength_add, semilength_nest, + add_right_comm] + +include h in +theorem semilength_insidePart_lt : p.insidePart.semilength < p.semilength := by + have := semilength_insidePart_add_semilength_outsidePart_add_one h + omega + +include h in +theorem semilength_outsidePart_lt : p.outsidePart.semilength < p.semilength := by + have := semilength_insidePart_add_semilength_outsidePart_add_one h + omega + +end FirstReturn + +section Order + +instance : Preorder DyckWord where + le := Relation.ReflTransGen (fun p q ↦ p = q.insidePart ∨ p = q.outsidePart) + le_refl p := Relation.ReflTransGen.refl + le_trans p q r := Relation.ReflTransGen.trans + +lemma le_add_self (p q : DyckWord) : q ≤ p + q := by + by_cases h : p = 0 + · simp [h] + · have := semilength_outsidePart_lt h + exact (le_add_self p.outsidePart q).trans + (Relation.ReflTransGen.single (Or.inr (outsidePart_add h).symm)) +termination_by p.semilength + +variable (p) in protected lemma zero_le : 0 ≤ p := add_zero p ▸ le_add_self p 0 + +lemma infix_of_le (h : p ≤ q) : p.toList <:+: q.toList := by + induction h with + | refl => exact infix_refl _ + | tail _pm mq ih => + rename_i m r + rcases eq_or_ne r 0 with rfl | hr + · rw [insidePart_zero, outsidePart_zero, or_self] at mq + rwa [mq] at ih + · have : [U] ++ r.insidePart ++ [D] ++ r.outsidePart = r := + DyckWord.ext_iff.mp (nest_insidePart_add_outsidePart hr) + rcases mq with hm | hm + · have : r.insidePart <:+: r.toList := by + use [U], [D] ++ r.outsidePart; rwa [← append_assoc] + exact ih.trans (hm ▸ this) + · have : r.outsidePart <:+: r.toList := by + use [U] ++ r.insidePart ++ [D], []; rwa [append_nil] + exact ih.trans (hm ▸ this) + +lemma le_of_suffix (h : p.toList <:+ q.toList) : p ≤ q := by + obtain ⟨r', h⟩ := h + have hc : (q.toList.take (q.toList.length - p.toList.length)).count U = + (q.toList.take (q.toList.length - p.toList.length)).count D := by + have hq := q.count_U_eq_count_D + rw [← h] at hq ⊢ + rw [count_append, count_append, p.count_U_eq_count_D, Nat.add_right_cancel_iff] at hq + simp [hq] + let r : DyckWord := q.take _ hc + have e : r' = r := by + simp_rw [r, take, ← h, length_append, add_tsub_cancel_right, take_left'] + rw [e] at h; replace h : r + p = q := DyckWord.ext h; rw [← h]; exact le_add_self .. + +/-- Partial order on Dyck words: `p ≤ q` if a (possibly empty) sequence of +`insidePart` and `outsidePart` operations can turn `q` into `p`. -/ +instance : PartialOrder DyckWord where + le_antisymm p q pq qp := by + have h₁ := infix_of_le pq + have h₂ := infix_of_le qp + exact DyckWord.ext <| h₁.eq_of_length <| h₁.length_le.antisymm h₂.length_le + +protected lemma pos_iff_ne_zero : 0 < p ↔ p ≠ 0 := by + rw [ne_comm, iff_comm, ne_iff_lt_iff_le] + exact DyckWord.zero_le p + +lemma monotone_semilength : Monotone semilength := fun p q pq ↦ by + induction pq with + | refl => rfl + | tail _ mq ih => + rename_i m r _ + rcases eq_or_ne r 0 with rfl | hr + · rw [insidePart_zero, outsidePart_zero, or_self] at mq + rwa [mq] at ih + · rcases mq with hm | hm + · exact ih.trans (hm ▸ semilength_insidePart_lt hr).le + · exact ih.trans (hm ▸ semilength_outsidePart_lt hr).le + +lemma strictMono_semilength : StrictMono semilength := fun p q pq ↦ by + obtain ⟨plq, pnq⟩ := lt_iff_le_and_ne.mp pq + apply lt_of_le_of_ne (monotone_semilength plq) + contrapose! pnq + replace pnq := congr(2 * $(pnq)) + simp_rw [two_mul_semilength_eq_length] at pnq + exact DyckWord.ext ((infix_of_le plq).eq_of_length pnq) + +end Order + +section Tree + +open Tree + +/-- Convert a Dyck word to a binary rooted tree. + +`f(0) = nil`. For a nonzero word find the `D` that matches the initial `U`, +which has index `p.firstReturn`, then let `x` be everything strictly between said `U` and `D`, +and `y` be everything strictly after said `D`. `p = x.nest + y` with `x, y` (possibly empty) +Dyck words. `f(p) = f(x) △ f(y)`, where △ (defined in `Mathlib.Data.Tree`) joins two subtrees +to a new root node. -/ +private def equivTreeToFun (p : DyckWord) : Tree Unit := + if h : p = 0 then nil else + have := semilength_insidePart_lt h + have := semilength_outsidePart_lt h + equivTreeToFun p.insidePart △ equivTreeToFun p.outsidePart +termination_by p.semilength + +/-- Convert a binary rooted tree to a Dyck word. + +`g(nil) = 0`. A nonempty tree with left subtree `l` and right subtree `r` +is sent to `g(l).nest + g(r)`. -/ +private def equivTreeInvFun : Tree Unit → DyckWord + | Tree.nil => 0 + | Tree.node _ l r => (equivTreeInvFun l).nest + equivTreeInvFun r + +@[nolint unusedHavesSuffices] +private lemma equivTree_left_inv (p) : equivTreeInvFun (equivTreeToFun p) = p := by + by_cases h : p = 0 + · simp [h, equivTreeToFun, equivTreeInvFun] + · rw [equivTreeToFun] + simp_rw [h, dite_false, equivTreeInvFun] + have := semilength_insidePart_lt h + have := semilength_outsidePart_lt h + rw [equivTree_left_inv p.insidePart, equivTree_left_inv p.outsidePart] + exact nest_insidePart_add_outsidePart h +termination_by p.semilength + +@[nolint unusedHavesSuffices] +private lemma equivTree_right_inv : ∀ t, equivTreeToFun (equivTreeInvFun t) = t + | Tree.nil => by simp [equivTreeInvFun, equivTreeToFun] + | Tree.node _ _ _ => by simp [equivTreeInvFun, equivTreeToFun, equivTree_right_inv] + +/-- Equivalence between Dyck words and rooted binary trees. -/ +def equivTree : DyckWord ≃ Tree Unit where + toFun := equivTreeToFun + invFun := equivTreeInvFun + left_inv := equivTree_left_inv + right_inv := equivTree_right_inv + +@[nolint unusedHavesSuffices] +lemma semilength_eq_numNodes_equivTree (p) : p.semilength = (equivTree p).numNodes := by + by_cases h : p = 0 + · simp [h, equivTree, equivTreeToFun] + · rw [equivTree, Equiv.coe_fn_mk, equivTreeToFun] + simp_rw [h, dite_false, numNodes] + have := semilength_insidePart_lt h + have := semilength_outsidePart_lt h + rw [← semilength_insidePart_add_semilength_outsidePart_add_one h, + semilength_eq_numNodes_equivTree p.insidePart, + semilength_eq_numNodes_equivTree p.outsidePart]; rfl +termination_by p.semilength + +/-- Equivalence between Dyck words of semilength `n` and rooted binary trees with +`n` internal nodes. -/ +def equivTreesOfNumNodesEq (n : ℕ) : + { p : DyckWord // p.semilength = n } ≃ treesOfNumNodesEq n where + toFun := fun ⟨p, _⟩ ↦ ⟨equivTree p, by + rwa [mem_treesOfNumNodesEq, ← semilength_eq_numNodes_equivTree]⟩ + invFun := fun ⟨tr, _⟩ ↦ ⟨equivTree.symm tr, by + rwa [semilength_eq_numNodes_equivTree, ← mem_treesOfNumNodesEq, Equiv.apply_symm_apply]⟩ + left_inv _ := by simp only [Equiv.symm_apply_apply] + right_inv _ := by simp only [Equiv.apply_symm_apply] + +instance {n : ℕ} : Fintype { p : DyckWord // p.semilength = n } := + Fintype.ofEquiv _ (equivTreesOfNumNodesEq n).symm + +/-- There are `catalan n` Dyck words of semilength `n` (or length `2 * n`). -/ +theorem card_dyckWord_semilength_eq_catalan (n : ℕ) : + Fintype.card { p : DyckWord // p.semilength = n } = catalan n := by + rw [← Fintype.ofEquiv_card (equivTreesOfNumNodesEq n), ← treesOfNumNodesEq_card_eq_catalan] + convert Fintype.card_coe _ + +end Tree + end DyckWord + +namespace Mathlib.Meta.Positivity + +open Lean Meta Qq + +/-- Extension for the `positivity` tactic: `p.firstReturn` is positive if `p` is nonzero. -/ +@[positivity DyckWord.firstReturn _] +def evalDyckWordFirstReturn : PositivityExt where eval {u α} _zα _pα e := do + match u, α, e with + | 0, ~q(ℕ), ~q(DyckWord.firstReturn $a) => + let ra ← core q(inferInstance) q(inferInstance) a + assertInstancesCommute + match ra with + | .positive pa => pure (.positive q(DyckWord.firstReturn_pos ($pa).ne')) + | .nonzero pa => pure (.positive q(DyckWord.firstReturn_pos $pa)) + | _ => pure .none + | _, _, _ => throwError "not DyckWord.firstReturn" + +end Mathlib.Meta.Positivity diff --git a/Mathlib/Combinatorics/Enumerative/Partition.lean b/Mathlib/Combinatorics/Enumerative/Partition.lean index d88c1fba8060d..94bcb8771017a 100644 --- a/Mathlib/Combinatorics/Enumerative/Partition.lean +++ b/Mathlib/Combinatorics/Enumerative/Partition.lean @@ -50,7 +50,7 @@ namespace Nat structure Partition (n : ℕ) where /-- positive integers summing to `n`-/ parts : Multiset ℕ - /-- proof that the `parts` are positive-/ + /-- proof that the `parts` are positive -/ parts_pos : ∀ {i}, i ∈ parts → 0 < i /-- proof that the `parts` sum to `n`-/ parts_sum : parts.sum = n diff --git a/Mathlib/Combinatorics/Hall/Basic.lean b/Mathlib/Combinatorics/Hall/Basic.lean index 180890300f1c4..52a8937ef3082 100644 --- a/Mathlib/Combinatorics/Hall/Basic.lean +++ b/Mathlib/Combinatorics/Hall/Basic.lean @@ -57,7 +57,7 @@ universe u v /-- The set of matchings for `t` when restricted to a `Finset` of `ι`. -/ def hallMatchingsOn {ι : Type u} {α : Type v} (t : ι → Finset α) (ι' : Finset ι) := - { f : ι' → α | Function.Injective f ∧ ∀ x, f x ∈ t x } + { f : ι' → α | Function.Injective f ∧ ∀ (x : {x // x ∈ ι'}), f x ∈ t x } /-- Given a matching on a finset, construct the restriction of that matching to a subset. -/ def hallMatchingsOn.restrict {ι : Type u} {α : Type v} (t : ι → Finset α) {ι' ι'' : Finset ι} diff --git a/Mathlib/Combinatorics/Quiver/Arborescence.lean b/Mathlib/Combinatorics/Quiver/Arborescence.lean index f535487f7fad2..44f2fe930821c 100644 --- a/Mathlib/Combinatorics/Quiver/Arborescence.lean +++ b/Mathlib/Combinatorics/Quiver/Arborescence.lean @@ -62,27 +62,32 @@ noncomputable def arborescenceMk {V : Type u} [Quiver V] (r : V) (height : V → uniquePath b := ⟨Classical.inhabited_of_nonempty (by rcases show ∃ n, height b < n from ⟨_, Nat.lt.base _⟩ with ⟨n, hn⟩ - induction' n with n ih generalizing b - · exact False.elim (Nat.not_lt_zero _ hn) + induction n generalizing b with + | zero => exact False.elim (Nat.not_lt_zero _ hn) + | succ n ih => rcases root_or_arrow b with (⟨⟨⟩⟩ | ⟨a, ⟨e⟩⟩) · exact ⟨Path.nil⟩ · rcases ih a (lt_of_lt_of_le (height_lt e) (Nat.lt_succ_iff.mp hn)) with ⟨p⟩ exact ⟨p.cons e⟩), by have height_le : ∀ {a b}, Path a b → height a ≤ height b := by intro a b p - induction' p with b c _ e ih - · rfl - · exact le_of_lt (lt_of_le_of_lt ih (height_lt e)) + induction p with + | nil => rfl + | cons _ e ih => exact le_of_lt (lt_of_le_of_lt ih (height_lt e)) suffices ∀ p q : Path r b, p = q by intro p apply this intro p q - induction' p with a c p e ih <;> cases' q with b _ q f - · rfl - · exact False.elim (lt_irrefl _ (lt_of_le_of_lt (height_le q) (height_lt f))) - · exact False.elim (lt_irrefl _ (lt_of_le_of_lt (height_le p) (height_lt e))) - · rcases unique_arrow e f with ⟨⟨⟩, ⟨⟩⟩ - rw [ih]⟩ + induction p with + | nil => + rcases q with _ | ⟨q, f⟩ + · rfl + · exact False.elim (lt_irrefl _ (lt_of_le_of_lt (height_le q) (height_lt f))) + | cons p e ih => + rcases q with _ | ⟨q, f⟩ + · exact False.elim (lt_irrefl _ (lt_of_le_of_lt (height_le p) (height_lt e))) + · rcases unique_arrow e f with ⟨⟨⟩, ⟨⟩⟩ + rw [ih]⟩ /-- `RootedConnected r` means that there is a path from `r` to any other vertex. -/ class RootedConnected {V : Type u} [Quiver V] (r : V) : Prop where diff --git a/Mathlib/Combinatorics/Quiver/Basic.lean b/Mathlib/Combinatorics/Quiver/Basic.lean index 32fe7fd00a050..0000d08b93bfe 100644 --- a/Mathlib/Combinatorics/Quiver/Basic.lean +++ b/Mathlib/Combinatorics/Quiver/Basic.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: David Wärn, Scott Morrison -/ import Mathlib.Data.Opposite -import Mathlib.Tactic.Cases /-! # Quivers @@ -72,8 +71,8 @@ theorem ext {V : Type u} [Quiver.{v₁} V] {W : Type u₂} [Quiver.{v₂} W] {F (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 - cases' F with F_obj _ - cases' G with G_obj _ + obtain ⟨F_obj, _⟩ := F + obtain ⟨G_obj, _⟩ := G obtain rfl : F_obj = G_obj := by ext X apply h_obj diff --git a/Mathlib/Combinatorics/Quiver/Path.lean b/Mathlib/Combinatorics/Quiver/Path.lean index a57df538d7c60..5466770a184d0 100644 --- a/Mathlib/Combinatorics/Quiver/Path.lean +++ b/Mathlib/Combinatorics/Quiver/Path.lean @@ -104,15 +104,19 @@ theorem length_comp (p : Path a b) : ∀ {c} (q : Path b c), (p.comp q).length = theorem comp_inj {p₁ p₂ : Path a b} {q₁ q₂ : Path b c} (hq : q₁.length = q₂.length) : p₁.comp q₁ = p₂.comp q₂ ↔ p₁ = p₂ ∧ q₁ = q₂ := by refine ⟨fun h => ?_, by rintro ⟨rfl, rfl⟩; rfl⟩ - induction' q₁ with d₁ e₁ q₁ f₁ ih <;> obtain _ | ⟨q₂, f₂⟩ := q₂ - · exact ⟨h, rfl⟩ - · cases hq - · cases hq - · simp only [comp_cons, cons.injEq] at h - obtain rfl := h.1 - obtain ⟨rfl, rfl⟩ := ih (Nat.succ.inj hq) h.2.1.eq - rw [h.2.2.eq] - exact ⟨rfl, rfl⟩ + induction q₁ with + | nil => + rcases q₂ with _ | ⟨q₂, f₂⟩ + · exact ⟨h, rfl⟩ + · cases hq + | cons q₁ f₁ ih => + rcases q₂ with _ | ⟨q₂, f₂⟩ + · cases hq + · simp only [comp_cons, cons.injEq] at h + obtain rfl := h.1 + obtain ⟨rfl, rfl⟩ := ih (Nat.succ.inj hq) h.2.1.eq + rw [h.2.2.eq] + exact ⟨rfl, rfl⟩ theorem comp_inj' {p₁ p₂ : Path a b} {q₁ q₂ : Path b c} (h : p₁.length = p₂.length) : p₁.comp q₁ = p₂.comp q₂ ↔ p₁ = p₂ ∧ q₁ = q₂ := diff --git a/Mathlib/Combinatorics/Quiver/SingleObj.lean b/Mathlib/Combinatorics/Quiver/SingleObj.lean index 21fb2f1c43094..0f8ecb66a9de8 100644 --- a/Mathlib/Combinatorics/Quiver/SingleObj.lean +++ b/Mathlib/Combinatorics/Quiver/SingleObj.lean @@ -111,14 +111,14 @@ def listToPath : List α → Path (star α) (star α) theorem listToPath_pathToList {x : SingleObj α} (p : Path (star α) x) : listToPath (pathToList p) = p.cast rfl ext := by - induction' p with y z p a ih - · rfl - · dsimp at *; rw [ih] + induction p with + | nil => rfl + | cons _ _ ih => dsimp at *; rw [ih] theorem pathToList_listToPath (l : List α) : pathToList (listToPath l) = l := by - induction' l with a l ih - · rfl - · change a :: pathToList (listToPath l) = a :: l; rw [ih] + induction l with + | nil => rfl + | cons a l ih => change a :: pathToList (listToPath l) = a :: l; rw [ih] /-- Paths in `SingleObj α` quiver correspond to lists of elements of type `α`. -/ def pathEquivList : Path (star α) (star α) ≃ List α := diff --git a/Mathlib/Combinatorics/Quiver/Symmetric.lean b/Mathlib/Combinatorics/Quiver/Symmetric.lean index 0cbc2f0156725..cf87c843a83f7 100644 --- a/Mathlib/Combinatorics/Quiver/Symmetric.lean +++ b/Mathlib/Combinatorics/Quiver/Symmetric.lean @@ -45,7 +45,7 @@ class HasReverse where def reverse {V} [Quiver.{v + 1} V] [HasReverse V] {a b : V} : (a ⟶ b) → (b ⟶ a) := HasReverse.reverse' -/-- A quiver `HasInvolutiveReverse` if reversing twice is the identity. -/ +/-- A quiver `HasInvolutiveReverse` if reversing twice is the identity. -/ class HasInvolutiveReverse extends HasReverse V where /-- `reverse` is involutive -/ inv' : ∀ {a b : V} (f : a ⟶ b), reverse (reverse f) = f @@ -132,16 +132,17 @@ theorem Path.reverse_toPath [HasReverse V] {a b : V} (f : a ⟶ b) : @[simp] theorem Path.reverse_comp [HasReverse V] {a b c : V} (p : Path a b) (q : Path b c) : (p.comp q).reverse = q.reverse.comp p.reverse := by - induction' q with _ _ _ _ h - · simp - · simp [h] + induction q with + | nil => simp + | cons _ _ h => simp [h] @[simp] theorem Path.reverse_reverse [h : HasInvolutiveReverse V] {a b : V} (p : Path a b) : p.reverse.reverse = p := by - induction' p with _ _ _ _ h - · simp - · rw [Path.reverse, Path.reverse_comp, h, Path.reverse_toPath, Quiver.reverse_reverse] + induction p with + | nil => simp + | cons _ _ h => + rw [Path.reverse, Path.reverse_comp, h, Path.reverse_toPath, Quiver.reverse_reverse] rfl end Paths diff --git a/Mathlib/Combinatorics/Schnirelmann.lean b/Mathlib/Combinatorics/Schnirelmann.lean index 016b6c772835e..d56f44bd816ff 100644 --- a/Mathlib/Combinatorics/Schnirelmann.lean +++ b/Mathlib/Combinatorics/Schnirelmann.lean @@ -68,7 +68,7 @@ lemma schnirelmannDensity_mul_le_card_filter {n : ℕ} : schnirelmannDensity A * n ≤ ((Ioc 0 n).filter (· ∈ A)).card := by rcases eq_or_ne n 0 with rfl | hn · simp - exact (le_div_iff (by positivity)).1 (schnirelmannDensity_le_div hn) + exact (le_div_iff₀ (by positivity)).1 (schnirelmannDensity_le_div hn) /-- To show the Schnirelmann density is upper bounded by `x`, it suffices to show @@ -243,9 +243,9 @@ lemma schnirelmannDensity_setOf_mod_eq_one {m : ℕ} (hm : m ≠ 1) : simp only [Nat.mul_add_mod', Nat.mod_eq_of_lt hm, add_pos_iff, or_true, and_true, true_and, ← Nat.le_sub_iff_add_le hn, zero_lt_one] exact Nat.mul_le_of_le_div _ _ _ hy' - rw [le_div_iff (Nat.cast_pos.2 hn), mul_comm, ← div_eq_mul_inv] + rw [le_div_iff₀ (Nat.cast_pos.2 hn), mul_comm, ← div_eq_mul_inv] apply (Nat.cast_le.2 (card_le_card this)).trans' - rw [card_image_of_injective, Nat.card_Icc, Nat.sub_zero, div_le_iff (Nat.cast_pos.2 hm'), + rw [card_image_of_injective, Nat.card_Icc, Nat.sub_zero, div_le_iff₀ (Nat.cast_pos.2 hm'), ← Nat.cast_mul, Nat.cast_le, add_one_mul (α := ℕ)] · have := @Nat.lt_div_mul_add n.pred m hm' rwa [← Nat.succ_le, Nat.succ_pred hn.ne'] at this @@ -259,7 +259,7 @@ lemma schnirelmannDensity_setOf_modeq_one {m : ℕ} : rw [← schnirelmannDensity_setOf_mod_eq_one hm] apply schnirelmannDensity_congr ext n - simp only [Set.mem_setOf_eq, Nat.ModEq, Nat.one_mod_of_ne_one hm] + simp only [Set.mem_setOf_eq, Nat.ModEq, Nat.one_mod_eq_one.mpr hm] lemma schnirelmannDensity_setOf_Odd : schnirelmannDensity (setOf Odd) = 2⁻¹ := by have h : setOf Odd = {n | n % 2 = 1} := Set.ext fun _ => Nat.odd_iff diff --git a/Mathlib/Combinatorics/SetFamily/AhlswedeZhang.lean b/Mathlib/Combinatorics/SetFamily/AhlswedeZhang.lean index e27ea7862f429..ea08e4e2baeef 100644 --- a/Mathlib/Combinatorics/SetFamily/AhlswedeZhang.lean +++ b/Mathlib/Combinatorics/SetFamily/AhlswedeZhang.lean @@ -141,7 +141,7 @@ lemma map_truncatedSup [@DecidableRel β (· ≤ ·)] (e : α ≃o β) (s : Fins have : e a ∈ lowerClosure (s.map e.toEquiv.toEmbedding : Set β) ↔ a ∈ lowerClosure s := by simp simp_rw [truncatedSup, apply_dite e, map_finset_sup', map_top, this] congr with h - simp only [filter_map, Function.comp, Equiv.coe_toEmbedding, RelIso.coe_fn_toEquiv, + simp only [filter_map, Function.comp_def, Equiv.coe_toEmbedding, RelIso.coe_fn_toEquiv, OrderIso.le_iff_le, id] rw [sup'_map] -- TODO: Why can't `simp` use `Finset.sup'_map`? @@ -216,7 +216,7 @@ lemma map_truncatedInf (e : α ≃o β) (s : Finset α) (a : α) : have : e a ∈ upperClosure (s.map e.toEquiv.toEmbedding) ↔ a ∈ upperClosure s := by simp simp_rw [truncatedInf, apply_dite e, map_finset_inf', map_bot, this] congr with h - simp only [filter_map, Function.comp, Equiv.coe_toEmbedding, RelIso.coe_fn_toEquiv, + simp only [filter_map, Function.comp_def, Equiv.coe_toEmbedding, RelIso.coe_fn_toEquiv, OrderIso.le_iff_le, id, inf'_map] lemma truncatedInf_of_isAntichain (hs : IsAntichain (· ≤ ·) (s : Set α)) (ha : a ∈ s) : diff --git a/Mathlib/Combinatorics/SetFamily/Compression/UV.lean b/Mathlib/Combinatorics/SetFamily/Compression/UV.lean index 5ebbd630b7265..8bfa4e268eb8a 100644 --- a/Mathlib/Combinatorics/SetFamily/Compression/UV.lean +++ b/Mathlib/Combinatorics/SetFamily/Compression/UV.lean @@ -327,7 +327,7 @@ theorem shadow_compression_subset_compression_shadow (u v : Finset α) exact ⟨Or.inl hat, hav⟩ · rw [← erase_sdiff_comm, sup_eq_union, erase_union_distrib, erase_eq_of_not_mem hau] intro s hs𝒜' hs𝒜 - -- This is gonna be useful a couple of times so let's name it. + -- This is going to be useful a couple of times so let's name it. have m : ∀ y, y ∉ s → insert y s ∉ 𝒜 := fun y h a => hs𝒜 (mem_shadow_iff_insert_mem.2 ⟨y, h, a⟩) obtain ⟨x, _, _⟩ := mem_shadow_iff_insert_mem.1 hs𝒜' have hus : u ⊆ insert x s := le_of_mem_compression_of_not_mem ‹_ ∈ 𝒜'› (m _ ‹x ∉ s›) diff --git a/Mathlib/Combinatorics/SetFamily/KruskalKatona.lean b/Mathlib/Combinatorics/SetFamily/KruskalKatona.lean new file mode 100644 index 0000000000000..c038ae31aa350 --- /dev/null +++ b/Mathlib/Combinatorics/SetFamily/KruskalKatona.lean @@ -0,0 +1,294 @@ +/- +Copyright (c) 2020 Bhavik Mehta. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bhavik Mehta, Yaël Dillies +-/ +import Mathlib.Combinatorics.Colex +import Mathlib.Combinatorics.SetFamily.Compression.UV + +/-! +# Kruskal-Katona theorem + +This file proves the Kruskal-Katona theorem. This is a sharp statement about how many sets of size +`k - 1` are covered by a family of sets of size `k`, given only its size. + +## Main declarations + +The key results proved here are: +* `Finset.kruskal_katona`: The basic Kruskal-Katona theorem. Given a set family `𝒜` consisting of + `r`-sets, and `𝒞` an initial segment of the colex order of the same size, the shadow of `𝒞` is + smaller than the shadow of `𝒜`. In particular, this shows that the minimum shadow size is + achieved by initial segments of colex. +* `Finset.iterated_kruskal_katona`: An iterated form of the Kruskal-Katona theorem, stating that the + minimum iterated shadow size is given by initial segments of colex. + +## TODO + +* Define the `k`-cascade representation of a natural and prove the corresponding version of + Kruskal-Katona. +* Abstract away from `Fin n` so that it also applies to `ℕ`. Probably `LocallyFiniteOrderBot` + will help here. +* Characterise the equality case. + +## References + +* http://b-mehta.github.io/maths-notes/iii/mich/combinatorics.pdf +* http://discretemath.imp.fu-berlin.de/DMII-2015-16/kruskal.pdf + +## Tags + +kruskal-katona, kruskal, katona, shadow, initial segments, intersecting +-/ + +-- TODO: There's currently a diamond. See https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/DecidableEq.20diamond.20on.20Fin +-- import Mathlib.Order.Fin.Basic +-- example (n : ℕ) : instDecidableEqFin n = instDecidableEq_mathlib := rfl +attribute [-instance] instDecidableEqFin + +open Nat +open scoped FinsetFamily + +namespace Finset +namespace Colex +variable {α : Type*} [LinearOrder α] {𝒜 𝒜₁ 𝒜₂ : Finset (Finset α)} {s t : Finset α} {r : ℕ} + +/-- This is important for iterating Kruskal-Katona: the shadow of an initial segment is also an +initial segment. -/ +lemma shadow_initSeg [Fintype α] (hs : s.Nonempty) : + ∂ (initSeg s) = initSeg (erase s <| min' s hs) := by + -- This is a pretty painful proof, with lots of cases. + ext t + simp only [mem_shadow_iff_insert_mem, mem_initSeg, exists_prop] + constructor + -- First show that if t ∪ a ≤ s, then t ≤ s - min s + · rintro ⟨a, ha, hst, hts⟩ + constructor + · rw [card_erase_of_mem (min'_mem _ _), hst, card_insert_of_not_mem ha, add_tsub_cancel_right] + · simpa [ha] using erase_le_erase_min' hts hst.ge (mem_insert_self _ _) + -- Now show that if t ≤ s - min s, there is j such that t ∪ j ≤ s + -- We choose j as the smallest thing not in t + simp_rw [le_iff_eq_or_lt, lt_iff_exists_filter_lt, mem_sdiff, filter_inj, and_assoc] + simp only [toColex_inj, ofColex_toColex, ne_eq, and_imp] + rintro cards' (rfl | ⟨k, hks, hkt, z⟩) + -- If t = s - min s, then use j = min s so t ∪ j = s + · refine ⟨min' s hs, not_mem_erase _ _, ?_⟩ + rw [insert_erase (min'_mem _ _)] + exact ⟨rfl, Or.inl rfl⟩ + set j := min' tᶜ ⟨k, mem_compl.2 hkt⟩ + -- Assume first t < s - min s, and take k as the colex witness for this + have hjk : j ≤ k := min'_le _ _ (mem_compl.2 ‹k ∉ t›) + have : j ∉ t := mem_compl.1 (min'_mem _ _) + have hcard : card s = card (insert j t) := by + rw [card_insert_of_not_mem ‹j ∉ t›, ← ‹_ = card t›, card_erase_add_one (min'_mem _ _)] + refine ⟨j, ‹_›, hcard, ?_⟩ + -- Cases on j < k or j = k + obtain hjk | r₁ := hjk.lt_or_eq + -- if j < k, k is our colex witness for t ∪ {j} < s + · refine Or.inr ⟨k, mem_of_mem_erase ‹_›, fun hk ↦ hkt <| mem_of_mem_insert_of_ne hk hjk.ne', + fun x hx ↦ ?_⟩ + simpa only [mem_insert, z hx, (hjk.trans hx).ne', mem_erase, Ne, false_or_iff, + and_iff_right_iff_imp] using fun _ ↦ ((min'_le _ _ <| mem_of_mem_erase hks).trans_lt hx).ne' + -- if j = k, all of range k is in t so by sizes t ∪ {j} = s + refine Or.inl (eq_of_subset_of_card_le (fun a ha ↦ ?_) hcard.ge).symm + rcases lt_trichotomy k a with (lt | rfl | gt) + · apply mem_insert_of_mem + rw [z lt] + refine mem_erase_of_ne_of_mem (lt_of_le_of_lt ?_ lt).ne' ha + apply min'_le _ _ (mem_of_mem_erase ‹_›) + · rw [r₁]; apply mem_insert_self + · apply mem_insert_of_mem + rw [← r₁] at gt + by_contra + apply (min'_le tᶜ _ _).not_lt gt + rwa [mem_compl] + +/-- The shadow of an initial segment is also an initial segment. -/ +protected lemma IsInitSeg.shadow [Finite α] (h₁ : IsInitSeg 𝒜 r) : IsInitSeg (∂ 𝒜) (r - 1) := by + cases nonempty_fintype α + obtain rfl | hr := Nat.eq_zero_or_pos r + · have : 𝒜 ⊆ {∅} := fun s hs ↦ by rw [mem_singleton, ← Finset.card_eq_zero]; exact h₁.1 hs + have := shadow_monotone this + simp only [subset_empty, le_eq_subset, shadow_singleton_empty] at this + simp [this] + obtain rfl | h𝒜 := 𝒜.eq_empty_or_nonempty + · simp + obtain ⟨s, rfl, rfl⟩ := h₁.exists_initSeg h𝒜 + rw [shadow_initSeg (card_pos.1 hr), ← card_erase_of_mem (min'_mem _ _)] + exact isInitSeg_initSeg + +end Colex + +open Finset Colex Nat UV +open scoped BigOperators FinsetFamily + +variable {α : Type*} [LinearOrder α] {s U V : Finset α} {n : ℕ} + +namespace UV + +/-- Applying the compression makes the set smaller in colex. This is intuitive since a portion of +the set is being "shifted down" as `max U < max V`. -/ +lemma toColex_compress_lt_toColex {hU : U.Nonempty} {hV : V.Nonempty} (h : max' U hU < max' V hV) + (hA : compress U V s ≠ s) : toColex (compress U V s) < toColex s := by + rw [compress, ite_ne_right_iff] at hA + rw [compress, if_pos hA.1, lt_iff_exists_filter_lt] + simp_rw [mem_sdiff (s := s), filter_inj, and_assoc] + refine ⟨_, hA.1.2 <| max'_mem _ hV, not_mem_sdiff_of_mem_right <| max'_mem _ _, fun a ha ↦ ?_⟩ + have : a ∉ V := fun H ↦ ha.not_le (le_max' _ _ H) + have : a ∉ U := fun H ↦ ha.not_lt ((le_max' _ _ H).trans_lt h) + simp [‹a ∉ U›, ‹a ∉ V›] + +/-- These are the compressions which we will apply to decrease the "measure" of a family of sets.-/ +private def UsefulCompression (U V : Finset α) : Prop := + Disjoint U V ∧ U.card = V.card ∧ ∃ (HU : U.Nonempty) (HV : V.Nonempty), max' U HU < max' V HV + +private instance UsefulCompression.instDecidableRel : @DecidableRel (Finset α) UsefulCompression := + fun _U _V ↦ And.decidable + +/-- Applying a good compression will decrease measure, keep cardinality, keep sizes and decrease +shadow. In particular, 'good' means it's useful, and every smaller compression won't make a +difference. -/ +private lemma compression_improved (𝒜 : Finset (Finset α)) (h₁ : UsefulCompression U V) + (h₂ : ∀ ⦃U₁ V₁⦄, UsefulCompression U₁ V₁ → U₁.card < U.card → IsCompressed U₁ V₁ 𝒜) : + (∂ (𝓒 U V 𝒜)).card ≤ (∂ 𝒜).card := by + obtain ⟨UVd, same_size, hU, hV, max_lt⟩ := h₁ + refine card_shadow_compression_le _ _ fun x Hx ↦ ⟨min' V hV, min'_mem _ _, ?_⟩ + obtain hU' | hU' := eq_or_lt_of_le (succ_le_iff.2 hU.card_pos) + · rw [← hU'] at same_size + have : erase U x = ∅ := by rw [← Finset.card_eq_zero, card_erase_of_mem Hx, ← hU'] + have : erase V (min' V hV) = ∅ := by + rw [← Finset.card_eq_zero, card_erase_of_mem (min'_mem _ _), ← same_size] + rw [‹erase U x = ∅›, ‹erase V (min' V hV) = ∅›] + exact isCompressed_self _ _ + refine h₂ ⟨UVd.mono (erase_subset ..) (erase_subset ..), ?_, ?_, ?_, ?_⟩ (card_erase_lt_of_mem Hx) + · rw [card_erase_of_mem (min'_mem _ _), card_erase_of_mem Hx, same_size] + · rwa [← card_pos, card_erase_of_mem Hx, tsub_pos_iff_lt] + · rwa [← Finset.card_pos, card_erase_of_mem (min'_mem _ _), ← same_size, tsub_pos_iff_lt] + · exact (Finset.max'_subset _ <| erase_subset _ _).trans_lt (max_lt.trans_le <| le_max' _ _ <| + mem_erase.2 ⟨(min'_lt_max'_of_card _ (by rwa [← same_size])).ne', max'_mem _ _⟩) + +/-- If we're compressed by all useful compressions, then we're an initial segment. This is the other +key Kruskal-Katona part. -/ +lemma isInitSeg_of_compressed {ℬ : Finset (Finset α)} {r : ℕ} (h₁ : (ℬ : Set (Finset α)).Sized r) + (h₂ : ∀ U V, UsefulCompression U V → IsCompressed U V ℬ) : IsInitSeg ℬ r := by + refine ⟨h₁, ?_⟩ + rintro A B hA ⟨hBA, sizeA⟩ + by_contra hB + have hAB : A ≠ B := ne_of_mem_of_not_mem hA hB + have hAB' : A.card = B.card := (h₁ hA).trans sizeA.symm + have hU : (A \ B).Nonempty := sdiff_nonempty.2 fun h ↦ hAB <| eq_of_subset_of_card_le h hAB'.ge + have hV : (B \ A).Nonempty := + sdiff_nonempty.2 fun h ↦ hAB.symm <| eq_of_subset_of_card_le h hAB'.le + have disj : Disjoint (B \ A) (A \ B) := disjoint_sdiff.mono_left sdiff_subset + have smaller : max' _ hV < max' _ hU := by + obtain hlt | heq | hgt := lt_trichotomy (max' _ hU) (max' _ hV) + · rw [← compress_sdiff_sdiff A B] at hAB hBA + cases hBA.not_lt <| toColex_compress_lt_toColex hlt hAB + · exact (disjoint_right.1 disj (max'_mem _ hU) <| heq.symm ▸ max'_mem _ _).elim + · assumption + refine hB ?_ + rw [← (h₂ _ _ ⟨disj, card_sdiff_comm hAB'.symm, hV, hU, smaller⟩).eq] + exact mem_compression.2 (Or.inr ⟨hB, A, hA, compress_sdiff_sdiff _ _⟩) + +attribute [-instance] Fintype.decidableForallFintype + +/-- This measures roughly how compressed the family is. + +Note that this does depend on the order of the ground set, unlike the Kruskal-Katona theorem itself +(although `kruskal_katona` currently is stated in an order-dependent manner). -/ +private def familyMeasure (𝒜 : Finset (Finset (Fin n))) : ℕ := ∑ A in 𝒜, ∑ a in A, 2 ^ (a : ℕ) + +/-- Applying a compression strictly decreases the measure. This helps show that "compress until we +can't any more" is a terminating process. -/ +private lemma familyMeasure_compression_lt_familyMeasure {U V : Finset (Fin n)} {hU : U.Nonempty} + {hV : V.Nonempty} (h : max' U hU < max' V hV) {𝒜 : Finset (Finset (Fin n))} (a : 𝓒 U V 𝒜 ≠ 𝒜) : + familyMeasure (𝓒 U V 𝒜) < familyMeasure 𝒜 := by + rw [compression] at a ⊢ + have q : ∀ Q ∈ 𝒜.filter fun A ↦ compress U V A ∉ 𝒜, compress U V Q ≠ Q := by + simp_rw [mem_filter] + intro Q hQ h + rw [h] at hQ + exact hQ.2 hQ.1 + have uA : (𝒜.filter fun A => compress U V A ∈ 𝒜) ∪ 𝒜.filter (fun A ↦ compress U V A ∉ 𝒜) = 𝒜 := + filter_union_filter_neg_eq _ _ + have ne₂ : (𝒜.filter fun A ↦ compress U V A ∉ 𝒜).Nonempty := by + refine nonempty_iff_ne_empty.2 fun z ↦ a ?_ + rw [filter_image, z, image_empty, union_empty] + rwa [z, union_empty] at uA + rw [familyMeasure, familyMeasure, sum_union compress_disjoint] + conv_rhs => rw [← uA] + rw [sum_union (disjoint_filter_filter_neg _ _ _), add_lt_add_iff_left, filter_image, + sum_image compress_injOn] + refine sum_lt_sum_of_nonempty ne₂ fun A hA ↦ ?_ + simp_rw [← sum_image Fin.val_injective.injOn] + rw [geomSum_lt_geomSum_iff_toColex_lt_toColex le_rfl, + toColex_image_lt_toColex_image Fin.val_strictMono] + exact toColex_compress_lt_toColex h <| q _ hA + +/-- The main Kruskal-Katona helper: use induction with our measure to keep compressing until +we can't any more, which gives a set family which is fully compressed and has the nice properties we +want. -/ +private lemma kruskal_katona_helper {r : ℕ} (𝒜 : Finset (Finset (Fin n))) + (h : (𝒜 : Set (Finset (Fin n))).Sized r) : + ∃ ℬ : Finset (Finset (Fin n)), (∂ ℬ).card ≤ (∂ 𝒜).card ∧ 𝒜.card = ℬ.card ∧ + (ℬ : Set (Finset (Fin n))).Sized r ∧ ∀ U V, UsefulCompression U V → IsCompressed U V ℬ := by + classical + -- Are there any compressions we can make now? + set usable : Finset (Finset (Fin n) × Finset (Fin n)) := + univ.filter fun t ↦ UsefulCompression t.1 t.2 ∧ ¬ IsCompressed t.1 t.2 𝒜 + obtain husable | husable := usable.eq_empty_or_nonempty + -- No. Then where we are is the required set family. + · refine ⟨𝒜, le_rfl, rfl, h, fun U V hUV ↦ ?_⟩ + rw [eq_empty_iff_forall_not_mem] at husable + by_contra h + exact husable ⟨U, V⟩ <| mem_filter.2 ⟨mem_univ _, hUV, h⟩ + -- Yes. Then apply the smallest compression, then keep going + obtain ⟨⟨U, V⟩, hUV, t⟩ := exists_min_image usable (fun t ↦ t.1.card) husable + rw [mem_filter] at hUV + have h₂ : ∀ U₁ V₁, UsefulCompression U₁ V₁ → U₁.card < U.card → IsCompressed U₁ V₁ 𝒜 := by + rintro U₁ V₁ huseful hUcard + by_contra h + exact hUcard.not_le <| t ⟨U₁, V₁⟩ <| mem_filter.2 ⟨mem_univ _, huseful, h⟩ + have p1 : (∂ (𝓒 U V 𝒜)).card ≤ (∂ 𝒜).card := compression_improved _ hUV.2.1 h₂ + obtain ⟨-, hUV', hu, hv, hmax⟩ := hUV.2.1 + have := familyMeasure_compression_lt_familyMeasure hmax hUV.2.2 + obtain ⟨t, q1, q2, q3, q4⟩ := UV.kruskal_katona_helper (𝓒 U V 𝒜) (h.uvCompression hUV') + exact ⟨t, q1.trans p1, (card_compression _ _ _).symm.trans q2, q3, q4⟩ +termination_by familyMeasure 𝒜 + +end UV + +-- Finally we can prove Kruskal-Katona. +section KK +variable {r k i : ℕ} {𝒜 𝒞 : Finset <| Finset <| Fin n} + +/-- The **Kruskal-Katona theorem**. + +Given a set family `𝒜` consisting of `r`-sets, and `𝒞` an initial segment of the colex order of the +same size, the shadow of `𝒞` is smaller than the shadow of `𝒜`. In particular, this gives that the +minimum shadow size is achieved by initial segments of colex. -/ +theorem kruskal_katona (h𝒜r : (𝒜 : Set (Finset (Fin n))).Sized r) (h𝒞𝒜 : 𝒞.card ≤ 𝒜.card) + (h𝒞 : IsInitSeg 𝒞 r) : (∂ 𝒞).card ≤ (∂ 𝒜).card := by + -- WLOG `|𝒜| = |𝒞|` + obtain ⟨𝒜', h𝒜, h𝒜𝒞⟩ := exists_subset_card_eq h𝒞𝒜 + -- By `kruskal_katona_helper`, we find a fully compressed family `ℬ` of the same size as `𝒜` + -- whose shadow is no bigger. + obtain ⟨ℬ, hℬ𝒜, h𝒜ℬ, hℬr, hℬ⟩ := UV.kruskal_katona_helper 𝒜' (h𝒜r.mono (by gcongr)) + -- This means that `ℬ` is an initial segment of the same size as `𝒞`. Hence they are equal and + -- we are done. + suffices ℬ = 𝒞 by subst 𝒞; exact hℬ𝒜.trans (by gcongr) + have hcard : card ℬ = card 𝒞 := h𝒜ℬ.symm.trans h𝒜𝒞 + obtain h𝒞ℬ | hℬ𝒞 := h𝒞.total (UV.isInitSeg_of_compressed hℬr hℬ) + · exact (eq_of_subset_of_card_le h𝒞ℬ hcard.le).symm + · exact eq_of_subset_of_card_le hℬ𝒞 hcard.ge + +/-- An iterated form of the Kruskal-Katona theorem. In particular, the minimum possible iterated +shadow size is attained by initial segments. -/ +theorem iterated_kk (h₁ : (𝒜 : Set (Finset (Fin n))).Sized r) (h₂ : 𝒞.card ≤ 𝒜.card) + (h₃ : IsInitSeg 𝒞 r) : (∂^[k] 𝒞).card ≤ (∂^[k] 𝒜).card := by + induction' k with _k ih generalizing r 𝒜 𝒞 + · simpa + · refine ih h₁.shadow (kruskal_katona h₁ h₂ h₃) ?_ + convert h₃.shadow + +end KK +end Finset diff --git a/Mathlib/Combinatorics/SetFamily/LYM.lean b/Mathlib/Combinatorics/SetFamily/LYM.lean index b4677cec67585..6b5887d58e1ee 100644 --- a/Mathlib/Combinatorics/SetFamily/LYM.lean +++ b/Mathlib/Combinatorics/SetFamily/LYM.lean @@ -198,7 +198,7 @@ theorem sum_card_slice_div_choose_le_one [Fintype α] classical rw [← sum_flip] refine (le_card_falling_div_choose le_rfl h𝒜).trans ?_ - rw [div_le_iff] <;> norm_cast + rw [div_le_iff₀] <;> norm_cast · simpa only [Nat.sub_self, one_mul, Nat.choose_zero_right, falling] using Set.Sized.card_le (sized_falling 0 𝒜) · rw [tsub_self, choose_zero_right] diff --git a/Mathlib/Combinatorics/SetFamily/Shadow.lean b/Mathlib/Combinatorics/SetFamily/Shadow.lean index 4e2ec1fbdfd94..bc4f6f690c062 100644 --- a/Mathlib/Combinatorics/SetFamily/Shadow.lean +++ b/Mathlib/Combinatorics/SetFamily/Shadow.lean @@ -50,7 +50,7 @@ namespace Finset section Shadow -variable [DecidableEq α] {𝒜 : Finset (Finset α)} {s t : Finset α} {a : α} {k r : ℕ} +variable [DecidableEq α] {𝒜 ℬ : Finset (Finset α)} {s t : Finset α} {a : α} {k r : ℕ} /-- The shadow of a set family `𝒜` is all sets we can get by removing one element from any set in `𝒜`, and the (`k` times) iterated shadow (`shadow^[k]`) is all sets we can get by removing `k` @@ -81,6 +81,8 @@ theorem shadow_singleton_empty : ∂ ({∅} : Finset (Finset α)) = ∅ := theorem shadow_monotone : Monotone (shadow : Finset (Finset α) → Finset (Finset α)) := fun _ _ => sup_mono +@[gcongr] lemma shadow_mono (h𝒜ℬ : 𝒜 ⊆ ℬ) : ∂ 𝒜 ⊆ ∂ ℬ := shadow_monotone h𝒜ℬ + /-- `t` is in the shadow of `𝒜` iff there is a `s ∈ 𝒜` from which we can remove one element to get `t`. -/ lemma mem_shadow_iff : t ∈ ∂ 𝒜 ↔ ∃ s ∈ 𝒜, ∃ a ∈ s, erase s a = t := by diff --git a/Mathlib/Combinatorics/SimpleGraph/Acyclic.lean b/Mathlib/Combinatorics/SimpleGraph/Acyclic.lean index 6b8117d6925da..2cb9bcfec2287 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Acyclic.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Acyclic.lean @@ -170,11 +170,12 @@ lemma IsTree.card_edgeFinset [Fintype V] [Fintype G.edgeSet] (hG : G.IsTree) : · exact (congrArg (·.fst) h) · have h1 : ((f a).firstDart <| not_nil_of_ne (by simpa using ha)).snd = b := congrArg (·.snd) h - have h3 := congrArg length (hf' _ (((f _).tail _).copy h1 rfl) ?_) - · rw [length_copy, ← add_left_inj 1, length_tail_add_one] at h3 + have h3 := congrArg length (hf' _ ((f _).tail.copy h1 rfl) ?_) + · rw [length_copy, ← add_left_inj 1, + length_tail_add_one (not_nil_of_ne (by simpa using ha))] at h3 omega · simp only [ne_eq, eq_mp_eq_cast, id_eq, isPath_copy] - exact (hf _).tail _ + exact (hf _).tail (not_nil_of_ne (by simpa using ha)) case surj => simp only [mem_edgeFinset, Finset.mem_compl, Finset.mem_singleton, Sym2.forall, mem_edgeSet] intros x y h @@ -188,7 +189,7 @@ lemma IsTree.card_edgeFinset [Fintype V] [Fintype G.edgeSet] (hG : G.IsTree) : length_cons, length_nil] at h' simp [Nat.le_zero, Nat.one_ne_zero] at h' rw [← hf' _ (.cons h.symm (f x)) ((cons_isPath_iff _ _).2 ⟨hf _, fun hy => ?contra⟩)] - · rfl + · simp only [firstDart_toProd, getVert_cons_succ, getVert_zero, Prod.swap_prod_mk] case contra => suffices (f x).takeUntil y hy = .cons h .nil by rw [← take_spec _ hy] at h' diff --git a/Mathlib/Combinatorics/SimpleGraph/Circulant.lean b/Mathlib/Combinatorics/SimpleGraph/Circulant.lean index 1b44d179c5ede..dabe8553d196a 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Circulant.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Circulant.lean @@ -3,8 +3,8 @@ 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.Combinatorics.SimpleGraph.Hasse -import Mathlib.Data.Set.Pointwise.Basic /-! # Definition of circulant graphs diff --git a/Mathlib/Combinatorics/SimpleGraph/ConcreteColorings.lean b/Mathlib/Combinatorics/SimpleGraph/ConcreteColorings.lean index f82cadc1929e4..90abd52d115c4 100644 --- a/Mathlib/Combinatorics/SimpleGraph/ConcreteColorings.lean +++ b/Mathlib/Combinatorics/SimpleGraph/ConcreteColorings.lean @@ -62,7 +62,7 @@ theorem Coloring.even_length_iff_congr {α} {G : SimpleGraph α} theorem Coloring.odd_length_iff_not_congr {α} {G : SimpleGraph α} (c : G.Coloring Bool) {u v : α} (p : G.Walk u v) : Odd p.length ↔ (¬c u ↔ c v) := by - rw [Nat.odd_iff_not_even, c.even_length_iff_congr p] + rw [← Nat.not_even_iff_odd, c.even_length_iff_congr p] tauto theorem Walk.three_le_chromaticNumber_of_odd_loop {α} {G : SimpleGraph α} {u : α} (p : G.Walk u u) diff --git a/Mathlib/Combinatorics/SimpleGraph/Connectivity/Subgraph.lean b/Mathlib/Combinatorics/SimpleGraph/Connectivity/Subgraph.lean index e73b22eb31d5a..b19fdc540c1bb 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Connectivity/Subgraph.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Connectivity/Subgraph.lean @@ -189,9 +189,9 @@ theorem toSubgraph_adj_getVert {u v} (w : G.Walk u v) {i : ℕ} (hi : i < w.leng | nil => cases hi | cons hxy i' ih => cases i - · simp only [Walk.toSubgraph, Walk.getVert_zero, zero_add, cons_getVert_succ, Subgraph.sup_adj, + · simp only [Walk.toSubgraph, Walk.getVert_zero, zero_add, getVert_cons_succ, Subgraph.sup_adj, subgraphOfAdj_adj, true_or] - · simp only [Walk.toSubgraph, cons_getVert_succ, Subgraph.sup_adj, subgraphOfAdj_adj, Sym2.eq, + · simp only [Walk.toSubgraph, getVert_cons_succ, Subgraph.sup_adj, subgraphOfAdj_adj, Sym2.eq, Sym2.rel_iff', Prod.mk.injEq, Prod.swap_prod_mk] right exact ih (Nat.succ_lt_succ_iff.mp hi) @@ -211,7 +211,7 @@ theorem toSubgraph_adj_iff {u v u' v'} (w : G.Walk u v) : cases hadj with | inl hl => use 0 - simp only [Walk.getVert_zero, zero_add, cons_getVert_succ] + simp only [Walk.getVert_zero, zero_add, getVert_cons_succ] refine ⟨?_, by simp only [length_cons, Nat.zero_lt_succ]⟩ simp only [Sym2.eq, Sym2.rel_iff', Prod.mk.injEq, Prod.swap_prod_mk] cases hl with @@ -220,7 +220,7 @@ theorem toSubgraph_adj_iff {u v u' v'} (w : G.Walk u v) : | inr hr => obtain ⟨i, hi⟩ := (toSubgraph_adj_iff _).mp hr use i + 1 - simp only [cons_getVert_succ] + simp only [getVert_cons_succ] constructor · exact hi.1 · simp only [Walk.length_cons, add_lt_add_iff_right, Nat.add_lt_add_right hi.2 1] diff --git a/Mathlib/Combinatorics/SimpleGraph/Connectivity/WalkCounting.lean b/Mathlib/Combinatorics/SimpleGraph/Connectivity/WalkCounting.lean index e24349799722e..15302f6c68c45 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Connectivity/WalkCounting.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Connectivity/WalkCounting.lean @@ -58,8 +58,6 @@ theorem set_walk_length_succ_eq (u v : V) (n : ℕ) : · rintro ⟨w, huw, pwv, rfl, rfl, rfl⟩ rfl -variable [DecidableEq V] - /-- Walks of length two from `u` to `v` correspond bijectively to common neighbours of `u` and `v`. Note that `u` and `v` may be the same. -/ @[simps] @@ -73,7 +71,7 @@ def walkLengthTwoEquivCommonNeighbors (u v : V) : section LocallyFinite -variable [LocallyFinite G] +variable [DecidableEq V] [LocallyFinite G] /-- The `Finset` of length-`n` walks from `u` to `v`. This is used to give `{p : G.walk u v | p.length = n}` a `Fintype` instance, and it @@ -143,7 +141,7 @@ end LocallyFinite section Finite -variable [Fintype V] [DecidableRel G.Adj] +variable [DecidableEq V] [Fintype V] [DecidableRel G.Adj] theorem reachable_iff_exists_finsetWalkLength_nonempty (u v : V) : G.Reachable u v ↔ ∃ n : Fin (Fintype.card V), (G.finsetWalkLength n u v).Nonempty := by @@ -172,8 +170,33 @@ instance instDecidableMemSupp (c : G.ConnectedComponent) (v : V) : Decidable (v c.recOn (fun w ↦ decidable_of_iff (G.Reachable v w) <| by simp) (fun _ _ _ _ ↦ Subsingleton.elim _ _) -lemma odd_card_iff_odd_components : Odd (Nat.card V) ↔ +variable {G} in +lemma disjiUnion_supp_toFinset_eq_supp_toFinset {G' : SimpleGraph V} (h : G ≤ G') + (c' : ConnectedComponent G') [Fintype c'.supp] + [DecidablePred fun c : G.ConnectedComponent ↦ c.supp ⊆ c'.supp] : + .disjiUnion {c : ConnectedComponent G | c.supp ⊆ c'.supp} (fun c ↦ c.supp.toFinset) + (fun x _ y _ hxy ↦ by simpa using pairwise_disjoint_supp_connectedComponent _ hxy) = + c'.supp.toFinset := + Finset.coe_injective <| by simpa using ConnectedComponent.biUnion_supp_eq_supp h _ + +lemma ConnectedComponent.odd_card_supp_iff_odd_subcomponents {G'} + (h : G ≤ G') (c' : ConnectedComponent G') : + Odd (Nat.card c'.supp) ↔ Odd (Nat.card + ({c : ConnectedComponent G | c.supp ⊆ c'.supp ∧ Odd (Nat.card c.supp) })) := by + classical + -- have := Fintype.ofFinite: + rw [Nat.card_eq_card_toFinset, ← disjiUnion_supp_toFinset_eq_supp_toFinset h] + simp only [Finset.card_disjiUnion, Set.toFinset_card] + rw [Finset.odd_sum_iff_odd_card_odd, Nat.card_eq_fintype_card, Fintype.card_ofFinset] + simp only [Nat.card_eq_fintype_card, Finset.filter_filter] + rfl + +end Finite + +lemma odd_card_iff_odd_components [Finite V] : Odd (Nat.card V) ↔ Odd (Nat.card ({(c : ConnectedComponent G) | Odd (Nat.card c.supp)})) := by + classical + cases nonempty_fintype V rw [Nat.card_eq_fintype_card] simp only [← (set_fintype_card_eq_univ_iff _).mpr G.iUnion_connectedComponentSupp, ConnectedComponent.mem_supp_iff, Fintype.card_subtype_compl, @@ -184,8 +207,6 @@ lemma odd_card_iff_odd_components : Odd (Nat.card V) ↔ rw [Nat.card_eq_fintype_card, Fintype.card_ofFinset] exact (Finset.odd_sum_iff_odd_card_odd (fun x : G.ConnectedComponent ↦ Nat.card x.supp)) -end Finite - end WalkCounting end SimpleGraph diff --git a/Mathlib/Combinatorics/SimpleGraph/DegreeSum.lean b/Mathlib/Combinatorics/SimpleGraph/DegreeSum.lean index 5364ee41b6234..7a78571cb9edc 100644 --- a/Mathlib/Combinatorics/SimpleGraph/DegreeSum.lean +++ b/Mathlib/Combinatorics/SimpleGraph/DegreeSum.lean @@ -122,7 +122,7 @@ theorem even_card_odd_degree_vertices [Fintype V] [DecidableRel G.Adj] : exact ZMod.ne_zero_iff_odd.symm · intro v simp only [true_and_iff, mem_filter, mem_univ, Ne] - rw [ZMod.eq_zero_iff_even, ZMod.eq_one_iff_odd, Nat.odd_iff_not_even, imp_self] + rw [ZMod.eq_zero_iff_even, ZMod.eq_one_iff_odd, ← Nat.not_even_iff_odd, imp_self] trivial theorem odd_card_odd_degree_vertices_ne [Fintype V] [DecidableEq V] [DecidableRel G.Adj] (v : V) diff --git a/Mathlib/Combinatorics/SimpleGraph/Density.lean b/Mathlib/Combinatorics/SimpleGraph/Density.lean index 3da2261efc324..6f388c7ffd277 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Density.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Density.lean @@ -165,7 +165,7 @@ theorem mul_edgeDensity_le_edgeDensity (hs : s₂ ⊆ s₁) (ht : t₂ ⊆ t₁) (ht₂ : t₂.Nonempty) : (s₂.card : ℚ) / s₁.card * (t₂.card / t₁.card) * edgeDensity r s₂ t₂ ≤ edgeDensity r s₁ t₁ := by have hst : (s₂.card : ℚ) * t₂.card ≠ 0 := by simp [hs₂.ne_empty, ht₂.ne_empty] - rw [edgeDensity, edgeDensity, div_mul_div_comm, mul_comm, div_mul_div_cancel _ hst] + rw [edgeDensity, edgeDensity, div_mul_div_comm, mul_comm, div_mul_div_cancel₀ hst] gcongr exact interedges_mono hs ht @@ -214,9 +214,9 @@ theorem abs_edgeDensity_sub_edgeDensity_le_two_mul_sub_sq (hs : s₂ ⊆ s₁) ( have h₁ := hs₂'.mono hs have h₂ := ht₂'.mono ht gcongr - · refine (le_div_iff ?_).2 hs₂ + · refine (le_div_iff₀ ?_).2 hs₂ exact mod_cast h₁.card_pos - · refine (le_div_iff ?_).2 ht₂ + · refine (le_div_iff₀ ?_).2 ht₂ exact mod_cast h₂.card_pos /-- If `s₂ ⊆ s₁`, `t₂ ⊆ t₁` and they take up all but a `δ`-proportion, then the difference in edge diff --git a/Mathlib/Combinatorics/SimpleGraph/Diam.lean b/Mathlib/Combinatorics/SimpleGraph/Diam.lean index 42ae812095c70..08b5cadd73ca5 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Diam.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Diam.lean @@ -190,13 +190,11 @@ lemma diam_top [Nontrivial α] : (⊤ : SimpleGraph α).diam = 1 := by @[simp] lemma diam_eq_zero : G.diam = 0 ↔ G.ediam = ⊤ ∨ Subsingleton α := by - rw [diam, ENat.toNat_eq_zero] - aesop + rw [diam, ENat.toNat_eq_zero, or_comm, ediam_eq_zero_iff_subsingleton] @[simp] lemma diam_eq_one [Nontrivial α] : G.diam = 1 ↔ G = ⊤ := by - rw [diam, ENat.toNat_eq_iff (by decide)] - exact ediam_eq_one + rw [diam, ENat.toNat_eq_iff one_ne_zero, Nat.cast_one, ediam_eq_one] end diam diff --git a/Mathlib/Combinatorics/SimpleGraph/Ends/Defs.lean b/Mathlib/Combinatorics/SimpleGraph/Ends/Defs.lean index 0947929af9f98..e5a841272ed81 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Ends/Defs.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Ends/Defs.lean @@ -255,7 +255,9 @@ def componentComplFunctor : (Finset V)ᵒᵖ ⥤ Type u where obj K := G.ComponentCompl K.unop map f := ComponentCompl.hom (le_of_op_hom f) map_id _ := funext fun C => C.hom_refl - map_comp h h' := funext fun C => C.hom_trans (le_of_op_hom h) (le_of_op_hom h') + map_comp {_ Y Z} h h' := funext fun C => by + convert C.hom_trans (le_of_op_hom h) (le_of_op_hom _) + exact h' /-- The end of a graph, defined as the sections of the functor `component_compl_functor` . -/ protected def «end» := diff --git a/Mathlib/Combinatorics/SimpleGraph/Finite.lean b/Mathlib/Combinatorics/SimpleGraph/Finite.lean index ed7de03fd9d74..278ba02e0df80 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Finite.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Finite.lean @@ -242,7 +242,7 @@ theorem mem_incidenceFinset [DecidableEq V] (e : Sym2 V) : Set.mem_toFinset theorem incidenceFinset_eq_filter [DecidableEq V] [Fintype G.edgeSet] : - G.incidenceFinset v = G.edgeFinset.filter (Membership.mem v) := by + G.incidenceFinset v = G.edgeFinset.filter (v ∈ ·) := by ext e induction e simp [mk'_mem_incidenceSet_iff] @@ -278,7 +278,7 @@ section Finite variable [Fintype V] instance neighborSetFintype [DecidableRel G.Adj] (v : V) : Fintype (G.neighborSet v) := - @Subtype.fintype _ _ + @Subtype.fintype _ (· ∈ G.neighborSet v) (by simp_rw [mem_neighborSet] infer_instance) diff --git a/Mathlib/Combinatorics/SimpleGraph/Hamiltonian.lean b/Mathlib/Combinatorics/SimpleGraph/Hamiltonian.lean index 769c8115eecfa..0cb730278bd98 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Hamiltonian.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Hamiltonian.lean @@ -67,7 +67,7 @@ end /-- A hamiltonian cycle is a cycle that visits every vertex once. -/ structure IsHamiltonianCycle (p : G.Walk a a) extends p.IsCycle : Prop := - isHamiltonian_tail : (p.tail toIsCycle.not_nil).IsHamiltonian + isHamiltonian_tail : p.tail.IsHamiltonian variable {p : G.Walk a a} @@ -84,22 +84,23 @@ lemma IsHamiltonianCycle.map {H : SimpleGraph β} (f : G →g H) (hf : Bijective intro x rcases p with (_ | ⟨y, p⟩) · cases hp.ne_nil rfl - simp only [support_cons, List.count_cons, beq_iff_eq, List.head_cons, hf.injective.eq_iff, - add_tsub_cancel_right] + simp only [map_cons, getVert_cons_succ, tail_cons_eq, support_copy,support_map] + rw [List.count_map_of_injective _ _ hf.injective, ← support_copy, ← tail_cons_eq] exact hp.isHamiltonian_tail _ lemma isHamiltonianCycle_isCycle_and_isHamiltonian_tail : - p.IsHamiltonianCycle ↔ ∃ h : p.IsCycle, (p.tail h.not_nil).IsHamiltonian := + p.IsHamiltonianCycle ↔ p.IsCycle ∧ p.tail.IsHamiltonian := ⟨fun ⟨h, h'⟩ ↦ ⟨h, h'⟩, fun ⟨h, h'⟩ ↦ ⟨h, h'⟩⟩ lemma isHamiltonianCycle_iff_isCycle_and_support_count_tail_eq_one : p.IsHamiltonianCycle ↔ p.IsCycle ∧ ∀ a, (support p).tail.count a = 1 := by - simp only [isHamiltonianCycle_isCycle_and_isHamiltonian_tail, IsHamiltonian, support_tail, - exists_prop] + simp (config := { contextual := true }) [isHamiltonianCycle_isCycle_and_isHamiltonian_tail, + IsHamiltonian, support_tail, IsCycle.not_nil, exists_prop] /-- A hamiltonian cycle visits every vertex. -/ lemma IsHamiltonianCycle.mem_support (hp : p.IsHamiltonianCycle) (b : α) : - b ∈ p.support := List.mem_of_mem_tail <| support_tail p _ ▸ hp.isHamiltonian_tail.mem_support _ + b ∈ p.support := + List.mem_of_mem_tail <| support_tail p hp.1.not_nil ▸ hp.isHamiltonian_tail.mem_support _ /-- The length of a hamiltonian cycle is the number of vertices. -/ lemma IsHamiltonianCycle.length_eq [Fintype α] (hp : p.IsHamiltonianCycle) : @@ -110,11 +111,11 @@ lemma IsHamiltonianCycle.length_eq [Fintype α] (hp : p.IsHamiltonianCycle) : lemma IsHamiltonianCycle.count_support_self (hp : p.IsHamiltonianCycle) : p.support.count a = 2 := by - rw [support_eq_cons, List.count_cons_self, ← support_tail, hp.isHamiltonian_tail] + rw [support_eq_cons, List.count_cons_self, ← support_tail _ hp.1.not_nil, hp.isHamiltonian_tail] lemma IsHamiltonianCycle.support_count_of_ne (hp : p.IsHamiltonianCycle) (h : a ≠ b) : p.support.count b = 1 := by - rw [← cons_support_tail p, List.count_cons_of_ne h.symm, hp.isHamiltonian_tail] + rw [← cons_support_tail p hp.1.not_nil, List.count_cons_of_ne h.symm, hp.isHamiltonian_tail] end Walk diff --git a/Mathlib/Combinatorics/SimpleGraph/LapMatrix.lean b/Mathlib/Combinatorics/SimpleGraph/LapMatrix.lean index 570e89aa491e2..40f0ebf38db1e 100644 --- a/Mathlib/Combinatorics/SimpleGraph/LapMatrix.lean +++ b/Mathlib/Combinatorics/SimpleGraph/LapMatrix.lean @@ -113,9 +113,9 @@ theorem lapMatrix_toLinearMap₂'_apply'_eq_zero_iff_forall_reachable (x : V → rw [lapMatrix_toLinearMap₂'_apply'_eq_zero_iff_forall_adj] refine ⟨?_, fun h i j hA ↦ h i j hA.reachable⟩ intro h i j ⟨w⟩ - induction' w with w i j _ hA _ h' - · rfl - · exact (h i j hA).trans h' + induction w with + | nil => rfl + | cons hA _ h' => exact (h _ _ hA).trans h' theorem lapMatrix_toLin'_apply_eq_zero_iff_forall_reachable (x : V → ℝ) : Matrix.toLin' (G.lapMatrix ℝ) x = 0 ↔ ∀ i j : V, G.Reachable i j → x i = x j := by @@ -156,9 +156,10 @@ lemma linearIndependent_lapMatrix_ker_basis_aux : rw [Subtype.ext_iff] at h0 have h : ∑ c, g c • lapMatrix_ker_basis_aux G c = fun i ↦ g (connectedComponentMk G i) := by simp only [lapMatrix_ker_basis_aux, SetLike.mk_smul_mk, AddSubmonoid.coe_finset_sum] - conv_lhs => enter [2, c, j]; rw [Pi.smul_apply, smul_eq_mul, mul_ite, mul_one, mul_zero] + repeat rw [AddSubmonoid.coe_finset_sum] ext i - simp only [Finset.sum_apply, sum_ite_eq, mem_univ, ite_true] + simp only [Finset.sum_apply, Pi.smul_apply, smul_eq_mul, mul_ite, mul_one, mul_zero, sum_ite_eq, + mem_univ, ↓reduceIte] rw [h] at h0 intro c obtain ⟨i, h'⟩ : ∃ i : V, G.connectedComponentMk i = c := Quot.exists_rep c @@ -171,9 +172,10 @@ lemma top_le_span_range_lapMatrix_ker_basis_aux : use Quot.lift x.val (by rw [← lapMatrix_toLin'_apply_eq_zero_iff_forall_reachable G x, LinearMap.map_coe_ker]) ext j - simp only [lapMatrix_ker_basis_aux, AddSubmonoid.coe_finset_sum, Submodule.coe_toAddSubmonoid, - SetLike.val_smul, Finset.sum_apply, Pi.smul_apply, smul_eq_mul, mul_ite, mul_one, mul_zero, - sum_ite_eq, mem_univ, ite_true] + simp only [lapMatrix_ker_basis_aux] + rw [AddSubmonoid.coe_finset_sum] + simp only [SetLike.mk_smul_mk, Finset.sum_apply, Pi.smul_apply, smul_eq_mul, mul_ite, mul_one, + mul_zero, sum_ite_eq, mem_univ, ↓reduceIte] rfl /-- `lapMatrix_ker_basis G` is a basis of the nullspace indexed by its connected components, diff --git a/Mathlib/Combinatorics/SimpleGraph/Matching.lean b/Mathlib/Combinatorics/SimpleGraph/Matching.lean index 70951275d32d1..27c60bed5325d 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Matching.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Matching.lean @@ -198,7 +198,13 @@ variable [Fintype V] lemma even_card_of_isPerfectMatching [DecidableEq V] [DecidableRel G.Adj] (c : ConnectedComponent G) (hM : M.IsPerfectMatching) : Even (Fintype.card c.supp) := by - classical simpa using (hM.induce_connectedComponent_isMatching c).even_card + #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 : DecidablePred fun x ↦ x ∈ (M.induce c.supp).verts := fun a ↦ G.instDecidableMemSupp c a + simpa using (hM.induce_connectedComponent_isMatching c).even_card lemma odd_matches_node_outside {u : Set V} {c : ConnectedComponent (Subgraph.deleteVerts ⊤ u).coe} (hM : M.IsPerfectMatching) (codd : Odd (Nat.card c.supp)) : @@ -217,7 +223,7 @@ lemma odd_matches_node_outside {u : Set V} {c : ConnectedComponent (Subgraph.del and_true] at hv' ⊢ trivial - apply Nat.odd_iff_not_even.mp codd + apply Nat.not_even_iff_odd.2 codd haveI : Fintype ↑(Subgraph.induce M (Subtype.val '' supp c)).verts := Fintype.ofFinite _ classical have hMeven := Subgraph.IsMatching.even_card hMmatch diff --git a/Mathlib/Combinatorics/SimpleGraph/Metric.lean b/Mathlib/Combinatorics/SimpleGraph/Metric.lean index 17d5d69884b4e..615b2148d1687 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Metric.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Metric.lean @@ -56,7 +56,7 @@ protected theorem Reachable.exists_walk_length_eq_edist (hr : G.Reachable u v) : ∃ p : G.Walk u v, p.length = G.edist u v := csInf_mem <| Set.range_nonempty_iff_nonempty.mpr hr -protected theorem Connected.exists_walk_length_eq_edist (hconn : G.Connected) (u v : V) : +protected theorem Connected.exists_walk_length_eq_edist (hconn : G.Connected) (u v : V) : ∃ p : G.Walk u v, p.length = G.edist u v := (hconn u v).exists_walk_length_eq_edist diff --git a/Mathlib/Combinatorics/SimpleGraph/Path.lean b/Mathlib/Combinatorics/SimpleGraph/Path.lean index 1731440ff45a7..a094d7bce9012 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Path.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Path.lean @@ -178,6 +178,19 @@ theorem IsTrail.count_edges_eq_one [DecidableEq V] {u v : V} {p : G.Walk u v} (h {e : Sym2 V} (he : e ∈ p.edges) : p.edges.count e = 1 := List.count_eq_one_of_mem h.edges_nodup he +theorem IsTrail.length_le_card_edgeFinset [Fintype G.edgeSet] {u v : V} + {w : G.Walk u v} (h : w.IsTrail) : w.length ≤ G.edgeFinset.card := by + classical + let edges := w.edges.toFinset + have : edges.card = w.length := length_edges _ ▸ List.toFinset_card_of_nodup h.edges_nodup + rw [← this] + have : edges ⊆ G.edgeFinset := by + intro e h + refine mem_edgeFinset.mpr ?_ + apply w.edges_subset_edgeSet + simpa [edges] using h + exact Finset.card_le_card this + theorem IsPath.nil {u : V} : (nil : G.Walk u u).IsPath := by constructor <;> simp theorem IsPath.of_cons {u v w : V} {h : G.Adj u v} {p : G.Walk v w} : @@ -236,7 +249,7 @@ theorem cons_isCycle_iff {u v : V} (p : G.Walk v u) (h : G.Adj u v) : have : p.support.Nodup → p.edges.Nodup := edges_nodup_of_support_nodup tauto -lemma IsPath.tail {p : G.Walk u v} (hp : p.IsPath) (hp' : ¬ p.Nil) : (p.tail hp').IsPath := by +lemma IsPath.tail {p : G.Walk u v} (hp : p.IsPath) (hp' : ¬ p.Nil) : p.tail.IsPath := by rw [Walk.isPath_def] at hp ⊢ rw [← cons_support_tail _ hp', List.nodup_cons] at hp exact hp.2 @@ -264,7 +277,8 @@ protected theorem IsTrail.takeUntil {u v w : V} {p : G.Walk v w} (hc : p.IsTrail protected theorem IsTrail.dropUntil {u v w : V} {p : G.Walk v w} (hc : p.IsTrail) (h : u ∈ p.support) : (p.dropUntil u h).IsTrail := - IsTrail.of_append_right (q := p.dropUntil u h) (by rwa [← take_spec _ h] at hc) + IsTrail.of_append_right (p := p.takeUntil u h) (q := p.dropUntil u h) + (by rwa [← take_spec _ h] at hc) protected theorem IsPath.takeUntil {u v w : V} {p : G.Walk v w} (hc : p.IsPath) (h : u ∈ p.support) : (p.takeUntil u h).IsPath := @@ -273,7 +287,8 @@ protected theorem IsPath.takeUntil {u v w : V} {p : G.Walk v w} (hc : p.IsPath) -- Porting note: p was previously accidentally an explicit argument protected theorem IsPath.dropUntil {u v w : V} {p : G.Walk v w} (hc : p.IsPath) (h : u ∈ p.support) : (p.dropUntil u h).IsPath := - IsPath.of_append_right (q := p.dropUntil u h) (by rwa [← take_spec _ h] at hc) + IsPath.of_append_right (p := p.takeUntil u h) (q := p.dropUntil u h) + (by rwa [← take_spec _ h] at hc) protected theorem IsTrail.rotate {u v : V} {c : G.Walk v v} (hc : c.IsTrail) (h : u ∈ c.support) : (c.rotate h).IsTrail := by @@ -570,7 +585,7 @@ theorem mapEmbedding_injective (f : G ↪g G') (u v : V) : end Path -/-! ### Transferring between graphs -/ +/-! ### Transferring between graphs -/ namespace Walk @@ -794,6 +809,12 @@ namespace ConnectedComponent instance inhabited [Inhabited V] : Inhabited G.ConnectedComponent := ⟨G.connectedComponentMk default⟩ +instance isEmpty [IsEmpty V] : IsEmpty (ConnectedComponent G) := by + by_contra! hc + rw [@not_isEmpty_iff] at hc + obtain ⟨v, _⟩ := (Classical.inhabited_of_nonempty hc).default.exists_rep + exact IsEmpty.false v + @[elab_as_elim] protected theorem ind {β : G.ConnectedComponent → Prop} (h : ∀ v : V, β (G.connectedComponentMk v)) (c : G.ConnectedComponent) : β c := @@ -980,6 +1001,31 @@ lemma mem_coe_supp_of_adj {v w : V} {H : Subgraph G} {c : ConnectedComponent H.c rw [← (mem_supp_iff _ _).mp h.1] exact ⟨connectedComponentMk_eq_of_adj <| Subgraph.Adj.coe <| h.2 ▸ hadj.symm, rfl⟩ +lemma connectedComponentMk_supp_subset_supp {G'} {v : V} (h : G ≤ G') (c' : G'.ConnectedComponent) + (hc' : v ∈ c'.supp) : (G.connectedComponentMk v).supp ⊆ c'.supp := by + intro v' hv' + simp only [mem_supp_iff, ConnectedComponent.eq] at hv' ⊢ + rw [ConnectedComponent.sound (hv'.mono h)] + exact hc' + +lemma biUnion_supp_eq_supp {G G' : SimpleGraph V} (h : G ≤ G') (c' : ConnectedComponent G') : + ⋃ (c : ConnectedComponent G) (_ : c.supp ⊆ c'.supp), c.supp = c'.supp := by + ext v + simp_rw [Set.mem_iUnion] + refine ⟨fun ⟨_, ⟨hi, hi'⟩⟩ ↦ hi hi', ?_⟩ + intro hv + use G.connectedComponentMk v + use c'.connectedComponentMk_supp_subset_supp h hv + simp only [mem_supp_iff] + +lemma top_supp_eq_univ (c : ConnectedComponent (⊤ : SimpleGraph V)) : + c.supp = (Set.univ : Set V) := by + have ⟨w, hw⟩ := c.exists_rep + ext v + simp only [Set.mem_univ, iff_true, mem_supp_iff, ← hw] + apply SimpleGraph.ConnectedComponent.sound + exact (@SimpleGraph.top_connected V (Nonempty.intro v)).preconnected v w + end ConnectedComponent -- TODO: Extract as lemma about general equivalence relation diff --git a/Mathlib/Combinatorics/SimpleGraph/Regularity/Bound.lean b/Mathlib/Combinatorics/SimpleGraph/Regularity/Bound.lean index e4ad3f317a965..bd6d68eeeb2dd 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Regularity/Bound.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Regularity/Bound.lean @@ -219,17 +219,17 @@ theorem add_div_le_sum_sq_div_card (hst : s ⊆ t) (f : ι → 𝕜) (d : 𝕜) apply h₁.trans rw [sum_sub_distrib, sum_const, nsmul_eq_mul, sub_div, mul_div_cancel_left₀ _ hscard.ne'] apply (add_le_add_right ht _).trans - rw [← mul_div_right_comm, le_div_iff htcard, add_mul, div_mul_cancel₀ _ htcard.ne'] + rw [← mul_div_right_comm, le_div_iff₀ htcard, add_mul, div_mul_cancel₀ _ htcard.ne'] have h₃ := mul_sq_le_sum_sq hst (fun i => (f i - (∑ j ∈ t, f j) / t.card)) h₂ hscard.ne' apply (add_le_add_left h₃ _).trans -- Porting note: was -- `simp [← mul_div_right_comm _ (t.card : 𝕜), sub_div' _ _ _ htcard.ne', ← sum_div, ← add_div,` - -- ` mul_pow, div_le_iff (sq_pos_of_ne_zero htcard.ne'), sub_sq, sum_add_distrib, ← sum_mul,` + -- ` mul_pow, div_le_iff₀ (sq_pos_of_ne_zero htcard.ne'), sub_sq, sum_add_distrib, ← sum_mul,` -- ` ← mul_sum]` simp_rw [sub_div' _ _ _ htcard.ne'] conv_lhs => enter [2, 2, x]; rw [div_pow] rw [div_pow, ← sum_div, ← mul_div_right_comm _ (t.card : 𝕜), ← add_div, - div_le_iff (sq_pos_of_ne_zero htcard.ne')] + div_le_iff₀ (sq_pos_of_ne_zero htcard.ne')] simp_rw [sub_sq, sum_add_distrib, sum_const, nsmul_eq_mul, sum_sub_distrib, mul_pow, ← sum_mul, ← mul_sum, ← sum_mul] ring_nf; rfl diff --git a/Mathlib/Combinatorics/SimpleGraph/Regularity/Chunk.lean b/Mathlib/Combinatorics/SimpleGraph/Regularity/Chunk.lean index 1086cfd9ef8b8..4ffe166e5b4b8 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Regularity/Chunk.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Regularity/Chunk.lean @@ -123,7 +123,7 @@ private theorem one_sub_eps_mul_card_nonuniformWitness_le_card_star (hV : V ∈ (1 - ε / 10) * (G.nonuniformWitness ε U V).card ≤ ((star hP G ε hU V).biUnion id).card := by have hP₁ : 0 < P.parts.card := Finset.card_pos.2 ⟨_, hU⟩ have : (↑2 ^ P.parts.card : ℝ) * m / (U.card * ε) ≤ ε / 10 := by - rw [← div_div, div_le_iff'] + rw [← div_div, div_le_iff₀'] swap · sz_positivity refine le_of_mul_le_mul_left ?_ (pow_pos zero_lt_two P.parts.card) @@ -156,7 +156,7 @@ private theorem one_sub_eps_mul_card_nonuniformWitness_le_card_star (hV : V ∈ refine sub_le_sub_left ?_ _ have : (2 : ℝ) ^ P.parts.card = ↑2 ^ (P.parts.card - 1) * 2 := by rw [← _root_.pow_succ, tsub_add_cancel_of_le (succ_le_iff.2 hP₁)] - rw [← mul_div_right_comm, this, mul_right_comm _ (2 : ℝ), mul_assoc, le_div_iff] + rw [← mul_div_right_comm, this, mul_right_comm _ (2 : ℝ), mul_assoc, le_div_iff₀] · refine mul_le_mul_of_nonneg_left ?_ (by positivity) exact (G.le_card_nonuniformWitness hunif).trans (le_mul_of_one_le_left (cast_nonneg _) one_le_two) @@ -196,7 +196,7 @@ theorem card_biUnion_star_le_m_add_one_card_star_mul : private theorem le_sum_card_subset_chunk_parts (h𝒜 : 𝒜 ⊆ (chunk hP G ε hU).parts) (hs : s ∈ 𝒜) : (𝒜.card : ℝ) * s.card * (m / (m + 1)) ≤ (𝒜.sup id).card := by - rw [mul_div_assoc', div_le_iff coe_m_add_one_pos, mul_right_comm] + rw [mul_div_assoc', div_le_iff₀ coe_m_add_one_pos, mul_right_comm] refine mul_le_mul ?_ ?_ (cast_nonneg _) (cast_nonneg _) · rw [← (ofSubset _ h𝒜 rfl).sum_card_parts, ofSubset_parts, ← cast_mul, cast_le] exact card_nsmul_le_sum _ _ _ fun x hx => m_le_card_of_mem_chunk_parts <| h𝒜 hx @@ -205,7 +205,7 @@ private theorem le_sum_card_subset_chunk_parts (h𝒜 : 𝒜 ⊆ (chunk hP G ε private theorem sum_card_subset_chunk_parts_le (m_pos : (0 : ℝ) < m) (h𝒜 : 𝒜 ⊆ (chunk hP G ε hU).parts) (hs : s ∈ 𝒜) : ((𝒜.sup id).card : ℝ) ≤ 𝒜.card * s.card * ((m + 1) / m) := by - rw [sup_eq_biUnion, mul_div_assoc', le_div_iff m_pos, mul_right_comm] + rw [sup_eq_biUnion, mul_div_assoc', le_div_iff₀ m_pos, mul_right_comm] refine mul_le_mul ?_ ?_ (cast_nonneg _) (by positivity) · norm_cast refine card_biUnion_le_card_mul _ _ _ fun x hx => ?_ @@ -219,7 +219,7 @@ private theorem one_sub_le_m_div_m_add_one_sq [Nonempty α] rw [one_sub_div coe_m_add_one_pos.ne', add_sub_cancel_right] rw [this, sub_sq, one_pow, mul_one] refine le_trans ?_ (le_add_of_nonneg_right <| sq_nonneg _) - rw [sub_le_sub_iff_left, ← le_div_iff' (show (0 : ℝ) < 2 by norm_num), div_div, + rw [sub_le_sub_iff_left, ← le_div_iff₀' (show (0 : ℝ) < 2 by norm_num), div_div, one_div_le coe_m_add_one_pos, one_div_div] · refine le_trans ?_ (le_add_of_nonneg_right zero_le_one) norm_num @@ -238,7 +238,7 @@ private theorem m_add_one_div_m_le_one_add [Nonempty α] · positivity rw [add_sq, one_pow, add_assoc, add_le_add_iff_left, mul_one, ← le_sub_iff_add_le', 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] + 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) @@ -266,7 +266,7 @@ private theorem density_sub_eps_le_sum_density_div_card [Nonempty α] apply sum_le_sum simp only [and_imp, Prod.forall, mem_product] rintro x y hx hy - rw [mul_mul_mul_comm, mul_comm (x.card : ℝ), mul_comm (y.card : ℝ), le_div_iff, mul_assoc] + 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) @@ -303,7 +303,7 @@ private theorem sum_density_div_card_le_density_add_eps [Nonempty α] apply sum_le_sum simp only [and_imp, Prod.forall, mem_product, show A.product B = A ×ˢ B by rfl] intro x y hx hy - rw [mul_mul_mul_comm, mul_comm (x.card : ℝ), mul_comm (y.card : ℝ), div_le_iff, mul_assoc] + rw [mul_mul_mul_comm, mul_comm (x.card : ℝ), mul_comm (y.card : ℝ), div_le_iff₀, mul_assoc] · refine le_mul_of_one_le_right (cast_nonneg _) ?_ rw [div_mul_eq_mul_div, one_le_div] · refine le_trans ?_ (mul_le_mul_of_nonneg_right (m_add_one_div_m_le_one_add hPα hPε hε₁) ?_) @@ -388,7 +388,7 @@ private theorem eps_le_card_star_div [Nonempty α] (hPα : P.parts.card * 16 ^ P _ ≤ (1 - ε / 10) * (1 - (↑m)⁻¹) * ((G.nonuniformWitness ε U V).card / U.card) := by gcongr exacts [mod_cast (show 9 ≤ 100 by norm_num).trans (hundred_le_m hPα hPε hε₁), - (le_div_iff' <| cast_pos.2 (P.nonempty_of_mem_parts hU).card_pos).2 <| + (le_div_iff₀' <| cast_pos.2 (P.nonempty_of_mem_parts hU).card_pos).2 <| G.le_card_nonuniformWitness hunif] _ = (1 - ε / 10) * (G.nonuniformWitness ε U V).card * ((1 - (↑m)⁻¹) / U.card) := by rw [mul_assoc, mul_assoc, mul_div_left_comm] @@ -405,7 +405,7 @@ private theorem eps_le_card_star_div [Nonempty α] (hPα : P.parts.card * 16 ^ P refine mul_le_of_le_one_right (by positivity) ?_ have hm : (0 : ℝ) < m := by sz_positivity rw [mul_div_assoc', div_le_one hm, ← one_div, one_sub_div hm.ne', mul_div_assoc', - div_le_iff hm] + div_le_iff₀ hm] linarith /-! diff --git a/Mathlib/Combinatorics/SimpleGraph/Regularity/Energy.lean b/Mathlib/Combinatorics/SimpleGraph/Regularity/Energy.lean index c2dc97dd66768..64284f427847f 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Regularity/Energy.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Regularity/Energy.lean @@ -32,7 +32,7 @@ variable {α : Type*} [DecidableEq α] {s : Finset α} (P : Finpartition s) (G : namespace Finpartition /-- The energy of a partition, also known as index. Auxiliary quantity for Szemerédi's regularity -lemma. -/ +lemma. -/ def energy : ℚ := ((∑ uv ∈ P.parts.offDiag, G.edgeDensity uv.1 uv.2 ^ 2) : ℚ) / (P.parts.card : ℚ) ^ 2 diff --git a/Mathlib/Combinatorics/SimpleGraph/Regularity/Increment.lean b/Mathlib/Combinatorics/SimpleGraph/Regularity/Increment.lean index e990c3f0fe8b3..9e7da73f754a5 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Regularity/Increment.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Regularity/Increment.lean @@ -166,7 +166,7 @@ theorem energy_increment (hP : P.IsEquipartition) (hP₇ : 7 ≤ P.parts.card) _ = (6/7 * P.parts.card ^ 2) * ε ^ 5 * (7 / 24) := by ring _ ≤ P.parts.offDiag.card * ε ^ 5 * (22 / 75) := by gcongr ?_ * _ * ?_ - · rw [← mul_div_right_comm, div_le_iff (by norm_num), offDiag_card] + · rw [← mul_div_right_comm, div_le_iff₀ (by norm_num), offDiag_card] norm_cast rw [tsub_mul] refine le_tsub_of_add_le_left ?_ diff --git a/Mathlib/Combinatorics/SimpleGraph/Regularity/Lemma.lean b/Mathlib/Combinatorics/SimpleGraph/Regularity/Lemma.lean index 3c0421d65f4c2..5e120205aeeb8 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Regularity/Lemma.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Regularity/Lemma.lean @@ -104,7 +104,7 @@ theorem szemeredi_regularity (hε : 0 < ε) (hl : l ≤ card α) : exact mul_le_mul_left' (pow_le_pow_left (by norm_num) (by norm_num) _) _ calc (1 : ℝ) = ε ^ 5 / ↑4 * (↑4 / ε ^ 5) := by - rw [mul_comm, div_mul_div_cancel 4 (pow_pos hε 5).ne']; norm_num + rw [mul_comm, div_mul_div_cancel₀ (pow_pos hε 5).ne']; norm_num _ < ε ^ 5 / 4 * (⌊4 / ε ^ 5⌋₊ + 1) := ((mul_lt_mul_left <| by positivity).2 (Nat.lt_floor_add_one _)) _ ≤ (P.energy G : ℝ) := by rwa [← Nat.cast_add_one] @@ -131,9 +131,9 @@ theorem szemeredi_regularity (hε : 0 < ε) (hl : l ≤ card α) : (mul_le_mul_of_nonneg_right (pow_le_pow_right (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 + rw [div_mul_eq_mul_div, div_le_iff₀ (show (0 : ℝ) < 4 by norm_num)] at hi norm_num at hi - rwa [le_div_iff' (pow_pos hε _)] + rwa [le_div_iff₀' (pow_pos hε _)] have hsize : P.parts.card ≤ stepBound^[⌊4 / ε ^ 5⌋₊] t := hP₃.trans (monotone_iterate_of_id_le le_stepBound (Nat.le_floor hi) _) have hPα : P.parts.card * 16 ^ P.parts.card ≤ card α := diff --git a/Mathlib/Combinatorics/SimpleGraph/Regularity/Uniform.lean b/Mathlib/Combinatorics/SimpleGraph/Regularity/Uniform.lean index 34b41bc57eb0c..005b689effd65 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Regularity/Uniform.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Regularity/Uniform.lean @@ -329,7 +329,7 @@ lemma IsEquipartition.card_biUnion_offDiag_le (hε : 0 < ε) (hP : P.IsEquiparti obtain rfl | hA : A = ⊥ ∨ _ := A.eq_empty_or_nonempty · simp [Subsingleton.elim P ⊥] apply hP.card_biUnion_offDiag_le'.trans - rw [div_le_iff (Nat.cast_pos.2 (P.parts_nonempty hA.ne_empty).card_pos)] + rw [div_le_iff₀ (Nat.cast_pos.2 (P.parts_nonempty hA.ne_empty).card_pos)] have : (A.card : 𝕜) + P.parts.card ≤ 2 * A.card := by rw [two_mul]; exact add_le_add_left (Nat.cast_le.2 P.card_parts_le_card) _ refine (mul_le_mul_of_nonneg_left this <| by positivity).trans ?_ @@ -337,7 +337,7 @@ lemma IsEquipartition.card_biUnion_offDiag_le (hε : 0 < ε) (hP : P.IsEquiparti rw [mul_left_comm, ← sq] convert mul_le_mul_of_nonneg_left this (mul_nonneg zero_le_two <| sq_nonneg (A.card : 𝕜)) using 1 <;> ring - rwa [← div_le_iff', one_div_div] + rwa [← div_le_iff₀', one_div_div] positivity lemma IsEquipartition.sum_nonUniforms_lt' (hA : A.Nonempty) (hε : 0 < ε) (hP : P.IsEquipartition) diff --git a/Mathlib/Combinatorics/SimpleGraph/Trails.lean b/Mathlib/Combinatorics/SimpleGraph/Trails.lean index 4ce9dce76ebac..bf530ee6beb46 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Trails.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Trails.lean @@ -126,7 +126,7 @@ theorem IsEulerian.even_degree_iff {x u v : V} {p : G.Walk u v} (ht : p.IsEuleri rw [← Multiset.coe_countP, Multiset.countP_eq_card_filter, ← card_incidenceFinset_eq_degree] change Multiset.card _ = _ congr 1 - convert_to _ = (ht.isTrail.edgesFinset.filter (Membership.mem x)).val + convert_to _ = (ht.isTrail.edgesFinset.filter (x ∈ ·)).val have : Fintype G.edgeSet := fintypeEdgeSet ht rw [ht.edgesFinset_eq, G.incidenceFinset_eq_filter x] @@ -135,7 +135,7 @@ theorem IsEulerian.card_filter_odd_degree [Fintype V] [DecidableRel G.Adj] {u v (h : s = (Finset.univ : Finset V).filter fun v => Odd (G.degree v)) : s.card = 0 ∨ s.card = 2 := by subst s - simp only [Nat.odd_iff_not_even, Finset.card_eq_zero] + simp only [← Nat.not_even_iff_odd, Finset.card_eq_zero] simp only [ht.even_degree_iff, Ne, not_forall, not_and, Classical.not_not, exists_prop] obtain rfl | hn := eq_or_ne u v · left diff --git a/Mathlib/Combinatorics/SimpleGraph/Triangle/Removal.lean b/Mathlib/Combinatorics/SimpleGraph/Triangle/Removal.lean index 7af960554a9a8..c5d8d7059920e 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Triangle/Removal.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Triangle/Removal.lean @@ -61,7 +61,7 @@ private lemma card_bound (hP₁ : P.IsEquipartition) (hP₃ : P.parts.card ≤ b calc _ ≤ card α / (2 * P.parts.card : ℝ) := by gcongr _ ≤ ↑(card α / P.parts.card) := - (div_le_iff' (by positivity)).2 <| mod_cast (aux ‹_› P.card_parts_le_card).le + (div_le_iff₀' (by positivity)).2 <| mod_cast (aux ‹_› P.card_parts_le_card).le _ ≤ (s.card : ℝ) := mod_cast hP₁.average_le_card_part hX private lemma triangle_removal_aux (hε : 0 < ε) (hP₁ : P.IsEquipartition) diff --git a/Mathlib/Combinatorics/SimpleGraph/Triangle/Tripartite.lean b/Mathlib/Combinatorics/SimpleGraph/Triangle/Tripartite.lean index ceb4e3902e9d9..6bcfe21447840 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Triangle/Tripartite.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Triangle/Tripartite.lean @@ -155,7 +155,7 @@ instance graph.instDecidableRelAdj : DecidableRel (graph t).Adj toFun x := {in₀ x.1, in₁ x.2.1, in₂ x.2.2} inj' := fun ⟨a, b, c⟩ ⟨a', b', c'⟩ ↦ by simpa only [Finset.Subset.antisymm_iff, Finset.subset_iff, mem_insert, mem_singleton, forall_eq_or_imp, forall_eq, Prod.mk.inj_iff, or_false, false_or, - in₀, in₁, in₂, Sum.inl.inj_iff, Sum.inr.inj_iff] using And.left + in₀, in₁, in₂, Sum.inl.inj_iff, Sum.inr.inj_iff, reduceCtorEq] using And.left lemma toTriangle_is3Clique (hx : x ∈ t) : (graph t).IsNClique 3 (toTriangle x) := by simp only [toTriangle_apply, is3Clique_triple_iff, in₀₁_iff, in₀₂_iff, in₁₂_iff] diff --git a/Mathlib/Combinatorics/SimpleGraph/Turan.lean b/Mathlib/Combinatorics/SimpleGraph/Turan.lean index e83caeb3b7f52..45760dc0bd670 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Turan.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Turan.lean @@ -124,7 +124,7 @@ end Defs namespace IsTuranMaximal -variable {s t u : V} [DecidableEq V] +variable {s t u : V} /-- In a Turán-maximal graph, non-adjacent vertices have the same degree. -/ lemma degree_eq_of_not_adj (h : G.IsTuranMaximal r) (hn : ¬G.Adj s t) : @@ -186,7 +186,7 @@ instance : DecidableRel h.setoid.r := /-- The finpartition derived from `h.setoid`. -/ def finpartition [DecidableEq V] : Finpartition (univ : Finset V) := Finpartition.ofSetoid h.setoid -lemma not_adj_iff_part_eq : +lemma not_adj_iff_part_eq [DecidableEq V] : ¬G.Adj s t ↔ h.finpartition.part s = h.finpartition.part t := by change h.setoid.r s t ↔ _ rw [← Finpartition.mem_part_ofSetoid_iff_rel] @@ -194,7 +194,7 @@ lemma not_adj_iff_part_eq : change t ∈ fp.part s ↔ fp.part s = fp.part t rw [fp.mem_part_iff_part_eq_part (mem_univ t) (mem_univ s), eq_comm] -lemma degree_eq_card_sub_part_card : +lemma degree_eq_card_sub_part_card [DecidableEq V] : G.degree s = Fintype.card V - (h.finpartition.part s).card := calc _ = (univ.filter (G.Adj s)).card := by @@ -207,7 +207,7 @@ lemma degree_eq_card_sub_part_card : simp [setoid] /-- The parts of a Turán-maximal graph form an equipartition. -/ -theorem isEquipartition : h.finpartition.IsEquipartition := by +theorem isEquipartition [DecidableEq V] : h.finpartition.IsEquipartition := by set fp := h.finpartition by_contra hn rw [Finpartition.not_isEquipartition] at hn @@ -227,7 +227,7 @@ theorem isEquipartition : h.finpartition.IsEquipartition := by have : large.card ≤ Fintype.card V := by simpa using card_le_card large.subset_univ omega -lemma card_parts_le : h.finpartition.parts.card ≤ r := by +lemma card_parts_le [DecidableEq V] : h.finpartition.parts.card ≤ r := by by_contra! l obtain ⟨z, -, hz⟩ := h.finpartition.exists_subset_part_bijOn have ncf : ¬G.CliqueFree z.card := by @@ -240,7 +240,7 @@ lemma card_parts_le : h.finpartition.parts.card ≤ r := by /-- There are `min n r` parts in a graph on `n` vertices satisfying `G.IsTuranMaximal r`. `min` handles the `n < r` case, when `G` is complete but still `r + 1`-cliquefree for having insufficiently many vertices. -/ -theorem card_parts : h.finpartition.parts.card = min (Fintype.card V) r := by +theorem card_parts [DecidableEq V] : h.finpartition.parts.card = min (Fintype.card V) r := by set fp := h.finpartition apply le_antisymm (le_min fp.card_parts_le_card h.card_parts_le) by_contra! l @@ -280,8 +280,6 @@ theorem nonempty_iso_turanGraph : end IsTuranMaximal -variable [DecidableEq V] - /-- **Turán's theorem**, reverse direction. Any graph isomorphic to `turanGraph n r` is itself Turán-maximal if `0 < r`. -/ @@ -293,7 +291,7 @@ theorem isTuranMaximal_of_iso (f : G ≃g turanGraph n r) (hr : 0 < r) : G.IsTur fun H _ cf ↦ (f.symm.comp g).card_edgeFinset_eq ▸ j.2 H cf /-- Turán-maximality with `0 < r` transfers across graph isomorphisms. -/ -theorem IsTuranMaximal.iso {W : Type*} [DecidableEq W] [Fintype W] {H : SimpleGraph W} +theorem IsTuranMaximal.iso {W : Type*} [Fintype W] {H : SimpleGraph W} [DecidableRel H.Adj] (h : G.IsTuranMaximal r) (f : G ≃g H) (hr : 0 < r) : H.IsTuranMaximal r := isTuranMaximal_of_iso (h.nonempty_iso_turanGraph.some.comp f.symm) hr diff --git a/Mathlib/Combinatorics/SimpleGraph/Walk.lean b/Mathlib/Combinatorics/SimpleGraph/Walk.lean index 52c4b7eeca310..eff0a7cc8fc1b 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Walk.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Walk.lean @@ -177,16 +177,21 @@ theorem adj_getVert_succ {u v} (w : G.Walk u v) {i : ℕ} (hi : i < w.length) : · simp [getVert, hxy] · exact ih (Nat.succ_lt_succ_iff.1 hi) +lemma getVert_cons_one {u v w} (q : G.Walk v w) (hadj : G.Adj u v) : + (q.cons hadj).getVert 1 = v := by + have : (q.cons hadj).getVert 1 = q.getVert 0 := rfl + simpa [getVert_zero] using this + @[simp] -lemma cons_getVert_succ {u v w n} (p : G.Walk v w) (h : G.Adj u v) : +lemma getVert_cons_succ {u v w n} (p : G.Walk v w) (h : G.Adj u v) : (p.cons h).getVert (n + 1) = p.getVert n := rfl -lemma cons_getVert {u v w n} (p : G.Walk v w) (h : G.Adj u v) (hn : n ≠ 0) : +lemma getVert_cons {u v w n} (p : G.Walk v w) (h : G.Adj u v) (hn : n ≠ 0) : (p.cons h).getVert n = p.getVert (n - 1) := by obtain ⟨i, hi⟩ : ∃ (i : ℕ), i.succ = n := by use n - 1; exact Nat.succ_pred_eq_of_ne_zero hn rw [← hi] - simp only [Nat.succ_eq_add_one, cons_getVert_succ, Nat.add_sub_cancel] + simp only [Nat.succ_eq_add_one, getVert_cons_succ, Nat.add_sub_cancel] @[simp] theorem cons_append {u v w x : V} (h : G.Adj u v) (p : G.Walk v w) (q : G.Walk w x) : @@ -713,6 +718,19 @@ theorem edges_nodup_of_support_nodup {u v : V} {p : G.Walk u v} (h : p.support.N simp only [edges_cons, support_cons, List.nodup_cons] at h ⊢ exact ⟨fun h' => h.1 (fst_mem_support_of_mem_edges p' h'), ih h.2⟩ +theorem edges_injective {u v : V} : Function.Injective (Walk.edges : G.Walk u v → List (Sym2 V)) + | .nil, .nil, _ => rfl + | .nil, .cons _ _, h => by simp at h + | .cons _ _, .nil, h => by simp at h + | .cons' u v c h₁ w₁, .cons' _ v' _ h₂ w₂, h => by + have h₃ : u ≠ v' := by rintro rfl; exact G.loopless _ h₂ + obtain ⟨rfl, h₃⟩ : v = v' ∧ w₁.edges = w₂.edges := by simpa [h₁, h₃] using h + obtain rfl := Walk.edges_injective h₃ + rfl + +theorem darts_injective {u v : V} : Function.Injective (Walk.darts : G.Walk u v → List G.Dart) := + edges_injective.of_comp + /-- Predicate for the empty walk. Solves the dependent type problem where `p = G.Walk.nil` typechecks @@ -741,6 +759,9 @@ lemma nil_iff_support_eq {p : G.Walk v w} : p.Nil ↔ p.support = [v] := by lemma nil_iff_length_eq {p : G.Walk v w} : p.Nil ↔ p.length = 0 := by cases p <;> simp +lemma not_nil_iff_lt_length {p : G.Walk v w} : ¬ p.Nil ↔ 0 < p.length := by + cases p <;> simp + lemma not_nil_iff {p : G.Walk v w} : ¬ p.Nil ↔ ∃ (u : V) (h : G.Adj v u) (q : G.Walk u w), p = cons h q := by cases p <;> simp [*] @@ -765,61 +786,77 @@ lemma notNilRec_cons {motive : {u w : V} → (p : G.Walk u w) → ¬ p.Nil → S motive (q.cons h) Walk.not_nil_cons) (h' : G.Adj u v) (q' : G.Walk v w) : @Walk.notNilRec _ _ _ _ _ cons _ _ = cons h' q' := by rfl -/-- The second vertex along a non-nil walk. -/ -def sndOfNotNil (p : G.Walk v w) (hp : ¬ p.Nil) : V := - p.notNilRec (@fun _ u _ _ _ => u) hp +@[simp] lemma adj_getVert_one {p : G.Walk v w} (hp : ¬ p.Nil) : + G.Adj v (p.getVert 1) := by + simpa using adj_getVert_succ p (by simpa [not_nil_iff_lt_length] using hp : 0 < p.length) -@[simp] lemma adj_sndOfNotNil {p : G.Walk v w} (hp : ¬ p.Nil) : - G.Adj v (p.sndOfNotNil hp) := - p.notNilRec (fun h _ => h) hp +/-- The walk obtained by removing the first `n` darts of a walk. -/ +def drop {u v : V} (p : G.Walk u v) (n : ℕ) : G.Walk (p.getVert n) v := + match p, n with + | .nil, _ => .nil + | p, 0 => p.copy (getVert_zero p).symm rfl + | .cons h q, (n + 1) => (q.drop n).copy (getVert_cons_succ _ h).symm rfl /-- The walk obtained by removing the first dart of a non-nil walk. -/ -def tail (p : G.Walk u v) (hp : ¬ p.Nil) : G.Walk (p.sndOfNotNil hp) v := - p.notNilRec (fun _ q => q) hp +def tail (p : G.Walk u v) : G.Walk (p.getVert 1) v := p.drop 1 + +@[simp] +lemma tail_cons_nil (h : G.Adj u v) : (Walk.cons h .nil).tail = .nil := by rfl + +lemma tail_cons_eq (h : G.Adj u v) (p : G.Walk v w) : + (p.cons h).tail = p.copy (getVert_zero p).symm rfl := by + match p with + | .nil => rfl + | .cons h q => rfl /-- The first dart of a walk. -/ @[simps] def firstDart (p : G.Walk v w) (hp : ¬ p.Nil) : G.Dart where fst := v - snd := p.sndOfNotNil hp - adj := p.adj_sndOfNotNil hp + snd := p.getVert 1 + adj := p.adj_getVert_one hp lemma edge_firstDart (p : G.Walk v w) (hp : ¬ p.Nil) : - (p.firstDart hp).edge = s(v, p.sndOfNotNil hp) := rfl + (p.firstDart hp).edge = s(v, p.getVert 1) := rfl variable {x y : V} -- TODO: rename to u, v, w instead? -@[simp] lemma cons_tail_eq (p : G.Walk x y) (hp : ¬ p.Nil) : - cons (p.adj_sndOfNotNil hp) (p.tail hp) = p := - p.notNilRec (fun _ _ => rfl) hp +lemma cons_tail_eq (p : G.Walk x y) (hp : ¬ p.Nil) : + cons (p.adj_getVert_one hp) p.tail = p := by + cases p with + | nil => simp only [nil_nil, not_true_eq_false] at hp + | cons h q => + simp only [getVert_cons_succ, tail_cons_eq, cons_copy, copy_rfl_rfl] @[simp] lemma cons_support_tail (p : G.Walk x y) (hp : ¬p.Nil) : - x :: (p.tail hp).support = p.support := by - rw [← support_cons, cons_tail_eq] + x :: p.tail.support = p.support := by + rw [← support_cons, cons_tail_eq _ hp] @[simp] lemma length_tail_add_one {p : G.Walk x y} (hp : ¬ p.Nil) : - (p.tail hp).length + 1 = p.length := by - rw [← length_cons, cons_tail_eq] + p.tail.length + 1 = p.length := by + rw [← length_cons, cons_tail_eq _ hp] @[simp] lemma nil_copy {x' y' : V} {p : G.Walk x y} (hx : x = x') (hy : y = y') : (p.copy hx hy).Nil = p.Nil := by subst_vars; rfl -@[simp] lemma support_tail (p : G.Walk v v) (hp) : - (p.tail hp).support = p.support.tail := by +@[simp] lemma support_tail (p : G.Walk v v) (hp : ¬ p.Nil) : + p.tail.support = p.support.tail := by rw [← cons_support_tail p hp, List.tail_cons] @[simp] lemma tail_cons {t u v} (p : G.Walk u v) (h : G.Adj t u) : - (p.cons h).tail not_nil_cons = p := by - unfold Walk.tail; simp only [notNilRec_cons] + (p.cons h).tail = p.copy (getVert_zero p).symm rfl := by + match p with + | .nil => rfl + | .cons h q => rfl -lemma tail_support_eq_support_tail (p : G.Walk u v) (hnp : ¬p.Nil) : - (p.tail hnp).support = p.support.tail := - p.notNilRec (by - intro u v w huv q - unfold Walk.tail - simp only [notNilRec_cons, Walk.support_cons, List.tail_cons]) hnp +lemma support_tail_of_not_nil (p : G.Walk u v) (hnp : ¬p.Nil) : + p.tail.support = p.support.tail := by + match p with + | .nil => simp only [nil_nil, not_true_eq_false] at hnp + | .cons h q => + simp only [tail_cons, getVert_cons_succ, support_copy, support_cons, List.tail_cons] /-! ### Walk decompositions -/ @@ -995,17 +1032,23 @@ theorem exists_boundary_dart {u v : V} (p : G.Walk u v) (S : Set V) (uS : u ∈ exact ⟨d, List.Mem.tail _ hd, hcd⟩ · exact ⟨⟨(x, y), a⟩, List.Mem.head _, uS, h⟩ -lemma getVert_tail {u v n} (p : G.Walk u v) (hnp: ¬ p.Nil) : - (p.tail hnp).getVert n = p.getVert (n + 1) := - p.notNilRec (fun _ _ ↦ by simp only [tail_cons, cons_getVert_succ]) hnp - -@[simp] -lemma cons_sndOfNotNil (q : G.Walk v w) (hadj : G.Adj u v) : - (q.cons hadj).sndOfNotNil not_nil_cons = v := by - unfold sndOfNotNil; simp only [notNilRec_cons] - -lemma getVert_one (p : G.Walk u v) (hnp : ¬ p.Nil) : p.getVert 1 = p.sndOfNotNil hnp := - p.notNilRec (fun _ _ ↦ by simp only [cons_getVert_succ, getVert_zero, cons_sndOfNotNil]) hnp +@[simp] lemma getVert_copy {u v w x : V} (p : G.Walk u v) (i : ℕ) (h : u = w) (h' : v = x) : + (p.copy h h').getVert i = p.getVert i := by + subst_vars + match p, i with + | .nil, _ => + rw [getVert_of_length_le _ (by simp only [length_nil, Nat.zero_le] : nil.length ≤ _)] + rw [getVert_of_length_le _ (by simp only [length_copy, length_nil, Nat.zero_le])] + | .cons hadj q, 0 => simp only [copy_rfl_rfl, getVert_zero] + | .cons hadj q, (n + 1) => simp only [copy_cons, getVert_cons_succ]; rfl + +@[simp] lemma getVert_tail {u v n} (p : G.Walk u v) (hnp: ¬ p.Nil) : + p.tail.getVert n = p.getVert (n + 1) := by + match p with + | .nil => rfl + | .cons h q => + simp only [getVert_cons_succ, tail_cons_eq, getVert_cons] + exact getVert_copy q n (getVert_zero q).symm rfl /-- Given a walk `w` and a node in the support, there exists a natural `n`, such that given node is the `n`-th node (zero-indexed) in the walk. In addition, `n` is at most the length of the path. @@ -1032,13 +1075,18 @@ theorem mem_support_iff_exists_getVert {u v w : V} {p : G.Walk v w} : rw [@nil_iff_length_eq] have : 1 ≤ p.length := by omega exact Nat.not_eq_zero_of_lt this - rw [← tail_support_eq_support_tail _ hnp] + rw [← support_tail_of_not_nil _ hnp] rw [mem_support_iff_exists_getVert] use n - 1 - simp only [Nat.sub_le_iff_le_add, length_tail_add_one, getVert_tail] - have : n - 1 + 1 = n := by omega + simp only [Nat.sub_le_iff_le_add] + rw [getVert_tail _ hnp, length_tail_add_one hnp] + have : (n - 1 + 1) = n:= by omega rwa [this] termination_by p.length +decreasing_by +· simp_wf + rw [@Nat.lt_iff_add_one_le] + rw [length_tail_add_one hnp] end Walk @@ -1134,7 +1182,7 @@ theorem map_injective_of_injective {f : G →g G'} (hinj : Function.Injective f) abbrev mapLe {G G' : SimpleGraph V} (h : G ≤ G') {u v : V} (p : G.Walk u v) : G'.Walk u v := p.map (Hom.mapSpanningSubgraphs h) -/-! ### Transferring between graphs -/ +/-! ### Transferring between graphs -/ /-- The walk `p` transferred to lie in `H`, given that `H` contains its edges. -/ @[simp] diff --git a/Mathlib/Computability/AkraBazzi/AkraBazzi.lean b/Mathlib/Computability/AkraBazzi/AkraBazzi.lean index 73a3749b858d0..5f7d1c28e9623 100644 --- a/Mathlib/Computability/AkraBazzi/AkraBazzi.lean +++ b/Mathlib/Computability/AkraBazzi/AkraBazzi.lean @@ -266,7 +266,7 @@ lemma eventually_log_b_mul_pos : ∀ᶠ (n : ℕ) in atTop, ∀ i, 0 < log (b i exact h.eventually_gt_atTop 0 @[aesop safe apply] lemma T_pos (n : ℕ) : 0 < T n := by - induction n using Nat.strongInductionOn with + induction n using Nat.strongRecOn with | ind n h_ind => cases lt_or_le n R.n₀ with | inl hn => exact R.T_gt_zero' n hn -- n < R.n₀ @@ -508,7 +508,7 @@ lemma isTheta_smoothingFn_sub_self (i : α) : Every Akra-Bazzi recurrence has an associated exponent, denoted by `p : ℝ`, such that `∑ a_i b_i^p = 1`. This section shows the existence and uniqueness of this exponent `p` for any `R : AkraBazziRecurrence`, and defines `R.asympBound` to be the asymptotic bound satisfied by `R`, -namely `n^p (1 + ∑_{u < n} g(u) / u^(p+1))`. -/ +namely `n^p (1 + ∑_{u < n} g(u) / u^(p+1))`. -/ @[continuity] lemma continuous_sumCoeffsExp : Continuous (fun (p : ℝ) => ∑ i, a i * (b i) ^ p) := by @@ -1220,7 +1220,7 @@ lemma T_isBigO_smoothingFn_mul_asympBound : rw [Finset.mem_Ico] at hn have htmp1 : 0 < 1 - ε n := h_smoothingFn_floor n hn.1 have htmp2 : 0 < asympBound g a b n := h_asympBound_floor n hn.1 - rw [← _root_.div_le_iff (by positivity)] + rw [← _root_.div_le_iff₀ (by positivity)] rw [← Finset.mem_Ico] at hn calc T n / ((1 - ε ↑n) * asympBound g a b n) ≤ (Finset.Ico (⌊b' * n₀⌋₊) n₀).sup' h_base_nonempty @@ -1231,7 +1231,7 @@ lemma T_isBigO_smoothingFn_mul_asympBound : have h_one_sub_smoothingFn_pos' : 0 < 1 - ε n := h_smoothing_pos n hn rw [Real.norm_of_nonneg (R.T_nonneg n), Real.norm_of_nonneg (by positivity)] -- We now prove all other cases by induction - induction n using Nat.strongInductionOn with + induction n using Nat.strongRecOn with | ind n h_ind => have b_mul_n₀_le_ri i : ⌊b' * ↑n₀⌋₊ ≤ r i n := by exact_mod_cast calc ⌊b' * (n₀ : ℝ)⌋₊ ≤ b' * n₀ := Nat.floor_le <| by positivity @@ -1369,7 +1369,7 @@ lemma smoothingFn_mul_asympBound_isBigO_T : rw [Finset.mem_Ico] at hn have htmp1 : 0 < 1 + ε n := h_smoothingFn_floor n hn.1 have htmp2 : 0 < asympBound g a b n := h_asympBound_floor n hn.1 - rw [← _root_.le_div_iff (by positivity)] + rw [← _root_.le_div_iff₀ (by positivity)] rw [← Finset.mem_Ico] at hn calc T n / ((1 + ε ↑n) * asympBound g a b n) ≥ (Finset.Ico (⌊b' * n₀⌋₊) n₀).inf' h_base_nonempty @@ -1380,7 +1380,7 @@ lemma smoothingFn_mul_asympBound_isBigO_T : have h_one_sub_smoothingFn_pos' : 0 < 1 + ε n := h_smoothing_pos n hn rw [Real.norm_of_nonneg (R.T_nonneg n), Real.norm_of_nonneg (by positivity)] -- We now prove all other cases by induction - induction n using Nat.strongInductionOn with + induction n using Nat.strongRecOn with | ind n h_ind => have b_mul_n₀_le_ri i : ⌊b' * ↑n₀⌋₊ ≤ r i n := by exact_mod_cast calc ⌊b' * ↑n₀⌋₊ ≤ b' * n₀ := Nat.floor_le <| by positivity diff --git a/Mathlib/Computability/AkraBazzi/GrowsPolynomially.lean b/Mathlib/Computability/AkraBazzi/GrowsPolynomially.lean index d9f2aef25fade..65daa0a486dab 100644 --- a/Mathlib/Computability/AkraBazzi/GrowsPolynomially.lean +++ b/Mathlib/Computability/AkraBazzi/GrowsPolynomially.lean @@ -130,7 +130,7 @@ lemma eventually_zero_of_frequently_zero (hf : GrowsPolynomially f) (hf' : ∃ exact this refine hmain ⌊-logb 2 (x / x₀)⌋₊ x le_rfl ⟨?lb, ?ub⟩ case lb => - rw [← le_div_iff x₀_pos] + rw [← le_div_iff₀ x₀_pos] refine (logb_le_logb (b := 2) (by norm_num) (zpow_pos_of_pos (by norm_num) _) (by positivity)).mp ?_ rw [← rpow_intCast, logb_rpow (by norm_num) (by norm_num), ← neg_le_neg_iff] @@ -138,7 +138,7 @@ lemma eventually_zero_of_frequently_zero (hf : GrowsPolynomially f) (hf' : ∃ calc -logb 2 (x/x₀) ≤ ⌈-logb 2 (x/x₀)⌉₊ := Nat.le_ceil (-logb 2 (x / x₀)) _ ≤ _ := by rw [add_comm]; exact_mod_cast Nat.ceil_le_floor_add_one _ case ub => - rw [← div_le_iff x₀_pos] + 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 ?_ rw [← rpow_intCast, logb_rpow (by norm_num) (by norm_num), ← neg_le_neg_iff] diff --git a/Mathlib/Computability/ContextFreeGrammar.lean b/Mathlib/Computability/ContextFreeGrammar.lean index 4ee8b65304fa8..74ef24c357923 100644 --- a/Mathlib/Computability/ContextFreeGrammar.lean +++ b/Mathlib/Computability/ContextFreeGrammar.lean @@ -53,10 +53,10 @@ inductive Rewrites (r : ContextFreeRule T N) : List (Symbol T N) → List (Symbo r.Rewrites (x :: s₁) (x :: s₂) lemma Rewrites.exists_parts {r : ContextFreeRule T N} {u v : List (Symbol T N)} - (hyp : r.Rewrites u v) : + (hr : r.Rewrites u v) : ∃ p q : List (Symbol T N), u = p ++ [Symbol.nonterminal r.input] ++ q ∧ v = p ++ r.output ++ q := by - induction hyp with + induction hr with | head s => use [], s simp @@ -181,7 +181,7 @@ lemma Derives.append_left {v w : List (Symbol T g.NT)} | refl => rfl | tail _ last ih => exact ih.trans_produces <| last.append_left p -/-- Add extra prefix to context-free deriving. -/ +/-- Add extra postfix to context-free deriving. -/ lemma Derives.append_right {v w : List (Symbol T g.NT)} (hvw : g.Derives v w) (p : List (Symbol T g.NT)) : g.Derives (v ++ p) (w ++ p) := by @@ -193,7 +193,10 @@ end ContextFreeGrammar /-- Context-free languages are defined by context-free grammars. -/ def Language.IsContextFree (L : Language T) : Prop := - ∃ g : ContextFreeGrammar.{uT} T, g.language = L + ∃ g : ContextFreeGrammar.{0} T, g.language = L + +proof_wanted Language.isContextFree_iff {L : Language T} : + L.IsContextFree ↔ ∃ g : ContextFreeGrammar.{uN} T, g.language = L section closure_reversal diff --git a/Mathlib/Computability/DFA.lean b/Mathlib/Computability/DFA.lean index 312e709b9fe77..48d4c11638987 100644 --- a/Mathlib/Computability/DFA.lean +++ b/Mathlib/Computability/DFA.lean @@ -28,11 +28,9 @@ Currently, there are two disjoint sets of simp lemmas: one for `DFA.eval`, and a - Should `mem_accepts` and `mem_acceptsFrom` be marked `@[simp]`? -/ - -open Computability - universe u v +open Computability /-- A DFA is a set of states (`σ`), a transition function from state to state labelled by the alphabet (`step`), a starting state (`start`) and a set of acceptance states (`accept`). -/ @@ -247,3 +245,11 @@ theorem comap_reindex (f : α' → α) (g : σ ≃ σ') : end Maps end DFA + +/-- A regular language is a language that is defined by a DFA with finite states. -/ +def Language.IsRegular {T : Type u} (L : Language T) : Prop := + ∃ σ : Type, ∃ _ : Fintype σ, ∃ M : DFA T σ, M.accepts = L + +proof_wanted Language.isRegular_iff {T : Type u} {L : Language T} : + L.IsRegular ↔ ∃ σ : Type v, ∃ _ : Fintype σ, ∃ M : DFA T σ, M.accepts = L +-- probably needs `import Mathlib.Data.Countable.Small` diff --git a/Mathlib/Computability/Halting.lean b/Mathlib/Computability/Halting.lean index 9777467e4dbd1..6d113f0675c90 100644 --- a/Mathlib/Computability/Halting.lean +++ b/Mathlib/Computability/Halting.lean @@ -16,7 +16,6 @@ A universal partial recursive function, Rice's theorem, and the halting problem. * [Mario Carneiro, *Formalizing computability theory via partial recursive functions*][carneiro2019] -/ - open Mathlib (Vector) open Encodable Denumerable @@ -215,7 +214,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 - ⟨by infer_instance, Computable.const _⟩ }⟩ + ⟨⟨inferInstance⟩, Computable.const _⟩ }⟩ /-- The Halting problem is recursively enumerable -/ theorem halting_problem_re (n) : RePred fun c => (eval c n).Dom := diff --git a/Mathlib/Computability/Language.lean b/Mathlib/Computability/Language.lean index c3cfcd963d09b..cc112e2e09266 100644 --- a/Mathlib/Computability/Language.lean +++ b/Mathlib/Computability/Language.lean @@ -162,7 +162,7 @@ lemma mem_kstar_iff_exists_nonempty {x : List α} : refine ⟨S.filter fun l ↦ !List.isEmpty l, by simp, 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, isEmpty_iff_eq_nil] at hy + rw [mem_filter, Bool.not_eq_true', ← Bool.bool_iff_false, List.isEmpty_iff] at hy exact ⟨h y hy.1, hy.2⟩ · rintro ⟨S, hx, h⟩ exact ⟨S, hx, fun y hy ↦ (h y hy).1⟩ diff --git a/Mathlib/Computability/PartrecCode.lean b/Mathlib/Computability/PartrecCode.lean index 0bb7463dbe554..83c17cd86fb12 100644 --- a/Mathlib/Computability/PartrecCode.lean +++ b/Mathlib/Computability/PartrecCode.lean @@ -488,7 +488,7 @@ theorem eval_prec_succ (cf cg : Code) (a k : ℕ) : simp instance : Membership (ℕ →. ℕ) Code := - ⟨fun f c => eval c = f⟩ + ⟨fun c f => eval c = f⟩ @[simp] theorem eval_const : ∀ n m, eval (Code.const n) m = Part.some n diff --git a/Mathlib/Computability/Primrec.lean b/Mathlib/Computability/Primrec.lean index 0d8527495b4d2..967626fac3c92 100644 --- a/Mathlib/Computability/Primrec.lean +++ b/Mathlib/Computability/Primrec.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ import Mathlib.Algebra.Order.Ring.Nat -import Mathlib.Data.List.GetD import Mathlib.Logic.Equiv.List import Mathlib.Logic.Function.Iterate @@ -28,7 +27,6 @@ for this.) * [Mario Carneiro, *Formalizing computability theory via partial recursive functions*][carneiro2019] -/ - open Mathlib (Vector) open Denumerable Encodable Function @@ -653,7 +651,7 @@ theorem dom_fintype [Finite α] (f : α → σ) : Primrec f := option_some_iff.1 <| by haveI := decidableEqOfEncodable α refine ((list_get?₁ (l.map f)).comp (list_indexOf₁ l)).of_eq fun a => ?_ - rw [List.get?_eq_getElem?, List.getElem?_map, List.getElem?_indexOf (m a), Option.map_some'] + rw [List.get?_eq_getElem?, List.getElem?_map, List.getElem?_indexOf (m a), Option.map_some'] -- Porting note: These are new lemmas -- I added it because it actually simplified the proofs @@ -926,9 +924,14 @@ theorem list_get? : Primrec₂ (@List.get? α) := induction' l with _ l IH <;> simp [*] · apply IH +theorem list_getElem? : Primrec₂ (fun (l : List α) (n : ℕ) => l[n]?) := by + convert list_get? + ext + simp + theorem list_getD (d : α) : Primrec₂ fun l n => List.getD l n d := by - simp only [List.getD_eq_getD_get?] - exact option_getD.comp₂ list_get? (const _) + simp only [List.getD_eq_getElem?_getD] + exact option_getD.comp₂ list_getElem? (const _) theorem list_getI [Inhabited α] : Primrec₂ (@List.getI α _) := list_getD _ diff --git a/Mathlib/Computability/RegularExpressions.lean b/Mathlib/Computability/RegularExpressions.lean index 95abb4a8e3941..04ff068cce5f2 100644 --- a/Mathlib/Computability/RegularExpressions.lean +++ b/Mathlib/Computability/RegularExpressions.lean @@ -215,14 +215,15 @@ theorem char_rmatch_iff (a : α) (x : List α) : rmatch (char a) x ↔ x = [a] : · simp [List.singleton_inj]; tauto · rw [rmatch, rmatch, deriv] split_ifs with h - · simp only [deriv_one, zero_rmatch, cons.injEq, and_false] - · simp only [deriv_zero, zero_rmatch, cons.injEq, and_false] + · simp only [deriv_one, zero_rmatch, cons.injEq, and_false, reduceCtorEq] + · simp only [deriv_zero, zero_rmatch, cons.injEq, and_false, reduceCtorEq] theorem add_rmatch_iff (P Q : RegularExpression α) (x : List α) : (P + Q).rmatch x ↔ P.rmatch x ∨ Q.rmatch x := by - induction' x with _ _ ih generalizing P Q - · simp only [rmatch, matchEpsilon, Bool.or_eq_true_iff] - · repeat rw [rmatch] + induction x generalizing P Q with + | nil => simp only [rmatch, matchEpsilon, Bool.or_eq_true_iff] + | cons _ _ ih => + repeat rw [rmatch] rw [deriv_add] exact ih _ _ @@ -294,7 +295,7 @@ theorem star_rmatch_iff (P : RegularExpression α) : · intro t' ht' cases ht' with | head ht' => - simp only [ne_eq, not_false_iff, true_and, rmatch] + simp only [ne_eq, not_false_iff, true_and, rmatch, reduceCtorEq] exact ht | tail _ ht' => exact helem t' ht' · rintro ⟨S, hsum, helem⟩ diff --git a/Mathlib/Computability/TMToPartrec.lean b/Mathlib/Computability/TMToPartrec.lean index b4e1c66e921db..59fb6a5cf5aed 100644 --- a/Mathlib/Computability/TMToPartrec.lean +++ b/Mathlib/Computability/TMToPartrec.lean @@ -248,7 +248,7 @@ theorem exists_code.comp {m n} {f : Vector ℕ n →. ℕ} {g : Fin n → Vector · obtain ⟨cf, hf⟩ := hf exact ⟨cf.comp cg, fun v => by - simp [hg, hf, map_bind, seq_bind_eq, Function.comp] + simp [hg, hf, map_bind, seq_bind_eq, Function.comp_def] rfl⟩ clear hf f; induction' n with n IH · exact ⟨nil, fun v => by simp [Vector.mOfFn, Bind.bind]; rfl⟩ @@ -341,7 +341,7 @@ theorem exists_code {n} {f : Vector ℕ n →. ℕ} (hf : Nat.Partrec' f) : simp only [hf, Part.bind_some] at this split_ifs at this with h · simp only [List.headI_nil, List.headI_cons, exists_false, or_false_iff, Part.mem_some_iff, - List.tail_cons, false_and_iff, Sum.inl.injEq] at this + List.tail_cons, false_and_iff, Sum.inl.injEq, reduceCtorEq] at this subst this exact ⟨_, ⟨h, @(hm)⟩, rfl⟩ · refine IH (n.succ::v.val) (by simp_all) _ rfl fun m h' => ?_ @@ -511,10 +511,14 @@ def Cont.then : Cont → Cont → Cont | Cont.fix f k => fun k' => Cont.fix f (k.then k') theorem Cont.then_eval {k k' : Cont} {v} : (k.then k').eval v = k.eval v >>= k'.eval := by - induction' k with _ _ _ _ _ _ _ _ _ k_ih _ _ k_ih generalizing v <;> - simp only [Cont.eval, Cont.then, bind_assoc, pure_bind, *] - · simp only [← k_ih] - · split_ifs <;> [rfl; simp only [← k_ih, bind_assoc]] + induction k generalizing v with + | halt => simp only [Cont.eval, Cont.then, pure_bind] + | cons₁ => simp only [Cont.eval, bind_assoc, *] + | cons₂ => simp only [Cont.eval, *] + | comp _ _ k_ih => simp only [Cont.eval, bind_assoc, ← k_ih] + | fix _ _ k_ih => + simp only [Cont.eval, *] + split_ifs <;> [rfl; simp only [← k_ih, bind_assoc]] /-- The `then k` function is a "configuration homomorphism". Its operation on states is to append `k` to the continuation of a `Cfg.ret` state, and to run `k` on `v` if we are in the `Cfg.halt v` @@ -898,6 +902,7 @@ def natEnd : Γ' → Bool | Γ'.consₗ => true | Γ'.cons => true | _ => false +attribute [nolint simpNF] natEnd.eq_3 /-- Pop a value from the stack and place the result in local store. -/ @[simp] @@ -1233,7 +1238,7 @@ theorem move_ok {p k₁ k₂ q s L₁ o L₂} {S : K' → List Γ'} (h₁ : k₁ rfl simp only [splitAtPred, Option.elim, List.head?, List.tail_cons, Option.iget_some] at e ⊢ revert e; cases p a <;> intro e <;> - simp only [cond_false, cond_true, Prod.mk.injEq, true_and, false_and] at e ⊢ + simp only [cond_false, cond_true, Prod.mk.injEq, true_and, false_and, reduceCtorEq] at e ⊢ simp only [e] rfl · refine TransGen.head rfl ?_ @@ -1288,7 +1293,7 @@ theorem clear_ok {p k q s L₁ o L₂} {S : K' → List Γ'} (e : splitAtPred p rfl simp only [splitAtPred, Option.elim, List.head?, List.tail_cons] at e ⊢ revert e; cases p a <;> intro e <;> - simp only [cond_false, cond_true, Prod.mk.injEq, true_and, false_and] at e ⊢ + simp only [cond_false, cond_true, Prod.mk.injEq, true_and, false_and, reduceCtorEq] at e ⊢ rcases e with ⟨e₁, e₂⟩ rw [e₁, e₂] · refine TransGen.head rfl ?_ @@ -1405,7 +1410,7 @@ theorem succ_ok {q s n} {c d : List Γ'} : Reaches₁ (TM2.step tr) ⟨some q.succ, s, K'.elim (trPosNum a ++ [Γ'.cons]) l₁ c d⟩ ⟨some (unrev q), s', K'.elim (l₂' ++ [Γ'.cons]) l₁' c d⟩ by obtain ⟨l₁', l₂', s', e, h⟩ := this [] - simp? [List.reverseAux] at e says simp only [List.reverseAux] at e + simp? [List.reverseAux] at e says simp only [List.reverseAux, List.reverseAux_eq] at e refine h.trans ?_ convert unrev_ok using 2 simp [e, List.reverseAux_eq] @@ -1597,10 +1602,13 @@ def trStmts₁ : Λ' → Finset Λ' | Q@(Λ'.ret _) => {Q} theorem trStmts₁_trans {q q'} : q' ∈ trStmts₁ q → trStmts₁ q' ⊆ trStmts₁ q := by - induction' q with _ _ _ q q_ih _ _ q q_ih q q_ih _ _ q q_ih q q_ih q q_ih q₁ q₂ q₁_ih q₂_ih _ <;> + 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 (config := { contextual := true }) only [trStmts₁, Finset.mem_insert, Finset.mem_union, or_imp, Finset.mem_singleton, Finset.Subset.refl, imp_true_iff, true_and_iff] - repeat exact fun h => Finset.Subset.trans (q_ih h) (Finset.subset_insert _ _) + repeat exact fun h => Finset.Subset.trans (q_ih h) (Finset.subset_insert _ _) · simp intro s h x h' simp only [Finset.mem_biUnion, Finset.mem_univ, true_and, Finset.mem_insert] @@ -1791,8 +1799,10 @@ theorem ret_supports {S k} (H₁ : contSupp k ⊆ S) : TM2.SupportsStmt S (tr ( theorem trStmts₁_supports {S q} (H₁ : (q : Λ').Supports S) (HS₁ : trStmts₁ q ⊆ S) : Supports (trStmts₁ q) S := by have W := fun {q} => trStmts₁_self q - induction' q with _ _ _ q q_ih _ _ q q_ih q q_ih _ _ q q_ih q q_ih q q_ih q₁ q₂ q₁_ih q₂_ih _ <;> - simp [trStmts₁, -Finset.singleton_subset_iff] at HS₁ ⊢ + 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₁ ⊢ any_goals cases' Finset.insert_subset_iff.1 HS₁ with h₁ h₂ first | have h₃ := h₂ W | try simp [Finset.subset_iff] at h₂ @@ -1906,3 +1916,5 @@ end end PartrecToTM2 end Turing + +set_option linter.style.longFile 2100 diff --git a/Mathlib/Computability/TuringMachine.lean b/Mathlib/Computability/TuringMachine.lean index 99a30824f06d0..8ebbf88168bcd 100644 --- a/Mathlib/Computability/TuringMachine.lean +++ b/Mathlib/Computability/TuringMachine.lean @@ -310,7 +310,7 @@ theorem ListBlank.nth_modifyNth {Γ} [Inhabited Γ] (f : Γ → Γ) (n i) (L : L (L.modifyNth f n).nth i = if i = n then f (L.nth i) else L.nth i := by induction' n with n IH generalizing i L · cases i <;> simp only [ListBlank.nth_zero, if_true, ListBlank.head_cons, ListBlank.modifyNth, - ListBlank.nth_succ, if_false, ListBlank.tail_cons] + ListBlank.nth_succ, if_false, ListBlank.tail_cons, reduceCtorEq] · cases i · rw [if_neg (Nat.succ_ne_zero _).symm] simp only [ListBlank.nth_zero, ListBlank.head_cons, ListBlank.modifyNth] @@ -1614,7 +1614,8 @@ theorem stepAux_write (q : Stmt'₁) (v : σ) (a b : Γ) (L R : ListBlank Γ) : induction' l₂ with a l₂ IH generalizing l₁ l₂' · cases List.length_eq_zero.1 e rfl - cases' l₂' with b l₂' <;> simp only [List.length_nil, List.length_cons, Nat.succ_inj'] at e + cases' l₂' with b l₂' <;> + simp only [List.length_nil, List.length_cons, Nat.succ_inj', reduceCtorEq] at e rw [List.reverseAux, ← IH (a :: l₁) l₂' e] simp only [stepAux, ListBlank.append, Tape.write_mk', Tape.move_right_mk', ListBlank.head_cons, ListBlank.tail_cons] @@ -2353,7 +2354,7 @@ theorem tr_respects_aux₂ [DecidableEq K] {k : K} {q : Stmt₂₁} {v : σ} {S · refine ⟨_, fun k' ↦ ?_, by erw [List.length_cons, Tape.move_right_n_head, Tape.mk'_nth_nat, addBottom_nth_succ_fst, - cond, iterate_succ', Function.comp, Tape.move_right_left, Tape.move_right_n_head, + cond_false, iterate_succ', Function.comp, Tape.move_right_left, Tape.move_right_n_head, Tape.mk'_nth_nat, Tape.write_move_right_n fun a : Γ' ↦ (a.1, update a.2 k none), addBottom_modifyNth fun a ↦ update a k none, addBottom_nth_snd, stk_nth_val _ (hL k), e, @@ -2487,7 +2488,6 @@ theorem trCfg_init (k) (L : List (Γ k)) : TrCfg (TM2.init k L) (TM1.init (trIni rw [ListBlank.nth_mk, List.getI_eq_iget_get?, List.map, List.reverse_nil] cases L.reverse.get? i <;> rfl · rw [trInit, TM1.init] - dsimp only congr <;> cases L.reverse <;> try rfl simp only [List.map_map, List.tail_cons, List.map] rfl @@ -2569,3 +2569,5 @@ end end TM2to1 end Turing + +set_option linter.style.longFile 2700 diff --git a/Mathlib/Condensed/Basic.lean b/Mathlib/Condensed/Basic.lean index fb904e7ecb227..8d384f0d7eb88 100644 --- a/Mathlib/Condensed/Basic.lean +++ b/Mathlib/Condensed/Basic.lean @@ -76,7 +76,7 @@ namespace CondensedSet -- Note: `simp` can prove this when stated for `Condensed C` for a concrete category `C`. -- However, it doesn't seem to see through the abbreviation `CondensedSet` @[simp] -lemma hom_naturality_apply {X Y : CondensedSet.{u}} (f : X ⟶ Y) {S T : CompHausᵒᵖ} (g : S ⟶ T) +lemma hom_naturality_apply {X Y : CondensedSet.{u}} (f : X ⟶ Y) {S T : CompHausᵒᵖ} (g : S ⟶ T) (x : X.val.obj S) : f.val.app T (X.val.map g x) = Y.val.map g (f.val.app S x) := NatTrans.naturality_apply f.val g x diff --git a/Mathlib/Condensed/CartesianClosed.lean b/Mathlib/Condensed/CartesianClosed.lean new file mode 100644 index 0000000000000..879b84fb4b87a --- /dev/null +++ b/Mathlib/Condensed/CartesianClosed.lean @@ -0,0 +1,20 @@ +/- +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.Condensed.Limits +import Mathlib.CategoryTheory.Closed.Types +import Mathlib.CategoryTheory.Sites.CartesianClosed +/-! + +# Condensed sets form a cartesian closed category +-/ + +universe u + +noncomputable section + +open CategoryTheory + +instance : CartesianClosed (CondensedSet.{u}) := inferInstanceAs (CartesianClosed (Sheaf _ _)) diff --git a/Mathlib/Condensed/Discrete/Basic.lean b/Mathlib/Condensed/Discrete/Basic.lean index 5f2ed84dfda6a..d7964352317fa 100644 --- a/Mathlib/Condensed/Discrete/Basic.lean +++ b/Mathlib/Condensed/Discrete/Basic.lean @@ -12,13 +12,13 @@ import Mathlib.Condensed.Light.Basic # Discrete-underlying adjunction Given a category `C` with sheafification with respect to the coherent topology on compact Hausdorff -spaces, we define a functor `C ⥤ Condensed C` which associates to an object of `C` the +spaces, we define a functor `C ⥤ Condensed C` which associates to an object of `C` the corresponding "discrete" condensed object (see `Condensed.discrete`). -In `Condensed.discreteUnderlyingAdj` we prove that this functor is left adjoint to the forgetful +In `Condensed.discreteUnderlyingAdj` we prove that this functor is left adjoint to the forgetful functor from `Condensed C` to `C`. -We also give the variant `LightCondensed.discreteUnderlyingAdj` for light condensed objects. +We also give the variant `LightCondensed.discreteUnderlyingAdj` for light condensed objects. -/ universe u v w @@ -30,13 +30,13 @@ namespace Condensed variable (C : Type w) [Category.{u+1} C] [HasWeakSheafify (coherentTopology CompHaus.{u}) C] /-- -The discrete condensed object associated to an object of `C` is the constant sheaf at that object. +The discrete condensed object associated to an object of `C` is the constant sheaf at that object. -/ @[simps!] noncomputable def discrete : C ⥤ Condensed.{u} C := constantSheaf _ C /-- -The underlying object of a condensed object in `C` is the condensed object evaluated at a point. +The underlying object of a condensed object in `C` is the condensed object evaluated at a point. This can be viewed as a sort of forgetful functor from `Condensed C` to `C` -/ @[simps!] @@ -45,7 +45,7 @@ noncomputable def underlying : Condensed.{u} C ⥤ C := /-- Discreteness is left adjoint to the forgetful functor. When `C` is `Type*`, this is analogous to -`TopCat.adj₁ : TopCat.discrete ⊣ forget TopCat`.   +`TopCat.adj₁ : TopCat.discrete ⊣ forget TopCat`. -/ noncomputable def discreteUnderlyingAdj : discrete C ⊣ underlying C := constantSheafAdj _ _ CompHaus.isTerminalPUnit @@ -57,14 +57,14 @@ namespace LightCondensed variable (C : Type w) [Category.{u} C] [HasSheafify (coherentTopology LightProfinite.{u}) C] /-- -The discrete light condensed object associated to an object of `C` is the constant sheaf at that +The discrete light condensed object associated to an object of `C` is the constant sheaf at that object. -/ @[simps!] noncomputable def discrete : C ⥤ LightCondensed.{u} C := constantSheaf _ C /-- -The underlying object of a condensed object in `C` is the light condensed object evaluated at a +The underlying object of a condensed object in `C` is the light condensed object evaluated at a point. This can be viewed as a sort of forgetful functor from `LightCondensed C` to `C` -/ @[simps!] @@ -73,7 +73,7 @@ noncomputable def underlying : LightCondensed.{u} C ⥤ C := /-- Discreteness is left adjoint to the forgetful functor. When `C` is `Type*`, this is analogous to -`TopCat.adj₁ : TopCat.discrete ⊣ forget TopCat`.   +`TopCat.adj₁ : TopCat.discrete ⊣ forget TopCat`. -/ noncomputable def discreteUnderlyingAdj : discrete C ⊣ underlying C := constantSheafAdj _ _ CompHausLike.isTerminalPUnit diff --git a/Mathlib/Condensed/Equivalence.lean b/Mathlib/Condensed/Equivalence.lean index 579875bfae18a..abc50a1886387 100644 --- a/Mathlib/Condensed/Equivalence.lean +++ b/Mathlib/Condensed/Equivalence.lean @@ -20,7 +20,7 @@ Since Stonean spaces are the projective objects in `CompHaus`, which has enough and the notions of effective epimorphism, epimorphism and surjective continuous map are equivalent in `CompHaus` and `Stonean`, we can use the general setup in `Mathlib.CategoryTheory.Sites.Coherent.SheafComparison` to deduce the equivalence of categories. -We give the corresponding statements for `Profinite` as well. +We give the corresponding statements for `Profinite` as well. ## Main results @@ -61,7 +61,7 @@ instance : Stonean.toProfinite.ReflectsEffectiveEpis where ((Stonean.effectiveEpi_tfae f).out 0 2).mpr (((Profinite.effectiveEpi_tfae _).out 0 2).mp h) /-- -An effective presentation of an `X : Profinite` with respect to the inclusion functor from `Stonean` +An effective presentation of an `X : Profinite` with respect to the inclusion functor from `Stonean` -/ noncomputable def stoneanToProfiniteEffectivePresentation (X : Profinite) : Stonean.toProfinite.EffectivePresentation X where diff --git a/Mathlib/Condensed/Explicit.lean b/Mathlib/Condensed/Explicit.lean index 15e67c5ac1557..541c0747e15fc 100644 --- a/Mathlib/Condensed/Explicit.lean +++ b/Mathlib/Condensed/Explicit.lean @@ -19,9 +19,9 @@ We give the following three explicit descriptions of condensed objects: * `Condensed.ofSheafStonean`: A finite-product-preserving presheaf on `CompHaus`, satisfying `EqualizerCondition`. -The property `EqualizerCondition` is defined in `Mathlib/CategoryTheory/Sites/RegularSheaves.lean` +The property `EqualizerCondition` is defined in `Mathlib/CategoryTheory/Sites/RegularSheaves.lean` and it says that for any effective epi `X ⟶ B` (in this case that is equivalent to being a -continuous surjection), the presheaf `F` exhibits `F(B)` as the equalizer of the two maps +continuous surjection), the presheaf `F` exhibits `F(B)` as the equalizer of the two maps `F(X) ⇉ F(X ×_B X)` We also give variants for condensed objects in concrete categories whose forgetful functor @@ -150,17 +150,17 @@ end Condensed namespace CondensedSet -/-- A `CondensedSet` version of `Condensed.ofSheafStonean`. -/ +/-- A `CondensedSet` version of `Condensed.ofSheafStonean`. -/ noncomputable abbrev ofSheafStonean (F : Stonean.{u}ᵒᵖ ⥤ Type (u+1)) [PreservesFiniteProducts F] : CondensedSet := Condensed.ofSheafStonean F -/-- A `CondensedSet` version of `Condensed.ofSheafProfinite`. -/ +/-- A `CondensedSet` version of `Condensed.ofSheafProfinite`. -/ noncomputable abbrev ofSheafProfinite (F : Profinite.{u}ᵒᵖ ⥤ Type (u+1)) [PreservesFiniteProducts F] (hF : EqualizerCondition F) : CondensedSet := Condensed.ofSheafProfinite F hF -/-- A `CondensedSet` version of `Condensed.ofSheafCompHaus`. -/ +/-- A `CondensedSet` version of `Condensed.ofSheafCompHaus`. -/ noncomputable abbrev ofSheafCompHaus (F : CompHaus.{u}ᵒᵖ ⥤ Type (u+1)) [PreservesFiniteProducts F] (hF : EqualizerCondition F) : CondensedSet := Condensed.ofSheafCompHaus F hF @@ -171,19 +171,19 @@ namespace CondensedMod variable (R : Type (u+1)) [Ring R] -/-- A `CondensedMod` version of `Condensed.ofSheafStonean`. -/ +/-- A `CondensedMod` version of `Condensed.ofSheafStonean`. -/ noncomputable abbrev ofSheafStonean (F : Stonean.{u}ᵒᵖ ⥤ ModuleCat.{u+1} R) [PreservesFiniteProducts F] : CondensedMod R := haveI : HasLimitsOfSize.{u, u+1} (ModuleCat R) := hasLimitsOfSizeShrink.{u, u+1, u+1, u+1} _ Condensed.ofSheafStonean F -/-- A `CondensedMod` version of `Condensed.ofSheafProfinite`. -/ +/-- A `CondensedMod` version of `Condensed.ofSheafProfinite`. -/ noncomputable abbrev ofSheafProfinite (F : Profinite.{u}ᵒᵖ ⥤ ModuleCat.{u+1} R) [PreservesFiniteProducts F] (hF : EqualizerCondition F) : CondensedMod R := haveI : HasLimitsOfSize.{u, u+1} (ModuleCat R) := hasLimitsOfSizeShrink.{u, u+1, u+1, u+1} _ Condensed.ofSheafProfinite F hF -/-- A `CondensedMod` version of `Condensed.ofSheafCompHaus`. -/ +/-- A `CondensedMod` version of `Condensed.ofSheafCompHaus`. -/ noncomputable abbrev ofSheafCompHaus (F : CompHaus.{u}ᵒᵖ ⥤ ModuleCat.{u+1} R) [PreservesFiniteProducts F] (hF : EqualizerCondition F) : CondensedMod R := Condensed.ofSheafCompHaus F hF diff --git a/Mathlib/Condensed/Functors.lean b/Mathlib/Condensed/Functors.lean index 73869ef6f22b8..c83e320059c0d 100644 --- a/Mathlib/Condensed/Functors.lean +++ b/Mathlib/Condensed/Functors.lean @@ -17,16 +17,16 @@ sets. ## Main definitions -* `compHausToCondensed : CompHaus.{u} ⥤ CondensedSet.{u}` is essentially the yoneda presheaf - functor. We also define `profiniteToCondensed` and `stoneanToCondensed`. +* `compHausToCondensed : CompHaus.{u} ⥤ CondensedSet.{u}` is essentially the yoneda presheaf + functor. We also define `profiniteToCondensed` and `stoneanToCondensed`. TODO (Dagur): -* Define the analogues of `compHausToCondensed` for sheaves on `Profinite` and `Stonean` and provide - the relevant isomorphisms with `profiniteToCondensed` and `stoneanToCondensed`. +* Define the analogues of `compHausToCondensed` for sheaves on `Profinite` and `Stonean` and provide + the relevant isomorphisms with `profiniteToCondensed` and `stoneanToCondensed`. * Define the functor `Type (u+1) ⥤ CondensedSet.{u}` which takes a set `X` to the presheaf given by - mapping a compact Hausdorff space `S` to `LocallyConstant S X`, along with the isomorphism with + mapping a compact Hausdorff space `S` to `LocallyConstant S X`, along with the isomorphism with the functor that goes through `TopCat.{u+1}`. -/ @@ -49,7 +49,7 @@ end Universes section Topology -/-- The functor from `CompHaus` to `Condensed.{u} (Type u)` given by the Yoneda sheaf. -/ +/-- The functor from `CompHaus` to `Condensed.{u} (Type u)` given by the Yoneda sheaf. -/ def compHausToCondensed' : CompHaus.{u} ⥤ Condensed.{u} (Type u) := (coherentTopology.subcanonical CompHaus).yoneda diff --git a/Mathlib/Condensed/Light/Basic.lean b/Mathlib/Condensed/Light/Basic.lean index e4336e0a3ea2d..f5156d707ed0f 100644 --- a/Mathlib/Condensed/Light/Basic.lean +++ b/Mathlib/Condensed/Light/Basic.lean @@ -60,7 +60,7 @@ namespace LightCondSet -- Note: `simp` can prove this when stated for `LightCondensed C` for a concrete category `C`. -- However, it doesn't seem to see through the abbreviation `LightCondSet` @[simp] -lemma hom_naturality_apply {X Y : LightCondSet.{u}} (f : X ⟶ Y) {S T : LightProfiniteᵒᵖ} +lemma hom_naturality_apply {X Y : LightCondSet.{u}} (f : X ⟶ Y) {S T : LightProfiniteᵒᵖ} (g : S ⟶ T) (x : X.val.obj S) : f.val.app T (X.val.map g x) = Y.val.map g (f.val.app S x) := NatTrans.naturality_apply f.val g x diff --git a/Mathlib/Condensed/Light/CartesianClosed.lean b/Mathlib/Condensed/Light/CartesianClosed.lean new file mode 100644 index 0000000000000..99af9b717d59a --- /dev/null +++ b/Mathlib/Condensed/Light/CartesianClosed.lean @@ -0,0 +1,22 @@ +/- +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.Condensed.Light.Limits +import Mathlib.CategoryTheory.Closed.Types +import Mathlib.CategoryTheory.Sites.CartesianClosed +/-! + +# Light condensed sets form a cartesian closed category +-/ + +universe u + +noncomputable section + +open CategoryTheory + +variable {C : Type u} [SmallCategory C] + +instance : CartesianClosed (LightCondSet.{u}) := inferInstanceAs (CartesianClosed (Sheaf _ _)) diff --git a/Mathlib/Condensed/Light/Explicit.lean b/Mathlib/Condensed/Light/Explicit.lean index 8967577b1c7d4..837d7f33f7fab 100644 --- a/Mathlib/Condensed/Light/Explicit.lean +++ b/Mathlib/Condensed/Light/Explicit.lean @@ -14,9 +14,9 @@ We give explicit description of light condensed sets: * `LightCondensed.ofSheafLightProfinite`: A finite-product-preserving presheaf on `LightProfinite`, satisfying `EqualizerCondition`. -The property `EqualizerCondition` is defined in `Mathlib/CategoryTheory/Sites/RegularExtensive.lean` +The property `EqualizerCondition` is defined in `Mathlib/CategoryTheory/Sites/RegularExtensive.lean` and it says that for any effective epi `X ⟶ B` (in this case that is equivalent to being a -continuous surjection), the presheaf `F` exhibits `F(B)` as the equalizer of the two maps +continuous surjection), the presheaf `F` exhibits `F(B)` as the equalizer of the two maps `F(X) ⇉ F(X ×_B X)` We also give variants for light condensed objects in concrete categories whose forgetful functor @@ -71,7 +71,7 @@ end LightCondensed namespace LightCondSet -/-- A `LightCondSet` version of `LightCondensed.ofSheafLightProfinite`. -/ +/-- A `LightCondSet` version of `LightCondensed.ofSheafLightProfinite`. -/ noncomputable abbrev ofSheafLightProfinite (F : LightProfinite.{u}ᵒᵖ ⥤ Type u) [PreservesFiniteProducts F] (hF : EqualizerCondition F) : LightCondSet := LightCondensed.ofSheafLightProfinite F hF @@ -82,7 +82,7 @@ namespace LightCondMod variable (R : Type u) [Ring R] -/-- A `LightCondAb` version of `LightCondensed.ofSheafLightProfinite`. -/ +/-- A `LightCondAb` version of `LightCondensed.ofSheafLightProfinite`. -/ noncomputable abbrev ofSheafLightProfinite (F : LightProfinite.{u}ᵒᵖ ⥤ ModuleCat.{u} R) [PreservesFiniteProducts F] (hF : EqualizerCondition F) : LightCondMod.{u} R := LightCondensed.ofSheafLightProfinite F hF @@ -91,7 +91,7 @@ end LightCondMod namespace LightCondAb -/-- A `LightCondAb` version of `LightCondensed.ofSheafLightProfinite`. -/ +/-- A `LightCondAb` version of `LightCondensed.ofSheafLightProfinite`. -/ noncomputable abbrev ofSheafLightProfinite (F : LightProfiniteᵒᵖ ⥤ ModuleCat ℤ) [PreservesFiniteProducts F] (hF : EqualizerCondition F) : LightCondAb := LightCondMod.ofSheafLightProfinite ℤ F hF diff --git a/Mathlib/Condensed/Light/Functors.lean b/Mathlib/Condensed/Light/Functors.lean index 191499d9bb0d8..7d58dbe10bb93 100644 --- a/Mathlib/Condensed/Light/Functors.lean +++ b/Mathlib/Condensed/Light/Functors.lean @@ -14,13 +14,13 @@ sets. ## Main definitions -* `lightProfiniteToLightCondSet : LightProfinite.{u} ⥤ LightCondSet.{u}`  +* `lightProfiniteToLightCondSet : LightProfinite.{u} ⥤ LightCondSet.{u}` is the yoneda presheaf functor. TODO (Dagur): * Define the functor `Type u ⥤ LightCondSet.{u}` which takes a set `X` to the presheaf given by - mapping a light profinite space `S` to `LocallyConstant S X`, along with the isomorphism with + mapping a light profinite space `S` to `LocallyConstant S X`, along with the isomorphism with the functor that goes through `TopCat.{u+1}`. -/ @@ -29,7 +29,7 @@ universe u v open CategoryTheory Limits -/-- The functor from `LightProfinite.{u}` to `LightCondSet.{u}` given by the Yoneda sheaf. -/ +/-- The functor from `LightProfinite.{u}` to `LightCondSet.{u}` given by the Yoneda sheaf. -/ def lightProfiniteToLightCondSet : LightProfinite.{u} ⥤ LightCondSet.{u} := (coherentTopology.subcanonical LightProfinite).yoneda diff --git a/Mathlib/Condensed/Light/Limits.lean b/Mathlib/Condensed/Light/Limits.lean new file mode 100644 index 0000000000000..c1509f55c090b --- /dev/null +++ b/Mathlib/Condensed/Light/Limits.lean @@ -0,0 +1,30 @@ +/- +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.Condensed.Light.Module +/-! + +# Limits in categories of light condensed objects + +This file adds some instances for limits in light condensed sets and modules. +-/ + +universe u + +open CategoryTheory Limits + +instance : HasLimitsOfSize.{u, u} LightCondSet.{u} := by + change HasLimitsOfSize (Sheaf _ _) + infer_instance + +instance : HasFiniteLimits LightCondSet.{u} := hasFiniteLimits_of_hasLimitsOfSize _ + +variable (R : Type u) [Ring R] + +instance : HasLimitsOfSize.{u, u} (LightCondMod.{u} R) := by + change HasLimitsOfSize (Sheaf _ _) + infer_instance + +instance : HasFiniteLimits (LightCondMod.{u} R) := hasFiniteLimits_of_hasLimitsOfSize _ diff --git a/Mathlib/Condensed/Light/Module.lean b/Mathlib/Condensed/Light/Module.lean index d75eee03e1156..e4ba98cbb8812 100644 --- a/Mathlib/Condensed/Light/Module.lean +++ b/Mathlib/Condensed/Light/Module.lean @@ -68,7 +68,7 @@ namespace LightCondMod -- Note: `simp` can prove this when stated for `LightCondensed C` for a concrete category `C`. -- However, it doesn't seem to see through the abbreviation `LightCondMod` @[simp] -lemma hom_naturality_apply {X Y : LightCondMod.{u} R} (f : X ⟶ Y) {S T : LightProfiniteᵒᵖ} +lemma hom_naturality_apply {X Y : LightCondMod.{u} R} (f : X ⟶ Y) {S T : LightProfiniteᵒᵖ} (g : S ⟶ T) (x : X.val.obj S) : f.val.app T (X.val.map g x) = Y.val.map g (f.val.app S x) := NatTrans.naturality_apply f.val g x diff --git a/Mathlib/Condensed/Light/TopCatAdjunction.lean b/Mathlib/Condensed/Light/TopCatAdjunction.lean index 2b67bf1e860bb..740982a3a7bad 100644 --- a/Mathlib/Condensed/Light/TopCatAdjunction.lean +++ b/Mathlib/Condensed/Light/TopCatAdjunction.lean @@ -39,14 +39,14 @@ private def coinducingCoprod : X.val.obj ⟨LightProfinite.of PUnit⟩ := fun ⟨⟨S, i⟩, s⟩ ↦ X.val.map (S.const s).op i -/-- Let `X` be a light condensed set. We define a topology on `X(*)` as the quotient topology of +/-- Let `X` be a light condensed set. We define a topology on `X(*)` as the quotient topology of all the maps from light profinite sets `S` to `X(*)`, corresponding to elements of `X(S)`. In other words, the topology coinduced by the map `LightCondSet.coinducingCoprod` above. -/ local instance underlyingTopologicalSpace : TopologicalSpace (X.val.obj ⟨LightProfinite.of PUnit⟩) := TopologicalSpace.coinduced (coinducingCoprod X) inferInstance -/-- The object part of the functor `LightCondSet ⥤ TopCat`  -/ +/-- The object part of the functor `LightCondSet ⥤ TopCat` -/ def toTopCat : TopCat.{u} := TopCat.of (X.val.obj ⟨LightProfinite.of PUnit⟩) lemma continuous_coinducingCoprod {S : LightProfinite.{u}} (x : X.val.obj ⟨S⟩) : @@ -58,7 +58,7 @@ lemma continuous_coinducingCoprod {S : LightProfinite.{u}} (x : X.val.obj ⟨S variable {X} {Y : LightCondSet} (f : X ⟶ Y) -/-- The map part of the functor `LightCondSet ⥤ TopCat`  -/ +/-- The map part of the functor `LightCondSet ⥤ TopCat` -/ @[simps] def toTopCatMap : X.toTopCat ⟶ Y.toTopCat where toFun := f.val.app ⟨LightProfinite.of PUnit⟩ @@ -73,7 +73,7 @@ def toTopCatMap : X.toTopCat ⟶ Y.toTopCat where rw [this] exact continuous_coinducingCoprod _ _ -/-- The functor `LightCondSet ⥤ TopCat`  -/ +/-- The functor `LightCondSet ⥤ TopCat` -/ @[simps] def _root_.lightCondSetToTopCat : LightCondSet.{u} ⥤ TopCat.{u} where obj X := X.toTopCat @@ -87,7 +87,7 @@ def topCatAdjunctionCounit (X : TopCat.{u}) : X.toLightCondSet.toTopCat ⟶ X wh continuity /-- The counit of the adjunction `lightCondSetToTopCat ⊣ topCatToLightCondSet` is always bijective, -but not an isomorphism in general (the inverse isn't continuous unless `X` is sequential). +but not an isomorphism in general (the inverse isn't continuous unless `X` is sequential). -/ def topCatAdjunctionCounitEquiv (X : TopCat.{u}) : X.toLightCondSet.toTopCat ≃ X where toFun := topCatAdjunctionCounit X diff --git a/Mathlib/Condensed/Light/TopComparison.lean b/Mathlib/Condensed/Light/TopComparison.lean index ee4dbcaabc7ae..bebf7bfe42841 100644 --- a/Mathlib/Condensed/Light/TopComparison.lean +++ b/Mathlib/Condensed/Light/TopComparison.lean @@ -26,7 +26,7 @@ noncomputable abbrev TopCat.toLightCondSet (X : TopCat.{u}) : LightCondSet.{u} : toSheafCompHausLike.{u} _ X (fun _ _ _ ↦ (LightProfinite.effectiveEpi_iff_surjective _).mp) /-- -`TopCat.toLightCondSet` yields a functor from `TopCat.{u}` to `LightCondSet.{u}`. +`TopCat.toLightCondSet` yields a functor from `TopCat.{u}` to `LightCondSet.{u}`. -/ noncomputable abbrev topCatToLightCondSet : TopCat.{u} ⥤ LightCondSet.{u} := topCatToSheafCompHausLike.{u} _ (fun _ _ _ ↦ (LightProfinite.effectiveEpi_iff_surjective _).mp) diff --git a/Mathlib/Condensed/Module.lean b/Mathlib/Condensed/Module.lean index c9e76f9b22338..24a5079139cfa 100644 --- a/Mathlib/Condensed/Module.lean +++ b/Mathlib/Condensed/Module.lean @@ -74,7 +74,7 @@ namespace CondensedMod -- Note: `simp` can prove this when stated for `Condensed C` for a concrete category `C`. -- However, it doesn't seem to see through the abbreviation `CondensedMod` @[simp] -lemma hom_naturality_apply {X Y : CondensedMod.{u} R} (f : X ⟶ Y) {S T : CompHausᵒᵖ} (g : S ⟶ T) +lemma hom_naturality_apply {X Y : CondensedMod.{u} R} (f : X ⟶ Y) {S T : CompHausᵒᵖ} (g : S ⟶ T) (x : X.val.obj S) : f.val.app T (X.val.map g x) = Y.val.map g (f.val.app S x) := NatTrans.naturality_apply f.val g x diff --git a/Mathlib/Condensed/TopCatAdjunction.lean b/Mathlib/Condensed/TopCatAdjunction.lean index 13fedf0cb5e3d..d6794943e54a1 100644 --- a/Mathlib/Condensed/TopCatAdjunction.lean +++ b/Mathlib/Condensed/TopCatAdjunction.lean @@ -34,13 +34,13 @@ private def CondensedSet.coinducingCoprod : (Σ (i : (S : CompHaus.{u}) × X.val.obj ⟨S⟩), i.fst) → X.val.obj ⟨CompHaus.of PUnit⟩ := fun ⟨⟨S, i⟩, s⟩ ↦ X.val.map (S.const s).op i -/-- Let `X` be a condensed set. We define a topology on `X(*)` as the quotient topology of +/-- Let `X` be a condensed set. We define a topology on `X(*)` as the quotient topology of all the maps from compact Hausdorff `S` spaces to `X(*)`, corresponding to elements of `X(S)`. In other words, the topology coinduced by the map `CondensedSet.coinducingCoprod` above. -/ local instance : TopologicalSpace (X.val.obj ⟨CompHaus.of PUnit⟩) := TopologicalSpace.coinduced (coinducingCoprod X) inferInstance -/-- The object part of the functor `CondensedSet ⥤ TopCat`  -/ +/-- The object part of the functor `CondensedSet ⥤ TopCat` -/ def CondensedSet.toTopCat : TopCat.{u+1} := TopCat.of (X.val.obj ⟨CompHaus.of PUnit⟩) namespace CondensedSet @@ -54,7 +54,7 @@ lemma continuous_coinducingCoprod {S : CompHaus.{u}} (x : X.val.obj ⟨S⟩) : variable {X} {Y : CondensedSet} (f : X ⟶ Y) -/-- The map part of the functor `CondensedSet ⥤ TopCat`  -/ +/-- The map part of the functor `CondensedSet ⥤ TopCat` -/ @[simps] def toTopCatMap : X.toTopCat ⟶ Y.toTopCat where toFun := f.val.app ⟨CompHaus.of PUnit⟩ @@ -71,7 +71,7 @@ def toTopCatMap : X.toTopCat ⟶ Y.toTopCat where end CondensedSet -/-- The functor `CondensedSet ⥤ TopCat`  -/ +/-- The functor `CondensedSet ⥤ TopCat` -/ @[simps] def condensedSetToTopCat : CondensedSet.{u} ⥤ TopCat.{u+1} where obj X := X.toTopCat @@ -88,7 +88,7 @@ def topCatAdjunctionCounit (X : TopCat.{u+1}) : X.toCondensedSet.toTopCat ⟶ X continuity /-- The counit of the adjunction `condensedSetToTopCat ⊣ topCatToCondensedSet` is always bijective, -but not an isomorphism in general (the inverse isn't continuous unless `X` is compactly generated). +but not an isomorphism in general (the inverse isn't continuous unless `X` is compactly generated). -/ def topCatAdjunctionCounitEquiv (X : TopCat.{u+1}) : X.toCondensedSet.toTopCat ≃ X where toFun := topCatAdjunctionCounit X diff --git a/Mathlib/Condensed/TopComparison.lean b/Mathlib/Condensed/TopComparison.lean index 290e5f0d3433f..c8679d14fddbc 100644 --- a/Mathlib/Condensed/TopComparison.lean +++ b/Mathlib/Condensed/TopComparison.lean @@ -12,7 +12,7 @@ import Mathlib.Topology.Category.TopCat.Yoneda # The functor from topological spaces to condensed sets -This file builds on the API from the file `TopCat.Yoneda`. If the forgetful functor to `TopCat` has +This file builds on the API from the file `TopCat.Yoneda`. If the forgetful functor to `TopCat` has nice properties, like preserving pullbacks and finite coproducts, then this Yoneda presheaf satisfies the sheaf condition for the regular and extensive topologies respectively. @@ -31,7 +31,7 @@ variable {C : Type u} [Category.{v} C] (G : C ⥤ TopCat.{w}) (X : Type w') [TopologicalSpace X] /-- -An auxiliary lemma to that allows us to use `QuotientMap.lift` in the proof of +An auxiliary lemma to that allows us to use `QuotientMap.lift` in the proof of `equalizerCondition_yonedaPresheaf`. -/ theorem factorsThrough_of_pullbackCondition {Z B : C} {π : Z ⟶ B} [HasPullback π π] @@ -56,7 +56,7 @@ theorem factorsThrough_of_pullbackCondition {Z B : C} {π : Z ⟶ B} [HasPullbac /-- If `G` preserves the relevant pullbacks and every effective epi in `C` is a quotient map (which is -the case when `C` is `CompHaus` or `Profinite`), then `yonedaPresheaf` satisfies the equalizer +the case when `C` is `CompHaus` or `Profinite`), then `yonedaPresheaf` satisfies the equalizer condition which is required to be a sheaf for the regular topology. -/ theorem equalizerCondition_yonedaPresheaf @@ -83,7 +83,7 @@ theorem equalizerCondition_yonedaPresheaf exact DFunLike.ext'_iff.mp ((hq Z B π).lift_comp a (factorsThrough_of_pullbackCondition G X ha)) /-- -If `G` preserves finite coproducts (which is the case when `C` is `CompHaus`, `Profinite` or +If `G` preserves finite coproducts (which is the case when `C` is `CompHaus`, `Profinite` or `Stonean`), then `yonedaPresheaf` preserves finite products, which is required to be a sheaf for the extensive topology. -/ @@ -99,7 +99,7 @@ variable (P : TopCat.{u} → Prop) (X : TopCat.{max u w}) (hs : ∀ ⦃X Y : CompHausLike P⦄ (f : X ⟶ Y), EffectiveEpi f → Function.Surjective f) /-- -The sheaf on `CompHausLike P` of continuous maps to a topological space. +The sheaf on `CompHausLike P` of continuous maps to a topological space. -/ @[simps! val_obj val_map] def TopCat.toSheafCompHausLike : @@ -136,7 +136,7 @@ noncomputable abbrev TopCat.toCondensedSet (X : TopCat.{u+1}) : CondensedSet.{u} toSheafCompHausLike.{u+1} _ X (fun _ _ _ ↦ ((CompHaus.effectiveEpi_tfae _).out 0 2).mp) /-- -`TopCat.toCondensedSet` yields a functor from `TopCat.{u+1}` to `CondensedSet.{u}`. +`TopCat.toCondensedSet` yields a functor from `TopCat.{u+1}` to `CondensedSet.{u}`. -/ noncomputable abbrev topCatToCondensedSet : TopCat.{u+1} ⥤ CondensedSet.{u} := topCatToSheafCompHausLike.{u+1} _ (fun _ _ _ ↦ ((CompHaus.effectiveEpi_tfae _).out 0 2).mp) diff --git a/Mathlib/Control/Applicative.lean b/Mathlib/Control/Applicative.lean index 50670dad3673d..87acbfcaf5833 100644 --- a/Mathlib/Control/Applicative.lean +++ b/Mathlib/Control/Applicative.lean @@ -82,11 +82,11 @@ theorem map_pure (f : α → β) (x : α) : (f <$> pure x : Comp F G β) = pure Comp.ext <| by simp theorem seq_pure (f : Comp F G (α → β)) (x : α) : f <*> pure x = (fun g : α → β => g x) <$> f := - Comp.ext <| by simp [(· ∘ ·), functor_norm] + Comp.ext <| by simp [comp_def, functor_norm] theorem seq_assoc (x : Comp F G α) (f : Comp F G (α → β)) (g : Comp F G (β → γ)) : g <*> (f <*> x) = @Function.comp α β γ <$> g <*> f <*> x := - Comp.ext <| by simp [(· ∘ ·), functor_norm] + Comp.ext <| by simp [comp_def, functor_norm] theorem pure_seq_eq_map (f : α → β) (x : Comp F G α) : pure f <*> x = f <$> x := Comp.ext <| by simp [Applicative.pure_seq_eq_map', functor_norm] @@ -119,7 +119,7 @@ instance {f : Type u → Type w} {g : Type v → Type u} [Applicative f] [Applic commutative_prod _ _ := by simp! [map, Seq.seq] rw [commutative_map] - simp only [mk, flip, seq_map_assoc, Function.comp, map_map] + simp only [mk, flip, seq_map_assoc, Function.comp_def, map_map] congr funext x y rw [commutative_map] diff --git a/Mathlib/Control/Basic.lean b/Mathlib/Control/Basic.lean index 8796014b34cc6..0df3671f162c4 100644 --- a/Mathlib/Control/Basic.lean +++ b/Mathlib/Control/Basic.lean @@ -54,6 +54,7 @@ theorem seq_map_assoc (x : F (α → β)) (f : γ → α) (y : F γ) : simp only [← pure_seq] simp only [seq_assoc, Function.comp, seq_pure, ← comp_map] simp [pure_seq] + rfl @[functor_norm] theorem map_seq (f : β → γ) (x : F (α → β)) (y : F α) : @@ -224,3 +225,4 @@ theorem CommApplicative.commutative_map {m : Type u → Type v} [h : Applicative _ = (fun b a => f a b) <$> b <*> a := by rw [@CommApplicative.commutative_prod m h] simp [seq_map_assoc, map_seq, seq_assoc, seq_pure, map_map, (· ∘ ·)] + rfl diff --git a/Mathlib/Control/Bitraversable/Instances.lean b/Mathlib/Control/Bitraversable/Instances.lean index ad3106d4f11c4..0627c13d3bbac 100644 --- a/Mathlib/Control/Bitraversable/Instances.lean +++ b/Mathlib/Control/Bitraversable/Instances.lean @@ -93,7 +93,7 @@ instance (priority := 10) Bitraversable.isLawfulTraversable [LawfulBitraversable constructor <;> intros <;> simp [traverse, comp_tsnd, functor_norm] · simp [tsnd_eq_snd_id, (· <$> ·), id.mk] - · simp [tsnd, binaturality, Function.comp, functor_norm] + · simp [tsnd, binaturality, Function.comp_def, functor_norm] end diff --git a/Mathlib/Control/Bitraversable/Lemmas.lean b/Mathlib/Control/Bitraversable/Lemmas.lean index 085f0781b4305..a13f3aa61a6b2 100644 --- a/Mathlib/Control/Bitraversable/Lemmas.lean +++ b/Mathlib/Control/Bitraversable/Lemmas.lean @@ -66,27 +66,27 @@ theorem id_tsnd : ∀ {α β} (x : t α β), tsnd (F := Id) pure x = pure x := theorem comp_tfst {α₀ α₁ α₂ β} (f : α₀ → F α₁) (f' : α₁ → G α₂) (x : t α₀ β) : Comp.mk (tfst f' <$> tfst f x) = tfst (Comp.mk ∘ map f' ∘ f) x := by rw [← comp_bitraverse] - simp only [Function.comp, tfst, map_pure, Pure.pure] + simp only [Function.comp_def, tfst, map_pure, Pure.pure] @[higher_order tfst_comp_tsnd] theorem tfst_tsnd {α₀ α₁ β₀ β₁} (f : α₀ → F α₁) (f' : β₀ → G β₁) (x : t α₀ β₀) : Comp.mk (tfst f <$> tsnd f' x) = bitraverse (Comp.mk ∘ pure ∘ f) (Comp.mk ∘ map pure ∘ f') x := by rw [← comp_bitraverse] - simp only [Function.comp, map_pure] + simp only [Function.comp_def, map_pure] @[higher_order tsnd_comp_tfst] theorem tsnd_tfst {α₀ α₁ β₀ β₁} (f : α₀ → F α₁) (f' : β₀ → G β₁) (x : t α₀ β₀) : Comp.mk (tsnd f' <$> tfst f x) = bitraverse (Comp.mk ∘ map pure ∘ f) (Comp.mk ∘ pure ∘ f') x := by rw [← comp_bitraverse] - simp only [Function.comp, map_pure] + simp only [Function.comp_def, map_pure] @[higher_order tsnd_comp_tsnd] theorem comp_tsnd {α β₀ β₁ β₂} (g : β₀ → F β₁) (g' : β₁ → G β₂) (x : t α β₀) : Comp.mk (tsnd g' <$> tsnd g x) = tsnd (Comp.mk ∘ map g' ∘ g) x := by rw [← comp_bitraverse] - simp only [Function.comp, map_pure] + simp only [Function.comp_def, map_pure] rfl open Bifunctor diff --git a/Mathlib/Control/Fold.lean b/Mathlib/Control/Fold.lean index 5d51cf1544185..71a4d437faaa3 100644 --- a/Mathlib/Control/Fold.lean +++ b/Mathlib/Control/Fold.lean @@ -315,7 +315,8 @@ theorem toList_spec (xs : t α) : toList xs = FreeMonoid.toList (foldMap FreeMon Function.comp_apply] theorem foldMap_map [Monoid γ] (f : α → β) (g : β → γ) (xs : t α) : - foldMap g (f <$> xs) = foldMap (g ∘ f) xs := by simp only [foldMap, traverse_map, Function.comp] + foldMap g (f <$> xs) = foldMap (g ∘ f) xs := by + simp only [foldMap, traverse_map, Function.comp_def] theorem foldl_toList (f : α → β → α) (xs : t β) (x : α) : foldl f x xs = List.foldl f x (toList xs) := by @@ -331,18 +332,19 @@ theorem foldr_toList (f : α → β → β) (xs : t α) (x : β) : theorem toList_map (f : α → β) (xs : t α) : toList (f <$> xs) = f <$> toList xs := by simp only [toList_spec, Free.map_eq_map, foldMap_hom, foldMap_map, FreeMonoid.ofList_toList, - FreeMonoid.map_of, (· ∘ ·)] + FreeMonoid.map_of, Function.comp_def] @[simp] theorem foldl_map (g : β → γ) (f : α → γ → α) (a : α) (l : t β) : foldl f a (g <$> l) = foldl (fun x y => f x (g y)) a l := by #adaptation_note /-- nightly-2024-03-16: simp was simp only [foldl, foldMap_map, (· ∘ ·), flip] -/ - simp only [foldl, foldMap_map, (· ∘ ·), Function.flip_def] + simp only [foldl, foldMap_map, Function.comp_def, Function.flip_def] @[simp] theorem foldr_map (g : β → γ) (f : γ → α → α) (a : α) (l : t β) : - foldr f a (g <$> l) = foldr (f ∘ g) a l := by simp only [foldr, foldMap_map, (· ∘ ·), flip] + foldr f a (g <$> l) = foldr (f ∘ g) a l := by + simp only [foldr, foldMap_map, Function.comp_def, flip] @[simp] theorem toList_eq_self {xs : List α} : toList xs = xs := by @@ -357,9 +359,9 @@ theorem length_toList {xs : t α} : length xs = List.length (toList xs) := by generalize toList xs = ys rw [← Nat.add_zero ys.length] generalize 0 = n - induction' ys with _ _ ih generalizing n - · simp - · simp_arith [ih] + induction ys generalizing n with + | nil => simp + | cons _ _ ih => simp_arith [ih] variable {m : Type u → Type u} [Monad m] [LawfulMonad m] @@ -382,11 +384,12 @@ theorem foldlm_map (g : β → γ) (f : α → γ → m α) (a : α) (l : t β) foldlm f a (g <$> l) = foldlm (fun x y => f x (g y)) a l := by #adaptation_note /-- nightly-2024-03-16: simp was simp only [foldlm, foldMap_map, (· ∘ ·), flip] -/ - simp only [foldlm, foldMap_map, (· ∘ ·), Function.flip_def] + simp only [foldlm, foldMap_map, Function.comp_def, Function.flip_def] @[simp] theorem foldrm_map (g : β → γ) (f : γ → α → m α) (a : α) (l : t β) : - foldrm f a (g <$> l) = foldrm (f ∘ g) a l := by simp only [foldrm, foldMap_map, (· ∘ ·), flip] + foldrm f a (g <$> l) = foldrm (f ∘ g) a l := by + simp only [foldrm, foldMap_map, Function.comp_def, flip] end Equalities diff --git a/Mathlib/Control/Functor.lean b/Mathlib/Control/Functor.lean index 8aad2ceefbc06..59ebe2553d456 100644 --- a/Mathlib/Control/Functor.lean +++ b/Mathlib/Control/Functor.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Simon Hudon -/ import Mathlib.Control.Basic -import Mathlib.Init.Set +import Mathlib.Data.Set.Defs import Mathlib.Tactic.TypeStar import Batteries.Tactic.Lint diff --git a/Mathlib/Control/Functor/Multivariate.lean b/Mathlib/Control/Functor/Multivariate.lean index b2d82ecaeea4d..993d066487aa9 100644 --- a/Mathlib/Control/Functor/Multivariate.lean +++ b/Mathlib/Control/Functor/Multivariate.lean @@ -213,7 +213,7 @@ theorem LiftR_RelLast_iff (x y : F (α ::: β)) : -- Porting note: proof was -- rw [MvFunctor.map_map, MvFunctor.map_map, (· ⊚ ·), (· ⊚ ·)] -- congr <;> ext i ⟨x, _⟩ <;> cases i <;> rfl - suffices (fun i t => t.val.fst) = ((fun i x => (MvFunctor.f' rr n α i x).val.fst)) + suffices (fun i t => t.val.fst) = ((fun i x => (MvFunctor.f' rr n α i x).val.fst)) ∧ (fun i t => t.val.snd) = ((fun i x => (MvFunctor.f' rr n α i x).val.snd)) by rw [this.1, this.2] constructor <;> ext i ⟨x, _⟩ <;> cases i <;> rfl diff --git a/Mathlib/Control/LawfulFix.lean b/Mathlib/Control/LawfulFix.lean index 82375eb1c0037..934e97d1407a7 100644 --- a/Mathlib/Control/LawfulFix.lean +++ b/Mathlib/Control/LawfulFix.lean @@ -107,7 +107,7 @@ def approxChain : Chain ((a : _) → Part <| β a) := ⟨approx f, approx_mono f⟩ theorem le_f_of_mem_approx {x} : x ∈ approxChain f → x ≤ f x := by - simp only [(· ∈ ·), forall_exists_index] + simp only [Membership.mem, forall_exists_index] rintro i rfl apply approx_mono' diff --git a/Mathlib/Control/Random.lean b/Mathlib/Control/Random.lean index 05198d61db646..598d03e3d3880 100644 --- a/Mathlib/Control/Random.lean +++ b/Mathlib/Control/Random.lean @@ -32,14 +32,14 @@ set_option autoImplicit true /-- A monad transformer to generate random objects using the generic generator type `g` -/ abbrev RandGT (g : Type) := StateT (ULift g) -/-- A monad to generate random objects using the generator type `g`. -/ +/-- A monad to generate random objects using the generator type `g`. -/ abbrev RandG (g : Type) := RandGT g Id /-- A monad transformer to generate random objects using the generator type `StdGen`. `RandT m α` should be thought of a random value in `m α`. -/ abbrev RandT := RandGT StdGen -/-- A monad to generate random objects using the generator type `StdGen`. -/ +/-- A monad to generate random objects using the generator type `StdGen`. -/ abbrev Rand := RandG StdGen instance [MonadLift m n] : MonadLiftT (RandGT g m) (RandGT g n) where diff --git a/Mathlib/Control/Traversable/Basic.lean b/Mathlib/Control/Traversable/Basic.lean index 6c338a28da53e..e9103c5c55aa4 100644 --- a/Mathlib/Control/Traversable/Basic.lean +++ b/Mathlib/Control/Traversable/Basic.lean @@ -221,7 +221,7 @@ satisfy a naturality condition with respect to applicative transformations. -/ class LawfulTraversable (t : Type u → Type u) [Traversable t] extends LawfulFunctor t : Prop where - /-- `traverse` plays well with `pure` of the identity monad-/ + /-- `traverse` plays well with `pure` of the identity monad -/ id_traverse : ∀ {α} (x : t α), traverse (pure : α → Id α) x = x /-- `traverse` plays well with composition of applicative functors. -/ comp_traverse : diff --git a/Mathlib/Control/Traversable/Equiv.lean b/Mathlib/Control/Traversable/Equiv.lean index 6b7276bafe9a7..fbd1a7fcc724e 100644 --- a/Mathlib/Control/Traversable/Equiv.lean +++ b/Mathlib/Control/Traversable/Equiv.lean @@ -43,7 +43,7 @@ protected def map {α β : Type u} (f : α → β) (x : t' α) : t' β := eqv β <| map f ((eqv α).symm x) /-- The function `Equiv.map` transfers the functoriality of `t` to -`t'` using the equivalences `eqv`. -/ +`t'` using the equivalences `eqv`. -/ protected def functor : Functor t' where map := Equiv.map eqv variable [LawfulFunctor t] diff --git a/Mathlib/Data/Analysis/Topology.lean b/Mathlib/Data/Analysis/Topology.lean index f8db5f20dd999..6da9c694593d9 100644 --- a/Mathlib/Data/Analysis/Topology.lean +++ b/Mathlib/Data/Analysis/Topology.lean @@ -208,7 +208,7 @@ end Ctop.Realizer /-- A `LocallyFinite.Realizer F f` is a realization that `f` is locally finite, namely it is a choice of open sets from the basis of `F` such that they intersect only finitely many of the values -of `f`. -/ +of `f`. -/ structure LocallyFinite.Realizer [TopologicalSpace α] (F : Ctop.Realizer α) (f : β → Set α) where bas : ∀ a, { s // a ∈ F.F s } sets : ∀ x : α, Fintype { i | (f i ∩ F.F (bas x)).Nonempty } @@ -237,7 +237,7 @@ instance [TopologicalSpace α] [Finite β] (F : Ctop.Realizer α) (f : β → Se (locallyFinite_iff_exists_realizer _).1 <| locallyFinite_of_finite _ /-- A `Compact.Realizer s` is a realization that `s` is compact, namely it is a -choice of finite open covers for each set family covering `s`. -/ +choice of finite open covers for each set family covering `s`. -/ def Compact.Realizer [TopologicalSpace α] (s : Set α) := ∀ {f : Filter α} (F : f.Realizer) (x : F.σ), f ≠ ⊥ → F.F x ⊆ s → { a // a ∈ s ∧ 𝓝 a ⊓ f ≠ ⊥ } diff --git a/Mathlib/Data/Bool/AllAny.lean b/Mathlib/Data/Bool/AllAny.lean index 2e419d830a5b4..49c4ca9337f53 100644 --- a/Mathlib/Data/Bool/AllAny.lean +++ b/Mathlib/Data/Bool/AllAny.lean @@ -3,7 +3,8 @@ Copyright (c) 2017 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ -import Mathlib.Data.List.Basic +import Batteries.Tactic.Alias +import Mathlib.Tactic.TypeStar /-! # Boolean quantifiers @@ -17,26 +18,16 @@ variable {α : Type*} {p : α → Prop} [DecidablePred p] {l : List α} {a : α} namespace List --- Porting note: in Batteries - -theorem all_iff_forall {p : α → Bool} : all l p ↔ ∀ a ∈ l, p a := by - induction' l with a l ih - · exact iff_of_true rfl (forall_mem_nil _) - simp only [all_cons, Bool.and_eq_true_iff, ih, forall_mem_cons] +@[deprecated (since := "2024-08-10")] alias all_iff_forall := all_eq_true theorem all_iff_forall_prop : (all l fun a => p a) ↔ ∀ a ∈ l, p a := by - simp only [all_iff_forall, decide_eq_true_iff] - --- Porting note: in Batteries + simp -theorem any_iff_exists {p : α → Bool} : any l p ↔ ∃ a ∈ l, p a := by - induction' l with a l ih - · exact iff_of_false Bool.false_ne_true (not_exists_mem_nil _) - simp only [any_cons, Bool.or_eq_true_iff, ih, exists_mem_cons_iff] +@[deprecated (since := "2024-08-10")] alias any_iff_exists := any_eq_true -theorem any_iff_exists_prop : (any l fun a => p a) ↔ ∃ a ∈ l, p a := by simp [any_iff_exists] +theorem any_iff_exists_prop : (any l fun a => p a) ↔ ∃ a ∈ l, p a := by simp theorem any_of_mem {p : α → Bool} (h₁ : a ∈ l) (h₂ : p a) : any l p := - any_iff_exists.2 ⟨_, h₁, h₂⟩ + any_eq_true.2 ⟨_, h₁, h₂⟩ end List diff --git a/Mathlib/Data/Bool/Basic.lean b/Mathlib/Data/Bool/Basic.lean index da700043cf44d..530942959a201 100644 --- a/Mathlib/Data/Bool/Basic.lean +++ b/Mathlib/Data/Bool/Basic.lean @@ -120,21 +120,6 @@ alias of_decide_iff := decide_eq_true_iff theorem dichotomy (b : Bool) : b = false ∨ b = true := by cases b <;> simp -theorem forall_bool' {p : Bool → Prop} (b : Bool) : (∀ x, p x) ↔ p b ∧ p !b := - ⟨fun h ↦ ⟨h _, h _⟩, fun ⟨h₁, h₂⟩ x ↦ by cases b <;> cases x <;> assumption⟩ - -@[simp] -theorem forall_bool {p : Bool → Prop} : (∀ b, p b) ↔ p false ∧ p true := - forall_bool' false - -theorem exists_bool' {p : Bool → Prop} (b : Bool) : (∃ x, p x) ↔ p b ∨ p !b := - ⟨fun ⟨x, hx⟩ ↦ by cases x <;> cases b <;> first | exact .inl ‹_› | exact .inr ‹_›, - fun h ↦ by cases h <;> exact ⟨_, ‹_›⟩⟩ - -@[simp] -theorem exists_bool {p : Bool → Prop} : (∃ b, p b) ↔ p false ∨ p true := - exists_bool' false - theorem not_ne_id : not ≠ id := fun h ↦ false_ne_true <| congrFun h true @[deprecated (since := "2024-06-07")] alias eq_true_of_ne_false := eq_true_of_ne_false @@ -181,7 +166,7 @@ attribute [simp] xor_assoc theorem xor_iff_ne : ∀ {x y : Bool}, xor x y = true ↔ x ≠ y := by decide -/-! ### De Morgan's laws for booleans-/ +/-! ### De Morgan's laws for booleans -/ instance linearOrder : LinearOrder Bool where le_refl := by decide @@ -221,8 +206,8 @@ def ofNat (n : Nat) : Bool := @[simp] lemma toNat_beq_zero (b : Bool) : (b.toNat == 0) = !b := by cases b <;> rfl @[simp] lemma toNat_bne_zero (b : Bool) : (b.toNat != 0) = b := by simp [bne] -@[simp] lemma toNat_beq_one (b : Bool) : (b.toNat == 1) = b := by cases b <;> rfl -@[simp] lemma toNat_bne_one (b : Bool) : (b.toNat != 1) = !b := by simp [bne] +@[simp] lemma toNat_beq_one (b : Bool) : (b.toNat == 1) = b := by cases b <;> rfl +@[simp] lemma toNat_bne_one (b : Bool) : (b.toNat != 1) = !b := by simp [bne] theorem ofNat_le_ofNat {n m : Nat} (h : n ≤ m) : ofNat n ≤ ofNat m := by simp only [ofNat, ne_eq, _root_.decide_not] diff --git a/Mathlib/Data/ByteArray.lean b/Mathlib/Data/ByteArray.lean index 012385bb8d7cf..c199be41b3f7c 100644 --- a/Mathlib/Data/ByteArray.lean +++ b/Mathlib/Data/ByteArray.lean @@ -3,17 +3,23 @@ Copyright (c) 2021 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ - +import Batteries.Data.ByteSubarray -- Only needed for the deprecation. import Mathlib.Init + /-! # Main result Introduce main properties of `Up` (well-ordered relation for "upwards" induction on `ℕ`) and of `ByteArray` + +This entire file has been deprecated on 2024-08-19 in favour of `ByteSubarray` in Batteries. -/ +set_option linter.deprecated false + namespace Nat /-- A well-ordered relation for "upwards" induction on the natural numbers up to some bound `ub`. -/ +@[deprecated (since := "2024-08-19")] def Up (ub a i : Nat) := i < a ∧ i < ub theorem Up.next {ub i} (h : i < ub) : Up ub (i+1) i := ⟨Nat.lt_succ_self _, h⟩ @@ -22,11 +28,13 @@ theorem Up.WF (ub) : WellFounded (Up ub) := Subrelation.wf (h₂ := (measure (ub - ·)).wf) fun ⟨ia, iu⟩ ↦ Nat.sub_lt_sub_left iu ia /-- A well-ordered relation for "upwards" induction on the natural numbers up to some bound `ub`. -/ +@[deprecated (since := "2024-08-19")] def upRel (ub : Nat) : WellFoundedRelation Nat := ⟨Up ub, Up.WF ub⟩ end Nat /-- A terminal byte slice, a suffix of a byte array. -/ +@[deprecated (since := "2024-08-19")] structure ByteSliceT := (arr : ByteArray) (off : Nat) namespace ByteSliceT @@ -43,6 +51,7 @@ end ByteSliceT def ByteArray.toSliceT (arr : ByteArray) : ByteSliceT := ⟨arr, 0⟩ /-- A byte slice, given by a backing byte array, and an offset and length. -/ +@[deprecated Batteries.ByteSubarray (since := "2024-08-19")] structure ByteSlice := (arr : ByteArray) (off len : Nat) namespace ByteSlice @@ -57,6 +66,7 @@ def toArray : ByteSlice → ByteArray universe u v /-- The inner loop of the `forIn` implementation for byte slices. -/ +@[deprecated (since := "2024-08-19")] def forIn.loop {m : Type u → Type v} {β : Type u} [Monad m] (f : UInt8 → β → m (ForInStep β)) (arr : ByteArray) (off _end : Nat) (i : Nat) (b : β) : m β := if h : i < _end then do @@ -64,8 +74,8 @@ def forIn.loop {m : Type u → Type v} {β : Type u} [Monad m] (f : UInt8 → β | ForInStep.done b => pure b | ForInStep.yield b => have := Nat.Up.next h; loop f arr off _end (i+1) b else pure b -termination_by _end - i +@[deprecated (since := "2024-08-19")] instance {m : Type u → Type v} : ForIn m ByteSlice UInt8 := ⟨fun ⟨arr, off, len⟩ b f ↦ forIn.loop f arr off (off + len) off b⟩ @@ -78,19 +88,6 @@ def ByteSliceT.toSlice : ByteSliceT → ByteSlice /-- Convert a byte array into a byte slice. -/ def ByteArray.toSlice (arr : ByteArray) : ByteSlice := ⟨arr, 0, arr.size⟩ -/-- Convert a string of assumed-ASCII characters into a byte array. -(If any characters are non-ASCII they will be reduced modulo 256.) -/ -def String.toAsciiByteArray (s : String) : ByteArray := - let rec loop (p : Pos) (out : ByteArray) : ByteArray := - if h : s.atEnd p then out else - let c := s.get p - have : utf8ByteSize s - (next s p).byteIdx < utf8ByteSize s - p.byteIdx := - Nat.sub_lt_sub_left (Nat.lt_of_not_le <| mt decide_eq_true h) - (Nat.lt_add_of_pos_right (Char.utf8Size_pos _)) - loop (s.next p) (out.push c.toUInt8) - termination_by utf8ByteSize s - p.byteIdx - loop 0 ByteArray.empty - /-- Convert a byte slice into a string. This does not handle non-ASCII characters correctly: every byte will become a unicode character with codepoint < 256. -/ def ByteSlice.toString (bs : ByteSlice) : String := Id.run do diff --git a/Mathlib/Data/Complex/Abs.lean b/Mathlib/Data/Complex/Abs.lean index dbca5f2e696e6..8ca8f1fbe0ea6 100644 --- a/Mathlib/Data/Complex/Abs.lean +++ b/Mathlib/Data/Complex/Abs.lean @@ -202,12 +202,12 @@ theorem abs_le_sqrt_two_mul_max (z : ℂ) : Complex.abs z ≤ Real.sqrt 2 * max theorem abs_re_div_abs_le_one (z : ℂ) : |z.re / Complex.abs z| ≤ 1 := if hz : z = 0 then by simp [hz, zero_le_one] else by simp_rw [_root_.abs_div, abs_abs, - div_le_iff (AbsoluteValue.pos Complex.abs hz), one_mul, abs_re_le_abs] + div_le_iff₀ (AbsoluteValue.pos Complex.abs hz), one_mul, abs_re_le_abs] theorem abs_im_div_abs_le_one (z : ℂ) : |z.im / Complex.abs z| ≤ 1 := if hz : z = 0 then by simp [hz, zero_le_one] else by simp_rw [_root_.abs_div, abs_abs, - div_le_iff (AbsoluteValue.pos Complex.abs hz), one_mul, abs_im_le_abs] + div_le_iff₀ (AbsoluteValue.pos Complex.abs hz), one_mul, abs_im_le_abs] @[simp, norm_cast] lemma abs_intCast (n : ℤ) : abs n = |↑n| := by rw [← ofReal_intCast, abs_ofReal] diff --git a/Mathlib/Data/Complex/Exponential.lean b/Mathlib/Data/Complex/Exponential.lean index 9e9f187d59df4..c009cde85a7f2 100644 --- a/Mathlib/Data/Complex/Exponential.lean +++ b/Mathlib/Data/Complex/Exponential.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes, Abhimanyu Pallavi Sudhir -/ import Mathlib.Algebra.Order.CauSeq.BigOperators -import Mathlib.Algebra.Star.Order +import Mathlib.Algebra.Order.Star.Basic import Mathlib.Data.Complex.Abs import Mathlib.Data.Complex.BigOperators import Mathlib.Data.Nat.Choose.Sum @@ -186,6 +186,7 @@ theorem exp_add : exp (x + y) = exp x * exp y := by -- Porting note (#11445): new definition /-- the exponential function as a monoid hom from `Multiplicative ℂ` to `ℂ` -/ +@[simps] noncomputable def expMonoidHom : MonoidHom (Multiplicative ℂ) ℂ := { toFun := fun z => exp (Multiplicative.toAdd z), map_one' := by simp, @@ -210,7 +211,7 @@ theorem exp_nat_mul (x : ℂ) : ∀ n : ℕ, exp (n * x) = exp x ^ n @[simp] theorem exp_ne_zero : exp x ≠ 0 := fun h => - zero_ne_one <| by rw [← exp_zero, ← add_neg_cancel x, exp_add, h]; simp + zero_ne_one (α := ℂ) <| by rw [← exp_zero, ← add_neg_cancel x, exp_add, h]; simp theorem exp_neg : exp (-x) = (exp x)⁻¹ := by rw [← mul_right_inj' (exp_ne_zero x), ← exp_add]; simp [mul_inv_cancel₀ (exp_ne_zero x)] @@ -689,6 +690,7 @@ nonrec theorem exp_add : exp (x + y) = exp x * exp y := by simp [exp_add, exp] -- Porting note (#11445): new definition /-- the exponential function as a monoid hom from `Multiplicative ℝ` to `ℝ` -/ +@[simps] noncomputable def expMonoidHom : MonoidHom (Multiplicative ℝ) ℝ := { toFun := fun x => exp (Multiplicative.toAdd x), map_one' := by simp, @@ -1357,7 +1359,7 @@ theorem sin_pos_of_pos_of_le_one {x : ℝ} (hx0 : 0 < x) (hx : x ≤ 1) : 0 < si sub_le_comm.1 (abs_sub_le_iff.1 (sin_bound (by rwa [_root_.abs_of_nonneg (le_of_lt hx0)]))).2 theorem sin_pos_of_pos_of_le_two {x : ℝ} (hx0 : 0 < x) (hx : x ≤ 2) : 0 < sin x := - have : x / 2 ≤ 1 := (div_le_iff (by norm_num)).mpr (by simpa) + have : x / 2 ≤ 1 := (div_le_iff₀ (by norm_num)).mpr (by simpa) calc 0 < 2 * sin (x / 2) * cos (x / 2) := mul_pos (mul_pos (by norm_num) (sin_pos_of_pos_of_le_one (half_pos hx0) this)) diff --git a/Mathlib/Data/Complex/FiniteDimensional.lean b/Mathlib/Data/Complex/FiniteDimensional.lean index 6bcc28c3ae79b..5fbde35674c53 100644 --- a/Mathlib/Data/Complex/FiniteDimensional.lean +++ b/Mathlib/Data/Complex/FiniteDimensional.lean @@ -45,7 +45,7 @@ instance (priority := 100) FiniteDimensional.complexToReal (E : Type*) [AddCommG theorem rank_real_of_complex (E : Type*) [AddCommGroup E] [Module ℂ E] : Module.rank ℝ E = 2 * Module.rank ℂ E := - Cardinal.lift_inj.1 <| by + Cardinal.lift_inj.{_,0}.1 <| by rw [← lift_rank_mul_lift_rank ℝ ℂ E, Complex.rank_real_complex'] simp only [Cardinal.lift_id'] diff --git a/Mathlib/Data/Complex/Module.lean b/Mathlib/Data/Complex/Module.lean index d79c2f4a80d70..e8fc5c5c392dc 100644 --- a/Mathlib/Data/Complex/Module.lean +++ b/Mathlib/Data/Complex/Module.lean @@ -291,7 +291,7 @@ def liftAux (I' : A) (hf : I' * I' = -1) : ℂ →ₐ[ℝ] A := congr 1 -- equate "real" and "imaginary" parts · let inst : SMulCommClass ℝ A A := by infer_instance -- Porting note: added - rw [smul_mul_smul, hf, smul_neg, ← Algebra.algebraMap_eq_smul_one, ← sub_eq_add_neg, ← + rw [smul_mul_smul_comm, hf, smul_neg, ← Algebra.algebraMap_eq_smul_one, ← sub_eq_add_neg, ← RingHom.map_mul, ← RingHom.map_sub] · rw [Algebra.smul_def, Algebra.smul_def, Algebra.smul_def, ← Algebra.right_comm _ x₂, ← mul_assoc, ← add_mul, ← RingHom.map_mul, ← RingHom.map_mul, ← RingHom.map_add] @@ -498,8 +498,8 @@ lemma imaginaryPart_ofReal (r : ℝ) : ℑ (r : ℂ) = 0 := by ext1; simp [imaginaryPart_apply_coe, conj_ofReal] lemma Complex.coe_realPart (z : ℂ) : (ℜ z : ℂ) = z.re := calc - (ℜ z : ℂ) = _ := by congrm (ℜ $((re_add_im z).symm)) - _ = z.re := by + (ℜ z : ℂ) = (↑(ℜ (↑z.re + ↑z.im * I))) := by congrm (ℜ $((re_add_im z).symm)) + _ = z.re := by rw [map_add, AddSubmonoid.coe_add, mul_comm, ← smul_eq_mul, realPart_I_smul] simp [conj_ofReal, ← two_mul] diff --git a/Mathlib/Data/Countable/Basic.lean b/Mathlib/Data/Countable/Basic.lean index c3c3559c29934..9b80d33df3f88 100644 --- a/Mathlib/Data/Countable/Basic.lean +++ b/Mathlib/Data/Countable/Basic.lean @@ -65,12 +65,19 @@ instance Sum.uncountable_inl [Uncountable α] : Uncountable (α ⊕ β) := instance Sum.uncountable_inr [Uncountable β] : Uncountable (α ⊕ β) := inr_injective.uncountable -instance [Countable α] : Countable (Option α) := +instance Option.instCountable [Countable α] : Countable (Option α) := Countable.of_equiv _ (Equiv.optionEquivSumPUnit.{_, 0} α).symm +instance WithTop.instCountable [Countable α] : Countable (WithTop α) := Option.instCountable +instance WithBot.instCountable [Countable α] : Countable (WithBot α) := Option.instCountable +instance ENat.instCountable : Countable ℕ∞ := Option.instCountable + instance Option.instUncountable [Uncountable α] : Uncountable (Option α) := Injective.uncountable fun _ _ ↦ Option.some_inj.1 +instance WithTop.instUncountable [Uncountable α] : Uncountable (WithTop α) := Option.instUncountable +instance WithBot.instUncountable [Uncountable α] : Uncountable (WithBot α) := Option.instUncountable + instance [Countable α] [Countable β] : Countable (α × β) := by rcases exists_injective_nat α with ⟨f, hf⟩ rcases exists_injective_nat β with ⟨g, hg⟩ @@ -123,7 +130,7 @@ instance [Finite α] [∀ a, Countable (π a)] : Countable (∀ a, π a) := by induction' n with n ihn · change Countable (Fin 0 → ℕ); infer_instance · haveI := ihn - exact Countable.of_equiv (ℕ × (Fin n → ℕ)) (Equiv.piFinSucc _ _).symm + exact Countable.of_equiv (ℕ × (Fin n → ℕ)) (Fin.consEquiv fun _ ↦ ℕ) rcases Finite.exists_equiv_fin α with ⟨n, ⟨e⟩⟩ have f := fun a => (nonempty_embedding_nat (π a)).some exact ((Embedding.piCongrRight f).trans (Equiv.piCongrLeft' _ e).toEmbedding).countable diff --git a/Mathlib/Data/DFinsupp/Basic.lean b/Mathlib/Data/DFinsupp/Basic.lean index 2a240cc29359d..11111a2e35ca6 100644 --- a/Mathlib/Data/DFinsupp/Basic.lean +++ b/Mathlib/Data/DFinsupp/Basic.lean @@ -3,6 +3,7 @@ Copyright (c) 2018 Kenny Lau. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl, Kenny Lau -/ +import Mathlib.Algebra.BigOperators.GroupWithZero.Action import Mathlib.Algebra.BigOperators.GroupWithZero.Finset import Mathlib.Algebra.Group.Action.Prod import Mathlib.Algebra.Group.Submonoid.Membership @@ -11,7 +12,6 @@ import Mathlib.Algebra.Module.LinearMap.Defs import Mathlib.Data.Finset.Preimage import Mathlib.Data.Fintype.Quotient import Mathlib.Data.Set.Finite -import Mathlib.GroupTheory.GroupAction.BigOperators import Mathlib.Order.ConditionallyCompleteLattice.Basic /-! @@ -1300,7 +1300,7 @@ instance distribMulAction₂ [Monoid γ] [∀ i j, AddMonoid (δ i j)] variable [DecidableEq ι] -/-- The natural map between `Π₀ (i : Σ i, α i), δ i.1 i.2` and `Π₀ i (j : α i), δ i j`. -/ +/-- The natural map between `Π₀ (i : Σ i, α i), δ i.1 i.2` and `Π₀ i (j : α i), δ i j`. -/ def sigmaCurry [∀ i j, Zero (δ i j)] (f : Π₀ (i : Σ _, _), δ i.1 i.2) : Π₀ (i) (j), δ i j where toFun := fun i ↦ @@ -2093,3 +2093,5 @@ instance DFinsupp.infinite_of_right {ι : Sort _} {π : ι → Sort _} [∀ i, I DFinsupp.infinite_of_exists_right (Classical.arbitrary ι) end FiniteInfinite + +set_option linter.style.longFile 2200 diff --git a/Mathlib/Data/DFinsupp/Lex.lean b/Mathlib/Data/DFinsupp/Lex.lean index 46b0543f7f7bc..b0c8d8ea0b694 100644 --- a/Mathlib/Data/DFinsupp/Lex.lean +++ b/Mathlib/Data/DFinsupp/Lex.lean @@ -60,10 +60,9 @@ theorem lex_lt_of_lt [∀ i, PartialOrder (α i)] (r) [IsStrictOrder ι r] {x y variable [LinearOrder ι] instance Lex.isStrictOrder [∀ i, PartialOrder (α i)] : - IsStrictOrder (Lex (Π₀ i, α i)) (· < ·) := - let i : IsStrictOrder (Lex (∀ i, α i)) (· < ·) := Pi.Lex.isStrictOrder - { irrefl := toLex.surjective.forall.2 fun _ ↦ @irrefl _ _ i.toIsIrrefl _ - trans := toLex.surjective.forall₃.2 fun _ _ _ ↦ @trans _ _ i.toIsTrans _ _ _ } + IsStrictOrder (Lex (Π₀ i, α i)) (· < ·) where + irrefl _ := lt_irrefl (α := Lex (∀ i, α i)) _ + trans _ _ _ := lt_trans (α := Lex (∀ i, α i)) /-- The partial order on `DFinsupp`s obtained by the lexicographic ordering. See `DFinsupp.Lex.linearOrder` for a proof that this partial order is in fact linear. -/ diff --git a/Mathlib/Data/DFinsupp/Notation.lean b/Mathlib/Data/DFinsupp/Notation.lean index 7da5e6203d43a..f4782385250a8 100644 --- a/Mathlib/Data/DFinsupp/Notation.lean +++ b/Mathlib/Data/DFinsupp/Notation.lean @@ -19,9 +19,7 @@ is correct. namespace DFinsupp -open Lean -open Lean.Parser -open Lean.Parser.Term +open Lean Parser Term attribute [term_parser] Finsupp.stxSingle₀ Finsupp.stxUpdate₀ diff --git a/Mathlib/Data/DList/Defs.lean b/Mathlib/Data/DList/Defs.lean index 30de15869b4ca..408fa448595bd 100644 --- a/Mathlib/Data/DList/Defs.lean +++ b/Mathlib/Data/DList/Defs.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Leonardo de Moura -/ import Batteries.Data.DList -import Mathlib.Tactic.Cases /-! # Difference list @@ -39,7 +38,7 @@ theorem toList_ofList (l : List α) : DList.toList (DList.ofList l) = l := by cases l; rfl; simp only [DList.toList, DList.ofList, List.cons_append, List.append_nil] theorem ofList_toList (l : DList α) : DList.ofList (DList.toList l) = l := by - cases' l with app inv + obtain ⟨app, inv⟩ := l simp only [ofList, toList, mk.injEq] funext x rw [(inv x)] @@ -48,14 +47,13 @@ theorem toList_empty : toList (@empty α) = [] := by simp theorem toList_singleton (x : α) : toList (singleton x) = [x] := by simp -theorem toList_append (l₁ l₂ : DList α) : toList (l₁ ++ l₂) = toList l₁ ++ toList l₂ := - show toList (DList.append l₁ l₂) = toList l₁ ++ toList l₂ by - cases' l₁ with _ l₁_invariant; cases' l₂; simp; rw [l₁_invariant] +theorem toList_append (l₁ l₂ : DList α) : toList (l₁ ++ l₂) = toList l₁ ++ toList l₂ := by + obtain ⟨_, l₁_invariant⟩ := l₁; cases l₂; simp; rw [l₁_invariant] theorem toList_cons (x : α) (l : DList α) : toList (cons x l) = x :: toList l := by cases l; simp theorem toList_push (x : α) (l : DList α) : toList (push l x) = toList l ++ [x] := by - cases' l with _ l_invariant; simp; rw [l_invariant] + obtain ⟨_, l_invariant⟩ := l; simp; rw [l_invariant] end Batteries.DList diff --git a/Mathlib/Data/ENNReal/Basic.lean b/Mathlib/Data/ENNReal/Basic.lean index 4acf0165b1904..e44228f3991d3 100644 --- a/Mathlib/Data/ENNReal/Basic.lean +++ b/Mathlib/Data/ENNReal/Basic.lean @@ -186,8 +186,7 @@ protected def toReal (a : ℝ≥0∞) : Real := a.toNNReal /-- `ofReal x` returns `x` if it is nonnegative, `0` otherwise. -/ protected noncomputable def ofReal (r : Real) : ℝ≥0∞ := r.toNNReal -@[simp, norm_cast] -theorem toNNReal_coe : (r : ℝ≥0∞).toNNReal = r := rfl +@[simp, norm_cast] lemma toNNReal_coe (r : ℝ≥0) : (r : ℝ≥0∞).toNNReal = r := rfl @[simp] theorem coe_toNNReal : ∀ {a : ℝ≥0∞}, a ≠ ∞ → ↑a.toNNReal = a @@ -215,6 +214,8 @@ theorem ofReal_eq_coe_nnreal {x : ℝ} (h : 0 ≤ x) : ENNReal.ofReal x = ofNNReal ⟨x, h⟩ := (coe_nnreal_eq ⟨x, h⟩).symm +theorem ofNNReal_toNNReal (x : ℝ) : (Real.toNNReal x : ℝ≥0∞) = ENNReal.ofReal x := rfl + @[simp] theorem ofReal_coe_nnreal : ENNReal.ofReal p = p := (coe_nnreal_eq p).symm @[simp, norm_cast] theorem coe_zero : ↑(0 : ℝ≥0) = (0 : ℝ≥0∞) := rfl @@ -402,7 +403,7 @@ def neTopEquivNNReal : { a | a ≠ ∞ } ≃ ℝ≥0 where toFun x := ENNReal.toNNReal x invFun x := ⟨x, coe_ne_top⟩ left_inv := fun x => Subtype.eq <| coe_toNNReal x.2 - right_inv _ := toNNReal_coe + right_inv := toNNReal_coe theorem cinfi_ne_top [InfSet α] (f : ℝ≥0∞ → α) : ⨅ x : { x // x ≠ ∞ }, f x = ⨅ x : ℝ≥0, f x := Eq.symm <| neTopEquivNNReal.symm.surjective.iInf_congr _ fun _ => rfl @@ -471,6 +472,7 @@ theorem coe_natCast (n : ℕ) : ((n : ℝ≥0) : ℝ≥0∞) = n := rfl ofReal_natCast n @[simp] theorem natCast_ne_top (n : ℕ) : (n : ℝ≥0∞) ≠ ∞ := WithTop.natCast_ne_top n +@[simp] theorem natCast_lt_top (n : ℕ) : (n : ℝ≥0∞) < ∞ := WithTop.natCast_lt_top n @[simp] theorem top_ne_natCast (n : ℕ) : ∞ ≠ n := WithTop.top_ne_natCast n diff --git a/Mathlib/Data/ENNReal/Inv.lean b/Mathlib/Data/ENNReal/Inv.lean index f32953b91a158..d0e3217ac181c 100644 --- a/Mathlib/Data/ENNReal/Inv.lean +++ b/Mathlib/Data/ENNReal/Inv.lean @@ -97,6 +97,15 @@ protected theorem div_mul_cancel (h0 : a ≠ 0) (hI : a ≠ ∞) : b / a * a = b protected theorem mul_div_cancel' (h0 : a ≠ 0) (hI : a ≠ ∞) : a * (b / a) = b := by rw [mul_comm, ENNReal.div_mul_cancel h0 hI] +protected theorem mul_eq_left (ha : a ≠ 0) (h'a : a ≠ ∞) : a * b = a ↔ b = 1 := by + refine ⟨fun h ↦ ?_, fun h ↦ by rw [h, mul_one]⟩ + have : a * b * a⁻¹ = a * a⁻¹ := by rw [h] + rwa [mul_assoc, mul_comm b, ← mul_assoc, ENNReal.mul_inv_cancel ha h'a, one_mul] at this + +protected theorem mul_eq_right (ha : a ≠ 0) (h'a : a ≠ ∞) : b * a = a ↔ b = 1 := by + rw [mul_comm] + exact ENNReal.mul_eq_left ha h'a + -- Porting note: `simp only [div_eq_mul_inv, mul_comm, mul_assoc]` doesn't work in the following two protected theorem mul_comm_div : a / b * c = a * (c / b) := by simp only [div_eq_mul_inv, mul_right_comm, ← mul_assoc] @@ -119,7 +128,7 @@ theorem inv_lt_top {x : ℝ≥0∞} : x⁻¹ < ∞ ↔ 0 < x := by simp only [lt_top_iff_ne_top, inv_ne_top, pos_iff_ne_zero] theorem div_lt_top {x y : ℝ≥0∞} (h1 : x ≠ ∞) (h2 : y ≠ 0) : x / y < ∞ := - mul_lt_top h1 (inv_ne_top.mpr h2) + mul_lt_top h1.lt_top (inv_ne_top.mpr h2).lt_top @[simp] protected theorem inv_eq_zero : a⁻¹ = 0 ↔ a = ∞ := @@ -458,7 +467,7 @@ def orderIsoIicCoe (a : ℝ≥0) : Iic (a : ℝ≥0∞) ≃o Iic a := OrderIso.symm { toFun := fun x => ⟨x, coe_le_coe.2 x.2⟩ invFun := fun x => ⟨ENNReal.toNNReal x, coe_le_coe.1 <| coe_toNNReal_le_self.trans x.2⟩ - left_inv := fun x => Subtype.ext <| toNNReal_coe + left_inv := fun x => Subtype.ext <| toNNReal_coe _ right_inv := fun x => Subtype.ext <| coe_toNNReal (ne_top_of_le_ne_top coe_ne_top x.2) map_rel_iff' := fun {_ _} => by simp only [Equiv.coe_fn_mk, Subtype.mk_le_mk, coe_le_coe, Subtype.coe_le_coe] } diff --git a/Mathlib/Data/ENNReal/Operations.lean b/Mathlib/Data/ENNReal/Operations.lean index 9f5df7b047487..9f0b1dbbbddc3 100644 --- a/Mathlib/Data/ENNReal/Operations.lean +++ b/Mathlib/Data/ENNReal/Operations.lean @@ -5,6 +5,7 @@ Authors: Johannes Hölzl, Yury Kudryashov -/ import Mathlib.Algebra.BigOperators.WithTop import Mathlib.Algebra.GroupWithZero.Divisibility +import Mathlib.Algebra.Module.Basic import Mathlib.Data.ENNReal.Basic /-! @@ -186,9 +187,8 @@ theorem top_pow {n : ℕ} (n_pos : 0 < n) : (∞ : ℝ≥0∞) ^ n = ∞ := With theorem mul_eq_top : a * b = ∞ ↔ a ≠ 0 ∧ b = ∞ ∨ a = ∞ ∧ b ≠ 0 := WithTop.mul_eq_top_iff -theorem mul_lt_top : a ≠ ∞ → b ≠ ∞ → a * b < ∞ := WithTop.mul_lt_top - -theorem mul_ne_top : a ≠ ∞ → b ≠ ∞ → a * b ≠ ∞ := by simpa only [lt_top_iff_ne_top] using mul_lt_top +theorem mul_lt_top : a < ∞ → b < ∞ → a * b < ∞ := WithTop.mul_lt_top +theorem mul_ne_top : a ≠ ∞ → b ≠ ∞ → a * b ≠ ∞ := WithTop.mul_ne_top theorem lt_top_of_mul_ne_top_left (h : a * b ≠ ∞) (hb : b ≠ 0) : a < ∞ := lt_top_iff_ne_top.2 fun ha => h <| mul_eq_top.2 (Or.inr ⟨ha, hb⟩) @@ -202,7 +202,7 @@ theorem mul_lt_top_iff {a b : ℝ≥0∞} : a * b < ∞ ↔ a < ∞ ∧ b < ∞ rw [← or_assoc, or_iff_not_imp_right, or_iff_not_imp_right] intro hb ha exact ⟨lt_top_of_mul_ne_top_left h.ne hb, lt_top_of_mul_ne_top_right h.ne ha⟩ - · rintro (⟨ha, hb⟩ | rfl | rfl) <;> [exact mul_lt_top ha.ne hb.ne; simp; simp] + · rintro (⟨ha, hb⟩ | rfl | rfl) <;> [exact mul_lt_top ha hb; simp; simp] theorem mul_self_lt_top_iff {a : ℝ≥0∞} : a * a < ⊤ ↔ a < ⊤ := by rw [ENNReal.mul_lt_top_iff, and_self, or_self, or_iff_left_iff_imp] @@ -399,27 +399,28 @@ section Sum open Finset -variable {α : Type*} +variable {α : Type*} {s : Finset α} {f : α → ℝ≥0∞} + +/-- A product of finite numbers is still finite. -/ +lemma prod_ne_top (h : ∀ a ∈ s, f a ≠ ∞) : ∏ a ∈ s, f a ≠ ∞ := WithTop.prod_ne_top h + +/-- A product of finite numbers is still finite. -/ +lemma prod_lt_top (h : ∀ a ∈ s, f a < ∞) : ∏ a ∈ s, f a < ∞ := WithTop.prod_lt_top h -/-- A product of finite numbers is still finite -/ -theorem prod_lt_top {s : Finset α} {f : α → ℝ≥0∞} (h : ∀ a ∈ s, f a ≠ ∞) : ∏ a ∈ s, f a < ∞ := - WithTop.prod_lt_top h +/-- A sum is infinite iff one of the summands is infinite. -/ +@[simp] lemma sum_eq_top : ∑ x ∈ s, f x = ∞ ↔ ∃ a ∈ s, f a = ∞ := WithTop.sum_eq_top -/-- A sum of finite numbers is still finite -/ -theorem sum_lt_top {s : Finset α} {f : α → ℝ≥0∞} (h : ∀ a ∈ s, f a ≠ ∞) : ∑ a ∈ s, f a < ∞ := - WithTop.sum_lt_top h +/-- A sum is finite iff all summands are finite. -/ +lemma sum_ne_top : ∑ a ∈ s, f a ≠ ∞ ↔ ∀ a ∈ s, f a ≠ ∞ := WithTop.sum_ne_top -/-- A sum of finite numbers is still finite -/ -theorem sum_lt_top_iff {s : Finset α} {f : α → ℝ≥0∞} : ∑ a ∈ s, f a < ∞ ↔ ∀ a ∈ s, f a < ∞ := - WithTop.sum_lt_top_iff +/-- A sum is finite iff all summands are finite. -/ +@[simp] lemma sum_lt_top : ∑ a ∈ s, f a < ∞ ↔ ∀ a ∈ s, f a < ∞ := WithTop.sum_lt_top -/-- A sum of numbers is infinite iff one of them is infinite -/ -theorem sum_eq_top_iff {s : Finset α} {f : α → ℝ≥0∞} : ∑ x ∈ s, f x = ∞ ↔ ∃ a ∈ s, f a = ∞ := - WithTop.sum_eq_top_iff +@[deprecated (since := "2024-08-25")] alias sum_lt_top_iff := sum_lt_top theorem lt_top_of_sum_ne_top {s : Finset α} {f : α → ℝ≥0∞} (h : ∑ x ∈ s, f x ≠ ∞) {a : α} (ha : a ∈ s) : f a < ∞ := - sum_lt_top_iff.1 h.lt_top a ha + sum_lt_top.1 h.lt_top a ha /-- Seeing `ℝ≥0∞` as `ℝ≥0` does not change their sum, unless one of the `ℝ≥0∞` is infinity -/ @@ -428,7 +429,7 @@ theorem toNNReal_sum {s : Finset α} {f : α → ℝ≥0∞} (hf : ∀ a ∈ s, rw [← coe_inj, coe_toNNReal, coe_finset_sum, sum_congr rfl] · intro x hx exact (coe_toNNReal (hf x hx)).symm - · exact (sum_lt_top hf).ne + · exact sum_ne_top.2 hf /-- seeing `ℝ≥0∞` as `Real` does not change their sum, unless one of the `ℝ≥0∞` is infinity -/ theorem toReal_sum {s : Finset α} {f : α → ℝ≥0∞} (hf : ∀ a ∈ s, f a ≠ ∞) : @@ -523,6 +524,15 @@ theorem smul_top {R} [Zero R] [SMulWithZero R ℝ≥0∞] [IsScalarTower R ℝ -- Porting note: need the primed version of `one_ne_zero` now simp_rw [smul_eq_zero, or_iff_left (one_ne_zero' ℝ≥0∞)] +lemma nnreal_smul_lt_top {x : ℝ≥0} {y : ℝ≥0∞} (hy : y < ⊤) : x • y < ⊤ := mul_lt_top (by simp) hy +lemma nnreal_smul_ne_top {x : ℝ≥0} {y : ℝ≥0∞} (hy : y ≠ ⊤) : x • y ≠ ⊤ := mul_ne_top (by simp) hy + +lemma nnreal_smul_ne_top_iff {x : ℝ≥0} {y : ℝ≥0∞} (hx : x ≠ 0) : x • y ≠ ⊤ ↔ y ≠ ⊤ := + ⟨by rintro h rfl; simp [smul_top, hx] at h, nnreal_smul_ne_top⟩ + +lemma nnreal_smul_lt_top_iff {x : ℝ≥0} {y : ℝ≥0∞} (hx : x ≠ 0) : x • y < ⊤ ↔ y < ⊤ := by + rw [lt_top_iff_ne_top, lt_top_iff_ne_top, nnreal_smul_ne_top_iff hx] + end Actions end ENNReal diff --git a/Mathlib/Data/ENNReal/Real.lean b/Mathlib/Data/ENNReal/Real.lean index d1cdba2b5cfd8..4b6df926ef130 100644 --- a/Mathlib/Data/ENNReal/Real.lean +++ b/Mathlib/Data/ENNReal/Real.lean @@ -360,7 +360,7 @@ theorem smul_toNNReal (a : ℝ≥0) (b : ℝ≥0∞) : (a • b).toNNReal = a * /-- `ENNReal.toNNReal` as a `MonoidHom`. -/ def toNNRealHom : ℝ≥0∞ →* ℝ≥0 where toFun := ENNReal.toNNReal - map_one' := toNNReal_coe + map_one' := toNNReal_coe _ map_mul' _ _ := toNNReal_mul @[simp] @@ -441,18 +441,18 @@ theorem toReal_pos_iff_ne_top (p : ℝ≥0∞) [Fact (1 ≤ p)] : 0 < p.toReal this rfl, fun h => zero_lt_one.trans_le (p.dichotomy.resolve_left h)⟩ -theorem toNNReal_inv (a : ℝ≥0∞) : a⁻¹.toNNReal = a.toNNReal⁻¹ := by +@[simp] theorem toNNReal_inv (a : ℝ≥0∞) : a⁻¹.toNNReal = a.toNNReal⁻¹ := by induction' a with a; · simp rcases eq_or_ne a 0 with (rfl | ha); · simp rw [← coe_inv ha, toNNReal_coe, toNNReal_coe] -theorem toNNReal_div (a b : ℝ≥0∞) : (a / b).toNNReal = a.toNNReal / b.toNNReal := by +@[simp] theorem toNNReal_div (a b : ℝ≥0∞) : (a / b).toNNReal = a.toNNReal / b.toNNReal := by rw [div_eq_mul_inv, toNNReal_mul, toNNReal_inv, div_eq_mul_inv] -theorem toReal_inv (a : ℝ≥0∞) : a⁻¹.toReal = a.toReal⁻¹ := by +@[simp] theorem toReal_inv (a : ℝ≥0∞) : a⁻¹.toReal = a.toReal⁻¹ := by simp only [ENNReal.toReal, toNNReal_inv, NNReal.coe_inv] -theorem toReal_div (a b : ℝ≥0∞) : (a / b).toReal = a.toReal / b.toReal := by +@[simp] theorem toReal_div (a b : ℝ≥0∞) : (a / b).toReal = a.toReal / b.toReal := by rw [div_eq_mul_inv, toReal_mul, toReal_inv, div_eq_mul_inv] theorem ofReal_prod_of_nonneg {α : Type*} {s : Finset α} {f : α → ℝ} (hf : ∀ i, i ∈ s → 0 ≤ f i) : diff --git a/Mathlib/Data/ENat/Basic.lean b/Mathlib/Data/ENat/Basic.lean index e641b878298b9..5854a9a681ac5 100644 --- a/Mathlib/Data/ENat/Basic.lean +++ b/Mathlib/Data/ENat/Basic.lean @@ -24,22 +24,16 @@ and `Nat.cast` coercion. If you need to apply a lemma about `WithTop`, you may e and forth using `ENat.some_eq_coe`, or restate the lemma for `ENat`. -/ -/-- Extended natural numbers `ℕ∞ = WithTop ℕ`. -/ -def ENat : Type := - WithTop ℕ -deriving Zero, +deriving instance Zero, CanonicallyOrderedCommSemiring, Nontrivial, + LinearOrder, Bot, CanonicallyLinearOrderedAddCommMonoid, Sub, + LinearOrderedAddCommMonoidWithTop, WellFoundedRelation + for ENat -- AddCommMonoidWithOne, - CanonicallyOrderedCommSemiring, Nontrivial, - LinearOrder, Bot, Top, CanonicallyLinearOrderedAddCommMonoid, Sub, - LinearOrderedAddCommMonoidWithTop, WellFoundedRelation, Inhabited -- OrderBot, OrderTop, OrderedSub, SuccOrder, WellFoundedLt, CharZero -- Porting Note: In `Data.Nat.ENatPart` proofs timed out when having -- the `deriving AddCommMonoidWithOne`, and it seems to work without. -/-- Extended natural numbers `ℕ∞ = WithTop ℕ`. -/ -notation "ℕ∞" => ENat - namespace ENat -- Porting note: instances that derive failed to find @@ -118,23 +112,6 @@ theorem toNat_top : toNat ⊤ = 0 := @[simp] theorem toNat_eq_zero : toNat n = 0 ↔ n = 0 ∨ n = ⊤ := WithTop.untop'_eq_self_iff --- Porting note (#11445): new definition copied from `WithTop` -/-- Recursor for `ENat` using the preferred forms `⊤` and `↑a`. -/ -@[elab_as_elim, induction_eliminator, cases_eliminator] -def recTopCoe {C : ℕ∞ → Sort*} (top : C ⊤) (coe : ∀ a : ℕ, C a) : ∀ n : ℕ∞, C n - | none => top - | Option.some a => coe a - -@[simp] -theorem recTopCoe_top {C : ℕ∞ → Sort*} (d : C ⊤) (f : ∀ a : ℕ, C a) : - @recTopCoe C d f ⊤ = d := - rfl - -@[simp] -theorem recTopCoe_coe {C : ℕ∞ → Sort*} (d : C ⊤) (f : ∀ a : ℕ, C a) (x : ℕ) : - @recTopCoe C d f ↑x = f x := - rfl - @[simp] theorem recTopCoe_zero {C : ℕ∞ → Sort*} (d : C ⊤) (f : ∀ a : ℕ, C a) : @recTopCoe C d f 0 = f 0 := rfl @@ -225,7 +202,11 @@ lemma toNat_le_toNat {m n : ℕ∞} (h : m ≤ n) (hn : n ≠ ⊤) : toNat m ≤ toNat_le_of_le_coe <| h.trans_eq (coe_toNat hn).symm @[simp] -theorem succ_def (m : ℕ∞) : Order.succ m = m + 1 := by cases m <;> rfl +theorem succ_def (m : ℕ∞) : Order.succ m = m + 1 := by + cases m + · rfl + · change ite .. = _ + simp theorem add_one_le_of_lt (h : m < n) : m + 1 ≤ n := m.succ_def ▸ Order.succ_le_of_lt h diff --git a/Mathlib/Data/Fin/Basic.lean b/Mathlib/Data/Fin/Basic.lean index 1eef0858bcbcf..aede754a4bba3 100644 --- a/Mathlib/Data/Fin/Basic.lean +++ b/Mathlib/Data/Fin/Basic.lean @@ -194,8 +194,6 @@ section Order ### order -/ - - theorem le_iff_val_le_val {a b : Fin n} : a ≤ b ↔ (a : ℕ) ≤ b := Iff.rfl @@ -404,12 +402,12 @@ alias val_nat_cast := val_natCast -- Porting note: is this the right name for things involving `Nat.cast`? /-- Converting an in-range number to `Fin (n + 1)` produces a result -whose value is the original number. -/ +whose value is the original number. -/ theorem val_cast_of_lt {n : ℕ} [NeZero n] {a : ℕ} (h : a < n) : (a : Fin n).val = a := Nat.mod_eq_of_lt h /-- If `n` is non-zero, converting the value of a `Fin n` to `Fin n` results -in the same value. -/ +in the same value. -/ @[simp] theorem cast_val_eq_self {n : ℕ} [NeZero n] (a : Fin n) : (a.val : Fin n) = a := Fin.ext <| val_cast_of_lt a.isLt @@ -535,7 +533,7 @@ lemma castAdd_injective (m n : ℕ) : Injective (@Fin.castAdd m n) := castLE_inj lemma castSucc_injective (n : ℕ) : Injective (@Fin.castSucc n) := castAdd_injective _ _ -/-- `Fin.castLE` as an `Embedding`, `castLEEmb h i` embeds `i` into a larger `Fin` type. -/ +/-- `Fin.castLE` as an `Embedding`, `castLEEmb h i` embeds `i` into a larger `Fin` type. -/ @[simps! apply] def castLEEmb (h : n ≤ m) : Fin n ↪ Fin m where toFun := castLE h @@ -759,8 +757,6 @@ section Pred ### pred -/ - - theorem pred_one' [NeZero n] (h := (zero_ne_one' (n := n)).symm) : Fin.pred (1 : Fin (n + 1)) h = 0 := by simp_rw [Fin.ext_iff, coe_pred, val_one', val_zero', Nat.sub_eq_zero_iff_le, Nat.mod_le] @@ -1435,7 +1431,8 @@ instance uniqueFinOne : Unique (Fin 1) where 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] using hi) + fin_two_eq_of_eq_zero_iff + (by simpa only [one_eq_zero_iff, succ.injEq, iff_false, reduceCtorEq] using hi) @[simp] theorem coe_neg_one : ↑(-1 : Fin (n + 1)) = n := by @@ -1523,3 +1520,5 @@ instance toExpr (n : ℕ) : Lean.ToExpr (Fin n) where q(OfNat.ofNat $i) end Fin + +set_option linter.style.longFile 1700 diff --git a/Mathlib/Data/Fin/Tuple/Basic.lean b/Mathlib/Data/Fin/Tuple/Basic.lean index 0bb5943fae65c..0f9f303f592bb 100644 --- a/Mathlib/Data/Fin/Tuple/Basic.lean +++ b/Mathlib/Data/Fin/Tuple/Basic.lean @@ -5,7 +5,6 @@ Authors: Floris van Doorn, Yury Kudryashov, Sébastien Gouëzel, Chris Hughes -/ import Mathlib.Data.Fin.Basic import Mathlib.Data.Nat.Find -import Batteries.Data.Fin.Lemmas /-! # Operation on tuples @@ -724,9 +723,37 @@ def succAboveCases {α : Fin (n + 1) → Sort u} (i : Fin (n + 1)) (x : α i) else @Eq.recOn _ _ (fun x _ ↦ α x) _ (succAbove_pred_of_lt _ _ <| (Fin.lt_or_lt_of_ne hj).resolve_left hlt) (p _) -theorem forall_iff_succAbove {p : Fin (n + 1) → Prop} (i : Fin (n + 1)) : - (∀ j, p j) ↔ p i ∧ ∀ j, p (i.succAbove j) := - ⟨fun h ↦ ⟨h _, fun _ ↦ h _⟩, fun h ↦ succAboveCases i h.1 h.2⟩ +-- This is a duplicate of `Fin.exists_fin_succ` in Core. We should upstream the name change. +alias forall_iff_succ := forall_fin_succ + +-- This is a duplicate of `Fin.exists_fin_succ` in Core. We should upstream the name change. +alias exists_iff_succ := exists_fin_succ + +lemma forall_iff_castSucc {P : Fin (n + 1) → Prop} : + (∀ i, P i) ↔ P (last n) ∧ ∀ i, P (castSucc i) := + ⟨fun h ↦ ⟨h _, fun _ ↦ h _⟩, fun h ↦ lastCases h.1 h.2⟩ + +lemma exists_iff_castSucc {P : Fin (n + 1) → Prop} : + (∃ i, P i) ↔ P (last n) ∨ ∃ i, P (castSucc i) where + mp := by + rintro ⟨i, hi⟩ + induction' i using lastCases + · exact .inl hi + · exact .inr ⟨_, hi⟩ + mpr := by rintro (h | ⟨i, hi⟩) <;> exact ⟨_, ‹_›⟩ + +theorem forall_iff_succAbove {P : Fin (n + 1) → Prop} (p : Fin (n + 1)) : + (∀ i, P i) ↔ P p ∧ ∀ i, P (p.succAbove i) := + ⟨fun h ↦ ⟨h _, fun _ ↦ h _⟩, fun h ↦ succAboveCases p h.1 h.2⟩ + +lemma exists_iff_succAbove {P : Fin (n + 1) → Prop} (p : Fin (n + 1)) : + (∃ i, P i) ↔ P p ∨ ∃ i, P (p.succAbove i) where + mp := by + rintro ⟨i, hi⟩ + induction' i using p.succAboveCases + · exact .inl hi + · exact .inr ⟨_, hi⟩ + mpr := by rintro (h | ⟨i, hi⟩) <;> exact ⟨_, ‹_›⟩ /-- Remove the `p`-th entry of a tuple. -/ def removeNth (p : Fin (n + 1)) (f : ∀ i, α i) : ∀ i, α (p.succAbove i) := fun i ↦ f (p.succAbove i) diff --git a/Mathlib/Data/Fin/Tuple/Finset.lean b/Mathlib/Data/Fin/Tuple/Finset.lean index 103c2df7fa9f0..5d845ab373afb 100644 --- a/Mathlib/Data/Fin/Tuple/Finset.lean +++ b/Mathlib/Data/Fin/Tuple/Finset.lean @@ -17,11 +17,11 @@ variable {n : ℕ} {α : Fin (n + 1) → Type*} lemma mem_piFinset_succ {x : ∀ i, α i} {s : ∀ i, Finset (α i)} : x ∈ piFinset s ↔ x 0 ∈ s 0 ∧ tail x ∈ piFinset (tail s) := by - simp only [mem_piFinset, forall_fin_succ, tail] + simp only [mem_piFinset, forall_iff_succ, tail] lemma mem_piFinset_succ' {x : ∀ i, α i} {s : ∀ i, Finset (α i)} : - x ∈ piFinset s ↔ init x ∈ piFinset (init s) ∧ x (last n) ∈ s (last n) := by - simp only [mem_piFinset, forall_fin_succ', init] + x ∈ piFinset s ↔ x (last n) ∈ s (last n) ∧ init x ∈ piFinset (init s) := by + simp only [mem_piFinset, forall_iff_castSucc, init] lemma cons_mem_piFinset_cons {x₀ : α 0} {x : ∀ i : Fin n, α i.succ} {s₀ : Finset (α 0)} {s : ∀ i : Fin n, Finset (α i.succ)} : @@ -30,7 +30,7 @@ lemma cons_mem_piFinset_cons {x₀ : α 0} {x : ∀ i : Fin n, α i.succ} lemma snoc_mem_piFinset_snoc {x : ∀ i : Fin n, α i.castSucc} {xₙ : α (.last n)} {s : ∀ i : Fin n, Finset (α i.castSucc)} {sₙ : Finset (α <| .last n)} : - snoc x xₙ ∈ piFinset (snoc s sₙ) ↔ x ∈ piFinset s ∧ xₙ ∈ sₙ := by + snoc x xₙ ∈ piFinset (snoc s sₙ) ↔ xₙ ∈ sₙ ∧ x ∈ piFinset s := by simp_rw [mem_piFinset_succ', init_snoc, snoc_last] end Fin diff --git a/Mathlib/Data/Fin/VecNotation.lean b/Mathlib/Data/Fin/VecNotation.lean index fa80efe84fef3..d3b561640f0ae 100644 --- a/Mathlib/Data/Fin/VecNotation.lean +++ b/Mathlib/Data/Fin/VecNotation.lean @@ -171,7 +171,7 @@ theorem range_cons_cons_empty (x y : α) (u : Fin 0 → α) : @[simp] theorem vecCons_const (a : α) : (vecCons a fun _ : Fin n => a) = fun _ => a := - funext <| Fin.forall_fin_succ.2 ⟨rfl, cons_val_succ _ _⟩ + funext <| Fin.forall_iff_succ.2 ⟨rfl, cons_val_succ _ _⟩ theorem vec_single_eq_const (a : α) : ![a] = fun _ => a := let _ : Unique (Fin 1) := inferInstance @@ -208,8 +208,7 @@ theorem cons_val_fin_one (x : α) (u : Fin 0 → α) : ∀ (i : Fin 1), vecCons theorem cons_fin_one (x : α) (u : Fin 0 → α) : vecCons x u = fun _ => x := funext (cons_val_fin_one x u) -open Lean in -open Qq in +open Lean Qq in protected instance _root_.PiFin.toExpr [ToLevel.{u}] [ToExpr α] (n : ℕ) : ToExpr (Fin n → α) := have lu := toLevel.{u} have eα : Q(Type $lu) := toTypeExpr α diff --git a/Mathlib/Data/Finite/Card.lean b/Mathlib/Data/Finite/Card.lean index e13bf96384a2c..c16b94bbcd01b 100644 --- a/Mathlib/Data/Finite/Card.lean +++ b/Mathlib/Data/Finite/Card.lean @@ -206,4 +206,8 @@ theorem equiv_image_eq_iff_subset (e : α ≃ α) (hs : s.Finite) : e '' s = s end Finite +theorem eq_top_of_card_le_of_finite [Finite α] {s : Set α} (h : Nat.card α ≤ Nat.card s) : s = ⊤ := + Set.Finite.eq_of_subset_of_card_le univ.toFinite (subset_univ s) <| + Nat.card_congr (Equiv.Set.univ α) ▸ h + end Set diff --git a/Mathlib/Data/Finmap.lean b/Mathlib/Data/Finmap.lean index fb4a761948449..ed5e6a411c850 100644 --- a/Mathlib/Data/Finmap.lean +++ b/Mathlib/Data/Finmap.lean @@ -17,7 +17,7 @@ open List variable {α : Type u} {β : α → Type v} -/-! ### Multisets of sigma types-/ +/-! ### Multisets of sigma types -/ namespace Multiset @@ -151,7 +151,7 @@ theorem ext_iff' {s t : Finmap β} : s.entries = t.entries ↔ s = t := /-- The predicate `a ∈ s` means that `s` has a value associated to the key `a`. -/ instance : Membership α (Finmap β) := - ⟨fun a s => a ∈ s.entries.keys⟩ + ⟨fun s a => a ∈ s.entries.keys⟩ theorem mem_def {a : α} {s : Finmap β} : a ∈ s ↔ a ∈ s.entries.keys := Iff.rfl diff --git a/Mathlib/Data/Finset/Basic.lean b/Mathlib/Data/Finset/Basic.lean index e421e88c289c7..07d86ddb5847a 100644 --- a/Mathlib/Data/Finset/Basic.lean +++ b/Mathlib/Data/Finset/Basic.lean @@ -105,8 +105,9 @@ In Lean, we use lattice notation to talk about things involving unions and inter ### Equivalences between finsets -* The `Mathlib/Data/Equiv.lean` files describe a general type of equivalence, so look in there for - any lemmas. There is some API for rewriting sums and products from `s` to `t` given that `s ≃ t`. +* The `Mathlib/Logic/Equiv/Defs.lean` files describe a general type of equivalence, so look in there + for any lemmas. There is some API for rewriting sums and products from `s` to `t` given that + `s ≃ t`. TODO: examples ## Tags @@ -163,7 +164,7 @@ instance decidableEq [DecidableEq α] : DecidableEq (Finset α) instance : Membership α (Finset α) := - ⟨fun a s => a ∈ s.1⟩ + ⟨fun s a => a ∈ s.1⟩ theorem mem_def {a : α} {s : Finset α} : a ∈ s ↔ a ∈ s.1 := Iff.rfl @@ -214,17 +215,13 @@ instance decidableMem' [DecidableEq α] (a : α) (s : Finset α) : Decidable (a /-! ### extensionality -/ - -theorem ext_iff {s₁ s₂ : Finset α} : s₁ = s₂ ↔ ∀ a, a ∈ s₁ ↔ a ∈ s₂ := - val_inj.symm.trans <| s₁.nodup.ext s₂.nodup - @[ext] -theorem ext {s₁ s₂ : Finset α} : (∀ a, a ∈ s₁ ↔ a ∈ s₂) → s₁ = s₂ := - ext_iff.2 +theorem ext {s₁ s₂ : Finset α} (h : ∀ a, a ∈ s₁ ↔ a ∈ s₂) : s₁ = s₂ := + (val_inj.symm.trans <| s₁.nodup.ext s₂.nodup).mpr h @[simp, norm_cast] theorem coe_inj {s₁ s₂ : Finset α} : (s₁ : Set α) = s₂ ↔ s₁ = s₂ := - Set.ext_iff.trans ext_iff.symm + Set.ext_iff.trans Finset.ext_iff.symm theorem coe_injective {α} : Injective ((↑) : Finset α → Set α) := fun _s _t => coe_inj.1 @@ -1041,7 +1038,7 @@ theorem insert_subset_insert (a : α) {s t : Finset α} (h : s ⊆ t) : insert a simp_rw [← coe_subset]; simp [-coe_subset, ha] theorem insert_inj (ha : a ∉ s) : insert a s = insert b s ↔ a = b := - ⟨fun h => eq_of_not_mem_of_mem_insert (h.subst <| mem_insert_self _ _) ha, congr_arg (insert · s)⟩ + ⟨fun h => eq_of_not_mem_of_mem_insert (h ▸ mem_insert_self _ _) ha, congr_arg (insert · s)⟩ theorem insert_inj_on (s : Finset α) : Set.InjOn (fun a => insert a s) sᶜ := fun _ h _ _ => (insert_inj h).1 @@ -1445,6 +1442,10 @@ theorem singleton_inter_of_not_mem {a : α} {s : Finset α} (H : a ∉ s) : {a} eq_empty_of_forall_not_mem <| by simp only [mem_inter, mem_singleton]; rintro x ⟨rfl, h⟩; exact H h +lemma singleton_inter {a : α} {s : Finset α} : + {a} ∩ s = if a ∈ s then {a} else ∅ := by + split_ifs with h <;> simp [h] + @[simp] theorem inter_singleton_of_mem {a : α} {s : Finset α} (h : a ∈ s) : s ∩ {a} = {a} := by rw [inter_comm, singleton_inter_of_mem h] @@ -1453,6 +1454,10 @@ theorem inter_singleton_of_mem {a : α} {s : Finset α} (h : a ∈ s) : s ∩ {a theorem inter_singleton_of_not_mem {a : α} {s : Finset α} (h : a ∉ s) : s ∩ {a} = ∅ := by rw [inter_comm, singleton_inter_of_not_mem h] +lemma inter_singleton {a : α} {s : Finset α} : + s ∩ {a} = if a ∈ s then {a} else ∅ := by + split_ifs with h <;> simp [h] + @[mono, gcongr] theorem inter_subset_inter {x y s t : Finset α} (h : x ⊆ y) (h' : s ⊆ t) : x ∩ s ⊆ y ∩ t := by intro a a_in @@ -1764,11 +1769,11 @@ theorem inter_sdiff_self (s₁ s₂ : Finset α) : s₁ ∩ (s₂ \ s₁) = ∅ instance : GeneralizedBooleanAlgebra (Finset α) := { sup_inf_sdiff := fun x y => by - simp only [ext_iff, mem_union, mem_sdiff, inf_eq_inter, sup_eq_union, mem_inter, + simp only [Finset.ext_iff, mem_union, mem_sdiff, inf_eq_inter, sup_eq_union, mem_inter, ← and_or_left, em, and_true, implies_true] inf_inf_sdiff := fun x y => by - simp only [ext_iff, inter_sdiff_self, inter_empty, inter_assoc, false_iff_iff, inf_eq_inter, - not_mem_empty, bot_eq_empty, not_false_iff, implies_true] } + simp only [Finset.ext_iff, inter_sdiff_self, inter_empty, inter_assoc, false_iff_iff, + inf_eq_inter, not_mem_empty, bot_eq_empty, not_false_iff, implies_true] } theorem not_mem_sdiff_of_mem_right (h : a ∈ t) : a ∉ s \ t := by simp only [mem_sdiff, h, not_true, not_false_iff, and_false_iff] @@ -2179,7 +2184,7 @@ def knownToBeFinsetNotSet (expectedType? : Option Expr) : TermElabM Bool := `Finset ?α` or the expected type is not `Set ?α` and `s` has expected type `Finset ?α`. See also -* `Init.Set` for the `Set` builder notation elaborator that this elaborator partly overrides. +* `Data.Set.Defs` for the `Set` builder notation elaborator that this elaborator partly overrides. * `Data.Fintype.Basic` for the `Finset` builder notation elaborator handling syntax of the form `{x | p x}`, `{x : α | p x}`, `{x ∉ s | p x}`, `{x ≠ a | p x}`. * `Order.LocallyFinite.Basic` for the `Finset` builder notation elaborator handling syntax of the @@ -2493,9 +2498,11 @@ theorem filter_union_filter_neg_eq [∀ x, Decidable (¬p x)] (s : Finset α) : end -lemma filter_inj : s.filter p = t.filter p ↔ ∀ ⦃a⦄, p a → (a ∈ s ↔ a ∈ t) := by simp [ext_iff] +lemma filter_inj : s.filter p = t.filter p ↔ ∀ ⦃a⦄, p a → (a ∈ s ↔ a ∈ t) := by + simp [Finset.ext_iff] -lemma filter_inj' : s.filter p = s.filter q ↔ ∀ ⦃a⦄, a ∈ s → (p a ↔ q a) := by simp [ext_iff] +lemma filter_inj' : s.filter p = s.filter q ↔ ∀ ⦃a⦄, a ∈ s → (p a ↔ q a) := by + simp [Finset.ext_iff] end Filter @@ -3063,3 +3070,5 @@ def proveFinsetNonempty {u : Level} {α : Q(Type u)} (s : Q(Finset $α)) : Lean.getExprMVarAssignment? mvar end Mathlib.Meta + +set_option linter.style.longFile 3100 diff --git a/Mathlib/Data/Finset/Density.lean b/Mathlib/Data/Finset/Density.lean index 30ed02c7deba6..43125f7fcc4f3 100644 --- a/Mathlib/Data/Finset/Density.lean +++ b/Mathlib/Data/Finset/Density.lean @@ -4,8 +4,9 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies -/ import Mathlib.Algebra.Order.Field.Basic -import Mathlib.Algebra.Order.Field.Rat import Mathlib.Data.Fintype.Card +import Mathlib.Data.NNRat.Order +import Mathlib.Data.Rat.Cast.CharZero /-! # Density of a finite set @@ -102,6 +103,36 @@ lemma dens_map_le [Fintype β] (f : α ↪ β) : dens (s.map f) ≤ dens s := by · exact mod_cast Fintype.card_pos · exact Fintype.card_le_of_injective _ f.2 +@[simp] lemma dens_map_equiv [Fintype β] (e : α ≃ β) : (s.map e.toEmbedding).dens = s.dens := by + simp [dens, Fintype.card_congr e] + +lemma dens_image [Fintype β] [DecidableEq β] {f : α → β} (hf : Bijective f) (s : Finset α) : + (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 + 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 + 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 + +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] + +end Semifield + section Nonempty variable [Nonempty α] @@ -114,6 +145,11 @@ lemma dens_ne_one : dens s ≠ 1 ↔ s ≠ univ := dens_eq_one.not end Nonempty +@[simp] lemma dens_le_one : s.dens ≤ 1 := by + cases isEmpty_or_nonempty α + · simp [Subsingleton.elim s ∅] + · simpa using dens_le_dens s.subset_univ + section Lattice variable [DecidableEq α] diff --git a/Mathlib/Data/Finset/Image.lean b/Mathlib/Data/Finset/Image.lean index f659fdf322788..4008aa95219f0 100644 --- a/Mathlib/Data/Finset/Image.lean +++ b/Mathlib/Data/Finset/Image.lean @@ -129,7 +129,7 @@ theorem map_map (f : α ↪ β) (g : β ↪ γ) (s : Finset α) : (s.map f).map theorem map_comm {β'} {f : β ↪ γ} {g : α ↪ β} {f' : α ↪ β'} {g' : β' ↪ γ} (h_comm : ∀ a, f (g a) = g' (f' a)) : (s.map g).map f = (s.map f').map g' := by - simp_rw [map_map, Embedding.trans, Function.comp, h_comm] + simp_rw [map_map, Embedding.trans, Function.comp_def, h_comm] theorem _root_.Function.Semiconj.finset_map {f : α ↪ β} {ga : α ↪ α} {gb : β ↪ β} (h : Function.Semiconj f ga gb) : Function.Semiconj (map f) (map ga) (map gb) := fun _ => @@ -186,7 +186,7 @@ theorem filter_map {p : β → Prop} [DecidablePred p] : lemma map_filter' (p : α → Prop) [DecidablePred p] (f : α ↪ β) (s : Finset α) [DecidablePred (∃ a, p a ∧ f a = ·)] : (s.filter p).map f = (s.map f).filter fun b => ∃ a, p a ∧ f a = b := by - simp [(· ∘ ·), filter_map, f.injective.eq_iff] + simp [Function.comp_def, filter_map, f.injective.eq_iff] lemma filter_attach' [DecidableEq α] (s : Finset α) (p : s → Prop) [DecidablePred p] : s.attach.filter p = @@ -201,7 +201,7 @@ lemma filter_attach (p : α → Prop) [DecidablePred p] (s : Finset α) : theorem map_filter {f : α ≃ β} {p : α → Prop} [DecidablePred p] : (s.filter p).map f.toEmbedding = (s.map f.toEmbedding).filter (p ∘ f.symm) := by - simp only [filter_map, Function.comp, Equiv.toEmbedding_apply, Equiv.symm_apply_apply] + simp only [filter_map, Function.comp_def, Equiv.toEmbedding_apply, Equiv.symm_apply_apply] @[simp] theorem disjoint_map {s t : Finset α} (f : α ↪ β) : @@ -392,7 +392,7 @@ theorem image_image [DecidableEq γ] {g : β → γ} : (s.image f).image g = s.i theorem image_comm {β'} [DecidableEq β'] [DecidableEq γ] {f : β → γ} {g : α → β} {f' : α → β'} {g' : β' → γ} (h_comm : ∀ a, f (g a) = g' (f' a)) : - (s.image g).image f = (s.image f').image g' := by simp_rw [image_image, comp, h_comm] + (s.image g).image f = (s.image f').image g' := by simp_rw [image_image, comp_def, h_comm] theorem _root_.Function.Semiconj.finset_image [DecidableEq α] {f : α → β} {ga : α → α} {gb : β → β} (h : Function.Semiconj f ga gb) : Function.Semiconj (image f) (image ga) (image gb) := fun _ => @@ -633,7 +633,7 @@ theorem mem_subtype {p : α → Prop} [DecidablePred p] {s : Finset α} : | ⟨a, ha⟩ => by simp [Finset.subtype, ha] theorem subtype_eq_empty {p : α → Prop} [DecidablePred p] {s : Finset α} : - s.subtype p = ∅ ↔ ∀ x, p x → x ∉ s := by simp [ext_iff, Subtype.forall, Subtype.coe_mk] + s.subtype p = ∅ ↔ ∀ x, p x → x ∉ s := by simp [Finset.ext_iff, Subtype.forall, Subtype.coe_mk] @[mono] theorem subtype_mono {p : α → Prop} [DecidablePred p] : Monotone (Finset.subtype p) := diff --git a/Mathlib/Data/Finset/Lattice.lean b/Mathlib/Data/Finset/Lattice.lean index 9cb9fd5e3090c..452204c7d625f 100644 --- a/Mathlib/Data/Finset/Lattice.lean +++ b/Mathlib/Data/Finset/Lattice.lean @@ -18,7 +18,6 @@ import Mathlib.Order.Nat # Lattice operations on finsets -/ --- TODO: assert_not_exists OrderedCommMonoid assert_not_exists MonoidWithZero @@ -521,7 +520,7 @@ theorem inf_sup {κ : ι → Type*} (s : Finset ι) (t : ∀ i, Finset (κ i)) ( -- Porting note: `simpa` doesn't support placeholders in proof terms have := h (fun j hj => if hji : j = i then cast (congr_arg κ hji.symm) a else g _ <| mem_of_mem_insert_of_ne hj hji) (fun j hj => ?_) - · simpa only [cast_eq, dif_pos, Function.comp, Subtype.coe_mk, dif_neg, aux] using this + · simpa only [cast_eq, dif_pos, Function.comp_def, Subtype.coe_mk, dif_neg, aux] using this rw [mem_insert] at hj obtain (rfl | hj) := hj · simpa @@ -1306,14 +1305,14 @@ protected theorem le_min_iff {m : WithTop α} {s : Finset α} : m ≤ s.min ↔ 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`, +/-- 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`, +/-- 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 @@ -1952,3 +1951,5 @@ theorem set_biInter_biUnion (s : Finset γ) (t : γ → Finset α) (f : α → S iInf_biUnion s t f end Finset + +set_option linter.style.longFile 2100 diff --git a/Mathlib/Data/Finset/MulAntidiagonal.lean b/Mathlib/Data/Finset/MulAntidiagonal.lean index 683d02323b1ff..d361b2e348cd7 100644 --- a/Mathlib/Data/Finset/MulAntidiagonal.lean +++ b/Mathlib/Data/Finset/MulAntidiagonal.lean @@ -3,8 +3,8 @@ 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.Order.Monoid.Defs -import Mathlib.Data.Set.Pointwise.Basic import Mathlib.Data.Set.MulAntidiagonal /-! # Multiplication antidiagonal as a `Finset`. diff --git a/Mathlib/Data/Finset/NoncommProd.lean b/Mathlib/Data/Finset/NoncommProd.lean index 16af175533226..61a09de161041 100644 --- a/Mathlib/Data/Finset/NoncommProd.lean +++ b/Mathlib/Data/Finset/NoncommProd.lean @@ -48,7 +48,7 @@ def noncommFoldr (s : Multiset α) @[simp] theorem noncommFoldr_coe (l : List α) (comm) (b : β) : noncommFoldr f (l : Multiset α) comm b = l.foldr f b := by - simp only [noncommFoldr, coe_foldr, coe_attach, List.attach, List.attachWith, Function.comp] + simp only [noncommFoldr, coe_foldr, coe_attach, List.attach, List.attachWith, Function.comp_def] rw [← List.foldr_map] simp [List.map_pmap] diff --git a/Mathlib/Data/Finset/PiInduction.lean b/Mathlib/Data/Finset/PiInduction.lean index d040789ab2d0d..4eb4a769d4e6a 100644 --- a/Mathlib/Data/Finset/PiInduction.lean +++ b/Mathlib/Data/Finset/PiInduction.lean @@ -65,7 +65,7 @@ maps provided that it is true on `fun _ ↦ ∅` and for any function `g : ∀ i `i : ι`, and `x ∉ g i`, `p g` implies `p (update g i (insert x (g i)))`. See also `Finset.induction_on_pi_max` and `Finset.induction_on_pi_min` for specialized versions -that require `∀ i, LinearOrder (α i)`. -/ +that require `∀ i, LinearOrder (α i)`. -/ theorem induction_on_pi {p : (∀ i, Finset (α i)) → Prop} (f : ∀ i, Finset (α i)) (h0 : p fun _ ↦ ∅) (step : ∀ (g : ∀ i, Finset (α i)) (i : ι), ∀ x ∉ g i, p g → p (update g i (insert x (g i)))) : p f := diff --git a/Mathlib/Data/Finset/Pointwise/Basic.lean b/Mathlib/Data/Finset/Pointwise/Basic.lean index ffbddd2367556..0ed2c95d8cb3c 100644 --- a/Mathlib/Data/Finset/Pointwise/Basic.lean +++ b/Mathlib/Data/Finset/Pointwise/Basic.lean @@ -3,15 +3,13 @@ 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.BigOperators.Group.Finset import Mathlib.Algebra.Group.Action.Pi +import Mathlib.Algebra.Order.Ring.Nat +import Mathlib.Algebra.Ring.Pointwise.Set import Mathlib.Data.Finset.NAry -import Mathlib.Data.Finset.Preimage import Mathlib.Data.Set.Pointwise.Finite -import Mathlib.Data.Set.Pointwise.SMul import Mathlib.Data.Set.Pointwise.ListOfFn -import Mathlib.Data.ULift -import Mathlib.Algebra.BigOperators.Group.Finset -import Mathlib.Algebra.Order.Ring.Nat /-! # Pointwise operations of finsets @@ -772,10 +770,9 @@ scoped[Pointwise] attribute [instance] Finset.monoid Finset.addMonoid @[to_additive] theorem pow_mem_pow (ha : a ∈ s) : ∀ n : ℕ, a ^ n ∈ s ^ n | 0 => by - rw [pow_zero] - exact one_mem_one + simp only [pow_zero, mem_one] | n + 1 => by - rw [pow_succ] + simp only [pow_succ] exact mul_mem_mul (pow_mem_pow ha n) ha @[to_additive] @@ -1420,7 +1417,7 @@ instance smulCommClass [SMul α γ] [SMul β γ] [SMulCommClass α β γ] : @[to_additive vaddAssocClass] instance isScalarTower [SMul α β] [SMul α γ] [SMul β γ] [IsScalarTower α β γ] : IsScalarTower α β (Finset γ) := - ⟨fun a b s => by simp only [← image_smul, image_image, smul_assoc, Function.comp]⟩ + ⟨fun a b s => by simp only [← image_smul, image_image, smul_assoc, Function.comp_def]⟩ variable [DecidableEq β] @@ -1828,7 +1825,7 @@ variable [Monoid α] [AddGroup β] [DistribMulAction α β] [DecidableEq β] (a @[simp] theorem smul_finset_neg : a • -t = -(a • t) := by - simp only [← image_smul, ← image_neg, Function.comp, image_image, smul_neg] + simp only [← image_smul, ← image_neg, Function.comp_def, image_image, smul_neg] @[simp] protected theorem smul_neg : s • -t = -(s • t) := by @@ -1844,7 +1841,7 @@ variable [Ring α] [AddCommGroup β] [Module α β] [DecidableEq β] {s : Finset @[simp] theorem neg_smul_finset : -a • t = -(a • t) := by - simp only [← image_smul, ← image_neg, image_image, neg_smul, Function.comp] + simp only [← image_smul, ← image_neg, image_image, neg_smul, Function.comp_def] @[simp] protected theorem neg_smul [DecidableEq α] : -s • t = -(s • t) := by @@ -1913,6 +1910,10 @@ namespace Set section One +-- Redeclaring an instance for better keys +@[to_additive] +instance instFintypeOne [One α] : Fintype (1 : Set α) := Set.fintypeSingleton _ + variable [One α] @[to_additive (attr := simp)] @@ -1995,3 +1996,5 @@ instance Nat.decidablePred_mem_vadd_set {s : Set ℕ} [DecidablePred (· ∈ s)] DecidablePred (· ∈ a +ᵥ s) := fun n ↦ decidable_of_iff' (a ≤ n ∧ n - a ∈ s) <| by simp only [Set.mem_vadd_set, vadd_eq_add]; aesop + +set_option linter.style.longFile 2100 diff --git a/Mathlib/Data/Finset/Preimage.lean b/Mathlib/Data/Finset/Preimage.lean index d5c3ba82dd978..840e7e2c93e3e 100644 --- a/Mathlib/Data/Finset/Preimage.lean +++ b/Mathlib/Data/Finset/Preimage.lean @@ -21,7 +21,7 @@ namespace Finset section Preimage -/-- Preimage of `s : Finset β` under a map `f` injective on `f ⁻¹' s` as a `Finset`. -/ +/-- Preimage of `s : Finset β` under a map `f` injective on `f ⁻¹' s` as a `Finset`. -/ noncomputable def preimage (s : Finset β) (f : α → β) (hf : Set.InjOn f (f ⁻¹' ↑s)) : Finset α := (s.finite_toSet.preimage hf).toFinset diff --git a/Mathlib/Data/Finset/Sort.lean b/Mathlib/Data/Finset/Sort.lean index 418f537711a77..a8cf2ef2b5057 100644 --- a/Mathlib/Data/Finset/Sort.lean +++ b/Mathlib/Data/Finset/Sort.lean @@ -117,13 +117,13 @@ theorem sorted_last_eq_max' {s : Finset α} {h : (s.sort (· ≤ ·)).length - 1 < (s.sort (· ≤ ·)).length} : (s.sort (· ≤ ·))[(s.sort (· ≤ ·)).length - 1] = s.max' (by rw [length_sort] at h; exact card_pos.1 (lt_of_le_of_lt bot_le h)) := - sorted_last_eq_max'_aux _ _ _ + sorted_last_eq_max'_aux _ h _ theorem max'_eq_sorted_last {s : Finset α} {h : s.Nonempty} : s.max' h = (s.sort (· ≤ ·))[(s.sort (· ≤ ·)).length - 1]' (by simpa using Nat.sub_lt (card_pos.mpr h) Nat.zero_lt_one) := - (sorted_last_eq_max'_aux _ _ _).symm + (sorted_last_eq_max'_aux _ (by simpa using Nat.sub_lt (card_pos.mpr h) Nat.zero_lt_one) _).symm /-- Given a finset `s` of cardinality `k` in a linear order `α`, the map `orderIsoOfFin s h` is the increasing bijection between `Fin k` and `s` as an `OrderIso`. Here, `h` is a proof that @@ -241,3 +241,21 @@ theorem sort_univ (n : ℕ) : Finset.univ.sort (fun x y : Fin n => x ≤ y) = Li (List.pairwise_le_finRange n) end Fin + +/-- Given a `Fintype` `α` of cardinality `k`, the map `orderIsoFinOfCardEq s h` is the increasing +bijection between `Fin k` and `α` as an `OrderIso`. Here, `h` is a proof that the cardinality of `α` +is `k`. We use this instead of an iso `Fin (Fintype.card α) ≃o α` to avoid casting issues in further +uses of this function. -/ +def Fintype.orderIsoFinOfCardEq + (α : Type*) [LinearOrder α] [Fintype α] {k : ℕ} (h : Fintype.card α = k) : + Fin k ≃o α := + (Finset.univ.orderIsoOfFin h).trans + ((OrderIso.setCongr _ _ Finset.coe_univ).trans OrderIso.Set.univ) + +/-- Any finite linear order order-embeds into any infinite linear order. -/ +lemma nonempty_orderEmbedding_of_finite_infinite + (α : Type*) [LinearOrder α] [hα : Finite α] + (β : Type*) [LinearOrder β] [hβ : Infinite β] : Nonempty (α ↪o β) := by + haveI := Fintype.ofFinite α + obtain ⟨s, hs⟩ := Infinite.exists_subset_card_eq β (Fintype.card α) + exact ⟨((Fintype.orderIsoFinOfCardEq α rfl).symm.toOrderEmbedding).trans (s.orderEmbOfFin hs)⟩ diff --git a/Mathlib/Data/Finset/Sum.lean b/Mathlib/Data/Finset/Sum.lean index b07e704317ad9..f9863829696b5 100644 --- a/Mathlib/Data/Finset/Sum.lean +++ b/Mathlib/Data/Finset/Sum.lean @@ -68,7 +68,7 @@ theorem inr_mem_disjSum : inr b ∈ s.disjSum t ↔ b ∈ t := Multiset.inr_mem_disjSum @[simp] -theorem disjSum_eq_empty : s.disjSum t = ∅ ↔ s = ∅ ∧ t = ∅ := by simp [ext_iff] +theorem disjSum_eq_empty : s.disjSum t = ∅ ↔ s = ∅ ∧ t = ∅ := by simp [Finset.ext_iff] theorem disjSum_mono (hs : s₁ ⊆ s₂) (ht : t₁ ⊆ t₂) : s₁.disjSum t₁ ⊆ s₂.disjSum t₂ := val_le_iff.1 <| Multiset.disjSum_mono (val_le_iff.2 hs) (val_le_iff.2 ht) diff --git a/Mathlib/Data/Finsupp/Basic.lean b/Mathlib/Data/Finsupp/Basic.lean index 30a1877ed23d9..17123acc6aff6 100644 --- a/Mathlib/Data/Finsupp/Basic.lean +++ b/Mathlib/Data/Finsupp/Basic.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl, Scott Morrison -/ import Mathlib.Algebra.BigOperators.Finsupp +import Mathlib.Algebra.Group.Action.Basic import Mathlib.Algebra.Module.Basic import Mathlib.Algebra.Regular.SMul import Mathlib.Data.Rat.BigOperators @@ -84,7 +85,8 @@ theorem not_mem_graph_snd_zero (a : α) (f : α →₀ M) : (a, (0 : M)) ∉ f.g @[simp] theorem image_fst_graph [DecidableEq α] (f : α →₀ M) : f.graph.image Prod.fst = f.support := by - classical simp only [graph, map_eq_image, image_image, Embedding.coeFn_mk, (· ∘ ·), image_id'] + classical + simp only [graph, map_eq_image, image_image, Embedding.coeFn_mk, Function.comp_def, image_id'] theorem graph_injective (α M) [Zero M] : Injective (@graph α M _) := by intro f g h @@ -1701,3 +1703,5 @@ theorem sigmaFinsuppAddEquivPiFinsupp_apply {α : Type*} {ιs : η → Type*} [A end Sigma end Finsupp + +set_option linter.style.longFile 1900 diff --git a/Mathlib/Data/Finsupp/Defs.lean b/Mathlib/Data/Finsupp/Defs.lean index c58fab65e2979..4e65162454d8b 100644 --- a/Mathlib/Data/Finsupp/Defs.lean +++ b/Mathlib/Data/Finsupp/Defs.lean @@ -23,7 +23,7 @@ Functions with finite support are used (at least) in the following parts of the * the linear combination of a family of vectors `v i` with coefficients `f i` (as used, e.g., to define linearly independent family `LinearIndependent`) is defined as a map - `Finsupp.total : (ι → M) → (ι →₀ R) →ₗ[R] M`. + `Finsupp.linearCombination : (ι → M) → (ι →₀ R) →ₗ[R] M`. Some other constructions are naturally equivalent to `α →₀ M` with some `α` and `M` but are defined in a different way in the library: @@ -365,15 +365,18 @@ theorem unique_single_eq_iff [Unique α] {b' : M} : single a b = single a' b' rw [Finsupp.unique_ext_iff, Unique.eq_default a, Unique.eq_default a', single_eq_same, single_eq_same] -lemma apply_single [AddCommMonoid N] [AddCommMonoid P] - {F : Type*} [FunLike F N P] [AddMonoidHomClass F N P] (e : F) - (a : α) (n : N) (b : α) : +lemma apply_single' [Zero N] [Zero P] (e : N → P) (he : e 0 = 0) (a : α) (n : N) (b : α) : e ((single a n) b) = single a (e n) b := by classical simp only [single_apply] split_ifs · rfl - · exact map_zero e + · exact he + +lemma apply_single [Zero N] [Zero P] {F : Type*} [FunLike F N P] [ZeroHomClass F N P] + (e : F) (a : α) (n : N) (b : α) : + e ((single a n) b) = single a (e n) b := + apply_single' e (map_zero e) a n b theorem support_eq_singleton {f : α →₀ M} {a : α} : f.support = {a} ↔ f a ≠ 0 ∧ f = single a (f a) := @@ -907,6 +910,20 @@ theorem support_add_eq [DecidableEq α] {g₁ g₂ : α →₀ M} (h : Disjoint theorem single_add (a : α) (b₁ b₂ : M) : single a (b₁ + b₂) = single a b₁ + single a b₂ := (zipWith_single_single _ _ _ _ _).symm +theorem support_single_add {a : α} {b : M} {f : α →₀ M} (ha : a ∉ f.support) (hb : b ≠ 0) : + support (single a b + f) = cons a f.support ha := by + classical + have H := support_single_ne_zero a hb + rw [support_add_eq, H, cons_eq_insert, insert_eq] + rwa [H, disjoint_singleton_left] + +theorem support_add_single {a : α} {b : M} {f : α →₀ M} (ha : a ∉ f.support) (hb : b ≠ 0) : + support (f + single a b) = cons a f.support ha := by + classical + have H := support_single_ne_zero a hb + rw [support_add_eq, H, union_comm, cons_eq_insert, insert_eq] + rwa [H, disjoint_singleton_right] + instance instAddZeroClass : AddZeroClass (α →₀ M) := DFunLike.coe_injective.addZeroClass _ coe_zero coe_add diff --git a/Mathlib/Data/Finsupp/Lex.lean b/Mathlib/Data/Finsupp/Lex.lean index 887891452be35..9174fd421d429 100644 --- a/Mathlib/Data/Finsupp/Lex.lean +++ b/Mathlib/Data/Finsupp/Lex.lean @@ -55,10 +55,9 @@ theorem lex_lt_of_lt [PartialOrder N] (r) [IsStrictOrder α r] {x y : α →₀ DFinsupp.lex_lt_of_lt r (id hlt : x.toDFinsupp < y.toDFinsupp) instance Lex.isStrictOrder [LinearOrder α] [PartialOrder N] : - IsStrictOrder (Lex (α →₀ N)) (· < ·) := - let i : IsStrictOrder (Lex (α → N)) (· < ·) := Pi.Lex.isStrictOrder - { irrefl := toLex.surjective.forall.2 fun _ ↦ @irrefl _ _ i.toIsIrrefl _ - trans := toLex.surjective.forall₃.2 fun _ _ _ ↦ @trans _ _ i.toIsTrans _ _ _ } + IsStrictOrder (Lex (α →₀ N)) (· < ·) where + irrefl _ := lt_irrefl (α := Lex (α → N)) _ + trans _ _ _ := lt_trans (α := Lex (α → N)) variable [LinearOrder α] diff --git a/Mathlib/Data/Finsupp/Notation.lean b/Mathlib/Data/Finsupp/Notation.lean index ef547e495b37b..2091f9b3cb8d1 100644 --- a/Mathlib/Data/Finsupp/Notation.lean +++ b/Mathlib/Data/Finsupp/Notation.lean @@ -15,9 +15,7 @@ This file provides `fun₀ | 3 => a | 7 => b` notation for `Finsupp`, which desu namespace Finsupp -open Lean -open Lean.Parser -open Lean.Parser.Term +open Lean Parser Term -- A variant of `Lean.Parser.Term.matchAlts` with less line wrapping. @[nolint docBlame] -- we do not want any doc hover on this notation. diff --git a/Mathlib/Data/Finsupp/ToDFinsupp.lean b/Mathlib/Data/Finsupp/ToDFinsupp.lean index 53292b96ad67d..a66af26255602 100644 --- a/Mathlib/Data/Finsupp/ToDFinsupp.lean +++ b/Mathlib/Data/Finsupp/ToDFinsupp.lean @@ -8,7 +8,7 @@ import Mathlib.Data.DFinsupp.Basic import Mathlib.Data.Finsupp.Basic /-! -# Conversion between `Finsupp` and homogenous `DFinsupp` +# Conversion between `Finsupp` and homogeneous `DFinsupp` This module provides conversions between `Finsupp` and `DFinsupp`. It is in its own file since neither `Finsupp` or `DFinsupp` depend on each other. @@ -65,7 +65,7 @@ variable {ι : Type*} {R : Type*} {M : Type*} section Defs -/-- Interpret a `Finsupp` as a homogenous `DFinsupp`. -/ +/-- Interpret a `Finsupp` as a homogeneous `DFinsupp`. -/ def Finsupp.toDFinsupp [Zero M] (f : ι →₀ M) : Π₀ _ : ι, M where toFun := f support' := @@ -93,7 +93,7 @@ theorem toDFinsupp_support (f : ι →₀ M) : f.toDFinsupp.support = f.support ext simp -/-- Interpret a homogenous `DFinsupp` as a `Finsupp`. +/-- Interpret a homogeneous `DFinsupp` as a `Finsupp`. Note that the elaborator has a lot of trouble with this definition - it is often necessary to write `(DFinsupp.toFinsupp f : ι →₀ M)` instead of `f.toFinsupp`, as for some unknown reason diff --git a/Mathlib/Data/Finsupp/Weight.lean b/Mathlib/Data/Finsupp/Weight.lean index 8c24117e1132d..fc57c22790c2d 100644 --- a/Mathlib/Data/Finsupp/Weight.lean +++ b/Mathlib/Data/Finsupp/Weight.lean @@ -24,7 +24,7 @@ We fix a type `σ` and an `AddCommMonoid M`, as well as a function `w : σ → M - `Finsupp.weight` of a finitely supported function `f : σ →₀ ℕ` with respect to `w`: it is the sum `∑ (f i) • (w i)`. -It is an `AddMonoidHom` map defined using `Finsupp.total`. +It is an `AddMonoidHom` map defined using `Finsupp.linearCombination`. - `Finsupp.le_weight`says that `f s ≤ f.weight w` when `M = ℕ`` @@ -72,7 +72,7 @@ variable [AddCommMonoid M] /-- The `weight` of the finitely supported function `f : σ →₀ ℕ` with respect to `w : σ → M` is the sum `∑(f i)•(w i)`. -/ noncomputable def weight : (σ →₀ ℕ) →+ M := - (Finsupp.total σ M ℕ w).toAddMonoidHom + (Finsupp.linearCombination ℕ w).toAddMonoidHom @[deprecated weight (since := "2024-07-20")] alias _root_.MvPolynomial.weightedDegree := weight @@ -145,7 +145,7 @@ variable {M : Type*} [CanonicallyOrderedAddCommMonoid M] (w : σ → M) theorem le_weight_of_ne_zero' {s : σ} {f : σ →₀ ℕ} (hs : f s ≠ 0) : w s ≤ weight w f := - le_weight_of_ne_zero w (fun _ ↦ zero_le _) hs + le_weight_of_ne_zero (fun _ ↦ zero_le _) hs /-- If `M` is a `CanonicallyOrderedAddCommMonoid`, then `weight f` is zero iff `f=0. -/ theorem weight_eq_zero_iff_eq_zero diff --git a/Mathlib/Data/Fintype/Basic.lean b/Mathlib/Data/Fintype/Basic.lean index 6b6d8e3c5377b..64062b2403702 100644 --- a/Mathlib/Data/Fintype/Basic.lean +++ b/Mathlib/Data/Fintype/Basic.lean @@ -5,7 +5,6 @@ Authors: Mario Carneiro -/ import Mathlib.Data.Finset.Image import Mathlib.Data.List.FinRange -import Mathlib.Init.Data.Nat.Lemmas /-! # Finite types @@ -76,7 +75,7 @@ theorem mem_univ (x : α) : x ∈ (univ : Finset α) := theorem mem_univ_val : ∀ x, x ∈ (univ : Finset α).1 := mem_univ -theorem eq_univ_iff_forall : s = univ ↔ ∀ x, x ∈ s := by simp [ext_iff] +theorem eq_univ_iff_forall : s = univ ↔ ∀ x, x ∈ s := by simp [Finset.ext_iff] theorem eq_univ_of_forall : (∀ x, x ∈ s) → s = univ := eq_univ_iff_forall.2 @@ -162,7 +161,7 @@ open Lean Elab Term Meta Batteries.ExtendedBinder `Finset ?α`. See also -* `Init.Set` for the `Set` builder notation elaborator that this elaborator partly overrides. +* `Data.Set.Defs` for the `Set` builder notation elaborator that this elaborator partly overrides. * `Data.Finset.Basic` for the `Finset` builder notation elaborator partly overriding this one for syntax of the form `{x ∈ s | p x}`. * `Data.Fintype.Basic` for the `Finset` builder notation elaborator handling syntax of the form @@ -348,7 +347,7 @@ namespace Finset variable {s t : Finset α} @[simp] lemma subtype_eq_univ {p : α → Prop} [DecidablePred p] [Fintype {a // p a}] : - s.subtype p = univ ↔ ∀ ⦃a⦄, p a → a ∈ s := by simp [ext_iff] + s.subtype p = univ ↔ ∀ ⦃a⦄, p a → a ∈ s := by simp [Finset.ext_iff] @[simp] lemma subtype_univ [Fintype α] (p : α → Prop) [DecidablePred p] [Fintype {a // p a}] : univ.subtype p = univ := by simp @@ -569,7 +568,7 @@ def ofEquiv (α : Type*) [Fintype α] (f : α ≃ β) : Fintype β := def ofSubsingleton (a : α) [Subsingleton α] : Fintype α := ⟨{a}, fun _ => Finset.mem_singleton.2 (Subsingleton.elim _ _)⟩ --- In principle, this could be a `simp` theorem but it applies to any occurence of `univ` and +-- In principle, this could be a `simp` theorem but it applies to any occurrence of `univ` and -- required unification of the (possibly very complex) `Fintype` instances. theorem univ_ofSubsingleton (a : α) [Subsingleton α] : @univ _ (ofSubsingleton a) = {a} := rfl @@ -593,7 +592,7 @@ namespace Set variable {s t : Set α} -/-- Construct a finset enumerating a set `s`, given a `Fintype` instance. -/ +/-- Construct a finset enumerating a set `s`, given a `Fintype` instance. -/ def toFinset (s : Set α) [Fintype s] : Finset α := (@Finset.univ s _).map <| Function.Embedding.subtype _ diff --git a/Mathlib/Data/Fintype/BigOperators.lean b/Mathlib/Data/Fintype/BigOperators.lean index 2cef64927c55b..c1ae6185decf8 100644 --- a/Mathlib/Data/Fintype/BigOperators.lean +++ b/Mathlib/Data/Fintype/BigOperators.lean @@ -167,7 +167,7 @@ lemma card_filter_piFinset_const (s : Finset κ) (i : ι) (j : κ) : end Fintype end Pi --- TODO: this is a basic thereom about `Fintype.card`, +-- TODO: this is a basic theorem about `Fintype.card`, -- and ideally could be moved to `Mathlib.Data.Fintype.Card`. theorem Fintype.card_fun [DecidableEq α] [Fintype α] [Fintype β] : Fintype.card (α → β) = Fintype.card β ^ Fintype.card α := by diff --git a/Mathlib/Data/Fintype/Card.lean b/Mathlib/Data/Fintype/Card.lean index 4c50104e54305..c2ac99212e5f5 100644 --- a/Mathlib/Data/Fintype/Card.lean +++ b/Mathlib/Data/Fintype/Card.lean @@ -77,7 +77,7 @@ See `Fintype.truncFinBijection` for a version without `[DecidableEq α]`. def truncEquivFin (α) [DecidableEq α] [Fintype α] : Trunc (α ≃ Fin (card α)) := by unfold card Finset.card exact - Quot.recOnSubsingleton' + Quot.recOnSubsingleton (motive := fun s : Multiset α => (∀ x : α, x ∈ s) → s.Nodup → Trunc (α ≃ Fin (Multiset.card s))) univ.val @@ -106,7 +106,7 @@ given `[DecidableEq α]`. def truncFinBijection (α) [Fintype α] : Trunc { f : Fin (card α) → α // Bijective f } := by unfold card Finset.card refine - Quot.recOnSubsingleton' + Quot.recOnSubsingleton (motive := fun s : Multiset α => (∀ x : α, x ∈ s) → s.Nodup → Trunc {f : Fin (Multiset.card s) → α // Bijective f}) univ.val diff --git a/Mathlib/Data/Fintype/Fin.lean b/Mathlib/Data/Fintype/Fin.lean index bdd198e51a477..1c108db32e13b 100644 --- a/Mathlib/Data/Fintype/Fin.lean +++ b/Mathlib/Data/Fintype/Fin.lean @@ -67,7 +67,7 @@ theorem card_filter_univ_eq_vector_get_eq_count [DecidableEq α] (a : α) (v : V (univ.filter fun i => v.get i = a).card = v.toList.count a := by induction' v with n x xs hxs · simp - · simp_rw [card_filter_univ_succ', Vector.get_cons_zero, Vector.toList_cons, Function.comp, + · simp_rw [card_filter_univ_succ', Vector.get_cons_zero, Vector.toList_cons, Function.comp_def, Vector.get_cons_succ, hxs, List.count_cons, add_comm (ite (x = a) 1 0), beq_iff_eq] end Fin diff --git a/Mathlib/Data/Fintype/Order.lean b/Mathlib/Data/Fintype/Order.lean index daef09e27fc55..93fb8dff25530 100644 --- a/Mathlib/Data/Fintype/Order.lean +++ b/Mathlib/Data/Fintype/Order.lean @@ -188,7 +188,7 @@ variable {α : Type*} {r : α → α → Prop} [IsTrans α r] {β γ : Type*} [N theorem Directed.finite_set_le (D : Directed r f) {s : Set γ} (hs : s.Finite) : ∃ z, ∀ i ∈ s, r (f i) (f z) := by - convert D.finset_le hs.toFinset; rw [Set.Finite.mem_toFinset] + convert D.finset_le hs.toFinset using 3; rw [Set.Finite.mem_toFinset] theorem Directed.finite_le (D : Directed r f) (g : β → γ) : ∃ z, ∀ i, r (f (g i)) (f z) := by classical @@ -211,12 +211,14 @@ theorem Set.Finite.exists_ge [IsDirected α (· ≥ ·)] {s : Set α} (hs : s.Fi ∃ M, ∀ i ∈ s, M ≤ i := directed_id.finite_set_le (r := (· ≥ ·)) hs +@[simp] theorem Finite.bddAbove_range [IsDirected α (· ≤ ·)] (f : β → α) : BddAbove (Set.range f) := by obtain ⟨M, hM⟩ := Finite.exists_le f refine ⟨M, fun a ha => ?_⟩ obtain ⟨b, rfl⟩ := ha exact hM b +@[simp] theorem Finite.bddBelow_range [IsDirected α (· ≥ ·)] (f : β → α) : BddBelow (Set.range f) := by obtain ⟨M, hM⟩ := Finite.exists_ge f refine ⟨M, fun a ha => ?_⟩ diff --git a/Mathlib/Data/Fintype/Perm.lean b/Mathlib/Data/Fintype/Perm.lean index 4e2bc19dc273d..bdf570b09044a 100644 --- a/Mathlib/Data/Fintype/Perm.lean +++ b/Mathlib/Data/Fintype/Perm.lean @@ -36,7 +36,7 @@ theorem length_permsOfList : ∀ l : List α, length (permsOfList l) = l.length | [] => rfl | a :: l => by rw [length_cons, Nat.factorial_succ] - simp only [permsOfList, length_append, length_permsOfList, length_bind, comp, + simp only [permsOfList, length_append, length_permsOfList, length_bind, comp_def, length_map, map_const', sum_replicate, smul_eq_mul, succ_mul] ring diff --git a/Mathlib/Data/Fintype/Sigma.lean b/Mathlib/Data/Fintype/Sigma.lean index de9ae773d01eb..64f8de8f89ab0 100644 --- a/Mathlib/Data/Fintype/Sigma.lean +++ b/Mathlib/Data/Fintype/Sigma.lean @@ -30,6 +30,7 @@ lemma Set.biUnion_finsetSigma_univ' (s : Finset ι) (f : Π i, κ i → Set α) lemma Set.biInter_finsetSigma_univ (s : Finset ι) (f : Sigma κ → Set α) : ⋂ ij ∈ s.sigma fun _ ↦ Finset.univ, f ij = ⋂ i ∈ s, ⋂ j, f ⟨i, j⟩ := by aesop +attribute [local simp] Sigma.forall in lemma Set.biInter_finsetSigma_univ' (s : Finset ι) (f : Π i, κ i → Set α) : ⋂ i ∈ s, ⋂ j, f i j = ⋂ ij ∈ s.sigma fun _ ↦ Finset.univ, f ij.1 ij.2 := by aesop diff --git a/Mathlib/Data/Int/Bitwise.lean b/Mathlib/Data/Int/Bitwise.lean index 646ee6284ae3e..664c817a6e578 100644 --- a/Mathlib/Data/Int/Bitwise.lean +++ b/Mathlib/Data/Int/Bitwise.lean @@ -24,7 +24,7 @@ def div2 : ℤ → ℤ | (n : ℕ) => n.div2 | -[n +1] => negSucc n.div2 -/-- `bodd n` returns `true` if `n` is odd-/ +/-- `bodd n` returns `true` if `n` is odd -/ def bodd : ℤ → Bool | (n : ℕ) => n.bodd | -[n +1] => not (n.bodd) @@ -81,7 +81,7 @@ def ldiff : ℤ → ℤ → ℤ | -[m +1], -[n +1] => Nat.ldiff n m -- Porting note: I don't know why `Nat.xor'` got the prime, but I'm matching this change here -/-- `xor` computes the bitwise `xor` of two natural numbers-/ +/-- `xor` computes the bitwise `xor` of two natural numbers -/ protected def xor : ℤ → ℤ → ℤ | (m : ℕ), (n : ℕ) => (m ^^^ n) | (m : ℕ), -[n +1] => -[(m ^^^ n) +1] diff --git a/Mathlib/Data/Int/CardIntervalMod.lean b/Mathlib/Data/Int/CardIntervalMod.lean index 8b80171fc546a..045f7ee4c7aa8 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 662009abfdf46..b5619f8bcea08 100644 --- a/Mathlib/Data/Int/Defs.lean +++ b/Mathlib/Data/Int/Defs.lean @@ -234,7 +234,7 @@ where conv => rhs; exact b.add_zero.symm rw [Int.add_lt_add_iff_left]; apply negSucc_lt_zero -variable (b) {z b b H0 Hs Hp} +variable {z b H0 Hs Hp} lemma inductionOn'_self : b.inductionOn' b H0 Hs Hp = H0 := cast_eq_iff_heq.mpr <| .symm <| by rw [b.sub_self, ← cast_eq_iff_heq]; rfl @@ -333,9 +333,9 @@ lemma natAbs_add_of_nonpos {a b : Int} (ha : a ≤ 0) (hb : b ≤ 0) : lemma natAbs_surjective : natAbs.Surjective := fun n => ⟨n, natAbs_ofNat n⟩ lemma natAbs_pow (n : ℤ) (k : ℕ) : Int.natAbs (n ^ k) = Int.natAbs n ^ k := by - induction' k with k ih - · rfl - · rw [Int.pow_succ, natAbs_mul, Nat.pow_succ, ih, Nat.mul_comm] + induction k with + | zero => rfl + | succ k ih => rw [Int.pow_succ, natAbs_mul, Nat.pow_succ, ih, Nat.mul_comm] lemma pow_right_injective (h : 1 < a.natAbs) : ((a ^ ·) : ℕ → ℤ).Injective := by refine (?_ : (natAbs ∘ (a ^ · : ℕ → ℤ)).Injective).of_comp @@ -562,13 +562,12 @@ lemma lt_of_toNat_lt {a b : ℤ} (h : toNat a < toNat b) : a < b := (toNat_lt_toNat <| lt_toNat.1 <| Nat.lt_of_le_of_lt (Nat.zero_le _) h).1 h @[simp] lemma toNat_pred_coe_of_pos {i : ℤ} (h : 0 < i) : ((i.toNat - 1 : ℕ) : ℤ) = i - 1 := by - simp [h, Int.le_of_lt h, push_cast] + simp only [lt_toNat, Nat.cast_ofNat_Int, h, natCast_pred_of_pos, Int.le_of_lt h, toNat_of_nonneg] @[simp] lemma toNat_eq_zero : ∀ {n : ℤ}, n.toNat = 0 ↔ n ≤ 0 | (n : ℕ) => by simp | -[n+1] => by simpa [toNat] using Int.le_of_lt (negSucc_lt_zero n) -@[simp] theorem toNat_sub_of_le {a b : ℤ} (h : b ≤ a) : (toNat (a - b) : ℤ) = a - b := Int.toNat_of_nonneg (Int.sub_nonneg_of_le h) diff --git a/Mathlib/Data/Int/GCD.lean b/Mathlib/Data/Int/GCD.lean index 108bf803cbc6f..038b354fda39a 100644 --- a/Mathlib/Data/Int/GCD.lean +++ b/Mathlib/Data/Int/GCD.lean @@ -5,9 +5,9 @@ Authors: Sangwoo Jo (aka Jason), Guy Leroy, Johannes Hölzl, Mario Carneiro -/ import Mathlib.Algebra.Group.Int import Mathlib.Algebra.GroupWithZero.Semiconj -import Mathlib.Order.Bounds.Basic import Mathlib.Algebra.Group.Commute.Units import Mathlib.Data.Nat.GCD.Basic +import Mathlib.Order.Bounds.Basic /-! # Extended GCD and divisibility over ℤ diff --git a/Mathlib/Data/Int/Interval.lean b/Mathlib/Data/Int/Interval.lean index a0d03d9652740..ce53928746469 100644 --- a/Mathlib/Data/Int/Interval.lean +++ b/Mathlib/Data/Int/Interval.lean @@ -112,7 +112,7 @@ theorem card_Ioo : (Ioo a b).card = (b - a - 1).toNat := (card_map _).trans <| c @[simp] theorem card_uIcc : (uIcc a b).card = (b - a).natAbs + 1 := (card_map _).trans <| - Nat.cast_inj.mp <| by + (Nat.cast_inj (R := ℤ)).mp <| by rw [card_range, sup_eq_max, inf_eq_min, Int.toNat_of_nonneg (sub_nonneg_of_le <| le_add_one min_le_max), Int.ofNat_add, Int.natCast_natAbs, add_comm, add_sub_assoc, max_sub_min_eq_abs, add_comm, Int.ofNat_one] diff --git a/Mathlib/Init/Data/Int/Order.lean b/Mathlib/Data/Int/Order/Basic.lean similarity index 57% rename from Mathlib/Init/Data/Int/Order.lean rename to Mathlib/Data/Int/Order/Basic.lean index 62b66941747ef..4fcb9a0a8f8f8 100644 --- a/Mathlib/Init/Data/Int/Order.lean +++ b/Mathlib/Data/Int/Order/Basic.lean @@ -9,13 +9,6 @@ import Mathlib.Data.Nat.Notation import Mathlib.Order.Defs /-! -# Note about `Mathlib/Init/` -The files in `Mathlib/Init` are leftovers from the port from Mathlib3. -(They contain content moved from lean3 itself that Mathlib needed but was not moved to lean4.) - -We intend to move all the content of these files out into the main `Mathlib` directory structure. -Contributions assisting with this are appreciated. - # The order relation on the integers -/ @@ -53,4 +46,24 @@ instance instLinearOrder : LinearOrder ℤ where protected theorem eq_zero_or_eq_zero_of_mul_eq_zero {a b : ℤ} (h : a * b = 0) : a = 0 ∨ b = 0 := Int.mul_eq_zero.mp h +theorem nonneg_or_nonpos_of_mul_nonneg {a b : ℤ} : 0 ≤ a * b → 0 ≤ a ∧ 0 ≤ b ∨ a ≤ 0 ∧ b ≤ 0 := by + intro h + by_cases ha : 0 ≤ a <;> by_cases hb : 0 ≤ b + · exact .inl ⟨ha, hb⟩ + · refine .inr ⟨?_, le_of_not_le hb⟩ + obtain _ | _ := Int.mul_eq_zero.mp <| + Int.le_antisymm (Int.mul_nonpos_of_nonneg_of_nonpos ha <| le_of_not_le hb) h + all_goals omega + · refine .inr ⟨le_of_not_le ha, ?_⟩ + obtain _ | _ := Int.mul_eq_zero.mp <| + Int.le_antisymm (Int.mul_nonpos_of_nonpos_of_nonneg (le_of_not_le ha) hb) h + all_goals omega + · exact .inr ⟨le_of_not_ge ha, le_of_not_ge hb⟩ + +theorem mul_nonneg_of_nonneg_or_nonpos {a b : ℤ} : 0 ≤ a ∧ 0 ≤ b ∨ a ≤ 0 ∧ b ≤ 0 → 0 ≤ a * b + | .inl ⟨ha, hb⟩ => Int.mul_nonneg ha hb + | .inr ⟨ha, hb⟩ => Int.mul_nonneg_of_nonpos_of_nonpos ha hb + +protected theorem mul_nonneg_iff {a b : ℤ} : 0 ≤ a * b ↔ 0 ≤ a ∧ 0 ≤ b ∨ a ≤ 0 ∧ b ≤ 0 := + ⟨nonneg_or_nonpos_of_mul_nonneg, mul_nonneg_of_nonneg_or_nonpos⟩ end Int diff --git a/Mathlib/Data/Int/Sqrt.lean b/Mathlib/Data/Int/Sqrt.lean index 8a9136358543f..1c6db061ba8f7 100644 --- a/Mathlib/Data/Int/Sqrt.lean +++ b/Mathlib/Data/Int/Sqrt.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Kenny Lau -/ import Mathlib.Data.Int.Defs -import Mathlib.Data.Nat.Defs +import Mathlib.Data.Nat.Sqrt import Mathlib.Tactic.Common /-! diff --git a/Mathlib/Data/Int/Star.lean b/Mathlib/Data/Int/Star.lean index 1304983eb851c..b4e7290794d36 100644 --- a/Mathlib/Data/Int/Star.lean +++ b/Mathlib/Data/Int/Star.lean @@ -3,11 +3,11 @@ 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.Star.Order import Mathlib.Algebra.Order.Group.Abs import Mathlib.Algebra.Order.Monoid.Submonoid import Mathlib.Algebra.Order.Ring.Basic import Mathlib.Algebra.Order.Ring.Int +import Mathlib.Algebra.Order.Star.Basic /-! # Star ordered ring structure on `ℤ` @@ -31,6 +31,6 @@ lemma addSubmonoid_closure_range_mul_self : closure (range fun x : ℤ ↦ x * x simpa only [sq] using addSubmonoid_closure_range_pow even_two instance instStarOrderedRing : StarOrderedRing ℤ where - le_iff a b := by simp [le_iff_exists_nonneg_add a b] + le_iff a b := by simp [eq_comm, le_iff_exists_nonneg_add (a := a)] end Int diff --git a/Mathlib/Data/Int/SuccPred.lean b/Mathlib/Data/Int/SuccPred.lean index b7ca8527c1e1b..d16d87c88e2dd 100644 --- a/Mathlib/Data/Int/SuccPred.lean +++ b/Mathlib/Data/Int/SuccPred.lean @@ -27,7 +27,6 @@ namespace Int pred_le _ := (sub_one_lt_of_le le_rfl).le min_of_le_pred ha := ((sub_one_lt_of_le le_rfl).not_le ha).elim le_pred_of_lt {_ _} := le_sub_one_of_lt - le_of_pred_lt {_ _} := le_of_sub_one_lt @[simp] theorem succ_eq_succ : Order.succ = succ := diff --git a/Mathlib/Data/LazyList/Basic.lean b/Mathlib/Data/LazyList/Basic.lean index ad67f3d3f60aa..7a9b820336505 100644 --- a/Mathlib/Data/LazyList/Basic.lean +++ b/Mathlib/Data/LazyList/Basic.lean @@ -47,25 +47,29 @@ instance : Traversable LazyList where @[deprecated (since := "2024-07-22")] instance : LawfulTraversable LazyList := by apply Equiv.isLawfulTraversable' listEquivLazyList <;> intros <;> ext <;> rename_i f xs - · induction' xs using LazyList.rec with _ _ _ _ ih - · simp only [Functor.map, LazyList.traverse, pure, Equiv.map, listEquivLazyList, + · induction xs using LazyList.rec with + | nil => + simp only [Functor.map, LazyList.traverse, pure, Equiv.map, listEquivLazyList, Equiv.coe_fn_symm_mk, toList, Equiv.coe_fn_mk, ofList] - · simpa only [Equiv.map, Functor.map, listEquivLazyList, Equiv.coe_fn_symm_mk, Equiv.coe_fn_mk, + | cons => + simpa only [Equiv.map, Functor.map, listEquivLazyList, Equiv.coe_fn_symm_mk, Equiv.coe_fn_mk, LazyList.traverse, Seq.seq, toList, ofList, cons.injEq, true_and] - · ext; apply ih + | mk _ ih => ext; apply ih · simp only [Equiv.map, listEquivLazyList, Equiv.coe_fn_symm_mk, Equiv.coe_fn_mk, comp, Functor.mapConst] - induction' xs using LazyList.rec with _ _ _ _ ih - · simp only [LazyList.traverse, pure, Functor.map, toList, ofList] - · simpa only [toList, ofList, LazyList.traverse, Seq.seq, Functor.map, cons.injEq, true_and] - · congr; apply ih + induction xs using LazyList.rec with + | nil => simp only [LazyList.traverse, pure, Functor.map, toList, ofList] + | cons => + simpa only [toList, ofList, LazyList.traverse, Seq.seq, Functor.map, cons.injEq, true_and] + | mk _ ih => congr; apply ih · simp only [traverse, Equiv.traverse, listEquivLazyList, Equiv.coe_fn_mk, Equiv.coe_fn_symm_mk] - induction' xs using LazyList.rec with _ tl ih _ ih - · simp only [LazyList.traverse, toList, List.traverse, map_pure, ofList] - · replace ih : tl.get.traverse f = ofList <$> tl.get.toList.traverse f := ih + induction xs using LazyList.rec with + | nil => simp only [LazyList.traverse, toList, List.traverse, map_pure, ofList] + | cons _ tl ih => + replace ih : tl.get.traverse f = ofList <$> tl.get.toList.traverse f := ih simp [traverse.eq_2, ih, Functor.map_map, seq_map_assoc, toList, List.traverse, map_seq, - Function.comp, Thunk.pure, ofList] - · apply ih + Function.comp_def, Thunk.pure, ofList] + | mk _ ih => apply ih @[deprecated (since := "2024-07-22"), simp] theorem bind_singleton {α} (x : LazyList α) : x.bind singleton = x := by @@ -91,10 +95,10 @@ instance : LawfulMonad LazyList := LawfulMonad.mk' apply append_nil) (bind_assoc := by intro _ _ _ xs _ _ - induction' xs using LazyList.rec with _ _ _ _ ih - · simp only [bind, LazyList.bind] - · simp only [bind, LazyList.bind, append_bind]; congr - · congr; funext; apply ih) + induction xs using LazyList.rec with + | nil => simp only [bind, LazyList.bind] + | cons => simp only [bind, LazyList.bind, append_bind]; congr + | mk _ ih => congr; funext; apply ih) (bind_pure_comp := by intro _ _ f xs simp only [bind, Functor.map, pure, singleton] diff --git a/Mathlib/Data/List/AList.lean b/Mathlib/Data/List/AList.lean index 1498c2afd3a09..cb4442a55a060 100644 --- a/Mathlib/Data/List/AList.lean +++ b/Mathlib/Data/List/AList.lean @@ -78,7 +78,7 @@ theorem keys_nodup (s : AList β) : s.keys.Nodup := /-- The predicate `a ∈ s` means that `s` has a value associated to the key `a`. -/ instance : Membership α (AList β) := - ⟨fun a s => a ∈ s.keys⟩ + ⟨fun s a => a ∈ s.keys⟩ theorem mem_keys {a : α} {s : AList β} : a ∈ s ↔ a ∈ s.keys := Iff.rfl diff --git a/Mathlib/Data/List/Basic.lean b/Mathlib/Data/List/Basic.lean index e47f6853ce6e7..d2ddf144bd1f4 100644 --- a/Mathlib/Data/List/Basic.lean +++ b/Mathlib/Data/List/Basic.lean @@ -7,11 +7,9 @@ import Mathlib.Data.Nat.Defs import Mathlib.Data.Option.Basic import Mathlib.Data.List.Defs import Mathlib.Data.List.Monad -import Mathlib.Init.Data.List.Lemmas import Mathlib.Logic.Unique import Mathlib.Order.Basic import Mathlib.Tactic.Common -import Batteries.Data.List.Perm /-! # Basic properties of lists @@ -41,10 +39,6 @@ theorem le_eq_not_gt [LT α] : ∀ l₁ l₂ : List α, (l₁ ≤ l₂) = ¬l₂ -- Porting note: Delete this attribute -- attribute [inline] List.head! -theorem getElem?_eq (l : List α) (i : Nat) : - l[i]? = if h : i < l.length then some l[i] else none := by - split <;> simp_all - /-- There is only one list of an empty type -/ instance uniqueOfIsEmpty [IsEmpty α] : Unique (List α) := { instInhabitedList with @@ -193,8 +187,6 @@ theorem append_subset_of_subset_of_subset {l₁ l₂ l : List α} (l₁subl : l l₁ ++ l₂ ⊆ l := fun _ h ↦ (mem_append.1 h).elim (@l₁subl _) (@l₂subl _) -alias ⟨eq_nil_of_subset_nil, _⟩ := subset_nil - theorem map_subset_iff {l₁ l₂ : List α} (f : α → β) (h : Injective f) : map f l₁ ⊆ map f l₂ ↔ l₁ ⊆ l₂ := by refine ⟨?_, map_subset f⟩; intro h2 x hx @@ -214,18 +206,6 @@ theorem append_eq_has_append {L₁ L₂ : List α} : List.append L₁ L₂ = L @[deprecated (since := "2024-01-18")] alias append_right_cancel := append_cancel_right -@[simp] theorem append_left_eq_self {x y : List α} : x ++ y = y ↔ x = [] := by - rw [← append_left_inj (s₁ := x), nil_append] - -@[simp] theorem self_eq_append_left {x y : List α} : y = x ++ y ↔ x = [] := by - rw [eq_comm, append_left_eq_self] - -@[simp] theorem append_right_eq_self {x y : List α} : x ++ y = x ↔ y = [] := by - rw [← append_right_inj (t₁ := y), append_nil] - -@[simp] theorem self_eq_append_right {x y : List α} : x = x ++ y ↔ y = [] := by - rw [eq_comm, append_right_eq_self] - theorem append_right_injective (s : List α) : Injective fun t ↦ s ++ t := fun _ _ ↦ append_cancel_left @@ -250,9 +230,6 @@ theorem replicate_subset_singleton (n) (a : α) : replicate n a ⊆ [a] := fun _ 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] theorem tail_replicate (a : α) (n) : - tail (replicate n a) = replicate (n - 1) a := by cases n <;> rfl - theorem replicate_right_injective {n : ℕ} (hn : n ≠ 0) : Injective (@replicate α n) := fun _ _ h => (eq_replicate.1 h).2 _ <| mem_replicate.2 ⟨hn, rfl⟩ @@ -310,10 +287,6 @@ theorem reverse_surjective : Surjective (@reverse α) := theorem reverse_bijective : Bijective (@reverse α) := reverse_involutive.bijective -@[simp] -theorem reverse_inj {l₁ l₂ : List α} : reverse l₁ = reverse l₂ ↔ l₁ = l₂ := - reverse_injective.eq_iff - theorem concat_eq_reverse_cons (a : α) (l : List α) : concat l a = reverse (a :: reverse l) := by simp only [concat_eq_append, reverse_cons, reverse_reverse] @@ -323,9 +296,7 @@ theorem map_reverseAux (f : α → β) (l₁ l₂ : List α) : /-! ### empty -/ -theorem isEmpty_iff_eq_nil {l : List α} : l.isEmpty ↔ l = [] := by cases l <;> simp [isEmpty] - -/-! ### dropLast -/ +@[deprecated (since := "2024-08-15")] alias isEmpty_iff_eq_nil := isEmpty_iff /-! ### getLast -/ @@ -338,11 +309,9 @@ theorem getLast_append_singleton {a : α} (l : List α) : -- Porting note: name should be fixed upstream theorem getLast_append' (l₁ l₂ : List α) (h : l₂ ≠ []) : getLast (l₁ ++ l₂) (append_ne_nil_of_right_ne_nil l₁ h) = getLast l₂ h := by - induction' l₁ with _ _ ih - · simp - · simp only [cons_append] - rw [List.getLast_cons] - exact ih + induction l₁ with + | nil => simp + | cons _ _ ih => simp only [cons_append]; rw [List.getLast_cons]; exact ih theorem getLast_concat' {a : α} (l : List α) : getLast (concat l a) (concat_ne_nil a l) = a := by simp @@ -390,11 +359,8 @@ lemma getLast_filter {p : α → Bool} : /-! ### getLast? -/ -@[simp] -theorem getLast?_cons_cons (a b : α) (l : List α) : - getLast? (a :: b :: l) = getLast? (b :: l) := rfl - -@[simp] +-- 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 @@ -536,37 +502,20 @@ theorem head!_mem_self [Inhabited α] {l : List α} (h : l ≠ nil) : l.head! have h' := mem_cons_self l.head! l.tail rwa [cons_head!_tail h] at h' -theorem tail_append_of_ne_nil (l l' : List α) (h : l ≠ []) : (l ++ l').tail = l.tail ++ l' := by - cases l - · contradiction - · simp - theorem get_eq_get? (l : List α) (i : Fin l.length) : l.get i = (l.get? i).get (by simp [getElem?_eq_getElem]) := by simp [getElem_eq_iff] -section deprecated -set_option linter.deprecated false -- TODO(Mario): make replacements for theorems in this section - -/-- nth element of a list `l` given `n < l.length`. -/ -@[deprecated get (since := "2023-01-05")] -def nthLe (l : List α) (n) (h : n < l.length) : α := get l ⟨n, h⟩ - -@[simp] theorem nthLe_tail (l : List α) (i) (h : i < l.tail.length) +theorem get_tail (l : List α) (i) (h : i < l.tail.length) (h' : i + 1 < l.length := (by simp only [length_tail] at h; omega)) : - l.tail.nthLe i h = l.nthLe (i + 1) h' := by + l.tail.get ⟨i, h⟩ = l.get ⟨i + 1, h'⟩ := by cases l <;> [cases h; rfl] -theorem nthLe_cons_aux {l : List α} {a : α} {n} (hn : n ≠ 0) (h : n < (a :: l).length) : - n - 1 < l.length := by - contrapose! h - rw [length_cons] - omega - -theorem nthLe_cons {l : List α} {a : α} {n} (hl) : - (a :: l).nthLe n hl = if hn : n = 0 then a else l.nthLe (n - 1) (nthLe_cons_aux hn hl) := by +theorem get_cons {l : List α} {a : α} {n} (hl) : + (a :: l).get ⟨n, hl⟩ = if hn : n = 0 then a else + l.get ⟨n - 1, by contrapose! hl; rw [length_cons]; omega⟩ := by split_ifs with h - · simp [nthLe, h] + · simp [h] cases l · rw [length_singleton, Nat.lt_succ_iff] at hl omega @@ -574,9 +523,6 @@ theorem nthLe_cons {l : List α} {a : α} {n} (hl) : · contradiction rfl -end deprecated - -@[simp 1100] theorem modifyHead_modifyHead (l : List α) (f g : α → α) : (l.modifyHead f).modifyHead g = l.modifyHead (g ∘ f) := by cases l <;> simp @@ -705,26 +651,11 @@ lemma cons_sublist_cons' {a b : α} : a :: l₁ <+ b :: l₂ ↔ a :: l₁ <+ l theorem sublist_cons_of_sublist (a : α) (h : l₁ <+ l₂) : l₁ <+ a :: l₂ := h.cons _ -theorem tail_sublist : ∀ l : List α, tail l <+ l - | [] => .slnil - | a::l => sublist_cons_self a l - -@[gcongr] protected theorem Sublist.tail : ∀ {l₁ l₂ : List α}, l₁ <+ l₂ → tail l₁ <+ tail l₂ - | _, _, slnil => .slnil - | _, _, Sublist.cons _ h => (tail_sublist _).trans h - | _, _, Sublist.cons₂ _ h => h - -theorem Sublist.of_cons_cons {l₁ l₂ : List α} {a b : α} (h : a :: l₁ <+ b :: l₂) : l₁ <+ l₂ := - h.tail - @[deprecated (since := "2024-04-07")] theorem sublist_of_cons_sublist_cons {a} (h : a :: l₁ <+ a :: l₂) : l₁ <+ l₂ := h.of_cons_cons @[deprecated (since := "2024-04-07")] alias cons_sublist_cons_iff := cons_sublist_cons -theorem eq_nil_of_sublist_nil {l : List α} (s : l <+ []) : l = [] := - eq_nil_of_subset_nil <| s.subset - -- Porting note: this lemma seems to have been renamed on the occasion of its move to Batteries alias sublist_nil_iff_eq_nil := sublist_nil @@ -827,31 +758,14 @@ end IndexOf section deprecated set_option linter.deprecated false -@[deprecated get_of_mem (since := "2023-01-05")] -theorem nthLe_of_mem {a} {l : List α} (h : a ∈ l) : ∃ n h, nthLe l n h = a := - let ⟨i, h⟩ := get_of_mem h; ⟨i.1, i.2, h⟩ - -@[deprecated get?_eq_get (since := "2023-01-05")] -theorem nthLe_get? {l : List α} {n} (h) : get? l n = some (nthLe l n h) := get?_eq_get _ - @[simp] theorem getElem?_length (l : List α) : l[l.length]? = none := getElem?_len_le le_rfl @[deprecated getElem?_length (since := "2024-06-12")] theorem get?_length (l : List α) : l.get? l.length = none := get?_len_le le_rfl -@[deprecated get_mem (since := "2023-01-05")] -theorem nthLe_mem (l : List α) (n h) : nthLe l n h ∈ l := get_mem .. - -@[deprecated mem_iff_get (since := "2023-01-05")] -theorem mem_iff_nthLe {a} {l : List α} : a ∈ l ↔ ∃ n h, nthLe l n h = a := - mem_iff_get.trans ⟨fun ⟨⟨n, h⟩, e⟩ => ⟨n, h, e⟩, fun ⟨n, h, e⟩ => ⟨⟨n, h⟩, e⟩⟩ - @[deprecated (since := "2024-05-03")] alias get?_injective := get?_inj -@[deprecated get_map (since := "2023-01-05")] -theorem nthLe_map (f : α → β) {l n} (H1 H2) : nthLe (map f l) n H1 = f (nthLe l n H2) := get_map .. - /-- A version of `getElem_map` that can be used for rewriting. -/ theorem getElem_map_rev (f : α → β) {l} {n : Nat} {h : n < l.length} : f l[n] = (map f l)[n]'((l.length_map f).symm ▸ h) := Eq.symm (getElem_map _) @@ -861,32 +775,10 @@ theorem getElem_map_rev (f : α → β) {l} {n : Nat} {h : n < l.length} : theorem get_map_rev (f : α → β) {l n} : f (get l n) = get (map f l) ⟨n.1, (l.length_map f).symm ▸ n.2⟩ := Eq.symm (get_map _) -/-- A version of `nthLe_map` that can be used for rewriting. -/ -@[deprecated get_map_rev (since := "2023-01-05")] -theorem nthLe_map_rev (f : α → β) {l n} (H) : - f (nthLe l n H) = nthLe (map f l) n ((l.length_map f).symm ▸ H) := - (nthLe_map f _ _).symm - -@[simp, deprecated get_map (since := "2023-01-05")] -theorem nthLe_map' (f : α → β) {l n} (H) : - nthLe (map f l) n H = f (nthLe l n (l.length_map f ▸ H)) := nthLe_map f _ _ - -@[simp, deprecated get_singleton (since := "2023-01-05")] -theorem nthLe_singleton (a : α) {n : ℕ} (hn : n < 1) : nthLe [a] n hn = a := get_singleton .. - -@[deprecated get_append_right' (since := "2023-01-05")] -theorem nthLe_append_right {l₁ l₂ : List α} {n : ℕ} (h₁ : l₁.length ≤ n) (h₂) : - (l₁ ++ l₂).nthLe n h₂ = l₂.nthLe (n - l₁.length) (get_append_right_aux h₁ h₂) := - get_append_right' h₁ h₂ - theorem get_length_sub_one {l : List α} (h : l.length - 1 < l.length) : l.get ⟨l.length - 1, h⟩ = l.getLast (by rintro rfl; exact Nat.lt_irrefl 0 h) := (getLast_eq_get l _).symm -@[deprecated get_cons_length (since := "2023-01-05")] -theorem nthLe_cons_length : ∀ (x : α) (xs : List α) (n : ℕ) (h : n = xs.length), - (x :: xs).nthLe n (by simp [h]) = (x :: xs).getLast (cons_ne_nil x xs) := get_cons_length - theorem take_one_drop_eq_of_lt_length {l : List α} {n : ℕ} (h : n < l.length) : (l.drop n).take 1 = [l.get ⟨n, h⟩] := by rw [drop_eq_get_cons h, take, take] @@ -914,11 +806,6 @@ theorem ext_get?_iff' {l₁ l₂ : List α} : l₁ = l₂ ↔ ∀ n < max l₁.length l₂.length, l₁.get? n = l₂.get? n := ⟨by rintro rfl _ _; rfl, ext_get?'⟩ -@[deprecated ext_get (since := "2023-01-05")] -theorem ext_nthLe {l₁ l₂ : List α} (hl : length l₁ = length l₂) - (h : ∀ n h₁ h₂, nthLe l₁ n h₁ = nthLe l₂ n h₂) : l₁ = l₂ := - ext_get hl h - @[simp] theorem getElem_indexOf [DecidableEq α] {a : α} : ∀ {l : List α} (h : indexOf a l < l.length), l[indexOf a l] = a @@ -957,6 +844,7 @@ 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 @@ -971,39 +859,23 @@ theorem getElem_reverse_aux₂ : rw [← heq] at aux apply aux -@[simp] theorem getElem_reverse (l : List α) (i : Nat) (h1 h2) : - (reverse l)[length l - 1 - i]'h1 = l[i]'h2 := - getElem_reverse_aux₂ _ _ _ _ _ - -@[deprecated getElem_reverse_aux₂ (since := "2024-06-12")] +@[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 [getElem_reverse_aux₂, h1, h2] + 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₂ _ _ _ _ _ -@[simp, deprecated get_reverse (since := "2023-01-05")] -theorem nthLe_reverse (l : List α) (i : Nat) (h1 h2) : - nthLe (reverse l) (length l - 1 - i) h1 = nthLe l i h2 := - get_reverse .. - -theorem nthLe_reverse' (l : List α) (n : ℕ) (hn : n < l.reverse.length) (hn') : - l.reverse.nthLe n hn = l.nthLe (l.length - 1 - n) hn' := by +theorem get_reverse' (l : List α) (n) (hn') : + l.reverse.get n = l.get ⟨l.length - 1 - n, hn'⟩ := by rw [eq_comm] - convert nthLe_reverse l.reverse n (by simpa) hn using 1 + convert get_reverse l.reverse n (by simpa) n.2 using 1 simp -theorem get_reverse' (l : List α) (n) (hn') : - l.reverse.get n = l.get ⟨l.length - 1 - n, hn'⟩ := nthLe_reverse' .. - --- FIXME: prove it the other way around -attribute [deprecated get_reverse' (since := "2023-01-05")] nthLe_reverse' - -theorem eq_cons_of_length_one {l : List α} (h : l.length = 1) : - l = [l.nthLe 0 (by omega)] := by +theorem eq_cons_of_length_one {l : List α} (h : l.length = 1) : l = [l.get ⟨0, by omega⟩] := by refine ext_get (by convert h) fun n h₁ h₂ => ?_ simp only [get_singleton] congr @@ -1186,13 +1058,6 @@ theorem zipWith_flip (f : α → β → γ) : ∀ as bs, zipWith (flip f) bs as /-! ### take, drop -/ -theorem take_cons (n) (a : α) (l : List α) : take (succ n) (a :: l) = a :: take n l := - rfl - -@[simp] -theorem drop_tail (l : List α) (n : ℕ) : l.tail.drop n = l.drop (n + 1) := by - rw [← drop_drop, drop_one] - theorem cons_getElem_drop_succ {l : List α} {n : Nat} {h : n < l.length} : l[n] :: l.drop (n + 1) = l.drop n := (drop_eq_getElem_cons h).symm @@ -1297,11 +1162,10 @@ theorem foldr_fixed {b : β} : ∀ l : List α, foldr (fun _ b => b) b l = b := -- Porting note (#10618): simp can prove this -- @[simp] theorem foldr_eta : ∀ l : List α, foldr cons [] l = l := by - simp only [foldr_self_append, append_nil, forall_const] + simp only [foldr_cons_eq_append, append_nil, forall_const] -@[simp] theorem reverse_foldl {l : List α} : reverse (foldl (fun t h => h :: t) [] l) = l := by - rw [← foldr_reverse]; simp only [foldr_self_append, append_nil, reverse_reverse] + rw [← foldr_reverse]; simp only [foldr_cons_eq_append, append_nil, reverse_reverse] theorem foldl_hom₂ (l : List ι) (f : α → β → γ) (op₁ : α → ι → α) (op₂ : β → ι → β) (op₃ : γ → ι → γ) (a : α) (b : β) (h : ∀ a b i, f (op₁ a i) (op₂ b i) = op₃ (f a b) i) : @@ -1325,52 +1189,6 @@ theorem injective_foldl_comp {l : List (α → α)} {f : α → α} apply Function.Injective.comp hf apply hl _ (List.mem_cons_self _ _) -/-- Induction principle for values produced by a `foldr`: if a property holds -for the seed element `b : β` and for all incremental `op : α → β → β` -performed on the elements `(a : α) ∈ l`. The principle is given for -a `Sort`-valued predicate, i.e., it can also be used to construct data. -/ -def foldrRecOn {C : β → Sort*} (l : List α) (op : α → β → β) (b : β) (hb : C b) - (hl : ∀ b, C b → ∀ a ∈ l, C (op a b)) : C (foldr op b l) := by - induction l with - | nil => exact hb - | cons hd tl IH => - refine hl _ ?_ hd (mem_cons_self hd tl) - refine IH ?_ - intro y hy x hx - exact hl y hy x (mem_cons_of_mem hd hx) - -/-- Induction principle for values produced by a `foldl`: if a property holds -for the seed element `b : β` and for all incremental `op : β → α → β` -performed on the elements `(a : α) ∈ l`. The principle is given for -a `Sort`-valued predicate, i.e., it can also be used to construct data. -/ -def foldlRecOn {C : β → Sort*} (l : List α) (op : β → α → β) (b : β) (hb : C b) - (hl : ∀ b, C b → ∀ a ∈ l, C (op b a)) : C (foldl op b l) := by - induction l generalizing b with - | nil => exact hb - | cons hd tl IH => - refine IH _ ?_ ?_ - · exact hl b hb hd (mem_cons_self hd tl) - · intro y hy x hx - exact hl y hy x (mem_cons_of_mem hd hx) - -@[simp] -theorem foldrRecOn_nil {C : β → Sort*} (op : α → β → β) (b) (hb : C b) (hl) : - foldrRecOn [] op b hb hl = hb := - rfl - -@[simp] -theorem foldrRecOn_cons {C : β → Sort*} (x : α) (l : List α) (op : α → β → β) (b) (hb : C b) - (hl : ∀ b, C b → ∀ a ∈ x :: l, C (op a b)) : - foldrRecOn (x :: l) op b hb hl = - hl _ (foldrRecOn l op b hb fun b hb a ha => hl b hb a (mem_cons_of_mem _ ha)) x - (mem_cons_self _ _) := - rfl - -@[simp] -theorem foldlRecOn_nil {C : β → Sort*} (op : β → α → β) (b) (hb : C b) (hl) : - foldlRecOn [] op b hb hl = hb := - rfl - /-- Consider two lists `l₁` and `l₂` with designated elements `a₁` and `a₂` somewhere in them: `l₁ = x₁ ++ [a₁] ++ z₁` and `l₂ = x₂ ++ [a₂] ++ z₂`. Assume the designated element `a₂` is present in neither `x₁` nor `z₁`. @@ -1424,11 +1242,6 @@ theorem getElem_scanl_zero {h : 0 < (scanl f b l).length} : (scanl f b l)[0] = b theorem get_zero_scanl {h : 0 < (scanl f b l).length} : (scanl f b l).get ⟨0, h⟩ = b := by simp [getElem_scanl_zero] -set_option linter.deprecated false in -@[simp, deprecated get_zero_scanl (since := "2023-01-05")] -theorem nthLe_zero_scanl {h : 0 < (scanl f b l).length} : (scanl f b l).nthLe 0 h = b := - get_zero_scanl - theorem get?_succ_scanl {i : ℕ} : (scanl f b l).get? (i + 1) = ((scanl f b l).get? i).bind fun x => (l.get? i).map fun y => f x y := by induction' l with hd tl hl generalizing b i @@ -1440,33 +1253,24 @@ theorem get?_succ_scanl {i : ℕ} : (scanl f b l).get? (i + 1) = · simp · simp only [hl, get?] -set_option linter.deprecated false in -theorem nthLe_succ_scanl {i : ℕ} {h : i + 1 < (scanl f b l).length} : - (scanl f b l).nthLe (i + 1) h = - f ((scanl f b l).nthLe i (Nat.lt_of_succ_lt h)) - (l.nthLe i (Nat.lt_of_succ_lt_succ (lt_of_lt_of_le h (le_of_eq (length_scanl b l))))) := by +theorem get_succ_scanl {i : ℕ} {h : i + 1 < (scanl f b l).length} : + (scanl f b l).get ⟨i + 1, h⟩ = + f ((scanl f b l).get ⟨i, Nat.lt_of_succ_lt h⟩) + (l.get ⟨i, Nat.lt_of_succ_lt_succ (lt_of_lt_of_le h (le_of_eq (length_scanl b l)))⟩) := by induction i generalizing b l with | zero => cases l · simp only [length, zero_eq, lt_self_iff_false] at h - · simp [scanl_cons, singleton_append, nthLe_zero_scanl, nthLe_cons] + · simp | succ i hi => - cases l - · simp only [length] at h + cases l with + | nil => + simp only [length] at h exact absurd h (by omega) - · simp_rw [scanl_cons] - rw [nthLe_append_right] - · simp only [length, Nat.zero_add 1, succ_add_sub_one, hi]; rfl - · simp only [length_singleton]; omega - -theorem get_succ_scanl {i : ℕ} {h : i + 1 < (scanl f b l).length} : - (scanl f b l).get ⟨i + 1, h⟩ = - f ((scanl f b l).get ⟨i, Nat.lt_of_succ_lt h⟩) - (l.get ⟨i, Nat.lt_of_succ_lt_succ (lt_of_lt_of_le h (le_of_eq (length_scanl b l)))⟩) := - nthLe_succ_scanl - --- FIXME: we should do the proof the other way around -attribute [deprecated get_succ_scanl (since := "2023-01-05")] nthLe_succ_scanl + | cons head tail => + simp_rw [get_of_eq scanl_cons, get_eq_getElem]; rw [getElem_append_right'] + · simp_rw [length_singleton, Nat.add_one_sub_one]; exact hi + · rw [length_singleton]; omega end Scanl @@ -1779,15 +1583,6 @@ theorem sizeOf_lt_sizeOf_of_mem [SizeOf α] {x : α} {l : List α} (hx : x ∈ l @[deprecated attach_map_coe (since := "2024-07-29")] alias attach_map_coe' := attach_map_coe @[deprecated attach_map_val (since := "2024-07-29")] alias attach_map_val' := attach_map_val -set_option linter.deprecated false in -@[deprecated get_pmap (since := "2023-01-05")] -theorem nthLe_pmap {p : α → Prop} (f : ∀ a, p a → β) {l : List α} (h : ∀ a ∈ l, p a) {n : ℕ} - (hn : n < (pmap f l h).length) : - nthLe (pmap f l h) n hn = - f (nthLe l n (@length_pmap _ _ p f l h ▸ hn)) - (h _ (get_mem l n (@length_pmap _ _ p f l h ▸ hn))) := - get_pmap .. - /-! ### find -/ section find? @@ -1971,21 +1766,21 @@ theorem monotone_filter_right (l : List α) ⦃p q : α → Bool⦄ lemma map_filter' {f : α → β} (hf : Injective f) (l : List α) [DecidablePred fun b => ∃ a, p a ∧ f a = b] : (l.filter p).map f = (l.map f).filter fun b => ∃ a, p a ∧ f a = b := by - simp [(· ∘ ·), filter_map, hf.eq_iff] + simp [comp_def, filter_map, hf.eq_iff] lemma filter_attach' (l : List α) (p : {a // a ∈ l} → Bool) [DecidableEq α] : l.attach.filter p = (l.filter fun x => ∃ h, p ⟨x, h⟩).attach.map (Subtype.map id fun x => mem_of_mem_filter) := by classical refine map_injective_iff.2 Subtype.coe_injective ?_ - simp [(· ∘ ·), map_filter' _ Subtype.coe_injective] + simp [comp_def, map_filter' _ Subtype.coe_injective] -- Porting note: `Lean.Internal.coeM` forces us to type-ascript `{x // x ∈ l}` lemma filter_attach (l : List α) (p : α → Bool) : (l.attach.filter fun x => p x : List {x // x ∈ l}) = (l.filter p).attach.map (Subtype.map id fun x => mem_of_mem_filter) := map_injective_iff.2 Subtype.coe_injective <| by - simp_rw [map_map, (· ∘ ·), Subtype.map, id, ← Function.comp_apply (g := Subtype.val), + simp_rw [map_map, comp_def, Subtype.map, id, ← Function.comp_apply (g := Subtype.val), ← filter_map, attach_map_subtype_val] lemma filter_comm (q) (l : List α) : filter p (filter q l) = filter q (filter p l) := by @@ -2010,16 +1805,20 @@ theorem span.loop_eq_take_drop : theorem span_eq_take_drop (l : List α) : span p l = (takeWhile p l, dropWhile p l) := by simpa using span.loop_eq_take_drop p l [] --- TODO update to use `get` instead of `nthLe` -set_option linter.deprecated false in -theorem dropWhile_nthLe_zero_not (l : List α) (hl : 0 < (l.dropWhile p).length) : - ¬p ((l.dropWhile p).nthLe 0 hl) := by +theorem dropWhile_get_zero_not (l : List α) (hl : 0 < (l.dropWhile p).length) : + ¬p ((l.dropWhile p).get ⟨0, hl⟩) := by induction' l with hd tl IH · cases hl · simp only [dropWhile] by_cases hp : p hd - · simp [hp, IH] - · simp [hp, nthLe_cons] + · simp_all only [get_eq_getElem] + apply IH + simp_all only [dropWhile_cons_of_pos] + · simp [hp] + +@[deprecated (since := "2024-08-19")] alias nthLe_tail := get_tail +@[deprecated (since := "2024-08-19")] alias nthLe_cons := get_cons +@[deprecated (since := "2024-08-19")] alias dropWhile_nthLe_zero_not := dropWhile_get_zero_not variable {p} {l : List α} @@ -2027,23 +1826,21 @@ variable {p} {l : List α} theorem dropWhile_eq_nil_iff : dropWhile p l = [] ↔ ∀ x ∈ l, p x := by induction' l with x xs IH · simp [dropWhile] - · by_cases hp : p x <;> simp [hp, dropWhile, IH] + · by_cases hp : p x <;> simp [hp, IH] @[simp] theorem takeWhile_eq_self_iff : takeWhile p l = l ↔ ∀ x ∈ l, p x := by induction' l with x xs IH · simp - · by_cases hp : p x <;> simp [hp, takeWhile_cons, IH] + · by_cases hp : p x <;> simp [hp, IH] --- TODO update to use `get` instead of `nthLe` -set_option linter.deprecated false in @[simp] -theorem takeWhile_eq_nil_iff : takeWhile p l = [] ↔ ∀ hl : 0 < l.length, ¬p (l.nthLe 0 hl) := by +theorem takeWhile_eq_nil_iff : takeWhile p l = [] ↔ ∀ hl : 0 < l.length, ¬p (l.get ⟨0, hl⟩) := by induction' l with x xs IH · simp only [takeWhile_nil, Bool.not_eq_true, true_iff] intro h simp at h - · by_cases hp : p x <;> simp [hp, takeWhile_cons, IH, nthLe_cons] + · by_cases hp : p x <;> simp [hp, IH] theorem mem_takeWhile_imp {x : α} (hx : x ∈ takeWhile p l) : p x := by induction l with simp [takeWhile] at hx @@ -2506,6 +2303,23 @@ theorem disjoint_map {f : α → β} {s t : List α} (hf : Function.Injective f) rw [← pmap_eq_map _ _ _ (fun _ _ ↦ trivial), ← pmap_eq_map _ _ _ (fun _ _ ↦ trivial)] exact disjoint_pmap _ _ (fun _ _ _ _ h' ↦ hf h') h + +theorem Perm.disjoint_left {l₁ l₂ l : List α} (p : List.Perm l₁ l₂) : + Disjoint l₁ l ↔ Disjoint l₂ l := by + simp_rw [List.disjoint_left, p.mem_iff] + +theorem Perm.disjoint_right {l₁ l₂ l : List α} (p : List.Perm l₁ l₂) : + Disjoint l l₁ ↔ Disjoint l l₂ := by + simp_rw [List.disjoint_right, p.mem_iff] + +@[simp] +theorem disjoint_reverse_left {l₁ l₂ : List α} : Disjoint l₁.reverse l₂ ↔ Disjoint l₁ l₂ := + reverse_perm _ |>.disjoint_left + +@[simp] +theorem disjoint_reverse_right {l₁ l₂ : List α} : Disjoint l₁ l₂.reverse ↔ Disjoint l₁ l₂ := + reverse_perm _ |>.disjoint_right + end Disjoint section lookup @@ -2523,3 +2337,5 @@ lemma lookup_graph (f : α → β) {a : α} {as : List α} (h : a ∈ as) : end lookup end List + +set_option linter.style.longFile 2700 diff --git a/Mathlib/Data/List/Chain.lean b/Mathlib/Data/List/Chain.lean index a6c2410414b7d..b73a2aa957cd3 100644 --- a/Mathlib/Data/List/Chain.lean +++ b/Mathlib/Data/List/Chain.lean @@ -6,7 +6,6 @@ Authors: Mario Carneiro, Kenny Lau, Yury Kudryashov import Mathlib.Logic.Relation import Mathlib.Data.List.Forall2 import Mathlib.Data.List.Lex -import Mathlib.Data.List.Infix /-! # Relation chain @@ -37,9 +36,12 @@ theorem Chain.iff {S : α → α → Prop} (H : ∀ a b, R a b ↔ S a b) {a : theorem Chain.iff_mem {a : α} {l : List α} : Chain R a l ↔ Chain (fun x y => x ∈ a :: l ∧ y ∈ l ∧ R x y) a l := ⟨fun p => by - induction' p with _ a b l r _ IH <;> constructor <;> - [exact ⟨mem_cons_self _ _, mem_cons_self _ _, r⟩; - exact IH.imp fun a b ⟨am, bm, h⟩ => ⟨mem_cons_of_mem _ am, mem_cons_of_mem _ bm, h⟩], + induction p with + | nil => exact nil + | @cons _ _ _ r _ IH => + constructor + · exact ⟨mem_cons_self _ _, mem_cons_self _ _, r⟩ + · exact IH.imp fun a b ⟨am, bm, h⟩ => ⟨mem_cons_of_mem _ am, mem_cons_of_mem _ bm, h⟩, Chain.imp fun a b h => h.2.2⟩ theorem chain_singleton {a b : α} : Chain R a [b] ↔ R a b := by @@ -318,31 +320,53 @@ theorem exists_chain_of_relationReflTransGen (h : Relation.ReflTransGen r a b) : refine ⟨d :: l, Chain.cons e hl₁, ?_⟩ rwa [getLast_cons_cons] +/-- Given a chain from `a` to `b`, and a predicate true at `a`, if `r x y → p x → p y` then +the predicate is true everywhere in the chain. +That is, we can propagate the predicate down the chain. +-/ +theorem Chain.induction (p : α → Prop) (l : List α) (h : Chain r a l) + (carries : ∀ ⦃x y : α⦄, r x y → p x → p y) (initial : p a) : ∀ i ∈ l, p i := by + induction h with + | nil => simp + | @cons a b t hab _ h_ind => + simp only [mem_cons, forall_eq_or_imp] + exact ⟨carries hab initial, h_ind (carries hab initial)⟩ + +/-- A version of `List.Chain.induction` for `List.Chain'` +-/ +theorem Chain'.induction (p : α → Prop) (l : List α) (h : Chain' r l) + (carries : ∀ ⦃x y : α⦄, r x y → p x → p y) (initial : (lne : l ≠ []) → p (l.head lne)) : + ∀ i ∈ l, p i := by + unfold Chain' at h + split at h + · simp + · simp_all only [ne_eq, not_false_eq_true, head_cons, true_implies, mem_cons, forall_eq_or_imp, + true_and, reduceCtorEq] + exact h.induction p _ carries initial + /-- Given a chain from `a` to `b`, and a predicate true at `b`, if `r x y → p y → p x` then the predicate is true everywhere in the chain and at `a`. That is, we can propagate the predicate up the chain. -/ -theorem Chain.induction (p : α → Prop) (l : List α) (h : Chain r a l) +theorem Chain.backwards_induction (p : α → Prop) (l : List α) (h : Chain r a l) (hb : getLast (a :: l) (cons_ne_nil _ _) = b) (carries : ∀ ⦃x y : α⦄, r x y → p y → p x) (final : p b) : ∀ i ∈ a :: l, p i := by - induction' l with _ _ l_ih generalizing a - · cases hb - simpa using final - · rw [chain_cons] at h - simp only [mem_cons] - rintro _ (rfl | H) - · apply carries h.1 (l_ih h.2 hb _ (mem_cons.2 (Or.inl rfl))) - · apply l_ih h.2 hb _ (mem_cons.2 H) + have : Chain' (flip (flip r)) (a :: l) := by simpa [Chain'] + replace this := chain'_reverse.mpr this + simp_rw (config := {singlePass := true}) [← List.mem_reverse] + apply this.induction _ _ (fun _ _ h ↦ carries h) + simpa only [ne_eq, reverse_eq_nil_iff, not_false_eq_true, head_reverse, forall_true_left, hb, + reduceCtorEq] /-- Given a chain from `a` to `b`, and a predicate true at `b`, if `r x y → p y → p x` then the predicate is true at `a`. That is, we can propagate the predicate all the way up the chain. -/ @[elab_as_elim] -theorem Chain.induction_head (p : α → Prop) (l : List α) (h : Chain r a l) +theorem Chain.backwards_induction_head (p : α → Prop) (l : List α) (h : Chain r a l) (hb : getLast (a :: l) (cons_ne_nil _ _) = b) (carries : ∀ ⦃x y : α⦄, r x y → p y → p x) (final : p b) : p a := - (Chain.induction p l h hb carries final) _ (mem_cons_self _ _) + (Chain.backwards_induction p l h hb carries final) _ (mem_cons_self _ _) /-- If there is an `r`-chain starting from `a` and ending at `b`, then `a` and `b` are related by the @@ -350,7 +374,7 @@ reflexive transitive closure of `r`. The converse of `exists_chain_of_relationRe -/ theorem relationReflTransGen_of_exists_chain (l : List α) (hl₁ : Chain r a l) (hl₂ : getLast (a :: l) (cons_ne_nil _ _) = b) : Relation.ReflTransGen r a b := - Chain.induction_head _ l hl₁ hl₂ (fun _ _ => Relation.ReflTransGen.head) + Chain.backwards_induction_head _ l hl₁ hl₂ (fun _ _ => Relation.ReflTransGen.head) Relation.ReflTransGen.refl theorem Chain'.cons_of_le [LinearOrder α] {a : α} {as m : List α} @@ -362,7 +386,7 @@ theorem Chain'.cons_of_le [LinearOrder α] {a : α} {as m : List α} apply hm.cons cases as with | nil => - simp only [le_iff_lt_or_eq, or_false] at hmas + simp only [le_iff_lt_or_eq, reduceCtorEq, or_false] at hmas exact (List.Lex.not_nil_right (·<·) _ hmas).elim | cons a' as => rw [List.chain'_cons] at ha @@ -376,6 +400,25 @@ theorem Chain'.cons_of_le [LinearOrder α] {a : α} {as m : List α} exact (List.lt_iff_lex_lt _ _).mp (List.lt.head _ _ hh) · simp_all only [List.cons.injEq, le_refl] +lemma Chain'.chain {α : Type*} {R : α → α → Prop} {l : List α} {v : α} + (hl : l.Chain' R) (hv : (lne : l ≠ []) → R v (l.head lne)) : l.Chain R v := by + rw [List.chain_iff_get] + constructor + · intro h + rw [List.get_mk_zero] + apply hv + · exact List.chain'_iff_get.mp hl + +lemma Chain'.iterate_eq_of_apply_eq {α : Type*} {f : α → α} {l : List α} + (hl : l.Chain' (fun x y ↦ f x = y)) (i : ℕ) (hi : i < l.length) : + f^[i] l[0] = l[i] := by + induction' i with i h + · rfl + · rw [Function.iterate_succ', Function.comp_apply, h (by omega)] + rw [List.chain'_iff_get] at hl + apply hl + omega + end List diff --git a/Mathlib/Data/List/Count.lean b/Mathlib/Data/List/Count.lean index 1e128c3d42e2b..45f4be1166e42 100644 --- a/Mathlib/Data/List/Count.lean +++ b/Mathlib/Data/List/Count.lean @@ -30,7 +30,9 @@ section Count @[simp] theorem count_map_of_injective {β} [DecidableEq α] [DecidableEq β] (l : List α) (f : α → β) (hf : Function.Injective f) (x : α) : count (f x) (map f l) = count x l := by - simp only [count, countP_map, (· ∘ ·), hf.beq_eq] + simp only [count, countP_map] + unfold Function.comp + simp only [hf.beq_eq] variable [DecidableEq α] diff --git a/Mathlib/Data/List/Cycle.lean b/Mathlib/Data/List/Cycle.lean index bcc952df08431..d68df32b94451 100644 --- a/Mathlib/Data/List/Cycle.lean +++ b/Mathlib/Data/List/Cycle.lean @@ -165,7 +165,7 @@ theorem next_getLast_cons (h : x ∈ l) (y : α) (h : x ∈ y :: l) (hy : x ≠ intro H obtain ⟨⟨_ | k, hk⟩, hk'⟩ := get_of_mem H · rw [← Option.some_inj] at hk' - rw [← get?_eq_get, dropLast_eq_take, get?_eq_getElem?, getElem?_take, getElem?_cons_zero, + rw [← get?_eq_get, dropLast_eq_take, get?_eq_getElem?, getElem?_take_of_lt, getElem?_cons_zero, Option.some_inj] at hk' · exact hy (Eq.symm hk') rw [length_cons] @@ -178,7 +178,7 @@ theorem next_getLast_cons (h : x ∈ l) (y : α) (h : x ∈ y :: l) (hy : x ≠ refine Fin.val_eq_of_eq <| @hl ⟨k, Nat.lt_of_succ_lt <| by simpa using hk⟩ ⟨tl.length, by simp⟩ ?_ rw [← Option.some_inj] at hk' - rw [← get?_eq_get, dropLast_eq_take, get?_eq_getElem?, getElem?_take, getElem?_cons_succ, + rw [← get?_eq_get, dropLast_eq_take, get?_eq_getElem?, getElem?_take_of_lt, getElem?_cons_succ, getElem?_eq_getElem, Option.some_inj] at hk' · rw [get_eq_getElem, hk'] simp only [getLast_eq_getElem, length_cons, Nat.succ_eq_add_one, Nat.succ_sub_succ_eq_sub, @@ -233,13 +233,14 @@ theorem prev_mem (h : x ∈ l) : l.prev x h ∈ l := by · exact mem_cons_self _ _ · exact mem_cons_of_mem _ (hl _ _) -theorem next_get : ∀ (l : List α) (_h : Nodup l) (i : Fin l.length), - next l (l.get i) (get_mem _ _ _) = l.get ⟨(i + 1) % l.length, - Nat.mod_lt _ (i.1.zero_le.trans_lt i.2)⟩ +theorem next_get (l : List α) (h : Nodup l) (i : Fin l.length) : + next l (l.get i) (get_mem _ _ _) = + l.get ⟨(i + 1) % l.length, Nat.mod_lt _ (i.1.zero_le.trans_lt i.2)⟩ := + match l, h, i with | [], _, i => by simpa using i.2 | [_], _, _ => by simp | x::y::l, _h, ⟨0, h0⟩ => by - have h₁ : get (x :: y :: l) { val := 0, isLt := h0 } = x := by simp + have h₁ : get (x :: y :: l) ⟨0, h0⟩ = x := by simp rw [next_cons_cons_eq' _ _ _ _ _ h₁] simp | x::y::l, hn, ⟨i+1, hi⟩ => by @@ -273,74 +274,65 @@ theorem next_get : ∀ (l : List α) (_h : Nodup l) (i : Fin l.length), simp at this; simp [this] at hi' · rw [get_cons_succ]; exact get_mem _ _ _ -set_option linter.deprecated false in -@[deprecated next_get (since := "2023-01-27")] -theorem next_nthLe (l : List α) (h : Nodup l) (n : ℕ) (hn : n < l.length) : - next l (l.nthLe n hn) (nthLe_mem _ _ _) = - l.nthLe ((n + 1) % l.length) (Nat.mod_lt _ (n.zero_le.trans_lt hn)) := - next_get l h ⟨n, hn⟩ - -set_option linter.deprecated false in -theorem prev_nthLe (l : List α) (h : Nodup l) (n : ℕ) (hn : n < l.length) : - prev l (l.nthLe n hn) (nthLe_mem _ _ _) = - l.nthLe ((n + (l.length - 1)) % l.length) (Nat.mod_lt _ (n.zero_le.trans_lt hn)) := by - cases' l with x l - · simp at hn - induction' l with y l hl generalizing n x - · simp - · rcases n with (_ | _ | n) - · simp [Nat.add_succ_sub_one, add_zero, List.prev_cons_cons_eq, List.length, - List.nthLe, Nat.succ_add_sub_one, zero_add, getLast_eq_get, - Nat.mod_eq_of_lt (Nat.succ_lt_succ l.length.lt_succ_self)] - · simp only [mem_cons, nodup_cons] at h - push_neg at h - simp only [List.prev_cons_cons_of_ne _ _ _ _ h.left.left.symm, List.length, - List.nthLe, add_comm, eq_self_iff_true, Nat.succ_add_sub_one, Nat.mod_self, zero_add, - List.get] - · rw [prev_ne_cons_cons] - · convert hl n.succ y h.of_cons (Nat.le_of_succ_le_succ hn) using 1 - have : ∀ k hk, (y :: l).nthLe k hk = (x :: y :: l).nthLe (k + 1) (Nat.succ_lt_succ hk) := by - simp [List.nthLe] - rw [this] - congr - simp only [Nat.add_succ_sub_one, add_zero, length] - simp only [length, Nat.succ_lt_succ_iff] at hn - set k := l.length - rw [Nat.succ_add, ← Nat.add_succ, Nat.add_mod_right, Nat.succ_add, ← Nat.add_succ _ k, - Nat.add_mod_right, Nat.mod_eq_of_lt, Nat.mod_eq_of_lt] - · exact Nat.lt_succ_of_lt hn - · exact Nat.succ_lt_succ (Nat.lt_succ_of_lt hn) - · intro H - suffices n.succ.succ = 0 by simpa - rw [nodup_iff_nthLe_inj] at h - refine h _ _ hn Nat.succ_pos' ?_ - simpa using H - · intro H - suffices n.succ.succ = 1 by simpa - rw [nodup_iff_nthLe_inj] at h - refine h _ _ hn (Nat.succ_lt_succ Nat.succ_pos') ?_ - simpa using H - -set_option linter.deprecated false in +-- Unused variable linter incorrectly reports that `h` is unused here. +set_option linter.unusedVariables false in +theorem prev_get (l : List α) (h : Nodup l) (i : Fin l.length) : + prev l (l.get i) (get_mem _ _ _) = + l.get ⟨(i + (l.length - 1)) % l.length, Nat.mod_lt _ i.pos⟩ := + match l with + | [] => by simpa using i.2 + | x::l => by + obtain ⟨n, hn⟩ := i + induction l generalizing n x with + | nil => simp + | cons y l hl => + rcases n with (_ | _ | n) + · simp [getLast_eq_getElem] + · simp only [mem_cons, nodup_cons] at h + push_neg at h + simp only [List.prev_cons_cons_of_ne _ _ _ _ h.left.left.symm, List.length, + List.get, add_comm, Nat.succ_add_sub_one, Nat.mod_self, zero_add] + · rw [prev_ne_cons_cons] + · convert hl y h.of_cons n.succ (Nat.le_of_succ_le_succ hn) using 1 + have : ∀ k hk, (y :: l).get ⟨k, hk⟩ = (x :: y :: l).get ⟨k + 1, Nat.succ_lt_succ hk⟩ := by + simp [List.get] + rw [this] + congr + simp only [Nat.add_succ_sub_one, add_zero, length] + simp only [length, Nat.succ_lt_succ_iff] at hn + set k := l.length + rw [Nat.succ_add, ← Nat.add_succ, Nat.add_mod_right, Nat.succ_add, ← Nat.add_succ _ k, + Nat.add_mod_right, Nat.mod_eq_of_lt, Nat.mod_eq_of_lt] + · exact Nat.lt_succ_of_lt hn + · exact Nat.succ_lt_succ (Nat.lt_succ_of_lt hn) + · intro H + suffices n.succ.succ = 0 by simpa + suffices Fin.mk _ hn = ⟨0, by omega⟩ by rwa [Fin.mk.inj_iff] at this + rw [nodup_iff_injective_get] at h + apply h; rw [← H]; simp + · intro H + suffices n.succ.succ = 1 by simpa + suffices Fin.mk _ hn = ⟨1, by omega⟩ by rwa [Fin.mk.inj_iff] at this + rw [nodup_iff_injective_get] at h + apply h; rw [← H]; simp + theorem pmap_next_eq_rotate_one (h : Nodup l) : (l.pmap l.next fun _ h => h) = l.rotate 1 := by - apply List.ext_nthLe + apply List.ext_get · simp · intros - rw [nthLe_pmap, nthLe_rotate, next_nthLe _ h] + rw [get_pmap, get_rotate, next_get _ h] -set_option linter.deprecated false in theorem pmap_prev_eq_rotate_length_sub_one (h : Nodup l) : (l.pmap l.prev fun _ h => h) = l.rotate (l.length - 1) := by - apply List.ext_nthLe + apply List.ext_get · simp · intro n hn hn' - rw [nthLe_rotate, nthLe_pmap, prev_nthLe _ h] + rw [get_rotate, get_pmap, prev_get _ h] -set_option linter.deprecated false in theorem prev_next (l : List α) (h : Nodup l) (x : α) (hx : x ∈ l) : prev l (next l x hx) (next_mem _ _ _) = x := by - obtain ⟨n, hn, rfl⟩ := nthLe_of_mem hx - simp only [next_nthLe, prev_nthLe, h, Nat.mod_add_mod] + 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 · have : (n + 1 + length tl) % (length tl + 1) = n := by @@ -348,11 +340,10 @@ theorem prev_next (l : List α) (h : Nodup l) (x : α) (hx : x ∈ l) : rw [add_assoc, add_comm 1, Nat.add_mod_right, Nat.mod_eq_of_lt hn] simp only [length_cons, Nat.succ_sub_succ_eq_sub, Nat.sub_zero, Nat.succ_eq_add_one, this] -set_option linter.deprecated false in theorem next_prev (l : List α) (h : Nodup l) (x : α) (hx : x ∈ l) : next l (prev l x hx) (prev_mem _ _ _) = x := by - obtain ⟨n, hn, rfl⟩ := nthLe_of_mem hx - simp only [next_nthLe, prev_nthLe, h, Nat.mod_add_mod] + 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 · have : (n + length tl + 1) % (length tl + 1) = n := by @@ -360,21 +351,19 @@ theorem next_prev (l : List α) (h : Nodup l) (x : α) (hx : x ∈ l) : rw [add_assoc, Nat.add_mod_right, Nat.mod_eq_of_lt hn] simp [this] -set_option linter.deprecated false in theorem prev_reverse_eq_next (l : List α) (h : Nodup l) (x : α) (hx : x ∈ l) : prev l.reverse x (mem_reverse.mpr hx) = next l x hx := by - obtain ⟨k, hk, rfl⟩ := nthLe_of_mem hx + obtain ⟨k, hk, rfl⟩ := getElem_of_mem hx have lpos : 0 < l.length := k.zero_le.trans_lt hk have key : l.length - 1 - k < l.length := by omega - rw [← nthLe_pmap l.next (fun _ h => h) (by simpa using hk)] - simp_rw [← nthLe_reverse l k (key.trans_le (by simp)), pmap_next_eq_rotate_one _ h] - rw [← nthLe_pmap l.reverse.prev fun _ h => h] + rw [← getElem_pmap l.next (fun _ h => h) (by simpa using hk)] + simp_rw [getElem_eq_getElem_reverse (l := l), pmap_next_eq_rotate_one _ h] + rw [← getElem_pmap l.reverse.prev fun _ h => h] · simp_rw [pmap_prev_eq_rotate_length_sub_one _ (nodup_reverse.mpr h), rotate_reverse, length_reverse, Nat.mod_eq_of_lt (Nat.sub_lt lpos Nat.succ_pos'), Nat.sub_sub_self (Nat.succ_le_of_lt lpos)] - rw [← nthLe_reverse] + rw [getElem_eq_getElem_reverse] · simp [Nat.sub_sub_self (Nat.le_sub_one_of_lt hk)] - · simpa using (Nat.sub_le _ _).trans_lt (Nat.sub_lt lpos Nat.succ_pos') · simpa theorem next_reverse_eq_prev (l : List α) (h : Nodup l) (x : α) (hx : x ∈ l) : @@ -466,7 +455,7 @@ theorem induction_on {C : Cycle α → Prop} (s : Cycle α) (H0 : C nil) assumption' /-- For `x : α`, `s : Cycle α`, `x ∈ s` indicates that `x` occurs at least once in `s`. -/ -def Mem (a : α) (s : Cycle α) : Prop := +def Mem (s : Cycle α) (a : α) : Prop := Quot.liftOn s (fun l => a ∈ l) fun _ _ e => propext <| e.mem_iff instance : Membership α (Cycle α) := @@ -678,10 +667,10 @@ def decidableNontrivialCoe : ∀ l : List α, Decidable (Nontrivial (l : Cycle else isTrue ⟨x, y, h, by simp, by simp⟩ instance {s : Cycle α} : Decidable (Nontrivial s) := - Quot.recOnSubsingleton' s decidableNontrivialCoe + Quot.recOnSubsingleton s decidableNontrivialCoe instance {s : Cycle α} : Decidable (Nodup s) := - Quot.recOnSubsingleton' s List.nodupDecidable + Quot.recOnSubsingleton s List.nodupDecidable instance fintypeNodupCycle [Fintype α] : Fintype { s : Cycle α // s.Nodup } := Fintype.ofSurjective (fun l : { l : List α // l.Nodup } => ⟨l.val, by simpa using l.prop⟩) diff --git a/Mathlib/Data/List/Dedup.lean b/Mathlib/Data/List/Dedup.lean index d75adc40ad06c..bb2bf2901cd89 100644 --- a/Mathlib/Data/List/Dedup.lean +++ b/Mathlib/Data/List/Dedup.lean @@ -5,6 +5,7 @@ Authors: Mario Carneiro -/ import Mathlib.Data.List.Nodup import Mathlib.Data.List.Lattice +import Batteries.Data.List.Pairwise /-! # Erasure of duplicates in a list @@ -95,7 +96,7 @@ theorem dedup_eq_nil (l : List α) : l.dedup = [] ↔ l = [] := by induction' l with a l hl · exact Iff.rfl · by_cases h : a ∈ l - · simp only [List.dedup_cons_of_mem h, hl, List.ne_nil_of_mem h] + · simp only [List.dedup_cons_of_mem h, hl, List.ne_nil_of_mem h, reduceCtorEq] · simp only [List.dedup_cons_of_not_mem h, List.cons_ne_nil] protected theorem Nodup.dedup {l : List α} (h : l.Nodup) : l.dedup = l := diff --git a/Mathlib/Data/List/Defs.lean b/Mathlib/Data/List/Defs.lean index fc6eaa2b034dc..80750fd2c8b30 100644 --- a/Mathlib/Data/List/Defs.lean +++ b/Mathlib/Data/List/Defs.lean @@ -446,4 +446,64 @@ theorem iterate_eq_iterateTR : @iterate = @iterateTR := by funext α f a n exact Eq.symm <| iterateTR_loop_eq f a n [] +section MapAccumr + +/-- Runs a function over a list returning the intermediate results and a final result. -/ +def mapAccumr (f : α → γ → γ × β) : List α → γ → γ × List β + | [], c => (c, []) + | y :: yr, c => + let r := mapAccumr f yr c + let z := f y r.1 + (z.1, z.2 :: r.2) + +/-- Length of the list obtained by `mapAccumr`. -/ +@[simp] +theorem length_mapAccumr : + ∀ (f : α → γ → γ × β) (x : List α) (s : γ), length (mapAccumr f x s).2 = length x + | f, _ :: x, s => congr_arg succ (length_mapAccumr f x s) + | _, [], _ => rfl + +/-- Runs a function over two lists returning the intermediate results and a final result. -/ +def mapAccumr₂ (f : α → β → γ → γ × δ) : List α → List β → γ → γ × List δ + | [], _, c => (c, []) + | _, [], c => (c, []) + | x :: xr, y :: yr, c => + let r := mapAccumr₂ f xr yr c + let q := f x y r.1 + (q.1, q.2 :: r.2) + +/-- Length of a list obtained using `mapAccumr₂`. -/ +@[simp] +theorem length_mapAccumr₂ : + ∀ (f : α → β → γ → γ × δ) (x y c), length (mapAccumr₂ f x y c).2 = min (length x) (length y) + | f, _ :: x, _ :: y, c => + calc + succ (length (mapAccumr₂ f x y c).2) = succ (min (length x) (length y)) := + congr_arg succ (length_mapAccumr₂ f x y c) + _ = min (succ (length x)) (succ (length y)) := Eq.symm (succ_min_succ (length x) (length y)) + | _, _ :: _, [], _ => rfl + | _, [], _ :: _, _ => rfl + | _, [], [], _ => rfl + +end MapAccumr + +section Deprecated + +@[deprecated List.mem_cons (since := "2024-08-10")] +theorem mem_cons_eq (a y : α) (l : List α) : (a ∈ y :: l) = (a = y ∨ a ∈ l) := + propext List.mem_cons + +alias ⟨eq_or_mem_of_mem_cons, _⟩ := mem_cons + +@[deprecated List.not_mem_nil (since := "2024-08-10")] +theorem not_exists_mem_nil (p : α → Prop) : ¬∃ x ∈ @nil α, p x := + fun ⟨_, hx, _⟩ => List.not_mem_nil _ hx + +@[deprecated (since := "2024-03-23")] alias not_bex_nil := not_exists_mem_nil +@[deprecated (since := "2024-03-23")] alias bex_cons := exists_mem_cons + +@[deprecated (since := "2024-08-10")] alias length_le_of_sublist := Sublist.length_le + +end Deprecated + end List diff --git a/Mathlib/Data/List/DropRight.lean b/Mathlib/Data/List/DropRight.lean index 6a591c57257f2..10638f80de52e 100644 --- a/Mathlib/Data/List/DropRight.lean +++ b/Mathlib/Data/List/DropRight.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 Yakov Pechersky. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yakov Pechersky -/ -import Mathlib.Data.List.Infix +import Mathlib.Data.List.Basic /-! # Dropping or taking from lists on the right @@ -155,7 +155,7 @@ variable (p) (l) theorem dropWhile_idempotent : dropWhile p (dropWhile p l) = dropWhile p l := by simp only [dropWhile_eq_self_iff] - exact fun h => dropWhile_nthLe_zero_not p l h + exact fun h => dropWhile_get_zero_not p l h theorem rdropWhile_idempotent : rdropWhile p (rdropWhile p l) = rdropWhile p l := rdropWhile_eq_self_iff.mpr (rdropWhile_last_not _ _) @@ -198,7 +198,7 @@ theorem rtakeWhile_eq_nil_iff : rtakeWhile p l = [] ↔ ∀ hl : l ≠ [], ¬p ( · simp only [rtakeWhile, takeWhile, reverse_nil, true_iff] intro f; contradiction · simp only [rtakeWhile, reverse_append, takeWhile, ne_eq, not_false_eq_true, - getLast_append_of_ne_nil, getLast_singleton] + getLast_append_of_ne_nil, getLast_singleton, reduceCtorEq] refine ⟨fun h => ?_ , fun h => ?_⟩ · split at h <;> simp_all · simp [h] diff --git a/Mathlib/Data/List/Duplicate.lean b/Mathlib/Data/List/Duplicate.lean index 0a020d73eafca..9023118d20cb8 100644 --- a/Mathlib/Data/List/Duplicate.lean +++ b/Mathlib/Data/List/Duplicate.lean @@ -39,9 +39,9 @@ theorem Duplicate.duplicate_cons (h : x ∈+ l) (y : α) : x ∈+ y :: l := Duplicate.cons_duplicate h theorem Duplicate.mem (h : x ∈+ l) : x ∈ l := by - induction' h with l' _ y l' _ hm - · exact mem_cons_self _ _ - · exact mem_cons_of_mem _ hm + induction h with + | cons_mem => exact mem_cons_self _ _ + | cons_duplicate _ hm => exact mem_cons_of_mem _ hm theorem Duplicate.mem_cons_self (h : x ∈+ x :: l) : x ∈ l := by cases' h with _ h _ _ h diff --git a/Mathlib/Data/List/EditDistance/Estimator.lean b/Mathlib/Data/List/EditDistance/Estimator.lean index 4b79e8b7234fa..056d119f6af71 100644 --- a/Mathlib/Data/List/EditDistance/Estimator.lean +++ b/Mathlib/Data/List/EditDistance/Estimator.lean @@ -90,7 +90,7 @@ instance estimator' : constructor · simp only [List.minimum_of_length_pos_le_iff] exact suffixLevenshtein_minimum_le_levenshtein_append _ _ _ - · exact List.length_le_of_sublist (List.sublist_append_right _ _) + · exact (List.sublist_append_right _ _).length_le improve_spec e := by dsimp [EstimatorData.improve] match e.pre_rev, e.split, e.bound_eq, e.distances_eq with diff --git a/Mathlib/Data/List/Enum.lean b/Mathlib/Data/List/Enum.lean index e7bd524eb313e..edc801c308976 100644 --- a/Mathlib/Data/List/Enum.lean +++ b/Mathlib/Data/List/Enum.lean @@ -9,47 +9,58 @@ import Mathlib.Data.Nat.Notation /-! # Properties of `List.enum` + +## Deprecation note +Everything in this file has been replaced by theorems in Lean4, +in terms of `xs[i]?` and `xs[i]` rather than `get` and `get?`. + +The results here are unused in Mathlib, and deprecated. +Any downstream users who can not easily adapt may remove the deprecations as needed. -/ namespace List variable {α β : Type*} +@[deprecated getElem?_enumFrom (since := "2024-08-15")] theorem get?_enumFrom (n) (l : List α) (m) : get? (enumFrom n l) m = (get? l m).map fun a => (n + m, a) := by simp @[deprecated (since := "2024-04-06")] alias enumFrom_get? := get?_enumFrom +@[deprecated getElem?_enum (since := "2024-08-15")] theorem get?_enum (l : List α) (n) : get? (enum l) n = (get? l n).map fun a => (n, a) := by simp @[deprecated (since := "2024-04-06")] alias enum_get? := get?_enum +@[deprecated getElem_enumFrom (since := "2024-08-15")] theorem get_enumFrom (l : List α) (n) (i : Fin (l.enumFrom n).length) : (l.enumFrom n).get i = (n + i, l.get (i.cast enumFrom_length)) := by simp +@[deprecated getElem_enum (since := "2024-08-15")] theorem get_enum (l : List α) (i : Fin l.enum.length) : l.enum.get i = (i.1, l.get (i.cast enum_length)) := by simp +@[deprecated mk_add_mem_enumFrom_iff_getElem? (since := "2024-08-12")] theorem mk_add_mem_enumFrom_iff_get? {n i : ℕ} {x : α} {l : List α} : (n + i, x) ∈ enumFrom n l ↔ l.get? i = x := by simp [mem_iff_get?] +@[deprecated mk_mem_enumFrom_iff_le_and_getElem?_sub (since := "2024-08-12")] theorem mk_mem_enumFrom_iff_le_and_get?_sub {n i : ℕ} {x : α} {l : List α} : (i, x) ∈ enumFrom n l ↔ n ≤ i ∧ l.get? (i - n) = x := by - if h : n ≤ i then - rcases Nat.exists_eq_add_of_le h with ⟨i, rfl⟩ - simp [mk_add_mem_enumFrom_iff_get?, Nat.add_sub_cancel_left] - else - have : ∀ k, n + k ≠ i := by rintro k rfl; simp at h - simp [h, mem_iff_get?, this] + simp [mk_mem_enumFrom_iff_le_and_getElem?_sub] +@[deprecated mk_mem_enum_iff_getElem? (since := "2024-08-15")] theorem mk_mem_enum_iff_get? {i : ℕ} {x : α} {l : List α} : (i, x) ∈ enum l ↔ l.get? i = x := by - simp [enum, mk_mem_enumFrom_iff_le_and_get?_sub] + simp [enum, mk_mem_enumFrom_iff_le_and_getElem?_sub] +set_option linter.deprecated false in +@[deprecated mem_enum_iff_getElem? (since := "2024-08-15")] theorem mem_enum_iff_get? {x : ℕ × α} {l : List α} : x ∈ enum l ↔ l.get? x.1 = x.2 := mk_mem_enum_iff_get? diff --git a/Mathlib/Data/List/FinRange.lean b/Mathlib/Data/List/FinRange.lean index 3ca008028c7c7..bb4b35d88e9a0 100644 --- a/Mathlib/Data/List/FinRange.lean +++ b/Mathlib/Data/List/FinRange.lean @@ -5,6 +5,7 @@ Authors: Mario Carneiro, Kenny Lau, Scott Morrison, Alex Keizer -/ import Mathlib.Data.List.OfFn import Mathlib.Data.List.Range +import Batteries.Data.List.Perm /-! # Lists of elements of `Fin n` @@ -29,7 +30,7 @@ theorem finRange_succ_eq_map (n : ℕ) : finRange n.succ = 0 :: (finRange n).map apply map_injective_iff.mpr Fin.val_injective rw [map_cons, map_coe_finRange, range_succ_eq_map, Fin.val_zero, ← map_coe_finRange, map_map, map_map] - simp only [Function.comp, Fin.val_succ] + simp only [Function.comp_def, Fin.val_succ] theorem finRange_succ (n : ℕ) : finRange n.succ = (finRange n |>.map Fin.castSucc |>.concat (.last _)) := by diff --git a/Mathlib/Data/List/Forall2.lean b/Mathlib/Data/List/Forall2.lean index 132891a19defd..f2e78d52a7c08 100644 --- a/Mathlib/Data/List/Forall2.lean +++ b/Mathlib/Data/List/Forall2.lean @@ -136,10 +136,6 @@ theorem Forall₂.get : | _, _, Forall₂.cons ha _, 0, _, _ => ha | _, _, Forall₂.cons _ hl, succ _, _, _ => hl.get _ _ -set_option linter.deprecated false in -@[deprecated (since := "2024-05-05")] theorem Forall₂.nthLe {x y} (h : Forall₂ R x y) ⦃i : ℕ⦄ - (hx : i < x.length) (hy : i < y.length) : R (x.nthLe i hx) (y.nthLe i hy) := h.get hx hy - theorem forall₂_of_length_eq_of_get : ∀ {x : List α} {y : List β}, x.length = y.length → (∀ i h₁ h₂, R (x.get ⟨i, h₁⟩) (y.get ⟨i, h₂⟩)) → Forall₂ R x y @@ -149,20 +145,10 @@ theorem forall₂_of_length_eq_of_get : (forall₂_of_length_eq_of_get (succ.inj hl) fun i h₁ h₂ => h i.succ (succ_lt_succ h₁) (succ_lt_succ h₂)) -set_option linter.deprecated false in -@[deprecated (since := "2024-05-05")] theorem forall₂_of_length_eq_of_nthLe {x y} - (H : x.length = y.length) (H' : ∀ i h₁ h₂, R (x.nthLe i h₁) (y.nthLe i h₂)) : - Forall₂ R x y := forall₂_of_length_eq_of_get H H' - theorem forall₂_iff_get {l₁ : List α} {l₂ : List β} : Forall₂ R l₁ l₂ ↔ l₁.length = l₂.length ∧ ∀ i h₁ h₂, R (l₁.get ⟨i, h₁⟩) (l₂.get ⟨i, h₂⟩) := ⟨fun h => ⟨h.length_eq, h.get⟩, fun h => forall₂_of_length_eq_of_get h.1 h.2⟩ -set_option linter.deprecated false in -@[deprecated (since := "2024-05-05")] theorem forall₂_iff_nthLe {l₁ : List α} {l₂ : List β} : - Forall₂ R l₁ l₂ ↔ l₁.length = l₂.length ∧ ∀ i h₁ h₂, R (l₁.nthLe i h₁) (l₂.nthLe i h₂) := - forall₂_iff_get - theorem forall₂_zip : ∀ {l₁ l₂}, Forall₂ R l₁ l₂ → ∀ {a b}, (a, b) ∈ zip l₁ l₂ → R a b | _, _, Forall₂.cons h₁ h₂, x, y, hx => by rw [zip, zipWith, mem_cons] at hx @@ -282,19 +268,25 @@ inductive SublistForall₂ (R : α → β → Prop) : List α → List β → Pr theorem sublistForall₂_iff {l₁ : List α} {l₂ : List β} : SublistForall₂ R l₁ l₂ ↔ ∃ l, Forall₂ R l₁ l ∧ l <+ l₂ := by constructor <;> intro h - · induction' h with _ a b l1 l2 rab _ ih b l1 l2 _ ih - · exact ⟨nil, Forall₂.nil, nil_sublist _⟩ - · obtain ⟨l, hl1, hl2⟩ := ih + · induction h with + | nil => exact ⟨nil, Forall₂.nil, nil_sublist _⟩ + | @cons a b l1 l2 rab _ ih => + obtain ⟨l, hl1, hl2⟩ := ih exact ⟨b :: l, Forall₂.cons rab hl1, hl2.cons_cons b⟩ - · obtain ⟨l, hl1, hl2⟩ := ih + | cons_right _ ih => + obtain ⟨l, hl1, hl2⟩ := ih exact ⟨l, hl1, hl2.trans (Sublist.cons _ (Sublist.refl _))⟩ · obtain ⟨l, hl1, hl2⟩ := h revert l₁ - induction' hl2 with _ _ _ _ ih _ _ _ _ ih <;> intro l₁ hl1 - · rw [forall₂_nil_right_iff.1 hl1] + induction hl2 with + | slnil => + intro l₁ hl1 + rw [forall₂_nil_right_iff.1 hl1] exact SublistForall₂.nil - · exact SublistForall₂.cons_right (ih hl1) - · cases' hl1 with _ _ _ _ hr hl _ + | cons _ _ ih => intro l₁ hl1; exact SublistForall₂.cons_right (ih hl1) + | cons₂ _ _ ih => + intro l₁ hl1 + cases' hl1 with _ _ _ _ hr hl _ exact SublistForall₂.cons hr (ih hl) instance SublistForall₂.is_refl [IsRefl α Rₐ] : IsRefl (List α) (SublistForall₂ Rₐ) := @@ -303,11 +295,13 @@ instance SublistForall₂.is_refl [IsRefl α Rₐ] : IsRefl (List α) (SublistFo instance SublistForall₂.is_trans [IsTrans α Rₐ] : IsTrans (List α) (SublistForall₂ Rₐ) := ⟨fun a b c => by revert a b - induction' c with _ _ ih - · rintro _ _ h1 h2 + induction c with + | nil => + rintro _ _ h1 h2 cases h2 exact h1 - · rintro a b h1 h2 + | cons _ _ ih => + rintro a b h1 h2 cases' h2 with _ _ _ _ _ hbc tbc _ _ y1 btc · cases h1 exact SublistForall₂.nil @@ -324,4 +318,22 @@ theorem Sublist.sublistForall₂ {l₁ l₂ : List α} (h : l₁ <+ l₂) [IsRef theorem tail_sublistForall₂_self [IsRefl α Rₐ] (l : List α) : SublistForall₂ Rₐ l.tail l := l.tail_sublist.sublistForall₂ +@[simp] +theorem sublistForall₂_map_left_iff {f : γ → α} {l₁ : List γ} {l₂ : List β} : + SublistForall₂ R (map f l₁) l₂ ↔ SublistForall₂ (fun c b => R (f c) b) l₁ l₂ := by + simp [sublistForall₂_iff] + +@[simp] +theorem sublistForall₂_map_right_iff {f : γ → β} {l₁ : List α} {l₂ : List γ} : + SublistForall₂ R l₁ (map f l₂) ↔ SublistForall₂ (fun a c => R a (f c)) l₁ l₂ := by + simp only [sublistForall₂_iff] + constructor + · rintro ⟨l1, h1, h2⟩ + obtain ⟨l', hl1, rfl⟩ := sublist_map_iff.mp h2 + use l' + simpa [hl1] using h1 + · rintro ⟨l1, h1, h2⟩ + use l1.map f + simp [h1, h2.map] + end List diff --git a/Mathlib/Data/List/GetD.lean b/Mathlib/Data/List/GetD.lean index d11003beb0ec4..bc144f95b4785 100644 --- a/Mathlib/Data/List/GetD.lean +++ b/Mathlib/Data/List/GetD.lean @@ -110,11 +110,11 @@ theorem getI_cons_succ : getI (x :: xs) (n + 1) = getI xs n := rfl theorem getI_eq_getElem {n : ℕ} (hn : n < l.length) : l.getI n = l[n] := - getD_eq_getElem .. + getD_eq_getElem l default hn @[deprecated getI_eq_getElem (since := "2024-08-02")] theorem getI_eq_get {n : ℕ} (hn : n < l.length) : l.getI n = l.get ⟨n, hn⟩ := - getD_eq_getElem .. + getD_eq_getElem l default hn theorem getI_eq_default {n : ℕ} (hn : l.length ≤ n) : l.getI n = default := getD_eq_default _ _ hn diff --git a/Mathlib/Data/List/Indexes.lean b/Mathlib/Data/List/Indexes.lean index a9af61d933c06..b2351ad435a24 100644 --- a/Mathlib/Data/List/Indexes.lean +++ b/Mathlib/Data/List/Indexes.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Jannis Limperg -/ import Mathlib.Data.List.OfFn -import Mathlib.Data.List.Range import Mathlib.Data.List.Zip /-! @@ -161,13 +160,13 @@ theorem mapIdx_append (K L : List α) (f : ℕ → α → β) : 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] -set_option linter.deprecated false in -@[simp, deprecated (since := "2023-02-11")] -theorem nthLe_mapIdx (l : List α) (f : ℕ → α → β) (i : ℕ) (h : i < l.length) +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) : - (l.mapIdx f).nthLe i h' = f i (l.nthLe i h) := by + (l.mapIdx f).get ⟨i, h'⟩ = f i (l.get ⟨i, h⟩) := by simp [mapIdx_eq_enum_map, enum_eq_zip_range] +@[deprecated (since := "2024-08-19")] alias nthLe_mapIdx := get_mapIdx + theorem mapIdx_eq_ofFn (l : List α) (f : ℕ → α → β) : l.mapIdx f = ofFn fun i : Fin l.length ↦ f (i : ℕ) (l.get i) := by induction l generalizing f with @@ -283,73 +282,6 @@ theorem findIdxs_eq_map_indexesValues (p : α → Prop) [DecidablePred p] (as : map_filter_eq_foldr, findIdxs, uncurry, foldrIdx_eq_foldr_enum, decide_eq_true_eq, comp_apply, Bool.cond_decide] -section FindIdx -- TODO: upstream to Batteries - -theorem findIdx_eq_length {p : α → Bool} {xs : List α} : - xs.findIdx p = xs.length ↔ ∀ x ∈ xs, ¬p x := by - induction xs with - | nil => simp_all - | cons x xs ih => - rw [findIdx_cons, length_cons] - constructor <;> intro h - · have : ¬p x := by contrapose h; simp_all - simp_all - · simp_rw [h x (mem_cons_self x xs), cond_false, Nat.succ.injEq, ih] - exact fun y hy ↦ h y <| mem_cons.mpr (Or.inr hy) - -theorem findIdx_le_length (p : α → Bool) {xs : List α} : xs.findIdx p ≤ xs.length := by - by_cases e : ∃ x ∈ xs, p x - · exact (findIdx_lt_length_of_exists e).le - · push_neg at e; exact (findIdx_eq_length.mpr e).le - -theorem findIdx_lt_length {p : α → Bool} {xs : List α} : - xs.findIdx p < xs.length ↔ ∃ x ∈ xs, p x := by - rw [← not_iff_not, not_lt] - have := @le_antisymm_iff _ _ (xs.findIdx p) xs.length - simp only [findIdx_le_length, true_and] at this - rw [← this, findIdx_eq_length, not_exists] - simp only [Bool.not_eq_true, not_and] - -/-- `p` does not hold for elements with indices less than `xs.findIdx p`. -/ -theorem not_of_lt_findIdx {p : α → Bool} {xs : List α} {i : ℕ} (h : i < xs.findIdx p) : - ¬p (xs.get ⟨i, h.trans_le (findIdx_le_length p)⟩) := by - revert i - induction xs with - | nil => intro i h; rw [findIdx_nil] at h; omega - | cons x xs ih => - intro i h - have ho := h - rw [findIdx_cons] at h - have npx : ¬p x := by by_contra y; rw [y, cond_true] at h; omega - simp_rw [npx, cond_false] at h - cases' i.eq_zero_or_pos with e e - · simpa only [e, Fin.zero_eta, get_cons_zero] - · have ipm := Nat.succ_pred_eq_of_pos e - have ilt := ho.trans_le (findIdx_le_length p) - rw [(Fin.mk_eq_mk (h' := ipm ▸ ilt)).mpr ipm.symm, get_cons_succ] - rw [← ipm, Nat.succ_lt_succ_iff] at h - exact ih h - -theorem le_findIdx_of_not {p : α → Bool} {xs : List α} {i : ℕ} (h : i < xs.length) - (h2 : ∀ j (hji : j < i), ¬p (xs.get ⟨j, hji.trans h⟩)) : i ≤ xs.findIdx p := by - by_contra! f - exact absurd (@findIdx_get _ p xs (f.trans h)) (h2 (xs.findIdx p) f) - -theorem lt_findIdx_of_not {p : α → Bool} {xs : List α} {i : ℕ} (h : i < xs.length) - (h2 : ∀ j (hji : j ≤ i), ¬p (xs.get ⟨j, hji.trans_lt h⟩)) : i < xs.findIdx p := by - by_contra! f - exact absurd (@findIdx_get _ p xs (f.trans_lt h)) (h2 (xs.findIdx p) f) - -theorem findIdx_eq {p : α → Bool} {xs : List α} {i : ℕ} (h : i < xs.length) : - xs.findIdx p = i ↔ p (xs.get ⟨i, h⟩) ∧ ∀ j (hji : j < i), ¬p (xs.get ⟨j, hji.trans h⟩) := by - refine ⟨fun f ↦ ⟨f ▸ (@findIdx_get _ p xs (f ▸ h)), fun _ hji ↦ not_of_lt_findIdx (f ▸ hji)⟩, - fun ⟨h1, h2⟩ ↦ ?_⟩ - apply Nat.le_antisymm _ (le_findIdx_of_not h h2) - contrapose! h1 - exact not_of_lt_findIdx h1 - -end FindIdx - section FoldlIdx -- Porting note: Changed argument order of `foldlIdxSpec` to align better with `foldlIdx`. diff --git a/Mathlib/Data/List/Infix.lean b/Mathlib/Data/List/Infix.lean index 4dcb64c9655da..4218035da5095 100644 --- a/Mathlib/Data/List/Infix.lean +++ b/Mathlib/Data/List/Infix.lean @@ -25,8 +25,6 @@ All those (except `insert`) are defined in `Mathlib.Data.List.Defs`. * `l₁ <:+: l₂`: `l₁` is an infix of `l₂`. -/ -open Nat - variable {α β : Type*} namespace List @@ -35,45 +33,23 @@ variable {l l₁ l₂ l₃ : List α} {a b : α} {m n : ℕ} /-! ### prefix, suffix, infix -/ - section Fix -theorem prefix_rfl : l <+: l := - prefix_refl _ - -theorem suffix_rfl : l <:+ l := - suffix_refl _ - -theorem infix_rfl : l <:+: l := - infix_refl _ - -theorem prefix_concat (a : α) (l) : l <+: concat l a := by simp - -theorem prefix_concat_iff {l₁ l₂ : List α} {a : α} : - l₁ <+: l₂ ++ [a] ↔ l₁ = l₂ ++ [a] ∨ l₁ <+: l₂ := by - simpa only [← reverse_concat', reverse_inj, reverse_suffix] using - suffix_cons_iff (l₁ := l₁.reverse) (l₂ := l₂.reverse) - -protected alias ⟨_, isSuffix.reverse⟩ := reverse_prefix - -protected alias ⟨_, isPrefix.reverse⟩ := reverse_suffix - -protected alias ⟨_, isInfix.reverse⟩ := reverse_infix - -alias ⟨eq_nil_of_infix_nil, _⟩ := infix_nil - -alias ⟨eq_nil_of_prefix_nil, _⟩ := prefix_nil - -alias ⟨eq_nil_of_suffix_nil, _⟩ := suffix_nil +@[deprecated IsSuffix.reverse (since := "2024-08-12")] alias isSuffix.reverse := IsSuffix.reverse +@[deprecated IsPrefix.reverse (since := "2024-08-12")] alias isPrefix.reverse := IsPrefix.reverse +@[deprecated IsInfix.reverse (since := "2024-08-12")] alias isInfix.reverse := IsInfix.reverse +@[deprecated IsInfix.eq_of_length (since := "2024-08-12")] theorem eq_of_infix_of_length_eq (h : l₁ <:+: l₂) : l₁.length = l₂.length → l₁ = l₂ := - h.sublist.eq_of_length + h.eq_of_length +@[deprecated IsPrefix.eq_of_length (since := "2024-08-12")] theorem eq_of_prefix_of_length_eq (h : l₁ <+: l₂) : l₁.length = l₂.length → l₁ = l₂ := - h.sublist.eq_of_length + h.eq_of_length +@[deprecated IsSuffix.eq_of_length (since := "2024-08-12")] theorem eq_of_suffix_of_length_eq (h : l₁ <:+ l₂) : l₁.length = l₂.length → l₁ = l₂ := - h.sublist.eq_of_length + h.eq_of_length lemma dropSlice_sublist (n m : ℕ) (l : List α) : l.dropSlice n m <+ l := calc @@ -87,28 +63,7 @@ lemma dropSlice_subset (n m : ℕ) (l : List α) : l.dropSlice n m ⊆ l := lemma mem_of_mem_dropSlice {n m : ℕ} {l : List α} {a : α} (h : a ∈ l.dropSlice n m) : a ∈ l := dropSlice_subset n m l h -theorem takeWhile_prefix (p : α → Bool) : l.takeWhile p <+: l := - ⟨l.dropWhile p, takeWhile_append_dropWhile p l⟩ - -theorem dropWhile_suffix (p : α → Bool) : l.dropWhile p <:+ l := - ⟨l.takeWhile p, takeWhile_append_dropWhile p l⟩ - -theorem dropLast_prefix : ∀ l : List α, l.dropLast <+: l - | [] => ⟨nil, by rw [dropLast, List.append_nil]⟩ - | a :: l => ⟨_, dropLast_append_getLast (cons_ne_nil a l)⟩ - -theorem tail_suffix (l : List α) : tail l <:+ l := by rw [← drop_one]; apply drop_suffix - -theorem dropLast_sublist (l : List α) : l.dropLast <+ l := - (dropLast_prefix l).sublist - -@[gcongr] -theorem drop_sublist_drop_left (l : List α) {m n : ℕ} (h : m ≤ n) : drop n l <+ drop m l := by - rw [← Nat.sub_add_cancel h, ← drop_drop] - apply drop_sublist - -theorem dropLast_subset (l : List α) : l.dropLast ⊆ l := - (dropLast_sublist l).subset +attribute [gcongr] drop_sublist_drop_left theorem tail_subset (l : List α) : tail l ⊆ l := (tail_sublist l).subset @@ -119,35 +74,7 @@ theorem mem_of_mem_dropLast (h : a ∈ l.dropLast) : a ∈ l := theorem mem_of_mem_tail (h : a ∈ l.tail) : a ∈ l := tail_subset l h -@[gcongr] -protected theorem Sublist.drop : ∀ {l₁ l₂ : List α}, l₁ <+ l₂ → ∀ n, l₁.drop n <+ l₂.drop n - | _, _, h, 0 => h - | _, _, h, n + 1 => by rw [← drop_tail, ← drop_tail]; exact h.tail.drop n - -theorem prefix_iff_eq_append : l₁ <+: l₂ ↔ l₁ ++ drop (length l₁) l₂ = l₂ := - ⟨by rintro ⟨r, rfl⟩; rw [drop_left], fun e => ⟨_, e⟩⟩ - -theorem suffix_iff_eq_append : l₁ <:+ l₂ ↔ take (length l₂ - length l₁) l₂ ++ l₁ = l₂ := - ⟨by rintro ⟨r, rfl⟩; simp only [length_append, Nat.add_sub_cancel_right, take_left], fun e => - ⟨_, e⟩⟩ - -theorem prefix_iff_eq_take : l₁ <+: l₂ ↔ l₁ = take (length l₁) l₂ := - ⟨fun h => append_cancel_right <| (prefix_iff_eq_append.1 h).trans (take_append_drop _ _).symm, - fun e => e.symm ▸ take_prefix _ _⟩ - -theorem prefix_take_iff {x y : List α} {n : ℕ} : x <+: y.take n ↔ x <+: y ∧ x.length ≤ n := by - constructor - · intro h - constructor - · exact List.IsPrefix.trans h <| List.take_prefix n y - · replace h := h.length_le - rw [length_take, Nat.le_min] at h - exact h.left - · intro ⟨hp, hl⟩ - have hl' := hp.length_le - rw [List.prefix_iff_eq_take] at * - rw [hp, List.take_take] - simp [min_eq_left, hl, hl'] +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 @@ -156,75 +83,10 @@ 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 -theorem suffix_iff_eq_drop : l₁ <:+ l₂ ↔ l₁ = drop (length l₂ - length l₁) l₂ := - ⟨fun h => append_cancel_left <| (suffix_iff_eq_append.1 h).trans (take_append_drop _ _).symm, - fun e => e.symm ▸ drop_suffix _ _⟩ - -instance decidablePrefix [DecidableEq α] : ∀ l₁ l₂ : List α, Decidable (l₁ <+: l₂) - | [], l₂ => isTrue ⟨l₂, rfl⟩ - | a :: l₁, [] => isFalse fun ⟨t, te⟩ => List.noConfusion te - | a :: l₁, b :: l₂ => - if h : a = b then - @decidable_of_decidable_of_iff _ _ (decidablePrefix l₁ l₂) (by rw [← h, prefix_cons_inj]) - else - isFalse fun ⟨t, te⟩ => h <| by injection te - --- Alternatively, use mem_tails -instance decidableSuffix [DecidableEq α] : ∀ l₁ l₂ : List α, Decidable (l₁ <:+ l₂) - | [], l₂ => isTrue ⟨l₂, append_nil _⟩ - | a :: l₁, [] => isFalse <| mt (Sublist.length_le ∘ IsSuffix.sublist) (by simp) - | l₁, b :: l₂ => - @decidable_of_decidable_of_iff _ _ - (@instDecidableOr _ _ _ (l₁.decidableSuffix l₂)) - suffix_cons_iff.symm - -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₂ => - @decidable_of_decidable_of_iff _ _ - (@instDecidableOr _ _ (l₁.decidablePrefix (b :: l₂)) (l₁.decidableInfix l₂)) - infix_cons_iff.symm - -theorem prefix_take_le_iff {L : List α} (hm : m < L.length) : - L.take m <+: L.take n ↔ m ≤ n := by - simp only [prefix_iff_eq_take, length_take] - induction m generalizing L n with - | zero => simp [min_eq_left, eq_self_iff_true, Nat.zero_le, take] - | succ m IH => - cases L with - | nil => simp_all - | cons l ls => - cases n with - | zero => - simp - | succ n => - simp only [length_cons, succ_eq_add_one, Nat.add_lt_add_iff_right] at hm - simp [← @IH n ls hm, Nat.min_eq_left, Nat.le_of_lt hm] - @[deprecated cons_prefix_cons (since := "2024-08-14")] theorem cons_prefix_iff : a :: l₁ <+: b :: l₂ ↔ a = b ∧ l₁ <+: l₂ := by simp -protected theorem IsPrefix.map (h : l₁ <+: l₂) (f : α → β) : l₁.map f <+: l₂.map f := by - induction' l₁ with hd tl hl generalizing l₂ - · simp only [nil_prefix, map_nil] - · cases' l₂ with hd₂ tl₂ - · simpa only using eq_nil_of_prefix_nil h - · rw [cons_prefix_cons] at h - simp only [List.map_cons, h, prefix_cons_inj, hl, map] - -protected theorem IsPrefix.filterMap (h : l₁ <+: l₂) (f : α → Option β) : - l₁.filterMap f <+: l₂.filterMap f := by - induction' l₁ with hd₁ tl₁ hl generalizing l₂ - · simp only [nil_prefix, filterMap_nil] - · cases' l₂ with hd₂ tl₂ - · simpa only using eq_nil_of_prefix_nil h - · rw [cons_prefix_cons] at h - rw [← @singleton_append _ hd₁ _, ← @singleton_append _ hd₂ _, filterMap_append, - filterMap_append, h.left, prefix_append_right_inj] - exact hl h.right - @[deprecated (since := "2024-03-26")] alias IsPrefix.filter_map := IsPrefix.filterMap protected theorem IsPrefix.reduceOption {l₁ l₂ : List (Option α)} (h : l₁ <+: l₂) : @@ -232,19 +94,19 @@ protected theorem IsPrefix.reduceOption {l₁ l₂ : List (Option α)} (h : l₁ h.filterMap id instance : IsPartialOrder (List α) (· <+: ·) where - refl := prefix_refl + refl _ := prefix_rfl trans _ _ _ := IsPrefix.trans - antisymm _ _ h₁ h₂ := eq_of_prefix_of_length_eq h₁ <| h₁.length_le.antisymm h₂.length_le + antisymm _ _ h₁ h₂ := h₁.eq_of_length <| h₁.length_le.antisymm h₂.length_le instance : IsPartialOrder (List α) (· <:+ ·) where - refl := suffix_refl + refl _ := suffix_rfl trans _ _ _ := IsSuffix.trans - antisymm _ _ h₁ h₂ := eq_of_suffix_of_length_eq h₁ <| h₁.length_le.antisymm h₂.length_le + antisymm _ _ h₁ h₂ := h₁.eq_of_length <| h₁.length_le.antisymm h₂.length_le instance : IsPartialOrder (List α) (· <:+: ·) where - refl := infix_refl + refl _ := infix_rfl trans _ _ _ := IsInfix.trans - antisymm _ _ h₁ h₂ := eq_of_infix_of_length_eq h₁ <| h₁.length_le.antisymm h₂.length_le + antisymm _ _ h₁ h₂ := h₁.eq_of_length <| h₁.length_le.antisymm h₂.length_le end Fix @@ -254,7 +116,7 @@ section InitsTails theorem mem_inits : ∀ s t : List α, s ∈ inits t ↔ s <+: t | s, [] => suffices s = nil ↔ s <+: nil by simpa only [inits, mem_singleton] - ⟨fun h => h.symm ▸ prefix_refl [], eq_nil_of_prefix_nil⟩ + ⟨fun h => h.symm ▸ prefix_rfl, eq_nil_of_prefix_nil⟩ | s, a :: t => suffices (s = nil ∨ ∃ l ∈ inits t, a :: l = s) ↔ s <+: a :: t by simpa ⟨fun o => @@ -295,8 +157,8 @@ theorem tails_cons (a : α) (l : List α) : tails (a :: l) = (a :: l) :: l.tails @[simp] 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 [· ∘ ·] - | a :: s, t => by simp [inits_append s t, · ∘ ·] + | [], a :: t => by simp + | a :: s, t => by simp [inits_append s t, Function.comp_def] @[simp] theorem tails_append : @@ -365,20 +227,6 @@ theorem getElem_inits (l : List α) (n : Nat) (h : n < length (inits l)) : theorem get_inits (l : List α) (n : Fin (length (inits l))) : (inits l).get n = l.take n := by simp -section deprecated -set_option linter.deprecated false - -@[simp, deprecated get_tails (since := "2024-04-16")] -theorem nth_le_tails (l : List α) (n : ℕ) (hn : n < length (tails l)) : - nthLe (tails l) n hn = l.drop n := - get_tails l _ - -@[simp, deprecated get_inits (since := "2024-04-16")] -theorem nth_le_inits (l : List α) (n : ℕ) (hn : n < length (inits l)) : - nthLe (inits l) n hn = l.take n := - get_inits l _ -end deprecated - end InitsTails /-! ### insert -/ @@ -409,24 +257,13 @@ theorem subset_insert (a : α) (l : List α) : l ⊆ l.insert a := end Insert -theorem mem_of_mem_suffix (hx : a ∈ l₁) (hl : l₁ <:+ l₂) : a ∈ l₂ := - hl.subset hx - -theorem IsPrefix.ne_nil {x y : List α} (h : x <+: y) (hx : x ≠ []) : y ≠ [] := by - rintro rfl; exact hx <| List.prefix_nil.mp h - -theorem IsPrefix.getElem {x y : List α} (h : x <+: y) {n} (hn : n < x.length) : - x[n] = y[n]'(hn.trans_le h.length_le) := by - obtain ⟨_, rfl⟩ := h - exact (List.getElem_append n hn).symm +@[deprecated (since := "2024-08-15")] alias mem_of_mem_suffix := IsSuffix.mem +@[deprecated IsPrefix.getElem (since := "2024-08-15")] theorem IsPrefix.get_eq {x y : List α} (h : x <+: y) {n} (hn : n < x.length) : x.get ⟨n, hn⟩ = y.get ⟨n, hn.trans_le h.length_le⟩ := by simp only [get_eq_getElem, IsPrefix.getElem h hn] -theorem IsPrefix.head_eq {x y : List α} (h : x <+: y) (hx : x ≠ []) : - x.head hx = y.head (h.ne_nil hx) := by - cases x <;> cases y <;> simp only [head_cons, ne_eq, not_true_eq_false] at hx ⊢ - all_goals (obtain ⟨_, h⟩ := h; injection h) +@[deprecated (since := "2024-08-15")] alias IsPrefix.head_eq := IsPrefix.head end List diff --git a/Mathlib/Data/List/InsertNth.lean b/Mathlib/Data/List/InsertNth.lean index 33044a0a6908c..99646ea33a4c5 100644 --- a/Mathlib/Data/List/InsertNth.lean +++ b/Mathlib/Data/List/InsertNth.lean @@ -139,12 +139,6 @@ theorem get_insertNth_of_lt (l : List α) (x : α) (n k : ℕ) (hn : k < n) (hk (insertNth n x l).get ⟨k, hk'⟩ = l.get ⟨k, hk⟩ := by simp_all [getElem_insertNth_of_lt] -set_option linter.deprecated false in -@[deprecated get_insertNth_of_lt (since := "2023-01-05")] -theorem nthLe_insertNth_of_lt : ∀ (l : List α) (x : α) (n k : ℕ), k < n → ∀ (hk : k < l.length) - (hk' : k < (insertNth n x l).length := hk.trans_le (length_le_length_insertNth _ _ _)), - (insertNth n x l).nthLe k hk' = l.nthLe k hk := @get_insertNth_of_lt _ - @[simp] theorem getElem_insertNth_self (l : List α) (x : α) (n : ℕ) (hn : n ≤ l.length) (hn' : n < (insertNth n x l).length := (by rwa [length_insertNth _ _ hn, Nat.lt_succ_iff])) : @@ -163,12 +157,6 @@ theorem get_insertNth_self (l : List α) (x : α) (n : ℕ) (hn : n ≤ l.length (insertNth n x l).get ⟨n, hn'⟩ = x := by simp [hn, hn'] -set_option linter.deprecated false in -@[simp, deprecated get_insertNth_self (since := "2023-01-05")] -theorem nthLe_insertNth_self (l : List α) (x : α) (n : ℕ) (hn : n ≤ l.length) - (hn' : n < (insertNth n x l).length := (by rwa [length_insertNth _ _ hn, Nat.lt_succ_iff])) : - (insertNth n x l).nthLe n hn' = x := get_insertNth_self _ _ _ hn - theorem getElem_insertNth_add_succ (l : List α) (x : α) (n k : ℕ) (hk' : n + k < l.length) (hk : n + k + 1 < (insertNth n x l).length := (by rwa [length_insertNth _ _ (by omega), Nat.succ_lt_succ_iff])) : @@ -185,14 +173,6 @@ theorem get_insertNth_add_succ (l : List α) (x : α) (n k : ℕ) (hk' : n + k < (insertNth n x l).get ⟨n + k + 1, hk⟩ = get l ⟨n + k, hk'⟩ := by simp [getElem_insertNth_add_succ, hk, hk'] -set_option linter.deprecated false in -@[deprecated get_insertNth_add_succ (since := "2023-01-05")] -theorem nthLe_insertNth_add_succ : ∀ (l : List α) (x : α) (n k : ℕ) (hk' : n + k < l.length) - (hk : n + k + 1 < (insertNth n x l).length := (by - rwa [length_insertNth _ _ (by omega), Nat.succ_lt_succ_iff])), - (insertNth n x l).nthLe (n + k + 1) hk = nthLe l (n + k) hk' := - @get_insertNth_add_succ _ - set_option linter.unnecessarySimpa false in theorem insertNth_injective (n : ℕ) (x : α) : Function.Injective (insertNth n x) := by induction' n with n IH diff --git a/Mathlib/Data/List/Intervals.lean b/Mathlib/Data/List/Intervals.lean index 39e9340abd44f..fdfa018a9e884 100644 --- a/Mathlib/Data/List/Intervals.lean +++ b/Mathlib/Data/List/Intervals.lean @@ -42,15 +42,15 @@ theorem zero_bot (n : ℕ) : Ico 0 n = range n := by rw [Ico, Nat.sub_zero, rang @[simp] theorem length (n m : ℕ) : length (Ico n m) = m - n := by dsimp [Ico] - simp [length_range', autoParam] + simp [length_range'] theorem pairwise_lt (n m : ℕ) : Pairwise (· < ·) (Ico n m) := by dsimp [Ico] - simp [pairwise_lt_range', autoParam] + simp [pairwise_lt_range'] theorem nodup (n m : ℕ) : Nodup (Ico n m) := by dsimp [Ico] - simp [nodup_range', autoParam] + simp [nodup_range'] @[simp] theorem mem {n m l : ℕ} : l ∈ Ico n m ↔ n ≤ l ∧ l < m := by diff --git a/Mathlib/Data/List/Iterate.lean b/Mathlib/Data/List/Iterate.lean index dc981a78f8e38..5fe809d67beed 100644 --- a/Mathlib/Data/List/Iterate.lean +++ b/Mathlib/Data/List/Iterate.lean @@ -31,15 +31,17 @@ theorem getElem?_iterate (f : α → α) (a : α) : | n + 1, 0 , _ => by simp | n + 1, i + 1, h => by simp [getElem?_iterate f (f a) n i (by simpa using h)] +@[deprecated getElem?_iterate (since := "2024-08-23")] theorem get?_iterate (f : α → α) (a : α) (n i : ℕ) (h : i < n) : get? (iterate f a n) i = f^[i] a := by - simp only [get?_eq_getElem?, length_iterate, h, Option.some.injEq, getElem?_iterate] + simp only [get?_eq_getElem?, getElem?_iterate, h] @[simp] theorem getElem_iterate (f : α → α) (a : α) (n : ℕ) (i : Nat) (h : i < (iterate f a n).length) : - (iterate f a n)[i] = f^[↑i] a := - (get?_eq_some.1 <| get?_iterate f a n i (by simpa using h)).2 + (iterate f a n)[i] = f^[i] a := + getElem_eq_iff.2 <| getElem?_iterate _ _ _ _ <| by rwa [length_iterate] at h +@[deprecated getElem_iterate (since := "2024-08-23")] theorem get_iterate (f : α → α) (a : α) (n : ℕ) (i : Fin (iterate f a n).length) : get (iterate f a n) i = f^[↑i] a := by simp @@ -52,7 +54,7 @@ theorem mem_iterate {f : α → α} {a : α} {n : ℕ} {b : α} : @[simp] theorem range_map_iterate (n : ℕ) (f : α → α) (a : α) : (List.range n).map (f^[·] a) = List.iterate f a n := by - apply List.ext_get <;> simp + apply List.ext_getElem <;> simp theorem iterate_add (f : α → α) (a : α) (m n : ℕ) : iterate f a (m + n) = iterate f a m ++ iterate f (f^[m] a) n := by diff --git a/Mathlib/Data/List/Join.lean b/Mathlib/Data/List/Join.lean index c8ecd55aad8c5..69f2b6f90ab34 100644 --- a/Mathlib/Data/List/Join.lean +++ b/Mathlib/Data/List/Join.lean @@ -19,31 +19,8 @@ variable {α β : Type*} namespace List --- Porting note (#10618): simp can prove this --- @[simp] -theorem join_singleton (l : List α) : [l].join = l := by rw [join, join, append_nil] - -@[deprecated join_eq_nil_iff (since := "2024-07-10")] -theorem join_eq_nil : ∀ {L : List (List α)}, join L = [] ↔ ∀ l ∈ L, l = [] := join_eq_nil_iff - - -@[simp] -theorem join_filter_not_isEmpty : - ∀ {L : List (List α)}, join (L.filter fun l => !l.isEmpty) = L.join - | [] => rfl - | [] :: L => by - simp [join_filter_not_isEmpty (L := L), isEmpty_iff_eq_nil] - | (a :: l) :: L => by - simp [join_filter_not_isEmpty (L := L)] - @[deprecated (since := "2024-02-25")] alias join_filter_isEmpty_eq_false := join_filter_not_isEmpty -@[simp] -theorem join_filter_ne_nil [DecidablePred fun l : List α => l ≠ []] {L : List (List α)} : - join (L.filter fun l => l ≠ []) = L.join := by - simp only [ne_eq, ← isEmpty_iff_eq_nil, Bool.not_eq_true, Bool.decide_eq_false, - join_filter_not_isEmpty] - /-- See `List.length_join` for the corresponding statement using `List.sum`. -/ lemma length_join' (L : List (List α)) : length (join L) = Nat.sum (map length L) := by induction L <;> [rfl; simp only [*, join, map, Nat.sum_cons, length_append]] @@ -70,11 +47,6 @@ lemma countP_bind' (p : β → Bool) (l : List α) (f : α → List β) : lemma count_bind' [BEq β] (l : List α) (f : α → List β) (x : β) : count x (l.bind f) = Nat.sum (map (count x ∘ f) l) := countP_bind' _ _ _ -@[simp] -theorem bind_eq_nil {l : List α} {f : α → List β} : List.bind l f = [] ↔ ∀ x ∈ l, f x = [] := - join_eq_nil_iff.trans <| by - simp only [mem_map, forall_exists_index, and_imp, forall_apply_eq_imp_iff₂] - /-- In a join, taking the first elements up to an index which is the sum of the lengths of the first `i` sublists, is the same as taking the join of the first `i` sublists. @@ -110,22 +82,6 @@ theorem drop_take_succ_eq_cons_get (L : List α) (i : Fin L.length) : (L.take (i + 1)).drop i = [get L i] := by simp [drop_take_succ_eq_cons_getElem] -set_option linter.deprecated false in -/-- Taking only the first `i+1` elements in a list, and then dropping the first `i` ones, one is -left with a list of length `1` made of the `i`-th element of the original list. -/ -@[deprecated drop_take_succ_eq_cons_get (since := "2023-01-10")] -theorem drop_take_succ_eq_cons_nthLe (L : List α) {i : ℕ} (hi : i < L.length) : - (L.take (i + 1)).drop i = [nthLe L i hi] := by - induction' L with head tail generalizing i - · simp only [length] at hi - exact (Nat.not_succ_le_zero i hi).elim - cases' i with i hi - · simp - rfl - have : i < tail.length := by simpa using hi - simp [*] - rfl - /-- In a join of sublists, taking the slice between the indices `A` and `B - 1` gives back the original sublist of index `i` if `A` is the sum of the lengths of sublists of index `< i`, and `B` is the sum of the lengths of sublists of index `≤ i`. @@ -145,18 +101,6 @@ theorem drop_take_succ_join_eq_get' (L : List (List α)) (i : Fin L.length) : get L i := by simp [drop_take_succ_join_eq_getElem'] -/-- Two lists of sublists are equal iff their joins coincide, as well as the lengths of the -sublists. -/ -theorem eq_iff_join_eq (L L' : List (List α)) : - L = L' ↔ L.join = L'.join ∧ map length L = map length L' := by - refine ⟨fun H => by simp [H], ?_⟩ - rintro ⟨join_eq, length_eq⟩ - apply ext_getElem - · have : length (map length L) = length (map length L') := by rw [length_eq] - simpa using this - · intro n h₁ h₂ - rw [← drop_take_succ_join_eq_getElem', ← drop_take_succ_join_eq_getElem', join_eq, length_eq] - theorem join_drop_length_sub_one {L : List (List α)} (h : L ≠ []) : (L.drop (L.length - 1)).join = L.getLast h := by induction L using List.reverseRecOn @@ -167,25 +111,10 @@ theorem join_drop_length_sub_one {L : List (List α)} (h : L ≠ []) : `(x ++ l₁) ++ (x ++ l₂) ++ ... ++ (x ++ lₙ) ++ x` where `L = [l₁, l₂, ..., lₙ]`. -/ theorem append_join_map_append (L : List (List α)) (x : List α) : x ++ (L.map (· ++ x)).join = (L.map (x ++ ·)).join ++ x := by - induction' L with _ _ ih - · rw [map_nil, join, append_nil, map_nil, join, nil_append] - · rw [map_cons, join, map_cons, join, append_assoc, ih, append_assoc, append_assoc] - - -/-- Any member of `L : List (List α))` is a sublist of `L.join` -/ -lemma sublist_join (L : List (List α)) {s : List α} (hs : s ∈ L) : - s.Sublist L.join := by induction L with - | nil => - exfalso - exact not_mem_nil s hs - | cons t m ht => - cases mem_cons.mp hs with - | inl h => - rw [h] - simp only [join_cons, sublist_append_left] - | inr h => - simp only [join_cons] - exact sublist_append_of_sublist_right (ht h) + | nil => rw [map_nil, join, append_nil, map_nil, join, nil_append] + | cons _ _ ih => rw [map_cons, join, map_cons, join, append_assoc, ih, append_assoc, append_assoc] + +@[deprecated (since := "2024-08-15")] alias sublist_join := sublist_join_of_mem end List diff --git a/Mathlib/Data/List/Lemmas.lean b/Mathlib/Data/List/Lemmas.lean index d01b10c18df2b..919bfb342a5c6 100644 --- a/Mathlib/Data/List/Lemmas.lean +++ b/Mathlib/Data/List/Lemmas.lean @@ -5,7 +5,6 @@ Authors: Yakov Pechersky, Yury Kudryashov -/ import Mathlib.Data.Set.Image import Mathlib.Data.List.InsertNth -import Mathlib.Init.Data.List.Lemmas /-! # Some lemmas about lists involving sets @@ -18,13 +17,36 @@ variable {α β γ : Type*} namespace List +@[deprecated (since := "2024-08-20")] alias getElem_reverse' := getElem_reverse + +theorem tail_reverse_eq_reverse_dropLast (l : List α) : + l.reverse.tail = l.dropLast.reverse := by + ext i v; by_cases hi : i < l.length - 1 + · simp only [← drop_one] + rw [getElem?_eq_getElem (by simpa), getElem?_eq_getElem (by simpa), + ← getElem_drop' _, getElem_reverse, getElem_reverse, getElem_dropLast] + simp [show l.length - 1 - (1 + i) = l.length - 1 - 1 - i by omega] + all_goals ((try simp); omega) + · 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 |- + theorem injOn_insertNth_index_of_not_mem (l : List α) (x : α) (hx : x ∉ l) : Set.InjOn (fun k => insertNth k x l) { n | n ≤ l.length } := by induction' l with hd tl IH · intro n hn m hm _ - simp only [Set.mem_singleton_iff, Set.setOf_eq_eq_singleton, - length] at hn hm - simp_all [hn, hm] + simp_all [Set.mem_singleton_iff, Set.setOf_eq_eq_singleton, length] · intro n hn m hm h simp only [length, Set.mem_setOf_eq] at hn hm simp only [mem_cons, not_or] at hx diff --git a/Mathlib/Data/List/Lex.lean b/Mathlib/Data/List/Lex.lean index fad422e7a7b85..9431966564a45 100644 --- a/Mathlib/Data/List/Lex.lean +++ b/Mathlib/Data/List/Lex.lean @@ -99,6 +99,7 @@ instance isAsymm (r : α → α → Prop) [IsAsymm α r] : IsAsymm (List α) (Le | _, _, Lex.cons _, Lex.rel h₂ => asymm h₂ h₂ | _, _, Lex.cons h₁, Lex.cons h₂ => aux _ _ h₁ h₂ +@[deprecated (since := "2024-07-30")] instance isStrictTotalOrder (r : α → α → Prop) [IsStrictTotalOrder α r] : IsStrictTotalOrder (List α) (Lex r) := { isStrictWeakOrder_of_isOrderConnected with } diff --git a/Mathlib/Data/List/Nodup.lean b/Mathlib/Data/List/Nodup.lean index f5d371b85b7ad..c4ede7b589049 100644 --- a/Mathlib/Data/List/Nodup.lean +++ b/Mathlib/Data/List/Nodup.lean @@ -77,14 +77,6 @@ theorem nodup_iff_injective_get {l : List α} : change _ ↔ Injective (fun i => l.get i) simp -set_option linter.deprecated false in -@[deprecated nodup_iff_injective_get (since := "2023-01-10")] -theorem nodup_iff_nthLe_inj {l : List α} : - Nodup l ↔ ∀ i j h₁ h₂, nthLe l i h₁ = nthLe l j h₂ → i = j := - nodup_iff_injective_get.trans - ⟨fun hinj _ _ _ _ h => congr_arg Fin.val (hinj h), - fun hinj i j h => Fin.eq_of_val_eq (hinj i j i.2 j.2 h)⟩ - theorem Nodup.get_inj_iff {l : List α} (h : Nodup l) {i j : Fin l.length} : l.get i = l.get j ↔ i = j := (nodup_iff_injective_get.1 h).eq_iff @@ -95,19 +87,13 @@ theorem Nodup.getElem_inj_iff {l : List α} (h : Nodup l) have := @Nodup.get_inj_iff _ _ h ⟨i, hi⟩ ⟨j, hj⟩ simpa -set_option linter.deprecated false in -@[deprecated Nodup.get_inj_iff (since := "2023-01-10")] -theorem Nodup.nthLe_inj_iff {l : List α} (h : Nodup l) {i j : ℕ} (hi : i < l.length) - (hj : j < l.length) : l.nthLe i hi = l.nthLe j hj ↔ i = j := - ⟨nodup_iff_nthLe_inj.mp h _ _ _ _, by simp (config := { contextual := true })⟩ - theorem nodup_iff_getElem?_ne_getElem? {l : List α} : l.Nodup ↔ ∀ i j : ℕ, i < j → j < l.length → l[i]? ≠ l[j]? := by rw [Nodup, pairwise_iff_getElem] constructor · intro h i j hij hj rw [getElem?_eq_getElem (lt_trans hij hj), getElem?_eq_getElem hj, Ne, Option.some_inj] - exact h _ _ _ _ hij + exact h _ _ (by omega) hj hij · intro h i j hi hj hij rw [Ne, ← Option.some_inj, ← getElem?_eq_getElem, ← getElem?_eq_getElem] exact h i j hij hj @@ -372,7 +358,7 @@ theorem Nodup.pairwise_coe [IsSymm α r] (hl : l.Nodup) : rw [List.nodup_cons] at hl have : ∀ b ∈ l, ¬a = b → r a b ↔ r a b := fun b hb => imp_iff_right (ne_of_mem_of_not_mem hb hl.1).symm - simp [Set.setOf_or, Set.pairwise_insert_of_symmetric (@symm_of _ r _), ih hl.2, and_comm, + simp [Set.setOf_or, Set.pairwise_insert_of_symmetric fun _ _ ↦ symm_of r, ih hl.2, and_comm, forall₂_congr this] theorem Nodup.take_eq_filter_mem [DecidableEq α] : @@ -380,7 +366,7 @@ theorem Nodup.take_eq_filter_mem [DecidableEq α] : | [], n, _ => by simp | b::l, 0, _ => by simp | b::l, n+1, hl => by - rw [take_cons, Nodup.take_eq_filter_mem (Nodup.of_cons hl), List.filter_cons_of_pos (by simp)] + rw [take_succ_cons, Nodup.take_eq_filter_mem (Nodup.of_cons hl), filter_cons_of_pos (by simp)] congr 1 refine List.filter_congr ?_ intro x hx diff --git a/Mathlib/Data/List/NodupEquivFin.lean b/Mathlib/Data/List/NodupEquivFin.lean index 36b450b8c49a8..5266ae7b60164 100644 --- a/Mathlib/Data/List/NodupEquivFin.lean +++ b/Mathlib/Data/List/NodupEquivFin.lean @@ -137,12 +137,14 @@ theorem sublist_iff_exists_orderEmbedding_get?_eq {l l' : List α} : l <+ l' ↔ ∃ f : ℕ ↪o ℕ, ∀ ix : ℕ, l.get? ix = l'.get? (f ix) := by constructor · intro H - induction' H with xs ys y _H IH xs ys x _H IH - · simp - · obtain ⟨f, hf⟩ := IH + induction H with + | slnil => simp + | cons _ _ IH => + obtain ⟨f, hf⟩ := IH refine ⟨f.trans (OrderEmbedding.ofStrictMono (· + 1) fun _ => by simp), ?_⟩ simpa using hf - · obtain ⟨f, hf⟩ := IH + | cons₂ _ _ IH => + obtain ⟨f, hf⟩ := IH refine ⟨OrderEmbedding.ofMapLEIff (fun ix : ℕ => if ix = 0 then 0 else (f ix.pred).succ) ?_, ?_⟩ · rintro ⟨_ | a⟩ ⟨_ | b⟩ <;> simp [Nat.succ_le_succ_iff] @@ -221,19 +223,6 @@ theorem duplicate_iff_exists_distinct_get {l : List α} {x : α} : · simpa using h · simpa using h' -set_option linter.deprecated false in -/-- An element `x : α` of `l : List α` is a duplicate iff it can be found -at two distinct indices `n m : ℕ` inside the list `l`. --/ -@[deprecated duplicate_iff_exists_distinct_get (since := "2023-01-19")] -theorem duplicate_iff_exists_distinct_nthLe {l : List α} {x : α} : - l.Duplicate x ↔ - ∃ (n : ℕ) (hn : n < l.length) (m : ℕ) (hm : m < l.length) (_ : n < m), - x = l.nthLe n hn ∧ x = l.nthLe m hm := - duplicate_iff_exists_distinct_get.trans - ⟨fun ⟨n, m, h⟩ => ⟨n.1, n.2, m.1, m.2, h⟩, - fun ⟨n, hn, m, hm, h⟩ => ⟨⟨n, hn⟩, ⟨m, hm⟩, h⟩⟩ - end Sublist end List diff --git a/Mathlib/Data/List/OfFn.lean b/Mathlib/Data/List/OfFn.lean index 99f86c4e1dc1c..cdfcb9554f599 100644 --- a/Mathlib/Data/List/OfFn.lean +++ b/Mathlib/Data/List/OfFn.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 -/ +import Batteries.Data.List.Pairwise import Mathlib.Data.Fin.Tuple.Basic -import Mathlib.Data.List.Basic /-! # Lists from functions @@ -74,18 +74,6 @@ theorem getElem?_ofFn {n} (f : Fin n → α) (i) : (ofFn f)[i]? = ofFnNthVal f i theorem get?_ofFn {n} (f : Fin n → α) (i) : get? (ofFn f) i = ofFnNthVal f i := by simp -set_option linter.deprecated false in -@[deprecated get_ofFn (since := "2023-01-17")] -theorem nthLe_ofFn {n} (f : Fin n → α) (i : Fin n) : - nthLe (ofFn f) i ((length_ofFn f).symm ▸ i.2) = f i := by - simp [nthLe] - -set_option linter.deprecated false in -@[simp, deprecated get_ofFn (since := "2023-01-17")] -theorem nthLe_ofFn' {n} (f : Fin n → α) {i : ℕ} (h : i < (ofFn f).length) : - nthLe (ofFn f) i h = f ⟨i, length_ofFn f ▸ h⟩ := - nthLe_ofFn f ⟨i, length_ofFn f ▸ h⟩ - @[simp] theorem map_ofFn {β : Type*} {n : ℕ} (f : Fin n → α) (g : α → β) : map g (ofFn f) = ofFn (g ∘ f) := @@ -129,7 +117,7 @@ theorem ofFn_succ' {n} (f : Fin (succ n) → α) : @[simp] theorem ofFn_eq_nil_iff {n : ℕ} {f : Fin n → α} : ofFn f = [] ↔ n = 0 := by - cases n <;> simp only [ofFn_zero, ofFn_succ, eq_self_iff_true, Nat.succ_ne_zero] + cases n <;> simp only [ofFn_zero, ofFn_succ, eq_self_iff_true, Nat.succ_ne_zero, reduceCtorEq] theorem last_ofFn {n : ℕ} (f : Fin n → α) (h : ofFn f ≠ []) (hn : n - 1 < n := Nat.pred_lt <| ofFn_eq_nil_iff.not.mp h) : @@ -201,11 +189,6 @@ theorem ofFn_getElem_eq_map {β : Type*} (l : List α) (f : α → β) : theorem ofFn_get_eq_map {β : Type*} (l : List α) (f : α → β) : ofFn (f <| l.get ·) = l.map f := by simp -set_option linter.deprecated false in -@[deprecated ofFn_get (since := "2023-01-17")] -theorem ofFn_nthLe : ∀ l : List α, (ofFn fun i => nthLe l i i.2) = l := - ofFn_get - -- not registered as a simp lemma, as otherwise it fires before `forall_mem_ofFn_iff` which -- is much more useful theorem mem_ofFn {n} (f : Fin n → α) (a : α) : a ∈ ofFn f ↔ a ∈ Set.range f := by diff --git a/Mathlib/Data/List/Pairwise.lean b/Mathlib/Data/List/Pairwise.lean index 9f117438fd350..1a562e854c8c7 100644 --- a/Mathlib/Data/List/Pairwise.lean +++ b/Mathlib/Data/List/Pairwise.lean @@ -3,9 +3,9 @@ Copyright (c) 2018 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ +import Batteries.Data.List.Pairwise import Mathlib.Logic.Pairwise import Mathlib.Logic.Relation -import Mathlib.Data.List.Basic /-! # Pairwise relations on a list @@ -57,30 +57,6 @@ theorem Pairwise.set_pairwise (hl : Pairwise R l) (hr : Symmetric R) : { x | x simp only [map, pairwise_cons, mem_map, forall_exists_index, and_imp, forall_apply_eq_imp_iff₂, pairwise_map] -theorem pairwise_pmap {p : β → Prop} {f : ∀ b, p b → α} {l : List β} (h : ∀ x ∈ l, p x) : - Pairwise R (l.pmap f h) ↔ - Pairwise (fun b₁ b₂ => ∀ (h₁ : p b₁) (h₂ : p b₂), R (f b₁ h₁) (f b₂ h₂)) l := by - induction' l with a l ihl - · simp - obtain ⟨_, hl⟩ : p a ∧ ∀ b, b ∈ l → p b := by simpa using h - simp only [ihl hl, pairwise_cons, exists₂_imp, pmap, and_congr_left_iff, mem_pmap] - refine fun _ => ⟨fun H b hb _ hpb => H _ _ hb rfl, ?_⟩ - rintro H _ b hb rfl - exact H b hb _ _ - -theorem Pairwise.pmap {l : List α} (hl : Pairwise R l) {p : α → Prop} {f : ∀ a, p a → β} - (h : ∀ x ∈ l, p x) {S : β → β → Prop} - (hS : ∀ ⦃x⦄ (hx : p x) ⦃y⦄ (hy : p y), R x y → S (f x hx) (f y hy)) : - Pairwise S (l.pmap f h) := by - refine (pairwise_pmap h).2 (Pairwise.imp_of_mem ?_ hl) - intros; apply hS; assumption - -theorem pairwise_of_forall_mem_list {l : List α} {r : α → α → Prop} (h : ∀ a ∈ l, ∀ b ∈ l, r a b) : - l.Pairwise r := by - rw [pairwise_iff_forall_sublist] - intro a b hab - apply h <;> (apply hab.subset; simp) - theorem pairwise_of_reflexive_of_forall_ne {l : List α} {r : α → α → Prop} (hr : Reflexive r) (h : ∀ a ∈ l, ∀ b ∈ l, a ≠ b → r a b) : l.Pairwise r := by rw [pairwise_iff_forall_sublist] @@ -91,14 +67,6 @@ theorem pairwise_of_reflexive_of_forall_ne {l : List α} {r : α → α → Prop apply h <;> try (apply hab.subset; simp) exact heq -set_option linter.deprecated false in -@[deprecated pairwise_iff_get (since := "2023-01-10")] -theorem pairwise_iff_nthLe {R} {l : List α} : Pairwise R l ↔ - ∀ (i j) (h₁ : j < length l) (h₂ : i < j), R (nthLe l i (lt_trans h₂ h₁)) (nthLe l j h₁) := - pairwise_iff_get.trans - ⟨fun h i j _ h₂ => h ⟨i, _⟩ ⟨j, _⟩ h₂, - fun h i j hij => h i j _ hij⟩ - /-! ### Pairwise filtering -/ diff --git a/Mathlib/Data/List/Perm.lean b/Mathlib/Data/List/Perm.lean index 4aaffa789fd29..565fc6ade6048 100644 --- a/Mathlib/Data/List/Perm.lean +++ b/Mathlib/Data/List/Perm.lean @@ -10,6 +10,7 @@ import Mathlib.Data.List.InsertNth import Mathlib.Data.List.Lattice import Mathlib.Data.List.Permutation import Mathlib.Data.Nat.Factorial.Basic +import Batteries.Data.List.Perm /-! # List Permutations @@ -216,16 +217,18 @@ variable [DecidableEq α] theorem Perm.bagInter_right {l₁ l₂ : List α} (t : List α) (h : l₁ ~ l₂) : l₁.bagInter t ~ l₂.bagInter t := by - induction' h with x _ _ _ _ x y _ _ _ _ _ _ ih_1 ih_2 generalizing t; · simp - · by_cases x ∈ t <;> simp [*, Perm.cons] - · by_cases h : x = y + induction h generalizing t with + | nil => simp + | cons x => by_cases x ∈ t <;> simp [*, Perm.cons] + | swap x y => + by_cases h : x = y · simp [h] by_cases xt : x ∈ t <;> by_cases yt : y ∈ t · simp [xt, yt, mem_erase_of_ne h, mem_erase_of_ne (Ne.symm h), erase_comm, swap] · simp [xt, yt, mt mem_of_mem_erase, Perm.cons] · simp [xt, yt, mt mem_of_mem_erase, Perm.cons] · simp [xt, yt] - · exact (ih_1 _).trans (ih_2 _) + | trans _ _ ih_1 ih_2 => exact (ih_1 _).trans (ih_2 _) theorem Perm.bagInter_left (l : List α) {t₁ t₂ : List α} (p : t₁ ~ t₂) : l.bagInter t₁ = l.bagInter t₂ := by @@ -335,10 +338,9 @@ theorem Perm.drop_inter [DecidableEq α] {xs ys : List α} (n : ℕ) (h : xs ~ y by_cases h'' : n ≤ xs.length · let n' := xs.length - n have h₀ : n = xs.length - n' := by rwa [Nat.sub_sub_self] - have h₁ : n' ≤ xs.length := Nat.sub_le .. - have h₂ : xs.drop n = (xs.reverse.take n').reverse := by - rw [take_reverse h₁, h₀, reverse_reverse] - rw [h₂] + have h₁ : xs.drop n = (xs.reverse.take n').reverse := by + rw [take_reverse, h₀, reverse_reverse] + rw [h₁] apply (reverse_perm _).trans rw [inter_reverse] apply Perm.take_inter _ _ h' @@ -453,14 +455,16 @@ theorem perm_permutations'Aux_comm (a b : α) (l : List α) : exact perm_append_comm.append (ih.map _) theorem Perm.permutations' {s t : List α} (p : s ~ t) : permutations' s ~ permutations' t := by - induction' p with a s t _ IH a b l s t u _ _ IH₁ IH₂; · simp - · exact IH.bind_right _ - · dsimp + induction p with + | nil => simp + | cons _ _ IH => exact IH.bind_right _ + | swap => + dsimp rw [bind_assoc, bind_assoc] apply Perm.bind_left intro l' _ apply perm_permutations'Aux_comm - · exact IH₁.trans IH₂ + | trans _ _ IH₁ IH₂ => exact IH₁.trans IH₂ theorem permutations_perm_permutations' (ts : List α) : ts.permutations ~ ts.permutations' := by obtain ⟨n, h⟩ : ∃ n, length ts < n := ⟨_, Nat.lt_succ_self _⟩ @@ -513,13 +517,6 @@ theorem get_permutations'Aux (s : List α) (x : α) (n : ℕ) (permutations'Aux x s).get ⟨n, hn⟩ = s.insertNth n x := by simp [getElem_permutations'Aux] -set_option linter.deprecated false in -@[deprecated get_permutations'Aux (since := "2024-04-23")] -theorem nthLe_permutations'Aux (s : List α) (x : α) (n : ℕ) - (hn : n < length (permutations'Aux x s)) : - (permutations'Aux x s).nthLe n hn = s.insertNth n x := - get_permutations'Aux s x n hn - theorem count_permutations'Aux_self [DecidableEq α] (l : List α) (x : α) : count (x :: l) (permutations'Aux x l) = length (takeWhile (x = ·) l) + 1 := by induction' l with y l IH generalizing x @@ -564,37 +561,34 @@ theorem nodup_permutations'Aux_of_not_mem (s : List α) (x : α) (hx : x ∉ s) · exact IH hx.right · simp -set_option linter.deprecated false in theorem nodup_permutations'Aux_iff {s : List α} {x : α} : Nodup (permutations'Aux x s) ↔ x ∉ s := by - refine ⟨fun h => ?_, nodup_permutations'Aux_of_not_mem _ _⟩ - intro H - obtain ⟨k, hk, hk'⟩ := nthLe_of_mem H - rw [nodup_iff_nthLe_inj] at h - refine k.succ_ne_self.symm <| h k (k + 1) ?_ ?_ ?_ - · simpa [Nat.lt_succ_iff] using hk.le - · simpa using hk - rw [nthLe_permutations'Aux, nthLe_permutations'Aux] + refine ⟨fun h H ↦ ?_, nodup_permutations'Aux_of_not_mem _ _⟩ + obtain ⟨⟨k, hk⟩, hk'⟩ := get_of_mem H + rw [nodup_iff_injective_get] at h + apply k.succ_ne_self.symm + have kl : k < (permutations'Aux x s).length := by simpa [Nat.lt_succ_iff] using hk.le + have k1l : k + 1 < (permutations'Aux x s).length := by simpa using hk + rw [← @Fin.mk.inj_iff _ _ _ kl k1l]; apply h + rw [get_permutations'Aux, get_permutations'Aux] have hl : length (insertNth k x s) = length (insertNth (k + 1) x s) := by rw [length_insertNth _ _ hk.le, length_insertNth _ _ (Nat.succ_le_of_lt hk)] - refine ext_nthLe hl fun n hn hn' => ?_ + refine ext_get hl fun n hn hn' => ?_ rcases lt_trichotomy n k with (H | rfl | H) - · rw [nthLe_insertNth_of_lt _ _ _ _ H (H.trans hk), - nthLe_insertNth_of_lt _ _ _ _ (H.trans (Nat.lt_succ_self _))] - · rw [nthLe_insertNth_self _ _ _ hk.le, nthLe_insertNth_of_lt _ _ _ _ (Nat.lt_succ_self _) hk, - hk'] + · rw [get_insertNth_of_lt _ _ _ _ H (H.trans hk), + get_insertNth_of_lt _ _ _ _ (H.trans (Nat.lt_succ_self _))] + · rw [get_insertNth_self _ _ _ hk.le, get_insertNth_of_lt _ _ _ _ (Nat.lt_succ_self _) hk, hk'] · rcases (Nat.succ_le_of_lt H).eq_or_lt with (rfl | H') - · rw [nthLe_insertNth_self _ _ _ (Nat.succ_le_of_lt hk)] + · rw [get_insertNth_self _ _ _ (Nat.succ_le_of_lt hk)] convert hk' using 1 - exact nthLe_insertNth_add_succ _ _ _ 0 _ + 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 [nthLe_insertNth_add_succ] - · convert nthLe_insertNth_add_succ s x k m.succ (by simpa using hn) using 2 + 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] · simp [Nat.add_left_comm, Nat.add_comm] · simpa [Nat.succ_add] using hn -set_option linter.deprecated false in theorem nodup_permutations (s : List α) (hs : Nodup s) : Nodup s.permutations := by rw [(permutations_perm_permutations' s).nodup_iff] induction' hs with x l h h' IH @@ -614,24 +608,23 @@ theorem nodup_permutations (s : List α) (hs : Nodup s) : Nodup s.permutations : rw [mem_permutations'] at ha hb have hl : as.length = bs.length := (ha.trans hb.symm).length_eq simp only [Nat.lt_succ_iff, length_permutations'Aux] at hn hm - rw [← nthLe, nthLe_permutations'Aux] at hn' hm' + rw [get_permutations'Aux] at hn' hm' have hx : - nthLe (insertNth n x as) m (by rwa [length_insertNth _ _ hn, Nat.lt_succ_iff, hl]) = x := by + (insertNth n x as)[m]'(by rwa [length_insertNth _ _ hn, Nat.lt_succ_iff, hl]) = x := by simp [hn', ← hm', hm] have hx' : - nthLe (insertNth m x bs) n (by rwa [length_insertNth _ _ hm, Nat.lt_succ_iff, ← hl]) = - x := by + (insertNth m x bs)[n]'(by rwa [length_insertNth _ _ hm, Nat.lt_succ_iff, ← hl]) = x := by simp [hm', ← hn', hn] rcases lt_trichotomy n m with (ht | ht | ht) · suffices x ∈ bs by exact h x (hb.subset this) rfl - rw [← hx', nthLe_insertNth_of_lt _ _ _ _ ht (ht.trans_le hm)] - exact nthLe_mem _ _ _ + rw [← hx', getElem_insertNth_of_lt _ _ _ _ ht (ht.trans_le hm)] + exact get_mem _ _ _ · simp only [ht] at hm' hn' rw [← hm'] at hn' exact H (insertNth_injective _ _ hn') · suffices x ∈ as by exact h x (ha.subset this) rfl - rw [← hx, nthLe_insertNth_of_lt _ _ _ _ ht (ht.trans_le hn)] - exact nthLe_mem _ _ _ + rw [← hx, getElem_insertNth_of_lt _ _ _ _ ht (ht.trans_le hn)] + exact get_mem _ _ _ lemma permutations_take_two (x y : α) (s : List α) : (x :: y :: s).permutations.take 2 = [x :: y :: s, y :: x :: s] := by diff --git a/Mathlib/Data/List/Permutation.lean b/Mathlib/Data/List/Permutation.lean index 873cf8aacfaee..dfa4674956933 100644 --- a/Mathlib/Data/List/Permutation.lean +++ b/Mathlib/Data/List/Permutation.lean @@ -182,7 +182,7 @@ theorem mem_foldr_permutationsAux2 {t : α} {ts : List α} {r L : List (List α) theorem length_foldr_permutationsAux2 (t : α) (ts : List α) (r L : List (List α)) : length (foldr (fun y r => (permutationsAux2 t ts r y id).2) r L) = Nat.sum (map length L) + length r := by - simp [foldr_permutationsAux2, (· ∘ ·), length_permutationsAux2, length_bind'] + simp [foldr_permutationsAux2, Function.comp_def, length_permutationsAux2, length_bind'] theorem length_foldr_permutationsAux2' (t : α) (ts : List α) (r L : List (List α)) (n) (H : ∀ l ∈ L, length l = n) : diff --git a/Mathlib/Data/List/Pi.lean b/Mathlib/Data/List/Pi.lean index 25244772bc6f4..629d8a1e4f855 100644 --- a/Mathlib/Data/List/Pi.lean +++ b/Mathlib/Data/List/Pi.lean @@ -24,12 +24,12 @@ def nil (α : ι → Sort*) : (∀ i ∈ ([] : List ι), α i) := variable {i : ι} {l : List ι} -/-- Given `f` a function whose domain is `i :: l`, get its value at `i`. -/ +/-- Given `f` a function whose domain is `i :: l`, get its value at `i`. -/ def head (f : ∀ j ∈ i :: l, α j) : α i := f i (mem_cons_self _ _) /-- Given `f` a function whose domain is `i :: l`, produce a function whose domain -is restricted to `l`. -/ +is restricted to `l`. -/ def tail (f : ∀ j ∈ i :: l, α j) : ∀ j ∈ l, α j := fun j hj ↦ f j (mem_cons_of_mem _ hj) diff --git a/Mathlib/Data/List/ProdSigma.lean b/Mathlib/Data/List/ProdSigma.lean index 254509b226ec3..5b55bac8afedb 100644 --- a/Mathlib/Data/List/ProdSigma.lean +++ b/Mathlib/Data/List/ProdSigma.lean @@ -5,7 +5,6 @@ Authors: Leonardo de Moura, Mario Carneiro -/ import Mathlib.Data.List.Basic import Mathlib.Data.Sigma.Basic -import Batteries.Data.Nat.Lemmas /-! # Lists in product and sigma types diff --git a/Mathlib/Data/List/Range.lean b/Mathlib/Data/List/Range.lean index 65b273ac1e98b..66dd6c10fdb9b 100644 --- a/Mathlib/Data/List/Range.lean +++ b/Mathlib/Data/List/Range.lean @@ -5,8 +5,6 @@ Authors: Mario Carneiro, Kenny Lau, Scott Morrison -/ import Mathlib.Data.List.Chain import Mathlib.Data.List.Nodup -import Mathlib.Data.List.Pairwise -import Batteries.Data.Nat.Lemmas /-! # Ranges of naturals as lists @@ -27,14 +25,8 @@ namespace List variable {α : Type u} -set_option linter.deprecated false in -@[simp] -theorem nthLe_range' {n m step} (i) (H : i < (range' n m step).length) : - nthLe (range' n m step) i H = n + step * i := get_range' i H - -set_option linter.deprecated false in -theorem nthLe_range'_1 {n m} (i) (H : i < (range' n m).length) : - nthLe (range' n m) i H = n + i := by simp +theorem getElem_range'_1 {n m} (i) (H : i < (range' n m).length) : + (range' n m)[i] = n + i := by simp theorem chain'_range_succ (r : ℕ → ℕ → Prop) (n : ℕ) : Chain' r (range n.succ) ↔ ∀ m < n, r m m.succ := by @@ -83,31 +75,25 @@ theorem pairwise_lt_finRange (n : ℕ) : Pairwise (· < ·) (finRange n) := theorem pairwise_le_finRange (n : ℕ) : Pairwise (· ≤ ·) (finRange n) := (List.pairwise_le_range n).pmap (by simp) (by simp) -set_option linter.deprecated false in -@[simp] -theorem nthLe_range {n} (i) (H : i < (range n).length) : nthLe (range n) i H = i := - get_range i H - @[simp] theorem getElem_finRange {n : ℕ} {i : ℕ} (h) : (finRange n)[i] = ⟨i, length_finRange n ▸ h⟩ := by - simp only [finRange, getElem_range, getElem_pmap] + simp [finRange, getElem_range, getElem_pmap] -- Porting note (#10756): new theorem theorem get_finRange {n : ℕ} {i : ℕ} (h) : (finRange n).get ⟨i, h⟩ = ⟨i, length_finRange n ▸ h⟩ := by simp +@[deprecated (since := "2024-08-19")] alias nthLe_range' := get_range' +@[deprecated (since := "2024-08-19")] alias nthLe_range'_1 := getElem_range'_1 +@[deprecated (since := "2024-08-19")] alias nthLe_range := get_range +@[deprecated (since := "2024-08-19")] alias nthLe_finRange := get_finRange + @[simp] theorem finRange_map_get (l : List α) : (finRange l.length).map l.get = l := List.ext_get (by simp) (by simp) -set_option linter.deprecated false in -@[simp] -theorem nthLe_finRange {n : ℕ} {i : ℕ} (h) : - (finRange n).nthLe i h = ⟨i, length_finRange n ▸ h⟩ := - get_finRange h - @[simp] theorem indexOf_finRange {k : ℕ} (i : Fin k) : (finRange k).indexOf i = i := by have : (finRange k).indexOf i < (finRange k).length := indexOf_lt_length.mpr (by simp) have h₁ : (finRange k).get ⟨(finRange k).indexOf i, this⟩ = i := indexOf_get this diff --git a/Mathlib/Data/List/Rotate.lean b/Mathlib/Data/List/Rotate.lean index c38e181f92a8d..5cbd6337a5630 100644 --- a/Mathlib/Data/List/Rotate.lean +++ b/Mathlib/Data/List/Rotate.lean @@ -168,7 +168,6 @@ theorem rotate_eq_nil_iff {l : List α} {n : ℕ} : l.rotate n = [] ↔ l = [] : · simp · simp [rotate_cons_succ, hn] -@[simp] theorem nil_eq_rotate_iff {l : List α} {n : ℕ} : [] = l.rotate n ↔ [] = l := by rw [eq_comm, rotate_eq_nil_iff, eq_comm] @@ -195,11 +194,11 @@ theorem getElem?_rotate {l : List α} {n m : ℕ} (hml : m < l.length) : (l.rotate n)[m]? = l[(m + n) % l.length]? := by rw [rotate_eq_drop_append_take_mod] rcases lt_or_le m (l.drop (n % l.length)).length with hm | hm - · rw [getElem?_append hm, getElem?_drop, ← add_mod_mod] + · rw [getElem?_append_left hm, getElem?_drop, ← add_mod_mod] rw [length_drop, Nat.lt_sub_iff_add_lt] at hm rw [mod_eq_of_lt hm, Nat.add_comm] · have hlt : n % length l < length l := mod_lt _ (m.zero_le.trans_lt hml) - rw [getElem?_append_right hm, getElem?_take, length_drop] + rw [getElem?_append_right hm, getElem?_take_of_lt, length_drop] · congr 1 rw [length_drop] at hm have hm' := Nat.sub_le_iff_le_add'.1 hm @@ -225,28 +224,18 @@ theorem get?_rotate {l : List α} {n m : ℕ} (hml : m < l.length) : -- Porting note (#10756): new lemma theorem get_rotate (l : List α) (n : ℕ) (k : Fin (l.rotate n).length) : - (l.rotate n).get k = - l.get ⟨(k + n) % l.length, mod_lt _ (length_rotate l n ▸ k.1.zero_le.trans_lt k.2)⟩ := by + (l.rotate n).get k = l.get ⟨(k + n) % l.length, mod_lt _ (length_rotate l n ▸ k.pos)⟩ := by simp [getElem_rotate] theorem head?_rotate {l : List α} {n : ℕ} (h : n < l.length) : head? (l.rotate n) = l[n]? := by rw [← get?_zero, get?_rotate (n.zero_le.trans_lt h), Nat.zero_add, Nat.mod_eq_of_lt h, get?_eq_getElem?] --- Porting note: moved down from its original location below `get_rotate` so that the --- non-deprecated lemma does not use the deprecated version -set_option linter.deprecated false in -@[deprecated get_rotate (since := "2023-01-13")] -theorem nthLe_rotate (l : List α) (n k : ℕ) (hk : k < (l.rotate n).length) : - (l.rotate n).nthLe k hk = - l.nthLe ((k + n) % l.length) (mod_lt _ (length_rotate l n ▸ k.zero_le.trans_lt hk)) := - get_rotate l n ⟨k, hk⟩ - -set_option linter.deprecated false in -theorem nthLe_rotate_one (l : List α) (k : ℕ) (hk : k < (l.rotate 1).length) : - (l.rotate 1).nthLe k hk = - l.nthLe ((k + 1) % l.length) (mod_lt _ (length_rotate l 1 ▸ k.zero_le.trans_lt hk)) := - nthLe_rotate l 1 k hk +theorem get_rotate_one (l : List α) (k : Fin (l.rotate 1).length) : + (l.rotate 1).get k = l.get ⟨(k + 1) % l.length, mod_lt _ (length_rotate l 1 ▸ k.pos)⟩ := + get_rotate l 1 k + +@[deprecated (since := "2024-08-19")] alias nthLe_rotate_one := get_rotate_one /-- A version of `List.get_rotate` that represents `List.get l` in terms of `List.get (List.rotate l n)`, not vice versa. Can be used instead of rewriting `List.get_rotate` @@ -260,15 +249,6 @@ theorem get_eq_get_rotate (l : List α) (n : ℕ) (k : Fin l.length) : rw [← add_mod_mod, Nat.add_right_comm, Nat.sub_add_cancel, add_mod_left, mod_eq_of_lt] exacts [k.2, (mod_lt _ (k.1.zero_le.trans_lt k.2)).le] -set_option linter.deprecated false in -/-- A variant of `List.nthLe_rotate` useful for rewrites from right to left. -/ -@[deprecated get_eq_get_rotate (since := "2023-03-26")] -theorem nthLe_rotate' (l : List α) (n k : ℕ) (hk : k < l.length) : - (l.rotate n).nthLe ((l.length - n % l.length + k) % l.length) - ((Nat.mod_lt _ (k.zero_le.trans_lt hk)).trans_le (length_rotate _ _).ge) = - l.nthLe k hk := - (get_eq_get_rotate l n ⟨k, hk⟩).symm - theorem rotate_eq_self_iff_eq_replicate [hα : Nonempty α] : ∀ {l : List α}, (∀ n, l.rotate n = l) ↔ ∃ a, l = replicate l.length a | [] => by simp @@ -478,6 +458,24 @@ theorem IsRotated.map {β : Type*} {l₁ l₂ : List α} (h : l₁ ~r l₂) (f : rw [map_rotate] use n +theorem IsRotated.cons_getLast_dropLast + (L : List α) (hL : L ≠ []) : L.getLast hL :: L.dropLast ~r L := by + induction L using List.reverseRecOn with + | nil => simp at hL + | append_singleton a L _ => + simp only [getLast_append, dropLast_concat] + apply IsRotated.symm + apply isRotated_concat + +theorem IsRotated.dropLast_tail {α} + {L : List α} (hL : L ≠ []) (hL' : L.head hL = L.getLast hL) : L.dropLast ~r L.tail := + match L with + | [] => by simp + | [_] => by simp + | a :: b :: L => by + simp at hL' |- + simp [hL', IsRotated.cons_getLast_dropLast] + /-- List of all cyclic permutations of `l`. The `cyclicPermutations` of a nonempty list `l` will always contain `List.length l` elements. This implies that under certain conditions, there are duplicates in `List.cyclicPermutations l`. diff --git a/Mathlib/Data/List/Sigma.lean b/Mathlib/Data/List/Sigma.lean index 4419034921ee1..ba2c572fe9480 100644 --- a/Mathlib/Data/List/Sigma.lean +++ b/Mathlib/Data/List/Sigma.lean @@ -26,11 +26,11 @@ If `α : Type*` and `β : α → Type*`, then we regard `s : Sigma β` as having - `List.kextract` returns a value with a given key and the rest of the values. -/ -universe u v +universe u u' v v' namespace List -variable {α : Type u} {β : α → Type v} {l l₁ l₂ : List (Sigma β)} +variable {α : Type u} {α' : Type u'} {β : α → Type v} {β' : α' → Type v'} {l l₁ l₂ : List (Sigma β)} /-! ### `keys` -/ @@ -123,7 +123,7 @@ theorem nodupKeys_join {L : List (List (Sigma β))} : rw [nodupKeys_iff_pairwise, pairwise_join, pairwise_map] refine and_congr (forall₂_congr fun l _ => by simp [nodupKeys_iff_pairwise]) ?_ apply iff_of_eq; congr with (l₁ l₂) - simp [keys, disjoint_iff_ne] + simp [keys, disjoint_iff_ne, Sigma.forall] theorem nodup_enum_map_fst (l : List α) : (l.enum.map Prod.fst).Nodup := by simp [List.nodup_range] @@ -131,7 +131,7 @@ theorem mem_ext {l₀ l₁ : List (Sigma β)} (nd₀ : l₀.Nodup) (nd₁ : l₁ (h : ∀ x, x ∈ l₀ ↔ x ∈ l₁) : l₀ ~ l₁ := (perm_ext_iff_of_nodup nd₀ nd₁).2 h -variable [DecidableEq α] +variable [DecidableEq α] [DecidableEq α'] /-! ### `dlookup` -/ @@ -204,6 +204,25 @@ theorem lookup_ext {l₀ l₁ : List (Sigma β)} (nd₀ : l₀.NodupKeys) (nd₁ mem_ext nd₀.nodup nd₁.nodup fun ⟨a, b⟩ => by rw [← mem_dlookup_iff, ← mem_dlookup_iff, h] <;> assumption +theorem dlookup_map (l : List (Sigma β)) + {f : α → α'} (hf : Function.Injective f) (g : ∀ a, β a → β' (f a)) (a : α) : + (l.map fun x => ⟨f x.1, g _ x.2⟩).dlookup (f a) = (l.dlookup a).map (g a) := by + induction' l with b l IH + · rw [map_nil, dlookup_nil, dlookup_nil, Option.map_none'] + · rw [map_cons] + obtain rfl | h := eq_or_ne a b.1 + · rw [dlookup_cons_eq, dlookup_cons_eq, Option.map_some'] + · rw [dlookup_cons_ne _ _ h, dlookup_cons_ne _ _ (fun he => h <| hf he), IH] + +theorem dlookup_map₁ {β : Type v} (l : List (Σ _ : α, β)) + {f : α → α'} (hf : Function.Injective f) (a : α) : + (l.map fun x => ⟨f x.1, x.2⟩ : List (Σ _ : α', β)).dlookup (f a) = l.dlookup a := by + rw [dlookup_map (β' := fun _ => β) l hf (fun _ x => x) a, Option.map_id'] + +theorem dlookup_map₂ {γ δ : α → Type*} {l : List (Σ a, γ a)} {f : ∀ a, γ a → δ a} (a : α) : + (l.map fun x => ⟨x.1, f _ x.2⟩ : List (Σ a, δ a)).dlookup a = (l.dlookup a).map (f a) := + dlookup_map l Function.injective_id _ _ + /-! ### `lookupAll` -/ @@ -231,7 +250,7 @@ theorem lookupAll_eq_nil {a : α} : by_cases h : a = a' · subst a' simp only [lookupAll_cons_eq, mem_cons, Sigma.mk.inj_iff, heq_eq_eq, true_and, not_or, - false_iff, not_forall, not_and, not_not] + false_iff, not_forall, not_and, not_not, reduceCtorEq] use b simp · simp [h, lookupAll_eq_nil] @@ -282,6 +301,16 @@ theorem perm_lookupAll (a : α) {l₁ l₂ : List (Sigma β)} (nd₁ : l₁.Nodu (p : l₁ ~ l₂) : lookupAll a l₁ = lookupAll a l₂ := by simp [lookupAll_eq_dlookup, nd₁, nd₂, perm_dlookup a nd₁ nd₂ p] +theorem dlookup_append (l₁ l₂ : List (Sigma β)) (a : α) : + (l₁ ++ l₂).dlookup a = (l₁.dlookup a).or (l₂.dlookup a) := by + induction l₁ with + | nil => rfl + | cons x l₁ IH => + rw [cons_append] + obtain rfl | hb := Decidable.eq_or_ne a x.1 + · rw [dlookup_cons_eq, dlookup_cons_eq, Option.or] + · rw [dlookup_cons_ne _ _ hb, dlookup_cons_ne _ _ hb, IH] + /-! ### `kreplace` -/ @@ -350,7 +379,9 @@ theorem kerase_cons_ne {a} {s : Sigma β} {l : List (Sigma β)} (h : a ≠ s.1) @[simp] theorem kerase_of_not_mem_keys {a} {l : List (Sigma β)} (h : a ∉ l.keys) : kerase a l = l := by - induction' l with _ _ ih <;> [rfl; (simp [not_or] at h; simp [h.1, ih h.2])] + induction l with + | nil => rfl + | cons _ _ ih => simp [not_or] at h; simp [h.1, ih h.2] theorem kerase_sublist (a : α) (l : List (Sigma β)) : kerase a l <+ l := eraseP_sublist _ @@ -388,7 +419,7 @@ theorem mem_keys_kerase_of_ne {a₁ a₂} {l : List (Sigma β)} (h : a₁ ≠ a else by simp [q, p] theorem keys_kerase {a} {l : List (Sigma β)} : (kerase a l).keys = l.keys.erase a := by - rw [keys, kerase, erase_eq_eraseP, eraseP_map, Function.comp] + rw [keys, kerase, erase_eq_eraseP, eraseP_map, Function.comp_def] simp only [beq_eq_decide] congr funext diff --git a/Mathlib/Data/List/Sort.lean b/Mathlib/Data/List/Sort.lean index 7866907505fca..6936029a0217b 100644 --- a/Mathlib/Data/List/Sort.lean +++ b/Mathlib/Data/List/Sort.lean @@ -5,8 +5,8 @@ Authors: Jeremy Avigad -/ import Mathlib.Data.List.OfFn import Mathlib.Data.List.Nodup -import Mathlib.Data.List.Infix import Mathlib.Order.Fin.Basic +import Batteries.Data.List.Perm /-! # Sorting algorithms on lists @@ -14,13 +14,31 @@ import Mathlib.Order.Fin.Basic In this file we define `List.Sorted r l` to be an alias for `List.Pairwise r l`. This alias is preferred in the case that `r` is a `<` or `≤`-like relation. Then we define two sorting algorithms: -`List.insertionSort` and `List.mergeSort`, and prove their correctness. +`List.insertionSort` and `List.mergeSort'`, and prove their correctness. +-/ + +#adaptation_note +/-- +`List.mergeSort` has now been implemented in Lean4. +It improves on the one here by being a "stable" sort +(in the sense that a sorted sublist of the original list remains a sublist of the result), +and is also marginally faster. + +However we haven't yet replaced `List.mergeSort'` here. +The obstacle is that `mergeSort'` is written using `r : α → α → Prop` with `[DecidableRel r]`, +while `mergeSort` uses `r : α → α → Bool`. This is hardly insurmountable, +but it's a bit of work that hasn't been done yet. + +`List.mergeSort'` is only used in Mathlib to sort multisets for printing, so this is not critical. + +A pull request cleaning up here, and ideally deprecating or deleting `List.mergeSort'`, +would be welcome. -/ open List.Perm -universe u +universe u v namespace List @@ -31,7 +49,7 @@ namespace List section Sorted -variable {α : Type u} {r : α → α → Prop} {a : α} {l : List α} +variable {α : Type u} {β : Type v} {r : α → α → Prop} {s : β → β → Prop} {a : α} {l : List α} /-- `Sorted r l` is the same as `List.Pairwise r l`, preferred in the case that `r` is a `<` or `≤`-like relation (transitive and antisymmetric or asymmetric) -/ @@ -123,27 +141,15 @@ theorem Sorted.rel_get_of_lt {l : List α} (h : l.Sorted r) {a b : Fin l.length} r (l.get a) (l.get b) := List.pairwise_iff_get.1 h _ _ hab -set_option linter.deprecated false in -@[deprecated Sorted.rel_get_of_lt (since := "2024-05-08")] -theorem Sorted.rel_nthLe_of_lt {l : List α} (h : l.Sorted r) {a b : ℕ} (ha : a < l.length) - (hb : b < l.length) (hab : a < b) : r (l.nthLe a ha) (l.nthLe b hb) := - List.pairwise_iff_get.1 h ⟨a, ha⟩ ⟨b, hb⟩ hab - theorem Sorted.rel_get_of_le [IsRefl α r] {l : List α} (h : l.Sorted r) {a b : Fin l.length} (hab : a ≤ b) : r (l.get a) (l.get b) := by obtain rfl | hlt := Fin.eq_or_lt_of_le hab; exacts [refl _, h.rel_get_of_lt hlt] -set_option linter.deprecated false in -@[deprecated Sorted.rel_get_of_le (since := "2024-05-08")] -theorem Sorted.rel_nthLe_of_le [IsRefl α r] {l : List α} (h : l.Sorted r) {a b : ℕ} - (ha : a < l.length) (hb : b < l.length) (hab : a ≤ b) : r (l.nthLe a ha) (l.nthLe b hb) := - h.rel_get_of_le hab - theorem Sorted.rel_of_mem_take_of_mem_drop {l : List α} (h : List.Sorted r l) {k : ℕ} {x y : α} (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) @@ -167,10 +173,6 @@ strictly monotone. -/ @[simp] theorem sorted_le_ofFn_iff : (ofFn f).Sorted (· ≤ ·) ↔ Monotone f := sorted_ofFn_iff.trans monotone_iff_forall_lt.symm -/-- A tuple is monotone if and only if the list obtained from it is sorted. -/ -@[deprecated sorted_le_ofFn_iff (since := "2023-01-10")] -theorem monotone_iff_ofFn_sorted : Monotone f ↔ (ofFn f).Sorted (· ≤ ·) := sorted_le_ofFn_iff.symm - /-- The list obtained from a monotone tuple is sorted. -/ alias ⟨_, _root_.Monotone.ofFn_sorted⟩ := sorted_le_ofFn_iff @@ -178,9 +180,11 @@ end Monotone section sort -variable {α : Type u} (r : α → α → Prop) [DecidableRel r] +variable {α : Type u} {β : Type v} (r : α → α → Prop) (s : β → β → Prop) +variable [DecidableRel r] [DecidableRel s] local infixl:50 " ≼ " => r +local infixl:50 " ≼ " => s /-! ### Insertion sort -/ @@ -236,6 +240,18 @@ theorem mem_orderedInsert {a b : α} {l : List α} : · simp [orderedInsert] · rw [mem_cons, mem_cons, mem_orderedInsert, or_left_comm] +theorem map_orderedInsert (f : α → β) (l : List α) (x : α) + (hl₁ : ∀ a ∈ l, a ≼ x ↔ f a ≼ f x) (hl₂ : ∀ a ∈ l, x ≼ a ↔ f x ≼ f a) : + (l.orderedInsert r x).map f = (l.map f).orderedInsert s (f x) := by + induction l with + | nil => simp + | cons x xs ih => + rw [List.forall_mem_cons] at hl₁ hl₂ + simp only [List.map, List.orderedInsert, ← hl₁.1, ← hl₂.1] + split_ifs + · rw [List.map, List.map] + · rw [List.map, ih (fun _ ha => hl₁.2 _ ha) (fun _ ha => hl₂.2 _ ha)] + section Correctness open Perm @@ -257,6 +273,25 @@ theorem perm_insertionSort : ∀ l : List α, insertionSort r l ~ l | b :: l => by simpa [insertionSort] using (perm_orderedInsert _ _ _).trans ((perm_insertionSort l).cons b) +@[simp] +theorem mem_insertionSort {l : List α} {x : α} : x ∈ l.insertionSort r ↔ x ∈ l := + (perm_insertionSort r l).mem_iff + +@[simp] +theorem length_insertionSort (l : List α) : (insertionSort r l).length = l.length := + (perm_insertionSort r _).length_eq + +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 + | nil => simp + | cons x xs ih => + simp_rw [List.forall_mem_cons, forall_and] at hl + simp_rw [List.map, List.insertionSort] + rw [List.map_orderedInsert _ s, ih hl.2.2] + · simpa only [mem_insertionSort] using hl.2.1 + · simpa only [mem_insertionSort] using hl.1.2 + variable {r} /-- If `l` is already `List.Sorted` with respect to `r`, then `insertionSort` does not change @@ -363,6 +398,17 @@ def split : List α → List α × List α theorem split_cons_of_eq (a : α) {l l₁ l₂ : List α} (h : split l = (l₁, l₂)) : split (a :: l) = (a :: l₂, l₁) := by rw [split, h] +@[simp] +theorem map_split (f : α → β) : + ∀ l : List α, (map f l).split = (l.split.1.map f, l.split.2.map f) + | [] => rfl + | a :: l => by simp [map_split] + +@[simp] +theorem mem_split_iff {x : α} : ∀ {l : List α}, x ∈ l.split.1 ∨ x ∈ l.split.2 ↔ x ∈ l + | [] => by simp + | a :: l => by simp_rw [split, mem_cons, or_assoc, or_comm, mem_split_iff] + theorem length_split_le : ∀ {l l₁ l₂ : List α}, split l = (l₁, l₂) → length l₁ ≤ length l ∧ length l₂ ≤ length l | [], _, _, rfl => ⟨Nat.le_refl 0, Nat.le_refl 0⟩ @@ -393,7 +439,7 @@ theorem perm_split : ∀ {l l₁ l₂ : List α}, split l = (l₁, l₂) → l ~ exact ((perm_split e).trans perm_append_comm).cons a /-- Implementation of a merge sort algorithm to sort a list. -/ -def mergeSort : List α → List α +def mergeSort' : List α → List α | [] => [] | [a] => [a] | a :: b :: l => by @@ -401,31 +447,35 @@ 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 (r · ·) (mergeSort' ls.1) (mergeSort' ls.2) 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 - simp only [mergeSort, h] +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 + simp only [mergeSort', h] section Correctness -theorem perm_mergeSort : ∀ l : List α, mergeSort r l ~ l - | [] => by simp [mergeSort] - | [a] => by simp [mergeSort] +theorem perm_mergeSort' : ∀ l : List α, mergeSort' r l ~ l + | [] => by simp [mergeSort'] + | [a] => by simp [mergeSort'] | a :: b :: l => by cases' e : split (a :: b :: l) with l₁ l₂ cases' length_split_lt e with h₁ h₂ - rw [mergeSort_cons_cons r e] + rw [mergeSort'_cons_cons r e] apply (perm_merge (r · ·) _ _).trans exact - ((perm_mergeSort l₁).append (perm_mergeSort l₂)).trans (perm_split e).symm + ((perm_mergeSort' l₁).append (perm_mergeSort' l₂)).trans (perm_split e).symm termination_by l => length l @[simp] -theorem length_mergeSort (l : List α) : (mergeSort r l).length = l.length := - (perm_mergeSort r _).length_eq +theorem mem_mergeSort' {l : List α} {x : α} : x ∈ l.mergeSort' r ↔ x ∈ l := + (perm_mergeSort' r l).mem_iff + +@[simp] +theorem length_mergeSort' (l : List α) : (mergeSort' r l).length = l.length := + (perm_mergeSort' r _).length_eq section TotalAndTransitive @@ -460,33 +510,72 @@ theorem Sorted.merge : ∀ {l l' : List α}, Sorted r l → Sorted r l' → Sort variable (r) -theorem sorted_mergeSort : ∀ l : List α, Sorted r (mergeSort r l) - | [] => by simp [mergeSort] - | [a] => by simp [mergeSort] +theorem sorted_mergeSort' : ∀ l : List α, Sorted r (mergeSort' r l) + | [] => by simp [mergeSort'] + | [a] => by simp [mergeSort'] | a :: b :: l => by cases' e : split (a :: b :: l) with l₁ l₂ cases' length_split_lt e with h₁ h₂ - rw [mergeSort_cons_cons r e] - exact (sorted_mergeSort l₁).merge (sorted_mergeSort l₂) + rw [mergeSort'_cons_cons r e] + exact (sorted_mergeSort' l₁).merge (sorted_mergeSort' l₂) termination_by l => length l -theorem mergeSort_eq_self [IsAntisymm α r] {l : List α} : Sorted r l → mergeSort r l = l := - eq_of_perm_of_sorted (perm_mergeSort _ _) (sorted_mergeSort _ _) +theorem mergeSort'_eq_self [IsAntisymm α r] {l : List α} : Sorted r l → mergeSort' r l = l := + eq_of_perm_of_sorted (perm_mergeSort' _ _) (sorted_mergeSort' _ _) -theorem mergeSort_eq_insertionSort [IsAntisymm α r] (l : List α) : - mergeSort r l = insertionSort r l := - eq_of_perm_of_sorted ((perm_mergeSort r l).trans (perm_insertionSort r l).symm) - (sorted_mergeSort r l) (sorted_insertionSort r l) +theorem mergeSort'_eq_insertionSort [IsAntisymm α r] (l : List α) : + mergeSort' r l = insertionSort r l := + eq_of_perm_of_sorted ((perm_mergeSort' r l).trans (perm_insertionSort r l).symm) + (sorted_mergeSort' r l) (sorted_insertionSort r l) end TotalAndTransitive end Correctness @[simp] -theorem mergeSort_nil : [].mergeSort r = [] := by rw [List.mergeSort] +theorem mergeSort'_nil : [].mergeSort' r = [] := by rw [List.mergeSort'] @[simp] -theorem mergeSort_singleton (a : α) : [a].mergeSort r = [a] := by rw [List.mergeSort] +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 + | [] => by simp + | [x] => by simp + | a :: b :: l => by + simp_rw [← mem_split_iff (l := a :: b :: l), or_imp, forall_and] at hl + set l₁ := (split (a :: b :: l)).1 + set l₂ := (split (a :: b :: l)).2 + have e : split (a :: b :: l) = (l₁, l₂) := rfl + have fe : split (f a :: f b :: l.map f) = (l₁.map f, l₂.map f) := by + rw [← map, ← map, map_split, e] + have := length_split_fst_le l + 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] + simp_rw [mem_mergeSort', decide_eq_decide] + exact hl.1.2 + termination_by length l end MergeSort @@ -494,5 +583,5 @@ end sort -- try them out! --#eval insertionSort (fun m n : ℕ => m ≤ n) [5, 27, 221, 95, 17, 43, 7, 2, 98, 567, 23, 12] ---#eval mergeSort (fun m n : ℕ => m ≤ n) [5, 27, 221, 95, 17, 43, 7, 2, 98, 567, 23, 12] +--#eval mergeSort' (fun m n : ℕ => m ≤ n) [5, 27, 221, 95, 17, 43, 7, 2, 98, 567, 23, 12] end List diff --git a/Mathlib/Data/List/Sublists.lean b/Mathlib/Data/List/Sublists.lean index 7df5ef9099e10..8eac342a35b41 100644 --- a/Mathlib/Data/List/Sublists.lean +++ b/Mathlib/Data/List/Sublists.lean @@ -138,7 +138,7 @@ theorem sublists_append (l₁ l₂ : List α) : | nil => simp | cons a l₁ ih => rw [foldr_cons, ih] - simp [List.bind, join_join, Function.comp] + simp [List.bind, join_join, Function.comp_def] theorem sublists_cons (a : α) (l : List α) : sublists (a :: l) = sublists l >>= (fun x => [x, a :: x]) := @@ -155,13 +155,13 @@ theorem sublists_concat (l : List α) (a : α) : theorem sublists_reverse (l : List α) : sublists (reverse l) = map reverse (sublists' l) := by induction' l with hd tl ih <;> [rfl; simp only [reverse_cons, sublists_append, sublists'_cons, map_append, ih, sublists_singleton, - map_eq_map, bind_eq_bind, map_map, bind_cons, append_nil, bind_nil, (· ∘ ·)]] + map_eq_map, bind_eq_bind, map_map, bind_cons, append_nil, bind_nil, Function.comp_def]] theorem sublists_eq_sublists' (l : List α) : sublists l = map reverse (sublists' (reverse l)) := by rw [← sublists_reverse, reverse_reverse] theorem sublists'_reverse (l : List α) : sublists' (reverse l) = map reverse (sublists l) := by - simp only [sublists_eq_sublists', map_map, map_id'' reverse_reverse, Function.comp] + simp only [sublists_eq_sublists', map_map, map_id'' reverse_reverse, Function.comp_def] theorem sublists'_eq_sublists (l : List α) : sublists' l = map reverse (sublists (reverse l)) := by rw [← sublists'_reverse, reverse_reverse] diff --git a/Mathlib/Data/List/ToFinsupp.lean b/Mathlib/Data/List/ToFinsupp.lean index b8fbb880f704e..5d55f1ae03af6 100644 --- a/Mathlib/Data/List/ToFinsupp.lean +++ b/Mathlib/Data/List/ToFinsupp.lean @@ -62,10 +62,10 @@ theorem toFinsupp_support : rfl theorem toFinsupp_apply_lt (hn : n < l.length) : l.toFinsupp n = l[n] := - getD_eq_getElem _ _ _ + getD_eq_getElem _ _ hn theorem toFinsupp_apply_fin (n : Fin l.length) : l.toFinsupp n = l[n] := - getD_eq_getElem _ _ _ + getD_eq_getElem _ _ n.isLt theorem toFinsupp_apply_le (hn : l.length ≤ n) : l.toFinsupp n = 0 := getD_eq_default _ _ hn diff --git a/Mathlib/Data/List/Zip.lean b/Mathlib/Data/List/Zip.lean index b67d88264a517..b53a34837076a 100644 --- a/Mathlib/Data/List/Zip.lean +++ b/Mathlib/Data/List/Zip.lean @@ -144,27 +144,12 @@ theorem get_zipWith {f : α → β → γ} {l : List α} {l' : List β} {i : Fin (l'.get ⟨i, lt_length_right_of_zipWith i.isLt⟩) := by simp -set_option linter.deprecated false in -@[simp, deprecated get_zipWith (since := "2024-05-09")] -theorem nthLe_zipWith {f : α → β → γ} {l : List α} {l' : List β} {i : ℕ} - {h : i < (zipWith f l l').length} : - (zipWith f l l').nthLe i h = - f (l.nthLe i (lt_length_left_of_zipWith h)) (l'.nthLe i (lt_length_right_of_zipWith h)) := - get_zipWith (i := ⟨i, h⟩) - @[deprecated getElem_zip (since := "2024-06-12")] theorem get_zip {l : List α} {l' : List β} {i : Fin (zip l l').length} : (zip l l').get i = (l.get ⟨i, lt_length_left_of_zip i.isLt⟩, l'.get ⟨i, lt_length_right_of_zip i.isLt⟩) := by simp -set_option linter.deprecated false in -@[simp, deprecated get_zip (since := "2024-05-09")] -theorem nthLe_zip {l : List α} {l' : List β} {i : ℕ} {h : i < (zip l l').length} : - (zip l l').nthLe i h = - (l.nthLe i (lt_length_left_of_zip h), l'.nthLe i (lt_length_right_of_zip h)) := - nthLe_zipWith - theorem mem_zip_inits_tails {l : List α} {init tail : List α} : (init, tail) ∈ zip l.inits l.tails ↔ init ++ tail = l := by induction' l with hd tl ih generalizing init tail <;> simp_rw [tails, inits, zip_cons_cons] diff --git a/Mathlib/Data/MLList/BestFirst.lean b/Mathlib/Data/MLList/BestFirst.lean index 38b1922f6cf69..04d8b676c5644 100644 --- a/Mathlib/Data/MLList/BestFirst.lean +++ b/Mathlib/Data/MLList/BestFirst.lean @@ -40,7 +40,7 @@ If someone would like to generalize appropriately that would be great. We want to maintain a priority queue of `MLList m β`, each indexed by some `a : α` with a priority. (One could simplify matters here by simply flattening this out to a priority queue of pairs `α × β`, with the priority determined by the `α` factor. -However the lazyness of `MLList` is essential to performance here: +However the laziness of `MLList` is essential to performance here: we will extract elements from these lists one at a time, and only when they at the head of the queue. If another item arrives at the head of the queue, @@ -87,9 +87,7 @@ structure BestFirstNode {α : Sort*} {ω : Type*} (prio : α → Thunk ω) (ε : (We will assume we have `[∀ a : α, Estimator (prio a) (ε a)]`.) -/ estimator : ε key -set_option autoImplicit true - -variable {α : Type} {prio : α → Thunk ω} {ε : α → Type} [LinearOrder ω] +variable {ω α : Type} {prio : α → Thunk ω} {ε : α → Type} [LinearOrder ω] [∀ a, Estimator (prio a) (ε a)] [I : ∀ a : α, WellFoundedGT (range (bound (prio a) : ε a → ω))] {m : Type → Type} [Monad m] {β : Type} diff --git a/Mathlib/Data/MLList/Dedup.lean b/Mathlib/Data/MLList/Dedup.lean index 880fe43d4416e..870c13fb4f7ab 100644 --- a/Mathlib/Data/MLList/Dedup.lean +++ b/Mathlib/Data/MLList/Dedup.lean @@ -9,8 +9,14 @@ import Batteries.Data.HashMap.Basic /-! # Lazy deduplication of lazy lists + +## Deprecation + +This material has been moved out of Mathlib to https://github.com/semorrison/lean-monadic-list. -/ +set_option linter.deprecated false + open Batteries namespace MLList @@ -19,6 +25,7 @@ variable {α β : Type} {m : Type → Type} [Monad m] [BEq β] [Hashable β] /-- Lazily deduplicate a lazy list, using a stored `HashMap`. -/ -- We choose `HashMap` here instead of `RBSet` as the initial application is `Expr`. +@[deprecated "See deprecation note in module documentation." (since := "2024-08-22")] def dedupBy (L : MLList m α) (f : α → m β) : MLList m α := ((L.liftM : MLList (StateT (HashMap β Unit) m) α) >>= fun a => do let b ← f a @@ -28,6 +35,7 @@ def dedupBy (L : MLList m α) (f : α → m β) : MLList m α := |>.runState' ∅ /-- 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) diff --git a/Mathlib/Data/MLList/DepthFirst.lean b/Mathlib/Data/MLList/DepthFirst.lean index 0e0b0e96a5e2b..4454d1b3d8207 100644 --- a/Mathlib/Data/MLList/DepthFirst.lean +++ b/Mathlib/Data/MLList/DepthFirst.lean @@ -3,9 +3,9 @@ Copyright (c) 2023 Scott Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Morrison -/ -import Lean.Data.HashSet import Batteries.Data.MLList.Basic import Mathlib.Control.Combinators +import Std.Data.HashSet.Basic /-! # Depth first search @@ -17,8 +17,14 @@ or a lazy list `α → MLList MetaM α`. This is useful in meta code for searching for solutions in the presence of alternatives. It can be nice to represent the choices via a lazy list, so the later choices don't need to be evaluated while we do depth first search on earlier choices. + +## Deprecation + +This material has been moved out of Mathlib to https://github.com/semorrison/lean-monadic-list. -/ +set_option linter.deprecated false + universe u variable {α : Type u} {m : Type u → Type u} @@ -28,6 +34,7 @@ variable [Monad m] [Alternative m] /-- A generalisation of `depthFirst`, which allows the generation function to know the current depth, and to count the depth starting from a specified value. -/ +@[deprecated "See deprecation note in module documentation." (since := "2024-08-22")] partial def depthFirst' (f : Nat → α → m α) (n : Nat) (a : α) : m α := pure a <|> joinM ((f n a) <&> (depthFirst' f (n+1))) @@ -43,6 +50,7 @@ The option `maxDepth` limits the search depth. Note that if the graph is not a tree then elements will be visited multiple times. (See `depthFirstRemovingDuplicates`) -/ +@[deprecated "See deprecation note in module documentation." (since := "2024-08-22")] def depthFirst (f : α → m α) (a : α) (maxDepth : Option Nat := none) : m α := match maxDepth with | some d => depthFirst' (fun n a => if n ≤ d then f a else failure) 0 a @@ -66,15 +74,16 @@ avoiding duplication up to equality or isomorphism, use Brendan McKay's method of "generation by canonical construction path". -/ -- TODO can you make this work in `List` and `MLList m` simultaneously, by being tricky with monads? +@[deprecated "See deprecation note in module documentation." (since := "2024-08-22")] def depthFirstRemovingDuplicates {α : Type u} [BEq α] [Hashable α] (f : α → MLList m α) (a : α) (maxDepth : Option Nat := none) : MLList m α := -let f' : α → MLList (StateT.{u} (HashSet α) m) α := fun a => +let f' : α → MLList (StateT.{u} (Std.HashSet α) m) α := fun a => (f a).liftM >>= fun b => do let s ← get if s.contains b then failure set <| s.insert b pure b -(depthFirst f' a maxDepth).runState' (HashSet.empty.insert a) +(depthFirst f' a maxDepth).runState' (Std.HashSet.empty.insert a) /-- Variant of `depthFirst`, @@ -82,6 +91,7 @@ using an internal `HashSet` to record and avoid already visited nodes. This version describes the graph using `α → List α`, and returns the list of nodes visited in order. -/ +@[deprecated "See deprecation note in module documentation." (since := "2024-08-22")] def depthFirstRemovingDuplicates' [BEq α] [Hashable α] (f : α → List α) (a : α) (maxDepth : Option Nat := none) : List α := depthFirstRemovingDuplicates diff --git a/Mathlib/Data/MLList/IO.lean b/Mathlib/Data/MLList/IO.lean index 8f0a5da58d9d2..3887b991697a4 100644 --- a/Mathlib/Data/MLList/IO.lean +++ b/Mathlib/Data/MLList/IO.lean @@ -8,13 +8,19 @@ import Batteries.Data.MLList.Basic /-! # Reading from handles, files, and processes as lazy lists. + +## Deprecation + +This material has been moved out of Mathlib to https://github.com/semorrison/lean-monadic-list. -/ open System IO.FS +set_option linter.deprecated false namespace MLList /-- Read lines of text from a handle, as a lazy list in `IO`. -/ +@[deprecated "See deprecation note in module documentation." (since := "2024-08-22")] def linesFromHandle (h : Handle) : MLList IO String := MLList.iterate (do let line ← h.getLine @@ -31,6 +37,7 @@ def linesFromHandle (h : Handle) : MLList IO String := |>.takeWhile (·.isSome) |>.map (fun o => o.getD "") /-- Read lines of text from a file, as a lazy list in `IO`. -/ +@[deprecated "See deprecation note in module documentation." (since := "2024-08-22")] def lines (f : FilePath) : MLList IO String := .squash fun _ => do return linesFromHandle (← Handle.mk f Mode.read) @@ -39,6 +46,7 @@ open IO.Process in Run a command with given input on `stdio`, returning `stdout` as a lazy list in `IO`. -/ +@[deprecated "See deprecation note in module documentation." (since := "2024-08-22")] def runCmd (cmd : String) (args : Array String) (input : String := "") : MLList IO String := do let child ← spawn { cmd := cmd, args := args, stdin := .piped, stdout := .piped, stderr := .piped } diff --git a/Mathlib/Data/MLList/Split.lean b/Mathlib/Data/MLList/Split.lean index 1aaf2fbbd9927..4a29154f9b6d2 100644 --- a/Mathlib/Data/MLList/Split.lean +++ b/Mathlib/Data/MLList/Split.lean @@ -8,8 +8,14 @@ import Mathlib.Data.ULift /-! # Functions for splitting monadic lazy lists. + +## Deprecation + +This material has been moved out of Mathlib to https://github.com/semorrison/lean-monadic-list. -/ +set_option linter.deprecated false + namespace MLList universe u @@ -20,6 +26,7 @@ Extract the prefix of a lazy list consisting of elements up to and including the first element satisfying a monadic predicate. Return (in the monad) the prefix as a `List`, along with the remaining elements as a `MLList`. -/ +@[deprecated "See deprecation note in module documentation." (since := "2024-08-22")] partial def getUpToFirstM (L : MLList m α) (p : α → m (ULift Bool)) : m (List α × MLList m α) := do match ← L.uncons with | none => return ([], nil) @@ -34,6 +41,7 @@ Extract the prefix of a lazy list consisting of elements up to and including the first element satisfying a predicate. Return (in the monad) the prefix as a `List`, along with the remaining elements as a `MLList`. -/ +@[deprecated "See deprecation note in module documentation." (since := "2024-08-22")] def getUpToFirst (L : MLList m α) (p : α → Bool) : m (List α × MLList m α) := L.getUpToFirstM fun a => pure (.up (p a)) @@ -45,6 +53,7 @@ Return (in the monad) the prefix as a `List`, along with the remaining elements (Note that the first element *not* satisfying the predicate will be generated, and pushed back on to the remaining lazy list.) -/ +@[deprecated "See deprecation note in module documentation." (since := "2024-08-22")] partial def splitWhileM (L : MLList m α) (p : α → m (ULift Bool)) : m (List α × MLList m α) := do match ← L.uncons with @@ -63,6 +72,7 @@ Return (in the monad) the prefix as a `List`, along with the remaining elements (Note that the first element *not* satisfying the predicate will be generated, and pushed back on to the remaining lazy list.) -/ +@[deprecated "See deprecation note in module documentation." (since := "2024-08-22")] def splitWhile (L : MLList m α) (p : α → Bool) : m (List α × MLList m α) := L.splitWhileM fun a => pure (.up (p a)) @@ -72,6 +82,7 @@ a monadic function. Return a lazy lists of pairs, consisting of a value under that function, and a maximal list of elements having that value. -/ +@[deprecated "See deprecation note in module documentation." (since := "2024-08-22")] partial def groupByM [DecidableEq β] (L : MLList m α) (f : α → m β) : MLList m (β × List α) := L.cases (fun _ => nil) fun a t => squash fun _ => do let b ← f a @@ -83,6 +94,7 @@ Splits a lazy list into contiguous sublists of elements with the same value unde Return a lazy lists of pairs, consisting of a value under that function, and a maximal list of elements having that value. -/ +@[deprecated "See deprecation note in module documentation." (since := "2024-08-22")] def groupBy [DecidableEq β] (L : MLList m α) (f : α → β) : MLList m (β × List α) := L.groupByM fun a => pure (f a) @@ -93,6 +105,7 @@ def groupBy [DecidableEq β] (L : MLList m α) (f : α → β) : MLList m (β × Split a lazy list into contiguous sublists, starting a new sublist each time a monadic predicate changes from `false` to `true`. -/ +@[deprecated "See deprecation note in module documentation." (since := "2024-08-22")] partial def splitAtBecomesTrueM (L : MLList m α) (p : α → m (ULift Bool)) : MLList m (List α) := aux (L.groupByM p) where aux (M : MLList m (ULift.{u} Bool × List α)) : MLList m (List α) := @@ -106,6 +119,7 @@ where aux (M : MLList m (ULift.{u} Bool × List α)) : MLList m (List α) := Split a lazy list into contiguous sublists, starting a new sublist each time a predicate changes from `false` to `true`. -/ +@[deprecated "See deprecation note in module documentation." (since := "2024-08-22")] def splitAtBecomesTrue (L : MLList m α) (p : α → Bool) : MLList m (List α) := L.splitAtBecomesTrueM fun a => pure (.up (p a)) diff --git a/Mathlib/Data/Matrix/Basic.lean b/Mathlib/Data/Matrix/Basic.lean index 3d645f33d8402..dfb96ff464262 100644 --- a/Mathlib/Data/Matrix/Basic.lean +++ b/Mathlib/Data/Matrix/Basic.lean @@ -5,6 +5,7 @@ Authors: Ellen Arlt, Blair Shi, Sean Leather, Mario Carneiro, Johan Commelin, Lu -/ import Mathlib.Algebra.Algebra.Opposite import Mathlib.Algebra.Algebra.Pi +import Mathlib.Algebra.BigOperators.GroupWithZero.Action import Mathlib.Algebra.BigOperators.Pi import Mathlib.Algebra.BigOperators.Ring import Mathlib.Algebra.BigOperators.RingEquiv @@ -13,7 +14,6 @@ import Mathlib.Algebra.Star.BigOperators import Mathlib.Algebra.Star.Module import Mathlib.Algebra.Star.Pi import Mathlib.Data.Fintype.BigOperators -import Mathlib.GroupTheory.GroupAction.BigOperators /-! # Matrices @@ -733,7 +733,7 @@ theorem dotProduct_comp_equiv_symm (e : n ≃ m) : u ⬝ᵥ x ∘ e.symm = u ∘ @[simp] theorem comp_equiv_dotProduct_comp_equiv (e : m ≃ n) : x ∘ e ⬝ᵥ y ∘ e = x ⬝ᵥ y := by -- Porting note: was `simp only` with all three lemmas - rw [← dotProduct_comp_equiv_symm]; simp only [Function.comp, Equiv.apply_symm_apply] + rw [← dotProduct_comp_equiv_symm]; simp only [Function.comp_def, Equiv.apply_symm_apply] end NonUnitalNonAssocSemiring @@ -2526,10 +2526,12 @@ theorem map_dotProduct [NonAssocSemiring R] [NonAssocSemiring S] (f : R →+* S) theorem map_vecMul [NonAssocSemiring R] [NonAssocSemiring S] (f : R →+* S) (M : Matrix n m R) (v : n → R) (i : m) : f ((v ᵥ* M) i) = ((f ∘ v) ᵥ* M.map f) i := by - simp only [Matrix.vecMul, Matrix.map_apply, RingHom.map_dotProduct, Function.comp] + simp only [Matrix.vecMul, Matrix.map_apply, RingHom.map_dotProduct, Function.comp_def] theorem map_mulVec [NonAssocSemiring R] [NonAssocSemiring S] (f : R →+* S) (M : Matrix m n R) (v : n → R) (i : m) : f ((M *ᵥ v) i) = (M.map f *ᵥ (f ∘ v)) i := by - simp only [Matrix.mulVec, Matrix.map_apply, RingHom.map_dotProduct, Function.comp] + simp only [Matrix.mulVec, Matrix.map_apply, RingHom.map_dotProduct, Function.comp_def] end RingHom + +set_option linter.style.longFile 2700 diff --git a/Mathlib/Data/Matrix/ColumnRowPartitioned.lean b/Mathlib/Data/Matrix/ColumnRowPartitioned.lean index d8f1117d5f756..6961195e3a83e 100644 --- a/Mathlib/Data/Matrix/ColumnRowPartitioned.lean +++ b/Mathlib/Data/Matrix/ColumnRowPartitioned.lean @@ -74,11 +74,11 @@ lemma toRows₂_apply (A : Matrix (m₁ ⊕ m₂) n R) (i : m₂) (j : n) : (toRows₂ A) i j = A (Sum.inr i) j := rfl @[simp] -lemma toRows₁_fromRows (A₁ : Matrix m₁ n R) (A₂ : Matrix m₂ n R) : +lemma toRows₁_fromRows (A₁ : Matrix m₁ n R) (A₂ : Matrix m₂ n R) : toRows₁ (fromRows A₁ A₂) = A₁ := rfl @[simp] -lemma toRows₂_fromRows (A₁ : Matrix m₁ n R) (A₂ : Matrix m₂ n R) : +lemma toRows₂_fromRows (A₁ : Matrix m₁ n R) (A₂ : Matrix m₂ n R) : toRows₂ (fromRows A₁ A₂) = A₂ := rfl @[simp] @@ -124,14 +124,14 @@ lemma fromRows_ext_iff (A₁ : Matrix m₁ n R) (A₂ : Matrix m₂ n R) (B₁ : (B₂ : Matrix m₂ n R) : fromRows A₁ A₂ = fromRows B₁ B₂ ↔ A₁ = B₁ ∧ A₂ = B₂ := fromRows_inj.eq_iff -/-- A column partioned matrix when transposed gives a row partioned matrix with columns of the -initial matrix tranposed to become rows. -/ +/-- A column partitioned matrix when transposed gives a row partitioned matrix with columns of the +initial matrix transposed to become rows. -/ lemma transpose_fromColumns (A₁ : Matrix m n₁ R) (A₂ : Matrix m n₂ R) : transpose (fromColumns A₁ A₂) = fromRows (transpose A₁) (transpose A₂) := by ext (i | i) j <;> simp -/-- A row partioned matrix when transposed gives a column partioned matrix with rows of the initial -matrix tranposed to become columns. -/ +/-- A row partitioned matrix when transposed gives a column partitioned matrix with rows of the +initial matrix transposed to become columns. -/ lemma transpose_fromRows (A₁ : Matrix m₁ n R) (A₂ : Matrix m₂ n R) : transpose (fromRows A₁ A₂) = fromColumns (transpose A₁) (transpose A₂) := by ext i (j | j) <;> simp @@ -212,29 +212,31 @@ lemma fromRows_zero : fromRows (0 : Matrix m₁ n R) (0 : Matrix m₂ n R) = 0 : lemma fromColumns_zero : fromColumns (0 : Matrix m n₁ R) (0 : Matrix m n₂ R) = 0 := by ext _ (_ | _) <;> simp -/-- A row partitioned matrix multiplied by a column partioned matrix gives a 2 by 2 block matrix -/ +/-- A row partitioned matrix multiplied by a column partitioned matrix gives a 2 by 2 block +matrix. -/ lemma fromRows_mul_fromColumns [Fintype n] (A₁ : Matrix m₁ n R) (A₂ : Matrix m₂ n R) (B₁ : Matrix n n₁ R) (B₂ : Matrix n n₂ R) : (fromRows A₁ A₂) * (fromColumns B₁ B₂) = fromBlocks (A₁ * B₁) (A₁ * B₂) (A₂ * B₁) (A₂ * B₂) := by ext (_ | _) (_ | _) <;> simp -/-- A column partitioned matrix mulitplied by a row partitioned matrix gives the sum of the "outer" -products of the block matrices -/ +/-- A column partitioned matrix multiplied by a row partitioned matrix gives the sum of the "outer" +products of the block matrices. -/ lemma fromColumns_mul_fromRows [Fintype n₁] [Fintype n₂] (A₁ : Matrix m n₁ R) (A₂ : Matrix m n₂ R) (B₁ : Matrix n₁ n R) (B₂ : Matrix n₂ n R) : fromColumns A₁ A₂ * fromRows B₁ B₂ = (A₁ * B₁ + A₂ * B₂) := by ext simp [mul_apply] -/-- A column partitioned matrix multipiled by a block matrix results in a column partioned matrix -/ +/-- A column partitioned matrix multipiled by a block matrix results in a column partitioned +matrix. -/ lemma fromColumns_mul_fromBlocks [Fintype m₁] [Fintype m₂] (A₁ : Matrix m m₁ R) (A₂ : Matrix m m₂ R) (B₁₁ : Matrix m₁ n₁ R) (B₁₂ : Matrix m₁ n₂ R) (B₂₁ : Matrix m₂ n₁ R) (B₂₂ : Matrix m₂ n₂ R) : (fromColumns A₁ A₂) * fromBlocks B₁₁ B₁₂ B₂₁ B₂₂ = fromColumns (A₁ * B₁₁ + A₂ * B₂₁) (A₁ * B₁₂ + A₂ * B₂₂) := by ext _ (_ | _) <;> simp [mul_apply] -/-- A block matrix mulitplied by a row partitioned matrix gives a row partitioned matrix -/ +/-- A block matrix multiplied by a row partitioned matrix gives a row partitioned matrix. -/ lemma fromBlocks_mul_fromRows [Fintype n₁] [Fintype n₂] (A₁ : Matrix n₁ n R) (A₂ : Matrix n₂ n R) (B₁₁ : Matrix m₁ n₁ R) (B₁₂ : Matrix m₁ n₂ R) (B₂₁ : Matrix m₂ n₁ R) (B₂₂ : Matrix m₂ n₂ R) : fromBlocks B₁₁ B₁₂ B₂₁ B₂₂ * (fromRows A₁ A₂) = @@ -282,14 +284,14 @@ end CommRing section Star variable [Star R] -/-- A column partioned matrix in a Star ring when conjugate transposed gives a row partitioned +/-- A column partitioned matrix in a Star ring when conjugate transposed gives a row partitioned matrix with the columns of the initial matrix conjugate transposed to become rows. -/ lemma conjTranspose_fromColumns_eq_fromRows_conjTranspose (A₁ : Matrix m n₁ R) (A₂ : Matrix m n₂ R) : conjTranspose (fromColumns A₁ A₂) = fromRows (conjTranspose A₁) (conjTranspose A₂) := by ext (_ | _) _ <;> simp -/-- A row partioned matrix in a Star ring when conjugate transposed gives a column partitioned +/-- A row partitioned matrix in a Star ring when conjugate transposed gives a column partitioned matrix with the rows of the initial matrix conjugate transposed to become columns. -/ lemma conjTranspose_fromRows_eq_fromColumns_conjTranspose (A₁ : Matrix m₁ n R) (A₂ : Matrix m₂ n R) : conjTranspose (fromRows A₁ A₂) = diff --git a/Mathlib/Data/Matrix/Composition.lean b/Mathlib/Data/Matrix/Composition.lean index 31de61ff426dd..de52659e526d6 100644 --- a/Mathlib/Data/Matrix/Composition.lean +++ b/Mathlib/Data/Matrix/Composition.lean @@ -24,7 +24,7 @@ Semiring, and Algebra over a CommSemiring K. namespace Matrix -variable (I J K L R : Type*) +variable (I J K L R : Type*) /-- I by J matrix where each entry is a K by L matrix is equivalent to I × K by J × L matrix -/ diff --git a/Mathlib/Data/Matrix/Kronecker.lean b/Mathlib/Data/Matrix/Kronecker.lean index f2afadf172ca1..61bfd0d4ab97b 100644 --- a/Mathlib/Data/Matrix/Kronecker.lean +++ b/Mathlib/Data/Matrix/Kronecker.lean @@ -217,8 +217,8 @@ theorem det_kroneckerMapBilinear [CommSemiring R] [Fintype m] [Fintype n] [Decid det (kroneckerMapBilinear f A B) = det (kroneckerMapBilinear f A 1 * kroneckerMapBilinear f 1 B) := by rw [← kroneckerMapBilinear_mul_mul f h_comm, Matrix.mul_one, Matrix.one_mul] - _ = det (blockDiagonal fun _ => A.map fun a => f a 1) * - det (blockDiagonal fun _ => B.map fun b => f 1 b) := by + _ = det (blockDiagonal fun (_ : n) => A.map fun a => f a 1) * + det (blockDiagonal fun (_ : m) => B.map fun b => f 1 b) := by rw [det_mul, ← diagonal_one, ← diagonal_one, kroneckerMapBilinear_apply_apply, kroneckerMap_diagonal_right _ fun _ => _, kroneckerMapBilinear_apply_apply, kroneckerMap_diagonal_left _ fun _ => _, det_reindex_self] diff --git a/Mathlib/Data/Matrix/Notation.lean b/Mathlib/Data/Matrix/Notation.lean index cabbdb210c83a..34515d69bf4ca 100644 --- a/Mathlib/Data/Matrix/Notation.lean +++ b/Mathlib/Data/Matrix/Notation.lean @@ -46,8 +46,8 @@ variable {α : Type u} {o n m : ℕ} {m' : Type uₘ} {n' : Type uₙ} {o' : Typ open Matrix section toExpr -open Lean -open Qq + +open Lean Qq /-- Matrices can be reflected whenever their entries can. We insert a `Matrix.of` to prevent immediate decay to a function. -/ diff --git a/Mathlib/Data/Matroid/Basic.lean b/Mathlib/Data/Matroid/Basic.lean index 22af93d6f230f..5f098b5a7e053 100644 --- a/Mathlib/Data/Matroid/Basic.lean +++ b/Mathlib/Data/Matroid/Basic.lean @@ -169,7 +169,7 @@ def Matroid.ExchangeProperty {α : Type _} (P : Set α → Prop) : Prop := ∀ X Y, P X → P Y → ∀ a ∈ X \ Y, ∃ b ∈ Y \ X, P (insert b (X \ {a})) /-- A set `X` has the maximal subset property for a predicate `P` if every subset of `X` satisfying - `P` is contained in a maximal subset of `X` satisfying `P`. -/ + `P` is contained in a maximal subset of `X` satisfying `P`. -/ def Matroid.ExistsMaximalSubsetProperty {α : Type _} (P : Set α → Prop) (X : Set α) : Prop := ∀ I, P I → I ⊆ X → ∃ J, I ⊆ J ∧ Maximal (fun K ↦ P K ∧ K ⊆ X) J @@ -186,7 +186,7 @@ def Matroid.ExistsMaximalSubsetProperty {α : Type _} (P : Set α → Prop) (X : @[ext] structure Matroid (α : Type _) where /-- `M` has a ground set `E`. -/ (E : Set α) - /-- `M` has a predicate `Base` definining its bases. -/ + /-- `M` has a predicate `Base` defining its bases. -/ (Base : Set α → Prop) /-- `M` has a predicate `Indep` defining its independent sets. -/ (Indep : Set α → Prop) @@ -713,7 +713,7 @@ def Basis (M : Matroid α) (I X : Set α) : Prop := Maximal (fun A ↦ M.Indep A ∧ A ⊆ X) I ∧ X ⊆ M.E /-- A `Basis'` is a basis without the requirement that `X ⊆ M.E`. This is convenient for some - API building, especially when working with rank and closure. -/ + API building, especially when working with rank and closure. -/ def Basis' (M : Matroid α) (I X : Set α) : Prop := Maximal (fun A ↦ M.Indep A ∧ A ⊆ X) I diff --git a/Mathlib/Data/Matroid/Closure.lean b/Mathlib/Data/Matroid/Closure.lean index 555e6ec09d4dd..10fddef9acbd1 100644 --- a/Mathlib/Data/Matroid/Closure.lean +++ b/Mathlib/Data/Matroid/Closure.lean @@ -50,7 +50,7 @@ Its disadvantage is that the statement `X ⊆ M.closure X` is only true provided Choice (2) has the reverse property: we would have `X ⊆ M.closure X` for all `X`, but the condition `M.closure X ⊆ M.E` requires `X ⊆ M.E` to hold. -It has a couple of other advantages too: is is actually the closure function of a matroid on `α` +It has a couple of other advantages too: it is actually the closure function of a matroid on `α` with ground set `univ` (specifically, the direct sum of `M` and a free matroid on `M.Eᶜ`), and because of this, it is an example of a `ClosureOperator` on `α`, which in turn gives access to nice existing API for both `ClosureOperator` and `GaloisInsertion`. diff --git a/Mathlib/Data/Matroid/Map.lean b/Mathlib/Data/Matroid/Map.lean index b231376efdada..bf22fe80c5b92 100644 --- a/Mathlib/Data/Matroid/Map.lean +++ b/Mathlib/Data/Matroid/Map.lean @@ -501,7 +501,7 @@ end map section mapSetEquiv /-- Map `M : Matroid α` to a `Matroid β` with ground set `E` using an equivalence `M.E ≃ E`. -Defined using `Matroid.ofExistsMatroid` for better defeq. -/ +Defined using `Matroid.ofExistsMatroid` for better defeq. -/ def mapSetEquiv (M : Matroid α) {E : Set β} (e : M.E ≃ E) : Matroid β := Matroid.ofExistsMatroid E (fun I ↦ (M.Indep ↑(e.symm '' (E ↓∩ I)) ∧ I ⊆ E)) ⟨M.mapSetEmbedding (e.toEmbedding.trans <| Function.Embedding.subtype _), by diff --git a/Mathlib/Data/Matroid/Restrict.lean b/Mathlib/Data/Matroid/Restrict.lean index 46d88f70b7cf7..013d3c6c68740 100644 --- a/Mathlib/Data/Matroid/Restrict.lean +++ b/Mathlib/Data/Matroid/Restrict.lean @@ -36,7 +36,7 @@ It also proves some `Basis` analogues of `Base` lemmas that, while they could be ## Implementation Notes Since `R` and `M.E` are both terms in `Set α`, to define the restriction `M ↾ R`, -we need to either insist that `R ⊆ M.E`, or to say what happens when `R` contains the junk +we need to either insist that `R ⊆ M.E`, or to say what happens when `R` contains the junk outside `M.E`. It turns out that `R ⊆ M.E` is just an unnecessary hypothesis; if we say the restriction @@ -115,7 +115,7 @@ section restrict /-- Change the ground set of a matroid to some `R : Set α`. The independent sets of the restriction are the independent subsets of the new ground set. Most commonly used when `R ⊆ M.E`, - but it is convenient not to require this. The elements of `R \ M.E` become 'loops'. -/ + but it is convenient not to require this. The elements of `R \ M.E` become 'loops'. -/ def restrict (M : Matroid α) (R : Set α) : Matroid α := (M.restrictIndepMatroid R).matroid /-- `M ↾ R` means `M.restrict R`. -/ diff --git a/Mathlib/Data/Multiset/Basic.lean b/Mathlib/Data/Multiset/Basic.lean index 2c9d3259722e0..4c016c6338efe 100644 --- a/Mathlib/Data/Multiset/Basic.lean +++ b/Mathlib/Data/Multiset/Basic.lean @@ -7,7 +7,6 @@ import Mathlib.Algebra.Group.Nat import Mathlib.Algebra.Order.Sub.Unbundled.Basic import Mathlib.Data.List.Perm import Mathlib.Data.Set.List -import Mathlib.Init.Quot import Mathlib.Order.Hom.Basic /-! @@ -27,7 +26,7 @@ open List Subtype Nat Function variable {α : Type*} {β : Type v} {γ : Type*} /-- `Multiset α` is the quotient of `List α` by list permutation. The result - is a type of finite sets with duplicates allowed. -/ + is a type of finite sets with duplicates allowed. -/ def Multiset.{u} (α : Type u) : Type u := Quotient (List.isSetoid α) @@ -113,7 +112,7 @@ theorem coe_eq_zero (l : List α) : (l : Multiset α) = 0 ↔ l = [] := Iff.trans coe_eq_coe perm_nil theorem coe_eq_zero_iff_isEmpty (l : List α) : (l : Multiset α) = 0 ↔ l.isEmpty := - Iff.trans (coe_eq_zero l) isEmpty_iff_eq_nil.symm + Iff.trans (coe_eq_zero l) isEmpty_iff.symm /-! ### `Multiset.cons` -/ @@ -149,7 +148,7 @@ theorem cons_inj_right (a : α) : ∀ {s t : Multiset α}, a ::ₘ s = a ::ₘ t @[elab_as_elim] protected theorem induction {p : Multiset α → Prop} (empty : p 0) (cons : ∀ (a : α) (s : Multiset α), p s → p (a ::ₘ s)) : ∀ s, p s := by - rintro ⟨l⟩; induction' l with _ _ ih <;> [exact empty; exact cons _ _ ih] + rintro ⟨l⟩; induction l with | nil => exact empty | cons _ _ ih => exact cons _ _ ih @[elab_as_elim] protected theorem induction_on {p : Multiset α → Prop} (s : Multiset α) (empty : p 0) @@ -204,7 +203,7 @@ end Rec section Mem /-- `a ∈ s` means that `a` has nonzero multiplicity in `s`. -/ -def Mem (a : α) (s : Multiset α) : Prop := +def Mem (s : Multiset α) (a : α) : Prop := Quot.liftOn s (fun l => a ∈ l) fun l₁ l₂ (e : l₁ ~ l₂) => propext <| e.mem_iff instance : Membership α (Multiset α) := @@ -215,7 +214,7 @@ theorem mem_coe {a : α} {l : List α} : a ∈ (l : Multiset α) ↔ a ∈ l := Iff.rfl instance decidableMem [DecidableEq α] (a : α) (s : Multiset α) : Decidable (a ∈ s) := - Quot.recOnSubsingleton' s fun l ↦ inferInstanceAs (Decidable (a ∈ l)) + Quot.recOnSubsingleton s fun l ↦ inferInstanceAs (Decidable (a ∈ l)) @[simp] theorem mem_cons {a b : α} {s : Multiset α} : a ∈ b ::ₘ s ↔ a = b ∨ a ∈ s := @@ -1283,7 +1282,7 @@ theorem foldl_induction (f : α → α → α) (H : RightCommutative f) (x : α) /-- Lift of the list `pmap` operation. Map a partial function `f` over a multiset `s` whose elements are all in the domain of `f`. -/ nonrec def pmap {p : α → Prop} (f : ∀ a, p a → β) (s : Multiset α) : (∀ a ∈ s, p a) → Multiset β := - Quot.recOn' s (fun l H => ↑(pmap f l H)) fun l₁ l₂ (pp : l₁ ~ l₂) => + Quot.recOn s (fun l H => ↑(pmap f l H)) fun l₁ l₂ (pp : l₁ ~ l₂) => funext fun H₂ : ∀ a ∈ l₂, p a => have H₁ : ∀ a ∈ l₁, p a := fun a h => H₂ a (pp.subset h) have : ∀ {s₂ e H}, @Eq.ndrec (Multiset α) l₁ (fun s => (∀ a ∈ s, p a) → Multiset β) @@ -1740,13 +1739,12 @@ theorem mem_filter_of_mem {a : α} {l} (m : a ∈ l) (h : p a) : a ∈ filter p theorem filter_eq_self {s} : filter p s = s ↔ ∀ a ∈ s, p a := Quot.inductionOn s fun _l => - Iff.trans ⟨fun h => (filter_sublist _).eq_of_length (@congr_arg _ _ _ _ card h), + Iff.trans ⟨fun h => (filter_sublist _).eq_of_length (congr_arg card h), congr_arg ofList⟩ <| by simp theorem filter_eq_nil {s} : filter p s = 0 ↔ ∀ a ∈ s, ¬p a := Quot.inductionOn s fun _l => - Iff.trans ⟨fun h => eq_nil_of_length_eq_zero (@congr_arg _ _ _ _ card h), congr_arg ofList⟩ <| - by simpa using List.filter_eq_nil (p := (p ·)) + Iff.trans ⟨fun h => eq_nil_of_length_eq_zero (congr_arg card h), congr_arg ofList⟩ (by simp) theorem le_filter {s t} : s ≤ filter p t ↔ s ≤ t ∧ ∀ a ∈ s, p a := ⟨fun h => ⟨le_trans h (filter_le _ _), fun _a m => of_mem_filter (mem_of_le h m)⟩, fun ⟨h, al⟩ => @@ -1835,7 +1833,7 @@ theorem filter_map (f : β → α) (s : Multiset β) : filter p (map f s) = map lemma map_filter' {f : α → β} (hf : Injective f) (s : Multiset α) [DecidablePred fun b => ∃ a, p a ∧ f a = b] : (s.filter p).map f = (s.map f).filter fun b => ∃ a, p a ∧ f a = b := by - simp [(· ∘ ·), filter_map, hf.eq_iff] + simp [comp_def, filter_map, hf.eq_iff] lemma card_filter_le_iff (s : Multiset α) (P : α → Prop) [DecidablePred P] (n : ℕ) : card (s.filter P) ≤ n ↔ ∀ s' ≤ s, n < card s' → ∃ a ∈ s', ¬ P a := by @@ -2718,13 +2716,12 @@ end Choose variable (α) -set_option linter.deprecated false in /-- The equivalence between lists and multisets of a subsingleton type. -/ def subsingletonEquiv [Subsingleton α] : List α ≃ Multiset α where toFun := ofList invFun := (Quot.lift id) fun (a b : List α) (h : a ~ b) => - (List.ext_nthLe h.length_eq) fun _ _ _ => Subsingleton.elim _ _ + (List.ext_get h.length_eq) fun _ _ _ => Subsingleton.elim _ _ left_inv _ := rfl right_inv m := Quot.inductionOn m fun _ => rfl @@ -2739,3 +2736,5 @@ theorem coe_subsingletonEquiv [Subsingleton α] : @[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/Functor.lean b/Mathlib/Data/Multiset/Functor.lean index 05b29adb37aa7..9c8f9ecbfb459 100644 --- a/Mathlib/Data/Multiset/Functor.lean +++ b/Mathlib/Data/Multiset/Functor.lean @@ -55,7 +55,7 @@ def traverse : Multiset α' → F (Multiset β') := by congr funext a b l simpa [flip] using Perm.swap a b l - simp [(· ∘ ·), this, functor_norm, Coe.coe] + simp [Function.comp_def, this, functor_norm, Coe.coe] | trans => simp [*] instance : Monad Multiset := @@ -99,7 +99,7 @@ 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, lift_coe] + simp only [Function.comp_def, lift_coe] theorem map_traverse {G : Type* → Type _} [Applicative G] [CommApplicative G] {α β γ : Type _} (g : α → G β) (h : β → γ) (x : Multiset α) : diff --git a/Mathlib/Data/Multiset/Lattice.lean b/Mathlib/Data/Multiset/Lattice.lean index ebc72e3ce307b..194cae4b5a776 100644 --- a/Mathlib/Data/Multiset/Lattice.lean +++ b/Mathlib/Data/Multiset/Lattice.lean @@ -79,9 +79,9 @@ theorem nodup_sup_iff {α : Type*} [DecidableEq α] {m : Multiset (Multiset α)} m.sup.Nodup ↔ ∀ a : Multiset α, a ∈ m → a.Nodup := by -- Porting note: this was originally `apply m.induction_on`, which failed due to -- `failed to elaborate eliminator, expected type is not available` - induction' m using Multiset.induction_on with _ _ h - · simp - · simp [h] + induction m using Multiset.induction_on with + | empty => simp + | cons _ _ h => simp [h] end Sup diff --git a/Mathlib/Data/Multiset/Powerset.lean b/Mathlib/Data/Multiset/Powerset.lean index e344eddc1b02f..924f768a2ffbb 100644 --- a/Mathlib/Data/Multiset/Powerset.lean +++ b/Mathlib/Data/Multiset/Powerset.lean @@ -50,16 +50,18 @@ theorem powersetAux'_cons (a : α) (l : List α) : simp [powersetAux'] theorem powerset_aux'_perm {l₁ l₂ : List α} (p : l₁ ~ l₂) : powersetAux' l₁ ~ powersetAux' l₂ := by - induction' p with a l₁ l₂ p IH a b l l₁ l₂ l₃ _ _ IH₁ IH₂ - · simp - · simp only [powersetAux'_cons] + induction p with + | nil => simp + | cons _ _ IH => + simp only [powersetAux'_cons] exact IH.append (IH.map _) - · simp only [powersetAux'_cons, map_append, List.map_map, append_assoc] + | swap a b => + simp only [powersetAux'_cons, map_append, List.map_map, append_assoc] apply Perm.append_left rw [← append_assoc, ← append_assoc, (by funext s; simp [cons_swap] : cons b ∘ cons a = cons a ∘ cons b)] exact perm_append_comm.append_right _ - · exact IH₁.trans IH₂ + | trans _ _ IH₁ IH₂ => exact IH₁.trans IH₂ theorem powersetAux_perm {l₁ l₂ : List α} (p : l₁ ~ l₂) : powersetAux l₁ ~ powersetAux l₂ := powersetAux_perm_powersetAux'.trans <| @@ -179,11 +181,13 @@ theorem powersetCardAux_perm {n} {l₁ l₂ : List α} (p : l₁ ~ l₂) : powersetCardAux n l₁ ~ powersetCardAux n l₂ := by induction' n with n IHn generalizing l₁ l₂ · simp - induction' p with a l₁ l₂ p IH a b l l₁ l₂ l₃ _ _ IH₁ IH₂ - · rfl - · simp only [powersetCardAux_cons] + induction p with + | nil => rfl + | cons _ p IH => + simp only [powersetCardAux_cons] exact IH.append ((IHn p).map _) - · simp only [powersetCardAux_cons, append_assoc] + | swap a b => + simp only [powersetCardAux_cons, append_assoc] apply Perm.append_left cases n · simp [Perm.swap] @@ -191,7 +195,7 @@ theorem powersetCardAux_perm {n} {l₁ l₂ : List α} (p : l₁ ~ l₂) : rw [← append_assoc, ← append_assoc, (by funext s; simp [cons_swap] : cons b ∘ cons a = cons a ∘ cons b)] exact perm_append_comm.append_right _ - · exact IH₁.trans IH₂ + | trans _ _ IH₁ IH₂ => exact IH₁.trans IH₂ /-- `powersetCard n s` is the multiset of all submultisets of `s` of length `n`. -/ def powersetCard (n : ℕ) (s : Multiset α) : Multiset (Multiset α) := @@ -219,7 +223,7 @@ theorem powersetCard_cons (n : ℕ) (a : α) (s) : theorem powersetCard_one (s : Multiset α) : powersetCard 1 s = s.map singleton := Quotient.inductionOn s fun l ↦ by - simp [powersetCard_coe, sublistsLen_one, map_reverse, Function.comp] + simp [powersetCard_coe, sublistsLen_one, map_reverse, Function.comp_def] @[simp] theorem mem_powersetCard {n : ℕ} {s t : Multiset α} : s ∈ powersetCard n t ↔ s ≤ t ∧ card s = n := diff --git a/Mathlib/Data/Multiset/Sections.lean b/Mathlib/Data/Multiset/Sections.lean index 8a09ff3a33675..4cc916de7c550 100644 --- a/Mathlib/Data/Multiset/Sections.lean +++ b/Mathlib/Data/Multiset/Sections.lean @@ -42,7 +42,7 @@ theorem coe_sections : | a :: l => by simp only [List.map_cons, List.sections] rw [← cons_coe, sections_cons, bind_map_comm, coe_sections l] - simp [List.sections, (· ∘ ·), List.bind] + simp [List.sections, Function.comp_def, List.bind] @[simp] theorem sections_add (s t : Multiset (Multiset α)) : diff --git a/Mathlib/Data/Multiset/Sort.lean b/Mathlib/Data/Multiset/Sort.lean index c3a6dabdb273b..545d09d151580 100644 --- a/Mathlib/Data/Multiset/Sort.lean +++ b/Mathlib/Data/Multiset/Sort.lean @@ -15,45 +15,52 @@ namespace Multiset open List -variable {α : Type*} +variable {α β : Type*} section sort variable (r : α → α → Prop) [DecidableRel r] [IsTrans α r] [IsAntisymm α r] [IsTotal α r] +variable (r' : β → β → Prop) [DecidableRel r'] [IsTrans β r'] [IsAntisymm β r'] [IsTotal β r'] /-- `sort s` constructs a sorted list from the multiset `s`. (Uses merge sort algorithm.) -/ def sort (s : Multiset α) : List α := - Quot.liftOn s (mergeSort r) fun _ _ h => - eq_of_perm_of_sorted ((perm_mergeSort _ _).trans <| h.trans (perm_mergeSort _ _).symm) - (sorted_mergeSort r _) (sorted_mergeSort r _) + Quot.liftOn s (mergeSort' r) fun _ _ h => + eq_of_perm_of_sorted ((perm_mergeSort' _ _).trans <| h.trans (perm_mergeSort' _ _).symm) + (sorted_mergeSort' r _) (sorted_mergeSort' r _) @[simp] -theorem coe_sort (l : List α) : sort r l = mergeSort r l := +theorem coe_sort (l : List α) : sort r l = mergeSort' r l := rfl @[simp] theorem sort_sorted (s : Multiset α) : Sorted r (sort r s) := - Quot.inductionOn s fun _l => sorted_mergeSort r _ + Quot.inductionOn s fun _l => sorted_mergeSort' r _ @[simp] theorem sort_eq (s : Multiset α) : ↑(sort r s) = s := - Quot.inductionOn s fun _ => Quot.sound <| perm_mergeSort _ _ + Quot.inductionOn s fun _ => Quot.sound <| perm_mergeSort' _ _ @[simp] theorem mem_sort {s : Multiset α} {a : α} : a ∈ sort r s ↔ a ∈ s := by rw [← mem_coe, sort_eq] @[simp] theorem length_sort {s : Multiset α} : (sort r s).length = card s := - Quot.inductionOn s <| length_mergeSort _ + Quot.inductionOn s <| length_mergeSort' _ @[simp] theorem sort_zero : sort r 0 = [] := - List.mergeSort_nil r + List.mergeSort'_nil r @[simp] theorem sort_singleton (a : α) : sort r {a} = [a] := - List.mergeSort_singleton r a + List.mergeSort'_singleton r a + +theorem map_sort (f : α → β) (s : Multiset α) + (hs : ∀ a ∈ s, ∀ b ∈ s, r a b ↔ r' (f a) (f b)) : + (s.sort r).map f = (s.map f).sort r' := by + revert s + exact Quot.ind fun _ => List.map_mergeSort' _ _ _ _ end sort diff --git a/Mathlib/Data/NNRat/Defs.lean b/Mathlib/Data/NNRat/Defs.lean index 48552f3ade343..e41ecbe750139 100644 --- a/Mathlib/Data/NNRat/Defs.lean +++ b/Mathlib/Data/NNRat/Defs.lean @@ -3,11 +3,10 @@ Copyright (c) 2022 Yaël Dillies, Bhavik Mehta. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies, Bhavik Mehta -/ -import Mathlib.Algebra.Order.Nonneg.Ring import Mathlib.Algebra.Order.Group.Unbundled.Int -import Mathlib.Algebra.Order.Ring.Rat +import Mathlib.Algebra.Order.Ring.Unbundled.Nonneg import Mathlib.Algebra.Order.Ring.Unbundled.Rat -import Mathlib.Data.Nat.Cast.Order.Ring +import Mathlib.Algebra.Ring.Rat /-! # Nonnegative rationals @@ -32,6 +31,8 @@ Whenever you state a lemma about the coercion `ℚ≥0 → ℚ`, check that Lean `Subtype.val`. Else your lemma will never apply. -/ +assert_not_exists OrderedCommMonoid + library_note "specialised high priority simp lemma" /-- It sometimes happens that a `@[simp]` lemma declared early in the library can be proved by `simp` using later, more general simp lemmas. In that case, the following reasons might be arguments for @@ -45,14 +46,19 @@ un``@[simp]``ed): open Function -deriving instance CanonicallyOrderedCommSemiring for NNRat -deriving instance CanonicallyLinearOrderedAddCommMonoid for NNRat +instance Rat.instZeroLEOneClass : ZeroLEOneClass ℚ where + zero_le_one := rfl + +instance Rat.instPosMulMono : PosMulMono ℚ where + elim := fun r p q h => by + simp only [mul_comm] + simpa [sub_mul, sub_nonneg] using Rat.mul_nonneg (sub_nonneg.2 h) r.2 + +deriving instance CommSemiring for NNRat +deriving instance LinearOrder for NNRat deriving instance Sub for NNRat deriving instance Inhabited for NNRat --- TODO: `deriving instance OrderedSub for NNRat` doesn't work yet, so we add the instance manually -instance NNRat.instOrderedSub : OrderedSub ℚ≥0 := Nonneg.orderedSub - namespace NNRat variable {α : Type*} {p q : ℚ≥0} @@ -155,7 +161,7 @@ theorem toNNRat_coe (q : ℚ≥0) : toNNRat q = q := @[simp] theorem toNNRat_coe_nat (n : ℕ) : toNNRat n = n := - ext <| by simp only [Nat.cast_nonneg, Rat.coe_toNNRat]; rfl + ext <| by simp only [Nat.cast_nonneg', Rat.coe_toNNRat]; rfl /-- `toNNRat` and `(↑) : ℚ≥0 → ℚ` form a Galois insertion. -/ protected def gi : GaloisInsertion toNNRat (↑) := @@ -173,7 +179,7 @@ def coeHom : ℚ≥0 →+* ℚ where -- See note [no_index around OfNat.ofNat] @[simp] -theorem mk_natCast (n : ℕ) : @Eq ℚ≥0 (⟨(n : ℚ), n.cast_nonneg⟩ : ℚ≥0) n := +theorem mk_natCast (n : ℕ) : @Eq ℚ≥0 (⟨(n : ℚ), Nat.cast_nonneg' n⟩ : ℚ≥0) n := rfl @[deprecated (since := "2024-04-05")] alias mk_coe_nat := mk_natCast @@ -212,6 +218,11 @@ theorem sub_def (p q : ℚ≥0) : p - q = toNNRat (p - q) := theorem abs_coe (q : ℚ≥0) : |(q : ℚ)| = q := abs_of_nonneg q.2 +-- See note [specialised high priority simp lemma] +@[simp high] +theorem nonpos_iff_eq_zero (q : ℚ≥0) : q ≤ 0 ↔ q = 0 := + ⟨fun h => le_antisymm h q.2, fun h => h.symm ▸ q.2⟩ + end NNRat open NNRat @@ -305,7 +316,8 @@ theorem natAbs_num_coe : (q : ℚ).num.natAbs = q.num := rfl @[norm_cast] lemma den_coe : (q : ℚ).den = q.den := rfl @[simp] lemma num_ne_zero : q.num ≠ 0 ↔ q ≠ 0 := by simp [num] -@[simp] lemma num_pos : 0 < q.num ↔ 0 < q := by simp [pos_iff_ne_zero] +@[simp] lemma num_pos : 0 < q.num ↔ 0 < q := by + simpa [num, -nonpos_iff_eq_zero] using nonpos_iff_eq_zero _ |>.not.symm @[simp] lemma den_pos (q : ℚ≥0) : 0 < q.den := Rat.den_pos _ @[simp] lemma den_ne_zero (q : ℚ≥0) : q.den ≠ 0 := Rat.den_ne_zero _ diff --git a/Mathlib/Data/NNRat/Lemmas.lean b/Mathlib/Data/NNRat/Lemmas.lean index fcd82064c57c7..4e1ee467939eb 100644 --- a/Mathlib/Data/NNRat/Lemmas.lean +++ b/Mathlib/Data/NNRat/Lemmas.lean @@ -43,7 +43,7 @@ variable {p q : ℚ} lemma toNNRat_inv (q : ℚ) : toNNRat q⁻¹ = (toNNRat q)⁻¹ := by obtain hq | hq := le_total q 0 - · rw [toNNRat_eq_zero.mpr hq, inv_zero, toNNRat_eq_zero.mpr (inv_nonpos (α := ℚ) |>.mpr hq)] + · rw [toNNRat_eq_zero.mpr hq, inv_zero, toNNRat_eq_zero.mpr (inv_nonpos.mpr hq)] · nth_rw 1 [← Rat.coe_toNNRat q hq] rw [← coe_inv, toNNRat_coe] @@ -51,7 +51,7 @@ lemma toNNRat_div (hp : 0 ≤ p) : toNNRat (p / q) = toNNRat p / toNNRat q := by rw [div_eq_mul_inv, div_eq_mul_inv, ← toNNRat_inv, ← toNNRat_mul hp] lemma toNNRat_div' (hq : 0 ≤ q) : toNNRat (p / q) = toNNRat p / toNNRat q := by - rw [div_eq_inv_mul, div_eq_inv_mul, toNNRat_mul (inv_nonneg (α := ℚ) |>.2 hq), toNNRat_inv] + rw [div_eq_inv_mul, div_eq_inv_mul, toNNRat_mul (inv_nonneg.2 hq), toNNRat_inv] end Rat diff --git a/Mathlib/Data/NNRat/Order.lean b/Mathlib/Data/NNRat/Order.lean new file mode 100644 index 0000000000000..4b09aedfa4560 --- /dev/null +++ b/Mathlib/Data/NNRat/Order.lean @@ -0,0 +1,19 @@ +/- +Copyright (c) 2022 Yaël Dillies, Bhavik Mehta. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yaël Dillies, Bhavik Mehta +-/ +import Mathlib.Data.NNRat.Defs +import Mathlib.Algebra.Order.Ring.Rat +import Mathlib.Algebra.Order.Nonneg.Ring + +/-! +# Bundled ordered algebra structures on `ℚ≥0` + +-/ + +deriving instance CanonicallyOrderedCommSemiring for NNRat +deriving instance CanonicallyLinearOrderedAddCommMonoid for NNRat + +-- TODO: `deriving instance OrderedSub for NNRat` doesn't work yet, so we add the instance manually +instance NNRat.instOrderedSub : OrderedSub ℚ≥0 := Nonneg.orderedSub diff --git a/Mathlib/Data/NNReal/Basic.lean b/Mathlib/Data/NNReal/Basic.lean index 86a021f070b0d..c3165b2271890 100644 --- a/Mathlib/Data/NNReal/Basic.lean +++ b/Mathlib/Data/NNReal/Basic.lean @@ -70,7 +70,8 @@ scoped notation "ℝ≥0" => NNReal noncomputable instance : FloorSemiring ℝ≥0 := Nonneg.floorSemiring instance instDenselyOrdered : DenselyOrdered ℝ≥0 := Nonneg.instDenselyOrdered instance : OrderBot ℝ≥0 := inferInstance -instance : Archimedean ℝ≥0 := Nonneg.archimedean +instance : Archimedean ℝ≥0 := Nonneg.instArchimedean +instance : MulArchimedean ℝ≥0 := Nonneg.instMulArchimedean noncomputable instance : Sub ℝ≥0 := Nonneg.sub noncomputable instance : OrderedSub ℝ≥0 := Nonneg.orderedSub @@ -94,7 +95,7 @@ instance canLift : CanLift ℝ ℝ≥0 toReal fun r => 0 ≤ r := Subtype.eq theorem ne_iff {x y : ℝ≥0} : (x : ℝ) ≠ (y : ℝ) ↔ x ≠ y := - NNReal.eq_iff.symm.not + not_congr <| NNReal.eq_iff.symm protected theorem «forall» {p : ℝ≥0 → Prop} : (∀ x : ℝ≥0, p x) ↔ ∀ (x : ℝ) (hx : 0 ≤ x), p ⟨x, hx⟩ := @@ -154,6 +155,9 @@ protected theorem coe_injective : Injective ((↑) : ℝ≥0 → ℝ) := Subtype @[simp, norm_cast] lemma coe_one : ((1 : ℝ≥0) : ℝ) = 1 := rfl +@[simp] lemma mk_zero : (⟨0, le_rfl⟩ : ℝ≥0) = 0 := rfl +@[simp] lemma mk_one : (⟨1, zero_le_one⟩ : ℝ≥0) = 1 := rfl + @[simp, norm_cast] protected theorem coe_add (r₁ r₂ : ℝ≥0) : ((r₁ + r₂ : ℝ≥0) : ℝ) = r₁ + r₂ := rfl @@ -274,7 +278,7 @@ 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 -@[norm_cast] +@[simp, norm_cast] theorem coe_sum {α} {s : Finset α} {f : α → ℝ≥0} : ↑(∑ a ∈ s, f a) = ∑ a ∈ s, (f a : ℝ) := map_sum toRealHom _ _ @@ -284,7 +288,7 @@ theorem _root_.Real.toNNReal_sum_of_nonneg {α} {s : Finset α} {f : α → ℝ} 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)] -@[norm_cast] +@[simp, norm_cast] theorem coe_prod {α} {s : Finset α} {f : α → ℝ≥0} : ↑(∏ a ∈ s, f a) = ∏ a ∈ s, (f a : ℝ) := map_prod toRealHom _ _ @@ -294,8 +298,8 @@ theorem _root_.Real.toNNReal_prod_of_nonneg {α} {s : Finset α} {f : α → ℝ 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)] --- Porting note (#11215): TODO: `simp`? `norm_cast`? -theorem coe_nsmul (r : ℝ≥0) (n : ℕ) : ↑(n • r) = n • (r : ℝ) := rfl +@[simp, norm_cast] lemma coe_nsmul (r : ℝ≥0) (n : ℕ) : ↑(n • r) = n • (r : ℝ) := rfl +@[simp, norm_cast] lemma coe_nnqsmul (q : ℚ≥0) (x : ℝ≥0) : ↑(q • x) = (q • x : ℝ) := rfl @[simp, norm_cast] protected theorem coe_natCast (n : ℕ) : (↑(↑n : ℝ≥0) : ℝ) = n := @@ -428,7 +432,7 @@ theorem orderIsoIccZeroCoe_symm_apply_coe (a : ℝ≥0) (b : Set.Iic a) : -- note we need the `@` to make the `Membership.mem` have a sensible type theorem coe_image {s : Set ℝ≥0} : - (↑) '' s = { x : ℝ | ∃ h : 0 ≤ x, @Membership.mem ℝ≥0 _ _ ⟨x, h⟩ s } := + (↑) '' s = { x : ℝ | ∃ h : 0 ≤ x, @Membership.mem ℝ≥0 _ _ s ⟨x, h⟩ } := Subtype.coe_image theorem bddAbove_coe {s : Set ℝ≥0} : BddAbove (((↑) : ℝ≥0 → ℝ) '' s) ↔ BddAbove s := @@ -811,42 +815,46 @@ theorem le_inv_iff_mul_le {r p : ℝ≥0} (h : p ≠ 0) : r ≤ p⁻¹ ↔ r * p theorem lt_inv_iff_mul_lt {r p : ℝ≥0} (h : p ≠ 0) : r < p⁻¹ ↔ r * p < 1 := by rw [← mul_lt_mul_left (pos_iff_ne_zero.2 h), mul_inv_cancel₀ h, mul_comm] -theorem mul_le_iff_le_inv {a b r : ℝ≥0} (hr : r ≠ 0) : r * a ≤ b ↔ a ≤ r⁻¹ * b := by - have : 0 < r := lt_of_le_of_ne (zero_le r) hr.symm - rw [← mul_le_mul_left (inv_pos.mpr this), ← mul_assoc, inv_mul_cancel₀ hr, one_mul] +@[deprecated le_inv_mul_iff₀ (since := "2024-08-21")] +theorem mul_le_iff_le_inv {a b r : ℝ≥0} (hr : r ≠ 0) : r * a ≤ b ↔ a ≤ r⁻¹ * b := + (le_inv_mul_iff₀ (pos_iff_ne_zero.2 hr)).symm +@[deprecated le_div_iff₀ (since := "2024-08-21")] theorem le_div_iff_mul_le {a b r : ℝ≥0} (hr : r ≠ 0) : a ≤ b / r ↔ a * r ≤ b := - le_div_iff₀ hr + le_div_iff₀ (pos_iff_ne_zero.2 hr) -theorem div_le_iff {a b r : ℝ≥0} (hr : r ≠ 0) : a / r ≤ b ↔ a ≤ b * r := - div_le_iff₀ hr +@[deprecated div_le_iff₀ (since := "2024-08-21")] +protected lemma div_le_iff {a b r : ℝ≥0} (hr : r ≠ 0) : a / r ≤ b ↔ a ≤ b * r := + div_le_iff₀ (pos_iff_ne_zero.2 hr) -nonrec theorem div_le_iff' {a b r : ℝ≥0} (hr : r ≠ 0) : a / r ≤ b ↔ a ≤ r * b := - @div_le_iff' ℝ _ a r b <| pos_iff_ne_zero.2 hr +@[deprecated div_le_iff₀' (since := "2024-08-21")] +protected lemma div_le_iff' {a b r : ℝ≥0} (hr : r ≠ 0) : a / r ≤ b ↔ a ≤ r * b := + div_le_iff₀' (pos_iff_ne_zero.2 hr) theorem div_le_of_le_mul {a b c : ℝ≥0} (h : a ≤ b * c) : a / c ≤ b := - if h0 : c = 0 then by simp [h0] else (div_le_iff h0).2 h + if h0 : c = 0 then by simp [h0] else (div_le_iff₀ (pos_iff_ne_zero.2 h0)).2 h theorem div_le_of_le_mul' {a b c : ℝ≥0} (h : a ≤ b * c) : a / b ≤ c := div_le_of_le_mul <| mul_comm b c ▸ h -nonrec theorem le_div_iff {a b r : ℝ≥0} (hr : r ≠ 0) : a ≤ b / r ↔ a * r ≤ b := - @le_div_iff ℝ _ a b r <| pos_iff_ne_zero.2 hr +@[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 nonrec theorem le_div_iff' {a b r : ℝ≥0} (hr : r ≠ 0) : a ≤ b / r ↔ r * a ≤ b := - @le_div_iff' ℝ _ a b r <| pos_iff_ne_zero.2 hr + le_div_iff₀' <| pos_iff_ne_zero.2 hr 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 hr) + lt_iff_lt_of_le_iff_le (le_div_iff₀ (pos_iff_ne_zero.2 hr)) 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' hr) + lt_iff_lt_of_le_iff_le (le_div_iff₀' (pos_iff_ne_zero.2 hr)) 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 hr) + lt_iff_lt_of_le_iff_le (div_le_iff₀ (pos_iff_ne_zero.2 hr)) 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' hr) + lt_iff_lt_of_le_iff_le (div_le_iff₀' (pos_iff_ne_zero.2 hr)) 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 @@ -928,6 +936,11 @@ theorem iSup_empty [IsEmpty ι] (f : ι → ℝ≥0) : ⨆ i, f i = 0 := ciSup_o theorem iInf_empty [IsEmpty ι] (f : ι → ℝ≥0) : ⨅ i, f i = 0 := by rw [_root_.iInf_of_isEmpty, sInf_empty] +@[simp] lemma iSup_eq_zero (hf : BddAbove (range f)) : ⨆ i, f i = 0 ↔ ∀ i, f i = 0 := by + cases isEmpty_or_nonempty ι + · simp + · simp [← bot_eq_zero', ← le_bot_iff, ciSup_le_iff hf] + @[simp] theorem iInf_const_zero {α : Sort*} : ⨅ _ : α, (0 : ℝ≥0) = 0 := by rw [← coe_inj, coe_iInf] diff --git a/Mathlib/Data/Nat/BitIndices.lean b/Mathlib/Data/Nat/BitIndices.lean index 2b9034e73c7b8..8e257d61ead92 100644 --- a/Mathlib/Data/Nat/BitIndices.lean +++ b/Mathlib/Data/Nat/BitIndices.lean @@ -7,8 +7,8 @@ import Mathlib.Data.List.Sort import Mathlib.Data.Nat.Bitwise import Mathlib.Algebra.BigOperators.Ring.List import Mathlib.Algebra.Order.BigOperators.Group.List +import Mathlib.Algebra.Order.Star.Basic import Mathlib.Algebra.Order.Sub.Defs -import Mathlib.Algebra.Star.Order /-! # Bit Indices diff --git a/Mathlib/Data/Nat/Bits.lean b/Mathlib/Data/Nat/Bits.lean index df2a618f055ba..3fff69bc6dc3f 100644 --- a/Mathlib/Data/Nat/Bits.lean +++ b/Mathlib/Data/Nat/Bits.lean @@ -43,7 +43,7 @@ def boddDiv2 : ℕ → Bool × ℕ /-- `div2 n = ⌊n/2⌋` the greatest integer smaller than `n/2`-/ def div2 (n : ℕ) : ℕ := (boddDiv2 n).2 -/-- `bodd n` returns `true` if `n` is odd-/ +/-- `bodd n` returns `true` if `n` is odd -/ def bodd (n : ℕ) : Bool := (boddDiv2 n).1 @[simp] lemma bodd_zero : bodd 0 = false := rfl @@ -66,9 +66,10 @@ lemma bodd_add (m n : ℕ) : bodd (m + n) = bxor (bodd m) (bodd n) := by @[simp] lemma bodd_mul (m n : ℕ) : bodd (m * n) = (bodd m && bodd n) := by - induction' n with n IH - · simp - · simp only [mul_succ, bodd_add, IH, bodd_succ] + induction n with + | zero => simp + | succ n IH => + simp only [mul_succ, bodd_add, IH, bodd_succ] cases bodd m <;> cases bodd n <;> rfl lemma mod_two_of_bodd (n : ℕ) : n % 2 = cond (bodd n) 1 0 := by @@ -83,7 +84,7 @@ lemma mod_two_of_bodd (n : ℕ) : n % 2 = cond (bodd n) 1 0 := by intro b cases b <;> rfl rw [← this] - cases' mod_two_eq_zero_or_one n with h h <;> rw [h] <;> rfl + rcases mod_two_eq_zero_or_one n with h | h <;> rw [h] <;> rfl @[simp] lemma div2_zero : div2 0 = 0 := rfl @@ -131,7 +132,7 @@ lemma bit_zero : bit false 0 = 0 := /-- `shiftLeft' b m n` performs a left shift of `m` `n` times and adds the bit `b` as the least significant bit each time. - Returns the corresponding natural number-/ + Returns the corresponding natural number -/ def shiftLeft' (b : Bool) (m : ℕ) : ℕ → ℕ | 0 => m | n + 1 => bit b (shiftLeft' b m n) @@ -339,7 +340,7 @@ theorem binaryRec_eq' {C : ℕ → Sort*} {z : C 0} {f : ∀ b n, C n → C (bit split_ifs with h' · rcases bit_eq_zero_iff.mp h' with ⟨rfl, rfl⟩ rw [binaryRec_zero] - simp only [imp_false, or_false_iff, eq_self_iff_true, not_true] at h + simp only [imp_false, or_false_iff, eq_self_iff_true, not_true, reduceCtorEq] at h exact h.symm · dsimp only [] generalize_proofs e @@ -396,11 +397,13 @@ theorem one_bits : Nat.bits 1 = [true] := by -- := by norm_num theorem bodd_eq_bits_head (n : ℕ) : n.bodd = n.bits.headI := by - induction' n using Nat.binaryRec' with b n h _; · simp - simp [bodd_bit, bits_append_bit _ _ h] + induction n using Nat.binaryRec' with + | z => simp + | f _ _ h _ => simp [bodd_bit, bits_append_bit _ _ h] theorem div2_bits_eq_tail (n : ℕ) : n.div2.bits = n.bits.tail := by - induction' n using Nat.binaryRec' with b n h _; · simp - simp [div2_bit, bits_append_bit _ _ h] + induction n using Nat.binaryRec' with + | z => simp + | f _ _ h _ => simp [div2_bit, bits_append_bit _ _ h] end Nat diff --git a/Mathlib/Data/Nat/Bitwise.lean b/Mathlib/Data/Nat/Bitwise.lean index 0d5dc3611afd5..2a2306e5f1f71 100644 --- a/Mathlib/Data/Nat/Bitwise.lean +++ b/Mathlib/Data/Nat/Bitwise.lean @@ -246,34 +246,11 @@ theorem lt_of_testBit {n m : ℕ} (i : ℕ) (hn : testBit n i = false) (hm : tes _ ≤ 2 * m := mul_le_mul_left 2 this · exact Nat.succ_lt_succ this' -@[simp] -theorem testBit_two_pow_self (n : ℕ) : testBit (2 ^ n) n = true := by - rw [testBit, shiftRight_eq_div_pow, Nat.div_self (Nat.pow_pos Nat.zero_lt_two)] - simp - -theorem testBit_two_pow_of_ne {n m : ℕ} (hm : n ≠ m) : testBit (2 ^ n) m = false := by - rw [testBit, shiftRight_eq_div_pow] - cases' hm.lt_or_lt with hm hm - · rw [Nat.div_eq_of_lt] - · simp - · exact Nat.pow_lt_pow_right Nat.one_lt_two hm - · rw [Nat.pow_div hm.le Nat.two_pos, ← Nat.sub_add_cancel (succ_le_of_lt <| Nat.sub_pos_of_lt hm)] - -- Porting note: XXX why does this make it work? - rw [(rfl : succ 0 = 1)] - simp [pow_succ, and_one_is_mod, mul_mod_left] - -theorem testBit_two_pow (n m : ℕ) : testBit (2 ^ n) m = (n = m) := by - by_cases h : n = m - · cases h - simp - · rw [testBit_two_pow_of_ne h] - simp [h] - theorem bitwise_swap {f : Bool → Bool → Bool} : bitwise (Function.swap f) = Function.swap (bitwise f) := by funext m n simp only [Function.swap] - induction' m using Nat.strongInductionOn with m ih generalizing n + induction' m using Nat.strongRecOn with m ih generalizing n cases' m with m <;> cases' n with n <;> try rw [bitwise_zero_left, bitwise_zero_right] diff --git a/Mathlib/Data/Nat/Cast/Defs.lean b/Mathlib/Data/Nat/Cast/Defs.lean index 0a184083269a5..937ea2f0f088c 100644 --- a/Mathlib/Data/Nat/Cast/Defs.lean +++ b/Mathlib/Data/Nat/Cast/Defs.lean @@ -83,7 +83,7 @@ class AddMonoidWithOne (R : Type*) extends NatCast R, AddMonoid R, One R where /-- The canonical map `ℕ → R` is a homomorphism. -/ natCast_succ : ∀ n, natCast (n + 1) = natCast n + 1 := by intros; rfl -/-- An `AddCommMonoidWithOne` is an `AddMonoidWithOne` satisfying `a + b = b + a`. -/ +/-- An `AddCommMonoidWithOne` is an `AddMonoidWithOne` satisfying `a + b = b + a`. -/ class AddCommMonoidWithOne (R : Type*) extends AddMonoidWithOne R, AddCommMonoid R library_note "coercion into rings" @@ -149,8 +149,7 @@ protected def binCast [Zero R] [One R] [Add R] : ℕ → R @[simp] theorem binCast_eq [AddMonoidWithOne R] (n : ℕ) : (Nat.binCast n : R) = ((n : ℕ) : R) := by - apply Nat.strongInductionOn n - intros k hk + induction n using Nat.strongRecOn with | ind k hk => ?_ cases k with | zero => rw [Nat.binCast, Nat.cast_zero] | succ k => diff --git a/Mathlib/Data/Nat/Cast/Field.lean b/Mathlib/Data/Nat/Cast/Field.lean index 3fe4913e4f2ef..d532397a177fd 100644 --- a/Mathlib/Data/Nat/Cast/Field.lean +++ b/Mathlib/Data/Nat/Cast/Field.lean @@ -37,6 +37,6 @@ theorem cast_div_div_div_cancel_right [DivisionSemiring α] [CharZero α] {m n d (↑(m / d) : α) / (↑(n / d) : α) = (m : α) / n := by rcases eq_or_ne d 0 with (rfl | hd); · simp [Nat.zero_dvd.1 hm] replace hd : (d : α) ≠ 0 := by norm_cast - rw [cast_div hm, cast_div hn, div_div_div_cancel_right _ hd] <;> exact hd + rw [cast_div hm, cast_div hn, div_div_div_cancel_right₀ hd] <;> exact hd end Nat diff --git a/Mathlib/Data/Nat/Cast/Order/Field.lean b/Mathlib/Data/Nat/Cast/Order/Field.lean index 74674ae19eeb2..8b16df559d51a 100644 --- a/Mathlib/Data/Nat/Cast/Order/Field.lean +++ b/Mathlib/Data/Nat/Cast/Order/Field.lean @@ -28,7 +28,7 @@ lemma cast_inv_le_one : ∀ n : ℕ, (n⁻¹ : α) ≤ 1 theorem cast_div_le {m n : ℕ} : ((m / n : ℕ) : α) ≤ m / n := by cases n · rw [cast_zero, div_zero, Nat.div_zero, cast_zero] - rw [le_div_iff, ← Nat.cast_mul, @Nat.cast_le] + rw [le_div_iff₀, ← Nat.cast_mul, @Nat.cast_le] · exact Nat.div_mul_le_self m _ · exact Nat.cast_pos.2 (Nat.succ_pos _) diff --git a/Mathlib/Data/Nat/Choose/Basic.lean b/Mathlib/Data/Nat/Choose/Basic.lean index dd13795e37b76..af9347cfba776 100644 --- a/Mathlib/Data/Nat/Choose/Basic.lean +++ b/Mathlib/Data/Nat/Choose/Basic.lean @@ -365,7 +365,5 @@ theorem multichoose_eq : ∀ n k : ℕ, multichoose n k = (n + k - 1).choose k erw [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] - termination_by a b => a + b - decreasing_by all_goals assumption end Nat diff --git a/Mathlib/Data/Nat/Choose/Bounds.lean b/Mathlib/Data/Nat/Choose/Bounds.lean index 2f82b251e6fa9..d4b21ddf606d9 100644 --- a/Mathlib/Data/Nat/Choose/Bounds.lean +++ b/Mathlib/Data/Nat/Choose/Bounds.lean @@ -3,7 +3,7 @@ Copyright (c) 2021 Yaël Dillies. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies, Eric Rodriguez -/ -import Mathlib.Algebra.Order.Field.Basic +import Mathlib.Algebra.Order.Field.Defs import Mathlib.Data.Nat.Cast.Order.Basic import Mathlib.Data.Nat.Choose.Basic @@ -15,7 +15,7 @@ bounds `n^r/r^r ≤ n.choose r ≤ e^r n^r/r^r` in the future. ## Main declarations -* `Nat.choose_le_pow`: `n.choose r ≤ n^r / r!` +* `Nat.choose_le_pow_div`: `n.choose r ≤ n^r / r!` * `Nat.pow_le_choose`: `(n + 1 - r)^r / r! ≤ n.choose r`. Beware of the fishy ℕ-subtraction. -/ @@ -26,16 +26,25 @@ variable {α : Type*} [LinearOrderedSemifield α] namespace Nat -theorem choose_le_pow (r n : ℕ) : (n.choose r : α) ≤ (n ^ r : α) / r ! := by - rw [le_div_iff'] +theorem choose_le_pow_div (r n : ℕ) : (n.choose r : α) ≤ (n ^ r : α) / r ! := by + rw [le_div_iff₀'] · norm_cast rw [← Nat.descFactorial_eq_factorial_mul_choose] exact n.descFactorial_le_pow r exact mod_cast r.factorial_pos +lemma choose_le_descFactorial (n k : ℕ) : n.choose k ≤ n.descFactorial k := by + rw [choose_eq_descFactorial_div_factorial] + exact Nat.div_le_self _ _ + +/-- This lemma was changed on 2024/08/29, the old statement is available +in `Nat.choose_le_pow_div`. -/ +lemma choose_le_pow (n k : ℕ) : n.choose k ≤ n ^ k := + (choose_le_descFactorial n k).trans (descFactorial_le_pow n k) + -- horrific casting is due to ℕ-subtraction theorem pow_le_choose (r n : ℕ) : ((n + 1 - r : ℕ) ^ r : α) / r ! ≤ n.choose r := by - rw [div_le_iff'] + rw [div_le_iff₀'] · norm_cast rw [← Nat.descFactorial_eq_factorial_mul_choose] exact n.pow_sub_le_descFactorial r diff --git a/Mathlib/Data/Nat/Choose/Sum.lean b/Mathlib/Data/Nat/Choose/Sum.lean index ac70377042b48..d9bafecbbe840 100644 --- a/Mathlib/Data/Nat/Choose/Sum.lean +++ b/Mathlib/Data/Nat/Choose/Sum.lean @@ -17,13 +17,9 @@ import Mathlib.Tactic.Ring This file includes variants of the binomial theorem and other results on sums of binomial coefficients. Theorems whose proofs depend on such sums may also go in this file for import reasons. - -/ - -open Nat - -open Finset +open Nat Finset variable {R : Type*} @@ -33,32 +29,33 @@ variable [Semiring R] {x y : R} /-- A version of the **binomial theorem** for commuting elements in noncommutative semirings. -/ theorem add_pow (h : Commute x y) (n : ℕ) : - (x + y) ^ n = ∑ m ∈ range (n + 1), x ^ m * y ^ (n - m) * choose n m := by - let t : ℕ → ℕ → R := fun n m ↦ x ^ m * y ^ (n - m) * choose n m + (x + y) ^ n = ∑ m ∈ range (n + 1), x ^ m * y ^ (n - m) * n.choose m := by + let t : ℕ → ℕ → R := fun n m ↦ x ^ m * y ^ (n - m) * n.choose m change (x + y) ^ n = ∑ m ∈ range (n + 1), t n m have h_first : ∀ n, t n 0 = y ^ n := fun n ↦ by - simp only [t, choose_zero_right, _root_.pow_zero, Nat.cast_one, mul_one, one_mul, tsub_zero] + simp only [t, choose_zero_right, pow_zero, cast_one, mul_one, one_mul, tsub_zero] have h_last : ∀ n, t n n.succ = 0 := fun n ↦ by simp only [t, choose_succ_self, cast_zero, mul_zero] have h_middle : - ∀ n i : ℕ, i ∈ range n.succ → (t n.succ (Nat.succ i)) = - x * t n i + y * t n i.succ := by + ∀ n i : ℕ, i ∈ range n.succ → (t n.succ i.succ) = x * t n i + y * t n i.succ := by intro n i h_mem - have h_le : i ≤ n := Nat.le_of_lt_succ (mem_range.mp h_mem) + have h_le : i ≤ n := le_of_lt_succ (mem_range.mp h_mem) dsimp only [t] - rw [choose_succ_succ, Nat.cast_add, mul_add] + rw [choose_succ_succ, cast_add, mul_add] congr 1 · rw [pow_succ' x, succ_sub_succ, mul_assoc, mul_assoc, mul_assoc] · rw [← mul_assoc y, ← mul_assoc y, (h.symm.pow_right i.succ).eq] by_cases h_eq : i = n - · rw [h_eq, choose_succ_self, Nat.cast_zero, mul_zero, mul_zero] + · rw [h_eq, choose_succ_self, cast_zero, mul_zero, mul_zero] · rw [succ_sub (lt_of_le_of_ne h_le h_eq)] rw [pow_succ' y, mul_assoc, mul_assoc, mul_assoc, mul_assoc] - induction' n with n ih - · rw [_root_.pow_zero, sum_range_succ, range_zero, sum_empty, zero_add] + induction n with + | zero => + rw [pow_zero, sum_range_succ, range_zero, sum_empty, zero_add] dsimp only [t] - rw [_root_.pow_zero, _root_.pow_zero, choose_self, Nat.cast_one, mul_one, mul_one] - · rw [sum_range_succ', h_first, sum_congr rfl (h_middle n), sum_add_distrib, add_assoc, + rw [pow_zero, pow_zero, choose_self, cast_one, mul_one, mul_one] + | succ n ih => + rw [sum_range_succ', h_first, sum_congr rfl (h_middle n), sum_add_distrib, add_assoc, pow_succ' (x + y), ih, add_mul, mul_sum, mul_sum] congr 1 rw [sum_range_succ', sum_range_succ, h_first, h_last, mul_zero, add_zero, _root_.pow_succ'] @@ -66,81 +63,96 @@ theorem add_pow (h : Commute x y) (n : ℕ) : /-- A version of `Commute.add_pow` that avoids ℕ-subtraction by summing over the antidiagonal and also with the binomial coefficient applied via scalar action of ℕ. -/ theorem add_pow' (h : Commute x y) (n : ℕ) : - (x + y) ^ n = ∑ m ∈ antidiagonal n, choose n m.fst • (x ^ m.fst * y ^ m.snd) := by - simp_rw [Finset.Nat.sum_antidiagonal_eq_sum_range_succ fun m p ↦ choose n m • (x ^ m * y ^ p), - _root_.nsmul_eq_mul, cast_comm, h.add_pow] + (x + y) ^ n = ∑ m ∈ antidiagonal n, n.choose m.1 • (x ^ m.1 * y ^ m.2) := by + simp_rw [Nat.sum_antidiagonal_eq_sum_range_succ fun m p ↦ n.choose m • (x ^ m * y ^ p), + nsmul_eq_mul, cast_comm, h.add_pow] end Commute /-- The **binomial theorem** -/ theorem add_pow [CommSemiring R] (x y : R) (n : ℕ) : - (x + y) ^ n = ∑ m ∈ range (n + 1), x ^ m * y ^ (n - m) * choose n m := + (x + y) ^ n = ∑ m ∈ range (n + 1), x ^ m * y ^ (n - m) * n.choose m := (Commute.all x y).add_pow n namespace Nat /-- The sum of entries in a row of Pascal's triangle -/ -theorem sum_range_choose (n : ℕ) : (∑ m ∈ range (n + 1), choose n m) = 2 ^ n := by +theorem sum_range_choose (n : ℕ) : (∑ m ∈ range (n + 1), n.choose m) = 2 ^ n := by have := (add_pow 1 1 n).symm simpa [one_add_one_eq_two] using this -theorem sum_range_choose_halfway (m : Nat) : (∑ i ∈ range (m + 1), choose (2 * m + 1) i) = 4 ^ m := - have : (∑ i ∈ range (m + 1), choose (2 * m + 1) (2 * m + 1 - i)) = - ∑ i ∈ range (m + 1), choose (2 * m + 1) i := +theorem sum_range_choose_halfway (m : ℕ) : (∑ i ∈ range (m + 1), (2 * m + 1).choose i) = 4 ^ m := + have : (∑ i ∈ range (m + 1), (2 * m + 1).choose (2 * m + 1 - i)) = + ∑ i ∈ range (m + 1), (2 * m + 1).choose i := sum_congr rfl fun i hi ↦ choose_symm <| by linarith [mem_range.1 hi] mul_right_injective₀ two_ne_zero <| calc - (2 * ∑ i ∈ range (m + 1), choose (2 * m + 1) i) = - (∑ i ∈ range (m + 1), choose (2 * m + 1) i) + - ∑ i ∈ range (m + 1), choose (2 * m + 1) (2 * m + 1 - i) := by rw [two_mul, this] - _ = (∑ i ∈ range (m + 1), choose (2 * m + 1) i) + - ∑ i ∈ Ico (m + 1) (2 * m + 2), choose (2 * m + 1) i := by - { rw [range_eq_Ico, sum_Ico_reflect] - · congr - have A : m + 1 ≤ 2 * m + 1 := by omega - rw [add_comm, add_tsub_assoc_of_le A, ← add_comm] - congr - rw [tsub_eq_iff_eq_add_of_le A] - ring - · omega } - _ = ∑ i ∈ range (2 * m + 2), choose (2 * m + 1) i := sum_range_add_sum_Ico _ (by omega) + (2 * ∑ i ∈ range (m + 1), (2 * m + 1).choose i) = + (∑ i ∈ range (m + 1), (2 * m + 1).choose i) + + ∑ i ∈ range (m + 1), (2 * m + 1).choose (2 * m + 1 - i) := by rw [two_mul, this] + _ = (∑ i ∈ range (m + 1), (2 * m + 1).choose i) + + ∑ i ∈ Ico (m + 1) (2 * m + 2), (2 * m + 1).choose i := by + rw [range_eq_Ico, sum_Ico_reflect _ _ (by omega)] + congr + have A : m + 1 ≤ 2 * m + 1 := by omega + rw [add_comm, add_tsub_assoc_of_le A, ← add_comm] + congr + rw [tsub_eq_iff_eq_add_of_le A] + ring + _ = ∑ i ∈ range (2 * m + 2), (2 * m + 1).choose i := sum_range_add_sum_Ico _ (by omega) _ = 2 ^ (2 * m + 1) := sum_range_choose (2 * m + 1) - _ = 2 * 4 ^ m := by rw [Nat.pow_succ, pow_mul, mul_comm]; rfl + _ = 2 * 4 ^ m := by rw [pow_succ, pow_mul, mul_comm]; rfl -theorem choose_middle_le_pow (n : ℕ) : choose (2 * n + 1) n ≤ 4 ^ n := by - have t : choose (2 * n + 1) n ≤ ∑ i ∈ range (n + 1), choose (2 * n + 1) i := +theorem choose_middle_le_pow (n : ℕ) : (2 * n + 1).choose n ≤ 4 ^ n := by + have t : (2 * n + 1).choose n ≤ ∑ i ∈ range (n + 1), (2 * n + 1).choose i := single_le_sum (fun x _ ↦ by omega) (self_mem_range_succ n) simpa [sum_range_choose_halfway n] using t theorem four_pow_le_two_mul_add_one_mul_central_binom (n : ℕ) : - 4 ^ n ≤ (2 * n + 1) * choose (2 * n) n := + 4 ^ n ≤ (2 * n + 1) * (2 * n).choose n := calc 4 ^ n = (1 + 1) ^ (2 * n) := by norm_num [pow_mul] - _ = ∑ m ∈ range (2 * n + 1), choose (2 * n) m := by set_option simprocs false in simp [add_pow] - _ ≤ ∑ m ∈ range (2 * n + 1), choose (2 * n) (2 * n / 2) := by gcongr; apply choose_le_middle + _ = ∑ m ∈ range (2 * n + 1), (2 * n).choose m := by set_option simprocs false in simp [add_pow] + _ ≤ ∑ m ∈ range (2 * n + 1), (2 * n).choose (2 * n / 2) := by gcongr; apply choose_le_middle _ = (2 * n + 1) * choose (2 * n) n := by simp -/-- **Zhu Shijie's identity** aka hockey-stick identity. -/ +/-- **Zhu Shijie's identity** aka hockey-stick identity, version with `Icc`. -/ theorem sum_Icc_choose (n k : ℕ) : ∑ m ∈ Icc k n, m.choose k = (n + 1).choose (k + 1) := by - cases' le_or_gt k n with h h - · induction' n, h using le_induction with n _ ih; · simp - rw [← Ico_insert_right (by omega), sum_insert (by simp), - show Ico k (n + 1) = Icc k n by rfl, ih, choose_succ_succ' (n + 1)] + rcases lt_or_le n k with h | h · rw [choose_eq_zero_of_lt (by omega), Icc_eq_empty_of_lt h, sum_empty] + · induction n, h using le_induction with + | base => simp + | succ n _ ih => + rw [← Ico_insert_right (by omega), sum_insert (by simp), + show Ico k (n + 1) = Icc k n by rfl, ih, choose_succ_succ' (n + 1)] + +/-- **Zhu Shijie's identity** aka hockey-stick identity, version with `range`. +Summing `(i + k).choose k` for `i ∈ [0, n]` gives `(n + k + 1).choose (k + 1)`. + +Combinatorial interpretation: `(i + k).choose k` is the number of decompositions of `[0, i)` in +`k + 1` (possibly empty) intervals (this follows from a stars and bars description). In particular, +`(n + k + 1).choose (k + 1)` corresponds to decomposing `[0, n)` into `k + 2` intervals. +By putting away the last interval (of some length `n - i`), +we have to decompose the remaining interval `[0, i)` into `k + 1` intervals, hence the sum. -/ +lemma sum_range_add_choose (n k : ℕ) : + ∑ i ∈ Finset.range (n + 1), (i + k).choose k = (n + k + 1).choose (k + 1) := by + rw [← sum_Icc_choose, range_eq_Ico] + convert (sum_map _ (addRightEmbedding k) (·.choose k)).symm using 2 + rw [map_add_right_Ico, zero_add, add_right_comm, Nat.Ico_succ_right] end Nat theorem Int.alternating_sum_range_choose {n : ℕ} : - (∑ m ∈ range (n + 1), ((-1) ^ m * ↑(choose n m) : ℤ)) = if n = 0 then 1 else 0 := by + (∑ m ∈ range (n + 1), ((-1) ^ m * n.choose m : ℤ)) = if n = 0 then 1 else 0 := by cases n with | zero => simp | succ n => have h := add_pow (-1 : ℤ) 1 n.succ simp only [one_pow, mul_one, neg_add_cancel] at h - rw [← h, zero_pow n.succ_ne_zero, if_neg (Nat.succ_ne_zero n)] + rw [← h, zero_pow n.succ_ne_zero, if_neg n.succ_ne_zero] theorem Int.alternating_sum_range_choose_of_ne {n : ℕ} (h0 : n ≠ 0) : - (∑ m ∈ range (n + 1), ((-1) ^ m * ↑(choose n m) : ℤ)) = 0 := by + (∑ m ∈ range (n + 1), ((-1) ^ m * n.choose m : ℤ)) = 0 := by rw [Int.alternating_sum_range_choose, if_neg h0] namespace Finset @@ -166,9 +178,8 @@ theorem sum_powerset_neg_one_pow_card {α : Type*} [DecidableEq α] {x : Finset theorem sum_powerset_neg_one_pow_card_of_nonempty {α : Type*} {x : Finset α} (h0 : x.Nonempty) : (∑ m ∈ x.powerset, (-1 : ℤ) ^ m.card) = 0 := by classical - rw [sum_powerset_neg_one_pow_card, if_neg] - rw [← Ne, ← nonempty_iff_ne_empty] - apply h0 + rw [sum_powerset_neg_one_pow_card] + exact if_neg (nonempty_iff_ne_empty.mp h0) variable {M R : Type*} [CommMonoid M] [NonAssocSemiring R] @@ -179,10 +190,9 @@ theorem prod_pow_choose_succ {M : Type*} [CommMonoid M] (f : ℕ → ℕ → M) ∏ i ∈ range (n + 1), f (i + 1) (n - i) ^ n.choose i := by have A : (∏ i ∈ range (n + 1), f (i + 1) (n - i) ^ (n.choose (i + 1))) * f 0 (n + 1) = ∏ i ∈ range (n + 1), f i (n + 1 - i) ^ (n.choose i) := by - rw [prod_range_succ, prod_range_succ'] - simp + rw [prod_range_succ, prod_range_succ']; simp rw [prod_range_succ'] - simpa [Nat.choose_succ_succ, pow_add, prod_mul_distrib, A, mul_assoc] using mul_comm _ _ + simpa [choose_succ_succ, pow_add, prod_mul_distrib, A, mul_assoc] using mul_comm _ _ @[to_additive sum_antidiagonal_choose_succ_nsmul] theorem prod_antidiagonal_pow_choose_succ {M : Type*} [CommMonoid M] (f : ℕ → ℕ → M) (n : ℕ) : @@ -195,9 +205,8 @@ theorem prod_antidiagonal_pow_choose_succ {M : Type*} [CommMonoid M] (f : ℕ · refine prod_congr rfl fun i hi ↦ ?_ rw [tsub_add_eq_add_tsub (this _ hi)] · refine prod_congr rfl fun i hi ↦ ?_ - rw [Nat.choose_symm (this _ hi)] + rw [choose_symm (this _ hi)] --- Porting note: moved from `Mathlib.Analysis.Calculus.ContDiff` /-- The sum of `(n+1).choose i * f i (n+1-i)` can be split into two sums at rank `n`, respectively of `n.choose i * f i (n+1-i)` and `n.choose i * f (i+1) (n-i)`. -/ theorem sum_choose_succ_mul (f : ℕ → ℕ → R) (n : ℕ) : @@ -215,8 +224,7 @@ theorem sum_antidiagonal_choose_succ_mul (f : ℕ → ℕ → R) (n : ℕ) : simpa only [nsmul_eq_mul] using sum_antidiagonal_choose_succ_nsmul f n theorem sum_antidiagonal_choose_add (d n : ℕ) : - (Finset.sum (antidiagonal n) fun ij => (d + ij.2).choose d) = - (d + n).choose d + (d + n).choose (succ d) := by + (∑ ij ∈ antidiagonal n, (d + ij.2).choose d) = (d + n).choose d + (d + n).choose (d + 1) := by induction n with | zero => simp | succ n hn => simpa [Nat.sum_antidiagonal_succ] using hn diff --git a/Mathlib/Data/Nat/Defs.lean b/Mathlib/Data/Nat/Defs.lean index 31452114335f3..dd38886b716c7 100644 --- a/Mathlib/Data/Nat/Defs.lean +++ b/Mathlib/Data/Nat/Defs.lean @@ -5,11 +5,9 @@ Authors: Floris van Doorn, Leonardo de Moura, Jeremy Avigad, Mario Carneiro -/ import Mathlib.Logic.Function.Basic import Mathlib.Logic.Nontrivial.Defs -import Mathlib.Tactic.Cases import Mathlib.Tactic.GCongr.Core import Mathlib.Tactic.PushNeg import Mathlib.Util.AssertExists -import Batteries.Data.Nat.Basic /-! # Basic operations on the natural numbers @@ -826,6 +824,22 @@ 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 +/-- Induction principle deriving the next case from the two previous ones. -/ +def twoStepInduction {P : ℕ → Sort*} (zero : P 0) (one : P 1) + (more : ∀ n, P n → P (n + 1) → P (n + 2)) : ∀ a, P a + | 0 => zero + | 1 => one + | _ + 2 => more _ (twoStepInduction zero one more _) (twoStepInduction zero one more _) + +@[elab_as_elim] +protected theorem strong_induction_on {p : ℕ → Prop} (n : ℕ) + (h : ∀ n, (∀ m, m < n → p m) → p n) : p n := + Nat.strongRecOn n h + +protected theorem case_strong_induction_on {p : ℕ → Prop} (a : ℕ) (hz : p 0) + (hi : ∀ n, (∀ m, m ≤ n → p m) → p (n + 1)) : p a := + Nat.caseStrongRecOn a hz hi + /-- Decreasing induction: if `P (k+1)` implies `P k` for all `k < n`, then `P n` implies `P m` for all `m ≤ n`. Also works for functions to `Sort*`. @@ -925,8 +939,6 @@ theorem diag_induction (P : ℕ → ℕ → Prop) (ha : ∀ a, P (a + 1) (a + 1) have _ : a + (b + 1) < (a + 1) + (b + 1) := by simp apply diag_induction P ha hb hd a (b + 1) apply Nat.lt_of_le_of_lt (Nat.le_succ _) h - termination_by a b _c => a + b - decreasing_by all_goals assumption /-- A subset of `ℕ` containing `k : ℕ` and closed under `Nat.succ` contains every `n ≥ k`. -/ lemma set_induction_bounded {S : Set ℕ} (hk : k ∈ S) (h_ind : ∀ k : ℕ, k ∈ S → k + 1 ∈ S) @@ -943,10 +955,10 @@ lemma set_induction {S : Set ℕ} (hb : 0 ∈ S) (h_ind : ∀ k : ℕ, k ∈ S attribute [simp] Nat.dvd_zero @[simp] lemma mod_two_ne_one : ¬n % 2 = 1 ↔ n % 2 = 0 := by - cases' mod_two_eq_zero_or_one n with h h <;> simp [h] + cases mod_two_eq_zero_or_one n <;> simp [*] @[simp] lemma mod_two_ne_zero : ¬n % 2 = 0 ↔ n % 2 = 1 := by - cases' mod_two_eq_zero_or_one n with h h <;> simp [h] + cases mod_two_eq_zero_or_one n <;> simp [*] @[deprecated mod_mul_right_div_self (since := "2024-05-29")] lemma div_mod_eq_mod_mul_div (a b c : ℕ) : a / b % c = a % (b * c) / b := @@ -1066,8 +1078,11 @@ lemma sub_mod_eq_zero_of_mod_eq (h : m % k = n % k) : (m - n) % k = 0 := by @[simp] lemma one_mod (n : ℕ) : 1 % (n + 2) = 1 := Nat.mod_eq_of_lt (Nat.add_lt_add_right n.succ_pos 1) -lemma one_mod_of_ne_one : ∀ {n : ℕ}, n ≠ 1 → 1 % n = 1 - | 0, _ | (n + 2), _ => by simp +lemma one_mod_eq_one : ∀ {n : ℕ}, 1 % n = 1 ↔ n ≠ 1 + | 0 | 1 | n + 2 => by simp + +@[deprecated (since := "2024-08-28")] +lemma one_mod_of_ne_one : ∀ {n : ℕ}, n ≠ 1 → 1 % n = 1 := one_mod_eq_one.mpr lemma dvd_sub_mod (k : ℕ) : n ∣ k - k % n := ⟨k / n, Nat.sub_eq_of_eq_add (Nat.div_add_mod k n).symm⟩ @@ -1280,196 +1295,6 @@ lemma div_lt_div_of_lt_of_dvd {a b d : ℕ} (hdb : d ∣ b) (h : a < b) : a / d rw [Nat.lt_div_iff_mul_lt hdb] exact lt_of_le_of_lt (mul_div_le a d) h -/-! -### `sqrt` - -See [Wikipedia, *Methods of computing square roots*] -(https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Binary_numeral_system_(base_2)). --/ - -private lemma iter_fp_bound (n k : ℕ) : - let iter_next (n guess : ℕ) := (guess + n / guess) / 2; - sqrt.iter n k ≤ iter_next n (sqrt.iter n k) := by - intro iter_next - unfold sqrt.iter - if h : (k + n / k) / 2 < k then - simpa [if_pos h] using iter_fp_bound _ _ - else - simpa [if_neg h] using Nat.le_of_not_lt h - -private lemma AM_GM : {a b : ℕ} → (4 * a * b ≤ (a + b) * (a + b)) - | 0, _ => by rw [Nat.mul_zero, Nat.zero_mul]; exact zero_le _ - | _, 0 => by rw [Nat.mul_zero]; exact zero_le _ - | a + 1, b + 1 => by - simpa only [Nat.mul_add, Nat.add_mul, show (4 : ℕ) = 1 + 1 + 1 + 1 from rfl, Nat.one_mul, - Nat.mul_one, Nat.add_assoc, Nat.add_left_comm, Nat.add_le_add_iff_left] - using Nat.add_le_add_right (@AM_GM a b) 4 - --- These two lemmas seem like they belong to `Batteries.Data.Nat.Basic`. - -lemma sqrt.iter_sq_le (n guess : ℕ) : sqrt.iter n guess * sqrt.iter n guess ≤ n := by - unfold sqrt.iter - let next := (guess + n / guess) / 2 - if h : next < guess then - simpa only [dif_pos h] using sqrt.iter_sq_le n next - else - simp only [dif_neg h] - apply Nat.mul_le_of_le_div - apply Nat.le_of_add_le_add_left (a := guess) - rw [← Nat.mul_two, ← le_div_iff_mul_le] - · exact Nat.le_of_not_lt h - · exact Nat.zero_lt_two - -lemma sqrt.lt_iter_succ_sq (n guess : ℕ) (hn : n < (guess + 1) * (guess + 1)) : - n < (sqrt.iter n guess + 1) * (sqrt.iter n guess + 1) := by - unfold sqrt.iter - -- m was `next` - let m := (guess + n / guess) / 2 - dsimp - split_ifs with h - · suffices n < (m + 1) * (m + 1) by - simpa only [dif_pos h] using sqrt.lt_iter_succ_sq n m this - refine Nat.lt_of_mul_lt_mul_left ?_ (a := 4 * (guess * guess)) - apply Nat.lt_of_le_of_lt AM_GM - rw [show (4 : ℕ) = 2 * 2 from rfl] - rw [Nat.mul_mul_mul_comm 2, Nat.mul_mul_mul_comm (2 * guess)] - refine Nat.mul_self_lt_mul_self (?_ : _ < _ * ((_ / 2) + 1)) - rw [← add_div_right _ (by decide), Nat.mul_comm 2, Nat.mul_assoc, - show guess + n / guess + 2 = (guess + n / guess + 1) + 1 from rfl] - have aux_lemma {a : ℕ} : a ≤ 2 * ((a + 1) / 2) := by omega - refine lt_of_lt_of_le ?_ (Nat.mul_le_mul_left _ aux_lemma) - rw [Nat.add_assoc, Nat.mul_add] - exact Nat.add_lt_add_left (lt_mul_div_succ _ (lt_of_le_of_lt (Nat.zero_le m) h)) _ - · simpa only [dif_neg h] using hn --- Porting note: the implementation of `Nat.sqrt` in `Batteries` no longer needs `sqrt_aux`. -private def IsSqrt (n q : ℕ) : Prop := - q * q ≤ n ∧ n < (q + 1) * (q + 1) --- Porting note: as the definition of square root has changed, --- the proof of `sqrt_isSqrt` is attempted from scratch. -/- -Sketch of proof: -Up to rounding, in terms of the definition of `sqrt.iter`, - -* By AM-GM inequality, `next² ≥ n` giving one of the bounds. -* When we terminated, we have `guess ≥ next` from which we deduce the other bound `n ≥ next²`. - -To turn this into a lean proof we need to manipulate, use properties of natural number division etc. --/ -private lemma sqrt_isSqrt (n : ℕ) : IsSqrt n (sqrt n) := by - match n with - | 0 => simp [IsSqrt, sqrt] - | 1 => simp [IsSqrt, sqrt] - | n + 2 => - have h : ¬ (n + 2) ≤ 1 := by simp - simp only [IsSqrt, sqrt, h, ite_false] - refine ⟨sqrt.iter_sq_le _ _, sqrt.lt_iter_succ_sq _ _ ?_⟩ - simp only [Nat.mul_add, Nat.add_mul, Nat.one_mul, Nat.mul_one, ← Nat.add_assoc] - rw [Nat.lt_add_one_iff, Nat.add_assoc, ← Nat.mul_two] - refine le_trans (Nat.le_of_eq (div_add_mod' (n + 2) 2).symm) ?_ - rw [Nat.add_comm, Nat.add_le_add_iff_right, add_mod_right] - simp only [Nat.zero_lt_two, add_div_right, succ_mul_succ] - refine le_trans (b := 1) ?_ ?_ - · exact (lt_succ.1 <| mod_lt n Nat.zero_lt_two) - · exact Nat.le_add_left _ _ - -lemma sqrt_le (n : ℕ) : sqrt n * sqrt n ≤ n := (sqrt_isSqrt n).left - -lemma sqrt_le' (n : ℕ) : sqrt n ^ 2 ≤ n := by simpa [Nat.pow_two] using sqrt_le n - -lemma lt_succ_sqrt (n : ℕ) : n < succ (sqrt n) * succ (sqrt n) := (sqrt_isSqrt n).right - -lemma lt_succ_sqrt' (n : ℕ) : n < succ (sqrt n) ^ 2 := by simpa [Nat.pow_two] using lt_succ_sqrt n - -lemma sqrt_le_add (n : ℕ) : n ≤ sqrt n * sqrt n + sqrt n + sqrt n := by - rw [← succ_mul]; exact le_of_lt_succ (lt_succ_sqrt n) - -lemma le_sqrt : m ≤ sqrt n ↔ m * m ≤ n := - ⟨fun h ↦ le_trans (mul_self_le_mul_self h) (sqrt_le n), - fun h ↦ le_of_lt_succ <| Nat.mul_self_lt_mul_self_iff.1 <| lt_of_le_of_lt h (lt_succ_sqrt n)⟩ - -lemma le_sqrt' : m ≤ sqrt n ↔ m ^ 2 ≤ n := by simpa only [Nat.pow_two] using le_sqrt - -lemma sqrt_lt : sqrt m < n ↔ m < n * n := by simp only [← not_le, le_sqrt] - -lemma sqrt_lt' : sqrt m < n ↔ m < n ^ 2 := by simp only [← not_le, le_sqrt'] - -lemma sqrt_le_self (n : ℕ) : sqrt n ≤ n := le_trans (le_mul_self _) (sqrt_le n) - -lemma sqrt_le_sqrt (h : m ≤ n) : sqrt m ≤ sqrt n := le_sqrt.2 (le_trans (sqrt_le _) h) - -@[simp] lemma sqrt_zero : sqrt 0 = 0 := rfl - -@[simp] lemma sqrt_one : sqrt 1 = 1 := rfl - -lemma sqrt_eq_zero : sqrt n = 0 ↔ n = 0 := - ⟨fun h ↦ - Nat.eq_zero_of_le_zero <| le_of_lt_succ <| (@sqrt_lt n 1).1 <| by rw [h]; decide, - by rintro rfl; simp⟩ - -lemma eq_sqrt : a = sqrt n ↔ a * a ≤ n ∧ n < (a + 1) * (a + 1) := - ⟨fun e ↦ e.symm ▸ sqrt_isSqrt n, - fun ⟨h₁, h₂⟩ ↦ le_antisymm (le_sqrt.2 h₁) (le_of_lt_succ <| sqrt_lt.2 h₂)⟩ - -lemma eq_sqrt' : a = sqrt n ↔ a ^ 2 ≤ n ∧ n < (a + 1) ^ 2 := by - simpa only [Nat.pow_two] using eq_sqrt - -lemma le_three_of_sqrt_eq_one (h : sqrt n = 1) : n ≤ 3 := - le_of_lt_succ <| (@sqrt_lt n 2).1 <| by rw [h]; decide - -lemma sqrt_lt_self (h : 1 < n) : sqrt n < n := - sqrt_lt.2 <| by have := Nat.mul_lt_mul_of_pos_left h (lt_of_succ_lt h); rwa [Nat.mul_one] at this - -lemma sqrt_pos : 0 < sqrt n ↔ 0 < n := - le_sqrt - -lemma sqrt_add_eq (n : ℕ) (h : a ≤ n + n) : sqrt (n * n + a) = n := - le_antisymm - (le_of_lt_succ <| - sqrt_lt.2 <| by - rw [succ_mul, mul_succ, add_succ, Nat.add_assoc] - exact lt_succ_of_le (Nat.add_le_add_left h _)) - (le_sqrt.2 <| Nat.le_add_right _ _) - -lemma sqrt_add_eq' (n : ℕ) (h : a ≤ n + n) : sqrt (n ^ 2 + a) = n := by - simpa [Nat.pow_two] using sqrt_add_eq n h - -lemma sqrt_eq (n : ℕ) : sqrt (n * n) = n := sqrt_add_eq n (zero_le _) - -lemma sqrt_eq' (n : ℕ) : sqrt (n ^ 2) = n := sqrt_add_eq' n (zero_le _) - -lemma sqrt_succ_le_succ_sqrt (n : ℕ) : sqrt n.succ ≤ n.sqrt.succ := - le_of_lt_succ <| sqrt_lt.2 <| lt_succ_of_le <| - succ_le_succ <| le_trans (sqrt_le_add n) <| Nat.add_le_add_right - (by refine add_le_add (Nat.mul_le_mul_right _ ?_) ?_ <;> exact Nat.le_add_right _ 2) _ - -lemma exists_mul_self (x : ℕ) : (∃ n, n * n = x) ↔ sqrt x * sqrt x = x := - ⟨fun ⟨n, hn⟩ ↦ by rw [← hn, sqrt_eq], fun h ↦ ⟨sqrt x, h⟩⟩ - -lemma exists_mul_self' (x : ℕ) : (∃ n, n ^ 2 = x) ↔ sqrt x ^ 2 = x := by - simpa only [Nat.pow_two] using exists_mul_self x - -lemma sqrt_mul_sqrt_lt_succ (n : ℕ) : sqrt n * sqrt n < n + 1 := - Nat.lt_succ_iff.mpr (sqrt_le _) - -lemma sqrt_mul_sqrt_lt_succ' (n : ℕ) : sqrt n ^ 2 < n + 1 := - Nat.lt_succ_iff.mpr (sqrt_le' _) - -lemma succ_le_succ_sqrt (n : ℕ) : n + 1 ≤ (sqrt n + 1) * (sqrt n + 1) := - le_of_pred_lt (lt_succ_sqrt _) - -lemma succ_le_succ_sqrt' (n : ℕ) : n + 1 ≤ (sqrt n + 1) ^ 2 := - le_of_pred_lt (lt_succ_sqrt' _) - -/-- There are no perfect squares strictly between m² and (m+1)² -/ -lemma not_exists_sq (hl : m * m < n) (hr : n < (m + 1) * (m + 1)) : ¬∃ t, t * t = n := by - rintro ⟨t, rfl⟩ - have h1 : m < t := Nat.mul_self_lt_mul_self_iff.1 hl - have h2 : t < m + 1 := Nat.mul_self_lt_mul_self_iff.1 hr - exact (not_lt_of_ge <| le_of_lt_succ h2) h1 - -lemma not_exists_sq' : m ^ 2 < n → n < (m + 1) ^ 2 → ¬∃ t, t ^ 2 = n := by - simpa only [Nat.pow_two] using not_exists_sq - /-! ### Decidability of predicates -/ instance decidableLoHi (lo hi : ℕ) (P : ℕ → Prop) [H : DecidablePred P] : diff --git a/Mathlib/Data/Nat/Digits.lean b/Mathlib/Data/Nat/Digits.lean index 3465ed5369aa7..cd2a1c41ebd01 100644 --- a/Mathlib/Data/Nat/Digits.lean +++ b/Mathlib/Data/Nat/Digits.lean @@ -246,9 +246,7 @@ theorem ofDigits_digits (b n : ℕ) : ofDigits b (digits b n) = n := by · rfl · rw [Nat.zero_add] at ih ⊢ simp only [ih, add_comm 1, ofDigits_one_cons, Nat.cast_id, digits_one_succ] - · apply Nat.strongInductionOn n _ - clear n - intro n h + · induction n using Nat.strongRecOn with | ind n h => ?_ cases n · rw [digits_zero] rfl @@ -258,9 +256,9 @@ theorem ofDigits_digits (b n : ℕ) : ofDigits b (digits b n) = n := by rw [Nat.mod_add_div] theorem ofDigits_one (L : List ℕ) : ofDigits 1 L = L.sum := by - induction' L with _ _ ih - · rfl - · simp [ofDigits, List.sum_cons, ih] + induction L with + | nil => rfl + | cons _ _ ih => simp [ofDigits, List.sum_cons, ih] /-! ### Properties @@ -328,8 +326,8 @@ theorem getLast_digit_ne_zero (b : ℕ) {m : ℕ} (hm : m ≠ 0) : simp only [zero_add, digits_one, List.getLast_replicate_succ m 1] exact Nat.one_ne_zero revert hm - apply Nat.strongInductionOn m - intro n IH hn + induction m using Nat.strongRecOn with | ind n IH => ?_ + intro hn by_cases hnb : n < b + 2 · simpa only [digits_of_lt (b + 2) n hn hnb] · rw [digits_getLast n (le_add_left 2 b)] @@ -345,7 +343,7 @@ theorem mul_ofDigits (n : ℕ) {b : ℕ} {l : List ℕ} : rw [List.map_cons, ofDigits_cons, ofDigits_cons, ← ih] ring -/-- The addition of ofDigits of two lists is equal to ofDigits of digit-wise addition of them-/ +/-- The addition of ofDigits of two lists is equal to ofDigits of digit-wise addition of them -/ theorem ofDigits_add_ofDigits_eq_ofDigits_zipWith_of_length_eq {b : ℕ} {l1 l2 : List ℕ} (h : l1.length = l2.length) : ofDigits b l1 + ofDigits b l2 = ofDigits b (l1.zipWith (· + ·) l2) := by @@ -362,8 +360,8 @@ theorem ofDigits_add_ofDigits_eq_ofDigits_zipWith_of_length_eq {b : ℕ} {l1 l2 /-- The digits in the base b+2 expansion of n are all less than b+2 -/ theorem digits_lt_base' {b m : ℕ} : ∀ {d}, d ∈ digits (b + 2) m → d < b + 2 := by - apply Nat.strongInductionOn m - intro n IH d hd + induction m using Nat.strongRecOn with | ind n IH => ?_ + intro d hd cases' n with n · rw [digits_zero] at hd cases hd @@ -440,9 +438,10 @@ theorem le_digits_len_le (b n m : ℕ) (h : n ≤ m) : (digits b n).length ≤ ( @[mono] theorem ofDigits_monotone {p q : ℕ} (L : List ℕ) (h : p ≤ q) : ofDigits p L ≤ ofDigits q L := by - induction' L with _ _ hi - · rfl - · simp only [ofDigits, cast_id, add_le_add_iff_left] + induction L with + | nil => rfl + | cons _ _ hi => + simp only [ofDigits, cast_id, add_le_add_iff_left] exact Nat.mul_le_mul h hi theorem sum_le_ofDigits {p : ℕ} (L : List ℕ) (h : 1 ≤ p) : L.sum ≤ ofDigits p L := diff --git a/Mathlib/Data/Nat/Dist.lean b/Mathlib/Data/Nat/Dist.lean index 8151b3d7c07f2..b207d03af6224 100644 --- a/Mathlib/Data/Nat/Dist.lean +++ b/Mathlib/Data/Nat/Dist.lean @@ -89,7 +89,7 @@ theorem dist_succ_succ {i j : Nat} : dist (succ i) (succ j) = dist i j := by simp [dist, succ_sub_succ] theorem dist_pos_of_ne {i j : Nat} : i ≠ j → 0 < dist i j := fun hne => - Nat.ltByCases + ltByCases i j (fun h : i < j => by rw [dist_eq_sub_of_le (le_of_lt h)]; apply tsub_pos_of_lt h) (fun h : i = j => by contradiction) fun h : i > j => by rw [dist_eq_sub_of_le_right (le_of_lt h)]; apply tsub_pos_of_lt h diff --git a/Mathlib/Data/Nat/Factorial/Basic.lean b/Mathlib/Data/Nat/Factorial/Basic.lean index f41001d9b85d8..cacc9997b8c7e 100644 --- a/Mathlib/Data/Nat/Factorial/Basic.lean +++ b/Mathlib/Data/Nat/Factorial/Basic.lean @@ -354,12 +354,32 @@ theorem factorial_mul_descFactorial : ∀ {n k : ℕ}, k ≤ n → (n - k)! * n. rw [succ_descFactorial_succ, succ_sub_succ, ← Nat.mul_assoc, Nat.mul_comm (n - k)!, Nat.mul_assoc, factorial_mul_descFactorial (Nat.succ_le_succ_iff.1 h), factorial_succ] +theorem descFactorial_mul_descFactorial {k m n : ℕ} (hkm : k ≤ m) : + (n - k).descFactorial (m - k) * n.descFactorial k = n.descFactorial m := by + by_cases hmn : m ≤ n + · apply Nat.mul_left_cancel (n - m).factorial_pos + rw [factorial_mul_descFactorial hmn, show n - m = (n - k) - (m - k) by omega, ← Nat.mul_assoc, + factorial_mul_descFactorial (show m - k ≤ n - k by omega), + factorial_mul_descFactorial (le_trans hkm hmn)] + · rw [descFactorial_eq_zero_iff_lt.mpr (show n < m by omega)] + by_cases hkn : k ≤ n + · rw [descFactorial_eq_zero_iff_lt.mpr (show n - k < m - k by omega), Nat.zero_mul] + · rw [descFactorial_eq_zero_iff_lt.mpr (show n < k by omega), Nat.mul_zero] + /-- Avoid in favor of `Nat.factorial_mul_descFactorial` if you can. ℕ-division isn't worth it. -/ theorem descFactorial_eq_div {n k : ℕ} (h : k ≤ n) : n.descFactorial k = n ! / (n - k)! := by apply Nat.mul_left_cancel (n - k).factorial_pos rw [factorial_mul_descFactorial h] exact (Nat.mul_div_cancel' <| factorial_dvd_factorial <| Nat.sub_le n k).symm +theorem descFactorial_le (n : ℕ) {k m : ℕ} (h : k ≤ m) : + k.descFactorial n ≤ m.descFactorial n := by + induction n with + | zero => rfl + | succ n ih => + rw [descFactorial_succ, descFactorial_succ] + exact Nat.mul_le_mul (Nat.sub_le_sub_right h n) ih + theorem pow_sub_le_descFactorial (n : ℕ) : ∀ k : ℕ, (n + 1 - k) ^ k ≤ n.descFactorial k | 0 => by rw [descFactorial_zero, Nat.pow_zero] | k + 1 => by diff --git a/Mathlib/Data/Nat/Factorization/Basic.lean b/Mathlib/Data/Nat/Factorization/Basic.lean index 3b99f2f2baaac..6e116bcf98273 100644 --- a/Mathlib/Data/Nat/Factorization/Basic.lean +++ b/Mathlib/Data/Nat/Factorization/Basic.lean @@ -7,6 +7,7 @@ import Mathlib.Data.Nat.PrimeFin import Mathlib.Data.Nat.Factorization.Defs import Mathlib.Data.Nat.GCD.BigOperators import Mathlib.Order.Interval.Finset.Nat +import Mathlib.Tactic.IntervalCases /-! # Basic lemmas on prime factorizations @@ -243,7 +244,7 @@ two `2 ^ k`. -/ theorem exists_eq_two_pow_mul_odd {n : ℕ} (hn : n ≠ 0) : ∃ k m : ℕ, Odd m ∧ n = 2 ^ k * m := let ⟨k, m, hm, hn⟩ := exists_eq_pow_mul_and_not_dvd hn 2 (succ_ne_self 1) - ⟨k, m, odd_iff_not_even.mpr (mt Even.two_dvd hm), hn⟩ + ⟨k, m, not_even_iff_odd.1 (mt Even.two_dvd hm), hn⟩ theorem dvd_iff_div_factorization_eq_tsub {d n : ℕ} (hd : d ≠ 0) (hdn : d ≤ n) : d ∣ n ↔ (n / d).factorization = n.factorization - d.factorization := by @@ -387,7 +388,7 @@ lemma factorizationLCMRight_pos : rw [factorizationLCMRight, Finsupp.prod_ne_zero_iff] intro p _ H by_cases h : b.factorization p ≤ a.factorization p - · simp only [h, reduceIte, pow_eq_zero_iff', ne_eq] at H + · simp only [h, reduceIte, pow_eq_zero_iff', ne_eq, reduceCtorEq] at H · simp only [h, ↓reduceIte, pow_eq_zero_iff', ne_eq] at H simpa [H.1] using H.2 @@ -529,7 +530,7 @@ theorem prod_pow_prime_padicValNat (n : Nat) (hn : n ≠ 0) (m : Nat) (pr : n < -- TODO: Port lemmas from `Data/Nat/Multiplicity` to here, re-written in terms of `factorization` /-- Exactly `n / p` naturals in `[1, n]` are multiples of `p`. -See `Nat.card_multiples'` for an alternative spelling of the statement. -/ +See `Nat.card_multiples'` for an alternative spelling of the statement. -/ theorem card_multiples (n p : ℕ) : card ((Finset.range n).filter fun e => p ∣ e + 1) = n / p := by induction' n with n hn · simp diff --git a/Mathlib/Data/Nat/Factorization/Defs.lean b/Mathlib/Data/Nat/Factorization/Defs.lean index 5e73f5097014d..fbabc1edc00fd 100644 --- a/Mathlib/Data/Nat/Factorization/Defs.lean +++ b/Mathlib/Data/Nat/Factorization/Defs.lean @@ -4,7 +4,9 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Stuart Presnell -/ import Mathlib.Data.Finsupp.Multiset -import Mathlib.NumberTheory.Padics.PadicVal +import Mathlib.Data.Nat.Prime.Defs +import Mathlib.Data.Nat.PrimeFin +import Mathlib.NumberTheory.Padics.PadicVal.Defs /-! # Prime factorizations diff --git a/Mathlib/Data/Nat/Factorization/Induction.lean b/Mathlib/Data/Nat/Factorization/Induction.lean index 1add41840d66f..df145576e8514 100644 --- a/Mathlib/Data/Nat/Factorization/Induction.lean +++ b/Mathlib/Data/Nat/Factorization/Induction.lean @@ -22,7 +22,7 @@ we can define `P` for all natural numbers. -/ @[elab_as_elim] def recOnPrimePow {P : ℕ → Sort*} (h0 : P 0) (h1 : P 1) (h : ∀ a p n : ℕ, p.Prime → ¬p ∣ a → 0 < n → P a → P (p ^ n * a)) : ∀ a : ℕ, P a := fun a => - Nat.strongRecOn a fun n => + Nat.strongRecOn' a fun n => match n with | 0 => fun _ => h0 | 1 => fun _ => h1 diff --git a/Mathlib/Data/Nat/Factors.lean b/Mathlib/Data/Nat/Factors.lean index 3f99b646ebaa3..df65aa467ceea 100644 --- a/Mathlib/Data/Nat/Factors.lean +++ b/Mathlib/Data/Nat/Factors.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Leonardo de Moura, Jeremy Avigad, Mario Carneiro -/ import Mathlib.Algebra.BigOperators.Ring.List +import Mathlib.Data.Nat.GCD.Basic import Mathlib.Data.Nat.Prime.Defs import Mathlib.Data.List.Prime import Mathlib.Data.List.Sort @@ -79,7 +80,7 @@ theorem prod_primeFactorsList : ∀ {n}, n ≠ 0 → List.prod (primeFactorsList Nat.mul_div_cancel' (minFac_dvd _)] theorem primeFactorsList_prime {p : ℕ} (hp : Nat.Prime p) : p.primeFactorsList = [p] := by - have : p = p - 2 + 2 := (Nat.sub_add_cancel hp.two_le).symm + have : p = p - 2 + 2 := Nat.eq_add_of_sub_eq hp.two_le rfl rw [this, primeFactorsList] simp only [Eq.symm this] have : Nat.minFac p = p := (Nat.prime_def_minFac.mp hp).2 diff --git a/Mathlib/Data/Nat/Fib/Basic.lean b/Mathlib/Data/Nat/Fib/Basic.lean index fb9601268e67e..4d5698a009a29 100644 --- a/Mathlib/Data/Nat/Fib/Basic.lean +++ b/Mathlib/Data/Nat/Fib/Basic.lean @@ -5,10 +5,8 @@ Authors: Kevin Kappelmann, Kyle Miller, Mario Carneiro -/ import Mathlib.Algebra.BigOperators.Group.Finset import Mathlib.Data.Finset.NatAntidiagonal -import Mathlib.Data.Nat.GCD.Basic import Mathlib.Data.Nat.Bits -import Mathlib.Init.Data.Nat.Lemmas -import Mathlib.Logic.Function.Iterate +import Mathlib.Data.Nat.GCD.Basic import Mathlib.Tactic.Ring import Mathlib.Tactic.Zify diff --git a/Mathlib/Data/Nat/Find.lean b/Mathlib/Data/Nat/Find.lean index 014c1729bbfe4..e37f555306458 100644 --- a/Mathlib/Data/Nat/Find.lean +++ b/Mathlib/Data/Nat/Find.lean @@ -150,12 +150,14 @@ lemma findGreatest_of_not (h : ¬ P (n + 1)) : findGreatest P (n + 1) = findGrea lemma findGreatest_eq_iff : Nat.findGreatest P k = m ↔ m ≤ k ∧ (m ≠ 0 → P m) ∧ ∀ ⦃n⦄, m < n → n ≤ k → ¬P n := by - induction' k with k ihk generalizing m - · rw [eq_comm, Iff.comm] + induction k generalizing m with + | zero => + rw [eq_comm, Iff.comm] simp only [zero_eq, Nat.le_zero, ne_eq, findGreatest_zero, and_iff_left_iff_imp] rintro rfl exact ⟨fun h ↦ (h rfl).elim, fun n hlt heq ↦ by omega⟩ - · by_cases hk : P (k + 1) + | succ k ihk => + by_cases hk : P (k + 1) · rw [findGreatest_eq hk] constructor · rintro rfl @@ -196,21 +198,23 @@ lemma le_findGreatest (hmb : m ≤ n) (hm : P m) : m ≤ Nat.findGreatest P n := lemma findGreatest_mono_right (P : ℕ → Prop) [DecidablePred P] {m n} (hmn : m ≤ n) : Nat.findGreatest P m ≤ Nat.findGreatest P n := by - induction' hmn with k hmk ih - · simp - rw [findGreatest_succ] - split_ifs - · exact le_trans ih <| le_trans (findGreatest_le _) (le_succ _) - · exact ih + induction hmn with + | refl => simp + | step hmk ih => + rw [findGreatest_succ] + split_ifs + · exact le_trans ih <| le_trans (findGreatest_le _) (le_succ _) + · exact ih lemma findGreatest_mono_left [DecidablePred Q] (hPQ : ∀ n, P n → Q n) (n : ℕ) : Nat.findGreatest P n ≤ Nat.findGreatest Q n := by - induction' n with n hn - · rfl - by_cases h : P (n + 1) - · rw [findGreatest_eq h, findGreatest_eq (hPQ _ h)] - · rw [findGreatest_of_not h] - exact le_trans hn (Nat.findGreatest_mono_right _ <| le_succ _) + induction n with + | zero => rfl + | succ n hn => + by_cases h : P (n + 1) + · rw [findGreatest_eq h, findGreatest_eq (hPQ _ h)] + · rw [findGreatest_of_not h] + exact le_trans hn (Nat.findGreatest_mono_right _ <| le_succ _) lemma findGreatest_mono [DecidablePred Q] (hPQ : ∀ n, P n → Q n) (hmn : m ≤ n) : Nat.findGreatest P m ≤ Nat.findGreatest Q n := diff --git a/Mathlib/Data/Nat/GCD/Basic.lean b/Mathlib/Data/Nat/GCD/Basic.lean index ffce815884fb3..8d4d667ffa251 100644 --- a/Mathlib/Data/Nat/GCD/Basic.lean +++ b/Mathlib/Data/Nat/GCD/Basic.lean @@ -3,22 +3,25 @@ Copyright (c) 2014 Jeremy Avigad. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad, Leonardo de Moura -/ -import Mathlib.Order.Lattice import Mathlib.Algebra.GroupWithZero.Divisibility import Mathlib.Algebra.Ring.Nat -import Mathlib.Init.Data.Nat.Lemmas /-! -# Definitions and properties of `Nat.gcd`, `Nat.lcm`, and `Nat.coprime` +# Properties of `Nat.gcd`, `Nat.lcm`, and `Nat.Coprime` + +Definitions are provided in batteries. Generalizations of these are provided in a later file as `GCDMonoid.gcd` and `GCDMonoid.lcm`. -Note that the global `IsCoprime` is not a straightforward generalization of `Nat.coprime`, see +Note that the global `IsCoprime` is not a straightforward generalization of `Nat.Coprime`, see `Nat.isCoprime_iff_coprime` for the connection between the two. +Most of this file could be moved to batteries as well. -/ +assert_not_exists OrderedCommMonoid + namespace Nat /-! ### `gcd` -/ @@ -129,8 +132,6 @@ theorem lcm_mul_right {m n k : ℕ} : (m * n).lcm (k * n) = m.lcm k * n := by See also `Nat.coprime_of_dvd` and `Nat.coprime_of_dvd'` to prove `Nat.Coprime m n`. -/ -instance (m n : ℕ) : Decidable (Coprime m n) := inferInstanceAs (Decidable (gcd m n = 1)) - theorem Coprime.lcm_eq_mul {m n : ℕ} (h : Coprime m n) : lcm m n = m * n := by rw [← one_mul (lcm m n), ← h.gcd_eq_one, gcd_mul_lcm] @@ -209,7 +210,7 @@ theorem coprime_self_sub_right {m n : ℕ} (h : m ≤ n) : Coprime n (n - m) ↔ @[simp] theorem coprime_pow_left_iff {n : ℕ} (hn : 0 < n) (a b : ℕ) : Nat.Coprime (a ^ n) b ↔ Nat.Coprime a b := by - obtain ⟨n, rfl⟩ := exists_eq_succ_of_ne_zero hn.ne' + obtain ⟨n, rfl⟩ := exists_eq_succ_of_ne_zero (Nat.ne_of_gt hn) rw [Nat.pow_succ, Nat.coprime_mul_iff_left] exact ⟨And.right, fun hab => ⟨hab.pow_left _, hab⟩⟩ @@ -233,7 +234,7 @@ theorem gcd_mul_of_coprime_of_dvd {a b c : ℕ} (hac : Coprime a c) (b_dvd_c : b theorem Coprime.eq_of_mul_eq_zero {m n : ℕ} (h : m.Coprime n) (hmn : m * n = 0) : m = 0 ∧ n = 1 ∨ m = 1 ∧ n = 0 := - (Nat.eq_zero_of_mul_eq_zero hmn).imp (fun hm => ⟨hm, n.coprime_zero_left.mp <| hm ▸ h⟩) fun hn => + (Nat.mul_eq_zero.mp hmn).imp (fun hm => ⟨hm, n.coprime_zero_left.mp <| hm ▸ h⟩) fun hn => let eq := hn ▸ h.symm ⟨m.coprime_zero_left.mp <| eq, hn⟩ @@ -270,7 +271,7 @@ theorem pow_dvd_pow_iff {a b n : ℕ} (n0 : n ≠ 0) : a ^ n ∣ b ^ n ↔ a ∣ · simp [eq_zero_of_gcd_eq_zero_right g0] rcases exists_coprime' g0 with ⟨g, a', b', g0', co, rfl, rfl⟩ rw [mul_pow, mul_pow] at h - replace h := Nat.dvd_of_mul_dvd_mul_right (Nat.pos_pow_of_pos _ g0') h + replace h := Nat.dvd_of_mul_dvd_mul_right (Nat.pow_pos g0') h have := pow_dvd_pow a' <| Nat.pos_of_ne_zero n0 rw [pow_one, (co.pow n n).eq_one_of_dvd h] at this simp [eq_one_of_dvd_one this] diff --git a/Mathlib/Data/Nat/Log.lean b/Mathlib/Data/Nat/Log.lean index 0e33dd6f02898..eb2ae3bc58f52 100644 --- a/Mathlib/Data/Nat/Log.lean +++ b/Mathlib/Data/Nat/Log.lean @@ -3,8 +3,6 @@ Copyright (c) 2020 Simon Hudon. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Simon Hudon, Yaël Dillies -/ -import Mathlib.Data.Nat.Defs -import Mathlib.Init.Data.Nat.Lemmas import Mathlib.Order.Interval.Set.Basic import Mathlib.Tactic.Bound.Attribute import Mathlib.Tactic.Monotonicity.Attr @@ -78,7 +76,7 @@ theorem log_one_right (b : ℕ) : log b 1 = 0 := `Nat.le_log_of_pow_le` for individual implications under weaker assumptions. -/ theorem pow_le_iff_le_log {b : ℕ} (hb : 1 < b) {x y : ℕ} (hy : y ≠ 0) : b ^ x ≤ y ↔ x ≤ log b y := by - induction' y using Nat.strong_induction_on with y ih generalizing x + induction y using Nat.strong_induction_on generalizing x with | h y ih => ?_ cases x with | zero => dsimp; omega | succ x => @@ -111,6 +109,15 @@ theorem log_lt_of_lt_pow {b x y : ℕ} (hy : y ≠ 0) : y < b ^ x → log b y < theorem lt_pow_of_log_lt {b x y : ℕ} (hb : 1 < b) : log b y < x → y < b ^ x := lt_imp_lt_of_le_imp_le (le_log_of_pow_le hb) +lemma log_lt_self (b : ℕ) {x : ℕ} (hx : x ≠ 0) : log b x < x := + match le_or_lt b 1 with + | .inl h => log_of_left_le_one h x ▸ Nat.pos_iff_ne_zero.2 hx + | .inr h => log_lt_of_lt_pow hx <| lt_pow_self h _ + +lemma log_le_self (b x : ℕ) : log b x ≤ x := + if hx : x = 0 then by simp [hx] + else (log_lt_self b hx).le + theorem lt_pow_succ_log_self {b : ℕ} (hb : 1 < b) (x : ℕ) : x < b ^ (log b x).succ := lt_pow_of_log_lt hb (lt_succ_self _) @@ -181,7 +188,7 @@ theorem log_antitone_left {n : ℕ} : AntitoneOn (fun b => log b n) (Set.Ioi 1) theorem log_div_base (b n : ℕ) : log b (n / b) = log b n - 1 := by rcases le_or_lt b 1 with hb | hb · rw [log_of_left_le_one hb, log_of_left_le_one hb, Nat.zero_sub] - cases' lt_or_le n b with h h + rcases lt_or_le n b with h | h · rw [div_eq_of_lt h, log_of_lt h, log_zero_right] rw [log_of_one_lt_of_le hb h, Nat.add_sub_cancel_right] @@ -189,7 +196,7 @@ theorem log_div_base (b n : ℕ) : log b (n / b) = log b n - 1 := by theorem log_div_mul_self (b n : ℕ) : log b (n / b * b) = log b n := by rcases le_or_lt b 1 with hb | hb · rw [log_of_left_le_one hb, log_of_left_le_one hb] - cases' lt_or_le n b with h h + rcases lt_or_le n b with h | h · rw [div_eq_of_lt h, Nat.zero_mul, log_zero_right, log_of_lt h] rw [log_mul_base hb (Nat.div_pos h (by omega)).ne', log_div_base, Nat.sub_add_cancel (succ_le_iff.2 <| log_pos hb h)] @@ -199,6 +206,13 @@ theorem add_pred_div_lt {b n : ℕ} (hb : 1 < b) (hn : 2 ≤ n) : (n + b - 1) / succ_pred_eq_of_pos (by omega)] exact Nat.add_le_mul hn hb +lemma log2_eq_log_two {n : ℕ} : Nat.log2 n = Nat.log 2 n := by + rcases eq_or_ne n 0 with rfl | hn + · rw [log2_zero, log_zero_right] + apply eq_of_forall_le_iff + intro m + rw [Nat.le_log2 hn, ← Nat.pow_le_iff_le_log Nat.one_lt_two hn] + /-! ### Ceil logarithm -/ @@ -244,7 +258,7 @@ theorem clog_eq_one {b n : ℕ} (hn : 2 ≤ n) (h : n ≤ b) : clog b n = 1 := b /-- `clog b` and `pow b` form a Galois connection. -/ theorem le_pow_iff_clog_le {b : ℕ} (hb : 1 < b) {x y : ℕ} : x ≤ b ^ y ↔ clog b x ≤ y := by - induction' x using Nat.strong_induction_on with x ih generalizing y + induction x using Nat.strong_induction_on generalizing y with | h x ih => ?_ cases y · rw [Nat.pow_zero] refine ⟨fun h => (clog_of_right_le_one h b).le, ?_⟩ diff --git a/Mathlib/Data/Nat/Notation.lean b/Mathlib/Data/Nat/Notation.lean index 582c017ea9161..729e9b67b0f52 100644 --- a/Mathlib/Data/Nat/Notation.lean +++ b/Mathlib/Data/Nat/Notation.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Floris van Doorn, Leonardo de Moura -/ -import Mathlib.Init /-! # Notation `ℕ` for the natural numbers. -/ diff --git a/Mathlib/Data/Nat/Nth.lean b/Mathlib/Data/Nat/Nth.lean index 83719860919c9..e31e9bcb4390d 100644 --- a/Mathlib/Data/Nat/Nth.lean +++ b/Mathlib/Data/Nat/Nth.lean @@ -12,7 +12,7 @@ import Mathlib.Order.OrderIsoNat /-! # The `n`th Number Satisfying a Predicate -This file defines a function for "what is the `n`th number that satisifies a given predicate `p`", +This file defines a function for "what is the `n`th number that satisfies a given predicate `p`", and provides lemmas that deal with this function and its connection to `Nat.count`. ## Main definitions diff --git a/Mathlib/Data/Nat/PSub.lean b/Mathlib/Data/Nat/PSub.lean index e752c7156034f..e4d0b1efeaaae 100644 --- a/Mathlib/Data/Nat/PSub.lean +++ b/Mathlib/Data/Nat/PSub.lean @@ -73,13 +73,11 @@ theorem psub_eq_some {m : ℕ} : ∀ {n k}, psub m n = some k ↔ k + n = m simp [add_comm, add_left_comm] theorem psub_eq_none {m n : ℕ} : psub m n = none ↔ m < n := by - cases s : psub m n <;> simp [eq_comm] - · show m < n - refine lt_of_not_ge fun h => ?_ - cases' le.dest h with k e + rcases s : psub m n <;> simp [eq_comm] + · refine lt_of_not_ge fun h => ?_ + obtain ⟨k, e⟩ := le.dest h injection s.symm.trans (psub_eq_some.2 <| (add_comm _ _).trans e) - · show n ≤ m - rw [← psub_eq_some.1 s] + · rw [← psub_eq_some.1 s] apply Nat.le_add_left theorem ppred_eq_pred {n} (h : 0 < n) : ppred n = some (pred n) := diff --git a/Mathlib/Data/Nat/Pairing.lean b/Mathlib/Data/Nat/Pairing.lean index b33b6e5f5723c..6265833d77e17 100644 --- a/Mathlib/Data/Nat/Pairing.lean +++ b/Mathlib/Data/Nat/Pairing.lean @@ -5,6 +5,7 @@ Authors: Leonardo de Moura, Mario Carneiro -/ import Mathlib.Algebra.Group.Prod import Mathlib.Data.Set.Lattice +import Mathlib.Data.Nat.Sqrt /-! # Naturals pairing function diff --git a/Mathlib/Data/Nat/Prime/Basic.lean b/Mathlib/Data/Nat/Prime/Basic.lean index 419ca7d32efae..e75aca751b05e 100644 --- a/Mathlib/Data/Nat/Prime/Basic.lean +++ b/Mathlib/Data/Nat/Prime/Basic.lean @@ -132,7 +132,7 @@ theorem Prime.not_dvd_mul {p m n : ℕ} (pp : Prime p) (Hm : ¬p ∣ m) (Hn : ¬ mt pp.dvd_mul.1 <| by simp [Hm, Hn] @[simp] lemma coprime_two_left : Coprime 2 n ↔ Odd n := by - rw [prime_two.coprime_iff_not_dvd, odd_iff_not_even, even_iff_two_dvd] + rw [prime_two.coprime_iff_not_dvd, ← not_even_iff_odd, even_iff_two_dvd] @[simp] lemma coprime_two_right : n.Coprime 2 ↔ Odd n := coprime_comm.trans coprime_two_left diff --git a/Mathlib/Data/Nat/Prime/Defs.lean b/Mathlib/Data/Nat/Prime/Defs.lean index 57010bbdfe78c..8cff72a3c2aa9 100644 --- a/Mathlib/Data/Nat/Prime/Defs.lean +++ b/Mathlib/Data/Nat/Prime/Defs.lean @@ -5,7 +5,6 @@ Authors: Leonardo de Moura, Jeremy Avigad, Mario Carneiro -/ import Mathlib.Algebra.Associated.Basic import Mathlib.Algebra.Ring.Parity -import Mathlib.Data.Nat.GCD.Basic /-! # Prime numbers @@ -83,7 +82,7 @@ theorem prime_def_lt'' {p : ℕ} : Prime p ↔ 2 ≤ p ∧ ∀ m, m ∣ p → m simp only [Nat.isUnit_iff] apply Or.imp_right _ (h.2 a _) · rintro rfl - rw [← mul_right_inj' (zero_lt_of_lt h1).ne', ← hab, mul_one] + rw [← mul_right_inj' (not_eq_zero_of_lt h1), ← hab, mul_one] · rw [hab] exact dvd_mul_right _ _ @@ -104,7 +103,7 @@ theorem prime_def_lt' {p : ℕ} : Prime p ↔ 2 ≤ p ∧ ∀ m, 2 ≤ m → m < revert p2 decide · rfl - · exact (h (le_add_left _ _) l).elim d⟩ + · exact (h (le_add_left 2 m) l).elim d⟩ theorem prime_def_le_sqrt {p : ℕ} : Prime p ↔ 2 ≤ p ∧ ∀ m, 2 ≤ m → m ≤ sqrt p → ¬m ∣ p := prime_def_lt'.trans <| diff --git a/Mathlib/Data/Nat/Set.lean b/Mathlib/Data/Nat/Set.lean index 7da3f139267a2..26f1795892ced 100644 --- a/Mathlib/Data/Nat/Set.lean +++ b/Mathlib/Data/Nat/Set.lean @@ -35,10 +35,9 @@ theorem range_rec {α : Type*} (x : α) (f : ℕ → α → α) : convert (range_of_succ (fun n => Nat.rec x f n : ℕ → α)).symm using 4 dsimp rename_i n - induction' n with n ihn - · rfl - · dsimp at ihn ⊢ - rw [ihn] + induction n with + | zero => rfl + | succ n ihn => dsimp at ihn ⊢; rw [ihn] theorem range_casesOn {α : Type*} (x : α) (f : ℕ → α) : (Set.range fun n => Nat.casesOn n x f : Set α) = {x} ∪ Set.range f := diff --git a/Mathlib/Data/Nat/Size.lean b/Mathlib/Data/Nat/Size.lean index 322711980b545..f3f51b3aa4f02 100644 --- a/Mathlib/Data/Nat/Size.lean +++ b/Mathlib/Data/Nat/Size.lean @@ -57,20 +57,21 @@ end @[simp] theorem size_shiftLeft' {b m n} (h : shiftLeft' b m n ≠ 0) : size (shiftLeft' b m n) = size m + n := by - induction' n with n IH - · simp [shiftLeft'] - simp only [shiftLeft', ne_eq] at h ⊢ - rw [size_bit h, Nat.add_succ] - by_cases s0 : shiftLeft' b m n = 0 - case neg => rw [IH s0] - rw [s0] at h ⊢ - cases b; · exact absurd rfl h - have : shiftLeft' true m n + 1 = 1 := congr_arg (· + 1) s0 - rw [shiftLeft'_tt_eq_mul_pow] at this - obtain rfl := succ.inj (eq_one_of_dvd_one ⟨_, this.symm⟩) - simp only [zero_add, one_mul] at this - obtain rfl : n = 0 := not_ne_iff.1 fun hn ↦ ne_of_gt (Nat.one_lt_pow hn (by decide)) this - rw [add_zero] + induction n with + | zero => simp [shiftLeft'] + | succ n IH => + simp only [shiftLeft', ne_eq] at h ⊢ + rw [size_bit h, Nat.add_succ] + by_cases s0 : shiftLeft' b m n = 0 + case neg => rw [IH s0] + rw [s0] at h ⊢ + cases b; · exact absurd rfl h + have : shiftLeft' true m n + 1 = 1 := congr_arg (· + 1) s0 + rw [shiftLeft'_tt_eq_mul_pow] at this + obtain rfl := succ.inj (eq_one_of_dvd_one ⟨_, this.symm⟩) + simp only [zero_add, one_mul] at this + obtain rfl : n = 0 := not_ne_iff.1 fun hn ↦ ne_of_gt (Nat.one_lt_pow hn (by decide)) this + rw [add_zero] -- TODO: decide whether `Nat.shiftLeft_eq` (which rewrites the LHS into a power) should be a simp -- lemma; it was not in mathlib3. Until then, tell the simpNF linter to ignore the issue. @@ -99,9 +100,10 @@ theorem size_le {m n : ℕ} : size m ≤ n ↔ m < 2 ^ n := by_cases e : bit b m = 0 · simp [e] rw [size_bit e] - cases' n with n - · exact e.elim (Nat.eq_zero_of_le_zero (le_of_lt_succ h)) - · apply succ_le_succ (IH _) + cases n with + | zero => exact e.elim (Nat.eq_zero_of_le_zero (le_of_lt_succ h)) + | succ n => + apply succ_le_succ (IH _) apply Nat.lt_of_mul_lt_mul_left (a := 2) simp only [shiftLeft_succ] at * refine lt_of_le_of_lt ?_ h @@ -123,9 +125,11 @@ theorem size_le_size {m n : ℕ} (h : m ≤ n) : size m ≤ size n := size_le.2 <| lt_of_le_of_lt h (lt_size_self _) theorem size_eq_bits_len (n : ℕ) : n.bits.length = n.size := by - induction' n using Nat.binaryRec' with b n h ih; · simp - rw [size_bit, bits_append_bit _ _ h] - · simp [ih] - · simpa [bit_eq_zero_iff] + induction n using Nat.binaryRec' with + | z => simp + | f _ _ h ih => + rw [size_bit, bits_append_bit _ _ h] + · simp [ih] + · simpa [bit_eq_zero_iff] end Nat diff --git a/Mathlib/Data/Nat/Sqrt.lean b/Mathlib/Data/Nat/Sqrt.lean new file mode 100644 index 0000000000000..d5ebe7765840f --- /dev/null +++ b/Mathlib/Data/Nat/Sqrt.lean @@ -0,0 +1,210 @@ +/- +Copyright (c) 2014 Floris van Doorn (c) 2016 Microsoft Corporation. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Floris van Doorn, Leonardo de Moura, Jeremy Avigad, Mario Carneiro +-/ +import Mathlib.Data.Nat.Defs +import Batteries.Data.Nat.Basic + +/-! +# Properties of the natural number square root function. +-/ + +namespace Nat + +/- We don't want to import the algebraic hierarchy in this file. -/ +assert_not_exists Monoid + +variable {m n a : ℕ} + +/-! +### `sqrt` + +See [Wikipedia, *Methods of computing square roots*] +(https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Binary_numeral_system_(base_2)). +-/ + +private lemma iter_fp_bound (n k : ℕ) : + let iter_next (n guess : ℕ) := (guess + n / guess) / 2; + sqrt.iter n k ≤ iter_next n (sqrt.iter n k) := by + intro iter_next + unfold sqrt.iter + if h : (k + n / k) / 2 < k then + simpa [if_pos h] using iter_fp_bound _ _ + else + simpa [if_neg h] using Nat.le_of_not_lt h + +private lemma AM_GM : {a b : ℕ} → (4 * a * b ≤ (a + b) * (a + b)) + | 0, _ => by rw [Nat.mul_zero, Nat.zero_mul]; exact zero_le _ + | _, 0 => by rw [Nat.mul_zero]; exact zero_le _ + | a + 1, b + 1 => by + simpa only [Nat.mul_add, Nat.add_mul, show (4 : ℕ) = 1 + 1 + 1 + 1 from rfl, Nat.one_mul, + Nat.mul_one, Nat.add_assoc, Nat.add_left_comm, Nat.add_le_add_iff_left] + using Nat.add_le_add_right (@AM_GM a b) 4 + +-- These two lemmas seem like they belong to `Batteries.Data.Nat.Basic`. + +lemma sqrt.iter_sq_le (n guess : ℕ) : sqrt.iter n guess * sqrt.iter n guess ≤ n := by + unfold sqrt.iter + let next := (guess + n / guess) / 2 + if h : next < guess then + simpa only [dif_pos h] using sqrt.iter_sq_le n next + else + simp only [dif_neg h] + apply Nat.mul_le_of_le_div + apply Nat.le_of_add_le_add_left (a := guess) + rw [← Nat.mul_two, ← le_div_iff_mul_le] + · exact Nat.le_of_not_lt h + · exact Nat.zero_lt_two + +lemma sqrt.lt_iter_succ_sq (n guess : ℕ) (hn : n < (guess + 1) * (guess + 1)) : + n < (sqrt.iter n guess + 1) * (sqrt.iter n guess + 1) := by + unfold sqrt.iter + -- m was `next` + let m := (guess + n / guess) / 2 + dsimp + split_ifs with h + · suffices n < (m + 1) * (m + 1) by + simpa only [dif_pos h] using sqrt.lt_iter_succ_sq n m this + refine Nat.lt_of_mul_lt_mul_left ?_ (a := 4 * (guess * guess)) + apply Nat.lt_of_le_of_lt AM_GM + rw [show (4 : ℕ) = 2 * 2 from rfl] + rw [Nat.mul_mul_mul_comm 2, Nat.mul_mul_mul_comm (2 * guess)] + refine Nat.mul_self_lt_mul_self (?_ : _ < _ * ((_ / 2) + 1)) + rw [← add_div_right _ (by decide), Nat.mul_comm 2, Nat.mul_assoc, + show guess + n / guess + 2 = (guess + n / guess + 1) + 1 from rfl] + have aux_lemma {a : ℕ} : a ≤ 2 * ((a + 1) / 2) := by omega + refine lt_of_lt_of_le ?_ (Nat.mul_le_mul_left _ aux_lemma) + rw [Nat.add_assoc, Nat.mul_add] + exact Nat.add_lt_add_left (lt_mul_div_succ _ (lt_of_le_of_lt (Nat.zero_le m) h)) _ + · simpa only [dif_neg h] using hn +-- Porting note: the implementation of `Nat.sqrt` in `Batteries` no longer needs `sqrt_aux`. +private def IsSqrt (n q : ℕ) : Prop := + q * q ≤ n ∧ n < (q + 1) * (q + 1) +-- Porting note: as the definition of square root has changed, +-- the proof of `sqrt_isSqrt` is attempted from scratch. +/- +Sketch of proof: +Up to rounding, in terms of the definition of `sqrt.iter`, + +* By AM-GM inequality, `next² ≥ n` giving one of the bounds. +* When we terminated, we have `guess ≥ next` from which we deduce the other bound `n ≥ next²`. + +To turn this into a lean proof we need to manipulate, use properties of natural number division etc. +-/ +private lemma sqrt_isSqrt (n : ℕ) : IsSqrt n (sqrt n) := by + match n with + | 0 => simp [IsSqrt, sqrt] + | 1 => simp [IsSqrt, sqrt] + | n + 2 => + have h : ¬ (n + 2) ≤ 1 := by simp + simp only [IsSqrt, sqrt, h, ite_false] + refine ⟨sqrt.iter_sq_le _ _, sqrt.lt_iter_succ_sq _ _ ?_⟩ + simp only [Nat.mul_add, Nat.add_mul, Nat.one_mul, Nat.mul_one, ← Nat.add_assoc] + rw [Nat.lt_add_one_iff, Nat.add_assoc, ← Nat.mul_two] + refine le_trans (Nat.le_of_eq (div_add_mod' (n + 2) 2).symm) ?_ + rw [Nat.add_comm, Nat.add_le_add_iff_right, add_mod_right] + simp only [Nat.zero_lt_two, add_div_right, succ_mul_succ] + refine le_trans (b := 1) ?_ ?_ + · exact (lt_succ.1 <| mod_lt n Nat.zero_lt_two) + · exact Nat.le_add_left _ _ + +lemma sqrt_le (n : ℕ) : sqrt n * sqrt n ≤ n := (sqrt_isSqrt n).left + +lemma sqrt_le' (n : ℕ) : sqrt n ^ 2 ≤ n := by simpa [Nat.pow_two] using sqrt_le n + +lemma lt_succ_sqrt (n : ℕ) : n < succ (sqrt n) * succ (sqrt n) := (sqrt_isSqrt n).right + +lemma lt_succ_sqrt' (n : ℕ) : n < succ (sqrt n) ^ 2 := by simpa [Nat.pow_two] using lt_succ_sqrt n + +lemma sqrt_le_add (n : ℕ) : n ≤ sqrt n * sqrt n + sqrt n + sqrt n := by + rw [← succ_mul]; exact le_of_lt_succ (lt_succ_sqrt n) + +lemma le_sqrt : m ≤ sqrt n ↔ m * m ≤ n := + ⟨fun h ↦ le_trans (mul_self_le_mul_self h) (sqrt_le n), + fun h ↦ le_of_lt_succ <| Nat.mul_self_lt_mul_self_iff.1 <| lt_of_le_of_lt h (lt_succ_sqrt n)⟩ + +lemma le_sqrt' : m ≤ sqrt n ↔ m ^ 2 ≤ n := by simpa only [Nat.pow_two] using le_sqrt + +lemma sqrt_lt : sqrt m < n ↔ m < n * n := by simp only [← not_le, le_sqrt] + +lemma sqrt_lt' : sqrt m < n ↔ m < n ^ 2 := by simp only [← not_le, le_sqrt'] + +lemma sqrt_le_self (n : ℕ) : sqrt n ≤ n := le_trans (le_mul_self _) (sqrt_le n) + +lemma sqrt_le_sqrt (h : m ≤ n) : sqrt m ≤ sqrt n := le_sqrt.2 (le_trans (sqrt_le _) h) + +@[simp] lemma sqrt_zero : sqrt 0 = 0 := rfl + +@[simp] lemma sqrt_one : sqrt 1 = 1 := rfl + +lemma sqrt_eq_zero : sqrt n = 0 ↔ n = 0 := + ⟨fun h ↦ + Nat.eq_zero_of_le_zero <| le_of_lt_succ <| (@sqrt_lt n 1).1 <| by rw [h]; decide, + by rintro rfl; simp⟩ + +lemma eq_sqrt : a = sqrt n ↔ a * a ≤ n ∧ n < (a + 1) * (a + 1) := + ⟨fun e ↦ e.symm ▸ sqrt_isSqrt n, + fun ⟨h₁, h₂⟩ ↦ le_antisymm (le_sqrt.2 h₁) (le_of_lt_succ <| sqrt_lt.2 h₂)⟩ + +lemma eq_sqrt' : a = sqrt n ↔ a ^ 2 ≤ n ∧ n < (a + 1) ^ 2 := by + simpa only [Nat.pow_two] using eq_sqrt + +lemma le_three_of_sqrt_eq_one (h : sqrt n = 1) : n ≤ 3 := + le_of_lt_succ <| (@sqrt_lt n 2).1 <| by rw [h]; decide + +lemma sqrt_lt_self (h : 1 < n) : sqrt n < n := + sqrt_lt.2 <| by have := Nat.mul_lt_mul_of_pos_left h (lt_of_succ_lt h); rwa [Nat.mul_one] at this + +lemma sqrt_pos : 0 < sqrt n ↔ 0 < n := + le_sqrt + +lemma sqrt_add_eq (n : ℕ) (h : a ≤ n + n) : sqrt (n * n + a) = n := + le_antisymm + (le_of_lt_succ <| + sqrt_lt.2 <| by + rw [succ_mul, mul_succ, add_succ, Nat.add_assoc] + exact lt_succ_of_le (Nat.add_le_add_left h _)) + (le_sqrt.2 <| Nat.le_add_right _ _) + +lemma sqrt_add_eq' (n : ℕ) (h : a ≤ n + n) : sqrt (n ^ 2 + a) = n := by + simpa [Nat.pow_two] using sqrt_add_eq n h + +lemma sqrt_eq (n : ℕ) : sqrt (n * n) = n := sqrt_add_eq n (zero_le _) + +lemma sqrt_eq' (n : ℕ) : sqrt (n ^ 2) = n := sqrt_add_eq' n (zero_le _) + +lemma sqrt_succ_le_succ_sqrt (n : ℕ) : sqrt n.succ ≤ n.sqrt.succ := + le_of_lt_succ <| sqrt_lt.2 <| lt_succ_of_le <| + succ_le_succ <| le_trans (sqrt_le_add n) <| Nat.add_le_add_right + (by refine add_le_add (Nat.mul_le_mul_right _ ?_) ?_ <;> exact Nat.le_add_right _ 2) _ + +lemma exists_mul_self (x : ℕ) : (∃ n, n * n = x) ↔ sqrt x * sqrt x = x := + ⟨fun ⟨n, hn⟩ ↦ by rw [← hn, sqrt_eq], fun h ↦ ⟨sqrt x, h⟩⟩ + +lemma exists_mul_self' (x : ℕ) : (∃ n, n ^ 2 = x) ↔ sqrt x ^ 2 = x := by + simpa only [Nat.pow_two] using exists_mul_self x + +lemma sqrt_mul_sqrt_lt_succ (n : ℕ) : sqrt n * sqrt n < n + 1 := + Nat.lt_succ_iff.mpr (sqrt_le _) + +lemma sqrt_mul_sqrt_lt_succ' (n : ℕ) : sqrt n ^ 2 < n + 1 := + Nat.lt_succ_iff.mpr (sqrt_le' _) + +lemma succ_le_succ_sqrt (n : ℕ) : n + 1 ≤ (sqrt n + 1) * (sqrt n + 1) := + le_of_pred_lt (lt_succ_sqrt _) + +lemma succ_le_succ_sqrt' (n : ℕ) : n + 1 ≤ (sqrt n + 1) ^ 2 := + le_of_pred_lt (lt_succ_sqrt' _) + +/-- There are no perfect squares strictly between m² and (m+1)² -/ +lemma not_exists_sq (hl : m * m < n) (hr : n < (m + 1) * (m + 1)) : ¬∃ t, t * t = n := by + rintro ⟨t, rfl⟩ + have h1 : m < t := Nat.mul_self_lt_mul_self_iff.1 hl + have h2 : t < m + 1 := Nat.mul_self_lt_mul_self_iff.1 hr + exact (not_lt_of_ge <| le_of_lt_succ h2) h1 + +lemma not_exists_sq' : m ^ 2 < n → n < (m + 1) ^ 2 → ¬∃ t, t ^ 2 = n := by + simpa only [Nat.pow_two] using not_exists_sq + +end Nat diff --git a/Mathlib/Data/Nat/Squarefree.lean b/Mathlib/Data/Nat/Squarefree.lean index 4f5bc89c79f72..8e5ebe1de87d1 100644 --- a/Mathlib/Data/Nat/Squarefree.lean +++ b/Mathlib/Data/Nat/Squarefree.lean @@ -87,7 +87,7 @@ theorem Squarefree.ext_iff {n m : ℕ} (hn : Squarefree n) (hm : Squarefree m) : · rwa [h₂, eq_comm, ← h₁] · rw [h₂, h₃.resolve_left] rw [← h₁, h₂] - simp only [Nat.one_ne_zero, not_false_iff] + simp only [Nat.one_ne_zero, not_false_iff, reduceCtorEq] rw [factorization_eq_zero_of_non_prime _ hp, factorization_eq_zero_of_non_prime _ hp] theorem squarefree_pow_iff {n k : ℕ} (hn : n ≠ 1) (hk : k ≠ 0) : diff --git a/Mathlib/Data/Nat/SuccPred.lean b/Mathlib/Data/Nat/SuccPred.lean index 262d0f7f1138c..ba369b1c0fb26 100644 --- a/Mathlib/Data/Nat/SuccPred.lean +++ b/Mathlib/Data/Nat/SuccPred.lean @@ -35,10 +35,6 @@ variable {m n : ℕ} cases b · exact (a.not_lt_zero h).elim · exact le_of_succ_le_succ h - le_of_pred_lt {a} {b} h := by - cases a - · exact b.zero_le - · exact h @[simp] theorem succ_eq_succ : Order.succ = succ := diff --git a/Mathlib/Data/Nat/Totient.lean b/Mathlib/Data/Nat/Totient.lean index 938f58268c44a..5602a10425923 100644 --- a/Mathlib/Data/Nat/Totient.lean +++ b/Mathlib/Data/Nat/Totient.lean @@ -8,6 +8,7 @@ import Mathlib.Data.Nat.Factorization.Basic import Mathlib.Data.Nat.Factorization.Induction import Mathlib.Data.Nat.Periodic import Mathlib.Data.ZMod.Basic +import Mathlib.NumberTheory.Divisors /-! # Euler's totient function diff --git a/Mathlib/Data/Nat/Upto.lean b/Mathlib/Data/Nat/Upto.lean index 47b6802fa1c14..f62ea9e9062d1 100644 --- a/Mathlib/Data/Nat/Upto.lean +++ b/Mathlib/Data/Nat/Upto.lean @@ -28,7 +28,7 @@ no `j` less than `i` satisfies `p`. This is an initial segment of the natural numbers, up to and including the first value satisfying `p`. We will be particularly interested in the case where there exists a value -satisfying `p`, because in this case the `>` relation is well-founded. -/ +satisfying `p`, because in this case the `>` relation is well-founded. -/ abbrev Upto (p : ℕ → Prop) : Type := { i : ℕ // ∀ j < i, ¬p j } diff --git a/Mathlib/Data/Num/Lemmas.lean b/Mathlib/Data/Num/Lemmas.lean index c3669ef62772a..ac946c8f455bc 100644 --- a/Mathlib/Data/Num/Lemmas.lean +++ b/Mathlib/Data/Num/Lemmas.lean @@ -1576,3 +1576,5 @@ instance SNum.lt : LT SNum := instance SNum.le : LE SNum := ⟨fun a b => (a : ℤ) ≤ b⟩ + +set_option linter.style.longFile 1700 diff --git a/Mathlib/Data/Option/Basic.lean b/Mathlib/Data/Option/Basic.lean index 533abe5270de7..138ba4471da95 100644 --- a/Mathlib/Data/Option/Basic.lean +++ b/Mathlib/Data/Option/Basic.lean @@ -194,16 +194,14 @@ theorem pbind_eq_none {f : ∀ a : α, a ∈ x → Option β} (h' : ∀ a (H : a ∈ x), f a H = none → x = none) : x.pbind f = none ↔ x = none := by cases x · simp - · simp only [pbind, iff_false] + · simp only [pbind, iff_false, reduceCtorEq] intro h cases h' _ rfl h theorem pbind_eq_some {f : ∀ a : α, a ∈ x → Option β} {y : β} : x.pbind f = some y ↔ ∃ (z : α) (H : z ∈ x), f z H = some y := by rcases x with (_|x) - · simp only [pbind, false_iff, not_exists] - intro z h - simp at h + · simp · simp only [pbind] refine ⟨fun h ↦ ⟨x, rfl, h⟩, ?_⟩ rintro ⟨z, H, hz⟩ @@ -219,7 +217,7 @@ theorem pmap_eq_none_iff {h} : pmap f x h = none ↔ x = none := by cases x <;> 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] + · 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 @@ -253,11 +251,6 @@ theorem orElse_none' (x : Option α) : x.orElse (fun _ ↦ none) = x := by cases theorem exists_ne_none {p : Option α → Prop} : (∃ x ≠ none, p x) ↔ (∃ x : α, p x) := by simp only [← exists_prop, bex_ne_none] -@[simp] -theorem get_map (f : α → β) {o : Option α} (h : isSome (o.map f)) : - (o.map f).get h = f (o.get (by rwa [← isSome_map'])) := by - cases o <;> [simp at h; rfl] - theorem iget_mem [Inhabited α] : ∀ {o : Option α}, isSome o → o.iget ∈ o | some _, _ => rfl @@ -311,8 +304,8 @@ compile_inductive% Option theorem orElse_eq_some (o o' : Option α) (x : α) : (o <|> o') = some x ↔ o = some x ∨ o = none ∧ o' = some x := by cases o - · simp only [true_and, false_or, eq_self_iff_true, none_orElse] - · simp only [some_orElse, or_false, false_and] + · simp only [true_and, false_or, eq_self_iff_true, none_orElse, reduceCtorEq] + · simp only [some_orElse, or_false, false_and, reduceCtorEq] theorem orElse_eq_some' (o o' : Option α) (x : α) : @@ -323,7 +316,7 @@ theorem orElse_eq_some' (o o' : Option α) (x : α) : theorem orElse_eq_none (o o' : Option α) : (o <|> o') = none ↔ o = none ∧ o' = none := by cases o · simp only [true_and, none_orElse, eq_self_iff_true] - · simp only [some_orElse, false_and] + · simp only [some_orElse, reduceCtorEq, false_and] @[simp] theorem orElse_eq_none' (o o' : Option α) : o.orElse (fun _ ↦ o') = none ↔ o = none ∧ o' = none := diff --git a/Mathlib/Data/Ordering/Lemmas.lean b/Mathlib/Data/Ordering/Lemmas.lean index 2fd0f777cc70d..7b9714aa85ed5 100644 --- a/Mathlib/Data/Ordering/Lemmas.lean +++ b/Mathlib/Data/Ordering/Lemmas.lean @@ -3,8 +3,8 @@ Copyright (c) 2017 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Leonardo de Moura -/ -import Mathlib.Init.Algebra.Classes import Mathlib.Data.Ordering.Basic +import Mathlib.Order.Defs /-! # Some `Ordering` lemmas @@ -39,12 +39,12 @@ attribute [local simp] cmpUsing @[simp] theorem cmpUsing_eq_lt (a b : α) : (cmpUsing lt a b = Ordering.lt) = lt a b := by - simp only [cmpUsing, Ordering.ite_eq_lt_distrib, ite_self, if_false_right, and_true] + simp only [cmpUsing, Ordering.ite_eq_lt_distrib, ite_self, if_false_right, and_true, reduceCtorEq] @[simp] theorem cmpUsing_eq_gt [IsStrictOrder α lt] (a b : α) : cmpUsing lt a b = Ordering.gt ↔ lt b a := by simp only [cmpUsing, Ordering.ite_eq_gt_distrib, if_false_right, and_true, if_false_left, - and_iff_right_iff_imp] + and_iff_right_iff_imp, reduceCtorEq] exact fun hba hab ↦ (irrefl a) (_root_.trans hab hba) @[simp] diff --git a/Mathlib/Data/Ordmap/Ordnode.lean b/Mathlib/Data/Ordmap/Ordnode.lean index b72b6d54b107b..0739a52acab99 100644 --- a/Mathlib/Data/Ordmap/Ordnode.lean +++ b/Mathlib/Data/Ordmap/Ordnode.lean @@ -183,27 +183,27 @@ O(1). Rebalance a tree which was previously balanced but has had its left side grow by 1, or its right side shrink by 1. -/ def balanceL (l : Ordnode α) (x : α) (r : Ordnode α) : Ordnode α := by -- Porting note: removed `clean` - cases' id r with rs - · cases' id l with ls ll lx lr + rcases id r with _ | rs + · rcases id l with _ | ⟨ls, ll, lx, lr⟩ · exact ι x - · cases' id ll with lls - · cases' lr with _ _ lrx + · rcases id ll with _ | lls + · rcases lr with _ | ⟨_, _, lrx⟩ · exact node 2 l x nil · exact node 3 (ι lx) lrx ι x - · cases' id lr with lrs lrl lrx lrr + · rcases id lr with _ | ⟨lrs, lrl, lrx, lrr⟩ · exact node 3 ll lx ι x · exact if lrs < ratio * lls then node (ls + 1) ll lx (node (lrs + 1) lr x nil) else node (ls + 1) (node (lls + size lrl + 1) ll lx lrl) lrx (node (size lrr + 1) lrr x nil) - · cases' id l with ls ll lx lr + · rcases id l with _ | ⟨ls, ll, lx, lr⟩ · exact node (rs + 1) nil x r · refine if ls > delta * rs then ?_ else node (ls + rs + 1) l x r - cases' id ll with lls + rcases id ll with _ | lls · exact nil --should not happen - cases' id lr with lrs lrl lrx lrr + rcases id lr with _ | ⟨lrs, lrl, lrx, lrr⟩ · exact nil --should not happen exact @@ -218,27 +218,27 @@ O(1). Rebalance a tree which was previously balanced but has had its right side grow by 1, or its left side shrink by 1. -/ def balanceR (l : Ordnode α) (x : α) (r : Ordnode α) : Ordnode α := by -- Porting note: removed `clean` - cases' id l with ls - · cases' id r with rs rl rx rr + rcases id l with _ | ls + · rcases id r with _ | ⟨rs, rl, rx, rr⟩ · exact ι x - · cases' id rr with rrs - · cases' rl with _ _ rlx + · rcases id rr with _ | rrs + · rcases rl with _ | ⟨_, _, rlx⟩ · exact node 2 nil x r · exact node 3 (ι x) rlx ι rx - · cases' id rl with rls rll rlx rlr + · rcases id rl with _ | ⟨rls, rll, rlx, rlr⟩ · exact node 3 (ι x) rx rr · exact if rls < ratio * rrs then node (rs + 1) (node (rls + 1) nil x rl) rx rr else node (rs + 1) (node (size rll + 1) nil x rll) rlx (node (size rlr + rrs + 1) rlr rx rr) - · cases' id r with rs rl rx rr + · rcases id r with _ | ⟨rs, rl, rx, rr⟩ · exact node (ls + 1) l x nil · refine if rs > delta * ls then ?_ else node (ls + rs + 1) l x r - cases' id rr with rrs + rcases id rr with _ | rrs · exact nil --should not happen - cases' id rl with rls rll rlx rlr + rcases id rl with _ | ⟨rls, rll, rlx, rlr⟩ · exact nil --should not happen exact @@ -253,26 +253,26 @@ O(1). Rebalance a tree which was previously balanced but has had one side change by at most 1. -/ def balance (l : Ordnode α) (x : α) (r : Ordnode α) : Ordnode α := by -- Porting note: removed `clean` - cases' id l with ls ll lx lr - · cases' id r with rs rl rx rr + rcases id l with _ | ⟨ls, ll, lx, lr⟩ + · rcases id r with _ | ⟨rs, rl, rx, rr⟩ · exact ι x - · cases' id rl with rls rll rlx rlr + · rcases id rl with _ | ⟨rls, rll, rlx, rlr⟩ · cases id rr · exact node 2 nil x r · exact node 3 (ι x) rx rr - · cases' id rr with rrs + · rcases id rr with _ | rrs · exact node 3 (ι x) rlx ι rx · exact if rls < ratio * rrs then node (rs + 1) (node (rls + 1) nil x rl) rx rr else node (rs + 1) (node (size rll + 1) nil x rll) rlx (node (size rlr + rrs + 1) rlr rx rr) - · cases' id r with rs rl rx rr - · cases' id ll with lls - · cases' lr with _ _ lrx + · rcases id r with _ | ⟨rs, rl, rx, rr⟩ + · rcases id ll with _ | lls + · rcases lr with _ | ⟨_, _, lrx⟩ · exact node 2 l x nil · exact node 3 (ι lx) lrx ι x - · cases' id lr with lrs lrl lrx lrr + · rcases id lr with _ | ⟨lrs, lrl, lrx, lrr⟩ · exact node 3 ll lx ι x · exact if lrs < ratio * lls then node (ls + 1) ll lx (node (lrs + 1) lr x nil) @@ -281,10 +281,10 @@ def balance (l : Ordnode α) (x : α) (r : Ordnode α) : Ordnode α := by (node (size lrr + 1) lrr x nil) · refine if delta * ls < rs then ?_ else if delta * rs < ls then ?_ else node (ls + rs + 1) l x r - · cases' id rl with rls rll rlx rlr + · rcases id rl with _ | ⟨rls, rll, rlx, rlr⟩ · exact nil --should not happen - cases' id rr with rrs + rcases id rr with _ | rrs · exact nil --should not happen exact @@ -292,10 +292,10 @@ def balance (l : Ordnode α) (x : α) (r : Ordnode α) : Ordnode α := by else node (ls + rs + 1) (node (ls + size rll + 1) l x rll) rlx (node (size rlr + rrs + 1) rlr rx rr) - · cases' id ll with lls + · rcases id ll with _ | lls · exact nil --should not happen - cases' id lr with lrs lrl lrx lrr + rcases id lr with _ | ⟨lrs, lrl, lrx, lrr⟩ · exact nil --should not happen exact @@ -845,7 +845,7 @@ def find (x : α) : Ordnode α → Option α | Ordering.gt => find x r instance : Membership α (Ordnode α) := - ⟨fun x t => t.mem x⟩ + ⟨fun t x => t.mem x⟩ instance mem.decidable (x : α) (t : Ordnode α) : Decidable (x ∈ t) := Bool.decEq _ _ diff --git a/Mathlib/Data/Ordmap/Ordset.lean b/Mathlib/Data/Ordmap/Ordset.lean index fc25de56b3862..d0706d174ec05 100644 --- a/Mathlib/Data/Ordmap/Ordset.lean +++ b/Mathlib/Data/Ordmap/Ordset.lean @@ -1556,7 +1556,7 @@ def find (x : α) (s : Ordset α) : Option α := Ordnode.find x s.val instance instMembership : Membership α (Ordset α) := - ⟨fun x s => mem x s⟩ + ⟨fun s x => mem x s⟩ instance mem.decidable (x : α) (s : Ordset α) : Decidable (x ∈ s) := instDecidableEqBool _ _ @@ -1578,3 +1578,5 @@ def map {β} [Preorder β] (f : α → β) (f_strict_mono : StrictMono f) (s : O ⟨Ordnode.map f s.val, Ordnode.map.valid f_strict_mono s.property⟩ end Ordset + +set_option linter.style.longFile 1700 diff --git a/Mathlib/Data/PEquiv.lean b/Mathlib/Data/PEquiv.lean index 539fbcf90563e..b80eb899c2f5e 100644 --- a/Mathlib/Data/PEquiv.lean +++ b/Mathlib/Data/PEquiv.lean @@ -118,7 +118,7 @@ theorem symm_refl : (PEquiv.refl α).symm = PEquiv.refl α := rfl @[simp] -theorem symm_symm (f : α ≃. β) : f.symm.symm = f := by cases f; rfl +theorem symm_symm (f : α ≃. β) : f.symm.symm = f := rfl theorem symm_bijective : Function.Bijective (PEquiv.symm : (α ≃. β) → β ≃. α) := Function.bijective_iff_has_inverse.mpr ⟨_, symm_symm, symm_symm⟩ @@ -201,7 +201,7 @@ theorem mem_ofSet_iff {s : Set α} [DecidablePred (· ∈ s)] {a b : α} : · simp only [mem_def, eq_comm, some.injEq, iff_self_and] rintro rfl exact h - · simp only [mem_def, false_iff, not_and] + · simp only [mem_def, false_iff, not_and, reduceCtorEq] rintro rfl exact h @@ -294,9 +294,9 @@ def single (a : α) (b : β) : dsimp only split_ifs with h1 h2 · simp [*] - · simp only [mem_def, some.injEq, iff_false] at * + · simp only [mem_def, some.injEq, iff_false, reduceCtorEq] at * exact Ne.symm h2 - · simp only [mem_def, some.injEq, false_iff] at * + · simp only [mem_def, some.injEq, false_iff, reduceCtorEq] at * exact Ne.symm h1 · simp @@ -343,7 +343,7 @@ theorem trans_single_of_eq_none {b : β} (c : γ) {f : δ ≃. β} (h : f.symm b ext simp only [eq_none_iff_forall_not_mem, Option.mem_def, f.eq_some_iff] at h dsimp [PEquiv.trans, single] - simp only [mem_def, bind_eq_some, iff_false, not_exists, not_and] + simp only [mem_def, bind_eq_some, iff_false, not_exists, not_and, reduceCtorEq] intros split_ifs <;> simp_all @@ -367,7 +367,7 @@ instance instPartialOrderPEquiv : PartialOrder (α ≃. β) where ext (by intro a - cases' h : g a with b + rcases h : g a with _ | b · exact eq_none_iff_forall_not_mem.2 fun b hb => Option.not_mem_none b <| h ▸ fg a b hb · exact gf _ _ h) diff --git a/Mathlib/Data/PFun.lean b/Mathlib/Data/PFun.lean index 3e342591b8463..376018c747f3e 100644 --- a/Mathlib/Data/PFun.lean +++ b/Mathlib/Data/PFun.lean @@ -58,7 +58,7 @@ open Function def PFun (α β : Type*) := α → Part β -/-- `α →. β` is notation for the type `PFun α β` of partial functions from `α` to `β`. -/ +/-- `α →. β` is notation for the type `PFun α β` of partial functions from `α` to `β`. -/ infixr:25 " →. " => PFun namespace PFun @@ -286,7 +286,7 @@ def fixInduction {C : α → Sort*} {f : α →. β ⊕ α} {b : β} {a : α} (h have h₂ := (Part.mem_assert_iff.1 h).snd generalize_proofs at h₂ clear h - induction' ‹Acc _ _› with a ha IH + induction ‹Acc _ _› with | intro a ha IH => _ have h : b ∈ f.fix a := Part.mem_assert_iff.2 ⟨⟨a, ha⟩, h₂⟩ exact H a h fun a' fa' => IH a' fa' (Part.mem_assert_iff.1 (fix_fwd h fa')).snd @@ -545,7 +545,7 @@ theorem mem_prodLift {f : α →. β} {g : α →. γ} {x : α} {y : β × γ} : trans ∃ hp hq, (f x).get hp = y.1 ∧ (g x).get hq = y.2 · simp only [prodLift, Part.mem_mk_iff, And.exists, Prod.ext_iff] -- Porting note: was just `[exists_and_left, exists_and_right]` - · simp only [exists_and_left, exists_and_right, (· ∈ ·), Part.Mem] + · simp only [exists_and_left, exists_and_right, Membership.mem, Part.Mem] /-- Product of partial functions. -/ def prodMap (f : α →. γ) (g : β →. δ) : α × β →. γ × δ := fun x => @@ -569,7 +569,7 @@ theorem mem_prodMap {f : α →. γ} {g : β →. δ} {x : α × β} {y : γ × y ∈ f.prodMap g x ↔ y.1 ∈ f x.1 ∧ y.2 ∈ g x.2 := by trans ∃ hp hq, (f x.1).get hp = y.1 ∧ (g x.2).get hq = y.2 · simp only [prodMap, Part.mem_mk_iff, And.exists, Prod.ext_iff] - · simp only [exists_and_left, exists_and_right, (· ∈ ·), Part.Mem] + · simp only [exists_and_left, exists_and_right, Membership.mem, Part.Mem] @[simp] theorem prodLift_fst_comp_snd_comp (f : α →. γ) (g : β →. δ) : diff --git a/Mathlib/Data/PFunctor/Multivariate/M.lean b/Mathlib/Data/PFunctor/Multivariate/M.lean index 8a40846b7c6fc..cb6ed15fd11ac 100644 --- a/Mathlib/Data/PFunctor/Multivariate/M.lean +++ b/Mathlib/Data/PFunctor/Multivariate/M.lean @@ -58,7 +58,7 @@ variable {n : ℕ} (P : MvPFunctor.{u} (n + 1)) /-- A path from the root of a tree to one of its node -/ inductive M.Path : P.last.M → Fin2 n → Type u - | root (x : P.last.M) + | root (x : P.last.M) (a : P.A) (f : P.last.B a → P.last.M) (h : PFunctor.M.dest x = ⟨a, f⟩) @@ -268,21 +268,21 @@ theorem M.bisim₀ {α : TypeVec n} (R : P.M α → P.M α → Prop) (h₀ : Equ intro i replace h₁ := congr_fun (congr_fun h₁ Fin2.fz) i simp only [TypeVec.comp, appendFun, splitFun] at h₁ - replace h₁ := Quot.exact _ h₁ + replace h₁ := Quot.eqvGen_exact h₁ rw [h₀.eqvGen_iff] at h₁ exact h₁ theorem M.bisim' {α : TypeVec n} (R : P.M α → P.M α → Prop) (h : ∀ x y, R x y → (id ::: Quot.mk R) <$$> M.dest _ x = (id ::: Quot.mk R) <$$> M.dest _ y) (x y) (r : R x y) : x = y := by - have := M.bisim₀ P (EqvGen R) ?_ ?_ - · solve_by_elim [EqvGen.rel] - · apply EqvGen.is_equivalence + have := M.bisim₀ P (Relation.EqvGen R) ?_ ?_ + · solve_by_elim [Relation.EqvGen.rel] + · apply Relation.EqvGen.is_equivalence · clear r x y introv Hr - have : ∀ x y, R x y → EqvGen R x y := @EqvGen.rel _ R + have : ∀ x y, R x y → Relation.EqvGen R x y := @Relation.EqvGen.rel _ R induction Hr - · rw [← Quot.factor_mk_eq R (EqvGen R) this] + · rw [← Quot.factor_mk_eq R (Relation.EqvGen R) this] rwa [appendFun_comp_id, ← MvFunctor.map_map, ← MvFunctor.map_map, h] all_goals aesop diff --git a/Mathlib/Data/PFunctor/Multivariate/W.lean b/Mathlib/Data/PFunctor/Multivariate/W.lean index 449da825496bd..369a12fd42178 100644 --- a/Mathlib/Data/PFunctor/Multivariate/W.lean +++ b/Mathlib/Data/PFunctor/Multivariate/W.lean @@ -169,7 +169,7 @@ theorem wRec_eq {α : TypeVec n} {C : Type*} (g : ∀ a : P.A, P.drop.B a ⟹ α → (P.last.B a → P.W α) → (P.last.B a → C) → C) (a : P.A) (f' : P.drop.B a ⟹ α) (f : P.last.B a → P.W α) : P.wRec g (P.wMk a f' f) = g a f' f fun i => P.wRec g (f i) := by - rw [wMk, wRec]; dsimp; rw [wpRec_eq] + rw [wMk, wRec]; rw [wpRec_eq] dsimp only [wPathDestLeft_wPathCasesOn, wPathDestRight_wPathCasesOn] congr diff --git a/Mathlib/Data/PFunctor/Univariate/M.lean b/Mathlib/Data/PFunctor/Univariate/M.lean index f0339ae9be2d7..f3eb8596e529a 100644 --- a/Mathlib/Data/PFunctor/Univariate/M.lean +++ b/Mathlib/Data/PFunctor/Univariate/M.lean @@ -91,7 +91,7 @@ theorem truncate_eq_of_agree {n : ℕ} (x : CofixA F n) (y : CofixA F (succ n)) · rfl · -- cases' h with _ _ _ _ _ h₀ h₁ cases h - simp only [truncate, Function.comp, true_and_iff, eq_self_iff_true, heq_iff_eq] + simp only [truncate, Function.comp_def, true_and_iff, eq_self_iff_true, heq_iff_eq] -- Porting note: used to be `ext y` rename_i n_ih a f y h₁ suffices (fun x => truncate (y x)) = f @@ -281,9 +281,7 @@ theorem mk_dest (x : M F) : M.mk (dest x) = x := by cases' h : x.approx (succ n) with _ hd ch have h' : hd = head' (x.approx 1) := by rw [← head_succ' n, h, head'] - · split - injections - · apply x.consistent + apply x.consistent revert ch rw [h'] intros ch h diff --git a/Mathlib/Data/PNat/Defs.lean b/Mathlib/Data/PNat/Defs.lean index beb992780ee62..3004d33fc9df7 100644 --- a/Mathlib/Data/PNat/Defs.lean +++ b/Mathlib/Data/PNat/Defs.lean @@ -6,9 +6,10 @@ Authors: Mario Carneiro, Neil Strickland import Mathlib.Algebra.NeZero import Mathlib.Data.Nat.Defs import Mathlib.Order.Basic +import Mathlib.Order.TypeTags import Mathlib.Tactic.Coe import Mathlib.Tactic.Lift -import Mathlib.Init.Data.Int.Order +import Mathlib.Data.Int.Order.Basic /-! # The positive natural numbers @@ -17,29 +18,11 @@ This file contains the definitions, and basic results. Most algebraic facts are deferred to `Data.PNat.Basic`, as they need more imports. -/ - -/-- `ℕ+` is the type of positive natural numbers. It is defined as a subtype, - and the VM representation of `ℕ+` is the same as `ℕ` because the proof - is not stored. -/ -def PNat := { n : ℕ // 0 < n } - deriving DecidableEq, LinearOrder - -@[inherit_doc] -notation "ℕ+" => PNat +deriving instance LinearOrder for PNat instance : One ℕ+ := ⟨⟨1, Nat.zero_lt_one⟩⟩ -/-- The underlying natural number -/ -@[coe] -def PNat.val : ℕ+ → ℕ := Subtype.val - -instance coePNatNat : Coe ℕ+ ℕ := - ⟨PNat.val⟩ - -instance : Repr ℕ+ := - ⟨fun n n' => reprPrec n.1 n'⟩ - instance (n : ℕ) [NeZero n] : OfNat ℕ+ n := ⟨⟨n, Nat.pos_of_ne_zero <| NeZero.ne n⟩⟩ diff --git a/Mathlib/Data/PNat/Xgcd.lean b/Mathlib/Data/PNat/Xgcd.lean index 03c2d2cb0227d..f5c3a61a1fe5f 100644 --- a/Mathlib/Data/PNat/Xgcd.lean +++ b/Mathlib/Data/PNat/Xgcd.lean @@ -202,7 +202,7 @@ theorem flip_v : (flip u).v = u.v.swap := by · simp only ring -/-- Properties of division with remainder for a / b. -/ +/-- Properties of division with remainder for a / b. -/ theorem rq_eq : u.r + (u.bp + 1) * u.q = u.ap + 1 := Nat.mod_add_div (u.ap + 1) (u.bp + 1) diff --git a/Mathlib/Data/Part.lean b/Mathlib/Data/Part.lean index cdbd018a1d088..c4903f9bf5b4a 100644 --- a/Mathlib/Data/Part.lean +++ b/Mathlib/Data/Part.lean @@ -81,7 +81,7 @@ theorem eta : ∀ o : Part α, (⟨o.Dom, fun h => o.get h⟩ : Part α) = o | ⟨_, _⟩ => rfl /-- `a ∈ o` means that `o` is defined and equal to `a` -/ -protected def Mem (a : α) (o : Part α) : Prop := +protected def Mem (o : Part α) (a : α) : Prop := ∃ h, o.get h = a instance : Membership α (Part α) := diff --git a/Mathlib/Data/Prod/Basic.lean b/Mathlib/Data/Prod/Basic.lean index c13f7a9e55f7b..f30532075537d 100644 --- a/Mathlib/Data/Prod/Basic.lean +++ b/Mathlib/Data/Prod/Basic.lean @@ -28,14 +28,6 @@ def mk.injArrow {x₁ : α} {y₁ : β} {x₂ : α} {y₂ : β} : theorem mk.eta : ∀ {p : α × β}, (p.1, p.2) = p | (_, _) => rfl -@[simp] -theorem «forall» {p : α × β → Prop} : (∀ x, p x) ↔ ∀ a b, p (a, b) := - ⟨fun h a b ↦ h (a, b), fun h ⟨a, b⟩ ↦ h a b⟩ - -@[simp] -theorem «exists» {p : α × β → Prop} : (∃ x, p x) ↔ ∃ a b, p (a, b) := - ⟨fun ⟨⟨a, b⟩, h⟩ ↦ ⟨a, b, h⟩, fun ⟨a, b, h⟩ ↦ ⟨⟨a, b⟩, h⟩⟩ - theorem forall' {p : α → β → Prop} : (∀ x : α × β, p x.1 x.2) ↔ ∀ a b, p a b := Prod.forall @@ -179,6 +171,10 @@ is equal to the composition of `Prod.swap` with `Prod.map g f`.-/ theorem map_comp_swap (f : α → β) (g : γ → δ) : Prod.map f g ∘ Prod.swap = Prod.swap ∘ Prod.map g f := rfl +theorem _root_.Function.Semiconj.swap_map (f : α → α) (g : β → β) : + Function.Semiconj swap (map f g) (map g f) := + Function.semiconj_iff_comp_eq.2 (map_comp_swap g f).symm + theorem eq_iff_fst_eq_snd_eq : ∀ {p q : α × β}, p = q ↔ p.1 = q.1 ∧ p.2 = q.2 | ⟨p₁, p₂⟩, ⟨q₁, q₂⟩ => by simp diff --git a/Mathlib/Data/Prod/Lex.lean b/Mathlib/Data/Prod/Lex.lean index d0d7a66835728..f55eac2c324de 100644 --- a/Mathlib/Data/Prod/Lex.lean +++ b/Mathlib/Data/Prod/Lex.lean @@ -41,7 +41,7 @@ instance decidableEq (α β : Type*) [DecidableEq α] [DecidableEq β] : Decidab instance inhabited (α β : Type*) [Inhabited α] [Inhabited β] : Inhabited (α ×ₗ β) := instInhabitedProd -/-- Dictionary / lexicographic ordering on pairs. -/ +/-- Dictionary / lexicographic ordering on pairs. -/ instance instLE (α β : Type*) [LT α] [LE β] : LE (α ×ₗ β) where le := Prod.Lex (· < ·) (· ≤ ·) instance instLT (α β : Type*) [LT α] [LT β] : LT (α ×ₗ β) where lt := Prod.Lex (· < ·) (· < ·) @@ -118,12 +118,11 @@ theorem toLex_strictMono : StrictMono (toLex : α × β → α ×ₗ β) := by end Preorder /-- Dictionary / lexicographic partial order for pairs. -/ -instance partialOrder (α β : Type*) [PartialOrder α] [PartialOrder β] : PartialOrder (α ×ₗ β) := - { Prod.Lex.preorder α β with - le_antisymm := by - haveI : IsStrictOrder α (· < ·) := { irrefl := lt_irrefl, trans := fun _ _ _ => lt_trans } - haveI : IsAntisymm β (· ≤ ·) := ⟨fun _ _ => le_antisymm⟩ - exact @antisymm _ (Prod.Lex _ _) _ } +instance partialOrder (α β : Type*) [PartialOrder α] [PartialOrder β] : PartialOrder (α ×ₗ β) where + le_antisymm _ _ := by + haveI : IsStrictOrder α (· < ·) := { irrefl := lt_irrefl, trans := fun _ _ _ => lt_trans } + haveI : IsAntisymm β (· ≤ ·) := ⟨fun _ _ => le_antisymm⟩ + exact antisymm (r := Prod.Lex _ _) /-- Dictionary / lexicographic linear order for pairs. -/ instance linearOrder (α β : Type*) [LinearOrder α] [LinearOrder β] : LinearOrder (α ×ₗ β) := diff --git a/Mathlib/Data/QPF/Multivariate/Basic.lean b/Mathlib/Data/QPF/Multivariate/Basic.lean index a0d0fd66952f8..9c13a82349a20 100644 --- a/Mathlib/Data/QPF/Multivariate/Basic.lean +++ b/Mathlib/Data/QPF/Multivariate/Basic.lean @@ -69,7 +69,7 @@ matched because they preserve the properties of QPF. The latter example, each proves that some operations on functors preserves the QPF structure -/ -set_option linter.longLine false in +set_option linter.style.longLine false in /-! ## Reference diff --git a/Mathlib/Data/QPF/Multivariate/Constructions/Fix.lean b/Mathlib/Data/QPF/Multivariate/Constructions/Fix.lean index 7a6f0204617b0..284cbecc9b925 100644 --- a/Mathlib/Data/QPF/Multivariate/Constructions/Fix.lean +++ b/Mathlib/Data/QPF/Multivariate/Constructions/Fix.lean @@ -315,7 +315,7 @@ def Fix.drec {β : Fix F α → Type u} rhs rw [← ih] rw [MvFunctor.map_map, ← appendFun_comp, id_comp] - simp only [Function.comp] + simp only [Function.comp_def] cast (by rw [this]) y.2 end MvQPF diff --git a/Mathlib/Data/QPF/Univariate/Basic.lean b/Mathlib/Data/QPF/Univariate/Basic.lean index 3f3dbf6911b6b..b767d995bd81b 100644 --- a/Mathlib/Data/QPF/Univariate/Basic.lean +++ b/Mathlib/Data/QPF/Univariate/Basic.lean @@ -176,7 +176,7 @@ theorem recF_eq_of_Wequiv {α : Type u} (u : F α → α) (x y : q.P.W) : Wequiv x y → recF u x = recF u y := by intro h induction h with - | ind a f f' _ ih => simp only [recF_eq', PFunctor.map_eq, Function.comp, ih] + | ind a f f' _ ih => simp only [recF_eq', PFunctor.map_eq, Function.comp_def, ih] | abs a f a' f' h => simp only [recF_eq', abs_map, h] | trans x y z _ _ ih₁ ih₂ => exact Eq.trans ih₁ ih₂ diff --git a/Mathlib/Data/Quot.lean b/Mathlib/Data/Quot.lean index c78bf64552825..6af294f0b9665 100644 --- a/Mathlib/Data/Quot.lean +++ b/Mathlib/Data/Quot.lean @@ -3,8 +3,7 @@ Copyright (c) 2017 Johannes Hölzl. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl -/ -import Mathlib.Init.Data.Quot -import Mathlib.Logic.Relator +import Mathlib.Logic.Relation import Mathlib.Logic.Unique import Mathlib.Util.Notation3 @@ -46,6 +45,9 @@ instance (r : α → α → Prop) [Inhabited α] : Inhabited (Quot r) := protected instance Subsingleton [Subsingleton α] : Subsingleton (Quot ra) := ⟨fun x ↦ Quot.induction_on x fun _ ↦ Quot.ind fun _ ↦ congr_arg _ (Subsingleton.elim _ _)⟩ +@[deprecated (since := "2024-08-26")] alias recOn' := Quot.recOn +@[deprecated (since := "2024-08-26")] alias recOnSubsingleton' := Quot.recOnSubsingleton + instance [Unique α] : Unique (Quot ra) := Unique.mk' _ /-- Recursion on two `Quotient` arguments `a` and `b`, result type depends on `⟦a⟧` and `⟦b⟧`. -/ @@ -263,8 +265,8 @@ instance (q₁ : Quotient sa) (q₂ : Quotient sb) (f : α → β → Prop) end Quotient theorem Quot.eq {α : Type*} {r : α → α → Prop} {x y : α} : - Quot.mk r x = Quot.mk r y ↔ EqvGen r x y := - ⟨Quot.exact r, Quot.EqvGen_sound⟩ + Quot.mk r x = Quot.mk r y ↔ Relation.EqvGen r x y := + ⟨Quot.eqvGen_exact, Quot.eqvGen_sound⟩ @[simp] theorem Quotient.eq [r : Setoid α] {x y : α} : Quotient.mk r x = ⟦y⟧ ↔ x ≈ y := diff --git a/Mathlib/Data/Rat/Cast/Order.lean b/Mathlib/Data/Rat/Cast/Order.lean index 01ee5b4fb33f1..2a4ebd3ceadb2 100644 --- a/Mathlib/Data/Rat/Cast/Order.lean +++ b/Mathlib/Data/Rat/Cast/Order.lean @@ -132,6 +132,27 @@ def castOrderEmbedding : ℚ≥0 ↪o K := @[simp] lemma cast_pos : (0 : K) < q ↔ 0 < q := by norm_cast @[norm_cast] lemma cast_lt_zero : (q : K) < 0 ↔ q < 0 := by norm_cast @[simp] lemma not_cast_lt_zero : ¬(q : K) < 0 := mod_cast not_lt_zero' +@[simp] lemma cast_le_one : (p : K) ≤ 1 ↔ p ≤ 1 := by norm_cast +@[simp] lemma one_le_cast : 1 ≤ (p : K) ↔ 1 ≤ p := by norm_cast +@[simp] lemma cast_lt_one : (p : K) < 1 ↔ p < 1 := by norm_cast +@[simp] lemma one_lt_cast : 1 < (p : K) ↔ 1 < p := by norm_cast + +section ofNat +variable {n : ℕ} [n.AtLeastTwo] + +@[simp] lemma cast_le_ofNat : (p : K) ≤ no_index (OfNat.ofNat n) ↔ p ≤ OfNat.ofNat n := by + simp [← cast_le (K := K)] + +@[simp] lemma ofNat_le_cast : no_index (OfNat.ofNat n) ≤ (p : K) ↔ OfNat.ofNat n ≤ p := by + simp [← cast_le (K := K)] + +@[simp] lemma cast_lt_ofNat : (p : K) < no_index (OfNat.ofNat n) ↔ p < OfNat.ofNat n := by + simp [← cast_lt (K := K)] + +@[simp] lemma ofNat_lt_cast : no_index (OfNat.ofNat n) < (p : K) ↔ OfNat.ofNat n < p := by + simp [← cast_lt (K := K)] + +end ofNat @[simp, norm_cast] lemma cast_min (p q : ℚ≥0) : (↑(min p q) : K) = min (p : K) (q : K) := (@cast_mono K _).map_min diff --git a/Mathlib/Data/Rat/Encodable.lean b/Mathlib/Data/Rat/Encodable.lean index 077213e24cef7..4779cf7a54c82 100644 --- a/Mathlib/Data/Rat/Encodable.lean +++ b/Mathlib/Data/Rat/Encodable.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl, Mario Carneiro -/ import Mathlib.Logic.Encodable.Basic -import Mathlib.Data.Nat.GCD.Basic import Mathlib.Data.Rat.Init /-! # The rationals are `Encodable`. diff --git a/Mathlib/Data/Rat/Star.lean b/Mathlib/Data/Rat/Star.lean index a09ca020eab6d..8f4b38afcab0e 100644 --- a/Mathlib/Data/Rat/Star.lean +++ b/Mathlib/Data/Rat/Star.lean @@ -5,7 +5,7 @@ Authors: Jireh Loreaux, Yaël Dillies -/ import Mathlib.Algebra.GroupWithZero.Commute import Mathlib.Algebra.Order.Ring.Abs -import Mathlib.Algebra.Star.Order +import Mathlib.Algebra.Order.Star.Basic import Mathlib.Data.NNRat.Lemmas import Mathlib.Algebra.Order.Monoid.Submonoid import Mathlib.Tactic.FieldSimp @@ -38,7 +38,7 @@ namespace NNRat simpa only [sq] using addSubmonoid_closure_range_pow two_ne_zero instance instStarOrderedRing : StarOrderedRing ℚ≥0 where - le_iff a b := by simp [le_iff_exists_nonneg_add a b] + le_iff a b := by simp [eq_comm, le_iff_exists_nonneg_add (a := a)] end NNRat @@ -57,6 +57,6 @@ lemma addSubmonoid_closure_range_mul_self : closure (range fun x : ℚ ↦ x * x simpa only [sq] using addSubmonoid_closure_range_pow two_ne_zero even_two instance instStarOrderedRing : StarOrderedRing ℚ where - le_iff a b := by simp [le_iff_exists_nonneg_add a b] + le_iff a b := by simp [eq_comm, le_iff_exists_nonneg_add (a := a)] end Rat diff --git a/Mathlib/Data/Real/Archimedean.lean b/Mathlib/Data/Real/Archimedean.lean index 9c2e636a07e34..320d601909bab 100644 --- a/Mathlib/Data/Real/Archimedean.lean +++ b/Mathlib/Data/Real/Archimedean.lean @@ -62,7 +62,7 @@ theorem exists_isLUB {S : Set ℝ} (hne : S.Nonempty) (hbdd : BddAbove S) : ∃ 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 => let ⟨y, yS, hy⟩ := (hf n).1 - ⟨y, yS, by simpa using (div_le_iff (Nat.cast_pos.2 n0 : (_ : ℝ) < _)).2 hy⟩ + ⟨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 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 _⟩) @@ -343,7 +343,7 @@ lemma exists_natCast_add_one_lt_pow_of_one_lt {a : ℝ} (ha : 1 < a) : refine le_of_forall_lt_rat_imp_le ?_ intro q hq refine (ha q.den (by positivity)).trans ?_ - rw [← le_sub_iff_add_le, div_le_iff (by positivity), sub_mul, one_mul] + rw [← le_sub_iff_add_le, div_le_iff₀ (by positivity), sub_mul, one_mul] norm_cast at hq ⊢ rw [← q.num_div_den, one_lt_div (by positivity)] at hq rw [q.mul_den_eq_num] diff --git a/Mathlib/Data/Real/EReal.lean b/Mathlib/Data/Real/EReal.lean index 3de259cbaf4d5..4ff49b8b9459b 100644 --- a/Mathlib/Data/Real/EReal.lean +++ b/Mathlib/Data/Real/EReal.lean @@ -929,6 +929,64 @@ lemma neg_sub {x y : EReal} (h1 : x ≠ ⊥ ∨ y ≠ ⊥) (h2 : x ≠ ⊤ ∨ y - (x - y) = - x + y := by rw [sub_eq_add_neg, neg_add _ _, sub_eq_add_neg, neg_neg] <;> simp_all +/-! ### Addition and order -/ + +lemma le_of_forall_lt_iff_le {x y : EReal} : (∀ z : ℝ, x < z → y ≤ z) ↔ y ≤ x := by + refine ⟨fun h ↦ WithBot.le_of_forall_lt_iff_le.1 ?_, fun h _ x_z ↦ h.trans x_z.le⟩ + rw [WithTop.forall] + aesop + +lemma ge_of_forall_gt_iff_ge {x y : EReal} : (∀ z : ℝ, z < y → z ≤ x) ↔ y ≤ x := by + refine ⟨fun h ↦ WithBot.ge_of_forall_gt_iff_ge.1 ?_, fun h _ x_z ↦ x_z.le.trans h⟩ + rw [WithTop.forall] + aesop + +/-- This lemma is superseded by `add_le_of_forall_add_le`. -/ +private lemma top_add_le_of_forall_add_le {a b : EReal} (h : ∀ c < ⊤, ∀ d < a, c + d ≤ b) : + ⊤ + a ≤ b := by + induction a with + | h_bot => exact add_bot ⊤ ▸ bot_le + | h_real a => + refine top_add_coe a ▸ le_of_forall_lt_iff_le.1 fun c b_c ↦ ?_ + specialize h (c - a + 1) (coe_lt_top (c - a + 1)) (a - 1) + rw [← coe_one, ← coe_sub, ← coe_sub, ← coe_add, ← coe_add, add_add_sub_cancel, sub_add_cancel, + EReal.coe_lt_coe_iff] at h + exact (not_le_of_lt b_c (h (sub_one_lt a))).rec + | h_top => + refine top_add_top ▸ le_of_forall_lt_iff_le.1 fun c b_c ↦ ?_ + specialize h c (coe_lt_top c) 0 zero_lt_top + rw [add_zero] at h + exact (not_le_of_lt b_c h).rec + +lemma add_le_of_forall_add_le {a b c : EReal} (h : ∀ d < a, ∀ e < b, d + e ≤ c) : a + b ≤ c := by + induction a with + | h_bot => exact bot_add b ▸ bot_le + | h_real a => induction b with + | h_bot => exact add_bot (a : EReal) ▸ bot_le + | h_real b => + refine (@ge_of_forall_gt_iff_ge c (a+b)).1 fun d d_ab ↦ ?_ + rw [← coe_add, EReal.coe_lt_coe_iff] at d_ab + rcases exists_between d_ab with ⟨e, e_d, e_ab⟩ + have key₁ : (a + d - e : ℝ) < (a : EReal) := by apply EReal.coe_lt_coe_iff.2; linarith + have key₂ : (e - a : ℝ) < (b : EReal) := by apply EReal.coe_lt_coe_iff.2; linarith + apply le_of_eq_of_le _ (h (a + d - e) key₁ (e - a) key₂) + rw [← coe_add, ← coe_sub, ← coe_sub, ← coe_add, sub_add_sub_cancel, add_sub_cancel_left] + | h_top => + rw [add_comm (a : EReal) ⊤] + exact top_add_le_of_forall_add_le fun d d_top e e_a ↦ (add_comm d e ▸ h e e_a d d_top) + | h_top => exact top_add_le_of_forall_add_le h + +lemma le_add_of_forall_le_add {a b c : EReal} (h₁ : a ≠ ⊥ ∨ b ≠ ⊤) (h₂ : a ≠ ⊤ ∨ b ≠ ⊥) + (h : ∀ d > a, ∀ e > b, c ≤ d + e) : + c ≤ a + b := by + rw [← neg_le_neg_iff, neg_add h₁ h₂] + refine add_le_of_forall_add_le fun d d_a e e_b ↦ ?_ + have h₃ : d ≠ ⊥ ∨ e ≠ ⊤ := Or.inr (ne_top_of_lt e_b) + have h₄ : d ≠ ⊤ ∨ e ≠ ⊥ := Or.inl (ne_top_of_lt d_a) + rw [← neg_neg d, neg_lt_iff_neg_lt, neg_neg a] at d_a + rw [← neg_neg e, neg_lt_iff_neg_lt, neg_neg b] at e_b + exact le_neg_of_le_neg <| neg_add h₃ h₄ ▸ h (- d) d_a (- e) e_b + /-! ### Subtraction @@ -1169,52 +1227,6 @@ lemma left_distrib_of_nonneg {a b c : EReal} (ha : 0 ≤ a) (hb : 0 ≤ b) : nth_rewrite 1 [EReal.mul_comm]; nth_rewrite 2 [EReal.mul_comm]; nth_rewrite 3 [EReal.mul_comm] exact right_distrib_of_nonneg ha hb -lemma le_iff_le_forall_real_gt (x y : EReal) : (∀ z : ℝ, x < z → y ≤ z) ↔ y ≤ x := by - symm - refine ⟨fun h z x_lt_z ↦ le_trans h (le_of_lt x_lt_z), ?_⟩ - intro h - induction x - · apply le_of_eq ((eq_bot_iff_forall_lt y).2 _) - intro z - specialize h (z-1) (bot_lt_coe (z-1)) - apply lt_of_le_of_lt h - rw [EReal.coe_lt_coe_iff] - exact sub_one_lt z - · induction y - · exact bot_le - · norm_cast - norm_cast at h - by_contra x_lt_y - rcases exists_between (lt_of_not_le x_lt_y) with ⟨z, x_lt_z, z_lt_y⟩ - specialize h z x_lt_z - exact not_le_of_lt z_lt_y h - · exfalso - specialize h (_+ 1) (EReal.coe_lt_coe_iff.2 (lt_add_one _)) - exact not_le_of_lt (coe_lt_top (_ + 1)) h - · exact le_top - -lemma ge_iff_le_forall_real_lt (x y : EReal) : (∀ z : ℝ, z < y → z ≤ x) ↔ y ≤ x := by - refine ⟨fun h ↦ ?_, fun h z z_lt_y ↦ le_trans (le_of_lt z_lt_y) h⟩ - induction x with - | h_bot => - refine ((eq_bot_iff_forall_lt y).2 fun z ↦ ?_).le - refine lt_of_not_le fun z_le_y ↦ (not_le_of_lt (bot_lt_coe (z - 1)) (h (z - 1) - (lt_of_lt_of_le ?_ z_le_y))) - exact_mod_cast sub_one_lt z - | h_real x => - induction y with - | h_bot => exact bot_le - | h_real y => - norm_cast at h ⊢ - by_contra! x_lt_y - rcases exists_between x_lt_y with ⟨z, x_lt_z, z_lt_y⟩ - exact not_le_of_lt x_lt_z (h z z_lt_y) - | h_top => - exfalso - norm_cast at h - exact not_le_of_lt (lt_add_one x) <| h (x + 1) (coe_lt_top (x + 1)) - | h_top => exact le_top - /-! ### Absolute value -/ -- Porting note (#11215): TODO: use `Real.nnabs` for the case `(x : ℝ)` @@ -1548,7 +1560,7 @@ lemma div_right_distrib_of_nonneg {a b c : EReal} (h : 0 ≤ a) (h' : 0 ≤ b) : (a + b) / c = (a / c) + (b / c) := EReal.right_distrib_of_nonneg h h' -/-! #### Division and Order s-/ +/-! #### Division and Order s -/ lemma monotone_div_right_of_nonneg {b : EReal} (h : 0 ≤ b) : Monotone fun a ↦ a / b := fun _ _ h' ↦ mul_le_mul_of_nonneg_right h' (inv_nonneg_of_nonneg h) @@ -1668,3 +1680,5 @@ unsafe def positivity_coe_ennreal_ereal : expr → tactic strictness end Tactic -/ + +set_option linter.style.longFile 1800 diff --git a/Mathlib/Data/Real/Hyperreal.lean b/Mathlib/Data/Real/Hyperreal.lean index 3ec6b4835c02e..68aee623dbde7 100644 --- a/Mathlib/Data/Real/Hyperreal.lean +++ b/Mathlib/Data/Real/Hyperreal.lean @@ -127,11 +127,11 @@ theorem ofSeq_surjective : Function.Surjective ofSeq := Quot.exists_rep theorem ofSeq_lt_ofSeq {f g : ℕ → ℝ} : ofSeq f < ofSeq g ↔ ∀ᶠ n in hyperfilter ℕ, f n < g n := Germ.coe_lt -/-- A sample infinitesimal hyperreal-/ +/-- A sample infinitesimal hyperreal -/ noncomputable def epsilon : ℝ* := ofSeq fun n => n⁻¹ -/-- A sample infinite hyperreal-/ +/-- A sample infinite hyperreal -/ noncomputable def omega : ℝ* := ofSeq Nat.cast @[inherit_doc] scoped notation "ε" => Hyperreal.epsilon diff --git a/Mathlib/Data/Real/Pi/Bounds.lean b/Mathlib/Data/Real/Pi/Bounds.lean index 20aaebc121269..20ca11d6273d2 100644 --- a/Mathlib/Data/Real/Pi/Bounds.lean +++ b/Mathlib/Data/Real/Pi/Bounds.lean @@ -42,19 +42,19 @@ theorem pi_lt_sqrtTwoAddSeries (n : ℕ) : 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'] + · 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 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)] - rw [le_div_iff (by norm_num), ← mul_pow] + rw [le_div_iff₀ (by norm_num), ← mul_pow] refine le_trans ?_ (le_of_eq (one_pow 3)); apply pow_le_pow_left · apply le_of_lt; apply mul_pos · apply div_pos pi_pos; apply pow_pos; norm_num · apply pow_pos; norm_num - · rw [← le_div_iff (by norm_num)] + · rw [← le_div_iff₀ (by norm_num)] refine le_trans ((div_le_div_right ?_).mpr pi_le_four) ?_ · apply pow_pos; norm_num · simp only [pow_succ', ← div_div, one_div] @@ -74,7 +74,7 @@ theorem pi_lower_bound_start (n : ℕ) {a} (h : sqrtTwoAddSeries ((0 : ℕ) / (1 : ℕ)) n ≤ (2 : ℝ) - (a / (2 : ℝ) ^ (n + 1)) ^ 2) : a < π := by refine lt_of_le_of_lt ?_ (pi_gt_sqrtTwoAddSeries n); rw [mul_comm] - refine (div_le_iff (pow_pos (by norm_num) _ : (0 : ℝ) < _)).mp (le_sqrt_of_sq_le ?_) + refine (div_le_iff₀ (pow_pos (by norm_num) _ : (0 : ℝ) < _)).mp (le_sqrt_of_sq_le ?_) rwa [le_sub_comm, show (0 : ℝ) = (0 : ℕ) / (1 : ℕ) by rw [Nat.cast_zero, zero_div]] theorem sqrtTwoAddSeries_step_up (c d : ℕ) {a b n : ℕ} {z : ℝ} (hz : sqrtTwoAddSeries (c / d) n ≤ z) @@ -124,7 +124,7 @@ theorem pi_upper_bound_start (n : ℕ) {a} sqrtTwoAddSeries ((0 : ℕ) / (1 : ℕ)) n) (h₂ : (1 : ℝ) / (4 : ℝ) ^ n ≤ a) : π < a := by refine lt_of_lt_of_le (pi_lt_sqrtTwoAddSeries n) ?_ - rw [← le_sub_iff_add_le, ← le_div_iff', sqrt_le_left, sub_le_comm] + rw [← le_sub_iff_add_le, ← le_div_iff₀', sqrt_le_left, sub_le_comm] · rwa [Nat.cast_zero, zero_div] at h · exact div_nonneg (sub_nonneg.2 h₂) (pow_nonneg (le_of_lt zero_lt_two) _) · exact pow_pos zero_lt_two _ diff --git a/Mathlib/Data/Real/Pi/Wallis.lean b/Mathlib/Data/Real/Pi/Wallis.lean index 096ffc009e98f..23aca82d62f0e 100644 --- a/Mathlib/Data/Real/Pi/Wallis.lean +++ b/Mathlib/Data/Real/Pi/Wallis.lean @@ -80,13 +80,11 @@ theorem W_le (k : ℕ) : W k ≤ π / 2 := by apply integral_sin_pow_succ_le theorem le_W (k : ℕ) : ((2 : ℝ) * k + 1) / (2 * k + 2) * (π / 2) ≤ W k := by - rw [← le_div_iff pi_div_two_pos, div_eq_inv_mul (W k) _] - rw [W_eq_integral_sin_pow_div_integral_sin_pow, le_div_iff (integral_sin_pow_pos _)] + rw [← le_div_iff₀ pi_div_two_pos, div_eq_inv_mul (W k) _] + rw [W_eq_integral_sin_pow_div_integral_sin_pow, le_div_iff₀ (integral_sin_pow_pos _)] convert integral_sin_pow_succ_le (2 * k + 1) rw [integral_sin_pow (2 * k)] - simp only [sin_zero, ne_eq, add_eq_zero, and_false, not_false_eq_true, zero_pow, cos_zero, - mul_one, sin_pi, cos_pi, mul_neg, neg_zero, sub_self, zero_div, zero_add] - norm_cast + simp theorem tendsto_W_nhds_pi_div_two : Tendsto W atTop (𝓝 <| π / 2) := by refine tendsto_of_tendsto_of_tendsto_of_le_of_le ?_ tendsto_const_nhds le_W W_le diff --git a/Mathlib/Data/Real/Sign.lean b/Mathlib/Data/Real/Sign.lean index e1b46f2c8ba69..d4b23cdfb07e2 100644 --- a/Mathlib/Data/Real/Sign.lean +++ b/Mathlib/Data/Real/Sign.lean @@ -104,8 +104,8 @@ theorem inv_sign (r : ℝ) : (sign r)⁻¹ = sign r := by @[simp] theorem sign_inv (r : ℝ) : sign r⁻¹ = sign r := by obtain hn | rfl | hp := lt_trichotomy r (0 : ℝ) - · rw [sign_of_neg hn, sign_of_neg (inv_lt_zero (α := ℝ) |>.mpr hn)] + · rw [sign_of_neg hn, sign_of_neg (inv_lt_zero.mpr hn)] · rw [sign_zero, inv_zero, sign_zero] - · rw [sign_of_pos hp, sign_of_pos (inv_pos (α := ℝ) |>.mpr hp)] + · rw [sign_of_pos hp, sign_of_pos (inv_pos.mpr hp)] end Real diff --git a/Mathlib/Data/Real/Sqrt.lean b/Mathlib/Data/Real/Sqrt.lean index d94c45c1cc6cd..48f8aad052901 100644 --- a/Mathlib/Data/Real/Sqrt.lean +++ b/Mathlib/Data/Real/Sqrt.lean @@ -115,15 +115,6 @@ noncomputable def sqrt (x : ℝ) : ℝ := @[inherit_doc] prefix:max "√" => Real.sqrt -/- quotient.lift_on x - (λ f, mk ⟨sqrt_aux f, (sqrt_aux_converges f).fst⟩) - (λ f g e, begin - rcases sqrt_aux_converges f with ⟨hf, x, x0, xf, xs⟩, - rcases sqrt_aux_converges g with ⟨hg, y, y0, yg, ys⟩, - refine xs.trans (eq.trans _ ys.symm), - rw [← @mul_self_inj_of_nonneg ℝ _ x y x0 y0, xf, yg], - congr' 1, exact quotient.sound e - end)-/ variable {x y : ℝ} @[simp, norm_cast] @@ -136,8 +127,7 @@ theorem continuous_sqrt : Continuous (√· : ℝ → ℝ) := theorem sqrt_eq_zero_of_nonpos (h : x ≤ 0) : sqrt x = 0 := by simp [sqrt, Real.toNNReal_eq_zero.2 h] -theorem sqrt_nonneg (x : ℝ) : 0 ≤ √x := - NNReal.coe_nonneg _ +@[simp] theorem sqrt_nonneg (x : ℝ) : 0 ≤ √x := NNReal.coe_nonneg _ @[simp] theorem mul_self_sqrt (h : 0 ≤ x) : √x * √x = x := by @@ -156,8 +146,12 @@ theorem sqrt_eq_cases : √x = y ↔ y * y = x ∧ 0 ≤ y ∨ x < 0 ∧ y = 0 : · rintro (⟨rfl, hy⟩ | ⟨hx, rfl⟩) exacts [sqrt_mul_self hy, sqrt_eq_zero_of_nonpos hx.le] -theorem sqrt_eq_iff_mul_self_eq (hx : 0 ≤ x) (hy : 0 ≤ y) : √x = y ↔ y * y = x := - ⟨fun h => by rw [← h, mul_self_sqrt hx], fun h => by rw [← h, sqrt_mul_self hy]⟩ +theorem sqrt_eq_iff_mul_self_eq (hx : 0 ≤ x) (hy : 0 ≤ y) : √x = y ↔ x = y * y := + ⟨fun h => by rw [← h, mul_self_sqrt hx], fun h => by rw [h, sqrt_mul_self hy]⟩ + +@[deprecated sqrt_eq_iff_mul_self_eq (since := "2024-08-25")] +theorem sqrt_eq_iff_eq_mul_self (hx : 0 ≤ x) (hy : 0 ≤ y) : √x = y ↔ y * y = x := by + rw [sqrt_eq_iff_mul_self_eq hx hy, eq_comm] theorem sqrt_eq_iff_mul_self_eq_of_pos (h : 0 < y) : √x = y ↔ y * y = x := by simp [sqrt_eq_cases, h.ne', h.le] @@ -174,9 +168,13 @@ theorem sq_sqrt (h : 0 ≤ x) : √x ^ 2 = x := by rw [sq, mul_self_sqrt h] @[simp] theorem sqrt_sq (h : 0 ≤ x) : √(x ^ 2) = x := by rw [sq, sqrt_mul_self h] -theorem sqrt_eq_iff_sq_eq (hx : 0 ≤ x) (hy : 0 ≤ y) : √x = y ↔ y ^ 2 = x := by +theorem sqrt_eq_iff_eq_sq (hx : 0 ≤ x) (hy : 0 ≤ y) : √x = y ↔ x = y ^ 2 := by rw [sq, sqrt_eq_iff_mul_self_eq hx hy] +@[deprecated sqrt_eq_iff_eq_sq (since := "2024-08-25")] +theorem sqrt_eq_iff_sq_eq (hx : 0 ≤ x) (hy : 0 ≤ y) : √x = y ↔ y ^ 2 = x := by + rw [sqrt_eq_iff_eq_sq hx hy, eq_comm] + theorem sqrt_mul_self_eq_abs (x : ℝ) : √(x * x) = |x| := by rw [← abs_mul_abs_self x, sqrt_mul_self (abs_nonneg _)] diff --git a/Mathlib/Data/Real/StarOrdered.lean b/Mathlib/Data/Real/StarOrdered.lean index 3bb4a4ddd017d..ef1ad46ac2800 100644 --- a/Mathlib/Data/Real/StarOrdered.lean +++ b/Mathlib/Data/Real/StarOrdered.lean @@ -3,7 +3,7 @@ Copyright (c) 2020 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kim Morrison -/ -import Mathlib.Algebra.Star.Order +import Mathlib.Algebra.Order.Star.Basic import Mathlib.Data.Real.Sqrt /-! # `ℝ` and `ℝ≥0` are *-ordered rings. -/ diff --git a/Mathlib/Data/Rel.lean b/Mathlib/Data/Rel.lean index a0fbadb670218..27adb8a69b26d 100644 --- a/Mathlib/Data/Rel.lean +++ b/Mathlib/Data/Rel.lean @@ -333,7 +333,7 @@ theorem graph_injective : Injective (graph : (α → β) → Rel α β) := by @[simp] lemma graph_inj {f g : α → β} : f.graph = g.graph ↔ f = g := graph_injective.eq_iff -theorem graph_id : graph id = @Eq α := by simp (config := { unfoldPartialApp := true }) [graph] +theorem graph_id : graph id = @Eq α := by simp (config := { unfoldPartialApp := true }) [graph] theorem graph_comp {f : β → γ} {g : α → β} : graph (f ∘ g) = Rel.comp (graph g) (graph f) := by ext x y diff --git a/Mathlib/Data/Semiquot.lean b/Mathlib/Data/Semiquot.lean index 5557146ba9262..fb1f34b2cb8c3 100644 --- a/Mathlib/Data/Semiquot.lean +++ b/Mathlib/Data/Semiquot.lean @@ -34,7 +34,7 @@ namespace Semiquot variable {α : Type*} {β : Type*} instance : Membership α (Semiquot α) := - ⟨fun a q => a ∈ q.s⟩ + ⟨fun q a => a ∈ q.s⟩ /-- Construct a `Semiquot α` from `h : a ∈ s` where `s : Set α`. -/ def mk {a : α} {s : Set α} (h : a ∈ s) : Semiquot α := diff --git a/Mathlib/Data/Seq/Computation.lean b/Mathlib/Data/Seq/Computation.lean index 9b4a265a6475b..643390111d77a 100644 --- a/Mathlib/Data/Seq/Computation.lean +++ b/Mathlib/Data/Seq/Computation.lean @@ -236,18 +236,19 @@ section Bisim variable (R : Computation α → Computation α → Prop) -/-- bisimilarity relation-/ +/-- bisimilarity relation -/ local infixl:50 " ~ " => R -/-- Bisimilarity over a sum of `Computation`s-/ +/-- Bisimilarity over a sum of `Computation`s -/ def BisimO : α ⊕ (Computation α) → α ⊕ (Computation α) → Prop | Sum.inl a, Sum.inl a' => a = a' | Sum.inr s, Sum.inr s' => R s s' | _, _ => False attribute [simp] BisimO +attribute [nolint simpNF] BisimO.eq_3 -/-- Attribute expressing bisimilarity over two `Computation`s-/ +/-- Attribute expressing bisimilarity over two `Computation`s -/ def IsBisimulation := ∀ ⦃s₁ s₂⦄, s₁ ~ s₂ → BisimO R (destruct s₁) (destruct s₂) @@ -280,7 +281,7 @@ end Bisim -- It's more of a stretch to use ∈ for this relation, but it -- asserts that the computation limits to the given value. /-- Assertion that a `Computation` limits to a given value-/ -protected def Mem (a : α) (s : Computation α) := +protected def Mem (s : Computation α) (a : α) := some a ∈ s.1 instance : Membership α (Computation α) := @@ -504,7 +505,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 n IH <;> intro s <;> apply recOn s (fun a' => _) fun s => _ <;> intro a h + induction n with | zero => _ | succ n IH => _ + all_goals 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 @@ -519,7 +521,7 @@ theorem eq_thinkN' (s : Computation α) [_h : Terminates s] : s = thinkN (pure (get s)) (length s) := eq_thinkN (results_of_terminates _) -/-- Recursor based on membership-/ +/-- Recursor based on membership -/ def memRecOn {C : Computation α → Sort v} {a s} (M : a ∈ s) (h1 : C (pure a)) (h2 : ∀ s, C s → C (think s)) : C s := by haveI T := terminates_of_mem M @@ -694,7 +696,8 @@ 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 with n IH generalizing s <;> apply recOn s (fun a => _) fun s' => _ <;> intro e h + induction k generalizing s with | zero => _ | succ n IH => _ + all_goals 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) @@ -753,7 +756,7 @@ theorem exists_of_mem_map {f : α → β} {b : β} {s : Computation α} (h : b exact ⟨a, as, mem_unique (ret_mem _) fb⟩ instance terminates_map (f : α → β) (s : Computation α) [Terminates s] : Terminates (map f s) := by - rw [← bind_pure]; exact terminates_of_mem (mem_bind (get_mem s) (get_mem (f (get s)))) + rw [← bind_pure]; exact terminates_of_mem (mem_bind (get_mem s) (get_mem (α := β) (f (get s)))) theorem terminates_map_iff (f : α → β) (s : Computation α) : Terminates (map f s) ↔ Terminates s := ⟨fun ⟨⟨_, h⟩⟩ => @@ -820,7 +823,7 @@ theorem orElse_empty (c : Computation α) : (c <|> empty α) = c := by def Equiv (c₁ c₂ : Computation α) : Prop := ∀ a, a ∈ c₁ ↔ a ∈ c₂ -/-- equivalence relation for computations-/ +/-- equivalence relation for computations -/ scoped infixl:50 " ~ " => Equiv @[refl] @@ -1041,7 +1044,7 @@ theorem map_congr {s1 s2 : Computation α} {f : α → β} rw [← lift_eq_iff_equiv] exact liftRel_map Eq _ ((lift_eq_iff_equiv _ _).2 h1) fun {a} b => congr_arg _ -/-- Alternate definition of `LiftRel` over relations between `Computation`s-/ +/-- Alternate definition of `LiftRel` over relations between `Computation`s -/ def LiftRelAux (R : α → β → Prop) (C : Computation α → Computation β → Prop) : α ⊕ (Computation α) → β ⊕ (Computation β) → Prop | Sum.inl a, Sum.inl b => R a b diff --git a/Mathlib/Data/Seq/Parallel.lean b/Mathlib/Data/Seq/Parallel.lean index 95a1d67f43238..ee4bdac0f33db 100644 --- a/Mathlib/Data/Seq/Parallel.lean +++ b/Mathlib/Data/Seq/Parallel.lean @@ -128,7 +128,6 @@ theorem terminates_parallel {S : WSeq (Computation α)} {c} (h : c ∈ S) [T : T · have C : corec parallel.aux1 (l, S) = pure a := by apply destruct_eq_pure rw [corec_eq, parallel.aux1] - dsimp only [] rw [h] simp only [rmap] rw [C] @@ -146,7 +145,6 @@ theorem terminates_parallel {S : WSeq (Computation α)} {c} (h : c ∈ S) [T : T · have C : corec parallel.aux1 (l, S) = pure a := by apply destruct_eq_pure rw [corec_eq, parallel.aux1] - dsimp only [] rw [h] simp only [rmap] rw [C] diff --git a/Mathlib/Data/Seq/Seq.lean b/Mathlib/Data/Seq/Seq.lean index 974c780ddf181..e1c08ea1f9bdc 100644 --- a/Mathlib/Data/Seq/Seq.lean +++ b/Mathlib/Data/Seq/Seq.lean @@ -126,7 +126,7 @@ def tail (s : Seq α) : Seq α := exact al n'⟩ /-- member definition for `Seq`-/ -protected def Mem (a : α) (s : Seq α) := +protected def Mem (s : Seq α) (a : α) := some a ∈ s.1 instance : Membership α (Seq α) := @@ -258,7 +258,7 @@ theorem mem_rec_on {C : Seq α → Prop} {a s} (M : a ∈ s) rw [h_eq] at e apply h1 _ _ (Or.inr (IH e)) -/-- Corecursor over pairs of `Option` values-/ +/-- Corecursor over pairs of `Option` values -/ def Corec.f (f : β → Option (α × β)) : Option β → Option α × Option β | none => (none, none) | some b => @@ -315,8 +315,9 @@ def BisimO : Option (Seq1 α) → Option (Seq1 α) → Prop | _, _ => False attribute [simp] BisimO +attribute [nolint simpNF] BisimO.eq_3 -/-- a relation is bisimilar if it meets the `BisimO` test-/ +/-- a relation is bisimilar if it meets the `BisimO` test -/ def IsBisimulation := ∀ ⦃s₁ s₂⦄, s₁ ~ s₂ → BisimO R (destruct s₁) (destruct s₂) diff --git a/Mathlib/Data/Seq/WSeq.lean b/Mathlib/Data/Seq/WSeq.lean index 9d86f9ce4e599..8a167a30145c9 100644 --- a/Mathlib/Data/Seq/WSeq.lean +++ b/Mathlib/Data/Seq/WSeq.lean @@ -106,8 +106,8 @@ def recOn {C : WSeq α → Sort v} (s : WSeq α) (h1 : C nil) (h2 : ∀ x s, C ( Seq.recOn s h1 fun o => Option.recOn o h3 h2 /-- membership for weak sequences-/ -protected def Mem (a : α) (s : WSeq α) := - Seq.Mem (some a) s +protected def Mem (s : WSeq α) (a : α) := + Seq.Mem s (some a) instance membership : Membership α (WSeq α) := ⟨WSeq.Mem⟩ @@ -394,6 +394,7 @@ def LiftRelO (R : α → β → Prop) (C : WSeq α → WSeq β → Prop) : | none, none => True | some (a, s), some (b, t) => R a b ∧ C s t | _, _ => False +attribute [nolint simpNF] LiftRelO.eq_3 theorem LiftRelO.imp {R S : α → β → Prop} {C D : WSeq α → WSeq β → Prop} (H1 : ∀ a b, R a b → S a b) (H2 : ∀ s t, C s t → D s t) : ∀ {o p}, LiftRelO R C o p → LiftRelO S D o p @@ -406,7 +407,7 @@ theorem LiftRelO.imp_right (R : α → β → Prop) {C D : WSeq α → WSeq β (H : ∀ s t, C s t → D s t) {o p} : LiftRelO R C o p → LiftRelO R D o p := LiftRelO.imp (fun _ _ => id) H -/-- Definition of bisimilarity for weak sequences-/ +/-- Definition of bisimilarity for weak sequences -/ @[simp] def BisimO (R : WSeq α → WSeq α → Prop) : Option (α × WSeq α) → Option (α × WSeq α) → Prop := LiftRelO (· = ·) R @@ -684,7 +685,7 @@ theorem append_nil (s : WSeq α) : append s nil = s := theorem append_assoc (s t u : WSeq α) : append (append s t) u = append s (append t u) := Seq.append_assoc _ _ _ -/-- auxiliary definition of tail over weak sequences-/ +/-- auxiliary definition of tail over weak sequences -/ @[simp] def tail.aux : Option (α × WSeq α) → Computation (Option (α × WSeq α)) | none => Computation.pure none @@ -694,7 +695,7 @@ theorem destruct_tail (s : WSeq α) : destruct (tail s) = destruct s >>= tail.au simp only [tail, destruct_flatten, tail.aux]; rw [← bind_pure_comp, LawfulMonad.bind_assoc] apply congr_arg; ext1 (_ | ⟨a, s⟩) <;> apply (@pure_bind Computation _ _ _ _ _ _).trans _ <;> simp -/-- auxiliary definition of drop over weak sequences-/ +/-- auxiliary definition of drop over weak sequences -/ @[simp] def drop.aux : ℕ → Option (α × WSeq α) → Computation (Option (α × WSeq α)) | 0 => Computation.pure @@ -816,7 +817,7 @@ theorem eq_or_mem_iff_mem {s : WSeq α} {a a' s'} : · cases' this with i1 i2 rw [i1, i2] cases' s' with f al - dsimp only [cons, (· ∈ ·), WSeq.Mem, Seq.Mem, Seq.cons] + dsimp only [cons, Membership.mem, WSeq.Mem, Seq.Mem, Seq.cons] have h_a_eq_a' : a = a' ↔ some (some a) = some (some a') := by simp rw [h_a_eq_a'] refine ⟨Stream'.eq_or_mem_of_mem_cons, fun o => ?_⟩ @@ -1330,7 +1331,7 @@ theorem liftRel_map {δ} (R : α → β → Prop) (S : γ → δ → Prop) {s1 : theorem map_congr (f : α → β) {s t : WSeq α} (h : s ~ʷ t) : map f s ~ʷ map f t := liftRel_map _ _ h fun {_ _} => congr_arg _ -/-- auxiliary definition of `destruct_append` over weak sequences-/ +/-- auxiliary definition of `destruct_append` over weak sequences -/ @[simp] def destruct_append.aux (t : WSeq α) : Option (α × WSeq α) → Computation (Option (α × WSeq α)) | none => destruct t @@ -1349,7 +1350,7 @@ theorem destruct_append (s t : WSeq α) : · refine ⟨nil, t, ?_, ?_⟩ <;> simp · exact ⟨s, t, rfl, rfl⟩ -/-- auxiliary definition of `destruct_join` over weak sequences-/ +/-- auxiliary definition of `destruct_join` over weak sequences -/ @[simp] def destruct_join.aux : Option (WSeq α × WSeq (WSeq α)) → Computation (Option (α × WSeq α)) | none => Computation.pure none @@ -1407,7 +1408,7 @@ theorem liftRel_join.lem (R : α → β → Prop) {S T} {U : WSeq α → WSeq β U s1 s2) {a} (ma : a ∈ destruct (join S)) : ∃ b, b ∈ destruct (join T) ∧ LiftRelO R U a b := by cases' exists_results_of_mem ma with n h; clear ma; revert S T ST a - induction' n using Nat.strongInductionOn with n IH + induction' n using Nat.strongRecOn with n IH intro S T ST a ra; simp only [destruct_join] at ra exact let ⟨o, m, k, rs1, rs2, en⟩ := of_results_bind ra @@ -1622,3 +1623,5 @@ instance lawfulMonad : LawfulMonad WSeq := end WSeq end Stream' + +set_option linter.style.longFile 1800 diff --git a/Mathlib/Data/Set/Basic.lean b/Mathlib/Data/Set/Basic.lean index c2505bdf4d84b..dba783a5ea356 100644 --- a/Mathlib/Data/Set/Basic.lean +++ b/Mathlib/Data/Set/Basic.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad, Leonardo de Moura -/ import Mathlib.Algebra.Group.ZeroOne -import Mathlib.Data.Set.Defs +import Mathlib.Data.Set.Operations import Mathlib.Order.Basic import Mathlib.Order.SymmDiff import Mathlib.Tactic.Tauto @@ -435,6 +435,11 @@ theorem Nonempty.to_type : s.Nonempty → Nonempty α := fun ⟨x, _⟩ => ⟨x instance univ.nonempty [Nonempty α] : Nonempty (↥(Set.univ : Set α)) := Set.univ_nonempty.to_subtype +-- Redeclare for refined keys +-- `Nonempty (@Subtype _ (@Membership.mem _ (Set _) _ (@Top.top (Set _) _)))` +instance instNonemptyTop [Nonempty α] : Nonempty (⊤ : Set α) := + inferInstanceAs (Nonempty (univ : Set α)) + theorem nonempty_of_nonempty_subtype [Nonempty (↥s)] : s.Nonempty := nonempty_subtype.mp ‹_› @@ -962,7 +967,7 @@ theorem insert_union_distrib (a : α) (s t : Set α) : insert a (s ∪ t) = inse ext fun _ => or_or_distrib_left theorem insert_inj (ha : a ∉ s) : insert a s = insert b s ↔ a = b := - ⟨fun h => eq_of_not_mem_of_mem_insert (h.subst <| mem_insert a s) ha, + ⟨fun h => eq_of_not_mem_of_mem_insert (h ▸ mem_insert a s) ha, congr_arg (fun x => insert x s)⟩ -- useful in proofs by induction @@ -1428,8 +1433,9 @@ theorem not_mem_of_mem_diff {s t : Set α} {x : α} (h : x ∈ s \ t) : x ∉ t theorem diff_eq_compl_inter {s t : Set α} : s \ t = tᶜ ∩ s := by rw [diff_eq, inter_comm] -theorem nonempty_diff {s t : Set α} : (s \ t).Nonempty ↔ ¬s ⊆ t := +theorem diff_nonempty {s t : Set α} : (s \ t).Nonempty ↔ ¬s ⊆ t := inter_compl_nonempty_iff +@[deprecated (since := "2024-08-27")] alias nonempty_diff := diff_nonempty theorem diff_subset {s t : Set α} : s \ t ⊆ s := show s \ t ≤ s from sdiff_le @@ -1972,9 +1978,8 @@ section Inclusion variable {α : Type*} {s t u : Set α} /-- `inclusion` is the "identity" function between two subsets `s` and `t`, where `s ⊆ t` -/ -def inclusion (h : s ⊆ t) : s → t := fun x : s => (⟨x, h x.2⟩ : t) +abbrev inclusion (h : s ⊆ t) : s → t := fun x : s => (⟨x, h x.2⟩ : t) -@[simp] theorem inclusion_self (x : s) : inclusion Subset.rfl x = x := by cases x rfl @@ -2011,7 +2016,6 @@ theorem val_comp_inclusion (h : s ⊆ t) : Subtype.val ∘ inclusion h = Subtype theorem inclusion_injective (h : s ⊆ t) : Injective (inclusion h) | ⟨_, _⟩, ⟨_, _⟩ => Subtype.ext_iff_val.2 ∘ Subtype.ext_iff_val.1 -@[simp] theorem inclusion_inj (h : s ⊆ t) {x y : s} : inclusion h x = inclusion h y ↔ x = y := (inclusion_injective h).eq_iff @@ -2021,11 +2025,9 @@ theorem eq_of_inclusion_surjective {s t : Set α} {h : s ⊆ t} obtain ⟨y, hy⟩ := h_surj ⟨x, hx⟩ exact mem_of_eq_of_mem (congr_arg Subtype.val hy).symm y.prop -@[simp] theorem inclusion_le_inclusion [Preorder α] {s t : Set α} (h : s ⊆ t) {x y : s} : inclusion h x ≤ inclusion h y ↔ x ≤ y := Iff.rfl -@[simp] theorem inclusion_lt_inclusion [Preorder α] {s t : Set α} (h : s ⊆ t) {x y : s} : inclusion h x < inclusion h y ↔ x < y := Iff.rfl @@ -2171,3 +2173,5 @@ end Disjoint @[simp] theorem Prop.compl_singleton (p : Prop) : ({p}ᶜ : Set Prop) = {¬p} := ext fun q ↦ by simpa [@Iff.comm q] using not_iff + +set_option linter.style.longFile 2300 diff --git a/Mathlib/Data/Set/Card.lean b/Mathlib/Data/Set/Card.lean index 115d6555eaac1..547c12a239211 100644 --- a/Mathlib/Data/Set/Card.lean +++ b/Mathlib/Data/Set/Card.lean @@ -557,7 +557,7 @@ section InsertErase hs.cast_ncard_eq, encard_insert_of_not_mem h] theorem ncard_insert_of_mem {a : α} (h : a ∈ s) : ncard (insert a s) = s.ncard := by - rw [insert_eq_of_mem h] + rw [insert_eq_of_mem h] theorem ncard_insert_le (a : α) (s : Set α) : (insert a s).ncard ≤ s.ncard + 1 := by obtain hs | hs := s.finite_or_infinite @@ -753,7 +753,7 @@ theorem surj_on_of_inj_on_of_ncard_le {t : Set β} (f : ∀ a ∈ s, β) (hf : have hft := ht.fintype have hft' := Fintype.ofInjective f' finj set f'' : ∀ a, a ∈ s.toFinset → β := fun a h ↦ f a (by simpa using h) - convert @Finset.surj_on_of_inj_on_of_card_le _ _ _ t.toFinset f'' _ _ _ _ (by simpa) + convert @Finset.surj_on_of_inj_on_of_card_le _ _ _ t.toFinset f'' _ _ _ _ (by simpa) using 1 · simp · simp [hf] · intros a₁ a₂ ha₁ ha₂ h @@ -947,7 +947,8 @@ theorem exists_eq_insert_iff_ncard (hs : s.Finite := by toFinite_tac) : convert Iff.rfl using 2; simp only [Finite.mem_toFinset] ext x simp [Finset.ext_iff, Set.ext_iff] - simp only [ht.ncard, exists_prop, add_eq_zero, and_false, iff_false, not_exists, not_and] + simp only [ht.ncard, exists_prop, add_eq_zero, and_false, iff_false, not_exists, not_and, + reduceCtorEq] rintro x - rfl exact ht (hs.insert x) @@ -1012,9 +1013,8 @@ theorem eq_insert_of_ncard_eq_succ {n : ℕ} (h : s.ncard = n + 1) : obtain ⟨a, t, hat, hts, rfl⟩ := h simp only [Finset.ext_iff, Finset.mem_insert, Finite.mem_toFinset] at hts refine ⟨a, t, hat, ?_, ?_⟩ - · simp only [Finset.mem_coe, Set.ext_iff, mem_insert_iff] - tauto - simp + · simp [Set.ext_iff, hts] + · simp theorem ncard_eq_succ {n : ℕ} (hs : s.Finite := by toFinite_tac) : s.ncard = n + 1 ↔ ∃ a t, a ∉ t ∧ insert a t = s ∧ t.ncard = n := by @@ -1026,13 +1026,13 @@ theorem ncard_eq_two : s.ncard = 2 ↔ ∃ x y, x ≠ y ∧ s = {x, y} := by rw [← encard_eq_two, ncard_def, ← Nat.cast_inj (R := ℕ∞), Nat.cast_ofNat] refine ⟨fun h ↦ ?_, fun h ↦ ?_⟩ · rwa [ENat.coe_toNat] at h; rintro h'; simp [h'] at h - rw [h]; rfl + simp [h] theorem ncard_eq_three : s.ncard = 3 ↔ ∃ x y z, x ≠ y ∧ x ≠ z ∧ y ≠ z ∧ s = {x, y, z} := by rw [← encard_eq_three, ncard_def, ← Nat.cast_inj (R := ℕ∞), Nat.cast_ofNat] refine ⟨fun h ↦ ?_, fun h ↦ ?_⟩ · rwa [ENat.coe_toNat] at h; rintro h'; simp [h'] at h - rw [h]; rfl + simp [h] end ncard diff --git a/Mathlib/Data/Set/Constructions.lean b/Mathlib/Data/Set/Constructions.lean index 9011537864b94..6690c61075cd1 100644 --- a/Mathlib/Data/Set/Constructions.lean +++ b/Mathlib/Data/Set/Constructions.lean @@ -59,12 +59,14 @@ theorem finiteInter_mem (cond : FiniteInter S) (F : Finset (Set α)) : theorem finiteInterClosure_insert {A : Set α} (cond : FiniteInter S) (P) (H : P ∈ finiteInterClosure (insert A S)) : P ∈ S ∨ ∃ Q ∈ S, P = A ∩ Q := by - induction' H with S h T1 T2 _ _ h1 h2 - · cases h + induction H with + | basic h => + cases h · exact Or.inr ⟨Set.univ, cond.univ_mem, by simpa⟩ · exact Or.inl (by assumption) - · exact Or.inl cond.univ_mem - · rcases h1 with (h | ⟨Q, hQ, rfl⟩) <;> rcases h2 with (i | ⟨R, hR, rfl⟩) + | univ => exact Or.inl cond.univ_mem + | @inter T1 T2 _ _ h1 h2 => + rcases h1 with (h | ⟨Q, hQ, rfl⟩) <;> rcases h2 with (i | ⟨R, hR, rfl⟩) · exact Or.inl (cond.inter_mem h i) · exact Or.inr ⟨T1 ∩ R, cond.inter_mem h hR, by simp only [← Set.inter_assoc, Set.inter_comm _ A]⟩ diff --git a/Mathlib/Data/Set/Countable.lean b/Mathlib/Data/Set/Countable.lean index bd1f3720faffe..074e6b876960c 100644 --- a/Mathlib/Data/Set/Countable.lean +++ b/Mathlib/Data/Set/Countable.lean @@ -101,8 +101,8 @@ lemma range_enumerateCountable_of_mem {s : Set α} (h : s.Countable) {default : lemma enumerateCountable_mem {s : Set α} (h : s.Countable) {default : α} (h_mem : default ∈ s) (n : ℕ) : enumerateCountable h default n ∈ s := by - conv_rhs => rw [← range_enumerateCountable_of_mem h h_mem] - exact mem_range_self n + convert mem_range_self n + exact (range_enumerateCountable_of_mem h h_mem).symm end Enumerate @@ -257,6 +257,10 @@ theorem countable_setOf_finite_subset {s : Set α} (hs : s.Countable) : lift t to Finset s using ht.of_finite_image Subtype.val_injective.injOn exact mem_range_self _ +/-- The set of finite sets in a countable type is countable. -/ +theorem Countable.setOf_finite [Countable α] : {s : Set α | s.Finite}.Countable := by + simpa using countable_setOf_finite_subset countable_univ + theorem countable_univ_pi {π : α → Type*} [Finite α] {s : ∀ a, Set (π a)} (hs : ∀ a, (s a).Countable) : (pi univ s).Countable := have := fun a ↦ (hs a).to_subtype; .of_equiv _ (Equiv.Set.univPi s).symm @@ -287,9 +291,9 @@ theorem countable_setOf_nonempty_of_disjoint {f : β → Set α} have A : Injective F := by rintro ⟨t, ht⟩ ⟨t', ht'⟩ htt' have A : (f t ∩ f t').Nonempty := by - refine ⟨F ⟨t, ht⟩, hF _, ?_⟩ + refine ⟨F ⟨t, ht⟩, hF ⟨t, _⟩, ?_⟩ rw [htt'] - exact hF _ + exact hF ⟨t', _⟩ simp only [Subtype.mk.injEq] by_contra H exact not_disjoint_iff_nonempty_inter.2 A (hf H) diff --git a/Mathlib/Data/Set/Defs.lean b/Mathlib/Data/Set/Defs.lean index 620c7afe1b44c..4ffdc4697e45f 100644 --- a/Mathlib/Data/Set/Defs.lean +++ b/Mathlib/Data/Set/Defs.lean @@ -1,297 +1,263 @@ /- -Copyright (c) 2016 Jeremy Avigad. All rights reserved. +Copyright (c) 2016 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Jeremy Avigad, Johannes Hölzl, Reid Barton, Scott Morrison, Patrick Massot, Kyle Miller, -Minchao Wu, Yury Kudryashov, Floris van Doorn +Authors: Leonardo de Moura -/ -import Mathlib.Data.SProd -import Mathlib.Data.Subtype -import Mathlib.Order.Notation -import Mathlib.Util.CompileInductive +import Mathlib.Init +import Batteries.Util.ExtendedBinder +import Lean.Elab.Term /-! -# Basic definitions about sets +# Sets -In this file we define various operations on sets. -We also provide basic lemmas needed to unfold the definitions. -More advanced theorems about these definitions are located in other files in `Mathlib/Data/Set`. +This file sets up the theory of sets whose elements have a given type. ## Main definitions -- complement of a set and set difference; -- `Set.Elem`: coercion of a set to a type; it is reducibly equal to `{x // x ∈ s}`; -- `Set.preimage f s`, a.k.a. `f ⁻¹' s`: preimage of a set; -- `Set.range f`: the range of a function; - it is more general than `f '' univ` because it allows functions from `Sort*`; -- `s ×ˢ t`: product of `s : Set α` and `t : Set β` as a set in `α × β`; -- `Set.diagonal`: the diagonal in `α × α`; -- `Set.offDiag s`: the part of `s ×ˢ s` that is off the diagonal; -- `Set.pi`: indexed product of a family of sets `∀ i, Set (α i)`, - as a set in `∀ i, α i`; -- `Set.EqOn f g s`: the predicate saying that two functions are equal on a set; -- `Set.MapsTo f s t`: the predicate syaing that `f` sends all points of `s` to `t; -- `Set.MapsTo.restrict`: restrict `f : α → β` to `f' : s → t` provided that `Set.MapsTo f s t`; -- `Set.restrictPreimage`: restrict `f : α → β` to `f' : (f ⁻¹' t) → t`; -- `Set.InjOn`: the predicate saying that `f` is injective on a set; -- `Set.SurjOn f s t`: the prediate saying that `t ⊆ f '' s`; -- `Set.BijOn f s t`: the predicate saying that `f` is injective on `s` and `f '' s = t`; -- `Set.graphOn`: the graph of a function on a set; -- `Set.LeftInvOn`, `Set.RightInvOn`, `Set.InvOn`: - the predicates saying that `f'` is a left, right or two-sided inverse of `f` on `s`, `t`, or both; -- `Set.image2`: the image of a pair of sets under a binary operation, - mostly useful to define pointwise algebraic operations on sets; -- `Set.seq`: monadic `seq` operation on sets; - we don't use monadic notation to ensure support for maps between different universes; - -## Notations - -- `f '' s`: image of a set; -- `f ⁻¹' s`: preimage of a set; -- `s ×ˢ t`: the product of sets; -- `s ∪ t`: the union of two sets; -- `s ∩ t`: the intersection of two sets; -- `sᶜ`: the complement of a set; -- `s \ t`: the difference of two sets. - -## Keywords - -set, image, preimage --/ - --- https://github.com/leanprover/lean4/issues/2096 -compile_def% Union.union -compile_def% Inter.inter -compile_def% SDiff.sdiff -compile_def% HasCompl.compl -compile_def% EmptyCollection.emptyCollection -compile_def% Insert.insert -compile_def% Singleton.singleton - -attribute [ext] Set.ext - -universe u v w - -namespace Set - -variable {α : Type u} {β : Type v} {γ : Type w} - -@[simp, mfld_simps] theorem mem_setOf_eq {x : α} {p : α → Prop} : (x ∈ {y | p y}) = p x := rfl - -@[simp, mfld_simps] theorem mem_univ (x : α) : x ∈ @univ α := trivial - -instance : HasCompl (Set α) := ⟨fun s ↦ {x | x ∉ s}⟩ - -@[simp] theorem mem_compl_iff (s : Set α) (x : α) : x ∈ sᶜ ↔ x ∉ s := Iff.rfl - -theorem diff_eq (s t : Set α) : s \ t = s ∩ tᶜ := rfl - -@[simp] theorem mem_diff {s t : Set α} (x : α) : x ∈ s \ t ↔ x ∈ s ∧ x ∉ t := Iff.rfl - -theorem mem_diff_of_mem {s t : Set α} {x : α} (h1 : x ∈ s) (h2 : x ∉ t) : x ∈ s \ t := ⟨h1, h2⟩ - --- Porting note: I've introduced this abbreviation, with the `@[coe]` attribute, --- so that `norm_cast` has something to index on. --- It is currently an abbreviation so that instance coming from `Subtype` are available. --- If you're interested in making it a `def`, as it probably should be, --- you'll then need to create additional instances (and possibly prove lemmas about them). --- The first error should appear below at `monotoneOn_iff_monotone`. -/-- Given the set `s`, `Elem s` is the `Type` of element of `s`. -/ -@[coe, reducible] def Elem (s : Set α) : Type u := {x // x ∈ s} - -/-- Coercion from a set to the corresponding subtype. -/ -instance : CoeSort (Set α) (Type u) := ⟨Elem⟩ - -/-- The preimage of `s : Set β` by `f : α → β`, written `f ⁻¹' s`, - is the set of `x : α` such that `f x ∈ s`. -/ -def preimage (f : α → β) (s : Set β) : Set α := {x | f x ∈ s} - -/-- `f ⁻¹' t` denotes the preimage of `t : Set β` under the function `f : α → β`. -/ -infixl:80 " ⁻¹' " => preimage - -@[simp, mfld_simps] -theorem mem_preimage {f : α → β} {s : Set β} {a : α} : a ∈ f ⁻¹' s ↔ f a ∈ s := Iff.rfl - -/-- `f '' s` denotes the image of `s : Set α` under the function `f : α → β`. -/ -infixl:80 " '' " => image - -@[simp] -theorem mem_image (f : α → β) (s : Set α) (y : β) : y ∈ f '' s ↔ ∃ x ∈ s, f x = y := - Iff.rfl +Given a type `X` and a predicate `p : X → Prop`: -@[mfld_simps] -theorem mem_image_of_mem (f : α → β) {x : α} {a : Set α} (h : x ∈ a) : f x ∈ f '' a := - ⟨_, h, rfl⟩ +* `Set X` : the type of sets whose elements have type `X` +* `{a : X | p a} : Set X` : the set of all elements of `X` satisfying `p` +* `{a | p a} : Set X` : a more concise notation for `{a : X | p a}` +* `{f x y | (x : X) (y : Y)} : Set Z` : a more concise notation for `{z : Z | ∃ x y, f x y = z}` +* `{a ∈ S | p a} : Set X` : given `S : Set X`, the subset of `S` consisting of + its elements satisfying `p`. -/-- Restriction of `f` to `s` factors through `s.imageFactorization f : s → f '' s`. -/ -def imageFactorization (f : α → β) (s : Set α) : s → f '' s := fun p => - ⟨f p.1, mem_image_of_mem f p.2⟩ +## Implementation issues -/-- `kernImage f s` is the set of `y` such that `f ⁻¹ y ⊆ s`. -/ -def kernImage (f : α → β) (s : Set α) : Set β := {y | ∀ ⦃x⦄, f x = y → x ∈ s} +As in Lean 3, `Set X := X → Prop` +This file is a port of the core Lean 3 file `lib/lean/library/init/data/set.lean`. -lemma subset_kernImage_iff {s : Set β} {t : Set α} {f : α → β} : s ⊆ kernImage f t ↔ f ⁻¹' s ⊆ t := - ⟨fun h _ hx ↦ h hx rfl, - fun h _ hx y hy ↦ h (show f y ∈ s from hy.symm ▸ hx)⟩ - -section Range - -variable {ι : Sort*} {f : ι → α} - -/-- Range of a function. - -This function is more flexible than `f '' univ`, as the image requires that the domain is in Type -and not an arbitrary Sort. -/ -def range (f : ι → α) : Set α := {x | ∃ y, f y = x} - -@[simp] theorem mem_range {x : α} : x ∈ range f ↔ ∃ y, f y = x := Iff.rfl - -@[mfld_simps] theorem mem_range_self (i : ι) : f i ∈ range f := ⟨i, rfl⟩ - -/-- Any map `f : ι → α` factors through a map `rangeFactorization f : ι → range f`. -/ -def rangeFactorization (f : ι → α) : ι → range f := fun i => ⟨f i, mem_range_self i⟩ - -end Range - -/-- We can use the axiom of choice to pick a preimage for every element of `range f`. -/ -noncomputable def rangeSplitting (f : α → β) : range f → α := fun x => x.2.choose - --- This can not be a `@[simp]` lemma because the head of the left hand side is a variable. -theorem apply_rangeSplitting (f : α → β) (x : range f) : f (rangeSplitting f x) = x := - x.2.choose_spec - -@[simp] -theorem comp_rangeSplitting (f : α → β) : f ∘ rangeSplitting f = Subtype.val := by - ext - simp only [Function.comp_apply] - apply apply_rangeSplitting - -section Prod +-/ -/-- The cartesian product `Set.prod s t` is the set of `(a, b)` such that `a ∈ s` and `b ∈ t`. -/ -def prod (s : Set α) (t : Set β) : Set (α × β) := {p | p.1 ∈ s ∧ p.2 ∈ t} +open Lean Elab Term Meta Batteries.ExtendedBinder -@[default_instance] -instance instSProd : SProd (Set α) (Set β) (Set (α × β)) where - sprod := Set.prod +universe u +variable {α : Type u} -theorem prod_eq (s : Set α) (t : Set β) : s ×ˢ t = Prod.fst ⁻¹' s ∩ Prod.snd ⁻¹' t := rfl +/-- A set is a collection of elements of some type `α`. -variable {a : α} {b : β} {s : Set α} {t : Set β} {p : α × β} +Although `Set` is defined as `α → Prop`, this is an implementation detail which should not be +relied on. Instead, `setOf` and membership of a set (`∈`) should be used to convert between sets +and predicates. +-/ +def Set (α : Type u) := α → Prop -theorem mem_prod_eq : (p ∈ s ×ˢ t) = (p.1 ∈ s ∧ p.2 ∈ t) := rfl +/-- Turn a predicate `p : α → Prop` into a set, also written as `{x | p x}` -/ +def setOf {α : Type u} (p : α → Prop) : Set α := + p -@[simp, mfld_simps] -theorem mem_prod : p ∈ s ×ˢ t ↔ p.1 ∈ s ∧ p.2 ∈ t := .rfl +namespace Set -@[mfld_simps] -theorem prod_mk_mem_set_prod_eq : ((a, b) ∈ s ×ˢ t) = (a ∈ s ∧ b ∈ t) := rfl +/-- Membership in a set -/ +protected def Mem (s : Set α) (a : α) : Prop := + s a -theorem mk_mem_prod (ha : a ∈ s) (hb : b ∈ t) : (a, b) ∈ s ×ˢ t := ⟨ha, hb⟩ +instance : Membership α (Set α) := + ⟨Set.Mem⟩ -end Prod +theorem ext {a b : Set α} (h : ∀ (x : α), x ∈ a ↔ x ∈ b) : a = b := + funext (fun x ↦ propext (h x)) -section Diagonal -/-- `diagonal α` is the set of `α × α` consisting of all pairs of the form `(a, a)`. -/ -def diagonal (α : Type*) : Set (α × α) := {p | p.1 = p.2} +/-- The subset relation on sets. `s ⊆ t` means that all elements of `s` are elements of `t`. -theorem mem_diagonal (x : α) : (x, x) ∈ diagonal α := rfl +Note that you should **not** use this definition directly, but instead write `s ⊆ t`. -/ +protected def Subset (s₁ s₂ : Set α) := + ∀ ⦃a⦄, a ∈ s₁ → a ∈ s₂ -@[simp] theorem mem_diagonal_iff {x : α × α} : x ∈ diagonal α ↔ x.1 = x.2 := .rfl +/-- Porting note: we introduce `≤` before `⊆` to help the unifier when applying lattice theorems +to subset hypotheses. -/ +instance : LE (Set α) := + ⟨Set.Subset⟩ -/-- The off-diagonal of a set `s` is the set of pairs `(a, b)` with `a, b ∈ s` and `a ≠ b`. -/ -def offDiag (s : Set α) : Set (α × α) := {x | x.1 ∈ s ∧ x.2 ∈ s ∧ x.1 ≠ x.2} +instance : HasSubset (Set α) := + ⟨(· ≤ ·)⟩ -@[simp] -theorem mem_offDiag {x : α × α} {s : Set α} : x ∈ s.offDiag ↔ x.1 ∈ s ∧ x.2 ∈ s ∧ x.1 ≠ x.2 := - Iff.rfl +instance : EmptyCollection (Set α) := + ⟨fun _ ↦ False⟩ -end Diagonal +end Set -section Pi +namespace Mathlib.Meta -variable {ι : Type*} {α : ι → Type*} +/-- Set builder syntax. This can be elaborated to either a `Set` or a `Finset` depending on context. -/-- Given an index set `ι` and a family of sets `t : Π i, Set (α i)`, `pi s t` -is the set of dependent functions `f : Πa, π a` such that `f a` belongs to `t a` -whenever `a ∈ s`. -/ -def pi (s : Set ι) (t : ∀ i, Set (α i)) : Set (∀ i, α i) := {f | ∀ i ∈ s, f i ∈ t i} +The elaborators for this syntax are located in: +* `Data.Set.Defs` for the `Set` builder notation elaborator for syntax of the form `{x | p x}`, + `{x : α | p x}`, `{binder x | p x}`. +* `Data.Finset.Basic` for the `Finset` builder notation elaborator for syntax of the form + `{x ∈ s | p x}`. +* `Data.Fintype.Basic` for the `Finset` builder notation elaborator for syntax of the form + `{x | p x}`, `{x : α | p x}`, `{x ∉ s | p x}`, `{x ≠ a | p x}`. +* `Order.LocallyFinite.Basic` for the `Finset` builder notation elaborator for syntax of the form + `{x ≤ a | p x}`, `{x ≥ a | p x}`, `{x < a | p x}`, `{x > a | p x}`. +-/ +syntax (name := setBuilder) "{" extBinder " | " term "}" : term + +/-- Elaborate set builder notation for `Set`. + +* `{x | p x}` is elaborated as `Set.setOf fun x ↦ p x` +* `{x : α | p x}` is elaborated as `Set.setOf fun x : α ↦ p x` +* `{binder x | p x}`, where `x` is bound by the `binder` binder, is elaborated as + `{x | binder x ∧ p x}`. The typical example is `{x ∈ s | p x}`, which is elaborated as + `{x | x ∈ s ∧ p x}`. The possible binders are + * `· ∈ s`, `· ∉ s` + * `· ⊆ s`, `· ⊂ s`, `· ⊇ s`, `· ⊃ s` + * `· ≤ a`, `· ≥ a`, `· < a`, `· > a`, `· ≠ a` + + More binders can be declared using the `binder_predicate` command, see `Init.BinderPredicates` for + more info. + +See also +* `Data.Finset.Basic` for the `Finset` builder notation elaborator partly overriding this one for + syntax of the form `{x ∈ s | p x}`. +* `Data.Fintype.Basic` for the `Finset` builder notation elaborator partly overriding this one for + syntax of the form `{x | p x}`, `{x : α | p x}`, `{x ∉ s | p x}`, `{x ≠ a | p x}`. +* `Order.LocallyFinite.Basic` for the `Finset` builder notation elaborator partly overriding this + one for syntax of the form `{x ≤ a | p x}`, `{x ≥ a | p x}`, `{x < a | p x}`, `{x > a | p x}`. +-/ +@[term_elab setBuilder] +def elabSetBuilder : TermElab + | `({ $x:ident | $p }), expectedType? => do + elabTerm (← `(setOf fun $x:ident ↦ $p)) expectedType? + | `({ $x:ident : $t | $p }), expectedType? => do + elabTerm (← `(setOf fun $x:ident : $t ↦ $p)) expectedType? + | `({ $x:ident $b:binderPred | $p }), expectedType? => do + elabTerm (← `(setOf fun $x:ident ↦ satisfies_binder_pred% $x $b ∧ $p)) expectedType? + | _, _ => throwUnsupportedSyntax + +/-- Unexpander for set builder notation. -/ +@[app_unexpander setOf] +def setOf.unexpander : Lean.PrettyPrinter.Unexpander + | `($_ fun $x:ident ↦ $p) => `({ $x:ident | $p }) + | `($_ fun ($x:ident : $ty:term) ↦ $p) => `({ $x:ident : $ty:term | $p }) + | _ => throw () + +open Batteries.ExtendedBinder in +/-- +`{ f x y | (x : X) (y : Y) }` is notation for the set of elements `f x y` constructed from the +binders `x` and `y`, equivalent to `{z : Z | ∃ x y, f x y = z}`. + +If `f x y` is a single identifier, it must be parenthesized to avoid ambiguity with `{x | p x}`; +for instance, `{(x) | (x : Nat) (y : Nat) (_hxy : x = y^2)}`. +-/ +macro (priority := low) "{" t:term " | " bs:extBinders "}" : term => + `({x | ∃ᵉ $bs:extBinders, $t = x}) + +/-- +* `{ pat : X | p }` is notation for pattern matching in set-builder notation, + where `pat` is a pattern that is matched by all objects of type `X` + and `p` is a proposition that can refer to variables in the pattern. + It is the set of all objects of type `X` which, when matched with the pattern `pat`, + make `p` come out true. +* `{ pat | p }` is the same, but in the case when the type `X` can be inferred. + +For example, `{ (m, n) : ℕ × ℕ | m * n = 12 }` denotes the set of all ordered pairs of +natural numbers whose product is 12. + +Note that if the type ascription is left out and `p` can be interpreted as an extended binder, +then the extended binder interpretation will be used. For example, `{ n + 1 | n < 3 }` will +be interpreted as `{ x : Nat | ∃ n < 3, n + 1 = x }` rather than using pattern matching. +-/ +macro (name := macroPattSetBuilder) (priority := low-1) + "{" pat:term " : " t:term " | " p:term "}" : term => + `({ x : $t | match x with | $pat => $p }) + +@[inherit_doc macroPattSetBuilder] +macro (priority := low-1) "{" pat:term " | " p:term "}" : term => + `({ x | match x with | $pat => $p }) + +/-- Pretty printing for set-builder notation with pattern matching. -/ +@[app_unexpander setOf] +def setOfPatternMatchUnexpander : Lean.PrettyPrinter.Unexpander + | `($_ fun $x:ident ↦ match $y:ident with | $pat => $p) => + if x == y then + `({ $pat:term | $p:term }) + else + throw () + | `($_ fun ($x:ident : $ty:term) ↦ match $y:ident with | $pat => $p) => + if x == y then + `({ $pat:term : $ty:term | $p:term }) + else + throw () + | _ => throw () + +end Mathlib.Meta -variable {s : Set ι} {t : ∀ i, Set (α i)} {f : ∀ i, α i} +namespace Set -@[simp] theorem mem_pi : f ∈ s.pi t ↔ ∀ i ∈ s, f i ∈ t i := .rfl +/-- The universal set on a type `α` is the set containing all elements of `α`. -theorem mem_univ_pi : f ∈ pi univ t ↔ ∀ i, f i ∈ t i := by simp +This is conceptually the "same as" `α` (in set theory, it is actually the same), but type theory +makes the distinction that `α` is a type while `Set.univ` is a term of type `Set α`. `Set.univ` can +itself be coerced to a type `↥Set.univ` which is in bijection with (but distinct from) `α`. -/ +def univ : Set α := {_a | True} -end Pi +/-- `Set.insert a s` is the set `{a} ∪ s`. -/-- Two functions `f₁ f₂ : α → β` are equal on `s` if `f₁ x = f₂ x` for all `x ∈ s`. -/ -def EqOn (f₁ f₂ : α → β) (s : Set α) : Prop := ∀ ⦃x⦄, x ∈ s → f₁ x = f₂ x +Note that you should **not** use this definition directly, but instead write `insert a s` (which is +mediated by the `Insert` typeclass). -/ +protected def insert (a : α) (s : Set α) : Set α := {b | b = a ∨ b ∈ s} -/-- `MapsTo f a b` means that the image of `a` is contained in `b`. -/ -def MapsTo (f : α → β) (s : Set α) (t : Set β) : Prop := ∀ ⦃x⦄, x ∈ s → f x ∈ t +instance : Insert α (Set α) := ⟨Set.insert⟩ -theorem mapsTo_image (f : α → β) (s : Set α) : MapsTo f s (f '' s) := fun _ ↦ mem_image_of_mem f +/-- The singleton of an element `a` is the set with `a` as a single element. -theorem mapsTo_preimage (f : α → β) (t : Set β) : MapsTo f (f ⁻¹' t) t := fun _ ↦ id +Note that you should **not** use this definition directly, but instead write `{a}`. -/ +protected def singleton (a : α) : Set α := {b | b = a} -/-- Given a map `f` sending `s : Set α` into `t : Set β`, restrict domain of `f` to `s` -and the codomain to `t`. Same as `Subtype.map`. -/ -def MapsTo.restrict (f : α → β) (s : Set α) (t : Set β) (h : MapsTo f s t) : s → t := - Subtype.map f h +instance instSingletonSet : Singleton α (Set α) := ⟨Set.singleton⟩ -/-- The restriction of a function onto the preimage of a set. -/ -@[simps!] -def restrictPreimage (t : Set β) (f : α → β) : f ⁻¹' t → t := - (Set.mapsTo_preimage f t).restrict _ _ _ +/-- The union of two sets `s` and `t` is the set of elements contained in either `s` or `t`. -/-- `f` is injective on `a` if the restriction of `f` to `a` is injective. -/ -def InjOn (f : α → β) (s : Set α) : Prop := - ∀ ⦃x₁ : α⦄, x₁ ∈ s → ∀ ⦃x₂ : α⦄, x₂ ∈ s → f x₁ = f x₂ → x₁ = x₂ +Note that you should **not** use this definition directly, but instead write `s ∪ t`. -/ +protected def union (s₁ s₂ : Set α) : Set α := {a | a ∈ s₁ ∨ a ∈ s₂} -/-- The graph of a function `f : α → β` on a set `s`. -/ -def graphOn (f : α → β) (s : Set α) : Set (α × β) := (fun x ↦ (x, f x)) '' s +instance : Union (Set α) := ⟨Set.union⟩ -/-- `f` is surjective from `a` to `b` if `b` is contained in the image of `a`. -/ -def SurjOn (f : α → β) (s : Set α) (t : Set β) : Prop := t ⊆ f '' s +/-- The intersection of two sets `s` and `t` is the set of elements contained in both `s` and `t`. -/-- `f` is bijective from `s` to `t` if `f` is injective on `s` and `f '' s = t`. -/ -def BijOn (f : α → β) (s : Set α) (t : Set β) : Prop := MapsTo f s t ∧ InjOn f s ∧ SurjOn f s t +Note that you should **not** use this definition directly, but instead write `s ∩ t`. -/ +protected def inter (s₁ s₂ : Set α) : Set α := {a | a ∈ s₁ ∧ a ∈ s₂} -/-- `g` is a left inverse to `f` on `a` means that `g (f x) = x` for all `x ∈ a`. -/ -def LeftInvOn (f' : β → α) (f : α → β) (s : Set α) : Prop := ∀ ⦃x⦄, x ∈ s → f' (f x) = x +instance : Inter (Set α) := ⟨Set.inter⟩ -/-- `g` is a right inverse to `f` on `b` if `f (g x) = x` for all `x ∈ b`. -/ -abbrev RightInvOn (f' : β → α) (f : α → β) (t : Set β) : Prop := LeftInvOn f f' t +/-- The complement of a set `s` is the set of elements not contained in `s`. -/-- `g` is an inverse to `f` viewed as a map from `a` to `b` -/ -def InvOn (g : β → α) (f : α → β) (s : Set α) (t : Set β) : Prop := - LeftInvOn g f s ∧ RightInvOn g f t +Note that you should **not** use this definition directly, but instead write `sᶜ`. -/ +protected def compl (s : Set α) : Set α := {a | a ∉ s} -section image2 +/-- The difference of two sets `s` and `t` is the set of elements contained in `s` but not in `t`. -/-- The image of a binary function `f : α → β → γ` as a function `Set α → Set β → Set γ`. -Mathematically this should be thought of as the image of the corresponding function `α × β → γ`. -/ -def image2 (f : α → β → γ) (s : Set α) (t : Set β) : Set γ := {c | ∃ a ∈ s, ∃ b ∈ t, f a b = c} +Note that you should **not** use this definition directly, but instead write `s \ t`. -/ +protected def diff (s t : Set α) : Set α := {a ∈ s | a ∉ t} -variable {f : α → β → γ} {s : Set α} {t : Set β} {a : α} {b : β} {c : γ} +instance : SDiff (Set α) := ⟨Set.diff⟩ -@[simp] theorem mem_image2 : c ∈ image2 f s t ↔ ∃ a ∈ s, ∃ b ∈ t, f a b = c := .rfl +/-- `𝒫 s` is the set of all subsets of `s`. -/ +def powerset (s : Set α) : Set (Set α) := {t | t ⊆ s} -theorem mem_image2_of_mem (ha : a ∈ s) (hb : b ∈ t) : f a b ∈ image2 f s t := - ⟨a, ha, b, hb, rfl⟩ +@[inherit_doc] prefix:100 "𝒫" => powerset -end image2 +universe v in +/-- The image of `s : Set α` by `f : α → β`, written `f '' s`, is the set of `b : β` such that +`f a = b` for some `a ∈ s`. -/ +def image {β : Type v} (f : α → β) (s : Set α) : Set β := {f a | a ∈ s} -/-- Given a set `s` of functions `α → β` and `t : Set α`, `seq s t` is the union of `f '' t` over -all `f ∈ s`. -/ -def seq (s : Set (α → β)) (t : Set α) : Set β := image2 (fun f ↦ f) s t +instance : Functor Set where map := @Set.image -@[simp] -theorem mem_seq_iff {s : Set (α → β)} {t : Set α} {b : β} : - b ∈ seq s t ↔ ∃ f ∈ s, ∃ a ∈ t, (f : α → β) a = b := - Iff.rfl +instance : LawfulFunctor Set where + id_map _ := funext fun _ ↦ propext ⟨fun ⟨_, sb, rfl⟩ ↦ sb, fun sb ↦ ⟨_, sb, rfl⟩⟩ + comp_map g h _ := funext <| fun c ↦ propext + ⟨fun ⟨a, ⟨h₁, h₂⟩⟩ ↦ ⟨g a, ⟨⟨a, ⟨h₁, rfl⟩⟩, h₂⟩⟩, + fun ⟨_, ⟨⟨a, ⟨h₁, h₂⟩⟩, h₃⟩⟩ ↦ ⟨a, ⟨h₁, show h (g a) = c from h₂ ▸ h₃⟩⟩⟩ + map_const := rfl -lemma seq_eq_image2 (s : Set (α → β)) (t : Set α) : seq s t = image2 (fun f a ↦ f a) s t := rfl +/-- The property `s.Nonempty` expresses the fact that the set `s` is not empty. It should be used +in theorem assumptions instead of `∃ x, x ∈ s` or `s ≠ ∅` as it gives access to a nice API thanks +to the dot notation. -/ +protected def Nonempty (s : Set α) : Prop := + ∃ x, x ∈ s end Set diff --git a/Mathlib/Data/Set/Enumerate.lean b/Mathlib/Data/Set/Enumerate.lean index c6313777fa313..fd4f8dbb791b1 100644 --- a/Mathlib/Data/Set/Enumerate.lean +++ b/Mathlib/Data/Set/Enumerate.lean @@ -88,7 +88,8 @@ theorem enumerate_inj {n₁ n₂ : ℕ} {a : α} {s : Set α} (h_sel : ∀ s a, cases h : sel s with /- Porting note: The original covered both goals with just `simp_all <;> tauto` -/ | none => - simp_all only [add_comm, self_eq_add_left, Nat.add_succ, enumerate_eq_none_of_sel _ h] + simp_all only [add_comm, self_eq_add_left, Nat.add_succ, enumerate_eq_none_of_sel _ h, + reduceCtorEq] | some => simp_all only [add_comm, self_eq_add_left, enumerate, Option.some.injEq, Nat.add_succ, Nat.succ.injEq] diff --git a/Mathlib/Data/Set/Finite.lean b/Mathlib/Data/Set/Finite.lean index 933b71188dd78..3807e40b76e3c 100644 --- a/Mathlib/Data/Set/Finite.lean +++ b/Mathlib/Data/Set/Finite.lean @@ -280,6 +280,9 @@ section FintypeInstances instance fintypeUniv [Fintype α] : Fintype (@univ α) := Fintype.ofEquiv α (Equiv.Set.univ α).symm +-- Redeclared with appropriate keys +instance fintypeTop [Fintype α] : Fintype (⊤ : Set α) := inferInstanceAs (Fintype (univ : Set α)) + /-- If `(Set.univ : Set α)` is finite then `α` is a finite type. -/ noncomputable def fintypeOfFiniteUniv (H : (univ (α := α)).Finite) : Fintype α := @Fintype.ofEquiv _ (univ : Set α) H.fintype (Equiv.Set.univ _) @@ -1348,9 +1351,10 @@ theorem exists_upper_bound_image [Nonempty α] [LinearOrder β] (s : Set α) (f theorem Finite.iSup_biInf_of_monotone {ι ι' α : Type*} [Preorder ι'] [Nonempty ι'] [IsDirected ι' (· ≤ ·)] [Order.Frame α] {s : Set ι} (hs : s.Finite) {f : ι → ι' → α} (hf : ∀ i ∈ s, Monotone (f i)) : ⨆ j, ⨅ i ∈ s, f i j = ⨅ i ∈ s, ⨆ j, f i j := by - induction' s, hs using Set.Finite.dinduction_on with a s _ _ ihs hf - · simp [iSup_const] - · rw [forall_mem_insert] at hf + induction s, hs using Set.Finite.dinduction_on with + | H0 => simp [iSup_const] + | H1 _ _ ihs => + rw [forall_mem_insert] at hf simp only [iInf_insert, ← ihs hf.2] exact iSup_inf_of_monotone hf.1 fun j₁ j₂ hj => iInf₂_mono fun i hi => hf.2 i hi hj @@ -1563,3 +1567,5 @@ theorem DirectedOn.exists_mem_subset_of_finset_subset_biUnion {α ι : Type*} {f rw [Set.biUnion_eq_iUnion] at hs haveI := hn.coe_sort simpa using (directed_comp.2 hc.directed_val).exists_mem_subset_of_finset_subset_biUnion hs + +set_option linter.style.longFile 1700 diff --git a/Mathlib/Data/Set/Function.lean b/Mathlib/Data/Set/Function.lean index 937769bbf1c82..56e1886f2c539 100644 --- a/Mathlib/Data/Set/Function.lean +++ b/Mathlib/Data/Set/Function.lean @@ -253,7 +253,7 @@ theorem EqOn.congr_strictAntiOn (h : s.EqOn f₁ f₂) : StrictAntiOn f₁ s ↔ end Order -/-! ### Monotonicity lemmas-/ +/-! ### Monotonicity lemmas -/ section Mono variable {s s₁ s₂ : Set α} {f f₁ f₂ : α → β} [Preorder α] [Preorder β] @@ -303,8 +303,9 @@ theorem MapsTo.val_restrict_apply (h : MapsTo f s t) (x : s) : (h.restrict f s t theorem MapsTo.coe_iterate_restrict {f : α → α} (h : MapsTo f s s) (x : s) (k : ℕ) : h.restrict^[k] x = f^[k] x := by - induction' k with k ih; · simp - simp only [iterate_succ', comp_apply, val_restrict_apply, ih] + induction k with + | zero => simp + | succ k ih => simp only [iterate_succ', comp_apply, val_restrict_apply, ih] /-- Restricting the domain and then the codomain is the same as `MapsTo.restrict`. -/ @[simp] @@ -379,9 +380,9 @@ theorem MapsTo.iterate_restrict {f : α → α} {s : Set α} (h : MapsTo f s s) (h.restrict f s s)^[n] = (h.iterate n).restrict _ _ _ := by funext x rw [Subtype.ext_iff, MapsTo.val_restrict_apply] - induction' n with n ihn generalizing x - · rfl - · simp [Nat.iterate, ihn] + induction n generalizing x with + | zero => rfl + | succ n ihn => simp [Nat.iterate, ihn] lemma mapsTo_of_subsingleton' [Subsingleton β] (f : α → β) (h : s.Nonempty → t.Nonempty) : MapsTo f s t := @@ -1132,15 +1133,17 @@ end Set /-! ### `invFunOn` is a left/right inverse -/ namespace Function -variable [Nonempty α] {s : Set α} {f : α → β} {a : α} {b : β} +variable {s : Set α} {f : α → β} {a : α} {b : β} attribute [local instance] Classical.propDecidable /-- Construct the inverse for a function `f` on domain `s`. This function is a right inverse of `f` on `f '' s`. For a computable version, see `Function.Embedding.invOfMemRange`. -/ -noncomputable def invFunOn (f : α → β) (s : Set α) (b : β) : α := +noncomputable def invFunOn [Nonempty α] (f : α → β) (s : Set α) (b : β) : α := if h : ∃ a, a ∈ s ∧ f a = b then Classical.choose h else Classical.choice ‹Nonempty α› +variable [Nonempty α] + theorem invFunOn_pos (h : ∃ a ∈ s, f a = b) : invFunOn f s b ∈ s ∧ f (invFunOn f s b) = b := by rw [invFunOn, dif_pos h] exact Classical.choose_spec h @@ -1738,3 +1741,5 @@ lemma bijOn_swap (ha : a ∈ s) (hb : b ∈ s) : BijOn (swap a b) s s := simp [*, swap_apply_of_ne_of_ne] end Equiv + +set_option linter.style.longFile 1900 diff --git a/Mathlib/Data/Set/Functor.lean b/Mathlib/Data/Set/Functor.lean index c907a7750a067..86ef698729203 100644 --- a/Mathlib/Data/Set/Functor.lean +++ b/Mathlib/Data/Set/Functor.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Leonardo de Moura -/ import Mathlib.Data.Set.Lattice -import Mathlib.Init.Set +import Mathlib.Data.Set.Defs import Mathlib.Control.Basic import Mathlib.Data.Set.Notation diff --git a/Mathlib/Data/Set/Image.lean b/Mathlib/Data/Set/Image.lean index 482de2b723d5d..09b79da91cf44 100644 --- a/Mathlib/Data/Set/Image.lean +++ b/Mathlib/Data/Set/Image.lean @@ -4,9 +4,10 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad, Leonardo de Moura -/ import Mathlib.Data.Set.Subsingleton -import Mathlib.Order.WithBot import Mathlib.Tactic.Use import Batteries.Tactic.Congr +import Mathlib.Order.TypeTags +import Mathlib.Data.Option.Basic /-! # Images and preimages of sets @@ -135,8 +136,9 @@ theorem preimage_comp_eq : preimage (g ∘ f) = preimage f ∘ preimage g := rfl theorem preimage_iterate_eq {f : α → α} {n : ℕ} : Set.preimage f^[n] = (Set.preimage f)^[n] := by - induction' n with n ih; · simp - rw [iterate_succ, iterate_succ', preimage_comp_eq, ih] + induction n with + | zero => simp + | succ n ih => rw [iterate_succ, iterate_succ', preimage_comp_eq, ih] theorem preimage_preimage {g : β → γ} {f : α → β} {s : Set γ} : f ⁻¹' (g ⁻¹' s) = (fun x => g (f x)) ⁻¹' s := @@ -175,7 +177,7 @@ section Image variable {f : α → β} {s t : Set α} --- Porting note: `Set.image` is already defined in `Init.Set` +-- Porting note: `Set.image` is already defined in `Data.Set.Defs` @[deprecated mem_image (since := "2024-03-23")] theorem mem_image_iff_bex {f : α → β} {s : Set α} {y : β} : @@ -299,7 +301,7 @@ theorem image_eq_empty {α β} {f : α → β} {s : Set α} : f '' s = ∅ ↔ s simp only [eq_empty_iff_forall_not_mem] exact ⟨fun H a ha => H _ ⟨_, ha, rfl⟩, fun H b ⟨_, ha, _⟩ => H _ ha⟩ --- Porting note: `compl` is already defined in `Init.Set` +-- Porting note: `compl` is already defined in `Data.Set.Defs` theorem preimage_compl_eq_image_compl [BooleanAlgebra α] (S : Set α) : HasCompl.compl ⁻¹' S = HasCompl.compl '' S := Set.ext fun x => @@ -1283,13 +1285,13 @@ theorem preimage_injective : Injective (preimage f) ↔ Surjective f := by @[simp] theorem preimage_surjective : Surjective (preimage f) ↔ Injective f := by refine ⟨fun h x x' hx => ?_, Injective.preimage_surjective⟩ - cases' h {x} with s hs; have := mem_singleton x + rcases h {x} with ⟨s, hs⟩; have := mem_singleton x rwa [← hs, mem_preimage, hx, ← mem_preimage, hs, mem_singleton_iff, eq_comm] at this @[simp] theorem image_surjective : Surjective (image f) ↔ Surjective f := by refine ⟨fun h y => ?_, Surjective.image_surjective⟩ - cases' h {y} with s hs + rcases h {y} with ⟨s, hs⟩ have := mem_singleton y; rw [← hs] at this; rcases this with ⟨x, _, hx⟩ exact ⟨x, hx⟩ diff --git a/Mathlib/Data/Set/Lattice.lean b/Mathlib/Data/Set/Lattice.lean index c994bb0f5366b..fbff041791382 100644 --- a/Mathlib/Data/Set/Lattice.lean +++ b/Mathlib/Data/Set/Lattice.lean @@ -686,6 +686,10 @@ theorem iInter_iInter_eq_or_left {b : β} {p : β → Prop} {s : ∀ x : β, x = ⋂ (x) (h), s x h = s b (Or.inl rfl) ∩ ⋂ (x) (h : p x), s x (Or.inr h) := by simp only [iInter_or, iInter_inter_distrib, iInter_iInter_eq_left] +lemma iUnion_sum {s : α ⊕ β → Set γ} : ⋃ x, s x = (⋃ x, s (.inl x)) ∪ ⋃ x, s (.inr x) := iSup_sum + +lemma iInter_sum {s : α ⊕ β → Set γ} : ⋂ x, s x = (⋂ x, s (.inl x)) ∩ ⋂ x, s (.inr x) := iInf_sum + /-! ### Bounded unions and intersections -/ @@ -1931,3 +1935,5 @@ lemma forall_sUnion {S : Set (Set α)} {p : α → Prop} : lemma exists_sUnion {S : Set (Set α)} {p : α → Prop} : (∃ x ∈ ⋃₀ S, p x) ↔ ∃ s ∈ S, ∃ x ∈ s, p x := by simp_rw [← exists_prop, ← iSup_Prop_eq, iSup_sUnion] + +set_option linter.style.longFile 2100 diff --git a/Mathlib/Data/Set/List.lean b/Mathlib/Data/Set/List.lean index bbd932e0d0918..60839e4f416e6 100644 --- a/Mathlib/Data/Set/List.lean +++ b/Mathlib/Data/Set/List.lean @@ -22,10 +22,12 @@ namespace Set theorem range_list_map (f : α → β) : range (map f) = { l | ∀ x ∈ l, x ∈ range f } := by refine antisymm (range_subset_iff.2 fun l => forall_mem_map.2 fun y _ => mem_range_self _) fun l hl => ?_ - induction' l with a l ihl; · exact ⟨[], rfl⟩ - rcases ihl fun x hx => hl x <| subset_cons_self _ _ hx with ⟨l, rfl⟩ - rcases hl a (mem_cons_self _ _) with ⟨a, rfl⟩ - exact ⟨a :: l, map_cons _ _ _⟩ + induction l with + | nil => exact ⟨[], rfl⟩ + | cons a l ihl => + rcases ihl fun x hx => hl x <| subset_cons_self _ _ hx with ⟨l, rfl⟩ + rcases hl a (mem_cons_self _ _) with ⟨a, rfl⟩ + exact ⟨a :: l, map_cons _ _ _⟩ theorem range_list_map_coe (s : Set α) : range (map ((↑) : s → α)) = { l | ∀ x ∈ l, x ∈ s } := by rw [range_list_map, Subtype.range_coe] @@ -46,7 +48,7 @@ theorem range_list_get? : range l.get? = insert none (some '' { x | x ∈ l }) : theorem range_list_getD (d : α) : (range fun n : Nat => l[n]?.getD d) = insert d { x | x ∈ l } := calc (range fun n => l[n]?.getD d) = (fun o : Option α => o.getD d) '' range l.get? := by - simp [← range_comp, (· ∘ ·)] + simp [← range_comp, Function.comp_def] _ = insert d { x | x ∈ l } := by simp only [range_list_get?, image_insert_eq, Option.getD, image_image, image_id'] diff --git a/Mathlib/Data/Set/Operations.lean b/Mathlib/Data/Set/Operations.lean new file mode 100644 index 0000000000000..620c7afe1b44c --- /dev/null +++ b/Mathlib/Data/Set/Operations.lean @@ -0,0 +1,297 @@ +/- +Copyright (c) 2016 Jeremy Avigad. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Jeremy Avigad, Johannes Hölzl, Reid Barton, Scott Morrison, Patrick Massot, Kyle Miller, +Minchao Wu, Yury Kudryashov, Floris van Doorn +-/ +import Mathlib.Data.SProd +import Mathlib.Data.Subtype +import Mathlib.Order.Notation +import Mathlib.Util.CompileInductive + +/-! +# Basic definitions about sets + +In this file we define various operations on sets. +We also provide basic lemmas needed to unfold the definitions. +More advanced theorems about these definitions are located in other files in `Mathlib/Data/Set`. + +## Main definitions + +- complement of a set and set difference; +- `Set.Elem`: coercion of a set to a type; it is reducibly equal to `{x // x ∈ s}`; +- `Set.preimage f s`, a.k.a. `f ⁻¹' s`: preimage of a set; +- `Set.range f`: the range of a function; + it is more general than `f '' univ` because it allows functions from `Sort*`; +- `s ×ˢ t`: product of `s : Set α` and `t : Set β` as a set in `α × β`; +- `Set.diagonal`: the diagonal in `α × α`; +- `Set.offDiag s`: the part of `s ×ˢ s` that is off the diagonal; +- `Set.pi`: indexed product of a family of sets `∀ i, Set (α i)`, + as a set in `∀ i, α i`; +- `Set.EqOn f g s`: the predicate saying that two functions are equal on a set; +- `Set.MapsTo f s t`: the predicate syaing that `f` sends all points of `s` to `t; +- `Set.MapsTo.restrict`: restrict `f : α → β` to `f' : s → t` provided that `Set.MapsTo f s t`; +- `Set.restrictPreimage`: restrict `f : α → β` to `f' : (f ⁻¹' t) → t`; +- `Set.InjOn`: the predicate saying that `f` is injective on a set; +- `Set.SurjOn f s t`: the prediate saying that `t ⊆ f '' s`; +- `Set.BijOn f s t`: the predicate saying that `f` is injective on `s` and `f '' s = t`; +- `Set.graphOn`: the graph of a function on a set; +- `Set.LeftInvOn`, `Set.RightInvOn`, `Set.InvOn`: + the predicates saying that `f'` is a left, right or two-sided inverse of `f` on `s`, `t`, or both; +- `Set.image2`: the image of a pair of sets under a binary operation, + mostly useful to define pointwise algebraic operations on sets; +- `Set.seq`: monadic `seq` operation on sets; + we don't use monadic notation to ensure support for maps between different universes; + +## Notations + +- `f '' s`: image of a set; +- `f ⁻¹' s`: preimage of a set; +- `s ×ˢ t`: the product of sets; +- `s ∪ t`: the union of two sets; +- `s ∩ t`: the intersection of two sets; +- `sᶜ`: the complement of a set; +- `s \ t`: the difference of two sets. + +## Keywords + +set, image, preimage +-/ + +-- https://github.com/leanprover/lean4/issues/2096 +compile_def% Union.union +compile_def% Inter.inter +compile_def% SDiff.sdiff +compile_def% HasCompl.compl +compile_def% EmptyCollection.emptyCollection +compile_def% Insert.insert +compile_def% Singleton.singleton + +attribute [ext] Set.ext + +universe u v w + +namespace Set + +variable {α : Type u} {β : Type v} {γ : Type w} + +@[simp, mfld_simps] theorem mem_setOf_eq {x : α} {p : α → Prop} : (x ∈ {y | p y}) = p x := rfl + +@[simp, mfld_simps] theorem mem_univ (x : α) : x ∈ @univ α := trivial + +instance : HasCompl (Set α) := ⟨fun s ↦ {x | x ∉ s}⟩ + +@[simp] theorem mem_compl_iff (s : Set α) (x : α) : x ∈ sᶜ ↔ x ∉ s := Iff.rfl + +theorem diff_eq (s t : Set α) : s \ t = s ∩ tᶜ := rfl + +@[simp] theorem mem_diff {s t : Set α} (x : α) : x ∈ s \ t ↔ x ∈ s ∧ x ∉ t := Iff.rfl + +theorem mem_diff_of_mem {s t : Set α} {x : α} (h1 : x ∈ s) (h2 : x ∉ t) : x ∈ s \ t := ⟨h1, h2⟩ + +-- Porting note: I've introduced this abbreviation, with the `@[coe]` attribute, +-- so that `norm_cast` has something to index on. +-- It is currently an abbreviation so that instance coming from `Subtype` are available. +-- If you're interested in making it a `def`, as it probably should be, +-- you'll then need to create additional instances (and possibly prove lemmas about them). +-- The first error should appear below at `monotoneOn_iff_monotone`. +/-- Given the set `s`, `Elem s` is the `Type` of element of `s`. -/ +@[coe, reducible] def Elem (s : Set α) : Type u := {x // x ∈ s} + +/-- Coercion from a set to the corresponding subtype. -/ +instance : CoeSort (Set α) (Type u) := ⟨Elem⟩ + +/-- The preimage of `s : Set β` by `f : α → β`, written `f ⁻¹' s`, + is the set of `x : α` such that `f x ∈ s`. -/ +def preimage (f : α → β) (s : Set β) : Set α := {x | f x ∈ s} + +/-- `f ⁻¹' t` denotes the preimage of `t : Set β` under the function `f : α → β`. -/ +infixl:80 " ⁻¹' " => preimage + +@[simp, mfld_simps] +theorem mem_preimage {f : α → β} {s : Set β} {a : α} : a ∈ f ⁻¹' s ↔ f a ∈ s := Iff.rfl + +/-- `f '' s` denotes the image of `s : Set α` under the function `f : α → β`. -/ +infixl:80 " '' " => image + +@[simp] +theorem mem_image (f : α → β) (s : Set α) (y : β) : y ∈ f '' s ↔ ∃ x ∈ s, f x = y := + Iff.rfl + +@[mfld_simps] +theorem mem_image_of_mem (f : α → β) {x : α} {a : Set α} (h : x ∈ a) : f x ∈ f '' a := + ⟨_, h, rfl⟩ + +/-- Restriction of `f` to `s` factors through `s.imageFactorization f : s → f '' s`. -/ +def imageFactorization (f : α → β) (s : Set α) : s → f '' s := fun p => + ⟨f p.1, mem_image_of_mem f p.2⟩ + +/-- `kernImage f s` is the set of `y` such that `f ⁻¹ y ⊆ s`. -/ +def kernImage (f : α → β) (s : Set α) : Set β := {y | ∀ ⦃x⦄, f x = y → x ∈ s} + +lemma subset_kernImage_iff {s : Set β} {t : Set α} {f : α → β} : s ⊆ kernImage f t ↔ f ⁻¹' s ⊆ t := + ⟨fun h _ hx ↦ h hx rfl, + fun h _ hx y hy ↦ h (show f y ∈ s from hy.symm ▸ hx)⟩ + +section Range + +variable {ι : Sort*} {f : ι → α} + +/-- Range of a function. + +This function is more flexible than `f '' univ`, as the image requires that the domain is in Type +and not an arbitrary Sort. -/ +def range (f : ι → α) : Set α := {x | ∃ y, f y = x} + +@[simp] theorem mem_range {x : α} : x ∈ range f ↔ ∃ y, f y = x := Iff.rfl + +@[mfld_simps] theorem mem_range_self (i : ι) : f i ∈ range f := ⟨i, rfl⟩ + +/-- Any map `f : ι → α` factors through a map `rangeFactorization f : ι → range f`. -/ +def rangeFactorization (f : ι → α) : ι → range f := fun i => ⟨f i, mem_range_self i⟩ + +end Range + +/-- We can use the axiom of choice to pick a preimage for every element of `range f`. -/ +noncomputable def rangeSplitting (f : α → β) : range f → α := fun x => x.2.choose + +-- This can not be a `@[simp]` lemma because the head of the left hand side is a variable. +theorem apply_rangeSplitting (f : α → β) (x : range f) : f (rangeSplitting f x) = x := + x.2.choose_spec + +@[simp] +theorem comp_rangeSplitting (f : α → β) : f ∘ rangeSplitting f = Subtype.val := by + ext + simp only [Function.comp_apply] + apply apply_rangeSplitting + +section Prod + +/-- The cartesian product `Set.prod s t` is the set of `(a, b)` such that `a ∈ s` and `b ∈ t`. -/ +def prod (s : Set α) (t : Set β) : Set (α × β) := {p | p.1 ∈ s ∧ p.2 ∈ t} + +@[default_instance] +instance instSProd : SProd (Set α) (Set β) (Set (α × β)) where + sprod := Set.prod + +theorem prod_eq (s : Set α) (t : Set β) : s ×ˢ t = Prod.fst ⁻¹' s ∩ Prod.snd ⁻¹' t := rfl + +variable {a : α} {b : β} {s : Set α} {t : Set β} {p : α × β} + +theorem mem_prod_eq : (p ∈ s ×ˢ t) = (p.1 ∈ s ∧ p.2 ∈ t) := rfl + +@[simp, mfld_simps] +theorem mem_prod : p ∈ s ×ˢ t ↔ p.1 ∈ s ∧ p.2 ∈ t := .rfl + +@[mfld_simps] +theorem prod_mk_mem_set_prod_eq : ((a, b) ∈ s ×ˢ t) = (a ∈ s ∧ b ∈ t) := rfl + +theorem mk_mem_prod (ha : a ∈ s) (hb : b ∈ t) : (a, b) ∈ s ×ˢ t := ⟨ha, hb⟩ + +end Prod + +section Diagonal + +/-- `diagonal α` is the set of `α × α` consisting of all pairs of the form `(a, a)`. -/ +def diagonal (α : Type*) : Set (α × α) := {p | p.1 = p.2} + +theorem mem_diagonal (x : α) : (x, x) ∈ diagonal α := rfl + +@[simp] theorem mem_diagonal_iff {x : α × α} : x ∈ diagonal α ↔ x.1 = x.2 := .rfl + +/-- The off-diagonal of a set `s` is the set of pairs `(a, b)` with `a, b ∈ s` and `a ≠ b`. -/ +def offDiag (s : Set α) : Set (α × α) := {x | x.1 ∈ s ∧ x.2 ∈ s ∧ x.1 ≠ x.2} + +@[simp] +theorem mem_offDiag {x : α × α} {s : Set α} : x ∈ s.offDiag ↔ x.1 ∈ s ∧ x.2 ∈ s ∧ x.1 ≠ x.2 := + Iff.rfl + +end Diagonal + +section Pi + +variable {ι : Type*} {α : ι → Type*} + +/-- Given an index set `ι` and a family of sets `t : Π i, Set (α i)`, `pi s t` +is the set of dependent functions `f : Πa, π a` such that `f a` belongs to `t a` +whenever `a ∈ s`. -/ +def pi (s : Set ι) (t : ∀ i, Set (α i)) : Set (∀ i, α i) := {f | ∀ i ∈ s, f i ∈ t i} + +variable {s : Set ι} {t : ∀ i, Set (α i)} {f : ∀ i, α i} + +@[simp] theorem mem_pi : f ∈ s.pi t ↔ ∀ i ∈ s, f i ∈ t i := .rfl + +theorem mem_univ_pi : f ∈ pi univ t ↔ ∀ i, f i ∈ t i := by simp + +end Pi + +/-- Two functions `f₁ f₂ : α → β` are equal on `s` if `f₁ x = f₂ x` for all `x ∈ s`. -/ +def EqOn (f₁ f₂ : α → β) (s : Set α) : Prop := ∀ ⦃x⦄, x ∈ s → f₁ x = f₂ x + +/-- `MapsTo f a b` means that the image of `a` is contained in `b`. -/ +def MapsTo (f : α → β) (s : Set α) (t : Set β) : Prop := ∀ ⦃x⦄, x ∈ s → f x ∈ t + +theorem mapsTo_image (f : α → β) (s : Set α) : MapsTo f s (f '' s) := fun _ ↦ mem_image_of_mem f + +theorem mapsTo_preimage (f : α → β) (t : Set β) : MapsTo f (f ⁻¹' t) t := fun _ ↦ id + +/-- Given a map `f` sending `s : Set α` into `t : Set β`, restrict domain of `f` to `s` +and the codomain to `t`. Same as `Subtype.map`. -/ +def MapsTo.restrict (f : α → β) (s : Set α) (t : Set β) (h : MapsTo f s t) : s → t := + Subtype.map f h + +/-- The restriction of a function onto the preimage of a set. -/ +@[simps!] +def restrictPreimage (t : Set β) (f : α → β) : f ⁻¹' t → t := + (Set.mapsTo_preimage f t).restrict _ _ _ + +/-- `f` is injective on `a` if the restriction of `f` to `a` is injective. -/ +def InjOn (f : α → β) (s : Set α) : Prop := + ∀ ⦃x₁ : α⦄, x₁ ∈ s → ∀ ⦃x₂ : α⦄, x₂ ∈ s → f x₁ = f x₂ → x₁ = x₂ + +/-- The graph of a function `f : α → β` on a set `s`. -/ +def graphOn (f : α → β) (s : Set α) : Set (α × β) := (fun x ↦ (x, f x)) '' s + +/-- `f` is surjective from `a` to `b` if `b` is contained in the image of `a`. -/ +def SurjOn (f : α → β) (s : Set α) (t : Set β) : Prop := t ⊆ f '' s + +/-- `f` is bijective from `s` to `t` if `f` is injective on `s` and `f '' s = t`. -/ +def BijOn (f : α → β) (s : Set α) (t : Set β) : Prop := MapsTo f s t ∧ InjOn f s ∧ SurjOn f s t + +/-- `g` is a left inverse to `f` on `a` means that `g (f x) = x` for all `x ∈ a`. -/ +def LeftInvOn (f' : β → α) (f : α → β) (s : Set α) : Prop := ∀ ⦃x⦄, x ∈ s → f' (f x) = x + +/-- `g` is a right inverse to `f` on `b` if `f (g x) = x` for all `x ∈ b`. -/ +abbrev RightInvOn (f' : β → α) (f : α → β) (t : Set β) : Prop := LeftInvOn f f' t + +/-- `g` is an inverse to `f` viewed as a map from `a` to `b` -/ +def InvOn (g : β → α) (f : α → β) (s : Set α) (t : Set β) : Prop := + LeftInvOn g f s ∧ RightInvOn g f t + +section image2 + +/-- The image of a binary function `f : α → β → γ` as a function `Set α → Set β → Set γ`. +Mathematically this should be thought of as the image of the corresponding function `α × β → γ`. -/ +def image2 (f : α → β → γ) (s : Set α) (t : Set β) : Set γ := {c | ∃ a ∈ s, ∃ b ∈ t, f a b = c} + +variable {f : α → β → γ} {s : Set α} {t : Set β} {a : α} {b : β} {c : γ} + +@[simp] theorem mem_image2 : c ∈ image2 f s t ↔ ∃ a ∈ s, ∃ b ∈ t, f a b = c := .rfl + +theorem mem_image2_of_mem (ha : a ∈ s) (hb : b ∈ t) : f a b ∈ image2 f s t := + ⟨a, ha, b, hb, rfl⟩ + +end image2 + +/-- Given a set `s` of functions `α → β` and `t : Set α`, `seq s t` is the union of `f '' t` over +all `f ∈ s`. -/ +def seq (s : Set (α → β)) (t : Set α) : Set β := image2 (fun f ↦ f) s t + +@[simp] +theorem mem_seq_iff {s : Set (α → β)} {t : Set α} {b : β} : + b ∈ seq s t ↔ ∃ f ∈ s, ∃ a ∈ t, (f : α → β) a = b := + Iff.rfl + +lemma seq_eq_image2 (s : Set (α → β)) (t : Set α) : seq s t = image2 (fun f a ↦ f a) s t := rfl + +end Set diff --git a/Mathlib/Data/Set/Opposite.lean b/Mathlib/Data/Set/Opposite.lean index 77e16fe7c9064..b513d07864d91 100644 --- a/Mathlib/Data/Set/Opposite.lean +++ b/Mathlib/Data/Set/Opposite.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Markus Himmel -/ import Mathlib.Data.Opposite -import Mathlib.Data.Set.Defs +import Mathlib.Data.Set.Operations /-! # The opposite of a set diff --git a/Mathlib/Data/Set/Pairwise/Lattice.lean b/Mathlib/Data/Set/Pairwise/Lattice.lean index 9830f4e15681f..6e82a9acdc83d 100644 --- a/Mathlib/Data/Set/Pairwise/Lattice.lean +++ b/Mathlib/Data/Set/Pairwise/Lattice.lean @@ -71,7 +71,7 @@ theorem PairwiseDisjoint.biUnion {s : Set ι'} {g : ι' → Set ι} {f : ι → obtain ⟨c, hc, ha⟩ := ha obtain ⟨d, hd, hb⟩ := hb obtain hcd | hcd := eq_or_ne (g c) (g d) - · exact hg d hd (hcd.subst ha) hb hab + · exact hg d hd (hcd ▸ ha) hb hab -- Porting note: the elaborator couldn't figure out `f` here. · exact (hs hc hd <| ne_of_apply_ne _ hcd).mono (le_iSup₂ (f := fun i (_ : i ∈ g c) => f i) a ha) diff --git a/Mathlib/Data/Set/Pointwise/BigOperators.lean b/Mathlib/Data/Set/Pointwise/BigOperators.lean index 8ad41832d91c2..2cc66bb66f328 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.Data.Set.Pointwise.Basic +import Mathlib.Algebra.Group.Pointwise.Set /-! # 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 b98cbbde6ca66..0472b092e5f72 100644 --- a/Mathlib/Data/Set/Pointwise/BoundedMul.lean +++ b/Mathlib/Data/Set/Pointwise/BoundedMul.lean @@ -3,8 +3,8 @@ Copyright (c) 2021 Yury Kudryashov. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury KudryashovJ -/ +import Mathlib.Algebra.Group.Pointwise.Set import Mathlib.Algebra.Order.Monoid.Defs -import Mathlib.Data.Set.Pointwise.Basic /-! diff --git a/Mathlib/Data/Set/Pointwise/Interval.lean b/Mathlib/Data/Set/Pointwise/Interval.lean index 06375bbd88b1d..291fcb810c4c8 100644 --- a/Mathlib/Data/Set/Pointwise/Interval.lean +++ b/Mathlib/Data/Set/Pointwise/Interval.lean @@ -3,11 +3,11 @@ 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.Order.Interval.Set.UnorderedInterval -import Mathlib.Algebra.Order.Interval.Set.Monoid -import Mathlib.Data.Set.Pointwise.Basic +import Mathlib.Algebra.Group.Pointwise.Set import Mathlib.Algebra.Order.Field.Basic import Mathlib.Algebra.Order.Group.MinMax +import Mathlib.Algebra.Order.Interval.Set.Monoid +import Mathlib.Order.Interval.Set.UnorderedInterval /-! # (Pre)images of intervals @@ -519,12 +519,12 @@ theorem preimage_mul_const_Ioi (a : α) {c : α} (h : 0 < c) : @[simp] theorem preimage_mul_const_Iic (a : α) {c : α} (h : 0 < c) : (fun x => x * c) ⁻¹' Iic a = Iic (a / c) := - ext fun _x => (le_div_iff h).symm + ext fun _x => (le_div_iff₀ h).symm @[simp] theorem preimage_mul_const_Ici (a : α) {c : α} (h : 0 < c) : (fun x => x * c) ⁻¹' Ici a = Ici (a / c) := - ext fun _x => (div_le_iff h).symm + ext fun _x => (div_le_iff₀ h).symm @[simp] theorem preimage_mul_const_Ioo (a b : α) {c : α} (h : 0 < c) : @@ -590,11 +590,11 @@ theorem preimage_const_mul_Ioi (a : α) {c : α} (h : 0 < c) : (c * ·) ⁻¹' I @[simp] theorem preimage_const_mul_Iic (a : α) {c : α} (h : 0 < c) : (c * ·) ⁻¹' Iic a = Iic (a / c) := - ext fun _x => (le_div_iff' h).symm + ext fun _x => (le_div_iff₀' h).symm @[simp] theorem preimage_const_mul_Ici (a : α) {c : α} (h : 0 < c) : (c * ·) ⁻¹' Ici a = Ici (a / c) := - ext fun _x => (div_le_iff' h).symm + ext fun _x => (div_le_iff₀' h).symm @[simp] theorem preimage_const_mul_Ioo (a b : α) {c : α} (h : 0 < c) : @@ -719,17 +719,17 @@ 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 => - ⟨inv_pos (α := α) |>.2 <| (inv_pos (α := α) |>.2 ha).trans h, - inv_inv a ▸ (inv_lt_inv ((inv_pos (α := α) |>.2 ha).trans h) - (inv_pos (α := α) |>.2 ha)).2 h⟩⟩ + ⟨inv_pos.2 <| (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 - rw [inv_eq_iff_eq_inv, inv_Ioo_0_left (inv_pos (α := α) |>.2 ha), inv_inv] + rw [inv_eq_iff_eq_inv, inv_Ioo_0_left (inv_pos.2 ha), inv_inv] theorem image_const_mul_Ioi_zero {k : Type*} [LinearOrderedField k] {x : k} (hx : 0 < x) : (fun y => x * y) '' Ioi (0 : k) = Ioi 0 := by erw [(Units.mk0 x hx.ne').mulLeft.image_eq_preimage, - preimage_const_mul_Ioi 0 (inv_pos (α := k) |>.mpr hx), zero_div] + preimage_const_mul_Ioi 0 (inv_pos.mpr hx), zero_div] /-! ### Images under `x ↦ a * x + b` diff --git a/Mathlib/Data/Set/Pointwise/ListOfFn.lean b/Mathlib/Data/Set/Pointwise/ListOfFn.lean index c87a75ed34d9d..309b0b70bb701 100644 --- a/Mathlib/Data/Set/Pointwise/ListOfFn.lean +++ b/Mathlib/Data/Set/Pointwise/ListOfFn.lean @@ -4,8 +4,8 @@ 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.Data.List.OfFn -import Mathlib.Data.Set.Pointwise.Basic /-! # Pointwise operations with lists of sets diff --git a/Mathlib/Data/Set/Pointwise/SMul.lean b/Mathlib/Data/Set/Pointwise/SMul.lean index fd2bf0cf217e8..71e47a9d5b35c 100644 --- a/Mathlib/Data/Set/Pointwise/SMul.lean +++ b/Mathlib/Data/Set/Pointwise/SMul.lean @@ -4,11 +4,10 @@ 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.GroupWithZero.Action.Basic import Mathlib.Algebra.Module.Defs import Mathlib.Data.Set.Pairwise.Basic -import Mathlib.Data.Set.Pointwise.Basic -import Mathlib.GroupTheory.GroupAction.Group /-! # Pointwise operations of sets diff --git a/Mathlib/Data/Set/Prod.lean b/Mathlib/Data/Set/Prod.lean index 6210548212b18..07ef12d57509b 100644 --- a/Mathlib/Data/Set/Prod.lean +++ b/Mathlib/Data/Set/Prod.lean @@ -730,7 +730,7 @@ theorem union_pi_inter simp only [mem_pi, mem_union, mem_inter_iff] refine ⟨fun h ↦ ⟨fun i his₁ ↦ (h i (Or.inl his₁)).1, fun i his₂ ↦ (h i (Or.inr his₂)).2⟩, fun h i hi ↦ ?_⟩ - cases' hi with hi hi + rcases hi with hi | hi · by_cases hi2 : i ∈ s₂ · exact ⟨h.1 i hi, h.2 i hi2⟩ · refine ⟨h.1 i hi, ?_⟩ @@ -802,6 +802,23 @@ 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 + 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 + intro i + if hi : i ∈ s then + exact (hb i hi).imp fun a ⟨hat, hab⟩ ↦ ⟨hab, fun _ ↦ hat⟩ + else + exact (hf i hi (b i)).imp fun a ha ↦ ⟨ha, (absurd · hi)⟩ + 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 + theorem pi_subset_pi_iff : pi s t₁ ⊆ pi s t₂ ↔ (∀ i ∈ s, t₁ i ⊆ t₂ i) ∨ pi s t₁ = ∅ := by refine ⟨fun h => or_iff_not_imp_right.2 ?_, fun h => h.elim pi_mono fun h' => h'.symm ▸ empty_subset _⟩ @@ -837,7 +854,10 @@ theorem update_preimage_pi [DecidableEq ι] {f : ∀ i, α i} (hi : i ∈ s) theorem update_image [DecidableEq ι] (x : (i : ι) → β i) (i : ι) (s : Set (β i)) : update x i '' s = Set.univ.pi (update (fun j ↦ {x j}) i s) := by ext y - simp [update_eq_iff, and_left_comm (a := _ ∈ s), forall_update_iff, eq_comm (a := y _)] + simp only [mem_image, update_eq_iff, ne_eq, and_left_comm (a := _ ∈ s), exists_eq_left, mem_pi, + mem_univ, true_implies] + rw [forall_update_iff (p := fun x s => y x ∈ s)] + simp [eq_comm] theorem update_preimage_univ_pi [DecidableEq ι] {f : ∀ i, α i} (hf : ∀ j ≠ i, f j ∈ t j) : update f i ⁻¹' pi univ t = t i := diff --git a/Mathlib/Data/Set/Semiring.lean b/Mathlib/Data/Set/Semiring.lean index 9acda7f2291a3..65db6ecc8dee6 100644 --- a/Mathlib/Data/Set/Semiring.lean +++ b/Mathlib/Data/Set/Semiring.lean @@ -3,9 +3,9 @@ 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.Order.Kleene import Mathlib.Algebra.Order.Ring.Canonical -import Mathlib.Data.Set.Pointwise.Basic /-! # Sets as a semiring under union diff --git a/Mathlib/Data/Set/Sigma.lean b/Mathlib/Data/Set/Sigma.lean index d8a73c0f8e40f..b10a51f01db79 100644 --- a/Mathlib/Data/Set/Sigma.lean +++ b/Mathlib/Data/Set/Sigma.lean @@ -191,7 +191,7 @@ theorem mk_preimage_sigma_fn_eq_if {β : Type*} [DecidablePred (· ∈ s)] (g : theorem sigma_univ_range_eq {f : ∀ i, α i → β i} : (univ : Set ι).sigma (fun i ↦ range (f i)) = range fun x : Σ i, α i ↦ ⟨x.1, f _ x.2⟩ := - ext <| by simp [range] + ext <| by simp [range, Sigma.forall] protected theorem Nonempty.sigma : s.Nonempty → (∀ i, (t i).Nonempty) → (s.sigma t).Nonempty := fun ⟨i, hi⟩ h ↦ diff --git a/Mathlib/Data/Set/UnionLift.lean b/Mathlib/Data/Set/UnionLift.lean index 9b8184a95693c..cd2d6ffd31433 100644 --- a/Mathlib/Data/Set/UnionLift.lean +++ b/Mathlib/Data/Set/UnionLift.lean @@ -62,7 +62,6 @@ variable {S : ι → Set α} {f : ∀ i, S i → β} theorem iUnionLift_mk {i : ι} (x : S i) (hx : (x : α) ∈ T) : iUnionLift S f hf T hT ⟨x, hx⟩ = f i x := hf _ i x _ _ -@[simp] theorem iUnionLift_inclusion {i : ι} (x : S i) (h : S i ⊆ T) : iUnionLift S f hf T hT (Set.inclusion h x) = f i x := iUnionLift_mk x _ @@ -139,7 +138,6 @@ theorem iUnionLift_binary (dir : Directed (· ≤ ·) S) (op : T → T → T) (o have hxy : (Set.inclusion (Set.subset_iUnion S k) (opi k ⟨x, hik hi⟩ ⟨y, hjk hj⟩) : α) ∈ S k := (opi k ⟨x, hik hi⟩ ⟨y, hjk hj⟩).prop conv_lhs => rw [hx, hy, ← hopi, iUnionLift_of_mem _ hxy] - rfl end UnionLift diff --git a/Mathlib/Data/SetLike/Basic.lean b/Mathlib/Data/SetLike/Basic.lean index bd1f5ca66f08e..fa52573699827 100644 --- a/Mathlib/Data/SetLike/Basic.lean +++ b/Mathlib/Data/SetLike/Basic.lean @@ -106,7 +106,7 @@ variable {A : Type*} {B : Type*} [i : SetLike A B] instance : CoeTC A (Set B) where coe := SetLike.coe instance (priority := 100) instMembership : Membership B A := - ⟨fun x p => x ∈ (p : Set B)⟩ + ⟨fun p x => x ∈ (p : Set B)⟩ instance (priority := 100) : CoeSort A (Type _) := ⟨fun p => { x : B // x ∈ p }⟩ diff --git a/Mathlib/Data/Setoid/Basic.lean b/Mathlib/Data/Setoid/Basic.lean index 294f426f6d013..ca1d0ac665068 100644 --- a/Mathlib/Data/Setoid/Basic.lean +++ b/Mathlib/Data/Setoid/Basic.lean @@ -192,10 +192,14 @@ def map_sInf {S : Set (Setoid α)} {s : Setoid α} (h : s ∈ S) : Quotient (sInf S) → Quotient s := Setoid.map_of_le fun _ _ a ↦ a s h +section EqvGen + +open Relation + /-- The inductively defined equivalence closure of a binary relation r is the infimum of the set of all equivalence relations containing r. -/ theorem eqvGen_eq (r : α → α → Prop) : - EqvGen.Setoid r = sInf { s : Setoid α | ∀ ⦃x y⦄, r x y → s.Rel x y } := + EqvGen.setoid r = sInf { s : Setoid α | ∀ ⦃x y⦄, r x y → s.Rel x y } := le_antisymm (fun _ _ H => EqvGen.rec (fun _ _ h _ hs => hs h) (refl' _) (fun _ _ _ => symm' _) @@ -205,20 +209,20 @@ theorem eqvGen_eq (r : α → α → Prop) : /-- The supremum of two equivalence relations r and s is the equivalence closure of the binary relation `x is related to y by r or s`. -/ theorem sup_eq_eqvGen (r s : Setoid α) : - r ⊔ s = EqvGen.Setoid fun x y => r.Rel x y ∨ s.Rel x y := by + r ⊔ s = EqvGen.setoid fun x y => r.Rel x y ∨ s.Rel x y := by rw [eqvGen_eq] apply congr_arg sInf simp only [le_def, or_imp, ← forall_and] /-- The supremum of 2 equivalence relations r and s is the equivalence closure of the supremum of the underlying binary operations. -/ -theorem sup_def {r s : Setoid α} : r ⊔ s = EqvGen.Setoid (r.Rel ⊔ s.Rel) := by +theorem sup_def {r s : Setoid α} : r ⊔ s = EqvGen.setoid (r.Rel ⊔ s.Rel) := by rw [sup_eq_eqvGen]; rfl /-- The supremum of a set S of equivalence relations is the equivalence closure of the binary relation `there exists r ∈ S relating x and y`. -/ theorem sSup_eq_eqvGen (S : Set (Setoid α)) : - sSup S = EqvGen.Setoid fun x y => ∃ r : Setoid α, r ∈ S ∧ r.Rel x y := by + sSup S = EqvGen.setoid fun x y => ∃ r : Setoid α, r ∈ S ∧ r.Rel x y := by rw [eqvGen_eq] apply congr_arg sInf simp only [upperBounds, le_def, and_imp, exists_imp] @@ -227,39 +231,41 @@ theorem sSup_eq_eqvGen (S : Set (Setoid α)) : /-- The supremum of a set of equivalence relations is the equivalence closure of the supremum of the set's image under the map to the underlying binary operation. -/ -theorem sSup_def {s : Set (Setoid α)} : sSup s = EqvGen.Setoid (sSup (Rel '' s)) := by +theorem sSup_def {s : Set (Setoid α)} : sSup s = EqvGen.setoid (sSup (Rel '' s)) := by rw [sSup_eq_eqvGen, sSup_image] congr with (x y) simp only [iSup_apply, iSup_Prop_eq, exists_prop] /-- The equivalence closure of an equivalence relation r is r. -/ @[simp] -theorem eqvGen_of_setoid (r : Setoid α) : EqvGen.Setoid r.r = r := +theorem eqvGen_of_setoid (r : Setoid α) : EqvGen.setoid r.r = r := le_antisymm (by rw [eqvGen_eq]; exact sInf_le fun _ _ => id) EqvGen.rel /-- Equivalence closure is idempotent. -/ @[simp] -theorem eqvGen_idem (r : α → α → Prop) : EqvGen.Setoid (EqvGen.Setoid r).Rel = EqvGen.Setoid r := +theorem eqvGen_idem (r : α → α → Prop) : EqvGen.setoid (EqvGen.setoid r).Rel = EqvGen.setoid r := eqvGen_of_setoid _ /-- The equivalence closure of a binary relation r is contained in any equivalence relation containing r. -/ theorem eqvGen_le {r : α → α → Prop} {s : Setoid α} (h : ∀ x y, r x y → s.Rel x y) : - EqvGen.Setoid r ≤ s := by rw [eqvGen_eq]; exact sInf_le h + EqvGen.setoid r ≤ s := by rw [eqvGen_eq]; exact sInf_le h /-- Equivalence closure of binary relations is monotone. -/ theorem eqvGen_mono {r s : α → α → Prop} (h : ∀ x y, r x y → s x y) : - EqvGen.Setoid r ≤ EqvGen.Setoid s := + EqvGen.setoid r ≤ EqvGen.setoid s := eqvGen_le fun _ _ hr => EqvGen.rel _ _ <| h _ _ hr /-- There is a Galois insertion of equivalence relations on α into binary relations on α, with equivalence closure the lower adjoint. -/ -def gi : @GaloisInsertion (α → α → Prop) (Setoid α) _ _ EqvGen.Setoid Rel where - choice r _ := EqvGen.Setoid r +def gi : @GaloisInsertion (α → α → Prop) (Setoid α) _ _ EqvGen.setoid Rel where + choice r _ := EqvGen.setoid r gc _ s := ⟨fun H _ _ h => H <| EqvGen.rel _ _ h, fun H => eqvGen_of_setoid s ▸ eqvGen_mono H⟩ le_l_u x := (eqvGen_of_setoid x).symm ▸ le_refl x choice_eq _ _ := rfl +end EqvGen + open Function /-- A function from α to β is injective iff its kernel is the bottom element of the complete lattice @@ -335,7 +341,7 @@ variable {r f} closure of the relation on `f`'s image defined by '`x ≈ y` iff the elements of `f⁻¹(x)` are related to the elements of `f⁻¹(y)` by `r`.' -/ def map (r : Setoid α) (f : α → β) : Setoid β := - EqvGen.Setoid fun x y => ∃ a b, f a = x ∧ f b = y ∧ r.Rel a b + Relation.EqvGen.setoid fun x y => ∃ a b, f a = x ∧ f b = y ∧ r.Rel a b /-- Given a surjective function f whose kernel is contained in an equivalence relation r, the equivalence relation on f's codomain defined by x ≈ y ↔ the elements of f⁻¹(x) are related to @@ -428,7 +434,8 @@ theorem Quotient.subsingleton_iff {s : Setoid α} : Subsingleton (Quotient s) simp_rw [Prop.top_eq_true, true_implies, Quotient.eq'] rfl -theorem Quot.subsingleton_iff (r : α → α → Prop) : Subsingleton (Quot r) ↔ EqvGen r = ⊤ := by +theorem Quot.subsingleton_iff (r : α → α → Prop) : + Subsingleton (Quot r) ↔ Relation.EqvGen r = ⊤ := by simp only [_root_.subsingleton_iff, _root_.eq_top_iff, Pi.le_def, Pi.top_apply, forall_const] refine (surjective_quot_mk _).forall.trans (forall_congr' fun a => ?_) refine (surjective_quot_mk _).forall.trans (forall_congr' fun b => ?_) diff --git a/Mathlib/Data/Setoid/Partition.lean b/Mathlib/Data/Setoid/Partition.lean index ecf06ea7c220d..1cc028237c179 100644 --- a/Mathlib/Data/Setoid/Partition.lean +++ b/Mathlib/Data/Setoid/Partition.lean @@ -301,7 +301,7 @@ This type is primarily useful for definitional control of `s` - if this is not n structure IndexedPartition {ι α : Type*} (s : ι → Set α) where /-- two indexes are equal if they are equal in membership -/ eq_of_mem : ∀ {x i j}, x ∈ s i → x ∈ s j → i = j - /-- sends an index to an element of the corresponding set-/ + /-- sends an index to an element of the corresponding set -/ some : ι → α /-- membership invariance for `some`-/ some_mem : ∀ i, some i ∈ s i diff --git a/Mathlib/Data/Sigma/Basic.lean b/Mathlib/Data/Sigma/Basic.lean index 54166f10c5b7c..552e884b81259 100644 --- a/Mathlib/Data/Sigma/Basic.lean +++ b/Mathlib/Data/Sigma/Basic.lean @@ -79,7 +79,7 @@ theorem subtype_ext {β : Type*} {p : α → β → Prop} : ∀ {x₀ x₁ : Σa, Subtype (p a)}, x₀.fst = x₁.fst → (x₀.snd : β) = x₁.snd → x₀ = x₁ | ⟨_, _, _⟩, ⟨_, _, _⟩, rfl, rfl => rfl -@[simp] +-- This is not a good simp lemma, as its discrimination tree key is just an arrow. theorem «forall» {p : (Σa, β a) → Prop} : (∀ x, p x) ↔ ∀ a b, p ⟨a, b⟩ := ⟨fun h a b ↦ h ⟨a, b⟩, fun h ⟨a, b⟩ ↦ h a b⟩ @@ -243,16 +243,11 @@ protected theorem eq {α : Sort*} {β : α → Sort*} : ∀ {p₁ p₂ : Σ' a, (Eq.recOn h₁ p₁.2 : β p₂.1) = p₂.2 → p₁ = p₂ | ⟨_, _⟩, _, rfl, rfl => rfl -@[simp] +-- This should not be a simp lemma, since its discrimination tree key would just be `→`. theorem «forall» {p : (Σ'a, β a) → Prop} : (∀ x, p x) ↔ ∀ a b, p ⟨a, b⟩ := ⟨fun h a b ↦ h ⟨a, b⟩, fun h ⟨a, b⟩ ↦ h a b⟩ -#adaptation_note -/-- -This should be renamed back to `exists` after `nightly-2024-07-31`. --/ -@[simp] -theorem exists' {p : (Σ'a, β a) → Prop} : (∃ x, p x) ↔ ∃ a b, p ⟨a, b⟩ := +@[simp] lemma «exists» {p : (Σ' a, β a) → Prop} : (∃ x, p x) ↔ ∃ a b, p ⟨a, b⟩ := ⟨fun ⟨⟨a, b⟩, h⟩ ↦ ⟨a, b, h⟩, fun ⟨a, b, h⟩ ↦ ⟨⟨a, b⟩, h⟩⟩ /-- A specialized ext lemma for equality of `PSigma` types over an indexed subtype. -/ diff --git a/Mathlib/Data/Stream/Defs.lean b/Mathlib/Data/Stream/Defs.lean index 2a596ea48dac9..ce2dc694fd4fc 100644 --- a/Mathlib/Data/Stream/Defs.lean +++ b/Mathlib/Data/Stream/Defs.lean @@ -48,7 +48,7 @@ def Any (p : α → Prop) (s : Stream' α) := ∃ n, p (get s n) /-- `a ∈ s` means that `a = Stream'.get n s` for some `n`. -/ instance : Membership α (Stream' α) := - ⟨fun a s => Any (fun b => a = b) s⟩ + ⟨fun s a => Any (fun b => a = b) s⟩ /-- Apply a function `f` to all elements of a stream `s`. -/ def map (f : α → β) (s : Stream' α) : Stream' β := fun n => f (get s n) diff --git a/Mathlib/Data/Stream/Init.lean b/Mathlib/Data/Stream/Init.lean index 7f714ab54b4df..c90ad62ac925d 100644 --- a/Mathlib/Data/Stream/Init.lean +++ b/Mathlib/Data/Stream/Init.lean @@ -12,7 +12,7 @@ import Mathlib.Data.List.Basic Porting note: This file used to be in the core library. It was moved to `mathlib` and renamed to `init` to avoid -name clashes. -/ +name clashes. -/ open Nat Function Option @@ -493,7 +493,7 @@ theorem length_take (n : ℕ) (s : Stream' α) : (take n s).length = n := by theorem take_take {s : Stream' α} : ∀ {m n}, (s.take n).take m = s.take (min n m) | 0, n => by rw [Nat.min_zero, List.take_zero, take_zero] | m, 0 => by rw [Nat.zero_min, take_zero, List.take_nil] - | m+1, n+1 => by rw [take_succ, List.take_cons, Nat.succ_min_succ, take_succ, take_take] + | m+1, n+1 => by rw [take_succ, List.take_succ_cons, Nat.succ_min_succ, take_succ, take_take] @[simp] theorem concat_take_get {n : ℕ} {s : Stream' α} : s.take n ++ [s.get n] = s.take (n+1) := (take_succ' n).symm diff --git a/Mathlib/Data/String/Basic.lean b/Mathlib/Data/String/Basic.lean index 1208ee3912785..99c98349ad745 100644 --- a/Mathlib/Data/String/Basic.lean +++ b/Mathlib/Data/String/Basic.lean @@ -60,7 +60,7 @@ theorem ltb_cons_addChar (c : Char) (cs₁ cs₂ : List Char) (i₁ i₂ : Pos) intro ⟨cs₁⟩ ⟨cs₂⟩ i₁ i₂ <;> intros <;> (conv => lhs; unfold ltb) <;> (conv => rhs; unfold ltb) <;> - simp only [Iterator.hasNext_cons_addChar, ite_false, ite_true, *] + simp only [Iterator.hasNext_cons_addChar, ite_false, ite_true, *, reduceCtorEq] · rename_i h₂ h₁ heq ih simp only [Iterator.next, next, heq, Iterator.curr, get_cons_addChar, ite_true] at ih ⊢ repeat rw [Pos.addChar_right_comm _ c] diff --git a/Mathlib/Data/Sum/Basic.lean b/Mathlib/Data/Sum/Basic.lean index 9265b7b297c2d..9da00e98e9adb 100644 --- a/Mathlib/Data/Sum/Basic.lean +++ b/Mathlib/Data/Sum/Basic.lean @@ -133,7 +133,7 @@ theorem isRight_right (h : LiftRel r s (inr b) y) : y.isRight := by cases h; rfl theorem exists_of_isLeft_left (h₁ : LiftRel r s x y) (h₂ : x.isLeft) : ∃ a c, r a c ∧ x = inl a ∧ y = inl c := by rcases isLeft_iff.mp h₂ with ⟨_, rfl⟩ - simp only [liftRel_iff, false_and, and_false, exists_false, or_false] at h₁ + simp only [liftRel_iff, false_and, and_false, exists_false, or_false, reduceCtorEq] at h₁ exact h₁ theorem exists_of_isLeft_right (h₁ : LiftRel r s x y) (h₂ : y.isLeft) : @@ -142,7 +142,7 @@ theorem exists_of_isLeft_right (h₁ : LiftRel r s x y) (h₂ : y.isLeft) : theorem exists_of_isRight_left (h₁ : LiftRel r s x y) (h₂ : x.isRight) : ∃ b d, s b d ∧ x = inr b ∧ y = inr d := by rcases isRight_iff.mp h₂ with ⟨_, rfl⟩ - simp only [liftRel_iff, false_and, and_false, exists_false, false_or] at h₁ + simp only [liftRel_iff, false_and, and_false, exists_false, false_or, reduceCtorEq] at h₁ exact h₁ theorem exists_of_isRight_right (h₁ : LiftRel r s x y) (h₂ : y.isRight) : diff --git a/Mathlib/Data/Sum/Interval.lean b/Mathlib/Data/Sum/Interval.lean index fa3850967d3d3..75478d551bcc8 100644 --- a/Mathlib/Data/Sum/Interval.lean +++ b/Mathlib/Data/Sum/Interval.lean @@ -300,7 +300,7 @@ local elab "simp_lex" : tactic => do map_empty, not_mem_empty, true_and, inl_mem_disjSum, inr_mem_disjSum, and_true, ofLex_toLex, mem_map, Embedding.coeFn_mk, exists_prop, exists_eq_right, Embedding.inl_apply, -- Porting note: added - inl.injEq, inr.injEq] + inl.injEq, inr.injEq, reduceCtorEq] ) instance locallyFiniteOrder : LocallyFiniteOrder (α ⊕ₗ β) where diff --git a/Mathlib/Data/Sum/Order.lean b/Mathlib/Data/Sum/Order.lean index ae5edfa7ffcf1..7eef753b32d1a 100644 --- a/Mathlib/Data/Sum/Order.lean +++ b/Mathlib/Data/Sum/Order.lean @@ -651,7 +651,7 @@ def orderIsoPUnitSumLex : WithBot α ≃o PUnit ⊕ₗ α := ⟨(Equiv.optionEquivSumPUnit α).trans <| (Equiv.sumComm _ _).trans toLex, fun {a b} => by simp only [Equiv.optionEquivSumPUnit, Option.elim, Equiv.trans_apply, Equiv.coe_fn_mk, Equiv.sumComm_apply, swap, Lex.toLex_le_toLex, le_refl] - cases' a <;> cases' b + cases a <;> cases b · simp only [elim_inr, lex_inl_inl, bot_le, le_rfl] · simp only [elim_inr, elim_inl, Lex.sep, bot_le] · simp only [elim_inl, elim_inr, lex_inr_inl, false_iff] @@ -688,7 +688,7 @@ def orderIsoSumLexPUnit : WithTop α ≃o α ⊕ₗ PUnit := ⟨(Equiv.optionEquivSumPUnit α).trans toLex, fun {a b} => by simp only [Equiv.optionEquivSumPUnit, Option.elim, Equiv.trans_apply, Equiv.coe_fn_mk, Lex.toLex_le_toLex, le_refl, lex_inr_inr, le_top] - cases' a <;> cases' b + cases a <;> cases b · simp only [lex_inr_inr, le_top] · simp only [lex_inr_inl, false_iff] exact not_top_le_coe _ diff --git a/Mathlib/Data/Sym/Basic.lean b/Mathlib/Data/Sym/Basic.lean index aa85d9183ee69..4378b439653ed 100644 --- a/Mathlib/Data/Sym/Basic.lean +++ b/Mathlib/Data/Sym/Basic.lean @@ -142,7 +142,7 @@ theorem card_coe : Multiset.card (s : Multiset α) = n := s.prop /-- `α ∈ s` means that `a` appears as one of the factors in `s`. -/ instance : Membership α (Sym α n) := - ⟨fun a s => a ∈ s.1⟩ + ⟨fun s a => a ∈ s.1⟩ instance decidableMem [DecidableEq α] (a : α) (s : Sym α n) : Decidable (a ∈ s) := s.1.decidableMem _ diff --git a/Mathlib/Data/Sym/Sym2.lean b/Mathlib/Data/Sym/Sym2.lean index 4e94151a85335..e94c465684a68 100644 --- a/Mathlib/Data/Sym/Sym2.lean +++ b/Mathlib/Data/Sym/Sym2.lean @@ -318,7 +318,7 @@ theorem mem_mk_left (x y : α) : x ∈ s(x, y) := ⟨y, rfl⟩ theorem mem_mk_right (x y : α) : y ∈ s(x, y) := - eq_swap.subst <| mem_mk_left y x + eq_swap ▸ mem_mk_left y x @[simp, aesop norm (rule_sets := [Sym2])] theorem mem_iff {a b c : α} : a ∈ s(b, c) ↔ a = b ∨ a = c := diff --git a/Mathlib/Data/TypeVec.lean b/Mathlib/Data/TypeVec.lean index 104d68020ce33..ed974cab4a625 100644 --- a/Mathlib/Data/TypeVec.lean +++ b/Mathlib/Data/TypeVec.lean @@ -448,16 +448,16 @@ end @[simp] theorem prod_fst_mk {α β : TypeVec n} (i : Fin2 n) (a : α i) (b : β i) : TypeVec.prod.fst i (prod.mk i a b) = a := by - induction' i with _ _ _ i_ih - · simp_all only [prod.fst, prod.mk] - apply i_ih + induction i with + | fz => simp_all only [prod.fst, prod.mk] + | fs _ i_ih => apply i_ih @[simp] theorem prod_snd_mk {α β : TypeVec n} (i : Fin2 n) (a : α i) (b : β i) : TypeVec.prod.snd i (prod.mk i a b) = b := by - induction' i with _ _ _ i_ih - · simp_all [prod.snd, prod.mk] - apply i_ih + induction i with + | fz => simp_all [prod.snd, prod.mk] + | fs _ i_ih => apply i_ih /-- `prod` is functorial -/ protected def prod.map : ∀ {n} {α α' β β' : TypeVec.{u} n}, α ⟹ β → α' ⟹ β' → α ⊗ α' ⟹ β ⊗ β' @@ -493,9 +493,9 @@ theorem snd_diag {α : TypeVec n} : TypeVec.prod.snd ⊚ (prod.diag : α ⟹ _) theorem repeatEq_iff_eq {α : TypeVec n} {i x y} : ofRepeat (repeatEq α i (prod.mk _ x y)) ↔ x = y := by - induction' i with _ _ _ i_ih - · rfl - erw [repeatEq, i_ih] + induction i with + | fz => rfl + | fs _ i_ih => erw [repeatEq, i_ih] /-- given a predicate vector `p` over vector `α`, `Subtype_ p` is the type of vectors that contain an `α` that satisfies `p` -/ @@ -547,17 +547,16 @@ theorem subtypeVal_nil {α : TypeVec.{u} 0} (ps : α ⟹ «repeat» 0 Prop) : theorem diag_sub_val {n} {α : TypeVec.{u} n} : subtypeVal (repeatEq α) ⊚ diagSub = prod.diag := by ext i x - induction' i with _ _ _ i_ih - · simp only [comp, subtypeVal, repeatEq.eq_2, diagSub, prod.diag] - apply @i_ih (drop α) + induction i with + | fz => simp only [comp, subtypeVal, repeatEq.eq_2, diagSub, prod.diag] + | fs _ i_ih => apply @i_ih (drop α) theorem prod_id : ∀ {n} {α β : TypeVec.{u} n}, (id ⊗' id) = (id : α ⊗ β ⟹ _) := by intros ext i a - induction' i with _ _ _ i_ih - · cases a - rfl - · apply i_ih + induction i with + | fz => cases a; rfl + | fs _ i_ih => apply i_ih theorem append_prod_appendFun {n} {α α' β β' : TypeVec.{u} n} {φ φ' ψ ψ' : Type u} {f₀ : α ⟹ α'} {g₀ : β ⟹ β'} {f₁ : φ → φ'} {g₁ : ψ → ψ'} : @@ -655,9 +654,10 @@ theorem prod_map_id {α β : TypeVec n} : (@TypeVec.id _ α ⊗' @TypeVec.id _ @[simp] theorem subtypeVal_diagSub {α : TypeVec n} : subtypeVal (repeatEq α) ⊚ diagSub = prod.diag := by ext i x - induction' i with _ _ _ i_ih - · simp [comp, diagSub, subtypeVal, prod.diag] - · simp only [comp, subtypeVal, diagSub, prod.diag] at * + induction i with + | fz => simp [comp, diagSub, subtypeVal, prod.diag] + | fs _ i_ih => + simp only [comp, subtypeVal, diagSub, prod.diag] at * apply i_ih @[simp] diff --git a/Mathlib/Data/ULift.lean b/Mathlib/Data/ULift.lean index 45fa5cad19423..29aed3723b5e7 100644 --- a/Mathlib/Data/ULift.lean +++ b/Mathlib/Data/ULift.lean @@ -56,7 +56,7 @@ theorem down_surjective : Surjective (@down α) := theorem down_bijective : Bijective (@down α) := Equiv.plift.bijective -@[simp] +-- This is not a good simp lemma, as its discrimination tree key is just an arrow. theorem «forall» {p : PLift α → Prop} : (∀ x, p x) ↔ ∀ x : α, p (PLift.up x) := up_surjective.forall diff --git a/Mathlib/Data/Vector/Basic.lean b/Mathlib/Data/Vector/Basic.lean index 75c60fd7cda24..5db96436f76b0 100644 --- a/Mathlib/Data/Vector/Basic.lean +++ b/Mathlib/Data/Vector/Basic.lean @@ -17,18 +17,14 @@ import Mathlib.Control.Traversable.Basic This file introduces the infix notation `::ᵥ` for `Vector.cons`. -/ -set_option autoImplicit true - universe u -variable {n : ℕ} +variable {α β γ σ φ : Type*} {m n : ℕ} namespace Mathlib namespace Vector -variable {α : Type*} - @[inherit_doc] infixr:67 " ::ᵥ " => Vector.cons @@ -640,7 +636,7 @@ protected theorem comp_traverse (f : β → F γ) (g : α → G β) (x : Vector · simp! [cast, *, functor_norm] rfl · rw [Vector.traverse_def, ih] - simp [functor_norm, (· ∘ ·)] + simp [functor_norm, Function.comp_def] protected theorem traverse_eq_map_id {α β} (f : α → β) : ∀ x : Vector α n, x.traverse ((pure : _ → Id _) ∘ f) = (pure : _ → Id _) (map f x) := by @@ -690,7 +686,7 @@ instance : LawfulTraversable.{u} (flip Vector n) where section Simp -variable (xs : Vector α n) +variable {x : α} {y : β} {s : σ} (xs : Vector α n) @[simp] theorem replicate_succ (val : α) : @@ -729,7 +725,7 @@ theorem get_map₂ (v₁ : Vector α n) (v₂ : Vector β n) (f : α → β → · simp only [get_cons_succ, ih] @[simp] -theorem mapAccumr_cons : +theorem mapAccumr_cons {f : α → σ → σ × β} : mapAccumr f (x ::ᵥ xs) s = let r := mapAccumr f xs s let q := f x r.1 @@ -737,7 +733,7 @@ theorem mapAccumr_cons : rfl @[simp] -theorem mapAccumr₂_cons : +theorem mapAccumr₂_cons {f : α → β → σ → σ × φ} : mapAccumr₂ f (x ::ᵥ xs) (y ::ᵥ ys) s = let r := mapAccumr₂ f xs ys s let q := f x y r.1 diff --git a/Mathlib/Data/Vector/Defs.lean b/Mathlib/Data/Vector/Defs.lean index c25f510f74bd1..81ec5ceb94570 100644 --- a/Mathlib/Data/Vector/Defs.lean +++ b/Mathlib/Data/Vector/Defs.lean @@ -3,7 +3,7 @@ Copyright (c) 2016 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Leonardo de Moura -/ -import Mathlib.Init.Data.List.Lemmas +import Mathlib.Data.List.Defs import Mathlib.Tactic.Common /-! @@ -20,8 +20,7 @@ def Vector (α : Type u) (n : ℕ) := namespace Vector -variable {α : Type u} {β : Type v} {φ : Type w} -variable {n : ℕ} +variable {α β σ φ : Type*} {n : ℕ} instance [DecidableEq α] : DecidableEq (Vector α n) := inferInstanceAs (DecidableEq {l : List α // l.length = n}) @@ -53,7 +52,7 @@ def head : Vector α (Nat.succ n) → α theorem head_cons (a : α) : ∀ v : Vector α n, head (cons a v) = a | ⟨_, _⟩ => rfl -/-- The tail of a vector, with an empty vector having empty tail. -/ +/-- The tail of a vector, with an empty vector having empty tail. -/ def tail : Vector α n → Vector α (n - 1) | ⟨[], h⟩ => ⟨[], congrArg pred h⟩ | ⟨_ :: v, h⟩ => ⟨v, congrArg pred h⟩ @@ -137,8 +136,6 @@ section Accum open Prod -variable {σ : Type} - /-- Runs a function over a vector returning the intermediate results and a final result. -/ @@ -150,15 +147,14 @@ def mapAccumr (f : α → σ → σ × β) : Vector α n → σ → σ × Vector /-- Runs a function over a pair of vectors returning the intermediate results and a final result. -/ -def mapAccumr₂ {α β σ φ : Type} (f : α → β → σ → σ × φ) : - Vector α n → Vector β n → σ → σ × Vector φ n +def mapAccumr₂ (f : α → β → σ → σ × φ) : Vector α n → Vector β n → σ → σ × Vector φ n | ⟨x, px⟩, ⟨y, py⟩, c => let res := List.mapAccumr₂ f x y c ⟨res.1, res.2, by simp [*, res]⟩ end Accum -/-! ### Shift Primitives-/ +/-! ### Shift Primitives -/ section Shift /-- `shiftLeftFill v i` is the vector obtained by left-shifting `v` `i` times and padding with the @@ -185,7 +181,7 @@ protected theorem eq_nil (v : Vector α 0) : v = nil := v.eq nil (List.eq_nil_of_length_eq_zero v.2) /-- Vector of length from a list `v` -with witness that `v` has length `n` maps to `v` under `toList`. -/ +with witness that `v` has length `n` maps to `v` under `toList`. -/ @[simp] theorem toList_mk (v : List α) (P : List.length v = n) : toList (Subtype.mk v P) = v := rfl diff --git a/Mathlib/Data/Vector/MapLemmas.lean b/Mathlib/Data/Vector/MapLemmas.lean index 3c67c95406853..54dc2f7a0d4ae 100644 --- a/Mathlib/Data/Vector/MapLemmas.lean +++ b/Mathlib/Data/Vector/MapLemmas.lean @@ -10,7 +10,7 @@ import Mathlib.Data.Vector.Snoc This file establishes a set of normalization lemmas for `map`/`mapAccumr` operations on vectors -/ -set_option autoImplicit true +variable {α β γ ζ σ σ₁ σ₂ φ : Type*} {n : ℕ} {s : σ} {s₁ : σ₁} {s₂ : σ₂} namespace Mathlib @@ -36,12 +36,12 @@ theorem mapAccumr_mapAccumr : induction xs using Vector.revInductionOn generalizing s₁ s₂ <;> simp_all @[simp] -theorem mapAccumr_map (f₂ : α → β) : +theorem mapAccumr_map {s : σ₁} (f₂ : α → β) : (mapAccumr f₁ (map f₂ xs) s) = (mapAccumr (fun x s => f₁ (f₂ x) s) xs s) := by induction xs using Vector.revInductionOn generalizing s <;> simp_all @[simp] -theorem map_mapAccumr (f₁ : β → γ) : +theorem map_mapAccumr {s : σ₂} (f₁ : β → γ) : (map f₁ (mapAccumr f₂ xs s).snd) = (mapAccumr (fun x s => let r := (f₂ x s); (r.fst, f₁ r.snd) ) xs s).snd := by @@ -222,7 +222,7 @@ accumulation state section RedundantState variable {xs : Vector α n} {ys : Vector β n} -protected theorem map_eq_mapAccumr : +protected theorem map_eq_mapAccumr {f : α → β} : map f xs = (mapAccumr (fun x (_ : Unit) ↦ ((), f x)) xs ()).snd := by induction xs using Vector.revInductionOn <;> simp_all @@ -240,7 +240,7 @@ theorem mapAccumr_eq_map {f : α → σ → σ × β} {s₀ : σ} (S : Set σ) ( use fun s _ => s ∈ S, h₀ exact @fun s _q a h => ⟨closure a s h, out a s s₀ h h₀⟩ -protected theorem map₂_eq_mapAccumr₂ : +protected theorem map₂_eq_mapAccumr₂ {f : α → β → γ} : map₂ f xs ys = (mapAccumr₂ (fun x y (_ : Unit) ↦ ((), f x y)) xs ys ()).snd := by induction xs, ys using Vector.revInductionOn₂ <;> simp_all diff --git a/Mathlib/Data/Vector/Snoc.lean b/Mathlib/Data/Vector/Snoc.lean index 41b4c9e7e94c8..ec5dccd5f02c9 100644 --- a/Mathlib/Data/Vector/Snoc.lean +++ b/Mathlib/Data/Vector/Snoc.lean @@ -16,21 +16,21 @@ import Mathlib.Data.Vector.Basic `snoc xs x` for its inductive case. Effectively doing induction from right-to-left -/ -set_option autoImplicit true - namespace Mathlib namespace Vector +variable {α β σ φ : Type*} {n : ℕ} {x : α} {s : σ} (xs : Vector α n) + /-- Append a single element to the end of a vector -/ def snoc : Vector α n → α → Vector α (n+1) := fun xs x => append xs (x ::ᵥ Vector.nil) -/-! -## Simplification lemmas --/ +/-! ## Simplification lemmas -/ + section Simp -variable (xs : Vector α n) + +variable {y : α} @[simp] theorem snoc_cons : (x ::ᵥ xs).snoc y = x ::ᵥ (xs.snoc y) := @@ -64,9 +64,8 @@ theorem replicate_succ_to_snoc (val : α) : end Simp -/-! -## Reverse induction principle --/ +/-! ## Reverse induction principle -/ + section Induction /-- Define `C v` by *reverse* induction on `v : Vector α n`. @@ -115,24 +114,20 @@ def revCasesOn {C : ∀ {n : ℕ}, Vector α n → Sort*} {n : ℕ} (v : Vector end Induction -/-! -## More simplification lemmas --/ +/-! ## More simplification lemmas -/ section Simp -variable (xs : Vector α n) - @[simp] -theorem map_snoc : map f (xs.snoc x) = (map f xs).snoc (f x) := by +theorem map_snoc {f : α → β} : map f (xs.snoc x) = (map f xs).snoc (f x) := by induction xs <;> simp_all @[simp] -theorem mapAccumr_nil : mapAccumr f Vector.nil s = (s, Vector.nil) := +theorem mapAccumr_nil {f : α → σ → σ × β} {s : σ} : mapAccumr f Vector.nil s = (s, Vector.nil) := rfl @[simp] -theorem mapAccumr_snoc : +theorem mapAccumr_snoc {f : α → σ → σ × β} {s : σ} : mapAccumr f (xs.snoc x) s = let q := f x s let r := mapAccumr f xs q.1 @@ -144,17 +139,19 @@ theorem mapAccumr_snoc : variable (ys : Vector β n) @[simp] -theorem map₂_snoc : map₂ f (xs.snoc x) (ys.snoc y) = (map₂ f xs ys).snoc (f x y) := by +theorem map₂_snoc {f : α → β → σ} {y : β} : + map₂ f (xs.snoc x) (ys.snoc y) = (map₂ f xs ys).snoc (f x y) := by induction xs, ys using Vector.inductionOn₂ <;> simp_all @[simp] -theorem mapAccumr₂_nil : mapAccumr₂ f Vector.nil Vector.nil s = (s, Vector.nil) := +theorem mapAccumr₂_nil {f : α → β → σ → σ × φ} : + mapAccumr₂ f Vector.nil Vector.nil s = (s, Vector.nil) := rfl @[simp] theorem mapAccumr₂_snoc (f : α → β → σ → σ × φ) (x : α) (y : β) : - mapAccumr₂ f (xs.snoc x) (ys.snoc y) c - = let q := f x y c + mapAccumr₂ f (xs.snoc x) (ys.snoc y) s + = let q := f x y s let r := mapAccumr₂ f xs ys q.1 (r.1, r.2.snoc q.2) := by induction xs, ys using Vector.inductionOn₂ <;> simp_all diff --git a/Mathlib/Data/ZMod/Basic.lean b/Mathlib/Data/ZMod/Basic.lean index db8d87e23d3e4..0e84d37f5fb66 100644 --- a/Mathlib/Data/ZMod/Basic.lean +++ b/Mathlib/Data/ZMod/Basic.lean @@ -446,7 +446,7 @@ noncomputable def ringEquiv [Fintype R] (h : Fintype.card R = n) : ZMod n ≃+* /-- The unique ring isomorphism between `ZMod p` and a ring `R` of cardinality a prime `p`. If you need any property of this isomorphism, first of all use `ringEquivOfPrime_eq_ringEquiv` -below (after `have : CharP R p := ...`) and deduce it by the results about `ZMod.ringEquiv`. -/ +below (after `have : CharP R p := ...`) and deduce it by the results about `ZMod.ringEquiv`. -/ noncomputable def ringEquivOfPrime [Fintype R] {p : ℕ} (hp : p.Prime) (hR : Fintype.card R = p) : ZMod p ≃+* R := have : Nontrivial R := Fintype.one_lt_card_iff_nontrivial.1 (hR ▸ hp.one_lt) @@ -752,6 +752,12 @@ theorem val_mul_of_lt {n : ℕ} {a b : ZMod n} (h : a.val * b.val < n) : rw [val_mul] apply Nat.mod_eq_of_lt h +theorem val_mul_iff_lt {n : ℕ} [NeZero n] (a b : ZMod n) : + (a * b).val = a.val * b.val ↔ a.val * b.val < n := by + constructor <;> intro h + · rw [← h]; apply ZMod.val_lt + · apply ZMod.val_mul_of_lt h + instance nontrivial (n : ℕ) [Fact (1 < n)] : Nontrivial (ZMod n) := ⟨⟨0, 1, fun h => zero_ne_one <| @@ -988,6 +994,14 @@ theorem natAbs_mod_two (a : ℤ) : (a.natAbs : ZMod 2) = a := by theorem val_ne_zero {n : ℕ} (a : ZMod n) : a.val ≠ 0 ↔ a ≠ 0 := (val_eq_zero a).not +theorem val_pos {n : ℕ} {a : ZMod n} : 0 < a.val ↔ a ≠ 0 := by + simp [pos_iff_ne_zero] + +theorem val_eq_one : ∀ {n : ℕ} (_ : 1 < n) (a : ZMod n), a.val = 1 ↔ a = 1 + | 0, hn, _ + | 1, hn, _ => by simp at hn + | n + 2, _, _ => by simp only [val, ZMod, Fin.ext_iff, Fin.val_one] + 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 @@ -1018,6 +1032,17 @@ theorem neg_eq_self_iff {n : ℕ} (a : ZMod n) : -a = a ↔ a = 0 ∨ 2 * a.val theorem val_cast_of_lt {n : ℕ} {a : ℕ} (h : a < n) : (a : ZMod n).val = a := by rw [val_natCast, Nat.mod_eq_of_lt h] +theorem val_cast_zmod_lt {m : ℕ} [NeZero m] (n : ℕ) [NeZero n] (a : ZMod m) : + (a.cast : ZMod n).val < m := by + rcases m with (⟨⟩|⟨m⟩); · cases NeZero.ne 0 rfl + by_cases h : m < n + · rcases n with (⟨⟩|⟨n⟩); · simp at h + rw [← natCast_val, val_cast_of_lt] + apply ZMod.val_lt a + apply lt_of_le_of_lt (Nat.le_of_lt_succ (ZMod.val_lt a)) h + · rw [not_lt] at h + apply lt_of_lt_of_le (ZMod.val_lt _) (le_trans h (Nat.le_succ m)) + theorem neg_val' {n : ℕ} [NeZero n] (a : ZMod n) : (-a).val = (n - a.val) % n := calc (-a).val = val (-a) % n := by rw [Nat.mod_eq_of_lt (-a).val_lt] @@ -1063,6 +1088,28 @@ theorem cast_cast_zmod_of_le {m n : ℕ} [hm : NeZero m] (h : m ≤ n) (a : ZMod have : NeZero n := ⟨((Nat.zero_lt_of_ne_zero hm.out).trans_le h).ne'⟩ rw [cast_eq_val, val_cast_eq_val_of_lt (a.val_lt.trans_le h), natCast_zmod_val] +theorem val_pow {m n : ℕ} {a : ZMod n} [ilt : Fact (1 < n)] (h : a.val ^ m < n) : + (a ^ m).val = a.val ^ m := by + induction m with + | zero => simp [ZMod.val_one] + | succ m ih => + have : a.val ^ m < n := by + obtain rfl | ha := eq_or_ne a 0 + · by_cases hm : m = 0 + · cases hm; simp [ilt.out] + · simp only [val_zero, ne_eq, hm, not_false_eq_true, zero_pow, Nat.zero_lt_of_lt h] + · exact lt_of_le_of_lt + (Nat.pow_le_pow_of_le_right (by rwa [gt_iff_lt, ZMod.val_pos]) (Nat.le_succ m)) h + rw [pow_succ, ZMod.val_mul, ih this, ← pow_succ, Nat.mod_eq_of_lt h] + +theorem val_pow_le {m n : ℕ} [Fact (1 < n)] {a : ZMod n} : (a ^ m).val ≤ a.val ^ m := by + induction m with + | zero => simp [ZMod.val_one] + | succ m ih => + rw [pow_succ, pow_succ] + apply le_trans (ZMod.val_mul_le _ _) + apply Nat.mul_le_mul_right _ ih + /-- `valMinAbs x` returns the integer in the same equivalence class as `x` that is closest to `0`, The result will be in the interval `(-n/2, n/2]`. -/ def valMinAbs : ∀ {n : ℕ}, ZMod n → ℤ @@ -1429,6 +1476,8 @@ lemma pow_pow_zmod_val_inv (hn : (Nat.card α).Coprime n) (a : α) : end Group +open ZMod + /-- The range of `(m * · + k)` on natural numbers is the set of elements `≥ k` in the residue class of `k` mod `m`. -/ lemma Nat.range_mul_add (m k : ℕ) : @@ -1442,3 +1491,17 @@ lemma Nat.range_mul_add (m k : ℕ) : simp only [ha, Nat.cast_add, add_right_eq_self, ZMod.natCast_zmod_eq_zero_iff_dvd] at H₁ obtain ⟨b, rfl⟩ := H₁ exact ⟨b, ha⟩ + +/-- Equivalence between `ℕ` and `ZMod N × ℕ`, sending `n` to `(n mod N, n / N)`. -/ +def Nat.residueClassesEquiv (N : ℕ) [NeZero N] : ℕ ≃ ZMod N × ℕ where + toFun n := (↑n, n / N) + invFun p := p.1.val + N * p.2 + left_inv n := by simpa only [val_natCast] using mod_add_div n N + right_inv p := by + ext1 + · simp only [add_comm p.1.val, cast_add, cast_mul, natCast_self, zero_mul, natCast_val, + cast_id', id_eq, zero_add] + · simp only [add_comm p.1.val, mul_add_div (NeZero.pos _), + (Nat.div_eq_zero_iff <| (NeZero.pos _)).2 p.1.val_lt, add_zero] + +set_option linter.style.longFile 1700 diff --git a/Mathlib/Data/ZMod/Quotient.lean b/Mathlib/Data/ZMod/Quotient.lean index 39ff9a8cdf6d4..3ea9499281fd8 100644 --- a/Mathlib/Data/ZMod/Quotient.lean +++ b/Mathlib/Data/ZMod/Quotient.lean @@ -57,6 +57,10 @@ def quotientSpanNatEquivZMod : ℤ ⧸ Ideal.span {(n : ℤ)} ≃+* ZMod n := def quotientSpanEquivZMod (a : ℤ) : ℤ ⧸ Ideal.span ({a} : Set ℤ) ≃+* ZMod a.natAbs := (Ideal.quotEquivOfEq (span_natAbs a)).symm.trans (quotientSpanNatEquivZMod a.natAbs) +@[simp] +lemma index_zmultiples (a : ℤ) : (AddSubgroup.zmultiples a).index = a.natAbs := by + rw [AddSubgroup.index, Nat.card_congr (quotientZMultiplesEquivZMod a).toEquiv, Nat.card_zmod] + end Int noncomputable section ChineseRemainder diff --git a/Mathlib/Deprecated/HashMap.lean b/Mathlib/Deprecated/HashMap.lean index 5917267c7b004..a70ec4665c767 100644 --- a/Mathlib/Deprecated/HashMap.lean +++ b/Mathlib/Deprecated/HashMap.lean @@ -8,6 +8,7 @@ nothing from the mathlib3 file `data.hash_map` is reflected here. The porting header is just here to mark that no further work on `data.hash_map` is desired. -/ import Mathlib.Init +import Mathlib.Tactic.TypeStar import Batteries.Data.HashMap.Basic import Batteries.Data.RBMap.Basic @@ -17,7 +18,7 @@ import Batteries.Data.RBMap.Basic These should be replaced by proper implementations in Batteries. -/ -set_option autoImplicit true +variable {α β : Type*} namespace Batteries.HashMap diff --git a/Mathlib/Deprecated/Subgroup.lean b/Mathlib/Deprecated/Subgroup.lean index 17691db27d6d4..cf7b641cb3195 100644 --- a/Mathlib/Deprecated/Subgroup.lean +++ b/Mathlib/Deprecated/Subgroup.lean @@ -589,11 +589,11 @@ theorem normalClosure.is_normal : IsNormalSubgroup (normalClosure s) := /-- The normal closure of s is the smallest normal subgroup containing s. -/ theorem normalClosure_subset {s t : Set G} (ht : IsNormalSubgroup t) (h : s ⊆ t) : normalClosure s ⊆ t := fun a w => by - induction' w with x hx x _ ihx x y _ _ ihx ihy - · exact conjugatesOfSet_subset' ht h <| hx - · exact ht.toIsSubgroup.toIsSubmonoid.one_mem - · exact ht.toIsSubgroup.inv_mem ihx - · exact ht.toIsSubgroup.toIsSubmonoid.mul_mem ihx ihy + induction w with + | basic hx => exact conjugatesOfSet_subset' ht h <| hx + | one => exact ht.toIsSubgroup.toIsSubmonoid.one_mem + | inv _ ihx => exact ht.toIsSubgroup.inv_mem ihx + | mul _ _ ihx ihy => exact ht.toIsSubgroup.toIsSubmonoid.mul_mem ihx ihy theorem normalClosure_subset_iff {s t : Set G} (ht : IsNormalSubgroup t) : s ⊆ t ↔ normalClosure s ⊆ t := diff --git a/Mathlib/Deprecated/Subring.lean b/Mathlib/Deprecated/Subring.lean index 6a652a4c798a3..7c267c4d4f513 100644 --- a/Mathlib/Deprecated/Subring.lean +++ b/Mathlib/Deprecated/Subring.lean @@ -104,7 +104,7 @@ theorem exists_list_of_mem_closure {a : R} (h : a ∈ closure s) : ⟨L1.map (List.cons (-1)), fun L2 h2 ↦ match L2, List.mem_map.1 h2 with | _, ⟨L3, h3, rfl⟩ => List.forall_mem_cons.2 ⟨Or.inr rfl, h1 L3 h3⟩, by - simp only [List.map_map, (· ∘ ·), List.prod_cons, neg_one_mul] + simp only [List.map_map, Function.comp_def, List.prod_cons, neg_one_mul] refine List.recOn L1 neg_zero.symm fun hd tl ih ↦ ?_ rw [List.map_cons, List.sum_cons, ih, List.map_cons, List.sum_cons, neg_add]⟩ fun {r1 r2} _ _ ih1 ih2 ↦ match r1, r2, ih1, ih2 with diff --git a/Mathlib/Dynamics/Circle/RotationNumber/TranslationNumber.lean b/Mathlib/Dynamics/Circle/RotationNumber/TranslationNumber.lean index 7a0cf2877f279..a47e9d3145ffb 100644 --- a/Mathlib/Dynamics/Circle/RotationNumber/TranslationNumber.lean +++ b/Mathlib/Dynamics/Circle/RotationNumber/TranslationNumber.lean @@ -115,7 +115,6 @@ Here are some short-term goals. circle homeomorphism, rotation number -/ - open Filter Set Int Topology open Function hiding Commute @@ -566,7 +565,7 @@ theorem translationNumber_eq_of_tendsto_aux {τ' : ℝ} (h : Tendsto f.transnumA theorem translationNumber_eq_of_tendsto₀ {τ' : ℝ} (h : Tendsto (fun n : ℕ => f^[n] 0 / n) atTop (𝓝 τ')) : τ f = τ' := f.translationNumber_eq_of_tendsto_aux <| by - simpa [(· ∘ ·), transnumAuxSeq_def, coe_pow] using + simpa [Function.comp_def, transnumAuxSeq_def, coe_pow] using h.comp (Nat.tendsto_pow_atTop_atTop_of_one_lt one_lt_two) theorem translationNumber_eq_of_tendsto₀' {τ' : ℝ} @@ -708,7 +707,7 @@ theorem le_translationNumber_of_add_le {z : ℝ} (hz : ∀ x, x + z ≤ f x) : z theorem translationNumber_le_of_le_add_int {x : ℝ} {m : ℤ} (h : f x ≤ x + m) : τ f ≤ m := le_of_tendsto' (f.tendsto_translation_number' x) fun n => - (div_le_iff' (n.cast_add_one_pos : (0 : ℝ) < _)).mpr <| sub_le_iff_le_add'.2 <| + (div_le_iff₀' (n.cast_add_one_pos : (0 : ℝ) < _)).mpr <| sub_le_iff_le_add'.2 <| (coe_pow f (n + 1)).symm ▸ @Nat.cast_add_one ℝ _ n ▸ f.iterate_le_of_map_le_add_int h (n + 1) theorem translationNumber_le_of_le_add_nat {x : ℝ} {m : ℕ} (h : f x ≤ x + m) : τ f ≤ m := @@ -716,7 +715,7 @@ theorem translationNumber_le_of_le_add_nat {x : ℝ} {m : ℕ} (h : f x ≤ x + theorem le_translationNumber_of_add_int_le {x : ℝ} {m : ℤ} (h : x + m ≤ f x) : ↑m ≤ τ f := ge_of_tendsto' (f.tendsto_translation_number' x) fun n => - (le_div_iff (n.cast_add_one_pos : (0 : ℝ) < _)).mpr <| le_sub_iff_add_le'.2 <| by + (le_div_iff₀ (n.cast_add_one_pos : (0 : ℝ) < _)).mpr <| le_sub_iff_add_le'.2 <| by simp only [coe_pow, mul_comm (m : ℝ), ← Nat.cast_add_one, f.le_iterate_of_add_int_le_map h] theorem le_translationNumber_of_add_nat_le {x : ℝ} {m : ℕ} (h : x + m ≤ f x) : ↑m ≤ τ f := diff --git a/Mathlib/Dynamics/Ergodic/Conservative.lean b/Mathlib/Dynamics/Ergodic/Conservative.lean index 4853d8c9c1bfc..7e924b8864da3 100644 --- a/Mathlib/Dynamics/Ergodic/Conservative.lean +++ b/Mathlib/Dynamics/Ergodic/Conservative.lean @@ -147,7 +147,7 @@ theorem measure_inter_frequently_image_mem_eq (hf : Conservative f μ) (hs : Nul /-- Poincaré recurrence theorem: if `f` is a conservative dynamical system and `s` is a measurable set, then for `μ`-a.e. `x`, if the orbit of `x` visits `s` at least once, then it visits `s` -infinitely many times. -/ +infinitely many times. -/ theorem ae_forall_image_mem_imp_frequently_image_mem (hf : Conservative f μ) (hs : NullMeasurableSet s μ) : ∀ᵐ x ∂μ, ∀ k, f^[k] x ∈ s → ∃ᶠ n in atTop, f^[n] x ∈ s := by refine ae_all_iff.2 fun k => ?_ diff --git a/Mathlib/Dynamics/Ergodic/Ergodic.lean b/Mathlib/Dynamics/Ergodic/Ergodic.lean index 0198ed3650021..2efbb69a9f654 100644 --- a/Mathlib/Dynamics/Ergodic/Ergodic.lean +++ b/Mathlib/Dynamics/Ergodic/Ergodic.lean @@ -111,18 +111,16 @@ namespace QuasiErgodic /-- For a quasi ergodic map, sets that are almost invariant (rather than strictly invariant) are still either almost empty or full. -/ -theorem ae_empty_or_univ' (hf : QuasiErgodic f μ) (hs : MeasurableSet s) (hs' : f ⁻¹' s =ᵐ[μ] s) : - s =ᵐ[μ] (∅ : Set α) ∨ s =ᵐ[μ] univ := by - obtain ⟨t, h₀, h₁, h₂⟩ := hf.toQuasiMeasurePreserving.exists_preimage_eq_of_preimage_ae hs hs' - rcases hf.ae_empty_or_univ h₀ h₂ with (h₃ | h₃) <;> [left; right] <;> exact ae_eq_trans h₁.symm h₃ +theorem ae_empty_or_univ₀ (hf : QuasiErgodic f μ) (hsm : NullMeasurableSet s μ) + (hs : f ⁻¹' s =ᵐ[μ] s) : s =ᵐ[μ] (∅ : Set α) ∨ s =ᵐ[μ] univ := + let ⟨_t, h₀, h₁, h₂⟩ := hf.toQuasiMeasurePreserving.exists_preimage_eq_of_preimage_ae hsm hs + (hf.ae_empty_or_univ h₀ h₂).imp h₁.symm.trans h₁.symm.trans /-- For a quasi ergodic map, sets that are almost invariant (rather than strictly invariant) are still either almost empty or full. -/ -theorem ae_empty_or_univ₀ (hf : QuasiErgodic f μ) (hsm : NullMeasurableSet s μ) - (hs : f ⁻¹' s =ᵐ[μ] s) : s =ᵐ[μ] (∅ : Set α) ∨ s =ᵐ[μ] univ := - let ⟨t, htm, hst⟩ := hsm - have : f ⁻¹' t =ᵐ[μ] t := (hf.preimage_ae_eq hst.symm).trans <| hs.trans hst - (hf.ae_empty_or_univ' htm this).imp hst.trans hst.trans +theorem ae_empty_or_univ' (hf : QuasiErgodic f μ) (hs : MeasurableSet s) (hs' : f ⁻¹' s =ᵐ[μ] s) : + s =ᵐ[μ] (∅ : Set α) ∨ s =ᵐ[μ] univ := + ae_empty_or_univ₀ hf hs.nullMeasurableSet hs' /-- For a quasi ergodic map, sets that are almost invariant (rather than strictly invariant) are still either almost empty or full. -/ @@ -140,23 +138,21 @@ theorem quasiErgodic (hf : Ergodic f μ) : QuasiErgodic f μ := { hf.toPreErgodic, hf.toMeasurePreserving.quasiMeasurePreserving with } /-- See also `Ergodic.ae_empty_or_univ_of_preimage_ae_le`. -/ -theorem ae_empty_or_univ_of_preimage_ae_le' (hf : Ergodic f μ) (hs : MeasurableSet s) +theorem ae_empty_or_univ_of_preimage_ae_le' (hf : Ergodic f μ) (hs : NullMeasurableSet s μ) (hs' : f ⁻¹' s ≤ᵐ[μ] s) (h_fin : μ s ≠ ∞) : s =ᵐ[μ] (∅ : Set α) ∨ s =ᵐ[μ] univ := by - refine hf.quasiErgodic.ae_empty_or_univ' hs ?_ - refine ae_eq_of_ae_subset_of_measure_ge hs' - (hf.measure_preimage hs.nullMeasurableSet).symm.le ?_ h_fin - exact measurableSet_preimage hf.measurable hs + refine hf.quasiErgodic.ae_empty_or_univ₀ hs ?_ + refine ae_eq_of_ae_subset_of_measure_ge hs' (hf.measure_preimage hs).ge ?_ h_fin + exact hs.preimage hf.quasiMeasurePreserving /-- See also `Ergodic.ae_empty_or_univ_of_ae_le_preimage`. -/ -theorem ae_empty_or_univ_of_ae_le_preimage' (hf : Ergodic f μ) (hs : MeasurableSet s) +theorem ae_empty_or_univ_of_ae_le_preimage' (hf : Ergodic f μ) (hs : NullMeasurableSet s μ) (hs' : s ≤ᵐ[μ] f ⁻¹' s) (h_fin : μ s ≠ ∞) : s =ᵐ[μ] (∅ : Set α) ∨ s =ᵐ[μ] univ := by - replace h_fin : μ (f ⁻¹' s) ≠ ∞ := by rwa [hf.measure_preimage hs.nullMeasurableSet] - refine hf.quasiErgodic.ae_empty_or_univ' hs ?_ - exact (ae_eq_of_ae_subset_of_measure_ge hs' - (hf.measure_preimage hs.nullMeasurableSet).le hs h_fin).symm + replace h_fin : μ (f ⁻¹' s) ≠ ∞ := by rwa [hf.measure_preimage hs] + refine hf.quasiErgodic.ae_empty_or_univ₀ hs ?_ + exact (ae_eq_of_ae_subset_of_measure_ge hs' (hf.measure_preimage hs).le hs h_fin).symm /-- See also `Ergodic.ae_empty_or_univ_of_image_ae_le`. -/ -theorem ae_empty_or_univ_of_image_ae_le' (hf : Ergodic f μ) (hs : MeasurableSet s) +theorem ae_empty_or_univ_of_image_ae_le' (hf : Ergodic f μ) (hs : NullMeasurableSet s μ) (hs' : f '' s ≤ᵐ[μ] s) (h_fin : μ s ≠ ∞) : s =ᵐ[μ] (∅ : Set α) ∨ s =ᵐ[μ] univ := by replace hs' : s ≤ᵐ[μ] f ⁻¹' s := (HasSubset.Subset.eventuallyLE (subset_preimage_image f s)).trans @@ -167,15 +163,15 @@ section IsFiniteMeasure variable [IsFiniteMeasure μ] -theorem ae_empty_or_univ_of_preimage_ae_le (hf : Ergodic f μ) (hs : MeasurableSet s) +theorem ae_empty_or_univ_of_preimage_ae_le (hf : Ergodic f μ) (hs : NullMeasurableSet s μ) (hs' : f ⁻¹' s ≤ᵐ[μ] s) : s =ᵐ[μ] (∅ : Set α) ∨ s =ᵐ[μ] univ := ae_empty_or_univ_of_preimage_ae_le' hf hs hs' <| measure_ne_top μ s -theorem ae_empty_or_univ_of_ae_le_preimage (hf : Ergodic f μ) (hs : MeasurableSet s) +theorem ae_empty_or_univ_of_ae_le_preimage (hf : Ergodic f μ) (hs : NullMeasurableSet s μ) (hs' : s ≤ᵐ[μ] f ⁻¹' s) : s =ᵐ[μ] (∅ : Set α) ∨ s =ᵐ[μ] univ := ae_empty_or_univ_of_ae_le_preimage' hf hs hs' <| measure_ne_top μ s -theorem ae_empty_or_univ_of_image_ae_le (hf : Ergodic f μ) (hs : MeasurableSet s) +theorem ae_empty_or_univ_of_image_ae_le (hf : Ergodic f μ) (hs : NullMeasurableSet s μ) (hs' : f '' s ≤ᵐ[μ] s) : s =ᵐ[μ] (∅ : Set α) ∨ s =ᵐ[μ] univ := ae_empty_or_univ_of_image_ae_le' hf hs hs' <| measure_ne_top μ s diff --git a/Mathlib/Dynamics/OmegaLimit.lean b/Mathlib/Dynamics/OmegaLimit.lean index 61f82cc579837..7de977bddf6ba 100644 --- a/Mathlib/Dynamics/OmegaLimit.lean +++ b/Mathlib/Dynamics/OmegaLimit.lean @@ -86,8 +86,8 @@ theorem mapsTo_omegaLimit' {α' β' : Type*} [TopologicalSpace β'] {f : Filter intro y hy u hu refine map_mem_closure hgc (hy _ (inter_mem hu hg)) (forall_image2_iff.2 fun t ht x hx ↦ ?_) calc - gb (ϕ t x) = ϕ' t (ga x) := ht.2 hx - _ ∈ image2 ϕ' u s' := mem_image2_of_mem ht.1 (hs hx) + ϕ' t (ga x) ∈ image2 ϕ' u s' := mem_image2_of_mem ht.1 (hs hx) + _ = gb (ϕ t x) := ht.2 hx |>.symm theorem mapsTo_omegaLimit {α' β' : Type*} [TopologicalSpace β'] {f : Filter τ} {ϕ : τ → α → β} {ϕ' : τ → α' → β'} {ga : α → α'} {s' : Set α'} (hs : MapsTo ga s s') {gb : β → β'} @@ -192,6 +192,9 @@ theorem omegaLimit_subset_closure_fw_image {u : Set τ} (hu : u ∈ f) : rw [mem_iInter] at hx exact hx ⟨u, hu⟩ +-- An instance with better keys +instance : Inhabited f.sets := Filter.inhabitedMem + /-! ### ω-limits and compactness -/ diff --git a/Mathlib/Dynamics/PeriodicPts.lean b/Mathlib/Dynamics/PeriodicPts.lean index 658cf28c6f47d..3f47192c4cc47 100644 --- a/Mathlib/Dynamics/PeriodicPts.lean +++ b/Mathlib/Dynamics/PeriodicPts.lean @@ -6,6 +6,7 @@ Authors: Yury Kudryashov import Mathlib.Algebra.GroupPower.IterateHom import Mathlib.Algebra.Ring.Divisibility.Basic import Mathlib.Data.List.Cycle +import Mathlib.Data.Nat.GCD.Basic import Mathlib.Data.Nat.Prime.Basic import Mathlib.Data.PNat.Basic import Mathlib.Dynamics.FixedPoints.Basic diff --git a/Mathlib/Dynamics/TopologicalEntropy/CoverEntropy.lean b/Mathlib/Dynamics/TopologicalEntropy/CoverEntropy.lean new file mode 100644 index 0000000000000..0333f199aa230 --- /dev/null +++ b/Mathlib/Dynamics/TopologicalEntropy/CoverEntropy.lean @@ -0,0 +1,596 @@ +/- +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.Analysis.SpecialFunctions.Log.ENNRealLog +import Mathlib.Data.Real.ENatENNReal +import Mathlib.Dynamics.TopologicalEntropy.DynamicalEntourage + +/-! +# Topological entropy via covers +We implement Bowen-Dinaburg's definitions of the topological entropy, via covers. + +All is stated in the vocabulary of uniform spaces. For compact spaces, the uniform structure +is canonical, so the topological entropy depends only on the topological structure. This will give +a clean proof that the topological entropy is a topological invariant of the dynamics. + +A notable choice is that we define the topological entropy of a subset `F` of the whole space. +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 +equivalence between both versions. + +Another choice is to give a meaning to the entropy of `∅` (it must be `-∞` to stay coherent) and to +keep the possibility for the entropy to be infinite. Hence, the entropy takes values in the extended +reals `[-∞, +∞]`. The consequence is that we use `ℕ∞`, `ℝ≥0∞` and `EReal` numbers. + +## 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 +versions of the topological entropy with covers. Take values in `EReal`. + +## Implementation notes +There are two competing definitions of topological entropy in this file: one uses a `liminf`, +the other a `limsup`. These two topological entropies are equal as soon as they are applied to an +invariant subset by theorem `coverEntropyInf_eq_coverEntropy`. We choose the default definition +to be the definition using a `limsup`, and give it the simpler name `coverEntropy` (instead of +`coverEntropySup`). Theorems about the topological entropy of invariant subsets will be stated +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. +- `coverEntropyInf_eq_coverEntropy`: equality between the notions of topological entropy defined +with a `liminf` and a `limsup`. + +## Tags +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. + +Get versions of the topological entropy on (pseudo-e)metric spaces. +-/ + +namespace Dynamics + +open Set Uniformity UniformSpace + +variable {X : Type*} + +/-! ### Dynamical covers -/ + +/-- Given a subset `F`, an entourage `U` and an integer `n`, a subset `s` is a `(U, n)`- +dynamical cover of `F` if any orbit of length `n` in `F` is `U`-shadowed by an orbit of length `n` +of a point in `s`.-/ +def IsDynCoverOf (T : X → X) (F : Set X) (U : Set (X × X)) (n : ℕ) (s : Set X) : Prop := + F ⊆ ⋃ x ∈ s, ball x (dynEntourage T U n) + +lemma IsDynCoverOf.of_le {T : X → X} {F : Set X} {U : Set (X × X)} {m n : ℕ} (m_n : m ≤ n) + {s : Set X} (h : IsDynCoverOf T F U n s) : + IsDynCoverOf T F U m s := by + exact Subset.trans (c := ⋃ x ∈ s, ball x (dynEntourage T U m)) h + (iUnion₂_mono fun x _ ↦ ball_mono (dynEntourage_antitone T U m_n) x) + +lemma IsDynCoverOf.of_entourage_subset {T : X → X} {F : Set X} {U V : Set (X × X)} (U_V : U ⊆ V) + {n : ℕ} {s : Set X} (h : IsDynCoverOf T F U n s) : + IsDynCoverOf T F V n s := by + exact Subset.trans (c := ⋃ x ∈ s, ball x (dynEntourage T V n)) h + (iUnion₂_mono fun x _ ↦ ball_mono (dynEntourage_monotone T n U_V) x) + +@[simp] +lemma isDynCoverOf_empty {T : X → X} {U : Set (X × X)} {n : ℕ} {s : Set X} : + IsDynCoverOf T ∅ U n s := by + simp only [IsDynCoverOf, empty_subset] + +lemma IsDynCoverOf.nonempty {T : X → X} {F : Set X} (h : F.Nonempty) {U : Set (X × X)} {n : ℕ} + {s : Set X} (h' : IsDynCoverOf T F U n s) : + s.Nonempty := by + rcases nonempty_biUnion.1 (Nonempty.mono h' h) with ⟨x, x_s, _⟩ + exact nonempty_of_mem x_s + +lemma isDynCoverOf_zero (T : X → X) (F : Set X) (U : Set (X × X)) {s : Set X} (h : s.Nonempty) : + IsDynCoverOf T F U 0 s := by + simp only [IsDynCoverOf, ball, dynEntourage, not_lt_zero', Prod.map_iterate, iInter_of_empty, + iInter_univ, preimage_univ] + rcases h with ⟨x, x_s⟩ + exact subset_iUnion₂_of_subset x x_s (subset_univ F) + +lemma isDynCoverOf_univ (T : X → X) (F : Set X) (n : ℕ) {s : Set X} (h : s.Nonempty) : + IsDynCoverOf T F univ n s := by + simp only [IsDynCoverOf, ball, dynEntourage, Prod.map_iterate, preimage_univ, iInter_univ, + iUnion_coe_set] + rcases h with ⟨x, x_s⟩ + exact subset_iUnion₂_of_subset x x_s (subset_univ F) + +lemma IsDynCoverOf.nonempty_inter {T : X → X} {F : Set X} {U : Set (X × X)} {n : ℕ} {s : Finset X} + (h : IsDynCoverOf T F U n s) : + ∃ t : Finset X, IsDynCoverOf T F U n t ∧ t.card ≤ s.card + ∧ ∀ x ∈ t, ((ball x (dynEntourage T U n)) ∩ F).Nonempty := by + classical + use Finset.filter (fun x : X ↦ ((ball x (dynEntourage T U n)) ∩ F).Nonempty) s + simp only [Finset.coe_filter, Finset.mem_filter, and_imp, imp_self, implies_true, and_true] + refine ⟨fun y y_F ↦ ?_, Finset.card_mono (Finset.filter_subset _ s)⟩ + specialize h y_F + simp only [Finset.coe_sort_coe, mem_iUnion, Subtype.exists, exists_prop] at h + rcases h with ⟨z, z_s, y_Bz⟩ + simp only [coe_setOf, mem_setOf_eq, mem_iUnion, Subtype.exists, exists_prop] + exact ⟨z, ⟨z_s, nonempty_of_mem ⟨y_Bz, y_F⟩⟩, y_Bz⟩ + +/-- 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`).-/ +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 + classical + -- Deal with the edge cases: `F = ∅` or `m = 0`. + rcases F.eq_empty_or_nonempty with rfl | F_nemp + · exact ⟨∅, by simp⟩ + have _ : Nonempty X := nonempty_of_exists F_nemp + have s_nemp := h.nonempty F_nemp + rcases F_nemp with ⟨x, x_F⟩ + rcases m.eq_zero_or_pos with rfl | m_pos + · use {x} + simp only [zero_mul, Finset.coe_singleton, Finset.card_singleton] + exact And.intro (isDynCoverOf_zero T F (U ○ U) (singleton_nonempty x)) + <| one_le_pow_of_one_le' (Nat.one_le_of_lt (Finset.Nonempty.card_pos s_nemp)) n + -- The proof goes as follows. Given an orbit of length `(m * n)` starting from `y`, each of its + -- iterates `y`, `T^[m] y`, `T^[m]^[2] y` ... is `(dynEntourage T U m)`-close to a point of `s`. + -- Conversely, given a sequence `t 0`, `t 1`, `t 2` of points in `s`, we choose a point + -- `z = dyncover t` such that `z`, `T^[m] z`, `T^[m]^[2] z` ... are `(dynEntourage T U m)`-close + -- to `t 0`, `t 1`, `t 2`... Then `y`, `T^[m] y`, `T^[m]^[2] y` ... are + -- `(dynEntourage T (U ○ U) m)`-close to `z`, `T^[m] z`, `T^[m]^[2] z`, so that the union of such + -- `z` provides the desired cover. Since there are at most `s.card ^ n` sequences of + -- length `n` with values in `s`, we get the upper bound we want on the cardinality. + -- First step: construct `dyncover`. Given `t 0`, `t 1`, `t 2`, if we cannot find such a point + -- `dyncover t`, we use the dummy `x`. + have (t : Fin n → s) : ∃ y : X, (⋂ k : Fin n, T^[m * k] ⁻¹' ball (t k) (dynEntourage T U m)) ⊆ + ball y (dynEntourage T (U ○ U) (m * n)) := by + rcases (⋂ k : Fin n, T^[m * k] ⁻¹' ball (t k) (dynEntourage T U m)).eq_empty_or_nonempty + with inter_empt | inter_nemp + · exact inter_empt ▸ ⟨x, empty_subset _⟩ + · rcases inter_nemp with ⟨y, y_int⟩ + refine ⟨y, fun z z_int ↦ ?_⟩ + simp only [ball, dynEntourage, Prod.map_iterate, mem_preimage, mem_iInter, + Prod.map_apply] at y_int z_int ⊢ + intro k k_mn + replace k_mn := Nat.div_lt_of_lt_mul k_mn + specialize z_int ⟨(k / m), k_mn⟩ (k % m) (Nat.mod_lt k m_pos) + specialize y_int ⟨(k / m), k_mn⟩ (k % m) (Nat.mod_lt k m_pos) + rw [← Function.iterate_add_apply T (k % m) (m * (k / m)), Nat.mod_add_div k m] at y_int z_int + exact mem_comp_of_mem_ball U_symm y_int z_int + choose! dyncover h_dyncover using this + -- The cover we want is the set of all `dyncover t`, that is, `range dyncover`. We need to check + -- that it is indeed a `(U ○ U, m * n)` cover, and that its cardinality is at most `card s ^ n`. + -- Only the first point requires significant work. + let sn := range dyncover + have := fintypeRange dyncover + refine ⟨sn.toFinset, ?_, ?_⟩ + · -- We implement the argument at the beginning: given `y ∈ F`, we extract `t 0`, `t 1`, `t 2` + -- such that `y`, `T^[m] y`, `T^[m]^[2] y` ... is `(dynEntourage T U m)`-close to `t 0`, `t 1`, + -- `t 2`... Then `dyncover t` is a point of `range dyncover` which satisfies the conclusion + -- of the lemma. + rw [Finset.coe_nonempty] at s_nemp + have _ : Nonempty s := Finset.Nonempty.coe_sort s_nemp + intro y y_F + have key : ∀ k : Fin n, ∃ z : s, y ∈ T^[m * k] ⁻¹' ball z (dynEntourage T U m) := by + intro k + have := h (MapsTo.iterate F_inv (m * k) y_F) + simp only [Finset.coe_sort_coe, mem_iUnion, Subtype.exists, exists_prop] at this + rcases this with ⟨z, z_s, hz⟩ + exact ⟨⟨z, z_s⟩, hz⟩ + choose! t ht using key + simp only [toFinset_range, Finset.coe_image, Finset.coe_univ, image_univ, mem_range, + iUnion_exists, iUnion_iUnion_eq', mem_iUnion, sn] + use t + apply h_dyncover t + simp only [mem_iInter, mem_preimage] at ht ⊢ + exact ht + · rw [toFinset_card] + apply (Fintype.card_range_le dyncover).trans + simp only [Fintype.card_fun, Fintype.card_coe, Fintype.card_fin, le_refl] + +lemma exists_isDynCoverOf_of_isCompact_uniformContinuous [UniformSpace X] {T : X → X} {F : Set X} + (F_comp : IsCompact F) (h : UniformContinuous T) {U : Set (X × X)} (U_uni : U ∈ 𝓤 X) (n : ℕ) : + ∃ s : Finset X, IsDynCoverOf T F U n s := by + have uni_ite := dynEntourage_mem_uniformity h U_uni n + let open_cover := fun x : X ↦ ball x (dynEntourage T U n) + obtain ⟨s, _, s_cover⟩ := IsCompact.elim_nhds_subcover F_comp open_cover + (fun (x : X) _ ↦ ball_mem_nhds x uni_ite) + exact ⟨s, s_cover⟩ + +lemma exists_isDynCoverOf_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 : ℕ) : + ∃ s : Finset X, IsDynCoverOf T F U n s := by + rcases comp_symm_mem_uniformity_sets U_uni with ⟨V, V_uni, V_symm, V_U⟩ + obtain ⟨s, _, s_cover⟩ := IsCompact.elim_nhds_subcover F_comp (fun x : X ↦ ball x V) + (fun (x : X) _ ↦ ball_mem_nhds x V_uni) + have : IsDynCoverOf T F V 1 s := by + simp only [IsDynCoverOf, Finset.mem_coe, dynEntourage_one, s_cover] + rcases this.iterate_le_pow F_inv V_symm n with ⟨t, t_dyncover, t_card⟩ + rw [one_mul n] at t_dyncover + exact ⟨t, t_dyncover.of_entourage_subset V_U⟩ + +/-! ### Minimal cardinality of dynamical covers -/ + +/-- The smallest cardinality of a `(U, n)`-dynamical cover of `F`. Takes values in `ℕ∞`, and is + infinite if and only if `F` admits no finite dynamical cover.-/ +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) : + 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)) : + Monotone (fun n : ℕ ↦ coverMincard T F U n) := + fun _ _ m_n ↦ biInf_mono fun _ h ↦ h.of_le m_n + +lemma coverMincard_antitone (T : X → X) (F : Set X) (n : ℕ) : + Antitone (fun U : Set (X × X) ↦ coverMincard T F U n) := + fun _ _ U_V ↦ biInf_mono fun _ h ↦ h.of_entourage_subset U_V + +lemma coverMincard_finite_iff (T : X → X) (F : Set X) (U : Set (X × X)) (n : ℕ) : + coverMincard T F U n < ⊤ ↔ + ∃ s : Finset X, IsDynCoverOf T F U n s ∧ s.card = coverMincard T F U n := by + refine ⟨fun h_fin ↦ ?_, (fun ⟨s, _, s_coverMincard⟩ ↦ s_coverMincard ▸ WithTop.coe_lt_top s.card)⟩ + rcases WithTop.ne_top_iff_exists.1 (ne_of_lt h_fin) with ⟨k, k_min⟩ + rw [← k_min] + simp only [ENat.some_eq_coe, Nat.cast_inj] + have : Nonempty {s : Finset X // IsDynCoverOf T F U n s} := by + by_contra h + apply ENat.coe_ne_top k + rw [← ENat.some_eq_coe, k_min, coverMincard, iInf₂_eq_top] + simp only [ENat.coe_ne_top, imp_false] + rw [nonempty_subtype, not_exists] at h + exact h + have key := ciInf_mem (fun s : {s : Finset X // IsDynCoverOf T F U n s} ↦ (s.val.card : ℕ∞)) + rw [coverMincard, iInf_subtype'] at k_min + rw [← k_min, mem_range, Subtype.exists] at key + simp only [ENat.some_eq_coe, Nat.cast_inj, exists_prop] at key + exact key + +@[simp] +lemma coverMincard_empty {T : X → X} {U : Set (X × X)} {n : ℕ} : coverMincard T ∅ U n = 0 := + (sInf_le (by simp [IsDynCoverOf])).antisymm (zero_le (coverMincard T ∅ U n)) + +lemma coverMincard_eq_zero_iff (T : X → X) (F : Set X) (U : Set (X × X)) (n : ℕ) : + coverMincard T F U n = 0 ↔ F = ∅ := by + refine Iff.intro (fun h ↦ subset_empty_iff.1 ?_) (fun F_empt ↦ by rw [F_empt, coverMincard_empty]) + have := coverMincard_finite_iff T F U n + rw [h, eq_true ENat.zero_lt_top, true_iff] at this + simp only [IsDynCoverOf, Finset.mem_coe, Nat.cast_eq_zero, Finset.card_eq_zero, exists_eq_right, + Finset.not_mem_empty, iUnion_of_empty, iUnion_empty] at this + exact this + +lemma one_le_coverMincard_iff (T : X → X) (F : Set X) (U : Set (X × X)) (n : ℕ) : + 1 ≤ coverMincard T F U n ↔ F.Nonempty := by + rw [ENat.one_le_iff_ne_zero, nonempty_iff_ne_empty, not_iff_not] + exact coverMincard_eq_zero_iff T F U n + +lemma coverMincard_zero (T : X → X) {F : Set X} (h : F.Nonempty) (U : Set (X × X)) : + coverMincard T F U 0 = 1 := by + apply le_antisymm _ ((one_le_coverMincard_iff T F U 0).2 h) + 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) + rw [Finset.card_singleton, Nat.cast_one] + +lemma coverMincard_univ (T : X → X) {F : Set X} (h : F.Nonempty) (n : ℕ) : + coverMincard T F univ n = 1 := by + apply le_antisymm _ ((one_le_coverMincard_iff T F univ n).2 h) + 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) + 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)} + (U_symm : SymmetricRel U) (m n : ℕ) : + coverMincard T F (U ○ U) (m * n) ≤ coverMincard T F U m ^ n := by + rcases F.eq_empty_or_nonempty with rfl | F_nonempty + · rw [coverMincard_empty]; exact zero_le _ + 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 + · 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) + +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_mul_le_pow F_inv U_symm m (n / m + 1)) + +lemma coverMincard_finite_of_isCompact_uniformContinuous [UniformSpace X] {T : X → X} + {F : Set X} (F_comp : IsCompact F) (h : UniformContinuous T) {U : Set (X × X)} (U_uni : U ∈ 𝓤 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) + +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) + +/-- 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 + of topological entropy with nets.-/ +lemma nonempty_inter_of_coverMincard {T : X → X} {F : Set X} {U : Set (X × X)} {n : ℕ} + {s : Finset X} (h : IsDynCoverOf T F U n s) (h' : s.card = coverMincard T F U n) : + ∀ x ∈ s, (F ∩ ball x (dynEntourage T U n)).Nonempty := by + -- Otherwise, there is a ball which does not intersect `F`. Removing it yields a smaller cover. + classical + by_contra! hypo + rcases hypo with ⟨x, x_s, ball_empt⟩ + have smaller_cover : IsDynCoverOf T F U n (Finset.erase s x) := by + intro y y_F + specialize h y_F + simp only [Finset.mem_coe, mem_iUnion, exists_prop] at h + rcases h with ⟨z, z_s, hz⟩ + simp only [Finset.coe_erase, mem_diff, Finset.mem_coe, mem_singleton_iff, mem_iUnion, + exists_prop] + refine ⟨z, And.intro (And.intro z_s fun z_x ↦ not_mem_empty y ?_) hz⟩ + rw [← ball_empt] + rw [z_x] at hz + exact mem_inter y_F hz + apply not_lt_of_le (coverMincard_le_card smaller_cover) + rw [← h'] + exact_mod_cast Finset.card_erase_lt_of_mem x_s + +open ENNReal EReal + +lemma log_coverMincard_nonneg (T : X → X) {F : Set X} (h : F.Nonempty) (U : Set (X × X)) (n : ℕ) : + 0 ≤ log (coverMincard T F U n) := by + apply zero_le_log_iff.2 + rw [← ENat.toENNReal_one, ENat.toENNReal_le] + exact (one_le_coverMincard_iff T F U n).2 h + +lemma log_coverMincard_iterate_le {T : X → X} {F : Set X} (F_inv : MapsTo T F F) {U : Set (X × X)} + (U_symm : SymmetricRel U) (m : ℕ) {n : ℕ} (n_pos : 0 < n) : + log (coverMincard T F (U ○ U) (m * n)) / n ≤ log (coverMincard T F U m) := by + apply (EReal.div_le_iff_le_mul (b := n) (Nat.cast_pos'.2 n_pos) (natCast_ne_top n)).2 + rw [← log_pow, StrictMono.le_iff_le log_strictMono] + nth_rw 2 [← ENat.toENNRealRingHom_apply] + rw [← RingHom.map_pow ENat.toENNRealRingHom _ n, ENat.toENNRealRingHom_apply, ENat.toENNReal_le] + exact coverMincard_mul_le_pow F_inv U_symm m n + +lemma log_coverMincard_le_add {T : X → X} {F : Set X} (F_inv : MapsTo T F F) + {U : Set (X × X)} (U_symm : SymmetricRel U) {m n : ℕ} (m_pos : 0 < m) (n_pos : 0 < n) : + log (coverMincard T F (U ○ U) n) / n + ≤ log (coverMincard T F U m) / m + log (coverMincard T F U m) / n := by + -- If `n` is a multiple of `m`, this follows directly from `log_coverMincard_iterate_le`. + -- Otherwise, we bound the LHS by the smallest multiple of `m` larger than `n`, which gives the + -- error term `log (coverMincard T F U m) / n`. + rcases F.eq_empty_or_nonempty with rfl | F_nemp + · rw [coverMincard_empty, ENat.toENNReal_zero, log_zero, + bot_div_of_pos_ne_top (Nat.cast_pos'.2 n_pos) (natCast_ne_top n)] + exact bot_le + 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)) + 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) + 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)) := + 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)) := + 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) := + 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) := + 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 + +@[simp] +lemma coverEntropyEnt_empty {T : X → X} {U : Set (X × X)} : + coverEntropyEnt T ∅ U = ⊥ := by + suffices h : ∀ᶠ n : ℕ in atTop, log (coverMincard T ∅ U n) / n = ⊥ by + rw [coverEntropyEnt] + 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 coverEntropyInfEnt_nonneg (T : X → X) {F : Set X} (h : F.Nonempty) (U : Set (X × X)) : + 0 ≤ coverEntropyInfEnt 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 coverEntropyEnt_univ (T : X → X) {F : Set X} (h : F.Nonempty) : + coverEntropyEnt T F univ = 0 := by + simp [coverEntropyEnt, 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 coverEntropyEnt_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 + -- 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, + coverMincard_eq_zero_iff T F U n] at logm_bot + simp [logm_bot] + rcases eq_or_ne (log (coverMincard T F U n)) ⊤ with logm_top | logm_fin + · rw [logm_top, top_div_of_pos_ne_top (Nat.cast_pos'.2 n_pos) (natCast_ne_top n)] + exact le_top + -- The general case follows from `log_coverMincard_le_add`, with careful manipulation of limits. + let u := fun _ : ℕ ↦ log (coverMincard T F U n) / n + let v := fun m : ℕ ↦ log (coverMincard T F U n) / m + let w := fun m : ℕ ↦ log (coverMincard T F (U ○ U) m) / m + have key : w ≤ᶠ[atTop] u + v := + eventually_atTop.2 ⟨1, fun m m_pos ↦ log_coverMincard_le_add F_inv U_symm n_pos m_pos⟩ + apply ((limsup_le_limsup) key).trans + suffices h : atTop.limsup v = 0 by + 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 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 + 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 := + (le_liminf_of_le) (eventually_atTop.2 + ⟨1, fun m m_pos ↦ coverEntropyEnt_le_log_coverMincard_div F_inv U_symm m_pos⟩) + +lemma coverEntropyEnt_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 + 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 + 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.-/ +noncomputable def coverEntropy [UniformSpace X] (T : X → X) (F : Set X) := + ⨆ U ∈ 𝓤 X, coverEntropyEnt 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.-/ +noncomputable def coverEntropyInf [UniformSpace X] (T : X → X) (F : Set X) := + ⨆ U ∈ 𝓤 X, coverEntropyInfEnt T F U + +lemma coverEntropyInf_antitone (T : X → X) (F : Set X) : + Antitone fun (u : UniformSpace X) ↦ @coverEntropyInf X u T F := + fun _ _ h ↦ iSup₂_mono' fun U U_uni ↦ ⟨U, (le_def.1 h) U U_uni, le_refl _⟩ + +lemma coverEntropy_antitone (T : X → X) (F : Set X) : + Antitone fun (u : UniformSpace X) ↦ @coverEntropy X u T F := + fun _ _ h ↦ iSup₂_mono' fun U U_uni ↦ ⟨U, (le_def.1 h) U U_uni, le_refl _⟩ + +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 coverEntropyInfEnt_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 + +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 + 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) + +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 + 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) + +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 + +@[simp] +lemma coverEntropy_empty {T : X → X} : coverEntropy T ∅ = ⊥ := by + simp only [coverEntropy, coverEntropyEnt_empty, iSup_bot] + +@[simp] +lemma coverEntropyInf_empty {T : X → X} : coverEntropyInf T ∅ = ⊥ := by + simp only [coverEntropyInf, coverEntropyInfEnt_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) + +lemma coverEntropy_nonneg (T : X → X) {F : Set X} (h : F.Nonempty) : + 0 ≤ coverEntropy T F := + (coverEntropyInf_nonneg T h).trans (coverEntropyInf_le_coverEntropy T F) + +lemma coverEntropyInf_eq_coverEntropy (T : X → X) {F : Set X} (h : MapsTo T F 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)) + +end Dynamics diff --git a/Mathlib/FieldTheory/Adjoin.lean b/Mathlib/FieldTheory/Adjoin.lean index bb6ec619c92ea..e83645c2902e6 100644 --- a/Mathlib/FieldTheory/Adjoin.lean +++ b/Mathlib/FieldTheory/Adjoin.lean @@ -4,10 +4,11 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Thomas Browning, Patrick Lutz -/ import Mathlib.Algebra.Algebra.Subalgebra.Directed -import Mathlib.FieldTheory.IntermediateField +import Mathlib.FieldTheory.IntermediateField.Algebraic import Mathlib.FieldTheory.Separable import Mathlib.FieldTheory.SplittingField.IsSplittingField import Mathlib.RingTheory.TensorProduct.Basic +import Mathlib.LinearAlgebra.Dimension.FreeAndStrongRankCondition /-! # Adjoining Elements to Fields @@ -356,12 +357,12 @@ theorem adjoin_adjoin_left (T : Set E) : apply Set.eq_of_subset_of_subset <;> rw [adjoin_subset_adjoin_iff] <;> constructor · rintro _ ⟨⟨x, hx⟩, rfl⟩; exact adjoin.mono _ _ _ Set.subset_union_left hx · exact subset_adjoin_of_subset_right _ _ Set.subset_union_right --- Porting note: orginal proof times out +-- Porting note: original proof times out · rintro x ⟨f, rfl⟩ refine Subfield.subset_closure ?_ left exact ⟨f, rfl⟩ --- Porting note: orginal proof times out +-- Porting note: original proof times out · refine Set.union_subset (fun x hx => Subfield.subset_closure ?_) (fun x hx => Subfield.subset_closure ?_) · left @@ -1069,6 +1070,8 @@ theorem adjoin_minpoly_coeff_of_exists_primitive_element ((g.monic_toSubring _ _).mpr <| (minpoly.monic <| .of_finite K α).map _).ne_zero using 1 rw [natDegree_toSubring, natDegree_map] +instance : Module.Finite F (⊥ : IntermediateField F E) := Subalgebra.finite_bot + variable {F} in /-- If `E / F` is an infinite algebraic extension, then there exists an intermediate field `L / F` with arbitrarily large finite extension degree. -/ diff --git a/Mathlib/FieldTheory/Extension.lean b/Mathlib/FieldTheory/Extension.lean index 4fca6eb496228..abfd3dbf451d7 100644 --- a/Mathlib/FieldTheory/Extension.lean +++ b/Mathlib/FieldTheory/Extension.lean @@ -144,7 +144,7 @@ end variable (hK : ∀ s ∈ S, IsIntegral F s ∧ (minpoly F s).Splits (algebraMap F K)) (hK' : ∀ s : E, IsIntegral F s ∧ (minpoly F s).Splits (algebraMap F K)) - {L : IntermediateField F E} (f : L →ₐ[F] K) (hL : L ≤ adjoin F S) {x : E} {y : K} + {L : IntermediateField F E} (f : L →ₐ[F] K) (hL : L ≤ adjoin F S) {x : E} {y : K} section include hK diff --git a/Mathlib/FieldTheory/Finite/Basic.lean b/Mathlib/FieldTheory/Finite/Basic.lean index dad50e120b86c..a6f4ffff2c1aa 100644 --- a/Mathlib/FieldTheory/Finite/Basic.lean +++ b/Mathlib/FieldTheory/Finite/Basic.lean @@ -145,9 +145,8 @@ theorem sum_subgroup_units_eq_zero [Ring K] [NoZeroDivisors K] have h_sum_map := Finset.univ.sum_map a_mul_emb fun x => ((x : Kˣ) : K) -- ... and the former is the sum of x over G. -- By algebraic manipulation, we have Σ G, x = ∑ G, a x = a ∑ G, x - simp only [a_mul_emb, h_unchanged, Function.Embedding.coeFn_mk, Function.Embedding.toFun_eq_coe, - mulLeftEmbedding_apply, Submonoid.coe_mul, Subgroup.coe_toSubmonoid, Units.val_mul, - ← Finset.mul_sum] at h_sum_map + simp only [h_unchanged, mulLeftEmbedding_apply, Subgroup.coe_mul, Units.val_mul, ← mul_sum, + a_mul_emb] at h_sum_map -- thus one of (a - 1) or ∑ G, x is zero have hzero : (((a : Kˣ) : K) - 1) = 0 ∨ ∑ x : ↥G, ((x : Kˣ) : K) = 0 := by rw [← mul_eq_zero, sub_mul, ← h_sum_map, one_mul, sub_self] @@ -163,8 +162,9 @@ theorem sum_subgroup_units [Ring K] [NoZeroDivisors K] ∑ x : G, (x.val : K) = if G = ⊥ then 1 else 0 := by by_cases G_bot : G = ⊥ · subst G_bot - simp only [ite_true, Subgroup.mem_bot, Fintype.card_ofSubsingleton, Nat.cast_ite, Nat.cast_one, - Nat.cast_zero, univ_unique, Set.default_coe_singleton, sum_singleton, Units.val_one] + simp only [univ_unique, sum_singleton, ↓reduceIte, Units.val_eq_one, OneMemClass.coe_eq_one] + rw [Set.default_coe_singleton] + rfl · simp only [G_bot, ite_false] exact sum_subgroup_units_eq_zero G_bot @@ -184,7 +184,7 @@ theorem sum_subgroup_pow_eq_zero [CommRing K] [NoZeroDivisors K] (fun x : ↥G => (((x : Kˣ) : K) * ((a : Kˣ) : K)) ^ k) = (fun x : ↥G => ((x : Kˣ) : K) ^ k) ∘ fun x : ↥G => x * a := by funext x - simp only [Function.comp_apply, Submonoid.coe_mul, Subgroup.coe_toSubmonoid, Units.val_mul] + simp only [Function.comp_apply, Subgroup.coe_mul, Units.val_mul] rw [as_comp, ← Multiset.map_map] congr rw [eq_comm] diff --git a/Mathlib/FieldTheory/Finite/GaloisField.lean b/Mathlib/FieldTheory/Finite/GaloisField.lean index c2262e4cf2be6..baca752d4d5c6 100644 --- a/Mathlib/FieldTheory/Finite/GaloisField.lean +++ b/Mathlib/FieldTheory/Finite/GaloisField.lean @@ -92,7 +92,7 @@ theorem finrank {n} (h : n ≠ 0) : FiniteDimensional.finrank (ZMod p) (GaloisFi 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 - -- Porting note: in the statment of `key`, replaced `g_poly` by its value otherwise the + -- Porting note: in the statement of `key`, replaced `g_poly` by its value otherwise the -- proof fails have key : Fintype.card (g_poly.rootSet (GaloisField p n)) = g_poly.natDegree := card_rootSet_eq_natDegree (galois_poly_separable p _ (dvd_pow (dvd_refl p) h)) @@ -189,7 +189,7 @@ namespace FiniteField variable {K : Type*} [Field K] [Fintype K] {K' : Type*} [Field K'] [Fintype K'] /-- Uniqueness of finite fields: - Any two finite fields of the same cardinality are (possibly non canonically) isomorphic-/ + Any two finite fields of the same cardinality are (possibly non canonically) isomorphic -/ def algEquivOfCardEq (p : ℕ) [h_prime : Fact p.Prime] [Algebra (ZMod p) K] [Algebra (ZMod p) K'] (hKK' : Fintype.card K = Fintype.card K') : K ≃ₐ[ZMod p] K' := by have : CharP K p := by rw [← Algebra.charP_iff (ZMod p) K p]; exact ZMod.charP p @@ -203,7 +203,7 @@ def algEquivOfCardEq (p : ℕ) [h_prime : Fact p.Prime] [Algebra (ZMod p) K] [Al exact AlgEquiv.trans hGalK hK'Gal /-- Uniqueness of finite fields: - Any two finite fields of the same cardinality are (possibly non canonically) isomorphic-/ + Any two finite fields of the same cardinality are (possibly non canonically) isomorphic -/ def ringEquivOfCardEq (hKK' : Fintype.card K = Fintype.card K') : K ≃+* K' := by choose p _char_p_K using CharP.exists K choose p' _char_p'_K' using CharP.exists K' diff --git a/Mathlib/FieldTheory/Fixed.lean b/Mathlib/FieldTheory/Fixed.lean index 11e8c66077f0c..bf86498f3027a 100644 --- a/Mathlib/FieldTheory/Fixed.lean +++ b/Mathlib/FieldTheory/Fixed.lean @@ -8,7 +8,7 @@ import Mathlib.Algebra.Ring.Action.Field import Mathlib.Algebra.Ring.Action.Invariant import Mathlib.FieldTheory.Normal import Mathlib.FieldTheory.Separable -import Mathlib.FieldTheory.Tower +import Mathlib.LinearAlgebra.FreeModule.Finite.Matrix /-! # Fixed field under a group action. @@ -118,8 +118,8 @@ theorem linearIndependent_smul_of_linearIndependent {s : Finset F} : rw [coe_insert] at hs ⊢ rw [linearIndependent_insert (mt mem_coe.1 has)] at hs rw [linearIndependent_insert' (mt mem_coe.1 has)]; refine ⟨ih hs.1, fun ha => ?_⟩ - rw [Finsupp.mem_span_image_iff_total] at ha; rcases ha with ⟨l, hl, hla⟩ - rw [Finsupp.total_apply_of_mem_supported F hl] at hla + rw [Finsupp.mem_span_image_iff_linearCombination] at ha; rcases ha with ⟨l, hl, hla⟩ + rw [Finsupp.linearCombination_apply_of_mem_supported F hl] at hla suffices ∀ i ∈ s, l i ∈ FixedPoints.subfield G F by replace hla := (sum_apply _ _ fun i => l i • toFun G F i).symm.trans (congr_fun hla 1) simp_rw [Pi.smul_apply, toFun_apply, one_smul] at hla @@ -166,7 +166,8 @@ def minpoly : Polynomial (FixedPoints.subfield G F) := namespace minpoly theorem monic : (minpoly G F x).Monic := by - simp only [minpoly, Polynomial.monic_toSubring] + simp only [minpoly] + rw [Polynomial.monic_toSubring] exact prodXSubSMul.monic G F x theorem eval₂ : diff --git a/Mathlib/FieldTheory/Galois.lean b/Mathlib/FieldTheory/Galois.lean index 97c0878478581..259a8533aa662 100644 --- a/Mathlib/FieldTheory/Galois.lean +++ b/Mathlib/FieldTheory/Galois.lean @@ -380,15 +380,12 @@ theorem of_separable_splitting_field [sp : p.IsSplittingField F E] (hp : p.Separ rw [IntermediateField.adjoin_zero] intro K x hx hK simp only [P] at * - -- Porting note: need to specify two implicit arguments of `finrank_mul_finrank` - letI := K⟮x⟯.module - letI := K⟮x⟯.isScalarTower (R := F) rw [of_separable_splitting_field_aux hp K (Multiset.mem_toFinset.mp hx), hK, finrank_mul_finrank] symm refine LinearEquiv.finrank_eq ?_ rfl -/-- Equivalent characterizations of a Galois extension of finite degree-/ +/-- Equivalent characterizations of a Galois extension of finite degree -/ theorem tfae [FiniteDimensional F E] : List.TFAE [ IsGalois F E, IntermediateField.fixedField (⊤ : Subgroup (E ≃ₐ[F] E)) = ⊥, diff --git a/Mathlib/FieldTheory/IntermediateField/Algebraic.lean b/Mathlib/FieldTheory/IntermediateField/Algebraic.lean new file mode 100644 index 0000000000000..99eab922d6a3d --- /dev/null +++ b/Mathlib/FieldTheory/IntermediateField/Algebraic.lean @@ -0,0 +1,119 @@ +/- +Copyright (c) 2020 Anne Baanen. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Anne Baanen +-/ +import Mathlib.FieldTheory.IntermediateField.Basic +import Mathlib.RingTheory.Algebraic +import Mathlib.FieldTheory.Tower +import Mathlib.FieldTheory.Minpoly.Basic +import Mathlib.LinearAlgebra.FreeModule.StrongRankCondition + +/-! +# Results on finite dimensionality and algebraicity of intermediate fields. +-/ + +open FiniteDimensional + +variable {K : Type*} {L : Type*} [Field K] [Field L] [Algebra K L] + {S : IntermediateField K L} + +namespace IntermediateField + +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 + +@[simp] +theorem rank_eq_rank_subalgebra : Module.rank K F.toSubalgebra = Module.rank K F := + rfl + +@[simp] +theorem finrank_eq_finrank_subalgebra : finrank K F.toSubalgebra = finrank K F := + rfl + +variable {F} {E} + +@[simp] +theorem toSubalgebra_eq_iff : F.toSubalgebra = E.toSubalgebra ↔ F = E := by + rw [SetLike.ext_iff, SetLike.ext'_iff, Set.ext_iff] + rfl + +/-- If `F ≤ E` are two intermediate fields of `L / K` such that `[E : K] ≤ [F : K]` are finite, +then `F = E`. -/ +theorem eq_of_le_of_finrank_le [hfin : FiniteDimensional K E] (h_le : F ≤ E) + (h_finrank : finrank K E ≤ finrank K F) : F = E := + haveI : Module.Finite K E.toSubalgebra := hfin + toSubalgebra_injective <| Subalgebra.eq_of_le_of_finrank_le h_le h_finrank + +/-- If `F ≤ E` are two intermediate fields of `L / K` such that `[F : K] = [E : K]` are finite, +then `F = E`. -/ +theorem eq_of_le_of_finrank_eq [FiniteDimensional K E] (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 + +-- If `F ≤ E` are two intermediate fields of a finite extension `L / K` such that +-- `[L : F] ≤ [L : E]`, then `F = E`. Marked as private since it's a direct corollary of +-- `eq_of_le_of_finrank_le'` (the `FiniteDimensional K L` implies `FiniteDimensional F L` +-- automatically by typeclass resolution). +private theorem eq_of_le_of_finrank_le'' [FiniteDimensional K L] (h_le : F ≤ E) + (h_finrank : finrank F L ≤ finrank E L) : F = E := by + apply eq_of_le_of_finrank_le h_le + have h1 := finrank_mul_finrank K F L + have h2 := finrank_mul_finrank K E L + have h3 : 0 < finrank E L := finrank_pos + nlinarith + +/-- If `F ≤ E` are two intermediate fields of `L / K` such that `[L : F] ≤ [L : E]` are finite, +then `F = E`. -/ +theorem eq_of_le_of_finrank_le' [FiniteDimensional F L] (h_le : F ≤ E) + (h_finrank : finrank F L ≤ finrank E L) : F = E := by + refine le_antisymm h_le (fun l hl ↦ ?_) + rwa [← mem_extendScalars (le_refl F), eq_of_le_of_finrank_le'' + ((extendScalars_le_extendScalars_iff (le_refl F) h_le).2 h_le) h_finrank, mem_extendScalars] + +/-- If `F ≤ E` are two intermediate fields of `L / K` such that `[L : F] = [L : E]` are finite, +then `F = E`. -/ +theorem eq_of_le_of_finrank_eq' [FiniteDimensional F L] (h_le : F ≤ E) + (h_finrank : finrank F L = finrank E L) : F = E := + eq_of_le_of_finrank_le' h_le h_finrank.le + +end FiniteDimensional + +theorem isAlgebraic_iff {x : S} : IsAlgebraic K x ↔ IsAlgebraic K (x : L) := + (isAlgebraic_algebraMap_iff (algebraMap S L).injective).symm + +theorem isIntegral_iff {x : S} : IsIntegral K x ↔ IsIntegral K (x : L) := by + rw [← isAlgebraic_iff_isIntegral, isAlgebraic_iff, isAlgebraic_iff_isIntegral] + +theorem minpoly_eq (x : S) : minpoly K x = minpoly K (x : L) := + (minpoly.algebraMap_eq (algebraMap S L).injective x).symm + +end IntermediateField + +/-- If `L/K` is algebraic, the `K`-subalgebras of `L` are all fields. -/ +def subalgebraEquivIntermediateField [Algebra.IsAlgebraic K L] : + Subalgebra K L ≃o IntermediateField K L where + toFun S := S.toIntermediateField fun x hx => S.inv_mem_of_algebraic + (Algebra.IsAlgebraic.isAlgebraic ((⟨x, hx⟩ : S) : L)) + invFun S := S.toSubalgebra + left_inv _ := toSubalgebra_toIntermediateField _ _ + right_inv := toIntermediateField_toSubalgebra + map_rel_iff' := Iff.rfl + +@[simp] +theorem mem_subalgebraEquivIntermediateField [Algebra.IsAlgebraic K L] {S : Subalgebra K L} + {x : L} : x ∈ subalgebraEquivIntermediateField S ↔ x ∈ S := + Iff.rfl + +@[simp] +theorem mem_subalgebraEquivIntermediateField_symm [Algebra.IsAlgebraic K L] + {S : IntermediateField K L} {x : L} : + x ∈ subalgebraEquivIntermediateField.symm S ↔ x ∈ S := + Iff.rfl diff --git a/Mathlib/FieldTheory/IntermediateField.lean b/Mathlib/FieldTheory/IntermediateField/Basic.lean similarity index 85% rename from Mathlib/FieldTheory/IntermediateField.lean rename to Mathlib/FieldTheory/IntermediateField/Basic.lean index 1f54cb6acfb38..27a9fb8cd57cd 100644 --- a/Mathlib/FieldTheory/IntermediateField.lean +++ b/Mathlib/FieldTheory/IntermediateField/Basic.lean @@ -3,9 +3,10 @@ Copyright (c) 2020 Anne Baanen. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Anne Baanen -/ -import Mathlib.FieldTheory.Tower -import Mathlib.RingTheory.Algebraic -import Mathlib.FieldTheory.Minpoly.Basic +import Mathlib.Algebra.Field.Subfield +import Mathlib.Algebra.Polynomial.AlgebraMap +import Mathlib.RingTheory.LocalRing.Basic +import Mathlib.RingTheory.IntegralClosure.IsIntegral.Defs /-! # Intermediate fields @@ -36,7 +37,7 @@ intermediate field, field extension -/ -open FiniteDimensional Polynomial +open Polynomial open Polynomial @@ -306,29 +307,31 @@ theorem coe_prod {ι : Type*} [Fintype ι] (f : ι → S) : (↑(∏ i, f i) : L /-! `IntermediateField`s inherit structure from their `Subalgebra` coercions. -/ +instance toAlgebra : Algebra S L := + inferInstanceAs (Algebra S.toSubalgebra L) instance module' {R} [Semiring R] [SMul R K] [Module R L] [IsScalarTower R K L] : Module R S := - S.toSubalgebra.module' + inferInstanceAs (Module R S.toSubalgebra) -instance module : Module K S := - inferInstanceAs (Module K S.toSubsemiring) +instance algebra' {R' K L : Type*} [Field K] [Field L] [Algebra K L] (S : IntermediateField K L) + [CommSemiring R'] [SMul R' K] [Algebra R' L] [IsScalarTower R' K L] : Algebra R' S := + inferInstanceAs (Algebra R' S.toSubalgebra) instance isScalarTower {R} [Semiring R] [SMul R K] [Module R L] [IsScalarTower R K L] : IsScalarTower R K S := - inferInstanceAs (IsScalarTower R K S.toSubsemiring) + inferInstanceAs (IsScalarTower R K S.toSubalgebra) @[simp] theorem coe_smul {R} [Semiring R] [SMul R K] [Module R L] [IsScalarTower R K L] (r : R) (x : S) : ↑(r • x : S) = (r • (x : L)) := rfl -instance algebra : Algebra K S := - inferInstanceAs (Algebra K S.toSubsemiring) - @[simp] lemma algebraMap_apply (x : S) : algebraMap S L x = x := rfl @[simp] lemma coe_algebraMap_apply (x : K) : ↑(algebraMap K S x) = algebraMap K L x := rfl +instance {R : Type*} [Semiring R] [Algebra L R] : SMul S R := S.instSMulSubtypeMem + instance isScalarTower_bot {R : Type*} [Semiring R] [Algebra L R] : IsScalarTower S L R := IsScalarTower.subalgebra _ _ _ S.toSubalgebra @@ -340,6 +343,8 @@ instance isScalarTower_mid {R : Type*} [Semiring R] [Algebra L R] [Algebra K R] instance isScalarTower_mid' : IsScalarTower K S L := S.isScalarTower_mid +instance {E} [Semiring E] [Algebra L E] : Algebra S E := inferInstanceAs (Algebra S.toSubalgebra E) + section shortcut_instances variable {E} [Field E] [Algebra L E] (T : IntermediateField S E) {S} instance : Algebra S T := T.algebra @@ -752,100 +757,4 @@ end Restrict end Tower -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 - -@[simp] -theorem rank_eq_rank_subalgebra : Module.rank K F.toSubalgebra = Module.rank K F := - rfl - -@[simp] -theorem finrank_eq_finrank_subalgebra : finrank K F.toSubalgebra = finrank K F := - rfl - -variable {F} {E} - -@[simp] -theorem toSubalgebra_eq_iff : F.toSubalgebra = E.toSubalgebra ↔ F = E := by - rw [SetLike.ext_iff, SetLike.ext'_iff, Set.ext_iff] - rfl - -/-- If `F ≤ E` are two intermediate fields of `L / K` such that `[E : K] ≤ [F : K]` are finite, -then `F = E`. -/ -theorem eq_of_le_of_finrank_le [hfin : FiniteDimensional K E] (h_le : F ≤ E) - (h_finrank : finrank K E ≤ finrank K F) : F = E := - haveI : Module.Finite K E.toSubalgebra := hfin - toSubalgebra_injective <| Subalgebra.eq_of_le_of_finrank_le h_le h_finrank - -/-- If `F ≤ E` are two intermediate fields of `L / K` such that `[F : K] = [E : K]` are finite, -then `F = E`. -/ -theorem eq_of_le_of_finrank_eq [FiniteDimensional K E] (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 - --- If `F ≤ E` are two intermediate fields of a finite extension `L / K` such that --- `[L : F] ≤ [L : E]`, then `F = E`. Marked as private since it's a direct corollary of --- `eq_of_le_of_finrank_le'` (the `FiniteDimensional K L` implies `FiniteDimensional F L` --- automatically by typeclass resolution). -private theorem eq_of_le_of_finrank_le'' [FiniteDimensional K L] (h_le : F ≤ E) - (h_finrank : finrank F L ≤ finrank E L) : F = E := by - apply eq_of_le_of_finrank_le h_le - have h1 := finrank_mul_finrank K F L - have h2 := finrank_mul_finrank K E L - have h3 : 0 < finrank E L := finrank_pos - nlinarith - -/-- If `F ≤ E` are two intermediate fields of `L / K` such that `[L : F] ≤ [L : E]` are finite, -then `F = E`. -/ -theorem eq_of_le_of_finrank_le' [FiniteDimensional F L] (h_le : F ≤ E) - (h_finrank : finrank F L ≤ finrank E L) : F = E := by - refine le_antisymm h_le (fun l hl ↦ ?_) - rwa [← mem_extendScalars (le_refl F), eq_of_le_of_finrank_le'' - ((extendScalars_le_extendScalars_iff (le_refl F) h_le).2 h_le) h_finrank, mem_extendScalars] - -/-- If `F ≤ E` are two intermediate fields of `L / K` such that `[L : F] = [L : E]` are finite, -then `F = E`. -/ -theorem eq_of_le_of_finrank_eq' [FiniteDimensional F L] (h_le : F ≤ E) - (h_finrank : finrank F L = finrank E L) : F = E := - eq_of_le_of_finrank_le' h_le h_finrank.le - -end FiniteDimensional - -theorem isAlgebraic_iff {x : S} : IsAlgebraic K x ↔ IsAlgebraic K (x : L) := - (isAlgebraic_algebraMap_iff (algebraMap S L).injective).symm - -theorem isIntegral_iff {x : S} : IsIntegral K x ↔ IsIntegral K (x : L) := by - rw [← isAlgebraic_iff_isIntegral, isAlgebraic_iff, isAlgebraic_iff_isIntegral] - -theorem minpoly_eq (x : S) : minpoly K x = minpoly K (x : L) := - (minpoly.algebraMap_eq (algebraMap S L).injective x).symm - end IntermediateField - -/-- If `L/K` is algebraic, the `K`-subalgebras of `L` are all fields. -/ -def subalgebraEquivIntermediateField [Algebra.IsAlgebraic K L] : - Subalgebra K L ≃o IntermediateField K L where - toFun S := S.toIntermediateField fun x hx => S.inv_mem_of_algebraic - (Algebra.IsAlgebraic.isAlgebraic ((⟨x, hx⟩ : S) : L)) - invFun S := S.toSubalgebra - left_inv _ := toSubalgebra_toIntermediateField _ _ - right_inv := toIntermediateField_toSubalgebra - map_rel_iff' := Iff.rfl - -@[simp] -theorem mem_subalgebraEquivIntermediateField [Algebra.IsAlgebraic K L] {S : Subalgebra K L} - {x : L} : x ∈ subalgebraEquivIntermediateField S ↔ x ∈ S := - Iff.rfl - -@[simp] -theorem mem_subalgebraEquivIntermediateField_symm [Algebra.IsAlgebraic K L] - {S : IntermediateField K L} {x : L} : - x ∈ subalgebraEquivIntermediateField.symm S ↔ x ∈ S := - Iff.rfl diff --git a/Mathlib/FieldTheory/IsAlgClosed/AlgebraicClosure.lean b/Mathlib/FieldTheory/IsAlgClosed/AlgebraicClosure.lean index bef0b0e2de8f4..27b94d1b6a535 100644 --- a/Mathlib/FieldTheory/IsAlgClosed/AlgebraicClosure.lean +++ b/Mathlib/FieldTheory/IsAlgClosed/AlgebraicClosure.lean @@ -73,10 +73,10 @@ theorem toSplittingField_evalXSelf {s : Finset (MonicIrreducible k)} {f} (hf : f theorem spanEval_ne_top : spanEval k ≠ ⊤ := by rw [Ideal.ne_top_iff_one, spanEval, Ideal.span, ← Set.image_univ, - Finsupp.mem_span_image_iff_total] + Finsupp.mem_span_image_iff_linearCombination] rintro ⟨v, _, hv⟩ replace hv := congr_arg (toSplittingField k v.support) hv - rw [map_one, Finsupp.total_apply, Finsupp.sum, map_sum, Finset.sum_eq_zero] at hv + 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, diff --git a/Mathlib/FieldTheory/KummerExtension.lean b/Mathlib/FieldTheory/KummerExtension.lean index 6b3c4cdc76d6e..65eb3d88e45c4 100644 --- a/Mathlib/FieldTheory/KummerExtension.lean +++ b/Mathlib/FieldTheory/KummerExtension.lean @@ -197,7 +197,7 @@ theorem X_pow_sub_C_irreducible_of_odd {n : ℕ} (hn : Odd n) {a : K} (ha : ∀ p : ℕ, p.Prime → p ∣ n → ∀ b : K, b ^ p ≠ a) : Irreducible (X ^ n - C a) := by induction n using induction_on_primes generalizing K a with - | h₀ => simp at hn + | h₀ => simp [← Nat.not_even_iff_odd] at hn | h₁ => simpa using irreducible_X_sub_C a | h p n hp IH => rw [mul_comm] @@ -412,8 +412,8 @@ variable {α : L} (hα : α ^ n = algebraMap K L a) /-- Suppose `L/K` is the splitting field of `Xⁿ - a`, then a choice of `ⁿ√a` gives an equivalence of `L` with `K[n√a]`. -/ noncomputable -def adjoinRootXPowSubCEquiv : - K[n√a] ≃ₐ[K] L := +def adjoinRootXPowSubCEquiv (hζ : (primitiveRoots n K).Nonempty) (H : Irreducible (X ^ n - C a)) + (hα : α ^ n = algebraMap K L a) : K[n√a] ≃ₐ[K] L := AlgEquiv.ofBijective (AdjoinRoot.liftHom (X ^ n - C a) α (by simp [hα])) <| by haveI := Fact.mk H letI := isSplittingField_AdjoinRoot_X_pow_sub_C hζ H @@ -450,7 +450,8 @@ variable (a) (L) /-- An arbitrary choice of `ⁿ√a` in the splitting field of `Xⁿ - a`. -/ noncomputable -abbrev rootOfSplitsXPowSubC : L := +abbrev rootOfSplitsXPowSubC (hn : 0 < n) (a : K) + (L) [Field L] [Algebra K L] [IsSplittingField K L (X ^ n - C a)] : L := (rootOfSplits _ (IsSplittingField.splits L (X ^ n - C a)) (by simpa [degree_X_pow_sub_C hn] using Nat.pos_iff_ne_zero.mp hn)) diff --git a/Mathlib/FieldTheory/Minpoly/MinpolyDiv.lean b/Mathlib/FieldTheory/Minpoly/MinpolyDiv.lean index 317ae7f335968..c327e135c3ddd 100644 --- a/Mathlib/FieldTheory/Minpoly/MinpolyDiv.lean +++ b/Mathlib/FieldTheory/Minpoly/MinpolyDiv.lean @@ -164,8 +164,8 @@ lemma span_coeff_minpolyDiv : Submodule.span_le] simp only [Finset.coe_image, Finset.coe_range, Set.image_subset_iff] intro i - apply Nat.strongInductionOn i - intro i hi hi' + induction i using Nat.strongRecOn with | ind i hi => ?_ + intro hi' have : coeff (minpolyDiv R x) (natDegree (minpolyDiv R x) - i) ∈ Submodule.span R (Set.range (coeff (minpolyDiv R x))) := Submodule.subset_span (Set.mem_range_self _) diff --git a/Mathlib/FieldTheory/Normal.lean b/Mathlib/FieldTheory/Normal.lean index 0b609f7d4d2a1..98ae051a5fd57 100644 --- a/Mathlib/FieldTheory/Normal.lean +++ b/Mathlib/FieldTheory/Normal.lean @@ -174,6 +174,26 @@ instance normal_sup Normal F (E ⊔ E' : IntermediateField F K) := iSup_bool_eq (f := Bool.rec E' E) ▸ normal_iSup (h := by rintro (_|_) <;> infer_instance) +/-- An intersection of normal extensions is normal -/ +instance normal_iInf {ι : Type*} [hι : Nonempty ι] + (t : ι → IntermediateField F K) [h : ∀ i, Normal F (t i)] : + Normal F (⨅ i, t i : IntermediateField F K) := by + refine { toIsAlgebraic := ?_, splits' := fun x => ?_ } + · let f := inclusion (iInf_le t hι.some) + exact Algebra.IsAlgebraic.of_injective f f.injective + · have hx : ∀ i, Splits (algebraMap F (t i)) (minpoly F x) := by + intro i + rw [← minpoly.algHom_eq (inclusion (iInf_le t i)) (inclusion (iInf_le t i)).injective] + exact (h i).splits' (inclusion (iInf_le t i) x) + simp only [splits_iff_mem (splits_of_isScalarTower K (hx hι.some))] at hx ⊢ + rintro y hy - ⟨-, ⟨i, rfl⟩, rfl⟩ + exact hx i y hy + +instance normal_inf + (E E' : IntermediateField F K) [Normal F E] [Normal F E'] : + Normal F (E ⊓ E' : IntermediateField F K) := + iInf_bool_eq (f := Bool.rec E' E) ▸ normal_iInf (h := by rintro (_|_) <;> infer_instance) + variable {F K} variable {L : Type*} [Field L] [Algebra F L] [Algebra K L] [IsScalarTower F K L] diff --git a/Mathlib/FieldTheory/NormalClosure.lean b/Mathlib/FieldTheory/NormalClosure.lean index a1d7bf881f7dd..680dc94bf8709 100644 --- a/Mathlib/FieldTheory/NormalClosure.lean +++ b/Mathlib/FieldTheory/NormalClosure.lean @@ -6,6 +6,7 @@ Authors: Thomas Browning import Mathlib.FieldTheory.Normal import Mathlib.Order.Closure +import Mathlib.LinearAlgebra.FreeModule.Finite.Matrix /-! # Normal closures @@ -98,8 +99,8 @@ lemma isNormalClosure_normalClosure : IsNormalClosure F K (normalClosure F K L) SetLike.coe_subset_coe.mpr <| by apply le_iSup _ x) simp_rw [normalClosure, ← top_le_iff] refine fun x _ ↦ (IntermediateField.val _).injective.mem_set_image.mp ?_ - change x.val ∈ IntermediateField.map (IntermediateField.val _) _ - rw [IntermediateField.map_iSup] + rw [AlgHom.toRingHom_eq_coe, RingHom.coe_coe, coe_val, ← IntermediateField.coe_val, + ← IntermediateField.coe_map, IntermediateField.map_iSup] refine (iSup_le fun f ↦ ?_ : normalClosure F K L ≤ _) x.2 refine le_iSup_of_le (f.codRestrict _ fun x ↦ f.fieldRange_le_normalClosure ⟨x, rfl⟩) ?_ rw [AlgHom.map_fieldRange, val, AlgHom.val_comp_codRestrict] @@ -173,7 +174,7 @@ variable [Algebra K L] [IsScalarTower F K L] noncomputable instance algebra : Algebra K (normalClosure F K L) := - IntermediateField.algebra + IntermediateField.algebra' { ⨆ f : K →ₐ[F] L, f.fieldRange with algebraMap_mem' := fun r ↦ (toAlgHom F K L).fieldRange_le_normalClosure ⟨r, rfl⟩ } diff --git a/Mathlib/FieldTheory/Perfect.lean b/Mathlib/FieldTheory/Perfect.lean index f0725115ada01..6e4aecef5c66e 100644 --- a/Mathlib/FieldTheory/Perfect.lean +++ b/Mathlib/FieldTheory/Perfect.lean @@ -376,7 +376,7 @@ variable [PerfectRing R p] a bijection from the set of roots of `Polynomial.expand R p f` to the set of roots of `f`. It's given by `x ↦ x ^ p`, see `rootsExpandEquivRoots_apply`. -/ noncomputable def rootsExpandEquivRoots : (expand R p f).roots.toFinset ≃ f.roots.toFinset := - ((frobeniusEquiv R p).image _).trans <| .Set.ofEq <| show _ '' (setOf _) = setOf _ by + ((frobeniusEquiv R p).image _).trans <| .Set.ofEq <| show _ '' setOf (· ∈ _) = setOf (· ∈ _) by classical simp_rw [← roots_expand_image_frobenius (p := p) (f := f), Finset.mem_val, Finset.setOf_mem, Finset.coe_image, RingEquiv.toEquiv_eq_coe, EquivLike.coe_coe, frobeniusEquiv_apply] @@ -389,7 +389,8 @@ a bijection from the set of roots of `Polynomial.expand R (p ^ n) f` to the set It's given by `x ↦ x ^ (p ^ n)`, see `rootsExpandPowEquivRoots_apply`. -/ noncomputable def rootsExpandPowEquivRoots (n : ℕ) : (expand R (p ^ n) f).roots.toFinset ≃ f.roots.toFinset := - ((iterateFrobeniusEquiv R p n).image _).trans <| .Set.ofEq <| show _ '' (setOf _) = setOf _ by + ((iterateFrobeniusEquiv R p n).image _).trans <| + .Set.ofEq <| show _ '' (setOf (· ∈ _)) = setOf (· ∈ _) by classical simp_rw [← roots_expand_image_iterateFrobenius (p := p) (f := f) (n := n), Finset.mem_val, Finset.setOf_mem, Finset.coe_image, RingEquiv.toEquiv_eq_coe, EquivLike.coe_coe, iterateFrobeniusEquiv_apply] diff --git a/Mathlib/FieldTheory/PerfectClosure.lean b/Mathlib/FieldTheory/PerfectClosure.lean index 924955c214e97..df62d0fc00813 100644 --- a/Mathlib/FieldTheory/PerfectClosure.lean +++ b/Mathlib/FieldTheory/PerfectClosure.lean @@ -224,12 +224,17 @@ instance instZero : Zero (PerfectClosure K p) := theorem zero_def : (0 : PerfectClosure K p) = mk K p (0, 0) := rfl +/-- Prior to #15862, this lemma was called `mk_zero_zero`. +See `mk_zero_right` for the lemma used to be called `mk_zero`. -/ @[simp] -theorem mk_zero_zero : mk K p (0, 0) = 0 := +theorem mk_zero : mk K p 0 = 0 := rfl +@[deprecated (since := "2024-08-16")] alias mk_zero_zero := mk_zero + -- Porting note: improved proof structure -theorem mk_zero (n : ℕ) : mk K p (n, 0) = 0 := by +@[simp] +theorem mk_zero_right (n : ℕ) : mk K p (n, 0) = 0 := by induction' n with n ih · rfl rw [← ih] @@ -270,7 +275,7 @@ instance instAddCommGroup : AddCommGroup (PerfectClosure K p) := sub_eq_add_neg := fun a b => rfl neg_add_cancel := fun e => Quot.inductionOn e fun ⟨n, x⟩ => by - simp only [quot_mk_eq_mk, neg_mk, mk_add_mk, iterate_map_neg, neg_add_cancel, mk_zero] + simp only [quot_mk_eq_mk, neg_mk, mk_add_mk, iterate_map_neg, neg_add_cancel, mk_zero_right] add_comm := fun e f => Quot.inductionOn e fun ⟨m, x⟩ => Quot.inductionOn f fun ⟨n, y⟩ => congr_arg (Quot.mk _) <| by simp only [add_comm] @@ -284,11 +289,11 @@ instance instCommRing : CommRing (PerfectClosure K p) := zero_mul := fun a => by refine Quot.inductionOn a fun ⟨m, x⟩ => ?_ rw [zero_def, quot_mk_eq_mk, mk_mul_mk] - simp only [zero_add, iterate_zero, id_eq, iterate_map_zero, zero_mul, mk_zero] + simp only [zero_add, iterate_zero, id_eq, iterate_map_zero, zero_mul, mk_zero_right] mul_zero := fun a => by refine Quot.inductionOn a fun ⟨m, x⟩ => ?_ rw [zero_def, quot_mk_eq_mk, mk_mul_mk] - simp only [zero_add, iterate_zero, id_eq, iterate_map_zero, mul_zero, mk_zero] + simp only [zero_add, iterate_zero, id_eq, iterate_map_zero, mul_zero, mk_zero_right] left_distrib := fun e f g => Quot.inductionOn e fun ⟨m, x⟩ => Quot.inductionOn f fun ⟨n, y⟩ => @@ -312,7 +317,7 @@ theorem mk_eq_iff (x y : ℕ × K) : mk K p x = mk K p y ↔ ∃ z, (frobenius K p)^[y.1 + z] x.2 = (frobenius K p)^[x.1 + z] y.2 := by constructor · intro H - replace H := Quot.exact _ H + replace H := Quot.eqvGen_exact H induction H with | rel x y H => cases' H with n x; exact ⟨0, rfl⟩ | refl H => exact ⟨0, rfl⟩ @@ -491,7 +496,9 @@ instance instDivisionRing : DivisionRing (PerfectClosure K p) where rw [mul_inv_cancel₀ this, iterate_map_one] inv_zero := congr_arg (Quot.mk (R K p)) (by rw [inv_zero]) nnqsmul := _ + nnqsmul_def := fun q a => rfl qsmul := _ + qsmul_def := fun q a => rfl instance instField : Field (PerfectClosure K p) := { (inferInstance : DivisionRing (PerfectClosure K p)), diff --git a/Mathlib/FieldTheory/PolynomialGaloisGroup.lean b/Mathlib/FieldTheory/PolynomialGaloisGroup.lean index 3c936d1dc75f4..159fca2636398 100644 --- a/Mathlib/FieldTheory/PolynomialGaloisGroup.lean +++ b/Mathlib/FieldTheory/PolynomialGaloisGroup.lean @@ -253,7 +253,7 @@ theorem restrictDvd_surjective (hpq : p ∣ q) (hq : q ≠ 0) : variable (p q) -/-- The Galois group of a product maps into the product of the Galois groups. -/ +/-- The Galois group of a product maps into the product of the Galois groups. -/ def restrictProd : (p * q).Gal →* p.Gal × q.Gal := MonoidHom.prod (restrictDvd (dvd_mul_right p q)) (restrictDvd (dvd_mul_left q p)) diff --git a/Mathlib/FieldTheory/PurelyInseparable.lean b/Mathlib/FieldTheory/PurelyInseparable.lean index a2d8f90ef45d9..a4608eb8e72f9 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 +open FiniteDimensional Polynomial IntermediateField Field Finsupp noncomputable section @@ -282,7 +282,7 @@ theorem mem_perfectClosure_iff_pow_mem (q : ℕ) [ExpChar F q] {x : E} : x ∈ perfectClosure F E ↔ ∃ n : ℕ, x ^ q ^ n ∈ (algebraMap F E).range := by rw [mem_perfectClosure_iff, ringExpChar.eq F q] -/-- An element is contained in the relative perfect closure if and only if its mininal polynomial +/-- An element is contained in the relative perfect closure if and only if its minimal polynomial has separable degree one. -/ theorem mem_perfectClosure_iff_natSepDegree_eq_one {x : E} : x ∈ perfectClosure F E ↔ (minpoly F x).natSepDegree = 1 := by @@ -629,7 +629,7 @@ namespace IntermediateField instance isPurelyInseparable_bot : IsPurelyInseparable F (⊥ : IntermediateField F E) := (botEquiv F E).symm.isPurelyInseparable -/-- `F⟮x⟯ / F` is a purely inseparable extension if and only if the mininal polynomial of `x` +/-- `F⟮x⟯ / F` is a purely inseparable extension if and only if the minimal polynomial of `x` has separable degree one. -/ theorem isPurelyInseparable_adjoin_simple_iff_natSepDegree_eq_one {x : E} : IsPurelyInseparable F F⟮x⟯ ↔ (minpoly F x).natSepDegree = 1 := by @@ -741,7 +741,8 @@ private theorem LinearIndependent.map_pow_expChar_pow_of_fd_isSeparable (finrank_eq_card_basis b).symm let f (i : ι) : ι' := ⟨v i, h'.subset_extend _ ⟨i, rfl⟩⟩ convert H.comp f fun _ _ heq ↦ h.injective (by simpa only [f, Subtype.mk.injEq] using heq) - simp_rw [Function.comp_apply, b, Basis.extend_apply_self] + simp_rw [Function.comp_apply, b] + rw [Basis.extend_apply_self] /-- If `E / F` is a separable extension of exponential characteristic `q`, if `{ u_i }` is a family of elements of `E` which is `F`-linearly independent, then `{ u_i ^ (q ^ n) }` is also @@ -920,8 +921,8 @@ theorem LinearIndependent.map_of_isPurelyInseparable_of_isSeparable [IsPurelyIns rw [hlF, Finsupp.not_mem_support_iff.1 hs, zero_pow this] replace h := linearIndependent_iff.1 (h.map_pow_expChar_pow_of_isIntegral' q n hsep) lF₀ <| by replace hl := congr($hl ^ q ^ n) - rw [Finsupp.total_apply, Finsupp.sum, sum_pow_char_pow, zero_pow this] at hl - rw [← hl, Finsupp.total_apply, Finsupp.onFinset_sum _ (fun _ ↦ by exact zero_smul _ _)] + rw [linearCombination_apply, Finsupp.sum, sum_pow_char_pow, zero_pow this] at hl + rw [← hl, linearCombination_apply, onFinset_sum _ (fun _ ↦ by exact zero_smul _ _)] refine Finset.sum_congr rfl fun i _ ↦ ?_ simp_rw [Algebra.smul_def, mul_pow, IsScalarTower.algebraMap_apply F E K, hlF, map_pow] refine pow_eq_zero ((hlF _).symm.trans ?_) diff --git a/Mathlib/FieldTheory/RatFunc/Basic.lean b/Mathlib/FieldTheory/RatFunc/Basic.lean index 323ae1661d472..abc89f3acb54f 100644 --- a/Mathlib/FieldTheory/RatFunc/Basic.lean +++ b/Mathlib/FieldTheory/RatFunc/Basic.lean @@ -522,7 +522,9 @@ instance instField [IsDomain K] : Field (RatFunc K) where mul_inv_cancel _ := mul_inv_cancel zpow := zpowRec nnqsmul := _ + nnqsmul_def := fun q a => rfl qsmul := _ + qsmul_def := fun q a => rfl section IsFractionRing diff --git a/Mathlib/FieldTheory/RatFunc/Defs.lean b/Mathlib/FieldTheory/RatFunc/Defs.lean index b1ffa6109ae6d..b45d1838b3eb7 100644 --- a/Mathlib/FieldTheory/RatFunc/Defs.lean +++ b/Mathlib/FieldTheory/RatFunc/Defs.lean @@ -63,7 +63,7 @@ the maps between `RatFunc K` and another field of fractions of `K[X]`, especially `FractionRing K[X]`, are given by `IsLocalization.algEquiv`. -/ structure RatFunc [CommRing K] : Type u where ofFractionRing :: -/-- the coercion to the fraction ring of the polynomial ring-/ +/-- the coercion to the fraction ring of the polynomial ring -/ toFractionRing : FractionRing K[X] namespace RatFunc diff --git a/Mathlib/FieldTheory/SplittingField/IsSplittingField.lean b/Mathlib/FieldTheory/SplittingField/IsSplittingField.lean index 4ca9cadac0e55..79a96d25426a0 100644 --- a/Mathlib/FieldTheory/SplittingField/IsSplittingField.lean +++ b/Mathlib/FieldTheory/SplittingField/IsSplittingField.lean @@ -3,8 +3,8 @@ Copyright (c) 2018 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes -/ -import Mathlib.FieldTheory.IntermediateField import Mathlib.RingTheory.Adjoin.Field +import Mathlib.FieldTheory.IntermediateField.Basic /-! # Splitting fields @@ -150,6 +150,13 @@ theorem IntermediateField.splits_of_splits (h : p.Splits (algebraMap K L)) simp_rw [← F.fieldRange_val, rootSet_def, Finset.mem_coe, Multiset.mem_toFinset] at hF exact splits_of_comp _ F.val.toRingHom h hF +theorem IntermediateField.splits_iff_mem (h : p.Splits (algebraMap K L)) : + p.Splits (algebraMap K F) ↔ ∀ x ∈ p.rootSet L, x ∈ F := by + refine ⟨?_, IntermediateField.splits_of_splits h⟩ + intro hF + rw [← Polynomial.image_rootSet hF F.val, Set.forall_mem_image] + exact fun x _ ↦ x.2 + theorem IsIntegral.mem_intermediateField_of_minpoly_splits {x : L} (int : IsIntegral K x) {F : IntermediateField K L} (h : Splits (algebraMap K F) (minpoly K x)) : x ∈ F := by rw [← F.fieldRange_val]; exact int.mem_range_algebraMap_of_minpoly_splits h diff --git a/Mathlib/FieldTheory/Tower.lean b/Mathlib/FieldTheory/Tower.lean index 160ecd9442513..4a4720b3cb6aa 100644 --- a/Mathlib/FieldTheory/Tower.lean +++ b/Mathlib/FieldTheory/Tower.lean @@ -3,27 +3,19 @@ Copyright (c) 2020 Kenny Lau. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kenny Lau -/ -import Mathlib.Data.Nat.Prime.Defs import Mathlib.RingTheory.AlgebraTower -import Mathlib.LinearAlgebra.FiniteDimensional.Defs -import Mathlib.LinearAlgebra.FreeModule.Finite.Matrix -import Mathlib.RingTheory.LocalRing.Basic +import Mathlib.RingTheory.Noetherian /-! -# Tower of field extensions +# Finiteness of `IsScalarTower` -In this file we prove the tower law for arbitrary extensions and finite extensions. -Suppose `L` is a field extension of `K` and `K` is a field extension of `F`. -Then `[L:F] = [L:K] [K:F]` where `[E₁:E₂]` means the `E₂`-dimension of `E₁`. +We prove that given `IsScalarTower F K A`, if `A` is finite as a module over `F` then +`A` is finite over `K`, and +(as long as `A` is Noetherian over `F` and we have `NoZeroSMulDivisors K A`) `K` is finite over `F`. -In fact we generalize it to rings and modules, where `L` is not necessarily a field, -but just a free module over `K`. +In particular these conditions hold when `A`, `F`, and `K` are fields. -## Implementation notes - -We prove two versions, since there are two notions of dimensions: `Module.rank` which gives -the dimension of an arbitrary vector space as a cardinal, and `FiniteDimensional.finrank` which -gives the dimension of a finite-dimensional vector space as a natural number. +The formulas for the dimensions are given elsewhere by `FiniteDimensional.finrank_mul_finrank`. ## Tags @@ -38,49 +30,31 @@ open Cardinal Submodule variable (F : Type u) (K : Type v) (A : Type w) -section Field - -variable [DivisionRing F] [DivisionRing K] [AddCommGroup A] -variable [Module F K] [Module K A] [Module F A] [IsScalarTower F K A] - -namespace FiniteDimensional - -open IsNoetherian +namespace Module.Finite +variable [Ring F] [Ring K] [Module F K] + [AddCommGroup A] [Module K A] [NoZeroSMulDivisors K A] + [Module F A] [IsNoetherian F A] [IsScalarTower F K A] in /-- In a tower of field extensions `A / K / F`, if `A / F` is finite, so is `K / F`. (In fact, it suffices that `A` is a nontrivial ring.) Note this cannot be an instance as Lean cannot infer `A`. -/ -theorem left [Nontrivial A] [FiniteDimensional F A] : FiniteDimensional F K := +theorem left [Nontrivial A] : Module.Finite F K := let ⟨x, hx⟩ := exists_ne (0 : A) - FiniteDimensional.of_injective + Module.Finite.of_injective (LinearMap.ringLmapEquivSelf K ℕ A |>.symm x |>.restrictScalars F) (smul_left_injective K hx) -theorem right [hf : FiniteDimensional F A] : FiniteDimensional K A := +variable [Semiring F] [Semiring K] [Module F K] + [AddCommMonoid A] [Module K A] [Module F A] [IsScalarTower F K A] in +theorem right [hf : Module.Finite F A] : Module.Finite K A := let ⟨⟨b, hb⟩⟩ := hf ⟨⟨b, Submodule.restrictScalars_injective F _ _ <| by rw [Submodule.restrictScalars_top, eq_top_iff, ← hb, Submodule.span_le] exact Submodule.subset_span⟩⟩ -theorem Subalgebra.isSimpleOrder_of_finrank_prime (F A) [Field F] [Ring A] [IsDomain A] - [Algebra F A] (hp : (finrank F A).Prime) : IsSimpleOrder (Subalgebra F A) := - { toNontrivial := - ⟨⟨⊥, ⊤, fun he => - Nat.not_prime_one ((Subalgebra.bot_eq_top_iff_finrank_eq_one.1 he).subst hp)⟩⟩ - eq_bot_or_eq_top := fun K => by - haveI : FiniteDimensional _ _ := .of_finrank_pos hp.pos - letI := divisionRingOfFiniteDimensional F K - refine (hp.eq_one_or_self_of_dvd _ ⟨_, (finrank_mul_finrank F K A).symm⟩).imp ?_ fun h => ?_ - · exact fun h' => Subalgebra.eq_bot_of_finrank_one h' - · exact - Algebra.toSubmodule_eq_top.1 (eq_top_of_finrank_eq <| K.finrank_toSubmodule.trans h) } --- TODO: `IntermediateField` version - -@[deprecated (since := "2024-01-12")] -alias finrank_linear_map' := FiniteDimensional.finrank_linearMap_self - -end FiniteDimensional - -end Field +end Module.Finite + +alias FiniteDimensional.left := Module.Finite.left +alias FiniteDimensional.right := Module.Finite.right diff --git a/Mathlib/Geometry/Euclidean/Angle/Oriented/Basic.lean b/Mathlib/Geometry/Euclidean/Angle/Oriented/Basic.lean index eb15d01c7e2d7..fb641332e085a 100644 --- a/Mathlib/Geometry/Euclidean/Angle/Oriented/Basic.lean +++ b/Mathlib/Geometry/Euclidean/Angle/Oriented/Basic.lean @@ -758,7 +758,7 @@ theorem oangle_smul_add_right_eq_zero_or_eq_pi_iff {x y : V} (r : ℝ) : o.oangle x (r • x + y) = 0 ∨ o.oangle x (r • x + y) = π ↔ o.oangle x y = 0 ∨ o.oangle x y = π := by simp_rw [oangle_eq_zero_or_eq_pi_iff_not_linearIndependent, Fintype.not_linearIndependent_iff] - -- Porting note: at this point all occurences of the bound variable `i` are of type + -- Porting note: at this point all occurrences of the bound variable `i` are of type -- `Fin (Nat.succ (Nat.succ 0))`, but `Fin.sum_univ_two` and `Fin.exists_fin_two` expect it to be -- `Fin 2` instead. Hence all the `conv`s. -- Was `simp_rw [Fin.sum_univ_two, Fin.exists_fin_two]` diff --git a/Mathlib/Geometry/Euclidean/Circumcenter.lean b/Mathlib/Geometry/Euclidean/Circumcenter.lean index 6ab81a7fe36a9..137f90c80106a 100644 --- a/Mathlib/Geometry/Euclidean/Circumcenter.lean +++ b/Mathlib/Geometry/Euclidean/Circumcenter.lean @@ -427,7 +427,7 @@ theorem dist_circumcenter_sq_eq_sq_sub_circumradius {n : ℕ} {r : ℝ} (s : Sim /-- If there exists a distance that a point has from all vertices of a simplex, the orthogonal projection of that point onto the subspace -spanned by that simplex is its circumcenter. -/ +spanned by that simplex is its circumcenter. -/ theorem orthogonalProjection_eq_circumcenter_of_exists_dist_eq {n : ℕ} (s : Simplex ℝ P n) {p : P} (hr : ∃ r, ∀ i, dist (s.points i) p = r) : ↑(s.orthogonalProjectionSpan p) = s.circumcenter := by @@ -445,7 +445,7 @@ theorem orthogonalProjection_eq_circumcenter_of_exists_dist_eq {n : ℕ} (s : Si /-- If a point has the same distance from all vertices of a simplex, the orthogonal projection of that point onto the subspace spanned by -that simplex is its circumcenter. -/ +that simplex is its circumcenter. -/ theorem orthogonalProjection_eq_circumcenter_of_dist_eq {n : ℕ} (s : Simplex ℝ P n) {p : P} {r : ℝ} (hr : ∀ i, dist (s.points i) p = r) : ↑(s.orthogonalProjectionSpan p) = s.circumcenter := s.orthogonalProjection_eq_circumcenter_of_exists_dist_eq ⟨r, hr⟩ diff --git a/Mathlib/Geometry/Euclidean/Sphere/Basic.lean b/Mathlib/Geometry/Euclidean/Sphere/Basic.lean index 0b37ec458a9f3..20d5711b81e4d 100644 --- a/Mathlib/Geometry/Euclidean/Sphere/Basic.lean +++ b/Mathlib/Geometry/Euclidean/Sphere/Basic.lean @@ -57,7 +57,7 @@ instance : Coe (Sphere P) (Set P) := ⟨fun s => Metric.sphere s.center s.radius⟩ instance : Membership P (Sphere P) := - ⟨fun p s => p ∈ (s : Set P)⟩ + ⟨fun s p => p ∈ (s : Set P)⟩ theorem Sphere.mk_center (c : P) (r : ℝ) : (⟨c, r⟩ : Sphere P).center = c := rfl diff --git a/Mathlib/Geometry/Manifold/Algebra/LeftInvariantDerivation.lean b/Mathlib/Geometry/Manifold/Algebra/LeftInvariantDerivation.lean index b624c050ba3ce..5e70b3f083574 100644 --- a/Mathlib/Geometry/Manifold/Algebra/LeftInvariantDerivation.lean +++ b/Mathlib/Geometry/Manifold/Algebra/LeftInvariantDerivation.lean @@ -207,7 +207,7 @@ theorem evalAt_mul : evalAt (g * h) X = 𝒅ₕ (L_apply I g h) (evalAt h X) := ext f rw [← left_invariant, apply_hfdifferential, apply_hfdifferential, L_mul, fdifferential_comp, apply_fdifferential] - -- Porting note: more agressive here + -- Porting note: more aggressive here erw [LinearMap.comp_apply] -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644 erw [apply_fdifferential, ← apply_hfdifferential, left_invariant] diff --git a/Mathlib/Geometry/Manifold/Algebra/LieGroup.lean b/Mathlib/Geometry/Manifold/Algebra/LieGroup.lean index 47d6a6e3e4f01..8bec2b7fa5b4f 100644 --- a/Mathlib/Geometry/Manifold/Algebra/LieGroup.lean +++ b/Mathlib/Geometry/Manifold/Algebra/LieGroup.lean @@ -41,7 +41,7 @@ groups here are not necessarily finite dimensional. A priori, a Lie group here is a manifold with corners. The definition of Lie group cannot require `I : ModelWithCorners 𝕜 E E` with the same space as the -model space and as the model vector space, as one might hope, beause in the product situation, +model space and as the model vector space, as one might hope, because in the product situation, the model space is `ModelProd E E'` and the model vector space is `E × E'`, which are not the same, so the definition does not apply. Hence the definition should be more general, allowing `I : ModelWithCorners 𝕜 E H`. diff --git a/Mathlib/Geometry/Manifold/Algebra/SmoothFunctions.lean b/Mathlib/Geometry/Manifold/Algebra/SmoothFunctions.lean index 594cfdfdde353..067e86f792acd 100644 --- a/Mathlib/Geometry/Manifold/Algebra/SmoothFunctions.lean +++ b/Mathlib/Geometry/Manifold/Algebra/SmoothFunctions.lean @@ -159,7 +159,7 @@ end GroupStructure section RingStructure /-! -### Ring stucture +### Ring structure In this section we show that smooth functions valued in a smooth ring `R` inherit a ring structure under pointwise multiplication. @@ -223,7 +223,7 @@ end RingStructure section ModuleStructure /-! -### Semimodule stucture +### Semimodule structure In this section we show that smooth functions valued in a vector space `M` over a normed field `𝕜` inherit a vector space structure. diff --git a/Mathlib/Geometry/Manifold/AnalyticManifold.lean b/Mathlib/Geometry/Manifold/AnalyticManifold.lean index 86f101cc015ef..296acd0490652 100644 --- a/Mathlib/Geometry/Manifold/AnalyticManifold.lean +++ b/Mathlib/Geometry/Manifold/AnalyticManifold.lean @@ -1,10 +1,12 @@ /- Copyright (c) 2023 Michael Lee. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Michael Lee +Authors: Michael Lee, Geoffrey Irving -/ import Mathlib.Analysis.Analytic.Composition +import Mathlib.Analysis.Analytic.Constructions import Mathlib.Analysis.Analytic.Linear +import Mathlib.Analysis.Analytic.Within import Mathlib.Analysis.Calculus.FDeriv.Analytic import Mathlib.Geometry.Manifold.SmoothManifoldWithCorners @@ -17,8 +19,8 @@ interior and smooth everywhere (including at the boundary). The definition mirr `SmoothManifoldWithCorners`, but using an `analyticGroupoid` in place of `contDiffGroupoid`. All analytic manifolds are smooth manifolds. -For now we define only `analyticGroupoid`; an upcoming commit will add `AnalyticManifold` (see -https://github.com/leanprover-community/mathlib4/pull/10853). +Completeness is required throughout, but this is nonessential: it is due to many of the lemmas about +AnalyticWithinOn` requiring completeness for ease of proof. -/ noncomputable section @@ -29,7 +31,7 @@ open scoped Manifold Filter Topology variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] -variable {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] {H : Type*} +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] [CompleteSpace E] {H : Type*} [TopologicalSpace H] (I : ModelWithCorners 𝕜 E H) {M : Type*} [TopologicalSpace M] /-! @@ -42,117 +44,53 @@ 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 groupoid of analytic transformations of `H` -as the maps that are analytic and map interior to interior when read in `E` through `I`. We also -explicitly define that they are `C^∞` on the whole domain, since we are only requiring -analyticity on the interior of the domain. -/ +/-- 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. -/ +def analyticPregroupoid : Pregroupoid H where + property f s := AnalyticWithinOn 𝕜 (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] + apply hg.comp + · exact hf.mono fun _ ⟨hx1, hx2⟩ ↦ ⟨hx1.1, hx2⟩ + · rintro x ⟨hx1, _⟩ + simpa only [mfld_simps] using hx1.2 + id_mem := by + apply (analyticOn_id 𝕜).analyticWithinOn.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 + rintro y ⟨hy1, hy2⟩ + obtain ⟨x, hx⟩ := mem_range.1 hy2 + simp only [mfld_simps, ← hx] at hy1 ⊢ + obtain ⟨v, v_open, xv, hv⟩ := H x hy1 + have : I.symm ⁻¹' (u ∩ v) ∩ range I = I.symm ⁻¹' u ∩ range I ∩ I.symm ⁻¹' v := by + rw [preimage_inter, inter_assoc, inter_assoc, inter_comm _ (range I)] + exact ⟨I.symm ⁻¹' v, v_open.preimage I.continuous_symm, by simpa, this ▸ hv⟩ + congr {f g u} _ fg hf := by + apply hf.congr + rintro y ⟨hy1, hy2⟩ + obtain ⟨x, hx⟩ := mem_range.1 hy2 + simp only [mfld_simps, ← hx] at hy1 ⊢ + 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. -/ def analyticGroupoid : StructureGroupoid H := - (contDiffGroupoid ∞ I) ⊓ Pregroupoid.groupoid - { property := fun f s => AnalyticOn 𝕜 (I ∘ f ∘ I.symm) (I.symm ⁻¹' s ∩ interior (range I)) ∧ - (I.symm ⁻¹' s ∩ interior (range I)).image (I ∘ f ∘ I.symm) ⊆ interior (range I) - comp := fun {f g u v} hf hg _ _ _ => by - simp only [] at hf hg ⊢ - have comp : I ∘ (g ∘ f) ∘ I.symm = (I ∘ g ∘ I.symm) ∘ I ∘ f ∘ I.symm := by ext x; simp - apply And.intro - · simp only [comp, preimage_inter] - refine hg.left.comp (hf.left.mono ?_) ?_ - · simp only [subset_inter_iff, inter_subset_right] - rw [inter_assoc] - simp - · intro x hx - apply And.intro - · rw [mem_preimage, comp_apply, I.left_inv] - exact hx.left.right - · apply hf.right - rw [mem_image] - exact ⟨x, ⟨⟨hx.left.left, hx.right⟩, rfl⟩⟩ - · simp only [comp] - rw [image_comp] - intro x hx - rw [mem_image] at hx - rcases hx with ⟨x', hx'⟩ - refine hg.right ⟨x', And.intro ?_ hx'.right⟩ - apply And.intro - · have hx'1 : x' ∈ ((v.preimage f).preimage (I.symm)).image (I ∘ f ∘ I.symm) := by - refine image_subset (I ∘ f ∘ I.symm) ?_ hx'.left - rw [preimage_inter] - refine Subset.trans ?_ (u.preimage I.symm).inter_subset_right - apply inter_subset_left - rcases hx'1 with ⟨x'', hx''⟩ - rw [hx''.right.symm] - simp only [comp_apply, mem_preimage, I.left_inv] - exact hx''.left - · rw [mem_image] at hx' - rcases hx'.left with ⟨x'', hx''⟩ - exact hf.right ⟨x'', ⟨⟨hx''.left.left.left, hx''.left.right⟩, hx''.right⟩⟩ - id_mem := by - apply And.intro - · simp only [preimage_univ, univ_inter] - exact AnalyticOn.congr isOpen_interior - (f := (1 : E →L[𝕜] E)) (fun x _ => (1 : E →L[𝕜] E).analyticAt x) - (fun z hz => (I.right_inv (interior_subset hz)).symm) - · intro x hx - simp only [id_comp, comp_apply, preimage_univ, univ_inter, mem_image] at hx - rcases hx with ⟨y, hy⟩ - rw [← hy.right, I.right_inv (interior_subset hy.left)] - exact hy.left - locality := fun {f u} _ h => by - simp only [] at h - simp only [AnalyticOn] - apply And.intro - · intro x hx - rcases h (I.symm x) (mem_preimage.mp hx.left) with ⟨v, hv⟩ - exact hv.right.right.left x ⟨mem_preimage.mpr ⟨hx.left, hv.right.left⟩, hx.right⟩ - · apply mapsTo'.mp - simp only [MapsTo] - intro x hx - rcases h (I.symm x) hx.left with ⟨v, hv⟩ - apply hv.right.right.right - rw [mem_image] - have hx' := And.intro hx (mem_preimage.mpr hv.right.left) - rw [← mem_inter_iff, inter_comm, ← inter_assoc, ← preimage_inter, inter_comm v u] at hx' - exact ⟨x, ⟨hx', rfl⟩⟩ - congr := fun {f g u} hu fg hf => by - simp only [] at hf ⊢ - apply And.intro - · refine AnalyticOn.congr (IsOpen.inter (hu.preimage I.continuous_symm) isOpen_interior) - hf.left ?_ - intro z hz - simp only [comp_apply] - rw [fg (I.symm z) hz.left] - · intro x hx - apply hf.right - rw [mem_image] at hx ⊢ - rcases hx with ⟨y, hy⟩ - refine ⟨y, ⟨hy.left, ?_⟩⟩ - rw [comp_apply, comp_apply, fg (I.symm y) hy.left.left] at hy - exact hy.right } + (analyticPregroupoid I).groupoid /-- An identity partial homeomorphism belongs to the analytic groupoid. -/ theorem ofSet_mem_analyticGroupoid {s : Set H} (hs : IsOpen s) : PartialHomeomorph.ofSet s hs ∈ analyticGroupoid I := by - rw [analyticGroupoid] - refine And.intro (ofSet_mem_contDiffGroupoid ∞ I hs) ?_ - apply mem_groupoid_of_pregroupoid.mpr - suffices h : AnalyticOn 𝕜 (I ∘ I.symm) (I.symm ⁻¹' s ∩ interior (range I)) ∧ - (I.symm ⁻¹' s ∩ interior (range I)).image (I ∘ I.symm) ⊆ interior (range I) by - simp only [PartialHomeomorph.ofSet_apply, id_comp, PartialHomeomorph.ofSet_toPartialEquiv, - PartialEquiv.ofSet_source, h, comp_apply, mem_range, image_subset_iff, true_and, - PartialHomeomorph.ofSet_symm, PartialEquiv.ofSet_target, and_self] - intro x hx - refine mem_preimage.mpr ?_ - rw [← I.right_inv (interior_subset hx.right)] at hx - exact hx.right - apply And.intro - · have : AnalyticOn 𝕜 (1 : E →L[𝕜] E) (univ : Set E) := (fun x _ => (1 : E →L[𝕜] E).analyticAt x) - exact (this.mono (subset_univ (s.preimage (I.symm) ∩ interior (range I)))).congr - ((hs.preimage I.continuous_symm).inter isOpen_interior) - fun z hz => (I.right_inv (interior_subset hz.right)).symm - · intro x hx - simp only [comp_apply, mem_image] at hx - rcases hx with ⟨y, hy⟩ - rw [← hy.right, I.right_inv (interior_subset hy.left.right)] - exact hy.left.right + rw [analyticGroupoid, mem_groupoid_of_pregroupoid] + suffices h : AnalyticWithinOn 𝕜 (I ∘ I.symm) (I.symm ⁻¹' s ∩ range I) by + simp [h, analyticPregroupoid] + have hi : AnalyticWithinOn 𝕜 id (univ : Set E) := (analyticOn_id _).analyticWithinOn + exact (hi.mono (subset_univ _)).congr (fun x hx ↦ (I.right_inv hx.2).symm) /-- The composition of a partial homeomorphism from `H` to `M` and its inverse belongs to the analytic groupoid. -/ @@ -168,25 +106,72 @@ instance : ClosedUnderRestriction (analyticGroupoid I) := (by rw [StructureGroupoid.le_iff] rintro e ⟨s, hs, hes⟩ - apply (analyticGroupoid I).mem_of_eqOnSource' _ _ _ hes - exact ofSet_mem_analyticGroupoid I hs) + exact (analyticGroupoid I).mem_of_eqOnSource' _ _ (ofSet_mem_analyticGroupoid I hs) hes) + +/-- `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 + 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 [CompleteSpace E] [I.Boundaryless] - (e : PartialHomeomorph H H) : +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 - apply Iff.intro - · intro he - have := mem_groupoid_of_pregroupoid.mp he.right - simp only [I.image_eq, I.range_eq_univ, interior_univ, subset_univ, and_true] at this ⊢ - exact this - · intro he - apply And.intro - all_goals apply mem_groupoid_of_pregroupoid.mpr; simp only [I.image_eq, I.range_eq_univ, - interior_univ, subset_univ, and_true, contDiffPregroupoid] at he ⊢ - · exact ⟨he.left.contDiffOn, he.right.contDiffOn⟩ - · exact he + AnalyticOn 𝕜 (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] + · exact I.continuous_symm.isOpen_preimage _ e.open_target + · exact I.continuous_symm.isOpen_preimage _ e.open_source + +/-- `analyticGroupoid` is closed under products -/ +theorem analyticGroupoid_prod {E A : Type} [NormedAddCommGroup E] [NormedSpace 𝕜 E] + [CompleteSpace E] [TopologicalSpace A] {F B : Type} [NormedAddCommGroup F] [NormedSpace 𝕜 F] + [CompleteSpace F] [TopologicalSpace B] {I : ModelWithCorners 𝕜 E A} {J : ModelWithCorners 𝕜 F B} + {f : PartialHomeomorph A A} {g : PartialHomeomorph B B} + (fa : f ∈ analyticGroupoid I) (ga : g ∈ analyticGroupoid J) : + 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 (analyticOn_fst _).analyticWithinOn fun _ m ↦ ⟨m.1.1, (pe ▸ m.2).1⟩) + (ga.1.comp (analyticOn_snd _).analyticWithinOn fun _ m ↦ ⟨m.1.2, (pe ▸ m.2).2⟩), + AnalyticWithinOn.prod + (fa.2.comp (analyticOn_fst _).analyticWithinOn fun _ m ↦ ⟨m.1.1, (pe ▸ m.2).1⟩) + (ga.2.comp (analyticOn_snd _).analyticWithinOn fun _ m ↦ ⟨m.1.2, (pe ▸ m.2).2⟩)⟩ end analyticGroupoid + +section AnalyticManifold + +/-- An analytic manifold w.r.t. a model `I : ModelWithCorners 𝕜 E H` is a charted space over `H` +s.t. all extended chart conversion maps are analytic. -/ +class AnalyticManifold (I : ModelWithCorners 𝕜 E H) (M : Type*) [TopologicalSpace M] + [ChartedSpace H M] extends HasGroupoid M (analyticGroupoid I) : Prop + +/-- Normed spaces are analytic manifolds over themselves. -/ +instance AnalyticManifold.self : AnalyticManifold 𝓘(𝕜, E) E where + +/-- `M × N` is an analytic manifold if `M` and `N` are -/ +instance AnalyticManifold.prod {E A : Type} [NormedAddCommGroup E] [NormedSpace 𝕜 E] + [CompleteSpace E] [TopologicalSpace A] {F B : Type} [NormedAddCommGroup F] [NormedSpace 𝕜 F] + [CompleteSpace F] [TopologicalSpace B] {I : ModelWithCorners 𝕜 E A} {J : ModelWithCorners 𝕜 F B} + {M : Type} [TopologicalSpace M] [ChartedSpace A M] [m : AnalyticManifold I M] + {N : Type} [TopologicalSpace N] [ChartedSpace B N] [n : AnalyticManifold J N] : + AnalyticManifold (I.prod J) (M × N) where + compatible := by + intro f g ⟨f1, f2, hf1, hf2, fe⟩ ⟨g1, g2, hg1, hg2, ge⟩ + rw [← fe, ← ge, PartialHomeomorph.prod_symm, PartialHomeomorph.prod_trans] + exact analyticGroupoid_prod (m.toHasGroupoid.compatible f2 g2) + (n.toHasGroupoid.compatible hf2 hg2) + +/-- Analytic manifolds are smooth manifolds. -/ +instance AnalyticManifold.smoothManifoldWithCorners [ChartedSpace H M] [cm : AnalyticManifold I M] : + SmoothManifoldWithCorners I M where + compatible := by + intro f g hf hg + have m := cm.compatible hf hg + exact ⟨m.1.contDiffOn, m.2.contDiffOn⟩ + +end AnalyticManifold diff --git a/Mathlib/Geometry/Manifold/ChartedSpace.lean b/Mathlib/Geometry/Manifold/ChartedSpace.lean index c1ce4ba8838db..1c0a9cf284750 100644 --- a/Mathlib/Geometry/Manifold/ChartedSpace.lean +++ b/Mathlib/Geometry/Manifold/ChartedSpace.lean @@ -176,7 +176,7 @@ structure StructureGroupoid (H : Type u) [TopologicalSpace H] where variable [TopologicalSpace H] instance : Membership (PartialHomeomorph H H) (StructureGroupoid H) := - ⟨fun (e : PartialHomeomorph H H) (G : StructureGroupoid H) ↦ e ∈ G.members⟩ + ⟨fun (G : StructureGroupoid H) (e : PartialHomeomorph H H) ↦ e ∈ G.members⟩ instance (H : Type u) [TopologicalSpace H] : SetLike (StructureGroupoid H) (PartialHomeomorph H H) where @@ -1161,6 +1161,12 @@ theorem chartAt_subtype_val_symm_eventuallyEq (U : Opens M) {x : U} : exact Filter.eventuallyEq_of_mem heUx_nhds (e.subtypeRestr_symm_eqOn ⟨x⟩) theorem chartAt_inclusion_symm_eventuallyEq {U V : Opens M} (hUV : U ≤ V) {x : U} : + #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 : ChartedSpace H V := V.instChartedSpace (chartAt H (Set.inclusion hUV x)).symm =ᶠ[𝓝 (chartAt H (Set.inclusion hUV x) (Set.inclusion hUV x))] Set.inclusion hUV ∘ (chartAt H x).symm := by @@ -1289,7 +1295,13 @@ theorem StructureGroupoid.restriction_mem_maximalAtlas_subtype rw [PartialHomeomorph.subtypeRestr_def, PartialHomeomorph.trans_refl] let goal := e.toHomeomorphSourceTarget.toPartialHomeomorph ≫ₕ (t.partialHomeomorphSubtypeCoe this) have : goal ≈ e.subtypeRestr (s := s) hs := - (goal.eqOnSource_iff (e.subtypeRestr (s := s) hs)).mpr ⟨by simp [s, goal], by intro _ _; rfl⟩ + (goal.eqOnSource_iff (e.subtypeRestr (s := s) hs)).mpr + ⟨by + simp only [trans_toPartialEquiv, PartialEquiv.trans_source, + Homeomorph.toPartialHomeomorph_source, toFun_eq_coe, Homeomorph.toPartialHomeomorph_apply, + Opens.partialHomeomorphSubtypeCoe_source, preimage_univ, inter_self, subtypeRestr_source, + goal, s] + exact Subtype.coe_preimage_self _ |>.symm, by intro _ _; rfl⟩ exact G.mem_maximalAtlas_of_eqOnSource (M := s) this (G.restriction_in_maximalAtlas he hs) /-- Each chart of a charted space is a structomorphism between its source and target. -/ diff --git a/Mathlib/Geometry/Manifold/ContMDiff/Basic.lean b/Mathlib/Geometry/Manifold/ContMDiff/Basic.lean index a8f5c4d77931c..9539fe52ffd26 100644 --- a/Mathlib/Geometry/Manifold/ContMDiff/Basic.lean +++ b/Mathlib/Geometry/Manifold/ContMDiff/Basic.lean @@ -217,7 +217,7 @@ variable {c : M'} theorem contMDiff_const : ContMDiff I I' n fun _ : M => c := by intro x refine ⟨continuousWithinAt_const, ?_⟩ - simp only [ContDiffWithinAtProp, (· ∘ ·)] + simp only [ContDiffWithinAtProp, Function.comp_def] exact contDiffWithinAt_const @[to_additive] @@ -322,11 +322,19 @@ theorem ContMDiff.extend_one [T2Space M] [One M'] {n : ℕ∞} {U : Opens M} {f refine contMDiff_of_mulTSupport (fun x h ↦ ?_) _ lift x to U using Subtype.coe_image_subset _ _ (supp.mulTSupport_extend_one_subset continuous_subtype_val h) - rw [← contMdiffAt_subtype_iff, ← comp_def] + rw [← contMdiffAt_subtype_iff] + simp_rw [← comp_def] erw [extend_comp Subtype.val_injective] exact diff.contMDiffAt theorem contMDiff_inclusion {n : ℕ∞} {U V : Opens M} (h : U ≤ V) : + #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 : ChartedSpace H U := U.instChartedSpace + letI : ChartedSpace H V := V.instChartedSpace ContMDiff I I n (Set.inclusion h : U → V) := by rintro ⟨x, hx : x ∈ U⟩ apply (contDiffWithinAt_localInvariantProp I I n).liftProp_inclusion @@ -345,7 +353,15 @@ theorem Smooth.extend_one [T2Space M] [One M'] {U : Opens M} {f : U → M'} (supp : HasCompactMulSupport f) (diff : Smooth I I' f) : Smooth I I' (Subtype.val.extend f 1) := ContMDiff.extend_one supp diff -theorem smooth_inclusion {U V : Opens M} (h : U ≤ V) : Smooth I I (Set.inclusion h : U → V) := +theorem smooth_inclusion {U V : Opens M} (h : U ≤ V) : + #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 : ChartedSpace H U := U.instChartedSpace + letI : ChartedSpace H V := V.instChartedSpace + Smooth I I (Set.inclusion h : U → V) := contMDiff_inclusion h end Inclusion diff --git a/Mathlib/Geometry/Manifold/ContMDiff/NormedSpace.lean b/Mathlib/Geometry/Manifold/ContMDiff/NormedSpace.lean index 3f612e90bddc7..0b857f12e00f4 100644 --- a/Mathlib/Geometry/Manifold/ContMDiff/NormedSpace.lean +++ b/Mathlib/Geometry/Manifold/ContMDiff/NormedSpace.lean @@ -192,7 +192,7 @@ theorem ContMDiffWithinAt.clm_apply {g : M → F₁ →L[𝕜] F₂} {f : M → (hg : ContMDiffWithinAt I 𝓘(𝕜, F₁ →L[𝕜] F₂) n g s x) (hf : ContMDiffWithinAt I 𝓘(𝕜, F₁) n f s x) : ContMDiffWithinAt I 𝓘(𝕜, F₂) n (fun x => g x (f x)) s x := - ContDiffWithinAt.comp_contMDiffWithinAt + ContDiffWithinAt.comp_contMDiffWithinAt (t := univ) (g := fun x : (F₁ →L[𝕜] F₂) × F₁ => x.1 x.2) (by apply ContDiff.contDiffAt; exact contDiff_fst.clm_apply contDiff_snd) (hg.prod_mk_space hf) (by simp_rw [preimage_univ, subset_univ]) diff --git a/Mathlib/Geometry/Manifold/ContMDiff/Product.lean b/Mathlib/Geometry/Manifold/ContMDiff/Product.lean index 6cd5c2919d09b..5208fce1bdcc3 100644 --- a/Mathlib/Geometry/Manifold/ContMDiff/Product.lean +++ b/Mathlib/Geometry/Manifold/ContMDiff/Product.lean @@ -337,7 +337,7 @@ theorem contMDiffWithinAt_pi_space : ContMDiffWithinAt I 𝓘(𝕜, ∀ i, Fi i) n φ s x ↔ ∀ i, ContMDiffWithinAt I 𝓘(𝕜, Fi i) n (fun x => φ x i) s x := by simp only [contMDiffWithinAt_iff, continuousWithinAt_pi, contDiffWithinAt_pi, forall_and, - writtenInExtChartAt, extChartAt_model_space_eq_id, (· ∘ ·), PartialEquiv.refl_coe, id] + writtenInExtChartAt, extChartAt_model_space_eq_id, Function.comp_def, PartialEquiv.refl_coe, id] theorem contMDiffOn_pi_space : ContMDiffOn I 𝓘(𝕜, ∀ i, Fi i) n φ s ↔ ∀ i, ContMDiffOn I 𝓘(𝕜, Fi i) n (fun x => φ x i) s := diff --git a/Mathlib/Geometry/Manifold/ContMDiffMFDeriv.lean b/Mathlib/Geometry/Manifold/ContMDiffMFDeriv.lean index 2daa9b0a934c0..3dba3c04792f4 100644 --- a/Mathlib/Geometry/Manifold/ContMDiffMFDeriv.lean +++ b/Mathlib/Geometry/Manifold/ContMDiffMFDeriv.lean @@ -94,7 +94,7 @@ protected theorem ContMDiffAt.mfderiv {x₀ : N} (f : N → M → M') (g : N → (range I) (extChartAt I (g x₀) (g ((extChartAt J x₀).symm x)))) (range J) (extChartAt J x₀ x₀) := by rw [contMDiffAt_iff] at hf hg - simp_rw [Function.comp, uncurry, extChartAt_prod, PartialEquiv.prod_coe_symm, + 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 _) ?_ · simp_rw [extChartAt_to_inv]; exact hf.2 @@ -108,7 +108,7 @@ protected theorem ContMDiffAt.mfderiv {x₀ : N} (f : N → M → M') (g : N → (extChartAt I (g x₀) (g x))) x₀ := by simp_rw [contMDiffAt_iff_source_of_mem_source (mem_chart_source G x₀), - contMDiffWithinAt_iff_contDiffWithinAt, Function.comp] + contMDiffWithinAt_iff_contDiffWithinAt, Function.comp_def] exact this have : ContMDiffAt J 𝓘(𝕜, E →L[𝕜] E') m diff --git a/Mathlib/Geometry/Manifold/DerivationBundle.lean b/Mathlib/Geometry/Manifold/DerivationBundle.lean index d9bfdfd389518..fad0b9a9bd14e 100644 --- a/Mathlib/Geometry/Manifold/DerivationBundle.lean +++ b/Mathlib/Geometry/Manifold/DerivationBundle.lean @@ -10,7 +10,7 @@ import Mathlib.RingTheory.Derivation.Basic # Derivation bundle -In this file we define the derivations at a point of a manifold on the algebra of smooth fuctions. +In this file we define the derivations at a point of a manifold on the algebra of smooth functions. Moreover, we define the differential of a function in terms of derivations. The content of this file is not meant to be regarded as an alternative definition to the current diff --git a/Mathlib/Geometry/Manifold/Diffeomorph.lean b/Mathlib/Geometry/Manifold/Diffeomorph.lean index 45a273cc452b0..2c6f481393275 100644 --- a/Mathlib/Geometry/Manifold/Diffeomorph.lean +++ b/Mathlib/Geometry/Manifold/Diffeomorph.lean @@ -282,7 +282,7 @@ theorem contMDiffWithinAt_comp_diffeomorph_iff {m} (h : M ≃ₘ^n⟮I, J⟯ N) constructor · intro Hfh rw [← h.symm_apply_apply x] at Hfh - simpa only [(· ∘ ·), h.apply_symm_apply] using + simpa only [Function.comp_def, h.apply_symm_apply] using Hfh.comp (h x) (h.symm.contMDiffWithinAt.of_le hm) (mapsTo_preimage _ _) · rw [← h.image_eq_preimage] exact fun hf => hf.comp x (h.contMDiffWithinAt.of_le hm) (mapsTo_image _ _) @@ -308,7 +308,7 @@ theorem contMDiff_comp_diffeomorph_iff {m} (h : M ≃ₘ^n⟮I, J⟯ N) {f : N theorem contMDiffWithinAt_diffeomorph_comp_iff {m} (h : M ≃ₘ^n⟮I, J⟯ N) {f : M' → M} (hm : m ≤ n) {s x} : ContMDiffWithinAt I' J m (h ∘ f) s x ↔ ContMDiffWithinAt I' I m f s x := ⟨fun Hhf => by - simpa only [(· ∘ ·), h.symm_apply_apply] using + simpa only [Function.comp_def, h.symm_apply_apply] using (h.symm.contMDiffAt.of_le hm).comp_contMDiffWithinAt _ Hhf, fun Hf => (h.contMDiffAt.of_le hm).comp_contMDiffWithinAt _ Hf⟩ diff --git a/Mathlib/Geometry/Manifold/Instances/Real.lean b/Mathlib/Geometry/Manifold/Instances/Real.lean index cdb390895e851..32997ffec1950 100644 --- a/Mathlib/Geometry/Manifold/Instances/Real.lean +++ b/Mathlib/Geometry/Manifold/Instances/Real.lean @@ -47,7 +47,7 @@ open scoped Manifold /-- The half-space in `ℝ^n`, used to model manifolds with boundary. We only define it when `1 ≤ n`, as the definition only makes sense in this case. -/ -def EuclideanHalfSpace (n : ℕ) [Zero (Fin n)] : Type := +def EuclideanHalfSpace (n : ℕ) [NeZero n] : Type := { x : EuclideanSpace ℝ (Fin n) // 0 ≤ x 0 } /-- @@ -64,13 +64,13 @@ without the following reducibility attribute (which is only set in this section) variable {n : ℕ} -instance [Zero (Fin n)] : TopologicalSpace (EuclideanHalfSpace n) := +instance [NeZero n] : TopologicalSpace (EuclideanHalfSpace n) := instTopologicalSpaceSubtype instance : TopologicalSpace (EuclideanQuadrant n) := instTopologicalSpaceSubtype -instance [Zero (Fin n)] : Inhabited (EuclideanHalfSpace n) := +instance [NeZero n] : Inhabited (EuclideanHalfSpace n) := ⟨⟨0, le_rfl⟩⟩ instance : Inhabited (EuclideanQuadrant n) := @@ -81,15 +81,37 @@ theorem EuclideanQuadrant.ext (x y : EuclideanQuadrant n) (h : x.1 = y.1) : x = Subtype.eq h @[ext] -theorem EuclideanHalfSpace.ext [Zero (Fin n)] (x y : EuclideanHalfSpace n) +theorem EuclideanHalfSpace.ext [NeZero n] (x y : EuclideanHalfSpace n) (h : x.1 = y.1) : x = y := Subtype.eq h -theorem range_euclideanHalfSpace (n : ℕ) [Zero (Fin n)] : +theorem range_euclideanHalfSpace (n : ℕ) [NeZero n] : (range fun x : EuclideanHalfSpace n => x.val) = { y | 0 ≤ y 0 } := Subtype.range_val @[deprecated (since := "2024-04-05")] alias range_half_space := range_euclideanHalfSpace +open ENNReal in +@[simp] +theorem interior_halfspace {n : ℕ} (p : ℝ≥0∞) (a : ℝ) (i : Fin n) : + interior { y : PiLp p (fun _ : Fin n ↦ ℝ) | a ≤ y i } = { y | a < y i } := by + let f : PiLp p (fun _ : Fin n ↦ ℝ) →L[ℝ] ℝ := ContinuousLinearMap.proj i + simpa [interior_Ici] using f.interior_preimage (Function.surjective_eval _) (Ici a) + +open ENNReal in +@[simp] +theorem closure_halfspace {n : ℕ} (p : ℝ≥0∞) (a : ℝ) (i : Fin n) : + closure { y : PiLp p (fun _ : Fin n ↦ ℝ) | a ≤ y i } = { y | a ≤ y i } := by + let f : PiLp p (fun _ : Fin n ↦ ℝ) →L[ℝ] ℝ := ContinuousLinearMap.proj i + simpa [closure_Ici] using f.closure_preimage (Function.surjective_eval _) (Ici a) + +open ENNReal in +@[simp] +theorem frontier_halfspace {n : ℕ} (p : ℝ≥0∞) (a : ℝ) (i : Fin n) : + frontier { y : PiLp p (fun _ : Fin n ↦ ℝ) | a ≤ y i } = { y | a = y i } := by + rw [frontier, closure_halfspace, interior_halfspace] + ext y + simpa only [mem_diff, mem_setOf_eq, not_lt] using antisymm_iff + theorem range_euclideanQuadrant (n : ℕ) : (range fun x : EuclideanQuadrant n => x.val) = { y | ∀ i : Fin n, 0 ≤ y i } := Subtype.range_val @@ -101,7 +123,7 @@ end Definition of the model with corners `(EuclideanSpace ℝ (Fin n), EuclideanHalfSpace n)`, used as a model for manifolds with boundary. In the locale `Manifold`, use the shortcut `𝓡∂ n`. -/ -def modelWithCornersEuclideanHalfSpace (n : ℕ) [Zero (Fin n)] : +def modelWithCornersEuclideanHalfSpace (n : ℕ) [NeZero n] : ModelWithCorners ℝ (EuclideanSpace ℝ (Fin n)) (EuclideanHalfSpace n) where toFun := Subtype.val invFun x := ⟨update x 0 (max (x 0) 0), by simp [le_refl]⟩ @@ -157,6 +179,25 @@ scoped[Manifold] (modelWithCornersEuclideanHalfSpace n : ModelWithCorners ℝ (EuclideanSpace ℝ (Fin n)) (EuclideanHalfSpace n)) +lemma range_modelWithCornersEuclideanHalfSpace (n : ℕ) [NeZero n] : + range (𝓡∂ n) = { y | 0 ≤ y 0 } := range_euclideanHalfSpace n + +lemma interior_range_modelWithCornersEuclideanHalfSpace (n : ℕ) [NeZero n] : + interior (range (𝓡∂ n)) = { y | 0 < y 0 } := by + calc interior (range (𝓡∂ n)) + _ = interior ({ y | 0 ≤ y 0}) := by + congr! + apply range_euclideanHalfSpace + _ = { y | 0 < y 0 } := interior_halfspace _ _ _ + +lemma frontier_range_modelWithCornersEuclideanHalfSpace (n : ℕ) [NeZero n] : + frontier (range (𝓡∂ n)) = { y | 0 = y 0 } := by + calc frontier (range (𝓡∂ n)) + _ = frontier ({ y | 0 ≤ y 0 }) := by + congr! + apply range_euclideanHalfSpace + _ = { y | 0 = y 0 } := frontier_halfspace 2 _ _ + /-- The left chart for the topological space `[x, y]`, defined on `[x,y)` and sending `x` to `0` in `EuclideanHalfSpace 1`. -/ diff --git a/Mathlib/Geometry/Manifold/Instances/Sphere.lean b/Mathlib/Geometry/Manifold/Instances/Sphere.lean index 41a32a5f566cb..21821c1f74e99 100644 --- a/Mathlib/Geometry/Manifold/Instances/Sphere.lean +++ b/Mathlib/Geometry/Manifold/Instances/Sphere.lean @@ -421,7 +421,7 @@ instance (n : ℕ) : haveI := Fact.mk (@finrank_euclideanSpace_fin ℝ _ (n + 1)) EuclideanSpace.instSmoothManifoldWithCornersSphere -/-- The inclusion map (i.e., `coe`) from the sphere in `E` to `E` is smooth. -/ +/-- The inclusion map (i.e., `coe`) from the sphere in `E` to `E` is smooth. -/ theorem contMDiff_coe_sphere {n : ℕ} [Fact (finrank ℝ E = n + 1)] : ContMDiff (𝓡 n) 𝓘(ℝ, E) ∞ ((↑) : sphere (0 : E) 1 → E) := by -- Porting note: trouble with filling these implicit variables in the instance diff --git a/Mathlib/Geometry/Manifold/IntegralCurve.lean b/Mathlib/Geometry/Manifold/IntegralCurve.lean index beb8c885abb24..01130e726c4b7 100644 --- a/Mathlib/Geometry/Manifold/IntegralCurve.lean +++ b/Mathlib/Geometry/Manifold/IntegralCurve.lean @@ -492,7 +492,7 @@ theorem isIntegralCurve_eq_of_contMDiff (hγt : ∀ t, I.IsInteriorPoint (γ t)) obtain ⟨hS₂, hS₃⟩ := abs_lt.mp hS₂ exact ⟨T + S, by constructor <;> constructor <;> linarith⟩ exact isIntegralCurveOn_Ioo_eqOn_of_contMDiff ht (fun t _ ↦ hγt t) hv - ((hγ.isIntegralCurveOn _).mono (subset_univ _)) + ((hγ.isIntegralCurveOn _).mono (subset_univ _)) ((hγ'.isIntegralCurveOn _).mono (subset_univ _)) h ht₀ theorem isIntegralCurve_Ioo_eq_of_contMDiff_boundaryless [BoundarylessManifold I M] diff --git a/Mathlib/Geometry/Manifold/InteriorBoundary.lean b/Mathlib/Geometry/Manifold/InteriorBoundary.lean index 1bfcd8ec40979..ae3c3a754f493 100644 --- a/Mathlib/Geometry/Manifold/InteriorBoundary.lean +++ b/Mathlib/Geometry/Manifold/InteriorBoundary.lean @@ -21,10 +21,12 @@ Define the interior and boundary of a manifold. - `ModelWithCorners.univ_eq_interior_union_boundary`: `M` is the union of its interior and boundary - `ModelWithCorners.interior_boundary_disjoint`: interior and boundary of `M` are disjoint - `BoundarylessManifold.isInteriorPoint`: if `M` is boundaryless, every point is an interior point - +- `ModelWithCorners.Boundaryless.boundary_eq_empty` and `of_boundary_eq_empty`: +`M` is boundaryless if and only if its boundary is empty - `ModelWithCorners.interior_prod`: the interior of `M × N` is the product of the interiors of `M` and `N`. - `ModelWithCorners.boundary_prod`: the boundary of `M × N` is `∂M × N ∪ (M × ∂N)`. +- `ModelWithCorners.BoundarylessManifold.prod`: if `M` and `N` are boundaryless, so is `M × N` ## Tags manifold, interior, boundary @@ -96,10 +98,14 @@ lemma disjoint_interior_boundary : Disjoint (I.interior M) (I.boundary M) := by exact ⟨h1, h2⟩ /-- The boundary is the complement of the interior. -/ -lemma boundary_eq_complement_interior : I.boundary M = (I.interior M)ᶜ := by - apply (compl_unique ?_ I.interior_union_boundary_eq_univ).symm +lemma compl_interior : (I.interior M)ᶜ = I.boundary M:= by + apply compl_unique ?_ I.interior_union_boundary_eq_univ exact disjoint_iff_inter_eq_empty.mp (I.disjoint_interior_boundary) +/-- The interior is the complement of the boundary. -/ +lemma compl_boundary : (I.boundary M)ᶜ = I.interior M:= by + rw [← compl_interior, compl_compl] + variable {I} in lemma _root_.range_mem_nhds_isInteriorPoint {x : M} (h : I.IsInteriorPoint x) : range I ∈ 𝓝 (extChartAt I x x) := by @@ -123,36 +129,47 @@ instance : BoundarylessManifold I M where let r := ((chartAt H x).isOpen_extend_target I).interior_eq have : extChartAt I x = (chartAt H x).extend I := rfl rw [← this] at r - rw [ModelWithCorners.isInteriorPoint_iff, r] + rw [isInteriorPoint_iff, r] exact PartialEquiv.map_source _ (mem_extChartAt_source _ _) end Boundaryless section BoundarylessManifold -variable [BoundarylessManifold I M] /-- The empty manifold is boundaryless. -/ instance BoundarylessManifold.of_empty [IsEmpty M] : BoundarylessManifold I M where isInteriorPoint' x := (IsEmpty.false x).elim -lemma _root_.BoundarylessManifold.isInteriorPoint {x : M} : +lemma _root_.BoundarylessManifold.isInteriorPoint {x : M} [BoundarylessManifold I M] : IsInteriorPoint I x := BoundarylessManifold.isInteriorPoint' x /-- If `I` is boundaryless, `M` has full interior. -/ -lemma interior_eq_univ : I.interior M = univ := +lemma interior_eq_univ [BoundarylessManifold I M] : I.interior M = univ := eq_univ_of_forall fun _ => BoundarylessManifold.isInteriorPoint I /-- Boundaryless manifolds have empty boundary. -/ -lemma Boundaryless.boundary_eq_empty : I.boundary M = ∅ := by - rw [I.boundary_eq_complement_interior, I.interior_eq_univ, compl_empty_iff] +lemma Boundaryless.boundary_eq_empty [BoundarylessManifold I M] : I.boundary M = ∅ := by + rw [← I.compl_interior, I.interior_eq_univ, compl_empty_iff] instance [BoundarylessManifold I M] : IsEmpty (I.boundary M) := isEmpty_coe_sort.mpr (Boundaryless.boundary_eq_empty I) +/-- `M` is boundaryless iff its boundary is empty. -/ +lemma Boundaryless.iff_boundary_eq_empty : I.boundary M = ∅ ↔ BoundarylessManifold I M := by + refine ⟨fun h ↦ { isInteriorPoint' := ?_ }, fun a ↦ boundary_eq_empty I⟩ + intro x + show x ∈ I.interior M + rw [← compl_interior, compl_empty_iff] at h + rw [h] + trivial + +/-- Manifolds with empty boundary are boundaryless. -/ +lemma Boundaryless.of_boundary_eq_empty (h : I.boundary M = ∅) : BoundarylessManifold I M := + (Boundaryless.iff_boundary_eq_empty (I := I)).mp h + end BoundarylessManifold -end ModelWithCorners --- Interior and boundary of the product of two manifolds. +/-! Interior and boundary of the product of two manifolds. -/ section prod variable {I} @@ -162,43 +179,54 @@ variable {I} (J : ModelWithCorners 𝕜 E' H') {x : M} {y : N} /-- The interior of `M × N` is the product of the interiors of `M` and `N`. -/ -lemma ModelWithCorners.interior_prod : +lemma interior_prod : (I.prod J).interior (M × N) = (I.interior M) ×ˢ (J.interior N) := by ext p have aux : (interior (range ↑I)) ×ˢ (interior (range J)) = interior (range (I.prod J)) := by rw [← interior_prod_eq, ← Set.range_prod_map, modelWithCorners_prod_coe] constructor <;> intro hp · replace hp : (I.prod J).IsInteriorPoint p := hp - rw [ModelWithCorners.IsInteriorPoint, ← aux] at hp + rw [IsInteriorPoint, ← aux] at hp exact hp - · obtain ⟨h₁, h₂⟩ := Set.mem_prod.mp hp - rw [ModelWithCorners.interior] at h₁ h₂ - show (I.prod J).IsInteriorPoint p - rw [ModelWithCorners.IsInteriorPoint, ← aux, mem_prod] - exact ⟨h₁, h₂⟩ + · show (I.prod J).IsInteriorPoint p + rw [IsInteriorPoint, ← aux, mem_prod] + obtain h := Set.mem_prod.mp hp + rw [ModelWithCorners.interior] at h + exact h /-- The boundary of `M × N` is `∂M × N ∪ (M × ∂N)`. -/ -lemma ModelWithCorners.boundary_prod : +lemma boundary_prod : (I.prod J).boundary (M × N) = Set.prod univ (J.boundary N) ∪ Set.prod (I.boundary M) univ := by let h := calc (I.prod J).boundary (M × N) - _ = ((I.prod J).interior (M × N))ᶜ := (I.prod J).boundary_eq_complement_interior - _ = ((I.interior M) ×ˢ (J.interior N))ᶜ := by rw [ModelWithCorners.interior_prod] + _ = ((I.prod J).interior (M × N))ᶜ := (I.prod J).compl_interior.symm + _ = ((I.interior M) ×ˢ (J.interior N))ᶜ := by rw [interior_prod] _ = (I.interior M)ᶜ ×ˢ univ ∪ univ ×ˢ (J.interior N)ᶜ := by rw [compl_prod_eq_union] - rw [h, I.boundary_eq_complement_interior, J.boundary_eq_complement_interior, union_comm] + rw [h, I.compl_interior, J.compl_interior, union_comm] rfl /-- If `M` is boundaryless, `∂(M×N) = M × ∂N`. -/ -lemma boundary_of_boundaryless_left [I.Boundaryless] : +lemma boundary_of_boundaryless_left [BoundarylessManifold I M] : (I.prod J).boundary (M × N) = Set.prod (univ : Set M) (J.boundary N) := by - rw [ModelWithCorners.boundary_prod, ModelWithCorners.Boundaryless.boundary_eq_empty I] + rw [boundary_prod, Boundaryless.boundary_eq_empty I] have : Set.prod (∅ : Set M) (univ : Set N) = ∅ := Set.empty_prod rw [this, union_empty] /-- If `N` is boundaryless, `∂(M×N) = ∂M × N`. -/ -lemma boundary_of_boundaryless_right [J.Boundaryless] : +lemma boundary_of_boundaryless_right [BoundarylessManifold J N] : (I.prod J).boundary (M × N) = Set.prod (I.boundary M) (univ : Set N) := by - rw [ModelWithCorners.boundary_prod, ModelWithCorners.Boundaryless.boundary_eq_empty J] + rw [boundary_prod, Boundaryless.boundary_eq_empty J] have : Set.prod (univ : Set M) (∅ : Set N) = ∅ := Set.prod_empty rw [this, empty_union] +/-- The product of two boundaryless manifolds is boundaryless. -/ +instance BoundarylessManifold.prod [BoundarylessManifold I M] [BoundarylessManifold J N] : + BoundarylessManifold (I.prod J) (M × N) := by + apply Boundaryless.of_boundary_eq_empty + simp only [boundary_prod, Boundaryless.boundary_eq_empty, union_empty_iff] + -- These are simp lemmas, but `simp` does not apply them on its own: + -- presumably because of the distinction between `Prod` and `ModelProd` + exact ⟨Set.prod_empty, Set.empty_prod⟩ + end prod + +end ModelWithCorners diff --git a/Mathlib/Geometry/Manifold/LocalInvariantProperties.lean b/Mathlib/Geometry/Manifold/LocalInvariantProperties.lean index c464a37a39429..028b307e1c444 100644 --- a/Mathlib/Geometry/Manifold/LocalInvariantProperties.lean +++ b/Mathlib/Geometry/Manifold/LocalInvariantProperties.lean @@ -515,7 +515,16 @@ theorem liftProp_subtype_val {Q : (H → H) → Set H → H → Prop} (hG : Loca theorem liftProp_inclusion {Q : (H → H) → Set H → H → Prop} (hG : LocalInvariantProp G G Q) (hQ : ∀ y, Q id univ y) {U V : Opens M} (hUV : U ≤ V) : + letI : ChartedSpace H { x // x ∈ V } := V.instChartedSpace + letI : ChartedSpace H { x // x ∈ U } := U.instChartedSpace LiftProp Q (Set.inclusion hUV : U → V) := 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 : ChartedSpace H { x // x ∈ V } := V.instChartedSpace + letI : ChartedSpace H { x // x ∈ U } := U.instChartedSpace intro x show LiftPropAt Q (id ∘ inclusion hUV) x rw [← hG.liftPropAt_iff_comp_inclusion hUV] diff --git a/Mathlib/Geometry/Manifold/MFDeriv/Atlas.lean b/Mathlib/Geometry/Manifold/MFDeriv/Atlas.lean index cd4d98910c206..5161781aac7d7 100644 --- a/Mathlib/Geometry/Manifold/MFDeriv/Atlas.lean +++ b/Mathlib/Geometry/Manifold/MFDeriv/Atlas.lean @@ -198,7 +198,8 @@ theorem comp_symm_deriv {x : M'} (hx : x ∈ e.target) : /-- The derivative of a differentiable partial homeomorphism, as a continuous linear equivalence between the tangent spaces at `x` and `e x`. -/ -protected def mfderiv {x : M} (hx : x ∈ e.source) : TangentSpace I x ≃L[𝕜] TangentSpace I' (e x) := +protected def mfderiv (he : e.MDifferentiable I I') {x : M} (hx : x ∈ e.source) : + TangentSpace I x ≃L[𝕜] TangentSpace I' (e x) := { mfderiv I I' e x with invFun := mfderiv I' I e.symm (e x) continuous_toFun := (mfderiv I I' e x).cont diff --git a/Mathlib/Geometry/Manifold/MFDeriv/Basic.lean b/Mathlib/Geometry/Manifold/MFDeriv/Basic.lean index 29f6ccec46202..f9b96b110f3fc 100644 --- a/Mathlib/Geometry/Manifold/MFDeriv/Basic.lean +++ b/Mathlib/Geometry/Manifold/MFDeriv/Basic.lean @@ -277,7 +277,7 @@ theorem UniqueMDiffOn.eq (U : UniqueMDiffOn I s) (hx : x ∈ s) (h : HasMFDerivW /-! ### General lemmas on derivatives of functions between manifolds -We mimick the API for functions between vector spaces +We mimic the API for functions between vector spaces -/ /-- One can reformulate differentiability within a set at a point as continuity within this set at diff --git a/Mathlib/Geometry/Manifold/MFDeriv/SpecificFunctions.lean b/Mathlib/Geometry/Manifold/MFDeriv/SpecificFunctions.lean index efe86094c46e5..75f5779ee5a46 100644 --- a/Mathlib/Geometry/Manifold/MFDeriv/SpecificFunctions.lean +++ b/Mathlib/Geometry/Manifold/MFDeriv/SpecificFunctions.lean @@ -158,7 +158,7 @@ variable {c : M'} theorem hasMFDerivAt_const (c : M') (x : M) : HasMFDerivAt I I' (fun _ : M => c) x (0 : TangentSpace I x →L[𝕜] TangentSpace I' c) := by refine ⟨continuous_const.continuousAt, ?_⟩ - simp only [writtenInExtChartAt, (· ∘ ·), hasFDerivWithinAt_const] + simp only [writtenInExtChartAt, Function.comp_def, hasFDerivWithinAt_const] theorem hasMFDerivWithinAt_const (c : M') (s : Set M) (x : M) : HasMFDerivWithinAt I I' (fun _ : M => c) s x (0 : TangentSpace I x →L[𝕜] TangentSpace I' c) := diff --git a/Mathlib/Geometry/Manifold/Sheaf/Basic.lean b/Mathlib/Geometry/Manifold/Sheaf/Basic.lean index 1eacc748c2ec9..1bc91fe4b7efb 100644 --- a/Mathlib/Geometry/Manifold/Sheaf/Basic.lean +++ b/Mathlib/Geometry/Manifold/Sheaf/Basic.lean @@ -55,6 +55,12 @@ def StructureGroupoid.LocalInvariantProp.localPredicate (hG : LocalInvariantProp res := by intro U V i f h x have hUV : U ≤ V := CategoryTheory.leOfHom 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 : ChartedSpace H U := U.instChartedSpace show ChartedSpace.LiftPropAt P (f ∘ Set.inclusion hUV) x rw [← hG.liftPropAt_iff_comp_inclusion hUV] apply h diff --git a/Mathlib/Geometry/Manifold/Sheaf/LocallyRingedSpace.lean b/Mathlib/Geometry/Manifold/Sheaf/LocallyRingedSpace.lean index fcd7714d974ef..88bb6216fa89e 100644 --- a/Mathlib/Geometry/Manifold/Sheaf/LocallyRingedSpace.lean +++ b/Mathlib/Geometry/Manifold/Sheaf/LocallyRingedSpace.lean @@ -94,6 +94,12 @@ theorem smoothSheafCommRing.isUnit_stalk_iff {x : M} apply inv_mul_cancel₀ exact hVf y · intro y + #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 : ChartedSpace HM V := V.instChartedSpace exact ((contDiffAt_inv _ (hVf y)).contMDiffAt).comp y (f.smooth.comp (smooth_inclusion hUV)).smoothAt diff --git a/Mathlib/Geometry/Manifold/SmoothManifoldWithCorners.lean b/Mathlib/Geometry/Manifold/SmoothManifoldWithCorners.lean index 8d56a55352b79..b252d909311ac 100644 --- a/Mathlib/Geometry/Manifold/SmoothManifoldWithCorners.lean +++ b/Mathlib/Geometry/Manifold/SmoothManifoldWithCorners.lean @@ -20,13 +20,13 @@ With this groupoid at hand and the general machinery of charted spaces, we thus of `C^n` manifold with respect to any model with corners `I` on `(E, H)`. We also introduce a specific type class for `C^∞` manifolds as these are the most commonly used. -Some texts assume manifolds to be Hausdorff and secound countable. We (in mathlib) assume neither, +Some texts assume manifolds to be Hausdorff and second countable. We (in mathlib) assume neither, but add these assumptions later as needed. (Quite a few results still do not require them.) ## Main definitions * `ModelWithCorners 𝕜 E H` : - a structure containing informations on the way a space `H` embeds in a + a structure containing information on the way a space `H` embeds in a model vector space E over the field `𝕜`. This is all that is needed to define a smooth manifold with model space `H`, and model vector space `E`. * `modelWithCornersSelf 𝕜 E` : @@ -129,7 +129,7 @@ scoped[Manifold] notation "∞" => (⊤ : ℕ∞) /-! ### Models with corners. -/ -/-- A structure containing informations on the way a space `H` embeds in a +/-- A structure containing information on the way a space `H` embeds in a model vector space `E` over the field `𝕜`. This is all what is needed to define a smooth manifold with model space `H`, and model vector space `E`. -/ @@ -427,7 +427,7 @@ section Boundaryless /-- Property ensuring that the model with corners `I` defines manifolds without boundary. This differs from the more general `BoundarylessManifold`, which requires every point on the manifold - to be an interior point. -/ + to be an interior point. -/ class ModelWithCorners.Boundaryless {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] {H : Type*} [TopologicalSpace H] (I : ModelWithCorners 𝕜 E H) : Prop where diff --git a/Mathlib/Geometry/Manifold/VectorBundle/Basic.lean b/Mathlib/Geometry/Manifold/VectorBundle/Basic.lean index b4db2a8aa2149..02abb186cc8f9 100644 --- a/Mathlib/Geometry/Manifold/VectorBundle/Basic.lean +++ b/Mathlib/Geometry/Manifold/VectorBundle/Basic.lean @@ -175,7 +175,7 @@ theorem contMDiffWithinAt_totalSpace (f : M → TotalSpace F E) {s : Set M} {x simp (config := { singlePass := true }) only [contMDiffWithinAt_iff_target] rw [and_and_and_comm, ← FiberBundle.continuousWithinAt_totalSpace, and_congr_right_iff] intro hf - simp_rw [modelWithCornersSelf_prod, FiberBundle.extChartAt, Function.comp, + simp_rw [modelWithCornersSelf_prod, FiberBundle.extChartAt, Function.comp_def, PartialEquiv.trans_apply, PartialEquiv.prod_coe, PartialEquiv.refl_coe, extChartAt_self_apply, modelWithCornersSelf_coe, Function.id_def, ← chartedSpaceSelf_prod] refine (contMDiffWithinAt_prod_iff _).trans (and_congr ?_ Iff.rfl) diff --git a/Mathlib/Geometry/RingedSpace/LocallyRingedSpace.lean b/Mathlib/Geometry/RingedSpace/LocallyRingedSpace.lean index 340c62513dedd..75e798757aa2f 100644 --- a/Mathlib/Geometry/RingedSpace/LocallyRingedSpace.lean +++ b/Mathlib/Geometry/RingedSpace/LocallyRingedSpace.lean @@ -14,7 +14,7 @@ stalks are local rings), and morphisms between these (morphisms in `SheafedSpace `IsLocalRingHom` on the stalk maps). -/ --- Explicit universe annotations were used in this file to improve perfomance #12737 +-- Explicit universe annotations were used in this file to improve performance #12737 universe u diff --git a/Mathlib/Geometry/RingedSpace/OpenImmersion.lean b/Mathlib/Geometry/RingedSpace/OpenImmersion.lean index 6862e4b4c144c..5c5349f4adc95 100644 --- a/Mathlib/Geometry/RingedSpace/OpenImmersion.lean +++ b/Mathlib/Geometry/RingedSpace/OpenImmersion.lean @@ -69,7 +69,7 @@ class PresheafedSpace.IsOpenImmersion {X Y : PresheafedSpace C} (f : X ⟶ Y) : /-- the underlying continuous map of underlying spaces from the source to an open subset of the target. -/ base_open : OpenEmbedding f.base - /-- the underlying sheaf morphism is an isomorphism on each open subset-/ + /-- the underlying sheaf morphism is an isomorphism on each open subset -/ c_iso : ∀ U : Opens X, IsIso (f.c.app (op (base_open.isOpenMap.functor.obj U))) /-- A morphism of SheafedSpaces is an open immersion if it is an open immersion as a morphism @@ -515,16 +515,17 @@ open CategoryTheory.Limits.WalkingCospan section ToSheafedSpace variable {X : PresheafedSpace C} (Y : SheafedSpace C) -variable (f : X ⟶ Y.toPresheafedSpace) [H : IsOpenImmersion f] /-- If `X ⟶ Y` is an open immersion, and `Y` is a SheafedSpace, then so is `X`. -/ -def toSheafedSpace : SheafedSpace C where +def toSheafedSpace (f : X ⟶ Y.toPresheafedSpace) [H : IsOpenImmersion f] : SheafedSpace C where IsSheaf := by apply TopCat.Presheaf.isSheaf_of_iso (sheafIsoOfIso (isoRestrict f).symm).symm apply TopCat.Sheaf.pushforward_sheaf_of_sheaf exact (Y.restrict H.base_open).IsSheaf toPresheafedSpace := X +variable (f : X ⟶ Y.toPresheafedSpace) [H : IsOpenImmersion f] + @[simp] theorem toSheafedSpace_toPresheafedSpace : (toSheafedSpace Y f).toPresheafedSpace = X := rfl diff --git a/Mathlib/Geometry/RingedSpace/PresheafedSpace/Gluing.lean b/Mathlib/Geometry/RingedSpace/PresheafedSpace/Gluing.lean index be48cb8051370..b5ac976467db8 100644 --- a/Mathlib/Geometry/RingedSpace/PresheafedSpace/Gluing.lean +++ b/Mathlib/Geometry/RingedSpace/PresheafedSpace/Gluing.lean @@ -37,7 +37,7 @@ Analogous results are also provided for `SheafedSpace` and `LocallyRingedSpace`. ## Implementation details -Almost the whole file is dedicated to showing tht `ι i` is an open immersion. The fact that +Almost the whole file is dedicated to showing that `ι i` is an open immersion. The fact that this is an open embedding of topological spaces follows from `Mathlib/Topology/Gluing.lean`, and it remains to construct `Γ(𝒪_{U_i}, U) ⟶ Γ(𝒪_X, ι i '' U)` for each `U ⊆ U i`. Since `Γ(𝒪_X, ι i '' U)` is the limit of `diagram_over_open`, the components of the structure diff --git a/Mathlib/Geometry/RingedSpace/PresheafedSpace/HasColimits.lean b/Mathlib/Geometry/RingedSpace/PresheafedSpace/HasColimits.lean index 1a3dd8fdd7585..91683f96c4d14 100644 --- a/Mathlib/Geometry/RingedSpace/PresheafedSpace/HasColimits.lean +++ b/Mathlib/Geometry/RingedSpace/PresheafedSpace/HasColimits.lean @@ -97,7 +97,7 @@ def pushforwardDiagramToColimit (F : J ⥤ PresheafedSpace.{_, _, v} C) : obj j := op (colimit.ι (F ⋙ PresheafedSpace.forget C) j _* (F.obj j).presheaf) map {j j'} f := ((pushforward C (colimit.ι (F ⋙ PresheafedSpace.forget C) j')).map (F.map f).c ≫ - (Pushforward.comp ((F ⋙ PresheafedSpace.forget C).map f) + (Pushforward.comp ((F ⋙ PresheafedSpace.forget C).map f) (colimit.ι (F ⋙ PresheafedSpace.forget C) j') (F.obj j).presheaf).inv ≫ (pushforwardEq (colimit.w (F ⋙ PresheafedSpace.forget C) f) (F.obj j).presheaf).hom).op map_id j := by diff --git a/Mathlib/GroupTheory/CommutingProbability.lean b/Mathlib/GroupTheory/CommutingProbability.lean index a0a76793010e2..50ea33f499459 100644 --- a/Mathlib/GroupTheory/CommutingProbability.lean +++ b/Mathlib/GroupTheory/CommutingProbability.lean @@ -6,6 +6,7 @@ Authors: Thomas Browning import Mathlib.GroupTheory.Abelianization import Mathlib.GroupTheory.GroupAction.CardCommute import Mathlib.GroupTheory.SpecificGroups.Dihedral +import Mathlib.Tactic.FieldSimp import Mathlib.Tactic.LinearCombination import Mathlib.Tactic.Qify @@ -96,7 +97,7 @@ variable [Finite G] (H : Subgroup G) theorem Subgroup.commProb_subgroup_le : commProb H ≤ commProb G * (H.index : ℚ) ^ 2 := by /- After rewriting with `commProb_def`, we reduce to showing that `G` has at least as many commuting pairs as `H`. -/ - rw [commProb_def, commProb_def, div_le_iff, mul_assoc, ← mul_pow, ← Nat.cast_mul, + rw [commProb_def, commProb_def, div_le_iff₀, mul_assoc, ← mul_pow, ← Nat.cast_mul, mul_comm H.index, H.card_mul_index, div_mul_cancel₀, Nat.cast_le] · refine Finite.card_le_of_injective (fun p ↦ ⟨⟨p.1.1, p.1.2⟩, Subtype.ext_iff.mp p.2⟩) ?_ exact fun p q h ↦ by simpa only [Subtype.ext_iff, Prod.ext_iff] using h @@ -106,7 +107,7 @@ theorem Subgroup.commProb_subgroup_le : commProb H ≤ commProb G * (H.index : theorem Subgroup.commProb_quotient_le [H.Normal] : commProb (G ⧸ H) ≤ commProb G * Nat.card H := by /- After rewriting with `commProb_def'`, we reduce to showing that `G` has at least as many conjugacy classes as `G ⧸ H`. -/ - rw [commProb_def', commProb_def', div_le_iff, mul_assoc, ← Nat.cast_mul, ← Subgroup.index, + rw [commProb_def', commProb_def', div_le_iff₀, mul_assoc, ← Nat.cast_mul, ← Subgroup.index, H.card_mul_index, div_mul_cancel₀, Nat.cast_le] · apply Finite.card_le_of_surjective show Function.Surjective (ConjClasses.map (QuotientGroup.mk' H)) @@ -164,8 +165,8 @@ lemma reciprocalFactors_odd {n : ℕ} (h1 : n ≠ 1) (h2 : Odd n) : reciprocalFactors n = n % 4 * n :: reciprocalFactors (n / 4 + 1) := by have h0 : n ≠ 0 := by rintro rfl - norm_num at h2 - rw [reciprocalFactors, dif_neg h0, dif_neg h1, if_neg (Nat.odd_iff_not_even.mp h2)] + norm_num [← Nat.not_even_iff_odd] at h2 + rw [reciprocalFactors, dif_neg h0, dif_neg h1, if_neg (Nat.not_even_iff_odd.2 h2)] /-- A finite product of Dihedral groups. -/ abbrev Product (l : List ℕ) : Type := diff --git a/Mathlib/GroupTheory/Congruence/Basic.lean b/Mathlib/GroupTheory/Congruence/Basic.lean index f9137be6f7410..a3011ab4ba7d6 100644 --- a/Mathlib/GroupTheory/Congruence/Basic.lean +++ b/Mathlib/GroupTheory/Congruence/Basic.lean @@ -151,7 +151,7 @@ theorem rel_mk {s : Setoid M} {h a b} : Con.mk s h a b ↔ r a b := @[to_additive "Given a type `M` with an addition, `x, y ∈ M`, and an additive congruence relation `c` on `M`, `(x, y) ∈ M × M` iff `x` is related to `y` by `c`."] instance : Membership (M × M) (Con M) := - ⟨fun x c => c x.1 x.2⟩ + ⟨fun c x => c x.1 x.2⟩ variable {c} @@ -377,7 +377,7 @@ theorem coe_sInf (S : Set (Con M)) : @[to_additive (attr := simp, norm_cast)] theorem coe_iInf {ι : Sort*} (f : ι → Con M) : ⇑(iInf f) = ⨅ i, ⇑(f i) := by - rw [iInf, coe_sInf, ← Set.range_comp, sInf_range, Function.comp] + rw [iInf, coe_sInf, ← Set.range_comp, sInf_range, Function.comp_def] @[to_additive] instance : PartialOrder (Con M) where diff --git a/Mathlib/GroupTheory/CoprodI.lean b/Mathlib/GroupTheory/CoprodI.lean index 71732e3b60cb4..e0f94293ea1b6 100644 --- a/Mathlib/GroupTheory/CoprodI.lean +++ b/Mathlib/GroupTheory/CoprodI.lean @@ -772,9 +772,10 @@ theorem mulHead_head {i j : ι} (w : NeWord M i j) (x : M i) (hnotone : x * w.he theorem mulHead_prod {i j : ι} (w : NeWord M i j) (x : M i) (hnotone : x * w.head ≠ 1) : (mulHead w x hnotone).prod = of x * w.prod := by unfold mulHead - induction' w with _ _ _ _ _ _ _ _ _ _ w_ih_w₁ w_ih_w₂ - · simp [mulHead, replaceHead] - · specialize w_ih_w₁ _ hnotone + induction w with + | singleton => simp [mulHead, replaceHead] + | append _ _ _ w_ih_w₁ w_ih_w₂ => + specialize w_ih_w₁ _ hnotone clear w_ih_w₂ simp? [replaceHead, ← mul_assoc] at * says simp only [replaceHead, head, append_prod, ← mul_assoc] at * diff --git a/Mathlib/GroupTheory/Coset/Basic.lean b/Mathlib/GroupTheory/Coset/Basic.lean index b25a17f71817f..51d17eb7794d6 100644 --- a/Mathlib/GroupTheory/Coset/Basic.lean +++ b/Mathlib/GroupTheory/Coset/Basic.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Mitchell Rowett, Scott Morrison -/ import Mathlib.Algebra.Quotient -import Mathlib.Algebra.Group.Subgroup.Actions import Mathlib.Algebra.Group.Subgroup.MulOpposite import Mathlib.GroupTheory.GroupAction.Basic diff --git a/Mathlib/GroupTheory/Coxeter/Basic.lean b/Mathlib/GroupTheory/Coxeter/Basic.lean index fdbcf71b5c51d..fd14569331ee8 100644 --- a/Mathlib/GroupTheory/Coxeter/Basic.lean +++ b/Mathlib/GroupTheory/Coxeter/Basic.lean @@ -399,7 +399,7 @@ theorem alternatingWord_succ' (i i' : B) (m : ℕ) : · rw [alternatingWord] nth_rw 1 [ih i' i] rw [alternatingWord] - simp [Nat.even_add_one] + simp [Nat.even_add_one, ← Nat.not_even_iff_odd] @[simp] theorem length_alternatingWord (i i' : B) (m : ℕ) : @@ -437,10 +437,10 @@ theorem prod_alternatingWord_eq_prod_alternatingWord_sub (i i' : B) (m : ℕ) (h repeat rw [Int.mul_ediv_cancel _ (by norm_num)] rw [zpow_sub, zpow_natCast, simple_mul_simple_pow' cs i i', ← inv_zpow] simp - · have : ¬Even (2 * k + 1) := Int.odd_iff_not_even.mp ⟨k, rfl⟩ + · have : ¬Even (2 * k + 1) := Int.not_even_iff_odd.2 ⟨k, rfl⟩ rw [if_neg this] have : ¬Even (↑(M i i') * 2 - (2 * k + 1)) := - Int.odd_iff_not_even.mp ⟨↑(M i i') - k - 1, by ring⟩ + Int.not_even_iff_odd.2 ⟨↑(M i i') - k - 1, by ring⟩ rw [if_neg this] rw [(by ring : ↑(M i i') * 2 - (2 * k + 1) = -1 + (-k + ↑(M i i')) * 2), diff --git a/Mathlib/GroupTheory/Coxeter/Inversion.lean b/Mathlib/GroupTheory/Coxeter/Inversion.lean index 4901cbdf6ff8b..b07693855316a 100644 --- a/Mathlib/GroupTheory/Coxeter/Inversion.lean +++ b/Mathlib/GroupTheory/Coxeter/Inversion.lean @@ -300,13 +300,11 @@ theorem rightInvSeq_drop (ω : List B) (j : ℕ) : theorem leftInvSeq_take (ω : List B) (j : ℕ) : lis (ω.take j) = (lis ω).take j := by - obtain le | ge := Nat.le_or_ge j ω.length - · simp only [leftInvSeq_eq_reverse_rightInvSeq_reverse] - rw [List.take_reverse (by simpa)] - nth_rw 1 [← List.reverse_reverse ω] - rw [List.take_reverse (by simpa)] - simp [rightInvSeq_drop] - · rw [take_of_length_le ge, take_of_length_le (by simpa)] + simp only [leftInvSeq_eq_reverse_rightInvSeq_reverse] + rw [List.take_reverse] + nth_rw 1 [← List.reverse_reverse ω] + rw [List.take_reverse] + simp [rightInvSeq_drop] theorem isReflection_of_mem_rightInvSeq (ω : List B) {t : W} (ht : t ∈ ris ω) : cs.IsReflection t := by diff --git a/Mathlib/GroupTheory/DoubleCoset.lean b/Mathlib/GroupTheory/DoubleCoset.lean index 1d710162e3e55..126c81594b8d8 100644 --- a/Mathlib/GroupTheory/DoubleCoset.lean +++ b/Mathlib/GroupTheory/DoubleCoset.lean @@ -74,8 +74,8 @@ def Quotient (H K : Set G) : Type _ := theorem rel_iff {H K : Subgroup G} {x y : G} : (setoid ↑H ↑K).Rel x y ↔ ∃ a ∈ H, ∃ b ∈ K, y = a * x * b := Iff.trans - ⟨fun hxy => (congr_arg _ hxy).mpr (mem_doset_self H K y), fun hxy => (doset_eq_of_mem hxy).symm⟩ - mem_doset + ⟨fun (hxy : doset x H K = doset y H K) => hxy ▸ mem_doset_self H K y, + fun hxy => (doset_eq_of_mem hxy).symm⟩ mem_doset theorem bot_rel_eq_leftRel (H : Subgroup G) : (setoid ↑(⊥ : Subgroup G) ↑H).Rel = (QuotientGroup.leftRel H).Rel := by diff --git a/Mathlib/GroupTheory/Exponent.lean b/Mathlib/GroupTheory/Exponent.lean index 801c4d8d5a2c0..94ce55d4cf069 100644 --- a/Mathlib/GroupTheory/Exponent.lean +++ b/Mathlib/GroupTheory/Exponent.lean @@ -8,7 +8,7 @@ import Mathlib.Algebra.GCDMonoid.Finset import Mathlib.Algebra.GCDMonoid.Nat import Mathlib.Data.Nat.Factorization.Basic import Mathlib.Tactic.Peel -import Mathlib.Algebra.Order.Archimedean.Basic +import Mathlib.Algebra.Order.BigOperators.Ring.Finset /-! # Exponent of a group diff --git a/Mathlib/GroupTheory/FixedPointFree.lean b/Mathlib/GroupTheory/FixedPointFree.lean index 49ae5c66a0f12..2f9fb7c2c40f9 100644 --- a/Mathlib/GroupTheory/FixedPointFree.lean +++ b/Mathlib/GroupTheory/FixedPointFree.lean @@ -84,7 +84,7 @@ theorem odd_card_of_involutive (hφ : FixedPointFree φ) (h2 : Function.Involuti Odd (Nat.card G) := by have := Fintype.ofFinite G by_contra h - rw [← Nat.even_iff_not_odd, even_iff_two_dvd, Nat.card_eq_fintype_card] at h + rw [Nat.not_odd_iff_even, even_iff_two_dvd, Nat.card_eq_fintype_card] at h obtain ⟨g, hg⟩ := exists_prime_orderOf_dvd_card 2 h exact hφ.orderOf_ne_two_of_involutive h2 g hg diff --git a/Mathlib/GroupTheory/FreeGroup/Basic.lean b/Mathlib/GroupTheory/FreeGroup/Basic.lean index 74da573c0472e..0718b7ca18057 100644 --- a/Mathlib/GroupTheory/FreeGroup/Basic.lean +++ b/Mathlib/GroupTheory/FreeGroup/Basic.lean @@ -312,8 +312,8 @@ theorem inv_of_red_of_ne {x1 b1 x2 b2} (H1 : (x1, b1) ≠ (x2, b2)) open List -- for <+ notation @[to_additive] -theorem Step.sublist (H : Red.Step L₁ L₂) : Sublist L₂ L₁ := by - cases H; simp; constructor; constructor; rfl +theorem Step.sublist (H : Red.Step L₁ L₂) : L₂ <+ L₁ := by + cases H; simp /-- If `w₁ w₂` are words such that `w₁` reduces to `w₂`, then `w₂` is a sublist of `w₁`. -/ @[to_additive "If `w₁ w₂` are words such that `w₁` reduces to `w₂`, then `w₂` is a sublist of @@ -383,8 +383,8 @@ theorem eqvGen_step_iff_join_red : EqvGen Red.Step L₁ L₂ ↔ Join Red L₁ L (fun h => have : EqvGen (Join Red) L₁ L₂ := h.mono fun _ _ => join_red_of_step equivalence_join_red.eqvGen_iff.1 this) - (join_of_equivalence (EqvGen.is_equivalence _) fun _ _ => - reflTransGen_of_equivalence (EqvGen.is_equivalence _) EqvGen.rel) + (join_of_equivalence (Relation.EqvGen.is_equivalence _) fun _ _ => + reflTransGen_of_equivalence (Relation.EqvGen.is_equivalence _) EqvGen.rel) end FreeGroup @@ -462,7 +462,7 @@ theorem invRev_length : (invRev L₁).length = L₁.length := by simp [invRev] @[to_additive (attr := simp)] theorem invRev_invRev : invRev (invRev L₁) = L₁ := by - simp [invRev, List.map_reverse, (· ∘ ·)] + simp [invRev, List.map_reverse, Function.comp_def] @[to_additive (attr := simp)] theorem invRev_empty : invRev ([] : List (α × Bool)) = [] := @@ -538,7 +538,7 @@ def of (x : α) : FreeGroup α := @[to_additive] theorem Red.exact : mk L₁ = mk L₂ ↔ Join Red L₁ L₂ := calc - mk L₁ = mk L₂ ↔ EqvGen Red.Step L₁ L₂ := Iff.intro (Quot.exact _) Quot.EqvGen_sound + mk L₁ = mk L₂ ↔ EqvGen Red.Step L₁ L₂ := Iff.intro Quot.eqvGen_exact Quot.eqvGen_sound _ ↔ Join Red L₁ L₂ := eqvGen_step_iff_join_red /-- The canonical map from the type to the free group is an injection. -/ @@ -669,7 +669,7 @@ theorem map.id' (x : FreeGroup α) : map (fun z => z) x = x := @[to_additive] theorem map.comp {γ : Type w} (f : α → β) (g : β → γ) (x) : map g (map f x) = map (g ∘ f) x := by - rcases x with ⟨L⟩; simp [(· ∘ ·)] + rcases x with ⟨L⟩; simp [Function.comp_def] @[to_additive (attr := simp)] theorem map.of {x} : map f (of x) = of (f x) := diff --git a/Mathlib/GroupTheory/FreeGroup/IsFreeGroup.lean b/Mathlib/GroupTheory/FreeGroup/IsFreeGroup.lean index ff82a3c54c8d9..5999f4a20b721 100644 --- a/Mathlib/GroupTheory/FreeGroup/IsFreeGroup.lean +++ b/Mathlib/GroupTheory/FreeGroup/IsFreeGroup.lean @@ -149,7 +149,7 @@ def ofLift {G : Type u} [Group G] (X : Type u) (of : X → G) /-- If a group satisfies the universal property of a free group with respect to a given type, then it admits a free group basis based on this type. Here -the universal property is expressed as in `IsFreeGroup.unique_lift`. -/ +the universal property is expressed as in `IsFreeGroup.unique_lift`. -/ def ofUniqueLift {G : Type u} [Group G] (X : Type u) (of : X → G) (h : ∀ {H : Type u} [Group H] (f : X → H), ∃! F : G →* H, ∀ a, F (of a) = f a) : FreeGroupBasis X G := @@ -212,7 +212,7 @@ theorem ext_hom ⦃f g : G →* H⦄ (h : ∀ a : Generators G, f (of a) = g (of group extends in a unique way to a homomorphism from `G`. Note that since `IsFreeGroup.lift` is expressed as a bijection, it already -expresses the universal property. -/ +expresses the universal property. -/ theorem unique_lift (f : Generators G → H) : ∃! F : G →* H, ∀ a, F (of a) = f a := by simpa only [Function.funext_iff] using lift.symm.bijective.existsUnique f @@ -226,7 +226,7 @@ lemma ofLift {G : Type u} [Group G] (X : Type u) (of : X → G) (FreeGroupBasis.ofLift X of lift lift_of).isFreeGroup /-- If a group satisfies the universal property of a free group with respect to a given type, then -it is free. Here the universal property is expressed as in `IsFreeGroup.unique_lift`. -/ +it is free. Here the universal property is expressed as in `IsFreeGroup.unique_lift`. -/ lemma ofUniqueLift {G : Type u} [Group G] (X : Type u) (of : X → G) (h : ∀ {H : Type u} [Group H] (f : X → H), ∃! F : G →* H, ∀ a, F (of a) = f a) : IsFreeGroup G := diff --git a/Mathlib/GroupTheory/GroupAction/Basic.lean b/Mathlib/GroupTheory/GroupAction/Basic.lean index 70bf6218e1236..cc847556ec7f8 100644 --- a/Mathlib/GroupTheory/GroupAction/Basic.lean +++ b/Mathlib/GroupTheory/GroupAction/Basic.lean @@ -9,7 +9,6 @@ import Mathlib.Data.Fintype.Card import Mathlib.Data.Set.Finite import Mathlib.Data.Set.Pointwise.SMul import Mathlib.Data.Setoid.Basic -import Mathlib.GroupTheory.GroupAction.Group /-! # Basic properties of group actions @@ -328,6 +327,10 @@ theorem mem_orbit_smul (g : G) (a : α) : a ∈ orbit G (g • a) := by theorem smul_mem_orbit_smul (g h : G) (a : α) : g • a ∈ orbit G (h • a) := by simp only [orbit_smul, mem_orbit] +@[to_additive] +instance instMulAction (H : Subgroup G) : MulAction H α := + inferInstanceAs (MulAction H.toSubmonoid α) + @[to_additive] lemma orbit_subgroup_subset (H : Subgroup G) (a : α) : orbit H a ⊆ orbit G a := orbit_submonoid_subset H.toSubmonoid a @@ -346,11 +349,10 @@ lemma mem_subgroup_orbit_iff {H : Subgroup G} {x : α} {a b : orbit G x} : a ∈ MulAction.orbit H b ↔ (a : α) ∈ MulAction.orbit H (b : α) := by refine ⟨fun h ↦ ?_, fun h ↦ ?_⟩ · rcases h with ⟨g, rfl⟩ - simp_rw [Submonoid.smul_def, Subgroup.coe_toSubmonoid, orbit.coe_smul, ← Submonoid.smul_def] exact MulAction.mem_orbit _ g · rcases h with ⟨g, h⟩ - simp_rw [Submonoid.smul_def, Subgroup.coe_toSubmonoid, ← orbit.coe_smul, - ← Submonoid.smul_def, ← Subtype.ext_iff] at h + dsimp at h + erw [← orbit.coe_smul, ← Subtype.ext_iff] at h subst h exact MulAction.mem_orbit _ g @@ -564,12 +566,11 @@ lemma orbitRel.Quotient.mem_subgroup_orbit_iff {H : Subgroup G} {x : orbitRel.Qu {a b : x.orbit} : (a : α) ∈ MulAction.orbit H (b : α) ↔ a ∈ MulAction.orbit H b := by refine ⟨fun h ↦ ?_, fun h ↦ ?_⟩ · rcases h with ⟨g, h⟩ - simp_rw [Submonoid.smul_def, Subgroup.coe_toSubmonoid, ← orbit.coe_smul, - ← Submonoid.smul_def, ← Subtype.ext_iff] at h + dsimp at h + erw [← orbit.coe_smul, ← Subtype.ext_iff] at h subst h exact MulAction.mem_orbit _ g · rcases h with ⟨g, rfl⟩ - simp_rw [Submonoid.smul_def, Subgroup.coe_toSubmonoid, orbit.coe_smul, ← Submonoid.smul_def] exact MulAction.mem_orbit _ g @[to_additive] @@ -771,6 +772,7 @@ theorem le_stabilizer_iff_smul_le (s : Set α) (H : Subgroup G) : theorem mem_stabilizer_of_finite_iff_smul_le (s : Set α) (hs : s.Finite) (g : G) : g ∈ stabilizer G s ↔ g • s ⊆ s := by haveI : Fintype s := Set.Finite.fintype hs + haveI : Finite (g • s : Set α) := Finite.Set.finite_image .. haveI : Fintype (g • s : Set α) := Fintype.ofFinite _ rw [mem_stabilizer_iff] constructor diff --git a/Mathlib/GroupTheory/GroupAction/Blocks.lean b/Mathlib/GroupTheory/GroupAction/Blocks.lean index c82066c332d33..9fbae888310e9 100644 --- a/Mathlib/GroupTheory/GroupAction/Blocks.lean +++ b/Mathlib/GroupTheory/GroupAction/Blocks.lean @@ -8,6 +8,7 @@ import Mathlib.Data.Setoid.Partition import Mathlib.GroupTheory.GroupAction.Basic import Mathlib.GroupTheory.GroupAction.Pointwise import Mathlib.GroupTheory.GroupAction.SubMulAction +import Mathlib.Algebra.Group.Subgroup.Actions /-! # Blocks @@ -135,7 +136,8 @@ theorem IsBlock.def_one {B : Set X} : rw [Set.disjoint_iff] at h ⊢ rintro x hx suffices g'⁻¹ • x ∈ (g'⁻¹ * g) • B ∩ B by apply h this - simp only [Set.mem_inter_iff, ← Set.mem_smul_set_iff_inv_smul_mem, ← smul_smul, smul_inv_smul] + rw [Set.mem_inter_iff] + simp only [← smul_smul, ← Set.mem_smul_set_iff_inv_smul_mem, smul_inv_smul] exact hx theorem IsBlock.mk_notempty_one {B : Set X} : @@ -356,11 +358,11 @@ lemma smul_orbit_eq_orbit_smul (N : Subgroup G) [nN : N.Normal] (a : X) (g : G) constructor · rintro ⟨⟨k, hk⟩, rfl⟩ use ⟨g * k * g⁻¹, nN.conj_mem k hk g⟩ - simp only [Submonoid.mk_smul] + simp only [Subgroup.mk_smul] rw [smul_smul, inv_mul_cancel_right, ← smul_smul] · rintro ⟨⟨k, hk⟩, rfl⟩ use ⟨g⁻¹ * k * g, nN.conj_mem' k hk g⟩ - simp only [Submonoid.mk_smul] + simp only [Subgroup.mk_smul] simp only [← mul_assoc, ← smul_smul, smul_inv_smul, inv_inv] /-- An orbit of a normal subgroup is a block -/ @@ -396,7 +398,7 @@ theorem IsBlock.of_orbit {H : Subgroup G} {a : X} (hH : stabilizer G a ≤ H) : simp_rw [IsBlock.def_one, or_iff_not_imp_right, Set.not_disjoint_iff] rintro g ⟨-, ⟨-, ⟨h₁, rfl⟩, h⟩, ⟨h₂, rfl⟩⟩ suffices g ∈ H by - rw [← Subgroup.coe_mk H g this, ← H.smul_def, smul_orbit (⟨g, this⟩ : H) a] + rw [← Subgroup.coe_mk H g this, ← H.toSubmonoid.smul_def, smul_orbit (⟨g, this⟩ : H) a] rw [← mul_mem_cancel_left h₂⁻¹.2, ← mul_mem_cancel_right h₁.2] apply hH simp only [mem_stabilizer_iff, InvMemClass.coe_inv, mul_smul, inv_smul_eq_iff] @@ -419,7 +421,7 @@ theorem IsBlock.orbit_stabilizer_eq ext x constructor · rintro ⟨⟨k, k_mem⟩, rfl⟩ - simp only [Submonoid.mk_smul] + simp only [Subgroup.mk_smul] rw [← k_mem, Set.smul_mem_smul_set_iff] exact ha · intro hx @@ -434,11 +436,11 @@ theorem stabilizer_orbit_eq {a : X} {H : Subgroup G} (hH : stabilizer G a ≤ H) constructor · intro hg obtain ⟨-, ⟨b, rfl⟩, h⟩ := hg.symm ▸ mem_orbit_self a - simp_rw [H.smul_def, ← mul_smul, ← mem_stabilizer_iff] at h + simp_rw [H.toSubmonoid.smul_def, ← mul_smul, ← mem_stabilizer_iff] at h exact (mul_mem_cancel_right b.2).mp (hH h) · intro hg - rw [mem_stabilizer_iff, ← Subgroup.coe_mk H g hg, ← Submonoid.smul_def] - apply smul_orbit + rw [mem_stabilizer_iff, ← Subgroup.coe_mk H g hg, ← Submonoid.smul_def (S := H.toSubmonoid)] + apply smul_orbit (G := H) variable (G) diff --git a/Mathlib/GroupTheory/GroupAction/FixingSubgroup.lean b/Mathlib/GroupTheory/GroupAction/FixingSubgroup.lean index 4fd82a9683bf7..afcac247ac820 100644 --- a/Mathlib/GroupTheory/GroupAction/FixingSubgroup.lean +++ b/Mathlib/GroupTheory/GroupAction/FixingSubgroup.lean @@ -3,7 +3,6 @@ Copyright (c) 2022 Antoine Chambert-Loir. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Antoine Chambert-Loir -/ -import Mathlib.Algebra.Group.Subgroup.Actions import Mathlib.GroupTheory.GroupAction.Basic import Mathlib.GroupTheory.GroupAction.FixedPoints diff --git a/Mathlib/GroupTheory/GroupAction/Group.lean b/Mathlib/GroupTheory/GroupAction/Group.lean deleted file mode 100644 index ae6ba4516d404..0000000000000 --- a/Mathlib/GroupTheory/GroupAction/Group.lean +++ /dev/null @@ -1,112 +0,0 @@ -/- -Copyright (c) 2018 Chris Hughes. All rights reserved. -Released under Apache 2.0 license as described in the file LICENSE. -Authors: Chris Hughes --/ -import Mathlib.Algebra.Group.Action.Basic -import Mathlib.Algebra.Group.Invertible.Basic -import Mathlib.Algebra.GroupWithZero.Action.Units -import Mathlib.Algebra.GroupWithZero.Units.Basic -import Mathlib.Algebra.SMulWithZero - -/-! -# Group actions applied to various types of group - -This file contains lemmas about `SMul` on `GroupWithZero`, and `Group`. --/ - - -universe u v w - -variable {α : Type u} {β : Type v} {γ : Type w} - -section MulAction - -/-- `Monoid.toMulAction` is faithful on nontrivial cancellative monoids with zero. -/ -instance CancelMonoidWithZero.faithfulSMul [CancelMonoidWithZero α] [Nontrivial α] : - FaithfulSMul α α := - ⟨fun h => mul_left_injective₀ one_ne_zero (h 1)⟩ - -section Gwz - -variable [GroupWithZero α] [MulAction α β] {a : α} - -@[simp] -theorem inv_smul_smul₀ {c : α} (hc : c ≠ 0) (x : β) : c⁻¹ • c • x = x := - inv_smul_smul (Units.mk0 c hc) x - -@[simp] -theorem smul_inv_smul₀ {c : α} (hc : c ≠ 0) (x : β) : c • c⁻¹ • x = x := - smul_inv_smul (Units.mk0 c hc) x - -theorem inv_smul_eq_iff₀ {a : α} (ha : a ≠ 0) {x y : β} : a⁻¹ • x = y ↔ x = a • y := - ⟨fun h => by rw [← h, smul_inv_smul₀ ha], fun h => by rw [h, inv_smul_smul₀ ha]⟩ - -theorem eq_inv_smul_iff₀ {a : α} (ha : a ≠ 0) {x y : β} : x = a⁻¹ • y ↔ a • x = y := - (MulAction.toPerm (Units.mk0 a ha)).eq_symm_apply - -@[simp] -theorem Commute.smul_right_iff₀ [Mul β] [SMulCommClass α β β] [IsScalarTower α β β] {a b : β} - {c : α} (hc : c ≠ 0) : Commute a (c • b) ↔ Commute a b := - Commute.smul_right_iff (g := Units.mk0 c hc) - -@[simp] -theorem Commute.smul_left_iff₀ [Mul β] [SMulCommClass α β β] [IsScalarTower α β β] {a b : β} {c : α} - (hc : c ≠ 0) : Commute (c • a) b ↔ Commute a b := - Commute.smul_left_iff (g := Units.mk0 c hc) - -/-- Right scalar multiplication as an order isomorphism. -/ -@[simps] def Equiv.smulRight (ha : a ≠ 0) : β ≃ β where - toFun b := a • b - invFun b := a⁻¹ • b - left_inv := inv_smul_smul₀ ha - right_inv := smul_inv_smul₀ ha - -end Gwz - -end MulAction - -section DistribMulAction - -section Group - -variable [Group α] [AddMonoid β] [DistribMulAction α β] -variable (β) - -variable (α) - -/-- Each non-zero element of a `GroupWithZero` defines an additive monoid isomorphism of an -`AddMonoid` on which it acts distributively. -This is a stronger version of `DistribMulAction.toAddMonoidHom`. -/ -def DistribMulAction.toAddEquiv₀ {α : Type*} (β : Type*) [GroupWithZero α] [AddMonoid β] - [DistribMulAction α β] (x : α) (hx : x ≠ 0) : β ≃+ β := - { DistribMulAction.toAddMonoidHom β x with - invFun := fun b ↦ x⁻¹ • b - left_inv := fun b ↦ inv_smul_smul₀ hx b - right_inv := fun b ↦ smul_inv_smul₀ hx b } - -variable {α β} - -theorem smul_eq_zero_iff_eq (a : α) {x : β} : a • x = 0 ↔ x = 0 := - ⟨fun h => by rw [← inv_smul_smul a x, h, smul_zero], fun h => h.symm ▸ smul_zero _⟩ - -theorem smul_ne_zero_iff_ne (a : α) {x : β} : a • x ≠ 0 ↔ x ≠ 0 := - not_congr <| smul_eq_zero_iff_eq a - -end Group - -end DistribMulAction - -namespace IsUnit - -section DistribMulAction - -variable [Monoid α] [AddMonoid β] [DistribMulAction α β] - -@[simp] -theorem smul_eq_zero {u : α} (hu : IsUnit u) {x : β} : u • x = 0 ↔ x = 0 := - (Exists.elim hu) fun u hu => hu ▸ show u • x = 0 ↔ x = 0 from smul_eq_zero_iff_eq u - -end DistribMulAction - -end IsUnit diff --git a/Mathlib/GroupTheory/GroupAction/Hom.lean b/Mathlib/GroupTheory/GroupAction/Hom.lean index d843581eba0b4..2a9db62dd963a 100644 --- a/Mathlib/GroupTheory/GroupAction/Hom.lean +++ b/Mathlib/GroupTheory/GroupAction/Hom.lean @@ -59,7 +59,7 @@ variable (Z : Type*) [SMul P Z] /-- Equivariant functions : When `φ : M → N` is a function, and types `X` and `Y` are endowed with actions of `M` and `N`, -a function `f : X → Y` is `φ`-equivariant if `f (m • x) = (φ m) • (f x)`. -/ +a function `f : X → Y` is `φ`-equivariant if `f (m • x) = (φ m) • (f x)`. -/ -- Porting note(#5171): this linter isn't ported yet. -- @[nolint has_nonempty_instance] structure MulActionHom where diff --git a/Mathlib/GroupTheory/GroupAction/Quotient.lean b/Mathlib/GroupTheory/GroupAction/Quotient.lean index 8a484cbcfe58d..7f128130a1471 100644 --- a/Mathlib/GroupTheory/GroupAction/Quotient.lean +++ b/Mathlib/GroupTheory/GroupAction/Quotient.lean @@ -9,6 +9,7 @@ import Mathlib.GroupTheory.GroupAction.ConjAct import Mathlib.GroupTheory.GroupAction.Hom import Mathlib.GroupTheory.Coset.Basic import Mathlib.GroupTheory.Commutator.Basic +import Mathlib.Algebra.Group.Subgroup.Actions /-! # Properties of group actions involving quotient groups diff --git a/Mathlib/GroupTheory/GroupAction/SubMulAction.lean b/Mathlib/GroupTheory/GroupAction/SubMulAction.lean index 0d6267151258e..6f4c858afeb02 100644 --- a/Mathlib/GroupTheory/GroupAction/SubMulAction.lean +++ b/Mathlib/GroupTheory/GroupAction/SubMulAction.lean @@ -153,7 +153,7 @@ end OfTower end SetLike -/-- A SubMulAction is a set which is closed under scalar multiplication. -/ +/-- A SubMulAction is a set which is closed under scalar multiplication. -/ structure SubMulAction (R : Type u) (M : Type v) [SMul R M] : Type v where /-- The underlying set of a `SubMulAction`. -/ carrier : Set M @@ -243,7 +243,7 @@ variable [Monoid R] [MulAction R M] {A : Type*} [SetLike A M] variable [hA : SMulMemClass A R M] (S' : A) -- Prefer subclasses of `MulAction` over `SMulMemClass`. -/-- A `SubMulAction` of a `MulAction` is a `MulAction`. -/ +/-- A `SubMulAction` of a `MulAction` is a `MulAction`. -/ instance (priority := 75) toMulAction : MulAction R S' := Subtype.coe_injective.mulAction Subtype.val (SetLike.val_smul S') diff --git a/Mathlib/GroupTheory/HNNExtension.lean b/Mathlib/GroupTheory/HNNExtension.lean index f6df864683e3c..d4c6a1677d248 100644 --- a/Mathlib/GroupTheory/HNNExtension.lean +++ b/Mathlib/GroupTheory/HNNExtension.lean @@ -42,7 +42,7 @@ def HNNExtension.con (G : Type*) [Group G] (A B : Subgroup G) (φ : A ≃* B) : /-- The HNN Extension of a group `G`, `HNNExtension G A B φ`. Given a group `G`, subgroups `A` and `B` and an isomorphism `φ` of `A` and `B`, we adjoin a letter `t` to `G`, such that for any `a ∈ A`, the conjugate of `of a` by `t` is `of (φ a)`, where `of` is the canonical -map from `G` into the `HNNExtension`. -/ +map from `G` into the `HNNExtension`. -/ def HNNExtension (G : Type*) [Group G] (A B : Subgroup G) (φ : A ≃* B) : Type _ := (HNNExtension.con G A B φ).Quotient @@ -281,7 +281,7 @@ def cons (g : G) (u : ℤˣ) (w : NormalWord d) (h1 : w.head ∈ d.set u) rintro ⟨u', g'⟩ hu' hw1 exact h2 _ (by simp_all) hw1 } -/-- A recursor to induct on a `NormalWord`, by proving the propert is preserved under `cons` -/ +/-- A recursor to induct on a `NormalWord`, by proving the property is preserved under `cons` -/ @[elab_as_elim] def consRecOn {motive : NormalWord d → Sort*} (w : NormalWord d) (ofGroup : ∀g, motive (ofGroup g)) @@ -347,8 +347,8 @@ theorem unitsSMulGroup_snd (u : ℤˣ) (g : G) : variable {d} -/-- `Cancels u w` is a predicate expressing whether `t^u` cancels with some occurence -of `t^-u` when when we multiply `t^u` by `w`. -/ +/-- `Cancels u w` is a predicate expressing whether `t^u` cancels with some occurrence +of `t^-u` when we multiply `t^u` by `w`. -/ def Cancels (u : ℤˣ) (w : NormalWord d) : Prop := (w.head ∈ (toSubgroup A B u : Subgroup G)) ∧ w.toList.head?.map Prod.fst = some (-u) @@ -473,9 +473,8 @@ theorem unitsSMul_one_group_smul (g : A) (w : NormalWord d) : dsimp congr 1 · conv_lhs => erw [IsComplement.equiv_mul_left] - simp? says - simp only [toSubgroup_one, SetLike.coe_sort_coe, map_mul, Submonoid.coe_mul, - coe_toSubmonoid] + simp_rw [toSubgroup_one] + simp only [SetLike.coe_sort_coe, map_mul, Subgroup.coe_mul] conv_lhs => erw [IsComplement.equiv_mul_left] rfl @@ -653,9 +652,9 @@ theorem exists_normalWord_prod_eq simp [mul_assoc, unitsSMulGroup, (d.compl _).coe_equiv_snd_eq_one_iff_mem] /-- Two reduced words representing the same element of the `HNNExtension G A B φ` have the same -length corresponding list, with the same pattern of occurences of `t^1` and `t^(-1)`, +length corresponding list, with the same pattern of occurrences of `t^1` and `t^(-1)`, and also the `head` is in the same left coset of `toSubgroup A B (-u)`, where `u : ℤˣ` -is the exponent of the first occurence of `t` in the word. -/ +is the exponent of the first occurrence of `t` in the word. -/ theorem map_fst_eq_and_of_prod_eq {w₁ w₂ : ReducedWord G A B} (hprod : w₁.prod φ = w₂.prod φ) : w₁.toList.map Prod.fst = w₂.toList.map Prod.fst ∧ @@ -674,7 +673,7 @@ theorem map_fst_eq_and_of_prod_eq {w₁ w₂ : ReducedWord G A B} rwa [← List.head?_map, ← hw₂'2, hw₁'2, List.head?_map] /-- **Britton's Lemma**. Any reduced word whose product is an element of `G`, has no -occurences of `t`. -/ +occurrences of `t`. -/ theorem toList_eq_nil_of_mem_of_range (w : ReducedWord G A B) (hw : w.prod φ ∈ (of.range : Subgroup (HNNExtension G A B φ))) : w.toList = [] := by diff --git a/Mathlib/GroupTheory/Index.lean b/Mathlib/GroupTheory/Index.lean index ac23f4a5dddfc..0fc048268ebf6 100644 --- a/Mathlib/GroupTheory/Index.lean +++ b/Mathlib/GroupTheory/Index.lean @@ -449,6 +449,25 @@ lemma pow_mem_of_relindex_ne_zero_of_dvd (h : H.relindex K ≠ 0) {a : G} (ha : convert pow_mem_of_index_ne_zero_of_dvd h ⟨a, ha⟩ hn simp [pow_mem ha, mem_subgroupOf] +@[simp] +lemma index_toAddSubgroup : (Subgroup.toAddSubgroup H).index = H.index := + rfl + +@[simp] +lemma _root_.AddSubgroup.index_toSubgroup {G : Type*} [AddGroup G] (H : AddSubgroup G) : + (AddSubgroup.toSubgroup H).index = H.index := + rfl + +@[simp] +lemma relindex_toAddSubgroup : + (Subgroup.toAddSubgroup H).relindex (Subgroup.toAddSubgroup K) = H.relindex K := + rfl + +@[simp] +lemma _root_.AddSubgroup.relindex_toSubgroup {G : Type*} [AddGroup G] (H K : AddSubgroup G) : + (AddSubgroup.toSubgroup H).relindex (AddSubgroup.toSubgroup K) = H.relindex K := + rfl + section FiniteIndex variable (H K) diff --git a/Mathlib/GroupTheory/MonoidLocalization/Basic.lean b/Mathlib/GroupTheory/MonoidLocalization/Basic.lean index 61f01685b604e..988928ee6d456 100644 --- a/Mathlib/GroupTheory/MonoidLocalization/Basic.lean +++ b/Mathlib/GroupTheory/MonoidLocalization/Basic.lean @@ -797,12 +797,12 @@ theorem lift_id (x) : f.lift f.map_units x = x := /-- Given Localization maps `f : M →* N` for a Submonoid `S ⊆ M` and `k : M →* Q` for a Submonoid `T ⊆ M`, such that `S ≤ T`, and we have `l : M →* A`, the composition of the induced map `f.lift` for `k` with -the induced map `k.lift` for `l` is equal to the induced map `f.lift` for `l`. -/ +the induced map `k.lift` for `l` is equal to the induced map `f.lift` for `l`. -/ @[to_additive "Given Localization maps `f : M →+ N` for a Submonoid `S ⊆ M` and `k : M →+ Q` for a Submonoid `T ⊆ M`, such that `S ≤ T`, and we have `l : M →+ A`, the composition of the induced map `f.lift` for `k` with -the induced map `k.lift` for `l` is equal to the induced map `f.lift` for `l`"] +the induced map `k.lift` for `l` is equal to the induced map `f.lift` for `l`"] theorem lift_comp_lift {T : Submonoid M} (hST : S ≤ T) {Q : Type*} [CommMonoid Q] (k : LocalizationMap T Q) {A : Type*} [CommMonoid A] {l : M →* A} (hl : ∀ w : T, IsUnit (l w)) : diff --git a/Mathlib/GroupTheory/MonoidLocalization/MonoidWithZero.lean b/Mathlib/GroupTheory/MonoidLocalization/MonoidWithZero.lean index b0c5d7e2cac4a..3c6c5f38a066e 100644 --- a/Mathlib/GroupTheory/MonoidLocalization/MonoidWithZero.lean +++ b/Mathlib/GroupTheory/MonoidLocalization/MonoidWithZero.lean @@ -42,7 +42,7 @@ namespace Submonoid variable {S N} in /-- If `S` contains `0` then the localization at `S` is trivial. -/ -theorem LocalizationMap.subsingleton (f : Submonoid.LocalizationMap S N) (h : 0 ∈ S) : +theorem LocalizationMap.subsingleton (f : Submonoid.LocalizationMap S N) (h : 0 ∈ S) : Subsingleton N := by refine ⟨fun a b ↦ ?_⟩ rw [← LocalizationMap.mk'_sec f a, ← LocalizationMap.mk'_sec f b, LocalizationMap.eq] @@ -152,7 +152,7 @@ theorem leftCancelMulZero_of_le_isLeftRegular /-- Given a Localization map `f : M →*₀ N` for a Submonoid `S ⊆ M`, if `M` is a cancellative monoid with zero, and all elements of `S` are -regular, then N is a cancellative monoid with zero. -/ +regular, then N is a cancellative monoid with zero. -/ theorem isLeftRegular_of_le_isCancelMulZero (f : LocalizationWithZeroMap S N) [IsCancelMulZero M] (h : ∀ ⦃x⦄, x ∈ S → IsRegular x) : IsCancelMulZero N := by have : IsLeftCancelMulZero N := diff --git a/Mathlib/GroupTheory/OrderOfElement.lean b/Mathlib/GroupTheory/OrderOfElement.lean index fa52929c1c355..462873bca532e 100644 --- a/Mathlib/GroupTheory/OrderOfElement.lean +++ b/Mathlib/GroupTheory/OrderOfElement.lean @@ -745,7 +745,7 @@ end Finite variable [Fintype G] {x : G} @[to_additive] -lemma orderOf_eq_card_powers : orderOf x = Fintype.card (powers x : Set G) := +lemma orderOf_eq_card_powers : orderOf x = Fintype.card (powers x : Submonoid G) := (Fintype.card_fin (orderOf x)).symm.trans <| Fintype.card_eq.2 ⟨finEquivPowers x <| isOfFinOrder_of_finite _⟩ @@ -821,6 +821,7 @@ variable [Fintype G] {x : G} {n : ℕ} /-- See also `Nat.card_addSubgroupZPowers`. -/ @[to_additive "See also `Nat.card_subgroup`."] theorem Fintype.card_zpowers : Fintype.card (zpowers x) = orderOf x := + letI : Fintype (zpowers x) := (Subgroup.zpowers x).instFintypeSubtypeMemOfDecidablePred (Fintype.card_eq.2 ⟨finEquivZPowers x <| isOfFinOrder_of_finite _⟩).symm.trans <| Fintype.card_fin (orderOf x) @@ -948,7 +949,9 @@ theorem inf_eq_bot_of_coprime {G : Type*} [Group G] {H K : Subgroup G} /- TODO: Generalise to `Submonoid.powers`. -/ @[to_additive] theorem image_range_orderOf [DecidableEq G] : + letI : Fintype (zpowers x) := (Subgroup.zpowers x).instFintypeSubtypeMemOfDecidablePred Finset.image (fun i => x ^ i) (Finset.range (orderOf x)) = (zpowers x : Set G).toFinset := by + letI : Fintype (zpowers x) := (Subgroup.zpowers x).instFintypeSubtypeMemOfDecidablePred ext x rw [Set.mem_toFinset, SetLike.mem_coe, mem_zpowers_iff_mem_range_orderOf] diff --git a/Mathlib/GroupTheory/PGroup.lean b/Mathlib/GroupTheory/PGroup.lean index 1b48a93653134..ea820704dd164 100644 --- a/Mathlib/GroupTheory/PGroup.lean +++ b/Mathlib/GroupTheory/PGroup.lean @@ -37,7 +37,7 @@ theorem of_card {n : ℕ} (hG : Nat.card G = p ^ n) : IsPGroup p G := fun g => ⟨n, by rw [← hG, pow_card_eq_one']⟩ theorem of_bot : IsPGroup p (⊥ : Subgroup G) := - of_card (by rw [Subgroup.card_bot, pow_zero]) + of_card (n := 0) (by rw [Subgroup.card_bot, pow_zero]) theorem iff_card [Fact p.Prime] [Finite G] : IsPGroup p G ↔ ∃ n : ℕ, Nat.card G = p ^ n := by have hG : Nat.card G ≠ 0 := Nat.card_pos.ne' diff --git a/Mathlib/GroupTheory/Perm/Cycle/Concrete.lean b/Mathlib/GroupTheory/Perm/Cycle/Concrete.lean index 8b3c477a43b28..57afc2d245faf 100644 --- a/Mathlib/GroupTheory/Perm/Cycle/Concrete.lean +++ b/Mathlib/GroupTheory/Perm/Cycle/Concrete.lean @@ -109,11 +109,10 @@ theorem cycleType_formPerm (hl : Nodup l) (hn : 2 ≤ l.length) : · simpa using isCycle_formPerm hl hn · simp -set_option linter.deprecated false in theorem formPerm_apply_mem_eq_next (hl : Nodup l) (x : α) (hx : x ∈ l) : formPerm l x = next l x hx := by obtain ⟨k, rfl⟩ := get_of_mem hx - rw [next_get _ hl, formPerm_apply_get _ hl] + rw [next_get _ hl, get_eq_getElem, formPerm_apply_getElem _ hl]; rfl end List @@ -221,16 +220,6 @@ theorem get_toList (n : ℕ) (hn : n < length (toList p x)) : theorem toList_get_zero (h : x ∈ p.support) : (toList p x).get ⟨0, (length_toList_pos_of_mem_support _ _ h)⟩ = x := by simp [toList] -set_option linter.deprecated false in -@[deprecated get_toList (since := "2024-05-08")] -theorem nthLe_toList (n : ℕ) (hn : n < length (toList p x)) : - (toList p x).nthLe n hn = (p ^ n) x := by simp [toList] - -set_option linter.deprecated false in -@[deprecated toList_get_zero (since := "2024-05-08")] -theorem toList_nthLe_zero (h : x ∈ p.support) : - (toList p x).nthLe 0 (length_toList_pos_of_mem_support _ _ h) = x := by simp [toList] - variable {p} {x} theorem mem_toList_iff {y : α} : y ∈ toList p x ↔ SameCycle p x y ∧ x ∈ p.support := by @@ -244,17 +233,16 @@ theorem mem_toList_iff {y : α} : y ∈ toList p x ↔ SameCycle p x y ∧ x ∈ · rintro ⟨h, hx⟩ simpa using h.exists_pow_eq_of_mem_support hx -set_option linter.deprecated false in theorem nodup_toList (p : Perm α) (x : α) : Nodup (toList p x) := by by_cases hx : p x = x · rw [← not_mem_support, ← toList_eq_nil_iff] at hx simp [hx] have hc : IsCycle (cycleOf p x) := isCycle_cycleOf p hx - rw [nodup_iff_nthLe_inj] - rintro n m hn hm + rw [nodup_iff_injective_get] + intro ⟨n, hn⟩ ⟨m, hm⟩ rw [length_toList, ← hc.orderOf] at hm hn rw [← cycleOf_apply_self, ← Ne, ← mem_support] at hx - rw [nthLe_toList, nthLe_toList, ← cycleOf_pow_apply_self p x n, ← + rw [get_toList, get_toList, ← cycleOf_pow_apply_self p x n, ← cycleOf_pow_apply_self p x m] cases' n with n <;> cases' m with m · simp @@ -268,7 +256,7 @@ theorem nodup_toList (p : Perm α) (x : α) : Nodup (toList p x) := by have hn' : ¬orderOf (p.cycleOf x) ∣ n.succ := Nat.not_dvd_of_pos_of_lt n.zero_lt_succ hn have hm' : ¬orderOf (p.cycleOf x) ∣ m.succ := Nat.not_dvd_of_pos_of_lt m.zero_lt_succ hm rw [← hc.support_pow_eq_iff] at hn' hm' - rw [← Nat.mod_eq_of_lt hn, ← Nat.mod_eq_of_lt hm, ← pow_inj_mod] + rw [Fin.mk_eq_mk, ← Nat.mod_eq_of_lt hn, ← Nat.mod_eq_of_lt hm, ← pow_inj_mod] refine support_congr ?_ ?_ · rw [hm', hn'] · rw [hm'] @@ -277,24 +265,23 @@ theorem nodup_toList (p : Perm α) (x : α) : Nodup (toList p x) := by rw [← mul_apply, (Commute.pow_pow_self _ _ _).eq, mul_apply, h, ← mul_apply, ← mul_apply, (Commute.pow_pow_self _ _ _).eq] -set_option linter.deprecated false in theorem next_toList_eq_apply (p : Perm α) (x y : α) (hy : y ∈ toList p x) : next (toList p x) y hy = p y := by rw [mem_toList_iff] at hy obtain ⟨k, hk, hk'⟩ := hy.left.exists_pow_eq_of_mem_support hy.right - rw [← nthLe_toList p x k (by simpa using hk)] at hk' + rw [← get_toList p x k (by simpa using hk)] at hk' simp_rw [← hk'] - rw [next_nthLe _ (nodup_toList _ _), nthLe_toList, nthLe_toList, ← mul_apply, ← pow_succ', - length_toList, ← pow_mod_orderOf_cycleOf_apply p (k + 1), IsCycle.orderOf] + rw [next_get _ (nodup_toList _ _), get_toList, get_toList, ← mul_apply, ← pow_succ'] + simp_rw [length_toList] + rw [← pow_mod_orderOf_cycleOf_apply p (k + 1), IsCycle.orderOf] exact isCycle_cycleOf _ (mem_support.mp hy.right) -set_option linter.deprecated false in theorem toList_pow_apply_eq_rotate (p : Perm α) (x : α) (k : ℕ) : p.toList ((p ^ k) x) = (p.toList x).rotate k := by - apply ext_nthLe + apply ext_get · simp only [length_toList, cycleOf_self_apply_pow, length_rotate] · intro n hn hn' - rw [nthLe_toList, nthLe_rotate, nthLe_toList, length_toList, + rw [get_toList, get_rotate, get_toList, length_toList, pow_mod_card_support_cycleOf_self_apply, pow_add, mul_apply] theorem SameCycle.toList_isRotated {f : Perm α} {x y : α} (h : SameCycle f x y) : diff --git a/Mathlib/GroupTheory/Perm/Cycle/Factors.lean b/Mathlib/GroupTheory/Perm/Cycle/Factors.lean index 87dff651c4a05..95eaa03324542 100644 --- a/Mathlib/GroupTheory/Perm/Cycle/Factors.lean +++ b/Mathlib/GroupTheory/Perm/Cycle/Factors.lean @@ -303,12 +303,10 @@ section cycleFactors open scoped List in /-- Given a list `l : List α` and a permutation `f : Perm α` whose nonfixed points are all in `l`, recursively factors `f` into cycles. -/ -def cycleFactorsAux [DecidableEq α] [Fintype α] : - ∀ (l : List α) (f : Perm α), - (∀ {x}, f x ≠ x → x ∈ l) → - { l : List (Perm α) // l.prod = f ∧ (∀ g ∈ l, IsCycle g) ∧ l.Pairwise Disjoint } := by - intro l f h - exact match l with +def cycleFactorsAux [DecidableEq α] [Fintype α] (l : List α) (f : Perm α) + (h : ∀ {x}, f x ≠ x → x ∈ l) : + { l : List (Perm α) // l.prod = f ∧ (∀ g ∈ l, IsCycle g) ∧ l.Pairwise Disjoint } := + match l with | [] => ⟨[], by { simp only [imp_false, List.Pairwise.nil, List.not_mem_nil, forall_const, and_true_iff, forall_prop_of_false, Classical.not_not, not_false_iff, List.prod_nil] at * diff --git a/Mathlib/GroupTheory/Perm/Cycle/Type.lean b/Mathlib/GroupTheory/Perm/Cycle/Type.lean index 0b0d600b9a079..34e77ea5584a0 100644 --- a/Mathlib/GroupTheory/Perm/Cycle/Type.lean +++ b/Mathlib/GroupTheory/Perm/Cycle/Type.lean @@ -31,7 +31,6 @@ In this file we define the cycle type of a permutation. there exists an element of order `p` in `G`. This is known as Cauchy's theorem. -/ - namespace Equiv.Perm open Mathlib (Vector) @@ -65,7 +64,7 @@ theorem cycleType_eq {σ : Perm α} (l : List (Perm α)) (h0 : l.prod = σ) σ.cycleType = l.map (Finset.card ∘ support) := by have hl : l.Nodup := nodup_of_pairwise_disjoint_cycles h1 h2 rw [cycleType_eq' l.toFinset] - · simp [List.dedup_eq_self.mpr hl, (· ∘ ·)] + · simp [List.dedup_eq_self.mpr hl, Function.comp_def] · simpa using h1 · simpa [hl] using h2 · simp [hl, h0] @@ -418,7 +417,7 @@ theorem rotate_length : rotate v n = v := end VectorsProdEqOne --- TODO: Make make the `Finite` version of this theorem the default +-- TODO: Make the `Finite` version of this theorem the default /-- For every prime `p` dividing the order of a finite group `G` there exists an element of order `p` in `G`. This is known as Cauchy's theorem. -/ theorem _root_.exists_prime_orderOf_dvd_card {G : Type*} [Group G] [Fintype G] (p : ℕ) @@ -453,7 +452,7 @@ theorem _root_.exists_prime_orderOf_dvd_card {G : Type*} [Group G] [Fintype G] ( · rw [Subtype.ext_iff_val, Subtype.ext_iff_val, hg, hg', v.1.2] simp only [v₀, Vector.replicate] --- TODO: Make make the `Finite` version of this theorem the default +-- TODO: Make the `Finite` version of this theorem the default /-- For every prime `p` dividing the order of a finite additive group `G` there exists an element of order `p` in `G`. This is the additive version of Cauchy's theorem. -/ theorem _root_.exists_prime_addOrderOf_dvd_card {G : Type*} [AddGroup G] [Fintype G] (p : ℕ) @@ -462,7 +461,7 @@ theorem _root_.exists_prime_addOrderOf_dvd_card {G : Type*} [AddGroup G] [Fintyp attribute [to_additive existing] exists_prime_orderOf_dvd_card --- TODO: Make make the `Finite` version of this theorem the default +-- TODO: Make the `Finite` version of this theorem the default /-- For every prime `p` dividing the order of a finite group `G` there exists an element of order `p` in `G`. This is known as Cauchy's theorem. -/ @[to_additive] diff --git a/Mathlib/GroupTheory/Perm/Finite.lean b/Mathlib/GroupTheory/Perm/Finite.lean index 3e5fb88d4607f..4c4f0cfef47b7 100644 --- a/Mathlib/GroupTheory/Perm/Finite.lean +++ b/Mathlib/GroupTheory/Perm/Finite.lean @@ -13,7 +13,7 @@ import Mathlib.Logic.Equiv.Fintype # Permutations on `Fintype`s This file contains miscellaneous lemmas about `Equiv.Perm` and `Equiv.swap`, building on top -of those in `Data/Equiv/Basic` and other files in `GroupTheory/Perm/*`. +of those in `Logic/Equiv/Basic.lean` and other files in `GroupTheory/Perm/*`. -/ universe u v diff --git a/Mathlib/GroupTheory/Perm/List.lean b/Mathlib/GroupTheory/Perm/List.lean index 092595ac44ce4..1cdc01f35e5cd 100644 --- a/Mathlib/GroupTheory/Perm/List.lean +++ b/Mathlib/GroupTheory/Perm/List.lean @@ -144,12 +144,6 @@ theorem formPerm_apply_get_length (x : α) (xs : List α) : formPerm (x :: xs) ((x :: xs).get (Fin.mk xs.length (by simp))) = x := formPerm_apply_getElem_length .. -set_option linter.deprecated false in -@[deprecated formPerm_apply_getElem_length (since := "2024-05-30")] -theorem formPerm_apply_nthLe_length (x : α) (xs : List α) : - formPerm (x :: xs) ((x :: xs).nthLe xs.length (by simp)) = x := - formPerm_apply_getElem_length .. - theorem formPerm_apply_head (x y : α) (xs : List α) (h : Nodup (x :: y :: xs)) : formPerm (x :: y :: xs) x = y := by simp [formPerm_apply_of_not_mem h.not_mem] @@ -165,12 +159,6 @@ theorem formPerm_apply_get_zero (l : List α) (h : Nodup l) (hl : 1 < l.length) formPerm l (l.get (Fin.mk 0 (by omega))) = l.get (Fin.mk 1 hl) := formPerm_apply_getElem_zero l h hl -set_option linter.deprecated false in -@[deprecated formPerm_apply_getElem_zero (since := "2024-05-30")] -theorem formPerm_apply_nthLe_zero (l : List α) (h : Nodup l) (hl : 1 < l.length) : - formPerm l (l.nthLe 0 (by omega)) = l.nthLe 1 hl := by - apply formPerm_apply_get_zero _ h - variable (l) theorem formPerm_eq_head_iff_eq_getLast (x y : α) : @@ -199,12 +187,6 @@ theorem formPerm_apply_lt_get (xs : List α) (h : Nodup xs) (n : ℕ) (hn : n + xs.get (Fin.mk (n + 1) hn) := by simp_all [formPerm_apply_lt_getElem] -set_option linter.deprecated false in -@[deprecated formPerm_apply_lt_get (since := "2024-05-30")] -theorem formPerm_apply_lt (xs : List α) (h : Nodup xs) (n : ℕ) (hn : n + 1 < xs.length) : - formPerm xs (xs.nthLe n ((Nat.lt_succ_self n).trans hn)) = xs.nthLe (n + 1) hn := by - apply formPerm_apply_lt_get _ h - theorem formPerm_apply_getElem (xs : List α) (w : Nodup xs) (i : ℕ) (h : i < xs.length) : formPerm xs xs[i] = xs[(i + 1) % xs.length]'(Nat.mod_lt _ (i.zero_le.trans_lt h)) := by @@ -225,13 +207,6 @@ theorem formPerm_apply_get (xs : List α) (h : Nodup xs) (i : Fin xs.length) : xs.get ⟨((i.val + 1) % xs.length), (Nat.mod_lt _ (i.val.zero_le.trans_lt i.isLt))⟩ := by simp [formPerm_apply_getElem, h] -set_option linter.deprecated false in -@[deprecated formPerm_apply_get (since := "2024-04-23")] -theorem formPerm_apply_nthLe (xs : List α) (h : Nodup xs) (n : ℕ) (hn : n < xs.length) : - formPerm xs (xs.nthLe n hn) = - xs.nthLe ((n + 1) % xs.length) (Nat.mod_lt _ (n.zero_le.trans_lt hn)) := by - apply formPerm_apply_get _ h - theorem support_formPerm_of_nodup' (l : List α) (h : Nodup l) (h' : ∀ x : α, l ≠ [x]) : { x | formPerm l x ≠ x } = l.toFinset := by apply _root_.le_antisymm @@ -307,13 +282,6 @@ theorem formPerm_pow_apply_get (l : List α) (h : Nodup l) (n : ℕ) (i : Fin l. l.get ⟨((i.val + n) % l.length), (Nat.mod_lt _ (i.val.zero_le.trans_lt i.isLt))⟩ := by simp [formPerm_pow_apply_getElem, h] -set_option linter.deprecated false in -@[deprecated formPerm_pow_apply_get (since := "2024-04-23")] -theorem formPerm_pow_apply_nthLe (l : List α) (h : Nodup l) (n k : ℕ) (hk : k < l.length) : - (formPerm l ^ n) (l.nthLe k hk) = - l.nthLe ((k + n) % l.length) (Nat.mod_lt _ (k.zero_le.trans_lt hk)) := - formPerm_pow_apply_get l h n ⟨k, hk⟩ - theorem formPerm_pow_apply_head (x : α) (l : List α) (h : Nodup (x :: l)) (n : ℕ) : (formPerm (x :: l) ^ n) x = (x :: l)[(n % (x :: l).length)]'(Nat.mod_lt _ (Nat.zero_lt_succ _)) := by diff --git a/Mathlib/GroupTheory/Perm/Sign.lean b/Mathlib/GroupTheory/Perm/Sign.lean index 1f4c096e2337d..7e6e532bb4f4d 100644 --- a/Mathlib/GroupTheory/Perm/Sign.lean +++ b/Mathlib/GroupTheory/Perm/Sign.lean @@ -549,7 +549,7 @@ theorem sign_prodCongrRight (σ : α → Perm β) : sign (prodCongrRight σ) = exact List.mem_toFinset.mpr (mem_l b) rw [← prod_prodExtendRight σ hl mem_l, map_list_prod sign, List.map_map, ← l_to_finset, List.prod_toFinset _ hl] - simp_rw [← fun a => sign_prodExtendRight a (σ a), Function.comp] + simp_rw [← fun a => sign_prodExtendRight a (σ a), Function.comp_def] theorem sign_prodCongrLeft (σ : α → Perm β) : sign (prodCongrLeft σ) = ∏ k, sign (σ k) := by refine (sign_eq_sign_of_equiv _ _ (prodComm β α) ?_).trans (sign_prodCongrRight σ) diff --git a/Mathlib/GroupTheory/PushoutI.lean b/Mathlib/GroupTheory/PushoutI.lean index 6f3baeb1be190..ab561721ed4f6 100644 --- a/Mathlib/GroupTheory/PushoutI.lean +++ b/Mathlib/GroupTheory/PushoutI.lean @@ -301,7 +301,7 @@ theorem prod_empty : (empty : NormalWord d).prod = 1 := by simp [prod, empty] /-- A constructor that multiplies a `NormalWord` by an element, with condition to make -sure the underlying list does get longer. -/ +sure the underlying list does get longer. -/ @[simps!] noncomputable def cons {i} (g : G i) (w : NormalWord d) (hmw : w.fstIdx ≠ some i) (hgr : g ∉ (φ i).range) : NormalWord d := @@ -328,7 +328,7 @@ variable [DecidableEq ι] [∀ i, DecidableEq (G i)] /-- Given a word in `CoprodI`, if every letter is in the transversal and when we multiply by an element of the base group it still has this property, -then the element of the base group we multiplied by was one. -/ +then the element of the base group we multiplied by was one. -/ theorem eq_one_of_smul_normalized (w : CoprodI.Word G) {i : ι} (h : H) (hw : ∀ i g, ⟨i, g⟩ ∈ w.toList → g ∈ d.set i) (hφw : ∀ j g, ⟨j, g⟩ ∈ (CoprodI.of (φ i h) • w).toList → g ∈ d.set j) : @@ -355,8 +355,9 @@ theorem eq_one_of_smul_normalized (w : CoprodI.Word G) {i : ι} (h : H) equiv_mul_left_of_mem (d.compl i) ⟨_, rfl⟩ , hhead, Subtype.ext_iff, Prod.ext_iff, Subgroup.coe_mul] at h rcases h with ⟨h₁, h₂⟩ - rw [h₂, equiv_one (d.compl i) (one_mem _) (d.one_mem _), mul_one, - ((injective_iff_map_eq_one' _).1 (d.injective i))] at h₁ + rw [h₂, equiv_one (d.compl i) (one_mem _) (d.one_mem _)] at h₁ + erw [mul_one] at h₁ + simp only [((injective_iff_map_eq_one' _).1 (d.injective i))] at h₁ contradiction · rw [Word.equivPair_head] dsimp diff --git a/Mathlib/GroupTheory/QuotientGroup/Basic.lean b/Mathlib/GroupTheory/QuotientGroup/Basic.lean index 8989b6647b1d3..131f8cbdee6f4 100644 --- a/Mathlib/GroupTheory/QuotientGroup/Basic.lean +++ b/Mathlib/GroupTheory/QuotientGroup/Basic.lean @@ -51,13 +51,13 @@ variable {G : Type u} [Group G] (N : Subgroup G) [nN : N.Normal] {H : Type v} [G @[to_additive "The additive congruence relation generated by a normal additive subgroup."] protected def con : Con G where toSetoid := leftRel N - mul' := @fun a b c d hab hcd => by + mul' := fun {a b c d} hab hcd => by rw [leftRel_eq] at hab hcd ⊢ dsimp only calc - (a * c)⁻¹ * (b * d) = c⁻¹ * (a⁻¹ * b) * c⁻¹⁻¹ * (c⁻¹ * d) := by + c⁻¹ * (a⁻¹ * b) * c⁻¹⁻¹ * (c⁻¹ * d) ∈ N := N.mul_mem (nN.conj_mem _ hab _) hcd + _ = (a * c)⁻¹ * (b * d) := by simp only [mul_inv_rev, mul_assoc, inv_mul_cancel_left] - _ ∈ N := N.mul_mem (nN.conj_mem _ hab _) hcd @[to_additive] instance Quotient.group : Group (G ⧸ N) := @@ -423,7 +423,7 @@ Applying this equiv is nicer than rewriting along the equalities, since the type -/ @[to_additive "Let `A', A, B', B` be subgroups of `G`. If `A' = B'` and `A = B`, then the quotients `A / (A' ⊓ A)` and `B / (B' ⊓ B)` are isomorphic. Applying this equiv is nicer than rewriting along -the equalities, since the type of `(A'.addSubgroupOf A : AddSubgroup A)` depends on on `A`. "] +the equalities, since the type of `(A'.addSubgroupOf A : AddSubgroup A)` depends on `A`. "] def equivQuotientSubgroupOfOfEq {A' A B' B : Subgroup G} [hAN : (A'.subgroupOf A).Normal] [hBN : (B'.subgroupOf B).Normal] (h' : A' = B') (h : A = B) : A ⧸ A'.subgroupOf A ≃* B ⧸ B'.subgroupOf B := diff --git a/Mathlib/GroupTheory/SchurZassenhaus.lean b/Mathlib/GroupTheory/SchurZassenhaus.lean index 1cb524d82f333..a143963c7cc26 100644 --- a/Mathlib/GroupTheory/SchurZassenhaus.lean +++ b/Mathlib/GroupTheory/SchurZassenhaus.lean @@ -262,8 +262,8 @@ private theorem exists_right_complement'_of_coprime_aux' [Finite G] (hG : Nat.ca {N : Subgroup G} [N.Normal] (hN : Nat.Coprime (Nat.card N) N.index) : ∃ H : Subgroup G, IsComplement' N H := by revert G - apply Nat.strongInductionOn n - rintro n ih G _ _ rfl N _ hN + induction n using Nat.strongRecOn with | ind n ih => ?_ + rintro G _ _ rfl N _ hN refine not_forall_not.mp fun h3 => ?_ haveI := SchurZassenhausInduction.step7 hN (fun G' _ _ hG' => by apply ih _ hG'; rfl) h3 exact not_exists_of_forall_not h3 (exists_right_complement'_of_coprime_aux hN) diff --git a/Mathlib/GroupTheory/SemidirectProduct.lean b/Mathlib/GroupTheory/SemidirectProduct.lean index 904d910b72cfa..6996df7ab8182 100644 --- a/Mathlib/GroupTheory/SemidirectProduct.lean +++ b/Mathlib/GroupTheory/SemidirectProduct.lean @@ -222,7 +222,7 @@ section Map variable {N₁ : Type*} {G₁ : Type*} [Group N₁] [Group G₁] {φ₁ : G₁ →* MulAut N₁} /-- Define a map from `N ⋊[φ] G` to `N₁ ⋊[φ₁] G₁` given maps `N →* N₁` and `G →* G₁` that - satisfy a commutativity condition `∀ n g, f₁ (φ g n) = φ₁ (f₂ g) (f₁ n)`. -/ + satisfy a commutativity condition `∀ n g, f₁ (φ g n) = φ₁ (f₂ g) (f₁ n)`. -/ def map (f₁ : N →* N₁) (f₂ : G →* G₁) (h : ∀ g : G, f₁.comp (φ g).toMonoidHom = (φ₁ (f₂ g)).toMonoidHom.comp f₁) : N ⋊[φ] G →* N₁ ⋊[φ₁] G₁ where diff --git a/Mathlib/GroupTheory/Solvable.lean b/Mathlib/GroupTheory/Solvable.lean index 769f40a7f6ef5..f3783500b961a 100644 --- a/Mathlib/GroupTheory/Solvable.lean +++ b/Mathlib/GroupTheory/Solvable.lean @@ -180,7 +180,7 @@ theorem not_solvable_of_mem_derivedSeries {g : G} (h1 : g ≠ 1) (h2 : ∀ n : ℕ, g ∈ derivedSeries G n) : ¬IsSolvable G := mt (isSolvable_def _).mp (not_exists_of_forall_not fun n h => - h1 (Subgroup.mem_bot.mp ((congr_arg (Membership.mem g) h).mp (h2 n)))) + h1 (Subgroup.mem_bot.mp ((congr_arg (g ∈ ·) h).mp (h2 n)))) theorem Equiv.Perm.fin_5_not_solvable : ¬IsSolvable (Equiv.Perm (Fin 5)) := by let x : Equiv.Perm (Fin 5) := ⟨![1, 2, 0, 3, 4], ![2, 0, 1, 3, 4], by decide, by decide⟩ diff --git a/Mathlib/GroupTheory/SpecificGroups/Cyclic.lean b/Mathlib/GroupTheory/SpecificGroups/Cyclic.lean index 965253cc75dc7..08c5bf423e87d 100644 --- a/Mathlib/GroupTheory/SpecificGroups/Cyclic.lean +++ b/Mathlib/GroupTheory/SpecificGroups/Cyclic.lean @@ -109,6 +109,12 @@ theorem isCyclic_of_orderOf_eq_card [Fintype α] (x : α) (hx : orderOf x = Fint use x rw [← Set.range_iff_surjective, ← coe_zpowers] rw [← Fintype.card_congr (Equiv.Set.univ α), ← Fintype.card_zpowers] at hx + #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 : Fintype (zpowers x) := (Subgroup.zpowers x).instFintypeSubtypeMemOfDecidablePred exact Set.eq_of_subset_of_card_le (Set.subset_univ _) (ge_of_eq hx) @[deprecated (since := "2024-02-21")] alias isAddCyclic_of_orderOf_eq_card := isAddCyclic_of_addOrderOf_eq_card diff --git a/Mathlib/GroupTheory/SpecificGroups/Dihedral.lean b/Mathlib/GroupTheory/SpecificGroups/Dihedral.lean index 8cbe12005aff0..53949cd3a109b 100644 --- a/Mathlib/GroupTheory/SpecificGroups/Dihedral.lean +++ b/Mathlib/GroupTheory/SpecificGroups/Dihedral.lean @@ -111,7 +111,7 @@ instance : Infinite (DihedralGroup 0) := DihedralGroup.fintypeHelper.infinite_iff.mp inferInstance instance : Nontrivial (DihedralGroup n) := - ⟨⟨r 0, sr 0, by simp_rw [ne_eq, not_false_eq_true]⟩⟩ + ⟨⟨r 0, sr 0, by simp_rw [ne_eq, reduceCtorEq, not_false_eq_true]⟩⟩ /-- If `0 < n`, then `DihedralGroup n` has `2n` elements. -/ @@ -150,7 +150,7 @@ theorem orderOf_sr (i : ZMod n) : orderOf (sr i) = 2 := by · rw [sq, sr_mul_self] · -- Porting note: Previous proof was `decide` revert n - simp_rw [one_def, ne_eq, forall_const, not_false_eq_true] + simp_rw [one_def, ne_eq, reduceCtorEq, forall_const, not_false_eq_true] /-- If `0 < n`, then `r 1` has order `n`. -/ diff --git a/Mathlib/GroupTheory/SpecificGroups/Quaternion.lean b/Mathlib/GroupTheory/SpecificGroups/Quaternion.lean index be7d8cba6dabf..0db9e8be9fe21 100644 --- a/Mathlib/GroupTheory/SpecificGroups/Quaternion.lean +++ b/Mathlib/GroupTheory/SpecificGroups/Quaternion.lean @@ -204,7 +204,7 @@ theorem orderOf_xa [NeZero n] (i : ZMod (2 * n)) : orderOf (xa i) = 4 := by apply_fun ZMod.val at h' apply_fun (· / n) at h' simp only [ZMod.val_natCast, ZMod.val_zero, Nat.zero_div, Nat.mod_mul_left_div_self, - Nat.div_self (NeZero.pos n)] at h' + Nat.div_self (NeZero.pos n), reduceCtorEq] at h' · norm_num /-- In the special case `n = 1`, `Quaternion 1` is a cyclic group (of order `4`). -/ diff --git a/Mathlib/GroupTheory/Subgroup/Center.lean b/Mathlib/GroupTheory/Subgroup/Center.lean index a3b3323d2c5ff..a3733d06b31fb 100644 --- a/Mathlib/GroupTheory/Subgroup/Center.lean +++ b/Mathlib/GroupTheory/Subgroup/Center.lean @@ -15,9 +15,6 @@ import Mathlib.GroupTheory.Submonoid.Center assert_not_exists Multiset assert_not_exists Ring -open Function -open Int - variable {G : Type*} [Group G] namespace Subgroup diff --git a/Mathlib/GroupTheory/Subgroup/Centralizer.lean b/Mathlib/GroupTheory/Subgroup/Centralizer.lean index d5639da747843..19e40261c4734 100644 --- a/Mathlib/GroupTheory/Subgroup/Centralizer.lean +++ b/Mathlib/GroupTheory/Subgroup/Centralizer.lean @@ -10,10 +10,6 @@ import Mathlib.GroupTheory.Submonoid.Centralizer # Centralizers of subgroups -/ - -open Function -open Int - variable {G : Type*} [Group G] namespace Subgroup diff --git a/Mathlib/GroupTheory/Sylow.lean b/Mathlib/GroupTheory/Sylow.lean index 45a76037e7714..a534e244575fe 100644 --- a/Mathlib/GroupTheory/Sylow.lean +++ b/Mathlib/GroupTheory/Sylow.lean @@ -332,7 +332,8 @@ theorem Sylow.conj_eq_normalizer_conj_of_mem_centralizer [Fact p.Prime] [Finite theorem Sylow.conj_eq_normalizer_conj_of_mem [Fact p.Prime] [Finite (Sylow p G)] (P : Sylow p G) [_hP : (P : Subgroup G).IsCommutative] (x g : G) (hx : x ∈ P) (hy : g⁻¹ * x * g ∈ P) : ∃ n ∈ (P : Subgroup G).normalizer, g⁻¹ * x * g = n⁻¹ * x * n := - P.conj_eq_normalizer_conj_of_mem_centralizer x g (le_centralizer P hx) (le_centralizer P hy) + P.conj_eq_normalizer_conj_of_mem_centralizer x g + (le_centralizer (P : Subgroup G) hx) (le_centralizer (P : Subgroup G) hy) /-- Sylow `p`-subgroups are in bijection with cosets of the normalizer of a Sylow `p`-subgroup -/ noncomputable def Sylow.equivQuotientNormalizer [Fact p.Prime] [Finite (Sylow p G)] @@ -458,7 +459,7 @@ def fixedPointsMulLeftCosetsEquivQuotient (H : Subgroup G) [Finite (H : Set G)] rfl) /-- If `H` is a `p`-subgroup of `G`, then the index of `H` inside its normalizer is congruent - mod `p` to the index of `H`. -/ + mod `p` to the index of `H`. -/ theorem card_quotient_normalizer_modEq_card_quotient [Finite G] {p : ℕ} {n : ℕ} [hp : Fact p.Prime] {H : Subgroup G} (hH : Nat.card H = p ^ n) : Nat.card (normalizer H ⧸ Subgroup.comap ((normalizer H).subtype : normalizer H →* G) H) ≡ @@ -467,7 +468,7 @@ theorem card_quotient_normalizer_modEq_card_quotient [Finite G] {p : ℕ} {n : exact ((IsPGroup.of_card hH).card_modEq_card_fixedPoints _).symm /-- If `H` is a subgroup of `G` of cardinality `p ^ n`, then the cardinality of the - normalizer of `H` is congruent mod `p ^ (n + 1)` to the cardinality of `G`. -/ + normalizer of `H` is congruent mod `p ^ (n + 1)` to the cardinality of `G`. -/ theorem card_normalizer_modEq_card [Finite G] {p : ℕ} {n : ℕ} [hp : Fact p.Prime] {H : Subgroup G} (hH : Nat.card H = p ^ n) : Nat.card (normalizer H) ≡ Nat.card G [MOD p ^ (n + 1)] := by have : H.subgroupOf (normalizer H) ≃ H := (subgroupOfEquivOfLe le_normalizer).toEquiv diff --git a/Mathlib/GroupTheory/Torsion.lean b/Mathlib/GroupTheory/Torsion.lean index ec5b8b580bb9e..9e505a267b935 100644 --- a/Mathlib/GroupTheory/Torsion.lean +++ b/Mathlib/GroupTheory/Torsion.lean @@ -201,7 +201,10 @@ variable {G} {p} @[to_additive primaryComponent.exists_orderOf_eq_prime_nsmul "Elements of the `p`-primary component have additive order `p^n` for some `n`"] theorem primaryComponent.exists_orderOf_eq_prime_pow (g : CommMonoid.primaryComponent G p) : - ∃ n : ℕ, orderOf g = p ^ n := by simpa [primaryComponent] using g.property + ∃ n : ℕ, orderOf g = p ^ n := by + obtain ⟨_, hn⟩ := g.property + rw [orderOf_submonoid g] at hn + exact ⟨_, hn⟩ /-- The `p`- and `q`-primary components are disjoint for `p ≠ q`. -/ @[to_additive "The `p`- and `q`-primary components are disjoint for `p ≠ q`."] diff --git a/Mathlib/InformationTheory/Hamming.lean b/Mathlib/InformationTheory/Hamming.lean index 5f6eb9c5030e9..63b352144a998 100644 --- a/Mathlib/InformationTheory/Hamming.lean +++ b/Mathlib/InformationTheory/Hamming.lean @@ -262,12 +262,12 @@ instance (α) [Semiring α] (β : ι → Type*) [∀ i, AddCommMonoid (β i)] [ /-! API to/from the type synonym. -/ -/-- `Hamming.toHamming` is the identity function to the `Hamming` of a type. -/ +/-- `Hamming.toHamming` is the identity function to the `Hamming` of a type. -/ @[match_pattern] def toHamming : (∀ i, β i) ≃ Hamming β := Equiv.refl _ -/-- `Hamming.ofHamming` is the identity function from the `Hamming` of a type. -/ +/-- `Hamming.ofHamming` is the identity function from the `Hamming` of a type. -/ @[match_pattern] def ofHamming : Hamming β ≃ ∀ i, β i := Equiv.refl _ diff --git a/Mathlib/Init.lean b/Mathlib/Init.lean index c06095f8af584..fc6135c7832d0 100644 --- a/Mathlib/Init.lean +++ b/Mathlib/Init.lean @@ -1,6 +1,14 @@ +import Mathlib.Tactic.Linter.HashCommandLinter +import Mathlib.Tactic.Linter.GlobalAttributeIn +-- This file imports Batteries.Tactic.Lint, where the `env_linter` attribute is defined. +import Mathlib.Tactic.Linter.Lint +import Mathlib.Tactic.Linter.OldObtain +import Mathlib.Tactic.Linter.RefineLinter +import Mathlib.Tactic.Linter.UnusedTactic +import Mathlib.Tactic.Linter.Style + /-! This is the root file in Mathlib: it is imported by virtually *all* Mathlib files. - For this reason, the imports of this files are carefully curated. Any modification involving a change in the imports of this file should be discussed beforehand. @@ -9,4 +17,17 @@ Here are some general guidelines: * every import needs to have a comment explaining why the import is there; * strong preference for avoiding files that themselves have imports beyond `Lean`, and any exception to this rule should by accompanied by a comment explaining the transitive imports. + +## Linters + +All syntax linters defined in Mathlib which are active by default are imported here. +Syntax linters need to be imported to take effect, hence we would like them to be imported +as early as possible. + +All linters imported here have no bulk imports; +**Not** imported in this file are +- the text-based linters in `Linters/TextBased.lean`, as they can be imported later +- the `minImports` linter, as that is still disabled by default. +- the `haveLet` linter, as it is currently disabled by default + -/ diff --git a/Mathlib/Init/Algebra/Classes.lean b/Mathlib/Init/Algebra/Classes.lean index 0f9108a20df5d..e5149ae4efa16 100644 --- a/Mathlib/Init/Algebra/Classes.lean +++ b/Mathlib/Init/Algebra/Classes.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Leonardo de Moura -/ import Mathlib.Init.Logic +import Mathlib.Order.Defs /-! # Note about `Mathlib/Init/` @@ -13,6 +14,8 @@ The files in `Mathlib/Init` are leftovers from the port from Mathlib3. We intend to move all the content of these files out into the main `Mathlib` directory structure. Contributions assisting with this are appreciated. +(Yaël): The only things of interest in this file now are the unbundled algebra classes + # Unbundled algebra classes These classes are part of an incomplete refactor described @@ -67,6 +70,8 @@ Mario made the following analysis of uses in mathlib3: * `is_strict_total_order`: looks like the only usage is in `rbmap` again -/ +set_option linter.deprecated false + universe u v -- Porting note: removed `outParam` @@ -142,56 +147,12 @@ class is_idempotent (α : Sort u) (f : α → α) : Prop := (idempotent : ∀ a, f (f a) = f a) -/ -/-- `IsIrrefl X r` means the binary relation `r` on `X` is irreflexive (that is, `r x x` never -holds). -/ -class IsIrrefl (α : Sort u) (r : α → α → Prop) : Prop where - irrefl : ∀ a, ¬r a a - -/-- `IsRefl X r` means the binary relation `r` on `X` is reflexive. -/ -class IsRefl (α : Sort u) (r : α → α → Prop) : Prop where - refl : ∀ a, r a a - -/-- `IsSymm X r` means the binary relation `r` on `X` is symmetric. -/ -class IsSymm (α : Sort u) (r : α → α → Prop) : Prop where - symm : ∀ a b, r a b → r b a - /-- The opposite of a symmetric relation is symmetric. -/ instance (priority := 100) isSymmOp_of_isSymm (α : Sort u) (r : α → α → Prop) [IsSymm α r] : IsSymmOp α Prop r where symm_op a b := propext <| Iff.intro (IsSymm.symm a b) (IsSymm.symm b a) -/-- `IsAsymm X r` means that the binary relation `r` on `X` is asymmetric, that is, -`r a b → ¬ r b a`. -/ -class IsAsymm (α : Sort u) (r : α → α → Prop) : Prop where - asymm : ∀ a b, r a b → ¬r b a - -/-- `IsAntisymm X r` means the binary relation `r` on `X` is antisymmetric. -/ -class IsAntisymm (α : Sort u) (r : α → α → Prop) : Prop where - antisymm : ∀ a b, r a b → r b a → a = b - -instance (priority := 100) IsAsymm.toIsAntisymm {α : Sort u} (r : α → α → Prop) [IsAsymm α r] : - IsAntisymm α r where - antisymm _ _ hx hy := (IsAsymm.asymm _ _ hx hy).elim - -/-- `IsTrans X r` means the binary relation `r` on `X` is transitive. -/ -class IsTrans (α : Sort u) (r : α → α → Prop) : Prop where - trans : ∀ a b c, r a b → r b c → r a c - -instance {α : Sort u} {r : α → α → Prop} [IsTrans α r] : Trans r r r := - ⟨IsTrans.trans _ _ _⟩ - -instance (priority := 100) {α : Sort u} {r : α → α → Prop} [Trans r r r] : IsTrans α r := - ⟨fun _ _ _ => Trans.trans⟩ - -/-- `IsTotal X r` means that the binary relation `r` on `X` is total, that is, that for any -`x y : X` we have `r x y` or `r y x`. -/ -class IsTotal (α : Sort u) (r : α → α → Prop) : Prop where - total : ∀ a b, r a b ∨ r b a - -/-- `IsPreorder X r` means that the binary relation `r` on `X` is a pre-order, that is, reflexive -and transitive. -/ -class IsPreorder (α : Sort u) (r : α → α → Prop) extends IsRefl α r, IsTrans α r : Prop - /-- `IsTotalPreorder X r` means that the binary relation `r` on `X` is total and a preorder. -/ +@[deprecated (since := "2024-07-30")] class IsTotalPreorder (α : Sort u) (r : α → α → Prop) extends IsTrans α r, IsTotal α r : Prop /-- Every total pre-order is a pre-order. -/ @@ -200,51 +161,19 @@ instance (priority := 100) isTotalPreorder_isPreorder (α : Sort u) (r : α → trans := s.trans refl a := Or.elim (@IsTotal.total _ r _ a a) id id -/-- `IsPartialOrder X r` means that the binary relation `r` on `X` is a partial order, that is, -`IsPreorder X r` and `IsAntisymm X r`. -/ -class IsPartialOrder (α : Sort u) (r : α → α → Prop) extends IsPreorder α r, IsAntisymm α r : Prop - -/-- `IsLinearOrder X r` means that the binary relation `r` on `X` is a linear order, that is, -`IsPartialOrder X r` and `IsTotal X r`. -/ -class IsLinearOrder (α : Sort u) (r : α → α → Prop) extends IsPartialOrder α r, IsTotal α r : Prop - -/-- `IsEquiv X r` means that the binary relation `r` on `X` is an equivalence relation, that -is, `IsPreorder X r` and `IsSymm X r`. -/ -class IsEquiv (α : Sort u) (r : α → α → Prop) extends IsPreorder α r, IsSymm α r : Prop - -- /-- `IsPer X r` means that the binary relation `r` on `X` is a partial equivalence relation, that -- is, `IsSymm X r` and `IsTrans X r`. -/ -- class IsPer (α : Sort u) (r : α → α → Prop) extends IsSymm α r, IsTrans α r : Prop -/-- `IsStrictOrder X r` means that the binary relation `r` on `X` is a strict order, that is, -`IsIrrefl X r` and `IsTrans X r`. -/ -class IsStrictOrder (α : Sort u) (r : α → α → Prop) extends IsIrrefl α r, IsTrans α r : Prop - /-- `IsIncompTrans X lt` means that for `lt` a binary relation on `X`, the incomparable relation `fun a b => ¬ lt a b ∧ ¬ lt b a` is transitive. -/ +@[deprecated (since := "2024-07-30")] class IsIncompTrans (α : Sort u) (lt : α → α → Prop) : Prop where incomp_trans : ∀ a b c, ¬lt a b ∧ ¬lt b a → ¬lt b c ∧ ¬lt c b → ¬lt a c ∧ ¬lt c a -/-- `IsStrictWeakOrder X lt` means that the binary relation `lt` on `X` is a strict weak order, -that is, `IsStrictOrder X lt` and `IsIncompTrans X lt`. -/ -class IsStrictWeakOrder (α : Sort u) (lt : α → α → Prop) extends IsStrictOrder α lt, - IsIncompTrans α lt : Prop - -/-- `IsTrichotomous X lt` means that the binary relation `lt` on `X` is trichotomous, that is, -either `lt a b` or `a = b` or `lt b a` for any `a` and `b`. -/ -class IsTrichotomous (α : Sort u) (lt : α → α → Prop) : Prop where - trichotomous : ∀ a b, lt a b ∨ a = b ∨ lt b a - -/-- `IsStrictTotalOrder X lt` means that the binary relation `lt` on `X` is a strict total order, -that is, `IsTrichotomous X lt` and `IsStrictOrder X lt`. -/ -class IsStrictTotalOrder (α : Sort u) (lt : α → α → Prop) extends IsTrichotomous α lt, - IsStrictOrder α lt : Prop - -/-- Equality is an equivalence relation. -/ -instance eq_isEquiv (α : Sort u) : IsEquiv α (· = ·) where - symm := @Eq.symm _ - trans := @Eq.trans _ - refl := Eq.refl +@[deprecated (since := "2024-07-30")] +instance (priority := 100) (α : Sort u) (lt : α → α → Prop) [IsStrictWeakOrder α lt] : + IsIncompTrans α lt := { ‹IsStrictWeakOrder α lt› with } section @@ -252,68 +181,16 @@ variable {α : Sort u} {r : α → α → Prop} local infixl:50 " ≺ " => r -theorem irrefl [IsIrrefl α r] (a : α) : ¬a ≺ a := - IsIrrefl.irrefl a - -theorem refl [IsRefl α r] (a : α) : a ≺ a := - IsRefl.refl a - -theorem trans [IsTrans α r] {a b c : α} : a ≺ b → b ≺ c → a ≺ c := - IsTrans.trans _ _ _ - -theorem symm [IsSymm α r] {a b : α} : a ≺ b → b ≺ a := - IsSymm.symm _ _ - -theorem antisymm [IsAntisymm α r] {a b : α} : a ≺ b → b ≺ a → a = b := - IsAntisymm.antisymm _ _ - -theorem asymm [IsAsymm α r] {a b : α} : a ≺ b → ¬b ≺ a := - IsAsymm.asymm _ _ - -theorem trichotomous [IsTrichotomous α r] : ∀ a b : α, a ≺ b ∨ a = b ∨ b ≺ a := - IsTrichotomous.trichotomous - +@[deprecated (since := "2024-07-30")] theorem incomp_trans [IsIncompTrans α r] {a b c : α} : ¬a ≺ b ∧ ¬b ≺ a → ¬b ≺ c ∧ ¬c ≺ b → ¬a ≺ c ∧ ¬c ≺ a := IsIncompTrans.incomp_trans _ _ _ -instance (priority := 90) isAsymm_of_isTrans_of_isIrrefl [IsTrans α r] [IsIrrefl α r] : - IsAsymm α r := - ⟨fun a _b h₁ h₂ => absurd (_root_.trans h₁ h₂) (irrefl a)⟩ - section ExplicitRelationVariants variable (r) -@[elab_without_expected_type] -theorem irrefl_of [IsIrrefl α r] (a : α) : ¬a ≺ a := - irrefl a - -@[elab_without_expected_type] -theorem refl_of [IsRefl α r] (a : α) : a ≺ a := - refl a - -@[elab_without_expected_type] -theorem trans_of [IsTrans α r] {a b c : α} : a ≺ b → b ≺ c → a ≺ c := - _root_.trans - -@[elab_without_expected_type] -theorem symm_of [IsSymm α r] {a b : α} : a ≺ b → b ≺ a := - symm - -@[elab_without_expected_type] -theorem asymm_of [IsAsymm α r] {a b : α} : a ≺ b → ¬b ≺ a := - asymm - -@[elab_without_expected_type] -theorem total_of [IsTotal α r] (a b : α) : a ≺ b ∨ b ≺ a := - IsTotal.total _ _ - -@[elab_without_expected_type] -theorem trichotomous_of [IsTrichotomous α r] : ∀ a b : α, a ≺ b ∨ a = b ∨ b ≺ a := - trichotomous - -@[elab_without_expected_type] +@[elab_without_expected_type, deprecated (since := "2024-07-30")] theorem incomp_trans_of [IsIncompTrans α r] {a b c : α} : ¬a ≺ b ∧ ¬b ≺ a → ¬b ≺ c ∧ ¬c ≺ b → ¬a ≺ c ∧ ¬c ≺ a := incomp_trans @@ -330,25 +207,32 @@ variable {α : Sort u} {r : α → α → Prop} local infixl:50 " ≺ " => r +@[deprecated (since := "2024-07-30")] def Equiv (a b : α) : Prop := ¬a ≺ b ∧ ¬b ≺ a local infixl:50 " ≈ " => @Equiv _ r +@[deprecated (since := "2024-07-30")] theorem esymm {a b : α} : a ≈ b → b ≈ a := fun ⟨h₁, h₂⟩ => ⟨h₂, h₁⟩ +@[deprecated (since := "2024-07-30")] theorem not_lt_of_equiv {a b : α} : a ≈ b → ¬a ≺ b := fun h => h.1 +@[deprecated (since := "2024-07-30")] theorem not_lt_of_equiv' {a b : α} : a ≈ b → ¬b ≺ a := fun h => h.2 variable [IsStrictWeakOrder α r] +@[deprecated (since := "2024-07-30")] theorem erefl (a : α) : a ≈ a := ⟨irrefl a, irrefl a⟩ +@[deprecated (since := "2024-07-30")] theorem etrans {a b c : α} : a ≈ b → b ≈ c → a ≈ c := incomp_trans +@[deprecated (since := "2024-07-30")] instance isEquiv : IsEquiv α (@Equiv _ r) where refl := erefl trans _ _ _ := etrans @@ -361,6 +245,7 @@ notation:50 a " ≈[" lt "]" b:50 => @Equiv _ lt a b--Equiv (r := lt) a b end StrictWeakOrder +@[deprecated (since := "2024-07-30")] theorem isStrictWeakOrder_of_isTotalPreorder {α : Sort u} {le : α → α → Prop} {lt : α → α → Prop} [DecidableRel le] [IsTotalPreorder α le] (h : ∀ a b, lt a b ↔ ¬le b a) : IsStrictWeakOrder α lt := @@ -382,6 +267,25 @@ theorem isStrictWeakOrder_of_isTotalPreorder {α : Sort u} {le : α → α → P have hca : le c a := trans_of le hcb hba And.intro (fun n => absurd hca (Iff.mp (h _ _) n)) fun n => absurd hac (Iff.mp (h _ _) n) } +section LinearOrder +variable {α : Type*} [LinearOrder α] + +set_option linter.deprecated false in +@[deprecated (since := "2024-07-30")] +instance : IsTotalPreorder α (· ≤ ·) where + trans := @le_trans _ _ + total := le_total + +-- TODO(Leo): decide whether we should keep this instance or not +set_option linter.deprecated false in +@[deprecated (since := "2024-07-30")] +instance isStrictWeakOrder_of_linearOrder : IsStrictWeakOrder α (· < ·) := + have : IsTotalPreorder α (· ≤ ·) := by infer_instance -- Porting note: added + isStrictWeakOrder_of_isTotalPreorder lt_iff_not_ge + +end LinearOrder + +@[deprecated (since := "2024-07-30")] theorem lt_of_lt_of_incomp {α : Sort u} {lt : α → α → Prop} [IsStrictWeakOrder α lt] [DecidableRel lt] : ∀ {a b c}, lt a b → ¬lt b c ∧ ¬lt c b → lt a c := @fun a b c hab ⟨nbc, ncb⟩ => @@ -390,6 +294,7 @@ theorem lt_of_lt_of_incomp {α : Sort u} {lt : α → α → Prop} [IsStrictWeak have : ¬lt a b ∧ ¬lt b a := incomp_trans_of lt ⟨nac, nca⟩ ⟨ncb, nbc⟩ absurd hab this.1 +@[deprecated (since := "2024-07-30")] theorem lt_of_incomp_of_lt {α : Sort u} {lt : α → α → Prop} [IsStrictWeakOrder α lt] [DecidableRel lt] : ∀ {a b c}, ¬lt a b ∧ ¬lt b a → lt b c → lt a c := @fun a b c ⟨nab, nba⟩ hbc => @@ -398,6 +303,7 @@ theorem lt_of_incomp_of_lt {α : Sort u} {lt : α → α → Prop} [IsStrictWeak have : ¬lt b c ∧ ¬lt c b := incomp_trans_of lt ⟨nba, nab⟩ ⟨nac, nca⟩ absurd hbc this.1 +@[deprecated (since := "2024-07-30")] theorem eq_of_incomp {α : Sort u} {lt : α → α → Prop} [IsTrichotomous α lt] {a b} : ¬lt a b ∧ ¬lt b a → a = b := fun ⟨nab, nba⟩ => match trichotomous_of lt a b with @@ -405,17 +311,17 @@ theorem eq_of_incomp {α : Sort u} {lt : α → α → Prop} [IsTrichotomous α | Or.inr (Or.inl hab) => hab | Or.inr (Or.inr hba) => absurd hba nba +@[deprecated (since := "2024-07-30")] theorem eq_of_eqv_lt {α : Sort u} {lt : α → α → Prop} [IsTrichotomous α lt] {a b} : a ≈[lt]b → a = b := eq_of_incomp +@[deprecated (since := "2024-07-30")] theorem incomp_iff_eq {α : Sort u} {lt : α → α → Prop} [IsTrichotomous α lt] [IsIrrefl α lt] (a b) : ¬lt a b ∧ ¬lt b a ↔ a = b := Iff.intro eq_of_incomp fun hab => hab ▸ And.intro (irrefl_of lt a) (irrefl_of lt a) +@[deprecated (since := "2024-07-30")] theorem eqv_lt_iff_eq {α : Sort u} {lt : α → α → Prop} [IsTrichotomous α lt] [IsIrrefl α lt] (a b) : a ≈[lt]b ↔ a = b := incomp_iff_eq a b - -theorem not_lt_of_lt {α : Sort u} {lt : α → α → Prop} [IsStrictOrder α lt] {a b} : - lt a b → ¬lt b a := fun h₁ h₂ => absurd (trans_of lt h₁ h₂) (irrefl_of lt _) diff --git a/Mathlib/Init/Data/List/Lemmas.lean b/Mathlib/Init/Data/List/Lemmas.lean deleted file mode 100644 index d3326d2be2dba..0000000000000 --- a/Mathlib/Init/Data/List/Lemmas.lean +++ /dev/null @@ -1,96 +0,0 @@ -/- -Copyright (c) 2014 Parikshit Khanna. All rights reserved. -Released under Apache 2.0 license as described in the file LICENSE. -Authors: Parikshit Khanna, Jeremy Avigad, Leonardo de Moura, Floris van Doorn --/ -import Mathlib.Tactic.Cases -import Batteries.Logic - -/-! -# Note about `Mathlib/Init/` -The files in `Mathlib/Init` are leftovers from the port from Mathlib3. -(They contain content moved from lean3 itself that Mathlib needed but was not moved to lean4.) - -We intend to move all the content of these files out into the main `Mathlib` directory structure. -Contributions assisting with this are appreciated. - -# Lemmas for `List` not (yet) in `Batteries` --/ - -universe u v w w₁ w₂ - -variable {α : Type u} {β : Type v} {γ : Type w} - -namespace List - -open Nat - -/-! mem -/ - -theorem mem_cons_eq (a y : α) (l : List α) : (a ∈ y :: l) = (a = y ∨ a ∈ l) := - propext List.mem_cons - -alias ⟨eq_or_mem_of_mem_cons, _⟩ := mem_cons - -theorem not_exists_mem_nil (p : α → Prop) : ¬∃ x ∈ @nil α, p x := - fun ⟨_, hx, _⟩ => List.not_mem_nil _ hx - -@[deprecated (since := "2024-03-23")] alias not_bex_nil := not_exists_mem_nil -@[deprecated (since := "2024-03-23")] alias bex_cons := exists_mem_cons - -/-! sublists -/ - -alias length_le_of_sublist := Sublist.length_le - -/-! map_accumr -/ - -section MapAccumr - -variable {φ : Type w₁} {σ : Type w₂} - -/-- Runs a function over a list returning the intermediate results and a final result. -/ -def mapAccumr (f : α → σ → σ × β) : List α → σ → σ × List β - | [], c => (c, []) - | y :: yr, c => - let r := mapAccumr f yr c - let z := f y r.1 - (z.1, z.2 :: r.2) - -/-- Length of the list obtained by `mapAccumr`. -/ -@[simp] -theorem length_mapAccumr : - ∀ (f : α → σ → σ × β) (x : List α) (s : σ), length (mapAccumr f x s).2 = length x - | f, _ :: x, s => congr_arg succ (length_mapAccumr f x s) - | _, [], _ => rfl - -end MapAccumr - -section MapAccumr₂ - -variable {φ : Type w₁} {σ : Type w₂} - -/-- Runs a function over two lists returning the intermediate results and a final result. -/ -def mapAccumr₂ (f : α → β → σ → σ × φ) : List α → List β → σ → σ × List φ - | [], _, c => (c, []) - | _, [], c => (c, []) - | x :: xr, y :: yr, c => - let r := mapAccumr₂ f xr yr c - let q := f x y r.1 - (q.1, q.2 :: r.2) - -/-- Length of a list obtained using `mapAccumr₂`. -/ -@[simp] -theorem length_mapAccumr₂ : - ∀ (f : α → β → σ → σ × φ) (x y c), length (mapAccumr₂ f x y c).2 = min (length x) (length y) - | f, _ :: x, _ :: y, c => - calc - succ (length (mapAccumr₂ f x y c).2) = succ (min (length x) (length y)) := - congr_arg succ (length_mapAccumr₂ f x y c) - _ = min (succ (length x)) (succ (length y)) := Eq.symm (succ_min_succ (length x) (length y)) - | _, _ :: _, [], _ => rfl - | _, [], _ :: _, _ => rfl - | _, [], [], _ => rfl - -end MapAccumr₂ - -end List diff --git a/Mathlib/Init/Data/Nat/Lemmas.lean b/Mathlib/Init/Data/Nat/Lemmas.lean index 0117ea849a1e2..fe8bd94cacac2 100644 --- a/Mathlib/Init/Data/Nat/Lemmas.lean +++ b/Mathlib/Init/Data/Nat/Lemmas.lean @@ -24,22 +24,13 @@ namespace Nat /-! multiplication -/ -theorem eq_zero_of_mul_eq_zero {n m : ℕ} (h : n * m = 0) : n = 0 ∨ m = 0 := - mul_eq_zero.mp h - -/-! properties of inequality -/ - -protected def ltGeByCases {a b : ℕ} {C : Sort u} (h₁ : a < b → C) (h₂ : b ≤ a → C) : C := - Decidable.byCases h₁ fun h => h₂ (Or.elim (Nat.lt_or_ge a b) (fun a => absurd a h) fun a => a) - -protected def ltByCases {a b : ℕ} {C : Sort u} (h₁ : a < b → C) (h₂ : a = b → C) (h₃ : b < a → C) : - C := - Nat.ltGeByCases h₁ fun h₁ => Nat.ltGeByCases h₃ fun h => h₂ (Nat.le_antisymm h h₁) +@[deprecated (since := "2024-08-23")] alias ⟨eq_zero_of_mul_eq_zero, _⟩ := mul_eq_zero -- TODO: there are four variations, depending on which variables we assume to be nonneg /-! successor and predecessor -/ +@[deprecated (since := "2024-08-23")] def discriminate {B : Sort u} {n : ℕ} (H1 : n = 0 → B) (H2 : ∀ m, n = succ m → B) : B := by induction n with | zero => exact H1 rfl @@ -53,12 +44,6 @@ theorem one_eq_succ_zero : 1 = succ 0 := /-! induction principles -/ -def twoStepInduction {P : ℕ → Sort u} (H1 : P 0) (H2 : P 1) - (H3 : ∀ (n : ℕ) (_IH1 : P n) (_IH2 : P (succ n)), P (succ (succ n))) : ∀ a : ℕ, P a - | 0 => H1 - | 1 => H2 - | succ (succ _n) => H3 _ (twoStepInduction H1 H2 H3 _) (twoStepInduction H1 H2 H3 _) - -- Unused in Mathlib; -- if downstream projects find this essential please copy it or remove the deprecation. @[deprecated (since := "2024-07-27")] @@ -68,19 +53,6 @@ def subInduction {P : ℕ → ℕ → Sort u} (H1 : ∀ m, P 0 m) (H2 : ∀ n, P | succ _n, 0 => H2 _ | succ n, succ m => H3 _ _ (subInduction H1 H2 H3 n m) --- Porting note: added `elab_as_elim` -@[elab_as_elim] -protected theorem strong_induction_on {p : Nat → Prop} (n : Nat) - (h : ∀ n, (∀ m, m < n → p m) → p n) : p n := - Nat.strongRecOn n h - -protected theorem case_strong_induction_on {p : Nat → Prop} (a : Nat) (hz : p 0) - (hi : ∀ n, (∀ m, m ≤ n → p m) → p (succ n)) : p a := - Nat.strong_induction_on a fun n => - match n with - | 0 => fun _ => hz - | n + 1 => fun h₁ => hi n fun _m h₂ => h₁ _ (lt_succ_of_le h₂) - /-! mod -/ -- Unused in Mathlib; diff --git a/Mathlib/Init/Data/Quot.lean b/Mathlib/Init/Data/Quot.lean deleted file mode 100644 index 891d304ebce19..0000000000000 --- a/Mathlib/Init/Data/Quot.lean +++ /dev/null @@ -1,69 +0,0 @@ -/- -Copyright (c) 2015 Microsoft Corporation. All rights reserved. -Released under Apache 2.0 license as described in the file LICENSE. -Authors: Leonardo de Moura --/ - -import Mathlib.Init -/-! -# Note about `Mathlib/Init/` -The files in `Mathlib/Init` are leftovers from the port from Mathlib3. -(They contain content moved from lean3 itself that Mathlib needed but was not moved to lean4.) - -We intend to move all the content of these files out into the main `Mathlib` directory structure. -Contributions assisting with this are appreciated. - -# Quotient types - -These are ported from the Lean 3 standard library file `init/data/quot.lean`. --/ - -universe u - -section - -variable {α : Type u} -variable (r : α → α → Prop) - -/-- `EqvGen r` is the equivalence relation generated by `r`. -/ -inductive EqvGen : α → α → Prop - | rel : ∀ x y, r x y → EqvGen x y - | refl : ∀ x, EqvGen x x - | symm : ∀ x y, EqvGen x y → EqvGen y x - | trans : ∀ x y z, EqvGen x y → EqvGen y z → EqvGen x z - -theorem EqvGen.is_equivalence : Equivalence (@EqvGen α r) := - Equivalence.mk EqvGen.refl (EqvGen.symm _ _) (EqvGen.trans _ _ _) - -/-- `EqvGen.Setoid r` is the setoid generated by a relation `r`. - -The motivation for this definition is that `Quot r` behaves like `Quotient (EqvGen.Setoid r)`, -see for example `Quot.exact` and `Quot.EqvGen_sound`. --/ -def EqvGen.Setoid : Setoid α := - Setoid.mk _ (EqvGen.is_equivalence r) - -theorem Quot.exact {a b : α} (H : Quot.mk r a = Quot.mk r b) : EqvGen r a b := - @Quotient.exact _ (EqvGen.Setoid r) a b (congrArg - (Quot.lift (Quotient.mk (EqvGen.Setoid r)) (fun x y h ↦ Quot.sound (EqvGen.rel x y h))) H) - -theorem Quot.EqvGen_sound {r : α → α → Prop} {a b : α} (H : EqvGen r a b) : - Quot.mk r a = Quot.mk r b := - EqvGen.rec - (fun _ _ h ↦ Quot.sound h) - (fun _ ↦ rfl) - (fun _ _ _ IH ↦ Eq.symm IH) - (fun _ _ _ _ _ IH₁ IH₂ ↦ Eq.trans IH₁ IH₂) - H - -end - -open Decidable -instance Quotient.decidableEq {α : Sort u} {s : Setoid α} [d : ∀ a b : α, Decidable (a ≈ b)] : - DecidableEq (Quotient s) := - fun q₁ q₂ : Quotient s ↦ - Quotient.recOnSubsingleton₂ q₁ q₂ - (fun a₁ a₂ ↦ - match (d a₁ a₂) with - | (isTrue h₁) => isTrue (Quotient.sound h₁) - | (isFalse h₂) => isFalse (fun h ↦ absurd (Quotient.exact h) h₂)) diff --git a/Mathlib/Init/Logic.lean b/Mathlib/Init/Logic.lean index f6d926751096d..40c2fd17cf866 100644 --- a/Mathlib/Init/Logic.lean +++ b/Mathlib/Init/Logic.lean @@ -406,7 +406,7 @@ def RightCancelative := ∀ a b c, a * b = c * b → a = c def LeftDistributive := ∀ a b c, a * (b + c) = a * b + a * c def RightDistributive := ∀ a b c, (a + b) * c = a * c + b * c def RightCommutative (h : β → α → β) := ∀ b a₁ a₂, h (h b a₁) a₂ = h (h b a₂) a₁ -def LeftCommutative (h : α → β → β) := ∀ a₁ a₂ b, h a₁ (h a₂ b) = h a₂ (h a₁ b) +def LeftCommutative (h : α → β → β) := ∀ a₁ a₂ b, h a₁ (h a₂ b) = h a₂ (h a₁ b) theorem left_comm : Commutative f → Associative f → LeftCommutative f := fun hcomm hassoc a b c ↦ @@ -417,7 +417,7 @@ theorem left_comm : Commutative f → Associative f → LeftCommutative f := theorem right_comm : Commutative f → Associative f → RightCommutative f := fun hcomm hassoc a b c ↦ - calc (a*b)*c + calc (a*b)*c _ = a*(b*c) := hassoc a b c _ = a*(c*b) := hcomm b c ▸ rfl _ = (a*c)*b := Eq.symm (hassoc a c b) diff --git a/Mathlib/Init/Order/LinearOrder.lean b/Mathlib/Init/Order/LinearOrder.lean deleted file mode 100644 index 6a9a98b19129a..0000000000000 --- a/Mathlib/Init/Order/LinearOrder.lean +++ /dev/null @@ -1,150 +0,0 @@ -/- -Copyright (c) 2016 Microsoft Corporation. All rights reserved. -Released under Apache 2.0 license as described in the file LICENSE. -Authors: Jeremy Avigad, Leonardo de Moura --/ -import Mathlib.Order.Defs - -/-! -# Note about `Mathlib/Init/` -The files in `Mathlib/Init` are leftovers from the port from Mathlib3. -(They contain content moved from lean3 itself that Mathlib needed but was not moved to lean4.) - -We intend to move all the content of these files out into the main `Mathlib` directory structure. -Contributions assisting with this are appreciated. - -# Basic lemmas about linear orders. - -The contents of this file came from `init.algebra.functions` in Lean 3, -and it would be good to find everything a better home. --/ - -universe u - -section - -open Decidable - -variable {α : Type u} [LinearOrder α] - -theorem min_def (a b : α) : min a b = if a ≤ b then a else b := by - rw [LinearOrder.min_def a] - -theorem max_def (a b : α) : max a b = if a ≤ b then b else a := by - rw [LinearOrder.max_def a] - -theorem min_le_left (a b : α) : min a b ≤ a := by - -- Porting note: no `min_tac` tactic - if h : a ≤ b - then simp [min_def, if_pos h, le_refl] - else simp [min_def, if_neg h]; exact le_of_not_le h - -theorem min_le_right (a b : α) : min a b ≤ b := by - -- Porting note: no `min_tac` tactic - if h : a ≤ b - then simp [min_def, if_pos h]; exact h - else simp [min_def, if_neg h, le_refl] - -theorem le_min {a b c : α} (h₁ : c ≤ a) (h₂ : c ≤ b) : c ≤ min a b := by - -- Porting note: no `min_tac` tactic - if h : a ≤ b - then simp [min_def, if_pos h]; exact h₁ - else simp [min_def, if_neg h]; exact h₂ - -theorem le_max_left (a b : α) : a ≤ max a b := by - -- Porting note: no `min_tac` tactic - if h : a ≤ b - then simp [max_def, if_pos h]; exact h - else simp [max_def, if_neg h, le_refl] - -theorem le_max_right (a b : α) : b ≤ max a b := by - -- Porting note: no `min_tac` tactic - if h : a ≤ b - then simp [max_def, if_pos h, le_refl] - else simp [max_def, if_neg h]; exact le_of_not_le h - -theorem max_le {a b c : α} (h₁ : a ≤ c) (h₂ : b ≤ c) : max a b ≤ c := by - -- Porting note: no `min_tac` tactic - if h : a ≤ b - then simp [max_def, if_pos h]; exact h₂ - else simp [max_def, if_neg h]; exact h₁ - -theorem eq_min {a b c : α} (h₁ : c ≤ a) (h₂ : c ≤ b) (h₃ : ∀ {d}, d ≤ a → d ≤ b → d ≤ c) : - c = min a b := - le_antisymm (le_min h₁ h₂) (h₃ (min_le_left a b) (min_le_right a b)) - -theorem min_comm (a b : α) : min a b = min b a := - eq_min (min_le_right a b) (min_le_left a b) fun h₁ h₂ => le_min h₂ h₁ - -theorem 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 - -theorem min_left_comm : ∀ a b c : α, min a (min b c) = min b (min a c) := - left_comm (@min α _) (@min_comm α _) (@min_assoc α _) - -@[simp] -theorem min_self (a : α) : min a a = a := by simp [min_def] - -theorem min_eq_left {a b : α} (h : a ≤ b) : min a b = a := by - apply Eq.symm; apply eq_min (le_refl _) h; intros; assumption - -theorem min_eq_right {a b : α} (h : b ≤ a) : min a b = b := - min_comm b a ▸ min_eq_left h - -theorem eq_max {a b c : α} (h₁ : a ≤ c) (h₂ : b ≤ c) (h₃ : ∀ {d}, a ≤ d → b ≤ d → c ≤ d) : - c = max a b := - le_antisymm (h₃ (le_max_left a b) (le_max_right a b)) (max_le h₁ h₂) - -theorem max_comm (a b : α) : max a b = max b a := - eq_max (le_max_right a b) (le_max_left a b) fun h₁ h₂ => max_le h₂ h₁ - -theorem 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₂ - -theorem max_left_comm : ∀ a b c : α, max a (max b c) = max b (max a c) := - left_comm (@max α _) (@max_comm α _) (@max_assoc α _) - -@[simp] -theorem max_self (a : α) : max a a = a := by simp [max_def] - -theorem max_eq_left {a b : α} (h : b ≤ a) : max a b = a := by - apply Eq.symm; apply eq_max (le_refl _) h; intros; assumption - -theorem max_eq_right {a b : α} (h : a ≤ b) : max a b = b := - max_comm b a ▸ max_eq_left h - --- these rely on lt_of_lt -theorem min_eq_left_of_lt {a b : α} (h : a < b) : min a b = a := - min_eq_left (le_of_lt h) - -theorem min_eq_right_of_lt {a b : α} (h : b < a) : min a b = b := - min_eq_right (le_of_lt h) - -theorem max_eq_left_of_lt {a b : α} (h : b < a) : max a b = a := - max_eq_left (le_of_lt h) - -theorem max_eq_right_of_lt {a b : α} (h : a < b) : max a b = b := - max_eq_right (le_of_lt h) - --- these use the fact that it is a linear ordering -theorem lt_min {a b c : α} (h₁ : a < b) (h₂ : a < c) : a < min b c := - -- Porting note: no `min_tac` tactic - Or.elim (le_or_gt b c) - (fun h : b ≤ c ↦ by rwa [min_eq_left h]) - (fun h : b > c ↦ by rwa [min_eq_right_of_lt h]) - -theorem max_lt {a b c : α} (h₁ : a < c) (h₂ : b < c) : max a b < c := - -- Porting note: no `min_tac` tactic - Or.elim (le_or_gt a b) - (fun h : a ≤ b ↦ by rwa [max_eq_right h]) - (fun h : a > b ↦ by rwa [max_eq_left_of_lt h]) - -end diff --git a/Mathlib/Init/Quot.lean b/Mathlib/Init/Quot.lean deleted file mode 100644 index 5db59383719ff..0000000000000 --- a/Mathlib/Init/Quot.lean +++ /dev/null @@ -1,43 +0,0 @@ -/- -Copyright (c) 2023 Microsoft Corporation. All rights reserved. -Released under Apache 2.0 license as described in the file LICENSE. -Authors: Johan Commelin --/ - -import Mathlib.Init -/-! -# Note about `Mathlib/Init/` -The files in `Mathlib/Init` are leftovers from the port from Mathlib3. -(They contain content moved from lean3 itself that Mathlib needed but was not moved to lean4.) - -We intend to move all the content of these files out into the main `Mathlib` directory structure. -Contributions assisting with this are appreciated. - -# Quot - -Some induction principles tagged with `elab_as_elim`, since the attribute is missing in core. --/ - -universe u v -variable {α : Sort u} {r : α → α → Prop} {motive : Quot r → Sort v} - -@[inherit_doc Quot.rec, elab_as_elim] -- Porting note: adding `elab_as_elim` -protected abbrev Quot.recOn' - (q : Quot r) - (f : (a : α) → motive (Quot.mk r a)) - (h : (a b : α) → (p : r a b) → Eq.ndrec (f a) (Quot.sound p) = f b) : - motive q := - q.rec f h - -/-- Version of `Quot.recOnSubsingleton` tagged with `elab_as_elim` -/ -@[elab_as_elim] -- Porting note: this attribute is missing in core -protected abbrev Quot.recOnSubsingleton' - [h : (a : α) → Subsingleton (motive (Quot.mk r a))] - (q : Quot r) - (f : (a : α) → motive (Quot.mk r a)) : - motive q := by - induction q using Quot.rec - apply f - apply Subsingleton.elim - -theorem Quotient.mk'_eq_mk [s : Setoid α] : Quotient.mk' = Quotient.mk s := rfl diff --git a/Mathlib/Init/Set.lean b/Mathlib/Init/Set.lean deleted file mode 100644 index 9f91aa04e1f49..0000000000000 --- a/Mathlib/Init/Set.lean +++ /dev/null @@ -1,273 +0,0 @@ -/- -Copyright (c) 2016 Microsoft Corporation. All rights reserved. -Released under Apache 2.0 license as described in the file LICENSE. -Authors: Leonardo de Moura --/ -import Mathlib.Init -import Batteries.Util.ExtendedBinder -import Lean.Elab.Term - -/-! -# Note about `Mathlib/Init/` -The files in `Mathlib/Init` are leftovers from the port from Mathlib3. -(They contain content moved from lean3 itself that Mathlib needed but was not moved to lean4.) - -We intend to move all the content of these files out into the main `Mathlib` directory structure. -Contributions assisting with this are appreciated. - -# Sets - -This file sets up the theory of sets whose elements have a given type. - -## Main definitions - -Given a type `X` and a predicate `p : X → Prop`: - -* `Set X` : the type of sets whose elements have type `X` -* `{a : X | p a} : Set X` : the set of all elements of `X` satisfying `p` -* `{a | p a} : Set X` : a more concise notation for `{a : X | p a}` -* `{f x y | (x : X) (y : Y)} : Set Z` : a more concise notation for `{z : Z | ∃ x y, f x y = z}` -* `{a ∈ S | p a} : Set X` : given `S : Set X`, the subset of `S` consisting of - its elements satisfying `p`. - -## Implementation issues - -As in Lean 3, `Set X := X → Prop` - -I didn't call this file Data.Set.Basic because it contains core Lean 3 -stuff which happens before mathlib3's data.set.basic . -This file is a port of the core Lean 3 file `lib/lean/library/init/data/set.lean`. - --/ - -open Lean Elab Term Meta Batteries.ExtendedBinder - -universe u -variable {α : Type u} - -/-- A set is a collection of elements of some type `α`. - -Although `Set` is defined as `α → Prop`, this is an implementation detail which should not be -relied on. Instead, `setOf` and membership of a set (`∈`) should be used to convert between sets -and predicates. --/ -def Set (α : Type u) := α → Prop - -/-- Turn a predicate `p : α → Prop` into a set, also written as `{x | p x}` -/ -def setOf {α : Type u} (p : α → Prop) : Set α := - p - -namespace Set - -/-- Membership in a set -/ -protected def Mem (a : α) (s : Set α) : Prop := - s a - -instance : Membership α (Set α) := - ⟨Set.Mem⟩ - -theorem ext {a b : Set α} (h : ∀ (x : α), x ∈ a ↔ x ∈ b) : a = b := - funext (fun x ↦ propext (h x)) - - -/-- The subset relation on sets. `s ⊆ t` means that all elements of `s` are elements of `t`. - -Note that you should **not** use this definition directly, but instead write `s ⊆ t`. -/ -protected def Subset (s₁ s₂ : Set α) := - ∀ ⦃a⦄, a ∈ s₁ → a ∈ s₂ - -/-- Porting note: we introduce `≤` before `⊆` to help the unifier when applying lattice theorems -to subset hypotheses. -/ -instance : LE (Set α) := - ⟨Set.Subset⟩ - -instance : HasSubset (Set α) := - ⟨(· ≤ ·)⟩ - -instance : EmptyCollection (Set α) := - ⟨fun _ ↦ False⟩ - -end Set - -namespace Mathlib.Meta - -/-- Set builder syntax. This can be elaborated to either a `Set` or a `Finset` depending on context. - -The elaborators for this syntax are located in: -* `Init.Set` for the `Set` builder notation elaborator for syntax of the form `{x | p x}`, - `{x : α | p x}`, `{binder x | p x}`. -* `Data.Finset.Basic` for the `Finset` builder notation elaborator for syntax of the form - `{x ∈ s | p x}`. -* `Data.Fintype.Basic` for the `Finset` builder notation elaborator for syntax of the form - `{x | p x}`, `{x : α | p x}`, `{x ∉ s | p x}`, `{x ≠ a | p x}`. -* `Order.LocallyFinite.Basic` for the `Finset` builder notation elaborator for syntax of the form - `{x ≤ a | p x}`, `{x ≥ a | p x}`, `{x < a | p x}`, `{x > a | p x}`. --/ -syntax (name := setBuilder) "{" extBinder " | " term "}" : term - -/-- Elaborate set builder notation for `Set`. - -* `{x | p x}` is elaborated as `Set.setOf fun x ↦ p x` -* `{x : α | p x}` is elaborated as `Set.setOf fun x : α ↦ p x` -* `{binder x | p x}`, where `x` is bound by the `binder` binder, is elaborated as - `{x | binder x ∧ p x}`. The typical example is `{x ∈ s | p x}`, which is elaborated as - `{x | x ∈ s ∧ p x}`. The possible binders are - * `· ∈ s`, `· ∉ s` - * `· ⊆ s`, `· ⊂ s`, `· ⊇ s`, `· ⊃ s` - * `· ≤ a`, `· ≥ a`, `· < a`, `· > a`, `· ≠ a` - - More binders can be declared using the `binder_predicate` command, see `Init.BinderPredicates` for - more info. - -See also -* `Data.Finset.Basic` for the `Finset` builder notation elaborator partly overriding this one for - syntax of the form `{x ∈ s | p x}`. -* `Data.Fintype.Basic` for the `Finset` builder notation elaborator partly overriding this one for - syntax of the form `{x | p x}`, `{x : α | p x}`, `{x ∉ s | p x}`, `{x ≠ a | p x}`. -* `Order.LocallyFinite.Basic` for the `Finset` builder notation elaborator partly overriding this - one for syntax of the form `{x ≤ a | p x}`, `{x ≥ a | p x}`, `{x < a | p x}`, `{x > a | p x}`. --/ -@[term_elab setBuilder] -def elabSetBuilder : TermElab - | `({ $x:ident | $p }), expectedType? => do - elabTerm (← `(setOf fun $x:ident ↦ $p)) expectedType? - | `({ $x:ident : $t | $p }), expectedType? => do - elabTerm (← `(setOf fun $x:ident : $t ↦ $p)) expectedType? - | `({ $x:ident $b:binderPred | $p }), expectedType? => do - elabTerm (← `(setOf fun $x:ident ↦ satisfies_binder_pred% $x $b ∧ $p)) expectedType? - | _, _ => throwUnsupportedSyntax - -/-- Unexpander for set builder notation. -/ -@[app_unexpander setOf] -def setOf.unexpander : Lean.PrettyPrinter.Unexpander - | `($_ fun $x:ident ↦ $p) => `({ $x:ident | $p }) - | `($_ fun ($x:ident : $ty:term) ↦ $p) => `({ $x:ident : $ty:term | $p }) - | _ => throw () - -open Batteries.ExtendedBinder in -/-- -`{ f x y | (x : X) (y : Y) }` is notation for the set of elements `f x y` constructed from the -binders `x` and `y`, equivalent to `{z : Z | ∃ x y, f x y = z}`. - -If `f x y` is a single identifier, it must be parenthesized to avoid ambiguity with `{x | p x}`; -for instance, `{(x) | (x : Nat) (y : Nat) (_hxy : x = y^2)}`. --/ -macro (priority := low) "{" t:term " | " bs:extBinders "}" : term => - `({x | ∃ᵉ $bs:extBinders, $t = x}) - -/-- -* `{ pat : X | p }` is notation for pattern matching in set-builder notation, - where `pat` is a pattern that is matched by all objects of type `X` - and `p` is a proposition that can refer to variables in the pattern. - It is the set of all objects of type `X` which, when matched with the pattern `pat`, - make `p` come out true. -* `{ pat | p }` is the same, but in the case when the type `X` can be inferred. - -For example, `{ (m, n) : ℕ × ℕ | m * n = 12 }` denotes the set of all ordered pairs of -natural numbers whose product is 12. - -Note that if the type ascription is left out and `p` can be interpreted as an extended binder, -then the extended binder interpretation will be used. For example, `{ n + 1 | n < 3 }` will -be interpreted as `{ x : Nat | ∃ n < 3, n + 1 = x }` rather than using pattern matching. --/ -macro (name := macroPattSetBuilder) (priority := low-1) - "{" pat:term " : " t:term " | " p:term "}" : term => - `({ x : $t | match x with | $pat => $p }) - -@[inherit_doc macroPattSetBuilder] -macro (priority := low-1) "{" pat:term " | " p:term "}" : term => - `({ x | match x with | $pat => $p }) - -/-- Pretty printing for set-builder notation with pattern matching. -/ -@[app_unexpander setOf] -def setOfPatternMatchUnexpander : Lean.PrettyPrinter.Unexpander - | `($_ fun $x:ident ↦ match $y:ident with | $pat => $p) => - if x == y then - `({ $pat:term | $p:term }) - else - throw () - | `($_ fun ($x:ident : $ty:term) ↦ match $y:ident with | $pat => $p) => - if x == y then - `({ $pat:term : $ty:term | $p:term }) - else - throw () - | _ => throw () - -end Mathlib.Meta - -namespace Set - -/-- The universal set on a type `α` is the set containing all elements of `α`. - -This is conceptually the "same as" `α` (in set theory, it is actually the same), but type theory -makes the distinction that `α` is a type while `Set.univ` is a term of type `Set α`. `Set.univ` can -itself be coerced to a type `↥Set.univ` which is in bijection with (but distinct from) `α`. -/ -def univ : Set α := {_a | True} - -/-- `Set.insert a s` is the set `{a} ∪ s`. - -Note that you should **not** use this definition directly, but instead write `insert a s` (which is -mediated by the `Insert` typeclass). -/ -protected def insert (a : α) (s : Set α) : Set α := {b | b = a ∨ b ∈ s} - -instance : Insert α (Set α) := ⟨Set.insert⟩ - -/-- The singleton of an element `a` is the set with `a` as a single element. - -Note that you should **not** use this definition directly, but instead write `{a}`. -/ -protected def singleton (a : α) : Set α := {b | b = a} - -instance instSingletonSet : Singleton α (Set α) := ⟨Set.singleton⟩ - -/-- The union of two sets `s` and `t` is the set of elements contained in either `s` or `t`. - -Note that you should **not** use this definition directly, but instead write `s ∪ t`. -/ -protected def union (s₁ s₂ : Set α) : Set α := {a | a ∈ s₁ ∨ a ∈ s₂} - -instance : Union (Set α) := ⟨Set.union⟩ - -/-- The intersection of two sets `s` and `t` is the set of elements contained in both `s` and `t`. - -Note that you should **not** use this definition directly, but instead write `s ∩ t`. -/ -protected def inter (s₁ s₂ : Set α) : Set α := {a | a ∈ s₁ ∧ a ∈ s₂} - -instance : Inter (Set α) := ⟨Set.inter⟩ - -/-- The complement of a set `s` is the set of elements not contained in `s`. - -Note that you should **not** use this definition directly, but instead write `sᶜ`. -/ -protected def compl (s : Set α) : Set α := {a | a ∉ s} - -/-- The difference of two sets `s` and `t` is the set of elements contained in `s` but not in `t`. - -Note that you should **not** use this definition directly, but instead write `s \ t`. -/ -protected def diff (s t : Set α) : Set α := {a ∈ s | a ∉ t} - -instance : SDiff (Set α) := ⟨Set.diff⟩ - -/-- `𝒫 s` is the set of all subsets of `s`. -/ -def powerset (s : Set α) : Set (Set α) := {t | t ⊆ s} - -@[inherit_doc] prefix:100 "𝒫" => powerset - -universe v in -/-- The image of `s : Set α` by `f : α → β`, written `f '' s`, is the set of `b : β` such that -`f a = b` for some `a ∈ s`. -/ -def image {β : Type v} (f : α → β) (s : Set α) : Set β := {f a | a ∈ s} - -instance : Functor Set where map := @Set.image - -instance : LawfulFunctor Set where - id_map _ := funext fun _ ↦ propext ⟨fun ⟨_, sb, rfl⟩ ↦ sb, fun sb ↦ ⟨_, sb, rfl⟩⟩ - comp_map g h _ := funext <| fun c ↦ propext - ⟨fun ⟨a, ⟨h₁, h₂⟩⟩ ↦ ⟨g a, ⟨⟨a, ⟨h₁, rfl⟩⟩, h₂⟩⟩, - fun ⟨_, ⟨⟨a, ⟨h₁, h₂⟩⟩, h₃⟩⟩ ↦ ⟨a, ⟨h₁, show h (g a) = c from h₂ ▸ h₃⟩⟩⟩ - map_const := rfl - -/-- The property `s.Nonempty` expresses the fact that the set `s` is not empty. It should be used -in theorem assumptions instead of `∃ x, x ∈ s` or `s ≠ ∅` as it gives access to a nice API thanks -to the dot notation. -/ -protected def Nonempty (s : Set α) : Prop := - ∃ x, x ∈ s - -end Set diff --git a/Mathlib/Lean/Expr/Basic.lean b/Mathlib/Lean/Expr/Basic.lean index 0a3a8fa1db16f..cd4f02368e68b 100644 --- a/Mathlib/Lean/Expr/Basic.lean +++ b/Mathlib/Lean/Expr/Basic.lean @@ -8,7 +8,8 @@ import Mathlib.Init import Lean.Meta.Tactic.Rewrite import Batteries.Lean.Expr import Batteries.Data.Rat.Basic -import Batteries.Data.List.Basic +import Batteries.Tactic.Alias +import Lean.Elab.Binders /-! # Additional operations on Expr and related types diff --git a/Mathlib/Lean/Expr/ExtraRecognizers.lean b/Mathlib/Lean/Expr/ExtraRecognizers.lean index ebb2efb0cde41..b8ca5f661228f 100644 --- a/Mathlib/Lean/Expr/ExtraRecognizers.lean +++ b/Mathlib/Lean/Expr/ExtraRecognizers.lean @@ -3,7 +3,7 @@ Copyright (c) 2023 Kyle Miller. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kyle Miller -/ -import Mathlib.Data.Set.Defs +import Mathlib.Data.Set.Operations /-! # Additional Expr recognizers needing theory imports diff --git a/Mathlib/Lean/Meta/CongrTheorems.lean b/Mathlib/Lean/Meta/CongrTheorems.lean index 0d86cfc7904ae..a8dafe249c20f 100644 --- a/Mathlib/Lean/Meta/CongrTheorems.lean +++ b/Mathlib/Lean/Meta/CongrTheorems.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Kyle Miller -/ import Lean.Meta.Tactic.Cleanup -import Lean.Meta.Tactic.Cases import Lean.Meta.Tactic.Refl import Mathlib.Logic.IsEmpty @@ -129,7 +128,7 @@ instance {α : Sort u} [inst : FastIsEmpty α] {β : (x : α) → Sort v} : instance {α : Sort u} {β : (x : α) → Sort v} [inst : ∀ x, FastSubsingleton (β x)] : FastSubsingleton ((x : α) → β x) where - inst := have := λ x => (inst x).inst; inferInstance + inst := have := fun x ↦ (inst x).inst; inferInstance /-- Runs `mx` in a context where all local `Subsingleton` and `IsEmpty` instances @@ -285,8 +284,8 @@ where let rec loop (i : Nat) (ftyx ftyy : Expr) (xs ys : Array Expr) (fixed' : Array Bool) : MetaM α := do if i < numVars then - let ftyx ← whnf ftyx - let ftyy ← whnf ftyy + let ftyx ← whnfD ftyx + let ftyy ← whnfD ftyy unless ftyx.isForall do throwError "doubleTelescope: function doesn't have enough parameters" withLocalDeclD ftyx.bindingName! ftyx.bindingDomain! fun fvarx => do diff --git a/Mathlib/Lean/Thunk.lean b/Mathlib/Lean/Thunk.lean index e9d504dff0852..9ec29601a07ca 100644 --- a/Mathlib/Lean/Thunk.lean +++ b/Mathlib/Lean/Thunk.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Simon Hudon -/ import Mathlib.Init -import Batteries.Data.Thunk /-! # Basic facts about `Thunk`. diff --git a/Mathlib/LinearAlgebra/AffineSpace/AffineMap.lean b/Mathlib/LinearAlgebra/AffineSpace/AffineMap.lean index 75c1550c86990..b66ea39b78a5a 100644 --- a/Mathlib/LinearAlgebra/AffineSpace/AffineMap.lean +++ b/Mathlib/LinearAlgebra/AffineSpace/AffineMap.lean @@ -710,7 +710,7 @@ variable [Finite ι] [DecidableEq ι] {f g : ((i : ι) → φv i) →ᵃ[k] P2} /-- Two affine maps from a Pi-tyoe of modules `(i : ι) → φv i` are equal if they are equal in their operation on `Pi.single` and at zero. Analogous to `LinearMap.pi_ext`. See also `pi_ext_nonempty`, - which instead of agrement at zero requires `Nonempty ι`. -/ + which instead of agreement at zero requires `Nonempty ι`. -/ theorem pi_ext_zero (h : ∀ i x, f (Pi.single i x) = g (Pi.single i x)) (h₂ : f 0 = g 0) : f = g := by apply ext_linear diff --git a/Mathlib/LinearAlgebra/AffineSpace/AffineSubspace.lean b/Mathlib/LinearAlgebra/AffineSpace/AffineSubspace.lean index 3dff1b6db9f72..ab4b6063b2c23 100644 --- a/Mathlib/LinearAlgebra/AffineSpace/AffineSubspace.lean +++ b/Mathlib/LinearAlgebra/AffineSpace/AffineSubspace.lean @@ -230,7 +230,6 @@ theorem vadd_mem_of_mem_direction {s : AffineSubspace k P} {v : V} (hv : v ∈ s rw [hv] convert s.smul_vsub_vadd_mem 1 hp1 hp2 hp rw [one_smul] - exact s.mem_coe k P _ /-- Subtracting two points in the subspace produces a vector in the direction. -/ theorem vsub_mem_direction {s : AffineSubspace k P} {p1 p2 : P} (hp1 : p1 ∈ s) (hp2 : p2 ∈ s) : @@ -732,8 +731,10 @@ theorem card_pos_of_affineSpan_eq_top {ι : Type*} [Fintype ι] {p : ι → P} attribute [local instance] toAddTorsor -/-- The top affine subspace is linearly equivalent to the affine space. +-- An instance with better keys for the context +instance : Nonempty (⊤ : AffineSubspace k P) := inferInstanceAs (Nonempty (⊤ : Set P)) +/-- The top affine subspace is linearly equivalent to the affine space. This is the affine version of `Submodule.topEquiv`. -/ @[simps! linear apply symm_apply_coe] def topEquiv : (⊤ : AffineSubspace k P) ≃ᵃ[k] P where @@ -1691,3 +1692,5 @@ theorem affineSpan_pair_parallel_iff_vectorSpan_eq {p₁ p₂ p₃ p₄ : P} : not_nonempty_iff_eq_empty] end AffineSubspace + +set_option linter.style.longFile 1800 diff --git a/Mathlib/LinearAlgebra/AffineSpace/Combination.lean b/Mathlib/LinearAlgebra/AffineSpace/Combination.lean index ae32ab4bf5651..74aad257f2367 100644 --- a/Mathlib/LinearAlgebra/AffineSpace/Combination.lean +++ b/Mathlib/LinearAlgebra/AffineSpace/Combination.lean @@ -903,13 +903,13 @@ theorem weightedVSub_mem_vectorSpan {s : Finset ι} {w : ι → k} (h : ∑ i rcases isEmpty_or_nonempty ι with (hι | ⟨⟨i0⟩⟩) · simp [Finset.eq_empty_of_isEmpty s] · rw [vectorSpan_range_eq_span_range_vsub_right k p i0, ← Set.image_univ, - Finsupp.mem_span_image_iff_total, + Finsupp.mem_span_image_iff_linearCombination, Finset.weightedVSub_eq_weightedVSubOfPoint_of_sum_eq_zero s w p h (p i0), Finset.weightedVSubOfPoint_apply] let w' := Set.indicator (↑s) w have hwx : ∀ i, w' i ≠ 0 → i ∈ s := fun i => Set.mem_of_indicator_ne_zero use Finsupp.onFinset s w' hwx, Set.subset_univ _ - rw [Finsupp.total_apply, Finsupp.onFinset_sum hwx] + rw [Finsupp.linearCombination_apply, Finsupp.onFinset_sum hwx] · apply Finset.sum_congr rfl intro i hi simp [w', Set.indicator_apply, if_pos hi] @@ -954,7 +954,7 @@ theorem mem_vectorSpan_iff_eq_weightedVSub {v : V} {p : ι → P} : · rcases isEmpty_or_nonempty ι with (hι | ⟨⟨i0⟩⟩) swap · rw [vectorSpan_range_eq_span_range_vsub_right k p i0, ← Set.image_univ, - Finsupp.mem_span_image_iff_total] + Finsupp.mem_span_image_iff_linearCombination] rintro ⟨l, _, hv⟩ use insert i0 l.support set w := @@ -972,7 +972,7 @@ theorem mem_vectorSpan_iff_eq_weightedVSub {v : V} {p : ι → P} : have hz : w i0 • (p i0 -ᵥ p i0 : V) = 0 := (vsub_self (p i0)).symm ▸ smul_zero _ change (fun i => w i • (p i -ᵥ p i0 : V)) i0 = 0 at hz rw [Finset.weightedVSub_eq_weightedVSubOfPoint_of_sum_eq_zero _ w p hw (p i0), - Finset.weightedVSubOfPoint_apply, ← hv, Finsupp.total_apply, + Finset.weightedVSubOfPoint_apply, ← hv, Finsupp.linearCombination_apply, @Finset.sum_insert_zero _ _ l.support i0 _ _ _ hz] change (∑ i ∈ l.support, l i • _) = _ congr with i diff --git a/Mathlib/LinearAlgebra/AffineSpace/ContinuousAffineEquiv.lean b/Mathlib/LinearAlgebra/AffineSpace/ContinuousAffineEquiv.lean index 0360e2114a8d9..12ffbd6ace838 100644 --- a/Mathlib/LinearAlgebra/AffineSpace/ContinuousAffineEquiv.lean +++ b/Mathlib/LinearAlgebra/AffineSpace/ContinuousAffineEquiv.lean @@ -174,14 +174,12 @@ theorem apply_eq_iff_eq (e : P₁ ≃ᵃL[k] P₂) {p₁ p₂ : P₁} : e p₁ = e.toEquiv.apply_eq_iff_eq @[simp] -theorem symm_symm (e : P₁ ≃ᵃL[k] P₂) : e.symm.symm = e := by - ext x - rfl +theorem symm_symm (e : P₁ ≃ᵃL[k] P₂) : e.symm.symm = e := rfl theorem symm_symm_apply (e : P₁ ≃ᵃL[k] P₂) (x : P₁) : e.symm.symm x = e x := rfl -theorem symm_apply_eq (e : P₁ ≃ᵃL[k] P₂) {x y} : e.symm x = y ↔ x = e y := +theorem symm_apply_eq (e : P₁ ≃ᵃL[k] P₂) {x y} : e.symm x = y ↔ x = e y := e.toAffineEquiv.symm_apply_eq theorem eq_symm_apply (e : P₁ ≃ᵃL[k] P₂) {x y} : y = e.symm x ↔ e y = x := diff --git a/Mathlib/LinearAlgebra/AffineSpace/Matrix.lean b/Mathlib/LinearAlgebra/AffineSpace/Matrix.lean index 5ee4cb759178f..3ed1a0ba08f47 100644 --- a/Mathlib/LinearAlgebra/AffineSpace/Matrix.lean +++ b/Mathlib/LinearAlgebra/AffineSpace/Matrix.lean @@ -61,7 +61,7 @@ theorem affineIndependent_of_toMatrix_right_inv [Fintype ι] [Finite ι'] [Decid ext j change (∑ i, w₁ i • b.coord j (p i)) = ∑ i, w₂ i • b.coord j (p i) -- Porting note: Added `u` because `∘` was causing trouble - have u : (fun i => b.coord j (p i)) = b.coord j ∘ p := by simp only [(· ∘ ·)] + have u : (fun i => b.coord j (p i)) = b.coord j ∘ p := by simp only [Function.comp_def] rw [← Finset.univ.affineCombination_eq_linear_combination _ _ hw₁, ← Finset.univ.affineCombination_eq_linear_combination _ _ hw₂, u, ← Finset.univ.map_affineCombination p w₁ hw₁, ← Finset.univ.map_affineCombination p w₂ hw₂, diff --git a/Mathlib/LinearAlgebra/AffineSpace/Ordered.lean b/Mathlib/LinearAlgebra/AffineSpace/Ordered.lean index 7835a5c734a01..bc28ee54454cb 100644 --- a/Mathlib/LinearAlgebra/AffineSpace/Ordered.lean +++ b/Mathlib/LinearAlgebra/AffineSpace/Ordered.lean @@ -4,9 +4,10 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov -/ import Mathlib.Algebra.CharP.Invertible +import Mathlib.Algebra.Order.Group.Instances import Mathlib.Algebra.Order.Invertible import Mathlib.Algebra.Order.Module.OrderedSMul -import Mathlib.Algebra.Order.Group.Instances +import Mathlib.Algebra.Order.Module.Synonym import Mathlib.LinearAlgebra.AffineSpace.Slope import Mathlib.LinearAlgebra.AffineSpace.Midpoint import Mathlib.Tactic.FieldSimp diff --git a/Mathlib/LinearAlgebra/Alternating/Basic.lean b/Mathlib/LinearAlgebra/Alternating/Basic.lean index 90b2803f45d8e..3c306db16e0ea 100644 --- a/Mathlib/LinearAlgebra/Alternating/Basic.lean +++ b/Mathlib/LinearAlgebra/Alternating/Basic.lean @@ -656,10 +656,10 @@ def domDomCongrEquiv (σ : ι ≃ ι') : M [⋀^ι]→ₗ[R] N ≃+ M [⋀^ι'] invFun := domDomCongr σ.symm left_inv f := by ext - simp [Function.comp] + simp [Function.comp_def] right_inv m := by ext - simp [Function.comp] + simp [Function.comp_def] map_add' := domDomCongr_add σ section DomDomLcongr @@ -671,8 +671,8 @@ variable (S : Type*) [Semiring S] [Module S N] [SMulCommClass R S N] def domDomCongrₗ (σ : ι ≃ ι') : M [⋀^ι]→ₗ[R] N ≃ₗ[S] M [⋀^ι']→ₗ[R] N where toFun := domDomCongr σ invFun := domDomCongr σ.symm - left_inv f := by ext; simp [Function.comp] - right_inv m := by ext; simp [Function.comp] + left_inv f := by ext; simp [Function.comp_def] + right_inv m := by ext; simp [Function.comp_def] map_add' := domDomCongr_add σ map_smul' := domDomCongr_smul σ diff --git a/Mathlib/LinearAlgebra/Alternating/DomCoprod.lean b/Mathlib/LinearAlgebra/Alternating/DomCoprod.lean index ce50529aa2ab6..7ae6931a6aa29 100644 --- a/Mathlib/LinearAlgebra/Alternating/DomCoprod.lean +++ b/Mathlib/LinearAlgebra/Alternating/DomCoprod.lean @@ -233,8 +233,8 @@ theorem MultilinearMap.domCoprod_alternization [DecidableEq ιa] [DecidableEq ι fun x _ => QuotientGroup.eq (s := MonoidHom.range (Perm.sumCongrHom ιa ιb)) (a := x) (b := σ)] -- eliminate a multiplication rw [← Finset.map_univ_equiv (Equiv.mulLeft σ), Finset.filter_map, Finset.sum_map] - simp_rw [Equiv.coe_toEmbedding, Equiv.coe_mulLeft, (· ∘ ·), mul_inv_rev, inv_mul_cancel_right, - Subgroup.inv_mem_iff, MonoidHom.mem_range, Finset.univ_filter_exists, + simp_rw [Equiv.coe_toEmbedding, Equiv.coe_mulLeft, Function.comp_def, mul_inv_rev, + inv_mul_cancel_right, Subgroup.inv_mem_iff, MonoidHom.mem_range, Finset.univ_filter_exists, Finset.sum_image Perm.sumCongrHom_injective.injOn] -- now we're ready to clean up the RHS, pulling out the summation rw [domCoprod.summand_mk'', MultilinearMap.domCoprod_alternization_coe, ← Finset.sum_product', diff --git a/Mathlib/LinearAlgebra/Basis/Basic.lean b/Mathlib/LinearAlgebra/Basis/Basic.lean index bbf77e0742586..67204421b86e3 100644 --- a/Mathlib/LinearAlgebra/Basis/Basic.lean +++ b/Mathlib/LinearAlgebra/Basis/Basic.lean @@ -22,7 +22,7 @@ noncomputable section universe u -open Function Set Submodule +open Function Set Submodule Finsupp variable {ι : Type*} {ι' : Type*} {R : Type*} {R₂ : Type*} {K : Type*} variable {M : Type*} {M' M'' : Type*} {V : Type u} {V' : Type*} @@ -51,7 +51,7 @@ end Coord protected theorem linearIndependent : LinearIndependent R b := linearIndependent_iff.mpr fun l hl => calc - l = b.repr (Finsupp.total _ _ _ b l) := (b.repr_total l).symm + l = b.repr (Finsupp.linearCombination _ b l) := (b.repr_linearCombination l).symm _ = 0 := by rw [hl, LinearEquiv.map_zero] protected theorem ne_zero [Nontrivial R] (i) : b i ≠ 0 := @@ -125,7 +125,7 @@ protected theorem noZeroSMulDivisors [NoZeroDivisors R] (b : Basis ι R M) : NoZeroSMulDivisors R M := ⟨fun {c x} hcx => by exact or_iff_not_imp_right.mpr fun hx => by - rw [← b.total_repr x, ← LinearMap.map_smul] at hcx + rw [← b.linearCombination_repr x, ← LinearMap.map_smul] at hcx have := linearIndependent_iff.mp b.linearIndependent (c • b.repr x) hcx rw [smul_eq_zero] at this exact this.resolve_right fun hr => hx (b.repr.map_eq_zero_iff.mp hr)⟩ @@ -203,17 +203,18 @@ theorem maximal [Nontrivial R] (b : Basis ι R M) : b.linearIndependent.Maximal intro x p by_contra q -- and write it in terms of the basis. - have e := b.total_repr x + have e := b.linearCombination_repr x -- This then expresses `x` as a linear combination -- of elements of `w` which are in the range of `b`, let u : ι ↪ w := ⟨fun i => ⟨b i, h ⟨i, rfl⟩⟩, fun i i' r => b.injective (by simpa only [Subtype.mk_eq_mk] using r)⟩ - simp_rw [Finsupp.total_apply] at e + simp_rw [Finsupp.linearCombination_apply] at e change ((b.repr x).sum fun (i : ι) (a : R) ↦ a • (u i : M)) = ((⟨x, p⟩ : w) : M) at e - rw [← Finsupp.sum_embDomain (f := u) (g := fun x r ↦ r • (x : M)), ← Finsupp.total_apply] at e + rw [← Finsupp.sum_embDomain (f := u) (g := fun x r ↦ r • (x : M)), + ← Finsupp.linearCombination_apply] at e -- Now we can contradict the linear independence of `hi` - refine hi.total_ne_of_not_mem_support _ ?_ e + refine hi.linearCombination_ne_of_not_mem_support _ ?_ e simp only [Finset.mem_map, Finsupp.support_embDomain] rintro ⟨j, -, W⟩ simp only [u, Embedding.coeFn_mk, Subtype.mk_eq_mk] at W @@ -227,8 +228,8 @@ variable (hli : LinearIndependent R v) (hsp : ⊤ ≤ span R (range v)) protected noncomputable def mk : Basis ι R M := .ofRepr { hli.repr.comp (LinearMap.id.codRestrict _ fun _ => hsp Submodule.mem_top) with - invFun := Finsupp.total _ _ _ v - left_inv := fun x => hli.total_repr ⟨x, _⟩ + invFun := Finsupp.linearCombination _ v + left_inv := fun x => hli.linearCombination_repr ⟨x, _⟩ right_inv := fun _ => hli.repr_eq rfl } @[simp] @@ -236,7 +237,7 @@ theorem mk_repr : (Basis.mk hli hsp).repr x = hli.repr ⟨x, hsp Submodule.mem_t rfl theorem mk_apply (i : ι) : Basis.mk hli hsp i = v i := - show Finsupp.total _ _ _ v _ = v i by simp + show Finsupp.linearCombination _ v _ = v i by simp @[simp] theorem coe_mk : ⇑(Basis.mk hli hsp) = v := @@ -492,28 +493,31 @@ lemma Basis.mem_center_iff {A} constructor case comm => intro y - rw [← b.total_repr y, Finsupp.total_apply, Finsupp.sum, Finset.sum_mul, Finset.mul_sum] + rw [← b.linearCombination_repr y, linearCombination_apply, sum, Finset.sum_mul, + Finset.mul_sum] simp_rw [mul_smul_comm, smul_mul_assoc, (h.1 _).eq] case left_assoc => intro c d - rw [← b.total_repr c, ← b.total_repr d, Finsupp.total_apply, Finsupp.total_apply, Finsupp.sum, - Finsupp.sum, Finset.sum_mul, Finset.mul_sum, Finset.mul_sum, Finset.mul_sum] + rw [← b.linearCombination_repr c, ← b.linearCombination_repr d, linearCombination_apply, + linearCombination_apply, sum, sum, Finset.sum_mul, Finset.mul_sum, Finset.mul_sum, + Finset.mul_sum] simp_rw [smul_mul_assoc, Finset.mul_sum, Finset.sum_mul, mul_smul_comm, Finset.mul_sum, Finset.smul_sum, smul_mul_assoc, mul_smul_comm, (h.2 _ _).1, (@SMulCommClass.smul_comm R R A)] rw [Finset.sum_comm] case mid_assoc => intro c d - rw [← b.total_repr c, ← b.total_repr d, Finsupp.total_apply, Finsupp.total_apply, Finsupp.sum, - Finsupp.sum, Finset.sum_mul, Finset.mul_sum, Finset.mul_sum, Finset.mul_sum] + rw [← b.linearCombination_repr c, ← b.linearCombination_repr d, linearCombination_apply, + linearCombination_apply, sum, sum, Finset.sum_mul, Finset.mul_sum, Finset.mul_sum, + Finset.mul_sum] simp_rw [smul_mul_assoc, Finset.sum_mul, mul_smul_comm, smul_mul_assoc, (h.2 _ _).2.1] case right_assoc => intro c d - rw [← b.total_repr c, ← b.total_repr d, Finsupp.total_apply, Finsupp.total_apply, Finsupp.sum, - Finsupp.sum, Finset.sum_mul] + rw [← b.linearCombination_repr c, ← b.linearCombination_repr d, linearCombination_apply, + linearCombination_apply, sum, Finsupp.sum, Finset.sum_mul] simp_rw [smul_mul_assoc, Finset.mul_sum, Finset.sum_mul, mul_smul_comm, Finset.mul_sum, - Finset.smul_sum, smul_mul_assoc, mul_smul_comm, Finset.sum_mul, smul_mul_assoc, - (h.2 _ _).2.2] + Finset.smul_sum, smul_mul_assoc, mul_smul_comm, Finset.sum_mul, smul_mul_assoc, + (h.2 _ _).2.2] section RestrictScalars @@ -553,7 +557,7 @@ theorem Basis.mem_span_iff_repr_mem (m : M) : refine ⟨fun hm i => ⟨(b.restrictScalars R).repr ⟨m, hm⟩ i, b.restrictScalars_repr_apply R ⟨m, hm⟩ i⟩, fun h => ?_⟩ - rw [← b.total_repr m, Finsupp.total_apply S _] + rw [← b.linearCombination_repr m, Finsupp.linearCombination_apply S _] refine sum_mem fun i _ => ?_ obtain ⟨_, h⟩ := h i simp_rw [← h, algebraMap_smul] diff --git a/Mathlib/LinearAlgebra/Basis/Bilinear.lean b/Mathlib/LinearAlgebra/Basis/Bilinear.lean index dd756b57e5821..ec749b417a941 100644 --- a/Mathlib/LinearAlgebra/Basis/Bilinear.lean +++ b/Mathlib/LinearAlgebra/Basis/Bilinear.lean @@ -41,8 +41,8 @@ Version for semi-bilinear maps, see `sum_repr_mul_repr_mul` for the bilinear ver theorem sum_repr_mul_repr_mulₛₗ {B : M →ₛₗ[ρ₁₂] N →ₛₗ[σ₁₂] P} (x y) : ((b₁.repr x).sum fun i xi => (b₂.repr y).sum fun j yj => ρ₁₂ xi • σ₁₂ yj • B (b₁ i) (b₂ j)) = B x y := by - conv_rhs => rw [← b₁.total_repr x, ← b₂.total_repr y] - simp_rw [Finsupp.total_apply, Finsupp.sum, map_sum₂, map_sum, LinearMap.map_smulₛₗ₂, + conv_rhs => rw [← b₁.linearCombination_repr x, ← b₂.linearCombination_repr y] + simp_rw [Finsupp.linearCombination_apply, Finsupp.sum, map_sum₂, map_sum, LinearMap.map_smulₛₗ₂, LinearMap.map_smulₛₗ] /-- Write out `B x y` as a sum over `B (b i) (b j)` if `b` is a basis. @@ -51,8 +51,8 @@ Version for bilinear maps, see `sum_repr_mul_repr_mulₛₗ` for the semi-biline theorem sum_repr_mul_repr_mul {B : Mₗ →ₗ[Rₗ] Nₗ →ₗ[Rₗ] Pₗ} (x y) : ((b₁'.repr x).sum fun i xi => (b₂'.repr y).sum fun j yj => xi • yj • B (b₁' i) (b₂' j)) = B x y := by - conv_rhs => rw [← b₁'.total_repr x, ← b₂'.total_repr y] - simp_rw [Finsupp.total_apply, Finsupp.sum, map_sum₂, map_sum, LinearMap.map_smul₂, + conv_rhs => rw [← b₁'.linearCombination_repr x, ← b₂'.linearCombination_repr y] + simp_rw [Finsupp.linearCombination_apply, Finsupp.sum, map_sum₂, map_sum, LinearMap.map_smul₂, LinearMap.map_smul] end AddCommMonoid diff --git a/Mathlib/LinearAlgebra/Basis/Cardinality.lean b/Mathlib/LinearAlgebra/Basis/Cardinality.lean index 74b34a45465d4..fb70ac8a04ff1 100644 --- a/Mathlib/LinearAlgebra/Basis/Cardinality.lean +++ b/Mathlib/LinearAlgebra/Basis/Cardinality.lean @@ -12,7 +12,7 @@ import Mathlib.SetTheory.Cardinal.Cofinality section Finite -open Basis Cardinal Set Submodule +open Basis Cardinal Set Submodule Finsupp universe u v v' v'' u₁' w w' @@ -49,7 +49,7 @@ lemma basis_finite_of_finite_spans (w : Set M) (hw : w.Finite) (s : span R w = let bS : Set M := b '' S have h : ∀ x ∈ w, x ∈ span R bS := by intro x m - rw [← b.total_repr x, Finsupp.span_image_eq_map_total, Submodule.mem_map] + rw [← b.linearCombination_repr x, span_image_eq_map_linearCombination, Submodule.mem_map] use b.repr x simp only [and_true_iff, eq_self_iff_true, Finsupp.mem_supported] rw [Finset.coe_subset, ← Finset.le_iff_subset] @@ -101,9 +101,9 @@ theorem union_support_maximal_linearIndependent_eq_range_basis {ι : Type w} (b apply LinearIndependent.to_subtype_range rw [linearIndependent_iff] intro l z - rw [Finsupp.total_option] at z + rw [Finsupp.linearCombination_option] at z simp only [v', Option.elim'] at z - change _ + Finsupp.total κ M R v l.some = 0 at z + change _ + Finsupp.linearCombination R v l.some = 0 at z -- We have some linear combination of `b b'` and the `v i`, which we want to show is trivial. -- We'll first show the coefficient of `b b'` is zero, -- by expressing the `v i` in the basis `b`, and using that the `v i` have no `b b'` term. @@ -113,8 +113,9 @@ theorem union_support_maximal_linearIndependent_eq_range_basis {ι : Type w} (b apply_fun fun x => b.repr x b' at z simp only [repr_self, map_smul, mul_one, Finsupp.single_eq_same, Pi.neg_apply, Finsupp.smul_single', map_neg, Finsupp.coe_neg] at z - erw [DFunLike.congr_fun (Finsupp.apply_total R (b.repr : M →ₗ[R] ι →₀ R) v l.some) b'] at z - simpa [Finsupp.total_apply, w] using z + erw [DFunLike.congr_fun (apply_linearCombination R (b.repr : M →ₗ[R] ι →₀ R) v l.some) b'] + at z + simpa [Finsupp.linearCombination_apply, w] using z -- Then all the other coefficients are zero, because `v` is linear independent. have l₁ : l.some = 0 := by rw [l₀, zero_smul, zero_add] at z diff --git a/Mathlib/LinearAlgebra/Basis/Defs.lean b/Mathlib/LinearAlgebra/Basis/Defs.lean index 23deb6b640ceb..c731874f77c56 100644 --- a/Mathlib/LinearAlgebra/Basis/Defs.lean +++ b/Mathlib/LinearAlgebra/Basis/Defs.lean @@ -59,7 +59,7 @@ noncomputable section universe u -open Function Set Submodule +open Function Set Submodule Finsupp variable {ι : Type*} {ι' : Type*} {R : Type*} {R₂ : Type*} {K : Type*} variable {M : Type*} {M' M'' : Type*} {V : Type u} {V' : Type*} @@ -134,36 +134,42 @@ theorem repr_self_apply (j) [Decidable (i = j)] : b.repr (b i) j = if i = j then rw [repr_self, Finsupp.single_apply] @[simp] -theorem repr_symm_apply (v) : b.repr.symm v = Finsupp.total ι M R b v := +theorem repr_symm_apply (v) : b.repr.symm v = Finsupp.linearCombination R b v := calc b.repr.symm v = b.repr.symm (v.sum Finsupp.single) := by simp _ = v.sum fun i vi => b.repr.symm (Finsupp.single i vi) := map_finsupp_sum .. - _ = Finsupp.total ι M R b v := by simp only [repr_symm_single, Finsupp.total_apply] + _ = Finsupp.linearCombination R b v := by simp only [repr_symm_single, + Finsupp.linearCombination_apply] @[simp] -theorem coe_repr_symm : ↑b.repr.symm = Finsupp.total ι M R b := +theorem coe_repr_symm : ↑b.repr.symm = Finsupp.linearCombination R b := LinearMap.ext fun v => b.repr_symm_apply v @[simp] -theorem repr_total (v) : b.repr (Finsupp.total _ _ _ b v) = v := by +theorem repr_linearCombination (v) : b.repr (Finsupp.linearCombination _ b v) = v := by rw [← b.coe_repr_symm] exact b.repr.apply_symm_apply v +@[deprecated (since := "2024-08-29")] alias repr_total := repr_linearCombination + @[simp] -theorem total_repr : Finsupp.total _ _ _ b (b.repr x) = x := by +theorem linearCombination_repr : Finsupp.linearCombination _ b (b.repr x) = x := by rw [← b.coe_repr_symm] exact b.repr.symm_apply_apply x +@[deprecated (since := "2024-08-29")] alias total_repr := linearCombination_repr + theorem repr_range : LinearMap.range (b.repr : M →ₗ[R] ι →₀ R) = Finsupp.supported R R univ := by rw [LinearEquiv.range, Finsupp.supported_univ] theorem mem_span_repr_support (m : M) : m ∈ span R (b '' (b.repr m).support) := - (Finsupp.mem_span_image_iff_total _).2 ⟨b.repr m, by simp [Finsupp.mem_supported_support]⟩ + (Finsupp.mem_span_image_iff_linearCombination _).2 + ⟨b.repr m, by simp [Finsupp.mem_supported_support]⟩ theorem repr_support_subset_of_mem_span (s : Set ι) {m : M} (hm : m ∈ span R (b '' s)) : ↑(b.repr m).support ⊆ s := by - rcases (Finsupp.mem_span_image_iff_total _).1 hm with ⟨l, hl, rfl⟩ - rwa [repr_total, ← Finsupp.mem_supported R l] + rcases (Finsupp.mem_span_image_iff_linearCombination _).1 hm with ⟨l, hl, rfl⟩ + rwa [repr_linearCombination, ← Finsupp.mem_supported R l] theorem mem_span_image {m : M} {s : Set ι} : m ∈ span R (b '' s) ↔ ↑(b.repr m).support ⊆ s := ⟨repr_support_subset_of_mem_span _ _, fun h ↦ @@ -219,7 +225,7 @@ theorem dvd_coord_smul (i : ι) (m : M) (r : R) : r ∣ b.coord i (r • m) := theorem coord_repr_symm (b : Basis ι R M) (i : ι) (f : ι →₀ R) : b.coord i (b.repr.symm f) = f i := by - simp only [repr_symm_apply, coord_apply, repr_total] + simp only [repr_symm_apply, coord_apply, repr_linearCombination] end Coord @@ -232,13 +238,13 @@ variable {M₁ : Type*} [AddCommMonoid M₁] [Module R₁ M₁] /-- Two linear maps are equal if they are equal on basis vectors. -/ theorem ext {f₁ f₂ : M →ₛₗ[σ] M₁} (h : ∀ i, f₁ (b i) = f₂ (b i)) : f₁ = f₂ := by ext x - rw [← b.total_repr x, Finsupp.total_apply, Finsupp.sum] + rw [← b.linearCombination_repr x, Finsupp.linearCombination_apply, Finsupp.sum] simp only [map_sum, LinearMap.map_smulₛₗ, h] /-- Two linear equivs are equal if they are equal on basis vectors. -/ theorem ext' {f₁ f₂ : M ≃ₛₗ[σ] M₁} (h : ∀ i, f₁ (b i) = f₂ (b i)) : f₁ = f₂ := by ext x - rw [← b.total_repr x, Finsupp.total_apply, Finsupp.sum] + rw [← b.linearCombination_repr x, Finsupp.linearCombination_apply, Finsupp.sum] simp only [map_sum, LinearEquiv.map_smulₛₗ, h] /-- Two elements are equal iff their coordinates are equal. -/ @@ -532,8 +538,8 @@ theorem mem_submodule_iff {P : Submodule R M} (b : Basis ι R P) {x : M} : x ∈ P ↔ ∃ c : ι →₀ R, x = Finsupp.sum c fun i x => x • (b i : M) := by conv_lhs => rw [← P.range_subtype, ← Submodule.map_top, ← b.span_eq, Submodule.map_span, ← Set.range_comp, - ← Finsupp.range_total] - simp [@eq_comm _ x, Function.comp, Finsupp.total_apply] + ← Finsupp.range_linearCombination] + simp [@eq_comm _ x, Function.comp, Finsupp.linearCombination_apply] section Constr @@ -551,7 +557,7 @@ you can recover an `AddEquiv` by setting `S := ℕ`. See library note [bundled maps over different rings]. -/ def constr : (ι → M') ≃ₗ[S] M →ₗ[R] M' where - toFun f := (Finsupp.total M' M' R id).comp <| Finsupp.lmapDomain R R f ∘ₗ ↑b.repr + toFun f := (Finsupp.linearCombination R id).comp <| Finsupp.lmapDomain R R f ∘ₗ ↑b.repr invFun f i := f (b i) left_inv f := by ext @@ -567,12 +573,12 @@ def constr : (ι → M') ≃ₗ[S] M →ₗ[R] M' where simp theorem constr_def (f : ι → M') : - constr (M' := M') b S f = Finsupp.total M' M' R id ∘ₗ Finsupp.lmapDomain R R f ∘ₗ ↑b.repr := + constr (M' := M') b S f = linearCombination R id ∘ₗ Finsupp.lmapDomain R R f ∘ₗ ↑b.repr := rfl theorem constr_apply (f : ι → M') (x : M) : constr (M' := M') b S f x = (b.repr x).sum fun b a => a • f b := by - simp only [constr_def, LinearMap.comp_apply, Finsupp.lmapDomain_apply, Finsupp.total_apply] + simp only [constr_def, LinearMap.comp_apply, lmapDomain_apply, linearCombination_apply] rw [Finsupp.sum_mapDomain_index] <;> simp [add_smul] @[simp] @@ -590,7 +596,7 @@ theorem constr_range {f : ι → M'} : LinearMap.range (constr (M' := M') b S f) = span R (range f) := by rw [b.constr_def S f, LinearMap.range_comp, LinearMap.range_comp, LinearEquiv.range, ← Finsupp.supported_univ, Finsupp.lmapDomain_supported, ← Set.image_univ, ← - Finsupp.span_image_eq_map_total, Set.image_id] + Finsupp.span_image_eq_map_linearCombination, Set.image_id] @[simp] theorem constr_comp (f : M' →ₗ[R] M') (v : ι → M') : @@ -704,7 +710,7 @@ a function `x : ι → R` to the linear combination `∑_i x i • v i`. -/ @[simp] theorem Basis.equivFun_symm_apply [Fintype ι] (b : Basis ι R M) (x : ι → R) : b.equivFun.symm x = ∑ i, x i • b i := by - simp [Basis.equivFun, Finsupp.total_apply, Finsupp.sum_fintype, Finsupp.equivFunOnFinite] + simp [Basis.equivFun, Finsupp.linearCombination_apply, sum_fintype, equivFunOnFinite] @[simp] theorem Basis.equivFun_apply [Finite ι] (b : Basis ι R M) (u : M) : b.equivFun u = b.repr u := diff --git a/Mathlib/LinearAlgebra/BilinearForm/Hom.lean b/Mathlib/LinearAlgebra/BilinearForm/Hom.lean index 9e99d5b63ae90..f32f28e8aea31 100644 --- a/Mathlib/LinearAlgebra/BilinearForm/Hom.lean +++ b/Mathlib/LinearAlgebra/BilinearForm/Hom.lean @@ -347,8 +347,8 @@ theorem ext_basis (h : ∀ i j, B (b i) (b j) = F₂ (b i) (b j)) : B = F₂ := /-- Write out `B x y` as a sum over `B (b i) (b j)` if `b` is a basis. -/ theorem sum_repr_mul_repr_mul (x y : M) : ((b.repr x).sum fun i xi => (b.repr y).sum fun j yj => xi • yj • B (b i) (b j)) = B x y := by - conv_rhs => rw [← b.total_repr x, ← b.total_repr y] - simp_rw [Finsupp.total_apply, Finsupp.sum, sum_left, sum_right, smul_left, smul_right, + conv_rhs => rw [← b.linearCombination_repr x, ← b.linearCombination_repr y] + simp_rw [Finsupp.linearCombination_apply, Finsupp.sum, sum_left, sum_right, smul_left, smul_right, smul_eq_mul] end Basis diff --git a/Mathlib/LinearAlgebra/BilinearForm/Orthogonal.lean b/Mathlib/LinearAlgebra/BilinearForm/Orthogonal.lean index fb7036771789e..f4d1dcbf680e7 100644 --- a/Mathlib/LinearAlgebra/BilinearForm/Orthogonal.lean +++ b/Mathlib/LinearAlgebra/BilinearForm/Orthogonal.lean @@ -217,7 +217,7 @@ theorem iIsOrtho.not_isOrtho_basis_self_of_nondegenerate {n : Type w} [Nontrivia intro ho refine v.ne_zero i (hB (v i) fun m => ?_) obtain ⟨vi, rfl⟩ := v.repr.symm.surjective m - rw [Basis.repr_symm_apply, Finsupp.total_apply, Finsupp.sum, sum_right] + rw [Basis.repr_symm_apply, Finsupp.linearCombination_apply, Finsupp.sum, sum_right] apply Finset.sum_eq_zero rintro j - rw [smul_right] @@ -237,7 +237,8 @@ theorem iIsOrtho.nondegenerate_iff_not_isOrtho_basis_self {n : Type w} [Nontrivi ext i rw [Finsupp.zero_apply] specialize hB (v i) - simp_rw [Basis.repr_symm_apply, Finsupp.total_apply, Finsupp.sum, sum_left, smul_left] at hB + simp_rw [Basis.repr_symm_apply, Finsupp.linearCombination_apply, Finsupp.sum, sum_left, + smul_left] at hB rw [Finset.sum_eq_single i] at hB · exact eq_zero_of_ne_zero_of_mul_right_eq_zero (ho i) hB · intro j _ hij diff --git a/Mathlib/LinearAlgebra/BilinearForm/TensorProduct.lean b/Mathlib/LinearAlgebra/BilinearForm/TensorProduct.lean index eb6892bb52914..d7ab301e16a91 100644 --- a/Mathlib/LinearAlgebra/BilinearForm/TensorProduct.lean +++ b/Mathlib/LinearAlgebra/BilinearForm/TensorProduct.lean @@ -30,8 +30,7 @@ namespace LinearMap namespace BilinMap -open LinearMap (BilinMap) -open LinearMap (BilinForm) +open LinearMap (BilinMap BilinForm) section CommSemiring variable [CommSemiring R] [CommSemiring A] diff --git a/Mathlib/LinearAlgebra/CliffordAlgebra/Basic.lean b/Mathlib/LinearAlgebra/CliffordAlgebra/Basic.lean index ac24ee710f6f0..8f6b4168968e9 100644 --- a/Mathlib/LinearAlgebra/CliffordAlgebra/Basic.lean +++ b/Mathlib/LinearAlgebra/CliffordAlgebra/Basic.lean @@ -185,7 +185,7 @@ theorem hom_ext {A : Type*} [Semiring A] [Algebra R A] {f g : CliffordAlgebra Q -- This proof closely follows `TensorAlgebra.induction` /-- If `C` holds for the `algebraMap` of `r : R` into `CliffordAlgebra Q`, the `ι` of `x : M`, -and is preserved under addition and muliplication, then it holds for all of `CliffordAlgebra Q`. +and is preserved under addition and multiplication, then it holds for all of `CliffordAlgebra Q`. See also the stronger `CliffordAlgebra.left_induction` and `CliffordAlgebra.right_induction`. -/ diff --git a/Mathlib/LinearAlgebra/CliffordAlgebra/Contraction.lean b/Mathlib/LinearAlgebra/CliffordAlgebra/Contraction.lean index 978452899a1a5..8ef0b35b3f973 100644 --- a/Mathlib/LinearAlgebra/CliffordAlgebra/Contraction.lean +++ b/Mathlib/LinearAlgebra/CliffordAlgebra/Contraction.lean @@ -40,8 +40,7 @@ Within this file, we use the local notation -/ -open LinearMap (BilinMap) -open LinearMap (BilinForm) +open LinearMap (BilinMap BilinForm) universe u1 u2 u3 diff --git a/Mathlib/LinearAlgebra/CliffordAlgebra/Equivs.lean b/Mathlib/LinearAlgebra/CliffordAlgebra/Equivs.lean index 64eab0f1101ed..30687d5b35594 100644 --- a/Mathlib/LinearAlgebra/CliffordAlgebra/Equivs.lean +++ b/Mathlib/LinearAlgebra/CliffordAlgebra/Equivs.lean @@ -358,7 +358,7 @@ variable {R M : Type*} [CommRing R] [AddCommGroup M] [Module R M] theorem ι_mul_ι (r₁ r₂) : ι (0 : QuadraticForm R R) r₁ * ι (0 : QuadraticForm R R) r₂ = 0 := by rw [← mul_one r₁, ← mul_one r₂, ← smul_eq_mul R, ← smul_eq_mul R, LinearMap.map_smul, - LinearMap.map_smul, smul_mul_smul, ι_sq_scalar, QuadraticMap.zero_apply, RingHom.map_zero, + LinearMap.map_smul, smul_mul_smul_comm, ι_sq_scalar, QuadraticMap.zero_apply, RingHom.map_zero, smul_zero] /-- The clifford algebra over a 1-dimensional vector space with 0 quadratic form is isomorphic to diff --git a/Mathlib/LinearAlgebra/CliffordAlgebra/Even.lean b/Mathlib/LinearAlgebra/CliffordAlgebra/Even.lean index ab5a28a5dcedc..76bff36c9a4d1 100644 --- a/Mathlib/LinearAlgebra/CliffordAlgebra/Even.lean +++ b/Mathlib/LinearAlgebra/CliffordAlgebra/Even.lean @@ -125,7 +125,7 @@ variable {Q} namespace even.lift /-- An auxiliary submodule used to store the half-applied values of `f`. -This is the span of elements `f'` such that `∃ x m₂, ∀ m₁, f' m₁ = f m₁ m₂ * x`. -/ +This is the span of elements `f'` such that `∃ x m₂, ∀ m₁, f' m₁ = f m₁ m₂ * x`. -/ private def S : Submodule R (M →ₗ[R] A) := Submodule.span R {f' | ∃ x m₂, f' = LinearMap.lcomp R _ (f.bilin.flip m₂) (LinearMap.mulRight R x)} diff --git a/Mathlib/LinearAlgebra/CliffordAlgebra/EvenEquiv.lean b/Mathlib/LinearAlgebra/CliffordAlgebra/EvenEquiv.lean index ff16afc3d7f70..d699e29ff8b2d 100644 --- a/Mathlib/LinearAlgebra/CliffordAlgebra/EvenEquiv.lean +++ b/Mathlib/LinearAlgebra/CliffordAlgebra/EvenEquiv.lean @@ -187,7 +187,7 @@ theorem toEven_comp_ofEven : (toEven Q).comp (ofEven Q) = AlgHom.id R _ := have h2 : -(r₂ • e0 Q * v Q m₁) = v Q m₁ * r₂ • e0 Q := by rw [mul_smul_comm, smul_mul_assoc, ← smul_neg, neg_e0_mul_v] have h3 : -algebraMap R _ (r₁ * r₂) = r₁ • e0 Q * r₂ • e0 Q := by - rw [Algebra.algebraMap_eq_smul_one, smul_mul_smul, e0_mul_e0, smul_neg] + rw [Algebra.algebraMap_eq_smul_one, smul_mul_smul_comm, e0_mul_e0, smul_neg] rw [sub_eq_add_neg, sub_eq_add_neg, h1, h2, h3] _ = ι (Q' Q) (m₁, r₁) * ι (Q' Q) (m₂, r₂) := by rw [ι_eq_v_add_smul_e0, ι_eq_v_add_smul_e0, mul_add, add_mul, add_mul, add_assoc] diff --git a/Mathlib/LinearAlgebra/CliffordAlgebra/Prod.lean b/Mathlib/LinearAlgebra/CliffordAlgebra/Prod.lean index fab6f0c7bfae4..1e9ee43c0a118 100644 --- a/Mathlib/LinearAlgebra/CliffordAlgebra/Prod.lean +++ b/Mathlib/LinearAlgebra/CliffordAlgebra/Prod.lean @@ -43,7 +43,7 @@ variable (f₁ : Q₁ →qᵢ Qₙ) (f₂ : Q₂ →qᵢ Qₙ) (hf : ∀ x y, Q variable (m₁ : CliffordAlgebra Q₁) (m₂ : CliffordAlgebra Q₂) include hf -/-- If `m₁` and `m₂` are both homogenous, +/-- If `m₁` and `m₂` are both homogeneous, and the quadratic spaces `Q₁` and `Q₂` map into orthogonal subspaces of `Qₙ` (for instance, when `Qₙ = Q₁.prod Q₂`), then the product of the embedding in `CliffordAlgebra Q` commutes up to a sign factor. -/ @@ -151,9 +151,9 @@ lemma toProd_one_tmul_ι (m₂ : M₂) : toProd Q₁ Q₂ (1 ᵍ⊗ₜ ι _ m₂ lemma toProd_comp_ofProd : (toProd Q₁ Q₂).comp (ofProd Q₁ Q₂) = AlgHom.id _ _ := by ext m <;> dsimp - · rw [ofProd_ι_mk, map_add, toProd_one_tmul_ι, toProd_ι_tmul_one, ← Prod.zero_eq_mk, + · rw [ofProd_ι_mk, map_add, toProd_one_tmul_ι, toProd_ι_tmul_one, Prod.mk_zero_zero, LinearMap.map_zero, add_zero] - · rw [ofProd_ι_mk, map_add, toProd_one_tmul_ι, toProd_ι_tmul_one, ← Prod.zero_eq_mk, + · rw [ofProd_ι_mk, map_add, toProd_one_tmul_ι, toProd_ι_tmul_one, Prod.mk_zero_zero, LinearMap.map_zero, zero_add] lemma ofProd_comp_toProd : (ofProd Q₁ Q₂).comp (toProd Q₁ Q₂) = AlgHom.id _ _ := by diff --git a/Mathlib/LinearAlgebra/CliffordAlgebra/SpinGroup.lean b/Mathlib/LinearAlgebra/CliffordAlgebra/SpinGroup.lean new file mode 100644 index 0000000000000..06dfb81ec8f83 --- /dev/null +++ b/Mathlib/LinearAlgebra/CliffordAlgebra/SpinGroup.lean @@ -0,0 +1,411 @@ +/- +Copyright (c) 2022 Jiale Miao. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Jiale Miao, Utensil Song, Eric Wieser +-/ +import Mathlib.GroupTheory.GroupAction.ConjAct +import Mathlib.Algebra.Star.Unitary +import Mathlib.LinearAlgebra.CliffordAlgebra.Star +import Mathlib.LinearAlgebra.CliffordAlgebra.Even +import Mathlib.LinearAlgebra.CliffordAlgebra.Inversion + +/-! +# The Pin group and the Spin group + +In this file we define `lipschitzGroup`, `pinGroup` and `spinGroup` and show they form a group. + +## Main definitions + +* `lipschitzGroup`: the Lipschitz group with a quadratic form. +* `pinGroup`: the Pin group defined as the infimum of `lipschitzGroup` and `unitary`. +* `spinGroup`: the Spin group defined as the infimum of `pinGroup` and `CliffordAlgebra.even`. + +## Implementation Notes + +The definition of the Lipschitz group +$\{ x \in \mathop{\mathcal{C}\ell} | x \text{ is invertible and } x v x^{-1} ∈ V \}$ is given by: + +* [fulton2004][], Chapter 20 +* https://en.wikipedia.org/wiki/Clifford_algebra#Lipschitz_group + +But they presumably form a group only in finite dimensions. So we define `lipschitzGroup` with +closure of all the invertible elements in the form of `ι Q m`, and we show this definition is +at least as large as the other definition (See `lipschitzGroup.conjAct_smul_range_ι` and +`lipschitzGroup.involute_act_ι_mem_range_ι`). +The reverse statement presumably is true only in finite dimensions. + +Here are some discussions about the latent ambiguity of definition : +https://mathoverflow.net/q/427881/172242 and https://mathoverflow.net/q/251288/172242 + +## TODO + +Try to show the reverse statement is true in finite dimensions. +-/ + +variable {R : Type*} [CommRing R] +variable {M : Type*} [AddCommGroup M] [Module R M] +variable {Q : QuadraticForm R M} + +section Pin + +open CliffordAlgebra MulAction + +open scoped Pointwise + +/-- `lipschitzGroup` is the subgroup closure of all the invertible elements in the form of `ι Q m` +where `ι` is the canonical linear map `M →ₗ[R] CliffordAlgebra Q`. -/ +def lipschitzGroup (Q : QuadraticForm R M) : Subgroup (CliffordAlgebra Q)ˣ := + Subgroup.closure ((↑) ⁻¹' Set.range (ι Q) : Set (CliffordAlgebra Q)ˣ) + +namespace lipschitzGroup + +/-- The conjugation action by elements of the Lipschitz group keeps vectors as vectors. -/ +theorem conjAct_smul_ι_mem_range_ι {x : (CliffordAlgebra Q)ˣ} (hx : x ∈ lipschitzGroup Q) + [Invertible (2 : R)] (m : M) : + ConjAct.toConjAct x • ι Q m ∈ LinearMap.range (ι Q) := by + unfold lipschitzGroup at hx + rw [ConjAct.units_smul_def, ConjAct.ofConjAct_toConjAct] + induction hx using Subgroup.closure_induction'' generalizing m with + | mem x hx => + obtain ⟨a, ha⟩ := hx + letI := x.invertible + letI : Invertible (ι Q a) := by rwa [ha] + letI : Invertible (Q a) := invertibleOfInvertibleι Q a + simp_rw [← invOf_units x, ← ha, ι_mul_ι_mul_invOf_ι, LinearMap.mem_range_self] + | inv_mem x hx => + obtain ⟨a, ha⟩ := hx + letI := x.invertible + letI : Invertible (ι Q a) := by rwa [ha] + letI : Invertible (Q a) := invertibleOfInvertibleι Q a + letI := invertibleNeg (ι Q a) + letI := Invertible.map involute (ι Q a) + simp_rw [← invOf_units x, inv_inv, ← ha, invOf_ι_mul_ι_mul_ι, LinearMap.mem_range_self] + | one => simp_rw [inv_one, Units.val_one, one_mul, mul_one, LinearMap.mem_range_self] + | mul y z _ _ hy hz => + simp_rw [mul_inv_rev, Units.val_mul] + suffices ↑y * (↑z * ι Q m * ↑z⁻¹) * ↑y⁻¹ ∈ _ by + simpa only [mul_assoc] using this + obtain ⟨z', hz'⟩ := hz m + obtain ⟨y', hy'⟩ := hy z' + simp_rw [← hz', ← hy', LinearMap.mem_range_self] + +/-- This is another version of `lipschitzGroup.conjAct_smul_ι_mem_range_ι` which uses `involute`. -/ +theorem involute_act_ι_mem_range_ι [Invertible (2 : R)] + {x : (CliffordAlgebra Q)ˣ} (hx : x ∈ lipschitzGroup Q) (b : M) : + involute (Q := Q) ↑x * ι Q b * ↑x⁻¹ ∈ LinearMap.range (ι Q) := by + unfold lipschitzGroup at hx + induction hx using Subgroup.closure_induction'' generalizing b with + | mem x hx => + obtain ⟨a, ha⟩ := hx + letI := x.invertible + letI : Invertible (ι Q a) := by rwa [ha] + letI : Invertible (Q a) := invertibleOfInvertibleι Q a + simp_rw [← invOf_units x, ← ha, involute_ι, neg_mul, ι_mul_ι_mul_invOf_ι Q a b, ← map_neg, + LinearMap.mem_range_self] + | inv_mem x hx => + obtain ⟨a, ha⟩ := hx + letI := x.invertible + letI : Invertible (ι Q a) := by rwa [ha] + letI : Invertible (Q a) := invertibleOfInvertibleι Q a + letI := invertibleNeg (ι Q a) + letI := Invertible.map involute (ι Q a) + simp_rw [← invOf_units x, inv_inv, ← ha, map_invOf, involute_ι, invOf_neg, neg_mul, + invOf_ι_mul_ι_mul_ι, ← map_neg, LinearMap.mem_range_self] + | one => simp_rw [inv_one, Units.val_one, map_one, one_mul, mul_one, LinearMap.mem_range_self] + | mul y z _ _ hy hz => + simp_rw [mul_inv_rev, Units.val_mul, map_mul] + suffices involute (Q := Q) ↑y * (involute (Q := Q) ↑z * ι Q b * ↑z⁻¹) * ↑y⁻¹ ∈ _ by + simpa only [mul_assoc] using this + obtain ⟨z', hz'⟩ := hz b + obtain ⟨y', hy'⟩ := hy z' + simp_rw [← hz', ← hy', LinearMap.mem_range_self] + +/-- If x is in `lipschitzGroup Q`, then `(ι Q).range` is closed under twisted conjugation. +The reverse statement presumably is true only in finite dimensions.-/ +theorem conjAct_smul_range_ι {x : (CliffordAlgebra Q)ˣ} (hx : x ∈ lipschitzGroup Q) + [Invertible (2 : R)] : + ConjAct.toConjAct x • LinearMap.range (ι Q) = LinearMap.range (ι Q) := by + suffices ∀ x ∈ lipschitzGroup Q, + ConjAct.toConjAct x • LinearMap.range (ι Q) ≤ LinearMap.range (ι Q) by + apply le_antisymm + · exact this _ hx + · have := smul_mono_right (ConjAct.toConjAct x) <| this _ (inv_mem hx) + refine Eq.trans_le ?_ this + simp only [map_inv, smul_inv_smul] + intro x hx + erw [Submodule.map_le_iff_le_comap] + rintro _ ⟨m, rfl⟩ + exact conjAct_smul_ι_mem_range_ι hx _ + +theorem coe_mem_iff_mem {x : (CliffordAlgebra Q)ˣ} : + ↑x ∈ (lipschitzGroup Q).toSubmonoid.map (Units.coeHom <| CliffordAlgebra Q) ↔ + x ∈ lipschitzGroup Q := by + simp only [Submonoid.mem_map, Subgroup.mem_toSubmonoid, Units.coeHom_apply, exists_prop] + norm_cast + exact exists_eq_right + +end lipschitzGroup + +/-- `pinGroup Q` is defined as the infimum of `lipschitzGroup Q` and `unitary (CliffordAlgebra Q)`. +See `mem_iff`. -/ +def pinGroup (Q : QuadraticForm R M) : Submonoid (CliffordAlgebra Q) := + (lipschitzGroup Q).toSubmonoid.map (Units.coeHom <| CliffordAlgebra Q) ⊓ unitary _ + +namespace pinGroup + +/-- An element is in `pinGroup Q` if and only if it is in `lipschitzGroup Q` and `unitary`. -/ +theorem mem_iff {x : CliffordAlgebra Q} : + x ∈ pinGroup Q ↔ + x ∈ (lipschitzGroup Q).toSubmonoid.map (Units.coeHom <| CliffordAlgebra Q) ∧ + x ∈ unitary (CliffordAlgebra Q) := + Iff.rfl + +theorem mem_lipschitzGroup {x : CliffordAlgebra Q} (hx : x ∈ pinGroup Q) : + x ∈ (lipschitzGroup Q).toSubmonoid.map (Units.coeHom <| CliffordAlgebra Q) := + hx.1 + +theorem mem_unitary {x : CliffordAlgebra Q} (hx : x ∈ pinGroup Q) : + x ∈ unitary (CliffordAlgebra Q) := + hx.2 + +theorem units_mem_iff {x : (CliffordAlgebra Q)ˣ} : + ↑x ∈ pinGroup Q ↔ x ∈ lipschitzGroup Q ∧ ↑x ∈ unitary (CliffordAlgebra Q) := by + rw [mem_iff, lipschitzGroup.coe_mem_iff_mem] + +theorem units_mem_lipschitzGroup {x : (CliffordAlgebra Q)ˣ} (hx : ↑x ∈ pinGroup Q) : + x ∈ lipschitzGroup Q := + (units_mem_iff.1 hx).1 + +/-- The conjugation action by elements of the spin group keeps vectors as vectors. -/ +theorem conjAct_smul_ι_mem_range_ι {x : (CliffordAlgebra Q)ˣ} (hx : ↑x ∈ pinGroup Q) + [Invertible (2 : R)] (y : M) : ConjAct.toConjAct x • ι Q y ∈ LinearMap.range (ι Q) := + lipschitzGroup.conjAct_smul_ι_mem_range_ι (units_mem_lipschitzGroup hx) y + +/-- This is another version of `conjAct_smul_ι_mem_range_ι` which uses `involute`. -/ +theorem involute_act_ι_mem_range_ι {x : (CliffordAlgebra Q)ˣ} (hx : ↑x ∈ pinGroup Q) + [Invertible (2 : R)] (y : M) : involute (Q := Q) ↑x * ι Q y * ↑x⁻¹ ∈ LinearMap.range (ι Q) := + lipschitzGroup.involute_act_ι_mem_range_ι (units_mem_lipschitzGroup hx) y + +/-- If x is in `pinGroup Q`, then `(ι Q).range` is closed under twisted conjugation. The reverse +statement presumably being true only in finite dimensions.-/ +theorem conjAct_smul_range_ι {x : (CliffordAlgebra Q)ˣ} (hx : ↑x ∈ pinGroup Q) + [Invertible (2 : R)] : ConjAct.toConjAct x • LinearMap.range (ι Q) = LinearMap.range (ι Q) := + lipschitzGroup.conjAct_smul_range_ι (units_mem_lipschitzGroup hx) + +@[simp] +theorem star_mul_self_of_mem {x : CliffordAlgebra Q} (hx : x ∈ pinGroup Q) : star x * x = 1 := + hx.2.1 + +@[simp] +theorem mul_star_self_of_mem {x : CliffordAlgebra Q} (hx : x ∈ pinGroup Q) : x * star x = 1 := + hx.2.2 + +/-- See `star_mem_iff` for both directions. -/ +theorem star_mem {x : CliffordAlgebra Q} (hx : x ∈ pinGroup Q) : star x ∈ pinGroup Q := by + rw [mem_iff] at hx ⊢ + refine ⟨?_, unitary.star_mem hx.2⟩ + rcases hx with ⟨⟨y, hy₁, hy₂⟩, _hx₂, hx₃⟩ + simp only [Subgroup.coe_toSubmonoid, SetLike.mem_coe] at hy₁ + simp only [Units.coeHom_apply] at hy₂ + simp only [Submonoid.mem_map, Subgroup.mem_toSubmonoid, Units.coeHom_apply, exists_prop] + refine ⟨star y, ?_, by simp only [hy₂, Units.coe_star]⟩ + rw [← hy₂] at hx₃ + have hy₃ : y * star y = 1 := by + rw [← Units.eq_iff] + simp only [hx₃, Units.val_mul, Units.coe_star, Units.val_one] + apply_fun fun x => y⁻¹ * x at hy₃ + simp only [inv_mul_cancel_left, mul_one] at hy₃ + simp only [hy₃, hy₁, inv_mem_iff] + +/-- An element is in `pinGroup Q` if and only if `star x` is in `pinGroup Q`. +See `star_mem` for only one direction. -/ +@[simp] +theorem star_mem_iff {x : CliffordAlgebra Q} : star x ∈ pinGroup Q ↔ x ∈ pinGroup Q := by + refine ⟨?_, star_mem⟩ + intro hx + convert star_mem hx + exact (star_star x).symm + +instance : Star (pinGroup Q) where + star x := ⟨star x, star_mem x.prop⟩ + +@[simp, norm_cast] +theorem coe_star {x : pinGroup Q} : ↑(star x) = (star x : CliffordAlgebra Q) := + rfl + +theorem coe_star_mul_self (x : pinGroup Q) : (star x : CliffordAlgebra Q) * x = 1 := + star_mul_self_of_mem x.prop + +theorem coe_mul_star_self (x : pinGroup Q) : (x : CliffordAlgebra Q) * star x = 1 := + mul_star_self_of_mem x.prop + +@[simp] +theorem star_mul_self (x : pinGroup Q) : star x * x = 1 := + Subtype.ext <| coe_star_mul_self x + +@[simp] +theorem mul_star_self (x : pinGroup Q) : x * star x = 1 := + Subtype.ext <| coe_mul_star_self x + +/-- `pinGroup Q` forms a group where the inverse is `star`. -/ +instance : Group (pinGroup Q) where + inv := star + inv_mul_cancel := star_mul_self + +instance : StarMul (pinGroup Q) where + star_involutive _ := Subtype.ext <| star_involutive _ + star_mul _ _ := Subtype.ext <| star_mul _ _ + +instance : Inhabited (pinGroup Q) := + ⟨1⟩ + +theorem star_eq_inv (x : pinGroup Q) : star x = x⁻¹ := + rfl + +theorem star_eq_inv' : (star : pinGroup Q → pinGroup Q) = Inv.inv := + rfl + +/-- The elements in `pinGroup Q` embed into (CliffordAlgebra Q)ˣ. -/ +@[simps] +def toUnits : pinGroup Q →* (CliffordAlgebra Q)ˣ where + toFun x := ⟨x, ↑x⁻¹, coe_mul_star_self x, coe_star_mul_self x⟩ + map_one' := Units.ext rfl + map_mul' _x _y := Units.ext rfl + +theorem toUnits_injective : Function.Injective (toUnits : pinGroup Q → (CliffordAlgebra Q)ˣ) := + fun _x _y h => Subtype.ext <| Units.ext_iff.mp h + +end pinGroup + +end Pin + +section Spin + +open CliffordAlgebra MulAction + +open scoped Pointwise + +/-- `spinGroup Q` is defined as the infimum of `pinGroup Q` and `CliffordAlgebra.even Q`. +See `mem_iff`. -/ +def spinGroup (Q : QuadraticForm R M) : Submonoid (CliffordAlgebra Q) := + pinGroup Q ⊓ (CliffordAlgebra.even Q).toSubring.toSubmonoid + +namespace spinGroup + +/-- An element is in `spinGroup Q` if and only if it is in `pinGroup Q` and `even Q`. -/ +theorem mem_iff {x : CliffordAlgebra Q} : x ∈ spinGroup Q ↔ x ∈ pinGroup Q ∧ x ∈ even Q := + Iff.rfl + +theorem mem_pin {x : CliffordAlgebra Q} (hx : x ∈ spinGroup Q) : x ∈ pinGroup Q := + hx.1 + +theorem mem_even {x : CliffordAlgebra Q} (hx : x ∈ spinGroup Q) : x ∈ even Q := + hx.2 + +theorem units_mem_lipschitzGroup {x : (CliffordAlgebra Q)ˣ} (hx : ↑x ∈ spinGroup Q) : + x ∈ lipschitzGroup Q := + pinGroup.units_mem_lipschitzGroup (mem_pin hx) + +/-- If x is in `spinGroup Q`, then `involute x` is equal to x.-/ +theorem involute_eq {x : CliffordAlgebra Q} (hx : x ∈ spinGroup Q) : involute x = x := + involute_eq_of_mem_even (mem_even hx) + +theorem units_involute_act_eq_conjAct {x : (CliffordAlgebra Q)ˣ} (hx : ↑x ∈ spinGroup Q) (y : M) : + involute (Q := Q) ↑x * ι Q y * ↑x⁻¹ = ConjAct.toConjAct x • (ι Q y) := by + rw [involute_eq hx, @ConjAct.units_smul_def, @ConjAct.ofConjAct_toConjAct] + +/-- The conjugation action by elements of the spin group keeps vectors as vectors. -/ +theorem conjAct_smul_ι_mem_range_ι {x : (CliffordAlgebra Q)ˣ} (hx : ↑x ∈ spinGroup Q) + [Invertible (2 : R)] (y : M) : ConjAct.toConjAct x • ι Q y ∈ LinearMap.range (ι Q) := + lipschitzGroup.conjAct_smul_ι_mem_range_ι (units_mem_lipschitzGroup hx) y + +/- This is another version of `conjAct_smul_ι_mem_range_ι` which uses `involute`.-/ +theorem involute_act_ι_mem_range_ι {x : (CliffordAlgebra Q)ˣ} (hx : ↑x ∈ spinGroup Q) + [Invertible (2 : R)] (y : M) : involute (Q := Q) ↑x * ι Q y * ↑x⁻¹ ∈ LinearMap.range (ι Q) := + lipschitzGroup.involute_act_ι_mem_range_ι (units_mem_lipschitzGroup hx) y + +/- If x is in `spinGroup Q`, then `(ι Q).range` is closed under twisted conjugation. The reverse +statement presumably being true only in finite dimensions.-/ +theorem conjAct_smul_range_ι {x : (CliffordAlgebra Q)ˣ} (hx : ↑x ∈ spinGroup Q) + [Invertible (2 : R)] : ConjAct.toConjAct x • LinearMap.range (ι Q) = LinearMap.range (ι Q) := + lipschitzGroup.conjAct_smul_range_ι (units_mem_lipschitzGroup hx) + +@[simp] +theorem star_mul_self_of_mem {x : CliffordAlgebra Q} (hx : x ∈ spinGroup Q) : star x * x = 1 := + hx.1.2.1 + +@[simp] +theorem mul_star_self_of_mem {x : CliffordAlgebra Q} (hx : x ∈ spinGroup Q) : x * star x = 1 := + hx.1.2.2 + +/-- See `star_mem_iff` for both directions. -/ +theorem star_mem {x : CliffordAlgebra Q} (hx : x ∈ spinGroup Q) : star x ∈ spinGroup Q := by + rw [mem_iff] at hx ⊢ + cases' hx with hx₁ hx₂ + refine ⟨pinGroup.star_mem hx₁, ?_⟩ + dsimp only [CliffordAlgebra.even] at hx₂ ⊢ + simp only [Submodule.mem_toSubalgebra] at hx₂ ⊢ + simp only [star_def, reverse_mem_evenOdd_iff, involute_mem_evenOdd_iff, hx₂] + +/-- An element is in `spinGroup Q` if and only if `star x` is in `spinGroup Q`. +See `star_mem` for only one direction. +-/ +@[simp] +theorem star_mem_iff {x : CliffordAlgebra Q} : star x ∈ spinGroup Q ↔ x ∈ spinGroup Q := by + refine ⟨?_, star_mem⟩ + intro hx + convert star_mem hx + exact (star_star x).symm + +instance : Star (spinGroup Q) where + star x := ⟨star x, star_mem x.prop⟩ + +@[simp, norm_cast] +theorem coe_star {x : spinGroup Q} : ↑(star x) = (star x : CliffordAlgebra Q) := + rfl + +theorem coe_star_mul_self (x : spinGroup Q) : (star x : CliffordAlgebra Q) * x = 1 := + star_mul_self_of_mem x.prop + +theorem coe_mul_star_self (x : spinGroup Q) : (x : CliffordAlgebra Q) * star x = 1 := + mul_star_self_of_mem x.prop + +@[simp] +theorem star_mul_self (x : spinGroup Q) : star x * x = 1 := + Subtype.ext <| coe_star_mul_self x + +@[simp] +theorem mul_star_self (x : spinGroup Q) : x * star x = 1 := + Subtype.ext <| coe_mul_star_self x + +/-- `spinGroup Q` forms a group where the inverse is `star`. -/ +instance : Group (spinGroup Q) where + inv := star + inv_mul_cancel := star_mul_self + +instance : StarMul (spinGroup Q) where + star_involutive _ := Subtype.ext <| star_involutive _ + star_mul _ _ := Subtype.ext <| star_mul _ _ + +instance : Inhabited (spinGroup Q) := + ⟨1⟩ + +theorem star_eq_inv (x : spinGroup Q) : star x = x⁻¹ := + rfl + +theorem star_eq_inv' : (star : spinGroup Q → spinGroup Q) = Inv.inv := + rfl + +/-- The elements in `spinGroup Q` embed into (CliffordAlgebra Q)ˣ. -/ +@[simps] +def toUnits : spinGroup Q →* (CliffordAlgebra Q)ˣ where + toFun x := ⟨x, ↑x⁻¹, coe_mul_star_self x, coe_star_mul_self x⟩ + map_one' := Units.ext rfl + map_mul' _x _y := Units.ext rfl + +theorem toUnits_injective : Function.Injective (toUnits : spinGroup Q → (CliffordAlgebra Q)ˣ) := + fun _x _y h => Subtype.ext <| Units.ext_iff.mp h + +end spinGroup + +end Spin diff --git a/Mathlib/LinearAlgebra/DFinsupp.lean b/Mathlib/LinearAlgebra/DFinsupp.lean index c8e7dc428808d..fde50b6846a2f 100644 --- a/Mathlib/LinearAlgebra/DFinsupp.lean +++ b/Mathlib/LinearAlgebra/DFinsupp.lean @@ -340,7 +340,7 @@ lemma mem_iSup_iff_exists_finsupp (p : ι → Submodule R N) (x : N) : refine ⟨fun ⟨f, hf⟩ ↦ ⟨⟨f.support, fun i ↦ (f i : N), by simp⟩, by simp, hf⟩, ?_⟩ rintro ⟨f, hf, rfl⟩ refine ⟨DFinsupp.mk f.support fun i ↦ ⟨f i, hf i⟩, Finset.sum_congr ?_ fun i hi ↦ ?_⟩ - · ext; simp + · ext; simp [mk_eq_zero] · simp [Finsupp.mem_support_iff.mp hi] theorem mem_iSup_finset_iff_exists_sum {s : Finset ι} (p : ι → Submodule R N) (a : N) : @@ -422,14 +422,15 @@ theorem independent_of_dfinsupp_sumAddHom_injective (p : ι → AddSubmonoid N) rw [← independent_map_orderIso_iff (AddSubmonoid.toNatSubmodule : AddSubmonoid N ≃o _)] exact independent_of_dfinsupp_lsum_injective _ h -/-- Combining `DFinsupp.lsum` with `LinearMap.toSpanSingleton` is the same as `Finsupp.total` -/ +/-- Combining `DFinsupp.lsum` with `LinearMap.toSpanSingleton` is the same as +`Finsupp.linearCombination` -/ theorem lsum_comp_mapRange_toSpanSingleton [∀ m : R, Decidable (m ≠ 0)] (p : ι → Submodule R N) {v : ι → N} (hv : ∀ i : ι, v i ∈ p i) : (lsum ℕ (M := fun i ↦ ↥(p i)) fun i => (p i).subtype : _ →ₗ[R] _).comp ((mapRange.linearMap fun i => LinearMap.toSpanSingleton R (↥(p i)) ⟨v i, hv i⟩ : _ →ₗ[R] _).comp (finsuppLequivDFinsupp R : (ι →₀ R) ≃ₗ[R] _).toLinearMap) = - Finsupp.total ι N R v := by + Finsupp.linearCombination R v := by ext simp diff --git a/Mathlib/LinearAlgebra/Dimension/Constructions.lean b/Mathlib/LinearAlgebra/Dimension/Constructions.lean index 3724ba1ee3ccd..f34b954448f30 100644 --- a/Mathlib/LinearAlgebra/Dimension/Constructions.lean +++ b/Mathlib/LinearAlgebra/Dimension/Constructions.lean @@ -70,7 +70,7 @@ theorem rank_quotient_add_rank_le [Nontrivial R] (M' : Submodule R M) : refine ciSup_le fun ⟨s, hs⟩ ↦ ciSup_le fun ⟨t, ht⟩ ↦ ?_ choose f hf using Quotient.mk_surjective M' simpa [add_comm] using (LinearIndependent.sum_elim_of_quotient ht (fun (i : s) ↦ f i) - (by simpa [Function.comp, hf] using hs)).cardinal_le_rank + (by simpa [Function.comp_def, hf] using hs)).cardinal_le_rank theorem rank_quotient_le (p : Submodule R M) : Module.rank R (M ⧸ p) ≤ Module.rank R M := (mkQ p).rank_le_of_surjective (surjective_quot_mk _) @@ -402,7 +402,7 @@ section Span variable [StrongRankCondition R] theorem rank_span_le (s : Set M) : Module.rank R (span R s) ≤ #s := by - rw [Finsupp.span_eq_range_total, ← lift_strictMono.le_iff_le] + rw [Finsupp.span_eq_range_linearCombination, ← lift_strictMono.le_iff_le] refine (lift_rank_range_le _).trans ?_ rw [rank_finsupp_self] simp only [lift_lift, le_refl] diff --git a/Mathlib/LinearAlgebra/Dimension/DivisionRing.lean b/Mathlib/LinearAlgebra/Dimension/DivisionRing.lean index 6b0db8a0b52de..c18b030de59b8 100644 --- a/Mathlib/LinearAlgebra/Dimension/DivisionRing.lean +++ b/Mathlib/LinearAlgebra/Dimension/DivisionRing.lean @@ -180,9 +180,7 @@ theorem linearIndependent_iff_card_eq_finrank_span {ι : Type*} [Fintype ι] {b simp [f, Set.mem_image, Set.mem_range] rw [hf] at h have hx : (x : V) ∈ span K (Set.range b) := x.property - conv at hx => - arg 2 - rw [h] + simp_rw [h] at hx simpa [f, mem_map] using hx have hi : LinearMap.ker f = ⊥ := ker_subtype _ convert (linearIndependent_of_top_le_span_of_card_eq_finrank hs hc).map' _ hi @@ -249,8 +247,8 @@ theorem max_aleph0_card_le_rank_fun_nat : max ℵ₀ #K ≤ Module.rank K (ℕ contrapose! card_K exact (power_lt_aleph0 card_K <| nat_lt_aleph0 _).le obtain ⟨e⟩ := lift_mk_le'.mp (card_ιL.trans_eq (lift_uzero #ιL).symm) - have rep_e := bK.total_repr (bL ∘ e) - rw [Finsupp.total_apply, Finsupp.sum] at rep_e + have rep_e := bK.linearCombination_repr (bL ∘ e) + rw [Finsupp.linearCombination_apply, Finsupp.sum] at rep_e set c := bK.repr (bL ∘ e) set s := c.support let f i (j : s) : L := ⟨bK j i, Subfield.subset_closure ⟨(j, i), rfl⟩⟩ diff --git a/Mathlib/LinearAlgebra/Dimension/Finite.lean b/Mathlib/LinearAlgebra/Dimension/Finite.lean index 75052d2a62473..48217a2ace216 100644 --- a/Mathlib/LinearAlgebra/Dimension/Finite.lean +++ b/Mathlib/LinearAlgebra/Dimension/Finite.lean @@ -48,7 +48,7 @@ lemma rank_eq_zero_iff : rw [← Cardinal.one_le_iff_ne_zero] have : LinearIndependent R (fun _ : Unit ↦ x) := linearIndependent_iff.mpr (fun l hl ↦ Finsupp.unique_ext <| not_not.mp fun H ↦ - hx _ H ((Finsupp.total_unique _ _ _).symm.trans hl)) + hx _ H ((Finsupp.linearCombination_unique _ _ _).symm.trans hl)) simpa using this.cardinal_lift_le_rank · intro h rw [← le_zero_iff, Module.rank_def] @@ -214,11 +214,11 @@ lemma exists_finset_linearIndependent_of_le_rank {n : ℕ} (hn : n ≤ Module.ra (Cardinal.bddAbove_range.{v, v} _) _ (h.trans (Module.rank_def R M)).symm have : Finite s := lt_aleph0_iff_finite.mp (hs' ▸ nat_lt_aleph0 n) cases nonempty_fintype s - exact ⟨s.toFinset, by simpa using hs', by convert hs <;> exact Set.mem_toFinset⟩ + exact ⟨s.toFinset, by simpa using hs', by convert hs using 3 <;> exact Set.mem_toFinset⟩ · obtain ⟨s, hs, hs'⟩ := exists_set_linearIndependent_of_lt_rank h have : Finite s := lt_aleph0_iff_finite.mp (hs ▸ nat_lt_aleph0 n) cases nonempty_fintype s - exact ⟨s.toFinset, by simpa using hs, by convert hs' <;> exact Set.mem_toFinset⟩ + exact ⟨s.toFinset, by simpa using hs, by convert hs' using 3 <;> exact Set.mem_toFinset⟩ lemma exists_linearIndependent_of_le_rank {n : ℕ} (hn : n ≤ Module.rank R M) : ∃ f : Fin n → M, LinearIndependent R f := @@ -381,7 +381,7 @@ theorem FiniteDimensional.nontrivial_of_finrank_pos (h : 0 < finrank R M) : Nont natural number. -/ theorem FiniteDimensional.nontrivial_of_finrank_eq_succ {n : ℕ} (hn : finrank R M = n.succ) : Nontrivial M := - nontrivial_of_finrank_pos (by rw [hn]; exact n.succ_pos) + nontrivial_of_finrank_pos (R := R) (by rw [hn]; exact n.succ_pos) end diff --git a/Mathlib/LinearAlgebra/Dimension/FreeAndStrongRankCondition.lean b/Mathlib/LinearAlgebra/Dimension/FreeAndStrongRankCondition.lean index 883252149ac34..507f9e3b737de 100644 --- a/Mathlib/LinearAlgebra/Dimension/FreeAndStrongRankCondition.lean +++ b/Mathlib/LinearAlgebra/Dimension/FreeAndStrongRankCondition.lean @@ -139,8 +139,10 @@ its span. -/ theorem rank_submodule_eq_one_iff (s : Submodule K V) [Module.Free K s] : Module.rank K s = 1 ↔ ∃ v₀ ∈ s, v₀ ≠ 0 ∧ s ≤ K ∙ v₀ := by simp_rw [rank_eq_one_iff, le_span_singleton_iff] - refine ⟨fun ⟨⟨v₀, hv₀⟩, H, h⟩ ↦ ⟨v₀, hv₀, fun h' ↦ by simp [h'] at H, fun v hv ↦ ?_⟩, - fun ⟨v₀, hv₀, H, h⟩ ↦ ⟨⟨v₀, hv₀⟩, fun h' ↦ H (by simpa using h'), fun ⟨v, hv⟩ ↦ ?_⟩⟩ + refine ⟨fun ⟨⟨v₀, hv₀⟩, H, h⟩ ↦ ⟨v₀, hv₀, fun h' ↦ by + simp only [h', ne_eq] at H; exact H rfl, fun v hv ↦ ?_⟩, + fun ⟨v₀, hv₀, H, h⟩ ↦ ⟨⟨v₀, hv₀⟩, + fun h' ↦ H (by rwa [AddSubmonoid.mk_eq_zero] at h'), fun ⟨v, hv⟩ ↦ ?_⟩⟩ · obtain ⟨r, hr⟩ := h ⟨v, hv⟩ exact ⟨r, by rwa [Subtype.ext_iff, coe_smul] at hr⟩ · obtain ⟨r, hr⟩ := h v hv diff --git a/Mathlib/LinearAlgebra/Dimension/RankNullity.lean b/Mathlib/LinearAlgebra/Dimension/RankNullity.lean index 39b863dc84a22..79cac4a7d7ba4 100644 --- a/Mathlib/LinearAlgebra/Dimension/RankNullity.lean +++ b/Mathlib/LinearAlgebra/Dimension/RankNullity.lean @@ -104,7 +104,7 @@ theorem exists_linearIndependent_of_lt_rank [StrongRankCondition R] ← rank_quotient_add_rank (Submodule.span R s), add_comm, rank_span_set hs] exact HasLeftInverse.injective ⟨Submodule.Quotient.mk, hsec⟩ · apply LinearIndependent.union_of_quotient Submodule.subset_span hs - rwa [Function.comp, linearIndependent_image (hsec'.symm ▸ injective_id).injOn.image_of_comp, + rwa [Function.comp_def, linearIndependent_image (hsec'.symm ▸ injective_id).injOn.image_of_comp, ← image_comp, hsec', image_id] /-- Given a family of `n` linearly independent vectors in a space of dimension `> n`, one may extend diff --git a/Mathlib/LinearAlgebra/Dimension/StrongRankCondition.lean b/Mathlib/LinearAlgebra/Dimension/StrongRankCondition.lean index ea4d5b81f1804..b7d2c4c6e0497 100644 --- a/Mathlib/LinearAlgebra/Dimension/StrongRankCondition.lean +++ b/Mathlib/LinearAlgebra/Dimension/StrongRankCondition.lean @@ -106,10 +106,10 @@ theorem Basis.le_span'' {ι : Type*} [Fintype ι] (b : Basis ι R M) {w : Set M} -- We construct a surjective linear map `(w → R) →ₗ[R] (ι → R)`, -- by expressing a linear combination in `w` as a linear combination in `ι`. fapply card_le_of_surjective' R - · exact b.repr.toLinearMap.comp (Finsupp.total w M R (↑)) + · exact b.repr.toLinearMap.comp (Finsupp.linearCombination R (↑)) · apply Surjective.comp (g := b.repr.toLinearMap) · apply LinearEquiv.surjective - rw [← LinearMap.range_eq_top, Finsupp.range_total] + rw [← LinearMap.range_eq_top, Finsupp.range_linearCombination] simpa using s /-- @@ -162,7 +162,7 @@ section StrongRankCondition variable [StrongRankCondition R] -open Submodule +open Submodule Finsupp -- An auxiliary lemma for `linearIndependent_le_span'`, -- with the additional assumption that the linearly independent family is finite. @@ -174,11 +174,12 @@ theorem linearIndependent_le_span_aux' {ι : Type*} [Fintype ι] (v : ι → M) -- and expressing that (using the axiom of choice) as a linear combination over `w`. -- We can do this linearly by constructing the map on a basis. fapply card_le_of_injective' R - · apply Finsupp.total + · apply Finsupp.linearCombination exact fun i => Span.repr R w ⟨v i, s (mem_range_self i)⟩ · intro f g h - apply_fun Finsupp.total w M R (↑) at h - simp only [Finsupp.total_total, Submodule.coe_mk, Span.finsupp_total_repr] at h + apply_fun linearCombination R ((↑) : w → M) at h + simp only [linearCombination_linearCombination, Submodule.coe_mk, + Span.finsupp_linearCombination_repr] at h rw [← sub_eq_zero, ← LinearMap.map_sub] at h exact sub_eq_zero.mp (linearIndependent_iff.mp i _ h) diff --git a/Mathlib/LinearAlgebra/DirectSum/Finsupp.lean b/Mathlib/LinearAlgebra/DirectSum/Finsupp.lean index 3265071dd5bad..6facf782974d3 100644 --- a/Mathlib/LinearAlgebra/DirectSum/Finsupp.lean +++ b/Mathlib/LinearAlgebra/DirectSum/Finsupp.lean @@ -205,7 +205,7 @@ lemma finsuppScalarLeft_symm_apply_single (i : ι) (n : N) : variable (R M N ι) -/-- The tensor product of `M` and `ι →₀ R` is linearly equivalent to `ι →₀ N` -/ +/-- The tensor product of `M` and `ι →₀ R` is linearly equivalent to `ι →₀ M` -/ noncomputable def finsuppScalarRight : M ⊗[R] (ι →₀ R) ≃ₗ[R] ι →₀ M := finsuppRight R M R ι ≪≫ₗ Finsupp.mapRange.linearEquiv (TensorProduct.rid R M) diff --git a/Mathlib/LinearAlgebra/Dual.lean b/Mathlib/LinearAlgebra/Dual.lean index 1a73c224e14a7..b4d2e69e8d184 100644 --- a/Mathlib/LinearAlgebra/Dual.lean +++ b/Mathlib/LinearAlgebra/Dual.lean @@ -280,29 +280,34 @@ theorem toDual_apply (i j : ι) : b.toDual (b i) (b j) = if i = j then 1 else 0 simp only [eq_comm] @[simp] -theorem toDual_total_left (f : ι →₀ R) (i : ι) : - b.toDual (Finsupp.total ι M R b f) (b i) = f i := by - rw [Finsupp.total_apply, Finsupp.sum, _root_.map_sum, LinearMap.sum_apply] +theorem toDual_linearCombination_left (f : ι →₀ R) (i : ι) : + b.toDual (Finsupp.linearCombination R b f) (b i) = f i := by + rw [Finsupp.linearCombination_apply, Finsupp.sum, _root_.map_sum, LinearMap.sum_apply] simp_rw [LinearMap.map_smul, LinearMap.smul_apply, toDual_apply, smul_eq_mul, mul_boole, Finset.sum_ite_eq'] split_ifs with h · rfl · rw [Finsupp.not_mem_support_iff.mp h] +@[deprecated (since := "2024-08-29")] alias toDual_total_left := toDual_linearCombination_left + @[simp] -theorem toDual_total_right (f : ι →₀ R) (i : ι) : - b.toDual (b i) (Finsupp.total ι M R b f) = f i := by - rw [Finsupp.total_apply, Finsupp.sum, _root_.map_sum] +theorem toDual_linearCombination_right (f : ι →₀ R) (i : ι) : + b.toDual (b i) (Finsupp.linearCombination R b f) = f i := by + rw [Finsupp.linearCombination_apply, Finsupp.sum, _root_.map_sum] simp_rw [LinearMap.map_smul, toDual_apply, smul_eq_mul, mul_boole, Finset.sum_ite_eq] split_ifs with h · rfl · rw [Finsupp.not_mem_support_iff.mp h] +@[deprecated (since := "2024-08-29")] alias toDual_total_right := + toDual_linearCombination_right + theorem toDual_apply_left (m : M) (i : ι) : b.toDual m (b i) = b.repr m i := by - rw [← b.toDual_total_left, b.total_repr] + rw [← b.toDual_linearCombination_left, b.linearCombination_repr] theorem toDual_apply_right (i : ι) (m : M) : b.toDual (b i) m = b.repr m i := by - rw [← b.toDual_total_right, b.total_repr] + rw [← b.toDual_linearCombination_right, b.linearCombination_repr] theorem coe_toDual_self (i : ι) : b.toDual (b i) = b.coord i := by ext @@ -335,8 +340,8 @@ theorem toDual_ker : LinearMap.ker b.toDual = ⊥ := theorem toDual_range [Finite ι] : LinearMap.range b.toDual = ⊤ := by refine eq_top_iff'.2 fun f => ?_ let lin_comb : ι →₀ R := Finsupp.equivFunOnFinite.symm fun i => f (b i) - refine ⟨Finsupp.total ι M R b lin_comb, b.ext fun i => ?_⟩ - rw [b.toDual_eq_repr _ i, repr_total b] + refine ⟨Finsupp.linearCombination R b lin_comb, b.ext fun i => ?_⟩ + rw [b.toDual_eq_repr _ i, repr_linearCombination b] rfl end CommSemiring @@ -395,17 +400,19 @@ theorem dualBasis_apply_self (i j : ι) : b.dualBasis i (b j) = convert b.toDual_apply i j using 2 rw [@eq_comm _ j i] -theorem total_dualBasis (f : ι →₀ R) (i : ι) : - Finsupp.total ι (Dual R M) R b.dualBasis f (b i) = f i := by +theorem linearCombination_dualBasis (f : ι →₀ R) (i : ι) : + Finsupp.linearCombination R b.dualBasis f (b i) = f i := by cases nonempty_fintype ι - rw [Finsupp.total_apply, Finsupp.sum_fintype, LinearMap.sum_apply] + rw [Finsupp.linearCombination_apply, Finsupp.sum_fintype, LinearMap.sum_apply] · simp_rw [LinearMap.smul_apply, smul_eq_mul, dualBasis_apply_self, mul_boole, Finset.sum_ite_eq, if_pos (Finset.mem_univ i)] · intro rw [zero_smul] +@[deprecated (since := "2024-08-29")] alias total_dualBasis := linearCombination_dualBasis + theorem dualBasis_repr (l : Dual R M) (i : ι) : b.dualBasis.repr l i = l (b i) := by - rw [← total_dualBasis b, Basis.total_repr b.dualBasis l] + rw [← linearCombination_dualBasis b, Basis.linearCombination_repr b.dualBasis l] theorem dualBasis_apply (i : ι) (m : M) : b.dualBasis i m = b.repr m i := b.toDual_apply_right i m @@ -454,12 +461,14 @@ end end CommRing -/-- `simp` normal form version of `total_dualBasis` -/ +/-- `simp` normal form version of `linearCombination_dualBasis` -/ @[simp] -theorem total_coord [CommRing R] [AddCommGroup M] [Module R M] [Finite ι] (b : Basis ι R M) - (f : ι →₀ R) (i : ι) : Finsupp.total ι (Dual R M) R b.coord f (b i) = f i := by +theorem linearCombination_coord [CommRing R] [AddCommGroup M] [Module R M] [Finite ι] + (b : Basis ι R M) (f : ι →₀ R) (i : ι) : Finsupp.linearCombination R b.coord f (b i) = f i := by haveI := Classical.decEq ι - rw [← coe_dualBasis, total_dualBasis] + rw [← coe_dualBasis, linearCombination_dualBasis] + +@[deprecated (since := "2024-08-29")] alias total_coord := linearCombination_coord theorem dual_rank_eq [CommRing K] [AddCommGroup V] [Module K V] [Finite ι] (b : Basis ι K V) : Cardinal.lift.{uK,uV} (Module.rank K V) = Module.rank K (Dual K V) := by @@ -669,7 +678,7 @@ section DualBases open Module variable {R M ι : Type*} -variable [CommSemiring R] [AddCommMonoid M] [Module R M] [DecidableEq ι] +variable [CommSemiring R] [AddCommMonoid M] [Module R M] -- Porting note: replace use_finite_instance tactic open Lean.Elab.Tactic in @@ -682,10 +691,10 @@ elab "use_finite_instance" : tactic => evalUseFiniteInstance /-- `e` and `ε` have characteristic properties of a basis and its dual -/ -- @[nolint has_nonempty_instance] Porting note (#5171): removed structure Module.DualBases (e : ι → M) (ε : ι → Dual R M) : Prop where - eval : ∀ i j : ι, ε i (e j) = if i = j then 1 else 0 + eval_same : ∀ i, ε i (e i) = 1 + eval_of_ne : Pairwise fun i j ↦ ε i (e j) = 0 protected total : ∀ {m : M}, (∀ i, ε i m = 0) → m = 0 - protected finite : ∀ m : M, { i | ε i m ≠ 0 }.Finite := by - use_finite_instance + protected finite : ∀ m : M, {i | ε i m ≠ 0}.Finite := by use_finite_instance end DualBases @@ -698,35 +707,35 @@ variable [CommRing R] [AddCommGroup M] [Module R M] variable {e : ι → M} {ε : ι → Dual R M} /-- The coefficients of `v` on the basis `e` -/ -def coeffs [DecidableEq ι] (h : DualBases e ε) (m : M) : ι →₀ R where +def coeffs (h : DualBases e ε) (m : M) : ι →₀ R where toFun i := ε i m support := (h.finite m).toFinset mem_support_toFun i := by rw [Set.Finite.mem_toFinset, Set.mem_setOf_eq] @[simp] -theorem coeffs_apply [DecidableEq ι] (h : DualBases e ε) (m : M) (i : ι) : h.coeffs m i = ε i m := +theorem coeffs_apply (h : DualBases e ε) (m : M) (i : ι) : h.coeffs m i = ε i m := rfl /-- linear combinations of elements of `e`. -This is a convenient abbreviation for `Finsupp.total _ M R e l` -/ +This is a convenient abbreviation for `Finsupp.linearCombination R e l` -/ def lc {ι} (e : ι → M) (l : ι →₀ R) : M := l.sum fun (i : ι) (a : R) => a • e i -theorem lc_def (e : ι → M) (l : ι →₀ R) : lc e l = Finsupp.total _ _ R e l := +theorem lc_def (e : ι → M) (l : ι →₀ R) : lc e l = Finsupp.linearCombination R e l := rfl open Module -variable [DecidableEq ι] (h : DualBases e ε) +variable (h : DualBases e ε) include h theorem dual_lc (l : ι →₀ R) (i : ι) : ε i (DualBases.lc e l) = l i := by rw [lc, _root_.map_finsupp_sum, Finsupp.sum_eq_single i (g := fun a b ↦ (ε i) (b • e a))] -- Porting note: cannot get at • -- simp only [h.eval, map_smul, smul_eq_mul] - · simp [h.eval, smul_eq_mul] + · simp [h.eval_same, smul_eq_mul] · intro q _ q_ne - simp [q_ne.symm, h.eval, smul_eq_mul] + simp [h.eval_of_ne q_ne.symm, smul_eq_mul] · simp @[simp] @@ -741,7 +750,7 @@ theorem lc_coeffs (m : M) : DualBases.lc e (h.coeffs m) = m := by simp [LinearMap.map_sub, h.dual_lc, sub_eq_zero] /-- `(h : DualBases e ε).basis` shows the family of vectors `e` forms a basis. -/ -@[simps] +@[simps repr_apply, simps (config := .lemmasOnly) repr_symm_apply] def basis : Basis ι R M := Basis.ofRepr { toFun := coeffs h @@ -755,30 +764,24 @@ def basis : Basis ι R M := ext i exact (ε i).map_smul c v } --- Porting note: from simpNF the LHS simplifies; it yields lc_def.symm --- probably not a useful simp lemma; nolint simpNF since it cannot see this removal -attribute [-simp, nolint simpNF] basis_repr_symm_apply - @[simp] theorem coe_basis : ⇑h.basis = e := by ext i rw [Basis.apply_eq_iff] ext j - rw [h.basis_repr_apply, coeffs_apply, h.eval, Finsupp.single_apply] - convert if_congr (eq_comm (a := j) (b := i)) rfl rfl + rcases eq_or_ne i j with rfl | hne + · simp [h.eval_same] + · simp [hne, h.eval_of_ne hne.symm] --- `convert` to get rid of a `DecidableEq` mismatch theorem mem_of_mem_span {H : Set ι} {x : M} (hmem : x ∈ Submodule.span R (e '' H)) : ∀ i : ι, ε i x ≠ 0 → i ∈ H := by intro i hi - rcases (Finsupp.mem_span_image_iff_total _).mp hmem with ⟨l, supp_l, rfl⟩ + rcases (Finsupp.mem_span_image_iff_linearCombination _).mp hmem with ⟨l, supp_l, rfl⟩ apply not_imp_comm.mp ((Finsupp.mem_supported' _ _).mp supp_l i) rwa [← lc_def, h.dual_lc] at hi -theorem coe_dualBasis [_root_.Finite ι] : ⇑h.basis.dualBasis = ε := - funext fun i => - h.basis.ext fun j => by - rw [h.basis.dualBasis_apply_self, h.coe_basis, h.eval, if_congr eq_comm rfl rfl] +theorem coe_dualBasis [DecidableEq ι] [_root_.Finite ι] : ⇑h.basis.dualBasis = ε := + funext fun i => h.basis.ext fun j => by simp end Module.DualBases @@ -1076,7 +1079,7 @@ theorem dualAnnihilator_dualAnnihilator_eq (W : Subspace K V) : rw [dualCoannihilator, ← Module.mapEvalEquiv_symm_apply] at this rwa [← OrderIso.symm_apply_eq] -/-- The quotient by the dual is isomorphic to its dual annihilator. -/ +/-- The quotient by the dual is isomorphic to its dual annihilator. -/ -- Porting note (#11036): broken dot notation lean4#1910 LinearMap.range noncomputable def quotDualEquivAnnihilator (W : Subspace K V) : (Module.Dual K V ⧸ LinearMap.range W.dualLift) ≃ₗ[K] W.dualAnnihilator := @@ -1744,3 +1747,5 @@ noncomputable def dualDistribEquiv : Dual R M ⊗[R] Dual R N ≃ₗ[R] Dual R ( dualDistribEquivOfBasis (Module.Free.chooseBasis R M) (Module.Free.chooseBasis R N) end TensorProduct + +set_option linter.style.longFile 1900 diff --git a/Mathlib/LinearAlgebra/Eigenspace/Basic.lean b/Mathlib/LinearAlgebra/Eigenspace/Basic.lean index adad04b9bf8f0..b10d365990732 100644 --- a/Mathlib/LinearAlgebra/Eigenspace/Basic.lean +++ b/Mathlib/LinearAlgebra/Eigenspace/Basic.lean @@ -213,10 +213,8 @@ noncomputable def maxGenEigenspaceIndex (f : End R M) (μ : R) := /-- 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) : - maxGenEigenspace f μ = - f.genEigenspace μ (maxGenEigenspaceIndex f μ) := by - rw [isNoetherian_iff_wellFounded] at h - exact (WellFounded.iSup_eq_monotonicSequenceLimit h (f.genEigenspace μ) : _) + maxGenEigenspace f μ = f.genEigenspace μ (maxGenEigenspaceIndex f μ) := + h.wf.iSup_eq_monotonicSequenceLimit (f.genEigenspace μ) /-- A generalized eigenvalue for some exponent `k` is also a generalized eigenvalue for exponents larger than `k`. -/ diff --git a/Mathlib/LinearAlgebra/Eigenspace/Matrix.lean b/Mathlib/LinearAlgebra/Eigenspace/Matrix.lean index a58ddeb616fdd..7ae63cc2e199b 100644 --- a/Mathlib/LinearAlgebra/Eigenspace/Matrix.lean +++ b/Mathlib/LinearAlgebra/Eigenspace/Matrix.lean @@ -22,8 +22,7 @@ section SpectrumDiagonal variable {R n M : Type*} [DecidableEq n] [Fintype n] -open Matrix -open Module.End +open Matrix Module.End section NontrivialCommRing @@ -37,7 +36,7 @@ lemma hasEigenvector_toLin_diagonal (d : n → R) (i : n) (b : Basis n R M) : /-- Standard basis vectors are eigenvectors of any associated diagonal linear operator. -/ lemma hasEigenvector_toLin'_diagonal (d : n → R) (i : n) : HasEigenvector (toLin' (diagonal d)) (d i) (Pi.basisFun R n i) := - hasEigenvector_toLin_diagonal .. + hasEigenvector_toLin_diagonal _ _ (Pi.basisFun R n) /-- Eigenvalues of a diagonal linear operator are the diagonal entries. -/ lemma hasEigenvalue_toLin_diagonal_iff (d : n → R) {μ : R} [NoZeroSMulDivisors R M] diff --git a/Mathlib/LinearAlgebra/Eigenspace/Triangularizable.lean b/Mathlib/LinearAlgebra/Eigenspace/Triangularizable.lean index a8726197a4438..b6dd72733e4de 100644 --- a/Mathlib/LinearAlgebra/Eigenspace/Triangularizable.lean +++ b/Mathlib/LinearAlgebra/Eigenspace/Triangularizable.lean @@ -5,6 +5,7 @@ Authors: Alexander Bentkamp -/ import Mathlib.LinearAlgebra.Eigenspace.Basic import Mathlib.FieldTheory.IsAlgClosed.Spectrum +import Mathlib.LinearAlgebra.FreeModule.Finite.Matrix /-! # Triangularizable linear endomorphisms diff --git a/Mathlib/LinearAlgebra/ExteriorAlgebra/Basic.lean b/Mathlib/LinearAlgebra/ExteriorAlgebra/Basic.lean index 2ffd70d8b1bb4..3b3ed5d5dab30 100644 --- a/Mathlib/LinearAlgebra/ExteriorAlgebra/Basic.lean +++ b/Mathlib/LinearAlgebra/ExteriorAlgebra/Basic.lean @@ -132,7 +132,7 @@ theorem hom_ext {f g : ExteriorAlgebra R M →ₐ[R] A} CliffordAlgebra.hom_ext h /-- If `C` holds for the `algebraMap` of `r : R` into `ExteriorAlgebra R M`, the `ι` of `x : M`, -and is preserved under addition and muliplication, then it holds for all of `ExteriorAlgebra R M`. +and is preserved under addition and multiplication, then it holds for all of `ExteriorAlgebra R M`. -/ @[elab_as_elim] theorem induction {C : ExteriorAlgebra R M → Prop} @@ -372,7 +372,7 @@ theorem map_apply_ι (f : M →ₗ[R] N) (m : M) : map f (ι R m) = ι R (f m) : theorem map_apply_ιMulti {n : ℕ} (f : M →ₗ[R] N) (m : Fin n → M) : map f (ιMulti R n m) = ιMulti R n (f ∘ m) := by rw [ιMulti_apply, ιMulti_apply, map_list_prod] - simp only [List.map_ofFn, Function.comp, map_apply_ι] + simp only [List.map_ofFn, Function.comp_def, map_apply_ι] @[simp] theorem map_comp_ιMulti {n : ℕ} (f : M →ₗ[R] N) : diff --git a/Mathlib/LinearAlgebra/FiniteDimensional.lean b/Mathlib/LinearAlgebra/FiniteDimensional.lean index 640843d5b57d5..8aec07c6ff9dd 100644 --- a/Mathlib/LinearAlgebra/FiniteDimensional.lean +++ b/Mathlib/LinearAlgebra/FiniteDimensional.lean @@ -106,10 +106,9 @@ noncomputable def LinearEquiv.quotEquivOfEquiv {p : Subspace K V} {q : Subspace /-- Given the subspaces `p q`, if `p.quotient ≃ₗ[K] q`, then `q.quotient ≃ₗ[K] p` -/ noncomputable def LinearEquiv.quotEquivOfQuotEquiv {p q : Subspace K V} (f : (V ⧸ p) ≃ₗ[K] q) : (V ⧸ q) ≃ₗ[K] p := - LinearEquiv.ofFinrankEq _ _ <| - add_right_cancel <| by - rw [Submodule.finrank_quotient_add_finrank, ← LinearEquiv.finrank_eq f, add_comm, - Submodule.finrank_quotient_add_finrank] + LinearEquiv.ofFinrankEq _ _ <| by + rw [← add_right_cancel_iff, Submodule.finrank_quotient_add_finrank, ← LinearEquiv.finrank_eq f, + add_comm, Submodule.finrank_quotient_add_finrank] end DivisionRing diff --git a/Mathlib/LinearAlgebra/FiniteDimensional/Defs.lean b/Mathlib/LinearAlgebra/FiniteDimensional/Defs.lean index ed9305efcd20a..7209c69493247 100644 --- a/Mathlib/LinearAlgebra/FiniteDimensional/Defs.lean +++ b/Mathlib/LinearAlgebra/FiniteDimensional/Defs.lean @@ -684,7 +684,9 @@ noncomputable def divisionRingOfFiniteDimensional (F K : Type*) [Field F] [Ring exact (Classical.choose_spec (FiniteDimensional.exists_mul_eq_one F hx):) inv_zero := dif_pos rfl nnqsmul := _ + nnqsmul_def := fun q a => rfl qsmul := _ + qsmul_def := fun q a => rfl /-- An integral domain that is module-finite as an algebra over a field is a field. -/ noncomputable def fieldOfFiniteDimensional (F K : Type*) [Field F] [h : CommRing K] [IsDomain K] @@ -720,6 +722,7 @@ theorem finrank_span_singleton {v : V} (hv : v ≠ 0) : finrank K (K ∙ v) = 1 · exact finrank_span_le_card ({v} : Set V) · rw [Nat.succ_le_iff, finrank_pos_iff] use ⟨v, mem_span_singleton_self v⟩, 0 + apply Subtype.coe_ne_coe.mp simp [hv] /-- In a one-dimensional space, any vector is a multiple of any nonzero vector -/ diff --git a/Mathlib/LinearAlgebra/Finsupp.lean b/Mathlib/LinearAlgebra/Finsupp.lean index 209908215216b..fe713da58c68c 100644 --- a/Mathlib/LinearAlgebra/Finsupp.lean +++ b/Mathlib/LinearAlgebra/Finsupp.lean @@ -23,10 +23,10 @@ interpreted as a submodule of `α →₀ M`. We also define `LinearMap` versions linear map; * `Finsupp.restrictDom`: `Finsupp.filter` as a linear map to `Finsupp.supported s`; * `Finsupp.lsum`: `Finsupp.sum` or `Finsupp.liftAddHom` as a `LinearMap`; -* `Finsupp.total α M R (v : ι → M)`: sends `l : ι → R` to the linear combination of `v i` with - coefficients `l i`; -* `Finsupp.totalOn`: a restricted version of `Finsupp.total` with domain `Finsupp.supported R R s` - and codomain `Submodule.span R (v '' s)`; +* `Finsupp.linearCombination R (v : ι → M)`: sends `l : ι → R` to the linear combination of + `v i` with coefficients `l i`; +* `Finsupp.linearCombinationOn`: a restricted version of `Finsupp.linearCombination` with domain + `Finsupp.supported R R s` and codomain `Submodule.span R (v '' s)`; * `Finsupp.supportedEquivFinsupp`: a linear equivalence between the functions `α →₀ M` supported on `s` and the functions `s →₀ M`; * `Finsupp.lmapDomain`: a linear map version of `Finsupp.mapDomain`; @@ -587,75 +587,103 @@ def lcomapDomain (f : α → β) (hf : Function.Injective f) : (β →₀ M) → end LComapDomain -section Total +section LinearCombination -variable (α) (M) (R) +variable (R) variable {α' : Type*} {M' : Type*} [AddCommMonoid M'] [Module R M'] (v : α → M) {v' : α' → M'} -/-- Interprets (l : α →₀ R) as linear combination of the elements in the family (v : α → M) and +/-- Interprets (l : α →₀ R) as a linear combination of the elements in the family (v : α → M) and evaluates this linear combination. -/ -protected def total : (α →₀ R) →ₗ[R] M := +def linearCombination : (α →₀ R) →ₗ[R] M := Finsupp.lsum ℕ fun i => LinearMap.id.smulRight (v i) -variable {α M v} +@[deprecated (since := "2024-08-29")] noncomputable alias total := linearCombination + +variable {v} -theorem total_apply (l : α →₀ R) : Finsupp.total α M R v l = l.sum fun i a => a • v i := +theorem linearCombination_apply (l : α →₀ R) : linearCombination R v l = l.sum fun i a => a • v i := rfl -theorem total_apply_of_mem_supported {l : α →₀ R} {s : Finset α} - (hs : l ∈ supported R R (↑s : Set α)) : Finsupp.total α M R v l = s.sum fun i => l i • v i := +@[deprecated (since := "2024-08-29")] alias total_apply := linearCombination_apply + +theorem linearCombination_apply_of_mem_supported {l : α →₀ R} {s : Finset α} + (hs : l ∈ supported R R (↑s : Set α)) : linearCombination R v l = s.sum fun i => l i • v i := Finset.sum_subset hs fun x _ hxg => show l x • v x = 0 by rw [not_mem_support_iff.1 hxg, zero_smul] +@[deprecated (since := "2024-08-29")] alias total_apply_of_mem_supported := + linearCombination_apply_of_mem_supported + @[simp] -theorem total_single (c : R) (a : α) : Finsupp.total α M R v (single a c) = c • v a := by - simp [total_apply, sum_single_index] +theorem linearCombination_single (c : R) (a : α) : + linearCombination R v (single a c) = c • v a := by + simp [linearCombination_apply, sum_single_index] + +@[deprecated (since := "2024-08-29")] alias total_single := linearCombination_single -theorem total_zero_apply (x : α →₀ R) : (Finsupp.total α M R 0) x = 0 := by - simp [Finsupp.total_apply] +theorem linearCombination_zero_apply (x : α →₀ R) : (linearCombination R (0 : α → M)) x = 0 := by + simp [linearCombination_apply] + +@[deprecated (since := "2024-08-29")] alias total_zero_apply := linearCombination_zero_apply variable (α M) @[simp] -theorem total_zero : Finsupp.total α M R 0 = 0 := - LinearMap.ext (total_zero_apply R) +theorem linearCombination_zero : linearCombination R (0 : α → M) = 0 := + LinearMap.ext (linearCombination_zero_apply R) + +@[deprecated (since := "2024-08-29")] alias total_zero := linearCombination_zero variable {α M} -theorem apply_total (f : M →ₗ[R] M') (v) (l : α →₀ R) : - f (Finsupp.total α M R v l) = Finsupp.total α M' R (f ∘ v) l := by +theorem apply_linearCombination (f : M →ₗ[R] M') (v) (l : α →₀ R) : + f (linearCombination R v l) = linearCombination R (f ∘ v) l := by apply Finsupp.induction_linear l <;> simp (config := { contextual := true }) -theorem apply_total_id (f : M →ₗ[R] M') (l : M →₀ R) : - f (Finsupp.total M M R _root_.id l) = Finsupp.total M M' R f l := - apply_total .. +@[deprecated (since := "2024-08-29")] alias apply_total := apply_linearCombination + +theorem apply_linearCombination_id (f : M →ₗ[R] M') (l : M →₀ R) : + f (linearCombination R _root_.id l) = linearCombination R f l := + apply_linearCombination .. + +@[deprecated (since := "2024-08-29")] alias apply_total_id := apply_linearCombination_id + +theorem linearCombination_unique [Unique α] (l : α →₀ R) (v : α → M) : + linearCombination R v l = l default • v default := by + rw [← linearCombination_single, ← unique_single l] -theorem total_unique [Unique α] (l : α →₀ R) (v) : - Finsupp.total α M R v l = l default • v default := by rw [← total_single, ← unique_single l] +@[deprecated (since := "2024-08-29")] alias total_unique := linearCombination_unique -theorem total_surjective (h : Function.Surjective v) : - Function.Surjective (Finsupp.total α M R v) := by +theorem linearCombination_surjective (h : Function.Surjective v) : + Function.Surjective (linearCombination R v) := by intro x obtain ⟨y, hy⟩ := h x exact ⟨Finsupp.single y 1, by simp [hy]⟩ -theorem total_range (h : Function.Surjective v) : LinearMap.range (Finsupp.total α M R v) = ⊤ := - range_eq_top.2 <| total_surjective R h +@[deprecated (since := "2024-08-29")] alias total_surjective := linearCombination_surjective + +theorem linearCombination_range (h : Function.Surjective v) : + LinearMap.range (linearCombination R v) = ⊤ := + range_eq_top.2 <| linearCombination_surjective R h + +@[deprecated (since := "2024-08-29")] alias total_range := linearCombination_range /-- Any module is a quotient of a free module. This is stated as surjectivity of -`Finsupp.total M M R id : (M →₀ R) →ₗ[R] M`. -/ -theorem total_id_surjective (M) [AddCommMonoid M] [Module R M] : - Function.Surjective (Finsupp.total M M R _root_.id) := - total_surjective R Function.surjective_id +`Finsupp.linearCombination R id : (M →₀ R) →ₗ[R] M`. -/ +theorem linearCombination_id_surjective (M) [AddCommMonoid M] [Module R M] : + Function.Surjective (linearCombination R (id : M → M)) := + linearCombination_surjective R Function.surjective_id + +@[deprecated (since := "2024-08-29")] alias total_id_surjective := linearCombination_id_surjective -theorem range_total : LinearMap.range (Finsupp.total α M R v) = span R (range v) := by +theorem range_linearCombination : LinearMap.range (linearCombination R v) = span R (range v) := by ext x constructor · intro hx rw [LinearMap.mem_range] at hx rcases hx with ⟨l, hl⟩ rw [← hl] - rw [Finsupp.total_apply] + rw [linearCombination_apply] exact sum_mem fun i _ => Submodule.smul_mem _ _ (subset_span (mem_range_self i)) · apply span_le.2 intro x hx @@ -664,49 +692,68 @@ theorem range_total : LinearMap.range (Finsupp.total α M R v) = span R (range v use Finsupp.single i 1 simp [hi] -theorem lmapDomain_total (f : α → α') (g : M →ₗ[R] M') (h : ∀ i, g (v i) = v' (f i)) : - (Finsupp.total α' M' R v').comp (lmapDomain R R f) = g.comp (Finsupp.total α M R v) := by +@[deprecated (since := "2024-08-29")] alias range_total := range_linearCombination + +theorem lmapDomain_linearCombination (f : α → α') (g : M →ₗ[R] M') (h : ∀ i, g (v i) = v' (f i)) : + (linearCombination R v').comp (lmapDomain R R f) = g.comp (linearCombination R v) := by ext l - simp [total_apply, Finsupp.sum_mapDomain_index, add_smul, h] + simp [linearCombination_apply, Finsupp.sum_mapDomain_index, add_smul, h] + +@[deprecated (since := "2024-08-29")] alias lmapDomain_total := lmapDomain_linearCombination -theorem total_comp_lmapDomain (f : α → α') : - (Finsupp.total α' M' R v').comp (Finsupp.lmapDomain R R f) = Finsupp.total α M' R (v' ∘ f) := by +theorem linearCombination_comp_lmapDomain (f : α → α') : + (linearCombination R v').comp (Finsupp.lmapDomain R R f) = linearCombination R (v' ∘ f) := by ext simp +@[deprecated (since := "2024-08-29")] alias total_comp_lmapDomain := + linearCombination_comp_lmapDomain + @[simp] -theorem total_embDomain (f : α ↪ α') (l : α →₀ R) : - (Finsupp.total α' M' R v') (embDomain f l) = (Finsupp.total α M' R (v' ∘ f)) l := by - simp [total_apply, Finsupp.sum, support_embDomain, embDomain_apply] +theorem linearCombination_embDomain (f : α ↪ α') (l : α →₀ R) : + (linearCombination R v') (embDomain f l) = (linearCombination R (v' ∘ f)) l := by + simp [linearCombination_apply, Finsupp.sum, support_embDomain, embDomain_apply] + +@[deprecated (since := "2024-08-29")] alias total_embDomain := linearCombination_embDomain @[simp] -theorem total_mapDomain (f : α → α') (l : α →₀ R) : - (Finsupp.total α' M' R v') (mapDomain f l) = (Finsupp.total α M' R (v' ∘ f)) l := - LinearMap.congr_fun (total_comp_lmapDomain _ _) l +theorem linearCombination_mapDomain (f : α → α') (l : α →₀ R) : + (linearCombination R v') (mapDomain f l) = (linearCombination R (v' ∘ f)) l := + LinearMap.congr_fun (linearCombination_comp_lmapDomain _ _) l + +@[deprecated (since := "2024-08-29")] alias total_mapDomain := linearCombination_mapDomain @[simp] -theorem total_equivMapDomain (f : α ≃ α') (l : α →₀ R) : - (Finsupp.total α' M' R v') (equivMapDomain f l) = (Finsupp.total α M' R (v' ∘ f)) l := by - rw [equivMapDomain_eq_mapDomain, total_mapDomain] +theorem linearCombination_equivMapDomain (f : α ≃ α') (l : α →₀ R) : + (linearCombination R v') (equivMapDomain f l) = (linearCombination R (v' ∘ f)) l := by + rw [equivMapDomain_eq_mapDomain, linearCombination_mapDomain] + +@[deprecated (since := "2024-08-29")] alias total_equivMapDomain := linearCombination_equivMapDomain + +/-- A version of `Finsupp.range_linearCombination` which is useful for going in the other +direction -/ +theorem span_eq_range_linearCombination (s : Set M) : + span R s = LinearMap.range (linearCombination R ((↑) : s → M)) := by + rw [range_linearCombination, Subtype.range_coe_subtype, Set.setOf_mem_eq] -/-- A version of `Finsupp.range_total` which is useful for going in the other direction -/ -theorem span_eq_range_total (s : Set M) : span R s = LinearMap.range (Finsupp.total s M R (↑)) := by - rw [range_total, Subtype.range_coe_subtype, Set.setOf_mem_eq] +@[deprecated (since := "2024-08-29")] alias span_eq_range_total := span_eq_range_linearCombination -theorem mem_span_iff_total (s : Set M) (x : M) : - x ∈ span R s ↔ ∃ l : s →₀ R, Finsupp.total s M R (↑) l = x := - (SetLike.ext_iff.1 <| span_eq_range_total _ _) x +theorem mem_span_iff_linearCombination (s : Set M) (x : M) : + x ∈ span R s ↔ ∃ l : s →₀ R, linearCombination R (↑) l = x := + (SetLike.ext_iff.1 <| span_eq_range_linearCombination _ _) x + +@[deprecated (since := "2024-08-29")] alias mem_span_iff_total := mem_span_iff_linearCombination variable {R} theorem mem_span_range_iff_exists_finsupp {v : α → M} {x : M} : x ∈ span R (range v) ↔ ∃ c : α →₀ R, (c.sum fun i a => a • v i) = x := by - simp only [← Finsupp.range_total, LinearMap.mem_range, Finsupp.total_apply] + simp only [← Finsupp.range_linearCombination, LinearMap.mem_range, linearCombination_apply] variable (R) -theorem span_image_eq_map_total (s : Set α) : - span R (v '' s) = Submodule.map (Finsupp.total α M R v) (supported R R s) := by +theorem span_image_eq_map_linearCombination (s : Set α) : + span R (v '' s) = Submodule.map (linearCombination R v) (supported R R s) := by apply span_eq_of_le · intro x hx rw [Set.mem_image] at hx @@ -721,75 +768,99 @@ theorem span_image_eq_map_total (s : Set α) : · exact smul_mem _ _ (subset_span (Set.mem_image_of_mem _ h)) · simp [(Finsupp.mem_supported' R _).1 hz _ h] -- Porting note: `rw` is required to infer metavariables in `sum_mem`. - rw [mem_comap, total_apply] + rw [mem_comap, linearCombination_apply] refine sum_mem ?_ simp [this] -theorem mem_span_image_iff_total {s : Set α} {x : M} : - x ∈ span R (v '' s) ↔ ∃ l ∈ supported R R s, Finsupp.total α M R v l = x := by - rw [span_image_eq_map_total] +@[deprecated (since := "2024-08-29")] alias span_image_eq_map_total := + span_image_eq_map_linearCombination + +theorem mem_span_image_iff_linearCombination {s : Set α} {x : M} : + x ∈ span R (v '' s) ↔ ∃ l ∈ supported R R s, linearCombination R v l = x := by + rw [span_image_eq_map_linearCombination] simp -theorem total_option (v : Option α → M) (f : Option α →₀ R) : - Finsupp.total (Option α) M R v f = - f none • v none + Finsupp.total α M R (v ∘ Option.some) f.some := by - rw [total_apply, sum_option_index_smul, total_apply]; simp +@[deprecated (since := "2024-08-29")] alias mem_span_image_iff_total := + mem_span_image_iff_linearCombination + +theorem linearCombination_option (v : Option α → M) (f : Option α →₀ R) : + linearCombination R v f = + f none • v none + linearCombination R (v ∘ Option.some) f.some := by + rw [linearCombination_apply, sum_option_index_smul, linearCombination_apply]; simp -theorem total_total {α β : Type*} (A : α → M) (B : β → α →₀ R) (f : β →₀ R) : - Finsupp.total α M R A (Finsupp.total β (α →₀ R) R B f) = - Finsupp.total β M R (fun b => Finsupp.total α M R A (B b)) f := by +@[deprecated (since := "2024-08-29")] alias total_option := linearCombination_option + +theorem linearCombination_linearCombination {α β : Type*} (A : α → M) (B : β → α →₀ R) + (f : β →₀ R) : linearCombination R A (linearCombination R B f) = + linearCombination R (fun b => linearCombination R A (B b)) f := by classical - simp only [total_apply] + simp only [linearCombination_apply] apply induction_linear f · simp only [sum_zero_index] · intro f₁ f₂ h₁ h₂ simp [sum_add_index, h₁, h₂, add_smul] · simp [sum_single_index, sum_smul_index, smul_sum, mul_smul] +@[deprecated (since := "2024-08-29")] alias total_total := linearCombination_linearCombination + @[simp] -theorem total_fin_zero (f : Fin 0 → M) : Finsupp.total (Fin 0) M R f = 0 := by +theorem linearCombination_fin_zero (f : Fin 0 → M) : linearCombination R f = 0 := by ext i apply finZeroElim i +@[deprecated (since := "2024-08-29")] alias total_fin_zero := linearCombination_fin_zero + variable (α) (M) (v) -/-- `Finsupp.totalOn M v s` interprets `p : α →₀ R` as a linear combination of a +/-- `Finsupp.linearCombinationOn M v s` interprets `p : α →₀ R` as a linear combination of a subset of the vectors in `v`, mapping it to the span of those vectors. The subset is indicated by a set `s : Set α` of indices. -/ -protected def totalOn (s : Set α) : supported R R s →ₗ[R] span R (v '' s) := - LinearMap.codRestrict _ ((Finsupp.total _ _ _ v).comp (Submodule.subtype (supported R R s))) - fun ⟨l, hl⟩ => (mem_span_image_iff_total _).2 ⟨l, hl, rfl⟩ +def linearCombinationOn (s : Set α) : supported R R s →ₗ[R] span R (v '' s) := + LinearMap.codRestrict _ ((linearCombination _ v).comp (Submodule.subtype (supported R R s))) + fun ⟨l, hl⟩ => (mem_span_image_iff_linearCombination _).2 ⟨l, hl, rfl⟩ + +@[deprecated (since := "2024-08-29")] noncomputable alias totalOn := linearCombinationOn variable {α} {M} {v} -theorem totalOn_range (s : Set α) : LinearMap.range (Finsupp.totalOn α M R v s) = ⊤ := by - rw [Finsupp.totalOn, LinearMap.range_eq_map, LinearMap.map_codRestrict, +theorem linearCombinationOn_range (s : Set α) : + LinearMap.range (linearCombinationOn α M R v s) = ⊤ := by + rw [linearCombinationOn, LinearMap.range_eq_map, LinearMap.map_codRestrict, ← LinearMap.range_le_iff_comap, range_subtype, Submodule.map_top, LinearMap.range_comp, range_subtype] - exact (span_image_eq_map_total _ _).le + exact (span_image_eq_map_linearCombination _ _).le + +@[deprecated (since := "2024-08-29")] alias totalOn_range := linearCombinationOn_range -theorem total_comp (f : α' → α) : - Finsupp.total α' M R (v ∘ f) = (Finsupp.total α M R v).comp (lmapDomain R R f) := by +theorem linearCombination_comp (f : α' → α) : + linearCombination R (v ∘ f) = (linearCombination R v).comp (lmapDomain R R f) := by ext - simp [total_apply] + simp [linearCombination_apply] -theorem total_comapDomain (f : α → α') (l : α' →₀ R) (hf : Set.InjOn f (f ⁻¹' ↑l.support)) : - Finsupp.total α M R v (Finsupp.comapDomain f l hf) = +@[deprecated (since := "2024-08-29")] alias total_comp := linearCombination_comp + +theorem linearCombination_comapDomain (f : α → α') (l : α' →₀ R) + (hf : Set.InjOn f (f ⁻¹' ↑l.support)) : linearCombination R v (Finsupp.comapDomain f l hf) = (l.support.preimage f hf).sum fun i => l (f i) • v i := by - rw [Finsupp.total_apply]; rfl + rw [linearCombination_apply]; rfl + +@[deprecated (since := "2024-08-29")] alias total_comapDomain := linearCombination_comapDomain -theorem total_onFinset {s : Finset α} {f : α → R} (g : α → M) (hf : ∀ a, f a ≠ 0 → a ∈ s) : - Finsupp.total α M R g (Finsupp.onFinset s f hf) = Finset.sum s fun x : α => f x • g x := by +theorem linearCombination_onFinset {s : Finset α} {f : α → R} (g : α → M) + (hf : ∀ a, f a ≠ 0 → a ∈ s) : + linearCombination R g (Finsupp.onFinset s f hf) = Finset.sum s fun x : α => f x • g x := by classical - simp only [Finsupp.total_apply, Finsupp.sum, Finsupp.onFinset_apply, Finsupp.support_onFinset] + simp only [linearCombination_apply, Finsupp.sum, Finsupp.onFinset_apply, Finsupp.support_onFinset] rw [Finset.sum_filter_of_ne] intro x _ h contrapose! h simp [h] -end Total +@[deprecated (since := "2024-08-29")] alias total_onFinset := linearCombination_onFinset + +end LinearCombination /-- An equivalence of domains induces a linear equivalence of finitely supported functions. @@ -1036,13 +1107,13 @@ variable {α M : Type*} (R : Type*) [Fintype α] [Semiring R] [AddCommMonoid M] variable (S : Type*) [Semiring S] [Module S M] [SMulCommClass R S M] variable (v : α → M) -/-- `Fintype.total R S v f` is the linear combination of vectors in `v` with weights in `f`. -This variant of `Finsupp.total` is defined on fintype indexed vectors. +/-- `Fintype.linearCombination R S v f` is the linear combination of vectors in `v` with weights +in `f`. This variant of `Finsupp.linearCombination` is defined on fintype indexed vectors. This map is linear in `v` if `R` is commutative, and always linear in `f`. See note [bundled maps over different rings] for why separate `R` and `S` semirings are used. -/ -protected def Fintype.total : (α → M) →ₗ[S] (α → R) →ₗ[R] M where +protected def Fintype.linearCombination : (α → M) →ₗ[S] (α → R) →ₗ[R] M where toFun v := { toFun := fun f => ∑ i, f i • v i map_add' := fun f g => by simp_rw [← Finset.sum_add_distrib, ← add_smul]; rfl @@ -1050,39 +1121,55 @@ protected def Fintype.total : (α → M) →ₗ[S] (α → R) →ₗ[R] M where map_add' u v := by ext; simp [Finset.sum_add_distrib, Pi.add_apply, smul_add] map_smul' r v := by ext; simp [Finset.smul_sum, smul_comm] +@[deprecated (since := "2024-08-29")] alias Fintype.total := Fintype.linearCombination + variable {S} -theorem Fintype.total_apply (f) : Fintype.total R S v f = ∑ i, f i • v i := +theorem Fintype.linearCombination_apply (f) : Fintype.linearCombination R S v f = ∑ i, f i • v i := rfl +@[deprecated (since := "2024-08-29")] alias Fintype.total_apply := Fintype.linearCombination_apply + @[simp] -theorem Fintype.total_apply_single [DecidableEq α] (i : α) (r : R) : - Fintype.total R S v (Pi.single i r) = r • v i := by - simp_rw [Fintype.total_apply, Pi.single_apply, ite_smul, zero_smul] +theorem Fintype.linearCombination_apply_single [DecidableEq α] (i : α) (r : R) : + Fintype.linearCombination R S v (Pi.single i r) = r • v i := by + simp_rw [Fintype.linearCombination_apply, Pi.single_apply, ite_smul, zero_smul] rw [Finset.sum_ite_eq', if_pos (Finset.mem_univ _)] +@[deprecated (since := "2024-08-29")] alias Fintype.total_apply_single := + Fintype.linearCombination_apply_single + variable (S) -theorem Finsupp.total_eq_fintype_total_apply (x : α → R) : Finsupp.total α M R v - ((Finsupp.linearEquivFunOnFinite R R α).symm x) = Fintype.total R S v x := by +theorem Finsupp.linearCombination_eq_fintype_linearCombination_apply (x : α → R) : + linearCombination R v ((Finsupp.linearEquivFunOnFinite R R α).symm x) = + Fintype.linearCombination R S v x := by apply Finset.sum_subset · exact Finset.subset_univ _ · intro x _ hx rw [Finsupp.not_mem_support_iff.mp hx] exact zero_smul _ _ -theorem Finsupp.total_eq_fintype_total : - (Finsupp.total α M R v).comp (Finsupp.linearEquivFunOnFinite R R α).symm.toLinearMap = - Fintype.total R S v := - LinearMap.ext <| Finsupp.total_eq_fintype_total_apply R S v +@[deprecated (since := "2024-08-29")] alias Finsupp.total_eq_fintype_total_apply := + Finsupp.linearCombination_eq_fintype_linearCombination_apply + +theorem Finsupp.linearCombination_eq_fintype_linearCombination : + (linearCombination R v).comp (Finsupp.linearEquivFunOnFinite R R α).symm.toLinearMap = + Fintype.linearCombination R S v := + LinearMap.ext <| linearCombination_eq_fintype_linearCombination_apply R S v + +@[deprecated (since := "2024-08-29")] alias Finsupp.total_eq_fintype_total := + Finsupp.linearCombination_eq_fintype_linearCombination variable {S} @[simp] -theorem Fintype.range_total : - LinearMap.range (Fintype.total R S v) = Submodule.span R (Set.range v) := by - rw [← Finsupp.total_eq_fintype_total, LinearMap.range_comp, LinearEquiv.range, - Submodule.map_top, Finsupp.range_total] +theorem Fintype.range_linearCombination : + LinearMap.range (Fintype.linearCombination R S v) = Submodule.span R (Set.range v) := by + rw [← Finsupp.linearCombination_eq_fintype_linearCombination, LinearMap.range_comp, + LinearEquiv.range, Submodule.map_top, Finsupp.range_linearCombination] + +@[deprecated (since := "2024-08-29")] alias Fintype.range_total := Fintype.range_linearCombination section SpanRange @@ -1112,32 +1199,40 @@ end Fintype variable {R : Type*} {M : Type*} {N : Type*} variable [Semiring R] [AddCommMonoid M] [Module R M] [AddCommMonoid N] [Module R N] +open Finsupp + section variable (R) /-- Pick some representation of `x : span R w` as a linear combination in `w`, -using the axiom of choice. + ((Finsupp.mem_span_iff_linearCombination _ _ _).mp x.2).choose -/ irreducible_def Span.repr (w : Set M) (x : span R w) : w →₀ R := - ((Finsupp.mem_span_iff_total _ _ _).mp x.2).choose + ((Finsupp.mem_span_iff_linearCombination _ _ _).mp x.2).choose @[simp] -theorem Span.finsupp_total_repr {w : Set M} (x : span R w) : - Finsupp.total w M R (↑) (Span.repr R w x) = x := by +theorem Span.finsupp_linearCombination_repr {w : Set M} (x : span R w) : + Finsupp.linearCombination R ((↑) : w → M) (Span.repr R w x) = x := by rw [Span.repr_def] - exact ((Finsupp.mem_span_iff_total _ _ _).mp x.2).choose_spec + exact ((Finsupp.mem_span_iff_linearCombination _ _ _).mp x.2).choose_spec +@[deprecated (since := "2024-08-29")] alias Span.finsupp_total_repr := + Span.finsupp_linearCombination_repr end protected theorem Submodule.finsupp_sum_mem {ι β : Type*} [Zero β] (S : Submodule R M) (f : ι →₀ β) (g : ι → β → M) (h : ∀ c, f c ≠ 0 → g c (f c) ∈ S) : f.sum g ∈ S := AddSubmonoidClass.finsupp_sum_mem S f g h -theorem LinearMap.map_finsupp_total (f : M →ₗ[R] N) {ι : Type*} {g : ι → M} (l : ι →₀ R) : - f (Finsupp.total ι M R g l) = Finsupp.total ι N R (f ∘ g) l := by +theorem LinearMap.map_finsupp_linearCombination (f : M →ₗ[R] N) {ι : Type*} {g : ι → M} + (l : ι →₀ R) : f (linearCombination R g l) = linearCombination R (f ∘ g) l := by -- Porting note: `(· ∘ ·)` is required. - simp only [Finsupp.total_apply, Finsupp.total_apply, Finsupp.sum, map_sum, map_smul, (· ∘ ·)] + simp only [linearCombination_apply, linearCombination_apply, Finsupp.sum, map_sum, map_smul, + (· ∘ ·)] + +@[deprecated (since := "2024-08-29")] alias LinearMap.map_finsupp_total := + LinearMap.map_finsupp_linearCombination theorem Submodule.exists_finset_of_mem_iSup {ι : Sort _} (p : ι → Submodule R M) {m : M} (hm : m ∈ ⨆ i, p i) : ∃ s : Finset ι, m ∈ ⨆ i ∈ s, p i := by @@ -1168,9 +1263,9 @@ theorem mem_span_finset {s : Finset M} {x : M} : x ∈ span R (↑s : Set M) ↔ ∃ f : M → R, ∑ i ∈ s, f i • i = x := ⟨fun hx => let ⟨v, hvs, hvx⟩ := - (Finsupp.mem_span_image_iff_total _).1 + (Finsupp.mem_span_image_iff_linearCombination _).1 (show x ∈ span R (_root_.id '' (↑s : Set M)) by rwa [Set.image_id]) - ⟨v, hvx ▸ (Finsupp.total_apply_of_mem_supported _ hvs).symm⟩, + ⟨v, hvx ▸ (linearCombination_apply_of_mem_supported _ hvs).symm⟩, fun ⟨f, hf⟩ => hf ▸ sum_mem fun i hi => smul_mem _ _ <| subset_span hi⟩ /-- An element `m ∈ M` is contained in the `R`-submodule spanned by a set `s ⊆ M`, if and only if @@ -1180,7 +1275,7 @@ theorem mem_span_set {m : M} {s : Set M} : m ∈ Submodule.span R s ↔ ∃ c : M →₀ R, (c.support : Set M) ⊆ s ∧ (c.sum fun mi r => r • mi) = m := by conv_lhs => rw [← Set.image_id s] - exact Finsupp.mem_span_image_iff_total R (v := _root_.id (α := M)) + exact Finsupp.mem_span_image_iff_linearCombination R (v := _root_.id (α := M)) /-- An element `m ∈ M` is contained in the `R`-submodule spanned by a set `s ⊆ M`, if and only if `m` can be written as a finite `R`-linear combination of elements of `s`. diff --git a/Mathlib/LinearAlgebra/FreeModule/Basic.lean b/Mathlib/LinearAlgebra/FreeModule/Basic.lean index d93fc0610a6b4..ae0a984945266 100644 --- a/Mathlib/LinearAlgebra/FreeModule/Basic.lean +++ b/Mathlib/LinearAlgebra/FreeModule/Basic.lean @@ -13,7 +13,8 @@ import Mathlib.LinearAlgebra.TensorProduct.Basis We introduce a class `Module.Free R M`, for `R` a `Semiring` and `M` an `R`-module and we provide several basic instances for this class. -Use `Finsupp.total_id_surjective` to prove that any module is the quotient of a free module. +Use `Finsupp.linearCombination_id_surjective` to prove that any module is the quotient of a free +module. ## Main definition diff --git a/Mathlib/LinearAlgebra/FreeModule/Finite/Matrix.lean b/Mathlib/LinearAlgebra/FreeModule/Finite/Matrix.lean index 7be847207c3de..d0b35b5f4be62 100644 --- a/Mathlib/LinearAlgebra/FreeModule/Finite/Matrix.lean +++ b/Mathlib/LinearAlgebra/FreeModule/Finite/Matrix.lean @@ -65,6 +65,9 @@ theorem FiniteDimensional.rank_linearMap_self : theorem FiniteDimensional.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 + end Ring section AlgHom diff --git a/Mathlib/LinearAlgebra/FreeModule/PID.lean b/Mathlib/LinearAlgebra/FreeModule/PID.lean index 4d837a3b56384..ea581374ba3ee 100644 --- a/Mathlib/LinearAlgebra/FreeModule/PID.lean +++ b/Mathlib/LinearAlgebra/FreeModule/PID.lean @@ -369,9 +369,8 @@ noncomputable def Module.basisOfFiniteTypeTorsionFree [Fintype ι] {s : ι → M apply this intro i calc - (∏ j, a j) • s i = (∏ j ∈ {i}ᶜ, a j) • a i • s i := by - rw [Fintype.prod_eq_prod_compl_mul i, mul_smul] - _ ∈ N := N.smul_mem _ (ha' i) + (∏ j ∈ {i}ᶜ, a j) • a i • s i ∈ N := N.smul_mem _ (ha' i) + _ = (∏ j, a j) • s i := by rw [Fintype.prod_eq_prod_compl_mul i, mul_smul] -- Since a submodule of a free `R`-module is free, we get that `A • M` is free obtain ⟨n, b : Basis (Fin n) R (LinearMap.range φ)⟩ := Submodule.basisOfPidOfLE this sI_basis diff --git a/Mathlib/LinearAlgebra/JordanChevalley.lean b/Mathlib/LinearAlgebra/JordanChevalley.lean index 76d5f6488464f..b526d14e3ebcd 100644 --- a/Mathlib/LinearAlgebra/JordanChevalley.lean +++ b/Mathlib/LinearAlgebra/JordanChevalley.lean @@ -5,6 +5,7 @@ Authors: Oliver Nash -/ import Mathlib.Dynamics.Newton import Mathlib.LinearAlgebra.Semisimple +import Mathlib.LinearAlgebra.FreeModule.Finite.Matrix /-! # Jordan-Chevalley-Dunford decomposition diff --git a/Mathlib/LinearAlgebra/Lagrange.lean b/Mathlib/LinearAlgebra/Lagrange.lean index d3e6374765d4c..982898e6d7590 100644 --- a/Mathlib/LinearAlgebra/Lagrange.lean +++ b/Mathlib/LinearAlgebra/Lagrange.lean @@ -504,8 +504,9 @@ theorem nodal_eq_mul_nodal_erase [DecidableEq ι] {i : ι} (hi : i ∈ s) : nodal s v = (X - C (v i)) * nodal (s.erase i) v := by simp_rw [nodal, Finset.mul_prod_erase _ (fun x => X - C (v x)) hi] -theorem X_sub_C_dvd_nodal (v : ι → R) {i : ι} (hi : i ∈ s) : X - C (v i) ∣ nodal s v := - ⟨_, by classical exact nodal_eq_mul_nodal_erase hi⟩ +theorem X_sub_C_dvd_nodal (v : ι → R) {i : ι} (hi : i ∈ s) : X - C (v i) ∣ nodal s v := by + classical + exact ⟨nodal (s.erase i) v, nodal_eq_mul_nodal_erase hi⟩ theorem nodal_insert_eq_nodal [DecidableEq ι] {i : ι} (hi : i ∉ s) : nodal (insert i s) v = (X - C (v i)) * nodal s v := by diff --git a/Mathlib/LinearAlgebra/LinearDisjoint.lean b/Mathlib/LinearAlgebra/LinearDisjoint.lean index 725d409379f59..20c9c3b4316e4 100644 --- a/Mathlib/LinearAlgebra/LinearDisjoint.lean +++ b/Mathlib/LinearAlgebra/LinearDisjoint.lean @@ -208,15 +208,15 @@ theorem of_basis_right' {ι : Type*} (n : Basis ι R N) /-- If `{ m_i }` is an `R`-basis of `M`, if `{ n_i }` is an `R`-basis of `N`, such that the family `{ m_i * n_j }` in `S` is `R`-linearly independent -(in this result it is stated as the relevant `Finsupp.total` is injective), +(in this result it is stated as the relevant `Finsupp.linearCombination` is injective), then `M` and `N` are linearly disjoint. -/ theorem of_basis_mul' {κ ι : Type*} (m : Basis κ R M) (n : Basis ι R N) - (H : Function.Injective (Finsupp.total (κ × ι) S R fun i ↦ m i.1 * n i.2)) : + (H : Function.Injective (Finsupp.linearCombination R fun i : κ × ι ↦ (m i.1 * n i.2 : S))) : M.LinearDisjoint N := by let i0 := (finsuppTensorFinsupp' R κ ι).symm let i1 := TensorProduct.congr m.repr n.repr let i := mulMap M N ∘ₗ (i0.trans i1.symm).toLinearMap - have : i = Finsupp.total (κ × ι) S R fun i ↦ m i.1 * n i.2 := by + have : i = Finsupp.linearCombination R fun i : κ × ι ↦ (m i.1 * n i.2 : S) := by ext x simp [i, i0, i1, finsuppTensorFinsupp'_symm_single_eq_single_one_tmul] simp_rw [← this, i, LinearMap.coe_comp, LinearEquiv.coe_coe, EquivLike.injective_comp] at H @@ -354,13 +354,13 @@ theorem linearIndependent_mul_of_flat_left (H : M.LinearDisjoint N) [Module.Flat (hn : LinearIndependent R n) : LinearIndependent R fun (i : κ × ι) ↦ (m i.1).1 * (n i.2).1 := by rw [LinearIndependent, LinearMap.ker_eq_bot] at hm hn ⊢ let i0 := (finsuppTensorFinsupp' R κ ι).symm - let i1 := LinearMap.rTensor (ι →₀ R) (Finsupp.total κ M R m) - let i2 := LinearMap.lTensor M (Finsupp.total ι N R n) + let i1 := LinearMap.rTensor (ι →₀ R) (Finsupp.linearCombination R m) + let i2 := LinearMap.lTensor M (Finsupp.linearCombination R n) let i := mulMap M N ∘ₗ i2 ∘ₗ i1 ∘ₗ i0.toLinearMap have h1 : Function.Injective i1 := Module.Flat.rTensor_preserves_injective_linearMap _ hm have h2 : Function.Injective i2 := Module.Flat.lTensor_preserves_injective_linearMap _ hn have h : Function.Injective i := H.injective.comp h2 |>.comp h1 |>.comp i0.injective - have : i = Finsupp.total (κ × ι) S R fun i ↦ (m i.1).1 * (n i.2).1 := by + have : i = Finsupp.linearCombination R fun i ↦ (m i.1).1 * (n i.2).1 := by ext x simp [i, i0, i1, i2, finsuppTensorFinsupp'_symm_single_eq_single_one_tmul] rwa [this] at h @@ -375,13 +375,13 @@ theorem linearIndependent_mul_of_flat_right (H : M.LinearDisjoint N) [Module.Fla (hn : LinearIndependent R n) : LinearIndependent R fun (i : κ × ι) ↦ (m i.1).1 * (n i.2).1 := by rw [LinearIndependent, LinearMap.ker_eq_bot] at hm hn ⊢ let i0 := (finsuppTensorFinsupp' R κ ι).symm - let i1 := LinearMap.lTensor (κ →₀ R) (Finsupp.total ι N R n) - let i2 := LinearMap.rTensor N (Finsupp.total κ M R m) + let i1 := LinearMap.lTensor (κ →₀ R) (Finsupp.linearCombination R n) + let i2 := LinearMap.rTensor N (Finsupp.linearCombination R m) let i := mulMap M N ∘ₗ i2 ∘ₗ i1 ∘ₗ i0.toLinearMap have h1 : Function.Injective i1 := Module.Flat.lTensor_preserves_injective_linearMap _ hn have h2 : Function.Injective i2 := Module.Flat.rTensor_preserves_injective_linearMap _ hm have h : Function.Injective i := H.injective.comp h2 |>.comp h1 |>.comp i0.injective - have : i = Finsupp.total (κ × ι) S R fun i ↦ (m i.1).1 * (n i.2).1 := by + have : i = Finsupp.linearCombination R fun i ↦ (m i.1).1 * (n i.2).1 := by ext x simp [i, i0, i1, i2, finsuppTensorFinsupp'_symm_single_eq_single_one_tmul] rwa [this] at h @@ -477,8 +477,8 @@ theorem not_linearIndependent_pair_of_commute_of_flat_left [Module.Flat R M] have hm : mulRightMap M n m = 0 := by simp [m, n, show _ * _ = _ * _ from hc] rw [← LinearMap.mem_ker, H.linearIndependent_right_of_flat hn, mem_bot] at hm simp only [Fin.isValue, sub_eq_zero, Finsupp.single_eq_single_iff, zero_ne_one, Subtype.mk.injEq, - SetLike.coe_eq_coe, false_and, AddSubmonoid.mk_eq_zero, ZeroMemClass.coe_eq_zero, - false_or, m] at hm + SetLike.coe_eq_coe, false_and, false_or, m] at hm + repeat rw [AddSubmonoid.mk_eq_zero, ZeroMemClass.coe_eq_zero] at hm exact h.ne_zero 0 hm.2 /-- If `M` and `N` are linearly disjoint, if `N` is flat, then any two commutative @@ -493,8 +493,8 @@ theorem not_linearIndependent_pair_of_commute_of_flat_right [Module.Flat R N] have hn : mulLeftMap N m n = 0 := by simp [m, n, show _ * _ = _ * _ from hc] rw [← LinearMap.mem_ker, H.linearIndependent_left_of_flat hm, mem_bot] at hn simp only [Fin.isValue, sub_eq_zero, Finsupp.single_eq_single_iff, zero_ne_one, Subtype.mk.injEq, - SetLike.coe_eq_coe, false_and, AddSubmonoid.mk_eq_zero, ZeroMemClass.coe_eq_zero, - false_or, n] at hn + SetLike.coe_eq_coe, false_and, false_or, n] at hn + repeat rw [AddSubmonoid.mk_eq_zero, ZeroMemClass.coe_eq_zero] at hn exact h.ne_zero 0 hn.2 /-- If `M` and `N` are linearly disjoint, if one of `M` and `N` is flat, then any two commutative diff --git a/Mathlib/LinearAlgebra/LinearIndependent.lean b/Mathlib/LinearAlgebra/LinearIndependent.lean index e6a3d680dc9fc..3a13689ce7686 100644 --- a/Mathlib/LinearAlgebra/LinearIndependent.lean +++ b/Mathlib/LinearAlgebra/LinearIndependent.lean @@ -21,11 +21,11 @@ This file defines linear independence in a module or vector space. It is inspired by Isabelle/HOL's linear algebra, and hence indirectly by HOL Light. -We define `LinearIndependent R v` as `ker (Finsupp.total ι M R v) = ⊥`. Here `Finsupp.total` is the -linear map sending a function `f : ι →₀ R` with finite support to the linear combination of vectors -from `v` with these coefficients. Then we prove that several other statements are equivalent to this -one, including injectivity of `Finsupp.total ι M R v` and some versions with explicitly written -linear combinations. +We define `LinearIndependent R v` as `ker (Finsupp.linearCombination R v) = ⊥`. Here +`Finsupp.linearCombination` is the linear map sending a function `f : ι →₀ R` with finite support to +the linear combination of vectors from `v` with these coefficients. Then we prove that several other +statements are equivalent to this one, including injectivity of `Finsupp.linearCombination R v` and +some versions with explicitly written linear combinations. ## Main definitions All definitions are given for families of vectors, i.e. `v : ι → M` where `M` is the module or @@ -97,7 +97,7 @@ variable (R) (v) /-- `LinearIndependent R v` states the family of vectors `v` is linearly independent over `R`. -/ def LinearIndependent : Prop := - LinearMap.ker (Finsupp.total ι M R v) = ⊥ + LinearMap.ker (Finsupp.linearCombination R v) = ⊥ open Lean PrettyPrinter.Delaborator SubExpr in /-- Delaborator for `LinearIndependent` that suggests pretty printing with type hints @@ -122,7 +122,7 @@ def delabLinearIndependent : Delab := variable {R} {v} theorem linearIndependent_iff : - LinearIndependent R v ↔ ∀ l, Finsupp.total ι M R v l = 0 → l = 0 := by + LinearIndependent R v ↔ ∀ l, Finsupp.linearCombination R v l = 0 → l = 0 := by simp [LinearIndependent, LinearMap.ker_eq_bot'] theorem linearIndependent_iff' : @@ -132,7 +132,7 @@ theorem linearIndependent_iff' : ⟨fun hf s g hg i his => have h := hf (∑ i ∈ s, Finsupp.single i (g i)) <| by - simpa only [map_sum, Finsupp.total_single] using hg + simpa only [map_sum, Finsupp.linearCombination_single] using hg calc g i = (Finsupp.lapply i : (ι →₀ R) →ₗ[R] R) (Finsupp.single i (g i)) := by { rw [Finsupp.lapply_apply, Finsupp.single_eq_same] } @@ -220,7 +220,7 @@ lemma LinearIndependent.pair_iff {x y : M} : linearly independent family. -/ theorem LinearIndependent.comp (h : LinearIndependent R v) (f : ι' → ι) (hf : Injective f) : LinearIndependent R (v ∘ f) := by - rw [linearIndependent_iff, Finsupp.total_comp] + rw [linearIndependent_iff, Finsupp.linearCombination_comp] intro l hl have h_map_domain : ∀ x, (Finsupp.mapDomain f l) (f x) = 0 := by rw [linearIndependent_iff.1 h (Finsupp.mapDomain f l) hl]; simp @@ -244,24 +244,24 @@ disjoint with the submodule spanned by the vectors of `v`, then `f ∘ v` is a l family of vectors. See also `LinearIndependent.map'` for a special case assuming `ker f = ⊥`. -/ theorem LinearIndependent.map (hv : LinearIndependent R v) {f : M →ₗ[R] M'} (hf_inj : Disjoint (span R (range v)) (LinearMap.ker f)) : LinearIndependent R (f ∘ v) := by - rw [disjoint_iff_inf_le, ← Set.image_univ, Finsupp.span_image_eq_map_total, + rw [disjoint_iff_inf_le, ← Set.image_univ, Finsupp.span_image_eq_map_linearCombination, map_inf_eq_map_inf_comap, map_le_iff_le_comap, comap_bot, Finsupp.supported_univ, top_inf_eq] at hf_inj unfold LinearIndependent at hv ⊢ rw [hv, le_bot_iff] at hf_inj haveI : Inhabited M := ⟨0⟩ - rw [Finsupp.total_comp, Finsupp.lmapDomain_total _ _ f, LinearMap.ker_comp, - hf_inj] + rw [Finsupp.linearCombination_comp, Finsupp.lmapDomain_linearCombination _ _ f, + LinearMap.ker_comp, hf_inj] exact fun _ => rfl -/-- If `v` is an injective family of vectors such that `f ∘ v` is linearly independent, then `v` +/-- If `v` is an injective family of vectors such that `f ∘ v` is linearly independent, then `v` spans a submodule disjoint from the kernel of `f` -/ theorem Submodule.range_ker_disjoint {f : M →ₗ[R] M'} (hv : LinearIndependent R (f ∘ v)) : Disjoint (span R (range v)) (LinearMap.ker f) := by - rw [LinearIndependent, Finsupp.total_comp, Finsupp.lmapDomain_total R _ f (fun _ ↦ rfl), - LinearMap.ker_comp] at hv - rw [disjoint_iff_inf_le, ← Set.image_univ, Finsupp.span_image_eq_map_total, + rw [LinearIndependent, Finsupp.linearCombination_comp, + Finsupp.lmapDomain_linearCombination R _ f (fun _ ↦ rfl), LinearMap.ker_comp] at hv + rw [disjoint_iff_inf_le, ← Set.image_univ, Finsupp.span_image_eq_map_linearCombination, map_inf_eq_map_inf_comap, hv, inf_bot_eq, map_bot] /-- An injective linear map sends linearly independent families of vectors to linearly independent @@ -406,8 +406,8 @@ section Subtype theorem linearIndependent_comp_subtype {s : Set ι} : LinearIndependent R (v ∘ (↑) : s → M) ↔ - ∀ l ∈ Finsupp.supported R R s, (Finsupp.total ι M R v) l = 0 → l = 0 := by - simp only [linearIndependent_iff, (· ∘ ·), Finsupp.mem_supported, Finsupp.total_apply, + ∀ l ∈ Finsupp.supported R R s, (Finsupp.linearCombination R v) l = 0 → l = 0 := by + simp only [linearIndependent_iff, (· ∘ ·), Finsupp.mem_supported, Finsupp.linearCombination_apply, Set.subset_def, Finset.mem_coe] constructor · intro h l hl₁ hl₂ @@ -423,10 +423,10 @@ theorem linearIndependent_comp_subtype {s : Set ι} : theorem linearDependent_comp_subtype' {s : Set ι} : ¬LinearIndependent R (v ∘ (↑) : s → M) ↔ - ∃ f : ι →₀ R, f ∈ Finsupp.supported R R s ∧ Finsupp.total ι M R v f = 0 ∧ f ≠ 0 := by + ∃ f : ι →₀ R, f ∈ Finsupp.supported R R s ∧ Finsupp.linearCombination R v f = 0 ∧ f ≠ 0 := by simp [linearIndependent_comp_subtype, and_left_comm] -/-- A version of `linearDependent_comp_subtype'` with `Finsupp.total` unfolded. -/ +/-- A version of `linearDependent_comp_subtype'` with `Finsupp.linearCombination` unfolded. -/ theorem linearDependent_comp_subtype {s : Set ι} : ¬LinearIndependent R (v ∘ (↑) : s → M) ↔ ∃ f : ι →₀ R, f ∈ Finsupp.supported R R s ∧ ∑ i ∈ f.support, f i • v i = 0 ∧ f ≠ 0 := @@ -434,25 +434,28 @@ theorem linearDependent_comp_subtype {s : Set ι} : theorem linearIndependent_subtype {s : Set M} : LinearIndependent R (fun x => x : s → M) ↔ - ∀ l ∈ Finsupp.supported R R s, (Finsupp.total M M R id) l = 0 → l = 0 := by + ∀ l ∈ Finsupp.supported R R s, (Finsupp.linearCombination R id) l = 0 → l = 0 := by apply linearIndependent_comp_subtype (v := id) theorem linearIndependent_comp_subtype_disjoint {s : Set ι} : LinearIndependent R (v ∘ (↑) : s → M) ↔ - Disjoint (Finsupp.supported R R s) (LinearMap.ker <| Finsupp.total ι M R v) := by + Disjoint (Finsupp.supported R R s) (LinearMap.ker <| Finsupp.linearCombination R v) := by rw [linearIndependent_comp_subtype, LinearMap.disjoint_ker] theorem linearIndependent_subtype_disjoint {s : Set M} : LinearIndependent R (fun x => x : s → M) ↔ - Disjoint (Finsupp.supported R R s) (LinearMap.ker <| Finsupp.total M M R id) := by + Disjoint (Finsupp.supported R R s) (LinearMap.ker <| Finsupp.linearCombination R id) := by apply linearIndependent_comp_subtype_disjoint (v := id) -theorem linearIndependent_iff_totalOn {s : Set M} : +theorem linearIndependent_iff_linearCombinationOn {s : Set M} : LinearIndependent R (fun x => x : s → M) ↔ - (LinearMap.ker <| Finsupp.totalOn M M R id s) = ⊥ := by - rw [Finsupp.totalOn, LinearMap.ker, LinearMap.comap_codRestrict, Submodule.map_bot, comap_bot, - LinearMap.ker_comp, linearIndependent_subtype_disjoint, disjoint_iff_inf_le, ← - map_comap_subtype, map_le_iff_le_comap, comap_bot, ker_subtype, le_bot_iff] + (LinearMap.ker <| Finsupp.linearCombinationOn M M R id s) = ⊥ := by + rw [Finsupp.linearCombinationOn, LinearMap.ker, LinearMap.comap_codRestrict, Submodule.map_bot, + comap_bot, LinearMap.ker_comp, linearIndependent_subtype_disjoint, disjoint_iff_inf_le, + ← map_comap_subtype, map_le_iff_le_comap, comap_bot, ker_subtype, le_bot_iff] + +@[deprecated (since := "2024-08-29")] alias linearIndependent_iff_totalOn := + linearIndependent_iff_linearCombinationOn theorem LinearIndependent.restrict_of_comp_subtype {s : Set ι} (hs : LinearIndependent R (v ∘ (↑) : s → M)) : LinearIndependent R (s.restrict v) := @@ -515,18 +518,26 @@ variable [Ring R] [AddCommGroup M] [AddCommGroup M'] [AddCommGroup M''] variable [Module R M] [Module R M'] [Module R M''] variable {a b : R} {x y : M} -theorem linearIndependent_iff_injective_total : - LinearIndependent R v ↔ Function.Injective (Finsupp.total ι M R v) := +theorem linearIndependent_iff_injective_linearCombination : + LinearIndependent R v ↔ Function.Injective (Finsupp.linearCombination R v) := linearIndependent_iff.trans - (injective_iff_map_eq_zero (Finsupp.total ι M R v).toAddMonoidHom).symm + (injective_iff_map_eq_zero (Finsupp.linearCombination R v).toAddMonoidHom).symm + +@[deprecated (since := "2024-08-29")] alias linearIndependent_iff_injective_total := + linearIndependent_iff_injective_linearCombination + +alias ⟨LinearIndependent.injective_linearCombination, _⟩ := + + linearIndependent_iff_injective_linearCombination -alias ⟨LinearIndependent.injective_total, _⟩ := linearIndependent_iff_injective_total +@[deprecated (since := "2024-08-29")] alias LinearIndependent.injective_total := + LinearIndependent.injective_linearCombination theorem LinearIndependent.injective [Nontrivial R] (hv : LinearIndependent R v) : Injective v := by intro i j hij let l : ι →₀ R := Finsupp.single i (1 : R) - Finsupp.single j 1 - have h_total : Finsupp.total ι M R v l = 0 := by - simp_rw [l, LinearMap.map_sub, Finsupp.total_apply] + have h_total : Finsupp.linearCombination R v l = 0 := by + simp_rw [l, LinearMap.map_sub, Finsupp.linearCombination_apply] simp [hij] have h_single_eq : Finsupp.single i (1 : R) = Finsupp.single j 1 := by rw [linearIndependent_iff] at hv @@ -657,8 +668,8 @@ theorem LinearIndependent.eq_of_smul_apply_eq_smul_apply {M : Type*} [AddCommGro {v : ι → M} (li : LinearIndependent R v) (c d : R) (i j : ι) (hc : c ≠ 0) (h : c • v i = d • v j) : i = j := by let l : ι →₀ R := Finsupp.single i c - Finsupp.single j d - have h_total : Finsupp.total ι M R v l = 0 := by - simp_rw [l, LinearMap.map_sub, Finsupp.total_apply] + have h_total : Finsupp.linearCombination R v l = 0 := by + simp_rw [l, LinearMap.map_sub, Finsupp.linearCombination_apply] simp [h] have h_single_eq : Finsupp.single i c = Finsupp.single j d := by rw [linearIndependent_iff] at li @@ -673,9 +684,9 @@ section Subtype theorem LinearIndependent.disjoint_span_image (hv : LinearIndependent R v) {s t : Set ι} (hs : Disjoint s t) : Disjoint (Submodule.span R <| v '' s) (Submodule.span R <| v '' t) := by - simp only [disjoint_def, Finsupp.mem_span_image_iff_total] + simp only [disjoint_def, Finsupp.mem_span_image_iff_linearCombination] rintro _ ⟨l₁, hl₁, rfl⟩ ⟨l₂, hl₂, H⟩ - rw [hv.injective_total.eq_iff] at H; subst l₂ + rw [hv.injective_linearCombination.eq_iff] at H; subst l₂ have : l₁ = 0 := Submodule.disjoint_def.mp (Finsupp.disjoint_supported_supported hs) _ hl₁ hl₂ simp [this] @@ -689,16 +700,20 @@ theorem LinearIndependent.not_mem_span_image [Nontrivial R] (hv : LinearIndepend refine disjoint_def.1 (hv.disjoint_span_image ?_) (v x) h' w simpa using h -theorem LinearIndependent.total_ne_of_not_mem_support [Nontrivial R] (hv : LinearIndependent R v) - {x : ι} (f : ι →₀ R) (h : x ∉ f.support) : Finsupp.total ι M R v f ≠ v x := by +theorem LinearIndependent.linearCombination_ne_of_not_mem_support [Nontrivial R] + (hv : LinearIndependent R v) {x : ι} (f : ι →₀ R) (h : x ∉ f.support) : + Finsupp.linearCombination R v f ≠ v x := by replace h : x ∉ (f.support : Set ι) := h have p := hv.not_mem_span_image h intro w rw [← w] at p - rw [Finsupp.span_image_eq_map_total] at p + rw [Finsupp.span_image_eq_map_linearCombination] at p simp only [not_exists, not_and, mem_map] at p -- Porting note: `mem_map` isn't currently triggered exact p f (f.mem_supported_support R) rfl +@[deprecated (since := "2024-08-29")] alias LinearIndependent.total_ne_of_not_mem_support := + LinearIndependent.linearCombination_ne_of_not_mem_support + theorem linearIndependent_sum {v : ι ⊕ ι' → M} : LinearIndependent R v ↔ LinearIndependent R (v ∘ Sum.inl) ∧ @@ -801,41 +816,54 @@ variable (hv : LinearIndependent R v) /-- Canonical isomorphism between linear combinations and the span of linearly independent vectors. -/ @[simps (config := { rhsMd := default }) symm_apply] -def LinearIndependent.totalEquiv (hv : LinearIndependent R v) : +def LinearIndependent.linearCombinationEquiv (hv : LinearIndependent R v) : (ι →₀ R) ≃ₗ[R] span R (range v) := by - apply LinearEquiv.ofBijective (LinearMap.codRestrict (span R (range v)) (Finsupp.total ι M R v) _) + apply LinearEquiv.ofBijective (LinearMap.codRestrict (span R (range v)) + (Finsupp.linearCombination R v) _) constructor · rw [← LinearMap.ker_eq_bot, LinearMap.ker_codRestrict] · apply hv · intro l - rw [← Finsupp.range_total] + rw [← Finsupp.range_linearCombination] rw [LinearMap.mem_range] apply mem_range_self l · rw [← LinearMap.range_eq_top, LinearMap.range_eq_map, LinearMap.map_codRestrict, ← LinearMap.range_le_iff_comap, range_subtype, Submodule.map_top] - rw [Finsupp.range_total] + rw [Finsupp.range_linearCombination] + +@[deprecated (since := "2024-08-29")] noncomputable alias LinearIndependent.totalEquiv := + LinearIndependent.linearCombinationEquiv -- Porting note: The original theorem generated by `simps` was -- different from the theorem on Lean 3, and not simp-normal form. @[simp] -theorem LinearIndependent.totalEquiv_apply_coe (hv : LinearIndependent R v) (l : ι →₀ R) : - hv.totalEquiv l = Finsupp.total ι M R v l := rfl +theorem LinearIndependent.linearCombinationEquiv_apply_coe (hv : LinearIndependent R v) + (l : ι →₀ R) : hv.linearCombinationEquiv l = Finsupp.linearCombination R v l := rfl +@[deprecated (since := "2024-08-29")] alias LinearIndependent.totalEquiv_apply_coe := + LinearIndependent.linearCombinationEquiv_apply_coe /-- Linear combination representing a vector in the span of linearly independent vectors. Given a family of linearly independent vectors, we can represent any vector in their span as a linear combination of these vectors. These are provided by this linear map. -It is simply one direction of `LinearIndependent.total_equiv`. -/ +It is simply one direction of `LinearIndependent.linearCombinationEquiv`. -/ def LinearIndependent.repr (hv : LinearIndependent R v) : span R (range v) →ₗ[R] ι →₀ R := - hv.totalEquiv.symm + hv.linearCombinationEquiv.symm @[simp] -theorem LinearIndependent.total_repr (x) : Finsupp.total ι M R v (hv.repr x) = x := - Subtype.ext_iff.1 (LinearEquiv.apply_symm_apply hv.totalEquiv x) +theorem LinearIndependent.linearCombination_repr (x) : + Finsupp.linearCombination R v (hv.repr x) = x := + Subtype.ext_iff.1 (LinearEquiv.apply_symm_apply hv.linearCombinationEquiv x) + +@[deprecated (since := "2024-08-29")] alias LinearIndependent.total_repr := + LinearIndependent.linearCombination_repr + +theorem LinearIndependent.linearCombination_comp_repr : + (Finsupp.linearCombination R v).comp hv.repr = Submodule.subtype _ := + LinearMap.ext <| hv.linearCombination_repr -theorem LinearIndependent.total_comp_repr : - (Finsupp.total ι M R v).comp hv.repr = Submodule.subtype _ := - LinearMap.ext <| hv.total_repr +@[deprecated (since := "2024-08-29")] alias LinearIndependent.total_comp_repr := + LinearIndependent.linearCombination_comp_repr theorem LinearIndependent.repr_ker : LinearMap.ker hv.repr = ⊥ := by rw [LinearIndependent.repr, LinearEquiv.ker] @@ -844,22 +872,22 @@ theorem LinearIndependent.repr_range : LinearMap.range hv.repr = ⊤ := by rw [LinearIndependent.repr, LinearEquiv.range] theorem LinearIndependent.repr_eq {l : ι →₀ R} {x : span R (range v)} - (eq : Finsupp.total ι M R v l = ↑x) : hv.repr x = l := by + (eq : Finsupp.linearCombination R v l = ↑x) : hv.repr x = l := by have : - ↑((LinearIndependent.totalEquiv hv : (ι →₀ R) →ₗ[R] span R (range v)) l) = - Finsupp.total ι M R v l := + ↑((LinearIndependent.linearCombinationEquiv hv : (ι →₀ R) →ₗ[R] span R (range v)) l) = + Finsupp.linearCombination R v l := rfl - have : (LinearIndependent.totalEquiv hv : (ι →₀ R) →ₗ[R] span R (range v)) l = x := by + have : (LinearIndependent.linearCombinationEquiv hv : (ι →₀ R) →ₗ[R] span R (range v)) l = x := by rw [eq] at this exact Subtype.ext_iff.2 this - rw [← LinearEquiv.symm_apply_apply hv.totalEquiv l] + rw [← LinearEquiv.symm_apply_apply hv.linearCombinationEquiv l] rw [← this] rfl theorem LinearIndependent.repr_eq_single (i) (x : span R (range v)) (hx : ↑x = v i) : hv.repr x = Finsupp.single i 1 := by apply hv.repr_eq - simp [Finsupp.total_single, hx] + simp [Finsupp.linearCombination_single, hx] theorem LinearIndependent.span_repr_eq [Nontrivial R] (x) : Span.repr R (Set.range v) x = @@ -867,17 +895,18 @@ theorem LinearIndependent.span_repr_eq [Nontrivial R] (x) : have p : (Span.repr R (Set.range v) x).equivMapDomain (Equiv.ofInjective _ hv.injective).symm = hv.repr x := by - apply (LinearIndependent.totalEquiv hv).injective + apply (LinearIndependent.linearCombinationEquiv hv).injective ext - simp only [LinearIndependent.totalEquiv_apply_coe, Equiv.self_comp_ofInjective_symm, - LinearIndependent.total_repr, Finsupp.total_equivMapDomain, Span.finsupp_total_repr] + simp only [LinearIndependent.linearCombinationEquiv_apply_coe, Equiv.self_comp_ofInjective_symm, + LinearIndependent.linearCombination_repr, Finsupp.linearCombination_equivMapDomain, + Span.finsupp_linearCombination_repr] ext ⟨_, ⟨i, rfl⟩⟩ simp [← p] theorem linearIndependent_iff_not_smul_mem_span : LinearIndependent R v ↔ ∀ (i : ι) (a : R), a • v i ∈ span R (v '' (univ \ {i})) → a = 0 := ⟨fun hv i a ha => by - rw [Finsupp.span_image_eq_map_total, mem_map] at ha + rw [Finsupp.span_image_eq_map_linearCombination, mem_map] at ha rcases ha with ⟨l, hl, e⟩ rw [sub_eq_zero.1 (linearIndependent_iff.1 hv (l - Finsupp.single i a) (by simp [e]))] at hl by_contra hn @@ -886,7 +915,7 @@ theorem linearIndependent_iff_not_smul_mem_span : ext i; simp only [Finsupp.zero_apply] by_contra hn refine hn (H i _ ?_) - refine (Finsupp.mem_span_image_iff_total R).2 ⟨Finsupp.single i (l i) - l, ?_, ?_⟩ + refine (Finsupp.mem_span_image_iff_linearCombination R).2 ⟨Finsupp.single i (l i) - l, ?_, ?_⟩ · rw [Finsupp.mem_supported'] intro j hj have hij : j = i := @@ -979,13 +1008,14 @@ theorem surjective_of_linearIndependent_of_span [Nontrivial R] (hv : LinearIndep intro i let repr : (span R (range (v ∘ f)) : Type _) → ι' →₀ R := (hv.comp f f.injective).repr let l := (repr ⟨v i, hss (mem_range_self i)⟩).mapDomain f - have h_total_l : Finsupp.total ι M R v l = v i := by + have h_total_l : Finsupp.linearCombination R v l = v i := by dsimp only [l] - rw [Finsupp.total_mapDomain] - rw [(hv.comp f f.injective).total_repr] + rw [Finsupp.linearCombination_mapDomain] + rw [(hv.comp f f.injective).linearCombination_repr] -- Porting note: `rfl` isn't necessary. - have h_total_eq : (Finsupp.total ι M R v) l = (Finsupp.total ι M R v) (Finsupp.single i 1) := by - rw [h_total_l, Finsupp.total_single, one_smul] + have h_total_eq : Finsupp.linearCombination R v l = Finsupp.linearCombination R v + (Finsupp.single i 1) := by + rw [h_total_l, Finsupp.linearCombination_single, one_smul] have l_eq : l = _ := LinearMap.ker_eq_bot.1 hv h_total_eq dsimp only [l] at l_eq rw [← Finsupp.embDomain_eq_mapDomain] at l_eq @@ -1000,7 +1030,7 @@ theorem eq_of_linearIndependent_of_span_subtype [Nontrivial R] {s t : Set M} ⟨fun x => ⟨x.1, h x.2⟩, fun a b hab => Subtype.coe_injective (Subtype.mk.inj hab)⟩ have h_surj : Surjective f := by apply surjective_of_linearIndependent_of_span hs f _ - convert hst <;> simp [f, comp] + convert hst <;> simp [f, comp_def] show s = t apply Subset.antisymm _ h intro x hx @@ -1164,7 +1194,7 @@ variable {v : ι → M} {s t : Set M} {x y z : M} theorem linearIndependent_unique_iff (v : ι → M) [Unique ι] : LinearIndependent R v ↔ v default ≠ 0 := by - simp only [linearIndependent_iff, Finsupp.total_unique, smul_eq_zero] + simp only [linearIndependent_iff, Finsupp.linearCombination_unique, smul_eq_zero] refine ⟨fun h hv => ?_, fun hv l hl => Finsupp.unique_ext <| hl.resolve_right hv⟩ have := h (Finsupp.single default 1) (Or.inr hv) exact one_ne_zero (Finsupp.single_eq_zero.1 this) @@ -1250,7 +1280,7 @@ theorem linearIndependent_insert' {ι} {s : Set ι} {a : ι} {f : ι → V} (has linearIndependent_option] -- Porting note: `simp [(· ∘ ·), range_comp f]` → `simp [(· ∘ ·)]; erw [range_comp f ..]; simp` -- https://github.com/leanprover-community/mathlib4/issues/5164 - simp only [(· ∘ ·)] + simp only [Function.comp_def] erw [range_comp f ((↑) : s → ι)] simp diff --git a/Mathlib/LinearAlgebra/Matrix/Adjugate.lean b/Mathlib/LinearAlgebra/Matrix/Adjugate.lean index 86afb594ac8cb..b814a9748abac 100644 --- a/Mathlib/LinearAlgebra/Matrix/Adjugate.lean +++ b/Mathlib/LinearAlgebra/Matrix/Adjugate.lean @@ -158,7 +158,7 @@ theorem cramer_submatrix_equiv (A : Matrix m m α) (e : n ≃ m) (b : n → α) cramer (A.submatrix e e) b = cramer A (b ∘ e.symm) ∘ e := by ext i simp_rw [Function.comp_apply, cramer_apply, updateColumn_submatrix_equiv, - det_submatrix_equiv_self e, Function.comp] + det_submatrix_equiv_self e, Function.comp_def] theorem cramer_reindex (e : m ≃ n) (A : Matrix m m α) (b : n → α) : cramer (reindex e e A) b = cramer A (b ∘ e) ∘ e.symm := diff --git a/Mathlib/LinearAlgebra/Matrix/Charpoly/Coeff.lean b/Mathlib/LinearAlgebra/Matrix/Charpoly/Coeff.lean index 3b0529e1973d4..1fcd2932b0cee 100644 --- a/Mathlib/LinearAlgebra/Matrix/Charpoly/Coeff.lean +++ b/Mathlib/LinearAlgebra/Matrix/Charpoly/Coeff.lean @@ -150,7 +150,7 @@ theorem matPolyEquiv_symm_map_eval (M : (Matrix n n R)[X]) (r : R) : DFunLike.congr_fun this M ext : 1 · ext M : 1 - simp [Function.comp] + simp [Function.comp_def] · simp [smul_eq_diagonal_mul] theorem matPolyEquiv_eval_eq_map (M : Matrix n n R[X]) (r : R) : @@ -298,7 +298,6 @@ end Ideal section reverse -open Polynomial open LaurentPolynomial hiding C /-- The reverse of the characteristic polynomial of a matrix. diff --git a/Mathlib/LinearAlgebra/Matrix/Charpoly/LinearMap.lean b/Mathlib/LinearAlgebra/Matrix/Charpoly/LinearMap.lean index 45a4644bc6fc5..73a35fa98fa85 100644 --- a/Mathlib/LinearAlgebra/Matrix/Charpoly/LinearMap.lean +++ b/Mathlib/LinearAlgebra/Matrix/Charpoly/LinearMap.lean @@ -28,41 +28,41 @@ variable (b : ι → M) open Polynomial Matrix /-- The composition of a matrix (as an endomorphism of `ι → R`) with the projection -`(ι → R) →ₗ[R] M`. -/ +`(ι → R) →ₗ[R] M`. -/ def PiToModule.fromMatrix [DecidableEq ι] : Matrix ι ι R →ₗ[R] (ι → R) →ₗ[R] M := - (LinearMap.llcomp R _ _ _ (Fintype.total R R b)).comp algEquivMatrix'.symm.toLinearMap + (LinearMap.llcomp R _ _ _ (Fintype.linearCombination R R b)).comp algEquivMatrix'.symm.toLinearMap theorem PiToModule.fromMatrix_apply [DecidableEq ι] (A : Matrix ι ι R) (w : ι → R) : - PiToModule.fromMatrix R b A w = Fintype.total R R b (A *ᵥ w) := + PiToModule.fromMatrix R b A w = Fintype.linearCombination R R b (A *ᵥ w) := rfl theorem PiToModule.fromMatrix_apply_single_one [DecidableEq ι] (A : Matrix ι ι R) (j : ι) : PiToModule.fromMatrix R b A (Pi.single j 1) = ∑ i : ι, A i j • b i := by - rw [PiToModule.fromMatrix_apply, Fintype.total_apply, Matrix.mulVec_single] + rw [PiToModule.fromMatrix_apply, Fintype.linearCombination_apply, Matrix.mulVec_single] simp_rw [mul_one] /-- The endomorphisms of `M` acts on `(ι → R) →ₗ[R] M`, and takes the projection to a `(ι → R) →ₗ[R] M`. -/ def PiToModule.fromEnd : Module.End R M →ₗ[R] (ι → R) →ₗ[R] M := - LinearMap.lcomp _ _ (Fintype.total R R b) + LinearMap.lcomp _ _ (Fintype.linearCombination R R b) theorem PiToModule.fromEnd_apply (f : Module.End R M) (w : ι → R) : - PiToModule.fromEnd R b f w = f (Fintype.total R R b w) := + PiToModule.fromEnd R b f w = f (Fintype.linearCombination R R b w) := rfl theorem PiToModule.fromEnd_apply_single_one [DecidableEq ι] (f : Module.End R M) (i : ι) : PiToModule.fromEnd R b f (Pi.single i 1) = f (b i) := by rw [PiToModule.fromEnd_apply] congr - convert Fintype.total_apply_single (S := R) R b i (1 : R) + convert Fintype.linearCombination_apply_single (S := R) R b i (1 : R) rw [one_smul] theorem PiToModule.fromEnd_injective (hb : Submodule.span R (Set.range b) = ⊤) : Function.Injective (PiToModule.fromEnd R b) := by intro x y e ext m - obtain ⟨m, rfl⟩ : m ∈ LinearMap.range (Fintype.total R R b) := by - rw [(Fintype.range_total R b).trans hb] + obtain ⟨m, rfl⟩ : m ∈ LinearMap.range (Fintype.linearCombination R R b) := by + rw [(Fintype.range_linearCombination R b).trans hb] exact Submodule.mem_top exact (LinearMap.congr_fun e m : _) @@ -71,18 +71,19 @@ section variable {R} [DecidableEq ι] /-- We say that a matrix represents an endomorphism of `M` if the matrix acting on `ι → R` is -equal to `f` via the projection `(ι → R) →ₗ[R] M` given by a fixed (spanning) set. -/ +equal to `f` via the projection `(ι → R) →ₗ[R] M` given by a fixed (spanning) set. -/ def Matrix.Represents (A : Matrix ι ι R) (f : Module.End R M) : Prop := PiToModule.fromMatrix R b A = PiToModule.fromEnd R b f variable {b} theorem Matrix.Represents.congr_fun {A : Matrix ι ι R} {f : Module.End R M} (h : A.Represents b f) - (x) : Fintype.total R R b (A *ᵥ x) = f (Fintype.total R R b x) := + (x) : Fintype.linearCombination R R b (A *ᵥ x) = f (Fintype.linearCombination R R b x) := LinearMap.congr_fun h x theorem Matrix.represents_iff {A : Matrix ι ι R} {f : Module.End R M} : - A.Represents b f ↔ ∀ x, Fintype.total R R b (A *ᵥ x) = f (Fintype.total R R b x) := + A.Represents b f ↔ + ∀ x, Fintype.linearCombination R R b (A *ᵥ x) = f (Fintype.linearCombination R R b x) := ⟨fun e x => e.congr_fun x, fun H => LinearMap.ext fun x => H x⟩ theorem Matrix.represents_iff' {A : Matrix ι ι R} {f : Module.End R M} : diff --git a/Mathlib/LinearAlgebra/Matrix/Charpoly/Univ.lean b/Mathlib/LinearAlgebra/Matrix/Charpoly/Univ.lean index 060c707fa9548..4f8c88911dcd1 100644 --- a/Mathlib/LinearAlgebra/Matrix/Charpoly/Univ.lean +++ b/Mathlib/LinearAlgebra/Matrix/Charpoly/Univ.lean @@ -17,7 +17,7 @@ and hence has coefficients that are multivariate polynomials. It is universal in the sense that one obtains the characteristic polynomial of a matrix `M` by evaluating the coefficients of `univ` at the entries of `M`. -We use it to show that the coeffients of the characteristic polynomial +We use it to show that the coefficients of the characteristic polynomial of a matrix are homogeneous polynomials in the matrix entries. ## Main results diff --git a/Mathlib/LinearAlgebra/Matrix/Determinant/Basic.lean b/Mathlib/LinearAlgebra/Matrix/Determinant/Basic.lean index bed32a8a62a86..85a32f9416529 100644 --- a/Mathlib/LinearAlgebra/Matrix/Determinant/Basic.lean +++ b/Mathlib/LinearAlgebra/Matrix/Determinant/Basic.lean @@ -760,7 +760,7 @@ theorem det_fin_three (A : Matrix (Fin 3) (Fin 3) R) : A 0 0 * A 1 1 * A 2 2 - A 0 0 * A 1 2 * A 2 1 - A 0 1 * A 1 0 * A 2 2 + A 0 1 * A 1 2 * A 2 0 + A 0 2 * A 1 0 * A 2 1 - A 0 2 * A 1 1 * A 2 0 := by - simp only [det_succ_row_zero, Nat.odd_iff_not_even, submatrix_apply, Fin.succ_zero_eq_one, + 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] diff --git a/Mathlib/LinearAlgebra/Matrix/DotProduct.lean b/Mathlib/LinearAlgebra/Matrix/DotProduct.lean index a549bac8773ce..d943a52a81685 100644 --- a/Mathlib/LinearAlgebra/Matrix/DotProduct.lean +++ b/Mathlib/LinearAlgebra/Matrix/DotProduct.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl, Patrick Massot, Casper Putz, Anne Baanen -/ import Mathlib.Algebra.Ring.Regular -import Mathlib.Algebra.Star.Order +import Mathlib.Algebra.Order.Star.Basic import Mathlib.Data.Matrix.Basic import Mathlib.LinearAlgebra.StdBasis import Mathlib.Algebra.Order.BigOperators.Group.Finset diff --git a/Mathlib/LinearAlgebra/Matrix/GeneralLinearGroup/Card.lean b/Mathlib/LinearAlgebra/Matrix/GeneralLinearGroup/Card.lean index 2e1d5ed83ed2b..8d2b791e900da 100644 --- a/Mathlib/LinearAlgebra/Matrix/GeneralLinearGroup/Card.lean +++ b/Mathlib/LinearAlgebra/Matrix/GeneralLinearGroup/Card.lean @@ -38,8 +38,8 @@ theorem card_linearIndependent {k : ℕ} (hk : k ≤ n) : ∏ i : Fin k, (q ^ n - q ^ i.val) := by rw [Nat.card_eq_fintype_card] induction k with - | zero => simp only [LinearIndependent, Finsupp.total_fin_zero, ker_zero, card_ofSubsingleton, - Finset.univ_eq_empty, Finset.prod_empty] + | zero => simp only [LinearIndependent, Finsupp.linearCombination_fin_zero, ker_zero, + card_ofSubsingleton, Finset.univ_eq_empty, Finset.prod_empty] | succ k ih => have (s : { s : Fin k → V // LinearIndependent K s }) : card ((Submodule.span K (Set.range (s : Fin k → V)))ᶜ : Set (V)) = @@ -64,7 +64,7 @@ local notation "q" => Fintype.card 𝔽 variable (n : ℕ) /-- Equivalence between `GL n F` and `n` vectors of length `n` that are linearly independent. Given -by sending a matrix to its coloumns. -/ +by sending a matrix to its columns. -/ noncomputable def equiv_GL_linearindependent (hn : 0 < n) : GL (Fin n) 𝔽 ≃ { s : Fin n → Fin n → 𝔽 // LinearIndependent 𝔽 s } where toFun M := ⟨transpose M, by diff --git a/Mathlib/LinearAlgebra/Matrix/GeneralLinearGroup/Defs.lean b/Mathlib/LinearAlgebra/Matrix/GeneralLinearGroup/Defs.lean index 301e6932dcf83..50c1c2dfc8bb0 100644 --- a/Mathlib/LinearAlgebra/Matrix/GeneralLinearGroup/Defs.lean +++ b/Mathlib/LinearAlgebra/Matrix/GeneralLinearGroup/Defs.lean @@ -37,7 +37,7 @@ open LinearMap attribute [-instance] SpecialLinearGroup.instCoeFun /-- `GL n R` is the group of `n` by `n` `R`-matrices with unit determinant. -Defined as a subtype of matrices-/ +Defined as a subtype of matrices -/ abbrev GeneralLinearGroup (n : Type u) (R : Type v) [DecidableEq n] [Fintype n] [CommRing R] : Type _ := (Matrix n n R)ˣ @@ -69,7 +69,7 @@ def det : GL n R →* Rˣ where map_one' := Units.ext det_one map_mul' A B := Units.ext <| det_mul _ _ -/-- The `GL n R` and `Matrix.GeneralLinearGroup R n` groups are multiplicatively equivalent-/ +/-- The `GL n R` and `Matrix.GeneralLinearGroup R n` groups are multiplicatively equivalent -/ def toLin : GL n R ≃* LinearMap.GeneralLinearGroup R (n → R) := Units.mapEquiv toLinAlgEquiv'.toMulEquiv diff --git a/Mathlib/LinearAlgebra/Matrix/HermitianFunctionalCalculus.lean b/Mathlib/LinearAlgebra/Matrix/HermitianFunctionalCalculus.lean index aedad97e0580a..336209008ab7e 100644 --- a/Mathlib/LinearAlgebra/Matrix/HermitianFunctionalCalculus.lean +++ b/Mathlib/LinearAlgebra/Matrix/HermitianFunctionalCalculus.lean @@ -76,7 +76,7 @@ noncomputable def cfcAux : C(spectrum ℝ A, ℝ) →⋆ₐ[ℝ] (Matrix n n congr! with i simp commutes' r := by - simp only [Function.comp, algebraMap_apply, smul_eq_mul, mul_one] + simp only [Function.comp_def, algebraMap_apply, smul_eq_mul, mul_one] rw [← mul_one (algebraMap _ _ _), ← unitary.coe_mul_star_self hA.eigenvectorUnitary, ← Algebra.left_comm, unitary.coe_star, mul_assoc] congr! @@ -134,7 +134,7 @@ instance instContinuousFunctionalCalculus : simp only [isSelfAdjoint_iff, cfcAux_apply, mul_assoc, star_mul, star_star] rw [star_eq_conjTranspose, diagonal_conjTranspose] congr! - simp [Pi.star_def, Function.comp] + simp [Pi.star_def, Function.comp_def] predicate_zero := .zero _ instance instUniqueContinuousFunctionalCalculus : @@ -157,7 +157,8 @@ lemma cfc_eq (f : ℝ → ℝ) : cfc f A = hA.cfc f := by have := cfcHom_eq_of_continuous_of_map_id hA' hA.cfcAux hA.closedEmbedding_cfcAux.continuous hA.cfcAux_id rw [cfc_apply f A hA' (by rw [continuousOn_iff_continuous_restrict]; fun_prop), this] - simp only [cfcAux_apply, ContinuousMap.coe_mk, Function.comp, Set.restrict_apply, IsHermitian.cfc] + simp only [cfcAux_apply, ContinuousMap.coe_mk, Function.comp_def, Set.restrict_apply, + IsHermitian.cfc] end IsHermitian end Matrix diff --git a/Mathlib/LinearAlgebra/Matrix/LDL.lean b/Mathlib/LinearAlgebra/Matrix/LDL.lean index 46bbe801bd60b..277c2bddd5c89 100644 --- a/Mathlib/LinearAlgebra/Matrix/LDL.lean +++ b/Mathlib/LinearAlgebra/Matrix/LDL.lean @@ -107,7 +107,7 @@ noncomputable def LDL.lower := (LDL.lowerInv hS)⁻¹ /-- **LDL decomposition**: any positive definite matrix `S` can be -decomposed as `S = LDLᴴ` where `L` is a lower-triangular matrix and `D` is a diagonal matrix. -/ +decomposed as `S = LDLᴴ` where `L` is a lower-triangular matrix and `D` is a diagonal matrix. -/ theorem LDL.lower_conj_diag : LDL.lower hS * LDL.diag hS * (LDL.lower hS)ᴴ = S := by rw [LDL.lower, conjTranspose_nonsing_inv, Matrix.mul_assoc, Matrix.inv_mul_eq_iff_eq_mul_of_invertible (LDL.lowerInv hS), diff --git a/Mathlib/LinearAlgebra/Matrix/PosDef.lean b/Mathlib/LinearAlgebra/Matrix/PosDef.lean index 5aee7b5572d59..941af97a89e99 100644 --- a/Mathlib/LinearAlgebra/Matrix/PosDef.lean +++ b/Mathlib/LinearAlgebra/Matrix/PosDef.lean @@ -18,7 +18,7 @@ of quadratic forms. Most results require `𝕜 = ℝ` or `ℂ`. * `Matrix.PosSemidef` : a matrix `M : Matrix n n 𝕜` is positive semidefinite if it is hermitian and `xᴴMx` is nonnegative for all `x`. -## Main results +## Main results * `Matrix.posSemidef_iff_eq_transpose_mul_self` : a matrix `M : Matrix n n 𝕜` is positive semidefinite iff it has the form `Bᴴ * B` for some `B`. @@ -263,7 +263,7 @@ theorem posSemidef_submatrix_equiv {M : Matrix n n R} (e : m ≃ n) : (M.submatrix e e).PosSemidef ↔ M.PosSemidef := ⟨fun h => by simpa using h.submatrix e.symm, fun h => h.submatrix _⟩ -/-- The conjugate transpose of a matrix mulitplied by the matrix is positive semidefinite -/ +/-- The conjugate transpose of a matrix multiplied by the matrix is positive semidefinite -/ theorem posSemidef_conjTranspose_mul_self [StarOrderedRing R] (A : Matrix m n R) : PosSemidef (Aᴴ * A) := by refine ⟨isHermitian_transpose_mul_self _, fun x => ?_⟩ diff --git a/Mathlib/LinearAlgebra/Matrix/SchurComplement.lean b/Mathlib/LinearAlgebra/Matrix/SchurComplement.lean index 03ef3530c8616..cdee1596abde6 100644 --- a/Mathlib/LinearAlgebra/Matrix/SchurComplement.lean +++ b/Mathlib/LinearAlgebra/Matrix/SchurComplement.lean @@ -27,8 +27,8 @@ Compare with `Matrix.invertibleOfFromBlocks₁₁Invertible`. block triangular matrix. * `Matrix.det_one_add_mul_comm`: the **Weinstein–Aronszajn identity**. * `Matrix.PosSemidef.fromBlocks₁₁` and `Matrix.PosSemidef.fromBlocks₂₂`: If a matrix `A` is - positive definite, then `[A B; Bᴴ D]` is postive semidefinite if and only if `D - Bᴴ A⁻¹ B` is - postive semidefinite. + positive definite, then `[A B; Bᴴ D]` is positive semidefinite if and only if `D - Bᴴ A⁻¹ B` is + positive semidefinite. -/ @@ -224,7 +224,7 @@ end Triangular section Block -/-! #### General 2×2 block matrices-/ +/-! #### General 2×2 block matrices -/ /-- A block matrix is invertible if the bottom right corner and the corresponding schur complement diff --git a/Mathlib/LinearAlgebra/Matrix/SesquilinearForm.lean b/Mathlib/LinearAlgebra/Matrix/SesquilinearForm.lean index 44fdd5263d583..13e2bba24b39b 100644 --- a/Mathlib/LinearAlgebra/Matrix/SesquilinearForm.lean +++ b/Mathlib/LinearAlgebra/Matrix/SesquilinearForm.lean @@ -485,7 +485,7 @@ end end ToMatrix -/-! ### Adjoint pairs-/ +/-! ### Adjoint pairs -/ section MatrixAdjoints @@ -623,7 +623,7 @@ end MatrixAdjoints namespace LinearMap -/-! ### Nondegenerate bilinear forms-/ +/-! ### Nondegenerate bilinear forms -/ section Det diff --git a/Mathlib/LinearAlgebra/Matrix/SpecialLinearGroup.lean b/Mathlib/LinearAlgebra/Matrix/SpecialLinearGroup.lean index bf7e0f5c040f9..abb3fa721cfad 100644 --- a/Mathlib/LinearAlgebra/Matrix/SpecialLinearGroup.lean +++ b/Mathlib/LinearAlgebra/Matrix/SpecialLinearGroup.lean @@ -285,7 +285,7 @@ def center_equiv_rootsOfUnity' (i : n) : map_mul' A B := by dsimp ext - simp only [Submonoid.coe_mul, coe_mul, rootsOfUnity.val_mkOfPowEq_coe, Units.val_mul] + simp only [rootsOfUnity.val_mkOfPowEq_coe, Subgroup.coe_mul, Units.val_mul] rw [← scalar_eq_coe_self_center A i, ← scalar_eq_coe_self_center B i] simp diff --git a/Mathlib/LinearAlgebra/Matrix/Spectrum.lean b/Mathlib/LinearAlgebra/Matrix/Spectrum.lean index d69134ff4820b..e20e0a672cfc3 100644 --- a/Mathlib/LinearAlgebra/Matrix/Spectrum.lean +++ b/Mathlib/LinearAlgebra/Matrix/Spectrum.lean @@ -17,7 +17,7 @@ the spectral theorem for linear maps (`LinearMap.IsSymmetric.eigenvectorBasis_ap ## Tags -spectral theorem, diagonalization theorem-/ +spectral theorem, diagonalization theorem -/ namespace Matrix diff --git a/Mathlib/LinearAlgebra/Matrix/ToLin.lean b/Mathlib/LinearAlgebra/Matrix/ToLin.lean index f7a4aba7c8c89..803a75b7be149 100644 --- a/Mathlib/LinearAlgebra/Matrix/ToLin.lean +++ b/Mathlib/LinearAlgebra/Matrix/ToLin.lean @@ -942,7 +942,7 @@ If `M₁` and `M₂` are modules with basis `b₁` and `b₂` respectively index by finite types `ι₁` and `ι₂`, then `Basis.linearMap b₁ b₂` is the basis of `M₁ →ₗ[R] M₂` indexed by `ι₂ × ι₁` where `(i, j)` indexes the linear map that sends `b j` to `b i` -and sends all other basis vectors to `0`. -/ +and sends all other basis vectors to `0`. -/ @[simps! (config := .lemmasOnly) repr_apply repr_symm_apply] noncomputable def linearMap (b₁ : Basis ι₁ R M₁) (b₂ : Basis ι₂ R M₂) : @@ -968,7 +968,7 @@ induced by a basis of the module. If `M` is a module with basis `b` indexed by a finite type `ι`, then `Basis.end b` is the basis of `Module.End R M` indexed by `ι × ι` where `(i, j)` indexes the linear map that sends `b j` to `b i` -and sends all other basis vectors to `0`. -/ +and sends all other basis vectors to `0`. -/ @[simps! (config := .lemmasOnly) repr_apply repr_symm_apply] noncomputable abbrev _root_.Basis.end (b : Basis ι R M) : Basis (ι × ι) R (Module.End R M) := diff --git a/Mathlib/LinearAlgebra/Matrix/Transvection.lean b/Mathlib/LinearAlgebra/Matrix/Transvection.lean index 24c27ffba8831..c360c3c4d9f0f 100644 --- a/Mathlib/LinearAlgebra/Matrix/Transvection.lean +++ b/Mathlib/LinearAlgebra/Matrix/Transvection.lean @@ -351,7 +351,7 @@ theorem listTransvecCol_get (i : Fin (listTransvecCol M).length) : (listTransvecCol M).get i = letI i' := Fin.cast (length_listTransvecCol M) i transvection (inl i') (inr unit) <| -M (inl i') (inr unit) / M (inr unit) (inr unit) := - listTransvecCol_getElem .. + listTransvecCol_getElem _ i.isLt @[simp] theorem length_listTransvecRow : (listTransvecRow M).length = r := by simp [listTransvecRow] @@ -367,7 +367,7 @@ theorem listTransvecRow_get (i : Fin (listTransvecRow M).length) : (listTransvecRow M).get i = letI i' := Fin.cast (length_listTransvecRow M) i transvection (inr unit) (inl i') <| -M (inr unit) (inl i') / M (inr unit) (inr unit) := - listTransvecRow_getElem .. + listTransvecRow_getElem _ i.isLt /-- Multiplying by some of the matrices in `listTransvecCol M` does not change the last row. -/ theorem listTransvecCol_mul_last_row_drop (i : Fin r ⊕ Unit) {k : ℕ} (hk : k ≤ r) : @@ -447,7 +447,7 @@ theorem mul_listTransvecRow_last_col_take (i : Fin r ⊕ Unit) {k : ℕ} (hk : k simp only [List.take_succ, ← Matrix.mul_assoc, this, List.prod_append, Matrix.mul_one, List.prod_cons, List.prod_nil, Option.toList_some] rw [mul_transvection_apply_of_ne, IH hkr.le] - simp only [Ne, not_false_iff] + simp only [Ne, not_false_iff, reduceCtorEq] /-- Multiplying by all the matrices in `listTransvecRow M` does not change the last column. -/ theorem mul_listTransvecRow_last_col (i : Fin r ⊕ Unit) : @@ -549,8 +549,8 @@ theorem exists_isTwoBlockDiagonal_of_ne_zero (hM : M (inr unit) (inr unit) ≠ 0 List.ofFn fun i : Fin r => ⟨inr unit, inl i, by simp, -M (inr unit) (inl i) / M (inr unit) (inr unit)⟩ refine ⟨L, L', ?_⟩ - have A : L.map toMatrix = listTransvecCol M := by simp [L, listTransvecCol, (· ∘ ·)] - have B : L'.map toMatrix = listTransvecRow M := by simp [L', listTransvecRow, (· ∘ ·)] + have A : L.map toMatrix = listTransvecCol M := by simp [L, listTransvecCol, Function.comp_def] + have B : L'.map toMatrix = listTransvecRow M := by simp [L', listTransvecRow, Function.comp_def] rw [A, B] exact isTwoBlockDiagonal_listTransvecCol_mul_mul_listTransvecRow M hM diff --git a/Mathlib/LinearAlgebra/Matrix/ZPow.lean b/Mathlib/LinearAlgebra/Matrix/ZPow.lean index d28a1a1448f30..dd11fe3101db7 100644 --- a/Mathlib/LinearAlgebra/Matrix/ZPow.lean +++ b/Mathlib/LinearAlgebra/Matrix/ZPow.lean @@ -110,12 +110,14 @@ theorem _root_.IsUnit.det_zpow {A : M} (h : IsUnit A.det) (n : ℤ) : IsUnit (A · simpa using h.pow n.succ theorem isUnit_det_zpow_iff {A : M} {z : ℤ} : IsUnit (A ^ z).det ↔ IsUnit A.det ∨ z = 0 := by - induction' z using Int.induction_on with z _ z _ - · simp - · rw [← Int.ofNat_succ, zpow_natCast, det_pow, isUnit_pow_succ_iff, ← Int.ofNat_zero, + induction z using Int.induction_on with + | hz => simp + | hp z => + rw [← Int.ofNat_succ, zpow_natCast, det_pow, isUnit_pow_succ_iff, ← Int.ofNat_zero, Int.ofNat_inj] simp - · rw [← neg_add', ← Int.ofNat_succ, zpow_neg_natCast, isUnit_nonsing_inv_det_iff, det_pow, + | hn z => + rw [← neg_add', ← Int.ofNat_succ, zpow_neg_natCast, isUnit_nonsing_inv_det_iff, det_pow, isUnit_pow_succ_iff, neg_eq_zero, ← Int.ofNat_zero, Int.ofNat_inj] simp diff --git a/Mathlib/LinearAlgebra/Multilinear/Basic.lean b/Mathlib/LinearAlgebra/Multilinear/Basic.lean index 9e188e11220cf..417f0dde15dc6 100644 --- a/Mathlib/LinearAlgebra/Multilinear/Basic.lean +++ b/Mathlib/LinearAlgebra/Multilinear/Basic.lean @@ -797,7 +797,7 @@ theorem compMultilinearMap_apply (g : M₂ →ₗ[R] M₃) (f : MultilinearMap R @[simp] theorem subtype_compMultilinearMap_codRestrict (f : MultilinearMap R M₁ M₂) (p : Submodule R M₂) (h) : p.subtype.compMultilinearMap (f.codRestrict p h) = f := - MultilinearMap.ext fun _ => rfl + rfl /-- The multilinear version of `LinearMap.comp_codRestrict` -/ @[simp] @@ -805,7 +805,7 @@ theorem compMultilinearMap_codRestrict (g : M₂ →ₗ[R] M₃) (f : Multilinea (p : Submodule R M₃) (h) : (g.codRestrict p h).compMultilinearMap f = (g.compMultilinearMap f).codRestrict p fun v => h (f v) := - MultilinearMap.ext fun _ => rfl + rfl variable {ι₁ ι₂ : Type*} @@ -1771,3 +1771,5 @@ def range [Nonempty ι] (f : MultilinearMap R M₁ M₂) : SubMulAction R M₂ : end Submodule end MultilinearMap + +set_option linter.style.longFile 1900 diff --git a/Mathlib/LinearAlgebra/Pi.lean b/Mathlib/LinearAlgebra/Pi.lean index d1342d034d19e..18abf808fda35 100644 --- a/Mathlib/LinearAlgebra/Pi.lean +++ b/Mathlib/LinearAlgebra/Pi.lean @@ -4,12 +4,12 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl, Mario Carneiro, Kevin Buzzard, Yury Kudryashov, Eric Wieser -/ import Mathlib.Algebra.Group.Fin.Tuple +import Mathlib.Algebra.BigOperators.GroupWithZero.Action import Mathlib.Algebra.BigOperators.Pi import Mathlib.Algebra.Module.Prod import Mathlib.Algebra.Module.Submodule.Ker import Mathlib.Algebra.Module.Submodule.Range import Mathlib.Algebra.Module.Equiv.Basic -import Mathlib.GroupTheory.GroupAction.BigOperators import Mathlib.Logic.Equiv.Fin /-! diff --git a/Mathlib/LinearAlgebra/PiTensorProduct.lean b/Mathlib/LinearAlgebra/PiTensorProduct.lean index 1175a41ee25f1..acdc671ceb60a 100644 --- a/Mathlib/LinearAlgebra/PiTensorProduct.lean +++ b/Mathlib/LinearAlgebra/PiTensorProduct.lean @@ -313,7 +313,7 @@ def lifts (x : ⨂[R] i, s i) : Set (FreeAddMonoid (R × Π i, s i)) := {p | AddCon.toQuotient (c := addConGen (PiTensorProduct.Eqv R s)) p = x} /-- An element `p` of `FreeAddMonoid (R × Π i, s i)` lifts an element `x` of `⨂[R] i, s i` -if and only if `x` is equal to to the sum of `a • ⨂ₜ[R] i, m i` over all the entries +if and only if `x` is equal to the sum of `a • ⨂ₜ[R] i, m i` over all the entries `(a, m)` of `p`. -/ lemma mem_lifts_iff (x : ⨂[R] i, s i) (p : FreeAddMonoid (R × Π i, s i)) : diff --git a/Mathlib/LinearAlgebra/Prod.lean b/Mathlib/LinearAlgebra/Prod.lean index 8a58b466b4060..4db6ffb5b5ed8 100644 --- a/Mathlib/LinearAlgebra/Prod.lean +++ b/Mathlib/LinearAlgebra/Prod.lean @@ -525,10 +525,9 @@ def fstEquiv : Submodule.fst R M M₂ ≃ₗ[R] M where -- Porting note: proofs were `tidy` or `simp` toFun x := x.1.1 invFun m := ⟨⟨m, 0⟩, by simp only [fst, comap_bot, mem_ker, snd_apply]⟩ - map_add' := by simp only [AddSubmonoid.coe_add, coe_toAddSubmonoid, Prod.fst_add, Subtype.forall, - implies_true, Prod.forall, forall_const] + map_add' := by simp only [coe_add, Prod.fst_add, implies_true] map_smul' := by simp only [SetLike.val_smul, Prod.smul_fst, RingHom.id_apply, Subtype.forall, - implies_true, Prod.forall, forall_const] + implies_true] left_inv := by rintro ⟨⟨x, y⟩, hy⟩ simp only [fst, comap_bot, mem_ker, snd_apply] at hy @@ -557,10 +556,9 @@ def sndEquiv : Submodule.snd R M M₂ ≃ₗ[R] M₂ where -- Porting note: proofs were `tidy` or `simp` toFun x := x.1.2 invFun n := ⟨⟨0, n⟩, by simp only [snd, comap_bot, mem_ker, fst_apply]⟩ - map_add' := by simp only [AddSubmonoid.coe_add, coe_toAddSubmonoid, Prod.snd_add, Subtype.forall, - implies_true, Prod.forall, forall_const] + map_add' := by simp only [coe_add, Prod.snd_add, implies_true] map_smul' := by simp only [SetLike.val_smul, Prod.smul_snd, RingHom.id_apply, Subtype.forall, - implies_true, Prod.forall, forall_const] + implies_true] left_inv := by rintro ⟨⟨x, y⟩, hx⟩ simp only [snd, comap_bot, mem_ker, fst_apply] at hx diff --git a/Mathlib/LinearAlgebra/QuadraticForm/Basic.lean b/Mathlib/LinearAlgebra/QuadraticForm/Basic.lean index 6476d73156547..caedda89e57e7 100644 --- a/Mathlib/LinearAlgebra/QuadraticForm/Basic.lean +++ b/Mathlib/LinearAlgebra/QuadraticForm/Basic.lean @@ -63,7 +63,7 @@ substantial refactors from the current version, such that $Q(rm) = rQ(m)r^*$ for suitable conjugation $r^*$. The [Zulip thread](https://leanprover.zulipchat.com/#narrow/stream/116395-maths/topic/Quadratic.20Maps/near/395529867) -has some further discusion. +has some further discussion. ## References @@ -75,14 +75,12 @@ has some further discusion. quadratic map, homogeneous polynomial, quadratic polynomial -/ - universe u v w variable {S T : Type*} variable {R : Type*} {M N P A : Type*} -open LinearMap (BilinMap) -open LinearMap (BilinForm) +open LinearMap (BilinMap BilinForm) section Polar @@ -147,7 +145,6 @@ section QuadraticForm variable (R : Type u) (M : Type v) [CommSemiring R] [AddCommMonoid M] [Module R M] -variable (R M) in /-- A quadratic form on a module. -/ abbrev QuadraticForm : Type _ := QuadraticMap R M R diff --git a/Mathlib/LinearAlgebra/QuadraticForm/Basis.lean b/Mathlib/LinearAlgebra/QuadraticForm/Basis.lean index 0c19cad735241..c2c99925d7bb1 100644 --- a/Mathlib/LinearAlgebra/QuadraticForm/Basis.lean +++ b/Mathlib/LinearAlgebra/QuadraticForm/Basis.lean @@ -35,8 +35,8 @@ theorem toBilin_apply (Q : QuadraticMap R M N) (bm : Basis ι R M) (i j : ι) : theorem toQuadraticMap_toBilin (Q : QuadraticMap R M N) (bm : Basis ι R M) : (Q.toBilin bm).toQuadraticMap = Q := by ext x - rw [← bm.total_repr x, LinearMap.BilinMap.toQuadraticMap_apply, Finsupp.total_apply, - Finsupp.sum] + rw [← bm.linearCombination_repr x, LinearMap.BilinMap.toQuadraticMap_apply, + Finsupp.linearCombination_apply, Finsupp.sum] simp_rw [LinearMap.map_sum₂, map_sum, LinearMap.map_smul₂, _root_.map_smul, toBilin_apply, smul_ite, smul_zero, ← Finset.sum_product', ← Finset.diag_union_offDiag, Finset.sum_union (Finset.disjoint_diag_offDiag _), Finset.sum_diag, if_true] diff --git a/Mathlib/LinearAlgebra/QuadraticForm/QuadraticModuleCat.lean b/Mathlib/LinearAlgebra/QuadraticForm/QuadraticModuleCat.lean index a86dc75313b8c..c05f820fefc9c 100644 --- a/Mathlib/LinearAlgebra/QuadraticForm/QuadraticModuleCat.lean +++ b/Mathlib/LinearAlgebra/QuadraticForm/QuadraticModuleCat.lean @@ -16,7 +16,7 @@ universe v u variable (R : Type u) [CommRing R] -/-- The category of quadratic modules; modules with an associated quadratic form-/ +/-- The category of quadratic modules; modules with an associated quadratic form -/ structure QuadraticModuleCat extends ModuleCat.{v} R where /-- The quadratic form associated with the module. -/ form : QuadraticForm R carrier @@ -25,8 +25,7 @@ variable {R} namespace QuadraticModuleCat -open QuadraticForm -open QuadraticMap +open QuadraticForm QuadraticMap instance : CoeSort (QuadraticModuleCat.{v} R) (Type v) := ⟨(·.carrier)⟩ diff --git a/Mathlib/LinearAlgebra/QuadraticForm/QuadraticModuleCat/Monoidal.lean b/Mathlib/LinearAlgebra/QuadraticForm/QuadraticModuleCat/Monoidal.lean index 0a4c42c63fd3c..f7b52334b7167 100644 --- a/Mathlib/LinearAlgebra/QuadraticForm/QuadraticModuleCat/Monoidal.lean +++ b/Mathlib/LinearAlgebra/QuadraticForm/QuadraticModuleCat/Monoidal.lean @@ -35,8 +35,7 @@ variable {R : Type u} [CommRing R] [Invertible (2 : R)] namespace QuadraticModuleCat -open QuadraticMap -open QuadraticForm +open QuadraticMap QuadraticForm namespace instMonoidalCategory @@ -87,22 +86,22 @@ noncomputable instance instMonoidalCategory : MonoidalCategory (QuadraticModuleC εIso := Iso.refl _ leftUnitor_eq := fun X => by simp only [forget₂_obj, forget₂_map, Iso.refl_symm, Iso.trans_assoc, Iso.trans_hom, - Iso.refl_hom, tensorIso_hom, MonoidalCategory.tensorHom_id] + Iso.refl_hom, MonoidalCategory.tensorIso_hom, MonoidalCategory.tensorHom_id] dsimp only [toModuleCat_tensor, ModuleCat.of_coe] erw [MonoidalCategory.id_whiskerRight] simp rfl rightUnitor_eq := fun X => by simp only [forget₂_obj, forget₂_map, Iso.refl_symm, Iso.trans_assoc, Iso.trans_hom, - Iso.refl_hom, tensorIso_hom, MonoidalCategory.id_tensorHom] + Iso.refl_hom, MonoidalCategory.tensorIso_hom, MonoidalCategory.id_tensorHom] dsimp only [toModuleCat_tensor, ModuleCat.of_coe] erw [MonoidalCategory.whiskerLeft_id] simp rfl associator_eq := fun X Y Z => by dsimp only [forget₂_obj, forget₂_map_associator_hom] - simp only [eqToIso_refl, Iso.refl_trans, Iso.refl_symm, Iso.trans_hom, tensorIso_hom, - Iso.refl_hom, MonoidalCategory.tensor_id] + simp only [eqToIso_refl, Iso.refl_trans, Iso.refl_symm, Iso.trans_hom, + MonoidalCategory.tensorIso_hom, Iso.refl_hom, MonoidalCategory.tensor_id] dsimp only [toModuleCat_tensor, ModuleCat.of_coe] rw [Category.id_comp, Category.id_comp, Category.comp_id, MonoidalCategory.tensor_id, Category.id_comp] } diff --git a/Mathlib/LinearAlgebra/QuadraticForm/TensorProduct.lean b/Mathlib/LinearAlgebra/QuadraticForm/TensorProduct.lean index f4bca4eca0457..1d4c4ee3c081a 100644 --- a/Mathlib/LinearAlgebra/QuadraticForm/TensorProduct.lean +++ b/Mathlib/LinearAlgebra/QuadraticForm/TensorProduct.lean @@ -20,10 +20,8 @@ universe uR uA uM₁ uM₂ variable {R : Type uR} {A : Type uA} {M₁ : Type uM₁} {M₂ : Type uM₂} -open TensorProduct -open LinearMap (BilinMap) -open LinearMap (BilinForm) -open QuadraticMap +open LinearMap (BilinMap BilinForm) +open TensorProduct QuadraticMap namespace QuadraticForm diff --git a/Mathlib/LinearAlgebra/Ray.lean b/Mathlib/LinearAlgebra/Ray.lean index 02d99609f467d..117d5b1c1a242 100644 --- a/Mathlib/LinearAlgebra/Ray.lean +++ b/Mathlib/LinearAlgebra/Ray.lean @@ -3,7 +3,6 @@ Copyright (c) 2021 Joseph Myers. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Joseph Myers -/ -import Mathlib.Algebra.Group.Subgroup.Actions import Mathlib.Algebra.Order.Module.Algebra import Mathlib.LinearAlgebra.LinearIndependent import Mathlib.Algebra.Ring.Subring.Units diff --git a/Mathlib/LinearAlgebra/Reflection.lean b/Mathlib/LinearAlgebra/Reflection.lean index e6bde244d8722..2d07ea2bd6890 100644 --- a/Mathlib/LinearAlgebra/Reflection.lean +++ b/Mathlib/LinearAlgebra/Reflection.lean @@ -40,7 +40,7 @@ should connect (or unify) these definitions with `Module.reflecton` defined here -/ -open Set Function Pointwise +open Function Set open Module hiding Finite open Submodule (span) @@ -161,13 +161,19 @@ lemma Dual.eq_of_preReflection_mapsTo' [CharZero R] [NoZeroSMulDivisors R M] set Φ' : Set (span R Φ) := range (inclusion <| Submodule.subset_span (R := R) (s := Φ)) rw [← finite_coe_iff] at hΦ₁ have hΦ'₁ : Φ'.Finite := finite_range (inclusion Submodule.subset_span) - have hΦ'₂ : span R Φ' = ⊤ := by simp [Φ'] + have hΦ'₂ : span R Φ' = ⊤ := by + simp only [Φ'] + rw [range_inclusion] + simp let x' : span R Φ := ⟨x, hx'⟩ have hx' : x' ≠ 0 := Subtype.coe_ne_coe.1 hx have this : ∀ {F : Dual R M}, MapsTo (preReflection x F) Φ Φ → MapsTo (preReflection x' ((span R Φ).subtype.dualMap F)) Φ' Φ' := by intro F hF ⟨y, hy⟩ hy' - simp only [Φ', range_inclusion, SetLike.coe_sort_coe, mem_setOf_eq] at hy' ⊢ + simp only [Φ'] at hy' ⊢ + rw [range_inclusion] at hy' + simp only [SetLike.coe_sort_coe, mem_setOf_eq] at hy' ⊢ + rw [range_inclusion] exact hF hy' exact eq_of_preReflection_mapsTo hx' hΦ'₁ hΦ'₂ hf₁ (this hf₂) hg₁ (this hg₂) diff --git a/Mathlib/LinearAlgebra/RootSystem/Basic.lean b/Mathlib/LinearAlgebra/RootSystem/Basic.lean index 4b4ba33c9fa5a..8ca70db9d0e55 100644 --- a/Mathlib/LinearAlgebra/RootSystem/Basic.lean +++ b/Mathlib/LinearAlgebra/RootSystem/Basic.lean @@ -17,7 +17,7 @@ This file contains basic results for root systems and root data. * `RootSystem.ext`: In characteristic zero if there is no torsion, a root system is determined entirely by its roots. * `RootPairing.mk'`: In characteristic zero if there is no torsion, to check that two finite - familes of of roots and coroots form a root pairing, it is sufficient to check that they are + families of roots and coroots form a root pairing, it is sufficient to check that they are stable under reflections. * `RootSystem.mk'`: In characteristic zero if there is no torsion, to check that a finite family of roots form a root system, we do not need to check that the coroots are stable under reflections @@ -173,7 +173,7 @@ private lemma coroot_eq_coreflection_of_root_eq' [CharZero R] [NoZeroSMulDivisor rw [comp_apply, hl, hk, hij] exact (hr i).comp <| (hr j).comp (hr i) -/-- In characteristic zero if there is no torsion, to check that two finite familes of of roots and +/-- In characteristic zero if there is no torsion, to check that two finite families of roots and coroots form a root pairing, it is sufficient to check that they are stable under reflections. -/ def mk' [Finite ι] [CharZero R] [NoZeroSMulDivisors R M] (p : PerfectPairing R M N) diff --git a/Mathlib/LinearAlgebra/RootSystem/Defs.lean b/Mathlib/LinearAlgebra/RootSystem/Defs.lean index 8ce5eed7055ed..b375be2df788c 100644 --- a/Mathlib/LinearAlgebra/RootSystem/Defs.lean +++ b/Mathlib/LinearAlgebra/RootSystem/Defs.lean @@ -16,25 +16,25 @@ This file contains basic definitions for root systems and root data. * `RootPairing`: Given two perfectly-paired `R`-modules `M` and `N` (over some commutative ring `R`) a root pairing with indexing set `ι` is the data of an `ι`-indexed subset of `M` ("the roots") an `ι`-indexed subset of `N` ("the coroots"), and an `ι`-indexed set of - permutations of `ι` such that each root-coroot pair - evaluates to `2`, and the permutation attached to each element of `ι` is compatible with the - reflections on the corresponding roots and coroots. + permutations of `ι` such that each root-coroot pair evaluates to `2`, and the permutation + attached to each element of `ι` is compatible with the reflections on the corresponding roots and + coroots. * `RootDatum`: A root datum is a root pairing for which the roots and coroots take values in finitely-generated free Abelian groups. * `RootSystem`: A root system is a root pairing for which the roots span their ambient module. * `RootPairing.IsCrystallographic`: A root pairing is said to be crystallographic if the pairing between a root and coroot is always an integer. - * `RootPairing.IsReduced`: A root pairing is said to be reduced if it never contains the double of - a root. + * `RootPairing.IsReduced`: A root pairing is said to be reduced if two linearly dependent roots are + always related by a sign. + * `RootPairing.weylGroup`: The group of linear isomorphisms on `M` generated by reflections. + * `RootPairing.weylGroupToPerm`: The permutation representation of the Weyl group on `ι`. ## TODO -* Put more API theorems in the Defs file. -* Introduce the Weyl Group, and its action on the indexing set. -* Base change of root pairings (may need flatness). -* 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. + * 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. ## Implementation details @@ -115,6 +115,8 @@ required to be the dual of `M`. -/ structure RootSystem extends RootPairing ι R M N := span_eq_top : span R (range root) = ⊤ +attribute [simp] RootSystem.span_eq_top + namespace RootPairing variable {ι R M N} @@ -189,6 +191,28 @@ lemma reflection_same (x : M) : P.reflection i (P.reflection i x) = x := Module.involutive_reflection (P.coroot_root_two i) x +@[simp] +lemma reflection_inv : + (P.reflection i)⁻¹ = P.reflection i := + rfl + +@[simp] +lemma reflection_sq : + P.reflection i ^ 2 = 1 := + mul_eq_one_iff_eq_inv.mpr rfl + +@[simp] +lemma reflection_perm_sq : + P.reflection_perm i ^ 2 = 1 := by + ext j + refine Embedding.injective P.root ?_ + simp only [sq, Equiv.Perm.mul_apply, root_reflection_perm, reflection_same, Equiv.Perm.one_apply] + +@[simp] +lemma reflection_perm_inv : + (P.reflection_perm i)⁻¹ = P.reflection_perm i := + (mul_eq_one_iff_eq_inv.mp <| P.reflection_perm_sq i).symm + lemma bijOn_reflection_root : BijOn (P.reflection i) (range P.root) (range P.root) := Module.bijOn_reflection_of_mapsTo _ <| P.mapsTo_reflection_root i @@ -230,6 +254,16 @@ lemma coreflection_same (x : N) : P.coreflection i (P.coreflection i x) = x := Module.involutive_reflection (P.flip.coroot_root_two i) x +@[simp] +lemma coreflection_inv : + (P.coreflection i)⁻¹ = P.coreflection i := + rfl + +@[simp] +lemma coreflection_sq : + P.coreflection i ^ 2 = 1 := + mul_eq_one_iff_eq_inv.mpr rfl + lemma bijOn_coreflection_coroot : BijOn (P.coreflection i) (range P.coroot) (range P.coroot) := bijOn_reflection_root P.flip i @@ -280,6 +314,150 @@ lemma isReduced_iff : P.IsReduced ↔ ∀ i j : ι, i ≠ j → · exact Or.inl (congrArg P.root h') · exact Or.inr (h i j h' hLin) +/-- The `Weyl group` of a root pairing is the group of automorphisms of the weight space generated +by reflections in roots. -/ +def weylGroup : Subgroup (M ≃ₗ[R] M) := + Subgroup.closure (range P.reflection) + +lemma reflection_mem_weylGroup : P.reflection i ∈ P.weylGroup := + Subgroup.subset_closure <| mem_range_self i + +lemma mem_range_root_of_mem_range_reflection_of_mem_range_root + {r : M ≃ₗ[R] M} {α : M} (hr : r ∈ range P.reflection) (hα : α ∈ range P.root) : + r • α ∈ range P.root := by + obtain ⟨i, rfl⟩ := hr + obtain ⟨j, rfl⟩ := hα + exact ⟨P.reflection_perm i j, P.root_reflection_perm i j⟩ + +lemma mem_range_coroot_of_mem_range_coreflection_of_mem_range_coroot + {r : N ≃ₗ[R] N} {α : N} (hr : r ∈ range P.coreflection) (hα : α ∈ range P.coroot) : + r • α ∈ range P.coroot := by + obtain ⟨i, rfl⟩ := hr + obtain ⟨j, rfl⟩ := hα + exact ⟨P.reflection_perm i j, P.coroot_reflection_perm i j⟩ + +lemma exists_root_eq_smul_of_mem_weylGroup {w : M ≃ₗ[R] M} (hw : w ∈ P.weylGroup) (i : ι) : + ∃ j, P.root j = w • P.root i := + Subgroup.smul_mem_of_mem_closure_of_mem (by simp) + (fun _ h _ ↦ P.mem_range_root_of_mem_range_reflection_of_mem_range_root h) hw (mem_range_self i) + +/-- The permutation representation of the Weyl group induced by `reflection_perm`. -/ +def weylGroupToPerm : P.weylGroup →* Equiv.Perm ι where + toFun w := + { toFun := fun i => (P.exists_root_eq_smul_of_mem_weylGroup w.2 i).choose + invFun := fun i => (P.exists_root_eq_smul_of_mem_weylGroup w⁻¹.2 i).choose + left_inv := fun i => by + obtain ⟨w, hw⟩ := w + apply P.root.injective + rw [(P.exists_root_eq_smul_of_mem_weylGroup ((Subgroup.inv_mem_iff P.weylGroup).mpr hw) + ((P.exists_root_eq_smul_of_mem_weylGroup hw i).choose)).choose_spec, + (P.exists_root_eq_smul_of_mem_weylGroup hw i).choose_spec, inv_smul_smul] + right_inv := fun i => by + obtain ⟨w, hw⟩ := w + have hw' : w⁻¹ ∈ P.weylGroup := (Subgroup.inv_mem_iff P.weylGroup).mpr hw + apply P.root.injective + rw [(P.exists_root_eq_smul_of_mem_weylGroup hw + ((P.exists_root_eq_smul_of_mem_weylGroup hw' i).choose)).choose_spec, + (P.exists_root_eq_smul_of_mem_weylGroup hw' i).choose_spec, smul_inv_smul] } + map_one' := by ext; simp + map_mul' x y := by + obtain ⟨x, hx⟩ := x + obtain ⟨y, hy⟩ := y + ext i + apply P.root.injective + simp only [Equiv.coe_fn_mk, Equiv.Perm.coe_mul, comp_apply] + rw [(P.exists_root_eq_smul_of_mem_weylGroup (mul_mem hx hy) i).choose_spec, + (P.exists_root_eq_smul_of_mem_weylGroup hx + ((P.exists_root_eq_smul_of_mem_weylGroup hy i).choose)).choose_spec, + (P.exists_root_eq_smul_of_mem_weylGroup hy i).choose_spec, mul_smul] + +@[simp] +lemma weylGroupToPerm_apply_reflection : + P.weylGroupToPerm ⟨P.reflection i, P.reflection_mem_weylGroup i⟩ = P.reflection_perm i := by + ext j + apply P.root.injective + rw [weylGroupToPerm, MonoidHom.coe_mk, OneHom.coe_mk, Equiv.coe_fn_mk, root_reflection_perm, + (P.exists_root_eq_smul_of_mem_weylGroup (P.reflection_mem_weylGroup i) j).choose_spec, + LinearEquiv.smul_def] + +@[simp] +lemma range_weylGroupToPerm : + P.weylGroupToPerm.range = Subgroup.closure (range P.reflection_perm) := by + refine (Subgroup.closure_eq_of_le _ ?_ ?_).symm + · rintro - ⟨i, rfl⟩ + simpa only [← weylGroupToPerm_apply_reflection] using mem_range_self _ + · rintro - ⟨⟨w, hw⟩, rfl⟩ + induction hw using Subgroup.closure_induction'' with + | one => + change P.weylGroupToPerm 1 ∈ _ + simpa only [map_one] using Subgroup.one_mem _ + | mem w' hw' => + obtain ⟨i, rfl⟩ := hw' + simpa only [weylGroupToPerm_apply_reflection] using Subgroup.subset_closure (mem_range_self i) + | inv_mem w' hw' => + obtain ⟨i, rfl⟩ := hw' + simpa only [reflection_inv, weylGroupToPerm_apply_reflection] using + Subgroup.subset_closure (mem_range_self i) + | mul w₁ w₂ hw₁ hw₂ h₁ h₂ => + simpa only [← Submonoid.mk_mul_mk _ w₁ w₂ hw₁ hw₂, map_mul] using Subgroup.mul_mem _ h₁ h₂ + +lemma pairing_smul_root_eq (k : ι) (hij : P.reflection_perm i = P.reflection_perm j) : + P.pairing k i • P.root i = P.pairing k j • P.root j := by + have h : P.reflection i (P.root k) = P.reflection j (P.root k) := by + simp only [← root_reflection_perm, hij] + simpa only [reflection_apply_root, sub_right_inj] using h + +lemma pairing_smul_coroot_eq (k : ι) (hij : P.reflection_perm i = P.reflection_perm j) : + P.pairing i k • P.coroot i = P.pairing j k • P.coroot j := by + have h : P.coreflection i (P.coroot k) = P.coreflection j (P.coroot k) := by + simp only [← coroot_reflection_perm, hij] + simpa only [coreflection_apply_coroot, sub_right_inj] using h + +lemma two_nsmul_reflection_eq_of_perm_eq (hij : P.reflection_perm i = P.reflection_perm j) : + 2 • ⇑(P.reflection i) = 2 • P.reflection j := by + ext x + suffices 2 • P.toLin x (P.coroot i) • P.root i = 2 • P.toLin x (P.coroot j) • P.root j by + simpa [reflection_apply] + calc 2 • P.toLin x (P.coroot i) • P.root i + = P.toLin x (P.coroot i) • ((2 : R) • P.root i) := ?_ + _ = P.toLin x (P.coroot i) • (P.pairing i j • P.root j) := ?_ + _ = P.toLin x (P.pairing i j • P.coroot i) • (P.root j) := ?_ + _ = P.toLin x ((2 : R) • P.coroot j) • (P.root j) := ?_ + _ = 2 • P.toLin x (P.coroot j) • P.root j := ?_ + · rw [smul_comm, ← Nat.cast_smul_eq_nsmul R, Nat.cast_ofNat] + · rw [P.pairing_smul_root_eq j i i hij.symm, pairing_same] + · rw [← smul_comm, ← smul_assoc, map_smul] + · rw [← P.pairing_smul_coroot_eq j i j hij.symm, pairing_same] + · rw [map_smul, smul_assoc, ← Nat.cast_smul_eq_nsmul R, Nat.cast_ofNat] + +lemma reflection_perm_eq_reflection_perm_iff_of_isSMulRegular (h2 : IsSMulRegular M 2) : + P.reflection_perm i = P.reflection_perm j ↔ P.reflection i = P.reflection j := by + refine ⟨fun h ↦ ?_, fun h ↦ Equiv.ext fun k ↦ P.root.injective <| by simp [h]⟩ + suffices ⇑(P.reflection i) = ⇑(P.reflection j) from DFunLike.coe_injective this + replace h2 : IsSMulRegular (M → M) 2 := IsSMulRegular.pi fun _ ↦ h2 + exact h2 <| P.two_nsmul_reflection_eq_of_perm_eq i j h + +lemma reflection_perm_eq_reflection_perm_iff_of_span : + P.reflection_perm i = P.reflection_perm j ↔ + ∀ x ∈ span R (range P.root), P.reflection i x = P.reflection j x := by + refine ⟨fun h x hx ↦ ?_, fun h ↦ ?_⟩ + · induction hx using Submodule.span_induction' with + | mem x hx => + obtain ⟨k, rfl⟩ := hx + simp only [← root_reflection_perm, h] + | zero => simp + | add x _ y _ hx hy => simp [hx, hy] + | smul t x _ hx => simp [hx] + · ext k + apply P.root.injective + simp [h (P.root k) (Submodule.subset_span <| mem_range_self k)] + +lemma _root_.RootSystem.reflection_perm_eq_reflection_perm_iff (P : RootSystem ι R M N) (i j : ι) : + P.reflection_perm i = P.reflection_perm j ↔ P.reflection i = P.reflection j := by + refine ⟨fun h ↦ ?_, fun h ↦ Equiv.ext fun k ↦ P.root.injective <| by simp [h]⟩ + ext x + exact (P.reflection_perm_eq_reflection_perm_iff_of_span i j).mp h x <| by simp + /-- The Coxeter Weight of a pair gives the weight of an edge in a Coxeter diagram, when it is finite. It is `4 cos² θ`, where `θ` describes the dihedral angle between hyperplanes. -/ def coxeterWeight : R := pairing P i j * pairing P j i diff --git a/Mathlib/LinearAlgebra/SesquilinearForm.lean b/Mathlib/LinearAlgebra/SesquilinearForm.lean index f97b86492d2e9..e1ee9539064ba 100644 --- a/Mathlib/LinearAlgebra/SesquilinearForm.lean +++ b/Mathlib/LinearAlgebra/SesquilinearForm.lean @@ -460,7 +460,7 @@ end AddCommGroup end AdjointPair -/-! ### Self-adjoint pairs-/ +/-! ### Self-adjoint pairs -/ section SelfadjointPair @@ -704,7 +704,7 @@ theorem IsOrthoᵢ.not_isOrtho_basis_self_of_separatingLeft [Nontrivial R] intro ho refine v.ne_zero i (hB (v i) fun m ↦ ?_) obtain ⟨vi, rfl⟩ := v.repr.symm.surjective m - rw [Basis.repr_symm_apply, Finsupp.total_apply, Finsupp.sum, map_sum] + rw [Basis.repr_symm_apply, Finsupp.linearCombination_apply, Finsupp.sum, map_sum] apply Finset.sum_eq_zero rintro j - rw [map_smulₛₗ] @@ -733,7 +733,8 @@ theorem IsOrthoᵢ.separatingLeft_of_not_isOrtho_basis_self [NoZeroSMulDivisors ext i rw [Finsupp.zero_apply] specialize hB (v i) - simp_rw [Basis.repr_symm_apply, Finsupp.total_apply, Finsupp.sum, map_sum₂, map_smulₛₗ₂] at hB + simp_rw [Basis.repr_symm_apply, Finsupp.linearCombination_apply, Finsupp.sum, map_sum₂, + map_smulₛₗ₂] at hB rw [Finset.sum_eq_single i] at hB · exact (smul_eq_zero.mp hB).elim _root_.id (h i).elim · intro j _hj hij diff --git a/Mathlib/LinearAlgebra/Span.lean b/Mathlib/LinearAlgebra/Span.lean index 9e71038dfec4b..e6fec62b7d0d8 100644 --- a/Mathlib/LinearAlgebra/Span.lean +++ b/Mathlib/LinearAlgebra/Span.lean @@ -744,7 +744,7 @@ theorem span_prod_le (s : Set M) (t : Set M') : span R (s ×ˢ t) ≤ prod (span theorem prod_top : (prod ⊤ ⊤ : Submodule R (M × M')) = ⊤ := by ext; simp @[simp] -theorem prod_bot : (prod ⊥ ⊥ : Submodule R (M × M')) = ⊥ := by ext ⟨x, y⟩; simp [Prod.zero_eq_mk] +theorem prod_bot : (prod ⊥ ⊥ : Submodule R (M × M')) = ⊥ := by ext ⟨x, y⟩; simp theorem prod_mono {p p' : Submodule R M} {q q' : Submodule R M'} : p ≤ p' → q ≤ q' → prod p q ≤ prod p' q' := diff --git a/Mathlib/LinearAlgebra/TensorAlgebra/Basic.lean b/Mathlib/LinearAlgebra/TensorAlgebra/Basic.lean index bfa9c8e59147a..9355d09c2992a 100644 --- a/Mathlib/LinearAlgebra/TensorAlgebra/Basic.lean +++ b/Mathlib/LinearAlgebra/TensorAlgebra/Basic.lean @@ -177,7 +177,7 @@ theorem hom_ext {A : Type*} [Semiring A] [Algebra R A] {f g : TensorAlgebra R M -- This proof closely follows `FreeAlgebra.induction` /-- If `C` holds for the `algebraMap` of `r : R` into `TensorAlgebra R M`, the `ι` of `x : M`, -and is preserved under addition and muliplication, then it holds for all of `TensorAlgebra R M`. +and is preserved under addition and multiplication, then it holds for all of `TensorAlgebra R M`. -/ @[elab_as_elim] theorem induction {C : TensorAlgebra R M → Prop} diff --git a/Mathlib/LinearAlgebra/TensorAlgebra/Basis.lean b/Mathlib/LinearAlgebra/TensorAlgebra/Basis.lean index 197e95b75cf05..24e2067ed86e6 100644 --- a/Mathlib/LinearAlgebra/TensorAlgebra/Basis.lean +++ b/Mathlib/LinearAlgebra/TensorAlgebra/Basis.lean @@ -35,7 +35,7 @@ with its index. -/ noncomputable def equivFreeAlgebra (b : Basis κ R M) : TensorAlgebra R M ≃ₐ[R] FreeAlgebra R κ := AlgEquiv.ofAlgHom - (TensorAlgebra.lift _ (Finsupp.total _ _ _ (FreeAlgebra.ι _) ∘ₗ b.repr.toLinearMap)) + (TensorAlgebra.lift _ (Finsupp.linearCombination _ (FreeAlgebra.ι _) ∘ₗ b.repr.toLinearMap)) (FreeAlgebra.lift _ (ι R ∘ b)) (by ext; simp) (hom_ext <| b.ext fun i => by simp) diff --git a/Mathlib/LinearAlgebra/TensorAlgebra/ToTensorPower.lean b/Mathlib/LinearAlgebra/TensorAlgebra/ToTensorPower.lean index bb0ee53dd453c..12adf5ad0f2b0 100644 --- a/Mathlib/LinearAlgebra/TensorAlgebra/ToTensorPower.lean +++ b/Mathlib/LinearAlgebra/TensorAlgebra/ToTensorPower.lean @@ -128,18 +128,18 @@ theorem _root_.TensorPower.list_prod_gradedMonoid_mk_single (n : ℕ) (x : Fin n rfl · intro n x₀ x ih rw [List.finRange_succ_eq_map, List.map_cons, List.prod_cons, List.map_map] - simp_rw [Function.comp, Fin.cons_zero, Fin.cons_succ] + simp_rw [Function.comp_def, Fin.cons_zero, Fin.cons_succ] rw [ih, GradedMonoid.mk_mul_mk, TensorPower.tprod_mul_tprod] refine TensorPower.gradedMonoid_eq_of_cast (add_comm _ _) ?_ dsimp only [GradedMonoid.mk] rw [TensorPower.cast_tprod] - simp_rw [Fin.append_left_eq_cons, Function.comp] + simp_rw [Fin.append_left_eq_cons, Function.comp_def] congr 1 with i theorem toDirectSum_tensorPower_tprod {n} (x : Fin n → M) : toDirectSum (tprod R M n x) = DirectSum.of _ n (PiTensorProduct.tprod R x) := by rw [tprod_apply, map_list_prod, List.map_ofFn] - simp_rw [Function.comp, toDirectSum_ι] + simp_rw [Function.comp_def, toDirectSum_ι] rw [DirectSum.list_prod_ofFn_of_eq_dProd] apply DirectSum.of_eq_of_gradedMonoid_eq rw [GradedMonoid.mk_list_dProd] diff --git a/Mathlib/LinearAlgebra/TensorPower.lean b/Mathlib/LinearAlgebra/TensorPower.lean index 0e0eed359fc0c..b05bd64ae042d 100644 --- a/Mathlib/LinearAlgebra/TensorPower.lean +++ b/Mathlib/LinearAlgebra/TensorPower.lean @@ -31,7 +31,7 @@ suppress_compilation open scoped TensorProduct -/-- Homogenous tensor powers $M^{\otimes n}$. `⨂[R]^n M` is a shorthand for +/-- Homogeneous tensor powers $M^{\otimes n}$. `⨂[R]^n M` is a shorthand for `⨂[R] (i : Fin n), M`. -/ abbrev TensorPower (R : Type*) (n : ℕ) (M : Type*) [CommSemiring R] [AddCommMonoid M] [Module R M] : Type _ := diff --git a/Mathlib/LinearAlgebra/TensorProduct/Basic.lean b/Mathlib/LinearAlgebra/TensorProduct/Basic.lean index 6bbe92a9b4b88..bcb3daf37d060 100644 --- a/Mathlib/LinearAlgebra/TensorProduct/Basic.lean +++ b/Mathlib/LinearAlgebra/TensorProduct/Basic.lean @@ -669,7 +669,7 @@ theorem comm_tmul (m : M) (n : N) : (TensorProduct.comm R M N) (m ⊗ₜ n) = n theorem comm_symm_tmul (m : M) (n : N) : (TensorProduct.comm R M N).symm (n ⊗ₜ m) = m ⊗ₜ n := rfl -lemma lift_comp_comm_eq (f : M →ₗ[R] N →ₗ[R] P) : +lemma lift_comp_comm_eq (f : M →ₗ[R] N →ₗ[R] P) : lift f ∘ₗ TensorProduct.comm R N M = lift f.flip := ext rfl end diff --git a/Mathlib/LinearAlgebra/TensorProduct/Graded/Internal.lean b/Mathlib/LinearAlgebra/TensorProduct/Graded/Internal.lean index d351d025cd8df..58c1cf353dbaa 100644 --- a/Mathlib/LinearAlgebra/TensorProduct/Graded/Internal.lean +++ b/Mathlib/LinearAlgebra/TensorProduct/Graded/Internal.lean @@ -150,7 +150,7 @@ theorem mulHom_apply (x y : 𝒜 ᵍ⊗[R] ℬ) : = (auxEquiv R 𝒜 ℬ).symm (gradedMul R (𝒜 ·) (ℬ ·) (auxEquiv R 𝒜 ℬ x) (auxEquiv R 𝒜 ℬ y)) := rfl -/-- The multipication on the graded tensor product. +/-- The multiplication on the graded tensor product. See `GradedTensorProduct.coe_mul_coe` for a characterization on pure tensors. -/ instance : Mul (𝒜 ᵍ⊗[R] ℬ) where mul x y := mulHom 𝒜 ℬ x y @@ -179,7 +179,7 @@ instance instRing : Ring (𝒜 ᵍ⊗[R] ℬ) where mul_zero x := by simp_rw [mul_def, map_zero] zero_mul x := by simp_rw [mul_def, LinearMap.map_zero₂] -/-- The characterization of this multiplication on partially homogenous elements. -/ +/-- The characterization of this multiplication on partially homogeneous elements. -/ theorem tmul_coe_mul_coe_tmul {j₁ i₂ : ι} (a₁ : A) (b₁ : ℬ j₁) (a₂ : 𝒜 i₂) (b₂ : B) : (a₁ ᵍ⊗ₜ[R] (b₁ : B) * (a₂ : A) ᵍ⊗ₜ[R] b₂ : 𝒜 ᵍ⊗[R] ℬ) = (-1 : ℤˣ)^(j₁ * i₂) • ((a₁ * a₂ : A) ᵍ⊗ₜ (b₁ * b₂ : B)) := by @@ -189,7 +189,6 @@ theorem tmul_coe_mul_coe_tmul {j₁ i₂ : ι} (a₁ : A) (b₁ : ℬ j₁) (a simp_rw [← lof_eq_of R] rw [tmul_of_gradedMul_of_tmul] simp_rw [lof_eq_of R] - rw [LinearEquiv.symm_symm] -- Note: #8386 had to specialize `map_smul` to `LinearEquiv.map_smul` rw [@Units.smul_def _ _ (_) (_), ← Int.cast_smul_eq_zsmul R, LinearEquiv.map_smul, map_smul, Int.cast_smul_eq_zsmul R, ← @Units.smul_def _ _ (_) (_)] @@ -296,7 +295,7 @@ lemma algebraMap_def' (r : R) : algebraMap R (𝒜 ᵍ⊗[R] ℬ) r = 1 ᵍ⊗ variable {C} [Ring C] [Algebra R C] /-- The forwards direction of the universal property; an algebra morphism out of the graded tensor -product can be assembed from maps on each component that (anti)commute on pure elements of the +product can be assembled from maps on each component that (anti)commute on pure elements of the corresponding graded algebras. -/ def lift (f : A →ₐ[R] C) (g : B →ₐ[R] C) (h_anti_commutes : ∀ ⦃i j⦄ (a : 𝒜 i) (b : ℬ j), f a * g b = (-1 : ℤˣ)^(j * i) • (g b * f a)) : diff --git a/Mathlib/LinearAlgebra/TensorProduct/RightExactness.lean b/Mathlib/LinearAlgebra/TensorProduct/RightExactness.lean index 3cdcdf07810e4..608cd74b64296 100644 --- a/Mathlib/LinearAlgebra/TensorProduct/RightExactness.lean +++ b/Mathlib/LinearAlgebra/TensorProduct/RightExactness.lean @@ -6,6 +6,7 @@ Authors: Antoine Chambert-Loir import Mathlib.Algebra.Exact import Mathlib.RingTheory.TensorProduct.Basic +import Mathlib.RingTheory.Ideal.Quotient /-! # Right-exactness properties of tensor product @@ -170,14 +171,15 @@ variable {f : M →ₗ[R] N} {g : N →ₗ[R] P} (hfg : Exact f g) (hg : Function.Surjective g) /-- The direct map in `lTensor.equiv` -/ -noncomputable def lTensor.toFun : +noncomputable def lTensor.toFun (hfg : Exact f g) : Q ⊗[R] N ⧸ LinearMap.range (lTensor Q f) →ₗ[R] Q ⊗[R] P := Submodule.liftQ _ (lTensor Q g) <| by rw [LinearMap.range_le_iff_comap, ← LinearMap.ker_comp, ← lTensor_comp, hfg.linearMap_comp_eq_zero, lTensor_zero, ker_zero] /-- The inverse map in `lTensor.equiv_of_rightInverse` (computably, given a right inverse)-/ -noncomputable def lTensor.inverse_of_rightInverse {h : P → N} (hgh : Function.RightInverse h g) : +noncomputable def lTensor.inverse_of_rightInverse {h : P → N} (hfg : Exact f g) + (hgh : Function.RightInverse h g) : Q ⊗[R] P →ₗ[R] Q ⊗[R] N ⧸ LinearMap.range (lTensor Q f) := TensorProduct.lift <| LinearMap.flip <| { toFun := fun p ↦ Submodule.mkQ _ ∘ₗ ((TensorProduct.mk R _ _).flip (h p)) @@ -276,14 +278,15 @@ lemma lTensor_mkQ (N : Submodule R M) : exact lTensor_exact Q (LinearMap.exact_subtype_mkQ N) (Submodule.mkQ_surjective N) /-- The direct map in `rTensor.equiv` -/ -noncomputable def rTensor.toFun : +noncomputable def rTensor.toFun (hfg : Exact f g) : N ⊗[R] Q ⧸ range (rTensor Q f) →ₗ[R] P ⊗[R] Q := Submodule.liftQ _ (rTensor Q g) <| by rw [range_le_iff_comap, ← ker_comp, ← rTensor_comp, hfg.linearMap_comp_eq_zero, rTensor_zero, ker_zero] /-- The inverse map in `rTensor.equiv_of_rightInverse` (computably, given a right inverse) -/ -noncomputable def rTensor.inverse_of_rightInverse {h : P → N} (hgh : Function.RightInverse h g) : +noncomputable def rTensor.inverse_of_rightInverse {h : P → N} (hfg : Exact f g) + (hgh : Function.RightInverse h g) : P ⊗[R] Q →ₗ[R] N ⊗[R] Q ⧸ LinearMap.range (rTensor Q f) := TensorProduct.lift { toFun := fun p ↦ Submodule.mkQ _ ∘ₗ TensorProduct.mk R _ _ (h p) diff --git a/Mathlib/LinearAlgebra/TensorProduct/Subalgebra.lean b/Mathlib/LinearAlgebra/TensorProduct/Subalgebra.lean index 5e2c363f1116d..2ec0b351ea9e9 100644 --- a/Mathlib/LinearAlgebra/TensorProduct/Subalgebra.lean +++ b/Mathlib/LinearAlgebra/TensorProduct/Subalgebra.lean @@ -3,9 +3,10 @@ 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.LinearAlgebra.Dimension.Constructions +import Mathlib.LinearAlgebra.FreeModule.StrongRankCondition import Mathlib.LinearAlgebra.TensorProduct.Submodule import Mathlib.RingTheory.TensorProduct.Basic -import Mathlib.LinearAlgebra.FreeModule.StrongRankCondition /-! diff --git a/Mathlib/LinearAlgebra/TensorProduct/Submodule.lean b/Mathlib/LinearAlgebra/TensorProduct/Submodule.lean index eb444a275be7e..838f15025ec00 100644 --- a/Mathlib/LinearAlgebra/TensorProduct/Submodule.lean +++ b/Mathlib/LinearAlgebra/TensorProduct/Submodule.lean @@ -234,13 +234,13 @@ theorem comm_trans_rTensorOne : variable {M} in theorem mulLeftMap_eq_mulMap_comp {ι : Type*} [DecidableEq ι] (m : ι → M) : - mulLeftMap N m = mulMap M N ∘ₗ LinearMap.rTensor N (Finsupp.total ι M R m) ∘ₗ + mulLeftMap N m = mulMap M N ∘ₗ LinearMap.rTensor N (Finsupp.linearCombination R m) ∘ₗ (TensorProduct.finsuppScalarLeft R N ι).symm.toLinearMap := by ext; simp variable {N} in theorem mulRightMap_eq_mulMap_comp {ι : Type*} [DecidableEq ι] (n : ι → N) : - mulRightMap M n = mulMap M N ∘ₗ LinearMap.lTensor M (Finsupp.total ι N R n) ∘ₗ + mulRightMap M n = mulMap M N ∘ₗ LinearMap.lTensor M (Finsupp.linearCombination R n) ∘ₗ (TensorProduct.finsuppScalarRight R M ι).symm.toLinearMap := by ext; simp diff --git a/Mathlib/LinearAlgebra/TensorProduct/Vanishing.lean b/Mathlib/LinearAlgebra/TensorProduct/Vanishing.lean index 968e2a986f444..dbf016581b5a2 100644 --- a/Mathlib/LinearAlgebra/TensorProduct/Vanishing.lean +++ b/Mathlib/LinearAlgebra/TensorProduct/Vanishing.lean @@ -60,7 +60,7 @@ variable (R : Type u) [CommRing R] variable {M : Type u} [AddCommGroup M] [Module R M] variable {N : Type u} [AddCommGroup N] [Module R N] -open DirectSum LinearMap Function Submodule +open DirectSum LinearMap Function Submodule Finsupp namespace TensorProduct @@ -102,7 +102,7 @@ vanishes, then it vanishes trivially. -/ theorem vanishesTrivially_of_sum_tmul_eq_zero (hm : Submodule.span R (Set.range m) = ⊤) (hmn : ∑ i, m i ⊗ₜ n i = (0 : M ⊗[R] N)) : VanishesTrivially R m n := by -- Define a map $G \colon R^\iota \to M$ whose matrix entries are the $m_i$. It is surjective. - set G : (ι →₀ R) →ₗ[R] M := Finsupp.total ι M R m with hG + set G : (ι →₀ R) →ₗ[R] M := Finsupp.linearCombination R m with hG have G_basis_eq (i : ι) : G (Finsupp.single i 1) = m i := by simp [hG, toModule_lof] have G_surjective : Surjective G := by apply LinearMap.range_eq_top.mp @@ -154,7 +154,7 @@ theorem vanishesTrivially_of_sum_tmul_eq_zero (hm : Submodule.span R (Set.range · next h'x => rw [h'x, zero_smul] · rfl · rintro ⟨⟨⟨k, hk⟩, _⟩, _⟩ - simpa only [hG, Finsupp.total_apply, zero_smul, implies_true, Finsupp.sum_fintype] using + simpa only [hG, linearCombination_apply, zero_smul, implies_true, Finsupp.sum_fintype] using mem_ker.mp hk /-- **Equational criterion for vanishing** diff --git a/Mathlib/LinearAlgebra/Trace.lean b/Mathlib/LinearAlgebra/Trace.lean index 9bbcd7e816372..d8dfa8fb4f30b 100644 --- a/Mathlib/LinearAlgebra/Trace.lean +++ b/Mathlib/LinearAlgebra/Trace.lean @@ -16,21 +16,16 @@ See also `LinearAlgebra/Matrix/Trace.lean` for the trace of a matrix. ## Tags linear_map, trace, diagonal - -/ - noncomputable section universe u v w namespace LinearMap -open Matrix - -open FiniteDimensional - -open TensorProduct +open scoped Matrix +open FiniteDimensional TensorProduct section @@ -64,16 +59,16 @@ theorem traceAux_eq : traceAux R b = traceAux R c := rw [LinearMap.toMatrix_comp _ b, LinearMap.toMatrix_comp _ c] _ = Matrix.trace (LinearMap.toMatrix c c f) := by rw [LinearMap.comp_id, LinearMap.comp_id] -open scoped Classical - variable (M) +open Classical in /-- Trace of an endomorphism independent of basis. -/ def trace : (M →ₗ[R] M) →ₗ[R] R := if H : ∃ s : Finset M, Nonempty (Basis s R M) then traceAux R H.choose_spec.some else 0 variable {M} +open Classical in /-- Auxiliary lemma for `trace_eq_matrix_trace`. -/ theorem trace_eq_matrix_trace_of_finset {s : Finset M} (b : Basis s R M) (f : M →ₗ[R] M) : trace R M f = Matrix.trace (LinearMap.toMatrix b b f) := by @@ -84,15 +79,17 @@ theorem trace_eq_matrix_trace_of_finset {s : Finset M} (b : Basis s R M) (f : M theorem trace_eq_matrix_trace (f : M →ₗ[R] M) : trace R M f = Matrix.trace (LinearMap.toMatrix b b f) := by + classical rw [trace_eq_matrix_trace_of_finset R b.reindexFinsetRange, ← traceAux_def, ← traceAux_def, traceAux_eq R b b.reindexFinsetRange] -theorem trace_mul_comm (f g : M →ₗ[R] M) : trace R M (f * g) = trace R M (g * f) := - if H : ∃ s : Finset M, Nonempty (Basis s R M) then by - let ⟨s, ⟨b⟩⟩ := H +theorem trace_mul_comm (f g : M →ₗ[R] M) : trace R M (f * g) = trace R M (g * f) := by + classical + by_cases H : ∃ s : Finset M, Nonempty (Basis s R M) + · let ⟨s, ⟨b⟩⟩ := H simp_rw [trace_eq_matrix_trace R b, LinearMap.toMatrix_mul] apply Matrix.trace_mul_comm - else by rw [trace, dif_neg H, LinearMap.zero_apply, LinearMap.zero_apply] + · rw [trace, dif_neg H, LinearMap.zero_apply, LinearMap.zero_apply] lemma trace_mul_cycle (f g h : M →ₗ[R] M) : trace R M (f * g * h) = trace R M (h * f * g) := by diff --git a/Mathlib/Logic/Basic.lean b/Mathlib/Logic/Basic.lean index 40d2b6b3b4dc5..0dfbe0940f130 100644 --- a/Mathlib/Logic/Basic.lean +++ b/Mathlib/Logic/Basic.lean @@ -3,7 +3,6 @@ Copyright (c) 2016 Jeremy Avigad. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad, Leonardo de Moura -/ -import Mathlib.Init.Algebra.Classes import Mathlib.Tactic.Attr.Register import Mathlib.Tactic.Basic import Batteries.Logic @@ -11,6 +10,7 @@ import Batteries.Util.LibraryNote import Batteries.Tactic.Lint.Basic import Mathlib.Data.Nat.Notation import Mathlib.Data.Int.Notation +import Mathlib.Order.Defs /-! # Basic logic properties @@ -39,9 +39,6 @@ section Miscellany attribute [simp] cast_heq --- This can be removed once we move to Lean v4.11 -attribute [simp] insert_emptyc_eq - /-- An identity function with its main argument implicit. This will be printed as `hidden` even if it is applied to a large term, so it can be used for elision, as done in the `elide` and `unelide` tactics. -/ @@ -416,16 +413,13 @@ theorem eqRec_heq' {α : Sort*} {a' : α} {motive : (a : α) → a' = a → Sort HEq (@Eq.rec α a' motive p a t) p := by subst t; rfl -set_option autoImplicit true in -theorem rec_heq_of_heq {C : α → Sort*} {x : C a} {y : β} (e : a = b) (h : HEq x y) : - HEq (e ▸ x) y := by subst e; exact h +theorem rec_heq_of_heq {α β : Sort _} {a b : α} {C : α → Sort*} {x : C a} {y : β} + (e : a = b) (h : HEq x y) : HEq (e ▸ x) y := by subst e; exact h -set_option autoImplicit true in -theorem rec_heq_iff_heq {C : α → Sort*} {x : C a} {y : β} {e : a = b} : +theorem rec_heq_iff_heq {α β : Sort _} {a b : α} {C : α → Sort*} {x : C a} {y : β} {e : a = b} : HEq (e ▸ x) y ↔ HEq x y := by subst e; rfl -set_option autoImplicit true in -theorem heq_rec_iff_heq {C : α → Sort*} {x : β} {y : C a} {e : a = b} : +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 end Equality @@ -831,8 +825,6 @@ theorem exists_mem_of_exists (H : ∀ x, p x) : (∃ x, q x) → ∃ (x : _) (_ theorem exists_of_exists_mem : (∃ (x : _) (_ : p x), q x) → ∃ x, q x | ⟨x, _, hq⟩ => ⟨x, hq⟩ -theorem exists₂_imp : (∃ x h, P x h) → b ↔ ∀ x h, P x h → b := by simp - @[deprecated (since := "2024-03-23")] alias bex_of_exists := exists_mem_of_exists @[deprecated (since := "2024-03-23")] alias exists_of_bex := exists_of_exists_mem @[deprecated (since := "2024-03-23")] alias bex_imp := exists₂_imp diff --git a/Mathlib/Logic/Embedding/Basic.lean b/Mathlib/Logic/Embedding/Basic.lean index 0f91bfa54fc08..c52ae8f8e8e1d 100644 --- a/Mathlib/Logic/Embedding/Basic.lean +++ b/Mathlib/Logic/Embedding/Basic.lean @@ -85,9 +85,6 @@ instance Equiv.coeEmbedding : Coe (α ≃ β) (α ↪ β) := @[instance] abbrev Equiv.Perm.coeEmbedding : Coe (Equiv.Perm α) (α ↪ α) := Equiv.coeEmbedding --- Porting note : `theorem Equiv.coe_eq_to_embedding : ↑f = f.toEmbedding` is a --- syntactic tautology in Lean 4 - end Equiv namespace Function diff --git a/Mathlib/Logic/Embedding/Set.lean b/Mathlib/Logic/Embedding/Set.lean index bff9f99b31ff2..0c0ce8045a169 100644 --- a/Mathlib/Logic/Embedding/Set.lean +++ b/Mathlib/Logic/Embedding/Set.lean @@ -90,7 +90,7 @@ variable {α : Type*} subtypes `{x // p x} ⊕ {x // q x}` such that `¬ p x` is sent to the right, when `Disjoint p q`. -See also `Equiv.sumCompl`, for when `IsCompl p q`. -/ +See also `Equiv.sumCompl`, for when `IsCompl p q`. -/ @[simps apply] def subtypeOrEquiv (p q : α → Prop) [DecidablePred p] (h : Disjoint p q) : { x // p x ∨ q x } ≃ { x // p x } ⊕ { x // q x } where diff --git a/Mathlib/Logic/Encodable/Basic.lean b/Mathlib/Logic/Encodable/Basic.lean index d6cac938c8892..60412ec201292 100644 --- a/Mathlib/Logic/Encodable/Basic.lean +++ b/Mathlib/Logic/Encodable/Basic.lean @@ -47,7 +47,7 @@ class Encodable (α : Type*) where --explicitly in Lean4 /-- Decoding from ℕ to Option α-/ decode : ℕ → Option α - /-- Invariant relationship between encoding and decoding-/ + /-- Invariant relationship between encoding and decoding -/ encodek : ∀ a, decode (encode a) = some a attribute [simp] Encodable.encodek diff --git a/Mathlib/Logic/Encodable/Lattice.lean b/Mathlib/Logic/Encodable/Lattice.lean index d5457863486ba..61e01cc0053a4 100644 --- a/Mathlib/Logic/Encodable/Lattice.lean +++ b/Mathlib/Logic/Encodable/Lattice.lean @@ -39,7 +39,7 @@ theorem iUnion_decode₂_cases {f : β → Set α} {C : Set α → Prop} (H0 : C C (⋃ b ∈ decode₂ β n, f b) := match decode₂ β n with | none => by - simp only [Option.mem_def, iUnion_of_empty, iUnion_empty] + simp only [Option.mem_def, iUnion_of_empty, iUnion_empty, reduceCtorEq] apply H0 | some b => by convert H1 b diff --git a/Mathlib/Logic/Equiv/Basic.lean b/Mathlib/Logic/Equiv/Basic.lean index 73e695fc742af..895f65103bc7c 100644 --- a/Mathlib/Logic/Equiv/Basic.lean +++ b/Mathlib/Logic/Equiv/Basic.lean @@ -38,7 +38,7 @@ In this file we continue the work on equivalences begun in `Logic/Equiv/Defs.lea `eb : β₁ ≃ β₂` using `Prod.map`. More definitions of this kind can be found in other files. - E.g., `Data/Equiv/TransferInstance.lean` does it for many algebraic type classes like + E.g., `Logic/Equiv/TransferInstance.lean` does it for many algebraic type classes like `Group`, `Module`, etc. ## Tags @@ -46,17 +46,18 @@ In this file we continue the work on equivalences begun in `Logic/Equiv/Defs.lea equivalence, congruence, bijective map -/ -set_option autoImplicit true - -universe u +universe u v w z open Function +-- Unless required to be `Type*`, all variables in this file are `Sort*` +variable {α α₁ α₂ β β₁ β₂ γ γ₁ γ₂ δ : Sort*} + namespace Equiv /-- `PProd α β` is equivalent to `α × β` -/ @[simps apply symm_apply] -def pprodEquivProd : PProd α β ≃ α × β where +def pprodEquivProd {α β} : PProd α β ≃ α × β where toFun x := (x.1, x.2) invFun x := ⟨x.1, x.2⟩ left_inv := fun _ => rfl @@ -74,13 +75,13 @@ def pprodCongr (e₁ : α ≃ β) (e₂ : γ ≃ δ) : PProd α γ ≃ PProd β /-- Combine two equivalences using `PProd` in the domain and `Prod` in the codomain. -/ @[simps! apply symm_apply] -def pprodProd (ea : α₁ ≃ α₂) (eb : β₁ ≃ β₂) : +def pprodProd {α₂ β₂} (ea : α₁ ≃ α₂) (eb : β₁ ≃ β₂) : PProd α₁ β₁ ≃ α₂ × β₂ := (ea.pprodCongr eb).trans pprodEquivProd /-- Combine two equivalences using `PProd` in the codomain and `Prod` in the domain. -/ @[simps! apply symm_apply] -def prodPProd (ea : α₁ ≃ α₂) (eb : β₁ ≃ β₂) : +def prodPProd {α₁ β₁} (ea : α₁ ≃ α₂) (eb : β₁ ≃ β₂) : α₁ × β₁ ≃ PProd α₂ β₂ := (ea.symm.pprodProd eb.symm).symm @@ -93,11 +94,11 @@ def pprodEquivProdPLift : PProd α β ≃ PLift α × PLift β := `Prod.map` as an equivalence. -/ -- Porting note: in Lean 3 there was also a @[congr] tag @[simps (config := .asFn) apply] -def prodCongr (e₁ : α₁ ≃ α₂) (e₂ : β₁ ≃ β₂) : α₁ × β₁ ≃ α₂ × β₂ := +def prodCongr {α₁ α₂ β₁ β₂} (e₁ : α₁ ≃ α₂) (e₂ : β₁ ≃ β₂) : α₁ × β₁ ≃ α₂ × β₂ := ⟨Prod.map e₁ e₂, Prod.map e₁.symm e₂.symm, fun ⟨a, b⟩ => by simp, fun ⟨a, b⟩ => by simp⟩ @[simp] -theorem prodCongr_symm (e₁ : α₁ ≃ α₂) (e₂ : β₁ ≃ β₂) : +theorem prodCongr_symm {α₁ α₂ β₁ β₂} (e₁ : α₁ ≃ α₂) (e₂ : β₁ ≃ β₂) : (prodCongr e₁ e₂).symm = prodCongr e₁.symm e₂.symm := rfl @@ -111,7 +112,7 @@ theorem coe_prodComm (α β) : (⇑(prodComm α β) : α × β → β × α) = P rfl @[simp] -theorem prodComm_apply (x : α × β) : prodComm α β x = x.swap := +theorem prodComm_apply {α β} (x : α × β) : prodComm α β x = x.swap := rfl @[simp] @@ -126,14 +127,14 @@ def prodAssoc (α β γ) : (α × β) × γ ≃ α × β × γ := /-- Four-way commutativity of `prod`. The name matches `mul_mul_mul_comm`. -/ @[simps apply] -def prodProdProdComm (α β γ δ : Type*) : (α × β) × γ × δ ≃ (α × γ) × β × δ where +def prodProdProdComm (α β γ δ) : (α × β) × γ × δ ≃ (α × γ) × β × δ where toFun abcd := ((abcd.1.1, abcd.2.1), (abcd.1.2, abcd.2.2)) invFun acbd := ((acbd.1.1, acbd.2.1), (acbd.1.2, acbd.2.2)) left_inv := fun ⟨⟨_a, _b⟩, ⟨_c, _d⟩⟩ => rfl right_inv := fun ⟨⟨_a, _c⟩, ⟨_b, _d⟩⟩ => rfl @[simp] -theorem prodProdProdComm_symm (α β γ δ : Type*) : +theorem prodProdProdComm_symm (α β γ δ) : (prodProdProdComm α β γ δ).symm = prodProdProdComm α γ β δ := rfl @@ -169,15 +170,14 @@ def prodUnique (α β) [Unique β] : α × β ≃ α := ((Equiv.refl α).prodCongr <| equivPUnit.{_,1} β).trans <| prodPUnit α @[simp] -theorem coe_prodUnique [Unique β] : (⇑(prodUnique α β) : α × β → α) = Prod.fst := +theorem coe_prodUnique {α β} [Unique β] : (⇑(prodUnique α β) : α × β → α) = Prod.fst := rfl -theorem prodUnique_apply [Unique β] (x : α × β) : prodUnique α β x = x.1 := +theorem prodUnique_apply {α β} [Unique β] (x : α × β) : prodUnique α β x = x.1 := rfl @[simp] -theorem prodUnique_symm_apply [Unique β] (x : α) : - (prodUnique α β).symm x = (x, default) := +theorem prodUnique_symm_apply {α β} [Unique β] (x : α) : (prodUnique α β).symm x = (x, default) := rfl /-- Any `Unique` type is a left identity for type product up to equivalence. -/ @@ -185,14 +185,14 @@ def uniqueProd (α β) [Unique β] : β × α ≃ α := ((equivPUnit.{_,1} β).prodCongr <| Equiv.refl α).trans <| punitProd α @[simp] -theorem coe_uniqueProd [Unique β] : (⇑(uniqueProd α β) : β × α → α) = Prod.snd := +theorem coe_uniqueProd {α β} [Unique β] : (⇑(uniqueProd α β) : β × α → α) = Prod.snd := rfl -theorem uniqueProd_apply [Unique β] (x : β × α) : uniqueProd α β x = x.2 := +theorem uniqueProd_apply {α β} [Unique β] (x : β × α) : uniqueProd α β x = x.2 := rfl @[simp] -theorem uniqueProd_symm_apply [Unique β] (x : α) : +theorem uniqueProd_symm_apply {α β} [Unique β] (x : α) : (uniqueProd α β).symm x = (default, x) := rfl @@ -202,16 +202,16 @@ def sigmaUnique (α) (β : α → Type*) [∀ a, Unique (β a)] : (a : α) × ( (Equiv.sigmaCongrRight fun a ↦ equivPUnit.{_,1} (β a)).trans <| sigmaPUnit α @[simp] -theorem coe_sigmaUnique {β : α → Type*} [∀ a, Unique (β a)] : +theorem coe_sigmaUnique {α} {β : α → Type*} [∀ a, Unique (β a)] : (⇑(sigmaUnique α β) : (a : α) × (β a) → α) = Sigma.fst := rfl -theorem sigmaUnique_apply {β : α → Type*} [∀ a, Unique (β a)] (x : (a : α) × β a) : +theorem sigmaUnique_apply {α} {β : α → Type*} [∀ a, Unique (β a)] (x : (a : α) × β a) : sigmaUnique α β x = x.1 := rfl @[simp] -theorem sigmaUnique_symm_apply {β : α → Type*} [∀ a, Unique (β a)] (x : α) : +theorem sigmaUnique_symm_apply {α} {β : α → Type*} [∀ a, Unique (β a)] (x : α) : (sigmaUnique α β).symm x = ⟨x, default⟩ := rfl @@ -246,7 +246,7 @@ def psumEquivSum (α β) : α ⊕' β ≃ α ⊕ β where /-- If `α ≃ α'` and `β ≃ β'`, then `α ⊕ β ≃ α' ⊕ β'`. This is `Sum.map` as an equivalence. -/ @[simps apply] -def sumCongr (ea : α₁ ≃ α₂) (eb : β₁ ≃ β₂) : α₁ ⊕ β₁ ≃ α₂ ⊕ β₂ := +def sumCongr {α₁ α₂ β₁ β₂} (ea : α₁ ≃ α₂) (eb : β₁ ≃ β₂) : α₁ ⊕ β₁ ≃ α₂ ⊕ β₂ := ⟨Sum.map ea eb, Sum.map ea.symm eb.symm, fun x => by simp, fun x => by simp⟩ /-- If `α ≃ α'` and `β ≃ β'`, then `α ⊕' β ≃ α' ⊕' β'`. -/ @@ -257,33 +257,35 @@ def psumCongr (e₁ : α ≃ β) (e₂ : γ ≃ δ) : α ⊕' γ ≃ β ⊕' δ right_inv := by rintro (x | x) <;> simp /-- Combine two `Equiv`s using `PSum` in the domain and `Sum` in the codomain. -/ -def psumSum (ea : α₁ ≃ α₂) (eb : β₁ ≃ β₂) : +def psumSum {α₂ β₂} (ea : α₁ ≃ α₂) (eb : β₁ ≃ β₂) : α₁ ⊕' β₁ ≃ α₂ ⊕ β₂ := (ea.psumCongr eb).trans (psumEquivSum _ _) /-- Combine two `Equiv`s using `Sum` in the domain and `PSum` in the codomain. -/ -def sumPSum (ea : α₁ ≃ α₂) (eb : β₁ ≃ β₂) : +def sumPSum {α₁ β₁} (ea : α₁ ≃ α₂) (eb : β₁ ≃ β₂) : α₁ ⊕ β₁ ≃ α₂ ⊕' β₂ := (ea.symm.psumSum eb.symm).symm @[simp] -theorem sumCongr_trans (e : α₁ ≃ β₁) (f : α₂ ≃ β₂) (g : β₁ ≃ γ₁) (h : β₂ ≃ γ₂) : +theorem sumCongr_trans {α₁ α₂ β₁ β₂ γ₁ γ₂} (e : α₁ ≃ β₁) (f : α₂ ≃ β₂) (g : β₁ ≃ γ₁) (h : β₂ ≃ γ₂) : (Equiv.sumCongr e f).trans (Equiv.sumCongr g h) = Equiv.sumCongr (e.trans g) (f.trans h) := by ext i cases i <;> rfl @[simp] -theorem sumCongr_symm (e : α ≃ β) (f : γ ≃ δ) : +theorem sumCongr_symm {α β γ δ} (e : α ≃ β) (f : γ ≃ δ) : (Equiv.sumCongr e f).symm = Equiv.sumCongr e.symm f.symm := rfl @[simp] -theorem sumCongr_refl : Equiv.sumCongr (Equiv.refl α) (Equiv.refl β) = Equiv.refl (α ⊕ β) := by +theorem sumCongr_refl {α β} : + Equiv.sumCongr (Equiv.refl α) (Equiv.refl β) = Equiv.refl (α ⊕ β) := by ext i cases i <;> rfl /-- A subtype of a sum is equivalent to a sum of subtypes. -/ -def subtypeSum {p : α ⊕ β → Prop} : {c // p c} ≃ {a // p (Sum.inl a)} ⊕ {b // p (Sum.inr b)} where +def subtypeSum {α β} {p : α ⊕ β → Prop} : + {c // p c} ≃ {a // p (Sum.inl a)} ⊕ {b // p (Sum.inr b)} where toFun c := match h : c.1 with | Sum.inl a => Sum.inl ⟨a, h ▸ c.2⟩ | Sum.inr b => Sum.inr ⟨b, h ▸ c.2⟩ @@ -296,25 +298,25 @@ def subtypeSum {p : α ⊕ β → Prop} : {c // p c} ≃ {a // p (Sum.inl a)} namespace Perm /-- Combine a permutation of `α` and of `β` into a permutation of `α ⊕ β`. -/ -abbrev sumCongr (ea : Equiv.Perm α) (eb : Equiv.Perm β) : Equiv.Perm (α ⊕ β) := +abbrev sumCongr {α β} (ea : Equiv.Perm α) (eb : Equiv.Perm β) : Equiv.Perm (α ⊕ β) := Equiv.sumCongr ea eb @[simp] -theorem sumCongr_apply (ea : Equiv.Perm α) (eb : Equiv.Perm β) (x : α ⊕ β) : +theorem sumCongr_apply {α β} (ea : Equiv.Perm α) (eb : Equiv.Perm β) (x : α ⊕ β) : sumCongr ea eb x = Sum.map (⇑ea) (⇑eb) x := Equiv.sumCongr_apply ea eb x -- Porting note: it seems the general theorem about `Equiv` is now applied, so there's no need -- to have this version also have `@[simp]`. Similarly for below. -theorem sumCongr_trans (e : Equiv.Perm α) (f : Equiv.Perm β) (g : Equiv.Perm α) +theorem sumCongr_trans {α β} (e : Equiv.Perm α) (f : Equiv.Perm β) (g : Equiv.Perm α) (h : Equiv.Perm β) : (sumCongr e f).trans (sumCongr g h) = sumCongr (e.trans g) (f.trans h) := Equiv.sumCongr_trans e f g h -theorem sumCongr_symm (e : Equiv.Perm α) (f : Equiv.Perm β) : +theorem sumCongr_symm {α β} (e : Equiv.Perm α) (f : Equiv.Perm β) : (sumCongr e f).symm = sumCongr e.symm f.symm := Equiv.sumCongr_symm e f -theorem sumCongr_refl : sumCongr (Equiv.refl α) (Equiv.refl β) = Equiv.refl (α ⊕ β) := +theorem sumCongr_refl {α β} : sumCongr (Equiv.refl α) (Equiv.refl β) = Equiv.refl (α ⊕ β) := Equiv.sumCongr_refl end Perm @@ -341,15 +343,15 @@ def sumAssoc (α β γ) : (α ⊕ β) ⊕ γ ≃ α ⊕ (β ⊕ γ) := rintro (_ | ⟨_ | _⟩) <;> rfl⟩ @[simp] -theorem sumAssoc_apply_inl_inl (a) : sumAssoc α β γ (inl (inl a)) = inl a := +theorem sumAssoc_apply_inl_inl {α β γ} (a) : sumAssoc α β γ (inl (inl a)) = inl a := rfl @[simp] -theorem sumAssoc_apply_inl_inr (b) : sumAssoc α β γ (inl (inr b)) = inr (inl b) := +theorem sumAssoc_apply_inl_inr {α β γ} (b) : sumAssoc α β γ (inl (inr b)) = inr (inl b) := rfl @[simp] -theorem sumAssoc_apply_inr (c) : sumAssoc α β γ (inr c) = inr (inr c) := +theorem sumAssoc_apply_inr {α β γ} (c) : sumAssoc α β γ (inr c) = inr (inr c) := rfl @[simp] @@ -365,6 +367,26 @@ theorem sumAssoc_symm_apply_inr_inl {α β γ} (b) : theorem sumAssoc_symm_apply_inr_inr {α β γ} (c) : (sumAssoc α β γ).symm (inr (inr c)) = inr c := rfl +/-- Four-way commutativity of `sum`. The name matches `add_add_add_comm`. -/ +@[simps apply] +def sumSumSumComm (α β γ δ) : (α ⊕ β) ⊕ γ ⊕ δ ≃ (α ⊕ γ) ⊕ β ⊕ δ where + toFun := + (sumAssoc (α ⊕ γ) β δ) ∘ (Sum.map (sumAssoc α γ β).symm (@id δ)) + ∘ (Sum.map (Sum.map (@id α) (sumComm β γ)) (@id δ)) + ∘ (Sum.map (sumAssoc α β γ) (@id δ)) + ∘ (sumAssoc (α ⊕ β) γ δ).symm + invFun := + (sumAssoc (α ⊕ β) γ δ) ∘ (Sum.map (sumAssoc α β γ).symm (@id δ)) + ∘ (Sum.map (Sum.map (@id α) (sumComm β γ).symm) (@id δ)) + ∘ (Sum.map (sumAssoc α γ β) (@id δ)) + ∘ (sumAssoc (α ⊕ γ) β δ).symm + left_inv x := by rcases x with ((a | b) | (c | d)) <;> simp + right_inv x := by rcases x with ((a | c) | (b | d)) <;> simp + +@[simp] +theorem sumSumSumComm_symm (α β γ δ) : (sumSumSumComm α β γ δ).symm = sumSumSumComm α γ β δ := + rfl + /-- Sum with `IsEmpty` is equivalent to the original type. -/ @[simps symm_apply] def sumEmpty (α β) [IsEmpty β] : α ⊕ β ≃ α where @@ -377,7 +399,7 @@ def sumEmpty (α β) [IsEmpty β] : α ⊕ β ≃ α where right_inv _ := rfl @[simp] -theorem sumEmpty_apply_inl [IsEmpty β] (a : α) : sumEmpty α β (Sum.inl a) = a := +theorem sumEmpty_apply_inl {α β} [IsEmpty β] (a : α) : sumEmpty α β (Sum.inl a) = a := rfl /-- The sum of `IsEmpty` with any type is equivalent to that type. -/ @@ -386,7 +408,7 @@ def emptySum (α β) [IsEmpty α] : α ⊕ β ≃ β := (sumComm _ _).trans <| sumEmpty _ _ @[simp] -theorem emptySum_apply_inr [IsEmpty α] (b : β) : emptySum α β (Sum.inr b) = b := +theorem emptySum_apply_inr {α β} [IsEmpty α] (b : β) : emptySum α β (Sum.inr b) = b := rfl /-- `Option α` is equivalent to `α ⊕ PUnit` -/ @@ -396,23 +418,23 @@ def optionEquivSumPUnit (α) : Option α ≃ α ⊕ PUnit := fun s => by rcases s with (_ | ⟨⟨⟩⟩) <;> rfl⟩ @[simp] -theorem optionEquivSumPUnit_none : optionEquivSumPUnit α none = Sum.inr PUnit.unit := +theorem optionEquivSumPUnit_none {α} : optionEquivSumPUnit α none = Sum.inr PUnit.unit := rfl @[simp] -theorem optionEquivSumPUnit_some (a) : optionEquivSumPUnit α (some a) = Sum.inl a := +theorem optionEquivSumPUnit_some {α} (a) : optionEquivSumPUnit α (some a) = Sum.inl a := rfl @[simp] -theorem optionEquivSumPUnit_coe (a : α) : optionEquivSumPUnit α a = Sum.inl a := +theorem optionEquivSumPUnit_coe {α} (a : α) : optionEquivSumPUnit α a = Sum.inl a := rfl @[simp] -theorem optionEquivSumPUnit_symm_inl (a) : (optionEquivSumPUnit α).symm (Sum.inl a) = a := +theorem optionEquivSumPUnit_symm_inl {α} (a) : (optionEquivSumPUnit α).symm (Sum.inl a) = a := rfl @[simp] -theorem optionEquivSumPUnit_symm_inr (a) : (optionEquivSumPUnit α).symm (Sum.inr a) = none := +theorem optionEquivSumPUnit_symm_inr {α} (a) : (optionEquivSumPUnit α).symm (Sum.inr a) = none := rfl /-- The set of `x : Option α` such that `isSome x` is equivalent to `α`. -/ @@ -426,7 +448,7 @@ def optionIsSomeEquiv (α) : { x : Option α // x.isSome } ≃ α where /-- The product over `Option α` of `β a` is the binary product of the product over `α` of `β (some α)` and `β none` -/ @[simps] -def piOptionEquivProd {β : Option α → Type*} : +def piOptionEquivProd {α} {β : Option α → Type*} : (∀ a : Option α, β a) ≃ β none × ∀ a : α, β (some a) where toFun f := (f none, fun a => f (some a)) invFun x a := Option.casesOn a x.fst x.snd @@ -437,7 +459,7 @@ def piOptionEquivProd {β : Option α → Type*} : `β` to be types from the same universe, so it cannot be used directly to transfer theorems about sigma types to theorems about sum types. In many cases one can use `ULift` to work around this difficulty. -/ -def sumEquivSigmaBool (α β : Type u) : α ⊕ β ≃ Σ b : Bool, b.casesOn α β := +def sumEquivSigmaBool (α β) : α ⊕ β ≃ Σ b : Bool, b.casesOn α β := ⟨fun s => s.elim (fun x => ⟨false, x⟩) fun x => ⟨true, x⟩, fun s => match s with | ⟨false, a⟩ => inl a @@ -472,7 +494,7 @@ the sum of the two subtypes `{a // p a}` and its complement `{a // ¬ p a}` is naturally equivalent to `α`. See `subtypeOrEquiv` for sum types over subtypes `{x // p x}` and `{x // q x}` -that are not necessarily `IsCompl p q`. -/ +that are not necessarily `IsCompl p q`. -/ def sumCompl {α : Type*} (p : α → Prop) [DecidablePred p] : { a // p a } ⊕ { a // ¬p a } ≃ α where toFun := Sum.elim Subtype.val Subtype.val @@ -486,32 +508,32 @@ def sumCompl {α : Type*} (p : α → Prop) [DecidablePred p] : split_ifs <;> rfl @[simp] -theorem sumCompl_apply_inl (p : α → Prop) [DecidablePred p] (x : { a // p a }) : +theorem sumCompl_apply_inl {α} (p : α → Prop) [DecidablePred p] (x : { a // p a }) : sumCompl p (Sum.inl x) = x := rfl @[simp] -theorem sumCompl_apply_inr (p : α → Prop) [DecidablePred p] (x : { a // ¬p a }) : +theorem sumCompl_apply_inr {α} (p : α → Prop) [DecidablePred p] (x : { a // ¬p a }) : sumCompl p (Sum.inr x) = x := rfl @[simp] -theorem sumCompl_apply_symm_of_pos (p : α → Prop) [DecidablePred p] (a : α) (h : p a) : +theorem sumCompl_apply_symm_of_pos {α} (p : α → Prop) [DecidablePred p] (a : α) (h : p a) : (sumCompl p).symm a = Sum.inl ⟨a, h⟩ := dif_pos h @[simp] -theorem sumCompl_apply_symm_of_neg (p : α → Prop) [DecidablePred p] (a : α) (h : ¬p a) : +theorem sumCompl_apply_symm_of_neg {α} (p : α → Prop) [DecidablePred p] (a : α) (h : ¬p a) : (sumCompl p).symm a = Sum.inr ⟨a, h⟩ := dif_neg h /-- Combines an `Equiv` between two subtypes with an `Equiv` between their complements to form a permutation. -/ -def subtypeCongr {p q : α → Prop} [DecidablePred p] [DecidablePred q] +def subtypeCongr {α} {p q : α → Prop} [DecidablePred p] [DecidablePred q] (e : { x // p x } ≃ { x // q x }) (f : { x // ¬p x } ≃ { x // ¬q x }) : Perm α := (sumCompl p).symm.trans ((sumCongr e f).trans (sumCompl q)) -variable {p : ε → Prop} [DecidablePred p] +variable {ε : Type*} {p : ε → Prop} [DecidablePred p] variable (ep ep' : Perm { a // p a }) (en en' : Perm { a // ¬p a }) /-- Combining permutations on `ε` that permute only inside or outside the subtype @@ -623,7 +645,7 @@ theorem piComm_symm {φ : α → β → Sort*} : (piComm φ).symm = (piComm <| s to the type of dependent functions of two arguments (i.e., functions to the space of functions). This is `Sigma.curry` and `Sigma.uncurry` together as an equiv. -/ -def piCurry {β : α → Type*} (γ : ∀ a, β a → Type*) : +def piCurry {α} {β : α → Type*} (γ : ∀ a, β a → Type*) : (∀ x : Σ i, β i, γ x.1 x.2) ≃ ∀ a b, γ a b where toFun := Sigma.curry invFun := Sigma.uncurry @@ -631,12 +653,12 @@ def piCurry {β : α → Type*} (γ : ∀ a, β a → Type*) : right_inv := Sigma.curry_uncurry -- `simps` overapplies these but `simps (config := .asFn)` under-applies them -@[simp] theorem piCurry_apply {β : α → Type*} (γ : ∀ a, β a → Type*) +@[simp] theorem piCurry_apply {α} {β : α → Type*} (γ : ∀ a, β a → Type*) (f : ∀ x : Σ i, β i, γ x.1 x.2) : piCurry γ f = Sigma.curry f := rfl -@[simp] theorem piCurry_symm_apply {β : α → Type*} (γ : ∀ a, β a → Type*) (f : ∀ a b, γ a b) : +@[simp] theorem piCurry_symm_apply {α} {β : α → Type*} (γ : ∀ a, β a → Type*) (f : ∀ a b, γ a b) : (piCurry γ).symm f = Sigma.uncurry f := rfl @@ -644,7 +666,7 @@ end section prodCongr -variable (e : α₁ → β₁ ≃ β₂) +variable {α₁ α₂ β₁ β₂ : Type*} (e : α₁ → β₁ ≃ β₂) /-- A family of equivalences `∀ (a : α₁), β₁ ≃ β₂` generates an equivalence between `β₁ × α₁` and `β₂ × α₁`. -/ @@ -716,7 +738,8 @@ theorem sigmaEquivProd_sigmaCongrRight : -- See also `Equiv.ofPreimageEquiv`. /-- A family of equivalences between fibers gives an equivalence between domains. -/ @[simps!] -def ofFiberEquiv {f : α → γ} {g : β → γ} (e : ∀ c, { a // f a = c } ≃ { b // g b = c }) : α ≃ β := +def ofFiberEquiv {α β γ} {f : α → γ} {g : β → γ} + (e : ∀ c, { a // f a = c } ≃ { b // g b = c }) : α ≃ β := (sigmaFiberEquiv f).symm.trans <| (Equiv.sigmaCongrRight e).trans (sigmaFiberEquiv g) theorem ofFiberEquiv_map {α β γ} {f : α → γ} {g : β → γ} @@ -741,7 +764,7 @@ end prodCongr namespace Perm -variable [DecidableEq α₁] (a : α₁) (e : Perm β₁) +variable {α₁ β₁ : Type*} [DecidableEq α₁] (a : α₁) (e : Perm β₁) /-- `prodExtendRight a e` extends `e : Perm β` to `Perm (α × β)` by sending `(a, b)` to `(a, e b)` and keeping the other `(a', b)` fixed. -/ @@ -801,7 +824,8 @@ open Sum /-- The type of dependent functions on a sum type `ι ⊕ ι'` is equivalent to the type of pairs of functions on `ι` and on `ι'`. This is a dependent version of `Equiv.sumArrowEquivProdArrow`. -/ @[simps] -def sumPiEquivProdPi (π : ι ⊕ ι' → Type*) : (∀ i, π i) ≃ (∀ i, π (inl i)) × ∀ i', π (inr i') where +def sumPiEquivProdPi {ι ι'} (π : ι ⊕ ι' → Type*) : + (∀ i, π i) ≃ (∀ i, π (inl i)) × ∀ i', π (inr i') where toFun f := ⟨fun i => f (inl i), fun i' => f (inr i')⟩ invFun g := Sum.rec g.1 g.2 left_inv f := by ext (i | i) <;> rfl @@ -810,7 +834,7 @@ def sumPiEquivProdPi (π : ι ⊕ ι' → Type*) : (∀ i, π i) ≃ (∀ i, π /-- The equivalence between a product of two dependent functions types and a single dependent function type. Basically a symmetric version of `Equiv.sumPiEquivProdPi`. -/ @[simps!] -def prodPiEquivSumPi (π : ι → Type u) (π' : ι' → Type u) : +def prodPiEquivSumPi {ι ι'} (π : ι → Type u) (π' : ι' → Type u) : ((∀ i, π i) × ∀ i', π' i') ≃ ∀ i, Sum.elim π π' i := sumPiEquivProdPi (Sum.elim π π') |>.symm @@ -822,22 +846,22 @@ def sumArrowEquivProdArrow (α β γ : Type*) : (α ⊕ β → γ) ≃ (α → rfl⟩ @[simp] -theorem sumArrowEquivProdArrow_apply_fst (f : α ⊕ β → γ) (a : α) : +theorem sumArrowEquivProdArrow_apply_fst {α β γ} (f : α ⊕ β → γ) (a : α) : (sumArrowEquivProdArrow α β γ f).1 a = f (inl a) := rfl @[simp] -theorem sumArrowEquivProdArrow_apply_snd (f : α ⊕ β → γ) (b : β) : +theorem sumArrowEquivProdArrow_apply_snd {α β γ} (f : α ⊕ β → γ) (b : β) : (sumArrowEquivProdArrow α β γ f).2 b = f (inr b) := rfl @[simp] -theorem sumArrowEquivProdArrow_symm_apply_inl (f : α → γ) (g : β → γ) (a : α) : +theorem sumArrowEquivProdArrow_symm_apply_inl {α β γ} (f : α → γ) (g : β → γ) (a : α) : ((sumArrowEquivProdArrow α β γ).symm (f, g)) (inl a) = f a := rfl @[simp] -theorem sumArrowEquivProdArrow_symm_apply_inr (f : α → γ) (g : β → γ) (b : β) : +theorem sumArrowEquivProdArrow_symm_apply_inr {α β γ} (f : α → γ) (g : β → γ) (b : β) : ((sumArrowEquivProdArrow α β γ).symm (f, g)) (inr b) = g b := rfl @@ -848,55 +872,55 @@ def sumProdDistrib (α β γ) : (α ⊕ β) × γ ≃ α × γ ⊕ β × γ := rintro ⟨_ | _, _⟩ <;> rfl, by rintro (⟨_, _⟩ | ⟨_, _⟩) <;> rfl⟩ @[simp] -theorem sumProdDistrib_apply_left (a : α) (c : γ) : +theorem sumProdDistrib_apply_left {α β γ} (a : α) (c : γ) : sumProdDistrib α β γ (Sum.inl a, c) = Sum.inl (a, c) := rfl @[simp] -theorem sumProdDistrib_apply_right (b : β) (c : γ) : +theorem sumProdDistrib_apply_right {α β γ} (b : β) (c : γ) : sumProdDistrib α β γ (Sum.inr b, c) = Sum.inr (b, c) := rfl @[simp] -theorem sumProdDistrib_symm_apply_left (a : α × γ) : +theorem sumProdDistrib_symm_apply_left {α β γ} (a : α × γ) : (sumProdDistrib α β γ).symm (inl a) = (inl a.1, a.2) := rfl @[simp] -theorem sumProdDistrib_symm_apply_right (b : β × γ) : +theorem sumProdDistrib_symm_apply_right {α β γ} (b : β × γ) : (sumProdDistrib α β γ).symm (inr b) = (inr b.1, b.2) := rfl /-- Type product is left distributive with respect to type sum up to an equivalence. -/ -def prodSumDistrib (α β γ : Type*) : α × (β ⊕ γ) ≃ (α × β) ⊕ (α × γ) := +def prodSumDistrib (α β γ) : α × (β ⊕ γ) ≃ (α × β) ⊕ (α × γ) := calc α × (β ⊕ γ) ≃ (β ⊕ γ) × α := prodComm _ _ _ ≃ (β × α) ⊕ (γ × α) := sumProdDistrib _ _ _ _ ≃ (α × β) ⊕ (α × γ) := sumCongr (prodComm _ _) (prodComm _ _) @[simp] -theorem prodSumDistrib_apply_left (a : α) (b : β) : +theorem prodSumDistrib_apply_left {α β γ} (a : α) (b : β) : prodSumDistrib α β γ (a, Sum.inl b) = Sum.inl (a, b) := rfl @[simp] -theorem prodSumDistrib_apply_right (a : α) (c : γ) : +theorem prodSumDistrib_apply_right {α β γ} (a : α) (c : γ) : prodSumDistrib α β γ (a, Sum.inr c) = Sum.inr (a, c) := rfl @[simp] -theorem prodSumDistrib_symm_apply_left (a : α × β) : +theorem prodSumDistrib_symm_apply_left {α β γ} (a : α × β) : (prodSumDistrib α β γ).symm (inl a) = (a.1, inl a.2) := rfl @[simp] -theorem prodSumDistrib_symm_apply_right (a : α × γ) : +theorem prodSumDistrib_symm_apply_right {α β γ} (a : α × γ) : (prodSumDistrib α β γ).symm (inr a) = (a.1, inr a.2) := rfl /-- An indexed sum of disjoint sums of types is equivalent to the sum of the indexed sums. -/ @[simps] -def sigmaSumDistrib (α β : ι → Type*) : +def sigmaSumDistrib {ι} (α β : ι → Type*) : (Σ i, α i ⊕ β i) ≃ (Σ i, α i) ⊕ (Σ i, β i) := ⟨fun p => p.2.map (Sigma.mk p.1) (Sigma.mk p.1), Sum.elim (Sigma.map id fun _ => Sum.inl) (Sigma.map id fun _ => Sum.inr), fun p => by @@ -904,7 +928,8 @@ def sigmaSumDistrib (α β : ι → Type*) : /-- The product of an indexed sum of types (formally, a `Sigma`-type `Σ i, α i`) by a type `β` is equivalent to the sum of products `Σ i, (α i × β)`. -/ -def sigmaProdDistrib (α : ι → Type*) (β : Type*) : (Σ i, α i) × β ≃ Σ i, α i × β := +@[simps apply symm_apply] +def sigmaProdDistrib {ι} (α : ι → Type*) (β) : (Σ i, α i) × β ≃ Σ i, α i × β := ⟨fun p => ⟨p.1.1, (p.1.2, p.2)⟩, fun p => (⟨p.1, p.2.1⟩, p.2.2), fun p => by rcases p with ⟨⟨_, _⟩, _⟩ rfl, fun p => by @@ -963,7 +988,7 @@ def intEquivNatSumNat : ℤ ≃ ℕ ⊕ ℕ where end /-- An equivalence between `α` and `β` generates an equivalence between `List α` and `List β`. -/ -def listEquivOfEquiv (e : α ≃ β) : List α ≃ List β where +def listEquivOfEquiv {α β} (e : α ≃ β) : List α ≃ List β where toFun := List.map e invFun := List.map e.symm left_inv l := by rw [List.map_map, e.symm_comp_self, List.map_id] @@ -997,7 +1022,7 @@ def subtypeEquiv {p : α → Prop} {q : β → Prop} (e : α ≃ β) (h : ∀ a, left_inv a := Subtype.ext <| by simp right_inv b := Subtype.ext <| by simp -lemma coe_subtypeEquiv_eq_map {X Y : Type*} {p : X → Prop} {q : Y → Prop} (e : X ≃ Y) +lemma coe_subtypeEquiv_eq_map {X Y} {p : X → Prop} {q : Y → Prop} (e : X ≃ Y) (h : ∀ x, p x ↔ q (e x)) : ⇑(e.subtypeEquiv h) = Subtype.map e (h · |>.mp) := rfl @@ -1076,25 +1101,25 @@ def subtypeSubtypeEquivSubtypeInter {α : Type u} (p q : α → Prop) : /-- If the outer subtype has more restrictive predicate than the inner one, then we can drop the latter. -/ @[simps!] -def subtypeSubtypeEquivSubtype {p q : α → Prop} (h : ∀ {x}, q x → p x) : +def subtypeSubtypeEquivSubtype {α} {p q : α → Prop} (h : ∀ {x}, q x → p x) : { x : Subtype p // q x.1 } ≃ Subtype q := (subtypeSubtypeEquivSubtypeInter p _).trans <| subtypeEquivRight fun _ => and_iff_right_of_imp h /-- If a proposition holds for all elements, then the subtype is equivalent to the original type. -/ @[simps apply symm_apply] -def subtypeUnivEquiv {p : α → Prop} (h : ∀ x, p x) : Subtype p ≃ α := +def subtypeUnivEquiv {α} {p : α → Prop} (h : ∀ x, p x) : Subtype p ≃ α := ⟨fun x => x, fun x => ⟨x, h x⟩, fun _ => Subtype.eq rfl, fun _ => rfl⟩ /-- A subtype of a sigma-type is a sigma-type over a subtype. -/ -def subtypeSigmaEquiv (p : α → Type v) (q : α → Prop) : { y : Sigma p // q y.1 } ≃ Σ x : +def subtypeSigmaEquiv {α} (p : α → Type v) (q : α → Prop) : { y : Sigma p // q y.1 } ≃ Σ x : Subtype q, p x.1 := ⟨fun x => ⟨⟨x.1.1, x.2⟩, x.1.2⟩, fun x => ⟨⟨x.1.1, x.2⟩, x.1.2⟩, fun _ => rfl, fun _ => rfl⟩ /-- A sigma type over a subtype is equivalent to the sigma set over the original type, if the fiber is empty outside of the subset -/ -def sigmaSubtypeEquivOfSubset (p : α → Type v) (q : α → Prop) (h : ∀ x, p x → q x) : +def sigmaSubtypeEquivOfSubset {α} (p : α → Type v) (q : α → Prop) (h : ∀ x, p x → q x) : (Σ x : Subtype q, p x) ≃ Σ x : α, p x := (subtypeSigmaEquiv p q).symm.trans <| subtypeUnivEquiv fun x => h x.1 x.2 @@ -1124,7 +1149,7 @@ def sigmaSubtypeFiberEquivSubtype {α β : Type*} (f : α → β) {p : α → Pr /-- A sigma type over an `Option` is equivalent to the sigma set over the original type, if the fiber is empty at none. -/ -def sigmaOptionEquivOfSome (p : Option α → Type v) (h : p none → False) : +def sigmaOptionEquivOfSome {α} (p : Option α → Type v) (h : p none → False) : (Σ x : Option α, p x) ≃ Σ x : α, p (some x) := haveI h' : ∀ x, p x → x.isSome := by intro x @@ -1163,7 +1188,7 @@ def subtypePiEquivPi {β : α → Sort v} {p : ∀ a, β a → Prop} : /-- A subtype of a product defined by componentwise conditions is equivalent to a product of subtypes. -/ -def subtypeProdEquivProd {p : α → Prop} {q : β → Prop} : +def subtypeProdEquivProd {α β} {p : α → Prop} {q : β → Prop} : { c : α × β // p c.1 ∧ q c.2 } ≃ { a // p a } × { b // q b } where toFun := fun x => ⟨⟨x.1.1, x.2.1⟩, ⟨x.1.2, x.2.2⟩⟩ invFun := fun x => ⟨⟨x.1.1, x.2.1⟩, ⟨x.1.2, x.2.2⟩⟩ @@ -1172,14 +1197,15 @@ def subtypeProdEquivProd {p : α → Prop} {q : β → Prop} : /-- A subtype of a `Prod` that depends only on the first component is equivalent to the corresponding subtype of the first type times the second type. -/ -def prodSubtypeFstEquivSubtypeProd {p : α → Prop} : {s : α × β // p s.1} ≃ {a // p a} × β where +def prodSubtypeFstEquivSubtypeProd {α β} {p : α → Prop} : + {s : α × β // p s.1} ≃ {a // p a} × β where toFun x := ⟨⟨x.1.1, x.2⟩, x.1.2⟩ invFun x := ⟨⟨x.1.1, x.2⟩, x.1.2⟩ left_inv _ := rfl right_inv _ := rfl /-- A subtype of a `Prod` is equivalent to a sigma type whose fibers are subtypes. -/ -def subtypeProdEquivSigmaSubtype (p : α → β → Prop) : +def subtypeProdEquivSigmaSubtype {α β} (p : α → β → Prop) : { x : α × β // p x.1 x.2 } ≃ Σa, { b : β // p a b } where toFun x := ⟨x.1.1, x.1.2, x.property⟩ invFun x := ⟨⟨x.1, x.2⟩, x.2.property⟩ @@ -1232,7 +1258,7 @@ end section subtypeEquivCodomain -variable [DecidableEq X] {x : X} +variable {X Y : Sort*} [DecidableEq X] {x : X} /-- The type of all functions `X → Y` with prescribed values for all `x' ≠ x` is equivalent to the codomain `Y`. -/ @@ -1532,6 +1558,9 @@ theorem toPerm_symm {f : α → α} (h : Involutive f) : (h.toPerm f).symm = h.t theorem toPerm_involutive {f : α → α} (h : Involutive f) : Involutive (h.toPerm f) := h +theorem symm_eq_self_of_involutive (f : Equiv.Perm α) (h : Involutive f) : f.symm = f := + DFunLike.coe_injective (h.leftInverse_iff.mp f.left_inv) + end Function.Involutive theorem PLift.eq_up_iff_down_eq {x : PLift α} {y : α} : x = PLift.up y ↔ x.down = y := @@ -1554,7 +1583,7 @@ variable (P : α → Sort w) (e : α ≃ β) /-- Transport dependent functions through an equivalence of the base space. -/ -@[simps] +@[simps apply, simps (config := .lemmasOnly) symm_apply] def piCongrLeft' (P : α → Sort*) (e : α ≃ β) : (∀ a, P a) ≃ ∀ b, P (e.symm b) where toFun f x := f (e.symm x) invFun f x := (e.symm_apply_apply x).ndrec (f (e x)) @@ -1578,13 +1607,11 @@ theorem piCongrLeft'_symm (P : Sort*) (e : α ≃ β) : LHS would have type `P a` while the RHS would have type `P (e.symm (e a))`. This lemma is a way around it in the case where `a` is of the form `e.symm b`, so we can use `g b` instead of `g (e (e.symm b))`. -/ +@[simp] lemma piCongrLeft'_symm_apply_apply (P : α → Sort*) (e : α ≃ β) (g : ∀ b, P (e.symm b)) (b : β) : (piCongrLeft' P e).symm g (e.symm b) = g b := by - change Eq.ndrec _ _ = _ - generalize_proofs hZa - revert hZa - rw [e.apply_symm_apply b] - simp + rw [piCongrLeft'_symm_apply, ← heq_iff_eq, rec_heq_iff_heq] + exact congr_arg_heq _ (e.apply_symm_apply _) end @@ -1626,13 +1653,13 @@ lemma piCongrLeft_apply_eq_cast {P : β → Sort v} {e : α ≃ β} piCongrLeft P e f b = cast (congr_arg P (e.apply_symm_apply b)) (f (e.symm b)) := Eq.rec_eq_cast _ _ -theorem piCongrLeft_sum_inl (π : ι'' → Type*) (e : ι ⊕ ι' ≃ ι'') (f : ∀ i, π (e (inl i))) +theorem piCongrLeft_sum_inl {ι ι' ι''} (π : ι'' → Type*) (e : ι ⊕ ι' ≃ ι'') (f : ∀ i, π (e (inl i))) (g : ∀ i, π (e (inr i))) (i : ι) : piCongrLeft π e (sumPiEquivProdPi (fun x => π (e x)) |>.symm (f, g)) (e (inl i)) = f i := by simp_rw [piCongrLeft_apply_eq_cast, sumPiEquivProdPi_symm_apply, sum_rec_congr _ _ _ (e.symm_apply_apply (inl i)), cast_cast, cast_eq] -theorem piCongrLeft_sum_inr (π : ι'' → Type*) (e : ι ⊕ ι' ≃ ι'') (f : ∀ i, π (e (inl i))) +theorem piCongrLeft_sum_inr {ι ι' ι''} (π : ι'' → Type*) (e : ι ⊕ ι' ≃ ι'') (f : ∀ i, π (e (inl i))) (g : ∀ i, π (e (inr i))) (j : ι') : piCongrLeft π e (sumPiEquivProdPi (fun x => π (e x)) |>.symm (f, g)) (e (inr j)) = g j := by simp_rw [piCongrLeft_apply_eq_cast, sumPiEquivProdPi_symm_apply, @@ -1717,7 +1744,7 @@ end BinaryOp section ULift @[simp] -theorem ulift_symm_down (x : α) : (Equiv.ulift.{u, v}.symm x).down = x := +theorem ulift_symm_down {α} (x : α) : (Equiv.ulift.{u, v}.symm x).down = x := rfl end ULift @@ -1741,7 +1768,7 @@ theorem Function.Injective.swap_comp funext fun _ => hf.swap_apply _ _ _ /-- If `α` is a subsingleton, then it is equivalent to `α × α`. -/ -def subsingletonProdSelfEquiv [Subsingleton α] : α × α ≃ α where +def subsingletonProdSelfEquiv {α} [Subsingleton α] : α × α ≃ α where toFun p := p.1 invFun a := (a, a) left_inv _ := Subsingleton.elim _ _ @@ -1772,6 +1799,8 @@ def uniqueEquivEquivUnique (α : Sort u) (β : Sort v) [Unique β] : Unique α namespace Function +variable {α' : Sort*} + theorem update_comp_equiv [DecidableEq α'] [DecidableEq α] (f : α → β) (g : α' ≃ α) (a : α) (v : β) : update f a v ∘ g = update (f ∘ g) (g.symm a) v := by @@ -1803,3 +1832,5 @@ theorem piCongrLeft'_symm_update [DecidableEq α] [DecidableEq β] (P : α → S simp [(e.piCongrLeft' P).symm_apply_eq, piCongrLeft'_update] end Function + +set_option linter.style.longFile 2000 diff --git a/Mathlib/Logic/Equiv/Defs.lean b/Mathlib/Logic/Equiv/Defs.lean index 07b977deedc18..f85dc2dee7a75 100644 --- a/Mathlib/Logic/Equiv/Defs.lean +++ b/Mathlib/Logic/Equiv/Defs.lean @@ -259,9 +259,7 @@ theorem Perm.coe_subsingleton {α : Type*} [Subsingleton α] (e : Perm α) : (e @[simp] theorem symm_trans_apply (f : α ≃ β) (g : β ≃ γ) (a : γ) : (f.trans g).symm a = f.symm (g.symm a) := rfl --- The `simp` attribute is needed to make this a `dsimp` lemma. --- `simp` will always rewrite with `Equiv.symm_symm` before this has a chance to fire. -@[simp, nolint simpNF] theorem symm_symm_apply (f : α ≃ β) (b : α) : f.symm.symm b = f b := rfl +theorem symm_symm_apply (f : α ≃ β) (b : α) : f.symm.symm b = f b := rfl theorem apply_eq_iff_eq (f : α ≃ β) {x y : α} : f x = f y ↔ x = y := EquivLike.apply_eq_iff_eq f @@ -288,7 +286,7 @@ theorem symm_apply_eq {α β} (e : α ≃ β) {x y} : e.symm x = y ↔ x = e y : theorem eq_symm_apply {α β} (e : α ≃ β) {x y} : y = e.symm x ↔ e y = x := (eq_comm.trans e.symm_apply_eq).trans eq_comm -@[simp] theorem symm_symm (e : α ≃ β) : e.symm.symm = e := by cases e; rfl +@[simp] theorem symm_symm (e : α ≃ β) : e.symm.symm = e := rfl theorem symm_bijective : Function.Bijective (Equiv.symm : (α ≃ β) → β ≃ α) := Function.bijective_iff_has_inverse.mpr ⟨_, symm_symm, symm_symm⟩ @@ -613,7 +611,7 @@ theorem sigmaCongrRight_symm {α} {β₁ β₂ : α → Type*} (F : ∀ a, β₁ theorem sigmaCongrRight_refl {α} {β : α → Type*} : (sigmaCongrRight fun a => Equiv.refl (β a)) = Equiv.refl (Σ a, β a) := rfl -/-- A `PSigma` with `Prop` fibers is equivalent to the subtype. -/ +/-- A `PSigma` with `Prop` fibers is equivalent to the subtype. -/ def psigmaEquivSubtype {α : Type v} (P : α → Prop) : (Σ' i, P i) ≃ Subtype P where toFun x := ⟨x.1, x.2⟩ invFun x := ⟨x.1, x.2⟩ diff --git a/Mathlib/Logic/Equiv/Embedding.lean b/Mathlib/Logic/Equiv/Embedding.lean index 5d383980cd4ea..10d04e64a9425 100644 --- a/Mathlib/Logic/Equiv/Embedding.lean +++ b/Mathlib/Logic/Equiv/Embedding.lean @@ -26,7 +26,7 @@ def sumEmbeddingEquivProdEmbeddingDisjoint {α β γ : Type*} : rintro _ ⟨a, h⟩ ⟨b, rfl⟩ simp only [trans_apply, inl_apply, inr_apply] at h have : Sum.inl a = Sum.inr b := f.injective h - simp only at this⟩ + simp only [reduceCtorEq] at this⟩ invFun := fun ⟨⟨f, g⟩, disj⟩ => ⟨fun x => match x with diff --git a/Mathlib/Logic/Equiv/Fin.lean b/Mathlib/Logic/Equiv/Fin.lean index 179b1141b3244..1d07d2d1b2b25 100644 --- a/Mathlib/Logic/Equiv/Fin.lean +++ b/Mathlib/Logic/Equiv/Fin.lean @@ -37,6 +37,59 @@ def finTwoEquiv : Fin 2 ≃ Bool where left_inv := Fin.forall_fin_two.2 <| by simp right_inv := Bool.forall_bool.2 <| by simp +/-! +### Tuples + +This section defines a bunch of equivalences between `n + 1`-tuples and products of `n`-tuples with +an entry. +-/ + +namespace Fin + +/-- Equivalence between tuples of length `n + 1` and pairs of an element and a tuple of length `n` +given by separating out the first element of the tuple. + +This is `Fin.cons` as an `Equiv`. -/ +@[simps] +def consEquiv (α : Fin (n + 1) → Type*) : α 0 × (∀ i, α (succ i)) ≃ ∀ i, α i where + toFun f := cons f.1 f.2 + invFun f := (f 0, tail f) + left_inv f := by simp + right_inv f := by simp + +/-- Equivalence between tuples of length `n + 1` and pairs of an element and a tuple of length `n` +given by separating out the last element of the tuple. + +This is `Fin.snoc` as an `Equiv`. -/ +@[simps] +def snocEquiv (α : Fin (n + 1) → Type*) : α (last n) × (∀ i, α (castSucc i)) ≃ ∀ i, α i where + toFun f i := Fin.snoc f.2 f.1 _ + invFun f := ⟨f _, Fin.init f⟩ + left_inv f := by simp + right_inv f := by simp + +/-- Equivalence between tuples of length `n + 1` and pairs of an element and a tuple of length `n` +given by separating out the `p`-th element of the tuple. + +This is `Fin.insertNth` as an `Equiv`. -/ +@[simps] +def insertNthEquiv (α : Fin (n + 1) → Type u) (p : Fin (n + 1)) : + α p × (∀ i, α (p.succAbove i)) ≃ ∀ i, α i where + toFun f := insertNth p f.1 f.2 + invFun f := (f p, removeNth p f) + left_inv f := by ext <;> simp + right_inv f := by simp + +@[simp] lemma insertNthEquiv_zero (α : Fin (n + 1) → Type*) : insertNthEquiv α 0 = consEquiv α := + Equiv.symm_bijective.injective <| by ext <;> rfl + +/-- Note this lemma can only be written about non-dependent tuples as `insertNth (last n) = snoc` is +not a definitional equality. -/ +@[simp] lemma insertNthEquiv_last (n : ℕ) (α : Type*) : + insertNthEquiv (fun _ ↦ α) (last n) = snocEquiv (fun _ ↦ α) := by ext; simp + +end Fin + /-- `Π i : Fin 2, α i` is equivalent to `α 0 × α 1`. See also `finTwoArrowEquiv` for a non-dependent version and `prodEquivPiFinTwo` for a version with inputs `α β : Type u`. -/ @[simps (config := .asFn)] @@ -46,6 +99,12 @@ def piFinTwoEquiv (α : Fin 2 → Type u) : (∀ i, α i) ≃ α 0 × α 1 where left_inv _ := funext <| Fin.forall_fin_two.2 ⟨rfl, rfl⟩ right_inv := fun _ => rfl +/-! +### Miscellaneous + +This is currently not very sorted. PRs welcome! +-/ + theorem Fin.preimage_apply_01_prod {α : Fin 2 → Type u} (s : Set (α 0)) (t : Set (α 1)) : (fun f : ∀ i, α i => (f 0, f 1)) ⁻¹' s ×ˢ t = Set.pi Set.univ (Fin.cons s <| Fin.cons t finZeroElim) := by @@ -202,7 +261,7 @@ theorem finSuccEquivLast_symm_some (i : Fin n) : finSuccEquiv'_symm_none _ /-- Equivalence between `Π j : Fin (n + 1), α j` and `α i × Π j : Fin n, α (Fin.succAbove i j)`. -/ -@[simps (config := .asFn)] +@[simps (config := .asFn), deprecated Fin.insertNthEquiv (since := "2024-07-12")] def Equiv.piFinSuccAbove (α : Fin (n + 1) → Type u) (i : Fin (n + 1)) : (∀ j, α j) ≃ α i × ∀ j, α (i.succAbove j) where toFun f := (f i, i.removeNth f) @@ -211,9 +270,9 @@ def Equiv.piFinSuccAbove (α : Fin (n + 1) → Type u) (i : Fin (n + 1)) : right_inv f := by simp /-- Equivalence between `Fin (n + 1) → β` and `β × (Fin n → β)`. -/ -@[simps! (config := .asFn)] +@[simps! (config := .asFn), deprecated Fin.consEquiv (since := "2024-07-12")] def Equiv.piFinSucc (n : ℕ) (β : Type u) : (Fin (n + 1) → β) ≃ β × (Fin n → β) := - Equiv.piFinSuccAbove (fun _ => β) 0 + (Fin.insertNthEquiv (fun _ => β) 0).symm /-- An embedding `e : Fin (n+1) ↪ ι` corresponds to an embedding `f : Fin n ↪ ι` (corresponding the last `n` coordinates of `e`) together with a value not taken by `f` (corresponding to `e 0`). -/ @@ -236,9 +295,9 @@ def Equiv.embeddingFinSucc (n : ℕ) (ι : Type*) : /-- Equivalence between `Fin (n + 1) → β` and `β × (Fin n → β)` which separates out the last element of the tuple. -/ -@[simps! (config := .asFn)] +@[simps! (config := .asFn), deprecated Fin.snocEquiv (since := "2024-07-12")] def Equiv.piFinCastSucc (n : ℕ) (β : Type u) : (Fin (n + 1) → β) ≃ β × (Fin n → β) := - Equiv.piFinSuccAbove (fun _ => β) (.last _) + (Fin.insertNthEquiv (fun _ => β) (.last _)).symm /-- Equivalence between `Fin m ⊕ Fin n` and `Fin (m + n)` -/ def finSumFinEquiv : Fin m ⊕ Fin n ≃ Fin (m + n) where diff --git a/Mathlib/Logic/Equiv/List.lean b/Mathlib/Logic/Equiv/List.lean index dd286968a4960..7a050c68661b5 100644 --- a/Mathlib/Logic/Equiv/List.lean +++ b/Mathlib/Logic/Equiv/List.lean @@ -14,7 +14,6 @@ This file defines some additional constructive equivalences using `Encodable` an function on `ℕ`. -/ - open Mathlib (Vector) open Nat List @@ -118,7 +117,7 @@ def encodableOfList [DecidableEq α] (l : List α) (H : ∀ x, x ∈ l) : Encoda /-- A finite type is encodable. Because the encoding is not unique, we wrap it in `Trunc` to preserve computability. -/ def _root_.Fintype.truncEncodable (α : Type*) [DecidableEq α] [Fintype α] : Trunc (Encodable α) := - @Quot.recOnSubsingleton' _ _ (fun s : Multiset α => (∀ x : α, x ∈ s) → Trunc (Encodable α)) _ + @Quot.recOnSubsingleton _ _ (fun s : Multiset α => (∀ x : α, x ∈ s) → Trunc (Encodable α)) _ Finset.univ.1 (fun l H => Trunc.mk <| encodableOfList l H) Finset.mem_univ /-- A noncomputable way to arbitrarily choose an ordering on a finite type. @@ -290,7 +289,7 @@ instance multiset : Denumerable (Multiset α) := raise_lower (List.sorted_cons.2 ⟨fun n _ => Nat.zero_le n, (s.map encode).sort_sorted _⟩) simp [-Multiset.map_coe, this], fun n => by - simp [-Multiset.map_coe, List.mergeSort_eq_self _ (raise_sorted _ _), lower_raise]⟩ + simp [-Multiset.map_coe, List.mergeSort'_eq_self _ (raise_sorted _ _), lower_raise]⟩ end Multiset @@ -345,7 +344,7 @@ instance finset : Denumerable (Finset α) := raise_lower' (fun n _ => Nat.zero_le n) (Finset.sort_sorted_lt _)], fun n => by simp [-Multiset.map_coe, Finset.map, raise'Finset, Finset.sort, - List.mergeSort_eq_self (· ≤ ·) ((raise'_sorted _ _).imp (@le_of_lt _ _)), lower_raise']⟩ + List.mergeSort'_eq_self (· ≤ ·) ((raise'_sorted _ _).imp (@le_of_lt _ _)), lower_raise']⟩ end Finset diff --git a/Mathlib/Logic/Equiv/Option.lean b/Mathlib/Logic/Equiv/Option.lean index 33a5a78ec5165..65c8c77633e6a 100644 --- a/Mathlib/Logic/Equiv/Option.lean +++ b/Mathlib/Logic/Equiv/Option.lean @@ -7,7 +7,6 @@ import Mathlib.Control.EquivFunctor import Mathlib.Data.Option.Basic import Mathlib.Data.Subtype import Mathlib.Logic.Equiv.Defs -import Mathlib.Tactic.Cases /-! # Equivalences for `Option α` @@ -125,13 +124,13 @@ theorem option_symm_apply_none_iff : e.symm none = none ↔ e none = none := ⟨fun h => by simpa using (congr_arg e h).symm, fun h => by simpa using (congr_arg e.symm h).symm⟩ theorem some_removeNone_iff {x : α} : some (removeNone e x) = e none ↔ e.symm none = some x := by - cases' h : e (some x) with a + rcases h : e (some x) with a | a · rw [removeNone_none _ h] simpa using (congr_arg e.symm h).symm · rw [removeNone_some _ ⟨a, h⟩] have h1 := congr_arg e.symm h rw [symm_apply_apply] at h1 - simp only [false_iff_iff, apply_eq_iff_eq] + simp only [false_iff_iff, apply_eq_iff_eq, reduceCtorEq] simp [h1, apply_eq_iff_eq] @[simp] diff --git a/Mathlib/Logic/Equiv/PartialEquiv.lean b/Mathlib/Logic/Equiv/PartialEquiv.lean index 60d671cc71a1e..7d93cc552f446 100644 --- a/Mathlib/Logic/Equiv/PartialEquiv.lean +++ b/Mathlib/Logic/Equiv/PartialEquiv.lean @@ -289,9 +289,7 @@ theorem symm_target : e.symm.target = e.source := rfl @[simp, mfld_simps] -theorem symm_symm : e.symm.symm = e := by - cases e - rfl +theorem symm_symm : e.symm.symm = e := rfl theorem symm_bijective : Function.Bijective (PartialEquiv.symm : PartialEquiv α β → PartialEquiv β α) := @@ -721,7 +719,7 @@ theorem EqOnSource.restr {e e' : PartialEquiv α β} (he : e ≈ e') (s : Set α theorem EqOnSource.source_inter_preimage_eq {e e' : PartialEquiv α β} (he : e ≈ e') (s : Set β) : e.source ∩ e ⁻¹' s = e'.source ∩ e' ⁻¹' s := by rw [he.eqOn.inter_preimage_eq, source_eq he] -/-- Composition of a partial equivlance and its inverse is equivalent to +/-- Composition of a partial equivalence and its inverse is equivalent to the restriction of the identity to the source. -/ theorem self_trans_symm : e.trans e.symm ≈ ofSet e.source := by have A : (e.trans e.symm).source = e.source := by mfld_set_tac diff --git a/Mathlib/Logic/Equiv/Set.lean b/Mathlib/Logic/Equiv/Set.lean index 65af5ec56aaec..fb51576130691 100644 --- a/Mathlib/Logic/Equiv/Set.lean +++ b/Mathlib/Logic/Equiv/Set.lean @@ -298,13 +298,13 @@ theorem sumCompl_symm_apply_of_not_mem {α : Type u} {s : Set α} [DecidablePred @[simp] theorem sumCompl_symm_apply {α : Type*} {s : Set α} [DecidablePred (· ∈ s)] {x : s} : - (Equiv.Set.sumCompl s).symm x = Sum.inl x := by - cases' x with x hx; exact Set.sumCompl_symm_apply_of_mem hx + (Equiv.Set.sumCompl s).symm x = Sum.inl x := + Set.sumCompl_symm_apply_of_mem x.2 @[simp] theorem sumCompl_symm_apply_compl {α : Type*} {s : Set α} [DecidablePred (· ∈ s)] - {x : (sᶜ : Set α)} : (Equiv.Set.sumCompl s).symm x = Sum.inr x := by - cases' x with x hx; exact Set.sumCompl_symm_apply_of_not_mem hx + {x : (sᶜ : Set α)} : (Equiv.Set.sumCompl s).symm x = Sum.inr x := + Set.sumCompl_symm_apply_of_not_mem x.2 /-- `sumDiffSubset s t` is the natural equivalence between `s ⊕ (t \ s)` and `t`, where `s` and `t` are two sets. -/ diff --git a/Mathlib/Logic/Function/Basic.lean b/Mathlib/Logic/Function/Basic.lean index 23b06d62b1a9b..35aaecce63413 100644 --- a/Mathlib/Logic/Function/Basic.lean +++ b/Mathlib/Logic/Function/Basic.lean @@ -3,9 +3,10 @@ Copyright (c) 2016 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.Logic.Nonempty -import Mathlib.Init.Set +import Mathlib.Init.Algebra.Classes +import Mathlib.Data.Set.Defs import Mathlib.Logic.Basic +import Mathlib.Logic.Nonempty import Batteries.Tactic.Init /-! @@ -763,6 +764,10 @@ theorem comp_self : f ∘ f = id := protected theorem leftInverse : LeftInverse f f := h +theorem leftInverse_iff {g : α → α} : + g.LeftInverse f ↔ g = f := + ⟨fun hg ↦ funext fun x ↦ by rw [← h x, hg, h], fun he ↦ he ▸ h.leftInverse⟩ + protected theorem rightInverse : RightInverse f f := h protected theorem injective : Injective f := h.leftInverse.injective diff --git a/Mathlib/Logic/Function/Defs.lean b/Mathlib/Logic/Function/Defs.lean index 57c703c66bfff..72aa534f806b9 100644 --- a/Mathlib/Logic/Function/Defs.lean +++ b/Mathlib/Logic/Function/Defs.lean @@ -91,10 +91,6 @@ theorem comp_id (f : α → β) : f ∘ id = f := rfl theorem comp.assoc (f : φ → δ) (g : β → φ) (h : α → β) : (f ∘ g) ∘ h = f ∘ g ∘ h := rfl -@[simp] theorem const_comp {γ : Sort*} (f : α → β) (c : γ) : const β c ∘ f = const α c := rfl - -@[simp] theorem comp_const (f : β → φ) (b : β) : f ∘ const α b = const α (f b) := rfl - @[deprecated (since := "2024-01-14")] alias comp_const_right := comp_const /-- A function `f : α → β` is called injective if `f x = f y` implies `x = y`. -/ diff --git a/Mathlib/Logic/Godel/GodelBetaFunction.lean b/Mathlib/Logic/Godel/GodelBetaFunction.lean index d83abadb18246..4fe1e162e2c5a 100644 --- a/Mathlib/Logic/Godel/GodelBetaFunction.lean +++ b/Mathlib/Logic/Godel/GodelBetaFunction.lean @@ -13,7 +13,7 @@ import Mathlib.Data.Nat.Pairing # Gödel's Beta Function Lemma This file proves Gödel's Beta Function Lemma, used to prove the First Incompleteness Theorem. It -permits quantification over finite sequences of natural numbers in formal theories of arithmetic. +permits quantification over finite sequences of natural numbers in formal theories of arithmetic. This Beta Function has no connection with the unrelated Beta Function defined in analysis. Note that `Nat.beta` and `Nat.unbeta` provide similar functionality to `Encodable.encodeList` and `Encodable.decodeList`. We define these separately, because it is easier to prove that `Nat.beta` diff --git a/Mathlib/Logic/IsEmpty.lean b/Mathlib/Logic/IsEmpty.lean index a7c0a41156632..b46a933890f1c 100644 --- a/Mathlib/Logic/IsEmpty.lean +++ b/Mathlib/Logic/IsEmpty.lean @@ -138,7 +138,7 @@ theorem not_isEmpty_iff : ¬IsEmpty α ↔ Nonempty α := @[simp] theorem isEmpty_Prop {p : Prop} : IsEmpty p ↔ ¬p := by - simp only [← not_nonempty_iff, nonempty_Prop] + simp only [← not_nonempty_iff, nonempty_prop] @[simp] theorem isEmpty_pi {π : α → Sort*} : IsEmpty (∀ a, π a) ↔ ∃ a, IsEmpty (π a) := by diff --git a/Mathlib/Logic/Nonempty.lean b/Mathlib/Logic/Nonempty.lean index 67d8bd928a527..1a52ca02ab2d4 100644 --- a/Mathlib/Logic/Nonempty.lean +++ b/Mathlib/Logic/Nonempty.lean @@ -32,9 +32,7 @@ theorem Nonempty.exists {α} {p : Nonempty α → Prop} : (∃ h : Nonempty α, theorem exists_true_iff_nonempty {α : Sort*} : (∃ _ : α, True) ↔ Nonempty α := Iff.intro (fun ⟨a, _⟩ ↦ ⟨a⟩) fun ⟨a⟩ ↦ ⟨a, trivial⟩ -@[simp] -theorem nonempty_Prop {p : Prop} : Nonempty p ↔ p := - Iff.intro (fun ⟨h⟩ ↦ h) fun h ↦ ⟨h⟩ +@[deprecated (since := "2024-08-30")] alias nonempty_Prop := nonempty_prop theorem Nonempty.imp {α} {p : Prop} : (Nonempty α → p) ↔ (α → p) := Nonempty.forall diff --git a/Mathlib/Logic/Pairwise.lean b/Mathlib/Logic/Pairwise.lean index 587b569ca7820..26dd58b7b3c9e 100644 --- a/Mathlib/Logic/Pairwise.lean +++ b/Mathlib/Logic/Pairwise.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl -/ import Mathlib.Logic.Function.Basic -import Mathlib.Init.Set +import Mathlib.Data.Set.Defs import Mathlib.Tactic.Common /-! diff --git a/Mathlib/Logic/Relation.lean b/Mathlib/Logic/Relation.lean index 9f30f820360f2..1140370051471 100644 --- a/Mathlib/Logic/Relation.lean +++ b/Mathlib/Logic/Relation.lean @@ -5,8 +5,6 @@ Authors: Johannes Hölzl -/ import Mathlib.Logic.Function.Basic import Mathlib.Logic.Relator -import Mathlib.Init.Data.Quot -import Mathlib.Tactic.Cases import Mathlib.Tactic.Use import Mathlib.Tactic.MkIffOfInductiveProp import Mathlib.Tactic.SimpRw @@ -14,8 +12,8 @@ import Mathlib.Tactic.SimpRw /-! # Relation closures -This file defines the reflexive, transitive, and reflexive transitive closures of relations. -It also proves some basic results on definitions such as `EqvGen`. +This file defines the reflexive, transitive, reflexive transitive and equivalence closures +of relations and proves some basic results on them. Note that this is about unbundled relations, that is terms of types of the form `α → β → Prop`. For the bundled version, see `Rel`. @@ -32,6 +30,8 @@ the bundled version, see `Rel`. the reflexive closure of the transitive closure, or the transitive closure of the reflexive closure. In terms of rewriting systems, this means that `a` can be rewritten to `b` in a number of rewrites. +* `Relation.EqvGen`: Equivalence closure. `EqvGen r` relates everything `ReflTransGen r` relates, + plus for all related pairs it relates them in the opposite order. * `Relation.Comp`: Relation composition. We provide notation `∘r`. For `r : α → β → Prop` and `s : β → γ → Prop`, `r ∘r s`relates `a : α` and `c : γ` iff there exists `b : β` that's related to both. @@ -167,7 +167,7 @@ variable {rα rβ} /-- If `f : α → β` is a fibration between relations `rα` and `rβ`, and `a : α` is accessible under `rα`, then `f a` is accessible under `rβ`. -/ theorem _root_.Acc.of_fibration (fib : Fibration rα rβ f) {a} (ha : Acc rα a) : Acc rβ (f a) := by - induction' ha with a _ ih + induction ha with | intro a _ ih => ?_ refine Acc.intro (f a) fun b hr ↦ ?_ obtain ⟨a', hr', rfl⟩ := fib hr exact ih a' hr' @@ -229,9 +229,16 @@ inductive ReflGen (r : α → α → Prop) (a : α) : α → Prop | refl : ReflGen r a a | single {b} : r a b → ReflGen r a b -attribute [mk_iff] TransGen - +variable (r) in +/-- `EqvGen r`: equivalence closure of `r`. -/ +@[mk_iff] +inductive EqvGen : α → α → Prop + | rel x y : r x y → EqvGen x y + | refl x : EqvGen x x + | symm x y : EqvGen x y → EqvGen y x + | trans x y z : EqvGen x y → EqvGen y z → EqvGen x z +attribute [mk_iff] TransGen attribute [refl] ReflGen.refl namespace ReflGen @@ -267,9 +274,9 @@ theorem head (hab : r a b) (hbc : ReflTransGen r b c) : ReflTransGen r a c := by theorem symmetric (h : Symmetric r) : Symmetric (ReflTransGen r) := by intro x y h - induction' h with z w _ b c - · rfl - · apply Relation.ReflTransGen.head (h b) c + induction h with + | refl => rfl + | tail _ b c => apply Relation.ReflTransGen.head (h b) c theorem cases_tail : ReflTransGen r a b → b = a ∨ ∃ c, ReflTransGen r a c ∧ r c b := (cases_tail_iff r a b).1 @@ -309,9 +316,10 @@ theorem cases_head_iff : ReflTransGen r a b ↔ a = b ∨ ∃ c, r a c ∧ ReflT theorem total_of_right_unique (U : Relator.RightUnique r) (ab : ReflTransGen r a b) (ac : ReflTransGen r a c) : ReflTransGen r b c ∨ ReflTransGen r c b := by - induction' ab with b d _ bd IH - · exact Or.inl ac - · rcases IH with (IH | IH) + induction ab with + | refl => exact Or.inl ac + | tail _ bd IH => + rcases IH with (IH | IH) · rcases cases_head IH with (rfl | ⟨e, be, ec⟩) · exact Or.inr (single bd) · cases U bd be @@ -323,10 +331,9 @@ end ReflTransGen namespace TransGen theorem to_reflTransGen {a b} (h : TransGen r a b) : ReflTransGen r a b := by - induction' h with b h b c _ bc ab - · exact ReflTransGen.single h - · exact ReflTransGen.tail ab bc --- Porting note: in Lean 3 this function was called `to_refl` which seems wrong. + induction h with + | single h => exact ReflTransGen.single h + | tail _ bc ab => exact ReflTransGen.tail ab bc theorem trans_left (hab : TransGen r a b) (hbc : ReflTransGen r b c) : TransGen r a c := by induction hbc with @@ -336,9 +343,7 @@ theorem trans_left (hab : TransGen r a b) (hbc : ReflTransGen r b c) : TransGen instance : Trans (TransGen r) (ReflTransGen r) (TransGen r) := ⟨trans_left⟩ -@[trans] -theorem trans (hab : TransGen r a b) (hbc : TransGen r b c) : TransGen r a c := - trans_left hab hbc.to_reflTransGen +attribute [trans] trans instance : Trans (TransGen r) (TransGen r) (TransGen r) := ⟨trans⟩ @@ -384,9 +389,9 @@ instance : Trans (ReflTransGen r) (TransGen r) (TransGen r) := theorem tail'_iff : TransGen r a c ↔ ∃ b, ReflTransGen r a b ∧ r b c := by refine ⟨fun h ↦ ?_, fun ⟨b, hab, hbc⟩ ↦ tail' hab hbc⟩ - cases' h with _ hac b _ hab hbc - · exact ⟨_, by rfl, hac⟩ - · exact ⟨_, hab.to_reflTransGen, hbc⟩ + cases h with + | single hac => exact ⟨_, by rfl, hac⟩ + | tail hab hbc => exact ⟨_, hab.to_reflTransGen, hbc⟩ theorem head'_iff : TransGen r a c ↔ ∃ b, r a b ∧ ReflTransGen r b c := by refine ⟨fun h ↦ ?_, fun ⟨b, hab, hbc⟩ ↦ head' hab hbc⟩ @@ -458,9 +463,9 @@ lemma transGen_minimal {r' : α → α → Prop} (hr' : Transitive r') (h : ∀ simpa [transGen_eq_self hr'] using TransGen.mono h hxy theorem TransGen.swap (h : TransGen r b a) : TransGen (swap r) a b := by - induction' h with b h b c _ hbc ih - · exact TransGen.single h - · exact ih.head hbc + induction h with + | single h => exact TransGen.single h + | tail _ hbc ih => exact ih.head hbc theorem transGen_swap : TransGen (swap r) a b ↔ TransGen r b a := ⟨TransGen.swap, TransGen.swap⟩ @@ -476,9 +481,9 @@ theorem reflTransGen_iff_eq (h : ∀ b, ¬r a b) : ReflTransGen r a b ↔ b = a theorem reflTransGen_iff_eq_or_transGen : ReflTransGen r a b ↔ b = a ∨ TransGen r a b := by refine ⟨fun h ↦ ?_, fun h ↦ ?_⟩ - · cases' h with c _ hac hcb - · exact Or.inl rfl - · exact Or.inr (TransGen.tail' hac hcb) + · cases h with + | refl => exact Or.inl rfl + | tail hac hcb => exact Or.inr (TransGen.tail' hac hcb) · rcases h with (rfl | h) · rfl · exact h.to_reflTransGen @@ -494,9 +499,9 @@ theorem ReflTransGen.mono {p : α → α → Prop} : (∀ a b, r a b → p a b) theorem reflTransGen_eq_self (refl : Reflexive r) (trans : Transitive r) : ReflTransGen r = r := funext fun a ↦ funext fun b ↦ propext <| ⟨fun h ↦ by - induction' h with b c _ h₂ IH - · apply refl - · exact trans IH h₂, single⟩ + induction h with + | refl => apply refl + | tail _ h₂ IH => exact trans IH h₂, single⟩ lemma reflTransGen_minimal {r' : α → α → Prop} (hr₁ : Reflexive r') (hr₂ : Transitive r') (h : ∀ x y, r x y → r' x y) {x y : α} (hxy : ReflTransGen r x y) : r' x y := by @@ -525,9 +530,9 @@ theorem reflTransGen_closed {p : α → α → Prop} : ReflTransGen.lift' id theorem ReflTransGen.swap (h : ReflTransGen r b a) : ReflTransGen (swap r) a b := by - induction' h with b c _ hbc ih - · rfl - · exact ih.head hbc + induction h with + | refl => rfl + | tail _ hbc ih => exact ih.head hbc theorem reflTransGen_swap : ReflTransGen (swap r) a b ↔ ReflTransGen r b a := ⟨ReflTransGen.swap, ReflTransGen.swap⟩ @@ -561,6 +566,34 @@ lemma reflTransGen_eq_reflGen (hr : Transitive r) : end ReflTransGen +namespace EqvGen + +variable (r) + +theorem is_equivalence : Equivalence (@EqvGen α r) := + Equivalence.mk EqvGen.refl (EqvGen.symm _ _) (EqvGen.trans _ _ _) + +/-- `EqvGen.setoid r` is the setoid generated by a relation `r`. + +The motivation for this definition is that `Quot r` behaves like `Quotient (EqvGen.setoid r)`, +see for example `Quot.eqvGen_exact` and `Quot.eqvGen_sound`. -/ +def setoid : Setoid α := + Setoid.mk _ (EqvGen.is_equivalence r) + +theorem mono {r p : α → α → Prop} (hrp : ∀ a b, r a b → p a b) (h : EqvGen r a b) : + EqvGen p a b := by + induction h with + | rel a b h => exact EqvGen.rel _ _ (hrp _ _ h) + | refl => exact EqvGen.refl _ + | symm a b _ ih => exact EqvGen.symm _ _ ih + | trans a b c _ _ hab hbc => exact EqvGen.trans _ _ _ hab hbc + +@[deprecated (since := "2024-09-01")] alias _root_.EqvGen.is_equivalence := is_equivalence +@[deprecated (since := "2024-09-01")] alias _root_.EqvGen.Setoid := setoid +@[deprecated (since := "2024-09-01")] alias _root_.EqvGen.mono := mono + +end EqvGen + /-- The join of a relation on a single type is a new relation for which pairs of terms are related if there is a third term they are both related to. For example, if `r` is a relation representing rewrites @@ -587,14 +620,15 @@ theorem church_rosser (h : ∀ a b c, r a b → r a c → ∃ d, ReflGen r b d | refl => exact ⟨e, refl, ReflGen.single hde⟩ | @tail f b _ hfb ih => rcases ih with ⟨a, hea, hfa⟩ - cases' hfa with _ hfa - · exact ⟨b, hea.tail hfb, ReflGen.refl⟩ - · rcases h _ _ _ hfb hfa with ⟨c, hbc, hac⟩ + cases hfa with + | refl => exact ⟨b, hea.tail hfb, ReflGen.refl⟩ + | single hfa => + rcases h _ _ _ hfb hfa with ⟨c, hbc, hac⟩ exact ⟨c, hea.trans hac, hbc⟩ rcases this with ⟨a, hea, hba⟩ - cases' hba with _ hba - · exact ⟨b, hea, hcb⟩ - · exact ⟨a, hea, hcb.tail hba⟩ + cases hba with + | refl => exact ⟨b, hea, hcb⟩ + | single hba => exact ⟨a, hea, hcb.tail hba⟩ theorem join_of_single (h : Reflexive r) (hab : r a b) : Join r a b := @@ -625,9 +659,9 @@ theorem join_of_equivalence {r' : α → α → Prop} (hr : Equivalence r) (h : theorem reflTransGen_of_transitive_reflexive {r' : α → α → Prop} (hr : Reflexive r) (ht : Transitive r) (h : ∀ a b, r' a b → r a b) (h' : ReflTransGen r' a b) : r a b := by - induction' h' with b c _ hbc ih - · exact hr _ - · exact ht ih (h _ _ hbc) + induction h' with + | refl => exact hr _ + | tail _ hbc ih => exact ht ih (h _ _ hbc) theorem reflTransGen_of_equivalence {r' : α → α → Prop} (hr : Equivalence r) : (∀ a b, r' a b → r a b) → ReflTransGen r' a b → r a b := @@ -639,8 +673,31 @@ end Relation section EqvGen +open Relation + variable {r : α → α → Prop} {a b : α} +theorem Quot.eqvGen_exact (H : Quot.mk r a = Quot.mk r b) : EqvGen r a b := + @Quotient.exact _ (EqvGen.setoid r) a b (congrArg + (Quot.lift (Quotient.mk (EqvGen.setoid r)) (fun x y h ↦ Quot.sound (EqvGen.rel x y h))) H) + +theorem Quot.eqvGen_sound (H : EqvGen r a b) : Quot.mk r a = Quot.mk r b := + EqvGen.rec + (fun _ _ h ↦ Quot.sound h) + (fun _ ↦ rfl) + (fun _ _ _ IH ↦ Eq.symm IH) + (fun _ _ _ _ _ IH₁ IH₂ ↦ Eq.trans IH₁ IH₂) + H + +instance Quotient.decidableEq {α : Sort*} {s : Setoid α} [d : ∀ a b : α, Decidable (a ≈ b)] : + DecidableEq (Quotient s) := + fun q₁ q₂ : Quotient s ↦ + Quotient.recOnSubsingleton₂ q₁ q₂ + (fun a₁ a₂ ↦ + match (d a₁ a₂) with + | (isTrue h₁) => isTrue (Quotient.sound h₁) + | (isFalse h₂) => isFalse (fun h ↦ absurd (Quotient.exact h) h₂)) + theorem Equivalence.eqvGen_iff (h : Equivalence r) : EqvGen r a b ↔ r a b := Iff.intro (by @@ -655,12 +712,7 @@ theorem Equivalence.eqvGen_iff (h : Equivalence r) : EqvGen r a b ↔ r a b := theorem Equivalence.eqvGen_eq (h : Equivalence r) : EqvGen r = r := funext fun _ ↦ funext fun _ ↦ propext <| h.eqvGen_iff -theorem EqvGen.mono {r p : α → α → Prop} (hrp : ∀ a b, r a b → p a b) (h : EqvGen r a b) : - EqvGen p a b := by - induction h with - | rel a b h => exact EqvGen.rel _ _ (hrp _ _ h) - | refl => exact EqvGen.refl _ - | symm a b _ ih => exact EqvGen.symm _ _ ih - | trans a b c _ _ hab hbc => exact EqvGen.trans _ _ _ hab hbc +@[deprecated (since := "2024-08-29")] alias Quot.exact := Quot.eqvGen_exact +@[deprecated (since := "2024-08-29")] alias Quot.EqvGen_sound := Quot.eqvGen_sound end EqvGen diff --git a/Mathlib/MeasureTheory/Constructions/BorelSpace/Basic.lean b/Mathlib/MeasureTheory/Constructions/BorelSpace/Basic.lean index 74681e526e72b..4c6af21ff5643 100644 --- a/Mathlib/MeasureTheory/Constructions/BorelSpace/Basic.lean +++ b/Mathlib/MeasureTheory/Constructions/BorelSpace/Basic.lean @@ -55,14 +55,6 @@ theorem borel_anti : Antitone (@borel α) := fun _ _ h => theorem borel_eq_top_of_discrete [TopologicalSpace α] [DiscreteTopology α] : borel α = ⊤ := top_le_iff.1 fun s _ => GenerateMeasurable.basic s (isOpen_discrete s) -theorem borel_eq_top_of_countable [TopologicalSpace α] [T1Space α] [Countable α] : borel α = ⊤ := by - refine top_le_iff.1 fun s _ => biUnion_of_singleton s ▸ ?_ - apply MeasurableSet.biUnion s.to_countable - intro x _ - apply MeasurableSet.of_compl - apply GenerateMeasurable.basic - exact isClosed_singleton.isOpen_compl - theorem borel_eq_generateFrom_of_subbasis {s : Set (Set α)} [t : TopologicalSpace α] [SecondCountableTopology α] (hs : t = .generateFrom s) : borel α = .generateFrom s := le_antisymm @@ -157,7 +149,7 @@ def borelToRefl (e : Expr) (i : FVarId) : TacticM Unit := do `‹TopologicalSpace {e}› := {et}\n\ depends on\n\ {Expr.fvar i} : MeasurableSpace {e}`\n\ - so `borelize` isn't avaliable" + so `borelize` isn't available" evalTactic <| ← `(tactic| refine_lift letI : MeasurableSpace $te := borel $te @@ -267,6 +259,9 @@ theorem IsClosed.nullMeasurableSet {μ} (h : IsClosed s) : NullMeasurableSet s theorem IsCompact.measurableSet [T2Space α] (h : IsCompact s) : MeasurableSet s := h.isClosed.measurableSet +theorem IsCompact.nullMeasurableSet [T2Space α] {μ} (h : IsCompact s) : NullMeasurableSet s μ := + h.isClosed.nullMeasurableSet + /-- If two points are topologically inseparable, then they can't be separated by a Borel measurable set. -/ theorem Inseparable.mem_measurableSet_iff {x y : γ} (h : Inseparable x y) {s : Set γ} @@ -286,7 +281,7 @@ the measure of the closure of a compact set `K` is equal to the measure of `K`. See also `MeasureTheory.Measure.OuterRegular.measure_closure_eq_of_isCompact` for a version that assumes `μ` to be outer regular -but does not assume the `σ`-algebra to be Borel. -/ +but does not assume the `σ`-algebra to be Borel. -/ theorem IsCompact.measure_closure [R1Space γ] {K : Set γ} (hK : IsCompact K) (μ : Measure γ) : μ (closure K) = μ K := by refine le_antisymm ?_ (measure_mono subset_closure) @@ -339,6 +334,12 @@ instance (priority := 100) OpensMeasurableSpace.separatesPoints [T0Space α] : rw [inseparable_iff_forall_open] exact fun s hs => hxy _ hs.measurableSet +theorem borel_eq_top_of_countable {α : Type*} [TopologicalSpace α] [T0Space α] [Countable α] : + borel α = ⊤ := by + refine top_unique fun s _ ↦ ?_ + borelize α + exact .of_discrete + -- see Note [lower instance priority] instance (priority := 100) OpensMeasurableSpace.toMeasurableSingletonClass [T1Space α] : MeasurableSingletonClass α := @@ -624,7 +625,7 @@ instance _root_.ULift.instBorelSpace : BorelSpace (ULift α) := instance DiscreteMeasurableSpace.toBorelSpace {α : Type*} [TopologicalSpace α] [DiscreteTopology α] [MeasurableSpace α] [DiscreteMeasurableSpace α] : BorelSpace α := by - constructor; ext; simp [MeasurableSpace.measurableSet_generateFrom, measurableSet_discrete] + constructor; ext; simp [MeasurableSpace.measurableSet_generateFrom, MeasurableSet.of_discrete] protected theorem Embedding.measurableEmbedding {f : α → β} (h₁ : Embedding f) (h₂ : MeasurableSet (range f)) : MeasurableEmbedding f := diff --git a/Mathlib/MeasureTheory/Constructions/BorelSpace/Metric.lean b/Mathlib/MeasureTheory/Constructions/BorelSpace/Metric.lean index 8abe04e25e044..2a7e7bc08abc6 100644 --- a/Mathlib/MeasureTheory/Constructions/BorelSpace/Metric.lean +++ b/Mathlib/MeasureTheory/Constructions/BorelSpace/Metric.lean @@ -128,7 +128,7 @@ theorem tendsto_measure_cthickening {μ : Measure α} {s : Set α} have A : Tendsto (fun r => μ (cthickening r s)) (𝓝[Ioi 0] 0) (𝓝 (μ (closure s))) := by rw [closure_eq_iInter_cthickening] exact - tendsto_measure_biInter_gt (fun r _ => isClosed_cthickening.measurableSet) + tendsto_measure_biInter_gt (fun r _ => isClosed_cthickening.nullMeasurableSet) (fun i j _ ij => cthickening_mono ij _) hs have B : Tendsto (fun r => μ (cthickening r s)) (𝓝[Iic 0] 0) (𝓝 (μ (closure s))) := by apply Tendsto.congr' _ tendsto_const_nhds @@ -151,7 +151,7 @@ theorem tendsto_measure_thickening {μ : Measure α} {s : Set α} (hs : ∃ R > 0, μ (thickening R s) ≠ ∞) : Tendsto (fun r => μ (thickening r s)) (𝓝[>] 0) (𝓝 (μ (closure s))) := by rw [closure_eq_iInter_thickening] - exact tendsto_measure_biInter_gt (fun r _ => isOpen_thickening.measurableSet) + exact tendsto_measure_biInter_gt (fun r _ => isOpen_thickening.nullMeasurableSet) (fun i j _ ij => thickening_mono ij _) hs /-- If a closed set has a thickening with finite measure, then the measure of its diff --git a/Mathlib/MeasureTheory/Constructions/BorelSpace/Order.lean b/Mathlib/MeasureTheory/Constructions/BorelSpace/Order.lean index d848798cf7bd9..42987950d650c 100644 --- a/Mathlib/MeasureTheory/Constructions/BorelSpace/Order.lean +++ b/Mathlib/MeasureTheory/Constructions/BorelSpace/Order.lean @@ -398,8 +398,8 @@ theorem ext_of_Iic {α : Type*} [TopologicalSpace α] {m : MeasurableSpace α} · rcases exists_countable_dense_bot_top α with ⟨s, hsc, hsd, -, hst⟩ have : DirectedOn (· ≤ ·) s := directedOn_iff_directed.2 (Subtype.mono_coe _).directed_le simp only [← biSup_measure_Iic hsc (hsd.exists_ge' hst) this, h] - rw [← Iic_diff_Iic, measure_diff (Iic_subset_Iic.2 hlt.le) measurableSet_Iic, - measure_diff (Iic_subset_Iic.2 hlt.le) measurableSet_Iic, h a, h b] + rw [← Iic_diff_Iic, measure_diff (Iic_subset_Iic.2 hlt.le) measurableSet_Iic.nullMeasurableSet, + measure_diff (Iic_subset_Iic.2 hlt.le) measurableSet_Iic.nullMeasurableSet, h a, h b] · rw [← h a] exact (measure_lt_top μ _).ne · exact (measure_lt_top μ _).ne @@ -558,6 +558,7 @@ theorem Measurable.isLUB_of_mem {ι} [Countable ι] {f : ι → δ → α} {g g' simp only [mem_singleton_iff] · rintro - rfl exact ⟨i, rfl⟩ + simp only [exists_prop'] at this simp [A, this, hg' hb, isLUB_singleton] theorem AEMeasurable.isLUB {ι} {μ : Measure δ} [Countable ι] {f : ι → δ → α} {g : δ → α} diff --git a/Mathlib/MeasureTheory/Constructions/BorelSpace/Real.lean b/Mathlib/MeasureTheory/Constructions/BorelSpace/Real.lean index 9e03eae8ea344..b566424678fd2 100644 --- a/Mathlib/MeasureTheory/Constructions/BorelSpace/Real.lean +++ b/Mathlib/MeasureTheory/Constructions/BorelSpace/Real.lean @@ -505,7 +505,7 @@ variable (μ : Measure ℝ) [IsFiniteMeasureOnCompacts μ] lemma tendsto_measure_Icc_nhdsWithin_right' (b : ℝ) : Tendsto (fun δ ↦ μ (Icc (b - δ) (b + δ))) (𝓝[>] (0 : ℝ)) (𝓝 (μ {b})) := by rw [Real.singleton_eq_inter_Icc] - apply tendsto_measure_biInter_gt (fun r hr ↦ measurableSet_Icc) + apply tendsto_measure_biInter_gt (fun r hr ↦ measurableSet_Icc.nullMeasurableSet) · intro r s _rpos hrs exact Icc_subset_Icc (by linarith) (by linarith) · exact ⟨1, zero_lt_one, isCompact_Icc.measure_ne_top⟩ diff --git a/Mathlib/MeasureTheory/Constructions/EventuallyMeasurable.lean b/Mathlib/MeasureTheory/Constructions/EventuallyMeasurable.lean index fe7b968db5833..c26b40b3beb7d 100644 --- a/Mathlib/MeasureTheory/Constructions/EventuallyMeasurable.lean +++ b/Mathlib/MeasureTheory/Constructions/EventuallyMeasurable.lean @@ -33,11 +33,11 @@ TODO: Implement the latter. open Filter Set MeasurableSpace -variable {α : Type*} (m : MeasurableSpace α) (l : Filter α) [CountableInterFilter l] {s t : Set α} +variable {α : Type*} (m : MeasurableSpace α) {s t : Set α} /-- The `MeasurableSpace` of sets which are measurable with respect to a given σ-algebra `m` on `α`, modulo a given σ-filter `l` on `α`. -/ -def EventuallyMeasurableSpace : MeasurableSpace α where +def EventuallyMeasurableSpace (l : Filter α) [CountableInterFilter l] : MeasurableSpace α where MeasurableSet' s := ∃ t, MeasurableSet t ∧ s =ᶠ[l] t measurableSet_empty := ⟨∅, MeasurableSet.empty, EventuallyEq.refl _ _ ⟩ measurableSet_compl := fun s ⟨t, ht, hts⟩ => ⟨tᶜ, ht.compl, hts.compl⟩ @@ -48,9 +48,11 @@ def EventuallyMeasurableSpace : MeasurableSpace α where /-- We say a set `s` is an `EventuallyMeasurableSet` with respect to a given σ-algebra `m` and σ-filter `l` if it differs from a set in `m` by a set in the dual ideal of `l`. -/ -def EventuallyMeasurableSet (s : Set α) : Prop := @MeasurableSet _ (EventuallyMeasurableSpace m l) s +def EventuallyMeasurableSet (l : Filter α) [CountableInterFilter l] (s : Set α) : Prop := + @MeasurableSet _ (EventuallyMeasurableSpace m l) s -variable {l m} +variable {l : Filter α} [CountableInterFilter l] +variable {m} theorem MeasurableSet.eventuallyMeasurableSet (hs : MeasurableSet s) : EventuallyMeasurableSet m l s := diff --git a/Mathlib/MeasureTheory/Constructions/HaarToSphere.lean b/Mathlib/MeasureTheory/Constructions/HaarToSphere.lean index 97bd8507cbce3..9326504897129 100644 --- a/Mathlib/MeasureTheory/Constructions/HaarToSphere.lean +++ b/Mathlib/MeasureTheory/Constructions/HaarToSphere.lean @@ -74,8 +74,8 @@ theorem toSphere_apply_univ : μ.toSphere univ = dim E * μ (ball 0 1) := by instance : IsFiniteMeasure μ.toSphere where measure_univ_lt_top := by rw [toSphere_apply_univ'] - exact ENNReal.mul_lt_top (ENNReal.natCast_ne_top _) <| - ne_top_of_le_ne_top measure_ball_lt_top.ne <| measure_mono diff_subset + exact ENNReal.mul_lt_top (ENNReal.natCast_lt_top _) <| + measure_ball_lt_top.trans_le' <| measure_mono diff_subset /-- The measure on `(0, +∞)` that has density `(· ^ n)` with respect to the Lebesgue measure. -/ def volumeIoiPow (n : ℕ) : Measure (Ioi (0 : ℝ)) := diff --git a/Mathlib/MeasureTheory/Constructions/Pi.lean b/Mathlib/MeasureTheory/Constructions/Pi.lean index 3482a2535938d..12c48b54b7654 100644 --- a/Mathlib/MeasureTheory/Constructions/Pi.lean +++ b/Mathlib/MeasureTheory/Constructions/Pi.lean @@ -325,7 +325,7 @@ def FiniteSpanningSetsIn.pi {C : ∀ i, Set (Set (α i))} _ = ∏ i, μ i (toMeasurable (μ i) ((hμ i).set (e n i))) := (pi_pi_aux μ _ fun i => measurableSet_toMeasurable _ _) _ = ∏ i, μ i ((hμ i).set (e n i)) := by simp only [measure_toMeasurable] - _ < ∞ := ENNReal.prod_lt_top fun i _ => ((hμ i).finite _).ne + _ < ∞ := ENNReal.prod_lt_top fun i _ => (hμ i).finite _ · simp_rw [(surjective_decode_iget (ι → ℕ)).iUnion_comp fun x => Set.pi univ fun i => (hμ i).set (x i), iUnion_univ_pi fun i => (hμ i).set, (hμ _).spanning, Set.pi_univ] @@ -385,7 +385,7 @@ instance {α : ι → Type*} [∀ i, MeasureSpace (α i)] [∀ i, SigmaFinite (v instance pi.instIsFiniteMeasure [∀ i, IsFiniteMeasure (μ i)] : IsFiniteMeasure (Measure.pi μ) := - ⟨Measure.pi_univ μ ▸ ENNReal.prod_lt_top (fun i _ ↦ measure_ne_top (μ i) _)⟩ + ⟨Measure.pi_univ μ ▸ ENNReal.prod_lt_top (fun i _ ↦ measure_lt_top (μ i) _)⟩ instance {α : ι → Type*} [∀ i, MeasureSpace (α i)] [∀ i, IsFiniteMeasure (volume : Measure (α i))] : IsFiniteMeasure (volume : Measure (∀ i, α i)) := @@ -570,7 +570,7 @@ instance pi.isLocallyFiniteMeasure choose s hxs ho hμ using fun i => (μ i).exists_isOpen_measure_lt_top (x i) refine ⟨pi univ s, set_pi_mem_nhds finite_univ fun i _ => IsOpen.mem_nhds (ho i) (hxs i), ?_⟩ rw [pi_pi] - exact ENNReal.prod_lt_top fun i _ => (hμ i).ne + exact ENNReal.prod_lt_top fun i _ => hμ i instance {X : ι → Type*} [∀ i, TopologicalSpace (X i)] [∀ i, MeasureSpace (X i)] [∀ i, SigmaFinite (volume : Measure (X i))] @@ -648,7 +648,7 @@ instance pi.isFiniteMeasureOnCompacts [∀ i, TopologicalSpace (α i)] exact lt_of_le_of_lt (measure_mono (univ.subset_pi_eval_image K)) this rw [Measure.pi_pi] refine WithTop.prod_lt_top ?_ - exact fun i _ => ne_of_lt (IsCompact.measure_lt_top (IsCompact.image hK (continuous_apply i))) + exact fun i _ => IsCompact.measure_lt_top (IsCompact.image hK (continuous_apply i)) instance {X : ι → Type*} [∀ i, MeasureSpace (X i)] [∀ i, TopologicalSpace (X i)] [∀ i, SigmaFinite (volume : Measure (X i))] diff --git a/Mathlib/MeasureTheory/Constructions/Polish/Basic.lean b/Mathlib/MeasureTheory/Constructions/Polish/Basic.lean index be0467e7351a6..f1677d8c92db5 100644 --- a/Mathlib/MeasureTheory/Constructions/Polish/Basic.lean +++ b/Mathlib/MeasureTheory/Constructions/Polish/Basic.lean @@ -561,7 +561,7 @@ theorem measurableSet_preimage_iff_preimage_val {f : X → Z} [CountablySeparate /-- If `f : X → Z` is a Borel measurable map from a standard Borel space to a countably separated measurable space and the range of `f` is measurable, then the preimage of a set `s` is measurable -if and only if the intesection with `Set.range f` is measurable. -/ +if and only if the intersection with `Set.range f` is measurable. -/ theorem measurableSet_preimage_iff_inter_range {f : X → Z} [CountablySeparated (range f)] (hf : Measurable f) (hr : MeasurableSet (range f)) {s : Set Z} : MeasurableSet (f ⁻¹' s) ↔ MeasurableSet (s ∩ range f) := by @@ -985,7 +985,7 @@ noncomputable def measurableEquivNatBoolOfNotCountable (h : ¬Countable α) : α apply Nonempty.some letI := upgradeStandardBorel α obtain ⟨f, -, fcts, finj⟩ := - isClosed_univ.exists_nat_bool_injection_of_not_countable + isClosed_univ.exists_nat_bool_injection_of_not_countable (α := α) (by rwa [← countable_coe_iff, (Equiv.Set.univ _).countable_iff]) obtain ⟨g, gmeas, ginj⟩ := MeasurableSpace.measurable_injection_nat_bool_of_countablySeparated α diff --git a/Mathlib/MeasureTheory/Constructions/Polish/EmbeddingReal.lean b/Mathlib/MeasureTheory/Constructions/Polish/EmbeddingReal.lean index f6436e70180fc..67a330bbb5bb7 100644 --- a/Mathlib/MeasureTheory/Constructions/Polish/EmbeddingReal.lean +++ b/Mathlib/MeasureTheory/Constructions/Polish/EmbeddingReal.lean @@ -63,4 +63,9 @@ lemma measurableEmbedding_embeddingReal (Ω : Type*) [MeasurableSpace Ω] [Stand MeasurableEmbedding (embeddingReal Ω) := (exists_measurableEmbedding_real Ω).choose_spec +@[fun_prop] +lemma measurable_embeddingReal (Ω : Type*) [MeasurableSpace Ω] [StandardBorelSpace Ω] : + Measurable (embeddingReal Ω) := + (measurableEmbedding_embeddingReal Ω).measurable + end MeasureTheory diff --git a/Mathlib/MeasureTheory/Constructions/Prod/Basic.lean b/Mathlib/MeasureTheory/Constructions/Prod/Basic.lean index febc262889c89..a8e405fc234e1 100644 --- a/Mathlib/MeasureTheory/Constructions/Prod/Basic.lean +++ b/Mathlib/MeasureTheory/Constructions/Prod/Basic.lean @@ -383,7 +383,7 @@ instance prod.instIsFiniteMeasure {α β : Type*} {mα : MeasurableSpace α} {m IsFiniteMeasure (μ.prod ν) := by constructor rw [← univ_prod_univ, prod_prod] - exact mul_lt_top (measure_lt_top _ _).ne (measure_lt_top _ _).ne + exact mul_lt_top (measure_lt_top _ _) (measure_lt_top _ _) instance {α β : Type*} [MeasureSpace α] [MeasureSpace β] [IsFiniteMeasure (volume : Measure α)] [IsFiniteMeasure (volume : Measure β)] : IsFiniteMeasure (volume : Measure (α × β)) := @@ -412,7 +412,7 @@ instance prod.instIsFiniteMeasureOnCompacts {α β : Type*} [TopologicalSpace α exact ⟨⟨y, hxy⟩, ⟨x, hxy⟩⟩ apply lt_of_le_of_lt (measure_mono this) rw [hL, prod_prod] - exact mul_lt_top (hK.image continuous_fst).measure_ne_top (hK.image continuous_snd).measure_ne_top + exact mul_lt_top (hK.image continuous_fst).measure_lt_top (hK.image continuous_snd).measure_lt_top instance {X Y : Type*} [TopologicalSpace X] [MeasureSpace X] [IsFiniteMeasureOnCompacts (volume : Measure X)] @@ -520,7 +520,7 @@ lemma _root_.MeasureTheory.NullMeasurableSet.right_of_prod {s : Set α} {t : Set /-- If `Prod.snd ⁻¹' t` is a null measurable set and `μ ≠ 0`, then `t` is a null measurable set. -/ lemma _root_.MeasureTheory.NullMeasurableSet.of_preimage_snd [NeZero μ] {t : Set β} (h : NullMeasurableSet (Prod.snd ⁻¹' t) (μ.prod ν)) : NullMeasurableSet t ν := - .right_of_prod (by rwa [univ_prod]) (NeZero.ne _) + .right_of_prod (by rwa [univ_prod]) (NeZero.ne (μ univ)) /-- `Prod.snd ⁻¹' t` is null measurable w.r.t. `μ.prod ν` iff `t` is null measurable w.r.t. `ν` provided that `μ ≠ 0`. -/ @@ -541,7 +541,7 @@ noncomputable def FiniteSpanningSetsIn.prod {ν : Measure β} {C : Set (Set α)} ⟨fun n => hμ.set n.unpair.1 ×ˢ hν.set n.unpair.2, fun n => mem_image2_of_mem (hμ.set_mem _) (hν.set_mem _), fun n => ?_, ?_⟩ · rw [prod_prod] - exact mul_lt_top (hμ.finite _).ne (hν.finite _).ne + exact mul_lt_top (hμ.finite _) (hν.finite _) · simp_rw [iUnion_unpair_prod, hμ.spanning, hν.spanning, univ_prod_univ] lemma prod_sum_left {ι : Type*} (m : ι → Measure α) (μ : Measure β) [SFinite μ] : @@ -657,7 +657,7 @@ lemma _root_.MeasureTheory.NullMeasurableSet.left_of_prod {s : Set α} {t : Set /-- If `Prod.fst ⁻¹' s` is a null measurable set and `ν ≠ 0`, then `s` is a null measurable set. -/ lemma _root_.MeasureTheory.NullMeasurableSet.of_preimage_fst [NeZero ν] {s : Set α} (h : NullMeasurableSet (Prod.fst ⁻¹' s) (μ.prod ν)) : NullMeasurableSet s μ := - .left_of_prod (by rwa [prod_univ]) (NeZero.ne _) + .left_of_prod (by rwa [prod_univ]) (NeZero.ne (ν univ)) /-- `Prod.fst ⁻¹' s` is null measurable w.r.t. `μ.prod ν` iff `s` is null measurable w.r.t. `μ` provided that `ν ≠ 0`. -/ @@ -1012,6 +1012,9 @@ theorem fst_map_prod_mk {X : α → β} {Y : α → γ} {μ : Measure α} (hY : Measurable Y) : (μ.map fun a => (X a, Y a)).fst = μ.map X := fst_map_prod_mk₀ hY.aemeasurable +@[gcongr] +theorem fst_mono {μ : Measure (α × β)} (h : ρ ≤ μ) : ρ.fst ≤ μ.fst := map_mono h measurable_fst + /-- Marginal measure on `β` obtained from a measure on `ρ` `α × β`, defined by `ρ.map Prod.snd`. -/ noncomputable def snd (ρ : Measure (α × β)) : Measure β := ρ.map Prod.snd @@ -1056,6 +1059,9 @@ theorem snd_map_prod_mk {X : α → β} {Y : α → γ} {μ : Measure α} (hX : (μ.map fun a => (X a, Y a)).snd = μ.map Y := snd_map_prod_mk₀ hX.aemeasurable +@[gcongr] +theorem snd_mono {μ : Measure (α × β)} (h : ρ ≤ μ) : ρ.snd ≤ μ.snd := map_mono h measurable_snd + @[simp] lemma fst_map_swap : (ρ.map Prod.swap).fst = ρ.snd := by rw [Measure.fst, Measure.map_map measurable_fst measurable_swap] rfl diff --git a/Mathlib/MeasureTheory/Constructions/Prod/Integral.lean b/Mathlib/MeasureTheory/Constructions/Prod/Integral.lean index fd2189d76b79a..87e289fa69c30 100644 --- a/Mathlib/MeasureTheory/Constructions/Prod/Integral.lean +++ b/Mathlib/MeasureTheory/Constructions/Prod/Integral.lean @@ -422,7 +422,7 @@ theorem integral_prod (f : α × β → E) (hf : Integrable f (μ.prod ν)) : revert f apply Integrable.induction · intro c s hs h2s - simp_rw [integral_indicator hs, ← indicator_comp_right, Function.comp, + simp_rw [integral_indicator hs, ← indicator_comp_right, Function.comp_def, integral_indicator (measurable_prod_mk_left hs), setIntegral_const, integral_smul_const, integral_toReal (measurable_measure_prod_mk_left hs).aemeasurable (ae_measure_lt_top hs h2s.ne)] diff --git a/Mathlib/MeasureTheory/Covering/Besicovitch.lean b/Mathlib/MeasureTheory/Covering/Besicovitch.lean index 29bfebfa3b723..5fc2bf194df58 100644 --- a/Mathlib/MeasureTheory/Covering/Besicovitch.lean +++ b/Mathlib/MeasureTheory/Covering/Besicovitch.lean @@ -319,7 +319,7 @@ theorem mem_iUnionUpTo_lastStep (x : β) : p.c x ∈ p.iUnionUpTo p.lastStep := rcases A y with (Hy | Hy) · exact hy1 Hy · rw [← div_eq_inv_mul] at hy2 - have := (div_le_iff' (_root_.zero_lt_one.trans p.one_lt_tau)).1 hy2.le + have := (div_le_iff₀' (_root_.zero_lt_one.trans p.one_lt_tau)).1 hy2.le exact lt_irrefl _ (Hy.trans_le this) /-- If there are no configurations of satellites with `N+1` points, one never uses more than `N` @@ -621,9 +621,9 @@ theorem exist_finset_disjoint_balls_large_measure (μ : Measure α) [IsFiniteMea rw [← diff_inter_self_eq_diff, measure_diff_le_iff_le_add _ inter_subset_right (measure_lt_top μ _).ne] swap - · apply MeasurableSet.inter _ omeas - haveI : Encodable (u i) := (u_count i).toEncodable - exact MeasurableSet.iUnion fun b => MeasurableSet.iUnion fun _ => measurableSet_closedBall + · exact .inter + (w.nullMeasurableSet_biUnion fun _ _ ↦ measurableSet_closedBall.nullMeasurableSet) + omeas.nullMeasurableSet calc μ o = 1 / (N + 1) * μ s + N / (N + 1) * μ s := by rw [μo, ← add_mul, ENNReal.div_add_div_same, add_comm, ENNReal.div_self, one_mul] <;> simp @@ -808,7 +808,7 @@ theorem exists_disjoint_closedBall_covering_ae_aux (μ : Measure α) [SFinite μ t.PairwiseDisjoint fun p => closedBall p.1 p.2 := by /- This is deduced from the finite measure case, by using a finite measure with respect to which the initial sigma-finite measure is absolutely continuous. -/ - rcases exists_absolutelyContinuous_isFiniteMeasure μ with ⟨ν, hν, hμν⟩ + rcases exists_isFiniteMeasure_absolutelyContinuous μ with ⟨ν, hν, hμν, -⟩ rcases exists_disjoint_closedBall_covering_ae_of_finiteMeasure_aux ν f s hf with ⟨t, t_count, ts, tr, tν, tdisj⟩ exact ⟨t, t_count, ts, tr, hμν tν, tdisj⟩ diff --git a/Mathlib/MeasureTheory/Covering/BesicovitchVectorSpace.lean b/Mathlib/MeasureTheory/Covering/BesicovitchVectorSpace.lean index 9311803c85be1..97a0b59d00769 100644 --- a/Mathlib/MeasureTheory/Covering/BesicovitchVectorSpace.lean +++ b/Mathlib/MeasureTheory/Covering/BesicovitchVectorSpace.lean @@ -319,11 +319,11 @@ theorem exists_normalized_aux1 {N : ℕ} {τ : ℝ} (a : SatelliteConfig E N τ) _ = (1 : ℝ) - δ ^ 2 / 16 := by ring _ ≤ 1 := by linarith only [sq_nonneg δ] have J : 1 - δ ≤ 1 - δ / 4 := by linarith only [δnonneg] - have K : 1 - δ / 4 ≤ τ⁻¹ := by rw [inv_eq_one_div, le_div_iff τpos]; exact I + have K : 1 - δ / 4 ≤ τ⁻¹ := by rw [inv_eq_one_div, le_div_iff₀ τpos]; exact I suffices L : τ⁻¹ ≤ ‖a.c i - a.c j‖ by linarith only [J, K, L] have hτ' : ∀ k, τ⁻¹ ≤ a.r k := by intro k - rw [inv_eq_one_div, div_le_iff τpos, ← lastr, mul_comm] + rw [inv_eq_one_div, div_le_iff₀ τpos, ← lastr, mul_comm] exact a.hlast' k hτ rcases ah inej with (H | H) · apply le_trans _ H.1 @@ -380,7 +380,7 @@ theorem exists_normalized_aux2 {N : ℕ} {τ : ℝ} (a : SatelliteConfig E N τ) _ ≤ ‖a.c i - d‖ + ‖d - a.c j‖ := by simp only [← dist_eq_norm, dist_triangle] _ ≤ ‖a.c i - d‖ + (a.r j - 1) := by apply add_le_add_left - have A : 0 ≤ 1 - 2 / ‖a.c j‖ := by simpa [div_le_iff (zero_le_two.trans_lt hj)] using hj.le + have A : 0 ≤ 1 - 2 / ‖a.c j‖ := by simpa [div_le_iff₀ (zero_le_two.trans_lt hj)] using hj.le rw [← one_smul ℝ (a.c j), hd, ← sub_smul, norm_smul, norm_sub_rev, Real.norm_eq_abs, abs_of_nonneg A, sub_mul] field_simp [(zero_le_two.trans_lt hj).ne'] @@ -417,7 +417,7 @@ theorem exists_normalized_aux3 {N : ℕ} {τ : ℝ} (a : SatelliteConfig E N τ) nth_rw 1 [← one_smul ℝ (a.c j)] rw [add_left_inj, hd, ← sub_smul, norm_smul, Real.norm_eq_abs, abs_of_nonneg, sub_mul, one_mul, div_mul_cancel₀ _ (zero_le_two.trans_lt hj).ne'] - rwa [sub_nonneg, div_le_iff (zero_lt_two.trans hj), one_mul] + rwa [sub_nonneg, div_le_iff₀ (zero_lt_two.trans hj), one_mul] have J : a.r j - ‖a.c j - a.c i‖ ≤ s / 2 * δ := calc a.r j - ‖a.c j - a.c i‖ ≤ s * (τ - 1) := by diff --git a/Mathlib/MeasureTheory/Decomposition/Exhaustion.lean b/Mathlib/MeasureTheory/Decomposition/Exhaustion.lean index e58004315b7e8..a6f283377c6c5 100644 --- a/Mathlib/MeasureTheory/Decomposition/Exhaustion.lean +++ b/Mathlib/MeasureTheory/Decomposition/Exhaustion.lean @@ -252,9 +252,9 @@ section SFinite lemma measure_eq_top_of_subset_compl_sigmaFiniteSetWRT [SFinite ν] (hs_subset : s ⊆ (μ.sigmaFiniteSetWRT ν)ᶜ) (hνs : ν s ≠ 0) : μ s = ∞ := by - have ⟨ν', hν', hνν'⟩ := exists_absolutelyContinuous_isFiniteMeasure ν + have ⟨ν', hν', hνν', _⟩ := exists_isFiniteMeasure_absolutelyContinuous ν have h : ∃ s : Set α, MeasurableSet s ∧ SigmaFinite (μ.restrict s) - ∧ (∀ t (_ : t ⊆ sᶜ) (_ : ν t ≠ 0), μ t = ∞) := by + ∧ (∀ t ⊆ sᶜ, ν t ≠ 0 → μ t = ∞) := by refine ⟨μ.sigmaFiniteSetWRT' ν', measurableSet_sigmaFiniteSetWRT', sigmaFinite_restrict_sigmaFiniteSetWRT' _ _, fun t ht_subset hνt ↦ measure_eq_top_of_subset_compl_sigmaFiniteSetWRT' ht_subset ?_⟩ @@ -306,9 +306,8 @@ lemma measurableSet_sigmaFiniteSet : MeasurableSet μ.sigmaFiniteSet := lemma measure_eq_zero_or_top_of_subset_compl_sigmaFiniteSet [SFinite μ] (ht_subset : t ⊆ μ.sigmaFiniteSetᶜ) : μ t = 0 ∨ μ t = ∞ := by - by_cases h0 : μ t = 0 - · exact Or.inl h0 - · exact Or.inr <| measure_eq_top_of_subset_compl_sigmaFiniteSetWRT ht_subset h0 + rw [or_iff_not_imp_left] + exact measure_eq_top_of_subset_compl_sigmaFiniteSetWRT ht_subset /-- The measure `μ.restrict μ.sigmaFiniteSetᶜ` takes only two values: 0 and ∞ . -/ lemma restrict_compl_sigmaFiniteSet_eq_zero_or_top (μ : Measure α) [SFinite μ] (s : Set α) : diff --git a/Mathlib/MeasureTheory/Decomposition/Lebesgue.lean b/Mathlib/MeasureTheory/Decomposition/Lebesgue.lean index 4842fd3b46f30..243efac2011bc 100644 --- a/Mathlib/MeasureTheory/Decomposition/Lebesgue.lean +++ b/Mathlib/MeasureTheory/Decomposition/Lebesgue.lean @@ -108,9 +108,15 @@ theorem haveLebesgueDecomposition_add (μ ν : Measure α) [HaveLebesgueDecompos μ = μ.singularPart ν + ν.withDensity (μ.rnDeriv ν) := (haveLebesgueDecomposition_spec μ ν).2.2 +/-- For the versions of this lemma where `ν.withDensity (μ.rnDeriv ν)` or `μ.singularPart ν` are +isolated, see `MeasureTheory.Measure.measure_sub_singularPart` and +`MeasureTheory.Measure.measure_sub_rnDeriv`. -/ lemma singularPart_add_rnDeriv (μ ν : Measure α) [HaveLebesgueDecomposition μ ν] : μ.singularPart ν + ν.withDensity (μ.rnDeriv ν) = μ := (haveLebesgueDecomposition_add μ ν).symm +/-- For the versions of this lemma where `μ.singularPart ν` or `ν.withDensity (μ.rnDeriv ν)` are +isolated, see `MeasureTheory.Measure.measure_sub_singularPart` and +`MeasureTheory.Measure.measure_sub_rnDeriv`. -/ lemma rnDeriv_add_singularPart (μ ν : Measure α) [HaveLebesgueDecomposition μ ν] : ν.withDensity (μ.rnDeriv ν) + μ.singularPart ν = μ := by rw [add_comm, singularPart_add_rnDeriv] @@ -464,6 +470,17 @@ lemma singularPart_restrict (μ ν : Measure α) [HaveLebesgueDecomposition μ rw [withDensity_indicator hs, ← restrict_withDensity hs, ← Measure.restrict_add, ← μ.haveLebesgueDecomposition_add ν] +lemma measure_sub_singularPart (μ ν : Measure α) [HaveLebesgueDecomposition μ ν] + [IsFiniteMeasure μ] : + μ - μ.singularPart ν = ν.withDensity (μ.rnDeriv ν) := by + nth_rw 1 [← rnDeriv_add_singularPart μ ν] + exact Measure.add_sub_cancel + +lemma measure_sub_rnDeriv (μ ν : Measure α) [HaveLebesgueDecomposition μ ν] [IsFiniteMeasure μ] : + μ - ν.withDensity (μ.rnDeriv ν) = μ.singularPart ν := by + nth_rw 1 [← singularPart_add_rnDeriv μ ν] + exact Measure.add_sub_cancel + /-- Given measures `μ` and `ν`, if `s` is a measure mutually singular to `ν` and `f` is a measurable function such that `μ = s + fν`, then `f = μ.rnDeriv ν`. diff --git a/Mathlib/MeasureTheory/Decomposition/RadonNikodym.lean b/Mathlib/MeasureTheory/Decomposition/RadonNikodym.lean index aa62a9d723094..48bb69b5fadb2 100644 --- a/Mathlib/MeasureTheory/Decomposition/RadonNikodym.lean +++ b/Mathlib/MeasureTheory/Decomposition/RadonNikodym.lean @@ -390,6 +390,12 @@ lemma integral_toReal_rnDeriv [SigmaFinite μ] [SigmaFinite ν] (hμν : μ ≪ ∫ x, (μ.rnDeriv ν x).toReal ∂ν = (μ Set.univ).toReal := by rw [← integral_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] + end integral lemma rnDeriv_mul_rnDeriv {κ : Measure α} [SigmaFinite μ] [SigmaFinite ν] [SigmaFinite κ] @@ -563,6 +569,11 @@ theorem integral_rnDeriv_smul [HaveLebesgueDecomposition μ ν] (hμν : μ ≪ contrapose! hf exact (integrable_rnDeriv_smul_iff hμν).mp hf +lemma setIntegral_rnDeriv_smul [HaveLebesgueDecomposition μ ν] (hμν : μ ≪ ν) + [SigmaFinite μ] {f : α → E} {s : Set α} (hs : MeasurableSet s) : + ∫ x in s, (μ.rnDeriv ν x).toReal • f x ∂ν = ∫ x in s, f x ∂μ := by + simp_rw [← integral_indicator hs, Set.indicator_smul, integral_rnDeriv_smul hμν] + end IntegralRNDerivMul end MeasureTheory diff --git a/Mathlib/MeasureTheory/Decomposition/SignedHahn.lean b/Mathlib/MeasureTheory/Decomposition/SignedHahn.lean index 054d7829fab2f..3891d1175c65d 100644 --- a/Mathlib/MeasureTheory/Decomposition/SignedHahn.lean +++ b/Mathlib/MeasureTheory/Decomposition/SignedHahn.lean @@ -81,7 +81,7 @@ To implement this in Lean, we define several auxiliary definitions. where `restrictNonposSeq s i 0 = someExistsOneDivLT s (i \ ∅)` and `restrictNonposSeq s i (n + 1) = someExistsOneDivLT s (i \ ⋃ k ≤ n, restrictNonposSeq k)`. - This definition represents the sequence $(A_n)$ in the proof as described above. + This definition represents the sequence $(A_n)$ in the proof as described above. With these definitions, we are able consider the case where the sequence terminates separately, allowing us to prove `exists_subset_restrict_nonpos`. diff --git a/Mathlib/MeasureTheory/Decomposition/UnsignedHahn.lean b/Mathlib/MeasureTheory/Decomposition/UnsignedHahn.lean index f6b3615d79356..de9f47a8ba7a8 100644 --- a/Mathlib/MeasureTheory/Decomposition/UnsignedHahn.lean +++ b/Mathlib/MeasureTheory/Decomposition/UnsignedHahn.lean @@ -56,9 +56,8 @@ theorem hahn_decomposition [IsFiniteMeasure μ] [IsFiniteMeasure ν] : have d_Inter (s : ℕ → Set α) (hs : ∀ n, MeasurableSet (s n)) (hm : ∀ n m, n ≤ m → s m ⊆ s n) : Tendsto (fun n => d (s n)) atTop (𝓝 (d (⋂ n, s n))) := by refine Tendsto.sub ?_ ?_ <;> - refine - NNReal.tendsto_coe.2 <| - (ENNReal.tendsto_toNNReal <| ?_).comp <| tendsto_measure_iInter hs hm ?_ + refine NNReal.tendsto_coe.2 <| (ENNReal.tendsto_toNNReal <| ?_).comp <| + tendsto_measure_iInter (fun n ↦ (hs n).nullMeasurableSet) hm ?_ exacts [hμ _, ⟨0, hμ _⟩, hν _, ⟨0, hν _⟩] have bdd_c : BddAbove c := by use (μ univ).toNNReal diff --git a/Mathlib/MeasureTheory/Function/AEEqFun.lean b/Mathlib/MeasureTheory/Function/AEEqFun.lean index cb6030efa880d..c0d68d263e2f8 100644 --- a/Mathlib/MeasureTheory/Function/AEEqFun.lean +++ b/Mathlib/MeasureTheory/Function/AEEqFun.lean @@ -93,7 +93,7 @@ variable (α) /-- The space of equivalence classes of almost everywhere strongly measurable functions, where two strongly measurable functions are equivalent if they agree almost everywhere, i.e., - they differ on a set of measure `0`. -/ + they differ on a set of measure `0`. -/ def AEEqFun (μ : Measure α) : Type _ := Quotient (μ.aeEqSetoid β) @@ -235,7 +235,7 @@ variable [TopologicalSpace γ] [MeasurableSpace β] {ν : MeasureTheory.Measure /-- Composition of an almost everywhere equal function and a quasi measure preserving function. This is an important special case of `AEEqFun.compQuasiMeasurePreserving`. We use a separate -definition so that lemmas that need `f` to be measure preserving can be `@[simp]` lemmas. -/ +definition so that lemmas that need `f` to be measure preserving can be `@[simp]` lemmas. -/ def compMeasurePreserving (g : β →ₘ[ν] γ) (f : α → β) (hf : MeasurePreserving f μ ν) : α →ₘ[μ] γ := g.compQuasiMeasurePreserving f hf.quasiMeasurePreserving diff --git a/Mathlib/MeasureTheory/Function/AEEqOfIntegral.lean b/Mathlib/MeasureTheory/Function/AEEqOfIntegral.lean index 75e3cb37ba203..bb4121b69171b 100644 --- a/Mathlib/MeasureTheory/Function/AEEqOfIntegral.lean +++ b/Mathlib/MeasureTheory/Function/AEEqOfIntegral.lean @@ -581,7 +581,7 @@ alias Integrable.ae_eq_of_forall_set_integral_eq := variable {β : Type*} [TopologicalSpace β] [MeasurableSpace β] [BorelSpace β] /-- If an integrable function has zero integral on all closed sets, then it is zero -almost everwhere. -/ +almost everywhere. -/ lemma ae_eq_zero_of_forall_setIntegral_isClosed_eq_zero {μ : Measure β} {f : β → E} (hf : Integrable f μ) (h'f : ∀ (s : Set β), IsClosed s → ∫ x in s, f x ∂μ = 0) : f =ᵐ[μ] 0 := by @@ -604,7 +604,7 @@ alias ae_eq_zero_of_forall_set_integral_isClosed_eq_zero := ae_eq_zero_of_forall_setIntegral_isClosed_eq_zero /-- If an integrable function has zero integral on all compact sets in a sigma-compact space, then -it is zero almost everwhere. -/ +it is zero almost everywhere. -/ lemma ae_eq_zero_of_forall_setIntegral_isCompact_eq_zero [SigmaCompactSpace β] [R1Space β] {μ : Measure β} {f : β → E} (hf : Integrable f μ) (h'f : ∀ (s : Set β), IsCompact s → ∫ x in s, f x ∂μ = 0) : @@ -628,7 +628,7 @@ lemma ae_eq_zero_of_forall_setIntegral_isCompact_eq_zero · exact hf.integrableOn /-- If a locally integrable function has zero integral on all compact sets in a sigma-compact space, -then it is zero almost everwhere. -/ +then it is zero almost everywhere. -/ lemma ae_eq_zero_of_forall_setIntegral_isCompact_eq_zero' [SigmaCompactSpace β] [R1Space β] {μ : Measure β} {f : β → E} (hf : LocallyIntegrable f μ) (h'f : ∀ (s : Set β), IsCompact s → ∫ x in s, f x ∂μ = 0) : diff --git a/Mathlib/MeasureTheory/Function/ConditionalExpectation/AEMeasurable.lean b/Mathlib/MeasureTheory/Function/ConditionalExpectation/AEMeasurable.lean index 9aeca60eb12fa..98a2a41d0a279 100644 --- a/Mathlib/MeasureTheory/Function/ConditionalExpectation/AEMeasurable.lean +++ b/Mathlib/MeasureTheory/Function/ConditionalExpectation/AEMeasurable.lean @@ -100,6 +100,12 @@ theorem const_inner {𝕜 β} [RCLike 𝕜] [NormedAddCommGroup β] [InnerProduc dsimp only rw [hx] +@[simp] theorem of_subsingleton [Subsingleton β] : AEStronglyMeasurable' m f μ := + ⟨f, by simp, by simp⟩ + +@[simp] theorem of_subsingleton' [Subsingleton α] : AEStronglyMeasurable' m f μ := + ⟨f, by simp, by simp⟩ + /-- An `m`-strongly measurable function almost everywhere equal to `f`. -/ noncomputable def mk (f : α → β) (hfm : AEStronglyMeasurable' m f μ) : α → β := hfm.choose diff --git a/Mathlib/MeasureTheory/Function/ConditionalExpectation/CondexpL1.lean b/Mathlib/MeasureTheory/Function/ConditionalExpectation/CondexpL1.lean index b900dbece2f95..779e0ed7f4ba6 100644 --- a/Mathlib/MeasureTheory/Function/ConditionalExpectation/CondexpL1.lean +++ b/Mathlib/MeasureTheory/Function/ConditionalExpectation/CondexpL1.lean @@ -11,7 +11,7 @@ This file contains two more steps of the construction of the conditional expecta completed in `MeasureTheory.Function.ConditionalExpectation.Basic`. See that file for a description of the full process. -The contitional expectation of an `L²` function is defined in +The conditional expectation of an `L²` function is defined in `MeasureTheory.Function.ConditionalExpectation.CondexpL2`. In this file, we perform two steps. * Show that the conditional expectation of the indicator of a measurable set with finite measure is integrable and define a map `Set α → (E →L[ℝ] (α →₁[μ] E))` which to a set associates a linear diff --git a/Mathlib/MeasureTheory/Function/ConditionalExpectation/CondexpL2.lean b/Mathlib/MeasureTheory/Function/ConditionalExpectation/CondexpL2.lean index bea64c5684025..fd79dc7a0b777 100644 --- a/Mathlib/MeasureTheory/Function/ConditionalExpectation/CondexpL2.lean +++ b/Mathlib/MeasureTheory/Function/ConditionalExpectation/CondexpL2.lean @@ -347,7 +347,7 @@ theorem integrable_condexpL2_indicator (hm : m ≤ m0) [SigmaFinite (μ.trim hm) (hs : MeasurableSet s) (hμs : μ s ≠ ∞) (x : E') : Integrable (β := E') (condexpL2 E' 𝕜 hm (indicatorConstLp 2 hs hμs x)) μ := by refine integrable_of_forall_fin_meas_le' hm (μ s * ‖x‖₊) - (ENNReal.mul_lt_top hμs ENNReal.coe_ne_top) ?_ ?_ + (ENNReal.mul_lt_top hμs.lt_top ENNReal.coe_lt_top) ?_ ?_ · rw [lpMeas_coe]; exact Lp.aestronglyMeasurable _ · refine fun t ht hμt => (setLIntegral_nnnorm_condexpL2_indicator_le hm hs hμs x ht hμt).trans ?_ @@ -426,7 +426,7 @@ with finite measure is integrable. -/ theorem integrable_condexpIndSMul (hm : m ≤ m0) [SigmaFinite (μ.trim hm)] (hs : MeasurableSet s) (hμs : μ s ≠ ∞) (x : G) : Integrable (condexpIndSMul hm hs hμs x) μ := by refine integrable_of_forall_fin_meas_le' hm (μ s * ‖x‖₊) - (ENNReal.mul_lt_top hμs ENNReal.coe_ne_top) ?_ ?_ + (ENNReal.mul_lt_top hμs.lt_top ENNReal.coe_lt_top) ?_ ?_ · exact Lp.aestronglyMeasurable _ · refine fun t ht hμt => (setLIntegral_nnnorm_condexpIndSMul_le hm hs hμs x ht hμt).trans ?_ gcongr diff --git a/Mathlib/MeasureTheory/Function/ContinuousMapDense.lean b/Mathlib/MeasureTheory/Function/ContinuousMapDense.lean index d16ec22981a70..be9517c3b1db9 100644 --- a/Mathlib/MeasureTheory/Function/ContinuousMapDense.lean +++ b/Mathlib/MeasureTheory/Function/ContinuousMapDense.lean @@ -366,7 +366,7 @@ namespace ContinuousMap /-- Continuous functions are dense in `MeasureTheory.Lp`, `1 ≤ p < ∞`. This theorem assumes that the domain is a compact space because otherwise `ContinuousMap.toLp` is undefined. Use -`BoundedContinuousFunction.toLp_denseRange` if the domain is not a compact space. -/ +`BoundedContinuousFunction.toLp_denseRange` if the domain is not a compact space. -/ theorem toLp_denseRange [CompactSpace α] [μ.WeaklyRegular] [IsFiniteMeasure μ] (hp : p ≠ ∞) : DenseRange (toLp p μ 𝕜 : C(α, E) →L[𝕜] Lp E p μ) := by refine (BoundedContinuousFunction.toLp_denseRange _ _ 𝕜 hp).mono ?_ diff --git a/Mathlib/MeasureTheory/Function/Egorov.lean b/Mathlib/MeasureTheory/Function/Egorov.lean index 402e64e727ca0..932a6fefb1d33 100644 --- a/Mathlib/MeasureTheory/Function/Egorov.lean +++ b/Mathlib/MeasureTheory/Function/Egorov.lean @@ -81,7 +81,8 @@ theorem measure_notConvergentSeq_tendsto_zero [SemilatticeSup ι] [Countable ι] rw [this] exact tendsto_const_nhds rw [← measure_inter_notConvergentSeq_eq_zero hfg n, Set.inter_iInter] - refine tendsto_measure_iInter (fun n => hsm.inter <| notConvergentSeq_measurableSet hf hg) + refine tendsto_measure_iInter + (fun n ↦ (hsm.inter <| notConvergentSeq_measurableSet hf hg).nullMeasurableSet) (fun k l hkl => Set.inter_subset_inter_right _ <| notConvergentSeq_antitone hkl) ⟨h.some, ne_top_of_le_ne_top hs (measure_mono Set.inter_subset_left)⟩ diff --git a/Mathlib/MeasureTheory/Function/Jacobian.lean b/Mathlib/MeasureTheory/Function/Jacobian.lean index 79ef7cb7efe73..38f7a8882415c 100644 --- a/Mathlib/MeasureTheory/Function/Jacobian.lean +++ b/Mathlib/MeasureTheory/Function/Jacobian.lean @@ -506,7 +506,7 @@ theorem _root_.ApproximatesLinearOn.norm_fderiv_sub_le {A : E →L[ℝ] E} {δ : exact ⟨a, az, by simp only [ha, add_neg_cancel_left]⟩ have norm_a : ‖a‖ ≤ ‖z‖ + ε := calc - ‖a‖ = ‖z + (a - z)‖ := by simp only [add_sub_cancel] + ‖a‖ = ‖z + (a - z)‖ := by simp only [_root_.add_sub_cancel] _ ≤ ‖z‖ + ‖a - z‖ := norm_add_le _ _ _ ≤ ‖z‖ + ε := add_le_add_left (mem_closedBall_iff_norm.1 az) _ -- use the approximation properties to control `(f' x - A) a`, and then `(f' x - A) z` as `z` is diff --git a/Mathlib/MeasureTheory/Function/L1Space.lean b/Mathlib/MeasureTheory/Function/L1Space.lean index 974593ec53552..8951025e6bfb6 100644 --- a/Mathlib/MeasureTheory/Function/L1Space.lean +++ b/Mathlib/MeasureTheory/Function/L1Space.lean @@ -191,7 +191,7 @@ theorem hasFiniteIntegral_add_measure {f : α → β} : theorem HasFiniteIntegral.smul_measure {f : α → β} (h : HasFiniteIntegral f μ) {c : ℝ≥0∞} (hc : c ≠ ∞) : HasFiniteIntegral f (c • μ) := by simp only [HasFiniteIntegral, lintegral_smul_measure] at * - exact mul_lt_top hc h.ne + exact mul_lt_top hc.lt_top h @[simp] theorem hasFiniteIntegral_zero_measure {m : MeasurableSpace α} (f : α → β) : @@ -360,7 +360,7 @@ theorem HasFiniteIntegral.smul [NormedAddCommGroup 𝕜] [SMulZeroClass 𝕜 β] exact mod_cast (nnnorm_smul_le c (f i)) _ < ∞ := by rw [lintegral_const_mul'] - exacts [mul_lt_top coe_ne_top hfi.ne, coe_ne_top] + exacts [mul_lt_top coe_lt_top hfi, coe_ne_top] theorem hasFiniteIntegral_smul_iff [NormedRing 𝕜] [MulActionWithZero 𝕜 β] [BoundedSMul 𝕜 β] {c : 𝕜} (hc : IsUnit c) (f : α → β) : HasFiniteIntegral (c • f) μ ↔ HasFiniteIntegral f μ := by @@ -693,7 +693,7 @@ theorem Integrable.bdd_mul {F : Type*} [NormedDivisionRing F] {f g : α → F} ( refine lt_of_le_of_lt (lintegral_mono_nnreal this) ?_ simp only [ENNReal.coe_mul] rw [lintegral_const_mul' _ _ ENNReal.coe_ne_top] - exact ENNReal.mul_lt_top ENNReal.coe_ne_top (ne_of_lt hint.2) + exact ENNReal.mul_lt_top ENNReal.coe_lt_top hint.2 /-- **Hölder's inequality for integrable functions**: the scalar multiplication of an integrable vector-valued function by a scalar function with finite essential supremum is integrable. -/ @@ -708,7 +708,7 @@ theorem Integrable.essSup_smul {𝕜 : Type*} [NormedField 𝕜] [NormedSpace calc eLpNorm (fun x : α => g x • f x) 1 μ ≤ _ := by simpa using MeasureTheory.eLpNorm_smul_le_mul_eLpNorm hf.1 g_aestronglyMeasurable h - _ < ∞ := ENNReal.mul_lt_top hg' hf.2.ne + _ < ∞ := ENNReal.mul_lt_top hg'.lt_top hf.2 /-- Hölder's inequality for integrable functions: the scalar multiplication of an integrable scalar-valued function by a vector-value function with finite essential supremum is integrable. -/ @@ -724,7 +724,7 @@ theorem Integrable.smul_essSup {𝕜 : Type*} [NormedRing 𝕜] [Module 𝕜 β] calc eLpNorm (fun x : α => f x • g x) 1 μ ≤ _ := by simpa using MeasureTheory.eLpNorm_smul_le_mul_eLpNorm g_aestronglyMeasurable hf.1 h - _ < ∞ := ENNReal.mul_lt_top hf.2.ne hg' + _ < ∞ := ENNReal.mul_lt_top hf.2 hg'.lt_top theorem integrable_norm_iff {f : α → β} (hf : AEStronglyMeasurable f μ) : Integrable (fun a => ‖f a‖) μ ↔ Integrable f μ := by @@ -763,10 +763,10 @@ theorem Integrable.measure_norm_ge_lt_top {f : α → β} (hf : Integrable f μ) refine (meas_ge_le_mul_pow_eLpNorm μ one_ne_zero ENNReal.one_ne_top hf.1 ?_).trans_lt ?_ · simpa only [Ne, ENNReal.ofReal_eq_zero, not_le] using hε apply ENNReal.mul_lt_top - · simpa only [ENNReal.one_toReal, ENNReal.rpow_one, Ne, ENNReal.inv_eq_top, - ENNReal.ofReal_eq_zero, not_le] using hε - simpa only [ENNReal.one_toReal, ENNReal.rpow_one] using - (memℒp_one_iff_integrable.2 hf).eLpNorm_ne_top + · simpa only [ENNReal.one_toReal, ENNReal.rpow_one, ENNReal.inv_lt_top, ENNReal.ofReal_pos] + using hε + · simpa only [ENNReal.one_toReal, ENNReal.rpow_one] using + (memℒp_one_iff_integrable.2 hf).eLpNorm_lt_top /-- A non-quantitative version of Markov inequality for integrable functions: the measure of points where `‖f x‖ > ε` is finite for all positive `ε`. -/ @@ -1182,7 +1182,8 @@ theorem integrable_of_forall_fin_meas_le [SigmaFinite μ] (C : ℝ≥0∞) (hC : (hf_meas : AEStronglyMeasurable f μ) (hf : ∀ s : Set α, MeasurableSet[m] s → μ s ≠ ∞ → (∫⁻ x in s, ‖f x‖₊ ∂μ) ≤ C) : Integrable f μ := - @integrable_of_forall_fin_meas_le' _ m _ m _ _ _ (by rwa [@trim_eq_self _ m]) C hC _ hf_meas hf + have : SigmaFinite (μ.trim le_rfl) := by rwa [@trim_eq_self _ m] + integrable_of_forall_fin_meas_le' le_rfl C hC hf_meas hf end SigmaFinite diff --git a/Mathlib/MeasureTheory/Function/L2Space.lean b/Mathlib/MeasureTheory/Function/L2Space.lean index 7af0d94802b18..e89d919547be1 100644 --- a/Mathlib/MeasureTheory/Function/L2Space.lean +++ b/Mathlib/MeasureTheory/Function/L2Space.lean @@ -65,7 +65,7 @@ theorem Memℒp.const_inner (c : E) {f : α → E} (hf : Memℒp f p μ) : Mem (Eventually.of_forall fun _ => norm_inner_le_norm _ _) theorem Memℒp.inner_const {f : α → E} (hf : Memℒp f p μ) (c : E) : Memℒp (fun a => ⟪f a, c⟫) p μ := - hf.of_le_mul (AEStronglyMeasurable.inner hf.1 aestronglyMeasurable_const) + hf.of_le_mul (c := ‖c‖) (AEStronglyMeasurable.inner hf.1 aestronglyMeasurable_const) (Eventually.of_forall fun x => by rw [mul_comm]; exact norm_inner_le_norm _ _) variable {f : α → E} diff --git a/Mathlib/MeasureTheory/Function/LocallyIntegrable.lean b/Mathlib/MeasureTheory/Function/LocallyIntegrable.lean index 2acd297ad0fd6..7ef4263f03c4a 100644 --- a/Mathlib/MeasureTheory/Function/LocallyIntegrable.lean +++ b/Mathlib/MeasureTheory/Function/LocallyIntegrable.lean @@ -129,22 +129,14 @@ theorem LocallyIntegrableOn.aestronglyMeasurable [SecondCountableTopology X] /-- 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`. -/ -theorem locallyIntegrableOn_iff [LocallyCompactSpace X] [T2Space X] (hs : IsClosed s ∨ IsOpen s) : +theorem locallyIntegrableOn_iff [LocallyCompactSpace X] (hs : IsLocallyClosed s) : LocallyIntegrableOn f s μ ↔ ∀ (k : Set X), k ⊆ s → (IsCompact k → IntegrableOn f k μ) := by - -- The correct condition is that `s` be *locally closed*, i.e. for every `x ∈ s` there is some - -- `U ∈ 𝓝 x` such that `U ∩ s` is closed. But mathlib doesn't have locally closed sets yet. - refine ⟨fun hf k hk => hf.integrableOn_compact_subset hk, fun hf x hx => ?_⟩ - cases hs with - | inl hs => - exact - let ⟨K, hK, h2K⟩ := exists_compact_mem_nhds x - ⟨_, inter_mem_nhdsWithin s h2K, - hf _ inter_subset_left - (hK.of_isClosed_subset (hs.inter hK.isClosed) inter_subset_right)⟩ - | inr hs => - obtain ⟨K, hK, h2K, h3K⟩ := exists_compact_subset hs hx - refine ⟨K, ?_, hf K h3K hK⟩ - simpa only [IsOpen.nhdsWithin_eq hs hx, interior_eq_nhds'] using h2K + 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⟩ + rw [nhdsWithin_inter_of_mem (nhdsWithin_le_nhds <| hU.mem_nhds hx.1)] + refine ⟨Z ∩ K, inter_mem_nhdsWithin _ (mem_interior_iff_mem_nhds.1 hxK), ?_⟩ + exact hf (Z ∩ K) (fun y hy ↦ ⟨hKU hy.2, hy.1⟩) (.inter_left hK hZ) protected theorem LocallyIntegrableOn.add (hf : LocallyIntegrableOn f s μ) (hg : LocallyIntegrableOn g s μ) : @@ -619,28 +611,30 @@ namespace LocallyIntegrableOn theorem continuousOn_mul [LocallyCompactSpace X] [T2Space X] [NormedRing R] [SecondCountableTopologyEither X R] {f g : X → R} {s : Set X} (hf : LocallyIntegrableOn f s μ) - (hg : ContinuousOn g s) (hs : IsOpen s) : LocallyIntegrableOn (fun x => g x * f x) s μ := by - rw [MeasureTheory.locallyIntegrableOn_iff (Or.inr hs)] at hf ⊢ + (hg : ContinuousOn g s) (hs : IsLocallyClosed s) : + LocallyIntegrableOn (fun x => g x * f x) s μ := by + rw [MeasureTheory.locallyIntegrableOn_iff hs] at hf ⊢ exact fun k hk_sub hk_c => (hf k hk_sub hk_c).continuousOn_mul (hg.mono hk_sub) hk_c theorem mul_continuousOn [LocallyCompactSpace X] [T2Space X] [NormedRing R] [SecondCountableTopologyEither X R] {f g : X → R} {s : Set X} (hf : LocallyIntegrableOn f s μ) - (hg : ContinuousOn g s) (hs : IsOpen s) : LocallyIntegrableOn (fun x => f x * g x) s μ := by - rw [MeasureTheory.locallyIntegrableOn_iff (Or.inr hs)] at hf ⊢ + (hg : ContinuousOn g s) (hs : IsLocallyClosed s) : + LocallyIntegrableOn (fun x => f x * g x) s μ := by + rw [MeasureTheory.locallyIntegrableOn_iff hs] at hf ⊢ exact fun k hk_sub hk_c => (hf k hk_sub hk_c).mul_continuousOn (hg.mono hk_sub) hk_c theorem continuousOn_smul [LocallyCompactSpace X] [T2Space X] {𝕜 : Type*} [NormedField 𝕜] [SecondCountableTopologyEither X 𝕜] [NormedSpace 𝕜 E] {f : X → E} {g : X → 𝕜} {s : Set X} - (hs : IsOpen s) (hf : LocallyIntegrableOn f s μ) (hg : ContinuousOn g s) : + (hs : IsLocallyClosed s) (hf : LocallyIntegrableOn f s μ) (hg : ContinuousOn g s) : LocallyIntegrableOn (fun x => g x • f x) s μ := by - rw [MeasureTheory.locallyIntegrableOn_iff (Or.inr hs)] at hf ⊢ + rw [MeasureTheory.locallyIntegrableOn_iff hs] at hf ⊢ exact fun k hk_sub hk_c => (hf k hk_sub hk_c).continuousOn_smul (hg.mono hk_sub) hk_c theorem smul_continuousOn [LocallyCompactSpace X] [T2Space X] {𝕜 : Type*} [NormedField 𝕜] [SecondCountableTopologyEither X E] [NormedSpace 𝕜 E] {f : X → 𝕜} {g : X → E} {s : Set X} - (hs : IsOpen s) (hf : LocallyIntegrableOn f s μ) (hg : ContinuousOn g s) : + (hs : IsLocallyClosed s) (hf : LocallyIntegrableOn f s μ) (hg : ContinuousOn g s) : LocallyIntegrableOn (fun x => f x • g x) s μ := by - rw [MeasureTheory.locallyIntegrableOn_iff (Or.inr hs)] at hf ⊢ + rw [MeasureTheory.locallyIntegrableOn_iff hs] at hf ⊢ exact fun k hk_sub hk_c => (hf k hk_sub hk_c).smul_continuousOn (hg.mono hk_sub) hk_c end LocallyIntegrableOn diff --git a/Mathlib/MeasureTheory/Function/LpSeminorm/Basic.lean b/Mathlib/MeasureTheory/Function/LpSeminorm/Basic.lean index c35df4f7ac93b..021f82da8c982 100644 --- a/Mathlib/MeasureTheory/Function/LpSeminorm/Basic.lean +++ b/Mathlib/MeasureTheory/Function/LpSeminorm/Basic.lean @@ -75,7 +75,8 @@ def eLpNormEssSup {_ : MeasurableSpace α} (f : α → F) (μ : Measure α) := /-- `ℒp` seminorm, equal to `0` for `p=0`, to `(∫ ‖f a‖^p ∂μ) ^ (1/p)` for `0 < p < ∞` and to `essSup ‖f‖ μ` for `p = ∞`. -/ -def eLpNorm {_ : MeasurableSpace α} (f : α → F) (p : ℝ≥0∞) (μ : Measure α) : ℝ≥0∞ := +def eLpNorm {_ : MeasurableSpace α} + (f : α → F) (p : ℝ≥0∞) (μ : Measure α := by volume_tac) : ℝ≥0∞ := if p = 0 then 0 else if p = ∞ then eLpNormEssSup f μ else eLpNorm' f (ENNReal.toReal p) μ @[deprecated (since := "2024-07-26")] noncomputable alias snorm := eLpNorm @@ -427,8 +428,8 @@ theorem memℒp_const (c : E) [IsFiniteMeasure μ] : Memℒp (fun _ : α => c) p by_cases hμ : μ = 0 · simp [hμ] rw [eLpNorm_const c h0 hμ] - refine ENNReal.mul_lt_top ENNReal.coe_ne_top ?_ - refine (ENNReal.rpow_lt_top_of_nonneg ?_ (measure_ne_top μ Set.univ)).ne + refine ENNReal.mul_lt_top ENNReal.coe_lt_top ?_ + refine ENNReal.rpow_lt_top_of_nonneg ?_ (measure_ne_top μ Set.univ) simp theorem memℒp_top_const (c : E) : Memℒp (fun _ : α => c) ∞ μ := by @@ -849,7 +850,7 @@ theorem Memℒp.of_measure_le_smul {μ' : Measure α} (c : ℝ≥0∞) (hc : c by_cases hc0 : c = 0 · simp [hc0] rw [eLpNorm_smul_measure_of_ne_zero hc0, smul_eq_mul] - refine ENNReal.mul_lt_top ?_ hf.2.ne + refine ENNReal.mul_lt_top (Ne.lt_top ?_) hf.2 simp [hc, hc0] theorem Memℒp.smul_measure {f : α → E} {c : ℝ≥0∞} (hf : Memℒp f p μ) (hc : c ≠ ∞) : @@ -963,6 +964,10 @@ theorem eLpNorm_eq_zero_iff {f : α → E} (hf : AEStronglyMeasurable f μ) (h0 @[deprecated (since := "2024-07-27")] alias snorm_eq_zero_iff := eLpNorm_eq_zero_iff +theorem eLpNorm_eq_zero_of_ae_zero {f : α → E} (hf : f =ᵐ[μ] 0) : eLpNorm f p μ = 0 := by + rw [← eLpNorm_zero (p := p) (μ := μ) (α := α) (F := E)] + exact eLpNorm_congr_ae hf + theorem ae_le_eLpNormEssSup {f : α → F} : ∀ᵐ y ∂μ, ‖f y‖₊ ≤ eLpNormEssSup f μ := ae_le_essSup @@ -1160,13 +1165,13 @@ theorem Memℒp.of_nnnorm_le_mul {f : α → E} {g : α → F} {c : ℝ≥0} (hg (hf : AEStronglyMeasurable f μ) (hfg : ∀ᵐ x ∂μ, ‖f x‖₊ ≤ c * ‖g x‖₊) : Memℒp f p μ := ⟨hf, (eLpNorm_le_nnreal_smul_eLpNorm_of_ae_le_mul hfg p).trans_lt <| - ENNReal.mul_lt_top ENNReal.coe_ne_top hg.eLpNorm_ne_top⟩ + ENNReal.mul_lt_top ENNReal.coe_lt_top hg.eLpNorm_lt_top⟩ theorem Memℒp.of_le_mul {f : α → E} {g : α → F} {c : ℝ} (hg : Memℒp g p μ) (hf : AEStronglyMeasurable f μ) (hfg : ∀ᵐ x ∂μ, ‖f x‖ ≤ c * ‖g x‖) : Memℒp f p μ := ⟨hf, (eLpNorm_le_mul_eLpNorm_of_ae_le_mul hfg p).trans_lt <| - ENNReal.mul_lt_top ENNReal.ofReal_ne_top hg.eLpNorm_ne_top⟩ + ENNReal.mul_lt_top ENNReal.ofReal_lt_top hg.eLpNorm_lt_top⟩ end Monotonicity @@ -1205,7 +1210,7 @@ alias snorm_const_smul_le := eLpNorm_const_smul_le theorem Memℒp.const_smul {f : α → E} (hf : Memℒp f p μ) (c : 𝕜) : Memℒp (c • f) p μ := ⟨AEStronglyMeasurable.const_smul hf.1 c, - (eLpNorm_const_smul_le c f).trans_lt (ENNReal.mul_lt_top ENNReal.coe_ne_top hf.2.ne)⟩ + (eLpNorm_const_smul_le c f).trans_lt (ENNReal.mul_lt_top ENNReal.coe_lt_top hf.2)⟩ theorem Memℒp.const_mul {R} [NormedRing R] {f : α → R} (hf : Memℒp f p μ) (c : R) : Memℒp (fun x => c * f x) p μ := diff --git a/Mathlib/MeasureTheory/Function/LpSeminorm/ChebyshevMarkov.lean b/Mathlib/MeasureTheory/Function/LpSeminorm/ChebyshevMarkov.lean index df00ceb205d0a..32599fde917d0 100644 --- a/Mathlib/MeasureTheory/Function/LpSeminorm/ChebyshevMarkov.lean +++ b/Mathlib/MeasureTheory/Function/LpSeminorm/ChebyshevMarkov.lean @@ -11,7 +11,7 @@ import Mathlib.MeasureTheory.Function.LpSeminorm.Basic In this file we formulate several versions of the Chebyshev-Markov inequality in terms of the `MeasureTheory.eLpNorm` seminorm. -/ -open scoped ENNReal +open scoped NNReal ENNReal namespace MeasureTheory @@ -67,4 +67,18 @@ theorem meas_ge_le_mul_pow_eLpNorm (hp_ne_zero : p ≠ 0) (hp_ne_top : p ≠ ∞ @[deprecated (since := "2024-07-27")] alias meas_ge_le_mul_pow_snorm := meas_ge_le_mul_pow_eLpNorm +theorem Memℒp.meas_ge_lt_top' {μ : Measure α} (hℒp : Memℒp f p μ) (hp_ne_zero : p ≠ 0) + (hp_ne_top : p ≠ ∞) {ε : ℝ≥0∞} (hε : ε ≠ 0) : + μ { x | ε ≤ ‖f x‖₊ } < ∞ := by + apply (meas_ge_le_mul_pow_eLpNorm μ hp_ne_zero hp_ne_top hℒp.aestronglyMeasurable hε).trans_lt + (ENNReal.mul_lt_top ?_ ?_) + · simp [hε, lt_top_iff_ne_top] + · simp [hℒp.eLpNorm_lt_top.ne, lt_top_iff_ne_top] + +theorem Memℒp.meas_ge_lt_top {μ : Measure α} (hℒp : Memℒp f p μ) (hp_ne_zero : p ≠ 0) + (hp_ne_top : p ≠ ∞) {ε : ℝ≥0} (hε : ε ≠ 0) : + μ { x | ε ≤ ‖f x‖₊ } < ∞ := by + simp_rw [← ENNReal.coe_le_coe] + apply hℒp.meas_ge_lt_top' hp_ne_zero hp_ne_top (by simp [hε]) + end MeasureTheory diff --git a/Mathlib/MeasureTheory/Function/LpSeminorm/CompareExp.lean b/Mathlib/MeasureTheory/Function/LpSeminorm/CompareExp.lean index 04c5adbec044e..dcafb2aeecbec 100644 --- a/Mathlib/MeasureTheory/Function/LpSeminorm/CompareExp.lean +++ b/Mathlib/MeasureTheory/Function/LpSeminorm/CompareExp.lean @@ -148,8 +148,8 @@ theorem Memℒp.memℒp_of_exponent_le {p q : ℝ≥0∞} [IsFiniteMeasure μ] { · rw [eLpNorm_eq_eLpNorm' hp0 hp_top] rw [hq_top, eLpNorm_exponent_top] at hfq_lt_top refine lt_of_le_of_lt (eLpNorm'_le_eLpNormEssSup_mul_rpow_measure_univ hp_pos) ?_ - refine ENNReal.mul_lt_top hfq_lt_top.ne ?_ - exact (ENNReal.rpow_lt_top_of_nonneg (by simp [hp_pos.le]) (measure_ne_top μ Set.univ)).ne + refine ENNReal.mul_lt_top hfq_lt_top ?_ + exact ENNReal.rpow_lt_top_of_nonneg (by simp [hp_pos.le]) (measure_ne_top μ Set.univ) have hq0 : q ≠ 0 := by by_contra hq_eq_zero have hp_eq_zero : p = 0 := le_antisymm (by rwa [hq_eq_zero] at hpq) (zero_le _) @@ -343,7 +343,7 @@ theorem Memℒp.smul {p q r : ℝ≥0∞} {f : α → E} {φ : α → 𝕜} (hf (hpqr : 1 / p = 1 / q + 1 / r) : Memℒp (φ • f) p μ := ⟨hφ.1.smul hf.1, (eLpNorm_smul_le_mul_eLpNorm hf.1 hφ.1 hpqr).trans_lt - (ENNReal.mul_lt_top hφ.eLpNorm_ne_top hf.eLpNorm_ne_top)⟩ + (ENNReal.mul_lt_top hφ.eLpNorm_lt_top hf.eLpNorm_lt_top)⟩ theorem Memℒp.smul_of_top_right {p : ℝ≥0∞} {f : α → E} {φ : α → 𝕜} (hf : Memℒp f p μ) (hφ : Memℒp φ ∞ μ) : Memℒp (φ • f) p μ := by diff --git a/Mathlib/MeasureTheory/Function/LpSeminorm/TriangleInequality.lean b/Mathlib/MeasureTheory/Function/LpSeminorm/TriangleInequality.lean index 76196abdb4abc..42f9edb4bd2b4 100644 --- a/Mathlib/MeasureTheory/Function/LpSeminorm/TriangleInequality.lean +++ b/Mathlib/MeasureTheory/Function/LpSeminorm/TriangleInequality.lean @@ -154,8 +154,8 @@ theorem eLpNorm_add_lt_top {f g : α → E} (hf : Memℒp f p μ) (hg : Memℒp eLpNorm (f + g) p μ ≤ LpAddConst p * (eLpNorm f p μ + eLpNorm g p μ) := eLpNorm_add_le' hf.aestronglyMeasurable hg.aestronglyMeasurable p _ < ∞ := by - apply ENNReal.mul_lt_top (LpAddConst_lt_top p).ne - exact (ENNReal.add_lt_top.2 ⟨hf.2, hg.2⟩).ne + apply ENNReal.mul_lt_top (LpAddConst_lt_top p) + exact ENNReal.add_lt_top.2 ⟨hf.2, hg.2⟩ @[deprecated (since := "2024-07-27")] alias snorm_add_lt_top := eLpNorm_add_lt_top diff --git a/Mathlib/MeasureTheory/Function/LpSpace.lean b/Mathlib/MeasureTheory/Function/LpSpace.lean index cfd54d45970a3..d5eca9056cc76 100644 --- a/Mathlib/MeasureTheory/Function/LpSpace.lean +++ b/Mathlib/MeasureTheory/Function/LpSpace.lean @@ -1877,7 +1877,7 @@ theorem toLp_inj {f g : C(α, E)} [μ.IsOpenPosMeasure] [NormedField 𝕜] [Norm variable {μ} /-- If a sum of continuous functions `g n` is convergent, and the same sum converges in `Lᵖ` to `h`, -then in fact `g n` converges uniformly to `h`. -/ +then in fact `g n` converges uniformly to `h`. -/ theorem hasSum_of_hasSum_Lp {β : Type*} [μ.IsOpenPosMeasure] [NormedField 𝕜] [NormedSpace 𝕜 E] {g : β → C(α, E)} {f : C(α, E)} (hg : Summable g) (hg2 : HasSum (toLp (E := E) p μ 𝕜 ∘ g) (toLp (E := E) p μ 𝕜 f)) : HasSum g f := by @@ -1929,3 +1929,5 @@ theorem meas_ge_le_mul_pow_norm (f : Lp E p μ) (hp_ne_zero : p ≠ 0) (hp_ne_to end Lp end MeasureTheory + +set_option linter.style.longFile 2100 diff --git a/Mathlib/MeasureTheory/Function/SimpleFunc.lean b/Mathlib/MeasureTheory/Function/SimpleFunc.lean index 8f21bd8c21ed8..90386bdd03776 100644 --- a/Mathlib/MeasureTheory/Function/SimpleFunc.lean +++ b/Mathlib/MeasureTheory/Function/SimpleFunc.lean @@ -353,6 +353,10 @@ theorem pair_preimage_singleton (f : α →ₛ β) (g : α →ₛ γ) (b : β) ( rw [← singleton_prod_singleton] exact pair_preimage _ _ _ _ +@[simp] theorem map_fst_pair (f : α →ₛ β) (g : α →ₛ γ) : (f.pair g).map Prod.fst = f := rfl +@[simp] theorem map_snd_pair (f : α →ₛ β) (g : α →ₛ γ) : (f.pair g).map Prod.snd = g := rfl + +@[simp] theorem bind_const (f : α →ₛ β) : f.bind (const α) = f := by ext; simp @[to_additive] @@ -812,7 +816,7 @@ theorem lintegral_eq_of_subset' (f : α →ₛ ℝ≥0∞) {s : Finset ℝ≥0 f.lintegral_eq_of_subset fun x hfx _ => hs <| Finset.mem_sdiff.2 ⟨f.mem_range_self x, mt Finset.mem_singleton.1 hfx⟩ -/-- Calculate the integral of `(g ∘ f)`, where `g : β → ℝ≥0∞` and `f : α →ₛ β`. -/ +/-- Calculate the integral of `(g ∘ f)`, where `g : β → ℝ≥0∞` and `f : α →ₛ β`. -/ theorem map_lintegral (g : β → ℝ≥0∞) (f : α →ₛ β) : (f.map g).lintegral μ = ∑ x ∈ f.range, g x * μ (f ⁻¹' {x}) := by simp only [lintegral, range_map] @@ -924,27 +928,30 @@ theorem restrict_const_lintegral (c : ℝ≥0∞) {s : Set α} (hs : MeasurableS ((const α c).restrict s).lintegral μ = c * μ s := by rw [restrict_lintegral_eq_lintegral_restrict _ hs, const_lintegral_restrict] -theorem le_sup_lintegral (f g : α →ₛ ℝ≥0∞) : f.lintegral μ ⊔ g.lintegral μ ≤ (f ⊔ g).lintegral μ := +@[gcongr] +theorem lintegral_mono_fun {f g : α →ₛ ℝ≥0∞} (h : f ≤ g) : f.lintegral μ ≤ g.lintegral μ := by + refine Monotone.of_left_le_map_sup (f := (lintegral · μ)) (fun f g ↦ ?_) h calc - f.lintegral μ ⊔ g.lintegral μ = - ((pair f g).map Prod.fst).lintegral μ ⊔ ((pair f g).map Prod.snd).lintegral μ := - rfl - _ ≤ ∑ x ∈ (pair f g).range, (x.1 ⊔ x.2) * μ (pair f g ⁻¹' {x}) := by - rw [map_lintegral, map_lintegral] - refine sup_le ?_ ?_ <;> refine Finset.sum_le_sum fun a _ => mul_le_mul_right' ?_ _ - · exact le_sup_left - · exact le_sup_right - _ = (f ⊔ g).lintegral μ := by rw [sup_eq_map₂, map_lintegral] + f.lintegral μ = ((pair f g).map Prod.fst).lintegral μ := by rw [map_fst_pair] + _ ≤ ((pair f g).map fun p ↦ p.1 ⊔ p.2).lintegral μ := by + simp only [map_lintegral] + gcongr + exact le_sup_left + +theorem le_sup_lintegral (f g : α →ₛ ℝ≥0∞) : f.lintegral μ ⊔ g.lintegral μ ≤ (f ⊔ g).lintegral μ := + Monotone.le_map_sup (fun _ _ ↦ lintegral_mono_fun) f g + +@[gcongr] +theorem lintegral_mono_measure {f : α →ₛ ℝ≥0∞} (h : μ ≤ ν) : f.lintegral μ ≤ f.lintegral ν := by + simp only [lintegral] + gcongr + apply h /-- `SimpleFunc.lintegral` is monotone both in function and in measure. -/ -@[mono] +@[mono, gcongr] theorem lintegral_mono {f g : α →ₛ ℝ≥0∞} (hfg : f ≤ g) (hμν : μ ≤ ν) : f.lintegral μ ≤ g.lintegral ν := - calc - f.lintegral μ ≤ f.lintegral μ ⊔ g.lintegral μ := le_sup_left - _ ≤ (f ⊔ g).lintegral μ := le_sup_lintegral _ _ - _ = g.lintegral μ := by rw [sup_of_le_right hfg] - _ ≤ g.lintegral ν := Finset.sum_le_sum fun y _ => ENNReal.mul_left_mono <| hμν _ + (lintegral_mono_fun hfg).trans (lintegral_mono_measure hμν) /-- `SimpleFunc.lintegral` depends only on the measures of `f ⁻¹' {y}`. -/ theorem lintegral_eq_of_measure_preimage [MeasurableSpace β] {f : α →ₛ ℝ≥0∞} {g : β →ₛ ℝ≥0∞} @@ -1003,8 +1010,7 @@ theorem finMeasSupp_iff : f.FinMeasSupp μ ↔ ∀ y, y ≠ 0 → μ (f ⁻¹' { exact fun x hx (H : f x = 0) => hy <| H ▸ Eq.symm hx · intro H rw [finMeasSupp_iff_support, support_eq] - refine lt_of_le_of_lt (measure_biUnion_finset_le _ _) (sum_lt_top ?_) - exact fun y hy => (H y (Finset.mem_filter.1 hy).2).ne + exact measure_biUnion_lt_top (finite_toSet _) fun y hy ↦ H y (mem_filter.1 hy).2 namespace FinMeasSupp @@ -1046,14 +1052,14 @@ protected theorem mul {β} [MonoidWithZero β] {f g : α →ₛ β} (hf : f.FinM theorem lintegral_lt_top {f : α →ₛ ℝ≥0∞} (hm : f.FinMeasSupp μ) (hf : ∀ᵐ a ∂μ, f a ≠ ∞) : f.lintegral μ < ∞ := by - refine sum_lt_top fun a ha => ?_ + refine sum_lt_top.2 fun a ha => ?_ rcases eq_or_ne a ∞ with (rfl | ha) · simp only [ae_iff, Ne, Classical.not_not] at hf simp [Set.preimage, hf] · by_cases ha0 : a = 0 · subst a - rwa [zero_mul] - · exact mul_ne_top ha (finMeasSupp_iff.1 hm _ ha0).ne + simp + · exact mul_lt_top ha.lt_top (finMeasSupp_iff.1 hm _ ha0) theorem of_lintegral_ne_top {f : α →ₛ ℝ≥0∞} (h : f.lintegral μ ≠ ∞) : f.FinMeasSupp μ := by refine finMeasSupp_iff.2 fun b hb => ?_ diff --git a/Mathlib/MeasureTheory/Function/SimpleFuncDenseLp.lean b/Mathlib/MeasureTheory/Function/SimpleFuncDenseLp.lean index 163748ae34896..679c905a01e48 100644 --- a/Mathlib/MeasureTheory/Function/SimpleFuncDenseLp.lean +++ b/Mathlib/MeasureTheory/Function/SimpleFuncDenseLp.lean @@ -293,7 +293,7 @@ theorem measure_preimage_lt_top_of_memℒp (hp_pos : p ≠ 0) (hp_ne_top : p ≠ rw [eLpNorm_eq_eLpNorm' hp_pos hp_ne_top, f.eLpNorm'_eq, one_div, ← @ENNReal.lt_rpow_inv_iff _ _ p.toReal⁻¹ (by simp [hp_pos_real]), @ENNReal.top_rpow_of_pos p.toReal⁻¹⁻¹ (by simp [hp_pos_real]), - ENNReal.sum_lt_top_iff] at hf_eLpNorm + ENNReal.sum_lt_top] at hf_eLpNorm by_cases hyf : y ∈ f.range swap · suffices h_empty : f ⁻¹' {y} = ∅ by @@ -322,11 +322,11 @@ theorem memℒp_of_finite_measure_preimage (p : ℝ≥0∞) {f : α →ₛ E} · rw [hp_top]; exact memℒp_top f μ refine ⟨f.aestronglyMeasurable, ?_⟩ rw [eLpNorm_eq_eLpNorm' hp0 hp_top, f.eLpNorm'_eq] - refine ENNReal.rpow_lt_top_of_nonneg (by simp) (ENNReal.sum_lt_top_iff.mpr fun y _ => ?_).ne + refine ENNReal.rpow_lt_top_of_nonneg (by simp) (ENNReal.sum_lt_top.mpr fun y _ => ?_).ne by_cases hy0 : y = 0 · simp [hy0, ENNReal.toReal_pos hp0 hp_top] - · refine ENNReal.mul_lt_top ?_ (hf y hy0).ne - exact (ENNReal.rpow_lt_top_of_nonneg ENNReal.toReal_nonneg ENNReal.coe_ne_top).ne + · refine ENNReal.mul_lt_top ?_ (hf y hy0) + exact ENNReal.rpow_lt_top_of_nonneg ENNReal.toReal_nonneg ENNReal.coe_ne_top theorem memℒp_iff {f : α →ₛ E} (hp_pos : p ≠ 0) (hp_ne_top : p ≠ ∞) : Memℒp f p μ ↔ ∀ y, y ≠ 0 → μ (f ⁻¹' {y}) < ∞ := @@ -369,7 +369,7 @@ theorem measure_preimage_lt_top_of_integrable (f : α →ₛ E) (hf : Integrable theorem measure_support_lt_top [Zero β] (f : α →ₛ β) (hf : ∀ y, y ≠ 0 → μ (f ⁻¹' {y}) < ∞) : μ (support f) < ∞ := by rw [support_eq] - refine (measure_biUnion_finset_le _ _).trans_lt (ENNReal.sum_lt_top_iff.mpr fun y hy => ?_) + refine (measure_biUnion_finset_le _ _).trans_lt (ENNReal.sum_lt_top.mpr fun y hy => ?_) rw [Finset.mem_filter] at hy exact hf y hy.2 diff --git a/Mathlib/MeasureTheory/Function/StronglyMeasurable/Basic.lean b/Mathlib/MeasureTheory/Function/StronglyMeasurable/Basic.lean index 0c844b249cd24..b2fb9342d5eb9 100644 --- a/Mathlib/MeasureTheory/Function/StronglyMeasurable/Basic.lean +++ b/Mathlib/MeasureTheory/Function/StronglyMeasurable/Basic.lean @@ -278,13 +278,13 @@ theorem finStronglyMeasurable_of_set_sigmaFinite [TopologicalSpace β] [Zero β] refine Set.indicator_of_not_mem ?_ _ simp [hxt] refine ⟨fs, ?_, fun x => ?_⟩ - · simp_rw [SimpleFunc.support_eq] - refine fun n => (measure_biUnion_finset_le _ _).trans_lt ?_ - refine ENNReal.sum_lt_top_iff.mpr fun y hy => ?_ + · simp_rw [SimpleFunc.support_eq, ← Finset.mem_coe] + classical + refine fun n => measure_biUnion_lt_top {y ∈ (fs n).range | y ≠ 0}.finite_toSet fun y hy => ?_ rw [SimpleFunc.restrict_preimage_singleton _ ((hS_meas n).inter ht)] swap · letI : (y : β) → Decidable (y = 0) := fun y => Classical.propDecidable _ - rw [Finset.mem_filter] at hy + rw [Finset.mem_coe, Finset.mem_filter] at hy exact hy.2 refine (measure_mono Set.inter_subset_left).trans_lt ?_ have h_lt_top := measure_spanningSets_lt_top (μ.restrict t) n @@ -1880,3 +1880,5 @@ theorem stronglyMeasurable_uncurry_of_continuous_of_stronglyMeasurable {α β ι exact ((t_sf n).measurable.comp measurable_fst).subtype_mk end MeasureTheory + +set_option linter.style.longFile 2000 diff --git a/Mathlib/MeasureTheory/Group/Action.lean b/Mathlib/MeasureTheory/Group/Action.lean index 159a5bff0f4ff..28b06957d5abb 100644 --- a/Mathlib/MeasureTheory/Group/Action.lean +++ b/Mathlib/MeasureTheory/Group/Action.lean @@ -171,7 +171,7 @@ theorem smulInvariantMeasure_iterateMulAct section SMulHomClass universe uM uN uα uβ -variable {M : Type uM} {N : Type uN} {α : Type uα} {β : Type uβ} +variable {M : Type uM} {N : Type uN} {α : Type uα} {β : Type uβ} [MeasurableSpace M] [MeasurableSpace N] [MeasurableSpace α] [MeasurableSpace β] @[to_additive] diff --git a/Mathlib/MeasureTheory/Group/AddCircle.lean b/Mathlib/MeasureTheory/Group/AddCircle.lean index 6483fa54f3cec..38e54d654f75e 100644 --- a/Mathlib/MeasureTheory/Group/AddCircle.lean +++ b/Mathlib/MeasureTheory/Group/AddCircle.lean @@ -35,9 +35,9 @@ theorem closedBall_ae_eq_ball {x : AddCircle T} {ε : ℝ} : closedBall x ε = · rw [ball_eq_empty.mpr hε, ae_eq_empty, volume_closedBall, min_eq_right (by linarith [hT.out] : 2 * ε ≤ T), ENNReal.ofReal_eq_zero] exact mul_nonpos_of_nonneg_of_nonpos zero_le_two hε - · suffices volume (closedBall x ε) ≤ volume (ball x ε) by - exact (ae_eq_of_subset_of_measure_ge ball_subset_closedBall this measurableSet_ball - (measure_ne_top _ _)).symm + · suffices volume (closedBall x ε) ≤ volume (ball x ε) from + (ae_eq_of_subset_of_measure_ge ball_subset_closedBall this + measurableSet_ball.nullMeasurableSet (measure_ne_top _ _)).symm have : Tendsto (fun δ => volume (closedBall x δ)) (𝓝[<] ε) (𝓝 <| volume (closedBall x ε)) := by simp_rw [volume_closedBall] refine ENNReal.tendsto_ofReal (Tendsto.min tendsto_const_nhds <| Tendsto.const_mul _ ?_) @@ -70,7 +70,7 @@ theorem isAddFundamentalDomain_of_ae_ball (I : Set <| AddCircle T) (u x : AddCir rw [hBg] apply ball_disjoint_ball rw [dist_eq_norm, add_sub_cancel_right, div_mul_eq_div_div, ← add_div, ← add_div, - add_self_div_two, div_le_iff' (by positivity : 0 < (n : ℝ)), ← nsmul_eq_mul] + add_self_div_two, div_le_iff₀' (by positivity : 0 < (n : ℝ)), ← nsmul_eq_mul] refine (le_add_order_smul_norm_of_isOfFinAddOrder (hu.of_mem_zmultiples hg) hg').trans (nsmul_le_nsmul_left (norm_nonneg g) ?_) exact Nat.le_of_dvd (addOrderOf_pos_iff.mpr hu) (addOrderOf_dvd_of_mem_zmultiples hg) diff --git a/Mathlib/MeasureTheory/Group/Arithmetic.lean b/Mathlib/MeasureTheory/Group/Arithmetic.lean index d58f14fb0b7a4..1893764f613b0 100644 --- a/Mathlib/MeasureTheory/Group/Arithmetic.lean +++ b/Mathlib/MeasureTheory/Group/Arithmetic.lean @@ -836,23 +836,23 @@ variable [MeasurableSpace α] [Mul α] [Div α] [Inv α] @[to_additive] -- See note [lower instance priority] instance (priority := 100) DiscreteMeasurableSpace.toMeasurableMul [DiscreteMeasurableSpace α] : MeasurableMul α where - measurable_const_mul _ := measurable_discrete _ - measurable_mul_const _ := measurable_discrete _ + measurable_const_mul _ := .of_discrete + measurable_mul_const _ := .of_discrete @[to_additive DiscreteMeasurableSpace.toMeasurableAdd₂] -- See note [lower instance priority] instance (priority := 100) DiscreteMeasurableSpace.toMeasurableMul₂ - [DiscreteMeasurableSpace (α × α)] : MeasurableMul₂ α := ⟨measurable_discrete _⟩ + [DiscreteMeasurableSpace (α × α)] : MeasurableMul₂ α := ⟨.of_discrete⟩ @[to_additive] -- See note [lower instance priority] instance (priority := 100) DiscreteMeasurableSpace.toMeasurableInv [DiscreteMeasurableSpace α] : - MeasurableInv α := ⟨measurable_discrete _⟩ + MeasurableInv α := ⟨.of_discrete⟩ @[to_additive] -- See note [lower instance priority] instance (priority := 100) DiscreteMeasurableSpace.toMeasurableDiv [DiscreteMeasurableSpace α] : MeasurableDiv α where - measurable_const_div _ := measurable_discrete _ - measurable_div_const _ := measurable_discrete _ + measurable_const_div _ := .of_discrete + measurable_div_const _ := .of_discrete @[to_additive DiscreteMeasurableSpace.toMeasurableSub₂] -- See note [lower instance priority] instance (priority := 100) DiscreteMeasurableSpace.toMeasurableDiv₂ - [DiscreteMeasurableSpace (α × α)] : MeasurableDiv₂ α := ⟨measurable_discrete _⟩ + [DiscreteMeasurableSpace (α × α)] : MeasurableDiv₂ α := ⟨.of_discrete⟩ diff --git a/Mathlib/MeasureTheory/Group/FundamentalDomain.lean b/Mathlib/MeasureTheory/Group/FundamentalDomain.lean index 561111dd29111..b7e676a68b71b 100644 --- a/Mathlib/MeasureTheory/Group/FundamentalDomain.lean +++ b/Mathlib/MeasureTheory/Group/FundamentalDomain.lean @@ -346,7 +346,7 @@ protected theorem aEStronglyMeasurable_on_iff {β : Type*} [TopologicalSpace β] have he : MeasurableEmbedding (g⁻¹ • · : α → α) := measurableEmbedding_const_smul _ rw [← image_smul, ← ((measurePreserving_smul g⁻¹ μ).restrict_image_emb he _).aestronglyMeasurable_comp_iff he] - simp only [(· ∘ ·), hf] + simp only [Function.comp_def, hf] _ ↔ AEStronglyMeasurable f (μ.restrict t) := by simp only [← aestronglyMeasurable_sum_measure_iff, ← hs.restrict_restrict, hs.sum_restrict_of_ac restrict_le_self.absolutelyContinuous] diff --git a/Mathlib/MeasureTheory/Group/GeometryOfNumbers.lean b/Mathlib/MeasureTheory/Group/GeometryOfNumbers.lean index 9fd4d3c6d24d8..fb1be755747f1 100644 --- a/Mathlib/MeasureTheory/Group/GeometryOfNumbers.lean +++ b/Mathlib/MeasureTheory/Group/GeometryOfNumbers.lean @@ -57,7 +57,7 @@ theorem exists_pair_mem_lattice_not_disjoint_vadd [AddCommGroup L] [Countable L] /-- The **Minkowski Convex Body Theorem**. If `s` is a convex symmetric domain of `E` whose volume is large enough compared to the covolume of a lattice `L` of `E`, then it contains a non-zero -lattice point of `L`. -/ +lattice point of `L`. -/ theorem exists_ne_zero_mem_lattice_of_measure_mul_two_pow_lt_measure [NormedAddCommGroup E] [NormedSpace ℝ E] [BorelSpace E] [FiniteDimensional ℝ E] [IsAddHaarMeasure μ] {L : AddSubgroup E} [Countable L] (fund : IsAddFundamentalDomain L F μ) diff --git a/Mathlib/MeasureTheory/Group/Measure.lean b/Mathlib/MeasureTheory/Group/Measure.lean index f1af9d26dac18..7d2ff6e601dcc 100644 --- a/Mathlib/MeasureTheory/Group/Measure.lean +++ b/Mathlib/MeasureTheory/Group/Measure.lean @@ -359,7 +359,7 @@ instance inv.instIsMulRightInvariant [IsMulLeftInvariant μ] : IsMulRightInvaria intro g conv_rhs => rw [← map_mul_left_eq_self μ g⁻¹] simp_rw [Measure.inv, map_map (measurable_mul_const g) measurable_inv, - map_map measurable_inv (measurable_const_mul g⁻¹), Function.comp, mul_inv_rev, inv_inv] + map_map measurable_inv (measurable_const_mul g⁻¹), Function.comp_def, mul_inv_rev, inv_inv] @[to_additive] instance inv.instIsMulLeftInvariant [IsMulRightInvariant μ] : IsMulLeftInvariant μ.inv := by @@ -367,7 +367,7 @@ instance inv.instIsMulLeftInvariant [IsMulRightInvariant μ] : IsMulLeftInvarian intro g conv_rhs => rw [← map_mul_right_eq_self μ g⁻¹] simp_rw [Measure.inv, map_map (measurable_const_mul g) measurable_inv, - map_map measurable_inv (measurable_mul_const g⁻¹), Function.comp, mul_inv_rev, inv_inv] + map_map measurable_inv (measurable_mul_const g⁻¹), Function.comp_def, mul_inv_rev, inv_inv] @[to_additive] theorem measurePreserving_div_left (μ : Measure G) [IsInvInvariant μ] [IsMulLeftInvariant μ] @@ -470,7 +470,7 @@ lemma eventually_nhds_one_measure_smul_diff_lt [LocallyCompactSpace G] μ (g • k \ k) ≤ μ (U \ k) := by gcongr exact (smul_set_subset_smul hg).trans hVkU - _ < ε := measure_diff_lt_of_lt_add h'k.measurableSet hUk hk.measure_lt_top.ne hμUk + _ < ε := measure_diff_lt_of_lt_add h'k.nullMeasurableSet hUk hk.measure_lt_top.ne hμUk /-- Continuity of the measure of translates of a compact set: Given a closed compact set `k` in a topological group, @@ -544,13 +544,9 @@ any compact set."] theorem measure_lt_top_of_isCompact_of_isMulLeftInvariant (U : Set G) (hU : IsOpen U) (h'U : U.Nonempty) (h : μ U ≠ ∞) {K : Set G} (hK : IsCompact K) : μ K < ∞ := by rw [← hU.interior_eq] at h'U - obtain ⟨t, hKt⟩ : ∃ t : Finset G, K ⊆ ⋃ (g : G) (_ : g ∈ t), (fun h : G => g * h) ⁻¹' U := + obtain ⟨t, hKt⟩ : ∃ t : Finset G, K ⊆ ⋃ g ∈ t, (fun h : G => g * h) ⁻¹' U := compact_covered_by_mul_left_translates hK h'U - calc - μ K ≤ μ (⋃ (g : G) (_ : g ∈ t), (fun h : G => g * h) ⁻¹' U) := measure_mono hKt - _ ≤ ∑ g ∈ t, μ ((fun h : G => g * h) ⁻¹' U) := measure_biUnion_finset_le _ _ - _ = Finset.card t * μ U := by simp only [measure_preimage_mul, Finset.sum_const, nsmul_eq_mul] - _ < ∞ := ENNReal.mul_lt_top (ENNReal.natCast_ne_top _) h + exact (measure_mono hKt).trans_lt <| measure_biUnion_lt_top t.finite_toSet <| by simp [h.lt_top] /-- If a left-invariant measure gives finite mass to a set with nonempty interior, then it gives finite mass to any compact set. -/ @@ -711,7 +707,7 @@ theorem haar_singleton [TopologicalGroup G] [BorelSpace G] (g : G) : μ {g} = μ @[to_additive IsAddHaarMeasure.smul] theorem IsHaarMeasure.smul {c : ℝ≥0∞} (cpos : c ≠ 0) (ctop : c ≠ ∞) : IsHaarMeasure (c • μ) := - { lt_top_of_isCompact := fun _K hK => ENNReal.mul_lt_top ctop hK.measure_lt_top.ne + { lt_top_of_isCompact := fun _K hK => ENNReal.mul_lt_top ctop.lt_top hK.measure_lt_top toIsOpenPosMeasure := isOpenPosMeasure_smul μ cpos } /-- If a left-invariant measure gives positive mass to some compact set with nonempty interior, then @@ -732,14 +728,15 @@ a Haar measure. See also `MulEquiv.isHaarMeasure_map`. -/ "The image of an additive Haar measure under a continuous surjective proper additive group homomorphism is again an additive Haar measure. See also `AddEquiv.isAddHaarMeasure_map`."] theorem isHaarMeasure_map [BorelSpace G] [TopologicalGroup G] {H : Type*} [Group H] - [TopologicalSpace H] [MeasurableSpace H] [BorelSpace H] [T2Space H] [TopologicalGroup H] + [TopologicalSpace H] [MeasurableSpace H] [BorelSpace H] [TopologicalGroup H] (f : G →* H) (hf : Continuous f) (h_surj : Surjective f) (h_prop : Tendsto f (cocompact G) (cocompact H)) : IsHaarMeasure (Measure.map f μ) := { toIsMulLeftInvariant := isMulLeftInvariant_map f.toMulHom hf.measurable h_surj lt_top_of_isCompact := by intro K hK - rw [map_apply hf.measurable hK.measurableSet] - exact IsCompact.measure_lt_top ((⟨⟨f, hf⟩, h_prop⟩ : CocompactMap G H).isCompact_preimage hK) + rw [← hK.measure_closure, map_apply hf.measurable isClosed_closure.measurableSet] + set g : CocompactMap G H := ⟨⟨f, hf⟩, h_prop⟩ + exact IsCompact.measure_lt_top (g.isCompact_preimage_of_isClosed hK.closure isClosed_closure) toIsOpenPosMeasure := hf.isOpenPosMeasure_map h_surj } /-- The image of a finite Haar measure under a continuous surjective group homomorphism is again @@ -751,10 +748,9 @@ theorem isHaarMeasure_map_of_isFiniteMeasure [BorelSpace G] [TopologicalGroup G] {H : Type*} [Group H] [TopologicalSpace H] [MeasurableSpace H] [BorelSpace H] [TopologicalGroup H] [IsFiniteMeasure μ] (f : G →* H) (hf : Continuous f) (h_surj : Surjective f) : - IsHaarMeasure (Measure.map f μ) := - { toIsMulLeftInvariant := isMulLeftInvariant_map f.toMulHom hf.measurable h_surj - lt_top_of_isCompact := fun _K hK ↦ hK.measure_lt_top - toIsOpenPosMeasure := hf.isOpenPosMeasure_map h_surj } + IsHaarMeasure (Measure.map f μ) where + toIsMulLeftInvariant := isMulLeftInvariant_map f.toMulHom hf.measurable h_surj + toIsOpenPosMeasure := hf.isOpenPosMeasure_map h_surj /-- The image of a Haar measure under map of a left action is again a Haar measure. -/ @[to_additive @@ -784,20 +780,11 @@ nonrec theorem _root_.MulEquiv.isHaarMeasure_map [BorelSpace G] [TopologicalGrou [Group H] [TopologicalSpace H] [MeasurableSpace H] [BorelSpace H] [TopologicalGroup H] (e : G ≃* H) (he : Continuous e) (hesymm : Continuous e.symm) : IsHaarMeasure (Measure.map e μ) := - { toIsMulLeftInvariant := isMulLeftInvariant_map e.toMulHom he.measurable e.surjective - lt_top_of_isCompact := by - intro K hK - let F : G ≃ₜ H := { - e.toEquiv with - continuous_toFun := he - continuous_invFun := hesymm } - change map F.toMeasurableEquiv μ K < ∞ - rw [F.toMeasurableEquiv.map_apply K] - exact (F.isCompact_preimage.mpr hK).measure_lt_top - toIsOpenPosMeasure := he.isOpenPosMeasure_map e.surjective } + let f : G ≃ₜ H := .mk e + isHaarMeasure_map μ e he e.surjective f.closedEmbedding.tendsto_cocompact /-- A convenience wrapper for MeasureTheory.Measure.isAddHaarMeasure_map`. -/ -theorem _root_.ContinuousLinearEquiv.isAddHaarMeasure_map +instance _root_.ContinuousLinearEquiv.isAddHaarMeasure_map {E F R S : Type*} [Semiring R] [Semiring S] [AddCommGroup E] [Module R E] [AddCommGroup F] [Module S F] [TopologicalSpace E] [TopologicalAddGroup E] [TopologicalSpace F] diff --git a/Mathlib/MeasureTheory/Group/Prod.lean b/Mathlib/MeasureTheory/Group/Prod.lean index 7e695cc33d3e1..775c06472f6f6 100644 --- a/Mathlib/MeasureTheory/Group/Prod.lean +++ b/Mathlib/MeasureTheory/Group/Prod.lean @@ -356,7 +356,7 @@ theorem measurePreserving_prod_mul_swap_right [IsMulRightInvariant μ] : " The map `(x, y) ↦ (x + y, y)` preserves the measure `μ × ν`. "] theorem measurePreserving_mul_prod [IsMulRightInvariant μ] : MeasurePreserving (fun z : G × G => (z.1 * z.2, z.2)) (μ.prod ν) (μ.prod ν) := - measurePreserving_swap.comp <| by apply measurePreserving_prod_mul_swap_right μ ν + measurePreserving_swap.comp (measurePreserving_prod_mul_swap_right μ ν) variable [MeasurableInv G] @@ -378,7 +378,7 @@ theorem measurePreserving_prod_div_swap [IsMulRightInvariant μ] : " The map `(x, y) ↦ (x - y, y)` preserves the measure `μ × ν`. "] theorem measurePreserving_div_prod [IsMulRightInvariant μ] : MeasurePreserving (fun z : G × G => (z.1 / z.2, z.2)) (μ.prod ν) (μ.prod ν) := - measurePreserving_swap.comp <| by apply measurePreserving_prod_div_swap μ ν + measurePreserving_swap.comp (measurePreserving_prod_div_swap μ ν) /-- The map `(x, y) ↦ (xy, x⁻¹)` is measure-preserving. -/ @[to_additive measurePreserving_add_prod_neg_right @@ -455,7 +455,7 @@ theorem quasiMeasurePreserving_mul_left [IsMulRightInvariant μ] (g : G) : have := (quasiMeasurePreserving_inv_of_right_invariant μ).comp (this.comp (quasiMeasurePreserving_inv_of_right_invariant μ)) - simp_rw [Function.comp, mul_inv_rev, inv_inv] at this + simp_rw [Function.comp_def, mul_inv_rev, inv_inv] at this exact this end QuasiMeasurePreserving diff --git a/Mathlib/MeasureTheory/Integral/Asymptotics.lean b/Mathlib/MeasureTheory/Integral/Asymptotics.lean index 17d15d5d198ac..f80409c54ea35 100644 --- a/Mathlib/MeasureTheory/Integral/Asymptotics.lean +++ b/Mathlib/MeasureTheory/Integral/Asymptotics.lean @@ -5,6 +5,7 @@ Authors: Lawrence Wu -/ import Mathlib.MeasureTheory.Group.Measure import Mathlib.MeasureTheory.Integral.IntegrableOn +import Mathlib.MeasureTheory.Integral.SetIntegral import Mathlib.MeasureTheory.Function.LocallyIntegrable /-! @@ -28,8 +29,13 @@ We establish integrability of `f` from `f = O(g)`. open Asymptotics MeasureTheory Set Filter -variable {α E F : Type*} [MeasurableSpace α] [NormedAddCommGroup E] [NormedAddCommGroup F] - {f : α → E} {g : α → F} {a b : α} {μ : Measure α} {l : Filter α} +variable {α E F : Type*} [NormedAddCommGroup E] {f : α → E} {g : α → F} {a b : α} {l : Filter α} + +namespace Asymptotics + +section Basic + +variable [MeasurableSpace α] [NormedAddCommGroup F] {μ : Measure α} /-- If `f = O[l] g` on measurably generated `l`, `f` is strongly measurable at `l`, and `g` is integrable at `l`, then `f` is integrable at `l`. -/ @@ -49,7 +55,53 @@ theorem _root_.Asymptotics.IsBigO.integrable (hfm : AEStronglyMeasurable f μ) rewrite [← integrableAtFilter_top] at * exact hf.integrableAtFilter ⟨univ, univ_mem, hfm.restrict⟩ hg -variable [TopologicalSpace α] [SecondCountableTopology α] +end Basic + +variable {ι : Type*} [MeasurableSpace ι] {f : ι × α → E} {s : Set ι} {μ : Measure ι} + +/-- Let `f : X x Y → Z`. If as `y` tends to `l`, `f(x, y) = O(g(y))` uniformly on `s : Set X` +of finite measure, then f is eventually (as `y` tends to `l`) integrable along `s`. -/ +theorem IsBigO.eventually_integrableOn [Norm F] + (hf : f =O[𝓟 s ×ˢ l] (g ∘ Prod.snd)) + (hfm : ∀ᶠ x in l, AEStronglyMeasurable (fun i ↦ f (i, x)) (μ.restrict s)) + (hs : MeasurableSet s) (hμ : μ s < ⊤) : + ∀ᶠ x in l, IntegrableOn (fun i ↦ f (i, x)) s μ := by + obtain ⟨C, hC⟩ := hf.bound + obtain ⟨t, htl, ht⟩ := hC.exists_mem + obtain ⟨u, hu, v, hv, huv⟩ := Filter.mem_prod_iff.mp htl + obtain ⟨w, hwl, hw⟩ := hfm.exists_mem + refine eventually_iff_exists_mem.mpr ⟨w ∩ v, inter_mem hwl hv, fun x hx ↦ ?_⟩ + haveI : IsFiniteMeasure (μ.restrict s) := ⟨Measure.restrict_apply_univ s ▸ hμ⟩ + refine Integrable.mono' (integrable_const (C * ‖g x‖)) (hw x hx.1) ?_ + filter_upwards [MeasureTheory.self_mem_ae_restrict hs] + intro y hy + exact ht (y, x) <| huv ⟨hu hy, hx.2⟩ + +variable [NormedSpace ℝ E] [NormedAddCommGroup F] + +/-- Let `f : X x Y → Z`. If as `y` tends to `l`, `f(x, y) = O(g(y))` uniformly on `s : Set X` +of finite measure, then the integral of `f` along `s` is `O(g(y))`. -/ +theorem IsBigO.set_integral_isBigO + (hf : f =O[𝓟 s ×ˢ l] (g ∘ Prod.snd)) (hs : MeasurableSet s) (hμ : μ s < ⊤) : + (fun x ↦ ∫ i in s, f (i, x) ∂μ) =O[l] g := by + obtain ⟨C, hC⟩ := hf.bound + obtain ⟨t, htl, ht⟩ := hC.exists_mem + obtain ⟨u, hu, v, hv, huv⟩ := Filter.mem_prod_iff.mp htl + refine isBigO_iff.mpr ⟨C * (μ s).toReal, eventually_iff_exists_mem.mpr ⟨v, hv, fun x hx ↦ ?_⟩⟩ + rw [mul_assoc, ← smul_eq_mul (a' := ‖g x‖), ← MeasureTheory.Measure.restrict_apply_univ, + ← integral_const, mul_comm, ← smul_eq_mul, ← integral_smul_const] + haveI : IsFiniteMeasure (μ.restrict s) := ⟨by rw [Measure.restrict_apply_univ s]; exact hμ⟩ + refine (norm_integral_le_integral_norm _).trans <| + integral_mono_of_nonneg (univ_mem' fun _ ↦ norm_nonneg _) (integrable_const _) ?_ + filter_upwards [MeasureTheory.self_mem_ae_restrict hs] + intro y hy + rw [smul_eq_mul, mul_comm] + exact ht (y, x) <| huv ⟨hu hy, hx⟩ + +end Asymptotics + +variable [TopologicalSpace α] [SecondCountableTopology α] [MeasurableSpace α] {μ : Measure α} + [NormedAddCommGroup F] namespace MeasureTheory diff --git a/Mathlib/MeasureTheory/Integral/Bochner.lean b/Mathlib/MeasureTheory/Integral/Bochner.lean index ab1f1a86e1f93..e26b72d02951b 100644 --- a/Mathlib/MeasureTheory/Integral/Bochner.lean +++ b/Mathlib/MeasureTheory/Integral/Bochner.lean @@ -433,7 +433,7 @@ theorem norm_eq_integral (f : α →₁ₛ[μ] E) : ‖f‖ = ((toSimpleFunc f). section PosPart -/-- Positive part of a simple function in L1 space. -/ +/-- Positive part of a simple function in L1 space. -/ nonrec def posPart (f : α →₁ₛ[μ] ℝ) : α →₁ₛ[μ] ℝ := ⟨Lp.posPart (f : α →₁[μ] ℝ), by rcases f with ⟨f, s, hsf⟩ @@ -441,7 +441,7 @@ nonrec def posPart (f : α →₁ₛ[μ] ℝ) : α →₁ₛ[μ] ℝ := simp only [Subtype.coe_mk, Lp.coe_posPart, ← hsf, AEEqFun.posPart_mk, SimpleFunc.coe_map, mk_eq_mk] -- Porting note: added - simp [SimpleFunc.posPart, Function.comp, EventuallyEq.rfl] ⟩ + simp [SimpleFunc.posPart, Function.comp_def, EventuallyEq.rfl] ⟩ /-- Negative part of a simple function in L1 space. -/ def negPart (f : α →₁ₛ[μ] ℝ) : α →₁ₛ[μ] ℝ := @@ -1000,7 +1000,7 @@ theorem continuous_of_dominated {F : X → α → G} {bound : α → ℝ} · simp [integral, hG, continuous_const] /-- The Bochner integral of a real-valued function `f : α → ℝ` is the difference between the - integral of the positive part of `f` and the integral of the negative part of `f`. -/ + integral of the positive part of `f` and the integral of the negative part of `f`. -/ theorem integral_eq_lintegral_pos_part_sub_lintegral_neg_part {f : α → ℝ} (hf : Integrable f μ) : ∫ a, f a ∂μ = ENNReal.toReal (∫⁻ a, .ofReal (f a) ∂μ) - ENNReal.toReal (∫⁻ a, .ofReal (-f a) ∂μ) := by @@ -1468,6 +1468,10 @@ theorem integral_zero_measure {m : MeasurableSpace α} (f : α → G) : exact setToFun_measure_zero (dominatedFinMeasAdditive_weightedSMul _) rfl · simp [integral, hG] +@[simp] +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 + 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 @@ -1958,3 +1962,5 @@ def evalIntegral : PositivityExt where eval {u α} zα pα e := do | _ => throwError "not MeasureTheory.integral" end Mathlib.Meta.Positivity + +set_option linter.style.longFile 2100 diff --git a/Mathlib/MeasureTheory/Integral/BoundedContinuousFunction.lean b/Mathlib/MeasureTheory/Integral/BoundedContinuousFunction.lean index 509fc54a3bb5b..326da6df177b3 100644 --- a/Mathlib/MeasureTheory/Integral/BoundedContinuousFunction.lean +++ b/Mathlib/MeasureTheory/Integral/BoundedContinuousFunction.lean @@ -87,7 +87,7 @@ lemma integrable [IsFiniteMeasure μ] (f : X →ᵇ E) : refine ⟨f.continuous.measurable.aestronglyMeasurable, (hasFiniteIntegral_def _ _).mp ?_⟩ calc ∫⁻ x, ‖f x‖₊ ∂μ _ ≤ ‖f‖₊ * (μ Set.univ) := f.lintegral_nnnorm_le μ - _ < ∞ := ENNReal.mul_lt_top ENNReal.coe_ne_top (measure_ne_top μ Set.univ) + _ < ∞ := ENNReal.mul_lt_top ENNReal.coe_lt_top (measure_lt_top μ Set.univ) variable [NormedSpace ℝ E] @@ -142,8 +142,8 @@ lemma tendsto_integral_of_forall_limsup_integral_le_integral {ι : Type*} {L : F rcases eq_or_neBot L with rfl|hL · simp only [tendsto_bot] have obs := BoundedContinuousFunction.isBounded_range_integral μs f - have bdd_above : IsBoundedUnder (· ≤ ·) L (fun i ↦ ∫ x, f x ∂μs i) := obs.bddAbove.isBoundedUnder - have bdd_below : IsBoundedUnder (· ≥ ·) L (fun i ↦ ∫ x, f x ∂μs i) := obs.bddBelow.isBoundedUnder + have bdd_above := BddAbove.isBoundedUnder L.univ_mem (by simpa using obs.bddAbove) + have bdd_below := BddBelow.isBoundedUnder L.univ_mem (by simpa using obs.bddBelow) apply tendsto_of_le_liminf_of_limsup_le _ _ bdd_above bdd_below · have key := h _ (f.norm_sub_nonneg) simp_rw [f.integral_const_sub ‖f‖] at key @@ -164,8 +164,8 @@ lemma tendsto_integral_of_forall_integral_le_liminf_integral {ι : Type*} {L : F rcases eq_or_neBot L with rfl|hL · simp only [tendsto_bot] have obs := BoundedContinuousFunction.isBounded_range_integral μs f - have bdd_above : IsBoundedUnder (· ≤ ·) L (fun i ↦ ∫ x, f x ∂μs i) := obs.bddAbove.isBoundedUnder - have bdd_below : IsBoundedUnder (· ≥ ·) L (fun i ↦ ∫ x, f x ∂μs i) := obs.bddBelow.isBoundedUnder + have bdd_above := BddAbove.isBoundedUnder L.univ_mem (by simpa using obs.bddAbove) + have bdd_below := BddBelow.isBoundedUnder L.univ_mem (by simpa using obs.bddBelow) apply @tendsto_of_le_liminf_of_limsup_le ℝ ι _ _ _ L (fun i ↦ ∫ x, f x ∂ (μs i)) (∫ x, f x ∂μ) · have key := h _ (f.add_norm_nonneg) simp_rw [f.integral_add_const ‖f‖] at key diff --git a/Mathlib/MeasureTheory/Integral/CircleIntegral.lean b/Mathlib/MeasureTheory/Integral/CircleIntegral.lean index 761aa3eb77f15..673ac92017bbf 100644 --- a/Mathlib/MeasureTheory/Integral/CircleIntegral.lean +++ b/Mathlib/MeasureTheory/Integral/CircleIntegral.lean @@ -362,7 +362,7 @@ theorem norm_two_pi_i_inv_smul_integral_le_of_norm_le_const {f : ℂ → E} {c : (hR : 0 ≤ R) (hf : ∀ z ∈ sphere c R, ‖f z‖ ≤ C) : ‖(2 * π * I : ℂ)⁻¹ • ∮ z in C(c, R), f z‖ ≤ R * C := by have : ‖(2 * π * I : ℂ)⁻¹‖ = (2 * π)⁻¹ := by simp [Real.pi_pos.le] - rw [norm_smul, this, ← div_eq_inv_mul, div_le_iff Real.two_pi_pos, mul_comm (R * C), ← mul_assoc] + rw [norm_smul, this, ← div_eq_inv_mul, div_le_iff₀ Real.two_pi_pos, mul_comm (R * C), ← mul_assoc] exact norm_integral_le_of_norm_le_const hR hf /-- If `f` is continuous on the circle `|z - c| = R`, `R > 0`, the `‖f z‖` is less than or equal to diff --git a/Mathlib/MeasureTheory/Integral/DivergenceTheorem.lean b/Mathlib/MeasureTheory/Integral/DivergenceTheorem.lean index dfb6dddd4aaef..2280f163883e0 100644 --- a/Mathlib/MeasureTheory/Integral/DivergenceTheorem.lean +++ b/Mathlib/MeasureTheory/Integral/DivergenceTheorem.lean @@ -236,7 +236,7 @@ theorem integral_divergence_of_hasFDerivWithinAt_off_countable_aux₂ (I : Box ( exact max_le hk.le δpos.lt.le _ ≤ ε := by rw [Box.Icc_def, Real.volume_Icc_pi_toReal ((J k).face i).lower_le_upper, - ← le_div_iff (hvol_pos _)] + ← le_div_iff₀ (hvol_pos _)] gcongr exacts [hvol_pos _, fun _ _ ↦ sub_nonneg.2 (Box.lower_le_upper _ _), (hJ_sub' _ (J _).upper_mem_Icc).2 _, (hJ_sub' _ (J _).lower_mem_Icc).1 _] @@ -350,7 +350,7 @@ theorem integral_divergence_of_hasFDerivWithinAt_off_countable_of_equiv {F : Typ simpa only [Set.mem_preimage, eL.apply_symm_apply, ← pi_univ_Icc, interior_pi_set (@finite_univ (Fin _) _), interior_Icc] using hx.1 · rw [← he_vol.integrableOn_comp_preimage he_emb, hIcc] - simp [← hDF, (· ∘ ·), Hi] + simp [← hDF, Function.comp_def, Hi] end diff --git a/Mathlib/MeasureTheory/Integral/DominatedConvergence.lean b/Mathlib/MeasureTheory/Integral/DominatedConvergence.lean index 0aa5977e8f9e6..7dc0c8c165627 100644 --- a/Mathlib/MeasureTheory/Integral/DominatedConvergence.lean +++ b/Mathlib/MeasureTheory/Integral/DominatedConvergence.lean @@ -255,8 +255,8 @@ variable {X : Type*} [TopologicalSpace X] [FirstCountableTopology X] /-- Continuity of interval integral with respect to a parameter, at a point within a set. Given `F : X → ℝ → E`, assume `F x` is ae-measurable on `[a, b]` for `x` in a - neighborhood of `x₀` within `s` and at `x₀`, and assume it is bounded by a function integrable - on `[a, b]` independent of `x` in a neighborhood of `x₀` within `s`. If `(fun x ↦ F x t)` + neighborhood of `x₀` within `s` and at `x₀`, and assume it is bounded by a function integrable + on `[a, b]` independent of `x` in a neighborhood of `x₀` within `s`. If `(fun x ↦ F x t)` is continuous at `x₀` within `s` for almost every `t` in `[a, b]` then the same holds for `(fun x ↦ ∫ t in a..b, F x t ∂μ) s x₀`. -/ theorem continuousWithinAt_of_dominated_interval {F : X → ℝ → E} {x₀ : X} {bound : ℝ → ℝ} {a b : ℝ} diff --git a/Mathlib/MeasureTheory/Integral/FundThmCalculus.lean b/Mathlib/MeasureTheory/Integral/FundThmCalculus.lean index 0ab09a7e17c02..d84c9db973bd2 100644 --- a/Mathlib/MeasureTheory/Integral/FundThmCalculus.lean +++ b/Mathlib/MeasureTheory/Integral/FundThmCalculus.lean @@ -1559,3 +1559,5 @@ theorem integral_deriv_comp_mul_deriv {f f' g g' : ℝ → ℝ} end Mul end intervalIntegral + +set_option linter.style.longFile 1700 diff --git a/Mathlib/MeasureTheory/Integral/IntegralEqImproper.lean b/Mathlib/MeasureTheory/Integral/IntegralEqImproper.lean index 4b9143054ef0c..902812d6d999d 100644 --- a/Mathlib/MeasureTheory/Integral/IntegralEqImproper.lean +++ b/Mathlib/MeasureTheory/Integral/IntegralEqImproper.lean @@ -1241,7 +1241,7 @@ theorem integral_mul_deriv_eq_deriv_mul [CompleteSpace A] (huv' : Integrable (u * v')) (hu'v : Integrable (u' * v)) (h_bot : Tendsto (u * v) atBot (𝓝 a')) (h_top : Tendsto (u * v) atTop (𝓝 b')) : ∫ (x : ℝ), u x * v' x = b' - a' - ∫ (x : ℝ), u' x * v x := - integral_bilinear_hasDerivAt_right_eq_sub (L := ContinuousLinearMap.mul ℝ A) + integral_bilinear_hasDerivAt_right_eq_sub (L := ContinuousLinearMap.mul ℝ A) hu hv huv' hu'v h_bot h_top /-- **Integration by parts on (-∞, ∞).** diff --git a/Mathlib/MeasureTheory/Integral/IntervalIntegral.lean b/Mathlib/MeasureTheory/Integral/IntervalIntegral.lean index 3e19fb4e62ced..0acaf9efc4688 100644 --- a/Mathlib/MeasureTheory/Integral/IntervalIntegral.lean +++ b/Mathlib/MeasureTheory/Integral/IntervalIntegral.lean @@ -620,12 +620,7 @@ section Comp variable {a b c d : ℝ} (f : ℝ → E) -/-! -Porting note: some `@[simp]` attributes in this section were removed to make the `simpNF` linter -happy. TODO: find out if these lemmas are actually good or bad `simp` lemmas. --/ - -@[simp] -- Porting note (#10618): was @[simp] +@[simp] theorem integral_comp_mul_right (hc : c ≠ 0) : (∫ x in a..b, f (x * c)) = c⁻¹ • ∫ x in a * c..b * c, f x := by have A : MeasurableEmbedding fun x => x * c := @@ -638,32 +633,32 @@ theorem integral_comp_mul_right (hc : c ≠ 0) : Measure.restrict_congr_set (α := ℝ) (μ := volume) Ico_ae_eq_Ioc] · simp [h, mul_div_cancel_right₀, hc, abs_of_pos] -@[simp] -- Porting note (#10618): was @[simp] +@[simp] theorem smul_integral_comp_mul_right (c) : (c • ∫ x in a..b, f (x * c)) = ∫ x in a * c..b * c, f x := by by_cases hc : c = 0 <;> simp [hc, integral_comp_mul_right] -@[simp] -- Porting note (#10618): was @[simp] +@[simp] theorem integral_comp_mul_left (hc : c ≠ 0) : (∫ x in a..b, f (c * x)) = c⁻¹ • ∫ x in c * a..c * b, f x := by simpa only [mul_comm c] using integral_comp_mul_right f hc -@[simp] -- Porting note (#10618): was @[simp] +@[simp] theorem smul_integral_comp_mul_left (c) : (c • ∫ x in a..b, f (c * x)) = ∫ x in c * a..c * b, f x := by by_cases hc : c = 0 <;> simp [hc, integral_comp_mul_left] -@[simp] -- Porting note (#10618): was @[simp] +@[simp] theorem integral_comp_div (hc : c ≠ 0) : (∫ x in a..b, f (x / c)) = c • ∫ x in a / c..b / c, f x := by simpa only [inv_inv] using integral_comp_mul_right f (inv_ne_zero hc) -@[simp] -- Porting note (#10618): was @[simp] +@[simp] theorem inv_smul_integral_comp_div (c) : (c⁻¹ • ∫ x in a..b, f (x / c)) = ∫ x in a / c..b / c, f x := by by_cases hc : c = 0 <;> simp [hc, integral_comp_div] -@[simp] -- Porting note (#10618): was @[simp] +@[simp] theorem integral_comp_add_right (d) : (∫ x in a..b, f (x + d)) = ∫ x in a + d..b + d, f x := have A : MeasurableEmbedding fun x => x + d := (Homeomorph.addRight d).closedEmbedding.measurableEmbedding @@ -672,102 +667,102 @@ theorem integral_comp_add_right (d) : (∫ x in a..b, f (x + d)) = ∫ x in a + simp [intervalIntegral, A.setIntegral_map] _ = ∫ x in a + d..b + d, f x := by rw [map_add_right_eq_self] -@[simp] -- Porting note (#10618): was @[simp] +@[simp] nonrec theorem integral_comp_add_left (d) : (∫ x in a..b, f (d + x)) = ∫ x in d + a..d + b, f x := by simpa only [add_comm d] using integral_comp_add_right f d -@[simp] -- Porting note (#10618): was @[simp] +@[simp] theorem integral_comp_mul_add (hc : c ≠ 0) (d) : (∫ x in a..b, f (c * x + d)) = c⁻¹ • ∫ x in c * a + d..c * b + d, f x := by rw [← integral_comp_add_right, ← integral_comp_mul_left _ hc] -@[simp] -- Porting note (#10618): was @[simp] +@[simp] theorem smul_integral_comp_mul_add (c d) : (c • ∫ x in a..b, f (c * x + d)) = ∫ x in c * a + d..c * b + d, f x := by by_cases hc : c = 0 <;> simp [hc, integral_comp_mul_add] -@[simp] -- Porting note (#10618): was @[simp] +@[simp] theorem integral_comp_add_mul (hc : c ≠ 0) (d) : (∫ x in a..b, f (d + c * x)) = c⁻¹ • ∫ x in d + c * a..d + c * b, f x := by rw [← integral_comp_add_left, ← integral_comp_mul_left _ hc] --- Porting note (#10618): was @[simp] +@[simp] theorem smul_integral_comp_add_mul (c d) : (c • ∫ x in a..b, f (d + c * x)) = ∫ x in d + c * a..d + c * b, f x := by by_cases hc : c = 0 <;> simp [hc, integral_comp_add_mul] --- Porting note (#10618): was @[simp] +@[simp] theorem integral_comp_div_add (hc : c ≠ 0) (d) : (∫ x in a..b, f (x / c + d)) = c • ∫ x in a / c + d..b / c + d, f x := by simpa only [div_eq_inv_mul, inv_inv] using integral_comp_mul_add f (inv_ne_zero hc) d --- Porting note (#10618): was @[simp] +@[simp] theorem inv_smul_integral_comp_div_add (c d) : (c⁻¹ • ∫ x in a..b, f (x / c + d)) = ∫ x in a / c + d..b / c + d, f x := by by_cases hc : c = 0 <;> simp [hc, integral_comp_div_add] --- Porting note (#10618): was @[simp] +@[simp] theorem integral_comp_add_div (hc : c ≠ 0) (d) : (∫ x in a..b, f (d + x / c)) = c • ∫ x in d + a / c..d + b / c, f x := by simpa only [div_eq_inv_mul, inv_inv] using integral_comp_add_mul f (inv_ne_zero hc) d --- Porting note (#10618): was @[simp] +@[simp] theorem inv_smul_integral_comp_add_div (c d) : (c⁻¹ • ∫ x in a..b, f (d + x / c)) = ∫ x in d + a / c..d + b / c, f x := by by_cases hc : c = 0 <;> simp [hc, integral_comp_add_div] --- Porting note (#10618): was @[simp] +@[simp] theorem integral_comp_mul_sub (hc : c ≠ 0) (d) : (∫ x in a..b, f (c * x - d)) = c⁻¹ • ∫ x in c * a - d..c * b - d, f x := by simpa only [sub_eq_add_neg] using integral_comp_mul_add f hc (-d) --- Porting note (#10618): was @[simp] +@[simp] theorem smul_integral_comp_mul_sub (c d) : (c • ∫ x in a..b, f (c * x - d)) = ∫ x in c * a - d..c * b - d, f x := by by_cases hc : c = 0 <;> simp [hc, integral_comp_mul_sub] --- Porting note (#10618): was @[simp] +@[simp] theorem integral_comp_sub_mul (hc : c ≠ 0) (d) : (∫ x in a..b, f (d - c * x)) = c⁻¹ • ∫ x in d - c * b..d - c * a, f x := by simp only [sub_eq_add_neg, neg_mul_eq_neg_mul] rw [integral_comp_add_mul f (neg_ne_zero.mpr hc) d, integral_symm] simp only [inv_neg, smul_neg, neg_neg, neg_smul] --- Porting note (#10618): was @[simp] +@[simp] theorem smul_integral_comp_sub_mul (c d) : (c • ∫ x in a..b, f (d - c * x)) = ∫ x in d - c * b..d - c * a, f x := by by_cases hc : c = 0 <;> simp [hc, integral_comp_sub_mul] --- Porting note (#10618): was @[simp] +@[simp] theorem integral_comp_div_sub (hc : c ≠ 0) (d) : (∫ x in a..b, f (x / c - d)) = c • ∫ x in a / c - d..b / c - d, f x := by simpa only [div_eq_inv_mul, inv_inv] using integral_comp_mul_sub f (inv_ne_zero hc) d --- Porting note (#10618): was @[simp] +@[simp] theorem inv_smul_integral_comp_div_sub (c d) : (c⁻¹ • ∫ x in a..b, f (x / c - d)) = ∫ x in a / c - d..b / c - d, f x := by by_cases hc : c = 0 <;> simp [hc, integral_comp_div_sub] --- Porting note (#10618): was @[simp] +@[simp] theorem integral_comp_sub_div (hc : c ≠ 0) (d) : (∫ x in a..b, f (d - x / c)) = c • ∫ x in d - b / c..d - a / c, f x := by simpa only [div_eq_inv_mul, inv_inv] using integral_comp_sub_mul f (inv_ne_zero hc) d --- Porting note (#10618): was @[simp] +@[simp] theorem inv_smul_integral_comp_sub_div (c d) : (c⁻¹ • ∫ x in a..b, f (d - x / c)) = ∫ x in d - b / c..d - a / c, f x := by by_cases hc : c = 0 <;> simp [hc, integral_comp_sub_div] --- Porting note (#10618): was @[simp] +@[simp] theorem integral_comp_sub_right (d) : (∫ x in a..b, f (x - d)) = ∫ x in a - d..b - d, f x := by simpa only [sub_eq_add_neg] using integral_comp_add_right f (-d) --- Porting note (#10618): was @[simp] +@[simp] theorem integral_comp_sub_left (d) : (∫ x in a..b, f (d - x)) = ∫ x in d - b..d - a, f x := by simpa only [one_mul, one_smul, inv_one] using integral_comp_sub_mul f one_ne_zero d --- Porting note (#10618): was @[simp] +@[simp] theorem integral_comp_neg : (∫ x in a..b, f (-x)) = ∫ x in -b..-a, f x := by simpa only [zero_sub] using integral_comp_sub_left f 0 diff --git a/Mathlib/MeasureTheory/Integral/Layercake.lean b/Mathlib/MeasureTheory/Integral/Layercake.lean index 220f6a09f2e21..e0771f0991c48 100644 --- a/Mathlib/MeasureTheory/Integral/Layercake.lean +++ b/Mathlib/MeasureTheory/Integral/Layercake.lean @@ -237,7 +237,7 @@ theorem lintegral_comp_eq_lintegral_meas_le_mul_of_measurable (μ : Measure α) exact fun a ha ↦ hx.2.trans (le_of_lt ha) _ ≤ ∫⁻ t in Ioi 0, μ {a : α | t ≤ f a} * ENNReal.ofReal (g t) := lintegral_mono_set Ioc_subset_Ioi_self - /- The second integral is infinite, as one integrates amont other things on those `ω` where + /- The second integral is infinite, as one integrates among other things on those `ω` where `f ω > s`: this is an infinite measure set, and on it the integrand is bounded below by `∫ t in 0..s, g t` which is positive. -/ have B : ∫⁻ ω, ENNReal.ofReal (∫ t in (0)..f ω, g t) ∂μ = ∞ := by diff --git a/Mathlib/MeasureTheory/Integral/Lebesgue.lean b/Mathlib/MeasureTheory/Integral/Lebesgue.lean index f85ddf5e5f9b9..f41a9e5db44de 100644 --- a/Mathlib/MeasureTheory/Integral/Lebesgue.lean +++ b/Mathlib/MeasureTheory/Integral/Lebesgue.lean @@ -146,7 +146,7 @@ alias set_lintegral_one := setLIntegral_one theorem setLIntegral_const_lt_top [IsFiniteMeasure μ] (s : Set α) {c : ℝ≥0∞} (hc : c ≠ ∞) : ∫⁻ _ in s, c ∂μ < ∞ := by rw [lintegral_const] - exact ENNReal.mul_lt_top hc (measure_ne_top (μ.restrict s) univ) + exact ENNReal.mul_lt_top hc.lt_top (measure_lt_top (μ.restrict s) univ) @[deprecated (since := "2024-06-29")] alias set_lintegral_const_lt_top := setLIntegral_const_lt_top @@ -476,7 +476,7 @@ theorem exists_pos_setLIntegral_lt_of_measure_lt {f : α → ℝ≥0∞} (h : exact SimpleFunc.lintegral_mono le_rfl Measure.restrict_le_self _ ≤ (SimpleFunc.const α (C : ℝ≥0∞)).lintegral (μ.restrict s) + ε₁ := by gcongr - exact SimpleFunc.lintegral_mono (fun x ↦ ENNReal.coe_le_coe.2 (hC x)) le_rfl + exact fun x ↦ ENNReal.coe_le_coe.2 (hC x) _ = C * μ s + ε₁ := by simp only [← SimpleFunc.lintegral_eq_lintegral, coe_const, lintegral_const, Measure.restrict_apply, MeasurableSet.univ, univ_inter, Function.const] @@ -918,6 +918,15 @@ theorem lintegral_eq_zero_iff' {f : α → ℝ≥0∞} (hf : AEMeasurable f μ) theorem lintegral_eq_zero_iff {f : α → ℝ≥0∞} (hf : Measurable f) : ∫⁻ a, f a ∂μ = 0 ↔ f =ᵐ[μ] 0 := lintegral_eq_zero_iff' hf.aemeasurable +theorem setLIntegral_eq_zero_iff' {s : Set α} (hs : MeasurableSet s) + {f : α → ℝ≥0∞} (hf : AEMeasurable f (μ.restrict s)) : + ∫⁻ a in s, f a ∂μ = 0 ↔ ∀ᵐ x ∂μ, x ∈ s → f x = 0 := + (lintegral_eq_zero_iff' hf).trans (ae_restrict_iff' hs) + +theorem setLIntegral_eq_zero_iff {s : Set α} (hs : MeasurableSet s) {f : α → ℝ≥0∞} + (hf : Measurable f) : ∫⁻ a in s, f a ∂μ = 0 ↔ ∀ᵐ x ∂μ, x ∈ s → f x = 0 := + setLIntegral_eq_zero_iff' hs hf.aemeasurable + theorem lintegral_pos_iff_support {f : α → ℝ≥0∞} (hf : Measurable f) : (0 < ∫⁻ a, f a ∂μ) ↔ 0 < μ (Function.support f) := by simp [pos_iff_ne_zero, hf, Filter.EventuallyEq, ae_iff, Function.support] @@ -926,7 +935,7 @@ theorem setLintegral_pos_iff {f : α → ℝ≥0∞} (hf : Measurable f) {s : Se 0 < ∫⁻ a in s, f a ∂μ ↔ 0 < μ (Function.support f ∩ s) := by rw [lintegral_pos_iff_support hf, Measure.restrict_apply (measurableSet_support hf)] -/-- Weaker version of the monotone convergence theorem-/ +/-- Weaker version of the monotone convergence theorem -/ theorem lintegral_iSup_ae {f : ℕ → α → ℝ≥0∞} (hf : ∀ n, Measurable (f n)) (h_mono : ∀ n, ∀ᵐ a ∂μ, f n a ≤ f n.succ a) : ∫⁻ a, ⨆ n, f n a ∂μ = ⨆ n, ∫⁻ a, f n a ∂μ := by classical @@ -1649,7 +1658,7 @@ theorem setLIntegral_lt_top_of_le_nnreal {s : Set α} (hs : μ s ≠ ∞) {f : (hbdd : ∃ y : ℝ≥0, ∀ x ∈ s, f x ≤ y) : ∫⁻ x in s, f x ∂μ < ∞ := by obtain ⟨M, hM⟩ := hbdd refine lt_of_le_of_lt (setLIntegral_mono measurable_const hM) ?_ - simp [ENNReal.mul_lt_top, hs] + simp [ENNReal.mul_lt_top, hs.lt_top] /-- Lebesgue integral of a bounded function over a set of finite measure is finite. Note that this lemma assumes no regularity of either `f` or `s`. -/ @@ -1832,7 +1841,7 @@ theorem exists_measurable_le_forall_setLIntegral_eq [SFinite μ] (f : α → ℝ have hφle : φ ≤ f := fun x ↦ iSup_le (hgf · x) refine ⟨φ, hφm, hφle, fun s ↦ ?_⟩ -- Now we show the inequality between set integrals. - -- Choose a simple function `ψ ≤ f` with values in `ℝ≥0` and prove for `ψ`. + -- Choose a simple function `ψ ≤ f` with values in `ℝ≥0` and prove for `ψ`. rw [lintegral_eq_nnreal] refine iSup₂_le fun ψ hψ ↦ ?_ -- Choose `n` such that `ψ x ≤ n` for all `x`. @@ -1943,7 +1952,8 @@ constant. -/ theorem lintegral_le_of_forall_fin_meas_le [MeasurableSpace α] {μ : Measure α} [SigmaFinite μ] (C : ℝ≥0∞) {f : α → ℝ≥0∞} (hf : ∀ s, MeasurableSet s → μ s ≠ ∞ → ∫⁻ x in s, f x ∂μ ≤ C) : ∫⁻ x, f x ∂μ ≤ C := - @lintegral_le_of_forall_fin_meas_trim_le _ _ _ _ _ (by rwa [trim_eq_self]) C _ hf + have : SigmaFinite (μ.trim le_rfl) := by rwa [trim_eq_self] + lintegral_le_of_forall_fin_meas_trim_le _ C hf theorem SimpleFunc.exists_lt_lintegral_simpleFunc_of_lt_lintegral {m : MeasurableSpace α} {μ : Measure α} [SigmaFinite μ] {f : α →ₛ ℝ≥0} {L : ℝ≥0∞} (hL : L < ∫⁻ x, f x ∂μ) : @@ -1967,7 +1977,7 @@ theorem SimpleFunc.exists_lt_lintegral_simpleFunc_of_lt_lintegral {m : Measurabl exact zero_le _ · simp only [ht, const_zero, coe_piecewise, coe_const, SimpleFunc.coe_zero, univ_inter, piecewise_eq_indicator, ENNReal.coe_indicator, Function.const_apply, lintegral_indicator, - lintegral_const, Measure.restrict_apply', ENNReal.mul_lt_top ENNReal.coe_ne_top t_top.ne] + lintegral_const, Measure.restrict_apply', ENNReal.mul_lt_top ENNReal.coe_lt_top t_top] · simp only [ht, const_zero, coe_piecewise, coe_const, SimpleFunc.coe_zero, piecewise_eq_indicator, ENNReal.coe_indicator, Function.const_apply, lintegral_indicator, lintegral_const, Measure.restrict_apply', univ_inter] @@ -2049,3 +2059,5 @@ lemma tendsto_measure_of_ae_tendsto_indicator_of_isFiniteMeasure end TendstoIndicator -- section end MeasureTheory + +set_option linter.style.longFile 2200 diff --git a/Mathlib/MeasureTheory/Integral/MeanInequalities.lean b/Mathlib/MeasureTheory/Integral/MeanInequalities.lean index 9db0c3fc5fb59..39a15c80e968f 100644 --- a/Mathlib/MeasureTheory/Integral/MeanInequalities.lean +++ b/Mathlib/MeasureTheory/Integral/MeanInequalities.lean @@ -296,7 +296,7 @@ theorem lintegral_rpow_add_lt_top_of_lintegral_rpow_lt_top {p : ℝ} {f g : α ENNReal.rpow_ne_top_of_nonneg (by simp [hp1]) ENNReal.coe_ne_top rw [lintegral_add_left', lintegral_const_mul'' _ (hf.pow_const p), lintegral_const_mul' _ _ h_two, ENNReal.add_lt_top] - · exact ⟨ENNReal.mul_lt_top h_two hf_top.ne, ENNReal.mul_lt_top h_two hg_top.ne⟩ + · exact ⟨ENNReal.mul_lt_top h_two.lt_top hf_top, ENNReal.mul_lt_top h_two.lt_top hg_top⟩ · exact (hf.pow_const p).const_mul _ theorem lintegral_Lp_mul_le_Lq_mul_Lr {α} [MeasurableSpace α] {p q r : ℝ} (hp0_lt : 0 < p) diff --git a/Mathlib/MeasureTheory/Integral/Pi.lean b/Mathlib/MeasureTheory/Integral/Pi.lean index ad9202ef91631..3445cc3f930f1 100644 --- a/Mathlib/MeasureTheory/Integral/Pi.lean +++ b/Mathlib/MeasureTheory/Integral/Pi.lean @@ -33,7 +33,8 @@ theorem Integrable.fin_nat_prod {n : ℕ} {E : Fin n → Type*} | succ n n_ih => have := ((measurePreserving_piFinSuccAbove (fun i => (volume : Measure (E i))) 0).symm) rw [volume_pi, ← this.integrable_comp_emb (MeasurableEquiv.measurableEmbedding _)] - simp_rw [MeasurableEquiv.piFinSuccAbove_symm_apply, Fin.prod_univ_succ, Fin.insertNth_zero] + simp_rw [MeasurableEquiv.piFinSuccAbove_symm_apply, Fin.insertNthEquiv, + Fin.prod_univ_succ, Fin.insertNth_zero] simp only [Fin.zero_succAbove, cast_eq, Function.comp_def, Fin.cons_zero, Fin.cons_succ] have : Integrable (fun (x : (j : Fin n) → E (Fin.succ j)) ↦ ∏ j, f (Fin.succ j) (x j)) := n_ih (fun i ↦ hf _) @@ -75,9 +76,9 @@ theorem integral_fin_nat_prod_eq_prod {n : ℕ} {E : Fin n → Type*} f 0 x.1 * ∏ i : Fin n, f (Fin.succ i) (x.2 i) := by rw [volume_pi, ← ((measurePreserving_piFinSuccAbove (fun i => (volume : Measure (E i))) 0).symm).integral_comp'] - simp_rw [MeasurableEquiv.piFinSuccAbove_symm_apply, - Fin.prod_univ_succ, Fin.insertNth_zero, Fin.cons_succ, volume_eq_prod, volume_pi, - Fin.zero_succAbove, cast_eq, Fin.cons_zero] + simp_rw [MeasurableEquiv.piFinSuccAbove_symm_apply, Fin.insertNthEquiv, + Fin.prod_univ_succ, Fin.insertNth_zero, Equiv.coe_fn_mk, Fin.cons_succ, volume_eq_prod, + volume_pi, Fin.zero_succAbove, cast_eq, Fin.cons_zero] _ = (∫ x, f 0 x) * ∏ i : Fin n, ∫ (x : E (Fin.succ i)), f (Fin.succ i) x := by rw [← n_ih, ← integral_prod_mul, volume_eq_prod] _ = ∏ i, ∫ x, f i x := by rw [Fin.prod_univ_succ] diff --git a/Mathlib/MeasureTheory/Integral/SetIntegral.lean b/Mathlib/MeasureTheory/Integral/SetIntegral.lean index 9982a8ab04974..f7e029875e697 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.Compact +import Mathlib.Topology.ContinuousFunction.ContinuousMapZero import Mathlib.Analysis.NormedSpace.HahnBanach.SeparatingDual /-! @@ -233,7 +233,7 @@ theorem tendsto_setIntegral_of_monotone {ι : Type*} [Countable ι] [Semilattice rw [mem_closedBall_iff_norm', ← integral_diff (hsm i) hfi hsub, ← coe_nnnorm, NNReal.coe_le_coe, ← ENNReal.coe_le_coe] refine (ennnorm_integral_le_lintegral_ennnorm _).trans ?_ - rw [← withDensity_apply _ (hSm.diff (hsm _)), ← hν, measure_diff hsub (hsm _)] + rw [← withDensity_apply _ (hSm.diff (hsm _)), ← hν, measure_diff hsub (hsm _).nullMeasurableSet] exacts [tsub_le_iff_tsub_le.mp hi.1, (hi.2.trans_lt <| ENNReal.add_lt_top.2 ⟨hfi', ENNReal.coe_lt_top⟩).ne] @@ -255,14 +255,15 @@ theorem tendsto_setIntegral_of_antitone {ι : Type*} [Countable ι] [Semilattice simpa [hsm i₀, ν, ENNReal.ofReal, norm_toNNReal] using hi₀.norm.lintegral_lt_top.ne have νS : ν S ≠ ∞ := ((measure_mono (hsub i₀)).trans_lt νi₀.lt_top).ne have : ∀ᶠ i in atTop, ν (s i) ∈ Icc (ν S - ε) (ν S + ε) := by - apply tendsto_measure_iInter hsm h_anti ⟨i₀, νi₀⟩ + apply tendsto_measure_iInter (fun i ↦ (hsm i).nullMeasurableSet) h_anti ⟨i₀, νi₀⟩ apply ENNReal.Icc_mem_nhds νS (ENNReal.coe_pos.2 ε0).ne' filter_upwards [this, Ici_mem_atTop i₀] with i hi h'i rw [mem_closedBall_iff_norm, ← integral_diff hSm (hi₀.mono_set (h_anti h'i)) (hsub i), ← coe_nnnorm, NNReal.coe_le_coe, ← ENNReal.coe_le_coe] refine (ennnorm_integral_le_lintegral_ennnorm _).trans ?_ - rw [← withDensity_apply _ ((hsm _).diff hSm), ← hν, measure_diff (hsub i) hSm νS] - exact tsub_le_iff_left.2 hi.2 + rw [← withDensity_apply _ ((hsm _).diff hSm), ← hν, + measure_diff_le_iff_le_add hSm.nullMeasurableSet (hsub i) νS] + exact hi.2 @[deprecated (since := "2024-04-17")] alias tendsto_set_integral_of_antitone := tendsto_setIntegral_of_antitone @@ -1266,16 +1267,27 @@ theorem integral_comp_comm (L : E ≃L[𝕜] F) (φ : X → E) : ∫ x, L (φ x) end ContinuousLinearEquiv -namespace ContinuousMap +section ContinuousMap -lemma integral_apply [TopologicalSpace Y] [CompactSpace Y] [NormedSpace ℝ E] - [CompleteSpace E] {f : X → C(Y, E)} (hf : Integrable f μ) (y : Y) : - (∫ x, f x ∂μ) y = ∫ x, f x y ∂μ := by +variable [TopologicalSpace Y] [CompactSpace Y] + +lemma ContinuousMap.integral_apply [NormedSpace ℝ E] [CompleteSpace E] {f : X → C(Y, E)} + (hf : Integrable f μ) (y : Y) : (∫ x, f x ∂μ) y = ∫ x, f x y ∂μ := by calc (∫ x, f x ∂μ) y = ContinuousMap.evalCLM ℝ y (∫ x, f x ∂μ) := rfl _ = ∫ x, ContinuousMap.evalCLM ℝ y (f x) ∂μ := (ContinuousLinearMap.integral_comp_comm _ hf).symm _ = _ := rfl +open scoped ContinuousMapZero in +theorem ContinuousMapZero.integral_apply {R : Type*} [NormedCommRing R] [Zero Y] + [NormedAlgebra ℝ R] [CompleteSpace R] {f : X → C(Y, R)₀} + (hf : MeasureTheory.Integrable f μ) (y : Y) : + (∫ (x : X), f x ∂μ) y = ∫ (x : X), (f x) y ∂μ := by + calc (∫ x, f x ∂μ) y = ContinuousMapZero.evalCLM ℝ y (∫ x, f x ∂μ) := rfl + _ = ∫ x, ContinuousMapZero.evalCLM ℝ y (f x) ∂μ := + (ContinuousLinearMap.integral_comp_comm _ hf).symm + _ = _ := rfl + end ContinuousMap @[norm_cast] @@ -1604,3 +1616,5 @@ lemma continuousOn_integral_of_compact_support hk hf hfs (integrableOn_const.2 (Or.inr hk.measure_lt_top)) (μ := μ) (g := fun _ ↦ 1) end ParametricIntegral + +set_option linter.style.longFile 1700 diff --git a/Mathlib/MeasureTheory/Integral/SetToL1.lean b/Mathlib/MeasureTheory/Integral/SetToL1.lean index 55416b4d8f253..02f0849ff37db 100644 --- a/Mathlib/MeasureTheory/Integral/SetToL1.lean +++ b/Mathlib/MeasureTheory/Integral/SetToL1.lean @@ -158,9 +158,8 @@ theorem map_iUnion_fin_meas_set_eq_sum (T : Set α → β) (T_empty : T ∅ = 0) h_add (S a) (⋃ i ∈ s, S i) (hS_meas a) (measurableSet_biUnion _ fun i _ => hS_meas i) (hps a (Finset.mem_insert_self a s))] · congr; convert Finset.iSup_insert a s S - · exact - ((measure_biUnion_finset_le _ _).trans_lt <| - ENNReal.sum_lt_top fun i hi => hps i <| Finset.mem_insert_of_mem hi).ne + · exact (measure_biUnion_lt_top s.finite_toSet fun i hi ↦ + (hps i <| Finset.mem_insert_of_mem hi).lt_top).ne · simp_rw [Set.inter_iUnion] refine iUnion_eq_empty.mpr fun i => iUnion_eq_empty.mpr fun hi => ?_ rw [← Set.disjoint_iff_inter_eq_empty] @@ -1427,8 +1426,8 @@ theorem continuous_L1_toL1 {μ' : Measure α} (c' : ℝ≥0∞) (hc' : c' ≠ have h_eLpNorm_ne_top' : eLpNorm (⇑g - ⇑f) 1 μ' ≠ ∞ := by refine ((eLpNorm_mono_measure _ hμ'_le).trans_lt ?_).ne rw [eLpNorm_smul_measure_of_ne_zero hc'0, smul_eq_mul] - refine ENNReal.mul_lt_top ?_ h_eLpNorm_ne_top - simp [hc', hc'0] + refine ENNReal.mul_lt_top ?_ h_eLpNorm_ne_top.lt_top + simp [hc'.lt_top, hc'0] calc (eLpNorm (⇑g - ⇑f) 1 μ').toReal ≤ (c' * eLpNorm (⇑g - ⇑f) 1 μ).toReal := by rw [toReal_le_toReal h_eLpNorm_ne_top' (ENNReal.mul_ne_top hc' h_eLpNorm_ne_top)] @@ -1455,7 +1454,7 @@ theorem setToFun_congr_measure_of_integrable {μ' : Measure α} (c' : ℝ≥0∞ have hμ's : μ' s ≠ ∞ := by refine ((hμ'_le s).trans_lt ?_).ne rw [Measure.smul_apply, smul_eq_mul] - exact ENNReal.mul_lt_top hc' hμs.ne + exact ENNReal.mul_lt_top hc'.lt_top hμs rw [setToFun_indicator_const hT hs hμs.ne, setToFun_indicator_const hT' hs hμ's] · intro f₂ g₂ _ hf₂ hg₂ h_eq_f h_eq_g rw [setToFun_add hT hf₂ hg₂, setToFun_add hT' (h_int f₂ hf₂) (h_int g₂ hg₂), h_eq_f, h_eq_g] @@ -1646,3 +1645,5 @@ theorem continuous_setToFun_of_dominated (hT : DominatedFinMeasAdditive μ T C) end Function end MeasureTheory + +set_option linter.style.longFile 1800 diff --git a/Mathlib/MeasureTheory/Integral/TorusIntegral.lean b/Mathlib/MeasureTheory/Integral/TorusIntegral.lean index 3398c9ead73c2..2ac46ce80a629 100644 --- a/Mathlib/MeasureTheory/Integral/TorusIntegral.lean +++ b/Mathlib/MeasureTheory/Integral/TorusIntegral.lean @@ -217,7 +217,7 @@ theorem torusIntegral_succAbove have hem : MeasurePreserving e := (volume_preserving_piFinSuccAbove (fun _ : Fin (n + 1) => ℝ) i).symm _ have heπ : (e ⁻¹' Icc 0 fun _ => 2 * π) = Icc 0 (2 * π) ×ˢ Icc (0 : ℝⁿ) fun _ => 2 * π := - ((OrderIso.piFinSuccAboveIso (fun _ => ℝ) i).symm.preimage_Icc _ _).trans (Icc_prod_eq _ _) + ((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 θ _ => ?_ @@ -225,7 +225,7 @@ theorem torusIntegral_succAbove deriv_circleMap, i.prod_univ_succAbove _, smul_smul, torusMap, circleMap_zero] refine setIntegral_congr measurableSet_Icc fun Θ _ => ?_ simp only [MeasurableEquiv.piFinSuccAbove_symm_apply, i.insertNth_apply_same, - i.insertNth_apply_succAbove, (· ∘ ·)] + i.insertNth_apply_succAbove, (· ∘ ·), Fin.insertNthEquiv, Equiv.coe_fn_mk] congr 2 simp only [funext_iff, i.forall_iff_succAbove, circleMap, Fin.insertNth_apply_same, eq_self_iff_true, Fin.insertNth_apply_succAbove, imp_true_iff, and_self_iff] diff --git a/Mathlib/MeasureTheory/MeasurableSpace/Basic.lean b/Mathlib/MeasureTheory/MeasurableSpace/Basic.lean index 72f27d9b68033..bcafad90b41d4 100644 --- a/Mathlib/MeasureTheory/MeasurableSpace/Basic.lean +++ b/Mathlib/MeasureTheory/MeasurableSpace/Basic.lean @@ -351,6 +351,16 @@ theorem measurable_to_countable' [MeasurableSpace α] [Countable α] [Measurable (h : ∀ x, MeasurableSet (f ⁻¹' {x})) : Measurable f := measurable_to_countable fun y => h (f y) +theorem ENat.measurable_iff {α : Type*} [MeasurableSpace α] {f : α → ℕ∞} : + Measurable f ↔ ∀ n : ℕ, MeasurableSet (f ⁻¹' {↑n}) := by + refine ⟨fun hf n ↦ hf <| measurableSet_singleton _, fun h ↦ measurable_to_countable' fun n ↦ ?_⟩ + cases n with + | top => + rw [← WithTop.none_eq_top, ← compl_range_some, preimage_compl, ← iUnion_singleton_eq_range, + preimage_iUnion] + exact .compl <| .iUnion h + | coe n => exact h n + @[measurability] theorem measurable_unit [MeasurableSpace α] (f : Unit → α) : Measurable f := measurable_from_top @@ -508,7 +518,7 @@ alias Measurable.subtype_val := Measurable.subtype_coe @[measurability] theorem Measurable.subtype_mk {p : β → Prop} {f : α → β} (hf : Measurable f) {h : ∀ x, p (f x)} : Measurable fun x => (⟨f x, h x⟩ : Subtype p) := fun t ⟨s, hs⟩ => - hs.2 ▸ by simp only [← preimage_comp, (· ∘ ·), Subtype.coe_mk, hf hs.1] + hs.2 ▸ by simp only [← preimage_comp, Function.comp_def, Subtype.coe_mk, hf hs.1] @[measurability] protected theorem Measurable.rangeFactorization {f : α → β} (hf : Measurable f) : @@ -661,6 +671,7 @@ theorem Measurable.prod_mk {β γ} {_ : MeasurableSpace β} {_ : MeasurableSpace {g : α → γ} (hf : Measurable f) (hg : Measurable g) : Measurable fun a : α => (f a, g a) := Measurable.prod hf hg +@[fun_prop] theorem Measurable.prod_map [MeasurableSpace δ] {f : α → β} {g : γ → δ} (hf : Measurable f) (hg : Measurable g) : Measurable (Prod.map f g) := (hf.comp measurable_fst).prod_mk (hg.comp measurable_snd) @@ -805,7 +816,7 @@ variable [∀ a, MeasurableSpace (π a)] [MeasurableSpace γ] theorem measurable_pi_iff {g : α → ∀ a, π a} : Measurable g ↔ ∀ a, Measurable fun x => g x a := by simp_rw [measurable_iff_comap_le, MeasurableSpace.pi, MeasurableSpace.comap_iSup, - MeasurableSpace.comap_comp, Function.comp, iSup_le_iff] + MeasurableSpace.comap_comp, Function.comp_def, iSup_le_iff] @[fun_prop, aesop safe 100 apply (rule_sets := [Measurable])] theorem measurable_pi_apply (a : δ) : Measurable fun f : ∀ a, π a => f a := @@ -1081,7 +1092,7 @@ lemma measurable_set_mem (a : α) : Measurable fun s : Set α ↦ a ∈ s := mea @[aesop safe 100 apply (rule_sets := [Measurable])] lemma measurable_set_not_mem (a : α) : Measurable fun s : Set α ↦ a ∉ s := - (measurable_discrete Not).comp <| measurable_set_mem a + (Measurable.of_discrete (f := Not)).comp <| measurable_set_mem a @[aesop safe 100 apply (rule_sets := [Measurable])] lemma measurableSet_mem (a : α) : MeasurableSet {s : Set α | a ∈ s} := @@ -1094,6 +1105,20 @@ lemma measurableSet_not_mem (a : α) : MeasurableSet {s : Set α | a ∉ s} := lemma measurable_compl : Measurable ((·ᶜ) : Set α → Set α) := measurable_set_iff.2 fun _ ↦ measurable_set_not_mem _ +lemma MeasurableSet.setOf_finite [Countable α] : MeasurableSet {s : Set α | s.Finite} := + Countable.setOf_finite.measurableSet + +lemma MeasurableSet.setOf_infinite [Countable α] : MeasurableSet {s : Set α | s.Infinite} := + .setOf_finite |> .compl + +lemma MeasurableSet.sep_finite [Countable α] {S : Set (Set α)} (hS : MeasurableSet S) : + MeasurableSet {s ∈ S | s.Finite} := + hS.inter .setOf_finite + +lemma MeasurableSet.sep_infinite [Countable α] {S : Set (Set α)} (hS : MeasurableSet S) : + MeasurableSet {s ∈ S | s.Infinite} := + hS.inter .setOf_infinite + end Set end Constructions @@ -1204,7 +1229,7 @@ namespace MeasurableSet variable [MeasurableSpace α] instance Subtype.instMembership : Membership α (Subtype (MeasurableSet : Set α → Prop)) := - ⟨fun a s => a ∈ (s : Set α)⟩ + ⟨fun s a => a ∈ (s : Set α)⟩ @[simp] theorem mem_coe (a : α) (s : Subtype (MeasurableSet : Set α → Prop)) : a ∈ (s : Set α) ↔ a ∈ s := diff --git a/Mathlib/MeasureTheory/MeasurableSpace/Card.lean b/Mathlib/MeasureTheory/MeasurableSpace/Card.lean index 879f1bfe0994b..9da03d77e896e 100644 --- a/Mathlib/MeasureTheory/MeasurableSpace/Card.lean +++ b/Mathlib/MeasureTheory/MeasurableSpace/Card.lean @@ -32,7 +32,7 @@ variable {α : Type u} open Cardinal Set -- Porting note: fix universe below, not here -local notation "ω₁" => (WellOrder.α <| Quotient.out <| Cardinal.ord (aleph 1 : Cardinal)) +local notation "ω₁" => (Ordinal.toType <| Cardinal.ord (aleph 1)) namespace MeasurableSpace @@ -42,12 +42,11 @@ countable unions of already constructed sets. We index this construction by an o this will be enough to generate all sets in the sigma-algebra. This construction is very similar to that of the Borel hierarchy. -/ -def generateMeasurableRec (s : Set (Set α)) : (ω₁ : Type u) → Set (Set α) - | i => - let S := ⋃ j : Iio i, generateMeasurableRec s (j.1) - s ∪ {∅} ∪ compl '' S ∪ Set.range fun f : ℕ → S => ⋃ n, (f n).1 - termination_by i => i - decreasing_by exact j.2 +def generateMeasurableRec (s : Set (Set α)) (i : (ω₁ : Type u)) : Set (Set α) := + let S := ⋃ j : Iio i, generateMeasurableRec s (j.1) + s ∪ {∅} ∪ compl '' S ∪ Set.range fun f : ℕ → S => ⋃ n, (f n).1 +termination_by i +decreasing_by exact j.2 theorem self_subset_generateMeasurableRec (s : Set (Set α)) (i : ω₁) : s ⊆ generateMeasurableRec s i := by @@ -78,20 +77,19 @@ theorem generateMeasurableRec_subset (s : Set (Set α)) {i j : ω₁} (h : i ≤ · convert iUnion_mem_generateMeasurableRec fun _ => ⟨i, h, hx⟩ exact (iUnion_const x).symm -/-- At each step of the inductive construction, the cardinality bound `≤ (max #s 2) ^ ℵ₀` holds. --/ +/-- At each step of the inductive construction, the cardinality bound `≤ (max #s 2) ^ ℵ₀` holds. -/ theorem cardinal_generateMeasurableRec_le (s : Set (Set α)) (i : ω₁) : - #(generateMeasurableRec s i) ≤ max #s 2 ^ aleph0.{u} := by - apply (aleph 1).ord.out.wo.wf.induction i + #(generateMeasurableRec s i) ≤ max #s 2 ^ ℵ₀ := by + apply WellFoundedLT.induction i intro i IH have A := aleph0_le_aleph 1 - have B : aleph 1 ≤ max #s 2 ^ aleph0.{u} := + have B : aleph 1 ≤ max #s 2 ^ ℵ₀ := aleph_one_le_continuum.trans (power_le_power_right (le_max_right _ _)) - have C : ℵ₀ ≤ max #s 2 ^ aleph0.{u} := A.trans B - have J : #(⋃ j : Iio i, generateMeasurableRec s j.1) ≤ max #s 2 ^ aleph0.{u} := by + have C : ℵ₀ ≤ max #s 2 ^ ℵ₀ := A.trans B + have J : #(⋃ j : Iio i, generateMeasurableRec s j.1) ≤ max #s 2 ^ ℵ₀ := by refine (mk_iUnion_le _).trans ?_ have D : ⨆ j : Iio i, #(generateMeasurableRec s j) ≤ _ := ciSup_le' fun ⟨j, hj⟩ => IH j hj - apply (mul_le_mul' ((mk_subtype_le _).trans (aleph 1).mk_ord_out.le) D).trans + apply (mul_le_mul' ((mk_subtype_le _).trans (aleph 1).mk_ord_toType.le) D).trans rw [mul_eq_max A C] exact max_le B le_rfl rw [generateMeasurableRec] @@ -107,20 +105,21 @@ theorem cardinal_generateMeasurableRec_le (s : Set (Set α)) (i : ω₁) : /-- `generateMeasurableRec s` generates precisely the smallest sigma-algebra containing `s`. -/ theorem generateMeasurable_eq_rec (s : Set (Set α)) : { t | GenerateMeasurable s t } = - ⋃ (i : (Quotient.out (aleph 1).ord).α), generateMeasurableRec s i := by + ⋃ (i : (aleph 1).ord.toType), generateMeasurableRec s i := by ext t; refine ⟨fun ht => ?_, fun ht => ?_⟩ · inhabit ω₁ - induction' ht with u hu u _ IH f _ IH - · exact mem_iUnion.2 ⟨default, self_subset_generateMeasurableRec s _ hu⟩ - · exact mem_iUnion.2 ⟨default, empty_mem_generateMeasurableRec s _⟩ - · rcases mem_iUnion.1 IH with ⟨i, hi⟩ + induction ht with + | basic u hu => exact mem_iUnion.2 ⟨default, self_subset_generateMeasurableRec s _ hu⟩ + | empty => exact mem_iUnion.2 ⟨default, empty_mem_generateMeasurableRec s _⟩ + | compl _ _ IH => + rcases mem_iUnion.1 IH with ⟨i, hi⟩ obtain ⟨j, hj⟩ := exists_gt i exact mem_iUnion.2 ⟨j, compl_mem_generateMeasurableRec hj hi⟩ - · have : ∀ n, ∃ i, f n ∈ generateMeasurableRec s i := fun n => by simpa using IH n + | iUnion f _ IH => + have : ∀ n, ∃ i, f n ∈ generateMeasurableRec s i := fun n => by simpa using IH n choose I hI using this - have : IsWellOrder (ω₁ : Type u) (· < ·) := isWellOrder_out_lt _ - refine mem_iUnion.2 - ⟨Ordinal.enum (· < ·) (Ordinal.lsub fun n => Ordinal.typein.{u} (· < ·) (I n)) ?_, + refine mem_iUnion.2 ⟨Ordinal.enum (α := ω₁) (· < ·) + ⟨Ordinal.lsub fun n => Ordinal.typein.{u} (α := ω₁) (· < ·) (I n), ?_⟩, iUnion_mem_generateMeasurableRec fun n => ⟨I n, ?_, hI n⟩⟩ · rw [Ordinal.type_lt] refine Ordinal.lsub_lt_ord_lift ?_ fun i => Ordinal.typein_lt_self _ @@ -130,7 +129,7 @@ theorem generateMeasurable_eq_rec (s : Set (Set α)) : apply Ordinal.lt_lsub fun n : ℕ => _ · rcases ht with ⟨t, ⟨i, rfl⟩, hx⟩ revert t - apply (aleph 1).ord.out.wo.wf.induction i + apply WellFoundedLT.induction i intro j H t ht unfold generateMeasurableRec at ht rcases ht with (((h | (rfl : t = ∅)) | ⟨u, ⟨-, ⟨⟨k, hk⟩, rfl⟩, hu⟩, rfl⟩) | ⟨f, rfl⟩) @@ -144,10 +143,10 @@ theorem generateMeasurable_eq_rec (s : Set (Set α)) : /-- If a sigma-algebra is generated by a set of sets `s`, then the sigma-algebra has cardinality at most `(max #s 2) ^ ℵ₀`. -/ theorem cardinal_generateMeasurable_le (s : Set (Set α)) : - #{ t | GenerateMeasurable s t } ≤ max #s 2 ^ aleph0.{u} := by + #{ t | GenerateMeasurable s t } ≤ max #s 2 ^ ℵ₀ := by rw [generateMeasurable_eq_rec] apply (mk_iUnion_le _).trans - rw [(aleph 1).mk_ord_out] + rw [(aleph 1).mk_ord_toType] refine le_trans (mul_le_mul' aleph_one_le_continuum (ciSup_le' fun i => cardinal_generateMeasurableRec_le s i)) ?_ refine (mul_le_max_of_aleph0_le_left aleph0_le_continuum).trans (max_le ?_ le_rfl) @@ -156,7 +155,7 @@ theorem cardinal_generateMeasurable_le (s : Set (Set α)) : /-- If a sigma-algebra is generated by a set of sets `s`, then the sigma algebra has cardinality at most `(max #s 2) ^ ℵ₀`. -/ theorem cardinalMeasurableSet_le (s : Set (Set α)) : - #{ t | @MeasurableSet α (generateFrom s) t } ≤ max #s 2 ^ aleph0.{u} := + #{ t | @MeasurableSet α (generateFrom s) t } ≤ max #s 2 ^ ℵ₀ := cardinal_generateMeasurable_le s /-- If a sigma-algebra is generated by a set of sets `s` with cardinality at most the continuum, diff --git a/Mathlib/MeasureTheory/MeasurableSpace/CountablyGenerated.lean b/Mathlib/MeasureTheory/MeasurableSpace/CountablyGenerated.lean index f2a385de89049..19be50fbff257 100644 --- a/Mathlib/MeasureTheory/MeasurableSpace/CountablyGenerated.lean +++ b/Mathlib/MeasureTheory/MeasurableSpace/CountablyGenerated.lean @@ -208,6 +208,17 @@ instance (priority := 100) separatesPoints_of_measurableSingletonClass [Measurab simp_rw [mem_singleton_iff, forall_true_left] at h exact h.symm +instance (priority := 50) MeasurableSingletonClass.of_separatesPoints [MeasurableSpace α] + [Countable α] [SeparatesPoints α] : MeasurableSingletonClass α where + measurableSet_singleton x := by + choose s hsm hxs hys using fun y (h : x ≠ y) ↦ exists_measurableSet_of_ne h + convert MeasurableSet.iInter fun y ↦ .iInter fun h ↦ hsm y h + ext y + rcases eq_or_ne x y with rfl | h + · simpa + · simp only [mem_singleton_iff, h.symm, false_iff, mem_iInter, not_forall] + exact ⟨y, h, hys y h⟩ + instance hasCountableSeparatingOn_of_countablySeparated_subtype [MeasurableSpace α] {s : Set α} [h : CountablySeparated s] : HasCountableSeparatingOn _ MeasurableSet s := CountablySeparated.subtype_iff.mp h @@ -418,7 +429,7 @@ end MeasurableMemPartition variable [m : MeasurableSpace α] [h : CountablyGenerated α] /-- For each `n : ℕ`, `countablePartition α n` is a partition of the space in at most -`2^n` sets. Each partition is finer than the preceeding one. The measurable space generated by +`2^n` sets. Each partition is finer than the preceding one. The measurable space generated by the union of all those partitions is the measurable space on `α`. -/ def countablePartition (α : Type*) [MeasurableSpace α] [CountablyGenerated α] : ℕ → Set (Set α) := memPartition (enumerateCountable countable_countableGeneratingSet ∅) diff --git a/Mathlib/MeasureTheory/MeasurableSpace/Defs.lean b/Mathlib/MeasureTheory/MeasurableSpace/Defs.lean index 24be3674a76da..6345012319658 100644 --- a/Mathlib/MeasureTheory/MeasurableSpace/Defs.lean +++ b/Mathlib/MeasureTheory/MeasurableSpace/Defs.lean @@ -517,7 +517,7 @@ end MeasurableFunctions /-- A typeclass mixin for `MeasurableSpace`s such that all sets are measurable. -/ class DiscreteMeasurableSpace (α : Type*) [MeasurableSpace α] : Prop where - /-- Do not use this. Use `measurableSet_discrete` instead. -/ + /-- Do not use this. Use `MeasurableSet.of_discrete` instead. -/ forall_measurableSet : ∀ s : Set α, MeasurableSet s instance : @DiscreteMeasurableSpace α ⊤ := @@ -529,19 +529,24 @@ instance (priority := 100) MeasurableSingletonClass.toDiscreteMeasurableSpace [M forall_measurableSet _ := (Set.to_countable _).measurableSet section DiscreteMeasurableSpace -variable [MeasurableSpace α] [MeasurableSpace β] [DiscreteMeasurableSpace α] +variable [MeasurableSpace α] [MeasurableSpace β] [DiscreteMeasurableSpace α] {s : Set α} {f : α → β} -@[measurability] lemma measurableSet_discrete (s : Set α) : MeasurableSet s := +@[measurability] lemma MeasurableSet.of_discrete : MeasurableSet s := DiscreteMeasurableSpace.forall_measurableSet _ -@[measurability] -lemma measurable_discrete (f : α → β) : Measurable f := fun _ _ ↦ measurableSet_discrete _ +@[measurability] 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 + +@[deprecated Measurable.of_discrete (since := "2024-08-25")] +lemma measurable_discrete (f : α → β) : Measurable f := .of_discrete /-- Warning: Creates a typeclass loop with `MeasurableSingletonClass.toDiscreteMeasurableSpace`. To be monitored. -/ -- See note [lower instance priority] instance (priority := 100) DiscreteMeasurableSpace.toMeasurableSingletonClass : MeasurableSingletonClass α where - measurableSet_singleton _ := measurableSet_discrete _ + measurableSet_singleton _ := .of_discrete end DiscreteMeasurableSpace diff --git a/Mathlib/MeasureTheory/MeasurableSpace/Embedding.lean b/Mathlib/MeasureTheory/MeasurableSpace/Embedding.lean index ec89ef7faa51b..539df69ae463e 100644 --- a/Mathlib/MeasureTheory/MeasurableSpace/Embedding.lean +++ b/Mathlib/MeasureTheory/MeasurableSpace/Embedding.lean @@ -488,17 +488,17 @@ def finTwoArrow : (Fin 2 → α) ≃ᵐ α × α := piFinTwo fun _ => α /-- Measurable equivalence between `Π j : Fin (n + 1), α j` and -`α i × Π j : Fin n, α (Fin.succAbove i j)`. -/ +`α i × Π j : Fin n, α (Fin.succAbove i j)`. + +Measurable version of `Fin.insertNthEquiv`. -/ @[simps! (config := .asFn)] def piFinSuccAbove {n : ℕ} (α : Fin (n + 1) → Type*) [∀ i, MeasurableSpace (α i)] (i : Fin (n + 1)) : (∀ j, α j) ≃ᵐ α i × ∀ j, α (i.succAbove j) where - toEquiv := .piFinSuccAbove α i + toEquiv := (Fin.insertNthEquiv α i).symm measurable_toFun := (measurable_pi_apply i).prod_mk <| measurable_pi_iff.2 fun j => measurable_pi_apply _ measurable_invFun := measurable_pi_iff.2 <| i.forall_iff_succAbove.2 - ⟨by simp only [piFinSuccAbove_symm_apply, Fin.insertNth_apply_same, measurable_fst], - fun j => by simpa only [piFinSuccAbove_symm_apply, Fin.insertNth_apply_succAbove] - using (measurable_pi_apply _).comp measurable_snd⟩ + ⟨by simp [measurable_fst], fun j => by simpa using (measurable_pi_apply _).comp measurable_snd⟩ variable (π) diff --git a/Mathlib/MeasureTheory/MeasurableSpace/Instances.lean b/Mathlib/MeasureTheory/MeasurableSpace/Instances.lean index 2de7f4465974c..a760b97654d0d 100644 --- a/Mathlib/MeasureTheory/MeasurableSpace/Instances.lean +++ b/Mathlib/MeasureTheory/MeasurableSpace/Instances.lean @@ -25,6 +25,8 @@ instance Prop.instMeasurableSpace : MeasurableSpace Prop := ⊤ instance Nat.instMeasurableSpace : MeasurableSpace ℕ := ⊤ +instance ENat.instMeasurableSpace : MeasurableSpace ℕ∞ := ⊤ + instance Fin.instMeasurableSpace (n : ℕ) : MeasurableSpace (Fin n) := ⊤ instance ZMod.instMeasurableSpace (n : ℕ) : MeasurableSpace (ZMod n) := ⊤ @@ -53,6 +55,10 @@ instance Prop.instMeasurableSingletonClass : MeasurableSingletonClass Prop := instance Nat.instMeasurableSingletonClass : MeasurableSingletonClass ℕ := ⟨fun _ => trivial⟩ +instance ENat.instDiscreteMeasurableSpace : DiscreteMeasurableSpace ℕ∞ := ⟨fun _ ↦ trivial⟩ + +instance ENat.instMeasurableSingletonClass : MeasurableSingletonClass ℕ∞ := inferInstance + instance Fin.instMeasurableSingletonClass (n : ℕ) : MeasurableSingletonClass (Fin n) := ⟨fun _ => trivial⟩ diff --git a/Mathlib/MeasureTheory/MeasurableSpace/NCard.lean b/Mathlib/MeasureTheory/MeasurableSpace/NCard.lean new file mode 100644 index 0000000000000..4385de7626560 --- /dev/null +++ b/Mathlib/MeasureTheory/MeasurableSpace/NCard.lean @@ -0,0 +1,27 @@ +/- +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.MeasureTheory.MeasurableSpace.Basic +import Mathlib.Data.Set.Card + +/-! +# Measurability of `Set.encard` and `Set.ncard` + +In this file we prove that `Set.encard` and `Set.ncard` are measurable functions, +provided that the ambient space is countable. +-/ + +open Set + +variable {α : Type*} [Countable α] + +@[measurability] +theorem measurable_encard : Measurable (Set.encard : Set α → ℕ∞) := + ENat.measurable_iff.2 fun _n ↦ Countable.measurableSet <| Countable.setOf_finite.mono fun _s hs ↦ + finite_of_encard_eq_coe hs + +@[measurability] +theorem measurable_ncard : Measurable (Set.ncard : Set α → ℕ) := + Measurable.of_discrete.comp measurable_encard diff --git a/Mathlib/MeasureTheory/Measure/AEDisjoint.lean b/Mathlib/MeasureTheory/Measure/AEDisjoint.lean index 4e7005ee1da8e..7998e50fd3efc 100644 --- a/Mathlib/MeasureTheory/Measure/AEDisjoint.lean +++ b/Mathlib/MeasureTheory/Measure/AEDisjoint.lean @@ -117,7 +117,7 @@ set `u`. -/ theorem exists_disjoint_diff (h : AEDisjoint μ s t) : ∃ u, MeasurableSet u ∧ μ u = 0 ∧ Disjoint (s \ u) t := ⟨toMeasurable μ (s ∩ t), measurableSet_toMeasurable _ _, (measure_toMeasurable _).trans h, - disjoint_sdiff_self_left.mono_left fun x hx => by + disjoint_sdiff_self_left.mono_left (b := s \ t) fun x hx => by simpa using ⟨hx.1, fun hxt => hx.2 <| subset_toMeasurable _ _ ⟨hx.1, hxt⟩⟩⟩ theorem of_null_right (h : μ t = 0) : AEDisjoint μ s t := diff --git a/Mathlib/MeasureTheory/Measure/Complex.lean b/Mathlib/MeasureTheory/Measure/Complex.lean index ccb2008885c00..decf1c54caa15 100644 --- a/Mathlib/MeasureTheory/Measure/Complex.lean +++ b/Mathlib/MeasureTheory/Measure/Complex.lean @@ -54,7 +54,7 @@ def re : ComplexMeasure α →ₗ[ℝ] SignedMeasure α := def im : ComplexMeasure α →ₗ[ℝ] SignedMeasure α := mapRangeₗ Complex.imCLM Complex.continuous_im -/-- Given `s` and `t` signed measures, `s + it` is a complex measure-/ +/-- Given `s` and `t` signed measures, `s + it` is a complex measure -/ @[simps!] def _root_.MeasureTheory.SignedMeasure.toComplexMeasure (s t : SignedMeasure α) : ComplexMeasure α where diff --git a/Mathlib/MeasureTheory/Measure/ContinuousPreimage.lean b/Mathlib/MeasureTheory/Measure/ContinuousPreimage.lean index e6124f9f8875b..b98c2b2b39069 100644 --- a/Mathlib/MeasureTheory/Measure/ContinuousPreimage.lean +++ b/Mathlib/MeasureTheory/Measure/ContinuousPreimage.lean @@ -79,12 +79,12 @@ theorem tendsto_measure_symmDiff_preimage_nhds_zero obtain ⟨K, hKg, hKco, hKcl, hKμ⟩ : ∃ K, MapsTo g K s ∧ IsCompact K ∧ IsClosed K ∧ μ (g ⁻¹' s \ K) < ε / 2 := (hg.measurable hso.measurableSet).exists_isCompact_isClosed_diff_lt hνs' <| by simp [hε.ne'] - have hKm : MeasurableSet K := hKcl.measurableSet + have hKm : NullMeasurableSet K μ := hKcl.nullMeasurableSet -- Take `a` such that `f a` is measure preserving and maps `K` to `s`. -- This is possible, because `K` is a compact set and `s` is an open set. filter_upwards [hf, ContinuousMap.tendsto_nhds_compactOpen.mp hfg K hKco s hso hKg] with a hfa ha -- Then each of the sets `g ⁻¹' s ∆ K = g ⁻¹' s \ K` and `f a ⁻¹' s ∆ K = f a ⁻¹' s \ K` - -- have measure at most `ε / 2`, thus `f a ⁻¹' s ∆ g ⁻¹' s` has measure at most `ε`. + -- have measure at most `ε / 2`, thus `f a ⁻¹' s ∆ g ⁻¹' s` has measure at most `ε`. rw [← ENNReal.add_halves ε] refine (measure_symmDiff_le _ K _).trans ?_ rw [symmDiff_of_ge ha.subset_preimage, symmDiff_of_le hKg.subset_preimage] diff --git a/Mathlib/MeasureTheory/Measure/Count.lean b/Mathlib/MeasureTheory/Measure/Count.lean index 6b263eb05db16..0383da666916a 100644 --- a/Mathlib/MeasureTheory/Measure/Count.lean +++ b/Mathlib/MeasureTheory/Measure/Count.lean @@ -26,6 +26,8 @@ namespace MeasureTheory.Measure def count : Measure α := sum dirac +@[simp] lemma count_ne_zero'' [Nonempty α] : (count : Measure α) ≠ 0 := by simp [count] + theorem le_count_apply : ∑' _ : s, (1 : ℝ≥0∞) ≤ count s := calc (∑' _ : s, 1 : ℝ≥0∞) = ∑' i, indicator s 1 i := tsum_subtype s 1 @@ -157,9 +159,10 @@ theorem count_injective_image [MeasurableSingletonClass α] [MeasurableSingleton instance count.isFiniteMeasure [Finite α] : IsFiniteMeasure (Measure.count : Measure α) := - ⟨by - cases nonempty_fintype α - simpa [Measure.count_apply, tsum_fintype] using (ENNReal.natCast_ne_top _).lt_top⟩ + ⟨by cases nonempty_fintype α; simp [Measure.count_apply, tsum_fintype]⟩ + +@[simp] lemma count_univ [Fintype α] : count (univ : Set α) = Fintype.card α := by + rw [count_apply .univ]; exact (tsum_univ 1).trans (by simp [tsum_fintype]) end Measure diff --git a/Mathlib/MeasureTheory/Measure/Dirac.lean b/Mathlib/MeasureTheory/Measure/Dirac.lean index ad6623a9ff812..29e9d534230ce 100644 --- a/Mathlib/MeasureTheory/Measure/Dirac.lean +++ b/Mathlib/MeasureTheory/Measure/Dirac.lean @@ -54,6 +54,9 @@ theorem dirac_apply [MeasurableSingletonClass α] (a : α) (s : Set α) : dirac a s ≤ dirac a {a}ᶜ := measure_mono (subset_compl_comm.1 <| singleton_subset_iff.2 h) _ = 0 := by simp [dirac_apply' _ (measurableSet_singleton _).compl] +@[simp] lemma dirac_ne_zero : dirac a ≠ 0 := + fun h ↦ by simpa [h] using dirac_apply_of_mem (mem_univ a) + theorem map_dirac {f : α → β} (hf : Measurable f) (a : α) : (dirac a).map f = dirac (f a) := by classical exact ext fun s hs => by simp [hs, map_apply hf hs, hf hs, indicator_apply] diff --git a/Mathlib/MeasureTheory/Measure/FiniteMeasureProd.lean b/Mathlib/MeasureTheory/Measure/FiniteMeasureProd.lean index 5ec34e572fd68..97ffeece7c11c 100644 --- a/Mathlib/MeasureTheory/Measure/FiniteMeasureProd.lean +++ b/Mathlib/MeasureTheory/Measure/FiniteMeasureProd.lean @@ -71,7 +71,7 @@ lemma prod_prod (s : Set α) (t : Set β) : μ.prod ν (s ×ˢ t) = μ s * ν t @[simp] lemma map_snd_prod : (μ.prod ν).map Prod.snd = μ univ • ν := by ext; simp lemma map_prod_map {α' : Type*} [MeasurableSpace α'] {β' : Type*} [MeasurableSpace β'] - {f : α → α'} {g : β → β'} (f_mble : Measurable f) (g_mble : Measurable g) : + {f : α → α'} {g : β → β'} (f_mble : Measurable f) (g_mble : Measurable g) : (μ.map f).prod (ν.map g) = (μ.prod ν).map (Prod.map f g) := by apply Subtype.ext simp only [val_eq_toMeasure, toMeasure_prod, toMeasure_map] diff --git a/Mathlib/MeasureTheory/Measure/Haar/Basic.lean b/Mathlib/MeasureTheory/Measure/Haar/Basic.lean index 58a67caecf0c9..b8bf558a35d4e 100644 --- a/Mathlib/MeasureTheory/Measure/Haar/Basic.lean +++ b/Mathlib/MeasureTheory/Measure/Haar/Basic.lean @@ -265,7 +265,7 @@ theorem is_left_invariant_index {K : Set G} (hK : IsCompact K) (g : G) {V : Set @[to_additive add_prehaar_le_addIndex] theorem prehaar_le_index (K₀ : PositiveCompacts G) {U : Set G} (K : Compacts G) (hU : (interior U).Nonempty) : prehaar (K₀ : Set G) U K ≤ index (K : Set G) K₀ := by - unfold prehaar; rw [div_le_iff] <;> norm_cast + unfold prehaar; rw [div_le_iff₀] <;> norm_cast · apply le_index_mul K₀ K hU · exact index_pos K₀ hU diff --git a/Mathlib/MeasureTheory/Measure/Haar/Disintegration.lean b/Mathlib/MeasureTheory/Measure/Haar/Disintegration.lean index 1a085463ecac8..c3c47f6abc70a 100644 --- a/Mathlib/MeasureTheory/Measure/Haar/Disintegration.lean +++ b/Mathlib/MeasureTheory/Measure/Haar/Disintegration.lean @@ -36,6 +36,10 @@ variable {𝕜 E F : Type*} variable [LocallyCompactSpace E] variable (L μ ν) +-- Instances with keys using `Submodule` +instance (T : Submodule 𝕜 E) : BorelSpace T := Subtype.borelSpace _ +instance (T : Submodule 𝕜 E) : OpensMeasurableSpace T := Subtype.opensMeasurableSpace _ + /-- The image of an additive Haar measure under a surjective linear map is proportional to a given additive Haar measure. The proportionality factor will be infinite if the linear map has a nontrivial kernel. -/ @@ -46,7 +50,6 @@ theorem LinearMap.exists_map_addHaar_eq_smul_addHaar' (h : Function.Surjective L is also true for linear equivalences, as they map Haar measure to Haar measure. The general case follows from these two and linear algebra, as `L` can be interpreted as the composition of the projection `P` on a complement `T` to its kernel `S`, together with a linear equivalence. -/ - have : ProperSpace E := .of_locallyCompactSpace 𝕜 have : FiniteDimensional 𝕜 E := .of_locallyCompactSpace 𝕜 have : ProperSpace F := by rcases subsingleton_or_nontrivial E with hE|hE @@ -97,7 +100,8 @@ theorem LinearMap.exists_map_addHaar_eq_smul_addHaar' (h : Function.Surjective L isAddLeftInvariant_eq_smul _ _⟩ simpa only [ne_eq, ENNReal.coe_eq_zero] using (addHaarScalarFactor_pos_of_isAddHaarMeasure (μT.map L') ν).ne' - refine ⟨c₀ * c₁, by simp [pos_iff_ne_zero, c₀_pos, c₁_pos], ENNReal.mul_lt_top c₀_fin c₁_fin, ?_⟩ + refine ⟨c₀ * c₁, by simp [pos_iff_ne_zero, c₀_pos, c₁_pos], + ENNReal.mul_lt_top c₀_fin.lt_top c₁_fin.lt_top, ?_⟩ simp only [I, h₀, Measure.map_smul, J, smul_smul, h₁] rw [mul_assoc, mul_comm _ c₁, ← mul_assoc] diff --git a/Mathlib/MeasureTheory/Measure/Haar/NormedSpace.lean b/Mathlib/MeasureTheory/Measure/Haar/NormedSpace.lean index 23979e07b5cf8..29af339ad2552 100644 --- a/Mathlib/MeasureTheory/Measure/Haar/NormedSpace.lean +++ b/Mathlib/MeasureTheory/Measure/Haar/NormedSpace.lean @@ -30,23 +30,19 @@ example {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] [Nontrivial E] [F [MeasurableSpace E] [BorelSpace E] (μ : Measure E) [IsAddHaarMeasure μ] : NoAtoms μ := by infer_instance -section ContinuousLinearEquiv +section LinearEquiv variable {𝕜 G H : Type*} [MeasurableSpace G] [MeasurableSpace H] [NontriviallyNormedField 𝕜] [TopologicalSpace G] [TopologicalSpace H] [AddCommGroup G] [AddCommGroup H] [TopologicalAddGroup G] [TopologicalAddGroup H] [Module 𝕜 G] [Module 𝕜 H] (μ : Measure G) - [IsAddHaarMeasure μ] [BorelSpace G] [BorelSpace H] [T2Space H] - -instance MapContinuousLinearEquiv.isAddHaarMeasure (e : G ≃L[𝕜] H) : IsAddHaarMeasure (μ.map e) := - e.toAddEquiv.isAddHaarMeasure_map _ e.continuous e.symm.continuous - -variable [CompleteSpace 𝕜] [T2Space G] [FiniteDimensional 𝕜 G] [ContinuousSMul 𝕜 G] - [ContinuousSMul 𝕜 H] + [IsAddHaarMeasure μ] [BorelSpace G] [BorelSpace H] + [CompleteSpace 𝕜] [T2Space G] [FiniteDimensional 𝕜 G] [ContinuousSMul 𝕜 G] + [ContinuousSMul 𝕜 H] [T2Space H] instance MapLinearEquiv.isAddHaarMeasure (e : G ≃ₗ[𝕜] H) : IsAddHaarMeasure (μ.map e) := - MapContinuousLinearEquiv.isAddHaarMeasure _ e.toContinuousLinearEquiv + e.toContinuousLinearEquiv.isAddHaarMeasure_map _ -end ContinuousLinearEquiv +end LinearEquiv variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] [MeasurableSpace E] [BorelSpace E] [FiniteDimensional ℝ E] (μ : Measure E) [IsAddHaarMeasure μ] {F : Type*} [NormedAddCommGroup F] diff --git a/Mathlib/MeasureTheory/Measure/Haar/Quotient.lean b/Mathlib/MeasureTheory/Measure/Haar/Quotient.lean index a63821bbd70b0..4882bfa945404 100644 --- a/Mathlib/MeasureTheory/Measure/Haar/Quotient.lean +++ b/Mathlib/MeasureTheory/Measure/Haar/Quotient.lean @@ -379,7 +379,7 @@ attribute [-instance] Quotient.instMeasurableSpace integral of a function `f` on `G` with respect to a right-invariant measure `μ` is equal to the integral over the quotient `G ⧸ Γ` of the automorphization of `f`. -/ @[to_additive "This is a simple version of the **Unfolding Trick**: Given a subgroup `Γ` of an - additive group `G`, the integral of a function `f` on `G` with respect to a right-invariant + additive group `G`, the integral of a function `f` on `G` with respect to a right-invariant measure `μ` is equal to the integral over the quotient `G ⧸ Γ` of the automorphization of `f`."] lemma QuotientGroup.integral_eq_integral_automorphize {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] [μ.IsMulRightInvariant] {f : G → E} diff --git a/Mathlib/MeasureTheory/Measure/Haar/Unique.lean b/Mathlib/MeasureTheory/Measure/Haar/Unique.lean index 51a8903fe9a11..0b75436b65433 100644 --- a/Mathlib/MeasureTheory/Measure/Haar/Unique.lean +++ b/Mathlib/MeasureTheory/Measure/Haar/Unique.lean @@ -378,7 +378,7 @@ lemma haarScalarFactor_eq_mul (μ' μ ν : Measure G) · exact g_cont.integrable_of_hasCompactSupport g_comp change (haarScalarFactor μ' ν : ℝ) * ∫ (x : G), g x ∂ν = (haarScalarFactor μ' μ * haarScalarFactor μ ν : ℝ≥0) * ∫ (x : G), g x ∂ν at Z - simpa only [mul_eq_mul_right_iff (M₀ := ℝ), int_g_pos.ne', or_false, NNReal.eq_iff] using Z + simpa only [mul_eq_mul_right_iff (M₀ := ℝ), int_g_pos.ne', or_false, ← NNReal.eq_iff] using Z /-- The scalar factor between two left-invariant measures is non-zero when both measures are positive on open sets. -/ @@ -573,7 +573,8 @@ lemma measure_isMulInvariant_eq_smul_of_isCompact_closure_of_innerRegularCompact exact t_comp.closure_of_subset diff_subset have B : μ' t = ν t := measure_preimage_isMulLeftInvariant_eq_smul_of_hasCompactSupport _ _ f_cont f_comp - rwa [measure_diff st hs, measure_diff st hs, ← B, ENNReal.sub_le_sub_iff_left] at A + rwa [measure_diff st hs.nullMeasurableSet, measure_diff st hs.nullMeasurableSet, ← B, + ENNReal.sub_le_sub_iff_left] at A · exact measure_mono st · exact t_comp.measure_lt_top.ne · exact ((measure_mono st).trans_lt t_comp.measure_lt_top).ne @@ -908,6 +909,32 @@ theorem absolutelyContinuous_isHaarMeasure [LocallyCompactSpace G] rw [haarMeasure_unique μ K, h, smul_smul] exact AbsolutelyContinuous.smul (Eq.absolutelyContinuous rfl) _ +/-- A continuous surjective monoid homomorphism of topological groups with compact codomain +is measure preserving, provided that the Haar measures on the domain and on the codomain +have the same total mass. +-/ +@[to_additive + "A continuous surjective additive monoid homomorphism of topological groups with compact codomain +is measure preserving, provided that the Haar measures on the domain and on the codomain +have the same total mass."] +theorem _root_.MonoidHom.measurePreserving + {H : Type*} [Group H] [TopologicalSpace H] [TopologicalGroup H] [CompactSpace H] + [MeasurableSpace H] [BorelSpace H] + {μ : Measure G} [IsHaarMeasure μ] {ν : Measure H} [IsHaarMeasure ν] + {f : G →* H} (hcont : Continuous f) (hsurj : Surjective f) (huniv : μ univ = ν univ) : + MeasurePreserving f μ ν where + measurable := hcont.measurable + map_eq := by + have : IsFiniteMeasure μ := ⟨by rw [huniv]; apply measure_lt_top⟩ + have : (μ.map f).IsHaarMeasure := isHaarMeasure_map_of_isFiniteMeasure μ f hcont hsurj + set C : ℝ≥0 := haarScalarFactor (μ.map f) ν + have hC : μ.map f = C • ν := isMulLeftInvariant_eq_smul_of_innerRegular _ _ + suffices C = 1 by rwa [this, one_smul] at hC + have : C * ν univ = 1 * ν univ := by + rw [one_mul, ← smul_eq_mul, ← ENNReal.smul_def, ← smul_apply, ← hC, + map_apply hcont.measurable .univ, preimage_univ, huniv] + rwa [ENNReal.mul_eq_mul_right (NeZero.ne _) (measure_ne_top _ _), ENNReal.coe_eq_one] at this + end Group section CommGroup @@ -968,22 +995,8 @@ instance (priority := 100) IsHaarMeasure.isInvInvariant_of_innerRegular @[to_additive] theorem measurePreserving_zpow [CompactSpace G] [RootableBy G ℤ] {n : ℤ} (hn : n ≠ 0) : MeasurePreserving (fun g : G => g ^ n) μ μ := - { measurable := (continuous_zpow n).measurable - map_eq := by - let f := @zpowGroupHom G _ n - have hf : Continuous f := continuous_zpow n - have : (μ.map f).IsHaarMeasure := - isHaarMeasure_map_of_isFiniteMeasure μ f hf (RootableBy.surjective_pow G ℤ hn) - let C : ℝ≥0∞ := haarScalarFactor (μ.map f) μ - have hC : μ.map f = C • μ := isMulLeftInvariant_eq_smul_of_innerRegular _ _ - suffices C = 1 by rwa [this, one_smul] at hC - have h_univ : (μ.map f) univ = μ univ := by - rw [map_apply_of_aemeasurable hf.measurable.aemeasurable MeasurableSet.univ, - preimage_univ] - have hμ₀ : μ univ ≠ 0 := IsOpenPosMeasure.open_pos univ isOpen_univ univ_nonempty - have hμ₁ : μ univ ≠ ∞ := CompactSpace.isFiniteMeasure.measure_univ_lt_top.ne - rwa [hC, smul_apply, Algebra.id.smul_eq_mul, mul_comm, ← ENNReal.eq_div_iff hμ₀ hμ₁, - ENNReal.div_self hμ₀ hμ₁] at h_univ } + (zpowGroupHom n).measurePreserving (continuous_zpow n) + (RootableBy.surjective_pow G ℤ hn) rfl @[to_additive] theorem MeasurePreserving.zpow [CompactSpace G] [RootableBy G ℤ] diff --git a/Mathlib/MeasureTheory/Measure/Hausdorff.lean b/Mathlib/MeasureTheory/Measure/Hausdorff.lean index 2bbc642378587..1eb27758afc84 100644 --- a/Mathlib/MeasureTheory/Measure/Hausdorff.lean +++ b/Mathlib/MeasureTheory/Measure/Hausdorff.lean @@ -732,7 +732,7 @@ variable {K : ℝ≥0} {f : X → Y} by the factor of `K ^ d`. -/ theorem hausdorffMeasure_image_le (h : LipschitzWith K f) {d : ℝ} (hd : 0 ≤ d) (s : Set X) : μH[d] (f '' s) ≤ (K : ℝ≥0∞) ^ d * μH[d] s := - (h.lipschitzOnWith s).hausdorffMeasure_image_le hd + h.lipschitzOnWith.hausdorffMeasure_image_le hd end LipschitzWith diff --git a/Mathlib/MeasureTheory/Measure/Lebesgue/EqHaar.lean b/Mathlib/MeasureTheory/Measure/Lebesgue/EqHaar.lean index 7411012c4e1c6..fb8dff12af177 100644 --- a/Mathlib/MeasureTheory/Measure/Lebesgue/EqHaar.lean +++ b/Mathlib/MeasureTheory/Measure/Lebesgue/EqHaar.lean @@ -492,7 +492,8 @@ theorem addHaar_sphere_of_ne_zero (x : E) {r : ℝ} (hr : r ≠ 0) : μ (sphere rcases hr.lt_or_lt with (h | h) · simp only [empty_diff, measure_empty, ← closedBall_diff_ball, closedBall_eq_empty.2 h] · rw [← closedBall_diff_ball, - measure_diff ball_subset_closedBall measurableSet_ball measure_ball_lt_top.ne, + measure_diff ball_subset_closedBall measurableSet_ball.nullMeasurableSet + measure_ball_lt_top.ne, addHaar_ball_of_pos μ _ h, addHaar_closedBall μ _ h.le, tsub_self] theorem addHaar_sphere [Nontrivial E] (x : E) (r : ℝ) : μ (sphere x r) = 0 := by @@ -696,7 +697,8 @@ theorem tendsto_addHaar_inter_smul_zero_of_density_zero (s : Set E) (x : E) (𝓝 (μ (⋂ n : ℕ, t \ closedBall 0 n))) := by have N : ∃ n : ℕ, μ (t \ closedBall 0 n) ≠ ∞ := ⟨0, ((measure_mono diff_subset).trans_lt h''t.lt_top).ne⟩ - refine tendsto_measure_iInter (fun n ↦ ht.diff measurableSet_closedBall) (fun m n hmn ↦ ?_) N + refine tendsto_measure_iInter (fun n ↦ (ht.diff measurableSet_closedBall).nullMeasurableSet) + (fun m n hmn ↦ ?_) N exact diff_subset_diff Subset.rfl (closedBall_subset_closedBall (Nat.cast_le.2 hmn)) have : ⋂ n : ℕ, t \ closedBall 0 n = ∅ := by simp_rw [diff_eq, ← inter_iInter, iInter_eq_compl_iUnion_compl, compl_compl, diff --git a/Mathlib/MeasureTheory/Measure/Lebesgue/Integral.lean b/Mathlib/MeasureTheory/Measure/Lebesgue/Integral.lean index f4d39f02991d6..15ee5ceb0977a 100644 --- a/Mathlib/MeasureTheory/Measure/Lebesgue/Integral.lean +++ b/Mathlib/MeasureTheory/Measure/Lebesgue/Integral.lean @@ -102,7 +102,7 @@ theorem integral_comp_abs {f : ℝ → ℝ} : rw [← Measure.map_neg_eq_self (volume : Measure ℝ)] let m : MeasurableEmbedding fun x : ℝ => -x := (Homeomorph.neg ℝ).measurableEmbedding rw [m.integrableOn_map_iff] - simp_rw [Function.comp, abs_neg, neg_preimage, preimage_neg_Iic, neg_zero] + simp_rw [Function.comp_def, abs_neg, neg_preimage, preimage_neg_Iic, neg_zero] exact integrableOn_Ici_iff_integrableOn_Ioi.mpr hf calc _ = (∫ x in Iic 0, f |x|) + ∫ x in Ioi 0, f |x| := by diff --git a/Mathlib/MeasureTheory/Measure/LevyProkhorovMetric.lean b/Mathlib/MeasureTheory/Measure/LevyProkhorovMetric.lean index 9fe65ea8e8dea..5b7eb39f8469e 100644 --- a/Mathlib/MeasureTheory/Measure/LevyProkhorovMetric.lean +++ b/Mathlib/MeasureTheory/Measure/LevyProkhorovMetric.lean @@ -525,7 +525,7 @@ lemma ProbabilityMeasure.continuous_toLevyProkhorov [SeparableSpace Ω] : have third_ε_pos : 0 < ε / 3 := by linarith have third_ε_pos' : 0 < ENNReal.ofReal (ε / 3) := ofReal_pos.mpr third_ε_pos -- First use separability to choose a countable partition of `Ω` into measurable - -- subsets `Es n ⊆ Ω` of small diamater, `diam (Es n) < ε/3`. + -- subsets `Es n ⊆ Ω` of small diameter, `diam (Es n) < ε/3`. obtain ⟨Es, Es_mble, Es_bdd, Es_diam, Es_cover, Es_disjoint⟩ := SeparableSpace.exists_measurable_partition_diam_le Ω third_ε_pos -- Instead of the whole space `Ω = ⋃ n ∈ ℕ, Es n`, focus on a large but finite @@ -533,7 +533,7 @@ lemma ProbabilityMeasure.continuous_toLevyProkhorov [SeparableSpace Ω] : -- `P (⋃ n < N, Es n)ᶜ < ε/3`. obtain ⟨N, hN⟩ : ∃ N, P.toMeasure (⋃ j ∈ Iio N, Es j)ᶜ < ENNReal.ofReal (ε/3) := by have exhaust := @tendsto_measure_biUnion_Ici_zero_of_pairwise_disjoint Ω _ P.toMeasure _ - Es Es_mble Es_disjoint + Es (fun n ↦ (Es_mble n).nullMeasurableSet) Es_disjoint simp only [tendsto_atTop_nhds, Function.comp_apply] at exhaust obtain ⟨N, hN⟩ := exhaust (Iio (ENNReal.ofReal (ε / 3))) third_ε_pos' isOpen_Iio refine ⟨N, ?_⟩ diff --git a/Mathlib/MeasureTheory/Measure/MeasureSpace.lean b/Mathlib/MeasureTheory/Measure/MeasureSpace.lean index 18b574d4208a0..26b0127325b4a 100644 --- a/Mathlib/MeasureTheory/Measure/MeasureSpace.lean +++ b/Mathlib/MeasureTheory/Measure/MeasureSpace.lean @@ -126,9 +126,10 @@ theorem measure_union_add_inter' (hs : MeasurableSet s) (t : Set α) : μ (s ∪ t) + μ (s ∩ t) = μ s + μ t := by rw [union_comm, inter_comm, measure_union_add_inter t hs, add_comm] -lemma measure_symmDiff_eq (hs : MeasurableSet s) (ht : MeasurableSet t) : +lemma measure_symmDiff_eq (hs : NullMeasurableSet s μ) (ht : NullMeasurableSet t μ) : μ (s ∆ t) = μ (s \ t) + μ (t \ s) := by - simpa only [symmDiff_def, sup_eq_union] using measure_union disjoint_sdiff_sdiff (ht.diff hs) + simpa only [symmDiff_def, sup_eq_union] + using measure_union₀ (ht.diff hs) disjoint_sdiff_sdiff.aedisjoint lemma measure_symmDiff_le (s t u : Set α) : μ (s ∆ u) ≤ μ (s ∆ t) + μ (t ∆ u) := @@ -205,14 +206,15 @@ theorem sum_measure_preimage_singleton (s : Finset β) {f : α → β} theorem measure_diff_null' (h : μ (s₁ ∩ s₂) = 0) : μ (s₁ \ s₂) = μ s₁ := measure_congr <| diff_ae_eq_self.2 h -theorem measure_add_diff (hs : MeasurableSet s) (t : Set α) : μ s + μ (t \ s) = μ (s ∪ t) := by - rw [← measure_union' disjoint_sdiff_right hs, union_diff_self] +theorem measure_add_diff (hs : NullMeasurableSet s μ) (t : Set α) : + μ s + μ (t \ s) = μ (s ∪ t) := by + rw [← measure_union₀' hs disjoint_sdiff_right.aedisjoint, union_diff_self] -theorem measure_diff' (s : Set α) (hm : MeasurableSet t) (h_fin : μ t ≠ ∞) : +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] -theorem measure_diff (h : s₂ ⊆ s₁) (h₂ : MeasurableSet s₂) (h_fin : μ s₂ ≠ ∞) : +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] theorem le_measure_diff : μ s₁ - μ s₂ ≤ μ (s₁ \ s₂) := @@ -238,13 +240,14 @@ then one has finite measure if and only if the other one does. -/ theorem measure_ne_top_iff_of_symmDiff (hμst : μ (s ∆ t) ≠ ∞) : μ s ≠ ∞ ↔ μ t ≠ ∞ := (measure_eq_top_iff_of_symmDiff hμst).ne -theorem measure_diff_lt_of_lt_add (hs : MeasurableSet s) (hst : s ⊆ t) (hs' : μ s ≠ ∞) {ε : ℝ≥0∞} - (h : μ t < μ s + ε) : μ (t \ s) < ε := by +theorem measure_diff_lt_of_lt_add (hs : NullMeasurableSet s μ) (hst : s ⊆ t) (hs' : μ s ≠ ∞) + {ε : ℝ≥0∞} (h : μ t < μ s + ε) : μ (t \ s) < ε := by rw [measure_diff hst hs hs']; rw [add_comm] at h exact ENNReal.sub_lt_of_lt_add (measure_mono hst) h -theorem measure_diff_le_iff_le_add (hs : MeasurableSet s) (hst : s ⊆ t) (hs' : μ s ≠ ∞) {ε : ℝ≥0∞} : - μ (t \ s) ≤ ε ↔ μ t ≤ μ s + ε := by rw [measure_diff hst hs hs', tsub_le_iff_left] +theorem measure_diff_le_iff_le_add (hs : NullMeasurableSet s μ) (hst : s ⊆ t) (hs' : μ s ≠ ∞) + {ε : ℝ≥0∞} : μ (t \ s) ≤ ε ↔ μ t ≤ μ s + ε := by + rw [measure_diff hst hs hs', tsub_le_iff_left] theorem measure_eq_measure_of_null_diff {s t : Set α} (hst : s ⊆ t) (h_nulldiff : μ (t \ s) = 0) : μ s = μ t := measure_congr <| @@ -295,15 +298,15 @@ theorem union_ae_eq_left_iff_ae_subset : (s ∪ t : Set α) =ᵐ[μ] s ↔ t ≤ theorem union_ae_eq_right_iff_ae_subset : (s ∪ t : Set α) =ᵐ[μ] t ↔ s ≤ᵐ[μ] t := by rw [union_comm, union_ae_eq_left_iff_ae_subset] -theorem ae_eq_of_ae_subset_of_measure_ge (h₁ : s ≤ᵐ[μ] t) (h₂ : μ t ≤ μ s) (hsm : MeasurableSet s) - (ht : μ t ≠ ∞) : s =ᵐ[μ] t := by +theorem ae_eq_of_ae_subset_of_measure_ge (h₁ : s ≤ᵐ[μ] t) (h₂ : μ t ≤ μ s) + (hsm : NullMeasurableSet s μ) (ht : μ t ≠ ∞) : s =ᵐ[μ] t := by refine eventuallyLE_antisymm_iff.mpr ⟨h₁, ae_le_set.mpr ?_⟩ replace h₂ : μ t = μ s := h₂.antisymm (measure_mono_ae h₁) replace ht : μ s ≠ ∞ := h₂ ▸ ht rw [measure_diff' t hsm ht, measure_congr (union_ae_eq_left_iff_ae_subset.mpr h₁), h₂, tsub_self] /-- If `s ⊆ t`, `μ t ≤ μ s`, `μ t ≠ ∞`, and `s` is measurable, then `s =ᵐ[μ] t`. -/ -theorem ae_eq_of_subset_of_measure_ge (h₁ : s ⊆ t) (h₂ : μ t ≤ μ s) (hsm : MeasurableSet s) +theorem ae_eq_of_subset_of_measure_ge (h₁ : s ⊆ t) (h₂ : μ t ≤ μ s) (hsm : NullMeasurableSet s μ) (ht : μ t ≠ ∞) : s =ᵐ[μ] t := ae_eq_of_ae_subset_of_measure_ge (HasSubset.Subset.eventuallyLE h₁) h₂ hsm ht @@ -325,7 +328,7 @@ theorem measure_iUnion_congr_of_subset [Countable β] {s : β → Set α} {t : measure_mono <| subset_inter ((hsub b).trans <| subset_toMeasurable _ _) ((subset_iUnion _ _).trans <| subset_toMeasurable _ _) - · exact (measurableSet_toMeasurable _ _).inter (measurableSet_toMeasurable _ _) + · measurability · rw [measure_toMeasurable] exact htop b calc @@ -426,7 +429,7 @@ theorem measure_iUnion_eq_iSup [Countable ι] {s : ι → Set α} (hd : Directed replace hd : Directed (· ⊆ ·) t := ht ▸ hd.extend_bot Encodable.encode_injective suffices μ (⋃ n, t n) = ⨆ n, μ (t n) by simp only [← ht, Function.apply_extend μ, ← iSup_eq_iUnion, - iSup_extend_bot Encodable.encode_injective, (· ∘ ·), Pi.bot_apply, bot_eq_empty, + iSup_extend_bot Encodable.encode_injective, Function.comp_def, Pi.bot_apply, bot_eq_empty, measure_empty] at this exact this.trans (iSup_extend_bot Encodable.encode_injective _) clear! ι @@ -472,13 +475,13 @@ theorem measure_biUnion_eq_iSup {s : ι → Set α} {t : Set ι} (ht : t.Countab /-- Continuity from above: the measure of the intersection of a decreasing sequence of measurable sets is the infimum of the measures. -/ -theorem measure_iInter_eq_iInf [Countable ι] {s : ι → Set α} (h : ∀ i, MeasurableSet (s i)) +theorem measure_iInter_eq_iInf [Countable ι] {s : ι → Set α} (h : ∀ i, NullMeasurableSet (s i) μ) (hd : Directed (· ⊇ ·) s) (hfin : ∃ i, μ (s i) ≠ ∞) : μ (⋂ i, s i) = ⨅ i, μ (s i) := by rcases hfin with ⟨k, hk⟩ have : ∀ t ⊆ s k, μ t ≠ ∞ := fun t ht => ne_top_of_le_ne_top hk (measure_mono ht) rw [← ENNReal.sub_sub_cancel hk (iInf_le _ k), ENNReal.sub_iInf, ← ENNReal.sub_sub_cancel hk (measure_mono (iInter_subset _ k)), ← - measure_diff (iInter_subset _ k) (MeasurableSet.iInter h) (this _ (iInter_subset _ k)), + measure_diff (iInter_subset _ k) (.iInter h) (this _ (iInter_subset _ k)), diff_iInter, measure_iUnion_eq_iSup] · congr 1 refine le_antisymm (iSup_mono' fun i => ?_) (iSup_mono fun i => ?_) @@ -486,17 +489,14 @@ theorem measure_iInter_eq_iInf [Countable ι] {s : ι → Set α} (h : ∀ i, Me use j rw [← measure_diff hjk (h _) (this _ hjk)] gcongr - · rw [tsub_le_iff_right, ← measure_union, Set.union_comm] - · exact measure_mono (diff_subset_iff.1 Subset.rfl) - · apply disjoint_sdiff_left - · apply h i + · apply le_measure_diff · exact hd.mono_comp _ fun _ _ => diff_subset_diff_right /-- Continuity from above: the measure of the intersection of a sequence of measurable sets is the infimum of the measures of the partial intersections. -/ theorem measure_iInter_eq_iInf' {α ι : Type*} [MeasurableSpace α] {μ : Measure α} [Countable ι] [Preorder ι] [IsDirected ι (· ≤ ·)] - {f : ι → Set α} (h : ∀ i, MeasurableSet (f i)) (hfin : ∃ i, μ (f i) ≠ ∞) : + {f : ι → Set α} (h : ∀ i, NullMeasurableSet (f i) μ) (hfin : ∃ i, μ (f i) ≠ ∞) : μ (⋂ i, f i) = ⨅ i, μ (⋂ j ≤ i, f j) := by let s := fun i ↦ ⋂ j ≤ i, f j have iInter_eq : ⋂ i, f i = ⋂ i, s i := by @@ -505,8 +505,8 @@ theorem measure_iInter_eq_iInf' {α ι : Type*} [MeasurableSpace α] {μ : Measu · intro h i rcases directed_of (· ≤ ·) i i with ⟨j, rij, -⟩ exact h j i rij - have ms : ∀ i, MeasurableSet (s i) := - fun i ↦ MeasurableSet.biInter (countable_univ.mono <| subset_univ _) fun i _ ↦ h i + have ms : ∀ i, NullMeasurableSet (s i) μ := + fun i ↦ .biInter (to_countable _) fun i _ ↦ h i have hd : Directed (· ⊇ ·) s := by intro i j rcases directed_of (· ≤ ·) i j with ⟨k, rik, rjk⟩ @@ -536,7 +536,7 @@ theorem tendsto_measure_iUnion' {α ι : Type*} [MeasurableSpace α] {μ : Measu /-- 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 α} - (hs : ∀ n, MeasurableSet (s n)) (hm : Antitone s) (hf : ∃ i, μ (s i) ≠ ∞) : + (hs : ∀ n, NullMeasurableSet (s n) μ) (hm : Antitone s) (hf : ∃ i, μ (s i) ≠ ∞) : Tendsto (μ ∘ s) atTop (𝓝 (μ (⋂ n, s n))) := by rw [measure_iInter_eq_iInf hs hm.directed_ge hf] exact tendsto_atTop_iInf fun n m hnm => measure_mono <| hm hnm @@ -544,7 +544,7 @@ theorem tendsto_measure_iInter [Countable ι] [Preorder ι] [IsDirected ι (· /-- Continuity from above: the measure of the intersection of a sequence of measurable sets such that one has finite measure is the limit of the measures of the partial intersections. -/ theorem tendsto_measure_iInter' {α ι : Type*} [MeasurableSpace α] {μ : Measure α} [Countable ι] - [Preorder ι] [IsDirected ι (· ≤ ·)] {f : ι → Set α} (hm : ∀ i, MeasurableSet (f i)) + [Preorder ι] [IsDirected ι (· ≤ ·)] {f : ι → Set α} (hm : ∀ i, NullMeasurableSet (f i) μ) (hf : ∃ i, μ (f i) ≠ ∞) : Tendsto (fun i ↦ μ (⋂ j ∈ {j | j ≤ i}, f j)) atTop (𝓝 (μ (⋂ i, f i))) := by rw [measure_iInter_eq_iInf' hm hf] @@ -555,7 +555,7 @@ theorem tendsto_measure_iInter' {α ι : Type*} [MeasurableSpace α] {μ : Measu sets indexed by a linear order with first countable topology is the limit of the measures. -/ theorem tendsto_measure_biInter_gt {ι : Type*} [LinearOrder ι] [TopologicalSpace ι] [OrderTopology ι] [DenselyOrdered ι] [FirstCountableTopology ι] {s : ι → Set α} - {a : ι} (hs : ∀ r > a, MeasurableSet (s r)) (hm : ∀ i j, a < i → i ≤ j → s i ⊆ s j) + {a : ι} (hs : ∀ r > a, NullMeasurableSet (s r) μ) (hm : ∀ i j, a < i → i ≤ j → s i ⊆ s j) (hf : ∃ r > a, μ (s r) ≠ ∞) : Tendsto (μ ∘ s) (𝓝[Ioi a] a) (𝓝 (μ (⋂ r > a, s r))) := by refine tendsto_order.2 ⟨fun l hl => ?_, fun L hL => ?_⟩ · filter_upwards [self_mem_nhdsWithin (s := Ioi a)] with r hr using hl.trans_le @@ -611,7 +611,7 @@ theorem measure_limsup_eq_zero {s : ℕ → Set α} (hs : (∑' i, μ (s i)) ≠ refine le_of_tendsto_of_tendsto' (tendsto_measure_iInter - (fun i => MeasurableSet.iUnion fun b => measurableSet_toMeasurable _ _) ?_ + (fun i => .iUnion fun b => (measurableSet_toMeasurable _ _).nullMeasurableSet) ?_ ⟨0, ne_top_of_le_ne_top ht (measure_iUnion_le t)⟩) (ENNReal.tendsto_sum_nat_add (μ ∘ t) ht) fun n => measure_iUnion_le _ intro n m hnm x @@ -749,6 +749,12 @@ theorem zero_toOuterMeasure {_m : MeasurableSpace α} : (0 : Measure α).toOuter theorem coe_zero {_m : MeasurableSpace α} : ⇑(0 : Measure α) = 0 := rfl +@[simp] lemma _root_.MeasureTheory.OuterMeasure.toMeasure_zero + [ms : MeasurableSpace α](h : ms ≤ (0 : OuterMeasure α).caratheodory) : + (0 : OuterMeasure α).toMeasure h = 0 := by + ext s hs + simp [hs] + @[nontriviality] lemma apply_eq_zero_of_isEmpty [IsEmpty α] {_ : MeasurableSpace α} (μ : Measure α) (s : Set α) : μ s = 0 := by @@ -870,14 +876,18 @@ theorem nnreal_smul_coe_apply {_m : MeasurableSpace α} (c : ℝ≥0) (μ : Meas c • μ s = c * μ s := by rfl -theorem ae_smul_measure_iff {p : α → Prop} {c : ℝ≥0∞} (hc : c ≠ 0) : - (∀ᵐ x ∂c • μ, p x) ↔ ∀ᵐ x ∂μ, p x := by +section SMulWithZero + +variable {R : Type*} [Zero R] [SMulWithZero R ℝ≥0∞] [IsScalarTower R ℝ≥0∞ ℝ≥0∞] + [NoZeroSMulDivisors R ℝ≥0∞] {c : R} {p : α → Prop} + +lemma ae_smul_measure_iff (hc : c ≠ 0) {μ : Measure α} : (∀ᵐ x ∂c • μ, p x) ↔ ∀ᵐ x ∂μ, p x := by simp [ae_iff, hc] -@[simp] -theorem ae_smul_measure_eq {c : ℝ≥0∞} (hc : c ≠ 0) : ae (c • μ) = ae μ := by - ext - exact ae_smul_measure_iff hc +@[simp] lemma ae_smul_measure_eq (hc : c ≠ 0) (μ : Measure α) : ae (c • μ) = ae μ := by + ext; exact ae_smul_measure_iff hc + +end SMulWithZero theorem measure_eq_left_of_subset_of_measure_add_eq {s t : Set α} (h : (μ + ν) t ≠ ∞) (h' : s ⊆ t) (h'' : (μ + ν) s = (μ + ν) t) : μ s = μ t := by @@ -1322,7 +1332,13 @@ theorem comap_preimage {β} [MeasurableSpace α] {mβ : MeasurableSpace β} (f : μ.comap f (f ⁻¹' s) = μ (s ∩ range f) := by rw [comap_apply₀ _ _ hf h (hf' hs).nullMeasurableSet, image_preimage_eq_inter_range] +@[simp] lemma comap_zero : (0 : Measure β).comap f = 0 := by + by_cases hf : Injective f ∧ ∀ s, MeasurableSet s → NullMeasurableSet (f '' s) (0 : Measure β) + · simp [comap, hf] + · simp [comap, hf] + section Sum +variable {f : ι → Measure α} /-- Sum of an indexed family of measures. -/ noncomputable def sum (f : ι → Measure α) : Measure α := @@ -1341,7 +1357,7 @@ theorem sum_apply (f : ι → Measure α) {s : Set α} (hs : MeasurableSet s) : theorem sum_apply₀ (f : ι → Measure α) {s : Set α} (hs : NullMeasurableSet s (sum f)) : sum f s = ∑' i, f i s := by apply le_antisymm ?_ (le_sum_apply _ _) - rcases hs.exists_measurable_subset_ae_eq with ⟨t, ts, t_meas, ht⟩ + rcases hs.exists_measurable_subset_ae_eq with ⟨t, ts, t_meas, ht⟩ calc sum f s = sum f t := measure_congr ht.symm _ = ∑' i, f i t := sum_apply _ t_meas @@ -1375,6 +1391,9 @@ theorem sum_apply_eq_zero [Countable ι] {μ : ι → Measure α} {s : Set α} : theorem sum_apply_eq_zero' {μ : ι → Measure α} {s : Set α} (hs : MeasurableSet s) : sum μ s = 0 ↔ ∀ i, μ i s = 0 := by simp [hs] +@[simp] lemma sum_eq_zero : sum f = 0 ↔ ∀ i, f i = 0 := by + simp (config := { contextual := true }) [Measure.ext_iff, forall_swap (α := ι)] + @[simp] lemma sum_zero : Measure.sum (fun (_ : ι) ↦ (0 : Measure α)) = 0 := by ext s hs @@ -1647,6 +1666,13 @@ theorem preimage_ae_eq {s t : Set β} (hf : QuasiMeasurePreserving f μa μb) (h f ⁻¹' s =ᵐ[μa] f ⁻¹' t := EventuallyLE.antisymm (hf.preimage_mono_ae h.le) (hf.preimage_mono_ae h.symm.le) +/-- The preimage of a null measurable set under a (quasi) measure preserving map is a null +measurable set. -/ +theorem _root_.MeasureTheory.NullMeasurableSet.preimage {s : Set β} (hs : NullMeasurableSet s μb) + (hf : QuasiMeasurePreserving f μa μb) : NullMeasurableSet (f ⁻¹' s) μa := + let ⟨t, htm, hst⟩ := hs + ⟨f ⁻¹' t, hf.measurable htm, hf.preimage_ae_eq hst⟩ + theorem preimage_iterate_ae_eq {s : Set α} {f : α → α} (hf : QuasiMeasurePreserving f μ μ) (k : ℕ) (hs : f ⁻¹' s =ᵐ[μ] s) : f^[k] ⁻¹' s =ᵐ[μ] s := by induction' k with k ih; · rfl @@ -1668,37 +1694,31 @@ theorem image_zpow_ae_eq {s : Set α} {e : α ≃ α} (he : QuasiMeasurePreservi replace he : (⇑e)^[k] ⁻¹' s =ᵐ[μ] s := he.preimage_iterate_ae_eq k hs rwa [Equiv.Perm.iterate_eq_pow e k] at he --- Need to specify `α := Set α` below because of diamond; see #19041 +-- Need to specify `α := Set α` below because of diamond; see #10941 theorem limsup_preimage_iterate_ae_eq {f : α → α} (hf : QuasiMeasurePreserving f μ μ) (hs : f ⁻¹' s =ᵐ[μ] s) : limsup (α := Set α) (fun n => (preimage f)^[n] s) atTop =ᵐ[μ] s := - haveI : ∀ n, (preimage f)^[n] s =ᵐ[μ] s := by - intro n - induction' n with n ih - · rfl - simpa only [iterate_succ', comp_apply] using ae_eq_trans (hf.ae_eq ih) hs - (limsup_ae_eq_of_forall_ae_eq (fun n => (preimage f)^[n] s) this).trans (ae_eq_refl _) + limsup_ae_eq_of_forall_ae_eq (fun n => (preimage f)^[n] s) fun n ↦ by + simpa only [Set.preimage_iterate_eq] using hf.preimage_iterate_ae_eq n hs --- Need to specify `α := Set α` below because of diamond; see #19041 +-- Need to specify `α := Set α` below because of diamond; see #10941 theorem liminf_preimage_iterate_ae_eq {f : α → α} (hf : QuasiMeasurePreserving f μ μ) - (hs : f ⁻¹' s =ᵐ[μ] s) : liminf (α := Set α) (fun n => (preimage f)^[n] s) atTop =ᵐ[μ] s := by - rw [← ae_eq_set_compl_compl, @Filter.liminf_compl (Set α)] - rw [← ae_eq_set_compl_compl, ← preimage_compl] at hs - convert hf.limsup_preimage_iterate_ae_eq hs - ext1 n - simp only [← Set.preimage_iterate_eq, comp_apply, preimage_compl] - -/-- By replacing a measurable set that is almost invariant with the `limsup` of its preimages, we -obtain a measurable set that is almost equal and strictly invariant. + (hs : f ⁻¹' s =ᵐ[μ] s) : liminf (α := Set α) (fun n => (preimage f)^[n] s) atTop =ᵐ[μ] s := + liminf_ae_eq_of_forall_ae_eq (fun n => (preimage f)^[n] s) fun n ↦ by + simpa only [Set.preimage_iterate_eq] using hf.preimage_iterate_ae_eq n hs -(The `liminf` would work just as well.) -/ +/-- For a quasi measure preserving self-map `f`, if a null measurable set `s` is a.e. invariant, +then it is a.e. equal to a measurable invariant set. +-/ theorem exists_preimage_eq_of_preimage_ae {f : α → α} (h : QuasiMeasurePreserving f μ μ) - (hs : MeasurableSet s) (hs' : f ⁻¹' s =ᵐ[μ] s) : - ∃ t : Set α, MeasurableSet t ∧ t =ᵐ[μ] s ∧ f ⁻¹' t = t := - ⟨limsup (fun n => (preimage f)^[n] s) atTop, - MeasurableSet.measurableSet_limsup fun n => - preimage_iterate_eq ▸ h.measurable.iterate n hs, - h.limsup_preimage_iterate_ae_eq hs', - (CompleteLatticeHom.setPreimage f).apply_limsup_iterate s⟩ + (hs : NullMeasurableSet s μ) (hs' : f ⁻¹' s =ᵐ[μ] s) : + ∃ t : Set α, MeasurableSet t ∧ t =ᵐ[μ] s ∧ f ⁻¹' t = t := by + obtain ⟨t, htm, ht⟩ := hs + refine ⟨limsup (f^[·] ⁻¹' t) atTop, ?_, ?_, ?_⟩ + · exact .measurableSet_limsup fun n ↦ h.measurable.iterate n htm + · have : f ⁻¹' t =ᵐ[μ] t := (h.preimage_ae_eq ht.symm).trans (hs'.trans ht) + exact limsup_ae_eq_of_forall_ae_eq _ fun n ↦ .trans (h.preimage_iterate_ae_eq _ this) ht.symm + · simp only [Set.preimage_iterate_eq] + exact CompleteLatticeHom.apply_limsup_iterate (CompleteLatticeHom.setPreimage f) t open Pointwise @@ -1770,14 +1790,6 @@ lemma _root_.AEMeasurable.nullMeasurableSet_preimage {f : α → β} {s : Set β (hf : AEMeasurable f μ) (hs : MeasurableSet s) : NullMeasurableSet (f ⁻¹' s) μ := hf.nullMeasurable hs -/-- The preimage of a null measurable set under a (quasi) measure preserving map is a null -measurable set. -/ -theorem NullMeasurableSet.preimage {ν : Measure β} {f : α → β} {t : Set β} - (ht : NullMeasurableSet t ν) (hf : QuasiMeasurePreserving f μ ν) : - NullMeasurableSet (f ⁻¹' t) μ := - ⟨f ⁻¹' toMeasurable ν t, hf.measurable (measurableSet_toMeasurable _ _), - hf.ae_eq ht.toMeasurable_ae_eq.symm⟩ - theorem NullMeasurableSet.mono_ac (h : NullMeasurableSet s μ) (hle : ν ≪ μ) : NullMeasurableSet s ν := h.preimage <| (QuasiMeasurePreserving.id μ).mono_left hle @@ -2015,13 +2027,6 @@ theorem quasiMeasurePreserving_symm (μ : Measure α) (e : α ≃ᵐ β) : end MeasurableEquiv -namespace MeasureTheory - -theorem OuterMeasure.toMeasure_zero [MeasurableSpace α] : - (0 : OuterMeasure α).toMeasure (le_top.trans OuterMeasure.zero_caratheodory.symm.le) = 0 := by - rw [← Measure.measure_univ_eq_zero, toMeasure_apply _ _ MeasurableSet.univ, - OuterMeasure.coe_zero, Pi.zero_apply] - -end MeasureTheory - end + +set_option linter.style.longFile 2200 diff --git a/Mathlib/MeasureTheory/Measure/MeasureSpaceDef.lean b/Mathlib/MeasureTheory/Measure/MeasureSpaceDef.lean index 3c9f822f568c8..5dcc0f77d0243 100644 --- a/Mathlib/MeasureTheory/Measure/MeasureSpaceDef.lean +++ b/Mathlib/MeasureTheory/Measure/MeasureSpaceDef.lean @@ -203,11 +203,11 @@ theorem exists_measurable_superset_iff_measure_eq_zero : ⟨fun ⟨_t, hst, _, ht⟩ => measure_mono_null hst ht, exists_measurable_superset_of_null⟩ theorem measure_biUnion_lt_top {s : Set β} {f : β → Set α} (hs : s.Finite) - (hfin : ∀ i ∈ s, μ (f i) ≠ ∞) : μ (⋃ i ∈ s, f i) < ∞ := by + (hfin : ∀ i ∈ s, μ (f i) < ∞) : μ (⋃ i ∈ s, f i) < ∞ := by convert (measure_biUnion_finset_le (μ := μ) hs.toFinset f).trans_lt _ using 3 · ext rw [Finite.mem_toFinset] - · apply ENNReal.sum_lt_top; simpa only [Finite.mem_toFinset] + · simpa only [ENNReal.sum_lt_top, Finite.mem_toFinset] @[deprecated measure_iUnion_null_iff (since := "2024-01-14")] theorem measure_iUnion_null_iff' {ι : Prop} {s : ι → Set α} : μ (⋃ i, s i) = 0 ↔ ∀ i, μ (s i) = 0 := @@ -378,6 +378,9 @@ theorem Measurable.aemeasurable (h : Measurable f) : AEMeasurable f μ := namespace AEMeasurable +lemma of_discrete [DiscreteMeasurableSpace α] : AEMeasurable f μ := + Measurable.of_discrete.aemeasurable + /-- Given an almost everywhere measurable function `f`, associate to it a measurable function that coincides with it almost everywhere. `f` is explicit in the definition to make sure that it shows in pretty-printing. -/ diff --git a/Mathlib/MeasureTheory/Measure/Regular.lean b/Mathlib/MeasureTheory/Measure/Regular.lean index 3ba9dadd512e0..cb00bad6d11e4 100644 --- a/Mathlib/MeasureTheory/Measure/Regular.lean +++ b/Mathlib/MeasureTheory/Measure/Regular.lean @@ -361,7 +361,7 @@ theorem _root_.MeasurableSet.exists_isOpen_diff_lt [OuterRegular μ] {A : Set α ∃ U, U ⊇ A ∧ IsOpen U ∧ μ U < ∞ ∧ μ (U \ A) < ε := by rcases A.exists_isOpen_lt_add hA' hε with ⟨U, hAU, hUo, hU⟩ use U, hAU, hUo, hU.trans_le le_top - exact measure_diff_lt_of_lt_add hA hAU hA' hU + exact measure_diff_lt_of_lt_add hA.nullMeasurableSet hAU hA' hU protected theorem map [OpensMeasurableSpace α] [MeasurableSpace β] [TopologicalSpace β] [BorelSpace β] (f : α ≃ₜ β) (μ : Measure α) [OuterRegular μ] : @@ -455,7 +455,7 @@ lemma of_restrict {μ : Measure α} {s : ℕ → Set α} (h : ∀ n, InnerRegularWRT (μ.restrict (s n)) p MeasurableSet) (hs : univ ⊆ ⋃ n, s n) (hmono : Monotone s) : InnerRegularWRT μ p MeasurableSet := by intro F hF r hr - have hBU : ⋃ n, F ∩ s n = F := by rw [← inter_iUnion, univ_subset_iff.mp hs, inter_univ] + have hBU : ⋃ n, F ∩ s n = F := by rw [← inter_iUnion, univ_subset_iff.mp hs, inter_univ] have : μ F = ⨆ n, μ (F ∩ s n) := by rw [← measure_iUnion_eq_iSup, hBU] exact Monotone.directed_le fun m n h ↦ inter_subset_inter_right _ (hmono h) @@ -730,7 +730,7 @@ theorem _root_.MeasurableSet.exists_isCompact_diff_lt [OpensMeasurableSpace α] {ε : ℝ≥0∞} (hε : ε ≠ 0) : ∃ K, K ⊆ A ∧ IsCompact K ∧ μ (A \ K) < ε := by rcases hA.exists_isCompact_lt_add h'A hε with ⟨K, hKA, hKc, hK⟩ - exact ⟨K, hKA, hKc, measure_diff_lt_of_lt_add hKc.measurableSet hKA + exact ⟨K, hKA, hKc, measure_diff_lt_of_lt_add hKc.nullMeasurableSet hKA (ne_top_of_le_ne_top h'A <| measure_mono hKA) hK⟩ /-- If `μ` is inner regular for finite measure sets with respect to compact sets, @@ -742,7 +742,7 @@ theorem _root_.MeasurableSet.exists_isCompact_isClosed_diff_lt [BorelSpace α] [ {ε : ℝ≥0∞} (hε : ε ≠ 0) : ∃ K, K ⊆ A ∧ IsCompact K ∧ IsClosed K ∧ μ (A \ K) < ε := by rcases hA.exists_isCompact_isClosed_lt_add h'A hε with ⟨K, hKA, hKco, hKcl, hK⟩ - exact ⟨K, hKA, hKco, hKcl, measure_diff_lt_of_lt_add hKcl.measurableSet hKA + exact ⟨K, hKA, hKco, hKcl, measure_diff_lt_of_lt_add hKcl.nullMeasurableSet hKA (ne_top_of_le_ne_top h'A <| measure_mono hKA) hK⟩ /-- If `μ` is inner regular for finite measure sets with respect to compact sets, @@ -826,12 +826,12 @@ protected theorem _root_.MeasurableSet.exists_isOpen_symmDiff_lt [InnerRegularCo rcases hs.exists_isCompact_isClosed_diff_lt hμs this with ⟨K, hKs, hKco, hKcl, hμK⟩ rcases hKco.exists_isOpen_lt_add (μ := μ) this with ⟨U, hKU, hUo, hμU⟩ refine ⟨U, hUo, hμU.trans_le le_top, ?_⟩ - rw [← ENNReal.add_halves ε, measure_symmDiff_eq hUo.measurableSet hs] + rw [← ENNReal.add_halves ε, measure_symmDiff_eq hUo.nullMeasurableSet hs.nullMeasurableSet] gcongr · calc μ (U \ s) ≤ μ (U \ K) := by gcongr _ < ε / 2 := by - apply measure_diff_lt_of_lt_add hKcl.measurableSet hKU _ hμU + apply measure_diff_lt_of_lt_add hKcl.nullMeasurableSet hKU _ hμU exact ne_top_of_le_ne_top hμs (by gcongr) · exact lt_of_le_of_lt (by gcongr) hμK @@ -918,7 +918,7 @@ theorem _root_.MeasurableSet.exists_isClosed_diff_lt [OpensMeasurableSpace α] [ ⦃A : Set α⦄ (hA : MeasurableSet A) (h'A : μ A ≠ ∞) {ε : ℝ≥0∞} (hε : ε ≠ 0) : ∃ F, F ⊆ A ∧ IsClosed F ∧ μ (A \ F) < ε := by rcases hA.exists_isClosed_lt_add h'A hε with ⟨F, hFA, hFc, hF⟩ - exact ⟨F, hFA, hFc, measure_diff_lt_of_lt_add hFc.measurableSet hFA + exact ⟨F, hFA, hFc, measure_diff_lt_of_lt_add hFc.nullMeasurableSet hFA (ne_top_of_le_ne_top h'A <| measure_mono hFA) hF⟩ /-- Given a weakly regular measure, any measurable set of finite mass can be approximated from diff --git a/Mathlib/MeasureTheory/Measure/Restrict.lean b/Mathlib/MeasureTheory/Measure/Restrict.lean index c38f9cc1c8cef..99d9b00f136b2 100644 --- a/Mathlib/MeasureTheory/Measure/Restrict.lean +++ b/Mathlib/MeasureTheory/Measure/Restrict.lean @@ -76,11 +76,21 @@ theorem restrict_mono' {_m0 : MeasurableSpace α} ⦃s s' : Set α⦄ ⦃μ ν : _ = ν.restrict s' t := (restrict_apply ht).symm /-- Restriction of a measure to a subset is monotone both in set and in measure. -/ -@[mono] +@[mono, gcongr] theorem restrict_mono {_m0 : MeasurableSpace α} ⦃s s' : Set α⦄ (hs : s ⊆ s') ⦃μ ν : Measure α⦄ (hμν : μ ≤ ν) : μ.restrict s ≤ ν.restrict s' := restrict_mono' (ae_of_all _ hs) hμν +@[gcongr] +theorem restrict_mono_measure {_ : MeasurableSpace α} {μ ν : Measure α} (h : μ ≤ ν) (s : Set α) : + μ.restrict s ≤ ν.restrict s := + restrict_mono subset_rfl h + +@[gcongr] +theorem restrict_mono_set {_ : MeasurableSpace α} (μ : Measure α) {s t : Set α} (h : s ⊆ t) : + μ.restrict s ≤ μ.restrict t := + restrict_mono h le_rfl + theorem restrict_mono_ae (h : s ≤ᵐ[μ] t) : μ.restrict s ≤ μ.restrict t := restrict_mono' h (le_refl μ) @@ -307,11 +317,8 @@ measurable subsets of `s ∪ t`. -/ theorem restrict_union_congr : μ.restrict (s ∪ t) = ν.restrict (s ∪ t) ↔ μ.restrict s = ν.restrict s ∧ μ.restrict t = ν.restrict t := by - refine - ⟨fun h => - ⟨restrict_congr_mono subset_union_left h, - restrict_congr_mono subset_union_right h⟩, - ?_⟩ + refine ⟨fun h ↦ ⟨restrict_congr_mono subset_union_left h, + restrict_congr_mono subset_union_right h⟩, ?_⟩ rintro ⟨hs, ht⟩ ext1 u hu simp only [restrict_apply hu, inter_union_distrib_left] @@ -319,14 +326,14 @@ theorem restrict_union_congr : calc μ (u ∩ s ∪ u ∩ t) = μ (US ∪ u ∩ t) := measure_union_congr_of_subset hsub hμ.le Subset.rfl le_rfl - _ = μ US + μ ((u ∩ t) \ US) := (measure_add_diff hm _).symm + _ = μ US + μ ((u ∩ t) \ US) := (measure_add_diff hm.nullMeasurableSet _).symm _ = restrict μ s u + restrict μ t (u \ US) := by simp only [restrict_apply, hu, hu.diff hm, hμ, ← inter_comm t, inter_diff_assoc] _ = restrict ν s u + restrict ν t (u \ US) := by rw [hs, ht] _ = ν US + ν ((u ∩ t) \ US) := by simp only [restrict_apply, hu, hu.diff hm, hν, ← inter_comm t, inter_diff_assoc] - _ = ν (US ∪ u ∩ t) := measure_add_diff hm _ - _ = ν (u ∩ s ∪ u ∩ t) := Eq.symm <| measure_union_congr_of_subset hsub hν.le Subset.rfl le_rfl + _ = ν (US ∪ u ∩ t) := measure_add_diff hm.nullMeasurableSet _ + _ = ν (u ∩ s ∪ u ∩ t) := .symm <| measure_union_congr_of_subset hsub hν.le Subset.rfl le_rfl theorem restrict_finset_biUnion_congr {s : Finset ι} {t : ι → Set α} : μ.restrict (⋃ i ∈ s, t i) = ν.restrict (⋃ i ∈ s, t i) ↔ diff --git a/Mathlib/MeasureTheory/Measure/Stieltjes.lean b/Mathlib/MeasureTheory/Measure/Stieltjes.lean index 7399a3bc6bab9..150f72aaf7a86 100644 --- a/Mathlib/MeasureTheory/Measure/Stieltjes.lean +++ b/Mathlib/MeasureTheory/Measure/Stieltjes.lean @@ -373,8 +373,9 @@ theorem measure_singleton (a : ℝ) : f.measure {a} = ofReal (f a - leftLim f a) simp [le_antisymm this (hx 0).2] have L1 : Tendsto (fun n => f.measure (Ioc (u n) a)) atTop (𝓝 (f.measure {a})) := by rw [A] - refine tendsto_measure_iInter (fun n => measurableSet_Ioc) (fun m n hmn => ?_) ?_ - · exact Ioc_subset_Ioc (u_mono.monotone hmn) le_rfl + refine tendsto_measure_iInter (fun n => measurableSet_Ioc.nullMeasurableSet) + (fun m n hmn => ?_) ?_ + · exact Ioc_subset_Ioc_left (u_mono.monotone hmn) · exact ⟨0, by simpa only [measure_Ioc] using ENNReal.ofReal_ne_top⟩ have L2 : Tendsto (fun n => f.measure (Ioc (u n) a)) atTop (𝓝 (ofReal (f a - leftLim f a))) := by diff --git a/Mathlib/MeasureTheory/Measure/Typeclasses.lean b/Mathlib/MeasureTheory/Measure/Typeclasses.lean index b76803bde0962..25c6a33aeb53c 100644 --- a/Mathlib/MeasureTheory/Measure/Typeclasses.lean +++ b/Mathlib/MeasureTheory/Measure/Typeclasses.lean @@ -12,6 +12,7 @@ We introduce the following typeclasses for measures: * `IsProbabilityMeasure μ`: `μ univ = 1`; * `IsFiniteMeasure μ`: `μ univ < ∞`; +* `IsZeroOrProbabilityMeasure μ`: `μ univ = 0 ∨ μ univ = 1`; * `SigmaFinite μ`: there exists a countable collection of sets that cover `univ` where `μ` is finite; * `SFinite μ`: the measure `μ` can be written as a countable sum of finite measures; @@ -95,7 +96,7 @@ instance isFiniteMeasureAdd [IsFiniteMeasure μ] [IsFiniteMeasure ν] : IsFinite exact ⟨measure_lt_top _ _, measure_lt_top _ _⟩ instance isFiniteMeasureSMulNNReal [IsFiniteMeasure μ] {r : ℝ≥0} : IsFiniteMeasure (r • μ) where - measure_univ_lt_top := ENNReal.mul_lt_top ENNReal.coe_ne_top (measure_ne_top _ _) + measure_univ_lt_top := ENNReal.mul_lt_top ENNReal.coe_lt_top (measure_lt_top _ _) instance IsFiniteMeasure.average : IsFiniteMeasure ((μ univ)⁻¹ • μ) where measure_univ_lt_top := by @@ -142,13 +143,9 @@ theorem summable_measure_toReal [hμ : IsFiniteMeasure μ] {f : ℕ → Set α} exact ne_of_lt (measure_lt_top _ _) theorem ae_eq_univ_iff_measure_eq [IsFiniteMeasure μ] (hs : NullMeasurableSet s μ) : - s =ᵐ[μ] univ ↔ μ s = μ univ := by - refine ⟨measure_congr, fun h => ?_⟩ - obtain ⟨t, -, ht₁, ht₂⟩ := hs.exists_measurable_subset_ae_eq - exact - ht₂.symm.trans - (ae_eq_of_subset_of_measure_ge (subset_univ t) (Eq.le ((measure_congr ht₂).trans h).symm) ht₁ - (measure_ne_top μ univ)) + s =ᵐ[μ] univ ↔ μ s = μ univ := + ⟨measure_congr, fun h ↦ + (ae_eq_of_subset_of_measure_ge (subset_univ s) h.ge hs (measure_ne_top μ univ))⟩ theorem ae_iff_measure_eq [IsFiniteMeasure μ] {p : α → Prop} (hp : NullMeasurableSet { a | p a } μ) : (∀ᵐ a ∂μ, p a) ↔ μ { a | p a } = μ univ := by @@ -160,7 +157,7 @@ theorem ae_mem_iff_measure_eq [IsFiniteMeasure μ] {s : Set α} (hs : NullMeasur lemma tendsto_measure_biUnion_Ici_zero_of_pairwise_disjoint {X : Type*} [MeasurableSpace X] {μ : Measure X} [IsFiniteMeasure μ] - {Es : ℕ → Set X} (Es_mble : ∀ i, MeasurableSet (Es i)) + {Es : ℕ → Set X} (Es_mble : ∀ i, NullMeasurableSet (Es i) μ) (Es_disj : Pairwise fun n m ↦ Disjoint (Es n) (Es m)) : Tendsto (μ ∘ fun n ↦ ⋃ i ≥ n, Es i) atTop (𝓝 0) := by have decr : Antitone fun n ↦ ⋃ i ≥ n, Es i := @@ -173,15 +170,16 @@ lemma tendsto_measure_biUnion_Ici_zero_of_pairwise_disjoint obtain ⟨k, k_gt_j, x_in_Es_k⟩ := hx (j+1) have oops := (Es_disj (Nat.ne_of_lt k_gt_j)).ne_of_mem x_in_Es_j x_in_Es_k contradiction - have key := - tendsto_measure_iInter (μ := μ) (fun n ↦ by measurability) decr ⟨0, measure_ne_top _ _⟩ + -- TODO: `by measurability` fails + have key := tendsto_measure_iInter (μ := μ) (fun n ↦ .iUnion fun _ ↦ .iUnion fun _ ↦ Es_mble _) + decr ⟨0, measure_ne_top _ _⟩ simp only [nothing, measure_empty] at key convert key open scoped symmDiff theorem abs_toReal_measure_sub_le_measure_symmDiff' - (hs : MeasurableSet s) (ht : MeasurableSet t) (hs' : μ s ≠ ∞) (ht' : μ t ≠ ∞) : + (hs : NullMeasurableSet s μ) (ht : NullMeasurableSet t μ) (hs' : μ s ≠ ∞) (ht' : μ t ≠ ∞) : |(μ s).toReal - (μ t).toReal| ≤ (μ (s ∆ t)).toReal := by have hst : μ (s \ t) ≠ ∞ := (measure_lt_top_of_subset diff_subset hs').ne have hts : μ (t \ s) ≠ ∞ := (measure_lt_top_of_subset diff_subset ht').ne @@ -195,12 +193,49 @@ theorem abs_toReal_measure_sub_le_measure_symmDiff' abel theorem abs_toReal_measure_sub_le_measure_symmDiff [IsFiniteMeasure μ] - (hs : MeasurableSet s) (ht : MeasurableSet t) : + (hs : NullMeasurableSet s μ) (ht : NullMeasurableSet t μ) : |(μ s).toReal - (μ t).toReal| ≤ (μ (s ∆ t)).toReal := abs_toReal_measure_sub_le_measure_symmDiff' hs ht (measure_ne_top μ s) (measure_ne_top μ t) +instance {s : Finset ι} {μ : ι → Measure α} [∀ i, IsFiniteMeasure (μ i)] : + IsFiniteMeasure (∑ i ∈ s, μ i) where measure_univ_lt_top := by simp [measure_lt_top] + +instance [Finite ι] {μ : ι → Measure α} [∀ i, IsFiniteMeasure (μ i)] : + IsFiniteMeasure (.sum μ) where + measure_univ_lt_top := by + cases nonempty_fintype ι + simp [measure_lt_top] + end IsFiniteMeasure +section IsZeroOrProbabilityMeasure + +/-- A measure `μ` is zero or a probability measure if `μ univ = 0` or `μ univ = 1`. This class +of measures appears naturally when conditioning on events, and many results which are true for +probability measures hold more generally over this class. -/ +class IsZeroOrProbabilityMeasure (μ : Measure α) : Prop where + measure_univ : μ univ = 0 ∨ μ univ = 1 + +lemma isZeroOrProbabilityMeasure_iff : IsZeroOrProbabilityMeasure μ ↔ μ univ = 0 ∨ μ univ = 1 := + ⟨fun _ ↦ IsZeroOrProbabilityMeasure.measure_univ, IsZeroOrProbabilityMeasure.mk⟩ + +lemma prob_le_one {μ : Measure α} [IsZeroOrProbabilityMeasure μ] {s : Set α} : μ s ≤ 1 := by + apply (measure_mono (subset_univ _)).trans + rcases IsZeroOrProbabilityMeasure.measure_univ (μ := μ) with h | h <;> simp [h] + +@[simp] +theorem one_le_prob_iff {μ : Measure α} [IsZeroOrProbabilityMeasure μ] : 1 ≤ μ s ↔ μ s = 1 := + ⟨fun h => le_antisymm prob_le_one h, fun h => h ▸ le_refl _⟩ + +instance (priority := 100) IsZeroOrProbabilityMeasure.toIsFiniteMeasure (μ : Measure α) + [IsZeroOrProbabilityMeasure μ] : IsFiniteMeasure μ := + ⟨prob_le_one.trans_lt one_lt_top⟩ + +instance : IsZeroOrProbabilityMeasure (0 : Measure α) := + ⟨Or.inl rfl⟩ + +end IsZeroOrProbabilityMeasure + section IsProbabilityMeasure /-- A measure `μ` is called a probability measure if `μ univ = 1`. -/ @@ -214,9 +249,9 @@ attribute [simp] IsProbabilityMeasure.measure_univ lemma isProbabilityMeasure_iff : IsProbabilityMeasure μ ↔ μ univ = 1 := ⟨fun _ ↦ measure_univ, IsProbabilityMeasure.mk⟩ -instance (priority := 100) IsProbabilityMeasure.toIsFiniteMeasure (μ : Measure α) - [IsProbabilityMeasure μ] : IsFiniteMeasure μ := - ⟨by simp only [measure_univ, ENNReal.one_lt_top]⟩ +instance (priority := 100) (μ : Measure α) [IsProbabilityMeasure μ] : + IsZeroOrProbabilityMeasure μ := + ⟨Or.inr measure_univ⟩ theorem IsProbabilityMeasure.ne_zero (μ : Measure α) [IsProbabilityMeasure μ] : μ ≠ 0 := mt measure_univ_eq_zero.2 <| by simp [measure_univ] @@ -230,9 +265,6 @@ theorem IsProbabilityMeasure.ae_neBot [IsProbabilityMeasure μ] : NeBot (ae μ) theorem prob_add_prob_compl [IsProbabilityMeasure μ] (h : MeasurableSet s) : μ s + μ sᶜ = 1 := (measure_add_measure_compl h).trans measure_univ -theorem prob_le_one [IsProbabilityMeasure μ] : μ s ≤ 1 := - (measure_mono <| Set.subset_univ _).trans_eq measure_univ - -- Porting note: made an `instance`, using `NeZero` instance isProbabilityMeasureSMul [IsFiniteMeasure μ] [NeZero μ] : IsProbabilityMeasure ((μ univ)⁻¹ • μ) := @@ -244,10 +276,6 @@ theorem isProbabilityMeasure_map {f : α → β} (hf : AEMeasurable f μ) : IsProbabilityMeasure (map f μ) := ⟨by simp [map_apply_of_aemeasurable, hf]⟩ -@[simp] -theorem one_le_prob_iff : 1 ≤ μ s ↔ μ s = 1 := - ⟨fun h => le_antisymm prob_le_one h, fun h => h ▸ le_refl _⟩ - /-- Note that this is not quite as useful as it looks because the measure takes values in `ℝ≥0∞`. Thus the subtraction appearing is the truncated subtraction of `ℝ≥0∞`, rather than the better-behaved subtraction of `ℝ`. -/ @@ -260,17 +288,6 @@ better-behaved subtraction of `ℝ`. -/ theorem prob_compl_eq_one_sub (hs : MeasurableSet s) : μ sᶜ = 1 - μ s := prob_compl_eq_one_sub₀ hs.nullMeasurableSet -lemma prob_compl_lt_one_sub_of_lt_prob {p : ℝ≥0∞} (hμs : p < μ s) (s_mble : MeasurableSet s) : - μ sᶜ < 1 - p := by - rw [prob_compl_eq_one_sub s_mble] - apply ENNReal.sub_lt_of_sub_lt prob_le_one (Or.inl one_ne_top) - convert hμs - exact ENNReal.sub_sub_cancel one_ne_top (lt_of_lt_of_le hμs prob_le_one).le - -lemma prob_compl_le_one_sub_of_le_prob {p : ℝ≥0∞} (hμs : p ≤ μ s) (s_mble : MeasurableSet s) : - μ sᶜ ≤ 1 - p := by - simpa [prob_compl_eq_one_sub s_mble] using tsub_le_tsub_left hμs 1 - @[simp] lemma prob_compl_eq_zero_iff₀ (hs : NullMeasurableSet s μ) : μ sᶜ = 0 ↔ μ s = 1 := by rw [prob_compl_eq_one_sub₀ hs, tsub_eq_zero_iff_le, one_le_prob_iff] @@ -313,6 +330,47 @@ instance isProbabilityMeasure_comap_down : IsProbabilityMeasure (μ.comap ULift. end IsProbabilityMeasure +section IsZeroOrProbabilityMeasure + +instance isZeroOrProbabilityMeasureSMul : + IsZeroOrProbabilityMeasure ((μ univ)⁻¹ • μ) := by + rcases eq_zero_or_neZero μ with rfl | h + · simp; infer_instance + rcases eq_top_or_lt_top (μ univ) with h | h + · simp [h]; infer_instance + have : IsFiniteMeasure μ := ⟨h⟩ + infer_instance + +variable [IsZeroOrProbabilityMeasure μ] {p : α → Prop} {f : β → α} + +variable (μ) in +lemma eq_zero_or_isProbabilityMeasure : μ = 0 ∨ IsProbabilityMeasure μ := by + rcases IsZeroOrProbabilityMeasure.measure_univ (μ := μ) with h | h + · apply Or.inl (measure_univ_eq_zero.mp h) + · exact Or.inr ⟨h⟩ + +instance {f : α → β} : IsZeroOrProbabilityMeasure (map f μ) := by + by_cases hf : AEMeasurable f μ + · simpa [isZeroOrProbabilityMeasure_iff, hf] using IsZeroOrProbabilityMeasure.measure_univ + · simp [isZeroOrProbabilityMeasure_iff, hf] + +lemma prob_compl_lt_one_sub_of_lt_prob {p : ℝ≥0∞} (hμs : p < μ s) (s_mble : MeasurableSet s) : + μ sᶜ < 1 - p := by + rcases eq_zero_or_isProbabilityMeasure μ with rfl | h + · simp at hμs + · rw [prob_compl_eq_one_sub s_mble] + apply ENNReal.sub_lt_of_sub_lt prob_le_one (Or.inl one_ne_top) + convert hμs + exact ENNReal.sub_sub_cancel one_ne_top (lt_of_lt_of_le hμs prob_le_one).le + +lemma prob_compl_le_one_sub_of_le_prob {p : ℝ≥0∞} (hμs : p ≤ μ s) (s_mble : MeasurableSet s) : + μ sᶜ ≤ 1 - p := by + rcases eq_zero_or_isProbabilityMeasure μ with rfl | h + · simp + · simpa [prob_compl_eq_one_sub s_mble] using tsub_le_tsub_left hμs 1 + +end IsZeroOrProbabilityMeasure + section NoAtoms /-- Measure `μ` *has no atoms* if the measure of each singleton is zero. @@ -510,7 +568,7 @@ lemma sFiniteSeq_zero (n : ℕ) : sFiniteSeq (0 : Measure α) n = 0 := by exact h n /-- A countable sum of finite measures is s-finite. -This lemma is superseeded by the instance below. -/ +This lemma is superseded by the instance below. -/ lemma sfinite_sum_of_countable [Countable ι] (m : ι → Measure α) [∀ n, IsFiniteMeasure (m n)] : SFinite (Measure.sum m) := by classical @@ -536,17 +594,24 @@ instance [SFinite μ] (s : Set α) : SFinite (μ.restrict s) := by rw [← restrict_sum_of_countable, sum_sFiniteSeq]⟩ variable (μ) in -/-- An s-finite measure is absolutely continuous with respect to some finite measure. -/ -theorem exists_absolutelyContinuous_isFiniteMeasure [SFinite μ] : - ∃ ν : Measure α, IsFiniteMeasure ν ∧ μ ≪ ν := by +/-- For an s-finite measure `μ`, there exists a finite measure `ν` +such that each of `μ` and `ν` is absolutely continuous with respect to the other. +-/ +theorem exists_isFiniteMeasure_absolutelyContinuous [SFinite μ] : + ∃ ν : Measure α, IsFiniteMeasure ν ∧ μ ≪ ν ∧ ν ≪ μ := by rcases ENNReal.exists_pos_tsum_mul_lt_of_countable top_ne_zero (sFiniteSeq μ · univ) fun _ ↦ measure_ne_top _ _ with ⟨c, hc₀, hc⟩ - refine ⟨.sum fun n ↦ c n • sFiniteSeq μ n, ⟨?_⟩, ?_⟩ - · simpa [mul_comm] using hc - · refine AbsolutelyContinuous.mk fun s hsm hs ↦ ?_ - have : ∀ n, (sFiniteSeq μ n) s = 0 := by simpa [hsm, (hc₀ _).ne'] using hs - rw [← sum_sFiniteSeq μ, sum_apply _ hsm] - simp [this] + have {s : Set α} : sum (fun n ↦ c n • sFiniteSeq μ n) s = 0 ↔ μ s = 0 := by + conv_rhs => rw [← sum_sFiniteSeq μ, sum_apply_of_countable] + simp [(hc₀ _).ne'] + refine ⟨.sum fun n ↦ c n • sFiniteSeq μ n, ⟨?_⟩, fun _ ↦ this.1, fun _ ↦ this.2⟩ + simpa [mul_comm] using hc + +variable (μ) in +@[deprecated exists_isFiniteMeasure_absolutelyContinuous (since := "2024-08-25")] +theorem exists_absolutelyContinuous_isFiniteMeasure [SFinite μ] : + ∃ ν : Measure α, IsFiniteMeasure ν ∧ μ ≪ ν := + let ⟨ν, hfin, h, _⟩ := exists_isFiniteMeasure_absolutelyContinuous μ; ⟨ν, hfin, h⟩ end SFinite @@ -586,7 +651,7 @@ theorem measurable_spanningSets (μ : Measure α) [SigmaFinite μ] (i : ℕ) : theorem measure_spanningSets_lt_top (μ : Measure α) [SigmaFinite μ] (i : ℕ) : μ (spanningSets μ i) < ∞ := - measure_biUnion_lt_top (finite_le_nat i) fun j _ => (μ.toFiniteSpanningSetsIn.finite j).ne + measure_biUnion_lt_top (finite_le_nat i) fun j _ => μ.toFiniteSpanningSetsIn.finite j theorem iUnion_spanningSets (μ : Measure α) [SigmaFinite μ] : ⋃ i : ℕ, spanningSets μ i = univ := by simp_rw [spanningSets, iUnion_accumulate, μ.toFiniteSpanningSetsIn.spanning] @@ -1013,7 +1078,7 @@ instance sum.sigmaFinite {ι} [Finite ι] (μ : ι → Measure α) [∀ i, Sigma have : ∀ n, MeasurableSet (⋂ i : ι, spanningSets (μ i) n) := fun n => MeasurableSet.iInter fun i => measurable_spanningSets (μ i) n refine ⟨⟨⟨fun n => ⋂ i, spanningSets (μ i) n, fun _ => trivial, fun n => ?_, ?_⟩⟩⟩ - · rw [sum_apply _ (this n), tsum_fintype, ENNReal.sum_lt_top_iff] + · rw [sum_apply _ (this n), tsum_fintype, ENNReal.sum_lt_top] rintro i - exact (measure_mono <| iInter_subset _ i).trans_lt (measure_spanningSets_lt_top (μ i) n) · rw [iUnion_iInter_of_monotone] @@ -1033,19 +1098,17 @@ instance SMul.sigmaFinite {μ : Measure α} [SigmaFinite μ] (c : ℝ≥0) : finite := by intro i simp only [Measure.coe_smul, Pi.smul_apply, nnreal_smul_coe_apply] - exact ENNReal.mul_lt_top ENNReal.coe_ne_top (measure_spanningSets_lt_top μ i).ne + exact ENNReal.mul_lt_top ENNReal.coe_lt_top (measure_spanningSets_lt_top μ i) spanning := iUnion_spanningSets μ }⟩ instance [SigmaFinite (μ.restrict s)] [SigmaFinite (μ.restrict t)] : SigmaFinite (μ.restrict (s ∪ t)) := sigmaFinite_of_le _ (restrict_union_le _ _) -instance [h : SigmaFinite (μ.restrict s)] : SigmaFinite (μ.restrict (s ∩ t)) := by - convert sigmaFinite_of_le _ (restrict_mono_ae (ae_of_all _ Set.inter_subset_left)) - exact h +instance [SigmaFinite (μ.restrict s)] : SigmaFinite (μ.restrict (s ∩ t)) := + sigmaFinite_of_le (μ.restrict s) (restrict_mono_ae (ae_of_all _ Set.inter_subset_left)) -instance [h : SigmaFinite (μ.restrict t)] : SigmaFinite (μ.restrict (s ∩ t)) := by - convert sigmaFinite_of_le _ (restrict_mono_ae (ae_of_all _ Set.inter_subset_right)) - exact h +instance [SigmaFinite (μ.restrict t)] : SigmaFinite (μ.restrict (s ∩ t)) := + sigmaFinite_of_le (μ.restrict t) (restrict_mono_ae (ae_of_all _ Set.inter_subset_right)) theorem SigmaFinite.of_map (μ : Measure α) {f : α → β} (hf : AEMeasurable f μ) (h : SigmaFinite (μ.map f)) : SigmaFinite μ := @@ -1115,7 +1178,7 @@ instance isLocallyFiniteMeasureSMulNNReal [TopologicalSpace α] (μ : Measure α refine ⟨fun x => ?_⟩ rcases μ.exists_isOpen_measure_lt_top x with ⟨o, xo, o_open, μo⟩ refine ⟨o, o_open.mem_nhds xo, ?_⟩ - apply ENNReal.mul_lt_top _ μo.ne + apply ENNReal.mul_lt_top _ μo simp protected theorem Measure.isTopologicalBasis_isOpen_lt_top [TopologicalSpace α] @@ -1160,7 +1223,7 @@ theorem measure_ball_lt_top [PseudoMetricSpace α] [ProperSpace α] {μ : Measur protected theorem IsFiniteMeasureOnCompacts.smul [TopologicalSpace α] (μ : Measure α) [IsFiniteMeasureOnCompacts μ] {c : ℝ≥0∞} (hc : c ≠ ∞) : IsFiniteMeasureOnCompacts (c • μ) := - ⟨fun _K hK => ENNReal.mul_lt_top hc hK.measure_lt_top.ne⟩ + ⟨fun _K hK => ENNReal.mul_lt_top hc.lt_top hK.measure_lt_top⟩ instance IsFiniteMeasureOnCompacts.smul_nnreal [TopologicalSpace α] (μ : Measure α) [IsFiniteMeasureOnCompacts μ] (c : ℝ≥0) : IsFiniteMeasureOnCompacts (c • μ) := @@ -1477,3 +1540,5 @@ theorem measure_Ioo_lt_top : μ (Ioo a b) < ∞ := (measure_mono Ioo_subset_Icc_self).trans_lt measure_Icc_lt_top end MeasureIxx + +set_option linter.style.longFile 1700 diff --git a/Mathlib/MeasureTheory/Order/UpperLower.lean b/Mathlib/MeasureTheory/Order/UpperLower.lean index 5e56bec648560..6e04d112e9d58 100644 --- a/Mathlib/MeasureTheory/Order/UpperLower.lean +++ b/Mathlib/MeasureTheory/Order/UpperLower.lean @@ -116,7 +116,7 @@ private lemma aux₁ mul_div_mul_left _ _ (two_ne_zero' ℝ), div_right_comm, div_self, one_div] all_goals try positivity · simp_all - · measurability + · exact measurableSet_closedBall.nullMeasurableSet theorem IsUpperSet.null_frontier (hs : IsUpperSet s) : volume (frontier s) = 0 := by refine measure_mono_null (fun x hx ↦ ?_) diff --git a/Mathlib/MeasureTheory/OuterMeasure/Caratheodory.lean b/Mathlib/MeasureTheory/OuterMeasure/Caratheodory.lean index 04c80d5a09c16..167ea1437b67c 100644 --- a/Mathlib/MeasureTheory/OuterMeasure/Caratheodory.lean +++ b/Mathlib/MeasureTheory/OuterMeasure/Caratheodory.lean @@ -148,7 +148,7 @@ theorem f_iUnion {s : ℕ → Set α} (h : ∀ i, IsCaratheodory m (s i)) (hd : simp only [inter_comm, inter_univ, univ_inter] at this; simp only [this] exact m.mono (iUnion₂_subset fun i _ => subset_iUnion _ i) -/-- The Carathéodory-measurable sets for an outer measure `m` form a Dynkin system. -/ +/-- The Carathéodory-measurable sets for an outer measure `m` form a Dynkin system. -/ def caratheodoryDynkin : MeasurableSpace.DynkinSystem α where Has := IsCaratheodory m has_empty := isCaratheodory_empty m diff --git a/Mathlib/MeasureTheory/OuterMeasure/Induced.lean b/Mathlib/MeasureTheory/OuterMeasure/Induced.lean index b1dd27d6be85b..d28e4da40ac3e 100644 --- a/Mathlib/MeasureTheory/OuterMeasure/Induced.lean +++ b/Mathlib/MeasureTheory/OuterMeasure/Induced.lean @@ -409,7 +409,7 @@ and `m₃ s`. -/ theorem trim_binop {m₁ m₂ m₃ : OuterMeasure α} {op : ℝ≥0∞ → ℝ≥0∞ → ℝ≥0∞} (h : ∀ s, m₁ s = op (m₂ s) (m₃ s)) (s : Set α) : m₁.trim s = op (m₂.trim s) (m₃.trim s) := by rcases exists_measurable_superset_forall_eq_trim ![m₁, m₂, m₃] s with ⟨t, _hst, _ht, htm⟩ - simp only [Fin.forall_fin_succ, Matrix.cons_val_zero, Matrix.cons_val_succ] at htm + simp only [Fin.forall_iff_succ, Matrix.cons_val_zero, Matrix.cons_val_succ] at htm rw [← htm.1, ← htm.2.1, ← htm.2.2.1, h] /-- If `m₁ s = op (m₂ s)` for all `s`, then the same is true for `m₁.trim` and `m₂.trim`. -/ diff --git a/Mathlib/MeasureTheory/OuterMeasure/OfFunction.lean b/Mathlib/MeasureTheory/OuterMeasure/OfFunction.lean index 9bdbbdf07b9ed..a6c90472f6f46 100644 --- a/Mathlib/MeasureTheory/OuterMeasure/OfFunction.lean +++ b/Mathlib/MeasureTheory/OuterMeasure/OfFunction.lean @@ -46,11 +46,11 @@ section OfFunction -- Porting note: "set_option eqn_compiler.zeta true" removed -variable {α : Type*} (m : Set α → ℝ≥0∞) (m_empty : m ∅ = 0) +variable {α : Type*} -/-- Given any function `m` assigning measures to sets satisying `m ∅ = 0`, there is +/-- Given any function `m` assigning measures to sets satisfying `m ∅ = 0`, there is a unique maximal outer measure `μ` satisfying `μ s ≤ m s` for all `s : Set α`. -/ -protected def ofFunction : OuterMeasure α := +protected def ofFunction (m : Set α → ℝ≥0∞) (m_empty : m ∅ = 0) : OuterMeasure α := let μ s := ⨅ (f : ℕ → Set α) (_ : s ⊆ ⋃ i, f i), ∑' i, m (f i) { measureOf := μ empty := @@ -86,10 +86,35 @@ protected def ofFunction : OuterMeasure α := intro j apply subset_iUnion₂ i } +variable (m : Set α → ℝ≥0∞) (m_empty : m ∅ = 0) + +/-- `ofFunction` of a set `s` is the infimum of `∑ᵢ, m (tᵢ)` for all collections of sets +`tᵢ` that cover `s`. -/ theorem ofFunction_apply (s : Set α) : OuterMeasure.ofFunction m m_empty s = ⨅ (t : ℕ → Set α) (_ : s ⊆ iUnion t), ∑' n, m (t n) := rfl +/-- `ofFunction` of a set `s` is the infimum of `∑ᵢ, m (tᵢ)` for all collections of sets +`tᵢ` that cover `s`, with all `tᵢ` satisfying a predicate `P` such that `m` is infinite for sets +that don't satisfy `P`. +This is similar to `ofFunction_apply`, except that the sets `tᵢ` satisfy `P`. +The hypothesis `m_top` applies in particular to a function of the form `extend m'`. -/ +theorem ofFunction_eq_iInf_mem {P : Set α → Prop} (m_top : ∀ s, ¬ P s → m s = ∞) (s : Set α) : + OuterMeasure.ofFunction m m_empty s = + ⨅ (t : ℕ → Set α) (_ : ∀ i, P (t i)) (_ : s ⊆ ⋃ i, t i), ∑' i, m (t i) := by + rw [OuterMeasure.ofFunction_apply] + apply le_antisymm + · exact le_iInf fun t ↦ le_iInf fun _ ↦ le_iInf fun h ↦ iInf₂_le _ (by exact h) + · simp_rw [le_iInf_iff] + refine fun t ht_subset ↦ iInf_le_of_le t ?_ + by_cases ht : ∀ i, P (t i) + · exact iInf_le_of_le ht (iInf_le_of_le ht_subset le_rfl) + · simp only [ht, not_false_eq_true, iInf_neg, top_le_iff] + push_neg at ht + obtain ⟨i, hti_not_mem⟩ := ht + have hfi_top : m (t i) = ∞ := m_top _ hti_not_mem + exact ENNReal.tsum_eq_top_of_eq_top ⟨i, hfi_top⟩ + variable {m m_empty} theorem ofFunction_le (s : Set α) : OuterMeasure.ofFunction m m_empty s ≤ m s := @@ -126,7 +151,7 @@ theorem ofFunction_eq_sSup : OuterMeasure.ofFunction m m_empty = sSup { μ | ∀ E.g., if `α` is an (e)metric space and `m u = ∞` on any set of diameter `≥ r`, then this lemma implies that `μ (s ∪ t) = μ s + μ t` on any two sets such that `r ≤ edist x y` for all `x ∈ s` -and `y ∈ t`. -/ +and `y ∈ t`. -/ theorem ofFunction_union_of_top_of_nonempty_inter {s t : Set α} (h : ∀ u, (s ∩ u).Nonempty → (t ∩ u).Nonempty → m u = ∞) : OuterMeasure.ofFunction m m_empty (s ∪ t) = @@ -289,7 +314,7 @@ theorem comap_boundedBy {β} (f : β → α) E.g., if `α` is an (e)metric space and `m u = ∞` on any set of diameter `≥ r`, then this lemma implies that `μ (s ∪ t) = μ s + μ t` on any two sets such that `r ≤ edist x y` for all `x ∈ s` -and `y ∈ t`. -/ +and `y ∈ t`. -/ theorem boundedBy_union_of_top_of_nonempty_inter {s t : Set α} (h : ∀ u, (s ∩ u).Nonempty → (t ∩ u).Nonempty → m u = ∞) : boundedBy m (s ∪ t) = boundedBy m s + boundedBy m t := diff --git a/Mathlib/MeasureTheory/PiSystem.lean b/Mathlib/MeasureTheory/PiSystem.lean index f00e51c4094e7..eb36ea8a28489 100644 --- a/Mathlib/MeasureTheory/PiSystem.lean +++ b/Mathlib/MeasureTheory/PiSystem.lean @@ -207,25 +207,25 @@ theorem subset_generatePiSystem_self {α} (S : Set (Set α)) : S ⊆ generatePiS theorem generatePiSystem_subset_self {α} {S : Set (Set α)} (h_S : IsPiSystem S) : generatePiSystem S ⊆ S := fun x h => by - induction' h with _ h_s s u _ _ h_nonempty h_s h_u - · exact h_s - · exact h_S _ h_s _ h_u h_nonempty + induction h with + | base h_s => exact h_s + | inter _ _ h_nonempty h_s h_u => exact h_S _ h_s _ h_u h_nonempty theorem generatePiSystem_eq {α} {S : Set (Set α)} (h_pi : IsPiSystem S) : generatePiSystem S = S := Set.Subset.antisymm (generatePiSystem_subset_self h_pi) (subset_generatePiSystem_self S) theorem generatePiSystem_mono {α} {S T : Set (Set α)} (hST : S ⊆ T) : generatePiSystem S ⊆ generatePiSystem T := fun t ht => by - induction' ht with s h_s s u _ _ h_nonempty h_s h_u - · exact generatePiSystem.base (Set.mem_of_subset_of_mem hST h_s) - · exact isPiSystem_generatePiSystem T _ h_s _ h_u h_nonempty + induction ht with + | base h_s => exact generatePiSystem.base (Set.mem_of_subset_of_mem hST h_s) + | inter _ _ h_nonempty h_s h_u => exact isPiSystem_generatePiSystem T _ h_s _ h_u h_nonempty theorem generatePiSystem_measurableSet {α} [M : MeasurableSpace α] {S : Set (Set α)} (h_meas_S : ∀ s ∈ S, MeasurableSet s) (t : Set α) (h_in_pi : t ∈ generatePiSystem S) : MeasurableSet t := by - induction' h_in_pi with s h_s s u _ _ _ h_s h_u - · apply h_meas_S _ h_s - · apply MeasurableSet.inter h_s h_u + induction h_in_pi with + | base h_s => apply h_meas_S _ h_s + | inter _ _ _ h_s h_u => apply MeasurableSet.inter h_s h_u theorem generateFrom_measurableSet_of_generatePiSystem {α} {g : Set (Set α)} (t : Set α) (ht : t ∈ generatePiSystem g) : MeasurableSet[generateFrom g] t := diff --git a/Mathlib/MeasureTheory/SetSemiring.lean b/Mathlib/MeasureTheory/SetSemiring.lean index c17719e996a4f..5da29e8340326 100644 --- a/Mathlib/MeasureTheory/SetSemiring.lean +++ b/Mathlib/MeasureTheory/SetSemiring.lean @@ -313,9 +313,10 @@ lemma biInter_mem {ι : Type*} (hC : IsSetRing C) {s : ι → Set α} (S : Finset ι) (hS : S.Nonempty) (hs : ∀ n ∈ S, s n ∈ C) : ⋂ i ∈ S, s i ∈ C := by classical - induction' hS using Finset.Nonempty.cons_induction with _ i S hiS _ h hs - · simpa using hs - · simp_rw [← Finset.mem_coe, Finset.coe_cons, Set.biInter_insert] + induction hS using Finset.Nonempty.cons_induction with + | singleton => simpa using hs + | cons i S hiS _ h => + simp_rw [← Finset.mem_coe, Finset.coe_cons, Set.biInter_insert] simp only [cons_eq_insert, Finset.mem_insert, forall_eq_or_imp] at hs refine hC.inter_mem hs.1 ?_ exact h (fun n hnS ↦ hs.2 n hnS) diff --git a/Mathlib/ModelTheory/Algebra/Field/IsAlgClosed.lean b/Mathlib/ModelTheory/Algebra/Field/IsAlgClosed.lean new file mode 100644 index 0000000000000..2d7efbda8ea35 --- /dev/null +++ b/Mathlib/ModelTheory/Algebra/Field/IsAlgClosed.lean @@ -0,0 +1,252 @@ +/- +Copyright (c) 2023 Chris Hughes. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Chris Hughes +-/ + +import Mathlib.Data.Nat.PrimeFin +import Mathlib.FieldTheory.IsAlgClosed.AlgebraicClosure +import Mathlib.FieldTheory.IsAlgClosed.Classification +import Mathlib.ModelTheory.Algebra.Field.CharP +import Mathlib.ModelTheory.Satisfiability + +/-! + +# The First Order Theory of Algebraically Closed Fields + +This file defines the theory of algebraically closed fields of characteristic `p`, as well +as proving completeness of the theory and the Lefschetz Principle. + +## Main definitions + +* `FirstOrder.Language.Theory.ACF p` : the theory of algebraically closed fields of characteristic + `p` as a theory over the language of rings. +* `FirstOrder.Field.ACF_isComplete` : the theory of algebraically closed fields of characteristic + `p` is complete whenever `p` is prime or zero. +* `FirstOrder.Field.ACF_zero_realize_iff_infinite_ACF_prime_realize` : the Lefschetz principle. + +## Implementation details + +To apply a theorem about the model theory of algebraically closed fields to a specific +algebraically closed field `K` which does not have a `Language.ring.Structure` instance, +you must introduce the local instance `compatibleRingOfRing K`. Theorems whose statement requires +both a `Language.ring.Structure` instance and a `Field` instance will all be stated with the +assumption `Field K`, `CharP K p`, `IsAlgClosed K` and `CompatibleRing K` and there are instances +defined saying that these assumptions imply `Theory.field.Model K` and `(Theory.ACF p).Model K` + +## References + +The first order theory of algebraically closed fields, along with the Lefschetz Principle and +the Ax-Grothendieck Theorem were first formalized in Lean 3 by Joseph Hua +[here](https://github.com/Jlh18/ModelTheoryInLean8) with the master's thesis +[here](https://github.com/Jlh18/ModelTheory8Report) + +-/ + +variable {K : Type*} + +namespace FirstOrder + +namespace Field + +open Ring FreeCommRing BigOperators Polynomial Language + +/-- A generic monic polynomial of degree `n` as an element of the +free commutative ring in `n+1` variables, with a variable for each +of the `n` non-leading coefficients of the polynomial and one variable (`Fin.last n`) +for `X`. -/ +def genericMonicPoly (n : ℕ) : FreeCommRing (Fin (n + 1)) := + of (Fin.last _) ^ n + ∑ i : Fin n, of i.castSucc * of (Fin.last _) ^ (i : ℕ) + +theorem lift_genericMonicPoly [CommRing K] [Nontrivial K] {n : ℕ} (v : Fin (n+1) → K) : + FreeCommRing.lift v (genericMonicPoly n) = + (((monicEquivDegreeLT n).trans (degreeLTEquiv K n).toEquiv).symm (v ∘ Fin.castSucc)).1.eval + (v (Fin.last _)) := by + simp only [genericMonicPoly, map_add, map_pow, lift_of, map_sum, map_mul, monicEquivDegreeLT, + degreeLTEquiv, Equiv.symm_trans_apply, LinearEquiv.coe_toEquiv_symm, EquivLike.coe_coe, + LinearEquiv.coe_symm_mk, Function.comp_apply, Equiv.coe_fn_symm_mk, eval_add, eval_pow, eval_X, + eval_finset_sum, eval_monomial] + +/-- A sentence saying every monic polynomial of degree `n` has a root. -/ +noncomputable def genericMonicPolyHasRoot (n : ℕ) : Language.ring.Sentence := + (∃' ((termOfFreeCommRing (genericMonicPoly n)).relabel Sum.inr =' 0)).alls + +theorem realize_genericMonicPolyHasRoot [Field K] [CompatibleRing K] (n : ℕ) : + K ⊨ genericMonicPolyHasRoot n ↔ + ∀ p : { p : K[X] // p.Monic ∧ p.natDegree = n }, ∃ x, p.1.eval x = 0 := by + let _ := Classical.decEq K + rw [Equiv.forall_congr_left ((monicEquivDegreeLT n).trans (degreeLTEquiv K n).toEquiv)] + simp [Sentence.Realize, genericMonicPolyHasRoot, lift_genericMonicPoly] + +/-- The theory of algebraically closed fields of characteristic `p` as a theory over +the language of rings -/ +def _root_.FirstOrder.Language.Theory.ACF (p : ℕ) : Theory .ring := + Theory.fieldOfChar p ∪ genericMonicPolyHasRoot '' {n | 0 < n} + +instance [Language.ring.Structure K] (p : ℕ) [h : (Theory.ACF p).Model K] : + (Theory.fieldOfChar p).Model K := + Theory.Model.mono h Set.subset_union_left + +instance [Field K] [CompatibleRing K] {p : ℕ} [CharP K p] [IsAlgClosed K] : + (Theory.ACF p).Model K := by + refine Theory.model_union_iff.2 ⟨inferInstance, ?_⟩ + simp only [Theory.model_iff, Set.mem_image, Set.mem_singleton_iff, + exists_prop, forall_exists_index, and_imp] + rintro _ n hn0 rfl + simp only [realize_genericMonicPolyHasRoot] + rintro ⟨p, _, rfl⟩ + exact IsAlgClosed.exists_root p (ne_of_gt + (natDegree_pos_iff_degree_pos.1 hn0)) + +theorem modelField_of_modelACF (p : ℕ) (K : Type*) [Language.ring.Structure K] + [h : (Theory.ACF p).Model K] : Theory.field.Model K := + Theory.Model.mono h (Set.subset_union_of_subset_left Set.subset_union_left _) + +/-- A model for the Theory of algebraically closed fields is a Field. After introducing +this as a local instance on a particular Type, you should usually also introduce +`modelField_of_modelACF p M`, `compatibleRingOfModelField` and `isAlgClosed_of_model_ACF` -/ +@[reducible] +noncomputable def fieldOfModelACF (p : ℕ) (K : Type*) + [Language.ring.Structure K] + [h : (Theory.ACF p).Model K] : Field K := by + have := modelField_of_modelACF p K + exact fieldOfModelField K + +theorem isAlgClosed_of_model_ACF (p : ℕ) (K : Type*) + [Field K] [CompatibleRing K] [h : (Theory.ACF p).Model K] : + IsAlgClosed K := by + refine IsAlgClosed.of_exists_root _ ?_ + intro p hpm hpi + have h : K ⊨ genericMonicPolyHasRoot '' {n | 0 < n} := + Theory.Model.mono h (by simp [Theory.ACF]) + simp only [Theory.model_iff, Set.mem_image, Set.mem_singleton_iff, + exists_prop, forall_exists_index, and_imp] at h + have := h _ p.natDegree (natDegree_pos_iff_degree_pos.2 + (degree_pos_of_irreducible hpi)) rfl + rw [realize_genericMonicPolyHasRoot] at this + exact this ⟨_, hpm, rfl⟩ + +theorem ACF_isSatisfiable {p : ℕ} (hp : p.Prime ∨ p = 0) : + (Theory.ACF p).IsSatisfiable := by + cases hp with + | inl hp => + have : Fact p.Prime := ⟨hp⟩ + let _ := compatibleRingOfRing (AlgebraicClosure (ZMod p)) + have : CharP (AlgebraicClosure (ZMod p)) p := + charP_of_injective_algebraMap + (RingHom.injective (algebraMap (ZMod p) (AlgebraicClosure (ZMod p)))) p + exact ⟨⟨AlgebraicClosure (ZMod p)⟩⟩ + | inr hp => + subst hp + let _ := compatibleRingOfRing (AlgebraicClosure ℚ) + have : CharP (AlgebraicClosure ℚ) 0 := + charP_of_injective_algebraMap + (RingHom.injective (algebraMap ℚ (AlgebraicClosure ℚ))) 0 + exact ⟨⟨AlgebraicClosure ℚ⟩⟩ + +open Cardinal + +/-- The Theory `Theory.ACF p` is `κ`-categorical whenever `κ` is an uncountable cardinal. +At the moment this is not as universe polymorphic as it could be, +it currently requires `κ : Cardinal.{0}`, but it is true for any universe. -/ +theorem ACF_categorical {p : ℕ} (κ : Cardinal.{0}) (hκ : ℵ₀ < κ) : + Categorical κ (Theory.ACF p) := by + rintro ⟨M⟩ ⟨N⟩ hM hN + let _ := fieldOfModelACF p M + have := modelField_of_modelACF p M + let _ := compatibleRingOfModelField M + have := isAlgClosed_of_model_ACF p M + have := charP_of_model_fieldOfChar p M + let _ := fieldOfModelACF p N + have := modelField_of_modelACF p N + let _ := compatibleRingOfModelField N + have := isAlgClosed_of_model_ACF p N + have := charP_of_model_fieldOfChar p N + constructor + refine languageEquivEquivRingEquiv.symm ?_ + apply Classical.choice + refine IsAlgClosed.ringEquivOfCardinalEqOfCharEq p ?_ ?_ + · rw [hM]; exact hκ + · rw [hM, hN] + +theorem ACF_isComplete {p : ℕ} (hp : p.Prime ∨ p = 0) : + (Theory.ACF p).IsComplete := by + apply Categorical.isComplete.{0, 0, 0} (Order.succ ℵ₀) _ + (ACF_categorical _ (Order.lt_succ _)) + (Order.le_succ ℵ₀) + · simp only [card_ring, lift_id'] + exact le_trans (le_of_lt (lt_aleph0_of_finite _)) (Order.le_succ _) + · exact ACF_isSatisfiable hp + · rintro ⟨M⟩ + let _ := fieldOfModelACF p M + have := modelField_of_modelACF p M + let _ := compatibleRingOfModelField M + have := isAlgClosed_of_model_ACF p M + infer_instance + +theorem finite_ACF_prime_not_realize_of_ACF_zero_realize + (φ : Language.ring.Sentence) (h : Theory.ACF 0 ⊨ᵇ φ) : + Set.Finite { p : Nat.Primes | ¬ Theory.ACF p ⊨ᵇ φ } := by + rw [Theory.models_iff_finset_models] at h + rcases h with ⟨T0, hT0, h⟩ + have f : ∀ ψ ∈ Theory.ACF 0, + { s : Finset Nat.Primes // ∀ q : Nat.Primes, q ∉ s → Theory.ACF q ⊨ᵇ ψ } := by + intro ψ hψ + rw [Theory.ACF, Theory.fieldOfChar, Set.union_right_comm, Set.mem_union, if_pos rfl, + Set.mem_image] at hψ + apply Classical.choice + rcases hψ with h | ⟨p, hp, rfl⟩ + · refine ⟨⟨∅, ?_⟩⟩ + intro q _ + exact Theory.models_sentence_of_mem + (by rw [Theory.ACF, Theory.fieldOfChar, Set.union_right_comm]; + exact Set.mem_union_left _ h) + · refine ⟨⟨{⟨p, hp⟩}, ?_⟩⟩ + rintro ⟨q, _⟩ hq ⟨K⟩ _ _ + have hqp : q ≠ p := by simpa [← Nat.Primes.coe_nat_inj] using hq + let _ := fieldOfModelACF q K + have := modelField_of_modelACF q K + let _ := compatibleRingOfModelField K + have := charP_of_model_fieldOfChar q K + simp only [eqZero, Term.equal, Term.relabel, BoundedFormula.realize_not, + BoundedFormula.realize_bdEqual, Term.realize_relabel, Sum.elim_comp_inl, + realize_termOfFreeCommRing, map_natCast, Term.realize_func, CompatibleRing.funMap_zero, + ne_eq, ← CharP.charP_iff_prime_eq_zero hp] + intro _ + exact hqp <| CharP.eq K inferInstance inferInstance + let s : Finset Nat.Primes := T0.attach.biUnion (fun φ => f φ.1 (hT0 φ.2)) + have hs : ∀ (p : Nat.Primes) ψ, ψ ∈ T0 → p ∉ s → Theory.ACF p ⊨ᵇ ψ := by + intro p ψ hψ hpψ + simp only [s, Finset.mem_biUnion, Finset.mem_attach, true_and, + Subtype.exists, not_exists] at hpψ + exact (f ψ (hT0 hψ)).2 p (hpψ _ hψ) + refine Set.Finite.subset (Finset.finite_toSet s) (Set.compl_subset_comm.2 ?_) + intro p hp + exact Theory.models_of_models_theory (fun ψ hψ => hs p ψ hψ hp) h + +/-- The **Lefschetz principle**. A first order sentence is modeled by the theory +of algebraically closed fields of characteristic zero if and only if it is modeled by +the theory of algebraically closed fields of characteristic `p` for infinitely many `p`. -/ +theorem ACF_zero_realize_iff_infinite_ACF_prime_realize {φ : Language.ring.Sentence} : + Theory.ACF 0 ⊨ᵇ φ ↔ Set.Infinite { p : Nat.Primes | Theory.ACF p ⊨ᵇ φ } := by + refine ⟨fun h => Set.infinite_of_finite_compl + (finite_ACF_prime_not_realize_of_ACF_zero_realize φ h), + not_imp_not.1 ?_⟩ + simpa [(ACF_isComplete (Or.inr rfl)).models_not_iff, + fun p : Nat.Primes => (ACF_isComplete (Or.inl p.2)).models_not_iff] using + finite_ACF_prime_not_realize_of_ACF_zero_realize φ.not + +/-- Another statement of the **Lefschetz principle**. A first order sentence is modeled by the +theory of algebraically closed fields of characteristic zero if and only if it is modeled by the +theory of algebraically closed fields of characteristic `p` for all but finitely many primes `p`. +-/ +theorem ACF_zero_realize_iff_finite_ACF_prime_not_realize {φ : Language.ring.Sentence} : + Theory.ACF 0 ⊨ᵇ φ ↔ Set.Finite { p : Nat.Primes | Theory.ACF p ⊨ᵇ φ }ᶜ := + ⟨fun h => finite_ACF_prime_not_realize_of_ACF_zero_realize φ h, + fun h => ACF_zero_realize_iff_infinite_ACF_prime_realize.2 + (Set.infinite_of_finite_compl h)⟩ + + +end Field + +end FirstOrder diff --git a/Mathlib/ModelTheory/Algebra/Ring/Basic.lean b/Mathlib/ModelTheory/Algebra/Ring/Basic.lean index 34291af0a1546..2a839ffd63d95 100644 --- a/Mathlib/ModelTheory/Algebra/Ring/Basic.lean +++ b/Mathlib/ModelTheory/Algebra/Ring/Basic.lean @@ -59,6 +59,7 @@ inductive ringFunc : ℕ → Type def Language.ring : Language := { Functions := ringFunc Relations := fun _ => Empty } + deriving IsAlgebraic namespace Ring @@ -225,7 +226,6 @@ def compatibleRingOfRing (R : Type*) [Add R] [Mul R] [Neg R] [One R] [Zero R] : | _, .neg => fun x => -x 0 | _, .zero => fun _ => 0 | _, .one => fun _ => 1 - RelMap := Empty.elim, funMap_add := fun _ => rfl, funMap_mul := fun _ => rfl, funMap_neg := fun _ => rfl, diff --git a/Mathlib/ModelTheory/Basic.lean b/Mathlib/ModelTheory/Basic.lean index e5610d623e310..b94652cfe073f 100644 --- a/Mathlib/ModelTheory/Basic.lean +++ b/Mathlib/ModelTheory/Basic.lean @@ -110,19 +110,26 @@ unary and binary relations. -/ protected def mk₂ (c f₁ f₂ : Type u) (r₁ r₂ : Type v) : Language := ⟨Sequence₂ c f₁ f₂, Sequence₂ PEmpty r₁ r₂⟩ +variable (L : Language.{u, v}) + +/-- A language is relational when it has no function symbols. -/ +abbrev IsRelational : Prop := ∀ n, IsEmpty (L.Functions n) + +/-- A language is algebraic when it has no relation symbols. -/ +abbrev IsAlgebraic := ∀ n, IsEmpty (L.Relations n) + /-- The empty language has no symbols. -/ protected def empty : Language := ⟨fun _ => Empty, fun _ => Empty⟩ + deriving IsAlgebraic, IsRelational instance : Inhabited Language := ⟨Language.empty⟩ /-- The sum of two languages consists of the disjoint union of their symbols. -/ -protected def sum (L : Language.{u, v}) (L' : Language.{u', v'}) : Language := +protected def sum (L' : Language.{u', v'}) : Language := ⟨fun n => L.Functions n ⊕ L'.Functions n, fun n => L.Relations n ⊕ L'.Relations n⟩ -variable (L : Language.{u, v}) - /-- The type of constants in a given language. -/ -- Porting note(#5171): this linter isn't ported yet. -- @[nolint has_nonempty_instance] @@ -144,16 +151,6 @@ def Symbols := def card : Cardinal := #L.Symbols -/-- A language is relational when it has no function symbols. -/ -class IsRelational : Prop where - /-- There are no function symbols in the language. -/ - empty_functions : ∀ n, IsEmpty (L.Functions n) - -/-- A language is algebraic when it has no relation symbols. -/ -class IsAlgebraic : Prop where - /-- There are no relation symbols in the language. -/ - empty_relations : ∀ n, IsEmpty (L.Relations n) - variable {L} {L' : Language.{u', v'}} theorem card_eq_card_functions_add_card_relations : @@ -162,42 +159,23 @@ theorem card_eq_card_functions_add_card_relations : Cardinal.sum fun l => Cardinal.lift.{u} #(L.Relations l) := by simp [card, Symbols] -instance [L.IsRelational] {n : ℕ} : IsEmpty (L.Functions n) := - IsRelational.empty_functions n - -instance [L.IsAlgebraic] {n : ℕ} : IsEmpty (L.Relations n) := - IsAlgebraic.empty_relations n - -instance isRelational_of_empty_functions {symb : ℕ → Type*} : - IsRelational ⟨fun _ => Empty, symb⟩ := - ⟨fun _ => instIsEmptyEmpty⟩ - -instance isAlgebraic_of_empty_relations {symb : ℕ → Type*} : IsAlgebraic ⟨symb, fun _ => Empty⟩ := - ⟨fun _ => instIsEmptyEmpty⟩ - -instance isRelational_empty : IsRelational Language.empty := - Language.isRelational_of_empty_functions - -instance isAlgebraic_empty : IsAlgebraic Language.empty := - Language.isAlgebraic_of_empty_relations - instance isRelational_sum [L.IsRelational] [L'.IsRelational] : IsRelational (L.sum L') := - ⟨fun _ => instIsEmptySum⟩ + fun _ => instIsEmptySum instance isAlgebraic_sum [L.IsAlgebraic] [L'.IsAlgebraic] : IsAlgebraic (L.sum L') := - ⟨fun _ => instIsEmptySum⟩ + fun _ => instIsEmptySum instance isRelational_mk₂ {c f₁ f₂ : Type u} {r₁ r₂ : Type v} [h0 : IsEmpty c] [h1 : IsEmpty f₁] [h2 : IsEmpty f₂] : IsRelational (Language.mk₂ c f₁ f₂ r₁ r₂) := - ⟨fun n => + fun n => Nat.casesOn n h0 fun n => Nat.casesOn n h1 fun n => Nat.casesOn n h2 fun _ => - inferInstanceAs (IsEmpty PEmpty)⟩ + inferInstanceAs (IsEmpty PEmpty) instance isAlgebraic_mk₂ {c f₁ f₂ : Type u} {r₁ r₂ : Type v} [h1 : IsEmpty r₁] [h2 : IsEmpty r₂] : IsAlgebraic (Language.mk₂ c f₁ f₂ r₁ r₂) := - ⟨fun n => + fun n => Nat.casesOn n (inferInstanceAs (IsEmpty PEmpty)) fun n => - Nat.casesOn n h1 fun n => Nat.casesOn n h2 fun _ => inferInstanceAs (IsEmpty PEmpty)⟩ + Nat.casesOn n h1 fun n => Nat.casesOn n h2 fun _ => inferInstanceAs (IsEmpty PEmpty) instance subsingleton_mk₂_functions {c f₁ f₂ : Type u} {r₁ r₂ : Type v} [h0 : Subsingleton c] [h1 : Subsingleton f₁] [h2 : Subsingleton f₂] {n : ℕ} : @@ -248,13 +226,13 @@ theorem card_mk₂ (c f₁ f₂ : Type u) (r₁ r₂ : Type v) : /-- Passes a `DecidableEq` instance on a type of function symbols through the `Language` constructor. Despite the fact that this is proven by `inferInstance`, it is still needed - -see the `example`s in `ModelTheory/Ring/Basic`. -/ +see the `example`s in `ModelTheory/Ring/Basic`. -/ instance instDecidableEqFunctions {f : ℕ → Type*} {R : ℕ → Type*} (n : ℕ) [DecidableEq (f n)] : DecidableEq ((⟨f, R⟩ : Language).Functions n) := inferInstance /-- Passes a `DecidableEq` instance on a type of relation symbols through the `Language` constructor. Despite the fact that this is proven by `inferInstance`, it is still needed - -see the `example`s in `ModelTheory/Ring/Basic`. -/ +see the `example`s in `ModelTheory/Ring/Basic`. -/ instance instDecidableEqRelations {f : ℕ → Type*} {R : ℕ → Type*} (n : ℕ) [DecidableEq (R n)] : DecidableEq ((⟨f, R⟩ : Language).Relations n) := inferInstance @@ -267,9 +245,11 @@ variable (L) (M : Type w) @[ext] class Structure where /-- Interpretation of the function symbols -/ - funMap : ∀ {n}, L.Functions n → (Fin n → M) → M + funMap : ∀ {n}, L.Functions n → (Fin n → M) → M := by + exact fun {n} => isEmptyElim /-- Interpretation of the relation symbols -/ - RelMap : ∀ {n}, L.Relations n → (Fin n → M) → Prop + RelMap : ∀ {n}, L.Relations n → (Fin n → M) → Prop := by + exact fun {n} => isEmptyElim variable (N : Type w') [L.Structure M] [L.Structure N] @@ -429,7 +409,7 @@ instance (priority := 100) StrongHomClass.homClass {F : Type*} [L.Structure M] theorem HomClass.strongHomClassOfIsAlgebraic [L.IsAlgebraic] {F M N} [L.Structure M] [L.Structure N] [FunLike F M N] [HomClass L F M N] : StrongHomClass L F M N where map_fun := HomClass.map_fun - map_rel _ n R _ := (IsAlgebraic.empty_relations n).elim R + map_rel _ _ := isEmptyElim theorem HomClass.map_constants {F M N} [L.Structure M] [L.Structure N] [FunLike F M N] [HomClass L F M N] (φ : F) (c : L.Constants) : φ c = c := @@ -526,7 +506,7 @@ theorem id_comp (f : M →[L] N) : (id L N).comp f = f := end Hom /-- Any element of a `HomClass` can be realized as a first_order homomorphism. -/ -def HomClass.toHom {F M N} [L.Structure M] [L.Structure N] [FunLike F M N] +@[simps] def HomClass.toHom {F M N} [L.Structure M] [L.Structure N] [FunLike F M N] [HomClass L F M N] : F → M →[L] N := fun φ => ⟨φ, HomClass.map_fun φ, HomClass.map_rel φ⟩ @@ -681,7 +661,7 @@ theorem refl_toHom : (refl L M).toHom = Hom.id L M := end Embedding /-- Any element of an injective `StrongHomClass` can be realized as a first_order embedding. -/ -def StrongHomClass.toEmbedding {F M N} [L.Structure M] [L.Structure N] [FunLike F M N] +@[simps] def StrongHomClass.toEmbedding {F M N} [L.Structure M] [L.Structure N] [FunLike F M N] [EmbeddingLike F M N] [StrongHomClass L F M N] : F → M ↪[L] N := fun φ => ⟨⟨φ, EmbeddingLike.injective φ⟩, StrongHomClass.map_fun φ, StrongHomClass.map_rel φ⟩ @@ -895,7 +875,7 @@ theorem comp_right_inj (h : M ≃[L] N) (f g : N ≃[L] P) : f.comp h = g.comp h end Equiv /-- Any element of a bijective `StrongHomClass` can be realized as a first_order isomorphism. -/ -def StrongHomClass.toEquiv {F M N} [L.Structure M] [L.Structure N] [EquivLike F M N] +@[simps] def StrongHomClass.toEquiv {F M N} [L.Structure M] [L.Structure N] [EquivLike F M N] [StrongHomClass L F M N] : F → M ≃[L] N := fun φ => ⟨⟨φ, EquivLike.inv φ, EquivLike.left_inv φ, EquivLike.right_inv φ⟩, StrongHomClass.map_fun φ, StrongHomClass.map_rel φ⟩ @@ -934,14 +914,23 @@ end SumStructure section Empty -section +/-- Any type can be made uniquely into a structure over the empty language. -/ +def emptyStructure : Language.empty.Structure M where + +instance : Unique (Language.empty.Structure M) := + ⟨⟨Language.emptyStructure⟩, fun a => by + ext _ f <;> exact Empty.elim f⟩ variable [Language.empty.Structure M] [Language.empty.Structure N] +instance (priority := 100) strongHomClassEmpty {F} [FunLike F M N] : + StrongHomClass Language.empty F M N := + ⟨fun _ _ f => Empty.elim f, fun _ _ r => Empty.elim r⟩ + @[simp] theorem empty.nonempty_embedding_iff : Nonempty (M ↪[Language.empty] N) ↔ Cardinal.lift.{w'} #M ≤ Cardinal.lift.{w} #N := - _root_.trans ⟨Nonempty.map fun f => f.toEmbedding, Nonempty.map fun f => { toEmbedding := f }⟩ + _root_.trans ⟨Nonempty.map fun f => f.toEmbedding, Nonempty.map StrongHomClass.toEmbedding⟩ Cardinal.lift_mk_le'.symm @[simp] @@ -950,47 +939,12 @@ theorem empty.nonempty_equiv_iff : _root_.trans ⟨Nonempty.map fun f => f.toEquiv, Nonempty.map fun f => { toEquiv := f }⟩ Cardinal.lift_mk_eq'.symm -end - -instance emptyStructure : Language.empty.Structure M := - ⟨Empty.elim, Empty.elim⟩ - -instance : Unique (Language.empty.Structure M) := - ⟨⟨Language.emptyStructure⟩, fun a => by - ext _ f <;> exact Empty.elim f⟩ - -instance (priority := 100) strongHomClassEmpty {F M N} [FunLike F M N] : - StrongHomClass Language.empty F M N := - ⟨fun _ _ f => Empty.elim f, fun _ _ r => Empty.elim r⟩ - -/-- Makes a `Language.empty.Hom` out of any function. -/ +/-- Makes a `Language.empty.Hom` out of any function. +This is only needed because there is no instance of `FunLike (M → N) M N`, and thus no instance of +`Language.empty.HomClass M N`. -/ @[simps] def _root_.Function.emptyHom (f : M → N) : M →[Language.empty] N where toFun := f -/-- Makes a `Language.empty.Embedding` out of any function. -/ ---@[simps] Porting note: commented out and lemmas added manually -def _root_.Embedding.empty (f : M ↪ N) : M ↪[Language.empty] N where toEmbedding := f - -@[simp] -theorem toFun_embedding_empty (f : M ↪ N) : (Embedding.empty f : M → N) = f := - rfl - -@[simp] -theorem toEmbedding_embedding_empty (f : M ↪ N) : (Embedding.empty f).toEmbedding = f := - rfl - -/-- Makes a `Language.empty.Equiv` out of any function. -/ ---@[simps] Porting note: commented out and lemmas added manually -def _root_.Equiv.empty (f : M ≃ N) : M ≃[Language.empty] N where toEquiv := f - -@[simp] -theorem toFun_equiv_empty (f : M ≃ N) : (Equiv.empty f : M → N) = f := - rfl - -@[simp] -theorem toEquiv_equiv_empty (f : M ≃ N) : (Equiv.empty f).toEquiv = f := - rfl - end Empty end Language diff --git a/Mathlib/ModelTheory/Bundled.lean b/Mathlib/ModelTheory/Bundled.lean index 9b260af7fec41..a480f4b745cd0 100644 --- a/Mathlib/ModelTheory/Bundled.lean +++ b/Mathlib/ModelTheory/Bundled.lean @@ -111,7 +111,8 @@ def equivInduced {M : ModelType.{u, v, w} T} {N : Type w'} (e : M ≃ N) : ModelType.{u, v, w'} T where Carrier := N struc := e.inducedStructure - is_model := @Equiv.theory_model L M N _ e.inducedStructure T e.inducedStructureEquiv _ + is_model := @StrongHomClass.theory_model L M N _ e.inducedStructure T + _ _ _ e.inducedStructureEquiv _ nonempty' := e.symm.nonempty instance of_small (M : Type w) [Nonempty M] [L.Structure M] [M ⊨ T] [h : Small.{w'} M] : diff --git a/Mathlib/ModelTheory/Complexity.lean b/Mathlib/ModelTheory/Complexity.lean index e51cf9755ab1a..4cf25f2b26ea4 100644 --- a/Mathlib/ModelTheory/Complexity.lean +++ b/Mathlib/ModelTheory/Complexity.lean @@ -79,19 +79,31 @@ theorem IsAtomic.isQF {φ : L.BoundedFormula α n} : IsAtomic φ → IsQF φ := theorem isQF_bot : IsQF (⊥ : L.BoundedFormula α n) := IsQF.falsum -theorem IsQF.not {φ : L.BoundedFormula α n} (h : IsQF φ) : IsQF φ.not := +namespace IsQF + +theorem not {φ : L.BoundedFormula α n} (h : IsQF φ) : IsQF φ.not := h.imp isQF_bot -theorem IsQF.relabel {m : ℕ} {φ : L.BoundedFormula α m} (h : φ.IsQF) (f : α → β ⊕ (Fin n)) : +theorem top : IsQF (⊤ : L.BoundedFormula α n) := isQF_bot.not + +theorem sup {φ ψ : L.BoundedFormula α n} (hφ : IsQF φ) (hψ : IsQF ψ) : IsQF (φ ⊔ ψ) := + hφ.not.imp hψ + +theorem inf {φ ψ : L.BoundedFormula α n} (hφ : IsQF φ) (hψ : IsQF ψ) : IsQF (φ ⊓ ψ) := + (hφ.imp hψ.not).not + +protected theorem relabel {m : ℕ} {φ : L.BoundedFormula α m} (h : φ.IsQF) (f : α → β ⊕ (Fin n)) : (φ.relabel f).IsQF := IsQF.recOn h isQF_bot (fun h => (h.relabel f).isQF) fun _ _ h1 h2 => h1.imp h2 -theorem IsQF.liftAt {k m : ℕ} (h : IsQF φ) : (φ.liftAt k m).IsQF := +protected theorem liftAt {k m : ℕ} (h : IsQF φ) : (φ.liftAt k m).IsQF := IsQF.recOn h isQF_bot (fun ih => ih.liftAt.isQF) fun _ _ ih1 ih2 => ih1.imp ih2 -theorem IsQF.castLE {h : l ≤ n} (hφ : IsQF φ) : (φ.castLE h).IsQF := +protected theorem castLE {h : l ≤ n} (hφ : IsQF φ) : (φ.castLE h).IsQF := IsQF.recOn hφ isQF_bot (fun ih => ih.castLE.isQF) fun _ _ ih1 ih2 => ih1.imp ih2 +end IsQF + theorem not_all_isQF (φ : L.BoundedFormula α (n + 1)) : ¬φ.all.IsQF := fun con => by cases' con with _ con exact φ.not_all_isAtomic con @@ -157,11 +169,10 @@ theorem IsQF.toPrenexImpRight {φ : L.BoundedFormula α n} : theorem isPrenex_toPrenexImpRight {φ ψ : L.BoundedFormula α n} (hφ : IsQF φ) (hψ : IsPrenex ψ) : IsPrenex (φ.toPrenexImpRight ψ) := by - induction' hψ with _ _ hψ _ _ _ ih1 _ _ _ ih2 - · rw [hψ.toPrenexImpRight] - exact (hφ.imp hψ).isPrenex - · exact (ih1 hφ.liftAt).all - · exact (ih2 hφ.liftAt).ex + induction hψ with + | of_isQF hψ => rw [hψ.toPrenexImpRight]; exact (hφ.imp hψ).isPrenex + | all _ ih1 => exact (ih1 hφ.liftAt).all + | ex _ ih2 => exact (ih2 hφ.liftAt).ex -- Porting note: universes in different order /-- An auxiliary operation to `FirstOrder.Language.BoundedFormula.toPrenex`. @@ -184,11 +195,10 @@ theorem IsQF.toPrenexImp : theorem isPrenex_toPrenexImp {φ ψ : L.BoundedFormula α n} (hφ : IsPrenex φ) (hψ : IsPrenex ψ) : IsPrenex (φ.toPrenexImp ψ) := by - induction' hφ with _ _ hφ _ _ _ ih1 _ _ _ ih2 - · rw [hφ.toPrenexImp] - exact isPrenex_toPrenexImpRight hφ hψ - · exact (ih1 hψ.liftAt).ex - · exact (ih2 hψ.liftAt).all + induction hφ with + | of_isQF hφ => rw [hφ.toPrenexImp]; exact isPrenex_toPrenexImpRight hφ hψ + | all _ ih1 => exact (ih1 hψ.liftAt).ex + | ex _ ih2 => exact (ih2 hψ.liftAt).all -- Porting note: universes in different order /-- For any bounded formula `φ`, `φ.toPrenex` is a semantically-equivalent formula in prenex normal @@ -210,12 +220,14 @@ variable [Nonempty M] theorem realize_toPrenexImpRight {φ ψ : L.BoundedFormula α n} (hφ : IsQF φ) (hψ : IsPrenex ψ) {v : α → M} {xs : Fin n → M} : (φ.toPrenexImpRight ψ).Realize v xs ↔ (φ.imp ψ).Realize v xs := by - induction' hψ with _ _ hψ _ _ _hψ ih _ _ _hψ ih - · rw [hψ.toPrenexImpRight] - · refine _root_.trans (forall_congr' fun _ => ih hφ.liftAt) ?_ + induction hψ with + | of_isQF hψ => rw [hψ.toPrenexImpRight] + | all _ ih => + refine _root_.trans (forall_congr' fun _ => ih hφ.liftAt) ?_ simp only [realize_imp, realize_liftAt_one_self, snoc_comp_castSucc, realize_all] exact ⟨fun h1 a h2 => h1 h2 a, fun h1 h2 a => h1 a h2⟩ - · unfold toPrenexImpRight + | ex _ ih => + unfold toPrenexImpRight rw [realize_ex] refine _root_.trans (exists_congr fun _ => ih hφ.liftAt) ?_ simp only [realize_imp, realize_liftAt_one_self, snoc_comp_castSucc, realize_ex] @@ -231,10 +243,14 @@ theorem realize_toPrenexImpRight {φ ψ : L.BoundedFormula α n} (hφ : IsQF φ) theorem realize_toPrenexImp {φ ψ : L.BoundedFormula α n} (hφ : IsPrenex φ) (hψ : IsPrenex ψ) {v : α → M} {xs : Fin n → M} : (φ.toPrenexImp ψ).Realize v xs ↔ (φ.imp ψ).Realize v xs := by revert ψ - induction' hφ with _ _ hφ _ _ _hφ ih _ _ _hφ ih <;> intro ψ hψ - · rw [hφ.toPrenexImp] + induction hφ with + | of_isQF hφ => + intro ψ hψ + rw [hφ.toPrenexImp] exact realize_toPrenexImpRight hφ hψ - · unfold toPrenexImp + | all _ ih => + intro ψ hψ + unfold toPrenexImp rw [realize_ex] refine _root_.trans (exists_congr fun _ => ih hψ.liftAt) ?_ simp only [realize_imp, realize_liftAt_one_self, snoc_comp_castSucc, realize_all] @@ -246,20 +262,24 @@ theorem realize_toPrenexImp {φ ψ : L.BoundedFormula α n} (hφ : IsPrenex φ) exact ⟨default, fun _h'' => h⟩ · obtain ⟨a, ha⟩ := not_forall.1 (h ∘ h') exact ⟨a, fun h => (ha h).elim⟩ - · refine _root_.trans (forall_congr' fun _ => ih hψ.liftAt) ?_ + | ex _ ih => + intro ψ hψ + refine _root_.trans (forall_congr' fun _ => ih hψ.liftAt) ?_ simp @[simp] theorem realize_toPrenex (φ : L.BoundedFormula α n) {v : α → M} : ∀ {xs : Fin n → M}, φ.toPrenex.Realize v xs ↔ φ.Realize v xs := by - induction' φ with _ _ _ _ _ _ _ _ _ f1 f2 h1 h2 _ _ h - · exact Iff.rfl - · exact Iff.rfl - · exact Iff.rfl - · intros + induction φ with + | falsum => exact Iff.rfl + | equal => exact Iff.rfl + | rel => exact Iff.rfl + | imp f1 f2 h1 h2 => + intros rw [toPrenex, realize_toPrenexImp f1.toPrenex_isPrenex f2.toPrenex_isPrenex, realize_imp, realize_imp, h1, h2] - · intros + | all _ h => + intros rw [realize_all, toPrenex, realize_all] exact forall_congr' fun a => h @@ -299,10 +319,10 @@ theorem induction_on_all_ex {P : ∀ {m}, L.BoundedFormula α m → Prop} (φ : suffices h' : ∀ {m} {φ : L.BoundedFormula α m}, φ.IsPrenex → P φ from (hse φ.semanticallyEquivalent_toPrenex).2 (h' φ.toPrenex_isPrenex) intro m φ hφ - induction' hφ with _ _ hφ _ _ _ hφ _ _ _ hφ - · exact hqf hφ - · exact hall hφ - · exact hex hφ + induction hφ with + | of_isQF hφ => exact hqf hφ + | all _ hφ => exact hall hφ + | ex _ hφ => exact hex hφ theorem induction_on_exists_not {P : ∀ {m}, L.BoundedFormula α m → Prop} (φ : L.BoundedFormula α n) (hqf : ∀ {m} {ψ : L.BoundedFormula α m}, IsQF ψ → P ψ) @@ -315,8 +335,145 @@ theorem induction_on_exists_not {P : ∀ {m}, L.BoundedFormula α m → Prop} ( (fun {_ φ} hφ => (hse φ.all_semanticallyEquivalent_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 +quantifier-free formula. -/ +inductive IsUniversal : ∀ {n}, L.BoundedFormula α n → Prop + | of_isQF {n} {φ : L.BoundedFormula α n} (h : IsQF φ) : IsUniversal φ + | all {n} {φ : L.BoundedFormula α (n + 1)} (h : IsUniversal φ) : IsUniversal φ.all + +lemma IsQF.isUniversal {φ : L.BoundedFormula α n} : IsQF φ → IsUniversal φ := + IsUniversal.of_isQF + +lemma IsAtomic.isUniversal {φ : L.BoundedFormula α n} (h : IsAtomic φ) : IsUniversal φ := + h.isQF.isUniversal + +/-- An existential formula is a formula defined by applying only existential quantifiers to a +quantifier-free formula. -/ +inductive IsExistential : ∀ {n}, L.BoundedFormula α n → Prop + | of_isQF {n} {φ : L.BoundedFormula α n} (h : IsQF φ) : IsExistential φ + | ex {n} {φ : L.BoundedFormula α (n + 1)} (h : IsExistential φ) : IsExistential φ.ex + +lemma IsQF.isExistential {φ : L.BoundedFormula α n} : IsQF φ → IsExistential φ := + IsExistential.of_isQF + +lemma IsAtomic.isExistential {φ : L.BoundedFormula α n} (h : IsAtomic φ) : IsExistential φ := + h.isQF.isExistential + +section Preservation + +variable {M : Type*} [L.Structure M] {N : Type*} [L.Structure N] +variable {F : Type*} [FunLike F M N] + +lemma IsAtomic.realize_comp_of_injective {φ : L.BoundedFormula α n} (hA : φ.IsAtomic) + [L.HomClass F M N] {f : F} (hInj : Function.Injective f) {v : α → M} {xs : Fin n → M} : + φ.Realize v xs → φ.Realize (f ∘ v) (f ∘ xs) := by + induction hA with + | equal t₁ t₂ => simp only [realize_bdEqual, ← Sum.comp_elim, HomClass.realize_term, hInj.eq_iff, + imp_self] + | rel R ts => + simp only [realize_rel, ← Sum.comp_elim, HomClass.realize_term] + exact HomClass.map_rel f R (fun i => Term.realize (Sum.elim v xs) (ts i)) + +lemma IsAtomic.realize_comp {φ : L.BoundedFormula α n} (hA : φ.IsAtomic) + [EmbeddingLike F M N] [L.HomClass F M N] (f : F) {v : α → M} {xs : Fin n → M} : + φ.Realize v xs → φ.Realize (f ∘ v) (f ∘ xs) := + hA.realize_comp_of_injective (EmbeddingLike.injective f) + +variable [EmbeddingLike F M N] [L.StrongHomClass F M N] + +lemma IsQF.realize_embedding {φ : L.BoundedFormula α n} (hQF : φ.IsQF) + (f : F) {v : α → M} {xs : Fin n → M} : + φ.Realize (f ∘ v) (f ∘ xs) ↔ φ.Realize v xs := by + induction hQF with + | falsum => rfl + | of_isAtomic hA => induction hA with + | equal t₁ t₂ => simp only [realize_bdEqual, ← Sum.comp_elim, HomClass.realize_term, + (EmbeddingLike.injective f).eq_iff] + | rel R ts => + simp only [realize_rel, ← Sum.comp_elim, HomClass.realize_term] + exact StrongHomClass.map_rel f R (fun i => Term.realize (Sum.elim v xs) (ts i)) + | imp _ _ ihφ ihψ => simp only [realize_imp, ihφ, ihψ] + +lemma IsUniversal.realize_embedding {φ : L.BoundedFormula α n} (hU : φ.IsUniversal) + (f : F) {v : α → M} {xs : Fin n → M} : + φ.Realize (f ∘ v) (f ∘ xs) → φ.Realize v xs := by + induction hU with + | of_isQF hQF => simp [hQF.realize_embedding] + | all _ ih => + simp only [realize_all, Nat.succ_eq_add_one] + refine fun h a => ih ?_ + rw [Fin.comp_snoc] + exact h (f a) + +lemma IsExistential.realize_embedding {φ : L.BoundedFormula α n} (hE : φ.IsExistential) + (f : F) {v : α → M} {xs : Fin n → M} : + φ.Realize v xs → φ.Realize (f ∘ v) (f ∘ xs) := by + induction hE with + | of_isQF hQF => simp [hQF.realize_embedding] + | ex _ ih => + simp only [realize_ex, Nat.succ_eq_add_one] + refine fun ⟨a, ha⟩ => ⟨f a, ?_⟩ + rw [← Fin.comp_snoc] + exact ih ha + +end Preservation + end BoundedFormula +/-- A theory is universal when it is comprised only of universal sentences - these theories apply +also to substructures. -/ +class Theory.IsUniversal (T : L.Theory) : Prop where + isUniversal_of_mem : ∀ ⦃φ⦄, φ ∈ T → φ.IsUniversal + +lemma Theory.IsUniversal.models_of_embedding {T : L.Theory} [hT : T.IsUniversal] + {N : Type*} [L.Structure N] [N ⊨ T] (f : M ↪[L] N) : M ⊨ T := by + simp only [model_iff] + refine fun φ hφ => (hT.isUniversal_of_mem hφ).realize_embedding f (?_) + rw [Subsingleton.elim (f ∘ default) default, Subsingleton.elim (f ∘ default) default] + exact Theory.realize_sentence_of_mem T hφ + +instance Substructure.models_of_isUniversal + (S : L.Substructure M) (T : L.Theory) [T.IsUniversal] [M ⊨ T] : S ⊨ T := + Theory.IsUniversal.models_of_embedding (Substructure.subtype S) + +lemma Theory.IsUniversal.insert + {T : L.Theory} [hT : T.IsUniversal] {φ : L.Sentence} (hφ : φ.IsUniversal) : + (insert φ T).IsUniversal := ⟨by + simp only [Set.mem_insert_iff, forall_eq_or_imp, hφ, true_and] + exact hT.isUniversal_of_mem⟩ + +namespace Relations + +open BoundedFormula + +lemma isAtomic (r : L.Relations l) (ts : Fin l → L.Term (α ⊕ (Fin n))) : + IsAtomic (r.boundedFormula ts) := IsAtomic.rel r ts + +lemma isQF (r : L.Relations l) (ts : Fin l → L.Term (α ⊕ (Fin n))) : + IsQF (r.boundedFormula ts) := (r.isAtomic ts).isQF + +variable (r : L.Relations 2) + +protected lemma isUniversal_reflexive : r.reflexive.IsUniversal := + (r.isQF _).isUniversal.all + +protected lemma isUniversal_irreflexive : r.irreflexive.IsUniversal := + (r.isAtomic _).isQF.not.isUniversal.all + +protected lemma isUniversal_symmetric : r.symmetric.IsUniversal := + ((r.isQF _).imp (r.isQF _)).isUniversal.all.all + +protected lemma isUniversal_antisymmetric : r.antisymmetric.IsUniversal := + ((r.isQF _).imp ((r.isQF _).imp (IsAtomic.equal _ _).isQF)).isUniversal.all.all + +protected lemma isUniversal_transitive : r.transitive.IsUniversal := + ((r.isQF _).imp ((r.isQF _).imp (r.isQF _))).isUniversal.all.all.all + +protected lemma isUniversal_total : r.total.IsUniversal := + ((r.isQF _).sup (r.isQF _)).isUniversal.all.all + +end Relations + theorem Formula.isAtomic_graph (f : L.Functions n) : (Formula.graph f).IsAtomic := BoundedFormula.IsAtomic.equal _ _ diff --git a/Mathlib/ModelTheory/DirectLimit.lean b/Mathlib/ModelTheory/DirectLimit.lean index 09c8d5f5ddb8e..a9c1fe39191e1 100644 --- a/Mathlib/ModelTheory/DirectLimit.lean +++ b/Mathlib/ModelTheory/DirectLimit.lean @@ -330,14 +330,14 @@ theorem exists_fg_substructure_in_Sigma (S : L.Substructure (DirectLimit G f)) ( rw [← image_univ, image_image, image_univ, ← eq_y, Subtype.range_coe_subtype, Finset.setOf_mem, A_closure] -variable {P : Type u₁} [L.Structure P] (g : ∀ i, G i ↪[L] P) -variable (Hg : ∀ i j hij x, g j (f i j hij x) = g i x) -variable (L ι G f) +variable {P : Type u₁} [L.Structure P] +variable (L ι G f) in /-- The universal property of the direct limit: maps from the components to another module that respect the directed system structure (i.e. make some diagram commute) give rise to a unique map out of the direct limit. -/ -def lift : DirectLimit G f ↪[L] P where +def lift (g : ∀ i, G i ↪[L] P) (Hg : ∀ i j hij x, g j (f i j hij x) = g i x) : + DirectLimit G f ↪[L] P where toFun := Quotient.lift (fun x : Σˣ f => (g x.1) x.2) fun x y xy => by simp only @@ -363,7 +363,7 @@ def lift : DirectLimit G f ↪[L] P where Quotient.lift_comp_mk] rfl -variable {L ι G f} +variable (g : ∀ i, G i ↪[L] P) (Hg : ∀ i j hij x, g j (f i j hij x) = g i x) @[simp] theorem lift_quotient_mk'_sigma_mk' {i} (x : G i) : lift L ι G f g Hg ⟦.mk f i x⟧ = (g i) x := by @@ -388,11 +388,11 @@ variable (L ι G f) variable (G' : ι → Type w') [∀ i, L.Structure (G' i)] variable (f' : ∀ i j, i ≤ j → G' i ↪[L] G' j) variable (g : ∀ i, G i ≃[L] G' i) -variable (H_commuting : ∀ i j hij x, g j (f i j hij x) = f' i j hij (g i x)) variable [DirectedSystem G' fun i j h => f' i j h] /-- The isomorphism between limits of isomorphic systems. -/ -noncomputable def equiv_lift : DirectLimit G f ≃[L] DirectLimit G' f' := by +noncomputable def equiv_lift (H_commuting : ∀ i j hij x, g j (f i j hij x) = f' i j hij (g i x)) : + DirectLimit G f ≃[L] DirectLimit G' f' := by let U i : G i ↪[L] DirectLimit G' f' := (of L _ G' f' i).comp (g i).toEmbedding let F : DirectLimit G f ↪[L] DirectLimit G' f' := lift L _ G f U <| by intro _ _ _ _ @@ -405,6 +405,8 @@ noncomputable def equiv_lift : DirectLimit G f ≃[L] DirectLimit G' f' := by rfl exact ⟨Equiv.ofBijective F ⟨F.injective, surj_f⟩, F.map_fun', F.map_rel'⟩ +variable (H_commuting : ∀ i j hij x, g j (f i j hij x) = f' i j hij (g i x)) + theorem equiv_lift_of {i : ι} (x : G i) : equiv_lift L ι G f G' f' g H_commuting (of L ι G f i x) = of L ι G' f' i (g i x) := rfl diff --git a/Mathlib/ModelTheory/ElementaryMaps.lean b/Mathlib/ModelTheory/ElementaryMaps.lean index 9c25fd43ecb9e..ea469044e0dc8 100644 --- a/Mathlib/ModelTheory/ElementaryMaps.lean +++ b/Mathlib/ModelTheory/ElementaryMaps.lean @@ -224,7 +224,7 @@ def ElementaryEmbedding.ofModelsElementaryDiagram (N : Type*) [L.Structure N] [L (Constants.term ∘ Sum.inr ∘ x)).alls).trans ?_) · simp_rw [Sentence.Realize, BoundedFormula.realize_alls, BoundedFormula.realize_subst, - LHom.realize_onBoundedFormula, Formula.Realize, Unique.forall_iff, Function.comp, + LHom.realize_onBoundedFormula, Formula.Realize, Unique.forall_iff, Function.comp_def, Term.realize_constants] · simp_rw [Sentence.Realize, BoundedFormula.realize_alls, BoundedFormula.realize_subst, LHom.realize_onBoundedFormula, Formula.Realize, Unique.forall_iff] @@ -248,9 +248,9 @@ theorem isElementary_of_exists (f : M ↪[L] N) refine fun n φ => φ.recOn ?_ ?_ ?_ ?_ ?_ · exact fun {_} _ => Iff.rfl · intros - simp [BoundedFormula.Realize, ← Sum.comp_elim, Embedding.realize_term] + simp [BoundedFormula.Realize, ← Sum.comp_elim, HomClass.realize_term] · intros - simp only [BoundedFormula.Realize, ← Sum.comp_elim, realize_term] + simp only [BoundedFormula.Realize, ← Sum.comp_elim, HomClass.realize_term] erw [map_rel f] · intro _ _ _ ih1 ih2 _ simp [ih1, ih2] @@ -301,7 +301,7 @@ end Equiv @[simp] theorem realize_term_substructure {α : Type*} {S : L.Substructure M} (v : α → S) (t : L.Term α) : t.realize ((↑) ∘ v) = (↑(t.realize v) : M) := - S.subtype.realize_term t + HomClass.realize_term S.subtype end Language diff --git a/Mathlib/ModelTheory/Encoding.lean b/Mathlib/ModelTheory/Encoding.lean index 4c7fe629d2236..98775b13439f3 100644 --- a/Mathlib/ModelTheory/Encoding.lean +++ b/Mathlib/ModelTheory/Encoding.lean @@ -132,8 +132,8 @@ theorem card_sigma : #(Σn, L.Term (α ⊕ (Fin n))) = max ℵ₀ #(α ⊕ (Σi, · simp only [Sum.elim_inl, Sigma.mk.inj_iff, heq_eq_eq, var.injEq, Sum.inl.injEq, true_and] at h rw [h] - · simp only [Sum.elim_inl, Sum.elim_inr, Sigma.mk.inj_iff, false_and] at h - · simp only [Sum.elim_inr, Sum.elim_inl, Sigma.mk.inj_iff, false_and] at h + · simp only [Sum.elim_inl, Sum.elim_inr, Sigma.mk.inj_iff, false_and, reduceCtorEq] at h + · simp only [Sum.elim_inr, Sum.elim_inl, Sigma.mk.inj_iff, false_and, reduceCtorEq] at h · simp only [Sum.elim_inr, Sigma.mk.inj_iff, heq_eq_eq, func.injEq, true_and] at h rw [Sigma.ext_iff.2 ⟨h.1, h.2.1⟩] @@ -227,12 +227,16 @@ theorem listDecode_encode_list (l : List (Σn, L.BoundedFormula α n)) : simp [listDecode] · rw [bind_cons, h φ _, ih] rintro ⟨n, φ⟩ - induction' φ with _ _ _ _ φ_n φ_l φ_R ts _ _ _ ih1 ih2 _ _ ih <;> intro l - · rw [listEncode, singleton_append, listDecode] - · rw [listEncode, cons_append, cons_append, listDecode, dif_pos] + induction φ with + | falsum => intro l; rw [listEncode, singleton_append, listDecode] + | equal => + intro l + rw [listEncode, cons_append, cons_append, listDecode, dif_pos] · simp only [eq_mp_eq_cast, cast_eq, eq_self_iff_true, heq_iff_eq, and_self_iff, nil_append] · simp only [eq_self_iff_true, heq_iff_eq, and_self_iff] - · rw [listEncode, cons_append, cons_append, singleton_append, cons_append, listDecode] + | @rel φ_n φ_l φ_R ts => + intro l + rw [listEncode, cons_append, cons_append, singleton_append, cons_append, listDecode] have h : ∀ i : Fin φ_l, ((List.map Sum.getLeft? (List.map (fun i : Fin φ_l => Sum.inl (⟨(⟨φ_n, rel φ_R ts⟩ : Σn, L.BoundedFormula α n).fst, ts i⟩ : Σn, L.Term (α ⊕ (Fin n)))) (finRange φ_l) ++ l)).get? ↑i).join = some ⟨_, ts i⟩ := by @@ -260,11 +264,15 @@ theorem listDecode_encode_list (l : List (Σn, L.BoundedFormula α n)) : rw [List.drop_append_eq_append_drop, length_map, length_finRange, Nat.sub_self, drop, drop_eq_nil_of_le, nil_append] rw [length_map, length_finRange] - · simp only [] at * + | imp _ _ ih1 ih2 => + intro l + simp only [] at * rw [listEncode, List.append_assoc, cons_append, listDecode] simp only [ih1, ih2, length_cons, le_add_iff_nonneg_left, _root_.zero_le, ↓reduceDIte, getElem_cons_zero, getElem_cons_succ, sigmaImp_apply, drop_succ_cons, drop_zero] - · simp only [] at * + | all _ ih => + intro l + simp only [] at * rw [listEncode, cons_append, listDecode] simp only [ih, length_cons, le_add_iff_nonneg_left, _root_.zero_le, ↓reduceDIte, getElem_cons_zero, sigmaAll_apply, drop_succ_cons, drop_zero] diff --git a/Mathlib/ModelTheory/FinitelyGenerated.lean b/Mathlib/ModelTheory/FinitelyGenerated.lean index 744fe0e4c4f1c..634921b6fb8b5 100644 --- a/Mathlib/ModelTheory/FinitelyGenerated.lean +++ b/Mathlib/ModelTheory/FinitelyGenerated.lean @@ -92,6 +92,18 @@ theorem FG.of_map_embedding {N : Type*} [L.Structure N] (f : M ↪[L] N) {s : L. rw [h] at h' exact Hom.map_le_range h' +theorem FG.of_finite {s : L.Substructure M} [h : Finite s] : s.FG := + ⟨Set.Finite.toFinset h, by simp only [Finite.coe_toFinset, closure_eq]⟩ + +theorem FG.finite [L.IsRelational] {S : L.Substructure M} (h : S.FG) : Finite S := by + obtain ⟨s, rfl⟩ := h + have hs := s.finite_toSet + rw [← ((closure L).mem_closed_iff _).1 (mem_closed_of_isRelational L (↑s : Set M))] at hs + exact hs + +theorem fg_iff_finite [L.IsRelational] {S : L.Substructure M} : S.FG ↔ Finite S := + ⟨FG.finite, fun _ => FG.of_finite⟩ + /-- A substructure of `M` is countably generated if it is the closure of a countable subset of `M`. -/ def CG (N : L.Substructure M) : Prop := @@ -172,7 +184,6 @@ open Substructure namespace Structure - variable (L) (M) /-- A structure is finitely generated if it is the closure of a finite subset. -/ @@ -227,6 +238,15 @@ instance Fg.instCountable_embedding (N : Type*) [L.Structure N] [Countable N] [h : FG L M] : Countable (M ↪[L] N) := FG.countable_embedding N h +theorem FG.of_finite [Finite M] : FG L M := by + simp only [fg_def, Substructure.FG.of_finite, topEquiv.toEquiv.finite_iff] + +theorem FG.finite [L.IsRelational] (h : FG L M) : Finite M := + Finite.of_finite_univ (Substructure.FG.finite (fg_def.1 h)) + +theorem fg_iff_finite [L.IsRelational] : FG L M ↔ Finite M := + ⟨FG.finite, fun _ => FG.of_finite⟩ + theorem cg_def : CG L M ↔ (⊤ : L.Substructure M).CG := ⟨fun h => h.1, fun h => ⟨h⟩⟩ diff --git a/Mathlib/ModelTheory/Fraisse.lean b/Mathlib/ModelTheory/Fraisse.lean index c0f806f87aaa1..cfb2a070bf89f 100644 --- a/Mathlib/ModelTheory/Fraisse.lean +++ b/Mathlib/ModelTheory/Fraisse.lean @@ -42,8 +42,12 @@ Fraïssé limit - the countable ultrahomogeneous structure with that age. essentially countable. - `FirstOrder.Language.exists_countable_is_age_of_iff` gives necessary and sufficient conditions for a class to be the age of a countable structure in a language with countably many functions. -- `FirstOrder.Language.IsFraisseLimit.nonempty_equiv` shows that any class which is Fraïsse has - at most one Fraïsse limit up to equivalence. +- `FirstOrder.Language.IsFraisseLimit.nonempty_equiv` shows that any class which is Fraïssé has + at most one Fraïssé limit up to equivalence. +- `FirstOrder.Language.empty.isFraisseLimit_of_countable_infinite` shows that any countably infinite + structure in the empty language is a Fraïssé limit of the class of finite structures. +- `FirstOrder.Language.empty.isFraisse_finite` shows that the class of finite structures in the + empty language is Fraïssé. ## Implementation Notes @@ -77,7 +81,7 @@ open Structure Substructure variable (L : Language.{u, v}) -/-! ### The Age of a Structure and Fraïssé Classes-/ +/-! ### The Age of a Structure and Fraïssé Classes -/ /-- The age of a structure `M` is the class of finitely-generated structures that embed into it. -/ @@ -88,7 +92,7 @@ variable {L} variable (K : Set (Bundled.{w} L.Structure)) /-- A class `K` has the hereditary property when all finitely-generated structures that embed into - structures in `K` are also in `K`. -/ + structures in `K` are also in `K`. -/ def Hereditary : Prop := ∀ M : Bundled.{w} L.Structure, M ∈ K → L.age M ⊆ K @@ -300,8 +304,8 @@ theorem IsUltrahomogeneous.extend_embedding (M_homog : L.IsUltrahomogeneous M) { Equiv.coe_toHom, Embedding.coe_toHom, coeSubtype] at eq' simp only [Embedding.comp_apply, ← eq', Equiv.coe_toEmbedding, EmbeddingLike.apply_eq_iff_eq] apply (Embedding.equivRange (Embedding.comp r g)).injective - simp only [Equiv.apply_symm_apply] - rfl + ext + simp only [Equiv.apply_symm_apply, Embedding.equivRange_apply, s] /-- A countably generated structure is ultrahomogeneous if and only if any equivalence between finitely generated substructures can be extended to any element in the domain.-/ @@ -382,8 +386,8 @@ protected theorem isExtensionPair : L.IsExtensionPair M N := by ((subtype f.cod).comp f.toEquiv.toEmbedding) (inclusion (le_sup_left : _ ≤ S)) refine ⟨⟨⟨S, g.toHom.range, g.equivRange⟩, S_FG⟩, subset_closure.trans (le_sup_right : _ ≤ S) (mem_singleton m), ⟨le_sup_left, ?_⟩⟩ - simp only [Subtype.mk_le_mk, PartialEquiv.le_def, g_eq] - rfl + ext + simp [Subtype.mk_le_mk, PartialEquiv.le_def, g_eq] /-- The Fraïssé limit of a class is unique, in that any two Fraïssé limits are isomorphic. -/ theorem nonempty_equiv : Nonempty (M ≃[L] N) := by @@ -403,6 +407,35 @@ theorem nonempty_equiv : Nonempty (M ≃[L] N) := by end IsFraisseLimit +namespace empty + +/-- Any countable infinite structure in the empty language is a Fraïssé limit of the class of finite +structures. -/ +theorem isFraisseLimit_of_countable_infinite + (M : Type*) [Countable M] [Infinite M] [Language.empty.Structure M] : + IsFraisseLimit { S : Bundled Language.empty.Structure | Finite S } M where + age := by + ext S + simp only [age, Structure.fg_iff_finite, mem_setOf_eq, and_iff_left_iff_imp] + intro hS + simp + ultrahomogeneous S hS f := by + classical + have : Finite S := hS.finite + have : Infinite { x // x ∉ S } := ((Set.toFinite _).infinite_compl).to_subtype + have : Finite f.toHom.range := (((Substructure.fg_iff_structure_fg S).1 hS).range _).finite + have : Infinite { x // x ∉ f.toHom.range } := ((Set.toFinite _).infinite_compl ).to_subtype + refine ⟨StrongHomClass.toEquiv (f.equivRange.subtypeCongr nonempty_equiv_of_countable.some), ?_⟩ + ext x + simp [Equiv.subtypeCongr] + +/-- The class of finite structures in the empty language is Fraïssé. -/ +theorem isFraisse_finite : IsFraisse { S : Bundled.{w} Language.empty.Structure | Finite S } := by + have : Language.empty.Structure (ULift ℕ : Type w) := emptyStructure + exact (isFraisseLimit_of_countable_infinite (ULift ℕ)).isFraisse + +end empty + end Language end FirstOrder diff --git a/Mathlib/ModelTheory/Graph.lean b/Mathlib/ModelTheory/Graph.lean index 06519b49d2e04..c4ce433290e9c 100644 --- a/Mathlib/ModelTheory/Graph.lean +++ b/Mathlib/ModelTheory/Graph.lean @@ -21,9 +21,7 @@ This file defines first-order languages, structures, and theories in graph theor of the theory of simple graphs. -/ - - -universe u v w w' +universe u v namespace FirstOrder @@ -33,30 +31,31 @@ open FirstOrder open Structure -variable {L : Language.{u, v}} {α : Type w} {V : Type w'} {n : ℕ} +variable {α : Type u} {V : Type v} {n : ℕ} /-! ### Simple Graphs -/ +/-- The type of relations for the language of graphs, consisting of a single binary relation `adj`. +-/ +inductive graphRel : ℕ → Type + | adj : graphRel 2 + deriving DecidableEq /-- The language consisting of a single relation representing adjacency. -/ -protected def graph : Language := - Language.mk₂ Empty Empty Empty Empty Unit +protected def graph : Language := ⟨fun _ => Empty, graphRel⟩ + deriving IsRelational /-- The symbol representing the adjacency relation. -/ -def adj : Language.graph.Relations 2 := - Unit.unit +abbrev adj : Language.graph.Relations 2 := .adj /-- Any simple graph can be thought of as a structure in the language of graphs. -/ -def _root_.SimpleGraph.structure (G : SimpleGraph V) : Language.graph.Structure V := - Structure.mk₂ Empty.elim Empty.elim Empty.elim Empty.elim fun _ => G.Adj +def _root_.SimpleGraph.structure (G : SimpleGraph V) : Language.graph.Structure V where + RelMap | .adj => (fun x => G.Adj (x 0) (x 1)) namespace graph -instance instIsRelational : IsRelational Language.graph := - Language.isRelational_mk₂ - instance instSubsingleton : Subsingleton (Language.graph.Relations n) := - Language.subsingleton_mk₂_relations + ⟨by rintro ⟨⟩ ⟨⟩; rfl⟩ end graph @@ -73,7 +72,8 @@ theorem Theory.simpleGraph_model_iff [Language.graph.Structure V] : instance simpleGraph_model (G : SimpleGraph V) : @Theory.Model _ V G.structure Theory.simpleGraph := by - simp only [@Theory.simpleGraph_model_iff _ G.structure, relMap_apply₂] + letI := G.structure + rw [Theory.simpleGraph_model_iff] exact ⟨G.loopless, G.symm⟩ variable (V) @@ -104,19 +104,14 @@ theorem structure_simpleGraphOfStructure [S : Language.graph.Structure V] [V ⊨ (simpleGraphOfStructure V).structure = S := by ext case funMap n f xs => - exact (IsRelational.empty_functions n).elim f + exact isEmptyElim f case RelMap n r xs => - rw [iff_eq_eq] - cases' n with n - · exact r.elim - · cases' n with n - · exact r.elim - · cases' n with n - · cases r - change RelMap adj ![xs 0, xs 1] = _ - refine congr rfl (funext ?_) - simp [Fin.forall_fin_two] - · exact r.elim + match n, r with + | 2, .adj => + rw [iff_eq_eq] + change RelMap adj ![xs 0, xs 1] = _ + refine congr rfl (funext ?_) + simp [Fin.forall_fin_two] theorem Theory.simpleGraph_isSatisfiable : Theory.IsSatisfiable Theory.simpleGraph := ⟨@Theory.ModelType.of _ _ Unit (SimpleGraph.structure ⊥) _ _⟩ diff --git a/Mathlib/ModelTheory/LanguageMap.lean b/Mathlib/ModelTheory/LanguageMap.lean index a70065ee3ba7e..74d72ceb05122 100644 --- a/Mathlib/ModelTheory/LanguageMap.lean +++ b/Mathlib/ModelTheory/LanguageMap.lean @@ -47,8 +47,10 @@ variable (L : Language.{u, v}) (L' : Language.{u', v'}) {M : Type w} [L.Structur /-- A language homomorphism maps the symbols of one language to symbols of another. -/ structure LHom where - onFunction : ∀ ⦃n⦄, L.Functions n → L'.Functions n - onRelation : ∀ ⦃n⦄, L.Relations n → L'.Relations n + onFunction : ∀ ⦃n⦄, L.Functions n → L'.Functions n := by + exact fun {n} => isEmptyElim + onRelation : ∀ ⦃n⦄, L.Relations n → L'.Relations n :=by + exact fun {n} => isEmptyElim @[inherit_doc FirstOrder.Language.LHom] infixl:10 " →ᴸ " => LHom @@ -97,8 +99,7 @@ variable (L L') /-- The inclusion of an empty language into any other language. -/ @[simps] -protected def ofIsEmpty [L.IsAlgebraic] [L.IsRelational] : L →ᴸ L' := - ⟨fun n => (IsRelational.empty_functions n).elim, fun n => (IsAlgebraic.empty_relations n).elim⟩ +protected def ofIsEmpty [L.IsAlgebraic] [L.IsRelational] : L →ᴸ L' where variable {L L'} {L'' : Language} @@ -219,9 +220,12 @@ noncomputable def defaultExpansion (ϕ : L →ᴸ L') /-- A language homomorphism is an expansion on a structure if it commutes with the interpretation of all symbols on that structure. -/ class IsExpansionOn (M : Type*) [L.Structure M] [L'.Structure M] : Prop where - map_onFunction : ∀ {n} (f : L.Functions n) (x : Fin n → M), funMap (ϕ.onFunction f) x = funMap f x - map_onRelation : ∀ {n} (R : L.Relations n) (x : Fin n → M), - RelMap (ϕ.onRelation R) x = RelMap R x + map_onFunction : + ∀ {n} (f : L.Functions n) (x : Fin n → M), funMap (ϕ.onFunction f) x = funMap f x := by + exact fun {n} => isEmptyElim + map_onRelation : + ∀ {n} (R : L.Relations n) (x : Fin n → M), RelMap (ϕ.onRelation R) x = RelMap R x := by + exact fun {n} => isEmptyElim @[simp] theorem map_onFunction {M : Type*} [L.Structure M] [L'.Structure M] [ϕ.IsExpansionOn M] {n} @@ -237,9 +241,7 @@ instance id_isExpansionOn (M : Type*) [L.Structure M] : IsExpansionOn (LHom.id L ⟨fun _ _ => rfl, fun _ _ => rfl⟩ instance ofIsEmpty_isExpansionOn (M : Type*) [L.Structure M] [L'.Structure M] [L.IsAlgebraic] - [L.IsRelational] : IsExpansionOn (LHom.ofIsEmpty L L') M := - ⟨fun {n} => (IsRelational.empty_functions n).elim, - fun {n} => (IsAlgebraic.empty_relations n).elim⟩ + [L.IsRelational] : IsExpansionOn (LHom.ofIsEmpty L L') M where instance sumElim_isExpansionOn {L'' : Language} (ψ : L'' →ᴸ L') (M : Type*) [L.Structure M] [L'.Structure M] [L''.Structure M] [ϕ.IsExpansionOn M] [ψ.IsExpansionOn M] : @@ -404,7 +406,7 @@ theorem card_withConstants : L[[α]].card = Cardinal.lift.{w'} L.card + Cardinal.lift.{max u v} #α := by rw [withConstants, card_sum, card_constantsOn] -/-- The language map adding constants. -/ +/-- The language map adding constants. -/ @[simps!] -- Porting note: add `!` to `simps` def lhomWithConstants : L →ᴸ L[[α]] := LHom.sumInl @@ -420,7 +422,7 @@ protected def con (a : α) : L[[α]].Constants := variable {L} (α) -/-- Adds constants to a language map. -/ +/-- Adds constants to a language map. -/ def LHom.addConstants {L' : Language} (φ : L →ᴸ L') : L[[α]] →ᴸ L'[[α]] := φ.sumMap (LHom.id _) @@ -429,7 +431,7 @@ instance paramsStructure (A : Set α) : (constantsOn A).Structure α := variable (L) -/-- The language map removing an empty constant set. -/ +/-- The language map removing an empty constant set. -/ @[simps] def LEquiv.addEmptyConstants [ie : IsEmpty α] : L ≃ᴸ L[[α]] where toLHom := lhomWithConstants L α @@ -451,7 +453,7 @@ theorem withConstants_relMap_sum_inl [L[[α]].Structure M] [(lhomWithConstants L {n} {R : L.Relations n} {x : Fin n → M} : @RelMap (L[[α]]) M _ n (Sum.inl R) x = RelMap R x := (lhomWithConstants L α).map_onRelation R x -/-- The language map extending the constant set. -/ +/-- The language map extending the constant set. -/ def lhomWithConstantsMap (f : α → β) : L[[α]] →ᴸ L[[β]] := LHom.sumMap (LHom.id L) (LHom.constantsOnMap f) diff --git a/Mathlib/ModelTheory/Order.lean b/Mathlib/ModelTheory/Order.lean index a5c6f4fce9ec4..72c9b03c099bf 100644 --- a/Mathlib/ModelTheory/Order.lean +++ b/Mathlib/ModelTheory/Order.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 Aaron Anderson. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Aaron Anderson -/ -import Mathlib.ModelTheory.Semantics +import Mathlib.ModelTheory.Complexity /-! # Ordered First-Ordered Structures @@ -36,34 +36,43 @@ namespace FirstOrder namespace Language - open FirstOrder Structure variable {L : Language.{u, v}} {α : Type w} {M : Type w'} {n : ℕ} -/-- The language consisting of a single relation representing `≤`. -/ -protected def order : Language := - Language.mk₂ Empty Empty Empty Empty Unit +/-- The type of relations for the language of orders, consisting of a single binary relation `le`. +-/ +inductive orderRel : ℕ → Type + | le : orderRel 2 + deriving DecidableEq -instance orderStructure [LE M] : Language.order.Structure M := - Structure.mk₂ Empty.elim Empty.elim Empty.elim Empty.elim fun _ => (· ≤ ·) +/-- The relational language consisting of a single relation representing `≤`. -/ +protected def order : Language := ⟨fun _ => Empty, orderRel⟩ + deriving IsRelational -namespace Order +namespace order -instance Language.instIsRelational : IsRelational Language.order := - Language.isRelational_mk₂ +@[simp] +lemma forall_relations {P : ∀ (n) (_ : Language.order.Relations n), Prop} : + (∀ {n} (R), P n R) ↔ P 2 .le := ⟨fun h => h _, fun h n R => + match n, R with + | 2, .le => h⟩ -instance Language.instSubsingleton : Subsingleton (Language.order.Relations n) := - Language.subsingleton_mk₂_relations +instance instSubsingleton : Subsingleton (Language.order.Relations n) := + ⟨by rintro ⟨⟩ ⟨⟩; rfl⟩ -end Order +end order /-- A language is ordered if it has a symbol representing `≤`. -/ class IsOrdered (L : Language.{u, v}) where + /-- The relation symbol representing `≤`. -/ leSymb : L.Relations 2 export IsOrdered (leSymb) +instance : IsOrdered Language.order := + ⟨.le⟩ + section IsOrdered variable [IsOrdered L] @@ -80,16 +89,15 @@ variable (L) /-- The language homomorphism sending the unique symbol `≤` of `Language.order` to `≤` in an ordered language. -/ -def orderLHom : Language.order →ᴸ L := - LHom.mk₂ Empty.elim Empty.elim Empty.elim Empty.elim fun _ => leSymb +def orderLHom : Language.order →ᴸ L where + onRelation | _, .le => leSymb -end IsOrdered - -instance : IsOrdered Language.order := - ⟨Unit.unit⟩ +@[simp] +lemma orderLHom_apply : (R : Language.order.Relations 2) → L.orderLHom.onRelation R = leSymb + | .le => rfl @[simp] -theorem orderLHom_leSymb [L.IsOrdered] : +theorem orderLHom_leSymb : (orderLHom L).onRelation leSymb = (leSymb : L.Relations 2) := rfl @@ -97,24 +105,30 @@ theorem orderLHom_leSymb [L.IsOrdered] : theorem orderLHom_order : orderLHom Language.order = LHom.id Language.order := LHom.funext (Subsingleton.elim _ _) (Subsingleton.elim _ _) -instance sum.instIsOrdered : IsOrdered (L.sum Language.order) := - ⟨Sum.inr IsOrdered.leSymb⟩ - -section - -variable (L) [IsOrdered L] - /-- The theory of preorders. -/ def preorderTheory : L.Theory := {leSymb.reflexive, leSymb.transitive} +instance : Theory.IsUniversal L.preorderTheory := ⟨by + simp only [preorderTheory, Set.mem_insert_iff, Set.mem_singleton_iff, forall_eq_or_imp, forall_eq] + exact ⟨leSymb.isUniversal_reflexive, leSymb.isUniversal_transitive⟩⟩ + /-- The theory of partial orders. -/ def partialOrderTheory : L.Theory := - {leSymb.reflexive, leSymb.antisymmetric, leSymb.transitive} + insert leSymb.antisymmetric L.preorderTheory + +instance : Theory.IsUniversal L.partialOrderTheory := + Theory.IsUniversal.insert leSymb.isUniversal_antisymmetric /-- The theory of linear orders. -/ def linearOrderTheory : L.Theory := - {leSymb.reflexive, leSymb.antisymmetric, leSymb.transitive, leSymb.total} + insert leSymb.total L.partialOrderTheory + +instance : Theory.IsUniversal L.linearOrderTheory := + Theory.IsUniversal.insert leSymb.isUniversal_total + +example [L.Structure M] [M ⊨ L.linearOrderTheory] (S : L.Substructure M) : + S ⊨ L.linearOrderTheory := inferInstance /-- A sentence indicating that an order has no top element: $\forall x, \exists y, \neg y \le x$. -/ @@ -135,71 +149,59 @@ def denselyOrderedSentence : L.Sentence := def dlo : L.Theory := L.linearOrderTheory ∪ {L.noTopOrderSentence, L.noBotOrderSentence, L.denselyOrderedSentence} -end +variable [L.Structure M] + +instance [h : M ⊨ L.dlo] : M ⊨ L.linearOrderTheory := h.mono Set.subset_union_left + +instance [h : M ⊨ L.linearOrderTheory] : M ⊨ L.partialOrderTheory := h.mono (Set.subset_insert _ _) + +instance [h : M ⊨ L.partialOrderTheory] : M ⊨ L.preorderTheory := h.mono (Set.subset_insert _ _) + +end IsOrdered + +instance sum.instIsOrdered : IsOrdered (L.sum Language.order) := + ⟨Sum.inr IsOrdered.leSymb⟩ variable (L M) +instance orderStructure [LE M] : Language.order.Structure M where + RelMap | .le => (fun x => x 0 ≤ x 1) + /-- A structure is ordered if its language has a `≤` symbol whose interpretation is -/ abbrev OrderedStructure [IsOrdered L] [LE M] [L.Structure M] : Prop := LHom.IsExpansionOn (orderLHom L) M variable {L M} +@[simp] +theorem relMap_leSymb [IsOrdered L] [LE M] [L.Structure M] [L.OrderedStructure M] {a b : M} : + RelMap (leSymb : L.Relations 2) ![a, b] ↔ a ≤ b := by + rw [← orderLHom_leSymb, LHom.map_onRelation] + rfl + @[simp] theorem orderedStructure_iff [IsOrdered L] [LE M] [L.Structure M] : L.OrderedStructure M ↔ LHom.IsExpansionOn (orderLHom L) M := Iff.rfl -instance orderedStructure_LE [LE M] : OrderedStructure Language.order M := by - rw [orderedStructure_iff, orderLHom_order] - exact LHom.id_isExpansionOn M - -instance model_preorder [Preorder M] : M ⊨ Language.order.preorderTheory := by - simp only [preorderTheory, Theory.model_iff, Set.mem_insert_iff, Set.mem_singleton_iff, - forall_eq_or_imp, Relations.realize_reflexive, relMap_apply₂, forall_eq, - Relations.realize_transitive] - exact ⟨le_refl, fun _ _ _ => le_trans⟩ - -instance model_partialOrder [PartialOrder M] : M ⊨ Language.order.partialOrderTheory := by - simp only [partialOrderTheory, Theory.model_iff, Set.mem_insert_iff, Set.mem_singleton_iff, - forall_eq_or_imp, Relations.realize_reflexive, relMap_apply₂, Relations.realize_antisymmetric, - forall_eq, Relations.realize_transitive] - exact ⟨le_refl, fun _ _ => le_antisymm, fun _ _ _ => le_trans⟩ +section order_to_structure -instance model_linearOrder [LinearOrder M] : M ⊨ Language.order.linearOrderTheory := by - simp only [linearOrderTheory, Theory.model_iff, Set.mem_insert_iff, Set.mem_singleton_iff, - forall_eq_or_imp, Relations.realize_reflexive, relMap_apply₂, Relations.realize_antisymmetric, - Relations.realize_transitive, forall_eq, Relations.realize_total] - exact ⟨le_refl, fun _ _ => le_antisymm, fun _ _ _ => le_trans, le_total⟩ +variable [IsOrdered L] [L.Structure M] -section OrderedStructure +section LE -variable [IsOrdered L] [L.Structure M] +variable [LE M] [L.OrderedStructure M] -@[simp] -theorem relMap_leSymb [LE M] [L.OrderedStructure M] {a b : M} : - RelMap (leSymb : L.Relations 2) ![a, b] ↔ a ≤ b := by - rw [← orderLHom_leSymb, LHom.map_onRelation] - rfl +instance orderedStructure_LE [LE M] : OrderedStructure Language.order M := by + rw [orderedStructure_iff, orderLHom_order] + exact LHom.id_isExpansionOn M @[simp] -theorem Term.realize_le [LE M] [L.OrderedStructure M] {t₁ t₂ : L.Term (α ⊕ (Fin n))} {v : α → M} +theorem Term.realize_le {t₁ t₂ : L.Term (α ⊕ (Fin n))} {v : α → M} {xs : Fin n → M} : (t₁.le t₂).Realize v xs ↔ t₁.realize (Sum.elim v xs) ≤ t₂.realize (Sum.elim v xs) := by simp [Term.le] -@[simp] -theorem Term.realize_lt [Preorder M] [L.OrderedStructure M] {t₁ t₂ : L.Term (α ⊕ (Fin n))} - {v : α → M} {xs : Fin n → M} : - (t₁.lt t₂).Realize v xs ↔ t₁.realize (Sum.elim v xs) < t₂.realize (Sum.elim v xs) := by - simp [Term.lt, lt_iff_le_not_le] - -end OrderedStructure - -section LE - -variable [LE M] - theorem realize_noTopOrder_iff : M ⊨ Language.order.noTopOrderSentence ↔ NoTopOrder M := by simp only [noTopOrderSentence, Sentence.Realize, Formula.Realize, BoundedFormula.realize_all, BoundedFormula.realize_ex, BoundedFormula.realize_not, Term.realize, Term.realize_le, @@ -225,8 +227,22 @@ theorem realize_noBotOrder [h : NoBotOrder M] : M ⊨ Language.order.noBotOrderS realize_noBotOrder_iff.2 h end LE +section Preorder + +variable [Preorder M] + +instance model_preorder : M ⊨ Language.order.preorderTheory := by + simp only [preorderTheory, Theory.model_insert_iff, Relations.realize_reflexive, relMap_leSymb, + Theory.model_singleton_iff, Relations.realize_transitive] + exact ⟨le_refl, fun _ _ _ => le_trans⟩ + +@[simp] +theorem Term.realize_lt [L.OrderedStructure M] {t₁ t₂ : L.Term (α ⊕ (Fin n))} + {v : α → M} {xs : Fin n → M} : + (t₁.lt t₂).Realize v xs ↔ t₁.realize (Sum.elim v xs) < t₂.realize (Sum.elim v xs) := by + simp [Term.lt, lt_iff_le_not_le] -theorem realize_denselyOrdered_iff [Preorder M] : +theorem realize_denselyOrdered_iff : M ⊨ Language.order.denselyOrderedSentence ↔ DenselyOrdered M := by simp only [denselyOrderedSentence, Sentence.Realize, Formula.Realize, BoundedFormula.realize_imp, BoundedFormula.realize_all, Term.realize, Term.realize_lt, @@ -236,17 +252,33 @@ theorem realize_denselyOrdered_iff [Preorder M] : exact exists_between ab @[simp] -theorem realize_denselyOrdered [Preorder M] [h : DenselyOrdered M] : +theorem realize_denselyOrdered [h : DenselyOrdered M] : M ⊨ Language.order.denselyOrderedSentence := realize_denselyOrdered_iff.2 h -instance model_dlo [LinearOrder M] [DenselyOrdered M] [NoTopOrder M] [NoBotOrder M] : +end Preorder + +instance model_partialOrder [PartialOrder M] : M ⊨ Language.order.partialOrderTheory := by + simp only [partialOrderTheory, Theory.model_insert_iff, Relations.realize_antisymmetric, + relMap_leSymb, model_preorder, and_true] + exact fun _ _ => le_antisymm + +section LinearOrder + +variable [LinearOrder M] + +instance model_linearOrder : M ⊨ Language.order.linearOrderTheory := by + simp only [linearOrderTheory, Theory.model_insert_iff, Relations.realize_total, relMap_leSymb, + model_partialOrder, and_true] + exact le_total + +instance model_dlo [DenselyOrdered M] [NoTopOrder M] [NoBotOrder M] : M ⊨ Language.order.dlo := by - simp only [dlo, Set.union_insert, Set.union_singleton, Theory.model_iff, Set.mem_insert_iff, - forall_eq_or_imp, realize_noTopOrder, realize_noBotOrder, realize_denselyOrdered, - true_and_iff] - rw [← Theory.model_iff] - infer_instance + simp [dlo, model_linearOrder, Theory.model_insert_iff] + +end LinearOrder + +end order_to_structure end Language diff --git a/Mathlib/ModelTheory/PartialEquiv.lean b/Mathlib/ModelTheory/PartialEquiv.lean index 63599f2a61b3f..564891376068c 100644 --- a/Mathlib/ModelTheory/PartialEquiv.lean +++ b/Mathlib/ModelTheory/PartialEquiv.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2024 Gabin Kolly. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Aaron Anderson, Gabin Kolly +Authors: Aaron Anderson, Gabin Kolly, David Wärn -/ import Mathlib.ModelTheory.DirectLimit import Mathlib.Order.Ideal @@ -12,7 +12,26 @@ This file defines partial isomorphisms between first-order structures. ## Main Definitions - `FirstOrder.Language.PartialEquiv` is defined so that `L.PartialEquiv M N`, annotated - `M ≃ₚ[L] N`, is the type of equivalences between substructures of `M` and `N`. + `M ≃ₚ[L] N`, is the type of equivalences between substructures of `M` and `N`. These can be + ordered, with an order that is defined here in terms of a commutative square, but could also be + defined as the order on the graphs of the partial equivalences under inclusion as subsets of + `M × N`. +- `FirstOrder.Language.FGEquiv` is the type of partial equivalences `M ≃ₚ[L] N` with + finitely-generated domain (or equivalently, codomain). +- `FirstOrder.Language.IsExtensionPair` is defined so that `L.IsExtensionPair M N` indicates that + any finitely-generated partial equivalence from `M` to `N` can be extended to include an arbitrary + element `m : M` in its domain. + +## Main Results +- `FirstOrder.Language.embedding_from_cg` shows that if structures `M` and `N` form an equivalence + pair with `M` countably-generated, then any finite-generated partial equivalence between them + can be extended to an embedding `M ↪[L] N`. +- `FirstOrder.Language.equiv_from_cg` shows that if countably-generated structures `M` and `N` form + an equivalence pair in both directions, then any finite-generated partial equivalence between them + can be extended to an isomorphism `M ↪[L] N`. +- The proofs of these results are adapted in part from David Wärn's approach to countable dense + linear orders, a special case of this phenomenon in the case where `L = Language.order`. + -/ universe u v w w' @@ -61,7 +80,7 @@ theorem symm_apply (f : M ≃ₚ[L] N) (x : f.cod) : f.symm.toEquiv x = f.toEqui rfl instance : LE (M ≃ₚ[L] N) := - ⟨fun f g ↦ ∃h : f.dom ≤ g.dom, + ⟨fun f g ↦ ∃ h : f.dom ≤ g.dom, (subtype _).comp (g.toEquiv.toEmbedding.comp (Substructure.inclusion h)) = (subtype _).comp f.toEquiv.toEmbedding⟩ @@ -282,13 +301,13 @@ open PartialEquiv variable {ι : Type*} [Preorder ι] [Nonempty ι] [IsDirected ι (· ≤ ·)] variable (S : ι →o M ≃ₚ[L] N) -instance : DirectedSystem (fun i ↦ (S i).dom) (fun _ _ h ↦ - Substructure.inclusion (dom_le_dom (S.monotone h))) where +instance : DirectedSystem (fun i ↦ (S i).dom) + (fun _ _ h ↦ Substructure.inclusion (dom_le_dom (S.monotone h))) where map_self' := fun _ _ _ ↦ rfl map_map' := fun _ _ _ ↦ rfl -instance : DirectedSystem (fun i ↦ (S i).cod) (fun _ _ h ↦ - Substructure.inclusion (cod_le_cod (S.monotone h))) where +instance : DirectedSystem (fun i ↦ (S i).cod) + (fun _ _ h ↦ Substructure.inclusion (cod_le_cod (S.monotone h))) where map_self' := fun _ _ _ ↦ rfl map_map' := fun _ _ _ ↦ rfl @@ -326,10 +345,12 @@ lemma partialEquivLimit_comp_inclusion {i : ι} : rw [Equiv_isup_symm_inclusion] congr -theorem le_partialEquivLimit : ∀ i, S i ≤ partialEquivLimit S := - fun i => ⟨le_iSup (f := fun i ↦ (S i).dom) _, by - simp only [cod_partialEquivLimit, dom_partialEquivLimit, partialEquivLimit_comp_inclusion, ← - Embedding.comp_assoc, subtype_comp_inclusion]⟩ +theorem le_partialEquivLimit (i : ι) : S i ≤ partialEquivLimit S := + ⟨le_iSup (f := fun i ↦ (S i).dom) _, by + #adaptation_note /-- After lean4#5020, `simp` can no longer apply this lemma here. -/ + rw [partialEquivLimit_comp_inclusion] + simp only [cod_partialEquivLimit, dom_partialEquivLimit, ← Embedding.comp_assoc, + subtype_comp_inclusion]⟩ end DirectLimit diff --git a/Mathlib/ModelTheory/Quotients.lean b/Mathlib/ModelTheory/Quotients.lean index 798514c512fb1..fef412e512ae8 100644 --- a/Mathlib/ModelTheory/Quotients.lean +++ b/Mathlib/ModelTheory/Quotients.lean @@ -64,9 +64,9 @@ theorem relMap_quotient_mk' {n : ℕ} (r : L.Relations n) (x : Fin n → M) : theorem Term.realize_quotient_mk' {β : Type*} (t : L.Term β) (x : β → M) : (t.realize fun i => (⟦x i⟧ : Quotient s)) = ⟦@Term.realize _ _ ps.toStructure _ x t⟧ := by - induction' t with _ _ _ _ ih - · rfl - · simp only [ih, funMap_quotient_mk', Term.realize] + induction t with + | var => rfl + | func _ _ ih => simp only [ih, funMap_quotient_mk', Term.realize] end Language diff --git a/Mathlib/ModelTheory/Satisfiability.lean b/Mathlib/ModelTheory/Satisfiability.lean index 3185e8db3b62c..5adfbfe169f28 100644 --- a/Mathlib/ModelTheory/Satisfiability.lean +++ b/Mathlib/ModelTheory/Satisfiability.lean @@ -571,15 +571,16 @@ theorem Categorical.isComplete (h : κ.Categorical T) (h1 : ℵ₀ ≤ κ) obtain ⟨TF⟩ := h (MNT.toModel T) (MNF.toModel T) hNT hNF exact ((MNT.realize_sentence φ).trans - ((TF.realize_sentence φ).trans (MNF.realize_sentence φ).symm)).1 hMT⟩ + ((StrongHomClass.realize_sentence TF φ).trans (MNF.realize_sentence φ).symm)).1 hMT⟩ theorem empty_theory_categorical (T : Language.empty.Theory) : κ.Categorical T := fun M N hM hN => by rw [empty.nonempty_equiv_iff, hM, hN] theorem empty_infinite_Theory_isComplete : Language.empty.infiniteTheory.IsComplete := (empty_theory_categorical.{0} ℵ₀ _).isComplete ℵ₀ _ le_rfl (by simp) - ⟨Theory.Model.bundled ((model_infiniteTheory_iff Language.empty).2 - (inferInstanceAs (Infinite ℕ)))⟩ fun M => - (model_infiniteTheory_iff Language.empty).1 M.is_model + ⟨by + haveI : Language.empty.Structure ℕ := emptyStructure + exact ((model_infiniteTheory_iff Language.empty).2 (inferInstanceAs (Infinite ℕ))).bundled⟩ + fun M => (model_infiniteTheory_iff Language.empty).1 M.is_model end Cardinal diff --git a/Mathlib/ModelTheory/Semantics.lean b/Mathlib/ModelTheory/Semantics.lean index 8ab1b65be5c42..e84f09a5842c4 100644 --- a/Mathlib/ModelTheory/Semantics.lean +++ b/Mathlib/ModelTheory/Semantics.lean @@ -122,16 +122,17 @@ theorem realize_con {A : Set M} {a : A} {v : α → M} : (L.con a).term.realize @[simp] theorem realize_subst {t : L.Term α} {tf : α → L.Term β} {v : β → M} : (t.subst tf).realize v = t.realize fun a => (tf a).realize v := by - induction' t with _ _ _ _ ih - · rfl - · simp [ih] + induction t with + | var => rfl + | func _ _ ih => simp [ih] @[simp] theorem realize_restrictVar [DecidableEq α] {t : L.Term α} {s : Set α} (h : ↑t.varFinset ⊆ s) {v : α → M} : (t.restrictVar (Set.inclusion h)).realize (v ∘ (↑)) = t.realize v := by - induction' t with _ _ _ _ ih - · rfl - · simp_rw [varFinset, Finset.coe_biUnion, Set.iUnion_subset_iff] at h + induction t with + | var => rfl + | func _ _ ih => + simp_rw [varFinset, Finset.coe_biUnion, Set.iUnion_subset_iff] at h exact congr rfl (funext fun i => ih i (h i (Finset.mem_univ i))) @[simp] @@ -139,9 +140,10 @@ theorem realize_restrictVarLeft [DecidableEq α] {γ : Type*} {t : L.Term (α (h : ↑t.varFinsetLeft ⊆ s) {v : α → M} {xs : γ → M} : (t.restrictVarLeft (Set.inclusion h)).realize (Sum.elim (v ∘ (↑)) xs) = t.realize (Sum.elim v xs) := by - induction' t with a _ _ _ ih - · cases a <;> rfl - · simp_rw [varFinsetLeft, Finset.coe_biUnion, Set.iUnion_subset_iff] at h + induction t with + | var a => cases a <;> rfl + | func _ _ ih => + simp_rw [varFinsetLeft, Finset.coe_biUnion, Set.iUnion_subset_iff] at h exact congr rfl (funext fun i => ih i (h i (Finset.mem_univ i))) @[simp] @@ -201,25 +203,16 @@ theorem realize_onTerm [L'.Structure M] (φ : L →ᴸ L') [φ.IsExpansionOn M] end LHom @[simp] -theorem Hom.realize_term (g : M →[L] N) {t : L.Term α} {v : α → M} : +theorem HomClass.realize_term {F : Type*} [FunLike F M N] [HomClass L F M N] + (g : F) {t : L.Term α} {v : α → M} : t.realize (g ∘ v) = g (t.realize v) := by induction t · rfl - · rw [Term.realize, Term.realize, g.map_fun] + · rw [Term.realize, Term.realize, HomClass.map_fun] refine congr rfl ?_ ext x simp [*] -@[simp] -theorem Embedding.realize_term {v : α → M} (t : L.Term α) (g : M ↪[L] N) : - t.realize (g ∘ v) = g (t.realize v) := - g.toHom.realize_term - -@[simp] -theorem Equiv.realize_term {v : α → M} (t : L.Term α) (g : M ≃[L] N) : - t.realize (g ∘ v) = g (t.realize v) := - g.toHom.realize_term - variable {n : ℕ} namespace BoundedFormula @@ -330,12 +323,12 @@ theorem realize_mapTermRel_id [L'.Structure M] (ft n t).realize (Sum.elim v' xs) = t.realize (Sum.elim v xs)) (h2 : ∀ (n) (R : L.Relations n) (x : Fin n → M), RelMap (fr n R) x = RelMap R x) : (φ.mapTermRel ft fr fun _ => id).Realize v' xs ↔ φ.Realize v xs := by - induction' φ with _ _ _ _ _ _ _ _ _ _ _ ih1 ih2 _ _ ih - · rfl - · simp [mapTermRel, Realize, h1] - · simp [mapTermRel, Realize, h1, h2] - · simp [mapTermRel, Realize, ih1, ih2] - · simp only [mapTermRel, Realize, ih, id] + induction φ with + | falsum => rfl + | equal => simp [mapTermRel, Realize, h1] + | rel => simp [mapTermRel, Realize, h1, h2] + | imp _ _ ih1 ih2 => simp [mapTermRel, Realize, ih1, ih2] + | all _ ih => simp only [mapTermRel, Realize, ih, id] theorem realize_mapTermRel_add_castLe [L'.Structure M] {k : ℕ} {ft : ∀ n, L.Term (α ⊕ (Fin n)) → L'.Term (β ⊕ (Fin (k + n)))} @@ -348,12 +341,12 @@ theorem realize_mapTermRel_add_castLe [L'.Structure M] {k : ℕ} (hv : ∀ (n) (xs : Fin (k + n) → M) (x : M), @v (n + 1) (snoc xs x : Fin _ → M) = v xs) : (φ.mapTermRel ft fr fun n => castLE (add_assoc _ _ _).symm.le).Realize v' xs ↔ φ.Realize (v xs) (xs ∘ Fin.natAdd _) := by - induction' φ with _ _ _ _ _ _ _ _ _ _ _ ih1 ih2 _ _ ih - · rfl - · simp [mapTermRel, Realize, h1] - · simp [mapTermRel, Realize, h1, h2] - · simp [mapTermRel, Realize, ih1, ih2] - · simp [mapTermRel, Realize, ih, hv] + induction φ with + | falsum => rfl + | equal => simp [mapTermRel, Realize, h1] + | rel => simp [mapTermRel, Realize, h1, h2] + | imp _ _ ih1 ih2 => simp [mapTermRel, Realize, ih1, ih2] + | all _ ih => simp [mapTermRel, Realize, ih, hv] @[simp] theorem realize_relabel {m n : ℕ} {φ : L.BoundedFormula α n} {g : α → β ⊕ (Fin m)} {v : β → M} @@ -367,12 +360,13 @@ theorem realize_liftAt {n n' m : ℕ} {φ : L.BoundedFormula α n} {v : α → M (φ.liftAt n' m).Realize v xs ↔ φ.Realize v (xs ∘ fun i => if ↑i < m then Fin.castAdd n' i else Fin.addNat i n') := by rw [liftAt] - induction' φ with _ _ _ _ _ _ _ _ _ _ _ ih1 ih2 k _ ih3 - · simp [mapTermRel, Realize] - · simp [mapTermRel, Realize, realize_rel, realize_liftAt, Sum.elim_comp_map] - · simp [mapTermRel, Realize, realize_rel, realize_liftAt, Sum.elim_comp_map] - · simp only [mapTermRel, Realize, ih1 hmn, ih2 hmn] - · have h : k + 1 + n' = k + n' + 1 := by rw [add_assoc, add_comm 1 n', ← add_assoc] + induction φ with + | falsum => simp [mapTermRel, Realize] + | equal => simp [mapTermRel, Realize, realize_rel, realize_liftAt, Sum.elim_comp_map] + | rel => simp [mapTermRel, Realize, realize_rel, realize_liftAt, Sum.elim_comp_map] + | imp _ _ ih1 ih2 => simp only [mapTermRel, Realize, ih1 hmn, ih2 hmn] + | @all k _ ih3 => + have h : k + 1 + n' = k + n' + 1 := by rw [add_assoc, add_comm 1 n', ← add_assoc] simp only [mapTermRel, Realize, realize_castLE_of_eq h, ih3 (hmn.trans k.succ.le_succ)] refine forall_congr' fun x => iff_eq_eq.mpr (congr rfl (funext (Fin.lastCases ?_ fun i => ?_))) · simp only [Function.comp_apply, val_last, snoc_last] @@ -420,12 +414,22 @@ theorem realize_subst {φ : L.BoundedFormula α n} {tf : α → L.Term β} {v : theorem realize_restrictFreeVar [DecidableEq α] {n : ℕ} {φ : L.BoundedFormula α n} {s : Set α} (h : ↑φ.freeVarFinset ⊆ s) {v : α → M} {xs : Fin n → M} : (φ.restrictFreeVar (Set.inclusion h)).Realize (v ∘ (↑)) xs ↔ φ.Realize v xs := by - induction' φ with _ _ _ _ _ _ _ _ _ _ _ ih1 ih2 _ _ ih3 - · rfl - · simp [restrictFreeVar, Realize] - · simp [restrictFreeVar, Realize] - · simp [restrictFreeVar, Realize, ih1, ih2] - · simp [restrictFreeVar, Realize, ih3] + induction φ with + | falsum => rfl + | equal => + simp only [Realize, freeVarFinset.eq_2] + rw [Set.inclusion_comp_inclusion, Set.inclusion_comp_inclusion] + simp + | rel => + simp only [Realize, freeVarFinset.eq_3, Finset.biUnion_val] + congr! + erw [Set.inclusion_comp_inclusion _ h] + simp + | imp _ _ ih1 ih2 => + simp only [Realize, freeVarFinset.eq_4] + rw [Set.inclusion_comp_inclusion, Set.inclusion_comp_inclusion] + simp [ih1, ih2] + | all _ ih3 => simp [restrictFreeVar, Realize, ih3] theorem realize_constantsVarsEquiv [L[[α]].Structure M] [(lhomWithConstants L α).IsExpansionOn M] {n} {φ : L[[α]].BoundedFormula β n} {v : β → M} {xs : Fin n → M} : @@ -476,15 +480,15 @@ open BoundedFormula theorem realize_onBoundedFormula [L'.Structure M] (φ : L →ᴸ L') [φ.IsExpansionOn M] {n : ℕ} (ψ : L.BoundedFormula α n) {v : α → M} {xs : Fin n → M} : (φ.onBoundedFormula ψ).Realize v xs ↔ ψ.Realize v xs := by - induction' ψ with _ _ _ _ _ _ _ _ _ _ _ ih1 ih2 _ _ ih3 - · rfl - · simp only [onBoundedFormula, realize_bdEqual, realize_onTerm] - rfl - · simp only [onBoundedFormula, realize_rel, LHom.map_onRelation, + induction ψ with + | falsum => rfl + | equal => simp only [onBoundedFormula, realize_bdEqual, realize_onTerm]; rfl + | rel => + simp only [onBoundedFormula, realize_rel, LHom.map_onRelation, Function.comp_apply, realize_onTerm] rfl - · simp only [onBoundedFormula, ih1, ih2, realize_imp] - · simp only [onBoundedFormula, ih3, realize_all] + | imp _ _ ih1 ih2 => simp only [onBoundedFormula, ih1, ih2, realize_imp] + | all _ ih3 => simp only [onBoundedFormula, ih3, realize_all] end LHom @@ -698,8 +702,12 @@ theorem model_union_iff {T' : L.Theory} : M ⊨ T ∪ T' ↔ M ⊨ T ∧ M ⊨ T ⟨fun h => ⟨h.mono Set.subset_union_left, h.mono Set.subset_union_right⟩, fun h => h.1.union h.2⟩ +@[simp] theorem model_singleton_iff {φ : L.Sentence} : M ⊨ ({φ} : L.Theory) ↔ M ⊨ φ := by simp +theorem model_insert_iff {φ : L.Sentence} : M ⊨ insert φ T ↔ M ⊨ φ ∧ M ⊨ T := by + rw [Set.insert_eq, model_union_iff, model_singleton_iff] + theorem model_iff_subset_completeTheory : M ⊨ T ↔ T ⊆ L.completeTheory M := T.model_iff @@ -752,12 +760,12 @@ theorem _root_.FirstOrder.Language.Formula.realize_iAlls ∀ (i : γ → M), φ.Realize (fun a => Sum.elim v i (f a)) := by let e := Classical.choice (Classical.choose_spec (Finite.exists_equiv_fin γ)) rw [Formula.iAlls] - simp only [Nat.add_zero, realize_alls, realize_relabel, Function.comp, + simp only [Nat.add_zero, realize_alls, realize_relabel, Function.comp_def, castAdd_zero, finCongr_refl, OrderIso.refl_apply, Sum.elim_map, id_eq] refine Equiv.forall_congr ?_ ?_ · exact ⟨fun v => v ∘ e, fun v => v ∘ e.symm, - fun _ => by simp [Function.comp], - fun _ => by simp [Function.comp]⟩ + fun _ => by simp [Function.comp_def], + fun _ => by simp [Function.comp_def]⟩ · intro x rw [Formula.Realize, iff_iff_eq] congr @@ -778,13 +786,13 @@ theorem _root_.FirstOrder.Language.Formula.realize_iExs ∃ (i : γ → M), φ.Realize (fun a => Sum.elim v i (f a)) := by let e := Classical.choice (Classical.choose_spec (Finite.exists_equiv_fin γ)) rw [Formula.iExs] - simp only [Nat.add_zero, realize_exs, realize_relabel, Function.comp, + simp only [Nat.add_zero, realize_exs, realize_relabel, Function.comp_def, castAdd_zero, finCongr_refl, OrderIso.refl_apply, Sum.elim_map, id_eq] rw [← not_iff_not, not_exists, not_exists] refine Equiv.forall_congr ?_ ?_ · exact ⟨fun v => v ∘ e, fun v => v ∘ e.symm, - fun _ => by simp [Function.comp], - fun _ => by simp [Function.comp]⟩ + fun _ => by simp [Function.comp_def], + fun _ => by simp [Function.comp_def]⟩ · intro x rw [Formula.Realize, iff_iff_eq] congr @@ -801,18 +809,20 @@ theorem realize_iExs [Finite γ] {f : α → β ⊕ γ} @[simp] theorem realize_toFormula (φ : L.BoundedFormula α n) (v : α ⊕ (Fin n) → M) : φ.toFormula.Realize v ↔ φ.Realize (v ∘ Sum.inl) (v ∘ Sum.inr) := by - induction' φ with _ _ _ _ _ _ _ _ _ _ _ ih1 ih2 _ _ ih3 a8 a9 a0 - · rfl - · simp [BoundedFormula.Realize] - · simp [BoundedFormula.Realize] - · rw [toFormula, Formula.Realize, realize_imp, ← Formula.Realize, ih1, ← Formula.Realize, ih2, + induction φ with + | falsum => rfl + | equal => simp [BoundedFormula.Realize] + | rel => simp [BoundedFormula.Realize] + | imp _ _ ih1 ih2 => + rw [toFormula, Formula.Realize, realize_imp, ← Formula.Realize, ih1, ← Formula.Realize, ih2, realize_imp] - · rw [toFormula, Formula.Realize, realize_all, realize_all] + | all _ ih3 => + rw [toFormula, Formula.Realize, realize_all, realize_all] refine forall_congr' fun a => ?_ have h := ih3 (Sum.elim (v ∘ Sum.inl) (snoc (v ∘ Sum.inr) a)) simp only [Sum.elim_comp_inl, Sum.elim_comp_inr] at h rw [← h, realize_relabel, Formula.Realize, iff_iff_eq] - simp only [Function.comp] + simp only [Function.comp_def] congr with x · cases' x with _ x · simp @@ -842,44 +852,53 @@ theorem realize_iInf (s : Finset β) (f : β → L.BoundedFormula α n) end BoundedFormula -namespace Equiv +namespace StrongHomClass + +variable {F : Type*} [EquivLike F M N] [StrongHomClass L F M N] (g : F) @[simp] -theorem realize_boundedFormula (g : M ≃[L] N) (φ : L.BoundedFormula α n) {v : α → M} +theorem realize_boundedFormula (φ : L.BoundedFormula α n) {v : α → M} {xs : Fin n → M} : φ.Realize (g ∘ v) (g ∘ xs) ↔ φ.Realize v xs := by - induction' φ with _ _ _ _ _ _ _ _ _ _ _ ih1 ih2 _ _ ih3 - · rfl - · simp only [BoundedFormula.Realize, ← Sum.comp_elim, Equiv.realize_term, g.injective.eq_iff] - · simp only [BoundedFormula.Realize, ← Sum.comp_elim, Equiv.realize_term] - exact g.map_rel _ _ - · rw [BoundedFormula.Realize, ih1, ih2, BoundedFormula.Realize] - · rw [BoundedFormula.Realize, BoundedFormula.Realize] + induction φ with + | falsum => rfl + | equal => + simp only [BoundedFormula.Realize, ← Sum.comp_elim, HomClass.realize_term, + EmbeddingLike.apply_eq_iff_eq g] + | rel => + simp only [BoundedFormula.Realize, ← Sum.comp_elim, HomClass.realize_term] + exact StrongHomClass.map_rel g _ _ + | imp _ _ ih1 ih2 => rw [BoundedFormula.Realize, ih1, ih2, BoundedFormula.Realize] + | all _ ih3 => + rw [BoundedFormula.Realize, BoundedFormula.Realize] constructor · intro h a have h' := h (g a) rw [← Fin.comp_snoc, ih3] at h' exact h' · intro h a - have h' := h (g.symm a) - rw [← ih3, Fin.comp_snoc, g.apply_symm_apply] at h' + have h' := h (EquivLike.inv g a) + rw [← ih3, Fin.comp_snoc, EquivLike.apply_inv_apply g] at h' exact h' @[simp] -theorem realize_formula (g : M ≃[L] N) (φ : L.Formula α) {v : α → M} : +theorem realize_formula (φ : L.Formula α) {v : α → M} : φ.Realize (g ∘ v) ↔ φ.Realize v := by - rw [Formula.Realize, Formula.Realize, ← g.realize_boundedFormula φ, iff_eq_eq, + rw [Formula.Realize, Formula.Realize, ← realize_boundedFormula g φ, iff_eq_eq, Unique.eq_default (g ∘ default)] -theorem realize_sentence (g : M ≃[L] N) (φ : L.Sentence) : M ⊨ φ ↔ N ⊨ φ := by - rw [Sentence.Realize, Sentence.Realize, ← g.realize_formula, Unique.eq_default (g ∘ default)] +include g + +theorem realize_sentence (φ : L.Sentence) : M ⊨ φ ↔ N ⊨ φ := by + rw [Sentence.Realize, Sentence.Realize, ← realize_formula g, + Unique.eq_default (g ∘ default)] -theorem theory_model (g : M ≃[L] N) [M ⊨ T] : N ⊨ T := - ⟨fun φ hφ => (g.realize_sentence φ).1 (Theory.realize_sentence_of_mem T hφ)⟩ +theorem theory_model [M ⊨ T] : N ⊨ T := + ⟨fun φ hφ => (realize_sentence g φ).1 (Theory.realize_sentence_of_mem T hφ)⟩ -theorem elementarilyEquivalent (g : M ≃[L] N) : M ≅[L] N := - elementarilyEquivalent_iff.2 g.realize_sentence +theorem elementarilyEquivalent : M ≅[L] N := + elementarilyEquivalent_iff.2 (realize_sentence g) -end Equiv +end StrongHomClass namespace Relations diff --git a/Mathlib/ModelTheory/Skolem.lean b/Mathlib/ModelTheory/Skolem.lean index eefcbc6d811c1..0ff7aa3c3c2b8 100644 --- a/Mathlib/ModelTheory/Skolem.lean +++ b/Mathlib/ModelTheory/Skolem.lean @@ -82,11 +82,11 @@ theorem skolem₁_reduct_isElementary (S : (L.sum L.skolem₁).Substructure M) : apply (LHom.sumInl.substructureReduct S).isElementary_of_exists intro n φ x a h let φ' : (L.sum L.skolem₁).Functions n := LHom.sumInr.onFunction φ - exact - ⟨⟨funMap φ' ((↑) ∘ x), S.fun_mem (LHom.sumInr.onFunction φ) ((↑) ∘ x) (by - exact fun i => (x i).2)⟩, - by exact Classical.epsilon_spec (p := fun a => BoundedFormula.Realize φ default - (Fin.snoc (Subtype.val ∘ x) a)) ⟨a, h⟩⟩ + use ⟨funMap φ' ((↑) ∘ x), ?_⟩ + · exact Classical.epsilon_spec (p := fun a => BoundedFormula.Realize φ default + (Fin.snoc (Subtype.val ∘ x) a)) ⟨a, h⟩ + · exact S.fun_mem (LHom.sumInr.onFunction φ) ((↑) ∘ x) (by + exact fun i => (x i).2) /-- Any `L.sum L.skolem₁`-substructure is an elementary `L`-substructure. -/ noncomputable def elementarySkolem₁Reduct (S : (L.sum L.skolem₁).Substructure M) : @@ -116,7 +116,7 @@ variable {M} /-- The **Downward Löwenheim–Skolem theorem** : If `s` is a set in an `L`-structure `M` and `κ` an infinite cardinal such that `max (#s, L.card) ≤ κ` and `κ ≤ # M`, then `M` has an elementary substructure containing `s` of - cardinality `κ`. -/ + cardinality `κ`. -/ theorem exists_elementarySubstructure_card_eq (s : Set M) (κ : Cardinal.{w'}) (h1 : ℵ₀ ≤ κ) (h2 : Cardinal.lift.{w'} #s ≤ Cardinal.lift.{w} κ) (h3 : Cardinal.lift.{w'} L.card ≤ Cardinal.lift.{max u v} κ) diff --git a/Mathlib/ModelTheory/Substructures.lean b/Mathlib/ModelTheory/Substructures.lean index a91af2f676773..2d9ac4e09c346 100644 --- a/Mathlib/ModelTheory/Substructures.lean +++ b/Mathlib/ModelTheory/Substructures.lean @@ -289,8 +289,20 @@ theorem lift_card_closure_le : refine lift_card_closure_le_card_term.trans (Term.card_le.trans ?_) rw [mk_sum, lift_umax.{w, u}] +lemma mem_closed_iff (s : Set M) : + s ∈ (closure L).closed ↔ ∀ {n}, ∀ f : L.Functions n, ClosedUnder f s := by + refine ⟨fun h n f => ?_, fun h => ?_⟩ + · rw [← h] + exact Substructure.fun_mem _ _ + · have h' : closure L s = ⟨s, h⟩ := closure_eq_of_le (refl _) subset_closure + exact congr_arg _ h' + variable (L) +@[simp] +lemma mem_closed_of_isRelational [L.IsRelational] (s : Set M) : s ∈ (closure L).closed := + (mem_closed_iff s).2 isEmptyElim + theorem _root_.Set.Countable.substructure_closure [Countable (Σl, L.Functions l)] (h : s.Countable) : Countable.{w + 1} (closure L s) := by haveI : Countable s := h.to_subtype @@ -481,7 +493,7 @@ theorem comap_top (f : M →[L] N) : (⊤ : L.Substructure N).comap f = ⊤ := @[simp] theorem map_id (S : L.Substructure M) : S.map (Hom.id L M) = S := - ext fun _ => ⟨fun ⟨_, h, rfl⟩ => h, fun h => ⟨_, h, rfl⟩⟩ + SetLike.coe_injective <| Set.image_id _ theorem map_closure (f : M →[L] N) (s : Set M) : (closure L s).map f = closure L (f '' s) := Eq.symm <| @@ -607,13 +619,13 @@ theorem coe_topEquiv : theorem realize_boundedFormula_top {α : Type*} {n : ℕ} {φ : L.BoundedFormula α n} {v : α → (⊤ : L.Substructure M)} {xs : Fin n → (⊤ : L.Substructure M)} : φ.Realize v xs ↔ φ.Realize (((↑) : _ → M) ∘ v) ((↑) ∘ xs) := by - rw [← Substructure.topEquiv.realize_boundedFormula φ] + rw [← StrongHomClass.realize_boundedFormula Substructure.topEquiv φ] simp @[simp] theorem realize_formula_top {α : Type*} {φ : L.Formula α} {v : α → (⊤ : L.Substructure M)} : φ.Realize v ↔ φ.Realize (((↑) : (⊤ : L.Substructure M) → M) ∘ v) := by - rw [← Substructure.topEquiv.realize_formula φ] + rw [← StrongHomClass.realize_formula Substructure.topEquiv φ] simp /-- A dependent version of `Substructure.closure_induction`. -/ @@ -864,7 +876,7 @@ theorem subtype_substructureEquivMap (f : M ↪[L] N) (s : L.Substructure M) : ext; rfl /-- The equivalence between the domain and the range of an embedding `f`. -/ -noncomputable def equivRange (f : M ↪[L] N) : M ≃[L] f.toHom.range where +@[simps toEquiv_apply] noncomputable def equivRange (f : M ↪[L] N) : M ≃[L] f.toHom.range where toFun := codRestrict f.toHom.range f f.toHom.mem_range_self invFun n := Classical.choose n.2 left_inv m := diff --git a/Mathlib/ModelTheory/Syntax.lean b/Mathlib/ModelTheory/Syntax.lean index d77cfb5bd2104..b75f1a92257f2 100644 --- a/Mathlib/ModelTheory/Syntax.lean +++ b/Mathlib/ModelTheory/Syntax.lean @@ -79,6 +79,18 @@ variable {L} namespace Term +instance instDecidableEq [DecidableEq α] [∀ n, DecidableEq (L.Functions n)] : DecidableEq (L.Term α) + | .var a, .var b => decidable_of_iff (a = b) <| by simp + | @Term.func _ _ m f xs, @Term.func _ _ n g ys => + if h : m = n then + letI : DecidableEq (L.Term α) := instDecidableEq + decidable_of_iff (f = h ▸ g ∧ ∀ i : Fin m, xs i = ys (Fin.cast h i)) <| by + subst h + simp [Function.funext_iff] + else + .isFalse <| by simp [h] + | .var _, .func _ _ | .func _ _, .var _ => .isFalse <| by simp + open Finset /-- The `Finset` of variables used in a given term. -/ @@ -102,9 +114,9 @@ def relabel (g : α → β) : L.Term α → L.Term β | func f ts => func f fun {i} => (ts i).relabel g theorem relabel_id (t : L.Term α) : t.relabel id = t := by - induction' t with _ _ _ _ ih - · rfl - · simp [ih] + induction t with + | var => rfl + | func _ _ ih => simp [ih] @[simp] theorem relabel_id_eq_id : (Term.relabel id : L.Term α → L.Term α) = id := @@ -113,9 +125,9 @@ theorem relabel_id_eq_id : (Term.relabel id : L.Term α → L.Term α) = id := @[simp] theorem relabel_relabel (f : α → β) (g : β → γ) (t : L.Term α) : (t.relabel f).relabel g = t.relabel (g ∘ f) := by - induction' t with _ _ _ _ ih - · rfl - · simp [ih] + induction t with + | var => rfl + | func _ _ ih => simp [ih] @[simp] theorem relabel_comp_relabel (f : α → β) (g : β → γ) : @@ -185,9 +197,10 @@ def varsToConstants : L.Term (γ ⊕ α) → L[[γ]].Term α def constantsVarsEquiv : L[[γ]].Term α ≃ L.Term (γ ⊕ α) := ⟨constantsToVars, varsToConstants, by intro t - induction' t with _ n f _ ih - · rfl - · cases n + induction t with + | var => rfl + | @func n f _ ih => + cases n · cases f · simp [constantsToVars, varsToConstants, ih] · simp [constantsToVars, varsToConstants, Constants.term, eq_iff_true_of_subsingleton] @@ -248,19 +261,17 @@ def onTerm (φ : L →ᴸ L') : L.Term α → L'.Term α @[simp] theorem id_onTerm : ((LHom.id L).onTerm : L.Term α → L.Term α) = id := by ext t - induction' t with _ _ _ _ ih - · rfl - · simp_rw [onTerm, ih] - rfl + induction t with + | var => rfl + | func _ _ ih => simp_rw [onTerm, ih]; rfl @[simp] theorem comp_onTerm {L'' : Language} (φ : L' →ᴸ L'') (ψ : L →ᴸ L') : ((φ.comp ψ).onTerm : L.Term α → L''.Term α) = φ.onTerm ∘ ψ.onTerm := by ext t - induction' t with _ _ _ _ ih - · rfl - · simp_rw [onTerm, ih] - rfl + induction t with + | var => rfl + | func _ _ ih => simp_rw [onTerm, ih]; rfl end LHom @@ -390,25 +401,27 @@ def castLE : ∀ {m n : ℕ} (_h : m ≤ n), L.BoundedFormula α m → L.Bounded @[simp] theorem castLE_rfl {n} (h : n ≤ n) (φ : L.BoundedFormula α n) : φ.castLE h = φ := by - induction' φ with _ _ _ _ _ _ _ _ _ _ _ ih1 ih2 _ _ ih3 - · rfl - · simp [Fin.castLE_of_eq] - · simp [Fin.castLE_of_eq] - · simp [Fin.castLE_of_eq, ih1, ih2] - · simp [Fin.castLE_of_eq, ih3] + induction φ with + | falsum => rfl + | equal => simp [Fin.castLE_of_eq] + | rel => simp [Fin.castLE_of_eq] + | imp _ _ ih1 ih2 => simp [Fin.castLE_of_eq, ih1, ih2] + | all _ ih3 => simp [Fin.castLE_of_eq, ih3] @[simp] theorem castLE_castLE {k m n} (km : k ≤ m) (mn : m ≤ n) (φ : L.BoundedFormula α k) : (φ.castLE km).castLE mn = φ.castLE (km.trans mn) := by revert m n - induction' φ with _ _ _ _ _ _ _ _ _ _ _ ih1 ih2 _ _ ih3 <;> intro m n km mn - · rfl - · simp - · simp only [castLE, eq_self_iff_true, heq_iff_eq, true_and_iff] + induction φ with + | falsum => intros; rfl + | equal => simp + | rel => + intros + simp only [castLE, eq_self_iff_true, heq_iff_eq, true_and_iff] rw [← Function.comp.assoc, Term.relabel_comp_relabel] simp - · simp [ih1, ih2] - · simp only [castLE, ih3] + | imp _ _ ih1 ih2 => simp [ih1, ih2] + | all _ ih3 => intros; simp only [castLE, ih3] @[simp] theorem castLE_comp_castLE {k m n} (km : k ≤ m) (mn : m ≤ n) : @@ -471,22 +484,22 @@ theorem mapTermRel_mapTermRel {L'' : Language} (fr' : ∀ n, L'.Relations n → L''.Relations n) {n} (φ : L.BoundedFormula α n) : ((φ.mapTermRel ft fr fun _ => id).mapTermRel ft' fr' fun _ => id) = φ.mapTermRel (fun _ => ft' _ ∘ ft _) (fun _ => fr' _ ∘ fr _) fun _ => id := by - induction' φ with _ _ _ _ _ _ _ _ _ _ _ ih1 ih2 _ _ ih3 - · rfl - · simp [mapTermRel] - · simp [mapTermRel] - · simp [mapTermRel, ih1, ih2] - · simp [mapTermRel, ih3] + induction φ with + | falsum => rfl + | equal => simp [mapTermRel] + | rel => simp [mapTermRel] + | imp _ _ ih1 ih2 => simp [mapTermRel, ih1, ih2] + | all _ ih3 => simp [mapTermRel, ih3] @[simp] theorem mapTermRel_id_id_id {n} (φ : L.BoundedFormula α n) : (φ.mapTermRel (fun _ => id) (fun _ => id) fun _ => id) = φ := by - induction' φ with _ _ _ _ _ _ _ _ _ _ _ ih1 ih2 _ _ ih3 - · rfl - · simp [mapTermRel] - · simp [mapTermRel] - · simp [mapTermRel, ih1, ih2] - · simp [mapTermRel, ih3] + induction φ with + | falsum => rfl + | equal => simp [mapTermRel] + | rel => simp [mapTermRel] + | imp _ _ ih1 ih2 => simp [mapTermRel, ih1, ih2] + | all _ ih3 => simp [mapTermRel, ih3] /-- An equivalence of bounded formulas given by an equivalence of terms and an equivalence of relations. -/ @@ -559,12 +572,12 @@ theorem relabel_ex (g : α → β ⊕ (Fin n)) {k} (φ : L.BoundedFormula α (k theorem relabel_sum_inl (φ : L.BoundedFormula α n) : (φ.relabel Sum.inl : L.BoundedFormula α (0 + n)) = φ.castLE (ge_of_eq (zero_add n)) := by simp only [relabel, relabelAux_sum_inl] - induction' φ with _ _ _ _ _ _ _ _ _ _ _ ih1 ih2 _ _ ih3 - · rfl - · simp [Fin.natAdd_zero, castLE_of_eq, mapTermRel] - · simp [Fin.natAdd_zero, castLE_of_eq, mapTermRel]; rfl - · simp [mapTermRel, ih1, ih2] - · simp [mapTermRel, ih3, castLE] + induction φ with + | 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] /-- Substitutes the variables in a given formula with terms. -/ def subst {n : ℕ} (φ : L.BoundedFormula α n) (f : α → L.Term β) : L.BoundedFormula β n := @@ -615,26 +628,25 @@ def onBoundedFormula (g : L →ᴸ L') : ∀ {k : ℕ}, L.BoundedFormula α k theorem id_onBoundedFormula : ((LHom.id L).onBoundedFormula : L.BoundedFormula α n → L.BoundedFormula α n) = id := by ext f - induction' f with _ _ _ _ _ _ _ _ _ _ _ ih1 ih2 _ _ ih3 - · rfl - · rw [onBoundedFormula, LHom.id_onTerm, id, id, id, Term.bdEqual] - · rw [onBoundedFormula, LHom.id_onTerm] - rfl - · rw [onBoundedFormula, ih1, ih2, id, id, id] - · rw [onBoundedFormula, ih3, id, id] + induction f with + | falsum => rfl + | equal => rw [onBoundedFormula, LHom.id_onTerm, id, id, id, Term.bdEqual] + | rel => rw [onBoundedFormula, LHom.id_onTerm]; rfl + | imp _ _ ih1 ih2 => rw [onBoundedFormula, ih1, ih2, id, id, id] + | all _ ih3 => rw [onBoundedFormula, ih3, id, id] @[simp] theorem comp_onBoundedFormula {L'' : Language} (φ : L' →ᴸ L'') (ψ : L →ᴸ L') : ((φ.comp ψ).onBoundedFormula : L.BoundedFormula α n → L''.BoundedFormula α n) = φ.onBoundedFormula ∘ ψ.onBoundedFormula := by ext f - induction' f with _ _ _ _ _ _ _ _ _ _ _ ih1 ih2 _ _ ih3 - · rfl - · simp only [onBoundedFormula, comp_onTerm, Function.comp_apply] - · simp only [onBoundedFormula, comp_onRelation, comp_onTerm, Function.comp_apply] - rfl - · simp only [onBoundedFormula, Function.comp_apply, ih1, ih2, eq_self_iff_true, and_self_iff] - · simp only [ih3, onBoundedFormula, Function.comp_apply] + induction f with + | falsum => rfl + | equal => simp only [onBoundedFormula, comp_onTerm, Function.comp_apply] + | rel => simp only [onBoundedFormula, comp_onRelation, comp_onTerm, Function.comp_apply]; rfl + | imp _ _ ih1 ih2 => + simp only [onBoundedFormula, Function.comp_apply, ih1, ih2, eq_self_iff_true, and_self_iff] + | all _ ih3 => simp only [ih3, onBoundedFormula, Function.comp_apply] /-- Maps a formula's symbols along a language map. -/ def onFormula (g : L →ᴸ L') : L.Formula α → L'.Formula α := diff --git a/Mathlib/ModelTheory/Ultraproducts.lean b/Mathlib/ModelTheory/Ultraproducts.lean index efe11fdadc8cd..c7c3922d198a4 100644 --- a/Mathlib/ModelTheory/Ultraproducts.lean +++ b/Mathlib/ModelTheory/Ultraproducts.lean @@ -94,23 +94,27 @@ theorem boundedFormula_realize_cast {β : Type*} {n : ℕ} (φ : L.BoundedFormul (fun i => (v i : (u : Filter α).Product M))) ↔ ∀ᶠ a : α in u, φ.Realize (fun i : β => x i a) fun i => v i a := by letI := (u : Filter α).productSetoid M - induction' φ with _ _ _ _ _ _ _ _ m _ _ ih ih' k φ ih - · simp only [BoundedFormula.Realize, eventually_const] - · have h2 : ∀ a : α, (Sum.elim (fun i : β => x i a) fun i => v i a) = fun i => Sum.elim x v i a := + induction φ with + | falsum => simp only [BoundedFormula.Realize, eventually_const] + | equal => + have h2 : ∀ a : α, (Sum.elim (fun i : β => x i a) fun i => v i a) = fun i => Sum.elim x v i a := fun a => funext fun i => Sum.casesOn i (fun i => rfl) fun i => rfl simp only [BoundedFormula.Realize, h2, term_realize_cast] erw [(Sum.comp_elim ((↑) : (∀ a, M a) → (u : Filter α).Product M) x v).symm, term_realize_cast, term_realize_cast] exact Quotient.eq'' - · have h2 : ∀ a : α, (Sum.elim (fun i : β => x i a) fun i => v i a) = fun i => Sum.elim x v i a := + | rel => + have h2 : ∀ a : α, (Sum.elim (fun i : β => x i a) fun i => v i a) = fun i => Sum.elim x v i a := fun a => funext fun i => Sum.casesOn i (fun i => rfl) fun i => rfl simp only [BoundedFormula.Realize, h2] erw [(Sum.comp_elim ((↑) : (∀ a, M a) → (u : Filter α).Product M) x v).symm] conv_lhs => enter [2, i]; erw [term_realize_cast] apply relMap_quotient_mk' - · simp only [BoundedFormula.Realize, ih v, ih' v] + | imp _ _ ih ih' => + simp only [BoundedFormula.Realize, ih v, ih' v] rw [Ultrafilter.eventually_imp] - · simp only [BoundedFormula.Realize] + | @all k φ ih => + simp only [BoundedFormula.Realize] apply Iff.trans (b := ∀ m : ∀ a : α, M a, φ.Realize (fun i : β => (x i : (u : Filter α).Product M)) (Fin.snoc (((↑) : (∀ a, M a) → (u : Filter α).Product M) ∘ v) @@ -124,7 +128,7 @@ theorem boundedFormula_realize_cast {β : Type*} {n : ℕ} (φ : L.BoundedFormul · simp only [Fin.snoc_last] · simp only [Fin.snoc_castSucc] simp only [← Fin.comp_snoc] - simp only [Function.comp, ih, h'] + simp only [Function.comp_def, ih, h'] refine ⟨fun h => ?_, fun h m => ?_⟩ · contrapose! h simp_rw [← Ultrafilter.eventually_not, not_forall] at h diff --git a/Mathlib/NumberTheory/ArithmeticFunction.lean b/Mathlib/NumberTheory/ArithmeticFunction.lean index ffd2563801e40..442363c3a7429 100644 --- a/Mathlib/NumberTheory/ArithmeticFunction.lean +++ b/Mathlib/NumberTheory/ArithmeticFunction.lean @@ -390,7 +390,7 @@ instance {M : Type*} [Semiring R] [AddCommMonoid M] [Module R M] : section Zeta -/-- `ζ 0 = 0`, otherwise `ζ x = 1`. The Dirichlet Series is the Riemann `ζ`. -/ +/-- `ζ 0 = 0`, otherwise `ζ x = 1`. The Dirichlet Series is the Riemann `ζ`. -/ def zeta : ArithmeticFunction ℕ := ⟨fun x => ite (x = 0) 0 1, rfl⟩ @@ -776,7 +776,7 @@ end IsMultiplicative section SpecialFunctions -/-- The identity on `ℕ` as an `ArithmeticFunction`. -/ +/-- The identity on `ℕ` as an `ArithmeticFunction`. -/ nonrec -- Porting note (#11445): added def id : ArithmeticFunction ℕ := ⟨id, rfl⟩ diff --git a/Mathlib/NumberTheory/BernoulliPolynomials.lean b/Mathlib/NumberTheory/BernoulliPolynomials.lean index 4c666ceb7e29f..f333c35443ce6 100644 --- a/Mathlib/NumberTheory/BernoulliPolynomials.lean +++ b/Mathlib/NumberTheory/BernoulliPolynomials.lean @@ -175,8 +175,7 @@ theorem bernoulli_succ_eval (n p : ℕ) : (bernoulli p.succ).eval (n : ℚ) = theorem bernoulli_eval_one_add (n : ℕ) (x : ℚ) : (bernoulli n).eval (1 + x) = (bernoulli n).eval x + n * x ^ (n - 1) := by refine Nat.strong_induction_on n fun d hd => ?_ - have nz : ((d.succ : ℕ) : ℚ) ≠ 0 := by - norm_cast + have nz : ((d.succ : ℕ) : ℚ) ≠ 0 := by norm_cast apply (mul_right_inj' nz).1 rw [← smul_eq_mul, ← eval_smul, bernoulli_eq_sub_sum, mul_add, ← smul_eq_mul, ← eval_smul, bernoulli_eq_sub_sum, eval_sub, eval_finset_sum] diff --git a/Mathlib/NumberTheory/Bertrand.lean b/Mathlib/NumberTheory/Bertrand.lean index 487d4660f924d..772c5d12f2dff 100644 --- a/Mathlib/NumberTheory/Bertrand.lean +++ b/Mathlib/NumberTheory/Bertrand.lean @@ -122,7 +122,7 @@ theorem bertrand_main_inequality {n : ℕ} (n_large : 512 ≤ n) : · exact cast_div_le.trans (by norm_cast) /-- A lemma that tells us that, in the case where Bertrand's postulate does not hold, the prime -factorization of the central binomial coefficent only has factors at most `2 * n / 3 + 1`. +factorization of the central binomial coefficient only has factors at most `2 * n / 3 + 1`. -/ theorem centralBinom_factorization_small (n : ℕ) (n_large : 2 < n) (no_prime : ¬∃ p : ℕ, p.Prime ∧ n < p ∧ p ≤ 2 * n) : diff --git a/Mathlib/NumberTheory/Cyclotomic/CyclotomicCharacter.lean b/Mathlib/NumberTheory/Cyclotomic/CyclotomicCharacter.lean index 1f7a73c505206..fad2bbc131b52 100644 --- a/Mathlib/NumberTheory/Cyclotomic/CyclotomicCharacter.lean +++ b/Mathlib/NumberTheory/Cyclotomic/CyclotomicCharacter.lean @@ -105,7 +105,8 @@ theorem toFun_spec (g : L ≃+* L) {n : ℕ+} (t : rootsOfUnity n L) : g (t : Lˣ) = (t ^ (χ₀ n g).val : Lˣ) := by rw [ModularCyclotomicCharacter_aux_spec g n t, ← zpow_natCast, ModularCyclotomicCharacter.toFun, ZMod.val_intCast, ← Subgroup.coe_zpow] - exact Units.ext_iff.1 <| SetCoe.ext_iff.2 <| zpow_eq_zpow_emod _ pow_card_eq_one + exact Units.ext_iff.1 <| SetCoe.ext_iff.2 <| + zpow_eq_zpow_emod _ pow_card_eq_one (G := rootsOfUnity n L) theorem toFun_spec' (g : L ≃+* L) {n : ℕ+} {t : Lˣ} (ht : t ∈ rootsOfUnity n L) : g t = t ^ (χ₀ n g).val := @@ -195,7 +196,7 @@ lemma spec (g : L ≃+* L) {t : Lˣ} (ht : t ∈ rootsOfUnity n L) : congr 1 exact (ZMod.ringEquivCongr_val _ _).symm -lemma unique (g : L ≃+* L) {c : ZMod n} (hc : ∀ t ∈ rootsOfUnity n L, g t = t ^ c.val) : +lemma unique (g : L ≃+* L) {c : ZMod n} (hc : ∀ t ∈ rootsOfUnity n L, g t = t ^ c.val) : c = ModularCyclotomicCharacter L hn g := by change c = (ZMod.ringEquivCongr hn) (toFun n g) rw [← toFun_unique' n g (ZMod.ringEquivCongr hn.symm c) diff --git a/Mathlib/NumberTheory/Cyclotomic/Discriminant.lean b/Mathlib/NumberTheory/Cyclotomic/Discriminant.lean index 3ca7d4838404a..e526d1422118e 100644 --- a/Mathlib/NumberTheory/Cyclotomic/Discriminant.lean +++ b/Mathlib/NumberTheory/Cyclotomic/Discriminant.lean @@ -189,7 +189,7 @@ theorem discr_prime_pow_eq_unit_mul_pow [IsCyclotomicExtension {p ^ k} K L] by_cases heven : Even ((p ^ k : ℕ).totient / 2) · exact ⟨1, (p : ℕ) ^ (k - 1) * ((p - 1) * k - 1), by rw [heven.neg_one_pow]; norm_num⟩ · exact ⟨-1, (p : ℕ) ^ (k - 1) * ((p - 1) * k - 1), by - rw [(odd_iff_not_even.2 heven).neg_one_pow]; norm_num⟩ + rw [(not_even_iff_odd.1 heven).neg_one_pow]; norm_num⟩ /-- If `p` is an odd prime and `IsCyclotomicExtension {p} K L`, then `discr K (hζ.powerBasis K).basis = (-1) ^ ((p - 1) / 2) * p ^ (p - 2)` if diff --git a/Mathlib/NumberTheory/Cyclotomic/Gal.lean b/Mathlib/NumberTheory/Cyclotomic/Gal.lean index 003aa4ddd67fb..fb381459d36cf 100644 --- a/Mathlib/NumberTheory/Cyclotomic/Gal.lean +++ b/Mathlib/NumberTheory/Cyclotomic/Gal.lean @@ -85,12 +85,12 @@ noncomputable def Aut.commGroup : CommGroup (L ≃ₐ[K] L) := ((zeta_spec n K L).autToPow_injective K).commGroup _ (map_one _) (map_mul _) (map_inv _) (map_div _) (map_pow _) (map_zpow _) -variable (h : Irreducible (cyclotomic n K)) {K} (L) +variable {K} (L) /-- The `MulEquiv` that takes an automorphism `f` to the element `k : (ZMod n)ˣ` such that `f μ = μ ^ k` for any root of unity `μ`. A strengthening of `IsPrimitiveRoot.autToPow`. -/ @[simps] -noncomputable def autEquivPow : (L ≃ₐ[K] L) ≃* (ZMod n)ˣ := +noncomputable def autEquivPow (h : Irreducible (cyclotomic n K)) : (L ≃ₐ[K] L) ≃* (ZMod n)ˣ := let hζ := zeta_spec n K L let hμ t := hζ.pow_of_coprime _ (ZMod.val_coe_unit_coprime t) { (zeta_spec n K L).autToPow K with @@ -131,7 +131,7 @@ noncomputable def autEquivPow : (L ≃ₐ[K] L) ≃* (ZMod n)ˣ := simp only [ZMod.natCast_val, ZMod.cast_id', id] at key exact Units.ext key } -variable {L} +variable (h : Irreducible (cyclotomic n K)) {L} /-- Maps `μ` to the `AlgEquiv` that sends `IsCyclotomicExtension.zeta` to `μ`. -/ noncomputable def fromZetaAut : L ≃ₐ[K] L := diff --git a/Mathlib/NumberTheory/Cyclotomic/PrimitiveRoots.lean b/Mathlib/NumberTheory/Cyclotomic/PrimitiveRoots.lean index 14303f635d275..f03c4570e3c99 100644 --- a/Mathlib/NumberTheory/Cyclotomic/PrimitiveRoots.lean +++ b/Mathlib/NumberTheory/Cyclotomic/PrimitiveRoots.lean @@ -243,7 +243,7 @@ theorem exists_neg_pow_of_isOfFinOrder [IsCyclotomicExtension {n} ℚ K] convert IsPrimitiveRoot.orderOf (-ζ) rw [neg_eq_neg_one_mul, (Commute.all _ _).orderOf_mul_eq_mul_orderOf_of_coprime] · simp [hζ.eq_orderOf] - · simp [← hζ.eq_orderOf, Nat.odd_iff_not_even.1 hno] + · simp [← hζ.eq_orderOf, hno] obtain ⟨k, hkpos, hkn⟩ := isOfFinOrder_iff_pow_eq_one.1 hx obtain ⟨l, hl, hlroot⟩ := (isRoot_of_unity_iff hkpos _).1 hkn have hlzero : NeZero l := ⟨fun h ↦ by simp [h] at hl⟩ @@ -291,7 +291,7 @@ theorem norm_eq_one [IsDomain L] [IsCyclotomicExtension {n} K L] (hn : n ≠ 2) · replace h1 : 2 ≤ n := by by_contra! h exact h1 (PNat.eq_one_of_lt_two h) --- Porting note: specyfing the type of `cyclotomic_coeff_zero K h1` was not needed. +-- Porting note: specifying the type of `cyclotomic_coeff_zero K h1` was not needed. rw [← hζ.powerBasis_gen K, PowerBasis.norm_gen_eq_coeff_zero_minpoly, hζ.powerBasis_gen K, ← hζ.minpoly_eq_cyclotomic_of_irreducible hirr, (cyclotomic_coeff_zero K h1 : coeff (cyclotomic n K) 0 = 1), mul_one, @@ -411,7 +411,7 @@ theorem norm_pow_sub_one_of_prime_pow_ne_two {k s : ℕ} (hζ : IsPrimitiveRoot · 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 1 [← add_sub_cancel_right η 1] + 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) diff --git a/Mathlib/NumberTheory/Cyclotomic/Rat.lean b/Mathlib/NumberTheory/Cyclotomic/Rat.lean index 230f3be84d42c..58f251949cb62 100644 --- a/Mathlib/NumberTheory/Cyclotomic/Rat.lean +++ b/Mathlib/NumberTheory/Cyclotomic/Rat.lean @@ -225,7 +225,8 @@ unity and `K` is a `p`-th cyclotomic extension of `ℚ`. -/ noncomputable def _root_.IsPrimitiveRoot.adjoinEquivRingOfIntegers' [hcycl : IsCyclotomicExtension {p} ℚ K] (hζ : IsPrimitiveRoot ζ p) : adjoin ℤ ({ζ} : Set K) ≃ₐ[ℤ] 𝓞 K := - @adjoinEquivRingOfIntegers p 1 K _ _ _ _ (by convert hcycl; rw [pow_one]) (by rwa [pow_one]) + have : IsCyclotomicExtension {p ^ 1} ℚ K := by convert hcycl; rw [pow_one] + adjoinEquivRingOfIntegers (p := p) (k := 1) (ζ := ζ) (by rwa [pow_one]) /-- The ring of integers of a `p`-th cyclotomic extension of `ℚ` is a cyclotomic extension. -/ instance _root_.IsCyclotomicExtension.ring_of_integers' [IsCyclotomicExtension {p} ℚ K] : @@ -237,18 +238,19 @@ instance _root_.IsCyclotomicExtension.ring_of_integers' [IsCyclotomicExtension { cyclotomic extension of `ℚ`. -/ noncomputable def integralPowerBasis' [hcycl : IsCyclotomicExtension {p} ℚ K] (hζ : IsPrimitiveRoot ζ p) : PowerBasis ℤ (𝓞 K) := - @integralPowerBasis p 1 K _ _ _ _ (by convert hcycl; rw [pow_one]) (by rwa [pow_one]) + have : IsCyclotomicExtension {p ^ 1} ℚ K := by convert hcycl; rw [pow_one] + integralPowerBasis (p := p) (k := 1) (ζ := ζ) (by rwa [pow_one]) @[simp] theorem integralPowerBasis'_gen [hcycl : IsCyclotomicExtension {p} ℚ K] (hζ : IsPrimitiveRoot ζ p) : hζ.integralPowerBasis'.gen = hζ.toInteger := - @integralPowerBasis_gen p 1 K _ _ _ _ (by convert hcycl; rw [pow_one]) (by rwa [pow_one]) + integralPowerBasis_gen (hcycl := by rwa [pow_one]) (by rwa [pow_one]) @[simp] theorem power_basis_int'_dim [hcycl : IsCyclotomicExtension {p} ℚ K] (hζ : IsPrimitiveRoot ζ p) : hζ.integralPowerBasis'.dim = φ p := by - erw [@integralPowerBasis_dim p 1 K _ _ _ _ (by convert hcycl; rw [pow_one]) (by rwa [pow_one]), - pow_one] + erw [integralPowerBasis_dim (hcycl := by rwa [pow_one]) (by rwa [pow_one]), pow_one] + /-- The integral `PowerBasis` of `𝓞 K` given by `ζ - 1`, where `K` is a `p ^ k` cyclotomic extension of `ℚ`. -/ @@ -259,9 +261,7 @@ noncomputable def subOneIntegralPowerBasis [IsCyclotomicExtension {p ^ k} ℚ K] simp only [integralPowerBasis_gen, toInteger] convert Subalgebra.add_mem _ (self_mem_adjoin_singleton ℤ (⟨ζ - 1, _⟩ : 𝓞 K)) (Subalgebra.one_mem _) --- Porting note: `simp` was able to finish the proof. - · simp only [Subsemiring.coe_add, Subalgebra.coe_toSubsemiring, - OneMemClass.coe_one, sub_add_cancel] + · simp · exact Subalgebra.sub_mem _ (hζ.isIntegral (by simp)) (Subalgebra.one_mem _)) @[simp] @@ -273,15 +273,18 @@ theorem subOneIntegralPowerBasis_gen [IsCyclotomicExtension {p ^ k} ℚ K] /-- The integral `PowerBasis` of `𝓞 K` given by `ζ - 1`, where `K` is a `p`-th cyclotomic extension of `ℚ`. -/ -noncomputable def subOneIntegralPowerBasis' [hcycl : IsCyclotomicExtension {p} ℚ K] +noncomputable def subOneIntegralPowerBasis' [IsCyclotomicExtension {p} ℚ K] (hζ : IsPrimitiveRoot ζ p) : PowerBasis ℤ (𝓞 K) := - @subOneIntegralPowerBasis p 1 K _ _ _ _ (by convert hcycl; rw [pow_one]) (by rwa [pow_one]) + have : IsCyclotomicExtension {p ^ 1} ℚ K := by rwa [pow_one] + subOneIntegralPowerBasis (p := p) (k := 1) (ζ := ζ) (by rwa [pow_one]) -@[simp] -theorem subOneIntegralPowerBasis'_gen [hcycl : IsCyclotomicExtension {p} ℚ K] +@[simp, nolint unusedHavesSuffices] +theorem subOneIntegralPowerBasis'_gen [IsCyclotomicExtension {p} ℚ K] (hζ : IsPrimitiveRoot ζ p) : hζ.subOneIntegralPowerBasis'.gen = hζ.toInteger - 1 := - @subOneIntegralPowerBasis_gen p 1 K _ _ _ _ (by convert hcycl; rw [pow_one]) (by rwa [pow_one]) + -- The `unusedHavesSuffices` linter incorrectly thinks this `have` is unnecessary. + have : IsCyclotomicExtension {p ^ 1} ℚ K := by rwa [pow_one] + subOneIntegralPowerBasis_gen (by rwa [pow_one]) /-- `ζ - 1` is prime if `p ≠ 2` and `ζ` is a primitive `p ^ (k + 1)`-th root of unity. See `zeta_sub_one_prime` for a general statement. -/ diff --git a/Mathlib/NumberTheory/Dioph.lean b/Mathlib/NumberTheory/Dioph.lean index 674ecffb62b68..721b81b5271ba 100644 --- a/Mathlib/NumberTheory/Dioph.lean +++ b/Mathlib/NumberTheory/Dioph.lean @@ -439,14 +439,15 @@ open Vector3 open scoped Vector3 -- Porting note: Fails because declaration is in an imported module --- attribute [local reducible] Vector3 +set_option allowUnsafeReducibility true in +attribute [local reducible] Vector3 theorem diophFn_vec_comp1 {S : Set (Vector3 ℕ (succ n))} (d : Dioph S) {f : Vector3 ℕ n → ℕ} (df : DiophFn f) : Dioph {v : Vector3 ℕ n | (f v::v) ∈ S} := Dioph.ext (diophFn_comp1 (reindex_dioph _ (none::some) d) df) (fun v => by dsimp -- Porting note: `congr` use to be enough here - refine iff_of_eq (congrFun (congrArg Membership.mem ?_) S) + suffices ((f v ::ₒ v) ∘ none :: some) = f v :: v by rw [this]; rfl ext x; cases x <;> rfl) theorem vec_ex1_dioph (n) {S : Set (Vector3 ℕ (succ n))} (d : Dioph S) : @@ -470,7 +471,7 @@ theorem diophFn_compn : ext (reindex_dioph _ (id ⊗ Fin2.elim0) d) fun v => by dsimp -- Porting note: `congr` use to be enough here - refine iff_of_eq (congrFun (congrArg Membership.mem ?_) S) + suffices v ∘ (id ⊗ elim0) = v ⊗ fun i ↦ f i v by rw [this] ext x; obtain _ | _ | _ := x; rfl | succ n, S, d, f => f.consElim fun f fl => by @@ -482,14 +483,15 @@ theorem diophFn_compn : fun v => by dsimp -- Porting note: `congr` use to be enough here - refine iff_of_eq (congrFun (congrArg Membership.mem ?_) S) + suffices (f (v ∘ inl) ::ₒ v) ∘ (some ∘ inl ⊗ none :: some ∘ inr) = + v ∘ inl ⊗ f (v ∘ inl) :: v ∘ inr by rw [this] ext x; obtain _ | _ | _ := x <;> rfl have : Dioph {v | (v ⊗ f v::fun i : Fin2 n => fl i v) ∈ S} := @diophFn_compn n (fun v => S (v ∘ inl ⊗ f (v ∘ inl)::v ∘ inr)) this _ dfl ext this fun v => by dsimp -- Porting note: `congr` use to be enough here - refine iff_of_eq (congrFun (congrArg Membership.mem ?_) S) + suffices (v ⊗ f v :: fun i ↦ fl i v) = v ⊗ fun i ↦ (f :: fl) i v by rw [this] ext x; obtain _ | _ | _ := x <;> rfl theorem dioph_comp {S : Set (Vector3 ℕ n)} (d : Dioph S) (f : Vector3 ((α → ℕ) → ℕ) n) diff --git a/Mathlib/NumberTheory/DiophantineApproximation.lean b/Mathlib/NumberTheory/DiophantineApproximation.lean index e92bec64ba8ec..77d109b645420 100644 --- a/Mathlib/NumberTheory/DiophantineApproximation.lean +++ b/Mathlib/NumberTheory/DiophantineApproximation.lean @@ -93,7 +93,7 @@ theorem exists_int_int_abs_mul_sub_le (ξ : ℝ) {n : ℕ} (n_pos : 0 < n) : let f : ℤ → ℤ := fun m => ⌊fract (ξ * m) * (n + 1)⌋ have hn : 0 < (n : ℝ) + 1 := mod_cast Nat.succ_pos _ have hfu := fun m : ℤ => mul_lt_of_lt_one_left hn <| fract_lt_one (ξ * ↑m) - conv in |_| ≤ _ => rw [mul_comm, le_div_iff hn, ← abs_of_pos hn, ← abs_mul] + conv in |_| ≤ _ => rw [mul_comm, le_div_iff₀ hn, ← abs_of_pos hn, ← abs_mul] let D := Icc (0 : ℤ) n by_cases H : ∃ m ∈ D, f m = n · obtain ⟨m, hm, hf⟩ := H @@ -153,7 +153,7 @@ theorem exists_rat_abs_sub_le_and_den_le (ξ : ℝ) {n : ℕ} (n_pos : 0 < n) : convert le_of_dvd hk₀ (Rat.den_dvd j k) exact Rat.intCast_div_eq_divInt _ _ refine ⟨j / k, ?_, Nat.cast_le.mp (hden.trans hk₁)⟩ - rw [← div_div, le_div_iff (Nat.cast_pos.mpr <| Rat.pos _ : (0 : ℝ) < _)] + rw [← div_div, le_div_iff₀ (Nat.cast_pos.mpr <| Rat.pos _ : (0 : ℝ) < _)] refine (mul_le_mul_of_nonneg_left (Int.cast_le.mpr hden : _ ≤ (k : ℝ)) (abs_nonneg _)).trans ?_ rwa [← abs_of_pos hk₀', Rat.cast_div, Rat.cast_intCast, Rat.cast_intCast, ← abs_mul, sub_mul, div_mul_cancel₀ _ hk₀'.ne', mul_comm] diff --git a/Mathlib/NumberTheory/EllipticDivisibilitySequence.lean b/Mathlib/NumberTheory/EllipticDivisibilitySequence.lean index bca41d94b0569..b48aa4e66e245 100644 --- a/Mathlib/NumberTheory/EllipticDivisibilitySequence.lean +++ b/Mathlib/NumberTheory/EllipticDivisibilitySequence.lean @@ -119,7 +119,7 @@ def preNormEDS' (b c d : R) : ℕ → R preNormEDS' b c d (m + 1) * preNormEDS' b c d (m + 3) ^ 3 * (if Even m then 1 else b) else have h5 : m + 5 < n + 5 := add_lt_add_right - (Nat.div_lt_self (Nat.odd_iff_not_even.mpr hn).pos <| Nat.lt_succ_self 1) 5 + (Nat.div_lt_self (Nat.not_even_iff_odd.1 hn).pos <| Nat.lt_succ_self 1) 5 preNormEDS' b c d (m + 2) ^ 2 * preNormEDS' b c d (m + 3) * preNormEDS' b c d (m + 5) - preNormEDS' b c d (m + 1) * preNormEDS' b c d (m + 3) * preNormEDS' b c d (m + 4) ^ 2 diff --git a/Mathlib/NumberTheory/EulerProduct/DirichletLSeries.lean b/Mathlib/NumberTheory/EulerProduct/DirichletLSeries.lean index 82d366d734cee..ba72ec28fdfcd 100644 --- a/Mathlib/NumberTheory/EulerProduct/DirichletLSeries.lean +++ b/Mathlib/NumberTheory/EulerProduct/DirichletLSeries.lean @@ -77,12 +77,8 @@ lemma summable_dirichletSummand {N : ℕ} (χ : DirichletCharacter ℂ N) (hs : open scoped LSeries.notation in lemma tsum_dirichletSummand {N : ℕ} (χ : DirichletCharacter ℂ N) (hs : 1 < s.re) : ∑' (n : ℕ), dirichletSummandHom χ (ne_zero_of_one_lt_re hs) n = L ↗χ s := by - simp only [LSeries, LSeries.term, dirichletSummandHom] - refine tsum_congr (fun n ↦ ?_) - rcases eq_or_ne n 0 with rfl | hn - · simp only [map_zero, ↓reduceIte] - · simp only [cpow_neg, MonoidWithZeroHom.coe_mk, ZeroHom.coe_mk, hn, ↓reduceIte, - Field.div_eq_mul_inv] + simp only [dirichletSummandHom, cpow_neg, MonoidWithZeroHom.coe_mk, ZeroHom.coe_mk, LSeries, + LSeries.term_of_ne_zero' (ne_zero_of_one_lt_re hs), div_eq_mul_inv] open Filter Nat Topology EulerProduct diff --git a/Mathlib/NumberTheory/FLT/Basic.lean b/Mathlib/NumberTheory/FLT/Basic.lean index 49253dbdcc2fd..908060bf6699e 100644 --- a/Mathlib/NumberTheory/FLT/Basic.lean +++ b/Mathlib/NumberTheory/FLT/Basic.lean @@ -175,7 +175,7 @@ lemma fermatLastTheoremWith_of_fermatLastTheoremWith_coprime {n : ℕ} {R : Type rw [← Finset.gcd_mul_left, gcd_eq_gcd_image, image_insert, image_insert, image_singleton, id_eq, id_eq, id_eq, ← hA, ← hB, ← hC] -lemma dvd_c_of_prime_of_dvd_a_of_dvd_b_of_FLT {n : ℕ} {p : ℤ} (hp : Prime p) {a b c : ℤ} +lemma dvd_c_of_prime_of_dvd_a_of_dvd_b_of_FLT {n : ℕ} {p : ℤ} (hp : Prime p) {a b c : ℤ} (hpa : p ∣ a) (hpb : p ∣ b) (HF : a ^ n + b ^ n + c ^ n = 0) : p ∣ c := by rcases eq_or_ne n 0 with rfl | hn · simp at HF diff --git a/Mathlib/NumberTheory/FLT/Three.lean b/Mathlib/NumberTheory/FLT/Three.lean index 68fcc6a03f0ea..555bad3224e64 100644 --- a/Mathlib/NumberTheory/FLT/Three.lean +++ b/Mathlib/NumberTheory/FLT/Three.lean @@ -116,7 +116,7 @@ private lemma fermatLastTheoremThree_of_dvd_a_of_gcd_eq_one_of_case2 {a b c : open Finset Int in /-- - To prove Fermat's Last Theorem for `n = 3`, it is enough to show that that for all `a`, `b`, `c` + To prove Fermat's Last Theorem for `n = 3`, it is enough to show that for all `a`, `b`, `c` in `ℤ` such that `c ≠ 0`, `¬ 3 ∣ a`, `¬ 3 ∣ b`, `a` and `b` are coprime and `3 ∣ c`, we have `a ^ 3 + b ^ 3 ≠ c ^ 3`. -/ @@ -241,7 +241,7 @@ lemma Solution.exists_minimal : ∃ (S₁ : Solution hζ), S₁.isMinimal := by end DecidableRel /-- Given `S' : Solution'`, then `S'.a` and `S'.b` are both congruent to `1` modulo `λ ^ 4` or are -both congruent to `-1`. -/ +both congruent to `-1`. -/ lemma a_cube_b_cube_congr_one_or_neg_one : λ ^ 4 ∣ S'.a ^ 3 - 1 ∧ λ ^ 4 ∣ S'.b ^ 3 + 1 ∨ λ ^ 4 ∣ S'.a ^ 3 + 1 ∧ λ ^ 4 ∣ S'.b ^ 3 - 1 := by obtain ⟨z, hz⟩ := S'.hcdvd diff --git a/Mathlib/NumberTheory/Harmonic/EulerMascheroni.lean b/Mathlib/NumberTheory/Harmonic/EulerMascheroni.lean index 92a72fe1377c1..e61b195e807ac 100644 --- a/Mathlib/NumberTheory/Harmonic/EulerMascheroni.lean +++ b/Mathlib/NumberTheory/Harmonic/EulerMascheroni.lean @@ -84,7 +84,7 @@ lemma strictAnti_eulerMascheroniSeq' : StrictAnti eulerMascheroniSeq' := by refine strictAnti_nat_of_succ_lt (fun n ↦ ?_) rcases Nat.eq_zero_or_pos n with rfl | hn · simp [eulerMascheroniSeq'] - simp_rw [eulerMascheroniSeq', eq_false_intro hn.ne', if_false] + simp_rw [eulerMascheroniSeq', eq_false_intro hn.ne', reduceCtorEq, if_false] rw [← sub_pos, sub_sub_sub_comm, harmonic_succ, Rat.cast_add, ← sub_sub, sub_self, zero_sub, sub_eq_add_neg, neg_sub, ← sub_eq_neg_add, sub_pos, ← log_div (by positivity) (by positivity), ← neg_lt_neg_iff, diff --git a/Mathlib/NumberTheory/Harmonic/GammaDeriv.lean b/Mathlib/NumberTheory/Harmonic/GammaDeriv.lean index a66d5d7a47b91..90e05ffd8ff51 100644 --- a/Mathlib/NumberTheory/Harmonic/GammaDeriv.lean +++ b/Mathlib/NumberTheory/Harmonic/GammaDeriv.lean @@ -4,12 +4,13 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: David Loeffler -/ -import Mathlib.NumberTheory.Harmonic.EulerMascheroni +import Mathlib.Analysis.Convex.Deriv import Mathlib.Analysis.SpecialFunctions.Gamma.Deligne import Mathlib.Data.Nat.Factorial.Basic +import Mathlib.NumberTheory.Harmonic.EulerMascheroni /-! -# Derivative of Γ at positive integers +# Derivative of Γ at positive integers We prove the formula for the derivative of `Real.Gamma` at a positive integer: diff --git a/Mathlib/NumberTheory/Harmonic/ZetaAsymp.lean b/Mathlib/NumberTheory/Harmonic/ZetaAsymp.lean index c5c6b9529953e..99e63c94ec211 100644 --- a/Mathlib/NumberTheory/Harmonic/ZetaAsymp.lean +++ b/Mathlib/NumberTheory/Harmonic/ZetaAsymp.lean @@ -37,7 +37,7 @@ namespace ZetaAsymptotics -- since the intermediate lemmas are of little interest in themselves we put them in a namespace /-! -## Definitions +## Definitions -/ /-- Auxiliary function used in studying zeta-function asymptotics. -/ @@ -128,7 +128,7 @@ lemma term_tsum_one : HasSum (fun n ↦ term (n + 1) 1) (1 - γ) := by refine Tendsto.add ?_ tendsto_const_nhds have := (tendsto_eulerMascheroniSeq'.comp (tendsto_add_atTop_nat 1)).neg refine this.congr' (Eventually.of_forall (fun n ↦ ?_)) - simp_rw [Function.comp_apply, eulerMascheroniSeq', if_false] + simp_rw [Function.comp_apply, eulerMascheroniSeq', reduceCtorEq, if_false] push_cast abel diff --git a/Mathlib/NumberTheory/JacobiSum/Basic.lean b/Mathlib/NumberTheory/JacobiSum/Basic.lean new file mode 100644 index 0000000000000..6c989fdfbe4bb --- /dev/null +++ b/Mathlib/NumberTheory/JacobiSum/Basic.lean @@ -0,0 +1,110 @@ +/- +Copyright (c) 2024 Michael Stoll. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Michael Stoll +-/ +import Mathlib.NumberTheory.MulChar.Basic +import Mathlib.Algebra.Module.BigOperators + +/-! +# Jacobi Sums + +This file defines the *Jacobi sum* of two multiplicative characters `χ` and `ψ` on a finite +commutative ring `R` with values in another commutative ring `R'`: + +`jacobiSum χ ψ = ∑ x : R, χ x * ψ (1 - x)` + +(see `jacobiSum`) and provides some basic results and API lemmas on Jacobi sums. + +## References + +We essentially follow +* [K. Ireland, M. Rosen, *A classical introduction to modern number theory* + (Section 8.3)][IrelandRosen1990] + +but generalize where appropriate. + +This is based on Lean code written as part of the bachelor's thesis of Alexander Spahl. +-/ + +open BigOperators Finset + +/-! +### Jacobi sums: definition and first properties +-/ + +section Def + +-- need `Fintype` instead of `Finite` to make `jacobiSum` computable. +variable {R R' : Type*} [CommRing R] [Fintype R] [CommRing R'] + +/-- The *Jacobi sum* of two multiplicative characters on a finite commutative ring. -/ +def jacobiSum (χ ψ : MulChar R R') : R' := + ∑ x : R, χ x * ψ (1 - x) + +lemma jacobiSum_comm (χ ψ : MulChar R R') : jacobiSum χ ψ = jacobiSum ψ χ := by + simp only [jacobiSum, mul_comm (χ _)] + rw [← (Equiv.subLeft 1).sum_comp] + simp only [Equiv.subLeft_apply, sub_sub_cancel] + +/-- The Jacobi sum is compatible with ring homomorphisms. -/ +lemma jacobiSum_ringHomComp {R'' : Type*} [CommRing R''] (χ ψ : MulChar R R') (f : R' →+* R'') : + jacobiSum (χ.ringHomComp f) (ψ.ringHomComp f) = f (jacobiSum χ ψ) := by + simp only [jacobiSum, MulChar.ringHomComp, MulChar.coe_mk, MonoidHom.coe_mk, OneHom.coe_mk, + map_sum, map_mul] + +end Def + +/-! +### Jacobi sums over finite fields +-/ + +section FiniteField + +variable {F R : Type*} [Field F] [Fintype F] [DecidableEq F] [CommRing R] + +/-- The Jacobi sum of two multiplicative characters on a finite field `F` can be written +as a sum over `F \ {0,1}`. -/ +lemma jacobiSum_eq_sum_sdiff (χ ψ : MulChar F R) : + jacobiSum χ ψ = ∑ x ∈ univ \ {0,1}, χ x * ψ (1 - x) := by + simp only [jacobiSum, subset_univ, sum_sdiff_eq_sub, mem_singleton, zero_ne_one, + not_false_eq_true, sum_insert, isUnit_iff_ne_zero, ne_eq, not_true_eq_false, + MulCharClass.map_nonunit, sub_zero, map_one, mul_one, sum_singleton, sub_self, mul_zero, + add_zero] + +private lemma jacobiSum_eq_aux (χ ψ : MulChar F R) : + jacobiSum χ ψ = ∑ x : F, χ x + ∑ x : F, ψ x - Fintype.card F + + ∑ x ∈ univ \ {0, 1}, (χ x - 1) * (ψ (1 - x) - 1) := by + rw [jacobiSum] + conv => + enter [1, 2, x] + rw [show ∀ x y : R, x * y = x + y - 1 + (x - 1) * (y - 1) by intros; ring] + rw [sum_add_distrib, sum_sub_distrib, sum_add_distrib] + conv => enter [1, 1, 1, 2, 2, x]; rw [← Equiv.subLeft_apply 1] + rw [(Equiv.subLeft 1).sum_comp ψ, Fintype.card_eq_sum_ones, Nat.cast_sum, Nat.cast_one, + sum_sdiff_eq_sub (subset_univ _), ← sub_zero (_ - _ + _), add_sub_assoc] + congr + rw [sum_pair zero_ne_one, sub_zero, ψ.map_one, χ.map_one, sub_self, mul_zero, zero_mul, add_zero] + +/-- The Jacobi sum of twice the trivial multiplicative character on a finite field `F` +equals `#F-2`. -/ +theorem jacobiSum_trivial_trivial : + jacobiSum (MulChar.trivial F R) (MulChar.trivial F R) = Fintype.card F - 2 := by + rw [jacobiSum_eq_sum_sdiff] + have : ∀ x ∈ univ \ {0, 1}, (MulChar.trivial F R) x * (MulChar.trivial F R) (1 - x) = 1 := by + intros x hx + rw [← map_mul, MulChar.trivial_apply, if_pos] + simp only [mem_sdiff, mem_univ, mem_insert, mem_singleton, not_or, ← ne_eq, true_and] at hx + simpa only [isUnit_iff_ne_zero, mul_ne_zero_iff, ne_eq, sub_eq_zero, @eq_comm _ _ x] using hx + calc ∑ x ∈ univ \ {0, 1}, (MulChar.trivial F R) x * (MulChar.trivial F R) (1 - x) + _ = ∑ _ ∈ univ \ {0, 1}, 1 := sum_congr rfl this + _ = Finset.card (univ \ {0, 1}) := (cast_card _).symm + _ = Fintype.card F - 2 := by + rw [card_sdiff (subset_univ _), card_univ, card_pair zero_ne_one, + Nat.cast_sub <| Nat.add_one_le_of_lt Fintype.one_lt_card, Nat.cast_two] + +/-- If `1` is the trivial multiplicative character on a finite field `F`, then `J(1,1) = #F-2`. -/ +theorem jacobiSum_one_one : jacobiSum (1 : MulChar F R) 1 = Fintype.card F - 2 := + jacobiSum_trivial_trivial + +end FiniteField diff --git a/Mathlib/NumberTheory/KummerDedekind.lean b/Mathlib/NumberTheory/KummerDedekind.lean index 747f0b3cbec26..b93799f8bfa38 100644 --- a/Mathlib/NumberTheory/KummerDedekind.lean +++ b/Mathlib/NumberTheory/KummerDedekind.lean @@ -111,9 +111,9 @@ variable {I : Ideal R} theorem prod_mem_ideal_map_of_mem_conductor {p : R} {z : S} (hp : p ∈ Ideal.comap (algebraMap R S) (conductor R x)) (hz' : z ∈ I.map (algebraMap R S)) : algebraMap R S p * z ∈ algebraMap R S '' ↑(I.map (algebraMap R R)) := by - rw [Ideal.map, Ideal.span, Finsupp.mem_span_image_iff_total] at hz' + rw [Ideal.map, Ideal.span, Finsupp.mem_span_image_iff_linearCombination] at hz' obtain ⟨l, H, H'⟩ := hz' - rw [Finsupp.total_apply] at H' + rw [Finsupp.linearCombination_apply] at H' rw [← H', mul_comm, Finsupp.sum_mul] have lem : ∀ {a : R}, a ∈ I → l a • algebraMap R S a * algebraMap R S p ∈ algebraMap R S '' I.map (algebraMap R R) := by @@ -168,7 +168,8 @@ theorem comap_map_eq_map_adjoin_of_coprime_conductor obtain ⟨x₁, hx₁, hx₂⟩ := (Set.mem_image _ _ _).mp h have : x₁ = ⟨z, hz⟩ := by apply h_alg - simp [hx₂, algebraMap_eq_smul_one] + simp only [hx₂, algebraMap_eq_smul_one] + rw [Submonoid.mk_smul, smul_eq_mul, mul_one] rwa [← this] · -- The converse inclusion is trivial have : algebraMap R S = (algebraMap _ S).comp (algebraMap R R) := by ext; rfl @@ -282,8 +283,8 @@ theorem normalizedFactors_ideal_map_eq_normalizedFactors_min_poly_mk_map (hI : I by_cases hJ : J ∈ normalizedFactors (I.map (algebraMap R S)) swap · rw [Multiset.count_eq_zero.mpr hJ, eq_comm, Multiset.count_eq_zero, Multiset.mem_map] - simp only [Multiset.mem_attach, true_and_iff, not_exists] - rintro J' rfl + simp only [not_exists] + rintro J' ⟨_, rfl⟩ exact hJ ((normalizedFactorsMapEquivNormalizedFactorsMinPolyMk hI hI' hx hx').symm J').prop -- Then we just have to compare the multiplicities, which we already proved are equal. diff --git a/Mathlib/NumberTheory/LSeries/AbstractFuncEq.lean b/Mathlib/NumberTheory/LSeries/AbstractFuncEq.lean index 14bfeef13fb1d..9395e10f0cc6f 100644 --- a/Mathlib/NumberTheory/LSeries/AbstractFuncEq.lean +++ b/Mathlib/NumberTheory/LSeries/AbstractFuncEq.lean @@ -145,7 +145,7 @@ lemma hf_zero (P : WeakFEPair E) (r : ℝ) : specialize hC' hx simp_rw [Function.comp_apply, ← one_div, P.h_feq' _ hx] at hC' rw [← ((mul_inv_cancel₀ h_nv).symm ▸ one_smul ℂ P.g₀ :), mul_smul _ _ P.g₀, ← smul_sub, norm_smul, - ← le_div_iff' (lt_of_le_of_ne (norm_nonneg _) (norm_ne_zero_iff.mpr h_nv).symm)] at hC' + ← le_div_iff₀' (lt_of_le_of_ne (norm_nonneg _) (norm_ne_zero_iff.mpr h_nv).symm)] at hC' convert hC' using 1 · congr 3 rw [rpow_neg hx.le] diff --git a/Mathlib/NumberTheory/LSeries/Basic.lean b/Mathlib/NumberTheory/LSeries/Basic.lean index 4087714eb2195..7221b06b0360f 100644 --- a/Mathlib/NumberTheory/LSeries/Basic.lean +++ b/Mathlib/NumberTheory/LSeries/Basic.lean @@ -77,6 +77,16 @@ lemma term_of_ne_zero {n : ℕ} (hn : n ≠ 0) (f : ℕ → ℂ) (s : ℂ) : term f s n = f n / n ^ s := if_neg hn +/-- +If `s ≠ 0`, then the `if .. then .. else` construction in `LSeries.term` isn't needed, since +`0 ^ s = 0`. +-/ +lemma term_of_ne_zero' {s : ℂ} (hs : s ≠ 0) (f : ℕ → ℂ) (n : ℕ) : + term f s n = f n / n ^ s := by + rcases eq_or_ne n 0 with rfl | hn + · rw [term_zero, Nat.cast_zero, zero_cpow hs, div_zero] + · rw [term_of_ne_zero hn] + lemma term_congr {f g : ℕ → ℂ} (h : ∀ {n}, n ≠ 0 → f n = g n) (s : ℂ) (n : ℕ) : term f s n = term g s n := by rcases eq_or_ne n 0 with hn | hn <;> simp [hn, h] @@ -282,7 +292,7 @@ lemma LSeriesSummable.le_const_mul_rpow {f : ℕ → ℂ} {s : ℂ} (h : LSeries obtain ⟨n, hn₀, hn⟩ := H (tsum fun n ↦ ‖term f s n‖) have := le_tsum h n fun _ _ ↦ norm_nonneg _ rw [norm_term_eq, if_neg hn₀, - div_le_iff <| Real.rpow_pos_of_pos (Nat.cast_pos.mpr <| Nat.pos_of_ne_zero hn₀) _] at this + div_le_iff₀ <| Real.rpow_pos_of_pos (Nat.cast_pos.mpr <| Nat.pos_of_ne_zero hn₀) _] at this exact (this.trans_lt hn).false.elim open Filter in @@ -320,7 +330,7 @@ lemma LSeriesSummable_of_le_const_mul_rpow {f : ℕ → ℂ} {x : ℝ} {s : ℂ} · simp only [term_zero, norm_zero] exact norm_nonneg _ have hn' : 0 < (n : ℝ) ^ s.re := Real.rpow_pos_of_pos (Nat.cast_pos.mpr hn) _ - simp_rw [term_of_ne_zero hn.ne', norm_div, norm_natCast_cpow_of_pos hn, div_le_iff hn', + simp_rw [term_of_ne_zero hn.ne', norm_div, norm_natCast_cpow_of_pos hn, div_le_iff₀ hn', norm_eq_abs (C : ℂ), abs_ofReal, _root_.abs_of_nonneg hC₀, div_eq_mul_inv, mul_assoc, ← Real.rpow_neg <| Nat.cast_nonneg _, ← Real.rpow_add <| Nat.cast_pos.mpr hn] simp only [add_re, sub_re, one_re, ofReal_re, neg_add_rev, neg_sub, neg_add_cancel_right] @@ -344,7 +354,7 @@ lemma LSeriesSummable_of_isBigO_rpow {f : ℕ → ℂ} {x : ℝ} {s : ℂ} (hs : gcongr rw [Real.norm_eq_abs, abs_rpow_of_nonneg hn₀, _root_.abs_of_nonneg hn₀] · have hn' : 0 < n := Nat.pos_of_ne_zero hn₀ - refine (div_le_iff <| rpow_pos_of_pos (cast_pos.mpr hn') _).mp ?_ + refine (div_le_iff₀ <| rpow_pos_of_pos (cast_pos.mpr hn') _).mp ?_ refine (le_max' _ _ <| mem_insert_of_mem ?_).trans <| le_max_right .. exact mem_image.mpr ⟨n, mem_range.mpr hn, rfl⟩ diff --git a/Mathlib/NumberTheory/LSeries/Convolution.lean b/Mathlib/NumberTheory/LSeries/Convolution.lean index 4e4d8dd78c86e..5063a90643a41 100644 --- a/Mathlib/NumberTheory/LSeries/Convolution.lean +++ b/Mathlib/NumberTheory/LSeries/Convolution.lean @@ -109,7 +109,7 @@ lemma term_convolution (f g : ℕ → ℂ) (s : ℂ) (n : ℕ) : open Set in /-- We give an expression of the `LSeries.term` of the convolution of two functions -in terms of an a priori infinte sum over all pairs `(k, m)` with `k * m = n` +in terms of an a priori infinite sum over all pairs `(k, m)` with `k * m = n` (the set we sum over is infinite when `n = 0`). This is the version needed for the proof that `L (f ⍟ g) = L f * L g`. -/ lemma term_convolution' (f g : ℕ → ℂ) (s : ℂ) : diff --git a/Mathlib/NumberTheory/LSeries/Dirichlet.lean b/Mathlib/NumberTheory/LSeries/Dirichlet.lean index 2ee009cb3d46a..6e6fed2c20936 100644 --- a/Mathlib/NumberTheory/LSeries/Dirichlet.lean +++ b/Mathlib/NumberTheory/LSeries/Dirichlet.lean @@ -137,7 +137,7 @@ lemma convolution_mul_moebius {n : ℕ} (χ : DirichletCharacter ℂ n) : ↗χ lemma modZero_eq_delta {χ : DirichletCharacter ℂ 0} : ↗χ = δ := by ext n rcases eq_or_ne n 0 with rfl | hn - · simp_rw [cast_zero, χ.map_nonunit not_isUnit_zero, delta, if_false] + · simp_rw [cast_zero, χ.map_nonunit not_isUnit_zero, delta, reduceCtorEq, if_false] rcases eq_or_ne n 1 with rfl | hn' · simp only [cast_one, map_one, delta, ↓reduceIte] have : ¬ IsUnit (n : ZMod 0) := fun h ↦ hn' <| ZMod.eq_one_of_isUnit_natCast h diff --git a/Mathlib/NumberTheory/LSeries/DirichletContinuation.lean b/Mathlib/NumberTheory/LSeries/DirichletContinuation.lean new file mode 100644 index 0000000000000..dd4b132bc5130 --- /dev/null +++ b/Mathlib/NumberTheory/LSeries/DirichletContinuation.lean @@ -0,0 +1,70 @@ +/- +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.NumberTheory.LSeries.ZMod +import Mathlib.NumberTheory.DirichletCharacter.Basic + +/-! +# Analytic continuation of Dirichlet L-functions + +We show that if `χ` is a Dirichlet character `ZMod N → ℂ`, for a positive integer `N`, then the +L-series of `χ` has analytic continuation (away from a pole at `s = 1` if `χ` is trivial). + +All definitions and theorems are in the `DirichletCharacter` namespace. + +## Main definitions + +* `LFunction χ s`: the L-function, defined as a linear combination of Hurwitz zeta functions. + +## Main theorems + +* `LFunction_eq_LSeries`: if `1 < re s` then the `LFunction` coincides with the naive `LSeries`. +* `differentiable_LFunction`: if `χ` is nontrivial then `LFunction χ s` is differentiable + everywhere. +-/ + +open Complex + +namespace DirichletCharacter + +variable {N : ℕ} [NeZero N] + +/-- +The unique meromorphic function `ℂ → ℂ` which agrees with `∑' n : ℕ, χ n / n ^ s` wherever the +latter is convergent. This is constructed as a linear combination of Hurwitz zeta functions. + +Note that this is not the same as `LSeries χ`: they agree in the convergence range, but +`LSeries χ s` is defined to be `0` if `re s ≤ 1`. + -/ +noncomputable def LFunction (χ : DirichletCharacter ℂ N) (s : ℂ) : ℂ := ZMod.LFunction χ s + +/-- The L-function of the (unique) Dirichlet character mod 1 is the Riemann zeta function. +(Compare `DirichletCharacter.LSeries_modOne_eq`.) -/ +@[simp] lemma LFunction_modOne_eq {χ : DirichletCharacter ℂ 1} : + LFunction χ = riemannZeta := by + ext1; rw [LFunction, ZMod.LFunction_modOne_eq, (by rfl : (0 : ZMod 1) = 1), map_one, one_mul] + +/-- +For `1 < re s` the L-function of a Dirichlet character agrees with the sum of the naive Dirichlet +series. +-/ +lemma LFunction_eq_LSeries (χ : DirichletCharacter ℂ N) {s : ℂ} (hs : 1 < re s) : + LFunction χ s = LSeries (χ ·) s := + ZMod.LFunction_eq_LSeries χ hs + +/-- +The L-function of a Dirichlet character is differentiable, except at `s = 1` if the character is +trivial. +-/ +lemma differentiableAt_LFunction (χ : DirichletCharacter ℂ N) (s : ℂ) (hs : s ≠ 1 ∨ χ ≠ 1) : + DifferentiableAt ℂ (LFunction χ) s := + ZMod.differentiableAt_LFunction χ s (hs.imp_right χ.sum_eq_zero_of_ne_one) + +/-- The L-function of a non-trivial Dirichlet character is differentiable everywhere. -/ +lemma differentiable_LFunction {χ : DirichletCharacter ℂ N} (hχ : χ ≠ 1) : + Differentiable ℂ (LFunction χ) := + (differentiableAt_LFunction _ · <| Or.inr hχ) + +end DirichletCharacter diff --git a/Mathlib/NumberTheory/LSeries/HurwitzZeta.lean b/Mathlib/NumberTheory/LSeries/HurwitzZeta.lean index 79f23403685fc..69091d6315bba 100644 --- a/Mathlib/NumberTheory/LSeries/HurwitzZeta.lean +++ b/Mathlib/NumberTheory/LSeries/HurwitzZeta.lean @@ -142,11 +142,9 @@ lemma differentiable_expZeta_of_ne_zero {a : UnitAddCircle} (ha : a ≠ 0) : /-- Reformulation of `hasSum_expZeta_of_one_lt_re` using `LSeriesHasSum`. -/ lemma LSeriesHasSum_exp (a : ℝ) {s : ℂ} (hs : 1 < re s) : - LSeriesHasSum (cexp <| 2 * π * I * a * ·) s (expZeta a s) := by - refine (hasSum_expZeta_of_one_lt_re a hs).congr_fun (fun n ↦ ?_) - rcases eq_or_ne n 0 with rfl | hn - · rw [LSeries.term_zero, Nat.cast_zero, zero_cpow (ne_zero_of_one_lt_re hs), div_zero] - · apply LSeries.term_of_ne_zero hn + LSeriesHasSum (cexp <| 2 * π * I * a * ·) s (expZeta a s) := + (hasSum_expZeta_of_one_lt_re a hs).congr_fun + (LSeries.term_of_ne_zero' (ne_zero_of_one_lt_re hs) _) /-! ## The functional equation diff --git a/Mathlib/NumberTheory/LSeries/HurwitzZetaEven.lean b/Mathlib/NumberTheory/LSeries/HurwitzZetaEven.lean index 48fb9b87f7ce9..ac307e2324e77 100644 --- a/Mathlib/NumberTheory/LSeries/HurwitzZetaEven.lean +++ b/Mathlib/NumberTheory/LSeries/HurwitzZetaEven.lean @@ -768,12 +768,9 @@ lemma hasSum_nat_cosZeta (a : ℝ) {s : ℂ} (hs : 1 < re s) : /-- Reformulation of `hasSum_nat_cosZeta` using `LSeriesHasSum`. -/ lemma LSeriesHasSum_cos (a : ℝ) {s : ℂ} (hs : 1 < re s) : - LSeriesHasSum (Real.cos <| 2 * π * a * ·) s (cosZeta a s) := by - refine (hasSum_nat_cosZeta a hs).congr_fun (fun n ↦ ?_) - rcases eq_or_ne n 0 with rfl | hn - · rw [LSeries.term_zero, Nat.cast_zero, Nat.cast_zero, zero_cpow (ne_zero_of_one_lt_re hs), - div_zero] - · apply LSeries.term_of_ne_zero hn + LSeriesHasSum (Real.cos <| 2 * π * a * ·) s (cosZeta a s) := + (hasSum_nat_cosZeta a hs).congr_fun + (LSeries.term_of_ne_zero' (ne_zero_of_one_lt_re hs) _) /-! ## Functional equations for the un-completed zetas diff --git a/Mathlib/NumberTheory/LSeries/HurwitzZetaOdd.lean b/Mathlib/NumberTheory/LSeries/HurwitzZetaOdd.lean index e14ca16ba1108..cf70f0a830ee7 100644 --- a/Mathlib/NumberTheory/LSeries/HurwitzZetaOdd.lean +++ b/Mathlib/NumberTheory/LSeries/HurwitzZetaOdd.lean @@ -547,11 +547,9 @@ lemma hasSum_nat_sinZeta (a : ℝ) {s : ℂ} (hs : 1 < re s) : /-- Reformulation of `hasSum_nat_sinZeta` using `LSeriesHasSum`. -/ lemma LSeriesHasSum_sin (a : ℝ) {s : ℂ} (hs : 1 < re s) : - LSeriesHasSum (Real.sin <| 2 * π * a * ·) s (sinZeta a s) := by - refine (hasSum_nat_sinZeta a hs).congr_fun (fun n ↦ ?_) - rcases eq_or_ne n 0 with rfl | hn - · rw [LSeries.term_zero, Nat.cast_zero, mul_zero, Real.sin_zero, ofReal_zero, zero_div] - · apply LSeries.term_of_ne_zero hn + LSeriesHasSum (Real.sin <| 2 * π * a * ·) s (sinZeta a s) := + (hasSum_nat_sinZeta a hs).congr_fun + (LSeries.term_of_ne_zero' (ne_zero_of_one_lt_re hs) _) /-- The trivial zeroes of the odd Hurwitz zeta function. -/ theorem hurwitzZetaOdd_neg_two_mul_nat_sub_one (a : UnitAddCircle) (n : ℕ) : diff --git a/Mathlib/NumberTheory/LSeries/RiemannZeta.lean b/Mathlib/NumberTheory/LSeries/RiemannZeta.lean index 0afac073a7aa4..bcc35496bf6f6 100644 --- a/Mathlib/NumberTheory/LSeries/RiemannZeta.lean +++ b/Mathlib/NumberTheory/LSeries/RiemannZeta.lean @@ -158,7 +158,7 @@ def RiemannHypothesis : Prop := ∀ (s : ℂ) (_ : riemannZeta s = 0) (_ : ¬∃ n : ℕ, s = -2 * (n + 1)) (_ : s ≠ 1), s.re = 1 / 2 /-! -## Relating the Mellin transform to the Dirichlet series +## Relating the Mellin transform to the Dirichlet series -/ theorem completedZeta_eq_tsum_of_one_lt_re {s : ℂ} (hs : 1 < re s) : @@ -182,7 +182,7 @@ theorem zeta_eq_tsum_one_div_nat_cpow {s : ℂ} (hs : 1 < re s) : ofReal_one] using (hasSum_nat_cosZeta 0 hs).tsum_eq.symm /-- Alternate formulation of `zeta_eq_tsum_one_div_nat_cpow` with a `+ 1` (to avoid relying -on mathlib's conventions for `0 ^ s`). -/ +on mathlib's conventions for `0 ^ s`). -/ theorem zeta_eq_tsum_one_div_nat_add_one_cpow {s : ℂ} (hs : 1 < re s) : riemannZeta s = ∑' n : ℕ, 1 / (n + 1 : ℂ) ^ s := by have := zeta_eq_tsum_one_div_nat_cpow hs @@ -202,7 +202,7 @@ theorem zeta_nat_eq_tsum_of_gt_one {k : ℕ} (hk : 1 < k) : lemma riemannZeta_residue_one : Tendsto (fun s ↦ (s - 1) * riemannZeta s) (𝓝[≠] 1) (𝓝 1) := by exact hurwitzZetaEven_residue_one 0 -/- naming scheme was changed from from `riemannCompletedZeta` to `completedRiemannZeta`; add +/- naming scheme was changed from `riemannCompletedZeta` to `completedRiemannZeta`; add aliases for the old names -/ section aliases diff --git a/Mathlib/NumberTheory/LSeries/ZMod.lean b/Mathlib/NumberTheory/LSeries/ZMod.lean new file mode 100644 index 0000000000000..d7727a8fcffd7 --- /dev/null +++ b/Mathlib/NumberTheory/LSeries/ZMod.lean @@ -0,0 +1,200 @@ +/- +Copyright (c) 2024 David Loeffler. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: David Loeffler +-/ + +import Mathlib.Analysis.Fourier.ZMod +import Mathlib.Analysis.NormedSpace.Connected +import Mathlib.LinearAlgebra.Dimension.DivisionRing +import Mathlib.NumberTheory.LSeries.RiemannZeta +import Mathlib.Topology.Algebra.Module.Cardinality + +/-! +# L-series of functions on `ZMod N` + +We show that if `N` is a positive integer and `Φ : ZMod N → ℂ`, then the L-series of `Φ` has +analytic continuation (away from a pole at `s = 1` if `∑ j, Φ j ≠ 0`). + +The most familiar case is when `Φ` is a Dirichlet character, but the results here are valid +for general functions; for the specific case of Dirichlet characters see +`Mathlib.NumberTheory.LSeries.DirichletContinuation`. + +## Main definitions + +* `ZMod.LFunction Φ s`: the meromorphic continuation of the function `∑ n : ℕ, Φ n * n ^ (-s)`. + +## Main theorems + +* `ZMod.LFunction_eq_LSeries`: if `1 < re s` then the `LFunction` coincides with the naive + `LSeries`. +* `ZMod.differentiableAt_LFunction`: `ZMod.LFunction Φ` is differentiable at `s ∈ ℂ` if either + `s ≠ 1` or `∑ j, Φ j = 0`. +* `ZMod.LFunction_one_sub`: the functional equation relating `LFunction Φ (1 - s)` to + `LFunction (𝓕 Φ) s`, where `𝓕` is the Fourier transform. +-/ + +open HurwitzZeta Complex ZMod Finset Classical Topology Filter + +open scoped Real + +namespace ZMod + +variable {N : ℕ} [NeZero N] + +/-- If `Φ` is a periodic function, then the L-series of `Φ` converges for `1 < re s`. -/ +lemma LSeriesSummable_of_one_lt_re (Φ : ZMod N → ℂ) {s : ℂ} (hs : 1 < re s) : + LSeriesSummable (Φ ·) s := by + let c := max' _ <| univ_nonempty.image (Complex.abs ∘ Φ) + refine LSeriesSummable_of_bounded_of_one_lt_re (fun n _ ↦ le_max' _ _ ?_) (m := c) hs + exact mem_image_of_mem _ (mem_univ _) + +/-- +The unique meromorphic function `ℂ → ℂ` which agrees with `∑' n : ℕ, Φ n / n ^ s` wherever the +latter is convergent. This is constructed as a linear combination of Hurwitz zeta functions. + +Note that this is not the same as `LSeries Φ`: they agree in the convergence range, but +`LSeries Φ s` is defined to be `0` if `re s ≤ 1`. + -/ +noncomputable def LFunction (Φ : ZMod N → ℂ) (s : ℂ) : ℂ := + N ^ (-s) * ∑ j : ZMod N, Φ j * hurwitzZeta (toAddCircle j) s + +/-- The L-function of a function on `ZMod 1` is a scalar multiple of the Riemann zeta function. -/ +lemma LFunction_modOne_eq (Φ : ZMod 1 → ℂ) (s : ℂ) : + LFunction Φ s = Φ 0 * riemannZeta s := by + simp only [LFunction, Nat.cast_one, one_cpow, ← singleton_eq_univ (0 : ZMod 1), sum_singleton, + map_zero, hurwitzZeta_zero, one_mul] + +/-- For `1 < re s` the congruence L-function agrees with the sum of the Dirichlet series. -/ +lemma LFunction_eq_LSeries (Φ : ZMod N → ℂ) {s : ℂ} (hs : 1 < re s) : + LFunction Φ s = LSeries (Φ ·) s := by + rw [LFunction, LSeries, mul_sum, Nat.sumByResidueClasses (LSeriesSummable_of_one_lt_re Φ hs) N] + congr 1 with j + have : (j.val / N : ℝ) ∈ Set.Icc 0 1 := Set.mem_Icc.mpr ⟨by positivity, + (div_le_one (Nat.cast_pos.mpr <| NeZero.pos _)).mpr <| Nat.cast_le.mpr (val_lt j).le⟩ + rw [toAddCircle_apply, ← (hasSum_hurwitzZeta_of_one_lt_re this hs).tsum_eq, ← mul_assoc, + ← tsum_mul_left] + congr 1 with m + -- The following manipulation is slightly delicate because `(x * y) ^ s = x ^ s * y ^ s` is + -- false for general complex `x`, `y`, but it is true if `x` and `y` are non-negative reals, so + -- we have to carefully juggle coercions `ℕ → ℝ → ℂ`. + calc N ^ (-s) * Φ j * (1 / (m + (j.val / N : ℝ)) ^ s) + _ = Φ j * (N ^ (-s) * (1 / (m + (j.val / N : ℝ)) ^ s)) := by + rw [← mul_assoc, mul_comm _ (Φ _)] + _ = Φ j * (1 / (N : ℝ) ^ s * (1 / ((j.val + N * m) / N : ℝ) ^ s)) := by + simp only [cpow_neg, ← one_div, ofReal_div, ofReal_natCast, add_comm, add_div, ofReal_add, + ofReal_mul, mul_div_cancel_left₀ (m : ℂ) (Nat.cast_ne_zero.mpr (NeZero.ne N))] + _ = Φ j / ((N : ℝ) * ((j.val + N * m) / N : ℝ)) ^ s := by -- this is the delicate step! + rw [one_div_mul_one_div, mul_one_div, mul_cpow_ofReal_nonneg] <;> positivity + _ = Φ j / (N * (j.val + N * m) / N) ^ s := by + simp only [ofReal_natCast, ofReal_div, ofReal_add, ofReal_mul, mul_div_assoc] + _ = Φ j / (j.val + N * m) ^ s := by + rw [mul_div_cancel_left₀ _ (Nat.cast_ne_zero.mpr (NeZero.ne N))] + _ = Φ ↑(j.val + N * m) / (↑(j.val + N * m)) ^ s := by + simp only [Nat.cast_add, Nat.cast_mul, natCast_zmod_val, natCast_self, zero_mul, add_zero] + _ = LSeries.term (Φ ·) s (j.val + N * m) := by + rw [LSeries.term_of_ne_zero' (ne_zero_of_one_lt_re hs)] + +lemma differentiableAt_LFunction (Φ : ZMod N → ℂ) (s : ℂ) (hs : s ≠ 1 ∨ ∑ j, Φ j = 0) : + DifferentiableAt ℂ (LFunction Φ) s := by + apply (differentiable_neg.const_cpow (Or.inl <| NeZero.ne _) s).mul + rcases ne_or_eq s 1 with hs' | rfl + · exact .sum fun j _ ↦ (differentiableAt_hurwitzZeta _ hs').const_mul _ + · have := DifferentiableAt.sum (u := univ) fun j _ ↦ + (differentiableAt_hurwitzZeta_sub_one_div (toAddCircle j)).const_mul (Φ j) + simpa only [mul_sub, sum_sub_distrib, ← sum_mul, hs.neg_resolve_left rfl, zero_mul, sub_zero] + +lemma differentiable_LFunction_of_sum_zero {Φ : ZMod N → ℂ} (hΦ : ∑ j, Φ j = 0) : + Differentiable ℂ (LFunction Φ) := + fun s ↦ differentiableAt_LFunction Φ s (Or.inr hΦ) + +/-- The L-function of `Φ` has a residue at `s = 1` equal to the average value of `Φ`. -/ +lemma LFunction_residue_one (Φ : ZMod N → ℂ) : + Tendsto (fun s ↦ (s - 1) * LFunction Φ s) (𝓝[≠] 1) (𝓝 (∑ j, Φ j / N)) := by + simp only [sum_div, LFunction, mul_sum] + refine tendsto_finset_sum _ fun j _ ↦ ?_ + rw [(by ring : Φ j / N = Φ j * (1 / N * 1)), one_div, ← cpow_neg_one] + simp only [show ∀ a b c d : ℂ, a * (b * (c * d)) = c * (b * (a * d)) by intros; ring] + refine tendsto_const_nhds.mul (.mul ?_ <| hurwitzZeta_residue_one _) + exact ((continuous_neg.const_cpow (Or.inl <| NeZero.ne _)).tendsto _).mono_left + nhdsWithin_le_nhds + +/-- +The `LFunction` of the function `x ↦ e (j * x)`, where `e : ZMod N → ℂ` is the standard additive +character, is `expZeta (j / N)`. + +Note this is not at all obvious from the definitions, and we prove it by analytic continuation +from the convergence range. +-/ +lemma LFunction_stdAddChar_eq_expZeta (j : ZMod N) (s : ℂ) (hjs : j ≠ 0 ∨ s ≠ 1) : + LFunction (fun k ↦ stdAddChar (j * k)) s = expZeta (ZMod.toAddCircle j) s := by + let U := if j = 0 then {z : ℂ | z ≠ 1} else Set.univ -- region of analyticity of both functions + let V := {z : ℂ | 1 < re z} -- convergence region + have hUo : IsOpen U := by + by_cases h : j = 0 + · simpa only [h, ↓reduceIte, U] using isOpen_compl_singleton + · simp only [h, ↓reduceIte, isOpen_univ, U] + let f := LFunction (fun k ↦ stdAddChar (j * k)) + let g := expZeta (toAddCircle j) + have hU {u} : u ∈ U ↔ u ≠ 1 ∨ j ≠ 0 := by simp only [Set.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 + 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 + refine (differentiableAt_expZeta _ _ ((hU.mp hu).imp_right fun h ↦ ?_)).differentiableWithinAt + rwa [ne_eq, toAddCircle_eq_zero] + have hUc : IsPreconnected U := by + by_cases h : j = 0 + · simpa only [h, ↓reduceIte, U] using + (isConnected_compl_singleton_of_one_lt_rank (by simp) _).isPreconnected + · simpa only [h, ↓reduceIte, U] using isPreconnected_univ + have hV : V ∈ 𝓝 2 := (continuous_re.isOpen_preimage _ isOpen_Ioi).mem_nhds (by simp) + have hUmem : 2 ∈ U := by simp [U] + have hUmem' : s ∈ U := hU.mpr hjs.symm + -- apply uniqueness result + refine hf.eqOn_of_preconnected_of_eventuallyEq hg hUc hUmem ?_ hUmem' + -- now remains to prove equality on `1 < re s` + filter_upwards [hV] with z hz + dsimp only [f, g] + rw [toAddCircle_apply, ← (hasSum_expZeta_of_one_lt_re (j.val / N) hz).tsum_eq, + LFunction_eq_LSeries _ hz, LSeries] + congr 1 with n + rw [LSeries.term_of_ne_zero' (ne_zero_of_one_lt_re hz), ofReal_div, ofReal_natCast, + ofReal_natCast, mul_assoc, div_mul_eq_mul_div, stdAddChar_apply] + have := ZMod.toCircle_intCast (N := N) (j.val * n) + conv_rhs at this => rw [Int.cast_mul, Int.cast_natCast, Int.cast_natCast, mul_div_assoc] + rw [← this, Int.cast_mul, Int.cast_natCast, Int.cast_natCast, natCast_zmod_val] + +/-- Explicit formula for the L-function of `𝓕 Φ`, where `𝓕` is the discrete Fourier transform. -/ +lemma LFunction_dft (Φ : ZMod N → ℂ) {s : ℂ} (hs : s ≠ 1) : + LFunction (𝓕 Φ) s = ∑ j : ZMod N, Φ j * expZeta (toAddCircle (-j)) s := by + simp only [← LFunction_stdAddChar_eq_expZeta _ _ (Or.inr hs), LFunction, mul_sum] + rw [sum_comm, dft_def] + simp only [sum_mul, mul_sum, Circle.smul_def, smul_eq_mul, stdAddChar_apply, ← mul_assoc] + congr 1 with j + congr 1 with k + rw [mul_assoc (Φ _), mul_comm (Φ _), neg_mul] + +/-- Functional equation for `ZMod` L-functions, in terms of discrete Fourier transform. -/ +theorem LFunction_one_sub (Φ : ZMod N → ℂ) {s : ℂ} (hs : ∀ (n : ℕ), s ≠ -↑n) (hs' : s ≠ 1) : + LFunction Φ (1 - s) = N ^ (s - 1) * (2 * π) ^ (-s) * Gamma s * + (cexp (π * I * s / 2) * LFunction (𝓕 Φ) s + + cexp (-π * I * s / 2) * LFunction (𝓕 fun x ↦ Φ (-x)) s) := by + rw [LFunction] + simp only [hurwitzZeta_one_sub _ hs (Or.inr hs'), mul_assoc _ _ (Gamma s)] + -- get rid of Gamma terms and power of N + generalize (2 * π) ^ (-s) * Gamma s = C + simp_rw [← mul_assoc, mul_comm _ C, mul_assoc, ← mul_sum, ← mul_assoc, mul_comm _ C, mul_assoc, + neg_sub] + congr 2 + -- now gather sum terms + rw [LFunction_dft _ hs', LFunction_dft _ hs'] + conv_rhs => enter [2, 2]; rw [← (Equiv.neg _).sum_comp _ _ (by simp), Equiv.neg_apply] + simp_rw [neg_neg, mul_sum, ← sum_add_distrib, ← mul_assoc, mul_comm _ (Φ _), mul_assoc, + ← mul_add, map_neg, add_comm] + +end ZMod diff --git a/Mathlib/NumberTheory/LegendreSymbol/GaussEisensteinLemmas.lean b/Mathlib/NumberTheory/LegendreSymbol/GaussEisensteinLemmas.lean index 32524bd59090a..cd03518fe7e21 100644 --- a/Mathlib/NumberTheory/LegendreSymbol/GaussEisensteinLemmas.lean +++ b/Mathlib/NumberTheory/LegendreSymbol/GaussEisensteinLemmas.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes -/ import Mathlib.NumberTheory.LegendreSymbol.Basic -import Mathlib.Analysis.Normed.Field.Basic +import Mathlib.Analysis.Normed.Field.Lemmas /-! # Lemmas of Gauss and Eisenstein @@ -34,7 +34,7 @@ theorem Ico_map_valMinAbs_natAbs_eq_Ico_map_id (p : ℕ) [hp : Fact p.Prime] (a lt_of_le_of_lt (he hx).2 (Nat.div_lt_self hp.1.pos (by decide)) have hpe : ∀ {x}, x ∈ Ico 1 (p / 2).succ → ¬p ∣ x := fun hx hpx => not_lt_of_ge (le_of_dvd (Nat.pos_of_ne_zero (he hx).1) hpx) (hep hx) - have hmem : ∀ (x : ℕ) (hx : x ∈ Ico 1 (p / 2).succ), + have hmem : ∀ (x : ℕ) (_ : x ∈ Ico 1 (p / 2).succ), (a * x : ZMod p).valMinAbs.natAbs ∈ Ico 1 (p / 2).succ := by intro x hx simp [hap, CharP.cast_eq_zero_iff (ZMod p) p, hpe hx, Nat.lt_succ_iff, succ_le_iff, diff --git a/Mathlib/NumberTheory/LegendreSymbol/JacobiSymbol.lean b/Mathlib/NumberTheory/LegendreSymbol/JacobiSymbol.lean index 7002957721377..74dce799b0ee1 100644 --- a/Mathlib/NumberTheory/LegendreSymbol/JacobiSymbol.lean +++ b/Mathlib/NumberTheory/LegendreSymbol/JacobiSymbol.lean @@ -529,7 +529,7 @@ decreasing_by private theorem fastJacobiSymAux.eq_jacobiSym {a b : ℕ} {flip : Bool} {ha0 : a > 0} (hb2 : b % 2 = 1) (hb1 : b > 1) : fastJacobiSymAux a b flip ha0 = if flip then -J(a | b) else J(a | b) := by - induction' a using Nat.strongInductionOn with a IH generalizing b flip + induction' a using Nat.strongRecOn with a IH generalizing b flip unfold fastJacobiSymAux split <;> rename_i ha4 · rw [IH (a / 4) (a.div_lt_self ha0 (by decide)) hb2 hb1] @@ -569,7 +569,7 @@ private def fastJacobiSym (a : ℤ) (b : ℕ) : ℤ := @[csimp] private theorem fastJacobiSym.eq : jacobiSym = fastJacobiSym := by ext a b - induction' b using Nat.strongInductionOn with b IH + induction' b using Nat.strongRecOn with b IH unfold fastJacobiSym split_ifs with hb0 hb2 ha2 hb1 hab · rw [hb0, zero_right] diff --git a/Mathlib/NumberTheory/LegendreSymbol/QuadraticChar/Basic.lean b/Mathlib/NumberTheory/LegendreSymbol/QuadraticChar/Basic.lean index b9a2c36a497c9..4c18eb5f5ff10 100644 --- a/Mathlib/NumberTheory/LegendreSymbol/QuadraticChar/Basic.lean +++ b/Mathlib/NumberTheory/LegendreSymbol/QuadraticChar/Basic.lean @@ -137,7 +137,7 @@ theorem quadraticChar_zero : quadraticChar F 0 = 0 := by theorem quadraticChar_one_iff_isSquare {a : F} (ha : a ≠ 0) : quadraticChar F a = 1 ↔ IsSquare a := by simp only [quadraticChar_apply, quadraticCharFun, ha, if_false, ite_eq_left_iff, - (by omega : (-1 : ℤ) ≠ 1), imp_false, not_not] + (by omega : (-1 : ℤ) ≠ 1), imp_false, not_not, reduceCtorEq] /-- The quadratic character takes the value `1` on nonzero squares. -/ theorem quadraticChar_sq_one' {a : F} (ha : a ≠ 0) : quadraticChar F (a ^ 2) = 1 := by @@ -213,7 +213,7 @@ when the domain has odd characteristic. -/ theorem quadraticChar_ne_one (hF : ringChar F ≠ 2) : quadraticChar F ≠ 1 := by rcases quadraticChar_exists_neg_one' hF with ⟨a, ha⟩ intro hχ - simp only [hχ, one_apply a.isUnit, one_ne_zero] at ha + simp only [hχ, one_apply a.isUnit, one_ne_zero, reduceCtorEq] at ha set_option linter.deprecated false in @[deprecated quadraticChar_ne_one (since := "2024-06-16")] @@ -292,7 +292,7 @@ theorem FiniteField.isSquare_neg_one_iff : IsSquare (-1 : F) ↔ Fintype.card F rw [← quadraticChar_one_iff_isSquare (neg_ne_zero.mpr (one_ne_zero' F)), quadraticChar_neg_one hF, χ₄_nat_eq_if_mod_four, h₁] simp only [Nat.one_ne_zero, if_false, ite_eq_left_iff, (by omega : (-1 : ℤ) ≠ 1), imp_false, - not_not, Ne] + not_not, Ne, reduceCtorEq] exact ⟨fun h ↦ ne_of_eq_of_ne h (by omega), (Nat.odd_mod_four_iff.mp h₁).resolve_right⟩ end SpecialValues diff --git a/Mathlib/NumberTheory/Liouville/Basic.lean b/Mathlib/NumberTheory/Liouville/Basic.lean index 33994e47db69f..a9e820e8d2cad 100644 --- a/Mathlib/NumberTheory/Liouville/Basic.lean +++ b/Mathlib/NumberTheory/Liouville/Basic.lean @@ -108,7 +108,7 @@ theorem exists_one_le_pow_mul_dist {Z N R : Type*} [PseudoMetricSpace R] {d : N · -- `j z a = z / (a + 1)`: we prove that this ratio is close to `α` have : j z a ∈ closedBall α ε := by refine mem_closedBall'.mp (le_trans ?_ ((one_div_le me0 e0).mpr (le_max_left _ _))) - exact (le_div_iff me0).mpr (not_le.mp dm1).le + exact (le_div_iff₀ me0).mpr (not_le.mp dm1).le -- use the "separation from `1`" (assumption `L`) for numerators, refine (L this).trans ?_ -- remove a common factor and use the Lipschitz assumption `B` @@ -207,7 +207,7 @@ protected theorem transcendental {x : ℝ} (lx : Liouville x) : Transcendental · lift b to ℕ using zero_le_one.trans b1.le specialize h a b.pred rwa [← Nat.cast_succ, Nat.succ_pred_eq_of_pos (zero_lt_one.trans _), ← mul_assoc, ← - div_le_iff hA] at h + div_le_iff₀ hA] at h exact Int.ofNat_lt.mp b1 end Liouville diff --git a/Mathlib/NumberTheory/Liouville/LiouvilleWith.lean b/Mathlib/NumberTheory/Liouville/LiouvilleWith.lean index ac2e9e02f07f7..45980956c089e 100644 --- a/Mathlib/NumberTheory/Liouville/LiouvilleWith.lean +++ b/Mathlib/NumberTheory/Liouville/LiouvilleWith.lean @@ -103,7 +103,7 @@ theorem frequently_lt_rpow_neg (h : LiouvilleWith p x) (hlt : q < p) : 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. -/ +/-- The product of a Liouville number and a nonzero rational number is again a Liouville number. -/ theorem mul_rat (h : LiouvilleWith p x) (hr : r ≠ 0) : LiouvilleWith p (x * r) := by rcases h.exists_pos with ⟨C, _hC₀, hC⟩ refine ⟨r.den ^ p * (|r| * C), (tendsto_id.nsmul_atTop r.pos).frequently (hC.mono ?_)⟩ diff --git a/Mathlib/NumberTheory/LucasLehmer.lean b/Mathlib/NumberTheory/LucasLehmer.lean index 13cbbcc14f54e..b6ad0fed7b57e 100644 --- a/Mathlib/NumberTheory/LucasLehmer.lean +++ b/Mathlib/NumberTheory/LucasLehmer.lean @@ -59,6 +59,12 @@ theorem mersenne_le_mersenne {p q : ℕ} : mersenne p ≤ mersenne q ↔ p ≤ q @[simp] theorem mersenne_zero : mersenne 0 = 0 := rfl +@[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 _) + (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) namespace Mathlib.Meta.Positivity diff --git a/Mathlib/NumberTheory/Modular.lean b/Mathlib/NumberTheory/Modular.lean index e14a58682b9f1..812b9760b6b67 100644 --- a/Mathlib/NumberTheory/Modular.lean +++ b/Mathlib/NumberTheory/Modular.lean @@ -289,7 +289,7 @@ theorem exists_max_im : ∃ g : SL(2, ℤ), ∀ g' : SL(2, ℤ), (g' • z).im · exact normSq_denom_pos g z /-- Given `z : ℍ` and a bottom row `(c,d)`, among the `g : SL(2,ℤ)` with this bottom row, minimize - `|(g•z).re|`. -/ + `|(g•z).re|`. -/ theorem exists_row_one_eq_and_min_re {cd : Fin 2 → ℤ} (hcd : IsCoprime (cd 0) (cd 1)) : ∃ g : SL(2, ℤ), (↑ₘg) 1 = cd ∧ ∀ g' : SL(2, ℤ), (↑ₘg) 1 = (↑ₘg') 1 → |(g • z).re| ≤ |(g' • z).re| := by diff --git a/Mathlib/NumberTheory/ModularForms/EisensteinSeries/Defs.lean b/Mathlib/NumberTheory/ModularForms/EisensteinSeries/Defs.lean index 91bae3555b311..ce4577936eb32 100644 --- a/Mathlib/NumberTheory/ModularForms/EisensteinSeries/Defs.lean +++ b/Mathlib/NumberTheory/ModularForms/EisensteinSeries/Defs.lean @@ -64,7 +64,7 @@ lemma vecMul_SL2_mem_gammaSet {v : Fin 2 → ℤ} (hv : v ∈ gammaSet N a) (γ refine ⟨?_, hv.2.vecMulSL γ⟩ have := RingHom.map_vecMul (m := Fin 2) (n := Fin 2) (Int.castRingHom (ZMod N)) γ v simp only [eq_intCast, Int.coe_castRingHom] at this - simp_rw [Function.comp, this, hv.1] + simp_rw [Function.comp_def, this, hv.1] simp variable (a) in diff --git a/Mathlib/NumberTheory/ModularForms/EisensteinSeries/MDifferentiable.lean b/Mathlib/NumberTheory/ModularForms/EisensteinSeries/MDifferentiable.lean index 8b310863a3576..1ac2a1db2ed96 100644 --- a/Mathlib/NumberTheory/ModularForms/EisensteinSeries/MDifferentiable.lean +++ b/Mathlib/NumberTheory/ModularForms/EisensteinSeries/MDifferentiable.lean @@ -23,7 +23,7 @@ open UpperHalfPlane Filter Function Complex Manifold CongruenceSubgroup namespace EisensteinSeries -/-- Auxilary lemma showing that for any `k : ℤ` the function `z → 1/(c*z+d)^k` is +/-- Auxiliary lemma showing that for any `k : ℤ` the function `z → 1/(c*z+d)^k` is differentiable on `{z : ℂ | 0 < z.im}`. -/ lemma div_linear_zpow_differentiableOn (k : ℤ) (a : Fin 2 → ℤ) : DifferentiableOn ℂ (fun z : ℂ => (a 0 * z + a 1) ^ (-k)) {z : ℂ | 0 < z.im} := by @@ -36,7 +36,7 @@ lemma div_linear_zpow_differentiableOn (k : ℤ) (a : Fin 2 → ℤ) : · simp only [Fin.isValue, Pi.zero_apply, Int.cast_zero, zero_mul, add_zero, one_div] apply differentiableOn_const -/-- Auxilary lemma showing that for any `k : ℤ` and `(a : Fin 2 → ℤ)` +/-- Auxiliary lemma showing that for any `k : ℤ` and `(a : Fin 2 → ℤ)` the extension of `eisSummand` is differentiable on `{z : ℂ | 0 < z.im}`.-/ lemma eisSummand_extension_differentiableOn (k : ℤ) (a : Fin 2 → ℤ) : DifferentiableOn ℂ (↑ₕeisSummand k a) {z : ℂ | 0 < z.im} := by diff --git a/Mathlib/NumberTheory/ModularForms/EisensteinSeries/UniformConvergence.lean b/Mathlib/NumberTheory/ModularForms/EisensteinSeries/UniformConvergence.lean index ed9f6bb7e6f15..2ff96d352b04b 100644 --- a/Mathlib/NumberTheory/ModularForms/EisensteinSeries/UniformConvergence.lean +++ b/Mathlib/NumberTheory/ModularForms/EisensteinSeries/UniformConvergence.lean @@ -56,14 +56,14 @@ lemma r1_pos : 0 < r1 z := by dsimp only [r1] positivity -/-- For `c, d ∈ ℝ` with `1 ≤ d ^ 2`, we have `r1 z ≤ |c * z + d| ^ 2`. -/ +/-- For `c, d ∈ ℝ` with `1 ≤ d ^ 2`, we have `r1 z ≤ |c * z + d| ^ 2`. -/ lemma r1_aux_bound (c : ℝ) {d : ℝ} (hd : 1 ≤ d ^ 2) : r1 z ≤ (c * z.re + d) ^ 2 + (c * z.im) ^ 2 := by have H1 : (c * z.re + d) ^ 2 + (c * z.im) ^ 2 = c ^ 2 * (z.re ^ 2 + z.im ^ 2) + d * 2 * c * z.re + d ^ 2 := by ring have H2 : (c ^ 2 * (z.re ^ 2 + z.im ^ 2) + d * 2 * c * z.re + d ^ 2) * (z.re ^ 2 + z.im ^ 2) - z.im ^ 2 = (c * (z.re ^ 2 + z.im ^ 2) + d * z.re) ^ 2 + (d ^ 2 - 1) * z.im ^ 2 := by ring - rw [r1, H1, div_le_iff (by positivity), ← sub_nonneg, H2] + rw [r1, H1, div_le_iff₀ (by positivity), ← sub_nonneg, H2] exact add_nonneg (sq_nonneg _) (mul_nonneg (sub_nonneg.mpr hd) (sq_nonneg _)) /-- This function is used to give an upper bound on the summands in Eisenstein series; it is diff --git a/Mathlib/NumberTheory/ModularForms/JacobiTheta/Bounds.lean b/Mathlib/NumberTheory/ModularForms/JacobiTheta/Bounds.lean index f1931f2f1bb78..5af4baf5ed34a 100644 --- a/Mathlib/NumberTheory/ModularForms/JacobiTheta/Bounds.lean +++ b/Mathlib/NumberTheory/ModularForms/JacobiTheta/Bounds.lean @@ -7,7 +7,7 @@ Authors: David Loeffler import Mathlib.NumberTheory.ModularForms.JacobiTheta.TwoVariable /-! -# Asymptotic bounds for Jacobi theta functions +# Asymptotic bounds for Jacobi theta functions The goal of this file is to establish some technical lemmas about the asymptotics of the sums diff --git a/Mathlib/NumberTheory/ModularForms/JacobiTheta/TwoVariable.lean b/Mathlib/NumberTheory/ModularForms/JacobiTheta/TwoVariable.lean index 10883cf58e5b4..fb58da50e6f50 100644 --- a/Mathlib/NumberTheory/ModularForms/JacobiTheta/TwoVariable.lean +++ b/Mathlib/NumberTheory/ModularForms/JacobiTheta/TwoVariable.lean @@ -285,7 +285,7 @@ lemma jacobiTheta₂'_undef (z : ℂ) {τ : ℂ} (hτ : im τ ≤ 0) : jacobiThe exact not_lt.mpr hτ /-! -## Derivatives and continuity +## Derivatives and continuity -/ lemma hasFDerivAt_jacobiTheta₂ (z : ℂ) {τ : ℂ} (hτ : 0 < im τ) : @@ -373,7 +373,7 @@ lemma continuousAt_jacobiTheta₂' (z : ℂ) {τ : ℂ} (hτ : 0 < im τ) : · exact norm_jacobiTheta₂'_term_le hT (le_of_lt hz') (le_of_lt hτ') n /-! -## Periodicity and conjugation +## Periodicity and conjugation -/ /-- The two-variable Jacobi theta function is periodic in `τ` with period 2. -/ @@ -462,7 +462,7 @@ lemma jacobiTheta₂'_conj (z τ : ℂ) : ## Functional equations -/ -/-- The functional equation for the Jacobi theta function: `jacobiTheta₂ z τ` is an explict factor +/-- The functional equation for the Jacobi theta function: `jacobiTheta₂ z τ` is an explicit factor times `jacobiTheta₂ (z / τ) (-1 / τ)`. This is the key lemma behind the proof of the functional equation for L-series of even Dirichlet characters. -/ theorem jacobiTheta₂_functional_equation (z τ : ℂ) : jacobiTheta₂ z τ = diff --git a/Mathlib/NumberTheory/MulChar/Basic.lean b/Mathlib/NumberTheory/MulChar/Basic.lean index f9a5760d1bcda..7c8c94626c010 100644 --- a/Mathlib/NumberTheory/MulChar/Basic.lean +++ b/Mathlib/NumberTheory/MulChar/Basic.lean @@ -454,7 +454,7 @@ lemma injective_ringHomComp {f : R' →+* R''} (hf : Function.Injective f) : lemma ringHomComp_eq_one_iff {f : R' →+* R''} (hf : Function.Injective f) {χ : MulChar R R'} : χ.ringHomComp f = 1 ↔ χ = 1 := by - conv_lhs => rw [← (show (1 : MulChar R R').ringHomComp f = 1 by ext; simp)] + conv_lhs => rw [← (show (1 : MulChar R R').ringHomComp f = 1 by ext; simp)] exact (injective_ringHomComp hf).eq_iff lemma ringHomComp_ne_one_iff {f : R' →+* R''} (hf : Function.Injective f) {χ : MulChar R R'} : diff --git a/Mathlib/NumberTheory/MulChar/Lemmas.lean b/Mathlib/NumberTheory/MulChar/Lemmas.lean index b0e6da9769998..d4ac05321aeb8 100644 --- a/Mathlib/NumberTheory/MulChar/Lemmas.lean +++ b/Mathlib/NumberTheory/MulChar/Lemmas.lean @@ -111,7 +111,7 @@ noncomputable def equiv_rootsOfUnity [inst_cyc : IsCyclic Mˣ] : ext simp only [toUnitHom_eq, coe_equivToUnitHom, ofRootOfUnity_spec] map_mul' x y := by - simp only [toUnitHom_eq, equivToUnitHom_mul_apply, Submonoid.mk_mul_mk] + simp only [toUnitHom_eq, equivToUnitHom_mul_apply, MulMemClass.mk_mul_mk] end IsCyclic diff --git a/Mathlib/NumberTheory/Multiplicity.lean b/Mathlib/NumberTheory/Multiplicity.lean index 84bfdd8eb4529..dd1a44061a628 100644 --- a/Mathlib/NumberTheory/Multiplicity.lean +++ b/Mathlib/NumberTheory/Multiplicity.lean @@ -6,8 +6,9 @@ Authors: Tian Chen, Mantas Bakšys import Mathlib.Algebra.GeomSum import Mathlib.Algebra.Order.Ring.Basic import Mathlib.Algebra.Ring.Int -import Mathlib.NumberTheory.Padics.PadicVal +import Mathlib.NumberTheory.Padics.PadicVal.Defs import Mathlib.RingTheory.Ideal.Quotient +import Mathlib.Data.Nat.Prime.Basic /-! # Multiplicity in Number Theory @@ -256,7 +257,7 @@ theorem Int.sq_mod_four_eq_one_of_odd {x : ℤ} : Odd x → x ^ 2 % 4 = 1 := by theorem Int.two_pow_two_pow_add_two_pow_two_pow {x y : ℤ} (hx : ¬2 ∣ x) (hxy : 4 ∣ x - y) (i : ℕ) : multiplicity 2 (x ^ 2 ^ i + y ^ 2 ^ i) = ↑(1 : ℕ) := by - have hx_odd : Odd x := by rwa [Int.odd_iff_not_even, even_iff_two_dvd] + have hx_odd : Odd x := by rwa [← Int.not_even_iff_odd, even_iff_two_dvd] have hxy_even : Even (x - y) := even_iff_two_dvd.mpr (dvd_trans (by decide) hxy) have hy_odd : Odd y := by simpa using hx_odd.sub_even hxy_even refine multiplicity.eq_coe_iff.mpr ⟨?_, ?_⟩ @@ -286,7 +287,7 @@ theorem Int.two_pow_two_pow_sub_pow_two_pow {x y : ℤ} (n : ℕ) (hxy : 4 ∣ x theorem Int.two_pow_sub_pow' {x y : ℤ} (n : ℕ) (hxy : 4 ∣ x - y) (hx : ¬2 ∣ x) : multiplicity 2 (x ^ n - y ^ n) = multiplicity 2 (x - y) + multiplicity (2 : ℤ) n := by - have hx_odd : Odd x := by rwa [Int.odd_iff_not_even, even_iff_two_dvd] + have hx_odd : Odd x := by rwa [← Int.not_even_iff_odd, even_iff_two_dvd] have hxy_even : Even (x - y) := even_iff_two_dvd.mpr (dvd_trans (by decide) hxy) have hy_odd : Odd y := by simpa using hx_odd.sub_even hxy_even cases' n with n @@ -299,7 +300,7 @@ theorem Int.two_pow_sub_pow' {x y : ℤ} (n : ℕ) (hxy : 4 ∣ x - y) (hx : ¬2 · norm_cast · exact Int.prime_two · simpa only [even_iff_two_dvd] using hx_odd.pow.sub_odd hy_odd.pow - · simpa only [even_iff_two_dvd, Int.odd_iff_not_even] using hx_odd.pow + · simpa only [even_iff_two_dvd, ← Int.not_even_iff_odd] using hx_odd.pow erw [Int.natCast_dvd_natCast] -- `erw` to deal with `2 : ℤ` vs `(2 : ℕ) : ℤ` contrapose! hpn @@ -312,7 +313,7 @@ theorem Int.two_pow_sub_pow {x y : ℤ} {n : ℕ} (hxy : 2 ∣ x - y) (hx : ¬2 multiplicity 2 (x ^ n - y ^ n) + 1 = multiplicity 2 (x + y) + multiplicity 2 (x - y) + multiplicity (2 : ℤ) n := by have hy : Odd y := by - rw [← even_iff_two_dvd, ← Int.odd_iff_not_even] at hx + rw [← even_iff_two_dvd, Int.not_even_iff_odd] at hx replace hxy := (@even_neg _ _ (x - y)).mpr (even_iff_two_dvd.mpr hxy) convert Even.add_odd hxy hx abel @@ -323,7 +324,7 @@ theorem Int.two_pow_sub_pow {x y : ℤ} {n : ℕ} (hxy : 2 ∣ x - y) (hx : ¬2 rw [Int.dvd_iff_emod_eq_zero, Int.sub_emod, Int.sq_mod_four_eq_one_of_odd _, Int.sq_mod_four_eq_one_of_odd hy] · norm_num - · simp only [Int.odd_iff_not_even, even_iff_two_dvd, hx, not_false_iff] + · simp only [← Int.not_even_iff_odd, even_iff_two_dvd, hx, not_false_iff] rw [Int.two_pow_sub_pow' d hxy4 _, sq_sub_sq, ← Int.ofNat_mul_out, multiplicity.mul Int.prime_two, multiplicity.mul Int.prime_two] · suffices multiplicity (2 : ℤ) ↑(2 : ℕ) = 1 by rw [this, add_comm (1 : PartENat), ← add_assoc] @@ -332,9 +333,9 @@ theorem Int.two_pow_sub_pow {x y : ℤ} {n : ℕ} (hxy : 2 ∣ x - y) (hx : ¬2 · apply Prime.not_unit simp only [← Nat.prime_iff, Nat.prime_two] · exact two_ne_zero - · rw [← even_iff_two_dvd, ← Int.odd_iff_not_even] + · rw [← even_iff_two_dvd, Int.not_even_iff_odd] apply Odd.pow - simp only [Int.odd_iff_not_even, even_iff_two_dvd, hx, not_false_iff] + simp only [← Int.not_even_iff_odd, even_iff_two_dvd, hx, not_false_iff] theorem Nat.two_pow_sub_pow {x y : ℕ} (hxy : 2 ∣ x - y) (hx : ¬2 ∣ x) {n : ℕ} (hn : Even n) : multiplicity 2 (x ^ n - y ^ n) + 1 = diff --git a/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/Basic.lean b/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/Basic.lean index 5e0cd9a7ebdb7..ca7e6d3df61e9 100644 --- a/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/Basic.lean +++ b/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/Basic.lean @@ -278,7 +278,7 @@ def normAtPlace (w : InfinitePlace K) : (E K) →*₀ ℝ where map_one' := by simp map_mul' x y := by split_ifs <;> simp -theorem normAtPlace_nonneg (w : InfinitePlace K) (x : E K) : +theorem normAtPlace_nonneg (w : InfinitePlace K) (x : E K) : 0 ≤ normAtPlace w x := by rw [normAtPlace, MonoidWithZeroHom.coe_mk, ZeroHom.coe_mk] split_ifs <;> exact norm_nonneg _ diff --git a/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/ConvexBody.lean b/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/ConvexBody.lean index f34495bae5580..e96eb8256f308 100644 --- a/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/ConvexBody.lean +++ b/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/ConvexBody.lean @@ -98,7 +98,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_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) _) /-- The volume of `(ConvexBodyLt K f)` where `convexBodyLT K f` is the set of points `x` @@ -170,18 +170,21 @@ theorem convexBodyLT'_mem {x : K} : (∀ w : InfinitePlace K, w ≠ w₀ → w x < f w) ∧ |(w₀.val.embedding x).re| < 1 ∧ |(w₀.val.embedding x).im| < (f w₀ : ℝ) ^ 2 := by simp_rw [mixedEmbedding, RingHom.prod_apply, Set.mem_prod, Set.mem_pi, Set.mem_univ, - forall_true_left, Pi.ringHom_apply, apply_ite, mem_ball_zero_iff, ← Complex.norm_real, - embedding_of_isReal_apply, norm_embedding_eq, Subtype.forall, Set.mem_setOf_eq] + forall_true_left, Pi.ringHom_apply, mem_ball_zero_iff, ← Complex.norm_real, + embedding_of_isReal_apply, norm_embedding_eq, Subtype.forall] refine ⟨fun ⟨h₁, h₂⟩ ↦ ⟨fun w h_ne ↦ ?_, ?_⟩, fun ⟨h₁, h₂⟩ ↦ ⟨fun w hw ↦ ?_, fun w hw ↦ ?_⟩⟩ · by_cases hw : IsReal w · exact norm_embedding_eq w _ ▸ h₁ w hw · specialize h₂ w (not_isReal_iff_isComplex.mp hw) + rw [apply_ite (w.embedding x ∈ ·), Set.mem_setOf_eq, + mem_ball_zero_iff, norm_embedding_eq] at h₂ rwa [if_neg (by exact Subtype.coe_ne_coe.1 h_ne)] at h₂ · simpa [if_true] using h₂ w₀.val w₀.prop · exact h₁ w (ne_of_isReal_isComplex hw w₀.prop) · by_cases h_ne : w = w₀ · simpa [h_ne] · rw [if_neg (by exact Subtype.coe_ne_coe.1 h_ne)] + rw [mem_ball_zero_iff, norm_embedding_eq] exact h₁ w h_ne theorem convexBodyLT'_neg_mem (x : E K) (hx : x ∈ convexBodyLT' K f w₀) : @@ -195,8 +198,8 @@ theorem convexBodyLT'_convex : Convex ℝ (convexBodyLT' K f w₀) := by refine Convex.prod (convex_pi (fun _ _ => convex_ball _ _)) (convex_pi (fun _ _ => ?_)) split_ifs · simp_rw [abs_lt] - refine Convex.inter ((convex_halfspace_re_gt _).inter (convex_halfspace_re_lt _)) - ((convex_halfspace_im_gt _).inter (convex_halfspace_im_lt _)) + refine Convex.inter ((convex_halfspace_re_gt _).inter (convex_halfspace_re_lt _)) + ((convex_halfspace_im_gt _).inter (convex_halfspace_im_lt _)) · exact convex_ball _ _ open MeasureTheory MeasureTheory.Measure @@ -213,7 +216,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_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) _) theorem convexBodyLT'_volume : @@ -483,8 +486,8 @@ theorem volume_fundamentalDomain_fractionalIdealLatticeBasis : theorem minkowskiBound_lt_top : minkowskiBound K I < ⊤ := by refine ENNReal.mul_lt_top ?_ ?_ - · exact ne_of_lt (fundamentalDomain_isBounded _).measure_lt_top - · exact ne_of_lt (ENNReal.pow_lt_top (lt_top_iff_ne_top.mpr ENNReal.two_ne_top) _) + · exact (fundamentalDomain_isBounded _).measure_lt_top + · exact ENNReal.pow_lt_top (lt_top_iff_ne_top.mpr ENNReal.two_ne_top) _ theorem minkowskiBound_pos : 0 < minkowskiBound K I := by refine zero_lt_iff.mpr (mul_ne_zero ?_ ?_) @@ -502,7 +505,7 @@ theorem exists_ne_zero_mem_ideal_lt (h : minkowskiBound K I < volume (convexBody ∃ a ∈ (I : FractionalIdeal (𝓞 K)⁰ K), a ≠ 0 ∧ ∀ w : InfinitePlace K, w a < f w := by have h_fund := Zspan.isAddFundamentalDomain (fractionalIdealLatticeBasis K I) volume have : Countable (span ℤ (Set.range (fractionalIdealLatticeBasis K I))).toAddSubgroup := by - change Countable (span ℤ (Set.range (fractionalIdealLatticeBasis K I)) : Set (E K)) + change Countable (span ℤ (Set.range (fractionalIdealLatticeBasis K I))) infer_instance obtain ⟨⟨x, hx⟩, h_nz, h_mem⟩ := exists_ne_zero_mem_lattice_of_measure_mul_two_pow_lt_measure h_fund (convexBodyLT_neg_mem K f) (convexBodyLT_convex K f) h @@ -518,7 +521,7 @@ theorem exists_ne_zero_mem_ideal_lt' (w₀ : {w : InfinitePlace K // IsComplex w |(w₀.val.embedding a).re| < 1 ∧ |(w₀.val.embedding a).im| < (f w₀ : ℝ) ^ 2 := by have h_fund := Zspan.isAddFundamentalDomain (fractionalIdealLatticeBasis K I) volume have : Countable (span ℤ (Set.range (fractionalIdealLatticeBasis K I))).toAddSubgroup := by - change Countable (span ℤ (Set.range (fractionalIdealLatticeBasis K I)) : Set (E K)) + change Countable (span ℤ (Set.range (fractionalIdealLatticeBasis K I))) infer_instance obtain ⟨⟨x, hx⟩, h_nz, h_mem⟩ := exists_ne_zero_mem_lattice_of_measure_mul_two_pow_lt_measure h_fund (convexBodyLT'_neg_mem K f w₀) (convexBodyLT'_convex K f w₀) h @@ -606,7 +609,7 @@ theorem exists_ne_zero_mem_ideal_of_norm_le {B : ℝ} have h2 : 0 ≤ B / (finrank ℚ K) := div_nonneg hB (Nat.cast_nonneg _) have h_fund := Zspan.isAddFundamentalDomain (fractionalIdealLatticeBasis K I) volume have : Countable (span ℤ (Set.range (fractionalIdealLatticeBasis K I))).toAddSubgroup := by - change Countable (span ℤ (Set.range (fractionalIdealLatticeBasis K I)) : Set (E K)) + change Countable (span ℤ (Set.range (fractionalIdealLatticeBasis K I))) infer_instance obtain ⟨⟨x, hx⟩, h_nz, h_mem⟩ := exists_ne_zero_mem_lattice_of_measure_mul_two_pow_le_measure h_fund (fun _ ↦ convexBodySum_neg_mem K B) (convexBodySum_convex K B) @@ -616,9 +619,9 @@ theorem exists_ne_zero_mem_ideal_of_norm_le {B : ℝ} refine ⟨a, ha, by simpa using h_nz, ?_⟩ rw [← rpow_natCast, ← rpow_le_rpow_iff (by simp only [Rat.cast_abs, abs_nonneg]) (rpow_nonneg h2 _) h1, ← rpow_mul h2, mul_inv_cancel₀ (Nat.cast_ne_zero.mpr - (ne_of_gt finrank_pos)), rpow_one, le_div_iff' (Nat.cast_pos.mpr finrank_pos)] + (ne_of_gt finrank_pos)), rpow_one, le_div_iff₀' (Nat.cast_pos.mpr finrank_pos)] refine le_trans ?_ ((convexBodySum_mem K B).mp h_mem) - rw [← le_div_iff' (Nat.cast_pos.mpr finrank_pos), ← sum_mult_eq, Nat.cast_sum] + rw [← le_div_iff₀' (Nat.cast_pos.mpr finrank_pos), ← sum_mult_eq, Nat.cast_sum] refine le_trans ?_ (geom_mean_le_arith_mean Finset.univ _ _ (fun _ _ => Nat.cast_nonneg _) ?_ (fun _ _ => AbsoluteValue.nonneg _ _)) · simp_rw [← prod_eq_abs_norm, rpow_natCast] diff --git a/Mathlib/NumberTheory/NumberField/Discriminant.lean b/Mathlib/NumberTheory/NumberField/Discriminant.lean index a1d88ada36d6b..5981e3d788514 100644 --- a/Mathlib/NumberTheory/NumberField/Discriminant.lean +++ b/Mathlib/NumberTheory/NumberField/Discriminant.lean @@ -95,7 +95,7 @@ theorem _root_.NumberField.mixedEmbedding.volume_fundamentalDomain_latticeBasis coe_inv two_ne_zero, coe_ofNat, nnnorm_pow, NNReal.sqrt_sq] _ = (2 : ℝ≥0∞)⁻¹ ^ Fintype.card { w // IsComplex w } * NNReal.sqrt ‖discr K‖₊ := by rw [← Algebra.discr_eq_det_embeddingsMatrixReindex_pow_two, Algebra.discr_reindex, - ← coe_discr, map_intCast, ← Complex.nnnorm_int] + ← coe_discr, map_intCast, ← Complex.nnnorm_intCast] ext : 2 dsimp only [M] rw [Matrix.map_apply, Basis.toMatrix_apply, Basis.coe_reindex, Function.comp_apply, @@ -194,7 +194,7 @@ theorem abs_discr_ge (h : 1 < finrank ℚ K) : convert_to _ ≤ (a m) * (1 + 1 / m : ℝ) ^ (2 * m) / (4 / π) · simp_rw [a, add_mul, one_mul, pow_succ, Nat.factorial_succ] field_simp; ring - · rw [_root_.le_div_iff (by positivity), pow_succ] + · rw [_root_.le_div_iff₀ (by positivity), pow_succ] convert (mul_le_mul h_m this (by positivity) (by positivity)) using 1 field_simp; ring refine le_trans (le_of_eq (by field_simp; norm_num)) (one_add_mul_le_pow ?_ (2 * m)) @@ -233,7 +233,7 @@ Thus it follows from `mixedEmbedding.exists_primitive_element_lt_of_isComplex` a `x` of `K` such that `K = ℚ(x)` and the conjugates of `x` are all bounded by some quantity depending only on `N`. -Since the primitive element `x` is constructed differently depending on wether `K` has a infinite +Since the primitive element `x` is constructed differently depending on whether `K` has a infinite real place or not, the theorem is proved in two parts. -/ @@ -291,8 +291,8 @@ theorem rank_le_rankOfDiscrBdd : rw [Real.rpow_logb (lt_trans zero_lt_one h₂) (ne_of_gt h₂) (by positivity), ← mul_assoc, ← inv_div, inv_mul_cancel₀ (by norm_num), one_mul, Int.cast_natCast] · refine div_nonneg (Real.log_nonneg ?_) (Real.log_nonneg (le_of_lt h₂)) - rw [mul_comm, ← mul_div_assoc, _root_.le_div_iff (by positivity), one_mul, - ← _root_.div_le_iff (by positivity)] + rw [mul_comm, ← mul_div_assoc, _root_.le_div_iff₀ (by positivity), one_mul, + ← _root_.div_le_iff₀ (by positivity)] exact le_trans (by norm_num) (Nat.one_le_cast.mpr (Nat.one_le_iff_ne_zero.mpr h_nz)) · exact le_max_of_le_left h diff --git a/Mathlib/NumberTheory/NumberField/Embeddings.lean b/Mathlib/NumberTheory/NumberField/Embeddings.lean index 7df0582059f8b..d2421c79c769e 100644 --- a/Mathlib/NumberTheory/NumberField/Embeddings.lean +++ b/Mathlib/NumberTheory/NumberField/Embeddings.lean @@ -483,7 +483,7 @@ section NumberField variable [NumberField K] /-- The infinite part of the product formula : for `x ∈ K`, we have `Π_w ‖x‖_w = |norm(x)|` where -`‖·‖_w` is the normalized absolute value for `w`. -/ +`‖·‖_w` is the normalized absolute value for `w`. -/ theorem prod_eq_abs_norm (x : K) : ∏ w : InfinitePlace K, w x ^ mult w = abs (Algebra.norm ℚ x) := by convert (congr_arg Complex.abs (@Algebra.norm_eq_prod_embeddings ℚ _ _ _ _ ℂ _ _ _ _ _ x)).symm @@ -1021,11 +1021,11 @@ variable {K} lemma IsUnramifiedAtInfinitePlaces_of_odd_card_aut [IsGalois k K] [FiniteDimensional k K] (h : Odd (Fintype.card <| K ≃ₐ[k] K)) : IsUnramifiedAtInfinitePlaces k K := - ⟨fun _ ↦ not_not.mp (Nat.odd_iff_not_even.mp h ∘ InfinitePlace.even_card_aut_of_not_isUnramified)⟩ + ⟨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 := - ⟨fun _ ↦ not_not.mp (Nat.odd_iff_not_even.mp h ∘ InfinitePlace.even_finrank_of_not_isUnramified)⟩ + ⟨fun _ ↦ not_not.mp (Nat.not_even_iff_odd.2 h ∘ InfinitePlace.even_finrank_of_not_isUnramified)⟩ variable (k K) diff --git a/Mathlib/NumberTheory/NumberField/FractionalIdeal.lean b/Mathlib/NumberTheory/NumberField/FractionalIdeal.lean index 371f141943b5f..3d5cc80dab357 100644 --- a/Mathlib/NumberTheory/NumberField/FractionalIdeal.lean +++ b/Mathlib/NumberTheory/NumberField/FractionalIdeal.lean @@ -103,7 +103,7 @@ open Module /-- The absolute value of the determinant of the base change from `integralBasis` to `basisOfFractionalIdeal I` is equal to the norm of `I`. -/ -theorem det_basisOfFractionalIdeal_eq_absNorm (I : (FractionalIdeal (𝓞 K)⁰ K)ˣ) +theorem det_basisOfFractionalIdeal_eq_absNorm (I : (FractionalIdeal (𝓞 K)⁰ K)ˣ) (e : (Free.ChooseBasisIndex ℤ (𝓞 K)) ≃ (Free.ChooseBasisIndex ℤ I)) : |(integralBasis K).det ((basisOfFractionalIdeal K I).reindex e.symm)| = FractionalIdeal.absNorm I.1 := by diff --git a/Mathlib/NumberTheory/NumberField/House.lean b/Mathlib/NumberTheory/NumberField/House.lean index 7cceb1f1e7e7c..5d0cc0062fc60 100644 --- a/Mathlib/NumberTheory/NumberField/House.lean +++ b/Mathlib/NumberTheory/NumberField/House.lean @@ -149,7 +149,7 @@ private theorem asiegel_ne_0 : asiegel K a ≠ 0 := by variable {p q : ℕ} (h0p : 0 < p) (hpq : p < q) (x : β × (K →+* ℂ) → ℤ) (hxl : x ≠ 0) -/-- `ξ` is the the product of `x (l, r)` and the `r`-th basis element of the newBasis of `K`. -/ +/-- `ξ` is the product of `x (l, r)` and the `r`-th basis element of the newBasis of `K`. -/ private def ξ : β → 𝓞 K := fun l => ∑ r : K →+* ℂ, x (l, r) * (newBasis K r) include hxl in diff --git a/Mathlib/NumberTheory/NumberField/Norm.lean b/Mathlib/NumberTheory/NumberField/Norm.lean index 2b99550a8a94e..2b529a1d239bb 100644 --- a/Mathlib/NumberTheory/NumberField/Norm.lean +++ b/Mathlib/NumberTheory/NumberField/Norm.lean @@ -40,7 +40,7 @@ namespace RingOfIntegers variable {L : Type*} (K : Type*) [Field K] [Field L] [Algebra K L] [FiniteDimensional K L] -/-- `Algebra.norm` as a morphism betwen the rings of integers. -/ +/-- `Algebra.norm` as a morphism between the rings of integers. -/ noncomputable def norm [Algebra.IsSeparable K L] : 𝓞 L →* 𝓞 K := RingOfIntegers.restrict_monoidHom ((Algebra.norm K).comp (algebraMap (𝓞 L) L : (𝓞 L) →* L)) diff --git a/Mathlib/NumberTheory/NumberField/Units/Basic.lean b/Mathlib/NumberTheory/NumberField/Units/Basic.lean index bacedd52bdeb2..eaabbc19a44f8 100644 --- a/Mathlib/NumberTheory/NumberField/Units/Basic.lean +++ b/Mathlib/NumberTheory/NumberField/Units/Basic.lean @@ -121,7 +121,7 @@ instance [NumberField K] : Fintype (torsion K) := by instance : Nonempty (torsion K) := One.instNonempty -/-- The torsion subgroup is cylic. -/ +/-- The torsion subgroup is cyclic. -/ instance [NumberField K] : IsCyclic (torsion K) := subgroup_units_cyclic _ /-- The order of the torsion subgroup as a positive integer. -/ diff --git a/Mathlib/NumberTheory/NumberField/Units/Regulator.lean b/Mathlib/NumberTheory/NumberField/Units/Regulator.lean index 6f0d5731d2ffe..2248cacd96cec 100644 --- a/Mathlib/NumberTheory/NumberField/Units/Regulator.lean +++ b/Mathlib/NumberTheory/NumberField/Units/Regulator.lean @@ -37,7 +37,7 @@ open MeasureTheory Classical BigOperators NumberField.InfinitePlace variable [NumberField K] -/-- The regulator of a number fied `K`. -/ +/-- The regulator of a number field `K`. -/ def regulator : ℝ := Zlattice.covolume (unitLattice K) theorem regulator_ne_zero : regulator K ≠ 0 := Zlattice.covolume_ne_zero (unitLattice K) volume @@ -60,7 +60,7 @@ theorem regulator_eq_det' (e : {w : InfinitePlace K // w ≠ w₀} ≃ Fin (rank regulator K = |(Matrix.of fun i ↦ (logEmbedding K) (fundSystem K (e i))).det| := by simp_rw [regulator, Zlattice.covolume_eq_det _ (((basisModTorsion K).map (logEmbeddingEquiv K)).reindex e.symm), Basis.coe_reindex, - Function.comp, Basis.map_apply, ← fundSystem_mk, Equiv.symm_symm] + Function.comp_def, Basis.map_apply, ← fundSystem_mk, Equiv.symm_symm] rfl /-- Let `u : Fin (rank K) → (𝓞 K)ˣ` be a family of units and let `w₁` and `w₂` be two infinite diff --git a/Mathlib/NumberTheory/Ostrowski.lean b/Mathlib/NumberTheory/Ostrowski.lean index c41547159ecef..de32a03798da5 100644 --- a/Mathlib/NumberTheory/Ostrowski.lean +++ b/Mathlib/NumberTheory/Ostrowski.lean @@ -6,7 +6,7 @@ María Inés de Frutos-Fernández, Sam van Gool, Silvain Rideau-Kikuchi, Amos Tu Francesco Veneziano -/ -import Mathlib.Analysis.Normed.Field.Basic +import Mathlib.Analysis.Normed.Field.Lemmas import Mathlib.Analysis.SpecialFunctions.Log.Base import Mathlib.Analysis.SpecialFunctions.Pow.Real import Mathlib.Analysis.Normed.Ring.Seminorm diff --git a/Mathlib/NumberTheory/Padics/PadicIntegers.lean b/Mathlib/NumberTheory/Padics/PadicIntegers.lean index 2076ea8bd3206..5e22e36d43bd8 100644 --- a/Mathlib/NumberTheory/Padics/PadicIntegers.lean +++ b/Mathlib/NumberTheory/Padics/PadicIntegers.lean @@ -162,7 +162,8 @@ def inv : ℤ_[p] → ℤ_[p] | ⟨k, _⟩ => if h : ‖k‖ = 1 then ⟨k⁻¹, by simp [h]⟩ else 0 instance : CharZero ℤ_[p] where - cast_injective m n h := Nat.cast_injective (by rw [Subtype.ext_iff] at h; norm_cast at h) + cast_injective m n h := + Nat.cast_injective (R := ℚ_[p]) (by rw [Subtype.ext_iff] at h; norm_cast at h) @[norm_cast] -- @[simp] -- Porting note: not in simpNF theorem intCast_eq (z1 z2 : ℤ) : (z1 : ℤ_[p]) = z2 ↔ z1 = z2 := by @@ -333,7 +334,7 @@ theorem norm_int_le_pow_iff_dvd {k : ℤ} {n : ℕ} : /-! ### Valuation on `ℤ_[p]` -/ -/-- `PadicInt.valuation` lifts the `p`-adic valuation on `ℚ` to `ℤ_[p]`. -/ +/-- `PadicInt.valuation` lifts the `p`-adic valuation on `ℚ` to `ℤ_[p]`. -/ def valuation (x : ℤ_[p]) := Padic.valuation (x : ℚ_[p]) diff --git a/Mathlib/NumberTheory/Padics/PadicNorm.lean b/Mathlib/NumberTheory/Padics/PadicNorm.lean index fb022f982f49c..164a53abcb173 100644 --- a/Mathlib/NumberTheory/Padics/PadicNorm.lean +++ b/Mathlib/NumberTheory/Padics/PadicNorm.lean @@ -4,7 +4,7 @@ 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 +import Mathlib.NumberTheory.Padics.PadicVal.Basic /-! # p-adic norm diff --git a/Mathlib/NumberTheory/Padics/PadicNumbers.lean b/Mathlib/NumberTheory/Padics/PadicNumbers.lean index 23431de0d49ec..abccff73fbb92 100644 --- a/Mathlib/NumberTheory/Padics/PadicNumbers.lean +++ b/Mathlib/NumberTheory/Padics/PadicNumbers.lean @@ -5,7 +5,7 @@ Authors: Robert Y. Lewis -/ import Mathlib.RingTheory.Valuation.Basic import Mathlib.NumberTheory.Padics.PadicNorm -import Mathlib.Analysis.Normed.Field.Basic +import Mathlib.Analysis.Normed.Field.Lemmas import Mathlib.Tactic.Peel import Mathlib.Topology.MetricSpace.Ultra.Basic @@ -149,7 +149,8 @@ theorem not_limZero_const_of_nonzero {q : ℚ} (hq : q ≠ 0) : ¬LimZero (const fun h' ↦ hq <| const_limZero.1 h' theorem not_equiv_zero_const_of_nonzero {q : ℚ} (hq : q ≠ 0) : ¬const (padicNorm p) q ≈ 0 := - fun h : LimZero (const (padicNorm p) q - 0) ↦ not_limZero_const_of_nonzero hq <| by simpa using h + fun h : LimZero (const (padicNorm p) q - 0) ↦ + not_limZero_const_of_nonzero (p := p) hq <| by simpa using h theorem norm_nonneg (f : PadicSeq p) : 0 ≤ f.norm := by classical exact if hf : f ≈ 0 then by simp [hf, norm] else by simp [norm, hf, padicNorm.nonneg] @@ -634,10 +635,10 @@ theorem exi_rat_seq_conv {ε : ℚ} (hε : 0 < ε) : ∃ N, ∀ i ≥ N, padicNormE (f i - (limSeq f i : ℚ_[p]) : ℚ_[p]) < ε := by refine (exists_nat_gt (1 / ε)).imp fun N hN i hi ↦ ?_ have h := Classical.choose_spec (rat_dense' (f i) (div_nat_pos i)) - refine lt_of_lt_of_le h ((div_le_iff' <| mod_cast succ_pos _).mpr ?_) + refine lt_of_lt_of_le h ((div_le_iff₀' <| mod_cast succ_pos _).mpr ?_) rw [right_distrib] apply le_add_of_le_of_nonneg - · exact (div_le_iff hε).mp (le_trans (le_of_lt hN) (mod_cast hi)) + · exact (div_le_iff₀ hε).mp (le_trans (le_of_lt hN) (mod_cast hi)) · apply le_of_lt simpa diff --git a/Mathlib/NumberTheory/Padics/PadicVal.lean b/Mathlib/NumberTheory/Padics/PadicVal/Basic.lean similarity index 92% rename from Mathlib/NumberTheory/Padics/PadicVal.lean rename to Mathlib/NumberTheory/Padics/PadicVal/Basic.lean index 368932b6dad66..a50d9d73886f6 100644 --- a/Mathlib/NumberTheory/Padics/PadicVal.lean +++ b/Mathlib/NumberTheory/Padics/PadicVal/Basic.lean @@ -4,10 +4,9 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Robert Y. Lewis, Matthew Robert Ballard -/ import Mathlib.NumberTheory.Divisors -import Mathlib.Data.Nat.Digits +import Mathlib.NumberTheory.Padics.PadicVal.Defs import Mathlib.Data.Nat.MaxPowDiv import Mathlib.Data.Nat.Multiplicity -import Mathlib.Tactic.IntervalCases /-! # `p`-adic Valuation @@ -68,29 +67,12 @@ open Rat open multiplicity -/-- For `p ≠ 1`, the `p`-adic valuation of a natural `n ≠ 0` is the largest natural number `k` such -that `p^k` divides `n`. If `n = 0` or `p = 1`, then `padicValNat p q` defaults to `0`. -/ -def padicValNat (p : ℕ) (n : ℕ) : ℕ := - if h : p ≠ 1 ∧ 0 < n then (multiplicity p n).get (multiplicity.finite_nat_iff.2 h) else 0 - namespace padicValNat open multiplicity variable {p : ℕ} -/-- `padicValNat p 0` is `0` for any `p`. -/ -@[simp] -protected theorem zero : padicValNat p 0 = 0 := by simp [padicValNat] - -/-- `padicValNat p 1` is `0` for any `p`. -/ -@[simp] -protected theorem one : padicValNat p 1 = 0 := by - unfold padicValNat - split_ifs - · simp - · rfl - /-- If `p ≠ 0` and `p ≠ 1`, then `padicValNat p p` is `1`. -/ @[simp] theorem self (hp : 1 < p) : padicValNat p p = 1 := by @@ -98,11 +80,6 @@ theorem self (hp : 1 < p) : padicValNat p p = 1 := by have eq_zero_false : p = 0 ↔ False := iff_false_intro (zero_lt_one.trans hp).ne' simp [padicValNat, neq_one, eq_zero_false] -@[simp] -theorem eq_zero_iff {n : ℕ} : padicValNat p n = 0 ↔ p = 1 ∨ n = 0 ∨ ¬p ∣ n := by - simp only [padicValNat, dite_eq_right_iff, PartENat.get_eq_iff_eq_coe, Nat.cast_zero, - multiplicity_eq_zero, and_imp, pos_iff_ne_zero, Ne, ← or_iff_not_imp_left] - theorem eq_zero_of_not_dvd {n : ℕ} (h : ¬p ∣ n) : padicValNat p n = 0 := eq_zero_iff.2 <| Or.inr <| Or.inr h @@ -247,15 +224,6 @@ theorem zero_le_padicValRat_of_nat (n : ℕ) : 0 ≤ padicValRat p n := by simp @[norm_cast] theorem padicValRat_of_nat (n : ℕ) : ↑(padicValNat p n) = padicValRat p n := by simp -/-- A simplification of `padicValNat` when one input is prime, by analogy with -`padicValRat_def`. -/ -theorem padicValNat_def [hp : Fact p.Prime] {n : ℕ} (hn : 0 < n) : - padicValNat p n = (multiplicity p n).get (multiplicity.finite_nat_iff.2 ⟨hp.out.ne_one, hn⟩) := - dif_pos ⟨hp.out.ne_one, hn⟩ - -theorem padicValNat_def' {n : ℕ} (hp : p ≠ 1) (hn : 0 < n) : - ↑(padicValNat p n) = multiplicity p n := by simp [padicValNat, hp, hn] - @[simp] theorem padicValNat_self [Fact p.Prime] : padicValNat p p = 1 := by rw [padicValNat_def (@Fact.out p.Prime).pos] @@ -271,28 +239,6 @@ theorem dvd_iff_padicValNat_ne_zero {p n : ℕ} [Fact p.Prime] (hn0 : n ≠ 0) : ⟨fun h => one_le_iff_ne_zero.mp (one_le_padicValNat_of_dvd hn0.bot_lt h), fun h => Classical.not_not.1 (mt padicValNat.eq_zero_of_not_dvd h)⟩ -open List - -theorem le_multiplicity_iff_replicate_subperm_primeFactorsList {a b : ℕ} {n : ℕ} (ha : a.Prime) - (hb : b ≠ 0) : - ↑n ≤ multiplicity a b ↔ replicate n a <+~ b.primeFactorsList := - (replicate_subperm_primeFactorsList_iff ha hb).trans - multiplicity.pow_dvd_iff_le_multiplicity |>.symm - -@[deprecated (since := "2024-07-17")] -alias le_multiplicity_iff_replicate_subperm_factors := - le_multiplicity_iff_replicate_subperm_primeFactorsList - -theorem le_padicValNat_iff_replicate_subperm_primeFactorsList {a b : ℕ} {n : ℕ} (ha : a.Prime) - (hb : b ≠ 0) : - n ≤ padicValNat a b ↔ replicate n a <+~ b.primeFactorsList := by - rw [← le_multiplicity_iff_replicate_subperm_primeFactorsList ha hb, - ← padicValNat_def' ha.ne_one (Nat.pos_of_ne_zero hb), Nat.cast_le] - -@[deprecated (since := "2024-07-17")] -alias le_padicValNat_iff_replicate_subperm_factors := - le_padicValNat_iff_replicate_subperm_primeFactorsList - end padicValNat namespace padicValRat diff --git a/Mathlib/NumberTheory/Padics/PadicVal/Defs.lean b/Mathlib/NumberTheory/Padics/PadicVal/Defs.lean new file mode 100644 index 0000000000000..1a6910baae3ae --- /dev/null +++ b/Mathlib/NumberTheory/Padics/PadicVal/Defs.lean @@ -0,0 +1,88 @@ +/- +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, Matthew Robert Ballard +-/ +import Mathlib.RingTheory.Multiplicity +import Mathlib.Data.Nat.Factors + +/-! +# `p`-adic Valuation + +This file defines the `p`-adic valuation on `ℕ`, `ℤ`, and `ℚ`. + +The `p`-adic valuation on `ℚ` is the difference of the multiplicities of `p` in the numerator and +denominator of `q`. This function obeys the standard properties of a valuation, with the appropriate +assumptions on `p`. The `p`-adic valuations on `ℕ` and `ℤ` agree with that on `ℚ`. + +The valuation induces a norm on `ℚ`. This norm is defined in padicNorm.lean. +-/ + +universe u + +open Nat + +open multiplicity + +variable {p : ℕ} + +/-- For `p ≠ 1`, the `p`-adic valuation of a natural `n ≠ 0` is the largest natural number `k` such +that `p^k` divides `n`. If `n = 0` or `p = 1`, then `padicValNat p q` defaults to `0`. -/ +def padicValNat (p : ℕ) (n : ℕ) : ℕ := + if h : p ≠ 1 ∧ 0 < n then (multiplicity p n).get (multiplicity.finite_nat_iff.2 h) else 0 + +/-- A simplification of `padicValNat` when one input is prime, by analogy with +`padicValRat_def`. -/ +theorem padicValNat_def [hp : Fact p.Prime] {n : ℕ} (hn : 0 < n) : + padicValNat p n = (multiplicity p n).get (multiplicity.finite_nat_iff.2 ⟨hp.out.ne_one, hn⟩) := + dif_pos ⟨hp.out.ne_one, hn⟩ + +theorem padicValNat_def' {n : ℕ} (hp : p ≠ 1) (hn : 0 < n) : + ↑(padicValNat p n) = multiplicity p n := by simp [padicValNat, hp, hn] + +namespace padicValNat + +open multiplicity + +open List + +/-- `padicValNat p 0` is `0` for any `p`. -/ +@[simp] +protected theorem zero : padicValNat p 0 = 0 := by simp [padicValNat] + +/-- `padicValNat p 1` is `0` for any `p`. -/ +@[simp] +protected theorem one : padicValNat p 1 = 0 := by + unfold padicValNat + split_ifs + · simp + · rfl + +@[simp] +theorem eq_zero_iff {n : ℕ} : padicValNat p n = 0 ↔ p = 1 ∨ n = 0 ∨ ¬p ∣ n := by + simp only [padicValNat, dite_eq_right_iff, PartENat.get_eq_iff_eq_coe, Nat.cast_zero, + multiplicity_eq_zero, and_imp, pos_iff_ne_zero, Ne, ← or_iff_not_imp_left] + +end padicValNat + +open List + +theorem le_multiplicity_iff_replicate_subperm_primeFactorsList {a b : ℕ} {n : ℕ} (ha : a.Prime) + (hb : b ≠ 0) : + ↑n ≤ multiplicity a b ↔ replicate n a <+~ b.primeFactorsList := + (replicate_subperm_primeFactorsList_iff ha hb).trans + multiplicity.pow_dvd_iff_le_multiplicity |>.symm + +@[deprecated (since := "2024-07-17")] +alias le_multiplicity_iff_replicate_subperm_factors := + le_multiplicity_iff_replicate_subperm_primeFactorsList + +theorem le_padicValNat_iff_replicate_subperm_primeFactorsList {a b : ℕ} {n : ℕ} (ha : a.Prime) + (hb : b ≠ 0) : + n ≤ padicValNat a b ↔ replicate n a <+~ b.primeFactorsList := by + rw [← le_multiplicity_iff_replicate_subperm_primeFactorsList ha hb, + ← padicValNat_def' ha.ne_one (Nat.pos_of_ne_zero hb), Nat.cast_le] + +@[deprecated (since := "2024-07-17")] +alias le_padicValNat_iff_replicate_subperm_factors := + le_padicValNat_iff_replicate_subperm_primeFactorsList diff --git a/Mathlib/NumberTheory/PellMatiyasevic.lean b/Mathlib/NumberTheory/PellMatiyasevic.lean index 66f902be634a1..b931db03869a5 100644 --- a/Mathlib/NumberTheory/PellMatiyasevic.lean +++ b/Mathlib/NumberTheory/PellMatiyasevic.lean @@ -182,7 +182,7 @@ theorem pellZd_im (n : ℕ) : (pellZd a1 n).im = yn a1 n := theorem isPell_nat {x y : ℕ} : IsPell (⟨x, y⟩ : ℤ√(d a1)) ↔ x * x - d a1 * y * y = 1 := ⟨fun h => - Nat.cast_inj.1 + (Nat.cast_inj (R := ℤ)).1 (by rw [Int.ofNat_sub (Int.le_of_ofNat_le_ofNat <| Int.le.intro_sub _ h)]; exact h), fun h => show ((x * x : ℕ) - (d a1 * y * y : ℕ) : ℤ) = 1 by @@ -211,7 +211,7 @@ theorem pell_eq (n : ℕ) : xn a1 n * xn a1 n - d a1 * yn a1 n * yn a1 n = 1 := repeat' rw [Int.ofNat_mul]; exact pn have hl : d a1 * yn a1 n * yn a1 n ≤ xn a1 n * xn a1 n := Nat.cast_le.1 <| Int.le.intro _ <| add_eq_of_eq_sub' <| Eq.symm h - Nat.cast_inj.1 (by rw [Int.ofNat_sub hl]; exact h) + (Nat.cast_inj (R := ℤ)).1 (by rw [Int.ofNat_sub hl]; exact h) instance dnsq : Zsqrtd.Nonsquare (d a1) := ⟨fun n h => @@ -708,10 +708,7 @@ theorem eq_of_xn_modEq' {i j n} (ipos : 0 < i) (hin : i ≤ n) (j4n : j ≤ 4 * _root_.ne_of_gt ipos i0⟩) fun j2n : 2 * n < j => suffices i = 4 * n - j by rw [this, add_tsub_cancel_of_le j4n] - have j42n : 4 * n - j ≤ 2 * n := - Nat.le_of_add_le_add_right <| by - rw [tsub_add_cancel_of_le j4n, show 4 * n = 2 * n + 2 * n from right_distrib 2 2 n] - exact Nat.add_le_add_left (le_of_lt j2n) _ + have j42n : 4 * n - j ≤ 2 * n := by omega eq_of_xn_modEq a1 i2n j42n (h.symm.trans <| by let t := xn_modEq_x4n_sub a1 j42n @@ -753,7 +750,7 @@ theorem xy_modEq_of_modEq {a b c} (a1 : 1 < a) (b1 : 1 < b) (h : a ≡ b [MOD c] ⟨(xy_modEq_of_modEq a1 b1 h n).left.add_right_cancel <| by rw [xn_succ_succ a1, xn_succ_succ b1] exact (h.mul_left _).mul (xy_modEq_of_modEq _ _ h (n + 1)).left, - (xy_modEq_of_modEq _ _ h n).right.add_right_cancel <| by + (xy_modEq_of_modEq a1 b1 h n).right.add_right_cancel <| by rw [yn_succ_succ a1, yn_succ_succ b1] exact (h.mul_left _).mul (xy_modEq_of_modEq _ _ h (n + 1)).right⟩ diff --git a/Mathlib/NumberTheory/PrimeCounting.lean b/Mathlib/NumberTheory/PrimeCounting.lean index e49c213d69742..92dca84e7b65e 100644 --- a/Mathlib/NumberTheory/PrimeCounting.lean +++ b/Mathlib/NumberTheory/PrimeCounting.lean @@ -27,7 +27,7 @@ are not prime, and so only at most `φ(k)/k` fraction of the numbers from `k` to ## Notation -Wtih `open scoped Nat.Prime`, we use the standard notation `π` to represent the prime counting +With `open scoped Nat.Prime`, we use the standard notation `π` to represent the prime counting function (and `π'` to represent the reindexed version). -/ diff --git a/Mathlib/NumberTheory/Primorial.lean b/Mathlib/NumberTheory/Primorial.lean index e97e2a02e51de..8bc67a5f611f7 100644 --- a/Mathlib/NumberTheory/Primorial.lean +++ b/Mathlib/NumberTheory/Primorial.lean @@ -41,7 +41,7 @@ theorem primorial_pos (n : ℕ) : 0 < n# := theorem primorial_succ {n : ℕ} (hn1 : n ≠ 1) (hn : Odd n) : (n + 1)# = n# := by refine prod_congr ?_ fun _ _ ↦ rfl - rw [range_succ, filter_insert, if_neg fun h ↦ odd_iff_not_even.mp hn _] + rw [range_succ, filter_insert, if_neg fun h ↦ not_even_iff_odd.2 hn _] exact fun h ↦ h.even_sub_one <| mt succ.inj hn1 theorem primorial_add (m n : ℕ) : diff --git a/Mathlib/NumberTheory/Rayleigh.lean b/Mathlib/NumberTheory/Rayleigh.lean index efa4c9a35de90..d7a2e5f205472 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₄ @@ -102,7 +102,7 @@ private theorem hit_or_miss' (h : r > 0) : j ∈ {beattySeq' r k | k} ∨ ∃ k : ℤ, k ≤ j / r ∧ (j + 1) / r < k + 1 := by -- for both cases, the candidate is `k = ⌊(j + 1) / r⌋` cases le_or_gt (⌊(j + 1) / r⌋ * r) j - · exact Or.inr ⟨⌊(j + 1) / r⌋, (le_div_iff h).2 ‹_›, Int.lt_floor_add_one _⟩ + · exact Or.inr ⟨⌊(j + 1) / r⌋, (le_div_iff₀ h).2 ‹_›, Int.lt_floor_add_one _⟩ · refine Or.inl ⟨⌊(j + 1) / r⌋, ?_⟩ rw [beattySeq', sub_eq_iff_eq_add, Int.ceil_eq_iff, Int.cast_add, Int.cast_one] constructor diff --git a/Mathlib/NumberTheory/SumTwoSquares.lean b/Mathlib/NumberTheory/SumTwoSquares.lean index ac1c6735ecf20..4c8c1a2799082 100644 --- a/Mathlib/NumberTheory/SumTwoSquares.lean +++ b/Mathlib/NumberTheory/SumTwoSquares.lean @@ -5,7 +5,7 @@ Authors: Chris Hughes, Michael Stoll -/ import Mathlib.Data.Nat.Squarefree import Mathlib.NumberTheory.Zsqrtd.QuadraticReciprocity -import Mathlib.Tactic.LinearCombination +import Mathlib.NumberTheory.Padics.PadicVal.Basic /-! # Sums of two squares @@ -216,7 +216,7 @@ theorem Nat.eq_sq_add_sq_iff {n : ℕ} : exact even_two_mul _ · obtain ⟨b, a, hb₀, ha₀, hab, hb⟩ := Nat.sq_mul_squarefree_of_pos hn₀ refine ⟨a, b, hab.symm, (ZMod.isSquare_neg_one_iff hb).mpr fun {q} hqp hqb hq4 => ?_⟩ - refine Nat.odd_iff_not_even.mp ?_ (H hqp hq4) + refine Nat.not_even_iff_odd.2 ?_ (H hqp hq4) have hqb' : padicValNat q b = 1 := b.factorization_def hqp ▸ le_antisymm (hb.natFactorization_le_one _) ((hqp.dvd_iff_one_le_factorization hb₀.ne').mp hqb) diff --git a/Mathlib/NumberTheory/WellApproximable.lean b/Mathlib/NumberTheory/WellApproximable.lean index fa77ff16edf76..7b72f49ff60e8 100644 --- a/Mathlib/NumberTheory/WellApproximable.lean +++ b/Mathlib/NumberTheory/WellApproximable.lean @@ -10,7 +10,7 @@ import Mathlib.MeasureTheory.Covering.LiminfLimsup # Well-approximable numbers and Gallagher's ergodic theorem Gallagher's ergodic theorem is a result in metric number theory. It thus belongs to that branch of -mathematics concerning arithmetic properties of real numbers which hold almost eveywhere with +mathematics concerning arithmetic properties of real numbers which hold almost everywhere with respect to the Lebesgue measure. Gallagher's theorem concerns the approximation of real numbers by rational numbers. The input is a @@ -248,7 +248,7 @@ theorem addWellApproximable_ae_empty_or_univ (δ : ℕ → ℝ) (hδ : Tendsto let f : 𝕊 → 𝕊 := fun y => (p : ℕ) • y suffices f '' A p ⊆ blimsup (fun n => approxAddOrderOf 𝕊 n (p * δ n)) atTop fun n => 0 < n ∧ p∤n by - apply (ergodic_nsmul hp.one_lt).ae_empty_or_univ_of_image_ae_le (hA₀ p) + apply (ergodic_nsmul hp.one_lt).ae_empty_or_univ_of_image_ae_le (hA₀ p).nullMeasurableSet apply (HasSubset.Subset.eventuallyLE this).congr EventuallyEq.rfl exact blimsup_thickening_mul_ae_eq μ (fun n => 0 < n ∧ p∤n) (fun n => {y | addOrderOf y = n}) (Nat.cast_pos.mpr hp.pos) _ hδ @@ -261,7 +261,8 @@ theorem addWellApproximable_ae_empty_or_univ (δ : ℕ → ℝ) (hδ : Tendsto let f : 𝕊 → 𝕊 := fun y => p • y + x suffices f '' B p ⊆ blimsup (fun n => approxAddOrderOf 𝕊 n (p * δ n)) atTop fun n => 0 < n ∧ p∣∣n by - apply (ergodic_nsmul_add x hp.one_lt).ae_empty_or_univ_of_image_ae_le (hB₀ p) + apply (ergodic_nsmul_add x hp.one_lt).ae_empty_or_univ_of_image_ae_le + (hB₀ p).nullMeasurableSet apply (HasSubset.Subset.eventuallyLE this).congr EventuallyEq.rfl exact blimsup_thickening_mul_ae_eq μ (fun n => 0 < n ∧ p∣∣n) (fun n => {y | addOrderOf y = n}) (Nat.cast_pos.mpr hp.pos) _ hδ diff --git a/Mathlib/NumberTheory/Zsqrtd/Basic.lean b/Mathlib/NumberTheory/Zsqrtd/Basic.lean index a697ad60f1bbe..acbc027998af2 100644 --- a/Mathlib/NumberTheory/Zsqrtd/Basic.lean +++ b/Mathlib/NumberTheory/Zsqrtd/Basic.lean @@ -476,13 +476,13 @@ theorem norm_eq_mul_conj (n : ℤ√d) : (norm n : ℤ√d) = n * star n := by theorem norm_neg (x : ℤ√d) : (-x).norm = x.norm := -- Porting note: replaced `simp` with `rw` -- See https://github.com/leanprover-community/mathlib4/issues/5026 - Int.cast_inj.1 <| by rw [norm_eq_mul_conj, star_neg, neg_mul_neg, norm_eq_mul_conj] + (Int.cast_inj (α := ℤ√d)).1 <| by rw [norm_eq_mul_conj, star_neg, neg_mul_neg, norm_eq_mul_conj] @[simp] theorem norm_conj (x : ℤ√d) : (star x).norm = x.norm := -- Porting note: replaced `simp` with `rw` -- See https://github.com/leanprover-community/mathlib4/issues/5026 - Int.cast_inj.1 <| by rw [norm_eq_mul_conj, star_star, mul_comm, norm_eq_mul_conj] + (Int.cast_inj (α := ℤ√d)).1 <| by rw [norm_eq_mul_conj, star_star, mul_comm, norm_eq_mul_conj] theorem norm_nonneg (hd : d ≤ 0) (n : ℤ√d) : 0 ≤ n.norm := add_nonneg (mul_self_nonneg _) diff --git a/Mathlib/NumberTheory/Zsqrtd/QuadraticReciprocity.lean b/Mathlib/NumberTheory/Zsqrtd/QuadraticReciprocity.lean index a22d6696a31a2..413c023dba9e7 100644 --- a/Mathlib/NumberTheory/Zsqrtd/QuadraticReciprocity.lean +++ b/Mathlib/NumberTheory/Zsqrtd/QuadraticReciprocity.lean @@ -5,7 +5,7 @@ Authors: Chris Hughes -/ import Mathlib.NumberTheory.Zsqrtd.GaussianInt import Mathlib.NumberTheory.LegendreSymbol.Basic -import Mathlib.Analysis.Normed.Field.Basic +import Mathlib.Analysis.Normed.Field.Lemmas /-! # Facts about the gaussian integers relying on quadratic reciprocity. diff --git a/Mathlib/Order/Basic.lean b/Mathlib/Order/Basic.lean index 6e4c780550a19..22337e909a51a 100644 --- a/Mathlib/Order/Basic.lean +++ b/Mathlib/Order/Basic.lean @@ -3,14 +3,13 @@ Copyright (c) 2014 Jeremy Avigad. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad, Mario Carneiro -/ -import Mathlib.Init.Order.LinearOrder import Mathlib.Data.Prod.Basic import Mathlib.Data.Subtype +import Mathlib.Order.Defs +import Mathlib.Order.Notation import Mathlib.Tactic.Spread import Mathlib.Tactic.Convert import Mathlib.Tactic.SimpRw -import Mathlib.Tactic.Cases -import Mathlib.Order.Notation import Batteries.Data.Sum.Lemmas import Batteries.Tactic.Classical @@ -287,15 +286,6 @@ protected theorem GT.gt.lt [LT α] {x y : α} (h : x > y) : y < x := theorem ge_of_eq [Preorder α] {a b : α} (h : a = b) : a ≥ b := h.ge -theorem not_le_of_lt [Preorder α] {a b : α} (h : a < b) : ¬b ≤ a := - (le_not_le_of_lt h).right - -alias LT.lt.not_le := not_le_of_lt - -theorem not_lt_of_le [Preorder α] {a b : α} (h : a ≤ b) : ¬b < a := fun hba ↦ hba.not_le h - -alias LE.le.not_lt := not_lt_of_le - theorem ne_of_not_le [Preorder α] {a b : α} (h : ¬a ≤ b) : a ≠ b := fun hab ↦ h (le_of_eq hab) section PartialOrder @@ -452,7 +442,7 @@ theorem eq_of_forall_lt_iff [LinearOrder α] {a b : α} (h : ∀ c, c < a ↔ c theorem eq_of_forall_gt_iff [LinearOrder α] {a b : α} (h : ∀ c, a < c ↔ b < c) : a = b := (le_of_forall_lt' fun _ ↦ (h _).2).antisymm <| le_of_forall_lt' fun _ ↦ (h _).1 -/-- A symmetric relation implies two values are equal, when it implies they're less-equal. -/ +/-- A symmetric relation implies two values are equal, when it implies they're less-equal. -/ theorem rel_imp_eq_of_rel_imp_le [PartialOrder β] (r : α → α → Prop) [IsSymm α r] {f : α → β} (h : ∀ a b, r a b → f a ≤ f b) {a b : α} : r a b → f a = f b := fun hab ↦ le_antisymm (h a b hab) (h b a <| symm hab) @@ -1252,8 +1242,9 @@ lemma eq_or_eq_or_eq_of_forall_not_lt_lt [LinearOrder α] (h : ∀ ⦃x y z : α⦄, x < y → y < z → False) (x y z : α) : x = y ∨ y = z ∨ x = z := by by_contra hne simp only [not_or, ← Ne.eq_def] at hne - cases' hne.1.lt_or_lt with h₁ h₁ <;> cases' hne.2.1.lt_or_lt with h₂ h₂ <;> - cases' hne.2.2.lt_or_lt with h₃ h₃ + rcases hne.1.lt_or_lt with h₁ | h₁ <;> + rcases hne.2.1.lt_or_lt with h₂ | h₂ <;> + rcases hne.2.2.lt_or_lt with h₃ | h₃ exacts [h h₁ h₂, h h₂ h₃, h h₃ h₂, h h₃ h₁, h h₁ h₃, h h₂ h₃, h h₁ h₃, h h₂ h₁] namespace PUnit diff --git a/Mathlib/Order/Bounded.lean b/Mathlib/Order/Bounded.lean index 4ec049678f991..2a70d6afbe227 100644 --- a/Mathlib/Order/Bounded.lean +++ b/Mathlib/Order/Bounded.lean @@ -92,8 +92,8 @@ theorem unbounded_lt_of_unbounded_le [Preorder α] (h : Unbounded (· ≤ ·) s) theorem bounded_le_iff_bounded_lt [Preorder α] [NoMaxOrder α] : Bounded (· ≤ ·) s ↔ Bounded (· < ·) s := by refine ⟨fun h => ?_, bounded_le_of_bounded_lt⟩ - cases' h with a ha - cases' exists_gt a with b hb + obtain ⟨a, ha⟩ := h + obtain ⟨b, hb⟩ := exists_gt a exact ⟨b, fun c hc => lt_of_le_of_lt (ha c hc) hb⟩ theorem unbounded_lt_iff_unbounded_le [Preorder α] [NoMaxOrder α] : @@ -247,7 +247,7 @@ theorem bounded_inter_not (H : ∀ a b, ∃ m, ∀ c, r c a ∨ r c b → r c m) Bounded r (s ∩ { b | ¬r b a }) ↔ Bounded r s := by refine ⟨?_, Bounded.mono inter_subset_left⟩ rintro ⟨b, hb⟩ - cases' H a b with m hm + obtain ⟨m, hm⟩ := H a b exact ⟨m, fun c hc => hm c (or_iff_not_imp_left.2 fun hca => hb c ⟨hc, hca⟩)⟩ theorem unbounded_inter_not (H : ∀ a b, ∃ m, ∀ c, r c a ∨ r c b → r c m) (a : α) : diff --git a/Mathlib/Order/BoundedOrder.lean b/Mathlib/Order/BoundedOrder.lean index d4039a093f12d..eebe3d3ddcdd1 100644 --- a/Mathlib/Order/BoundedOrder.lean +++ b/Mathlib/Order/BoundedOrder.lean @@ -144,6 +144,9 @@ theorem StrictMono.apply_eq_top_iff (hf : StrictMono f) : f a = f ⊤ ↔ a = theorem StrictAnti.apply_eq_top_iff (hf : StrictAnti f) : f a = f ⊤ ↔ a = ⊤ := ⟨fun h => not_lt_top_iff.1 fun ha => (hf ha).ne' h, congr_arg _⟩ +lemma top_not_mem_iff {s : Set α} : ⊤ ∉ s ↔ ∀ x ∈ s, x < ⊤ := + ⟨fun h x hx ↦ Ne.lt_top (fun hx' : x = ⊤ ↦ h (hx' ▸ hx)), fun h h₀ ↦ (h ⊤ h₀).false⟩ + variable [Nontrivial α] theorem not_isMin_top : ¬IsMin (⊤ : α) := fun h => @@ -313,6 +316,9 @@ theorem StrictMono.apply_eq_bot_iff (hf : StrictMono f) : f a = f ⊥ ↔ a = theorem StrictAnti.apply_eq_bot_iff (hf : StrictAnti f) : f a = f ⊥ ↔ a = ⊥ := hf.dual.apply_eq_top_iff +lemma bot_not_mem_iff {s : Set α} : ⊥ ∉ s ↔ ∀ x ∈ s, ⊥ < x := + top_not_mem_iff (α := αᵒᵈ) + variable [Nontrivial α] theorem not_isMax_bot : ¬IsMax (⊥ : α) := diff --git a/Mathlib/Order/Bounds/Basic.lean b/Mathlib/Order/Bounds/Basic.lean index e1b7a921c750f..b8c81cbad1d9d 100644 --- a/Mathlib/Order/Bounds/Basic.lean +++ b/Mathlib/Order/Bounds/Basic.lean @@ -466,7 +466,7 @@ theorem le_glb_Ioi (a : α) (hb : IsGLB (Ioi a) b) : a ≤ b := theorem lub_Iio_eq_self_or_Iio_eq_Iic [PartialOrder γ] {j : γ} (i : γ) (hj : IsLUB (Iio i) j) : j = i ∨ Iio i = Iic j := by - cases' eq_or_lt_of_le (lub_Iio_le i hj) with hj_eq_i hj_lt_i + rcases eq_or_lt_of_le (lub_Iio_le i hj) with hj_eq_i | hj_lt_i · exact Or.inl hj_eq_i · right exact Set.ext fun k => ⟨fun hk_lt => hj.1 hk_lt, fun hk_le_j => lt_of_le_of_lt hk_le_j hj_lt_i⟩ @@ -609,7 +609,7 @@ variable [SemilatticeSup γ] [DenselyOrdered γ] theorem isGLB_Ioo {a b : γ} (h : a < b) : IsGLB (Ioo a b) a := ⟨fun x hx => hx.1.le, fun x hx => by - cases' eq_or_lt_of_le (le_sup_right : a ≤ x ⊔ a) with h₁ h₂ + rcases eq_or_lt_of_le (le_sup_right : a ≤ x ⊔ a) with h₁ | h₂ · exact h₁.symm ▸ le_sup_left obtain ⟨y, lty, ylt⟩ := exists_between h₂ apply (not_lt_of_le (sup_le (hx ⟨lty, ylt.trans_le (sup_le _ h.le)⟩) lty.le) ylt).elim diff --git a/Mathlib/Order/Category/FinPartOrd.lean b/Mathlib/Order/Category/FinPartOrd.lean index 07c4af377d9b9..5b90c8fa7d59d 100644 --- a/Mathlib/Order/Category/FinPartOrd.lean +++ b/Mathlib/Order/Category/FinPartOrd.lean @@ -86,11 +86,12 @@ def dual : FinPartOrd ⥤ FinPartOrd where map {X Y} := OrderHom.dual /-- The equivalence between `FinPartOrd` and itself induced by `OrderDual` both ways. -/ -@[simps! functor inverse] -def dualEquiv : FinPartOrd ≌ FinPartOrd := - CategoryTheory.Equivalence.mk dual dual - (NatIso.ofComponents fun X => Iso.mk <| OrderIso.dualDual X) - (NatIso.ofComponents fun X => Iso.mk <| OrderIso.dualDual X) +@[simps] +def dualEquiv : FinPartOrd ≌ FinPartOrd where + functor := dual + inverse := dual + unitIso := NatIso.ofComponents fun X => Iso.mk <| OrderIso.dualDual X + counitIso := NatIso.ofComponents fun X => Iso.mk <| OrderIso.dualDual X end FinPartOrd diff --git a/Mathlib/Order/Compare.lean b/Mathlib/Order/Compare.lean index 1c64ab9fca995..4bd82d405b971 100644 --- a/Mathlib/Order/Compare.lean +++ b/Mathlib/Order/Compare.lean @@ -110,14 +110,13 @@ theorem Compares.inj [Preorder α] {o₁} : theorem compares_iff_of_compares_impl [LinearOrder α] [Preorder β] {a b : α} {a' b' : β} (h : ∀ {o}, Compares o a b → Compares o a' b') (o) : Compares o a b ↔ Compares o a' b' := by refine ⟨h, fun ho => ?_⟩ - cases' lt_trichotomy a b with hab hab + rcases lt_trichotomy a b with hab | hab | hab · have hab : Compares Ordering.lt a b := hab rwa [ho.inj (h hab)] - · cases' hab with hab hab - · have hab : Compares Ordering.eq a b := hab - rwa [ho.inj (h hab)] - · have hab : Compares Ordering.gt a b := hab - rwa [ho.inj (h hab)] + · have hab : Compares Ordering.eq a b := hab + rwa [ho.inj (h hab)] + · have hab : Compares Ordering.gt a b := hab + rwa [ho.inj (h hab)] theorem swap_orElse (o₁ o₂) : (orElse o₁ o₂).swap = orElse o₁.swap o₂.swap := by cases o₁ <;> rfl diff --git a/Mathlib/Order/CompleteLattice.lean b/Mathlib/Order/CompleteLattice.lean index 8dcff462eddbf..dd660dbea66f8 100644 --- a/Mathlib/Order/CompleteLattice.lean +++ b/Mathlib/Order/CompleteLattice.lean @@ -326,40 +326,44 @@ open OrderDual section -variable [CompleteLattice α] {s t : Set α} {a b : α} +section OrderDual @[simp] -theorem toDual_sSup (s : Set α) : toDual (sSup s) = sInf (ofDual ⁻¹' s) := +theorem toDual_sSup [SupSet α] (s : Set α) : toDual (sSup s) = sInf (ofDual ⁻¹' s) := rfl @[simp] -theorem toDual_sInf (s : Set α) : toDual (sInf s) = sSup (ofDual ⁻¹' s) := +theorem toDual_sInf [InfSet α] (s : Set α) : toDual (sInf s) = sSup (ofDual ⁻¹' s) := rfl @[simp] -theorem ofDual_sSup (s : Set αᵒᵈ) : ofDual (sSup s) = sInf (toDual ⁻¹' s) := +theorem ofDual_sSup [InfSet α] (s : Set αᵒᵈ) : ofDual (sSup s) = sInf (toDual ⁻¹' s) := rfl @[simp] -theorem ofDual_sInf (s : Set αᵒᵈ) : ofDual (sInf s) = sSup (toDual ⁻¹' s) := +theorem ofDual_sInf [SupSet α] (s : Set αᵒᵈ) : ofDual (sInf s) = sSup (toDual ⁻¹' s) := rfl @[simp] -theorem toDual_iSup (f : ι → α) : toDual (⨆ i, f i) = ⨅ i, toDual (f i) := +theorem toDual_iSup [SupSet α] (f : ι → α) : toDual (⨆ i, f i) = ⨅ i, toDual (f i) := rfl @[simp] -theorem toDual_iInf (f : ι → α) : toDual (⨅ i, f i) = ⨆ i, toDual (f i) := +theorem toDual_iInf [InfSet α] (f : ι → α) : toDual (⨅ i, f i) = ⨆ i, toDual (f i) := rfl @[simp] -theorem ofDual_iSup (f : ι → αᵒᵈ) : ofDual (⨆ i, f i) = ⨅ i, ofDual (f i) := +theorem ofDual_iSup [InfSet α] (f : ι → αᵒᵈ) : ofDual (⨆ i, f i) = ⨅ i, ofDual (f i) := rfl @[simp] -theorem ofDual_iInf (f : ι → αᵒᵈ) : ofDual (⨅ i, f i) = ⨆ i, ofDual (f i) := +theorem ofDual_iInf [SupSet α] (f : ι → αᵒᵈ) : ofDual (⨅ i, f i) = ⨆ i, ofDual (f i) := rfl +end OrderDual + +variable [CompleteLattice α] {s t : Set α} {a b : α} + theorem sInf_le_sSup (hs : s.Nonempty) : sInf s ≤ sSup s := isGLB_le_isLUB (isGLB_sInf s) (isLUB_sSup s) hs @@ -866,6 +870,9 @@ theorem iSup_eq_bot : iSup s = ⊥ ↔ ∀ i, s i = ⊥ := theorem iInf_eq_top : iInf s = ⊤ ↔ ∀ i, s i = ⊤ := sInf_eq_top.trans forall_mem_range +@[simp] lemma bot_lt_iSup : ⊥ < ⨆ i, s i ↔ ∃ i, ⊥ < s i := by simp [bot_lt_iff_ne_bot] +@[simp] lemma iInf_lt_top : ⨅ i, s i < ⊤ ↔ ∃ i, s i < ⊤ := by simp [lt_top_iff_ne_top] + theorem iSup₂_eq_bot {f : ∀ i, κ i → α} : ⨆ (i) (j), f i j = ⊥ ↔ ∀ i j, f i j = ⊥ := by simp @@ -1025,7 +1032,7 @@ lemma le_biSup {ι : Type*} {s : Set ι} (f : ι → α) {i : ι} (hi : i ∈ s) begin apply @le_antisymm, - safe, pose h := f a ⊓ g a, begin [smt] ematch, ematch end + safe, pose h := f a ⊓ g a, begin [smt] ematch, ematch end end -/ theorem iSup_sup [Nonempty ι] {f : ι → α} {a : α} : (⨆ x, f x) ⊔ a = ⨆ x, f x ⊔ a := by @@ -1273,12 +1280,24 @@ theorem iInf_sigma {p : β → Type*} {f : Sigma p → α} : ⨅ x, f x = ⨅ (i @iSup_sigma αᵒᵈ _ _ _ _ lemma iSup_sigma' {κ : β → Type*} (f : ∀ i, κ i → α) : - (⨆ i, ⨆ j, f i j) = ⨆ x : Σ i, κ i, f x.1 x.2 := -(iSup_sigma (f := fun x ↦ f x.1 x.2)).symm + (⨆ i, ⨆ j, f i j) = ⨆ x : Σ i, κ i, f x.1 x.2 := (iSup_sigma (f := fun x ↦ f x.1 x.2)).symm lemma iInf_sigma' {κ : β → Type*} (f : ∀ i, κ i → α) : - (⨅ i, ⨅ j, f i j) = ⨅ x : Σ i, κ i, f x.1 x.2 := -(iInf_sigma (f := fun x ↦ f x.1 x.2)).symm + (⨅ i, ⨅ j, f i j) = ⨅ x : Σ i, κ i, f x.1 x.2 := (iInf_sigma (f := fun x ↦ f x.1 x.2)).symm + +lemma iSup_psigma {ι : Sort*} {κ : ι → Sort*} (f : (Σ' i, κ i) → α) : + ⨆ ij, f ij = ⨆ i, ⨆ j, f ⟨i, j⟩ := + eq_of_forall_ge_iff fun c ↦ by simp only [iSup_le_iff, PSigma.forall] + +lemma iInf_psigma {ι : Sort*} {κ : ι → Sort*} (f : (Σ' i, κ i) → α) : + ⨅ ij, f ij = ⨅ i, ⨅ j, f ⟨i, j⟩ := + eq_of_forall_le_iff fun c ↦ by simp only [le_iInf_iff, PSigma.forall] + +lemma iSup_psigma' {ι : Sort*} {κ : ι → Sort*} (f : ∀ i, κ i → α) : + (⨆ i, ⨆ j, f i j) = ⨆ ij : Σ' i, κ i, f ij.1 ij.2 := (iSup_psigma fun x ↦ f x.1 x.2).symm + +lemma iInf_psigma' {ι : Sort*} {κ : ι → Sort*} (f : ∀ i, κ i → α) : + (⨅ i, ⨅ j, f i j) = ⨅ ij : Σ' i, κ i, f ij.1 ij.2 := (iInf_psigma fun x ↦ f x.1 x.2).symm theorem iSup_prod {f : β × γ → α} : ⨆ x, f x = ⨆ (i) (j), f (i, j) := eq_of_forall_ge_iff fun c => by simp only [iSup_le_iff, Prod.forall] @@ -1412,6 +1431,12 @@ theorem iSup_eq_top (f : ι → α) : iSup f = ⊤ ↔ ∀ b < ⊤, ∃ i, b < f theorem iInf_eq_bot (f : ι → α) : iInf f = ⊥ ↔ ∀ b > ⊥, ∃ i, f i < b := by simp only [← sInf_range, sInf_eq_bot, Set.exists_range_iff] +lemma iSup₂_eq_top (f : ∀ i, κ i → α) : ⨆ i, ⨆ j, f i j = ⊤ ↔ ∀ b < ⊤, ∃ i j, b < f i j := by + simp_rw [iSup_psigma', iSup_eq_top, PSigma.exists] + +lemma iInf₂_eq_bot (f : ∀ i, κ i → α) : ⨅ i, ⨅ j, f i j = ⊥ ↔ ∀ b > ⊥, ∃ i j, f i j < b := by + simp_rw [iInf_psigma', iInf_eq_bot, PSigma.exists] + end CompleteLinearOrder /-! @@ -1575,7 +1600,7 @@ theorem snd_iInf [InfSet α] [InfSet β] (f : ι → α × β) : (iInf f).snd = congr_arg sInf (range_comp _ _).symm theorem swap_iInf [InfSet α] [InfSet β] (f : ι → α × β) : (iInf f).swap = ⨅ i, (f i).swap := by - simp_rw [iInf, swap_sInf, ← range_comp, Function.comp] -- Porting note: need to unfold `∘` + simp_rw [iInf, swap_sInf, ← range_comp, comp_def] -- Porting note: need to unfold `∘` theorem iInf_mk [InfSet α] [InfSet β] (f : ι → α) (g : ι → β) : ⨅ i, (f i, g i) = (⨅ i, f i, ⨅ i, g i) := @@ -1588,7 +1613,7 @@ theorem snd_iSup [SupSet α] [SupSet β] (f : ι → α × β) : (iSup f).snd = congr_arg sSup (range_comp _ _).symm theorem swap_iSup [SupSet α] [SupSet β] (f : ι → α × β) : (iSup f).swap = ⨆ i, (f i).swap := by - simp_rw [iSup, swap_sSup, ← range_comp, Function.comp] -- Porting note: need to unfold `∘` + simp_rw [iSup, swap_sSup, ← range_comp, comp_def] -- Porting note: need to unfold `∘` theorem iSup_mk [SupSet α] [SupSet β] (f : ι → α) (g : ι → β) : ⨆ i, (f i, g i) = (⨆ i, f i, ⨆ i, g i) := @@ -1719,3 +1744,5 @@ instance instCompleteLinearOrder : CompleteLinearOrder PUnit where top_sdiff := by intros; trivial end PUnit + +set_option linter.style.longFile 1900 diff --git a/Mathlib/Order/CompleteLatticeIntervals.lean b/Mathlib/Order/CompleteLatticeIntervals.lean index 44fa32da464fc..149df0ed5225d 100644 --- a/Mathlib/Order/CompleteLatticeIntervals.lean +++ b/Mathlib/Order/CompleteLatticeIntervals.lean @@ -52,7 +52,7 @@ theorem subset_sSup_def [Inhabited s] : rfl theorem subset_sSup_of_within [Inhabited s] {t : Set s} - (h' : t.Nonempty) (h'' : BddAbove t) (h : sSup ((↑) '' t : Set α) ∈ s) : + (h' : t.Nonempty) (h'' : BddAbove t) (h : sSup ((↑) '' t : Set α) ∈ s) : sSup ((↑) '' t : Set α) = (@sSup s _ t : α) := by simp [dif_pos, h, h', h''] theorem subset_sSup_emptyset [Inhabited s] : diff --git a/Mathlib/Order/CompleteSublattice.lean b/Mathlib/Order/CompleteSublattice.lean index 908ecea1281e8..cabb0e732606e 100644 --- a/Mathlib/Order/CompleteSublattice.lean +++ b/Mathlib/Order/CompleteSublattice.lean @@ -66,10 +66,10 @@ instance instTop : Top L where top := ⟨⊤, by simpa using L.sInfClosed' <| empty_subset _⟩ instance instSupSet : SupSet L where - sSup s := ⟨sSup s, L.sSupClosed' image_val_subset⟩ + sSup s := ⟨sSup <| (↑) '' s, L.sSupClosed' image_val_subset⟩ instance instInfSet : InfSet L where - sInf s := ⟨sInf s, L.sInfClosed' image_val_subset⟩ + sInf s := ⟨sInf <| (↑) '' s, L.sInfClosed' image_val_subset⟩ theorem sSupClosed {s : Set α} (h : s ⊆ L) : sSup s ∈ L := L.sSupClosed' h @@ -89,6 +89,10 @@ theorem coe_sSup' (S : Set L) : (↑(sSup S) : α) = ⨆ N ∈ S, (N : α) := by theorem coe_sInf' (S : Set L) : (↑(sInf S) : α) = ⨅ N ∈ S, (N : α) := by rw [coe_sInf, ← Set.image, sInf_image] +-- Redeclaring to get proper keys for these instances +instance : Sup {x // x ∈ L} := Sublattice.instSupCoe +instance : Inf {x // x ∈ L} := Sublattice.instInfCoe + instance instCompleteLattice : CompleteLattice L := Subtype.coe_injective.completeLattice _ Sublattice.coe_sup Sublattice.coe_inf coe_sSup' coe_sInf' coe_top coe_bot diff --git a/Mathlib/Order/ConditionallyCompleteLattice/Basic.lean b/Mathlib/Order/ConditionallyCompleteLattice/Basic.lean index 783720c3aa7e9..b65457aeeec04 100644 --- a/Mathlib/Order/ConditionallyCompleteLattice/Basic.lean +++ b/Mathlib/Order/ConditionallyCompleteLattice/Basic.lean @@ -155,7 +155,7 @@ every nonempty subset which is bounded below has an infimum. Typical examples are real numbers or natural numbers. To differentiate the statements from the corresponding statements in (unconditional) -complete lattices, we prefix sInf and subₛ by a c everywhere. The same statements should +complete lattices, we prefix `sInf` and `sSup` by a `c` everywhere. The same statements should hold in both worlds, sometimes with additional assumptions of nonemptiness or boundedness. -/ class ConditionallyCompleteLattice (α : Type*) extends Lattice α, SupSet α, InfSet α where @@ -175,7 +175,7 @@ every nonempty subset which is bounded below has an infimum. Typical examples are real numbers or natural numbers. To differentiate the statements from the corresponding statements in (unconditional) -complete linear orders, we prefix sInf and sSup by a c everywhere. The same statements should +complete linear orders, we prefix `sInf` and `sSup` by a `c` everywhere. The same statements should hold in both worlds, sometimes with additional assumptions of nonemptiness or boundedness. -/ class ConditionallyCompleteLinearOrder (α : Type*) extends ConditionallyCompleteLattice α where @@ -215,7 +215,7 @@ every nonempty subset which is bounded above has a supremum, and every nonempty bounded below) has an infimum. A typical example is the natural numbers. To differentiate the statements from the corresponding statements in (unconditional) -complete linear orders, we prefix `sInf` and `sSup` by a c everywhere. The same statements should +complete linear orders, we prefix `sInf` and `sSup` by a `c` everywhere. The same statements should hold in both worlds, sometimes with additional assumptions of nonemptiness or boundedness. -/ class ConditionallyCompleteLinearOrderBot (α : Type*) extends ConditionallyCompleteLinearOrder α, @@ -251,8 +251,8 @@ instance (priority := 100) CompleteLinearOrder.toConditionallyCompleteLinearOrde open scoped Classical in /-- A well founded linear order is conditionally complete, with a bottom element. -/ -noncomputable abbrev IsWellOrder.conditionallyCompleteLinearOrderBot (α : Type*) - [i₁ : _root_.LinearOrder α] [i₂ : OrderBot α] [h : IsWellOrder α (· < ·)] : +noncomputable abbrev WellFoundedLT.conditionallyCompleteLinearOrderBot (α : Type*) + [i₁ : LinearOrder α] [i₂ : OrderBot α] [h : WellFoundedLT α] : ConditionallyCompleteLinearOrderBot α := { i₁, i₂, LinearOrder.toLattice with sInf := fun s => if hs : s.Nonempty then h.wf.min s hs else ⊥ @@ -591,12 +591,12 @@ theorem exists_between_of_forall_le (sne : s.Nonempty) (tne : t.Nonempty) (hst : ∀ x ∈ s, ∀ y ∈ t, x ≤ y) : (upperBounds s ∩ lowerBounds t).Nonempty := ⟨sInf t, fun x hx => le_csInf tne <| hst x hx, fun _ hy => csInf_le (sne.mono hst) hy⟩ -/-- The supremum of a singleton is the element of the singleton-/ +/-- The supremum of a singleton is the element of the singleton -/ @[simp] theorem csSup_singleton (a : α) : sSup {a} = a := isGreatest_singleton.csSup_eq -/-- The infimum of a singleton is the element of the singleton-/ +/-- The infimum of a singleton is the element of the singleton -/ @[simp] theorem csInf_singleton (a : α) : sInf {a} = a := isLeast_singleton.csInf_eq @@ -698,18 +698,18 @@ theorem csSup_Ioc (h : a < b) : sSup (Ioc a b) = b := theorem csSup_Ioo [DenselyOrdered α] (h : a < b) : sSup (Ioo a b) = b := (isLUB_Ioo h).csSup_eq (nonempty_Ioo.2 h) -/-- The indexed supremum of a function is bounded above by a uniform bound-/ +/-- The indexed supremum of a function is bounded above by a uniform bound -/ theorem ciSup_le [Nonempty ι] {f : ι → α} {c : α} (H : ∀ x, f x ≤ c) : iSup f ≤ c := csSup_le (range_nonempty f) (by rwa [forall_mem_range]) -/-- The indexed supremum of a function is bounded below by the value taken at one point-/ +/-- The indexed supremum of a function is bounded below by the value taken at one point -/ theorem le_ciSup {f : ι → α} (H : BddAbove (range f)) (c : ι) : f c ≤ iSup f := le_csSup H (mem_range_self _) theorem le_ciSup_of_le {f : ι → α} (H : BddAbove (range f)) (c : ι) (h : a ≤ f c) : a ≤ iSup f := le_trans h (le_ciSup H c) -/-- The indexed supremum of two functions are comparable if the functions are pointwise comparable-/ +/-- The indexed suprema of two functions are comparable if the functions are pointwise comparable -/ theorem ciSup_mono {f g : ι → α} (B : BddAbove (range g)) (H : ∀ x, f x ≤ g x) : iSup f ≤ iSup g := by cases isEmpty_or_nonempty ι @@ -720,15 +720,15 @@ theorem le_ciSup_set {f : β → α} {s : Set β} (H : BddAbove (f '' s)) {c : f c ≤ ⨆ i : s, f i := (le_csSup H <| mem_image_of_mem f hc).trans_eq sSup_image' -/-- The indexed infimum of two functions are comparable if the functions are pointwise comparable-/ +/-- The indexed infimum of two functions are comparable if the functions are pointwise comparable -/ theorem ciInf_mono {f g : ι → α} (B : BddBelow (range f)) (H : ∀ x, f x ≤ g x) : iInf f ≤ iInf g := ciSup_mono (α := αᵒᵈ) B H -/-- The indexed minimum of a function is bounded below by a uniform lower bound-/ +/-- The indexed minimum of a function is bounded below by a uniform lower bound -/ theorem le_ciInf [Nonempty ι] {f : ι → α} {c : α} (H : ∀ x, c ≤ f x) : c ≤ iInf f := ciSup_le (α := αᵒᵈ) H -/-- The indexed infimum of a function is bounded above by the value taken at one point-/ +/-- The indexed infimum of a function is bounded above by the value taken at one point -/ theorem ciInf_le {f : ι → α} (H : BddBelow (range f)) (c : ι) : iInf f ≤ f c := le_ciSup (α := αᵒᵈ) H c @@ -1106,7 +1106,7 @@ theorem cbiInf_eq_of_not_forall {p : ι → Prop} {f : Subtype p → α} (hp : open Function -variable [IsWellOrder α (· < ·)] +variable [WellFoundedLT α] theorem sInf_eq_argmin_on (hs : s.Nonempty) : sInf s = argminOn id wellFounded_lt s hs := IsLeast.csInf_eq ⟨argminOn_mem _ _ _ _, fun _ ha => argminOn_le id _ _ ha⟩ @@ -1639,3 +1639,5 @@ lemma iInf_coe_lt_top : ⨅ i, (f i : WithTop α) < ⊤ ↔ Nonempty ι := by end WithTop end WithTopBot + +set_option linter.style.longFile 1700 diff --git a/Mathlib/Order/ConditionallyCompleteLattice/Finset.lean b/Mathlib/Order/ConditionallyCompleteLattice/Finset.lean index 18c36b633f629..c493a2324fc8c 100644 --- a/Mathlib/Order/ConditionallyCompleteLattice/Finset.lean +++ b/Mathlib/Order/ConditionallyCompleteLattice/Finset.lean @@ -46,12 +46,143 @@ theorem Set.Finite.csSup_lt_iff (hs : s.Finite) (h : s.Nonempty) : sSup s < a theorem Set.Finite.lt_csInf_iff (hs : s.Finite) (h : s.Nonempty) : a < sInf s ↔ ∀ x ∈ s, a < x := @Set.Finite.csSup_lt_iff αᵒᵈ _ _ _ hs h +variable (f : ι → α) + +theorem Finset.ciSup_eq_max'_image {s : Finset ι} (h : ∃ x ∈ s, sSup ∅ ≤ f x) + (h' : (s.image f).Nonempty := by classical exact image_nonempty.mpr (h.imp fun _ ↦ And.left)) : + ⨆ i ∈ s, f i = (s.image f).max' h' := by + classical + rw [iSup, ← h'.csSup_eq_max', coe_image] + refine csSup_eq_csSup_of_forall_exists_le ?_ ?_ + · simp only [ciSup_eq_ite, dite_eq_ite, Set.mem_range, Set.mem_image, mem_coe, + exists_exists_and_eq_and, forall_exists_index, forall_apply_eq_imp_iff] + intro i + split_ifs + · exact ⟨_, by assumption, le_rfl⟩ + · obtain ⟨a, ha, ha'⟩ := h + exact ⟨a, ha, ha'⟩ + · simp only [Set.mem_image, mem_coe, ciSup_eq_ite, dite_eq_ite, Set.mem_range, + exists_exists_eq_and, forall_exists_index, and_imp, forall_apply_eq_imp_iff₂] + intro i hi + refine ⟨i, ?_⟩ + simp [hi] + +theorem Finset.ciInf_eq_min'_image {s : Finset ι} (h : ∃ x ∈ s, f x ≤ sInf ∅) + (h' : (s.image f).Nonempty := by classical exact image_nonempty.mpr (h.imp fun _ ↦ And.left)) : + ⨅ i ∈ s, f i = (s.image f).min' h' := by + classical + rw [← OrderDual.toDual_inj, toDual_min', toDual_iInf] + simp only [Function.comp_apply, toDual_iInf] + rw [ciSup_eq_max'_image _ h] + simp only [image_image] + congr + +theorem Finset.ciSup_mem_image {s : Finset ι} (h : ∃ x ∈ s, sSup ∅ ≤ f x) : + ⨆ i ∈ s, f i ∈ s.image f := by + rw [ciSup_eq_max'_image _ h] + exact max'_mem (image f s) _ + +theorem Finset.ciInf_mem_image {s : Finset ι} (h : ∃ x ∈ s, f x ≤ sInf ∅) : + ⨅ i ∈ s, f i ∈ s.image f := by + rw [ciInf_eq_min'_image _ h] + exact min'_mem (image f s) _ + +theorem Set.Finite.ciSup_mem_image {s : Set ι} (hs : s.Finite) (h : ∃ x ∈ s, sSup ∅ ≤ f x) : + ⨆ i ∈ s, f i ∈ f '' s := by + lift s to Finset ι using hs + simp only [Finset.mem_coe] at h + simpa using Finset.ciSup_mem_image f h + +theorem Set.Finite.ciInf_mem_image {s : Set ι} (hs : s.Finite) (h : ∃ x ∈ s, f x ≤ sInf ∅) : + ⨅ i ∈ s, f i ∈ f '' s := by + lift s to Finset ι using hs + simp only [Finset.mem_coe] at h + simpa using Finset.ciInf_mem_image f h + +theorem Set.Finite.ciSup_lt_iff {s : Set ι} {f : ι → α} (hs : s.Finite) + (h : ∃ x ∈ s, sSup ∅ ≤ f x) : + ⨆ i ∈ s, f i < a ↔ ∀ x ∈ s, f x < a := by + constructor + · intro h x hx + refine h.trans_le' (le_csSup ?_ ?_) + · classical + refine (((hs.image f).union (finite_singleton (sSup ∅))).subset ?_).bddAbove + intro + simp only [ciSup_eq_ite, dite_eq_ite, mem_range, union_singleton, mem_insert_iff, mem_image, + forall_exists_index] + intro x hx + split_ifs at hx + · exact Or.inr ⟨_, by assumption, hx⟩ + · simp_all + · simp only [mem_range] + refine ⟨x, ?_⟩ + simp [hx] + · intro H + have := hs.ciSup_mem_image _ h + simp only [mem_image] at this + obtain ⟨_, hmem, hx⟩ := this + rw [← hx] + exact H _ hmem + +theorem Set.Finite.lt_ciInf_iff {s : Set ι} {f : ι → α} (hs : s.Finite) + (h : ∃ x ∈ s, f x ≤ sInf ∅) : + a < ⨅ i ∈ s, f i ↔ ∀ x ∈ s, a < f x := by + constructor + · intro h x hx + refine h.trans_le (csInf_le ?_ ?_) + · classical + refine (((hs.image f).union (finite_singleton (sInf ∅))).subset ?_).bddBelow + intro + simp only [ciInf_eq_ite, dite_eq_ite, mem_range, union_singleton, mem_insert_iff, mem_image, + forall_exists_index] + intro x hx + split_ifs at hx + · exact Or.inr ⟨_, by assumption, hx⟩ + · simp_all + · simp only [mem_range] + refine ⟨x, ?_⟩ + simp [hx] + · intro H + have := hs.ciInf_mem_image _ h + simp only [mem_image] at this + obtain ⟨_, hmem, hx⟩ := this + rw [← hx] + exact H _ hmem + +section ListMultiset + +lemma List.iSup_mem_map_of_exists_sSup_empty_le {l : List ι} (f : ι → α) + (h : ∃ x ∈ l, sSup ∅ ≤ f x) : + ⨆ x ∈ l, f x ∈ l.map f := by + classical + simpa using l.toFinset.ciSup_mem_image f (by simpa using h) + +lemma List.iInf_mem_map_of_exists_le_sInf_empty {l : List ι} (f : ι → α) + (h : ∃ x ∈ l, f x ≤ sInf ∅) : + ⨅ x ∈ l, f x ∈ l.map f := by + classical + simpa using l.toFinset.ciInf_mem_image f (by simpa using h) + +lemma Multiset.iSup_mem_map_of_exists_sSup_empty_le {s : Multiset ι} (f : ι → α) + (h : ∃ x ∈ s, sSup ∅ ≤ f x) : + ⨆ x ∈ s, f x ∈ s.map f := by + classical + simpa using s.toFinset.ciSup_mem_image f (by simpa using h) + +lemma Multiset.iInf_mem_map_of_exists_le_sInf_empty {s : Multiset ι} (f : ι → α) + (h : ∃ x ∈ s, f x ≤ sInf ∅) : + ⨅ x ∈ s, f x ∈ s.map f := by + classical + simpa using s.toFinset.ciInf_mem_image f (by simpa using h) + theorem exists_eq_ciSup_of_finite [Nonempty ι] [Finite ι] {f : ι → α} : ∃ i, f i = ⨆ i, f i := Nonempty.csSup_mem (range_nonempty f) (finite_range f) theorem exists_eq_ciInf_of_finite [Nonempty ι] [Finite ι] {f : ι → α} : ∃ i, f i = ⨅ i, f i := Nonempty.csInf_mem (range_nonempty f) (finite_range f) +end ListMultiset + end ConditionallyCompleteLinearOrder /-! @@ -102,3 +233,38 @@ lemma sup_univ_eq_ciSup [Fintype ι] (f : ι → α) : univ.sup f = ⨆ i, f i : end ConditionallyCompleteLinearOrderBot end Finset + +section ConditionallyCompleteLinearOrderBot + +variable [ConditionallyCompleteLinearOrderBot α] (f : ι → α) + +theorem Finset.Nonempty.ciSup_eq_max'_image {s : Finset ι} (h : s.Nonempty) + (h' : (s.image f).Nonempty := h.image f) : + ⨆ i ∈ s, f i = (s.image f).max' h' := + s.ciSup_eq_max'_image _ (h.imp (by simp)) _ + +theorem Finset.Nonempty.ciSup_mem_image {s : Finset ι} (h : s.Nonempty) : + ⨆ i ∈ s, f i ∈ s.image f := + s.ciSup_mem_image _ (h.imp (by simp)) + +theorem Set.Nonempty.ciSup_mem_image {s : Set ι} (h : s.Nonempty) (hs : s.Finite) : + ⨆ i ∈ s, f i ∈ f '' s := + hs.ciSup_mem_image _ (h.imp (by simp)) + +theorem Set.Nonempty.ciSup_lt_iff {s : Set ι} {a : α} {f : ι → α} (h : s.Nonempty) (hs : s.Finite) : + ⨆ i ∈ s, f i < a ↔ ∀ x ∈ s, f x < a := + hs.ciSup_lt_iff (h.imp (by simp)) + +section ListMultiset + +lemma List.iSup_mem_map_of_ne_nil {l : List ι} (f : ι → α) (h : l ≠ []) : + ⨆ x ∈ l, f x ∈ l.map f := + l.iSup_mem_map_of_exists_sSup_empty_le _ (by simpa using exists_mem_of_ne_nil _ h) + +lemma Multiset.iSup_mem_map_of_ne_zero {s : Multiset ι} (f : ι → α) (h : s ≠ 0) : + ⨆ x ∈ s, f x ∈ s.map f := + s.iSup_mem_map_of_exists_sSup_empty_le _ (by simpa using exists_mem_of_ne_zero h) + +end ListMultiset + +end ConditionallyCompleteLinearOrderBot diff --git a/Mathlib/Order/Cover.lean b/Mathlib/Order/Cover.lean index 28127f44875d2..945aa4514d439 100644 --- a/Mathlib/Order/Cover.lean +++ b/Mathlib/Order/Cover.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies, Violeta Hernández Palacios, Grayson Burton, Floris van Doorn -/ import Mathlib.Order.Interval.Set.OrdConnected +import Mathlib.Order.Interval.Set.WithBotTop import Mathlib.Order.Antisymmetrization /-! @@ -126,6 +127,19 @@ alias ⟨_, WCovBy.toDual⟩ := toDual_wcovBy_toDual_iff alias ⟨_, WCovBy.ofDual⟩ := ofDual_wcovBy_ofDual_iff +theorem OrderEmbedding.wcovBy_of_apply {α β : Type*} [Preorder α] [Preorder β] + (f : α ↪o β) {x y : α} (h : f x ⩿ f y) : x ⩿ y := by + use f.le_iff_le.1 h.1 + intro a + rw [← f.lt_iff_lt, ← f.lt_iff_lt] + apply h.2 + +theorem OrderIso.map_wcovBy {α β : Type*} [Preorder α] [Preorder β] + (f : α ≃o β) {x y : α} : f x ⩿ f y ↔ x ⩿ y := by + use f.toOrderEmbedding.wcovBy_of_apply + conv_lhs => rw [← f.symm_apply_apply x, ← f.symm_apply_apply y] + exact f.symm.toOrderEmbedding.wcovBy_of_apply + end Preorder section PartialOrder @@ -312,6 +326,19 @@ theorem apply_covBy_apply_iff {E : Type*} [EquivLike E α β] [OrderIsoClass E theorem covBy_of_eq_or_eq (hab : a < b) (h : ∀ c, a ≤ c → c ≤ b → c = a ∨ c = b) : a ⋖ b := ⟨hab, fun c ha hb => (h c ha.le hb.le).elim ha.ne' hb.ne⟩ +theorem OrderEmbedding.covBy_of_apply {α β : Type*} [Preorder α] [Preorder β] + (f : α ↪o β) {x y : α} (h : f x ⋖ f y) : x ⋖ y := by + use f.lt_iff_lt.1 h.1 + intro a + rw [← f.lt_iff_lt, ← f.lt_iff_lt] + apply h.2 + +theorem OrderIso.map_covBy {α β : Type*} [Preorder α] [Preorder β] + (f : α ≃o β) {x y : α} : f x ⋖ f y ↔ x ⋖ y := by + use f.toOrderEmbedding.covBy_of_apply + conv_lhs => rw [← f.symm_apply_apply x, ← f.symm_apply_apply y] + exact f.symm.toOrderEmbedding.covBy_of_apply + end Preorder section PartialOrder @@ -522,3 +549,45 @@ theorem covBy_iff : x ⋖ y ↔ x.1 ⋖ y.1 ∧ x.2 = y.2 ∨ x.2 ⋖ y.2 ∧ x. exact mk_covBy_mk_iff end Prod + +namespace WithTop + +variable [Preorder α] {a b : α} + +@[simp, norm_cast] lemma coe_wcovBy_coe : (a : WithTop α) ⩿ b ↔ a ⩿ b := + Set.OrdConnected.apply_wcovBy_apply_iff OrderEmbedding.withTopCoe <| by + simp [WithTop.range_coe, ordConnected_Iio] + +@[simp, norm_cast] lemma coe_covBy_coe : (a : WithTop α) ⋖ b ↔ a ⋖ b := + Set.OrdConnected.apply_covBy_apply_iff OrderEmbedding.withTopCoe <| by + simp [WithTop.range_coe, ordConnected_Iio] + +@[simp] lemma coe_covBy_top : (a : WithTop α) ⋖ ⊤ ↔ IsMax a := by + simp only [covBy_iff_Ioo_eq, ← image_coe_Ioi, coe_lt_top, image_eq_empty, + true_and, Ioi_eq_empty_iff] + +@[simp] lemma coe_wcovBy_top : (a : WithTop α) ⩿ ⊤ ↔ IsMax a := by + simp only [wcovBy_iff_Ioo_eq, ← image_coe_Ioi, le_top, image_eq_empty, true_and, Ioi_eq_empty_iff] + +end WithTop + +namespace WithBot + +variable [Preorder α] {a b : α} + +@[simp, norm_cast] lemma coe_wcovBy_coe : (a : WithBot α) ⩿ b ↔ a ⩿ b := + Set.OrdConnected.apply_wcovBy_apply_iff OrderEmbedding.withBotCoe <| by + simp [WithBot.range_coe, ordConnected_Ioi] + +@[simp, norm_cast] lemma coe_covBy_coe : (a : WithBot α) ⋖ b ↔ a ⋖ b := + Set.OrdConnected.apply_covBy_apply_iff OrderEmbedding.withBotCoe <| by + simp [WithBot.range_coe, ordConnected_Ioi] + +@[simp] lemma bot_covBy_coe : ⊥ ⋖ (a : WithBot α) ↔ IsMin a := by + simp only [covBy_iff_Ioo_eq, ← image_coe_Iio, bot_lt_coe, image_eq_empty, + true_and, Iio_eq_empty_iff] + +@[simp] lemma bot_wcovBy_coe : ⊥ ⩿ (a : WithBot α) ↔ IsMin a := by + simp only [wcovBy_iff_Ioo_eq, ← image_coe_Iio, bot_le, image_eq_empty, true_and, Iio_eq_empty_iff] + +end WithBot diff --git a/Mathlib/Order/Defs.lean b/Mathlib/Order/Defs.lean index ebc2f957c77e3..9a0471732ac3c 100644 --- a/Mathlib/Order/Defs.lean +++ b/Mathlib/Order/Defs.lean @@ -3,11 +3,10 @@ Copyright (c) 2016 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Leonardo de Moura -/ -import Mathlib.Init.Algebra.Classes +import Batteries.Classes.Order +import Mathlib.Init.Logic import Mathlib.Data.Ordering.Basic import Mathlib.Tactic.SplitIfs -import Mathlib.Tactic.TypeStar -import Batteries.Classes.Order /-! # Orders @@ -16,9 +15,131 @@ Defines classes for preorders, partial orders, and linear orders and proves some basic lemmas about them. -/ +/-! ### Unbundled classes -/ + universe u variable {α : Type u} +/-- `IsIrrefl X r` means the binary relation `r` on `X` is irreflexive (that is, `r x x` never +holds). -/ +class IsIrrefl (α : Sort*) (r : α → α → Prop) : Prop where + irrefl : ∀ a, ¬r a a + +/-- `IsRefl X r` means the binary relation `r` on `X` is reflexive. -/ +class IsRefl (α : Sort*) (r : α → α → Prop) : Prop where + refl : ∀ a, r a a + +/-- `IsSymm X r` means the binary relation `r` on `X` is symmetric. -/ +class IsSymm (α : Sort*) (r : α → α → Prop) : Prop where + symm : ∀ a b, r a b → r b a + +/-- `IsAsymm X r` means that the binary relation `r` on `X` is asymmetric, that is, +`r a b → ¬ r b a`. -/ +class IsAsymm (α : Sort*) (r : α → α → Prop) : Prop where + asymm : ∀ a b, r a b → ¬r b a + +/-- `IsAntisymm X r` means the binary relation `r` on `X` is antisymmetric. -/ +class IsAntisymm (α : Sort*) (r : α → α → Prop) : Prop where + antisymm : ∀ a b, r a b → r b a → a = b + +instance (priority := 100) IsAsymm.toIsAntisymm {α : Sort*} (r : α → α → Prop) [IsAsymm α r] : + IsAntisymm α r where + antisymm _ _ hx hy := (IsAsymm.asymm _ _ hx hy).elim + +/-- `IsTrans X r` means the binary relation `r` on `X` is transitive. -/ +class IsTrans (α : Sort*) (r : α → α → Prop) : Prop where + trans : ∀ a b c, r a b → r b c → r a c + +instance {α : Sort*} {r : α → α → Prop} [IsTrans α r] : Trans r r r := + ⟨IsTrans.trans _ _ _⟩ + +instance (priority := 100) {α : Sort*} {r : α → α → Prop} [Trans r r r] : IsTrans α r := + ⟨fun _ _ _ => Trans.trans⟩ + +/-- `IsTotal X r` means that the binary relation `r` on `X` is total, that is, that for any +`x y : X` we have `r x y` or `r y x`. -/ +class IsTotal (α : Sort*) (r : α → α → Prop) : Prop where + total : ∀ a b, r a b ∨ r b a + +/-- `IsPreorder X r` means that the binary relation `r` on `X` is a pre-order, that is, reflexive +and transitive. -/ +class IsPreorder (α : Sort*) (r : α → α → Prop) extends IsRefl α r, IsTrans α r : Prop + +/-- `IsPartialOrder X r` means that the binary relation `r` on `X` is a partial order, that is, +`IsPreorder X r` and `IsAntisymm X r`. -/ +class IsPartialOrder (α : Sort*) (r : α → α → Prop) extends IsPreorder α r, IsAntisymm α r : Prop + +/-- `IsLinearOrder X r` means that the binary relation `r` on `X` is a linear order, that is, +`IsPartialOrder X r` and `IsTotal X r`. -/ +class IsLinearOrder (α : Sort u) (r : α → α → Prop) extends IsPartialOrder α r, IsTotal α r : Prop + +/-- `IsEquiv X r` means that the binary relation `r` on `X` is an equivalence relation, that +is, `IsPreorder X r` and `IsSymm X r`. -/ +class IsEquiv (α : Sort*) (r : α → α → Prop) extends IsPreorder α r, IsSymm α r : Prop + +/-- `IsStrictOrder X r` means that the binary relation `r` on `X` is a strict order, that is, +`IsIrrefl X r` and `IsTrans X r`. -/ +class IsStrictOrder (α : Sort*) (r : α → α → Prop) extends IsIrrefl α r, IsTrans α r : Prop + +/-- `IsStrictWeakOrder X lt` means that the binary relation `lt` on `X` is a strict weak order, +that is, `IsStrictOrder X lt` and `¬lt a b ∧ ¬lt b a → ¬lt b c ∧ ¬lt c b → ¬lt a c ∧ ¬lt c a`. -/ +class IsStrictWeakOrder (α : Sort u) (lt : α → α → Prop) extends IsStrictOrder α lt : Prop where + incomp_trans : ∀ a b c, ¬lt a b ∧ ¬lt b a → ¬lt b c ∧ ¬lt c b → ¬lt a c ∧ ¬lt c a + +/-- `IsTrichotomous X lt` means that the binary relation `lt` on `X` is trichotomous, that is, +either `lt a b` or `a = b` or `lt b a` for any `a` and `b`. -/ +class IsTrichotomous (α : Sort*) (lt : α → α → Prop) : Prop where + trichotomous : ∀ a b, lt a b ∨ a = b ∨ lt b a + +/-- `IsStrictTotalOrder X lt` means that the binary relation `lt` on `X` is a strict total order, +that is, `IsTrichotomous X lt` and `IsStrictOrder X lt`. -/ +class IsStrictTotalOrder (α : Sort*) (lt : α → α → Prop) extends IsTrichotomous α lt, + IsStrictOrder α lt : Prop + +/-- Equality is an equivalence relation. -/ +instance eq_isEquiv (α : Sort*) : IsEquiv α (· = ·) where + symm := @Eq.symm _ + trans := @Eq.trans _ + refl := Eq.refl + +section + +variable {α : Sort*} {r : α → α → Prop} {a b c : α} + +local infixl:50 " ≺ " => r + +lemma irrefl [IsIrrefl α r] (a : α) : ¬a ≺ a := IsIrrefl.irrefl a +lemma refl [IsRefl α r] (a : α) : a ≺ a := IsRefl.refl a +lemma trans [IsTrans α r] : a ≺ b → b ≺ c → a ≺ c := IsTrans.trans _ _ _ +lemma symm [IsSymm α r] : a ≺ b → b ≺ a := IsSymm.symm _ _ +lemma antisymm [IsAntisymm α r] : a ≺ b → b ≺ a → a = b := IsAntisymm.antisymm _ _ +lemma asymm [IsAsymm α r] : a ≺ b → ¬b ≺ a := IsAsymm.asymm _ _ + +lemma trichotomous [IsTrichotomous α r] : ∀ a b : α, a ≺ b ∨ a = b ∨ b ≺ a := + IsTrichotomous.trichotomous + +instance (priority := 90) isAsymm_of_isTrans_of_isIrrefl [IsTrans α r] [IsIrrefl α r] : + IsAsymm α r := + ⟨fun a _b h₁ h₂ => absurd (_root_.trans h₁ h₂) (irrefl a)⟩ + +variable (r) + +@[elab_without_expected_type] lemma irrefl_of [IsIrrefl α r] (a : α) : ¬a ≺ a := irrefl a +@[elab_without_expected_type] lemma refl_of [IsRefl α r] (a : α) : a ≺ a := refl a +@[elab_without_expected_type] lemma trans_of [IsTrans α r] : a ≺ b → b ≺ c → a ≺ c := _root_.trans +@[elab_without_expected_type] lemma symm_of [IsSymm α r] : a ≺ b → b ≺ a := symm +@[elab_without_expected_type] lemma asymm_of [IsAsymm α r] : a ≺ b → ¬b ≺ a := asymm + +@[elab_without_expected_type] +lemma total_of [IsTotal α r] (a b : α) : a ≺ b ∨ b ≺ a := IsTotal.total _ _ + +@[elab_without_expected_type] +lemma trichotomous_of [IsTrichotomous α r] : ∀ a b : α, a ≺ b ∨ a = b ∨ b ≺ a := trichotomous + +end + +/-! ### Bundled classes -/ + section Preorder /-! @@ -32,84 +153,62 @@ class Preorder (α : Type u) extends LE α, LT α where lt := fun a b => a ≤ b ∧ ¬b ≤ a lt_iff_le_not_le : ∀ a b : α, a < b ↔ a ≤ b ∧ ¬b ≤ a := by intros; rfl -variable [Preorder α] +variable [Preorder α] {a b c : α} /-- The relation `≤` on a preorder is reflexive. -/ -@[refl] -theorem le_refl : ∀ a : α, a ≤ a := - Preorder.le_refl +@[refl] lemma le_refl : ∀ a : α, a ≤ a := Preorder.le_refl /-- A version of `le_refl` where the argument is implicit -/ -theorem le_rfl {a : α} : a ≤ a := - le_refl a +lemma le_rfl : a ≤ a := le_refl a /-- The relation `≤` on a preorder is transitive. -/ -@[trans] -theorem le_trans : ∀ {a b c : α}, a ≤ b → b ≤ c → a ≤ c := - Preorder.le_trans _ _ _ +@[trans] lemma le_trans : a ≤ b → b ≤ c → a ≤ c := Preorder.le_trans _ _ _ -theorem lt_iff_le_not_le : ∀ {a b : α}, a < b ↔ a ≤ b ∧ ¬b ≤ a := - Preorder.lt_iff_le_not_le _ _ +lemma lt_iff_le_not_le : a < b ↔ a ≤ b ∧ ¬b ≤ a := Preorder.lt_iff_le_not_le _ _ -theorem lt_of_le_not_le : ∀ {a b : α}, a ≤ b → ¬b ≤ a → a < b - | _a, _b, hab, hba => lt_iff_le_not_le.mpr ⟨hab, hba⟩ +lemma lt_of_le_not_le (hab : a ≤ b) (hba : ¬ b ≤ a) : a < b := lt_iff_le_not_le.2 ⟨hab, hba⟩ +@[deprecated (since := "2024-07-30")] theorem le_not_le_of_lt : ∀ {a b : α}, a < b → a ≤ b ∧ ¬b ≤ a | _a, _b, hab => lt_iff_le_not_le.mp hab -theorem le_of_eq {a b : α} : a = b → a ≤ b := fun h => h ▸ le_refl a - -@[trans] -theorem ge_trans : ∀ {a b c : α}, a ≥ b → b ≥ c → a ≥ c := fun h₁ h₂ => le_trans h₂ h₁ - -theorem lt_irrefl : ∀ a : α, ¬a < a - | _a, haa => - match le_not_le_of_lt haa with - | ⟨h1, h2⟩ => h2 h1 - -theorem gt_irrefl : ∀ a : α, ¬a > a := - lt_irrefl +lemma le_of_eq (hab : a = b) : a ≤ b := by rw [hab] +lemma le_of_lt (hab : a < b) : a ≤ b := (lt_iff_le_not_le.1 hab).1 +lemma not_le_of_lt (hab : a < b) : ¬ b ≤ a := (lt_iff_le_not_le.1 hab).2 +lemma not_le_of_gt (hab : a > b) : ¬a ≤ b := not_le_of_lt hab +lemma not_lt_of_le (hab : a ≤ b) : ¬ b < a := imp_not_comm.1 not_le_of_lt hab +lemma not_lt_of_ge (hab : a ≥ b) : ¬a < b := not_lt_of_le hab -@[trans] -theorem lt_trans : ∀ {a b c : α}, a < b → b < c → a < c - | _a, _b, _c, hab, hbc => - match le_not_le_of_lt hab, le_not_le_of_lt hbc with - | ⟨hab, _hba⟩, ⟨hbc, hcb⟩ => - lt_of_le_not_le (le_trans hab hbc) fun hca => hcb (le_trans hca hab) +alias LT.lt.not_le := not_le_of_lt +alias LE.le.not_lt := not_lt_of_le -@[trans] -theorem gt_trans : ∀ {a b c : α}, a > b → b > c → a > c := fun h₁ h₂ => lt_trans h₂ h₁ +@[trans] lemma ge_trans : a ≥ b → b ≥ c → a ≥ c := fun h₁ h₂ => le_trans h₂ h₁ -theorem ne_of_lt {a b : α} (h : a < b) : a ≠ b := fun he => absurd h (he ▸ lt_irrefl a) +lemma lt_irrefl (a : α) : ¬a < a := fun h ↦ not_le_of_lt h le_rfl +lemma gt_irrefl (a : α) : ¬a > a := lt_irrefl _ -theorem ne_of_gt {a b : α} (h : b < a) : a ≠ b := fun he => absurd h (he ▸ lt_irrefl a) +@[trans] lemma lt_of_lt_of_le (hab : a < b) (hbc : b ≤ c) : a < c := + lt_of_le_not_le (le_trans (le_of_lt hab) hbc) fun hca ↦ not_le_of_lt hab (le_trans hbc hca) -theorem lt_asymm {a b : α} (h : a < b) : ¬b < a := fun h1 : b < a => lt_irrefl a (lt_trans h h1) +@[trans] lemma lt_of_le_of_lt (hab : a ≤ b) (hbc : b < c) : a < c := + lt_of_le_not_le (le_trans hab (le_of_lt hbc)) fun hca ↦ not_le_of_lt hbc (le_trans hca hab) -theorem le_of_lt : ∀ {a b : α}, a < b → a ≤ b - | _a, _b, hab => (le_not_le_of_lt hab).left +@[trans] lemma gt_of_gt_of_ge (h₁ : a > b) (h₂ : b ≥ c) : a > c := lt_of_le_of_lt h₂ h₁ +@[trans] lemma gt_of_ge_of_gt (h₁ : a ≥ b) (h₂ : b > c) : a > c := lt_of_lt_of_le h₂ h₁ -@[trans] -theorem lt_of_lt_of_le : ∀ {a b c : α}, a < b → b ≤ c → a < c - | _a, _b, _c, hab, hbc => - let ⟨hab, hba⟩ := le_not_le_of_lt hab - lt_of_le_not_le (le_trans hab hbc) fun hca => hba (le_trans hbc hca) +@[trans] lemma lt_trans (hab : a < b) (hbc : b < c) : a < c := lt_of_lt_of_le hab (le_of_lt hbc) +@[trans] lemma gt_trans : a > b → b > c → a > c := fun h₁ h₂ => lt_trans h₂ h₁ -@[trans] -theorem lt_of_le_of_lt : ∀ {a b c : α}, a ≤ b → b < c → a < c - | _a, _b, _c, hab, hbc => - let ⟨hbc, hcb⟩ := le_not_le_of_lt hbc - lt_of_le_not_le (le_trans hab hbc) fun hca => hcb (le_trans hca hab) +lemma ne_of_lt (h : a < b) : a ≠ b := fun he => absurd h (he ▸ lt_irrefl a) +lemma ne_of_gt (h : b < a) : a ≠ b := fun he => absurd h (he ▸ lt_irrefl a) +lemma lt_asymm (h : a < b) : ¬b < a := fun h1 : b < a => lt_irrefl a (lt_trans h h1) -@[trans] -theorem gt_of_gt_of_ge {a b c : α} (h₁ : a > b) (h₂ : b ≥ c) : a > c := - lt_of_le_of_lt h₂ h₁ +alias not_lt_of_gt := lt_asymm +alias not_lt_of_lt := lt_asymm -@[trans] -theorem gt_of_ge_of_gt {a b c : α} (h₁ : a ≥ b) (h₂ : b > c) : a > c := - lt_of_lt_of_le h₂ h₁ +lemma le_of_lt_or_eq (h : a < b ∨ a = b) : a ≤ b := h.elim le_of_lt le_of_eq +lemma le_of_eq_or_lt (h : a = b ∨ a < b) : a ≤ b := h.elim le_of_eq le_of_lt --- Porting note (#10754): new instance instance (priority := 900) : @Trans α α α LE.le LE.le LE.le := ⟨le_trans⟩ instance (priority := 900) : @Trans α α α LT.lt LT.lt LT.lt := ⟨lt_trans⟩ instance (priority := 900) : @Trans α α α LT.lt LE.le LT.lt := ⟨lt_of_lt_of_le⟩ @@ -119,18 +218,6 @@ instance (priority := 900) : @Trans α α α GT.gt GT.gt GT.gt := ⟨gt_trans⟩ instance (priority := 900) : @Trans α α α GT.gt GE.ge GT.gt := ⟨gt_of_gt_of_ge⟩ instance (priority := 900) : @Trans α α α GE.ge GT.gt GT.gt := ⟨gt_of_ge_of_gt⟩ -theorem not_le_of_gt {a b : α} (h : a > b) : ¬a ≤ b := - (le_not_le_of_lt h).right - -theorem not_lt_of_ge {a b : α} (h : a ≥ b) : ¬a < b := fun hab => not_le_of_gt hab h - -theorem le_of_lt_or_eq : ∀ {a b : α}, a < b ∨ a = b → a ≤ b - | _a, _b, Or.inl hab => le_of_lt hab - | _a, _b, Or.inr hab => hab ▸ le_refl _ - -theorem le_of_eq_or_lt {a b : α} (h : a = b ∨ a < b) : a ≤ b := - Or.elim h le_of_eq le_of_lt - /-- `<` is decidable if `≤` is. -/ def decidableLTOfDecidableLE [@DecidableRel α (· ≤ ·)] : @DecidableRel α (· < ·) | a, b => @@ -151,17 +238,16 @@ section PartialOrder class PartialOrder (α : Type u) extends Preorder α where le_antisymm : ∀ a b : α, a ≤ b → b ≤ a → a = b -variable [PartialOrder α] +variable [PartialOrder α] {a b : α} -theorem le_antisymm : ∀ {a b : α}, a ≤ b → b ≤ a → a = b := - PartialOrder.le_antisymm _ _ +lemma le_antisymm : a ≤ b → b ≤ a → a = b := PartialOrder.le_antisymm _ _ alias eq_of_le_of_le := le_antisymm -theorem le_antisymm_iff {a b : α} : a = b ↔ a ≤ b ∧ b ≤ a := +lemma le_antisymm_iff : a = b ↔ a ≤ b ∧ b ≤ a := ⟨fun e => ⟨le_of_eq e, le_of_eq e.symm⟩, fun ⟨h1, h2⟩ => le_antisymm h1 h2⟩ -theorem lt_of_le_of_ne {a b : α} : a ≤ b → a ≠ b → a < b := fun h₁ h₂ => +lemma lt_of_le_of_ne : a ≤ b → a ≠ b → a < b := fun h₁ h₂ => lt_of_le_not_le h₁ <| mt (le_antisymm h₁) h₂ /-- Equality is decidable if `≤` is. -/ @@ -175,24 +261,21 @@ namespace Decidable variable [@DecidableRel α (· ≤ ·)] -theorem lt_or_eq_of_le {a b : α} (hab : a ≤ b) : a < b ∨ a = b := +lemma lt_or_eq_of_le (hab : a ≤ b) : a < b ∨ a = b := if hba : b ≤ a then Or.inr (le_antisymm hab hba) else Or.inl (lt_of_le_not_le hab hba) -theorem eq_or_lt_of_le {a b : α} (hab : a ≤ b) : a = b ∨ a < b := +lemma eq_or_lt_of_le (hab : a ≤ b) : a = b ∨ a < b := (lt_or_eq_of_le hab).symm -theorem le_iff_lt_or_eq {a b : α} : a ≤ b ↔ a < b ∨ a = b := +lemma le_iff_lt_or_eq : a ≤ b ↔ a < b ∨ a = b := ⟨lt_or_eq_of_le, le_of_lt_or_eq⟩ end Decidable attribute [local instance] Classical.propDecidable -theorem lt_or_eq_of_le {a b : α} : a ≤ b → a < b ∨ a = b := - Decidable.lt_or_eq_of_le - -theorem le_iff_lt_or_eq {a b : α} : a ≤ b ↔ a < b ∨ a = b := - Decidable.le_iff_lt_or_eq +lemma lt_or_eq_of_le : a ≤ b → a < b ∨ a = b := Decidable.lt_or_eq_of_le +lemma le_iff_lt_or_eq : a ≤ b ↔ a < b ∨ a = b := Decidable.le_iff_lt_or_eq end PartialOrder @@ -247,23 +330,17 @@ class LinearOrder (α : Type u) extends PartialOrder α, Min α, Max α, Ord α compare_eq_compareOfLessAndEq : ∀ a b, compare a b = compareOfLessAndEq a b := by compareOfLessAndEq_rfl -variable [LinearOrder α] +variable [LinearOrder α] {a b c : α} attribute [local instance] LinearOrder.decidableLE -theorem le_total : ∀ a b : α, a ≤ b ∨ b ≤ a := - LinearOrder.le_total +lemma le_total : ∀ a b : α, a ≤ b ∨ b ≤ a := LinearOrder.le_total -theorem le_of_not_ge {a b : α} : ¬a ≥ b → a ≤ b := - Or.resolve_left (le_total b a) +lemma le_of_not_ge : ¬a ≥ b → a ≤ b := (le_total b a).resolve_left +lemma le_of_not_le : ¬a ≤ b → b ≤ a := (le_total a b).resolve_left +lemma lt_of_not_ge (h : ¬a ≥ b) : a < b := lt_of_le_not_le (le_of_not_ge h) h -theorem le_of_not_le {a b : α} : ¬a ≤ b → b ≤ a := - Or.resolve_left (le_total a b) - -theorem not_lt_of_gt {a b : α} (h : a > b) : ¬a < b := - lt_asymm h - -theorem lt_trichotomy (a b : α) : a < b ∨ a = b ∨ b < a := +lemma lt_trichotomy (a b : α) : a < b ∨ a = b ∨ b < a := Or.elim (le_total a b) (fun h : a ≤ b => Or.elim (Decidable.lt_or_eq_of_le h) (fun h : a < b => Or.inl h) fun h : a = b => @@ -272,73 +349,40 @@ theorem lt_trichotomy (a b : α) : a < b ∨ a = b ∨ b < a := Or.elim (Decidable.lt_or_eq_of_le h) (fun h : b < a => Or.inr (Or.inr h)) fun h : b = a => Or.inr (Or.inl h.symm) -theorem le_of_not_lt {a b : α} (h : ¬b < a) : a ≤ b := +lemma le_of_not_lt (h : ¬b < a) : a ≤ b := match lt_trichotomy a b with | Or.inl hlt => le_of_lt hlt | Or.inr (Or.inl HEq) => HEq ▸ le_refl a | Or.inr (Or.inr hgt) => absurd hgt h -theorem le_of_not_gt {a b : α} : ¬a > b → a ≤ b := - le_of_not_lt - -theorem lt_of_not_ge {a b : α} (h : ¬a ≥ b) : a < b := - lt_of_le_not_le ((le_total _ _).resolve_right h) h +lemma le_of_not_gt : ¬a > b → a ≤ b := le_of_not_lt -theorem lt_or_le (a b : α) : a < b ∨ b ≤ a := +lemma lt_or_le (a b : α) : a < b ∨ b ≤ a := if hba : b ≤ a then Or.inr hba else Or.inl <| lt_of_not_ge hba -theorem le_or_lt (a b : α) : a ≤ b ∨ b < a := - (lt_or_le b a).symm +lemma le_or_lt (a b : α) : a ≤ b ∨ b < a := (lt_or_le b a).symm +lemma lt_or_ge : ∀ a b : α, a < b ∨ a ≥ b := lt_or_le +lemma le_or_gt : ∀ a b : α, a ≤ b ∨ a > b := le_or_lt -theorem lt_or_ge : ∀ a b : α, a < b ∨ a ≥ b := - lt_or_le - -theorem le_or_gt : ∀ a b : α, a ≤ b ∨ a > b := - le_or_lt - -theorem lt_or_gt_of_ne {a b : α} (h : a ≠ b) : a < b ∨ a > b := - match lt_trichotomy a b with - | Or.inl hlt => Or.inl hlt - | Or.inr (Or.inl HEq) => absurd HEq h - | Or.inr (Or.inr hgt) => Or.inr hgt +lemma lt_or_gt_of_ne (h : a ≠ b) : a < b ∨ a > b := by simpa [h] using lt_trichotomy a b -theorem ne_iff_lt_or_gt {a b : α} : a ≠ b ↔ a < b ∨ a > b := - ⟨lt_or_gt_of_ne, fun o => Or.elim o ne_of_lt ne_of_gt⟩ +lemma ne_iff_lt_or_gt : a ≠ b ↔ a < b ∨ a > b := ⟨lt_or_gt_of_ne, (Or.elim · ne_of_lt ne_of_gt)⟩ -theorem lt_iff_not_ge (x y : α) : x < y ↔ ¬x ≥ y := - ⟨not_le_of_gt, lt_of_not_ge⟩ +lemma lt_iff_not_ge (x y : α) : x < y ↔ ¬x ≥ y := ⟨not_le_of_gt, lt_of_not_ge⟩ -@[simp] -theorem not_lt {a b : α} : ¬a < b ↔ b ≤ a := - ⟨le_of_not_gt, not_lt_of_ge⟩ +@[simp] lemma not_lt : ¬a < b ↔ b ≤ a := ⟨le_of_not_gt, not_lt_of_ge⟩ +@[simp] lemma not_le : ¬a ≤ b ↔ b < a := (lt_iff_not_ge _ _).symm -@[simp] -theorem not_le {a b : α} : ¬a ≤ b ↔ b < a := - (lt_iff_not_ge _ _).symm +instance (priority := 900) (a b : α) : Decidable (a < b) := LinearOrder.decidableLT a b +instance (priority := 900) (a b : α) : Decidable (a ≤ b) := LinearOrder.decidableLE a b +instance (priority := 900) (a b : α) : Decidable (a = b) := LinearOrder.decidableEq a b -instance (priority := 900) (a b : α) : Decidable (a < b) := - LinearOrder.decidableLT a b - -instance (priority := 900) (a b : α) : Decidable (a ≤ b) := - LinearOrder.decidableLE a b - -instance (priority := 900) (a b : α) : Decidable (a = b) := - LinearOrder.decidableEq a b - -theorem eq_or_lt_of_not_lt {a b : α} (h : ¬a < b) : a = b ∨ b < a := +lemma eq_or_lt_of_not_lt (h : ¬a < b) : a = b ∨ b < a := if h₁ : a = b then Or.inl h₁ else Or.inr (lt_of_not_ge fun hge => h (lt_of_le_of_ne hge h₁)) -instance : IsTotalPreorder α (· ≤ ·) where - trans := @le_trans _ _ - total := le_total - --- TODO(Leo): decide whether we should keep this instance or not -instance isStrictWeakOrder_of_linearOrder : IsStrictWeakOrder α (· < ·) := - have : IsTotalPreorder α (· ≤ ·) := by infer_instance -- Porting note: added - isStrictWeakOrder_of_isTotalPreorder lt_iff_not_ge - -- TODO(Leo): decide whether we should keep this instance or not instance isStrictTotalOrder_of_linearOrder : IsStrictTotalOrder α (· < ·) where + irrefl := lt_irrefl trichotomous := lt_trichotomy /-- Perform a case-split on the ordering of `x` and `y` in a decidable linear order. -/ @@ -346,44 +390,153 @@ def ltByCases (x y : α) {P : Sort*} (h₁ : x < y → P) (h₂ : x = y → P) ( if h : x < y then h₁ h else if h' : y < x then h₃ h' else h₂ (le_antisymm (le_of_not_gt h') (le_of_not_gt h)) +namespace Nat + +/-! Deprecated properties of inequality on `Nat` -/ + +@[deprecated (since := "2024-08-23")] +protected def ltGeByCases {a b : Nat} {C : Sort u} (h₁ : a < b → C) (h₂ : b ≤ a → C) : C := + Decidable.byCases h₁ fun h => h₂ (Or.elim (Nat.lt_or_ge a b) (fun a => absurd a h) fun a => a) + +set_option linter.deprecated false in +@[deprecated ltByCases (since := "2024-08-23")] +protected def ltByCases {a b : Nat} {C : Sort u} (h₁ : a < b → C) (h₂ : a = b → C) + (h₃ : b < a → C) : C := + Nat.ltGeByCases h₁ fun h₁ => Nat.ltGeByCases h₃ fun h => h₂ (Nat.le_antisymm h h₁) + +end Nat + theorem le_imp_le_of_lt_imp_lt {α β} [Preorder α] [LinearOrder β] {a b : α} {c d : β} (H : d < c → b < a) (h : a ≤ b) : c ≤ d := le_of_not_lt fun h' => not_le_of_gt (H h') h --- Porting note: new +lemma min_def (a b : α) : min a b = if a ≤ b then a else b := by rw [LinearOrder.min_def a] +lemma max_def (a b : α) : max a b = if a ≤ b then b else a := by rw [LinearOrder.max_def a] + +-- Porting note: no `min_tac` tactic in the following series of lemmas + +lemma min_le_left (a b : α) : min a b ≤ a := by + if h : a ≤ b + then simp [min_def, if_pos h, le_refl] + else simp [min_def, if_neg h]; exact le_of_not_le h + +lemma min_le_right (a b : α) : min a b ≤ b := by + if h : a ≤ b + then simp [min_def, if_pos h]; exact h + else simp [min_def, if_neg h, le_refl] + +lemma le_min (h₁ : c ≤ a) (h₂ : c ≤ b) : c ≤ min a b := by + if h : a ≤ b + then simp [min_def, if_pos h]; exact h₁ + else simp [min_def, if_neg h]; exact h₂ + +lemma le_max_left (a b : α) : a ≤ max a b := by + if h : a ≤ b + then simp [max_def, if_pos h]; exact h + else simp [max_def, if_neg h, le_refl] + +lemma le_max_right (a b : α) : b ≤ max a b := by + if h : a ≤ b + then simp [max_def, if_pos h, le_refl] + else simp [max_def, if_neg h]; exact le_of_not_le h + +lemma max_le (h₁ : a ≤ c) (h₂ : b ≤ c) : max a b ≤ c := by + if h : a ≤ b + then simp [max_def, if_pos h]; exact h₂ + else simp [max_def, if_neg h]; exact h₁ + +lemma eq_min (h₁ : c ≤ a) (h₂ : c ≤ b) (h₃ : ∀ {d}, d ≤ a → d ≤ b → d ≤ c) : c = min a b := + le_antisymm (le_min h₁ h₂) (h₃ (min_le_left a b) (min_le_right a b)) + +lemma min_comm (a b : α) : min a b = min b a := + eq_min (min_le_right a b) (min_le_left a b) fun h₁ h₂ => le_min h₂ h₁ + +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 + +lemma min_left_comm : ∀ a b c : α, min a (min b c) = min b (min a c) := + left_comm (@min α _) (@min_comm α _) (@min_assoc α _) + +@[simp] lemma min_self (a : α) : min a a = a := by simp [min_def] + +lemma min_eq_left (h : a ≤ b) : min a b = a := by + apply Eq.symm; apply eq_min (le_refl _) h; intros; assumption + +lemma min_eq_right (h : b ≤ a) : min a b = b := min_comm b a ▸ min_eq_left h + +lemma eq_max (h₁ : a ≤ c) (h₂ : b ≤ c) (h₃ : ∀ {d}, a ≤ d → b ≤ d → c ≤ d) : + c = max a b := + le_antisymm (h₃ (le_max_left a b) (le_max_right a b)) (max_le h₁ h₂) + +lemma max_comm (a b : α) : max a b = max b a := + eq_max (le_max_right a b) (le_max_left a b) fun h₁ h₂ => max_le h₂ h₁ + +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₂ + +lemma max_left_comm : ∀ a b c : α, max a (max b c) = max b (max a c) := + left_comm (@max α _) (@max_comm α _) (@max_assoc α _) + +@[simp] lemma max_self (a : α) : max a a = a := by simp [max_def] + +lemma max_eq_left (h : b ≤ a) : max a b = a := by + apply Eq.symm; apply eq_max (le_refl _) h; intros; assumption + +lemma max_eq_right (h : a ≤ b) : max a b = b := max_comm b a ▸ max_eq_left h + +lemma min_eq_left_of_lt (h : a < b) : min a b = a := min_eq_left (le_of_lt h) +lemma min_eq_right_of_lt (h : b < a) : min a b = b := min_eq_right (le_of_lt h) +lemma max_eq_left_of_lt (h : b < a) : max a b = a := max_eq_left (le_of_lt h) +lemma max_eq_right_of_lt (h : a < b) : max a b = b := max_eq_right (le_of_lt h) + +lemma lt_min (h₁ : a < b) (h₂ : a < c) : a < min b c := by + cases le_total b c <;> simp [min_eq_left, min_eq_right, *] + +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} -theorem compare_lt_iff_lt {a b : α} : (compare a b = .lt) ↔ a < b := by +lemma compare_lt_iff_lt : compare a b = .lt ↔ a < b := by rw [LinearOrder.compare_eq_compareOfLessAndEq, compareOfLessAndEq] - split_ifs <;> simp only [*, lt_irrefl] + split_ifs <;> simp only [*, lt_irrefl, reduceCtorEq] -theorem compare_gt_iff_gt {a b : α} : (compare a b = .gt) ↔ a > b := by +lemma compare_gt_iff_gt : compare a b = .gt ↔ a > b := by rw [LinearOrder.compare_eq_compareOfLessAndEq, compareOfLessAndEq] - split_ifs <;> simp only [*, lt_irrefl, not_lt_of_gt] + split_ifs <;> simp only [*, lt_irrefl, not_lt_of_gt, reduceCtorEq] case _ h₁ h₂ => have h : b < a := lt_trichotomy a b |>.resolve_left h₁ |>.resolve_left h₂ exact true_iff_iff.2 h -theorem compare_eq_iff_eq {a b : α} : (compare a b = .eq) ↔ a = b := by +lemma compare_eq_iff_eq : compare a b = .eq ↔ a = b := by rw [LinearOrder.compare_eq_compareOfLessAndEq, compareOfLessAndEq] - split_ifs <;> try simp only + split_ifs <;> try simp only [reduceCtorEq] case _ h => exact false_iff_iff.2 <| ne_iff_lt_or_gt.2 <| .inl h case _ _ h => exact true_iff_iff.2 h case _ _ h => exact false_iff_iff.2 h -theorem compare_le_iff_le {a b : α} : (compare a b ≠ .gt) ↔ a ≤ b := by +lemma compare_le_iff_le : compare a b ≠ .gt ↔ a ≤ b := by cases h : compare a b <;> simp · exact le_of_lt <| compare_lt_iff_lt.1 h · exact le_of_eq <| compare_eq_iff_eq.1 h · exact compare_gt_iff_gt.1 h -theorem compare_ge_iff_ge {a b : α} : (compare a b ≠ .lt) ↔ a ≥ b := by +lemma compare_ge_iff_ge : compare a b ≠ .lt ↔ a ≥ b := by cases h : compare a b <;> simp · exact compare_lt_iff_lt.1 h · exact le_of_eq <| (·.symm) <| compare_eq_iff_eq.1 h · exact le_of_lt <| compare_gt_iff_gt.1 h -theorem compare_iff (a b : α) {o : Ordering} : compare a b = o ↔ o.toRel a b := by +lemma compare_iff (a b : α) : compare a b = o ↔ o.toRel a b := by cases o <;> simp only [Ordering.toRel] · exact compare_lt_iff_lt · exact compare_eq_iff_eq diff --git a/Mathlib/Order/Directed.lean b/Mathlib/Order/Directed.lean index 8ab4e604c1f95..311f396d99159 100644 --- a/Mathlib/Order/Directed.lean +++ b/Mathlib/Order/Directed.lean @@ -40,7 +40,7 @@ variable {α : Type u} {β : Type v} {ι : Sort w} (r r' s : α → α → Prop) local infixl:50 " ≼ " => r /-- A family of elements of α is directed (with respect to a relation `≼` on α) - if there is a member of the family `≼`-above any pair in the family. -/ + if there is a member of the family `≼`-above any pair in the family. -/ def Directed (f : ι → α) := ∀ x y, ∃ z, f x ≼ f z ∧ f y ≼ f z diff --git a/Mathlib/Order/Estimator.lean b/Mathlib/Order/Estimator.lean index 6ce851d7cff48..6cbb66c675781 100644 --- a/Mathlib/Order/Estimator.lean +++ b/Mathlib/Order/Estimator.lean @@ -3,7 +3,7 @@ Copyright (c) 2023 Kim Liesinger. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kim Liesinger -/ -import Mathlib.Data.Set.Defs +import Mathlib.Data.Set.Operations import Mathlib.Order.Heyting.Basic import Mathlib.Order.RelClasses import Mathlib.Order.Hom.Basic diff --git a/Mathlib/Order/Filter/AtTopBot.lean b/Mathlib/Order/Filter/AtTopBot.lean index f2357f5cf20d7..2504e1ba49618 100644 --- a/Mathlib/Order/Filter/AtTopBot.lean +++ b/Mathlib/Order/Filter/AtTopBot.lean @@ -14,7 +14,6 @@ import Mathlib.Order.Interval.Set.OrderIso import Mathlib.Order.ConditionallyCompleteLattice.Basic import Mathlib.Order.Filter.Bases import Mathlib.Algebra.Order.Ring.Nat -import Mathlib.Algebra.Order.Field.Unbundled.Basic /-! # `Filter.atTop` and `Filter.atBot` filters on preorders, monoids and groups. @@ -802,13 +801,15 @@ variable [OrderedRing α] {l : Filter β} {f g : β → α} theorem Tendsto.atTop_mul_atBot (hf : Tendsto f l atTop) (hg : Tendsto g l atBot) : Tendsto (fun x => f x * g x) l atBot := by have := hf.atTop_mul_atTop <| tendsto_neg_atBot_atTop.comp hg - simpa only [(· ∘ ·), neg_mul_eq_mul_neg, neg_neg] using tendsto_neg_atTop_atBot.comp this + simpa only [Function.comp_def, neg_mul_eq_mul_neg, neg_neg] using + tendsto_neg_atTop_atBot.comp this theorem Tendsto.atBot_mul_atTop (hf : Tendsto f l atBot) (hg : Tendsto g l atTop) : Tendsto (fun x => f x * g x) l atBot := by have : Tendsto (fun x => -f x * g x) l atTop := (tendsto_neg_atBot_atTop.comp hf).atTop_mul_atTop hg - simpa only [(· ∘ ·), neg_mul_eq_neg_mul, neg_neg] using tendsto_neg_atTop_atBot.comp this + simpa only [Function.comp_def, neg_mul_eq_neg_mul, neg_neg] using + tendsto_neg_atTop_atBot.comp this theorem Tendsto.atBot_mul_atBot (hf : Tendsto f l atBot) (hg : Tendsto g l atBot) : Tendsto (fun x => f x * g x) l atTop := by @@ -1322,6 +1323,18 @@ theorem prod_atTop_atTop_eq [Preorder α] [Preorder β] : · subsingleton simpa [atTop, prod_iInf_left, prod_iInf_right, iInf_prod] using iInf_comm +lemma tendsto_finset_prod_atTop : + Tendsto (fun (p : Finset ι × Finset ι') ↦ p.1 ×ˢ p.2) atTop atTop := by + classical + apply Monotone.tendsto_atTop_atTop + · intro p q hpq + simpa using Finset.product_subset_product hpq.1 hpq.2 + · intro b + use (Finset.image Prod.fst b, Finset.image Prod.snd b) + rintro ⟨d1, d2⟩ hd + simp only [Finset.mem_product, Finset.mem_image, Prod.exists, exists_and_right, exists_eq_right] + exact ⟨⟨d2, hd⟩, ⟨d1, hd⟩⟩ + theorem prod_atBot_atBot_eq [Preorder α] [Preorder β] : (atBot : Filter α) ×ˢ (atBot : Filter β) = (atBot : Filter (α × β)) := @prod_atTop_atTop_eq αᵒᵈ βᵒᵈ _ _ @@ -1832,3 +1845,5 @@ filters `atTop.map (fun s ↦ ∑ i ∈ s, f (g i))` and `atTop.map (fun s ↦ This lemma is used to prove the equality `∑' x, f (g x) = ∑' y, f y` under the same assumptions. -/ add_decl_doc Function.Injective.map_atTop_finset_sum_eq + +set_option linter.style.longFile 2000 diff --git a/Mathlib/Order/Filter/Bases.lean b/Mathlib/Order/Filter/Bases.lean index dee2d71c9f043..4891e31ed0e66 100644 --- a/Mathlib/Order/Filter/Bases.lean +++ b/Mathlib/Order/Filter/Bases.lean @@ -100,7 +100,7 @@ instance FilterBasis.nonempty_sets (B : FilterBasis α) : Nonempty B.sets := /-- If `B` is a filter basis on `α`, and `U` a subset of `α` then we can write `U ∈ B` as on paper. -/ instance {α : Type*} : Membership (Set α) (FilterBasis α) := - ⟨fun U B => U ∈ B.sets⟩ + ⟨fun B U => U ∈ B.sets⟩ @[simp] theorem FilterBasis.mem_sets {s : Set α} {B : FilterBasis α} : s ∈ B.sets ↔ s ∈ B := Iff.rfl @@ -671,7 +671,7 @@ theorem hasBasis_iInf_principal {s : ι → Set α} (h : Directed (· ≥ ·) s) 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)`. -/ +of `⨅ i, 𝓟 (s i)`. -/ theorem hasBasis_iInf_principal_finite {ι : Type*} (s : ι → Set α) : (⨅ i, 𝓟 (s i)).HasBasis (fun t : Set ι => t.Finite) fun t => ⋂ i ∈ t, s i := by refine ⟨fun U => (mem_iInf_finite _).trans ?_⟩ diff --git a/Mathlib/Order/Filter/Basic.lean b/Mathlib/Order/Filter/Basic.lean index 37961c2404ebb..17215ab8c1aee 100644 --- a/Mathlib/Order/Filter/Basic.lean +++ b/Mathlib/Order/Filter/Basic.lean @@ -97,7 +97,7 @@ structure Filter (α : Type*) where /-- 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 U F => U ∈ F.sets⟩ + ⟨fun F U => U ∈ F.sets⟩ namespace Filter @@ -139,6 +139,9 @@ theorem mem_of_superset {x y : Set α} (hx : x ∈ f) (hxy : x ⊆ y) : y ∈ f 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 @@ -533,20 +536,21 @@ theorem mem_iInf_of_mem {f : ι → Filter α} (i : ι) {s} (hs : s ∈ f i) : s iInf_le f i hs theorem mem_iInf_of_iInter {ι} {s : ι → Filter α} {U : Set α} {I : Set ι} (I_fin : I.Finite) - {V : I → Set α} (hV : ∀ i, V i ∈ s i) (hU : ⋂ i, V i ⊆ U) : U ∈ ⨅ i, s i := by + {V : I → Set α} (hV : ∀ (i : I), V i ∈ s i) (hU : ⋂ i, V i ⊆ U) : U ∈ ⨅ i, s i := by haveI := I_fin.fintype refine mem_of_superset (iInter_mem.2 fun i => ?_) hU exact mem_iInf_of_mem (i : ι) (hV _) theorem mem_iInf {ι} {s : ι → Filter α} {U : Set α} : - (U ∈ ⨅ i, s i) ↔ ∃ I : Set ι, I.Finite ∧ ∃ V : I → Set α, (∀ i, V i ∈ s i) ∧ U = ⋂ i, V i := by + (U ∈ ⨅ i, s i) ↔ + ∃ I : Set ι, I.Finite ∧ ∃ V : I → Set α, (∀ (i : I), V i ∈ s i) ∧ U = ⋂ i, V i := by constructor · rw [iInf_eq_generate, mem_generate_iff] rintro ⟨t, tsub, tfin, tinter⟩ rcases eq_finite_iUnion_of_finite_subset_iUnion tfin tsub with ⟨I, Ifin, σ, σfin, σsub, rfl⟩ rw [sInter_iUnion] at tinter set V := fun i => U ∪ ⋂₀ σ i with hV - have V_in : ∀ i, V i ∈ s i := by + have V_in : ∀ (i : I), V i ∈ s i := by rintro i have : ⋂₀ σ i ∈ s i := by rw [sInter_mem (σfin _)] @@ -568,7 +572,7 @@ theorem mem_iInf' {ι} {s : ι → Filter α} {U : Set α} : refine ⟨I, If, fun i => if hi : i ∈ I then V ⟨i, hi⟩ else univ, fun i => ?_, fun i hi => ?_, ?_⟩ · dsimp only split_ifs - exacts [hV _, univ_mem] + exacts [hV ⟨i,_⟩, univ_mem] · exact dif_neg hi · simp only [iInter_dite, biInter_eq_iInter, dif_pos (Subtype.coe_prop _), Subtype.coe_eta, iInter_univ, inter_univ, eq_self_iff_true, true_and_iff] @@ -707,7 +711,7 @@ theorem eq_sInf_of_mem_iff_exists_mem {S : Set (Filter α)} {l : Filter α} theorem eq_iInf_of_mem_iff_exists_mem {f : ι → Filter α} {l : Filter α} (h : ∀ {s}, s ∈ l ↔ ∃ i, s ∈ f i) : l = iInf f := - eq_sInf_of_mem_iff_exists_mem <| h.trans exists_range_iff.symm + eq_sInf_of_mem_iff_exists_mem <| h.trans (exists_range_iff (p := (_ ∈ ·))).symm theorem eq_biInf_of_mem_iff_exists_mem {f : ι → Filter α} {p : ι → Prop} {l : Filter α} (h : ∀ {s}, s ∈ l ↔ ∃ i, p i ∧ s ∈ f i) : l = ⨅ (i) (_ : p i), f i := by @@ -2264,13 +2268,6 @@ theorem comap_eval_neBot {ι : Type*} {α : ι → Type*} [∀ j, Nonempty (α j (f : Filter (α i)) [NeBot f] : (comap (eval i) f).NeBot := comap_eval_neBot_iff.2 ‹_› -theorem comap_inf_principal_neBot_of_image_mem {f : Filter β} {m : α → β} (hf : NeBot f) {s : Set α} - (hs : m '' s ∈ f) : NeBot (comap m f ⊓ 𝓟 s) := by - refine ⟨compl_compl s ▸ mt mem_of_eq_bot ?_⟩ - rintro ⟨t, ht, hts⟩ - rcases hf.nonempty_of_mem (inter_mem hs ht) with ⟨_, ⟨x, hxs, rfl⟩, hxt⟩ - exact absurd hxs (hts hxt) - theorem comap_coe_neBot_of_le_principal {s : Set γ} {l : Filter γ} [h : NeBot l] (h' : l ≤ 𝓟 s) : NeBot (comap ((↑) : s → γ) l) := h.comap_of_range_mem <| (@Subtype.range_coe γ s).symm ▸ h' (mem_principal_self s) @@ -2402,6 +2399,27 @@ protected theorem push_pull (f : α → β) (F : Filter α) (G : Filter β) : protected theorem push_pull' (f : α → β) (F : Filter α) (G : Filter β) : map f (comap f G ⊓ F) = G ⊓ map f F := by simp only [Filter.push_pull, inf_comm] +theorem disjoint_comap_iff_map {f : α → β} {F : Filter α} {G : Filter β} : + Disjoint F (comap f G) ↔ Disjoint (map f F) G := by + simp only [disjoint_iff, ← Filter.push_pull, map_eq_bot_iff] + +theorem disjoint_comap_iff_map' {f : α → β} {F : Filter α} {G : Filter β} : + Disjoint (comap f G) F ↔ Disjoint G (map f F) := by + simp only [disjoint_iff, ← Filter.push_pull', map_eq_bot_iff] + +theorem neBot_inf_comap_iff_map {f : α → β} {F : Filter α} {G : Filter β} : + NeBot (F ⊓ comap f G) ↔ NeBot (map f F ⊓ G) := by + rw [← map_neBot_iff, Filter.push_pull] + +theorem neBot_inf_comap_iff_map' {f : α → β} {F : Filter α} {G : Filter β} : + NeBot (comap f G ⊓ F) ↔ NeBot (G ⊓ map f F) := by + rw [← map_neBot_iff, Filter.push_pull'] + +theorem comap_inf_principal_neBot_of_image_mem {f : Filter β} {m : α → β} (hf : NeBot f) {s : Set α} + (hs : m '' s ∈ f) : NeBot (comap m f ⊓ 𝓟 s) := by + rw [neBot_inf_comap_iff_map', map_principal, ← frequently_mem_iff_neBot] + exact Eventually.frequently hs + theorem principal_eq_map_coe_top (s : Set α) : 𝓟 s = map ((↑) : s → α) ⊤ := by simp theorem inf_principal_eq_bot_iff_comap {F : Filter α} {s : Set α} : @@ -2908,3 +2926,5 @@ lemma compl_mem_comk {p : Set α → Prop} {he hmono hunion s} : simp end Filter + +set_option linter.style.longFile 3000 diff --git a/Mathlib/Order/Filter/CardinalInter.lean b/Mathlib/Order/Filter/CardinalInter.lean index 7462de92c6dd8..df6c37ffccbb7 100644 --- a/Mathlib/Order/Filter/CardinalInter.lean +++ b/Mathlib/Order/Filter/CardinalInter.lean @@ -300,16 +300,19 @@ theorem mem_cardinaleGenerate_iff {s : Set α} {hreg : c.IsRegular} : s ∈ cardinalGenerate g (IsRegular.nat_lt hreg 2) ↔ ∃ S : Set (Set α), S ⊆ g ∧ (#S < c) ∧ ⋂₀ S ⊆ s := by constructor <;> intro h - · induction' h with s hs s t _ st ih S Sct _ ih - · refine ⟨{s}, singleton_subset_iff.mpr hs, ?_⟩ + · induction h with + | @basic s hs => + refine ⟨{s}, singleton_subset_iff.mpr hs, ?_⟩ simpa [subset_refl] using IsRegular.nat_lt hreg 1 - · exact ⟨∅, ⟨empty_subset g, mk_eq_zero (∅ : Set <| Set α) ▸ IsRegular.nat_lt hreg 0, by simp⟩⟩ - · exact Exists.imp (by tauto) ih - choose T Tg Tct hT using ih - refine ⟨⋃ (s) (H : s ∈ S), T s H, by simpa, - (Cardinal.card_biUnion_lt_iff_forall_of_isRegular hreg Sct).2 Tct, ?_⟩ - apply subset_sInter - apply fun s H => subset_trans (sInter_subset_sInter (subset_iUnion₂ s H)) (hT s H) + | univ => + exact ⟨∅, ⟨empty_subset g, mk_eq_zero (∅ : Set <| Set α) ▸ IsRegular.nat_lt hreg 0, by simp⟩⟩ + | superset _ _ ih => exact Exists.imp (by tauto) ih + | @sInter S Sct _ ih => + choose T Tg Tct hT using ih + refine ⟨⋃ (s) (H : s ∈ S), T s H, by simpa, + (Cardinal.card_biUnion_lt_iff_forall_of_isRegular hreg Sct).2 Tct, ?_⟩ + apply subset_sInter + apply fun s H => subset_trans (sInter_subset_sInter (subset_iUnion₂ s H)) (hT s H) rcases h with ⟨S, Sg, Sct, hS⟩ have : CardinalInterFilter (cardinalGenerate g (IsRegular.nat_lt hreg 2)) c := cardinalInter_ofCardinalGenerate _ _ diff --git a/Mathlib/Order/Filter/CountableInter.lean b/Mathlib/Order/Filter/CountableInter.lean index ea7172ae2ea14..b9d5d1ef60f8d 100644 --- a/Mathlib/Order/Filter/CountableInter.lean +++ b/Mathlib/Order/Filter/CountableInter.lean @@ -242,16 +242,16 @@ it contains a countable intersection of elements of `g`. -/ theorem mem_countableGenerate_iff {s : Set α} : s ∈ countableGenerate g ↔ ∃ S : Set (Set α), S ⊆ g ∧ S.Countable ∧ ⋂₀ S ⊆ s := by constructor <;> intro h - · induction' h with s hs s t _ st ih S Sct _ ih - · exact ⟨{s}, by simp [hs, subset_refl]⟩ - · exact ⟨∅, by simp⟩ - · refine Exists.imp (fun S => ?_) ih - tauto - choose T Tg Tct hT using ih - refine ⟨⋃ (s) (H : s ∈ S), T s H, by simpa, Sct.biUnion Tct, ?_⟩ - apply subset_sInter - intro s H - exact subset_trans (sInter_subset_sInter (subset_iUnion₂ s H)) (hT s H) + · induction h with + | @basic s hs => exact ⟨{s}, by simp [hs, subset_refl]⟩ + | univ => exact ⟨∅, by simp⟩ + | superset _ _ ih => refine Exists.imp (fun S => ?_) ih; tauto + | @sInter S Sct _ ih => + choose T Tg Tct hT using ih + refine ⟨⋃ (s) (H : s ∈ S), T s H, by simpa, Sct.biUnion Tct, ?_⟩ + apply subset_sInter + intro s H + exact subset_trans (sInter_subset_sInter (subset_iUnion₂ s H)) (hT s H) rcases h with ⟨S, Sg, Sct, hS⟩ refine mem_of_superset ((countable_sInter_mem Sct).mpr ?_) hS intro s H @@ -262,11 +262,11 @@ theorem le_countableGenerate_iff_of_countableInterFilter {f : Filter α} [Counta constructor <;> intro h · exact subset_trans (fun s => CountableGenerateSets.basic) h intro s hs - induction' hs with s hs s t _ st ih S Sct _ ih - · exact h hs - · exact univ_mem - · exact mem_of_superset ih st - exact (countable_sInter_mem Sct).mpr ih + induction hs with + | basic hs => exact h hs + | univ => exact univ_mem + | superset _ st ih => exact mem_of_superset ih st + | sInter Sct _ ih => exact (countable_sInter_mem Sct).mpr ih variable (g) diff --git a/Mathlib/Order/Filter/EventuallyConst.lean b/Mathlib/Order/Filter/EventuallyConst.lean index 5ab7e4b3e49cd..6aaac667034f4 100644 --- a/Mathlib/Order/Filter/EventuallyConst.lean +++ b/Mathlib/Order/Filter/EventuallyConst.lean @@ -133,7 +133,7 @@ variable [One β] {s : Set α} {c : β} @[to_additive] lemma of_mulIndicator_const (h : EventuallyConst (s.mulIndicator fun _ ↦ c) l) (hc : c ≠ 1) : EventuallyConst s l := by - simpa [(· ∘ ·), hc, imp_false] using h.comp (· = c) + simpa [Function.comp_def, hc, imp_false] using h.comp (· = c) @[to_additive] theorem mulIndicator_const (h : EventuallyConst s l) (c : β) : diff --git a/Mathlib/Order/Filter/FilterProduct.lean b/Mathlib/Order/Filter/FilterProduct.lean index 99c01de709197..4f014874d2d27 100644 --- a/Mathlib/Order/Filter/FilterProduct.lean +++ b/Mathlib/Order/Filter/FilterProduct.lean @@ -38,7 +38,7 @@ instance instGroupWithZero [GroupWithZero β] : GroupWithZero β* where __ := instMonoidWithZero mul_inv_cancel f := inductionOn f fun f hf ↦ coe_eq.2 <| (φ.em fun y ↦ f y = 0).elim (fun H ↦ (hf <| coe_eq.2 H).elim) fun H ↦ H.mono fun x ↦ mul_inv_cancel₀ - inv_zero := coe_eq.2 <| by simp only [Function.comp, inv_zero, EventuallyEq.rfl] + inv_zero := coe_eq.2 <| by simp only [Function.comp_def, inv_zero, EventuallyEq.rfl] instance instDivisionSemiring [DivisionSemiring β] : DivisionSemiring β* where toSemiring := instSemiring diff --git a/Mathlib/Order/Filter/Germ/Basic.lean b/Mathlib/Order/Filter/Germ/Basic.lean index dd4039e19d250..dee43bb2b8c71 100644 --- a/Mathlib/Order/Filter/Germ/Basic.lean +++ b/Mathlib/Order/Filter/Germ/Basic.lean @@ -512,7 +512,7 @@ instance instAddGroupWithOne [AddGroupWithOne G] : AddGroupWithOne (Germ l G) wh __ := instAddMonoidWithOne __ := instAddGroup intCast_ofNat _ := congrArg ofFun <| by simp - intCast_negSucc _ := congrArg ofFun <| by simp [Function.comp]; rfl + intCast_negSucc _ := congrArg ofFun <| by simp [Function.comp_def]; rfl end Monoid diff --git a/Mathlib/Order/Filter/Lift.lean b/Mathlib/Order/Filter/Lift.lean index 6a193e98904ff..9c69971f95604 100644 --- a/Mathlib/Order/Filter/Lift.lean +++ b/Mathlib/Order/Filter/Lift.lean @@ -249,7 +249,7 @@ theorem lift'_cong (hh : ∀ s ∈ f, h₁ s = h₂ s) : f.lift' h₁ = f.lift' theorem map_lift'_eq {m : β → γ} (hh : Monotone h) : map m (f.lift' h) = f.lift' (image m ∘ h) := calc map m (f.lift' h) = f.lift (map m ∘ 𝓟 ∘ h) := map_lift_eq <| monotone_principal.comp hh - _ = f.lift' (image m ∘ h) := by simp only [comp, Filter.lift', map_principal] + _ = f.lift' (image m ∘ h) := by simp only [comp_def, Filter.lift', map_principal] theorem lift'_map_le {g : Set β → Set γ} {m : α → β} : (map m f).lift' g ≤ f.lift' (g ∘ image m) := lift_map_le @@ -259,7 +259,7 @@ theorem map_lift'_eq2 {g : Set β → Set γ} {m : α → β} (hg : Monotone g) map_lift_eq2 <| monotone_principal.comp hg theorem comap_lift'_eq {m : γ → β} : comap m (f.lift' h) = f.lift' (preimage m ∘ h) := by - simp only [Filter.lift', comap_lift_eq, (· ∘ ·), comap_principal] + simp only [Filter.lift', comap_lift_eq, comp_def, comap_principal] theorem comap_lift'_eq2 {m : β → α} {g : Set β → Set γ} (hg : Monotone g) : (comap m f).lift' g = f.lift' (g ∘ preimage m) := diff --git a/Mathlib/Order/Filter/NAry.lean b/Mathlib/Order/Filter/NAry.lean index 86955a76f0930..881c3b3ed2461 100644 --- a/Mathlib/Order/Filter/NAry.lean +++ b/Mathlib/Order/Filter/NAry.lean @@ -59,7 +59,7 @@ theorem map₂_mk_eq_prod (f : Filter α) (g : Filter β) : map₂ Prod.mk f g = -- lemma image2_mem_map₂_iff (hm : injective2 m) : image2 m s t ∈ map₂ m f g ↔ s ∈ f ∧ t ∈ g := -- ⟨by { rintro ⟨u, v, hu, hv, h⟩, rw image2_subset_image2_iff hm at h, --- exact ⟨mem_of_superset hu h.1, mem_of_superset hv h.2⟩ }, λ h, image2_mem_map₂ h.1 h.2⟩ +-- exact ⟨mem_of_superset hu h.1, mem_of_superset hv h.2⟩ }, fun h ↦ image2_mem_map₂ h.1 h.2⟩ theorem map₂_mono (hf : f₁ ≤ f₂) (hg : g₁ ≤ g₂) : map₂ m f₁ g₁ ≤ map₂ m f₂ g₂ := fun _ ⟨s, hs, t, ht, hst⟩ => ⟨s, hf hs, t, hg ht, hst⟩ @@ -168,7 +168,7 @@ theorem map₂_assoc {m : δ → γ → ε} {n : α → β → δ} {m' : α → map₂ m (map₂ n f g) h = map₂ m' f (map₂ n' g h) := by rw [← map_prod_eq_map₂ n, ← map_prod_eq_map₂ n', map₂_map_left, map₂_map_right, ← map_prod_eq_map₂, ← map_prod_eq_map₂, ← prod_assoc, map_map] - simp only [h_assoc, Function.comp, Equiv.prodAssoc_apply] + simp only [h_assoc, Function.comp_def, Equiv.prodAssoc_apply] theorem map₂_comm {n : β → α → γ} (h_comm : ∀ a b, m a b = n b a) : map₂ m f g = map₂ n g f := (map₂_swap _ _ _).trans <| by simp_rw [h_comm] diff --git a/Mathlib/Order/Filter/Pointwise.lean b/Mathlib/Order/Filter/Pointwise.lean index 3bfff41d94cf1..a6d2ad7077877 100644 --- a/Mathlib/Order/Filter/Pointwise.lean +++ b/Mathlib/Order/Filter/Pointwise.lean @@ -86,6 +86,12 @@ theorem one_mem_one : (1 : Set α) ∈ (1 : Filter α) := theorem pure_one : pure 1 = (1 : Filter α) := rfl +@[to_additive (attr := simp) zero_prod] +theorem one_prod {l : Filter β} : (1 : Filter α) ×ˢ l = map (1, ·) l := pure_prod + +@[to_additive (attr := simp) prod_zero] +theorem prod_one {l : Filter β} : l ×ˢ (1 : Filter α) = map (·, 1) l := prod_pure + @[to_additive (attr := simp)] theorem principal_one : 𝓟 1 = (1 : Filter α) := principal_singleton _ @@ -116,7 +122,7 @@ theorem eventually_one {p : α → Prop} : (∀ᶠ x in 1, p x) ↔ p 1 := theorem tendsto_one {a : Filter β} {f : β → α} : Tendsto f a 1 ↔ ∀ᶠ x in a, f x = 1 := tendsto_pure -@[to_additive (attr := simp) zero_prod_zero] +@[to_additive zero_prod_zero] theorem one_prod_one [One β] : (1 : Filter α) ×ˢ (1 : Filter β) = 1 := prod_pure_pure @@ -589,7 +595,7 @@ variable [DivisionMonoid α] {f g : Filter α} @[to_additive] protected theorem mul_eq_one_iff : f * g = 1 ↔ ∃ a b, f = pure a ∧ g = pure b ∧ a * b = 1 := by refine ⟨fun hfg => ?_, ?_⟩ - · obtain ⟨t₁, h₁, t₂, h₂, h⟩ : (1 : Set α) ∈ f * g := hfg.symm.subst one_mem_one + · obtain ⟨t₁, h₁, t₂, h₂, h⟩ : (1 : Set α) ∈ f * g := hfg.symm ▸ one_mem_one have hfg : (f * g).NeBot := hfg.symm.subst one_neBot rw [(hfg.nonempty_of_mem <| mul_mem_mul h₁ h₂).subset_one_iff, Set.mul_eq_one_iff] at h obtain ⟨a, b, rfl, rfl, h⟩ := h @@ -1042,7 +1048,7 @@ protected def mulAction [Monoid α] [MulAction α β] : MulAction (Filter α) (F @[to_additive "An additive action of an additive monoid on a type `β` gives an additive action on `Filter β`."] protected def mulActionFilter [Monoid α] [MulAction α β] : MulAction α (Filter β) where - mul_smul a b f := by simp only [← Filter.map_smul, map_map, Function.comp, ← mul_smul] + mul_smul a b f := by simp only [← Filter.map_smul, map_map, Function.comp_def, ← mul_smul] one_smul f := by simp only [← Filter.map_smul, one_smul, map_id'] scoped[Pointwise] attribute [instance] Filter.mulAction Filter.addAction Filter.mulActionFilter diff --git a/Mathlib/Order/Filter/Prod.lean b/Mathlib/Order/Filter/Prod.lean index 0202f4d85b27e..523512374f4c3 100644 --- a/Mathlib/Order/Filter/Prod.lean +++ b/Mathlib/Order/Filter/Prod.lean @@ -229,10 +229,11 @@ theorem prod_mono_right (f : Filter α) {g₁ g₂ : Filter β} (hf : g₁ ≤ g theorem prod_comap_comap_eq.{u, v, w, x} {α₁ : Type u} {α₂ : Type v} {β₁ : Type w} {β₂ : Type x} {f₁ : Filter α₁} {f₂ : Filter α₂} {m₁ : β₁ → α₁} {m₂ : β₂ → α₂} : comap m₁ f₁ ×ˢ comap m₂ f₂ = comap (fun p : β₁ × β₂ => (m₁ p.1, m₂ p.2)) (f₁ ×ˢ f₂) := by - simp only [SProd.sprod, Filter.prod, comap_comap, comap_inf, (· ∘ ·)] + simp only [SProd.sprod, Filter.prod, comap_comap, comap_inf, Function.comp_def] theorem prod_comm' : f ×ˢ g = comap Prod.swap (g ×ˢ f) := by - simp only [SProd.sprod, Filter.prod, comap_comap, (· ∘ ·), inf_comm, Prod.swap, comap_inf] + simp only [SProd.sprod, Filter.prod, comap_comap, Function.comp_def, inf_comm, Prod.swap, + comap_inf] theorem prod_comm : f ×ˢ g = map (fun p : β × α => (p.2, p.1)) (g ×ˢ f) := by rw [prod_comm', ← map_swap_eq_comap_swap] @@ -279,13 +280,13 @@ theorem eventually_swap_iff {p : α × β → Prop} : theorem prod_assoc (f : Filter α) (g : Filter β) (h : Filter γ) : map (Equiv.prodAssoc α β γ) ((f ×ˢ g) ×ˢ h) = f ×ˢ (g ×ˢ h) := by - simp_rw [← comap_equiv_symm, SProd.sprod, Filter.prod, comap_inf, comap_comap, inf_assoc, (· ∘ ·), - Equiv.prodAssoc_symm_apply] + simp_rw [← comap_equiv_symm, SProd.sprod, Filter.prod, comap_inf, comap_comap, inf_assoc, + Function.comp_def, Equiv.prodAssoc_symm_apply] theorem prod_assoc_symm (f : Filter α) (g : Filter β) (h : Filter γ) : map (Equiv.prodAssoc α β γ).symm (f ×ˢ (g ×ˢ h)) = (f ×ˢ g) ×ˢ h := by simp_rw [map_equiv_symm, SProd.sprod, Filter.prod, comap_inf, comap_comap, inf_assoc, - Function.comp, Equiv.prodAssoc_apply] + Function.comp_def, Equiv.prodAssoc_apply] theorem tendsto_prodAssoc {h : Filter γ} : Tendsto (Equiv.prodAssoc α β γ) ((f ×ˢ g) ×ˢ h) (f ×ˢ (g ×ˢ h)) := @@ -414,7 +415,7 @@ theorem tendsto_prod_iff' {g' : Filter γ} {s : α → β × γ} : Tendsto s f (g ×ˢ g') ↔ Tendsto (fun n => (s n).1) f g ∧ Tendsto (fun n => (s n).2) f g' := by dsimp only [SProd.sprod] unfold Filter.prod - simp only [tendsto_inf, tendsto_comap_iff, (· ∘ ·)] + simp only [tendsto_inf, tendsto_comap_iff, Function.comp_def] theorem le_prod {f : Filter (α × β)} {g : Filter α} {g' : Filter β} : (f ≤ g ×ˢ g') ↔ Tendsto Prod.fst f g ∧ Tendsto Prod.snd f g' := diff --git a/Mathlib/Order/Filter/SmallSets.lean b/Mathlib/Order/Filter/SmallSets.lean index fba0431ca4a38..fe284b82bd719 100644 --- a/Mathlib/Order/Filter/SmallSets.lean +++ b/Mathlib/Order/Filter/SmallSets.lean @@ -109,7 +109,7 @@ theorem smallSets_principal (s : Set α) : (𝓟 s).smallSets = 𝓟 (𝒫 s) := theorem smallSets_comap_eq_comap_image (l : Filter β) (f : α → β) : (comap f l).smallSets = comap (image f) l.smallSets := by refine (gc_map_comap _).u_comm_of_l_comm (gc_map_comap _) bind_smallSets_gc bind_smallSets_gc ?_ - simp [Function.comp, map_bind, bind_map] + simp [Function.comp_def, map_bind, bind_map] theorem smallSets_comap (l : Filter β) (f : α → β) : (comap f l).smallSets = l.lift' (powerset ∘ preimage f) := diff --git a/Mathlib/Order/Filter/Ultrafilter.lean b/Mathlib/Order/Filter/Ultrafilter.lean index 7d061cff74cf6..3d1ae9a87f5fc 100644 --- a/Mathlib/Order/Filter/Ultrafilter.lean +++ b/Mathlib/Order/Filter/Ultrafilter.lean @@ -19,16 +19,12 @@ In this file we define * `hyperfilter`: the ultrafilter extending the cofinite filter. -/ - universe u v variable {α : Type u} {β : Type v} {γ : Type*} open Set Filter Function -open scoped Classical -open Filter - /-- `Filter α` is an atomic type: for every filter there exists an ultrafilter that is less than or equal to this filter. -/ instance : IsAtomic (Filter α) := @@ -54,7 +50,7 @@ instance : CoeTC (Ultrafilter α) (Filter α) := ⟨Ultrafilter.toFilter⟩ instance : Membership (Set α) (Ultrafilter α) := - ⟨fun s f => s ∈ (f : Filter α)⟩ + ⟨fun f s => s ∈ (f : Filter α)⟩ theorem unique (f : Ultrafilter α) {g : Filter α} (h : g ≤ f) (hne : NeBot g := by infer_instance) : g = f := @@ -119,7 +115,7 @@ theorem diff_mem_iff (f : Ultrafilter α) : s \ t ∈ f ↔ s ∈ f ∧ t ∉ f inter_mem_iff.trans <| and_congr Iff.rfl compl_mem_iff_not_mem /-- If `sᶜ ∉ f ↔ s ∈ f`, then `f` is an ultrafilter. The other implication is given by -`Ultrafilter.compl_not_mem_iff`. -/ +`Ultrafilter.compl_not_mem_iff`. -/ def ofComplNotMemIff (f : Filter α) (h : ∀ s, sᶜ ∉ f ↔ s ∈ f) : Ultrafilter α where toFilter := f neBot' := ⟨fun hf => by simp [hf] at h⟩ diff --git a/Mathlib/Order/Fin/Basic.lean b/Mathlib/Order/Fin/Basic.lean index 3477d9965e7f1..5fac9d7e3e64c 100644 --- a/Mathlib/Order/Fin/Basic.lean +++ b/Mathlib/Order/Fin/Basic.lean @@ -5,7 +5,6 @@ Authors: Robert Y. Lewis, Keeley Hoek -/ import Mathlib.Data.Fin.Basic import Mathlib.Order.Hom.Set -import Mathlib.Init.Data.Nat.Lemmas /-! # `Fin n` forms a bounded linear order diff --git a/Mathlib/Order/Fin/Tuple.lean b/Mathlib/Order/Fin/Tuple.lean index 3327656123b53..428d79cc5cd09 100644 --- a/Mathlib/Order/Fin/Tuple.lean +++ b/Mathlib/Order/Fin/Tuple.lean @@ -25,7 +25,7 @@ lemma pi_lex_lt_cons_cons {x₀ y₀ : α 0} {x y : ∀ i : Fin n, α i.succ} (s : ∀ {i : Fin n.succ}, α i → α i → Prop) : Pi.Lex (· < ·) (@s) (Fin.cons x₀ x) (Fin.cons y₀ y) ↔ s x₀ y₀ ∨ x₀ = y₀ ∧ Pi.Lex (· < ·) (@fun i : Fin n ↦ @s i.succ) x y := by - simp_rw [Pi.Lex, Fin.exists_fin_succ, Fin.cons_succ, Fin.cons_zero, Fin.forall_fin_succ] + simp_rw [Pi.Lex, Fin.exists_fin_succ, Fin.cons_succ, Fin.cons_zero, Fin.forall_iff_succ] simp [and_assoc, exists_and_left] variable [∀ i, Preorder (α i)] @@ -54,7 +54,7 @@ variable {α : Type*} lemma liftFun_vecCons {n : ℕ} (r : α → α → Prop) [IsTrans α r] {f : Fin (n + 1) → α} {a : α} : ((· < ·) ⇒ r) (vecCons a f) (vecCons a f) ↔ r a (f 0) ∧ ((· < ·) ⇒ r) f f := by - simp only [liftFun_iff_succ r, forall_fin_succ, cons_val_succ, cons_val_zero, ← succ_castSucc, + simp only [liftFun_iff_succ r, forall_iff_succ, cons_val_succ, cons_val_zero, ← succ_castSucc, castSucc_zero] variable [Preorder α] {n : ℕ} {f : Fin (n + 1) → α} {a : α} @@ -112,11 +112,54 @@ def OrderIso.piFinTwoIso (α : Fin 2 → Type*) [∀ i, Preorder (α i)] : (∀ def OrderIso.finTwoArrowIso (α : Type*) [Preorder α] : (Fin 2 → α) ≃o α × α := { OrderIso.piFinTwoIso fun _ => α with toEquiv := finTwoArrowEquiv α } +namespace Fin + +/-- Order isomorphism between tuples of length `n + 1` and pairs of an element and a tuple of length +`n` given by separating out the first element of the tuple. + +This is `Fin.cons` as an `OrderIso`. -/ +@[simps!, simps toEquiv] +def consOrderIso (α : Fin (n + 1) → Type*) [∀ i, LE (α i)] : + α 0 × (∀ i, α (succ i)) ≃o ∀ i, α i where + toEquiv := consEquiv α + map_rel_iff' := forall_iff_succ + +/-- Order isomorphism between tuples of length `n + 1` and pairs of an element and a tuple of length +`n` given by separating out the last element of the tuple. + +This is `Fin.snoc` as an `OrderIso`. -/ +@[simps!, simps toEquiv] +def snocOrderIso (α : Fin (n + 1) → Type*) [∀ i, LE (α i)] : + α (last n) × (∀ i, α (castSucc i)) ≃o ∀ i, α i where + toEquiv := snocEquiv α + map_rel_iff' := by simp [Pi.le_def, Prod.le_def, forall_iff_castSucc] + +/-- Order isomorphism between tuples of length `n + 1` and pairs of an element and a tuple of length +`n` given by separating out the `p`-th element of the tuple. + +This is `Fin.insertNth` as an `OrderIso`. -/ +@[simps!, simps toEquiv] +def insertNthOrderIso (α : Fin (n + 1) → Type*) [∀ i, LE (α i)] (p : Fin (n + 1)) : + α p × (∀ i, α (p.succAbove i)) ≃o ∀ i, α i where + toEquiv := insertNthEquiv α p + map_rel_iff' := by simp [Pi.le_def, Prod.le_def, p.forall_iff_succAbove] + +@[simp] lemma insertNthOrderIso_zero (α : Fin (n + 1) → Type*) [∀ i, LE (α i)] : + insertNthOrderIso α 0 = consOrderIso α := by ext; simp [insertNthOrderIso] + +/-- Note this lemma can only be written about non-dependent tuples as `insertNth (last n) = snoc` is +not a definitional equality. -/ +@[simp] lemma insertNthOrderIso_last (n : ℕ) (α : Type*) [LE α] : + insertNthOrderIso (fun _ ↦ α) (last n) = snocOrderIso (fun _ ↦ α) := by ext; simp + +end Fin + /-- Order isomorphism between `Π j : Fin (n + 1), α j` and `α i × Π j : Fin n, α (Fin.succAbove i j)`. -/ +@[deprecated Fin.insertNthOrderIso (since := "2024-07-12")] def OrderIso.piFinSuccAboveIso (α : Fin (n + 1) → Type*) [∀ i, LE (α i)] (i : Fin (n + 1)) : (∀ j, α j) ≃o α i × ∀ j, α (i.succAbove j) where - toEquiv := Equiv.piFinSuccAbove α i + toEquiv := (Fin.insertNthEquiv α i).symm map_rel_iff' := Iff.symm i.forall_iff_succAbove /-- `Fin.succAbove` as an order isomorphism between `Fin n` and `{x : Fin (n + 1) // x ≠ p}`. -/ diff --git a/Mathlib/Order/FixedPoints.lean b/Mathlib/Order/FixedPoints.lean index 1f7d10d048fae..9d6da8b67abcb 100644 --- a/Mathlib/Order/FixedPoints.lean +++ b/Mathlib/Order/FixedPoints.lean @@ -5,6 +5,7 @@ Authors: Johannes Hölzl, Kenny Lau, Yury Kudryashov -/ import Mathlib.Dynamics.FixedPoints.Basic import Mathlib.Order.Hom.Order +import Mathlib.Order.OmegaCompletePartialOrder /-! # Fixed point construction on complete lattices @@ -275,4 +276,21 @@ instance completeLattice : CompleteLattice (fixedPoints f) where le_top x := f.le_gfp x.2.ge bot_le x := f.lfp_le x.2.le +open OmegaCompletePartialOrder fixedPoints + +/-- **Kleene's fixed point Theorem**: The least fixed point in a complete lattice is +the supremum of iterating a function on bottom arbitrary often. -/ +theorem lfp_eq_sSup_iterate (h : Continuous f) : + lfp f = ⨆ n, f^[n] ⊥ := by + apply le_antisymm + · apply lfp_le_fixed + exact Function.mem_fixedPoints.mp (ωSup_iterate_mem_fixedPoint ⟨f, h⟩ ⊥ bot_le) + · apply le_lfp + intro a h_a + exact ωSup_iterate_le_prefixedPoint ⟨f, h⟩ ⊥ bot_le h_a bot_le + +theorem gfp_eq_sInf_iterate (h : Continuous (OrderHom.dual f)) : + gfp f = ⨅ n, f^[n] ⊤ := + lfp_eq_sSup_iterate (OrderHom.dual f) h + end fixedPoints diff --git a/Mathlib/Order/Hom/Basic.lean b/Mathlib/Order/Hom/Basic.lean index 5b9b773385b2c..5a3d3bd055a2d 100644 --- a/Mathlib/Order/Hom/Basic.lean +++ b/Mathlib/Order/Hom/Basic.lean @@ -426,7 +426,7 @@ def coeFnHom : (α →o β) →o α → β where monotone' _ _ h := h /-- Function application `fun f => f a` (for fixed `a`) is a monotone function from the -monotone function space `α →o β` to `β`. See also `Pi.evalOrderHom`. -/ +monotone function space `α →o β` to `β`. See also `Pi.evalOrderHom`. -/ @[simps! (config := .asFn)] def apply (x : α) : (α →o β) →o β := (Pi.evalOrderHom x).comp coeFnHom @@ -447,7 +447,7 @@ def piIso : (α →o ∀ i, π i) ≃o ∀ i, α →o π i where right_inv _ := rfl map_rel_iff' := forall_swap -/-- `Subtype.val` as a bundled monotone function. -/ +/-- `Subtype.val` as a bundled monotone function. -/ @[simps (config := .asFn)] def Subtype.val (p : α → Prop) : Subtype p →o α := ⟨_root_.Subtype.val, fun _ _ h => h⟩ @@ -591,6 +591,18 @@ protected def withBotMap (f : α ↪o β) : WithBot α ↪o WithBot β := protected def withTopMap (f : α ↪o β) : WithTop α ↪o WithTop β := { f.dual.withBotMap.dual with toFun := WithTop.map f } +/-- Coercion `α → WithBot α` as an `OrderEmbedding`. -/ +@[simps (config := .asFn)] +protected def withBotCoe : α ↪o WithBot α where + toFun := .some + inj' := Option.some_injective _ + map_rel_iff' := WithBot.coe_le_coe + +/-- Coercion `α → WithTop α` as an `OrderEmbedding`. -/ +@[simps (config := .asFn)] +protected def withTopCoe : α ↪o WithTop α := + { (OrderEmbedding.withBotCoe (α := αᵒᵈ)).dual with toFun := .some } + /-- To define an order embedding from a partial order to a preorder it suffices to give a function together with a proof that it satisfies `f a ≤ f b ↔ a ≤ b`. -/ @@ -774,9 +786,7 @@ theorem symm_apply_eq (e : α ≃o β) {x : α} {y : β} : e.symm y = x ↔ y = e.toEquiv.symm_apply_eq @[simp] -theorem symm_symm (e : α ≃o β) : e.symm.symm = e := by - ext - rfl +theorem symm_symm (e : α ≃o β) : e.symm.symm = e := rfl theorem symm_bijective : Function.Bijective (OrderIso.symm : (α ≃o β) → β ≃o α) := Function.bijective_iff_has_inverse.mpr ⟨_, symm_symm, symm_symm⟩ @@ -1087,6 +1097,18 @@ theorem OrderIso.map_sup [SemilatticeSup α] [SemilatticeSup β] (f : α ≃o β f (x ⊔ y) = f x ⊔ f y := f.dual.map_inf x y +theorem OrderIso.isMax_apply {α β : Type*} [Preorder α] [Preorder β] (f : α ≃o β) {x : α} : + IsMax (f x) ↔ IsMax x := by + refine ⟨f.strictMono.isMax_of_apply, ?_⟩ + conv_lhs => rw [← f.symm_apply_apply x] + exact f.symm.strictMono.isMax_of_apply + +theorem OrderIso.isMin_apply {α β : Type*} [Preorder α] [Preorder β] (f : α ≃o β) {x : α} : + IsMin (f x) ↔ IsMin x := by + refine ⟨f.strictMono.isMin_of_apply, ?_⟩ + conv_lhs => rw [← f.symm_apply_apply x] + exact f.symm.strictMono.isMin_of_apply + /-- Note that this goal could also be stated `(Disjoint on f) a b` -/ theorem Disjoint.map_orderIso [SemilatticeInf α] [OrderBot α] [SemilatticeInf β] [OrderBot β] {a b : α} (f : α ≃o β) (ha : Disjoint a b) : Disjoint (f a) (f b) := by diff --git a/Mathlib/Order/Hom/CompleteLattice.lean b/Mathlib/Order/Hom/CompleteLattice.lean index 004c9a77b9bef..8fecfd2875b9b 100644 --- a/Mathlib/Order/Hom/CompleteLattice.lean +++ b/Mathlib/Order/Hom/CompleteLattice.lean @@ -118,13 +118,13 @@ section Hom variable [FunLike F α β] @[simp] theorem map_iSup [SupSet α] [SupSet β] [sSupHomClass F α β] (f : F) (g : ι → α) : - f (⨆ i, g i) = ⨆ i, f (g i) := by simp [iSup, ← Set.range_comp, Function.comp] + f (⨆ i, g i) = ⨆ i, f (g i) := by simp [iSup, ← Set.range_comp, Function.comp_def] theorem map_iSup₂ [SupSet α] [SupSet β] [sSupHomClass F α β] (f : F) (g : ∀ i, κ i → α) : f (⨆ (i) (j), g i j) = ⨆ (i) (j), f (g i j) := by simp_rw [map_iSup] @[simp] theorem map_iInf [InfSet α] [InfSet β] [sInfHomClass F α β] (f : F) (g : ι → α) : - f (⨅ i, g i) = ⨅ i, f (g i) := by simp [iInf, ← Set.range_comp, Function.comp] + f (⨅ i, g i) = ⨅ i, f (g i) := by simp [iInf, ← Set.range_comp, Function.comp_def] theorem map_iInf₂ [InfSet α] [InfSet β] [sInfHomClass F α β] (f : F) (g : ∀ i, κ i → α) : f (⨅ (i) (j), g i j) = ⨅ (i) (j), f (g i j) := by simp_rw [map_iInf] diff --git a/Mathlib/Order/Hom/Lattice.lean b/Mathlib/Order/Hom/Lattice.lean index a6513d866da90..94af3f7566504 100644 --- a/Mathlib/Order/Hom/Lattice.lean +++ b/Mathlib/Order/Hom/Lattice.lean @@ -474,6 +474,24 @@ theorem bot_apply [Bot β] (a : α) : (⊥ : SupHom α β) a = ⊥ := theorem top_apply [Top β] (a : α) : (⊤ : SupHom α β) a = ⊤ := rfl +/-- `Subtype.val` as a `SupHom`. -/ +def subtypeVal {P : β → Prop} + (Psup : ∀ ⦃x y : β⦄, P x → P y → P (x ⊔ y)) : + letI := Subtype.semilatticeSup Psup + SupHom {x : β // P x} β := + letI := Subtype.semilatticeSup Psup + .mk Subtype.val (by simp) + +@[simp] +lemma subtypeVal_apply {P : β → Prop} + (Psup : ∀ ⦃x y : β⦄, P x → P y → P (x ⊔ y)) (x : {x : β // P x}) : + subtypeVal Psup x = x := rfl + +@[simp] +lemma subtypeVal_coe {P : β → Prop} + (Psup : ∀ ⦃x y : β⦄, P x → P y → P (x ⊔ y)) : + ⇑(subtypeVal Psup) = Subtype.val := rfl + end SupHom /-! ### Infimum homomorphisms -/ @@ -632,6 +650,24 @@ theorem bot_apply [Bot β] (a : α) : (⊥ : InfHom α β) a = ⊥ := theorem top_apply [Top β] (a : α) : (⊤ : InfHom α β) a = ⊤ := rfl +/-- `Subtype.val` as an `InfHom`. -/ +def subtypeVal {P : β → Prop} + (Pinf : ∀ ⦃x y : β⦄, P x → P y → P (x ⊓ y)) : + letI := Subtype.semilatticeInf Pinf + InfHom {x : β // P x} β := + letI := Subtype.semilatticeInf Pinf + .mk Subtype.val (by simp) + +@[simp] +lemma subtypeVal_apply {P : β → Prop} + (Pinf : ∀ ⦃x y : β⦄, P x → P y → P (x ⊓ y)) (x : {x : β // P x}) : + subtypeVal Pinf x = x := rfl + +@[simp] +lemma subtypeVal_coe {P : β → Prop} + (Pinf : ∀ ⦃x y : β⦄, P x → P y → P (x ⊓ y)) : + ⇑(subtypeVal Pinf) = Subtype.val := rfl + end InfHom /-! ### Finitary supremum homomorphisms -/ @@ -762,6 +798,26 @@ theorem sup_apply (f g : SupBotHom α β) (a : α) : (f ⊔ g) a = f a ⊔ g a : theorem bot_apply (a : α) : (⊥ : SupBotHom α β) a = ⊥ := rfl +/-- `Subtype.val` as a `SupBotHom`. -/ +def subtypeVal {P : β → Prop} + (Pbot : P ⊥) (Psup : ∀ ⦃x y : β⦄, P x → P y → P (x ⊔ y)) : + letI := Subtype.orderBot Pbot + letI := Subtype.semilatticeSup Psup + SupBotHom {x : β // P x} β := + letI := Subtype.orderBot Pbot + letI := Subtype.semilatticeSup Psup + .mk (SupHom.subtypeVal Psup) (by simp [Subtype.coe_bot Pbot]) + +@[simp] +lemma subtypeVal_apply {P : β → Prop} + (Pbot : P ⊥) (Psup : ∀ ⦃x y : β⦄, P x → P y → P (x ⊔ y)) (x : {x : β // P x}) : + subtypeVal Pbot Psup x = x := rfl + +@[simp] +lemma subtypeVal_coe {P : β → Prop} + (Pbot : P ⊥) (Psup : ∀ ⦃x y : β⦄, P x → P y → P (x ⊔ y)) : + ⇑(subtypeVal Pbot Psup) = Subtype.val := rfl + end SupBotHom /-! ### Finitary infimum homomorphisms -/ @@ -893,6 +949,26 @@ theorem inf_apply (f g : InfTopHom α β) (a : α) : (f ⊓ g) a = f a ⊓ g a : theorem top_apply (a : α) : (⊤ : InfTopHom α β) a = ⊤ := rfl +/-- `Subtype.val` as an `InfTopHom`. -/ +def subtypeVal {P : β → Prop} + (Ptop : P ⊤) (Pinf : ∀ ⦃x y : β⦄, P x → P y → P (x ⊓ y)) : + letI := Subtype.orderTop Ptop + letI := Subtype.semilatticeInf Pinf + InfTopHom {x : β // P x} β := + letI := Subtype.orderTop Ptop + letI := Subtype.semilatticeInf Pinf + .mk (InfHom.subtypeVal Pinf) (by simp [Subtype.coe_top Ptop]) + +@[simp] +lemma subtypeVal_apply {P : β → Prop} + (Ptop : P ⊤) (Pinf : ∀ ⦃x y : β⦄, P x → P y → P (x ⊓ y)) (x : {x : β // P x}) : + subtypeVal Ptop Pinf x = x := rfl + +@[simp] +lemma subtypeVal_coe {P : β → Prop} + (Ptop : P ⊤) (Pinf : ∀ ⦃x y : β⦄, P x → P y → P (x ⊓ y)) : + ⇑(subtypeVal Ptop Pinf) = Subtype.val := rfl + end InfTopHom /-! ### Lattice homomorphisms -/ @@ -1013,6 +1089,25 @@ theorem cancel_left {g : LatticeHom β γ} {f₁ f₂ : LatticeHom α β} (hg : ⟨fun h => LatticeHom.ext fun a => hg <| by rw [← LatticeHom.comp_apply, h, LatticeHom.comp_apply], congr_arg _⟩ +/-- `Subtype.val` as a `LatticeHom`. -/ +def subtypeVal {P : β → Prop} + (Psup : ∀ ⦃x y⦄, P x → P y → P (x ⊔ y)) (Pinf : ∀ ⦃x y⦄, P x → P y → P (x ⊓ y)) : + letI := Subtype.lattice Psup Pinf + LatticeHom {x : β // P x} β := + letI := Subtype.lattice Psup Pinf + .mk (SupHom.subtypeVal Psup) (by simp) + +@[simp] +lemma subtypeVal_apply {P : β → Prop} + (Psup : ∀ ⦃x y⦄, P x → P y → P (x ⊔ y)) (Pinf : ∀ ⦃x y⦄, P x → P y → P (x ⊓ y)) + (x : {x : β // P x}) : + subtypeVal Psup Pinf x = x := rfl + +@[simp] +lemma subtypeVal_coe {P : β → Prop} + (Psup : ∀ ⦃x y⦄, P x → P y → P (x ⊔ y)) (Pinf : ∀ ⦃x y⦄, P x → P y → P (x ⊓ y)) : + ⇑(subtypeVal Psup Pinf) = Subtype.val := rfl + end LatticeHom namespace OrderHomClass @@ -1184,6 +1279,27 @@ theorem cancel_left {g : BoundedLatticeHom β γ} {f₁ f₂ : BoundedLatticeHom g.comp f₁ = g.comp f₂ ↔ f₁ = f₂ := ⟨fun h => ext fun a => hg <| by rw [← comp_apply, h, comp_apply], congr_arg _⟩ +/-- `Subtype.val` as a `BoundedLatticeHom`. -/ +def subtypeVal {P : β → Prop} (Pbot : P ⊥) (Ptop : P ⊤) + (Psup : ∀ ⦃x y⦄, P x → P y → P (x ⊔ y)) (Pinf : ∀ ⦃x y⦄, P x → P y → P (x ⊓ y)) : + letI := Subtype.lattice Psup Pinf + letI := Subtype.boundedOrder Pbot Ptop + BoundedLatticeHom {x : β // P x} β := + letI := Subtype.lattice Psup Pinf + letI := Subtype.boundedOrder Pbot Ptop + .mk (.subtypeVal Psup Pinf) (by simp [Subtype.coe_top Ptop]) (by simp [Subtype.coe_bot Pbot]) + +@[simp] +lemma subtypeVal_apply {P : β → Prop} + (Pbot : P ⊥) (Ptop : P ⊤) (Psup : ∀ ⦃x y⦄, P x → P y → P (x ⊔ y)) + (Pinf : ∀ ⦃x y⦄, P x → P y → P (x ⊓ y)) (x : {x : β // P x}) : + subtypeVal Pbot Ptop Psup Pinf x = x := rfl + +@[simp] +lemma subtypeVal_coe {P : β → Prop} (Pbot : P ⊥) (Ptop : P ⊤) + (Psup : ∀ ⦃x y⦄, P x → P y → P (x ⊔ y)) (Pinf : ∀ ⦃x y⦄, P x → P y → P (x ⊓ y)) : + ⇑(subtypeVal Pbot Ptop Psup Pinf) = Subtype.val := rfl + end BoundedLatticeHom /-! ### Dual homs -/ @@ -1660,3 +1776,5 @@ def withTopWithBot' [BoundedOrder β] (f : LatticeHom α β) : map_bot' := rfl end LatticeHom + +set_option linter.style.longFile 1800 diff --git a/Mathlib/Order/Hom/Order.lean b/Mathlib/Order/Hom/Order.lean index 668022c2fa728..c2db9e632bb02 100644 --- a/Mathlib/Order/Hom/Order.lean +++ b/Mathlib/Order/Hom/Order.lean @@ -130,9 +130,11 @@ theorem iterate_sup_le_sup_iff {α : Type*} [SemilatticeSup α] (f : α →o α) · intro n₁ n₂ a₁ a₂ have h' : ∀ n a₁ a₂, f^[n] (a₁ ⊔ a₂) ≤ f^[n] a₁ ⊔ a₂ := by intro n - induction' n with n ih <;> intro a₁ a₂ - · rfl - · calc + induction n with + | zero => intro a₁ a₂; rfl + | succ n ih => + intro a₁ a₂ + calc f^[n + 1] (a₁ ⊔ a₂) = f^[n] (f (a₁ ⊔ a₂)) := Function.iterate_succ_apply f n _ _ ≤ f^[n] (f a₁ ⊔ a₂) := f.mono.iterate n (h a₁ a₂) _ ≤ f^[n] (f a₁) ⊔ a₂ := ih _ _ diff --git a/Mathlib/Order/Ideal.lean b/Mathlib/Order/Ideal.lean index f10e971e09067..3e6b195981b8f 100644 --- a/Mathlib/Order/Ideal.lean +++ b/Mathlib/Order/Ideal.lean @@ -476,7 +476,7 @@ instance : Inhabited (Cofinal P) := mem_gt := fun x ↦ ⟨x, trivial, le_rfl⟩ }⟩ instance : Membership P (Cofinal P) := - ⟨fun x D ↦ x ∈ D.carrier⟩ + ⟨fun D x ↦ x ∈ D.carrier⟩ variable (D : Cofinal P) (x : P) diff --git a/Mathlib/Order/Interval/Basic.lean b/Mathlib/Order/Interval/Basic.lean index bb31af6cef48d..a8d64a2279fcd 100644 --- a/Mathlib/Order/Interval/Basic.lean +++ b/Mathlib/Order/Interval/Basic.lean @@ -101,7 +101,7 @@ instance : Coe (NonemptyInterval α) (Set α) := ⟨fun s => Icc s.fst s.snd⟩ instance (priority := 100) : Membership α (NonemptyInterval α) := - ⟨fun a s => a ∈ (s : Set α)⟩ + ⟨fun s a => a ∈ (s : Set α)⟩ @[simp] theorem mem_mk {hx : x.1 ≤ x.2} : a ∈ mk x hx ↔ x.1 ≤ a ∧ a ≤ x.2 := diff --git a/Mathlib/Order/Interval/Finset/Basic.lean b/Mathlib/Order/Interval/Finset/Basic.lean index 5d9683aba67b6..e0b90ecd39119 100644 --- a/Mathlib/Order/Interval/Finset/Basic.lean +++ b/Mathlib/Order/Interval/Finset/Basic.lean @@ -334,6 +334,12 @@ lemma nonempty_Ici : (Ici a).Nonempty := ⟨a, mem_Ici.2 le_rfl⟩ @[simp, aesop safe apply (rule_sets := [finsetNonempty])] lemma nonempty_Ioi : (Ioi a).Nonempty ↔ ¬ IsMax a := by simp [Finset.Nonempty] +theorem Ici_subset_Ici : Ici a ⊆ Ici b ↔ b ≤ a := by + simpa [← coe_subset] using Set.Ici_subset_Ici + +theorem Ioi_subset_Ioi (h : a ≤ b) : Ioi b ⊆ Ioi a := by + simpa [← coe_subset] using Set.Ioi_subset_Ioi h + variable [LocallyFiniteOrder α] theorem Icc_subset_Ici_self : Icc a b ⊆ Ici a := by @@ -363,6 +369,12 @@ variable [LocallyFiniteOrderBot α] @[simp] lemma nonempty_Iic : (Iic a).Nonempty := ⟨a, mem_Iic.2 le_rfl⟩ @[simp] lemma nonempty_Iio : (Iio a).Nonempty ↔ ¬ IsMin a := by simp [Finset.Nonempty] +theorem Iic_subset_Iic : Iic a ⊆ Iic b ↔ a ≤ b := by + simpa [← coe_subset] using Set.Iic_subset_Iic + +theorem Iio_subset_Iio (h : a ≤ b) : Iio a ⊆ Iio b := by + simpa [← coe_subset] using Set.Iio_subset_Iio h + variable [LocallyFiniteOrder α] theorem Icc_subset_Iic_self : Icc a b ⊆ Iic b := by @@ -844,7 +856,7 @@ theorem eq_of_mem_uIcc_of_mem_uIcc' : b ∈ [[a, c]] → c ∈ [[a, b]] → b = exact Set.eq_of_mem_uIcc_of_mem_uIcc' theorem uIcc_injective_right (a : α) : Injective fun b => [[b, a]] := fun b c h => by - rw [ext_iff] at h + rw [Finset.ext_iff] at h exact eq_of_mem_uIcc_of_mem_uIcc ((h _).1 left_mem_uIcc) ((h _).2 left_mem_uIcc) theorem uIcc_injective_left (a : α) : Injective (uIcc a) := by diff --git a/Mathlib/Order/Interval/Finset/Box.lean b/Mathlib/Order/Interval/Finset/Box.lean index ac0328f341edb..ae26532a1a735 100644 --- a/Mathlib/Order/Interval/Finset/Box.lean +++ b/Mathlib/Order/Interval/Finset/Box.lean @@ -68,7 +68,9 @@ variable {α β : Type*} [OrderedRing α] [OrderedRing β] [LocallyFiniteOrder (box (n + 1) : Finset (α × β)).card = (Icc (-n.succ : α) n.succ).card * (Icc (-n.succ : β) n.succ).card - (Icc (-n : α) n).card * (Icc (-n : β) n).card := by - rw [box_succ_eq_sdiff, card_sdiff (Icc_neg_mono n.le_succ), Prod.card_Icc, Prod.card_Icc]; rfl + rw [box_succ_eq_sdiff, card_sdiff (Icc_neg_mono n.le_succ), Finset.card_Icc_prod, + Finset.card_Icc_prod] + rfl end Prod diff --git a/Mathlib/Order/Interval/Finset/Defs.lean b/Mathlib/Order/Interval/Finset/Defs.lean index 4184e22a98c1e..0a306c3345be5 100644 --- a/Mathlib/Order/Interval/Finset/Defs.lean +++ b/Mathlib/Order/Interval/Finset/Defs.lean @@ -467,7 +467,7 @@ open Lean Elab Term Meta Batteries.ExtendedBinder is `Finset ?α`. See also -* `Init.Set` for the `Set` builder notation elaborator that this elaborator partly overrides. +* `Data.Set.Defs` for the `Set` builder notation elaborator that this elaborator partly overrides. * `Data.Finset.Basic` for the `Finset` builder notation elaborator partly overriding this one for syntax of the form `{x ∈ s | p x}`. * `Data.Fintype.Basic` for the `Finset` builder notation elaborator handling syntax of the form @@ -661,6 +661,8 @@ protected noncomputable def OrderEmbedding.locallyFiniteOrder [LocallyFiniteOrde finset_mem_Ioc a b x := by rw [mem_preimage, mem_Ioc, f.lt_iff_lt, f.le_iff_le] finset_mem_Ioo a b x := by rw [mem_preimage, mem_Ioo, f.lt_iff_lt, f.lt_iff_lt] +/-! ### `OrderDual` -/ + open OrderDual section LocallyFiniteOrder @@ -684,26 +686,30 @@ instance OrderDual.instLocallyFiniteOrder : LocallyFiniteOrder αᵒᵈ where finset_mem_Ioc _ _ _ := (mem_Ico (α := α)).trans and_comm finset_mem_Ioo _ _ _ := (mem_Ioo (α := α)).trans and_comm -theorem Icc_toDual : Icc (toDual a) (toDual b) = (Icc b a).map toDual.toEmbedding := map_refl.symm - -theorem Ico_toDual : Ico (toDual a) (toDual b) = (Ioc b a).map toDual.toEmbedding := map_refl.symm - -theorem Ioc_toDual : Ioc (toDual a) (toDual b) = (Ico b a).map toDual.toEmbedding := map_refl.symm - -theorem Ioo_toDual : Ioo (toDual a) (toDual b) = (Ioo b a).map toDual.toEmbedding := map_refl.symm - -theorem Icc_ofDual (a b : αᵒᵈ) : Icc (ofDual a) (ofDual b) = (Icc b a).map ofDual.toEmbedding := +lemma Finset.Icc_toDual : Icc (toDual a) (toDual b) = (Icc b a).map toDual.toEmbedding := map_refl.symm -theorem Ico_ofDual (a b : αᵒᵈ) : Ico (ofDual a) (ofDual b) = (Ioc b a).map ofDual.toEmbedding := +lemma Finset.Ico_toDual : Ico (toDual a) (toDual b) = (Ioc b a).map toDual.toEmbedding := map_refl.symm -theorem Ioc_ofDual (a b : αᵒᵈ) : Ioc (ofDual a) (ofDual b) = (Ico b a).map ofDual.toEmbedding := +lemma Finset.Ioc_toDual : Ioc (toDual a) (toDual b) = (Ico b a).map toDual.toEmbedding := map_refl.symm -theorem Ioo_ofDual (a b : αᵒᵈ) : Ioo (ofDual a) (ofDual b) = (Ioo b a).map ofDual.toEmbedding := +lemma Finset.Ioo_toDual : Ioo (toDual a) (toDual b) = (Ioo b a).map toDual.toEmbedding := map_refl.symm +lemma Finset.Icc_ofDual (a b : αᵒᵈ) : + Icc (ofDual a) (ofDual b) = (Icc b a).map ofDual.toEmbedding := map_refl.symm + +lemma Finset.Ico_ofDual (a b : αᵒᵈ) : + Ico (ofDual a) (ofDual b) = (Ioc b a).map ofDual.toEmbedding := map_refl.symm + +lemma Finset.Ioc_ofDual (a b : αᵒᵈ) : + Ioc (ofDual a) (ofDual b) = (Ico b a).map ofDual.toEmbedding := map_refl.symm + +lemma Finset.Ioo_ofDual (a b : αᵒᵈ) : + Ioo (ofDual a) (ofDual b) = (Ioo b a).map ofDual.toEmbedding := map_refl.symm + end LocallyFiniteOrder section LocallyFiniteOrderTop @@ -722,16 +728,16 @@ instance OrderDual.instLocallyFiniteOrderBot : LocallyFiniteOrderBot αᵒᵈ wh finset_mem_Iic _ _ := mem_Ici (α := α) finset_mem_Iio _ _ := mem_Ioi (α := α) -theorem Iic_toDual (a : α) : Iic (toDual a) = (Ici a).map toDual.toEmbedding := +lemma Finset.Iic_toDual (a : α) : Iic (toDual a) = (Ici a).map toDual.toEmbedding := map_refl.symm -theorem Iio_toDual (a : α) : Iio (toDual a) = (Ioi a).map toDual.toEmbedding := +lemma Finset.Iio_toDual (a : α) : Iio (toDual a) = (Ioi a).map toDual.toEmbedding := map_refl.symm -theorem Ici_ofDual (a : αᵒᵈ) : Ici (ofDual a) = (Iic a).map ofDual.toEmbedding := +lemma Finset.Ici_ofDual (a : αᵒᵈ) : Ici (ofDual a) = (Iic a).map ofDual.toEmbedding := map_refl.symm -theorem Ioi_ofDual (a : αᵒᵈ) : Ioi (ofDual a) = (Iio a).map ofDual.toEmbedding := +lemma Finset.Ioi_ofDual (a : αᵒᵈ) : Ioi (ofDual a) = (Iio a).map ofDual.toEmbedding := map_refl.symm end LocallyFiniteOrderTop @@ -752,78 +758,81 @@ instance OrderDual.instLocallyFiniteOrderTop : LocallyFiniteOrderTop αᵒᵈ wh finset_mem_Ici _ _ := mem_Iic (α := α) finset_mem_Ioi _ _ := mem_Iio (α := α) -theorem Ici_toDual (a : α) : Ici (toDual a) = (Iic a).map toDual.toEmbedding := +lemma Finset.Ici_toDual (a : α) : Ici (toDual a) = (Iic a).map toDual.toEmbedding := map_refl.symm -theorem Ioi_toDual (a : α) : Ioi (toDual a) = (Iio a).map toDual.toEmbedding := +lemma Finset.Ioi_toDual (a : α) : Ioi (toDual a) = (Iio a).map toDual.toEmbedding := map_refl.symm -theorem Iic_ofDual (a : αᵒᵈ) : Iic (ofDual a) = (Ici a).map ofDual.toEmbedding := +lemma Finset.Iic_ofDual (a : αᵒᵈ) : Iic (ofDual a) = (Ici a).map ofDual.toEmbedding := map_refl.symm -theorem Iio_ofDual (a : αᵒᵈ) : Iio (ofDual a) = (Ioi a).map ofDual.toEmbedding := +lemma Finset.Iio_ofDual (a : αᵒᵈ) : Iio (ofDual a) = (Ioi a).map ofDual.toEmbedding := map_refl.symm end LocallyFiniteOrderTop -namespace Prod +/-! ### `Prod` -/ + +section LocallyFiniteOrder +variable [LocallyFiniteOrder α] [LocallyFiniteOrder β] [@DecidableRel (α × β) (· ≤ ·)] -instance [LocallyFiniteOrder α] [LocallyFiniteOrder β] - [DecidableRel ((· ≤ ·) : α × β → α × β → Prop)] : LocallyFiniteOrder (α × β) := - LocallyFiniteOrder.ofIcc' (α × β) (fun a b => Icc a.fst b.fst ×ˢ Icc a.snd b.snd) fun a b x => by +instance Prod.instLocallyFiniteOrder : LocallyFiniteOrder (α × β) := + LocallyFiniteOrder.ofIcc' (α × β) (fun x y ↦ Icc x.1 y.1 ×ˢ Icc x.2 y.2) fun a b x => by rw [mem_product, mem_Icc, mem_Icc, and_and_and_comm, le_def, le_def] -instance [LocallyFiniteOrderTop α] [LocallyFiniteOrderTop β] - [DecidableRel ((· ≤ ·) : α × β → α × β → Prop)] : LocallyFiniteOrderTop (α × β) := - LocallyFiniteOrderTop.ofIci' (α × β) (fun a => Ici a.fst ×ˢ Ici a.snd) fun a x => by +lemma Finset.Icc_prod_def (x y : α × β) : Icc x y = Icc x.1 y.1 ×ˢ Icc x.2 y.2 := rfl + +lemma Finset.Icc_product_Icc (a₁ a₂ : α) (b₁ b₂ : β) : + Icc a₁ a₂ ×ˢ Icc b₁ b₂ = Icc (a₁, b₁) (a₂, b₂) := rfl + +lemma Finset.card_Icc_prod (x y : α × β) : + (Icc x y).card = (Icc x.1 y.1).card * (Icc x.2 y.2).card := card_product _ _ + +end LocallyFiniteOrder + +section LocallyFiniteOrderTop +variable [LocallyFiniteOrderTop α] [LocallyFiniteOrderTop β] [@DecidableRel (α × β) (· ≤ ·)] + +instance Prod.instLocallyFiniteOrderTop : LocallyFiniteOrderTop (α × β) := + LocallyFiniteOrderTop.ofIci' (α × β) (fun x => Ici x.1 ×ˢ Ici x.2) fun a x => by rw [mem_product, mem_Ici, mem_Ici, le_def] -instance [LocallyFiniteOrderBot α] [LocallyFiniteOrderBot β] - [DecidableRel ((· ≤ ·) : α × β → α × β → Prop)] : LocallyFiniteOrderBot (α × β) := - LocallyFiniteOrderBot.ofIic' (α × β) (fun a => Iic a.fst ×ˢ Iic a.snd) fun a x => by - rw [mem_product, mem_Iic, mem_Iic, le_def] +lemma Finset.Ici_prod_def (x : α × β) : Ici x = Ici x.1 ×ˢ Ici x.2 := rfl +lemma Finset.Ici_product_Ici (a : α) (b : β) : Ici a ×ˢ Ici b = Ici (a, b) := rfl +lemma Finset.card_Ici_prod (x : α × β) : (Ici x).card = (Ici x.1).card * (Ici x.2).card := + card_product _ _ -theorem Icc_eq [LocallyFiniteOrder α] [LocallyFiniteOrder β] - [DecidableRel ((· ≤ ·) : α × β → α × β → Prop)] (p q : α × β) : - Finset.Icc p q = Finset.Icc p.1 q.1 ×ˢ Finset.Icc p.2 q.2 := - rfl +end LocallyFiniteOrderTop -@[simp] -theorem Icc_mk_mk [LocallyFiniteOrder α] [LocallyFiniteOrder β] - [DecidableRel ((· ≤ ·) : α × β → α × β → Prop)] (a₁ a₂ : α) (b₁ b₂ : β) : - Finset.Icc (a₁, b₁) (a₂, b₂) = Finset.Icc a₁ a₂ ×ˢ Finset.Icc b₁ b₂ := - rfl +section LocallyFiniteOrderBot +variable [LocallyFiniteOrderBot α] [LocallyFiniteOrderBot β] [@DecidableRel (α × β) (· ≤ ·)] -theorem card_Icc [LocallyFiniteOrder α] [LocallyFiniteOrder β] - [DecidableRel ((· ≤ ·) : α × β → α × β → Prop)] (p q : α × β) : - (Finset.Icc p q).card = (Finset.Icc p.1 q.1).card * (Finset.Icc p.2 q.2).card := - Finset.card_product _ _ +instance Prod.instLocallyFiniteOrderBot : LocallyFiniteOrderBot (α × β) := + LocallyFiniteOrderBot.ofIic' (α × β) (fun x ↦ Iic x.1 ×ˢ Iic x.2) fun a x ↦ by + rw [mem_product, mem_Iic, mem_Iic, le_def] -end Prod +lemma Finset.Iic_prod_def (x : α × β) : Iic x = Iic x.1 ×ˢ Iic x.2 := rfl +lemma Finset.Iic_product_Iic (a : α) (b : β) : Iic a ×ˢ Iic b = Iic (a, b) := rfl +lemma Finset.card_Iic_prod (x : α × β) : (Iic x).card = (Iic x.1).card * (Iic x.2).card := + card_product _ _ +end LocallyFiniteOrderBot end Preorder -namespace Prod - -variable [Lattice α] [Lattice β] +section Lattice +variable [Lattice α] [Lattice β] [LocallyFiniteOrder α] [LocallyFiniteOrder β] + [@DecidableRel (α × β) (· ≤ ·)] -theorem uIcc_eq [LocallyFiniteOrder α] [LocallyFiniteOrder β] - [DecidableRel ((· ≤ ·) : α × β → α × β → Prop)] (p q : α × β) : - Finset.uIcc p q = Finset.uIcc p.1 q.1 ×ˢ Finset.uIcc p.2 q.2 := - rfl +lemma Finset.uIcc_prod_def (x y : α × β) : uIcc x y = uIcc x.1 y.1 ×ˢ uIcc x.2 y.2 := rfl -@[simp] -theorem uIcc_mk_mk [LocallyFiniteOrder α] [LocallyFiniteOrder β] - [DecidableRel ((· ≤ ·) : α × β → α × β → Prop)] (a₁ a₂ : α) (b₁ b₂ : β) : - Finset.uIcc (a₁, b₁) (a₂, b₂) = Finset.uIcc a₁ a₂ ×ˢ Finset.uIcc b₁ b₂ := - rfl +lemma Finset.uIcc_product_uIcc (a₁ a₂ : α) (b₁ b₂ : β) : + uIcc a₁ a₂ ×ˢ uIcc b₁ b₂ = uIcc (a₁, b₁) (a₂, b₂) := rfl -theorem card_uIcc [LocallyFiniteOrder α] [LocallyFiniteOrder β] - [DecidableRel ((· ≤ ·) : α × β → α × β → Prop)] (p q : α × β) : - (Finset.uIcc p q).card = (Finset.uIcc p.1 q.1).card * (Finset.uIcc p.2 q.2).card := - Prod.card_Icc _ _ +lemma Finset.card_uIcc_prod (x y : α × β) : + (uIcc x y).card = (uIcc x.1 y.1).card * (uIcc x.2 y.2).card := card_product _ _ -end Prod +end Lattice /-! #### `WithTop`, `WithBot` @@ -875,7 +884,7 @@ instance locallyFiniteOrder : LocallyFiniteOrder (WithTop α) where rw [← some_eq_coe, some_mem_insertNone, mem_Ici] | (a : α), (b : α), ⊤ => by simp only [Embedding.some, mem_map, mem_Icc, and_false, exists_const, some, le_top, - top_le_iff] + top_le_iff, reduceCtorEq] | (a : α), (b : α), (x : α) => by simp only [le_eq_subset, Embedding.some, mem_map, mem_Icc, Embedding.coeFn_mk, coe_le_coe] -- This used to be in the above `simp` before leanprover/lean4#2644 diff --git a/Mathlib/Order/Interval/Set/Basic.lean b/Mathlib/Order/Interval/Set/Basic.lean index 9533bfe783faa..1f7aa2076a01d 100644 --- a/Mathlib/Order/Interval/Set/Basic.lean +++ b/Mathlib/Order/Interval/Set/Basic.lean @@ -566,11 +566,13 @@ theorem _root_.IsTop.Iic_eq (h : IsTop a) : Iic a = univ := theorem _root_.IsBot.Ici_eq (h : IsBot a) : Ici a = univ := eq_univ_of_forall h -theorem _root_.IsMax.Ioi_eq (h : IsMax a) : Ioi a = ∅ := - eq_empty_of_subset_empty fun _ => h.not_lt +theorem Ioi_eq_empty_iff : Ioi a = ∅ ↔ IsMax a := by + simp only [isMax_iff_forall_not_lt, eq_empty_iff_forall_not_mem, mem_Ioi] -theorem _root_.IsMin.Iio_eq (h : IsMin a) : Iio a = ∅ := - eq_empty_of_subset_empty fun _ => h.not_lt +theorem Iio_eq_empty_iff : Iio a = ∅ ↔ IsMin a := Ioi_eq_empty_iff (α := αᵒᵈ) + +alias ⟨_, _root_.IsMax.Ioi_eq⟩ := Ioi_eq_empty_iff +alias ⟨_, _root_.IsMin.Iio_eq⟩ := Iio_eq_empty_iff theorem Iic_inter_Ioc_of_le (h : a ≤ c) : Iic a ∩ Ioc b c = Ioc b a := ext fun _ => ⟨fun H => ⟨H.2.1, H.1⟩, fun H => ⟨H.2, H.1, H.2.trans h⟩⟩ @@ -618,8 +620,8 @@ theorem Icc_eq_singleton_iff : Icc a b = {c} ↔ a = c ∧ b = c := by refine ⟨fun h => ?_, ?_⟩ · have hab : a ≤ b := nonempty_Icc.1 (h.symm.subst <| singleton_nonempty c) exact - ⟨eq_of_mem_singleton <| h.subst <| left_mem_Icc.2 hab, - eq_of_mem_singleton <| h.subst <| right_mem_Icc.2 hab⟩ + ⟨eq_of_mem_singleton <| h ▸ left_mem_Icc.2 hab, + eq_of_mem_singleton <| h ▸ right_mem_Icc.2 hab⟩ · rintro ⟨rfl, rfl⟩ exact Icc_self _ @@ -952,7 +954,7 @@ theorem Ico_eq_Ico_iff (h : a₁ < b₁ ∨ a₂ < b₂) : Ico a₁ b₁ = Ico a ⟨fun e => by simp only [Subset.antisymm_iff] at e simp only [le_antisymm_iff] - cases' h with h h <;> + rcases h with h | h <;> simp only [gt_iff_lt, not_lt, Ico_subset_Ico_iff h] at e <;> [ rcases e with ⟨⟨h₁, h₂⟩, e'⟩; rcases e with ⟨e', ⟨h₁, h₂⟩⟩ ] <;> -- Porting note: restore `tauto` @@ -1121,7 +1123,7 @@ theorem Icc_union_Ici' (h₁ : c ≤ b) : Icc a b ∪ Ici c = Ici (min a c) := b theorem Icc_union_Ici (h : c ≤ max a b) : Icc a b ∪ Ici c = Ici (min a c) := by rcases le_or_lt a b with hab | hab <;> simp [hab] at h · exact Icc_union_Ici' h - · cases' h with h h + · rcases h with h | h · simp [*] · have hca : c ≤ a := h.trans hab.le simp [*] @@ -1190,7 +1192,7 @@ theorem Iic_union_Ioo_eq_Iio (h : a < b) : Iic a ∪ Ioo a b = Iio b := theorem Iio_union_Ioo' (h₁ : c < b) : Iio b ∪ Ioo c d = Iio (max b d) := by ext x - cases' lt_or_le x b with hba hba + rcases lt_or_le x b with hba | hba · simp [hba, h₁] · simp only [mem_Iio, mem_union, mem_Ioo, lt_max_iff] refine or_congr Iff.rfl ⟨And.right, ?_⟩ @@ -1221,7 +1223,7 @@ theorem Iic_union_Icc' (h₁ : c ≤ b) : Iic b ∪ Icc c d = Iic (max b d) := b theorem Iic_union_Icc (h : min c d ≤ b) : Iic b ∪ Icc c d = Iic (max b d) := by rcases le_or_lt c d with hcd | hcd <;> simp [hcd] at h · exact Iic_union_Icc' h - · cases' h with h h + · rcases h with h | h · have hdb : d ≤ b := hcd.le.trans h simp [*] · simp [*] @@ -1648,3 +1650,5 @@ instance : NoMaxOrder (Set.Iio x) := exact ⟨⟨b, hb₂⟩, hb₁⟩⟩ end Dense + +set_option linter.style.longFile 1800 diff --git a/Mathlib/Order/Interval/Set/Monotone.lean b/Mathlib/Order/Interval/Set/Monotone.lean index d195cedc05460..4b95aaa3c724e 100644 --- a/Mathlib/Order/Interval/Set/Monotone.lean +++ b/Mathlib/Order/Interval/Set/Monotone.lean @@ -159,30 +159,7 @@ section SuccOrder open Order -variable {α β : Type*} [PartialOrder α] - -theorem StrictMonoOn.Iic_id_le [SuccOrder α] [IsSuccArchimedean α] [OrderBot α] {n : α} {φ : α → α} - (hφ : StrictMonoOn φ (Set.Iic n)) : ∀ m ≤ n, m ≤ φ m := by - revert hφ - refine - Succ.rec_bot (fun n => StrictMonoOn φ (Set.Iic n) → ∀ m ≤ n, m ≤ φ m) - (fun _ _ hm => hm.trans bot_le) ?_ _ - rintro k ih hφ m hm - by_cases hk : IsMax k - · rw [succ_eq_iff_isMax.2 hk] at hm - exact ih (hφ.mono <| Iic_subset_Iic.2 (le_succ _)) _ hm - obtain rfl | h := le_succ_iff_eq_or_le.1 hm - · specialize ih (StrictMonoOn.mono hφ fun x hx => le_trans hx (le_succ _)) k le_rfl - refine le_trans (succ_mono ih) (succ_le_of_lt (hφ (le_succ _) le_rfl ?_)) - rw [lt_succ_iff_eq_or_lt_of_not_isMax hk] - exact Or.inl rfl - · exact ih (StrictMonoOn.mono hφ fun x hx => le_trans hx (le_succ _)) _ h - -theorem StrictMonoOn.Ici_le_id [PredOrder α] [IsPredArchimedean α] [OrderTop α] {n : α} {φ : α → α} - (hφ : StrictMonoOn φ (Set.Ici n)) : ∀ m, n ≤ m → φ m ≤ m := - StrictMonoOn.Iic_id_le (α := αᵒᵈ) fun _ hi _ hj hij => hφ hj hi hij - -variable [Preorder β] {ψ : α → β} +variable {α β : Type*} [PartialOrder α] [Preorder β] {ψ : α → β} /-- A function `ψ` on a `SuccOrder` is strictly monotone before some `n` if for all `m` such that `m < n`, we have `ψ m < ψ (succ m)`. -/ @@ -224,3 +201,32 @@ theorem strictAntiOn_Ici_of_lt_pred [PredOrder α] [IsPredArchimedean α] {n : @strictAntiOn_Iic_of_succ_lt αᵒᵈ βᵒᵈ _ _ ψ _ _ n hψ j hj i hi hij end SuccOrder + +section LinearOrder + +open Order + +variable {α : Type*} [LinearOrder α] + +theorem StrictMonoOn.Iic_id_le [SuccOrder α] [IsSuccArchimedean α] [OrderBot α] {n : α} {φ : α → α} + (hφ : StrictMonoOn φ (Set.Iic n)) : ∀ m ≤ n, m ≤ φ m := by + revert hφ + refine + Succ.rec_bot (fun n => StrictMonoOn φ (Set.Iic n) → ∀ m ≤ n, m ≤ φ m) + (fun _ _ hm => hm.trans bot_le) ?_ _ + rintro k ih hφ m hm + by_cases hk : IsMax k + · rw [succ_eq_iff_isMax.2 hk] at hm + exact ih (hφ.mono <| Iic_subset_Iic.2 (le_succ _)) _ hm + obtain rfl | h := le_succ_iff_eq_or_le.1 hm + · specialize ih (StrictMonoOn.mono hφ fun x hx => le_trans hx (le_succ _)) k le_rfl + refine le_trans (succ_mono ih) (succ_le_of_lt (hφ (le_succ _) le_rfl ?_)) + rw [lt_succ_iff_eq_or_lt_of_not_isMax hk] + exact Or.inl rfl + · exact ih (StrictMonoOn.mono hφ fun x hx => le_trans hx (le_succ _)) _ h + +theorem StrictMonoOn.Ici_le_id [PredOrder α] [IsPredArchimedean α] [OrderTop α] {n : α} {φ : α → α} + (hφ : StrictMonoOn φ (Set.Ici n)) : ∀ m, n ≤ m → φ m ≤ m := + StrictMonoOn.Iic_id_le (α := αᵒᵈ) fun _ hi _ hj hij => hφ hj hi hij + +end LinearOrder diff --git a/Mathlib/Order/Interval/Set/WithBotTop.lean b/Mathlib/Order/Interval/Set/WithBotTop.lean index d5f2e62b5a1b9..a742d1b937b80 100644 --- a/Mathlib/Order/Interval/Set/WithBotTop.lean +++ b/Mathlib/Order/Interval/Set/WithBotTop.lean @@ -5,6 +5,7 @@ Authors: Yury Kudryashov -/ import Mathlib.Data.Set.Image import Mathlib.Order.Interval.Set.Basic +import Mathlib.Order.WithBot /-! # Intervals in `WithTop α` and `WithBot α` diff --git a/Mathlib/Order/IsWellOrderLimitElement.lean b/Mathlib/Order/IsWellOrderLimitElement.lean index 1628b90dac2f6..2d6bde7b9282b 100644 --- a/Mathlib/Order/IsWellOrderLimitElement.lean +++ b/Mathlib/Order/IsWellOrderLimitElement.lean @@ -25,7 +25,7 @@ section variable [IsWellOrder α (· < ·)] /-- Given an element `a : α` in a well ordered set, this is the successor of `a`, -i.e. the smallest element stricly greater than `a` if it exists (or `a` itself otherwise). -/ +i.e. the smallest element strictly greater than `a` if it exists (or `a` itself otherwise). -/ noncomputable def wellOrderSucc (a : α) : α := (IsWellFounded.wf (r := (· < ·))).succ a diff --git a/Mathlib/Order/Iterate.lean b/Mathlib/Order/Iterate.lean index 6e475b270ddfb..05f831756e6a4 100644 --- a/Mathlib/Order/Iterate.lean +++ b/Mathlib/Order/Iterate.lean @@ -39,16 +39,18 @@ lemmas in this section formalize this fact for different inequalities made stric theorem seq_le_seq (hf : Monotone f) (n : ℕ) (h₀ : x 0 ≤ y 0) (hx : ∀ k < n, x (k + 1) ≤ f (x k)) (hy : ∀ k < n, f (y k) ≤ y (k + 1)) : x n ≤ y n := by - induction' n with n ihn - · exact h₀ - · refine (hx _ n.lt_succ_self).trans ((hf <| ihn ?_ ?_).trans (hy _ n.lt_succ_self)) + induction n with + | zero => exact h₀ + | succ n ihn => + refine (hx _ n.lt_succ_self).trans ((hf <| ihn ?_ ?_).trans (hy _ n.lt_succ_self)) · exact fun k hk => hx _ (hk.trans n.lt_succ_self) · exact fun k hk => hy _ (hk.trans n.lt_succ_self) theorem seq_pos_lt_seq_of_lt_of_le (hf : Monotone f) {n : ℕ} (hn : 0 < n) (h₀ : x 0 ≤ y 0) (hx : ∀ k < n, x (k + 1) < f (x k)) (hy : ∀ k < n, f (y k) ≤ y (k + 1)) : x n < y n := by - induction' n with n ihn - · exact hn.false.elim + induction n with + | zero => exact hn.false.elim + | succ n ihn => suffices x n ≤ y n from (hx n n.lt_succ_self).trans_le ((hf this).trans <| hy n n.lt_succ_self) cases n with | zero => exact h₀ diff --git a/Mathlib/Order/KonigLemma.lean b/Mathlib/Order/KonigLemma.lean index 64ff1a4d6bd67..7e5c422c3fc04 100644 --- a/Mathlib/Order/KonigLemma.lean +++ b/Mathlib/Order/KonigLemma.lean @@ -69,7 +69,7 @@ theorem exists_orderEmbedding_covby_of_forall_covby_finite (hfin : ∀ (a : α), obtain ⟨f, hf⟩ := exists_seq_covby_of_forall_covby_finite hfin hb exact ⟨OrderEmbedding.ofStrictMono f (strictMono_nat_of_lt_succ (fun i ↦ (hf.2 i).lt)), hf⟩ -/-- A version of Kőnig's lemma where the sequence starts at the minimum of an infinite order. -/ +/-- A version of Kőnig's lemma where the sequence starts at the minimum of an infinite order. -/ theorem exists_orderEmbedding_covby_of_forall_covby_finite_of_bot [OrderBot α] [Infinite α] (hfin : ∀ (a : α), {x | a ⋖ x}.Finite) : ∃ f : ℕ ↪o α, f 0 = ⊥ ∧ ∀ i, f i ⋖ f (i+1) := exists_orderEmbedding_covby_of_forall_covby_finite hfin (by simpa using infinite_univ) diff --git a/Mathlib/Order/Lattice.lean b/Mathlib/Order/Lattice.lean index 9266523b8ef6a..502fe4375dfb9 100644 --- a/Mathlib/Order/Lattice.lean +++ b/Mathlib/Order/Lattice.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl -/ import Mathlib.Data.Bool.Basic -import Mathlib.Order.Defs import Mathlib.Order.Monotone.Basic import Mathlib.Order.ULift import Mathlib.Tactic.GCongr.Core @@ -197,7 +196,7 @@ instance : Std.Commutative (α := α) (· ⊔ ·) := ⟨sup_comm⟩ theorem sup_assoc (a b c : α) : a ⊔ b ⊔ c = a ⊔ (b ⊔ c) := eq_of_forall_ge_iff fun x => by simp only [sup_le_iff]; rw [and_assoc] -instance : Std.Associative (α := α) (· ⊔ ·) := ⟨sup_assoc⟩ +instance : Std.Associative (α := α) (· ⊔ ·) := ⟨sup_assoc⟩ theorem sup_left_right_swap (a b c : α) : a ⊔ b ⊔ c = c ⊔ b ⊔ a := by rw [sup_comm, sup_comm a, sup_assoc] @@ -902,9 +901,27 @@ theorem map_inf_le [SemilatticeInf α] [SemilatticeInf β] {f : α → β} (h : f (x ⊓ y) ≤ f x ⊓ f y := le_inf (h inf_le_left) (h inf_le_right) +theorem of_map_inf_le_left [SemilatticeInf α] [Preorder β] {f : α → β} + (h : ∀ x y, f (x ⊓ y) ≤ f x) : Monotone f := by + intro x y hxy + rw [← inf_eq_right.2 hxy] + apply h + +theorem of_map_inf_le [SemilatticeInf α] [SemilatticeInf β] {f : α → β} + (h : ∀ x y, f (x ⊓ y) ≤ f x ⊓ f y) : Monotone f := + of_map_inf_le_left fun x y ↦ (h x y).trans inf_le_left + theorem of_map_inf [SemilatticeInf α] [SemilatticeInf β] {f : α → β} (h : ∀ x y, f (x ⊓ y) = f x ⊓ f y) : Monotone f := - fun x y hxy => inf_eq_left.1 <| by rw [← h, inf_eq_left.2 hxy] + of_map_inf_le fun x y ↦ (h x y).le + +theorem of_left_le_map_sup [SemilatticeSup α] [Preorder β] {f : α → β} + (h : ∀ x y, f x ≤ f (x ⊔ y)) : Monotone f := + monotone_dual_iff.1 <| of_map_inf_le_left h + +theorem of_le_map_sup [SemilatticeSup α] [SemilatticeSup β] {f : α → β} + (h : ∀ x y, f x ⊔ f y ≤ f (x ⊔ y)) : Monotone f := + monotone_dual_iff.mp <| of_map_inf_le h theorem of_map_sup [SemilatticeSup α] [SemilatticeSup β] {f : α → β} (h : ∀ x y, f (x ⊔ y) = f x ⊔ f y) : Monotone f := diff --git a/Mathlib/Order/LiminfLimsup.lean b/Mathlib/Order/LiminfLimsup.lean index b407ed6f446a0..63af8fb864d03 100644 --- a/Mathlib/Order/LiminfLimsup.lean +++ b/Mathlib/Order/LiminfLimsup.lean @@ -105,15 +105,28 @@ theorem IsBoundedUnder.comp {l : Filter γ} {q : β → β → Prop} {u : γ → (hv : ∀ a₀ a₁, r a₀ a₁ → q (v a₀) (v a₁)) : l.IsBoundedUnder r u → l.IsBoundedUnder q (v ∘ u) | ⟨a, h⟩ => ⟨v a, show ∀ᶠ x in map u l, q (v x) (v a) from h.mono fun x => hv x a⟩ -/-- A bounded above function `u` is in particular eventually bounded above. -/ -lemma _root_.BddAbove.isBoundedUnder [Preorder α] {f : Filter β} {u : β → α} : - BddAbove (Set.range u) → f.IsBoundedUnder (· ≤ ·) u - | ⟨b, hb⟩ => isBoundedUnder_of ⟨b, by simpa [mem_upperBounds] using hb⟩ +section Preorder +variable [Preorder α] {f : Filter β} {u : β → α} {s : Set β} -/-- A bounded below function `u` is in particular eventually bounded below. -/ -lemma _root_.BddBelow.isBoundedUnder [Preorder α] {f : Filter β} {u : β → α} : - BddBelow (Set.range u) → f.IsBoundedUnder (· ≥ ·) u - | ⟨b, hb⟩ => isBoundedUnder_of ⟨b, by simpa [mem_lowerBounds] using hb⟩ +lemma isBoundedUnder_iff_eventually_bddAbove : + f.IsBoundedUnder (· ≤ ·) u ↔ ∃ s, BddAbove (u '' s) ∧ ∀ᶠ x in f, x ∈ s := by + constructor + · rintro ⟨b, hb⟩ + exact ⟨{a | u a ≤ b}, ⟨b, by rintro _ ⟨a, ha, rfl⟩; exact ha⟩, hb⟩ + · rintro ⟨s, ⟨b, hb⟩, hs⟩ + exact ⟨b, hs.mono <| by simpa [upperBounds] using hb⟩ + +lemma isBoundedUnder_iff_eventually_bddBelow : + f.IsBoundedUnder (· ≥ ·) u ↔ ∃ s, BddBelow (u '' s) ∧ ∀ᶠ x in f, x ∈ s := + isBoundedUnder_iff_eventually_bddAbove (α := αᵒᵈ) + +lemma _root_.BddAbove.isBoundedUnder (hs : s ∈ f) (hu : BddAbove (u '' s)) : + f.IsBoundedUnder (· ≤ ·) u := isBoundedUnder_iff_eventually_bddAbove.2 ⟨_, hu, hs⟩ + +lemma _root_.BddBelow.isBoundedUnder (hs : s ∈ f) (hu : BddBelow (u '' s)) : + f.IsBoundedUnder (· ≥ ·) u := isBoundedUnder_iff_eventually_bddBelow.2 ⟨_, hu, hs⟩ + +end Preorder theorem _root_.Monotone.isBoundedUnder_le_comp [Preorder α] [Preorder β] {l : Filter γ} {u : γ → α} {v : α → β} (hv : Monotone v) (hl : l.IsBoundedUnder (· ≤ ·) u) : @@ -1079,11 +1092,11 @@ theorem liminf_sdiff [NeBot f] (a : α) : liminf u f \ a = liminf (fun b => u b theorem sdiff_limsup [NeBot f] (a : α) : a \ limsup u f = liminf (fun b => a \ u b) f := by rw [← compl_inj_iff] - simp only [sdiff_eq, liminf_compl, (· ∘ ·), compl_inf, compl_compl, sup_limsup] + simp only [sdiff_eq, liminf_compl, comp_def, compl_inf, compl_compl, sup_limsup] theorem sdiff_liminf (a : α) : a \ liminf u f = limsup (fun b => a \ u b) f := by rw [← compl_inj_iff] - simp only [sdiff_eq, limsup_compl, (· ∘ ·), compl_inf, compl_compl, sup_liminf] + simp only [sdiff_eq, limsup_compl, comp_def, compl_inf, compl_compl, sup_liminf] end CompleteBooleanAlgebra @@ -1694,3 +1707,5 @@ lemma Antitone.isCoboundedUnder_ge_of_isCobounded {f : R → S} (f_decr : Antito Monotone.isCoboundedUnder_le_of_isCobounded (S := Sᵒᵈ) f_decr cobdd end frequently_bounded + +set_option linter.style.longFile 1800 diff --git a/Mathlib/Order/ModularLattice.lean b/Mathlib/Order/ModularLattice.lean index 0f3392396dadb..76b1789fce3e3 100644 --- a/Mathlib/Order/ModularLattice.lean +++ b/Mathlib/Order/ModularLattice.lean @@ -221,11 +221,11 @@ theorem inf_lt_inf_of_lt_of_sup_le_sup (hxy : x < y) (hinf : y ⊔ z ≤ x ⊔ z /-- 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 γ] - (h₁ : WellFounded ((· < ·) : β → β → Prop)) (h₂ : WellFounded ((· < ·) : γ → γ → Prop)) (K : α) + [h₁ : WellFoundedLT β] [h₂ : WellFoundedLT γ] (K : α) (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) : - WellFounded ((· < ·) : α → α → Prop) := - Subrelation.wf + 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, @@ -234,17 +234,17 @@ theorem wellFounded_lt_exact_sequence {β γ : Type*} [PartialOrder β] [Preorde 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₁.prod_lex h₂)) + (InvImage.wf _ (h₁.wf.prod_lex h₂.wf))⟩ /-- 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. -/ + `N` and `M / N` are both Noetherian, then `M` is Noetherian. -/ theorem wellFounded_gt_exact_sequence {β γ : Type*} [Preorder β] [PartialOrder γ] - (h₁ : WellFounded ((· > ·) : β → β → Prop)) (h₂ : WellFounded ((· > ·) : γ → γ → Prop)) (K : α) + [WellFoundedGT β] [WellFoundedGT γ] (K : α) (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) : - WellFounded ((· > ·) : α → α → Prop) := + WellFoundedGT α := wellFounded_lt_exact_sequence (α := αᵒᵈ) (β := γᵒᵈ) (γ := βᵒᵈ) - h₂ h₁ K g₁ g₂ f₁ f₂ gi.dual gci.dual hg hf + K g₁ g₂ f₁ f₂ gi.dual gci.dual hg hf /-- The diamond isomorphism between the intervals `[a ⊓ b, a]` and `[b, a ⊔ b]` -/ @[simps] diff --git a/Mathlib/Order/Monotone/Basic.lean b/Mathlib/Order/Monotone/Basic.lean index 21ba540d248fb..c1a6c68abafef 100644 --- a/Mathlib/Order/Monotone/Basic.lean +++ b/Mathlib/Order/Monotone/Basic.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad, Mario Carneiro, Yaël Dillies -/ import Mathlib.Logic.Function.Iterate -import Mathlib.Init.Data.Int.Order +import Mathlib.Data.Int.Order.Basic import Mathlib.Order.Compare import Mathlib.Order.Max import Mathlib.Order.RelClasses @@ -541,9 +541,10 @@ theorem StrictAnti.isMin_of_apply (hf : StrictAnti f) (ha : IsMax (f a)) : IsMin lemma StrictMono.add_le_nat {f : ℕ → ℕ} (hf : StrictMono f) (m n : ℕ) : m + f n ≤ f (m + n) := by rw [Nat.add_comm m, Nat.add_comm m] - induction' m with m ih - · rw [Nat.add_zero, Nat.add_zero] - · rw [← Nat.add_assoc, ← Nat.add_assoc, Nat.succ_le] + induction m with + | zero => rw [Nat.add_zero, Nat.add_zero] + | succ m ih => + rw [← Nat.add_assoc, ← Nat.add_assoc, Nat.succ_le] exact ih.trans_lt (hf (n + m).lt_succ_self) protected theorem StrictMono.ite' (hf : StrictMono f) (hg : StrictMono g) {p : α → Prop} @@ -876,8 +877,9 @@ variable [Preorder α] theorem Nat.rel_of_forall_rel_succ_of_le_of_lt (r : β → β → Prop) [IsTrans β r] {f : ℕ → β} {a : ℕ} (h : ∀ n, a ≤ n → r (f n) (f (n + 1))) ⦃b c : ℕ⦄ (hab : a ≤ b) (hbc : b < c) : r (f b) (f c) := by - induction' hbc with k b_lt_k r_b_k - exacts [h _ hab, _root_.trans r_b_k (h _ (hab.trans_lt b_lt_k).le)] + induction hbc with + | refl => exact h _ hab + | step b_lt_k r_b_k => exact _root_.trans r_b_k (h _ (hab.trans_lt b_lt_k).le) theorem Nat.rel_of_forall_rel_succ_of_le_of_le (r : β → β → Prop) [IsRefl β r] [IsTrans β r] {f : ℕ → β} {a : ℕ} (h : ∀ n, a ≤ n → r (f n) (f (n + 1))) @@ -937,11 +939,9 @@ theorem Int.rel_of_forall_rel_succ_of_lt (r : β → β → Prop) [IsTrans β r] (h : ∀ n, r (f n) (f (n + 1))) ⦃a b : ℤ⦄ (hab : a < b) : r (f a) (f b) := by rcases lt.dest hab with ⟨n, rfl⟩ clear hab - induction' n with n ihn - · rw [Int.ofNat_one] - apply h - · rw [Int.ofNat_succ, ← Int.add_assoc] - exact _root_.trans ihn (h _) + induction n with + | zero => rw [Int.ofNat_one]; apply h + | succ n ihn => rw [Int.ofNat_succ, ← Int.add_assoc]; exact _root_.trans ihn (h _) theorem Int.rel_of_forall_rel_succ_of_le (r : β → β → Prop) [IsRefl β r] [IsTrans β r] {f : ℤ → β} (h : ∀ n, r (f n) (f (n + 1))) ⦃a b : ℤ⦄ (hab : a ≤ b) : r (f a) (f b) := diff --git a/Mathlib/Order/Monotone/Monovary.lean b/Mathlib/Order/Monotone/Monovary.lean index 483265ced58b1..4c25c914b2698 100644 --- a/Mathlib/Order/Monotone/Monovary.lean +++ b/Mathlib/Order/Monotone/Monovary.lean @@ -3,7 +3,7 @@ Copyright (c) 2021 Yaël Dillies. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies -/ -import Mathlib.Data.Set.Defs +import Mathlib.Data.Set.Operations import Mathlib.Order.Lattice /-! @@ -249,7 +249,7 @@ end PartialOrder variable [LinearOrder ι] /- Porting note: Due to a bug in `alias`, many of the below lemmas have dot notation removed in the -proof-/ +proof -/ protected theorem Monotone.monovary (hf : Monotone f) (hg : Monotone g) : Monovary f g := fun _ _ hij => hf (hg.reflect_lt hij).le diff --git a/Mathlib/Order/Notation.lean b/Mathlib/Order/Notation.lean index cccd2eb9733f8..3f7c605518e6d 100644 --- a/Mathlib/Order/Notation.lean +++ b/Mathlib/Order/Notation.lean @@ -3,7 +3,7 @@ Copyright (c) 2017 Johannes Hölzl. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl, Yury Kudryashov, Yaël Dillies -/ -import Mathlib.Tactic.Basic +import Mathlib.Tactic.TypeStar import Mathlib.Tactic.Simps.NotationClass /-! diff --git a/Mathlib/Order/OmegaCompletePartialOrder.lean b/Mathlib/Order/OmegaCompletePartialOrder.lean index 79843f6802093..ccc81e97ad763 100644 --- a/Mathlib/Order/OmegaCompletePartialOrder.lean +++ b/Mathlib/Order/OmegaCompletePartialOrder.lean @@ -1,11 +1,13 @@ /- Copyright (c) 2020 Simon Hudon. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Simon Hudon +Authors: Simon Hudon, Ira Fesefeldt -/ import Mathlib.Control.Monad.Basic +import Mathlib.Dynamics.FixedPoints.Basic import Mathlib.Order.Chain import Mathlib.Order.Hom.Order +import Mathlib.Order.Iterate import Mathlib.Order.Part /-! @@ -76,7 +78,7 @@ instance [Inhabited α] : Inhabited (Chain α) := ⟨⟨default, fun _ _ _ => le_rfl⟩⟩ instance : Membership α (Chain α) := - ⟨fun a (c : ℕ →o α) => ∃ i, a = c i⟩ + ⟨fun (c : ℕ →o α) a => ∃ i, a = c i⟩ variable (c c' : Chain α) variable (f : α →o β) @@ -727,7 +729,7 @@ instance : OmegaCompletePartialOrder (α →𝒄 β) := namespace Prod -/-- The application of continuous functions as a continuous function. -/ +/-- The application of continuous functions as a continuous function. -/ @[simps] def apply : (α →𝒄 β) × α →𝒄 β where toFun f := f.1 f.2 @@ -795,4 +797,62 @@ noncomputable def seq {β γ : Type v} (f : α →𝒄 Part (β → γ)) (g : α end ContinuousHom +namespace fixedPoints + +open Function + +/-- Iteration of a function on an initial element interpreted as a chain. -/ +def iterateChain (f : α →o α) (x : α) (h : x ≤ f x) : Chain α := + ⟨fun n => f^[n] x, f.monotone.monotone_iterate_of_le_map h⟩ + +variable (f : α →𝒄 α) (x : α) + +/-- The supremum of iterating a function on x arbitrary often is a fixed point -/ +theorem ωSup_iterate_mem_fixedPoint (h : x ≤ f x) : + ωSup (iterateChain f x h) ∈ fixedPoints f := by + rw [mem_fixedPoints, IsFixedPt, f.continuous] + apply le_antisymm + · apply ωSup_le + intro n + simp only [Chain.map_coe, OrderHomClass.coe_coe, comp_apply] + have : iterateChain f x h (n.succ) = f (iterateChain f x h n) := + Function.iterate_succ_apply' .. + rw [← this] + apply le_ωSup + · apply ωSup_le + rintro (_ | n) + · apply le_trans h + change ((iterateChain f x h).map f) 0 ≤ ωSup ((iterateChain f x h).map (f : α →o α)) + apply le_ωSup + · have : iterateChain f x h (n.succ) = (iterateChain f x h).map f n := + Function.iterate_succ_apply' .. + rw [this] + apply le_ωSup + +/-- The supremum of iterating a function on x arbitrary often is smaller than any prefixed point. + +A prefixed point is a value `a` with `f a ≤ a`. -/ +theorem ωSup_iterate_le_prefixedPoint (h : x ≤ f x) {a : α} + (h_a : f a ≤ a) (h_x_le_a : x ≤ a) : + ωSup (iterateChain f x h) ≤ a := by + apply ωSup_le + intro n + induction n with + | zero => exact h_x_le_a + | succ n h_ind => + have : iterateChain f x h (n.succ) = f (iterateChain f x h n) := + Function.iterate_succ_apply' .. + rw [this] + exact le_trans (f.monotone h_ind) h_a + +/-- The supremum of iterating a function on x arbitrary often is smaller than any fixed point. -/ +theorem ωSup_iterate_le_fixedPoint (h : x ≤ f x) {a : α} + (h_a : a ∈ fixedPoints f) (h_x_le_a : x ≤ a) : + ωSup (iterateChain f x h) ≤ a := by + rw [mem_fixedPoints] at h_a + obtain h_a := Eq.le h_a + exact ωSup_iterate_le_prefixedPoint f x h h_a h_x_le_a + +end fixedPoints + end OmegaCompletePartialOrder diff --git a/Mathlib/Order/Partition/Finpartition.lean b/Mathlib/Order/Partition/Finpartition.lean index 13a431112afd8..de3531685cda0 100644 --- a/Mathlib/Order/Partition/Finpartition.lean +++ b/Mathlib/Order/Partition/Finpartition.lean @@ -67,7 +67,7 @@ structure Finpartition [Lattice α] [OrderBot α] (a : α) where supIndep : parts.SupIndep id /-- The supremum of the partition is `a` -/ sup_parts : parts.sup id = a - /-- No element of the partition is bottom-/ + /-- No element of the partition is bottom -/ not_bot_mem : ⊥ ∉ parts deriving DecidableEq @@ -465,7 +465,8 @@ def part (a : α) : Finset α := if ha : a ∈ s then choose (hp := P.existsUniq lemma part_mem (ha : a ∈ s) : P.part a ∈ P.parts := by simp [part, ha, choose_mem] -lemma mem_part (ha : a ∈ s) : a ∈ P.part a := by simp [part, ha, choose_property] +lemma mem_part (ha : a ∈ s) : a ∈ P.part a := by + simp [part, ha, choose_property (p := fun s => a ∈ s) P.parts (P.existsUnique_mem ha)] lemma part_eq_of_mem (ht : t ∈ P.parts) (hat : a ∈ t) : P.part a = t := by apply P.eq_of_mem_parts (P.part_mem _) ht (P.mem_part _) hat <;> exact mem_of_subset (P.le ht) hat diff --git a/Mathlib/Order/RelClasses.lean b/Mathlib/Order/RelClasses.lean index accea482ee544..dcfbcc1773326 100644 --- a/Mathlib/Order/RelClasses.lean +++ b/Mathlib/Order/RelClasses.lean @@ -12,12 +12,13 @@ import Batteries.WF /-! # Unbundled relation classes -In this file we prove some properties of `Is*` classes defined in `Init.Algebra.Classes`. The main +In this file we prove some properties of `Is*` classes defined in `Order.Defs`. The main difference between these classes and the usual order classes (`Preorder` etc) is that usual classes extend `LE` and/or `LT` while these classes take a relation as an explicit argument. -/ +set_option linter.deprecated false universe u v @@ -40,21 +41,21 @@ theorem antisymm_iff [IsRefl α r] [IsAntisymm α r] {a b : α} : r a b ∧ r b /-- A version of `antisymm` with `r` explicit. -This lemma matches the lemmas from lean core in `Init.Algebra.Classes`, but is missing there. -/ +This lemma matches the lemmas from lean core in `Init.Algebra.Classes`, but is missing there. -/ @[elab_without_expected_type] theorem antisymm_of (r : α → α → Prop) [IsAntisymm α r] {a b : α} : r a b → r b a → a = b := antisymm /-- A version of `antisymm'` with `r` explicit. -This lemma matches the lemmas from lean core in `Init.Algebra.Classes`, but is missing there. -/ +This lemma matches the lemmas from lean core in `Init.Algebra.Classes`, but is missing there. -/ @[elab_without_expected_type] theorem antisymm_of' (r : α → α → Prop) [IsAntisymm α r] {a b : α} : r a b → r b a → b = a := antisymm' /-- A version of `comm` with `r` explicit. -This lemma matches the lemmas from lean core in `Init.Algebra.Classes`, but is missing there. -/ +This lemma matches the lemmas from lean core in `Init.Algebra.Classes`, but is missing there. -/ theorem comm_of (r : α → α → Prop) [IsSymm α r] {a b : α} : r a b ↔ r b a := comm @@ -88,9 +89,11 @@ theorem IsStrictOrder.swap (r) [IsStrictOrder α r] : IsStrictOrder α (swap r) theorem IsPartialOrder.swap (r) [IsPartialOrder α r] : IsPartialOrder α (swap r) := { @IsPreorder.swap α r _, @IsAntisymm.swap α r _ with } +@[deprecated (since := "2024-07-30")] theorem IsTotalPreorder.swap (r) [IsTotalPreorder α r] : IsTotalPreorder α (swap r) := { @IsPreorder.swap α r _, @IsTotal.swap α r _ with } +@[deprecated (since := "2024-07-30")] theorem IsLinearOrder.swap (r) [IsLinearOrder α r] : IsLinearOrder α (swap r) := { @IsPartialOrder.swap α r _, @IsTotal.swap α r _ with } @@ -196,7 +199,7 @@ theorem IsStrictTotalOrder.swap (r) [IsStrictTotalOrder α r] : IsStrictTotalOrd /-- A connected order is one satisfying the condition `a < c → a < b ∨ b < c`. This is recognizable as an intuitionistic substitute for `a ≤ b ∨ b ≤ a` on the constructive reals, and is also known as negative transitivity, - since the contrapositive asserts transitivity of the relation `¬ a < b`. -/ + since the contrapositive asserts transitivity of the relation `¬ a < b`. -/ class IsOrderConnected (α : Type u) (lt : α → α → Prop) : Prop where /-- A connected order is one satisfying the condition `a < c → a < b ∨ b < c`. -/ conn : ∀ a b c, lt a c → lt a b ∨ lt b c @@ -219,6 +222,7 @@ instance (priority := 100) isStrictOrderConnected_of_isStrictTotalOrder [IsStric fun o ↦ o.elim (fun e ↦ e ▸ h) fun h' ↦ _root_.trans h' h⟩ -- see Note [lower instance priority] +@[deprecated (since := "2024-07-30")] instance (priority := 100) isStrictTotalOrder_of_isStrictTotalOrder [IsStrictTotalOrder α r] : IsStrictWeakOrder α r := { isStrictWeakOrder_of_isOrderConnected with } @@ -457,7 +461,7 @@ instance [IsWellOrder α r] [IsWellOrder β s] : IsWellOrder (α × β) (Prod.Le | Or.inr (Or.inr h) => Or.inr <| Or.inr <| Prod.Lex.right _ h | Or.inr (Or.inl (.refl _)) => Or.inr <| Or.inl rfl trans a b c h₁ h₂ := by - cases' h₁ with a₁ a₂ b₁ b₂ ab a₁ b₁ b₂ ab <;> cases' h₂ with _ _ c₁ c₂ bc _ _ c₂ bc + rcases h₁ with ⟨a₂, b₂, ab⟩ | ⟨a₁, ab⟩ <;> rcases h₂ with ⟨c₁, c₂, bc⟩ | ⟨c₂, bc⟩ exacts [.left _ _ (_root_.trans ab bc), .left _ _ ab, .left _ _ bc, .right _ (_root_.trans ab bc)] @@ -772,10 +776,8 @@ instance LE.isTotal [LinearOrder α] : IsTotal α (· ≤ ·) := instance [LinearOrder α] : IsTotal α (· ≥ ·) := IsTotal.swap _ --- Porting note: this was `by infer_instance` before -instance [LinearOrder α] : IsTotalPreorder α (· ≤ ·) where - -instance [LinearOrder α] : IsTotalPreorder α (· ≥ ·) where +@[deprecated (since := "2024-08-22")] instance [LinearOrder α] : IsTotalPreorder α (· ≤ ·) where +@[deprecated (since := "2024-08-22")] instance [LinearOrder α] : IsTotalPreorder α (· ≥ ·) where instance [LinearOrder α] : IsLinearOrder α (· ≤ ·) where @@ -797,8 +799,10 @@ instance [LinearOrder α] : IsStrictTotalOrder α (· < ·) where instance [LinearOrder α] : IsOrderConnected α (· < ·) := by infer_instance +@[deprecated (since := "2024-07-30")] instance [LinearOrder α] : IsIncompTrans α (· < ·) := by infer_instance +@[deprecated (since := "2024-07-30")] instance [LinearOrder α] : IsStrictWeakOrder α (· < ·) := by infer_instance theorem transitive_le [Preorder α] : Transitive (@LE.le α _) := diff --git a/Mathlib/Order/RelIso/Basic.lean b/Mathlib/Order/RelIso/Basic.lean index d319840aac665..bfbc41e545f91 100644 --- a/Mathlib/Order/RelIso/Basic.lean +++ b/Mathlib/Order/RelIso/Basic.lean @@ -81,13 +81,17 @@ protected theorem isAsymm [RelHomClass F r s] (f : F) : ∀ [IsAsymm β s], IsAs protected theorem acc [RelHomClass F r s] (f : F) (a : α) : Acc s (f a) → Acc r a := by generalize h : f a = b intro ac - induction' ac with _ H IH generalizing a + induction ac generalizing a with | intro _ H IH => ?_ subst h exact ⟨_, fun a' h => IH (f a') (map_rel f h) _ rfl⟩ protected theorem wellFounded [RelHomClass F r s] (f : F) : WellFounded s → WellFounded r | ⟨H⟩ => ⟨fun _ => RelHomClass.acc f _ (H _)⟩ +protected theorem isWellFounded [RelHomClass F r s] (f : F) [IsWellFounded β s] : + IsWellFounded α r := + ⟨RelHomClass.wellFounded f IsWellFounded.wf⟩ + end RelHomClass namespace RelHom @@ -323,7 +327,7 @@ protected theorem isStrictTotalOrder : ∀ (_ : r ↪r s) [IsStrictTotalOrder β protected theorem acc (f : r ↪r s) (a : α) : Acc s (f a) → Acc r a := by generalize h : f a = b intro ac - induction' ac with _ H IH generalizing a + induction ac generalizing a with | intro _ H IH => ?_ subst h exact ⟨_, fun a' h => IH (f a') (f.map_rel_iff.2 h) _ rfl⟩ @@ -374,7 +378,7 @@ theorem acc_lift₂_iff [Setoid α] {r : α → α → Prop} constructor · exact RelHomClass.acc (Quotient.mkRelHom H) a · intro ac - induction' ac with _ _ IH + induction ac with | intro _ _ IH => ?_ refine ⟨_, fun q h => ?_⟩ obtain ⟨a', rfl⟩ := q.exists_rep exact IH a' h @@ -697,7 +701,7 @@ lexicographic orders on the sum. def sumLexCongr {α₁ α₂ β₁ β₂ r₁ r₂ s₁ s₂} (e₁ : @RelIso α₁ β₁ r₁ s₁) (e₂ : @RelIso α₂ β₂ r₂ s₂) : Sum.Lex r₁ r₂ ≃r Sum.Lex s₁ s₂ := ⟨Equiv.sumCongr e₁.toEquiv e₂.toEquiv, @fun a b => by - cases' e₁ with f hf; cases' e₂ with g hg; cases a <;> cases b <;> simp [hf, hg]⟩ + obtain ⟨f, hf⟩ := e₁; obtain ⟨g, hg⟩ := e₂; cases a <;> cases b <;> simp [hf, hg]⟩ /-- Given relation isomorphisms `r₁ ≃r s₁` and `r₂ ≃r s₂`, construct a relation isomorphism for the lexicographic orders on the product. diff --git a/Mathlib/Order/RelSeries.lean b/Mathlib/Order/RelSeries.lean index 95ce68bb9c968..8650ab8aa8b4d 100644 --- a/Mathlib/Order/RelSeries.lean +++ b/Mathlib/Order/RelSeries.lean @@ -3,13 +3,11 @@ Copyright (c) 2023 Jujian Zhang. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jujian Zhang, Fangming Li -/ -import Mathlib.Algebra.Ring.Int -import Mathlib.Data.List.Chain -import Mathlib.Data.List.OfFn +import Mathlib.Algebra.Order.Ring.Nat +import Mathlib.Data.Fintype.Card +import Mathlib.Data.Fintype.Pi +import Mathlib.Data.Fintype.Sigma import Mathlib.Data.Rel -import Mathlib.Order.Fin.Basic -import Mathlib.Tactic.Abel -import Mathlib.Tactic.Linarith /-! # Series of a relation @@ -102,7 +100,7 @@ lemma toList_chain' (x : RelSeries r) : x.toList.Chain' r := by lemma toList_ne_nil (x : RelSeries r) : x.toList ≠ [] := fun m => List.eq_nil_iff_forall_not_mem.mp m (x 0) <| (List.mem_ofFn _ _).mpr ⟨_, rfl⟩ -/-- Every nonempty list satisfying the chain condition gives a relation series-/ +/-- Every nonempty list satisfying the chain condition gives a relation series -/ @[simps] def fromListChain' (x : List α) (x_ne_nil : x ≠ []) (hx : x.Chain' r) : RelSeries r where length := x.length - 1 @@ -171,7 +169,7 @@ lemma nonempty_of_infiniteDimensional [r.InfiniteDimensional] : Nonempty α := ⟨RelSeries.withLength r 0 0⟩ instance membership : Membership α (RelSeries r) := - ⟨(· ∈ Set.range ·)⟩ + ⟨Function.swap (· ∈ Set.range ·)⟩ theorem mem_def : x ∈ s ↔ x ∈ Set.range s := Iff.rfl @@ -237,7 +235,7 @@ such that `r aₙ b₀`, then there is a chain of length `n + m + 1` given by @[simps length] def append (p q : RelSeries r) (connect : r p.last q.head) : RelSeries r where length := p.length + q.length + 1 - toFun := Fin.append p q ∘ Fin.cast (by abel) + toFun := Fin.append p q ∘ Fin.cast (by omega) step i := by obtain hi | rfl | hi := lt_trichotomy i (Fin.castLE (by omega) (Fin.last _ : Fin (p.length + 1))) @@ -259,14 +257,14 @@ def append (p q : RelSeries r) (connect : r p.last q.head) : RelSeries r where rfl rw [hx, Fin.append_right, hy, Fin.append_right] convert q.step ⟨i - (p.length + 1), Nat.sub_lt_left_of_lt_add hi <| - by convert i.2 using 1; abel⟩ + by convert i.2 using 1; exact Nat.add_right_comm ..⟩ rw [Fin.succ_mk, Nat.sub_eq_iff_eq_add (le_of_lt hi : p.length ≤ i), Nat.add_assoc _ 1, add_comm 1, Nat.sub_add_cancel] exact hi lemma append_apply_left (p q : RelSeries r) (connect : r p.last q.head) (i : Fin (p.length + 1)) : - p.append q connect ((i.castAdd (q.length + 1)).cast (by dsimp; abel)) = p i := by + p.append q connect ((i.castAdd (q.length + 1)).cast (by dsimp; omega)) = p i := by delta append simp only [Function.comp_apply] convert Fin.append_left _ _ _ @@ -692,6 +690,22 @@ def mk (length : ℕ) (toFun : Fin (length + 1) → α) (strictMono : StrictMono toFun := toFun step i := strictMono <| lt_add_one i.1 +/-- An injection from the type of strictly monotone functions with limited length to `LTSeries`. -/ +def injStrictMono (n : ℕ) : + {f : (l : Fin n) × (Fin (l + 1) → α) // StrictMono f.2} ↪ LTSeries α where + toFun f := mk f.1.1 f.1.2 f.2 + inj' f g e := by + obtain ⟨⟨lf, f⟩, mf⟩ := f + obtain ⟨⟨lg, g⟩, mg⟩ := g + dsimp only at mf mg e + have leq := congr($(e).length) + rw [mk_length lf f mf, mk_length lg g mg, Fin.val_eq_val] at leq + subst leq + simp_rw [Subtype.mk_eq_mk, Sigma.mk.inj_iff, heq_eq_eq, true_and] + have feq := fun i ↦ congr($(e).toFun i) + simp_rw [mk_toFun lf f mf, mk_toFun lf g mg, mk_length lf f mf] at feq + rwa [Function.funext_iff] + /-- For two preorders `α, β`, if `f : α → β` is strictly monotonic, then a strict chain of `α` can be pushed out to a strict chain of `β` by @@ -720,6 +734,41 @@ noncomputable def comap (p : LTSeries β) (f : α → β) LTSeries α := mk p.length (fun i ↦ (surjective (p i)).choose) (fun i j h ↦ comap (by simpa only [(surjective _).choose_spec] using p.strictMono h)) +/-- The strict series `0 < … < n` in `ℕ`. -/ +def range (n : ℕ) : LTSeries ℕ where + length := n + toFun := fun i => i + step i := Nat.lt_add_one i + +@[simp] lemma length_range (n : ℕ) : (range n).length = n := rfl + +@[simp] lemma range_apply (n : ℕ) (i : Fin (n+1)) : (range n) i = i := rfl + +@[simp] lemma head_range (n : ℕ) : (range n).head = 0 := rfl + +@[simp] lemma last_range (n : ℕ) : (range n).last = n := rfl + +section Fintype + +variable [Fintype α] + +lemma length_lt_card (s : LTSeries α) : s.length < Fintype.card α := by + by_contra! h + obtain ⟨i, j, hn, he⟩ := Fintype.exists_ne_map_eq_of_card_lt s (by rw [Fintype.card_fin]; omega) + wlog hl : i < j generalizing i j + · exact this j i hn.symm he.symm (by omega) + exact absurd he (s.strictMono hl).ne + +instance [DecidableRel ((· < ·) : α → α → Prop)] : Fintype (LTSeries α) where + elems := Finset.univ.map (injStrictMono (Fintype.card α)) + complete s := by + have bl := s.length_lt_card + obtain ⟨l, f, mf⟩ := s + simp_rw [Finset.mem_map, Finset.mem_univ, true_and, Subtype.exists] + use ⟨⟨l, bl⟩, f⟩, Fin.strictMono_iff_lt_succ.mpr mf; rfl + +end Fintype + end LTSeries end LTSeries diff --git a/Mathlib/Order/SemiconjSup.lean b/Mathlib/Order/SemiconjSup.lean index 835ea7b923fb9..ebadc1795ef66 100644 --- a/Mathlib/Order/SemiconjSup.lean +++ b/Mathlib/Order/SemiconjSup.lean @@ -96,7 +96,7 @@ theorem semiconj_of_isLUB [PartialOrder α] [Group G] (f₁ f₂ : G →* α ≃ refine fun y => (H _).unique ?_ have := (f₁ g).leftOrdContinuous (H y) rw [← range_comp, ← (Equiv.mulRight g).surjective.range_comp _] at this - simpa [(· ∘ ·)] using this + simpa [comp_def] using this /-- Consider two actions `f₁ f₂ : G → α → α` of a group on a complete lattice by order isomorphisms. Then the map `x ↦ ⨆ g : G, (f₁ g)⁻¹ (f₂ g x)` semiconjugates each `f₁ g'` to `f₂ g'`. diff --git a/Mathlib/Order/SetNotation.lean b/Mathlib/Order/SetNotation.lean index dc586e637b640..7feb44d478558 100644 --- a/Mathlib/Order/SetNotation.lean +++ b/Mathlib/Order/SetNotation.lean @@ -3,7 +3,7 @@ Copyright (c) 2017 Johannes Hölzl. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl, Patrick Massot, Yury Kudryashov -/ -import Mathlib.Data.Set.Defs +import Mathlib.Data.Set.Operations import Mathlib.Util.Notation3 /-! diff --git a/Mathlib/Order/SuccPred/Basic.lean b/Mathlib/Order/SuccPred/Basic.lean index 3f18d2007775b..eab13f1846fc3 100644 --- a/Mathlib/Order/SuccPred/Basic.lean +++ b/Mathlib/Order/SuccPred/Basic.lean @@ -3,7 +3,7 @@ Copyright (c) 2021 Yaël Dillies. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies -/ -import Mathlib.Order.CompleteLattice +import Mathlib.Order.ConditionallyCompleteLattice.Basic import Mathlib.Order.Cover import Mathlib.Order.GaloisConnection import Mathlib.Order.Iterate @@ -44,7 +44,6 @@ The stricter condition of every element having a sensible successor can be obtai combination of `SuccOrder α` and `NoMaxOrder α`. -/ - open Function OrderDual Set variable {α β : Type*} @@ -52,30 +51,26 @@ variable {α β : Type*} /-- Order equipped with a sensible successor function. -/ @[ext] class SuccOrder (α : Type*) [Preorder α] where - /-- Successor function-/ + /-- Successor function -/ succ : α → α /-- Proof of basic ordering with respect to `succ`-/ le_succ : ∀ a, a ≤ succ a - /-- Proof of interaction between `succ` and maximal element-/ + /-- Proof of interaction between `succ` and maximal element -/ max_of_succ_le {a} : succ a ≤ a → IsMax a - /-- Proof that `succ` satisfies ordering invariants between `LT` and `LE`-/ + /-- Proof that `succ a` is the least element greater than `a`-/ succ_le_of_lt {a b} : a < b → succ a ≤ b - /-- Proof that `succ` satisfies ordering invariants between `LE` and `LT`-/ - le_of_lt_succ {a b} : a < succ b → a ≤ b /-- Order equipped with a sensible predecessor function. -/ @[ext] class PredOrder (α : Type*) [Preorder α] where - /-- Predecessor function-/ + /-- Predecessor function -/ pred : α → α /-- Proof of basic ordering with respect to `pred`-/ pred_le : ∀ a, pred a ≤ a - /-- Proof of interaction between `pred` and minimal element-/ + /-- Proof of interaction between `pred` and minimal element -/ min_of_le_pred {a} : a ≤ pred a → IsMin a - /-- Proof that `pred` satisfies ordering invariants between `LT` and `LE`-/ + /-- Proof that `pred b` is the greatest element less than `b`-/ le_pred_of_lt {a b} : a < b → a ≤ pred b - /-- Proof that `pred` satisfies ordering invariants between `LE` and `LT`-/ - le_of_pred_lt {a b} : pred a < b → a ≤ b instance [Preorder α] [SuccOrder α] : PredOrder αᵒᵈ where @@ -85,7 +80,6 @@ instance [Preorder α] [SuccOrder α] : SuccOrder.le_succ, implies_true] min_of_le_pred h := by apply SuccOrder.max_of_succ_le h le_pred_of_lt := by intro a b h; exact SuccOrder.succ_le_of_lt h - le_of_pred_lt := SuccOrder.le_of_lt_succ instance [Preorder α] [PredOrder α] : SuccOrder αᵒᵈ where @@ -95,29 +89,26 @@ instance [Preorder α] [PredOrder α] : PredOrder.pred_le, implies_true] max_of_succ_le h := by apply PredOrder.min_of_le_pred h succ_le_of_lt := by intro a b h; exact PredOrder.le_pred_of_lt h - le_of_lt_succ := PredOrder.le_of_pred_lt section Preorder variable [Preorder α] /-- A constructor for `SuccOrder α` usable when `α` has no maximal element. -/ -def SuccOrder.ofSuccLeIffOfLeLtSucc (succ : α → α) (hsucc_le_iff : ∀ {a b}, succ a ≤ b ↔ a < b) - (hle_of_lt_succ : ∀ {a b}, a < succ b → a ≤ b) : SuccOrder α := +def SuccOrder.ofSuccLeIff (succ : α → α) (hsucc_le_iff : ∀ {a b}, succ a ≤ b ↔ a < b) : + SuccOrder α := { succ le_succ := fun _ => (hsucc_le_iff.1 le_rfl).le max_of_succ_le := fun ha => (lt_irrefl _ <| hsucc_le_iff.1 ha).elim - succ_le_of_lt := fun h => hsucc_le_iff.2 h - le_of_lt_succ := fun h => hle_of_lt_succ h} + succ_le_of_lt := fun h => hsucc_le_iff.2 h } /-- A constructor for `PredOrder α` usable when `α` has no minimal element. -/ -def PredOrder.ofLePredIffOfPredLePred (pred : α → α) (hle_pred_iff : ∀ {a b}, a ≤ pred b ↔ a < b) - (hle_of_pred_lt : ∀ {a b}, pred a < b → a ≤ b) : PredOrder α := +def PredOrder.ofLePredIff (pred : α → α) (hle_pred_iff : ∀ {a b}, a ≤ pred b ↔ a < b) : + PredOrder α := { pred pred_le := fun _ => (hle_pred_iff.1 le_rfl).le min_of_le_pred := fun ha => (lt_irrefl _ <| hle_pred_iff.1 ha).elim - le_pred_of_lt := fun h => hle_pred_iff.2 h - le_of_pred_lt := fun h => hle_of_pred_lt h } + le_pred_of_lt := fun h => hle_pred_iff.2 h } end Preorder @@ -134,13 +125,11 @@ def SuccOrder.ofCore (succ : α → α) (hn : ∀ {a}, ¬IsMax a → ∀ b, a < by_cases (fun h hab => (hm a h).symm ▸ hab.le) fun h => (hn h b).mp le_succ := fun a => by_cases (fun h => (hm a h).symm.le) fun h => le_of_lt <| by simpa using (hn h a).not - le_of_lt_succ := fun {a b} hab => - by_cases (fun h => hm b h ▸ hab.le) fun h => by simpa [hab] using (hn h a).not max_of_succ_le := fun {a} => not_imp_not.mp fun h => by simpa using (hn h a).not } /-- A constructor for `PredOrder α` for `α` a linear order. -/ @[simps] -def PredOrder.ofCore {α} [LinearOrder α] (pred : α → α) +def PredOrder.ofCore (pred : α → α) (hn : ∀ {a}, ¬IsMin a → ∀ b, b ≤ pred a ↔ b < a) (hm : ∀ a, IsMin a → pred a = a) : PredOrder α := { pred @@ -148,32 +137,11 @@ def PredOrder.ofCore {α} [LinearOrder α] (pred : α → α) by_cases (fun h hab => (hm b h).symm ▸ hab.le) fun h => (hn h a).mpr pred_le := fun a => by_cases (fun h => (hm a h).le) fun h => le_of_lt <| by simpa using (hn h a).not - le_of_pred_lt := fun {a b} hab => - by_cases (fun h => hm a h ▸ hab.le) fun h => by simpa [hab] using (hn h b).not min_of_le_pred := fun {a} => not_imp_not.mp fun h => by simpa using (hn h a).not } -/-- A constructor for `SuccOrder α` usable when `α` is a linear order with no maximal element. -/ -def SuccOrder.ofSuccLeIff (succ : α → α) (hsucc_le_iff : ∀ {a b}, succ a ≤ b ↔ a < b) : - SuccOrder α := - { succ - le_succ := fun _ => (hsucc_le_iff.1 le_rfl).le - max_of_succ_le := fun ha => (lt_irrefl _ <| hsucc_le_iff.1 ha).elim - succ_le_of_lt := fun h => hsucc_le_iff.2 h - le_of_lt_succ := fun {_ _} h => le_of_not_lt ((not_congr hsucc_le_iff).1 h.not_le) } - -/-- A constructor for `PredOrder α` usable when `α` is a linear order with no minimal element. -/ -def PredOrder.ofLePredIff (pred : α → α) (hle_pred_iff : ∀ {a b}, a ≤ pred b ↔ a < b) : - PredOrder α := - { pred - pred_le := fun _ => (hle_pred_iff.1 le_rfl).le - min_of_le_pred := fun ha => (lt_irrefl _ <| hle_pred_iff.1 ha).elim - le_pred_of_lt := fun h => hle_pred_iff.2 h - le_of_pred_lt := fun {_ _} h => le_of_not_lt ((not_congr hle_pred_iff).1 h.not_le) } - -open scoped Classical - variable (α) +open Classical in /-- A well-order is a `SuccOrder`. -/ noncomputable def SuccOrder.ofLinearWellFoundedLT [WellFoundedLT α] : SuccOrder α := ofCore (fun a ↦ if h : (Ioi a).Nonempty then wellFounded_lt.min _ h else a) @@ -214,9 +182,6 @@ theorem succ_le_of_lt {a b : α} : a < b → succ a ≤ b := alias _root_.LT.lt.succ_le := succ_le_of_lt -theorem le_of_lt_succ {a b : α} : a < succ b → a ≤ b := - SuccOrder.le_of_lt_succ - @[simp] theorem succ_le_iff_isMax : succ a ≤ a ↔ IsMax a := ⟨max_of_succ_le, fun h => h <| le_succ _⟩ @@ -235,22 +200,14 @@ theorem wcovBy_succ (a : α) : a ⩿ succ a := theorem covBy_succ_of_not_isMax (h : ¬IsMax a) : a ⋖ succ a := (wcovBy_succ a).covBy_of_lt <| lt_succ_of_not_isMax h -theorem lt_succ_iff_of_not_isMax (ha : ¬IsMax a) : b < succ a ↔ b ≤ a := - ⟨le_of_lt_succ, fun h => h.trans_lt <| lt_succ_of_not_isMax ha⟩ +theorem lt_succ_of_le_of_not_isMax (hab : b ≤ a) (ha : ¬IsMax a) : b < succ a := + hab.trans_lt <| lt_succ_of_not_isMax ha theorem succ_le_iff_of_not_isMax (ha : ¬IsMax a) : succ a ≤ b ↔ a < b := ⟨(lt_succ_of_not_isMax ha).trans_le, succ_le_of_lt⟩ lemma succ_lt_succ_of_not_isMax (h : a < b) (hb : ¬ IsMax b) : succ a < succ b := - (lt_succ_iff_of_not_isMax hb).2 <| succ_le_of_lt h - -theorem succ_lt_succ_iff_of_not_isMax (ha : ¬IsMax a) (hb : ¬IsMax b) : - succ a < succ b ↔ a < b := by - rw [lt_succ_iff_of_not_isMax hb, succ_le_iff_of_not_isMax ha] - -theorem succ_le_succ_iff_of_not_isMax (ha : ¬IsMax a) (hb : ¬IsMax b) : - succ a ≤ succ b ↔ a ≤ b := by - rw [succ_le_iff_of_not_isMax ha, lt_succ_iff_of_not_isMax hb] + lt_succ_of_le_of_not_isMax (succ_le_of_lt h) hb @[simp, mono] theorem succ_le_succ (h : a ≤ b) : succ a ≤ succ b := by @@ -258,7 +215,8 @@ theorem succ_le_succ (h : a ≤ b) : succ a ≤ succ b := by · by_cases hba : b ≤ a · exact (hb <| hba.trans <| le_succ _).trans (le_succ _) · exact succ_le_of_lt ((h.lt_of_not_le hba).trans_le <| le_succ b) - · rwa [succ_le_iff_of_not_isMax fun ha => hb <| ha.mono h, lt_succ_iff_of_not_isMax hb] + · rw [succ_le_iff_of_not_isMax fun ha => hb <| ha.mono h] + apply lt_succ_of_le_of_not_isMax h hb theorem succ_mono : Monotone (succ : α → α) := fun _ _ => succ_le_succ @@ -290,17 +248,23 @@ theorem isMax_iterate_succ_of_eq_of_ne {n m : ℕ} (h_eq : succ^[n] a = succ^[m] · rw [h_eq] exact isMax_iterate_succ_of_eq_of_lt h_eq.symm (lt_of_le_of_ne h h_ne.symm) -theorem Iio_succ_of_not_isMax (ha : ¬IsMax a) : Iio (succ a) = Iic a := - Set.ext fun _ => lt_succ_iff_of_not_isMax ha +theorem Iic_subset_Iio_succ_of_not_isMax (ha : ¬IsMax a) : Iic a ⊆ Iio (succ a) := + fun _ => (lt_succ_of_le_of_not_isMax · ha) theorem Ici_succ_of_not_isMax (ha : ¬IsMax a) : Ici (succ a) = Ioi a := Set.ext fun _ => succ_le_iff_of_not_isMax ha -theorem Ico_succ_right_of_not_isMax (hb : ¬IsMax b) : Ico a (succ b) = Icc a b := by - rw [← Ici_inter_Iio, Iio_succ_of_not_isMax hb, Ici_inter_Iic] +theorem Icc_subset_Ico_succ_right_of_not_isMax (hb : ¬IsMax b) : Icc a b ⊆ Ico a (succ b) := by + rw [← Ici_inter_Iio, ← Ici_inter_Iic] + gcongr + intro _ h + apply lt_succ_of_le_of_not_isMax h hb -theorem Ioo_succ_right_of_not_isMax (hb : ¬IsMax b) : Ioo a (succ b) = Ioc a b := by - rw [← Ioi_inter_Iio, Iio_succ_of_not_isMax hb, Ioi_inter_Iic] +theorem Ioc_subset_Ioo_succ_right_of_not_isMax (hb : ¬IsMax b) : Ioc a b ⊆ Ioo a (succ b) := by + rw [← Ioi_inter_Iio, ← Ioi_inter_Iic] + gcongr + intro _ h + apply Iic_subset_Iio_succ_of_not_isMax hb h theorem Icc_succ_left_of_not_isMax (ha : ¬IsMax a) : Icc (succ a) b = Ioc a b := by rw [← Ici_inter_Iic, Ici_succ_of_not_isMax ha, Ioi_inter_Iic] @@ -316,20 +280,14 @@ theorem lt_succ (a : α) : a < succ a := lt_succ_of_not_isMax <| not_isMax a @[simp] -theorem lt_succ_iff : a < succ b ↔ a ≤ b := - lt_succ_iff_of_not_isMax <| not_isMax b +theorem lt_succ_of_le : a ≤ b → a < succ b := + (lt_succ_of_le_of_not_isMax · <| not_isMax b) @[simp] theorem succ_le_iff : succ a ≤ b ↔ a < b := succ_le_iff_of_not_isMax <| not_isMax a -theorem succ_le_succ_iff : succ a ≤ succ b ↔ a ≤ b := by simp - -theorem succ_lt_succ_iff : succ a < succ b ↔ a < b := by simp - -alias ⟨le_of_succ_le_succ, _⟩ := succ_le_succ_iff - -alias ⟨lt_of_succ_lt_succ, succ_lt_succ⟩ := succ_lt_succ_iff +@[gcongr] theorem succ_lt_succ (hab : a < b) : succ a < succ b := by simp [hab] theorem succ_strictMono : StrictMono (succ : α → α) := fun _ _ => succ_lt_succ @@ -337,20 +295,20 @@ theorem covBy_succ (a : α) : a ⋖ succ a := covBy_succ_of_not_isMax <| not_isMax a @[simp] -theorem Iio_succ (a : α) : Iio (succ a) = Iic a := - Iio_succ_of_not_isMax <| not_isMax _ +theorem Iic_subset_Iio_succ (a : α) : Iic a ⊆ Iio (succ a) := + Iic_subset_Iio_succ_of_not_isMax <| not_isMax _ @[simp] theorem Ici_succ (a : α) : Ici (succ a) = Ioi a := Ici_succ_of_not_isMax <| not_isMax _ @[simp] -theorem Ico_succ_right (a b : α) : Ico a (succ b) = Icc a b := - Ico_succ_right_of_not_isMax <| not_isMax _ +theorem Icc_subset_Ico_succ_right (a b : α) : Icc a b ⊆ Ico a (succ b) := + Icc_subset_Ico_succ_right_of_not_isMax <| not_isMax _ @[simp] -theorem Ioo_succ_right (a b : α) : Ioo a (succ b) = Ioc a b := - Ioo_succ_right_of_not_isMax <| not_isMax _ +theorem Ioc_subset_Ioo_succ_right (a b : α) : Ioc a b ⊆ Ioo a (succ b) := + Ioc_subset_Ioo_succ_right_of_not_isMax <| not_isMax _ @[simp] theorem Icc_succ_left (a b : α) : Icc (succ a) b = Ioc a b := @@ -374,11 +332,6 @@ theorem succ_eq_iff_isMax : succ a = a ↔ IsMax a := alias ⟨_, _root_.IsMax.succ_eq⟩ := succ_eq_iff_isMax -theorem succ_eq_succ_iff_of_not_isMax (ha : ¬IsMax a) (hb : ¬IsMax b) : - succ a = succ b ↔ a = b := by - rw [eq_iff_le_not_lt, eq_iff_le_not_lt, succ_le_succ_iff_of_not_isMax ha hb, - succ_lt_succ_iff_of_not_isMax ha hb] - theorem le_le_succ_iff : a ≤ b ∧ b ≤ succ a ↔ b = a ∨ b = succ a := by refine ⟨fun h => @@ -394,6 +347,84 @@ lemma succ_eq_of_covBy (h : a ⋖ b) : succ a = b := (succ_le_of_lt h.lt).antisy alias _root_.CovBy.succ_eq := succ_eq_of_covBy +theorem _root_.OrderIso.map_succ {β : Type*} [PartialOrder β] [SuccOrder β] (f : α ≃o β) (a : α) : + f (succ a) = succ (f a) := by + by_cases h : IsMax a + · rw [h.succ_eq, (f.isMax_apply.2 h).succ_eq] + · exact (f.map_covBy.2 <| covBy_succ_of_not_isMax h).succ_eq.symm + +section NoMaxOrder + +variable [NoMaxOrder α] + +theorem succ_eq_iff_covBy : succ a = b ↔ a ⋖ b := + ⟨by rintro rfl; exact covBy_succ _, CovBy.succ_eq⟩ + +end NoMaxOrder + +section OrderTop + +variable [OrderTop α] + +@[simp] +theorem succ_top : succ (⊤ : α) = ⊤ := by + rw [succ_eq_iff_isMax, isMax_iff_eq_top] + +theorem succ_le_iff_eq_top : succ a ≤ a ↔ a = ⊤ := + succ_le_iff_isMax.trans isMax_iff_eq_top + +theorem lt_succ_iff_ne_top : a < succ a ↔ a ≠ ⊤ := + lt_succ_iff_not_isMax.trans not_isMax_iff_ne_top + +end OrderTop + +section OrderBot + +variable [OrderBot α] [Nontrivial α] + +theorem bot_lt_succ (a : α) : ⊥ < succ a := + (lt_succ_of_not_isMax not_isMax_bot).trans_le <| succ_mono bot_le + +theorem succ_ne_bot (a : α) : succ a ≠ ⊥ := + (bot_lt_succ a).ne' + +end OrderBot + +end PartialOrder + +section LinearOrder + +variable [LinearOrder α] [SuccOrder α] {a b : α} + +theorem le_of_lt_succ {a b : α} : a < succ b → a ≤ b := fun h ↦ by + by_contra! nh + exact (h.trans_le (succ_le_of_lt nh)).false + +theorem lt_succ_iff_of_not_isMax (ha : ¬IsMax a) : b < succ a ↔ b ≤ a := + ⟨le_of_lt_succ, fun h => h.trans_lt <| lt_succ_of_not_isMax ha⟩ + +theorem succ_lt_succ_iff_of_not_isMax (ha : ¬IsMax a) (hb : ¬IsMax b) : + succ a < succ b ↔ a < b := by + rw [lt_succ_iff_of_not_isMax hb, succ_le_iff_of_not_isMax ha] + +theorem succ_le_succ_iff_of_not_isMax (ha : ¬IsMax a) (hb : ¬IsMax b) : + succ a ≤ succ b ↔ a ≤ b := by + rw [succ_le_iff_of_not_isMax ha, lt_succ_iff_of_not_isMax hb] + +theorem Iio_succ_of_not_isMax (ha : ¬IsMax a) : Iio (succ a) = Iic a := + Set.ext fun _ => lt_succ_iff_of_not_isMax ha + +theorem Ico_succ_right_of_not_isMax (hb : ¬IsMax b) : Ico a (succ b) = Icc a b := by + rw [← Ici_inter_Iio, Iio_succ_of_not_isMax hb, Ici_inter_Iic] + +theorem Ioo_succ_right_of_not_isMax (hb : ¬IsMax b) : Ioo a (succ b) = Ioc a b := by + rw [← Ioi_inter_Iio, Iio_succ_of_not_isMax hb, Ioi_inter_Iic] + +theorem succ_eq_succ_iff_of_not_isMax (ha : ¬IsMax a) (hb : ¬IsMax b) : + succ a = succ b ↔ a = b := by + rw [eq_iff_le_not_lt, eq_iff_le_not_lt, succ_le_succ_iff_of_not_isMax ha hb, + succ_lt_succ_iff_of_not_isMax ha hb] + theorem le_succ_iff_eq_or_le : a ≤ succ b ↔ a = succ b ∨ a ≤ b := by by_cases hb : IsMax b · rw [hb.succ_eq, or_iff_right_of_imp le_of_eq] @@ -426,6 +457,30 @@ section NoMaxOrder variable [NoMaxOrder α] +@[simp] +theorem lt_succ_iff : a < succ b ↔ a ≤ b := + lt_succ_iff_of_not_isMax <| not_isMax b + +theorem succ_le_succ_iff : succ a ≤ succ b ↔ a ≤ b := by simp +theorem succ_lt_succ_iff : succ a < succ b ↔ a < b := by simp + +alias ⟨le_of_succ_le_succ, _⟩ := succ_le_succ_iff +alias ⟨lt_of_succ_lt_succ, _⟩ := succ_lt_succ_iff + +-- TODO: prove for a succ-archimedean non-linear order with bottom +@[simp] +theorem Iio_succ (a : α) : Iio (succ a) = Iic a := + Iio_succ_of_not_isMax <| not_isMax _ + +@[simp] +theorem Ico_succ_right (a b : α) : Ico a (succ b) = Icc a b := + Ico_succ_right_of_not_isMax <| not_isMax _ + +-- TODO: prove for a succ-archimedean non-linear order +@[simp] +theorem Ioo_succ_right (a b : α) : Ioo a (succ b) = Ioc a b := + Ioo_succ_right_of_not_isMax <| not_isMax _ + @[simp] theorem succ_eq_succ_iff : succ a = succ b ↔ a = b := succ_eq_succ_iff_of_not_isMax (not_isMax a) (not_isMax b) @@ -440,11 +495,6 @@ alias ⟨_, succ_ne_succ⟩ := succ_ne_succ_iff theorem lt_succ_iff_eq_or_lt : a < succ b ↔ a = b ∨ a < b := lt_succ_iff.trans le_iff_eq_or_lt -theorem succ_eq_iff_covBy : succ a = b ↔ a ⋖ b := - ⟨by - rintro rfl - exact covBy_succ _, CovBy.succ_eq⟩ - theorem Iio_succ_eq_insert (a : α) : Iio (succ a) = insert a (Iio a) := Iio_succ_eq_insert_of_not_isMax <| not_isMax a @@ -456,45 +506,18 @@ theorem Ioo_succ_right_eq_insert (h : a < b) : Ioo a (succ b) = insert b (Ioo a end NoMaxOrder -section OrderTop - -variable [OrderTop α] - -@[simp] -theorem succ_top : succ (⊤ : α) = ⊤ := by - rw [succ_eq_iff_isMax, isMax_iff_eq_top] - --- Porting note (#10618): removing @[simp],`simp` can prove it -theorem succ_le_iff_eq_top : succ a ≤ a ↔ a = ⊤ := - succ_le_iff_isMax.trans isMax_iff_eq_top - --- Porting note (#10618): removing @[simp],`simp` can prove it -theorem lt_succ_iff_ne_top : a < succ a ↔ a ≠ ⊤ := - lt_succ_iff_not_isMax.trans not_isMax_iff_ne_top - -end OrderTop - section OrderBot variable [OrderBot α] --- Porting note (#10618): removing @[simp],`simp` can prove it theorem lt_succ_bot_iff [NoMaxOrder α] : a < succ ⊥ ↔ a = ⊥ := by rw [lt_succ_iff, le_bot_iff] theorem le_succ_bot_iff : a ≤ succ ⊥ ↔ a = ⊥ ∨ a = succ ⊥ := by rw [le_succ_iff_eq_or_le, le_bot_iff, or_comm] -variable [Nontrivial α] - -theorem bot_lt_succ (a : α) : ⊥ < succ a := - (lt_succ_of_not_isMax not_isMax_bot).trans_le <| succ_mono bot_le - -theorem succ_ne_bot (a : α) : succ a ≠ ⊥ := - (bot_lt_succ a).ne' - end OrderBot -end PartialOrder +end LinearOrder /-- There is at most one way to define the successors in a `PartialOrder`. -/ instance [PartialOrder α] : Subsingleton (SuccOrder α) := @@ -505,18 +528,21 @@ instance [PartialOrder α] : Subsingleton (SuccOrder α) := · exact (@IsMax.succ_eq _ _ h₀ _ ha).trans ha.succ_eq.symm · exact @CovBy.succ_eq _ _ h₀ _ _ (covBy_succ_of_not_isMax ha)⟩ -section CompleteLattice - -variable [CompleteLattice α] [SuccOrder α] - -theorem succ_eq_iInf (a : α) : succ a = ⨅ (b) (_ : a < b), b := by - refine le_antisymm (le_iInf fun b => le_iInf succ_le_of_lt) ?_ +theorem succ_eq_sInf [CompleteLattice α] [SuccOrder α] (a : α) : + succ a = sInf (Set.Ioi a) := by + apply (le_sInf fun b => succ_le_of_lt).antisymm obtain rfl | ha := eq_or_ne a ⊤ · rw [succ_top] exact le_top - exact iInf₂_le _ (lt_succ_iff_ne_top.2 ha) + · exact sInf_le (lt_succ_iff_ne_top.2 ha) + +theorem succ_eq_iInf [CompleteLattice α] [SuccOrder α] (a : α) : succ a = ⨅ b > a, b := by + rw [succ_eq_sInf, iInf_subtype', iInf, Subtype.range_coe_subtype, Ioi] -end CompleteLattice +theorem succ_eq_csInf [ConditionallyCompleteLattice α] [SuccOrder α] [NoMaxOrder α] (a : α) : + succ a = sInf (Set.Ioi a) := by + apply (le_csInf nonempty_Ioi fun b => succ_le_of_lt).antisymm + exact csInf_le ⟨a, fun b => le_of_lt⟩ <| lt_succ a /-! ### Predecessor order -/ @@ -540,9 +566,6 @@ theorem le_pred_of_lt {a b : α} : a < b → a ≤ pred b := alias _root_.LT.lt.le_pred := le_pred_of_lt -theorem le_of_pred_lt {a b : α} : pred a < b → a ≤ b := - PredOrder.le_of_pred_lt - @[simp] theorem le_pred_iff_isMin : a ≤ pred a ↔ IsMin a := ⟨min_of_le_pred, fun h => h <| pred_le _⟩ @@ -556,27 +579,24 @@ theorem pred_lt_iff_not_isMin : pred a < a ↔ ¬IsMin a := alias ⟨_, pred_lt_of_not_isMin⟩ := pred_lt_iff_not_isMin theorem pred_wcovBy (a : α) : pred a ⩿ a := - ⟨pred_le a, fun _ hb => (le_of_pred_lt hb).not_lt⟩ + ⟨pred_le a, fun _ hb nh => (le_pred_of_lt nh).not_lt hb⟩ theorem pred_covBy_of_not_isMin (h : ¬IsMin a) : pred a ⋖ a := (pred_wcovBy a).covBy_of_lt <| pred_lt_of_not_isMin h -theorem pred_lt_iff_of_not_isMin (ha : ¬IsMin a) : pred a < b ↔ a ≤ b := - ⟨le_of_pred_lt, (pred_lt_of_not_isMin ha).trans_le⟩ +theorem pred_lt_of_not_isMin_of_le (ha : ¬IsMin a) : a ≤ b → pred a < b := + (pred_lt_of_not_isMin ha).trans_le theorem le_pred_iff_of_not_isMin (ha : ¬IsMin a) : b ≤ pred a ↔ b < a := ⟨fun h => h.trans_lt <| pred_lt_of_not_isMin ha, le_pred_of_lt⟩ lemma pred_lt_pred_of_not_isMin (h : a < b) (ha : ¬ IsMin a) : pred a < pred b := - (pred_lt_iff_of_not_isMin ha).2 <| le_pred_of_lt h + pred_lt_of_not_isMin_of_le ha <| le_pred_of_lt h -theorem pred_lt_pred_iff_of_not_isMin (ha : ¬IsMin a) (hb : ¬IsMin b) : - pred a < pred b ↔ a < b := by - rw [pred_lt_iff_of_not_isMin ha, le_pred_iff_of_not_isMin hb] - -theorem pred_le_pred_iff_of_not_isMin (ha : ¬IsMin a) (hb : ¬IsMin b) : - pred a ≤ pred b ↔ a ≤ b := by - rw [le_pred_iff_of_not_isMin hb, pred_lt_iff_of_not_isMin ha] +theorem pred_le_pred_of_not_isMin_of_le (ha : ¬IsMin a) (hb : ¬IsMin b) : + a ≤ b → pred a ≤ pred b := by + rw [le_pred_iff_of_not_isMin hb] + apply pred_lt_of_not_isMin_of_le ha @[simp, mono] theorem pred_le_pred {a b : α} (h : a ≤ b) : pred a ≤ pred b := @@ -605,17 +625,21 @@ theorem isMin_iterate_pred_of_eq_of_ne {n m : ℕ} (h_eq : pred^[n] a = pred^[m] (h_ne : n ≠ m) : IsMin (pred^[n] a) := @isMax_iterate_succ_of_eq_of_ne αᵒᵈ _ _ _ _ _ h_eq h_ne -theorem Ioi_pred_of_not_isMin (ha : ¬IsMin a) : Ioi (pred a) = Ici a := - Set.ext fun _ => pred_lt_iff_of_not_isMin ha +theorem Ici_subset_Ioi_pred_of_not_isMin (ha : ¬IsMin a) : Ici a ⊆ Ioi (pred a) := + fun _ ↦ pred_lt_of_not_isMin_of_le ha theorem Iic_pred_of_not_isMin (ha : ¬IsMin a) : Iic (pred a) = Iio a := Set.ext fun _ => le_pred_iff_of_not_isMin ha -theorem Ioc_pred_left_of_not_isMin (ha : ¬IsMin a) : Ioc (pred a) b = Icc a b := by - rw [← Ioi_inter_Iic, Ioi_pred_of_not_isMin ha, Ici_inter_Iic] +theorem Icc_subset_Ioc_pred_left_of_not_isMin (ha : ¬IsMin a) : Icc a b ⊆ Ioc (pred a) b := by + rw [← Ioi_inter_Iic, ← Ici_inter_Iic] + gcongr + apply Ici_subset_Ioi_pred_of_not_isMin ha -theorem Ioo_pred_left_of_not_isMin (ha : ¬IsMin a) : Ioo (pred a) b = Ico a b := by - rw [← Ioi_inter_Iio, Ioi_pred_of_not_isMin ha, Ici_inter_Iio] +theorem Ico_subset_Ioo_pred_left_of_not_isMin (ha : ¬IsMin a) : Ico a b ⊆ Ioo (pred a) b := by + rw [← Ioi_inter_Iio, ← Ici_inter_Iio] + gcongr + apply Ici_subset_Ioi_pred_of_not_isMin ha theorem Icc_pred_right_of_not_isMin (ha : ¬IsMin b) : Icc a (pred b) = Ico a b := by rw [← Ici_inter_Iic, Iic_pred_of_not_isMin ha, Ici_inter_Iio] @@ -631,20 +655,16 @@ theorem pred_lt (a : α) : pred a < a := pred_lt_of_not_isMin <| not_isMin a @[simp] -theorem pred_lt_iff : pred a < b ↔ a ≤ b := - pred_lt_iff_of_not_isMin <| not_isMin a +theorem pred_lt_of_le : a ≤ b → pred a < b := + pred_lt_of_not_isMin_of_le <| not_isMin a @[simp] theorem le_pred_iff : a ≤ pred b ↔ a < b := le_pred_iff_of_not_isMin <| not_isMin b -theorem pred_le_pred_iff : pred a ≤ pred b ↔ a ≤ b := by simp +theorem pred_le_pred_of_le : a ≤ b → pred a ≤ pred b := by intro; simp_all -theorem pred_lt_pred_iff : pred a < pred b ↔ a < b := by simp - -alias ⟨le_of_pred_le_pred, _⟩ := pred_le_pred_iff - -alias ⟨lt_of_pred_lt_pred, pred_lt_pred⟩ := pred_lt_pred_iff +theorem pred_lt_pred : a < b → pred a < pred b := by intro; simp_all theorem pred_strictMono : StrictMono (pred : α → α) := fun _ _ => pred_lt_pred @@ -652,20 +672,20 @@ theorem pred_covBy (a : α) : pred a ⋖ a := pred_covBy_of_not_isMin <| not_isMin a @[simp] -theorem Ioi_pred (a : α) : Ioi (pred a) = Ici a := - Ioi_pred_of_not_isMin <| not_isMin a +theorem Ici_subset_Ioi_pred (a : α) : Ici a ⊆ Ioi (pred a) := + Ici_subset_Ioi_pred_of_not_isMin <| not_isMin a @[simp] theorem Iic_pred (a : α) : Iic (pred a) = Iio a := Iic_pred_of_not_isMin <| not_isMin a @[simp] -theorem Ioc_pred_left (a b : α) : Ioc (pred a) b = Icc a b := - Ioc_pred_left_of_not_isMin <| not_isMin _ +theorem Icc_subset_Ioc_pred_left (a b : α) : Icc a b ⊆ Ioc (pred a) b := + Icc_subset_Ioc_pred_left_of_not_isMin <| not_isMin _ @[simp] -theorem Ioo_pred_left (a b : α) : Ioo (pred a) b = Ico a b := - Ioo_pred_left_of_not_isMin <| not_isMin _ +theorem Ico_subset_Ioo_pred_left (a b : α) : Ico a b ⊆ Ioo (pred a) b := + Ico_subset_Ioo_pred_left_of_not_isMin <| not_isMin _ @[simp] theorem Icc_pred_right (a b : α) : Icc a (pred b) = Ico a b := @@ -689,11 +709,6 @@ theorem pred_eq_iff_isMin : pred a = a ↔ IsMin a := alias ⟨_, _root_.IsMin.pred_eq⟩ := pred_eq_iff_isMin -theorem pred_eq_pred_iff_of_not_isMin (ha : ¬IsMin a) (hb : ¬IsMin b) : - pred a = pred b ↔ a = b := by - rw [eq_iff_le_not_lt, eq_iff_le_not_lt, pred_le_pred_iff_of_not_isMin ha hb, - pred_lt_pred_iff_of_not_isMin ha hb] - theorem pred_le_le_iff {a b : α} : pred a ≤ b ∧ b ≤ a ↔ b = a ∨ b = pred a := by refine ⟨fun h => @@ -707,6 +722,84 @@ lemma pred_eq_of_covBy (h : a ⋖ b) : pred b = a := h.wcovBy.pred_le.antisymm ( alias _root_.CovBy.pred_eq := pred_eq_of_covBy +theorem _root_.OrderIso.map_pred {β : Type*} [PartialOrder β] [PredOrder β] (f : α ≃o β) (a : α) : + f (pred a) = pred (f a) := + f.dual.map_succ a + +section NoMinOrder + +variable [NoMinOrder α] + +theorem pred_eq_iff_covBy : pred b = a ↔ a ⋖ b := + ⟨by + rintro rfl + exact pred_covBy _, CovBy.pred_eq⟩ + +end NoMinOrder + +section OrderBot + +variable [OrderBot α] + +@[simp] +theorem pred_bot : pred (⊥ : α) = ⊥ := + isMin_bot.pred_eq + +theorem le_pred_iff_eq_bot : a ≤ pred a ↔ a = ⊥ := + @succ_le_iff_eq_top αᵒᵈ _ _ _ _ + +theorem pred_lt_iff_ne_bot : pred a < a ↔ a ≠ ⊥ := + @lt_succ_iff_ne_top αᵒᵈ _ _ _ _ + +end OrderBot + +section OrderTop + +variable [OrderTop α] [Nontrivial α] + +theorem pred_lt_top (a : α) : pred a < ⊤ := + (pred_mono le_top).trans_lt <| pred_lt_of_not_isMin not_isMin_top + +theorem pred_ne_top (a : α) : pred a ≠ ⊤ := + (pred_lt_top a).ne + +end OrderTop + +end PartialOrder + +section LinearOrder + +variable [LinearOrder α] [PredOrder α] {a b : α} + +theorem le_of_pred_lt {a b : α} : pred a < b → a ≤ b := fun h ↦ by + by_contra! nh + exact le_pred_of_lt nh |>.trans_lt h |>.false + +theorem pred_lt_iff_of_not_isMin (ha : ¬IsMin a) : pred a < b ↔ a ≤ b := + ⟨le_of_pred_lt, (pred_lt_of_not_isMin ha).trans_le⟩ + +theorem pred_lt_pred_iff_of_not_isMin (ha : ¬IsMin a) (hb : ¬IsMin b) : + pred a < pred b ↔ a < b := by + rw [pred_lt_iff_of_not_isMin ha, le_pred_iff_of_not_isMin hb] + +theorem pred_le_pred_iff_of_not_isMin (ha : ¬IsMin a) (hb : ¬IsMin b) : + pred a ≤ pred b ↔ a ≤ b := by + rw [le_pred_iff_of_not_isMin hb, pred_lt_iff_of_not_isMin ha] + +theorem Ioi_pred_of_not_isMin (ha : ¬IsMin a) : Ioi (pred a) = Ici a := + Set.ext fun _ => pred_lt_iff_of_not_isMin ha + +theorem Ioc_pred_left_of_not_isMin (ha : ¬IsMin a) : Ioc (pred a) b = Icc a b := by + rw [← Ioi_inter_Iic, Ioi_pred_of_not_isMin ha, Ici_inter_Iic] + +theorem Ioo_pred_left_of_not_isMin (ha : ¬IsMin a) : Ioo (pred a) b = Ico a b := by + rw [← Ioi_inter_Iio, Ioi_pred_of_not_isMin ha, Ici_inter_Iio] + +theorem pred_eq_pred_iff_of_not_isMin (ha : ¬IsMin a) (hb : ¬IsMin b) : + pred a = pred b ↔ a = b := by + rw [eq_iff_le_not_lt, eq_iff_le_not_lt, pred_le_pred_iff_of_not_isMin ha hb, + pred_lt_pred_iff_of_not_isMin ha hb] + theorem pred_le_iff_eq_or_le : pred a ≤ b ↔ b = pred a ∨ a ≤ b := by by_cases ha : IsMin a · rw [ha.pred_eq, or_iff_right_of_imp ge_of_eq] @@ -732,6 +825,32 @@ section NoMinOrder variable [NoMinOrder α] +@[simp] +theorem pred_lt_iff : pred a < b ↔ a ≤ b := + pred_lt_iff_of_not_isMin <| not_isMin a + +theorem pred_le_pred_iff : pred a ≤ pred b ↔ a ≤ b := by simp + +theorem pred_lt_pred_iff : pred a < pred b ↔ a < b := by simp + +alias ⟨le_of_pred_le_pred, _⟩ := pred_le_pred_iff + +alias ⟨lt_of_pred_lt_pred, _⟩ := pred_lt_pred_iff + +-- TODO: prove for a pred-archimedean non-linear order with top +@[simp] +theorem Ioi_pred (a : α) : Ioi (pred a) = Ici a := + Ioi_pred_of_not_isMin <| not_isMin a + +@[simp] +theorem Ioc_pred_left (a b : α) : Ioc (pred a) b = Icc a b := + Ioc_pred_left_of_not_isMin <| not_isMin _ + +-- TODO: prove for a pred-archimedean non-linear order +@[simp] +theorem Ioo_pred_left (a b : α) : Ioo (pred a) b = Ico a b := + Ioo_pred_left_of_not_isMin <| not_isMin _ + @[simp] theorem pred_eq_pred_iff : pred a = pred b ↔ a = b := by simp_rw [eq_iff_le_not_lt, pred_le_pred_iff, pred_lt_pred_iff] @@ -746,11 +865,6 @@ alias ⟨_, pred_ne_pred⟩ := pred_ne_pred_iff theorem pred_lt_iff_eq_or_lt : pred a < b ↔ a = b ∨ a < b := pred_lt_iff.trans le_iff_eq_or_lt -theorem pred_eq_iff_covBy : pred b = a ↔ a ⋖ b := - ⟨by - rintro rfl - exact pred_covBy _, CovBy.pred_eq⟩ - theorem Ioi_pred_eq_insert (a : α) : Ioi (pred a) = insert a (Ioi a) := ext fun _ => pred_lt_iff_eq_or_lt.trans <| or_congr_left eq_comm @@ -762,46 +876,19 @@ theorem Ioo_pred_right_eq_insert (h : a < b) : Ioo (pred a) b = insert a (Ioo a end NoMinOrder -section OrderBot - -variable [OrderBot α] - -@[simp] -theorem pred_bot : pred (⊥ : α) = ⊥ := - isMin_bot.pred_eq - --- Porting note (#10618): removing @[simp],`simp` can prove it -theorem le_pred_iff_eq_bot : a ≤ pred a ↔ a = ⊥ := - @succ_le_iff_eq_top αᵒᵈ _ _ _ _ - --- Porting note (#10618): removing @[simp],`simp` can prove it -theorem pred_lt_iff_ne_bot : pred a < a ↔ a ≠ ⊥ := - @lt_succ_iff_ne_top αᵒᵈ _ _ _ _ - -end OrderBot - section OrderTop variable [OrderTop α] --- Porting note (#10618): removing @[simp],`simp` can prove it theorem pred_top_lt_iff [NoMinOrder α] : pred ⊤ < a ↔ a = ⊤ := @lt_succ_bot_iff αᵒᵈ _ _ _ _ _ theorem pred_top_le_iff : pred ⊤ ≤ a ↔ a = ⊤ ∨ a = pred ⊤ := @le_succ_bot_iff αᵒᵈ _ _ _ _ -variable [Nontrivial α] - -theorem pred_lt_top (a : α) : pred a < ⊤ := - (pred_mono le_top).trans_lt <| pred_lt_of_not_isMin not_isMin_top - -theorem pred_ne_top (a : α) : pred a ≠ ⊤ := - (pred_lt_top a).ne - end OrderTop -end PartialOrder +end LinearOrder /-- There is at most one way to define the predecessors in a `PartialOrder`. -/ instance [PartialOrder α] : Subsingleton (PredOrder α) := @@ -812,18 +899,16 @@ instance [PartialOrder α] : Subsingleton (PredOrder α) := · exact (@IsMin.pred_eq _ _ h₀ _ ha).trans ha.pred_eq.symm · exact @CovBy.pred_eq _ _ h₀ _ _ (pred_covBy_of_not_isMin ha)⟩ -section CompleteLattice +theorem pred_eq_sSup [CompleteLattice α] [PredOrder α] : + ∀ a : α, pred a = sSup (Set.Iio a) := + succ_eq_sInf (α := αᵒᵈ) -variable [CompleteLattice α] [PredOrder α] +theorem pred_eq_iSup [CompleteLattice α] [PredOrder α] (a : α) : pred a = ⨆ b < a, b := + succ_eq_iInf (α := αᵒᵈ) a -theorem pred_eq_iSup (a : α) : pred a = ⨆ (b) (_ : b < a), b := by - refine le_antisymm ?_ (iSup_le fun b => iSup_le le_pred_of_lt) - obtain rfl | ha := eq_or_ne a ⊥ - · rw [pred_bot] - exact bot_le - · exact @le_iSup₂ _ _ (fun b => b < a) _ (fun a _ => a) (pred a) (pred_lt_iff_ne_bot.2 ha) - -end CompleteLattice +theorem pred_eq_csSup [ConditionallyCompleteLattice α] [PredOrder α] [NoMinOrder α] (a : α) : + pred a = sSup (Set.Iio a) := + succ_eq_csInf (α := αᵒᵈ) a /-! ### Successor-predecessor orders -/ @@ -852,18 +937,16 @@ theorem succ_pred_of_not_isMin (h : ¬IsMin a) : succ (pred a) = a := theorem pred_succ_of_not_isMax (h : ¬IsMax a) : pred (succ a) = a := CovBy.pred_eq (covBy_succ_of_not_isMax h) --- Porting note (#10618): removing @[simp],`simp` can prove it theorem succ_pred [NoMinOrder α] (a : α) : succ (pred a) = a := CovBy.succ_eq (pred_covBy _) --- Porting note (#10618): removing @[simp],`simp` can prove it theorem pred_succ [NoMaxOrder α] (a : α) : pred (succ a) = a := CovBy.pred_eq (covBy_succ _) theorem pred_succ_iterate_of_not_isMax (i : α) (n : ℕ) (hin : ¬IsMax (succ^[n - 1] i)) : pred^[n] (succ^[n] i) = i := by induction' n with n hn - · simp only [Function.iterate_zero, id] + · simp only [Nat.zero_eq, Function.iterate_zero, id] rw [Nat.succ_sub_succ_eq_sub, Nat.sub_zero] at hin have h_not_max : ¬IsMax (succ^[n - 1] i) := by cases' n with n @@ -909,13 +992,13 @@ namespace WithTop section Succ -variable [DecidableEq α] [PartialOrder α] [OrderTop α] [SuccOrder α] +variable [DecidableEq α] [PartialOrder α] [SuccOrder α] instance : SuccOrder (WithTop α) where succ a := match a with | ⊤ => ⊤ - | Option.some a => ite (a = ⊤) ⊤ (some (succ a)) + | Option.some a => ite (succ a = a) ⊤ (some (succ a)) le_succ a := by cases' a with a a · exact le_top @@ -929,7 +1012,7 @@ instance : SuccOrder (WithTop α) where dsimp only at ha split_ifs at ha with ha' · exact (not_top_le_coe _ ha).elim - · rw [coe_le_coe, succ_le_iff_eq_top] at ha + · rw [coe_le_coe, succ_le_iff_isMax, ← succ_eq_iff_isMax] at ha exact (ha' ha).elim succ_le_of_lt {a b} h := by cases b @@ -939,27 +1022,20 @@ instance : SuccOrder (WithTop α) where rw [coe_lt_coe] at h change ite _ _ _ ≤ _ split_ifs with ha - · rw [ha] at h - exact (not_top_lt h).elim + · rw [succ_eq_iff_isMax] at ha + exact (ha.not_lt h).elim · exact coe_le_coe.2 (succ_le_of_lt h) - le_of_lt_succ {a b} h := by - cases a - · exact (not_top_lt h).elim - cases b - · exact le_top - dsimp only at h - rw [coe_le_coe] - split_ifs at h with hb - · rw [hb] - exact le_top - · exact le_of_lt_succ (coe_lt_coe.1 h) @[simp] -theorem succ_coe_top : succ ↑(⊤ : α) = (⊤ : WithTop α) := - dif_pos rfl +theorem succ_coe_of_isMax {a : α} (h : IsMax a) : succ ↑a = (⊤ : WithTop α) := + dif_pos (succ_eq_iff_isMax.2 h) -theorem succ_coe_of_ne_top {a : α} (h : a ≠ ⊤) : succ (↑a : WithTop α) = ↑(succ a) := - dif_neg h +theorem succ_coe_of_not_isMax {a : α} (h : ¬ IsMax a) : succ (↑a : WithTop α) = ↑(succ a) := + dif_neg (succ_eq_iff_isMax.not.2 h) + +@[simp] +theorem succ_coe [NoMaxOrder α] {a : α} : succ (↑a : WithTop α) = ↑(succ a) := + succ_coe_of_not_isMax <| not_isMax a end Succ @@ -986,12 +1062,6 @@ instance : PredOrder (WithTop α) where cases b · exact coe_le_coe.2 le_top exact coe_le_coe.2 (le_pred_of_lt <| coe_lt_coe.1 h) - le_of_pred_lt {a b} h := by - cases b - · exact le_top - cases a - · exact (not_top_lt <| coe_lt_coe.1 h).elim - · exact coe_le_coe.2 (le_of_pred_lt <| coe_lt_coe.1 h) @[simp] theorem pred_top : pred (⊤ : WithTop α) = ↑(⊤ : α) := @@ -1010,44 +1080,6 @@ theorem pred_untop : end Pred -/-! #### Adding a `⊤` to a `NoMaxOrder` -/ - -section Succ - -variable [Preorder α] [NoMaxOrder α] [SuccOrder α] - -instance succOrderOfNoMaxOrder : SuccOrder (WithTop α) where - succ a := - match a with - | ⊤ => ⊤ - | Option.some a => some (succ a) - le_succ a := by - cases' a with a a - · exact le_top - · exact coe_le_coe.2 (le_succ a) - max_of_succ_le {a} ha := by - cases a - · exact isMax_top - · exact (not_isMax _ <| max_of_succ_le <| coe_le_coe.1 ha).elim - succ_le_of_lt {a b} h := by - cases a - · exact (not_top_lt h).elim - cases b - · exact le_top - · exact coe_le_coe.2 (succ_le_of_lt <| coe_lt_coe.1 h) - le_of_lt_succ {a b} h := by - cases a - · exact (not_top_lt h).elim - cases b - · exact le_top - · exact coe_le_coe.2 (le_of_lt_succ <| coe_lt_coe.1 h) - -@[simp] -theorem succ_coe (a : α) : succ (↑a : WithTop α) = ↑(succ a) := - rfl - -end Succ - section Pred variable [Preorder α] [NoMaxOrder α] @@ -1059,7 +1091,7 @@ instance [hα : Nonempty α] : IsEmpty (PredOrder (WithTop α)) := · exact hα.elim fun a => (min_of_le_pred h.ge).not_lt <| coe_lt_top a · obtain ⟨c, hc⟩ := exists_gt a rw [← coe_lt_coe, ← h] at hc - exact (le_of_pred_lt hc).not_lt (coe_lt_top _)⟩ + exact (le_pred_of_lt (coe_lt_top c)).not_lt hc⟩ end Pred @@ -1092,12 +1124,6 @@ instance : SuccOrder (WithBot α) where cases a · exact coe_le_coe.2 bot_le · exact coe_le_coe.2 (succ_le_of_lt <| coe_lt_coe.1 h) - le_of_lt_succ {a b} h := by - cases a - · exact bot_le - cases b - · exact (not_lt_bot <| coe_lt_coe.1 h).elim - · exact coe_le_coe.2 (le_of_lt_succ <| coe_lt_coe.1 h) @[simp] theorem succ_bot : succ (⊥ : WithBot α) = ↑(⊥ : α) := @@ -1118,13 +1144,13 @@ end Succ section Pred -variable [DecidableEq α] [PartialOrder α] [OrderBot α] [PredOrder α] +variable [DecidableEq α] [PartialOrder α] [PredOrder α] instance : PredOrder (WithBot α) where pred a := match a with | ⊥ => ⊥ - | Option.some a => ite (a = ⊥) ⊥ (some (pred a)) + | Option.some a => ite (pred a = a) ⊥ (some (pred a)) pred_le a := by cases' a with a a · exact bot_le @@ -1138,7 +1164,7 @@ instance : PredOrder (WithBot α) where dsimp only at ha split_ifs at ha with ha' · exact (not_coe_le_bot _ ha).elim - · rw [coe_le_coe, le_pred_iff_eq_bot] at ha + · rw [coe_le_coe, le_pred_iff_isMin, ← pred_eq_iff_isMin] at ha exact (ha' ha).elim le_pred_of_lt {a b} h := by cases a @@ -1148,27 +1174,19 @@ instance : PredOrder (WithBot α) where rw [coe_lt_coe] at h change _ ≤ ite _ _ _ split_ifs with hb - · rw [hb] at h - exact (not_lt_bot h).elim + · rw [pred_eq_iff_isMin] at hb + exact (hb.not_lt h).elim · exact coe_le_coe.2 (le_pred_of_lt h) - le_of_pred_lt {a b} h := by - cases b - · exact (not_lt_bot h).elim - cases a - · exact bot_le - dsimp only at h - rw [coe_le_coe] - split_ifs at h with ha - · rw [ha] - exact bot_le - · exact le_of_pred_lt (coe_lt_coe.1 h) @[simp] -theorem pred_coe_bot : pred ↑(⊥ : α) = (⊥ : WithBot α) := - dif_pos rfl +theorem pred_coe_of_isMin {a : α} (h : IsMin a) : pred ↑a = (⊥ : WithBot α) := + dif_pos (pred_eq_iff_isMin.2 h) -theorem pred_coe_of_ne_bot {a : α} (h : a ≠ ⊥) : pred (↑a : WithBot α) = ↑(pred a) := - dif_neg h +theorem pred_coe_of_not_isMin {a : α} (h : ¬ IsMin a) : pred (↑a : WithBot α) = ↑(pred a) := + dif_neg (pred_eq_iff_isMin.not.2 h) + +theorem pred_coe [NoMinOrder α] {a : α} : pred (↑a : WithBot α) = ↑(pred a) := + pred_coe_of_not_isMin <| not_isMin a end Pred @@ -1185,46 +1203,10 @@ instance [hα : Nonempty α] : IsEmpty (SuccOrder (WithBot α)) := · exact hα.elim fun a => (max_of_succ_le h.le).not_lt <| bot_lt_coe a · obtain ⟨c, hc⟩ := exists_lt a rw [← coe_lt_coe, ← h] at hc - exact (le_of_lt_succ hc).not_lt (bot_lt_coe _)⟩ + exact (succ_le_of_lt (bot_lt_coe _)).not_lt hc⟩ end Succ -section Pred - -variable [Preorder α] [NoMinOrder α] [PredOrder α] - -instance predOrderOfNoMinOrder : PredOrder (WithBot α) where - pred a := - match a with - | ⊥ => ⊥ - | Option.some a => some (pred a) - pred_le a := by - cases' a with a a - · exact bot_le - · exact coe_le_coe.2 (pred_le a) - min_of_le_pred {a} ha := by - cases a - · exact isMin_bot - · exact (not_isMin _ <| min_of_le_pred <| coe_le_coe.1 ha).elim - le_pred_of_lt {a b} h := by - cases b - · exact (not_lt_bot h).elim - cases a - · exact bot_le - · exact coe_le_coe.2 (le_pred_of_lt <| coe_lt_coe.1 h) - le_of_pred_lt {a b} h := by - cases b - · exact (not_lt_bot h).elim - cases a - · exact bot_le - · exact coe_le_coe.2 (le_of_pred_lt <| coe_lt_coe.1 h) - -@[simp] -theorem pred_coe (a : α) : pred (↑a : WithBot α) = ↑(pred a) := - rfl - -end Pred - end WithBot /-! ### Archimedeanness -/ @@ -1374,11 +1356,11 @@ lemma StrictAnti.not_bddBelow_range [NoMaxOrder α] [PredOrder β] [IsPredArchim end bdd_range -section IsWellOrder +section IsWellFounded -variable [LinearOrder α] +variable [PartialOrder α] -instance (priority := 100) IsWellOrder.toIsPredArchimedean [h : IsWellOrder α (· < ·)] +instance (priority := 100) WellFoundedLT.toIsPredArchimedean [h : WellFoundedLT α] [PredOrder α] : IsPredArchimedean α := ⟨fun {a b} => by refine WellFounded.fix (C := fun b => a ≤ b → ∃ n, Nat.iterate pred n b = a) @@ -1387,19 +1369,19 @@ instance (priority := 100) IsWellOrder.toIsPredArchimedean [h : IsWellOrder α ( replace hab := eq_or_lt_of_le hab rcases hab with (rfl | hab) · exact ⟨0, rfl⟩ - rcases le_or_lt b (pred b) with hb | hb - · cases (min_of_le_pred hb).not_lt hab + rcases eq_or_lt_of_le (pred_le b) with hb | hb + · cases (min_of_le_pred hb.ge).not_lt hab dsimp at ih obtain ⟨k, hk⟩ := ih (pred b) hb (le_pred_of_lt hab) refine ⟨k + 1, ?_⟩ rw [iterate_add_apply, iterate_one, hk]⟩ -instance (priority := 100) IsWellOrder.toIsSuccArchimedean [h : IsWellOrder α (· > ·)] +instance (priority := 100) WellFoundedGT.toIsSuccArchimedean [h : WellFoundedGT α] [SuccOrder α] : IsSuccArchimedean α := let h : IsPredArchimedean αᵒᵈ := by infer_instance ⟨h.1⟩ -end IsWellOrder +end IsWellFounded section OrderBot diff --git a/Mathlib/Order/SuccPred/CompleteLinearOrder.lean b/Mathlib/Order/SuccPred/CompleteLinearOrder.lean index 3496364a6b58f..6e68665cc40b0 100644 --- a/Mathlib/Order/SuccPred/CompleteLinearOrder.lean +++ b/Mathlib/Order/SuccPred/CompleteLinearOrder.lean @@ -59,6 +59,27 @@ lemma IsGLB.exists_of_nonempty_of_not_isPredLimit (hf : IsGLB (Set.range f) x) (hx : ¬ IsPredLimit x) : ∃ i, f i = x := hf.mem_of_nonempty_of_not_isPredLimit (Set.range_nonempty f) hx +open Classical in +/-- Every conditionally complete linear order with well-founded `<` is a successor order, by setting +the successor of an element to be the infimum of all larger elements. -/ +noncomputable def ConditionallyCompleteLinearOrder.toSuccOrder [WellFoundedLT α] : + SuccOrder α where + succ a := if IsMax a then a else sInf {b | a < b} + le_succ a := by + by_cases h : IsMax a + · simp [h] + · simp only [h, ↓reduceIte] + rw [not_isMax_iff] at h + exact le_csInf h (fun b => le_of_lt) + max_of_succ_le hs := by + by_contra h + simp [h] at hs + rw [not_isMax_iff] at h + exact hs.not_lt (csInf_mem h) + succ_le_of_lt {a b} ha := by + simp [ha.not_isMax] + exact csInf_le ⟨a, fun _ hc => hc.le⟩ ha + end ConditionallyCompleteLinearOrder section ConditionallyCompleteLinearOrderBot diff --git a/Mathlib/Order/SuccPred/Limit.lean b/Mathlib/Order/SuccPred/Limit.lean index f155e590cd460..2add48d39726f 100644 --- a/Mathlib/Order/SuccPred/Limit.lean +++ b/Mathlib/Order/SuccPred/Limit.lean @@ -120,6 +120,9 @@ theorem mem_range_succ_of_not_isSuccLimit (h : ¬IsSuccLimit a) : a ∈ range (@ cases' not_isSuccLimit_iff.1 h with b hb exact ⟨b, hb.2⟩ +theorem mem_range_succ_or_isSuccLimit (a) : a ∈ range (@succ α _ _) ∨ IsSuccLimit a := + or_iff_not_imp_right.2 <| mem_range_succ_of_not_isSuccLimit + theorem isSuccLimit_of_succ_lt (H : ∀ a < b, succ a < b) : IsSuccLimit b := fun a hab => (H a hab.lt).ne (CovBy.succ_eq hab) @@ -137,74 +140,10 @@ theorem IsSuccLimit.succ_lt_iff (hb : IsSuccLimit b) : succ a < b ↔ a < b := theorem isSuccLimit_iff_succ_lt : IsSuccLimit b ↔ ∀ a < b, succ a < b := ⟨fun hb _ => hb.succ_lt, isSuccLimit_of_succ_lt⟩ -/-- A value can be built by building it on successors and successor limits. -/ -@[elab_as_elim] -noncomputable def isSuccLimitRecOn (b : α) (hs : ∀ a, ¬IsMax a → C (succ a)) - (hl : ∀ a, IsSuccLimit a → C a) : C b := by - by_cases hb : IsSuccLimit b - · exact hl b hb - · have H := Classical.choose_spec (not_isSuccLimit_iff.1 hb) - rw [← H.2] - exact hs _ H.1 - -theorem isSuccLimitRecOn_limit (hs : ∀ a, ¬IsMax a → C (succ a)) (hl : ∀ a, IsSuccLimit a → C a) - (hb : IsSuccLimit b) : @isSuccLimitRecOn α _ _ C b hs hl = hl b hb := by - classical exact dif_pos hb - -theorem isSuccLimitRecOn_succ' (hs : ∀ a, ¬IsMax a → C (succ a)) (hl : ∀ a, IsSuccLimit a → C a) - {b : α} (hb : ¬IsMax b) : @isSuccLimitRecOn α _ _ C (succ b) hs hl = hs b hb := by - have hb' := not_isSuccLimit_succ_of_not_isMax hb - have H := Classical.choose_spec (not_isSuccLimit_iff.1 hb') - rw [isSuccLimitRecOn] - simp only [cast_eq_iff_heq, hb', not_false_iff, eq_mpr_eq_cast, dif_neg] - congr 1 <;> first | - exact (succ_eq_succ_iff_of_not_isMax H.left hb).mp H.right | - exact proof_irrel_heq H.left hb - -section limitRecOn - -variable [WellFoundedLT α] - (H_succ : ∀ a, ¬IsMax a → C a → C (succ a)) - (H_lim : ∀ a, IsSuccLimit a → (∀ b < a, C b) → C a) - -open scoped Classical in -variable (a) in -/-- Recursion principle on a well-founded partial `SuccOrder`. -/ -@[elab_as_elim] noncomputable def _root_.SuccOrder.limitRecOn : C a := - wellFounded_lt.fix - (fun a IH ↦ if h : IsSuccLimit a then H_lim a h IH else - let x := Classical.indefiniteDescription _ (not_isSuccLimit_iff.mp h) - x.2.2 ▸ H_succ x x.2.1 (IH x <| x.2.2.subst <| lt_succ_of_not_isMax x.2.1)) - a - -@[simp] -theorem _root_.SuccOrder.limitRecOn_succ (ha : ¬ IsMax a) : - SuccOrder.limitRecOn (succ a) H_succ H_lim - = H_succ a ha (SuccOrder.limitRecOn a H_succ H_lim) := by - have h := not_isSuccLimit_succ_of_not_isMax ha - rw [SuccOrder.limitRecOn, WellFounded.fix_eq, dif_neg h] - have {b c hb hc} {x : ∀ a, C a} (h : b = c) : - congr_arg succ h ▸ H_succ b hb (x b) = H_succ c hc (x c) := by subst h; rfl - let x := Classical.indefiniteDescription _ (not_isSuccLimit_iff.mp h) - exact this ((succ_eq_succ_iff_of_not_isMax x.2.1 ha).mp x.2.2) - -@[simp] -theorem _root_.SuccOrder.limitRecOn_limit (ha : IsSuccLimit a) : - SuccOrder.limitRecOn a H_succ H_lim - = H_lim a ha fun x _ ↦ SuccOrder.limitRecOn x H_succ H_lim := by - rw [SuccOrder.limitRecOn, WellFounded.fix_eq, dif_pos ha]; rfl - -end limitRecOn - section NoMaxOrder variable [NoMaxOrder α] -@[simp] -theorem isSuccLimitRecOn_succ (hs : ∀ a, ¬IsMax a → C (succ a)) (hl : ∀ a, IsSuccLimit a → C a) - (b : α) : @isSuccLimitRecOn α _ _ C (succ b) hs hl = hs b (not_isMax b) := - isSuccLimitRecOn_succ' _ _ _ - theorem isSuccLimit_iff_succ_ne : IsSuccLimit a ↔ ∀ b, succ b ≠ a := ⟨IsSuccLimit.succ_ne, isSuccLimit_of_succ_ne⟩ @@ -335,6 +274,9 @@ theorem mem_range_pred_of_not_isPredLimit (h : ¬IsPredLimit a) : a ∈ range (@ cases' not_isPredLimit_iff.1 h with b hb exact ⟨b, hb.2⟩ +theorem mem_range_pred_or_isPredLimit (a) : a ∈ range (@pred α _ _) ∨ IsPredLimit a := + or_iff_not_imp_right.2 <| mem_range_pred_of_not_isPredLimit + theorem isPredLimit_of_pred_lt (H : ∀ a > b, pred a < b) : IsPredLimit b := fun a hab => (H a hab.lt).ne (CovBy.pred_eq hab) @@ -347,81 +289,204 @@ theorem IsPredLimit.lt_pred_iff (h : IsPredLimit a) : a < pred b ↔ a < b := theorem isPredLimit_iff_lt_pred : IsPredLimit a ↔ ∀ ⦃b⦄, a < b → a < pred b := isSuccLimit_toDual_iff.symm.trans isSuccLimit_iff_succ_lt +section NoMinOrder + +variable [NoMinOrder α] + +end NoMinOrder + +section IsPredArchimedean + +variable [IsPredArchimedean α] + +protected theorem IsPredLimit.isMax (h : IsPredLimit a) : IsMax a := + (isPredLimit.dual h).isMin + +@[simp] +theorem isPredLimit_iff : IsPredLimit a ↔ IsMax a := + isSuccLimit_toDual_iff.symm.trans isSuccLimit_iff + +theorem not_isPredLimit [NoMaxOrder α] : ¬IsPredLimit a := by simp + +end IsPredArchimedean + +end PartialOrder + +/-! ### Induction principles -/ + + +variable {C : α → Sort*} {b : α} + +section isSuccLimitRecOn + +section PartialOrder + +variable [PartialOrder α] [SuccOrder α] + +/-- A value can be built by building it on successors and successor limits. -/ +@[elab_as_elim] +noncomputable def isSuccLimitRecOn (b : α) (hs : ∀ a, ¬ IsMax a → C (succ a)) + (hl : ∀ a, IsSuccLimit a → C a) : C b := by + by_cases hb : IsSuccLimit b + · exact hl b hb + · have H := Classical.choose_spec (not_isSuccLimit_iff.1 hb) + rw [← H.2] + exact hs _ H.1 + +theorem isSuccLimitRecOn_limit (hs : ∀ a, ¬ IsMax a → C (succ a)) (hl : ∀ a, IsSuccLimit a → C a) + (hb : IsSuccLimit b) : @isSuccLimitRecOn α C _ _ b hs hl = hl b hb := + dif_pos hb + +end PartialOrder + +section LinearOrder + +variable [LinearOrder α] [SuccOrder α] + +theorem isSuccLimitRecOn_succ' (hs : ∀ a, ¬ IsMax a → C (succ a)) (hl : ∀ a, IsSuccLimit a → C a) + (hb : ¬ IsMax b) : @isSuccLimitRecOn α C _ _ (succ b) hs hl = hs b hb := by + have hb' := not_isSuccLimit_succ_of_not_isMax hb + have H := Classical.choose_spec (not_isSuccLimit_iff.1 hb') + rw [isSuccLimitRecOn] + simp only [cast_eq_iff_heq, hb', not_false_iff, eq_mpr_eq_cast, dif_neg] + congr 1 <;> first | + exact (succ_eq_succ_iff_of_not_isMax H.left hb).mp H.right | + exact proof_irrel_heq H.left hb + +@[simp] +theorem isSuccLimitRecOn_succ [NoMaxOrder α] (hs : ∀ a, ¬ IsMax a → C (succ a)) + (hl : ∀ a, IsSuccLimit a → C a) (b : α) : + @isSuccLimitRecOn α C _ _ (succ b) hs hl = hs b (not_isMax b) := + isSuccLimitRecOn_succ' _ _ _ + +end LinearOrder + +end isSuccLimitRecOn + +section isPredLimitRecOn + +section PartialOrder + +variable [PartialOrder α] [PredOrder α] + /-- A value can be built by building it on predecessors and predecessor limits. -/ @[elab_as_elim] -noncomputable def isPredLimitRecOn (b : α) (hs : ∀ a, ¬IsMin a → C (pred a)) +noncomputable def isPredLimitRecOn (b : α) (hs : ∀ a, ¬ IsMin a → C (pred a)) (hl : ∀ a, IsPredLimit a → C a) : C b := @isSuccLimitRecOn αᵒᵈ _ _ _ _ hs fun _ ha => hl _ (isSuccLimit.dual ha) -theorem isPredLimitRecOn_limit (hs : ∀ a, ¬IsMin a → C (pred a)) (hl : ∀ a, IsPredLimit a → C a) - (hb : IsPredLimit b) : @isPredLimitRecOn α _ _ C b hs hl = hl b hb := +theorem isPredLimitRecOn_limit (hs : ∀ a, ¬ IsMin a → C (pred a)) (hl : ∀ a, IsPredLimit a → C a) + (hb : IsPredLimit b) : @isPredLimitRecOn α C _ _ b hs hl = hl b hb := isSuccLimitRecOn_limit _ _ (isPredLimit.dual hb) -theorem isPredLimitRecOn_pred' (hs : ∀ a, ¬IsMin a → C (pred a)) (hl : ∀ a, IsPredLimit a → C a) - {b : α} (hb : ¬IsMin b) : @isPredLimitRecOn α _ _ C (pred b) hs hl = hs b hb := +end PartialOrder + +section LinearOrder + +variable [LinearOrder α] [PredOrder α] + (hs : ∀ a, ¬ IsMin a → C (pred a)) (hl : ∀ a, IsPredLimit a → C a) + +theorem isPredLimitRecOn_pred' {b : α} (hb : ¬ IsMin b) : + @isPredLimitRecOn α C _ _ (pred b) hs hl = hs b hb := isSuccLimitRecOn_succ' _ _ _ +@[simp] +theorem isPredLimitRecOn_pred [NoMinOrder α] (b : α) : + @isPredLimitRecOn α C _ _ (pred b) hs hl = hs b (not_isMin b) := + isSuccLimitRecOn_succ _ _ _ + +end LinearOrder + +end isPredLimitRecOn + +end Order + +open Order + +variable {C : α → Sort*} {b : α} + +namespace SuccOrder + section limitRecOn -variable [WellFoundedGT α] - (H_pred : ∀ a, ¬IsMin a → C a → C (pred a)) - (H_lim : ∀ a, IsPredLimit a → (∀ b > a, C b) → C a) +section PartialOrder + +variable [PartialOrder α] [SuccOrder α] [WellFoundedLT α] open scoped Classical in -variable (a) in -/-- Recursion principle on a well-founded partial `PredOrder`. -/ -@[elab_as_elim] noncomputable def _root_.PredOrder.limitRecOn : C a := - wellFounded_gt.fix - (fun a IH ↦ if h : IsPredLimit a then H_lim a h IH else - let x := Classical.indefiniteDescription _ (not_isPredLimit_iff.mp h) - x.2.2 ▸ H_pred x x.2.1 (IH x <| x.2.2.subst <| pred_lt_of_not_isMin x.2.1)) - a +/-- Recursion principle on a well-founded partial `SuccOrder`. -/ +@[elab_as_elim] noncomputable def limitRecOn (b : α) + (hs : ∀ a, ¬ IsMax a → C a → C (Order.succ a)) + (hl : ∀ a, IsSuccLimit a → (∀ b < a, C b) → C a) : C b := + wellFounded_lt.fix + (fun a IH ↦ if h : IsSuccLimit a then hl a h IH else + let x := Classical.indefiniteDescription _ (not_isSuccLimit_iff.mp h) + x.2.2 ▸ hs x x.2.1 (IH x <| x.2.2.subst <| lt_succ_of_not_isMax x.2.1)) + b @[simp] -theorem _root_.PredOrder.limitRecOn_pred (ha : ¬ IsMin a) : - PredOrder.limitRecOn (pred a) H_pred H_lim - = H_pred a ha (PredOrder.limitRecOn a H_pred H_lim) := by - have h := not_isPredLimit_pred_of_not_isMin ha - rw [PredOrder.limitRecOn, WellFounded.fix_eq, dif_neg h] - have {b c hb hc} {x : ∀ a, C a} (h : b = c) : - congr_arg pred h ▸ H_pred b hb (x b) = H_pred c hc (x c) := by subst h; rfl - let x := Classical.indefiniteDescription _ (not_isPredLimit_iff.mp h) - exact this ((pred_eq_pred_iff_of_not_isMin x.2.1 ha).mp x.2.2) +theorem limitRecOn_limit (hs : ∀ a, ¬ IsMax a → C a → C (Order.succ a)) + (hl : ∀ a, IsSuccLimit a → (∀ b < a, C b) → C a) (hb : IsSuccLimit b) : + limitRecOn b hs hl = hl b hb fun x _ ↦ SuccOrder.limitRecOn x hs hl := by + rw [SuccOrder.limitRecOn, WellFounded.fix_eq, dif_pos hb]; rfl + +end PartialOrder + +section LinearOrder + +variable [LinearOrder α] [SuccOrder α] [WellFoundedLT α] + (hs : ∀ a, ¬ IsMax a → C a → C (Order.succ a)) (hl : ∀ a, IsSuccLimit a → (∀ b < a, C b) → C a) @[simp] -theorem _root_.PredOrder.limitRecOn_limit (ha : IsPredLimit a) : - PredOrder.limitRecOn a H_pred H_lim - = H_lim a ha fun x _ ↦ PredOrder.limitRecOn x H_pred H_lim := by - rw [PredOrder.limitRecOn, WellFounded.fix_eq, dif_pos ha]; rfl +theorem limitRecOn_succ (hb : ¬ IsMax b) : + limitRecOn (Order.succ b) hs hl = hs b hb (limitRecOn b hs hl) := by + have h := not_isSuccLimit_succ_of_not_isMax hb + rw [limitRecOn, WellFounded.fix_eq, dif_neg h] + have {b c hb hc} {x : ∀ a, C a} (h : b = c) : + congr_arg Order.succ h ▸ hs b hb (x b) = hs c hc (x c) := by subst h; rfl + let x := Classical.indefiniteDescription _ (not_isSuccLimit_iff.mp h) + exact this ((succ_eq_succ_iff_of_not_isMax x.2.1 hb).mp x.2.2) + +end LinearOrder end limitRecOn -section NoMinOrder +end SuccOrder -variable [NoMinOrder α] +namespace PredOrder -@[simp] -theorem isPredLimitRecOn_pred (hs : ∀ a, ¬IsMin a → C (pred a)) (hl : ∀ a, IsPredLimit a → C a) - (b : α) : @isPredLimitRecOn α _ _ C (pred b) hs hl = hs b (not_isMin b) := - isSuccLimitRecOn_succ _ _ _ - -end NoMinOrder +section limitRecOn -section IsPredArchimedean +section PartialOrder -variable [IsPredArchimedean α] +variable [PartialOrder α] [PredOrder α] [WellFoundedGT α] -protected theorem IsPredLimit.isMax (h : IsPredLimit a) : IsMax a := - (isPredLimit.dual h).isMin +/-- Recursion principle on a well-founded partial `PredOrder`. -/ +@[elab_as_elim] noncomputable def limitRecOn (b : α) + (hp : ∀ a, ¬ IsMin a → C a → C (Order.pred a)) + (hl : ∀ a, IsPredLimit a → (∀ b > a, C b) → C a) : C b := + SuccOrder.limitRecOn (α := αᵒᵈ) b hp fun a ha => hl a (isSuccLimit.dual ha) @[simp] -theorem isPredLimit_iff : IsPredLimit a ↔ IsMax a := - isSuccLimit_toDual_iff.symm.trans isSuccLimit_iff +theorem limitRecOn_limit (hp : ∀ a, ¬ IsMin a → C a → C (Order.pred a)) + (hl : ∀ a, IsPredLimit a → (∀ b > a, C b) → C a) (hb : IsPredLimit b) : + limitRecOn b hp hl = hl b hb fun x _ ↦ limitRecOn x hp hl := + SuccOrder.limitRecOn_limit _ _ (isPredLimit.dual hb) -theorem not_isPredLimit [NoMaxOrder α] : ¬IsPredLimit a := by simp +end PartialOrder -end IsPredArchimedean +section LinearOrder -end PartialOrder +variable [LinearOrder α] [PredOrder α] [WellFoundedGT α] + (hp : ∀ a, ¬ IsMin a → C a → C (Order.pred a)) (hl : ∀ a, IsPredLimit a → (∀ b > a, C b) → C a) -end Order +@[simp] +theorem limitRecOn_pred (hb : ¬ IsMin b) : + limitRecOn (Order.pred b) hp hl = hp b hb (limitRecOn b hp hl) := + SuccOrder.limitRecOn_succ (α := αᵒᵈ) _ _ hb + +end LinearOrder + +end limitRecOn + +end PredOrder diff --git a/Mathlib/Order/SuccPred/LinearLocallyFinite.lean b/Mathlib/Order/SuccPred/LinearLocallyFinite.lean index 3e7e6fbefc5d2..7dd5b3aa363f5 100644 --- a/Mathlib/Order/SuccPred/LinearLocallyFinite.lean +++ b/Mathlib/Order/SuccPred/LinearLocallyFinite.lean @@ -56,6 +56,40 @@ open Order variable {ι : Type*} [LinearOrder ι] +namespace LinearOrder + +variable [SuccOrder ι] [PredOrder ι] + +instance (priority := 100) isPredArchimedean_of_isSuccArchimedean [IsSuccArchimedean ι] : + IsPredArchimedean ι where + exists_pred_iterate_of_le {i j} hij := by + have h_exists := exists_succ_iterate_of_le hij + obtain ⟨n, hn_eq, hn_lt_ne⟩ : ∃ n, succ^[n] i = j ∧ ∀ m < n, succ^[m] i ≠ j := + ⟨Nat.find h_exists, Nat.find_spec h_exists, fun m hmn ↦ Nat.find_min h_exists hmn⟩ + refine ⟨n, ?_⟩ + rw [← hn_eq] + induction' n with n + · simp only [Function.iterate_zero, id] + · rw [pred_succ_iterate_of_not_isMax] + rw [Nat.succ_sub_succ_eq_sub, tsub_zero] + suffices succ^[n] i < succ^[n.succ] i from not_isMax_of_lt this + refine lt_of_le_of_ne ?_ ?_ + · rw [Function.iterate_succ'] + exact le_succ _ + · rw [hn_eq] + exact hn_lt_ne _ (Nat.lt_succ_self n) + +instance isSuccArchimedean_of_isPredArchimedean [IsPredArchimedean ι] : IsSuccArchimedean ι := + inferInstanceAs (IsSuccArchimedean ιᵒᵈᵒᵈ) + +/-- In a linear `SuccOrder` that's also a `PredOrder`, `IsSuccArchimedean` and `IsPredArchimedean` +are equivalent. -/ +theorem isSuccArchimedean_iff_isPredArchimedean : IsSuccArchimedean ι ↔ IsPredArchimedean ι := + ⟨fun _ => isPredArchimedean_of_isSuccArchimedean, + fun _ => isSuccArchimedean_of_isPredArchimedean⟩ + +end LinearOrder + namespace LinearLocallyFiniteOrder /-- Successor in a linear order. This defines a true successor only when `i` is isolated from above, @@ -109,15 +143,11 @@ noncomputable instance (priority := 100) [LocallyFiniteOrder ι] : SuccOrder ι le_succ := le_succFn max_of_succ_le h := isMax_of_succFn_le _ h succ_le_of_lt h := succFn_le_of_lt _ _ h - le_of_lt_succ h := le_of_lt_succFn _ _ h noncomputable instance (priority := 100) [LocallyFiniteOrder ι] : PredOrder ι := - (inferInstance : PredOrder (OrderDual ιᵒᵈ)) + inferInstanceAs (PredOrder ιᵒᵈᵒᵈ) -end LinearLocallyFiniteOrder - -instance (priority := 100) LinearLocallyFiniteOrder.isSuccArchimedean [LocallyFiniteOrder ι] : - IsSuccArchimedean ι where +instance (priority := 100) [LocallyFiniteOrder ι] : IsSuccArchimedean ι where exists_succ_iterate_of_le := by intro i j hij rw [le_iff_lt_or_eq] at hij @@ -146,28 +176,14 @@ instance (priority := 100) LinearLocallyFiniteOrder.isSuccArchimedean [LocallyFi have h_max : IsMax (succ^[n] i) := isMax_iterate_succ_of_eq_of_ne h_eq hnm.ne exact not_le.mpr (h_lt n) (h_max (h_lt n).le) -instance (priority := 100) LinearOrder.isPredArchimedean_of_isSuccArchimedean [SuccOrder ι] - [PredOrder ι] [IsSuccArchimedean ι] : IsPredArchimedean ι where - exists_pred_iterate_of_le := by - intro i j hij - have h_exists := exists_succ_iterate_of_le hij - obtain ⟨n, hn_eq, hn_lt_ne⟩ : ∃ n, succ^[n] i = j ∧ ∀ m < n, succ^[m] i ≠ j := - ⟨Nat.find h_exists, Nat.find_spec h_exists, fun m hmn ↦ Nat.find_min h_exists hmn⟩ - refine ⟨n, ?_⟩ - rw [← hn_eq] - induction' n with n - · simp only [Function.iterate_zero, id] - · rw [pred_succ_iterate_of_not_isMax] - rw [Nat.succ_sub_succ_eq_sub, tsub_zero] - suffices succ^[n] i < succ^[n.succ] i from not_isMax_of_lt this - refine lt_of_le_of_ne ?_ ?_ - · rw [Function.iterate_succ'] - exact le_succ _ - · rw [hn_eq] - exact hn_lt_ne _ (Nat.lt_succ_self n) +instance (priority := 100) [LocallyFiniteOrder ι] : IsPredArchimedean ι := + inferInstance + +end LinearLocallyFiniteOrder section toZ +-- Requiring either of `IsSuccArchimedean` or `IsPredArchimedean` is equivalent. variable [SuccOrder ι] [IsSuccArchimedean ι] [PredOrder ι] {i0 i : ι} -- For "to_Z" @@ -239,8 +255,8 @@ theorem toZ_iterate_succ_of_not_isMax (n : ℕ) (hn : ¬IsMax (succ^[n] i0)) : theorem toZ_iterate_pred_of_not_isMin (n : ℕ) (hn : ¬IsMin (pred^[n] i0)) : toZ i0 (pred^[n] i0) = -n := by - cases' n with n n - · simp only [Function.iterate_zero, id, toZ_of_eq, Nat.cast_zero, neg_zero]; rfl + cases' n with n + · simp have : pred^[n.succ] i0 < i0 := by refine lt_of_le_of_ne (pred_iterate_le _ _) fun h_pred_iterate_eq ↦ hn ?_ have h_pred_eq_pred : pred^[n.succ] i0 = pred^[0] i0 := by diff --git a/Mathlib/Order/SupIndep.lean b/Mathlib/Order/SupIndep.lean index e3a967e7b0c55..b973420ec6a20 100644 --- a/Mathlib/Order/SupIndep.lean +++ b/Mathlib/Order/SupIndep.lean @@ -138,7 +138,7 @@ theorem supIndep_pair [DecidableEq ι] {i j : ι} (hij : i ≠ j) : theorem supIndep_univ_bool (f : Bool → α) : (Finset.univ : Finset Bool).SupIndep f ↔ Disjoint (f false) (f true) := - haveI : true ≠ false := by simp only [Ne, not_false_iff] + haveI : true ≠ false := by simp only [Ne, not_false_iff, reduceCtorEq] (supIndep_pair this).trans disjoint_comm @[simp] diff --git a/Mathlib/Order/SymmDiff.lean b/Mathlib/Order/SymmDiff.lean index f16a508003350..8805a9c3184ad 100644 --- a/Mathlib/Order/SymmDiff.lean +++ b/Mathlib/Order/SymmDiff.lean @@ -397,7 +397,7 @@ theorem symmDiff_symmDiff_right : theorem symmDiff_assoc : a ∆ b ∆ c = a ∆ (b ∆ c) := by rw [symmDiff_symmDiff_left, symmDiff_symmDiff_right] -instance symmDiff_isAssociative : Std.Associative (α := α) (· ∆ ·) := +instance symmDiff_isAssociative : Std.Associative (α := α) (· ∆ ·) := ⟨symmDiff_assoc⟩ theorem symmDiff_left_comm : a ∆ (b ∆ c) = b ∆ (a ∆ c) := by diff --git a/Mathlib/Order/Synonym.lean b/Mathlib/Order/Synonym.lean index 70558d627478e..1ff3b4dca5241 100644 --- a/Mathlib/Order/Synonym.lean +++ b/Mathlib/Order/Synonym.lean @@ -44,11 +44,11 @@ namespace OrderDual instance [h : Nontrivial α] : Nontrivial αᵒᵈ := h -/-- `toDual` is the identity function to the `OrderDual` of a linear order. -/ +/-- `toDual` is the identity function to the `OrderDual` of a linear order. -/ def toDual : α ≃ αᵒᵈ := Equiv.refl _ -/-- `ofDual` is the identity function from the `OrderDual` of a linear order. -/ +/-- `ofDual` is the identity function from the `OrderDual` of a linear order. -/ def ofDual : αᵒᵈ ≃ α := Equiv.refl _ @@ -134,12 +134,12 @@ end OrderDual def Lex (α : Type*) := α -/-- `toLex` is the identity function to the `Lex` of a type. -/ +/-- `toLex` is the identity function to the `Lex` of a type. -/ @[match_pattern] def toLex : α ≃ Lex α := Equiv.refl _ -/-- `ofLex` is the identity function from the `Lex` of a type. -/ +/-- `ofLex` is the identity function from the `Lex` of a type. -/ @[match_pattern] def ofLex : Lex α ≃ α := Equiv.refl _ diff --git a/Mathlib/Order/TypeTags.lean b/Mathlib/Order/TypeTags.lean new file mode 100644 index 0000000000000..37df7cf0f1e86 --- /dev/null +++ b/Mathlib/Order/TypeTags.lean @@ -0,0 +1,151 @@ +/- +Copyright (c) 2018 Mario Carneiro. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Mario Carneiro, Simon Hudon, Yury Kudryashov +-/ +import Mathlib.Order.Notation +import Mathlib.Data.Nat.Notation + +/-! +# Order-related type synonyms + +In this file we define `WithBot`, `WithTop`, `ENat`, and `PNat`. +The definitions were moved to this file without any theory +so that, e.g., `Data/Countable/Basic` can prove `Countable ENat` +without exploding its imports. +-/ + +variable {α : Type*} + +/-- Attach `⊥` to a type. -/ +def WithBot (α : Type*) := Option α + +namespace WithBot + +instance [Repr α] : Repr (WithBot α) := + ⟨fun o _ => + match o with + | none => "⊥" + | some a => "↑" ++ repr a⟩ + +/-- The canonical map from `α` into `WithBot α` -/ +@[coe, match_pattern] def some : α → WithBot α := + Option.some + +-- Porting note: changed this from `CoeTC` to `Coe` but I am not 100% confident that's correct. +instance coe : Coe α (WithBot α) := + ⟨some⟩ + +instance bot : Bot (WithBot α) := + ⟨none⟩ + +instance inhabited : Inhabited (WithBot α) := + ⟨⊥⟩ + +/-- Recursor for `WithBot` using the preferred forms `⊥` and `↑a`. -/ +@[elab_as_elim, induction_eliminator, cases_eliminator] +def recBotCoe {C : WithBot α → Sort*} (bot : C ⊥) (coe : ∀ a : α, C a) : ∀ n : WithBot α, C n + | ⊥ => bot + | (a : α) => coe a + +@[simp] +theorem recBotCoe_bot {C : WithBot α → Sort*} (d : C ⊥) (f : ∀ a : α, C a) : + @recBotCoe _ C d f ⊥ = d := + rfl + +@[simp] +theorem recBotCoe_coe {C : WithBot α → Sort*} (d : C ⊥) (f : ∀ a : α, C a) (x : α) : + @recBotCoe _ C d f ↑x = f x := + rfl + +end WithBot + +--TODO(Mario): Construct using order dual on `WithBot` +/-- Attach `⊤` to a type. -/ +def WithTop (α : Type*) := + Option α + +namespace WithTop + +instance [Repr α] : Repr (WithTop α) := + ⟨fun o _ => + match o with + | none => "⊤" + | some a => "↑" ++ repr a⟩ + +/-- The canonical map from `α` into `WithTop α` -/ +@[coe, match_pattern] def some : α → WithTop α := + Option.some + +instance coeTC : CoeTC α (WithTop α) := + ⟨some⟩ + +instance top : Top (WithTop α) := + ⟨none⟩ + +instance inhabited : Inhabited (WithTop α) := + ⟨⊤⟩ + +/-- Recursor for `WithTop` using the preferred forms `⊤` and `↑a`. -/ +@[elab_as_elim, induction_eliminator, cases_eliminator] +def recTopCoe {C : WithTop α → Sort*} (top : C ⊤) (coe : ∀ a : α, C a) : ∀ n : WithTop α, C n + | none => top + | Option.some a => coe a + +@[simp] +theorem recTopCoe_top {C : WithTop α → Sort*} (d : C ⊤) (f : ∀ a : α, C a) : + @recTopCoe _ C d f ⊤ = d := + rfl + +@[simp] +theorem recTopCoe_coe {C : WithTop α → Sort*} (d : C ⊤) (f : ∀ a : α, C a) (x : α) : + @recTopCoe _ C d f ↑x = f x := + rfl + +end WithTop + +/-- Extended natural numbers `ℕ∞ = WithTop ℕ`. -/ +def ENat : Type := WithTop ℕ deriving Top, Inhabited + +@[inherit_doc] notation "ℕ∞" => ENat + +namespace ENat + +instance instNatCast : NatCast ℕ∞ := ⟨WithTop.some⟩ + +-- Porting note (#11445): new definition copied from `WithTop` +/-- Recursor for `ENat` using the preferred forms `⊤` and `↑a`. -/ +@[elab_as_elim, induction_eliminator, cases_eliminator] +def recTopCoe {C : ℕ∞ → Sort*} (top : C ⊤) (coe : ∀ a : ℕ, C a) : ∀ n : ℕ∞, C n + | none => top + | Option.some a => coe a + +@[simp] +theorem recTopCoe_top {C : ℕ∞ → Sort*} (d : C ⊤) (f : ∀ a : ℕ, C a) : + @recTopCoe C d f ⊤ = d := + rfl + +@[simp] +theorem recTopCoe_coe {C : ℕ∞ → Sort*} (d : C ⊤) (f : ∀ a : ℕ, C a) (x : ℕ) : + @recTopCoe C d f ↑x = f x := + rfl + +end ENat + +/-- `ℕ+` is the type of positive natural numbers. It is defined as a subtype, + and the VM representation of `ℕ+` is the same as `ℕ` because the proof + is not stored. -/ +def PNat := { n : ℕ // 0 < n } deriving DecidableEq + +@[inherit_doc] +notation "ℕ+" => PNat + +/-- The underlying natural number -/ +@[coe] +def PNat.val : ℕ+ → ℕ := Subtype.val + +instance coePNatNat : Coe ℕ+ ℕ := + ⟨PNat.val⟩ + +instance : Repr ℕ+ := + ⟨fun n n' => reprPrec n.1 n'⟩ diff --git a/Mathlib/Order/UpperLower/Basic.lean b/Mathlib/Order/UpperLower/Basic.lean index efe287062c81e..1c2dbcf53ed26 100644 --- a/Mathlib/Order/UpperLower/Basic.lean +++ b/Mathlib/Order/UpperLower/Basic.lean @@ -1802,3 +1802,5 @@ theorem lowerClosure_prod (s : Set α) (t : Set β) : simp [Prod.le_def, @and_and_and_comm _ (_ ∈ t)] end Preorder + +set_option linter.style.longFile 1900 diff --git a/Mathlib/Order/WellFounded.lean b/Mathlib/Order/WellFounded.lean index 107a3a70cbacc..cacf754c0c287 100644 --- a/Mathlib/Order/WellFounded.lean +++ b/Mathlib/Order/WellFounded.lean @@ -133,7 +133,7 @@ private theorem eq_strictMono_iff_eq_range_aux {f g : β → γ} (hf : StrictMon obtain ⟨c, hc⟩ : g b ∈ Set.range f := by rw [hfg] exact Set.mem_range_self b - cases' lt_or_le c b with hcb hbc + rcases lt_or_le c b with hcb | hbc · rw [H c hcb] at hc rw [hg.injective hc] at hcb exact hcb.false.elim @@ -280,3 +280,15 @@ theorem StrictAnti.wellFoundedGT [WellFoundedLT β] (hf : StrictAnti f) : WellFo StrictMono.wellFoundedLT (α := αᵒᵈ) (fun _ _ h ↦ hf h) end WellFoundedLT + +/-- A nonempty linear order with well-founded `<` has a bottom element. -/ +noncomputable def WellFoundedLT.toOrderBot {α} [LinearOrder α] [Nonempty α] [h : WellFoundedLT α] : + OrderBot α where + bot := h.wf.min _ Set.univ_nonempty + bot_le a := h.wf.min_le (Set.mem_univ a) + +/-- A nonempty linear order with well-founded `>` has a top element. -/ +noncomputable def WellFoundedGT.toOrderTop {α} [LinearOrder α] [Nonempty α] [WellFoundedGT α] : + OrderTop α := + have := WellFoundedLT.toOrderBot (α := αᵒᵈ) + inferInstanceAs (OrderTop αᵒᵈᵒᵈ) diff --git a/Mathlib/Order/WellFoundedSet.lean b/Mathlib/Order/WellFoundedSet.lean index 84f0ca38e5c7b..5e939f8f9b787 100644 --- a/Mathlib/Order/WellFoundedSet.lean +++ b/Mathlib/Order/WellFoundedSet.lean @@ -695,7 +695,7 @@ theorem iff_not_exists_isMinBadSeq (rk : α → ℕ) {s : Set α} : /-- Higman's Lemma, which states that for any reflexive, transitive relation `r` which is partially well-ordered on a set `s`, the relation `List.SublistForall₂ r` is partially well-ordered on the set of lists of elements of `s`. That relation is defined so that - `List.SublistForall₂ r l₁ l₂` whenever `l₁` related pointwise by `r` to a sublist of `l₂`. -/ + `List.SublistForall₂ r l₁ l₂` whenever `l₁` related pointwise by `r` to a sublist of `l₂`. -/ theorem partiallyWellOrderedOn_sublistForall₂ (r : α → α → Prop) [IsRefl α r] [IsTrans α r] {s : Set α} (h : s.PartiallyWellOrderedOn r) : { l : List α | ∀ x, x ∈ l → x ∈ s }.PartiallyWellOrderedOn (List.SublistForall₂ r) := by diff --git a/Mathlib/Order/WithBot.lean b/Mathlib/Order/WithBot.lean index 364cc4b359466..81a092fceb2e0 100644 --- a/Mathlib/Order/WithBot.lean +++ b/Mathlib/Order/WithBot.lean @@ -6,7 +6,9 @@ Authors: Johannes Hölzl import Mathlib.Init.Algebra.Classes import Mathlib.Logic.Nontrivial.Basic import Mathlib.Order.BoundedOrder +import Mathlib.Order.TypeTags import Mathlib.Data.Option.NAry +import Mathlib.Tactic.Contrapose import Mathlib.Tactic.Lift import Mathlib.Data.Option.Basic @@ -23,34 +25,10 @@ Adding a `bot` or a `top` to an order. variable {α β γ δ : Type*} -/-- Attach `⊥` to a type. -/ -def WithBot (α : Type*) := - Option α - namespace WithBot variable {a b : α} -instance [Repr α] : Repr (WithBot α) := - ⟨fun o _ => - match o with - | none => "⊥" - | some a => "↑" ++ repr a⟩ - -/-- The canonical map from `α` into `WithBot α` -/ -@[coe, match_pattern] def some : α → WithBot α := - Option.some - --- Porting note: changed this from `CoeTC` to `Coe` but I am not 100% confident that's correct. -instance coe : Coe α (WithBot α) := - ⟨some⟩ - -instance bot : Bot (WithBot α) := - ⟨none⟩ - -instance inhabited : Inhabited (WithBot α) := - ⟨⊥⟩ - instance nontrivial [Nonempty α] : Nontrivial (WithBot α) := Option.nontrivial @@ -83,22 +61,6 @@ theorem bot_ne_coe : ⊥ ≠ (a : WithBot α) := theorem coe_ne_bot : (a : WithBot α) ≠ ⊥ := nofun -/-- Recursor for `WithBot` using the preferred forms `⊥` and `↑a`. -/ -@[elab_as_elim, induction_eliminator, cases_eliminator] -def recBotCoe {C : WithBot α → Sort*} (bot : C ⊥) (coe : ∀ a : α, C a) : ∀ n : WithBot α, C n - | ⊥ => bot - | (a : α) => coe a - -@[simp] -theorem recBotCoe_bot {C : WithBot α → Sort*} (d : C ⊥) (f : ∀ a : α, C a) : - @recBotCoe _ C d f ⊥ = d := - rfl - -@[simp] -theorem recBotCoe_coe {C : WithBot α → Sort*} (d : C ⊥) (f : ∀ a : α, C a) (x : α) : - @recBotCoe _ C d f ↑x = f x := - rfl - /-- Specialization of `Option.getD` to values in `WithBot α` that respects API boundaries. -/ def unbot' (d : α) (x : WithBot α) : α := @@ -340,13 +302,15 @@ instance preorder [Preorder α] : Preorder (WithBot α) where instance partialOrder [PartialOrder α] : PartialOrder (WithBot α) := { WithBot.preorder with - le_antisymm := fun o₁ o₂ h₁ h₂ => by - cases' o₁ with a - · cases' o₂ with b - · rfl - rcases h₂ b rfl with ⟨_, ⟨⟩, _⟩ - · rcases h₁ a rfl with ⟨b, ⟨⟩, h₁'⟩ - rcases h₂ b rfl with ⟨_, ⟨⟩, h₂'⟩ + le_antisymm := fun o₁ o₂ h₁ h₂ ↦ by + cases o₁ with + | bot => + cases o₂ with + | bot => rfl + | coe b => obtain ⟨_, ⟨⟩, _⟩ := h₂ b rfl + | coe a => + obtain ⟨b, ⟨⟩, h₁'⟩ := h₁ a rfl + obtain ⟨_, ⟨⟩, h₂'⟩ := h₂ b rfl rw [le_antisymm h₁' h₂'] } section Preorder @@ -416,12 +380,19 @@ instance semilatticeSup [SemilatticeSup α] : SemilatticeSup (WithBot α) where le_sup_left := fun o₁ o₂ a ha => by cases ha; cases o₂ <;> simp le_sup_right := fun o₁ o₂ a ha => by cases ha; cases o₁ <;> simp sup_le := fun o₁ o₂ o₃ h₁ h₂ a ha => by - cases' o₁ with b <;> cases' o₂ with c <;> cases ha - · exact h₂ a rfl - · exact h₁ a rfl - · rcases h₁ b rfl with ⟨d, ⟨⟩, h₁'⟩ - simp only [coe_le_coe] at h₂ - exact ⟨d, rfl, sup_le h₁' h₂⟩ + cases o₁ with + | bot => + cases o₂ with + | bot => exact h₁ a ha + | coe c => exact h₂ a ha + | coe b => + cases o₂ with + | bot => exact h₁ a ha + | coe c => + cases ha + obtain ⟨d, ⟨⟩, h₁'⟩ := h₁ b rfl + simp only [coe_le_coe] at h₂ + exact ⟨d, rfl, sup_le h₁' h₂⟩ theorem coe_sup [SemilatticeSup α] (a b : α) : ((a ⊔ b : α) : WithBot α) = (a : WithBot α) ⊔ b := rfl @@ -559,34 +530,10 @@ instance noMaxOrder [LT α] [NoMaxOrder α] [Nonempty α] : NoMaxOrder (WithBot end WithBot ---TODO(Mario): Construct using order dual on `WithBot` -/-- Attach `⊤` to a type. -/ -def WithTop (α : Type*) := - Option α - namespace WithTop variable {a b : α} -instance [Repr α] : Repr (WithTop α) := - ⟨fun o _ => - match o with - | none => "⊤" - | some a => "↑" ++ repr a⟩ - -/-- The canonical map from `α` into `WithTop α` -/ -@[coe, match_pattern] def some : α → WithTop α := - Option.some - -instance coeTC : CoeTC α (WithTop α) := - ⟨some⟩ - -instance top : Top (WithTop α) := - ⟨none⟩ - -instance inhabited : Inhabited (WithTop α) := - ⟨⊤⟩ - instance nontrivial [Nonempty α] : Nontrivial (WithTop α) := Option.nontrivial @@ -619,22 +566,6 @@ theorem top_ne_coe : ⊤ ≠ (a : WithTop α) := theorem coe_ne_top : (a : WithTop α) ≠ ⊤ := nofun -/-- Recursor for `WithTop` using the preferred forms `⊤` and `↑a`. -/ -@[elab_as_elim, induction_eliminator, cases_eliminator] -def recTopCoe {C : WithTop α → Sort*} (top : C ⊤) (coe : ∀ a : α, C a) : ∀ n : WithTop α, C n - | none => top - | Option.some a => coe a - -@[simp] -theorem recTopCoe_top {C : WithTop α → Sort*} (d : C ⊤) (f : ∀ a : α, C a) : - @recTopCoe _ C d f ⊤ = d := - rfl - -@[simp] -theorem recTopCoe_coe {C : WithTop α → Sort*} (d : C ⊤) (f : ∀ a : α, C a) (x : α) : - @recTopCoe _ C d f ↑x = f x := - rfl - /-- `WithTop.toDual` is the equivalence sending `⊤` to `⊥` and any `a : α` to `toDual a : αᵒᵈ`. See `WithTop.toDualBotEquiv` for the related order-iso. -/ @@ -973,7 +904,33 @@ theorem ofDual_map (f : αᵒᵈ → βᵒᵈ) (a : WithBot αᵒᵈ) : lemma forall_lt_iff_eq_bot [Preorder α] {x : WithBot α} : (∀ y : α, x < y) ↔ x = ⊥ := - ⟨fun h ↦ forall_ne_iff_eq_bot.mp (fun x ↦ (h x).ne'), fun h ↦ h ▸ fun y ↦ bot_lt_coe y⟩ + ⟨fun h ↦ forall_ne_iff_eq_bot.mp (fun x ↦ (h x).ne'), fun h y ↦ h ▸ bot_lt_coe y⟩ + +lemma forall_le_iff_eq_bot [Preorder α] [NoMinOrder α] {x : WithBot α} : + (∀ y : α, x ≤ y) ↔ x = ⊥ := by + refine ⟨fun h ↦ forall_lt_iff_eq_bot.1 fun y ↦ ?_, fun h _ ↦ h ▸ bot_le⟩ + obtain ⟨w, hw⟩ := exists_lt y + exact (h w).trans_lt (coe_lt_coe.2 hw) + +lemma le_of_forall_lt_iff_le [LinearOrder α] [DenselyOrdered α] [NoMinOrder α] + {x y : WithBot α} : (∀ z : α, x < z → y ≤ z) ↔ y ≤ x := by + refine ⟨fun h ↦ ?_, fun h z x_z ↦ h.trans x_z.le⟩ + induction x with + | bot => exact le_of_eq <| forall_le_iff_eq_bot.1 fun z ↦ h z (bot_lt_coe z) + | coe x => + rw [le_coe_iff] + rintro y rfl + exact le_of_forall_le_of_dense (by exact_mod_cast h) + +lemma ge_of_forall_gt_iff_ge [LinearOrder α] [DenselyOrdered α] [NoMinOrder α] + {x y : WithBot α} : (∀ z : α, z < x → z ≤ y) ↔ x ≤ y := by + apply Iff.intro _ (fun h _ x_z ↦ x_z.le.trans h) + induction y with + | bot => simpa using forall_le_iff_eq_bot.1 + | coe y => + rw [le_coe_iff] + rintro h x rfl + exact le_of_forall_ge_of_dense (by exact_mod_cast h) section LE @@ -1142,11 +1099,22 @@ theorem coe_untop'_le (a : WithTop α) (b : α) : a.untop' b ≤ a := theorem coe_top_lt [OrderTop α] {x : WithTop α} : (⊤ : α) < x ↔ x = ⊤ := WithBot.lt_coe_bot (α := αᵒᵈ) -lemma forall_lt_iff_eq_top {x : WithTop α} : (∀ y : α, y < x) ↔ x = ⊤ := - ⟨fun h ↦ forall_ne_iff_eq_top.mp (fun x ↦ (h x).ne), fun h ↦ h ▸ fun y ↦ coe_lt_top y⟩ +lemma forall_gt_iff_eq_top {x : WithTop α} : (∀ y : α, y < x) ↔ x = ⊤ := + WithBot.forall_lt_iff_eq_bot (α := αᵒᵈ) + +lemma forall_ge_iff_eq_top [NoMaxOrder α] {x : WithTop α} : (∀ y : α, y ≤ x) ↔ x = ⊤ := + WithBot.forall_le_iff_eq_bot (α := αᵒᵈ) end Preorder +lemma le_of_forall_lt_iff_le [LinearOrder α] [DenselyOrdered α] [NoMaxOrder α] + {x y : WithTop α} : (∀ z : α, x < z → y ≤ z) ↔ y ≤ x := + WithBot.ge_of_forall_gt_iff_ge (α := αᵒᵈ) + +lemma ge_of_forall_gt_iff_ge [LinearOrder α] [DenselyOrdered α] [NoMaxOrder α] + {x y : WithTop α} : (∀ z : α, z < x → z ≤ y) ↔ x ≤ y := + WithBot.le_of_forall_lt_iff_le (α := αᵒᵈ) + instance semilatticeInf [SemilatticeInf α] : SemilatticeInf (WithTop α) := { WithTop.partialOrder with inf := Option.liftOrGet (· ⊓ ·), diff --git a/Mathlib/Order/Zorn.lean b/Mathlib/Order/Zorn.lean index e31a5347f9d81..8c519e1bbaec1 100644 --- a/Mathlib/Order/Zorn.lean +++ b/Mathlib/Order/Zorn.lean @@ -59,8 +59,6 @@ Originally ported from Isabelle/HOL. The Fleuriot, Tobias Nipkow, Christian Sternagel. -/ - -open scoped Classical open Set variable {α β : Type*} {r : α → α → Prop} {c : Set α} diff --git a/Mathlib/Probability/BorelCantelli.lean b/Mathlib/Probability/BorelCantelli.lean index a1f404dfaedf6..be4a2299f904e 100644 --- a/Mathlib/Probability/BorelCantelli.lean +++ b/Mathlib/Probability/BorelCantelli.lean @@ -29,7 +29,7 @@ open MeasureTheory namespace ProbabilityTheory -variable {Ω : Type*} {m0 : MeasurableSpace Ω} {μ : Measure Ω} [IsProbabilityMeasure μ] +variable {Ω : Type*} {m0 : MeasurableSpace Ω} {μ : Measure Ω} section BorelCantelli @@ -45,8 +45,9 @@ theorem iIndepFun.indep_comap_natural_of_lt (hf : ∀ i, StronglyMeasurable (f i theorem iIndepFun.condexp_natural_ae_eq_of_lt [SecondCountableTopology β] [CompleteSpace β] [NormedSpace ℝ β] (hf : ∀ i, StronglyMeasurable (f i)) (hfi : iIndepFun (fun _ => mβ) f μ) - (hij : i < j) : μ[f j|Filtration.natural f hf i] =ᵐ[μ] fun _ => μ[f j] := - condexp_indep_eq (hf j).measurable.comap_le (Filtration.le _ _) + (hij : i < j) : μ[f j|Filtration.natural f hf i] =ᵐ[μ] fun _ => μ[f j] := by + have : IsProbabilityMeasure μ := hfi.isProbabilityMeasure + exact condexp_indep_eq (hf j).measurable.comap_le (Filtration.le _ _) (comap_measurable <| f j).stronglyMeasurable (hfi.indep_comap_natural_of_lt hf hij) theorem iIndepSet.condexp_indicator_filtrationOfSet_ae_eq (hsm : ∀ n, MeasurableSet (s n)) @@ -63,6 +64,7 @@ open Filter `∑ n, μ sₙ = ∞`, `limsup sₙ` has measure 1. -/ theorem measure_limsup_eq_one {s : ℕ → Set Ω} (hsm : ∀ n, MeasurableSet (s n)) (hs : iIndepSet s μ) (hs' : (∑' n, μ (s n)) = ∞) : μ (limsup s atTop) = 1 := by + have : IsProbabilityMeasure μ := hs.isProbabilityMeasure rw [measure_congr (eventuallyEq_set.2 (ae_mem_limsup_atTop_iff μ <| measurableSet_filtrationOfSet' hsm) : (limsup s atTop : Set Ω) =ᵐ[μ] {ω | Tendsto (fun n => ∑ k ∈ Finset.range n, @@ -90,7 +92,7 @@ theorem measure_limsup_eq_one {s : ℕ → Set Ω} (hsm : ∀ n, MeasurableSet ( · refine ⟨n, ?_⟩ rw [ENNReal.toReal_sum] exact fun _ _ => measure_ne_top _ _ - · rw [not_lt, ← ENNReal.toReal_le_toReal (ENNReal.sum_lt_top _).ne ENNReal.coe_ne_top] + · rw [not_lt, ← ENNReal.toReal_le_toReal (ENNReal.sum_ne_top.2 _) ENNReal.coe_ne_top] · exact hB.trans (by simp) · exact fun _ _ => measure_ne_top _ _ diff --git a/Mathlib/Probability/CDF.lean b/Mathlib/Probability/CDF.lean index f17cc568c2d9e..ae51880f7f115 100644 --- a/Mathlib/Probability/CDF.lean +++ b/Mathlib/Probability/CDF.lean @@ -70,7 +70,6 @@ lemma tendsto_cdf_atBot : Tendsto (cdf μ) atBot (𝓝 0) := tendsto_condCDF_atB lemma tendsto_cdf_atTop : Tendsto (cdf μ) atTop (𝓝 1) := tendsto_condCDF_atTop _ _ lemma ofReal_cdf [IsProbabilityMeasure μ] (x : ℝ) : ENNReal.ofReal (cdf μ x) = μ (Iic x) := by - have := IsProbabilityMeasure.toIsFiniteMeasure (Measure.prod (Measure.dirac ()) μ) have h := lintegral_condCDF ((Measure.dirac Unit.unit).prod μ) x simpa only [MeasureTheory.Measure.fst_prod, Measure.prod_prod, measure_univ, one_mul, lintegral_dirac] using h diff --git a/Mathlib/Probability/CondCount.lean b/Mathlib/Probability/CondCount.lean index 6eb8dc1795d29..1ea9812d6c2f6 100644 --- a/Mathlib/Probability/CondCount.lean +++ b/Mathlib/Probability/CondCount.lean @@ -52,6 +52,9 @@ This is a probability measure when `s` is finite and nonempty and is given by 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] @@ -72,11 +75,10 @@ theorem condCount_univ [Fintype Ω] {s : Set Ω} : variable [MeasurableSingletonClass Ω] theorem condCount_isProbabilityMeasure {s : Set Ω} (hs : s.Finite) (hs' : s.Nonempty) : - IsProbabilityMeasure (condCount s) := - { measure_univ := by - rw [condCount, cond_apply _ hs.measurableSet, Set.inter_univ, 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 } + 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 diff --git a/Mathlib/Probability/ConditionalProbability.lean b/Mathlib/Probability/ConditionalProbability.lean index 7a9f4513f7f3a..aa9148f363412 100644 --- a/Mathlib/Probability/ConditionalProbability.lean +++ b/Mathlib/Probability/ConditionalProbability.lean @@ -97,11 +97,15 @@ is a probability measure. -/ theorem cond_isProbabilityMeasure [IsFiniteMeasure μ] (hcs : μ s ≠ 0) : IsProbabilityMeasure μ[|s] := cond_isProbabilityMeasure_of_finite μ hcs (measure_ne_top μ s) -instance cond_isFiniteMeasure : IsFiniteMeasure μ[|s] := by +instance : IsZeroOrProbabilityMeasure μ[|s] := by constructor - simp only [Measure.coe_smul, Pi.smul_apply, MeasurableSet.univ, Measure.restrict_apply, - Set.univ_inter, smul_eq_mul, ProbabilityTheory.cond, ← ENNReal.div_eq_inv_mul] - exact ENNReal.div_self_le_one.trans_lt ENNReal.one_lt_top + simp only [cond, Measure.coe_smul, Pi.smul_apply, MeasurableSet.univ, Measure.restrict_apply, + univ_inter, smul_eq_mul, ← ENNReal.div_eq_inv_mul] + rcases eq_or_ne (μ s) 0 with h | h + · simp [h] + rcases eq_or_ne (μ s) ∞ with h' | h' + · simp [h'] + simp [ENNReal.div_self h h'] theorem cond_toMeasurable_eq : μ[|(toMeasurable μ s)] = μ[|s] := by @@ -140,6 +144,9 @@ theorem cond_apply (hms : MeasurableSet s) (t : Set Ω) : μ[t|s] = (μ s)⁻¹ theorem cond_apply' {t : Set Ω} (hA : MeasurableSet t) : μ[t|s] = (μ s)⁻¹ * μ (s ∩ t) := by rw [cond, Measure.smul_apply, Measure.restrict_apply hA, Set.inter_comm, smul_eq_mul] +@[simp] lemma cond_apply_self (hs₀ : μ s ≠ 0) (hs : μ s ≠ ∞) : μ[s|s] = 1 := by + simpa [cond] using ENNReal.inv_mul_cancel hs₀ hs + theorem cond_inter_self (hms : MeasurableSet s) (t : Set Ω) : μ[s ∩ t|s] = μ[t|s] := by rw [cond_apply _ hms, ← Set.inter_assoc, Set.inter_self, ← cond_apply _ hms] diff --git a/Mathlib/Probability/Distributions/Exponential.lean b/Mathlib/Probability/Distributions/Exponential.lean index fb141c97472bc..2a2c503ce5f51 100644 --- a/Mathlib/Probability/Distributions/Exponential.lean +++ b/Mathlib/Probability/Distributions/Exponential.lean @@ -73,7 +73,7 @@ lemma measurable_exponentialPDFReal (r : ℝ) : Measurable (exponentialPDFReal r lemma exponentialPDFReal_pos {x r : ℝ} (hr : 0 < r) (hx : 0 < x) : 0 < exponentialPDFReal r x := gammaPDFReal_pos zero_lt_one hr hx -/-- The exponential pdf is nonnegative-/ +/-- The exponential pdf is nonnegative -/ lemma exponentialPDFReal_nonneg {r : ℝ} (hr : 0 < r) (x : ℝ) : 0 ≤ exponentialPDFReal r x := gammaPDFReal_nonneg zero_lt_one hr x diff --git a/Mathlib/Probability/Distributions/Gaussian.lean b/Mathlib/Probability/Distributions/Gaussian.lean index b31dba6a5ddf3..10a5c010266d0 100644 --- a/Mathlib/Probability/Distributions/Gaussian.lean +++ b/Mathlib/Probability/Distributions/Gaussian.lean @@ -93,7 +93,7 @@ lemma integrable_gaussianPDFReal (μ : ℝ) (v : ℝ≥0) : field_simp exact Integrable.comp_sub_right hg μ -/-- The gaussian distribution pdf integrates to 1 when the variance is not zero. -/ +/-- The gaussian distribution pdf integrates to 1 when the variance is not zero. -/ lemma lintegral_gaussianPDFReal_eq_one (μ : ℝ) {v : ℝ≥0} (h : v ≠ 0) : ∫⁻ x, ENNReal.ofReal (gaussianPDFReal μ v x) = 1 := by rw [← ENNReal.toReal_eq_one_iff] @@ -112,7 +112,7 @@ lemma lintegral_gaussianPDFReal_eq_one (μ : ℝ) {v : ℝ≥0} (h : v ≠ 0) : ring · positivity -/-- The gaussian distribution pdf integrates to 1 when the variance is not zero. -/ +/-- The gaussian distribution pdf integrates to 1 when the variance is not zero. -/ lemma integral_gaussianPDFReal_eq_one (μ : ℝ) {v : ℝ≥0} (hv : v ≠ 0) : ∫ x, gaussianPDFReal μ v x = 1 := by have h := lintegral_gaussianPDFReal_eq_one μ hv @@ -283,7 +283,7 @@ lemma gaussianReal_map_const_mul (c : ℝ) : rw [Measure.map_const] simp only [ne_eq, measure_univ, one_smul, mul_eq_zero] convert (gaussianReal_zero_var 0).symm - simp only [ne_eq, zero_pow, mul_eq_zero, hv, or_false, not_false_eq_true] + simp only [ne_eq, zero_pow, mul_eq_zero, hv, or_false, not_false_eq_true, reduceCtorEq] rfl let e : ℝ ≃ᵐ ℝ := (Homeomorph.mulLeft₀ c hc).symm.toMeasurableEquiv have he' : ∀ x, HasDerivAt e ((fun _ ↦ c⁻¹) x) x := by diff --git a/Mathlib/Probability/Distributions/Uniform.lean b/Mathlib/Probability/Distributions/Uniform.lean index 18d02e427ea51..67f4746b80fcf 100644 --- a/Mathlib/Probability/Distributions/Uniform.lean +++ b/Mathlib/Probability/Distributions/Uniform.lean @@ -158,8 +158,8 @@ theorem mul_pdf_integrable (hcs : IsCompact s) (huX : IsUniform X s ℙ) : simp only [ind, this, lintegral_indicator _ hcs.measurableSet, mul_one, Algebra.id.smul_eq_mul, Pi.one_apply, Pi.smul_apply] rw [lintegral_mul_const _ measurable_nnnorm.coe_nnreal_ennreal] - exact (ENNReal.mul_lt_top (setLIntegral_lt_top_of_isCompact hnt.2 hcs continuous_nnnorm).ne - (ENNReal.inv_lt_top.2 (pos_iff_ne_zero.mpr hnt.1)).ne).ne + exact ENNReal.mul_ne_top (setLIntegral_lt_top_of_isCompact hnt.2 hcs continuous_nnnorm).ne + (ENNReal.inv_lt_top.2 (pos_iff_ne_zero.mpr hnt.1)).ne /-- A real uniform random variable `X` with support `s` has expectation `(λ s)⁻¹ * ∫ x in s, x ∂λ` where `λ` is the Lebesgue measure. -/ diff --git a/Mathlib/Probability/Independence/Basic.lean b/Mathlib/Probability/Independence/Basic.lean index 3ff422fb422f8..cd225daccfa3e 100644 --- a/Mathlib/Probability/Independence/Basic.lean +++ b/Mathlib/Probability/Independence/Basic.lean @@ -144,6 +144,9 @@ lemma iIndepSets.meas_biInter (h : iIndepSets π μ) (s : Finset ι) {f : ι → (hf : ∀ i, i ∈ s → f i ∈ π i) : μ (⋂ i ∈ s, f i) = ∏ i ∈ s, μ (f i) := (iIndepSets_iff _ _).1 h s hf +lemma iIndepSets.isProbabilityMeasure (h : iIndepSets π μ) : IsProbabilityMeasure μ := + ⟨by simpa using h ∅ (f := fun _ ↦ univ)⟩ + lemma iIndepSets.meas_iInter [Fintype ι] (h : iIndepSets π μ) (hs : ∀ i, s i ∈ π i) : μ (⋂ i, s i) = ∏ i, μ (s i) := by simp [← h.meas_biInter _ fun _i _ ↦ hs _] @@ -159,6 +162,9 @@ lemma iIndep.iIndepSets' {m : ι → MeasurableSpace Ω} {_ : MeasurableSpace Ω} {μ : Measure Ω} (hμ : iIndep m μ) : iIndepSets (fun x ↦ {s | MeasurableSet[m x] s}) μ := (iIndep_iff_iIndepSets _ _).1 hμ +lemma iIndep.isProbabilityMeasure (h : iIndep m μ) : IsProbabilityMeasure μ := + h.iIndepSets'.isProbabilityMeasure + lemma iIndep_iff (m : ι → MeasurableSpace Ω) {_mΩ : MeasurableSpace Ω} (μ : Measure Ω) : iIndep m μ ↔ ∀ (s : Finset ι) {f : ι → Set Ω} (_H : ∀ i, i ∈ s → MeasurableSet[m i] (f i)), μ (⋂ i ∈ s, f i) = ∏ i ∈ s, μ (f i) := by @@ -183,6 +189,9 @@ lemma iIndepSet_iff_iIndep (s : ι → Set Ω) (μ : Measure Ω) : iIndepSet s μ ↔ iIndep (fun i ↦ generateFrom {s i}) μ := by simp only [iIndepSet, iIndep, Kernel.iIndepSet] +lemma iIndepSet.isProbabilityMeasure (h : iIndepSet s μ) : IsProbabilityMeasure μ := + ((iIndepSet_iff_iIndep _ _).1 h).isProbabilityMeasure + lemma iIndepSet_iff (s : ι → Set Ω) (μ : Measure Ω) : iIndepSet s μ ↔ ∀ (s' : Finset ι) {f : ι → Set Ω} (_H : ∀ i, i ∈ s' → MeasurableSet[generateFrom {s i}] (f i)), @@ -253,15 +262,15 @@ theorem IndepSets.symm {s₁ s₂ : Set (Set Ω)} (h : IndepSets s₁ s₂ μ) : @[symm] theorem Indep.symm (h : Indep m₁ m₂ μ) : Indep m₂ m₁ μ := IndepSets.symm h -theorem indep_bot_right [IsProbabilityMeasure μ] : Indep m' ⊥ μ := +theorem indep_bot_right [IsZeroOrProbabilityMeasure μ] : Indep m' ⊥ μ := Kernel.indep_bot_right m' -theorem indep_bot_left [IsProbabilityMeasure μ] : Indep ⊥ m' μ := (indep_bot_right m').symm +theorem indep_bot_left [IsZeroOrProbabilityMeasure μ] : Indep ⊥ m' μ := (indep_bot_right m').symm -theorem indepSet_empty_right [IsProbabilityMeasure μ] (s : Set Ω) : IndepSet s ∅ μ := +theorem indepSet_empty_right [IsZeroOrProbabilityMeasure μ] (s : Set Ω) : IndepSet s ∅ μ := Kernel.indepSet_empty_right s -theorem indepSet_empty_left [IsProbabilityMeasure μ] (s : Set Ω) : IndepSet ∅ s μ := +theorem indepSet_empty_left [IsZeroOrProbabilityMeasure μ] (s : Set Ω) : IndepSet ∅ s μ := Kernel.indepSet_empty_left s theorem indepSets_of_indepSets_of_le_left {s₁ s₂ s₃ : Set (Set Ω)} @@ -327,7 +336,7 @@ end Indep section FromIndepToIndep -variable {m : ι → MeasurableSpace Ω} {_mΩ : MeasurableSpace Ω} {μ : Measure Ω} +variable {m : ι → MeasurableSpace Ω} {_mΩ : MeasurableSpace Ω} {μ : Measure Ω} theorem iIndepSets.indepSets {s : ι → Set (Set Ω)} (h_indep : iIndepSets s μ) {i j : ι} (hij : i ≠ j) : IndepSets (s i) (s j) μ := @@ -376,61 +385,62 @@ variable {m : ι → MeasurableSpace Ω} {m1 m2 _mΩ : MeasurableSpace Ω} {μ : /-! ### Independence of generating π-systems implies independence of measurable space structures -/ -theorem IndepSets.indep [IsProbabilityMeasure μ] +theorem IndepSets.indep [IsZeroOrProbabilityMeasure μ] {p1 p2 : Set (Set Ω)} (h1 : m1 ≤ _mΩ) (h2 : m2 ≤ _mΩ) (hp1 : IsPiSystem p1) (hp2 : IsPiSystem p2) (hpm1 : m1 = generateFrom p1) (hpm2 : m2 = generateFrom p2) (hyp : IndepSets p1 p2 μ) : Indep m1 m2 μ := Kernel.IndepSets.indep h1 h2 hp1 hp2 hpm1 hpm2 hyp -theorem IndepSets.indep' [IsProbabilityMeasure μ] +theorem IndepSets.indep' [IsZeroOrProbabilityMeasure μ] {p1 p2 : Set (Set Ω)} (hp1m : ∀ s ∈ p1, MeasurableSet s) (hp2m : ∀ s ∈ p2, MeasurableSet s) (hp1 : IsPiSystem p1) (hp2 : IsPiSystem p2) (hyp : IndepSets p1 p2 μ) : Indep (generateFrom p1) (generateFrom p2) μ := Kernel.IndepSets.indep' hp1m hp2m hp1 hp2 hyp -theorem indepSets_piiUnionInter_of_disjoint [IsProbabilityMeasure μ] {s : ι → Set (Set Ω)} +theorem indepSets_piiUnionInter_of_disjoint {s : ι → Set (Set Ω)} {S T : Set ι} (h_indep : iIndepSets s μ) (hST : Disjoint S T) : IndepSets (piiUnionInter s S) (piiUnionInter s T) μ := Kernel.indepSets_piiUnionInter_of_disjoint h_indep hST -theorem iIndepSet.indep_generateFrom_of_disjoint [IsProbabilityMeasure μ] {s : ι → Set Ω} +theorem iIndepSet.indep_generateFrom_of_disjoint {s : ι → Set Ω} (hsm : ∀ n, MeasurableSet (s n)) (hs : iIndepSet s μ) (S T : Set ι) (hST : Disjoint S T) : Indep (generateFrom { t | ∃ n ∈ S, s n = t }) (generateFrom { t | ∃ k ∈ T, s k = t }) μ := Kernel.iIndepSet.indep_generateFrom_of_disjoint hsm hs S T hST -theorem indep_iSup_of_disjoint [IsProbabilityMeasure μ] +theorem indep_iSup_of_disjoint (h_le : ∀ i, m i ≤ _mΩ) (h_indep : iIndep m μ) {S T : Set ι} (hST : Disjoint S T) : Indep (⨆ i ∈ S, m i) (⨆ i ∈ T, m i) μ := Kernel.indep_iSup_of_disjoint h_le h_indep hST theorem indep_iSup_of_directed_le - [IsProbabilityMeasure μ] (h_indep : ∀ i, Indep (m i) m1 μ) + [IsZeroOrProbabilityMeasure μ] (h_indep : ∀ i, Indep (m i) m1 μ) (h_le : ∀ i, m i ≤ _mΩ) (h_le' : m1 ≤ _mΩ) (hm : Directed (· ≤ ·) m) : Indep (⨆ i, m i) m1 μ := Kernel.indep_iSup_of_directed_le h_indep h_le h_le' hm -theorem iIndepSet.indep_generateFrom_lt [Preorder ι] [IsProbabilityMeasure μ] {s : ι → Set Ω} +theorem iIndepSet.indep_generateFrom_lt [Preorder ι] {s : ι → Set Ω} (hsm : ∀ n, MeasurableSet (s n)) (hs : iIndepSet s μ) (i : ι) : Indep (generateFrom {s i}) (generateFrom { t | ∃ j < i, s j = t }) μ := Kernel.iIndepSet.indep_generateFrom_lt hsm hs i -theorem iIndepSet.indep_generateFrom_le [LinearOrder ι] [IsProbabilityMeasure μ] {s : ι → Set Ω} +theorem iIndepSet.indep_generateFrom_le [LinearOrder ι] + {s : ι → Set Ω} (hsm : ∀ n, MeasurableSet (s n)) (hs : iIndepSet s μ) (i : ι) {k : ι} (hk : i < k) : Indep (generateFrom {s k}) (generateFrom { t | ∃ j ≤ i, s j = t }) μ := Kernel.iIndepSet.indep_generateFrom_le hsm hs i hk -theorem iIndepSet.indep_generateFrom_le_nat [IsProbabilityMeasure μ] {s : ℕ → Set Ω} +theorem iIndepSet.indep_generateFrom_le_nat {s : ℕ → Set Ω} (hsm : ∀ n, MeasurableSet (s n)) (hs : iIndepSet s μ) (n : ℕ) : Indep (generateFrom {s (n + 1)}) (generateFrom { t | ∃ k ≤ n, s k = t }) μ := Kernel.iIndepSet.indep_generateFrom_le_nat hsm hs n -theorem indep_iSup_of_monotone [SemilatticeSup ι] [IsProbabilityMeasure μ] +theorem indep_iSup_of_monotone [SemilatticeSup ι] [IsZeroOrProbabilityMeasure μ] (h_indep : ∀ i, Indep (m i) m1 μ) (h_le : ∀ i, m i ≤ _mΩ) (h_le' : m1 ≤ _mΩ) (hm : Monotone m) : Indep (⨆ i, m i) m1 μ := Kernel.indep_iSup_of_monotone h_indep h_le h_le' hm -theorem indep_iSup_of_antitone [SemilatticeInf ι] [IsProbabilityMeasure μ] +theorem indep_iSup_of_antitone [SemilatticeInf ι] [IsZeroOrProbabilityMeasure μ] (h_indep : ∀ i, Indep (m i) m1 μ) (h_le : ∀ i, m i ≤ _mΩ) (h_le' : m1 ≤ _mΩ) (hm : Antitone m) : Indep (⨆ i, m i) m1 μ := Kernel.indep_iSup_of_antitone h_indep h_le h_le' hm @@ -441,7 +451,7 @@ theorem iIndepSets.piiUnionInter_of_not_mem {π : ι → Set (Set Ω)} {a : ι} Kernel.iIndepSets.piiUnionInter_of_not_mem hp_ind haS /-- The measurable space structures generated by independent pi-systems are independent. -/ -theorem iIndepSets.iIndep [IsProbabilityMeasure μ] +theorem iIndepSets.iIndep (h_le : ∀ i, m i ≤ _mΩ) (π : ι → Set (Set Ω)) (h_pi : ∀ n, IsPiSystem (π n)) (h_generate : ∀ i, m i = generateFrom (π i)) (h_ind : iIndepSets π μ) : iIndep m μ := @@ -463,17 +473,21 @@ variable {m₁ m₂ _mΩ : MeasurableSpace Ω} {μ : Measure Ω} {s t : Set Ω} theorem indepSet_iff_indepSets_singleton (hs_meas : MeasurableSet s) (ht_meas : MeasurableSet t) (μ : Measure Ω := by volume_tac) - [IsProbabilityMeasure μ] : IndepSet s t μ ↔ IndepSets {s} {t} μ := + [IsZeroOrProbabilityMeasure μ] : IndepSet s t μ ↔ IndepSets {s} {t} μ := Kernel.indepSet_iff_indepSets_singleton hs_meas ht_meas _ _ theorem indepSet_iff_measure_inter_eq_mul (hs_meas : MeasurableSet s) (ht_meas : MeasurableSet t) (μ : Measure Ω := by volume_tac) - [IsProbabilityMeasure μ] : IndepSet s t μ ↔ μ (s ∩ t) = μ s * μ t := + [IsZeroOrProbabilityMeasure μ] : IndepSet s t μ ↔ μ (s ∩ t) = μ s * μ t := (indepSet_iff_indepSets_singleton hs_meas ht_meas μ).trans indepSets_singleton_iff +lemma IndepSet.measure_inter_eq_mul {μ : Measure Ω} (h : IndepSet s t μ) : + μ (s ∩ t) = μ s * μ t := by + simpa using Kernel.IndepSet.measure_inter_eq_mul _ _ h + theorem IndepSets.indepSet_of_mem (hs : s ∈ S) (ht : t ∈ T) (hs_meas : MeasurableSet s) (ht_meas : MeasurableSet t) - (μ : Measure Ω := by volume_tac) [IsProbabilityMeasure μ] + (μ : Measure Ω := by volume_tac) [IsZeroOrProbabilityMeasure μ] (h_indep : IndepSets S T μ) : IndepSet s t μ := Kernel.IndepSets.indepSet_of_mem _ _ hs ht hs_meas ht_meas _ _ h_indep @@ -498,7 +512,9 @@ theorem iIndepSets_singleton_iff {s : ι → Set Ω} : simp_rw [iIndepSets, Kernel.iIndepSets_singleton_iff, ae_dirac_eq, Filter.eventually_pure, Kernel.const_apply] -variable [IsProbabilityMeasure μ] +theorem iIndepSet.meas_biInter {f : ι → Set Ω} (h : iIndepSet f μ) (s : Finset ι) : + μ (⋂ i ∈ s, f i) = ∏ i ∈ s, μ (f i) := by + simpa using Kernel.iIndepSet.meas_biInter h s theorem iIndepSet_iff_iIndepSets_singleton {f : ι → Set Ω} (hf : ∀ i, MeasurableSet (f i)) : iIndepSet f μ ↔ iIndepSets (fun i ↦ {f i}) μ := @@ -533,16 +549,20 @@ theorem indepFun_iff_measure_inter_preimage_eq_mul {mβ : MeasurableSpace β} simp only [IndepFun, Kernel.indepFun_iff_measure_inter_preimage_eq_mul, ae_dirac_eq, Filter.eventually_pure, Kernel.const_apply] +alias ⟨IndepFun.measure_inter_preimage_eq_mul, _⟩ := indepFun_iff_measure_inter_preimage_eq_mul + theorem iIndepFun_iff_measure_inter_preimage_eq_mul {ι : Type*} {β : ι → Type*} - (m : ∀ x, MeasurableSpace (β x)) (f : ∀ i, Ω → β i) : + {m : ∀ x, MeasurableSpace (β x)} {f : ∀ i, Ω → β i} : iIndepFun m f μ ↔ ∀ (S : Finset ι) {sets : ∀ i : ι, Set (β i)} (_H : ∀ i, i ∈ S → MeasurableSet[m i] (sets i)), μ (⋂ i ∈ S, f i ⁻¹' sets i) = ∏ i ∈ S, μ (f i ⁻¹' sets i) := by simp only [iIndepFun, Kernel.iIndepFun_iff_measure_inter_preimage_eq_mul, ae_dirac_eq, Filter.eventually_pure, Kernel.const_apply] +alias ⟨iIndepFun.measure_inter_preimage_eq_mul, _⟩ := iIndepFun_iff_measure_inter_preimage_eq_mul + theorem indepFun_iff_indepSet_preimage {mβ : MeasurableSpace β} {mβ' : MeasurableSpace β'} - [IsProbabilityMeasure μ] (hf : Measurable f) (hg : Measurable g) : + [IsZeroOrProbabilityMeasure μ] (hf : Measurable f) (hg : Measurable g) : IndepFun f g μ ↔ ∀ s t, MeasurableSet s → MeasurableSet t → IndepSet (f ⁻¹' s) (g ⁻¹' t) μ := by simp only [IndepFun, IndepSet, Kernel.indepFun_iff_indepSet_preimage hf hg, ae_dirac_eq, @@ -604,13 +624,11 @@ tuple `(f i)_i` for `i ∈ T`. -/ lemma iIndepFun.indepFun_finset (S T : Finset ι) (hST : Disjoint S T) (hf_Indep : iIndepFun m f μ) (hf_meas : ∀ i, Measurable (f i)) : IndepFun (fun a (i : S) ↦ f i a) (fun a (i : T) ↦ f i a) μ := - have := hf_Indep.isProbabilityMeasure Kernel.iIndepFun.indepFun_finset S T hST hf_Indep hf_meas lemma iIndepFun.indepFun_prod_mk (hf_Indep : iIndepFun m f μ) (hf_meas : ∀ i, Measurable (f i)) (i j k : ι) (hik : i ≠ k) (hjk : j ≠ k) : IndepFun (fun a => (f i a, f j a)) (f k) μ := - have := hf_Indep.isProbabilityMeasure Kernel.iIndepFun.indepFun_prod_mk hf_Indep hf_meas i j k hik hjk open Finset in @@ -632,14 +650,12 @@ variable {β : Type*} {m : MeasurableSpace β} [Mul β] [MeasurableMul₂ β] {f lemma iIndepFun.indepFun_mul_left (hf_indep : iIndepFun (fun _ ↦ m) f μ) (hf_meas : ∀ i, Measurable (f i)) (i j k : ι) (hik : i ≠ k) (hjk : j ≠ k) : IndepFun (f i * f j) (f k) μ := - have := hf_indep.isProbabilityMeasure Kernel.iIndepFun.indepFun_mul_left hf_indep hf_meas i j k hik hjk @[to_additive] lemma iIndepFun.indepFun_mul_right (hf_indep : iIndepFun (fun _ ↦ m) f μ) (hf_meas : ∀ i, Measurable (f i)) (i j k : ι) (hij : i ≠ j) (hik : i ≠ k) : IndepFun (f i) (f j * f k) μ := - have := hf_indep.isProbabilityMeasure Kernel.iIndepFun.indepFun_mul_right hf_indep hf_meas i j k hij hik @[to_additive] @@ -647,7 +663,6 @@ lemma iIndepFun.indepFun_mul_mul (hf_indep : iIndepFun (fun _ ↦ m) f μ) (hf_meas : ∀ i, Measurable (f i)) (i j k l : ι) (hik : i ≠ k) (hil : i ≠ l) (hjk : j ≠ k) (hjl : j ≠ l) : IndepFun (f i * f j) (f k * f l) μ := - have := hf_indep.isProbabilityMeasure Kernel.iIndepFun.indepFun_mul_mul hf_indep hf_meas i j k l hik hil hjk hjl end Mul @@ -659,14 +674,12 @@ variable {β : Type*} {m : MeasurableSpace β} [Div β] [MeasurableDiv₂ β] {f lemma iIndepFun.indepFun_div_left (hf_indep : iIndepFun (fun _ ↦ m) f μ) (hf_meas : ∀ i, Measurable (f i)) (i j k : ι) (hik : i ≠ k) (hjk : j ≠ k) : IndepFun (f i / f j) (f k) μ := - have := hf_indep.isProbabilityMeasure Kernel.iIndepFun.indepFun_div_left hf_indep hf_meas i j k hik hjk @[to_additive] lemma iIndepFun.indepFun_div_right (hf_indep : iIndepFun (fun _ ↦ m) f μ) (hf_meas : ∀ i, Measurable (f i)) (i j k : ι) (hij : i ≠ j) (hik : i ≠ k) : IndepFun (f i) (f j / f k) μ := - have := hf_indep.isProbabilityMeasure Kernel.iIndepFun.indepFun_div_right hf_indep hf_meas i j k hij hik @[to_additive] @@ -674,7 +687,6 @@ lemma iIndepFun.indepFun_div_div (hf_indep : iIndepFun (fun _ ↦ m) f μ) (hf_meas : ∀ i, Measurable (f i)) (i j k l : ι) (hik : i ≠ k) (hil : i ≠ l) (hjk : j ≠ k) (hjl : j ≠ l) : IndepFun (f i / f j) (f k / f l) μ := - have := hf_indep.isProbabilityMeasure Kernel.iIndepFun.indepFun_div_div hf_indep hf_meas i j k l hik hil hjk hjl end Div @@ -686,13 +698,11 @@ variable {β : Type*} {m : MeasurableSpace β} [CommMonoid β] [MeasurableMul₂ lemma iIndepFun.indepFun_finset_prod_of_not_mem (hf_Indep : iIndepFun (fun _ ↦ m) f μ) (hf_meas : ∀ i, Measurable (f i)) {s : Finset ι} {i : ι} (hi : i ∉ s) : IndepFun (∏ j ∈ s, f j) (f i) μ := - have := hf_Indep.isProbabilityMeasure Kernel.iIndepFun.indepFun_finset_prod_of_not_mem hf_Indep hf_meas hi @[to_additive] lemma iIndepFun.indepFun_prod_range_succ {f : ℕ → Ω → β} (hf_Indep : iIndepFun (fun _ ↦ m) f μ) (hf_meas : ∀ i, Measurable (f i)) (n : ℕ) : IndepFun (∏ j ∈ Finset.range n, f j) (f n) μ := - have := hf_Indep.isProbabilityMeasure Kernel.iIndepFun.indepFun_prod_range_succ hf_Indep hf_meas n end CommMonoid @@ -705,3 +715,44 @@ theorem iIndepSet.iIndepFun_indicator [Zero β] [One β] {m : MeasurableSpace β end IndepFun end ProbabilityTheory + +namespace MeasureTheory + +open Filter ProbabilityTheory +open scoped NNReal Topology + +/-- If a nonzero function belongs to `ℒ^p` and is independent of another function, then +the space is a probability space. -/ +lemma Memℒp.isProbabilityMeasure_of_indepFun + {Ω : Type*} [MeasurableSpace Ω] {μ : Measure Ω} + {E : Type*} [NormedAddCommGroup E] [MeasurableSpace E] [BorelSpace E] + {F : Type*} [MeasurableSpace F] + (f : Ω → E) (g : Ω → F) {p : ℝ≥0∞} (hp : p ≠ 0) (hp' : p ≠ ∞) + (hℒp : Memℒp f p μ) (h'f : ¬(∀ᵐ ω ∂μ, f ω = 0)) (hindep : IndepFun f g μ) : + IsProbabilityMeasure μ := by + obtain ⟨c, c_pos, hc⟩ : ∃ (c : ℝ≥0), 0 < c ∧ 0 < μ {ω | c ≤ ‖f ω‖₊} := by + contrapose! h'f + have A (c : ℝ≥0) (hc : 0 < c) : ∀ᵐ ω ∂μ, ‖f ω‖₊ < c := by simpa [ae_iff] using h'f c hc + obtain ⟨u, -, u_pos, u_lim⟩ : ∃ u, StrictAnti u ∧ (∀ (n : ℕ), 0 < u n) + ∧ Tendsto u atTop (𝓝 0) := exists_seq_strictAnti_tendsto (0 : ℝ≥0) + filter_upwards [ae_all_iff.2 (fun n ↦ A (u n) (u_pos n))] with ω hω + simpa using ge_of_tendsto' u_lim (fun i ↦ (hω i).le) + have h'c : μ {ω | c ≤ ‖f ω‖₊} < ∞ := hℒp.meas_ge_lt_top hp hp' c_pos.ne' + have := hindep.measure_inter_preimage_eq_mul {x | c ≤ ‖x‖₊} Set.univ + (isClosed_le continuous_const continuous_nnnorm).measurableSet MeasurableSet.univ + simp only [Set.preimage_setOf_eq, Set.preimage_univ, Set.inter_univ] at this + exact ⟨(ENNReal.mul_eq_left hc.ne' h'c.ne).1 this.symm⟩ + +/-- If a nonzero function is integrable and is independent of another function, then +the space is a probability space. -/ +lemma Integrable.isProbabilityMeasure_of_indepFun + {Ω : Type*} [MeasurableSpace Ω] {μ : Measure Ω} + {E : Type*} [NormedAddCommGroup E] [MeasurableSpace E] [BorelSpace E] + {F : Type*} [MeasurableSpace F] + (f : Ω → E) (g : Ω → F) + (hf : Integrable f μ) (h'f : ¬(∀ᵐ ω ∂μ, f ω = 0)) (hindep : IndepFun f g μ) : + IsProbabilityMeasure μ := + Memℒp.isProbabilityMeasure_of_indepFun f g one_ne_zero ENNReal.one_ne_top + (memℒp_one_iff_integrable.mpr hf) h'f hindep + +end MeasureTheory diff --git a/Mathlib/Probability/Independence/Conditional.lean b/Mathlib/Probability/Independence/Conditional.lean index e7f9c9211e252..0b5e3f0b6dcaf 100644 --- a/Mathlib/Probability/Independence/Conditional.lean +++ b/Mathlib/Probability/Independence/Conditional.lean @@ -62,9 +62,7 @@ section Definitions section -variable (m' : MeasurableSpace Ω) - {mΩ : MeasurableSpace Ω} [StandardBorelSpace Ω] [Nonempty Ω] - (hm' : m' ≤ mΩ) +variable (m' : MeasurableSpace Ω) {mΩ : MeasurableSpace Ω} [StandardBorelSpace Ω] (hm' : m' ≤ mΩ) /-- A family of sets of sets `π : ι → Set (Set Ω)` is conditionally independent given `m'` with respect to a measure `μ` if for any finite set of indices `s = {i_1, ..., i_n}`, for any sets @@ -100,13 +98,13 @@ end `t₁ ∈ m₁, t₂ ∈ m₂`, `μ⟦t₁ ∩ t₂ | m'⟧ =ᵐ[μ] μ⟦t₁ | m'⟧ * μ⟦t₂ | m'⟧`. See `ProbabilityTheory.condIndep_iff`. -/ def CondIndep (m' m₁ m₂ : MeasurableSpace Ω) - {mΩ : MeasurableSpace Ω} [StandardBorelSpace Ω] [Nonempty Ω] + {mΩ : MeasurableSpace Ω} [StandardBorelSpace Ω] (hm' : m' ≤ mΩ) (μ : Measure Ω := by volume_tac) [IsFiniteMeasure μ] : Prop := Kernel.Indep m₁ m₂ (condexpKernel μ m') (μ.trim hm') section -variable (m' : MeasurableSpace Ω) {mΩ : MeasurableSpace Ω} [StandardBorelSpace Ω] [Nonempty Ω] +variable (m' : MeasurableSpace Ω) {mΩ : MeasurableSpace Ω} [StandardBorelSpace Ω] (hm' : m' ≤ mΩ) /-- A family of sets is conditionally independent if the family of measurable space structures they @@ -148,8 +146,7 @@ end Definitions section DefinitionLemmas section -variable (m' : MeasurableSpace Ω) {mΩ : MeasurableSpace Ω} [StandardBorelSpace Ω] [Nonempty Ω] - (hm' : m' ≤ mΩ) +variable (m' : MeasurableSpace Ω) {mΩ : MeasurableSpace Ω} [StandardBorelSpace Ω] (hm' : m' ≤ mΩ) lemma iCondIndepSets_iff (π : ι → Set (Set Ω)) (hπ : ∀ i s (_hs : s ∈ π i), MeasurableSet s) (μ : Measure Ω) [IsFiniteMeasure μ] : @@ -184,7 +181,7 @@ lemma iCondIndepSets_iff (π : ι → Set (Set Ω)) (hπ : ∀ i s (_hs : s ∈ have h_ne_top : condexpKernel μ m' ω (⋂ i ∈ s, f i) ≠ ∞ := (measure_ne_top (condexpKernel μ m' ω) _) have : (∏ i ∈ s, condexpKernel μ m' ω (f i)) ≠ ∞ := - (ENNReal.prod_lt_top (fun _ _ ↦ measure_ne_top (condexpKernel μ m' ω) _)).ne + ENNReal.prod_ne_top fun _ _ ↦ measure_ne_top (condexpKernel μ m' ω) _ rw [← ENNReal.ofReal_toReal h_ne_top, h_inter_eq, h, Finset.prod_apply, ← ENNReal.ofReal_toReal this, ENNReal.toReal_prod] congr 1 @@ -267,13 +264,13 @@ end section CondIndep lemma condIndep_iff_condIndepSets (m' m₁ m₂ : MeasurableSpace Ω) {mΩ : MeasurableSpace Ω} - [StandardBorelSpace Ω] [Nonempty Ω] (hm' : m' ≤ mΩ) (μ : Measure Ω ) [IsFiniteMeasure μ] : + [StandardBorelSpace Ω] (hm' : m' ≤ mΩ) (μ : Measure Ω ) [IsFiniteMeasure μ] : CondIndep m' m₁ m₂ hm' μ ↔ CondIndepSets m' hm' {s | MeasurableSet[m₁] s} {s | MeasurableSet[m₂] s} μ := by simp only [CondIndep, CondIndepSets, Kernel.Indep] lemma condIndep_iff (m' m₁ m₂ : MeasurableSpace Ω) - {mΩ : MeasurableSpace Ω} [StandardBorelSpace Ω] [Nonempty Ω] + {mΩ : MeasurableSpace Ω} [StandardBorelSpace Ω] (hm' : m' ≤ mΩ) (hm₁ : m₁ ≤ mΩ) (hm₂ : m₂ ≤ mΩ) (μ : Measure Ω) [IsFiniteMeasure μ] : CondIndep m' m₁ m₂ hm' μ ↔ ∀ t1 t2, MeasurableSet[m₁] t1 → MeasurableSet[m₂] t2 @@ -285,7 +282,7 @@ lemma condIndep_iff (m' m₁ m₂ : MeasurableSpace Ω) end CondIndep -variable (m' : MeasurableSpace Ω) {mΩ : MeasurableSpace Ω} [StandardBorelSpace Ω] [Nonempty Ω] +variable (m' : MeasurableSpace Ω) {mΩ : MeasurableSpace Ω} [StandardBorelSpace Ω] (hm' : m' ≤ mΩ) lemma iCondIndepSet_iff_iCondIndep (s : ι → Set Ω) (μ : Measure Ω) [IsFiniteMeasure μ] : @@ -352,7 +349,7 @@ end DefinitionLemmas section CondIndepSets -variable {m' : MeasurableSpace Ω} {mΩ : MeasurableSpace Ω} [StandardBorelSpace Ω] [Nonempty Ω] +variable {m' : MeasurableSpace Ω} {mΩ : MeasurableSpace Ω} [StandardBorelSpace Ω] {hm' : m' ≤ mΩ} {μ : Measure Ω} [IsFiniteMeasure μ] @[symm] @@ -410,7 +407,7 @@ end CondIndepSets section CondIndepSet -variable {m' : MeasurableSpace Ω} {mΩ : MeasurableSpace Ω} [StandardBorelSpace Ω] [Nonempty Ω] +variable {m' : MeasurableSpace Ω} {mΩ : MeasurableSpace Ω} [StandardBorelSpace Ω] {hm' : m' ≤ mΩ} {μ : Measure Ω} [IsFiniteMeasure μ] theorem condIndepSet_empty_right (s : Set Ω) : CondIndepSet m' hm' s ∅ μ := @@ -425,32 +422,32 @@ section CondIndep @[symm] theorem CondIndep.symm {m' m₁ m₂ : MeasurableSpace Ω} {mΩ : MeasurableSpace Ω} - [StandardBorelSpace Ω] [Nonempty Ω] {hm' : m' ≤ mΩ} {μ : Measure Ω} [IsFiniteMeasure μ] + [StandardBorelSpace Ω] {hm' : m' ≤ mΩ} {μ : Measure Ω} [IsFiniteMeasure μ] (h : CondIndep m' m₁ m₂ hm' μ) : CondIndep m' m₂ m₁ hm' μ := CondIndepSets.symm h theorem condIndep_bot_right (m₁ : MeasurableSpace Ω) {m' : MeasurableSpace Ω} - {mΩ : MeasurableSpace Ω} [StandardBorelSpace Ω] [Nonempty Ω] + {mΩ : MeasurableSpace Ω} [StandardBorelSpace Ω] {hm' : m' ≤ mΩ} {μ : Measure Ω} [IsFiniteMeasure μ] : CondIndep m' m₁ ⊥ hm' μ := Kernel.indep_bot_right m₁ theorem condIndep_bot_left (m₁ : MeasurableSpace Ω) {m' : MeasurableSpace Ω} - {mΩ : MeasurableSpace Ω} [StandardBorelSpace Ω] [Nonempty Ω] + {mΩ : MeasurableSpace Ω} [StandardBorelSpace Ω] {hm' : m' ≤ mΩ} {μ : Measure Ω} [IsFiniteMeasure μ] : CondIndep m' ⊥ m₁ hm' μ := (Kernel.indep_bot_right m₁).symm theorem condIndep_of_condIndep_of_le_left {m' m₁ m₂ m₃ : MeasurableSpace Ω} - {mΩ : MeasurableSpace Ω} [StandardBorelSpace Ω] [Nonempty Ω] + {mΩ : MeasurableSpace Ω} [StandardBorelSpace Ω] {hm' : m' ≤ mΩ} {μ : Measure Ω} [IsFiniteMeasure μ] (h_indep : CondIndep m' m₁ m₂ hm' μ) (h31 : m₃ ≤ m₁) : CondIndep m' m₃ m₂ hm' μ := Kernel.indep_of_indep_of_le_left h_indep h31 theorem condIndep_of_condIndep_of_le_right {m' m₁ m₂ m₃ : MeasurableSpace Ω} - {mΩ : MeasurableSpace Ω} [StandardBorelSpace Ω] [Nonempty Ω] + {mΩ : MeasurableSpace Ω} [StandardBorelSpace Ω] {hm' : m' ≤ mΩ} {μ : Measure Ω} [IsFiniteMeasure μ] (h_indep : CondIndep m' m₁ m₂ hm' μ) (h32 : m₃ ≤ m₂) : CondIndep m' m₁ m₃ hm' μ := @@ -464,7 +461,7 @@ end CondIndep section FromiCondIndepToCondIndep variable {m' : MeasurableSpace Ω} - {mΩ : MeasurableSpace Ω} [StandardBorelSpace Ω] [Nonempty Ω] + {mΩ : MeasurableSpace Ω} [StandardBorelSpace Ω] {hm' : m' ≤ mΩ} {μ : Measure Ω} [IsFiniteMeasure μ] theorem iCondIndepSets.condIndepSets {s : ι → Set (Set Ω)} @@ -499,7 +496,7 @@ section FromMeasurableSpacesToSetsOfSets generating π-systems -/ variable {m' : MeasurableSpace Ω} - {mΩ : MeasurableSpace Ω} [StandardBorelSpace Ω] [Nonempty Ω] + {mΩ : MeasurableSpace Ω} [StandardBorelSpace Ω] {hm' : m' ≤ mΩ} {μ : Measure Ω} [IsFiniteMeasure μ] theorem iCondIndep.iCondIndepSets {m : ι → MeasurableSpace Ω} @@ -520,7 +517,7 @@ section FromPiSystemsToMeasurableSpaces /-! ### Conditional independence of generating π-systems implies conditional independence of σ-algebras -/ -variable {m' m₁ m₂ : MeasurableSpace Ω} {mΩ : MeasurableSpace Ω} [StandardBorelSpace Ω] [Nonempty Ω] +variable {m' m₁ m₂ : MeasurableSpace Ω} {mΩ : MeasurableSpace Ω} [StandardBorelSpace Ω] {hm' : m' ≤ mΩ} {μ : Measure Ω} [IsFiniteMeasure μ] theorem CondIndepSets.condIndep @@ -608,7 +605,7 @@ section CondIndepSet -/ -variable {m' m₁ m₂ : MeasurableSpace Ω} {mΩ : MeasurableSpace Ω} [StandardBorelSpace Ω] [Nonempty Ω] +variable {m' m₁ m₂ : MeasurableSpace Ω} {mΩ : MeasurableSpace Ω} [StandardBorelSpace Ω] {hm' : m' ≤ mΩ} {s t : Set Ω} (S T : Set (Set Ω)) @@ -638,7 +635,7 @@ section CondIndepFun -/ variable {β β' : Type*} {m' : MeasurableSpace Ω} - {mΩ : MeasurableSpace Ω} [StandardBorelSpace Ω] [Nonempty Ω] + {mΩ : MeasurableSpace Ω} [StandardBorelSpace Ω] {hm' : m' ≤ mΩ} {μ : Measure Ω} [IsFiniteMeasure μ] {f : Ω → β} {g : Ω → β'} diff --git a/Mathlib/Probability/Independence/Kernel.lean b/Mathlib/Probability/Independence/Kernel.lean index 65ebb710ed088..ed4fbcb838ea5 100644 --- a/Mathlib/Probability/Independence/Kernel.lean +++ b/Mathlib/Probability/Independence/Kernel.lean @@ -118,13 +118,98 @@ section ByDefinition variable {β : ι → Type*} {mβ : ∀ i, MeasurableSpace (β i)} {_mα : MeasurableSpace α} {m : ι → MeasurableSpace Ω} {_mΩ : MeasurableSpace Ω} - {κ : Kernel α Ω} {μ : Measure α} + {κ η : Kernel α Ω} {μ : Measure α} {π : ι → Set (Set Ω)} {s : ι → Set Ω} {S : Finset ι} {f : ∀ x : ι, Ω → β x} + {s1 s2 : Set (Set Ω)} + +@[simp] lemma iIndepSets_zero_right : iIndepSets π κ 0 := by simp [iIndepSets] + +@[simp] lemma indepSets_zero_right : IndepSets s1 s2 κ 0 := by simp [IndepSets] + +@[simp] lemma indepSets_zero_left : IndepSets s1 s2 (0 : Kernel α Ω) μ := by simp [IndepSets] + +@[simp] lemma iIndep_zero_right : iIndep m κ 0 := by simp [iIndep] + +@[simp] lemma indep_zero_right {m₁ m₂ : MeasurableSpace Ω} {_mΩ : MeasurableSpace Ω} + {κ : Kernel α Ω} : Indep m₁ m₂ κ 0 := by simp [Indep] + +@[simp] lemma indep_zero_left {m₁ m₂ : MeasurableSpace Ω} {_mΩ : MeasurableSpace Ω} : + Indep m₁ m₂ (0 : Kernel α Ω) μ := by simp [Indep] + +@[simp] lemma iIndepSet_zero_right : iIndepSet s κ 0 := by simp [iIndepSet] + +@[simp] lemma indepSet_zero_right {s t : Set Ω} : IndepSet s t κ 0 := by simp [IndepSet] + +@[simp] lemma indepSet_zero_left {s t : Set Ω} : IndepSet s t (0 : Kernel α Ω) μ := by + simp [IndepSet] + +@[simp] lemma iIndepFun_zero_right {β : ι → Type*} {m : ∀ x : ι, MeasurableSpace (β x)} + {f : ∀ x : ι, Ω → β x} : iIndepFun m f κ 0 := by simp [iIndepFun] + +@[simp] lemma indepFun_zero_right {β γ} [MeasurableSpace β] [MeasurableSpace γ] + {f : Ω → β} {g : Ω → γ} : IndepFun f g κ 0 := by simp [IndepFun] + +@[simp] lemma indepFun_zero_left {β γ} [MeasurableSpace β] [MeasurableSpace γ] + {f : Ω → β} {g : Ω → γ} : IndepFun f g (0 : Kernel α Ω) μ := by simp [IndepFun] + +lemma iIndepSets_congr (h : κ =ᵐ[μ] η) : iIndepSets π κ μ ↔ iIndepSets π η μ := by + peel 3 + refine ⟨fun h' ↦ ?_, fun h' ↦ ?_⟩ <;> + · filter_upwards [h, h'] with a ha h'a + simpa [ha] using h'a + +alias ⟨iIndepSets.congr, _⟩ := iIndepSets_congr + +lemma indepSets_congr (h : κ =ᵐ[μ] η) : IndepSets s1 s2 κ μ ↔ IndepSets s1 s2 η μ := by + peel 4 + refine ⟨fun h' ↦ ?_, fun h' ↦ ?_⟩ <;> + · filter_upwards [h, h'] with a ha h'a + simpa [ha] using h'a + +alias ⟨IndepSets.congr, _⟩ := indepSets_congr + +lemma iIndep_congr (h : κ =ᵐ[μ] η) : iIndep m κ μ ↔ iIndep m η μ := + iIndepSets_congr h + +alias ⟨iIndep.congr, _⟩ := iIndep_congr + +lemma indep_congr {m₁ m₂ : MeasurableSpace Ω} {_mΩ : MeasurableSpace Ω} + {κ η : Kernel α Ω} (h : κ =ᵐ[μ] η) : Indep m₁ m₂ κ μ ↔ Indep m₁ m₂ η μ := + indepSets_congr h + +alias ⟨Indep.congr, _⟩ := indep_congr + +lemma iIndepSet_congr (h : κ =ᵐ[μ] η) : iIndepSet s κ μ ↔ iIndepSet s η μ := + iIndep_congr h + +alias ⟨iIndepSet.congr, _⟩ := iIndepSet_congr + +lemma indepSet_congr {s t : Set Ω} (h : κ =ᵐ[μ] η) : IndepSet s t κ μ ↔ IndepSet s t η μ := + indep_congr h + +alias ⟨indepSet.congr, _⟩ := indepSet_congr + +lemma iIndepFun_congr {β : ι → Type*} {m : ∀ x : ι, MeasurableSpace (β x)} + {f : ∀ x : ι, Ω → β x} (h : κ =ᵐ[μ] η) : iIndepFun m f κ μ ↔ iIndepFun m f η μ := + iIndep_congr h + +alias ⟨iIndepFun.congr, _⟩ := iIndepFun_congr + +lemma indepFun_congr {β γ} [MeasurableSpace β] [MeasurableSpace γ] + {f : Ω → β} {g : Ω → γ} (h : κ =ᵐ[μ] η) : IndepFun f g κ μ ↔ IndepFun f g η μ := + indep_congr h + +alias ⟨IndepFun.congr, _⟩ := indepFun_congr lemma iIndepSets.meas_biInter (h : iIndepSets π κ μ) (s : Finset ι) {f : ι → Set Ω} (hf : ∀ i, i ∈ s → f i ∈ π i) : ∀ᵐ a ∂μ, κ a (⋂ i ∈ s, f i) = ∏ i ∈ s, κ a (f i) := h s hf +lemma iIndepSets.ae_isProbabilityMeasure (h : iIndepSets π κ μ) : + ∀ᵐ a ∂μ, IsProbabilityMeasure (κ a) := by + filter_upwards [h.meas_biInter ∅ (f := fun _ ↦ Set.univ) (by simp)] with a ha + exact ⟨by simpa using ha⟩ + lemma iIndepSets.meas_iInter [Fintype ι] (h : iIndepSets π κ μ) (hs : ∀ i, s i ∈ π i) : ∀ᵐ a ∂μ, κ a (⋂ i, s i) = ∏ i, κ a (s i) := by filter_upwards [h.meas_biInter Finset.univ (fun _i _ ↦ hs _)] with a ha using by simp [← ha] @@ -132,6 +217,10 @@ lemma iIndepSets.meas_iInter [Fintype ι] (h : iIndepSets π κ μ) (hs : ∀ i, lemma iIndep.iIndepSets' (hμ : iIndep m κ μ) : iIndepSets (fun x ↦ {s | MeasurableSet[m x] s}) κ μ := hμ +lemma iIndep.ae_isProbabilityMeasure (h : iIndep m κ μ) : + ∀ᵐ a ∂μ, IsProbabilityMeasure (κ a) := + h.iIndepSets'.ae_isProbabilityMeasure + lemma iIndep.meas_biInter (hμ : iIndep m κ μ) (hs : ∀ i, i ∈ S → MeasurableSet[m i] (s i)) : ∀ᵐ a ∂μ, κ a (⋂ i ∈ S, s i) = ∏ i ∈ S, κ a (s i) := hμ _ hs @@ -143,6 +232,10 @@ lemma iIndep.meas_iInter [Fintype ι] (h : iIndep m κ μ) (hs : ∀ i, Measurab protected lemma iIndepFun.iIndep (hf : iIndepFun mβ f κ μ) : iIndep (fun x ↦ (mβ x).comap (f x)) κ μ := hf +lemma iIndepFun.ae_isProbabilityMeasure (h : iIndepFun mβ f κ μ) : + ∀ᵐ a ∂μ, IsProbabilityMeasure (κ a) := + h.iIndep.ae_isProbabilityMeasure + lemma iIndepFun.meas_biInter (hf : iIndepFun mβ f κ μ) (hs : ∀ i, i ∈ S → MeasurableSet[(mβ i).comap (f i)] (s i)) : ∀ᵐ a ∂μ, κ a (⋂ i ∈ S, s i) = ∏ i ∈ S, κ a (s i) := hf.iIndep.meas_biInter hs @@ -177,27 +270,29 @@ theorem Indep.symm {m₁ m₂ : MeasurableSpace Ω} {_mΩ : MeasurableSpace Ω} IndepSets.symm h theorem indep_bot_right (m' : MeasurableSpace Ω) {_mΩ : MeasurableSpace Ω} - {κ : Kernel α Ω} {μ : Measure α} [IsMarkovKernel κ] : + {κ : Kernel α Ω} {μ : Measure α} [IsZeroOrMarkovKernel κ] : Indep m' ⊥ κ μ := by intros s t _ ht rw [Set.mem_setOf_eq, MeasurableSpace.measurableSet_bot_iff] at ht + rcases eq_zero_or_isMarkovKernel κ with rfl| h + · simp refine Filter.Eventually.of_forall (fun a ↦ ?_) cases' ht with ht ht · rw [ht, Set.inter_empty, measure_empty, mul_zero] · rw [ht, Set.inter_univ, measure_univ, mul_one] theorem indep_bot_left (m' : MeasurableSpace Ω) {_mΩ : MeasurableSpace Ω} - {κ : Kernel α Ω} {μ : Measure α} [IsMarkovKernel κ] : + {κ : Kernel α Ω} {μ : Measure α} [IsZeroOrMarkovKernel κ] : Indep ⊥ m' κ μ := (indep_bot_right m').symm theorem indepSet_empty_right {_mΩ : MeasurableSpace Ω} - {κ : Kernel α Ω} {μ : Measure α} [IsMarkovKernel κ] (s : Set Ω) : + {κ : Kernel α Ω} {μ : Measure α} [IsZeroOrMarkovKernel κ] (s : Set Ω) : IndepSet s ∅ κ μ := by simp only [IndepSet, generateFrom_singleton_empty] exact indep_bot_right _ theorem indepSet_empty_left {_mΩ : MeasurableSpace Ω} {κ : Kernel α Ω} - {μ : Measure α} [IsMarkovKernel κ] (s : Set Ω) : + {μ : Measure α} [IsZeroOrMarkovKernel κ] (s : Set Ω) : IndepSet ∅ s κ μ := (indepSet_empty_right s).symm @@ -376,10 +471,12 @@ section FromPiSystemsToMeasurableSpaces variable {_mα : MeasurableSpace α} theorem IndepSets.indep_aux {m₂ m : MeasurableSpace Ω} - {κ : Kernel α Ω} {μ : Measure α} [IsMarkovKernel κ] {p1 p2 : Set (Set Ω)} (h2 : m₂ ≤ m) + {κ : Kernel α Ω} {μ : Measure α} [IsZeroOrMarkovKernel κ] {p1 p2 : Set (Set Ω)} (h2 : m₂ ≤ m) (hp2 : IsPiSystem p2) (hpm2 : m₂ = generateFrom p2) (hyp : IndepSets p1 p2 κ μ) {t1 t2 : Set Ω} (ht1 : t1 ∈ p1) (ht1m : MeasurableSet[m] t1) (ht2m : MeasurableSet[m₂] t2) : ∀ᵐ a ∂μ, κ a (t1 ∩ t2) = κ a t1 * κ a t2 := by + rcases eq_zero_or_isMarkovKernel κ with rfl | h + · simp refine @induction_on_inter _ (fun t ↦ ∀ᵐ a ∂μ, κ a (t1 ∩ t) = κ a t1 * κ a t) _ m₂ hpm2 hp2 ?_ ?_ ?_ ?_ t2 ht2m · simp only [Set.inter_empty, measure_empty, mul_zero, eq_self_iff_true, @@ -390,7 +487,8 @@ theorem IndepSets.indep_aux {m₂ m : MeasurableSpace Ω} have : t1 ∩ tᶜ = t1 \ (t1 ∩ t) := by rw [Set.diff_self_inter, Set.diff_eq_compl_inter, Set.inter_comm] rw [this, - measure_diff Set.inter_subset_left (ht1m.inter (h2 _ ht)) (measure_ne_top (κ a) _), + measure_diff Set.inter_subset_left (ht1m.inter (h2 _ ht)).nullMeasurableSet + (measure_ne_top (κ a) _), measure_compl (h2 _ ht) (measure_ne_top (κ a) t), measure_univ, ENNReal.mul_sub (fun _ _ ↦ measure_ne_top (κ a) _), mul_one, ha] · intros f hf_disj hf_meas h @@ -408,10 +506,12 @@ theorem IndepSets.indep_aux {m₂ m : MeasurableSpace Ω} /-- The measurable space structures generated by independent pi-systems are independent. -/ theorem IndepSets.indep {m1 m2 m : MeasurableSpace Ω} {κ : Kernel α Ω} {μ : Measure α} - [IsMarkovKernel κ] {p1 p2 : Set (Set Ω)} (h1 : m1 ≤ m) (h2 : m2 ≤ m) (hp1 : IsPiSystem p1) + [IsZeroOrMarkovKernel κ] {p1 p2 : Set (Set Ω)} (h1 : m1 ≤ m) (h2 : m2 ≤ m) (hp1 : IsPiSystem p1) (hp2 : IsPiSystem p2) (hpm1 : m1 = generateFrom p1) (hpm2 : m2 = generateFrom p2) (hyp : IndepSets p1 p2 κ μ) : Indep m1 m2 κ μ := by + rcases eq_zero_or_isMarkovKernel κ with rfl | h + · simp intros t1 t2 ht1 ht2 refine @induction_on_inter _ (fun t ↦ ∀ᵐ (a : α) ∂μ, κ a (t ∩ t2) = κ a t * κ a t2) _ m1 hpm1 hp1 ?_ ?_ ?_ ?_ _ ht1 @@ -428,7 +528,7 @@ theorem IndepSets.indep {m1 m2 m : MeasurableSpace Ω} {κ : Kernel α Ω} {μ : have : tᶜ ∩ t2 = t2 \ (t ∩ t2) := by rw [Set.inter_comm t, Set.diff_self_inter, Set.diff_eq_compl_inter] rw [this, Set.inter_comm t t2, - measure_diff Set.inter_subset_left ((h2 _ ht2).inter (h1 _ ht)) + measure_diff Set.inter_subset_left ((h2 _ ht2).inter (h1 _ ht)).nullMeasurableSet (measure_ne_top (κ a) _), Set.inter_comm, ha, measure_compl (h1 _ ht) (measure_ne_top (κ a) t), measure_univ, mul_comm (1 - κ a t), ENNReal.mul_sub (fun _ _ ↦ measure_ne_top (κ a) _), mul_one, mul_comm] @@ -446,7 +546,7 @@ theorem IndepSets.indep {m1 m2 m : MeasurableSpace Ω} {κ : Kernel α Ω} {μ : · exact fun i ↦ (h2 _ ht2).inter (h1 _ (hf_meas i)) theorem IndepSets.indep' {_mΩ : MeasurableSpace Ω} - {κ : Kernel α Ω} {μ : Measure α} [IsMarkovKernel κ] + {κ : Kernel α Ω} {μ : Measure α} [IsZeroOrMarkovKernel κ] {p1 p2 : Set (Set Ω)} (hp1m : ∀ s ∈ p1, MeasurableSet s) (hp2m : ∀ s ∈ p2, MeasurableSet s) (hp1 : IsPiSystem p1) (hp2 : IsPiSystem p2) (hyp : IndepSets p1 p2 κ μ) : Indep (generateFrom p1) (generateFrom p2) κ μ := @@ -454,7 +554,7 @@ theorem IndepSets.indep' {_mΩ : MeasurableSpace Ω} variable {_mΩ : MeasurableSpace Ω} {κ : Kernel α Ω} {μ : Measure α} -theorem indepSets_piiUnionInter_of_disjoint [IsMarkovKernel κ] {s : ι → Set (Set Ω)} +theorem indepSets_piiUnionInter_of_disjoint {s : ι → Set (Set Ω)} {S T : Set ι} (h_indep : iIndepSets s κ μ) (hST : Disjoint S T) : IndepSets (piiUnionInter s S) (piiUnionInter s T) κ μ := by rintro t1 t2 ⟨p1, hp1, f1, ht1_m, ht1_eq⟩ ⟨p2, hp2, f2, ht2_m, ht2_eq⟩ @@ -481,7 +581,8 @@ theorem indepSets_piiUnionInter_of_disjoint [IsMarkovKernel κ] {s : ι → Set ⟨fun i hi => (h i (Or.inl hi)).1 hi, fun i hi => (h i (Or.inr hi)).2 hi⟩⟩ filter_upwards [h_indep _ hgm] with a ha rw [ht1_eq, ht2_eq, h_p1_inter_p2, ← ha] - filter_upwards [h_P_inter, h_indep p1 ht1_m, h_indep p2 ht2_m] with a h_P_inter ha1 ha2 + filter_upwards [h_P_inter, h_indep p1 ht1_m, h_indep p2 ht2_m, h_indep.ae_isProbabilityMeasure] + with a h_P_inter ha1 ha2 h' have h_μg : ∀ n, κ a (g n) = (ite (n ∈ p1) (κ a (f1 n)) 1) * (ite (n ∈ p2) (κ a (f2 n)) 1) := by intro n dsimp only [g] @@ -493,9 +594,15 @@ theorem indepSets_piiUnionInter_of_disjoint [IsMarkovKernel κ] {s : ι → Set Finset.prod_ite_mem (p1 ∪ p2) p2 (fun x => κ a (f2 x)), Finset.union_inter_cancel_right, ht1_eq, ← ha1, ht2_eq, ← ha2] -theorem iIndepSet.indep_generateFrom_of_disjoint [IsMarkovKernel κ] {s : ι → Set Ω} +theorem iIndepSet.indep_generateFrom_of_disjoint {s : ι → Set Ω} (hsm : ∀ n, MeasurableSet (s n)) (hs : iIndepSet s κ μ) (S T : Set ι) (hST : Disjoint S T) : Indep (generateFrom { t | ∃ n ∈ S, s n = t }) (generateFrom { t | ∃ k ∈ T, s k = t }) κ μ := by + classical + rcases eq_or_ne μ 0 with rfl | hμ + · simp + obtain ⟨η, η_eq, hη⟩ : ∃ (η : Kernel α Ω), κ =ᵐ[μ] η ∧ IsMarkovKernel η := + exists_ae_eq_isMarkovKernel hs.ae_isProbabilityMeasure hμ + apply Indep.congr (Filter.EventuallyEq.symm η_eq) rw [← generateFrom_piiUnionInter_singleton_left, ← generateFrom_piiUnionInter_singleton_left] refine IndepSets.indep' @@ -505,21 +612,27 @@ theorem iIndepSet.indep_generateFrom_of_disjoint [IsMarkovKernel κ] {s : ι → · exact fun k => generateFrom_le fun t ht => (Set.mem_singleton_iff.1 ht).symm ▸ hsm k · exact isPiSystem_piiUnionInter _ (fun k => IsPiSystem.singleton _) _ · exact isPiSystem_piiUnionInter _ (fun k => IsPiSystem.singleton _) _ - · classical exact indepSets_piiUnionInter_of_disjoint (iIndep.iIndepSets (fun n => rfl) hs) hST + · exact indepSets_piiUnionInter_of_disjoint (iIndep.iIndepSets (fun n => rfl) (hs.congr η_eq)) hST -theorem indep_iSup_of_disjoint [IsMarkovKernel κ] {m : ι → MeasurableSpace Ω} +theorem indep_iSup_of_disjoint {m : ι → MeasurableSpace Ω} (h_le : ∀ i, m i ≤ _mΩ) (h_indep : iIndep m κ μ) {S T : Set ι} (hST : Disjoint S T) : Indep (⨆ i ∈ S, m i) (⨆ i ∈ T, m i) κ μ := by + classical + rcases eq_or_ne μ 0 with rfl | hμ + · simp + obtain ⟨η, η_eq, hη⟩ : ∃ (η : Kernel α Ω), κ =ᵐ[μ] η ∧ IsMarkovKernel η := + exists_ae_eq_isMarkovKernel h_indep.ae_isProbabilityMeasure hμ + apply Indep.congr (Filter.EventuallyEq.symm η_eq) refine IndepSets.indep (iSup₂_le fun i _ => h_le i) (iSup₂_le fun i _ => h_le i) ?_ ?_ (generateFrom_piiUnionInter_measurableSet m S).symm (generateFrom_piiUnionInter_measurableSet m T).symm ?_ · exact isPiSystem_piiUnionInter _ (fun n => @isPiSystem_measurableSet Ω (m n)) _ · exact isPiSystem_piiUnionInter _ (fun n => @isPiSystem_measurableSet Ω (m n)) _ - · classical exact indepSets_piiUnionInter_of_disjoint h_indep hST + · exact indepSets_piiUnionInter_of_disjoint (h_indep.congr η_eq) hST theorem indep_iSup_of_directed_le {Ω} {m : ι → MeasurableSpace Ω} {m' m0 : MeasurableSpace Ω} - {κ : Kernel α Ω} {μ : Measure α} [IsMarkovKernel κ] (h_indep : ∀ i, Indep (m i) m' κ μ) + {κ : Kernel α Ω} {μ : Measure α} [IsZeroOrMarkovKernel κ] (h_indep : ∀ i, Indep (m i) m' κ μ) (h_le : ∀ i, m i ≤ m0) (h_le' : m' ≤ m0) (hm : Directed (· ≤ ·) m) : Indep (⨆ i, m i) m' κ μ := by let p : ι → Set (Set Ω) := fun n => { t | MeasurableSet[m n] t } @@ -541,34 +654,34 @@ theorem indep_iSup_of_directed_le {Ω} {m : ι → MeasurableSpace Ω} {m' m0 : refine IndepSets.indep (iSup_le h_le) h_le' hp_supr_pi hp'_pi ?_ h_gen' h_pi_system_indep exact (generateFrom_iUnion_measurableSet _).symm -theorem iIndepSet.indep_generateFrom_lt [Preorder ι] [IsMarkovKernel κ] {s : ι → Set Ω} +theorem iIndepSet.indep_generateFrom_lt [Preorder ι] {s : ι → Set Ω} (hsm : ∀ n, MeasurableSet (s n)) (hs : iIndepSet s κ μ) (i : ι) : Indep (generateFrom {s i}) (generateFrom { t | ∃ j < i, s j = t }) κ μ := by convert iIndepSet.indep_generateFrom_of_disjoint hsm hs {i} { j | j < i } - (Set.disjoint_singleton_left.mpr (lt_irrefl _)) + (Set.disjoint_singleton_left.mpr (lt_irrefl _)) using 1 simp only [Set.mem_singleton_iff, exists_prop, exists_eq_left, Set.setOf_eq_eq_singleton'] -theorem iIndepSet.indep_generateFrom_le [LinearOrder ι] [IsMarkovKernel κ] {s : ι → Set Ω} +theorem iIndepSet.indep_generateFrom_le [LinearOrder ι] {s : ι → Set Ω} (hsm : ∀ n, MeasurableSet (s n)) (hs : iIndepSet s κ μ) (i : ι) {k : ι} (hk : i < k) : Indep (generateFrom {s k}) (generateFrom { t | ∃ j ≤ i, s j = t }) κ μ := by convert iIndepSet.indep_generateFrom_of_disjoint hsm hs {k} { j | j ≤ i } - (Set.disjoint_singleton_left.mpr hk.not_le) + (Set.disjoint_singleton_left.mpr hk.not_le) using 1 simp only [Set.mem_singleton_iff, exists_prop, exists_eq_left, Set.setOf_eq_eq_singleton'] -theorem iIndepSet.indep_generateFrom_le_nat [IsMarkovKernel κ] {s : ℕ → Set Ω} +theorem iIndepSet.indep_generateFrom_le_nat {s : ℕ → Set Ω} (hsm : ∀ n, MeasurableSet (s n)) (hs : iIndepSet s κ μ) (n : ℕ) : Indep (generateFrom {s (n + 1)}) (generateFrom { t | ∃ k ≤ n, s k = t }) κ μ := iIndepSet.indep_generateFrom_le hsm hs _ n.lt_succ_self theorem indep_iSup_of_monotone [SemilatticeSup ι] {Ω} {m : ι → MeasurableSpace Ω} - {m' m0 : MeasurableSpace Ω} {κ : Kernel α Ω} {μ : Measure α} [IsMarkovKernel κ] + {m' m0 : MeasurableSpace Ω} {κ : Kernel α Ω} {μ : Measure α} [IsZeroOrMarkovKernel κ] (h_indep : ∀ i, Indep (m i) m' κ μ) (h_le : ∀ i, m i ≤ m0) (h_le' : m' ≤ m0) (hm : Monotone m) : Indep (⨆ i, m i) m' κ μ := indep_iSup_of_directed_le h_indep h_le h_le' (Monotone.directed_le hm) theorem indep_iSup_of_antitone [SemilatticeInf ι] {Ω} {m : ι → MeasurableSpace Ω} - {m' m0 : MeasurableSpace Ω} {κ : Kernel α Ω} {μ : Measure α} [IsMarkovKernel κ] + {m' m0 : MeasurableSpace Ω} {κ : Kernel α Ω} {μ : Measure α} [IsZeroOrMarkovKernel κ] (h_indep : ∀ i, Indep (m i) m' κ μ) (h_le : ∀ i, m i ≤ m0) (h_le' : m' ≤ m0) (hm : Antitone m) : Indep (⨆ i, m i) m' κ μ := @@ -612,11 +725,16 @@ theorem iIndepSets.piiUnionInter_of_not_mem {π : ι → Set (Set Ω)} {a : ι} rw [ha2, Finset.prod_insert has, h_t2, mul_comm, ha1] /-- The measurable space structures generated by independent pi-systems are independent. -/ -theorem iIndepSets.iIndep [IsMarkovKernel κ] (m : ι → MeasurableSpace Ω) +theorem iIndepSets.iIndep (m : ι → MeasurableSpace Ω) (h_le : ∀ i, m i ≤ _mΩ) (π : ι → Set (Set Ω)) (h_pi : ∀ n, IsPiSystem (π n)) (h_generate : ∀ i, m i = generateFrom (π i)) (h_ind : iIndepSets π κ μ) : iIndep m κ μ := by classical + rcases eq_or_ne μ 0 with rfl | hμ + · simp + obtain ⟨η, η_eq, hη⟩ : ∃ (η : Kernel α Ω), κ =ᵐ[μ] η ∧ IsMarkovKernel η := + exists_ae_eq_isMarkovKernel h_ind.ae_isProbabilityMeasure hμ + apply iIndep.congr (Filter.EventuallyEq.symm η_eq) intro s f refine Finset.induction ?_ ?_ s · simp only [Finset.not_mem_empty, Set.mem_setOf_eq, IsEmpty.forall_iff, implies_true, @@ -626,12 +744,12 @@ theorem iIndepSets.iIndep [IsMarkovKernel κ] (m : ι → MeasurableSpace Ω) have hf_m_S : ∀ x ∈ S, MeasurableSet[m x] (f x) := fun x hx => hf_m x (by simp [hx]) let p := piiUnionInter π S set m_p := generateFrom p with hS_eq_generate - have h_indep : Indep m_p (m a) κ μ := by + have h_indep : Indep m_p (m a) η μ := by have hp : IsPiSystem p := isPiSystem_piiUnionInter π h_pi S have h_le' : ∀ i, generateFrom (π i) ≤ _mΩ := fun i ↦ (h_generate i).symm.trans_le (h_le i) have hm_p : m_p ≤ _mΩ := generateFrom_piiUnionInter_le π h_le' S exact IndepSets.indep hm_p (h_le a) hp (h_pi a) hS_eq_generate (h_generate a) - (iIndepSets.piiUnionInter_of_not_mem h_ind ha_notin_S) + (iIndepSets.piiUnionInter_of_not_mem (h_ind.congr η_eq) ha_notin_S) have h := h_indep.symm (f a) (⋂ n ∈ S, f n) (hf_m a (Finset.mem_insert_self a S)) ?_ · filter_upwards [h_rec hf_m_S, h] with a' ha' h' rwa [Finset.set_biInter_insert, Finset.prod_insert ha_notin_S, ← ha'] @@ -657,22 +775,25 @@ We prove the following equivalences on `IndepSet`, for measurable sets `s, t`. variable {_mα : MeasurableSpace α} theorem iIndepSet_iff_iIndepSets_singleton {_mΩ : MeasurableSpace Ω} {κ : Kernel α Ω} - [IsMarkovKernel κ] {μ : Measure α} {f : ι → Set Ω} - (hf : ∀ i, MeasurableSet (f i)) : + {μ : Measure α} {f : ι → Set Ω} (hf : ∀ i, MeasurableSet (f i)) : iIndepSet f κ μ ↔ iIndepSets (fun i ↦ {f i}) κ μ := ⟨iIndep.iIndepSets fun _ ↦ rfl, iIndepSets.iIndep _ (fun i ↦ generateFrom_le <| by rintro t (rfl : t = _); exact hf _) _ (fun _ ↦ IsPiSystem.singleton _) fun _ ↦ rfl⟩ +theorem iIndepSet.meas_biInter {_mΩ : MeasurableSpace Ω} {κ : Kernel α Ω} + {μ : Measure α} {f : ι → Set Ω} (h : iIndepSet f κ μ) (s : Finset ι) : + ∀ᵐ a ∂μ, κ a (⋂ i ∈ s, f i) = ∏ i ∈ s, κ a (f i) := + iIndep.iIndepSets (fun _ ↦ rfl) h _ (by simp) + theorem iIndepSet_iff_meas_biInter {_mΩ : MeasurableSpace Ω} {κ : Kernel α Ω} - [IsMarkovKernel κ] {μ : Measure α} {f : ι → Set Ω} (hf : ∀ i, MeasurableSet (f i)) : + {μ : Measure α} {f : ι → Set Ω} (hf : ∀ i, MeasurableSet (f i)) : iIndepSet f κ μ ↔ ∀ s, ∀ᵐ a ∂μ, κ a (⋂ i ∈ s, f i) = ∏ i ∈ s, κ a (f i) := (iIndepSet_iff_iIndepSets_singleton hf).trans iIndepSets_singleton_iff theorem iIndepSets.iIndepSet_of_mem {_mΩ : MeasurableSpace Ω} {κ : Kernel α Ω} - [IsMarkovKernel κ] {μ : Measure α} {π : ι → Set (Set Ω)} {f : ι → Set Ω} - (hfπ : ∀ i, f i ∈ π i) (hf : ∀ i, MeasurableSet (f i)) - (hπ : iIndepSets π κ μ) : + {μ : Measure α} {π : ι → Set (Set Ω)} {f : ι → Set Ω} + (hfπ : ∀ i, f i ∈ π i) (hf : ∀ i, MeasurableSet (f i)) (hπ : iIndepSets π κ μ) : iIndepSet f κ μ := (iIndepSet_iff_meas_biInter hf).2 fun _t ↦ hπ.meas_biInter _ fun _i _ ↦ hfπ _ @@ -680,7 +801,7 @@ variable {s t : Set Ω} (S T : Set (Set Ω)) theorem indepSet_iff_indepSets_singleton {m0 : MeasurableSpace Ω} (hs_meas : MeasurableSet s) (ht_meas : MeasurableSet t) (κ : Kernel α Ω) (μ : Measure α) - [IsMarkovKernel κ] : + [IsZeroOrMarkovKernel κ] : IndepSet s t κ μ ↔ IndepSets {s} {t} κ μ := ⟨Indep.indepSets, fun h => IndepSets.indep @@ -690,13 +811,17 @@ theorem indepSet_iff_indepSets_singleton {m0 : MeasurableSpace Ω} (hs_meas : Me theorem indepSet_iff_measure_inter_eq_mul {_m0 : MeasurableSpace Ω} (hs_meas : MeasurableSet s) (ht_meas : MeasurableSet t) (κ : Kernel α Ω) (μ : Measure α) - [IsMarkovKernel κ] : + [IsZeroOrMarkovKernel κ] : IndepSet s t κ μ ↔ ∀ᵐ a ∂μ, κ a (s ∩ t) = κ a s * κ a t := (indepSet_iff_indepSets_singleton hs_meas ht_meas κ μ).trans indepSets_singleton_iff +theorem IndepSet.measure_inter_eq_mul {_m0 : MeasurableSpace Ω} (κ : Kernel α Ω) (μ : Measure α) + (h : IndepSet s t κ μ) : ∀ᵐ a ∂μ, κ a (s ∩ t) = κ a s * κ a t := + Indep.indepSets h _ _ (by simp) (by simp) + theorem IndepSets.indepSet_of_mem {_m0 : MeasurableSpace Ω} (hs : s ∈ S) (ht : t ∈ T) (hs_meas : MeasurableSet s) (ht_meas : MeasurableSet t) - (κ : Kernel α Ω) (μ : Measure α) [IsMarkovKernel κ] + (κ : Kernel α Ω) (μ : Measure α) [IsZeroOrMarkovKernel κ] (h_indep : IndepSets S T κ μ) : IndepSet s t κ μ := (indepSet_iff_measure_inter_eq_mul hs_meas ht_meas κ μ).mpr (h_indep s t hs ht) @@ -746,6 +871,8 @@ theorem indepFun_iff_measure_inter_preimage_eq_mul {mβ : MeasurableSpace β} · refine fun s t hs ht => h (f ⁻¹' s) (g ⁻¹' t) ⟨s, hs, rfl⟩ ⟨t, ht, rfl⟩ · rintro _ _ ⟨s, hs, rfl⟩ ⟨t, ht, rfl⟩; exact h s t hs ht +alias ⟨IndepFun.measure_inter_preimage_eq_mul, _⟩ := indepFun_iff_measure_inter_preimage_eq_mul + theorem iIndepFun_iff_measure_inter_preimage_eq_mul {ι : Type*} {β : ι → Type*} (m : ∀ x, MeasurableSpace (β x)) (f : ∀ i, Ω → β i) : iIndepFun m f κ μ ↔ @@ -777,8 +904,10 @@ theorem iIndepFun_iff_measure_inter_preimage_eq_mul {ι : Type*} {β : ι → Ty filter_upwards [h S h_measβ] with a ha rw [h_left_eq a, h_right_eq a, ha] +alias ⟨iIndepFun.measure_inter_preimage_eq_mul, _⟩ := iIndepFun_iff_measure_inter_preimage_eq_mul + theorem indepFun_iff_indepSet_preimage {mβ : MeasurableSpace β} {mβ' : MeasurableSpace β'} - [IsMarkovKernel κ] (hf : Measurable f) (hg : Measurable g) : + [IsZeroOrMarkovKernel κ] (hf : Measurable f) (hg : Measurable g) : IndepFun f g κ μ ↔ ∀ s t, MeasurableSet s → MeasurableSet t → IndepSet (f ⁻¹' s) (g ⁻¹' t) κ μ := by refine indepFun_iff_measure_inter_preimage_eq_mul.trans ?_ @@ -828,16 +957,17 @@ lemma iIndepFun.of_subsingleton [IsMarkovKernel κ] [Subsingleton ι] : iIndepFu · have : s = {x} := by ext y; simp [Subsingleton.elim y x, hx] simp [this] -lemma iIndepFun.ae_isProbabilityMeasure (h : iIndepFun m f κ μ) : - ∀ᵐ a ∂μ, IsProbabilityMeasure (κ a) := by - simpa [isProbabilityMeasure_iff] using h.meas_biInter (S := ∅) (s := fun _ ↦ Set.univ) - /-- If `f` is a family of mutually independent random variables (`iIndepFun m f μ`) and `S, T` are two disjoint finite index sets, then the tuple formed by `f i` for `i ∈ S` is independent of the tuple `(f i)_i` for `i ∈ T`. -/ -theorem iIndepFun.indepFun_finset [IsMarkovKernel κ] (S T : Finset ι) (hST : Disjoint S T) +theorem iIndepFun.indepFun_finset (S T : Finset ι) (hST : Disjoint S T) (hf_Indep : iIndepFun m f κ μ) (hf_meas : ∀ i, Measurable (f i)) : IndepFun (fun a (i : S) => f i a) (fun a (i : T) => f i a) κ μ := by + rcases eq_or_ne μ 0 with rfl | hμ + · simp + obtain ⟨η, η_eq, hη⟩ : ∃ (η : Kernel α Ω), κ =ᵐ[μ] η ∧ IsMarkovKernel η := + exists_ae_eq_isMarkovKernel hf_Indep.ae_isProbabilityMeasure hμ + apply IndepFun.congr (Filter.EventuallyEq.symm η_eq) -- We introduce π-systems, built from the π-system of boxes which generates `MeasurableSpace.pi`. let πSβ := Set.pi (Set.univ : Set S) '' Set.pi (Set.univ : Set S) fun i => { s : Set (β i) | MeasurableSet[m i] s } @@ -889,6 +1019,7 @@ theorem iIndepFun.indepFun_finset [IsMarkovKernel κ] (S T : Finset ι) (hST : D constructor <;> intro h · intro i hi; simp_rw [sets_t', dif_pos hi]; exact h ⟨i, hi⟩ · rintro ⟨i, hi⟩; specialize h i hi; simp_rw [sets_t', dif_pos hi] at h; exact h + replace hf_Indep := hf_Indep.congr η_eq rw [iIndepFun_iff_measure_inter_preimage_eq_mul] at hf_Indep have h_Inter_inter : ((⋂ i ∈ S, f i ⁻¹' sets_s' i) ∩ ⋂ i ∈ T, f i ⁻¹' sets_t' i) = @@ -925,7 +1056,7 @@ theorem iIndepFun.indepFun_finset [IsMarkovKernel κ] (S T : Finset ι) (hST : D · refine Finset.prod_congr rfl fun i hi => ?_ rw [h_sets_s'_univ hi, Set.univ_inter] -theorem iIndepFun.indepFun_prod_mk [IsMarkovKernel κ] (hf_Indep : iIndepFun m f κ μ) +theorem iIndepFun.indepFun_prod_mk (hf_Indep : iIndepFun m f κ μ) (hf_meas : ∀ i, Measurable (f i)) (i j k : ι) (hik : i ≠ k) (hjk : j ≠ k) : IndepFun (fun a => (f i a, f j a)) (f k) κ μ := by classical @@ -952,7 +1083,7 @@ theorem iIndepFun.indepFun_prod_mk [IsMarkovKernel κ] (hf_Indep : iIndepFun m f exact ⟨hik.symm, hjk.symm⟩ open Finset in -lemma iIndepFun.indepFun_prod_mk_prod_mk [IsMarkovKernel κ] (hf_indep : iIndepFun m f κ μ) +lemma iIndepFun.indepFun_prod_mk_prod_mk (hf_indep : iIndepFun m f κ μ) (hf_meas : ∀ i, Measurable (f i)) (i j k l : ι) (hik : i ≠ k) (hil : i ≠ l) (hjk : j ≠ k) (hjl : j ≠ l) : IndepFun (fun a ↦ (f i a, f j a)) (fun a ↦ (f k a, f l a)) κ μ := by @@ -966,7 +1097,6 @@ end iIndepFun section Mul variable {β : Type*} {m : MeasurableSpace β} [Mul β] [MeasurableMul₂ β] {f : ι → Ω → β} - [IsMarkovKernel κ] @[to_additive] lemma iIndepFun.indepFun_mul_left (hf_indep : iIndepFun (fun _ ↦ m) f κ μ) @@ -994,7 +1124,6 @@ end Mul section Div variable {β : Type*} {m : MeasurableSpace β} [Div β] [MeasurableDiv₂ β] {f : ι → Ω → β} - [IsMarkovKernel κ] @[to_additive] lemma iIndepFun.indepFun_div_left (hf_indep : iIndepFun (fun _ ↦ m) f κ μ) @@ -1022,7 +1151,6 @@ end Div section CommMonoid variable {β : Type*} {m : MeasurableSpace β} [CommMonoid β] [MeasurableMul₂ β] {f : ι → Ω → β} - [IsMarkovKernel κ] @[to_additive] theorem iIndepFun.indepFun_finset_prod_of_not_mem (hf_Indep : iIndepFun (fun _ ↦ m) f κ μ) diff --git a/Mathlib/Probability/Independence/ZeroOne.lean b/Mathlib/Probability/Independence/ZeroOne.lean index 8af5f5af8b3e6..06403152bcee2 100644 --- a/Mathlib/Probability/Independence/ZeroOne.lean +++ b/Mathlib/Probability/Independence/ZeroOne.lean @@ -46,19 +46,24 @@ theorem measure_eq_zero_or_one_or_top_of_indepSet_self {t : Set Ω} simpa only [ae_dirac_eq, Filter.eventually_pure] using Kernel.measure_eq_zero_or_one_or_top_of_indepSet_self h_indep -theorem Kernel.measure_eq_zero_or_one_of_indepSet_self [∀ a, IsFiniteMeasure (κ a)] {t : Set Ω} - (h_indep : IndepSet t t κ μα) : +theorem Kernel.measure_eq_zero_or_one_of_indepSet_self' (h : ∀ᵐ a ∂μα, IsFiniteMeasure (κ a)) + {t : Set Ω} (h_indep : IndepSet t t κ μα) : ∀ᵐ a ∂μα, κ a t = 0 ∨ κ a t = 1 := by - filter_upwards [measure_eq_zero_or_one_or_top_of_indepSet_self h_indep] with a h_0_1_top + filter_upwards [measure_eq_zero_or_one_or_top_of_indepSet_self h_indep, h] with a h_0_1_top h' simpa only [measure_ne_top (κ a), or_false] using h_0_1_top +theorem Kernel.measure_eq_zero_or_one_of_indepSet_self [h : ∀ a, IsFiniteMeasure (κ a)] {t : Set Ω} + (h_indep : IndepSet t t κ μα) : + ∀ᵐ a ∂μα, κ a t = 0 ∨ κ a t = 1 := + Kernel.measure_eq_zero_or_one_of_indepSet_self' (ae_of_all μα h) h_indep + theorem measure_eq_zero_or_one_of_indepSet_self [IsFiniteMeasure μ] {t : Set Ω} (h_indep : IndepSet t t μ) : μ t = 0 ∨ μ t = 1 := by simpa only [ae_dirac_eq, Filter.eventually_pure] using Kernel.measure_eq_zero_or_one_of_indepSet_self h_indep theorem condexp_eq_zero_or_one_of_condIndepSet_self - [StandardBorelSpace Ω] [Nonempty Ω] + [StandardBorelSpace Ω] (hm : m ≤ m0) [hμ : IsFiniteMeasure μ] {t : Set Ω} (ht : MeasurableSet t) (h_indep : CondIndepSet m hm t t μ) : ∀ᵐ ω ∂μ, (μ⟦t | m⟧) ω = 0 ∨ (μ⟦t | m⟧) ω = 1 := by @@ -71,20 +76,17 @@ theorem condexp_eq_zero_or_one_of_condIndepSet_self | inl h => exact Or.inl (Or.inl h) | inr h => exact Or.inr h -variable [IsMarkovKernel κ] - open Filter theorem Kernel.indep_biSup_compl (h_le : ∀ n, s n ≤ m0) (h_indep : iIndep s κ μα) (t : Set ι) : Indep (⨆ n ∈ t, s n) (⨆ n ∈ tᶜ, s n) κ μα := indep_iSup_of_disjoint h_le h_indep disjoint_compl_right -theorem indep_biSup_compl [IsProbabilityMeasure μ] - (h_le : ∀ n, s n ≤ m0) (h_indep : iIndep s μ) (t : Set ι) : +theorem indep_biSup_compl (h_le : ∀ n, s n ≤ m0) (h_indep : iIndep s μ) (t : Set ι) : Indep (⨆ n ∈ t, s n) (⨆ n ∈ tᶜ, s n) μ := Kernel.indep_biSup_compl h_le h_indep t -theorem condIndep_biSup_compl [StandardBorelSpace Ω] [Nonempty Ω] +theorem condIndep_biSup_compl [StandardBorelSpace Ω] (hm : m ≤ m0) [IsFiniteMeasure μ] (h_le : ∀ n, s n ≤ m0) (h_indep : iCondIndep m hm s μ) (t : Set ι) : CondIndep m (⨆ n ∈ t, s n) (⨆ n ∈ tᶜ, s n) hm μ := @@ -92,7 +94,7 @@ theorem condIndep_biSup_compl [StandardBorelSpace Ω] [Nonempty Ω] section Abstract -variable {α : Type*} {p : Set ι → Prop} {f : Filter ι} {ns : α → Set ι} +variable {β : Type*} {p : Set ι → Prop} {f : Filter ι} {ns : β → Set ι} /-! We prove a version of Kolmogorov's 0-1 law for the σ-algebra `limsup s f` where `f` is a filter for which we can define the following two functions: @@ -112,13 +114,13 @@ theorem Kernel.indep_biSup_limsup (h_le : ∀ n, s n ≤ m0) (h_indep : iIndep s simp only [Set.mem_compl_iff, eventually_map] exact eventually_of_mem (hf t ht) le_iSup₂ -theorem indep_biSup_limsup [IsProbabilityMeasure μ] +theorem indep_biSup_limsup (h_le : ∀ n, s n ≤ m0) (h_indep : iIndep s μ) (hf : ∀ t, p t → tᶜ ∈ f) {t : Set ι} (ht : p t) : Indep (⨆ n ∈ t, s n) (limsup s f) μ := Kernel.indep_biSup_limsup h_le h_indep hf ht -theorem condIndep_biSup_limsup [StandardBorelSpace Ω] [Nonempty Ω] +theorem condIndep_biSup_limsup [StandardBorelSpace Ω] (hm : m ≤ m0) [IsFiniteMeasure μ] (h_le : ∀ n, s n ≤ m0) (h_indep : iCondIndep m hm s μ) (hf : ∀ t, p t → tᶜ ∈ f) {t : Set ι} (ht : p t) : @@ -128,6 +130,12 @@ theorem condIndep_biSup_limsup [StandardBorelSpace Ω] [Nonempty Ω] theorem Kernel.indep_iSup_directed_limsup (h_le : ∀ n, s n ≤ m0) (h_indep : iIndep s κ μα) (hf : ∀ t, p t → tᶜ ∈ f) (hns : Directed (· ≤ ·) ns) (hnsp : ∀ a, p (ns a)) : Indep (⨆ a, ⨆ n ∈ ns a, s n) (limsup s f) κ μα := by + rcases eq_or_ne μα 0 with rfl | hμ + · simp + obtain ⟨η, η_eq, hη⟩ : ∃ (η : Kernel α Ω), κ =ᵐ[μα] η ∧ IsMarkovKernel η := + exists_ae_eq_isMarkovKernel h_indep.ae_isProbabilityMeasure hμ + replace h_indep := h_indep.congr η_eq + apply Indep.congr (Filter.EventuallyEq.symm η_eq) apply indep_iSup_of_directed_le · exact fun a => indep_biSup_limsup h_le h_indep hf (hnsp a) · exact fun a => iSup₂_le fun n _ => h_le n @@ -138,14 +146,14 @@ theorem Kernel.indep_iSup_directed_limsup (h_le : ∀ n, s n ≤ m0) (h_indep : · exact hc.1 hn · exact hc.2 hn -theorem indep_iSup_directed_limsup [IsProbabilityMeasure μ] +theorem indep_iSup_directed_limsup (h_le : ∀ n, s n ≤ m0) (h_indep : iIndep s μ) (hf : ∀ t, p t → tᶜ ∈ f) (hns : Directed (· ≤ ·) ns) (hnsp : ∀ a, p (ns a)) : Indep (⨆ a, ⨆ n ∈ ns a, s n) (limsup s f) μ := Kernel.indep_iSup_directed_limsup h_le h_indep hf hns hnsp theorem condIndep_iSup_directed_limsup [StandardBorelSpace Ω] - [Nonempty Ω] (hm : m ≤ m0) [IsFiniteMeasure μ] + (hm : m ≤ m0) [IsFiniteMeasure μ] (h_le : ∀ n, s n ≤ m0) (h_indep : iCondIndep m hm s μ) (hf : ∀ t, p t → tᶜ ∈ f) (hns : Directed (· ≤ ·) ns) (hnsp : ∀ a, p (ns a)) : CondIndep m (⨆ a, ⨆ n ∈ ns a, s n) (limsup s f) hm μ := @@ -160,17 +168,17 @@ theorem Kernel.indep_iSup_limsup (h_le : ∀ n, s n ≤ m0) (h_indep : iIndep s exact indep_iSup_directed_limsup h_le h_indep hf hns hnsp rw [iSup_comm] refine iSup_congr fun n => ?_ - have h : ⨆ (i : α) (_ : n ∈ ns i), s n = ⨆ _ : ∃ i, n ∈ ns i, s n := by rw [iSup_exists] - haveI : Nonempty (∃ i : α, n ∈ ns i) := ⟨hns_univ n⟩ + have h : ⨆ (i : β) (_ : n ∈ ns i), s n = ⨆ _ : ∃ i, n ∈ ns i, s n := by rw [iSup_exists] + haveI : Nonempty (∃ i : β, n ∈ ns i) := ⟨hns_univ n⟩ rw [h, iSup_const] -theorem indep_iSup_limsup [IsProbabilityMeasure μ] +theorem indep_iSup_limsup (h_le : ∀ n, s n ≤ m0) (h_indep : iIndep s μ) (hf : ∀ t, p t → tᶜ ∈ f) (hns : Directed (· ≤ ·) ns) (hnsp : ∀ a, p (ns a)) (hns_univ : ∀ n, ∃ a, n ∈ ns a) : Indep (⨆ n, s n) (limsup s f) μ := Kernel.indep_iSup_limsup h_le h_indep hf hns hnsp hns_univ -theorem condIndep_iSup_limsup [StandardBorelSpace Ω] [Nonempty Ω] +theorem condIndep_iSup_limsup [StandardBorelSpace Ω] (hm : m ≤ m0) [IsFiniteMeasure μ] (h_le : ∀ n, s n ≤ m0) (h_indep : iCondIndep m hm s μ) (hf : ∀ t, p t → tᶜ ∈ f) (hns : Directed (· ≤ ·) ns) (hnsp : ∀ a, p (ns a)) (hns_univ : ∀ n, ∃ a, n ∈ ns a) : @@ -183,13 +191,13 @@ theorem Kernel.indep_limsup_self (h_le : ∀ n, s n ≤ m0) (h_indep : iIndep s Indep (limsup s f) (limsup s f) κ μα := indep_of_indep_of_le_left (indep_iSup_limsup h_le h_indep hf hns hnsp hns_univ) limsup_le_iSup -theorem indep_limsup_self [IsProbabilityMeasure μ] +theorem indep_limsup_self (h_le : ∀ n, s n ≤ m0) (h_indep : iIndep s μ) (hf : ∀ t, p t → tᶜ ∈ f) (hns : Directed (· ≤ ·) ns) (hnsp : ∀ a, p (ns a)) (hns_univ : ∀ n, ∃ a, n ∈ ns a) : Indep (limsup s f) (limsup s f) μ := Kernel.indep_limsup_self h_le h_indep hf hns hnsp hns_univ -theorem condIndep_limsup_self [StandardBorelSpace Ω] [Nonempty Ω] +theorem condIndep_limsup_self [StandardBorelSpace Ω] (hm : m ≤ m0) [IsFiniteMeasure μ] (h_le : ∀ n, s n ≤ m0) (h_indep : iCondIndep m hm s μ) (hf : ∀ t, p t → tᶜ ∈ f) (hns : Directed (· ≤ ·) ns) (hnsp : ∀ a, p (ns a)) (hns_univ : ∀ n, ∃ a, n ∈ ns a) : @@ -200,12 +208,13 @@ theorem Kernel.measure_zero_or_one_of_measurableSet_limsup (h_le : ∀ n, s n (h_indep : iIndep s κ μα) (hf : ∀ t, p t → tᶜ ∈ f) (hns : Directed (· ≤ ·) ns) (hnsp : ∀ a, p (ns a)) (hns_univ : ∀ n, ∃ a, n ∈ ns a) {t : Set Ω} (ht_tail : MeasurableSet[limsup s f] t) : - ∀ᵐ a ∂μα, κ a t = 0 ∨ κ a t = 1 := - measure_eq_zero_or_one_of_indepSet_self + ∀ᵐ a ∂μα, κ a t = 0 ∨ κ a t = 1 := by + apply measure_eq_zero_or_one_of_indepSet_self' ?_ ((indep_limsup_self h_le h_indep hf hns hnsp hns_univ).indepSet_of_measurableSet ht_tail ht_tail) + filter_upwards [h_indep.ae_isProbabilityMeasure] with a ha using by infer_instance -theorem measure_zero_or_one_of_measurableSet_limsup [IsProbabilityMeasure μ] +theorem measure_zero_or_one_of_measurableSet_limsup (h_le : ∀ n, s n ≤ m0) (h_indep : iIndep s μ) (hf : ∀ t, p t → tᶜ ∈ f) (hns : Directed (· ≤ ·) ns) (hnsp : ∀ a, p (ns a)) (hns_univ : ∀ n, ∃ a, n ∈ ns a) {t : Set Ω} (ht_tail : MeasurableSet[limsup s f] t) : @@ -214,7 +223,7 @@ theorem measure_zero_or_one_of_measurableSet_limsup [IsProbabilityMeasure μ] using Kernel.measure_zero_or_one_of_measurableSet_limsup h_le h_indep hf hns hnsp hns_univ ht_tail -theorem condexp_zero_or_one_of_measurableSet_limsup [StandardBorelSpace Ω] [Nonempty Ω] +theorem condexp_zero_or_one_of_measurableSet_limsup [StandardBorelSpace Ω] (hm : m ≤ m0) [IsFiniteMeasure μ] (h_le : ∀ n, s n ≤ m0) (h_indep : iCondIndep m hm s μ) (hf : ∀ t, p t → tᶜ ∈ f) (hns : Directed (· ≤ ·) ns) (hnsp : ∀ a, p (ns a)) @@ -249,12 +258,11 @@ theorem Kernel.indep_limsup_atTop_self (h_le : ∀ n, s n ≤ m0) (h_indep : iIn · exact Monotone.directed_le fun i j hij k hki => le_trans hki hij · exact fun n => ⟨n, le_rfl⟩ -theorem indep_limsup_atTop_self [IsProbabilityMeasure μ] - (h_le : ∀ n, s n ≤ m0) (h_indep : iIndep s μ) : +theorem indep_limsup_atTop_self (h_le : ∀ n, s n ≤ m0) (h_indep : iIndep s μ) : Indep (limsup s atTop) (limsup s atTop) μ := Kernel.indep_limsup_atTop_self h_le h_indep -theorem condIndep_limsup_atTop_self [StandardBorelSpace Ω] [Nonempty Ω] +theorem condIndep_limsup_atTop_self [StandardBorelSpace Ω] (hm : m ≤ m0) [IsFiniteMeasure μ] (h_le : ∀ n, s n ≤ m0) (h_indep : iCondIndep m hm s μ) : CondIndep m (limsup s atTop) (limsup s atTop) hm μ := @@ -262,21 +270,22 @@ theorem condIndep_limsup_atTop_self [StandardBorelSpace Ω] [Nonempty Ω] theorem Kernel.measure_zero_or_one_of_measurableSet_limsup_atTop (h_le : ∀ n, s n ≤ m0) (h_indep : iIndep s κ μα) {t : Set Ω} (ht_tail : MeasurableSet[limsup s atTop] t) : - ∀ᵐ a ∂μα, κ a t = 0 ∨ κ a t = 1 := - measure_eq_zero_or_one_of_indepSet_self + ∀ᵐ a ∂μα, κ a t = 0 ∨ κ a t = 1 := by + apply measure_eq_zero_or_one_of_indepSet_self' ?_ ((indep_limsup_atTop_self h_le h_indep).indepSet_of_measurableSet ht_tail ht_tail) + filter_upwards [h_indep.ae_isProbabilityMeasure] with a ha using by infer_instance /-- **Kolmogorov's 0-1 law** : any event in the tail σ-algebra of an independent sequence of sub-σ-algebras has probability 0 or 1. The tail σ-algebra `limsup s atTop` is the same as `⋂ n, ⋃ i ≥ n, s i`. -/ -theorem measure_zero_or_one_of_measurableSet_limsup_atTop [IsProbabilityMeasure μ] +theorem measure_zero_or_one_of_measurableSet_limsup_atTop (h_le : ∀ n, s n ≤ m0) (h_indep : iIndep s μ) {t : Set Ω} (ht_tail : MeasurableSet[limsup s atTop] t) : μ t = 0 ∨ μ t = 1 := by simpa only [ae_dirac_eq, Filter.eventually_pure] using Kernel.measure_zero_or_one_of_measurableSet_limsup_atTop h_le h_indep ht_tail -theorem condexp_zero_or_one_of_measurableSet_limsup_atTop [StandardBorelSpace Ω] [Nonempty Ω] +theorem condexp_zero_or_one_of_measurableSet_limsup_atTop [StandardBorelSpace Ω] (hm : m ≤ m0) [IsFiniteMeasure μ] (h_le : ∀ n, s n ≤ m0) (h_indep : iCondIndep m hm s μ) {t : Set Ω} (ht_tail : MeasurableSet[limsup s atTop] t) : ∀ᵐ ω ∂μ, (μ⟦t | m⟧) ω = 0 ∨ (μ⟦t | m⟧) ω = 1 := @@ -303,12 +312,12 @@ theorem Kernel.indep_limsup_atBot_self (h_le : ∀ n, s n ≤ m0) (h_indep : iIn · exact Antitone.directed_le fun _ _ ↦ Set.Ici_subset_Ici.2 · exact fun n => ⟨n, le_rfl⟩ -theorem indep_limsup_atBot_self [IsProbabilityMeasure μ] +theorem indep_limsup_atBot_self (h_le : ∀ n, s n ≤ m0) (h_indep : iIndep s μ) : Indep (limsup s atBot) (limsup s atBot) μ := Kernel.indep_limsup_atBot_self h_le h_indep -theorem condIndep_limsup_atBot_self [StandardBorelSpace Ω] [Nonempty Ω] +theorem condIndep_limsup_atBot_self [StandardBorelSpace Ω] (hm : m ≤ m0) [IsFiniteMeasure μ] (h_le : ∀ n, s n ≤ m0) (h_indep : iCondIndep m hm s μ) : CondIndep m (limsup s atBot) (limsup s atBot) hm μ := @@ -318,13 +327,14 @@ theorem condIndep_limsup_atBot_self [StandardBorelSpace Ω] [Nonempty Ω] sequence of sub-σ-algebras has probability 0 or 1 almost surely. -/ theorem Kernel.measure_zero_or_one_of_measurableSet_limsup_atBot (h_le : ∀ n, s n ≤ m0) (h_indep : iIndep s κ μα) {t : Set Ω} (ht_tail : MeasurableSet[limsup s atBot] t) : - ∀ᵐ a ∂μα, κ a t = 0 ∨ κ a t = 1 := - measure_eq_zero_or_one_of_indepSet_self + ∀ᵐ a ∂μα, κ a t = 0 ∨ κ a t = 1 := by + apply measure_eq_zero_or_one_of_indepSet_self' ?_ ((indep_limsup_atBot_self h_le h_indep).indepSet_of_measurableSet ht_tail ht_tail) + filter_upwards [h_indep.ae_isProbabilityMeasure] with a ha using by infer_instance /-- **Kolmogorov's 0-1 law** : any event in the tail σ-algebra of an independent sequence of sub-σ-algebras has probability 0 or 1. -/ -theorem measure_zero_or_one_of_measurableSet_limsup_atBot [IsProbabilityMeasure μ] +theorem measure_zero_or_one_of_measurableSet_limsup_atBot (h_le : ∀ n, s n ≤ m0) (h_indep : iIndep s μ) {t : Set Ω} (ht_tail : MeasurableSet[limsup s atBot] t) : μ t = 0 ∨ μ t = 1 := by @@ -332,8 +342,8 @@ theorem measure_zero_or_one_of_measurableSet_limsup_atBot [IsProbabilityMeasure using Kernel.measure_zero_or_one_of_measurableSet_limsup_atBot h_le h_indep ht_tail /-- **Kolmogorov's 0-1 law**, conditional version: any event in the tail σ-algebra of a -conditinoally independent sequence of sub-σ-algebras has conditional probability 0 or 1. -/ -theorem condexp_zero_or_one_of_measurableSet_limsup_atBot [StandardBorelSpace Ω] [Nonempty Ω] +conditionally independent sequence of sub-σ-algebras has conditional probability 0 or 1. -/ +theorem condexp_zero_or_one_of_measurableSet_limsup_atBot [StandardBorelSpace Ω] (hm : m ≤ m0) [IsFiniteMeasure μ] (h_le : ∀ n, s n ≤ m0) (h_indep : iCondIndep m hm s μ) {t : Set Ω} (ht_tail : MeasurableSet[limsup s atBot] t) : ∀ᵐ ω ∂μ, (μ⟦t | m⟧) ω = 0 ∨ (μ⟦t | m⟧) ω = 1 := diff --git a/Mathlib/Probability/Integration.lean b/Mathlib/Probability/Integration.lean index 9fd7234ccf87f..ad5bc0600a169 100644 --- a/Mathlib/Probability/Integration.lean +++ b/Mathlib/Probability/Integration.lean @@ -143,7 +143,7 @@ theorem IndepFun.integrable_mul {β : Type*} [MeasurableSpace β] {X Y : Ω → lintegral_mul_eq_lintegral_mul_lintegral_of_indepFun' hnX hnY hXY'' refine ⟨hX.1.mul hY.1, ?_⟩ simp_rw [HasFiniteIntegral, Pi.mul_apply, nnnorm_mul, ENNReal.coe_mul, hmul] - exact ENNReal.mul_lt_top hX.2.ne hY.2.ne + exact ENNReal.mul_lt_top hX.2 hY.2 /-- If the product of two independent real-valued random variables is integrable and the second one is not almost everywhere zero, then the first one is integrable. -/ diff --git a/Mathlib/Probability/Kernel/Basic.lean b/Mathlib/Probability/Kernel/Basic.lean index 5a8caec90e730..2c9a8b8c7a5cb 100644 --- a/Mathlib/Probability/Kernel/Basic.lean +++ b/Mathlib/Probability/Kernel/Basic.lean @@ -20,6 +20,8 @@ Classes of kernels: * `ProbabilityTheory.Kernel α β`: kernels from `α` to `β`. * `ProbabilityTheory.IsMarkovKernel κ`: a kernel from `α` to `β` is said to be a Markov kernel if for all `a : α`, `k a` is a probability measure. +* `ProbabilityTheory.IsZeroOrMarkovKernel κ`: a kernel from `α` to `β` which is zero or + a Markov kernel. * `ProbabilityTheory.IsFiniteKernel κ`: a kernel from `α` to `β` is said to be finite if there exists `C : ℝ≥0∞` such that `C < ∞` and for all `a : α`, `κ a univ ≤ C`. This implies in particular that all measures in the image of `κ` are finite, but is stronger since it requires a @@ -73,8 +75,6 @@ scoped notation "Kernel[" mα "]" α:arg β:arg => @Kernel α β mα _ /-- Notation for `Kernel` with respect to a non-standard σ-algebra in the domain and codomain. -/ scoped notation "Kernel[" mα ", " mβ "]" α:arg β:arg => @Kernel α β mα mβ -initialize_simps_projections Kernel (toFun → apply) - variable {α β ι : Type*} {mα : MeasurableSpace α} {mβ : MeasurableSpace β} namespace Kernel @@ -84,6 +84,9 @@ instance instFunLike : FunLike (Kernel α β) α (Measure β) where coe_injective' f g h := by cases f; cases g; congr lemma measurable (κ : Kernel α β) : Measurable κ := κ.measurable' +@[simp, norm_cast] lemma coe_mk (f : α → Measure β) (hf) : mk f hf = f := rfl + +initialize_simps_projections Kernel (toFun → apply) instance instZero : Zero (Kernel α β) where zero := ⟨0, measurable_zero⟩ noncomputable instance instAdd : Add (Kernel α β) where add κ η := ⟨κ + η, κ.2.add η.2⟩ @@ -136,10 +139,19 @@ end Kernel class IsMarkovKernel (κ : Kernel α β) : Prop where isProbabilityMeasure : ∀ a, IsProbabilityMeasure (κ a) +/-- A class for kernels which are zero or a Markov kernel. -/ +class IsZeroOrMarkovKernel (κ : Kernel α β) : Prop where + eq_zero_or_isMarkovKernel' : κ = 0 ∨ IsMarkovKernel κ + /-- A kernel is finite if every measure in its image is finite, with a uniform bound. -/ class IsFiniteKernel (κ : Kernel α β) : Prop where exists_univ_le : ∃ C : ℝ≥0∞, C < ∞ ∧ ∀ a, κ a Set.univ ≤ C +theorem eq_zero_or_isMarkovKernel + (κ : Kernel α β) [h : IsZeroOrMarkovKernel κ] : + κ = 0 ∨ IsMarkovKernel κ := + h.eq_zero_or_isMarkovKernel' + /-- A constant `C : ℝ≥0∞` such that `C < ∞` (`ProbabilityTheory.IsFiniteKernel.bound_lt_top κ`) and for all `a : α` and `s : Set β`, `κ a s ≤ C` (`ProbabilityTheory.Kernel.measure_le_bound κ a s`). @@ -183,12 +195,26 @@ instance IsMarkovKernel.is_probability_measure' [IsMarkovKernel κ] (a : α) : IsProbabilityMeasure (κ a) := IsMarkovKernel.isProbabilityMeasure a +instance : IsZeroOrMarkovKernel (0 : Kernel α β) := ⟨Or.inl rfl⟩ + +instance (priority := 100) IsMarkovKernel.IsZeroOrMarkovKernel [h : IsMarkovKernel κ] : + IsZeroOrMarkovKernel κ := ⟨Or.inr h⟩ + +instance (priority := 100) IsZeroOrMarkovKernel.isZeroOrProbabilityMeasure + [IsZeroOrMarkovKernel κ] (a : α) : IsZeroOrProbabilityMeasure (κ a) := by + rcases eq_zero_or_isMarkovKernel κ with rfl | h' + · simp only [Kernel.zero_apply] + infer_instance + · infer_instance + instance IsFiniteKernel.isFiniteMeasure [IsFiniteKernel κ] (a : α) : IsFiniteMeasure (κ a) := ⟨(Kernel.measure_le_bound κ a Set.univ).trans_lt (IsFiniteKernel.bound_lt_top κ)⟩ -instance (priority := 100) IsMarkovKernel.isFiniteKernel [IsMarkovKernel κ] : - IsFiniteKernel κ := - ⟨⟨1, ENNReal.one_lt_top, fun _ => prob_le_one⟩⟩ +instance (priority := 100) IsZeroOrMarkovKernel.isFiniteKernel [h : IsZeroOrMarkovKernel κ] : + IsFiniteKernel κ := by + rcases eq_zero_or_isMarkovKernel κ with rfl | _h' + · infer_instance + · exact ⟨⟨1, ENNReal.one_lt_top, fun _ => prob_le_one⟩⟩ namespace Kernel @@ -223,7 +249,7 @@ lemma IsFiniteKernel.integrable (μ : Measure α) [IsFiniteMeasure μ] (κ : Kernel α β) [IsFiniteKernel κ] {s : Set β} (hs : MeasurableSet s) : Integrable (fun x => (κ x s).toReal) μ := by refine Integrable.mono' (integrable_const (IsFiniteKernel.bound κ).toReal) - ((κ.measurable_coe hs).ennreal_toReal.aestronglyMeasurable) + ((κ.measurable_coe hs).ennreal_toReal.aestronglyMeasurable) (ae_of_all μ fun x => ?_) rw [Real.norm_eq_abs, abs_of_nonneg ENNReal.toReal_nonneg, ENNReal.toReal_le_toReal (measure_ne_top _ _) (IsFiniteKernel.bound_ne_top _)] @@ -477,6 +503,13 @@ instance const.instIsMarkovKernel {μβ : Measure β} [hμβ : IsProbabilityMeas IsMarkovKernel (const α μβ) := ⟨fun _ => hμβ⟩ +instance const.instIsZeroOrMarkovKernel {μβ : Measure β} [hμβ : IsZeroOrProbabilityMeasure μβ] : + IsZeroOrMarkovKernel (const α μβ) := by + rcases eq_zero_or_isProbabilityMeasure μβ with rfl | h + · simp only [const_zero] + infer_instance + · infer_instance + lemma isSFiniteKernel_const [Nonempty α] {μβ : Measure β} : IsSFiniteKernel (const α μβ) ↔ SFinite μβ := ⟨fun h ↦ h.sFinite (Classical.arbitrary α), fun _ ↦ inferInstance⟩ @@ -698,5 +731,27 @@ theorem setIntegral_piecewise {E : Type*} [NormedAddCommGroup E] [NormedSpace alias set_integral_piecewise := setIntegral_piecewise end Piecewise + +lemma exists_ae_eq_isMarkovKernel {μ : Measure α} + (h : ∀ᵐ a ∂μ, IsProbabilityMeasure (κ a)) (h' : μ ≠ 0) : + ∃ (η : Kernel α β), (κ =ᵐ[μ] η) ∧ IsMarkovKernel η := by + classical + obtain ⟨s, s_meas, μs, hs⟩ : ∃ s, MeasurableSet s ∧ μ s = 0 + ∧ ∀ a ∉ s, IsProbabilityMeasure (κ a) := by + refine ⟨toMeasurable μ {a | ¬ IsProbabilityMeasure (κ a)}, measurableSet_toMeasurable _ _, + by simpa [measure_toMeasurable] using h, ?_⟩ + intro a ha + contrapose! ha + exact subset_toMeasurable _ _ ha + obtain ⟨a, ha⟩ : sᶜ.Nonempty := by + contrapose! h'; simpa [μs, h'] using measure_univ_le_add_compl s (μ := μ) + refine ⟨Kernel.piecewise s_meas (Kernel.const _ (κ a)) κ, ?_, ?_⟩ + · filter_upwards [measure_zero_iff_ae_nmem.1 μs] with b hb + simp [hb, piecewise] + · refine ⟨fun b ↦ ?_⟩ + by_cases hb : b ∈ s + · simpa [hb, piecewise] using hs _ ha + · simpa [hb, piecewise] using hs _ hb + end Kernel end ProbabilityTheory diff --git a/Mathlib/Probability/Kernel/Composition.lean b/Mathlib/Probability/Kernel/Composition.lean index 3a97aa563d5d9..dc9246345f09c 100644 --- a/Mathlib/Probability/Kernel/Composition.lean +++ b/Mathlib/Probability/Kernel/Composition.lean @@ -29,8 +29,8 @@ Kernels built from other kernels: * `compProd (κ : Kernel α β) (η : Kernel (α × β) γ) : Kernel α (β × γ)`: composition-product of 2 s-finite kernels. We define a notation `κ ⊗ₖ η = compProd κ η`. `∫⁻ bc, f bc ∂((κ ⊗ₖ η) a) = ∫⁻ b, ∫⁻ c, f (b, c) ∂(η (a, b)) ∂(κ a)` -* `map (κ : Kernel α β) (f : β → γ) (hf : Measurable f) : Kernel α γ` - `∫⁻ c, g c ∂(map κ f hf a) = ∫⁻ b, g (f b) ∂(κ a)` +* `map (κ : Kernel α β) (f : β → γ) : Kernel α γ` + `∫⁻ c, g c ∂(map κ f a) = ∫⁻ b, g (f b) ∂(κ a)` * `comap (κ : Kernel α β) (f : γ → α) (hf : Measurable f) : Kernel γ β` `∫⁻ b, g b ∂(comap κ f hf c) = ∫⁻ b, g b ∂(κ (f c))` * `comp (η : Kernel β γ) (κ : Kernel α β) : Kernel α γ`: composition of 2 kernels. @@ -96,16 +96,14 @@ theorem compProdFun_iUnion (κ : Kernel α β) (η : Kernel (α × β) γ) [IsSF (f : ℕ → Set (β × γ)) (hf_meas : ∀ i, MeasurableSet (f i)) (hf_disj : Pairwise (Disjoint on f)) : compProdFun κ η a (⋃ i, f i) = ∑' i, compProdFun κ η a (f i) := by - have h_Union : - (fun b => η (a, b) {c : γ | (b, c) ∈ ⋃ i, f i}) = fun b => - η (a, b) (⋃ i, {c : γ | (b, c) ∈ f i}) := by + have h_Union : (fun b ↦ η (a, b) {c : γ | (b, c) ∈ ⋃ i, f i}) + = fun b ↦ η (a, b) (⋃ i, {c : γ | (b, c) ∈ f i}) := by ext1 b congr with c simp only [Set.mem_iUnion, Set.iSup_eq_iUnion, Set.mem_setOf_eq] rw [compProdFun, h_Union] - have h_tsum : - (fun b => η (a, b) (⋃ i, {c : γ | (b, c) ∈ f i})) = fun b => - ∑' i, η (a, b) {c : γ | (b, c) ∈ f i} := by + have h_tsum : (fun b ↦ η (a, b) (⋃ i, {c : γ | (b, c) ∈ f i})) + = fun b ↦ ∑' i, η (a, b) {c : γ | (b, c) ∈ f i} := by ext1 b rw [measure_iUnion] · intro i j hij s hsi hsj c hcs @@ -113,9 +111,7 @@ theorem compProdFun_iUnion (κ : Kernel α β) (η : Kernel (α × β) γ) [IsSF have hbcj : {(b, c)} ⊆ f j := by rw [Set.singleton_subset_iff]; exact hsj hcs simpa only [Set.bot_eq_empty, Set.le_eq_subset, Set.singleton_subset_iff, Set.mem_empty_iff_false] using hf_disj hij hbci hbcj - · -- Porting note: behavior of `@` changed relative to lean 3, was - -- exact fun i => (@measurable_prod_mk_left β γ _ _ b) _ (hf_meas i) - exact fun i => (@measurable_prod_mk_left β γ _ _ b) (hf_meas i) + · exact fun i ↦ measurable_prod_mk_left (hf_meas i) rw [h_tsum, lintegral_tsum] · rfl · intro i @@ -126,15 +122,13 @@ theorem compProdFun_iUnion (κ : Kernel α β) (η : Kernel (α × β) γ) [IsSF theorem compProdFun_tsum_right (κ : Kernel α β) (η : Kernel (α × β) γ) [IsSFiniteKernel η] (a : α) (hs : MeasurableSet s) : compProdFun κ η a s = ∑' n, compProdFun κ (seq η n) a s := by simp_rw [compProdFun, (measure_sum_seq η _).symm] - have : - ∫⁻ b, Measure.sum (fun n => seq η n (a, b)) {c : γ | (b, c) ∈ s} ∂κ a = - ∫⁻ b, ∑' n, seq η n (a, b) {c : γ | (b, c) ∈ s} ∂κ a := by - congr - ext1 b + have : ∫⁻ b, Measure.sum (fun n => seq η n (a, b)) {c : γ | (b, c) ∈ s} ∂κ a + = ∫⁻ b, ∑' n, seq η n (a, b) {c : γ | (b, c) ∈ s} ∂κ a := by + congr with b rw [Measure.sum_apply] exact measurable_prod_mk_left hs rw [this, lintegral_tsum] - exact fun n => ((measurable_kernel_prod_mk_left (κ := (seq η n)) + exact fun n ↦ ((measurable_kernel_prod_mk_left (κ := (seq η n)) ((measurable_fst.snd.prod_mk measurable_snd) hs)).comp measurable_prod_mk_left).aemeasurable theorem compProdFun_tsum_left (κ : Kernel α β) (η : Kernel (α × β) γ) [IsSFiniteKernel κ] (a : α) @@ -146,34 +140,21 @@ theorem compProdFun_eq_tsum (κ : Kernel α β) [IsSFiniteKernel κ] (η : Kerne compProdFun κ η a s = ∑' (n) (m), compProdFun (seq κ n) (seq η m) a s := by simp_rw [compProdFun_tsum_left κ η a s, compProdFun_tsum_right _ η a hs] -/-- Auxiliary lemma for `measurable_compProdFun`. -/ -theorem measurable_compProdFun_of_finite (κ : Kernel α β) [IsFiniteKernel κ] (η : Kernel (α × β) γ) - [IsFiniteKernel η] (hs : MeasurableSet s) : Measurable fun a => compProdFun κ η a s := by +theorem measurable_compProdFun (κ : Kernel α β) [IsSFiniteKernel κ] (η : Kernel (α × β) γ) + [IsSFiniteKernel η] (hs : MeasurableSet s) : + Measurable fun a ↦ compProdFun κ η a s := by simp only [compProdFun] have h_meas : Measurable (Function.uncurry fun a b => η (a, b) {c : γ | (b, c) ∈ s}) := by - have : - (Function.uncurry fun a b => η (a, b) {c : γ | (b, c) ∈ s}) = fun p => - η p {c : γ | (p.2, c) ∈ s} := by + have : (Function.uncurry fun a b => η (a, b) {c : γ | (b, c) ∈ s}) + = fun p ↦ η p {c : γ | (p.2, c) ∈ s} := by ext1 p rw [Function.uncurry_apply_pair] rw [this] exact measurable_kernel_prod_mk_left (measurable_fst.snd.prod_mk measurable_snd hs) exact h_meas.lintegral_kernel_prod_right -theorem measurable_compProdFun (κ : Kernel α β) [IsSFiniteKernel κ] (η : Kernel (α × β) γ) - [IsSFiniteKernel η] (hs : MeasurableSet s) : Measurable fun a => compProdFun κ η a s := by - simp_rw [compProdFun_tsum_right κ η _ hs] - refine Measurable.ennreal_tsum fun n => ?_ - simp only [compProdFun] - have h_meas : Measurable (Function.uncurry fun a b => seq η n (a, b) {c : γ | (b, c) ∈ s}) := by - have : - (Function.uncurry fun a b => seq η n (a, b) {c : γ | (b, c) ∈ s}) = fun p => - seq η n p {c : γ | (p.2, c) ∈ s} := by - ext1 p - rw [Function.uncurry_apply_pair] - rw [this] - exact measurable_kernel_prod_mk_left (measurable_fst.snd.prod_mk measurable_snd hs) - exact h_meas.lintegral_kernel_prod_right +@[deprecated (since := "2024-08-30")] +alias measurable_compProdFun_of_finite := measurable_compProdFun open scoped Classical @@ -182,24 +163,24 @@ open scoped Classical (see `ProbabilityTheory.Kernel.lintegral_compProd`). If either of the kernels is not s-finite, `compProd` is given the junk value 0. -/ noncomputable def compProd (κ : Kernel α β) (η : Kernel (α × β) γ) : Kernel α (β × γ) := -if h : IsSFiniteKernel κ ∧ IsSFiniteKernel η then -{ toFun := fun a ↦ - Measure.ofMeasurable (fun s _ => compProdFun κ η a s) (compProdFun_empty κ η a) - (@compProdFun_iUnion _ _ _ _ _ _ κ η h.2 a) - measurable' := by - have : IsSFiniteKernel κ := h.1 - have : IsSFiniteKernel η := h.2 - refine Measure.measurable_of_measurable_coe _ fun s hs => ?_ - have : - (fun a => - Measure.ofMeasurable (fun s _ => compProdFun κ η a s) (compProdFun_empty κ η a) - (compProdFun_iUnion κ η a) s) = - fun a => compProdFun κ η a s := by - ext1 a; rwa [Measure.ofMeasurable_apply] - rw [this] - exact measurable_compProdFun κ η hs } -else 0 - + if h : IsSFiniteKernel κ ∧ IsSFiniteKernel η then + { toFun := fun a ↦ + have : IsSFiniteKernel η := h.2 + Measure.ofMeasurable (fun s _ ↦ compProdFun κ η a s) (compProdFun_empty κ η a) + (compProdFun_iUnion κ η a) + measurable' := by + have : IsSFiniteKernel κ := h.1 + have : IsSFiniteKernel η := h.2 + refine Measure.measurable_of_measurable_coe _ fun s hs ↦ ?_ + have : (fun a ↦ Measure.ofMeasurable (fun s _ ↦ compProdFun κ η a s) (compProdFun_empty κ η a) + (compProdFun_iUnion κ η a) s) + = fun a ↦ compProdFun κ η a s := by + ext1 a; rwa [Measure.ofMeasurable_apply] + rw [this] + exact measurable_compProdFun κ η hs } + else 0 + +@[inherit_doc] scoped[ProbabilityTheory] infixl:100 " ⊗ₖ " => ProbabilityTheory.Kernel.compProd theorem compProd_apply_eq_compProdFun (κ : Kernel α β) [IsSFiniteKernel κ] (η : Kernel (α × β) γ) @@ -529,7 +510,7 @@ theorem compProd_apply_univ_le (κ : Kernel α β) (η : Kernel (α × β) γ) [ instance IsFiniteKernel.compProd (κ : Kernel α β) [IsFiniteKernel κ] (η : Kernel (α × β) γ) [IsFiniteKernel η] : IsFiniteKernel (κ ⊗ₖ η) := ⟨⟨IsFiniteKernel.bound κ * IsFiniteKernel.bound η, - ENNReal.mul_lt_top (IsFiniteKernel.bound_ne_top κ) (IsFiniteKernel.bound_ne_top η), fun a => + ENNReal.mul_lt_top (IsFiniteKernel.bound_lt_top κ) (IsFiniteKernel.bound_lt_top η), fun a => calc (κ ⊗ₖ η) a Set.univ ≤ κ a Set.univ * IsFiniteKernel.bound η := compProd_apply_univ_le κ η a _ ≤ IsFiniteKernel.bound κ * IsFiniteKernel.bound η := @@ -586,62 +567,95 @@ section MapComap /-! ### map, comap -/ -variable {γ δ : Type*} {mγ : MeasurableSpace γ} {mδ : MeasurableSpace δ} {f : β → γ} {g : γ → α} +variable {γ δ : Type*} [MeasurableSpace γ] {mδ : MeasurableSpace δ} {f : β → γ} {g : γ → α} -/-- The pushforward of a kernel along a measurable function. -We include measurability in the assumptions instead of using junk values -to make sure that typeclass inference can infer that the `map` of a Markov kernel -is again a Markov kernel. -/ -noncomputable def map (κ : Kernel α β) (f : β → γ) (hf : Measurable f) : Kernel α γ where +/-- The pushforward of a kernel along a measurable function. This is an implementation detail, +use `map κ f` instead. -/ +noncomputable def mapOfMeasurable (κ : Kernel α β) (f : β → γ) (hf : Measurable f) : + Kernel α γ where toFun a := (κ a).map f measurable' := (Measure.measurable_map _ hf).comp (Kernel.measurable κ) -theorem map_apply (κ : Kernel α β) (hf : Measurable f) (a : α) : map κ f hf a = (κ a).map f := +open Classical in +/-- The pushforward of a kernel along a function. +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 α γ := + if hf : Measurable f then mapOfMeasurable κ f hf else 0 + +theorem map_of_not_measurable (κ : Kernel α β) {f : β → γ} (hf : ¬(Measurable f)) : + map κ f = 0 := by + simp [map, hf] + +@[simp] theorem mapOfMeasurable_eq_map (κ : Kernel α β) {f : β → γ} (hf : Measurable f) : + mapOfMeasurable κ f hf = map κ f := by + simp [map, hf] + +theorem map_apply (κ : Kernel α β) (hf : Measurable f) (a : α) : map κ f a = (κ a).map f := by + simp only [map, hf, ↓reduceDIte, mapOfMeasurable] rfl theorem map_apply' (κ : Kernel α β) (hf : Measurable f) (a : α) {s : Set γ} (hs : MeasurableSet s) : - map κ f hf a s = κ a (f ⁻¹' s) := by rw [map_apply, Measure.map_apply hf hs] + map κ f a s = κ a (f ⁻¹' s) := by rw [map_apply _ hf, Measure.map_apply hf hs] @[simp] -lemma map_zero (hf : Measurable f) : Kernel.map (0 : Kernel α β) f hf = 0 := by - ext; rw [Kernel.map_apply]; simp +lemma map_zero : Kernel.map (0 : Kernel α β) f = 0 := by + ext + by_cases hf : Measurable f + · simp [map_apply, hf] + · simp [map_of_not_measurable _ hf, map_apply] @[simp] -lemma map_id (κ : Kernel α β) : map κ id measurable_id = κ := by ext a; rw [map_apply]; simp +lemma map_id (κ : Kernel α β) : map κ id = κ := by + ext a + simp [map_apply, measurable_id] @[simp] -lemma map_id' (κ : Kernel α β) : map κ (fun a ↦ a) measurable_id = κ := map_id κ +lemma map_id' (κ : Kernel α β) : map κ (fun a ↦ a) = κ := map_id κ nonrec theorem lintegral_map (κ : Kernel α β) (hf : Measurable f) (a : α) {g' : γ → ℝ≥0∞} - (hg : Measurable g') : ∫⁻ b, g' b ∂map κ f hf a = ∫⁻ a, g' (f a) ∂κ a := by + (hg : Measurable g') : ∫⁻ b, g' b ∂map κ f a = ∫⁻ a, g' (f a) ∂κ a := by rw [map_apply _ hf, lintegral_map hg hf] -theorem sum_map_seq (κ : Kernel α β) [IsSFiniteKernel κ] (hf : Measurable f) : - (Kernel.sum fun n => map (seq κ n) f hf) = map κ f hf := by - ext a s hs - rw [Kernel.sum_apply, map_apply' κ hf a hs, Measure.sum_apply _ hs, ← measure_sum_seq κ, - Measure.sum_apply _ (hf hs)] - simp_rw [map_apply' _ hf _ hs] +theorem sum_map_seq (κ : Kernel α β) [IsSFiniteKernel κ] (f : β → γ) : + (Kernel.sum fun n => map (seq κ n) f) = map κ f := by + by_cases hf : Measurable f + · ext a s hs + rw [Kernel.sum_apply, map_apply' κ hf a hs, Measure.sum_apply _ hs, ← measure_sum_seq κ, + Measure.sum_apply _ (hf hs)] + simp_rw [map_apply' _ hf _ hs] + · simp [map_of_not_measurable _ hf] -instance IsMarkovKernel.map (κ : Kernel α β) [IsMarkovKernel κ] (hf : Measurable f) : - IsMarkovKernel (map κ f hf) := +lemma IsMarkovKernel.map (κ : Kernel α β) [IsMarkovKernel κ] (hf : Measurable f) : + IsMarkovKernel (map κ f) := ⟨fun a => ⟨by rw [map_apply' κ hf a MeasurableSet.univ, Set.preimage_univ, measure_univ]⟩⟩ -instance IsFiniteKernel.map (κ : Kernel α β) [IsFiniteKernel κ] (hf : Measurable f) : - IsFiniteKernel (map κ f hf) := by +instance IsZeroOrMarkovKernel.map (κ : Kernel α β) [IsZeroOrMarkovKernel κ] (f : β → γ) : + IsZeroOrMarkovKernel (map κ f) := by + by_cases hf : Measurable f + · rcases eq_zero_or_isMarkovKernel κ with rfl | h + · simp only [map_zero]; infer_instance + · have := IsMarkovKernel.map κ hf; infer_instance + · simp only [map_of_not_measurable _ hf]; infer_instance + +instance IsFiniteKernel.map (κ : Kernel α β) [IsFiniteKernel κ] (f : β → γ) : + IsFiniteKernel (map κ f) := by refine ⟨⟨IsFiniteKernel.bound κ, IsFiniteKernel.bound_lt_top κ, fun a => ?_⟩⟩ - rw [map_apply' κ hf a MeasurableSet.univ] - exact measure_le_bound κ a _ + by_cases hf : Measurable f + · rw [map_apply' κ hf a MeasurableSet.univ] + exact measure_le_bound κ a _ + · simp [map_of_not_measurable _ hf] -instance IsSFiniteKernel.map (κ : Kernel α β) [IsSFiniteKernel κ] (hf : Measurable f) : - IsSFiniteKernel (map κ f hf) := - ⟨⟨fun n => Kernel.map (seq κ n) f hf, inferInstance, (sum_map_seq κ hf).symm⟩⟩ +instance IsSFiniteKernel.map (κ : Kernel α β) [IsSFiniteKernel κ] (f : β → γ) : + IsSFiniteKernel (map κ f) := + ⟨⟨fun n => Kernel.map (seq κ n) f, inferInstance, (sum_map_seq κ f).symm⟩⟩ @[simp] lemma map_const (μ : Measure α) {f : α → β} (hf : Measurable f) : - map (const γ μ) f hf = const γ (μ.map f) := by + map (const γ μ) f = const γ (μ.map f) := by ext x s hs - rw [map_apply' _ _ _ hs, const_apply, const_apply, Measure.map_apply hf hs] + rw [map_apply' _ hf _ hs, const_apply, const_apply, Measure.map_apply hf hs] /-- Pullback of a kernel, such that for each set s `comap κ g hg c s = κ (g c) s`. We include measurability in the assumptions instead of using junk values @@ -695,9 +709,9 @@ instance IsSFiniteKernel.comap (κ : Kernel α β) [IsSFiniteKernel κ] (hg : Me lemma comap_map_comm (κ : Kernel β γ) {f : α → β} {g : γ → δ} (hf : Measurable f) (hg : Measurable g) : - comap (map κ g hg) f hf = map (comap κ f hf) g hg := by + comap (map κ g) f hf = map (comap κ f hf) g := by ext x s _ - rw [comap_apply, map_apply, map_apply, comap_apply] + rw [comap_apply, map_apply _ hg, map_apply _ hg, comap_apply] end MapComap @@ -783,13 +797,19 @@ lemma isSFiniteKernel_prodMkRight_unit {κ : Kernel α β} : change IsSFiniteKernel ((prodMkRight Unit κ).comap (fun a ↦ (a, ())) (by fun_prop)) infer_instance -lemma map_prodMkLeft (γ : Type*) [MeasurableSpace γ] (κ : Kernel α β) - {f : β → δ} (hf : Measurable f) : - map (prodMkLeft γ κ) f hf = prodMkLeft γ (map κ f hf) := rfl +lemma map_prodMkLeft (γ : Type*) [MeasurableSpace γ] (κ : Kernel α β) (f : β → δ) : + map (prodMkLeft γ κ) f = prodMkLeft γ (map κ f) := by + by_cases hf : Measurable f + · simp only [map, hf, ↓reduceDIte] + rfl + · simp [map_of_not_measurable _ hf] -lemma map_prodMkRight (κ : Kernel α β) (γ : Type*) [MeasurableSpace γ] - {f : β → δ} (hf : Measurable f) : - map (prodMkRight γ κ) f hf = prodMkRight γ (map κ f hf) := rfl +lemma map_prodMkRight (κ : Kernel α β) (γ : Type*) [MeasurableSpace γ] (f : β → δ) : + map (prodMkRight γ κ) f = prodMkRight γ (map κ f) := by + by_cases hf : Measurable f + · simp only [map, hf, ↓reduceDIte] + rfl + · simp [map_of_not_measurable _ hf] /-- Define a `Kernel (β × α) γ` from a `Kernel (α × β) γ` by taking the comap of `Prod.swap`. -/ def swapLeft (κ : Kernel (α × β) γ) : Kernel (β × α) γ := @@ -820,9 +840,13 @@ instance IsSFiniteKernel.swapLeft (κ : Kernel (α × β) γ) [IsSFiniteKernel @[simp] lemma swapLeft_prodMkRight (κ : Kernel α β) (γ : Type*) [MeasurableSpace γ] : swapLeft (prodMkRight γ κ) = prodMkLeft γ κ := rfl -/-- Define a `Kernel α (γ × β)` from a `Kernel α (β × γ)` by taking the map of `Prod.swap`. -/ +/-- Define a `Kernel α (γ × β)` from a `Kernel α (β × γ)` by taking the map of `Prod.swap`. +We use `mapOfMeasurable` in the definition for better defeqs. -/ noncomputable def swapRight (κ : Kernel α (β × γ)) : Kernel α (γ × β) := - map κ Prod.swap measurable_swap + mapOfMeasurable κ Prod.swap measurable_swap + +lemma swapRight_eq (κ : Kernel α (β × γ)) : swapRight κ = map κ Prod.swap := by + simp [swapRight] theorem swapRight_apply (κ : Kernel α (β × γ)) (a : α) : swapRight κ a = (κ a).map Prod.swap := rfl @@ -833,20 +857,27 @@ theorem swapRight_apply' (κ : Kernel α (β × γ)) (a : α) {s : Set (γ × β theorem lintegral_swapRight (κ : Kernel α (β × γ)) (a : α) {g : γ × β → ℝ≥0∞} (hg : Measurable g) : ∫⁻ c, g c ∂swapRight κ a = ∫⁻ bc : β × γ, g bc.swap ∂κ a := by - rw [swapRight, lintegral_map _ measurable_swap a hg] + rw [swapRight_eq, lintegral_map _ measurable_swap a hg] instance IsMarkovKernel.swapRight (κ : Kernel α (β × γ)) [IsMarkovKernel κ] : - IsMarkovKernel (swapRight κ) := by rw [Kernel.swapRight]; infer_instance + IsMarkovKernel (swapRight κ) := by + rw [Kernel.swapRight_eq]; exact IsMarkovKernel.map _ measurable_swap + +instance IsZeroOrMarkovKernel.swapRight (κ : Kernel α (β × γ)) [IsZeroOrMarkovKernel κ] : + IsZeroOrMarkovKernel (swapRight κ) := by rw [Kernel.swapRight_eq]; infer_instance instance IsFiniteKernel.swapRight (κ : Kernel α (β × γ)) [IsFiniteKernel κ] : - IsFiniteKernel (swapRight κ) := by rw [Kernel.swapRight]; infer_instance + IsFiniteKernel (swapRight κ) := by rw [Kernel.swapRight_eq]; infer_instance instance IsSFiniteKernel.swapRight (κ : Kernel α (β × γ)) [IsSFiniteKernel κ] : - IsSFiniteKernel (swapRight κ) := by rw [Kernel.swapRight]; infer_instance + IsSFiniteKernel (swapRight κ) := by rw [Kernel.swapRight_eq]; infer_instance -/-- Define a `Kernel α β` from a `Kernel α (β × γ)` by taking the map of the first projection. -/ +/-- Define a `Kernel α β` from a `Kernel α (β × γ)` by taking the map of the first projection. +We use `mapOfMeasurable` for better defeqs. -/ noncomputable def fst (κ : Kernel α (β × γ)) : Kernel α β := - map κ Prod.fst measurable_fst + mapOfMeasurable κ Prod.fst measurable_fst + +theorem fst_eq (κ : Kernel α (β × γ)) : fst κ = map κ Prod.fst := by simp [fst] theorem fst_apply (κ : Kernel α (β × γ)) (a : α) : fst κ a = (κ a).map Prod.fst := rfl @@ -859,16 +890,20 @@ lemma fst_zero : fst (0 : Kernel α (β × γ)) = 0 := by simp [fst] theorem lintegral_fst (κ : Kernel α (β × γ)) (a : α) {g : β → ℝ≥0∞} (hg : Measurable g) : ∫⁻ c, g c ∂fst κ a = ∫⁻ bc : β × γ, g bc.fst ∂κ a := by - rw [fst, lintegral_map _ measurable_fst a hg] + rw [fst_eq, lintegral_map _ measurable_fst a hg] instance IsMarkovKernel.fst (κ : Kernel α (β × γ)) [IsMarkovKernel κ] : IsMarkovKernel (fst κ) := by - rw [Kernel.fst]; infer_instance + rw [Kernel.fst_eq]; exact IsMarkovKernel.map _ measurable_fst + +instance IsZeroOrMarkovKernel.fst (κ : Kernel α (β × γ)) [IsZeroOrMarkovKernel κ] : + IsZeroOrMarkovKernel (fst κ) := by + rw [Kernel.fst_eq]; infer_instance instance IsFiniteKernel.fst (κ : Kernel α (β × γ)) [IsFiniteKernel κ] : IsFiniteKernel (fst κ) := by - rw [Kernel.fst]; infer_instance + rw [Kernel.fst_eq]; infer_instance instance IsSFiniteKernel.fst (κ : Kernel α (β × γ)) [IsSFiniteKernel κ] : - IsSFiniteKernel (fst κ) := by rw [Kernel.fst]; infer_instance + IsSFiniteKernel (fst κ) := by rw [Kernel.fst_eq]; infer_instance instance (priority := 100) isFiniteKernel_of_isFiniteKernel_fst {κ : Kernel α (β × γ)} [h : IsFiniteKernel (fst κ)] : @@ -877,18 +912,21 @@ instance (priority := 100) isFiniteKernel_of_isFiniteKernel_fst {κ : Kernel α rw [fst_apply' _ _ MeasurableSet.univ] simp -lemma fst_map_prod (κ : Kernel α β) {f : β → γ} {g : β → δ} - (hf : Measurable f) (hg : Measurable g) : - fst (map κ (fun x ↦ (f x, g x)) (hf.prod_mk hg)) = map κ f hf := by - ext x s hs - rw [fst_apply' _ _ hs, map_apply', map_apply' _ _ _ hs] - · rfl - · exact measurable_fst hs +lemma fst_map_prod (κ : Kernel α β) {f : β → γ} {g : β → δ} (hg : Measurable g) : + fst (map κ (fun x ↦ (f x, g x))) = map κ f := by + by_cases hf : Measurable f + · ext x s hs + rw [fst_apply' _ _ hs, map_apply' _ (hf.prod hg), map_apply' _ hf _ hs] + · rfl + · exact measurable_fst hs + · have : ¬ Measurable (fun x ↦ (f x, g x)) := by + contrapose! hf; exact hf.fst + simp [map_of_not_measurable _ hf, map_of_not_measurable _ this] lemma fst_map_id_prod (κ : Kernel α β) {γ : Type*} {mγ : MeasurableSpace γ} {f : β → γ} (hf : Measurable f) : - fst (map κ (fun a ↦ (a, f a)) (measurable_id.prod_mk hf)) = κ := by - rw [fst_map_prod _ measurable_id' hf, Kernel.map_id'] + fst (map κ (fun a ↦ (a, f a))) = κ := by + rw [fst_map_prod _ hf, Kernel.map_id'] @[simp] lemma fst_compProd (κ : Kernel α β) (η : Kernel (α × β) γ) [IsSFiniteKernel κ] [IsMarkovKernel η] : @@ -910,9 +948,12 @@ lemma fst_prodMkLeft (δ : Type*) [MeasurableSpace δ] (κ : Kernel α (β × γ lemma fst_prodMkRight (κ : Kernel α (β × γ)) (δ : Type*) [MeasurableSpace δ] : fst (prodMkRight δ κ) = prodMkRight δ (fst κ) := rfl -/-- Define a `Kernel α γ` from a `Kernel α (β × γ)` by taking the map of the second projection. -/ +/-- Define a `Kernel α γ` from a `Kernel α (β × γ)` by taking the map of the second projection. +We use `mapOfMeasurable` for better defeqs. -/ noncomputable def snd (κ : Kernel α (β × γ)) : Kernel α γ := - map κ Prod.snd measurable_snd + mapOfMeasurable κ Prod.snd measurable_snd + +theorem snd_eq (κ : Kernel α (β × γ)) : snd κ = map κ Prod.snd := by simp [snd] theorem snd_apply (κ : Kernel α (β × γ)) (a : α) : snd κ a = (κ a).map Prod.snd := rfl @@ -925,16 +966,20 @@ lemma snd_zero : snd (0 : Kernel α (β × γ)) = 0 := by simp [snd] theorem lintegral_snd (κ : Kernel α (β × γ)) (a : α) {g : γ → ℝ≥0∞} (hg : Measurable g) : ∫⁻ c, g c ∂snd κ a = ∫⁻ bc : β × γ, g bc.snd ∂κ a := by - rw [snd, lintegral_map _ measurable_snd a hg] + rw [snd_eq, lintegral_map _ measurable_snd a hg] instance IsMarkovKernel.snd (κ : Kernel α (β × γ)) [IsMarkovKernel κ] : IsMarkovKernel (snd κ) := by - rw [Kernel.snd]; infer_instance + rw [Kernel.snd_eq]; exact IsMarkovKernel.map _ measurable_snd + +instance IsZeroOrMarkovKernel.snd (κ : Kernel α (β × γ)) [IsZeroOrMarkovKernel κ] : + IsZeroOrMarkovKernel (snd κ) := by + rw [Kernel.snd_eq]; infer_instance instance IsFiniteKernel.snd (κ : Kernel α (β × γ)) [IsFiniteKernel κ] : IsFiniteKernel (snd κ) := by - rw [Kernel.snd]; infer_instance + rw [Kernel.snd_eq]; infer_instance instance IsSFiniteKernel.snd (κ : Kernel α (β × γ)) [IsSFiniteKernel κ] : - IsSFiniteKernel (snd κ) := by rw [Kernel.snd]; infer_instance + IsSFiniteKernel (snd κ) := by rw [Kernel.snd_eq]; infer_instance instance (priority := 100) isFiniteKernel_of_isFiniteKernel_snd {κ : Kernel α (β × γ)} [h : IsFiniteKernel (snd κ)] : @@ -943,18 +988,21 @@ instance (priority := 100) isFiniteKernel_of_isFiniteKernel_snd {κ : Kernel α rw [snd_apply' _ _ MeasurableSet.univ] simp -lemma snd_map_prod (κ : Kernel α β) {f : β → γ} {g : β → δ} - (hf : Measurable f) (hg : Measurable g) : - snd (map κ (fun x ↦ (f x, g x)) (hf.prod_mk hg)) = map κ g hg := by - ext x s hs - rw [snd_apply' _ _ hs, map_apply', map_apply' _ _ _ hs] - · rfl - · exact measurable_snd hs +lemma snd_map_prod (κ : Kernel α β) {f : β → γ} {g : β → δ} (hf : Measurable f) : + snd (map κ (fun x ↦ (f x, g x))) = map κ g := by + by_cases hg : Measurable g + · ext x s hs + rw [snd_apply' _ _ hs, map_apply' _ (hf.prod hg), map_apply' _ hg _ hs] + · rfl + · exact measurable_snd hs + · have : ¬ Measurable (fun x ↦ (f x, g x)) := by + contrapose! hg; exact hg.snd + simp [map_of_not_measurable _ hg, map_of_not_measurable _ this] lemma snd_map_prod_id (κ : Kernel α β) {γ : Type*} {mγ : MeasurableSpace γ} {f : β → γ} (hf : Measurable f) : - snd (map κ (fun a ↦ (f a, a)) (hf.prod_mk measurable_id)) = κ := by - rw [snd_map_prod _ hf measurable_id', Kernel.map_id'] + snd (map κ (fun a ↦ (f a, a))) = κ := by + rw [snd_map_prod _ hf, Kernel.map_id'] lemma snd_prodMkLeft (δ : Type*) [MeasurableSpace δ] (κ : Kernel α (β × γ)) : snd (prodMkLeft δ κ) = prodMkLeft δ (snd κ) := rfl @@ -1080,6 +1128,7 @@ noncomputable def comp (η : Kernel β γ) (κ : Kernel α β) : Kernel α γ wh toFun a := (κ a).bind η measurable' := (Measure.measurable_bind' η.measurable).comp κ.measurable +@[inherit_doc] scoped[ProbabilityTheory] infixl:100 " ∘ₖ " => ProbabilityTheory.Kernel.comp theorem comp_apply (η : Kernel β γ) (κ : Kernel α β) (a : α) : (η ∘ₖ κ) a = (κ a).bind η := @@ -1117,9 +1166,9 @@ theorem comp_assoc {δ : Type*} {mδ : MeasurableSpace δ} (ξ : Kernel γ δ) [ simp_rw [lintegral_comp _ _ _ hf, lintegral_comp _ _ _ hf.lintegral_kernel] theorem deterministic_comp_eq_map (hf : Measurable f) (κ : Kernel α β) : - deterministic f hf ∘ₖ κ = map κ f hf := by + deterministic f hf ∘ₖ κ = map κ f := by ext a s hs - simp_rw [map_apply' _ _ _ hs, comp_apply' _ _ _ hs, deterministic_apply' hf _ hs, + simp_rw [map_apply' _ hf _ hs, comp_apply' _ _ _ hs, deterministic_apply' hf _ hs, lintegral_indicator_const_comp hf hs, one_mul] theorem comp_deterministic_eq_comap (κ : Kernel α β) (hg : Measurable g) : @@ -1179,6 +1228,14 @@ theorem lintegral_prod (κ : Kernel α β) [IsSFiniteKernel κ] (η : Kernel α instance IsMarkovKernel.prod (κ : Kernel α β) [IsMarkovKernel κ] (η : Kernel α γ) [IsMarkovKernel η] : IsMarkovKernel (κ ×ₖ η) := by rw [Kernel.prod]; infer_instance +nonrec instance IsZeroOrMarkovKernel.prod (κ : Kernel α β) [h : IsZeroOrMarkovKernel κ] + (η : Kernel α γ) [IsZeroOrMarkovKernel η] : IsZeroOrMarkovKernel (κ ×ₖ η) := by + rcases eq_zero_or_isMarkovKernel κ with rfl | h + · simp only [prod, swapLeft_prodMkLeft, compProd_zero_left]; infer_instance + rcases eq_zero_or_isMarkovKernel η with rfl | h' + · simp only [prod, swapLeft, prodMkLeft_zero, comap_zero, compProd_zero_right]; infer_instance + infer_instance + instance IsFiniteKernel.prod (κ : Kernel α β) [IsFiniteKernel κ] (η : Kernel α γ) [IsFiniteKernel η] : IsFiniteKernel (κ ×ₖ η) := by rw [Kernel.prod]; infer_instance diff --git a/Mathlib/Probability/Kernel/Condexp.lean b/Mathlib/Probability/Kernel/Condexp.lean index 59fb17ba03c8b..b0d43c826a6c7 100644 --- a/Mathlib/Probability/Kernel/Condexp.lean +++ b/Mathlib/Probability/Kernel/Condexp.lean @@ -56,8 +56,9 @@ theorem _root_.MeasureTheory.Integrable.comp_snd_map_prod_id [NormedAddCommGroup end AuxLemmas variable {Ω F : Type*} {m : MeasurableSpace Ω} [mΩ : MeasurableSpace Ω] - [StandardBorelSpace Ω] [Nonempty Ω] {μ : Measure Ω} [IsFiniteMeasure μ] + [StandardBorelSpace Ω] {μ : Measure Ω} [IsFiniteMeasure μ] +open Classical in /-- Kernel associated with the conditional expectation with respect to a σ-algebra. It satisfies `μ[f | m] =ᵐ[μ] fun ω => ∫ y, f y ∂(condexpKernel μ m ω)`. It is defined as the conditional distribution of the identity given the identity, where the second @@ -66,14 +67,25 @@ We use `m ⊓ mΩ` instead of `m` to ensure that it is a sub-σ-algebra of `mΩ` `Kernel.comap` to get a kernel from `m` to `mΩ` instead of from `m ⊓ mΩ` to `mΩ`. -/ noncomputable irreducible_def condexpKernel (μ : Measure Ω) [IsFiniteMeasure μ] (m : MeasurableSpace Ω) : @Kernel Ω Ω m mΩ := - Kernel.comap (@condDistrib Ω Ω Ω mΩ _ _ mΩ (m ⊓ mΩ) id id μ _) id - (measurable_id'' (inf_le_left : m ⊓ mΩ ≤ m)) - -lemma condexpKernel_apply_eq_condDistrib {ω : Ω} : + if _h : Nonempty Ω then + Kernel.comap (@condDistrib Ω Ω Ω mΩ _ _ mΩ (m ⊓ mΩ) id id μ _) id + (measurable_id'' (inf_le_left : m ⊓ mΩ ≤ m)) + else 0 + +lemma condexpKernel_eq (μ : Measure Ω) [IsFiniteMeasure μ] [h : Nonempty Ω] + (m : MeasurableSpace Ω) : + condexpKernel (mΩ := mΩ) μ m = Kernel.comap (@condDistrib Ω Ω Ω mΩ _ _ mΩ (m ⊓ mΩ) id id μ _) id + (measurable_id'' (inf_le_left : m ⊓ mΩ ≤ m)) := by + simp [condexpKernel, h] + +lemma condexpKernel_apply_eq_condDistrib [Nonempty Ω] {ω : Ω} : condexpKernel μ m ω = @condDistrib Ω Ω Ω mΩ _ _ mΩ (m ⊓ mΩ) id id μ _ (id ω) := by - simp_rw [condexpKernel, Kernel.comap_apply] + simp [condexpKernel_eq, Kernel.comap_apply] -instance : IsMarkovKernel (condexpKernel μ m) := by simp only [condexpKernel]; infer_instance +instance : IsMarkovKernel (condexpKernel μ m) := by + rcases isEmpty_or_nonempty Ω with h | h + · exact ⟨fun a ↦ (IsEmpty.false a).elim⟩ + · simp [condexpKernel, h]; infer_instance section Measurability @@ -81,6 +93,7 @@ variable [NormedAddCommGroup F] {f : Ω → F} theorem measurable_condexpKernel {s : Set Ω} (hs : MeasurableSet s) : Measurable[m] fun ω => condexpKernel μ m ω s := by + nontriviality Ω simp_rw [condexpKernel_apply_eq_condDistrib] refine Measurable.mono ?_ (inf_le_left : m ⊓ mΩ ≤ m) le_rfl convert measurable_condDistrib (μ := μ) hs @@ -93,6 +106,7 @@ theorem stronglyMeasurable_condexpKernel {s : Set Ω} (hs : MeasurableSet s) : theorem _root_.MeasureTheory.AEStronglyMeasurable.integral_condexpKernel [NormedSpace ℝ F] (hf : AEStronglyMeasurable f μ) : AEStronglyMeasurable (fun ω => ∫ y, f y ∂condexpKernel μ m ω) μ := by + nontriviality Ω simp_rw [condexpKernel_apply_eq_condDistrib] exact AEStronglyMeasurable.integral_condDistrib (aemeasurable_id'' μ (inf_le_right : m ⊓ mΩ ≤ mΩ)) aemeasurable_id @@ -101,7 +115,8 @@ theorem _root_.MeasureTheory.AEStronglyMeasurable.integral_condexpKernel [Normed theorem aestronglyMeasurable'_integral_condexpKernel [NormedSpace ℝ F] (hf : AEStronglyMeasurable f μ) : AEStronglyMeasurable' m (fun ω => ∫ y, f y ∂condexpKernel μ m ω) μ := by - rw [condexpKernel] + nontriviality Ω + rw [condexpKernel_eq] have h := aestronglyMeasurable'_integral_condDistrib (aemeasurable_id'' μ (inf_le_right : m ⊓ mΩ ≤ mΩ)) aemeasurable_id (hf.comp_snd_map_prod_id (inf_le_right : m ⊓ mΩ ≤ mΩ)) @@ -116,14 +131,16 @@ variable [NormedAddCommGroup F] {f : Ω → F} theorem _root_.MeasureTheory.Integrable.condexpKernel_ae (hf_int : Integrable f μ) : ∀ᵐ ω ∂μ, Integrable f (condexpKernel μ m ω) := by - rw [condexpKernel] + nontriviality Ω + rw [condexpKernel_eq] convert Integrable.condDistrib_ae (aemeasurable_id'' μ (inf_le_right : m ⊓ mΩ ≤ mΩ)) aemeasurable_id (hf_int.comp_snd_map_prod_id (inf_le_right : m ⊓ mΩ ≤ mΩ)) using 1 theorem _root_.MeasureTheory.Integrable.integral_norm_condexpKernel (hf_int : Integrable f μ) : Integrable (fun ω => ∫ y, ‖f y‖ ∂condexpKernel μ m ω) μ := by - rw [condexpKernel] + nontriviality Ω + rw [condexpKernel_eq] convert Integrable.integral_norm_condDistrib (aemeasurable_id'' μ (inf_le_right : m ⊓ mΩ ≤ mΩ)) aemeasurable_id (hf_int.comp_snd_map_prod_id (inf_le_right : m ⊓ mΩ ≤ mΩ)) using 1 @@ -131,7 +148,8 @@ theorem _root_.MeasureTheory.Integrable.integral_norm_condexpKernel (hf_int : In theorem _root_.MeasureTheory.Integrable.norm_integral_condexpKernel [NormedSpace ℝ F] (hf_int : Integrable f μ) : Integrable (fun ω => ‖∫ y, f y ∂condexpKernel μ m ω‖) μ := by - rw [condexpKernel] + nontriviality Ω + rw [condexpKernel_eq] convert Integrable.norm_integral_condDistrib (aemeasurable_id'' μ (inf_le_right : m ⊓ mΩ ≤ mΩ)) aemeasurable_id (hf_int.comp_snd_map_prod_id (inf_le_right : m ⊓ mΩ ≤ mΩ)) using 1 @@ -139,20 +157,25 @@ theorem _root_.MeasureTheory.Integrable.norm_integral_condexpKernel [NormedSpace theorem _root_.MeasureTheory.Integrable.integral_condexpKernel [NormedSpace ℝ F] (hf_int : Integrable f μ) : Integrable (fun ω => ∫ y, f y ∂condexpKernel μ m ω) μ := by - rw [condexpKernel] + nontriviality Ω + rw [condexpKernel_eq] convert Integrable.integral_condDistrib (aemeasurable_id'' μ (inf_le_right : m ⊓ mΩ ≤ mΩ)) aemeasurable_id (hf_int.comp_snd_map_prod_id (inf_le_right : m ⊓ mΩ ≤ mΩ)) using 1 theorem integrable_toReal_condexpKernel {s : Set Ω} (hs : MeasurableSet s) : Integrable (fun ω => (condexpKernel μ m ω s).toReal) μ := by - rw [condexpKernel] + nontriviality Ω + rw [condexpKernel_eq] exact integrable_toReal_condDistrib (aemeasurable_id'' μ (inf_le_right : m ⊓ mΩ ≤ mΩ)) hs end Integrability lemma condexpKernel_ae_eq_condexp' {s : Set Ω} (hs : MeasurableSet s) : (fun ω ↦ (condexpKernel μ m ω s).toReal) =ᵐ[μ] μ⟦s | m ⊓ mΩ⟧ := by + rcases isEmpty_or_nonempty Ω with h | h + · have : μ = 0 := Measure.eq_zero_of_isEmpty μ + simpa [this] using trivial have h := condDistrib_ae_eq_condexp (μ := μ) (measurable_id'' (inf_le_right : m ⊓ mΩ ≤ mΩ)) measurable_id hs simp only [id_eq, MeasurableSpace.comap_id, preimage_id_eq] at h @@ -175,6 +198,9 @@ lemma condexpKernel_ae_eq_trim_condexp theorem condexp_ae_eq_integral_condexpKernel' [NormedAddCommGroup F] {f : Ω → F} [NormedSpace ℝ F] [CompleteSpace F] (hf_int : Integrable f μ) : μ[f|m ⊓ mΩ] =ᵐ[μ] fun ω => ∫ y, f y ∂condexpKernel μ m ω := by + rcases isEmpty_or_nonempty Ω with h | h + · have : μ = 0 := Measure.eq_zero_of_isEmpty μ + simpa [this] using trivial have hX : @Measurable Ω Ω mΩ (m ⊓ mΩ) id := measurable_id.mono le_rfl (inf_le_right : m ⊓ mΩ ≤ mΩ) simp_rw [condexpKernel_apply_eq_condDistrib] have h := condexp_ae_eq_integral_condDistrib_id hX hf_int diff --git a/Mathlib/Probability/Kernel/Disintegration/CDFToKernel.lean b/Mathlib/Probability/Kernel/Disintegration/CDFToKernel.lean index a27ba1c121a56..18005da5094fd 100644 --- a/Mathlib/Probability/Kernel/Disintegration/CDFToKernel.lean +++ b/Mathlib/Probability/Kernel/Disintegration/CDFToKernel.lean @@ -12,7 +12,7 @@ import Mathlib.Probability.Kernel.Disintegration.MeasurableStieltjes Let `κ : Kernel α (β × ℝ)` and `ν : Kernel α β` be two finite kernels. A function `f : α × β → StieltjesFunction` is called a conditional kernel CDF of `κ` with respect -to `ν` if it is measurable, tends to to 0 at -∞ and to 1 at +∞ for all `p : α × β`, +to `ν` if it is measurable, tends to 0 at -∞ and to 1 at +∞ for all `p : α × β`, `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`. @@ -24,7 +24,7 @@ denoted by `hf.toKernel f` such that `κ = ν ⊗ₖ hf.toKernel f`. Let `κ : Kernel α (β × ℝ)` and `ν : Kernel α β`. * `ProbabilityTheory.IsCondKernelCDF`: a function `f : α × β → StieltjesFunction` is called - a conditional kernel CDF of `κ` with respect to `ν` if it is measurable, tends to to 0 at -∞ and + a conditional kernel CDF of `κ` with respect to `ν` if it is measurable, tends to 0 at -∞ and to 1 at +∞ for all `p : α × β`, if `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`. @@ -147,7 +147,7 @@ lemma setLIntegral_stieltjesOfMeasurableRat [IsFiniteKernel κ] (hf : IsRatCondK · exact mod_cast ha.le · refine le_of_forall_lt_rat_imp_le fun q hq ↦ h q ?_ exact mod_cast hq - · exact fun _ ↦ measurableSet_Iic + · exact fun _ ↦ measurableSet_Iic.nullMeasurableSet · refine Monotone.directed_ge fun r r' hrr' ↦ Iic_subset_Iic.mpr ?_ exact mod_cast hrr' · obtain ⟨q, hq⟩ := exists_rat_gt x @@ -172,7 +172,7 @@ lemma setLIntegral_stieltjesOfMeasurableRat [IsFiniteKernel κ] (hf : IsRatCondK congr with y simp only [mem_iInter, mem_Iic, Subtype.forall, Subtype.coe_mk] exact ⟨le_of_forall_lt_rat_imp_le, fun hyx q hq ↦ hyx.trans hq.le⟩ - · exact fun i ↦ hs.prod measurableSet_Iic + · exact fun i ↦ (hs.prod measurableSet_Iic).nullMeasurableSet · refine Monotone.directed_ge fun i j hij ↦ ?_ refine prod_subset_prod_iff.mpr (Or.inl ⟨subset_rfl, Iic_subset_Iic.mpr ?_⟩) exact mod_cast hij @@ -355,7 +355,7 @@ lemma _root_.MeasureTheory.Measure.iInf_rat_gt_prod_Iic {ρ : Measure (α × ℝ · refine le_of_forall_lt_rat_imp_le fun q htq ↦ h q ?_ exact mod_cast htq · exact mod_cast hta.le - · exact fun _ => hs.prod measurableSet_Iic + · exact fun _ => (hs.prod measurableSet_Iic).nullMeasurableSet · refine Monotone.directed_ge fun r r' hrr' ↦ prod_subset_prod_iff.mpr (Or.inl ⟨subset_rfl, ?_⟩) refine Iic_subset_Iic.mpr ?_ exact mod_cast hrr' @@ -420,7 +420,7 @@ section IsCondKernelCDF variable {f : α × β → StieltjesFunction} /-- A function `f : α × β → StieltjesFunction` is called a conditional kernel CDF of `κ` with -respect to `ν` if it is measurable, tends to to 0 at -∞ and to 1 at +∞ for all `p : α × β`, +respect to `ν` if it is measurable, tends to 0 at -∞ and to 1 at +∞ for all `p : α × β`, `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 α β) : @@ -589,7 +589,7 @@ lemma setLIntegral_toKernel_prod [IsFiniteKernel κ] (hf : IsCondKernelCDF f κ _ = κ a (s ×ˢ univ) - κ a (s ×ˢ t) := by rw [setLIntegral_toKernel_univ hf a hs, ht_lintegral] _ = κ a (s ×ˢ tᶜ) := by - rw [← measure_diff _ (hs.prod ht) (measure_ne_top _ _)] + rw [← measure_diff _ (hs.prod ht).nullMeasurableSet (measure_ne_top _ _)] · rw [prod_diff_prod, compl_eq_univ_diff] simp only [diff_self, empty_prod, union_empty] · rw [prod_subset_prod_iff] diff --git a/Mathlib/Probability/Kernel/Disintegration/CondCDF.lean b/Mathlib/Probability/Kernel/Disintegration/CondCDF.lean index 0659092ade23a..4b5aac1603122 100644 --- a/Mathlib/Probability/Kernel/Disintegration/CondCDF.lean +++ b/Mathlib/Probability/Kernel/Disintegration/CondCDF.lean @@ -50,23 +50,18 @@ noncomputable def IicSnd (r : ℝ) : Measure α := theorem IicSnd_apply (r : ℝ) {s : Set α} (hs : MeasurableSet s) : ρ.IicSnd r s = ρ (s ×ˢ Iic r) := by - rw [IicSnd, fst_apply hs, - restrict_apply' (MeasurableSet.univ.prod (measurableSet_Iic : MeasurableSet (Iic r))), ← - prod_univ, prod_inter_prod, inter_univ, univ_inter] + rw [IicSnd, fst_apply hs, restrict_apply' (MeasurableSet.univ.prod measurableSet_Iic), + univ_prod, Set.prod_eq] theorem IicSnd_univ (r : ℝ) : ρ.IicSnd r univ = ρ (univ ×ˢ Iic r) := IicSnd_apply ρ r MeasurableSet.univ +@[gcongr] theorem IicSnd_mono {r r' : ℝ} (h_le : r ≤ r') : ρ.IicSnd r ≤ ρ.IicSnd r' := by - refine Measure.le_iff.2 fun s hs ↦ ?_ - simp_rw [IicSnd_apply ρ _ hs] - refine measure_mono (prod_subset_prod_iff.mpr (Or.inl ⟨subset_rfl, Iic_subset_Iic.mpr ?_⟩)) - exact mod_cast h_le + unfold IicSnd; gcongr -theorem IicSnd_le_fst (r : ℝ) : ρ.IicSnd r ≤ ρ.fst := by - refine Measure.le_iff.2 fun s hs ↦ ?_ - simp_rw [fst_apply hs, IicSnd_apply ρ r hs] - exact measure_mono (prod_subset_preimage_fst _ _) +theorem IicSnd_le_fst (r : ℝ) : ρ.IicSnd r ≤ ρ.fst := + fst_mono restrict_le_self theorem IicSnd_ac_fst (r : ℝ) : ρ.IicSnd r ≪ ρ.fst := Measure.absolutelyContinuous_of_le (IicSnd_le_fst ρ r) @@ -106,8 +101,9 @@ theorem tendsto_IicSnd_atBot [IsFiniteMeasure ρ] {s : Set α} (hs : MeasurableS simp_rw [neg_neg] rw [h_fun_eq] exact h_neg.comp tendsto_neg_atBot_atTop - refine tendsto_measure_iInter (fun q ↦ hs.prod measurableSet_Iic) ?_ ⟨0, measure_ne_top ρ _⟩ - refine fun q r hqr ↦ prod_subset_prod_iff.mpr (Or.inl ⟨subset_rfl, fun x hx ↦ ?_⟩) + refine tendsto_measure_iInter (fun q ↦ (hs.prod measurableSet_Iic).nullMeasurableSet) + ?_ ⟨0, measure_ne_top ρ _⟩ + refine fun q r hqr ↦ Set.prod_mono subset_rfl fun x hx ↦ ?_ simp only [Rat.cast_neg, mem_Iic] at hx ⊢ refine hx.trans (neg_le_neg ?_) exact mod_cast hqr @@ -126,7 +122,7 @@ attribute [local instance] MeasureTheory.Measure.IsFiniteMeasure.IicSnd We build towards the definition of `ProbabilityTheory.condCDF`. We first define `ProbabilityTheory.preCDF`, a function defined on `α × ℚ` with the properties of a cdf almost -everywhere. -/ +everywhere. -/ /-- `preCDF` is the Radon-Nikodym derivative of `ρ.IicSnd` with respect to `ρ.fst` at each `r : ℚ`. This function `ℚ → α → ℝ≥0∞` is such that for almost all `a : α`, the function `ℚ → ℝ≥0∞` diff --git a/Mathlib/Probability/Kernel/Disintegration/Density.lean b/Mathlib/Probability/Kernel/Disintegration/Density.lean index 8b2f314be1286..77a32c6fbfe53 100644 --- a/Mathlib/Probability/Kernel/Disintegration/Density.lean +++ b/Mathlib/Probability/Kernel/Disintegration/Density.lean @@ -385,7 +385,7 @@ lemma tendsto_densityProcess_atTop_empty_of_antitone (κ : Kernel α (γ × β)) ?_ ?_ ?_ · convert h rw [← prod_iInter, hseq_iInter] - · exact fun m ↦ MeasurableSet.prod (measurableSet_countablePartitionSet _ _) (hseq_meas m) + · exact fun m ↦ ((measurableSet_countablePartitionSet _ _).prod (hseq_meas m)).nullMeasurableSet · intro m m' hmm' simp only [le_eq_subset, prod_subset_prod_iff, subset_rfl, true_and] exact Or.inl <| hseq hmm' @@ -599,7 +599,7 @@ lemma setIntegral_density (hκν : fst κ ≤ ν) [IsFiniteKernel ν] have : Aᶜ ×ˢ s = univ ×ˢ s \ A ×ˢ s := by rw [prod_diff_prod, compl_eq_univ_diff] simp - rw [this, measure_diff (by intro x; simp) (hA.prod hs) (measure_ne_top (κ a) _), + rw [this, measure_diff (by intro; simp) (hA.prod hs).nullMeasurableSet (measure_ne_top (κ a) _), ENNReal.toReal_sub_of_le (measure_mono (by intro x; simp)) (measure_ne_top _ _)] rw [eq_tsub_iff_add_eq_of_le, add_comm] · exact h @@ -677,7 +677,7 @@ lemma tendsto_integral_density_of_antitone (hκν : fst κ ≤ ν) [IsFiniteKern · simp refine h_cont.tendsto.comp ?_ have h := tendsto_measure_iInter (s := fun m ↦ univ ×ˢ seq m) (μ := κ a) - (fun m ↦ MeasurableSet.univ.prod (hseq_meas m)) ?_ ?_ + (fun m ↦ (MeasurableSet.univ.prod (hseq_meas m)).nullMeasurableSet) ?_ ?_ rotate_left · intro n m hnm x; simp only [mem_prod, mem_univ, true_and]; exact fun h ↦ hseq hnm h · refine ⟨0, measure_ne_top _ _⟩ diff --git a/Mathlib/Probability/Kernel/Disintegration/Integral.lean b/Mathlib/Probability/Kernel/Disintegration/Integral.lean index 20389e93f27ce..f712bc83a22b8 100644 --- a/Mathlib/Probability/Kernel/Disintegration/Integral.lean +++ b/Mathlib/Probability/Kernel/Disintegration/Integral.lean @@ -187,7 +187,7 @@ lemma setLIntegral_condKernel (hf : Measurable f) {s : Set β} ∫⁻ b in s, ∫⁻ ω in t, f (b, ω) ∂(ρ.condKernel b) ∂ρ.fst = ∫⁻ x in s ×ˢ t, f x ∂ρ := by conv_rhs => rw [← ρ.disintegrate ρ.condKernel] - rw [setLIntegral_compProd hf hs ht] + rw [setLIntegral_compProd hf hs ht] @[deprecated (since := "2024-06-29")] alias set_lintegral_condKernel := setLIntegral_condKernel diff --git a/Mathlib/Probability/Kernel/Disintegration/StandardBorel.lean b/Mathlib/Probability/Kernel/Disintegration/StandardBorel.lean index 1659fdaec44bc..c9a1f8966a14e 100644 --- a/Mathlib/Probability/Kernel/Disintegration/StandardBorel.lean +++ b/Mathlib/Probability/Kernel/Disintegration/StandardBorel.lean @@ -234,22 +234,18 @@ instance instIsMarkovKernelBorelMarkovFromReal (η : Kernel α ℝ) [IsMarkovKer · rw [deterministic_apply] simp [(range_nonempty (embeddingReal Ω)).choose_spec] -/-- For `κ' := map κ (Prod.map (id : β → β) e) (measurable_id.prod_map he.measurable)`, the -hypothesis `hη` is `fst κ' ⊗ₖ η = κ'`. The conclusion of the lemma is -`fst κ ⊗ₖ borelMarkovFromReal Ω η = comapRight (fst κ' ⊗ₖ η) _`. -/ +/-- For `κ' := map κ (Prod.map (id : β → β) e)`, the hypothesis `hη` is `fst κ' ⊗ₖ η = κ'`. +The conclusion of the lemma is `fst κ ⊗ₖ borelMarkovFromReal Ω η = comapRight (fst κ' ⊗ₖ η) _`. -/ lemma compProd_fst_borelMarkovFromReal_eq_comapRight_compProd (κ : Kernel α (β × Ω)) [IsSFiniteKernel κ] (η : Kernel (α × β) ℝ) [IsSFiniteKernel η] - (hη : (fst (map κ (Prod.map (id : β → β) (embeddingReal Ω)) - (measurable_id.prod_map (measurableEmbedding_embeddingReal Ω).measurable))) ⊗ₖ η - = map κ (Prod.map (id : β → β) (embeddingReal Ω)) - (measurable_id.prod_map (measurableEmbedding_embeddingReal Ω).measurable)) : + (hη : (fst (map κ (Prod.map (id : β → β) (embeddingReal Ω)))) ⊗ₖ η + = map κ (Prod.map (id : β → β) (embeddingReal Ω))) : fst κ ⊗ₖ borelMarkovFromReal Ω η - = comapRight (fst (map κ (Prod.map (id : β → β) (embeddingReal Ω)) - (measurable_id.prod_map (measurableEmbedding_embeddingReal Ω).measurable)) ⊗ₖ η) + = comapRight (fst (map κ (Prod.map (id : β → β) (embeddingReal Ω))) ⊗ₖ η) (MeasurableEmbedding.id.prod_mk (measurableEmbedding_embeddingReal Ω)) := by let e := embeddingReal Ω let he := measurableEmbedding_embeddingReal Ω - let κ' := map κ (Prod.map (id : β → β) e) (measurable_id.prod_map he.measurable) + let κ' := map κ (Prod.map (id : β → β) e) have hη' : fst κ' ⊗ₖ η = κ' := hη have h_prod_embed : MeasurableEmbedding (Prod.map (id : β → β) e) := MeasurableEmbedding.id.prod_mk he @@ -258,7 +254,8 @@ lemma compProd_fst_borelMarkovFromReal_eq_comapRight_compProd have h_fst : fst κ' = fst κ := by ext a u unfold_let κ' - rw [fst_apply, map_apply, Measure.map_map measurable_fst h_prod_embed.measurable, fst_apply] + rw [fst_apply, map_apply _ (by fun_prop), + Measure.map_map measurable_fst h_prod_embed.measurable, fst_apply] congr rw [h_fst] ext a t ht : 2 @@ -268,7 +265,7 @@ lemma compProd_fst_borelMarkovFromReal_eq_comapRight_compProd rw [← h_fst] have h_compProd : κ' a (univ ×ˢ range e)ᶜ = 0 := by unfold_let κ' - rw [map_apply'] + rw [map_apply' _ (by fun_prop)] swap; · exact (MeasurableSet.univ.prod he.measurableSet_range).compl suffices Prod.map id e ⁻¹' (univ ×ˢ range e)ᶜ = ∅ by rw [this]; simp ext x @@ -286,26 +283,23 @@ lemma compProd_fst_borelMarkovFromReal_eq_comapRight_compProd rw [piecewise_apply, if_pos] exact ha -/-- For `κ' := map κ (Prod.map (id : β → β) e) (measurable_id.prod_map he.measurable)`, the -hypothesis `hη` is `fst κ' ⊗ₖ η = κ'`. With that hypothesis, -`fst κ ⊗ₖ borelMarkovFromReal κ η = κ`.-/ +/-- For `κ' := map κ (Prod.map (id : β → β) e)`, the hypothesis `hη` is `fst κ' ⊗ₖ η = κ'`. +With that hypothesis, `fst κ ⊗ₖ borelMarkovFromReal κ η = κ`.-/ lemma compProd_fst_borelMarkovFromReal (κ : Kernel α (β × Ω)) [IsSFiniteKernel κ] (η : Kernel (α × β) ℝ) [IsSFiniteKernel η] - (hη : (fst (map κ (Prod.map (id : β → β) (embeddingReal Ω)) - (measurable_id.prod_map (measurableEmbedding_embeddingReal Ω).measurable))) ⊗ₖ η - = map κ (Prod.map (id : β → β) (embeddingReal Ω)) - (measurable_id.prod_map (measurableEmbedding_embeddingReal Ω).measurable)) : + (hη : (fst (map κ (Prod.map (id : β → β) (embeddingReal Ω)))) ⊗ₖ η + = map κ (Prod.map (id : β → β) (embeddingReal Ω))) : fst κ ⊗ₖ borelMarkovFromReal Ω η = κ := by let e := embeddingReal Ω let he := measurableEmbedding_embeddingReal Ω - let κ' := map κ (Prod.map (id : β → β) e) (measurable_id.prod_map he.measurable) + let κ' := map κ (Prod.map (id : β → β) e) have hη' : fst κ' ⊗ₖ η = κ' := hη have h_prod_embed : MeasurableEmbedding (Prod.map (id : β → β) e) := MeasurableEmbedding.id.prod_mk he have : κ = comapRight κ' h_prod_embed := by ext c t : 2 unfold_let κ' - rw [comapRight_apply, map_apply, h_prod_embed.comap_map] + rw [comapRight_apply, map_apply _ (by fun_prop), h_prod_embed.comap_map] conv_rhs => rw [this, ← hη'] exact compProd_fst_borelMarkovFromReal_eq_comapRight_compProd κ η hη @@ -320,9 +314,7 @@ A conditional kernel for `κ : Kernel α (γ × Ω)` where `γ` is countably gen standard Borel. -/ noncomputable def condKernelBorel (κ : Kernel α (γ × Ω)) [IsFiniteKernel κ] : Kernel (α × γ) Ω := - let e := embeddingReal Ω - let he := measurableEmbedding_embeddingReal Ω - let κ' := map κ (Prod.map (id : γ → γ) e) (measurable_id.prod_map he.measurable) + let κ' := map κ (Prod.map (id : γ → γ) (embeddingReal Ω)) borelMarkovFromReal Ω (condKernelReal κ') instance instIsMarkovKernelCondKernelBorel (κ : Kernel α (γ × Ω)) [IsFiniteKernel κ] : @@ -349,9 +341,7 @@ variable (κ : Kernel Unit (α × Ω)) [IsFiniteKernel κ] A conditional kernel for `κ : Kernel Unit (α × Ω)` where `Ω` is standard Borel. -/ noncomputable def condKernelUnitBorel : Kernel (Unit × α) Ω := - let e := embeddingReal Ω - let he := measurableEmbedding_embeddingReal Ω - let κ' := map κ (Prod.map (id : α → α) e) (measurable_id.prod_map he.measurable) + let κ' := map κ (Prod.map (id : α → α) (embeddingReal Ω)) borelMarkovFromReal Ω (condKernelUnitReal κ') instance instIsMarkovKernelCondKernelUnitBorel : IsMarkovKernel κ.condKernelUnitBorel := by diff --git a/Mathlib/Probability/Kernel/Disintegration/Unique.lean b/Mathlib/Probability/Kernel/Disintegration/Unique.lean index a55d8224d6a44..e1b79719abfe1 100644 --- a/Mathlib/Probability/Kernel/Disintegration/Unique.lean +++ b/Mathlib/Probability/Kernel/Disintegration/Unique.lean @@ -91,35 +91,35 @@ theorem eq_condKernel_of_measure_eq_compProd (κ : Kernel α Ω) [IsFiniteKernel rw [hρ'def, Measure.fst_apply, Measure.fst_apply, Measure.map_apply] exacts [rfl, Measurable.prod measurable_fst <| hf.measurable.comp measurable_snd, measurable_fst hs, hs, hs] - have hρ'' : ∀ᵐ x ∂ρ.fst, Kernel.map κ f hf.measurable x = ρ'.condKernel x := by + have hρ'' : ∀ᵐ x ∂ρ.fst, Kernel.map κ f x = ρ'.condKernel x := by rw [← hρ'] - refine eq_condKernel_of_measure_eq_compProd_real (Kernel.map κ f hf.measurable) ?_ + refine eq_condKernel_of_measure_eq_compProd_real (Kernel.map κ f) ?_ ext s hs conv_lhs => rw [hρ'def, hκ] rw [Measure.map_apply (measurable_id.prod_map hf.measurable) hs, hρ', Measure.compProd_apply hs, Measure.compProd_apply (measurable_id.prod_map hf.measurable hs)] congr with a - rw [Kernel.map_apply'] + rw [Kernel.map_apply' _ hf.measurable] exacts [rfl, measurable_prod_mk_left hs] suffices ∀ᵐ x ∂ρ.fst, ∀ s, MeasurableSet s → ρ'.condKernel x s = ρ.condKernel x (f ⁻¹' s) by filter_upwards [hρ'', this] with x hx h - rw [Kernel.map_apply] at hx + rw [Kernel.map_apply _ hf.measurable] at hx ext s hs rw [← Set.preimage_image_eq s hf.injective, ← Measure.map_apply hf.measurable <| hf.measurableSet_image.2 hs, hx, h _ <| hf.measurableSet_image.2 hs] - suffices ρ.map (Prod.map id f) = (ρ.fst ⊗ₘ (Kernel.map ρ.condKernel f hf.measurable)) by + suffices ρ.map (Prod.map id f) = (ρ.fst ⊗ₘ (Kernel.map ρ.condKernel f)) by rw [← hρ'] at this have heq := eq_condKernel_of_measure_eq_compProd_real _ this rw [hρ'] at heq filter_upwards [heq] with x hx s hs - rw [← hx, Kernel.map_apply, Measure.map_apply hf.measurable hs] + rw [← hx, Kernel.map_apply _ hf.measurable, Measure.map_apply hf.measurable hs] ext s hs conv_lhs => rw [← ρ.disintegrate ρ.condKernel] rw [Measure.compProd_apply hs, Measure.map_apply (measurable_id.prod_map hf.measurable) hs, Measure.compProd_apply] · congr with a - rw [Kernel.map_apply'] + rw [Kernel.map_apply' _ hf.measurable] exacts [rfl, measurable_prod_mk_left hs] · exact measurable_id.prod_map hf.measurable hs diff --git a/Mathlib/Probability/Kernel/IntegralCompProd.lean b/Mathlib/Probability/Kernel/IntegralCompProd.lean index 6e080b423d194..a6cb2cd870a84 100644 --- a/Mathlib/Probability/Kernel/IntegralCompProd.lean +++ b/Mathlib/Probability/Kernel/IntegralCompProd.lean @@ -226,7 +226,7 @@ theorem integral_compProd : · simp [integral, hE] apply Integrable.induction · intro c s hs h2s - simp_rw [integral_indicator hs, ← indicator_comp_right, Function.comp, + simp_rw [integral_indicator hs, ← indicator_comp_right, Function.comp_def, integral_indicator (measurable_prod_mk_left hs), MeasureTheory.setIntegral_const, integral_smul_const] congr 1 @@ -249,7 +249,7 @@ theorem integral_compProd : theorem setIntegral_compProd {f : β × γ → E} {s : Set β} {t : Set γ} (hs : MeasurableSet s) (ht : MeasurableSet t) (hf : IntegrableOn f (s ×ˢ t) ((κ ⊗ₖ η) a)) : ∫ z in s ×ˢ t, f z ∂(κ ⊗ₖ η) a = ∫ x in s, ∫ y in t, f (x, y) ∂η (a, x) ∂κ a := by - -- Porting note: `compProd_restrict` needed some explicit argumnts + -- Porting note: `compProd_restrict` needed some explicit arguments rw [← Kernel.restrict_apply (κ ⊗ₖ η) (hs.prod ht), ← compProd_restrict hs ht, integral_compProd] · simp_rw [Kernel.restrict_apply] · rw [compProd_restrict, Kernel.restrict_apply]; exact hf diff --git a/Mathlib/Probability/Kernel/MeasurableIntegral.lean b/Mathlib/Probability/Kernel/MeasurableIntegral.lean index 6790cc25384d2..312093ef4376d 100644 --- a/Mathlib/Probability/Kernel/MeasurableIntegral.lean +++ b/Mathlib/Probability/Kernel/MeasurableIntegral.lean @@ -71,7 +71,7 @@ theorem measurable_kernel_prod_mk_left_of_finite {t : Set (α × β)} (ht : Meas κ a Set.univ - κ a (Prod.mk a ⁻¹' t') := by ext1 a rw [← Set.diff_inter_self_eq_diff, Set.inter_univ, measure_diff (Set.subset_univ _)] - · exact (@measurable_prod_mk_left α β _ _ a) ht' + · exact (measurable_prod_mk_left ht').nullMeasurableSet · exact measure_ne_top _ _ rw [this] exact Measurable.sub (Kernel.measurable_coe κ MeasurableSet.univ) h_meas diff --git a/Mathlib/Probability/Kernel/MeasureCompProd.lean b/Mathlib/Probability/Kernel/MeasureCompProd.lean index cce788e06190d..e3e4cb3a71c31 100644 --- a/Mathlib/Probability/Kernel/MeasureCompProd.lean +++ b/Mathlib/Probability/Kernel/MeasureCompProd.lean @@ -102,16 +102,14 @@ lemma ae_compProd_iff [SFinite μ] [IsSFiniteKernel κ] {p : α × β → Prop} lemma compProd_add_left (μ ν : Measure α) [SFinite μ] [SFinite ν] (κ : Kernel α β) : (μ + ν) ⊗ₘ κ = μ ⊗ₘ κ + ν ⊗ₘ κ := by by_cases hκ : IsSFiniteKernel κ - · rw [Measure.compProd, Kernel.const_add, Kernel.compProd_add_left] - rfl + · simp_rw [Measure.compProd, Kernel.const_add, Kernel.compProd_add_left, Kernel.add_apply] · simp [compProd_of_not_isSFiniteKernel _ _ hκ] lemma compProd_add_right (μ : Measure α) (κ η : Kernel α β) [IsSFiniteKernel κ] [IsSFiniteKernel η] : μ ⊗ₘ (κ + η) = μ ⊗ₘ κ + μ ⊗ₘ η := by by_cases hμ : SFinite μ - · rw [Measure.compProd, Kernel.prodMkLeft_add, Kernel.compProd_add_right] - rfl + · simp_rw [Measure.compProd, Kernel.prodMkLeft_add, Kernel.compProd_add_right, Kernel.add_apply] · simp [compProd_of_not_sfinite _ _ hμ] section Integral @@ -137,8 +135,8 @@ lemma integrable_compProd_iff [SFinite μ] [IsSFiniteKernel κ] {E : Type*} [Nor Integrable f (μ ⊗ₘ κ) ↔ (∀ᵐ x ∂μ, Integrable (fun y => f (x, y)) (κ x)) ∧ Integrable (fun x => ∫ y, ‖f (x, y)‖ ∂(κ x)) μ := by - rw [Measure.compProd, ProbabilityTheory.integrable_compProd_iff hf] - rfl + simp_rw [Measure.compProd, ProbabilityTheory.integrable_compProd_iff hf, Kernel.prodMkLeft_apply, + Kernel.const_apply] lemma integral_compProd [SFinite μ] [IsSFiniteKernel κ] {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] diff --git a/Mathlib/Probability/Kernel/RadonNikodym.lean b/Mathlib/Probability/Kernel/RadonNikodym.lean index 7f5426267ce77..d99f2e27d910e 100644 --- a/Mathlib/Probability/Kernel/RadonNikodym.lean +++ b/Mathlib/Probability/Kernel/RadonNikodym.lean @@ -69,9 +69,9 @@ Theorem 1.28 in [O. Kallenberg, Random Measures, Theory and Applications][kallen -/ -open MeasureTheory Set Filter +open MeasureTheory Set Filter ENNReal -open scoped NNReal ENNReal MeasureTheory Topology ProbabilityTheory +open scoped NNReal MeasureTheory Topology ProbabilityTheory namespace ProbabilityTheory.Kernel @@ -88,8 +88,7 @@ noncomputable def rnDerivAux (κ η : Kernel α γ) (a : α) (x : γ) : ℝ := if hα : Countable α then ((κ a).rnDeriv (η a) x).toReal else haveI := hαγ.countableOrCountablyGenerated.resolve_left hα - density (map κ (fun a ↦ (a, ())) - (@measurable_prod_mk_right γ Unit _ inferInstance _)) η a x univ + density (map κ (fun a ↦ (a, ()))) η a x univ lemma rnDerivAux_nonneg (hκη : κ ≤ η) {a : α} {x : γ} : 0 ≤ rnDerivAux κ η a x := by rw [rnDerivAux] @@ -144,7 +143,7 @@ lemma setLIntegral_rnDerivAux (κ η : Kernel α γ) [IsFiniteKernel κ] [IsFini rw [ENNReal.ofReal_toReal hx_lt.ne] · have := hαγ.countableOrCountablyGenerated.resolve_left hα rw [setLIntegral_density ((fst_map_id_prod _ measurable_const).trans_le h_le) _ - MeasurableSet.univ hs, map_apply' _ _ _ (hs.prod MeasurableSet.univ)] + MeasurableSet.univ hs, map_apply' _ (by fun_prop) _ (hs.prod MeasurableSet.univ)] congr with x simp @@ -157,8 +156,7 @@ lemma withDensity_rnDerivAux (κ η : Kernel α γ) [IsFiniteKernel κ] [IsFinit rw [Kernel.withDensity_apply'] swap · exact (measurable_rnDerivAux _ _).ennreal_ofReal - have : ∀ b, (Real.toNNReal b : ℝ≥0∞) = ENNReal.ofReal b := fun _ ↦ rfl - simp_rw [this] + simp_rw [ofNNReal_toNNReal] exact setLIntegral_rnDerivAux κ η a hs lemma withDensity_one_sub_rnDerivAux (κ η : Kernel α γ) [IsFiniteKernel κ] [IsFiniteKernel η] : @@ -217,11 +215,10 @@ lemma measurableSet_mutuallySingularSetSlice (κ η : Kernel α γ) (a : α) : lemma measure_mutuallySingularSetSlice (κ η : Kernel α γ) [IsFiniteKernel κ] [IsFiniteKernel η] (a : α) : η a (mutuallySingularSetSlice κ η a) = 0 := by - have h_coe : ∀ b, (Real.toNNReal b : ℝ≥0∞) = ENNReal.ofReal b := fun _ ↦ rfl suffices withDensity (κ + η) (fun a x ↦ Real.toNNReal (1 - rnDerivAux κ (κ + η) a x)) a {x | 1 ≤ rnDerivAux κ (κ + η) a x} = 0 by rwa [withDensity_one_sub_rnDerivAux κ η] at this - simp_rw [h_coe] + simp_rw [ofNNReal_toNNReal] rw [Kernel.withDensity_apply', lintegral_eq_zero_iff, EventuallyEq, ae_restrict_iff] rotate_left · exact (measurable_const.sub @@ -289,10 +286,9 @@ lemma measurable_singularPart_fun_right (κ η : Kernel α γ) (a : α) : lemma singularPart_compl_mutuallySingularSetSlice (κ η : Kernel α γ) [IsSFiniteKernel κ] [IsSFiniteKernel η] (a : α) : singularPart κ η a (mutuallySingularSetSlice κ η a)ᶜ = 0 := by - have h_coe : ∀ b, (Real.toNNReal b : ℝ≥0∞) = ENNReal.ofReal b := fun _ ↦ rfl rw [singularPart, Kernel.withDensity_apply', lintegral_eq_zero_iff, EventuallyEq, ae_restrict_iff] - all_goals simp_rw [h_coe] + all_goals simp_rw [ofNNReal_toNNReal] rotate_left · exact measurableSet_preimage (measurable_singularPart_fun_right κ η a) (measurableSet_singleton _) @@ -351,7 +347,6 @@ lemma withDensity_rnDeriv_of_subset_compl_mutuallySingularSetSlice [IsFiniteKernel κ] [IsFiniteKernel η] {a : α} {s : Set γ} (hsm : MeasurableSet s) (hs : s ⊆ (mutuallySingularSetSlice κ η a)ᶜ) : withDensity η (rnDeriv κ η) a s = κ a s := by - have h_coe : ∀ b, (Real.toNNReal b : ℝ≥0∞) = ENNReal.ofReal b := fun _ ↦ rfl have : withDensity η (rnDeriv κ η) = withDensity (withDensity (κ + η) (fun a x ↦ Real.toNNReal (1 - rnDerivAux κ (κ + η) a x))) (rnDeriv κ η) := by @@ -374,8 +369,8 @@ lemma withDensity_rnDeriv_of_subset_compl_mutuallySingularSetSlice ENNReal.ofReal (1 - rnDerivAux κ (κ + η) a x)) ∂(κ + η) a _ = ∫⁻ x in s, ENNReal.ofReal (rnDerivAux κ (κ + η) a x) ∂(κ + η) a := by refine setLIntegral_congr_fun hsm (ae_of_all _ fun x hx ↦ ?_) - rw [h_coe, ← ENNReal.ofReal_div_of_pos, div_eq_inv_mul, ← ENNReal.ofReal_mul, ← mul_assoc, - mul_inv_cancel₀, one_mul] + rw [ofNNReal_toNNReal, ← ENNReal.ofReal_div_of_pos, div_eq_inv_mul, ← ENNReal.ofReal_mul, + ← mul_assoc, mul_inv_cancel₀, one_mul] · rw [ne_eq, sub_eq_zero] exact (hs' x hx).ne' · simp [(hs' x hx).le] @@ -391,7 +386,7 @@ lemma mutuallySingular_singularPart (κ η : Kernel α γ) [IsFiniteKernel κ] [ measure_mutuallySingularSetSlice κ η a, singularPart_compl_mutuallySingularSetSlice κ η a⟩ /-- Lebesgue decomposition of a finite kernel `κ` with respect to another one `η`. -`κ` is the sum of an abolutely continuous part `withDensity η (rnDeriv κ η)` and a singular part +`κ` is the sum of an absolutely continuous part `withDensity η (rnDeriv κ η)` and a singular part `singularPart κ η`. -/ lemma rnDeriv_add_singularPart (κ η : Kernel α γ) [IsFiniteKernel κ] [IsFiniteKernel η] : withDensity η (rnDeriv κ η) + singularPart κ η = κ := by diff --git a/Mathlib/Probability/Kernel/WithDensity.lean b/Mathlib/Probability/Kernel/WithDensity.lean index 40aa1c46c8c20..a6d76ca32dd21 100644 --- a/Mathlib/Probability/Kernel/WithDensity.lean +++ b/Mathlib/Probability/Kernel/WithDensity.lean @@ -180,8 +180,8 @@ is finite. -/ theorem isFiniteKernel_withDensity_of_bounded (κ : Kernel α β) [IsFiniteKernel κ] {B : ℝ≥0∞} (hB_top : B ≠ ∞) (hf_B : ∀ a b, f a b ≤ B) : IsFiniteKernel (withDensity κ f) := by by_cases hf : Measurable (Function.uncurry f) - · exact ⟨⟨B * IsFiniteKernel.bound κ, ENNReal.mul_lt_top hB_top (IsFiniteKernel.bound_ne_top κ), - fun a => by + · exact ⟨⟨B * IsFiniteKernel.bound κ, ENNReal.mul_lt_top hB_top.lt_top + (IsFiniteKernel.bound_lt_top κ), fun a => by rw [Kernel.withDensity_apply' κ hf a Set.univ] calc ∫⁻ b in Set.univ, f a b ∂κ a ≤ ∫⁻ _ in Set.univ, B ∂κ a := lintegral_mono (hf_B a) diff --git a/Mathlib/Probability/Martingale/BorelCantelli.lean b/Mathlib/Probability/Martingale/BorelCantelli.lean index bf606fa145ff1..fffa57f7af53e 100644 --- a/Mathlib/Probability/Martingale/BorelCantelli.lean +++ b/Mathlib/Probability/Martingale/BorelCantelli.lean @@ -61,7 +61,7 @@ theorem leastGE_le {i : ℕ} {r : ℝ} (ω : Ω) : leastGE f r i ω ≤ i := -- The following four lemmas shows `leastGE` behaves like a stopped process. Ideally we should -- define `leastGE` as a stopping time and take its stopped process. However, we can't do that --- with our current definition since a stopping time takes only finite indicies. An upcomming +-- with our current definition since a stopping time takes only finite indices. An upcoming -- refactor should hopefully make it possible to have stopping times taking infinity as a value theorem leastGE_mono {n m : ℕ} (hnm : n ≤ m) (r : ℝ) (ω : Ω) : leastGE f r n ω ≤ leastGE f r m ω := hitting_mono hnm diff --git a/Mathlib/Probability/Martingale/Convergence.lean b/Mathlib/Probability/Martingale/Convergence.lean index 0757535ae6937..831ab2d4dae51 100644 --- a/Mathlib/Probability/Martingale/Convergence.lean +++ b/Mathlib/Probability/Martingale/Convergence.lean @@ -163,7 +163,7 @@ theorem Submartingale.upcrossings_ae_lt_top' [IsFiniteMeasure μ] (hf : Submarti · simp_rw [lintegral_add_right _ measurable_const, lintegral_const] exact add_le_add (hbdd _) le_rfl refine ne_of_lt (iSup_lt_iff.2 ⟨R + ‖a‖₊ * μ Set.univ, ENNReal.add_lt_top.2 - ⟨ENNReal.coe_lt_top, ENNReal.mul_lt_top ENNReal.coe_lt_top.ne (measure_ne_top _ _)⟩, + ⟨ENNReal.coe_lt_top, ENNReal.mul_lt_top ENNReal.coe_lt_top (measure_lt_top _ _)⟩, fun n => le_trans ?_ (hR' n)⟩) refine lintegral_mono fun ω => ?_ rw [ENNReal.ofReal_le_iff_le_toReal, ENNReal.coe_toReal, coe_nnnorm] @@ -269,12 +269,12 @@ $(f_n)_n$ is a martingale by the tower property for conditional expectations. Fu $(f_n)_n$ is uniformly integrable in the probability sense. Indeed, as a single function is uniformly integrable in the measure theory sense, for all $\epsilon > 0$, there exists some $\delta > 0$ such that for all measurable set $A$ with $\mu(A) < δ$, we have -$\mathbb{E}|h|\mathbf{1}_A < \epsilon$. So, since for sufficently large $\lambda$, by the Markov +$\mathbb{E}|h|\mathbf{1}_A < \epsilon$. So, since for sufficiently large $\lambda$, by the Markov inequality, we have for all $n$, $$ \mu(|f_n| \ge \lambda) \le \lambda^{-1}\mathbb{E}|f_n| \le \lambda^{-1}\mathbb|g| < \delta, $$ -we have for sufficently large $\lambda$, for all $n$, +we have for sufficiently large $\lambda$, for all $n$, $$ \mathbb{E}|f_n|\mathbf{1}_{|f_n| \ge \lambda} \le \mathbb|g|\mathbf{1}_{|f_n| \ge \lambda} < \epsilon, diff --git a/Mathlib/Probability/Martingale/OptionalStopping.lean b/Mathlib/Probability/Martingale/OptionalStopping.lean index 9ccbef6e43662..fee8f4ea1c1a3 100644 --- a/Mathlib/Probability/Martingale/OptionalStopping.lean +++ b/Mathlib/Probability/Martingale/OptionalStopping.lean @@ -130,7 +130,7 @@ theorem smul_le_stoppedValue_hitting [IsFiniteMeasure μ] (hsub : Submartingale we have `ε • μ {ε ≤ f* n} ≤ ∫ ω in {ε ≤ f* n}, f n` where `f* n ω = max_{k ≤ n}, f k ω`. In some literature, the Doob's maximal inequality refers to what we call Doob's Lp inequality -(which is a corollary of this lemma and will be proved in an upcomming PR). -/ +(which is a corollary of this lemma and will be proved in an upcoming PR). -/ theorem maximal_ineq [IsFiniteMeasure μ] (hsub : Submartingale f 𝒢 μ) (hnonneg : 0 ≤ f) {ε : ℝ≥0} (n : ℕ) : ε • μ {ω | (ε : ℝ) ≤ (range (n + 1)).sup' nonempty_range_succ fun k => f k ω} ≤ ENNReal.ofReal (∫ ω in {ω | (ε : ℝ) ≤ (range (n + 1)).sup' nonempty_range_succ fun k => f k ω}, diff --git a/Mathlib/Probability/Martingale/Upcrossing.lean b/Mathlib/Probability/Martingale/Upcrossing.lean index 148f91df06297..0d3e293008a55 100644 --- a/Mathlib/Probability/Martingale/Upcrossing.lean +++ b/Mathlib/Probability/Martingale/Upcrossing.lean @@ -430,7 +430,7 @@ theorem upperCrossingTime_lt_of_le_upcrossingsBefore (hN : 0 < N) (hab : a < b) theorem upperCrossingTime_eq_of_upcrossingsBefore_lt (hab : a < b) (hn : upcrossingsBefore a b f N ω < n) : upperCrossingTime a b f N n ω = N := by refine le_antisymm upperCrossingTime_le (not_lt.1 ?_) - convert not_mem_of_csSup_lt hn (upperCrossingTime_lt_bddAbove hab) + convert not_mem_of_csSup_lt hn (upperCrossingTime_lt_bddAbove hab) using 1 theorem upcrossingsBefore_le (f : ℕ → Ω → ℝ) (ω : Ω) (hab : a < b) : upcrossingsBefore a b f N ω ≤ N := by @@ -625,10 +625,7 @@ theorem crossing_pos_eq (hab : a < b) : have hf' (ω i) : (f i ω - a)⁺ ≤ 0 ↔ f i ω ≤ a := by rw [posPart_nonpos, sub_nonpos] induction' n with k ih · refine ⟨rfl, ?_⟩ - #adaptation_note /-- nightly-2024-03-16: simp was simp (config := { unfoldPartialApp := true }) only [lowerCrossingTime_zero, hitting, - Set.mem_Icc, Set.mem_Iic] -/ - simp (config := { unfoldPartialApp := true }) only [lowerCrossingTime_zero, hitting_def, Set.mem_Icc, Set.mem_Iic] ext ω split_ifs with h₁ h₂ h₂ diff --git a/Mathlib/Probability/Moments.lean b/Mathlib/Probability/Moments.lean index f50aedd37546c..9f39ce4a332a9 100644 --- a/Mathlib/Probability/Moments.lean +++ b/Mathlib/Probability/Moments.lean @@ -71,7 +71,9 @@ theorem centralMoment_one' [IsFiniteMeasure μ] (h_int : Integrable X μ) : simp only [sub_mul, integral_const, smul_eq_mul, one_mul] @[simp] -theorem centralMoment_one [IsProbabilityMeasure μ] : centralMoment X 1 μ = 0 := by +theorem centralMoment_one [IsZeroOrProbabilityMeasure μ] : centralMoment X 1 μ = 0 := by + rcases eq_zero_or_isProbabilityMeasure μ with rfl | h + · simp [centralMoment] by_cases h_int : Integrable X μ · rw [centralMoment_one' h_int] simp only [measure_univ, ENNReal.one_toReal, sub_self, zero_mul] @@ -141,12 +143,11 @@ theorem mgf_zero' : mgf X μ 0 = (μ Set.univ).toReal := by theorem mgf_zero [IsProbabilityMeasure μ] : mgf X μ 0 = 1 := by simp only [mgf_zero', measure_univ, ENNReal.one_toReal] -@[simp] theorem cgf_zero' : cgf X μ 0 = log (μ Set.univ).toReal := by simp only [cgf, mgf_zero'] --- @[simp] -- Porting note: `simp only` already proves this -theorem cgf_zero [IsProbabilityMeasure μ] : cgf X μ 0 = 0 := by - simp only [cgf_zero', measure_univ, ENNReal.one_toReal, log_one] +@[simp] +theorem cgf_zero [IsZeroOrProbabilityMeasure μ] : cgf X μ 0 = 0 := by + rcases eq_zero_or_isProbabilityMeasure μ with rfl | h <;> simp [cgf_zero'] theorem mgf_undef (hX : ¬Integrable (fun ω => exp (t * X ω)) μ) : mgf X μ t = 0 := by simp only [mgf, integral_undef hX] @@ -242,7 +243,7 @@ theorem IndepFun.integrable_exp_mul_add {X Y : Ω → ℝ} (h_indep : IndepFun X simp_rw [Pi.add_apply, mul_add, exp_add] exact (h_indep.exp_mul t t).integrable_mul h_int_X h_int_Y -theorem iIndepFun.integrable_exp_mul_sum [IsProbabilityMeasure μ] {X : ι → Ω → ℝ} +theorem iIndepFun.integrable_exp_mul_sum [IsFiniteMeasure μ] {X : ι → Ω → ℝ} (h_indep : iIndepFun (fun i => inferInstance) X μ) (h_meas : ∀ i, Measurable (X i)) {s : Finset ι} (h_int : ∀ i ∈ s, Integrable (fun ω => exp (t * X i ω)) μ) : Integrable (fun ω => exp (t * (∑ i ∈ s, X i) ω)) μ := by @@ -257,9 +258,10 @@ theorem iIndepFun.integrable_exp_mul_sum [IsProbabilityMeasure μ] {X : ι → refine IndepFun.integrable_exp_mul_add ?_ (h_int i (mem_insert_self _ _)) h_rec exact (h_indep.indepFun_finset_sum_of_not_mem h_meas hi_notin_s).symm -theorem iIndepFun.mgf_sum [IsProbabilityMeasure μ] {X : ι → Ω → ℝ} +theorem iIndepFun.mgf_sum {X : ι → Ω → ℝ} (h_indep : iIndepFun (fun i => inferInstance) X μ) (h_meas : ∀ i, Measurable (X i)) (s : Finset ι) : mgf (∑ i ∈ s, X i) μ t = ∏ i ∈ s, mgf (X i) μ t := by + have : IsProbabilityMeasure μ := h_indep.isProbabilityMeasure classical induction' s using Finset.induction_on with i s hi_notin_s h_rec h_int · simp only [sum_empty, mgf_zero_fun, measure_univ, ENNReal.one_toReal, prod_empty] @@ -270,10 +272,11 @@ theorem iIndepFun.mgf_sum [IsProbabilityMeasure μ] {X : ι → Ω → ℝ} (aestronglyMeasurable_exp_mul_sum fun i _ => h_int' i), h_rec, prod_insert hi_notin_s] -theorem iIndepFun.cgf_sum [IsProbabilityMeasure μ] {X : ι → Ω → ℝ} +theorem iIndepFun.cgf_sum {X : ι → Ω → ℝ} (h_indep : iIndepFun (fun i => inferInstance) X μ) (h_meas : ∀ i, Measurable (X i)) {s : Finset ι} (h_int : ∀ i ∈ s, Integrable (fun ω => exp (t * X i ω)) μ) : cgf (∑ i ∈ s, X i) μ t = ∑ i ∈ s, cgf (X i) μ t := by + have : IsProbabilityMeasure μ := h_indep.isProbabilityMeasure simp_rw [cgf] rw [← log_prod _ _ fun j hj => ?_] · rw [h_indep.mgf_sum h_meas] @@ -298,7 +301,7 @@ theorem measure_ge_le_exp_mul_mgf [IsFiniteMeasure μ] (ε : ℝ) (ht : 0 ≤ t) have : exp (t * ε) * (μ {ω | exp (t * ε) ≤ exp (t * X ω)}).toReal ≤ μ[fun ω => exp (t * X ω)] := mul_meas_ge_le_integral_of_nonneg (ae_of_all _ fun x => (exp_pos _).le) h_int _ - rwa [mul_comm (exp (t * ε))⁻¹, ← div_eq_mul_inv, le_div_iff' (exp_pos _)] + rwa [mul_comm (exp (t * ε))⁻¹, ← div_eq_mul_inv, le_div_iff₀' (exp_pos _)] _ = exp (-t * ε) * mgf X μ t := by rw [neg_mul, exp_neg]; rfl /-- **Chernoff bound** on the lower tail of a real random variable. -/ diff --git a/Mathlib/Probability/ProbabilityMassFunction/Constructions.lean b/Mathlib/Probability/ProbabilityMassFunction/Constructions.lean index 9b85c12e07cf7..9ae6765fb79bd 100644 --- a/Mathlib/Probability/ProbabilityMassFunction/Constructions.lean +++ b/Mathlib/Probability/ProbabilityMassFunction/Constructions.lean @@ -58,7 +58,7 @@ theorem bind_pure_comp : bind p (pure ∘ f) = map f p := rfl theorem map_id : map id p = p := bind_pure _ -theorem map_comp (g : β → γ) : (p.map f).map g = p.map (g ∘ f) := by simp [map, Function.comp] +theorem map_comp (g : β → γ) : (p.map f).map g = p.map (g ∘ f) := by simp [map, Function.comp_def] theorem pure_map (a : α) : (pure a).map f = pure (f a) := pure_bind _ _ @@ -72,7 +72,7 @@ theorem bind_map (p : PMF α) (f : α → β) (q : β → PMF γ) : (p.map f).bi @[simp] theorem map_const : p.map (Function.const α b) = pure b := by - simp only [map, Function.comp, bind_const, Function.const] + simp only [map, Function.comp_def, bind_const, Function.const] section Measure diff --git a/Mathlib/Probability/ProbabilityMassFunction/Integrals.lean b/Mathlib/Probability/ProbabilityMassFunction/Integrals.lean index ec731b0e0b14f..0803f711af0ab 100644 --- a/Mathlib/Probability/ProbabilityMassFunction/Integrals.lean +++ b/Mathlib/Probability/ProbabilityMassFunction/Integrals.lean @@ -35,7 +35,7 @@ theorem integral_eq_tsum (p : PMF α) (f : α → E) (hf : Integrable f p.toMeas congr with x; congr 2 apply PMF.toMeasure_apply_singleton p x (MeasurableSet.singleton _) _ = ∑' a, (p a).toReal • f a := - tsum_subtype_eq_of_support_subset <| by calc + tsum_subtype_eq_of_support_subset <| calc (fun a ↦ (p a).toReal • f a).support ⊆ (fun a ↦ (p a).toReal).support := Function.support_smul_subset_left _ _ _ ⊆ support p := fun x h1 h2 => h1 (by simp [h2]) diff --git a/Mathlib/Probability/Process/Stopping.lean b/Mathlib/Probability/Process/Stopping.lean index 23d8793910896..9d48460885ec5 100644 --- a/Mathlib/Probability/Process/Stopping.lean +++ b/Mathlib/Probability/Process/Stopping.lean @@ -704,7 +704,7 @@ variable [LinearOrder ι] /-- Given a map `u : ι → Ω → E`, the stopped process with respect to `τ` is `u i ω` if `i ≤ τ ω`, and `u (τ ω) ω` otherwise. -Intuitively, the stopped process stops evolving once the stopping time has occured. -/ +Intuitively, the stopped process stops evolving once the stopping time has occurred. -/ def stoppedProcess (u : ι → Ω → β) (τ : Ω → ι) : ι → Ω → β := fun i ω => u (min i (τ ω)) ω theorem stoppedProcess_eq_stoppedValue {u : ι → Ω → β} {τ : Ω → ι} : diff --git a/Mathlib/Probability/StrongLaw.lean b/Mathlib/Probability/StrongLaw.lean index 12a5969e58728..ec1e988d50e44 100644 --- a/Mathlib/Probability/StrongLaw.lean +++ b/Mathlib/Probability/StrongLaw.lean @@ -380,11 +380,11 @@ theorem strong_law_aux1 {c : ℝ} (c_one : 1 < c) {ε : ℝ} (εpos : 0 < ε) : ε * ⌊c ^ n⌋₊ := by /- Let `S n = ∑ i ∈ range n, Y i` where `Y i = truncation (X i) i`. We should show that `|S k - 𝔼[S k]| / k ≤ ε` along the sequence of powers of `c`. For this, we apply Borel-Cantelli: - it suffices to show that the converse probabilites are summable. From Chebyshev inequality, this - will follow from a variance control `∑' Var[S (c^i)] / (c^i)^2 < ∞`. This is checked in `I2` - using pairwise independence to expand the variance of the sum as the sum of the variances, + it suffices to show that the converse probabilities are summable. From Chebyshev inequality, + this will follow from a variance control `∑' Var[S (c^i)] / (c^i)^2 < ∞`. This is checked in + `I2` using pairwise independence to expand the variance of the sum as the sum of the variances, and then a straightforward but tedious computation (essentially boiling down to the fact that - the sum of `1/(c ^ i)^2` beyong a threshold `j` is comparable to `1/j^2`). + the sum of `1/(c ^ i)^2` beyond a threshold `j` is comparable to `1/j^2`). Note that we have written `c^i` in the above proof sketch, but rigorously one should put integer parts everywhere, making things more painful. We write `u i = ⌊c^i⌋₊` for brevity. -/ have c_pos : 0 < c := zero_lt_one.trans c_one @@ -602,9 +602,22 @@ 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 (X : ℕ → Ω → ℝ) (hint : Integrable (X 0)) +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 + -- 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 + 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 Ω) := + 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. let pos : ℝ → ℝ := fun x => max x 0 let neg : ℝ → ℝ := fun x => max (-x) 0 have posm : Measurable pos := measurable_id'.max measurable_const @@ -773,10 +786,20 @@ lemma strong_law_ae_of_measurable 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 +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 + -- 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 + 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 Ω) := + 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 @@ -799,7 +822,7 @@ end StrongLawVectorSpace section StrongLawLp -variable {Ω : Type*} [MeasureSpace Ω] [IsProbabilityMeasure (ℙ : Measure Ω)] +variable {Ω : Type*} [MeasureSpace Ω] {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] [CompleteSpace E] [MeasurableSpace E] [BorelSpace E] @@ -808,8 +831,23 @@ identically distributed random variables in Lᵖ, then `n⁻¹ • ∑ i ∈ ran 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 ℙ) + 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 + 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 + 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 + (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 => (hident i).aestronglyMeasurable_iff.2 hℒp.1 have hint : Integrable (X 0) ℙ := hℒp.integrable hp diff --git a/Mathlib/RepresentationTheory/Action/Basic.lean b/Mathlib/RepresentationTheory/Action/Basic.lean index 6002bcee80785..f52d5604cf170 100644 --- a/Mathlib/RepresentationTheory/Action/Basic.lean +++ b/Mathlib/RepresentationTheory/Action/Basic.lean @@ -5,7 +5,7 @@ Authors: Scott Morrison -/ import Mathlib.Algebra.Category.Grp.Basic import Mathlib.CategoryTheory.SingleObj -import Mathlib.CategoryTheory.Limits.FunctorCategory +import Mathlib.CategoryTheory.Limits.FunctorCategory.Basic import Mathlib.CategoryTheory.Limits.Preserves.Basic import Mathlib.CategoryTheory.Adjunction.Limits import Mathlib.CategoryTheory.Conj diff --git a/Mathlib/RepresentationTheory/Action/Monoidal.lean b/Mathlib/RepresentationTheory/Action/Monoidal.lean index 831b1acf591af..022783ffbf8d2 100644 --- a/Mathlib/RepresentationTheory/Action/Monoidal.lean +++ b/Mathlib/RepresentationTheory/Action/Monoidal.lean @@ -308,7 +308,7 @@ each factor. -/ @[simps!] noncomputable def diagonalSucc (G : Type u) [Monoid G] (n : ℕ) : diagonal G (n + 1) ≅ leftRegular G ⊗ diagonal G n := - mkIso (Equiv.piFinSuccAbove _ 0).toIso fun _ => rfl + mkIso (Fin.consEquiv _).symm.toIso fun _ => rfl end Action diff --git a/Mathlib/RepresentationTheory/FDRep.lean b/Mathlib/RepresentationTheory/FDRep.lean index be57941de8e9f..b45a965988b28 100644 --- a/Mathlib/RepresentationTheory/FDRep.lean +++ b/Mathlib/RepresentationTheory/FDRep.lean @@ -3,10 +3,11 @@ Copyright (c) 2022 Scott Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Morrison -/ -import Mathlib.RepresentationTheory.Rep import Mathlib.Algebra.Category.FGModuleCat.Limits +import Mathlib.CategoryTheory.Monoidal.Rigid.Braided import Mathlib.CategoryTheory.Preadditive.Schur import Mathlib.RepresentationTheory.Basic +import Mathlib.RepresentationTheory.Rep /-! # `FDRep k G` is the category of finite dimensional `k`-linear representations of `G`. @@ -27,12 +28,10 @@ We verify that `FDRep k G` is a `k`-linear monoidal category, and rigid when `G` `FDRep k G` has all finite limits. ## TODO -* `FDRep k G ≌ FullSubcategory (FiniteDimensional k)` -* Upgrade the right rigid structure to a rigid structure - (this just needs to be done for `FGModuleCat`). -* `FDRep k G` has all finite colimits. -* `FDRep k G` is abelian. -* `FDRep k G ≌ FGModuleCat (MonoidAlgebra k G)`. +* `FdRep k G ≌ FullSubcategory (FiniteDimensional k)` +* `FdRep k G` has all finite colimits. +* `FdRep k G` is abelian. +* `FdRep k G ≌ FGModuleCat (MonoidAlgebra k G)`. -/ @@ -119,7 +118,7 @@ open FiniteDimensional open scoped Classical --- We need to provide this instance explicitely as otherwise `finrank_hom_simple_simple` gives a +-- We need to provide this instance explicitly as otherwise `finrank_hom_simple_simple` gives a -- deterministic timeout. instance : HasKernels (FDRep k G) := by infer_instance @@ -150,6 +149,8 @@ variable {k G : Type u} [Field k] [Group G] noncomputable instance : RightRigidCategory (FDRep k G) := by change RightRigidCategory (Action (FGModuleCat k) (Grp.of G)); infer_instance +example : RigidCategory (FDRep k G) := by infer_instance + end FDRep namespace FDRep diff --git a/Mathlib/RepresentationTheory/GroupCohomology/Hilbert90.lean b/Mathlib/RepresentationTheory/GroupCohomology/Hilbert90.lean index 222ef95b2b79e..b666cf6409176 100644 --- a/Mathlib/RepresentationTheory/GroupCohomology/Hilbert90.lean +++ b/Mathlib/RepresentationTheory/GroupCohomology/Hilbert90.lean @@ -55,7 +55,7 @@ variable {K L : Type*} [Field K] [Field L] [Algebra K L] [FiniteDimensional K L] /-- Given `f : Aut_K(L) → Lˣ`, the sum `∑ f(φ) • φ` for `φ ∈ Aut_K(L)`, as a function `L → L`. -/ noncomputable def aux (f : (L ≃ₐ[K] L) → Lˣ) : L → L := - Finsupp.total (L ≃ₐ[K] L) (L → L) L (fun φ => φ) + Finsupp.linearCombination L (fun φ : L ≃ₐ[K] L ↦ (φ : L → L)) (Finsupp.equivFunOnFinite.symm (fun φ => (f φ : L))) theorem aux_ne_zero (f : (L ≃ₐ[K] L) → Lˣ) : aux f ≠ 0 := @@ -83,7 +83,7 @@ theorem isMulOneCoboundary_of_isMulOneCocycle_of_aut_to_units /- Let `z : L` be such that `∑ f(h) * h(z) ≠ 0`, for `h ∈ Aut_K(L)` -/ obtain ⟨z, hz⟩ : ∃ z, aux f z ≠ 0 := not_forall.1 (fun H => aux_ne_zero f <| funext <| fun x => H x) - have : aux f z = ∑ h, f h * h z := by simp [aux, Finsupp.total, Finsupp.sum_fintype] + have : aux f z = ∑ h, f h * h z := by simp [aux, Finsupp.linearCombination, Finsupp.sum_fintype] /- Let `β = (∑ f(h) * h(z))⁻¹.` -/ use (Units.mk0 (aux f z) hz)⁻¹ intro g diff --git a/Mathlib/RepresentationTheory/GroupCohomology/LowDegree.lean b/Mathlib/RepresentationTheory/GroupCohomology/LowDegree.lean index c0689ba27a5a7..fbe67ec9e3438 100644 --- a/Mathlib/RepresentationTheory/GroupCohomology/LowDegree.lean +++ b/Mathlib/RepresentationTheory/GroupCohomology/LowDegree.lean @@ -39,7 +39,7 @@ The file also contains an identification between the definitions in 1-coboundaries (i.e. `B¹(G, A) := Im(d⁰: A → Fun(G, A))`). * `groupCohomology.H2 A`: 2-cocycles (i.e. `Z²(G, A) := Ker(d² : Fun(G², A) → Fun(G³, A)`) modulo 2-coboundaries (i.e. `B²(G, A) := Im(d¹: Fun(G, A) → Fun(G², A))`). -* `groupCohomology.H1LequivOfIsTrivial`: the isomorphism `H¹(G, A) ≃ Hom(G, A)` when the +* `groupCohomology.H1LequivOfIsTrivial`: the isomorphism `H¹(G, A) ≃ Hom(G, A)` when the representation on `A` is trivial. * `groupCohomology.isoHn` for `n = 0, 1, 2`: an isomorphism `groupCohomology A n ≅ groupCohomology.Hn A`. @@ -82,7 +82,7 @@ def twoCochainsLequiv : (inhomogeneousCochains A).X 2 ≃ₗ[k] G × G → A := /-- The 3rd object in the complex of inhomogeneous cochains of `A : Rep k G` is isomorphic to `Fun(G³, A)` as a `k`-module. -/ def threeCochainsLequiv : (inhomogeneousCochains A).X 3 ≃ₗ[k] G × G × G → A := - LinearEquiv.funCongrLeft k A <| ((Equiv.piFinSucc 2 G).trans + LinearEquiv.funCongrLeft k A <| ((Fin.consEquiv _).symm.trans ((Equiv.refl G).prodCongr (piFinTwoEquiv fun _ => G))).symm end Cochains @@ -337,7 +337,7 @@ theorem oneCoboundaries_of_mem_range_apply {f : G → A} (h : f ∈ LinearMap.ra `ρ(g)(x) - x = f(g)` for all `g : G`. -/ def oneCoboundariesOfEq {f : G → A} {x : A} (hf : ∀ g, A.ρ g x - x = f g) : oneCoboundaries A := - oneCoboundariesOfMemRange ⟨x, by ext g; exact hf g⟩ + oneCoboundariesOfMemRange ⟨x, funext hf⟩ theorem oneCoboundariesOfEq_apply {f : G → A} {x : A} (hf : ∀ g, A.ρ g x - x = f g) : (oneCoboundariesOfEq hf).1.1 = f := rfl @@ -365,7 +365,7 @@ theorem twoCoboundariesOfMemRange_apply {f : G × G → A} (h : f ∈ LinearMap. def twoCoboundariesOfEq {f : G × G → A} {x : G → A} (hf : ∀ g h, A.ρ g (x h) - x (g * h) + x g = f (g, h)) : twoCoboundaries A := - twoCoboundariesOfMemRange ⟨x, by ext g; exact hf g.1 g.2⟩ + twoCoboundariesOfMemRange ⟨x, funext fun g ↦ hf g.1 g.2⟩ theorem twoCoboundariesOfEq_apply {f : G × G → A} {x : G → A} (hf : ∀ g h, A.ρ g (x h) - x (g * h) + x g = f (g, h)) : @@ -465,7 +465,7 @@ theorem isOneCocycle_of_oneCocycles (f : oneCocycles (Rep.ofDistribMulAction k G on `A` induced by the `DistribMulAction`. -/ def oneCoboundariesOfIsOneCoboundary {f : G → A} (hf : IsOneCoboundary f) : oneCoboundaries (Rep.ofDistribMulAction k G A) := - oneCoboundariesOfMemRange (by rcases hf with ⟨x, hx⟩; exact ⟨x, by ext g; exact hx g⟩) + oneCoboundariesOfMemRange ⟨hf.choose, funext hf.choose_spec⟩ theorem isOneCoboundary_of_oneCoboundaries (f : oneCoboundaries (Rep.ofDistribMulAction k G A)) : IsOneCoboundary (A := A) f.1.1 := by @@ -487,7 +487,7 @@ theorem isTwoCocycle_of_twoCocycles (f : twoCocycles (Rep.ofDistribMulAction k G representation on `A` induced by the `DistribMulAction`. -/ def twoCoboundariesOfIsTwoCoboundary {f : G × G → A} (hf : IsTwoCoboundary f) : twoCoboundaries (Rep.ofDistribMulAction k G A) := - twoCoboundariesOfMemRange (by rcases hf with ⟨x, hx⟩; exact ⟨x, by ext g; exact hx g.1 g.2⟩) + twoCoboundariesOfMemRange (⟨hf.choose,funext fun g ↦ hf.choose_spec g.1 g.2⟩) theorem isTwoCoboundary_of_twoCoboundaries (f : twoCoboundaries (Rep.ofDistribMulAction k G A)) : IsTwoCoboundary (A := A) f.1.1 := by @@ -588,8 +588,7 @@ theorem isMulOneCocycle_of_oneCocycles (f : oneCocycles (Rep.ofMulDistribMulActi 1-coboundary for the representation on `Additive M` induced by the `MulDistribMulAction`. -/ def oneCoboundariesOfIsMulOneCoboundary {f : G → M} (hf : IsMulOneCoboundary f) : oneCoboundaries (Rep.ofMulDistribMulAction G M) := - oneCoboundariesOfMemRange (f := Additive.ofMul ∘ f) - (by rcases hf with ⟨x, hx⟩; exact ⟨x, by ext g; exact hx g⟩) + oneCoboundariesOfMemRange (f := Additive.ofMul ∘ f) ⟨hf.choose, funext hf.choose_spec⟩ theorem isMulOneCoboundary_of_oneCoboundaries (f : oneCoboundaries (Rep.ofMulDistribMulAction G M)) : @@ -612,7 +611,7 @@ theorem isMulTwoCocycle_of_twoCocycles (f : twoCocycles (Rep.ofMulDistribMulActi 2-coboundary for the representation on `M` induced by the `MulDistribMulAction`. -/ def twoCoboundariesOfIsMulTwoCoboundary {f : G × G → M} (hf : IsMulTwoCoboundary f) : twoCoboundaries (Rep.ofMulDistribMulAction G M) := - twoCoboundariesOfMemRange (by rcases hf with ⟨x, hx⟩; exact ⟨x, by ext g; exact hx g.1 g.2⟩) + twoCoboundariesOfMemRange ⟨hf.choose, funext fun g ↦ hf.choose_spec g.1 g.2⟩ theorem isMulTwoCoboundary_of_twoCoboundaries (f : twoCoboundaries (Rep.ofMulDistribMulAction G M)) : diff --git a/Mathlib/RepresentationTheory/GroupCohomology/Resolution.lean b/Mathlib/RepresentationTheory/GroupCohomology/Resolution.lean index e1fdb9f4e2b18..c225b3a938bec 100644 --- a/Mathlib/RepresentationTheory/GroupCohomology/Resolution.lean +++ b/Mathlib/RepresentationTheory/GroupCohomology/Resolution.lean @@ -68,7 +68,7 @@ universe u v w variable {k G : Type u} [CommRing k] {n : ℕ} -open CategoryTheory +open CategoryTheory Finsupp local notation "Gⁿ" => Fin n → G @@ -102,7 +102,7 @@ def actionDiagonalSucc (G : Type u) [Group G] : tensorIso (Iso.refl _) (actionDiagonalSucc G n) ≪≫ leftRegularTensorIso _ _ ≪≫ tensorIso (Iso.refl _) - (mkIso (Equiv.piFinSuccAbove (fun _ => G) 0).symm.toIso fun _ => rfl) + (mkIso (Fin.insertNthEquiv (fun _ => G) 0).toIso fun _ => rfl) theorem actionDiagonalSucc_hom_apply {G : Type u} [Group G] {n : ℕ} (f : Fin (n + 1) → G) : (actionDiagonalSucc G n).hom.hom f = (f 0, fun i => (f (Fin.castSucc i))⁻¹ * f i.succ) := by @@ -143,7 +143,7 @@ theorem actionDiagonalSucc_inv_apply {G : Type u} [Group G] {n : ℕ} (g : G) (f simpa only [Fin.cons_succ, Pi.smul_apply, smul_eq_mul, Fin.partialProd_succ', mul_assoc] -/ funext x dsimp [actionDiagonalSucc] - erw [hn, Equiv.piFinSuccAbove_symm_apply] + erw [hn, Fin.consEquiv_apply] refine Fin.cases ?_ (fun i => ?_) x · simp only [Fin.insertNth_zero, Fin.cons_zero, Fin.partialProd_zero, mul_one] · simp only [Fin.cons_succ, Pi.smul_apply, smul_eq_mul, Fin.partialProd_succ', ← mul_assoc] @@ -565,12 +565,12 @@ def forget₂ToModuleCatHomotopyEquiv : /-- The hom of `k`-linear `G`-representations `k[G¹] → k` sending `∑ nᵢgᵢ ↦ ∑ nᵢ`. -/ def ε : Rep.ofMulAction k G (Fin 1 → G) ⟶ Rep.trivial k G k where - hom := Finsupp.total _ _ _ fun _ => (1 : k) + hom := Finsupp.linearCombination _ fun _ => (1 : k) comm g := Finsupp.lhom_ext' fun _ => LinearMap.ext_ring (by show - Finsupp.total (Fin 1 → G) k k (fun _ => (1 : k)) (Finsupp.mapDomain _ (Finsupp.single _ _)) = - Finsupp.total (Fin 1 → G) k k (fun _ => (1 : k)) (Finsupp.single _ _) - simp only [Finsupp.mapDomain_single, Finsupp.total_single]) + Finsupp.linearCombination k (fun _ => (1 : k)) (Finsupp.mapDomain _ (Finsupp.single _ _)) = + Finsupp.linearCombination k (fun _ => (1 : k)) (Finsupp.single _ _) + simp only [Finsupp.mapDomain_single, Finsupp.linearCombination_single]) /-- The homotopy equivalence of complexes of `k`-modules between the standard resolution of `k` as a trivial `G`-representation, and the complex which is `k` at 0 and 0 everywhere else, acts as @@ -583,9 +583,9 @@ theorem forget₂ToModuleCatHomotopyEquiv_f_0_eq : convert Category.id_comp (X := (forget₂ToModuleCat k G).X 0) _ · dsimp only [HomotopyEquiv.ofIso, compForgetAugmentedIso] simp only [Iso.symm_hom, eqToIso.inv, HomologicalComplex.eqToHom_f, eqToHom_refl] - trans (Finsupp.total _ _ _ fun _ => (1 : k)).comp ((ModuleCat.free k).map (terminal.from _)) + trans (linearCombination _ fun _ => (1 : k)).comp ((ModuleCat.free k).map (terminal.from _)) · dsimp - erw [Finsupp.lmapDomain_total (α := Fin 1 → G) (R := k) (α' := ⊤_ Type u) + erw [Finsupp.lmapDomain_linearCombination (α := Fin 1 → G) (R := k) (α' := ⊤_ Type u) (v := fun _ => (1 : k)) (v' := fun _ => (1 : k)) (terminal.from ((classifyingSpaceUniversalCover G).obj (Opposite.op (SimplexCategory.mk 0))).V) @@ -596,7 +596,8 @@ theorem forget₂ToModuleCatHomotopyEquiv_f_0_eq : · ext x dsimp (config := { unfoldPartialApp := true }) [HomotopyEquiv.ofIso, Finsupp.LinearEquiv.finsuppUnique] - rw [Finsupp.total_single, one_smul, @Unique.eq_default _ Types.terminalIso.toEquiv.unique x, + rw [linearCombination_single, one_smul, + @Unique.eq_default _ Types.terminalIso.toEquiv.unique x, ChainComplex.single₀_map_f_zero, LinearMap.coe_mk, AddHom.coe_mk, Function.comp_apply, Finsupp.equivFunOnFinite_apply, Finsupp.single_eq_same] · exact @Subsingleton.elim _ (@Unique.instSubsingleton _ (Limits.uniqueToTerminal _)) _ _ diff --git a/Mathlib/RingTheory/AdicCompletion/Basic.lean b/Mathlib/RingTheory/AdicCompletion/Basic.lean index b1a5ab9bf4f6c..a680f5898fdf6 100644 --- a/Mathlib/RingTheory/AdicCompletion/Basic.lean +++ b/Mathlib/RingTheory/AdicCompletion/Basic.lean @@ -555,7 +555,7 @@ theorem le_jacobson_bot [IsAdicComplete I R] : I ≤ (⊥ : Ideal R).jacobson := ring cases n · simp only [Ideal.one_eq_top, pow_zero, mem_top] - · rw [← neg_sub _ (1 : R), neg_mul, mul_geom_sum, neg_sub, sub_sub, add_comm, ← sub_sub, + · rw [← neg_sub _ (1 : R), neg_mul, mul_geom_sum, neg_sub, sub_sub, add_comm (_ ^ _), ← sub_sub, sub_self, zero_sub, @neg_mem_iff, mul_pow] exact Ideal.mul_mem_right _ (I ^ _) (Ideal.pow_mem_pow hx _) diff --git a/Mathlib/RingTheory/AdicCompletion/Exactness.lean b/Mathlib/RingTheory/AdicCompletion/Exactness.lean index 347ac711c8b05..c184632614480 100644 --- a/Mathlib/RingTheory/AdicCompletion/Exactness.lean +++ b/Mathlib/RingTheory/AdicCompletion/Exactness.lean @@ -39,14 +39,13 @@ section Surjectivity variable {M : Type v} [AddCommGroup M] [Module R M] variable {N : Type w} [AddCommGroup N] [Module R N] -variable {f : M →ₗ[R] N} (hf : Function.Surjective f) -include hf +variable {f : M →ₗ[R] N} /- In each step, a preimage is constructed from the preimage of the previous step by subtracting this delta. -/ -private noncomputable def mapPreimageDelta (x : AdicCauchySequence I N) +private noncomputable def mapPreimageDelta (hf : Function.Surjective f) (x : AdicCauchySequence I N) {n : ℕ} {y yₙ : M} (hy : f y = x (n + 1)) (hyₙ : f yₙ = x n) : - { d : (I ^ n • ⊤ : Submodule R M) | f d = f (yₙ - y) } := + {d : (I ^ n • ⊤ : Submodule R M) | f d = f (yₙ - y) } := have h : f (yₙ - y) ∈ Submodule.map f (I ^ n • ⊤ : Submodule R M) := by rw [Submodule.map_smul'', Submodule.map_top, LinearMap.range_eq_top.mpr hf, map_sub, hyₙ, hy, ← Submodule.neg_mem_iff, neg_sub, ← SModEq.sub_mem] @@ -54,20 +53,19 @@ private noncomputable def mapPreimageDelta (x : AdicCauchySequence I N) ⟨⟨h.choose, h.choose_spec.1⟩, h.choose_spec.2⟩ /- Inductively construct preimage of cauchy sequence. -/ -private noncomputable def mapPreimage (x : AdicCauchySequence I N) : +private noncomputable def mapPreimage (hf : Function.Surjective f) (x : AdicCauchySequence I N) : (n : ℕ) → f ⁻¹' {x n} | .zero => ⟨(hf (x 0)).choose, (hf (x 0)).choose_spec⟩ | .succ n => let y := (hf (x (n + 1))).choose have hy := (hf (x (n + 1))).choose_spec - let ⟨yₙ, (hyₙ : f yₙ = x n)⟩ := mapPreimage x n + let ⟨yₙ, (hyₙ : f yₙ = x n)⟩ := mapPreimage hf x n let ⟨⟨d, _⟩, (p : f d = f (yₙ - y))⟩ := mapPreimageDelta hf x hy hyₙ ⟨yₙ - d, by simpa [p]⟩ -variable (I) - +variable (I) in /-- Adic completion preserves surjectivity -/ -theorem map_surjective : Function.Surjective (map I f) := fun y ↦ by +theorem map_surjective (hf : Function.Surjective f) : Function.Surjective (map I f) := fun y ↦ by apply AdicCompletion.induction_on I N y (fun b ↦ ?_) let a := mapPreimage hf b refine ⟨AdicCompletion.mk I M (AdicCauchySequence.mk I M (fun n ↦ (a n : M)) ?_), ?_⟩ @@ -100,7 +98,7 @@ theorem map_injective {f : M →ₗ[R] N} (hf : Function.Injective f) : rw [← Submodule.comap_map_eq_of_injective hf (I ^ n • ⊤ : Submodule R M), Submodule.map_smul'', Submodule.map_top] apply (smul_mono_right _ inf_le_right : I ^ n • (I ^ k • ⊤ ⊓ (range f)) ≤ _) - nth_rw 2 [show n = n + k - k by omega] + nth_rw 1 [show n = n + k - k by omega] rw [← hk (n + k) (show n + k ≥ k by omega)] exact ⟨by simpa using congrArg (fun x ↦ x.val (n + k)) hx, ⟨a (n + k), rfl⟩⟩ diff --git a/Mathlib/RingTheory/Adjoin/Basic.lean b/Mathlib/RingTheory/Adjoin/Basic.lean index 2e497804ccf8a..83e58942dce2b 100644 --- a/Mathlib/RingTheory/Adjoin/Basic.lean +++ b/Mathlib/RingTheory/Adjoin/Basic.lean @@ -251,7 +251,7 @@ theorem adjoin_inl_union_inr_eq_prod (s) (t) : simpa [P] using Subalgebra.add_mem _ Ha Hb /-- If all elements of `s : Set A` commute pairwise, then `adjoin R s` is a commutative -semiring. -/ +semiring. -/ def adjoinCommSemiringOfComm {s : Set A} (hcomm : ∀ a ∈ s, ∀ b ∈ s, a * b = b * a) : CommSemiring (adjoin R s) := { (adjoin R s).toSemiring with @@ -355,7 +355,7 @@ theorem pow_smul_mem_of_smul_subset_of_mem_adjoin [CommSemiring B] [Algebra R B] [IsScalarTower R A B] (r : A) (s : Set B) (B' : Subalgebra R B) (hs : r • s ⊆ B') {x : B} (hx : x ∈ adjoin R s) (hr : algebraMap A B r ∈ B') : ∃ n₀ : ℕ, ∀ n ≥ n₀, r ^ n • x ∈ B' := by change x ∈ Subalgebra.toSubmodule (adjoin R s) at hx - rw [adjoin_eq_span, Finsupp.mem_span_iff_total] at hx + rw [adjoin_eq_span, Finsupp.mem_span_iff_linearCombination] at hx rcases hx with ⟨l, rfl : (l.sum fun (i : Submonoid.closure s) (c : R) => c • (i : B)) = x⟩ choose n₁ n₂ using fun x : Submonoid.closure s => Submonoid.pow_smul_mem_closure_smul r s x.prop use l.support.sup n₁ @@ -403,7 +403,7 @@ theorem adjoin_eq_ring_closure (s : Set A) : variable (R) /-- If all elements of `s : Set A` commute pairwise, then `adjoin R s` is a commutative -ring. -/ +ring. -/ def adjoinCommRingOfComm {s : Set A} (hcomm : ∀ a ∈ s, ∀ b ∈ s, a * b = b * a) : CommRing (adjoin R s) := { (adjoin R s).toRing, adjoinCommSemiringOfComm R hcomm with } diff --git a/Mathlib/RingTheory/Adjoin/FG.lean b/Mathlib/RingTheory/Adjoin/FG.lean index eae1117ae1555..1256cc4e9a973 100644 --- a/Mathlib/RingTheory/Adjoin/FG.lean +++ b/Mathlib/RingTheory/Adjoin/FG.lean @@ -58,17 +58,17 @@ theorem fg_trans (h1 : (adjoin R s).toSubmodule.FG) (h2 : (adjoin (adjoin R s) t change r ∈ adjoin R (s ∪ t) at hr rw [adjoin_union_eq_adjoin_adjoin] at hr change r ∈ Subalgebra.toSubmodule (adjoin (adjoin R s) t) at hr - rw [← hq', ← Set.image_id q, Finsupp.mem_span_image_iff_total (adjoin R s)] at hr + rw [← hq', ← Set.image_id q, Finsupp.mem_span_image_iff_linearCombination (adjoin R s)] at hr rcases hr with ⟨l, hlq, rfl⟩ - have := @Finsupp.total_apply A A (adjoin R s) + have := @Finsupp.linearCombination_apply A A (adjoin R s) rw [this, Finsupp.sum] refine sum_mem ?_ intro z hz change (l z).1 * _ ∈ _ have : (l z).1 ∈ Subalgebra.toSubmodule (adjoin R s) := (l z).2 - rw [← hp', ← Set.image_id p, Finsupp.mem_span_image_iff_total R] at this + rw [← hp', ← Set.image_id p, Finsupp.mem_span_image_iff_linearCombination R] at this rcases this with ⟨l2, hlp, hl⟩ - have := @Finsupp.total_apply A A R + have := @Finsupp.linearCombination_apply A A R rw [this] at hl rw [← hl, Finsupp.sum_mul] refine sum_mem ?_ diff --git a/Mathlib/RingTheory/Adjoin/Field.lean b/Mathlib/RingTheory/Adjoin/Field.lean index eb204b8922d11..4463b01947e1f 100644 --- a/Mathlib/RingTheory/Adjoin/Field.lean +++ b/Mathlib/RingTheory/Adjoin/Field.lean @@ -88,7 +88,7 @@ variable [Algebra R L] theorem IsIntegral.mem_range_algHom_of_minpoly_splits (int : IsIntegral R x) (h : Splits (algebraMap R K) (minpoly R x))(f : K →ₐ[R] L) : x ∈ f.range := - show x ∈ Set.range f from Set.image_subset_range _ _ <| by + show x ∈ Set.range f from Set.image_subset_range _ ((minpoly R x).rootSet K) <| by rw [image_rootSet h f, mem_rootSet'] exact ⟨((minpoly.monic int).map _).ne_zero, minpoly.aeval R x⟩ diff --git a/Mathlib/RingTheory/AdjoinRoot.lean b/Mathlib/RingTheory/AdjoinRoot.lean index 75dc495a1ff01..7532a1f66cbdf 100644 --- a/Mathlib/RingTheory/AdjoinRoot.lean +++ b/Mathlib/RingTheory/AdjoinRoot.lean @@ -736,7 +736,7 @@ theorem quotAdjoinRootEquivQuotPolynomialQuot_symm_mk_mk (p : R[X]) : quotMapCMapSpanMkEquivQuotMapCQuotMapSpanMk_symm_quotQuotMk, quotMapOfEquivQuotMapCMapSpanMk_symm_mk] -/-- Promote `AdjoinRoot.quotAdjoinRootEquivQuotPolynomialQuot` to an alg_equiv. -/ +/-- Promote `AdjoinRoot.quotAdjoinRootEquivQuotPolynomialQuot` to an alg_equiv. -/ @[simps!] noncomputable def quotEquivQuotMap (f : R[X]) (I : Ideal R) : (AdjoinRoot f ⧸ Ideal.map (of f) I) ≃ₐ[R] diff --git a/Mathlib/RingTheory/AlgebraicIndependent.lean b/Mathlib/RingTheory/AlgebraicIndependent.lean index 6a5c5db0549e9..b0e1db85e19c4 100644 --- a/Mathlib/RingTheory/AlgebraicIndependent.lean +++ b/Mathlib/RingTheory/AlgebraicIndependent.lean @@ -100,19 +100,19 @@ variable (hx : AlgebraicIndependent R x) include hx theorem algebraMap_injective : Injective (algebraMap R A) := by - simpa [Function.comp] using + simpa [Function.comp_def] using (Injective.of_comp_iff (algebraicIndependent_iff_injective_aeval.1 hx) MvPolynomial.C).2 (MvPolynomial.C_injective _ _) theorem linearIndependent : LinearIndependent R x := by - rw [linearIndependent_iff_injective_total] - have : Finsupp.total ι A R x = - (MvPolynomial.aeval x).toLinearMap.comp (Finsupp.total ι _ R X) := by + rw [linearIndependent_iff_injective_linearCombination] + have : Finsupp.linearCombination R x = + (MvPolynomial.aeval x).toLinearMap.comp (Finsupp.linearCombination R X) := by ext simp rw [this] refine hx.comp ?_ - rw [← linearIndependent_iff_injective_total] + rw [← linearIndependent_iff_injective_linearCombination] exact linearIndependent_X _ _ protected theorem injective [Nontrivial R] : Injective x := @@ -135,7 +135,7 @@ theorem map {f : A →ₐ[R] A'} (hf_inj : Set.InjOn f (adjoin R (range x))) : intro p rw [AlgHom.mem_range] refine ⟨MvPolynomial.rename (codRestrict x (range x) mem_range_self) p, ?_⟩ - simp [Function.comp, aeval_rename] + simp [Function.comp_def, aeval_rename] intro x y hxy rw [this] at hxy rw [adjoin_eq_range] at hf_inj diff --git a/Mathlib/RingTheory/Artinian.lean b/Mathlib/RingTheory/Artinian.lean index 65ecbf2b5c896..60965f6c689e4 100644 --- a/Mathlib/RingTheory/Artinian.lean +++ b/Mathlib/RingTheory/Artinian.lean @@ -12,7 +12,6 @@ import Mathlib.Tactic.RSuffices /-! # Artinian rings and modules - A module satisfying these equivalent conditions is said to be an *Artinian* R-module if every decreasing chain of submodules is eventually constant, or equivalently, if the relation `<` on submodules is well founded. @@ -58,8 +57,12 @@ open Set Filter Pointwise /-- `IsArtinian R M` is the proposition that `M` is an Artinian `R`-module, implemented as the well-foundedness of submodule inclusion. -/ -class IsArtinian (R M) [Semiring R] [AddCommMonoid M] [Module R M] : Prop where - wellFounded_submodule_lt' : WellFounded ((· < ·) : Submodule R M → Submodule R M → Prop) +abbrev IsArtinian (R M) [Semiring R] [AddCommMonoid M] [Module R M] : Prop := + WellFoundedLT (Submodule R M) + +theorem isArtinian_iff (R M) [Semiring R] [AddCommMonoid M] [Module R M] : IsArtinian R M ↔ + WellFounded (· < · : Submodule R M → Submodule R M → Prop) := + isWellFounded_iff _ _ section @@ -67,19 +70,11 @@ variable {R M P N : Type*} variable [Ring R] [AddCommGroup M] [AddCommGroup P] [AddCommGroup N] variable [Module R M] [Module R P] [Module R N] -open IsArtinian - -/- Porting note: added this version with `R` and `M` explicit because infer kinds are unsupported in -Lean 4-/ -theorem IsArtinian.wellFounded_submodule_lt (R M) [Semiring R] [AddCommMonoid M] [Module R M] - [IsArtinian R M] : WellFounded ((· < ·) : Submodule R M → Submodule R M → Prop) := - IsArtinian.wellFounded_submodule_lt' - theorem isArtinian_of_injective (f : M →ₗ[R] P) (h : Function.Injective f) [IsArtinian R P] : IsArtinian R M := ⟨Subrelation.wf (fun {A B} hAB => show A.map f < B.map f from Submodule.map_strictMono_of_injective h hAB) - (InvImage.wf (Submodule.map f) (IsArtinian.wellFounded_submodule_lt R P))⟩ + (InvImage.wf (Submodule.map f) IsWellFounded.wf)⟩ instance isArtinian_submodule' [IsArtinian R M] (N : Submodule R M) : IsArtinian R N := isArtinian_of_injective N.subtype Subtype.val_injective @@ -94,7 +89,7 @@ theorem isArtinian_of_surjective (f : M →ₗ[R] P) (hf : Function.Surjective f ⟨Subrelation.wf (fun {A B} hAB => show A.comap f < B.comap f from Submodule.comap_strictMono_of_surjective hf hAB) - (InvImage.wf (Submodule.comap f) (IsArtinian.wellFounded_submodule_lt R M))⟩ + (InvImage.wf (Submodule.comap f) IsWellFounded.wf)⟩ variable {M} @@ -104,11 +99,10 @@ theorem isArtinian_of_linearEquiv (f : M ≃ₗ[R] P) [IsArtinian R M] : IsArtin 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 (IsArtinian.wellFounded_submodule_lt R M) - (IsArtinian.wellFounded_submodule_lt R P) (LinearMap.range f) (Submodule.map f) + 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])⟩ + (by simp [Submodule.map_comap_eq, inf_comm]) (by simp [Submodule.comap_map_eq, h]) 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 @@ -147,20 +141,15 @@ instance isArtinian_finsupp {R ι M : Type*} [Ring R] [AddCommGroup M] [Module R end -open IsArtinian Submodule Function +open Submodule Function section Ring variable {R M : Type*} [Ring R] [AddCommGroup M] [Module R M] -theorem isArtinian_iff_wellFounded : - IsArtinian R M ↔ WellFounded ((· < ·) : Submodule R M → Submodule R M → Prop) := - ⟨fun h => h.1, IsArtinian.mk⟩ - -theorem IsArtinian.finite_of_linearIndependent [Nontrivial R] [IsArtinian R M] {s : Set M} +theorem IsArtinian.finite_of_linearIndependent [Nontrivial R] [h : IsArtinian R M] {s : Set M} (hs : LinearIndependent R ((↑) : s → M)) : s.Finite := by - refine by_contradiction fun hf => (RelEmbedding.wellFounded_iff_no_descending_seq.1 - (wellFounded_submodule_lt (R := R) (M := M))).elim' ?_ + refine by_contradiction fun hf => (RelEmbedding.wellFounded_iff_no_descending_seq.1 h.wf).elim' ?_ have f : ℕ ↪ s := Set.Infinite.natEmbedding s hf have : ∀ n, (↑) ∘ f '' { m | n ≤ m } ⊆ s := by rintro n x ⟨y, _, rfl⟩ @@ -182,7 +171,7 @@ theorem IsArtinian.finite_of_linearIndependent [Nontrivial R] [IsArtinian R M] { /-- A module is Artinian iff every nonempty set of submodules has a minimal submodule among them. -/ theorem set_has_minimal_iff_artinian : (∀ a : Set <| Submodule R M, a.Nonempty → ∃ M' ∈ a, ∀ I ∈ a, ¬I < M') ↔ IsArtinian R M := by - rw [isArtinian_iff_wellFounded, WellFounded.wellFounded_iff_has_min] + rw [isArtinian_iff, WellFounded.wellFounded_iff_has_min] theorem IsArtinian.set_has_minimal [IsArtinian R M] (a : Set <| Submodule R M) (ha : a.Nonempty) : ∃ M' ∈ a, ∀ I ∈ a, ¬I < M' := @@ -191,7 +180,7 @@ theorem IsArtinian.set_has_minimal [IsArtinian R M] (a : Set <| Submodule R M) ( /-- A module is Artinian iff every decreasing chain of submodules stabilizes. -/ theorem monotone_stabilizes_iff_artinian : (∀ f : ℕ →o (Submodule R M)ᵒᵈ, ∃ n, ∀ m, n ≤ m → f n = f m) ↔ IsArtinian R M := by - rw [isArtinian_iff_wellFounded] + rw [isArtinian_iff] exact WellFounded.monotone_chain_condition.symm namespace IsArtinian @@ -209,7 +198,7 @@ theorem eventuallyConst_of_isArtinian (f : ℕ →o (Submodule R M)ᵒᵈ) : /-- If `∀ I > J, P I` implies `P J`, then `P` holds for all submodules. -/ theorem induction {P : Submodule R M → Prop} (hgt : ∀ I, (∀ J < I, P J) → P I) (I : Submodule R M) : P I := - (wellFounded_submodule_lt R M).recursion I hgt + WellFoundedLT.induction I hgt end IsArtinian @@ -222,7 +211,7 @@ and range. -/ theorem eventually_codisjoint_ker_pow_range_pow (f : M →ₗ[R] M) : ∀ᶠ n in atTop, Codisjoint (LinearMap.ker (f ^ n)) (LinearMap.range (f ^ n)) := by obtain ⟨n, hn : ∀ m, n ≤ m → LinearMap.range (f ^ n) = LinearMap.range (f ^ m)⟩ := - monotone_stabilizes f.iterateRange + IsArtinian.monotone_stabilizes f.iterateRange refine eventually_atTop.mpr ⟨n, fun m hm ↦ codisjoint_iff.mpr ?_⟩ simp_rw [← hn _ hm, Submodule.eq_top_iff', Submodule.mem_sup] intro x @@ -236,7 +225,7 @@ theorem eventually_codisjoint_ker_pow_range_pow (f : M →ₗ[R] M) : lemma eventually_iInf_range_pow_eq (f : Module.End R M) : ∀ᶠ n in atTop, ⨅ m, LinearMap.range (f ^ m) = LinearMap.range (f ^ n) := by obtain ⟨n, hn : ∀ m, n ≤ m → LinearMap.range (f ^ n) = LinearMap.range (f ^ m)⟩ := - monotone_stabilizes f.iterateRange + IsArtinian.monotone_stabilizes f.iterateRange refine eventually_atTop.mpr ⟨n, fun l hl ↦ le_antisymm (iInf_le _ _) (le_iInf fun m ↦ ?_)⟩ rcases le_or_lt l m with h | h · rw [← hn _ (hl.trans h), hn _ hl] @@ -353,9 +342,8 @@ instance isArtinian_of_quotient_of_artinian (R) [Ring R] (M) [AddCommGroup M] [M /-- 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 := by - rw [isArtinian_iff_wellFounded] at h ⊢ - exact (Submodule.restrictScalarsEmbedding R S M).wellFounded h + [Module S M] [Module R M] [IsScalarTower R S M] (h : IsArtinian R M) : IsArtinian S M := + ⟨(Submodule.restrictScalarsEmbedding R S M).wellFounded h.wf⟩ instance (R) [CommRing R] [IsArtinianRing R] (I : Ideal R) : IsArtinianRing (R ⧸ I) := isArtinian_of_tower R inferInstance @@ -367,7 +355,7 @@ theorem isArtinian_of_fg_of_artinian {R M} [Ring R] [AddCommGroup M] [Module R M haveI := Classical.decEq R have : ∀ x ∈ s, x ∈ N := fun x hx => hs ▸ Submodule.subset_span hx refine @isArtinian_of_surjective _ ((↑s : Set M) →₀ R) N _ _ _ _ _ ?_ ?_ isArtinian_finsupp - · exact Finsupp.total (↑s : Set M) N R (fun i => ⟨i, hs ▸ subset_span i.2⟩) + · exact Finsupp.linearCombination R (fun i => ⟨i, hs ▸ subset_span i.2⟩) · rw [← LinearMap.range_eq_top, eq_top_iff, ← map_le_map_iff_of_injective (show Injective (Submodule.subtype N) from Subtype.val_injective), Submodule.map_top, range_subtype, @@ -395,8 +383,8 @@ theorem isArtinian_span_of_finite (R) {M} [Ring R] [AddCommGroup M] [Module R M] theorem Function.Surjective.isArtinianRing {R} [Ring R] {S} [Ring S] {F} [FunLike F R S] [RingHomClass F R S] {f : F} (hf : Function.Surjective f) [H : IsArtinianRing R] : IsArtinianRing S := by - rw [isArtinianRing_iff, isArtinian_iff_wellFounded] at H ⊢ - exact (Ideal.orderEmbeddingOfSurjective f hf).wellFounded H + rw [isArtinianRing_iff] at H ⊢ + exact ⟨(Ideal.orderEmbeddingOfSurjective f hf).wellFounded H.wf⟩ instance isArtinianRing_range {R} [Ring R] {S} [Ring S] (f : R →+* S) [IsArtinianRing R] : IsArtinianRing f.range := diff --git a/Mathlib/RingTheory/Bezout.lean b/Mathlib/RingTheory/Bezout.lean index 488ce7db5c4fb..4ef7731887a6d 100644 --- a/Mathlib/RingTheory/Bezout.lean +++ b/Mathlib/RingTheory/Bezout.lean @@ -59,7 +59,7 @@ theorem TFAE [IsBezout R] [IsDomain R] : tfae_have 4 → 1 · rintro ⟨h⟩ rw [isNoetherianRing_iff, isNoetherian_iff_fg_wellFounded] - apply RelEmbedding.wellFounded _ h + refine ⟨RelEmbedding.wellFounded ?_ h⟩ have : ∀ I : { J : Ideal R // J.FG }, ∃ x : R, (I : Ideal R) = Ideal.span {x} := fun ⟨I, hI⟩ => (IsBezout.isPrincipal_of_FG I hI).1 choose f hf using this diff --git a/Mathlib/RingTheory/Bialgebra/Basic.lean b/Mathlib/RingTheory/Bialgebra/Basic.lean index dfcfce5f3f06e..516dc36878824 100644 --- a/Mathlib/RingTheory/Bialgebra/Basic.lean +++ b/Mathlib/RingTheory/Bialgebra/Basic.lean @@ -68,7 +68,7 @@ class Bialgebra (R : Type u) (A : Type v) [CommSemiring R] [Semiring A] extends /-- The comultiplication on a bialgebra preserves multiplication. This is written in a rather obscure way: it says that two bilinear maps `A →ₗ[R] A →ₗ[R] (A ⊗[R] A)` are equal. The corresponding equal linear maps `A ⊗[R] A →ₗ[R] A ⊗[R] A` - are firstly multiplcation followed by `comul`, and secondly `comul ⊗ comul` followed + are firstly multiplication followed by `comul`, and secondly `comul ⊗ comul` followed by multiplication on `A ⊗[R] A`. See `Bialgebra.mk'` for a constructor for bialgebras which uses the more familiar diff --git a/Mathlib/RingTheory/Bialgebra/Equiv.lean b/Mathlib/RingTheory/Bialgebra/Equiv.lean index a94379991aff9..c0160257534d0 100644 --- a/Mathlib/RingTheory/Bialgebra/Equiv.lean +++ b/Mathlib/RingTheory/Bialgebra/Equiv.lean @@ -39,7 +39,7 @@ attribute [nolint docBlame] BialgEquiv.toCoalgEquiv notation:50 A " ≃ₐc[" R "] " B => BialgEquiv R A B /-- `BialgEquivClass F R A B` asserts `F` is a type of bundled bialgebra equivalences -from `A` to `B`. -/ +from `A` to `B`. -/ class BialgEquivClass (F : Type*) (R A B : outParam Type*) [CommSemiring R] [Semiring A] [Semiring B] [Algebra R A] [Algebra R B] [CoalgebraStruct R A] [CoalgebraStruct R B] [EquivLike F A B] diff --git a/Mathlib/RingTheory/Bialgebra/Hom.lean b/Mathlib/RingTheory/Bialgebra/Hom.lean index fe171794c8b66..f1b2923cd334c 100644 --- a/Mathlib/RingTheory/Bialgebra/Hom.lean +++ b/Mathlib/RingTheory/Bialgebra/Hom.lean @@ -45,7 +45,7 @@ infixr:25 " →ₐc " => BialgHom _ notation:25 A " →ₐc[" R "] " B => BialgHom R A B /-- `BialgHomClass F R A B` asserts `F` is a type of bundled bialgebra homomorphisms -from `A` to `B`. -/ +from `A` to `B`. -/ class BialgHomClass (F : Type*) (R A B : outParam Type*) [CommSemiring R] [Semiring A] [Algebra R A] [Semiring B] [Algebra R B] [CoalgebraStruct R A] [CoalgebraStruct R B] [FunLike F A B] diff --git a/Mathlib/RingTheory/Binomial.lean b/Mathlib/RingTheory/Binomial.lean index 31d44ff0e4ac7..45bbba6501dad 100644 --- a/Mathlib/RingTheory/Binomial.lean +++ b/Mathlib/RingTheory/Binomial.lean @@ -241,7 +241,7 @@ instance Int.instBinomialRing : BinomialRing ℤ where nsmul_right_injective n hn r s hrs := Int.eq_of_mul_eq_mul_left (Int.ofNat_ne_zero.mpr hn) hrs multichoose := Int.multichoose factorial_nsmul_multichoose r k := by - rw [Int.multichoose, nsmul_eq_mul] + rw [Int.multichoose.eq_def, nsmul_eq_mul] cases r with | ofNat n => simp only [multichoose, nsmul_eq_mul, Int.ofNat_eq_coe, Int.ofNat_mul_out] @@ -452,7 +452,7 @@ theorem choose_smul_choose [NatPowAssoc R] (r : R) (n k : ℕ) (hkn : k ≤ n) : refine nsmul_right_injective (Nat.factorial n) (Nat.factorial_ne_zero n) ?_ simp only rw [nsmul_left_comm, ← descPochhammer_eq_factorial_smul_choose, - ← Nat.choose_mul_factorial_mul_factorial hkn, ← smul_mul_smul, + ← Nat.choose_mul_factorial_mul_factorial hkn, ← smul_mul_smul_comm, ← descPochhammer_eq_factorial_smul_choose, mul_nsmul', ← descPochhammer_eq_factorial_smul_choose, smul_mul_assoc] nth_rw 2 [← Nat.sub_add_cancel hkn] diff --git a/Mathlib/RingTheory/Coalgebra/Equiv.lean b/Mathlib/RingTheory/Coalgebra/Equiv.lean index 5b15a25b51a3b..f1e8563bdc49c 100644 --- a/Mathlib/RingTheory/Coalgebra/Equiv.lean +++ b/Mathlib/RingTheory/Coalgebra/Equiv.lean @@ -38,7 +38,7 @@ attribute [nolint docBlame] CoalgEquiv.toLinearEquiv notation:50 A " ≃ₗc[" R "] " B => CoalgEquiv R A B /-- `CoalgEquivClass F R A B` asserts `F` is a type of bundled coalgebra equivalences -from `A` to `B`. -/ +from `A` to `B`. -/ class CoalgEquivClass (F : Type*) (R A B : outParam Type*) [CommSemiring R] [AddCommMonoid A] [AddCommMonoid B] [Module R A] [Module R B] [CoalgebraStruct R A] [CoalgebraStruct R B] [EquivLike F A B] diff --git a/Mathlib/RingTheory/Coalgebra/Hom.lean b/Mathlib/RingTheory/Coalgebra/Hom.lean index 75d7d5fd60d0e..b10428555036d 100644 --- a/Mathlib/RingTheory/Coalgebra/Hom.lean +++ b/Mathlib/RingTheory/Coalgebra/Hom.lean @@ -43,7 +43,7 @@ infixr:25 " →ₗc " => CoalgHom _ notation:25 A " →ₗc[" R "] " B => CoalgHom R A B /-- `CoalgHomClass F R A B` asserts `F` is a type of bundled coalgebra homomorphisms -from `A` to `B`. -/ +from `A` to `B`. -/ class CoalgHomClass (F : Type*) (R A B : outParam Type*) [CommSemiring R] [AddCommMonoid A] [Module R A] [AddCommMonoid B] [Module R B] [CoalgebraStruct R A] [CoalgebraStruct R B] [FunLike F A B] @@ -312,7 +312,7 @@ def Repr.induced {a : A} (repr : Repr R a) lemma sum_tmul_counit_apply_eq {F : Type*} [FunLike F A B] [CoalgHomClass F R A B] (φ : F) {a : A} (repr : Repr R a) : ∑ i ∈ repr.index, counit (R := R) (repr.left i) ⊗ₜ φ (repr.right i) = 1 ⊗ₜ[R] φ a := by - simp [← sum_counit_tmul_eq (repr.induced φ)] + simp [← sum_counit_tmul_eq (repr.induced φ)] @[simp] lemma sum_tmul_apply_counit_eq diff --git a/Mathlib/RingTheory/Congruence/Basic.lean b/Mathlib/RingTheory/Congruence/Basic.lean index 30337d5e5beaf..1a9c8ef824451 100644 --- a/Mathlib/RingTheory/Congruence/Basic.lean +++ b/Mathlib/RingTheory/Congruence/Basic.lean @@ -448,7 +448,7 @@ theorem coe_sInf (S : Set (RingCon R)) : ⇑(sInf S) = sInf ((⇑) '' S) := by @[simp, norm_cast] theorem coe_iInf {ι : Sort*} (f : ι → RingCon R) : ⇑(iInf f) = ⨅ i, ⇑(f i) := by - rw [iInf, coe_sInf, ← Set.range_comp, sInf_range, Function.comp] + rw [iInf, coe_sInf, ← Set.range_comp, sInf_range, Function.comp_def] instance : PartialOrder (RingCon R) where le_refl _c _ _ := id diff --git a/Mathlib/RingTheory/Coprime/Basic.lean b/Mathlib/RingTheory/Coprime/Basic.lean index ea3e3dce7eff2..851c87915e7a1 100644 --- a/Mathlib/RingTheory/Coprime/Basic.lean +++ b/Mathlib/RingTheory/Coprime/Basic.lean @@ -232,7 +232,7 @@ variable {R G : Type*} [CommSemiring R] [Group G] [MulAction G R] [SMulCommClass theorem isCoprime_group_smul_left : IsCoprime (x • y) z ↔ IsCoprime y z := ⟨fun ⟨a, b, h⟩ => ⟨x • a, b, by rwa [smul_mul_assoc, ← mul_smul_comm]⟩, fun ⟨a, b, h⟩ => - ⟨x⁻¹ • a, b, by rwa [smul_mul_smul, inv_mul_cancel, one_smul]⟩⟩ + ⟨x⁻¹ • a, b, by rwa [smul_mul_smul_comm, inv_mul_cancel, one_smul]⟩⟩ theorem isCoprime_group_smul_right : IsCoprime y (x • z) ↔ IsCoprime y z := isCoprime_comm.trans <| (isCoprime_group_smul_left x z y).trans isCoprime_comm diff --git a/Mathlib/RingTheory/DedekindDomain/AdicValuation.lean b/Mathlib/RingTheory/DedekindDomain/AdicValuation.lean index 9659b2099784c..a9006150a5a66 100644 --- a/Mathlib/RingTheory/DedekindDomain/AdicValuation.lean +++ b/Mathlib/RingTheory/DedekindDomain/AdicValuation.lean @@ -458,11 +458,11 @@ instance : Algebra R (v.adicCompletionIntegers K) where map_one' := by simp only [map_one]; rfl map_mul' x y := by ext - simp_rw [RingHom.map_mul, Subring.coe_mul, UniformSpace.Completion.coe_mul] + simp only [map_mul, UniformSpace.Completion.coe_mul, MulMemClass.mk_mul_mk] map_zero' := by simp only [map_zero]; rfl map_add' x y := by ext - simp_rw [RingHom.map_add, Subring.coe_add, UniformSpace.Completion.coe_add] + simp only [map_add, UniformSpace.Completion.coe_add, AddMemClass.mk_add_mk] commutes' r x := by rw [mul_comm] smul_def' r x := by diff --git a/Mathlib/RingTheory/DedekindDomain/Factorization.lean b/Mathlib/RingTheory/DedekindDomain/Factorization.lean index 21265293630ad..9c8f207b3ee90 100644 --- a/Mathlib/RingTheory/DedekindDomain/Factorization.lean +++ b/Mathlib/RingTheory/DedekindDomain/Factorization.lean @@ -406,7 +406,7 @@ theorem count_neg_zpow (n : ℤ) (I : FractionalIdeal R⁰ K) : ← zpow_add₀ hI, neg_add_cancel, zpow_zero] exact count_one K v -theorem count_inv (I : FractionalIdeal R⁰ K) : +theorem count_inv (I : FractionalIdeal R⁰ K) : count K v (I⁻¹) = - count K v I := by rw [← zpow_neg_one, count_neg_zpow K v (1 : ℤ) I, zpow_one] diff --git a/Mathlib/RingTheory/DedekindDomain/FiniteAdeleRing.lean b/Mathlib/RingTheory/DedekindDomain/FiniteAdeleRing.lean index ed2483621633c..8591f904f4b2b 100644 --- a/Mathlib/RingTheory/DedekindDomain/FiniteAdeleRing.lean +++ b/Mathlib/RingTheory/DedekindDomain/FiniteAdeleRing.lean @@ -54,6 +54,9 @@ instance : CommRing (FiniteIntegralAdeles R K) := instance : TopologicalSpace (FiniteIntegralAdeles R K) := inferInstanceAs (TopologicalSpace (∀ v : HeightOneSpectrum R, v.adicCompletionIntegers K)) +instance (v : HeightOneSpectrum R) : TopologicalRing (v.adicCompletionIntegers K) := + Subring.instTopologicalRing .. + instance : TopologicalRing (FiniteIntegralAdeles R K) := inferInstanceAs (TopologicalRing (∀ v : HeightOneSpectrum R, v.adicCompletionIntegers K)) @@ -344,7 +347,7 @@ lemma ext {a₁ a₂ : FiniteAdeleRing R K} (h : (a₁ : K_hat R K) = a₂) : a instance : Algebra (R_hat R K) (FiniteAdeleRing R K) where smul rhat fadele := ⟨fun v ↦ rhat v * fadele.1 v, Finite.subset fadele.2 <| fun v hv ↦ by simp only [mem_adicCompletionIntegers, mem_compl_iff, mem_setOf_eq, map_mul] at hv ⊢ - exact mt (mul_le_one₀ (rhat v).2) hv + exact mt (mul_le_one' (rhat v).2) hv ⟩ toFun r := ⟨r, by simp_all⟩ map_one' := by ext; rfl diff --git a/Mathlib/RingTheory/DedekindDomain/Ideal.lean b/Mathlib/RingTheory/DedekindDomain/Ideal.lean index 6c656b177371a..b7d49d8d88e73 100644 --- a/Mathlib/RingTheory/DedekindDomain/Ideal.lean +++ b/Mathlib/RingTheory/DedekindDomain/Ideal.lean @@ -108,7 +108,7 @@ theorem right_inverse_eq (I J : FractionalIdeal R₁⁰ K) (h : I * J = 1) : J = apply (le_div_iff_of_nonzero hI).mpr _ intro y hy x hx rw [mul_comm] - exact mul_mem_mul hx hy + exact mul_mem_mul hy hx theorem mul_inv_cancel_iff {I : FractionalIdeal R₁⁰ K} : I * I⁻¹ = 1 ↔ ∃ J, I * J = 1 := ⟨fun h => ⟨I⁻¹, h⟩, fun ⟨J, hJ⟩ => by rwa [← right_inverse_eq K I J hJ]⟩ @@ -562,6 +562,7 @@ noncomputable instance FractionalIdeal.semifield : Semifield (FractionalIdeal A div_eq_mul_inv := FractionalIdeal.div_eq_mul_inv mul_inv_cancel _ := FractionalIdeal.mul_inv_cancel nnqsmul := _ + nnqsmul_def := fun q a => rfl /-- Fractional ideals have cancellative multiplication in a Dedekind domain. @@ -609,9 +610,8 @@ theorem Ideal.dvdNotUnit_iff_lt {I J : Ideal A} : DvdNotUnit I J ↔ J < I := instance : WfDvdMonoid (Ideal A) where wellFounded_dvdNotUnit := by - have : WellFounded ((· > ·) : Ideal A → Ideal A → Prop) := - isNoetherian_iff_wellFounded.mp (isNoetherianRing_iff.mp IsDedekindRing.toIsNoetherian) - convert this + have : WellFoundedGT (Ideal A) := inferInstance + convert this.wf ext rw [Ideal.dvdNotUnit_iff_lt] diff --git a/Mathlib/RingTheory/DedekindDomain/PID.lean b/Mathlib/RingTheory/DedekindDomain/PID.lean index 881352fd3f2ce..258435cca7f9a 100644 --- a/Mathlib/RingTheory/DedekindDomain/PID.lean +++ b/Mathlib/RingTheory/DedekindDomain/PID.lean @@ -9,7 +9,7 @@ import Mathlib.RingTheory.DedekindDomain.Ideal /-! # Criteria under which a Dedekind domain is a PID -This file contains some results that we can use to test wether all ideals in a Dedekind domain are +This file contains some results that we can use to test whether all ideals in a Dedekind domain are principal. ## Main results @@ -96,7 +96,7 @@ theorem FractionalIdeal.isPrincipal_of_unit_of_comap_mul_span_singleton_eq_top { · conv_rhs => rw [← hinv, mul_comm] apply FractionalIdeal.mul_le_mul_left (FractionalIdeal.spanSingleton_le_iff_mem.mpr hw) · rw [FractionalIdeal.one_le, ← hvw, mul_comm] - exact FractionalIdeal.mul_mem_mul hv (FractionalIdeal.mem_spanSingleton_self _ _) + exact FractionalIdeal.mul_mem_mul (FractionalIdeal.mem_spanSingleton_self _ _) hv /-- An invertible fractional ideal of a commutative ring with finitely many maximal ideals is principal. diff --git a/Mathlib/RingTheory/DedekindDomain/SelmerGroup.lean b/Mathlib/RingTheory/DedekindDomain/SelmerGroup.lean index 3c636cfac5471..43994f9070494 100644 --- a/Mathlib/RingTheory/DedekindDomain/SelmerGroup.lean +++ b/Mathlib/RingTheory/DedekindDomain/SelmerGroup.lean @@ -123,7 +123,7 @@ theorem valuation_of_unit_eq (x : Rˣ) : apply_fun v.intValuation at hx rw [map_one, map_mul] at hx rw [not_lt, ← hx, ← mul_one <| v.valuation _, valuation_of_algebraMap, - mul_le_mul_left₀ <| left_ne_zero_of_mul_eq_one hx] + mul_le_mul_left <| zero_lt_iff.2 <| left_ne_zero_of_mul_eq_one hx] exact v.intValuation_le_one _ -- Porting note: invalid attribute 'semireducible', declaration is in an imported module @@ -173,7 +173,7 @@ theorem monotone (hS : S ≤ S') : K⟮S,n⟯ ≤ K⟮S',n⟯ := fun _ hx v => h def valuation : K⟮S,n⟯ →* S → Multiplicative (ZMod n) where toFun x v := (v : HeightOneSpectrum R).valuationOfNeZeroMod n (x : K/n) map_one' := funext fun v => map_one _ - map_mul' x y := by simp only [Submonoid.coe_mul, Subgroup.coe_toSubmonoid, map_mul]; rfl + map_mul' x y := by simp only [Subgroup.coe_mul, map_mul]; rfl theorem valuation_ker_eq : valuation.ker = K⟮(∅ : Set <| HeightOneSpectrum R),n⟯.subgroupOf (K⟮S,n⟯) := by @@ -191,8 +191,8 @@ def fromUnit {n : ℕ} : Rˣ →* K⟮(∅ : Set <| HeightOneSpectrum R),n⟯ wh ⟨QuotientGroup.mk <| Units.map (algebraMap R K).toMonoidHom x, fun v _ => v.valuation_of_unit_mod_eq n x⟩ map_one' := by simp only [map_one, QuotientGroup.mk_one, Subgroup.mk_eq_one] - map_mul' _ _ := by simp only [RingHom.toMonoidHom_eq_coe, map_mul, MonoidHom.mem_range, - powMonoidHom_apply, QuotientGroup.mk_mul, Submonoid.mk_mul_mk] + map_mul' _ _ := by simp only [RingHom.toMonoidHom_eq_coe, map_mul, QuotientGroup.mk_mul, + MulMemClass.mk_mul_mk] theorem fromUnit_ker [hn : Fact <| 0 < n] : (@fromUnit R _ _ K _ _ _ n).ker = (powMonoidHom n : Rˣ →* Rˣ).range := by diff --git a/Mathlib/RingTheory/Derivation/Basic.lean b/Mathlib/RingTheory/Derivation/Basic.lean index 31605cb3d9c2b..6a97903473082 100644 --- a/Mathlib/RingTheory/Derivation/Basic.lean +++ b/Mathlib/RingTheory/Derivation/Basic.lean @@ -344,7 +344,8 @@ variable {R : Type*} [CommSemiring R] {A : Type*} [CommSemiring A] [Algebra R A] rule. -/ def mk' (D : A →ₗ[R] M) (h : ∀ a b, D (a * b) = a • D b + b • D a) : Derivation R A M where toLinearMap := D - map_one_eq_zero' := add_right_eq_self.1 <| by simpa only [one_smul, one_mul] using (h 1 1).symm + map_one_eq_zero' := (add_right_eq_self (a := D 1)).1 <| by + simpa only [one_smul, one_mul] using (h 1 1).symm leibniz' := h @[simp] @@ -473,5 +474,4 @@ end end - end Derivation diff --git a/Mathlib/RingTheory/Derivation/DifferentialRing.lean b/Mathlib/RingTheory/Derivation/DifferentialRing.lean new file mode 100644 index 0000000000000..f26d5aab07492 --- /dev/null +++ b/Mathlib/RingTheory/Derivation/DifferentialRing.lean @@ -0,0 +1,95 @@ +/- +Copyright (c) 2024 Daniel Weber. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Daniel Weber +-/ +import Mathlib.RingTheory.Derivation.Basic + +/-! +# Differential and Algebras + +This file defines derivations from a commutative ring to itself as a typeclass, which lets us +use the x′ notation for the derivative of x. +-/ + +/-- A derivation from a ring to itself, as a typeclass. -/ +class Differential (R : Type*) [CommRing R] where + /-- The `Derivation` associated with the ring. -/ + deriv : Derivation ℤ R R + +@[inherit_doc] +scoped[Differential] postfix:max "′" => Differential.deriv + +open scoped Differential + +open Lean PrettyPrinter Delaborator SubExpr in +/-- +A delaborator for the x′ notation. This is required because it's not direct function application, +so the default delaborator doesn't work. +-/ +@[delab app.DFunLike.coe] +def delabDeriv : Delab := do + let e ← getExpr + guard <| e.isAppOfArity' ``DFunLike.coe 6 + guard <| (e.getArg!' 4).isAppOf' ``Differential.deriv + let arg ← withAppArg delab + `($arg′) + +/-- +A differential algebra is an `Algebra` where the derivation commutes with `algebraMap`. +-/ +class DifferentialAlgebra (A B : Type*) [CommRing A] [CommRing B] [Algebra A B] + [Differential A] [Differential B] : Prop where + deriv_algebraMap : ∀ a : A, (algebraMap A B a)′ = algebraMap A B a′ + +export DifferentialAlgebra (deriv_algebraMap) + +@[norm_cast] +lemma algebraMap.coe_deriv {A : Type*} {B : Type*} [CommRing A] [CommRing B] [Algebra A B] + [Differential A] [Differential B] [DifferentialAlgebra A B] (a : A) : + (a′ : A) = (a : B)′ := + (DifferentialAlgebra.deriv_algebraMap _).symm + +/-- +A differential ring `A` and an algebra over it `B` share constants if all +constants in B are in the range of `algberaMap A B`. +-/ +class Differential.ContainConstants (A B : Type*) [CommRing A] [CommRing B] + [Algebra A B] [Differential B] : Prop where + /-- If the derivative of x is 0, then it's in the range of `algberaMap A B`. -/ + protected mem_range_of_deriv_eq_zero {x : B} (h : x′ = 0) : x ∈ (algebraMap A B).range + +lemma mem_range_of_deriv_eq_zero (A : Type*) {B : Type*} [CommRing A] [CommRing B] [Algebra A B] + [Differential B] [Differential.ContainConstants A B] {x : B} (h : x′ = 0) : + x ∈ (algebraMap A B).range := + Differential.ContainConstants.mem_range_of_deriv_eq_zero h + +instance (A : Type*) [CommRing A] [Differential A] : DifferentialAlgebra A A where + deriv_algebraMap _ := rfl + +instance (A : Type*) [CommRing A] [Differential A] : Differential.ContainConstants A A where + mem_range_of_deriv_eq_zero {x} _ := ⟨x, rfl⟩ + +/-- Transfer a `Differential` instance across a `RingEquiv`. -/ +@[reducible] +def Differential.equiv {R R₂ : Type*} [CommRing R] [CommRing R₂] [Differential R₂] + (h : R ≃+* R₂) : Differential R := + ⟨Derivation.mk' (h.symm.toAddMonoidHom.toIntLinearMap ∘ₗ + Differential.deriv.toLinearMap ∘ₗ h.toAddMonoidHom.toIntLinearMap) (by simp)⟩ + +/-- +Transfer a `DifferentialAlgebra` instance across a `AlgEquiv`. +-/ +lemma DifferentialAlgebra.equiv {A : Type*} [CommRing A] [Differential A] + {R R₂ : Type*} [CommRing R] [CommRing R₂] [Differential R₂] [Algebra A R] + [Algebra A R₂] [DifferentialAlgebra A R₂] (h : R ≃ₐ[A] R₂) : + letI := Differential.equiv h.toRingEquiv + DifferentialAlgebra A R := + letI := Differential.equiv h.toRingEquiv + ⟨fun a ↦ by + change (LinearMap.comp ..) _ = _ + simp only [AlgEquiv.toRingEquiv_eq_coe, RingHom.toAddMonoidHom_eq_coe, + RingEquiv.toRingHom_eq_coe, AlgEquiv.toRingEquiv_toRingHom, LinearMap.coe_comp, + AddMonoidHom.coe_toIntLinearMap, AddMonoidHom.coe_coe, RingHom.coe_coe, Derivation.coeFn_coe, + Function.comp_apply, AlgEquiv.commutes, deriv_algebraMap] + apply h.symm.commutes⟩ diff --git a/Mathlib/RingTheory/Derivation/ToSquareZero.lean b/Mathlib/RingTheory/Derivation/ToSquareZero.lean index eba48921f14f4..398d75d13c3f9 100644 --- a/Mathlib/RingTheory/Derivation/ToSquareZero.lean +++ b/Mathlib/RingTheory/Derivation/ToSquareZero.lean @@ -20,7 +20,7 @@ section ToSquareZero universe u v w variable {R : Type u} {A : Type v} {B : Type w} [CommSemiring R] [CommSemiring A] [CommRing B] -variable [Algebra R A] [Algebra R B] (I : Ideal B) (hI : I ^ 2 = ⊥) +variable [Algebra R A] [Algebra R B] (I : Ideal B) /-- If `f₁ f₂ : A →ₐ[R] B` are two lifts of the same `A →ₐ[R] B ⧸ I`, we may define a map `f₁ - f₂ : A →ₗ[R] I`. -/ @@ -42,7 +42,7 @@ variable [Algebra A B] /-- Given a tower of algebras `R → A → B`, and a square-zero `I : Ideal B`, each lift `A →ₐ[R] B` of the canonical map `A →ₐ[R] B ⧸ I` corresponds to an `R`-derivation from `A` to `I`. -/ -def derivationToSquareZeroOfLift [IsScalarTower R A B] (f : A →ₐ[R] B) +def derivationToSquareZeroOfLift [IsScalarTower R A B] (hI : I ^ 2 = ⊥) (f : A →ₐ[R] B) (e : (Ideal.Quotient.mkₐ R I).comp f = IsScalarTower.toAlgHom R A (B ⧸ I)) : Derivation R A I := by refine @@ -66,6 +66,8 @@ def derivationToSquareZeroOfLift [IsScalarTower R A B] (f : A →ₐ[R] B) IsScalarTower.coe_toAlgHom'] ring +variable (hI : I ^ 2 = ⊥) + theorem derivationToSquareZeroOfLift_apply [IsScalarTower R A B] (f : A →ₐ[R] B) (e : (Ideal.Quotient.mkₐ R I).comp f = IsScalarTower.toAlgHom R A (B ⧸ I)) (x : A) : (derivationToSquareZeroOfLift I hI f e x : B) = f x - algebraMap A B x := @@ -74,7 +76,8 @@ theorem derivationToSquareZeroOfLift_apply [IsScalarTower R A B] (f : A →ₐ[R /-- Given a tower of algebras `R → A → B`, and a square-zero `I : Ideal B`, each `R`-derivation from `A` to `I` corresponds to a lift `A →ₐ[R] B` of the canonical map `A →ₐ[R] B ⧸ I`. -/ @[simps (config := .lemmasOnly)] -def liftOfDerivationToSquareZero [IsScalarTower R A B] (f : Derivation R A I) : A →ₐ[R] B := +def liftOfDerivationToSquareZero [IsScalarTower R A B] (hI : I ^ 2 = ⊥) (f : Derivation R A I) : + A →ₐ[R] B := { ((I.restrictScalars R).subtype.comp f.toLinearMap + (IsScalarTower.toAlgHom R A B).toLinearMap : A →ₗ[R] B) with toFun := fun x => f x + algebraMap A B x diff --git a/Mathlib/RingTheory/EssentialFiniteness.lean b/Mathlib/RingTheory/EssentialFiniteness.lean index 65b40d237017c..c23b4328ea0fb 100644 --- a/Mathlib/RingTheory/EssentialFiniteness.lean +++ b/Mathlib/RingTheory/EssentialFiniteness.lean @@ -34,7 +34,7 @@ class EssFiniteType : Prop where IsLocalization ((IsUnit.submonoid S).comap (algebraMap (adjoin R (s : Set S)) S)) S /-- Let `S` be an `R`-algebra essentially of finite type, this is a choice of a finset `s ⊆ S` -such that `S` is the localization of `R[s]`. -/ +such that `S` is the localization of `R[s]`. -/ noncomputable def EssFiniteType.finset [h : EssFiniteType R S] : Finset S := h.cond.choose diff --git a/Mathlib/RingTheory/Filtration.lean b/Mathlib/RingTheory/Filtration.lean index a73354fbc33c0..8ce8b760670a3 100644 --- a/Mathlib/RingTheory/Filtration.lean +++ b/Mathlib/RingTheory/Filtration.lean @@ -294,11 +294,11 @@ theorem submodule_eq_span_le_iff_stable_ge (n₀ : ℕ) : · intro H n hn refine (F.smul_le n).antisymm ?_ intro x hx - obtain ⟨l, hl⟩ := (Finsupp.mem_span_iff_total _ _ _).mp (H _ ⟨x, hx, rfl⟩) + obtain ⟨l, hl⟩ := (Finsupp.mem_span_iff_linearCombination _ _ _).mp (H _ ⟨x, hx, rfl⟩) replace hl := congr_arg (fun f : ℕ →₀ M => f (n + 1)) hl dsimp only at hl erw [Finsupp.single_eq_same] at hl - rw [← hl, Finsupp.total_apply, Finsupp.sum_apply] + rw [← hl, Finsupp.linearCombination_apply, Finsupp.sum_apply] apply Submodule.sum_mem _ _ rintro ⟨_, _, ⟨n', rfl⟩, _, ⟨hn', rfl⟩, m, hm, rfl⟩ - dsimp only [Subtype.coe_mk] diff --git a/Mathlib/RingTheory/FiniteType.lean b/Mathlib/RingTheory/FiniteType.lean index 6272fa5f1de4d..b0366a10493a5 100644 --- a/Mathlib/RingTheory/FiniteType.lean +++ b/Mathlib/RingTheory/FiniteType.lean @@ -122,7 +122,8 @@ theorem iff_quotient_freeAlgebra : intro x have hrw : (↑s : Set A) = fun x : A => x ∈ s.val := rfl rw [← Set.mem_range, ← AlgHom.coe_range] - erw [← adjoin_eq_range_freeAlgebra_lift, ← hrw, hs] + erw [← adjoin_eq_range_freeAlgebra_lift] + simp_rw [← hrw, hs] exact Set.mem_univ x · rintro ⟨s, ⟨f, hsur⟩⟩ exact FiniteType.of_surjective (FiniteType.freeAlgebra R s) f hsur @@ -137,7 +138,8 @@ theorem iff_quotient_mvPolynomial : use s, MvPolynomial.aeval (↑) intro x have hrw : (↑s : Set S) = fun x : S => x ∈ s.val := rfl - rw [← Set.mem_range, ← AlgHom.coe_range, ← adjoin_eq_range, ← hrw, hs] + rw [← Set.mem_range, ← AlgHom.coe_range, ← adjoin_eq_range] + simp_rw [← hrw, hs] exact Set.mem_univ x · rintro ⟨s, ⟨f, hsur⟩⟩ exact FiniteType.of_surjective (FiniteType.mvPolynomial R { x // x ∈ s }) f hsur diff --git a/Mathlib/RingTheory/Finiteness.lean b/Mathlib/RingTheory/Finiteness.lean index 208f3f7f870cb..42e2948fd00cc 100644 --- a/Mathlib/RingTheory/Finiteness.lean +++ b/Mathlib/RingTheory/Finiteness.lean @@ -35,6 +35,7 @@ In this file we define a notion of finiteness that is common in commutative alge open Function (Surjective) +open Finsupp namespace Submodule @@ -274,14 +275,14 @@ theorem fg_of_fg_map_of_fg_inf_ker {R M P : Type*} [Ring R] [AddCommGroup M] [Mo have : f x ∈ s.map f := by rw [mem_map] exact ⟨x, hx, rfl⟩ - rw [← ht1, ← Set.image_id (t1 : Set P), Finsupp.mem_span_image_iff_total] at this + rw [← ht1, ← Set.image_id (t1 : Set P), Finsupp.mem_span_image_iff_linearCombination] at this rcases this with ⟨l, hl1, hl2⟩ refine mem_sup.2 - ⟨(Finsupp.total M M R id).toFun ((Finsupp.lmapDomain R R g : (P →₀ R) → M →₀ R) l), ?_, - x - Finsupp.total M M R id ((Finsupp.lmapDomain R R g : (P →₀ R) → M →₀ R) l), ?_, + ⟨(linearCombination R id).toFun ((lmapDomain R R g : (P →₀ R) → M →₀ R) l), ?_, + x - linearCombination R id ((lmapDomain R R g : (P →₀ R) → M →₀ R) l), ?_, add_sub_cancel _ _⟩ - · rw [← Set.image_id (g '' ↑t1), Finsupp.mem_span_image_iff_total] + · rw [← Set.image_id (g '' ↑t1), Finsupp.mem_span_image_iff_linearCombination] refine ⟨_, ?_, rfl⟩ haveI : Inhabited P := ⟨0⟩ rw [← Finsupp.lmapDomain_supported _ _ g, mem_map] @@ -290,14 +291,14 @@ theorem fg_of_fg_map_of_fg_inf_ker {R M P : Type*} [Ring R] [AddCommGroup M] [Mo rw [ht2, mem_inf] constructor · apply s.sub_mem hx - rw [Finsupp.total_apply, Finsupp.lmapDomain_apply, Finsupp.sum_mapDomain_index] + rw [Finsupp.linearCombination_apply, Finsupp.lmapDomain_apply, Finsupp.sum_mapDomain_index] · refine s.sum_mem ?_ intro y hy exact s.smul_mem _ (hg y (hl1 hy)).1 · exact zero_smul _ · exact fun _ _ _ => add_smul _ _ _ · rw [LinearMap.mem_ker, f.map_sub, ← hl2] - rw [Finsupp.total_apply, Finsupp.total_apply, Finsupp.lmapDomain_apply] + rw [Finsupp.linearCombination_apply, Finsupp.linearCombination_apply, Finsupp.lmapDomain_apply] rw [Finsupp.sum_mapDomain_index, Finsupp.sum, Finsupp.sum, map_sum] · rw [sub_eq_zero] refine Finset.sum_congr rfl fun y hy => ?_ diff --git a/Mathlib/RingTheory/Flat/Basic.lean b/Mathlib/RingTheory/Flat/Basic.lean index c495efa177414..7592d42a7c793 100644 --- a/Mathlib/RingTheory/Flat/Basic.lean +++ b/Mathlib/RingTheory/Flat/Basic.lean @@ -3,17 +3,16 @@ Copyright (c) 2020 Johan Commelin. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Johan Commelin, Jujian Zhang -/ -import Mathlib.RingTheory.Noetherian -import Mathlib.Algebra.DirectSum.Module import Mathlib.Algebra.DirectSum.Finsupp -import Mathlib.Algebra.Module.Projective -import Mathlib.Algebra.Module.Injective +import Mathlib.Algebra.DirectSum.Module +import Mathlib.Algebra.Exact import Mathlib.Algebra.Module.CharacterModule +import Mathlib.Algebra.Module.Injective +import Mathlib.Algebra.Module.Projective import Mathlib.LinearAlgebra.DirectSum.TensorProduct import Mathlib.LinearAlgebra.FreeModule.Basic -import Mathlib.Algebra.Module.Projective import Mathlib.LinearAlgebra.TensorProduct.RightExactness -import Mathlib.Algebra.Exact +import Mathlib.RingTheory.Noetherian /-! # Flat modules @@ -74,6 +73,10 @@ the canonical map `I ⊗ M →ₗ M` is injective. -/ namespace Flat +variable {R} in +instance instSubalgebraToSubmodule {S : Type v} [Ring S] [Algebra R S] + (A : Subalgebra R S) [Flat R A] : Flat R (Subalgebra.toSubmodule A) := ‹Flat R A› + instance self (R : Type u) [CommRing R] : Flat R R := ⟨by intro I _ diff --git a/Mathlib/RingTheory/Flat/EquationalCriterion.lean b/Mathlib/RingTheory/Flat/EquationalCriterion.lean index 42f4b8bf28bd1..bef434517f9b0 100644 --- a/Mathlib/RingTheory/Flat/EquationalCriterion.lean +++ b/Mathlib/RingTheory/Flat/EquationalCriterion.lean @@ -144,20 +144,20 @@ theorem tfae_equational_criterion : List.TFAE [ _ = 0 := hfx obtain ⟨κ, hκ, a', y', ⟨ha'y', ha'⟩⟩ := h₄ this use κ, hκ - use Finsupp.total ι (κ →₀ R) R (fun i ↦ equivFunOnFinite.symm (a' i)) - use Finsupp.total κ M R y' + use Finsupp.linearCombination R (fun i ↦ equivFunOnFinite.symm (a' i)) + use Finsupp.linearCombination R y' constructor · apply Finsupp.basisSingleOne.ext intro i - simpa [total_apply, sum_fintype, Finsupp.single_apply] using ha'y' i + simpa [linearCombination_apply, sum_fintype, Finsupp.single_apply] using ha'y' i · ext j - simp only [total_apply, zero_smul, implies_true, sum_fintype, finset_sum_apply] + simp only [linearCombination_apply, zero_smul, implies_true, sum_fintype, finset_sum_apply] exact ha' j tfae_have 5 → 4 · intro h₅ ι hi f x hfx let f' : ι →₀ R := equivFunOnFinite.symm f - let x' : (ι →₀ R) →ₗ[R] M := Finsupp.total ι M R x - have : x' f' = 0 := by simpa [x', f', total_apply, sum_fintype] using hfx + let x' : (ι →₀ R) →ₗ[R] M := Finsupp.linearCombination R x + have : x' f' = 0 := by simpa [x', f', linearCombination_apply, sum_fintype] using hfx obtain ⟨κ, hκ, a', y', ha'y', ha'⟩ := h₅ this refine ⟨κ, hκ, fun i ↦ a' (single i 1), fun j ↦ y' (single j 1), fun i ↦ ?_, fun j ↦ ?_⟩ · simpa [x', ← map_smul, ← map_sum, smul_single] using diff --git a/Mathlib/RingTheory/Flat/Stability.lean b/Mathlib/RingTheory/Flat/Stability.lean index 27ba15c69ed04..57de113408f23 100644 --- a/Mathlib/RingTheory/Flat/Stability.lean +++ b/Mathlib/RingTheory/Flat/Stability.lean @@ -22,7 +22,7 @@ We show that flatness is stable under composition and base change. then `S ⊗[R] M` is `S`-flat. * `Module.Flat.of_isLocalizedModule`: if `M` is a flat `R`-module and `S` is a submonoid of `R` then the localization of `M` at `S` is flat as a module - for the localzation of `R` at `S`. + for the localization of `R` at `S`. -/ universe u v w t diff --git a/Mathlib/RingTheory/FractionalIdeal/Basic.lean b/Mathlib/RingTheory/FractionalIdeal/Basic.lean index 155b25b1b2ad7..4ebe1fa201f1f 100644 --- a/Mathlib/RingTheory/FractionalIdeal/Basic.lean +++ b/Mathlib/RingTheory/FractionalIdeal/Basic.lean @@ -462,6 +462,10 @@ theorem sup_eq_add (I J : FractionalIdeal S P) : I ⊔ J = I + J := theorem coe_add (I J : FractionalIdeal S P) : (↑(I + J) : Submodule R P) = I + J := rfl +theorem mem_add (I J : FractionalIdeal S P) (x : P) : + x ∈ I + J ↔ ∃ i ∈ I, ∃ j ∈ J, i + j = x := by + rw [← mem_coe, coe_add, Submodule.add_eq_sup]; exact Submodule.mem_sup + @[simp, norm_cast] theorem coeIdeal_sup (I J : Ideal R) : ↑(I ⊔ J) = (I + J : FractionalIdeal S P) := coeToSubmodule_injective <| coeSubmodule_sup _ _ _ diff --git a/Mathlib/RingTheory/FractionalIdeal/Extended.lean b/Mathlib/RingTheory/FractionalIdeal/Extended.lean new file mode 100644 index 0000000000000..c2dcadde7c9b5 --- /dev/null +++ b/Mathlib/RingTheory/FractionalIdeal/Extended.lean @@ -0,0 +1,111 @@ +/- +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.RingTheory.FractionalIdeal.Basic + +/-! +# Extension of fractional ideals + +This file defines the extension of a fractional ideal along a ring homomorphism. + +## Main definition + +* `FractionalIdeal.extended`: Let `A` and `B` be commutative rings with respective localizations + `IsLocalization M K` and `IsLocalization N L`. Let `f : A →+* B` be a ring homomorphism with + `hf : M ≤ Submonoid.comap f N`. If `I : FractionalIdeal M K`, then the extension of `I` along + `f` is `extended L hf I : FractionalIdeal N L`. + +## Main results + +* `extended_add` says that extension commutes with addition. +* `extended_mul` says that extension commutes with multiplication. + +## Tags + +fractional ideal, fractional ideals, extended, extension +-/ + +open IsLocalization FractionalIdeal Submodule + +namespace FractionalIdeal + +variable {A : Type*} [CommRing A] {B : Type*} [CommRing B] {f : A →+* B} +variable {K : Type*} {M : Submonoid A} [CommRing K] [Algebra A K] [IsLocalization M K] +variable (L : Type*) {N : Submonoid B} [CommRing L] [Algebra B L] [IsLocalization N L] +variable (hf : M ≤ Submonoid.comap f N) +variable (I : FractionalIdeal M K) (J : FractionalIdeal M K) + +/-- Given commutative rings `A` and `B` with respective localizations `IsLocalization M K` and +`IsLocalization N L`, and a ring homomorphism `f : A →+* B` satisfying `M ≤ Submonoid.comap f N`, a +fractional ideal `I` of `A` can be extended along `f` to a fractional ideal of `B`. -/ +def extended (I : FractionalIdeal M K) : FractionalIdeal N L where + val := span B <| (IsLocalization.map (S := K) L f hf) '' I + property := by + have ⟨a, ha, frac⟩ := I.isFractional + refine ⟨f a, hf ha, fun b hb ↦ ?_⟩ + refine span_induction hb (fun x hx ↦ ?_) ⟨0, by simp⟩ + (fun x y hx hy ↦ smul_add (f a) x y ▸ isInteger_add hx hy) (fun b c hc ↦ ?_) + · rcases hx with ⟨k, kI, rfl⟩ + obtain ⟨c, hc⟩ := frac k kI + exact ⟨f c, by simp [← IsLocalization.map_smul, ← hc]⟩ + · rw [← smul_assoc, smul_eq_mul, mul_comm (f a), ← smul_eq_mul, smul_assoc] + exact isInteger_smul hc + +local notation "map_f" => (IsLocalization.map (S := K) L f hf) + +lemma mem_extended_iff (x : L) : (x ∈ I.extended L hf) ↔ x ∈ span B (map_f '' I) := by + constructor <;> { intro hx; simpa } + +@[simp] +lemma coe_extended_eq_span : I.extended L hf = span B (map_f '' I) := by + ext; simp [mem_coe, mem_extended_iff] + +@[simp] +theorem extended_zero : extended L hf (0 : FractionalIdeal M K) = 0 := + have : ((0 : FractionalIdeal M K) : Set K) = {0} := by ext; simp + coeToSubmodule_injective (by simp [this]) + +@[simp] +theorem extended_one : extended L hf (1 : FractionalIdeal M K) = 1 := by + refine coeToSubmodule_injective <| Submodule.ext fun x ↦ ⟨fun hx ↦ span_induction hx + ?_ (zero_mem _) (fun y z hy hz ↦ add_mem hy hz) (fun b y hy ↦ smul_mem _ b hy), ?_⟩ + · rintro ⟨b, _, rfl⟩ + rw [Algebra.linearMap_apply, Algebra.algebraMap_eq_smul_one] + exact smul_mem _ _ <| subset_span ⟨1, by simp [one_mem_one]⟩ + · rintro _ ⟨_, ⟨a, ha, rfl⟩, rfl⟩ + exact ⟨f a, ha, by rw [Algebra.linearMap_apply, Algebra.linearMap_apply, map_eq]⟩ + +theorem extended_add : (I + J).extended L hf = (I.extended L hf) + (J.extended L hf) := by + apply coeToSubmodule_injective + simp only [coe_extended_eq_span, coe_add, Submodule.add_eq_sup, ← span_union, ← Set.image_union] + apply Submodule.span_eq_span + · rintro _ ⟨y, hy, rfl⟩ + obtain ⟨i, hi, j, hj, rfl⟩ := (mem_add I J y).mp <| SetLike.mem_coe.mp hy + rw [RingHom.map_add] + exact add_mem (Submodule.subset_span ⟨i, Set.mem_union_left _ hi, by simp⟩) + (Submodule.subset_span ⟨j, Set.mem_union_right _ hj, by simp⟩) + · rintro _ ⟨y, hy, rfl⟩ + suffices y ∈ I + J from SetLike.mem_coe.mpr <| Submodule.subset_span ⟨y, by simp [this]⟩ + exact hy.elim (fun h ↦ (mem_add I J y).mpr ⟨y, h, 0, zero_mem J, add_zero y⟩) + (fun h ↦ (mem_add I J y).mpr ⟨0, zero_mem I, y, h, zero_add y⟩) + +theorem extended_mul : (I * J).extended L hf = (I.extended L hf) * (J.extended L hf) := by + apply coeToSubmodule_injective + simp only [coe_extended_eq_span, coe_mul, span_mul_span] + refine Submodule.span_eq_span (fun _ h ↦ ?_) (fun _ h ↦ ?_) + · rcases h with ⟨x, hx, rfl⟩ + replace hx : x ∈ (I : Submodule A K) * (J : Submodule A K) := coe_mul I J ▸ hx + rw [Submodule.mul_eq_span_mul_set] at hx + refine span_induction hx (fun y hy ↦ ?_) (by simp) (fun y z hy hz ↦ ?_) (fun a y hy ↦ ?_) + · rcases Set.mem_mul.mp hy with ⟨i, hi, j, hj, rfl⟩ + exact subset_span <| Set.mem_mul.mpr + ⟨map_f i, ⟨i, hi, by simp [hi]⟩, map_f j, ⟨j, hj, by simp [hj]⟩, by simp⟩ + · exact map_add map_f y z ▸ Submodule.add_mem _ hy hz + · rw [Algebra.smul_def, map_mul, map_eq, ← Algebra.smul_def] + exact smul_mem _ (f a) hy + · rcases Set.mem_mul.mp h with ⟨y, ⟨i, hi, rfl⟩, z, ⟨j, hj, rfl⟩, rfl⟩ + exact Submodule.subset_span ⟨i * j, mul_mem_mul hi hj, by simp⟩ + +end FractionalIdeal diff --git a/Mathlib/RingTheory/FractionalIdeal/Operations.lean b/Mathlib/RingTheory/FractionalIdeal/Operations.lean index 56982ee5c698d..50c15f91c6b62 100644 --- a/Mathlib/RingTheory/FractionalIdeal/Operations.lean +++ b/Mathlib/RingTheory/FractionalIdeal/Operations.lean @@ -226,7 +226,7 @@ theorem canonicalEquiv_symm : (canonicalEquiv S P P').symm = canonicalEquiv S P' exact ⟨fun ⟨y, mem, Eq⟩ => ⟨y, mem, Eq⟩, fun ⟨y, mem, Eq⟩ => ⟨y, mem, Eq⟩⟩ theorem canonicalEquiv_flip (I) : canonicalEquiv S P P' (canonicalEquiv S P' P I) = I := by - rw [← canonicalEquiv_symm]; erw [RingEquiv.apply_symm_apply] + rw [← canonicalEquiv_symm, RingEquiv.symm_apply_apply] @[simp] theorem canonicalEquiv_canonicalEquiv (P'' : Type*) [CommRing P''] [Algebra R P''] @@ -454,7 +454,7 @@ theorem eq_one_div_of_mul_eq_one_right (I J : FractionalIdeal R₁⁰ K) (h : I apply (le_div_iff_of_nonzero hI).mpr _ intro y hy x hx rw [mul_comm] - exact mul_mem_mul hx hy + exact mul_mem_mul hy hx theorem mul_div_self_cancel_iff {I : FractionalIdeal R₁⁰ K} : I * (1 / I) = 1 ↔ ∃ J, I * J = 1 := ⟨fun h => ⟨1 / I, h⟩, fun ⟨J, hJ⟩ => by rwa [← eq_one_div_of_mul_eq_one_right I J hJ]⟩ diff --git a/Mathlib/RingTheory/Generators.lean b/Mathlib/RingTheory/Generators.lean index 0aac65c1e9c25..8cd1cdb774bff 100644 --- a/Mathlib/RingTheory/Generators.lean +++ b/Mathlib/RingTheory/Generators.lean @@ -45,7 +45,7 @@ variable (R : Type u) (S : Type v) [CommRing R] [CommRing S] [Algebra R S] 2. `val : vars → S`: The assignment of each variable to a value in `S`. 3. `σ`: A section of `R[X] → S`. -/ structure Algebra.Generators where - /-- The type of variables. -/ + /-- The type of variables. -/ vars : Type w /-- The assignment of each variable to a value in `S`. -/ val : vars → S @@ -157,7 +157,7 @@ end Localization variable {T} [CommRing T] [Algebra R T] [Algebra S T] [IsScalarTower R S T] /-- Given two families of generators `S[X] → T` and `R[Y] → S`, -we may constuct the family of generators `R[X, Y] → T`. -/ +we may construct the family of generators `R[X, Y] → T`. -/ @[simps val, simps (config := .lemmasOnly) vars σ] noncomputable def comp (Q : Generators S T) (P : Generators R S) : Generators R T where @@ -166,7 +166,7 @@ def comp (Q : Generators S T) (P : Generators R S) : Generators R T where σ' x := (Q.σ x).sum (fun n r ↦ rename Sum.inr (P.σ r) * monomial (n.mapDomain Sum.inl) 1) aeval_val_σ' s := by have (x : P.Ring) : aeval (algebraMap S T ∘ P.val) x = algebraMap S T (aeval P.val x) := by - rw [map_aeval, aeval_def, coe_eval₂Hom, ← IsScalarTower.algebraMap_eq, Function.comp] + rw [map_aeval, aeval_def, coe_eval₂Hom, ← IsScalarTower.algebraMap_eq, Function.comp_def] conv_rhs => rw [← Q.aeval_val_σ s, ← (Q.σ s).sum_single] simp only [map_finsupp_sum, map_mul, aeval_rename, Sum.elim_comp_inr, this, aeval_val_σ, aeval_monomial, map_one, Finsupp.prod_mapDomain_index_inj Sum.inl_injective, Sum.elim_inl, @@ -381,10 +381,10 @@ instance : AddCommGroup P.Cotangent := inferInstanceAs (AddCommGroup P.ker.Cotan variable {P} -/-- The identity map `P.ker.Cotangent → P.Cotangent` into the type synonym. -/ +/-- The identity map `P.ker.Cotangent → P.Cotangent` into the type synonym. -/ def Cotangent.of (x : P.ker.Cotangent) : P.Cotangent := x -/-- The identity map `P.Cotangent → P.ker.Cotangent` from the type synonym. -/ +/-- The identity map `P.Cotangent → P.ker.Cotangent` from the type synonym. -/ def Cotangent.val (x : P.Cotangent) : P.ker.Cotangent := x @[ext] diff --git a/Mathlib/RingTheory/GradedAlgebra/Basic.lean b/Mathlib/RingTheory/GradedAlgebra/Basic.lean index de86d0cc60388..0d6693692b34f 100644 --- a/Mathlib/RingTheory/GradedAlgebra/Basic.lean +++ b/Mathlib/RingTheory/GradedAlgebra/Basic.lean @@ -207,7 +207,7 @@ end DirectSum open DirectSum -/-- The projection maps of graded algebra-/ +/-- The projection maps of graded algebra -/ def GradedAlgebra.proj (𝒜 : ι → Submodule R A) [GradedAlgebra 𝒜] (i : ι) : A →ₗ[R] A := (𝒜 i).subtype.comp <| (DFinsupp.lapply i).comp <| (decomposeAlgEquiv 𝒜).toAlgHom.toLinearMap @@ -350,7 +350,7 @@ noncomputable def coeAlgEquiv (hM : DirectSum.IsInternal M) : /-- Given an `R`-algebra `A` and a family `ι → Submodule R A` of submodules parameterized by an additive monoid `ι` -and statisfying `SetLike.GradedMonoid M` (essentially, is multiplicative) +and satisfying `SetLike.GradedMonoid M` (essentially, is multiplicative) such that `DirectSum.IsInternal M` (`A` is the direct sum of the `M i`), we endow `A` with the structure of a graded algebra. The submodules are the *homogeneous* parts. -/ diff --git a/Mathlib/RingTheory/GradedAlgebra/HomogeneousIdeal.lean b/Mathlib/RingTheory/GradedAlgebra/HomogeneousIdeal.lean index f19c6b57a7077..dc2ec96afc47a 100644 --- a/Mathlib/RingTheory/GradedAlgebra/HomogeneousIdeal.lean +++ b/Mathlib/RingTheory/GradedAlgebra/HomogeneousIdeal.lean @@ -154,10 +154,10 @@ theorem Ideal.mul_homogeneous_element_mem_of_mem {I : Ideal A} (r x : A) (hx₁ theorem Ideal.homogeneous_span (s : Set A) (h : ∀ x ∈ s, Homogeneous 𝒜 x) : (Ideal.span s).IsHomogeneous 𝒜 := by rintro i r hr - rw [Ideal.span, Finsupp.span_eq_range_total] at hr + rw [Ideal.span, Finsupp.span_eq_range_linearCombination] at hr rw [LinearMap.mem_range] at hr obtain ⟨s, rfl⟩ := hr - rw [Finsupp.total_apply, Finsupp.sum, decompose_sum, DFinsupp.finset_sum_apply, + rw [Finsupp.linearCombination_apply, Finsupp.sum, decompose_sum, DFinsupp.finset_sum_apply, AddSubmonoidClass.coe_finset_sum] refine Ideal.sum_mem _ ?_ rintro z hz1 diff --git a/Mathlib/RingTheory/GradedAlgebra/HomogeneousLocalization.lean b/Mathlib/RingTheory/GradedAlgebra/HomogeneousLocalization.lean index 10ab27fe2e406..c3721f85c4ec5 100644 --- a/Mathlib/RingTheory/GradedAlgebra/HomogeneousLocalization.lean +++ b/Mathlib/RingTheory/GradedAlgebra/HomogeneousLocalization.lean @@ -603,7 +603,7 @@ def map (g : A →+* B) /-- Let `A` be a graded algebra and `P ≤ Q` be two submonoids, then the homogeneous localization of `A` -at `P` embedds into the homogeneous localization of `A` at `Q`. +at `P` embeds into the homogeneous localization of `A` at `Q`. -/ abbrev mapId {P Q : Submonoid A} (h : P ≤ Q) : HomogeneousLocalization 𝒜 P →+* HomogeneousLocalization 𝒜 Q := diff --git a/Mathlib/RingTheory/GradedAlgebra/Radical.lean b/Mathlib/RingTheory/GradedAlgebra/Radical.lean index 8d91baaa58401..976b7748f818d 100644 --- a/Mathlib/RingTheory/GradedAlgebra/Radical.lean +++ b/Mathlib/RingTheory/GradedAlgebra/Radical.lean @@ -168,7 +168,7 @@ theorem Ideal.IsHomogeneous.radical {I : Ideal A} (h : I.IsHomogeneous 𝒜) : rw [h.radical_eq] exact Ideal.IsHomogeneous.sInf fun _ => And.left -/-- The radical of a homogenous ideal, as another homogenous ideal. -/ +/-- The radical of a homogeneous ideal, as another homogeneous ideal. -/ def HomogeneousIdeal.radical (I : HomogeneousIdeal 𝒜) : HomogeneousIdeal 𝒜 := ⟨I.toIdeal.radical, I.isHomogeneous.radical⟩ diff --git a/Mathlib/RingTheory/HahnSeries/PowerSeries.lean b/Mathlib/RingTheory/HahnSeries/PowerSeries.lean index e37029a7b20db..1441d746ae5c7 100644 --- a/Mathlib/RingTheory/HahnSeries/PowerSeries.lean +++ b/Mathlib/RingTheory/HahnSeries/PowerSeries.lean @@ -87,7 +87,7 @@ theorem ofPowerSeries_injective : Function.Injective (ofPowerSeries Γ R) := embDomain_injective.comp toPowerSeries.symm.injective /-@[simp] Porting note: removing simp. RHS is more complicated and it makes linter -failures elsewhere-/ +failures elsewhere -/ theorem ofPowerSeries_apply (x : PowerSeries R) : ofPowerSeries Γ R x = HahnSeries.embDomain diff --git a/Mathlib/RingTheory/HahnSeries/Valuation.lean b/Mathlib/RingTheory/HahnSeries/Valuation.lean index 86b6d16e4a9a0..95c72f7dfe144 100644 --- a/Mathlib/RingTheory/HahnSeries/Valuation.lean +++ b/Mathlib/RingTheory/HahnSeries/Valuation.lean @@ -35,7 +35,7 @@ section Valuation variable (Γ R) [LinearOrderedCancelAddCommMonoid Γ] [Ring R] [IsDomain R] /-- The additive valuation on `HahnSeries Γ R`, returning the smallest index at which - a Hahn Series has a nonzero coefficient, or `⊤` for the 0 series. -/ + a Hahn Series has a nonzero coefficient, or `⊤` for the 0 series. -/ def addVal : AddValuation (HahnSeries Γ R) (WithTop Γ) := AddValuation.of orderTop orderTop_zero (orderTop_one) (fun x y => min_orderTop_le_orderTop_add) fun x y => by diff --git a/Mathlib/RingTheory/Ideal/Basic.lean b/Mathlib/RingTheory/Ideal/Basic.lean index bb631626fa74b..b54b293c33f77 100644 --- a/Mathlib/RingTheory/Ideal/Basic.lean +++ b/Mathlib/RingTheory/Ideal/Basic.lean @@ -35,7 +35,7 @@ open Set Function open Pointwise /-- A (left) ideal in a semiring `R` is an additive submonoid `s` such that -`a * b ∈ s` whenever `b ∈ s`. If `R` is a ring, then `s` is an additive subgroup. -/ +`a * b ∈ s` whenever `b ∈ s`. If `R` is a ring, then `s` is an additive subgroup. -/ abbrev Ideal (R : Type u) [Semiring R] := Submodule R R @@ -76,9 +76,9 @@ theorem sum_mem (I : Ideal α) {ι : Type*} {t : Finset ι} {f : ι → α} : theorem eq_top_of_unit_mem (x y : α) (hx : x ∈ I) (h : y * x = 1) : I = ⊤ := eq_top_iff.2 fun z _ => calc - z = z * (y * x) := by simp [h] - _ = z * y * x := Eq.symm <| mul_assoc z y x - _ ∈ I := I.mul_mem_left _ hx + z * y * x ∈ I := I.mul_mem_left _ hx + _ = z * (y * x) := mul_assoc z y x + _ = z := by rw [h, mul_one] theorem eq_top_of_isUnit_mem {x} (hx : x ∈ I) (h : IsUnit x) : I = ⊤ := let ⟨y, hy⟩ := h.exists_left_inv @@ -570,7 +570,7 @@ theorem span_pow_eq_top (s : Set α) (hs : span s = ⊤) (n : ℕ) : · rw [Set.image_empty, hs] trivial · exact subset_span ⟨_, hx, pow_zero _⟩ - rw [eq_top_iff_one, span, Finsupp.mem_span_iff_total] at hs + rw [eq_top_iff_one, span, Finsupp.mem_span_iff_linearCombination] at hs rcases hs with ⟨f, hf⟩ have hf : (f.support.sum fun a => f a * a) = 1 := hf -- Porting note: was `change ... at hf` have := sum_pow_mem_span_pow f.support (fun a => f a * a) n diff --git a/Mathlib/RingTheory/Ideal/Cotangent.lean b/Mathlib/RingTheory/Ideal/Cotangent.lean index 3156cab853769..948ea0ff4843f 100644 --- a/Mathlib/RingTheory/Ideal/Cotangent.lean +++ b/Mathlib/RingTheory/Ideal/Cotangent.lean @@ -149,8 +149,9 @@ theorem cotangentEquivIdeal_apply (x : I.Cotangent) : theorem cotangentEquivIdeal_symm_apply (x : R) (hx : x ∈ I) : -- Note: #8386 had to specify `(R₂ := R)` because `I.toCotangent` suggested `R ⧸ I^2` instead - I.cotangentEquivIdeal.symm ⟨(I ^ 2).mkQ x, Submodule.mem_map_of_mem (R₂ := R) hx⟩ = - I.toCotangent ⟨x, hx⟩ := by + I.cotangentEquivIdeal.symm ⟨(I ^ 2).mkQ x, + Submodule.mem_map_of_mem (F := R →ₗ[R] R ⧸ I ^ 2) (f := (I ^ 2).mkQ) hx⟩ = + I.toCotangent (R := R) ⟨x, hx⟩ := by apply I.cotangentEquivIdeal.injective rw [I.cotangentEquivIdeal.apply_symm_apply] ext diff --git a/Mathlib/RingTheory/Ideal/Maps.lean b/Mathlib/RingTheory/Ideal/Maps.lean index 04c32e6e803d6..8b0482cf861a6 100644 --- a/Mathlib/RingTheory/Ideal/Maps.lean +++ b/Mathlib/RingTheory/Ideal/Maps.lean @@ -220,7 +220,7 @@ theorem smul_restrictScalars {R S M} [CommSemiring R] [CommSemiring S] (I.map (algebraMap R S) • N).restrictScalars R = I • N.restrictScalars R := by simp_rw [map, Submodule.span_smul_eq, ← Submodule.coe_set_smul, Submodule.set_smul_eq_iSup, ← element_smul_restrictScalars, iSup_image] - exact (_root_.map_iSup₂ (Submodule.restrictScalarsLatticeHom R S M) _) + exact map_iSup₂ (Submodule.restrictScalarsLatticeHom R S M) _ @[simp] theorem smul_top_eq_map {R S : Type*} [CommSemiring R] [CommSemiring S] [Algebra R S] diff --git a/Mathlib/RingTheory/Ideal/Operations.lean b/Mathlib/RingTheory/Ideal/Operations.lean index a31ec62d4e7be..839647966fb3a 100644 --- a/Mathlib/RingTheory/Ideal/Operations.lean +++ b/Mathlib/RingTheory/Ideal/Operations.lean @@ -6,6 +6,8 @@ Authors: Kenny Lau import Mathlib.Algebra.Algebra.Operations import Mathlib.Data.Fintype.Lattice import Mathlib.RingTheory.Coprime.Lemmas +import Mathlib.RingTheory.NonUnitalSubring.Basic +import Mathlib.RingTheory.NonUnitalSubsemiring.Basic /-! # More operations on modules and ideals @@ -1185,16 +1187,16 @@ variable (ι : Type*) variable (M : Type*) [AddCommGroup M] {R : Type*} [CommRing R] [Module R M] (I : Ideal R) variable (v : ι → M) (hv : Submodule.span R (Set.range v) = ⊤) -/-- A variant of `Finsupp.total` that takes in vectors valued in `I`. -/ +/-- A variant of `Finsupp.linearCombination` that takes in vectors valued in `I`. -/ noncomputable def finsuppTotal : (ι →₀ I) →ₗ[R] M := - (Finsupp.total ι M R v).comp (Finsupp.mapRange.linearMap I.subtype) + (Finsupp.linearCombination R v).comp (Finsupp.mapRange.linearMap I.subtype) variable {ι M v} theorem finsuppTotal_apply (f : ι →₀ I) : finsuppTotal ι M I v f = f.sum fun i x => (x : R) • v i := by dsimp [finsuppTotal] - rw [Finsupp.total_apply, Finsupp.sum_mapRange_index] + rw [Finsupp.linearCombination_apply, Finsupp.sum_mapRange_index] exact fun _ => zero_smul _ _ theorem finsuppTotal_apply_eq_of_fintype [Fintype ι] (f : ι →₀ I) : @@ -1209,7 +1211,8 @@ theorem range_finsuppTotal : refine ⟨fun ⟨f, h⟩ => ⟨Finsupp.mapRange.linearMap I.subtype f, fun i => (f i).2, h⟩, ?_⟩ rintro ⟨a, ha, rfl⟩ classical - refine ⟨a.mapRange (fun r => if h : r ∈ I then ⟨r, h⟩ else 0) (by simp), ?_⟩ + refine ⟨a.mapRange (fun r => if h : r ∈ I then ⟨r, h⟩ else 0) + (by simp only [Submodule.zero_mem, ↓reduceDIte]; rfl), ?_⟩ rw [finsuppTotal_apply, Finsupp.sum_mapRange_index] · apply Finsupp.sum_congr intro i _ @@ -1273,3 +1276,7 @@ theorem set_smul_top_eq_span (s : Set R) : Eq.trans (smul_eq_mul (Ideal R)) (Ideal.mul_top (.span s)) end Submodule + +instance {R} [Semiring R] : NonUnitalSubsemiringClass (Ideal R) R where + mul_mem _ hb := Ideal.mul_mem_left _ _ hb +instance {R} [Ring R] : NonUnitalSubringClass (Ideal R) R where diff --git a/Mathlib/RingTheory/Idempotents.lean b/Mathlib/RingTheory/Idempotents.lean index 84922b3c3220e..2e8db654b863c 100644 --- a/Mathlib/RingTheory/Idempotents.lean +++ b/Mathlib/RingTheory/Idempotents.lean @@ -109,7 +109,7 @@ variable {I : Type*} (e : I → R) @[mk_iff] structure OrthogonalIdempotents : Prop where idem : ∀ i, IsIdempotentElem (e i) - ortho : ∀ i j, i ≠ j → e i * e j = 0 + ortho : Pairwise (e · * e · = 0) variable {e} @@ -117,17 +117,27 @@ lemma OrthogonalIdempotents.mul_eq [DecidableEq I] (he : OrthogonalIdempotents e e i * e j = if i = j then e i else 0 := by split · simp [*, (he.idem j).eq] - · exact he.ortho _ _ ‹_› + · exact he.ortho ‹_› lemma OrthogonalIdempotents.iff_mul_eq [DecidableEq I] : OrthogonalIdempotents e ↔ ∀ i j, e i * e j = if i = j then e i else 0 := ⟨mul_eq, fun H ↦ ⟨fun i ↦ by simpa using H i i, fun i j e ↦ by simpa [e] using H i j⟩⟩ -lemma OrthogonalIdempotents.isIdempotentElem_sum [Fintype I] (he : OrthogonalIdempotents e) : - IsIdempotentElem (∑ i, e i) := by +lemma OrthogonalIdempotents.isIdempotentElem_sum (he : OrthogonalIdempotents e) {s : Finset I} : + IsIdempotentElem (∑ i ∈ s, e i) := by classical simp [IsIdempotentElem, Finset.sum_mul, Finset.mul_sum, he.mul_eq] +lemma OrthogonalIdempotents.mul_sum_of_mem (he : OrthogonalIdempotents e) + {i : I} {s : Finset I} (h : i ∈ s) : e i * ∑ j ∈ s, e j = e i := by + classical + simp [Finset.mul_sum, he.mul_eq, h] + +lemma OrthogonalIdempotents.mul_sum_of_not_mem (he : OrthogonalIdempotents e) + {i : I} {s : Finset I} (h : i ∉ s) : e i * ∑ j ∈ s, e j = 0 := by + classical + simp [Finset.mul_sum, he.mul_eq, h] + lemma OrthogonalIdempotents.map (he : OrthogonalIdempotents e) : OrthogonalIdempotents (f ∘ e) := by classical @@ -150,7 +160,7 @@ lemma OrthogonalIdempotents.equiv {J} (i : J ≃ I) : lemma OrthogonalIdempotents.unique [Unique I] : OrthogonalIdempotents e ↔ IsIdempotentElem (e default) := by - simp [orthogonalIdempotents_iff, Unique.forall_iff] + simp only [orthogonalIdempotents_iff, Unique.forall_iff, Subsingleton.pairwise, and_true] lemma OrthogonalIdempotents.option (he : OrthogonalIdempotents e) [Fintype I] (x) (hx : IsIdempotentElem x) (hx₁ : x * ∑ i, e i = 0) (hx₂ : (∑ i, e i) * x = 0) : @@ -164,7 +174,7 @@ lemma OrthogonalIdempotents.option (he : OrthogonalIdempotents e) [Fintype I] (x ↓reduceIte, zero_mul] using congr_arg (· * e j) hx₁ · simpa only [Option.elim_some, Option.elim_none, ← mul_assoc, Finset.mul_sum, he.mul_eq, Finset.sum_ite_eq, Finset.mem_univ, ↓reduceIte, mul_zero] using congr_arg (e i * ·) hx₂ - · exact he.ortho i j (Option.some_inj.ne.mp ne) + · exact he.ortho (Option.some_inj.ne.mp ne) lemma OrthogonalIdempotents.lift_of_isNilpotent_ker_aux (h : ∀ x ∈ RingHom.ker f, IsNilpotent x) @@ -208,14 +218,13 @@ variable (he : CompleteOrthogonalIdempotents e) lemma CompleteOrthogonalIdempotents.unique_iff [Unique I] : CompleteOrthogonalIdempotents e ↔ e default = 1 := by - rw [completeOrthogonalIdempotents_iff, orthogonalIdempotents_iff] - simp only [Unique.forall_iff, ne_eq, not_true_eq_false, false_implies, and_true, - Finset.univ_unique, Finset.sum_singleton, and_iff_right_iff_imp] + rw [completeOrthogonalIdempotents_iff, OrthogonalIdempotents.unique, Fintype.sum_unique, + and_iff_right_iff_imp] exact (· ▸ IsIdempotentElem.one) lemma CompleteOrthogonalIdempotents.pair_iff {x y : R} : CompleteOrthogonalIdempotents ![x, y] ↔ IsIdempotentElem x ∧ y = 1 - x := by - rw [completeOrthogonalIdempotents_iff, orthogonalIdempotents_iff, and_assoc] + rw [completeOrthogonalIdempotents_iff, orthogonalIdempotents_iff, and_assoc, Pairwise] simp only [Nat.succ_eq_add_one, Nat.reduceAdd, Fin.forall_fin_two, Fin.isValue, Matrix.cons_val_zero, Matrix.cons_val_one, Matrix.head_cons, ne_eq, not_true_eq_false, false_implies, zero_ne_one, not_false_eq_true, true_implies, true_and, one_ne_zero, @@ -358,7 +367,15 @@ lemma OrthogonalIdempotents.surjective_pi {I : Type*} [Finite I] {e : I → R} exact ⟨x, by ext i; simp [Ideal.quotientInfToPiQuotient]⟩ intros i j hij rw [Ideal.isCoprime_span_singleton_iff] - exact ⟨1, e i, by simp [mul_sub, sub_mul, he.ortho i j hij]⟩ + exact ⟨1, e i, by simp [mul_sub, sub_mul, he.ortho hij]⟩ + +lemma OrthogonalIdempotents.prod_one_sub {I : Type*} {e : I → R} + (he : OrthogonalIdempotents e) (s : Finset I) : + ∏ i ∈ s, (1 - e i) = 1 - ∑ i ∈ s, e i := by + induction s using Finset.cons_induction with + | empty => simp + | cons a s has ih => + simp [ih, sub_mul, mul_sub, he.mul_sum_of_not_mem has, sub_sub] variable {I : Type*} [Fintype I] {e : I → R} @@ -369,18 +386,8 @@ theorem CompleteOrthogonalIdempotents.of_ker_isNilpotent (h : ∀ x ∈ RingHom. of_ker_isNilpotent_of_isMulCentral f h he (fun _ ↦ Semigroup.mem_center_iff.mpr (mul_comm · _)) he' -lemma OrthogonalIdempotents.prod_one_sub (he : OrthogonalIdempotents e) : - ∏ i, (1 - e i) = 1 - ∑ i, e i := by - classical - induction' (@Finset.univ I _) using Finset.induction_on with a s has ih - · simp - · suffices (1 - e a) * (1 - ∑ i in s, e i) = 1 - (e a + ∑ i in s, e i) by simp [*] - have : e a * ∑ i in s, e i = 0 := by - rw [Finset.mul_sum, ← Finset.sum_const_zero (s := s)] - exact Finset.sum_congr rfl fun j hj ↦ he.ortho a j (fun e ↦ has (e ▸ hj)) - rw [sub_mul, mul_sub, mul_sub, one_mul, mul_one, one_mul, this, sub_zero, sub_sub, add_comm] - -lemma CompleteOrthogonalIdempotents.prod_one_sub (he : CompleteOrthogonalIdempotents e) : +lemma CompleteOrthogonalIdempotents.prod_one_sub + (he : CompleteOrthogonalIdempotents e) : ∏ i, (1 - e i) = 0 := by rw [he.1.prod_one_sub, he.complete, sub_self] diff --git a/Mathlib/RingTheory/Int/Basic.lean b/Mathlib/RingTheory/Int/Basic.lean index 99efaa6a6e662..2f194c3abb9aa 100644 --- a/Mathlib/RingTheory/Int/Basic.lean +++ b/Mathlib/RingTheory/Int/Basic.lean @@ -138,7 +138,7 @@ alias eq_pow_of_mul_eq_pow_bit1_left := eq_pow_of_mul_eq_pow_odd_left theorem eq_pow_of_mul_eq_pow_odd_right {a b c : ℤ} (hab : IsCoprime a b) {k : ℕ} (hk : Odd k) (h : a * b = c ^ k) : ∃ d, b = d ^ k := - eq_pow_of_mul_eq_pow_odd_left hab.symm hk (by rwa [mul_comm] at h) + eq_pow_of_mul_eq_pow_odd_left (c := c) hab.symm hk (by rwa [mul_comm] at h) @[deprecated (since := "2024-07-12")] alias eq_pow_of_mul_eq_pow_bit1_right := eq_pow_of_mul_eq_pow_odd_right diff --git a/Mathlib/RingTheory/IntegralClosure/Algebra/Basic.lean b/Mathlib/RingTheory/IntegralClosure/Algebra/Basic.lean index c84cfb1553f9f..ccb893e5a0cc6 100644 --- a/Mathlib/RingTheory/IntegralClosure/Algebra/Basic.lean +++ b/Mathlib/RingTheory/IntegralClosure/Algebra/Basic.lean @@ -33,23 +33,28 @@ section variable {A B : Type*} [Ring A] [Ring B] [Algebra R A] [Algebra R B] variable (f : A →ₐ[R] B) (hf : Function.Injective f) +theorem Algebra.IsIntegral.of_injective (hf : Function.Injective f) [Algebra.IsIntegral R B] : + Algebra.IsIntegral R A := + ⟨fun _ ↦ (isIntegral_algHom_iff f hf).mp (isIntegral _)⟩ + end instance Module.End.isIntegral {M : Type*} [AddCommGroup M] [Module R M] [Module.Finite R M] : Algebra.IsIntegral R (Module.End R M) := ⟨LinearMap.exists_monic_and_aeval_eq_zero R⟩ -variable (R) +variable (R) in theorem IsIntegral.of_finite [Module.Finite R B] (x : B) : IsIntegral R x := (isIntegral_algHom_iff (Algebra.lmul R B) Algebra.lmul_injective).mp (Algebra.IsIntegral.isIntegral _) -variable (B) +theorem isIntegral_of_noetherian (_ : IsNoetherian R B) (x : B) : IsIntegral R x := + .of_finite R x + +variable (R B) in instance Algebra.IsIntegral.of_finite [Module.Finite R B] : Algebra.IsIntegral R B := ⟨.of_finite R⟩ -variable {R B} - /-- If `S` is a sub-`R`-algebra of `A` and `S` is finitely-generated as an `R`-module, then all elements of `S` are integral over `R`. -/ theorem IsIntegral.of_mem_of_fg {A} [Ring A] [Algebra R A] (S : Subalgebra R A) @@ -57,6 +62,61 @@ theorem IsIntegral.of_mem_of_fg {A} [Ring A] [Algebra R A] (S : Subalgebra R A) have : Module.Finite R S := ⟨(fg_top _).mpr HS⟩ (isIntegral_algHom_iff S.val Subtype.val_injective).mpr (.of_finite R (⟨x, hx⟩ : S)) +theorem isIntegral_of_submodule_noetherian (S : Subalgebra R B) + (H : IsNoetherian R (Subalgebra.toSubmodule S)) (x : B) (hx : x ∈ S) : IsIntegral R x := + .of_mem_of_fg _ ((fg_top _).mp <| H.noetherian _) _ hx + +/-- Suppose `A` is an `R`-algebra, `M` is an `A`-module such that `a • m ≠ 0` for all non-zero `a` +and `m`. If `x : A` fixes a nontrivial f.g. `R`-submodule `N` of `M`, then `x` is `R`-integral. -/ +theorem isIntegral_of_smul_mem_submodule {M : Type*} [AddCommGroup M] [Module R M] [Module A M] + [IsScalarTower R A M] [NoZeroSMulDivisors A M] (N : Submodule R M) (hN : N ≠ ⊥) (hN' : N.FG) + (x : A) (hx : ∀ n ∈ N, x • n ∈ N) : IsIntegral R x := by + let A' : Subalgebra R A := + { carrier := { x | ∀ n ∈ N, x • n ∈ N } + mul_mem' := fun {a b} ha hb n hn => smul_smul a b n ▸ ha _ (hb _ hn) + one_mem' := fun n hn => (one_smul A n).symm ▸ hn + add_mem' := fun {a b} ha hb n hn => (add_smul a b n).symm ▸ N.add_mem (ha _ hn) (hb _ hn) + zero_mem' := fun n _hn => (zero_smul A n).symm ▸ N.zero_mem + algebraMap_mem' := fun r n hn => (algebraMap_smul A r n).symm ▸ N.smul_mem r hn } + let f : A' →ₐ[R] Module.End R N := + AlgHom.ofLinearMap + { toFun := fun x => (DistribMulAction.toLinearMap R M x).restrict x.prop + -- Porting note: was + -- `fun x y => LinearMap.ext fun n => Subtype.ext <| add_smul x y n` + map_add' := by intros x y; ext; exact add_smul _ _ _ + -- Porting note: was + -- `fun r s => LinearMap.ext fun n => Subtype.ext <| smul_assoc r s n` + map_smul' := by intros r s; ext; apply smul_assoc } + -- Porting note: the next two lines were + --`(LinearMap.ext fun n => Subtype.ext <| one_smul _ _) fun x y =>` + --`LinearMap.ext fun n => Subtype.ext <| mul_smul x y n` + (by ext; apply one_smul) + (by intros x y; ext; apply mul_smul) + obtain ⟨a, ha₁, ha₂⟩ : ∃ a ∈ N, a ≠ (0 : M) := by + by_contra! h' + apply hN + rwa [eq_bot_iff] + have : Function.Injective f := by + show Function.Injective f.toLinearMap + rw [← LinearMap.ker_eq_bot, eq_bot_iff] + intro s hs + have : s.1 • a = 0 := congr_arg Subtype.val (LinearMap.congr_fun hs ⟨a, ha₁⟩) + exact Subtype.ext ((eq_zero_or_eq_zero_of_smul_eq_zero this).resolve_right ha₂) + show IsIntegral R (A'.val ⟨x, hx⟩) + rw [isIntegral_algHom_iff A'.val Subtype.val_injective, ← isIntegral_algHom_iff f this] + haveI : Module.Finite R N := by rwa [Module.finite_def, Submodule.fg_top] + apply Algebra.IsIntegral.isIntegral + +variable {f} + +theorem RingHom.Finite.to_isIntegral (h : f.Finite) : f.IsIntegral := + letI := f.toAlgebra + fun _ ↦ IsIntegral.of_mem_of_fg ⊤ h.1 _ trivial + +alias RingHom.IsIntegral.of_finite := RingHom.Finite.to_isIntegral + +variable (f) + theorem RingHom.IsIntegralElem.of_mem_closure {x y z : S} (hx : f.IsIntegralElem x) (hy : f.IsIntegralElem y) (hz : z ∈ Subring.closure ({x, y} : Set S)) : f.IsIntegralElem z := by letI : Algebra R S := f.toAlgebra diff --git a/Mathlib/RingTheory/IntegralClosure/IsIntegral/Basic.lean b/Mathlib/RingTheory/IntegralClosure/IsIntegral/Basic.lean index 4950bcffb0f99..ef2c7b2672431 100644 --- a/Mathlib/RingTheory/IntegralClosure/IsIntegral/Basic.lean +++ b/Mathlib/RingTheory/IntegralClosure/IsIntegral/Basic.lean @@ -104,3 +104,77 @@ theorem IsIntegral.of_pow [Algebra R B] {x : B} {n : ℕ} (hn : 0 < n) (hx : IsI exact ⟨expand R n p, hmonic.expand hn, by rwa [← aeval_def, expand_aeval]⟩ end + +section + +variable {R A B S : Type*} +variable [CommRing R] [CommRing A] [Ring B] [CommRing S] +variable [Algebra R A] [Algebra R B] (f : R →+* S) + +theorem IsIntegral.map_of_comp_eq {R S T U : Type*} [CommRing R] [Ring S] + [CommRing T] [Ring U] [Algebra R S] [Algebra T U] (φ : R →+* T) (ψ : S →+* U) + (h : (algebraMap T U).comp φ = ψ.comp (algebraMap R S)) {a : S} (ha : IsIntegral R a) : + IsIntegral T (ψ a) := + let ⟨p, hp⟩ := ha + ⟨p.map φ, hp.1.map _, by + rw [← eval_map, map_map, h, ← map_map, eval_map, eval₂_at_apply, eval_map, hp.2, ψ.map_zero]⟩ + +@[simp] +theorem isIntegral_algEquiv {A B : Type*} [Ring A] [Ring B] [Algebra R A] [Algebra R B] + (f : A ≃ₐ[R] B) {x : A} : IsIntegral R (f x) ↔ IsIntegral R x := + ⟨fun h ↦ by simpa using h.map f.symm, IsIntegral.map f⟩ + +/-- If `R → A → B` is an algebra tower, +then if the entire tower is an integral extension so is `A → B`. -/ +theorem IsIntegral.tower_top [Algebra A B] [IsScalarTower R A B] {x : B} + (hx : IsIntegral R x) : IsIntegral A x := + let ⟨p, hp, hpx⟩ := hx + ⟨p.map <| algebraMap R A, hp.map _, by rw [← aeval_def, aeval_map_algebraMap, aeval_def, hpx]⟩ + +theorem map_isIntegral_int {B C F : Type*} [Ring B] [Ring C] {b : B} + [FunLike F B C] [RingHomClass F B C] (f : F) + (hb : IsIntegral ℤ b) : IsIntegral ℤ (f b) := + hb.map (f : B →+* C).toIntAlgHom + +theorem IsIntegral.of_subring {x : B} (T : Subring R) (hx : IsIntegral T x) : IsIntegral R x := + hx.tower_top + +protected theorem IsIntegral.algebraMap [Algebra A B] [IsScalarTower R A B] {x : A} + (h : IsIntegral R x) : IsIntegral R (algebraMap A B x) := by + rcases h with ⟨f, hf, hx⟩ + use f, hf + rw [IsScalarTower.algebraMap_eq R A B, ← hom_eval₂, hx, RingHom.map_zero] + +theorem isIntegral_algebraMap_iff [Algebra A B] [IsScalarTower R A B] {x : A} + (hAB : Function.Injective (algebraMap A B)) : + IsIntegral R (algebraMap A B x) ↔ IsIntegral R x := + isIntegral_algHom_iff (IsScalarTower.toAlgHom R A B) hAB + +theorem isIntegral_iff_isIntegral_closure_finite {r : B} : + IsIntegral R r ↔ ∃ s : Set R, s.Finite ∧ IsIntegral (Subring.closure s) r := by + constructor <;> intro hr + · rcases hr with ⟨p, hmp, hpr⟩ + refine ⟨_, Finset.finite_toSet _, p.restriction, monic_restriction.2 hmp, ?_⟩ + rw [← aeval_def, ← aeval_map_algebraMap R r p.restriction, map_restriction, aeval_def, hpr] + rcases hr with ⟨s, _, hsr⟩ + exact hsr.of_subring _ + +theorem fg_adjoin_of_finite {s : Set A} (hfs : s.Finite) (his : ∀ x ∈ s, IsIntegral R x) : + (Algebra.adjoin R s).toSubmodule.FG := + Set.Finite.induction_on hfs + (fun _ => + ⟨{1}, + Submodule.ext fun x => by + rw [Algebra.adjoin_empty, Finset.coe_singleton, ← one_eq_span, Algebra.toSubmodule_bot]⟩) + (fun {a s} _ _ ih his => by + rw [← Set.union_singleton, Algebra.adjoin_union_coe_submodule] + exact + FG.mul (ih fun i hi => his i <| Set.mem_insert_of_mem a hi) + (his a <| Set.mem_insert a s).fg_adjoin_singleton) + his + +theorem isNoetherian_adjoin_finset [IsNoetherianRing R] (s : Finset A) + (hs : ∀ x ∈ s, IsIntegral R x) : IsNoetherian R (Algebra.adjoin R (s : Set A)) := + isNoetherian_of_fg_of_noetherian _ (fg_adjoin_of_finite s.finite_toSet hs) + +end diff --git a/Mathlib/RingTheory/IntegralClosure/IsIntegralClosure/Basic.lean b/Mathlib/RingTheory/IntegralClosure/IsIntegralClosure/Basic.lean index b1fb223b3f0ba..0a9301168ce1c 100644 --- a/Mathlib/RingTheory/IntegralClosure/IsIntegralClosure/Basic.lean +++ b/Mathlib/RingTheory/IntegralClosure/IsIntegralClosure/Basic.lean @@ -7,6 +7,7 @@ import Mathlib.RingTheory.IntegralClosure.IsIntegralClosure.Defs import Mathlib.RingTheory.IntegralClosure.Algebra.Basic import Mathlib.RingTheory.FiniteType import Mathlib.RingTheory.Polynomial.ScaleRoots +import Mathlib.LinearAlgebra.FiniteDimensional.Defs /-! # # Integral closure as a characteristic predicate @@ -22,140 +23,7 @@ section variable {R A B S : Type*} variable [CommRing R] [CommRing A] [Ring B] [CommRing S] -variable [Algebra R A] [Algebra R B] (f : R →+* S) - -theorem IsIntegral.map_of_comp_eq {R S T U : Type*} [CommRing R] [Ring S] - [CommRing T] [Ring U] [Algebra R S] [Algebra T U] (φ : R →+* T) (ψ : S →+* U) - (h : (algebraMap T U).comp φ = ψ.comp (algebraMap R S)) {a : S} (ha : IsIntegral R a) : - IsIntegral T (ψ a) := - let ⟨p, hp⟩ := ha - ⟨p.map φ, hp.1.map _, by - rw [← eval_map, map_map, h, ← map_map, eval_map, eval₂_at_apply, eval_map, hp.2, ψ.map_zero]⟩ - -section - -variable {A B : Type*} [Ring A] [Ring B] [Algebra R A] [Algebra R B] -variable (f : A →ₐ[R] B) - -theorem Algebra.IsIntegral.of_injective (hf : Function.Injective f) [Algebra.IsIntegral R B] : - Algebra.IsIntegral R A := - ⟨fun _ ↦ (isIntegral_algHom_iff f hf).mp (isIntegral _)⟩ - -end - -@[simp] -theorem isIntegral_algEquiv {A B : Type*} [Ring A] [Ring B] [Algebra R A] [Algebra R B] - (f : A ≃ₐ[R] B) {x : A} : IsIntegral R (f x) ↔ IsIntegral R x := - ⟨fun h ↦ by simpa using h.map f.symm, IsIntegral.map f⟩ - -/-- If `R → A → B` is an algebra tower, -then if the entire tower is an integral extension so is `A → B`. -/ -theorem IsIntegral.tower_top [Algebra A B] [IsScalarTower R A B] {x : B} - (hx : IsIntegral R x) : IsIntegral A x := - let ⟨p, hp, hpx⟩ := hx - ⟨p.map <| algebraMap R A, hp.map _, by rw [← aeval_def, aeval_map_algebraMap, aeval_def, hpx]⟩ - -theorem map_isIntegral_int {B C F : Type*} [Ring B] [Ring C] {b : B} - [FunLike F B C] [RingHomClass F B C] (f : F) - (hb : IsIntegral ℤ b) : IsIntegral ℤ (f b) := - hb.map (f : B →+* C).toIntAlgHom - -theorem IsIntegral.of_subring {x : B} (T : Subring R) (hx : IsIntegral T x) : IsIntegral R x := - hx.tower_top - -protected theorem IsIntegral.algebraMap [Algebra A B] [IsScalarTower R A B] {x : A} - (h : IsIntegral R x) : IsIntegral R (algebraMap A B x) := by - rcases h with ⟨f, hf, hx⟩ - use f, hf - rw [IsScalarTower.algebraMap_eq R A B, ← hom_eval₂, hx, RingHom.map_zero] - -theorem isIntegral_algebraMap_iff [Algebra A B] [IsScalarTower R A B] {x : A} - (hAB : Function.Injective (algebraMap A B)) : - IsIntegral R (algebraMap A B x) ↔ IsIntegral R x := - isIntegral_algHom_iff (IsScalarTower.toAlgHom R A B) hAB - -theorem isIntegral_iff_isIntegral_closure_finite {r : B} : - IsIntegral R r ↔ ∃ s : Set R, s.Finite ∧ IsIntegral (Subring.closure s) r := by - constructor <;> intro hr - · rcases hr with ⟨p, hmp, hpr⟩ - refine ⟨_, Finset.finite_toSet _, p.restriction, monic_restriction.2 hmp, ?_⟩ - rw [← aeval_def, ← aeval_map_algebraMap R r p.restriction, map_restriction, aeval_def, hpr] - rcases hr with ⟨s, _, hsr⟩ - exact hsr.of_subring _ - -theorem fg_adjoin_of_finite {s : Set A} (hfs : s.Finite) (his : ∀ x ∈ s, IsIntegral R x) : - (Algebra.adjoin R s).toSubmodule.FG := - Set.Finite.induction_on hfs - (fun _ => - ⟨{1}, - Submodule.ext fun x => by - rw [Algebra.adjoin_empty, Finset.coe_singleton, ← one_eq_span, Algebra.toSubmodule_bot]⟩) - (fun {a s} _ _ ih his => by - rw [← Set.union_singleton, Algebra.adjoin_union_coe_submodule] - exact - FG.mul (ih fun i hi => his i <| Set.mem_insert_of_mem a hi) - (his a <| Set.mem_insert a s).fg_adjoin_singleton) - his - -theorem isNoetherian_adjoin_finset [IsNoetherianRing R] (s : Finset A) - (hs : ∀ x ∈ s, IsIntegral R x) : IsNoetherian R (Algebra.adjoin R (s : Set A)) := - isNoetherian_of_fg_of_noetherian _ (fg_adjoin_of_finite s.finite_toSet hs) - -theorem isIntegral_of_noetherian (_ : IsNoetherian R B) (x : B) : IsIntegral R x := - .of_finite R x - -theorem isIntegral_of_submodule_noetherian (S : Subalgebra R B) - (H : IsNoetherian R (Subalgebra.toSubmodule S)) (x : B) (hx : x ∈ S) : IsIntegral R x := - .of_mem_of_fg _ ((fg_top _).mp <| H.noetherian _) _ hx - -/-- Suppose `A` is an `R`-algebra, `M` is an `A`-module such that `a • m ≠ 0` for all non-zero `a` -and `m`. If `x : A` fixes a nontrivial f.g. `R`-submodule `N` of `M`, then `x` is `R`-integral. -/ -theorem isIntegral_of_smul_mem_submodule {M : Type*} [AddCommGroup M] [Module R M] [Module A M] - [IsScalarTower R A M] [NoZeroSMulDivisors A M] (N : Submodule R M) (hN : N ≠ ⊥) (hN' : N.FG) - (x : A) (hx : ∀ n ∈ N, x • n ∈ N) : IsIntegral R x := by - let A' : Subalgebra R A := - { carrier := { x | ∀ n ∈ N, x • n ∈ N } - mul_mem' := fun {a b} ha hb n hn => smul_smul a b n ▸ ha _ (hb _ hn) - one_mem' := fun n hn => (one_smul A n).symm ▸ hn - add_mem' := fun {a b} ha hb n hn => (add_smul a b n).symm ▸ N.add_mem (ha _ hn) (hb _ hn) - zero_mem' := fun n _hn => (zero_smul A n).symm ▸ N.zero_mem - algebraMap_mem' := fun r n hn => (algebraMap_smul A r n).symm ▸ N.smul_mem r hn } - let f : A' →ₐ[R] Module.End R N := - AlgHom.ofLinearMap - { toFun := fun x => (DistribMulAction.toLinearMap R M x).restrict x.prop - -- Porting note: was - -- `fun x y => LinearMap.ext fun n => Subtype.ext <| add_smul x y n` - map_add' := by intros x y; ext; exact add_smul _ _ _ - -- Porting note: was - -- `fun r s => LinearMap.ext fun n => Subtype.ext <| smul_assoc r s n` - map_smul' := by intros r s; ext; apply smul_assoc } - -- Porting note: the next two lines were - --`(LinearMap.ext fun n => Subtype.ext <| one_smul _ _) fun x y =>` - --`LinearMap.ext fun n => Subtype.ext <| mul_smul x y n` - (by ext; apply one_smul) - (by intros x y; ext; apply mul_smul) - obtain ⟨a, ha₁, ha₂⟩ : ∃ a ∈ N, a ≠ (0 : M) := by - by_contra! h' - apply hN - rwa [eq_bot_iff] - have : Function.Injective f := by - show Function.Injective f.toLinearMap - rw [← LinearMap.ker_eq_bot, eq_bot_iff] - intro s hs - have : s.1 • a = 0 := congr_arg Subtype.val (LinearMap.congr_fun hs ⟨a, ha₁⟩) - exact Subtype.ext ((eq_zero_or_eq_zero_of_smul_eq_zero this).resolve_right ha₂) - show IsIntegral R (A'.val ⟨x, hx⟩) - rw [isIntegral_algHom_iff A'.val Subtype.val_injective, ← isIntegral_algHom_iff f this] - haveI : Module.Finite R N := by rwa [Module.finite_def, Submodule.fg_top] - apply Algebra.IsIntegral.isIntegral - -variable {f} - -theorem RingHom.Finite.to_isIntegral (h : f.Finite) : f.IsIntegral := - letI := f.toAlgebra - fun _ ↦ IsIntegral.of_mem_of_fg ⊤ h.1 _ trivial - -alias RingHom.IsIntegral.of_finite := RingHom.Finite.to_isIntegral +variable [Algebra R A] [Algebra R B] {f : R →+* S} /-- The [Kurosh problem](https://en.wikipedia.org/wiki/Kurosh_problem) asks to show that this is still true when `A` is not necessarily commutative and `R` is a field, but it has @@ -693,7 +561,7 @@ theorem Algebra.IsIntegral.isField_iff_isField {R S : Type*} [CommRing R] end Algebra theorem integralClosure_idem {R A : Type*} [CommRing R] [CommRing A] [Algebra R A] : - integralClosure (integralClosure R A : Set A) A = ⊥ := + integralClosure (integralClosure R A) A = ⊥ := letI := (integralClosure R A).algebra eq_bot_iff.2 fun x hx ↦ Algebra.mem_bot.2 ⟨⟨x, isIntegral_trans (A := integralClosure R A) x hx⟩, rfl⟩ diff --git a/Mathlib/RingTheory/IntegralDomain.lean b/Mathlib/RingTheory/IntegralDomain.lean index aff1446d6ba80..544f816a2f202 100644 --- a/Mathlib/RingTheory/IntegralDomain.lean +++ b/Mathlib/RingTheory/IntegralDomain.lean @@ -92,7 +92,9 @@ def Fintype.divisionRingOfIsDomain (R : Type*) [Ring R] [IsDomain R] [DecidableE __ := Fintype.groupWithZeroOfCancel R __ := ‹Ring R› nnqsmul := _ + nnqsmul_def := fun q a => rfl qsmul := _ + qsmul_def := fun q a => rfl /-- Every finite commutative domain is a field. More generally, commutativity is not required: this can be found in `Mathlib.RingTheory.LittleWedderburn`. -/ diff --git a/Mathlib/RingTheory/IsAdjoinRoot.lean b/Mathlib/RingTheory/IsAdjoinRoot.lean index f48ab8430a1bd..03e036aa35719 100644 --- a/Mathlib/RingTheory/IsAdjoinRoot.lean +++ b/Mathlib/RingTheory/IsAdjoinRoot.lean @@ -195,7 +195,7 @@ variable (i x) -- To match `AdjoinRoot.lift` /-- Lift a ring homomorphism `R →+* T` to `S →+* T` by specifying a root `x` of `f` in `T`, where `S` is given by adjoining a root of `f` to `R`. -/ -def lift (h : IsAdjoinRoot S f) : S →+* T where +def lift (h : IsAdjoinRoot S f) (hx : f.eval₂ i x = 0) : S →+* T where toFun z := (h.repr z).eval₂ i x map_zero' := by dsimp only -- Porting note (#10752): added `dsimp only` @@ -370,7 +370,7 @@ Auxiliary definition for `IsAdjoinRootMonic.powerBasis`. -/ def basis (h : IsAdjoinRootMonic S f) : Basis (Fin (natDegree f)) R S := Basis.ofRepr { toFun := fun x => (h.modByMonicHom x).toFinsupp.comapDomain _ Fin.val_injective.injOn - invFun := fun g => h.map (ofFinsupp (g.mapDomain _)) + invFun := fun g => h.map (ofFinsupp (g.mapDomain Fin.val)) left_inv := fun x => by cases subsingleton_or_nontrivial R · subsingleton [h.subsingleton] @@ -393,12 +393,10 @@ def basis (h : IsAdjoinRootMonic S f) : Basis (Fin (natDegree f)) R S := ext i simp only [h.modByMonicHom_map, Finsupp.comapDomain_apply, Polynomial.toFinsupp_apply] rw [(Polynomial.modByMonic_eq_self_iff h.Monic).mpr, Polynomial.coeff] - · dsimp only -- Porting note (#10752): added `dsimp only` - rw [Finsupp.mapDomain_apply Fin.val_injective] + · rw [Finsupp.mapDomain_apply Fin.val_injective] rw [degree_eq_natDegree h.Monic.ne_zero, degree_lt_iff_coeff_zero] intro m hm rw [Polynomial.coeff] - dsimp only -- Porting note (#10752): added `dsimp only` rw [Finsupp.mapDomain_notin_range] rw [Set.mem_range, not_exists] rintro i rfl diff --git a/Mathlib/RingTheory/Kaehler/Basic.lean b/Mathlib/RingTheory/Kaehler/Basic.lean index 661532a73b713..4c0d923b7ddfc 100644 --- a/Mathlib/RingTheory/Kaehler/Basic.lean +++ b/Mathlib/RingTheory/Kaehler/Basic.lean @@ -49,7 +49,7 @@ suppress_compilation section KaehlerDifferential open scoped TensorProduct -open Algebra +open Algebra Finsupp universe u v @@ -320,7 +320,7 @@ theorem KaehlerDifferential.tensorProductTo_surjective : exact ⟨x, KaehlerDifferential.D_tensorProductTo x⟩ /-- The `S`-linear maps from `Ω[S⁄R]` to `M` are (`S`-linearly) equivalent to `R`-derivations -from `S` to `M`. -/ +from `S` to `M`. -/ @[simps! symm_apply apply_apply] def KaehlerDifferential.linearMapEquivDerivation : (Ω[S⁄R] →ₗ[S] M) ≃ₗ[S] Derivation R S M := { Derivation.llcomp.flip <| KaehlerDifferential.D R S with @@ -369,7 +369,7 @@ theorem KaehlerDifferential.End_equiv_aux (f : S →ₐ[R] S ⊗ S ⧸ KaehlerDi · intro e; apply (KaehlerDifferential.quotientCotangentIdealRingEquiv R S).injective exact e₁.symm.trans (e.trans e₂) -/- Note: Lean is slow to synthesize theses instances (times out). +/- Note: Lean is slow to synthesize these instances (times out). Without them the endEquivDerivation' and endEquivAuxEquiv both have significant timeouts. In Mathlib 3, it was slow but not this slow. -/ /-- A shortcut instance to prevent timing out. Hopefully to be removed in the future. -/ @@ -499,8 +499,9 @@ the relations: 3. `dr = 0` for `r ∈ R` where `db` is the unit in the copy of `S` with index `b`. -This is the kernel of the surjection `Finsupp.total S Ω[S⁄R] S (KaehlerDifferential.D R S)`. -See `KaehlerDifferential.kerTotal_eq` and `KaehlerDifferential.total_surjective`. +This is the kernel of the surjection +`Finsupp.linearCombination S Ω[S⁄R] S (KaehlerDifferential.D R S)`. +See `KaehlerDifferential.kerTotal_eq` and `KaehlerDifferential.linearCombination_surjective`. -/ noncomputable def KaehlerDifferential.kerTotal : Submodule S (S →₀ S) := Submodule.span S @@ -555,46 +556,55 @@ theorem KaehlerDifferential.derivationQuotKerTotal_apply (x) : KaehlerDifferential.derivationQuotKerTotal R S x = 1𝖣x := rfl -theorem KaehlerDifferential.derivationQuotKerTotal_lift_comp_total : +theorem KaehlerDifferential.derivationQuotKerTotal_lift_comp_linearCombination : (KaehlerDifferential.derivationQuotKerTotal R S).liftKaehlerDifferential.comp - (Finsupp.total S (Ω[S⁄R]) S (KaehlerDifferential.D R S)) = + (Finsupp.linearCombination S (KaehlerDifferential.D R S)) = Submodule.mkQ _ := by apply Finsupp.lhom_ext intro a b conv_rhs => rw [← Finsupp.smul_single_one a b, LinearMap.map_smul] simp [KaehlerDifferential.derivationQuotKerTotal_apply] +@[deprecated (since := "2024-08-29")] alias + KaehlerDifferential.derivationQuotKerTotal_lift_comp_total := + KaehlerDifferential.derivationQuotKerTotal_lift_comp_linearCombination + theorem KaehlerDifferential.kerTotal_eq : - LinearMap.ker (Finsupp.total S (Ω[S⁄R]) S (KaehlerDifferential.D R S)) = + LinearMap.ker (Finsupp.linearCombination S (KaehlerDifferential.D R S)) = KaehlerDifferential.kerTotal R S := by apply le_antisymm · conv_rhs => rw [← (KaehlerDifferential.kerTotal R S).ker_mkQ] - rw [← KaehlerDifferential.derivationQuotKerTotal_lift_comp_total] + rw [← KaehlerDifferential.derivationQuotKerTotal_lift_comp_linearCombination] exact LinearMap.ker_le_ker_comp _ _ · rw [KaehlerDifferential.kerTotal, Submodule.span_le] rintro _ ((⟨⟨x, y⟩, rfl⟩ | ⟨⟨x, y⟩, rfl⟩) | ⟨x, rfl⟩) <;> dsimp <;> simp [LinearMap.mem_ker] -theorem KaehlerDifferential.total_surjective : - Function.Surjective (Finsupp.total S (Ω[S⁄R]) S (KaehlerDifferential.D R S)) := by - rw [← LinearMap.range_eq_top, Finsupp.range_total, KaehlerDifferential.span_range_derivation] +theorem KaehlerDifferential.linearCombination_surjective : + Function.Surjective (Finsupp.linearCombination S (KaehlerDifferential.D R S)) := by + rw [← LinearMap.range_eq_top, range_linearCombination, KaehlerDifferential.span_range_derivation] + +@[deprecated (since := "2024-08-29")] alias KaehlerDifferential.total_surjective := + KaehlerDifferential.linearCombination_surjective /-- `Ω[S⁄R]` is isomorphic to `S` copies of `S` with kernel `KaehlerDifferential.kerTotal`. -/ @[simps!] noncomputable def KaehlerDifferential.quotKerTotalEquiv : ((S →₀ S) ⧸ KaehlerDifferential.kerTotal R S) ≃ₗ[S] Ω[S⁄R] := { (KaehlerDifferential.kerTotal R S).liftQ - (Finsupp.total S (Ω[S⁄R]) S (KaehlerDifferential.D R S)) + (Finsupp.linearCombination S (KaehlerDifferential.D R S)) (KaehlerDifferential.kerTotal_eq R S).ge with invFun := (KaehlerDifferential.derivationQuotKerTotal R S).liftKaehlerDifferential left_inv := by intro x obtain ⟨x, rfl⟩ := Submodule.mkQ_surjective _ x exact - LinearMap.congr_fun (KaehlerDifferential.derivationQuotKerTotal_lift_comp_total R S : _) x + LinearMap.congr_fun + (KaehlerDifferential.derivationQuotKerTotal_lift_comp_linearCombination R S : _) x right_inv := by intro x - obtain ⟨x, rfl⟩ := KaehlerDifferential.total_surjective R S x - have := LinearMap.congr_fun (KaehlerDifferential.derivationQuotKerTotal_lift_comp_total R S) x + obtain ⟨x, rfl⟩ := KaehlerDifferential.linearCombination_surjective R S x + have := LinearMap.congr_fun + (KaehlerDifferential.derivationQuotKerTotal_lift_comp_linearCombination R S) x rw [LinearMap.comp_apply] at this rw [this] rfl } @@ -704,13 +714,13 @@ theorem KaehlerDifferential.map_D (x : A) : theorem KaehlerDifferential.ker_map : LinearMap.ker (KaehlerDifferential.map R S A B) = (((kerTotal S B).restrictScalars A).comap finsupp_map).map - (Finsupp.total A (Ω[A⁄R]) A (D R A)) := by - rw [← Submodule.map_comap_eq_of_surjective (total_surjective R A) (LinearMap.ker _)] + (Finsupp.linearCombination (M := Ω[A⁄R]) A (D R A)) := by + rw [← Submodule.map_comap_eq_of_surjective (linearCombination_surjective R A) (LinearMap.ker _)] congr 1 ext x - simp only [Submodule.mem_comap, LinearMap.mem_ker, Finsupp.apply_total, ← kerTotal_eq, + simp only [Submodule.mem_comap, LinearMap.mem_ker, Finsupp.apply_linearCombination, ← kerTotal_eq, Submodule.restrictScalars_mem] - simp only [Finsupp.total_apply, Function.comp_apply, LinearMap.coe_comp, Finsupp.lmapDomain_apply, + simp only [linearCombination_apply, Function.comp_apply, LinearMap.coe_comp, lmapDomain_apply, Finsupp.mapRange.linearMap_apply] rw [Finsupp.sum_mapRange_index, Finsupp.sum_mapDomain_index] · simp [ofId] @@ -720,10 +730,10 @@ theorem KaehlerDifferential.ker_map : lemma KaehlerDifferential.ker_map_of_surjective (h : Function.Surjective (algebraMap A B)) : LinearMap.ker (map R R A B) = - (LinearMap.ker finsupp_map).map (Finsupp.total A _ A (D R A)) := by + (LinearMap.ker finsupp_map).map (Finsupp.linearCombination A (D R A)) := by rw [ker_map, ← kerTotal_map' R A B h, Submodule.comap_map_eq, Submodule.map_sup, Submodule.map_sup, ← kerTotal_eq, ← Submodule.comap_bot, - Submodule.map_comap_eq_of_surjective (total_surjective _ _), + Submodule.map_comap_eq_of_surjective (linearCombination_surjective _ _), bot_sup_eq, Submodule.map_span, ← Set.range_comp] convert bot_sup_eq _ rw [Submodule.span_eq_bot]; simp @@ -763,14 +773,14 @@ lemma KaehlerDifferential.range_mapBaseChange : · rintro _ ⟨x, rfl⟩ induction' x with r s · simp - · obtain ⟨x, rfl⟩ := total_surjective _ _ s + · obtain ⟨x, rfl⟩ := linearCombination_surjective _ _ s simp only [mapBaseChange_tmul, LinearMap.mem_ker, map_smul] induction x using Finsupp.induction_linear · simp · simp [smul_add, *] · simp · rw [map_add]; exact add_mem ‹_› ‹_› - · convert_to (kerTotal A B).map (Finsupp.total B (Ω[B⁄R]) B (D R B)) ≤ _ + · convert_to (kerTotal A B).map (Finsupp.linearCombination B (D R B)) ≤ _ · rw [KaehlerDifferential.ker_map] congr 1 convert Submodule.comap_id _ @@ -795,11 +805,11 @@ noncomputable def KaehlerDifferential.kerToTensor : RingHom.ker (algebraMap A B) →ₗ[A] B ⊗[A] Ω[A⁄R] where toFun x := 1 ⊗ₜ D R A x - map_add' x y := by simp only [AddSubmonoid.coe_add, Submodule.coe_toAddSubmonoid, map_add, - TensorProduct.tmul_add] - map_smul' r x := by simp only [SetLike.val_smul, Derivation.leibniz, RingHom.id_apply, - TensorProduct.tmul_smul, TensorProduct.smul_tmul', add_zero, ← Algebra.algebraMap_eq_smul_one, - TensorProduct.zero_tmul, smul_eq_mul, TensorProduct.tmul_add, (RingHom.mem_ker _).mp x.prop] + map_add' x y := by simp only [Submodule.coe_add, map_add, TensorProduct.tmul_add] + map_smul' r x := by simp only [SetLike.val_smul, smul_eq_mul, Derivation.leibniz, + TensorProduct.tmul_add, TensorProduct.tmul_smul, TensorProduct.smul_tmul', ← + algebraMap_eq_smul_one, (RingHom.mem_ker _).mp x.prop, TensorProduct.zero_tmul, add_zero, + RingHom.id_apply] /-- The map `I/I² → B ⊗[A] B ⊗[A] Ω[A⁄R]` where `I = ker(A → B)`. -/ noncomputable @@ -844,14 +854,16 @@ theorem KaehlerDifferential.range_kerCotangentToTensor intro c _ simp only [Finset.filter_congr_decidable, TensorProduct.lid_symm_apply, LinearMap.rTensor_tmul, AlgHom.toLinearMap_apply, map_one, LinearMap.mem_range] - simp only [map_sum, Finsupp.total_single] + simp only [map_sum, Finsupp.linearCombination_single] have : (x.support.filter (algebraMap A B · = c)).sum x ∈ RingHom.ker (algebraMap A B) := by simpa [Finsupp.mapDomain, Finsupp.sum, Finsupp.finset_sum_apply, RingHom.mem_ker, Finsupp.single_apply, ← Finset.sum_filter] using DFunLike.congr_fun hx c obtain ⟨a, ha⟩ := h c use (x.support.filter (algebraMap A B · = c)).attach.sum fun i ↦ x i • Ideal.toCotangent _ ⟨i - a, ?_⟩; swap - · have : x i ≠ 0 ∧ algebraMap A B i = c := by simpa using i.prop + · have : x i ≠ 0 ∧ algebraMap A B i = c := by + convert i.prop + simp_rw [Finset.mem_filter, Finsupp.mem_support_iff] simp [RingHom.mem_ker, ha, this.2] · simp only [map_sum, LinearMapClass.map_smul, kerCotangentToTensor_toCotangent, map_sub] simp_rw [← TensorProduct.tmul_smul] diff --git a/Mathlib/RingTheory/Kaehler/Polynomial.lean b/Mathlib/RingTheory/Kaehler/Polynomial.lean index 103fa5aaec60a..c5e94eaca9de6 100644 --- a/Mathlib/RingTheory/Kaehler/Polynomial.lean +++ b/Mathlib/RingTheory/Kaehler/Polynomial.lean @@ -27,20 +27,23 @@ section MvPolynomial def KaehlerDifferential.mvPolynomialEquiv (σ : Type*) : Ω[MvPolynomial σ R⁄R] ≃ₗ[MvPolynomial σ R] σ →₀ MvPolynomial σ R where __ := (MvPolynomial.mkDerivation _ (Finsupp.single · 1)).liftKaehlerDifferential - invFun := Finsupp.total σ _ _ (fun x ↦ D _ _ (MvPolynomial.X x)) + invFun := Finsupp.linearCombination (α := σ) _ (fun x ↦ D _ _ (MvPolynomial.X x)) right_inv := by intro x - induction' x using Finsupp.induction_linear with _ _ _ _ a b - · simp only [AddHom.toFun_eq_coe, LinearMap.coe_toAddHom]; rw [map_zero, map_zero] - · simp only [AddHom.toFun_eq_coe, LinearMap.coe_toAddHom, map_add] at *; simp only [*] - · simp [LinearMap.map_smul, -map_smul] + induction x using Finsupp.induction_linear with + | h0 => simp only [AddHom.toFun_eq_coe, LinearMap.coe_toAddHom]; rw [map_zero, map_zero] + | hadd => simp only [AddHom.toFun_eq_coe, LinearMap.coe_toAddHom, map_add] at *; simp only [*] + | hsingle a b => simp [LinearMap.map_smul, -map_smul] left_inv := by intro x - obtain ⟨x, rfl⟩ := total_surjective _ _ x - induction' x using Finsupp.induction_linear with _ _ _ _ a b - · simp only [AddHom.toFun_eq_coe, LinearMap.coe_toAddHom]; rw [map_zero, map_zero, map_zero] - · simp only [map_add, AddHom.toFun_eq_coe, LinearMap.coe_toAddHom] at *; simp only [*] - · simp only [AddHom.toFun_eq_coe, LinearMap.coe_toAddHom, Finsupp.total_single, + obtain ⟨x, rfl⟩ := linearCombination_surjective _ _ x + induction x using Finsupp.induction_linear with + | h0 => + simp only [AddHom.toFun_eq_coe, LinearMap.coe_toAddHom] + rw [map_zero, map_zero, map_zero] + | hadd => simp only [map_add, AddHom.toFun_eq_coe, LinearMap.coe_toAddHom] at *; simp only [*] + | hsingle a b => + simp only [AddHom.toFun_eq_coe, LinearMap.coe_toAddHom, Finsupp.linearCombination_single, LinearMap.map_smul, Derivation.liftKaehlerDifferential_comp_D] congr 1 induction a using MvPolynomial.induction_on @@ -109,7 +112,7 @@ def KaehlerDifferential.polynomialEquiv : Ω[R[X]⁄R] ≃ₗ[R[X]] R[X] where invFun := (Algebra.lsmul R R _).toLinearMap.flip (D R R[X] X) left_inv := by intro x - obtain ⟨x, rfl⟩ := total_surjective _ _ x + obtain ⟨x, rfl⟩ := linearCombination_surjective _ _ x induction' x using Finsupp.induction_linear with x y hx hy x y · simp · simp only [map_add, AddHom.toFun_eq_coe, LinearMap.coe_toAddHom, LinearMap.flip_apply, diff --git a/Mathlib/RingTheory/LaurentSeries.lean b/Mathlib/RingTheory/LaurentSeries.lean index 0715d3ae16630..bd1f3b8b077e1 100644 --- a/Mathlib/RingTheory/LaurentSeries.lean +++ b/Mathlib/RingTheory/LaurentSeries.lean @@ -101,7 +101,7 @@ theorem coeff_coe_powerSeries (x : PowerSeries R) (n : ℕ) : /-- 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. -/ + constant term. -/ def powerSeriesPart (x : LaurentSeries R) : PowerSeries R := PowerSeries.mk fun n => x.coeff (x.order + n) @@ -233,7 +233,7 @@ theorem coeff_coe (i : ℤ) : · rw [ofPowerSeries_apply, embDomain_notin_image_support, if_pos (Int.negSucc_lt_zero _)] simp only [not_exists, RelEmbedding.coe_mk, Set.mem_image, not_and, Function.Embedding.coeFn_mk, Ne, toPowerSeries_symm_apply_coeff, mem_support, imp_true_iff, - not_false_iff] + not_false_iff, reduceCtorEq] -- Porting note (#10618): simp can prove this -- Porting note: removed norm_cast attribute @@ -525,7 +525,7 @@ theorem coeff_zero_of_lt_valuation {n D : ℤ} {f : LaurentSeries K} apply (intValuation_le_iff_coeff_lt_eq_zero K F).mp _ m (by linarith) rwa [hF, ofPowerSeries_powerSeriesPart f, hs, neg_neg, ← hd, neg_add_rev, ofAdd_add, map_mul, ← ofPowerSeries_X_pow s, PowerSeries.coe_pow, WithZero.coe_mul, valuation_X_pow K s, - mul_le_mul_left₀ (by simp only [ne_eq, WithZero.coe_ne_zero, not_false_iff])] + mul_le_mul_left (by simp only [ne_eq, WithZero.coe_ne_zero, not_false_iff, zero_lt_iff])] · rw [not_le] at ord_nonpos obtain ⟨s, hs⟩ := Int.exists_eq_neg_ofNat (Int.neg_nonpos_of_nonneg (le_of_lt ord_nonpos)) obtain ⟨m, hm⟩ := Int.eq_ofNat_of_zero_le (a := n - s) (by linarith) @@ -535,7 +535,7 @@ theorem coeff_zero_of_lt_valuation {n D : ℤ} {f : LaurentSeries K} apply (intValuation_le_iff_coeff_lt_eq_zero K F).mp _ m (by linarith) rwa [hF, ofPowerSeries_powerSeriesPart f, map_mul, ← hd, hs, neg_sub, sub_eq_add_neg, ofAdd_add, valuation_single_zpow, neg_neg, WithZero.coe_mul, - mul_le_mul_left₀ (by simp only [ne_eq, WithZero.coe_ne_zero, not_false_iff])] + 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} : @@ -558,7 +558,7 @@ theorem valuation_le_iff_coeff_lt_eq_zero {D : ℤ} {f : LaurentSeries K} : rw [powerSeriesPart_coeff f n, hs] apply h_val_f linarith - · simp only [ne_eq, WithZero.coe_ne_zero, not_false_iff] + · simp only [ne_eq, WithZero.coe_ne_zero, not_false_iff, zero_lt_iff] · obtain ⟨s, hs⟩ := Int.exists_eq_neg_ofNat <| neg_nonpos_of_nonneg <| le_of_lt <| not_le.mp ord_nonpos rw [neg_inj] at hs @@ -576,7 +576,7 @@ theorem valuation_le_iff_coeff_lt_eq_zero {D : ℤ} {f : LaurentSeries K} : rw [powerSeriesPart_coeff f n, hs] apply h_val_f (s + n) linarith - · simp only [ne_eq, WithZero.coe_ne_zero, not_false_iff] + · simp only [ne_eq, WithZero.coe_ne_zero, not_false_iff, zero_lt_iff] /- Two Laurent series whose difference has small valuation have the same coefficients for small enough indices. -/ @@ -601,7 +601,7 @@ theorem val_le_one_iff_eq_coe (f : LaurentSeries K) : Valued.v f ≤ (1 : ℤₘ all_goals apply HahnSeries.embDomain_notin_range simp only [Nat.coe_castAddMonoidHom, RelEmbedding.coe_mk, Function.Embedding.coeFn_mk, - Set.mem_range, not_exists, Int.negSucc_lt_zero,] + Set.mem_range, not_exists, Int.negSucc_lt_zero, reduceCtorEq] intro · simp only [not_false_eq_true] · linarith diff --git a/Mathlib/RingTheory/LittleWedderburn.lean b/Mathlib/RingTheory/LittleWedderburn.lean index 0c6818c3c622f..24f9b1cce5f40 100644 --- a/Mathlib/RingTheory/LittleWedderburn.lean +++ b/Mathlib/RingTheory/LittleWedderburn.lean @@ -6,6 +6,7 @@ Authors: Johan Commelin, Eric Rodriguez import Mathlib.GroupTheory.ClassEquation import Mathlib.GroupTheory.GroupAction.ConjAct import Mathlib.RingTheory.Polynomial.Cyclotomic.Eval +import Mathlib.LinearAlgebra.FreeModule.StrongRankCondition /-! # Wedderburn's Little Theorem @@ -95,7 +96,7 @@ private theorem center_eq_top [Finite D] (hD : InductionHyp D) : Subring.center refine not_le_of_lt hZ.lt_top (fun y _ ↦ Subring.mem_center_iff.mpr fun z ↦ ?_) obtain ⟨r, rfl⟩ := hx y obtain ⟨s, rfl⟩ := hx z - rw [smul_mul_smul, smul_mul_smul, mul_comm] + rw [smul_mul_smul_comm, smul_mul_smul_comm, mul_comm] rw [Nat.cast_sum] apply Finset.dvd_sum rintro ⟨x⟩ hx @@ -148,7 +149,7 @@ private theorem center_eq_top [Finite D] : Subring.center D = ⊤ := by rw [IH (Fintype.card R) _ R inferInstance rfl] · trivial rw [← hn, ← Subring.card_top D] - exact Set.card_lt_card hR + convert Set.card_lt_card hR end LittleWedderburn diff --git a/Mathlib/RingTheory/LocalProperties.lean b/Mathlib/RingTheory/LocalProperties.lean index 95ef9fd34099e..47a42f14e2524 100644 --- a/Mathlib/RingTheory/LocalProperties.lean +++ b/Mathlib/RingTheory/LocalProperties.lean @@ -540,7 +540,7 @@ theorem finite_ofLocalizationSpan : RingHom.OfLocalizationSpan @RingHom.Finite : obtain ⟨⟨_, n₂, rfl⟩, hn₂⟩ := IsLocalization.smul_mem_finsetIntegerMultiple_span (Submonoid.powers (r : R)) (Localization.Away (f r)) _ (s₁ r) hn₁ - rw [Submonoid.smul_def, ← Algebra.smul_def, smul_smul, Subtype.coe_mk, ← pow_add] at hn₂ + rw [Submonoid.smul_def, ← Algebra.smul_def, smul_smul, ← pow_add] at hn₂ simp_rw [Submonoid.map_powers] at hn₂ use n₂ + n₁ exact le_iSup (fun x : s => Submodule.span R (sf x : Set S)) r hn₂ @@ -657,7 +657,7 @@ theorem finiteType_ofLocalizationSpan : RingHom.OfLocalizationSpan @RingHom.Fini rw [Submonoid.smul_def, Algebra.smul_def, IsScalarTower.algebraMap_apply R S, ← map_mul] at hn₁ obtain ⟨⟨_, n₂, rfl⟩, hn₂⟩ := IsLocalization.lift_mem_adjoin_finsetIntegerMultiple (Submonoid.powers (r : R)) _ (s₁ r) hn₁ - rw [Submonoid.smul_def, ← Algebra.smul_def, smul_smul, Subtype.coe_mk, ← pow_add] at hn₂ + rw [Submonoid.smul_def, ← Algebra.smul_def, smul_smul, ← pow_add] at hn₂ simp_rw [Submonoid.map_powers] at hn₂ use n₂ + n₁ exact le_iSup (fun x : s => Algebra.adjoin R (sf x : Set S)) r hn₂ diff --git a/Mathlib/RingTheory/LocalRing/Module.lean b/Mathlib/RingTheory/LocalRing/Module.lean index f850665a24192..06103c98b607e 100644 --- a/Mathlib/RingTheory/LocalRing/Module.lean +++ b/Mathlib/RingTheory/LocalRing/Module.lean @@ -93,7 +93,7 @@ theorem span_eq_top_of_tmul_eq_basis [Module.Finite R M] {ι} rw [← map_tensorProduct_mk_eq_top, Submodule.map_span, ← Submodule.restrictScalars_span R k Ideal.Quotient.mk_surjective, Submodule.restrictScalars_eq_top_iff, ← b.span_eq, ← Set.range_comp] - simp only [Function.comp, mk_apply, hb, Basis.span_eq] + simp only [Function.comp_def, mk_apply, hb, Basis.span_eq] end LocalRing @@ -151,10 +151,10 @@ theorem free_of_maximalIdeal_rTensor_injective [Module.FinitePresentation R M] letI : IsNoetherian k (k ⊗[R] (I →₀ R)) := isNoetherian_of_isNoetherianRing_of_finite k (k ⊗[R] (I →₀ R)) choose f hf using TensorProduct.mk_surjective R M k Ideal.Quotient.mk_surjective - -- By choosing an abitrary lift of `b` to `I → M`, we get a surjection `i : Rᴵ → M`. - let i := Finsupp.total I M R (f ∘ b) + -- By choosing an arbitrary lift of `b` to `I → M`, we get a surjection `i : Rᴵ → M`. + let i := Finsupp.linearCombination R (f ∘ b) have hi : Surjective i := by - rw [← LinearMap.range_eq_top, Finsupp.range_total] + rw [← LinearMap.range_eq_top, Finsupp.range_linearCombination] exact LocalRing.span_eq_top_of_tmul_eq_basis (R := R) (f := f ∘ b) b (fun _ ↦ hf _) have : Module.Finite R (LinearMap.ker i) := by constructor diff --git a/Mathlib/RingTheory/Localization/Algebra.lean b/Mathlib/RingTheory/Localization/Algebra.lean index bf2fa84c5d38c..b92decb0ad796 100644 --- a/Mathlib/RingTheory/Localization/Algebra.lean +++ b/Mathlib/RingTheory/Localization/Algebra.lean @@ -58,10 +58,10 @@ def RingHom.toKerIsLocalization (hy : M ≤ Submonoid.comap g T) : RingHom.ker g →ₗ[R] RingHom.ker (IsLocalization.map Q g hy : S →+* Q) where toFun x := ⟨algebraMap R S x, by simp [RingHom.mem_ker, (RingHom.mem_ker g).mp x.property]⟩ map_add' x y := by - simp only [AddSubmonoid.coe_add, Submodule.coe_toAddSubmonoid, map_add, AddSubmonoid.mk_add_mk] + simp only [Submodule.coe_add, map_add, AddMemClass.mk_add_mk] map_smul' a x := by - simp only [SetLike.val_smul, smul_eq_mul, map_mul, RingHom.id_apply, - SetLike.mk_smul_of_tower_mk, Algebra.smul_def] + simp only [SetLike.val_smul, smul_eq_mul, map_mul, id_apply, SetLike.mk_smul_of_tower_mk, + Algebra.smul_def] @[simp] lemma RingHom.toKerIsLocalization_apply (hy : M ≤ Submonoid.comap g T) (r : RingHom.ker g) : diff --git a/Mathlib/RingTheory/Localization/Finiteness.lean b/Mathlib/RingTheory/Localization/Finiteness.lean index 10abd059206ce..e14b622040c88 100644 --- a/Mathlib/RingTheory/Localization/Finiteness.lean +++ b/Mathlib/RingTheory/Localization/Finiteness.lean @@ -53,10 +53,9 @@ lemma of_isLocalizedModule [Module.Finite R M] : Module.Finite Rₚ Mₚ := by (Submodule.span Rₚ (f '' T)).restrictScalars R := by rw [Submodule.span_le]; exact Submodule.subset_span convert (Submodule.span Rₚ (f '' T)).smul_mem - (IsLocalization.mk' Rₚ (1 : R) m) (H this) using 1 + (IsLocalization.mk' Rₚ (1 : R) m) (H this) using 0 · rw [← hyx, ← IsLocalizedModule.mk'_one S, IsLocalizedModule.mk'_smul_mk'] simp - · simp end diff --git a/Mathlib/RingTheory/Localization/NumDen.lean b/Mathlib/RingTheory/Localization/NumDen.lean index 10a844a4ca9d4..07a87d3552ccd 100644 --- a/Mathlib/RingTheory/Localization/NumDen.lean +++ b/Mathlib/RingTheory/Localization/NumDen.lean @@ -81,7 +81,7 @@ theorem num_mul_den_eq_num_mul_den_iff_eq {x y : K} : ⟨fun h ↦ by simpa only [mk'_num_den] using mk'_eq_of_eq' (S := K) h, fun h ↦ by rw [h]⟩ theorem eq_zero_of_num_eq_zero {x : K} (h : num A x = 0) : x = 0 := - num_mul_den_eq_num_iff_eq'.mp (by rw [zero_mul, h, RingHom.map_zero]) + (num_mul_den_eq_num_iff_eq' (A := A)).mp (by rw [zero_mul, h, RingHom.map_zero]) @[simp] lemma num_zero : IsFractionRing.num A (0 : K) = 0 := by diff --git a/Mathlib/RingTheory/Localization/Submodule.lean b/Mathlib/RingTheory/Localization/Submodule.lean index b00dfdb755232..b1cda5e8116b6 100644 --- a/Mathlib/RingTheory/Localization/Submodule.lean +++ b/Mathlib/RingTheory/Localization/Submodule.lean @@ -79,7 +79,7 @@ variable [IsLocalization M S] include M in theorem isNoetherianRing (h : IsNoetherianRing R) : IsNoetherianRing S := by - rw [isNoetherianRing_iff, isNoetherian_iff_wellFounded] at h ⊢ + rw [isNoetherianRing_iff, isNoetherian_iff] at h ⊢ exact OrderEmbedding.wellFounded (IsLocalization.orderEmbedding M S).dual h variable {S M} diff --git a/Mathlib/RingTheory/MvPolynomial/Homogeneous.lean b/Mathlib/RingTheory/MvPolynomial/Homogeneous.lean index f9a0ed2868cf3..4772bb3e6107b 100644 --- a/Mathlib/RingTheory/MvPolynomial/Homogeneous.lean +++ b/Mathlib/RingTheory/MvPolynomial/Homogeneous.lean @@ -49,7 +49,7 @@ variable [CommSemiring R] theorem weightedTotalDegree_one (φ : MvPolynomial σ R) : weightedTotalDegree (1 : σ → ℕ) φ = φ.totalDegree := by simp only [totalDegree, weightedTotalDegree, weight, LinearMap.toAddMonoidHom_coe, - Finsupp.total, Pi.one_apply, Finsupp.coe_lsum, LinearMap.coe_smulRight, LinearMap.id_coe, + linearCombination, Pi.one_apply, Finsupp.coe_lsum, LinearMap.coe_smulRight, LinearMap.id_coe, id, Algebra.id.smul_eq_mul, mul_one] variable (σ R) diff --git a/Mathlib/RingTheory/MvPolynomial/Localization.lean b/Mathlib/RingTheory/MvPolynomial/Localization.lean index 552085840486d..9f1b0b51970ce 100644 --- a/Mathlib/RingTheory/MvPolynomial/Localization.lean +++ b/Mathlib/RingTheory/MvPolynomial/Localization.lean @@ -129,8 +129,8 @@ private lemma auxInv_auxHom : (auxInv S r).comp (auxHom (S := S) r).toRingHom = Function.comp_apply, auxHom_mk, aeval_X, RingHomCompTriple.comp_eq] erw [IsLocalization.lift_mk'_spec] simp only [map_one, RingHom.coe_comp, Function.comp_apply] - rw [← map_one (Ideal.Quotient.mk _)] - rw [← map_mul, Ideal.Quotient.mk_eq_mk_iff_sub_mem, ← Ideal.neg_mem_iff, neg_sub] + rw [← map_one (Ideal.Quotient.mk _), ← map_mul, Ideal.Quotient.mk_eq_mk_iff_sub_mem, + ← Ideal.neg_mem_iff, neg_sub] exact Ideal.mem_span_singleton_self (C r * X x - 1) /-- The canonical algebra isomorphism from `MvPolynomial Unit R` quotiented by diff --git a/Mathlib/RingTheory/MvPolynomial/Tower.lean b/Mathlib/RingTheory/MvPolynomial/Tower.lean index 691f027ab1158..95f6fb384851e 100644 --- a/Mathlib/RingTheory/MvPolynomial/Tower.lean +++ b/Mathlib/RingTheory/MvPolynomial/Tower.lean @@ -47,7 +47,7 @@ theorem aeval_algebraMap_apply (x : σ → A) (p : MvPolynomial σ R) : rw [aeval_def, aeval_def, ← coe_eval₂Hom, ← coe_eval₂Hom, map_eval₂Hom, ← IsScalarTower.algebraMap_eq] -- Porting note: added - simp only [Function.comp] + simp only [Function.comp_def] theorem aeval_algebraMap_eq_zero_iff [NoZeroSMulDivisors A B] [Nontrivial B] (x : σ → A) (p : MvPolynomial σ R) : aeval (algebraMap A B ∘ x) p = 0 ↔ aeval x p = 0 := by diff --git a/Mathlib/RingTheory/MvPolynomial/WeightedHomogeneous.lean b/Mathlib/RingTheory/MvPolynomial/WeightedHomogeneous.lean index 2f0b07d5dd242..a5d6459f7d56f 100644 --- a/Mathlib/RingTheory/MvPolynomial/WeightedHomogeneous.lean +++ b/Mathlib/RingTheory/MvPolynomial/WeightedHomogeneous.lean @@ -214,7 +214,7 @@ theorem isWeightedHomogeneous_one (w : σ → M) : IsWeightedHomogeneous w (1 : theorem isWeightedHomogeneous_X (w : σ → M) (i : σ) : IsWeightedHomogeneous w (X i : MvPolynomial σ R) (w i) := by apply isWeightedHomogeneous_monomial - simp only [weight, LinearMap.toAddMonoidHom_coe, total_single, one_nsmul] + simp only [weight, LinearMap.toAddMonoidHom_coe, linearCombination_single, one_nsmul] namespace IsWeightedHomogeneous @@ -506,7 +506,7 @@ theorem weightedHomogeneousComponent_zero [NoZeroSMulDivisors ℕ M] (hw : ∀ i rcases Classical.em (d = 0) with (rfl | hd) · simp only [coeff_weightedHomogeneousComponent, if_pos, map_zero, coeff_zero_C] · rw [coeff_weightedHomogeneousComponent, if_neg, coeff_C, if_neg (Ne.symm hd)] - simp only [weight, LinearMap.toAddMonoidHom_coe, Finsupp.total_apply, Finsupp.sum, + simp only [weight, LinearMap.toAddMonoidHom_coe, Finsupp.linearCombination_apply, Finsupp.sum, sum_eq_zero_iff, Finsupp.mem_support_iff, Ne, smul_eq_zero, not_forall, not_or, and_self_left, exists_prop] simp only [DFunLike.ext_iff, Finsupp.coe_zero, Pi.zero_apply, not_forall] at hd @@ -531,7 +531,7 @@ variable [CanonicallyLinearOrderedAddCommMonoid M] {w : σ → M} (φ : MvPolyno has weighted degree zero if and only if `∀ x : σ, m x = 0`. -/ theorem weightedDegree_eq_zero_iff (hw : NonTorsionWeight w) {m : σ →₀ ℕ} : weight w m = 0 ↔ ∀ x : σ, m x = 0 := by - simp only [weight, Finsupp.total, LinearMap.toAddMonoidHom_coe, coe_lsum, + simp only [weight, Finsupp.linearCombination, LinearMap.toAddMonoidHom_coe, coe_lsum, LinearMap.coe_smulRight, LinearMap.id_coe, id_eq] rw [Finsupp.sum, Finset.sum_eq_zero_iff] apply forall_congr' @@ -582,7 +582,7 @@ theorem weightedHomogeneousComponent_eq_zero_of_not_mem [DecidableEq M] variable (R) -/-- The `decompose'` argument of `weightedDecomposition`. -/ +/-- The `decompose'` argument of `weightedDecomposition`. -/ def decompose' [DecidableEq M] := fun φ : MvPolynomial σ R => DirectSum.mk (fun i : M => ↥(weightedHomogeneousSubmodule R w i)) (Finset.image (weight w) φ.support) fun m => diff --git a/Mathlib/RingTheory/Nakayama.lean b/Mathlib/RingTheory/Nakayama.lean index 3c19bfdae99d5..2cf0c3850d107 100644 --- a/Mathlib/RingTheory/Nakayama.lean +++ b/Mathlib/RingTheory/Nakayama.lean @@ -46,7 +46,7 @@ namespace Submodule /-- **Nakayama's Lemma** - A slightly more general version of (2) in [Stacks 00DV](https://stacks.math.columbia.edu/tag/00DV). -See also `eq_bot_of_le_smul_of_le_jacobson_bot` for the special case when `J = ⊥`. -/ +See also `eq_bot_of_le_smul_of_le_jacobson_bot` for the special case when `J = ⊥`. -/ theorem eq_smul_of_le_smul_of_le_jacobson {I J : Ideal R} {N : Submodule R M} (hN : N.FG) (hIN : N ≤ I • N) (hIjac : I ≤ jacobson J) : N = J • N := by refine le_antisymm ?_ (Submodule.smul_le.2 fun _ _ _ => Submodule.smul_mem _ _) @@ -123,7 +123,7 @@ theorem sup_eq_sup_smul_of_le_smul_of_le_jacobson {I J : Ideal R} {N N' : Submod /-- **Nakayama's Lemma** - A slightly more general version of (4) in [Stacks 00DV](https://stacks.math.columbia.edu/tag/00DV). -See also `smul_le_of_le_smul_of_le_jacobson_bot` for the special case when `J = ⊥`. -/ +See also `smul_le_of_le_smul_of_le_jacobson_bot` for the special case when `J = ⊥`. -/ theorem sup_smul_eq_sup_smul_of_le_smul_of_le_jacobson {I J : Ideal R} {N N' : Submodule R M} (hN' : N'.FG) (hIJ : I ≤ jacobson J) (hNN : N' ≤ N ⊔ I • N') : N ⊔ I • N' = N ⊔ J • N' := ((sup_le_sup_left smul_le_right _).antisymm (sup_le le_sup_left hNN)).trans diff --git a/Mathlib/RingTheory/Nilpotent/Lemmas.lean b/Mathlib/RingTheory/Nilpotent/Lemmas.lean index 36d5f8aa60445..d5d61f66838de 100644 --- a/Mathlib/RingTheory/Nilpotent/Lemmas.lean +++ b/Mathlib/RingTheory/Nilpotent/Lemmas.lean @@ -103,7 +103,8 @@ lemma isNilpotent.restrict {R M : Type*} [Semiring R] [AddCommMonoid M] [Module {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 [LinearMap.pow_restrict n, LinearMap.restrict_apply, hn]⟩ + exact ⟨n, LinearMap.ext fun m ↦ by simp only [LinearMap.pow_restrict n, hn, + LinearMap.restrict_apply, LinearMap.zero_apply]; rfl⟩ 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 5115056fb0474..f3e0b396a8eb4 100644 --- a/Mathlib/RingTheory/Noetherian.lean +++ b/Mathlib/RingTheory/Noetherian.lean @@ -34,8 +34,8 @@ Let `R` be a ring and let `M` and `P` be `R`-modules. Let `N` be an `R`-submodul ## Main statements -* `isNoetherian_iff_wellFounded` is the theorem that an R-module M is Noetherian iff - `>` is well-founded on `Submodule R M`. +* `isNoetherian_iff` is the theorem that an R-module M is Noetherian iff `>` is well-founded on + `Submodule R M`. Note that the Hilbert basis theorem, that if a commutative ring R is Noetherian then so is R[X], is proved in `RingTheory.Polynomial`. @@ -289,7 +289,7 @@ 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_wellFounded : +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 -- Porting note: inlining this makes rw complain about it being a metavariable @@ -298,20 +298,28 @@ theorem isNoetherian_iff_wellFounded : ⟨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 ↔ WellFoundedGT (Submodule R M) := by + rw [isNoetherian_iff, ← isWellFounded_iff] + +alias ⟨IsNoetherian.wellFoundedGT, isNoetherian_mk⟩ := isNoetherian_iff' + +instance wellFoundedGT [h : IsNoetherian R M] : WellFoundedGT (Submodule R M) := + h.wellFoundedGT + theorem isNoetherian_iff_fg_wellFounded : - IsNoetherian R M ↔ - WellFounded - ((· > ·) : { N : Submodule R M // N.FG } → { N : Submodule R M // N.FG } → Prop) := by + IsNoetherian R M ↔ WellFoundedGT { N : Submodule R M // N.FG } := by let α := { N : Submodule R M // N.FG } constructor · intro H let f : α ↪o Submodule R M := OrderEmbedding.subtype _ - exact OrderEmbedding.wellFounded f.dual (isNoetherian_iff_wellFounded.mp H) + exact OrderEmbedding.wellFoundedLT f.dual · intro H constructor intro N obtain ⟨⟨N₀, h₁⟩, e : N₀ ≤ N, h₂⟩ := - WellFounded.has_min H { N' : α | N'.1 ≤ N } ⟨⟨⊥, Submodule.fg_bot⟩, @bot_le _ _ _ N⟩ + WellFounded.has_min H.wf { N' : α | N'.1 ≤ N } ⟨⟨⊥, Submodule.fg_bot⟩, @bot_le _ _ _ N⟩ convert h₁ refine (e.antisymm ?_).symm by_contra h₃ @@ -322,24 +330,16 @@ theorem isNoetherian_iff_fg_wellFounded : sup_le ((Submodule.span_singleton_le_iff_mem _ _).mpr hx₁) e)] exact (le_sup_left : (R ∙ x) ≤ _) (Submodule.mem_span_singleton_self _) -variable (R M) - -theorem wellFounded_submodule_gt (R M) [Semiring R] [AddCommMonoid M] [Module R M] : - ∀ [IsNoetherian R M], WellFounded ((· > ·) : Submodule R M → Submodule R M → Prop) := - isNoetherian_iff_wellFounded.mp ‹_› - -variable {R M} - /-- A module is Noetherian iff every nonempty set of submodules has a maximal submodule among them. -/ theorem set_has_maximal_iff_noetherian : (∀ a : Set <| Submodule R M, a.Nonempty → ∃ M' ∈ a, ∀ I ∈ a, ¬M' < I) ↔ IsNoetherian R M := by - rw [isNoetherian_iff_wellFounded, WellFounded.wellFounded_iff_has_min] + rw [isNoetherian_iff, WellFounded.wellFounded_iff_has_min] /-- A module is Noetherian iff every increasing chain of submodules stabilizes. -/ theorem monotone_stabilizes_iff_noetherian : (∀ f : ℕ →o Submodule R M, ∃ n, ∀ m, n ≤ m → f n = f m) ↔ IsNoetherian R M := by - rw [isNoetherian_iff_wellFounded, WellFounded.monotone_chain_condition] + rw [isNoetherian_iff, WellFounded.monotone_chain_condition] theorem eventuallyConst_of_isNoetherian [IsNoetherian R M] (f : ℕ →o Submodule R M) : atTop.EventuallyConst f := by @@ -349,7 +349,7 @@ theorem eventuallyConst_of_isNoetherian [IsNoetherian R M] (f : ℕ →o Submodu /-- If `∀ I > J, P I` implies `P J`, then `P` holds for all submodules. -/ theorem IsNoetherian.induction [IsNoetherian R M] {P : Submodule R M → Prop} (hgt : ∀ I, (∀ J > I, P J) → P I) (I : Submodule R M) : P I := - WellFounded.recursion (wellFounded_submodule_gt R M) I hgt + IsWellFounded.induction _ I hgt end @@ -364,14 +364,14 @@ lemma Submodule.finite_ne_bot_of_independent {ι : Type*} {N : ι → Submodule (h : CompleteLattice.Independent N) : Set.Finite {i | N i ≠ ⊥} := CompleteLattice.WellFounded.finite_ne_bot_of_independent - (isNoetherian_iff_wellFounded.mp inferInstance) h + (IsWellFounded.wf) 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 - have hwf := isNoetherian_iff_wellFounded.mp (by infer_instance : IsNoetherian R M) - refine CompleteLattice.WellFounded.finite_of_independent hwf hv.independent_span_singleton + refine CompleteLattice.WellFounded.finite_of_independent IsWellFounded.wf + hv.independent_span_singleton fun i contra => ?_ apply hv.ne_zero i have : v i ∈ R ∙ v i := Submodule.mem_span_singleton_self (v i) @@ -389,9 +389,8 @@ alias finite_of_linearIndependent := LinearIndependent.set_finite_of_isNoetheria theorem isNoetherian_of_range_eq_ker [IsNoetherian R P] (f : M →ₗ[R] N) (g : N →ₗ[R] P) (h : LinearMap.range f = LinearMap.ker g) : IsNoetherian R N := - isNoetherian_iff_wellFounded.2 <| + isNoetherian_mk <| wellFounded_gt_exact_sequence - (wellFounded_submodule_gt R _) (wellFounded_submodule_gt R _) (LinearMap.range f) (Submodule.map (f.ker.liftQ f <| le_rfl)) (Submodule.comap (f.ker.liftQ f <| le_rfl)) @@ -426,7 +425,7 @@ lemma LinearMap.eventually_iSup_ker_pow_eq (f : M →ₗ[R] M) : · rw [← hn _ (hm.trans h), hn _ hm] · exact f.iterateKer.monotone h.le -/-- **Orzech's theorem** for Noetherian module: if `R` is a ring (not necessarily commutative), +/-- **Orzech's theorem** for Noetherian modules: if `R` is a ring (not necessarily commutative), `M` and `N` are `R`-modules, `M` is Noetherian, `i : N →ₗ[R] M` is injective, `f : N →ₗ[R] M` is surjective, then `f` is also injective. The proof here is adapted from Djoković's paper *Epimorphisms of modules which must be isomorphisms* [djokovic1973], @@ -440,7 +439,7 @@ theorem IsNoetherian.injective_of_surjective_of_injective (i f : N →ₗ[R] M) exact LinearMap.ker_eq_bot.1 <| bot_unique <| f.ker_le_of_iterateMapComap_eq_succ i ⊥ n (H _ (Nat.le_succ _)) hf hi -/-- **Orzech's theorem** for Noetherian module: if `R` is a ring (not necessarily commutative), +/-- **Orzech's theorem** for Noetherian modules: if `R` is a ring (not necessarily commutative), `M` is a Noetherian `R`-module, `N` is a submodule, `f : N →ₗ[R] M` is surjective, then `f` is also injective. -/ theorem IsNoetherian.injective_of_surjective_of_submodule @@ -459,8 +458,7 @@ theorem IsNoetherian.bijective_of_surjective_endomorphism (f : M →ₗ[R] M) /-- A sequence `f` of submodules of a noetherian module, with `f (n+1)` disjoint from the supremum of `f 0`, ..., `f n`, -is eventually zero. --/ +is eventually zero. -/ theorem IsNoetherian.disjoint_partialSups_eventually_bot (f : ℕ → Submodule R M) (h : ∀ n, Disjoint (partialSups f n) (f (n + 1))) : ∃ n : ℕ, ∀ m, n ≤ m → f m = ⊥ := by @@ -493,8 +491,7 @@ def IsNoetherian.equivPUnitOfProdInjective (f : M × N →ₗ[R] M) end /-- A (semi)ring is Noetherian if it is Noetherian as a module over itself, -i.e. all its ideals are finitely generated. --/ +i.e. all its ideals are finitely generated. -/ abbrev IsNoetherianRing (R) [Semiring R] := IsNoetherian R R @@ -519,16 +516,14 @@ instance (priority := 100) isNoetherian_of_subsingleton (R M) [Subsingleton R] [ isNoetherian_of_finite R M theorem isNoetherian_of_submodule_of_noetherian (R M) [Semiring R] [AddCommMonoid M] [Module R M] - (N : Submodule R M) (h : IsNoetherian R M) : IsNoetherian R N := by - rw [isNoetherian_iff_wellFounded] at h ⊢ - exact OrderEmbedding.wellFounded (Submodule.MapSubtype.orderEmbedding N).dual h + (N : Submodule R M) (h : IsNoetherian R M) : IsNoetherian R N := + isNoetherian_mk ⟨OrderEmbedding.wellFounded (Submodule.MapSubtype.orderEmbedding N).dual h.wf⟩ /-- If `M / S / R` is a scalar tower, and `M / R` is Noetherian, then `M / S` is also noetherian. -/ theorem isNoetherian_of_tower (R) {S M} [Semiring R] [Semiring S] [AddCommMonoid M] [SMul R S] - [Module S M] [Module R M] [IsScalarTower R S M] (h : IsNoetherian R M) : IsNoetherian S M := by - rw [isNoetherian_iff_wellFounded] at h ⊢ - exact (Submodule.restrictScalarsEmbedding R S M).dual.wellFounded h + [Module S M] [Module R M] [IsScalarTower R S M] (h : IsNoetherian R M) : IsNoetherian S M := + isNoetherian_mk ⟨(Submodule.restrictScalarsEmbedding R S M).dual.wellFounded h.wf⟩ theorem isNoetherian_of_fg_of_noetherian {R M} [Ring R] [AddCommGroup M] [Module R M] (N : Submodule R M) [I : IsNoetherianRing R] (hN : N.FG) : IsNoetherian R N := by @@ -555,12 +550,12 @@ theorem isNoetherian_of_fg_of_noetherian {R M} [Ring R] [AddCommGroup M] [Module · rw [LinearMap.range_eq_top] rintro ⟨n, hn⟩ change n ∈ N at hn - rw [← hs, ← Set.image_id (s : Set M), Finsupp.mem_span_image_iff_total] at hn + rw [← hs, ← Set.image_id (s : Set M), Finsupp.mem_span_image_iff_linearCombination] at hn rcases hn with ⟨l, hl1, hl2⟩ refine ⟨fun x => l x, Subtype.ext ?_⟩ change (∑ i ∈ s.attach, l i • (i : M)) = n rw [s.sum_attach fun i ↦ l i • i, ← hl2, - Finsupp.total_apply, Finsupp.sum, eq_comm] + Finsupp.linearCombination_apply, Finsupp.sum, eq_comm] refine Finset.sum_subset hl1 fun x _ hx => ?_ rw [Finsupp.not_mem_support_iff.1 hx, zero_smul] @@ -578,9 +573,8 @@ theorem isNoetherian_span_of_finite (R) {M} [Ring R] [AddCommGroup M] [Module R isNoetherian_of_fg_of_noetherian _ (Submodule.fg_def.mpr ⟨A, hA, rfl⟩) theorem isNoetherianRing_of_surjective (R) [Ring R] (S) [Ring S] (f : R →+* S) - (hf : Function.Surjective f) [H : IsNoetherianRing R] : IsNoetherianRing S := by - rw [isNoetherianRing_iff, isNoetherian_iff_wellFounded] at H ⊢ - exact OrderEmbedding.wellFounded (Ideal.orderEmbeddingOfSurjective f hf).dual H + (hf : Function.Surjective f) [H : IsNoetherianRing R] : IsNoetherianRing S := + isNoetherian_mk ⟨OrderEmbedding.wellFounded (Ideal.orderEmbeddingOfSurjective f hf).dual H.wf⟩ instance isNoetherianRing_range {R} [Ring R] {S} [Ring S] (f : R →+* S) [IsNoetherianRing R] : IsNoetherianRing f.range := diff --git a/Mathlib/RingTheory/NonUnitalSubring/Basic.lean b/Mathlib/RingTheory/NonUnitalSubring/Basic.lean index 0a1478bc862f1..3d5642917f222 100644 --- a/Mathlib/RingTheory/NonUnitalSubring/Basic.lean +++ b/Mathlib/RingTheory/NonUnitalSubring/Basic.lean @@ -743,7 +743,7 @@ theorem mem_closure_iff {s : Set R} {x} : mul_mem hx hy) (zero_mem _) (fun x y hx hy => add_mem hx hy) fun x hx => neg_mem hx⟩ -/-- If all elements of `s : Set A` commute pairwise, then `closure s` is a commutative ring. -/ +/-- If all elements of `s : Set A` commute pairwise, then `closure s` is a commutative ring. -/ def closureNonUnitalCommRingOfComm {R : Type u} [NonUnitalRing R] {s : Set R} (hcomm : ∀ a ∈ s, ∀ b ∈ s, a * b = b * a) : NonUnitalCommRing (closure s) := { (closure s).toNonUnitalRing with diff --git a/Mathlib/RingTheory/OreLocalization/Ring.lean b/Mathlib/RingTheory/OreLocalization/Ring.lean index 952d2bd534a8f..2a911ebd37017 100644 --- a/Mathlib/RingTheory/OreLocalization/Ring.lean +++ b/Mathlib/RingTheory/OreLocalization/Ring.lean @@ -229,7 +229,7 @@ instance nontrivial : Nontrivial R[R⁰⁻¹] := variable [NoZeroDivisors R] open Classical in -/-- The inversion of Ore fractions for a ring without zero divisors, satisying `0⁻¹ = 0` and +/-- The inversion of Ore fractions for a ring without zero divisors, satisfying `0⁻¹ = 0` and `(r /ₒ r')⁻¹ = r' /ₒ r` for `r ≠ 0`. -/ @[irreducible] protected def inv : R[R⁰⁻¹] → R[R⁰⁻¹] := diff --git a/Mathlib/RingTheory/Polynomial/Basic.lean b/Mathlib/RingTheory/Polynomial/Basic.lean index f431e6d14be74..f8a24b9466bbf 100644 --- a/Mathlib/RingTheory/Polynomial/Basic.lean +++ b/Mathlib/RingTheory/Polynomial/Basic.lean @@ -173,6 +173,34 @@ theorem degreeLT_succ_eq_degreeLE {n : ℕ} : degreeLT R (n + 1) = degreeLE R n · rw [mem_degreeLT, mem_degreeLE, ← natDegree_lt_iff_degree_lt (by rwa [ne_eq]), ← natDegree_le_iff_degree_le, Nat.lt_succ] +/-- The equivalence between monic polynomials of degree `n` and polynomials of degree less than +`n`, formed by adding a term `X ^ n`. -/ +def monicEquivDegreeLT [Nontrivial R] (n : ℕ) : + { p : R[X] // p.Monic ∧ p.natDegree = n } ≃ degreeLT R n where + toFun p := ⟨p.1.eraseLead, by + rcases p with ⟨p, hp, rfl⟩ + simp only [mem_degreeLT] + refine lt_of_lt_of_le ?_ degree_le_natDegree + exact degree_eraseLead_lt (ne_zero_of_ne_zero_of_monic one_ne_zero hp)⟩ + invFun := fun p => + ⟨X^n + p.1, monic_X_pow_add (mem_degreeLT.1 p.2), by + rw [natDegree_add_eq_left_of_degree_lt] + · simp + · simp [mem_degreeLT.1 p.2]⟩ + left_inv := by + rintro ⟨p, hp, rfl⟩ + ext1 + simp only + conv_rhs => rw [← eraseLead_add_C_mul_X_pow p] + simp [Monic.def.1 hp, add_comm] + right_inv := by + rintro ⟨p, hp⟩ + ext1 + simp only + rw [eraseLead_add_of_degree_lt_left] + · simp + · simp [mem_degreeLT.1 hp] + /-- For every polynomial `p` in the span of a set `s : Set R[X]`, there exists a polynomial of `p' ∈ s` with higher degree. See also `Polynomial.exists_degree_le_of_mem_span_of_finite`. -/ theorem exists_degree_le_of_mem_span {s : Set R[X]} {p : R[X]} @@ -219,7 +247,7 @@ theorem span_of_finite_le_degreeLT {s : Set R[X]} (s_fin : s.Finite) : exact ⟨n + 1, by rwa [degreeLT_succ_eq_degreeLE]⟩ /-- If `R` is a nontrivial ring, the polynomials `R[X]` are not finite as an `R`-module. When `R` is -a field, this is equivalent to `R[X]` being an infinite-dimensional vector space over `R`. -/ +a field, this is equivalent to `R[X]` being an infinite-dimensional vector space over `R`. -/ theorem not_finite [Nontrivial R] : ¬ Module.Finite R R[X] := by rw [Module.finite_def, Submodule.fg_def] push_neg @@ -876,9 +904,7 @@ end Polynomial protected theorem Polynomial.isNoetherianRing [inst : IsNoetherianRing R] : IsNoetherianRing R[X] := isNoetherianRing_iff.2 ⟨fun I : Ideal R[X] => - let M := - WellFounded.min (isNoetherian_iff_wellFounded.1 (by infer_instance)) - (Set.range I.leadingCoeffNth) ⟨_, ⟨0, rfl⟩⟩ + let M := inst.wf.min (Set.range I.leadingCoeffNth) ⟨_, ⟨0, rfl⟩⟩ have hm : M ∈ Set.range I.leadingCoeffNth := WellFounded.min_mem _ _ _ let ⟨N, HN⟩ := hm let ⟨s, hs⟩ := I.is_fg_degreeLE N @@ -887,7 +913,7 @@ protected theorem Polynomial.isNoetherianRing [inst : IsNoetherianRing R] : IsNo Classical.by_contradiction fun hxm => haveI : IsNoetherian R R := inst have : ¬M < I.leadingCoeffNth k := by - refine WellFounded.not_lt_min (wellFounded_submodule_gt R R) _ _ ?_; exact ⟨k, rfl⟩ + refine WellFounded.not_lt_min inst.wf _ _ ?_; exact ⟨k, rfl⟩ this ⟨HN ▸ I.leadingCoeffNth_mono (le_of_lt h), fun H => hxm (H hx)⟩ have hs2 : ∀ {x}, x ∈ I.degreeLE N → x ∈ Ideal.span (↑s : Set R[X]) := hs ▸ fun hx => @@ -970,8 +996,8 @@ theorem exists_irreducible_of_natDegree_ne_zero {R : Type u} [CommRing R] [IsDom theorem linearIndependent_powers_iff_aeval (f : M →ₗ[R] M) (v : M) : (LinearIndependent R fun n : ℕ => (f ^ n) v) ↔ ∀ p : R[X], aeval f p v = 0 → p = 0 := by rw [linearIndependent_iff] - simp only [Finsupp.total_apply, aeval_endomorphism, forall_iff_forall_finsupp, Sum, support, - coeff, ofFinsupp_eq_zero] + simp only [Finsupp.linearCombination_apply, aeval_endomorphism, forall_iff_forall_finsupp, Sum, + support, coeff, ofFinsupp_eq_zero] exact Iff.rfl attribute [-instance] Ring.toNonAssocRing diff --git a/Mathlib/RingTheory/Polynomial/Content.lean b/Mathlib/RingTheory/Polynomial/Content.lean index 273f4f4ba8827..c92ff552d810e 100644 --- a/Mathlib/RingTheory/Polynomial/Content.lean +++ b/Mathlib/RingTheory/Polynomial/Content.lean @@ -207,7 +207,7 @@ theorem IsPrimitive.content_eq_one {p : R[X]} (hp : p.IsPrimitive) : p.content = section PrimPart /-- The primitive part of a polynomial `p` is the primitive polynomial gained by dividing `p` by - `p.content`. If `p = 0`, then `p.primPart = 1`. -/ + `p.content`. If `p = 0`, then `p.primPart = 1`. -/ noncomputable def primPart (p : R[X]) : R[X] := letI := Classical.decEq R if p = 0 then 1 else Classical.choose (C_content_dvd p) diff --git a/Mathlib/RingTheory/Polynomial/Cyclotomic/Eval.lean b/Mathlib/RingTheory/Polynomial/Cyclotomic/Eval.lean index cdd1003e5f3ad..af7686e449eba 100644 --- a/Mathlib/RingTheory/Polynomial/Cyclotomic/Eval.lean +++ b/Mathlib/RingTheory/Polynomial/Cyclotomic/Eval.lean @@ -6,7 +6,7 @@ Authors: Eric Rodriguez import Mathlib.RingTheory.Polynomial.Cyclotomic.Roots import Mathlib.Tactic.ByContra import Mathlib.Topology.Algebra.Polynomial -import Mathlib.NumberTheory.Padics.PadicVal +import Mathlib.NumberTheory.Padics.PadicVal.Basic import Mathlib.Analysis.Complex.Arg /-! @@ -80,7 +80,7 @@ theorem cyclotomic_pos {n : ℕ} (hn : 2 < n) {R} [LinearOrderedCommRing R] (x : cases' h with hk hx · refine (ih _ hi.2.2 (Nat.two_lt_of_ne ?_ hi.1 ?_)).le <;> rintro rfl · exact hn'.ne' (zero_dvd_iff.mp hi.2.1) - · exact even_iff_not_odd.mp (even_iff_two_dvd.mpr hi.2.1) hk + · exact not_odd_iff_even.2 (even_iff_two_dvd.mpr hi.2.1) hk · rcases eq_or_ne i 2 with (rfl | hk) · simpa only [eval_X, eval_one, cyclotomic_two, eval_add] using hx.le refine (ih _ hi.2.2 (Nat.two_lt_of_ne ?_ hi.1 hk)).le diff --git a/Mathlib/RingTheory/Polynomial/Cyclotomic/Roots.lean b/Mathlib/RingTheory/Polynomial/Cyclotomic/Roots.lean index ac741208832d2..74c4705dddc41 100644 --- a/Mathlib/RingTheory/Polynomial/Cyclotomic/Roots.lean +++ b/Mathlib/RingTheory/Polynomial/Cyclotomic/Roots.lean @@ -113,7 +113,7 @@ theorem cyclotomic.roots_to_finset_eq_primitiveRoots [NeZero (n : R)] : -- `simp [cyclotomic_ne_zero n R, isRoot_cyclotomic_iff, mem_primitiveRoots,` -- ` NeZero.pos_of_neZero_natCast R]` simp only [mem_primitiveRoots, NeZero.pos_of_neZero_natCast R] - convert isRoot_cyclotomic_iff (n := n) (μ := a) + convert isRoot_cyclotomic_iff (n := n) (μ := a) using 0 simp [cyclotomic_ne_zero n R] theorem cyclotomic.roots_eq_primitiveRoots_val [NeZero (n : R)] : diff --git a/Mathlib/RingTheory/Polynomial/Eisenstein/IsIntegral.lean b/Mathlib/RingTheory/Polynomial/Eisenstein/IsIntegral.lean index 50e6698cdb932..a7f446664bdad 100644 --- a/Mathlib/RingTheory/Polynomial/Eisenstein/IsIntegral.lean +++ b/Mathlib/RingTheory/Polynomial/Eisenstein/IsIntegral.lean @@ -53,6 +53,8 @@ theorem cyclotomic_comp_X_add_one_isEisensteinAt [hp : Fact p.Prime] : congr congr next => skip + congr + next => skip ext rw [lcoeff_apply, ← C_eq_natCast, C_mul_X_pow_eq_monomial, coeff_monomial] rw [natDegree_comp, show (X + 1 : ℤ[X]) = X + C 1 by simp, natDegree_X_add_C, mul_one, diff --git a/Mathlib/RingTheory/Polynomial/GaussLemma.lean b/Mathlib/RingTheory/Polynomial/GaussLemma.lean index ca29983d56934..1d03f572b1ea9 100644 --- a/Mathlib/RingTheory/Polynomial/GaussLemma.lean +++ b/Mathlib/RingTheory/Polynomial/GaussLemma.lean @@ -143,7 +143,7 @@ open IsIntegrallyClosed theorem Monic.irreducible_iff_irreducible_map_fraction_map [IsIntegrallyClosed R] {p : R[X]} (h : p.Monic) : Irreducible p ↔ Irreducible (p.map <| algebraMap R K) := by /- The ← direction follows from `IsPrimitive.irreducible_of_irreducible_map_of_injective`. - For the → direction, it is enought to show that if `(p.map <| algebraMap R K) = a * b` and + For the → direction, it is enough to show that if `(p.map <| algebraMap R K) = a * b` and `a` is not a unit then `b` is a unit -/ refine ⟨fun hp => diff --git a/Mathlib/RingTheory/Polynomial/Hermite/Basic.lean b/Mathlib/RingTheory/Polynomial/Hermite/Basic.lean index a4a78d9406f1c..6f7d2d23edce3 100644 --- a/Mathlib/RingTheory/Polynomial/Hermite/Basic.lean +++ b/Mathlib/RingTheory/Polynomial/Hermite/Basic.lean @@ -116,7 +116,7 @@ theorem hermite_monic (n : ℕ) : (hermite n).Monic := leadingCoeff_hermite n theorem coeff_hermite_of_odd_add {n k : ℕ} (hnk : Odd (n + k)) : coeff (hermite n) k = 0 := by - induction n generalizing k with + induction n generalizing k with | zero => rw [zero_add k] at hnk exact coeff_hermite_of_lt hnk.pos @@ -197,7 +197,7 @@ theorem coeff_hermite (n k : ℕ) : if Even (n + k) then (-1 : ℤ) ^ ((n - k) / 2) * (n - k - 1)‼ * Nat.choose n k else 0 := by split_ifs with h · exact coeff_hermite_of_even_add h - · exact coeff_hermite_of_odd_add (Nat.odd_iff_not_even.mpr h) + · exact coeff_hermite_of_odd_add (Nat.not_even_iff_odd.1 h) end CoeffExplicit diff --git a/Mathlib/RingTheory/PowerBasis.lean b/Mathlib/RingTheory/PowerBasis.lean index ce69b35f56744..b0b9c2d3d7536 100644 --- a/Mathlib/RingTheory/PowerBasis.lean +++ b/Mathlib/RingTheory/PowerBasis.lean @@ -40,9 +40,7 @@ power basis, powerbasis -/ -open Polynomial - -open Polynomial +open Polynomial Finsupp variable {R S T : Type*} [CommRing R] [Ring S] [Algebra R S] variable {A B : Type*} [CommRing A] [CommRing B] [Algebra A B] @@ -89,9 +87,9 @@ theorem mem_span_pow' {x y : S} {d : ℕ} : ext n simp_rw [Set.mem_range, Set.mem_image, Finset.mem_coe, Finset.mem_range] exact ⟨fun ⟨⟨i, hi⟩, hy⟩ => ⟨i, hi, hy⟩, fun ⟨i, hi, hy⟩ => ⟨⟨i, hi⟩, hy⟩⟩ - simp only [this, Finsupp.mem_span_image_iff_total, degree_lt_iff_coeff_zero, support, + simp only [this, mem_span_image_iff_linearCombination, degree_lt_iff_coeff_zero, Finsupp.support, exists_iff_exists_finsupp, coeff, aeval_def, eval₂RingHom', eval₂_eq_sum, Polynomial.sum, - Finsupp.mem_supported', Finsupp.total, Finsupp.sum, Algebra.smul_def, eval₂_zero, exists_prop, + mem_supported', linearCombination, Finsupp.sum, Algebra.smul_def, eval₂_zero, exists_prop, LinearMap.id_coe, eval₂_one, id, not_lt, Finsupp.coe_lsum, LinearMap.coe_smulRight, Finset.mem_range, AlgHom.coe_mks, Finset.mem_coe] simp_rw [@eq_comm _ y] @@ -164,8 +162,8 @@ noncomputable def minpolyGen (pb : PowerBasis A S) : A[X] := theorem aeval_minpolyGen (pb : PowerBasis A S) : aeval pb.gen (minpolyGen pb) = 0 := by simp_rw [minpolyGen, map_sub, map_sum, map_mul, map_pow, aeval_C, ← Algebra.smul_def, aeval_X] - refine sub_eq_zero.mpr ((pb.basis.total_repr (pb.gen ^ pb.dim)).symm.trans ?_) - rw [Finsupp.total_apply, Finsupp.sum_fintype] <;> + refine sub_eq_zero.mpr ((pb.basis.linearCombination_repr (pb.gen ^ pb.dim)).symm.trans ?_) + rw [Finsupp.linearCombination_apply, Finsupp.sum_fintype] <;> simp only [pb.coe_basis, zero_smul, eq_self_iff_true, imp_true_iff] theorem minpolyGen_monic (pb : PowerBasis A S) : Monic (minpolyGen pb) := by diff --git a/Mathlib/RingTheory/PowerSeries/Order.lean b/Mathlib/RingTheory/PowerSeries/Order.lean index f73b2bb21d977..cec9d16a7d726 100644 --- a/Mathlib/RingTheory/PowerSeries/Order.lean +++ b/Mathlib/RingTheory/PowerSeries/Order.lean @@ -272,7 +272,7 @@ theorem order_eq_multiplicity_X {R : Type*} [Semiring R] [@DecidableRel R⟦X⟧ exact Nat.lt_succ_self _ /-- Given a non-zero power series `f`, `divided_by_X_pow_order f` is the power series obtained by - dividing out the largest power of X that divides `f`, that is its order-/ + dividing out the largest power of X that divides `f`, that is its order -/ def divided_by_X_pow_order {f : PowerSeries R} (hf : f ≠ 0) : R⟦X⟧ := (exists_eq_mul_right_of_dvd (X_pow_order_dvd (order_finite_iff_ne_zero.2 hf))).choose diff --git a/Mathlib/RingTheory/Presentation.lean b/Mathlib/RingTheory/Presentation.lean index 5dfe5599b9bc1..b7d31cd531382 100644 --- a/Mathlib/RingTheory/Presentation.lean +++ b/Mathlib/RingTheory/Presentation.lean @@ -56,7 +56,7 @@ each relation to a polynomial in the generators. -/ @[nolint checkUnivs] structure Algebra.Presentation extends Algebra.Generators.{w} R S where - /-- The type of relations. -/ + /-- The type of relations. -/ rels : Type t /-- The assignment of each relation to a polynomial in the generators. -/ relation : rels → toGenerators.Ring diff --git a/Mathlib/RingTheory/PrimeSpectrum.lean b/Mathlib/RingTheory/PrimeSpectrum.lean index e42c803e3eef2..07320e17cdf81 100644 --- a/Mathlib/RingTheory/PrimeSpectrum.lean +++ b/Mathlib/RingTheory/PrimeSpectrum.lean @@ -40,7 +40,7 @@ and Chris Hughes (on an earlier repository). -/ -- A dividing line between this file and `AlgebraicGeometry.PrimeSpectrum.Basic` is --- that we should not depened on the Zariski topology here +-- that we should not depend on the Zariski topology here assert_not_exists TopologicalSpace noncomputable section @@ -186,7 +186,7 @@ theorem gc_set : @GaloisConnection (Set R) (Set (PrimeSpectrum R))ᵒᵈ _ _ (fun s => zeroLocus s) fun t => vanishingIdeal t := by have ideal_gc : GaloisConnection Ideal.span _ := (Submodule.gi R R).gc - simpa [zeroLocus_span, Function.comp] using ideal_gc.compose (gc R) + simpa [zeroLocus_span, Function.comp_def] using ideal_gc.compose (gc R) theorem subset_zeroLocus_iff_subset_vanishingIdeal (t : Set (PrimeSpectrum R)) (s : Set R) : t ⊆ zeroLocus s ↔ s ⊆ vanishingIdeal t := diff --git a/Mathlib/RingTheory/PrincipalIdealDomain.lean b/Mathlib/RingTheory/PrincipalIdealDomain.lean index 29bea641d71f3..40c180a84813b 100644 --- a/Mathlib/RingTheory/PrincipalIdealDomain.lean +++ b/Mathlib/RingTheory/PrincipalIdealDomain.lean @@ -92,8 +92,9 @@ theorem _root_.Ideal.span_singleton_generator (I : Ideal R) [I.IsPrincipal] : @[simp] theorem generator_mem (S : Submodule R M) [S.IsPrincipal] : generator S ∈ S := by - conv_rhs => rw [← span_singleton_generator S] - exact subset_span (mem_singleton _) + have : generator S ∈ span R {generator S} := subset_span (mem_singleton _) + convert this + exact span_singleton_generator S |>.symm theorem mem_iff_eq_smul_generator (S : Submodule R M) [S.IsPrincipal] {x : M} : x ∈ S ↔ ∃ s : R, x = s • generator S := by diff --git a/Mathlib/RingTheory/Regular/IsSMulRegular.lean b/Mathlib/RingTheory/Regular/IsSMulRegular.lean index 34012a4084c2b..efe4d52d7cef9 100644 --- a/Mathlib/RingTheory/Regular/IsSMulRegular.lean +++ b/Mathlib/RingTheory/Regular/IsSMulRegular.lean @@ -96,7 +96,7 @@ lemma isSMulRegular_on_submodule_iff_mem_imp_smul_eq_zero_imp_eq_zero : IsSMulRegular N r ↔ ∀ x ∈ N, r • x = 0 → x = 0 := Iff.trans (isSMulRegular_iff_smul_eq_zero_imp_eq_zero N r) <| Iff.trans Subtype.forall <| by - simp only [SetLike.mk_smul_mk, AddSubmonoid.mk_eq_zero] + simp only [SetLike.mk_smul_mk, Submodule.mk_eq_zero] lemma isSMulRegular_on_quot_iff_smul_mem_implies_mem : IsSMulRegular (M ⧸ N) r ↔ ∀ x : M, r • x ∈ N → x ∈ N := diff --git a/Mathlib/RingTheory/Regular/RegularSequence.lean b/Mathlib/RingTheory/Regular/RegularSequence.lean index 6da2991f4d4ca..a1e81fdf08b75 100644 --- a/Mathlib/RingTheory/Regular/RegularSequence.lean +++ b/Mathlib/RingTheory/Regular/RegularSequence.lean @@ -45,7 +45,7 @@ abbrev ofList (rs : List R) := span { r | r ∈ rs } have : { r | r ∈ rs₁ ++ rs₂ } = _ := Set.ext (fun _ => List.mem_append) Eq.trans (congrArg span this) (span_union _ _) -@[simp] lemma ofList_singleton (r : R) : ofList [r] = span {r} := +lemma ofList_singleton (r : R) : ofList [r] = span {r} := congrArg span (Set.ext fun _ => List.mem_singleton) @[simp] lemma ofList_cons (r : R) (rs : List R) : @@ -232,7 +232,7 @@ lemma isWeaklyRegular_cons_iff (r : R) (rs : List R) : IsSMulRegular M r ∧ IsWeaklyRegular (QuotSMulTop r M) rs := have := Eq.trans (congrArg (· • ⊤) Ideal.ofList_nil) (bot_smul ⊤) let e i := quotOfListConsSMulTopEquivQuotSMulTopInner M r (rs.take i) - Iff.trans (isWeaklyRegular_iff_Fin _ _) <| Iff.trans Fin.forall_fin_succ <| + Iff.trans (isWeaklyRegular_iff_Fin _ _) <| Iff.trans Fin.forall_iff_succ <| and_congr ((quotEquivOfEqBot _ this).isSMulRegular_congr r) <| Iff.trans (forall_congr' fun i => (e i).isSMulRegular_congr (rs.get i)) (isWeaklyRegular_iff_Fin _ _).symm @@ -316,7 +316,7 @@ def ndrecIterModByRegular /-- An alternate induction principle from `IsWeaklyRegular.recIterModByRegular` where we mod out by successive elements in both the module and the base ring. -This is useful for propogating certain properties of the initial `M`, e.g. +This is useful for propagating certain properties of the initial `M`, e.g. faithfulness or freeness, throughout the induction. -/ def recIterModByRegularWithRing {motive : (R : Type u) → [CommRing R] → (M : Type v) → [AddCommGroup M] → @@ -447,7 +447,7 @@ def ndrecIterModByRegular /-- An alternate induction principle from `IsRegular.recIterModByRegular` where we mod out by successive elements in both the module and the base ring. This is -useful for propogating certain properties of the initial `M`, e.g. faithfulness +useful for propagating certain properties of the initial `M`, e.g. faithfulness or freeness, throughout the induction. -/ def recIterModByRegularWithRing {motive : (R : Type u) → [CommRing R] → (M : Type v) → [AddCommGroup M] → @@ -555,12 +555,14 @@ lemma map_first_exact_on_four_term_right_exact_of_isSMulRegular_last (h₄ : IsWeaklyRegular M₄ rs) : Exact (mapQ _ _ _ (smul_top_le_comap_smul_top (Ideal.ofList rs) f₁)) (mapQ _ _ _ (smul_top_le_comap_smul_top (Ideal.ofList rs) f₂)) := by - induction' h₄ with _ _ _ N _ _ r rs h₄ _ ih generalizing M M₂ M₃ - · apply (Exact.iff_of_ladder_linearEquiv ?_ ?_).mp h₁₂ + induction h₄ generalizing M M₂ M₃ with + | nil => + apply (Exact.iff_of_ladder_linearEquiv ?_ ?_).mp h₁₂ any_goals exact quotEquivOfEqBot _ <| Eq.trans (congrArg (· • ⊤) Ideal.ofList_nil) (bot_smul ⊤) all_goals exact quot_hom_ext _ _ _ fun _ => rfl - · specialize ih + | cons r rs h₄ _ ih => + specialize ih (map_first_exact_on_four_term_exact_of_isSMulRegular_last h₁₂ h₂₃ h₄) (map_exact r h₂₃ h₃) (map_surjective r h₃) have H₁ := quotOfListConsSMulTopEquivQuotSMulTopInner_naturality r rs f₁ diff --git a/Mathlib/RingTheory/RingHom/FinitePresentation.lean b/Mathlib/RingTheory/RingHom/FinitePresentation.lean index 21b4cbcffb892..99b90e6894081 100644 --- a/Mathlib/RingTheory/RingHom/FinitePresentation.lean +++ b/Mathlib/RingTheory/RingHom/FinitePresentation.lean @@ -113,7 +113,7 @@ theorem finitePresentation_ofLocalizationSpanTarget : · infer_instance rw [RingHom.FinitePresentation] obtain ⟨n, f, hf⟩ := Algebra.FiniteType.iff_quotient_mvPolynomial''.mp hfintype - obtain ⟨l, hl⟩ := (Finsupp.mem_span_iff_total S (s : Set S) 1).mp + obtain ⟨l, hl⟩ := (Finsupp.mem_span_iff_linearCombination S (s : Set S) 1).mp (show (1 : S) ∈ Ideal.span (s : Set S) by rw [hs]; trivial) choose g' hg' using (fun g : s ↦ hf g) choose h' hh' using (fun g : s ↦ hf (l g)) @@ -124,7 +124,7 @@ theorem finitePresentation_ofLocalizationSpanTarget : simp only [Finset.univ_eq_attach, I, Ideal.mem_span_singleton] at hp obtain ⟨q, rfl⟩ := hp simp only [map_mul, map_sub, map_sum, map_one, hg', hh'] - erw [Finsupp.total_apply_of_mem_supported S (s := s.attach)] at hl + erw [Finsupp.linearCombination_apply_of_mem_supported S (s := s.attach)] at hl · rw [← hl] simp only [Finset.coe_sort_coe, smul_eq_mul, mul_comm, sub_self, mul_zero, zero_mul] · rintro a - @@ -149,7 +149,9 @@ theorem finitePresentation_ofLocalizationSpanTarget : exact ⟨{∑ g ∈ s.attach, g' g * h' g - 1}, by simp⟩ have Ht (g : t) : Algebra.FinitePresentation R (Localization.Away (f' g)) := by have : ∃ (a : S) (hb : a ∈ s), (Ideal.Quotient.mk I) (g' ⟨a, hb⟩) = g.val := by - simpa [t] using g.property + obtain ⟨g, hg⟩ := g + convert hg + simp [t] obtain ⟨r, hr, hrr⟩ := this simp only [f'] rw [← hrr, Ideal.Quotient.liftₐ_apply, Ideal.Quotient.lift_mk] diff --git a/Mathlib/RingTheory/RingHom/FiniteType.lean b/Mathlib/RingTheory/RingHom/FiniteType.lean index 7d6e84d24484f..fb75176c50b6e 100644 --- a/Mathlib/RingTheory/RingHom/FiniteType.lean +++ b/Mathlib/RingTheory/RingHom/FiniteType.lean @@ -33,7 +33,7 @@ theorem finiteType_holdsForLocalizationAway : HoldsForLocalizationAway @FiniteTy exact IsLocalization.finiteType_of_monoid_fg (Submonoid.powers r) S theorem finiteType_ofLocalizationSpanTarget : OfLocalizationSpanTarget @FiniteType := by - -- Setup algebra intances. + -- Setup algebra instances. rw [ofLocalizationSpanTarget_iff_finite] introv R hs H classical @@ -47,7 +47,7 @@ theorem finiteType_ofLocalizationSpanTarget : OfLocalizationSpanTarget @FiniteTy -- `∑ lᵢ * sᵢ = 1`. I claim that all `s` and `l` and the numerators of `t` and generates `S`. choose t ht using H obtain ⟨l, hl⟩ := - (Finsupp.mem_span_iff_total S (s : Set S) 1).mp + (Finsupp.mem_span_iff_linearCombination S (s : Set S) 1).mp (show (1 : S) ∈ Ideal.span (s : Set S) by rw [hs]; trivial) let sf := fun x : s => IsLocalization.finsetIntegerMultiple (Submonoid.powers (x : S)) (t x) use s.attach.biUnion sf ∪ s ∪ l.support.image l diff --git a/Mathlib/RingTheory/RingHom/Surjective.lean b/Mathlib/RingTheory/RingHom/Surjective.lean index 732f8377e880b..11bc6f10f5271 100644 --- a/Mathlib/RingTheory/RingHom/Surjective.lean +++ b/Mathlib/RingTheory/RingHom/Surjective.lean @@ -47,7 +47,7 @@ theorem surjective_ofLocalizationSpan : OfLocalizationSpan surjective := by rw [← Algebra.range_top_iff_surjective, eq_top_iff] rintro x - obtain ⟨l, hl⟩ := - (Finsupp.mem_span_iff_total R s 1).mp (show _ ∈ Ideal.span s by rw [hs]; trivial) + (Finsupp.mem_span_iff_linearCombination R s 1).mp (show _ ∈ Ideal.span s by rw [hs]; trivial) fapply Subalgebra.mem_of_finset_sum_eq_one_of_pow_smul_mem _ l.support (fun x : s => f x) fun x : s => f (l x) diff --git a/Mathlib/RingTheory/RootsOfUnity/Complex.lean b/Mathlib/RingTheory/RootsOfUnity/Complex.lean index 7f034a01f4772..ec56155951282 100644 --- a/Mathlib/RingTheory/RootsOfUnity/Complex.lean +++ b/Mathlib/RingTheory/RootsOfUnity/Complex.lean @@ -152,7 +152,7 @@ theorem IsPrimitiveRoot.arg {n : ℕ} {ζ : ℂ} (h : IsPrimitiveRoot ζ n) (hn rw [← mul_rotate', mul_div_assoc] rw [← mul_one n] at h₂ exact mul_le_of_le_one_right Real.pi_pos.le - ((div_le_iff' <| mod_cast pos_of_gt h).mpr <| mod_cast h₂) + ((div_le_iff₀' <| mod_cast pos_of_gt h).mpr <| mod_cast h₂) rw [← Complex.cos_sub_two_pi, ← Complex.sin_sub_two_pi] convert Complex.arg_cos_add_sin_mul_I _ · push_cast diff --git a/Mathlib/RingTheory/RootsOfUnity/Minpoly.lean b/Mathlib/RingTheory/RootsOfUnity/Minpoly.lean index 18723ca9b73e4..fddcf3946281c 100644 --- a/Mathlib/RingTheory/RootsOfUnity/Minpoly.lean +++ b/Mathlib/RingTheory/RootsOfUnity/Minpoly.lean @@ -199,7 +199,7 @@ theorem is_roots_of_minpoly [DecidableEq K] : intro x hx obtain ⟨m, _, hcop, rfl⟩ := (isPrimitiveRoot_iff h hpos).1 ((mem_primitiveRoots hpos).1 hx) simp only [Multiset.mem_toFinset, mem_roots] - convert pow_isRoot_minpoly h hcop + convert pow_isRoot_minpoly h hcop using 0 rw [← mem_roots] exact map_monic_ne_zero <| minpoly.monic <| isIntegral h hpos diff --git a/Mathlib/RingTheory/SimpleModule.lean b/Mathlib/RingTheory/SimpleModule.lean index 263f1455ae1d0..5bc001188d6d1 100644 --- a/Mathlib/RingTheory/SimpleModule.lean +++ b/Mathlib/RingTheory/SimpleModule.lean @@ -285,7 +285,7 @@ theorem IsSemisimpleModule.sup {p q : Submodule R M} instance IsSemisimpleRing.isSemisimpleModule [IsSemisimpleRing R] : IsSemisimpleModule R M := have : IsSemisimpleModule R (M →₀ R) := isSemisimpleModule_of_isSemisimpleModule_submodule' (fun _ ↦ .congr (LinearMap.quotKerEquivRange _).symm) Finsupp.iSup_lsingle_range - .congr (LinearMap.quotKerEquivOfSurjective _ <| Finsupp.total_id_surjective R M).symm + .congr (LinearMap.quotKerEquivOfSurjective _ <| Finsupp.linearCombination_id_surjective R M).symm instance IsSemisimpleRing.isCoatomic_submodule [IsSemisimpleRing R] : IsCoatomic (Submodule R M) := isCoatomic_of_isAtomic_of_complementedLattice_of_isModular @@ -398,7 +398,9 @@ noncomputable instance _root_.Module.End.divisionRing exact (LinearEquiv.ofBijective _ <| bijective_of_ne_zero a0).right_inv _ inv_zero := dif_pos rfl nnqsmul := _ + nnqsmul_def := fun q a => rfl qsmul := _ + qsmul_def := fun q a => rfl end LinearMap diff --git a/Mathlib/RingTheory/Smooth/Kaehler.lean b/Mathlib/RingTheory/Smooth/Kaehler.lean index 06b7cba8d586b..0e20b7e631d12 100644 --- a/Mathlib/RingTheory/Smooth/Kaehler.lean +++ b/Mathlib/RingTheory/Smooth/Kaehler.lean @@ -48,14 +48,14 @@ def derivationOfSectionOfKerSqZero (f : P →ₐ[R] S) (hf' : (RingHom.ker f) ^ (hg : f.comp g = AlgHom.id R S) : Derivation R P (RingHom.ker f) where toFun x := ⟨x - g (f x), by simpa [RingHom.mem_ker, sub_eq_zero] using AlgHom.congr_fun hg.symm (f x)⟩ - map_add' x y := by simp only [map_add, AddSubmonoid.mk_add_mk, Subtype.mk.injEq]; ring + map_add' x y := by simp only [map_add, AddMemClass.mk_add_mk, Subtype.mk.injEq]; ring map_smul' x y := by ext simp only [Algebra.smul_def, map_mul, ← IsScalarTower.algebraMap_apply, AlgHom.commutes, RingHom.id_apply, Submodule.coe_smul_of_tower] ring map_one_eq_zero' := by simp only [LinearMap.coe_mk, AddHom.coe_mk, map_one, sub_self, - AddSubmonoid.mk_eq_zero] + Submodule.mk_eq_zero] leibniz' a b := by have : (a - g (f a)) * (b - g (f b)) = 0 := by rw [← Ideal.mem_bot, ← hf', pow_two] @@ -66,7 +66,7 @@ def derivationOfSectionOfKerSqZero (f : P →ₐ[R] S) (hf' : (RingHom.ker f) ^ rw [← sub_eq_zero] conv_rhs => rw [← neg_zero, ← this] simp only [LinearMap.coe_mk, AddHom.coe_mk, map_mul, SetLike.mk_smul_mk, smul_eq_mul, mul_sub, - AddSubmonoid.mk_add_mk, sub_mul, neg_sub] + AddMemClass.mk_add_mk, sub_mul, neg_sub] ring variable (hf' : (RingHom.ker (algebraMap P S)) ^ 2 = ⊥) @@ -149,12 +149,12 @@ def sectionOfRetractionKerToTensorAux : S →ₐ[R] P where have (x y) : (l x).1 * (l y).1 = 0 := by rw [← Ideal.mem_bot, ← hf', pow_two]; exact Ideal.mul_mem_mul (l x).2 (l y).2 simp only [sectionOfRetractionKerToTensorAux_prop l hl (σ (a * b)) (σ a * σ b) (by simp [hσ]), - Derivation.leibniz, tmul_add, tmul_smul, map_add, map_smul, AddSubmonoid.coe_add, this, - Submodule.coe_toAddSubmonoid, SetLike.val_smul, smul_eq_mul, mul_sub, sub_mul, sub_zero] + Derivation.leibniz, tmul_add, tmul_smul, map_add, map_smul, Submodule.coe_add, + SetLike.val_smul, smul_eq_mul, mul_sub, sub_mul, this, sub_zero] ring map_add' a b := by simp only [sectionOfRetractionKerToTensorAux_prop l hl (σ (a + b)) (σ a + σ b) (by simp [hσ]), - map_add, tmul_add, AddSubmonoid.coe_add, Submodule.coe_toAddSubmonoid, add_sub_add_comm] + map_add, tmul_add, Submodule.coe_add, add_sub_add_comm] map_zero' := by simp [sectionOfRetractionKerToTensorAux_prop l hl (σ 0) 0 (by simp [hσ])] commutes' r := by simp [sectionOfRetractionKerToTensorAux_prop l hl diff --git a/Mathlib/RingTheory/TensorProduct/Basic.lean b/Mathlib/RingTheory/TensorProduct/Basic.lean index 228b5be3855a4..31824342a497b 100644 --- a/Mathlib/RingTheory/TensorProduct/Basic.lean +++ b/Mathlib/RingTheory/TensorProduct/Basic.lean @@ -3,10 +3,11 @@ Copyright (c) 2020 Scott Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Morrison, Johan Commelin -/ -import Mathlib.LinearAlgebra.FiniteDimensional.Defs -import Mathlib.LinearAlgebra.TensorProduct.Tower +import Mathlib.GroupTheory.MonoidLocalization.Basic +import Mathlib.LinearAlgebra.FreeModule.Basic +import Mathlib.LinearAlgebra.Matrix.ToLin import Mathlib.RingTheory.Adjoin.Basic -import Mathlib.LinearAlgebra.DirectSum.Finsupp +import Mathlib.RingTheory.Finiteness /-! # The tensor product of R-algebras @@ -34,6 +35,8 @@ multiplication is characterized by `(a₁ ⊗ₜ b₁) * (a₂ ⊗ₜ b₂) = (a -/ +assert_not_exists Equiv.Perm.cycleType + suppress_compilation open scoped TensorProduct @@ -779,7 +782,7 @@ Note that if `A` is commutative this can be instantiated with `S = A`. -/ protected nonrec def rid : A ⊗[R] R ≃ₐ[S] A := algEquivOfLinearEquivTensorProduct (AlgebraTensorModule.rid R S A) - (fun a₁ a₂ r₁ r₂ => smul_mul_smul r₁ r₂ a₁ a₂ |>.symm) + (fun a₁ a₂ r₁ r₂ => smul_mul_smul_comm r₁ a₁ r₂ a₂ |>.symm) (one_smul R _) @[simp] theorem rid_toLinearEquiv : @@ -1213,11 +1216,6 @@ theorem Subalgebra.finite_sup {K L : Type*} [CommSemiring K] [CommSemiring L] [A rw [← E1.range_val, ← E2.range_val, ← Algebra.TensorProduct.productMap_range] exact Module.Finite.range (Algebra.TensorProduct.productMap E1.val E2.val).toLinearMap -@[deprecated Subalgebra.finite_sup (since := "2024-04-11")] -theorem Subalgebra.finiteDimensional_sup {K L : Type*} [Field K] [CommRing L] [Algebra K L] - (E1 E2 : Subalgebra K L) [FiniteDimensional K E1] [FiniteDimensional K E2] : - FiniteDimensional K (E1 ⊔ E2 : Subalgebra K L) := Subalgebra.finite_sup E1 E2 - namespace TensorProduct.Algebra variable {R A B M : Type*} diff --git a/Mathlib/RingTheory/TwoSidedIdeal/Instances.lean b/Mathlib/RingTheory/TwoSidedIdeal/Instances.lean new file mode 100644 index 0000000000000..dc62e64d97bc8 --- /dev/null +++ b/Mathlib/RingTheory/TwoSidedIdeal/Instances.lean @@ -0,0 +1,14 @@ +/- +Copyright (c) 2024. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: euprunin +-/ +import Mathlib.Algebra.Ring.Defs +import Mathlib.RingTheory.NonUnitalSubring.Basic +import Mathlib.RingTheory.TwoSidedIdeal.Basic + +/-! +# Additional instances for two sided ideals. +-/ +instance {R} [NonUnitalNonAssocRing R] : NonUnitalSubringClass (TwoSidedIdeal R) R where + mul_mem _ hb := TwoSidedIdeal.mul_mem_left _ _ _ hb diff --git a/Mathlib/RingTheory/UniqueFactorizationDomain.lean b/Mathlib/RingTheory/UniqueFactorizationDomain.lean index 395b39b238df8..61c7058bd78c1 100644 --- a/Mathlib/RingTheory/UniqueFactorizationDomain.lean +++ b/Mathlib/RingTheory/UniqueFactorizationDomain.lean @@ -41,9 +41,9 @@ export WfDvdMonoid (wellFounded_dvdNotUnit) -- see Note [lower instance priority] instance (priority := 100) IsNoetherianRing.wfDvdMonoid [CommRing α] [IsDomain α] - [IsNoetherianRing α] : WfDvdMonoid α := + [h : IsNoetherianRing α] : WfDvdMonoid α := ⟨by - convert InvImage.wf (fun a => Ideal.span ({a} : Set α)) (wellFounded_submodule_gt _ _) + convert InvImage.wf (fun a => Ideal.span ({a} : Set α)) h.wf ext exact Ideal.span_singleton_lt_span_singleton.symm⟩ @@ -1013,7 +1013,7 @@ theorem prime_pow_coprime_prod_of_coprime_insert [DecidableEq α] {s : Finset α obtain ⟨q, q_mem, rfl⟩ := Multiset.mem_map.mp q_mem' replace hdq := hd.dvd_of_dvd_pow hdq have : p ∣ q := dvd_trans (hd.irreducible.dvd_symm hp.irreducible hdp) hdq - convert q_mem + convert q_mem using 0 rw [Finset.mem_val, is_coprime _ (Finset.mem_insert_self p s) _ (Finset.mem_insert_of_mem q_mem) this] @@ -1248,7 +1248,7 @@ def BfactorSetMem : { a : Associates α // Irreducible a } → FactorSet α → `s : FactorSet α`. If `p` is not irreducible, `p` is not a member of any `FactorSet`. -/ -def FactorSetMem (p : Associates α) (s : FactorSet α) : Prop := +def FactorSetMem (s : FactorSet α) (p : Associates α) : Prop := letI : Decidable (Irreducible p) := Classical.dec _ if hp : Irreducible p then BfactorSetMem ⟨p, hp⟩ s else False @@ -1256,7 +1256,7 @@ instance : Membership (Associates α) (FactorSet α) := ⟨FactorSetMem⟩ @[simp] -theorem factorSetMem_eq_mem (p : Associates α) (s : FactorSet α) : FactorSetMem p s = (p ∈ s) := +theorem factorSetMem_eq_mem (p : Associates α) (s : FactorSet α) : FactorSetMem s p = (p ∈ s) := rfl theorem mem_factorSet_top {p : Associates α} {hp : Irreducible p} : p ∈ (⊤ : FactorSet α) := by @@ -1572,21 +1572,21 @@ theorem coprime_iff_inf_one {a b : α} (ha0 : a ≠ 0) (hb0 : b ≠ 0) : theorem factors_self [Nontrivial α] {p : Associates α} (hp : Irreducible p) : p.factors = WithTop.some {⟨p, hp⟩} := eq_of_prod_eq_prod - (by rw [factors_prod, FactorSet.prod]; dsimp; rw [prod_singleton]) + (by rw [factors_prod, FactorSet.prod.eq_def]; dsimp; rw [prod_singleton]) theorem factors_prime_pow [Nontrivial α] {p : Associates α} (hp : Irreducible p) (k : ℕ) : factors (p ^ k) = WithTop.some (Multiset.replicate k ⟨p, hp⟩) := eq_of_prod_eq_prod (by - rw [Associates.factors_prod, FactorSet.prod] + rw [Associates.factors_prod, FactorSet.prod.eq_def] dsimp; rw [Multiset.map_replicate, Multiset.prod_replicate, Subtype.coe_mk]) theorem prime_pow_le_iff_le_bcount [DecidableEq (Associates α)] {m p : Associates α} (h₁ : m ≠ 0) (h₂ : Irreducible p) {k : ℕ} : p ^ k ≤ m ↔ k ≤ bcount ⟨p, h₂⟩ m.factors := by rcases Associates.exists_non_zero_rep h₁ with ⟨m, hm, rfl⟩ have := nontrivial_of_ne _ _ hm - rw [bcount, factors_mk, Multiset.le_count_iff_replicate_le, ← factors_le, factors_prime_pow, - factors_mk, WithTop.coe_le_coe] <;> assumption + rw [bcount.eq_def, factors_mk, Multiset.le_count_iff_replicate_le, ← factors_le, + factors_prime_pow, factors_mk, WithTop.coe_le_coe] <;> assumption @[simp] theorem factors_one [Nontrivial α] : factors (1 : Associates α) = 0 := by @@ -1849,7 +1849,7 @@ noncomputable def fintypeSubtypeDvd {M : Type*} [CancelCommMonoidWithZero M] haveI : NormalizationMonoid M := UniqueFactorizationMonoid.normalizationMonoid haveI := Classical.decEq M haveI := Classical.decEq (Associates M) - -- We'll show `λ (u : Mˣ) (f ⊆ factors y) → u * Π f` is injective + -- We'll show `fun (u : Mˣ) (f ⊆ factors y) ↦ u * Π f` is injective -- and has image exactly the divisors of `y`. refine Fintype.ofFinset @@ -1975,3 +1975,5 @@ lemma factors_multiset_prod_of_irreducible {s : Multiset ℕ} (h : ∀ x : ℕ, exact fun con ↦ not_irreducible_zero (h 0 con) end Nat + +set_option linter.style.longFile 2100 diff --git a/Mathlib/RingTheory/Unramified/Finite.lean b/Mathlib/RingTheory/Unramified/Finite.lean index 0afad0fed8c13..8652ea0e4337f 100644 --- a/Mathlib/RingTheory/Unramified/Finite.lean +++ b/Mathlib/RingTheory/Unramified/Finite.lean @@ -90,8 +90,9 @@ lemma finite_of_free_aux (I) [DecidableEq I] (b : Basis I R S) let a i := b.repr (b i * x) conv_lhs => simp only [TensorProduct.tmul_mul_tmul, one_mul, mul_comm x (b _), - ← show ∀ i, Finsupp.total _ _ _ b (a i) = b i * x from fun _ ↦ b.total_repr _] - conv_lhs => simp only [Finsupp.total, Finsupp.coe_lsum, + ← show ∀ i, Finsupp.linearCombination _ b (a i) = b i * x from + fun _ ↦ b.linearCombination_repr _] + conv_lhs => simp only [Finsupp.linearCombination, Finsupp.coe_lsum, LinearMap.coe_smulRight, LinearMap.id_coe, id_eq, Finsupp.sum, TensorProduct.tmul_sum, ← TensorProduct.smul_tmul] have h₁ : ∀ k, @@ -107,7 +108,7 @@ lemma finite_of_free_aux (I) [DecidableEq I] (b : Basis I R S) · intro; simp only [zero_smul] · intros; simp only [add_smul] have h₂ : ∀ (x : S), ((b.repr x).support.sum fun a ↦ b.repr x a • b a) = x := by - simpa only [Finsupp.total_apply, Finsupp.sum] using b.total_repr + simpa only [Finsupp.linearCombination_apply, Finsupp.sum] using b.linearCombination_repr simp_rw [map_finsupp_sum, map_smul, h₁, Finsupp.sum, Finset.sum_comm (t := f.support), TensorProduct.smul_tmul', ← TensorProduct.sum_tmul, ← Finset.smul_sum, h₂] apply Finset.sum_congr rfl @@ -159,7 +160,7 @@ lemma finite_of_free [Module.Free R S] : Module.Finite R S := by have ⟨f, hf⟩ : ∃ (a : I →₀ S), elem R S = a.sum (fun i x ↦ x ⊗ₜ b i) := by let b' := ((Basis.singleton PUnit.{1} S).tensorProduct b).reindex (Equiv.punitProd I) use b'.repr (elem R S) - conv_lhs => rw [← b'.total_repr (elem R S), Finsupp.total_apply] + conv_lhs => rw [← b'.linearCombination_repr (elem R S), Finsupp.linearCombination_apply] congr! with _ i x simp [b', Basis.tensorProduct, TensorProduct.smul_tmul'] constructor @@ -197,15 +198,15 @@ lemma finite_of_free [Module.Free R S] : Module.Finite R S := by simp only [Basis.repr_symm_apply, Finsupp.coe_lsum, LinearMap.coe_smulRight, LinearMap.id_coe, id_eq, Basis.tensorProduct_apply, Finsupp.finsuppProdEquiv, Equiv.coe_fn_symm_mk, Finsupp.uncurry, map_finsupp_sum, - Finsupp.total_single, Basis.tensorProduct_apply, Finsupp.equivCongrLeft_apply, - Finsupp.total_equivMapDomain, Equiv.coe_prodComm] + Finsupp.linearCombination_single, Basis.tensorProduct_apply, Finsupp.equivCongrLeft_apply, + Finsupp.linearCombination_equivMapDomain, Equiv.coe_prodComm] rw [Finsupp.onFinset_sum, Finsupp.onFinset_sum] simp only [Function.comp_apply, Prod.swap_prod_mk, Basis.tensorProduct_apply] have : ∀ i, ((b.repr (x * f i)).sum fun j k ↦ k • b j ⊗ₜ[R] b i) = (x * f i) ⊗ₜ[R] b i := by intro i simp_rw [Finsupp.sum, TensorProduct.smul_tmul', ← TensorProduct.sum_tmul] congr 1 - exact b.total_repr _ + exact b.linearCombination_repr _ trans (x ⊗ₜ 1) * elem R S · simp_rw [this, hf, Finsupp.sum, Finset.mul_sum, TensorProduct.tmul_mul_tmul, one_mul] · rw [← one_tmul_mul_elem, hf, finite_of_free_aux] diff --git a/Mathlib/RingTheory/Valuation/AlgebraInstances.lean b/Mathlib/RingTheory/Valuation/AlgebraInstances.lean new file mode 100644 index 0000000000000..e3339c12fafec --- /dev/null +++ b/Mathlib/RingTheory/Valuation/AlgebraInstances.lean @@ -0,0 +1,89 @@ +/- +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.Algebra.Order.Group.TypeTags +import Mathlib.RingTheory.IntegralClosure.IsIntegralClosure.Basic +import Mathlib.RingTheory.Valuation.ValuationSubring + +/-! +# Algebra instances + +This file contains several `Algebra` and `IsScalarTower` instances related to extensions +of a field with a valuation, as well as their unit balls. + +# Main Definitions +* `ValuationSubring.algebra` : Given an algebra between two field extensions `L` and `E` of a + field `K` with a valuation, create an algebra between their two rings of integers. + +# Main Results + +* `integralClosure_algebraMap_injective` : the unit ball of a field `K` with respect to a + valuation injects into its integral closure in a field extension `L` of `K`. +-/ + +open Function Valuation + +open scoped DiscreteValuation + +variable {K : Type*} [Field K] (v : Valuation K ℤₘ₀) (L : Type*) [Field L] [Algebra K L] + +namespace ValuationSubring + +-- Implementation note : this instance was automatic in Lean3 +instance : Algebra v.valuationSubring L := Algebra.ofSubring v.valuationSubring.toSubring + +theorem algebraMap_injective : Injective (algebraMap v.valuationSubring L) := + (NoZeroSMulDivisors.algebraMap_injective K L).comp (IsFractionRing.injective _ _) + +theorem isIntegral_of_mem_ringOfIntegers {x : L} (hx : x ∈ integralClosure v.valuationSubring L) : + IsIntegral v.valuationSubring (⟨x, hx⟩ : integralClosure v.valuationSubring L) := by + obtain ⟨P, hPm, hP⟩ := hx + refine ⟨P, hPm, ?_⟩ + rw [← Polynomial.aeval_def, ← Subalgebra.coe_eq_zero, Polynomial.aeval_subalgebra_coe, + Polynomial.aeval_def, Subtype.coe_mk, hP] + +theorem isIntegral_of_mem_ringOfIntegers' {x : (integralClosure v.valuationSubring L)} : + IsIntegral v.valuationSubring (x : integralClosure v.valuationSubring L) := by + apply isIntegral_of_mem_ringOfIntegers + +variable (E : Type _) [Field E] [Algebra K E] [Algebra L E] [IsScalarTower K L E] + +instance : IsScalarTower v.valuationSubring L E := Subring.instIsScalarTowerSubtypeMem _ + +/-- Given an algebra between two field extensions `L` and `E` of a field `K` with a valuation `v`, + create an algebra between their two rings of integers. -/ +instance algebra : + Algebra (integralClosure v.valuationSubring L) (integralClosure v.valuationSubring E) := + RingHom.toAlgebra + { toFun := fun k => ⟨algebraMap L E k, IsIntegral.algebraMap k.2⟩ + map_zero' := + Subtype.ext <| by simp only [Subtype.coe_mk, Subalgebra.coe_zero, _root_.map_zero] + map_one' := Subtype.ext <| by simp only [Subtype.coe_mk, Subalgebra.coe_one, _root_.map_one] + map_add' := fun x y => + Subtype.ext <| by simp only [_root_.map_add, Subalgebra.coe_add, Subtype.coe_mk] + map_mul' := fun x y => + Subtype.ext <| by simp only [Subalgebra.coe_mul, _root_.map_mul, Subtype.coe_mk] } + +/-- A ring equivalence between the integral closure of the valuation subring of `K` in `L` + and a ring `R` satisfying `isIntegralClosure R v.valuationSubring L`. -/ +protected noncomputable def equiv (R : Type*) [CommRing R] [Algebra v.valuationSubring R] + [Algebra R L] [IsScalarTower v.valuationSubring R L] + [IsIntegralClosure R v.valuationSubring L] : integralClosure v.valuationSubring L ≃+* R := by + have := IsScalarTower.subalgebra' (valuationSubring v) L L + (integralClosure (valuationSubring v) L) + exact (IsIntegralClosure.equiv v.valuationSubring R L + (integralClosure v.valuationSubring L)).symm.toRingEquiv + +theorem integralClosure_algebraMap_injective : + Injective (algebraMap v.valuationSubring (integralClosure v.valuationSubring L)) := by + have hinj : Injective ⇑(algebraMap v.valuationSubring L) := + ValuationSubring.algebraMap_injective v L + rw [injective_iff_map_eq_zero (algebraMap v.valuationSubring _)] + intro x hx + rw [← Subtype.coe_inj, Subalgebra.coe_zero] at hx + rw [injective_iff_map_eq_zero (algebraMap v.valuationSubring L)] at hinj + exact hinj x hx + +end ValuationSubring diff --git a/Mathlib/RingTheory/Valuation/Basic.lean b/Mathlib/RingTheory/Valuation/Basic.lean index 9dfcfbe3ccddc..e32f03f67f513 100644 --- a/Mathlib/RingTheory/Valuation/Basic.lean +++ b/Mathlib/RingTheory/Valuation/Basic.lean @@ -57,7 +57,6 @@ If ever someone extends `Valuation`, we should fully comply to the `DFunLike` by boilerplate lemmas to `ValuationClass`. -/ - open scoped Classical open Function Ideal @@ -211,6 +210,13 @@ theorem ne_zero_iff [Nontrivial Γ₀] (v : Valuation K Γ₀) {x : K} : v x ≠ theorem unit_map_eq (u : Rˣ) : (Units.map (v : R →* Γ₀) u : Γ₀) = v u := rfl +theorem ne_zero_of_unit [Nontrivial Γ₀] (v : Valuation K Γ₀) (x : Kˣ) : v x ≠ (0 : Γ₀) := by + simp only [ne_eq, Valuation.zero_iff, Units.ne_zero x, not_false_iff] + +theorem ne_zero_of_isUnit [Nontrivial Γ₀] (v : Valuation K Γ₀) (x : K) (hx : IsUnit x) : + v x ≠ (0 : Γ₀) := by + simpa [hx.choose_spec] using ne_zero_of_unit v hx.choose + /-- A ring homomorphism `S → R` induces a map `Valuation R Γ₀ → Valuation S Γ₀`. -/ def comap {S : Type*} [Ring S] (f : S →+* R) (v : Valuation R Γ₀) : Valuation S Γ₀ := { v.toMonoidWithZeroHom.comp f.toMonoidWithZeroHom with @@ -410,20 +416,10 @@ theorem isEquiv_of_val_le_one [LinearOrderedCommGroupWithZero Γ₀] [LinearOrderedCommGroupWithZero Γ'₀] (v : Valuation K Γ₀) (v' : Valuation K Γ'₀) (h : ∀ {x : K}, v x ≤ 1 ↔ v' x ≤ 1) : v.IsEquiv v' := by intro x y - by_cases hy : y = 0; · simp [hy, zero_iff] - rw [show y = 1 * y by rw [one_mul]] - rw [← inv_mul_cancel_right₀ hy x] - iterate 2 rw [v.map_mul _ y, v'.map_mul _ y] - rw [v.map_one, v'.map_one] - constructor <;> intro H - · apply mul_le_mul_right' - replace hy := v.ne_zero_iff.mpr hy - replace H := le_of_le_mul_right hy H - rwa [h] at H - · apply mul_le_mul_right' - replace hy := v'.ne_zero_iff.mpr hy - replace H := le_of_le_mul_right hy H - rwa [h] + obtain rfl | hy := eq_or_ne y 0 + · simp + · rw [← div_le_one₀, ← v.map_div, h, v'.map_div, div_le_one₀] <;> + rwa [zero_lt_iff, ne_zero_iff] theorem isEquiv_iff_val_le_one [LinearOrderedCommGroupWithZero Γ₀] [LinearOrderedCommGroupWithZero Γ'₀] (v : Valuation K Γ₀) (v' : Valuation K Γ'₀) : diff --git a/Mathlib/RingTheory/Valuation/Minpoly.lean b/Mathlib/RingTheory/Valuation/Minpoly.lean new file mode 100644 index 0000000000000..3448962da4e70 --- /dev/null +++ b/Mathlib/RingTheory/Valuation/Minpoly.lean @@ -0,0 +1,50 @@ +/- +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.FieldTheory.Adjoin +import Mathlib.RingTheory.Valuation.Basic + +/-! +# Minimal polynomials. + +We prove some results about valuations of zero coefficients of minimal polynomials. + +Let `K` be a field with a valuation `v` and let `L` be a field extension of `K`. + +# Main Results +* `coeff_zero_minpoly` : for `x ∈ K` the valuation of the zeroth coefficient of the minimal + polynomial of `algebra_map K L x` over `K` is equal to the valuation of `x`. +* `pow_coeff_zero_ne_zero_of_unit` : for any unit `x : Lˣ`, we prove that a certain power of the + valuation of zeroth coefficient of the minimal polynomial of `x` over `K` is nonzero. This lemma + is helpful for defining the valuation on `L` inducing `v`. +-/ + +open FiniteDimensional minpoly Polynomial + +variable {K : Type*} [Field K] {Γ₀ : Type*} [LinearOrderedCommGroupWithZero Γ₀] + (v : Valuation K Γ₀) (L : Type*) [Field L] [Algebra K L] + +namespace Valuation + +/-- For `x ∈ K` the valuation of the zeroth coefficient of the minimal polynomial +of `algebra_map K L x` over `K` is equal to the valuation of `x`.-/ +@[simp] +theorem coeff_zero_minpoly (x : K) : v ((minpoly K (algebraMap K L x)).coeff 0) = v x := by + rw [minpoly.eq_X_sub_C, coeff_sub, coeff_X_zero, coeff_C_zero, zero_sub, Valuation.map_neg] + +variable {L} + +/- For any unit `x : Lˣ`, we prove that a certain power of the valuation of zeroth coefficient of +the minimal polynomial of `x` over `K` is nonzero. This lemma is helpful for defining the valuation +on `L` inducing `v`.-/ +theorem pow_coeff_zero_ne_zero_of_unit [FiniteDimensional K L] (x : L) (hx : IsUnit x): + v ((minpoly K x).coeff 0) ^ (finrank K L / (minpoly K x).natDegree) ≠ (0 : Γ₀) := by + have h_alg : Algebra.IsAlgebraic K L := Algebra.IsAlgebraic.of_finite K L + have hx₀ : IsIntegral K x := (Algebra.IsAlgebraic.isAlgebraic x).isIntegral + have hdeg := Nat.div_pos (natDegree_le x) (natDegree_pos hx₀) + rw [ne_eq, pow_eq_zero_iff hdeg.ne.symm, Valuation.zero_iff] + exact coeff_zero_ne_zero hx₀ hx.ne_zero + +end Valuation diff --git a/Mathlib/RingTheory/Valuation/ValuationSubring.lean b/Mathlib/RingTheory/Valuation/ValuationSubring.lean index fb8a0c376dfbb..d3e74258289fb 100644 --- a/Mathlib/RingTheory/Valuation/ValuationSubring.lean +++ b/Mathlib/RingTheory/Valuation/ValuationSubring.lean @@ -532,8 +532,6 @@ theorem image_maximalIdeal : ((↑) : A → K) '' LocalRing.maximalIdeal A = A.n simp only [Set.mem_image, SetLike.mem_coe, mem_nonunits_iff_exists_mem_maximalIdeal] erw [Subtype.exists] simp_rw [exists_and_right, exists_eq_right] - -- Porting note: added - simp end nonunits @@ -613,7 +611,7 @@ def principalUnitGroupEquiv : A.coe_mem_principalUnitGroup_iff.1 x.2⟩ invFun x := ⟨A.unitGroupMulEquiv.symm x, by - rw [A.coe_mem_principalUnitGroup_iff]; simpa using SetLike.coe_mem x⟩ + rw [A.coe_mem_principalUnitGroup_iff]; simp⟩ left_inv x := by simp right_inv x := by simp map_mul' x y := rfl diff --git a/Mathlib/RingTheory/WittVector/Compare.lean b/Mathlib/RingTheory/WittVector/Compare.lean index 4f42b10dee496..c99776913713c 100644 --- a/Mathlib/RingTheory/WittVector/Compare.lean +++ b/Mathlib/RingTheory/WittVector/Compare.lean @@ -71,7 +71,8 @@ def zmodEquivTrunc : ZMod (p ^ n) ≃+* TruncatedWittVector p n (ZMod p) := ZMod.ringEquiv (TruncatedWittVector p n (ZMod p)) (card_zmod _ _) theorem zmodEquivTrunc_apply {x : ZMod (p ^ n)} : - zmodEquivTrunc p n x = ZMod.castHom (by rfl) (TruncatedWittVector p n (ZMod p)) x := + zmodEquivTrunc p n x = + ZMod.castHom (m := p ^ n) (by rfl) (TruncatedWittVector p n (ZMod p)) x := rfl /-- The following diagram commutes: diff --git a/Mathlib/RingTheory/WittVector/Defs.lean b/Mathlib/RingTheory/WittVector/Defs.lean index c50793f3e1de2..53b4f06f4f2d8 100644 --- a/Mathlib/RingTheory/WittVector/Defs.lean +++ b/Mathlib/RingTheory/WittVector/Defs.lean @@ -336,10 +336,10 @@ theorem pow_coeff (m : ℕ) (x : 𝕎 R) (n : ℕ) : simp [(· ^ ·), Pow.pow, eval, Matrix.cons_fin_one, coeff_mk] theorem add_coeff_zero (x y : 𝕎 R) : (x + y).coeff 0 = x.coeff 0 + y.coeff 0 := by - simp [add_coeff, peval] + simp [add_coeff, peval, Function.uncurry] theorem mul_coeff_zero (x y : 𝕎 R) : (x * y).coeff 0 = x.coeff 0 * y.coeff 0 := by - simp [mul_coeff, peval] + simp [mul_coeff, peval, Function.uncurry] end Coeff diff --git a/Mathlib/RingTheory/WittVector/IsPoly.lean b/Mathlib/RingTheory/WittVector/IsPoly.lean index bd28c2be06298..ef5430b614c18 100644 --- a/Mathlib/RingTheory/WittVector/IsPoly.lean +++ b/Mathlib/RingTheory/WittVector/IsPoly.lean @@ -116,7 +116,7 @@ theorem poly_eq_of_wittPolynomial_bind_eq' [Fact p.Prime] (f g : ℕ → MvPolyn rw [← Function.funext_iff] at h replace h := congr_arg (fun fam => bind₁ (MvPolynomial.map (Int.castRingHom ℚ) ∘ fam) (xInTermsOfW p ℚ n)) h - simpa only [Function.comp, map_bind₁, map_wittPolynomial, ← bind₁_bind₁, + simpa only [Function.comp_def, map_bind₁, map_wittPolynomial, ← bind₁_bind₁, bind₁_wittPolynomial_xInTermsOfW, bind₁_X_right] using h theorem poly_eq_of_wittPolynomial_bind_eq [Fact p.Prime] (f g : ℕ → MvPolynomial ℕ ℤ) @@ -126,7 +126,7 @@ theorem poly_eq_of_wittPolynomial_bind_eq [Fact p.Prime] (f g : ℕ → MvPolyno rw [← Function.funext_iff] at h replace h := congr_arg (fun fam => bind₁ (MvPolynomial.map (Int.castRingHom ℚ) ∘ fam) (xInTermsOfW p ℚ n)) h - simpa only [Function.comp, map_bind₁, map_wittPolynomial, ← bind₁_bind₁, + simpa only [Function.comp_def, map_bind₁, map_wittPolynomial, ← bind₁_bind₁, bind₁_wittPolynomial_xInTermsOfW, bind₁_X_right] using h -- Ideally, we would generalise this to n-ary functions @@ -233,7 +233,7 @@ instance IsPoly₂.comp {h f g} [hh : IsPoly₂ p h] [hf : IsPoly p f] [hg : IsP uncurry] apply eval₂Hom_congr rfl _ rfl ext ⟨i, n⟩ - fin_cases i <;> simp [aeval_eq_eval₂Hom, eval₂Hom_rename, Function.comp] + fin_cases i <;> simp [aeval_eq_eval₂Hom, eval₂Hom_rename, Function.comp_def] /-- The composition of a polynomial function with a binary polynomial function is polynomial. -/ -- Porting note (#10754): made this an instance @@ -301,10 +301,8 @@ theorem bind₁_onePoly_wittPolynomial [hp : Fact p.Prime] (n : ℕ) : instance oneIsPoly [Fact p.Prime] : IsPoly p fun _ _ _ => 1 := ⟨⟨onePoly, by intros; funext n; cases n - · -- Porting note: was `simp only [...]` but with slightly different `[...]`. - simp only [lt_self_iff_false, one_coeff_zero, onePoly, ite_true, map_one] - · -- Porting note: was `simp only [...]` but with slightly different `[...]`. - simp only [Nat.succ_pos', one_coeff_eq_of_pos, onePoly, Nat.succ_ne_zero, ite_false, + · simp only [lt_self_iff_false, one_coeff_zero, onePoly, ite_true, map_one] + · simp only [Nat.succ_pos', one_coeff_eq_of_pos, onePoly, Nat.succ_ne_zero, ite_false, map_zero] ⟩⟩ diff --git a/Mathlib/RingTheory/WittVector/MulCoeff.lean b/Mathlib/RingTheory/WittVector/MulCoeff.lean index edb4720376f65..52cb2c116b25b 100644 --- a/Mathlib/RingTheory/WittVector/MulCoeff.lean +++ b/Mathlib/RingTheory/WittVector/MulCoeff.lean @@ -222,7 +222,7 @@ theorem peval_polyOfInterest' (n : ℕ) (x y : 𝕎 k) : rw [peval_polyOfInterest] have : (p : k) = 0 := CharP.cast_eq_zero k p simp only [this, Nat.cast_pow, ne_eq, add_eq_zero, and_false, zero_pow, zero_mul, add_zero, - not_false_eq_true] + not_false_eq_true, reduceCtorEq] have sum_zero_pow_mul_pow_p (y : 𝕎 k) : ∑ x ∈ range (n + 1 + 1), (0 : k) ^ x * y.coeff x ^ p ^ (n + 1 - x) = y.coeff 0 ^ p ^ (n + 1) := by rw [Finset.sum_eq_single_of_mem 0] <;> simp (config := { contextual := true }) @@ -243,10 +243,15 @@ theorem nth_mul_coeff' (n : ℕ) : apply f₀ rintro ⟨a, ha⟩ apply Function.uncurry ![x, y] - simp_rw [product_val, this, Multiset.mem_product, mem_univ_val, true_and_iff, range_val, - Multiset.range_succ, Multiset.mem_cons, Multiset.mem_range] at ha + simp_rw [product_val, this, range_val, Multiset.range_succ] at ha + let S : Set (Fin 2 × ℕ) := (fun a => a.2 = n ∨ a.2 < n) + have ha' : a ∈ S := by + convert ha + dsimp [S] + congr! + simp refine ⟨a.fst, ⟨a.snd, ?_⟩⟩ - cases' ha with ha ha <;> omega + cases' ha' with ha ha <;> omega use f intro x y dsimp [f, peval] diff --git a/Mathlib/RingTheory/WittVector/MulP.lean b/Mathlib/RingTheory/WittVector/MulP.lean index c5519b92ba158..6cdf37a89f03d 100644 --- a/Mathlib/RingTheory/WittVector/MulP.lean +++ b/Mathlib/RingTheory/WittVector/MulP.lean @@ -70,7 +70,7 @@ theorem bind₁_wittMulN_wittPolynomial (n k : ℕ) : · rw [wittMulN, ← bind₁_bind₁, wittAdd, wittStructureInt_prop] simp only [map_add, Nat.cast_succ, bind₁_X_right] rw [add_mul, one_mul, bind₁_rename, bind₁_rename] - simp only [ih, Function.uncurry, Function.comp, bind₁_X_left, AlgHom.id_apply, + simp only [ih, Function.uncurry, Function.comp_def, bind₁_X_left, AlgHom.id_apply, Matrix.cons_val_zero, Matrix.head_cons, Matrix.cons_val_one] end diff --git a/Mathlib/RingTheory/WittVector/WittPolynomial.lean b/Mathlib/RingTheory/WittVector/WittPolynomial.lean index de01b15cb0a5c..aab99256bb5a2 100644 --- a/Mathlib/RingTheory/WittVector/WittPolynomial.lean +++ b/Mathlib/RingTheory/WittVector/WittPolynomial.lean @@ -201,8 +201,7 @@ theorem xInTermsOfW_eq [Invertible (p : R)] {n : ℕ} : xInTermsOfW p R n = @[simp] theorem constantCoeff_xInTermsOfW [hp : Fact p.Prime] [Invertible (p : R)] (n : ℕ) : constantCoeff (xInTermsOfW p R n) = 0 := by - apply Nat.strongInductionOn n; clear n - intro n IH + induction n using Nat.strongRecOn with | ind n IH => ?_ rw [xInTermsOfW_eq, mul_comm, RingHom.map_mul, RingHom.map_sub, map_sum, constantCoeff_C, constantCoeff_X, zero_sub, mul_neg, neg_eq_zero] -- Porting note: here, we should be able to do `rw [sum_eq_zero]`, but the goal that @@ -227,8 +226,7 @@ variable [hp : Fact p.Prime] theorem xInTermsOfW_vars_aux (n : ℕ) : n ∈ (xInTermsOfW p ℚ n).vars ∧ (xInTermsOfW p ℚ n).vars ⊆ range (n + 1) := by - apply Nat.strongInductionOn n; clear n - intro n ih + induction n using Nat.strongRecOn with | ind n ih => ?_ rw [xInTermsOfW_eq, mul_comm, vars_C_mul _ (Invertible.ne_zero _), vars_sub_of_disjoint, vars_X, range_succ, insert_eq] on_goal 1 => @@ -276,9 +274,7 @@ theorem bind₁_xInTermsOfW_wittPolynomial [Invertible (p : R)] (k : ℕ) : @[simp] theorem bind₁_wittPolynomial_xInTermsOfW [Invertible (p : R)] (n : ℕ) : bind₁ (W_ R) (xInTermsOfW p R n) = X n := by - apply Nat.strongInductionOn n - clear n - intro n H + induction n using Nat.strongRecOn with | ind n H => ?_ rw [xInTermsOfW_eq, map_mul, map_sub, bind₁_X_right, algHom_C, map_sum, show X n = (X n * C ((p : R) ^ n)) * C ((⅟p : R) ^ n) by rw [mul_assoc, ← C_mul, ← mul_pow, mul_invOf_self, one_pow, map_one, mul_one]] diff --git a/Mathlib/SetTheory/Cardinal/Basic.lean b/Mathlib/SetTheory/Cardinal/Basic.lean index 302fa05874ae6..6dfc1c178ffde 100644 --- a/Mathlib/SetTheory/Cardinal/Basic.lean +++ b/Mathlib/SetTheory/Cardinal/Basic.lean @@ -663,7 +663,7 @@ instance : WellFoundedLT Cardinal.{u} := instance wo : @IsWellOrder Cardinal.{u} (· < ·) where instance : ConditionallyCompleteLinearOrderBot Cardinal := - IsWellOrder.conditionallyCompleteLinearOrderBot _ + WellFoundedLT.conditionallyCompleteLinearOrderBot _ @[simp] theorem sInf_empty : sInf (∅ : Set Cardinal.{u}) = 0 := @@ -683,15 +683,10 @@ lemma iInf_eq_zero_iff {ι : Sort*} {f : ι → Cardinal} : simp [iInf, sInf_eq_zero_iff] /-- Note that the successor of `c` is not the same as `c + 1` except in the case of finite `c`. -/ -instance : SuccOrder Cardinal := - SuccOrder.ofSuccLeIff (fun c => sInf { c' | c < c' }) - -- Porting note: Needed to insert `by apply` in the next line - ⟨by apply lt_of_lt_of_le <| csInf_mem <| exists_gt _, - -- Porting note used to be just `csInf_le'` - fun h ↦ csInf_le' h⟩ +instance : SuccOrder Cardinal := ConditionallyCompleteLinearOrder.toSuccOrder theorem succ_def (c : Cardinal) : succ c = sInf { c' | c < c' } := - rfl + dif_neg <| not_isMax c theorem succ_pos : ∀ c : Cardinal, 0 < succ c := bot_lt_succ @@ -1031,7 +1026,7 @@ theorem lift_sSup {s : Set Cardinal} (hs : BddAbove s) : theorem lift_iSup {ι : Type v} {f : ι → Cardinal.{w}} (hf : BddAbove (range f)) : lift.{u} (iSup f) = ⨆ i, lift.{u} (f i) := by rw [iSup, iSup, lift_sSup hf, ← range_comp] - simp [Function.comp] + simp [Function.comp_def] /-- To prove that the lift of a supremum is bounded by some cardinal `t`, it suffices to show that the lift of each cardinal is bounded by `t`. -/ @@ -1998,3 +1993,5 @@ end Cardinal -- failed -- end Tactic + +set_option linter.style.longFile 2100 diff --git a/Mathlib/SetTheory/Cardinal/Cofinality.lean b/Mathlib/SetTheory/Cardinal/Cofinality.lean index aa8f521ccd377..0db148a847ba8 100644 --- a/Mathlib/SetTheory/Cardinal/Cofinality.lean +++ b/Mathlib/SetTheory/Cardinal/Cofinality.lean @@ -195,7 +195,7 @@ theorem ord_cof_eq (r : α → α → Prop) [IsWellOrder α r] : private theorem card_mem_cof {o} : ∃ (ι : _) (f : ι → Ordinal), lsub.{u, u} f = o ∧ #ι = o.card := - ⟨_, _, lsub_typein o, mk_ordinal_out o⟩ + ⟨_, _, lsub_typein o, mk_toType o⟩ /-- The set in the `lsub` characterization of `cof` is nonempty. -/ theorem cof_lsub_def_nonempty (o) : @@ -210,7 +210,7 @@ theorem cof_eq_sInf_lsub (o : Ordinal.{u}) : cof o = refine (cof_type_le fun a => ?_).trans (@mk_le_of_injective _ _ - (fun s : typein ((· < ·) : o.out.α → o.out.α → Prop) ⁻¹' Set.range f => + (fun s : typein ((· < ·) : o.toType → o.toType → Prop) ⁻¹' Set.range f => Classical.choose s.prop) fun s t hst => by let H := congr_arg f hst @@ -219,18 +219,18 @@ theorem cof_eq_sInf_lsub (o : Ordinal.{u}) : cof o = have := typein_lt_self a simp_rw [← hf, lt_lsub_iff] at this cases' this with i hi - refine ⟨enum (· < ·) (f i) ?_, ?_, ?_⟩ + refine ⟨enum (α := o.toType) (· < ·) ⟨f i, ?_⟩, ?_, ?_⟩ · rw [type_lt, ← hf] apply lt_lsub · rw [mem_preimage, typein_enum] exact mem_range_self i · rwa [← typein_le_typein, typein_enum] - · rcases cof_eq (· < · : (Quotient.out o).α → (Quotient.out o).α → Prop) with ⟨S, hS, hS'⟩ + · rcases cof_eq (α := o.toType) (· < ·) with ⟨S, hS, hS'⟩ let f : S → Ordinal := fun s => typein LT.lt s.val refine ⟨S, f, le_antisymm (lsub_le fun i => typein_lt_self (o := o) i) (le_of_forall_lt fun a ha => ?_), by rwa [type_lt o] at hS'⟩ rw [← type_lt o] at ha - rcases hS (enum (· < ·) a ha) with ⟨b, hb, hb'⟩ + rcases hS (enum (· < ·) ⟨a, ha⟩) with ⟨b, hb, hb'⟩ rw [← typein_le_typein, typein_enum] at hb' exact hb'.trans_lt (lt_lsub.{u, u} f ⟨b, hb⟩) @@ -352,7 +352,7 @@ theorem nfpFamily_lt_ord {ι} {f : ι → Ordinal → Ordinal} {c} (hc : ℵ₀ theorem nfpBFamily_lt_ord_lift {o : Ordinal} {f : ∀ a < o, Ordinal → Ordinal} {c} (hc : ℵ₀ < cof c) (hc' : Cardinal.lift.{v, u} o.card < cof c) (hf : ∀ (i hi), ∀ b < c, f i hi b < c) {a} : a < c → nfpBFamily.{u, v} o f a < c := - nfpFamily_lt_ord_lift hc (by rwa [mk_ordinal_out]) fun i => hf _ _ + nfpFamily_lt_ord_lift hc (by rwa [mk_toType]) fun i => hf _ _ theorem nfpBFamily_lt_ord {o : Ordinal} {f : ∀ a < o, Ordinal → Ordinal} {c} (hc : ℵ₀ < cof c) (hc' : o.card < cof c) (hf : ∀ (i hi), ∀ b < c, f i hi b < c) {a} : @@ -381,7 +381,7 @@ theorem le_cof_iff_blsub {b : Ordinal} {a : Cardinal} : theorem cof_blsub_le_lift {o} (f : ∀ a < o, Ordinal) : cof (blsub.{u, v} o f) ≤ Cardinal.lift.{v, u} o.card := by - rw [← mk_ordinal_out o] + rw [← mk_toType o] exact cof_lsub_le_lift _ theorem cof_blsub_le {o} (f : ∀ a < o, Ordinal) : cof (blsub.{u, u} o f) ≤ o.card := by @@ -553,7 +553,7 @@ theorem exists_fundamental_sequence (a : Ordinal.{u}) : let hrr' : r' ↪r r := Subrel.relEmbedding _ _ haveI := hrr'.isWellOrder refine - ⟨_, _, hrr'.ordinal_type_le.trans ?_, @fun i j _ h _ => (enum r' j h).prop _ ?_, + ⟨_, _, hrr'.ordinal_type_le.trans ?_, @fun i j _ h _ => (enum r' ⟨j, h⟩).prop _ ?_, le_antisymm (blsub_le fun i hi => lsub_le_iff.1 hf.le _) ?_⟩ · rw [← hι, hr] · change r (hrr'.1 _) (hrr'.1 _) @@ -660,7 +660,7 @@ 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 ⟨S, fun a => - let a' := enum r _ (h.2 _ (typein_lt_type r a)) + let a' := enum r ⟨_, h.2 _ (typein_lt_type r a)⟩ let ⟨b, h, ab⟩ := H a' ⟨b, h, (IsOrderConnected.conn a b a' <| @@ -1037,7 +1037,7 @@ theorem nfpBFamily_lt_ord_lift_of_isRegular {o : Ordinal} {f : ∀ a < o, Ordina (hc : IsRegular c) (ho : Cardinal.lift.{v, u} o.card < c) (hc' : c ≠ ℵ₀) (hf : ∀ (i hi), ∀ b < c.ord, f i hi b < c.ord) {a} : a < c.ord → nfpBFamily.{u, v} o f a < c.ord := - nfpFamily_lt_ord_lift_of_isRegular hc (by rwa [mk_ordinal_out]) hc' fun i => hf _ _ + nfpFamily_lt_ord_lift_of_isRegular hc (by rwa [mk_toType]) hc' fun i => hf _ _ theorem nfpBFamily_lt_ord_of_isRegular {o : Ordinal} {f : ∀ a < o, Ordinal → Ordinal} {c} (hc : IsRegular c) (ho : o.card < c) (hc' : c ≠ ℵ₀) @@ -1086,7 +1086,7 @@ theorem derivBFamily_lt_ord_lift {o : Ordinal} {f : ∀ a < o, Ordinal → Ordin (hc : IsRegular c) (hι : Cardinal.lift.{v, u} o.card < c) (hc' : c ≠ ℵ₀) (hf : ∀ (i hi), ∀ b < c.ord, f i hi b < c.ord) {a} : a < c.ord → derivBFamily.{u, v} o f a < c.ord := - derivFamily_lt_ord_lift hc (by rwa [mk_ordinal_out]) hc' fun i => hf _ _ + derivFamily_lt_ord_lift hc (by rwa [mk_toType]) hc' fun i => hf _ _ theorem derivBFamily_lt_ord {o : Ordinal} {f : ∀ a < o, Ordinal → Ordinal} {c} (hc : IsRegular c) (hι : o.card < c) (hc' : c ≠ ℵ₀) (hf : ∀ (i hi), ∀ b < c.ord, f i hi b < c.ord) {a} : diff --git a/Mathlib/SetTheory/Cardinal/Continuum.lean b/Mathlib/SetTheory/Cardinal/Continuum.lean index 8614f68343c3b..9aeb9a15becb8 100644 --- a/Mathlib/SetTheory/Cardinal/Continuum.lean +++ b/Mathlib/SetTheory/Cardinal/Continuum.lean @@ -166,15 +166,22 @@ theorem continuum_mul_ofNat {n : ℕ} [Nat.AtLeastTwo n] : 𝔠 * no_index (OfNa @[simp] -theorem aleph0_power_aleph0 : aleph0.{u} ^ aleph0.{u} = 𝔠 := +theorem aleph0_power_aleph0 : ℵ₀ ^ ℵ₀ = 𝔠 := power_self_eq le_rfl @[simp] -theorem nat_power_aleph0 {n : ℕ} (hn : 2 ≤ n) : (n ^ aleph0.{u} : Cardinal.{u}) = 𝔠 := +theorem nat_power_aleph0 {n : ℕ} (hn : 2 ≤ n) : n ^ ℵ₀ = 𝔠 := nat_power_eq le_rfl hn @[simp] -theorem continuum_power_aleph0 : continuum.{u} ^ aleph0.{u} = 𝔠 := by +theorem continuum_power_aleph0 : 𝔠 ^ ℵ₀ = 𝔠 := by rw [← two_power_aleph0, ← power_mul, mul_eq_left le_rfl le_rfl aleph0_ne_zero] +theorem power_aleph0_of_le_continuum {x : Cardinal} (h₁ : 2 ≤ x) (h₂ : x ≤ 𝔠) : x ^ ℵ₀ = 𝔠 := by + apply le_antisymm + · rw [← continuum_power_aleph0] + exact power_le_power_right h₂ + · rw [← two_power_aleph0] + exact power_le_power_right h₁ + end Cardinal diff --git a/Mathlib/SetTheory/Cardinal/CountableCover.lean b/Mathlib/SetTheory/Cardinal/CountableCover.lean index 35f9e9f8483e6..65caa5dd364f5 100644 --- a/Mathlib/SetTheory/Cardinal/CountableCover.lean +++ b/Mathlib/SetTheory/Cardinal/CountableCover.lean @@ -25,7 +25,7 @@ universe u v /-- If a set `t` is eventually covered by a countable family of sets, all with cardinality at most `a`, then the cardinality of `t` is also bounded by `a`. -Supersed by `mk_le_of_countable_eventually_mem` which does not assume +Superseded by `mk_le_of_countable_eventually_mem` which does not assume that the indexing set lives in the same universe. -/ lemma mk_subtype_le_of_countable_eventually_mem_aux {α ι : Type u} {a : Cardinal} [Countable ι] {f : ι → Set α} {l : Filter ι} [NeBot l] diff --git a/Mathlib/SetTheory/Cardinal/Finsupp.lean b/Mathlib/SetTheory/Cardinal/Finsupp.lean index fc2818b357c56..d62685c418254 100644 --- a/Mathlib/SetTheory/Cardinal/Finsupp.lean +++ b/Mathlib/SetTheory/Cardinal/Finsupp.lean @@ -58,15 +58,15 @@ theorem mk_finsupp_nat (α : Type u) [Nonempty α] : #(α →₀ ℕ) = max #α theorem mk_multiset_of_isEmpty (α : Type u) [IsEmpty α] : #(Multiset α) = 1 := Multiset.toFinsupp.toEquiv.cardinal_eq.trans (by simp) -open scoped Classical - @[simp] -theorem mk_multiset_of_nonempty (α : Type u) [Nonempty α] : #(Multiset α) = max #α ℵ₀ := - Multiset.toFinsupp.toEquiv.cardinal_eq.trans (mk_finsupp_nat α) +theorem mk_multiset_of_nonempty (α : Type u) [Nonempty α] : #(Multiset α) = max #α ℵ₀ := by + classical + exact Multiset.toFinsupp.toEquiv.cardinal_eq.trans (mk_finsupp_nat α) theorem mk_multiset_of_infinite (α : Type u) [Infinite α] : #(Multiset α) = #α := by simp -theorem mk_multiset_of_countable (α : Type u) [Countable α] [Nonempty α] : #(Multiset α) = ℵ₀ := - Multiset.toFinsupp.toEquiv.cardinal_eq.trans (by simp) +theorem mk_multiset_of_countable (α : Type u) [Countable α] [Nonempty α] : #(Multiset α) = ℵ₀ := by + classical + exact Multiset.toFinsupp.toEquiv.cardinal_eq.trans (by simp) end Cardinal diff --git a/Mathlib/SetTheory/Cardinal/Ordinal.lean b/Mathlib/SetTheory/Cardinal/Ordinal.lean index 98fb9b0b0ef76..b9f6c63e10014 100644 --- a/Mathlib/SetTheory/Cardinal/Ordinal.lean +++ b/Mathlib/SetTheory/Cardinal/Ordinal.lean @@ -66,10 +66,11 @@ theorem ord_isLimit {c} (co : ℵ₀ ≤ c) : (ord c).IsLimit := by · rw [ord_aleph0] exact omega_isLimit -theorem noMaxOrder {c} (h : ℵ₀ ≤ c) : NoMaxOrder c.ord.out.α := - Ordinal.out_no_max_of_succ_lt (ord_isLimit h).2 +theorem noMaxOrder {c} (h : ℵ₀ ≤ c) : NoMaxOrder c.ord.toType := + toType_noMax_of_succ_lt (ord_isLimit h).2 /-! ### Aleph cardinals -/ + section aleph /-- The `aleph'` index function, which gives the ordinal index of a cardinal. @@ -124,7 +125,7 @@ def alephIdx.relIso : @RelIso Cardinal.{u} Ordinal.{u} (· < ·) (· < ·) := simpa only [typein_enum, leftInverse_invFun I (succ s)] using le_ciSup (Cardinal.bddAbove_range.{u, u} fun a : α => invFun alephIdx (Ordinal.typein r a)) - (Ordinal.enum r _ (h (succ s))) + (Ordinal.enum r ⟨_, h (succ s)⟩) @[simp] theorem alephIdx.relIso_coe : (alephIdx.relIso : Cardinal → Ordinal) = alephIdx := @@ -271,15 +272,15 @@ theorem aleph_toNat (o : Ordinal) : toNat (aleph o) = 0 := theorem aleph_toPartENat (o : Ordinal) : toPartENat (aleph o) = ⊤ := toPartENat_apply_of_aleph0_le <| aleph0_le_aleph o -instance nonempty_out_aleph (o : Ordinal) : Nonempty (aleph o).ord.out.α := by - rw [out_nonempty_iff_ne_zero, ← ord_zero] +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.out.α := - out_no_max_of_succ_lt (ord_aleph_isLimit o).2 +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 => @@ -1444,9 +1445,9 @@ lemma mk_iUnion_Ordinal_le_of_le {β : Type*} {o : Ordinal} {c : Cardinal} (ho : o.card ≤ c) (hc : ℵ₀ ≤ c) (A : Ordinal → Set β) (hA : ∀ j < o, #(A j) ≤ c) : #(⋃ j < o, A j) ≤ c := by - simp_rw [← mem_Iio, biUnion_eq_iUnion, iUnion, iSup, ← o.enumIsoOut.symm.surjective.range_comp] + simp_rw [← mem_Iio, biUnion_eq_iUnion, iUnion, iSup, ← o.enumIsoToType.symm.surjective.range_comp] apply ((mk_iUnion_le _).trans _).trans_eq (mul_eq_self hc) - rw [mk_ordinal_out] + rw [mk_toType] exact mul_le_mul' ho <| ciSup_le' <| (hA _ <| typein_lt_self ·) end Cardinal diff --git a/Mathlib/SetTheory/Game/Basic.lean b/Mathlib/SetTheory/Game/Basic.lean index b8a4c1008298e..facf1b4ea1afd 100644 --- a/Mathlib/SetTheory/Game/Basic.lean +++ b/Mathlib/SetTheory/Game/Basic.lean @@ -134,7 +134,7 @@ end Game namespace PGame --- Porting note: In a lot of places, I had to add explicitely that the quotient element was a Game. +-- Porting note: In a lot of places, I had to add explicitly that the quotient element was a Game. -- In Lean4, quotients don't have the setoid as an instance argument, -- but as an explicit argument, see https://leanprover.zulipchat.com/#narrow/stream/113489-new-members/topic/confusion.20between.20equivalence.20and.20instance.20setoid/near/360822354 theorem le_iff_game_le {x y : PGame} : x ≤ y ↔ (⟦x⟧ : Game) ≤ ⟦y⟧ := @@ -246,8 +246,8 @@ Hence we define them here. -/ `{xL*y + x*yL - xL*yL, xR*y + x*yR - xR*yR | xL*y + x*yR - xL*yR, x*yL + xR*y - xR*yL }`. -/ instance : Mul PGame.{u} := ⟨fun x y => by - induction' x with xl xr _ _ IHxl IHxr generalizing y - induction' y with yl yr yL yR IHyl IHyr + induction x generalizing y with | mk xl xr _ _ IHxl IHxr => _ + induction y with | mk yl yr yL yR IHyl IHyr => _ have y := mk yl yr yL yR refine ⟨(xl × yl) ⊕ (xr × yr), (xl × yr) ⊕ (xr × yl), ?_, ?_⟩ <;> rintro (⟨i, j⟩ | ⟨i, j⟩) · exact IHxl i y + IHyl j - IHxl i (yL j) diff --git a/Mathlib/SetTheory/Game/Birthday.lean b/Mathlib/SetTheory/Game/Birthday.lean index ec738e14e6401..28f8edebd14c0 100644 --- a/Mathlib/SetTheory/Game/Birthday.lean +++ b/Mathlib/SetTheory/Game/Birthday.lean @@ -83,7 +83,6 @@ theorem Relabelling.birthday_congr : ∀ {x y : PGame.{u}}, x ≡r y → birthda · exact ⟨_, (r.moveLeftSymm j).birthday_congr⟩ · exact ⟨_, (r.moveRight j).birthday_congr.symm⟩ · exact ⟨_, (r.moveRightSymm j).birthday_congr⟩ -termination_by x y => (x, y) @[simp] theorem birthday_eq_zero {x : PGame} : diff --git a/Mathlib/SetTheory/Game/Nim.lean b/Mathlib/SetTheory/Game/Nim.lean index f56bc51986556..9253e4a97b9c6 100644 --- a/Mathlib/SetTheory/Game/Nim.lean +++ b/Mathlib/SetTheory/Game/Nim.lean @@ -24,7 +24,7 @@ However, this definition does not work for us because it would make the type of `Ordinal.{u} → SetTheory.PGame.{u + 1}`, which would make it impossible for us to state the Sprague-Grundy theorem, since that requires the type of `nim` to be `Ordinal.{u} → SetTheory.PGame.{u}`. For this reason, we -instead use `o.out.α` for the possible moves. You can use `to_left_moves_nim` and +instead use `o.toType` for the possible moves. You can use `to_left_moves_nim` and `to_right_moves_nim` to convert an ordinal less than `o` into a left or right move of `nim o`, and vice versa. -/ @@ -37,62 +37,54 @@ universe u namespace SetTheory open scoped PGame +open Ordinal namespace PGame --- Uses `noncomputable!` to avoid `rec_fn_macro only allowed in meta definitions` VM error /-- The definition of single-heap nim, which can be viewed as a pile of stones where each player can take a positive number of stones from it on their turn. -/ -noncomputable def nim : Ordinal.{u} → PGame.{u} - | o₁ => - let f o₂ := - have _ : Ordinal.typein o₁.out.r o₂ < o₁ := Ordinal.typein_lt_self o₂ - nim (Ordinal.typein o₁.out.r o₂) - ⟨o₁.out.α, o₁.out.α, f, f⟩ -termination_by o => o - -open Ordinal - -theorem nim_def (o : Ordinal) : - have : IsWellOrder (Quotient.out o).α (· < ·) := inferInstance - nim o = - PGame.mk o.out.α o.out.α (fun o₂ => nim (Ordinal.typein (· < ·) o₂)) fun o₂ => - nim (Ordinal.typein (· < ·) o₂) := by - rw [nim]; rfl - -theorem leftMoves_nim (o : Ordinal) : (nim o).LeftMoves = o.out.α := by rw [nim_def]; rfl - -theorem rightMoves_nim (o : Ordinal) : (nim o).RightMoves = o.out.α := by rw [nim_def]; rfl +noncomputable def nim (o : Ordinal.{u}) : PGame.{u} := + ⟨o.toType, o.toType, + fun x => nim ((enumIsoToType o).symm x).val, + fun x => nim ((enumIsoToType o).symm x).val⟩ +termination_by o +decreasing_by all_goals exact ((enumIsoToType o).symm x).prop + +theorem nim_def (o : Ordinal) : nim o = + ⟨o.toType, o.toType, + fun x => nim ((enumIsoToType o).symm x).val, + fun x => nim ((enumIsoToType o).symm x).val⟩ := by + rw [nim] + +theorem leftMoves_nim (o : Ordinal) : (nim o).LeftMoves = o.toType := by rw [nim_def]; rfl +theorem rightMoves_nim (o : Ordinal) : (nim o).RightMoves = o.toType := by rw [nim_def]; rfl theorem moveLeft_nim_hEq (o : Ordinal) : - have : IsWellOrder (Quotient.out o).α (· < ·) := inferInstance - HEq (nim o).moveLeft fun i : o.out.α => nim (typein (· < ·) i) := by rw [nim_def]; rfl + HEq (nim o).moveLeft fun i : o.toType => nim ((enumIsoToType o).symm i) := by rw [nim_def]; rfl theorem moveRight_nim_hEq (o : Ordinal) : - have : IsWellOrder (Quotient.out o).α (· < ·) := inferInstance - HEq (nim o).moveRight fun i : o.out.α => nim (typein (· < ·) i) := by rw [nim_def]; rfl + HEq (nim o).moveRight fun i : o.toType => nim ((enumIsoToType o).symm i) := by rw [nim_def]; rfl -/-- Turns an ordinal less than `o` into a left move for `nim o` and viceversa. -/ +/-- Turns an ordinal less than `o` into a left move for `nim o` and vice versa. -/ noncomputable def toLeftMovesNim {o : Ordinal} : Set.Iio o ≃ (nim o).LeftMoves := - (enumIsoOut o).toEquiv.trans (Equiv.cast (leftMoves_nim o).symm) + (enumIsoToType o).toEquiv.trans (Equiv.cast (leftMoves_nim o).symm) -/-- Turns an ordinal less than `o` into a right move for `nim o` and viceversa. -/ +/-- Turns an ordinal less than `o` into a right move for `nim o` and vice versa. -/ noncomputable def toRightMovesNim {o : Ordinal} : Set.Iio o ≃ (nim o).RightMoves := - (enumIsoOut o).toEquiv.trans (Equiv.cast (rightMoves_nim o).symm) + (enumIsoToType o).toEquiv.trans (Equiv.cast (rightMoves_nim o).symm) @[simp] theorem toLeftMovesNim_symm_lt {o : Ordinal} (i : (nim o).LeftMoves) : - ↑(toLeftMovesNim.symm i) < o := + toLeftMovesNim.symm i < o := (toLeftMovesNim.symm i).prop @[simp] theorem toRightMovesNim_symm_lt {o : Ordinal} (i : (nim o).RightMoves) : - ↑(toRightMovesNim.symm i) < o := + toRightMovesNim.symm i < o := (toRightMovesNim.symm i).prop @[simp] -theorem moveLeft_nim' {o : Ordinal.{u}} (i) : - (nim o).moveLeft i = nim (toLeftMovesNim.symm i).val := +theorem moveLeft_nim' {o : Ordinal} (i) : (nim o).moveLeft i = nim (toLeftMovesNim.symm i).val := (congr_heq (moveLeft_nim_hEq o).symm (cast_heq _ i)).symm theorem moveLeft_nim {o : Ordinal} (i) : (nim o).moveLeft (toLeftMovesNim i) = nim i := by simp @@ -117,11 +109,11 @@ def rightMovesNimRecOn {o : Ordinal} {P : (nim o).RightMoves → Sort*} (i : (ni instance isEmpty_nim_zero_leftMoves : IsEmpty (nim 0).LeftMoves := by rw [nim_def] - exact Ordinal.isEmpty_out_zero + exact isEmpty_toType_zero instance isEmpty_nim_zero_rightMoves : IsEmpty (nim 0).RightMoves := by rw [nim_def] - exact Ordinal.isEmpty_out_zero + exact isEmpty_toType_zero /-- `nim 0` has exactly the same moves as `0`. -/ def nimZeroRelabelling : nim 0 ≡r 0 := @@ -165,7 +157,7 @@ def nimOneRelabelling : nim 1 ≡r star := by rw [nim_def] refine ⟨?_, ?_, fun i => ?_, fun j => ?_⟩ any_goals dsimp; apply Equiv.equivOfUnique - all_goals simpa using nimZeroRelabelling + all_goals simpa [enumIsoToType] using nimZeroRelabelling theorem nim_one_equiv : nim 1 ≈ star := nimOneRelabelling.equiv @@ -190,9 +182,9 @@ instance nim_impartial (o : Ordinal) : Impartial (nim o) := by refine ⟨equiv_rfl, fun i => ?_, fun i => ?_⟩ <;> simpa using IH _ (typein_lt_self _) theorem nim_fuzzy_zero_of_ne_zero {o : Ordinal} (ho : o ≠ 0) : nim o ‖ 0 := by - rw [Impartial.fuzzy_zero_iff_lf, nim_def, lf_zero_le] - rw [← Ordinal.pos_iff_ne_zero] at ho - exact ⟨(Ordinal.principalSegOut ho).top, by simp⟩ + rw [Impartial.fuzzy_zero_iff_lf, lf_zero_le] + use toRightMovesNim ⟨0, Ordinal.pos_iff_ne_zero.2 ho⟩ + simp @[simp] theorem nim_add_equiv_zero_iff (o₁ o₂ : Ordinal) : (nim o₁ + nim o₂ ≈ 0) ↔ o₁ = o₂ := by @@ -200,12 +192,9 @@ theorem nim_add_equiv_zero_iff (o₁ o₂ : Ordinal) : (nim o₁ + nim o₂ ≈ · refine not_imp_not.1 fun hne : _ ≠ _ => (Impartial.not_equiv_zero_iff (nim o₁ + nim o₂)).2 ?_ wlog h : o₁ < o₂ · exact (fuzzy_congr_left add_comm_equiv).1 (this _ _ hne.symm (hne.lt_or_lt.resolve_left h)) - rw [Impartial.fuzzy_zero_iff_gf, zero_lf_le, nim_def o₂] - refine ⟨toLeftMovesAdd (Sum.inr ?_), ?_⟩ - · exact (Ordinal.principalSegOut h).top - · -- Porting note: squeezed simp - simpa only [Ordinal.typein_top, Ordinal.type_lt, PGame.add_moveLeft_inr, PGame.moveLeft_mk] - using (Impartial.add_self (nim o₁)).2 + rw [Impartial.fuzzy_zero_iff_gf, zero_lf_le] + use toLeftMovesAdd (Sum.inr <| toLeftMovesNim ⟨_, h⟩) + · simpa using (Impartial.add_self (nim o₁)).2 · rintro rfl exact Impartial.add_self (nim o₁) @@ -251,12 +240,11 @@ theorem equiv_nim_grundyValue : ∀ (G : PGame.{u}) [G.Impartial], G ≈ nim (gr intro i₂ have h' : ∃ i : G.LeftMoves, - grundyValue (G.moveLeft i) = Ordinal.typein (Quotient.out (grundyValue G)).r i₂ := by + grundyValue (G.moveLeft i) = Ordinal.typein (α := toType (grundyValue G)) (· < ·) i₂ := by revert i₂ rw [grundyValue_eq_mex_left] intro i₂ - have hnotin : _ ∉ _ := fun hin => - (le_not_le_of_lt (Ordinal.typein_lt_self i₂)).2 (csInf_le' hin) + have hnotin : _ ∉ _ := fun hin => not_le_of_lt (Ordinal.typein_lt_self i₂) (csInf_le' hin) simpa using hnotin cases' h' with i hi use toLeftMovesAdd (Sum.inl i) diff --git a/Mathlib/SetTheory/Game/Ordinal.lean b/Mathlib/SetTheory/Game/Ordinal.lean index f5a9f99f65e82..5fdf75f21eaa4 100644 --- a/Mathlib/SetTheory/Game/Ordinal.lean +++ b/Mathlib/SetTheory/Game/Ordinal.lean @@ -30,26 +30,20 @@ open scoped NaturalOps PGame namespace Ordinal /-- Converts an ordinal into the corresponding pre-game. -/ -noncomputable def toPGame : Ordinal.{u} → PGame.{u} - | o => - have : IsWellOrder o.out.α (· < ·) := isWellOrder_out_lt o - ⟨o.out.α, PEmpty, fun x => - have := Ordinal.typein_lt_self x - (typein (· < ·) x).toPGame, - PEmpty.elim⟩ -termination_by x => x +noncomputable def toPGame (o : Ordinal.{u}) : PGame.{u} := + ⟨o.toType, PEmpty, fun x => ((enumIsoToType o).symm x).val.toPGame, PEmpty.elim⟩ +termination_by o +decreasing_by exact ((enumIsoToType o).symm x).prop -@[nolint unusedHavesSuffices] -theorem toPGame_def (o : Ordinal) : - have : IsWellOrder o.out.α (· < ·) := isWellOrder_out_lt o - o.toPGame = ⟨o.out.α, PEmpty, fun x => (typein (· < ·) x).toPGame, PEmpty.elim⟩ := by +theorem toPGame_def (o : Ordinal) : o.toPGame = + ⟨o.toType, PEmpty, fun x => ((enumIsoToType o).symm x).val.toPGame, PEmpty.elim⟩ := by rw [toPGame] -@[simp, nolint unusedHavesSuffices] -theorem toPGame_leftMoves (o : Ordinal) : o.toPGame.LeftMoves = o.out.α := by +@[simp] +theorem toPGame_leftMoves (o : Ordinal) : o.toPGame.LeftMoves = o.toType := by rw [toPGame, LeftMoves] -@[simp, nolint unusedHavesSuffices] +@[simp] theorem toPGame_rightMoves (o : Ordinal) : o.toPGame.RightMoves = PEmpty := by rw [toPGame, RightMoves] @@ -62,7 +56,7 @@ instance isEmpty_toPGame_rightMoves (o : Ordinal) : IsEmpty o.toPGame.RightMoves /-- Converts an ordinal less than `o` into a move for the `PGame` corresponding to `o`, and vice versa. -/ noncomputable def toLeftMovesToPGame {o : Ordinal} : Set.Iio o ≃ o.toPGame.LeftMoves := - (enumIsoOut o).toEquiv.trans (Equiv.cast (toPGame_leftMoves o).symm) + (enumIsoToType o).toEquiv.trans (Equiv.cast (toPGame_leftMoves o).symm) @[simp] theorem toLeftMovesToPGame_symm_lt {o : Ordinal} (i : o.toPGame.LeftMoves) : @@ -71,8 +65,7 @@ theorem toLeftMovesToPGame_symm_lt {o : Ordinal} (i : o.toPGame.LeftMoves) : @[nolint unusedHavesSuffices] theorem toPGame_moveLeft_hEq {o : Ordinal} : - have : IsWellOrder o.out.α (· < ·) := isWellOrder_out_lt o - HEq o.toPGame.moveLeft fun x : o.out.α => (typein (· < ·) x).toPGame := by + HEq o.toPGame.moveLeft fun x : o.toType => ((enumIsoToType o).symm x).val.toPGame := by rw [toPGame] rfl diff --git a/Mathlib/SetTheory/Game/PGame.lean b/Mathlib/SetTheory/Game/PGame.lean index 2f4a23900dd0c..dec9ea13bd617 100644 --- a/Mathlib/SetTheory/Game/PGame.lean +++ b/Mathlib/SetTheory/Game/PGame.lean @@ -216,9 +216,9 @@ theorem wf_isOption : WellFounded IsOption := ⟨fun x => moveRecOn x fun x IHl IHr => Acc.intro x fun y h => by - induction' h with _ i _ j - · exact IHl i - · exact IHr j⟩ + induction h with + | moveLeft i => exact IHl i + | moveRight j => exact IHr j⟩ /-- `Subsequent x y` says that `x` can be obtained by playing some nonempty sequence of moves from `y`. It is the transitive closure of `IsOption`. -/ @@ -458,7 +458,7 @@ private theorem le_trans_aux {x y z : PGame} instance : Preorder PGame := { PGame.le with le_refl := fun x => by - induction' x with _ _ _ _ IHl IHr + induction x with | mk _ _ _ _ IHl IHr => _ exact le_of_forall_lf (fun i => lf_of_le_moveLeft (IHl i)) fun i => lf_of_moveRight_le (IHr i) le_trans := by @@ -676,7 +676,7 @@ instance : IsEquiv _ PGame.Equiv where trans := fun _ _ _ ⟨xy, yx⟩ ⟨yz, zy⟩ => ⟨xy.trans yz, zy.trans yx⟩ symm _ _ := And.symm --- Porting note: moved the setoid instance from Basic.lean to here +-- Porting note: moved the setoid instance from Basic.lean to here instance setoid : Setoid PGame := ⟨Equiv, refl, symm, Trans.trans⟩ @@ -1262,8 +1262,8 @@ theorem zero_fuzzy_neg_iff {x : PGame} : 0 ‖ -x ↔ 0 ‖ x := by rw [← neg_ /-- The sum of `x = {xL | xR}` and `y = {yL | yR}` is `{xL + y, x + yL | xR + y, x + yR}`. -/ instance : Add PGame.{u} := ⟨fun x y => by - induction' x with xl xr _ _ IHxl IHxr generalizing y - induction' y with yl yr yL yR IHyl IHyr + induction x generalizing y with | mk xl xr _ _ IHxl IHxr => _ + induction y with | mk yl yr yL yR IHyl IHyr => _ have y := mk yl yr yL yR refine ⟨xl ⊕ yl, xr ⊕ yr, Sum.rec ?_ ?_, Sum.rec ?_ ?_⟩ · exact fun i => IHxl i y @@ -1759,3 +1759,5 @@ theorem zero_lf_one : (0 : PGame) ⧏ 1 := end PGame end SetTheory + +set_option linter.style.longFile 1900 diff --git a/Mathlib/SetTheory/Game/Short.lean b/Mathlib/SetTheory/Game/Short.lean index f067239a8a277..fa9a0a1b91291 100644 --- a/Mathlib/SetTheory/Game/Short.lean +++ b/Mathlib/SetTheory/Game/Short.lean @@ -175,8 +175,8 @@ class inductive ListShort : List PGame.{u} → Type (u + 1) attribute [instance] ListShort.nil -instance ListShort.cons (hd : PGame.{u}) [short_hd : Short hd] - (tl : List PGame.{u}) [short_tl : ListShort tl] : +instance ListShort.cons + (hd : PGame.{u}) [short_hd : Short hd] (tl : List PGame.{u}) [short_tl : ListShort tl] : ListShort (hd::tl) := cons' short_hd short_tl @@ -188,9 +188,7 @@ instance listShortGet : instance shortOfLists : ∀ (L R : List PGame) [ListShort L] [ListShort R], Short (PGame.ofLists L R) | L, R, _, _ => by - apply Short.mk - · intros; infer_instance - · intros; apply PGame.listShortGet + exact Short.mk (fun i ↦ inferInstance) fun j ↦ listShortGet R (↑j.down) (ofLists.proof_2 R j) /-- If `x` is a short game, and `y` is a relabelling of `x`, then `y` is also short. -/ def shortOfRelabelling : ∀ {x y : PGame.{u}}, Relabelling x y → Short x → Short y diff --git a/Mathlib/SetTheory/Lists.lean b/Mathlib/SetTheory/Lists.lean index efd26b100c4e1..cd2aeac9c7722 100644 --- a/Mathlib/SetTheory/Lists.lean +++ b/Mathlib/SetTheory/Lists.lean @@ -129,7 +129,7 @@ instance : HasSubset (Lists' α true) := /-- ZFA prelist membership. A ZFA list is in a ZFA prelist if some element of this ZFA prelist is equivalent as a ZFA list to this ZFA list. -/ instance {b} : Membership (Lists α) (Lists' α b) := - ⟨fun a l => ∃ a' ∈ l.toList, a ~ a'⟩ + ⟨fun l a => ∃ a' ∈ l.toList, a ~ a'⟩ theorem mem_def {b a} {l : Lists' α b} : a ∈ l ↔ ∃ a' ∈ l.toList, a ~ a' := Iff.rfl @@ -148,9 +148,11 @@ theorem cons_subset {a} {l₁ l₂ : Lists' α true} : Lists'.cons a l₁ ⊆ l theorem ofList_subset {l₁ l₂ : List (Lists α)} (h : l₁ ⊆ l₂) : Lists'.ofList l₁ ⊆ Lists'.ofList l₂ := by - induction' l₁ with _ _ l₁_ih; · exact Subset.nil - refine Subset.cons (Lists.Equiv.refl _) ?_ (l₁_ih (List.subset_of_cons_subset h)) - simp only [List.cons_subset] at h; simp [h] + induction l₁ with + | nil => exact Subset.nil + | cons _ _ l₁_ih => + refine Subset.cons (Lists.Equiv.refl _) ?_ (l₁_ih (List.subset_of_cons_subset h)) + simp only [List.cons_subset] at h; simp [h] @[refl] theorem Subset.refl {l : Lists' α true} : l ⊆ l := by @@ -246,8 +248,8 @@ def mem (a : Lists α) : Lists α → Prop | ⟨false, _⟩ => False | ⟨_, l⟩ => a ∈ l -instance : Membership (Lists α) (Lists α) := - ⟨mem⟩ +instance : Membership (Lists α) (Lists α) where + mem ls l := mem l ls theorem isList_of_mem {a : Lists α} : ∀ {l : Lists α}, a ∈ l → IsList l | ⟨_, Lists'.nil⟩, _ => rfl @@ -299,16 +301,6 @@ instance instSetoidLists : Setoid (Lists α) := section Decidable -/-- Auxiliary function to prove termination of decidability checking -/ -@[simp, deprecated (since := "2023-06-24")] -def Equiv.decidableMeas : - ((Σ' _l₁ : Lists α, Lists α) ⊕' - ((Σ' _l₁ : Lists' α true, Lists' α true) ⊕' (Σ' _a : Lists α, Lists' α true))) → - ℕ - | PSum.inl ⟨l₁, l₂⟩ => SizeOf.sizeOf l₁ + SizeOf.sizeOf l₂ - | PSum.inr <| PSum.inl ⟨l₁, l₂⟩ => SizeOf.sizeOf l₁ + SizeOf.sizeOf l₂ - | PSum.inr <| PSum.inr ⟨l₁, l₂⟩ => SizeOf.sizeOf l₁ + SizeOf.sizeOf l₂ - theorem sizeof_pos {b} (l : Lists' α b) : 0 < SizeOf.sizeOf l := by cases l <;> simp only [Lists'.atom.sizeOf_spec, Lists'.nil.sizeOf_spec, Lists'.cons'.sizeOf_spec, true_or, add_pos_iff, zero_lt_one] diff --git a/Mathlib/SetTheory/Ordinal/Arithmetic.lean b/Mathlib/SetTheory/Ordinal/Arithmetic.lean index 42eadc412c344..e8a64b3d2223f 100644 --- a/Mathlib/SetTheory/Ordinal/Arithmetic.lean +++ b/Mathlib/SetTheory/Ordinal/Arithmetic.lean @@ -287,50 +287,48 @@ theorem limitRecOn_zero {C} (H₁ H₂ H₃) : @limitRecOn C 0 H₁ H₂ H₃ = @[simp] theorem limitRecOn_succ {C} (o H₁ H₂ H₃) : @limitRecOn C (succ o) H₁ H₂ H₃ = H₂ o (@limitRecOn C o H₁ H₂ H₃) := by - simp_rw [limitRecOn, SuccOrder.limitRecOn_succ _ _ (not_isMax _)] + rw [limitRecOn, limitRecOn, SuccOrder.limitRecOn_succ _ _ (not_isMax _)] @[simp] 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.limitRecOn_limit _ _ h.isSuccLimit, dif_neg h.1] -instance orderTopOutSucc (o : Ordinal) : OrderTop (succ o).out.α := +instance orderTopToTypeSucc (o : Ordinal) : OrderTop (succ o).toType := @OrderTop.mk _ _ (Top.mk _) le_enum_succ theorem enum_succ_eq_top {o : Ordinal} : - enum (· < ·) o - (by - rw [type_lt] - exact lt_succ o) = - (⊤ : (succ o).out.α) := + enum (α := (succ o).toType) (· < ·) ⟨o, by rw [type_lt]; exact lt_succ o⟩ = ⊤ := rfl theorem has_succ_of_type_succ_lt {α} {r : α → α → Prop} [wo : IsWellOrder α r] (h : ∀ a < type r, succ a < type r) (x : α) : ∃ y, r x y := by - use enum r (succ (typein r x)) (h _ (typein_lt_type r x)) - convert (enum_lt_enum (typein_lt_type r x) - (h _ (typein_lt_type r x))).mpr (lt_succ _); rw [enum_typein] + use enum r ⟨succ (typein r x), h _ (typein_lt_type r x)⟩ + convert enum_lt_enum (o₁ := ⟨_, typein_lt_type r x⟩) (o₂ := ⟨_, h _ (typein_lt_type r x)⟩).mpr _ + · rw [enum_typein] + · rw [Subtype.mk_lt_mk, lt_succ_iff] -theorem out_no_max_of_succ_lt {o : Ordinal} (ho : ∀ a < o, succ a < o) : NoMaxOrder o.out.α := +theorem toType_noMax_of_succ_lt {o : Ordinal} (ho : ∀ a < o, succ a < o) : NoMaxOrder o.toType := ⟨has_succ_of_type_succ_lt (by rwa [type_lt])⟩ +@[deprecated toType_noMax_of_succ_lt (since := "2024-08-26")] +alias out_no_max_of_succ_lt := toType_noMax_of_succ_lt + theorem bounded_singleton {r : α → α → Prop} [IsWellOrder α r] (hr : (type r).IsLimit) (x) : Bounded r {x} := by - refine ⟨enum r (succ (typein r x)) (hr.2 _ (typein_lt_type r x)), ?_⟩ + refine ⟨enum r ⟨succ (typein r x), hr.2 _ (typein_lt_type r x)⟩, ?_⟩ intro b hb rw [mem_singleton_iff.1 hb] nth_rw 1 [← enum_typein r x] - rw [@enum_lt_enum _ r] + 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 → Ordinal → Prop) { o' : Ordinal | o' < o }) - = Ordinal.lift.{u + 1} o := by + type (@Subrel Ordinal (· < ·) { o' : Ordinal | o' < o }) = Ordinal.lift.{u + 1} o := by refine Quotient.inductionOn o ?_ rintro ⟨α, r, wo⟩; apply Quotient.sound - -- Porting note: `symm; refine' [term]` → `refine' [term].symm` - constructor; refine ((RelIso.preimage Equiv.ulift r).trans (enumIso r).symm).symm + constructor; refine ((RelIso.preimage Equiv.ulift r).trans (enum r).symm).symm theorem mk_initialSeg (o : Ordinal.{u}) : #{ o' : Ordinal | o' < o } = Cardinal.lift.{u + 1} o.card := by @@ -341,7 +339,7 @@ theorem mk_initialSeg (o : Ordinal.{u}) : /-- A normal ordinal function is a strictly increasing function which is order-continuous, i.e., the image `f o` of a limit ordinal `o` is the sup of `f a` for - `a < o`. -/ + `a < o`. -/ def IsNormal (f : Ordinal → Ordinal) : Prop := (∀ o, f o < f (succ o)) ∧ ∀ o, IsLimit o → ∀ a, f o ≤ a ↔ ∀ b < o, f b ≤ a @@ -426,11 +424,11 @@ theorem add_le_of_limit {a b c : Ordinal} (h : IsLimit b) : a + b ≤ c ↔ ∀ induction b using inductionOn with | H β s => intro l - suffices ∀ x : β, Sum.Lex r s (Sum.inr x) (enum _ _ l) by + suffices ∀ x : β, Sum.Lex r s (Sum.inr x) (enum _ ⟨_, l⟩) by -- Porting note: `revert` & `intro` is required because `cases'` doesn't replace -- `enum _ _ l` in `this`. - revert this; cases' enum _ _ l with x x <;> intro this - · cases this (enum s 0 h.pos) + revert this; cases' enum _ ⟨_, l⟩ with x x <;> intro this + · cases this (enum s ⟨0, h.pos⟩) · exact irrefl _ (this _) intro x rw [← typein_lt_typein (Sum.Lex r s), typein_enum] @@ -452,7 +450,7 @@ theorem add_isLimit (a) {b} : IsLimit b → IsLimit (a + b) := alias IsLimit.add := add_isLimit -/-! ### Subtraction on ordinals-/ +/-! ### Subtraction on ordinals -/ /-- The set in the definition of subtraction is nonempty. -/ @@ -539,7 +537,7 @@ theorem one_add_omega : 1 + ω = ω := by 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] -/-! ### Multiplication of ordinals-/ +/-! ### Multiplication of ordinals -/ /-- The multiplication of ordinals `o₁` and `o₂` is the (well founded) lexicographic order on @@ -615,8 +613,8 @@ instance leftDistribClass : LeftDistribClass Ordinal.{u} := Quotient.sound ⟨⟨sumProdDistrib _ _ _, by rintro ⟨a₁ | a₁, a₂⟩ ⟨b₁ | b₁, b₂⟩ <;> - simp only [Prod.lex_def, Sum.lex_inl_inl, Sum.Lex.sep, Sum.lex_inr_inl, - Sum.lex_inr_inr, sumProdDistrib_apply_left, sumProdDistrib_apply_right] <;> + simp only [Prod.lex_def, Sum.lex_inl_inl, Sum.Lex.sep, Sum.lex_inr_inl, Sum.lex_inr_inr, + sumProdDistrib_apply_left, sumProdDistrib_apply_right, reduceCtorEq] <;> -- Porting note: `Sum.inr.inj_iff` is required. simp only [Sum.inl.inj_iff, Sum.inr.inj_iff, true_or_iff, false_and_iff, false_or_iff]⟩⟩⟩ @@ -654,8 +652,8 @@ theorem le_mul_right (a : Ordinal) {b : Ordinal} (hb : 0 < b) : a ≤ b * a := b private theorem mul_le_of_limit_aux {α β r s} [IsWellOrder α r] [IsWellOrder β s] {c} (h : IsLimit (type s)) (H : ∀ b' < type s, type r * b' ≤ c) (l : c < type r * type s) : False := by - suffices ∀ a b, Prod.Lex s r (b, a) (enum _ _ l) by - cases' enum _ _ l with b a + suffices ∀ a b, Prod.Lex s r (b, a) (enum _ ⟨_, l⟩) by + cases' enum _ ⟨_, l⟩ with b a exact irrefl _ (this _ _) intro a b rw [← typein_lt_typein (Prod.Lex s r), typein_enum] @@ -757,7 +755,7 @@ theorem div_nonempty {a b : Ordinal} (h : b ≠ 0) : { o | a < b * succ o }.None /-- `a / b` is the unique ordinal `o` satisfying `a = b * o + o'` with `o' < b`. -/ instance div : Div Ordinal := - ⟨fun a b => if _h : b = 0 then 0 else sInf { o | a < b * succ o }⟩ + ⟨fun a b => if b = 0 then 0 else sInf { o | a < b * succ o }⟩ @[simp] theorem div_zero (a : Ordinal) : a / 0 = 0 := @@ -824,6 +822,26 @@ theorem div_eq_zero_of_lt {a b : Ordinal} (h : a < b) : a / b = 0 := by theorem mul_div_cancel (a) {b : Ordinal} (b0 : b ≠ 0) : b * a / b = a := by simpa only [add_zero, zero_div] using mul_add_div a b0 0 +theorem mul_add_div_mul {a c : Ordinal} (hc : c < a) (b d : Ordinal) : + (a * b + c) / (a * d) = b / d := by + have ha : a ≠ 0 := ((Ordinal.zero_le c).trans_lt hc).ne' + obtain rfl | hd := eq_or_ne d 0 + · rw [mul_zero, div_zero, div_zero] + · have H := mul_ne_zero ha hd + apply le_antisymm + · rw [← lt_succ_iff, div_lt H, mul_assoc] + · apply (add_lt_add_left hc _).trans_le + rw [← mul_succ] + apply mul_le_mul_left' + rw [succ_le_iff] + exact lt_mul_succ_div b hd + · rw [le_div H, mul_assoc] + exact (mul_le_mul_left' (mul_div_le b d) a).trans (le_add_right _ c) + +theorem mul_div_mul_cancel {a : Ordinal} (ha : a ≠ 0) (b c) : a * b / (a * c) = b / c := by + convert mul_add_div_mul (Ordinal.pos_iff_ne_zero.2 ha) b c using 1 + rw [add_zero] + @[simp] theorem div_one (a : Ordinal) : a / 1 = a := by simpa only [one_mul] using mul_div_cancel a Ordinal.one_ne_zero @@ -936,6 +954,18 @@ theorem mul_add_mod_self (x y z : Ordinal) : (x * y + z) % x = z % x := by theorem mul_mod (x y : Ordinal) : x * y % x = 0 := by simpa using mul_add_mod_self x y 0 +theorem mul_add_mod_mul {w x : Ordinal} (hw : w < x) (y z : Ordinal) : + (x * y + w) % (x * z) = x * (y % z) + w := by + rw [mod_def, mul_add_div_mul hw] + apply sub_eq_of_add_eq + rw [← add_assoc, mul_assoc, ← mul_add, div_add_mod] + +theorem mul_mod_mul (x y z : Ordinal) : (x * y) % (x * z) = x * (y % z) := by + obtain rfl | hx := Ordinal.eq_zero_or_pos x + · simp + · convert mul_add_mod_mul hx y z using 1 <;> + rw [add_zero] + theorem mod_mod_of_dvd (a : Ordinal) {b c : Ordinal} (h : c ∣ b) : a % b % c = a % c := by nth_rw 2 [← div_add_mod a b] rcases h with ⟨d, rfl⟩ @@ -958,7 +988,7 @@ claim on the other. -/ /-- Converts a family indexed by a `Type u` to one indexed by an `Ordinal.{u}` using a specified well-ordering. -/ def bfamilyOfFamily' {ι : Type u} (r : ι → ι → Prop) [IsWellOrder ι r] (f : ι → α) : - ∀ a < type r, α := fun a ha => f (enum r a ha) + ∀ a < type r, α := fun a ha => f (enum r ⟨a, ha⟩) /-- Converts a family indexed by a `Type u` to one indexed by an `Ordinal.{u}` using a well-ordering given by the axiom of choice. -/ @@ -976,7 +1006,7 @@ def familyOfBFamily' {ι : Type u} (r : ι → ι → Prop) [IsWellOrder ι r] { /-- Converts a family indexed by an `Ordinal.{u}` to one indexed by a `Type u` using a well-ordering given by the axiom of choice. -/ -def familyOfBFamily (o : Ordinal) (f : ∀ a < o, α) : o.out.α → α := +def familyOfBFamily (o : Ordinal) (f : ∀ a < o, α) : o.toType → α := familyOfBFamily' (· < ·) (type_lt o) f @[simp] @@ -992,17 +1022,12 @@ theorem bfamilyOfFamily_typein {ι} (f : ι → α) (i) : @[simp, nolint simpNF] -- Porting note (#10959): simp cannot prove this theorem familyOfBFamily'_enum {ι : Type u} (r : ι → ι → Prop) [IsWellOrder ι r] {o} (ho : type r = o) (f : ∀ a < o, α) (i hi) : - familyOfBFamily' r ho f (enum r i (by rwa [ho])) = f i hi := by + familyOfBFamily' r ho f (enum r ⟨i, by rwa [ho]⟩) = f i hi := by simp only [familyOfBFamily', typein_enum] @[simp, nolint simpNF] -- Porting note (#10959): simp cannot prove this theorem familyOfBFamily_enum (o : Ordinal) (f : ∀ a < o, α) (i hi) : - familyOfBFamily o f - (enum (· < ·) i - (by - convert hi - exact type_lt _)) = - f i hi := + familyOfBFamily o f (enum (α := o.toType) (· < ·) ⟨i, hi.trans_eq (type_lt _).symm⟩) = f i hi := familyOfBFamily'_enum _ (type_lt o) f _ _ /-- The range of a family indexed by ordinals. -/ @@ -1044,7 +1069,7 @@ theorem brange_bfamilyOfFamily {ι : Type u} (f : ι → α) : brange _ (bfamily @[simp] theorem brange_const {o : Ordinal} (ho : o ≠ 0) {c : α} : (brange o fun _ _ => c) = {c} := by rw [← range_familyOfBFamily] - exact @Set.range_const _ o.out.α (out_nonempty_iff_ne_zero.2 ho) c + exact @Set.range_const _ o.toType (toType_nonempty_iff_ne_zero.2 ho) c theorem comp_bfamilyOfFamily' {ι : Type u} (r : ι → ι → Prop) [IsWellOrder ι r] (f : ι → α) (g : α → β) : (fun i hi => g (bfamilyOfFamily' r f i hi)) = bfamilyOfFamily' r (g ∘ f) := @@ -1169,13 +1194,13 @@ theorem le_sup_shrink_equiv {s : Set Ordinal.{u}} (hs : Small.{u} s) (a) (ha : a rw [symm_apply_apply] instance small_Iio (o : Ordinal.{u}) : Small.{u} (Set.Iio o) := - let f : o.out.α → Set.Iio o := - fun x => ⟨typein ((· < ·) : o.out.α → o.out.α → Prop) x, typein_lt_self x⟩ + let f : o.toType → Set.Iio o := + fun x => ⟨typein (α := o.toType) (· < ·) x, typein_lt_self x⟩ let hf : Surjective f := fun b => - ⟨enum (· < ·) b.val - (by + ⟨enum (α := o.toType) (· < ·) ⟨b.val, + by rw [type_lt] - exact b.prop), + exact b.prop⟩, Subtype.ext (typein_enum _ _)⟩ small_of_surjective hf @@ -1337,7 +1362,7 @@ theorem bsup_const {o : Ordinal.{u}} (ho : o ≠ 0) (a : Ordinal.{max u v}) : @[simp] theorem bsup_one (f : ∀ a < (1 : Ordinal), Ordinal) : bsup 1 f = f 0 zero_lt_one := by - simp_rw [← sup_eq_bsup, sup_unique, familyOfBFamily, familyOfBFamily', typein_one_out] + simp_rw [← sup_eq_bsup, sup_unique, familyOfBFamily, familyOfBFamily', typein_one_toType] theorem bsup_le_of_brange_subset {o o'} {f : ∀ a < o, Ordinal} {g : ∀ a < o', Ordinal} (h : brange o f ⊆ brange o' g) : bsup.{u, max v w} o f ≤ bsup.{v, max u w} o' g := @@ -1468,25 +1493,25 @@ theorem nonempty_compl_range {ι : Type u} (f : ι → Ordinal.{max u v}) : (Set ⟨_, lsub_not_mem_range.{_, v} f⟩ @[simp] -theorem lsub_typein (o : Ordinal) : lsub.{u, u} (typein ((· < ·) : o.out.α → o.out.α → Prop)) = o := +theorem lsub_typein (o : Ordinal) : lsub.{u, u} (typein (α := o.toType) (· < ·)) = o := (lsub_le.{u, u} typein_lt_self).antisymm (by by_contra! h -- Porting note: `nth_rw` → `conv_rhs` & `rw` conv_rhs at h => rw [← type_lt o] - simpa [typein_enum] using lt_lsub.{u, u} (typein (· < ·)) (enum (· < ·) _ h)) + simpa [typein_enum] using lt_lsub.{u, u} (typein (· < ·)) (enum (· < ·) ⟨_, h⟩)) theorem sup_typein_limit {o : Ordinal} (ho : ∀ a, a < o → succ a < o) : - sup.{u, u} (typein ((· < ·) : o.out.α → o.out.α → Prop)) = o := by + sup.{u, u} (typein ((· < ·) : o.toType → o.toType → Prop)) = o := by -- Porting note: `rwa` → `rw` & `assumption` rw [(sup_eq_lsub_iff_succ.{u, u} (typein (· < ·))).2] <;> rw [lsub_typein o]; assumption @[simp] theorem sup_typein_succ {o : Ordinal} : - sup.{u, u} (typein ((· < ·) : (succ o).out.α → (succ o).out.α → Prop)) = o := by + sup.{u, u} (typein ((· < ·) : (succ o).toType → (succ o).toType → Prop)) = o := by cases' sup_eq_lsub_or_sup_succ_eq_lsub.{u, u} - (typein ((· < ·) : (succ o).out.α → (succ o).out.α → Prop)) with + (typein ((· < ·) : (succ o).toType → (succ o).toType → Prop)) with h h · rw [sup_eq_lsub_iff_succ] at h simp only [lsub_typein] at h @@ -1610,7 +1635,7 @@ theorem blsub_succ_of_mono {o : Ordinal.{u}} {f : ∀ a < succ o, Ordinal.{max u @[simp] theorem blsub_eq_zero_iff {o} {f : ∀ a < o, Ordinal} : blsub o f = 0 ↔ o = 0 := by rw [← lsub_eq_blsub, lsub_eq_zero_iff] - exact out_empty_iff_eq_zero + exact toType_empty_iff_eq_zero -- Porting note: `rwa` → `rw` @[simp] @@ -1624,7 +1649,7 @@ theorem blsub_type {α : Type u} (r : α → α → Prop) [IsWellOrder α r] blsub.{_, v} (type r) f = lsub.{_, v} fun a => f (typein r a) (typein_lt_type _ _) := eq_of_forall_ge_iff fun o => by rw [blsub_le_iff, lsub_le_iff] - exact ⟨fun H b => H _ _, fun H i h => by simpa only [typein_enum] using H (enum r i h)⟩ + exact ⟨fun H b => H _ _, fun H i h => by simpa only [typein_enum] using H (enum r ⟨i, h⟩)⟩ theorem blsub_const {o : Ordinal} (ho : o ≠ 0) (a : Ordinal) : (blsub.{u, v} o fun _ _ => a) = succ a := @@ -1702,24 +1727,26 @@ theorem IsNormal.eq_iff_zero_and_succ {f g : Ordinal.{u} → Ordinal.{u}} (hf : (hg : IsNormal g) : f = g ↔ f 0 = g 0 ∧ ∀ a, f a = g a → f (succ a) = g (succ a) := ⟨fun h => by simp [h], fun ⟨h₁, h₂⟩ => funext fun a => by - induction' a using limitRecOn with _ _ _ ho H - any_goals solve_by_elim - rw [← IsNormal.bsup_eq.{u, u} hf ho, ← IsNormal.bsup_eq.{u, u} hg ho] - congr - ext b hb - exact H b hb⟩ + induction a using limitRecOn with + | H₁ => solve_by_elim + | H₂ => solve_by_elim + | H₃ _ ho H => + rw [← IsNormal.bsup_eq.{u, u} hf ho, ← IsNormal.bsup_eq.{u, u} hg ho] + congr + ext b hb + exact H b hb⟩ /-- A two-argument version of `Ordinal.blsub`. We don't develop a full API for this, since it's only used in a handful of existence results. -/ def blsub₂ (o₁ o₂ : Ordinal) (op : {a : Ordinal} → (a < o₁) → {b : Ordinal} → (b < o₂) → Ordinal) : Ordinal := - lsub (fun x : o₁.out.α × o₂.out.α => op (typein_lt_self x.1) (typein_lt_self x.2)) + lsub (fun x : o₁.toType × o₂.toType => op (typein_lt_self x.1) (typein_lt_self x.2)) theorem lt_blsub₂ {o₁ o₂ : Ordinal} (op : {a : Ordinal} → (a < o₁) → {b : Ordinal} → (b < o₂) → Ordinal) {a b : Ordinal} (ha : a < o₁) (hb : b < o₂) : op ha hb < blsub₂ o₁ o₂ op := by - convert lt_lsub _ (Prod.mk (enum (· < ·) a (by rwa [type_lt])) - (enum (· < ·) b (by rwa [type_lt]))) + convert lt_lsub _ (Prod.mk (enum (· < ·) ⟨a, by rwa [type_lt]⟩) + (enum (· < ·) ⟨b, by rwa [type_lt]⟩)) simp only [typein_enum] /-! ### Minimum excluded ordinals -/ @@ -1762,15 +1789,15 @@ theorem mex_lt_ord_succ_mk {ι : Type u} (f : ι → Ordinal.{u}) : by_contra! h apply (lt_succ #ι).not_le have H := fun a => exists_of_lt_mex ((typein_lt_self a).trans_le h) - let g : (succ #ι).ord.out.α → ι := fun a => Classical.choose (H a) + let g : (succ #ι).ord.toType → ι := fun a => Classical.choose (H a) have hg : Injective g := fun a b h' => by have Hf : ∀ x, f (g x) = - typein ((· < ·) : (succ #ι).ord.out.α → (succ #ι).ord.out.α → Prop) x := + typein ((· < ·) : (succ #ι).ord.toType → (succ #ι).ord.toType → Prop) x := fun a => Classical.choose_spec (H a) apply_fun f at h' rwa [Hf, Hf, typein_inj] at h' convert Cardinal.mk_le_of_injective hg - rw [Cardinal.mk_ord_out (succ #ι)] + rw [Cardinal.mk_ord_toType (succ #ι)] /-- The minimum excluded ordinal of a family of ordinals indexed by the set of ordinals less than some `o : Ordinal.{u}`. This is a special case of `mex` over the family provided by @@ -1792,7 +1819,7 @@ theorem le_bmex_of_forall {o : Ordinal} (f : ∀ a < o, Ordinal) {a : Ordinal} 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}) - ne_mex.{_, v} (familyOfBFamily o f) (enum (· < ·) i (by rwa [type_lt])) using 2 + ne_mex.{_, v} (familyOfBFamily o f) (enum (α := o.toType) (· < ·) ⟨i, by rwa [type_lt]⟩) using 2 -- Porting note: `familyOfBFamily_enum` → `typein_enum` rw [typein_enum] @@ -1816,7 +1843,7 @@ theorem bmex_monotone {o o' : Ordinal.{u}} 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_ordinal_out] + rw [← mk_toType] exact mex_lt_ord_succ_mk (familyOfBFamily o f) end Ordinal @@ -2270,3 +2297,5 @@ theorem rank_strictAnti [Preorder α] [WellFoundedGT α] : StrictAnti (rank <| @wellFounded_gt α _ _) := fun _ _ => rank_lt_of_rel wellFounded_gt end WellFounded + +set_option linter.style.longFile 2400 diff --git a/Mathlib/SetTheory/Ordinal/Basic.lean b/Mathlib/SetTheory/Ordinal/Basic.lean index 5aa1b13790de0..c638012729c42 100644 --- a/Mathlib/SetTheory/Ordinal/Basic.lean +++ b/Mathlib/SetTheory/Ordinal/Basic.lean @@ -21,7 +21,7 @@ initial segment (or, equivalently, in any way). This total order is well founded * `Ordinal.type r`: given a well-founded order `r`, this is the corresponding ordinal * `Ordinal.typein r a`: given a well-founded order `r` on a type `α`, and `a : α`, the ordinal corresponding to all elements smaller than `a`. -* `enum r o h`: given a well-order `r` on a type `α`, and an ordinal `o` strictly smaller than +* `enum r ⟨o, h⟩`: given a well-order `r` on a type `α`, and an ordinal `o` strictly smaller than the ordinal corresponding to `r` (this is the assumption `h`), returns the `o`-th element of `α`. In other words, the elements of `α` can be enumerated using ordinals up to `type r`. * `Ordinal.card o`: the cardinality of an ordinal `o`. @@ -141,13 +141,20 @@ instance Ordinal.isEquivalent : Setoid WellOrder where def Ordinal : Type (u + 1) := Quotient Ordinal.isEquivalent -instance hasWellFoundedOut (o : Ordinal) : WellFoundedRelation o.out.α := +/-- A "canonical" type order-isomorphic to the ordinal `o`, living in the same universe. This is +defined through the axiom of choice. + +Use this over `Iio o` only when it is paramount to have a `Type u` rather than a `Type (u + 1)`. -/ +def Ordinal.toType (o : Ordinal.{u}) : Type u := + o.out.α + +instance hasWellFounded_toType (o : Ordinal) : WellFoundedRelation o.toType := ⟨o.out.r, o.out.wo.wf⟩ -instance linearOrderOut (o : Ordinal) : LinearOrder o.out.α := - IsWellOrder.linearOrder o.out.r +instance linearOrder_toType (o : Ordinal) : LinearOrder o.toType := + @IsWellOrder.linearOrder _ o.out.r o.out.wo -instance isWellOrder_out_lt (o : Ordinal) : IsWellOrder o.out.α (· < ·) := +instance isWellOrder_toType_lt (o : Ordinal) : IsWellOrder o.toType (· < ·) := o.out.wo namespace Ordinal @@ -182,8 +189,12 @@ theorem type_def (r) [wo : IsWellOrder α r] : (⟦⟨α, r, wo⟩⟧ : Ordinal) rfl @[simp] -theorem type_out (o : Ordinal) : Ordinal.type o.out.r = o := by - rw [Ordinal.type, WellOrder.eta, Quotient.out_eq] +theorem type_lt (o : Ordinal) : type (α := o.toType) (· < ·) = o := + (type_def' _).symm.trans <| Quotient.out_eq o + +@[deprecated type_lt (since := "2024-08-26")] +theorem type_out (o : Ordinal) : Ordinal.type o.out.r = o := + type_lt o theorem type_eq {α β} {r : α → α → Prop} {s : β → β → Prop} [IsWellOrder α r] [IsWellOrder β s] : type r = type s ↔ Nonempty (r ≃r s) := @@ -193,10 +204,6 @@ theorem _root_.RelIso.ordinal_type_eq {α β} {r : α → α → Prop} {s : β [IsWellOrder β s] (h : r ≃r s) : type r = type s := type_eq.2 ⟨h⟩ -@[simp] -theorem type_lt (o : Ordinal) : type ((· < ·) : o.out.α → o.out.α → Prop) = o := - (type_def' _).symm.trans <| Quotient.out_eq o - theorem type_eq_zero_of_empty (r) [IsWellOrder α r] [IsEmpty α] : type r = 0 := (RelIso.relIsoOfIsEmpty r _).ordinal_type_eq @@ -235,21 +242,29 @@ theorem type_unit : type (@EmptyRelation Unit) = 1 := rfl @[simp] -theorem out_empty_iff_eq_zero {o : Ordinal} : IsEmpty o.out.α ↔ o = 0 := by - rw [← @type_eq_zero_iff_isEmpty o.out.α (· < ·), type_lt] +theorem toType_empty_iff_eq_zero {o : Ordinal} : IsEmpty o.toType ↔ o = 0 := by + rw [← @type_eq_zero_iff_isEmpty o.toType (· < ·), type_lt] + +@[deprecated toType_empty_iff_eq_zero (since := "2024-08-26")] +alias out_empty_iff_eq_zero := toType_empty_iff_eq_zero -theorem eq_zero_of_out_empty (o : Ordinal) [h : IsEmpty o.out.α] : o = 0 := - out_empty_iff_eq_zero.1 h +@[deprecated toType_empty_iff_eq_zero (since := "2024-08-26")] +theorem eq_zero_of_out_empty (o : Ordinal) [h : IsEmpty o.toType] : o = 0 := + toType_empty_iff_eq_zero.1 h -instance isEmpty_out_zero : IsEmpty (0 : Ordinal).out.α := - out_empty_iff_eq_zero.2 rfl +instance isEmpty_toType_zero : IsEmpty (toType 0) := + toType_empty_iff_eq_zero.2 rfl @[simp] -theorem out_nonempty_iff_ne_zero {o : Ordinal} : Nonempty o.out.α ↔ o ≠ 0 := by - rw [← @type_ne_zero_iff_nonempty o.out.α (· < ·), type_lt] +theorem toType_nonempty_iff_ne_zero {o : Ordinal} : Nonempty o.toType ↔ o ≠ 0 := by + rw [← @type_ne_zero_iff_nonempty o.toType (· < ·), type_lt] + +@[deprecated toType_nonempty_iff_ne_zero (since := "2024-08-26")] +alias out_nonempty_iff_ne_zero := toType_nonempty_iff_ne_zero -theorem ne_zero_of_out_nonempty (o : Ordinal) [h : Nonempty o.out.α] : o ≠ 0 := - out_nonempty_iff_ne_zero.1 h +@[deprecated toType_nonempty_iff_ne_zero (since := "2024-08-26")] +theorem ne_zero_of_out_nonempty (o : Ordinal) [h : Nonempty o.toType] : o ≠ 0 := + toType_nonempty_iff_ne_zero.1 h protected theorem one_ne_zero : (1 : Ordinal) ≠ 0 := type_ne_zero_of_nonempty _ @@ -363,27 +378,32 @@ instance zeroLEOneClass : ZeroLEOneClass Ordinal := instance NeZero.one : NeZero (1 : Ordinal) := ⟨Ordinal.one_ne_zero⟩ -/-- Given two ordinals `α ≤ β`, then `initialSegOut α β` is the initial segment embedding -of `α` to `β`, as map from a model type for `α` to a model type for `β`. -/ -def initialSegOut {α β : Ordinal} (h : α ≤ β) : - InitialSeg ((· < ·) : α.out.α → α.out.α → Prop) ((· < ·) : β.out.α → β.out.α → Prop) := by +/-- 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 -/-- Given two ordinals `α < β`, then `principalSegOut α β` is the principal segment embedding -of `α` to `β`, as map from a model type for `α` to a model type for `β`. -/ -def principalSegOut {α β : Ordinal} (h : α < β) : - PrincipalSeg ((· < ·) : α.out.α → α.out.α → Prop) ((· < ·) : β.out.α → β.out.α → Prop) := by +@[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 +@[deprecated principalSegToType (since := "2024-08-26")] +noncomputable alias principalSegOut := principalSegToType + theorem typein_lt_type (r : α → α → Prop) [IsWellOrder α r] (a : α) : typein r a < type r := ⟨PrincipalSeg.ofElement _ _⟩ -theorem typein_lt_self {o : Ordinal} (i : o.out.α) : - @typein _ (· < ·) (isWellOrder_out_lt _) i < o := by +theorem typein_lt_self {o : Ordinal} (i : o.toType) : typein (α := o.toType) (· < ·) i < o := by simp_rw [← type_lt o] apply typein_lt_type @@ -432,8 +452,8 @@ theorem typein_injective (r : α → α → Prop) [IsWellOrder α r] : Injective theorem typein_inj (r : α → α → Prop) [IsWellOrder α r] {a b} : typein r a = typein r b ↔ a = b := (typein_injective r).eq_iff -/-- Principal segment version of the `typein` function, embedding a well order into - ordinals as a principal segment. -/ +/-- Principal segment version of the `typein` function, embedding a well order into ordinals as a +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, @@ -446,63 +466,49 @@ theorem typein.principalSeg_coe (r : α → α → Prop) [IsWellOrder α r] : /-! ### Enumerating elements in a well-order with ordinals. -/ +/-- A well order `r` is order-isomorphic to the set of ordinals smaller than `type r`. +`enum r ⟨o, h⟩` is the `o`-th element of `α` ordered by `r`. -/-- `enum r o h` is the `o`-th element of `α` ordered by `r`. - That is, `enum` maps an initial segment of the ordinals, those - less than the order type of `r`, to the elements of `α`. -/ -def enum (r : α → α → Prop) [IsWellOrder α r] (o) (h : o < type r) : α := - (typein.principalSeg r).subrelIso ⟨o, h⟩ +That is, `enum` maps an initial segment of the ordinals, those less than the order type of `r`, to +the elements of `α`. -/ +-- The explicit typing is required in order for `simp` to work properly. +@[simps! symm_apply_coe] +def enum (r : α → α → Prop) [IsWellOrder α r] : + @RelIso (Subtype fun o => o < type r) α (Subrel (· < · ) _) r := + (typein.principalSeg r).subrelIso @[simp] theorem typein_enum (r : α → α → Prop) [IsWellOrder α r] {o} (h : o < type r) : - typein r (enum r o h) = o := + typein r (enum r ⟨o, h⟩) = o := (typein.principalSeg r).apply_subrelIso _ theorem enum_type {α β} {r : α → α → Prop} {s : β → β → Prop} [IsWellOrder α r] [IsWellOrder β s] - (f : s ≺i r) {h : type s < type r} : enum r (type s) h = f.top := + (f : s ≺i r) {h : type s < type r} : enum r ⟨type s, h⟩ = f.top := (typein.principalSeg r).injective <| (typein_enum _ _).trans (typein_top _).symm @[simp] theorem enum_typein (r : α → α → Prop) [IsWellOrder α r] (a : α) : - enum r (typein r a) (typein_lt_type r a) = a := + enum r ⟨typein r a, typein_lt_type r a⟩ = a := enum_type (PrincipalSeg.ofElement r a) -theorem enum_lt_enum {r : α → α → Prop} [IsWellOrder α r] {o₁ o₂ : Ordinal} (h₁ : o₁ < type r) - (h₂ : o₂ < type r) : r (enum r o₁ h₁) (enum r o₂ h₂) ↔ o₁ < o₂ := by - rw [← typein_lt_typein r, typein_enum, typein_enum] +theorem enum_lt_enum {r : α → α → Prop} [IsWellOrder α r] {o₁ o₂ : {o // o < type r}} : + r (enum r o₁) (enum r o₂) ↔ o₁ < o₂ := by + rw [← typein_lt_typein r, typein_enum, typein_enum, Subtype.coe_lt_coe] theorem relIso_enum' {α β : Type u} {r : α → α → Prop} {s : β → β → Prop} [IsWellOrder α r] [IsWellOrder β s] (f : r ≃r s) (o : Ordinal) : - ∀ (hr : o < type r) (hs : o < type s), f (enum r o hr) = enum s o hs := by + ∀ (hr : o < type r) (hs : o < type s), f (enum r ⟨o, hr⟩) = enum s ⟨o, hs⟩ := by refine inductionOn o ?_; rintro γ t wo ⟨g⟩ ⟨h⟩ rw [enum_type g, enum_type (PrincipalSeg.ltEquiv g f)]; rfl theorem relIso_enum {α β : Type u} {r : α → α → Prop} {s : β → β → Prop} [IsWellOrder α r] [IsWellOrder β s] (f : r ≃r s) (o : Ordinal) (hr : o < type r) : - f (enum r o hr) = - enum s o - (by - convert hr using 1 - apply Quotient.sound - exact ⟨f.symm⟩) := + f (enum r ⟨o, hr⟩) = enum s ⟨o, hr.trans_eq (Quotient.sound ⟨f⟩)⟩ := relIso_enum' _ _ _ _ theorem lt_wf : @WellFounded Ordinal (· < ·) := -/- - wellFounded_iff_wellFounded_subrel.mpr (·.induction_on fun ⟨_, r, wo⟩ ↦ - RelHomClass.wellFounded (typein.principalSeg r).subrelIso wo.wf) --/ - ⟨fun a => - inductionOn a fun α r wo => - suffices ∀ a, Acc (· < ·) (typein r a) from - ⟨_, fun o h => - let ⟨a, e⟩ := typein_surj r h - e ▸ this a⟩ - fun a => - Acc.recOn (wo.wf.apply a) fun x _ IH => - ⟨_, fun o h => by - rcases typein_surj r (lt_trans h (typein_lt_type r _)) with ⟨b, rfl⟩ - exact IH _ ((typein_lt_typein r).1 h)⟩⟩ + wellFounded_iff_wellFounded_subrel.mpr (·.induction_on fun ⟨_, _, wo⟩ ↦ + RelHomClass.wellFounded (enum _) wo.wf) instance wellFoundedRelation : WellFoundedRelation Ordinal := ⟨(· < ·), lt_wf⟩ @@ -866,7 +872,7 @@ instance wellFoundedLT : WellFoundedLT Ordinal := instance isWellOrder : IsWellOrder Ordinal (· < ·) where instance : ConditionallyCompleteLinearOrderBot Ordinal := - IsWellOrder.conditionallyCompleteLinearOrderBot _ + WellFoundedLT.conditionallyCompleteLinearOrderBot _ theorem max_zero_left : ∀ a : Ordinal, max 0 a = a := max_bot_left @@ -964,102 +970,100 @@ instance uniqueIioOne : Unique (Iio (1 : Ordinal)) where default := ⟨0, by simp⟩ uniq a := Subtype.ext <| lt_one_iff_zero.1 a.2 -instance uniqueOutOne : Unique (1 : Ordinal).out.α where - default := enum (· < ·) 0 (by simp) +instance uniqueToTypeOne : Unique (toType 1) where + default := enum (α := toType 1) (· < ·) ⟨0, by simp⟩ uniq a := by unfold default - rw [← @enum_typein _ (· < ·) (isWellOrder_out_lt _) a] + rw [← enum_typein (α := toType 1) (· < ·) a] congr rw [← lt_one_iff_zero] apply typein_lt_self -theorem one_out_eq (x : (1 : Ordinal).out.α) : x = enum (· < ·) 0 (by simp) := +theorem one_toType_eq (x : toType 1) : x = enum (· < ·) ⟨0, by simp⟩ := Unique.eq_default x +@[deprecated one_toType_eq (since := "2024-08-26")] +alias one_out_eq := one_toType_eq + /-! ### Extra properties of typein and enum -/ +-- TODO: move this section with the other properties of `typein` and `enum`. +-- TODO: use `enumIsoToType` for lemmas on `toType` rather than `enum` and `typein`. @[simp] -theorem typein_one_out (x : (1 : Ordinal).out.α) : - @typein _ (· < ·) (isWellOrder_out_lt _) x = 0 := by - rw [one_out_eq x, typein_enum] +theorem typein_one_toType (x : toType 1) : typein (α := toType 1) (· < ·) x = 0 := by + rw [one_toType_eq x, typein_enum] + +@[deprecated typein_one_toType (since := "2024-08-26")] +alias typein_one_out := typein_one_toType @[simp] -theorem typein_le_typein (r : α → α → Prop) [IsWellOrder α r] {x x' : α} : - typein r x ≤ typein r x' ↔ ¬r x' x := by rw [← not_lt, typein_lt_typein] +theorem typein_le_typein (r : α → α → Prop) [IsWellOrder α r] {x y : α} : + typein r x ≤ typein r y ↔ ¬r y x := by rw [← not_lt, typein_lt_typein] -- @[simp] -- Porting note (#10618): simp can prove this -theorem typein_le_typein' (o : Ordinal) {x x' : o.out.α} : - @typein _ (· < ·) (isWellOrder_out_lt _) x ≤ @typein _ (· < ·) (isWellOrder_out_lt _) x' - ↔ x ≤ x' := by +theorem typein_le_typein' (o : Ordinal) {x y : o.toType} : + typein (α := o.toType) (· < ·) x ≤ typein (α := o.toType) (· < ·) y ↔ x ≤ y := by rw [typein_le_typein] exact not_lt --- Porting note: added nolint, simpnf linter falsely claims it never applies -@[simp, nolint simpNF] -theorem enum_le_enum (r : α → α → Prop) [IsWellOrder α r] {o o' : Ordinal} (ho : o < type r) - (ho' : o' < type r) : ¬r (enum r o' ho') (enum r o ho) ↔ o ≤ o' := by - rw [← @not_lt _ _ o' o, enum_lt_enum ho'] +theorem enum_le_enum (r : α → α → Prop) [IsWellOrder α r] {o₁ o₂ : {o // o < type r}} : + ¬r (enum r o₁) (enum r o₂) ↔ o₂ ≤ o₁ := by + rw [← @not_lt _ _ o₁ o₂, enum_lt_enum (r := r)] @[simp] -theorem enum_le_enum' (a : Ordinal) {o o' : Ordinal} (ho : o < type (· < ·)) - (ho' : o' < type (· < ·)) : enum (· < ·) o ho ≤ @enum a.out.α (· < ·) _ o' ho' ↔ o ≤ o' := by - rw [← @enum_le_enum _ (· < ·) (isWellOrder_out_lt _), ← not_lt] +theorem enum_le_enum' (a : Ordinal) {o₁ o₂ : {o // o < type (· < ·)}} : + enum (· < ·) o₁ ≤ enum (α := a.toType) (· < ·) o₂ ↔ o₁ ≤ o₂ := by + rw [← enum_le_enum (α := a.toType) (· < ·), ← not_lt] theorem enum_zero_le {r : α → α → Prop} [IsWellOrder α r] (h0 : 0 < type r) (a : α) : - ¬r a (enum r 0 h0) := by + ¬r a (enum r ⟨0, h0⟩) := by rw [← enum_typein r a, enum_le_enum r] apply Ordinal.zero_le -theorem enum_zero_le' {o : Ordinal} (h0 : 0 < o) (a : o.out.α) : - @enum o.out.α (· < ·) _ 0 (by rwa [type_lt]) ≤ a := by +theorem enum_zero_le' {o : Ordinal} (h0 : 0 < o) (a : o.toType) : + enum (α := o.toType) (· < ·) ⟨0, by rwa [type_lt]⟩ ≤ a := by rw [← not_lt] apply enum_zero_le -theorem le_enum_succ {o : Ordinal} (a : (succ o).out.α) : - a ≤ - @enum (succ o).out.α (· < ·) _ o - (by - rw [type_lt] - exact lt_succ o) := by - rw [← @enum_typein _ (· < ·) (isWellOrder_out_lt _) a, enum_le_enum', ← lt_succ_iff] +theorem le_enum_succ {o : Ordinal} (a : (succ o).toType) : + a ≤ enum (α := (succ o).toType) (· < ·) ⟨o, (by rw [type_lt]; exact lt_succ o)⟩ := by + rw [← enum_typein (α := (succ o).toType) (· < ·) a, enum_le_enum', Subtype.mk_le_mk, + ← lt_succ_iff] apply typein_lt_self -@[simp] -theorem enum_inj {r : α → α → Prop} [IsWellOrder α r] {o₁ o₂ : Ordinal} (h₁ : o₁ < type r) - (h₂ : o₂ < type r) : enum r o₁ h₁ = enum r o₂ h₂ ↔ o₁ = o₂ := - (typein.principalSeg r).subrelIso.injective.eq_iff.trans Subtype.mk_eq_mk - --- TODO: Can we remove this definition and just use `(typein.principalSeg r).subrelIso` directly? -/-- A well order `r` is order isomorphic to the set of ordinals smaller than `type r`. -/ -@[simps] -def enumIso (r : α → α → Prop) [IsWellOrder α r] : Subrel (· < ·) (· < type r) ≃r r := - { (typein.principalSeg r).subrelIso with - toFun := fun x ↦ enum r x.1 x.2 - invFun := fun x ↦ ⟨typein r x, typein_lt_type r x⟩ } +theorem enum_inj {r : α → α → Prop} [IsWellOrder α r] {o₁ o₂ : {o // o < type r}} : + enum r o₁ = enum r o₂ ↔ o₁ = o₂ := by + rw [EmbeddingLike.apply_eq_iff_eq, Subtype.mk.injEq] -/-- The order isomorphism between ordinals less than `o` and `o.out.α`. -/ +/-- The order isomorphism between ordinals less than `o` and `o.toType`. -/ @[simps!] -noncomputable def enumIsoOut (o : Ordinal) : Set.Iio o ≃o o.out.α where +noncomputable def enumIsoToType (o : Ordinal) : Set.Iio o ≃o o.toType where toFun x := - enum (· < ·) x.1 <| by + enum (α := o.toType) (· < ·) ⟨x.1, by rw [type_lt] - exact x.2 - invFun x := ⟨@typein _ (· < ·) (isWellOrder_out_lt _) x, typein_lt_self x⟩ + exact x.2⟩ + invFun x := ⟨typein (α := o.toType) (· < ·) x, typein_lt_self x⟩ left_inv := fun ⟨o', h⟩ => Subtype.ext_val (typein_enum _ _) right_inv h := enum_typein _ _ map_rel_iff' := by rintro ⟨a, _⟩ ⟨b, _⟩ apply enum_le_enum' -/-- `o.out.α` is an `OrderBot` whenever `0 < o`. -/ -def outOrderBotOfPos {o : Ordinal} (ho : 0 < o) : OrderBot o.out.α where +@[deprecated (since := "2024-08-26")] +alias enumIsoOut := enumIsoToType + +/-- `o.toType` is an `OrderBot` whenever `0 < o`. -/ +def toTypeOrderBotOfPos {o : Ordinal} (ho : 0 < o) : OrderBot o.toType where bot_le := enum_zero_le' ho +@[deprecated toTypeOrderBotOfPos (since := "2024-08-26")] +noncomputable alias outOrderBotOfPos := toTypeOrderBotOfPos + theorem enum_zero_eq_bot {o : Ordinal} (ho : 0 < o) : - enum (· < ·) 0 (by rwa [type_lt]) = - haveI H := outOrderBotOfPos ho - (⊥ : (Quotient.out o).α) := + enum (α := o.toType) (· < ·) ⟨0, by rwa [type_lt]⟩ = + have H := toTypeOrderBotOfPos ho + (⊥ : o.toType) := rfl /-! ### Universal ordinal -/ @@ -1099,7 +1103,7 @@ def lift.principalSeg : @PrincipalSeg Ordinal.{u} Ordinal.{max (u + 1) v} (· < 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⟩) + · exact fun b => enum r ⟨f b, (hf _).2 ⟨_, rfl⟩⟩ · refine fun a b h => (typein_lt_typein r).1 ?_ rw [typein_enum, typein_enum] exact f.map_rel_iff.2 h @@ -1137,8 +1141,11 @@ namespace Cardinal open Ordinal @[simp] -theorem mk_ordinal_out (o : Ordinal) : #o.out.α = o.card := - (Ordinal.card_type (· < ·)).symm.trans <| by rw [Ordinal.type_lt] +theorem mk_toType (o : Ordinal) : #o.toType = o.card := + (Ordinal.card_type _).symm.trans <| by rw [Ordinal.type_lt] + +@[deprecated mk_toType (since := "2024-08-26")] +alias mk_ordinal_out := mk_toType /-- The ordinal corresponding to a cardinal `c` is the least ordinal whose cardinal is `c`. For the order-embedding version, see `ord.order_embedding`. -/ @@ -1259,19 +1266,29 @@ theorem lift_ord (c) : Ordinal.lift.{u,v} (ord c) = ord (lift.{u,v} c) := by rwa [lt_ord, ← lift_card, lift_lt, ← lt_ord, ← Ordinal.lift_lt] · rw [ord_le, ← lift_card, card_ord] -theorem mk_ord_out (c : Cardinal) : #c.ord.out.α = c := by simp +theorem mk_ord_toType (c : Cardinal) : #c.ord.toType = c := by simp + +@[deprecated mk_ord_toType (since := "2024-08-26")] +alias mk_ord_out := mk_ord_toType theorem card_typein_lt (r : α → α → Prop) [IsWellOrder α r] (x : α) (h : ord #α = type r) : card (typein r x) < #α := by rw [← lt_ord, h] apply typein_lt_type -theorem card_typein_out_lt (c : Cardinal) (x : c.ord.out.α) : - card (@typein _ (· < ·) (isWellOrder_out_lt _) x) < c := by +theorem card_typein_toType_lt (c : Cardinal) (x : c.ord.toType) : + card (typein (α := c.ord.toType) (· < ·) x) < c := by rw [← lt_ord] apply typein_lt_self -theorem mk_Iio_ord_out_α {c : Cardinal} (i : c.ord.out.α) : #(Iio i) < c := card_typein_out_lt c i +@[deprecated card_typein_toType_lt (since := "2024-08-26")] +alias card_typein_out_lt := card_typein_toType_lt + +theorem mk_Iio_ord_toType {c : Cardinal} (i : c.ord.toType) : #(Iio i) < c := + card_typein_toType_lt c i + +@[deprecated (since := "2024-08-26")] +alias mk_Iio_ord_out_α := mk_Iio_ord_toType theorem ord_injective : Injective ord := by intro c c' h diff --git a/Mathlib/SetTheory/Ordinal/Exponential.lean b/Mathlib/SetTheory/Ordinal/Exponential.lean index 7c5c895e19db7..6753d1d6c71f1 100644 --- a/Mathlib/SetTheory/Ordinal/Exponential.lean +++ b/Mathlib/SetTheory/Ordinal/Exponential.lean @@ -25,9 +25,6 @@ namespace Ordinal instance pow : Pow Ordinal Ordinal := ⟨fun a b => if a = 0 then 1 - b else limitRecOn b 1 (fun _ IH => IH * a) fun b _ => bsup.{u, u} b⟩ --- Porting note: Ambiguous notations. --- local infixr:0 "^" => @Pow.pow Ordinal Ordinal Ordinal.instPowOrdinalOrdinal - theorem opow_def (a b : Ordinal) : a ^ b = if a = 0 then 1 - b else limitRecOn b 1 (fun _ IH => IH * a) fun b _ => bsup.{u, u} b := rfl @@ -89,6 +86,12 @@ 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, norm_cast] +theorem opow_natCast (a : Ordinal) (n : ℕ) : a ^ (n : Ordinal) = a ^ n := by + induction n with + | zero => rw [Nat.cast_zero, opow_zero, pow_zero] + | succ n IH => rw [Nat.cast_succ, add_one_eq_succ, opow_succ, pow_succ, IH] + theorem opow_isNormal {a : Ordinal} (h : 1 < a) : IsNormal (a ^ ·) := have a0 : 0 < a := zero_lt_one.trans h ⟨fun b => by simpa only [mul_one, opow_succ] using (mul_lt_mul_iff_left (opow_pos b a0)).2 h, @@ -400,8 +403,9 @@ theorem natCast_opow (m : ℕ) : ∀ n : ℕ, ↑(m ^ n : ℕ) = (m : Ordinal) ^ @[deprecated (since := "2024-04-17")] alias nat_cast_opow := natCast_opow -theorem sup_opow_nat {o : Ordinal} (ho : 0 < o) : (sup fun n : ℕ => o ^ (n : Ordinal)) = o ^ ω := by - rcases lt_or_eq_of_le (one_le_iff_pos.2 ho) with (ho₁ | rfl) +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 · rw [one_opow] refine le_antisymm (sup_le fun n => by rw [one_opow]) ?_ diff --git a/Mathlib/SetTheory/Ordinal/FixedPoint.lean b/Mathlib/SetTheory/Ordinal/FixedPoint.lean index 9c3cc3e2c26af..c7a4b2b31ea32 100644 --- a/Mathlib/SetTheory/Ordinal/FixedPoint.lean +++ b/Mathlib/SetTheory/Ordinal/FixedPoint.lean @@ -263,7 +263,7 @@ theorem apply_lt_nfpBFamily (H : ∀ i hi, IsNormal (f i hi)) {a b} (hb : b < nf theorem apply_lt_nfpBFamily_iff (ho : o ≠ 0) (H : ∀ i hi, IsNormal (f i hi)) {a b} : (∀ i hi, f i hi b < nfpBFamily.{u, v} o f a) ↔ b < nfpBFamily.{u, v} o f a := ⟨fun h => by - haveI := out_nonempty_iff_ne_zero.2 ho + haveI := toType_nonempty_iff_ne_zero.2 ho refine (apply_lt_nfpFamily_iff.{u, v} ?_).1 fun _ => h _ _ exact fun _ => H _ _, apply_lt_nfpBFamily H⟩ @@ -542,13 +542,12 @@ theorem deriv_add_eq_mul_omega_add (a b : Ordinal.{u}) : deriv (a + ·) b = a * @[simp] theorem nfp_mul_one {a : Ordinal} (ha : 0 < a) : nfp (a * ·) 1 = (a^omega) := by - rw [← sup_iterate_eq_nfp, ← sup_opow_nat] - · congr - funext n - induction' n with n hn - · rw [Nat.cast_zero, opow_zero, iterate_zero_apply] - rw [iterate_succ_apply', Nat.add_comm, Nat.cast_add, Nat.cast_one, opow_add, opow_one, hn] - · exact ha + rw [← sup_iterate_eq_nfp, ← sup_opow_nat ha] + congr + funext n + induction' n with n hn + · rw [pow_zero, iterate_zero_apply] + · rw [iterate_succ_apply', Nat.add_comm, pow_add, pow_one, hn] @[simp] theorem nfp_mul_zero (a : Ordinal) : nfp (a * ·) 0 = 0 := by diff --git a/Mathlib/SetTheory/Ordinal/FixedPointApproximants.lean b/Mathlib/SetTheory/Ordinal/FixedPointApproximants.lean index 22ea84fdfe087..7cb80b64b2db5 100644 --- a/Mathlib/SetTheory/Ordinal/FixedPointApproximants.lean +++ b/Mathlib/SetTheory/Ordinal/FixedPointApproximants.lean @@ -145,7 +145,7 @@ theorem exists_lfpApprox_eq_lfpApprox : ∃ a < ord <| succ #α, ∃ b < ord <| · exact h_fab /-- If there are distinct ordinals with equal value then - every value succeding the smaller ordinal are fixed points -/ + every value succeeding the smaller ordinal are fixed points -/ 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 diff --git a/Mathlib/SetTheory/Ordinal/NaturalOps.lean b/Mathlib/SetTheory/Ordinal/NaturalOps.lean index e61e3fd7ddbe2..15a117be039a3 100644 --- a/Mathlib/SetTheory/Ordinal/NaturalOps.lean +++ b/Mathlib/SetTheory/Ordinal/NaturalOps.lean @@ -47,6 +47,7 @@ noncomputable section /-! ### Basic casts between `Ordinal` and `NatOrdinal` -/ + /-- A type synonym for ordinals with natural addition and multiplication. -/ def NatOrdinal : Type _ := -- Porting note: used to derive LinearOrder & SuccOrder but need to manually define @@ -199,6 +200,7 @@ scoped[NaturalOps] infixl:70 " ⨳ " => Ordinal.nmul /-! ### Natural addition -/ + theorem nadd_def (a b : Ordinal) : a ♯ b = max (blsub.{u, u} a fun a' _ => a' ♯ b) (blsub.{u, u} b fun b' _ => a ♯ b') := by rw [nadd] @@ -232,7 +234,7 @@ variable (a b) theorem nadd_comm (a b) : a ♯ b = b ♯ a := by rw [nadd_def, nadd_def, max_comm] congr <;> ext <;> apply nadd_comm -termination_by (a,b) +termination_by (a, b) theorem blsub_nadd_of_mono {f : ∀ c < a ♯ b, Ordinal.{max u v}} (hf : ∀ {i j} (hi hj), i ≤ j → f i hi ≤ f j hj) : @@ -429,6 +431,7 @@ theorem nadd_right_comm : ∀ a b c, a ♯ b ♯ c = a ♯ c ♯ b := /-! ### Natural multiplication -/ + variable {a b c d : Ordinal.{u}} theorem nmul_def (a b : Ordinal) : @@ -507,14 +510,20 @@ theorem nmul_lt_nmul_of_pos_left (h₁ : a < b) (h₂ : 0 < c) : c ⨳ a < c ⨳ theorem nmul_lt_nmul_of_pos_right (h₁ : a < b) (h₂ : 0 < c) : a ⨳ c < b ⨳ c := lt_nmul_iff.2 ⟨a, h₁, 0, h₂, by simp⟩ -theorem nmul_le_nmul_of_nonneg_left (h₁ : a ≤ b) (h₂ : 0 ≤ c) : c ⨳ a ≤ c ⨳ b := by - rcases lt_or_eq_of_le h₁ with (h₁ | rfl) <;> rcases lt_or_eq_of_le h₂ with (h₂ | rfl) +theorem nmul_le_nmul_left (h : a ≤ b) (c) : c ⨳ a ≤ c ⨳ b := by + rcases lt_or_eq_of_le h with (h₁ | rfl) <;> rcases (eq_zero_or_pos c).symm with (h₂ | rfl) · exact (nmul_lt_nmul_of_pos_left h₁ h₂).le all_goals simp -theorem nmul_le_nmul_of_nonneg_right (h₁ : a ≤ b) (h₂ : 0 ≤ c) : a ⨳ c ≤ b ⨳ c := by +@[deprecated nmul_le_nmul_left (since := "2024-08-20")] +alias nmul_le_nmul_of_nonneg_left := nmul_le_nmul_left + +theorem nmul_le_nmul_right (h : a ≤ b) (c) : a ⨳ c ≤ b ⨳ c := by rw [nmul_comm, nmul_comm b] - exact nmul_le_nmul_of_nonneg_left h₁ h₂ + exact nmul_le_nmul_left h c + +@[deprecated nmul_le_nmul_left (since := "2024-08-20")] +alias nmul_le_nmul_of_nonneg_right := nmul_le_nmul_right theorem nmul_nadd (a b c : Ordinal) : a ⨳ (b ♯ c) = a ⨳ b ♯ a ⨳ c := by refine le_antisymm (nmul_le_iff.2 fun a' ha d hd => ?_) @@ -671,8 +680,8 @@ instance : OrderedCommSemiring NatOrdinal.{u} := mul_one := nmul_one mul_comm := nmul_comm zero_le_one := @zero_le_one Ordinal _ _ _ _ - mul_le_mul_of_nonneg_left := fun a b c => nmul_le_nmul_of_nonneg_left - mul_le_mul_of_nonneg_right := fun a b c => nmul_le_nmul_of_nonneg_right } + mul_le_mul_of_nonneg_left := fun a b c h _ => nmul_le_nmul_left h c + mul_le_mul_of_nonneg_right := fun a b c h _ => nmul_le_nmul_right h c } namespace Ordinal @@ -695,12 +704,6 @@ theorem nmul_add_one : ∀ a b, a ⨳ (b + 1) = a ⨳ b ♯ a := theorem add_one_nmul : ∀ a b, (a + 1) ⨳ b = a ⨳ b ♯ b := succ_nmul -end Ordinal - -namespace NatOrdinal - -open Ordinal - theorem mul_le_nmul (a b : Ordinal.{u}) : a * b ≤ a ⨳ b := by refine b.limitRecOn ?_ ?_ ?_ · simp @@ -713,4 +716,7 @@ theorem mul_le_nmul (a b : Ordinal.{u}) : a * b ≤ a ⨳ b := by · rw [← IsNormal.blsub_eq.{u, u} (mul_isNormal ha) hc, blsub_le_iff] exact fun i hi => (H i hi).trans_lt (nmul_lt_nmul_of_pos_left hi ha) -end NatOrdinal +@[deprecated mul_le_nmul (since := "2024-08-20")] +alias _root_.NatOrdinal.mul_le_nmul := mul_le_nmul + +end Ordinal diff --git a/Mathlib/SetTheory/Ordinal/Notation.lean b/Mathlib/SetTheory/Ordinal/Notation.lean index 9feba54454817..d57c7f29037cc 100644 --- a/Mathlib/SetTheory/Ordinal/Notation.lean +++ b/Mathlib/SetTheory/Ordinal/Notation.lean @@ -164,8 +164,8 @@ theorem eq_of_cmp_eq : ∀ {o₁ o₂}, cmp o₁ o₂ = Ordering.eq → o₁ = o obtain rfl := eq_of_cmp_eq h₁ revert h; cases h₂ : _root_.cmp (n₁ : ℕ) n₂ <;> intro h <;> try cases h obtain rfl := eq_of_cmp_eq h - rw [_root_.cmp, cmpUsing_eq_eq] at h₂ - obtain rfl := Subtype.eq (eq_of_incomp h₂) + rw [_root_.cmp, cmpUsing_eq_eq, not_lt, not_lt, ← le_antisymm_iff] at h₂ + obtain rfl := Subtype.eq h₂ simp protected theorem zero_lt_one : (0 : ONote) < 1 := by @@ -230,9 +230,10 @@ theorem NF.zero_of_zero {e n a} (h : NF (ONote.oadd e n a)) (e0 : e = 0) : a = 0 simpa [e0, NFBelow_zero] using h.snd' theorem NFBelow.repr_lt {o b} (h : NFBelow o b) : repr o < ω ^ b := by - induction' h with _ e n a eb b h₁ h₂ h₃ _ IH - · exact opow_pos _ omega_pos - · rw [repr] + induction h with + | zero => exact opow_pos _ omega_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 @@ -240,8 +241,9 @@ theorem NFBelow.repr_lt {o b} (h : NFBelow o b) : repr o < ω ^ b := by exact opow_le_opow_right omega_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 _ e n a eb b h₁ h₂ h₃ _ _ <;> constructor - exacts [h₁, h₂, lt_of_lt_of_le h₃ bb] + induction h with + | zero => exact zero + | oadd' h₁ h₂ h₃ _ _ => constructor; exacts [h₁, h₂, lt_of_lt_of_le h₃ bb] theorem NF.below_of_lt {e n a b} (H : repr e < b) : NF (ONote.oadd e n a) → NFBelow (ONote.oadd e n a) b @@ -309,7 +311,7 @@ theorem cmp_compares : ∀ (a b : ONote) [NF a] [NF b], (cmp a b).Compares a b rw [ite_eq_iff] at nhr cases' nhr with nhr nhr · cases nhr; contradiction - obtain rfl := Subtype.eq (eq_of_incomp ⟨(not_lt_of_ge nhl), nhr.left⟩) + obtain rfl := Subtype.eq (nhl.eq_of_not_lt nhr.1) have IHa := @cmp_compares _ _ h₁.snd h₂.snd revert IHa; cases cmp a₁ a₂ <;> intro IHa <;> dsimp at IHa case lt => exact oadd_lt_oadd_3 IHa @@ -842,7 +844,8 @@ theorem repr_opow_aux₂ {a0 a'} [N0 : NF a0] [Na' : NF a'] (m : ℕ) (d : ω 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 - · simp [opow_mul, opow_add, mul_assoc] + · 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 _) @@ -901,6 +904,7 @@ theorem repr_opow (o₁ o₂) [NF o₁] [NF o₂] : repr (o₁ ^ o₂) = repr o 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] exact ⟨_, rfl⟩ @@ -915,7 +919,7 @@ theorem repr_opow (o₁ o₂) [NF o₁] [NF o₂] : repr (o₁ ^ o₂) = repr o simp only [opow_def, opow, e₁, r₁, split_eq_scale_split' e₂, opowAux2, repr] cases' k with k · simp [r₂, opow_mul, repr_opow_aux₁ a00 al aa, add_assoc] - · simp? [r₂, opow_add, opow_mul, mul_assoc, add_assoc, -repr] says + · simp? [r₂, opow_add, opow_mul, mul_assoc, add_assoc, -repr, -opow_natCast] says simp only [mulNat_eq_mul, repr_add, repr_scale, repr_mul, repr_ofNat, opow_add, opow_mul, mul_assoc, add_assoc, r₂, Nat.cast_add, Nat.cast_one, add_one_eq_succ, opow_succ] simp only [repr, opow_zero, Nat.succPNat_coe, Nat.cast_one, mul_one, add_zero, opow_one] diff --git a/Mathlib/SetTheory/Ordinal/Principal.lean b/Mathlib/SetTheory/Ordinal/Principal.lean index 02c84a0a53cd7..8d13d1a443605 100644 --- a/Mathlib/SetTheory/Ordinal/Principal.lean +++ b/Mathlib/SetTheory/Ordinal/Principal.lean @@ -24,16 +24,15 @@ We define principal or indecomposable ordinals, and we prove the standard proper of `fun x ↦ ω ^ x`. -/ -universe u v w - -noncomputable section +universe u open Order namespace Ordinal --- Porting note: commented out, doesn't seem necessary ---local infixr:0 "^" => @pow Ordinal Ordinal Ordinal.hasPow +section Arbitrary + +variable {op : Ordinal → Ordinal → Ordinal} /-! ### Principal ordinals -/ @@ -42,41 +41,50 @@ namespace Ordinal ordinals less than it is closed under that operation. In standard mathematical usage, this term is almost exclusively used for additive and multiplicative principal ordinals. -For simplicity, we break usual convention and regard 0 as principal. -/ +For simplicity, we break usual convention and regard `0` as principal. -/ def Principal (op : Ordinal → Ordinal → Ordinal) (o : Ordinal) : Prop := ∀ ⦃a b⦄, a < o → b < o → op a b < o -theorem principal_iff_principal_swap {op : Ordinal → Ordinal → Ordinal} {o : Ordinal} : - Principal op o ↔ Principal (Function.swap op) o := by +theorem principal_swap_iff {o : Ordinal} : Principal (Function.swap op) o ↔ Principal op o := by constructor <;> exact fun h a b ha hb => h hb ha -theorem principal_zero {op : Ordinal → Ordinal → Ordinal} : Principal op 0 := fun a _ h => +@[deprecated principal_swap_iff (since := "2024-08-18")] +theorem principal_iff_principal_swap {o : Ordinal} : + Principal op o ↔ Principal (Function.swap op) o := + principal_swap_iff + +theorem not_principal_iff {o : Ordinal} : ¬ Principal op o ↔ ∃ a < o, ∃ b < o, o ≤ op a b := by + simp [Principal] + +theorem principal_zero : Principal op 0 := fun a _ h => (Ordinal.not_lt_zero a h).elim @[simp] -theorem principal_one_iff {op : Ordinal → Ordinal → Ordinal} : Principal op 1 ↔ op 0 0 = 0 := by +theorem principal_one_iff : Principal op 1 ↔ op 0 0 = 0 := by refine ⟨fun h => ?_, fun h a b ha hb => ?_⟩ · rw [← lt_one_iff_zero] exact h zero_lt_one zero_lt_one · rwa [lt_one_iff_zero, ha, hb] at * -theorem Principal.iterate_lt {op : Ordinal → Ordinal → Ordinal} {a o : Ordinal} (hao : a < o) - (ho : Principal op o) (n : ℕ) : (op a)^[n] a < o := by +theorem Principal.iterate_lt {a o : Ordinal} (hao : a < o) (ho : Principal op o) (n : ℕ) : + (op a)^[n] a < o := by induction' n with n hn · rwa [Function.iterate_zero] · rw [Function.iterate_succ'] exact ho hao hn -theorem op_eq_self_of_principal {op : Ordinal → Ordinal → Ordinal} {a o : Ordinal.{u}} (hao : a < o) - (H : IsNormal (op a)) (ho : Principal op o) (ho' : IsLimit o) : op a o = o := by +theorem op_eq_self_of_principal {a o : Ordinal.{u}} (hao : a < o) (H : IsNormal (op a)) + (ho : Principal op o) (ho' : IsLimit o) : op a o = o := by refine le_antisymm ?_ (H.self_le _) rw [← IsNormal.bsup_eq.{u, u} H ho', bsup_le_iff] exact fun b hbo => (ho hao hbo).le -theorem nfp_le_of_principal {op : Ordinal → Ordinal → Ordinal} {a o : Ordinal} (hao : a < o) - (ho : Principal op o) : nfp (op a) a ≤ o := +theorem nfp_le_of_principal {a o : Ordinal} (hao : a < o) (ho : Principal op o) : + nfp (op a) a ≤ o := nfp_le fun n => (ho.iterate_lt hao n).le +end Arbitrary + /-! ### Principal ordinals are unbounded -/ #adaptation_note /-- 2024-04-23 @@ -85,8 +93,8 @@ we need to write `lt_blsub₂.{u}` twice below, where previously the universe annotation was not necessary. This appears to be correct behaviour, as `lt_blsub₂.{0}` also works. -/ theorem principal_nfp_blsub₂ (op : Ordinal → Ordinal → Ordinal) (o : Ordinal) : - Principal op (nfp (fun o' => blsub₂.{u, u, u} o' o' (@fun a _ b _ => op a b)) o) := - fun a b ha hb => by + Principal op (nfp (fun o' => blsub₂.{u, u, u} o' o' (@fun a _ b _ => op a b)) o) := by + intro a b ha hb rw [lt_nfp] at * cases' ha with m hm cases' hb with n hn @@ -95,11 +103,12 @@ theorem principal_nfp_blsub₂ (op : Ordinal → Ordinal → Ordinal) (o : Ordin ((fun o' => blsub₂.{u, u, u} o' o' (@fun a _ b _ => op a b))^[n] o) with h h · use n + 1 rw [Function.iterate_succ'] - exact lt_blsub₂.{u} (@fun a _ b _ => op a b) (hm.trans_le h) hn + exact lt_blsub₂ (@fun a _ b _ => op a b) (hm.trans_le h) hn · use m + 1 rw [Function.iterate_succ'] - exact lt_blsub₂.{u} (@fun a _ b _ => op a b) hm (hn.trans_le h) + exact lt_blsub₂ (@fun a _ b _ => op a b) hm (hn.trans_le h) +/-- Principal ordinals under any operation form a ZFC proper class. -/ theorem unbounded_principal (op : Ordinal → Ordinal → Ordinal) : Set.Unbounded (· < ·) { o | Principal op o } := fun o => ⟨_, principal_nfp_blsub₂ op o, (le_nfp _ o).not_lt⟩ @@ -139,60 +148,61 @@ theorem principal_add_iff_add_left_eq_self {o : Ordinal} : exact (add_isNormal a).strictMono hbo theorem exists_lt_add_of_not_principal_add {a} (ha : ¬Principal (· + ·) a) : - ∃ b c, b < a ∧ c < a ∧ b + c = a := by - unfold Principal at ha - push_neg at ha - rcases ha with ⟨b, c, hb, hc, H⟩ + ∃ b < a, ∃ c < a, b + c = a := by + rw [not_principal_iff] at ha + rcases ha with ⟨b, hb, c, hc, H⟩ refine - ⟨b, _, hb, lt_of_le_of_ne (sub_le_self a b) fun hab => ?_, Ordinal.add_sub_cancel_of_le hb.le⟩ + ⟨b, hb, _, lt_of_le_of_ne (sub_le_self a b) fun hab => ?_, Ordinal.add_sub_cancel_of_le hb.le⟩ rw [← sub_le, hab] at H exact H.not_lt hc theorem principal_add_iff_add_lt_ne_self {a} : - Principal (· + ·) a ↔ ∀ ⦃b c⦄, b < a → c < a → b + c ≠ a := - ⟨fun ha b c hb hc => (ha hb hc).ne, fun H => by + Principal (· + ·) a ↔ ∀ b < a, ∀ c < a, b + c ≠ a := + ⟨fun ha b hb c hc => (ha hb hc).ne, fun H => by by_contra! ha - rcases exists_lt_add_of_not_principal_add ha with ⟨b, c, hb, hc, rfl⟩ - exact (H hb hc).irrefl⟩ + 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 < omega) : a + omega = omega := by +theorem add_omega {a : Ordinal} (h : a < ω) : a + ω = ω := by rcases lt_omega.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 _)] -theorem principal_add_omega : Principal (· + ·) omega := +theorem principal_add_omega : Principal (· + ·) ω := principal_add_iff_add_left_eq_self.2 fun _ => add_omega -theorem add_omega_opow {a b : Ordinal} (h : a < (omega^b)) : a + (omega^b) = (omega^b) := by - refine le_antisymm ?_ (le_add_left _ _) +theorem add_omega_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⟩ - refine le_trans (add_le_add_right (le_of_lt 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⟩ - exact - (((add_isNormal a).trans (opow_isNormal one_lt_omega)).limit_le l).2 fun y yb => - (add_le_add_left (opow_le_opow_right omega_pos (le_max_right _ _)) _).trans - (le_trans - (IH _ (max_lt xb yb) (ax.trans_le <| opow_le_opow_right omega_pos (le_max_left _ _))) - (opow_le_opow_right omega_pos <| le_of_lt <| max_lt xb yb)) - -theorem principal_add_omega_opow (o : Ordinal) : Principal (· + ·) (omega^o) := + apply (((add_isNormal a).trans <| opow_isNormal one_lt_omega).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)) _ + _ ≤ ω ^ max x y := + IH _ (max_lt xb yb) <| ax.trans_le <| opow_le_opow_right omega_pos <| le_max_left x y + _ ≤ ω ^ b := + opow_le_opow_right omega_pos <| (max_lt xb yb).le + +theorem principal_add_omega_opow (o : Ordinal) : Principal (· + ·) (ω ^ o) := principal_add_iff_add_left_eq_self.2 fun _ => add_omega_opow /-- The main characterization theorem for additive principal ordinals. -/ theorem principal_add_iff_zero_or_omega_opow {o : Ordinal} : - Principal (· + ·) o ↔ o = 0 ∨ ∃ a : Ordinal, o = (omega^a) := by + 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] · rw [principal_add_iff_add_left_eq_self] simp only [ho, false_or_iff] refine - ⟨fun H => ⟨_, ((lt_or_eq_of_le (opow_log_le_self _ ho)).resolve_left fun h => ?_).symm⟩, + ⟨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⟩ have := H _ h have := lt_opow_succ_log_self one_lt_omega o @@ -202,14 +212,14 @@ theorem principal_add_iff_zero_or_omega_opow {o : Ordinal} : clear ao revert h' apply not_lt_of_le - suffices e : (omega^log omega o) * ↑n + o = o by - simpa only [e] using le_add_right ((omega^log omega o) * ↑n) o + suffices e : ω ^ log ω o * n + o = o by + simpa only [e] using le_add_right (ω ^ log ω o * ↑n) o induction' n with n IH · simp [Nat.cast_zero, mul_zero, zero_add] - simp only [Nat.cast_succ, mul_add_one, add_assoc, this, IH] + · simp only [Nat.cast_succ, mul_add_one, add_assoc, this, IH] theorem opow_principal_add_of_principal_add {a} (ha : Principal (· + ·) a) (b : Ordinal) : - Principal (· + ·) (a^b) := by + Principal (· + ·) (a ^ b) := by rcases principal_add_iff_zero_or_omega_opow.1 ha with (rfl | ⟨c, rfl⟩) · rcases eq_or_ne b 0 with (rfl | hb) · rw [opow_zero] @@ -218,7 +228,7 @@ theorem opow_principal_add_of_principal_add {a} (ha : Principal (· + ·) a) (b · rw [← opow_mul] exact principal_add_omega_opow _ -theorem add_absorp {a b c : Ordinal} (h₁ : a < (omega^b)) (h₂ : (omega^b) ≤ c) : a + c = c := by +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₁] theorem mul_principal_add_is_principal_add (a : Ordinal.{u}) {b : Ordinal.{u}} (hb₁ : b ≠ 1) @@ -245,17 +255,15 @@ theorem principal_mul_one : Principal (· * ·) 1 := by rw [principal_one_iff] exact zero_mul _ -theorem principal_mul_two : Principal (· * ·) 2 := fun a b ha hb => by - have h₂ : succ (1 : Ordinal) = 2 := by simp - dsimp only - rw [← h₂, lt_succ_iff] at ha hb ⊢ +theorem principal_mul_two : Principal (· * ·) 2 := by + intro a b ha hb + rw [← succ_one, lt_succ_iff] at * convert mul_le_mul' ha hb exact (mul_one 1).symm theorem principal_mul_of_le_two {o : Ordinal} (ho : o ≤ 2) : Principal (· * ·) o := by rcases lt_or_eq_of_le ho with (ho | rfl) - · have h₂ : succ (1 : Ordinal) = 2 := by simp - rw [← h₂, lt_succ_iff] at ho + · rw [← succ_one, lt_succ_iff] at ho rcases lt_or_eq_of_le ho with (ho | rfl) · rw [lt_one_iff_zero.1 ho] exact principal_zero @@ -294,17 +302,17 @@ 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 (· * ·) omega := fun a b ha hb => +theorem principal_mul_omega : Principal (· * ·) ω := fun a b ha hb => match a, b, lt_omega.1 ha, lt_omega.1 hb with | _, _, ⟨m, rfl⟩, ⟨n, rfl⟩ => by dsimp only; rw [← natCast_mul] apply nat_lt_omega -theorem mul_omega {a : Ordinal} (a0 : 0 < a) (ha : a < omega) : a * omega = omega := +theorem mul_omega {a : Ordinal} (a0 : 0 < a) (ha : a < ω) : a * ω = ω := principal_mul_iff_mul_left_eq.1 principal_mul_omega a a0 ha -theorem mul_lt_omega_opow {a b c : Ordinal} (c0 : 0 < c) (ha : a < (omega^c)) (hb : b < omega) : - a * b < (omega^c) := by +theorem mul_lt_omega_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 @@ -317,58 +325,60 @@ theorem mul_lt_omega_opow {a b c : Ordinal} (c0 : 0 < c) (ha : a < (omega^c)) (h rw [← opow_succ, opow_lt_opow_iff_right one_lt_omega] exact l.2 _ hx -theorem mul_omega_opow_opow {a b : Ordinal} (a0 : 0 < a) (h : a < (omega^omega^b)) : - a * (omega^omega^b) = (omega^omega^b) := by - by_cases b0 : b = 0 - · rw [b0, opow_zero, opow_one] at h ⊢ +theorem mul_omega_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 - refine - le_antisymm ?_ - (by simpa only [one_mul] using mul_le_mul_right' (one_le_iff_pos.2 a0) (omega^omega^b)) - rcases (lt_opow_of_limit omega_ne_zero (opow_isLimit_left omega_isLimit b0)).1 h with ⟨x, xb, ax⟩ - apply (mul_le_mul_right' (le_of_lt ax) _).trans - rw [← opow_add, add_omega_opow xb] - -theorem principal_mul_omega_opow_opow (o : Ordinal) : Principal (· * ·) (omega^omega^o) := + · apply le_antisymm + · obtain ⟨x, xb, ax⟩ := + (lt_opow_of_limit omega_ne_zero (opow_isLimit_left omega_isLimit b0)).1 h + apply (mul_le_mul_right' (le_of_lt ax) _).trans + rw [← opow_add, add_omega_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 theorem principal_add_of_principal_mul_opow {o b : Ordinal} (hb : 1 < b) - (ho : Principal (· * ·) (b^o)) : Principal (· + ·) o := fun x y hx hy => by + (ho : Principal (· * ·) (b ^ o)) : Principal (· + ·) o := by + intro x y hx hy have := ho ((opow_lt_opow_iff_right hb).2 hx) ((opow_lt_opow_iff_right hb).2 hy) - dsimp only at *; rwa [← opow_add, opow_lt_opow_iff_right hb] at this + dsimp only at * + 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} : - Principal (· * ·) o ↔ o ≤ 2 ∨ ∃ a : Ordinal, o = (omega^omega^a) := by + 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 + · rcases principal_add_iff_zero_or_omega_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⟩) - · simp - exact Or.inr ⟨b, 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⟩) + · simp + · exact Or.inr ⟨b, rfl⟩ · rintro (ho₂ | ⟨a, rfl⟩) · exact principal_mul_of_le_two ho₂ · exact principal_mul_omega_opow_opow a -theorem mul_omega_dvd {a : Ordinal} (a0 : 0 < a) (ha : a < omega) : ∀ {b}, omega ∣ b → a * b = b +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_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 + (hb₂ : 2 < b) : a * b = b ^ succ (log b a) := by apply le_antisymm · have hbl := principal_mul_isLimit hb₂ hb rw [← IsNormal.bsup_eq.{u, u} (mul_isNormal (Ordinal.pos_iff_ne_zero.2 ha)) hbl, bsup_le_iff] intro c hcb - have hb₁ : 1 < b := (lt_succ 1).trans (by simpa using hb₂) - have hbo₀ : (b^b.log a) ≠ 0 := Ordinal.pos_iff_ne_zero.1 (opow_pos _ (zero_lt_one.trans hb₁)) - apply le_trans (mul_le_mul_right' (le_of_lt (lt_mul_succ_div a hbo₀)) c) + have hb₁ : 1 < b := (lt_succ 1).trans (by rwa [succ_one]) + have hbo₀ : b ^ log b a ≠ 0 := Ordinal.pos_iff_ne_zero.1 (opow_pos _ (zero_lt_one.trans hb₁)) + apply (mul_le_mul_right' (le_of_lt (lt_mul_succ_div a hbo₀)) c).trans rw [mul_assoc, opow_succ] - refine mul_le_mul_left' (le_of_lt (hb (hbl.2 _ ?_) hcb)) _ + refine mul_le_mul_left' (hb (hbl.2 _ ?_) hcb).le _ rw [div_lt hbo₀, ← opow_succ] exact lt_opow_succ_log_self hb₁ _ · rw [opow_succ] @@ -377,16 +387,15 @@ theorem mul_eq_opow_log_succ {a b : Ordinal.{u}} (ha : a ≠ 0) (hb : Principal /-! #### Exponential principal ordinals -/ -theorem principal_opow_omega : Principal (·^·) omega := fun a b ha hb => +theorem principal_opow_omega : Principal (· ^ ·) ω := fun a b ha hb => match a, b, lt_omega.1 ha, lt_omega.1 hb with | _, _, ⟨m, rfl⟩, ⟨n, rfl⟩ => by simp_rw [← natCast_opow] apply nat_lt_omega -theorem opow_omega {a : Ordinal} (a1 : 1 < a) (h : a < omega) : (a^omega) = omega := - le_antisymm - ((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) - (right_le_opow _ a1) +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 + (right_le_opow _ a1) end Ordinal diff --git a/Mathlib/SetTheory/Ordinal/Topology.lean b/Mathlib/SetTheory/Ordinal/Topology.lean index 24d2a3e5e65c9..427fe767bdbf7 100644 --- a/Mathlib/SetTheory/Ordinal/Topology.lean +++ b/Mathlib/SetTheory/Ordinal/Topology.lean @@ -111,7 +111,7 @@ theorem mem_closure_tfae (a : Ordinal.{u}) (s : Set Ordinal) : · refine (if_pos hx).symm.trans_le (le_bsup _ _ <| (hlub.1 hx).trans_lt (lt_succ _)) tfae_have 5 → 6 · rintro ⟨o, h₀, f, hfs, rfl⟩ - exact ⟨_, out_nonempty_iff_ne_zero.2 h₀, familyOfBFamily o f, fun _ => hfs _ _, rfl⟩ + exact ⟨_, toType_nonempty_iff_ne_zero.2 h₀, familyOfBFamily o f, fun _ => hfs _ _, rfl⟩ tfae_have 6 → 1 · rintro ⟨ι, hne, f, hfs, rfl⟩ rw [sup, iSup] @@ -122,7 +122,10 @@ theorem mem_closure_tfae (a : Ordinal.{u}) (s : Set Ordinal) : theorem mem_closure_iff_sup : a ∈ closure s ↔ ∃ (ι : Type u) (_ : Nonempty ι) (f : ι → Ordinal), (∀ i, f i ∈ s) ∧ sup.{u, u} f = a := - ((mem_closure_tfae a s).out 0 5).trans <| by simp only [exists_prop] + calc + _ ↔ (∃ (ι : Type u), Nonempty ι ∧ ∃ f, (∀ (i : ι), f i ∈ s) ∧ sup f = a) := + (mem_closure_tfae a s).out 0 5 + _ ↔ _ := by simp only [exists_prop] theorem mem_closed_iff_sup (hs : IsClosed s) : a ∈ s ↔ ∃ (ι : Type u) (_hι : Nonempty ι) (f : ι → Ordinal), @@ -133,7 +136,10 @@ theorem mem_closure_iff_bsup : a ∈ closure s ↔ ∃ (o : Ordinal) (_ho : o ≠ 0) (f : ∀ a < o, Ordinal), (∀ i hi, f i hi ∈ s) ∧ bsup.{u, u} o f = a := - ((mem_closure_tfae a s).out 0 4).trans <| by simp only [exists_prop] + calc + _ ↔ ∃ o, o ≠ 0 ∧ ∃ f, (∀ (x : Ordinal.{u}) (hx : x < o), f x hx ∈ s) ∧ o.bsup f = a := + (mem_closure_tfae a s).out 0 4 + _ ↔ _ := by simp only [exists_prop] theorem mem_closed_iff_bsup (hs : IsClosed s) : a ∈ s ↔ @@ -155,7 +161,7 @@ theorem isClosed_iff_bsup : ∀ {o : Ordinal}, o ≠ 0 → ∀ f : ∀ a < o, Ordinal, (∀ i hi, f i hi ∈ s) → bsup.{u, u} o f ∈ s := by rw [isClosed_iff_sup] - refine ⟨fun H o ho f hf => H (out_nonempty_iff_ne_zero.2 ho) _ ?_, fun H ι hι f hf => ?_⟩ + refine ⟨fun H o ho f hf => H (toType_nonempty_iff_ne_zero.2 ho) _ ?_, fun H ι hι f hf => ?_⟩ · exact fun i => hf _ _ · rw [← bsup_eq_sup] apply H (type_ne_zero_iff_nonempty.2 hι) @@ -190,7 +196,7 @@ theorem isNormal_iff_strictMono_and_continuous (f : Ordinal.{u} → Ordinal.{u}) suffices o ∈ f ⁻¹' Set.Iic a from Set.mem_preimage.1 this rw [mem_closed_iff_sup (IsClosed.preimage h' (@isClosed_Iic _ _ _ _ a))] exact - ⟨_, out_nonempty_iff_ne_zero.2 ho.1, typein (· < ·), fun i => h _ (typein_lt_self i), + ⟨_, 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 (· < ·)) : diff --git a/Mathlib/SetTheory/Surreal/Multiplication.lean b/Mathlib/SetTheory/Surreal/Multiplication.lean index 3f931a7db4fd7..29f0f225bedb8 100644 --- a/Mathlib/SetTheory/Surreal/Multiplication.lean +++ b/Mathlib/SetTheory/Surreal/Multiplication.lean @@ -173,7 +173,7 @@ open Relation /-- The relation specifying when a list of (pregame) arguments is considered simpler than another: `ArgsRel a₁ a₂` is true if `a₁`, considered as a multiset, can be obtained from `a₂` by - repeatedly removing a pregame from `a₂` and adding back one or two options of the pregame. -/ + repeatedly removing a pregame from `a₂` and adding back one or two options of the pregame. -/ def ArgsRel := InvImage (TransGen <| CutExpand IsOption) Args.toMultiset /-- `ArgsRel` is well-founded. -/ @@ -463,7 +463,7 @@ theorem Equiv.mul_congr_left (hx₁ : x₁.Numeric) (hx₂ : x₂.Numeric) (hy : (he : x₁ ≈ x₂) : x₁ * y ≈ x₂ * y := equiv_iff_game_eq.2 <| (P24 hx₁ hx₂ hy).1 he -theorem Equiv.mul_congr_right (hx : x.Numeric) (hy₁ : y₁.Numeric) (hy₂ : y₂.Numeric) +theorem Equiv.mul_congr_right (hx : x.Numeric) (hy₁ : y₁.Numeric) (hy₂ : y₂.Numeric) (he : y₁ ≈ y₂) : x * y₁ ≈ x * y₂ := .trans (mul_comm_equiv _ _) <| .trans (mul_congr_left hy₁ hy₂ hx he) (mul_comm_equiv _ _) diff --git a/Mathlib/SetTheory/ZFC/Basic.lean b/Mathlib/SetTheory/ZFC/Basic.lean index 3b4f62f933cd2..a556cdab50f44 100644 --- a/Mathlib/SetTheory/ZFC/Basic.lean +++ b/Mathlib/SetTheory/ZFC/Basic.lean @@ -193,7 +193,7 @@ theorem Subset.congr_right : ∀ {x y z : PSet}, Equiv x y → (z ⊆ x ↔ z ⟨a, cb.trans (Equiv.symm ab)⟩⟩ /-- `x ∈ y` as pre-sets if `x` is extensionally equivalent to a member of the family `y`. -/ -protected def Mem (x y : PSet.{u}) : Prop := +protected def Mem (y x : PSet.{u}) : Prop := ∃ b, Equiv x (y.Func b) instance : Membership PSet PSet := @@ -232,6 +232,12 @@ theorem equiv_iff_mem {x y : PSet.{u}} : Equiv x y ↔ ∀ {w : PSet.{u}}, w ∈ theorem Mem.congr_left : ∀ {x y : PSet.{u}}, Equiv x y → ∀ {w : PSet.{u}}, x ∈ w ↔ y ∈ w | _, _, h, ⟨_, _⟩ => ⟨fun ⟨a, ha⟩ => ⟨a, h.symm.trans ha⟩, fun ⟨a, ha⟩ => ⟨a, h.trans ha⟩⟩ +theorem mem_of_subset {x y z : PSet} : x ⊆ y → z ∈ x → z ∈ y + | h₁, ⟨a, h₂⟩ => (h₁ a).elim fun b h₃ => ⟨b, h₂.trans h₃⟩ + +theorem subset_iff {x y : PSet} : x ⊆ y ↔ ∀ ⦃z⦄, z ∈ x → z ∈ y := + ⟨fun h _ => mem_of_subset h, fun h a => h (Mem.mk _ a)⟩ + private theorem mem_wf_aux : ∀ {x y : PSet.{u}}, Equiv x y → Acc (· ∈ ·) y | ⟨α, A⟩, ⟨β, B⟩, H => ⟨_, by @@ -254,10 +260,10 @@ instance : IsIrrefl PSet (· ∈ ·) := mem_wf.isIrrefl theorem mem_asymm {x y : PSet} : x ∈ y → y ∉ x := - asymm + asymm (r := (· ∈ ·)) theorem mem_irrefl (x : PSet) : x ∉ x := - irrefl x + irrefl (r := (· ∈ ·)) x /-- Convert a pre-set to a `Set` of pre-sets. -/ def toSet (u : PSet.{u}) : Set PSet.{u} := @@ -339,6 +345,33 @@ instance : LawfulSingleton PSet PSet := instance (x y : PSet) : Inhabited (insert x y).Type := inferInstanceAs (Inhabited <| Option y.Type) +@[simp] +theorem mem_insert_iff : ∀ {x y z : PSet.{u}}, x ∈ insert y z ↔ Equiv x y ∨ x ∈ z + | x, y, ⟨α, A⟩ => + show (x ∈ PSet.mk (Option α) fun o => Option.rec y A o) ↔ Equiv x y ∨ x ∈ PSet.mk α A from + ⟨fun m => + match m with + | ⟨some a, ha⟩ => Or.inr ⟨a, ha⟩ + | ⟨none, h⟩ => Or.inl h, + fun m => + match m with + | Or.inr ⟨a, ha⟩ => ⟨some a, ha⟩ + | Or.inl h => ⟨none, h⟩⟩ + +theorem mem_insert (x y : PSet) : x ∈ insert x y := + mem_insert_iff.2 <| Or.inl Equiv.rfl + +theorem mem_insert_of_mem {y z : PSet} (x) (h : z ∈ y) : z ∈ insert x y := + mem_insert_iff.2 <| Or.inr h + +@[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⟩ + +theorem mem_pair {x y z : PSet} : x ∈ ({y, z} : PSet) ↔ Equiv x y ∨ Equiv x z := by + simp + /-- The n-th von Neumann ordinal -/ def ofNat : ℕ → PSet | 0 => ∅ @@ -355,6 +388,12 @@ protected def sep (p : PSet → Prop) (x : PSet) : PSet := instance : Sep PSet PSet := ⟨PSet.sep⟩ +theorem mem_sep {p : PSet → Prop} (H : ∀ x y, Equiv x y → p x → p y) : + ∀ {x y : PSet}, y ∈ PSet.sep p x ↔ y ∈ x ∧ p y + | ⟨_, _⟩, _ => + ⟨fun ⟨⟨a, pa⟩, h⟩ => ⟨⟨a, h⟩, H _ _ h.symm pa⟩, fun ⟨⟨a, h⟩, pa⟩ => + ⟨⟨a, H _ _ h pa⟩, h⟩⟩ + /-- The pre-set powerset operator -/ def powerset (x : PSet) : PSet := ⟨Set x.Type, fun p => ⟨{ a // p a }, fun y => x.Func y.1⟩⟩ @@ -578,11 +617,11 @@ theorem eval_mk {n f x} : /-- The membership relation for ZFC sets is inherited from the membership relation for pre-sets. -/ protected def Mem : ZFSet → ZFSet → Prop := - Quotient.lift₂ PSet.Mem fun _ _ _ _ hx hy => + Quotient.lift₂ (· ∈ ·) fun _ _ _ _ hx hy => propext ((Mem.congr_left hx).trans (Mem.congr_right hy)) -instance : Membership ZFSet ZFSet := - ⟨ZFSet.Mem⟩ +instance : Membership ZFSet ZFSet where + mem t s := ZFSet.Mem s t @[simp] theorem mk_mem_iff {x y : PSet} : mk x ∈ mk y ↔ x ∈ y := @@ -726,16 +765,7 @@ instance : LawfulSingleton ZFSet ZFSet := @[simp] theorem mem_insert_iff {x y z : ZFSet.{u}} : x ∈ insert y z ↔ x = y ∨ x ∈ z := - Quotient.inductionOn₃ x y z fun x y ⟨α, A⟩ => - show (x ∈ PSet.mk (Option α) fun o => Option.rec y A o) ↔ mk x = mk y ∨ x ∈ PSet.mk α A from - ⟨fun m => - match m with - | ⟨some a, ha⟩ => Or.inr ⟨a, ha⟩ - | ⟨none, h⟩ => Or.inl (Quotient.sound h), - fun m => - match m with - | Or.inr ⟨a, ha⟩ => ⟨some a, ha⟩ - | Or.inl h => ⟨none, Quotient.exact h⟩⟩ + Quotient.inductionOn₃ x y z fun _ _ _ => PSet.mem_insert_iff.trans (or_congr_left eq.symm) theorem mem_insert (x y : ZFSet) : x ∈ insert x y := mem_insert_iff.2 <| Or.inl rfl @@ -750,8 +780,7 @@ theorem toSet_insert (x y : ZFSet) : (insert x y).toSet = insert x y.toSet := by @[simp] theorem mem_singleton {x y : ZFSet.{u}} : x ∈ @singleton ZFSet.{u} ZFSet.{u} _ y ↔ x = y := - Iff.trans mem_insert_iff - ⟨fun o => Or.rec (fun h => h) (fun n => absurd n (not_mem_empty _)) o, Or.inl⟩ + Quotient.inductionOn₂ x y fun _ _ => PSet.mem_singleton.trans eq.symm @[simp] theorem toSet_singleton (x : ZFSet) : ({x} : ZFSet).toSet = {x} := by @@ -802,12 +831,8 @@ instance : Sep ZFSet ZFSet := @[simp] theorem mem_sep {p : ZFSet.{u} → Prop} {x y : ZFSet.{u}} : y ∈ ZFSet.sep p x ↔ y ∈ x ∧ p y := - Quotient.inductionOn₂ x y fun ⟨α, A⟩ y => - ⟨fun ⟨⟨a, pa⟩, h⟩ => ⟨⟨a, h⟩, by rwa [@Quotient.sound PSet _ _ _ h]⟩, fun ⟨⟨a, h⟩, pa⟩ => - ⟨⟨a, by - rw [mk_func] at h - rwa [mk_func, ← ZFSet.sound h]⟩, - h⟩⟩ + Quotient.inductionOn₂ x y fun _ _ => + PSet.mem_sep (p := p ∘ mk) fun _ _ h => (Quotient.sound h).subst @[simp] theorem toSet_sep (a : ZFSet) (p : ZFSet → Prop) : @@ -831,8 +856,7 @@ def powerset : ZFSet → ZFSet := @[simp] theorem mem_powerset {x y : ZFSet.{u}} : y ∈ powerset x ↔ y ⊆ x := - Quotient.inductionOn₂ x y fun ⟨α, A⟩ ⟨β, B⟩ => - show (⟨β, B⟩ : PSet.{u}) ∈ PSet.powerset.{u} ⟨α, A⟩ ↔ _ by simp [mem_powerset, subset_iff] + Quotient.inductionOn₂ x y fun _ _ => PSet.mem_powerset.trans subset_iff.symm theorem sUnion_lem {α β : Type u} (A : α → PSet) (B : β → PSet) (αβ : ∀ a, ∃ b, Equiv (A a) (B b)) : ∀ a, ∃ b, Equiv ((sUnion ⟨α, A⟩).Func a) ((sUnion ⟨β, B⟩).Func b) @@ -871,9 +895,8 @@ prefix:110 "⋂₀ " => ZFSet.sInter @[simp] theorem mem_sUnion {x y : ZFSet.{u}} : y ∈ ⋃₀ x ↔ ∃ z ∈ x, y ∈ z := - Quotient.inductionOn₂ x y fun _ _ => - Iff.trans PSet.mem_sUnion - ⟨fun ⟨z, h⟩ => ⟨⟦z⟧, h⟩, fun ⟨z, h⟩ => Quotient.inductionOn z (fun z h => ⟨z, h⟩) h⟩ + Quotient.inductionOn₂ x y fun _ _ => PSet.mem_sUnion.trans + ⟨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] @@ -999,10 +1022,10 @@ instance : IsIrrefl ZFSet (· ∈ ·) := mem_wf.isIrrefl theorem mem_asymm {x y : ZFSet} : x ∈ y → y ∉ x := - asymm + asymm (r := (· ∈ ·)) theorem mem_irrefl (x : ZFSet) : x ∉ x := - irrefl x + irrefl (r := (· ∈ ·)) x theorem regularity (x : ZFSet.{u}) (h : x ≠ ∅) : ∃ y ∈ x, x ∩ y = ∅ := by_contradiction fun ne => @@ -1241,7 +1264,7 @@ def ToSet (B : Class.{u}) (A : Class.{u}) : Prop := ∃ x : ZFSet, ↑x = A ∧ B x /-- `A ∈ B` if `A` is a ZFC set which satisfies `B` -/ -protected def Mem (A B : Class.{u}) : Prop := +protected def Mem (B A : Class.{u}) : Prop := ToSet.{u} B A instance : Membership Class Class := @@ -1292,10 +1315,10 @@ instance : IsIrrefl Class (· ∈ ·) := mem_wf.isIrrefl theorem mem_asymm {x y : Class} : x ∈ y → y ∉ x := - asymm + asymm (r := (· ∈ ·)) theorem mem_irrefl (x : Class) : x ∉ x := - irrefl x + irrefl (r := (· ∈ ·)) x /-- **There is no universal set.** This is stated as `univ ∉ univ`, meaning that `univ` (the class of all sets) is proper (does not @@ -1541,3 +1564,5 @@ noncomputable def toSet_equiv : ZFSet.{u} ≃ {s : Set ZFSet.{u} // Small.{u, u+ right_inv s := Subtype.coe_injective <| toSet_equiv_aux s.2 end ZFSet + +set_option linter.style.longFile 1700 diff --git a/Mathlib/Tactic.lean b/Mathlib/Tactic.lean index dd7ed5f122df3..487a9cf1008d9 100644 --- a/Mathlib/Tactic.lean +++ b/Mathlib/Tactic.lean @@ -117,7 +117,9 @@ import Mathlib.Tactic.Linarith.Parsing import Mathlib.Tactic.Linarith.Preprocessing import Mathlib.Tactic.Linarith.Verification import Mathlib.Tactic.LinearCombination +import Mathlib.Tactic.LinearCombination' import Mathlib.Tactic.Linter +import Mathlib.Tactic.Linter.AdmitLinter import Mathlib.Tactic.Linter.GlobalAttributeIn import Mathlib.Tactic.Linter.HashCommandLinter import Mathlib.Tactic.Linter.HaveLetLinter @@ -202,6 +204,7 @@ import Mathlib.Tactic.Simps.NotationClass import Mathlib.Tactic.SlimCheck import Mathlib.Tactic.SplitIfs import Mathlib.Tactic.Spread +import Mathlib.Tactic.StacksAttribute import Mathlib.Tactic.Subsingleton import Mathlib.Tactic.Substs import Mathlib.Tactic.SuccessIfFailWithMsg diff --git a/Mathlib/Tactic/AdaptationNote.lean b/Mathlib/Tactic/AdaptationNote.lean index af508f76103bf..d8700ceceb3c2 100644 --- a/Mathlib/Tactic/AdaptationNote.lean +++ b/Mathlib/Tactic/AdaptationNote.lean @@ -11,7 +11,7 @@ import Lean This file defines a `#adaptation_note` command. Adaptation notes are comments that are used to indicate that a piece of code -has been changed to accomodate a change in Lean core. +has been changed to accommodate a change in Lean core. They typically require further action/maintenance to be taken in the future. -/ @@ -38,7 +38,7 @@ def reportAdaptationNote (f : Syntax → Meta.Tactic.TryThis.Suggestion) : MetaM Meta.Tactic.TryThis.addSuggestion (← getRef) (f stx') (origSpan? := ← getRef) /-- Adaptation notes are comments that are used to indicate that a piece of code -has been changed to accomodate a change in Lean core. +has been changed to accommodate a change in Lean core. They typically require further action/maintenance to be taken in the future. -/ elab (name := adaptationNoteCmd) "#adaptation_note " (docComment)? : command => do Elab.Command.liftTermElabM <| reportAdaptationNote (fun s => (⟨s⟩ : TSyntax `tactic)) diff --git a/Mathlib/Tactic/CC/Addition.lean b/Mathlib/Tactic/CC/Addition.lean index df7636b3fd528..3c63cb79c8fa9 100644 --- a/Mathlib/Tactic/CC/Addition.lean +++ b/Mathlib/Tactic/CC/Addition.lean @@ -192,8 +192,8 @@ def mkCCHCongrTheorem (fn : Expr) (nargs : Nat) : CCM (Option CCCongrTheorem) := -- Check if `{ fn, nargs }` is in the cache let key₁ : CCCongrTheoremKey := { fn, nargs } - if let some it₁ := cache.findEntry? key₁ then - return it₁.2 + if let some it := cache[key₁]? then + return it -- Try automatically generated congruence lemma with support for heterogeneous equality. let lemm ← mkCCHCongrWithArity fn nargs @@ -495,7 +495,7 @@ partial def mkProof (lhs rhs : Expr) (H : EntryExpr) (heqProofs : Bool) : CCM Ex getHEqProof a b >>= liftOption else -- TODO(Leo): the following code assumes R is homogeneous. - -- We should add support arbitrary heterogenous reflexive relations. + -- We should add support arbitrary heterogeneous reflexive relations. getEqProof a b >>= liftOption >>= fun aEqb => liftM (liftFromEq R aEqb) let aRbEqTrue ← mkEqTrue aRb if flip then @@ -662,7 +662,7 @@ equality to the todo list. If not, add `e` to the congruence table. -/ def addCongruenceTable (e : Expr) : CCM Unit := do guard e.isApp let k ← mkCongruencesKey e - if let some es := (← get).congruences.find? k then + if let some es := (← get).congruences[k]? then for oldE in es do if ← isCongruent e oldE then -- Found new equivalence: `e ~ oldE` @@ -687,7 +687,7 @@ def addSymmCongruenceTable (e : Expr) : CCM Unit := do let some (rel, lhs, rhs) ← e.relSidesIfSymm? | failure let k ← mkSymmCongruencesKey lhs rhs let newP := (e, rel) - if let some ps := (← get).symmCongruences.find? k then + if let some ps := (← get).symmCongruences[k]? then for p in ps do if ← compareSymm newP p then -- Found new equivalence: `e ~ p.1` @@ -1623,7 +1623,7 @@ def removeParents (e : Expr) (parentsToPropagate : Array Expr := #[]) : CCM (Arr if pocc.symmTable then let some (rel, lhs, rhs) ← p.relSidesIfSymm? | failure let k' ← mkSymmCongruencesKey lhs rhs - if let some lst := (← get).symmCongruences.find? k' then + if let some lst := (← get).symmCongruences[k']? then let k := (p, rel) let newLst ← lst.filterM fun k₂ => (!·) <$> compareSymm k k₂ if !newLst.isEmpty then @@ -1634,7 +1634,7 @@ def removeParents (e : Expr) (parentsToPropagate : Array Expr := #[]) : CCM (Arr { ccs with symmCongruences := ccs.symmCongruences.erase k' } else let k' ← mkCongruencesKey p - if let some es := (← get).congruences.find? k' then + if let some es := (← get).congruences[k']? then let newEs := es.erase p if !newEs.isEmpty then modify fun ccs => @@ -2099,3 +2099,5 @@ def add (type : Expr) (proof : Expr) : CCM Unit := do end CCM end Mathlib.Tactic.CC + +set_option linter.style.longFile 2300 diff --git a/Mathlib/Tactic/CC/Datatypes.lean b/Mathlib/Tactic/CC/Datatypes.lean index 2ea400963f095..6c11094d2ff5a 100644 --- a/Mathlib/Tactic/CC/Datatypes.lean +++ b/Mathlib/Tactic/CC/Datatypes.lean @@ -5,9 +5,9 @@ Authors: Leonardo de Moura, Miyahara Kō -/ import Lean.Meta.CongrTheorems import Lean.Meta.Tactic.Rfl -import Batteries.Data.HashMap.Basic import Batteries.Data.RBMap.Basic import Mathlib.Lean.Meta.Basic +import Std.Data.HashMap.Basic /-! # Datatypes for `cc` @@ -84,7 +84,7 @@ Once the `cc` tactic is used a lot in Mathlib, we should profile and see if `HashSet` could be more optimal. -/ abbrev RBExprSet := Batteries.RBSet Expr compare -/-- `CongrTheorem`s equiped with additional infos used by congruence closure modules. -/ +/-- `CongrTheorem`s equipped with additional infos used by congruence closure modules. -/ structure CCCongrTheorem extends CongrTheorem where /-- If `heqResult` is true, then lemma is based on heterogeneous equality and the conclusion is a heterogeneous equality. -/ @@ -110,7 +110,7 @@ structure CCCongrTheoremKey where deriving BEq, Hashable /-- Caches used to find corresponding `CCCongrTheorem`s. -/ -abbrev CCCongrTheoremCache := Batteries.HashMap CCCongrTheoremKey (Option CCCongrTheorem) +abbrev CCCongrTheoremCache := Std.HashMap CCCongrTheoremKey (Option CCCongrTheorem) /-- Configs used in congruence closure modules. -/ structure CCConfig where @@ -366,7 +366,7 @@ structure Entry where theorem prover. The basic idea is to introduce a counter gmt that records the number of heuristic instantiation that have occurred in the current branch. It is incremented after each round of heuristic instantiation. The field `mt` records the last time any proper descendant - of of thie entry was involved in a merge. -/ + of this entry was involved in a merge. -/ mt : Nat deriving Inhabited @@ -415,7 +415,7 @@ inductive CongruencesKey deriving BEq, Hashable /-- Maps each expression (via `mkCongruenceKey`) to expressions it might be congruent to. -/ -abbrev Congruences := Batteries.HashMap CongruencesKey (List Expr) +abbrev Congruences := Std.HashMap CongruencesKey (List Expr) structure SymmCongruencesKey where (h₁ h₂ : Expr) @@ -426,7 +426,7 @@ structure SymmCongruencesKey where The `Name` identifies which relation the congruence is considered for. Note that this only works for two-argument relations: `ModEq n` and `ModEq m` are considered the same. -/ -abbrev SymmCongruences := Batteries.HashMap SymmCongruencesKey (List (Expr × Name)) +abbrev SymmCongruences := Std.HashMap SymmCongruencesKey (List (Expr × Name)) /-- Stores the root representatives of subsingletons. -/ abbrev SubsingletonReprs := RBExprMap Expr @@ -462,7 +462,7 @@ structure CCState extends CCConfig where /-- Mapping from operators occurring in terms and their canonical representation in this module -/ canOps : RBExprMap Expr := ∅ - /-- Whether the canonical operator is suppoted by AC. -/ + /-- Whether the canonical operator is supported by AC. -/ opInfo : RBExprMap Bool := ∅ /-- Extra `Entry` information used by the AC part of the tactic. -/ acEntries : RBExprMap ACEntry := ∅ @@ -521,7 +521,7 @@ def isCgRoot (ccs : CCState) (e : Expr) : Bool := "Modification Time". The field `mt` is used to implement the mod-time optimization introduced by the Simplify theorem prover. The basic idea is to introduce a counter `gmt` that records the number of heuristic instantiation that have occurred in the current branch. It is incremented after each round -of heuristic instantiation. The field `mt` records the last time any proper descendant of of thie +of heuristic instantiation. The field `mt` records the last time any proper descendant of this entry was involved in a merge. -/ def mt (ccs : CCState) (e : Expr) : Nat := match ccs.entries.find? e with @@ -667,7 +667,7 @@ end CCState /-- The congruence closure module (optionally) uses a normalizer. The idea is to use it (if available) to normalize auxiliary expressions - produced by internal propagation rules (e.g., subsingleton propagator). -/ + produced by internal propagation rules (e.g., subsingleton propagator). -/ structure CCNormalizer where normalize : Expr → MetaM Expr diff --git a/Mathlib/Tactic/CancelDenoms/Core.lean b/Mathlib/Tactic/CancelDenoms/Core.lean index 4ba1bdec9c1cb..89310275c745f 100644 --- a/Mathlib/Tactic/CancelDenoms/Core.lean +++ b/Mathlib/Tactic/CancelDenoms/Core.lean @@ -10,7 +10,6 @@ import Mathlib.Logic.Basic import Mathlib.Tactic.NormNum.Core import Mathlib.Util.SynthesizeUsing import Mathlib.Util.Qq -import Mathlib.Algebra.Order.Field.Unbundled.Basic /-! # A tactic for canceling numeric denominators @@ -70,14 +69,14 @@ theorem cancel_factors_lt {α} [LinearOrderedField α] {a b ad bd a' b' gcd : α (a < b) = (1 / gcd * (bd * a') < 1 / gcd * (ad * b')) := by rw [mul_lt_mul_left, ← ha, ← hb, ← mul_assoc, ← mul_assoc, mul_comm bd, mul_lt_mul_left] · exact mul_pos had hbd - · exact one_div_pos (α := α) |>.2 hgcd + · exact one_div_pos.2 hgcd theorem cancel_factors_le {α} [LinearOrderedField α] {a b ad bd a' b' gcd : α} (ha : ad * a = a') (hb : bd * b = b') (had : 0 < ad) (hbd : 0 < bd) (hgcd : 0 < gcd) : (a ≤ b) = (1 / gcd * (bd * a') ≤ 1 / gcd * (ad * b')) := by rw [mul_le_mul_left, ← ha, ← hb, ← mul_assoc, ← mul_assoc, mul_comm bd, mul_le_mul_left] · exact mul_pos had hbd - · exact one_div_pos (α := α) |>.2 hgcd + · exact one_div_pos.2 hgcd theorem cancel_factors_eq {α} [Field α] {a b ad bd a' b' gcd : α} (ha : ad * a = a') (hb : bd * b = b') (had : ad ≠ 0) (hbd : bd ≠ 0) (hgcd : gcd ≠ 0) : @@ -147,7 +146,7 @@ def synthesizeUsingNormNum (type : Q(Prop)) : MetaM Q($type) := do catch e => throwError "Could not prove {type} using norm_num. {e.toMessageData}" -/-- `CancelResult mα e v'` provies a value for `v * e` where the denominators have been cancelled. +/-- `CancelResult mα e v'` provides a value for `v * e` where the denominators have been cancelled. -/ structure CancelResult {u : Level} {α : Q(Type u)} (mα : Q(Mul $α)) (e : Q($α)) (v : Q($α)) where /-- An expression with denominators cancelled. -/ diff --git a/Mathlib/Tactic/Cases.lean b/Mathlib/Tactic/Cases.lean index 9c917e8d070eb..34ad80c027727 100644 --- a/Mathlib/Tactic/Cases.lean +++ b/Mathlib/Tactic/Cases.lean @@ -6,6 +6,7 @@ Authors: Mario Carneiro import Lean.Elab.Tactic.Induction import Batteries.Tactic.OpenPrivate import Mathlib.Lean.Expr.Basic +import Batteries.Data.List.Basic /-! # Backward compatible implementation of lean 3 `cases` tactic diff --git a/Mathlib/Tactic/CategoryTheory/Reassoc.lean b/Mathlib/Tactic/CategoryTheory/Reassoc.lean index d83662642b472..eedc010454f06 100644 --- a/Mathlib/Tactic/CategoryTheory/Reassoc.lean +++ b/Mathlib/Tactic/CategoryTheory/Reassoc.lean @@ -29,7 +29,7 @@ namespace CategoryTheory variable {C : Type*} [Category C] -/-- A variant of `eq_whisker` with a more convenient argument order for use in tactics. -/ +/-- A variant of `eq_whisker` with a more convenient argument order for use in tactics. -/ theorem eq_whisker' {X Y : C} {f g : X ⟶ Y} (w : f = g) {Z : C} (h : Y ⟶ Z) : f ≫ h = g ≫ h := by rw [w] diff --git a/Mathlib/Tactic/Common.lean b/Mathlib/Tactic/Common.lean index 53c1b1a4c238f..eb2b980c73313 100644 --- a/Mathlib/Tactic/Common.lean +++ b/Mathlib/Tactic/Common.lean @@ -13,6 +13,7 @@ import ImportGraph.Imports -- Import common Batteries tactics and commands import Batteries.Tactic.Where +import Batteries.Tactic.Basic -- Import Mathlib-specific linters. import Mathlib.Tactic.Linter.Lint diff --git a/Mathlib/Tactic/CongrExclamation.lean b/Mathlib/Tactic/CongrExclamation.lean index 8bf7ba9cc9af7..93901abe7dd66 100644 --- a/Mathlib/Tactic/CongrExclamation.lean +++ b/Mathlib/Tactic/CongrExclamation.lean @@ -583,7 +583,7 @@ def Lean.MVarId.preCongr! (mvarId : MVarId) (tryClose : Bool) : MetaM (Option MV -- We allow synthetic opaque metavariables to be assigned to fill in `x = _` goals that might -- appear (for example, due to using `convert` with placeholders). try withAssignableSyntheticOpaque mvarId.refl; return none catch _ => pure () - -- Now we go for (heterogenous) equality via subsingleton considerations + -- Now we go for (heterogeneous) equality via subsingleton considerations if ← Lean.Meta.fastSubsingletonElim mvarId then return none if ← mvarId.proofIrrelHeq then return none return some mvarId diff --git a/Mathlib/Tactic/ContinuousFunctionalCalculus.lean b/Mathlib/Tactic/ContinuousFunctionalCalculus.lean index 0adbd41b52a2f..9eca49727383c 100644 --- a/Mathlib/Tactic/ContinuousFunctionalCalculus.lean +++ b/Mathlib/Tactic/ContinuousFunctionalCalculus.lean @@ -15,11 +15,17 @@ import Aesop At the moment, these tactics are just wrappers, but potentially they could be more sophisticated. -/ +declare_aesop_rule_sets [CStarAlgebra] + /-- A tactic used to automatically discharge goals relating to the continuous functional calculus, specifically whether the element satisfies the predicate. -/ syntax (name := cfcTac) "cfc_tac" : tactic macro_rules - | `(tactic| cfc_tac) => `(tactic| (try (first | assumption | infer_instance | aesop))) + | `(tactic| cfc_tac) => `(tactic| + try (first | + assumption | + infer_instance | + aesop (rule_sets := [$(Lean.mkIdent `CStarAlgebra):ident]))) -- we may want to try using `fun_prop` directly in the future. /-- A tactic used to automatically discharge goals relating to the continuous functional calculus, @@ -28,11 +34,14 @@ syntax (name := cfcContTac) "cfc_cont_tac" : tactic macro_rules | `(tactic| cfc_cont_tac) => `(tactic| try (first - | fun_prop (disch := aesop (config := {warnOnNonterminal := false})) + | fun_prop (disch := aesop (config := {warnOnNonterminal := false}) + (rule_sets := [$(Lean.mkIdent `CStarAlgebra):ident])) | assumption)) /-- A tactic used to automatically discharge goals relating to the non-unital continuous functional calculus, specifically concerning whether `f 0 = 0`. -/ syntax (name := cfcZeroTac) "cfc_zero_tac" : tactic macro_rules - | `(tactic| cfc_zero_tac) => `(tactic| try (first | aesop | assumption)) + | `(tactic| cfc_zero_tac) => + `(tactic| try + (first | aesop (rule_sets := [$(Lean.mkIdent `CStarAlgebra):ident]) | assumption)) diff --git a/Mathlib/Tactic/DefEqTransformations.lean b/Mathlib/Tactic/DefEqTransformations.lean index f84e06c214a9f..1bd541cc82ae7 100644 --- a/Mathlib/Tactic/DefEqTransformations.lean +++ b/Mathlib/Tactic/DefEqTransformations.lean @@ -247,7 +247,7 @@ elab "eta_reduce" : conv => runDefEqConvTactic etaReduceAll /-- Eta expand every sub-expression in the given expression. -As a side-effect, beta reduces any pre-existing instances of eta expanded terms. -/ +As a side-effect, beta reduces any pre-existing instances of eta expanded terms. -/ partial def etaExpandAll (e : Expr) : MetaM Expr := do let betaOrApp (f : Expr) (args : Array Expr) : Expr := if f.etaExpanded?.isSome then f.beta args else mkAppN f args diff --git a/Mathlib/Tactic/DeriveTraversable.lean b/Mathlib/Tactic/DeriveTraversable.lean index 147e79d3bde4c..9b4bba79c6c92 100644 --- a/Mathlib/Tactic/DeriveTraversable.lean +++ b/Mathlib/Tactic/DeriveTraversable.lean @@ -55,7 +55,7 @@ def mapField (n : Name) (cl f α β e : Expr) : TermElabM Expr := do return e /-- Get the auxiliary local declaration corresponding to the current declaration. If there are -multiple declaraions it will throw. -/ +multiple declarations it will throw. -/ def getAuxDefOfDeclName : TermElabM FVarId := do let some declName ← getDeclName? | throwError "no 'declName?'" let auxDeclMap := (← read).auxDeclToFullName diff --git a/Mathlib/Tactic/Explode.lean b/Mathlib/Tactic/Explode.lean index ee85b52734aea..d8c2f0dc5f172 100644 --- a/Mathlib/Tactic/Explode.lean +++ b/Mathlib/Tactic/Explode.lean @@ -115,7 +115,7 @@ partial def explodeCore (e : Expr) (depth : Nat) (entries : Entries) (start : Bo let entries := valEntry?.map (entries.addSynonym var) |>.getD entries explodeCore (body.instantiate1 var) depth entries | _ => do - -- Right now all of these are caught by this case case: + -- Right now all of these are caught by this case: -- Expr.lit, Expr.forallE, Expr.const, Expr.sort, Expr.mvar, Expr.fvar, Expr.bvar -- (Note: Expr.mdata is stripped by cleanupAnnotations) -- Might be good to handle them individually. diff --git a/Mathlib/Tactic/Explode/Datatypes.lean b/Mathlib/Tactic/Explode/Datatypes.lean index 2572429fcd5e5..1379a9f398989 100644 --- a/Mathlib/Tactic/Explode/Datatypes.lean +++ b/Mathlib/Tactic/Explode/Datatypes.lean @@ -66,7 +66,7 @@ structure Entries : Type where /-- Find a row where `Entry.expr` == `e`. -/ def Entries.find? (es : Entries) (e : Expr) : Option Entry := - es.s.find? e + es.s[e]? /-- Length of our entries. -/ def Entries.size (es : Entries) : Nat := diff --git a/Mathlib/Tactic/FBinop.lean b/Mathlib/Tactic/FBinop.lean index 590322600e3c9..01903971c62dd 100644 --- a/Mathlib/Tactic/FBinop.lean +++ b/Mathlib/Tactic/FBinop.lean @@ -206,7 +206,7 @@ where let type ← instantiateMVars (← inferType e) trace[Elab.fbinop] "visiting {e} : {type}" let some (_, x) ← extractS type - | -- We want our operators to be "homogenous" so do a defeq check as an elaboration hint + | -- We want our operators to be "homogeneous" so do a defeq check as an elaboration hint let x' ← mkFreshExprMVar none let some maxType ← applyS maxS x' | trace[Elab.fbinop] "mvar apply failed"; return t trace[Elab.fbinop] "defeq hint {maxType} =?= {type}" diff --git a/Mathlib/Tactic/FinCases.lean b/Mathlib/Tactic/FinCases.lean index 90da0519ec7cb..493404b8844af 100644 --- a/Mathlib/Tactic/FinCases.lean +++ b/Mathlib/Tactic/FinCases.lean @@ -60,7 +60,7 @@ partial def finCasesAt (g : MVarId) (hyp : FVarId) : MetaM (List MVarId) := g.wi -- Deal with `x : A`, where `[Fintype A]` is available: let inst ← synthInstance (← mkAppM ``Fintype #[type]) let elems ← mkAppOptM ``Fintype.elems #[type, inst] - let t ← mkAppM ``Membership.mem #[.fvar hyp, elems] + let t ← mkAppM ``Membership.mem #[elems, .fvar hyp] let v ← mkAppOptM ``Fintype.complete #[type, inst, Expr.fvar hyp] let (fvar, g) ← (← g.assert `this t v).intro1P finCasesAt g fvar diff --git a/Mathlib/Tactic/Find.lean b/Mathlib/Tactic/Find.lean index 6d91737566f29..6e411fa824810 100644 --- a/Mathlib/Tactic/Find.lean +++ b/Mathlib/Tactic/Find.lean @@ -23,7 +23,7 @@ or the `find` tactic which looks for lemmas which are `apply`able against the cu -/ -open Lean +open Lean Std open Lean.Meta open Lean.Elab open Lean.Elab @@ -51,7 +51,7 @@ private def isBlackListed (declName : Name) : MetaM Bool := do <||> isRec declName <||> isMatcher declName -initialize findDeclsPerHead : DeclCache (Lean.HashMap HeadIndex (Array Name)) ← +initialize findDeclsPerHead : DeclCache (Std.HashMap HeadIndex (Array Name)) ← DeclCache.mk "#find: init cache" failure {} fun _ c headMap ↦ do if (← isBlackListed c.name) then return headMap @@ -59,7 +59,7 @@ initialize findDeclsPerHead : DeclCache (Lean.HashMap HeadIndex (Array Name)) -- to avoid leaking metavariables. let (_, _, ty) ← forallMetaTelescopeReducing c.type let head := ty.toHeadIndex - pure <| headMap.insert head (headMap.findD head #[] |>.push c.name) + pure <| headMap.insert head (headMap.getD head #[] |>.push c.name) def findType (t : Expr) : TermElabM Unit := withReducible do let t ← instantiateMVars t @@ -68,7 +68,7 @@ def findType (t : Expr) : TermElabM Unit := withReducible do let env ← getEnv let mut numFound := 0 - for n in (← findDeclsPerHead.get).findD head #[] do + for n in (← findDeclsPerHead.get).getD head #[] do let c := env.find? n |>.get! let cTy := c.instantiateTypeLevelParams (← mkFreshLevelMVars c.numLevelParams) let found ← forallTelescopeReducing cTy fun cParams cTy' ↦ do diff --git a/Mathlib/Tactic/FunProp/ContDiff.lean b/Mathlib/Tactic/FunProp/ContDiff.lean index 636f5fa0db5bf..adc20fffe2b95 100644 --- a/Mathlib/Tactic/FunProp/ContDiff.lean +++ b/Mathlib/Tactic/FunProp/ContDiff.lean @@ -81,7 +81,7 @@ variable {F : Type*} [NormedAddCommGroup F] [NormedSpace K F] and `funProp` can't work with such theorem. The theorem should be state where `n` is explicitly the smallest possible value i.e. `n=m+1`. -In conjunction with `ContDiff.of_le` we can recover the full power of the original theorem. -/ +In conjunction with `ContDiff.of_le` we can recover the full power of the original theorem. -/ theorem ContDiff.differentiable_iteratedDeriv' {m : ℕ} {f : K → F} (hf : ContDiff K (m+1) f) : Differentiable K (iteratedDeriv m f) := ContDiff.differentiable_iteratedDeriv m hf (Nat.cast_lt.mpr m.lt_succ_self) diff --git a/Mathlib/Tactic/FunProp/Core.lean b/Mathlib/Tactic/FunProp/Core.lean index 03d0b6b5c6a57..abc5b5c1952c1 100644 --- a/Mathlib/Tactic/FunProp/Core.lean +++ b/Mathlib/Tactic/FunProp/Core.lean @@ -31,7 +31,7 @@ def synthesizeInstance (thmId : Origin) (x type : Expr) : MetaM Bool := do else trace[Meta.Tactic.fun_prop] "{← ppOrigin thmId}, failed to assign instance{indentExpr type} -sythesized value{indentExpr val}\nis not definitionally equal to{indentExpr x}" +synthesized value{indentExpr val}\nis not definitionally equal to{indentExpr x}" return false | _ => trace[Meta.Tactic.fun_prop] @@ -39,28 +39,23 @@ sythesized value{indentExpr val}\nis not definitionally equal to{indentExpr x}" return false -/-- Synthesize arguments `xs` either with typeclass synthesis, -with `fun_prop` or with a discharger. -/ -def synthesizeArgs (thmId : Origin) (xs : Array Expr) (bis : Array BinderInfo) + +/-- Synthesize arguments `xs` either with typeclass synthesis, with `fun_prop` or with +discharger. -/ +def synthesizeArgs (thmId : Origin) (xs : Array Expr) (funProp : Expr → FunPropM (Option Result)) : FunPropM Bool := do let mut postponed : Array Expr := #[] - for x in xs, bi in bis do + for x in xs do let type ← inferType x - if bi.isInstImplicit then - unless (← synthesizeInstance thmId x type) do - logError s!"Failed to synthesize instance `{← ppExpr type}` \ - when applying theorem `{← ppOrigin' thmId}`." - return false - else if (← instantiateMVars x).isMVar then + if (← instantiateMVars x).isMVar then -- try type class if (← isClass? type).isSome then if (← synthesizeInstance thmId x type) then continue - - -- try function property - if (← isFunProp type.getForallBody) then + else if (← isFunProp type.getForallBody) then + -- try function property if let .some ⟨proof⟩ ← funProp type then if (← isDefEq x proof) then continue @@ -104,14 +99,14 @@ def synthesizeArgs (thmId : Origin) (xs : Array Expr) (bis : Array BinderInfo) /-- Try to apply theorem - core function -/ -def tryTheoremCore (xs : Array Expr) (bis : Array BinderInfo) (val : Expr) (type : Expr) (e : Expr) +def tryTheoremCore (xs : Array Expr) (val : Expr) (type : Expr) (e : Expr) (thmId : Origin) (funProp : Expr → FunPropM (Option Result)) : FunPropM (Option Result) := do withTraceNode `Meta.Tactic.fun_prop (fun r => return s!"[{ExceptToEmoji.toEmoji r}] applying: {← ppOrigin' thmId}") do if (← isDefEq type e) then - if ¬(← synthesizeArgs thmId xs bis funProp) then + if ¬(← synthesizeArgs thmId xs funProp) then return none let proof ← instantiateMVars (mkAppN val xs) @@ -129,7 +124,7 @@ def tryTheoremWithHint? (e : Expr) (thmOrigin : Origin) let go : FunPropM (Option Result) := do let thmProof ← thmOrigin.getValue let type ← inferType thmProof - let (xs, bis, type) ← forallMetaTelescope type + let (xs, _, type) ← forallMetaTelescope type for (i,x) in hint do try @@ -139,7 +134,7 @@ def tryTheoremWithHint? (e : Expr) (thmOrigin : Origin) trace[Meta.Tactic.fun_trans] "failed to use hint {i} `{← ppExpr x} when applying theorem {← ppOrigin thmOrigin}" - tryTheoremCore xs bis thmProof type e thmOrigin funProp + tryTheoremCore xs thmProof type e thmOrigin funProp -- `simp` introduces new meta variable context depth for some reason -- This is probably to avoid mvar assignment when trying a theorem fails @@ -149,7 +144,7 @@ def tryTheoremWithHint? (e : Expr) (thmOrigin : Origin) -- hypothesis `(h : ContDiff ℝ ∞ f)` and assign `∞` to the mvar `?n`. -- -- This could be problematic if there are two local hypothesis `(hinf : ContDiff ℝ ∞ f)` and - -- `(h1 : ContDiff ℝ 1 f)` and appart from solving `ContDiff ℝ ?n f` there is also a subgoal + -- `(h1 : ContDiff ℝ 1 f)` and apart from solving `ContDiff ℝ ?n f` there is also a subgoal -- `2 ≤ ?n`. If `fun_prop` decides to try `h1` first it would assign `1` to `?n` and then there -- is no hope solving `2 ≤ 1` and it won't be able to apply `hinf` after trying `h1` as `n?` is -- assigned already. Ideally `fun_prop` would roll back the `MetaM.State`. This issue did not @@ -199,7 +194,6 @@ def applyConstRule (funPropDecl : FunPropDecl) (e : Expr) logError msg trace[Meta.Tactic.fun_prop] msg return none - for thm in thms do let .const := thm.thmArgs | return none if let .some r ← tryTheorem? e (.decl thm.thmName) funProp then @@ -215,7 +209,6 @@ For example, `e = q(Continuous fun f => f x)` and `funPropDecl` is `FunPropDecl` def applyApplyRule (funPropDecl : FunPropDecl) (e : Expr) (funProp : Expr → FunPropM (Option Result)) : FunPropM (Option Result) := do let thms := (← getLambdaTheorems funPropDecl.funPropName .apply) - for thm in thms do if let .some r ← tryTheoremWithHint? e (.decl thm.thmName) #[] funProp then return r @@ -228,7 +221,7 @@ Try to prove `e` using *composition lambda theorem*. For example, `e = q(Continuous fun x => f (g x))` and `funPropDecl` is `FunPropDecl` for `Continuous` -You also have to provide the functions `f` and `g`. -/ +You also have to provide the functions `f` and `g`. -/ def applyCompRule (funPropDecl : FunPropDecl) (e f g : Expr) (funProp : Expr → FunPropM (Option Result)) : FunPropM (Option Result) := do @@ -324,7 +317,7 @@ def applyMorRules (funPropDecl : FunPropDecl) (e : Expr) (fData : FunctionData) trace[Debug.Meta.Tactic.fun_prop] "applying morphism theorems to {← ppExpr e}" match ← fData.isMorApplication with - | .none => throwError "fun_prop bug: ivalid use of mor rules on {← ppExpr e}" + | .none => throwError "fun_prop bug: invalid use of mor rules on {← ppExpr e}" | .underApplied => applyPiRule funPropDecl e funProp | .overApplied => @@ -346,7 +339,7 @@ def applyMorRules (funPropDecl : FunPropDecl) (e : Expr) (fData : FunctionData) trace[Debug.Meta.Tactic.fun_prop] "no theorem matched" return none -/-- Prove function property of using *transition theorems*. -/ +/-- Prove function property of using *transition theorems*. -/ def applyTransitionRules (e : Expr) (funProp : Expr → FunPropM (Option Result)) : FunPropM (Option Result) := do withIncreasedTransitionDepth do diff --git a/Mathlib/Tactic/FunProp/FunctionData.lean b/Mathlib/Tactic/FunProp/FunctionData.lean index 158fcddfe23b1..88e61d9592bbd 100644 --- a/Mathlib/Tactic/FunProp/FunctionData.lean +++ b/Mathlib/Tactic/FunProp/FunctionData.lean @@ -41,7 +41,7 @@ def FunctionData.toExpr (f : FunctionData) : MetaM Expr := do let body := Mor.mkAppN f.fn f.args mkLambdaFVars #[f.mainVar] body -/-- Is `f` an indentity function? -/ +/-- Is `f` an identity function? -/ def FunctionData.isIdentityFun (f : FunctionData) : Bool := (f.args.size = 0 && f.fn == f.mainVar) diff --git a/Mathlib/Tactic/FunProp/Mor.lean b/Mathlib/Tactic/FunProp/Mor.lean index b9dd93ed43ec6..4ac97d317ff1c 100644 --- a/Mathlib/Tactic/FunProp/Mor.lean +++ b/Mathlib/Tactic/FunProp/Mor.lean @@ -29,12 +29,12 @@ namespace Meta.FunProp namespace Mor -/-- Is `name` a coerction from some function space to functiosn? -/ +/-- Is `name` a coerction from some function space to functions? -/ def isCoeFunName (name : Name) : CoreM Bool := do let .some info ← getCoeFnInfo? name | return false return info.type == .coeFun -/-- Is `e` a coerction from some function space to functiosn? -/ +/-- Is `e` a coerction from some function space to functions? -/ def isCoeFun (e : Expr) : MetaM Bool := do let .some (name,_) := e.getAppFn.const? | return false let .some info ← getCoeFnInfo? name | return false @@ -89,7 +89,7 @@ Weak normal head form of an expression involving morphism applications. For example calling this on `coe (f a) b` will put `f` in weak normal head form instead of `coe`. -/ -def whnf (e : Expr) (cfg : WhnfCoreConfig := {}) : MetaM Expr := +def whnf (e : Expr) (cfg : WhnfCoreConfig := {}) : MetaM Expr := whnfPred e (fun _ => return false) cfg diff --git a/Mathlib/Tactic/FunProp/RefinedDiscrTree.lean b/Mathlib/Tactic/FunProp/RefinedDiscrTree.lean index d5194c0971c73..da93ffa29a9af 100644 --- a/Mathlib/Tactic/FunProp/RefinedDiscrTree.lean +++ b/Mathlib/Tactic/FunProp/RefinedDiscrTree.lean @@ -47,7 +47,7 @@ I document here what features are not in the original: For example, matching `(1 + 2) + 3` with `add_comm` gives a score of 2, since the pattern of commutativity is [⟨HAdd.hAdd, 6⟩, *0, *0, *0, *1, *2, *3], so matching `⟨HAdd.hAdd, 6⟩` gives 1 point, - and matching `*0` after its first appearence gives another point, but the third argument is an + and matching `*0` after its first appearance gives another point, but the third argument is an outParam, so this gets ignored. Similarly, matching it with `add_assoc` gives a score of 5. - Patterns that have the potential to be η-reduced are put into the `RefinedDiscrTree` under all @@ -282,7 +282,7 @@ inductive DTExpr where | opaque : DTExpr /-- A constant. It stores the name and the arguments. -/ | const : Name → Array DTExpr → DTExpr - /-- A free variable. It stores the `FVarId` and the argumenst -/ + /-- A free variable. It stores the `FVarId` and the arguments -/ | fvar : FVarId → Array DTExpr → DTExpr /-- A bound variable. It stores the De Bruijn index and the arguments -/ | bvar : Nat → Array DTExpr → DTExpr @@ -530,10 +530,9 @@ def etaExpand (args : Array Expr) (type : Expr) (lambdas : List FVarId) (goalAri etaExpand (args.push fvar) type (fvar.fvarId! :: lambdas) goalArity k else k args lambdas -termination_by goalArity - args.size -/-- Normalize an application of a heterogenous binary operator like `HAdd.hAdd`, using: +/-- Normalize an application of a heterogeneous binary operator like `HAdd.hAdd`, using: - `f = fun x => f x` to increase the arity to 6 - `(f + g) a = f a + g a` to decrease the arity to 6 - `(fun x => f x + g x) = f + g` to get rid of any lambdas in front -/ @@ -883,7 +882,6 @@ where loop (i+1) else vs.push v -termination_by vs.size - i /-- Insert the value `v` at index `keys : Array Key` in a `Trie`. -/ partial def insertInTrie [BEq α] (keys : Array Key) (v : α) (i : Nat) : Trie α → Trie α @@ -909,7 +907,7 @@ partial def insertInTrie [BEq α] (keys : Array Key) (v : α) (i : Nat) : Trie /-- Insert the value `v` at index `keys : Array Key` in a `RefinedDiscrTree`. -Warning: to accound for η-reduction, an entry may need to be added at multiple indexes, +Warning: to account for η-reduction, an entry may need to be added at multiple indexes, so it is recommended to use `RefinedDiscrTree.insert` for insertion. -/ def insertInRefinedDiscrTree [BEq α] (d : RefinedDiscrTree α) (keys : Array Key) (v : α) : RefinedDiscrTree α := @@ -924,7 +922,7 @@ def insertInRefinedDiscrTree [BEq α] (d : RefinedDiscrTree α) (keys : Array Ke /-- Insert the value `v` at index `e : DTExpr` in a `RefinedDiscrTree`. -Warning: to accound for η-reduction, an entry may need to be added at multiple indexes, +Warning: to account for η-reduction, an entry may need to be added at multiple indexes, so it is recommended to use `RefinedDiscrTree.insert` for insertion. -/ def insertDTExpr [BEq α] (d : RefinedDiscrTree α) (e : DTExpr) (v : α) : RefinedDiscrTree α := insertInRefinedDiscrTree d e.flatten v diff --git a/Mathlib/Tactic/FunProp/ToBatteries.lean b/Mathlib/Tactic/FunProp/ToBatteries.lean index f553da7935be3..0f46a33e449ee 100644 --- a/Mathlib/Tactic/FunProp/ToBatteries.lean +++ b/Mathlib/Tactic/FunProp/ToBatteries.lean @@ -35,7 +35,7 @@ def isOrderedSubsetOf {α} [Inhabited α] [DecidableEq α] (a b : Array α) : Bo private def letTelescopeImpl {α} (e : Expr) (k : Array Expr → Expr → MetaM α) : MetaM α := - lambdaLetTelescope e λ xs b => do + lambdaLetTelescope e fun xs b ↦ do if let .some i ← xs.findIdxM? (fun x ↦ do pure ¬(← x.fvarId!.isLetVar)) then k xs[0:i] (← mkLambdaFVars xs[i:] b) else @@ -98,18 +98,18 @@ def mkProdProj (x : Expr) (i : Nat) (n : Nat) : MetaM Expr := do i.e. `#[xs.1, xs.2.1, xs.2.2.1, ..., xs.2..2]` -/ def mkProdSplitElem (xs : Expr) (n : Nat) : MetaM (Array Expr) := (Array.range n) - |>.mapM (λ i => mkProdProj xs i n) + |>.mapM (fun i ↦ mkProdProj xs i n) /-- Uncurry function `f` in `n` arguments. -/ def mkUncurryFun (n : Nat) (f : Expr) : MetaM Expr := do if n ≤ 1 then return f - forallBoundedTelescope (← inferType f) n λ xs _ => do - let xProdName : String ← xs.foldlM (init:="") λ n x => + forallBoundedTelescope (← inferType f) n fun xs _ ↦ do + let xProdName : String ← xs.foldlM (init:="") fun n x ↦ do return (n ++ toString (← x.fvarId!.getUserName).eraseMacroScopes) let xProdType ← inferType (← mkProdElem xs) - withLocalDecl (.mkSimple xProdName) default xProdType λ xProd => do + withLocalDecl (.mkSimple xProdName) default xProdType fun xProd ↦ do let xs' ← mkProdSplitElem xProd n mkLambdaFVars #[xProd] (← mkAppM' f xs').headBeta diff --git a/Mathlib/Tactic/FunProp/Types.lean b/Mathlib/Tactic/FunProp/Types.lean index 27036b17bce46..6f12b788e1928 100644 --- a/Mathlib/Tactic/FunProp/Types.lean +++ b/Mathlib/Tactic/FunProp/Types.lean @@ -67,7 +67,7 @@ def defaultNamesToUnfold : Array Name := /-- `fun_prop` configuration -/ structure Config where - /-- Maximum number of transitions between function properties. For example infering continuity + /-- Maximum number of transitions between function properties. For example inferring continuity from differentiability and then differentiability from smoothness (`ContDiff ℝ ∞`) requires `maxTransitionDepth = 2`. The default value of one expects that transition theorems are transitively closed e.g. there is a transition theorem that infers continuity directly from @@ -153,7 +153,7 @@ function property like continuity from another property like differentiability. The main reason is that if the user forgets to add a continuity theorem for function `foo` then `fun_prop` should report that there is a continuity theorem for `foo` missing. If we would log messages `transitionDepth > 0` then user will see messages saying that there is a missing theorem -for differentiability, smoothness, ... for `foo`. -/ +for differentiability, smoothness, ... for `foo`. -/ def logError (msg : String) : FunPropM Unit := do if (← read).transitionDepth = 0 then modify fun s => diff --git a/Mathlib/Tactic/GCongr/Core.lean b/Mathlib/Tactic/GCongr/Core.lean index 67a7dc94d4836..eeafb8d0cd02b 100644 --- a/Mathlib/Tactic/GCongr/Core.lean +++ b/Mathlib/Tactic/GCongr/Core.lean @@ -134,9 +134,9 @@ structure GCongrLemma where /-- Environment extension for "generalized congruence" (`gcongr`) lemmas. -/ initialize gcongrExt : SimpleScopedEnvExtension ((Name × Name × Array Bool) × GCongrLemma) - (HashMap (Name × Name × Array Bool) (Array GCongrLemma)) ← + (Std.HashMap (Name × Name × Array Bool) (Array GCongrLemma)) ← registerSimpleScopedEnvExtension { - addEntry := fun m (n, lem) => m.insert n ((m.findD n #[]).push lem) + addEntry := fun m (n, lem) => m.insert n ((m.getD n #[]).push lem) initial := {} } @@ -363,7 +363,7 @@ partial def _root_.Lean.MVarId.gcongr -- Look up the `@[gcongr]` lemmas whose conclusion has the same relation and head function as -- the goal and whether the boolean-array of varying/nonvarying arguments of such -- a lemma matches `varyingArgs`. - for lem in (gcongrExt.getState (← getEnv)).findD (relName, lhsHead, varyingArgs) #[] do + for lem in (gcongrExt.getState (← getEnv)).getD (relName, lhsHead, varyingArgs) #[] do let gs ← try -- Try `apply`-ing such a lemma to the goal. Except.ok <$> g.apply (← mkConstWithFreshMVarLevels lem.declName) diff --git a/Mathlib/Tactic/GeneralizeProofs.lean b/Mathlib/Tactic/GeneralizeProofs.lean index 8bb825b5909f9..7acd8bef29e3e 100644 --- a/Mathlib/Tactic/GeneralizeProofs.lean +++ b/Mathlib/Tactic/GeneralizeProofs.lean @@ -109,10 +109,10 @@ def MGen.runMAbs {α : Type} (mx : MAbs α) : MGen (α × Array (Expr × Expr)) Finds a proof of `prop` by looking at `propToFVar` and `propToProof`. -/ def MAbs.findProof? (prop : Expr) : MAbs (Option Expr) := do - if let some pf := (← read).propToFVar.find? prop then + if let some pf := (← read).propToFVar[prop]? then return pf else - return (← get).propToProof.find? prop + return (← get).propToProof[prop]? /-- Generalize `prop`, where `proof` is its proof. @@ -152,7 +152,7 @@ def appArgExpectedTypes (f : Expr) (args : Array Expr) (ty? : Option Expr) : -- Try using the expected type, but (*) below might find a bad solution (guard ty?.isSome *> go f args ty?) <|> go f args none where - /-- Core implementation for `appArgExpectedTypes`. -/ + /-- Core implementation for `appArgExpectedTypes`. -/ go (f : Expr) (args : Array Expr) (ty? : Option Expr) : MetaM (Array (Option Expr)) := do -- Metavariables for each argument to `f`: let mut margs := #[] @@ -355,14 +355,14 @@ partial def withGeneralizedProofs {α : Type} [Inhabited α] (e : Expr) (ty? : O (proofToFVar propToFVar : ExprMap Expr) : MGen α := do if h : i < generalizations.size then let (ty, pf) := generalizations[i] - let ty := (← instantiateMVars (ty.replace proofToFVar.find?)).cleanupAnnotations + let ty := (← instantiateMVars (ty.replace proofToFVar.get?)).cleanupAnnotations withLocalDeclD (← mkFreshUserName `pf) ty fun fvar => do go (i + 1) (fvars := fvars.push fvar) (pfs := pfs.push pf) (proofToFVar := proofToFVar.insert pf fvar) (propToFVar := propToFVar.insert ty fvar) else withNewLocalInstances fvars 0 do - let e' := e.replace proofToFVar.find? + let e' := e.replace proofToFVar.get? trace[Tactic.generalize_proofs] "after: e' = {e}" modify fun s => { s with propToFVar } k fvars pfs e' @@ -395,7 +395,7 @@ where let g' ← mkFreshExprSyntheticOpaqueMVar tgt' tag g.assign <| .app g' tgt.letValue! return ← go g'.mvarId! i hs - if let some pf := (← get).propToFVar.find? ty then + if let some pf := (← get).propToFVar[ty]? then -- Eliminate this local hypothesis using the pre-existing proof, using proof irrelevance let tgt' := tgt.bindingBody!.instantiate1 pf let g' ← mkFreshExprSyntheticOpaqueMVar tgt' tag diff --git a/Mathlib/Tactic/HelpCmd.lean b/Mathlib/Tactic/HelpCmd.lean index 5587ad008455a..1dafab19653f5 100644 --- a/Mathlib/Tactic/HelpCmd.lean +++ b/Mathlib/Tactic/HelpCmd.lean @@ -69,7 +69,7 @@ private def elabHelpOption (id : Option Ident) : CommandElabM Unit := do | .ofInt val => s!"Int := {repr val}" | .ofSyntax val => s!"Syntax := {repr val}" if let some val := opts.find (.mkSimple name) then - msg1 := s!"{msg1} (currently: {val})" + msg1 := s!"{msg1} (currently: {val})" msg := msg ++ .nest 2 (f!"option {name} : {msg1}" ++ .line ++ decl.descr) ++ .line ++ .line logInfo msg diff --git a/Mathlib/Tactic/IrreducibleDef.lean b/Mathlib/Tactic/IrreducibleDef.lean index 2d3987da6409c..bfdf7272c85bd 100644 --- a/Mathlib/Tactic/IrreducibleDef.lean +++ b/Mathlib/Tactic/IrreducibleDef.lean @@ -50,7 +50,7 @@ local elab "eta_helper " t:term : term => do let lhs := (mkAppN lhs xs).headBeta mkForallFVars xs <|← mkEq lhs rhs -/-- `val_proj x` elabs to the *primitive projection* `@x.val`. -/ +/-- `val_proj x` elabs to the *primitive projection* `@x.val`. -/ local elab "val_proj " e:term : term => do let e ← elabTerm (← `(($e : Subtype _))) none return mkProj ``Subtype 0 e diff --git a/Mathlib/Tactic/Linarith/Datatypes.lean b/Mathlib/Tactic/Linarith/Datatypes.lean index 5e0832bb5836a..d34b1f949f653 100644 --- a/Mathlib/Tactic/Linarith/Datatypes.lean +++ b/Mathlib/Tactic/Linarith/Datatypes.lean @@ -6,6 +6,7 @@ Authors: Robert Y. Lewis import Mathlib.Tactic.Linarith.Lemmas import Mathlib.Tactic.Ring.Basic import Mathlib.Util.SynthesizeUsing +import Batteries.Data.HashMap.Basic /-! # Datatypes for `linarith` diff --git a/Mathlib/Tactic/Linarith/Lemmas.lean b/Mathlib/Tactic/Linarith/Lemmas.lean index 44ee9f4ba3c58..9105528b9c4ec 100644 --- a/Mathlib/Tactic/Linarith/Lemmas.lean +++ b/Mathlib/Tactic/Linarith/Lemmas.lean @@ -8,7 +8,7 @@ import Mathlib.Algebra.Order.Monoid.Unbundled.Basic import Mathlib.Algebra.Order.Ring.Defs import Mathlib.Algebra.Order.ZeroLEOne import Mathlib.Data.Nat.Cast.Order.Ring -import Mathlib.Init.Data.Int.Order +import Mathlib.Data.Int.Order.Basic /-! # Lemmas for `linarith`. diff --git a/Mathlib/Tactic/Linarith/Oracle/SimplexAlgorithm/Datatypes.lean b/Mathlib/Tactic/Linarith/Oracle/SimplexAlgorithm/Datatypes.lean index 986bb5ed40031..8a5a9488ae1a9 100644 --- a/Mathlib/Tactic/Linarith/Oracle/SimplexAlgorithm/Datatypes.lean +++ b/Mathlib/Tactic/Linarith/Oracle/SimplexAlgorithm/Datatypes.lean @@ -4,8 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Vasily Nesterov -/ import Mathlib.Init -import Lean.Data.HashMap import Batteries.Data.Rat.Basic +import Std.Data.HashMap.Basic /-! # Datatypes for the Simplex Algorithm implementation @@ -82,10 +82,10 @@ values. -/ structure SparseMatrix (n m : Nat) where /-- The content of the matrix. -/ - data : Array <| Lean.HashMap Nat Rat + data : Array <| Std.HashMap Nat Rat instance : UsableInSimplexAlgorithm SparseMatrix where - getElem mat i j := mat.data[i]!.findD j 0 + getElem mat i j := mat.data[i]!.getD j 0 setElem mat i j v := if v == 0 then ⟨mat.data.modify i fun row => row.erase j⟩ @@ -96,7 +96,7 @@ instance : UsableInSimplexAlgorithm SparseMatrix where let rowVals := row.toList.map fun (j, v) => (i, j, v) rowVals ++ acc ofValues {n _ : Nat} vals := Id.run do - let mut data : Array (Lean.HashMap Nat Rat) := Array.mkArray n .empty + let mut data : Array (Std.HashMap Nat Rat) := Array.mkArray n .empty for ⟨i, j, v⟩ in vals do if v != 0 then data := data.modify i fun row => row.insert j v @@ -105,12 +105,12 @@ instance : UsableInSimplexAlgorithm SparseMatrix where subtractRow mat i j coef := let newData := mat.data.modify j fun row => mat.data[i]!.fold (fun cur k val => - let newVal := (cur.findD k 0) - coef * val + let newVal := (cur.getD k 0) - coef * val if newVal != 0 then cur.insert k newVal else cur.erase k ) row ⟨newData⟩ divideRow mat i coef := - let newData : Array (Lean.HashMap Nat Rat) := mat.data.modify i fun row => + let newData : Array (Std.HashMap Nat Rat) := mat.data.modify i fun row => row.fold (fun cur k v => cur.insert k (v / coef)) row ⟨newData⟩ diff --git a/Mathlib/Tactic/Linarith/Oracle/SimplexAlgorithm/PositiveVector.lean b/Mathlib/Tactic/Linarith/Oracle/SimplexAlgorithm/PositiveVector.lean index 3c23e2eb30aa9..c93e2e33f9b24 100644 --- a/Mathlib/Tactic/Linarith/Oracle/SimplexAlgorithm/PositiveVector.lean +++ b/Mathlib/Tactic/Linarith/Oracle/SimplexAlgorithm/PositiveVector.lean @@ -70,7 +70,7 @@ def stateLP {n m : Nat} (A : matType n m) (strictIndexes : List Nat) : matType ( ofValues (objectiveRow ++ constraintRow ++ valuesA) -/-- Extracts target vector from the tableau, putting auxilary variables aside (see `stateLP`). -/ +/-- Extracts target vector from the tableau, putting auxiliary variables aside (see `stateLP`). -/ def extractSolution (tableau : Tableau matType) : Array Rat := Id.run do let mut ans : Array Rat := Array.mkArray (tableau.basic.size + tableau.free.size - 3) 0 for i in [1:tableau.basic.size] do diff --git a/Mathlib/Tactic/Linarith/Preprocessing.lean b/Mathlib/Tactic/Linarith/Preprocessing.lean index 8d0a1bbd44edd..2a496d4cd5670 100644 --- a/Mathlib/Tactic/Linarith/Preprocessing.lean +++ b/Mathlib/Tactic/Linarith/Preprocessing.lean @@ -306,7 +306,7 @@ section nlinarith `findSquares s e` collects all terms of the form `a ^ 2` and `a * a` that appear in `e` and adds them to the set `s`. A pair `(i, true)` is added to `s` when `atoms[i]^2` appears in `e`, -and `(i, false)` is added to `s` when `atoms[i]*atoms[i]` appears in `e`. -/ +and `(i, false)` is added to `s` when `atoms[i]*atoms[i]` appears in `e`. -/ partial def findSquares (s : RBSet (Nat × Bool) lexOrd.compare) (e : Expr) : AtomM (RBSet (Nat × Bool) lexOrd.compare) := -- Completely traversing the expression is non-ideal, diff --git a/Mathlib/Tactic/LinearCombination'.lean b/Mathlib/Tactic/LinearCombination'.lean new file mode 100644 index 0000000000000..e42ba57d7608c --- /dev/null +++ b/Mathlib/Tactic/LinearCombination'.lean @@ -0,0 +1,258 @@ +/- +Copyright (c) 2022 Abby J. Goldberg. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Abby J. Goldberg, Mario Carneiro +-/ +import Mathlib.Tactic.Ring + +/-! +# linear_combination' Tactic + +In this file, the `linear_combination'` tactic is created. This tactic, which +works over `CommRing`s, attempts to simplify the target by creating a linear combination +of a list of equalities and subtracting it from the target. A `Syntax.Tactic` +object can also be passed into the tactic, allowing the user to specify a +normalization tactic. + +## Implementation Notes + +This tactic works by creating a weighted sum of the given equations with the +given coefficients. Then, it subtracts the right side of the weighted sum +from the left side so that the right side equals 0, and it does the same with +the target. Afterwards, it sets the goal to be the equality between the +lefthand side of the new goal and the lefthand side of the new weighted sum. +Lastly, calls a normalization tactic on this target. + +This file contains the `linear_combination'` tactic (note the '): the original +Lean 4 implementation of the "linear combination" idea, written at the time of +the port from Lean 3. Notably, its scope includes certain *nonlinear* +operations. The `linear_combination` tactic (in a separate file) is a variant +implementation, but this version is provided for backward-compatibility. + +## References + +* + +-/ + +namespace Mathlib.Tactic.LinearCombination' +open Lean hiding Rat +open Elab Meta Term + +variable {α : Type*} {a a' a₁ a₂ b b' b₁ b₂ c : α} + +theorem pf_add_c [Add α] (p : a = b) (c : α) : a + c = b + c := p ▸ rfl +theorem c_add_pf [Add α] (p : b = c) (a : α) : a + b = a + c := p ▸ rfl +theorem add_pf [Add α] (p₁ : (a₁:α) = b₁) (p₂ : a₂ = b₂) : a₁ + a₂ = b₁ + b₂ := p₁ ▸ p₂ ▸ rfl +theorem pf_sub_c [Sub α] (p : a = b) (c : α) : a - c = b - c := p ▸ rfl +theorem c_sub_pf [Sub α] (p : b = c) (a : α) : a - b = a - c := p ▸ rfl +theorem sub_pf [Sub α] (p₁ : (a₁:α) = b₁) (p₂ : a₂ = b₂) : a₁ - a₂ = b₁ - b₂ := p₁ ▸ p₂ ▸ rfl +theorem neg_pf [Neg α] (p : (a:α) = b) : -a = -b := p ▸ rfl +theorem pf_mul_c [Mul α] (p : a = b) (c : α) : a * c = b * c := p ▸ rfl +theorem c_mul_pf [Mul α] (p : b = c) (a : α) : a * b = a * c := p ▸ rfl +theorem mul_pf [Mul α] (p₁ : (a₁:α) = b₁) (p₂ : a₂ = b₂) : a₁ * a₂ = b₁ * b₂ := p₁ ▸ p₂ ▸ rfl +theorem inv_pf [Inv α] (p : (a:α) = b) : a⁻¹ = b⁻¹ := p ▸ rfl +theorem pf_div_c [Div α] (p : a = b) (c : α) : a / c = b / c := p ▸ rfl +theorem c_div_pf [Div α] (p : b = c) (a : α) : a / b = a / c := p ▸ rfl +theorem div_pf [Div α] (p₁ : (a₁:α) = b₁) (p₂ : a₂ = b₂) : a₁ / a₂ = b₁ / b₂ := p₁ ▸ p₂ ▸ rfl + +/-- Result of `expandLinearCombo`, either an equality proof or a value. -/ +inductive Expanded + /-- A proof of `a = b`. -/ + | proof (pf : Syntax.Term) + /-- A value, equivalently a proof of `c = c`. -/ + | const (c : Syntax.Term) + +/-- +Performs macro expansion of a linear combination expression, +using `+`/`-`/`*`/`/` on equations and values. +* `.proof p` means that `p` is a syntax corresponding to a proof of an equation. + For example, if `h : a = b` then `expandLinearCombo (2 * h)` returns `.proof (c_add_pf 2 h)` + which is a proof of `2 * a = 2 * b`. +* `.const c` means that the input expression is not an equation but a value. +-/ +partial def expandLinearCombo (ty : Expr) (stx : Syntax.Term) : TermElabM Expanded := withRef stx do + match stx with + | `(($e)) => expandLinearCombo ty e + | `($e₁ + $e₂) => do + match ← expandLinearCombo ty e₁, ← expandLinearCombo ty e₂ with + | .const c₁, .const c₂ => .const <$> ``($c₁ + $c₂) + | .proof p₁, .const c₂ => .proof <$> ``(pf_add_c $p₁ $c₂) + | .const c₁, .proof p₂ => .proof <$> ``(c_add_pf $p₂ $c₁) + | .proof p₁, .proof p₂ => .proof <$> ``(add_pf $p₁ $p₂) + | `($e₁ - $e₂) => do + match ← expandLinearCombo ty e₁, ← expandLinearCombo ty e₂ with + | .const c₁, .const c₂ => .const <$> ``($c₁ - $c₂) + | .proof p₁, .const c₂ => .proof <$> ``(pf_sub_c $p₁ $c₂) + | .const c₁, .proof p₂ => .proof <$> ``(c_sub_pf $p₂ $c₁) + | .proof p₁, .proof p₂ => .proof <$> ``(sub_pf $p₁ $p₂) + | `(-$e) => do + match ← expandLinearCombo ty e with + | .const c => .const <$> `(-$c) + | .proof p => .proof <$> ``(neg_pf $p) + | `(← $e) => do + match ← expandLinearCombo ty e with + | .const c => return .const c + | .proof p => .proof <$> ``(Eq.symm $p) + | `($e₁ * $e₂) => do + match ← expandLinearCombo ty e₁, ← expandLinearCombo ty e₂ with + | .const c₁, .const c₂ => .const <$> ``($c₁ * $c₂) + | .proof p₁, .const c₂ => .proof <$> ``(pf_mul_c $p₁ $c₂) + | .const c₁, .proof p₂ => .proof <$> ``(c_mul_pf $p₂ $c₁) + | .proof p₁, .proof p₂ => .proof <$> ``(mul_pf $p₁ $p₂) + | `($e⁻¹) => do + match ← expandLinearCombo ty e with + | .const c => .const <$> `($c⁻¹) + | .proof p => .proof <$> ``(inv_pf $p) + | `($e₁ / $e₂) => do + match ← expandLinearCombo ty e₁, ← expandLinearCombo ty e₂ with + | .const c₁, .const c₂ => .const <$> ``($c₁ / $c₂) + | .proof p₁, .const c₂ => .proof <$> ``(pf_div_c $p₁ $c₂) + | .const c₁, .proof p₂ => .proof <$> ``(c_div_pf $p₂ $c₁) + | .proof p₁, .proof p₂ => .proof <$> ``(div_pf $p₁ $p₂) + | e => + -- We have the expected type from the goal, so we can fully synthesize this leaf node. + withSynthesize do + -- It is OK to use `ty` as the expected type even if `e` is a proof. + -- The expected type is just a hint. + let c ← withSynthesizeLight <| Term.elabTerm e ty + if (← whnfR (← inferType c)).isEq then + .proof <$> c.toSyntax + else + .const <$> c.toSyntax + +theorem eq_trans₃ (p : (a:α) = b) (p₁ : a = a') (p₂ : b = b') : a' = b' := p₁ ▸ p₂ ▸ p + +theorem eq_of_add [AddGroup α] (p : (a:α) = b) (H : (a' - b') - (a - b) = 0) : a' = b' := by + rw [← sub_eq_zero] at p ⊢; rwa [sub_eq_zero, p] at H + +theorem eq_of_add_pow [Ring α] [NoZeroDivisors α] (n : ℕ) (p : (a:α) = b) + (H : (a' - b')^n - (a - b) = 0) : a' = b' := by + rw [← sub_eq_zero] at p ⊢; apply pow_eq_zero (n := n); rwa [sub_eq_zero, p] at H + +/-- Implementation of `linear_combination'` and `linear_combination2`. -/ +def elabLinearCombination' (tk : Syntax) + (norm? : Option Syntax.Tactic) (exp? : Option Syntax.NumLit) (input : Option Syntax.Term) + (twoGoals := false) : Tactic.TacticM Unit := Tactic.withMainContext do + let some (ty, _) := (← (← Tactic.getMainGoal).getType').eq? | + throwError "'linear_combination'' only proves equalities" + let p ← match input with + | none => `(Eq.refl 0) + | some e => + match ← expandLinearCombo ty e with + | .const c => `(Eq.refl $c) + | .proof p => pure p + let norm := norm?.getD (Unhygienic.run <| withRef tk `(tactic| ring1)) + Term.withoutErrToSorry <| Tactic.evalTactic <| ← withFreshMacroScope <| + if twoGoals then + `(tactic| ( + refine eq_trans₃ $p ?a ?b + case' a => $norm:tactic + case' b => $norm:tactic)) + else + match exp? with + | some n => + if n.getNat = 1 then `(tactic| (refine eq_of_add $p ?a; case' a => $norm:tactic)) + else `(tactic| (refine eq_of_add_pow $n $p ?a; case' a => $norm:tactic)) + | _ => `(tactic| (refine eq_of_add $p ?a; case' a => $norm:tactic)) + +/-- +The `(norm := $tac)` syntax says to use `tac` as a normalization postprocessor for +`linear_combination'`. The default normalizer is `ring1`, but you can override it with `ring_nf` +to get subgoals from `linear_combination'` or with `skip` to disable normalization. +-/ +syntax normStx := atomic(" (" &"norm" " := ") withoutPosition(tactic) ")" + +/-- +The `(exp := n)` syntax for `linear_combination'` says to take the goal to the `n`th power before +subtracting the given combination of hypotheses. +-/ +syntax expStx := atomic(" (" &"exp" " := ") withoutPosition(num) ")" + +/-- +`linear_combination'` attempts to simplify the target by creating a linear combination + of a list of equalities and subtracting it from the target. + The tactic will create a linear + combination by adding the equalities together from left to right, so the order + of the input hypotheses does matter. If the `normalize` field of the + configuration is set to false, then the tactic will simply set the user up to + prove their target using the linear combination instead of normalizing the subtraction. + +Note: There is also a similar tactic `linear_combination` (no prime); this version is +provided for backward compatibility. + +Note: The left and right sides of all the equalities should have the same + type, and the coefficients should also have this type. There must be + instances of `Mul` and `AddGroup` for this type. + +* The input `e` in `linear_combination' e` is a linear combination of proofs of equalities, + given as a sum/difference of coefficients multiplied by expressions. + The coefficients may be arbitrary expressions. + The expressions can be arbitrary proof terms proving equalities. + Most commonly they are hypothesis names `h1, h2, ...`. +* `linear_combination' (norm := tac) e` runs the "normalization tactic" `tac` + on the subgoal(s) after constructing the linear combination. + * The default normalization tactic is `ring1`, which closes the goal or fails. + * To get a subgoal in the case that it is not immediately provable, use + `ring_nf` as the normalization tactic. + * To avoid normalization entirely, use `skip` as the normalization tactic. +* `linear_combination' (exp := n) e` will take the goal to the `n`th power before subtracting the + combination `e`. In other words, if the goal is `t1 = t2`, `linear_combination' (exp := n) e` + will change the goal to `(t1 - t2)^n = 0` before proceeding as above. + This feature is not supported for `linear_combination2`. +* `linear_combination2 e` is the same as `linear_combination' e` but it produces two + subgoals instead of one: rather than proving that `(a - b) - (a' - b') = 0` where + `a' = b'` is the linear combination from `e` and `a = b` is the goal, + it instead attempts to prove `a = a'` and `b = b'`. + Because it does not use subtraction, this form is applicable also to semirings. + * Note that a goal which is provable by `linear_combination' e` may not be provable + by `linear_combination2 e`; in general you may need to add a coefficient to `e` + to make both sides match, as in `linear_combination2 e + c`. + * You can also reverse equalities using `← h`, so for example if `h₁ : a = b` + then `2 * (← h)` is a proof of `2 * b = 2 * a`. + +Example Usage: +``` +example (x y : ℤ) (h1 : x*y + 2*x = 1) (h2 : x = y) : x*y = -2*y + 1 := by + linear_combination' 1*h1 - 2*h2 + +example (x y : ℤ) (h1 : x*y + 2*x = 1) (h2 : x = y) : x*y = -2*y + 1 := by + linear_combination' h1 - 2*h2 + +example (x y : ℤ) (h1 : x*y + 2*x = 1) (h2 : x = y) : x*y = -2*y + 1 := by + linear_combination' (norm := ring_nf) -2*h2 + /- Goal: x * y + x * 2 - 1 = 0 -/ + +example (x y z : ℝ) (ha : x + 2*y - z = 4) (hb : 2*x + y + z = -2) + (hc : x + 2*y + z = 2) : + -3*x - 3*y - 4*z = 2 := by + linear_combination' ha - hb - 2*hc + +example (x y : ℚ) (h1 : x + y = 3) (h2 : 3*x = 7) : + x*x*y + y*x*y + 6*x = 3*x*y + 14 := by + linear_combination' x*y*h1 + 2*h2 + +example (x y : ℤ) (h1 : x = -3) (h2 : y = 10) : 2*x = -6 := by + linear_combination' (norm := skip) 2*h1 + simp + +axiom qc : ℚ +axiom hqc : qc = 2*qc + +example (a b : ℚ) (h : ∀ p q : ℚ, p = q) : 3*a + qc = 3*b + 2*qc := by + linear_combination' 3 * h a b + hqc +``` +-/ +syntax (name := linearCombination') "linear_combination'" + (normStx)? (expStx)? (ppSpace colGt term)? : tactic +elab_rules : tactic + | `(tactic| linear_combination'%$tk $[(norm := $tac)]? $[(exp := $n)]? $(e)?) => + elabLinearCombination' tk tac n e + +@[inherit_doc linearCombination'] +syntax "linear_combination2" (normStx)? (ppSpace colGt term)? : tactic +elab_rules : tactic + | `(tactic| linear_combination2%$tk $[(norm := $tac)]? $(e)?) => + elabLinearCombination' tk tac none e true + +end Mathlib.Tactic.LinearCombination' diff --git a/Mathlib/Tactic/LinearCombination.lean b/Mathlib/Tactic/LinearCombination.lean index 4677400bdced1..a0942a5645645 100644 --- a/Mathlib/Tactic/LinearCombination.lean +++ b/Mathlib/Tactic/LinearCombination.lean @@ -9,10 +9,9 @@ import Mathlib.Tactic.Ring # linear_combination Tactic In this file, the `linear_combination` tactic is created. This tactic, which -works over `Ring`s, attempts to simplify the target by creating a linear combination -of a list of equalities and subtracting it from the target. This file also includes a -definition for `linear_combination_config`. A `linear_combination_config` -object can be passed into the tactic, allowing the user to specify a +works over `CommRing`s, attempts to simplify the target by creating a linear combination +of a list of equalities and subtracting it from the target. A `Syntax.Tactic` +object can also be passed into the tactic, allowing the user to specify a normalization tactic. ## Implementation Notes @@ -41,8 +40,6 @@ theorem c_add_pf [Add α] (p : b = c) (a : α) : a + b = a + c := p ▸ rfl theorem add_pf [Add α] (p₁ : (a₁:α) = b₁) (p₂ : a₂ = b₂) : a₁ + a₂ = b₁ + b₂ := p₁ ▸ p₂ ▸ rfl theorem pf_sub_c [Sub α] (p : a = b) (c : α) : a - c = b - c := p ▸ rfl theorem c_sub_pf [Sub α] (p : b = c) (a : α) : a - b = a - c := p ▸ rfl -theorem sub_pf [Sub α] (p₁ : (a₁:α) = b₁) (p₂ : a₂ = b₂) : a₁ - a₂ = b₁ - b₂ := p₁ ▸ p₂ ▸ rfl -theorem neg_pf [Neg α] (p : (a:α) = b) : -a = -b := p ▸ rfl theorem pf_mul_c [Mul α] (p : a = b) (c : α) : a * c = b * c := p ▸ rfl theorem c_mul_pf [Mul α] (p : b = c) (a : α) : a * b = a * c := p ▸ rfl theorem mul_pf [Mul α] (p₁ : (a₁:α) = b₁) (p₂ : a₂ = b₂) : a₁ * a₂ = b₁ * b₂ := p₁ ▸ p₂ ▸ rfl @@ -80,14 +77,10 @@ partial def expandLinearCombo (ty : Expr) (stx : Syntax.Term) : TermElabM Expand | .const c₁, .const c₂ => .const <$> ``($c₁ - $c₂) | .proof p₁, .const c₂ => .proof <$> ``(pf_sub_c $p₁ $c₂) | .const c₁, .proof p₂ => .proof <$> ``(c_sub_pf $p₂ $c₁) - | .proof p₁, .proof p₂ => .proof <$> ``(sub_pf $p₁ $p₂) + | .proof p₁, .proof p₂ => .proof <$> ``(add_pf $p₁ (Eq.symm $p₂)) | `(-$e) => do match ← expandLinearCombo ty e with | .const c => .const <$> `(-$c) - | .proof p => .proof <$> ``(neg_pf $p) - | `(← $e) => do - match ← expandLinearCombo ty e with - | .const c => return .const c | .proof p => .proof <$> ``(Eq.symm $p) | `($e₁ * $e₂) => do match ← expandLinearCombo ty e₁, ← expandLinearCombo ty e₂ with @@ -116,40 +109,47 @@ partial def expandLinearCombo (ty : Expr) (stx : Syntax.Term) : TermElabM Expand else .const <$> c.toSyntax -theorem eq_trans₃ (p : (a:α) = b) (p₁ : a = a') (p₂ : b = b') : a' = b' := p₁ ▸ p₂ ▸ p - -theorem eq_of_add [AddGroup α] (p : (a:α) = b) (H : (a' - b') - (a - b) = 0) : a' = b' := by +theorem eq_of_sub [AddGroup α] (p : (a:α) = b) (H : (a' - b') - (a - b) = 0) : a' = b' := by rw [← sub_eq_zero] at p ⊢; rwa [sub_eq_zero, p] at H +theorem eq_of_add [Add α] [IsRightCancelAdd α] (p : (a:α) = b) (H : a' + b = b' + a) : a' = b' := by + rw [p] at H + exact add_right_cancel H + theorem eq_of_add_pow [Ring α] [NoZeroDivisors α] (n : ℕ) (p : (a:α) = b) (H : (a' - b')^n - (a - b) = 0) : a' = b' := by rw [← sub_eq_zero] at p ⊢; apply pow_eq_zero (n := n); rwa [sub_eq_zero, p] at H -/-- Implementation of `linear_combination` and `linear_combination2`. -/ -def elabLinearCombination - (norm? : Option Syntax.Tactic) (exp? : Option Syntax.NumLit) (input : Option Syntax.Term) - (twoGoals := false) : Tactic.TacticM Unit := Tactic.withMainContext do +/-- Implementation of `linear_combination`. -/ +def elabLinearCombination (tk : Syntax) + (norm? : Option Syntax.Tactic) (exp? : Option Syntax.NumLit) (input : Option Syntax.Term) : + Tactic.TacticM Unit := Tactic.withMainContext do let some (ty, _) := (← (← Tactic.getMainGoal).getType').eq? | throwError "'linear_combination' only proves equalities" let p ← match input with | none => `(Eq.refl 0) | some e => match ← expandLinearCombo ty e with - | .const c => `(Eq.refl $c) + | .const _ => throwError "To run 'linear_combination' without hypotheses, call it without input" | .proof p => pure p - let norm := norm?.getD (Unhygienic.run `(tactic| ring1)) + let norm := norm?.getD (Unhygienic.run <| withRef tk `(tactic| ring1)) + let lem : Ident ← mkIdent <$> do + try + -- if we are in a "true" ring, with well-behaved negation, it is better to present the + -- normalization tactic with a goal of the form `[stuff] = 0`, because this gives more useful + -- error messages on failure + let _ ← synthInstance (← mkAppM ``Neg #[ty]) + pure ``eq_of_sub + catch _ => + -- but otherwise (for example over `ℕ` or `ℝ≥0`) we can solve the problem by presenting the + -- normalization tactic with a goal of the form `[stuff] = [stuff]` + pure ``eq_of_add Term.withoutErrToSorry <| Tactic.evalTactic <| ← withFreshMacroScope <| - if twoGoals then - `(tactic| ( - refine eq_trans₃ $p ?a ?b - case' a => $norm:tactic - case' b => $norm:tactic)) - else - match exp? with - | some n => - if n.getNat = 1 then `(tactic| (refine eq_of_add $p ?a; case' a => $norm:tactic)) - else `(tactic| (refine eq_of_add_pow $n $p ?a; case' a => $norm:tactic)) - | _ => `(tactic| (refine eq_of_add $p ?a; case' a => $norm:tactic)) + match exp? with + | some n => + if n.getNat = 1 then `(tactic| (refine $lem $p ?a; case' a => $norm:tactic)) + else `(tactic| (refine eq_of_add_pow $n $p ?a; case' a => $norm:tactic)) + | _ => `(tactic| (refine $lem $p ?a; case' a => $norm:tactic)) /-- The `(norm := $tac)` syntax says to use `tac` as a normalization postprocessor for @@ -173,9 +173,13 @@ syntax expStx := atomic(" (" &"exp" " := ") withoutPosition(num) ")" configuration is set to false, then the tactic will simply set the user up to prove their target using the linear combination instead of normalizing the subtraction. -Note: The left and right sides of all the equalities should have the same - type, and the coefficients should also have this type. There must be - instances of `Mul` and `AddGroup` for this type. +Note: The left and right sides of all the equalities should have the same type `α`, and the +coefficients should also have type `α`. For full functionality `α` should be a commutative ring -- +strictly speaking, a commutative semiring with "cancellative" addition (in the semiring case, +negation and subtraction will be handled "formally" as if operating in the enveloping ring). If a +nonstandard normalization is used (for example `abel` or `skip`), the tactic will work over types +`α` with less algebraic structure: the minimum is instances of `[Add α] [IsRightCancelAdd α]` +together with instances of whatever operations are used in the tactic call. * The input `e` in `linear_combination e` is a linear combination of proofs of equalities, given as a sum/difference of coefficients multiplied by expressions. @@ -191,17 +195,6 @@ Note: The left and right sides of all the equalities should have the same * `linear_combination (exp := n) e` will take the goal to the `n`th power before subtracting the combination `e`. In other words, if the goal is `t1 = t2`, `linear_combination (exp := n) e` will change the goal to `(t1 - t2)^n = 0` before proceeding as above. - This feature is not supported for `linear_combination2`. -* `linear_combination2 e` is the same as `linear_combination e` but it produces two - subgoals instead of one: rather than proving that `(a - b) - (a' - b') = 0` where - `a' = b'` is the linear combination from `e` and `a = b` is the goal, - it instead attempts to prove `a = a'` and `b = b'`. - Because it does not use subtraction, this form is applicable also to semirings. - * Note that a goal which is provable by `linear_combination e` may not be provable - by `linear_combination2 e`; in general you may need to add a coefficient to `e` - to make both sides match, as in `linear_combination2 e + c`. - * You can also reverse equalities using `← h`, so for example if `h₁ : a = b` - then `2 * (← h)` is a proof of `2 * b = 2 * a`. Example Usage: ``` @@ -238,12 +231,7 @@ example (a b : ℚ) (h : ∀ p q : ℚ, p = q) : 3*a + qc = 3*b + 2*qc := by syntax (name := linearCombination) "linear_combination" (normStx)? (expStx)? (ppSpace colGt term)? : tactic elab_rules : tactic - | `(tactic| linear_combination $[(norm := $tac)]? $[(exp := $n)]? $(e)?) => - elabLinearCombination tac n e - -@[inherit_doc linearCombination] -syntax "linear_combination2" (normStx)? (ppSpace colGt term)? : tactic -elab_rules : tactic - | `(tactic| linear_combination2 $[(norm := $tac)]? $(e)?) => elabLinearCombination tac none e true + | `(tactic| linear_combination%$tk $[(norm := $tac)]? $[(exp := $n)]? $(e)?) => + elabLinearCombination tk tac n e end Mathlib.Tactic.LinearCombination diff --git a/Mathlib/Tactic/Linter.lean b/Mathlib/Tactic/Linter.lean index 5ed156753cbd9..33cb31377e2f4 100644 --- a/Mathlib/Tactic/Linter.lean +++ b/Mathlib/Tactic/Linter.lean @@ -1,16 +1,13 @@ /- -This is the `Linter`s file: it only imports files defining linters and is -intended to be imported fairly early in `Mathlib`. +This is the `Linter`s file: it imports files defining linters. +All syntax linters enabled by default are imported in `Mathlib.Init`; +this file contains all other linters. This file is ignored by `shake`: * it is in `ignoreAll`, meaning that all its imports are considered necessary; * it is in `ignoreImport`, meaning that where it is imported, it is considered necessary. -/ -import Mathlib.Tactic.Linter.GlobalAttributeIn -import Mathlib.Tactic.Linter.HashCommandLinter import Mathlib.Tactic.Linter.HaveLetLinter -import Mathlib.Tactic.Linter.Lint -import Mathlib.Tactic.Linter.RefineLinter -import Mathlib.Tactic.Linter.Style -import Mathlib.Tactic.Linter.UnusedTactic +import Mathlib.Tactic.Linter.MinImports +import Mathlib.Tactic.Linter.TextBased diff --git a/Mathlib/Tactic/Linter/AdmitLinter.lean b/Mathlib/Tactic/Linter/AdmitLinter.lean new file mode 100644 index 0000000000000..602952c5a6692 --- /dev/null +++ b/Mathlib/Tactic/Linter/AdmitLinter.lean @@ -0,0 +1,55 @@ +/- +Copyright (c) 2024 Adomas Baliuka. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Damiano Testa, Adomas Baliuka +-/ +import Lean.Elab.Command + +/-! +# The "admit" linter + +The "admit" linter flags usages of the `admit` tactic. + +The tactics `admit` and `sorry` are synonyms. +The use of `sorry` is much more common and should be preferred. + +This linter is an incentive to discourage uses of `admit`, without being a ban. +-/ + +namespace Mathlib.Linter + +/-- The admit linter emits a warning on usages of `admit`. -/ +register_option linter.admit : Bool := { + defValue := false + descr := "enable the admit linter" +} + +namespace AdmitLinter + +open Lean Elab + +/-- `getAdmit t` returns all usages of the `admit` tactic in the input syntax `t`. -/ +partial +def getAdmit (stx : Syntax) : Array Syntax := + if let `(tactic| admit) := stx then + #[stx] + else + stx.foldArgs (fun arg r => r ++ getAdmit arg) #[] + +/-- The "admit" linter flags usages of the `admit` tactic. + +The tactics `admit` and `sorry` are synonyms. +The use of `sorry` is much more common and should be preferred. +-/ +def admitLinter : Linter where run := withSetOptionIn fun stx => do + unless Linter.getLinterValue linter.admit (← getOptions) do + return + if (← MonadState.get).messages.hasErrors then + return + for stxAdmit in (getAdmit stx) do + Linter.logLint linter.admit stxAdmit + "The `admit` tactic is discouraged: please consider using the synonymous `sorry` instead." + +initialize addLinter admitLinter + +end AdmitLinter diff --git a/Mathlib/Tactic/Linter/GlobalAttributeIn.lean b/Mathlib/Tactic/Linter/GlobalAttributeIn.lean index b18e1defd647f..6a6c49e09f4ad 100644 --- a/Mathlib/Tactic/Linter/GlobalAttributeIn.lean +++ b/Mathlib/Tactic/Linter/GlobalAttributeIn.lean @@ -4,9 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Michael Rothgang, Damiano Testa -/ -import Mathlib.Init import Lean.Elab.Command -import Lean.Linter.Util /-! # Linter for `attribute [...] in` declarations diff --git a/Mathlib/Tactic/Linter/HashCommandLinter.lean b/Mathlib/Tactic/Linter/HashCommandLinter.lean index 76e570391be93..66cac438ada34 100644 --- a/Mathlib/Tactic/Linter/HashCommandLinter.lean +++ b/Mathlib/Tactic/Linter/HashCommandLinter.lean @@ -4,9 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Damiano Testa -/ -import Mathlib.Init import Lean.Elab.Command -import Lean.Linter.Util import Batteries.Lean.HashSet /-! @@ -30,7 +28,7 @@ For example, `#guard true` and `#check_tactic True ~> True by skip` trigger a me There is a list of silent `#`-command that are allowed. -/ register_option linter.hashCommand : Bool := { - defValue := true + defValue := false descr := "enable the `#`-command linter" } @@ -54,7 +52,7 @@ private partial def withSetOptionIn' (cmd : CommandElab) : CommandElab := fun st cmd stx /-- `allowed_commands` is the `HashSet` of `#`-commands that are allowed in 'Mathlib'. -/ -private abbrev allowed_commands : HashSet String := { "#adaptation_note" } +private abbrev allowed_commands : Std.HashSet String := { "#adaptation_note" } /-- Checks that no command beginning with `#` is present in 'Mathlib', except for the ones in `allowed_commands`. diff --git a/Mathlib/Tactic/Linter/HaveLetLinter.lean b/Mathlib/Tactic/Linter/HaveLetLinter.lean index c8f07ad46c4cc..08b0435b8de7c 100644 --- a/Mathlib/Tactic/Linter/HaveLetLinter.lean +++ b/Mathlib/Tactic/Linter/HaveLetLinter.lean @@ -39,7 +39,7 @@ There are three settings: The default value is `1`. -/ register_option linter.haveLet : Nat := { - defValue := 1 + defValue := 0 descr := "enable the `have` vs `let` linter:\n\ * 0 -- inactive;\n\ * 1 -- active only on noisy declarations;\n\ diff --git a/Mathlib/Tactic/Linter/Lint.lean b/Mathlib/Tactic/Linter/Lint.lean index 3025eadd9f127..18fe6fa7b91bb 100644 --- a/Mathlib/Tactic/Linter/Lint.lean +++ b/Mathlib/Tactic/Linter/Lint.lean @@ -3,9 +3,6 @@ Copyright (c) 2023 Floris van Doorn. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Floris van Doorn -/ -import Mathlib.Init -import Lean.Linter.Util -import Batteries.Data.String.Matcher import Batteries.Tactic.Lint /-! @@ -30,7 +27,7 @@ Linter that checks whether a structure should be in Prop. -- remark: using `Lean.Meta.isProp` doesn't suffice here, because it doesn't (always?) -- recognize predicates as propositional. let isProp ← forallTelescopeReducing (← inferType (← mkConstWithLevelParams declName)) - fun _ ty => return ty == .sort .zero + fun _ ty ↦ return ty == .sort .zero if isProp then return none let projs := (getStructureInfo? (← getEnv) declName).get!.fieldNames if projs.isEmpty then return none -- don't flag empty structures @@ -87,18 +84,18 @@ def getIds : Syntax → Array Syntax | .node _ `Batteries.Tactic.Alias.alias args => args[2:3] | .node _ ``Lean.Parser.Command.export args => (args[3:4] : Array Syntax).map (·[0]) | stx@(.node _ _ args) => - ((args.attach.map fun ⟨a, _⟩ => getIds a).foldl (· ++ ·) #[stx]).filter (·.getKind == ``declId) + ((args.attach.map fun ⟨a, _⟩ ↦ getIds a).foldl (· ++ ·) #[stx]).filter (·.getKind == ``declId) | _ => default @[inherit_doc linter.dupNamespace] -def dupNamespace : Linter where run := withSetOptionIn fun stx => do +def dupNamespace : Linter where run := withSetOptionIn fun stx ↦ do if Linter.getLinterValue linter.dupNamespace (← getOptions) then match getIds stx with | #[id] => let ns := (← getScope).currNamespace let declName := ns ++ (if id.getKind == ``declId then id[0].getId else id.getId) let nm := declName.components - let some (dup, _) := nm.zip (nm.tailD []) |>.find? fun (x, y) => x == y + let some (dup, _) := nm.zip (nm.tailD []) |>.find? fun (x, y) ↦ x == y | return Linter.logLint linter.dupNamespace id m!"The namespace '{dup}' is duplicated in the declaration '{declName}'" @@ -120,21 +117,18 @@ open Lean Elab Command /-- The "missing end" linter emits a warning on non-closed `section`s and `namespace`s. It allows the "outermost" `noncomputable section` to be left open (whether or not it is named). -/ -register_option linter.missingEnd : Bool := { - defValue := true +register_option linter.style.missingEnd : Bool := { + defValue := false descr := "enable the missing end linter" } -namespace MissingEnd +namespace Style.missingEnd -@[inherit_doc Mathlib.Linter.linter.missingEnd] +@[inherit_doc Mathlib.Linter.linter.style.missingEnd] def missingEndLinter : Linter where run := withSetOptionIn fun stx ↦ do -- Only run this linter at the end of a module. unless stx.isOfKind ``Lean.Parser.Command.eoi do return - -- TODO: once mathlib's Lean version includes leanprover/lean4#4741, make this configurable - unless #[`Mathlib, `test, `Archive, `Counterexamples].contains (← getMainModule).getRoot do - return - if Linter.getLinterValue linter.missingEnd (← getOptions) && + if Linter.getLinterValue linter.style.missingEnd (← getOptions) && !(← MonadState.get).messages.hasErrors then let sc ← getScopes -- The last scope is always the "base scope", corresponding to no active `section`s or @@ -147,12 +141,12 @@ def missingEndLinter : Linter where run := withSetOptionIn fun stx ↦ do if !ends.isEmpty then let ending := (ends.map Prod.fst).foldl (init := "") fun a b ↦ a ++ s!"\n\nend{if b == "" then "" else " "}{b}" - Linter.logLint linter.missingEnd stx + Linter.logLint linter.style.missingEnd stx m!"unclosed sections or namespaces; expected: '{ending}'" initialize addLinter missingEndLinter -end MissingEnd +end Style.missingEnd /-! # The `cdot` linter @@ -160,14 +154,16 @@ end MissingEnd The `cdot` linter is a syntax-linter that flags uses of the "cdot" `·` that are achieved by typing a character different from `·`. For instance, a "plain" dot `.` is allowed syntax, but is flagged by the linter. +It also flags "isolated cdots", i.e. when the `·` is on its own line. -/ /-- The `cdot` linter flags uses of the "cdot" `·` that are achieved by typing a character different from `·`. -For instance, a "plain" dot `.` is allowed syntax, but is flagged by the linter. -/ -register_option linter.cdot : Bool := { - defValue := true +For instance, a "plain" dot `.` is allowed syntax, but is flagged by the linter. +It also flags "isolated cdots", i.e. when the `·` is on its own line. -/ +register_option linter.style.cdot : Bool := { + defValue := false descr := "enable the `cdot` linter" } @@ -185,7 +181,7 @@ def findCDot : Syntax → Array Syntax | stx@(.node _ kind args) => let dargs := (args.map findCDot).flatten match kind with - | ``Lean.Parser.Term.cdot | ``cdotTk=> dargs.push stx + | ``Lean.Parser.Term.cdot | ``cdotTk => dargs.push stx | _ => dargs |_ => #[] @@ -196,41 +192,200 @@ This is precisely what the `cdot` linter flags. def unwanted_cdot (stx : Syntax) : Array Syntax := (findCDot stx).filter (!isCDot? ·) -namespace CDotLinter +namespace Style -@[inherit_doc linter.cdot] -def cdotLinter : Linter where run := withSetOptionIn fun stx => do - unless Linter.getLinterValue linter.cdot (← getOptions) do +@[inherit_doc linter.style.cdot] +def cdotLinter : Linter where run := withSetOptionIn fun stx ↦ do + unless Linter.getLinterValue linter.style.cdot (← getOptions) do return if (← MonadState.get).messages.hasErrors then return for s in unwanted_cdot stx do - Linter.logLint linter.cdot s m!"Please, use '·' (typed as `\\.`) instead of '{s}' as 'cdot'." + Linter.logLint linter.style.cdot s + m!"Please, use '·' (typed as `\\.`) instead of '{s}' as 'cdot'." + -- We also check for isolated cdot's, i.e. when the cdot is on its own line. + for cdot in Mathlib.Linter.findCDot stx do + match cdot.find? (·.isOfKind `token.«· ») with + | some (.node _ _ #[.atom (.original _ _ afterCDot _) _]) => + if (afterCDot.takeWhile (·.isWhitespace)).contains '\n' then + logWarningAt cdot <| .tagged linter.style.cdot.name + m!"This central dot `·` is isolated; please merge it with the next line." + | _ => return initialize addLinter cdotLinter -end CDotLinter +end Style + +/-! +# The `dollarSyntax` linter + +The `dollarSyntax` linter flags uses of `<|` that are achieved by typing `$`. +These are disallowed by the mathlib style guide, as using `<|` pairs better with `|>`. +-/ + +/-- The `dollarSyntax` linter flags uses of `<|` that are achieved by typing `$`. +These are disallowed by the mathlib style guide, as using `<|` pairs better with `|>`. -/ +register_option linter.style.dollarSyntax : Bool := { + defValue := false + descr := "enable the `dollarSyntax` linter" +} + +namespace Style.dollarSyntax + +/-- `findDollarSyntax stx` extracts from `stx` the syntax nodes of `kind` `$`. -/ +partial +def findDollarSyntax : Syntax → Array Syntax + | stx@(.node _ kind args) => + let dargs := (args.map findDollarSyntax).flatten + match kind with + | ``«term_$__» => dargs.push stx + | _ => dargs + |_ => #[] + +@[inherit_doc linter.style.dollarSyntax] +def dollarSyntaxLinter : Linter where run := withSetOptionIn fun stx ↦ do + unless Linter.getLinterValue linter.style.dollarSyntax (← getOptions) do + return + if (← MonadState.get).messages.hasErrors then + return + for s in findDollarSyntax stx do + Linter.logLint linter.style.dollarSyntax s + m!"Please use '<|' instead of '$' for the pipe operator." + +initialize addLinter dollarSyntaxLinter + +end Style.dollarSyntax + +/-! +# The `lambdaSyntax` linter + +The `lambdaSyntax` linter is a syntax linter that flags uses of the symbol `λ` to define anonymous +functions, as opposed to the `fun` keyword. These are syntactically equivalent; mathlib style +prefers the latter as it is considered more readable. +-/ + +/-- +The `lambdaSyntax` linter flags uses of the symbol `λ` to define anonymous functions. +This is syntactically equivalent to the `fun` keyword; mathlib style prefers using the latter. +-/ +register_option linter.style.lambdaSyntax : Bool := { + defValue := false + descr := "enable the `lambdaSyntax` linter" +} + +namespace Style.lambdaSyntax + +/-- +`findLambdaSyntax stx` extracts from `stx` all syntax nodes of `kind` `Term.fun`. -/ +partial +def findLambdaSyntax : Syntax → Array Syntax + | stx@(.node _ kind args) => + let dargs := (args.map findLambdaSyntax).flatten + match kind with + | ``Parser.Term.fun => dargs.push stx + | _ => dargs + |_ => #[] + +@[inherit_doc linter.style.lambdaSyntax] +def lambdaSyntaxLinter : Linter where run := withSetOptionIn fun stx ↦ do + unless Linter.getLinterValue linter.style.lambdaSyntax (← getOptions) do + return + if (← MonadState.get).messages.hasErrors then + return + for s in findLambdaSyntax stx do + if let .atom _ "λ" := s[0] then + Linter.logLint linter.style.lambdaSyntax s[0] m!"\ + Please use 'fun' and not 'λ' to define anonymous functions.\n\ + The 'λ' syntax is deprecated in mathlib4." + +initialize addLinter lambdaSyntaxLinter + +end Style.lambdaSyntax + +/-! +# The "longFile" linter + +The "longFile" linter emits a warning on files which are longer than a certain number of lines +(1500 by default). +-/ + +/-- +The "longFile" linter emits a warning on files which are longer than a certain number of lines +(1500 by default). If this option is set to `N` lines, the linter warns once a file has more than +`N` lines. A value of `0` silences the linter entirely. +-/ +register_option linter.style.longFile : Nat := { + defValue := 1500 + descr := "enable the longFile linter" +} + +namespace Style.longFile + +@[inherit_doc Mathlib.Linter.linter.style.longFile] +def longFileLinter : Linter where run := withSetOptionIn fun stx ↦ do + let linterBound := linter.style.longFile.get (← getOptions) + if linterBound == 0 then + return + let defValue := linter.style.longFile.defValue + let smallOption := match stx with + | `(set_option linter.style.longFile $x) => TSyntax.getNat ⟨x.raw⟩ ≤ defValue + | _ => false + if smallOption then + logWarningAt stx <| .tagged linter.style.longFile.name + m!"The default value of the `longFile` linter is {defValue}.\n\ + The current value of {linterBound} does not exceed the allowed bound.\n\ + Please, remove the `set_option linter.style.longFile {linterBound}`." + else + -- Thanks to the above check, the linter option is either not set (and hence equal + -- to the default) or set to some value *larger* than the default. + -- `Parser.isTerminalCommand` allows `stx` to be `#exit`: this is useful for tests. + unless Parser.isTerminalCommand stx do return + -- We exclude `Mathlib.lean` from the linter: it exceeds linter's default number of allowed + -- lines, and it is an auto-generated import-only file. + -- TODO: if there are more such files, revise the implementation. + if (← getMainModule) == `Mathlib then return + if let some init := stx.getTailPos? then + -- the last line: we subtract 1, since the last line is expected to be empty + let lastLine := ((← getFileMap).toPosition init).line + if lastLine ≤ defValue && defValue < linterBound then + logWarningAt stx <| .tagged linter.style.longFile.name + m!"The default value of the `longFile` linter is {defValue}.\n\ + This file is {lastLine} lines long which does not exceed the allowed bound.\n\ + Please, remove the `set_option linter.style.longFile {linterBound}`." + else + -- `candidate` is divisible by `100` and satisfies `lastLine + 100 < candidate ≤ lastLine + 200` + -- note that either `lastLine ≤ defValue` and `defValue = linterBound` hold or + -- `candidate` is necessarily bigger than `lastLine` and hence bigger than `defValue` + let candidate := (lastLine / 100) * 100 + 200 + let candidate := max candidate defValue + if linterBound < lastLine then + logWarningAt stx <| .tagged linter.style.longFile.name + m!"This file is {lastLine} lines long, but the limit is {linterBound}.\n\n\ + You can extend the allowed length of the file using \ + `set_option linter.style.longFile {candidate}`.\n\ + You can completely disable this linter by setting the length limit to `0`." + +initialize addLinter longFileLinter + +end Style.longFile /-! # The "longLine linter" -/ /-- The "longLine" linter emits a warning on lines longer than 100 characters. We allow lines containing URLs to be longer, though. -/ -register_option linter.longLine : Bool := { - defValue := true +register_option linter.style.longLine : Bool := { + defValue := false descr := "enable the longLine linter" } -namespace LongLine +namespace Style.longLine -@[inherit_doc Mathlib.Linter.linter.longLine] +@[inherit_doc Mathlib.Linter.linter.style.longLine] def longLineLinter : Linter where run := withSetOptionIn fun stx ↦ do - unless Linter.getLinterValue linter.longLine (← getOptions) do + unless Linter.getLinterValue linter.style.longLine (← getOptions) do return if (← MonadState.get).messages.hasErrors then return - -- TODO: once mathlib's Lean version includes leanprover/lean4#4741, make this configurable - unless #[`Mathlib, `test, `Archive, `Counterexamples].contains (← getMainModule).getRoot do - return -- The linter ignores the `#guard_msgs` command, in particular its doc-string. -- The linter still lints the message guarded by `#guard_msgs`. if stx.isOfKind ``Lean.guardMsgsCmd then @@ -246,15 +401,15 @@ def longLineLinter : Linter where run := withSetOptionIn fun stx ↦ do else return stx let sstr := stx.getSubstring? let fm ← getFileMap - let longLines := ((sstr.getD default).splitOn "\n").filter fun line => + let longLines := ((sstr.getD default).splitOn "\n").filter fun line ↦ (100 < (fm.toPosition line.stopPos).column) for line in longLines do - if !(line.containsSubstr "http") then - Linter.logLint linter.longLine (.ofRange ⟨line.startPos, line.stopPos⟩) + if (line.splitOn "http").length ≤ 1 then + Linter.logLint linter.style.longLine (.ofRange ⟨line.startPos, line.stopPos⟩) m!"This line exceeds the 100 character limit, please shorten it!" initialize addLinter longLineLinter -end LongLine +end Style.longLine end Mathlib.Linter diff --git a/Mathlib/Tactic/Linter/MinImports.lean b/Mathlib/Tactic/Linter/MinImports.lean index 129150e7718b2..202d32297ca82 100644 --- a/Mathlib/Tactic/Linter/MinImports.lean +++ b/Mathlib/Tactic/Linter/MinImports.lean @@ -62,7 +62,7 @@ def minImportsLinter : Linter where run := withSetOptionIn fun stx => do if stx == (← `(command| set_option $(mkIdent `linter.minImports) true)) then return let importsSoFar ← minImportsRef.get -- when the linter reaches the end of the file or `#exit`, it gives a report - if #[``Parser.Command.eoi, ``Lean.Parser.Command.exit].contains stx.getKind then + if #[``Parser.Command.eoi, ``Lean.Parser.Command.exit].contains stx.getKind then let explicitImportsInFile : NameSet := .fromArray (((← getEnv).imports.map (·.module)).erase `Init) Name.quickCmp let newImps := importsSoFar.diff explicitImportsInFile diff --git a/Mathlib/Tactic/Linter/OldObtain.lean b/Mathlib/Tactic/Linter/OldObtain.lean index 1c0a6d5783fb8..0fd427c77bbfe 100644 --- a/Mathlib/Tactic/Linter/OldObtain.lean +++ b/Mathlib/Tactic/Linter/OldObtain.lean @@ -4,9 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Michael Rothgang -/ -import Mathlib.Init import Lean.Elab.Command -import Lean.Linter.Util /-! # The `oldObtain` linter, against stream-of-conciousness `obtain` @@ -63,7 +61,7 @@ def is_obtain_without_proof : Syntax → Bool /-- The `oldObtain` linter emits a warning upon uses of the "stream-of-conciousness" variants of the `obtain` tactic, i.e. with the proof postponed. -/ register_option linter.oldObtain : Bool := { - defValue := true + defValue := false descr := "enable the `oldObtain` linter" } diff --git a/Mathlib/Tactic/Linter/RefineLinter.lean b/Mathlib/Tactic/Linter/RefineLinter.lean index b97dd76db8525..7bbc39eee11dc 100644 --- a/Mathlib/Tactic/Linter/RefineLinter.lean +++ b/Mathlib/Tactic/Linter/RefineLinter.lean @@ -3,9 +3,8 @@ Copyright (c) 2024 Damiano Testa. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Damiano Testa -/ -import Mathlib.Init + import Lean.Elab.Command -import Lean.Linter.Util /-! # The "refine" linter @@ -30,7 +29,7 @@ This means that they are not completely interchangeable, nor can one completely However, `refine` is more readable and (heuristically) tends to be more efficient on average. -/ register_option linter.refine : Bool := { - defValue := true + defValue := false descr := "enable the refine linter" } diff --git a/Mathlib/Tactic/Linter/Style.lean b/Mathlib/Tactic/Linter/Style.lean index 0064675cef1c7..1f737feb7c3ef 100644 --- a/Mathlib/Tactic/Linter/Style.lean +++ b/Mathlib/Tactic/Linter/Style.lean @@ -4,9 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Michael Rothgang -/ -import Mathlib.Init import Lean.Elab.Command -import Lean.Linter.Util /-! ## Style linters @@ -23,12 +21,12 @@ namespace Mathlib.Linter /-- The `setOption` linter emits a warning on a `set_option` command, term or tactic which sets a `pp`, `profiler` or `trace` option. -/ -register_option linter.setOption : Bool := { - defValue := true +register_option linter.style.setOption : Bool := { + defValue := false descr := "enable the `setOption` linter" } -namespace Style.SetOption +namespace Style.setOption /-- Whether a syntax element is a `set_option` command, tactic or term: Return the name of the option being set, if any. -/ @@ -52,18 +50,15 @@ used in production code. (Some tests will intentionally use one of these options; in this case, simply allow the linter.) -/ def setOptionLinter : Linter where run := withSetOptionIn fun stx => do - unless Linter.getLinterValue linter.setOption (← getOptions) do + unless Linter.getLinterValue linter.style.setOption (← getOptions) do return if (← MonadState.get).messages.hasErrors then return - -- TODO: once mathlib's Lean version includes leanprover/lean4#4741, make this configurable - unless #[`Mathlib, `test, `Archive, `Counterexamples].contains (← getMainModule).getRoot do - return if let some head := stx.find? is_set_option then if let some name := parse_set_option head then let forbidden := [`debug, `pp, `profiler, `trace] if forbidden.contains name.getRoot then - Linter.logLint linter.setOption head + Linter.logLint linter.style.setOption head m!"Setting options starting with '{"', '".intercalate (forbidden.map (·.toString))}' \ is only intended for development and not for final code. \ If you intend to submit this contribution to the Mathlib project, \ @@ -71,6 +66,6 @@ def setOptionLinter : Linter where run := withSetOptionIn fun stx => do initialize addLinter setOptionLinter -end Style.SetOption +end Style.setOption end Mathlib.Linter diff --git a/Mathlib/Tactic/Linter/TextBased.lean b/Mathlib/Tactic/Linter/TextBased.lean index 3da71f0a028bd..ff83c4868359e 100644 --- a/Mathlib/Tactic/Linter/TextBased.lean +++ b/Mathlib/Tactic/Linter/TextBased.lean @@ -18,7 +18,6 @@ For now, this only contains linters checking - existence of module docstrings (in the right place) - for certain disallowed imports - if the string "adaptation note" is used instead of the command #adaptation_note -- lines are at most 100 characters long (except for URLs) - files are at most 1500 lines long (unless specifically allowed). For historic reasons, some of these checks are still written in a Python script `lint-style.py`: @@ -27,11 +26,19 @@ these are gradually being rewritten in Lean. This linter maintains a list of exceptions, for legacy reasons. Ideally, the length of the list of exceptions tends to 0. +The `longFile` and the `longLine` *syntax* linter take care of flagging lines that exceed the +100 character limit and files that exceed the 1500 line limit. +The text-based versions of this file are still used for the files where the linter is not imported. +This means that the exceptions for the text-based linters are shorter, as they do not need to +include those handled with `set_option linter.style.longFile x`/`set_option linter.longLine false`. + An executable running all these linters is defined in `scripts/lint-style.lean`. -/ open System +namespace Mathlib.Linter.TextBased + /-- Different kinds of "broad imports" that are linted against. -/ inductive BroadImports /-- Importing the entire "Mathlib.Tactic" folder -/ @@ -55,13 +62,6 @@ inductive StyleError where /-- Lint against "too broad" imports, such as `Mathlib.Tactic` or any module in `Lake` (unless carefully measured) -/ | broadImport (module : BroadImports) - /-- Line longer than 100 characters -/ - | lineLength (actual : Int) : StyleError - /-- The current file was too large: this error contains the current number of lines - as well as a size limit (slightly larger). On future runs, this linter will allow this file - to grow up to this limit. - For diagnostic purposes, this may also contain a previous size limit, which is now exceeded. -/ - | fileTooLong (numberLines : ℕ) (newSizeLimit : ℕ) (previousLimit : Option ℕ) : StyleError deriving BEq /-- How to format style errors -/ @@ -77,7 +77,7 @@ inductive ErrorFormat deriving BEq /-- Create the underlying error message for a given `StyleError`. -/ -def StyleError.errorMessage (err : StyleError) (style : ErrorFormat) : String := match err with +def StyleError.errorMessage (err : StyleError) : String := match err with | StyleError.copyright (some context) => s!"Malformed or missing copyright header: {context}" | StyleError.copyright none => "Malformed or missing copyright header" | StyleError.authors => @@ -90,17 +90,6 @@ def StyleError.errorMessage (err : StyleError) (style : ErrorFormat) : String := "In the past, importing 'Lake' in mathlib has led to dramatic slow-downs of the linter (see \ e.g. mathlib4#13779). Please consider carefully if this import is useful and make sure to \ benchmark it. If this is fine, feel free to allow this linter." - | StyleError.lineLength n => s!"Line has {n} characters, which is more than 100" - | StyleError.fileTooLong currentSize sizeLimit previousLimit => - match style with - | ErrorFormat.github => - if let some n := previousLimit then - s!"file contains {currentSize} lines (at most {n} allowed), try to split it up" - else - s!"file contains {currentSize} lines, try to split it up" - | ErrorFormat.exceptionsFile => - s!"{sizeLimit} file contains {currentSize} lines, try to split it up" - | ErrorFormat.humanReadable => s!"file contains {currentSize} lines, try to split it up" /-- The error code for a given style error. Keep this in sync with `parse?_errorContext` below! -/ -- FUTURE: we're matching the old codes in `lint-style.py` for compatibility; @@ -110,8 +99,6 @@ def StyleError.errorCode (err : StyleError) : String := match err with | StyleError.authors => "ERR_AUT" | StyleError.adaptationNote => "ERR_ADN" | StyleError.broadImport _ => "ERR_IMP" - | StyleError.lineLength _ => "ERR_LIN" - | StyleError.fileTooLong _ _ _ => "ERR_NUM_LIN" /-- Context for a style error: the actual error, the line number in the file we're reading and the path to the file. -/ @@ -141,27 +128,17 @@ inductive ComparisonResult and, if it is, if we prefer replacing the new exception or keeping the previous one. -/ def compare (existing new : ErrorContext) : ComparisonResult := -- Two comparable error contexts must have the same path. - if existing.path != new.path then - ComparisonResult.Different + -- To avoid issues with different path separators across different operating systems, + -- we compare the set of path components instead. + if existing.path.components != new.path.components then ComparisonResult.Different -- We entirely ignore their line numbers: not sure if this is best. -- NB: keep the following in sync with `parse?_errorContext` below. -- Generally, comparable errors must have equal `StyleError`s, but there are some exceptions. else match (existing.error, new.error) with - -- File length errors are the biggest exceptions: generally, we prefer to keep the - -- existing entry, *except* when a newer entry is much shorter. - | (StyleError.fileTooLong n nLimit _, StyleError.fileTooLong m _mLimit _) => - -- The only exception are "file too long" errors. - -- If a file got much longer, the existing exception does not apply; - if m > nLimit then ComparisonResult.Different - -- if it does apply, we prefer to keep the existing entry, - -- *unless* the newer entry is much shorter. - else if m + 200 <= n then ComparisonResult.Comparable false - else ComparisonResult.Comparable true -- We do *not* care about the *kind* of wrong copyright, -- nor about the particular length of a too long line. | (StyleError.copyright _, StyleError.copyright _) => ComparisonResult.Comparable true - | (StyleError.lineLength _, StyleError.lineLength _) => ComparisonResult.Comparable true -- In all other cases, `StyleErrors` must compare equal. | (a, b) => if a == b then ComparisonResult.Comparable true else ComparisonResult.Different @@ -174,7 +151,7 @@ def ErrorContext.find?_comparable (e : ErrorContext) (exceptions : Array ErrorCo `style` specifies if the error should be formatted for humans to read, github problem matchers to consume, or for the style exceptions file. -/ def outputMessage (errctx : ErrorContext) (style : ErrorFormat) : String := - let errorMessage := errctx.error.errorMessage style + let errorMessage := errctx.error.errorMessage match style with | ErrorFormat.github => -- We are outputting for github: duplicate file path, line number and error code, @@ -205,12 +182,6 @@ def parse?_errorContext (line : String) : Option ErrorContext := Id.run do -- Use default values for parameters which are ignored for comparing style exceptions. -- NB: keep this in sync with `compare` above! | "ERR_COP" => some (StyleError.copyright none) - | "ERR_LIN" => - if let some n := errorMessage.get? 2 then - match String.toNat? n with - | some n => return StyleError.lineLength n - | none => none - else none | "ERR_AUT" => some (StyleError.authors) | "ERR_ADN" => some (StyleError.adaptationNote) | "ERR_IMP" => @@ -219,15 +190,6 @@ def parse?_errorContext (line : String) : Option ErrorContext := Id.run do some (StyleError.broadImport BroadImports.TacticFolder) else some (StyleError.broadImport BroadImports.Lake) - | "ERR_NUM_LIN" => - -- Parse the error message in the script. `none` indicates invalid input. - match (errorMessage.get? 0, errorMessage.get? 3) with - | (some limit, some current) => - match (String.toNat? limit, String.toNat? current) with - | (some sizeLimit, some currentSize) => - some (StyleError.fileTooLong currentSize sizeLimit (some sizeLimit)) - | _ => none - | _ => none | _ => none match String.toNat? lineNumber with | some n => err.map fun e ↦ (ErrorContext.mk e n path) @@ -342,15 +304,6 @@ def broadImportsLinter : TextbasedLinter := fun lines ↦ Id.run do lineNumber := lineNumber + 1 return errors -/-- Iterates over a collection of strings, finding all lines which are longer than 101 chars. -We allow URLs to be longer, though. --/ -def lineLengthLinter : TextbasedLinter := fun lines ↦ Id.run do - let errors := (lines.toList.enumFrom 1).filterMap (fun (lineNumber, line) ↦ - if line.length > 101 && !line.containsSubstr "http" then - some (StyleError.lineLength line.length, lineNumber) - else none) - errors.toArray /-- Whether a collection of lines consists *only* of imports, blank lines and single-line comments. In practice, this means it's an imports-only file and exempt from almost all linting. -/ @@ -359,57 +312,26 @@ def isImportsOnlyFile (lines : Array String) : Bool := -- this is in fact not necessary. (It is needed for `Tactic/Linter.lean`, though.) lines.all (fun line ↦ line.startsWith "import " || line == "" || line.startsWith "-- ") -/-- Error if a collection of lines is too large. "Too large" means more than 1500 lines -**and** longer than an optional previous limit. -If the file is too large, return a matching `StyleError`, which includes a new size limit -(which is somewhat larger than the current size). -/ -def checkFileLength (lines : Array String) (existingLimit : Option ℕ) : Option StyleError := - Id.run do - if lines.size > 1500 then - let isLarger : Bool := match existingLimit with - | some mark => lines.size > mark - | none => true - if isLarger then - -- We add about 200 lines of slack to the current file size: small PRs will be unaffected, - -- but sufficiently large PRs will get nudged towards splitting up this file. - return some (StyleError.fileTooLong lines.size - ((Nat.div lines.size 100) * 100 + 200) existingLimit) - none - end /-- All text-based linters registered in this file. -/ def allLinters : Array TextbasedLinter := #[ - copyrightHeaderLinter, adaptationNoteLinter, broadImportsLinter, lineLengthLinter + copyrightHeaderLinter, adaptationNoteLinter, broadImportsLinter ] -/-- Controls what kind of output this programme produces. -/ -inductive OutputSetting : Type - /-- Print any style error to standard output (the default) -/ - | print (style : ErrorFormat) - /-- Update the style exceptions file (and still print style errors to standard output). - This adds entries for any new exceptions, removes any entries which are no longer necessary, - and tries to not modify exception entries unless necessary. - To fully regenerate the exceptions file, delete `style-exceptions.txt` and run again in this mode. - -/ - | update - deriving BEq /-- Read a file and apply all text-based linters. Return a list of all unexpected errors. -`sizeLimit` is any pre-existing limit on this file's size. -`exceptions` are any other style exceptions. -/ -def lintFile (path : FilePath) (sizeLimit : Option ℕ) (exceptions : Array ErrorContext) : +`exceptions` are any pre-existing style exceptions for this file. -/ +def lintFile (path : FilePath) (exceptions : Array ErrorContext) : IO (Array ErrorContext) := do let lines ← IO.FS.lines path -- We don't need to run any checks on imports-only files. if isImportsOnlyFile lines then return #[] let mut errors := #[] - if let some (StyleError.fileTooLong n limit ex) := checkFileLength lines sizeLimit then - errors := #[ErrorContext.mk (StyleError.fileTooLong n limit ex) 1 path] let allOutput := (Array.map (fun lint ↦ (Array.map (fun (e, n) ↦ ErrorContext.mk e n path)) (lint lines))) allLinters - -- This this list is not sorted: for github, this is fine. + -- This list is not sorted: for github, this is fine. errors := errors.append (allOutput.flatten.filter (fun e ↦ (e.find?_comparable exceptions).isNone)) return errors @@ -421,60 +343,32 @@ Return the number of files which had new style errors. `moduleNames` are all the modules to lint, `mode` specifies what kind of output this script should produce, `fix` configures whether fixable errors should be corrected in-place. -/ -def lintModules (moduleNames : Array String) (mode : OutputSetting) (fix : Bool) : IO UInt32 := do - -- Read the style exceptions file. - -- We also have a `nolints` file with manual exceptions for the linter. - let exceptionsFilePath : FilePath := "scripts" / "style-exceptions.txt" - let exceptions ← IO.FS.lines exceptionsFilePath - let mut styleExceptions := parseStyleExceptions exceptions +def lintModules (moduleNames : Array String) (style : ErrorFormat) (fix : Bool) : IO UInt32 := do + -- Read the `nolints` file, with manual exceptions for the linter. let nolints ← IO.FS.lines ("scripts" / "nolints-style.txt") - styleExceptions := styleExceptions.append (parseStyleExceptions nolints) + let styleExceptions := parseStyleExceptions nolints let mut numberErrorFiles : UInt32 := 0 let mut allUnexpectedErrors := #[] for module in moduleNames do -- Convert the module name to a file name, then lint that file. let path := (mkFilePath (module.split (· == '.'))).addExtension "lean" - -- Find all size limits for this given file. - -- If several size limits are given (unlikely in practice), we use the first one. - let sizeLimits := (styleExceptions.filter (fun ex ↦ ex.path == path)).filterMap (fun errctx ↦ - match errctx.error with - | StyleError.fileTooLong _ limit _ => some limit - | _ => none) - let errors := - if let OutputSetting.print _ := mode then - ← lintFile path (sizeLimits.get? 0) styleExceptions - else - -- In "update" mode, we ignore the exceptions file (and only take `nolints` into account). - ← lintFile path none (parseStyleExceptions nolints) + let errors := ← lintFile path styleExceptions if errors.size > 0 then allUnexpectedErrors := allUnexpectedErrors.append errors numberErrorFiles := numberErrorFiles + 1 - match mode with - | OutputSetting.print style => - -- Run the remaining python linters. It is easier to just run on all files. - -- If this poses an issue, I can either filter the output - -- or wait until lint-style.py is fully rewritten in Lean. - let args := if fix then #["--fix"] else #[] - let pythonOutput ← IO.Process.run { cmd := "./scripts/print-style-errors.sh", args := args } - if pythonOutput != "" then IO.println pythonOutput - formatErrors allUnexpectedErrors style - if numberErrorFiles > 0 && mode matches OutputSetting.print _ then - IO.println s!"error: found {allUnexpectedErrors.size} new style errors\n\ - run `lake exe lint-style --update` to ignore all of them" - | OutputSetting.update => - formatErrors allUnexpectedErrors ErrorFormat.humanReadable - -- Regenerate the style exceptions file, including the Python output. - IO.FS.writeFile exceptionsFilePath "" - let pythonOutput ← IO.Process.run { cmd := "./scripts/print-style-errors.sh" } - -- Combine style exception entries: for each new error, replace by a corresponding - -- previous exception if that is preferred. - let mut tweaked := allUnexpectedErrors.map fun err ↦ - if let some existing := err.find?_comparable styleExceptions then - if let ComparisonResult.Comparable (true) := _root_.compare err existing then existing - else err - else err - let thisOutput := "\n".intercalate (tweaked.map - (fun err ↦ outputMessage err ErrorFormat.exceptionsFile)).toList - IO.FS.writeFile exceptionsFilePath s!"{pythonOutput}{thisOutput}\n" + + -- Run the remaining python linters. It is easier to just run on all files. + -- If this poses an issue, I can either filter the output + -- or wait until lint-style.py is fully rewritten in Lean. + let args := if fix then #["--fix"] else #[] + let pythonOutput ← IO.Process.run { cmd := "./scripts/print-style-errors.sh", args := args } + if pythonOutput != "" then + numberErrorFiles := numberErrorFiles + 1 + IO.print pythonOutput + formatErrors allUnexpectedErrors style + if allUnexpectedErrors.size > 0 then + IO.println s!"error: found {allUnexpectedErrors.size} new style error(s)" return numberErrorFiles + +end Mathlib.Linter.TextBased diff --git a/Mathlib/Tactic/Linter/UnusedTactic.lean b/Mathlib/Tactic/Linter/UnusedTactic.lean index 9389441b83460..7528d2a53673f 100644 --- a/Mathlib/Tactic/Linter/UnusedTactic.lean +++ b/Mathlib/Tactic/Linter/UnusedTactic.lean @@ -3,9 +3,8 @@ Copyright (c) 2024 Damiano Testa. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Damiano Testa -/ -import Mathlib.Init + import Lean.Elab.Command -import Lean.Linter.Util import Batteries.Tactic.Unreachable /-! @@ -51,7 +50,7 @@ before and after and see if there is some change. Yet another linter copied from the `unreachableTactic` linter! -/ -open Lean Elab +open Lean Elab Std namespace Mathlib.Linter @@ -64,13 +63,13 @@ register_option linter.unusedTactic : Bool := { namespace UnusedTactic /-- The monad for collecting the ranges of the syntaxes that do not modify any goal. -/ -abbrev M := StateRefT (HashMap String.Range Syntax) IO +abbrev M := StateRefT (Std.HashMap String.Range Syntax) IO /-- `Parser`s allowed to not change the tactic state. This can be increased dynamically, using `#allow_unused_tactic`. -/ -initialize allowedRef : IO.Ref (HashSet SyntaxNodeKind) ← - IO.mkRef <| HashSet.empty +initialize allowedRef : IO.Ref (Std.HashSet SyntaxNodeKind) ← + IO.mkRef <| Std.HashSet.empty |>.insert `Mathlib.Tactic.Says.says |>.insert `Batteries.Tactic.«tacticOn_goal-_=>_» -- attempt to speed up, by ignoring more tactics @@ -114,7 +113,7 @@ A list of blacklisted syntax kinds, which are expected to have subterms that con unevaluated tactics. -/ initialize ignoreTacticKindsRef : IO.Ref NameHashSet ← - IO.mkRef <| HashSet.empty + IO.mkRef <| Std.HashSet.empty |>.insert `Mathlib.Tactic.Says.says |>.insert ``Parser.Term.binderTactic |>.insert ``Lean.Parser.Term.dynamicQuot @@ -127,6 +126,7 @@ initialize ignoreTacticKindsRef : IO.Ref NameHashSet ← |>.insert `Batteries.Tactic.seq_focus |>.insert `Mathlib.Tactic.Hint.registerHintStx |>.insert `Mathlib.Tactic.LinearCombination.linearCombination + |>.insert `Mathlib.Tactic.LinearCombination'.linearCombination' -- the following `SyntaxNodeKind`s play a role in silencing `test`s |>.insert ``Lean.Parser.Tactic.failIfSuccess |>.insert `Mathlib.Tactic.successIfFailWithMsg @@ -218,7 +218,7 @@ def unusedTacticLinter : Linter where run := withSetOptionIn fun stx => do let key (r : String.Range) := (r.start.byteIdx, (-r.stop.byteIdx : Int)) let mut last : String.Range := ⟨0, 0⟩ for (r, stx) in let _ := @lexOrd; let _ := @ltOfOrd.{0}; unused.qsort (key ·.1 < key ·.1) do - if stx.getKind ∈ [``Batteries.Tactic.unreachable, ``Batteries.Tactic.unreachableConv] then + if stx.getKind ∈ [`Batteries.Tactic.unreachable, `Batteries.Tactic.unreachableConv] then continue if last.start ≤ r.start && r.stop ≤ last.stop then continue Linter.logLint linter.unusedTactic stx m!"'{stx}' tactic does nothing" diff --git a/Mathlib/Tactic/MinImports.lean b/Mathlib/Tactic/MinImports.lean index 788d4f9df7257..f079b40e3b93d 100644 --- a/Mathlib/Tactic/MinImports.lean +++ b/Mathlib/Tactic/MinImports.lean @@ -160,7 +160,7 @@ def getAllImports (cmd id : Syntax) (dbg? : Bool := false) : |>.append (getSyntaxNodeKinds cmd) |>.append (getAttrs env cmd) if dbg? then dbg_trace "{ts.toArray.qsort Name.lt}" - let mut hm : HashMap Nat Name := {} + let mut hm : Std.HashMap Nat Name := {} for imp in env.header.moduleNames do hm := hm.insert ((env.getModuleIdx? imp).getD default) imp let mut fins : NameSet := {} @@ -168,7 +168,7 @@ def getAllImports (cmd id : Syntax) (dbg? : Bool := false) : let tns := t1::(← resolveGlobalName t1).map Prod.fst for t in tns do let new := match env.getModuleIdxFor? t with - | some t => (hm.find? t).get! + | some t => (hm.get? t).get! | none => .anonymous -- instead of `getMainModule`, we omit the current module if !fins.contains new then fins := fins.insert new return fins.erase .anonymous diff --git a/Mathlib/Tactic/MoveAdd.lean b/Mathlib/Tactic/MoveAdd.lean index 1f76421725627..094ce46b60265 100644 --- a/Mathlib/Tactic/MoveAdd.lean +++ b/Mathlib/Tactic/MoveAdd.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Arthur Paulino, Damiano Testa -/ import Mathlib.Algebra.Group.Basic -import Mathlib.Init.Order.LinearOrder /-! diff --git a/Mathlib/Tactic/NormNum/Prime.lean b/Mathlib/Tactic/NormNum/Prime.lean index 015e44548304d..4f9a95a5d7158 100644 --- a/Mathlib/Tactic/NormNum/Prime.lean +++ b/Mathlib/Tactic/NormNum/Prime.lean @@ -57,7 +57,7 @@ theorem minFacHelper_0 (n : ℕ) (h1 : Nat.ble (nat_lit 2) n = true) (h2 : nat_lit 1 = n % (nat_lit 2)) : MinFacHelper n (nat_lit 3) := by refine ⟨by norm_num, by norm_num, ?_⟩ - refine (le_minFac'.mpr λ p hp hpn ↦ ?_).resolve_left (Nat.ne_of_gt (Nat.le_of_ble_eq_true h1)) + refine (le_minFac'.mpr fun p hp hpn ↦ ?_).resolve_left (Nat.ne_of_gt (Nat.le_of_ble_eq_true h1)) rcases hp.eq_or_lt with rfl|h · simp [(Nat.dvd_iff_mod_eq_zero ..).1 hpn] at h2 · exact h @@ -81,13 +81,13 @@ theorem minFacHelper_1 {n k k' : ℕ} (e : k + 2 = k') (h : MinFacHelper n k) theorem minFacHelper_2 {n k k' : ℕ} (e : k + 2 = k') (nk : ¬ Nat.Prime k) (h : MinFacHelper n k) : MinFacHelper n k' := by - refine minFacHelper_1 e h λ h2 ↦ ?_ + refine minFacHelper_1 e h fun h2 ↦ ?_ rw [← h2] at nk exact nk <| minFac_prime h.one_lt.ne' theorem minFacHelper_3 {n k k' : ℕ} (e : k + 2 = k') (nk : (n % k).beq 0 = false) (h : MinFacHelper n k) : MinFacHelper n k' := by - refine minFacHelper_1 e h λ h2 ↦ ?_ + refine minFacHelper_1 e h fun h2 ↦ ?_ have nk := Nat.ne_of_beq_eq_false nk rw [← Nat.dvd_iff_mod_eq_zero, ← h2] at nk exact nk <| minFac_dvd n @@ -109,7 +109,7 @@ theorem isNat_minFac_4 : {n n' k : ℕ} → | n, _, k, ⟨rfl⟩, h1, h2 => by refine ⟨(Nat.prime_def_minFac.mp ?_).2⟩ rw [Nat.prime_def_le_sqrt] - refine ⟨h1.one_lt, λ m hm hmn h2mn ↦ ?_⟩ + refine ⟨h1.one_lt, fun m hm hmn h2mn ↦ ?_⟩ exact lt_irrefl m <| calc m ≤ sqrt n := hmn _ < k := sqrt_lt.mpr (ble_eq_false.mp h2) diff --git a/Mathlib/Tactic/Peel.lean b/Mathlib/Tactic/Peel.lean index b3ab2443710a5..0428aed375d7c 100644 --- a/Mathlib/Tactic/Peel.lean +++ b/Mathlib/Tactic/Peel.lean @@ -225,7 +225,7 @@ def peelArgsIff (l : List Name) : TacticM Unit := withMainContext do elab_rules : tactic | `(tactic| peel $[$num?:num]? $e:term $[with $l?* $n?]?) => withMainContext do /- we use `elabTermForApply` instead of `elabTerm` so that terms passed to `peel` can contain - quantifiers with implicit bound variables without causing errors or requiring `@`. -/ + quantifiers with implicit bound variables without causing errors or requiring `@`. -/ let e ← elabTermForApply e false let n? := n?.bind fun n => if n.raw.isIdent then pure n.raw.getId else none let l := (l?.getD #[]).map getNameOfIdent' |>.toList diff --git a/Mathlib/Tactic/Positivity.lean b/Mathlib/Tactic/Positivity.lean index 88170863d05df..8d76b597bcf25 100644 --- a/Mathlib/Tactic/Positivity.lean +++ b/Mathlib/Tactic/Positivity.lean @@ -1,3 +1,3 @@ import Mathlib.Tactic.Positivity.Basic import Mathlib.Tactic.NormNum.Basic -import Mathlib.Init.Data.Int.Order +import Mathlib.Data.Int.Order.Basic diff --git a/Mathlib/Tactic/Positivity/Basic.lean b/Mathlib/Tactic/Positivity/Basic.lean index 14fd841e445d2..44f3d57c3fec7 100644 --- a/Mathlib/Tactic/Positivity/Basic.lean +++ b/Mathlib/Tactic/Positivity/Basic.lean @@ -5,7 +5,6 @@ Authors: Mario Carneiro, Heather Macbeth, Yaël Dillies -/ import Mathlib.Algebra.Order.Group.PosPart import Mathlib.Algebra.Order.Ring.Basic -import Mathlib.Algebra.Order.Ring.Rat import Mathlib.Data.Int.CharZero import Mathlib.Data.Nat.Factorial.Basic import Mathlib.Data.NNRat.Defs diff --git a/Mathlib/Tactic/Positivity/Core.lean b/Mathlib/Tactic/Positivity/Core.lean index f6f04104e28db..a03631e11fca8 100644 --- a/Mathlib/Tactic/Positivity/Core.lean +++ b/Mathlib/Tactic/Positivity/Core.lean @@ -341,7 +341,7 @@ private inductive OrderRel : Type end Meta.Positivity namespace Meta.Positivity -/-- An auxillary entry point to the `positivity` tactic. Given a proposition `t` of the form +/-- An auxiliary entry point to the `positivity` tactic. Given a proposition `t` of the form `0 [≤/ 1 | prod fst snd _ _ => fst.size + snd.size -/-- The components of an interated product, presented as a `ProdTree`. -/ +/-- The components of an iterated product, presented as a `ProdTree`. -/ def ProdTree.components : ProdTree → List Expr | type tp _ => [tp] | prod fst snd _ _ => fst.components ++ snd.components diff --git a/Mathlib/Tactic/PushNeg.lean b/Mathlib/Tactic/PushNeg.lean index 32ceeec86884d..07699624b4fc5 100644 --- a/Mathlib/Tactic/PushNeg.lean +++ b/Mathlib/Tactic/PushNeg.lean @@ -5,11 +5,10 @@ Authors: Patrick Massot, Simon Hudon, Alice Laroche, Frédéric Dupuis, Jireh Lo -/ import Lean.Elab.Tactic.Location +import Mathlib.Data.Set.Defs import Mathlib.Logic.Basic import Mathlib.Order.Defs import Mathlib.Tactic.Conv -import Mathlib.Init.Set -import Lean.Elab.Tactic.Location /-! # The `push_neg` tactic diff --git a/Mathlib/Tactic/Recover.lean b/Mathlib/Tactic/Recover.lean index b330002cecfd5..abae8c5304d60 100644 --- a/Mathlib/Tactic/Recover.lean +++ b/Mathlib/Tactic/Recover.lean @@ -26,21 +26,21 @@ which occur in the target or local context or delayed assignment (if any) of `mvarId`, plus the metavariables which occur in these metavariables, etc. -/ partial def getUnassignedGoalMVarDependencies (mvarId : MVarId) : - MetaM (HashSet MVarId) := + MetaM (Std.HashSet MVarId) := return (← go mvarId |>.run {}).snd where /-- auxiliary function for `getUnassignedGoalMVarDependencies` -/ - addMVars (e : Expr) : StateRefT (HashSet MVarId) MetaM Unit := do + addMVars (e : Expr) : StateRefT (Std.HashSet MVarId) MetaM Unit := do let mvars ← getMVars e let mut s ← get - set ({} : HashSet MVarId) -- Ensure that `s` is not shared. + set ({} : Std.HashSet MVarId) -- Ensure that `s` is not shared. for mvarId in mvars do unless ← mvarId.isDelayedAssigned do s := s.insert mvarId set s mvars.forM go /-- auxiliary function for `getUnassignedGoalMVarDependencies` -/ - go (mvarId : MVarId) : StateRefT (HashSet MVarId) MetaM Unit := + go (mvarId : MVarId) : StateRefT (Std.HashSet MVarId) MetaM Unit := withIncRecDepth do let mdecl ← mvarId.getDecl addMVars mdecl.type @@ -60,7 +60,7 @@ that are not closed, starting from the original goal. -/ elab "recover " tacs:tacticSeq : tactic => do let originalGoals ← getGoals evalTactic tacs - let mut unassigned : HashSet MVarId := {} + let mut unassigned : Std.HashSet MVarId := {} for mvarId in originalGoals do unless ← mvarId.isAssigned <||> mvarId.isDelayedAssigned do unassigned := unassigned.insert mvarId diff --git a/Mathlib/Tactic/Sat/FromLRAT.lean b/Mathlib/Tactic/Sat/FromLRAT.lean index 3bbdaa9c67d0c..b8d7f1a56e43c 100644 --- a/Mathlib/Tactic/Sat/FromLRAT.lean +++ b/Mathlib/Tactic/Sat/FromLRAT.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ import Mathlib.Algebra.Group.Nat +import Batteries.Data.HashMap.Basic /-! # `lrat_proof` command @@ -161,8 +162,9 @@ theorem Valuation.mk_implies {p} {as ps} (as₁) : as = List.reverseAux as₁ ps subst e; clear ih H suffices ∀ n n', n' = List.length as₁ + n → ∀ bs, mk (as₁.reverseAux bs) n' ↔ mk bs n from this 0 _ rfl (a::as) - induction as₁ with simp - | cons b as₁ ih => exact fun n bs ↦ ih (n+1) _ (Nat.succ_add ..) _ + induction as₁ with + | nil => simp + | cons b as₁ ih => simpa using fun n bs ↦ ih (n+1) _ (Nat.succ_add ..) _ /-- Asserts that `¬⟦f⟧_v` implies `p`. -/ structure Fmla.reify (v : Valuation) (f : Fmla) (p : Prop) : Prop where @@ -493,30 +495,30 @@ where open Lean namespace Parser -open Lean Parsec +open Lean Std.Internal.Parsec String /-- Parse a natural number -/ -def parseNat : Parsec Nat := Json.Parser.natMaybeZero +def parseNat : String.Parser Nat := Json.Parser.natMaybeZero /-- Parse an integer -/ -def parseInt : Parsec Int := do +def parseInt : String.Parser Int := do if (← peek!) = '-' then skip; pure <| -(← parseNat) else parseNat /-- Parse a list of integers terminated by 0 -/ -partial def parseInts (arr : Array Int := #[]) : Parsec (Array Int) := do +partial def parseInts (arr : Array Int := #[]) : String.Parser (Array Int) := do match ← parseInt <* ws with | 0 => pure arr | n => parseInts (arr.push n) /-- Parse a list of natural numbers terminated by 0 -/ -partial def parseNats (arr : Array Nat := #[]) : Parsec (Array Nat) := do +partial def parseNats (arr : Array Nat := #[]) : String.Parser (Array Nat) := do match ← parseNat <* ws with | 0 => pure arr | n => parseNats (arr.push n) /-- Parse a DIMACS format `.cnf` file. This is not very robust; we assume the file has had comments stripped. -/ -def parseDimacs : Parsec (Nat × Array (Array Int)) := do +def parseDimacs : String.Parser (Nat × Array (Array Int)) := do pstring "p cnf" *> ws let nvars ← parseNat <* ws let nclauses ← parseNat <* ws @@ -526,13 +528,15 @@ def parseDimacs : Parsec (Nat × Array (Array Int)) := do pure (nvars, clauses) /-- Parse an LRAT file into a list of steps. -/ -def parseLRAT : Parsec (Array LRATStep) := many do +def parseLRAT : String.Parser (Array LRATStep) := many do let step ← parseNat <* ws if (← peek!) = 'd' then skip <* ws; pure <| LRATStep.del (← parseNats) else ws; pure <| LRATStep.add step (← parseInts) (← parseInts) end Parser +open Std.Internal + /-- Core of `fromLRAT`. Constructs the context and main proof definitions, but not the reification theorem. Returns: diff --git a/Mathlib/Tactic/Simps/Basic.lean b/Mathlib/Tactic/Simps/Basic.lean index 6f1c5c4089821..ee2d6ee2fb88b 100644 --- a/Mathlib/Tactic/Simps/Basic.lean +++ b/Mathlib/Tactic/Simps/Basic.lean @@ -8,6 +8,7 @@ import Lean.Elab.App import Mathlib.Tactic.Simps.NotationClass import Batteries.Data.String.Basic import Mathlib.Lean.Expr.Basic +import Batteries.Data.List.Basic /-! # Simps attribute @@ -482,7 +483,7 @@ We use this variant because the latter is often a different field with an auto-g -/ private def dropPrefixIfNotNumber? (s : String) (pre : Substring) : Option Substring := do let ret ← Substring.dropPrefix? s pre - -- flag is true when the remaning part is nonempty and starts with a digit. + -- flag is true when the remaining part is nonempty and starts with a digit. let flag := ret.toString.data.head?.elim false Char.isDigit if flag then none else some ret @@ -535,7 +536,7 @@ partial def getCompositeOfProjectionsAux (proj : String) (e : Expr) (pos : Array initialize_simps_projections (toFun_toFun_toFun → myMul) ``` we will be able to generate the "projection" - `λ {A} (f : gradedFun A) (x : A i) (y : A j) ↦ ↑(↑(f.toFun i j) x) y`, + `fun {A} (f : gradedFun A) (x : A i) (y : A j) ↦ ↑(↑(f.toFun i j) x) y`, which projection notation cannot do. -/ def getCompositeOfProjections (structName : Name) (proj : String) : MetaM (Expr × Array Nat) := do let strExpr ← mkConstWithLevelParams structName diff --git a/Mathlib/Tactic/Simps/NotationClass.lean b/Mathlib/Tactic/Simps/NotationClass.lean index f1e36a9e926cc..4ce2493b876a1 100644 --- a/Mathlib/Tactic/Simps/NotationClass.lean +++ b/Mathlib/Tactic/Simps/NotationClass.lean @@ -46,7 +46,7 @@ We partly define this as a separate definition so that the unused arguments lint def findArgType : Type := Name → Name → Array Expr → MetaM (Array (Option Expr)) /-- Find arguments for a notation class -/ -def defaultfindArgs : findArgType := λ _ className args => do +def defaultfindArgs : findArgType := fun _ className args ↦ do let some classExpr := (← getEnv).find? className | throwError "no such class {className}" let arity := classExpr.type.forallArity if arity == args.size then @@ -58,29 +58,29 @@ def defaultfindArgs : findArgType := λ _ className args => do {className}" /-- Find arguments by duplicating the first argument. Used for `pow`. -/ -def copyFirst : findArgType := λ _ _ args => return (args.push <| args[0]?.getD default).map some +def copyFirst : findArgType := fun _ _ args ↦ return (args.push <| args[0]?.getD default).map some /-- Find arguments by duplicating the first argument. Used for `smul`. -/ -def copySecond : findArgType := λ _ _ args => return (args.push <| args[1]?.getD default).map some +def copySecond : findArgType := fun _ _ args ↦ return (args.push <| args[1]?.getD default).map some /-- Find arguments by prepending `ℕ` and duplicating the first argument. Used for `nsmul`. -/ -def nsmulArgs : findArgType := λ _ _ args => +def nsmulArgs : findArgType := fun _ _ args ↦ return #[Expr.const `Nat [], args[0]?.getD default] ++ args |>.map some /-- Find arguments by prepending `ℤ` and duplicating the first argument. Used for `zsmul`. -/ -def zsmulArgs : findArgType := λ _ _ args => +def zsmulArgs : findArgType := fun _ _ args ↦ return #[Expr.const `Int [], args[0]?.getD default] ++ args |>.map some /-- Find arguments for the `Zero` class. -/ -def findZeroArgs : findArgType := λ _ _ args => +def findZeroArgs : findArgType := fun _ _ args ↦ return #[some <| args[0]?.getD default, some <| mkRawNatLit 0] /-- Find arguments for the `One` class. -/ -def findOneArgs : findArgType := λ _ _ args => +def findOneArgs : findArgType := fun _ _ args ↦ return #[some <| args[0]?.getD default, some <| mkRawNatLit 1] /-- Find arguments of a coercion class (`DFunLike` or `SetLike`) -/ -def findCoercionArgs : findArgType := λ str className args => do +def findCoercionArgs : findArgType := fun str className args ↦ do let some classExpr := (← getEnv).find? className | throwError "no such class {className}" let arity := classExpr.type.forallArity let eStr := mkAppN (← mkConstWithLevelParams str) args diff --git a/Mathlib/Tactic/SlimCheck.lean b/Mathlib/Tactic/SlimCheck.lean index e5088f231ead7..66c0e52fbbb68 100644 --- a/Mathlib/Tactic/SlimCheck.lean +++ b/Mathlib/Tactic/SlimCheck.lean @@ -181,7 +181,7 @@ elab_rules : tactic | `(tactic| slim_check $[$cfg]?) => withMainContext do Failed to create a `testable` instance for `{tgt}`.\ \nWhat to do:\ \n1. make sure that the types you are using have `SlimCheck.SampleableExt` instances\ - \n (you can use `#sample my_type` if you are unsure);\ + \n (you can use `#sample my_type` if you are unsure);\ \n2. make sure that the relations and predicates that your proposition use are decidable;\ \n3. make sure that instances of `SlimCheck.Testable` exist that, when combined,\ \n apply to your decorated proposition:\ diff --git a/Mathlib/Tactic/SplitIfs.lean b/Mathlib/Tactic/SplitIfs.lean index d648be56512c6..97bfe7da56045 100644 --- a/Mathlib/Tactic/SplitIfs.lean +++ b/Mathlib/Tactic/SplitIfs.lean @@ -74,7 +74,7 @@ private def discharge? (e : Expr) : SimpM (Option Expr) := do private def reduceIfsAt (loc : Location) : TacticM Unit := do let ctx ← SplitIf.getSimpContext let ctx := { ctx with config := { ctx.config with failIfUnchanged := false } } - let _ ← simpLocation ctx {} discharge? loc + let _ ← simpLocation ctx (← ({} : Simp.SimprocsArray).add `reduceCtorEq false) discharge? loc pure () /-- Splits a single if-then-else expression and then reduces the resulting goals. diff --git a/Mathlib/Tactic/StacksAttribute.lean b/Mathlib/Tactic/StacksAttribute.lean new file mode 100644 index 0000000000000..b370a472ffc45 --- /dev/null +++ b/Mathlib/Tactic/StacksAttribute.lean @@ -0,0 +1,168 @@ +/- +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 `stacks` attribute + +This allows tagging of mathlib lemmas with the corresponding +[Tags](https://stacks.math.columbia.edu/tags) from the Stacks Project. +-/ + +open Lean Elab + +namespace Mathlib.Stacks + +/-- `Tag` is the structure that carries the data of a Stacks Projects tag and a corresponding +Mathlib declaration. -/ +structure Tag where + /-- The name of the declaration with the given tag. -/ + declName : Name + /-- The Stacks Project tag. -/ + tag : String + /-- The (optional) comment that comes with the given tag. -/ + comment : String + deriving BEq, Hashable + +/-- Defines the `tagExt` extension for adding a `HashSet` of `Tag`s +to the environment. -/ +initialize tagExt : SimplePersistentEnvExtension Tag (Std.HashSet Tag) ← + registerSimplePersistentEnvExtension { + addImportedFn := fun as => as.foldl Std.HashSet.insertMany {} + addEntryFn := .insert + } + +/-- +`addTagEntry declName tag comment` takes as input the `Name` `declName` of a declaration and +the `String`s `tag` and `comment` of the `stacks` attribute. +It extends the `Tag` environment extension with the data `declName, tag, comment`. +-/ +def addTagEntry {m : Type → Type} [MonadEnv m] (declName : Name) (tag comment : String) : m Unit := + modifyEnv (tagExt.addEntry · { declName := declName, tag := tag, comment := comment }) + +open Parser + +/-- `stacksTag` is the node kind of Stacks Project Tags: a sequence of digits and +uppercase letters. -/ +abbrev stacksTagKind : SyntaxNodeKind := `stacksTag + +/-- The main parser for Stacks Project Tags: it accepts any sequence of 4 digits or +uppercase letters. -/ +def stacksTagFn : ParserFn := fun c s => + let i := s.pos + let s := takeWhileFn (fun c => c.isAlphanum) c s + if s.hasError then + s + else if s.pos == i then + ParserState.mkError s "stacks tag" + else + let tag := Substring.mk c.input i s.pos |>.toString + if !tag.all fun c => c.isDigit || c.isUpper then + ParserState.mkUnexpectedError s + "Stacks tags must consist only of digits and uppercase letters." + else if tag.length != 4 then + ParserState.mkUnexpectedError s "Stacks tags must be exactly 4 characters" + else + mkNodeToken stacksTagKind i c s + +@[inherit_doc stacksTagFn] +def stacksTagNoAntiquot : Parser := { + fn := stacksTagFn + info := mkAtomicInfo "stacksTag" +} + +@[inherit_doc stacksTagFn] +def stacksTag : Parser := + withAntiquot (mkAntiquot "stacksTag" stacksTagKind) stacksTagNoAntiquot + +end Mathlib.Stacks + +open Mathlib.Stacks + +/-- Extract the underlying tag as a string from a `stacksTag` node. -/ +def Lean.TSyntax.getStacksTag (stx : TSyntax stacksTagKind) : CoreM String := do + let some val := Syntax.isLit? stacksTagKind stx | throwError "Malformed Stacks tag" + return val + +namespace Lean.PrettyPrinter + +namespace Formatter + +/-- The formatter for Stacks Project Tags syntax. -/ +@[combinator_formatter stacksTagNoAntiquot] def stacksTagNoAntiquot.formatter := + visitAtom stacksTagKind + +end Formatter + +namespace Parenthesizer + +/-- The parenthesizer for Stacks Project Tags syntax. -/ +@[combinator_parenthesizer stacksTagNoAntiquot] def stacksTagAntiquot.parenthesizer := visitToken + +end Lean.PrettyPrinter.Parenthesizer + +namespace Mathlib.Stacks + +/-- The `stacks` attribute. +Use it as `@[stacks TAG "Optional comment"]`. +The `TAG` is mandatory and should be a sequence of 4 digits or uppercase letters. + +See the [Tags page](https://stacks.math.columbia.edu/tags) in the Stacks project for more details. +-/ +syntax (name := stacks) "stacks " stacksTag (ppSpace str)? : attr + +initialize Lean.registerBuiltinAttribute { + name := `stacks + descr := "Apply a Stacks project tag to a theorem." + add := fun decl stx _attrKind => match stx with + | `(attr| stacks $tag $[$comment]?) => do + addTagEntry decl (← tag.getStacksTag) <| (comment.map (·.getString)).getD "" + | _ => throwUnsupportedSyntax +} + +end Mathlib.Stacks + +/-- +`getSortedStackProjectTags env` returns the array of `Tags`, sorted by alphabetical order of tag. +-/ +def Lean.Environment.getSortedStackProjectTags (env : Environment) : Array Tag := + tagExt.getState env |>.toArray.qsort (·.tag < ·.tag) + +/-- +`getSortedStackProjectDeclNames env tag` returns the array of declaration names of results +with Stacks Project tag equal to `tag`. +-/ +def Lean.Environment.getSortedStackProjectDeclNames (env : Environment) (tag : String) : + Array Name := + let tags := env.getSortedStackProjectTags + tags.filterMap fun d => if d.tag == tag then some d.declName else none + +/-- +`#stacks_tags` retrieves all declarations that have the `stacks` attribute. + +For each found declaration, it prints a line +``` +'declaration_name' corresponds to tag 'declaration_tag'. +``` +The variant `#stacks_tags!` also adds the theorem statement after each summary line. +-/ +elab (name := Mathlib.Stacks.stacksTags) "#stacks_tags" tk:("!")?: command => do + let env ← getEnv + let entries := env.getSortedStackProjectTags + if entries.isEmpty then logInfo "No tags found." else + let mut msgs := #[m!""] + for d in entries do + let dname ← Command.liftCoreM do realizeGlobalConstNoOverloadWithInfo (mkIdent d.declName) + let (parL, parR) := if d.comment.isEmpty then ("", "") else (" (", ")") + let cmt := parL ++ d.comment ++ parR + msgs := msgs.push + m!"[Stacks Tag {d.tag}](https://stacks.math.columbia.edu/tag/{d.tag}) \ + corresponds to declaration '{dname}'.{cmt}" + if tk.isSome then + let dType := ((env.find? dname).getD default).type + msgs := (msgs.push m!"{dType}").push "" + let msg := MessageData.joinSep msgs.toList "\n" + logInfo msg diff --git a/Mathlib/Tactic/Subsingleton.lean b/Mathlib/Tactic/Subsingleton.lean index 1a6dbcd2f6260..b5b8b9b18f06a 100644 --- a/Mathlib/Tactic/Subsingleton.lean +++ b/Mathlib/Tactic/Subsingleton.lean @@ -96,8 +96,9 @@ def Lean.MVarId.subsingleton (g : MVarId) (insts : Array (Term × AbstractMVarsR if ← (Meta.isProp xTy <&&> Meta.isProp yTy) then g.assign <| mkApp4 (.const ``proof_irrel_heq []) xTy yTy x y return - throwError "tactic 'subsingleton' could not prove heterogenous equality" - throwError "tactic 'subsingleton' failed, goal is neither an equality nor heterogenous equality" + throwError "tactic 'subsingleton' could not prove heterogeneous equality" + throwError "tactic 'subsingleton' failed, goal is neither an equality nor a \ + heterogeneous equality" namespace Mathlib.Tactic @@ -116,7 +117,7 @@ As a nicety, `subsingleton` first runs the `intros` tactic. Techniques the `subsingleton` tactic can apply: - proof irrelevance -- heterogenous proof irrelevance (via `proof_irrel_heq`) +- heterogeneous proof irrelevance (via `proof_irrel_heq`) - using `Subsingleton` (via `Subsingleton.elim`) - proving `BEq` instances are equal if they are both lawful (via `lawful_beq_subsingleton`) diff --git a/Mathlib/Tactic/SuppressCompilation.lean b/Mathlib/Tactic/SuppressCompilation.lean index aa50ea360913e..f647b5f2a31be 100644 --- a/Mathlib/Tactic/SuppressCompilation.lean +++ b/Mathlib/Tactic/SuppressCompilation.lean @@ -8,7 +8,7 @@ import Lean.Elab.Declaration import Lean.Elab.Notation /-! -# Supressing compilation to executable code in a file or in a section +# Suppressing compilation to executable code in a file or in a section Currently, the compiler may spend a lot of time trying to produce executable code for complicated definitions. This is a waste of resources for definitions in area of mathematics that will never diff --git a/Mathlib/Tactic/TFAE.lean b/Mathlib/Tactic/TFAE.lean index a5508905dec20..6eaad297bad50 100644 --- a/Mathlib/Tactic/TFAE.lean +++ b/Mathlib/Tactic/TFAE.lean @@ -101,7 +101,7 @@ where variable (hyps : Array (ℕ × ℕ × Expr)) (atoms : Array Q(Prop)) /-- Uses depth-first search to find a path from `P` to `P'`. -/ -partial def dfs (i j : ℕ) (P P' : Q(Prop)) (hP : Q($P)) : StateT (HashSet ℕ) MetaM Q($P') := do +partial def dfs (i j : ℕ) (P P' : Q(Prop)) (hP : Q($P)) : StateT (Std.HashSet ℕ) MetaM Q($P') := do if i == j then return hP modify (·.insert i) diff --git a/Mathlib/Tactic/TermCongr.lean b/Mathlib/Tactic/TermCongr.lean index 39a1d386b6041..5ec0c3b92a6bf 100644 --- a/Mathlib/Tactic/TermCongr.lean +++ b/Mathlib/Tactic/TermCongr.lean @@ -103,7 +103,7 @@ Note that there is no relation between `val` and the proof. We need to decouple these to support letting the proof's elaboration be deferred until we know whether we want an iff, eq, or heq, while also allowing it to choose to elaborate as an iff, eq, or heq. -Later, the congruence generator handles any discrepencies. +Later, the congruence generator handles any discrepancies. See `Mathlib.Tactic.TermCongr.CongrResult`. -/ @[reducible, nolint unusedArguments] def cHole {α : Sort u} (val : α) {p : Prop} (_pf : p) : α := val @@ -139,7 +139,7 @@ def cHole? (e : Expr) (mvarCounterSaved? : Option Nat := none) : Option (Bool × return (forLhs, val, pf) | _ => none -/-- Returns any subexpression that is a recent congruence hole. -/ +/-- Returns any subexpression that is a recent congruence hole. -/ def hasCHole (mvarCounterSaved : Nat) (e : Expr) : Option Expr := e.find? fun e' => (cHole? e' mvarCounterSaved).isSome diff --git a/Mathlib/Tactic/ToAdditive/Frontend.lean b/Mathlib/Tactic/ToAdditive/Frontend.lean index f1201fe61ce4c..7cc265e516329 100644 --- a/Mathlib/Tactic/ToAdditive/Frontend.lean +++ b/Mathlib/Tactic/ToAdditive/Frontend.lean @@ -13,8 +13,9 @@ import Mathlib.Lean.Name import Lean.Elab.Tactic.Ext import Lean.Meta.Tactic.Symm import Lean.Meta.Tactic.Rfl +import Lean.Meta.Match.MatcherInfo import Batteries.Lean.NameMapAttribute -import Batteries.Tactic.Lint -- useful to lint this file and for for DiscrTree.elements +import Batteries.Tactic.Lint -- useful to lint this file and for DiscrTree.elements import Mathlib.Tactic.Relation.Trans -- just to copy the attribute import Mathlib.Tactic.Eqns -- just to copy the attribute import Mathlib.Tactic.Simps.Basic @@ -816,6 +817,12 @@ partial def transformDeclAux selectionRange := ← getDeclarationRange cfg.ref } if isProtected (← getEnv) src then setEnv <| addProtected (← getEnv) tgt + if let some matcherInfo ← getMatcherInfo? src then + /- + Use `Match.addMatcherInfo tgt matcherInfo` + once https://github.com/leanprover/lean4/pull/5068 is in + -/ + modifyEnv fun env => Match.Extension.addMatcherInfo env tgt matcherInfo /-- Copy the instance attribute in a `to_additive` @@ -1217,7 +1224,7 @@ partial def copyMetaData (cfg : Config) (src tgt : Name) : CoreM (Array Name) := definitions. If we don't do that, the equation lemma for `src` might be generated later when doing a `rw`, but it won't be generated for `tgt`. -/ additivizeLemmas #[src, tgt] "equation lemmas" fun nm ↦ - (·.getD #[]) <$> MetaM.run' (getEqnsFor? nm true) + (·.getD #[]) <$> MetaM.run' (getEqnsFor? nm) MetaM.run' <| Elab.Term.TermElabM.run' <| applyAttributes cfg.ref cfg.attrs `to_additive src tgt @@ -1500,3 +1507,5 @@ initialize registerBuiltinAttribute { } end ToAdditive + +set_option linter.style.longFile 1700 diff --git a/Mathlib/Tactic/Variable.lean b/Mathlib/Tactic/Variable.lean index ae6e4f39f4ddb..ce1dd2966519a 100644 --- a/Mathlib/Tactic/Variable.lean +++ b/Mathlib/Tactic/Variable.lean @@ -250,7 +250,7 @@ def elabVariables : CommandElab := fun stx => where extendScope (binders : TSyntaxArray ``bracketedBinder) : CommandElabM Unit := do for binder in binders do - let varUIds ← getBracketedBinderIds binder |>.mapM + let varUIds ← (← getBracketedBinderIds binder) |>.mapM (withFreshMacroScope ∘ MonadQuotation.addMacroScope) modifyScope fun scope => { scope with varDecls := scope.varDecls.push binder, varUIds := scope.varUIds ++ varUIds } @@ -270,7 +270,7 @@ where Term.withAutoBoundImplicit <| Term.elabBinders binders fun _ => pure () -- Filter out omitted binders let binders' : TSyntaxArray ``bracketedBinder := - (binders.zip toOmit).filterMap fun (b, omit) => if omit then none else some b + (binders.zip toOmit).filterMap fun (b, toOmit) => if toOmit then none else some b if let some expectedBinders := expectedBinders? then trace[«variable?»] "checking expected binders" /- We re-elaborate the binders to create an expression that represents the entire resulting diff --git a/Mathlib/Tactic/Widget/StringDiagram.lean b/Mathlib/Tactic/Widget/StringDiagram.lean index 56a321a914335..5aca78961dfc3 100644 --- a/Mathlib/Tactic/Widget/StringDiagram.lean +++ b/Mathlib/Tactic/Widget/StringDiagram.lean @@ -215,11 +215,11 @@ structure PenroseVar : Type where instance : ToString PenroseVar := ⟨fun v => v.ident ++ v.indices.foldl (fun s x => s ++ s!"_{x}") ""⟩ -/-- The penrose variable assciated with a node. -/ +/-- The penrose variable associated with a node. -/ def Node.toPenroseVar (n : Node) : PenroseVar := ⟨"E", [n.vPos, n.hPosSrc, n.hPosTar], n.e⟩ -/-- The penrose variable assciated with a strand. -/ +/-- The penrose variable associated with a strand. -/ def Strand.toPenroseVar (s : Strand) : PenroseVar := ⟨"f", [s.vPos, s.hPos], s.atom₁.e⟩ diff --git a/Mathlib/Testing/SlimCheck/Functions.lean b/Mathlib/Testing/SlimCheck/Functions.lean index 7f0f7d67f8cb1..ddc576d88d833 100644 --- a/Mathlib/Testing/SlimCheck/Functions.lean +++ b/Mathlib/Testing/SlimCheck/Functions.lean @@ -335,7 +335,7 @@ theorem applyId_mem_iff [DecidableEq α] {xs ys : List α} (h₀ : List.Nodup xs · 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 - simp only [List.NodupKeys, List.keys, comp, Prod.fst_toSigma, List.map_map] + simp only [List.NodupKeys, List.keys, comp_def, Prod.fst_toSigma, List.map_map] rwa [List.map_fst_zip _ _ (le_of_eq h₆)] theorem List.applyId_eq_self [DecidableEq α] {xs ys : List α} (x : α) : @@ -430,9 +430,9 @@ protected def shrink {α : Type} [DecidableEq α] : have h₄ : ys'.length ≤ xs'.length := le_of_eq (List.Perm.length_eq h₀.symm) pure ⟨(List.zip xs' ys').map Prod.toSigma, - by simp only [comp, List.map_fst_zip, List.map_snd_zip, *, Prod.fst_toSigma, + by simp only [comp_def, List.map_fst_zip, List.map_snd_zip, *, Prod.fst_toSigma, Prod.snd_toSigma, List.map_map], - by simp only [comp, List.map_snd_zip, *, Prod.snd_toSigma, List.map_map]⟩ + by simp only [comp_def, List.map_snd_zip, *, Prod.snd_toSigma, List.map_map]⟩ /-- Create an injective function from one list and a permutation of that list. -/ protected def mk (xs ys : List α) (h : xs ~ ys) (h' : ys.Nodup) : InjectiveFunction α := @@ -440,9 +440,9 @@ protected def mk (xs ys : List α) (h : xs ~ ys) (h' : ys.Nodup) : InjectiveFunc have h₁ : ys.length ≤ xs.length := le_of_eq h.length_eq.symm InjectiveFunction.mapToSelf (List.toFinmap' (xs.zip ys)) (by - simp only [List.toFinmap', comp, List.map_fst_zip, List.map_snd_zip, *, Prod.fst_toSigma, + simp only [List.toFinmap', comp_def, List.map_fst_zip, List.map_snd_zip, *, Prod.fst_toSigma, Prod.snd_toSigma, List.map_map]) - (by simp only [List.toFinmap', comp, List.map_snd_zip, *, Prod.snd_toSigma, List.map_map]) + (by simp only [List.toFinmap', comp_def, List.map_snd_zip, *, Prod.snd_toSigma, List.map_map]) protected theorem injective [DecidableEq α] (f : InjectiveFunction α) : Injective (apply f) := by cases' f with xs hperm hnodup diff --git a/Mathlib/Testing/SlimCheck/Gen.lean b/Mathlib/Testing/SlimCheck/Gen.lean index a650357f85e5b..0f3d66842989e 100644 --- a/Mathlib/Testing/SlimCheck/Gen.lean +++ b/Mathlib/Testing/SlimCheck/Gen.lean @@ -92,7 +92,7 @@ def oneOf (xs : Array (Gen α)) (pos : 0 < xs.size := by decide) : Gen α := do /-- Given a list of examples, choose one to create an example. -/ def elements (xs : List α) (pos : 0 < xs.length) : Gen α := do let ⟨x, _, h2⟩ ← ULiftable.up <| chooseNatLt 0 xs.length pos - pure <| xs.get ⟨x, h2⟩ + pure <| xs[x] open List in /-- Generate a random permutation of a given list. -/ @@ -111,7 +111,7 @@ def prodOf {α : Type u} {β : Type v} (x : Gen α) (y : Gen β) : Gen (α × β end Gen -/-- Execute a `Gen` inside the `IO` monad using `size` as the example size-/ +/-- Execute a `Gen` inside the `IO` monad using `size` as the example size -/ def Gen.run {α : Type} (x : Gen α) (size : Nat) : BaseIO α := letI : MonadLift Id BaseIO := ⟨fun f => pure <| Id.run f⟩ IO.runRand (ReaderT.run x ⟨size⟩:) diff --git a/Mathlib/Testing/SlimCheck/Sampleable.lean b/Mathlib/Testing/SlimCheck/Sampleable.lean index b2c011792955b..f5cedcf3cb680 100644 --- a/Mathlib/Testing/SlimCheck/Sampleable.lean +++ b/Mathlib/Testing/SlimCheck/Sampleable.lean @@ -220,7 +220,7 @@ instance Bool.sampleableExt : SampleableExt Bool := /-- This can be specialized into customized `SampleableExt Char` instances. The resulting instance has `1 / length` chances of making an unrestricted choice of characters -and it otherwise chooses a character from `chars` with uniform probabilities. -/ +and it otherwise chooses a character from `chars` with uniform probabilities. -/ def Char.sampleable (length : Nat) (chars : List Char) (pos : 0 < chars.length) : SampleableExt Char := mkSelfContained do @@ -256,7 +256,7 @@ instance List.sampleableExt [SampleableExt α] : SampleableExt (List α) where end Samplers -/-- An annotation for values that should never get shrinked. -/ +/-- An annotation for values that should never get shrunk. -/ def NoShrink (α : Type u) := α namespace NoShrink diff --git a/Mathlib/Topology/Algebra/Algebra.lean b/Mathlib/Topology/Algebra/Algebra.lean index c229209194995..bcc728324280b 100644 --- a/Mathlib/Topology/Algebra/Algebra.lean +++ b/Mathlib/Topology/Algebra/Algebra.lean @@ -241,7 +241,7 @@ whose `TopologicalClosure` is `⊤` is sent to another such submodule. That is, the image of a dense subalgebra under a map with dense range is dense. -/ theorem _root_.DenseRange.topologicalClosure_map_subalgebra - [TopologicalSemiring B] {f : A →A[R] B} (hf' : DenseRange f) {s : Subalgebra R A} + [TopologicalSemiring B] {f : A →A[R] B} (hf' : DenseRange f) {s : Subalgebra R A} (hs : s.topologicalClosure = ⊤) : (s.map (f : A →ₐ[R] B)).topologicalClosure = ⊤ := by rw [SetLike.ext'_iff] at hs ⊢ simp only [Subalgebra.topologicalClosure_coe, coe_top, ← dense_iff_closure_eq, Subalgebra.coe_map, @@ -408,7 +408,7 @@ theorem fst_comp_prod (f : A →A[R] B) (g : A →A[R] C) : ext fun _x => rfl @[simp] -theorem snd_comp_prod (f : A →A[R] B) (g : A →A[R] C) : +theorem snd_comp_prod (f : A →A[R] B) (g : A →A[R] C) : (snd R B C).comp (f.prod g) = g := ext fun _x => rfl diff --git a/Mathlib/Topology/Algebra/ConstMulAction.lean b/Mathlib/Topology/Algebra/ConstMulAction.lean index 53ea74c2fe338..b76efc9f2c27f 100644 --- a/Mathlib/Topology/Algebra/ConstMulAction.lean +++ b/Mathlib/Topology/Algebra/ConstMulAction.lean @@ -504,7 +504,7 @@ alias set_smul_mem_nhds_smul_iff := smul_mem_nhds_smul_iff₀ alias ⟨_, smul_mem_nhds_smul₀⟩ := smul_mem_nhds_smul_iff₀ -@[deprecated smul_mem_nhds_smul₀ (since := "2024-08-06")] +@[deprecated smul_mem_nhds_smul₀ (since := "2024-08-06")] theorem set_smul_mem_nhds_smul {c : G₀} {s : Set α} {x : α} (hs : s ∈ 𝓝 x) (hc : c ≠ 0) : c • s ∈ 𝓝 (c • x : α) := smul_mem_nhds_smul₀ hc hs diff --git a/Mathlib/Topology/Algebra/Constructions.lean b/Mathlib/Topology/Algebra/Constructions.lean index 4ca7adfa8c318..96db33647784a 100644 --- a/Mathlib/Topology/Algebra/Constructions.lean +++ b/Mathlib/Topology/Algebra/Constructions.lean @@ -140,7 +140,7 @@ theorem continuous_val : Continuous ((↑) : Mˣ → M) := @[to_additive] protected theorem continuous_iff {f : X → Mˣ} : Continuous f ↔ Continuous (val ∘ f) ∧ Continuous (fun x => ↑(f x)⁻¹ : X → M) := by - simp only [inducing_embedProduct.continuous_iff, embedProduct_apply, (· ∘ ·), + simp only [inducing_embedProduct.continuous_iff, embedProduct_apply, Function.comp_def, continuous_prod_mk, opHomeomorph.symm.inducing.continuous_iff, opHomeomorph_symm_apply, unop_op] diff --git a/Mathlib/Topology/Algebra/FilterBasis.lean b/Mathlib/Topology/Algebra/FilterBasis.lean index 63619d775c916..e2732d46cdbb7 100644 --- a/Mathlib/Topology/Algebra/FilterBasis.lean +++ b/Mathlib/Topology/Algebra/FilterBasis.lean @@ -84,7 +84,7 @@ variable {G : Type u} [Group G] {B : GroupFilterBasis G} @[to_additive] instance : Membership (Set G) (GroupFilterBasis G) := - ⟨fun s f ↦ s ∈ f.sets⟩ + ⟨fun f s ↦ s ∈ f.sets⟩ @[to_additive] theorem one {U : Set G} : U ∈ B → (1 : G) ∈ U := @@ -149,10 +149,10 @@ theorem nhds_eq (B : GroupFilterBasis G) {x₀ : G} : @nhds G B.topology x₀ = filter_upwards [image_mem_map (B.mem_filter_of_mem V_in)] rintro _ ⟨x, hx, rfl⟩ calc - a • U ⊇ a • (V * V) := smul_set_mono hVU - _ ⊇ a • x • V := smul_set_mono <| smul_set_subset_smul hx - _ = (a * x) • V := smul_smul .. - _ ∈ (a * x) • B.filter := smul_set_mem_smul_filter <| B.mem_filter_of_mem V_in + (a * x) • V ∈ (a * x) • B.filter := smul_set_mem_smul_filter <| B.mem_filter_of_mem V_in + _ = a • x • V := smul_smul .. |>.symm + _ ⊆ a • (V * V) := smul_set_mono <| smul_set_subset_smul hx + _ ⊆ a • U := smul_set_mono hVU @[to_additive] theorem nhds_one_eq (B : GroupFilterBasis G) : @@ -224,7 +224,7 @@ namespace RingFilterBasis variable {R : Type u} [Ring R] (B : RingFilterBasis R) instance : Membership (Set R) (RingFilterBasis R) := - ⟨fun s B ↦ s ∈ B.sets⟩ + ⟨fun B s ↦ s ∈ B.sets⟩ theorem mul {U : Set R} (hU : U ∈ B) : ∃ V ∈ B, V * V ⊆ U := mul' hU @@ -284,7 +284,7 @@ variable {R M : Type*} [CommRing R] [TopologicalSpace R] [AddCommGroup M] [Modul (B : ModuleFilterBasis R M) instance GroupFilterBasis.hasMem : Membership (Set M) (ModuleFilterBasis R M) := - ⟨fun s B ↦ s ∈ B.sets⟩ + ⟨fun B s ↦ s ∈ B.sets⟩ theorem smul {U : Set M} (hU : U ∈ B) : ∃ V ∈ 𝓝 (0 : R), ∃ W ∈ B, V • W ⊆ U := B.smul' hU diff --git a/Mathlib/Topology/Algebra/Group/Basic.lean b/Mathlib/Topology/Algebra/Group/Basic.lean index 36c67204cd37c..4ef6b7171a58a 100644 --- a/Mathlib/Topology/Algebra/Group/Basic.lean +++ b/Mathlib/Topology/Algebra/Group/Basic.lean @@ -164,7 +164,7 @@ theorem ContinuousInv.induced {α : Type*} {β : Type*} {F : Type*} [FunLike F @ContinuousInv α (tβ.induced f) _ := by let _tα := tβ.induced f refine ⟨continuous_induced_rng.2 ?_⟩ - simp only [Function.comp, map_inv] + simp only [Function.comp_def, map_inv] fun_prop @[to_additive] @@ -376,7 +376,7 @@ end LatticeOps theorem Inducing.continuousInv {G H : Type*} [Inv G] [Inv H] [TopologicalSpace G] [TopologicalSpace H] [ContinuousInv H] {f : G → H} (hf : Inducing f) (hf_inv : ∀ x, f x⁻¹ = (f x)⁻¹) : ContinuousInv G := - ⟨hf.continuous_iff.2 <| by simpa only [(· ∘ ·), hf_inv] using hf.continuous.inv⟩ + ⟨hf.continuous_iff.2 <| by simpa only [Function.comp_def, hf_inv] using hf.continuous.inv⟩ section TopologicalGroup @@ -742,8 +742,8 @@ theorem continuous_of_continuousAt_one {M hom : Type*} [MulOneClass M] [Topologi (hf : ContinuousAt f 1) : Continuous f := continuous_iff_continuousAt.2 fun x => by - simpa only [ContinuousAt, ← map_mul_left_nhds_one x, tendsto_map'_iff, (· ∘ ·), map_mul, - map_one, mul_one] using hf.tendsto.const_mul (f x) + simpa only [ContinuousAt, ← map_mul_left_nhds_one x, tendsto_map'_iff, Function.comp_def, + map_mul, map_one, mul_one] using hf.tendsto.const_mul (f x) @[to_additive continuous_of_continuousAt_zero₂] theorem continuous_of_continuousAt_one₂ {H M : Type*} [CommMonoid M] [TopologicalSpace M] @@ -752,7 +752,7 @@ theorem continuous_of_continuousAt_one₂ {H M : Type*} [CommMonoid M] [Topologi (hl : ∀ x, ContinuousAt (f x) 1) (hr : ∀ y, ContinuousAt (f · y) 1) : Continuous (fun x : G × H ↦ f x.1 x.2) := continuous_iff_continuousAt.2 fun (x, y) => by simp only [ContinuousAt, nhds_prod_eq, ← map_mul_left_nhds_one x, ← map_mul_left_nhds_one y, - prod_map_map_eq, tendsto_map'_iff, (· ∘ ·), map_mul, MonoidHom.mul_apply] at * + prod_map_map_eq, tendsto_map'_iff, Function.comp_def, map_mul, MonoidHom.mul_apply] at * refine ((tendsto_const_nhds.mul ((hr y).comp tendsto_fst)).mul (((hl x).comp tendsto_snd).mul hf)).mono_right (le_of_eq ?_) simp only [map_one, mul_one, MonoidHom.one_apply] @@ -778,8 +778,8 @@ theorem ContinuousInv.of_nhds_one {G : Type*} [Group G] [TopologicalSpace G] refine ⟨continuous_iff_continuousAt.2 fun x₀ => ?_⟩ have : Tendsto (fun x => x₀⁻¹ * (x₀ * x⁻¹ * x₀⁻¹)) (𝓝 1) (map (x₀⁻¹ * ·) (𝓝 1)) := (tendsto_map.comp <| hconj x₀).comp hinv - simpa only [ContinuousAt, hleft x₀, hleft x₀⁻¹, tendsto_map'_iff, (· ∘ ·), mul_assoc, mul_inv_rev, - inv_mul_cancel_left] using this + simpa only [ContinuousAt, hleft x₀, hleft x₀⁻¹, tendsto_map'_iff, Function.comp_def, mul_assoc, + mul_inv_rev, inv_mul_cancel_left] using this @[to_additive] theorem TopologicalGroup.of_nhds_one' {G : Type u} [Group G] [TopologicalSpace G] @@ -806,7 +806,7 @@ theorem TopologicalGroup.of_nhds_one {G : Type u} [Group G] [TopologicalSpace G] replace hconj : ∀ x₀ : G, map (x₀ * · * x₀⁻¹) (𝓝 1) = 𝓝 1 := fun x₀ => map_eq_of_inverse (x₀⁻¹ * · * x₀⁻¹⁻¹) (by ext; simp [mul_assoc]) (hconj _) (hconj _) rw [← hconj x₀] - simpa [(· ∘ ·)] using hleft _ + simpa [Function.comp_def] using hleft _ @[to_additive] theorem TopologicalGroup.of_comm_of_nhds_one {G : Type u} [CommGroup G] [TopologicalSpace G] @@ -1915,3 +1915,5 @@ theorem coinduced_continuous {α β : Type*} [t : TopologicalSpace α] [Group β exact continuous_iff_coinduced_le.2 ht' end GroupTopology + +set_option linter.style.longFile 2100 diff --git a/Mathlib/Topology/Algebra/GroupWithZero.lean b/Mathlib/Topology/Algebra/GroupWithZero.lean index a363dc902e11b..b601051b87dc5 100644 --- a/Mathlib/Topology/Algebra/GroupWithZero.lean +++ b/Mathlib/Topology/Algebra/GroupWithZero.lean @@ -142,7 +142,7 @@ lemma nhds_inv₀ (hx : x ≠ 0) : 𝓝 x⁻¹ = (𝓝 x)⁻¹ := by lemma tendsto_inv_iff₀ {l : Filter α} {f : α → G₀} (hx : x ≠ 0) : Tendsto (fun x ↦ (f x)⁻¹) l (𝓝 x⁻¹) ↔ Tendsto f l (𝓝 x) := by - simp only [nhds_inv₀ hx, ← Filter.comap_inv, tendsto_comap_iff, (· ∘ ·), inv_inv] + simp only [nhds_inv₀ hx, ← Filter.comap_inv, tendsto_comap_iff, Function.comp_def, inv_inv] end NhdsInv @@ -300,7 +300,7 @@ theorem HasContinuousInv₀.of_nhds_one (h : Tendsto Inv.inv (𝓝 (1 : G₀)) ( have hx' := inv_ne_zero hx rw [ContinuousAt, ← map_mul_left_nhds_one₀ hx, ← nhds_translation_mul_inv₀ hx', tendsto_map'_iff, tendsto_comap_iff] - simpa only [(· ∘ ·), mul_inv_rev, mul_inv_cancel_right₀ hx'] + simpa only [Function.comp_def, mul_inv_rev, mul_inv_cancel_right₀ hx'] end map_comap diff --git a/Mathlib/Topology/Algebra/InfiniteSum/Defs.lean b/Mathlib/Topology/Algebra/InfiniteSum/Defs.lean index 53d82a6d80536..b4e52d99ca80c 100644 --- a/Mathlib/Topology/Algebra/InfiniteSum/Defs.lean +++ b/Mathlib/Topology/Algebra/InfiniteSum/Defs.lean @@ -90,8 +90,10 @@ def Multipliable (f : β → α) : Prop := ∃ a, HasProd f a open scoped Classical in -/-- `∏' i, f i` is the product of `f` it exists, or 1 otherwise. -/ -@[to_additive "`∑' i, f i` is the sum of `f` it exists, or 0 otherwise."] +/-- `∏' i, f i` is the product of `f` if it exists and is unconditionally convergent, +or 1 otherwise. -/ +@[to_additive "`∑' i, f i` is the sum of `f` if it exists and is unconditionally convergent, +or 0 otherwise."] noncomputable irreducible_def tprod {β} (f : β → α) := if h : Multipliable f then /- Note that the product might not be uniquely defined if the topology is not separated. diff --git a/Mathlib/Topology/Algebra/InfiniteSum/Group.lean b/Mathlib/Topology/Algebra/InfiniteSum/Group.lean index 06be853f4ac9d..9532cd4e53ab9 100644 --- a/Mathlib/Topology/Algebra/InfiniteSum/Group.lean +++ b/Mathlib/Topology/Algebra/InfiniteSum/Group.lean @@ -180,7 +180,7 @@ theorem cauchySeq_finset_iff_prod_vanishing : ∀ e ∈ 𝓝 (1 : α), ∃ s : Finset β, ∀ t, Disjoint t s → (∏ b ∈ t, f b) ∈ e := by classical simp only [CauchySeq, cauchy_map_iff, and_iff_right atTop_neBot, prod_atTop_atTop_eq, - uniformity_eq_comap_nhds_one α, tendsto_comap_iff, (· ∘ ·), atTop_neBot, true_and] + uniformity_eq_comap_nhds_one α, tendsto_comap_iff, Function.comp_def, atTop_neBot, true_and] rw [tendsto_atTop'] constructor · intro h e he diff --git a/Mathlib/Topology/Algebra/InfiniteSum/Module.lean b/Mathlib/Topology/Algebra/InfiniteSum/Module.lean index 1201d78d799cc..e8ef8f1cd13dc 100644 --- a/Mathlib/Topology/Algebra/InfiniteSum/Module.lean +++ b/Mathlib/Topology/Algebra/InfiniteSum/Module.lean @@ -240,7 +240,7 @@ variable {G : Type*} [Group G] {Γ : Subgroup G} @[to_additive "Given a subgroup `Γ` of an additive group `G`, and a function `f : G → M`, we automorphize `f` to a function `G ⧸ Γ → M` by summing over `Γ` orbits, `g ↦ ∑' (γ : Γ), f(γ • g)`."] -noncomputable def QuotientGroup.automorphize (f : G → M) : G ⧸ Γ → M := MulAction.automorphize f +noncomputable def QuotientGroup.automorphize (f : G → M) : G ⧸ Γ → M := MulAction.automorphize f /-- Automorphization of a function into an `R`-`Module` distributes, that is, commutes with the `R`-scalar multiplication. -/ diff --git a/Mathlib/Topology/Algebra/InfiniteSum/NatInt.lean b/Mathlib/Topology/Algebra/InfiniteSum/NatInt.lean index 09d1d25020184..688be889d23d8 100644 --- a/Mathlib/Topology/Algebra/InfiniteSum/NatInt.lean +++ b/Mathlib/Topology/Algebra/InfiniteSum/NatInt.lean @@ -74,7 +74,7 @@ theorem even_mul_odd {f : ℕ → M} (he : HasProd (fun k ↦ f (2 * k)) m) have := mul_right_injective₀ (two_ne_zero' ℕ) replace ho := ((add_left_injective 1).comp this).hasProd_range_iff.2 ho refine (this.hasProd_range_iff.2 he).mul_isCompl ?_ ho - simpa [(· ∘ ·)] using Nat.isCompl_even_odd + simpa [Function.comp_def] using Nat.isCompl_even_odd end ContinuousMul @@ -324,7 +324,7 @@ lemma HasProd.nat_mul_neg_add_one {f : ℤ → M} (hf : HasProd f m) : · rw [prod_union, prod_image Nat.cast_injective.injOn, prod_image this.injOn, prod_mul_distrib] simp only [disjoint_iff_ne, mem_image, ne_eq, forall_exists_index, and_imp, - forall_apply_eq_imp_iff₂, not_false_eq_true, implies_true, forall_const] + forall_apply_eq_imp_iff₂, not_false_eq_true, implies_true, forall_const, reduceCtorEq] @[to_additive Summable.nat_add_neg_add_one] lemma Multipliable.nat_mul_neg_add_one {f : ℤ → M} (hf : Multipliable f) : @@ -358,7 +358,7 @@ lemma HasProd.of_nat_of_neg_add_one {f : ℤ → M} @[to_additive Summable.of_nat_of_neg_add_one] lemma Multipliable.of_nat_of_neg_add_one {f : ℤ → M} - (hf₁ : Multipliable fun n : ℕ ↦ f n) (hf₂ : Multipliable fun n : ℕ ↦ f (-(n + 1))) : + (hf₁ : Multipliable fun n : ℕ ↦ f n) (hf₂ : Multipliable fun n : ℕ ↦ f (-(n + 1))) : Multipliable f := (hf₁.hasProd.of_nat_of_neg_add_one hf₂.hasProd).multipliable diff --git a/Mathlib/Topology/Algebra/InfiniteSum/Order.lean b/Mathlib/Topology/Algebra/InfiniteSum/Order.lean index a22caf1d21fd1..53773dace6081 100644 --- a/Mathlib/Topology/Algebra/InfiniteSum/Order.lean +++ b/Mathlib/Topology/Algebra/InfiniteSum/Order.lean @@ -14,9 +14,7 @@ import Mathlib.Topology.Order.MonotoneConvergence This file provides lemmas about the interaction of infinite sums and products and order operations. -/ - open Finset Filter Function -open scoped Classical variable {ι κ α : Type*} @@ -91,8 +89,9 @@ theorem prod_le_hasProd (s : Finset ι) (hs : ∀ i, i ∉ s → 1 ≤ f i) (hf @[to_additive] theorem isLUB_hasProd (h : ∀ i, 1 ≤ f i) (hf : HasProd f a) : - IsLUB (Set.range fun s ↦ ∏ i ∈ s, f i) a := - isLUB_of_tendsto_atTop (Finset.prod_mono_set_of_one_le' h) hf + IsLUB (Set.range fun s ↦ ∏ i ∈ s, f i) a := by + classical + exact isLUB_of_tendsto_atTop (Finset.prod_mono_set_of_one_le' h) hf @[to_additive] theorem le_hasProd (hf : HasProd f a) (i : ι) (hb : ∀ j, j ≠ i → 1 ≤ f j) : f i ≤ a := @@ -169,6 +168,7 @@ variable [OrderedCommGroup α] [TopologicalSpace α] [TopologicalGroup α] @[to_additive] theorem hasProd_lt (h : f ≤ g) (hi : f i < g i) (hf : HasProd f a₁) (hg : HasProd g a₂) : a₁ < a₂ := by + classical have : update f i 1 ≤ update g i 1 := update_le_update_iff.mpr ⟨rfl.le, fun i _ ↦ h i⟩ have : 1 / f i * a₁ ≤ 1 / g i * a₂ := hasProd_le this (hf.update i 1) (hg.update i 1) simpa only [one_div, mul_inv_cancel_left] using mul_lt_mul_of_lt_of_le hi this @@ -223,8 +223,9 @@ theorem tprod_ne_one_iff (hf : Multipliable f) : ∏' i, f i ≠ 1 ↔ ∃ x, f rw [Ne, tprod_eq_one_iff hf, not_forall] @[to_additive] -theorem isLUB_hasProd' (hf : HasProd f a) : IsLUB (Set.range fun s ↦ ∏ i ∈ s, f i) a := - isLUB_of_tendsto_atTop (Finset.prod_mono_set' f) hf +theorem isLUB_hasProd' (hf : HasProd f a) : IsLUB (Set.range fun s ↦ ∏ i ∈ s, f i) a := by + classical + exact isLUB_of_tendsto_atTop (Finset.prod_mono_set' f) hf end CanonicallyOrderedCommMonoid diff --git a/Mathlib/Topology/Algebra/InfiniteSum/Ring.lean b/Mathlib/Topology/Algebra/InfiniteSum/Ring.lean index c98296b0fb61f..6a1e6ade12789 100644 --- a/Mathlib/Topology/Algebra/InfiniteSum/Ring.lean +++ b/Mathlib/Topology/Algebra/InfiniteSum/Ring.lean @@ -17,11 +17,8 @@ This file provides lemmas about the interaction between infinite sums and multip * `tsum_mul_tsum_eq_tsum_sum_antidiagonal`: Cauchy product formula -/ - open Filter Finset Function -open scoped Classical - variable {ι κ R α : Type*} section NonUnitalNonAssocSemiring @@ -51,10 +48,11 @@ theorem Summable.tsum_mul_left (a) (hf : Summable f) : ∑' i, a * f i = a * ∑ theorem Summable.tsum_mul_right (a) (hf : Summable f) : ∑' i, f i * a = (∑' i, f i) * a := (hf.hasSum.mul_right _).tsum_eq -theorem Commute.tsum_right (a) (h : ∀ i, Commute a (f i)) : Commute a (∑' i, f i) := - if hf : Summable f then - (hf.tsum_mul_left a).symm.trans ((congr_arg _ <| funext h).trans (hf.tsum_mul_right a)) - else (tsum_eq_zero_of_not_summable hf).symm ▸ Commute.zero_right _ +theorem Commute.tsum_right (a) (h : ∀ i, Commute a (f i)) : Commute a (∑' i, f i) := by + classical + by_cases hf : Summable f + · exact (hf.tsum_mul_left a).symm.trans ((congr_arg _ <| funext h).trans (hf.tsum_mul_right a)) + · exact (tsum_eq_zero_of_not_summable hf).symm ▸ Commute.zero_right _ theorem Commute.tsum_left (a) (h : ∀ i, Commute (f i) a) : Commute (∑' i, f i) a := (Commute.tsum_right _ fun i ↦ (h i).symm).symm @@ -92,14 +90,16 @@ theorem summable_mul_right_iff (h : a ≠ 0) : (Summable fun i ↦ f i * a) ↔ theorem summable_div_const_iff (h : a ≠ 0) : (Summable fun i ↦ f i / a) ↔ Summable f := by simpa only [div_eq_mul_inv] using summable_mul_right_iff (inv_ne_zero h) -theorem tsum_mul_left [T2Space α] : ∑' x, a * f x = a * ∑' x, f x := - if hf : Summable f then hf.tsum_mul_left a +theorem tsum_mul_left [T2Space α] : ∑' x, a * f x = a * ∑' x, f x := by + classical + exact if hf : Summable f then hf.tsum_mul_left a else if ha : a = 0 then by simp [ha] else by rw [tsum_eq_zero_of_not_summable hf, tsum_eq_zero_of_not_summable (mt (summable_mul_left_iff ha).mp hf), mul_zero] -theorem tsum_mul_right [T2Space α] : ∑' x, f x * a = (∑' x, f x) * a := - if hf : Summable f then hf.tsum_mul_right a +theorem tsum_mul_right [T2Space α] : ∑' x, f x * a = (∑' x, f x) * a := by + classical + exact if hf : Summable f then hf.tsum_mul_right a else if ha : a = 0 then by simp [ha] else by rw [tsum_eq_zero_of_not_summable hf, tsum_eq_zero_of_not_summable (mt (summable_mul_right_iff ha).mp hf), zero_mul] diff --git a/Mathlib/Topology/Algebra/Module/Alternating/Basic.lean b/Mathlib/Topology/Algebra/Module/Alternating/Basic.lean index c6b9bc5f30347..0391d939b2f46 100644 --- a/Mathlib/Topology/Algebra/Module/Alternating/Basic.lean +++ b/Mathlib/Topology/Algebra/Module/Alternating/Basic.lean @@ -333,8 +333,8 @@ def _root_.ContinuousLinearEquiv.continuousAlternatingMapComp (e : M ≃L[R] M') M [⋀^ι]→L[R] N ≃ M' [⋀^ι]→L[R] N where toFun f := f.compContinuousLinearMap ↑e.symm invFun f := f.compContinuousLinearMap ↑e - left_inv f := by ext; simp [(· ∘ ·)] - right_inv f := by ext; simp [(· ∘ ·)] + left_inv f := by ext; simp [Function.comp_def] + right_inv f := by ext; simp [Function.comp_def] /-- A continuous linear equivalence of codomains defines an equivalence between continuous alternating maps. -/ @@ -618,12 +618,12 @@ def alternatization : ContinuousMultilinearMap R (fun _ : ι => M) N →+ M [⋀ theorem alternatization_apply_apply (v : ι → M) : alternatization f v = ∑ σ : Equiv.Perm ι, Equiv.Perm.sign σ • f (v ∘ σ) := by - simp [alternatization, (· ∘ ·)] + simp [alternatization, Function.comp_def] @[simp] theorem alternatization_apply_toAlternatingMap : (alternatization f).toAlternatingMap = MultilinearMap.alternatization f.1 := by ext v - simp [alternatization_apply_apply, MultilinearMap.alternatization_apply, (· ∘ ·)] + simp [alternatization_apply_apply, MultilinearMap.alternatization_apply, Function.comp_def] end ContinuousMultilinearMap diff --git a/Mathlib/Topology/Algebra/Module/Basic.lean b/Mathlib/Topology/Algebra/Module/Basic.lean index 03ce9dac62eb3..fd43144f79855 100644 --- a/Mathlib/Topology/Algebra/Module/Basic.lean +++ b/Mathlib/Topology/Algebra/Module/Basic.lean @@ -44,8 +44,9 @@ theorem ContinuousSMul.of_nhds_zero [TopologicalRing R] [TopologicalAddGroup M] (hmulleft : ∀ m : M, Tendsto (fun a : R => a • m) (𝓝 0) (𝓝 0)) (hmulright : ∀ a : R, Tendsto (fun m : M => a • m) (𝓝 0) (𝓝 0)) : ContinuousSMul R M where continuous_smul := by + rw [← nhds_prod_eq] at hmul refine continuous_of_continuousAt_zero₂ (AddMonoidHom.smul : R →+ M →+ M) ?_ ?_ ?_ <;> - simpa [ContinuousAt, nhds_prod_eq] + simpa [ContinuousAt] end @@ -251,7 +252,7 @@ class ContinuousSemilinearMapClass (F : Type*) {R S : outParam Type*} [Semiring /-- `ContinuousLinearMapClass F R M M₂` asserts `F` is a type of bundled continuous `R`-linear maps `M → M₂`. This is an abbreviation for -`ContinuousSemilinearMapClass F (RingHom.id R) M M₂`. -/ +`ContinuousSemilinearMapClass F (RingHom.id R) M M₂`. -/ abbrev ContinuousLinearMapClass (F : Type*) (R : outParam Type*) [Semiring R] (M : outParam Type*) [TopologicalSpace M] [AddCommMonoid M] (M₂ : outParam Type*) [TopologicalSpace M₂] [AddCommMonoid M₂] [Module R M] [Module R M₂] [FunLike F M M₂] := @@ -1637,8 +1638,6 @@ instance continuousSemilinearEquivClass : -- instance : CoeFun (M₁ ≃SL[σ₁₂] M₂) fun _ => M₁ → M₂ := -- ⟨fun f => f⟩ --- Porting note: Syntactic tautology. - theorem coe_apply (e : M₁ ≃SL[σ₁₂] M₂) (b : M₁) : (e : M₁ →SL[σ₁₂] M₂) b = e b := rfl @@ -1761,7 +1760,7 @@ theorem coe_refl : ↑(ContinuousLinearEquiv.refl R₁ M₁) = ContinuousLinearM theorem coe_refl' : ⇑(ContinuousLinearEquiv.refl R₁ M₁) = id := rfl -/-- The inverse of a continuous linear equivalence as a continuous linear equivalence-/ +/-- The inverse of a continuous linear equivalence as a continuous linear equivalence -/ @[symm] protected def symm (e : M₁ ≃SL[σ₁₂] M₂) : M₂ ≃SL[σ₂₁] M₁ := { e.toLinearEquiv.symm with @@ -1902,9 +1901,7 @@ theorem self_comp_symm (e : M₁ ≃SL[σ₁₂] M₂) : (e : M₁ → M₂) ∘ exact apply_symm_apply e x @[simp] -theorem symm_symm (e : M₁ ≃SL[σ₁₂] M₂) : e.symm.symm = e := by - ext x - rfl +theorem symm_symm (e : M₁ ≃SL[σ₁₂] M₂) : e.symm.symm = e := rfl @[simp] theorem refl_symm : (ContinuousLinearEquiv.refl R₁ M₁).symm = ContinuousLinearEquiv.refl R₁ M₁ := @@ -2234,8 +2231,6 @@ end ContinuousLinearEquiv namespace ContinuousLinearMap -open scoped Classical - variable {R : Type*} {M : Type*} {M₂ : Type*} [TopologicalSpace M] [TopologicalSpace M₂] section @@ -2244,6 +2239,7 @@ variable [Semiring R] variable [AddCommMonoid M₂] [Module R M₂] variable [AddCommMonoid M] [Module R M] +open Classical in /-- Introduce a function `inverse` from `M →L[R] M₂` to `M₂ →L[R] M`, which sends `f` to `f.symm` if `f` is a continuous linear equivalence and to `0` otherwise. This definition is somewhat ad hoc, but one needs a fully (rather than partially) defined inverse function for some purposes, including @@ -2393,3 +2389,5 @@ instance t3_quotient_of_isClosed [TopologicalAddGroup M] [IsClosed (S : Set M)] end Submodule end Quotient + +set_option linter.style.longFile 2500 diff --git a/Mathlib/Topology/Algebra/Module/CharacterSpace.lean b/Mathlib/Topology/Algebra/Module/CharacterSpace.lean index 98892800dddf3..aa4aeffcdfcb1 100644 --- a/Mathlib/Topology/Algebra/Module/CharacterSpace.lean +++ b/Mathlib/Topology/Algebra/Module/CharacterSpace.lean @@ -212,7 +212,7 @@ variable (𝕜 A) [CommRing 𝕜] [NoZeroDivisors 𝕜] [TopologicalSpace 𝕜] /-- The **Gelfand transform** is an algebra homomorphism (over `𝕜`) from a topological `𝕜`-algebra `A` into the `𝕜`-algebra of continuous `𝕜`-valued functions on the `characterSpace 𝕜 A`. -The character space itself consists of all algebra homomorphisms from `A` to `𝕜`. -/ +The character space itself consists of all algebra homomorphisms from `A` to `𝕜`. -/ @[simps] def gelfandTransform : A →ₐ[𝕜] C(characterSpace 𝕜 A, 𝕜) where toFun a := diff --git a/Mathlib/Topology/Algebra/Module/LinearPMap.lean b/Mathlib/Topology/Algebra/Module/LinearPMap.lean index bc1ef73338c9b..dc97ddf2c8859 100644 --- a/Mathlib/Topology/Algebra/Module/LinearPMap.lean +++ b/Mathlib/Topology/Algebra/Module/LinearPMap.lean @@ -85,8 +85,7 @@ theorem IsClosable.existsUnique {f : E →ₗ.[R] F} (hf : f.IsClosable) : refine exists_unique_of_exists_of_unique hf fun _ _ hy₁ hy₂ => eq_of_eq_graph ?_ rw [← hy₁, ← hy₂] -open scoped Classical - +open Classical in /-- If `f` is closable, then `f.closure` is the closure. Otherwise it is defined as `f.closure = f`. -/ noncomputable def closure (f : E →ₗ.[R] F) : E →ₗ.[R] F := diff --git a/Mathlib/Topology/Algebra/Module/Multilinear/Bounded.lean b/Mathlib/Topology/Algebra/Module/Multilinear/Bounded.lean index 6b8d509bb8ec2..85af2419a28c0 100644 --- a/Mathlib/Topology/Algebra/Module/Multilinear/Bounded.lean +++ b/Mathlib/Topology/Algebra/Module/Multilinear/Bounded.lean @@ -67,10 +67,7 @@ theorem image_multilinear' [Nonempty ι] {s : Set (∀ i, E i)} (hs : IsVonNBoun let ⟨i₀⟩ := ‹Nonempty ι› set y := I.piecewise (fun i ↦ c i • x i) x calc - a • f x = f (update y i₀ ((a / ∏ i ∈ I, c i) • y i₀)) := by - rw [f.map_smul, update_eq_self, f.map_piecewise_smul, div_eq_mul_inv, mul_smul, - inv_smul_smul₀ hc₀'] - _ ∈ V := hft fun i hi ↦ by + f (update y i₀ ((a / ∏ i ∈ I, c i) • y i₀)) ∈ V := hft fun i hi => by rcases eq_or_ne i i₀ with rfl | hne · simp_rw [update_same, y, I.piecewise_eq_of_mem _ _ hi, smul_smul] refine hc _ _ ?_ _ hx @@ -81,6 +78,9 @@ theorem image_multilinear' [Nonempty ι] {s : Set (∀ i, E i)} (hs : IsVonNBoun _ = ‖c i‖ := one_mul _ · simp_rw [update_noteq hne, y, I.piecewise_eq_of_mem _ _ hi] exact hc _ _ le_rfl _ hx + _ = a • f x := by + rw [f.map_smul, update_eq_self, f.map_piecewise_smul, div_eq_mul_inv, mul_smul, + inv_smul_smul₀ hc₀'] /-- The image of a von Neumann bounded set under a continuous multilinear map is von Neumann bounded. diff --git a/Mathlib/Topology/Algebra/Module/StrongTopology.lean b/Mathlib/Topology/Algebra/Module/StrongTopology.lean index a66e7b2cf135a..437453ea31e0d 100644 --- a/Mathlib/Topology/Algebra/Module/StrongTopology.lean +++ b/Mathlib/Topology/Algebra/Module/StrongTopology.lean @@ -63,7 +63,8 @@ section General variable {𝕜₁ 𝕜₂ : Type*} [NormedField 𝕜₁] [NormedField 𝕜₂] (σ : 𝕜₁ →+* 𝕜₂) {E F : Type*} [AddCommGroup E] [Module 𝕜₁ E] [TopologicalSpace E] - [AddCommGroup F] [Module 𝕜₂ F] (F) + [AddCommGroup F] [Module 𝕜₂ F] +variable (F) /-- Given `E` and `F` two topological vector spaces and `𝔖 : Set (Set E)`, then `UniformConvergenceCLM σ F 𝔖` is a type synonym of `E →SL[σ] F` equipped with the "topology of diff --git a/Mathlib/Topology/Algebra/Monoid.lean b/Mathlib/Topology/Algebra/Monoid.lean index 7d976664104f1..c2bebad5ed312 100644 --- a/Mathlib/Topology/Algebra/Monoid.lean +++ b/Mathlib/Topology/Algebra/Monoid.lean @@ -18,14 +18,10 @@ applications the underlying type is a monoid (multiplicative or additive), we do the definitions. -/ - universe u v -open scoped Classical open Set Filter TopologicalSpace - -open scoped Classical -open Topology Pointwise +open scoped Topology Pointwise variable {ι α M N X : Type*} [TopologicalSpace X] @@ -87,7 +83,7 @@ theorem ContinuousMul.induced {α : Type*} {β : Type*} {F : Type*} [FunLike F @ContinuousMul α (tβ.induced f) _ := by let tα := tβ.induced f refine ⟨continuous_induced_rng.2 ?_⟩ - simp only [Function.comp, map_mul] + simp only [Function.comp_def, map_mul] fun_prop @[to_additive (attr := continuity, fun_prop)] diff --git a/Mathlib/Topology/Algebra/MulAction.lean b/Mathlib/Topology/Algebra/MulAction.lean index 30ec72337a896..92b5c88ea7ba5 100644 --- a/Mathlib/Topology/Algebra/MulAction.lean +++ b/Mathlib/Topology/Algebra/MulAction.lean @@ -85,7 +85,7 @@ theorem ContinuousSMul.induced {R : Type*} {α : Type*} {β : Type*} {F : Type*} (f : F) : @ContinuousSMul R α _ _ (tβ.induced f) := by let tα := tβ.induced f refine ⟨continuous_induced_rng.2 ?_⟩ - simp only [Function.comp, map_smul] + simp only [Function.comp_def, map_smul] fun_prop @[to_additive] diff --git a/Mathlib/Topology/Algebra/OpenSubgroup.lean b/Mathlib/Topology/Algebra/OpenSubgroup.lean index 025b15e34f7a6..5512c7f43dcb2 100644 --- a/Mathlib/Topology/Algebra/OpenSubgroup.lean +++ b/Mathlib/Topology/Algebra/OpenSubgroup.lean @@ -10,7 +10,7 @@ import Mathlib.Topology.Sets.Opens /-! # Open subgroups of a topological groups -This files builds the lattice `OpenSubgroup G` of open subgroups in a topological group `G`, +This files builds the lattice `OpenSubgroup G` of open subgroups in a topological group `G`, and its additive version `OpenAddSubgroup`. This lattice has a top element, the subgroup of all elements, but no bottom element in general. The trivial subgroup which is the natural candidate bottom has no reason to be open (this happens only in discrete groups). diff --git a/Mathlib/Topology/Algebra/Order/Compact.lean b/Mathlib/Topology/Algebra/Order/Compact.lean index 79a810fef5137..1f1e14890b141 100644 --- a/Mathlib/Topology/Algebra/Order/Compact.lean +++ b/Mathlib/Topology/Algebra/Order/Compact.lean @@ -250,7 +250,8 @@ theorem cocompact_eq_atTop [NoMaxOrder α] [OrderBot α] theorem IsCompact.exists_isMinOn [ClosedIicTopology α] {s : Set β} (hs : IsCompact s) (ne_s : s.Nonempty) {f : β → α} (hf : ContinuousOn f s) : ∃ x ∈ s, IsMinOn f s x := by rcases (hs.image_of_continuousOn hf).exists_isLeast (ne_s.image f) with ⟨_, ⟨x, hxs, rfl⟩, hx⟩ - exact ⟨x, hxs, forall_mem_image.1 hx⟩ + refine ⟨x, hxs, forall_mem_image.1 (fun _ hb => hx <| mem_image_of_mem f ?_)⟩ + rwa [(image_id' s).symm] /-- If a continuous function lies strictly above `a` on a compact set, it has a lower bound strictly above `a`. -/ @@ -263,23 +264,11 @@ theorem IsCompact.exists_forall_le' [ClosedIicTopology α] [NoMaxOrder α] {f : · obtain ⟨x, hx, hx'⟩ := hs.exists_isMinOn hs' hf exact ⟨f x, hf' x hx, hx'⟩ -/-- The **extreme value theorem**: a continuous function realizes its minimum on a compact set. -/ -@[deprecated IsCompact.exists_isMinOn (since := "2023-02-06")] -theorem IsCompact.exists_forall_le [ClosedIicTopology α] {s : Set β} (hs : IsCompact s) - (ne_s : s.Nonempty) {f : β → α} (hf : ContinuousOn f s) : ∃ x ∈ s, ∀ y ∈ s, f x ≤ f y := - hs.exists_isMinOn ne_s hf - /-- The **extreme value theorem**: a continuous function realizes its maximum on a compact set. -/ theorem IsCompact.exists_isMaxOn [ClosedIciTopology α] {s : Set β} (hs : IsCompact s) (ne_s : s.Nonempty) {f : β → α} (hf : ContinuousOn f s) : ∃ x ∈ s, IsMaxOn f s x := IsCompact.exists_isMinOn (α := αᵒᵈ) hs ne_s hf -/-- The **extreme value theorem**: a continuous function realizes its maximum on a compact set. -/ -@[deprecated IsCompact.exists_isMaxOn (since := "2023-02-06")] -theorem IsCompact.exists_forall_ge [ClosedIciTopology α] {s : Set β} (hs : IsCompact s) - (ne_s : s.Nonempty) {f : β → α} (hf : ContinuousOn f s) : ∃ x ∈ s, ∀ y ∈ s, f y ≤ f x := - IsCompact.exists_isMaxOn hs ne_s hf - /-- The **extreme value theorem**: if a function `f` is continuous on a closed set `s` and it is larger than a value in its image away from compact sets, then it has a minimum on this set. -/ theorem ContinuousOn.exists_isMinOn' [ClosedIicTopology α] {s : Set β} {f : β → α} @@ -293,14 +282,6 @@ theorem ContinuousOn.exists_isMinOn' [ClosedIicTopology α] {s : Set β} {f : β by_cases hyK : y ∈ K exacts [hxf _ (Or.inr ⟨hyK, hy⟩), (hxf _ (Or.inl rfl)).trans (hKf ⟨hyK, hy⟩)] -/-- The **extreme value theorem**: if a function `f` is continuous on a closed set `s` and it is -larger than a value in its image away from compact sets, then it has a minimum on this set. -/ -@[deprecated ContinuousOn.exists_isMinOn' (since := "2023-02-06")] -theorem ContinuousOn.exists_forall_le' [ClosedIicTopology α] {s : Set β} {f : β → α} - (hf : ContinuousOn f s) (hsc : IsClosed s) {x₀ : β} (h₀ : x₀ ∈ s) - (hc : ∀ᶠ x in cocompact β ⊓ 𝓟 s, f x₀ ≤ f x) : ∃ x ∈ s, ∀ y ∈ s, f x ≤ f y := - hf.exists_isMinOn' hsc h₀ hc - /-- The **extreme value theorem**: if a function `f` is continuous on a closed set `s` and it is smaller than a value in its image away from compact sets, then it has a maximum on this set. -/ theorem ContinuousOn.exists_isMaxOn' [ClosedIciTopology α] {s : Set β} {f : β → α} @@ -308,14 +289,6 @@ theorem ContinuousOn.exists_isMaxOn' [ClosedIciTopology α] {s : Set β} {f : β (hc : ∀ᶠ x in cocompact β ⊓ 𝓟 s, f x ≤ f x₀) : ∃ x ∈ s, IsMaxOn f s x := ContinuousOn.exists_isMinOn' (α := αᵒᵈ) hf hsc h₀ hc -/-- The **extreme value theorem**: if a function `f` is continuous on a closed set `s` and it is -smaller than a value in its image away from compact sets, then it has a maximum on this set. -/ -@[deprecated ContinuousOn.exists_isMaxOn' (since := "2023-02-06")] -theorem ContinuousOn.exists_forall_ge' [ClosedIciTopology α] {s : Set β} {f : β → α} - (hf : ContinuousOn f s) (hsc : IsClosed s) {x₀ : β} (h₀ : x₀ ∈ s) - (hc : ∀ᶠ x in cocompact β ⊓ 𝓟 s, f x ≤ f x₀) : ∃ x ∈ s, ∀ y ∈ s, f y ≤ f x := - hf.exists_isMaxOn' hsc h₀ hc - /-- The **extreme value theorem**: if a continuous function `f` is larger than a value in its range away from compact sets, then it has a global minimum. -/ theorem Continuous.exists_forall_le' [ClosedIicTopology α] {f : β → α} (hf : Continuous f) @@ -490,13 +463,6 @@ theorem IsCompact.exists_isMaxOn_mem_subset [ClosedIciTopology α] {f : β → let ⟨x, hxt, hfx⟩ := ht.exists_isMaxOn ⟨z, hz⟩ hf ⟨x, by_contra fun hxs => (hfz x ⟨hxt, hxs⟩).not_le (hfx hz), hfx⟩ -@[deprecated IsCompact.exists_isMinOn_mem_subset (since := "2023-02-06")] -theorem IsCompact.exists_isLocalMinOn_mem_subset [ClosedIicTopology α] {f : β → α} {s t : Set β} - {z : β} (ht : IsCompact t) (hf : ContinuousOn f t) (hz : z ∈ t) - (hfz : ∀ z' ∈ t \ s, f z < f z') : ∃ x ∈ s, IsLocalMinOn f t x := - let ⟨x, hxs, h⟩ := ht.exists_isMinOn_mem_subset hf hz hfz - ⟨x, hxs, h.localize⟩ - -- Porting note: rfc: assume `t ∈ 𝓝ˢ s` (a.k.a. `s ⊆ interior t`) instead of `s ⊆ t` and -- `IsOpen s`? theorem IsCompact.exists_isLocalMin_mem_open [ClosedIicTopology α] {f : β → α} {s t : Set β} diff --git a/Mathlib/Topology/Algebra/Order/Field.lean b/Mathlib/Topology/Algebra/Order/Field.lean index 39438737e3443..210984070446a 100644 --- a/Mathlib/Topology/Algebra/Order/Field.lean +++ b/Mathlib/Topology/Algebra/Order/Field.lean @@ -75,7 +75,8 @@ tends to a negative constant `C` then `f * g` tends to `Filter.atBot`. -/ theorem Filter.Tendsto.atTop_mul_neg {C : 𝕜} (hC : C < 0) (hf : Tendsto f l atTop) (hg : Tendsto g l (𝓝 C)) : Tendsto (fun x => f x * g x) l atBot := by have := hf.atTop_mul (neg_pos.2 hC) hg.neg - simpa only [(· ∘ ·), neg_mul_eq_mul_neg, neg_neg] using tendsto_neg_atTop_atBot.comp this + simpa only [Function.comp_def, neg_mul_eq_mul_neg, neg_neg] using + tendsto_neg_atTop_atBot.comp this /-- In a linearly ordered field with the order topology, if `f` tends to a negative constant `C` and `g` tends to `Filter.atTop` then `f * g` tends to `Filter.atBot`. -/ @@ -88,14 +89,14 @@ tends to a positive constant `C` then `f * g` tends to `Filter.atBot`. -/ theorem Filter.Tendsto.atBot_mul {C : 𝕜} (hC : 0 < C) (hf : Tendsto f l atBot) (hg : Tendsto g l (𝓝 C)) : Tendsto (fun x => f x * g x) l atBot := by have := (tendsto_neg_atBot_atTop.comp hf).atTop_mul hC hg - simpa [(· ∘ ·)] using tendsto_neg_atTop_atBot.comp this + simpa [Function.comp_def] using tendsto_neg_atTop_atBot.comp this /-- In a linearly ordered field with the order topology, if `f` tends to `Filter.atBot` and `g` tends to a negative constant `C` then `f * g` tends to `Filter.atTop`. -/ theorem Filter.Tendsto.atBot_mul_neg {C : 𝕜} (hC : C < 0) (hf : Tendsto f l atBot) (hg : Tendsto g l (𝓝 C)) : Tendsto (fun x => f x * g x) l atTop := by have := (tendsto_neg_atBot_atTop.comp hf).atTop_mul_neg hC hg - simpa [(· ∘ ·)] using tendsto_neg_atBot_atTop.comp this + simpa [Function.comp_def] using tendsto_neg_atBot_atTop.comp this /-- In a linearly ordered field with the order topology, if `f` tends to a positive constant `C` and `g` tends to `Filter.atBot` then `f * g` tends to `Filter.atBot`. -/ diff --git a/Mathlib/Topology/Algebra/Order/Group.lean b/Mathlib/Topology/Algebra/Order/Group.lean index ed113a88b9cf3..be3a1247cf1fa 100644 --- a/Mathlib/Topology/Algebra/Order/Group.lean +++ b/Mathlib/Topology/Algebra/Order/Group.lean @@ -15,9 +15,9 @@ topological group. We also prove continuity of `abs : G → G` and provide conve -/ -open Set Filter +open Set Filter Function -open Topology Filter +open scoped Topology variable {α G : Type*} [TopologicalSpace G] [LinearOrderedAddCommGroup G] [OrderTopology G] variable {l : Filter α} {f g : α → G} @@ -88,3 +88,39 @@ protected theorem ContinuousOn.abs (h : ContinuousOn f s) : ContinuousOn (fun x theorem tendsto_abs_nhdsWithin_zero : Tendsto (abs : G → G) (𝓝[≠] 0) (𝓝[>] 0) := (continuous_abs.tendsto' (0 : G) 0 abs_zero).inf <| tendsto_principal_principal.2 fun _x => abs_pos.2 + +/-- In a linearly ordered additive group, the integer multiples of an element are dense +iff they are the whole group. -/ +theorem denseRange_zsmul_iff_surjective {a : G} : + DenseRange (· • a : ℤ → G) ↔ Surjective (· • a : ℤ → G) := by + refine ⟨fun h ↦ ?_, fun h ↦ h.denseRange⟩ + wlog ha₀ : 0 < a generalizing a + · simp only [← range_iff_surjective, DenseRange] at * + rcases (not_lt.1 ha₀).eq_or_lt with rfl | hlt + · simpa only [smul_zero, range_const, dense_iff_closure_eq, closure_singleton] using h + · have H : range (· • -a : ℤ → G) = range (· • a : ℤ → G) := by + simpa only [smul_neg, ← neg_smul] using neg_surjective.range_comp (· • a) + rw [← H] + apply this <;> simpa only [H, neg_pos] + intro b + obtain ⟨m, hm, hm'⟩ : ∃ m : ℤ, m • a ∈ Ioo b (b + a + a) := by + have hne : (Ioo b (b + a + a)).Nonempty := ⟨b + a, by simpa⟩ + simpa using h.exists_mem_open isOpen_Ioo hne + rcases eq_or_ne b ((m - 1) • a) with rfl | hne; · simp + suffices (Ioo (m • a) ((m + 1) • a)).Nonempty by + rcases h.exists_mem_open isOpen_Ioo this with ⟨l, hl⟩ + have : m < l ∧ l < m + 1 := by simpa [zsmul_lt_zsmul_iff ha₀] using hl + omega + rcases hne.lt_or_lt with hlt | hlt + · refine ⟨b + a + a, hm', ?_⟩ + simpa only [add_smul, sub_smul, one_smul, lt_sub_iff_add_lt, add_lt_add_iff_right] using hlt + · use b + a + simp only [mem_Ioo, add_smul, sub_smul, one_smul, add_lt_add_iff_right] at hlt ⊢ + exact ⟨sub_lt_iff_lt_add.1 hlt, hm⟩ + +/-- In a nontrivial densely linearly ordered additive group, +the integer multiples of an element can't be dense. -/ +theorem not_denseRange_zsmul [Nontrivial G] [DenselyOrdered G] {a : G} : + ¬DenseRange (· • a : ℤ → G) := + denseRange_zsmul_iff_surjective.not.mpr fun h ↦ + not_isAddCyclic_of_denselyOrdered G ⟨⟨a, h⟩⟩ diff --git a/Mathlib/Topology/Algebra/Order/LiminfLimsup.lean b/Mathlib/Topology/Algebra/Order/LiminfLimsup.lean index dc3ec2436b49f..43ef0e855d0da 100644 --- a/Mathlib/Topology/Algebra/Order/LiminfLimsup.lean +++ b/Mathlib/Topology/Algebra/Order/LiminfLimsup.lean @@ -27,10 +27,8 @@ The same lemmas are true in `ℝ`, `ℝ × ℝ`, `ι → ℝ`, `EuclideanSpace duplication, we provide an ad hoc axiomatisation of the properties we need. -/ - open Filter TopologicalSpace - -open scoped Topology Classical +open scoped Topology universe u v @@ -210,11 +208,13 @@ theorem tendsto_of_liminf_eq_limsup {f : Filter β} {u : β → α} {a : α} (hi and is greater than or equal to the `limsup` of `f`, then `f` tends to `a` along this filter. -/ theorem tendsto_of_le_liminf_of_limsup_le {f : Filter β} {u : β → α} {a : α} (hinf : a ≤ liminf u f) (hsup : limsup u f ≤ a) (h : f.IsBoundedUnder (· ≤ ·) u := by isBoundedDefault) - (h' : f.IsBoundedUnder (· ≥ ·) u := by isBoundedDefault) : Tendsto u f (𝓝 a) := - if hf : f = ⊥ then hf.symm ▸ tendsto_bot - else - haveI : NeBot f := ⟨hf⟩ - tendsto_of_liminf_eq_limsup (le_antisymm (le_trans (liminf_le_limsup h h') hsup) hinf) + (h' : f.IsBoundedUnder (· ≥ ·) u := by isBoundedDefault) : Tendsto u f (𝓝 a) := by + classical + by_cases hf : f = ⊥ + · rw [hf] + exact tendsto_bot + · haveI : NeBot f := ⟨hf⟩ + exact tendsto_of_liminf_eq_limsup (le_antisymm (le_trans (liminf_le_limsup h h') hsup) hinf) (le_antisymm hsup (le_trans hinf (liminf_le_limsup h h'))) h h' /-- Assume that, for any `a < b`, a sequence can not be infinitely many times below `a` and @@ -303,7 +303,7 @@ theorem Antitone.map_limsSup_of_continuousAt {F : Filter R} [NeBot F] {f : R → (cobdd : F.IsCobounded (· ≤ ·) := by isBoundedDefault) : f F.limsSup = F.liminf f := by apply le_antisymm - · rw [limsSup, f_decr.map_sInf_of_continuousAt' f_cont bdd_above cobdd] + · rw [limsSup, f_decr.map_csInf_of_continuousAt f_cont bdd_above cobdd] apply le_of_forall_lt intro c hc simp only [liminf, limsInf, eventually_map] at hc ⊢ diff --git a/Mathlib/Topology/Algebra/Polynomial.lean b/Mathlib/Topology/Algebra/Polynomial.lean index 82175ebb00e13..fb827c4965390 100644 --- a/Mathlib/Topology/Algebra/Polynomial.lean +++ b/Mathlib/Topology/Algebra/Polynomial.lean @@ -6,7 +6,7 @@ Authors: Robert Y. Lewis import Mathlib.Algebra.Polynomial.AlgebraMap import Mathlib.Algebra.Polynomial.Inductions import Mathlib.Algebra.Polynomial.Splits -import Mathlib.Analysis.Normed.Field.Basic +import Mathlib.Analysis.Normed.Field.Lemmas import Mathlib.RingTheory.Polynomial.Vieta /-! diff --git a/Mathlib/Topology/Algebra/PontryaginDual.lean b/Mathlib/Topology/Algebra/PontryaginDual.lean index afe0be4038552..80aa1eef70921 100644 --- a/Mathlib/Topology/Algebra/PontryaginDual.lean +++ b/Mathlib/Topology/Algebra/PontryaginDual.lean @@ -71,7 +71,7 @@ instance [LocallyCompactSpace G] : LocallyCompactSpace (PontryaginDual G) := by fun k _ ↦ ⟨Real.pi / 2 ^ (k + 1), by positivity, le_rfl⟩).map Circle.exp rw [Set.mem_setOf_eq] at ht ⊢ refine lt_of_lt_of_le ht ?_ - rw [div_le_iff' (pow_pos two_pos _), ← div_le_iff hx] + rw [div_le_iff₀' (pow_pos two_pos _), ← div_le_iff₀ hx] refine (Nat.le_ceil (Real.pi / x)).trans ?_ exact_mod_cast (Nat.le_succ _).trans (Nat.lt_two_pow _).le diff --git a/Mathlib/Topology/Algebra/ProperAction.lean b/Mathlib/Topology/Algebra/ProperAction.lean index 4834f7f44beb1..2c645d7ab198d 100644 --- a/Mathlib/Topology/Algebra/ProperAction.lean +++ b/Mathlib/Topology/Algebra/ProperAction.lean @@ -14,8 +14,8 @@ import Mathlib.Topology.Sequences In this file we define proper action of a group on a topological space, and we prove that in this case the quotient space is T2. We also give equivalent definitions of proper action using ultrafilters and show the transfer of proper action to a closed subgroup. -We give sufficent conditions on the topological space such that the action is properly discontinuous -(see `ProperlyDiscontinuousSMul`) if and only if it is continuous in +We give sufficient conditions on the topological space such that the action is properly +discontinuous (see `ProperlyDiscontinuousSMul`) if and only if it is continuous in the first variable (see `ContinuousConstSMul`) and proper in the sense defined here. ## Main definitions diff --git a/Mathlib/Topology/Algebra/Ring/Basic.lean b/Mathlib/Topology/Algebra/Ring/Basic.lean index 625d49d63a27c..94cf82277f373 100644 --- a/Mathlib/Topology/Algebra/Ring/Basic.lean +++ b/Mathlib/Topology/Algebra/Ring/Basic.lean @@ -40,7 +40,7 @@ The `TopologicalSemiring` class should *only* be instantiated in the presence of `NonUnitalNonAssocSemiring` instance; if there is an instance of `NonUnitalNonAssocRing`, then `TopologicalRing` should be used. Note: in the presence of `NonAssocRing`, these classes are mathematically equivalent (see `TopologicalSemiring.continuousNeg_of_mul` or -`TopologicalSemiring.toTopologicalRing`). -/ +`TopologicalSemiring.toTopologicalRing`). -/ class TopologicalSemiring [TopologicalSpace α] [NonUnitalNonAssocSemiring α] extends ContinuousAdd α, ContinuousMul α : Prop diff --git a/Mathlib/Topology/Algebra/SeparationQuotient.lean b/Mathlib/Topology/Algebra/SeparationQuotient.lean new file mode 100644 index 0000000000000..140e089dc9563 --- /dev/null +++ b/Mathlib/Topology/Algebra/SeparationQuotient.lean @@ -0,0 +1,421 @@ +/- +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 + +/-! +# Algebraic operations on `SeparationQuotient` + +In this file we define algebraic operations (multiplication, addition etc) +on the separation quotient of a topological space with corresponding operation, +provided that the original operation is continuous. + +We also prove continuity of these operations +and show that they satisfy the same kind of laws (`Monoid` etc) as the original ones. + +Finally, we construct a section of the quotient map +which is a continuous linear map `SeparationQuotient E →L[K] E`. +-/ + +namespace SeparationQuotient + +section SMul + +variable {M X : Type*} [TopologicalSpace X] [SMul M X] [ContinuousConstSMul M X] + +@[to_additive] +instance instSMul : SMul M (SeparationQuotient X) where + smul c := Quotient.map' (c • ·) fun _ _ h ↦ h.const_smul c + +@[to_additive (attr := simp)] +theorem mk_smul (c : M) (x : X) : mk (c • x) = c • mk x := rfl + +@[to_additive] +instance instContinuousConstSMul : ContinuousConstSMul M (SeparationQuotient X) where + continuous_const_smul c := quotientMap_mk.continuous_iff.2 <| + continuous_mk.comp <| continuous_const_smul c + +@[to_additive] +instance instIsPretransitiveSMul [MulAction.IsPretransitive M X] : + MulAction.IsPretransitive M (SeparationQuotient X) where + exists_smul_eq := surjective_mk.forall₂.2 fun x y ↦ + (MulAction.exists_smul_eq M x y).imp fun _ ↦ congr_arg mk + +@[to_additive] +instance instIsCentralScalar [SMul Mᵐᵒᵖ X] [IsCentralScalar M X] : + IsCentralScalar M (SeparationQuotient X) where + op_smul_eq_smul a := surjective_mk.forall.2 (congr_arg mk <| op_smul_eq_smul a ·) + +variable {N : Type*} [SMul N X] + +@[to_additive] +instance instSMulCommClass [ContinuousConstSMul N X] [SMulCommClass M N X] : + SMulCommClass M N (SeparationQuotient X) := + surjective_mk.smulCommClass mk_smul mk_smul + +@[to_additive instVAddAssocClass] +instance instIsScalarTower [SMul M N] [ContinuousConstSMul N X] [IsScalarTower M N X] : + IsScalarTower M N (SeparationQuotient X) where + smul_assoc a b := surjective_mk.forall.2 fun x ↦ congr_arg mk <| smul_assoc a b x + +end 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 + +@[to_additive] +instance instMulAction {M X : Type*} [Monoid M] [MulAction M X] [TopologicalSpace X] + [ContinuousConstSMul M X] : MulAction M (SeparationQuotient X) := + surjective_mk.mulAction mk mk_smul + +section Monoid + +variable {M : Type*} [TopologicalSpace M] + +@[to_additive] +instance instMul [Mul M] [ContinuousMul M] : Mul (SeparationQuotient M) where + mul := Quotient.map₂' (· * ·) fun _ _ h₁ _ _ h₂ ↦ Inseparable.mul h₁ h₂ + +@[to_additive (attr := simp)] +theorem mk_mul [Mul M] [ContinuousMul M] (a b : M) : mk (a * b) = mk a * mk b := rfl + + +@[to_additive] +instance instContinuousMul [Mul M] [ContinuousMul M] : ContinuousMul (SeparationQuotient M) where + continuous_mul := quotientMap_prodMap_mk.continuous_iff.2 <| continuous_mk.comp continuous_mul + +@[to_additive] +instance instCommMagma [CommMagma M] [ContinuousMul M] : CommMagma (SeparationQuotient M) := + surjective_mk.commMagma mk mk_mul + +@[to_additive] +instance instSemigroup [Semigroup M] [ContinuousMul M] : Semigroup (SeparationQuotient M) := + surjective_mk.semigroup mk mk_mul + +@[to_additive] +instance instCommSemigroup [CommSemigroup M] [ContinuousMul M] : + CommSemigroup (SeparationQuotient M) := + surjective_mk.commSemigroup mk mk_mul + +@[to_additive] +instance instMulOneClass [MulOneClass M] [ContinuousMul M] : + MulOneClass (SeparationQuotient M) := + surjective_mk.mulOneClass mk mk_one mk_mul + +/-- `SeparationQuotient.mk` as a `MonoidHom`. -/ +@[to_additive (attr := simps) "`SeparationQuotient.mk` as an `AddMonoidHom`."] +def mkMonoidHom [MulOneClass M] [ContinuousMul M] : M →* SeparationQuotient M where + toFun := mk + map_mul' := mk_mul + map_one' := mk_one + +instance (priority := 900) instNSmul [AddMonoid M] [ContinuousAdd M] : + SMul ℕ (SeparationQuotient M) := + inferInstance + +@[to_additive existing instNSmul] +instance instPow [Monoid M] [ContinuousMul M] : Pow (SeparationQuotient M) ℕ where + pow x n := Quotient.map' (s₁ := inseparableSetoid M) (· ^ n) (fun _ _ h ↦ Inseparable.pow h n) x + +@[to_additive, simp] -- `mk_nsmul` is not a `simp` lemma because we have `mk_smul` +theorem mk_pow [Monoid M] [ContinuousMul M] (x : M) (n : ℕ) : mk (x ^ n) = (mk x) ^ n := rfl + +@[to_additive] +instance instMonoid [Monoid M] [ContinuousMul M] : Monoid (SeparationQuotient M) := + surjective_mk.monoid mk mk_one mk_mul mk_pow + +@[to_additive] +instance instCommMonoid [CommMonoid M] [ContinuousMul M] : CommMonoid (SeparationQuotient M) := + surjective_mk.commMonoid mk mk_one mk_mul mk_pow + +end Monoid + +section Group + +variable {G : Type*} [TopologicalSpace G] + +@[to_additive] +instance instInv [Inv G] [ContinuousInv G] : Inv (SeparationQuotient G) where + inv := Quotient.map' (·⁻¹) fun _ _ ↦ Inseparable.inv + +@[to_additive (attr := simp)] +theorem mk_inv [Inv G] [ContinuousInv G] (x : G) : mk x⁻¹ = (mk x)⁻¹ := rfl + +@[to_additive] +instance instContinuousInv [Inv G] [ContinuousInv G] : ContinuousInv (SeparationQuotient G) where + continuous_inv := quotientMap_mk.continuous_iff.2 <| continuous_mk.comp continuous_inv + +@[to_additive] +instance instInvolutiveInv [InvolutiveInv G] [ContinuousInv G] : + InvolutiveInv (SeparationQuotient G) := + surjective_mk.involutiveInv mk mk_inv + +@[to_additive] +instance instInvOneClass [InvOneClass G] [ContinuousInv G] : + InvOneClass (SeparationQuotient G) where + inv_one := congr_arg mk inv_one + +@[to_additive] +instance instDiv [Div G] [ContinuousDiv G] : Div (SeparationQuotient G) where + div := Quotient.map₂' (· / ·) fun _ _ h₁ _ _ h₂ ↦ (Inseparable.prod h₁ h₂).map continuous_div' + +@[to_additive (attr := simp)] +theorem mk_div [Div G] [ContinuousDiv G] (x y : G) : mk (x / y) = mk x / mk y := rfl + +@[to_additive] +instance instContinuousDiv [Div G] [ContinuousDiv G] : ContinuousDiv (SeparationQuotient G) where + continuous_div' := quotientMap_prodMap_mk.continuous_iff.2 <| continuous_mk.comp continuous_div' + +instance instZSMul [AddGroup G] [TopologicalAddGroup G] : SMul ℤ (SeparationQuotient G) := + inferInstance + +@[to_additive existing] +instance instZPow [Group G] [TopologicalGroup G] : Pow (SeparationQuotient G) ℤ where + pow x n := Quotient.map' (s₁ := inseparableSetoid G) (· ^ n) (fun _ _ h ↦ Inseparable.zpow h n) x + +@[to_additive, simp] -- `mk_zsmul` is not a `simp` lemma because we have `mk_smul` +theorem mk_zpow [Group G] [TopologicalGroup G] (x : G) (n : ℤ) : mk (x ^ n) = (mk x) ^ n := rfl + +@[to_additive] +instance instGroup [Group G] [TopologicalGroup G] : Group (SeparationQuotient G) := + surjective_mk.group mk mk_one mk_mul mk_inv mk_div mk_pow mk_zpow + +@[to_additive] +instance instCommGroup [CommGroup G] [TopologicalGroup G] : CommGroup (SeparationQuotient G) := + surjective_mk.commGroup mk mk_one mk_mul mk_inv mk_div mk_pow mk_zpow + +end Group + +section MonoidWithZero + +variable {M₀ : Type*} [TopologicalSpace M₀] + +instance instMulZeroClass [MulZeroClass M₀] [ContinuousMul M₀] : + MulZeroClass (SeparationQuotient M₀) := + surjective_mk.mulZeroClass mk mk_zero mk_mul + +instance instSemigroupWithZero [SemigroupWithZero M₀] [ContinuousMul M₀] : + SemigroupWithZero (SeparationQuotient M₀) := + surjective_mk.semigroupWithZero mk mk_zero mk_mul + +instance instMulZeroOneClass [MulZeroOneClass M₀] [ContinuousMul M₀] : + MulZeroOneClass (SeparationQuotient M₀) := + surjective_mk.mulZeroOneClass mk mk_zero mk_one mk_mul + +instance instMonoidWithZero [MonoidWithZero M₀] [ContinuousMul M₀] : + MonoidWithZero (SeparationQuotient M₀) := + surjective_mk.monoidWithZero mk mk_zero mk_one mk_mul mk_pow + +instance instCommMonoidWithZero [CommMonoidWithZero M₀] [ContinuousMul M₀] : + CommMonoidWithZero (SeparationQuotient M₀) := + surjective_mk.commMonoidWithZero mk mk_zero mk_one mk_mul mk_pow + +end MonoidWithZero + +section Ring + +variable {R : Type*} [TopologicalSpace R] + +instance instDistrib [Distrib R] [ContinuousMul R] [ContinuousAdd R] : + Distrib (SeparationQuotient R) := + surjective_mk.distrib mk mk_add mk_mul + +instance instLeftDistribClass [Mul R] [Add R] [LeftDistribClass R] + [ContinuousMul R] [ContinuousAdd R] : + LeftDistribClass (SeparationQuotient R) := + surjective_mk.leftDistribClass mk mk_add mk_mul + +instance instRightDistribClass [Mul R] [Add R] [RightDistribClass R] + [ContinuousMul R] [ContinuousAdd R] : + RightDistribClass (SeparationQuotient R) := + surjective_mk.rightDistribClass mk mk_add mk_mul + +instance instNonUnitalnonAssocSemiring [NonUnitalNonAssocSemiring R] + [TopologicalSemiring R] : NonUnitalNonAssocSemiring (SeparationQuotient R) := + surjective_mk.nonUnitalNonAssocSemiring mk mk_zero mk_add mk_mul mk_smul + +instance instNonUnitalSemiring [NonUnitalSemiring R] [TopologicalSemiring R] : + NonUnitalSemiring (SeparationQuotient R) := + surjective_mk.nonUnitalSemiring mk mk_zero mk_add mk_mul mk_smul + +instance instNatCast [NatCast R] : NatCast (SeparationQuotient R) where + natCast n := mk n + +@[simp, norm_cast] +theorem mk_natCast [NatCast R] (n : ℕ) : mk (n : R) = n := rfl + +@[simp] +theorem mk_ofNat [NatCast R] (n : ℕ) [n.AtLeastTwo] : + mk (no_index (OfNat.ofNat n) : R) = OfNat.ofNat n := + rfl + +instance instIntCast [IntCast R] : IntCast (SeparationQuotient R) where + intCast n := mk n + +@[simp, norm_cast] +theorem mk_intCast [IntCast R] (n : ℤ) : mk (n : R) = n := rfl + +instance instNonAssocSemiring [NonAssocSemiring R] [TopologicalSemiring R] : + NonAssocSemiring (SeparationQuotient R) := + surjective_mk.nonAssocSemiring mk mk_zero mk_one mk_add mk_mul mk_smul mk_natCast + +instance instNonUnitalNonAssocRing [NonUnitalNonAssocRing R] [TopologicalRing R] : + NonUnitalNonAssocRing (SeparationQuotient R) := + surjective_mk.nonUnitalNonAssocRing mk mk_zero mk_add mk_mul mk_neg mk_sub mk_smul mk_smul + +instance instNonUnitalRing [NonUnitalRing R] [TopologicalRing R] : + NonUnitalRing (SeparationQuotient R) := + surjective_mk.nonUnitalRing mk mk_zero mk_add mk_mul mk_neg mk_sub mk_smul mk_smul + +instance instNonAssocRing [NonAssocRing R] [TopologicalRing R] : + NonAssocRing (SeparationQuotient R) := + surjective_mk.nonAssocRing mk mk_zero mk_one mk_add mk_mul mk_neg mk_sub mk_smul mk_smul + mk_natCast mk_intCast + +instance instSemiring [Semiring R] [TopologicalSemiring R] : + Semiring (SeparationQuotient R) := + surjective_mk.semiring mk mk_zero mk_one mk_add mk_mul mk_smul mk_pow mk_natCast + +instance instRing [Ring R] [TopologicalRing R] : + Ring (SeparationQuotient R) := + surjective_mk.ring mk mk_zero mk_one mk_add mk_mul mk_neg mk_sub mk_smul mk_smul mk_pow + mk_natCast mk_intCast + +instance instNonUnitalNonAssocCommSemiring [NonUnitalNonAssocCommSemiring R] + [TopologicalSemiring R] : + NonUnitalNonAssocCommSemiring (SeparationQuotient R) := + surjective_mk.nonUnitalNonAssocCommSemiring mk mk_zero mk_add mk_mul mk_smul + +instance instNonUnitalCommSemiring [NonUnitalCommSemiring R] [TopologicalSemiring R] : + NonUnitalCommSemiring (SeparationQuotient R) := + surjective_mk.nonUnitalCommSemiring mk mk_zero mk_add mk_mul mk_smul + +instance instCommSemiring [CommSemiring R] [TopologicalSemiring R] : + CommSemiring (SeparationQuotient R) := + surjective_mk.commSemiring mk mk_zero mk_one mk_add mk_mul mk_smul mk_pow mk_natCast + +instance instHasDistribNeg [Mul R] [HasDistribNeg R] [ContinuousMul R] [ContinuousNeg R] : + HasDistribNeg (SeparationQuotient R) := + surjective_mk.hasDistribNeg mk mk_neg mk_mul + +instance instNonUnitalNonAssocCommRing [NonUnitalNonAssocCommRing R] [TopologicalRing R] : + NonUnitalNonAssocCommRing (SeparationQuotient R) := + surjective_mk.nonUnitalNonAssocCommRing mk mk_zero mk_add mk_mul mk_neg mk_sub mk_smul mk_smul + +instance instNonUnitalCommRing [NonUnitalCommRing R] [TopologicalRing R] : + NonUnitalCommRing (SeparationQuotient R) := + surjective_mk.nonUnitalCommRing mk mk_zero mk_add mk_mul mk_neg mk_sub mk_smul mk_smul + +instance instCommRing [CommRing R] [TopologicalRing R] : + CommRing (SeparationQuotient 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 + +end Ring + +section DistribSMul + +variable {M A : Type*} [TopologicalSpace A] + +instance instDistribSMul [AddZeroClass A] [DistribSMul M A] + [ContinuousAdd A] [ContinuousConstSMul M A] : + DistribSMul M (SeparationQuotient A) := + surjective_mk.distribSMul mkAddMonoidHom mk_smul + +instance instDistribMulAction [Monoid M] [AddMonoid A] [DistribMulAction M A] + [ContinuousAdd A] [ContinuousConstSMul M A] : + DistribMulAction M (SeparationQuotient A) := + surjective_mk.distribMulAction mkAddMonoidHom mk_smul + +instance instMulDistribMulAction [Monoid M] [Monoid A] [MulDistribMulAction M A] + [ContinuousMul A] [ContinuousConstSMul M A] : + MulDistribMulAction M (SeparationQuotient A) := + surjective_mk.mulDistribMulAction mkMonoidHom mk_smul + +end DistribSMul + +section Module + +variable {R M : Type*} [Semiring R] [AddCommMonoid M] [Module R M] + [TopologicalSpace M] [ContinuousAdd M] [ContinuousConstSMul R M] + +instance instModule : Module R (SeparationQuotient M) := + surjective_mk.module R mkAddMonoidHom mk_smul + +variable (R M) + +/-- `SeparationQuotient.mk` as a continuous linear map. -/ +@[simps] +def mkCLM : M →L[R] SeparationQuotient M where + toFun := mk + map_add' := mk_add + map_smul' := mk_smul + +end Module + +section VectorSpace + +variable (K E : Type*) [DivisionRing K] [AddCommGroup E] [Module K E] + [TopologicalSpace E] [TopologicalAddGroup E] [ContinuousConstSMul K E] + +/-- There exists a continuous `K`-linear map from `SeparationQuotient E` to `E` +such that `mk (outCLM x) = x` for all `x`. + +Note that continuity of this map comes for free, because `mk` is a topology inducing map. +-/ +theorem exists_out_continuousLinearMap : + ∃ f : SeparationQuotient E →L[K] E, mkCLM K E ∘L f = .id K (SeparationQuotient E) := by + rcases (mkCLM K E).toLinearMap.exists_rightInverse_of_surjective + (LinearMap.range_eq_top.mpr surjective_mk) with ⟨f, hf⟩ + replace hf : mk ∘ f = id := congr_arg DFunLike.coe hf + exact ⟨⟨f, inducing_mk.continuous_iff.2 (by continuity)⟩, DFunLike.ext' hf⟩ + +/-- A continuous `K`-linear map from `SeparationQuotient E` to `E` +such that `mk (outCLM x) = x` for all `x`. -/ +noncomputable def outCLM : SeparationQuotient E →L[K] E := + (exists_out_continuousLinearMap K E).choose + +@[simp] +theorem mkCLM_comp_outCLM : mkCLM K E ∘L outCLM K E = .id K (SeparationQuotient E) := + (exists_out_continuousLinearMap K E).choose_spec + +variable {E} in +@[simp] +theorem mk_outCLM (x : SeparationQuotient E) : mk (outCLM K E x) = x := + DFunLike.congr_fun (mkCLM_comp_outCLM K E) x + +@[simp] +theorem mk_comp_outCLM : mk ∘ outCLM K E = id := funext (mk_outCLM K) + +/-- 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 _) + +theorem outCLM_injective : Function.Injective (outCLM K E) := + (outCLM_embedding K E).injective + +end VectorSpace + +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_uniformEmbedding : UniformEmbedding (outCLM K E) where + inj := outCLM_injective K E + toUniformInducing := outCLM_uniformInducing K E + +theorem outCLM_uniformContinuous : UniformContinuous (outCLM K E) := + (outCLM_uniformInducing K E).uniformContinuous + +end VectorSpaceUniform + +end SeparationQuotient diff --git a/Mathlib/Topology/Algebra/UniformField.lean b/Mathlib/Topology/Algebra/UniformField.lean index c626826669020..059b0ae0cacfb 100644 --- a/Mathlib/Topology/Algebra/UniformField.lean +++ b/Mathlib/Topology/Algebra/UniformField.lean @@ -195,3 +195,20 @@ instance (priority := 100) completableTopField_of_complete (L : Type*) [Field L] calc map (fun x => x⁻¹) F ≤ map (fun x => x⁻¹) (𝓝 x) := map_mono hx _ ≤ 𝓝 x⁻¹ := continuousAt_inv₀ hx' + +variable {α β : Type*} [Field β] [b : UniformSpace β] [CompletableTopField β] + [Field α] + +/-- The pullback of a completable topological field along a uniform inducing +ring homomorphism is a completable topological field. -/ +theorem UniformInducing.completableTopField + [UniformSpace α] [T0Space α] + {f : α →+* β} (hf : UniformInducing f) : + CompletableTopField α := by + refine CompletableTopField.mk (fun F F_cau inf_F => ?_) + rw [← UniformInducing.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] + apply CompletableTopField.nice _ F_cau + rw [← Filter.push_pull', ← map_zero f, ← hf.inducing.nhds_eq_comap, inf_F, Filter.map_bot] diff --git a/Mathlib/Topology/Algebra/UniformGroup.lean b/Mathlib/Topology/Algebra/UniformGroup.lean index f667159ebd3f8..b160ebca22eed 100644 --- a/Mathlib/Topology/Algebra/UniformGroup.lean +++ b/Mathlib/Topology/Algebra/UniformGroup.lean @@ -146,7 +146,7 @@ theorem uniformity_translate_mul (a : α) : ((𝓤 α).map fun x : α × α => ( (calc 𝓤 α = ((𝓤 α).map fun x : α × α => (x.1 * a⁻¹, x.2 * a⁻¹)).map fun x : α × α => - (x.1 * a, x.2 * a) := by simp [Filter.map_map, (· ∘ ·)] + (x.1 * a, x.2 * a) := by simp [Filter.map_map, Function.comp_def] _ ≤ (𝓤 α).map fun x : α × α => (x.1 * a, x.2 * a) := Filter.map_mono (uniformContinuous_id.mul uniformContinuous_const) ) @@ -270,7 +270,7 @@ theorem uniformity_eq_comap_inv_mul_nhds_one : 𝓤 α = comap (fun x : α × α => x.1⁻¹ * x.2) (𝓝 (1 : α)) := by rw [← comap_uniformity_mulOpposite, uniformity_eq_comap_nhds_one, ← op_one, ← comap_unop_nhds, comap_comap, comap_comap] - simp [(· ∘ ·)] + simp [Function.comp_def] @[to_additive] theorem uniformity_eq_comap_inv_mul_nhds_one_swapped : @@ -464,7 +464,7 @@ def TopologicalGroup.toUniformSpace : UniformSpace G where refine mem_map.2 (mem_of_superset (mem_lift' <| preimage_mem_comap V_nhds) ?_) rintro ⟨x, y⟩ ⟨z, hz₁, hz₂⟩ simpa using V_mul _ hz₂ _ hz₁ - nhds_eq_comap_uniformity _ := by simp only [comap_comap, (· ∘ ·), nhds_translation_div] + nhds_eq_comap_uniformity _ := by simp only [comap_comap, Function.comp_def, nhds_translation_div] attribute [local instance] TopologicalGroup.toUniformSpace @@ -568,7 +568,7 @@ theorem comm_topologicalGroup_is_uniform : UniformGroup G := by constructor rw [UniformContinuous, uniformity_prod_eq_prod, tendsto_map'_iff, uniformity_eq_comap_nhds_one' G, tendsto_comap_iff, prod_comap_comap_eq] - simp only [Function.comp, div_eq_mul_inv, mul_inv_rev, inv_inv, mul_comm, mul_left_comm] at * + simp only [Function.comp_def, div_eq_mul_inv, mul_inv_rev, inv_inv, mul_comm, mul_left_comm] at * simp only [inv_one, mul_one, ← mul_assoc] at this simp_rw [← mul_assoc, mul_comm] assumption @@ -829,7 +829,7 @@ instance QuotientGroup.completeSpace' (G : Type u) [Group G] [TopologicalSpace G exact fun m => ⟨m, fun n hmn => Nat.decreasingInduction' - (fun k _ _ hk => u_mul k ⟨_, hx' k, _, hk, div_mul_div_cancel' _ _ _⟩) hmn + (fun k _ _ hk => u_mul k ⟨_, hx' k, _, hk, div_mul_div_cancel _ _ _⟩) hmn (by simpa only [div_self'] using mem_of_mem_nhds (hu.mem _))⟩ /- Since `G` is complete, `x'` converges to some `x₀`, and so the image of this sequence under the quotient map converges to `↑x₀`. The image of `x'` is a convergent subsequence of `x`, and @@ -850,7 +850,7 @@ already equipped with a uniform structure. Even though `G` is equipped with a uniform structure, the quotient `G ⧸ N` does not inherit a uniform structure, so it is still provided manually via `TopologicalGroup.toUniformSpace`. In the most common use cases, this coincides (definitionally) with the uniform structure on the -quotient obtained via other means. -/ +quotient obtained via other means. -/ @[to_additive "The quotient `G ⧸ N` of a complete first countable uniform additive group `G` by a normal additive subgroup is itself complete. Consequently, quotients of Banach spaces by subspaces are complete. In contrast to `QuotientAddGroup.completeSpace'`, in this version diff --git a/Mathlib/Topology/Algebra/Valued/NormedValued.lean b/Mathlib/Topology/Algebra/Valued/NormedValued.lean index a947a5a38370c..7ce1d9f1fee9d 100644 --- a/Mathlib/Topology/Algebra/Valued/NormedValued.lean +++ b/Mathlib/Topology/Algebra/Valued/NormedValued.lean @@ -4,6 +4,7 @@ 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.Field.Basic +import Mathlib.Analysis.Normed.Group.Uniform import Mathlib.RingTheory.Valuation.RankOne import Mathlib.Topology.Algebra.Valued.ValuationTopology diff --git a/Mathlib/Topology/Algebra/Valued/ValuationTopology.lean b/Mathlib/Topology/Algebra/Valued/ValuationTopology.lean index acf68e9cf8d30..22bb1f84d63f6 100644 --- a/Mathlib/Topology/Algebra/Valued/ValuationTopology.lean +++ b/Mathlib/Topology/Algebra/Valued/ValuationTopology.lean @@ -15,10 +15,7 @@ The main definition is a `Valued` type class which equips a ring with a valuatio values in a group with zero. Other instances are then deduced from this. -/ - -open scoped Classical -open Topology uniformity - +open scoped Topology uniformity open Set Valuation noncomputable section diff --git a/Mathlib/Topology/Algebra/Valued/ValuedField.lean b/Mathlib/Topology/Algebra/Valued/ValuedField.lean index 615d15555a9be..2d7836874a275 100644 --- a/Mathlib/Topology/Algebra/Valued/ValuedField.lean +++ b/Mathlib/Topology/Algebra/Valued/ValuedField.lean @@ -364,7 +364,7 @@ def integer : Subring K := (vK.v).integer @[inherit_doc] scoped notation "𝒪[" K "]" => Valued.integer K -/-- An abbrevation for `LocalRing.maximalIdeal 𝒪[K]` of a valued field `K`, enabling the notation +/-- An abbreviation for `LocalRing.maximalIdeal 𝒪[K]` of a valued field `K`, enabling the notation `𝓂[K]` for the maximal ideal in `𝒪[K]` of a valued field `K`. -/ @[reducible] def maximalIdeal : Ideal 𝒪[K] := LocalRing.maximalIdeal 𝒪[K] @@ -372,7 +372,7 @@ def maximalIdeal : Ideal 𝒪[K] := LocalRing.maximalIdeal 𝒪[K] @[inherit_doc] scoped notation "𝓂[" K "]" => maximalIdeal K -/-- An abbrevation for `LocalRing.ResidueField 𝒪[K]` of a `Valued` instance, enabling the notation +/-- An abbreviation for `LocalRing.ResidueField 𝒪[K]` of a `Valued` instance, enabling the notation `𝓀[K]` for the residue field of a valued field `K`. -/ @[reducible] def ResidueField := LocalRing.ResidueField (𝒪[K]) diff --git a/Mathlib/Topology/Algebra/WithZeroTopology.lean b/Mathlib/Topology/Algebra/WithZeroTopology.lean index ae51c607ad1c0..8b290b9995546 100644 --- a/Mathlib/Topology/Algebra/WithZeroTopology.lean +++ b/Mathlib/Topology/Algebra/WithZeroTopology.lean @@ -159,7 +159,7 @@ scoped instance (priority := 100) : ContinuousMul Γ₀ where rintro ⟨x, y⟩ wlog hle : x ≤ y generalizing x y · have := (this y x (le_of_not_le hle)).comp (continuous_swap.tendsto (x, y)) - simpa only [mul_comm, Function.comp, Prod.swap] using this + simpa only [mul_comm, Function.comp_def, Prod.swap] using this rcases eq_or_ne x 0 with (rfl | hx) <;> [rcases eq_or_ne y 0 with (rfl | hy); skip] · rw [zero_mul] refine ((hasBasis_nhds_zero.prod_nhds hasBasis_nhds_zero).tendsto_iff hasBasis_nhds_zero).2 @@ -169,7 +169,7 @@ scoped instance (priority := 100) : ContinuousMul Γ₀ where · rw [zero_mul, nhds_prod_eq, nhds_of_ne_zero hy, prod_pure, tendsto_map'_iff] refine (hasBasis_nhds_zero.tendsto_iff hasBasis_nhds_zero).2 fun γ hγ => ?_ refine ⟨γ / y, div_ne_zero hγ hy, fun x hx => ?_⟩ - calc x * y < γ / y * y := mul_lt_right₀ _ hx hy + calc x * y < γ / y * y := mul_lt_mul_of_pos_right hx (zero_lt_iff.2 hy) _ = γ := div_mul_cancel₀ _ hy · have hy : y ≠ 0 := ((zero_lt_iff.mpr hx).trans_le hle).ne' rw [nhds_prod_eq, nhds_of_ne_zero hx, nhds_of_ne_zero hy, prod_pure_pure] diff --git a/Mathlib/Topology/Bases.lean b/Mathlib/Topology/Bases.lean index 7930817c3788d..033576301698e 100644 --- a/Mathlib/Topology/Bases.lean +++ b/Mathlib/Topology/Bases.lean @@ -65,7 +65,7 @@ variable {α : Type u} {β : Type*} [t : TopologicalSpace α] {B : Set (Set α)} it suffices to take unions of the basis sets to get a topology (without taking finite intersections as well). -/ structure IsTopologicalBasis (s : Set (Set α)) : Prop where - /-- For every point `x`, the set of `t ∈ s` such that `x ∈ t` is directed downwards. -/ + /-- For every point `x`, the set of `t ∈ s` such that `x ∈ t` is directed downwards. -/ exists_subset_inter : ∀ t₁ ∈ s, ∀ t₂ ∈ s, ∀ x ∈ t₁ ∩ t₂, ∃ t₃ ∈ s, x ∈ t₃ ∧ t₃ ⊆ t₁ ∩ t₂ /-- The sets from `s` cover the whole space. -/ sUnion_eq : ⋃₀ s = univ @@ -382,9 +382,9 @@ instance {ι : Type*} {X : ι → Type*} [∀ i, TopologicalSpace (X i)] [∀ i, (htd i).exists_mem_open (huo i i.2).1 ⟨_, (huo i i.2).2⟩ choose y hyt hyu using this lift y to ∀ i : I, t i using hyt - refine ⟨f ⟨I, y⟩, huU fun i (hi : i ∈ I) ↦ ?_, mem_range_self _⟩ + refine ⟨f ⟨I, y⟩, huU fun i (hi : i ∈ I) ↦ ?_, mem_range_self ⟨I, y⟩⟩ simp only [f, dif_pos hi] - exact hyu _ + exact hyu ⟨i, _⟩ instance [SeparableSpace α] {r : α → α → Prop} : SeparableSpace (Quot r) := quotientMap_quot_mk.separableSpace @@ -476,7 +476,7 @@ theorem IsSeparable.univ_pi {ι : Type*} [Countable ι] {X : ι → Type*} {s : refine ⟨range g, countable_range g, fun f hf ↦ mem_closure_iff.2 fun o ho hfo ↦ ?_⟩ rcases isOpen_pi_iff.1 ho f hfo with ⟨I, u, huo, hI⟩ rsuffices ⟨f, hf⟩ : ∃ f : (i : I) → c i, g ⟨I, f⟩ ∈ Set.pi I u - · exact ⟨g ⟨I, f⟩, hI hf, mem_range_self _⟩ + · exact ⟨g ⟨I, f⟩, hI hf, mem_range_self ⟨I, f⟩⟩ suffices H : ∀ i ∈ I, (u i ∩ c i).Nonempty by choose f hfu hfc using H refine ⟨fun i ↦ ⟨f i i.2, hfc i i.2⟩, fun i (hi : i ∈ I) ↦ ?_⟩ @@ -802,9 +802,8 @@ instance {ι : Type*} {π : ι → Type*} [Countable ι] [∀ a, TopologicalSpac instance (priority := 100) SecondCountableTopology.to_separableSpace [SecondCountableTopology α] : SeparableSpace α := by choose p hp using fun s : countableBasis α => nonempty_of_mem_countableBasis s.2 - exact - ⟨⟨range p, countable_range _, - (isBasis_countableBasis α).dense_iff.2 fun o ho _ => ⟨p ⟨o, ho⟩, hp _, mem_range_self _⟩⟩⟩ + exact ⟨⟨range p, countable_range _, (isBasis_countableBasis α).dense_iff.2 fun o ho _ => + ⟨p ⟨o, ho⟩, hp ⟨o, _⟩, mem_range_self _⟩⟩⟩ /-- A countable open cover induces a second-countable topology if all open covers are themselves second countable. -/ diff --git a/Mathlib/Topology/Basic.lean b/Mathlib/Topology/Basic.lean index 6c821ade241e9..43e41368cf38a 100644 --- a/Mathlib/Topology/Basic.lean +++ b/Mathlib/Topology/Basic.lean @@ -128,7 +128,7 @@ theorem Set.Finite.isOpen_biInter {s : Set α} {f : α → Set X} (hs : s.Finite theorem isOpen_iInter_of_finite [Finite ι] {s : ι → Set X} (h : ∀ i, IsOpen (s i)) : IsOpen (⋂ i, s i) := - (finite_range _).isOpen_sInter (forall_mem_range.2 h) + (finite_range _).isOpen_sInter (forall_mem_range.2 h) theorem isOpen_biInter_finset {s : Finset α} {f : α → Set X} (h : ∀ i ∈ s, IsOpen (f i)) : IsOpen (⋂ i ∈ s, f i) := @@ -156,6 +156,12 @@ theorem isClosed_const {p : Prop} : IsClosed { _x : X | p } := ⟨isOpen_const ( @[simp] theorem isClosed_univ : IsClosed (univ : Set X) := isClosed_const +lemma IsOpen.isLocallyClosed (hs : IsOpen s) : IsLocallyClosed s := + ⟨_, _, hs, isClosed_univ, (inter_univ _).symm⟩ + +lemma IsClosed.isLocallyClosed (hs : IsClosed s) : IsLocallyClosed s := + ⟨_, _, isOpen_univ, hs, (univ_inter _).symm⟩ + theorem IsClosed.union : IsClosed s₁ → IsClosed s₂ → IsClosed (s₁ ∪ s₂) := by simpa only [← isOpen_compl_iff, compl_union] using IsOpen.inter @@ -1738,3 +1744,5 @@ example [TopologicalSpace X] [TopologicalSpace Y] {x₀ : X} (f : X → X → Y) -- hf.comp_of_eq (continuousAt_id.prod continuousAt_id) rfl -- works ``` -/ + +set_option linter.style.longFile 1900 diff --git a/Mathlib/Topology/Bornology/BoundedOperation.lean b/Mathlib/Topology/Bornology/BoundedOperation.lean index 9340172558c61..a322077983828 100644 --- a/Mathlib/Topology/Bornology/BoundedOperation.lean +++ b/Mathlib/Topology/Bornology/BoundedOperation.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Kalle Kytölä -/ import Mathlib.Analysis.Normed.Group.Basic -import Mathlib.Analysis.Normed.Field.Basic +import Mathlib.Analysis.Normed.Field.Lemmas /-! # Bounded operations diff --git a/Mathlib/Topology/Bornology/Hom.lean b/Mathlib/Topology/Bornology/Hom.lean index 756bc3fdd6d3d..fb444353548de 100644 --- a/Mathlib/Topology/Bornology/Hom.lean +++ b/Mathlib/Topology/Bornology/Hom.lean @@ -83,8 +83,6 @@ instance : FunLike (LocallyBoundedMap α β) α β where instance : LocallyBoundedMapClass (LocallyBoundedMap α β) α β where comap_cobounded_le f := f.comap_cobounded_le' --- Porting note: syntactic tautology because of the way coercions work - @[ext] theorem ext {f g : LocallyBoundedMap α β} (h : ∀ a, f a = g a) : f = g := DFunLike.ext f g h diff --git a/Mathlib/Topology/Category/CompHaus/Basic.lean b/Mathlib/Topology/Category/CompHaus/Basic.lean index 19e8edca81f80..0306bef4b8f7d 100644 --- a/Mathlib/Topology/Category/CompHaus/Basic.lean +++ b/Mathlib/Topology/Category/CompHaus/Basic.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2020 Adam Topaz. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Adam Topaz, Bhavik Mehta +Authors: Adam Topaz, Bhavik Mehta, Dagur Asgeirsson -/ import Mathlib.CategoryTheory.Monad.Limits import Mathlib.Topology.StoneCech @@ -24,6 +24,11 @@ equivalence of categories in `CompactumToCompHaus.isEquivalence`. See `Mathlib/Topology/Category/Compactum.lean` for a more detailed discussion where these definitions are introduced. +## Implementation + +The category `CompHaus` is defined using the structure `CompHausLike`. See the file +`CompHausLike.Basic` for more information. + -/ @@ -219,6 +224,6 @@ theorem epi_iff_surjective {X Y : CompHaus.{u}} (f : X ⟶ Y) : Epi f ↔ Functi end CompHaus -/-- Every `CompHausLike` admits a functor to `CompHaus`. -/ +/-- Every `CompHausLike` admits a functor to `CompHaus`. -/ abbrev compHausLikeToCompHaus (P : TopCat → Prop) : CompHausLike P ⥤ CompHaus := CompHausLike.toCompHausLike (by simp only [implies_true]) diff --git a/Mathlib/Topology/Category/CompHausLike/Basic.lean b/Mathlib/Topology/Category/CompHausLike/Basic.lean index 05401767a1c2c..62495d9004dfa 100644 --- a/Mathlib/Topology/Category/CompHausLike/Basic.lean +++ b/Mathlib/Topology/Category/CompHausLike/Basic.lean @@ -10,6 +10,54 @@ import Mathlib.Topology.Category.TopCat.Basic # Categories of Compact Hausdorff Spaces We construct the category of compact Hausdorff spaces satisfying an additional property `P`. + +## Implementation + +We define a structure `CompHausLike` which takes as an argument a predicate `P` on topological +spaces. It consists of the data of a topological space, satisfying the additional properties of +being compact and Hausdorff, and satisfying `P`. We give a category structure to `CompHausLike P` +induced by the forgetful functor to topological spaces. + +It used to be the case (before #12930 was merged) that several different categories of compact +Hausdorff spaces, possibly satisfying some extra property, were defined from scratch in this way. +For example, one would define a structure `CompHaus` as follows: + +```lean +structure CompHaus where + toTop : TopCat + [is_compact : CompactSpace toTop] + [is_hausdorff : T2Space toTop] +```  + +and give it the category structure induced from topological spaces. Then the category of profinite +spaces was defined as follows: + +```lean +structure Profinite where + toCompHaus : CompHaus + [isTotallyDisconnected : TotallyDisconnectedSpace toCompHaus] +``` + +The categories `Stonean` consisting of extremally disconnected compact Hausdorff spaces and +`LightProfinite` consisting of totally disconnected, second countable compact Hausdorff spaces were +defined in a similar way. This resulted in code duplication, and reducing this duplication was part +of the motivation for introducing `CompHausLike`. + +Using `CompHausLike`, we can now define +`CompHaus := CompHausLike (fun _ ↦ True)` +`Profinite := CompHausLike (fun X ↦ TotallyDisconnectedSpace X)`. +`Stonean := CompHausLike (fun X ↦ ExtremallyDisconnected X)`. +`LightProfinite := CompHausLike (fun X ↦ TotallyDisconnectedSpace X ∧ SecondCountableTopology X)`. + +These four categories are important building blocks of condensed objects (see the files +`Condensed.Basic` and `Condensed.Light.Basic`). These categories share many properties and often, +one wants to argue about several of them simultaneously. This is the other part of the motivation +for introducing `CompHausLike`. On paper, one would say "let `C` be on of the categories `CompHaus` +or `Profinite`, then the following holds: ...". This was not possible in Lean using the old +definitions. Using the new definitions, this becomes a matter of identifying what common property +of `CompHaus` and `Profinite` is used in the proof in question, and then proving the theorem for +`CompHausLike P` satisfying that property, and it will automatically apply to both `CompHaus` and +`Profinite`. -/ universe u @@ -49,7 +97,7 @@ instance hasForget₂ : HasForget₂ (CompHausLike P) TopCat := variable (X : Type u) [TopologicalSpace X] [CompactSpace X] [T2Space X] -/-- This wraps the predicate `P : TopCat → Prop` in a typeclass. -/ +/-- This wraps the predicate `P : TopCat → Prop` in a typeclass. -/ class HasProp : Prop where hasProp : P (TopCat.of X) @@ -91,7 +139,7 @@ instance (X : CompHausLike.{u} P) : T2Space ((forget (CompHausLike P)).obj X) := variable {P} -/-- If `P` imples `P'`, then there is a functor from `CompHausLike P` to `CompHausLike P'`. -/ +/-- If `P` imples `P'`, then there is a functor from `CompHausLike P` to `CompHausLike P'`. -/ @[simps] def toCompHausLike {P P' : TopCat → Prop} (h : ∀ (X : CompHausLike P), P X.toTop → P' X.toTop) : CompHausLike P ⥤ CompHausLike P' where @@ -104,7 +152,7 @@ section variable {P P' : TopCat → Prop} (h : ∀ (X : CompHausLike P), P X.toTop → P' X.toTop) -/-- If `P` imples `P'`, then the functor from `CompHausLike P` to `CompHausLike P'` is fully +/-- If `P` imples `P'`, then the functor from `CompHausLike P` to `CompHausLike P'` is fully faithful. -/ def fullyFaithfulToCompHausLike : (toCompHausLike h).FullyFaithful := fullyFaithfulInducedFunctor _ diff --git a/Mathlib/Topology/Category/CompHausLike/Limits.lean b/Mathlib/Topology/Category/CompHausLike/Limits.lean index c3705bfeab520..845abc60f56e7 100644 --- a/Mathlib/Topology/Category/CompHausLike/Limits.lean +++ b/Mathlib/Topology/Category/CompHausLike/Limits.lean @@ -18,14 +18,14 @@ which may be useful due to their definitional properties. * `HasExplicitFiniteCoproducts`: A typeclass describing the property that forming all finite disjoint unions is stable under the property `P`. - Given this property, we deduce that `CompHausLike P` has finite coproducts and the inclusion - functors to other `CompHausLike P'` and to `TopCat` preserve them. + functors to other `CompHausLike P'` and to `TopCat` preserve them. * `HasExplicitPullbacks`: A typeclass describing the property that forming all "explicit pullbacks" is stable under the property `P`. Here, explicit pullbacks are defined as a subset of the product. - Given this property, we deduce that `CompHausLike P` has pullbacks and the inclusion - functors to other `CompHausLike P'` and to `TopCat` preserve them. + functors to other `CompHausLike P'` and to `TopCat` preserve them. - We also define a variant `HasExplicitPullbacksOfInclusions` which is says that explicit - pullbacks along inclusion maps into finite disjoint unions exist. `Stonean` has this property + pullbacks along inclusion maps into finite disjoint unions exist. `Stonean` has this property but not the stronger one. ## Main results @@ -127,7 +127,7 @@ class HasExplicitFiniteCoproducts : Prop where hasProp {α : Type w} [Finite α] (X : α → CompHausLike.{max u w} P) : HasExplicitFiniteCoproduct X /- -This linter complains that the universes `u` and `w` only occur together, but `w` appears by itself +This linter complains that the universes `u` and `w` only occur together, but `w` appears by itself in the indexing type of the coproduct. In almost all cases, `w` will be either `0` or `u`, but we want to allow both possibilities. -/ @@ -164,7 +164,7 @@ lemma Sigma.openEmbedding_ι (a : α) : change (Sigma.ι X a ≫ _) x = _ simp -/-- The functor to `TopCat` preserves finite coproducts if they exist. -/ +/-- The functor to `TopCat` preserves finite coproducts if they exist. -/ instance (P) [HasExplicitFiniteCoproducts.{0} P] : PreservesFiniteCoproducts (compHausLikeToTop P) := by refine ⟨fun J hJ ↦ ⟨fun {F} ↦ ?_⟩⟩ @@ -173,7 +173,7 @@ instance (P) [HasExplicitFiniteCoproducts.{0} P] : apply preservesColimitOfPreservesColimitCocone (CompHausLike.finiteCoproduct.isColimit _) exact TopCat.sigmaCofanIsColimit _ -/-- The functor to another `CompHausLike` preserves finite coproducts if they exist. -/ +/-- The functor to another `CompHausLike` preserves finite coproducts if they exist. -/ noncomputable instance {P' : TopCat.{u} → Prop} (h : ∀ (X : CompHausLike P), P X.toTop → P' X.toTop) : PreservesFiniteCoproducts (toCompHausLike h) := by @@ -275,18 +275,18 @@ def pullback.isLimit : Limits.IsLimit (pullback.cone f g) := instance : HasLimit (cospan f g) where exists_limit := ⟨⟨pullback.cone f g, pullback.isLimit f g⟩⟩ -/-- The functor to `TopCat` creates pullbacks if they exist. -/ +/-- The functor to `TopCat` creates pullbacks if they exist. -/ noncomputable instance : CreatesLimit (cospan f g) (compHausLikeToTop P) := by refine createsLimitOfFullyFaithfulOfIso (pullback f g) (((TopCat.pullbackConeIsLimit f g).conePointUniqueUpToIso (limit.isLimit _)) ≪≫ Limits.lim.mapIso (?_ ≪≫ (diagramIsoCospan _).symm)) exact Iso.refl _ -/-- The functor to `TopCat` preserves pullbacks. -/ +/-- The functor to `TopCat` preserves pullbacks. -/ noncomputable instance : PreservesLimit (cospan f g) (compHausLikeToTop P) := preservesLimitOfCreatesLimitAndHasLimit _ _ -/-- The functor to another `CompHausLike` preserves pullbacks. -/ +/-- The functor to another `CompHausLike` preserves pullbacks. -/ noncomputable instance {P' : TopCat → Prop} (h : ∀ (X : CompHausLike P), P X.toTop → P' X.toTop) : PreservesLimit (cospan f g) (toCompHausLike h) := by diff --git a/Mathlib/Topology/Category/CompHausLike/SigmaComparison.lean b/Mathlib/Topology/Category/CompHausLike/SigmaComparison.lean new file mode 100644 index 0000000000000..ae1412b6a3d0d --- /dev/null +++ b/Mathlib/Topology/Category/CompHausLike/SigmaComparison.lean @@ -0,0 +1,70 @@ +/- +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.Topology.Category.CompHausLike.Limits +/-! + +# The sigma-comparison map + +This file defines the map `CompHausLike.sigmaComparison` associated to a presheaf `X` on +`CompHausLike P`, and a finite family `S₁,...,Sₙ` of spaces in `CompHausLike P`, where `P` is +stable under taking finite disjoint unions. + +The map `sigmaComparison` is the canonical map `X(S₁ ⊔ ... ⊔ Sₙ) ⟶ X(S₁) × ... × X(Sₙ)` induced by +the inclusion maps `Sᵢ ⟶ S₁ ⊔ ... ⊔ Sₙ`, and it is an isomorphism when `X` preserves finite +products. +-/ + +universe u w + +open CategoryTheory Limits + +namespace CompHausLike + +variable {P : TopCat.{u} → Prop} [HasExplicitFiniteCoproducts.{u} P] + (X : (CompHausLike.{u} P)ᵒᵖ ⥤ Type max u w) [PreservesFiniteProducts X] + {α : Type u} [Finite α] (σ : α → Type u) + [∀ a, TopologicalSpace (σ a)] [∀ a, CompactSpace (σ a)] [∀ a, T2Space (σ a)] + [∀ a, HasProp P (σ a)] + +instance : HasProp P (Σ (a : α), (σ a)) := HasExplicitFiniteCoproducts.hasProp (fun a ↦ of P (σ a)) + +/-- +The comparison map from the value of a condensed set on a finite coproduct to the product of the +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))) + (productIsProduct fun x ↦ Opposite.op (of P (σ x))))).hom ≫ + (PreservesProduct.iso X fun a ↦ ⟨of P (σ a)⟩).hom ≫ + (Types.productIso.{u, max u w} fun a ↦ X.obj ⟨of P (σ a)⟩).hom := by + ext x a + simp only [Cofan.mk_pt, Fan.mk_pt, Functor.mapIso_hom, + PreservesProduct.iso_hom, types_comp_apply, Types.productIso_hom_comp_eval_apply] + have := congrFun (piComparison_comp_π X (fun a ↦ ⟨of P (σ a)⟩) a) + simp only [types_comp_apply] at this + rw [this, ← FunctorToTypes.map_comp_apply] + simp only [sigmaComparison] + apply congrFun + congr 2 + rw [← opCoproductIsoProduct_inv_comp_ι] + simp only [coe_of, Opposite.unop_op, unop_comp, Quiver.Hom.unop_op, Category.assoc] + simp only [opCoproductIsoProduct, ← unop_comp, opCoproductIsoProduct'_comp_self] + erw [IsColimit.fac] + rfl + +instance isIsoSigmaComparison : IsIso <| sigmaComparison X σ := by + rw [sigmaComparison_eq_comp_isos] + infer_instance + +end CompHausLike diff --git a/Mathlib/Topology/Category/CompactlyGenerated.lean b/Mathlib/Topology/Category/CompactlyGenerated.lean index 200b869bfa079..2563c6dffb796 100644 --- a/Mathlib/Topology/Category/CompactlyGenerated.lean +++ b/Mathlib/Topology/Category/CompactlyGenerated.lean @@ -9,7 +9,7 @@ import Mathlib.CategoryTheory.Elementwise # Compactly generated topological spaces -This file defines the category of compactly generated topological spaces. These are spaces `X` such +This file defines the category of compactly generated topological spaces. These are spaces `X` such that a map `f : X → Y` is continuous whenever the composition `S → X → Y` is continuous for all compact Hausdorff spaces `S` mapping continuously to `X`. diff --git a/Mathlib/Topology/Category/LightProfinite/AsLimit.lean b/Mathlib/Topology/Category/LightProfinite/AsLimit.lean index d5e2c6c5f4e62..48104258a6815 100644 --- a/Mathlib/Topology/Category/LightProfinite/AsLimit.lean +++ b/Mathlib/Topology/Category/LightProfinite/AsLimit.lean @@ -36,14 +36,14 @@ abbrev diagram : ℕᵒᵖ ⥤ LightProfinite := S.fintypeDiagram ⋙ FintypeCat /-- A cone over `S.diagram` whose cone point is isomorphic to `S`. -(Auxiliary definition, use `S.asLimitCone` instead.) +(Auxiliary definition, use `S.asLimitCone` instead.) -/ def asLimitConeAux : Cone S.diagram := let c : Cone (S.diagram ⋙ lightToProfinite) := S.toLightDiagram.cone let hc : IsLimit c := S.toLightDiagram.isLimit liftLimit hc -/-- An auxiliary isomorphism of cones used to prove that `S.asLimitConeAux` is a limit cone. -/ +/-- An auxiliary isomorphism of cones used to prove that `S.asLimitConeAux` is a limit cone. -/ def isoMapCone : lightToProfinite.mapCone S.asLimitConeAux ≅ S.toLightDiagram.cone := let c : Cone (S.diagram ⋙ lightToProfinite) := S.toLightDiagram.cone let hc : IsLimit c := S.toLightDiagram.isLimit @@ -51,7 +51,7 @@ def isoMapCone : lightToProfinite.mapCone S.asLimitConeAux ≅ S.toLightDiagram. /-- `S.asLimitConeAux` is indeed a limit cone. -(Auxiliary definition, use `S.asLimit` instead.) +(Auxiliary definition, use `S.asLimit` instead.) -/ def asLimitAux : IsLimit S.asLimitConeAux := let hc : IsLimit (lightToProfinite.mapCone S.asLimitConeAux) := diff --git a/Mathlib/Topology/Category/LightProfinite/Basic.lean b/Mathlib/Topology/Category/LightProfinite/Basic.lean index 73394bd6a5fbe..40d42567504e8 100644 --- a/Mathlib/Topology/Category/LightProfinite/Basic.lean +++ b/Mathlib/Topology/Category/LightProfinite/Basic.lean @@ -17,8 +17,14 @@ implemented as totally disconnected second countable compact Hausdorff spaces. This file also defines the category `LightDiagram`, which consists of those spaces that can be written as a sequential limit (in `Profinite`) of finite sets. -We define an equivalence of categories `LightProfinite ≌ LightDiagram` and prove that these are +We define an equivalence of categories `LightProfinite ≌ LightDiagram` and prove that these are essentially small categories. + +## Implementation + +The category `LightProfinite` is defined using the structure `CompHausLike`. See the file +`CompHausLike.Basic` for more information. + -/ /- The basic API for `LightProfinite` is largely copied from the API of `Profinite`; @@ -225,6 +231,9 @@ theorem epi_iff_surjective {X Y : LightProfinite.{u}} (f : X ⟶ Y) : · rw [← CategoryTheory.epi_iff_surjective] apply (forget LightProfinite).epi_of_epi_map +instance : lightToProfinite.PreservesEpimorphisms where + preserves f _ := (Profinite.epi_iff_surjective _).mpr ((epi_iff_surjective f).mp inferInstance) + end LightProfinite /-- A structure containing the data of sequential limit in `Profinite` of finite sets. -/ @@ -238,7 +247,7 @@ structure LightDiagram : Type (u+1) where namespace LightDiagram -/-- The underlying `Profinite` of a `LightDiagram`. -/ +/-- The underlying `Profinite` of a `LightDiagram`. -/ def toProfinite (S : LightDiagram) : Profinite := S.cone.pt @[simps!] @@ -380,7 +389,7 @@ instance : LightDiagram'.toLightFunctor.{u}.EssSurj where instance : LightDiagram'.toLightFunctor.IsEquivalence where -/-- The equivalence beween `LightDiagram` and a small category. -/ +/-- The equivalence between `LightDiagram` and a small category. -/ def LightDiagram.equivSmall : LightDiagram.{u} ≌ LightDiagram'.{u} := LightDiagram'.toLightFunctor.asEquivalence.symm diff --git a/Mathlib/Topology/Category/LightProfinite/Extend.lean b/Mathlib/Topology/Category/LightProfinite/Extend.lean new file mode 100644 index 0000000000000..55d6645661ad5 --- /dev/null +++ b/Mathlib/Topology/Category/LightProfinite/Extend.lean @@ -0,0 +1,198 @@ +/- +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.Topology.Category.LightProfinite.AsLimit +import Mathlib.Topology.Category.Profinite.Extend + +/-! + +# Extending cones in `LightProfinite` + +Let `(Sₙ)_{n : ℕᵒᵖ}` be a sequential inverse system of finite sets and let `S` be +its limit in `Profinite`. Let `G` be a functor from `LightProfinite` to a category `C` and suppose +that `G` preserves the limit described above. Suppose further that the projection maps `S ⟶ Sₙ` are +epimorphic for all `n`. Then `G.obj S` is isomorphic to a limit indexed by +`StructuredArrow S toLightProfinite` (see `LightProfinite.Extend.isLimitCone`). + +We also provide the dual result for a functor of the form `G : LightProfiniteᵒᵖ ⥤ C`. + +We apply this to define `LightProfinite.diagram'`, `LightProfinite.asLimitCone'`, and +`LightProfinite.asLimit'`, analogues to their unprimed versions in +`Mathlib.Topology.Category.LightProfinite.AsLimit`, in which the +indexing category is `StructuredArrow S toLightProfinite` instead of `ℕᵒᵖ`. +-/ + +universe u + +open CategoryTheory Limits FintypeCat Functor + +attribute [local instance] FintypeCat.discreteTopology ConcreteCategory.instFunLike + +namespace LightProfinite + +variable {F : ℕᵒᵖ ⥤ FintypeCat.{u}} (c : Cone <| F ⋙ toLightProfinite) + +namespace Extend + +/-- +Given a sequential cone in `LightProfinite` consisting of finite sets, +we obtain a functor from the indexing category to `StructuredArrow c.pt toLightProfinite`. +-/ +@[simps] +def functor : ℕᵒᵖ ⥤ StructuredArrow c.pt toLightProfinite where + obj i := StructuredArrow.mk (c.π.app i) + map f := StructuredArrow.homMk (F.map f) (c.w f) + +-- We check that the original diagram factors through `LightProfinite.Extend.functor`. +example : functor c ⋙ StructuredArrow.proj c.pt toLightProfinite ≅ F := Iso.refl _ + +/-- +Given a sequential cone in `LightProfinite` consisting of finite sets, +we obtain a functor from the opposite of the indexing category to +`CostructuredArrow toProfinite.op ⟨c.pt⟩`. +-/ +@[simps! obj map] +def functorOp : ℕ ⥤ CostructuredArrow toLightProfinite.op ⟨c.pt⟩ := + (functor c).rightOp ⋙ StructuredArrow.toCostructuredArrow _ _ + +-- We check that the opposite of the original diagram factors through `Profinite.Extend.functorOp`. +example : functorOp c ⋙ CostructuredArrow.proj toLightProfinite.op ⟨c.pt⟩ ≅ F.rightOp := Iso.refl _ + +-- We check that `Profinite.Extend.functor` factors through `LightProfinite.Extend.functor`, +-- via the equivalence `StructuredArrow.post _ _ lightToProfinite`. +example : functor c ⋙ (StructuredArrow.post _ _ lightToProfinite) = + Profinite.Extend.functor (lightToProfinite.mapCone c) := rfl + +/-- +If the projection maps in the cone are epimorphic and the cone is limiting, then +`LightProfinite.Extend.functor` is initial. +-/ +theorem functor_initial (hc : IsLimit c) [∀ i, Epi (c.π.app i)] : Initial (functor c) := by + rw [initial_iff_comp_equivalence _ (StructuredArrow.post _ _ lightToProfinite)] + have : ∀ i, Epi ((lightToProfinite.mapCone c).π.app i) := + fun i ↦ inferInstanceAs (Epi (lightToProfinite.map (c.π.app i))) + exact Profinite.Extend.functor_initial _ (isLimitOfPreserves lightToProfinite hc) + +/-- +If the projection maps in the cone are epimorphic and the cone is limiting, then +`LightProfinite.Extend.functorOp` is final. +-/ +theorem functorOp_final (hc : IsLimit c) [∀ i, Epi (c.π.app i)] : Final (functorOp c) := by + have := functor_initial c hc + have : ((StructuredArrow.toCostructuredArrow toLightProfinite c.pt)).IsEquivalence := + (inferInstance : (structuredArrowOpEquivalence _ _).functor.IsEquivalence ) + have : (functor c).rightOp.Final := + inferInstanceAs ((opOpEquivalence ℕ).inverse ⋙ (functor c).op).Final + exact Functor.final_comp (functor c).rightOp _ + +section Limit + +variable {C : Type*} [Category C] (G : LightProfinite ⥤ C) + +/-- +Given a functor `G` from `LightProfinite` and `S : LightProfinite`, we obtain a cone on +`(StructuredArrow.proj S toLightProfinite ⋙ toLightProfinite ⋙ G)` with cone point `G.obj S`. + +Whiskering this cone with `LightProfinite.Extend.functor c` gives `G.mapCone c` as we check in the +example below. +-/ +def cone (S : LightProfinite) : + Cone (StructuredArrow.proj S toLightProfinite ⋙ toLightProfinite ⋙ G) where + pt := G.obj S + π := { + app := fun i ↦ G.map i.hom + naturality := fun _ _ f ↦ (by + have := f.w + simp only [const_obj_obj, StructuredArrow.left_eq_id, const_obj_map, Category.id_comp, + StructuredArrow.w] at this + simp only [const_obj_obj, comp_obj, StructuredArrow.proj_obj, const_obj_map, Category.id_comp, + Functor.comp_map, StructuredArrow.proj_map, ← map_comp, StructuredArrow.w]) } + +example : G.mapCone c = (cone G c.pt).whisker (functor c) := rfl + +/-- +If `c` and `G.mapCone c` are limit cones and the projection maps in `c` are epimorphic, +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' + +end Limit + +section Colimit + +variable {C : Type*} [Category C] (G : LightProfiniteᵒᵖ ⥤ C) + +/-- +Given a functor `G` from `LightProfiniteᵒᵖ` and `S : LightProfinite`, we obtain a cocone on +`(CostructuredArrow.proj toLightProfinite.op ⟨S⟩ ⋙ toLightProfinite.op ⋙ G)` with cocone point +`G.obj ⟨S⟩`. + +Whiskering this cocone with `LightProfinite.Extend.functorOp c` gives `G.mapCocone c.op` as we +check in the example below. +-/ +@[simps] +def cocone (S : LightProfinite) : + Cocone (CostructuredArrow.proj toLightProfinite.op ⟨S⟩ ⋙ toLightProfinite.op ⋙ G) where + pt := G.obj ⟨S⟩ + ι := { + app := fun i ↦ G.map i.hom + naturality := fun _ _ f ↦ (by + have := f.w + simp only [op_obj, const_obj_obj, op_map, CostructuredArrow.right_eq_id, const_obj_map, + Category.comp_id] at this + simp only [comp_obj, CostructuredArrow.proj_obj, op_obj, const_obj_obj, Functor.comp_map, + CostructuredArrow.proj_map, op_map, ← map_comp, this, const_obj_map, Category.comp_id]) } + +example : G.mapCocone c.op = (cocone G c.pt).whisker + ((opOpEquivalence ℕ).functor ⋙ functorOp c) := rfl + +/-- +If `c` is a limit cone, `G.mapCocone c.op` is a colimit cone and the projection maps in `c` +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) := + haveI := functorOp_final c hc + (Functor.final_comp (opOpEquivalence ℕ).functor (functorOp c)).isColimitWhiskerEquiv _ hc' + +end Colimit + +end Extend + +open Extend + +section LightProfiniteAsLimit + +variable (S : LightProfinite.{u}) + +/-- +A functor `StructuredArrow S toLightProfinite ⥤ FintypeCat` whose limit in `LightProfinite` is +isomorphic to `S`. +-/ +abbrev fintypeDiagram' : StructuredArrow S toLightProfinite ⥤ FintypeCat := + StructuredArrow.proj S toLightProfinite + +/-- An abbreviation for `S.fintypeDiagram' ⋙ toLightProfinite`. -/ +abbrev diagram' : StructuredArrow S toLightProfinite ⥤ LightProfinite := + S.fintypeDiagram' ⋙ toLightProfinite + +/-- A cone over `S.diagram'` whose cone point is `S`. -/ +def asLimitCone' : Cone (S.diagram') := cone (𝟭 _) S + +instance (i : ℕᵒᵖ) : Epi (S.asLimitCone.π.app i) := + (epi_iff_surjective _).mpr (S.proj_surjective _) + +/-- `S.asLimitCone'` is a limit cone. -/ +noncomputable def asLimit' : IsLimit S.asLimitCone' := isLimitCone _ (𝟭 _) S.asLimit S.asLimit + +/-- A bundled version of `S.asLimitCone'` and `S.asLimit'`. -/ +noncomputable def lim' : LimitCone S.diagram' := ⟨S.asLimitCone', S.asLimit'⟩ + +end LightProfiniteAsLimit + +end LightProfinite diff --git a/Mathlib/Topology/Category/LightProfinite/Sequence.lean b/Mathlib/Topology/Category/LightProfinite/Sequence.lean index 17d3590bd8020..ae729f14b1979 100644 --- a/Mathlib/Topology/Category/LightProfinite/Sequence.lean +++ b/Mathlib/Topology/Category/LightProfinite/Sequence.lean @@ -17,7 +17,7 @@ open CategoryTheory TopologicalSpace OnePoint namespace LightProfinite -/-- The continuous map from `ℕ∪{∞}` to `ℝ` sending `n` to `1/(n+1)` and `∞` to `0`. -/ +/-- The continuous map from `ℕ∪{∞}` to `ℝ` sending `n` to `1/(n+1)` and `∞` to `0`. -/ noncomputable def natUnionInftyEmbedding : C(OnePoint ℕ, ℝ) where toFun | ∞ => 0 @@ -26,7 +26,7 @@ noncomputable def natUnionInftyEmbedding : C(OnePoint ℕ, ℝ) where tendsto_one_div_add_atTop_nhds_zero_nat /-- -The continuous map from `ℕ∪{∞}` to `ℝ` sending `n` to `1/(n+1)` and `∞` to `0` is a closed +The continuous map from `ℕ∪{∞}` to `ℝ` sending `n` to `1/(n+1)` and `∞` to `0` is a closed embedding. -/ lemma closedEmbedding_natUnionInftyEmbedding : ClosedEmbedding natUnionInftyEmbedding := by diff --git a/Mathlib/Topology/Category/Profinite/Basic.lean b/Mathlib/Topology/Category/Profinite/Basic.lean index 2fcfa55ea7cfa..01e03d65b2389 100644 --- a/Mathlib/Topology/Category/Profinite/Basic.lean +++ b/Mathlib/Topology/Category/Profinite/Basic.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2020 Kevin Buzzard. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Kevin Buzzard, Calle Sönne +Authors: Kevin Buzzard, Calle Sönne, Dagur Asgeirsson -/ import Mathlib.CategoryTheory.FintypeCat import Mathlib.Topology.Category.CompHaus.Basic @@ -23,6 +23,9 @@ is called `Profinite.toTop`. A profinite type is defined to be a topological space which is compact, Hausdorff and totally disconnected. +The category `Profinite` is defined using the structure `CompHausLike`. See the file +`CompHausLike.Basic` for more information. + ## TODO * Define procategories and prove that `Profinite` is equivalent to `Pro (FintypeCat)`. @@ -46,7 +49,7 @@ abbrev Profinite := CompHausLike (fun X ↦ TotallyDisconnectedSpace X) namespace Profinite -instance (X : Type*) [TopologicalSpace X] +instance (X : Type*) [TopologicalSpace X] [TotallyDisconnectedSpace X] : HasProp (fun Y ↦ TotallyDisconnectedSpace Y) X := ⟨(inferInstance : TotallyDisconnectedSpace X)⟩ diff --git a/Mathlib/Topology/Category/Profinite/EffectiveEpi.lean b/Mathlib/Topology/Category/Profinite/EffectiveEpi.lean index 2777ca0f06433..251da0eb75003 100644 --- a/Mathlib/Topology/Category/Profinite/EffectiveEpi.lean +++ b/Mathlib/Topology/Category/Profinite/EffectiveEpi.lean @@ -54,7 +54,7 @@ instance : profiniteToCompHaus.ReflectsEffectiveEpis where ((Profinite.effectiveEpi_tfae f).out 0 2).mpr (((CompHaus.effectiveEpi_tfae _).out 0 2).mp h) /-- -An effective presentation of an `X : Profinite` with respect to the inclusion functor from `Stonean` +An effective presentation of an `X : Profinite` with respect to the inclusion functor from `Stonean` -/ noncomputable def profiniteToCompHausEffectivePresentation (X : CompHaus) : profiniteToCompHaus.EffectivePresentation X where diff --git a/Mathlib/Topology/Category/Profinite/Extend.lean b/Mathlib/Topology/Category/Profinite/Extend.lean new file mode 100644 index 0000000000000..1ac168134b484 --- /dev/null +++ b/Mathlib/Topology/Category/Profinite/Extend.lean @@ -0,0 +1,217 @@ +/- +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.Topology.Category.Profinite.AsLimit +import Mathlib.Topology.Category.Profinite.CofilteredLimit +import Mathlib.CategoryTheory.Filtered.Final +/-! + +# Extending cones in `Profinite` + +Let `(Sᵢ)_{i : I}` be a family of finite sets indexed by a cofiltered category `I` and let `S` be +its limit in `Profinite`. Let `G` be a functor from `Profinite` to a category `C` and suppose that +`G` preserves the limit described above. Suppose further that the projection maps `S ⟶ Sᵢ` are +epimorphic for all `i`. Then `G.obj S` is isomorphic to a limit indexed by +`StructuredArrow S toProfinite` (see `Profinite.Extend.isLimitCone`). + +We also provide the dual result for a functor of the form `G : Profiniteᵒᵖ ⥤ C`. + +We apply this to define `Profinite.diagram'`, `Profinite.asLimitCone'`, and `Profinite.asLimit'`, +analogues to their unprimed versions in `Mathlib.Topology.Category.Profinite.AsLimit`, in which the +indexing category is `StructuredArrow S toProfinite` instead of `DiscreteQuotient S`. +-/ + +universe u w + +open CategoryTheory Limits FintypeCat Functor + +attribute [local instance] ConcreteCategory.instFunLike + +namespace Profinite + +variable {I : Type u} [SmallCategory I] [IsCofiltered I] + {F : I ⥤ FintypeCat.{max u w}} (c : Cone <| F ⋙ toProfinite) + +/-- +A continuous map from a profinite set to a finite set factors through one of the components of +the profinite set when written as a cofiltered limit of finite sets. +-/ +lemma exists_hom (hc : IsLimit c) {X : FintypeCat} (f : c.pt ⟶ toProfinite.obj X) : + ∃ (i : I) (g : F.obj i ⟶ X), f = c.π.app i ≫ toProfinite.map g := by + let _ : TopologicalSpace X := ⊥ + have : DiscreteTopology (toProfinite.obj X) := ⟨rfl⟩ + let f' : LocallyConstant c.pt (toProfinite.obj X) := + ⟨f, (IsLocallyConstant.iff_continuous _).mpr f.continuous⟩ + obtain ⟨i, g, h⟩ := exists_locallyConstant.{_, u} c hc f' + refine ⟨i, (g : _ → _), ?_⟩ + ext x + exact LocallyConstant.congr_fun h x + +namespace Extend + +/-- +Given a cone in `Profinite`, consisting of finite sets and indexed by a cofiltered category, +we obtain a functor from the indexing category to `StructuredArrow c.pt toProfinite`. +-/ +@[simps] +def functor : I ⥤ StructuredArrow c.pt toProfinite where + obj i := StructuredArrow.mk (c.π.app i) + map f := StructuredArrow.homMk (F.map f) (c.w f) + +-- We check that the original diagram factors through `Profinite.Extend.functor`. +example : functor c ⋙ StructuredArrow.proj c.pt toProfinite ≅ F := Iso.refl _ + +/-- +Given a cone in `Profinite`, consisting of finite sets and indexed by a cofiltered category, +we obtain a functor from the opposite of the indexing category to +`CostructuredArrow toProfinite.op ⟨c.pt⟩`. +-/ +@[simps! obj map] +def functorOp : Iᵒᵖ ⥤ CostructuredArrow toProfinite.op ⟨c.pt⟩ := + (functor c).op ⋙ StructuredArrow.toCostructuredArrow _ _ + +-- We check that the opposite of the original diagram factors through `Profinite.Extend.functorOp`. +example : functorOp c ⋙ CostructuredArrow.proj toProfinite.op ⟨c.pt⟩ ≅ F.op := Iso.refl _ + +/-- +If the projection maps in the cone are epimorphic and the cone is limiting, then +`Profinite.Extend.functor` is initial. + +TODO: investigate how to weaken the assumption `∀ i, Epi (c.π.app i)` to +`∀ i, ∃ j (_ : j ⟶ i), Epi (c.π.app j)`. +-/ +lemma functor_initial (hc : IsLimit c) [∀ i, Epi (c.π.app i)] : Initial (functor c) := by + let e : I ≌ ULiftHom.{w} (ULift.{w} I) := ULiftHomULiftCategory.equiv _ + suffices (e.inverse ⋙ functor c).Initial from initial_of_equivalence_comp e.inverse (functor c) + rw [initial_iff_of_isCofiltered (F := e.inverse ⋙ functor c)] + constructor + · intro ⟨_, X, (f : c.pt ⟶ _)⟩ + obtain ⟨i, g, h⟩ := exists_hom c hc f + refine ⟨⟨i⟩, ⟨StructuredArrow.homMk g h.symm⟩⟩ + · intro ⟨_, X, (f : c.pt ⟶ _)⟩ ⟨i⟩ ⟨_, (s : F.obj i ⟶ X), (w : f = c.π.app i ≫ _)⟩ + ⟨_, (s' : F.obj i ⟶ X), (w' : f = c.π.app i ≫ _)⟩ + simp only [functor_obj, functor_map, StructuredArrow.hom_eq_iff, StructuredArrow.mk_right, + StructuredArrow.comp_right, StructuredArrow.homMk_right] + refine ⟨⟨i⟩, 𝟙 _, ?_⟩ + simp only [CategoryTheory.Functor.map_id, Category.id_comp] + rw [w] at w' + exact toProfinite.map_injective <| Epi.left_cancellation _ _ w' + +/-- +If the projection maps in the cone are epimorphic and the cone is limiting, then +`Profinite.Extend.functorOp` is final. +-/ +lemma functorOp_final (hc : IsLimit c) [∀ i, Epi (c.π.app i)] : Final (functorOp c) := by + have := functor_initial c hc + have : ((StructuredArrow.toCostructuredArrow toProfinite c.pt)).IsEquivalence := + (inferInstance : (structuredArrowOpEquivalence _ _).functor.IsEquivalence ) + exact Functor.final_comp (functor c).op _ + +section Limit + +variable {C : Type*} [Category C] (G : Profinite ⥤ C) + +/-- +Given a functor `G` from `Profinite` and `S : Profinite`, we obtain a cone on +`(StructuredArrow.proj S toProfinite ⋙ toProfinite ⋙ G)` with cone point `G.obj S`. + +Whiskering this cone with `Profinite.Extend.functor c` gives `G.mapCone c` as we check in the +example below. +-/ +@[simps] +def cone (S : Profinite) : + Cone (StructuredArrow.proj S toProfinite ⋙ toProfinite ⋙ G) where + pt := G.obj S + π := { + app := fun i ↦ G.map i.hom + naturality := fun _ _ f ↦ (by + have := f.w + simp only [const_obj_obj, StructuredArrow.left_eq_id, const_obj_map, Category.id_comp, + StructuredArrow.w] at this + simp only [const_obj_obj, comp_obj, StructuredArrow.proj_obj, const_obj_map, Category.id_comp, + Functor.comp_map, StructuredArrow.proj_map, ← map_comp, StructuredArrow.w]) } + +example : G.mapCone c = (cone G c.pt).whisker (functor c) := rfl + +/-- +If `c` and `G.mapCone c` are limit cones and the projection maps in `c` are epimorphic, +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' + +end Limit + +section Colimit + +variable {C : Type*} [Category C] (G : Profiniteᵒᵖ ⥤ C) + +/-- +Given a functor `G` from `Profiniteᵒᵖ` and `S : Profinite`, we obtain a cocone on +`(CostructuredArrow.proj toProfinite.op ⟨S⟩ ⋙ toProfinite.op ⋙ G)` with cocone point `G.obj ⟨S⟩`. + +Whiskering this cocone with `Profinite.Extend.functorOp c` gives `G.mapCocone c.op` as we check in +the example below. +-/ +@[simps] +def cocone (S : Profinite) : + Cocone (CostructuredArrow.proj toProfinite.op ⟨S⟩ ⋙ toProfinite.op ⋙ G) where + pt := G.obj ⟨S⟩ + ι := { + app := fun i ↦ G.map i.hom + naturality := fun _ _ f ↦ (by + have := f.w + simp only [op_obj, const_obj_obj, op_map, CostructuredArrow.right_eq_id, const_obj_map, + Category.comp_id] at this + simp only [comp_obj, CostructuredArrow.proj_obj, op_obj, const_obj_obj, Functor.comp_map, + CostructuredArrow.proj_map, op_map, ← map_comp, this, const_obj_map, Category.comp_id]) } + +example : G.mapCocone c.op = (cocone G c.pt).whisker (functorOp c) := rfl + +/-- +If `c` is a limit cone, `G.mapCocone c.op` is a colimit cone and the projection maps in `c` +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' + +end Colimit + +end Extend + +open Extend + +section ProfiniteAsLimit + +variable (S : Profinite.{u}) + +/-- +A functor `StructuredArrow S toProfinite ⥤ FintypeCat` whose limit in `Profinite` is isomorphic +to `S`. +-/ +abbrev fintypeDiagram' : StructuredArrow S toProfinite ⥤ FintypeCat := + StructuredArrow.proj S toProfinite + +/-- An abbreviation for `S.fintypeDiagram' ⋙ toProfinite`. -/ +abbrev diagram' : StructuredArrow S toProfinite ⥤ Profinite := + S.fintypeDiagram' ⋙ toProfinite + +/-- A cone over `S.diagram'` whose cone point is `S`. -/ +abbrev asLimitCone' : Cone (S.diagram') := cone (𝟭 _) S + +instance (i : DiscreteQuotient S) : Epi (S.asLimitCone.π.app i) := + (epi_iff_surjective _).mpr i.proj_surjective + +/-- `S.asLimitCone'` is a limit cone. -/ +noncomputable def asLimit' : IsLimit S.asLimitCone' := isLimitCone _ (𝟭 _) S.asLimit S.asLimit + +/-- A bundled version of `S.asLimitCone'` and `S.asLimit'`. -/ +noncomputable def lim' : LimitCone S.diagram' := ⟨S.asLimitCone', S.asLimit'⟩ + +end ProfiniteAsLimit + +end Profinite diff --git a/Mathlib/Topology/Category/Profinite/Nobeling.lean b/Mathlib/Topology/Category/Profinite/Nobeling.lean index 03bbf9e71818c..b666e7f0d9593 100644 --- a/Mathlib/Topology/Category/Profinite/Nobeling.lean +++ b/Mathlib/Topology/Category/Profinite/Nobeling.lean @@ -18,16 +18,16 @@ This file proves Nöbeling's theorem. ## Main result * `LocallyConstant.freeOfProfinite`: Nöbeling's theorem. - For `S : Profinite`, the `ℤ`-module `LocallyConstant S ℤ` is free. + For `S : Profinite`, the `ℤ`-module `LocallyConstant S ℤ` is free. ## Proof idea We follow the proof of theorem 5.4 in [scholze2019condensed], in which the idea is to embed `S` in a product of `I` copies of `Bool` for some sufficiently large `I`, and then to choose a -well-ordering on `I` and use ordinal induction over that well-order. Here we can let `I` be -the set of clopen subsets of `S` since `S` is totally separated. +well-ordering on `I` and use ordinal induction over that well-order. Here we can let `I` be +the set of clopen subsets of `S` since `S` is totally separated. -The above means it suffices to prove the following statement: For a closed subset `C` of `I → Bool`, +The above means it suffices to prove the following statement: For a closed subset `C` of `I → Bool`, the `ℤ`-module `LocallyConstant C ℤ` is free. For `i : I`, let `e C i : LocallyConstant C ℤ` denote the map `fun f ↦ (if f.val i then 1 else 0)`. @@ -60,7 +60,7 @@ section Projections The purpose of this section is twofold. -Firstly, in the proof that the set `GoodProducts C` spans the whole module `LocallyConstant C ℤ`, +Firstly, in the proof that the set `GoodProducts C` spans the whole module `LocallyConstant C ℤ`, we need to project `C` down to finite discrete subsets and write `C` as a cofiltered limit of those. Secondly, in the inductive argument, we need to project `C` down to "smaller" sets satisfying the @@ -73,11 +73,11 @@ In this section we define the relevant projection maps and prove some compatibil * Let `J : I → Prop`. Then `Proj J : (I → Bool) → (I → Bool)` is the projection mapping everything that satisfies `J i` to itself, and everything else to `false`. -* The image of `C` under `Proj J` is denoted `π C J` and the corresponding map `C → π C J` is called - `ProjRestrict`. If `J` implies `K` we have a map `ProjRestricts : π C K → π C J`. +* The image of `C` under `Proj J` is denoted `π C J` and the corresponding map `C → π C J` is called + `ProjRestrict`. If `J` implies `K` we have a map `ProjRestricts : π C K → π C J`. * `spanCone_isLimit` establishes that when `C` is compact, it can be written as a limit of its - images under the maps `Proj (· ∈ s)` where `s : Finset I`. + images under the maps `Proj (· ∈ s)` where `s : Finset I`. -/ variable (J K L : I → Prop) [∀ i, Decidable (J i)] [∀ i, Decidable (K i)] [∀ i, Decidable (L i)] @@ -171,7 +171,7 @@ theorem projRestricts_comp_projRestrict (h : ∀ i, J i → K i) : variable (J) -/-- The objectwise map in the isomorphism `spanFunctor ≅ Profinite.indexFunctor`. -/ +/-- The objectwise map in the isomorphism `spanFunctor ≅ Profinite.indexFunctor`. -/ def iso_map : C(π C J, (IndexFunctor.obj C J)) := ⟨fun x ↦ ⟨fun i ↦ x.val i.val, by rcases x with ⟨x, y, hy, rfl⟩ @@ -197,7 +197,6 @@ lemma iso_map_bijective : Function.Bijective (iso_map C J) := by exact dif_pos i.prop variable {C} -variable (hC : IsCompact C) /-- For a given compact subset `C` of `I → Bool`, `spanFunctor` is the functor from the poset of finsets @@ -205,7 +204,7 @@ of `I` to `Profinite`, sending a finite subset set `J` to the image of `C` under `Proj J`. -/ noncomputable -def spanFunctor [∀ (s : Finset I) (i : I), Decidable (i ∈ s)] : +def spanFunctor [∀ (s : Finset I) (i : I), Decidable (i ∈ s)] (hC : IsCompact C) : (Finset I)ᵒᵖ ⥤ Profinite.{u} where obj s := @Profinite.of (π C (· ∈ (unop s))) _ (by rw [← isCompact_iff_compactSpace]; exact hC.image (continuous_proj _)) _ _ @@ -215,7 +214,8 @@ def spanFunctor [∀ (s : Finset I) (i : I), Decidable (i ∈ s)] : /-- The limit cone on `spanFunctor` with point `C`. -/ noncomputable -def spanCone [∀ (s : Finset I) (i : I), Decidable (i ∈ s)] : Cone (spanFunctor hC) where +def spanCone [∀ (s : Finset I) (i : I), Decidable (i ∈ s)] (hC : IsCompact C) : + Cone (spanFunctor hC) where pt := @Profinite.of C _ (by rwa [← isCompact_iff_compactSpace]) _ _ π := { app := fun s ↦ ⟨ProjRestrict C (· ∈ unop s), continuous_projRestrict _ _⟩ @@ -228,7 +228,7 @@ def spanCone [∀ (s : Finset I) (i : I), Decidable (i ∈ s)] : Cone (spanFunct /-- `spanCone` is a limit cone. -/ noncomputable -def spanCone_isLimit [∀ (s : Finset I) (i : I), Decidable (i ∈ s)] : +def spanCone_isLimit [∀ (s : Finset I) (i : I), Decidable (i ∈ s)] (hC : IsCompact C) : CategoryTheory.Limits.IsLimit (spanCone hC) := by refine (IsLimit.postcomposeHomEquiv (NatIso.ofComponents (fun s ↦ (CompHausLike.isoOfBijective _ (iso_map_bijective C (· ∈ unop s)))) ?_) (spanCone hC)) @@ -264,7 +264,7 @@ of `e`. * `Products I` is the type of lists of decreasing elements of `I`, so a typical element is `[i₁, i₂,..., iᵣ]` with `i₁ > i₂ > ... > iᵣ`. -* `Products.eval C` is the `C`-evaluation of a list. It takes a term `[i₁, i₂,..., iᵣ] : Products I` +* `Products.eval C` is the `C`-evaluation of a list. It takes a term `[i₁, i₂,..., iᵣ] : Products I` and returns the actual product `e C i₁ ··· e C iᵣ : LocallyConstant C ℤ`. * `GoodProducts C` is the set of `Products I` such that their `C`-evaluation cannot be written as @@ -272,7 +272,7 @@ of `e`. ### Main results -* `Products.evalFacProp` and `Products.evalFacProps` establish the fact that `Products.eval`  +* `Products.evalFacProp` and `Products.evalFacProps` establish the fact that `Products.eval` interacts nicely with the projection maps from the previous section. * `GoodProducts.span_iff_products`: the good products span `LocallyConstant C ℤ` iff all the @@ -359,7 +359,7 @@ theorem injective : Function.Injective (eval C) := by · exfalso; apply ha; rw [h] exact Submodule.subset_span ⟨b, ⟨h',rfl⟩⟩ -/-- The image of the good products in the module `LocallyConstant C ℤ`. -/ +/-- The image of the good products in the module `LocallyConstant C ℤ`. -/ def range := Set.range (GoodProducts.eval C) /-- The type of good products is equivalent to its image. -/ @@ -414,7 +414,7 @@ theorem evalFacProps {l : Products I} (J K : I → Prop) ext; simp [Homeomorph.setCongr, Products.eval_eq] rw [ProjRestricts, ← Function.comp.assoc, this, ← evalFacProp (π C K) J h] -theorem prop_of_isGood {l : Products I} (J : I → Prop) [∀ j, Decidable (J j)] +theorem prop_of_isGood {l : Products I} (J : I → Prop) [∀ j, Decidable (J j)] (h : l.isGood (π C J)) : ∀ a, a ∈ l.val → J a := by intro i hi by_contra h' @@ -624,8 +624,8 @@ theorem GoodProducts.spanFin [IsWellOrder I (· < ·)] : rw [List.map_cons, List.prod_cons] intro ha specialize ih (by rw [List.chain'_cons'] at ha; exact ha.2) - rw [Finsupp.mem_span_image_iff_total] at ih - simp only [Finsupp.mem_supported, Finsupp.total_apply] at ih + rw [Finsupp.mem_span_image_iff_linearCombination] at ih + simp only [Finsupp.mem_supported, Finsupp.linearCombination_apply] at ih obtain ⟨c, hc, hc'⟩ := ih rw [← hc']; clear hc' have hmap := fun g ↦ map_finsupp_sum (LinearMap.mulLeft ℤ (e (π C (· ∈ s)) a)) c g @@ -667,7 +667,7 @@ theorem fin_comap_jointlySurjective (spanCone_isLimit hC.isCompact) f exact ⟨(Opposite.unop J), g, h⟩ -/-- The good products span all of `LocallyConstant C ℤ` if `C` is closed. -/ +/-- The good products span all of `LocallyConstant C ℤ` if `C` is closed. -/ theorem GoodProducts.span [IsWellOrder I (· < ·)] (hC : IsClosed C) : ⊤ ≤ Submodule.span ℤ (Set.range (eval C)) := by rw [span_iff_products] @@ -692,14 +692,14 @@ can be regarded as the set of all strictly smaller ordinals, allowing to apply o ### Main definitions -* `ord I i` is the term `i` of `I` regarded as an ordinal. +* `ord I i` is the term `i` of `I` regarded as an ordinal. -* `term I ho` is a sufficiently small ordinal regarded as a term of `I`. +* `term I ho` is a sufficiently small ordinal regarded as a term of `I`. -* `contained C o` is a predicate saying that `C` is "small" enough in relation to the ordinal `o` +* `contained C o` is a predicate saying that `C` is "small" enough in relation to the ordinal `o` to satisfy the inductive hypothesis. -* `P I` is the predicate on ordinals about linear independence of good products, which the rest of +* `P I` is the predicate on ordinals about linear independence of good products, which the rest of this file is spent on proving by induction. -/ @@ -711,7 +711,7 @@ def ord (i : I) : Ordinal := Ordinal.typein ((·<·) : I → I → Prop) i /-- An ordinal regarded as a term of `I`. -/ noncomputable def term {o : Ordinal} (ho : o < Ordinal.type ((·<·) : I → I → Prop)) : I := - Ordinal.enum ((·<·) : I → I → Prop) o ho + Ordinal.enum ((·<·) : I → I → Prop) ⟨o, ho⟩ variable {I} @@ -732,13 +732,13 @@ theorem ord_term {o : Ordinal} (ho : o < Ordinal.type ((·<·) : I → I → Pro · subst h exact ord_term_aux ho -/-- A predicate saying that `C` is "small" enough to satisfy the inductive hypothesis. -/ +/-- A predicate saying that `C` is "small" enough to satisfy the inductive hypothesis. -/ def contained (o : Ordinal) : Prop := ∀ f, f ∈ C → ∀ (i : I), f i = true → ord I i < o variable (I) in /-- The predicate on ordinals which we prove by induction, see `GoodProducts.P0`, -`GoodProducts.Plimit` and `GoodProducts.linearIndependentAux` in the section `Induction` below +`GoodProducts.Plimit` and `GoodProducts.linearIndependentAux` in the section `Induction` below -/ def P (o : Ordinal) : Prop := o ≤ Ordinal.type (·<· : I → I → Prop) → @@ -762,7 +762,7 @@ section Zero ## The zero case of the induction -In this case, we have `contained C 0` which means that `C` is either empty or a singleton. +In this case, we have `contained C 0` which means that `C` is either empty or a singleton. -/ instance : Subsingleton (LocallyConstant (∅ : Set (I → Bool)) ℤ) := @@ -776,7 +776,7 @@ instance : IsEmpty { l // Products.isGood (∅ : Set (I → Bool)) l } := theorem GoodProducts.linearIndependentEmpty {I} [LinearOrder I] : LinearIndependent ℤ (eval (∅ : Set (I → Bool))) := linearIndependent_empty_type -/-- The empty list as a `Products` -/ +/-- The empty list as a `Products` -/ def Products.nil : Products I := ⟨[], by simp only [List.chain'_nil]⟩ theorem Products.lt_nil_empty {I} [LinearOrder I] : { m : Products I | m < Products.nil } = ∅ := by @@ -848,13 +848,13 @@ precomposition with the projections defined in the section `Projections`. ### Main definitions -* `πs` and `πs'` are the `ℤ`-linear maps corresponding to `ProjRestrict` and `ProjRestricts`  +* `πs` and `πs'` are the `ℤ`-linear maps corresponding to `ProjRestrict` and `ProjRestricts` respectively. ### Main result -* We prove that `πs` and `πs'` interact well with `Products.eval` and the main application is the - theorem `isGood_mono` which says that the property `isGood` is "monotone" on ordinals. +* We prove that `πs` and `πs'` interact well with `Products.eval` and the main application is the + theorem `isGood_mono` which says that the property `isGood` is "monotone" on ordinals. -/ theorem contained_eq_proj (o : Ordinal) (h : contained C o) : @@ -963,7 +963,7 @@ section Limit We relate linear independence in `LocallyConstant (π C (ord I · < o')) ℤ` with linear independence in `LocallyConstant C ℤ`, where `contained C o` and `o' < o`. -When `o` is a limit ordinal, we prove that the good products in `LocallyConstant C ℤ` are linearly +When `o` is a limit ordinal, we prove that the good products in `LocallyConstant C ℤ` are linearly independent if and only if a certain directed union is linearly independent. Each term in this directed union is in bijection with the good products w.r.t. `π C (ord I · < o')` for an ordinal `o' < o`, and these are linearly independent by the inductive hypothesis. @@ -972,13 +972,13 @@ directed union is in bijection with the good products w.r.t. `π C (ord I · < o * `GoodProducts.smaller` is the image of good products coming from a smaller ordinal. -* `GoodProducts.range_equiv`: The image of the `GoodProducts` in `C` is equivalent to the union of - `smaller C o'` over all ordinals `o' < o`. +* `GoodProducts.range_equiv`: The image of the `GoodProducts` in `C` is equivalent to the union of + `smaller C o'` over all ordinals `o' < o`. ### Main results * `Products.limitOrdinal`: for `o` a limit ordinal such that `contained C o`, a product `l` is good - w.r.t. `C` iff it there exists an ordinal `o' < o` such that `l` is good w.r.t. + w.r.t. `C` iff it there exists an ordinal `o' < o` such that `l` is good w.r.t. `π C (ord I · < o')`. * `GoodProducts.linearIndependent_iff_union_smaller` is the result mentioned above, that the good @@ -988,8 +988,8 @@ directed union is in bijection with the good products w.r.t. `π C (ord I · < o namespace GoodProducts /-- -The image of the `GoodProducts` for `π C (ord I · < o)` in `LocallyConstant C ℤ`. The name `smaller` -refers to the setting in which we will use this, when we are mapping in `GoodProducts` from a +The image of the `GoodProducts` for `π C (ord I · < o)` in `LocallyConstant C ℤ`. The name `smaller` +refers to the setting in which we will use this, when we are mapping in `GoodProducts` from a smaller set, i.e. when `o` is a smaller ordinal than the one `C` is "contained" in. -/ def smaller (o : Ordinal) : Set (LocallyConstant C ℤ) := @@ -1085,7 +1085,7 @@ theorem GoodProducts.union : range C = ⋃ (e : {o' // o' < o}), (smaller C e.va exact Products.isGood_mono C (le_of_lt h) hl /-- -The image of the `GoodProducts` in `C` is equivalent to the union of `smaller C o'` over all +The image of the `GoodProducts` in `C` is equivalent to the union of `smaller C o'` over all ordinals `o' < o`. -/ def GoodProducts.range_equiv : range C ≃ ⋃ (e : {o' // o' < o}), (smaller C e.val) := @@ -1108,8 +1108,8 @@ section Successor ## The successor case in the induction -Here we assume that `o` is an ordinal such that `contained C (o+1)` and `o < I`. The element in `I` -corresponding to `o` is called `term I ho`, but in this informal docstring we refer to it simply as +Here we assume that `o` is an ordinal such that `contained C (o+1)` and `o < I`. The element in `I` +corresponding to `o` is called `term I ho`, but in this informal docstring we refer to it simply as `o`. This section follows the proof in [scholze2019condensed] quite closely. A translation of the @@ -1140,32 +1140,32 @@ corresponds to the last paragraph in the proof in [scholze2019condensed]. The main definitions in the section `ExactSequence` are all just notation explained in the table above. -The main definitions in the section `GoodProducts` are as follows: +The main definitions in the section `GoodProducts` are as follows: * `MaxProducts`: the set of good products that contain the ordinal `o` (since we have `contained C (o+1)`, these all start with `o`). * `GoodProducts.sum_equiv`: the equivalence between `GoodProducts C` and the disjoint union of - `MaxProducts C` and `GoodProducts (π C (ord I · < o))`. + `MaxProducts C` and `GoodProducts (π C (ord I · < o))`. ### Main results -* The main results in the section `ExactSequence` are `succ_mono` and `succ_exact` which together - say that the secuence given by `πs` and `Linear_CC'` is left exact: +* The main results in the section `ExactSequence` are `succ_mono` and `succ_exact` which together + say that the sequence given by `πs` and `Linear_CC'` is left exact: ``` f g 0 --→ LocallyConstant (π C (ord I · < o)) ℤ --→ LocallyConstant C ℤ --→ LocallyConstant C' ℤ ``` - where `f` is `πs` and `g` is `Linear_CC'`. + where `f` is `πs` and `g` is `Linear_CC'`. -The main results in the section `GoodProducts` are as follows: +The main results in the section `GoodProducts` are as follows: * `Products.max_eq_eval` says that the linear map on the right in the exact sequence, i.e. - `Linear_CC'`, takes the evaluation of a term of `MaxProducts` to the evaluation of the + `Linear_CC'`, takes the evaluation of a term of `MaxProducts` to the evaluation of the corresponding list with the leading `o` removed. -* `GoodProducts.maxTail_isGood` says that removing the leading `o` from a term of `MaxProducts C`  - yields a list which `isGood` with respect to `C'`. +* `GoodProducts.maxTail_isGood` says that removing the leading `o` from a term of `MaxProducts C` + yields a list which `isGood` with respect to `C'`. -/ variable {o : Ordinal} (hC : IsClosed C) (hsC : contained C (Order.succ o)) @@ -1245,7 +1245,7 @@ theorem swapTrue_mem_C1 (f : π (C1 C ho) (ord I · < o)) : contrapose! hsC exact ⟨hsC, Order.succ_le_of_lt (h'.lt_of_ne' h)⟩ -/-- The first way to map `C'` into `C`. -/ +/-- The first way to map `C'` into `C`. -/ def CC'₀ : C' C ho → C := fun g ↦ ⟨g.val,g.prop.1.1⟩ /-- The second way to map `C'` into `C`. -/ @@ -1268,7 +1268,7 @@ noncomputable def Linear_CC'₁ : LocallyConstant C ℤ →ₗ[ℤ] LocallyConstant (C' C ho) ℤ := LocallyConstant.comapₗ ℤ ⟨(CC'₁ C hsC ho), (continuous_CC'₁ C hsC ho)⟩ -/-- The difference between `Linear_CC'₁` and `Linear_CC'₀`. -/ +/-- The difference between `Linear_CC'₁` and `Linear_CC'₀`. -/ noncomputable def Linear_CC' : LocallyConstant C ℤ →ₗ[ℤ] LocallyConstant (C' C ho) ℤ := Linear_CC'₁ C hsC ho - Linear_CC'₀ C ho @@ -1424,7 +1424,8 @@ theorem sum_to_range : /-- The equivalence from the sum of `GoodProducts (π C (ord I · < o))` and `(MaxProducts C ho)` to `GoodProducts C`. -/ noncomputable -def sum_equiv : GoodProducts (π C (ord I · < o)) ⊕ (MaxProducts C ho) ≃ GoodProducts C := +def sum_equiv (hsC : contained C (Order.succ o)) (ho : o < Ordinal.type (·<· : I → I → Prop)) : + GoodProducts (π C (ord I · < o)) ⊕ (MaxProducts C ho) ≃ GoodProducts C := calc _ ≃ Set.range (sum_to C ho) := Equiv.ofInjective (sum_to C ho) (injective_sum_to C ho) _ ≃ _ := Equiv.Set.ofEq <| by rw [sum_to_range C ho, union_succ C hsC ho] @@ -1449,7 +1450,7 @@ theorem sum_equiv_comp_eval_eq_elim : eval C ∘ (sum_equiv C hsC ho).toFun = Then `SumEval C ho` is the map `u` in the diagram below. It is linearly independent if and only if `GoodProducts.eval C` is, see `linearIndependent_iff_sum`. The top row is the exact sequence given -by `succ_exact` and `succ_mono`. The left square commutes by `GoodProducts.square_commutes`. +by `succ_exact` and `succ_mono`. The left square commutes by `GoodProducts.square_commutes`. ``` 0 --→ N --→ M --→ P ↑ ↑ ↑ @@ -1608,20 +1609,20 @@ theorem good_lt_maxProducts (q : GoodProducts (π C (ord I · < o))) include hC hsC in /-- -Removing the leading `o` from a term of `MaxProducts C` yields a list which `isGood` with respect to +Removing the leading `o` from a term of `MaxProducts C` yields a list which `isGood` with respect to `C'`. -/ theorem maxTail_isGood (l : MaxProducts C ho) (h₁ : ⊤ ≤ Submodule.span ℤ (Set.range (eval (π C (ord I · < o))))) : l.val.Tail.isGood (C' C ho) := by have : Inhabited I := ⟨term I ho⟩ - -- Write `l.Tail` as a linear combination of smaller products: + -- Write `l.Tail` as a linear combination of smaller products: intro h - rw [Finsupp.mem_span_image_iff_total, ← max_eq_eval C hsC ho] at h + rw [Finsupp.mem_span_image_iff_linearCombination, ← max_eq_eval C hsC ho] at h obtain ⟨m, ⟨hmmem, hmsum⟩⟩ := h - rw [Finsupp.total_apply] at hmsum + rw [Finsupp.linearCombination_apply] at hmsum - -- Write the image of `l` under `Linear_CC'` as `Linear_CC'` applied to the linear combination + -- Write the image of `l` under `Linear_CC'` as `Linear_CC'` applied to the linear combination -- above, with leading `term I ho`'s added to each term: have : (Linear_CC' C hsC ho) (l.val.eval C) = (Linear_CC' C hsC ho) (Finsupp.sum m fun i a ↦ a • ((term I ho :: i.1).map (e C)).prod) := by @@ -1645,7 +1646,7 @@ theorem maxTail_isGood (l : MaxProducts C ho) rw [ShortComplex.moduleCat_exact_iff_range_eq_ker] at hse dsimp [ModuleCat.ofHom] at hse - -- Rewrite `this` using exact sequence manipulations to conclude that a term is in the range of + -- Rewrite `this` using exact sequence manipulations to conclude that a term is in the range of -- the linear map `πs`: rw [← LinearMap.sub_mem_ker_iff, ← hse] at this obtain ⟨(n : LocallyConstant (π C (ord I · < o)) ℤ), hn⟩ := this @@ -1721,16 +1722,16 @@ section Induction ## The induction -Here we put together the results of the sections `Zero`, `Limit` and `Successor` to prove the -predicate `P I o` holds for all ordinals `o`, and conclude with the main result: +Here we put together the results of the sections `Zero`, `Limit` and `Successor` to prove the +predicate `P I o` holds for all ordinals `o`, and conclude with the main result: -* `GoodProducts.linearIndependent` which says that `GoodProducts C` is linearly independent when `C` +* `GoodProducts.linearIndependent` which says that `GoodProducts C` is linearly independent when `C` is closed. We also define -* `GoodProducts.Basis` which uses `GoodProducts.linearIndependent` and `GoodProducts.span` to - define a basis for `LocallyConstant C ℤ`  +* `GoodProducts.Basis` which uses `GoodProducts.linearIndependent` and `GoodProducts.span` to + define a basis for `LocallyConstant C ℤ` -/ theorem GoodProducts.P0 : P I 0 := fun _ C _ hsC ↦ by @@ -1770,7 +1771,7 @@ theorem GoodProducts.linearIndependent (hC : IsClosed C) : GoodProducts.linearIndependentAux (Ordinal.type (·<· : I → I → Prop)) (le_refl _) C hC (fun _ _ _ _ ↦ Ordinal.typein_lt_type _ _) -/-- `GoodProducts C` as a `ℤ`-basis for `LocallyConstant C ℤ`. -/ +/-- `GoodProducts C` as a `ℤ`-basis for `LocallyConstant C ℤ`. -/ noncomputable def GoodProducts.Basis (hC : IsClosed C) : Basis (GoodProducts C) ℤ (LocallyConstant C ℤ) := @@ -1782,7 +1783,7 @@ variable {S : Profinite} {ι : S → I → Bool} (hι : ClosedEmbedding ι) include hι /-- -Given a profinite set `S` and a closed embedding `S → (I → Bool)`, the `ℤ`-module +Given a profinite set `S` and a closed embedding `S → (I → Bool)`, the `ℤ`-module `LocallyConstant C ℤ` is free. -/ theorem Nobeling_aux : Module.Free ℤ (LocallyConstant S ℤ) := Module.Free.of_equiv' @@ -1799,7 +1800,7 @@ noncomputable def Nobeling.ι : S → ({C : Set S // IsClopen C} → Bool) := fun s C => decide (s ∈ C.1) open scoped Classical in -/-- The map `Nobeling.ι` is a closed embedding. -/ +/-- The map `Nobeling.ι` is a closed embedding. -/ theorem Nobeling.embedding : ClosedEmbedding (Nobeling.ι S) := by apply Continuous.closedEmbedding · dsimp (config := { unfoldPartialApp := true }) [ι] @@ -1829,9 +1830,11 @@ end Profinite open Profinite NobelingProof -/-- Nöbeling's theorem: the `ℤ`-module `LocallyConstant S ℤ` is free for every `S : Profinite` -/ +/-- Nöbeling's theorem: the `ℤ`-module `LocallyConstant S ℤ` is free for every `S : Profinite` -/ instance LocallyConstant.freeOfProfinite (S : Profinite.{u}) : Module.Free ℤ (LocallyConstant S ℤ) := @Nobeling_aux {C : Set S // IsClopen C} (IsWellOrder.linearOrder WellOrderingRel) WellOrderingRel.isWellOrder S (Nobeling.ι S) (Nobeling.embedding S) + +set_option linter.style.longFile 2000 diff --git a/Mathlib/Topology/Category/Profinite/Product.lean b/Mathlib/Topology/Category/Profinite/Product.lean index f79df72c64680..0224264e33b98 100644 --- a/Mathlib/Topology/Category/Profinite/Product.lean +++ b/Mathlib/Topology/Category/Profinite/Product.lean @@ -13,7 +13,7 @@ Hausdorff spaces as a cofiltered limit in `Profinite` indexed by `Finset ι`. ## Main definitions -- `Profinite.indexFunctor` is the functor `(Finset ι)ᵒᵖ ⥤ Profinite` indexing the limit. It maps +- `Profinite.indexFunctor` is the functor `(Finset ι)ᵒᵖ ⥤ Profinite` indexing the limit. It maps `J` to the restriction of `C` to `J` - `Profinite.indexCone` is a cone on `Profinite.indexFunctor` with cone point `C` @@ -78,23 +78,24 @@ end IndexFunctor variable [∀ i, T2Space (X i)] [∀ i, TotallyDisconnectedSpace (X i)] variable {C} -variable (hC : IsCompact C) open CategoryTheory Limits Opposite IndexFunctor /-- The functor from the poset of finsets of `ι` to `Profinite`, indexing the limit. -/ noncomputable -def indexFunctor : (Finset ι)ᵒᵖ ⥤ Profinite.{u} where +def indexFunctor (hC : IsCompact C) : (Finset ι)ᵒᵖ ⥤ Profinite.{u} where obj J := @Profinite.of (obj C (· ∈ (unop J))) _ (by rw [← isCompact_iff_compactSpace]; exact hC.image (Pi.continuous_precomp' _)) _ _ map h := map C (leOfHom h.unop) /-- The limit cone on `indexFunctor` -/ noncomputable -def indexCone : Cone (indexFunctor hC) where +def indexCone (hC : IsCompact C) : Cone (indexFunctor hC) where pt := @Profinite.of C _ (by rwa [← isCompact_iff_compactSpace]) _ _ π := { app := fun J ↦ π_app C (· ∈ unop J) } +variable (hC : IsCompact C) + instance isIso_indexCone_lift : IsIso ((limitConeIsLimit.{u, u} (indexFunctor hC)).lift (indexCone hC)) := haveI : CompactSpace C := by rwa [← isCompact_iff_compactSpace] diff --git a/Mathlib/Topology/Category/Sequential.lean b/Mathlib/Topology/Category/Sequential.lean index e7eccce4aeaf3..65e73b4a4fcb7 100644 --- a/Mathlib/Topology/Category/Sequential.lean +++ b/Mathlib/Topology/Category/Sequential.lean @@ -11,7 +11,7 @@ import Mathlib.Topology.Category.TopCat.Basic # The category of sequential topological spaces -We define the category `Sequential` of sequential topological spaces. We follow the ususal template +We define the category `Sequential` of sequential topological spaces. We follow the usual template for defining categories of topological spaces, by giving it the induced category structure from `TopCat`. -/ diff --git a/Mathlib/Topology/Category/Stonean/Adjunctions.lean b/Mathlib/Topology/Category/Stonean/Adjunctions.lean index d20e34fdfc9fb..dd99b65695aed 100644 --- a/Mathlib/Topology/Category/Stonean/Adjunctions.lean +++ b/Mathlib/Topology/Category/Stonean/Adjunctions.lean @@ -12,7 +12,7 @@ import Mathlib.Topology.StoneCech This file constructs the left adjoint `typeToStonean` to the forgetful functor from Stonean spaces to sets, using the Stone-Cech compactification. This allows to conclude that the monomorphisms in -`Stonean` are precisely the injective maps (see `Stonean.mono_iff_injective`). +`Stonean` are precisely the injective maps (see `Stonean.mono_iff_injective`). -/ universe u diff --git a/Mathlib/Topology/Category/Stonean/Basic.lean b/Mathlib/Topology/Category/Stonean/Basic.lean index 41c7eeabe0cde..47e784b8b878e 100644 --- a/Mathlib/Topology/Category/Stonean/Basic.lean +++ b/Mathlib/Topology/Category/Stonean/Basic.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2023 Adam Topaz. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Adam Topaz +Authors: Adam Topaz, Dagur Asgeirsson -/ import Mathlib.Topology.ExtremallyDisconnected import Mathlib.Topology.Category.CompHaus.Projective @@ -31,6 +31,11 @@ can be lifted along epimorphisms). spaces to compact Hausdorff spaces * `Stonean.toProfinite` : the functor from Stonean spaces to profinite spaces. +## Implementation + +The category `Stonean` is defined using the structure `CompHausLike`. See the file +`CompHausLike.Basic` for more information. + -/ universe u @@ -83,7 +88,7 @@ abbrev fullyFaithfulToCompHaus : toCompHaus.FullyFaithful := open CompHausLike -instance (X : Type*) [TopologicalSpace X] +instance (X : Type*) [TopologicalSpace X] [ExtremallyDisconnected X] : HasProp (fun Y ↦ ExtremallyDisconnected Y) X := ⟨(inferInstance : ExtremallyDisconnected X)⟩ @@ -116,7 +121,7 @@ def mkFinite (X : Type*) [Finite X] [TopologicalSpace X] [DiscreteTopology X] : apply isOpen_discrete (closure U) /-- -A morphism in `Stonean` is an epi iff it is surjective. +A morphism in `Stonean` is an epi iff it is surjective. -/ lemma epi_iff_surjective {X Y : Stonean} (f : X ⟶ Y) : Epi f ↔ Function.Surjective f := by @@ -186,7 +191,7 @@ end Stonean namespace CompHaus /-- If `X` is compact Hausdorff, `presentation X` is a Stonean space equipped with an epimorphism - down to `X` (see `CompHaus.presentation.π` and `CompHaus.presentation.epi_π`). It is a + down to `X` (see `CompHaus.presentation.π` and `CompHaus.presentation.epi_π`). It is a "constructive" witness to the fact that `CompHaus` has enough projectives. -/ noncomputable def presentation (X : CompHaus) : Stonean where @@ -253,7 +258,7 @@ end CompHaus namespace Profinite /-- If `X` is profinite, `presentation X` is a Stonean space equipped with an epimorphism down to - `X` (see `Profinite.presentation.π` and `Profinite.presentation.epi_π`). -/ + `X` (see `Profinite.presentation.π` and `Profinite.presentation.epi_π`). -/ noncomputable def presentation (X : Profinite) : Stonean where toTop := (profiniteToCompHaus.obj X).projectivePresentation.p.toTop diff --git a/Mathlib/Topology/Category/Stonean/EffectiveEpi.lean b/Mathlib/Topology/Category/Stonean/EffectiveEpi.lean index 6f0dcd7b65055..ff4d234dae338 100644 --- a/Mathlib/Topology/Category/Stonean/EffectiveEpi.lean +++ b/Mathlib/Topology/Category/Stonean/EffectiveEpi.lean @@ -55,7 +55,7 @@ instance : Stonean.toCompHaus.ReflectsEffectiveEpis where (((CompHaus.effectiveEpi_tfae (Stonean.toCompHaus.map f)).out 0 2).mp h) /-- -An effective presentation of an `X : CompHaus` with respect to the inclusion functor from `Stonean` +An effective presentation of an `X : CompHaus` with respect to the inclusion functor from `Stonean` -/ noncomputable def stoneanToCompHausEffectivePresentation (X : CompHaus) : Stonean.toCompHaus.EffectivePresentation X where diff --git a/Mathlib/Topology/Category/TopCat/EffectiveEpi.lean b/Mathlib/Topology/Category/TopCat/EffectiveEpi.lean index 841f550bb606f..5510c9abcf4ae 100644 --- a/Mathlib/Topology/Category/TopCat/EffectiveEpi.lean +++ b/Mathlib/Topology/Category/TopCat/EffectiveEpi.lean @@ -11,7 +11,7 @@ import Mathlib.Topology.Category.TopCat.Limits.Pullbacks # Effective epimorphisms in `TopCat` This file proves the result `TopCat.effectiveEpi_iff_quotientMap`: -The effective epimorphisms in `TopCat` are precisely the quotient maps. +The effective epimorphisms in `TopCat` are precisely the quotient maps. -/ @@ -37,7 +37,7 @@ def effectiveEpiStructOfQuotientMap {B X : TopCat.{u}} (π : X ⟶ B) (hπ : Quo fac e h := (hπ.lift_comp e fun a b hab ↦ DFunLike.congr_fun (h ⟨fun _ ↦ a, continuous_const⟩ ⟨fun _ ↦ b, continuous_const⟩ (by ext; exact hab)) a) - /- Uniqueness follows from the fact that `QuotientMap.lift` is an equivalence (given by + /- Uniqueness follows from the fact that `QuotientMap.lift` is an equivalence (given by `QuotientMap.liftEquiv`). -/ uniq e h g hm := by suffices g = hπ.liftEquiv ⟨e, @@ -49,12 +49,12 @@ def effectiveEpiStructOfQuotientMap {B X : TopCat.{u}} (π : X ⟶ B) (hπ : Quo simp only [QuotientMap.liftEquiv_symm_apply_coe, ContinuousMap.comp_apply, ← hm] rfl -/-- The effective epimorphisms in `TopCat` are precisely the quotient maps. -/ +/-- The effective epimorphisms in `TopCat` are precisely the quotient maps. -/ theorem effectiveEpi_iff_quotientMap {B X : TopCat.{u}} (π : X ⟶ B) : EffectiveEpi π ↔ QuotientMap π := by /- The backward direction is given by `effectiveEpiStructOfQuotientMap` above. -/ refine ⟨fun _ ↦ ?_, fun hπ ↦ ⟨⟨effectiveEpiStructOfQuotientMap π hπ⟩⟩⟩ - /- Since `TopCat` has pullbacks, `π` is in fact a `RegularEpi`. This means that it exhibits `B` as + /- Since `TopCat` has pullbacks, `π` is in fact a `RegularEpi`. This means that it exhibits `B` as a coequalizer of two maps into `X`. It suffices to prove that `π` followed by the isomorphism to an arbitrary coequalizer is a quotient map. -/ have hπ : RegularEpi π := inferInstance @@ -63,7 +63,7 @@ theorem effectiveEpi_iff_quotientMap {B X : TopCat.{u}} (π : X ⟶ B) : suffices QuotientMap (homeoOfIso i ∘ π) by simpa [← Function.comp.assoc] using (homeoOfIso i).symm.quotientMap.comp this constructor - /- Effective epimorphisms are epimorphisms and epimorphisms in `TopCat` are surjective. -/ + /- Effective epimorphisms are epimorphisms and epimorphisms in `TopCat` are surjective. -/ · change Function.Surjective (π ≫ i.hom) rw [← epi_iff_surjective] infer_instance diff --git a/Mathlib/Topology/Category/TopCat/Limits/Products.lean b/Mathlib/Topology/Category/TopCat/Limits/Products.lean index 43cd610adcbfb..20ee2f8395a8d 100644 --- a/Mathlib/Topology/Category/TopCat/Limits/Products.lean +++ b/Mathlib/Topology/Category/TopCat/Limits/Products.lean @@ -58,7 +58,7 @@ equipped with the product topology. -/ def piIsoPi {ι : Type v} (α : ι → TopCat.{max v u}) : ∏ᶜ α ≅ TopCat.of (∀ i, α i) := (limit.isLimit _).conePointUniqueUpToIso (piFanIsLimit.{v, u} α) - -- Specifying the universes in `piFanIsLimit` wasn't necessary when we had `TopCatMax`  + -- Specifying the universes in `piFanIsLimit` wasn't necessary when we had `TopCatMax` @[reassoc (attr := simp)] theorem piIsoPi_inv_π {ι : Type v} (α : ι → TopCat.{max v u}) (i : ι) : @@ -106,7 +106,7 @@ def sigmaCofanIsColimit {ι : Type v} (β : ι → TopCat.{max v u}) : IsColimit -/ def sigmaIsoSigma {ι : Type v} (α : ι → TopCat.{max v u}) : ∐ α ≅ TopCat.of (Σi, α i) := (colimit.isColimit _).coconePointUniqueUpToIso (sigmaCofanIsColimit.{v, u} α) - -- Specifying the universes in `sigmaCofanIsColimit` wasn't necessary when we had `TopCatMax`  + -- Specifying the universes in `sigmaCofanIsColimit` wasn't necessary when we had `TopCatMax` @[reassoc (attr := simp)] theorem sigmaIsoSigma_hom_ι {ι : Type v} (α : ι → TopCat.{max v u}) (i : ι) : diff --git a/Mathlib/Topology/Category/TopCat/OpenNhds.lean b/Mathlib/Topology/Category/TopCat/OpenNhds.lean index c5465486c0688..a5c79d6b932bf 100644 --- a/Mathlib/Topology/Category/TopCat/OpenNhds.lean +++ b/Mathlib/Topology/Category/TopCat/OpenNhds.lean @@ -10,12 +10,12 @@ import Mathlib.Data.Set.Subsingleton # The category of open neighborhoods of a point Given an object `X` of the category `TopCat` of topological spaces and a point `x : X`, this file -builds the type `OpenNhds x` of open neighborhoods of `x` in `X` and endows it with the partial +builds the type `OpenNhds x` of open neighborhoods of `x` in `X` and endows it with the partial order given by inclusion and the corresponding category structure (as a full subcategory of the poset category `Set X`). This is used in `Topology.Sheaves.Stalks` to build the stalk of a sheaf at `x` as a limit over `OpenNhds x`. -## Main declarations +## Main declarations Besides `OpenNhds`, the main constructions here are: diff --git a/Mathlib/Topology/Category/TopCat/Yoneda.lean b/Mathlib/Topology/Category/TopCat/Yoneda.lean index 4875f93370077..65ed0d1e00d83 100644 --- a/Mathlib/Topology/Category/TopCat/Yoneda.lean +++ b/Mathlib/Topology/Category/TopCat/Yoneda.lean @@ -57,7 +57,7 @@ theorem piComparison_fac {α : Type} (X : α → TopCat) : Equiv.coe_fn_symm_mk, comp_assoc, sigmaMk_apply, ← opCoproductIsoProduct_inv_comp_ι] rfl -/-- The universe polymorphic Yoneda presheaf on `TopCat` preserves finite products. -/ +/-- The universe polymorphic Yoneda presheaf on `TopCat` preserves finite products. -/ noncomputable instance : PreservesFiniteProducts (yonedaPresheaf'.{w, w'} Y) where preserves J _ := { preservesLimit := fun {K} => diff --git a/Mathlib/Topology/CompactOpen.lean b/Mathlib/Topology/CompactOpen.lean index 24a3372bc22ad..5f931fa17bc5c 100644 --- a/Mathlib/Topology/CompactOpen.lean +++ b/Mathlib/Topology/CompactOpen.lean @@ -277,7 +277,7 @@ theorem tendsto_compactOpen_iff_forall {ι : Type*} {l : Filter ι} (F : ι → Tendsto F l (𝓝 f) ↔ ∀ K, IsCompact K → Tendsto (fun i => (F i).restrict K) l (𝓝 (f.restrict K)) := by rw [compactOpen_eq_iInf_induced] - simp [nhds_iInf, nhds_induced, Filter.tendsto_comap_iff, Function.comp] + simp [nhds_iInf, nhds_induced, Filter.tendsto_comap_iff, Function.comp_def] /-- A family `F` of functions in `C(X, Y)` converges in the compact-open topology, if and only if it converges in the compact-open topology on each compact subset of `X`. -/ diff --git a/Mathlib/Topology/Compactness/CompactlyGeneratedSpace.lean b/Mathlib/Topology/Compactness/CompactlyGeneratedSpace.lean index ebc17cc09ad5a..fbcd4585a405a 100644 --- a/Mathlib/Topology/Compactness/CompactlyGeneratedSpace.lean +++ b/Mathlib/Topology/Compactness/CompactlyGeneratedSpace.lean @@ -54,7 +54,7 @@ The compactly generated topology on a topological space `X`. This is the finest which makes all maps from compact Hausdorff spaces to `X`, which are continuous for the original topology, continuous. -Note: this definition should be used with an explicit universe parameter `u` for the size of the +Note: this definition should be used with an explicit universe parameter `u` for the size of the compact Hausdorff spaces mapping to `X`. -/ def TopologicalSpace.compactlyGenerated (X : Type w) [TopologicalSpace X] : TopologicalSpace X := diff --git a/Mathlib/Topology/Compactness/Lindelof.lean b/Mathlib/Topology/Compactness/Lindelof.lean index 03b75fea6f233..6cbd814c5efbe 100644 --- a/Mathlib/Topology/Compactness/Lindelof.lean +++ b/Mathlib/Topology/Compactness/Lindelof.lean @@ -511,7 +511,7 @@ theorem IsClosed.isLindelof [LindelofSpace X] (h : IsClosed s) : IsLindelof s := theorem IsCompact.isLindelof (hs : IsCompact s) : IsLindelof s := by tauto -/-- A σ-compact set `s` is Lindelöf-/ +/-- A σ-compact set `s` is Lindelöf -/ theorem IsSigmaCompact.isLindelof (hs : IsSigmaCompact s) : IsLindelof s := by rw [IsSigmaCompact] at hs @@ -564,7 +564,7 @@ theorem Filter.coLindelof_neBot_iff : NeBot (Filter.coLindelof X) ↔ NonLindelo theorem not_LindelofSpace_iff : ¬LindelofSpace X ↔ NonLindelofSpace X := ⟨fun h₁ => ⟨fun h₂ => h₁ ⟨h₂⟩⟩, fun ⟨h₁⟩ ⟨h₂⟩ => h₁ h₂⟩ -/-- A compact space `X` is Lindelöf. -/ +/-- A compact space `X` is Lindelöf. -/ instance (priority := 100) [CompactSpace X] : LindelofSpace X := { isLindelof_univ := isCompact_univ.isLindelof} @@ -594,7 +594,7 @@ theorem Filter.comap_coLindelof_le {f : X → Y} (hf : Continuous f) : simpa using t.subset_preimage_image f theorem isLindelof_range [LindelofSpace X] {f : X → Y} (hf : Continuous f) : - IsLindelof (range f) := by rw [← image_univ]; exact isLindelof_univ.image hf + IsLindelof (range f) := by rw [← image_univ]; exact isLindelof_univ.image hf theorem isLindelof_diagonal [LindelofSpace X] : IsLindelof (diagonal X) := @range_diag X ▸ isLindelof_range (continuous_id.prod_mk continuous_id) @@ -692,7 +692,7 @@ for open sets in the definition, and then conclude that this holds for all sets def IsHereditarilyLindelof (s : Set X) := ∀ t ⊆ s, IsLindelof t -/-- Type class for Hereditarily Lindelöf spaces. -/ +/-- Type class for Hereditarily Lindelöf spaces. -/ class HereditarilyLindelofSpace (X : Type*) [TopologicalSpace X] : Prop where /-- In a Hereditarily Lindelöf space, `Set.univ` is a Hereditarily Lindelöf set. -/ isHereditarilyLindelof_univ : IsHereditarilyLindelof (univ : Set X) diff --git a/Mathlib/Topology/Connected/PathConnected.lean b/Mathlib/Topology/Connected/PathConnected.lean index 07fea44bddd1e..1cad1a9499c1e 100644 --- a/Mathlib/Topology/Connected/PathConnected.lean +++ b/Mathlib/Topology/Connected/PathConnected.lean @@ -33,7 +33,7 @@ Then there are corresponding relative notions for `F : Set X`. * `LocPathConnectedSpace X` is a predicate class asserting that `X` is locally path-connected: each point has a basis of path-connected neighborhoods (we do *not* ask these to be open). -## Main theorems +## Main theorems * `Joined` and `JoinedIn F` are transitive relations. @@ -247,7 +247,6 @@ theorem extend_zero : γ.extend 0 = x := by simp theorem extend_one : γ.extend 1 = y := by simp -@[simp] theorem extend_extends' {a b : X} (γ : Path a b) (t : (Icc 0 1 : Set ℝ)) : γ.extend t = γ t := IccExtend_val _ γ t diff --git a/Mathlib/Topology/Connected/Separation.lean b/Mathlib/Topology/Connected/Separation.lean index 57db6948dc729..8ce21856914c0 100644 --- a/Mathlib/Topology/Connected/Separation.lean +++ b/Mathlib/Topology/Connected/Separation.lean @@ -11,7 +11,7 @@ import Mathlib.Topology.Separation This file provides an instance `T2Space X` given `TotallySeparatedSpace X`. ## TODO -* Move the last part of `Topology/Separation` to this file. +* Move the last part of `Topology/Separation` to this file. -/ diff --git a/Mathlib/Topology/Constructions.lean b/Mathlib/Topology/Constructions.lean index 51eb2dee9f145..5888993492e49 100644 --- a/Mathlib/Topology/Constructions.lean +++ b/Mathlib/Topology/Constructions.lean @@ -600,7 +600,7 @@ theorem prod_generateFrom_generateFrom_eq {X Y : Type*} {s : Set (Set X)} {t : S (hs : ⋃₀ s = univ) (ht : ⋃₀ t = univ) : @instTopologicalSpaceProd X Y (generateFrom s) (generateFrom t) = generateFrom (image2 (· ×ˢ ·) s t) := - let G := generateFrom (image2 (· ×ˢ ·) s t) + let G := generateFrom (image2 (· ×ˢ ·) s t) le_antisymm (le_generateFrom fun g ⟨u, hu, v, hv, g_eq⟩ => g_eq.symm ▸ @@ -713,6 +713,12 @@ theorem isOpen_prod_iff' {s : Set X} {t : Set Y} : simp only [st.1.ne_empty, st.2.ne_empty, not_false_iff, or_false_iff] at H exact H.1.prod H.2 +theorem quotientMap_fst [Nonempty Y] : QuotientMap (Prod.fst : X × Y → X) := + isOpenMap_fst.to_quotientMap continuous_fst Prod.fst_surjective + +theorem quotientMap_snd [Nonempty X] : QuotientMap (Prod.snd : X × Y → Y) := + isOpenMap_snd.to_quotientMap continuous_snd Prod.snd_surjective + theorem closure_prod_eq {s : Set X} {t : Set Y} : closure (s ×ˢ t) = closure s ×ˢ closure t := ext fun ⟨a, b⟩ => by simp_rw [mem_prod, mem_closure_iff_nhdsWithin_neBot, nhdsWithin_prod_eq, prod_neBot] @@ -763,12 +769,12 @@ theorem Inducing.prod_map {f : X → Y} {g : Z → W} (hf : Inducing f) (hg : In @[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, + simp_rw [inducing_iff, instTopologicalSpaceProd, induced_inf, induced_compose, Function.comp_def, induced_const, top_inf_eq] @[simp] theorem inducing_prod_const {y : Y} {f : X → Z} : (Inducing fun x => (f x, y)) ↔ Inducing f := by - simp_rw [inducing_iff, instTopologicalSpaceProd, induced_inf, induced_compose, Function.comp, + 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) : @@ -841,6 +847,10 @@ theorem continuous_inl : Continuous (@inl X Y) := ⟨fun _ => And.left⟩ -- Porting note: the proof was `continuous_sup_rng_right continuous_coinduced_rng` theorem continuous_inr : Continuous (@inr X Y) := ⟨fun _ => And.right⟩ +@[fun_prop, continuity] +lemma continuous_sum_swap : Continuous (@Sum.swap X Y) := + Continuous.sum_elim continuous_inr continuous_inl + theorem isOpen_sum_iff {s : Set (X ⊕ Y)} : IsOpen s ↔ IsOpen (inl ⁻¹' s) ∧ IsOpen (inr ⁻¹' s) := Iff.rfl @@ -905,7 +915,11 @@ theorem Continuous.sum_map {f : X → Y} {g : Z → W} (hf : Continuous f) (hg : theorem isOpenMap_sum {f : X ⊕ Y → Z} : IsOpenMap f ↔ (IsOpenMap fun a => f (inl a)) ∧ IsOpenMap fun b => f (inr b) := by - simp only [isOpenMap_iff_nhds_le, Sum.forall, nhds_inl, nhds_inr, Filter.map_map, comp] + simp only [isOpenMap_iff_nhds_le, Sum.forall, nhds_inl, nhds_inr, Filter.map_map, comp_def] + +theorem IsOpenMap.sumMap {f : X → Y} {g : Z → W} (hf : IsOpenMap f) (hg : IsOpenMap g) : + IsOpenMap (Sum.map f g) := by + exact isOpenMap_sum.2 ⟨isOpenMap_inl.comp hf,isOpenMap_inr.comp hg⟩ @[simp] theorem isOpenMap_sum_elim {f : X → Z} {g : Y → Z} : @@ -1053,7 +1067,7 @@ theorem embedding_inclusion {s t : Set X} (h : s ⊆ t) : Embedding (inclusion h embedding_subtype_val.codRestrict _ _ /-- Let `s, t ⊆ X` be two subsets of a topological space `X`. If `t ⊆ s` and the topology induced -by `X`on `s` is discrete, then also the topology induces on `t` is discrete. -/ +by `X`on `s` is discrete, then also the topology induces on `t` is discrete. -/ theorem DiscreteTopology.of_subset {X : Type*} [TopologicalSpace X] {s t : Set X} (_ : DiscreteTopology s) (ts : t ⊆ s) : DiscreteTopology t := (embedding_inclusion ts).discreteTopology @@ -1129,7 +1143,7 @@ variable {ι : Type*} {π : ι → Type*} {κ : Type*} [TopologicalSpace X] [T : ∀ i, TopologicalSpace (π i)] {f : X → ∀ i : ι, π i} theorem continuous_pi_iff : Continuous f ↔ ∀ i, Continuous fun a => f a i := by - simp only [continuous_iInf_rng, continuous_induced_rng, comp] + simp only [continuous_iInf_rng, continuous_induced_rng, comp_def] @[continuity, fun_prop] theorem continuous_pi (h : ∀ i, Continuous fun a => f a i) : Continuous f := @@ -1187,7 +1201,7 @@ theorem Pi.continuous_postcomp [TopologicalSpace Y] {g : X → Y} (hg : Continuo lemma Pi.induced_precomp' {ι' : Type*} (φ : ι' → ι) : induced (fun (f : (∀ i, π i)) (j : ι') ↦ f (φ j)) Pi.topologicalSpace = ⨅ i', induced (eval (φ i')) (T (φ i')) := by - simp [Pi.topologicalSpace, induced_iInf, induced_compose, comp] + simp [Pi.topologicalSpace, induced_iInf, induced_compose, comp_def] lemma Pi.induced_precomp [TopologicalSpace Y] {ι' : Type*} (φ : ι' → ι) : induced (· ∘ φ) Pi.topologicalSpace = @@ -1372,7 +1386,7 @@ theorem pi_generateFrom_eq_finite {π : ι → Type*} {g : ∀ a, Set (Set (π a theorem induced_to_pi {X : Type*} (f : X → ∀ i, π i) : induced f Pi.topologicalSpace = ⨅ i, induced (f · i) inferInstance := by - simp_rw [Pi.topologicalSpace, induced_iInf, induced_compose, Function.comp] + simp_rw [Pi.topologicalSpace, induced_iInf, induced_compose, Function.comp_def] /-- Suppose `π i` is a family of topological spaces indexed by `i : ι`, and `X` is a type endowed with a family of maps `f i : X → π i` for every `i : ι`, hence inducing a @@ -1494,7 +1508,7 @@ theorem inducing_sigma {f : Sigma σ → X} : @[simp 1100] theorem continuous_sigma_map {f₁ : ι → κ} {f₂ : ∀ i, σ i → τ (f₁ i)} : Continuous (Sigma.map f₁ f₂) ↔ ∀ i, Continuous (f₂ i) := - continuous_sigma_iff.trans <| by simp only [Sigma.map, embedding_sigmaMk.continuous_iff, comp] + continuous_sigma_iff.trans <| by simp only [Sigma.map, embedding_sigmaMk.continuous_iff, comp_def] @[continuity, fun_prop] theorem Continuous.sigma_map {f₁ : ι → κ} {f₂ : ∀ i, σ i → τ (f₁ i)} (hf : ∀ i, Continuous (f₂ i)) : @@ -1502,7 +1516,7 @@ theorem Continuous.sigma_map {f₁ : ι → κ} {f₂ : ∀ i, σ i → τ (f₁ continuous_sigma_map.2 hf theorem isOpenMap_sigma {f : Sigma σ → X} : IsOpenMap f ↔ ∀ i, IsOpenMap fun a => f ⟨i, a⟩ := by - simp only [isOpenMap_iff_nhds_le, Sigma.forall, Sigma.nhds_eq, map_map, comp] + simp only [isOpenMap_iff_nhds_le, Sigma.forall, Sigma.nhds_eq, map_map, comp_def] theorem isOpenMap_sigma_map {f₁ : ι → κ} {f₂ : ∀ i, σ i → τ (f₁ i)} : IsOpenMap (Sigma.map f₁ f₂) ↔ ∀ i, IsOpenMap (f₂ i) := @@ -1594,3 +1608,5 @@ theorem Filter.Eventually.prod_nhdsSet {p : X × Y → Prop} {px : X → Prop} { nhdsSet_prod_le _ _ (mem_of_superset (prod_mem_prod hs ht) fun _ ⟨hx, hy⟩ ↦ hp hx hy) end NhdsSet + +set_option linter.style.longFile 1700 diff --git a/Mathlib/Topology/ContinuousFunction/Basic.lean b/Mathlib/Topology/ContinuousFunction/Basic.lean index b24e4f2ee999c..e77f01dabfc8e 100644 --- a/Mathlib/Topology/ContinuousFunction/Basic.lean +++ b/Mathlib/Topology/ContinuousFunction/Basic.lean @@ -68,7 +68,7 @@ instance : CoeTC F C(α, β) := ⟨toContinuousMap⟩ end ContinuousMapClass -/-! ### Continuous maps-/ +/-! ### Continuous maps -/ namespace ContinuousMap @@ -304,7 +304,7 @@ def sigma (f : ∀ i, C(X i, A)) : C((Σ i, X i), A) where variable (A X) in /-- Giving a continuous map out of a disjoint union is the same as giving a continuous map out of -each term. This is a version of `Equiv.piCurry` for continuous maps. +each term. This is a version of `Equiv.piCurry` for continuous maps. -/ @[simps] def sigmaEquiv : (∀ i, C(X i, A)) ≃ C((Σ i, X i), A) where @@ -494,7 +494,7 @@ noncomputable def lift : C(Y, Z) where continuous_toFun := Continuous.comp (continuous_quot_lift _ g.2) (Homeomorph.continuous _) /-- -The obvious triangle induced by `QuotientMap.lift` commutes: +The obvious triangle induced by `QuotientMap.lift` commutes: ``` g X --→ Z diff --git a/Mathlib/Topology/ContinuousFunction/Bounded.lean b/Mathlib/Topology/ContinuousFunction/Bounded.lean index 80e9caca4ffa6..3c61e9ba6a02d 100644 --- a/Mathlib/Topology/ContinuousFunction/Bounded.lean +++ b/Mathlib/Topology/ContinuousFunction/Bounded.lean @@ -1513,3 +1513,5 @@ lemma norm_sub_nonneg (f : α →ᵇ ℝ) : end end BoundedContinuousFunction + +set_option linter.style.longFile 1700 diff --git a/Mathlib/Topology/ContinuousFunction/Compact.lean b/Mathlib/Topology/ContinuousFunction/Compact.lean index 77c4cda47593d..114876977a04d 100644 --- a/Mathlib/Topology/ContinuousFunction/Compact.lean +++ b/Mathlib/Topology/ContinuousFunction/Compact.lean @@ -135,9 +135,6 @@ theorem dist_lt_iff (C0 : (0 : ℝ) < C) : dist f g < C ↔ ∀ x : α, dist (f end -instance [CompleteSpace β] : CompleteSpace C(α, β) := - (isometryEquivBoundedOfCompact α β).completeSpace - -- TODO at some point we will need lemmas characterising this norm! -- At the moment the only way to reason about it is to transfer `f : C(α,E)` back to `α →ᵇ E`. instance : Norm C(α, E) where norm x := dist x 0 @@ -205,6 +202,11 @@ theorem neg_norm_le_apply (f : C(α, ℝ)) (x : α) : -‖f‖ ≤ f x := theorem norm_eq_iSup_norm : ‖f‖ = ⨆ x : α, ‖f x‖ := (mkOfCompact f).norm_eq_iSup_norm +-- A version with better keys +instance {X : Type*} [TopologicalSpace X] (K : TopologicalSpace.Compacts X) : + CompactSpace (K : Set X) := + TopologicalSpace.Compacts.instCompactSpaceSubtypeMem .. + theorem norm_restrict_mono_set {X : Type*} [TopologicalSpace X] (f : C(X, E)) {K L : TopologicalSpace.Compacts X} (hKL : K ≤ L) : ‖f.restrict K‖ ≤ ‖f.restrict L‖ := (norm_le _ (norm_nonneg _)).mpr fun x => norm_coe_le_norm (f.restrict L) <| Set.inclusion hKL x diff --git a/Mathlib/Topology/ContinuousFunction/Ordered.lean b/Mathlib/Topology/ContinuousFunction/Ordered.lean index 0b4780410756f..7e46c520e70b6 100644 --- a/Mathlib/Topology/ContinuousFunction/Ordered.lean +++ b/Mathlib/Topology/ContinuousFunction/Ordered.lean @@ -85,7 +85,7 @@ section Extend variable [LinearOrder α] [OrderTopology α] {a b : α} (h : a ≤ b) -/-- Extend a continuous function `f : C(Set.Icc a b, β)` to a function `f : C(α, β)`. -/ +/-- Extend a continuous function `f : C(Set.Icc a b, β)` to a function `f : C(α, β)`. -/ def IccExtend (f : C(Set.Icc a b, β)) : C(α, β) where toFun := Set.IccExtend h f diff --git a/Mathlib/Topology/ContinuousFunction/Sigma.lean b/Mathlib/Topology/ContinuousFunction/Sigma.lean index c5bdc0f0b7351..a444781b712f5 100644 --- a/Mathlib/Topology/ContinuousFunction/Sigma.lean +++ b/Mathlib/Topology/ContinuousFunction/Sigma.lean @@ -25,7 +25,7 @@ because it is easier to use an equivalence in applications. ## TODO Some results in this file can be generalized to the case when `X` is a preconnected space. However, -if `X` is empty, then any index `i` will work, so there is no 1-to-1 corespondence. +if `X` is empty, then any index `i` will work, so there is no 1-to-1 correspondence. ## Keywords diff --git a/Mathlib/Topology/ContinuousFunction/ZeroAtInfty.lean b/Mathlib/Topology/ContinuousFunction/ZeroAtInfty.lean index 579bbebe2285c..932426106e17d 100644 --- a/Mathlib/Topology/ContinuousFunction/ZeroAtInfty.lean +++ b/Mathlib/Topology/ContinuousFunction/ZeroAtInfty.lean @@ -16,7 +16,7 @@ compact space, this type has nice properties. ## TODO -* Create more intances of algebraic structures (e.g., `NonUnitalSemiring`) once the necessary +* Create more instances of algebraic structures (e.g., `NonUnitalSemiring`) once the necessary type classes (e.g., `TopologicalRing`) are sufficiently generalized. * Relate the unitization of `C₀(α, β)` to the Alexandroff compactification. -/ diff --git a/Mathlib/Topology/ContinuousOn.lean b/Mathlib/Topology/ContinuousOn.lean index cc5cc3ae5b508..e94fe66abd47a 100644 --- a/Mathlib/Topology/ContinuousOn.lean +++ b/Mathlib/Topology/ContinuousOn.lean @@ -1138,7 +1138,8 @@ theorem IsOpen.ite' {s s' t : Set α} (hs : IsOpen s) (hs' : IsOpen s') (ht : ∀ x ∈ frontier t, x ∈ s ↔ x ∈ s') : IsOpen (t.ite s s') := by classical simp only [isOpen_iff_continuous_mem, Set.ite] at * - convert continuous_piecewise (fun x hx => propext (ht x hx)) hs.continuousOn hs'.continuousOn + convert + continuous_piecewise (fun x hx => propext (ht x hx)) hs.continuousOn hs'.continuousOn using 2 rename_i x by_cases hx : x ∈ t <;> simp [hx] diff --git a/Mathlib/Topology/DenseEmbedding.lean b/Mathlib/Topology/DenseEmbedding.lean index 7957b2b180fe4..f346261d50bed 100644 --- a/Mathlib/Topology/DenseEmbedding.lean +++ b/Mathlib/Topology/DenseEmbedding.lean @@ -253,7 +253,7 @@ protected theorem subtype (de : DenseEmbedding e) (p : α → Prop) : induced := (induced_iff_nhds_eq _).2 fun ⟨x, hx⟩ => by 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 diff --git a/Mathlib/Topology/DiscreteQuotient.lean b/Mathlib/Topology/DiscreteQuotient.lean index 6c041809ef504..a6413350f7c54 100644 --- a/Mathlib/Topology/DiscreteQuotient.lean +++ b/Mathlib/Topology/DiscreteQuotient.lean @@ -348,7 +348,7 @@ open Classical in If `X` is a compact space, then we associate to any discrete quotient on `X` a finite set of clopen subsets of `X`, given by the fibers of `proj`. -TODO: prove that these form a partition of `X`  +TODO: prove that these form a partition of `X` -/ noncomputable def finsetClopens [CompactSpace X] (d : DiscreteQuotient X) : Finset (Clopens X) := have : Fintype d := Fintype.ofFinite _ @@ -368,7 +368,7 @@ lemma comp_finsetClopens [CompactSpace X] : simpa [← h] using Quotient.mk_eq_iff_out (s := d.toSetoid) · exact fun ⟨y, h⟩ ↦ ⟨d.proj y, by ext; simp [h, proj]⟩ -/-- `finsetClopens X` is injective. -/ +/-- `finsetClopens X` is injective. -/ theorem finsetClopens_inj [CompactSpace X] : (finsetClopens X).Injective := by apply Function.Injective.of_comp (f := Set.image (fun (t : Clopens X) ↦ t.carrier) ∘ Finset.toSet) diff --git a/Mathlib/Topology/DiscreteSubset.lean b/Mathlib/Topology/DiscreteSubset.lean index 4122752067f57..5238fbf4e8e1e 100644 --- a/Mathlib/Topology/DiscreteSubset.lean +++ b/Mathlib/Topology/DiscreteSubset.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2023 Oliver Nash. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Oliver Nash, Bhavik Mehta +Authors: Oliver Nash, Bhavik Mehta, Daniel Weber -/ import Mathlib.Topology.Constructions import Mathlib.Topology.Separation @@ -30,8 +30,9 @@ see `IsClosed.tendsto_coe_cofinite_iff`. ## Co-discrete open sets -In a topological space the sets which are open with discrete complement form a filter. We -formalise this as `Filter.codiscrete`. +We define the filter `Filter.codiscreteWithin S`, which is the supremum of all `𝓝[S \ {x}] x`. +This is the filter of all open codiscrete sets within S. We also define `Filter.codiscrete` as +`Filter.codiscreteWithin univ`, which is the filter of all open codiscrete sets in the space. -/ @@ -95,17 +96,53 @@ theorem isClosed_and_discrete_iff {S : Set X} : · refine ⟨fun hx ↦ ?_, fun _ ↦ H⟩ simpa [disjoint_iff, nhdsWithin, inf_assoc, hx] using H -/-- In any topological space, the open sets with with discrete complement form a filter. -/ -def Filter.codiscrete (X : Type*) [TopologicalSpace X] : Filter X where - sets := {U | IsOpen U ∧ DiscreteTopology ↑Uᶜ} - univ_sets := ⟨isOpen_univ, compl_univ.symm ▸ Subsingleton.discreteTopology⟩ - sets_of_superset := by - intro U V hU hV - simp_rw [← isClosed_compl_iff, isClosed_and_discrete_iff] at hU ⊢ - exact fun x ↦ (hU x).mono_right (principal_mono.mpr <| compl_subset_compl.mpr hV) - inter_sets := by - intro U V hU hV - simp_rw [← isClosed_compl_iff, isClosed_and_discrete_iff] at hU hV ⊢ - exact fun x ↦ compl_inter U V ▸ sup_principal ▸ disjoint_sup_right.mpr ⟨hU x, hV x⟩ +/-- The filter of sets with no accumulation points inside a set `S : Set X`, implemented +as the supremum over all punctured neighborhoods within `S`. -/ +def Filter.codiscreteWithin (S : Set X) : Filter X := ⨆ x ∈ S, 𝓝[S \ {x}] x + +lemma mem_codiscreteWithin {S T : Set X} : + S ∈ codiscreteWithin T ↔ ∀ x ∈ T, Disjoint (𝓝[≠] x) (𝓟 (T \ S)) := by + simp only [codiscreteWithin, mem_iSup, mem_nhdsWithin, disjoint_principal_right, subset_def, + mem_diff, mem_inter_iff, mem_compl_iff] + congr! 7 with x - u y + tauto + +lemma mem_codiscreteWithin_accPt {S T : Set X} : + S ∈ codiscreteWithin T ↔ ∀ x ∈ T, ¬AccPt x (𝓟 (T \ S)) := by + simp only [mem_codiscreteWithin, disjoint_iff, AccPt, not_neBot] + +/-- In any topological space, the open sets with discrete complement form a filter, +defined as the supremum of all punctured neighborhoods. + +See `Filter.mem_codiscrete'` for the equivalence. -/ +def Filter.codiscrete (X : Type*) [TopologicalSpace X] : Filter X := codiscreteWithin Set.univ + +lemma mem_codiscrete {S : Set X} : + S ∈ codiscrete X ↔ ∀ x, Disjoint (𝓝[≠] x) (𝓟 Sᶜ) := by + simp [codiscrete, mem_codiscreteWithin, compl_eq_univ_diff] + +lemma mem_codiscrete_accPt {S : Set X} : + S ∈ codiscrete X ↔ ∀ x, ¬AccPt x (𝓟 Sᶜ) := by + simp only [mem_codiscrete, disjoint_iff, AccPt, not_neBot] + +lemma mem_codiscrete' {S : Set X} : + S ∈ codiscrete X ↔ IsOpen S ∧ DiscreteTopology ↑Sᶜ := by + rw [mem_codiscrete, ← isClosed_compl_iff, isClosed_and_discrete_iff] + +lemma mem_codiscrete_subtype_iff_mem_codiscreteWithin {S : Set X} {U : Set S} : + U ∈ codiscrete S ↔ (↑) '' U ∈ codiscreteWithin S := by + simp [mem_codiscrete, disjoint_principal_right, compl_compl, Subtype.forall, + mem_codiscreteWithin] + congr! with x hx + constructor + · rw [nhdsWithin_subtype, mem_comap] + rintro ⟨t, ht1, ht2⟩ + rw [mem_nhdsWithin] at ht1 ⊢ + obtain ⟨u, hu1, hu2, hu3⟩ := ht1 + refine ⟨u, hu1, hu2, fun v hv ↦ ?_⟩ + simpa using fun hv2 ↦ ⟨hv2, ht2 <| hu3 <| by simpa [hv2]⟩ + · suffices Tendsto (↑) (𝓝[≠] (⟨x, hx⟩ : S)) (𝓝[≠] x) by convert tendsto_def.mp this _; ext; simp + exact tendsto_nhdsWithin_of_tendsto_nhds_of_eventually_within _ + continuous_subtype_val.continuousWithinAt <| eventually_mem_nhdsWithin.mono (by simp) end codiscrete_filter diff --git a/Mathlib/Topology/EMetricSpace/Basic.lean b/Mathlib/Topology/EMetricSpace/Basic.lean index 79a2678c491d7..cf23aef640373 100644 --- a/Mathlib/Topology/EMetricSpace/Basic.lean +++ b/Mathlib/Topology/EMetricSpace/Basic.lean @@ -230,7 +230,7 @@ section Compact -- Porting note (#11215): TODO: generalize to metrizable spaces /-- A compact set in a pseudo emetric space is separable, i.e., it is a subset of the closure of a -countable set. -/ +countable set. -/ theorem subset_countable_closure_of_compact {s : Set α} (hs : IsCompact s) : ∃ t, t ⊆ s ∧ t.Countable ∧ s ⊆ closure t := by refine subset_countable_closure_of_almost_dense_set s fun ε hε => ?_ diff --git a/Mathlib/Topology/EMetricSpace/Defs.lean b/Mathlib/Topology/EMetricSpace/Defs.lean index aed2614cb3ad5..2d530cb9ad131 100644 --- a/Mathlib/Topology/EMetricSpace/Defs.lean +++ b/Mathlib/Topology/EMetricSpace/Defs.lean @@ -248,8 +248,9 @@ a uniformity which is equal to the original one, but maybe not defeq. This is useful if one wants to construct a pseudoemetric space with a specified uniformity. See Note [forgetful inheritance] explaining why having definitionally the right uniformity is often important. +See note [reducible non-instances]. -/ -def PseudoEMetricSpace.replaceUniformity {α} [U : UniformSpace α] (m : PseudoEMetricSpace α) +abbrev PseudoEMetricSpace.replaceUniformity {α} [U : UniformSpace α] (m : PseudoEMetricSpace α) (H : 𝓤[U] = 𝓤[PseudoEMetricSpace.toUniformSpace]) : PseudoEMetricSpace α where edist := @edist _ m.toEDist edist_self := edist_self @@ -258,8 +259,9 @@ def PseudoEMetricSpace.replaceUniformity {α} [U : UniformSpace α] (m : PseudoE toUniformSpace := U uniformity_edist := H.trans (@PseudoEMetricSpace.uniformity_edist α _) -/-- The extended pseudometric induced by a function taking values in a pseudoemetric space. -/ -def PseudoEMetricSpace.induced {α β} (f : α → β) (m : PseudoEMetricSpace β) : +/-- The extended pseudometric induced by a function taking values in a pseudoemetric space. +See note [reducible non-instances]. -/ +abbrev PseudoEMetricSpace.induced {α β} (f : α → β) (m : PseudoEMetricSpace β) : PseudoEMetricSpace α where edist x y := edist (f x) (f y) edist_self _ := edist_self _ @@ -593,8 +595,9 @@ a uniformity which is equal to the original one, but maybe not defeq. This is useful if one wants to construct an emetric space with a specified uniformity. See Note [forgetful inheritance] explaining why having definitionally the right uniformity is often important. +See note [reducible non-instances]. -/ -def EMetricSpace.replaceUniformity {γ} [U : UniformSpace γ] (m : EMetricSpace γ) +abbrev EMetricSpace.replaceUniformity {γ} [U : UniformSpace γ] (m : EMetricSpace γ) (H : 𝓤[U] = 𝓤[PseudoEMetricSpace.toUniformSpace]) : EMetricSpace γ where edist := @edist _ m.toEDist edist_self := edist_self @@ -604,8 +607,9 @@ def EMetricSpace.replaceUniformity {γ} [U : UniformSpace γ] (m : EMetricSpace toUniformSpace := U uniformity_edist := H.trans (@PseudoEMetricSpace.uniformity_edist γ _) -/-- The extended metric induced by an injective function taking values in an emetric space. -/ -def EMetricSpace.induced {γ β} (f : γ → β) (hf : Function.Injective f) (m : EMetricSpace β) : +/-- The extended metric induced by an injective function taking values in an emetric space. +See Note [reducible non-instances]. -/ +abbrev EMetricSpace.induced {γ β} (f : γ → β) (hf : Function.Injective f) (m : EMetricSpace β) : EMetricSpace γ := { PseudoEMetricSpace.induced f m.toPseudoEMetricSpace with eq_of_edist_eq_zero := fun h => hf (edist_eq_zero.1 h) } diff --git a/Mathlib/Topology/EMetricSpace/Lipschitz.lean b/Mathlib/Topology/EMetricSpace/Lipschitz.lean index 4240b7841e469..dc80b6180d219 100644 --- a/Mathlib/Topology/EMetricSpace/Lipschitz.lean +++ b/Mathlib/Topology/EMetricSpace/Lipschitz.lean @@ -59,11 +59,11 @@ def LipschitzOnWith (K : ℝ≥0) (f : α → β) (s : Set α) := ∀ ⦃x⦄, x ∈ s → ∀ ⦃y⦄, y ∈ s → edist (f x) (f y) ≤ K * edist x y /-- `f : α → β` is called **locally Lipschitz continuous** iff every point `x` -has a neighourhood on which `f` is Lipschitz. -/ +has a neighbourhood on which `f` is Lipschitz. -/ def LocallyLipschitz (f : α → β) : Prop := ∀ x, ∃ K, ∃ t ∈ 𝓝 x, LipschitzOnWith K f t /-- `f : α → β` is called **locally Lipschitz continuous** on `s` iff every point `x` of `s` -has a neighourhood within `s` on which `f` is Lipschitz. -/ +has a neighbourhood within `s` on which `f` is Lipschitz. -/ def LocallyLipschitzOn (s : Set α) (f : α → β) : Prop := ∀ ⦃x⦄, x ∈ s → ∃ K, ∃ t ∈ 𝓝[s] x, LipschitzOnWith K f t @@ -89,6 +89,9 @@ lemma LocallyLipschitzOn.mono (hf : LocallyLipschitzOn t f) (h : s ⊆ t) : Loca @[simp] lemma locallyLipschitzOn_univ : LocallyLipschitzOn univ f ↔ LocallyLipschitz f := by simp [LocallyLipschitzOn, LocallyLipschitz] +protected lemma LocallyLipschitz.locallyLipschitzOn (h : LocallyLipschitz f) : + LocallyLipschitzOn s f := (locallyLipschitzOn_univ.2 h).mono s.subset_univ + theorem lipschitzOnWith_iff_restrict : LipschitzOnWith K f s ↔ LipschitzWith K (s.restrict f) := by simp only [LipschitzOnWith, LipschitzWith, SetCoe.forall', restrict, Subtype.edist_eq] @@ -125,9 +128,9 @@ namespace LipschitzWith open EMetric variable [PseudoEMetricSpace α] [PseudoEMetricSpace β] [PseudoEMetricSpace γ] -variable {K : ℝ≥0} {f : α → β} {x y : α} {r : ℝ≥0∞} +variable {K : ℝ≥0} {f : α → β} {x y : α} {r : ℝ≥0∞} {s : Set α} -protected theorem lipschitzOnWith (h : LipschitzWith K f) (s : Set α) : LipschitzOnWith K f s := +protected theorem lipschitzOnWith (h : LipschitzWith K f) : LipschitzOnWith K f s := fun x _ y _ => h x y theorem edist_le_mul (h : LipschitzWith K f) (x y : α) : edist (f x) (f y) ≤ K * edist x y := @@ -149,7 +152,7 @@ theorem mapsTo_emetric_ball (h : LipschitzWith K f) (hK : K ≠ 0) (x : α) (r : theorem edist_lt_top (hf : LipschitzWith K f) {x y : α} (h : edist x y ≠ ⊤) : edist (f x) (f y) < ⊤ := - (hf x y).trans_lt <| ENNReal.mul_lt_top ENNReal.coe_ne_top h + (hf x y).trans_lt <| ENNReal.mul_lt_top ENNReal.coe_lt_top h.lt_top theorem mul_edist_le (h : LipschitzWith K f) (x y : α) : (K⁻¹ : ℝ≥0∞) * edist (f x) (f y) ≤ edist x y := by diff --git a/Mathlib/Topology/FiberBundle/Basic.lean b/Mathlib/Topology/FiberBundle/Basic.lean index 4606e9604e100..bb2f8386ba3a3 100644 --- a/Mathlib/Topology/FiberBundle/Basic.lean +++ b/Mathlib/Topology/FiberBundle/Basic.lean @@ -674,7 +674,7 @@ instance fiberBundle : FiberBundle F Z.Fiber where totalSpaceMk_inducing' b := inducing_iff_nhds.2 fun x ↦ by rw [(Z.localTrivAt b).nhds_eq_comap_inf_principal (mk_mem_localTrivAt_source _ _ _), comap_inf, comap_principal, comap_comap] - simp only [(· ∘ ·), localTrivAt_apply_mk, Trivialization.coe_coe, + simp only [Function.comp_def, localTrivAt_apply_mk, Trivialization.coe_coe, ← (embedding_prod_mk b).nhds_eq_comap] convert_to 𝓝 x = 𝓝 x ⊓ 𝓟 univ · congr diff --git a/Mathlib/Topology/FiberBundle/Constructions.lean b/Mathlib/Topology/FiberBundle/Constructions.lean index 01fe742ebee19..222d8ca96b186 100644 --- a/Mathlib/Topology/FiberBundle/Constructions.lean +++ b/Mathlib/Topology/FiberBundle/Constructions.lean @@ -292,7 +292,7 @@ variable [TopologicalSpace F] [TopologicalSpace B] theorem Pullback.continuous_totalSpaceMk [∀ x, TopologicalSpace (E x)] [FiberBundle F E] {f : B' → B} {x : B'} : Continuous (@TotalSpace.mk _ F (f *ᵖ E) x) := by simp only [continuous_iff_le_induced, Pullback.TotalSpace.topologicalSpace, induced_compose, - induced_inf, Function.comp, induced_const, top_inf_eq, pullbackTopology_def] + induced_inf, Function.comp_def, induced_const, top_inf_eq, pullbackTopology_def] exact le_of_eq (FiberBundle.totalSpaceMk_inducing F E (f x)).induced variable {E F} @@ -330,7 +330,7 @@ noncomputable def Trivialization.pullback (e : Trivialization F (π F E)) (f : K e.continuousOn.comp (Pullback.continuous_lift F E f).continuousOn Subset.rfl) continuousOn_invFun := by dsimp only - simp_rw [(inducing_pullbackTotalSpaceEmbedding F E f).continuousOn_iff, Function.comp, + simp_rw [(inducing_pullbackTotalSpaceEmbedding F E f).continuousOn_iff, Function.comp_def, pullbackTotalSpaceEmbedding] refine continuousOn_fst.prod diff --git a/Mathlib/Topology/FiberBundle/Trivialization.lean b/Mathlib/Topology/FiberBundle/Trivialization.lean index d5a5d504ff3af..72f78dd20048f 100644 --- a/Mathlib/Topology/FiberBundle/Trivialization.lean +++ b/Mathlib/Topology/FiberBundle/Trivialization.lean @@ -74,7 +74,7 @@ variable (e : Pretrivialization F proj) {x : Z} /-- Coercion of a pretrivialization to a function. We don't use `e.toFun` in the `CoeFun` instance because it is actually `e.toPartialEquiv.toFun`, so `simp` will apply lemmas about `toPartialEquiv`. While we may want to switch to this behavior later, doing it mid-port will break a -lot of proofs. -/ +lot of proofs. -/ @[coe] def toFun' : Z → (B × F) := e.toFun instance : CoeFun (Pretrivialization F proj) fun _ => Z → B × F := ⟨toFun'⟩ @@ -282,7 +282,7 @@ lemma ext' (e e' : Trivialization F proj) (h₁ : e.toPartialHomeomorph = e'.toP /-- Coercion of a trivialization to a function. We don't use `e.toFun` in the `CoeFun` instance because it is actually `e.toPartialEquiv.toFun`, so `simp` will apply lemmas about `toPartialEquiv`. While we may want to switch to this behavior later, doing it mid-port will break a -lot of proofs. -/ +lot of proofs. -/ @[coe] def toFun' : Z → (B × F) := e.toFun /-- Natural identification as a `Pretrivialization`. -/ @@ -418,7 +418,7 @@ theorem preimageHomeomorph_apply {s : Set B} (hb : s ⊆ e.baseSet) (p : proj e.preimageHomeomorph hb p = (⟨proj p, p.2⟩, (e p).2) := Prod.ext (Subtype.ext (e.proj_toFun p (e.mem_source.mpr (hb p.2)))) rfl -/-- Auxilliary definition to avoid looping in `dsimp` +/-- Auxiliary definition to avoid looping in `dsimp` with `Trivialization.preimageHomeomorph_symm_apply`. -/ protected def preimageHomeomorph_symm_apply.aux {s : Set B} (hb : s ⊆ e.baseSet) := (e.preimageHomeomorph hb).symm @@ -438,7 +438,7 @@ theorem sourceHomeomorphBaseSetProd_apply (p : e.source) : e.sourceHomeomorphBaseSetProd p = (⟨proj p, e.mem_source.mp p.2⟩, (e p).2) := e.preimageHomeomorph_apply subset_rfl ⟨p, e.mem_source.mp p.2⟩ -/-- Auxilliary definition to avoid looping in `dsimp` +/-- Auxiliary definition to avoid looping in `dsimp` with `Trivialization.sourceHomeomorphBaseSetProd_symm_apply`. -/ protected def sourceHomeomorphBaseSetProd_symm_apply.aux := e.sourceHomeomorphBaseSetProd.symm @@ -465,7 +465,7 @@ theorem preimageSingletonHomeomorph_symm_apply {b : B} (hb : b ∈ e.baseSet) (p ⟨e.symm (b, p), by rw [mem_preimage, e.proj_symm_apply' hb, mem_singleton_iff]⟩ := rfl -/-- In the domain of a bundle trivialization, the projection is continuous-/ +/-- In the domain of a bundle trivialization, the projection is continuous -/ theorem continuousAt_proj (ex : x ∈ e.source) : ContinuousAt proj x := (e.map_proj_nhds ex).le @@ -475,7 +475,7 @@ protected def compHomeomorph {Z' : Type*} [TopologicalSpace Z'] (h : Z' ≃ₜ Z toPartialHomeomorph := h.toPartialHomeomorph.trans e.toPartialHomeomorph baseSet := e.baseSet open_baseSet := e.open_baseSet - source_eq := by simp [source_eq, preimage_preimage, (· ∘ ·)] + source_eq := by simp [source_eq, preimage_preimage, Function.comp_def] target_eq := by simp [target_eq] proj_toFun p hp := by have hp : h p ∈ e.source := by simpa using hp diff --git a/Mathlib/Topology/Filter.lean b/Mathlib/Topology/Filter.lean index abaddb408699f..17a22a272b238 100644 --- a/Mathlib/Topology/Filter.lean +++ b/Mathlib/Topology/Filter.lean @@ -71,7 +71,7 @@ theorem nhds_eq (l : Filter α) : 𝓝 l = l.lift' (Iic ∘ 𝓟) := (· ∘ ·), mem_Iic, le_principal_iff] theorem nhds_eq' (l : Filter α) : 𝓝 l = l.lift' fun s => { l' | s ∈ l' } := by - simpa only [(· ∘ ·), Iic_principal] using nhds_eq l + simpa only [Function.comp_def, Iic_principal] using nhds_eq l protected theorem tendsto_nhds {la : Filter α} {lb : Filter β} {f : α → Filter β} : Tendsto f la (𝓝 lb) ↔ ∀ s ∈ lb, ∀ᶠ a in la, s ∈ f a := by @@ -105,7 +105,7 @@ theorem mem_nhds_iff' {l : Filter α} {S : Set (Filter α)} : @[simp] theorem nhds_bot : 𝓝 (⊥ : Filter α) = pure ⊥ := by - simp [nhds_eq, (· ∘ ·), lift'_bot monotone_principal.Iic] + simp [nhds_eq, Function.comp_def, lift'_bot monotone_principal.Iic] @[simp] theorem nhds_top : 𝓝 (⊤ : Filter α) = ⊤ := by simp [nhds_eq] @@ -131,8 +131,8 @@ theorem monotone_nhds : Monotone (𝓝 : Filter α → Filter (Filter α)) := Monotone.of_map_inf nhds_inf theorem sInter_nhds (l : Filter α) : ⋂₀ { s | s ∈ 𝓝 l } = Iic l := by - simp_rw [nhds_eq, (· ∘ ·), sInter_lift'_sets monotone_principal.Iic, Iic, le_principal_iff, - ← setOf_forall, ← Filter.le_def] + simp_rw [nhds_eq, Function.comp_def, sInter_lift'_sets monotone_principal.Iic, Iic, + le_principal_iff, ← setOf_forall, ← Filter.le_def] @[simp] theorem nhds_mono {l₁ l₂ : Filter α} : 𝓝 l₁ ≤ 𝓝 l₂ ↔ l₁ ≤ l₂ := by diff --git a/Mathlib/Topology/Gluing.lean b/Mathlib/Topology/Gluing.lean index 701ab09498e3c..49d3d693afe04 100644 --- a/Mathlib/Topology/Gluing.lean +++ b/Mathlib/Topology/Gluing.lean @@ -153,7 +153,7 @@ theorem eqvGen_of_π_eq -- Porting note: was `{x y : ∐ D.U} (h : 𝖣.π x = 𝖣.π y)` {x y : sigmaObj (β := D.toGlueData.J) (C := TopCat) D.toGlueData.U} (h : 𝖣.π x = 𝖣.π y) : - EqvGen + Relation.EqvGen -- Porting note: was (Types.CoequalizerRel 𝖣.diagram.fstSigmaMap 𝖣.diagram.sndSigmaMap) (Types.CoequalizerRel (X := sigmaObj (β := D.toGlueData.diagram.L) (C := TopCat) (D.toGlueData.diagram).left) @@ -200,7 +200,7 @@ theorem ι_eq_iff_rel (i j : D.J) (x : D.U i) (y : D.U j) : show _ = Sigma.mk j y from ConcreteCategory.congr_hom (sigmaIsoSigma.{_, u} D.U).inv_hom_id _] change InvImage D.Rel (sigmaIsoSigma.{_, u} D.U).hom _ _ rw [← (InvImage.equivalence _ _ D.rel_equiv).eqvGen_iff] - refine EqvGen.mono ?_ (D.eqvGen_of_π_eq h : _) + refine Relation.EqvGen.mono ?_ (D.eqvGen_of_π_eq h : _) rintro _ _ ⟨x⟩ obtain ⟨⟨⟨i, j⟩, y⟩, rfl⟩ := (ConcreteCategory.bijective_of_isIso (sigmaIsoSigma.{u, u} _).inv).2 x diff --git a/Mathlib/Topology/Homeomorph.lean b/Mathlib/Topology/Homeomorph.lean index 0e17099d1db0a..4d4ec2c0e46ee 100644 --- a/Mathlib/Topology/Homeomorph.lean +++ b/Mathlib/Topology/Homeomorph.lean @@ -27,11 +27,11 @@ directions continuous. We denote homeomorphisms with the notation `≃ₜ`. -/ -open Set Filter +open Set Filter Function open Topology -variable {X : Type*} {Y : Type*} {Z : Type*} +variable {X Y W Z : Type*} -- not all spaces are homeomorphic to each other /-- Homeomorphism between `X` and `Y`, also called topological isomorphism -/ @@ -47,7 +47,7 @@ infixl:25 " ≃ₜ " => Homeomorph namespace Homeomorph -variable [TopologicalSpace X] [TopologicalSpace Y] [TopologicalSpace Z] +variable [TopologicalSpace X] [TopologicalSpace Y] [TopologicalSpace W] [TopologicalSpace Z] {X' Y' : Type*} [TopologicalSpace X'] [TopologicalSpace Y'] theorem toEquiv_injective : Function.Injective (toEquiv : X ≃ₜ Y → X ≃ Y) @@ -404,6 +404,7 @@ theorem locallyCompactSpace_iff (h : X ≃ₜ Y) : fun _ => h.closedEmbedding.locallyCompactSpace⟩ /-- If a bijective map `e : X ≃ Y` is continuous and open, then it is a homeomorphism. -/ +@[simps toEquiv] def homeomorphOfContinuousOpen (e : X ≃ Y) (h₁ : Continuous e) (h₂ : IsOpenMap e) : X ≃ₜ Y where continuous_toFun := h₁ continuous_invFun := by @@ -413,6 +414,14 @@ def homeomorphOfContinuousOpen (e : X ≃ Y) (h₁ : Continuous e) (h₂ : IsOpe apply e.image_eq_preimage toEquiv := e +@[simp] +theorem homeomorphOfContinuousOpen_apply (e : X ≃ Y) (h₁ : Continuous e) (h₂ : IsOpenMap e) : + ⇑(homeomorphOfContinuousOpen e h₁ h₂) = e := rfl + +@[simp] +theorem homeomorphOfContinuousOpen_symm_apply (e : X ≃ Y) (h₁ : Continuous e) (h₂ : IsOpenMap e) : + ⇑(homeomorphOfContinuousOpen e h₁ h₂).symm = e.symm := rfl + @[simp] theorem comp_continuousOn_iff (h : X ≃ₜ Y) (f : Z → X) (s : Set Z) : ContinuousOn (h ∘ f) s ↔ ContinuousOn f s := @@ -499,9 +508,81 @@ theorem prodCongr_symm (h₁ : X ≃ₜ X') (h₂ : Y ≃ₜ Y') : theorem coe_prodCongr (h₁ : X ≃ₜ X') (h₂ : Y ≃ₜ Y') : ⇑(h₁.prodCongr h₂) = Prod.map h₁ h₂ := rfl -section +-- Commutativity and associativity of the disjoint union of topological spaces, +-- and the sum with an empty space. +section sum + +variable (X Y W Z) + +/-- `X ⊕ Y` is homeomorphic to `Y ⊕ X`. -/ +def sumComm : X ⊕ Y ≃ₜ Y ⊕ X where + toEquiv := Equiv.sumComm X Y + continuous_toFun := continuous_sum_swap + continuous_invFun := continuous_sum_swap + +@[simp] +theorem sumComm_symm : (sumComm X Y).symm = sumComm Y X := + rfl + +@[simp] +theorem coe_sumComm : ⇑(sumComm X Y) = Sum.swap := + rfl + +@[continuity, fun_prop] +lemma continuous_sumAssoc : Continuous (Equiv.sumAssoc X Y Z) := + Continuous.sum_elim (by fun_prop) (by fun_prop) + +@[continuity, fun_prop] +lemma continuous_sumAssoc_symm : Continuous (Equiv.sumAssoc X Y Z).symm := + Continuous.sum_elim (by fun_prop) (by fun_prop) + +/-- `(X ⊕ Y) ⊕ Z` is homeomorphic to `X ⊕ (Y ⊕ Z)`. -/ +def sumAssoc : (X ⊕ Y) ⊕ Z ≃ₜ X ⊕ Y ⊕ Z where + toEquiv := Equiv.sumAssoc X Y Z + continuous_toFun := continuous_sumAssoc X Y Z + continuous_invFun := continuous_sumAssoc_symm X Y Z + +@[simp] +lemma sumAssoc_toEquiv : (sumAssoc X Y Z).toEquiv = Equiv.sumAssoc X Y Z := rfl + +/-- Four-way commutativity of the disjoint union. The name matches `add_add_add_comm`. -/ +def sumSumSumComm : (X ⊕ Y) ⊕ W ⊕ Z ≃ₜ (X ⊕ W) ⊕ Y ⊕ Z where + toEquiv := Equiv.sumSumSumComm X Y W Z + continuous_toFun := by + unfold Equiv.sumSumSumComm + dsimp only + have : Continuous (Sum.map (Sum.map (@id X) ⇑(Equiv.sumComm Y W)) (@id Z)) := by continuity + fun_prop + continuous_invFun := by + unfold Equiv.sumSumSumComm + dsimp only + have : Continuous (Sum.map (Sum.map (@id X) (Equiv.sumComm Y W).symm) (@id Z)) := by continuity + fun_prop -variable (X Y Z) +@[simp] +lemma sumSumSumComm_toEquiv : (sumSumSumComm X Y W Z).toEquiv = (Equiv.sumSumSumComm X Y W Z) := rfl + +@[simp] +lemma sumSumSumComm_symm : (sumSumSumComm X Y W Z).symm = (sumSumSumComm X W Y Z) := rfl + +/-- The sum of `X` with any empty topological space is homeomorphic to `X`. -/ +@[simps! (config := .asFn) apply] +def sumEmpty [IsEmpty Y] : X ⊕ Y ≃ₜ X where + toEquiv := Equiv.sumEmpty X Y + continuous_toFun := Continuous.sum_elim continuous_id (by fun_prop) + continuous_invFun := continuous_inl + +/-- The sum of `X` with any empty topological space is homeomorphic to `X`. -/ +def emptySum [IsEmpty Y] : Y ⊕ X ≃ₜ X := (sumComm Y X).trans (sumEmpty X Y) + +@[simp] theorem coe_emptySum [IsEmpty Y] : (emptySum X Y).toEquiv = Equiv.emptySum Y X := rfl + +end sum + +-- Commutativity and associativity of the product of top. spaces, and the product with `PUnit`. +section prod + +variable (X Y W Z) /-- `X × Y` is homeomorphic to `Y × X`. -/ def prodComm : X × Y ≃ₜ Y × X where @@ -523,6 +604,25 @@ def prodAssoc : (X × Y) × Z ≃ₜ X × Y × Z where continuous_invFun := (continuous_fst.prod_mk continuous_snd.fst).prod_mk continuous_snd.snd toEquiv := Equiv.prodAssoc X Y Z +@[simp] +lemma prodAssoc_toEquiv : (prodAssoc X Y Z).toEquiv = Equiv.prodAssoc X Y Z := rfl + +/-- Four-way commutativity of `prod`. The name matches `mul_mul_mul_comm`. -/ +def prodProdProdComm : (X × Y) × W × Z ≃ₜ (X × W) × Y × Z where + toEquiv := Equiv.prodProdProdComm X Y W Z + continuous_toFun := by + unfold Equiv.prodProdProdComm + dsimp only + fun_prop + continuous_invFun := by + unfold Equiv.prodProdProdComm + dsimp only + fun_prop + +@[simp] +theorem prodProdProdComm_symm : (prodProdProdComm X Y W Z).symm = prodProdProdComm X W Y Z := + rfl + /-- `X × {*}` is homeomorphic to `X`. -/ @[simps! (config := .asFn) apply] def prodPUnit : X × PUnit ≃ₜ X where @@ -543,7 +643,7 @@ def homeomorphOfUnique [Unique X] [Unique Y] : X ≃ₜ Y := continuous_toFun := continuous_const continuous_invFun := continuous_const } -end +end prod /-- `Equiv.piCongrLeft` as a homeomorphism: this is the natural homeomorphism `Π i, Y (e i) ≃ₜ Π j, Y j` obtained from a bijection `ι ≃ ι'`. -/ @@ -589,6 +689,7 @@ def ulift.{u, v} {X : Type u} [TopologicalSpace X] : ULift.{v, u} X ≃ₜ X whe section Distrib /-- `(X ⊕ Y) × Z` is homeomorphic to `X × Z ⊕ Y × Z`. -/ +@[simps!] def sumProdDistrib : (X ⊕ Y) × Z ≃ₜ (X × Z) ⊕ (Y × Z) := Homeomorph.symm <| homeomorphOfContinuousOpen (Equiv.sumProdDistrib X Y Z).symm @@ -603,6 +704,7 @@ def prodSumDistrib : X × (Y ⊕ Z) ≃ₜ (X × Y) ⊕ (X × Z) := variable {ι : Type*} {X : ι → Type*} [∀ i, TopologicalSpace (X i)] /-- `(Σ i, X i) × Y` is homeomorphic to `Σ i, (X i × Y)`. -/ +@[simps! apply symm_apply toEquiv] def sigmaProdDistrib : (Σ i, X i) × Y ≃ₜ Σ i, X i × Y := Homeomorph.symm <| homeomorphOfContinuousOpen (Equiv.sigmaProdDistrib X Y).symm @@ -755,3 +857,105 @@ def homeoOfEquivCompactToT2 [CompactSpace X] [T2Space Y] {f : X ≃ Y} (hf : Con continuous_invFun := hf.continuous_symm_of_equiv_compact_to_t2 } end Continuous + +variable [TopologicalSpace X] [TopologicalSpace Y] [TopologicalSpace Z] + {W : Type*} [TopologicalSpace W] {f : X → Y} + +/-- Predicate saying that `f` is a homeomorphism. + +This should be used only when `f` is a concrete function whose continuous inverse is not easy to +write down. Otherwise, `Homeomorph` should be preferred as it bundles the continuous inverse. + +Having both `Homeomorph` and `IsHomeomorph` is justified by the fact that so many function +properties are unbundled in the topology part of the library, and by the fact that a homeomorphism +is not merely a continuous bijection, that is `IsHomeomorph f` is not equivalent to +`Continuous f ∧ Bijective f` but to `Continuous f ∧ Bijective f ∧ IsOpenMap f`. -/ +structure IsHomeomorph (f : X → Y) : Prop where + continuous : Continuous f + isOpenMap : IsOpenMap f + bijective : Bijective f + +protected theorem Homeomorph.isHomeomorph (h : X ≃ₜ Y) : IsHomeomorph h := + ⟨h.continuous, h.isOpenMap, h.bijective⟩ + +namespace IsHomeomorph +variable (hf : IsHomeomorph f) +include hf + +protected lemma injective : Function.Injective f := hf.bijective.injective +protected lemma surjective : Function.Surjective f := hf.bijective.surjective + +variable (f) in +/-- Bundled homeomorphism constructed from a map that is a homeomorphism. -/ +@[simps! toEquiv apply symm_apply] +noncomputable def homeomorph : X ≃ₜ Y where + continuous_toFun := hf.1 + continuous_invFun := by + rw [continuous_iff_continuousOn_univ, ← hf.bijective.2.range_eq] + exact hf.isOpenMap.continuousOn_range_of_leftInverse (leftInverse_surjInv hf.bijective) + toEquiv := Equiv.ofBijective f hf.bijective + +protected lemma isClosedMap : IsClosedMap f := (hf.homeomorph f).isClosedMap +protected lemma inducing : Inducing f := (hf.homeomorph f).inducing +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 + +end IsHomeomorph + +/-- A map is a homeomorphism iff it is the map underlying a bundled homeomorphism `h : X ≃ₜ Y`. -/ +lemma isHomeomorph_iff_exists_homeomorph : IsHomeomorph f ↔ ∃ h : X ≃ₜ Y, h = f := + ⟨fun hf => ⟨hf.homeomorph f, rfl⟩, fun ⟨h, h'⟩ => h' ▸ h.isHomeomorph⟩ + +/-- A map is a homeomorphism iff it is continuous and has a continuous inverse. -/ +lemma isHomeomorph_iff_exists_inverse : IsHomeomorph f ↔ Continuous f ∧ ∃ g : Y → X, + LeftInverse g f ∧ RightInverse g f ∧ Continuous g := by + refine ⟨fun hf ↦ ⟨hf.continuous, ?_⟩, fun ⟨hf, g, hg⟩ ↦ ?_⟩ + let h := hf.homeomorph f + exact ⟨h.symm, h.left_inv, h.right_inv, h.continuous_invFun⟩ + exact (Homeomorph.mk ⟨f, g, hg.1, hg.2.1⟩ hf hg.2.2).isHomeomorph + +/-- A map is a homeomorphism iff it is a surjective embedding. -/ +lemma isHomeomorph_iff_embedding_surjective : IsHomeomorph f ↔ Embedding f ∧ Surjective f where + mp hf := ⟨hf.embedding, hf.surjective⟩ + mpr h := ⟨h.1.continuous, ((openEmbedding_iff f).2 ⟨h.1, h.2.range_eq ▸ isOpen_univ⟩).isOpenMap, + h.1.inj, h.2⟩ + +/-- A map is a homeomorphism iff it is continuous, closed and bijective. -/ +lemma isHomeomorph_iff_continuous_isClosedMap_bijective : IsHomeomorph f ↔ + Continuous f ∧ IsClosedMap f ∧ Function.Bijective f := + ⟨fun hf => ⟨hf.continuous, hf.isClosedMap, hf.bijective⟩, fun ⟨hf, hf', hf''⟩ => + ⟨hf, fun _ hu => isClosed_compl_iff.1 (image_compl_eq hf'' ▸ hf' _ hu.isClosed_compl), hf''⟩⟩ + +/-- A map from a compact space to a T2 space is a homeomorphism iff it is continuous and + bijective. -/ +lemma isHomeomorph_iff_continuous_bijective [CompactSpace X] [T2Space Y] : + IsHomeomorph f ↔ Continuous f ∧ Bijective f := by + rw [isHomeomorph_iff_continuous_isClosedMap_bijective] + refine and_congr_right fun hf ↦ ?_ + rw [eq_true hf.isClosedMap, true_and] + +protected lemma IsHomeomorph.id : IsHomeomorph (@id X) := ⟨continuous_id, .id, bijective_id⟩ + +lemma IsHomeomorph.comp {g : Y → Z} (hg : IsHomeomorph g) (hf : IsHomeomorph f) : + IsHomeomorph (g ∘ f) := ⟨hg.1.comp hf.1, hg.2.comp hf.2, hg.3.comp hf.3⟩ + +lemma IsHomeomorph.sumMap {g : Z → W} (hf : IsHomeomorph f) (hg : IsHomeomorph g) : + 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⟩ + +lemma IsHomeomorph.sigmaMap {ι κ : Type*} {X : ι → Type*} {Y : κ → Type*} + [∀ i, TopologicalSpace (X i)] [∀ i, TopologicalSpace (Y i)] {f : ι → κ} + (hf : Bijective f) {g : (i : ι) → X i → Y (f i)} (hg : ∀ i, IsHomeomorph (g i)) : + IsHomeomorph (Sigma.map f g) := by + simp_rw [isHomeomorph_iff_embedding_surjective,] at hg ⊢ + exact ⟨(embedding_sigma_map hf.1).2 fun i ↦ (hg i).1, hf.2.sigma_map fun i ↦ (hg i).2⟩ + +lemma IsHomeomorph.pi_map {ι : Type*} {X Y : ι → Type*} [∀ i, TopologicalSpace (X i)] + [∀ i, TopologicalSpace (Y i)] {f : (i : ι) → X i → Y i} (h : ∀ i, IsHomeomorph (f i)) : + IsHomeomorph (fun (x : ∀ i, X i) i ↦ f i (x i)) := + (Homeomorph.piCongrRight fun i ↦ (h i).homeomorph (f i)).isHomeomorph diff --git a/Mathlib/Topology/Homotopy/Basic.lean b/Mathlib/Topology/Homotopy/Basic.lean index 75273bcf06755..caf0e3a6983a5 100644 --- a/Mathlib/Topology/Homotopy/Basic.lean +++ b/Mathlib/Topology/Homotopy/Basic.lean @@ -160,7 +160,6 @@ theorem extend_apply_of_one_le (F : Homotopy f₀ f₁) {t : ℝ} (ht : 1 ≤ t) rw [← F.apply_one] exact ContinuousMap.congr_fun (Set.IccExtend_of_right_le (zero_le_one' ℝ) F.curry ht) x -@[simp] theorem extend_apply_coe (F : Homotopy f₀ f₁) (t : I) (x : X) : F.extend t x = F (t, x) := ContinuousMap.congr_fun (Set.IccExtend_val (zero_le_one' ℝ) F.curry t) x diff --git a/Mathlib/Topology/Homotopy/HSpaces.lean b/Mathlib/Topology/Homotopy/HSpaces.lean index b6ecf5d805502..15648773fa822 100644 --- a/Mathlib/Topology/Homotopy/HSpaces.lean +++ b/Mathlib/Topology/Homotopy/HSpaces.lean @@ -170,7 +170,7 @@ theorem qRight_zero_left (θ : I) : qRight (0, θ) = 0 := theorem qRight_one_left (θ : I) : qRight (1, θ) = 1 := Set.projIcc_of_right_le _ <| - (le_div_iff <| add_pos zero_lt_one).2 <| by + (le_div_iff₀ <| add_pos zero_lt_one).2 <| by dsimp only rw [coe_one, one_mul, mul_one, add_comm, ← one_add_one_eq_two] simp only [add_le_add_iff_right] diff --git a/Mathlib/Topology/Inseparable.lean b/Mathlib/Topology/Inseparable.lean index a58bfe2c76c2f..f4f888556c776 100644 --- a/Mathlib/Topology/Inseparable.lean +++ b/Mathlib/Topology/Inseparable.lean @@ -541,6 +541,10 @@ instance [Inhabited X] : Inhabited (SeparationQuotient X) := instance [Subsingleton X] : Subsingleton (SeparationQuotient X) := surjective_mk.subsingleton +@[to_additive] instance [One X] : One (SeparationQuotient X) := ⟨mk 1⟩ + +@[to_additive (attr := simp)] theorem mk_one [One X] : mk (1 : X) = 1 := rfl + theorem preimage_image_mk_open (hs : IsOpen s) : mk ⁻¹' (mk '' s) = s := by refine Subset.antisymm ?_ (subset_preimage_image _ _) rintro x ⟨y, hys, hxy⟩ diff --git a/Mathlib/Topology/Instances/Complex.lean b/Mathlib/Topology/Instances/Complex.lean index d3dad6f31c97f..1bd41163d0387 100644 --- a/Mathlib/Topology/Instances/Complex.lean +++ b/Mathlib/Topology/Instances/Complex.lean @@ -5,10 +5,10 @@ Authors: Xavier Roblot -/ import Mathlib.Analysis.Complex.Basic import Mathlib.Data.Complex.FiniteDimensional -import Mathlib.FieldTheory.IntermediateField import Mathlib.LinearAlgebra.FiniteDimensional import Mathlib.Topology.Algebra.Field import Mathlib.Topology.Algebra.UniformRing +import Mathlib.FieldTheory.IntermediateField.Basic /-! # Some results about the topology of ℂ diff --git a/Mathlib/Topology/Instances/Discrete.lean b/Mathlib/Topology/Instances/Discrete.lean index f8dd829077e96..3a0fe98aa800a 100644 --- a/Mathlib/Topology/Instances/Discrete.lean +++ b/Mathlib/Topology/Instances/Discrete.lean @@ -42,7 +42,7 @@ theorem DiscreteTopology.secondCountableTopology_of_encodable {α : Type*} [TopologicalSpace α] [DiscreteTopology α] [Countable α] : SecondCountableTopology α := DiscreteTopology.secondCountableTopology_of_countable -theorem bot_topologicalSpace_eq_generateFrom_of_pred_succOrder {α} [PartialOrder α] [PredOrder α] +theorem bot_topologicalSpace_eq_generateFrom_of_pred_succOrder {α} [LinearOrder α] [PredOrder α] [SuccOrder α] [NoMinOrder α] [NoMaxOrder α] : (⊥ : TopologicalSpace α) = generateFrom { s | ∃ a, s = Ioi a ∨ s = Iio a } := by refine (eq_bot_of_singletons_open fun a => ?_).symm @@ -56,7 +56,7 @@ theorem bot_topologicalSpace_eq_generateFrom_of_pred_succOrder {α} [PartialOrde · exact isOpen_generateFrom_of_mem ⟨succ a, Or.inr rfl⟩ · exact isOpen_generateFrom_of_mem ⟨pred a, Or.inl rfl⟩ -theorem discreteTopology_iff_orderTopology_of_pred_succ' [PartialOrder α] [PredOrder α] +theorem discreteTopology_iff_orderTopology_of_pred_succ' [LinearOrder α] [PredOrder α] [SuccOrder α] [NoMinOrder α] [NoMaxOrder α] : DiscreteTopology α ↔ OrderTopology α := by refine ⟨fun h => ⟨?_⟩, fun h => ⟨?_⟩⟩ · rw [h.eq_bot] @@ -65,7 +65,7 @@ theorem discreteTopology_iff_orderTopology_of_pred_succ' [PartialOrder α] [Pred exact bot_topologicalSpace_eq_generateFrom_of_pred_succOrder.symm instance (priority := 100) DiscreteTopology.orderTopology_of_pred_succ' [h : DiscreteTopology α] - [PartialOrder α] [PredOrder α] [SuccOrder α] [NoMinOrder α] [NoMaxOrder α] : OrderTopology α := + [LinearOrder α] [PredOrder α] [SuccOrder α] [NoMinOrder α] [NoMaxOrder α] : OrderTopology α := discreteTopology_iff_orderTopology_of_pred_succ'.1 h theorem LinearOrder.bot_topologicalSpace_eq_generateFrom {α} [LinearOrder α] [PredOrder α] diff --git a/Mathlib/Topology/Instances/ENNReal.lean b/Mathlib/Topology/Instances/ENNReal.lean index 0b4d7a5befa98..631eda52d1417 100644 --- a/Mathlib/Topology/Instances/ENNReal.lean +++ b/Mathlib/Topology/Instances/ENNReal.lean @@ -267,8 +267,8 @@ instance : ContinuousAdd ℝ≥0∞ := by · exact tendsto_nhds_top_mono' continuousAt_fst fun p => le_add_right le_rfl rcases b with (_ | b) · exact tendsto_nhds_top_mono' continuousAt_snd fun p => le_add_left le_rfl - simp only [ContinuousAt, some_eq_coe, nhds_coe_coe, ← coe_add, tendsto_map'_iff, (· ∘ ·), - tendsto_coe, tendsto_add] + simp only [ContinuousAt, some_eq_coe, nhds_coe_coe, ← coe_add, tendsto_map'_iff, + Function.comp_def, tendsto_coe, tendsto_add] protected theorem tendsto_atTop_zero [Nonempty β] [SemilatticeSup β] {f : β → ℝ≥0∞} : Tendsto f atTop (𝓝 0) ↔ ∀ ε > 0, ∃ N, ∀ n ≥ N, f n ≤ ε := @@ -291,7 +291,7 @@ theorem tendsto_sub : ∀ {a b : ℝ≥0∞}, (a ≠ ∞ ∨ b ≠ ∞) → (lt_mem_nhds <| @coe_lt_top (a + 1))).mono fun x hx => tsub_eq_zero_iff_le.2 (hx.1.trans hx.2).le | (a : ℝ≥0), (b : ℝ≥0), _ => by - simp only [nhds_coe_coe, tendsto_map'_iff, ← ENNReal.coe_sub, (· ∘ ·), tendsto_coe] + simp only [nhds_coe_coe, tendsto_map'_iff, ← ENNReal.coe_sub, Function.comp_def, tendsto_coe] exact continuous_sub.tendsto (a, b) protected theorem Tendsto.sub {f : Filter α} {ma : α → ℝ≥0∞} {mb : α → ℝ≥0∞} {a b : ℝ≥0∞} @@ -316,10 +316,11 @@ protected theorem tendsto_mul (ha : a ≠ 0 ∨ b ≠ ∞) (hb : b ≠ 0 ∨ a induction b with | top => simp only [ne_eq, or_false, not_true_eq_false] at ha - simpa [(· ∘ ·), mul_comm, mul_top ha] + simpa [Function.comp_def, mul_comm, mul_top ha] using (ht a ha).comp (continuous_swap.tendsto (ofNNReal a, ∞)) | coe b => - simp only [nhds_coe_coe, ← coe_mul, tendsto_coe, tendsto_map'_iff, (· ∘ ·), tendsto_mul] + simp only [nhds_coe_coe, ← coe_mul, tendsto_coe, tendsto_map'_iff, Function.comp_def, + tendsto_mul] protected theorem Tendsto.mul {f : Filter α} {ma : α → ℝ≥0∞} {mb : α → ℝ≥0∞} {a b : ℝ≥0∞} (hma : Tendsto ma f (𝓝 a)) (ha : a ≠ 0 ∨ b ≠ ∞) (hmb : Tendsto mb f (𝓝 b)) @@ -356,7 +357,7 @@ theorem tendsto_finset_prod_of_ne_top {ι : Type*} {f : ι → α → ℝ≥0∞ simp only [Finset.prod_insert has] apply Tendsto.mul (h _ (Finset.mem_insert_self _ _)) · right - exact (prod_lt_top fun i hi => h' _ (Finset.mem_insert_of_mem hi)).ne + exact prod_ne_top fun i hi => h' _ (Finset.mem_insert_of_mem hi) · exact IH (fun i hi => h _ (Finset.mem_insert_of_mem hi)) fun i hi => h' _ (Finset.mem_insert_of_mem hi) · exact Or.inr (h' _ (Finset.mem_insert_self _ _)) @@ -444,7 +445,7 @@ theorem iInf_mul_left' {ι} {f : ι → ℝ≥0∞} {a : ℝ≥0∞} (h : a = 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_iInf_of_continuousAt' + · exact (ENNReal.mul_left_mono.map_ciInf_of_continuousAt (ENNReal.continuousAt_const_mul H)).symm theorem iInf_mul_left {ι} [Nonempty ι] {f : ι → ℝ≥0∞} {a : ℝ≥0∞} @@ -504,7 +505,7 @@ protected theorem tendsto_inv_nat_nhds_zero : Tendsto (fun n : ℕ => (n : ℝ 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_iSup_of_continuousAt' (continuousAt_id.add continuousAt_const) <| + 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∞} : @@ -610,7 +611,7 @@ protected theorem tendsto_coe_sub {b : ℝ≥0∞} : theorem sub_iSup {ι : Sort*} [Nonempty ι] {b : ι → ℝ≥0∞} (hr : a < ∞) : (a - ⨆ i, b i) = ⨅ i, a - b i := - antitone_const_tsub.map_iSup_of_continuousAt' (continuous_sub_left hr.ne).continuousAt + 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 @@ -1168,7 +1169,7 @@ theorem tsum_comp_le_tsum_of_inj {β : Type*} {f : α → ℝ} (hf : Summable f) {i : β → α} (hi : Function.Injective i) : tsum (f ∘ i) ≤ tsum f := by lift f to α → ℝ≥0 using hn rw [NNReal.summable_coe] at hf - simpa only [(· ∘ ·), ← NNReal.coe_tsum] using NNReal.tsum_comp_le_tsum_of_inj hf hi + simpa only [Function.comp_def, ← NNReal.coe_tsum] using NNReal.tsum_comp_le_tsum_of_inj hf hi /-- Comparison test of convergence of series of non-negative real numbers. -/ theorem Summable.of_nonneg_of_le {f g : β → ℝ} (hg : ∀ b, 0 ≤ g b) (hgf : ∀ b, g b ≤ f b) @@ -1523,3 +1524,5 @@ 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 a14e8778f0703..5ad8821215f37 100644 --- a/Mathlib/Topology/Instances/EReal.lean +++ b/Mathlib/Topology/Instances/EReal.lean @@ -145,143 +145,97 @@ 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] +/-! ### Infs and Sups -/ + +variable {α : Type*} {u v : α → EReal} + +lemma add_iInf_le_iInf_add : (⨅ x, u x) + (⨅ x, v x) ≤ ⨅ x, (u + v) x := by + refine add_le_of_forall_add_le fun a a_u b b_v ↦ ?_ + rw [lt_iInf_iff] at a_u b_v + rcases a_u with ⟨c, a_c, c_u⟩ + rcases b_v with ⟨d, b_d, d_v⟩ + simp only [Pi.add_apply, le_iInf_iff] + exact fun x ↦ add_le_add (lt_of_lt_of_le a_c (c_u x)).le (lt_of_lt_of_le b_d (d_v x)).le + +lemma iSup_add_le_add_iSup (h : ⨆ x, u x ≠ ⊥ ∨ ⨆ x, v x ≠ ⊤) (h' : ⨆ x, u x ≠ ⊤ ∨ ⨆ x, v x ≠ ⊥) : + ⨆ x, (u + v) x ≤ (⨆ x, u x) + (⨆ x, v x) := by + refine le_add_of_forall_le_add h h' fun a a_u b b_v ↦ ?_ + rw [gt_iff_lt, iSup_lt_iff] at a_u b_v + rcases a_u with ⟨c, a_c, c_u⟩ + rcases b_v with ⟨d, b_d, d_v⟩ + simp only [Pi.add_apply, iSup_le_iff] + exact fun x ↦ add_le_add (lt_of_le_of_lt (c_u x) a_c).le (lt_of_le_of_lt (d_v x) b_d).le + /-! ### Liminfs and Limsups -/ section LimInfSup -variable {α : Type*} {f : Filter α} {u v : α → EReal} {a b : EReal} +variable {α : Type*} {f : Filter α} {u v : α → EReal} -lemma liminf_le_liminf (h : u ≤ᶠ[f] v) : - liminf u f ≤ liminf v f := Filter.liminf_le_liminf h +lemma liminf_neg : liminf (- v) f = - limsup v f := + EReal.negOrderIso.limsup_apply.symm -lemma limsup_le_limsup (h : u ≤ᶠ[f] v) : - limsup u f ≤ limsup v f := Filter.limsup_le_limsup h +lemma limsup_neg : limsup (- v) f = - liminf v f := + EReal.negOrderIso.liminf_apply.symm -/-- This lemma is superseded by `limsup_add_le_of_le` (weaker hypothesis) and -`limsup_add_lt_of_lt` (stronger thesis). -/ -private lemma limsup_add_le_of_lt (ha : limsup u f < a) (hb : limsup v f < b) : - limsup (u + v) f ≤ a + b := by - rcases eq_or_neBot f with (rfl | _) - · simp only [limsup_bot, bot_le] - rw [← @limsup_const EReal α _ f _ (a + b)] - apply limsup_le_limsup (Eventually.mp (Eventually.and (eventually_lt_of_limsup_lt ha) - (eventually_lt_of_limsup_lt hb)) (Eventually.of_forall _)) - simp only [Pi.add_apply, and_imp] - intro x - exact fun ux_lt_a vx_lt_b ↦ add_le_add (le_of_lt ux_lt_a) (le_of_lt vx_lt_b) +lemma add_liminf_le_liminf_add : (liminf u f) + (liminf v f) ≤ liminf (u + v) f := by + refine add_le_of_forall_add_le fun a a_u b b_v ↦ (le_liminf_iff).2 fun c c_ab ↦ ?_ + filter_upwards [eventually_lt_of_lt_liminf a_u, eventually_lt_of_lt_liminf b_v] with x a_x b_x + exact lt_trans c_ab (add_lt_add a_x b_x) + +lemma limsup_add_le_add_limsup (h : limsup u f ≠ ⊥ ∨ limsup v f ≠ ⊤) + (h' : limsup u f ≠ ⊤ ∨ limsup v f ≠ ⊥) : + limsup (u + v) f ≤ (limsup u f) + (limsup v f) := by + refine le_add_of_forall_le_add h h' fun a a_u b b_v ↦ (limsup_le_iff).2 fun c c_ab ↦ ?_ + filter_upwards [eventually_lt_of_limsup_lt a_u, eventually_lt_of_limsup_lt b_v] with x a_x b_x + exact (add_lt_add a_x b_x).trans c_ab + +lemma limsup_add_liminf_le_limsup_add : (limsup u f) + (liminf v f) ≤ limsup (u + v) f := + add_le_of_forall_add_le fun a a_u b b_v ↦ (le_limsup_iff).2 fun c c_ab ↦ + Frequently.mono (Frequently.and_eventually ((frequently_lt_of_lt_limsup) a_u) + ((eventually_lt_of_lt_liminf) b_v)) fun _ ab_x ↦ c_ab.trans (add_lt_add ab_x.1 ab_x.2) + +lemma liminf_add_le_limsup_add_liminf (h : limsup u f ≠ ⊥ ∨ liminf v f ≠ ⊤) + (h' : limsup u f ≠ ⊤ ∨ liminf v f ≠ ⊥) : + liminf (u + v) f ≤ (limsup u f) + (liminf v f) := + le_add_of_forall_le_add h h' fun a a_u b b_v ↦ (liminf_le_iff).2 fun c c_ab ↦ + Frequently.mono (Frequently.and_eventually ((frequently_lt_of_liminf_lt) b_v) + ((eventually_lt_of_limsup_lt) a_u)) fun _ ab_x ↦ (add_lt_add ab_x.2 ab_x.1).trans c_ab -lemma limsup_add_lt_of_lt (ha : limsup u f < a) (hb : limsup v f < b) : - limsup (u + v) f < a + b := by - obtain ⟨c, hc, hca⟩ := DenselyOrdered.dense _ _ ha - obtain ⟨d, hd, hdb⟩ := DenselyOrdered.dense _ _ hb - exact (limsup_add_le_of_lt hc hd).trans_lt (add_lt_add hca hdb) +variable {a b : EReal} lemma limsup_add_bot_of_ne_top (h : limsup u f = ⊥) (h' : limsup v f ≠ ⊤) : limsup (u + v) f = ⊥ := by - apply le_bot_iff.1 - apply (le_iff_le_forall_real_gt ⊥ (limsup (u + v) f)).1 - intro x - rcases exists_between_coe_real (h'.lt_top) with ⟨y, ⟨hy, _⟩⟩ - rw [← sub_add_cancel x y, coe_add (x - y) y, coe_sub x y] - intro _ - apply @limsup_add_le_of_lt α f u v (x - y) y _ hy - rw [h, ← coe_sub x y] - exact bot_lt_coe (x - y) - -lemma limsup_add_le_add_limsup - (h : limsup u f ≠ ⊥ ∨ limsup v f ≠ ⊤) (h' : limsup u f ≠ ⊤ ∨ limsup v f ≠ ⊥) : - limsup (u + v) f ≤ (limsup u f) + (limsup v f) := by - rcases eq_bot_or_bot_lt (limsup u f) with (u_bot | u_nbot) - · have v_ntop := h.neg_resolve_left u_bot - rw [limsup_add_bot_of_ne_top u_bot v_ntop]; exact bot_le - rcases eq_bot_or_bot_lt (limsup v f) with (v_bot | v_nbot) - · have u_ntop := h'.neg_resolve_right v_bot - rw [add_comm, limsup_add_bot_of_ne_top v_bot u_ntop]; exact bot_le - rcases eq_top_or_lt_top (limsup v f) with (v_top | v_ntop) - · rw [v_top, add_top_of_ne_bot (ne_of_gt u_nbot)]; exact le_top - have limsup_v_real := coe_toReal (ne_of_lt v_ntop) (ne_of_gt v_nbot) - apply (le_iff_le_forall_real_gt _ _).1 - intros x hx - rcases lt_iff_exists_real_btwn.1 hx with ⟨y, ⟨sum_lt_y, y_lt_x⟩⟩ - have key₁ : limsup u f < (y - limsup v f) := by - apply lt_of_eq_of_lt _ (sub_lt_sub_of_lt_of_le sum_lt_y (le_of_eq (Eq.refl (limsup v f))) - (ne_of_gt v_nbot) (ne_of_lt v_ntop)) - rw [← limsup_v_real, add_sub_cancel_right] - have key₂ : limsup v f < limsup v f + x - y := by - rw [← limsup_v_real]; norm_cast; norm_cast at y_lt_x; linarith - apply le_of_le_of_eq (limsup_add_le_of_lt key₁ key₂) - rw [← limsup_v_real]; norm_cast; linarith + apply le_bot_iff.1 (le_trans (limsup_add_le_add_limsup (Or.inr h') _) _) + · rw [h]; exact Or.inl bot_ne_top + · rw [h, bot_add] lemma limsup_add_le_of_le (ha : limsup u f < a) (hb : limsup v f ≤ b) : limsup (u + v) f ≤ a + b := by - rcases lt_or_eq_of_le hb with (hb | hb) - · exact limsup_add_le_of_lt ha hb - by_cases hb' : b = ⊤ - · convert le_top - on_goal 1 => rw [hb'] - -- This closes both remaining goals at once. - exact add_top_of_ne_bot ha.ne_bot - exact (limsup_add_le_add_limsup (hb ▸ Or.inr hb') (Or.inl ha.ne_top)).trans - (add_le_add ha.le hb.le) - -lemma liminf_neg : liminf (- v) f = - limsup v f := - EReal.negOrderIso.limsup_apply.symm - -lemma limsup_neg : limsup (- v) f = - liminf v f := - EReal.negOrderIso.liminf_apply.symm + rcases eq_top_or_lt_top b with (rfl | h) + · rw [add_top_of_ne_bot ha.ne_bot]; exact le_top + · exact le_trans (limsup_add_le_add_limsup (Or.inr (lt_of_le_of_lt hb h).ne) (Or.inl ha.ne_top)) + (add_le_add ha.le hb) lemma liminf_add_gt_of_gt (ha : a < liminf u f) (hb : b < liminf v f) : - a + b < liminf (u + v) f := by - have ha' : a ≠ ⊤ := ha.ne_top - have hb' : b ≠ ⊤ := hb.ne_top - have h : limsup (-(u + v)) f = limsup (-u + -v) f := by - apply limsup_congr - filter_upwards [eventually_lt_of_lt_liminf ha, eventually_lt_of_lt_liminf hb] with x hax hbx - dsimp - rw [neg_add (Or.inl hax.ne_bot) (Or.inr hbx.ne_bot), sub_eq_add_neg] - rw [← neg_lt_neg_iff, ← limsup_neg] at ha hb ⊢ - rw [neg_add (Or.inr hb') (Or.inl ha'), h] - exact limsup_add_lt_of_lt ha hb + a + b < liminf (u + v) f := + lt_of_lt_of_le (add_lt_add ha hb) add_liminf_le_liminf_add lemma liminf_add_top_of_ne_bot (h : liminf u f = ⊤) (h' : liminf v f ≠ ⊥) : liminf (u + v) f = ⊤ := by - apply top_le_iff.1 ((ge_iff_le_forall_real_lt (liminf (u + v) f) ⊤).1 _) - intro x - rcases exists_between_coe_real (Ne.bot_lt h') with ⟨y, ⟨_, hy⟩⟩ - intro _ - rw [← sub_add_cancel x y, coe_add (x - y) y] - exact coe_sub x y ▸ @liminf_add_gt_of_gt α f u v (x - y) y - (h ▸ coe_sub x y ▸ coe_lt_top (x-y)) hy |>.le - -lemma add_liminf_le_liminf_add : (liminf u f) + (liminf v f) ≤ liminf (u + v) f := by - by_cases hu : liminf u f = ⊥ - · simp_all - by_cases hv : liminf v f = ⊥ - · simp_all - have h' : limsup (-(u + v)) f = limsup (-u + -v) f := by - apply limsup_congr - filter_upwards [eventually_lt_of_lt_liminf (bot_lt_iff_ne_bot.mpr hu), - eventually_lt_of_lt_liminf (bot_lt_iff_ne_bot.mpr hv)] with x hux hvx - dsimp - rw [neg_add (Or.inl hux.ne_bot) (Or.inr hvx.ne_bot), sub_eq_add_neg] - rw [← neg_le_neg_iff, neg_add (Or.inl hu) (Or.inr hv), sub_eq_add_neg] - rw [← neg_inj, neg_bot] at hu hv - simp_rw [← limsup_neg] at hu hv ⊢ - exact h' ▸ limsup_add_le_add_limsup (Or.inr hv) (Or.inl hu) + apply top_le_iff.1 (le_trans _ (add_liminf_le_liminf_add)) + rw [h, top_add_of_ne_bot h'] lemma limsup_le_iff {b : EReal} : limsup u f ≤ b ↔ ∀ c : ℝ, b < c → ∀ᶠ a : α in f, u a ≤ c := by - rw [← le_iff_le_forall_real_gt] - refine ⟨?_, ?_⟩ <;> intro h c b_lt_c - · rcases exists_between_coe_real b_lt_c with ⟨d, b_lt_d, d_lt_c⟩ - specialize h d b_lt_d - have key := Filter.eventually_lt_of_limsup_lt (lt_of_le_of_lt h d_lt_c) - apply Filter.mem_of_superset key + rw [← le_of_forall_lt_iff_le] + refine ⟨?_, ?_⟩ <;> intro h c b_c + · rcases exists_between_coe_real b_c with ⟨d, b_d, d_c⟩ + apply mem_of_superset (eventually_lt_of_limsup_lt (lt_of_le_of_lt (h d b_d) d_c)) rw [Set.setOf_subset_setOf] - exact fun a h' ↦ le_of_lt h' - · rcases eq_or_neBot f with (rfl | _) + exact fun _ h' ↦ h'.le + · rcases eq_or_neBot f with rfl | _ · simp only [limsup_bot, bot_le] - · specialize h c b_lt_c - exact @Filter.limsup_const EReal α _ f _ (c : EReal) ▸ limsup_le_limsup h + · exact (limsup_le_of_le) (h c b_c) end LimInfSup @@ -289,8 +243,8 @@ end LimInfSup theorem continuousAt_add_coe_coe (a b : ℝ) : ContinuousAt (fun p : EReal × EReal => p.1 + p.2) (a, b) := by - simp only [ContinuousAt, nhds_coe_coe, ← coe_add, tendsto_map'_iff, (· ∘ ·), tendsto_coe, - tendsto_add] + simp only [ContinuousAt, nhds_coe_coe, ← coe_add, tendsto_map'_iff, Function.comp_def, + tendsto_coe, tendsto_add] theorem continuousAt_add_top_coe (a : ℝ) : ContinuousAt (fun p : EReal × EReal => p.1 + p.2) (⊤, a) := by @@ -301,7 +255,7 @@ theorem continuousAt_add_top_coe (a : ℝ) : theorem continuousAt_add_coe_top (a : ℝ) : ContinuousAt (fun p : EReal × EReal => p.1 + p.2) (a, ⊤) := by - simpa only [add_comm, (· ∘ ·), ContinuousAt, Prod.swap] + simpa only [add_comm, Function.comp_def, ContinuousAt, Prod.swap] using Tendsto.comp (continuousAt_add_top_coe a) (continuous_swap.tendsto ((a : EReal), ⊤)) theorem continuousAt_add_top_top : ContinuousAt (fun p : EReal × EReal => p.1 + p.2) (⊤, ⊤) := by @@ -319,7 +273,7 @@ theorem continuousAt_add_bot_coe (a : ℝ) : theorem continuousAt_add_coe_bot (a : ℝ) : ContinuousAt (fun p : EReal × EReal => p.1 + p.2) (a, ⊥) := by - simpa only [add_comm, (· ∘ ·), ContinuousAt, Prod.swap] + simpa only [add_comm, Function.comp_def, ContinuousAt, Prod.swap] using Tendsto.comp (continuousAt_add_bot_coe a) (continuous_swap.tendsto ((a : EReal), ⊥)) theorem continuousAt_add_bot_bot : ContinuousAt (fun p : EReal × EReal => p.1 + p.2) (⊥, ⊥) := by @@ -386,7 +340,7 @@ private lemma continuousAt_mul_symm3 {a b : EReal} private lemma continuousAt_mul_coe_coe (a b : ℝ) : ContinuousAt (fun p : EReal × EReal ↦ p.1 * p.2) (a, b) := by simp [ContinuousAt, EReal.nhds_coe_coe, ← EReal.coe_mul, Filter.tendsto_map'_iff, - (· ∘ ·), EReal.tendsto_coe, tendsto_mul] + Function.comp_def, EReal.tendsto_coe, tendsto_mul] private lemma continuousAt_mul_top_top : ContinuousAt (fun p : EReal × EReal ↦ p.1 * p.2) (⊤, ⊤) := by diff --git a/Mathlib/Topology/Instances/NNReal.lean b/Mathlib/Topology/Instances/NNReal.lean index f7759c47f7eea..d6ef63c1b5f66 100644 --- a/Mathlib/Topology/Instances/NNReal.lean +++ b/Mathlib/Topology/Instances/NNReal.lean @@ -93,6 +93,11 @@ noncomputable def _root_.ContinuousMap.realToNNReal : C(ℝ, ℝ≥0) := theorem continuous_coe : Continuous ((↑) : ℝ≥0 → ℝ) := continuous_subtype_val +lemma _root_.ContinuousOn.ofReal_map_toNNReal {f : ℝ≥0 → ℝ≥0} {s : Set ℝ} {t : Set ℝ≥0} + (hf : ContinuousOn f t) (h : Set.MapsTo Real.toNNReal s t) : + ContinuousOn (fun x ↦ f x.toNNReal : ℝ → ℝ) s := + continuous_subtype_val.comp_continuousOn <| hf.comp continuous_real_toNNReal.continuousOn h + /-- Embedding of `ℝ≥0` to `ℝ` as a bundled continuous map. -/ @[simps (config := .asFn)] def _root_.ContinuousMap.coeNNRealReal : C(ℝ≥0, ℝ) := @@ -257,7 +262,7 @@ section Monotone /-- A monotone, bounded above sequence `f : ℕ → ℝ` has a finite limit. -/ theorem _root_.Real.tendsto_of_bddAbove_monotone {f : ℕ → ℝ} (h_bdd : BddAbove (Set.range f)) (h_mon : Monotone f) : ∃ r : ℝ, Tendsto f atTop (𝓝 r) := by - obtain ⟨B, hB⟩ := Real.exists_isLUB (Set.range_nonempty f) h_bdd + obtain ⟨B, hB⟩ := Real.exists_isLUB (Set.range_nonempty f) h_bdd exact ⟨B, tendsto_atTop_isLUB h_mon hB⟩ /-- An antitone, bounded below sequence `f : ℕ → ℝ` has a finite limit. -/ diff --git a/Mathlib/Topology/Instances/Rat.lean b/Mathlib/Topology/Instances/Rat.lean index ce48d2b2344a3..1fd5e8eaa6966 100644 --- a/Mathlib/Topology/Instances/Rat.lean +++ b/Mathlib/Topology/Instances/Rat.lean @@ -70,7 +70,7 @@ 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 - simp only [(· ∘ ·), Rat.cast_add] + simp only [Function.comp_def, Rat.cast_add] exact Real.uniformContinuous_add.comp (Rat.uniformContinuous_coe_real.prod_map Rat.uniformContinuous_coe_real) diff --git a/Mathlib/Topology/List.lean b/Mathlib/Topology/List.lean index 563dc61834ff2..f9e3f9ddbdfc3 100644 --- a/Mathlib/Topology/List.lean +++ b/Mathlib/Topology/List.lean @@ -86,7 +86,7 @@ theorem tendsto_cons_iff {β : Type*} {f : List α → β} {b : Filter β} {a : have : 𝓝 (a::l) = (𝓝 a ×ˢ 𝓝 l).map fun p : α × List α => p.1::p.2 := by simp only [nhds_cons, Filter.prod_eq, (Filter.map_def _ _).symm, (Filter.seq_eq_filter_seq _ _).symm] - simp [-Filter.map_def, (· ∘ ·), functor_norm] + simp [-Filter.map_def, Function.comp_def, functor_norm] rw [this, Filter.tendsto_map'_iff]; rfl theorem continuous_cons : Continuous fun x : α × List α => (x.1::x.2 : List α) := @@ -124,7 +124,7 @@ theorem tendsto_insertNth' {a : α} : have : 𝓝 a ×ˢ 𝓝 (a'::l) = (𝓝 a ×ˢ (𝓝 a' ×ˢ 𝓝 l)).map fun p : α × α × List α => (p.1, p.2.1::p.2.2) := by simp only [nhds_cons, Filter.prod_eq, ← Filter.map_def, ← Filter.seq_eq_filter_seq] - simp [-Filter.map_def, (· ∘ ·), functor_norm] + simp [-Filter.map_def, Function.comp_def, functor_norm] rw [this, tendsto_map'_iff] exact (tendsto_fst.comp tendsto_snd).cons diff --git a/Mathlib/Topology/LocalAtTarget.lean b/Mathlib/Topology/LocalAtTarget.lean index 62a0b258ffe46..5970438a142e8 100644 --- a/Mathlib/Topology/LocalAtTarget.lean +++ b/Mathlib/Topology/LocalAtTarget.lean @@ -108,7 +108,10 @@ theorem isLocallyClosed_iff_coe_preimage_of_iSup_eq_top (s : Set β) : IsLocallyClosed s ↔ ∀ i, IsLocallyClosed ((↑) ⁻¹' s : Set (U i)) := by simp_rw [isLocallyClosed_iff_isOpen_coborder] rw [isOpen_iff_coe_preimage_of_iSup_eq_top hU] - exact forall_congr' fun i ↦ by rw [(U i).isOpen.openEmbedding_subtype_val.coborder_preimage] + exact forall_congr' fun i ↦ by + have : coborder ((↑) ⁻¹' s : Set (U i)) = Subtype.val ⁻¹' coborder s := by + exact (U i).isOpen.openEmbedding_subtype_val.coborder_preimage _ + rw [this] theorem isOpenMap_iff_isOpenMap_of_iSup_eq_top : IsOpenMap f ↔ ∀ i, IsOpenMap ((U i).1.restrictPreimage f) := by diff --git a/Mathlib/Topology/LocallyClosed.lean b/Mathlib/Topology/LocallyClosed.lean index 90d7577eba4a9..2aeca93797b38 100644 --- a/Mathlib/Topology/LocallyClosed.lean +++ b/Mathlib/Topology/LocallyClosed.lean @@ -88,12 +88,6 @@ lemma isClosed_preimage_val_coborder : IsClosed (coborder s ↓∩ s) := by rw [isClosed_preimage_val, inter_eq_right.mpr subset_coborder, coborder_inter_closure] -lemma IsOpen.isLocallyClosed (hs : IsOpen s) : IsLocallyClosed s := - ⟨_, _, hs, isClosed_univ, (inter_univ _).symm⟩ - -lemma IsClosed.isLocallyClosed (hs : IsClosed s) : IsLocallyClosed s := - ⟨_, _, isOpen_univ, hs, (univ_inter _).symm⟩ - lemma IsLocallyClosed.inter (hs : IsLocallyClosed s) (ht : IsLocallyClosed t) : IsLocallyClosed (s ∩ t) := by obtain ⟨U₁, Z₁, hU₁, hZ₁, rfl⟩ := hs diff --git a/Mathlib/Topology/LocallyConstant/Algebra.lean b/Mathlib/Topology/LocallyConstant/Algebra.lean index 1e70ce1a80c57..986f83f29a8ac 100644 --- a/Mathlib/Topology/LocallyConstant/Algebra.lean +++ b/Mathlib/Topology/LocallyConstant/Algebra.lean @@ -186,7 +186,7 @@ instance [NonAssocSemiring Y] : NonAssocSemiring (LocallyConstant X Y) := Function.Injective.nonAssocSemiring DFunLike.coe DFunLike.coe_injective' rfl rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) fun _ => rfl -/-- The constant-function embedding, as a ring hom. -/ +/-- The constant-function embedding, as a ring hom. -/ @[simps] def constRingHom [NonAssocSemiring Y] : Y →+* LocallyConstant X Y := { constMonoidHom, constAddMonoidHom with toFun := const X } @@ -347,7 +347,7 @@ lemma ker_comapₗ [Semiring R] [AddCommMonoid Z] [Module R Z] (f : C(X, Y)) LinearMap.ker (comapₗ R f : LocallyConstant Y Z →ₗ[R] LocallyConstant X Z) = ⊥ := LinearMap.ker_eq_bot_of_injective <| comap_injective _ hfs -/-- `LocallyConstant.congrLeft` as a linear equivalence. -/ +/-- `LocallyConstant.congrLeft` as a linear equivalence. -/ @[simps!] def congrLeftₗ (R : Type*) [Semiring R] [AddCommMonoid Z] [Module R Z] (e : X ≃ₜ Y) : LocallyConstant X Z ≃ₗ[R] LocallyConstant Y Z where @@ -362,7 +362,7 @@ def congrLeftRingEquiv [Semiring Z] (e : X ≃ₜ Y) : __ := comapMonoidHom ⟨_, e.symm.continuous⟩ __ := comapAddMonoidHom ⟨_, e.symm.continuous⟩ -/-- `LocallyConstant.congrLeft` as an `AlgEquiv`. -/ +/-- `LocallyConstant.congrLeft` as an `AlgEquiv`. -/ @[simps!] def congrLeftₐ (R : Type*) [CommSemiring R] [Semiring Z] [Algebra R Z] (e : X ≃ₜ Y) : LocallyConstant X Z ≃ₐ[R] LocallyConstant Y Z where @@ -406,7 +406,7 @@ def mapₐ (R : Type*) [CommSemiring R] [Semiring Y] [Algebra R Y] [Semiring Z] toRingHom := mapRingHom f commutes' _ := by aesop -/-- `LocallyConstant.congrRight` as a linear equivalence. -/ +/-- `LocallyConstant.congrRight` as a linear equivalence. -/ @[simps!] def congrRightₗ (R : Type*) [Semiring R] [AddCommMonoid Y] [Module R Y] [AddCommMonoid Z] [Module R Z] (e : Y ≃ₗ[R] Z) : @@ -422,7 +422,7 @@ def congrRightRingEquiv [Semiring Y] [Semiring Z] (e : Y ≃+* Z) : __ := mapMonoidHom e.toMonoidHom __ := mapAddMonoidHom e.toAddMonoidHom -/-- `LocallyConstant.congrRight` as an `AlgEquiv`. -/ +/-- `LocallyConstant.congrRight` as an `AlgEquiv`. -/ @[simps!] def congrRightₐ (R : Type*) [CommSemiring R] [Semiring Y] [Algebra R Y] [Semiring Z] [Algebra R Z] (e : Y ≃ₐ[R] Z) : LocallyConstant X Y ≃ₐ[R] LocallyConstant X Z where diff --git a/Mathlib/Topology/LocallyConstant/Basic.lean b/Mathlib/Topology/LocallyConstant/Basic.lean index 48f981df57cff..bc918bf4803b5 100644 --- a/Mathlib/Topology/LocallyConstant/Basic.lean +++ b/Mathlib/Topology/LocallyConstant/Basic.lean @@ -465,7 +465,7 @@ end Indicator section Equiv /-- -The equivalence between `LocallyConstant X Z` and `LocallyConstant Y Z` given a +The equivalence between `LocallyConstant X Z` and `LocallyConstant Y Z` given a homeomorphism `X ≃ₜ Y` -/ @[simps] @@ -480,7 +480,7 @@ def congrLeft [TopologicalSpace Y] (e : X ≃ₜ Y) : LocallyConstant X Z ≃ Lo simp [comap_comap] /-- -The equivalence between `LocallyConstant X Y` and `LocallyConstant X Z` given an +The equivalence between `LocallyConstant X Y` and `LocallyConstant X Z` given an equivalence `Y ≃ Z` -/ @[simps] @@ -556,7 +556,7 @@ lemma piecewise_apply_right {C₁ C₂ : Set X} (h₁ : IsClosed C₁) (h₂ : I · exact hfg x ⟨h, hx⟩ · rfl -/-- A variant of `LocallyConstant.piecewise` where the two closed sets cover a subset. +/-- A variant of `LocallyConstant.piecewise` where the two closed sets cover a subset. TODO: Generalise this construction to `ContinuousMap`. -/ def piecewise' {C₀ C₁ C₂ : Set X} (h₀ : C₀ ⊆ C₁ ∪ C₂) (h₁ : IsClosed C₁) diff --git a/Mathlib/Topology/LocallyFinite.lean b/Mathlib/Topology/LocallyFinite.lean index 62ae2d2ecfd21..f8fbbee18a97d 100644 --- a/Mathlib/Topology/LocallyFinite.lean +++ b/Mathlib/Topology/LocallyFinite.lean @@ -183,7 +183,7 @@ end LocallyFinite @[simp] theorem Equiv.locallyFinite_comp_iff (e : ι' ≃ ι) : LocallyFinite (f ∘ e) ↔ LocallyFinite f := - ⟨fun h => by simpa only [(· ∘ ·), e.apply_symm_apply] using h.comp_injective e.symm.injective, + ⟨fun h => by simpa only [comp_def, e.apply_symm_apply] using h.comp_injective e.symm.injective, fun h => h.comp_injective e.injective⟩ theorem locallyFinite_sum {f : ι ⊕ ι' → Set X} : diff --git a/Mathlib/Topology/Maps/Proper/Basic.lean b/Mathlib/Topology/Maps/Proper/Basic.lean index 4fa716956cb8b..4132dd33262f6 100644 --- a/Mathlib/Topology/Maps/Proper/Basic.lean +++ b/Mathlib/Topology/Maps/Proper/Basic.lean @@ -279,8 +279,11 @@ lemma isProperMap_of_isClosedMap_of_inj (f_cont : Continuous f) (f_inj : f.Injec @[simp] lemma Homeomorph.isProperMap (e : X ≃ₜ Y) : IsProperMap e := isProperMap_of_isClosedMap_of_inj e.continuous e.injective e.isClosedMap +protected lemma IsHomeomorph.isProperMap (hf : IsHomeomorph f) : IsProperMap f := + isProperMap_of_isClosedMap_of_inj hf.continuous hf.injective hf.isClosedMap + /-- The identity is proper. -/ -@[simp] lemma isProperMap_id : IsProperMap (id : X → X) := (Homeomorph.refl X).isProperMap +@[simp] lemma isProperMap_id : IsProperMap (id : X → X) := IsHomeomorph.id.isProperMap /-- A closed embedding is proper. -/ lemma isProperMap_of_closedEmbedding (hf : ClosedEmbedding f) : IsProperMap f := diff --git a/Mathlib/Topology/MetricSpace/Antilipschitz.lean b/Mathlib/Topology/MetricSpace/Antilipschitz.lean index 7a5a8a6646dec..88e3996a46af3 100644 --- a/Mathlib/Topology/MetricSpace/Antilipschitz.lean +++ b/Mathlib/Topology/MetricSpace/Antilipschitz.lean @@ -33,9 +33,9 @@ open Set Filter Bornology def AntilipschitzWith [PseudoEMetricSpace α] [PseudoEMetricSpace β] (K : ℝ≥0) (f : α → β) := ∀ x y, edist x y ≤ K * edist (f x) (f y) -theorem AntilipschitzWith.edist_lt_top [PseudoEMetricSpace α] [PseudoMetricSpace β] {K : ℝ≥0} - {f : α → β} (h : AntilipschitzWith K f) (x y : α) : edist x y < ⊤ := - (h x y).trans_lt <| ENNReal.mul_lt_top ENNReal.coe_ne_top (edist_ne_top _ _) +protected lemma AntilipschitzWith.edist_lt_top [PseudoEMetricSpace α] [PseudoMetricSpace β] + {K : ℝ≥0} {f : α → β} (h : AntilipschitzWith K f) (x y : α) : edist x y < ⊤ := + (h x y).trans_lt <| ENNReal.mul_lt_top ENNReal.coe_lt_top (edist_lt_top _ _) theorem AntilipschitzWith.edist_ne_top [PseudoEMetricSpace α] [PseudoMetricSpace β] {K : ℝ≥0} {f : α → β} (h : AntilipschitzWith K f) (x y : α) : edist x y ≠ ⊤ := diff --git a/Mathlib/Topology/MetricSpace/Bounded.lean b/Mathlib/Topology/MetricSpace/Bounded.lean index 0bbc10d2bcc9f..5ce1a3fd60a5e 100644 --- a/Mathlib/Topology/MetricSpace/Bounded.lean +++ b/Mathlib/Topology/MetricSpace/Bounded.lean @@ -16,7 +16,7 @@ This file contains one definition, and various results on boundedness in pseudo- Defined in terms of `EMetric.diam`, for better handling of the case when it should be infinite. * `isBounded_iff_subset_closedBall`: a non-empty set is bounded if and only if - it is is included in some closed ball + it is included in some closed ball * describing the cobounded filter, relating to the cocompact filter * `IsCompact.isBounded`: compact sets are bounded * `TotallyBounded.isBounded`: totally bounded sets are bounded diff --git a/Mathlib/Topology/MetricSpace/CauSeqFilter.lean b/Mathlib/Topology/MetricSpace/CauSeqFilter.lean index 8bf22f3af496b..c057c66bf50bb 100644 --- a/Mathlib/Topology/MetricSpace/CauSeqFilter.lean +++ b/Mathlib/Topology/MetricSpace/CauSeqFilter.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Robert Y. Lewis, Sébastien Gouëzel -/ import Mathlib.Analysis.Normed.Field.Basic +import Mathlib.Topology.MetricSpace.Cauchy /-! # Completeness in terms of `Cauchy` filters vs `isCauSeq` sequences diff --git a/Mathlib/Topology/MetricSpace/Cauchy.lean b/Mathlib/Topology/MetricSpace/Cauchy.lean index 7a51a0300765e..cec514c737140 100644 --- a/Mathlib/Topology/MetricSpace/Cauchy.lean +++ b/Mathlib/Topology/MetricSpace/Cauchy.lean @@ -88,7 +88,7 @@ theorem Metric.uniformCauchySeqOn_iff {γ : Type*} {F : β → γ → α} {s : S exact hab (hN b.fst hbl.ge b.snd hbr.ge x hx) /-- If the distance between `s n` and `s m`, `n ≤ m` is bounded above by `b n` -and `b` converges to zero, then `s` is a Cauchy sequence. -/ +and `b` converges to zero, then `s` is a Cauchy sequence. -/ theorem cauchySeq_of_le_tendsto_0' {s : β → α} (b : β → ℝ) (h : ∀ n m : β, n ≤ m → dist (s n) (s m) ≤ b n) (h₀ : Tendsto b atTop (𝓝 0)) : CauchySeq s := Metric.cauchySeq_iff'.2 fun ε ε0 => (h₀.eventually (gt_mem_nhds ε0)).exists.imp fun N hN n hn => @@ -97,7 +97,7 @@ theorem cauchySeq_of_le_tendsto_0' {s : β → α} (b : β → ℝ) _ < ε := hN /-- If the distance between `s n` and `s m`, `n, m ≥ N` is bounded above by `b N` -and `b` converges to zero, then `s` is a Cauchy sequence. -/ +and `b` converges to zero, then `s` is a Cauchy sequence. -/ theorem cauchySeq_of_le_tendsto_0 {s : β → α} (b : β → ℝ) (h : ∀ n m N : β, N ≤ n → N ≤ m → dist (s n) (s m) ≤ b N) (h₀ : Tendsto b atTop (𝓝 0)) : CauchySeq s := diff --git a/Mathlib/Topology/MetricSpace/Contracting.lean b/Mathlib/Topology/MetricSpace/Contracting.lean index 23dc6110e8e0c..2fcec8e182a86 100644 --- a/Mathlib/Topology/MetricSpace/Contracting.lean +++ b/Mathlib/Topology/MetricSpace/Contracting.lean @@ -130,7 +130,7 @@ theorem edist_efixedPoint_le (hf : ContractingWith K f) {x : α} (hx : edist x ( theorem edist_efixedPoint_lt_top (hf : ContractingWith K f) {x : α} (hx : edist x (f x) ≠ ∞) : edist x (efixedPoint f hf x hx) < ∞ := (hf.edist_efixedPoint_le hx).trans_lt - (ENNReal.mul_lt_top hx <| ENNReal.inv_ne_top.2 hf.one_sub_K_ne_zero) + (ENNReal.mul_ne_top hx <| ENNReal.inv_ne_top.2 hf.one_sub_K_ne_zero).lt_top theorem efixedPoint_eq_of_edist_lt_top (hf : ContractingWith K f) {x : α} (hx : edist x (f x) ≠ ∞) {y : α} (hy : edist y (f y) ≠ ∞) (h : edist x y ≠ ∞) : @@ -205,7 +205,7 @@ theorem edist_efixedPoint_lt_top' {s : Set α} (hsc : IsComplete s) (hsf : MapsT (hf : ContractingWith K <| hsf.restrict f s s) {x : α} (hxs : x ∈ s) (hx : edist x (f x) ≠ ∞) : edist x (efixedPoint' f hsc hsf hf x hxs hx) < ∞ := (hf.edist_efixedPoint_le' hsc hsf hxs hx).trans_lt - (ENNReal.mul_lt_top hx <| ENNReal.inv_ne_top.2 hf.one_sub_K_ne_zero) + (ENNReal.mul_ne_top hx <| ENNReal.inv_ne_top.2 hf.one_sub_K_ne_zero).lt_top /-- If a globally contracting map `f` has two complete forward-invariant sets `s`, `t`, and `x ∈ s` is at a finite distance from `y ∈ t`, then the `efixedPoint'` constructed by `x` @@ -247,7 +247,7 @@ theorem dist_le_mul (x y : α) : dist (f x) (f y) ≤ K * dist x y := theorem dist_inequality (x y) : dist x y ≤ (dist x (f x) + dist y (f y)) / (1 - K) := suffices dist x y ≤ dist x (f x) + dist y (f y) + K * dist x y by - rwa [le_div_iff hf.one_sub_K_pos, mul_comm, _root_.sub_mul, one_mul, sub_le_iff_le_add] + rwa [le_div_iff₀ hf.one_sub_K_pos, mul_comm, _root_.sub_mul, one_mul, sub_le_iff_le_add] calc dist x y ≤ dist x (f x) + dist y (f y) + dist (f x) (f y) := dist_triangle4_right _ _ _ _ _ ≤ dist x (f x) + dist y (f y) + K * dist x y := add_le_add_left (hf.dist_le_mul _ _) _ diff --git a/Mathlib/Topology/MetricSpace/Defs.lean b/Mathlib/Topology/MetricSpace/Defs.lean index fa1af58dc2f89..3ce13e989e61a 100644 --- a/Mathlib/Topology/MetricSpace/Defs.lean +++ b/Mathlib/Topology/MetricSpace/Defs.lean @@ -80,11 +80,11 @@ theorem dist_pos {x y : γ} : 0 < dist x y ↔ x ≠ y := by theorem eq_of_forall_dist_le {x y : γ} (h : ∀ ε > 0, dist x y ≤ ε) : x = y := eq_of_dist_eq_zero (eq_of_le_of_forall_le_of_dense dist_nonneg h) -/-- Deduce the equality of points from the vanishing of the nonnegative distance-/ +/-- Deduce the equality of points from the vanishing of the nonnegative distance -/ theorem eq_of_nndist_eq_zero {x y : γ} : nndist x y = 0 → x = y := by simp only [NNReal.eq_iff, ← dist_nndist, imp_self, NNReal.coe_zero, dist_eq_zero] -/-- Characterize the equality of points as the vanishing of the nonnegative distance-/ +/-- Characterize the equality of points as the vanishing of the nonnegative distance -/ @[simp] theorem nndist_eq_zero {x y : γ} : nndist x y = 0 ↔ x = y := by simp only [NNReal.eq_iff, ← dist_nndist, imp_self, NNReal.coe_zero, dist_eq_zero] @@ -116,8 +116,9 @@ end Metric /-- Build a new metric space from an old one where the bundled uniform structure is provably (but typically non-definitionaly) equal to some given uniform structure. See Note [forgetful inheritance]. +See Note [reducible non-instances]. -/ -def MetricSpace.replaceUniformity {γ} [U : UniformSpace γ] (m : MetricSpace γ) +abbrev MetricSpace.replaceUniformity {γ} [U : UniformSpace γ] (m : MetricSpace γ) (H : 𝓤[U] = 𝓤[PseudoEMetricSpace.toUniformSpace]) : MetricSpace γ where toPseudoMetricSpace := PseudoMetricSpace.replaceUniformity m.toPseudoMetricSpace H eq_of_dist_eq_zero := @eq_of_dist_eq_zero _ _ @@ -129,6 +130,7 @@ theorem MetricSpace.replaceUniformity_eq {γ} [U : UniformSpace γ] (m : MetricS /-- Build a new metric space from an old one where the bundled topological structure is provably (but typically non-definitionaly) equal to some given topological structure. See Note [forgetful inheritance]. +See Note [reducible non-instances]. -/ abbrev MetricSpace.replaceTopology {γ} [U : TopologicalSpace γ] (m : MetricSpace γ) (H : U = m.toPseudoMetricSpace.toUniformSpace.toTopologicalSpace) : MetricSpace γ := @@ -142,8 +144,9 @@ theorem MetricSpace.replaceTopology_eq {γ} [U : TopologicalSpace γ] (m : Metri /-- Build a new metric space from an old one where the bundled bornology structure is provably (but typically non-definitionaly) equal to some given bornology structure. See Note [forgetful inheritance]. +See Note [reducible non-instances]. -/ -def MetricSpace.replaceBornology {α} [B : Bornology α] (m : MetricSpace α) +abbrev MetricSpace.replaceBornology {α} [B : Bornology α] (m : MetricSpace α) (H : ∀ s, @IsBounded _ B s ↔ @IsBounded _ PseudoMetricSpace.toBornology s) : MetricSpace α := { PseudoMetricSpace.replaceBornology _ H, m with toBornology := B } diff --git a/Mathlib/Topology/MetricSpace/Gluing.lean b/Mathlib/Topology/MetricSpace/Gluing.lean index 9091ef227ff5c..53a7579e013fa 100644 --- a/Mathlib/Topology/MetricSpace/Gluing.lean +++ b/Mathlib/Topology/MetricSpace/Gluing.lean @@ -580,8 +580,7 @@ attribute [local instance] inductivePremetric def InductiveLimit (I : ∀ n, Isometry (f n)) : Type _ := @SeparationQuotient _ (inductivePremetric I).toUniformSpace.toTopologicalSpace -set_option autoImplicit true in -instance : MetricSpace (InductiveLimit (f := f) I) := +instance {I : ∀ (n : ℕ), Isometry (f n)} : MetricSpace (InductiveLimit (f := f) I) := inferInstanceAs <| MetricSpace <| @SeparationQuotient _ (inductivePremetric I).toUniformSpace.toTopologicalSpace diff --git a/Mathlib/Topology/MetricSpace/GromovHausdorff.lean b/Mathlib/Topology/MetricSpace/GromovHausdorff.lean index fbeb7156e42d0..acc49b78007c1 100644 --- a/Mathlib/Topology/MetricSpace/GromovHausdorff.lean +++ b/Mathlib/Topology/MetricSpace/GromovHausdorff.lean @@ -255,7 +255,7 @@ theorem hausdorffDist_optimal {X : Type u} [MetricSpace X] [CompactSpace X] [Non rcases exists_mem_of_nonempty X with ⟨xX, _⟩ have : ∃ y ∈ range Ψ, dist (Φ xX) y < diam (univ : Set X) + 1 + diam (univ : Set Y) := by rw [Ψrange] - have : Φ xX ∈ ↑p := Φrange.subst (mem_range_self _) + have : Φ xX ∈ (p : Set _) := Φrange ▸ (mem_range_self _) exact exists_dist_lt_of_hausdorffDist_lt this bound (hausdorffEdist_ne_top_of_nonempty_of_bounded p.nonempty q.nonempty @@ -315,7 +315,7 @@ theorem hausdorffDist_optimal {X : Type u} [MetricSpace X] [CompactSpace X] [Non refine le_trans this (le_of_forall_le_of_dense fun r hr => ?_) have I1 : ∀ x : X, (⨅ y, Fb (inl x, inr y)) ≤ r := by intro x - have : f (inl x) ∈ ↑p := Φrange.subst (mem_range_self _) + have : f (inl x) ∈ (p : Set _) := Φrange ▸ (mem_range_self _) rcases exists_dist_lt_of_hausdorffDist_lt this hr (hausdorffEdist_ne_top_of_nonempty_of_bounded p.nonempty q.nonempty p.isCompact.isBounded q.isCompact.isBounded) with @@ -331,7 +331,7 @@ theorem hausdorffDist_optimal {X : Type u} [MetricSpace X] [CompactSpace X] [Non have I2 : ∀ y : Y, (⨅ x, Fb (inl x, inr y)) ≤ r := by intro y - have : f (inr y) ∈ ↑q := Ψrange.subst (mem_range_self _) + have : f (inr y) ∈ (q : Set _) := Ψrange ▸ (mem_range_self _) rcases exists_dist_lt_of_hausdorffDist_lt' this hr (hausdorffEdist_ne_top_of_nonempty_of_bounded p.nonempty q.nonempty p.isCompact.isBounded q.isCompact.isBounded) with @@ -940,7 +940,7 @@ limit of the `Y n`, and finally let `Z` be the completion of `Z0`. The images `X2 n` of `X n` in `Z` are at Hausdorff distance `< 1/2^n` by construction, hence they form a Cauchy sequence for the Hausdorff distance. By completeness (of `Z`, and therefore of its set of nonempty compact subsets), they converge to a limit `L`. This is the nonempty -compact metric space we are looking for. -/ +compact metric space we are looking for. -/ variable (X : ℕ → Type) [∀ n, MetricSpace (X n)] [∀ n, CompactSpace (X n)] [∀ n, Nonempty (X n)] /-- Auxiliary structure used to glue metric spaces below, recording an isometric embedding diff --git a/Mathlib/Topology/MetricSpace/GromovHausdorffRealized.lean b/Mathlib/Topology/MetricSpace/GromovHausdorffRealized.lean index 73e63a878282e..f343b3d1c3901 100644 --- a/Mathlib/Topology/MetricSpace/GromovHausdorffRealized.lean +++ b/Mathlib/Topology/MetricSpace/GromovHausdorffRealized.lean @@ -100,7 +100,7 @@ private theorem maxVar_bound [CompactSpace X] [Nonempty X] [CompactSpace Y] [Non _ ≤ diam (range inl : Set (X ⊕ Y)) + dist (inl default) (inr default) + diam (range inr : Set (X ⊕ Y)) := (diam_union (mem_range_self _) (mem_range_self _)) - _ = diam (univ : Set X) + (dist default default + 1 + dist default default) + + _ = diam (univ : Set X) + (dist (α := X) default default + 1 + dist (α := Y) default default) + diam (univ : Set Y) := by rw [isometry_inl.diam_range, isometry_inr.diam_range] rfl @@ -142,10 +142,10 @@ private theorem candidates_dist_bound (fA : f ∈ candidates X Y) : | inl x, inl y => calc f (inl x, inl y) = dist x y := candidates_dist_inl fA x y - _ = dist (inl x) (inl y) := by + _ = dist (α := X ⊕ Y) (inl x) (inl y) := by rw [@Sum.dist_eq X Y] rfl - _ = 1 * dist (inl x) (inl y) := by ring + _ = 1 * dist (α := X ⊕ Y) (inl x) (inl y) := by ring _ ≤ maxVar X Y * dist (inl x) (inl y) := by gcongr; exact one_le_maxVar X Y | inl x, inr y => calc @@ -160,10 +160,10 @@ private theorem candidates_dist_bound (fA : f ∈ candidates X Y) : | inr x, inr y => calc f (inr x, inr y) = dist x y := candidates_dist_inr fA x y - _ = dist (inr x) (inr y) := by + _ = dist (α := X ⊕ Y) (inr x) (inr y) := by rw [@Sum.dist_eq X Y] rfl - _ = 1 * dist (inr x) (inr y) := by ring + _ = 1 * dist (α := X ⊕ Y) (inr x) (inr y) := by ring _ ≤ maxVar X Y * dist (inr x) (inr y) := by gcongr; exact one_le_maxVar X Y /-- Technical lemma to prove that candidates are Lipschitz -/ diff --git a/Mathlib/Topology/MetricSpace/HausdorffDimension.lean b/Mathlib/Topology/MetricSpace/HausdorffDimension.lean index d33c00ae8e600..98f606a3e4ad3 100644 --- a/Mathlib/Topology/MetricSpace/HausdorffDimension.lean +++ b/Mathlib/Topology/MetricSpace/HausdorffDimension.lean @@ -322,7 +322,7 @@ namespace LipschitzWith /-- If `f` is a Lipschitz continuous map, then `dimH (f '' s) ≤ dimH s`. -/ theorem dimH_image_le (h : LipschitzWith K f) (s : Set X) : dimH (f '' s) ≤ dimH s := - (h.lipschitzOnWith s).dimH_image_le + h.lipschitzOnWith.dimH_image_le /-- If `f` is a Lipschitz continuous map, then the Hausdorff dimension of its range is at most the Hausdorff dimension of its domain. -/ diff --git a/Mathlib/Topology/MetricSpace/Isometry.lean b/Mathlib/Topology/MetricSpace/Isometry.lean index b2464d0e4b65a..fc48af3ac67e9 100644 --- a/Mathlib/Topology/MetricSpace/Isometry.lean +++ b/Mathlib/Topology/MetricSpace/Isometry.lean @@ -28,7 +28,7 @@ open Function Set open scoped Topology ENNReal /-- An isometry (also known as isometric embedding) is a map preserving the edistance -between pseudoemetric spaces, or equivalently the distance between pseudometric space. -/ +between pseudoemetric spaces, or equivalently the distance between pseudometric space. -/ def Isometry [PseudoEMetricSpace α] [PseudoEMetricSpace β] (f : α → β) : Prop := ∀ x1 x2 : α, edist (f x1) (f x2) = edist x1 x2 diff --git a/Mathlib/Topology/MetricSpace/Polish.lean b/Mathlib/Topology/MetricSpace/Polish.lean index 5be13837cfe9c..75a904e112479 100644 --- a/Mathlib/Topology/MetricSpace/Polish.lean +++ b/Mathlib/Topology/MetricSpace/Polish.lean @@ -3,11 +3,12 @@ Copyright (c) 2022 Sébastien Gouëzel. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Sébastien Gouëzel -/ +import Mathlib.Analysis.Normed.Field.Basic +import Mathlib.Topology.Instances.Nat import Mathlib.Topology.MetricSpace.PiNat import Mathlib.Topology.MetricSpace.Isometry import Mathlib.Topology.MetricSpace.Gluing import Mathlib.Topology.Sets.Opens -import Mathlib.Analysis.Normed.Field.Basic /-! # Polish spaces @@ -315,8 +316,8 @@ instance instCompleteSpace [CompleteSpace α] : CompleteSpace (CompleteCopy s) : rw [← s.isOpen.isClosed_compl.not_mem_iff_infDist_pos ⟨x, xs⟩]; exact not_not.symm have I : ∀ n, 1 / C ≤ infDist (u n).1 sᶜ := fun n ↦ by have : 0 < infDist (u n).1 sᶜ := Hmem.1 (u n).2 - rw [div_le_iff' Cpos] - exact (div_le_iff this).1 (hC n).le + rw [div_le_iff₀' Cpos] + exact (div_le_iff₀ this).1 (hC n).le have I' : 1 / C ≤ infDist x sᶜ := have : Tendsto (fun n => infDist (u n).1 sᶜ) atTop (𝓝 (infDist x sᶜ)) := ((continuous_infDist_pt (sᶜ : Set α)).tendsto x).comp xlim @@ -328,7 +329,10 @@ theorem _root_.IsOpen.polishSpace {α : Type*} [TopologicalSpace α] [PolishSpac (hs : IsOpen s) : PolishSpace s := by letI := upgradePolishSpace α lift s to Opens α using hs - have : SecondCountableTopology s.CompleteCopy := inferInstanceAs (SecondCountableTopology s) + #adaptation_note /-- After lean4#5020, many instances for Lie algebras and manifolds are no + longer found. -/ + have : SecondCountableTopology s.CompleteCopy := + TopologicalSpace.Subtype.secondCountableTopology _ exact inferInstanceAs (PolishSpace s.CompleteCopy) end CompleteCopy @@ -365,7 +369,13 @@ theorem _root_.IsClosed.isClopenable [TopologicalSpace α] [PolishSpace α] {s : · rw [← f.induced_symm] exact f.symm.polishSpace_induced · rw [isOpen_coinduced, isOpen_sum_iff] - simp [f, preimage_preimage] + simp only [preimage_preimage, f] + have inl (x : s) : (Equiv.Set.sumCompl s) (Sum.inl x) = x := Equiv.Set.sumCompl_apply_inl .. + have inr (x : ↑sᶜ) : (Equiv.Set.sumCompl s) (Sum.inr x) = x := Equiv.Set.sumCompl_apply_inr .. + simp_rw [inl, inr, Subtype.coe_preimage_self] + simp only [isOpen_univ, true_and] + rw [Subtype.preimage_coe_compl'] + simp theorem IsClopenable.compl [TopologicalSpace α] {s : Set α} (hs : IsClopenable s) : IsClopenable sᶜ := by diff --git a/Mathlib/Topology/MetricSpace/Pseudo/Defs.lean b/Mathlib/Topology/MetricSpace/Pseudo/Defs.lean index 04ae492896a9c..cfaf85d8f63ea 100644 --- a/Mathlib/Topology/MetricSpace/Pseudo/Defs.lean +++ b/Mathlib/Topology/MetricSpace/Pseudo/Defs.lean @@ -263,15 +263,15 @@ theorem edist_lt_coe {x y : α} {c : ℝ≥0} : edist x y < c ↔ nndist x y < c theorem edist_le_coe {x y : α} {c : ℝ≥0} : edist x y ≤ c ↔ nndist x y ≤ c := by rw [edist_nndist, ENNReal.coe_le_coe] -/-- In a pseudometric space, the extended distance is always finite-/ +/-- In a pseudometric space, the extended distance is always finite -/ theorem edist_lt_top {α : Type*} [PseudoMetricSpace α] (x y : α) : edist x y < ⊤ := (edist_dist x y).symm ▸ ENNReal.ofReal_lt_top -/-- In a pseudometric space, the extended distance is always finite-/ +/-- In a pseudometric space, the extended distance is always finite -/ theorem edist_ne_top (x y : α) : edist x y ≠ ⊤ := (edist_lt_top x y).ne -/-- `nndist x x` vanishes-/ +/-- `nndist x x` vanishes -/ @[simp] theorem nndist_self (a : α) : nndist a a = 0 := NNReal.coe_eq_zero.1 (dist_self a) -- Porting note: `dist_nndist` and `coe_nndist` moved up @@ -299,7 +299,7 @@ theorem nndist_dist (x y : α) : nndist x y = Real.toNNReal (dist x y) := by theorem nndist_comm (x y : α) : nndist x y = nndist y x := NNReal.eq <| dist_comm x y -/-- Triangle inequality for the nonnegative distance-/ +/-- Triangle inequality for the nonnegative distance -/ theorem nndist_triangle (x y z : α) : nndist x z ≤ nndist x y + nndist y z := dist_triangle _ _ _ @@ -920,6 +920,7 @@ theorem Metric.emetric_ball_top (x : α) : EMetric.ball x ⊤ = univ := /-- Build a new pseudometric space from an old one where the bundled uniform structure is provably (but typically non-definitionaly) equal to some given uniform structure. See Note [forgetful inheritance]. +See Note [reducible non-instances]. -/ abbrev PseudoMetricSpace.replaceUniformity {α} [U : UniformSpace α] (m : PseudoMetricSpace α) (H : 𝓤[U] = 𝓤[PseudoEMetricSpace.toUniformSpace]) : PseudoMetricSpace α := @@ -935,11 +936,13 @@ theorem PseudoMetricSpace.replaceUniformity_eq {α} [U : UniformSpace α] (m : P -- ensure that the bornology is unchanged when replacing the uniformity. example {α} [U : UniformSpace α] (m : PseudoMetricSpace α) (H : 𝓤[U] = 𝓤[PseudoEMetricSpace.toUniformSpace]) : - (PseudoMetricSpace.replaceUniformity m H).toBornology = m.toBornology := rfl + (PseudoMetricSpace.replaceUniformity m H).toBornology = m.toBornology := by + with_reducible_and_instances rfl /-- Build a new pseudo metric space from an old one where the bundled topological structure is provably (but typically non-definitionaly) equal to some given topological structure. See Note [forgetful inheritance]. +See Note [reducible non-instances]. -/ abbrev PseudoMetricSpace.replaceTopology {γ} [U : TopologicalSpace γ] (m : PseudoMetricSpace γ) (H : U = m.toUniformSpace.toTopologicalSpace) : PseudoMetricSpace γ := @@ -982,6 +985,7 @@ abbrev PseudoEMetricSpace.toPseudoMetricSpace {α : Type u} [PseudoEMetricSpace /-- Build a new pseudometric space from an old one where the bundled bornology structure is provably (but typically non-definitionaly) equal to some given bornology structure. See Note [forgetful inheritance]. +See Note [reducible non-instances]. -/ abbrev PseudoMetricSpace.replaceBornology {α} [B : Bornology α] (m : PseudoMetricSpace α) (H : ∀ s, @IsBounded _ B s ↔ @IsBounded _ PseudoMetricSpace.toBornology s) : @@ -1000,7 +1004,8 @@ theorem PseudoMetricSpace.replaceBornology_eq {α} [m : PseudoMetricSpace α] [B -- ensure that the uniformity is unchanged when replacing the bornology. example {α} [B : Bornology α] (m : PseudoMetricSpace α) (H : ∀ s, @IsBounded _ B s ↔ @IsBounded _ PseudoMetricSpace.toBornology s) : - (PseudoMetricSpace.replaceBornology m H).toUniformSpace = m.toUniformSpace := rfl + (PseudoMetricSpace.replaceBornology m H).toUniformSpace = m.toUniformSpace := by + with_reducible_and_instances rfl section Real @@ -1078,7 +1083,7 @@ theorem dist_dist_dist_le (x y x' y' : α) : dist (dist x y) (dist x' y') ≤ di theorem nhds_comap_dist (a : α) : ((𝓝 (0 : ℝ)).comap (dist · a)) = 𝓝 a := by simp only [@nhds_eq_comap_uniformity α, Metric.uniformity_eq_comap_nhds_zero, comap_comap, - (· ∘ ·), dist_comm] + Function.comp_def, dist_comm] theorem tendsto_iff_dist_tendsto_zero {f : β → α} {x : Filter β} {a : α} : Tendsto f x (𝓝 a) ↔ Tendsto (fun b => dist (f b) a) x (𝓝 0) := by @@ -1091,7 +1096,7 @@ variable {x y z : α} {ε ε₁ ε₂ : ℝ} {s : Set α} theorem ball_subset_interior_closedBall : ball x ε ⊆ interior (closedBall x ε) := interior_maximal ball_subset_closedBall isOpen_ball -/-- ε-characterization of the closure in pseudometric spaces-/ +/-- ε-characterization of the closure in pseudometric spaces -/ theorem mem_closure_iff {s : Set α} {a : α} : a ∈ closure s ↔ ∀ ε > 0, ∃ b ∈ s, dist a b < ε := (mem_closure_iff_nhds_basis nhds_basis_ball).trans <| by simp only [mem_ball, dist_comm] diff --git a/Mathlib/Topology/MetricSpace/Sequences.lean b/Mathlib/Topology/MetricSpace/Sequences.lean index e407168843967..ed02f21cdebd7 100644 --- a/Mathlib/Topology/MetricSpace/Sequences.lean +++ b/Mathlib/Topology/MetricSpace/Sequences.lean @@ -7,7 +7,7 @@ import Mathlib.Topology.Sequences import Mathlib.Topology.MetricSpace.Bounded /-! -# Sequencial compacts in metric spaces +# Sequential compacts in metric spaces In this file we prove 2 versions of Bolzano-Weierstrass theorem for proper metric spaces. -/ diff --git a/Mathlib/Topology/Metrizable/Uniformity.lean b/Mathlib/Topology/Metrizable/Uniformity.lean index 5a7ca2208776e..51973d61b6486 100644 --- a/Mathlib/Topology/Metrizable/Uniformity.lean +++ b/Mathlib/Topology/Metrizable/Uniformity.lean @@ -154,7 +154,7 @@ theorem le_two_mul_dist_ofPreNNDist (d : X → X → ℝ≥0) (dist_self : ∀ x have hMl' : length (take M l) = M := (length_take _ _).trans (min_eq_left hMl.le) refine (ihn _ hMl _ _ _ hMl').trans ?_ convert hMs.1.out - rw [take_zipWith, take, take_succ, getElem?_append hMl, getElem?_eq_getElem hMl, + rw [take_zipWith, take, take_succ, getElem?_append_left hMl, getElem?_eq_getElem hMl, ← 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) @@ -225,7 +225,7 @@ protected theorem UniformSpace.metrizable_uniformity (X : Type*) [UniformSpace X refine PseudoMetricSpace.le_two_mul_dist_ofPreNNDist _ _ _ fun x₁ x₂ x₃ x₄ => ?_ by_cases H : ∃ n, (x₁, x₄) ∉ U n · refine (dif_pos H).trans_le ?_ - rw [← NNReal.div_le_iff' two_ne_zero, ← mul_one_div (_ ^ _), ← pow_succ] + rw [← div_le_iff₀' zero_lt_two, ← mul_one_div (_ ^ _), ← pow_succ] simp only [le_max_iff, hle_d, ← not_and_or] rintro ⟨h₁₂, h₂₃, h₃₄⟩ refine Nat.find_spec H (hU_comp (lt_add_one <| Nat.find H) ?_) @@ -240,9 +240,9 @@ protected theorem UniformSpace.metrizable_uniformity (X : Type*) [UniformSpace X · refine fun n _ => ⟨n + 1, trivial, fun x hx => ?_⟩ rw [mem_setOf_eq] at hx contrapose! hx - refine le_trans ?_ ((div_le_iff' (zero_lt_two' ℝ)).2 (hd_le x.1 x.2)) + refine le_trans ?_ ((div_le_iff₀' zero_lt_two).2 (hd_le x.1 x.2)) rwa [← NNReal.coe_two, ← NNReal.coe_div, ← NNReal.coe_pow, NNReal.coe_le_coe, pow_succ, - mul_one_div, NNReal.div_le_iff two_ne_zero, div_mul_cancel₀ _ (two_ne_zero' ℝ≥0), hle_d] + mul_one_div, div_le_iff₀ zero_lt_two, div_mul_cancel₀ _ two_ne_zero, hle_d] /-- A `PseudoMetricSpace` instance compatible with a given `UniformSpace` structure. -/ protected noncomputable def UniformSpace.pseudoMetricSpace (X : Type*) [UniformSpace X] diff --git a/Mathlib/Topology/NhdsSet.lean b/Mathlib/Topology/NhdsSet.lean index 5580d18fa47ef..3a3f45b2eeff7 100644 --- a/Mathlib/Topology/NhdsSet.lean +++ b/Mathlib/Topology/NhdsSet.lean @@ -144,7 +144,7 @@ theorem nhdsSet_insert (x : X) (s : Set X) : 𝓝ˢ (insert x s) = 𝓝 x ⊔ rw [insert_eq, nhdsSet_union, nhdsSet_singleton] /-- Preimage of a set neighborhood of `t` under a continuous map `f` is a set neighborhood of `s` -provided that `f` maps `s` to `t`. -/ +provided that `f` maps `s` to `t`. -/ theorem Continuous.tendsto_nhdsSet {f : X → Y} {t : Set Y} (hf : Continuous f) (hst : MapsTo f s t) : Tendsto f (𝓝ˢ s) (𝓝ˢ t) := ((hasBasis_nhdsSet s).tendsto_iff (hasBasis_nhdsSet t)).mpr fun U hU => diff --git a/Mathlib/Topology/OmegaCompletePartialOrder.lean b/Mathlib/Topology/OmegaCompletePartialOrder.lean index 7f45468c25312..688068bf6217c 100644 --- a/Mathlib/Topology/OmegaCompletePartialOrder.lean +++ b/Mathlib/Topology/OmegaCompletePartialOrder.lean @@ -49,7 +49,7 @@ theorem IsOpen.inter (s t : Set α) : IsOpen α s → IsOpen α t → IsOpen α theorem isOpen_sUnion (s : Set (Set α)) (hs : ∀ t ∈ s, IsOpen α t) : IsOpen α (⋃₀ s) := by simp only [IsOpen] at hs ⊢ - convert CompleteLattice.sSup_continuous' (setOf ⁻¹' s) hs + convert CompleteLattice.sSup_continuous' (setOf ⁻¹' s) hs using 2 simp only [sSup_apply, setOf_bijective.surjective.exists, exists_prop, mem_preimage, SetCoe.exists, iSup_Prop_eq, mem_setOf_eq, mem_sUnion] diff --git a/Mathlib/Topology/Order.lean b/Mathlib/Topology/Order.lean index 83b1b248e808d..e533cd6e15a09 100644 --- a/Mathlib/Topology/Order.lean +++ b/Mathlib/Topology/Order.lean @@ -864,8 +864,16 @@ theorem isOpen_iSup_iff {s : Set α} : IsOpen[⨆ i, t i] s ↔ ∀ i, IsOpen[t show s ∈ {s | IsOpen[iSup t] s} ↔ s ∈ { x : Set α | ∀ i : ι, IsOpen[t i] x } by simp [setOf_isOpen_iSup] +theorem isOpen_sSup_iff {s : Set α} {T : Set (TopologicalSpace α)} : + IsOpen[sSup T] s ↔ ∀ t ∈ T, IsOpen[t] s := by + simp only [sSup_eq_iSup, isOpen_iSup_iff] + set_option tactic.skipAssignedInstances false in theorem isClosed_iSup_iff {s : Set α} : IsClosed[⨆ i, t i] s ↔ ∀ i, IsClosed[t i] s := by simp [← @isOpen_compl_iff _ _ (⨆ i, t i), ← @isOpen_compl_iff _ _ (t _), isOpen_iSup_iff] +theorem isClosed_sSup_iff {s : Set α} {T : Set (TopologicalSpace α)} : + IsClosed[sSup T] s ↔ ∀ t ∈ T, IsClosed[t] s := by + simp only [sSup_eq_iSup, isClosed_iSup_iff] + end iInf diff --git a/Mathlib/Topology/Order/LeftRightNhds.lean b/Mathlib/Topology/Order/LeftRightNhds.lean index 626dbfd4cd1b9..8983e91b3b08f 100644 --- a/Mathlib/Topology/Order/LeftRightNhds.lean +++ b/Mathlib/Topology/Order/LeftRightNhds.lean @@ -5,7 +5,7 @@ Authors: Johannes Hölzl, Mario Carneiro, Yury Kudryashov -/ import Mathlib.Topology.Order.Basic -import Mathlib.Data.Set.Pointwise.Basic +import Mathlib.Algebra.Ring.Pointwise.Set /-! # Neighborhoods to the left and to the right on an `OrderTopology` diff --git a/Mathlib/Topology/Order/LowerUpperTopology.lean b/Mathlib/Topology/Order/LowerUpperTopology.lean index a1a516349e3ba..efe6bf46b486b 100644 --- a/Mathlib/Topology/Order/LowerUpperTopology.lean +++ b/Mathlib/Topology/Order/LowerUpperTopology.lean @@ -287,7 +287,7 @@ variable [LinearOrder α] [TopologicalSpace α] [IsLower α] lemma isTopologicalBasis_insert_univ_subbasis : IsTopologicalBasis (insert univ {s : Set α | ∃ a, (Ici a)ᶜ = s}) := - isTopologicalBasis_of_subbasis_of_inter (by rw [topology_eq α]; rfl) (by + isTopologicalBasis_of_subbasis_of_inter (by rw [topology_eq α, lower]) (by rintro _ ⟨b, rfl⟩ _ ⟨c, rfl⟩ use b ⊓ c rw [compl_Ici, compl_Ici, compl_Ici, Iio_inter_Iio]) @@ -300,7 +300,7 @@ variable [CompleteLinearOrder α] [t : TopologicalSpace α] [IsLower α] lemma isTopologicalSpace_basis (U : Set α) : IsOpen U ↔ U = univ ∨ ∃ a, (Ici a)ᶜ = U := by by_cases hU : U = univ - simp only [hU, isOpen_univ, compl_Ici, true_or] + · simp only [hU, isOpen_univ, compl_Ici, true_or] refine ⟨?_, isTopologicalBasis_insert_univ_subbasis.isOpen⟩ intro hO apply Or.inr diff --git a/Mathlib/Topology/Order/Monotone.lean b/Mathlib/Topology/Order/Monotone.lean index 367caf03ec925..0493d4d868c9c 100644 --- a/Mathlib/Topology/Order/Monotone.lean +++ b/Mathlib/Topology/Order/Monotone.lean @@ -28,66 +28,123 @@ variable [ConditionallyCompleteLinearOrder α] [TopologicalSpace α] [OrderTopol /-- A monotone function continuous at the supremum of a nonempty set sends this supremum to the supremum of the image of this set. -/ -theorem Monotone.map_sSup_of_continuousAt' {f : α → β} {A : Set α} (Cf : ContinuousAt f (sSup A)) - (Mf : Monotone f) (A_nonemp : A.Nonempty) (A_bdd : BddAbove A := by bddDefault) : +theorem MonotoneOn.map_csSup_of_continuousWithinAt {f : α → β} {A : Set α} + (Cf : ContinuousWithinAt f A (sSup A)) + (Mf : MonotoneOn f A) (A_nonemp : A.Nonempty) (A_bdd : BddAbove A := by bddDefault) : f (sSup A) = sSup (f '' A) := --This is a particular case of the more general `IsLUB.isLUB_of_tendsto` - .symm <| ((isLUB_csSup A_nonemp A_bdd).isLUB_of_tendsto (Mf.monotoneOn _) A_nonemp <| - Cf.mono_left inf_le_left).csSup_eq (A_nonemp.image f) + .symm <| ((isLUB_csSup A_nonemp A_bdd).isLUB_of_tendsto Mf A_nonemp <| + Cf.mono_left fun ⦃_⦄ a ↦ a).csSup_eq (A_nonemp.image f) + +/-- A monotone function continuous at the supremum of a nonempty set sends this supremum to +the supremum of the image of this set. -/ +theorem Monotone.map_csSup_of_continuousAt {f : α → β} {A : Set α} + (Cf : ContinuousAt f (sSup A)) (Mf : Monotone f) (A_nonemp : A.Nonempty) + (A_bdd : BddAbove A := by bddDefault) : f (sSup A) = sSup (f '' A) := + MonotoneOn.map_csSup_of_continuousWithinAt Cf.continuousWithinAt + (Mf.monotoneOn _) A_nonemp A_bdd + +@[deprecated (since := "2024-08-26")] alias Monotone.map_sSup_of_continuousAt' := + Monotone.map_csSup_of_continuousAt /-- A monotone function continuous at the indexed supremum over a nonempty `Sort` sends this indexed supremum to the indexed supremum of the composition. -/ -theorem Monotone.map_iSup_of_continuousAt' {ι : Sort*} [Nonempty ι] {f : α → β} {g : ι → α} +theorem Monotone.map_ciSup_of_continuousAt {ι : Sort*} [Nonempty ι] {f : α → β} {g : ι → α} (Cf : ContinuousAt f (iSup g)) (Mf : Monotone f) (bdd : BddAbove (range g) := by bddDefault) : f (⨆ i, g i) = ⨆ i, f (g i) := by - rw [iSup, Monotone.map_sSup_of_continuousAt' Cf Mf (range_nonempty g) bdd, ← range_comp, iSup] + rw [iSup, Monotone.map_csSup_of_continuousAt Cf Mf (range_nonempty g) bdd, ← range_comp, iSup] rfl +@[deprecated (since := "2024-08-26")] alias Monotone.map_iSup_of_continuousAt' := + Monotone.map_ciSup_of_continuousAt + +/-- A monotone function continuous at the infimum of a nonempty set sends this infimum to +the infimum of the image of this set. -/ +theorem MonotoneOn.map_csInf_of_continuousWithinAt {f : α → β} {A : Set α} + (Cf : ContinuousWithinAt f A (sInf A)) + (Mf : MonotoneOn f A) (A_nonemp : A.Nonempty) (A_bdd : BddBelow A := by bddDefault) : + f (sInf A) = sInf (f '' A) := + MonotoneOn.map_csSup_of_continuousWithinAt (α := αᵒᵈ) (β := βᵒᵈ) Cf Mf.dual A_nonemp A_bdd + /-- A monotone function continuous at the infimum of a nonempty set sends this infimum to the infimum of the image of this set. -/ -theorem Monotone.map_sInf_of_continuousAt' {f : α → β} {A : Set α} (Cf : ContinuousAt f (sInf A)) +theorem Monotone.map_csInf_of_continuousAt {f : α → β} {A : Set α} (Cf : ContinuousAt f (sInf A)) (Mf : Monotone f) (A_nonemp : A.Nonempty) (A_bdd : BddBelow A := by bddDefault) : f (sInf A) = sInf (f '' A) := - Monotone.map_sSup_of_continuousAt' (α := αᵒᵈ) (β := βᵒᵈ) Cf Mf.dual A_nonemp A_bdd + Monotone.map_csSup_of_continuousAt (α := αᵒᵈ) (β := βᵒᵈ) Cf Mf.dual A_nonemp A_bdd + +@[deprecated (since := "2024-08-26")] alias Monotone.map_sInf_of_continuousAt' := + Monotone.map_csInf_of_continuousAt /-- A monotone function continuous at the indexed infimum over a nonempty `Sort` sends this indexed infimum to the indexed infimum of the composition. -/ -theorem Monotone.map_iInf_of_continuousAt' {ι : Sort*} [Nonempty ι] {f : α → β} {g : ι → α} +theorem Monotone.map_ciInf_of_continuousAt {ι : Sort*} [Nonempty ι] {f : α → β} {g : ι → α} (Cf : ContinuousAt f (iInf g)) (Mf : Monotone f) (bdd : BddBelow (range g) := by bddDefault) : f (⨅ i, g i) = ⨅ i, f (g i) := by - rw [iInf, Monotone.map_sInf_of_continuousAt' Cf Mf (range_nonempty g) bdd, ← range_comp, iInf] + rw [iInf, Monotone.map_csInf_of_continuousAt Cf Mf (range_nonempty g) bdd, ← range_comp, iInf] rfl +@[deprecated (since := "2024-08-26")] alias Monotone.map_iInf_of_continuousAt' := + Monotone.map_ciInf_of_continuousAt + +/-- An antitone function continuous at the infimum of a nonempty set sends this infimum to +the supremum of the image of this set. -/ +theorem AntitoneOn.map_csInf_of_continuousWithinAt {f : α → β} {A : Set α} + (Cf : ContinuousWithinAt f A (sInf A)) + (Af : AntitoneOn f A) (A_nonemp : A.Nonempty) (A_bdd : BddBelow A := by bddDefault) : + f (sInf A) = sSup (f '' A) := + MonotoneOn.map_csInf_of_continuousWithinAt (β := βᵒᵈ) Cf Af.dual_right A_nonemp A_bdd + /-- An antitone function continuous at the infimum of a nonempty set sends this infimum to the supremum of the image of this set. -/ -theorem Antitone.map_sInf_of_continuousAt' {f : α → β} {A : Set α} (Cf : ContinuousAt f (sInf A)) +theorem Antitone.map_csInf_of_continuousAt {f : α → β} {A : Set α} (Cf : ContinuousAt f (sInf A)) (Af : Antitone f) (A_nonemp : A.Nonempty) (A_bdd : BddBelow A := by bddDefault) : f (sInf A) = sSup (f '' A) := - Monotone.map_sInf_of_continuousAt' (β := βᵒᵈ) Cf Af.dual_right A_nonemp A_bdd + Monotone.map_csInf_of_continuousAt (β := βᵒᵈ) Cf Af.dual_right A_nonemp A_bdd + +@[deprecated (since := "2024-08-26")] alias Antitone.map_sInf_of_continuousAt' := + Antitone.map_csInf_of_continuousAt /-- An antitone function continuous at the indexed infimum over a nonempty `Sort` sends this indexed infimum to the indexed supremum of the composition. -/ -theorem Antitone.map_iInf_of_continuousAt' {ι : Sort*} [Nonempty ι] {f : α → β} {g : ι → α} +theorem Antitone.map_ciInf_of_continuousAt {ι : Sort*} [Nonempty ι] {f : α → β} {g : ι → α} (Cf : ContinuousAt f (iInf g)) (Af : Antitone f) (bdd : BddBelow (range g) := by bddDefault) : f (⨅ i, g i) = ⨆ i, f (g i) := by - rw [iInf, Antitone.map_sInf_of_continuousAt' Cf Af (range_nonempty g) bdd, ← range_comp, iSup] + rw [iInf, Antitone.map_csInf_of_continuousAt Cf Af (range_nonempty g) bdd, ← range_comp, iSup] rfl +@[deprecated (since := "2024-08-26")] alias Antitone.map_iInf_of_continuousAt' := + Antitone.map_ciInf_of_continuousAt + +/-- An antitone function continuous at the supremum of a nonempty set sends this supremum to +the infimum of the image of this set. -/ +theorem AntitoneOn.map_csSup_of_continuousWithinAt {f : α → β} {A : Set α} + (Cf : ContinuousWithinAt f A (sSup A)) + (Af : AntitoneOn f A) (A_nonemp : A.Nonempty) (A_bdd : BddAbove A := by bddDefault) : + f (sSup A) = sInf (f '' A) := + MonotoneOn.map_csSup_of_continuousWithinAt (β := βᵒᵈ) Cf Af.dual_right A_nonemp A_bdd + /-- An antitone function continuous at the supremum of a nonempty set sends this supremum to the infimum of the image of this set. -/ -theorem Antitone.map_sSup_of_continuousAt' {f : α → β} {A : Set α} (Cf : ContinuousAt f (sSup A)) +theorem Antitone.map_csSup_of_continuousAt {f : α → β} {A : Set α} (Cf : ContinuousAt f (sSup A)) (Af : Antitone f) (A_nonemp : A.Nonempty) (A_bdd : BddAbove A := by bddDefault) : f (sSup A) = sInf (f '' A) := - Monotone.map_sSup_of_continuousAt' (β := βᵒᵈ) Cf Af.dual_right A_nonemp A_bdd + Monotone.map_csSup_of_continuousAt (β := βᵒᵈ) Cf Af.dual_right A_nonemp A_bdd + +@[deprecated (since := "2024-08-26")] alias Antitone.map_sSup_of_continuousAt' := + Antitone.map_csSup_of_continuousAt /-- An antitone function continuous at the indexed supremum over a nonempty `Sort` sends this indexed supremum to the indexed infimum of the composition. -/ -theorem Antitone.map_iSup_of_continuousAt' {ι : Sort*} [Nonempty ι] {f : α → β} {g : ι → α} +theorem Antitone.map_ciSup_of_continuousAt {ι : Sort*} [Nonempty ι] {f : α → β} {g : ι → α} (Cf : ContinuousAt f (iSup g)) (Af : Antitone f) (bdd : BddAbove (range g) := by bddDefault) : f (⨆ i, g i) = ⨅ i, f (g i) := by - rw [iSup, Antitone.map_sSup_of_continuousAt' Cf Af (range_nonempty g) bdd, ← range_comp, iInf] + rw [iSup, Antitone.map_csSup_of_continuousAt Cf Af (range_nonempty g) bdd, ← range_comp, iInf] rfl +@[deprecated (since := "2024-08-26")] alias Antitone.map_iSup_of_continuousAt' := + Antitone.map_ciSup_of_continuousAt + end ConditionallyCompleteLinearOrder section CompleteLinearOrder @@ -109,11 +166,18 @@ theorem IsClosed.sInf_mem {s : Set α} (hs : s.Nonempty) (hc : IsClosed s) : sIn /-- A monotone function `f` sending `bot` to `bot` and continuous at the supremum of a set sends this supremum to the supremum of the image of this set. -/ -theorem Monotone.map_sSup_of_continuousAt {f : α → β} {s : Set α} (Cf : ContinuousAt f (sSup s)) - (Mf : Monotone f) (fbot : f ⊥ = ⊥) : f (sSup s) = sSup (f '' s) := by +theorem MonotoneOn.map_sSup_of_continuousWithinAt {f : α → β} {s : Set α} + (Cf : ContinuousWithinAt f s (sSup s)) + (Mf : MonotoneOn f s) (fbot : f ⊥ = ⊥) : f (sSup s) = sSup (f '' s) := by rcases s.eq_empty_or_nonempty with h | h · simp [h, fbot] - · exact Mf.map_sSup_of_continuousAt' Cf h + · exact Mf.map_csSup_of_continuousWithinAt Cf h + +/-- A monotone function `f` sending `bot` to `bot` and continuous at the supremum of a set sends +this supremum to the supremum of the image of this set. -/ +theorem Monotone.map_sSup_of_continuousAt {f : α → β} {s : Set α} (Cf : ContinuousAt f (sSup s)) + (Mf : Monotone f) (fbot : f ⊥ = ⊥) : f (sSup s) = sSup (f '' s) := + MonotoneOn.map_sSup_of_continuousWithinAt Cf.continuousWithinAt (Mf.monotoneOn _) fbot /-- If a monotone function sending `bot` to `bot` is continuous at the indexed supremum over a `Sort`, then it sends this indexed supremum to the indexed supremum of the composition. -/ @@ -122,6 +186,13 @@ theorem Monotone.map_iSup_of_continuousAt {ι : Sort*} {f : α → β} {g : ι f (⨆ i, g i) = ⨆ i, f (g i) := by rw [iSup, Mf.map_sSup_of_continuousAt Cf fbot, ← range_comp, iSup]; rfl +/-- A monotone function `f` sending `top` to `top` and continuous at the infimum of a set sends +this infimum to the infimum of the image of this set. -/ +theorem MonotoneOn.map_sInf_of_continuousWithinAt {f : α → β} {s : Set α} + (Cf : ContinuousWithinAt f s (sInf s)) (Mf : MonotoneOn f s) (ftop : f ⊤ = ⊤) : + f (sInf s) = sInf (f '' s) := + MonotoneOn.map_sSup_of_continuousWithinAt (α := αᵒᵈ) (β := βᵒᵈ) Cf Mf.dual ftop + /-- A monotone function `f` sending `top` to `top` and continuous at the infimum of a set sends this infimum to the infimum of the image of this set. -/ theorem Monotone.map_sInf_of_continuousAt {f : α → β} {s : Set α} (Cf : ContinuousAt f (sInf s)) @@ -134,6 +205,14 @@ theorem Monotone.map_iInf_of_continuousAt {ι : Sort*} {f : α → β} {g : ι (Cf : ContinuousAt f (iInf g)) (Mf : Monotone f) (ftop : f ⊤ = ⊤) : f (iInf g) = iInf (f ∘ g) := Monotone.map_iSup_of_continuousAt (α := αᵒᵈ) (β := βᵒᵈ) Cf Mf.dual ftop +/-- An antitone function `f` sending `bot` to `top` and continuous at the supremum of a set sends +this supremum to the infimum of the image of this set. -/ +theorem AntitoneOn.map_sSup_of_continuousWithinAt {f : α → β} {s : Set α} + (Cf : ContinuousWithinAt f s (sSup s)) (Af : AntitoneOn f s) (fbot : f ⊥ = ⊤) : + f (sSup s) = sInf (f '' s) := + MonotoneOn.map_sSup_of_continuousWithinAt + (show ContinuousWithinAt (OrderDual.toDual ∘ f) s (sSup s) from Cf) Af fbot + /-- An antitone function `f` sending `bot` to `top` and continuous at the supremum of a set sends this supremum to the infimum of the image of this set. -/ theorem Antitone.map_sSup_of_continuousAt {f : α → β} {s : Set α} (Cf : ContinuousAt f (sSup s)) @@ -149,6 +228,14 @@ theorem Antitone.map_iSup_of_continuousAt {ι : Sort*} {f : α → β} {g : ι Monotone.map_iSup_of_continuousAt (show ContinuousAt (OrderDual.toDual ∘ f) (iSup g) from Cf) Af fbot +/-- An antitone function `f` sending `top` to `bot` and continuous at the infimum of a set sends +this infimum to the supremum of the image of this set. -/ +theorem AntitoneOn.map_sInf_of_continuousWithinAt {f : α → β} {s : Set α} + (Cf : ContinuousWithinAt f s (sInf s)) (Af : AntitoneOn f s) (ftop : f ⊤ = ⊥) : + f (sInf s) = sSup (f '' s) := + MonotoneOn.map_sInf_of_continuousWithinAt + (show ContinuousWithinAt (OrderDual.toDual ∘ f) s (sInf s) from Cf) Af ftop + /-- An antitone function `f` sending `top` to `bot` and continuous at the infimum of a set sends this infimum to the supremum of the image of this set. -/ theorem Antitone.map_sInf_of_continuousAt {f : α → β} {s : Set α} (Cf : ContinuousAt f (sInf s)) @@ -192,72 +279,60 @@ theorem IsClosed.isGreatest_csSup {s : Set α} (hc : IsClosed s) (hs : s.Nonempt IsGreatest s (sSup s) := IsClosed.isLeast_csInf (α := αᵒᵈ) hc hs B -/-- If a monotone function is continuous at the supremum of a nonempty bounded above set `s`, -then it sends this supremum to the supremum of the image of `s`. -/ -theorem Monotone.map_csSup_of_continuousAt {f : α → β} {s : Set α} (Cf : ContinuousAt f (sSup s)) - (Mf : Monotone f) (ne : s.Nonempty) (H : BddAbove s) : f (sSup s) = sSup (f '' s) := by - refine ((isLUB_csSup (ne.image f) (Mf.map_bddAbove H)).unique ?_).symm - refine (isLUB_csSup ne H).isLUB_of_tendsto (fun x _ y _ xy => Mf xy) ne ?_ - exact Cf.mono_left inf_le_left - -/-- If a monotone function is continuous at the indexed supremum of a bounded function on -a nonempty `Sort`, then it sends this supremum to the supremum of the composition. -/ -theorem Monotone.map_ciSup_of_continuousAt {f : α → β} {g : γ → α} (Cf : ContinuousAt f (⨆ i, g i)) - (Mf : Monotone f) (H : BddAbove (range g)) : f (⨆ i, g i) = ⨆ i, f (g i) := by - rw [iSup, Mf.map_csSup_of_continuousAt Cf (range_nonempty _) H, ← range_comp, iSup]; rfl - -/-- If a monotone function is continuous at the infimum of a nonempty bounded below set `s`, -then it sends this infimum to the infimum of the image of `s`. -/ -theorem Monotone.map_csInf_of_continuousAt {f : α → β} {s : Set α} (Cf : ContinuousAt f (sInf s)) - (Mf : Monotone f) (ne : s.Nonempty) (H : BddBelow s) : f (sInf s) = sInf (f '' s) := - Monotone.map_csSup_of_continuousAt (α := αᵒᵈ) (β := βᵒᵈ) Cf Mf.dual ne H - -/-- A continuous monotone function sends indexed infimum to indexed infimum in conditionally -complete linear order, under a boundedness assumption. -/ -theorem Monotone.map_ciInf_of_continuousAt {f : α → β} {g : γ → α} (Cf : ContinuousAt f (⨅ i, g i)) - (Mf : Monotone f) (H : BddBelow (range g)) : f (⨅ i, g i) = ⨅ i, f (g i) := - Monotone.map_ciSup_of_continuousAt (α := αᵒᵈ) (β := βᵒᵈ) Cf Mf.dual H - -/-- If an antitone function is continuous at the supremum of a nonempty bounded above set `s`, -then it sends this supremum to the infimum of the image of `s`. -/ -theorem Antitone.map_csSup_of_continuousAt {f : α → β} {s : Set α} (Cf : ContinuousAt f (sSup s)) - (Af : Antitone f) (ne : s.Nonempty) (H : BddAbove s) : f (sSup s) = sInf (f '' s) := - Monotone.map_csSup_of_continuousAt (show ContinuousAt (OrderDual.toDual ∘ f) (sSup s) from Cf) Af - ne H - -/-- If an antitone function is continuous at the indexed supremum of a bounded function on -a nonempty `Sort`, then it sends this supremum to the infimum of the composition. -/ -theorem Antitone.map_ciSup_of_continuousAt {f : α → β} {g : γ → α} (Cf : ContinuousAt f (⨆ i, g i)) - (Af : Antitone f) (H : BddAbove (range g)) : f (⨆ i, g i) = ⨅ i, f (g i) := - Monotone.map_ciSup_of_continuousAt (show ContinuousAt (OrderDual.toDual ∘ f) (⨆ i, g i) from Cf) - Af H - -/-- If an antitone function is continuous at the infimum of a nonempty bounded below set `s`, -then it sends this infimum to the supremum of the image of `s`. -/ -theorem Antitone.map_csInf_of_continuousAt {f : α → β} {s : Set α} (Cf : ContinuousAt f (sInf s)) - (Af : Antitone f) (ne : s.Nonempty) (H : BddBelow s) : f (sInf s) = sSup (f '' s) := - Monotone.map_csInf_of_continuousAt (show ContinuousAt (OrderDual.toDual ∘ f) (sInf s) from Cf) Af - ne H - -/-- A continuous antitone function sends indexed infimum to indexed supremum in conditionally -complete linear order, under a boundedness assumption. -/ -theorem Antitone.map_ciInf_of_continuousAt {f : α → β} {g : γ → α} (Cf : ContinuousAt f (⨅ i, g i)) - (Af : Antitone f) (H : BddBelow (range g)) : f (⨅ i, g i) = ⨆ i, f (g i) := - Monotone.map_ciInf_of_continuousAt (show ContinuousAt (OrderDual.toDual ∘ f) (⨅ i, g i) from Cf) - Af H - -/-- A monotone map has a limit to the left of any point `x`, equal to `sSup (f '' (Iio x))`. -/ -theorem Monotone.tendsto_nhdsWithin_Iio {α β : Type*} [LinearOrder α] [TopologicalSpace α] +lemma MonotoneOn.tendsto_nhdsWithin_Ioo_left {α β : Type*} [LinearOrder α] [TopologicalSpace α] [OrderTopology α] [ConditionallyCompleteLinearOrder β] [TopologicalSpace β] [OrderTopology β] - {f : α → β} (Mf : Monotone f) (x : α) : Tendsto f (𝓝[<] x) (𝓝 (sSup (f '' Iio x))) := by + {f : α → β} {x y : α} (h_nonempty : (Ioo y x).Nonempty) (Mf : MonotoneOn f (Ioo y x)) + (h_bdd : BddAbove (f '' Ioo y x)) : + Tendsto f (𝓝[<] x) (𝓝 (sSup (f '' Ioo y x))) := by + refine tendsto_order.2 ⟨fun l hl => ?_, fun m hm => ?_⟩ + · obtain ⟨z, ⟨yz, zx⟩, lz⟩ : ∃ a : α, a ∈ Ioo y x ∧ l < f a := by + simpa only [mem_image, exists_prop, exists_exists_and_eq_and] using + exists_lt_of_lt_csSup (h_nonempty.image _) hl + refine mem_of_superset (Ioo_mem_nhdsWithin_Iio' zx) fun w hw => ?_ + exact lz.trans_le <| Mf ⟨yz, zx⟩ ⟨yz.trans_le hw.1.le, hw.2⟩ hw.1.le + · rcases h_nonempty with ⟨_, hy, hx⟩ + refine mem_of_superset (Ioo_mem_nhdsWithin_Iio' (hy.trans hx)) fun w hw => lt_of_le_of_lt ?_ hm + exact le_csSup h_bdd (mem_image_of_mem _ hw) + +lemma MonotoneOn.tendsto_nhdsWithin_Ioo_right {α β : Type*} [LinearOrder α] [TopologicalSpace α] + [OrderTopology α] [ConditionallyCompleteLinearOrder β] [TopologicalSpace β] [OrderTopology β] + {f : α → β} {x y : α} (h_nonempty : (Ioo x y).Nonempty) (Mf : MonotoneOn f (Ioo x y)) + (h_bdd : BddBelow (f '' Ioo x y)) : + Tendsto f (𝓝[>] x) (𝓝 (sInf (f '' Ioo x y))) := by + refine tendsto_order.2 ⟨fun l hl => ?_, fun m hm => ?_⟩ + · rcases h_nonempty with ⟨p, hy, hx⟩ + refine mem_of_superset (Ioo_mem_nhdsWithin_Ioi' (hy.trans hx)) fun w hw => hl.trans_le ?_ + exact csInf_le h_bdd (mem_image_of_mem _ hw) + · obtain ⟨z, ⟨xz, zy⟩, zm⟩ : ∃ a : α, a ∈ Ioo x y ∧ f a < m := by + simpa [mem_image, exists_prop, exists_exists_and_eq_and] using + exists_lt_of_csInf_lt (h_nonempty.image _) hm + refine mem_of_superset (Ioo_mem_nhdsWithin_Ioi' xz) fun w hw => ?_ + exact (Mf ⟨hw.1, hw.2.trans zy⟩ ⟨xz, zy⟩ hw.2.le).trans_lt zm + +lemma MonotoneOn.tendsto_nhdsWithin_Iio {α β : Type*} [LinearOrder α] [TopologicalSpace α] + [OrderTopology α] [ConditionallyCompleteLinearOrder β] [TopologicalSpace β] [OrderTopology β] + {f : α → β} {x : α} (Mf : MonotoneOn f (Iio x)) (h_bdd : BddAbove (f '' Iio x)) : + Tendsto f (𝓝[<] x) (𝓝 (sSup (f '' Iio x))) := by rcases eq_empty_or_nonempty (Iio x) with (h | h); · simp [h] refine tendsto_order.2 ⟨fun l hl => ?_, fun m hm => ?_⟩ · obtain ⟨z, zx, lz⟩ : ∃ a : α, a < x ∧ l < f a := by simpa only [mem_image, exists_prop, exists_exists_and_eq_and] using exists_lt_of_lt_csSup (h.image _) hl - exact mem_of_superset (Ioo_mem_nhdsWithin_Iio' zx) fun y hy => lz.trans_le (Mf hy.1.le) - · refine mem_of_superset self_mem_nhdsWithin fun _ hy => lt_of_le_of_lt ?_ hm - exact le_csSup (Mf.map_bddAbove bddAbove_Iio) (mem_image_of_mem _ hy) + exact mem_of_superset (Ioo_mem_nhdsWithin_Iio' zx) fun y hy => lz.trans_le (Mf zx hy.2 hy.1.le) + · refine mem_of_superset self_mem_nhdsWithin fun y hy => lt_of_le_of_lt ?_ hm + exact le_csSup h_bdd (mem_image_of_mem _ hy) + +lemma MonotoneOn.tendsto_nhdsWithin_Ioi {α β : Type*} [LinearOrder α] [TopologicalSpace α] + [OrderTopology α] [ConditionallyCompleteLinearOrder β] [TopologicalSpace β] [OrderTopology β] + {f : α → β} {x : α} (Mf : MonotoneOn f (Ioi x)) (h_bdd : BddBelow (f '' Ioi x)) : + Tendsto f (𝓝[>] x) (𝓝 (sInf (f '' Ioi x))) := + MonotoneOn.tendsto_nhdsWithin_Iio (α := αᵒᵈ) (β := βᵒᵈ) Mf.dual h_bdd + +/-- A monotone map has a limit to the left of any point `x`, equal to `sSup (f '' (Iio x))`. -/ +theorem Monotone.tendsto_nhdsWithin_Iio {α β : Type*} [LinearOrder α] [TopologicalSpace α] + [OrderTopology α] [ConditionallyCompleteLinearOrder β] [TopologicalSpace β] [OrderTopology β] + {f : α → β} (Mf : Monotone f) (x : α) : Tendsto f (𝓝[<] x) (𝓝 (sSup (f '' Iio x))) := + MonotoneOn.tendsto_nhdsWithin_Iio (Mf.monotoneOn _) (Mf.map_bddAbove bddAbove_Iio) /-- A monotone map has a limit to the right of any point `x`, equal to `sInf (f '' (Ioi x))`. -/ theorem Monotone.tendsto_nhdsWithin_Ioi {α β : Type*} [LinearOrder α] [TopologicalSpace α] @@ -265,4 +340,42 @@ theorem Monotone.tendsto_nhdsWithin_Ioi {α β : Type*} [LinearOrder α] [Topolo {f : α → β} (Mf : Monotone f) (x : α) : Tendsto f (𝓝[>] x) (𝓝 (sInf (f '' Ioi x))) := Monotone.tendsto_nhdsWithin_Iio (α := αᵒᵈ) (β := βᵒᵈ) Mf.dual x +lemma AntitoneOn.tendsto_nhdsWithin_Ioo_left {α β : Type*} [LinearOrder α] [TopologicalSpace α] + [OrderTopology α] [ConditionallyCompleteLinearOrder β] [TopologicalSpace β] [OrderTopology β] + {f : α → β} {x y : α} (h_nonempty : (Ioo y x).Nonempty) (Af : AntitoneOn f (Ioo y x)) + (h_bdd : BddBelow (f '' Ioo y x)) : + Tendsto f (𝓝[<] x) (𝓝 (sInf (f '' Ioo y x))) := + MonotoneOn.tendsto_nhdsWithin_Ioo_left h_nonempty Af.dual_right h_bdd + +lemma AntitoneOn.tendsto_nhdsWithin_Ioo_right {α β : Type*} [LinearOrder α] [TopologicalSpace α] + [OrderTopology α] [ConditionallyCompleteLinearOrder β] [TopologicalSpace β] [OrderTopology β] + {f : α → β} {x y : α} (h_nonempty : (Ioo x y).Nonempty) (Af : AntitoneOn f (Ioo x y)) + (h_bdd : BddAbove (f '' Ioo x y)) : + Tendsto f (𝓝[>] x) (𝓝 (sSup (f '' Ioo x y))) := + MonotoneOn.tendsto_nhdsWithin_Ioo_right h_nonempty Af.dual_right h_bdd + +lemma AntitoneOn.tendsto_nhdsWithin_Iio {α β : Type*} [LinearOrder α] [TopologicalSpace α] + [OrderTopology α] [ConditionallyCompleteLinearOrder β] [TopologicalSpace β] [OrderTopology β] + {f : α → β} {x : α} (Af : AntitoneOn f (Iio x)) (h_bdd : BddBelow (f '' Iio x)) : + Tendsto f (𝓝[<] x) (𝓝 (sInf (f '' Iio x))) := + MonotoneOn.tendsto_nhdsWithin_Iio Af.dual_right h_bdd + +lemma AntitoneOn.tendsto_nhdsWithin_Ioi {α β : Type*} [LinearOrder α] [TopologicalSpace α] + [OrderTopology α] [ConditionallyCompleteLinearOrder β] [TopologicalSpace β] [OrderTopology β] + {f : α → β} {x : α} (Af : AntitoneOn f (Ioi x)) (h_bdd : BddAbove (f '' Ioi x)) : + Tendsto f (𝓝[>] x) (𝓝 (sSup (f '' Ioi x))) := + MonotoneOn.tendsto_nhdsWithin_Ioi Af.dual_right h_bdd + +/-- An antitone map has a limit to the left of any point `x`, equal to `sInf (f '' (Iio x))`. -/ +theorem Antitone.tendsto_nhdsWithin_Iio {α β : Type*} [LinearOrder α] [TopologicalSpace α] + [OrderTopology α] [ConditionallyCompleteLinearOrder β] [TopologicalSpace β] [OrderTopology β] + {f : α → β} (Af : Antitone f) (x : α) : Tendsto f (𝓝[<] x) (𝓝 (sInf (f '' Iio x))) := + Monotone.tendsto_nhdsWithin_Iio Af.dual_right x + +/-- An antitone map has a limit to the right of any point `x`, equal to `sSup (f '' (Ioi x))`. -/ +theorem Antitone.tendsto_nhdsWithin_Ioi {α β : Type*} [LinearOrder α] [TopologicalSpace α] + [OrderTopology α] [ConditionallyCompleteLinearOrder β] [TopologicalSpace β] [OrderTopology β] + {f : α → β} (Af : Antitone f) (x : α) : Tendsto f (𝓝[>] x) (𝓝 (sSup (f '' Ioi x))) := + Monotone.tendsto_nhdsWithin_Ioi Af.dual_right x + end ConditionallyCompleteLinearOrder diff --git a/Mathlib/Topology/Order/UpperLowerSetTopology.lean b/Mathlib/Topology/Order/UpperLowerSetTopology.lean index ff3fc1e7a3de2..5aa350f222cbb 100644 --- a/Mathlib/Topology/Order/UpperLowerSetTopology.lean +++ b/Mathlib/Topology/Order/UpperLowerSetTopology.lean @@ -74,10 +74,10 @@ def WithUpperSet (α : Type*) := α namespace WithUpperSet -/-- `toUpperSet` is the identity function to the `WithUpperSet` of a type. -/ +/-- `toUpperSet` is the identity function to the `WithUpperSet` of a type. -/ @[match_pattern] def toUpperSet : α ≃ WithUpperSet α := Equiv.refl _ -/-- `ofUpperSet` is the identity function from the `WithUpperSet` of a type. -/ +/-- `ofUpperSet` is the identity function from the `WithUpperSet` of a type. -/ @[match_pattern] def ofUpperSet : WithUpperSet α ≃ α := Equiv.refl _ @[simp] lemma to_WithUpperSet_symm_eq : (@toUpperSet α).symm = ofUpperSet := rfl @@ -120,10 +120,10 @@ def WithLowerSet (α : Type*) := α namespace WithLowerSet -/-- `toLowerSet` is the identity function to the `WithLowerSet` of a type. -/ +/-- `toLowerSet` is the identity function to the `WithLowerSet` of a type. -/ @[match_pattern] def toLowerSet : α ≃ WithLowerSet α := Equiv.refl _ -/-- `ofLowerSet` is the identity function from the `WithLowerSet` of a type. -/ +/-- `ofLowerSet` is the identity function from the `WithLowerSet` of a type. -/ @[match_pattern] def ofLowerSet : WithLowerSet α ≃ α := Equiv.refl _ @[simp] lemma to_WithLowerSet_symm_eq : (@toLowerSet α).symm = ofLowerSet := rfl diff --git a/Mathlib/Topology/PartialHomeomorph.lean b/Mathlib/Topology/PartialHomeomorph.lean index ee0f1334ee46f..75f77fa794bf8 100644 --- a/Mathlib/Topology/PartialHomeomorph.lean +++ b/Mathlib/Topology/PartialHomeomorph.lean @@ -210,11 +210,6 @@ theorem replaceEquiv_eq_self (e' : PartialEquiv X Y) theorem source_preimage_target : e.source ⊆ e ⁻¹' e.target := e.mapsTo -@[deprecated toPartialEquiv_injective (since := "2023-02-18")] -theorem eq_of_partialEquiv_eq {e e' : PartialHomeomorph X Y} - (h : e.toPartialEquiv = e'.toPartialEquiv) : e = e' := - toPartialEquiv_injective h - theorem eventually_left_inverse {x} (hx : x ∈ e.source) : ∀ᶠ y in 𝓝 x, e.symm (e y) = y := (e.open_source.eventually_mem hx).mono e.left_inv' @@ -366,7 +361,7 @@ theorem eventually_nhdsWithin' {x : X} (p : X → Prop) {s : Set X} /-- This lemma is useful in the manifold library in the case that `e` is a chart. It states that locally around `e x` the set `e.symm ⁻¹' s` is the same as the set intersected with the target - of `e` and some other neighborhood of `f x` (which will be the source of a chart on `Z`). -/ + of `e` and some other neighborhood of `f x` (which will be the source of a chart on `Z`). -/ theorem preimage_eventuallyEq_target_inter_preimage_inter {e : PartialHomeomorph X Y} {s : Set X} {t : Set Z} {x : X} {f : X → Z} (hf : ContinuousWithinAt f s x) (hxe : x ∈ e.source) (ht : t ∈ 𝓝 (f x)) : @@ -1007,7 +1002,7 @@ theorem continuousOn_iff_continuousOn_comp_right {f : Y → Z} {s : Set Y} (h : /-- Continuity within a set at a point can be read under left composition with a local homeomorphism if a neighborhood of the initial point is sent to the source of the local -homeomorphism-/ +homeomorphism -/ theorem continuousWithinAt_iff_continuousWithinAt_comp_left {f : Z → X} {s : Set Z} {x : Z} (hx : f x ∈ e.source) (h : f ⁻¹' e.source ∈ 𝓝[s] x) : ContinuousWithinAt f s x ↔ ContinuousWithinAt (e ∘ f) s x := by @@ -1020,7 +1015,7 @@ theorem continuousWithinAt_iff_continuousWithinAt_comp_left {f : Z → X} {s : S exact this.congr (fun y hy => by simp [e.left_inv hy.2]) (by simp [e.left_inv hx]) /-- Continuity at a point can be read under left composition with a partial homeomorphism if a -neighborhood of the initial point is sent to the source of the partial homeomorphism-/ +neighborhood of the initial point is sent to the source of the partial homeomorphism -/ theorem continuousAt_iff_continuousAt_comp_left {f : Z → X} {x : Z} (h : f ⁻¹' e.source ∈ 𝓝 x) : ContinuousAt f x ↔ ContinuousAt (e ∘ f) x := by have hx : f x ∈ e.source := (mem_of_mem_nhds h : _) @@ -1074,7 +1069,7 @@ theorem nhds_eq_comap_inf_principal {x} (hx : x ∈ e.source) : lift x to e.source using hx rw [← e.open_source.nhdsWithin_eq x.2, ← map_nhds_subtype_val, ← map_comap_setCoe_val, e.toHomeomorphSourceTarget.nhds_eq_comap, nhds_subtype_eq_comap] - simp only [(· ∘ ·), toHomeomorphSourceTarget_apply_coe, comap_comap] + simp only [Function.comp_def, toHomeomorphSourceTarget_apply_coe, comap_comap] /-- If a partial homeomorphism has source and target equal to univ, then it induces a homeomorphism between the whole spaces, expressed in this definition. -/ diff --git a/Mathlib/Topology/RestrictGenTopology.lean b/Mathlib/Topology/RestrictGenTopology.lean index 9d244532a38d5..782e359360a79 100644 --- a/Mathlib/Topology/RestrictGenTopology.lean +++ b/Mathlib/Topology/RestrictGenTopology.lean @@ -91,4 +91,16 @@ lemma of_seq [SequentialSpace X] lemma isCompact_of_seq [SequentialSpace X] : RestrictGenTopology {K : Set X | IsCompact K} := of_seq fun _u _x hux ↦ hux.isCompact_insert_range +/-- If each point of the space has a neighborhood from the family `S`, +then the topology is generated by its restrictions to the sets of `S`. -/ +lemma of_nhds (h : ∀ x, ∃ s ∈ S, s ∈ 𝓝 x) : RestrictGenTopology S := + of_continuous_prop fun _f hf ↦ continuous_iff_continuousAt.2 fun x ↦ + let ⟨s, hsS, hsx⟩ := h x + (hf s hsS).continuousAt hsx + +/-- A weakly locally compact space is compactly generated. -/ +lemma isCompact_of_weaklyLocallyCompact [WeaklyLocallyCompactSpace X] : + RestrictGenTopology {K : Set X | IsCompact K} := + of_nhds exists_compact_mem_nhds + end RestrictGenTopology diff --git a/Mathlib/Topology/Separation.lean b/Mathlib/Topology/Separation.lean index 949fd616fcc6b..b87d9628b0774 100644 --- a/Mathlib/Topology/Separation.lean +++ b/Mathlib/Topology/Separation.lean @@ -259,7 +259,7 @@ end SeparatedNhds /-- A T₀ space, also known as a Kolmogorov space, is a topological space such that for every pair `x ≠ y`, there is an open set containing one but not the other. We formulate the definition in terms -of the `Inseparable` relation. -/ +of the `Inseparable` relation. -/ class T0Space (X : Type u) [TopologicalSpace X] : Prop where /-- Two inseparable points in a T₀ space are equal. -/ t0 : ∀ ⦃x y : X⦄, Inseparable x y → x = y @@ -974,13 +974,13 @@ theorem Filter.HasBasis.exists_inter_eq_singleton_of_mem_discrete {ι : Type*} { exact ⟨i, hi, hix.antisymm <| singleton_subset_iff.2 ⟨mem_of_mem_nhds <| hb.mem_of_mem hi, hx⟩⟩ /-- A point `x` in a discrete subset `s` of a topological space admits a neighbourhood -that only meets `s` at `x`. -/ +that only meets `s` at `x`. -/ theorem nhds_inter_eq_singleton_of_mem_discrete {s : Set X} [DiscreteTopology s] {x : X} (hx : x ∈ s) : ∃ U ∈ 𝓝 x, U ∩ s = {x} := by simpa using (𝓝 x).basis_sets.exists_inter_eq_singleton_of_mem_discrete hx /-- Let `x` be a point in a discrete subset `s` of a topological space, then there exists an open -set that only meets `s` at `x`. -/ +set that only meets `s` at `x`. -/ theorem isOpen_inter_eq_singleton_of_mem_discrete {s : Set X} [DiscreteTopology s] {x : X} (hx : x ∈ s) : ∃ U : Set X, IsOpen U ∧ U ∩ s = {x} := by obtain ⟨U, hU_nhds, hU_inter⟩ := nhds_inter_eq_singleton_of_mem_discrete hx @@ -1103,7 +1103,7 @@ theorem exists_isCompact_superset_iff {s : Set X} : alias exists_compact_superset_iff := exists_isCompact_superset_iff /-- If `K` and `L` are disjoint compact sets in an R₁ topological space -and `L` is also closed, then `K` and `L` have disjoint neighborhoods. -/ +and `L` is also closed, then `K` and `L` have disjoint neighborhoods. -/ theorem SeparatedNhds.of_isCompact_isCompact_isClosed {K L : Set X} (hK : IsCompact K) (hL : IsCompact L) (h'L : IsClosed L) (hd : Disjoint K L) : SeparatedNhds K L := by simp_rw [separatedNhds_iff_disjoint, hK.disjoint_nhdsSet_left, hL.disjoint_nhdsSet_right, @@ -1410,6 +1410,22 @@ theorem IsCompact.nhdsSet_inter_eq [T2Space X] {s t : Set X} (hs : IsCompact s) · exact le_iSup₂_of_le x ⟨hxs, hyt⟩ (inf_idem _).le · exact (disjoint_nhds_nhds.mpr hne).eq_bot ▸ bot_le +/-- In a `T2Space X`, for a compact set `t` and a point `x` outside `t`, there are open sets `U`, +`V` that separate `t` and `x`.-/ +lemma IsCompact.separation_of_not_mem {X : Type u_1} [TopologicalSpace X] [T2Space X] {x : X} + {t : Set X} (H1 : IsCompact t) (H2 : x ∉ t) : + ∃ (U : Set X), ∃ (V : Set X), IsOpen U ∧ IsOpen V ∧ t ⊆ U ∧ x ∈ V ∧ Disjoint U V := by + simpa [SeparatedNhds] using SeparatedNhds.of_isCompact_isCompact_isClosed H1 isCompact_singleton + isClosed_singleton <| disjoint_singleton_right.mpr H2 + +/-- In a `T2Space X`, for a compact set `t` and a point `x` outside `t`, `𝓝ˢ t` and `𝓝 x` are +disjoint. -/ +lemma IsCompact.disjoint_nhdsSet_nhds {X : Type u_1} [TopologicalSpace X] [T2Space X] {x : X} + {t : Set X} (H1 : IsCompact t) (H2 : x ∉ t) : + Disjoint (𝓝ˢ t) (𝓝 x) := by + simpa using SeparatedNhds.disjoint_nhdsSet <| .of_isCompact_isCompact_isClosed H1 + isCompact_singleton isClosed_singleton <| disjoint_singleton_right.mpr H2 + /-- If a function `f` is - injective on a compact set `s`; @@ -1738,6 +1754,25 @@ theorem SeparatedNhds.of_isCompact_isCompact [T2Space X] {s t : Set X} (hs : IsC @[deprecated (since := "2024-01-28")] alias separatedNhds_of_isCompact_isCompact := SeparatedNhds.of_isCompact_isCompact +/-- In a `T2Space X`, for disjoint closed sets `s t` such that `closure sᶜ` is compact, +there are neighbourhoods that separate `s` and `t`.-/ +lemma SeparatedNhds.of_isClosed_isCompact_closure_compl_isClosed [T2Space X] {s : Set X} + {t : Set X} (H1 : IsClosed s) (H2 : IsCompact (closure sᶜ)) (H3 : IsClosed t) + (H4 : Disjoint s t) : SeparatedNhds s t := by + -- Since `t` is a closed subset of the compact set `closure sᶜ`, it is compact. + have ht : IsCompact t := .of_isClosed_subset H2 H3 <| H4.subset_compl_left.trans subset_closure + -- we split `s` into its frontier and its interior. + rw [← diff_union_of_subset (interior_subset (s := s))] + -- since `t ⊆ sᶜ`, which is open, and `interior s` is open, we have + -- `SeparatedNhds (interior s) t`, which leaves us only with the frontier. + refine .union_left ?_ ⟨interior s, sᶜ, isOpen_interior, H1.isOpen_compl, le_rfl, + H4.subset_compl_left, disjoint_compl_right.mono_left interior_subset⟩ + -- Since the frontier of `s` is compact (as it is a subset of `closure sᶜ`), we simply apply + -- `SeparatedNhds_of_isCompact_isCompact`. + rw [← H1.frontier_eq, frontier_eq_closure_inter_closure, H1.closure_eq] + refine .of_isCompact_isCompact ?_ ht (disjoint_of_subset_left inter_subset_left H4) + exact H2.of_isClosed_subset (H1.inter isClosed_closure) inter_subset_right + section SeparatedFinset theorem SeparatedNhds.of_finset_finset [T2Space X] (s t : Finset X) (h : Disjoint s t) : @@ -1845,7 +1880,7 @@ of filters `𝓝ˢ s` and `𝓝 a`. -/ @[mk_iff] class RegularSpace (X : Type u) [TopologicalSpace X] : Prop where /-- If `a` is a point that does not belong to a closed set `s`, then `a` and `s` admit disjoint - neighborhoods. -/ + neighborhoods. -/ regular : ∀ {s : Set X} {a}, IsClosed s → a ∉ s → Disjoint (𝓝ˢ s) (𝓝 a) theorem regularSpace_TFAE (X : Type u) [TopologicalSpace X] : @@ -1910,6 +1945,7 @@ alias RegularSpace.ofExistsMemNhdsIsClosedSubset := RegularSpace.of_exists_mem_n instance (priority := 100) [WeaklyLocallyCompactSpace X] [R1Space X] : RegularSpace X := .of_hasBasis isCompact_isClosed_basis_nhds fun _ _ ⟨_, _, h⟩ ↦ h +section variable [RegularSpace X] {x : X} {s : Set X} theorem disjoint_nhdsSet_nhds : Disjoint (𝓝ˢ s) (𝓝 x) ↔ x ∉ closure s := by @@ -2022,9 +2058,11 @@ lemma SeparatedNhds.of_isCompact_isClosed {s t : Set X} @[deprecated (since := "2024-01-28")] alias separatedNhds_of_isCompact_isClosed := SeparatedNhds.of_isCompact_isClosed +end + /-- This technique to witness `HasSeparatingCover` in regular Lindelöf topological spaces will be used to prove regular Lindelöf spaces are normal. -/ -lemma IsClosed.HasSeparatingCover {s t : Set X} [LindelofSpace X] +lemma IsClosed.HasSeparatingCover {s t : Set X} [LindelofSpace X] [RegularSpace X] (s_cl : IsClosed s) (t_cl : IsClosed t) (st_dis : Disjoint s t) : HasSeparatingCover s t := by -- `IsLindelof.indexed_countable_subcover` requires the space be Nonempty rcases isEmpty_or_nonempty X with empty_X | nonempty_X @@ -2133,7 +2171,7 @@ end T25 section T3 /-- A T₃ space is a T₀ space which is a regular space. Any T₃ space is a T₁ space, a T₂ space, and -a T₂.₅ space. -/ +a T₂.₅ space. -/ class T3Space (X : Type u) [TopologicalSpace X] extends T0Space X, RegularSpace X : Prop instance (priority := 90) instT3Space [T0Space X] [RegularSpace X] : T3Space X := ⟨⟩ @@ -2226,6 +2264,7 @@ instance (priority := 100) NormalSpace.of_compactSpace_r1Space [CompactSpace X] NormalSpace X where normal _s _t hs ht := .of_isCompact_isCompact_isClosed hs.isCompact ht.isCompact ht +set_option pp.universes true in /-- A regular topological space with a Lindelöf topology is a normal space. A consequence of e.g. Corollaries 20.8 and 20.10 of [Willard's *General Topology*][zbMATH02107988] (without the assumption of Hausdorff). -/ @@ -2530,7 +2569,7 @@ theorem isTopologicalBasis_isClopen : IsTopologicalBasis { s : Set X | IsClopen tauto /-- Every member of an open set in a compact Hausdorff totally disconnected space - is contained in a clopen set contained in the open set. -/ + is contained in a clopen set contained in the open set. -/ theorem compact_exists_isClopen_in_isOpen {x : X} {U : Set X} (is_open : IsOpen U) (memU : x ∈ U) : ∃ V : Set X, IsClopen V ∧ x ∈ V ∧ V ⊆ U := isTopologicalBasis_isClopen.mem_nhds_iff.1 (is_open.mem_nhds memU) @@ -2605,3 +2644,5 @@ instance ConnectedComponents.t2 [T2Space X] [CompactSpace X] : T2Space (Connecte rw [ConnectedComponents.quotientMap_coe.isClopen_preimage] at hU refine ⟨Vᶜ, V, hU.compl.isOpen, hU.isOpen, ?_, hb mem_connectedComponent, disjoint_compl_left⟩ exact fun h => flip Set.Nonempty.ne_empty ha ⟨a, mem_connectedComponent, h⟩ + +set_option linter.style.longFile 2800 diff --git a/Mathlib/Topology/Sequences.lean b/Mathlib/Topology/Sequences.lean index c3f13a33c72e3..1ae5cef54ba68 100644 --- a/Mathlib/Topology/Sequences.lean +++ b/Mathlib/Topology/Sequences.lean @@ -158,7 +158,7 @@ theorem Inducing.frechetUrysohnSpace [FrechetUrysohnSpace Y] {f : X → Y} (hf : rcases hx with ⟨u, hus, hu⟩ choose v hv hvu using hus refine ⟨v, hv, ?_⟩ - simpa only [hf.tendsto_nhds_iff, (· ∘ ·), hvu] + simpa only [hf.tendsto_nhds_iff, Function.comp_def, hvu] /-- Subtype of a Fréchet-Urysohn space is a Fréchet-Urysohn space. -/ instance Subtype.instFrechetUrysohnSpace [FrechetUrysohnSpace X] {p : X → Prop} : diff --git a/Mathlib/Topology/Sheaves/Limits.lean b/Mathlib/Topology/Sheaves/Limits.lean index bd475bdcbd6cf..7309973470775 100644 --- a/Mathlib/Topology/Sheaves/Limits.lean +++ b/Mathlib/Topology/Sheaves/Limits.lean @@ -5,7 +5,7 @@ Authors: Scott Morrison -/ import Mathlib.Topology.Sheaves.Sheaf import Mathlib.CategoryTheory.Sites.Limits -import Mathlib.CategoryTheory.Limits.FunctorCategory +import Mathlib.CategoryTheory.Limits.FunctorCategory.Basic /-! # Presheaves in `C` have limits and colimits when `C` does. diff --git a/Mathlib/Topology/Sheaves/MayerVietoris.lean b/Mathlib/Topology/Sheaves/MayerVietoris.lean new file mode 100644 index 0000000000000..c50c3418dc9ee --- /dev/null +++ b/Mathlib/Topology/Sheaves/MayerVietoris.lean @@ -0,0 +1,69 @@ +/- +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.CategoryTheory.Sites.MayerVietorisSquare +import Mathlib.CategoryTheory.Sites.Spaces + +/-! +# Mayer-Vietoris squares + +Given two open subsets `U` and `V` of a topological space `T`, +we construct the associated Mayer-Vietoris square: +``` +U ⊓ V ---> U + | | + v v + V ---> U ⊔ V +``` + +-/ + +universe u + +namespace Opens + +open CategoryTheory Limits TopologicalSpace + +variable {T : Type u} [TopologicalSpace T] + +/-- A square consisting of opens `X₂ ⊓ X₃`, `X₂`, `X₃` and `X₂ ⊔ X₃` is +a Mayer-Vietoris square. -/ +@[simps! toSquare] +noncomputable def mayerVietorisSquare' (sq : Square (Opens T)) + (h₄ : sq.X₄ = sq.X₂ ⊔ sq.X₃) (h₁ : sq.X₁ = sq.X₂ ⊓ sq.X₃) : + (Opens.grothendieckTopology T).MayerVietorisSquare := + GrothendieckTopology.MayerVietorisSquare.mk_of_isPullback + (J := (Opens.grothendieckTopology T)) sq + (Square.IsPullback.mk _ (by + refine PullbackCone.IsLimit.mk _ ?_ ?_ ?_ ?_ + · intro s + apply homOfLE + rw [h₁, le_inf_iff] + exact ⟨leOfHom s.fst, leOfHom s.snd⟩ + all_goals intros; apply Subsingleton.elim)) + (fun x hx ↦ by + rw [h₄] at hx + obtain (hx|hx) := hx + · exact ⟨_, _, ⟨Sieve.ofArrows_mk _ _ WalkingPair.left, hx⟩⟩ + · exact ⟨_, _, ⟨Sieve.ofArrows_mk _ _ WalkingPair.right, hx⟩⟩) + +/-- The Mayer-Vietoris square attached to two open subsets +of a topological space. -/ +@[simps!] +noncomputable def mayerVietorisSquare (U V : Opens T): + (Opens.grothendieckTopology T).MayerVietorisSquare := + mayerVietorisSquare' + { X₁ := U ⊓ V + X₂ := U + X₃ := V + X₄ := U ⊔ V + f₁₂ := homOfLE inf_le_left + f₁₃ := homOfLE inf_le_right + f₂₄ := homOfLE le_sup_left + f₃₄ := homOfLE le_sup_right + fac := Subsingleton.elim _ _ } rfl rfl + +end Opens diff --git a/Mathlib/Topology/Sheaves/Operations.lean b/Mathlib/Topology/Sheaves/Operations.lean index c45d513f7dc54..85cb01ea80e1a 100644 --- a/Mathlib/Topology/Sheaves/Operations.lean +++ b/Mathlib/Topology/Sheaves/Operations.lean @@ -88,7 +88,7 @@ noncomputable def submonoidPresheafOfStalk (S : ∀ x : X, Submonoid (F.stalk x) intro x change (F.map i.unop.op ≫ F.germ x) s ∈ _ rw [F.germ_res] - exact hs _ + exact hs ⟨_,_⟩ noncomputable instance : Inhabited F.SubmonoidPresheaf := ⟨F.submonoidPresheafOfStalk fun _ => ⊥⟩ diff --git a/Mathlib/Topology/Sheaves/Presheaf.lean b/Mathlib/Topology/Sheaves/Presheaf.lean index 4469bab7e876e..1045f3e96ce28 100644 --- a/Mathlib/Topology/Sheaves/Presheaf.lean +++ b/Mathlib/Topology/Sheaves/Presheaf.lean @@ -154,7 +154,7 @@ def pushforward {X Y : TopCat.{w}} (f : X ⟶ Y) : X.Presheaf C ⥤ Y.Presheaf C (whiskeringLeft _ _ _).obj (Opens.map f).op set_option quotPrecheck false in -/-- push forward of a presheaf-/ +/-- push forward of a presheaf -/ notation f:80 " _* " P:81 => (pushforward _ f).obj P @[simp] @@ -291,7 +291,7 @@ def pullbackInvIsoPushforwardHom {X Y : TopCat.{v}} (H : X ≅ Y) : variable {C} -/-- If `f '' U` is open, then `f⁻¹ℱ U ≅ ℱ (f '' U)`. -/ +/-- If `f '' U` is open, then `f⁻¹ℱ U ≅ ℱ (f '' U)`. -/ def pullbackObjObjOfImageOpen {X Y : TopCat.{v}} (f : X ⟶ Y) (ℱ : Y.Presheaf C) (U : Opens X) (H : IsOpen (f '' SetLike.coe U)) : ((pullback C f).obj ℱ).obj (op U) ≅ ℱ.obj (op ⟨_, H⟩) := by let x : CostructuredArrow (Opens.map f).op (op U) := CostructuredArrow.mk @@ -303,7 +303,7 @@ def pullbackObjObjOfImageOpen {X Y : TopCat.{v}} (f : X ⟶ Y) (ℱ : Y.Presheaf refine (homOfLE ?_).op apply (Set.image_subset f s.pt.hom.unop.le).trans exact Set.image_preimage.l_u_le (SetLike.coe s.pt.left.unop) - · simp [autoParam, eq_iff_true_of_subsingleton] } + · simp [eq_iff_true_of_subsingleton] } exact IsColimit.coconePointUniqueUpToIso ((Opens.map f).op.isPointwiseLeftKanExtensionLanUnit ℱ (op U)) (colimitOfDiagramTerminal hx _) diff --git a/Mathlib/Topology/Sheaves/SheafCondition/OpensLeCover.lean b/Mathlib/Topology/Sheaves/SheafCondition/OpensLeCover.lean index 650373c48901f..ace2385ed29bd 100644 --- a/Mathlib/Topology/Sheaves/SheafCondition/OpensLeCover.lean +++ b/Mathlib/Topology/Sheaves/SheafCondition/OpensLeCover.lean @@ -98,7 +98,7 @@ def IsSheafOpensLeCover : Prop := section -variable {Y : Opens X} (hY : Y = iSup U) +variable {Y : Opens X} -- Porting note: split it out to prevent timeout /-- Given a family of opens `U` and an open `Y` equal to the union of opens in `U`, we may @@ -107,7 +107,7 @@ variable {Y : Opens X} (hY : Y = iSup U) in the sieve. This full subcategory is equivalent to `OpensLeCover U`, the (poset) category of opens contained in some `U i`. -/ @[simps] -def generateEquivalenceOpensLe_functor' : +def generateEquivalenceOpensLe_functor' (hY : Y = iSup U) : (FullSubcategory fun f : Over Y => (Sieve.generate (presieveOfCoveringAux U Y)).arrows f.hom) ⥤ OpensLeCover U := { obj := fun f => @@ -123,7 +123,7 @@ def generateEquivalenceOpensLe_functor' : in the sieve. This full subcategory is equivalent to `OpensLeCover U`, the (poset) category of opens contained in some `U i`. -/ @[simps] -def generateEquivalenceOpensLe_inverse' : +def generateEquivalenceOpensLe_inverse' (hY : Y = iSup U) : OpensLeCover U ⥤ (FullSubcategory fun f : Over Y => (Sieve.generate (presieveOfCoveringAux U Y)).arrows f.hom) where @@ -146,12 +146,12 @@ def generateEquivalenceOpensLe_inverse' : in the sieve. This full subcategory is equivalent to `OpensLeCover U`, the (poset) category of opens contained in some `U i`. -/ @[simps] -def generateEquivalenceOpensLe : +def generateEquivalenceOpensLe (hY : Y = iSup U) : (FullSubcategory fun f : Over Y => (Sieve.generate (presieveOfCoveringAux U Y)).arrows f.hom) ≌ OpensLeCover U where -- Porting note: split it out to prevent timeout - functor := generateEquivalenceOpensLe_functor' _ _ - inverse := generateEquivalenceOpensLe_inverse' _ _ + functor := generateEquivalenceOpensLe_functor' _ hY + inverse := generateEquivalenceOpensLe_inverse' _ hY unitIso := eqToIso <| CategoryTheory.Functor.ext (by rintro ⟨⟨_, _⟩, _⟩; dsimp; congr) (by intros; refine Over.OverMorphism.ext ?_; aesop_cat) @@ -162,7 +162,7 @@ def generateEquivalenceOpensLe : associated to the sieve generated by the presieve associated to `U` with indexing category changed using the above equivalence. -/ @[simps] -def whiskerIsoMapGenerateCocone : +def whiskerIsoMapGenerateCocone (hY : Y = iSup U) : (F.mapCone (opensLeCoverCocone U).op).whisker (generateEquivalenceOpensLe U hY).op.functor ≅ F.mapCone (Sieve.generate (presieveOfCoveringAux U Y)).arrows.cocone.op where hom := @@ -188,7 +188,7 @@ def whiskerIsoMapGenerateCocone : the natural cone associated to `F` and `U` used in the definition of `F.IsSheafOpensLeCover` is a limit cone iff the natural cone associated to `F` and the sieve generated by the presieve associated to `U` is a limit cone. -/ -def isLimitOpensLeEquivGenerate₁ : +def isLimitOpensLeEquivGenerate₁ (hY : Y = iSup U) : IsLimit (F.mapCone (opensLeCoverCocone U).op) ≃ IsLimit (F.mapCone (Sieve.generate (presieveOfCoveringAux U Y)).arrows.cocone.op) := (IsLimit.whiskerEquivalenceEquiv (generateEquivalenceOpensLe U hY).op).trans diff --git a/Mathlib/Topology/Sheaves/SheafOfFunctions.lean b/Mathlib/Topology/Sheaves/SheafOfFunctions.lean index e3707c87c39cc..4aea0cf255c09 100644 --- a/Mathlib/Topology/Sheaves/SheafOfFunctions.lean +++ b/Mathlib/Topology/Sheaves/SheafOfFunctions.lean @@ -75,7 +75,7 @@ theorem toTypes_isSheaf (T : X → Type u) : (presheafToTypes X T).IsSheaf := -- We verify that the non-dependent version is an immediate consequence: /-- The presheaf of not-necessarily-continuous functions to -a target type `T` satsifies the sheaf condition. +a target type `T` satisfies the sheaf condition. -/ theorem toType_isSheaf (T : Type u) : (presheafToType X T).IsSheaf := toTypes_isSheaf X fun _ => T diff --git a/Mathlib/Topology/Sheaves/Stalks.lean b/Mathlib/Topology/Sheaves/Stalks.lean index 70176d5a489ac..36574cf04a2b3 100644 --- a/Mathlib/Topology/Sheaves/Stalks.lean +++ b/Mathlib/Topology/Sheaves/Stalks.lean @@ -6,7 +6,6 @@ Authors: Scott Morrison, Justus Springer import Mathlib.Topology.Category.TopCat.OpenNhds import Mathlib.Topology.Sheaves.Presheaf import Mathlib.Topology.Sheaves.SheafCondition.UniqueGluing -import Mathlib.CategoryTheory.Adjunction.Evaluation import Mathlib.CategoryTheory.Limits.Types import Mathlib.CategoryTheory.Limits.Preserves.Filtered import Mathlib.CategoryTheory.Limits.Final @@ -474,7 +473,7 @@ instance stalkFunctor_preserves_mono (x : X) : (app_injective_iff_stalkFunctor_map_injective f.1).mpr (fun c => (ConcreteCategory.mono_iff_injective_of_preservesPullback (f.1.app (op c))).mp - ((NatTrans.mono_iff_mono_app _ f.1).mp + ((NatTrans.mono_iff_mono_app f.1).mp (CategoryTheory.presheaf_mono_of_mono ..) <| op c)) x⟩ @@ -486,7 +485,7 @@ theorem stalk_mono_of_mono {F G : Sheaf C X} (f : F ⟶ G) [Mono f] : theorem mono_of_stalk_mono {F G : Sheaf C X} (f : F ⟶ G) [∀ x, Mono <| (stalkFunctor C x).map f.1] : Mono f := (Sheaf.Hom.mono_iff_presheaf_mono _ _ _).mpr <| - (NatTrans.mono_iff_mono_app _ _).mpr fun U => + (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⟩ => (ConcreteCategory.mono_iff_injective_of_preservesPullback _).mp <| inferInstance diff --git a/Mathlib/Topology/Specialization.lean b/Mathlib/Topology/Specialization.lean index 53b1665a0beab..874083b9a9983 100644 --- a/Mathlib/Topology/Specialization.lean +++ b/Mathlib/Topology/Specialization.lean @@ -26,7 +26,7 @@ variable {α β γ : Type*} /-- `toEquiv` is the "identity" function to the `Specialization` of a type. -/ @[match_pattern] def toEquiv : α ≃ Specialization α := Equiv.refl _ -/-- `ofEquiv` is the identity function from the `Specialization` of a type. -/ +/-- `ofEquiv` is the identity function from the `Specialization` of a type. -/ @[match_pattern] def ofEquiv : Specialization α ≃ α := Equiv.refl _ @[simp] lemma toEquiv_symm : (@toEquiv α).symm = ofEquiv := rfl diff --git a/Mathlib/Topology/Spectral/Hom.lean b/Mathlib/Topology/Spectral/Hom.lean index 695abf50017b4..078b9875e0dbe 100644 --- a/Mathlib/Topology/Spectral/Hom.lean +++ b/Mathlib/Topology/Spectral/Hom.lean @@ -57,9 +57,9 @@ end Unbundled /-- The type of spectral maps from `α` to `β`. -/ structure SpectralMap (α β : Type*) [TopologicalSpace α] [TopologicalSpace β] where - /-- function between topological spaces-/ + /-- function between topological spaces -/ toFun : α → β - /-- proof that `toFun` is a spectral map-/ + /-- proof that `toFun` is a spectral map -/ spectral' : IsSpectralMap toFun section @@ -69,7 +69,7 @@ section You should extend this class when you extend `SpectralMap`. -/ class SpectralMapClass (F α β : Type*) [TopologicalSpace α] [TopologicalSpace β] [FunLike F α β] : Prop where - /-- statement that `F` is a type of spectral maps-/ + /-- statement that `F` is a type of spectral maps -/ map_spectral (f : F) : IsSpectralMap f end diff --git a/Mathlib/Topology/StoneCech.lean b/Mathlib/Topology/StoneCech.lean index 629e0e1ffa49c..ba2b4232abec5 100644 --- a/Mathlib/Topology/StoneCech.lean +++ b/Mathlib/Topology/StoneCech.lean @@ -13,7 +13,7 @@ Construction of the Stone-Čech compactification using ultrafilters. For any topological space `α`, we build a compact Hausdorff space `StoneCech α` and a continuous map `stoneCechUnit : α → StoneCech α` which is minimal in the sense of the following universal property: for any compact Hausdorff space `β` and every map `f : α → β` such that -`hf : Continuous f`, there is a unique map `stoneCechExtend hf : StoneCech α → β` such that +`hf : Continuous f`, there is a unique map `stoneCechExtend hf : StoneCech α → β` such that `stoneCechExtend_extends : stoneCechExtend hf ∘ stoneCechUnit = f`. Continuity of this extension is asserted by `continuous_stoneCechExtend` and uniqueness by `stoneCech_hom_ext`. @@ -221,7 +221,7 @@ section PreStoneCech variable (α : Type u) [TopologicalSpace α] -/-- Auxilliary construction towards the Stone-Čech compactification of a topological space. +/-- Auxiliary construction towards the Stone-Čech compactification of a topological space. It should not be used after the Stone-Čech compactification is constructed. -/ def PreStoneCech : Type u := Quot fun F G : Ultrafilter α ↦ ∃ x, (F : Filter α) ≤ 𝓝 x ∧ (G : Filter α) ≤ 𝓝 x diff --git a/Mathlib/Topology/TietzeExtension.lean b/Mathlib/Topology/TietzeExtension.lean index 704a18651fd7e..b1e175559e9fd 100644 --- a/Mathlib/Topology/TietzeExtension.lean +++ b/Mathlib/Topology/TietzeExtension.lean @@ -306,7 +306,7 @@ theorem exists_extension_forall_mem_Icc_of_closedEmbedding (f : X →ᵇ ℝ) {a embedding. Let `e` be a closed embedding of a nonempty topological space `X` into a normal topological space `Y`. Let `f` be a bounded continuous real-valued function on `X`. Then there exists a bounded continuous function `g : Y →ᵇ ℝ` such that `g ∘ e = f` and each value `g y` belongs -to a closed interval `[f x₁, f x₂]` for some `x₁` and `x₂`. -/ +to a closed interval `[f x₁, f x₂]` for some `x₁` and `x₂`. -/ theorem exists_extension_forall_exists_le_ge_of_closedEmbedding [Nonempty X] (f : X →ᵇ ℝ) {e : X → Y} (he : ClosedEmbedding e) : ∃ g : Y →ᵇ ℝ, (∀ y, ∃ x₁ x₂, g y ∈ Icc (f x₁) (f x₂)) ∧ g ∘ e = f := by @@ -340,7 +340,7 @@ theorem exists_extension_forall_exists_le_ge_of_closedEmbedding [Nonempty X] (f · exact ⟨g, fun y => ⟨x, hg_mem _⟩, hgf⟩ /- Otherwise, `g ⁻¹' {a}` is disjoint with `range e ∪ g ⁻¹' (Ici c)`, hence there exists a function `dg : Y → ℝ` such that `dg ∘ e = 0`, `dg y = 0` whenever `c ≤ g y`, `dg y = c - a` - whenever `g y = a`, and `0 ≤ dg y ≤ c - a` for all `y`. -/ + whenever `g y = a`, and `0 ≤ dg y ≤ c - a` for all `y`. -/ have hd : Disjoint (range e ∪ g ⁻¹' Ici c) (g ⁻¹' {a}) := by refine disjoint_union_left.2 ⟨?_, Disjoint.preimage _ ?_⟩ · rw [Set.disjoint_left] diff --git a/Mathlib/Topology/UniformSpace/AbstractCompletion.lean b/Mathlib/Topology/UniformSpace/AbstractCompletion.lean index 9f7d1efc35a9c..903552b0c52dd 100644 --- a/Mathlib/Topology/UniformSpace/AbstractCompletion.lean +++ b/Mathlib/Topology/UniformSpace/AbstractCompletion.lean @@ -187,7 +187,7 @@ theorem map_unique {f : α → β} {g : hatα → hatβ} (hg : UniformContinuous pkg.funext (pkg.continuous_map _ _) hg.continuous <| by intro a change pkg.extend (ι' ∘ f) _ = _ - simp_rw [(· ∘ ·), h, ← comp_apply (f := g)] + simp_rw [Function.comp_def, h, ← comp_apply (f := g)] rw [pkg.extend_coe (hg.comp pkg.uniformContinuous_coe)] @[simp] diff --git a/Mathlib/Topology/UniformSpace/Ascoli.lean b/Mathlib/Topology/UniformSpace/Ascoli.lean index 6ceb7a0371b6f..75e7105788ec2 100644 --- a/Mathlib/Topology/UniformSpace/Ascoli.lean +++ b/Mathlib/Topology/UniformSpace/Ascoli.lean @@ -39,7 +39,7 @@ a family of compact subsets of `X`, and `α` is a uniform space. embeddings instead of subspaces with the subspace topology. This is done because, in practice, one would rarely work with `X →ᵤ[𝔖] α` directly, so we need to provide API for bringing back the statements to various other types, such as `C(X, Y)` or `E →L[𝕜] F`. To counteract this, all - statements (as well as most proofs!) are documented quite thouroughly. + statements (as well as most proofs!) are documented quite thoroughly. * A lot of statements assume `∀ K ∈ 𝔖, EquicontinuousOn F K` instead of the more natural `EquicontinuousOn F (⋃₀ 𝔖)`. This is in order to keep the most generality, as the first statement @@ -89,7 +89,7 @@ theorem Equicontinuous.comap_uniformFun_eq [CompactSpace X] (F_eqcont : Equicont refine le_antisymm (UniformSpace.comap_mono UniformFun.uniformContinuous_toFun) ?_ -- A bit of rewriting to get a nice intermediate statement. change comap _ _ ≤ comap _ _ - simp_rw [Pi.uniformity, Filter.comap_iInf, comap_comap, Function.comp] + simp_rw [Pi.uniformity, Filter.comap_iInf, comap_comap, Function.comp_def] refine ((UniformFun.hasBasis_uniformity X α).comap (Prod.map F F)).ge_iff.mpr ?_ -- Core of the proof: we need to show that, for any entourage `U` in `α`, -- the set `𝐓(U) := {(i,j) : ι × ι | ∀ x : X, (F i x, F j x) ∈ U}` belongs to the filter @@ -220,7 +220,7 @@ theorem EquicontinuousOn.comap_uniformOnFun_eq {𝔖 : Set (Set X)} (𝔖_compac have H1 : (UniformOnFun.uniformSpace X α 𝔖).comap F = ⨅ (K ∈ 𝔖), (UniformFun.uniformSpace _ _).comap (K.restrict ∘ F) := by simp_rw [UniformOnFun.uniformSpace, UniformSpace.comap_iInf, ← UniformSpace.comap_comap, - UniformFun.ofFun, Equiv.coe_fn_mk, UniformOnFun.toFun, UniformOnFun.ofFun, Function.comp, + UniformFun.ofFun, Equiv.coe_fn_mk, UniformOnFun.toFun, UniformOnFun.ofFun, Function.comp_def, UniformFun, Equiv.coe_fn_symm_mk] -- Now, note that a similar fact is true for the uniform structure on `X → α` induced by -- the map `(⋃₀ 𝔖).restrict : (X → α) → ((⋃₀ 𝔖) → α)`: it is equal to the one induced by diff --git a/Mathlib/Topology/UniformSpace/Basic.lean b/Mathlib/Topology/UniformSpace/Basic.lean index 37b930b9377e6..eca83bcfea729 100644 --- a/Mathlib/Topology/UniformSpace/Basic.lean +++ b/Mathlib/Topology/UniformSpace/Basic.lean @@ -564,16 +564,16 @@ theorem comp_comp_symm_mem_uniformity_sets {s : Set (α × α)} (hs : s ∈ 𝓤 ### Balls in uniform spaces -/ +namespace UniformSpace + /-- The ball around `(x : β)` with respect to `(V : Set (β × β))`. Intended to be used for `V ∈ 𝓤 β`, but this is not needed for the definition. Recovers the -notions of metric space ball when `V = {p | dist p.1 p.2 < r }`. -/ -def UniformSpace.ball (x : β) (V : Set (β × β)) : Set β := - Prod.mk x ⁻¹' V +notions of metric space ball when `V = {p | dist p.1 p.2 < r }`. -/ +def ball (x : β) (V : Set (β × β)) : Set β := Prod.mk x ⁻¹' V open UniformSpace (ball) -theorem UniformSpace.mem_ball_self (x : α) {V : Set (α × α)} (hV : V ∈ 𝓤 α) : x ∈ ball x V := - refl_mem_uniformity hV +lemma mem_ball_self (x : α) {V : Set (α × α)} : V ∈ 𝓤 α → x ∈ ball x V := refl_mem_uniformity /-- The triangle inequality for `UniformSpace.ball` -/ theorem mem_ball_comp {V W : Set (β × β)} {x y z} (h : y ∈ ball x V) (h' : z ∈ ball y W) : @@ -612,11 +612,10 @@ theorem mem_comp_of_mem_ball {V W : Set (β × β)} {x y z : β} (hV : Symmetric rw [mem_ball_symmetry hV] at hx exact ⟨z, hx, hy⟩ -theorem UniformSpace.isOpen_ball (x : α) {V : Set (α × α)} (hV : IsOpen V) : IsOpen (ball x V) := +lemma isOpen_ball (x : α) {V : Set (α × α)} (hV : IsOpen V) : IsOpen (ball x V) := hV.preimage <| continuous_const.prod_mk continuous_id -theorem UniformSpace.isClosed_ball (x : α) {V : Set (α × α)} (hV : IsClosed V) : - IsClosed (ball x V) := +lemma isClosed_ball (x : α) {V : Set (α × α)} (hV : IsClosed V) : IsClosed (ball x V) := hV.preimage <| continuous_const.prod_mk continuous_id theorem mem_comp_comp {V W M : Set (β × β)} (hW' : SymmetricRel W) {p : β × β} : @@ -629,10 +628,14 @@ theorem mem_comp_comp {V W M : Set (β × β)} (hW' : SymmetricRel W) {p : β × rw [mem_ball_symmetry hW'] at z_in exact ⟨z, ⟨w, w_in, hwz⟩, z_in⟩ +end UniformSpace + /-! ### Neighborhoods in uniform spaces -/ +open UniformSpace + theorem mem_nhds_uniformity_iff_right {x : α} {s : Set α} : s ∈ 𝓝 x ↔ { p : α × α | p.1 = x → p.2 ∈ s } ∈ 𝓤 α := by simp only [nhds_eq_comap_uniformity, mem_comap_prod_mk] @@ -740,12 +743,12 @@ theorem tendsto_left_nhds_uniformity {a : α} : Tendsto (fun a' => (a, a')) ( theorem lift_nhds_left {x : α} {g : Set α → Filter β} (hg : Monotone g) : (𝓝 x).lift g = (𝓤 α).lift fun s : Set (α × α) => g (ball x s) := by rw [nhds_eq_comap_uniformity, comap_lift_eq2 hg] - simp_rw [ball, Function.comp] + simp_rw [ball, Function.comp_def] theorem lift_nhds_right {x : α} {g : Set α → Filter β} (hg : Monotone g) : (𝓝 x).lift g = (𝓤 α).lift fun s : Set (α × α) => g { y | (y, x) ∈ s } := by rw [nhds_eq_comap_uniformity', comap_lift_eq2 hg] - simp_rw [Function.comp, preimage] + simp_rw [Function.comp_def, preimage] theorem nhds_nhds_eq_uniformity_uniformity_prod {a b : α} : 𝓝 a ×ˢ 𝓝 b = (𝓤 α).lift fun s : Set (α × α) => @@ -1110,7 +1113,7 @@ abbrev UniformSpace.comap (f : α → β) (u : UniformSpace β) : UniformSpace (comap_mono u.comp) toTopologicalSpace := u.toTopologicalSpace.induced f nhds_eq_comap_uniformity x := by - simp only [nhds_induced, nhds_eq_comap_uniformity, comap_comap, Function.comp] + simp only [nhds_induced, nhds_eq_comap_uniformity, comap_comap, Function.comp_def] theorem uniformity_comap {_ : UniformSpace β} (f : α → β) : 𝓤[UniformSpace.comap f ‹_›] = comap (Prod.map f f) (𝓤 β) := @@ -1358,6 +1361,8 @@ end MulOpposite section Prod +open UniformSpace + /- a similar product space is possible on the function space (uniformity of pointwise convergence), but we want to have the uniformity of uniform convergence on function spaces -/ instance instUniformSpaceProd [u₁ : UniformSpace α] [u₂ : UniformSpace β] : UniformSpace (α × β) := @@ -1383,7 +1388,7 @@ theorem uniformity_prod_eq_comap_prod [UniformSpace α] [UniformSpace β] : 𝓤 (α × β) = comap (fun p : (α × β) × α × β => ((p.1.1, p.2.1), (p.1.2, p.2.2))) (𝓤 α ×ˢ 𝓤 β) := by dsimp [SProd.sprod] - rw [uniformity_prod, Filter.prod, comap_inf, comap_comap, comap_comap]; rfl + rw [uniformity_prod, Filter.prod, Filter.comap_inf, Filter.comap_comap, Filter.comap_comap]; rfl theorem uniformity_prod_eq_prod [UniformSpace α] [UniformSpace β] : 𝓤 (α × β) = map (fun p : (α × α) × β × β => ((p.1.1, p.2.1), (p.1.2, p.2.2))) (𝓤 α ×ˢ 𝓤 β) := by @@ -1396,10 +1401,35 @@ theorem mem_uniformity_of_uniformContinuous_invariant [UniformSpace α] [Uniform rcases mem_prod_iff.1 (mem_map.1 <| hf hs) with ⟨u, hu, v, hv, huvt⟩ exact ⟨u, hu, fun a b c hab => @huvt ((_, _), (_, _)) ⟨hab, refl_mem_uniformity hv⟩⟩ -theorem mem_uniform_prod [t₁ : UniformSpace α] [t₂ : UniformSpace β] {a : Set (α × α)} - {b : Set (β × β)} (ha : a ∈ 𝓤 α) (hb : b ∈ 𝓤 β) : - { p : (α × β) × α × β | (p.1.1, p.2.1) ∈ a ∧ (p.1.2, p.2.2) ∈ b } ∈ 𝓤 (α × β) := by - rw [uniformity_prod]; exact inter_mem_inf (preimage_mem_comap ha) (preimage_mem_comap hb) +/-- An entourage of the diagonal in `α` and an entourage in `β` yield an entourage in `α × β` +once we permute coordinates.-/ +def entourageProd (u : Set (α × α)) (v : Set (β × β)) : Set ((α × β) × α × β) := + {((a₁, b₁),(a₂, b₂)) | (a₁, a₂) ∈ u ∧ (b₁, b₂) ∈ v} + +theorem mem_entourageProd {u : Set (α × α)} {v : Set (β × β)} {p : (α × β) × α × β} : + p ∈ entourageProd u v ↔ (p.1.1, p.2.1) ∈ u ∧ (p.1.2, p.2.2) ∈ v := Iff.rfl + +theorem entourageProd_mem_uniformity [t₁ : UniformSpace α] [t₂ : UniformSpace β] {u : Set (α × α)} + {v : Set (β × β)} (hu : u ∈ 𝓤 α) (hv : v ∈ 𝓤 β) : + entourageProd u v ∈ 𝓤 (α × β) := by + rw [uniformity_prod]; exact inter_mem_inf (preimage_mem_comap hu) (preimage_mem_comap hv) + +theorem ball_entourageProd (u : Set (α × α)) (v : Set (β × β)) (x : α × β) : + ball x (entourageProd u v) = ball x.1 u ×ˢ ball x.2 v := by + ext p; simp only [ball, entourageProd, Set.mem_setOf_eq, Set.mem_prod, Set.mem_preimage] + +theorem Filter.HasBasis.uniformity_prod {ιa ιb : Type*} [UniformSpace α] [UniformSpace β] + {pa : ιa → Prop} {pb : ιb → Prop} {sa : ιa → Set (α × α)} {sb : ιb → Set (β × β)} + (ha : (𝓤 α).HasBasis pa sa) (hb : (𝓤 β).HasBasis pb sb) : + (𝓤 (α × β)).HasBasis (fun i : ιa × ιb ↦ pa i.1 ∧ pb i.2) + (fun i ↦ entourageProd (sa i.1) (sb i.2)) := + (ha.comap _).inf (hb.comap _) + +theorem entourageProd_subset [UniformSpace α] [UniformSpace β] + {s : Set ((α × β) × α × β)} (h : s ∈ 𝓤 (α × β)) : + ∃ u ∈ 𝓤 α, ∃ v ∈ 𝓤 β, entourageProd u v ⊆ s := by + rcases (((𝓤 α).basis_sets.uniformity_prod (𝓤 β).basis_sets).mem_iff' s).1 h with ⟨w, hw⟩ + use w.1, hw.1.1, w.2, hw.1.2, hw.2 theorem tendsto_prod_uniformity_fst [UniformSpace α] [UniformSpace β] : Tendsto (fun p : (α × β) × α × β => (p.1.1, p.2.1)) (𝓤 (α × β)) (𝓤 α) := @@ -1766,3 +1796,5 @@ theorem Filter.Tendsto.congr_uniformity {α β} [UniformSpace β] {f g : α → theorem Uniform.tendsto_congr {α β} [UniformSpace β] {f g : α → β} {l : Filter α} {b : β} (hfg : Tendsto (fun x => (f x, g x)) l (𝓤 β)) : Tendsto f l (𝓝 b) ↔ Tendsto g l (𝓝 b) := ⟨fun h => h.congr_uniformity hfg, fun h => h.congr_uniformity hfg.uniformity_symm⟩ + +set_option linter.style.longFile 1900 diff --git a/Mathlib/Topology/UniformSpace/Cauchy.lean b/Mathlib/Topology/UniformSpace/Cauchy.lean index 6ade1b68d70e8..726e5e6594398 100644 --- a/Mathlib/Topology/UniformSpace/Cauchy.lean +++ b/Mathlib/Topology/UniformSpace/Cauchy.lean @@ -207,7 +207,7 @@ theorem Function.Bijective.cauchySeq_comp_iff {f : ℕ → ℕ} (hf : Bijective CauchySeq (u ∘ f) ↔ CauchySeq u := by refine ⟨fun H => ?_, fun H => H.comp_injective hf.injective⟩ lift f to ℕ ≃ ℕ using hf - simpa only [(· ∘ ·), f.apply_symm_apply] using H.comp_injective f.symm.injective + simpa only [Function.comp_def, f.apply_symm_apply] using H.comp_injective f.symm.injective theorem CauchySeq.subseq_subseq_mem {V : ℕ → Set (α × α)} (hV : ∀ n, V n ∈ 𝓤 α) {u : ℕ → α} (hu : CauchySeq u) {f g : ℕ → ℕ} (hf : Tendsto f atTop atTop) (hg : Tendsto g atTop atTop) : @@ -562,7 +562,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] at hct + simp only [mem_setOf_eq, subset_def, mem_iUnion, exists_prop', nonempty_prop] at hct intro x hx simpa using hct x hx⟩ @@ -589,7 +589,7 @@ theorem totallyBounded_iff_filter {s : Set α} : have hb : HasAntitoneBasis f fun t : Finset α ↦ s \ ⋃ y ∈ t, { x | (x, y) ∈ d } := .iInf_principal fun _ _ ↦ diff_subset_diff_right ∘ biUnion_subset_biUnion_left have : Filter.NeBot f := hb.1.neBot_iff.2 fun _ ↦ - nonempty_diff.2 <| hd_cover _ (Finset.finite_toSet _) + diff_nonempty.2 <| hd_cover _ (Finset.finite_toSet _) have : f ≤ 𝓟 s := iInf_le_of_le ∅ (by simp) refine ⟨f, ‹_›, ‹_›, fun c hcf hc => ?_⟩ rcases mem_prod_same_iff.1 (hc.2 hd) with ⟨m, hm, hmd⟩ diff --git a/Mathlib/Topology/UniformSpace/Compact.lean b/Mathlib/Topology/UniformSpace/Compact.lean index 6c6f0ab1644d7..8f4de0a668e02 100644 --- a/Mathlib/Topology/UniformSpace/Compact.lean +++ b/Mathlib/Topology/UniformSpace/Compact.lean @@ -134,14 +134,14 @@ def uniformSpaceOfCompactT2 [TopologicalSpace γ] [CompactSpace γ] [T2Space γ] -- So we have a contradiction exact hU₁₂.le_bot ⟨uw_in.2, wv_in.1⟩ nhds_eq_comap_uniformity x := by - simp_rw [nhdsSet_diagonal, comap_iSup, nhds_prod_eq, comap_prod, (· ∘ ·), comap_id'] + simp_rw [nhdsSet_diagonal, comap_iSup, nhds_prod_eq, comap_prod, Function.comp_def, comap_id'] rw [iSup_split_single _ x, comap_const_of_mem fun V => mem_of_mem_nhds] suffices ∀ y ≠ x, comap (fun _ : γ ↦ x) (𝓝 y) ⊓ 𝓝 y ≤ 𝓝 x by simpa intro y hxy simp [comap_const_of_not_mem (compl_singleton_mem_nhds hxy) (not_not_intro rfl)] /-! -### Heine-Cantor theorem +### Heine-Cantor theorem -/ diff --git a/Mathlib/Topology/UniformSpace/CompactConvergence.lean b/Mathlib/Topology/UniformSpace/CompactConvergence.lean index 5014105f7a6b4..7f50b07c0cc1d 100644 --- a/Mathlib/Topology/UniformSpace/CompactConvergence.lean +++ b/Mathlib/Topology/UniformSpace/CompactConvergence.lean @@ -151,6 +151,10 @@ def toUniformOnFunIsCompact (f : C(α, β)) : α →ᵤ[{K | IsCompact K}] β := theorem toUniformOnFun_toFun (f : C(α, β)) : UniformOnFun.toFun _ f.toUniformOnFunIsCompact = f := rfl +theorem range_toUniformOnFunIsCompact : + range (toUniformOnFunIsCompact) = {f : UniformOnFun α β {K | IsCompact K} | Continuous f} := + Set.ext fun f ↦ ⟨fun g ↦ g.choose_spec ▸ g.choose.2, fun hf ↦ ⟨⟨f, hf⟩, rfl⟩⟩ + open UniformSpace in /-- Uniform space structure on `C(α, β)`. @@ -159,7 +163,7 @@ which defines topology of uniform convergence on compact sets. We use `ContinuousMap.tendsto_iff_forall_compact_tendstoUniformlyOn` to show that the induced topology agrees with the compact-open topology and replace the topology with `compactOpen` to avoid non-defeq diamonds, -see Note [forgetful inheritance]. -/ +see Note [forgetful inheritance]. -/ instance compactConvergenceUniformSpace : UniformSpace C(α, β) := .replaceTopology (.comap toUniformOnFunIsCompact inferInstance) <| by refine TopologicalSpace.ext_nhds fun f ↦ eq_of_forall_le_iff fun l ↦ ?_ @@ -330,7 +334,7 @@ theorem uniformSpace_eq_inf_precomp_of_cover {δ₁ δ₂ : Type*} [TopologicalS have h_preimage₂ : MapsTo (φ₂ ⁻¹' ·) 𝔖 𝔗₂ := fun K ↦ h_proper₂.isCompact_preimage have h_cover' : ∀ S ∈ 𝔖, S ⊆ range φ₁ ∪ range φ₂ := fun S _ ↦ h_cover ▸ subset_univ _ -- ... and we just pull it back. - simp_rw [compactConvergenceUniformSpace, replaceTopology_eq, inferInstanceAs, inferInstance, + simp_rw [compactConvergenceUniformSpace, replaceTopology_eq, UniformOnFun.uniformSpace_eq_inf_precomp_of_cover _ _ _ _ _ h_image₁ h_image₂ h_preimage₁ h_preimage₂ h_cover', UniformSpace.comap_inf, ← UniformSpace.comap_comap] @@ -351,9 +355,35 @@ theorem uniformSpace_eq_iInf_precomp_of_cover {δ : ι → Type*} [∀ i, Topolo inter_eq_right.mp ?_⟩ simp_rw [iUnion₂_inter, mem_setOf, iUnion_nonempty_self, ← iUnion_inter, h_cover, univ_inter] -- ... and we just pull it back. - simp_rw [compactConvergenceUniformSpace, replaceTopology_eq, inferInstanceAs, inferInstance, + simp_rw [compactConvergenceUniformSpace, replaceTopology_eq, UniformOnFun.uniformSpace_eq_iInf_precomp_of_cover _ _ _ h_image h_preimage h_cover', UniformSpace.comap_iInf, ← UniformSpace.comap_comap] rfl +section CompleteSpace + +variable [CompleteSpace β] + +/-- If the topology on `α` is generated by its restrictions to compact sets, then the space of +continuous maps `C(α, β)` is complete (wrt the compact convergence uniformity). + +Sufficient conditions on `α` to satisfy this condition are (weak) local compactness (see +`ContinuousMap.instCompleteSpaceOfWeaklyLocallyCompactSpace`) and sequential compactness (see +`ContinuousMap.instCompleteSpaceOfSequentialSpace`). -/ +lemma completeSpace_of_restrictGenTopology (h : RestrictGenTopology {K : Set α | IsCompact K}) : + CompleteSpace C(α, β) := by + rw [completeSpace_iff_isComplete_range uniformEmbedding_toUniformOnFunIsCompact.toUniformInducing, + range_toUniformOnFunIsCompact, ← completeSpace_coe_iff_isComplete] + exact (UniformOnFun.isClosed_setOf_continuous h).completeSpace_coe + +instance instCompleteSpaceOfWeaklyLocallyCompactSpace [WeaklyLocallyCompactSpace α] : + CompleteSpace C(α, β) := + completeSpace_of_restrictGenTopology RestrictGenTopology.isCompact_of_weaklyLocallyCompact + +instance instCompleteSpaceOfSequentialSpace [SequentialSpace α] : + CompleteSpace C(α, β) := + completeSpace_of_restrictGenTopology RestrictGenTopology.isCompact_of_seq + +end CompleteSpace + end ContinuousMap diff --git a/Mathlib/Topology/UniformSpace/Completion.lean b/Mathlib/Topology/UniformSpace/Completion.lean index 6e6085fcbee0d..25ec9b9b1bb0f 100644 --- a/Mathlib/Topology/UniformSpace/Completion.lean +++ b/Mathlib/Topology/UniformSpace/Completion.lean @@ -80,7 +80,7 @@ private theorem symm_gen : map Prod.swap ((𝓤 α).lift' gen) ≤ (𝓤 α).lif { p : CauchyFilter α × CauchyFilter α | s ∈ (p.2.val ×ˢ p.1.val : Filter (α × α)) } have h₁ : map Prod.swap ((𝓤 α).lift' gen) = (𝓤 α).lift' f := by delta gen - simp [map_lift'_eq, monotone_setOf, Filter.monotone_mem, Function.comp, + simp [map_lift'_eq, monotone_setOf, Filter.monotone_mem, Function.comp_def, image_swap_eq_preimage_swap] have h₂ : (𝓤 α).lift' f ≤ (𝓤 α).lift' gen := uniformity_lift_le_swap diff --git a/Mathlib/Topology/UniformSpace/Equicontinuity.lean b/Mathlib/Topology/UniformSpace/Equicontinuity.lean index 98b21924662ae..5fdd4c239966d 100644 --- a/Mathlib/Topology/UniformSpace/Equicontinuity.lean +++ b/Mathlib/Topology/UniformSpace/Equicontinuity.lean @@ -479,7 +479,7 @@ open UniformFun /-- A family `𝓕 : ι → X → α` is equicontinuous at `x₀` iff the function `swap 𝓕 : X → ι → α` is continuous at `x₀` *when `ι → α` is equipped with the topology of uniform convergence*. This is -very useful for developping the equicontinuity API, but it should not be used directly for other +very useful for developing the equicontinuity API, but it should not be used directly for other purposes. -/ theorem equicontinuousAt_iff_continuousAt {F : ι → X → α} {x₀ : X} : EquicontinuousAt F x₀ ↔ ContinuousAt (ofFun ∘ Function.swap F : X → ι →ᵤ α) x₀ := by @@ -489,7 +489,7 @@ theorem equicontinuousAt_iff_continuousAt {F : ι → X → α} {x₀ : X} : /-- A family `𝓕 : ι → X → α` is equicontinuous at `x₀` within `S` iff the function `swap 𝓕 : X → ι → α` is continuous at `x₀` within `S` *when `ι → α` is equipped with the topology of uniform convergence*. This is very useful for -developping the equicontinuity API, but it should not be used directly for other purposes. -/ +developing the equicontinuity API, but it should not be used directly for other purposes. -/ theorem equicontinuousWithinAt_iff_continuousWithinAt {F : ι → X → α} {S : Set X} {x₀ : X} : EquicontinuousWithinAt F S x₀ ↔ ContinuousWithinAt (ofFun ∘ Function.swap F : X → ι →ᵤ α) S x₀ := by @@ -498,7 +498,7 @@ theorem equicontinuousWithinAt_iff_continuousWithinAt {F : ι → X → α} {S : /-- A family `𝓕 : ι → X → α` is equicontinuous iff the function `swap 𝓕 : X → ι → α` is continuous *when `ι → α` is equipped with the topology of uniform convergence*. This is -very useful for developping the equicontinuity API, but it should not be used directly for other +very useful for developing the equicontinuity API, but it should not be used directly for other purposes. -/ theorem equicontinuous_iff_continuous {F : ι → X → α} : Equicontinuous F ↔ Continuous (ofFun ∘ Function.swap F : X → ι →ᵤ α) := by @@ -506,7 +506,7 @@ theorem equicontinuous_iff_continuous {F : ι → X → α} : /-- A family `𝓕 : ι → X → α` is equicontinuous on `S` iff the function `swap 𝓕 : X → ι → α` is continuous on `S` *when `ι → α` is equipped with the topology of uniform convergence*. This is -very useful for developping the equicontinuity API, but it should not be used directly for other +very useful for developing the equicontinuity API, but it should not be used directly for other purposes. -/ theorem equicontinuousOn_iff_continuousOn {F : ι → X → α} {S : Set X} : EquicontinuousOn F S ↔ ContinuousOn (ofFun ∘ Function.swap F : X → ι →ᵤ α) S := by @@ -514,7 +514,7 @@ theorem equicontinuousOn_iff_continuousOn {F : ι → X → α} {S : Set X} : /-- A family `𝓕 : ι → β → α` is uniformly equicontinuous iff the function `swap 𝓕 : β → ι → α` is uniformly continuous *when `ι → α` is equipped with the uniform structure of uniform convergence*. -This is very useful for developping the equicontinuity API, but it should not be used directly +This is very useful for developing the equicontinuity API, but it should not be used directly for other purposes. -/ theorem uniformEquicontinuous_iff_uniformContinuous {F : ι → β → α} : UniformEquicontinuous F ↔ UniformContinuous (ofFun ∘ Function.swap F : β → ι →ᵤ α) := by @@ -524,7 +524,7 @@ theorem uniformEquicontinuous_iff_uniformContinuous {F : ι → β → α} : /-- A family `𝓕 : ι → β → α` is uniformly equicontinuous on `S` iff the function `swap 𝓕 : β → ι → α` is uniformly continuous on `S` *when `ι → α` is equipped with the uniform structure of uniform convergence*. This is very useful -for developping the equicontinuity API, but it should not be used directly for other purposes. -/ +for developing the equicontinuity API, but it should not be used directly for other purposes. -/ theorem uniformEquicontinuousOn_iff_uniformContinuousOn {F : ι → β → α} {S : Set β} : UniformEquicontinuousOn F S ↔ UniformContinuousOn (ofFun ∘ Function.swap F : β → ι →ᵤ α) S := by rw [UniformContinuousOn, (UniformFun.hasBasis_uniformity ι α).tendsto_right_iff] @@ -756,7 +756,7 @@ theorem UniformInducing.uniformEquicontinuousOn_iff {F : ι → β → α} {S : /-- 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 whith a map +this will be applied to `DFunLike` types, we state it for any topological space with a map to `X → α` satisfying the right continuity conditions. See also `Set.EquicontinuousWithinAt.closure` for a more familiar (but weaker) statement. @@ -778,7 +778,7 @@ theorem EquicontinuousWithinAt.closure' {A : Set Y} {u : Y → X → α} {S : Se /-- If a set of functions is equicontinuous at some `x₀`, the same is true for its closure in *any* topology for which evaluation at any point is continuous. Since this will be applied to -`DFunLike` types, we state it for any topological space whith a map to `X → α` satisfying the right +`DFunLike` types, we state it for any topological space with a map to `X → α` satisfying the right continuity conditions. See also `Set.EquicontinuousAt.closure` for a more familiar statement. -/ theorem EquicontinuousAt.closure' {A : Set Y} {u : Y → X → α} {x₀ : X} (hA : EquicontinuousAt (u ∘ (↑) : A → X → α) x₀) (hu : Continuous u) : @@ -802,7 +802,7 @@ protected theorem Set.EquicontinuousWithinAt.closure {A : Set (X → α)} {S : S /-- If a set of functions is equicontinuous, the same is true for its closure in *any* topology for which evaluation at any point is continuous. Since this will be applied to -`DFunLike` types, we state it for any topological space whith a map to `X → α` satisfying the right +`DFunLike` types, we state it for any topological space with a map to `X → α` satisfying the right continuity conditions. See also `Set.Equicontinuous.closure` for a more familiar statement. -/ theorem Equicontinuous.closure' {A : Set Y} {u : Y → X → α} (hA : Equicontinuous (u ∘ (↑) : A → X → α)) (hu : Continuous u) : @@ -810,7 +810,7 @@ theorem Equicontinuous.closure' {A : Set Y} {u : Y → X → α} /-- If a set of functions is equicontinuous on a set `S`, the same is true for its closure in *any* topology for which evaluation at any `x ∈ S` is continuous. Since this will be applied to -`DFunLike` types, we state it for any topological space whith a map to `X → α` satisfying the right +`DFunLike` types, we state it for any topological space with a map to `X → α` satisfying the right continuity conditions. See also `Set.EquicontinuousOn.closure` for a more familiar (but weaker) statement. -/ theorem EquicontinuousOn.closure' {A : Set Y} {u : Y → X → α} {S : Set X} @@ -832,7 +832,7 @@ protected theorem Set.EquicontinuousOn.closure {A : Set <| X → α} {S : Set X} /-- If a set of functions is uniformly equicontinuous on a set `S`, the same is true for its closure in *any* topology for which evaluation at any `x ∈ S` i continuous. Since this will be -applied to `DFunLike` types, we state it for any topological space whith a map to `β → α` satisfying +applied to `DFunLike` types, we state it for any topological space with a map to `β → α` satisfying the right continuity conditions. See also `Set.UniformEquicontinuousOn.closure` for a more familiar (but weaker) statement. -/ theorem UniformEquicontinuousOn.closure' {A : Set Y} {u : Y → β → α} {S : Set β} @@ -850,7 +850,7 @@ theorem UniformEquicontinuousOn.closure' {A : Set Y} {u : Y → β → α} {S : /-- If a set of functions is uniformly equicontinuous, the same is true for its closure in *any* topology for which evaluation at any point is continuous. Since this will be applied to -`DFunLike` types, we state it for any topological space whith a map to `β → α` satisfying the right +`DFunLike` types, we state it for any topological space with a map to `β → α` satisfying the right continuity conditions. See also `Set.UniformEquicontinuous.closure` for a more familiar statement. -/ theorem UniformEquicontinuous.closure' {A : Set Y} {u : Y → β → α} diff --git a/Mathlib/Topology/UniformSpace/Pi.lean b/Mathlib/Topology/UniformSpace/Pi.lean index 6c6f45b6814fc..5c35d1206a3ad 100644 --- a/Mathlib/Topology/UniformSpace/Pi.lean +++ b/Mathlib/Topology/UniformSpace/Pi.lean @@ -42,7 +42,7 @@ instance [Countable ι] [∀ i, IsCountablyGenerated (𝓤 (α i))] : theorem uniformContinuous_pi {β : Type*} [UniformSpace β] {f : β → ∀ i, α i} : UniformContinuous f ↔ ∀ i, UniformContinuous fun x => f x i := by -- Porting note: required `Function.comp` to close - simp only [UniformContinuous, Pi.uniformity, tendsto_iInf, tendsto_comap_iff, Function.comp] + simp only [UniformContinuous, Pi.uniformity, tendsto_iInf, tendsto_comap_iff, Function.comp_def] variable (α) @@ -69,7 +69,7 @@ theorem Pi.uniformContinuous_postcomp {α : Type*} [UniformSpace α] {g : α → lemma Pi.uniformSpace_comap_precomp' (φ : ι' → ι) : UniformSpace.comap (fun g i' ↦ g (φ i')) (Pi.uniformSpace (fun i' ↦ α (φ i'))) = ⨅ i', UniformSpace.comap (eval (φ i')) (U (φ i')) := by - simp [Pi.uniformSpace_eq, UniformSpace.comap_iInf, ← UniformSpace.comap_comap, comp] + simp [Pi.uniformSpace_eq, UniformSpace.comap_iInf, ← UniformSpace.comap_comap, comp_def] lemma Pi.uniformSpace_comap_precomp (φ : ι' → ι) : UniformSpace.comap (· ∘ φ) (Pi.uniformSpace (fun _ ↦ β)) = @@ -124,7 +124,7 @@ protected theorem CompleteSpace.iInf {ι X : Type*} {u : ι → UniformSpace X} -- 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, - Filter.comap_comap, (· ∘ ·), const, Prod.eta, comap_id'] + 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, setOf_forall] diff --git a/Mathlib/Topology/UniformSpace/Separation.lean b/Mathlib/Topology/UniformSpace/Separation.lean index 9d11da63e1ac6..f50de8d5deebd 100644 --- a/Mathlib/Topology/UniformSpace/Separation.lean +++ b/Mathlib/Topology/UniformSpace/Separation.lean @@ -218,7 +218,7 @@ instance instUniformSpace : UniformSpace (SeparationQuotient α) where exact @hUt (x, z) ⟨y', this.mem_open (UniformSpace.isOpen_ball _ hUo) hxyU, hyzU⟩ nhds_eq_comap_uniformity := surjective_mk.forall.2 fun x ↦ comap_injective surjective_mk <| by conv_lhs => rw [comap_mk_nhds_mk, nhds_eq_comap_uniformity, ← comap_map_mk_uniformity] - simp only [Filter.comap_comap, Function.comp, Prod.map_apply] + simp only [Filter.comap_comap, Function.comp_def, Prod.map_apply] theorem uniformity_eq : 𝓤 (SeparationQuotient α) = (𝓤 α).map (Prod.map mk mk) := rfl @@ -285,6 +285,6 @@ theorem map_id : map (@id α) = id := map_unique uniformContinuous_id rfl theorem map_comp {f : α → β} {g : β → γ} (hf : UniformContinuous f) (hg : UniformContinuous g) : map g ∘ map f = map (g ∘ f) := - (map_unique (hg.comp hf) <| by simp only [Function.comp, map_mk, hf, hg]).symm + (map_unique (hg.comp hf) <| by simp only [Function.comp_def, map_mk, hf, hg]).symm end SeparationQuotient diff --git a/Mathlib/Topology/UniformSpace/UniformEmbedding.lean b/Mathlib/Topology/UniformSpace/UniformEmbedding.lean index b674ec1daf22e..a543aabffffb7 100644 --- a/Mathlib/Topology/UniformSpace/UniformEmbedding.lean +++ b/Mathlib/Topology/UniformSpace/UniformEmbedding.lean @@ -67,7 +67,7 @@ theorem UniformInducing.of_comp_iff {g : β → γ} (hg : UniformInducing g) {f UniformInducing (g ∘ f) ↔ UniformInducing f := by refine ⟨fun h ↦ ?_, hg.comp⟩ rw [uniformInducing_iff, ← hg.comap_uniformity, comap_comap, ← h.comap_uniformity, - Function.comp, Function.comp] + Function.comp_def, Function.comp_def] theorem UniformInducing.basis_uniformity {f : α → β} (hf : UniformInducing f) {ι : Sort*} {p : ι → Prop} {s : ι → Set (β × β)} (H : (𝓤 β).HasBasis p s) : @@ -109,7 +109,7 @@ theorem UniformInducing.inducing {f : α → β} (h : UniformInducing f) : Induc theorem UniformInducing.prod {α' : Type*} {β' : Type*} [UniformSpace α'] [UniformSpace β'] {e₁ : α → α'} {e₂ : β → β'} (h₁ : UniformInducing e₁) (h₂ : UniformInducing e₂) : UniformInducing fun p : α × β => (e₁ p.1, e₂ p.2) := - ⟨by simp [(· ∘ ·), uniformity_prod, ← h₁.1, ← h₂.1, comap_inf, comap_comap]⟩ + ⟨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 := @@ -238,9 +238,9 @@ theorem closure_image_mem_nhds_of_uniformInducing {s : Set (α × α)} {e : α ∃ U, (U ∈ 𝓤 β ∧ IsOpen U ∧ SymmetricRel U) ∧ Prod.map e e ⁻¹' U ⊆ s := by rwa [← he₁.comap_uniformity, (uniformity_hasBasis_open_symmetric.comap _).mem_iff] at hs rcases he₂.dense.mem_nhds (UniformSpace.ball_mem_nhds b hU) with ⟨a, ha⟩ - refine ⟨a, mem_of_superset ?_ (closure_mono <| image_subset _ <| ball_mono hs a)⟩ + refine ⟨a, mem_of_superset ?_ (closure_mono <| image_subset _ <| UniformSpace.ball_mono hs a)⟩ have ho : IsOpen (UniformSpace.ball (e a) U) := UniformSpace.isOpen_ball (e a) hUo - refine mem_of_superset (ho.mem_nhds <| (mem_ball_symmetry hsymm).2 ha) fun y hy => ?_ + refine mem_of_superset (ho.mem_nhds <| (UniformSpace.mem_ball_symmetry hsymm).2 ha) fun y hy => ?_ refine mem_closure_iff_nhds.2 fun V hV => ?_ 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⟩ @@ -248,7 +248,7 @@ theorem closure_image_mem_nhds_of_uniformInducing {s : Set (α × α)} {e : α theorem uniformEmbedding_subtypeEmb (p : α → Prop) {e : α → β} (ue : UniformEmbedding e) (de : DenseEmbedding e) : UniformEmbedding (DenseEmbedding.subtypeEmb p e) := { comap_uniformity := by - simp [comap_comap, (· ∘ ·), DenseEmbedding.subtypeEmb, uniformity_subtype, + simp [comap_comap, Function.comp_def, DenseEmbedding.subtypeEmb, uniformity_subtype, ue.comap_uniformity.symm] inj := (de.subtype p).inj } diff --git a/Mathlib/Topology/UnitInterval.lean b/Mathlib/Topology/UnitInterval.lean index 1a8a9c4a3a525..52d5c0fbe4012 100644 --- a/Mathlib/Topology/UnitInterval.lean +++ b/Mathlib/Topology/UnitInterval.lean @@ -162,9 +162,9 @@ instance : Nontrivial I := ⟨⟨1, 0, (one_ne_zero <| congrArg Subtype.val ·) theorem mul_pos_mem_iff {a t : ℝ} (ha : 0 < a) : a * t ∈ I ↔ t ∈ Set.Icc (0 : ℝ) (1 / a) := by constructor <;> rintro ⟨h₁, h₂⟩ <;> constructor · exact nonneg_of_mul_nonneg_right h₁ ha - · rwa [le_div_iff ha, mul_comm] + · rwa [le_div_iff₀ ha, mul_comm] · exact mul_nonneg ha.le h₁ - · rwa [le_div_iff ha, mul_comm] at h₂ + · rwa [le_div_iff₀ ha, mul_comm] at h₂ theorem two_mul_sub_one_mem_iff {t : ℝ} : 2 * t - 1 ∈ I ↔ t ∈ Set.Icc (1 / 2 : ℝ) 1 := by constructor <;> rintro ⟨h₁, h₂⟩ <;> constructor <;> linarith @@ -209,10 +209,15 @@ lemma monotone_addNSMul (hδ : 0 ≤ δ) : Monotone (addNSMul h δ) := lemma abs_sub_addNSMul_le (hδ : 0 ≤ δ) {t : Icc a b} (n : ℕ) (ht : t ∈ Icc (addNSMul h δ n) (addNSMul h δ (n+1))) : (|t - addNSMul h δ n| : α) ≤ δ := - (abs_eq_self.2 <| sub_nonneg.2 ht.1).trans_le <| (sub_le_sub_right (by exact ht.2) _).trans <| - (le_abs_self _).trans <| (abs_projIcc_sub_projIcc h).trans <| by - rw [add_sub_add_comm, sub_self, zero_add, succ_nsmul', add_sub_cancel_right] - exact (abs_eq_self.mpr hδ).le + calc + (|t - addNSMul h δ n| : α) = t - addNSMul h δ n := abs_eq_self.2 <| sub_nonneg.2 ht.1 + _ ≤ projIcc a b h (a + (n+1) • δ) - addNSMul h δ n := + sub_le_sub_right (b := (↑(projIcc a b h (a + (n + 1) • δ)))) (by exact ht.2) _ + _ ≤ (|projIcc a b h (a + (n+1) • δ) - addNSMul h δ n| : α) := le_abs_self _ + _ ≤ |a + (n+1) • δ - (a + n • δ)| := abs_projIcc_sub_projIcc h + _ ≤ δ := by + rw [add_sub_add_comm, sub_self, zero_add, succ_nsmul', add_sub_cancel_right] + exact (abs_eq_self.mpr hδ).le end Set.Icc diff --git a/Mathlib/Topology/UrysohnsLemma.lean b/Mathlib/Topology/UrysohnsLemma.lean index 3c801c768f6b1..9d616a00838cc 100644 --- a/Mathlib/Topology/UrysohnsLemma.lean +++ b/Mathlib/Topology/UrysohnsLemma.lean @@ -230,6 +230,9 @@ theorem tendsto_approx_atTop (c : CU P) (x : X) : theorem lim_of_mem_C (c : CU P) (x : X) (h : x ∈ c.C) : c.lim x = 0 := by simp only [CU.lim, approx_of_mem_C, h, ciSup_const] +theorem disjoint_C_support_lim (c : CU P) : Disjoint c.C (Function.support c.lim) := + Function.disjoint_support_iff.mpr (fun x hx => lim_of_mem_C c x hx) + theorem lim_of_nmem_U (c : CU P) (x : X) (h : x ∉ c.U) : c.lim x = 1 := by simp only [CU.lim, approx_of_nmem_U c _ h, ciSup_const] @@ -431,6 +434,54 @@ theorem exists_continuous_one_zero_of_isCompact_of_isGδ [RegularSpace X] [Local · apply le_trans _ hu.le exact tsum_le_tsum (fun n ↦ I n x) (S x) u_sum +/-- A variation of Urysohn's lemma. In a `T2Space X`, for a closed set `t` and a relatively +compact open set `s` such that `t ⊆ s`, there is a continuous function `f` supported in `s`, +`f x = 1` on `t` and `0 ≤ f x ≤ 1`. -/ +lemma exists_tsupport_one_of_isOpen_isClosed [T2Space X] {s t : Set X} + (hs : IsOpen s) (hscp : IsCompact (closure s)) (ht : IsClosed t) (hst : t ⊆ s) : ∃ f : C(X, ℝ), + tsupport f ⊆ s ∧ EqOn f 1 t ∧ ∀ x, f x ∈ Icc (0 : ℝ) 1 := by +-- separate `sᶜ` and `t` by `u` and `v`. + rw [← compl_compl s] at hscp + obtain ⟨u, v, huIsOpen, hvIsOpen, hscompl_subset_u, ht_subset_v, hDjsjointuv⟩ := + SeparatedNhds.of_isClosed_isCompact_closure_compl_isClosed (isClosed_compl_iff.mpr hs) + hscp ht (HasSubset.Subset.disjoint_compl_left hst) + rw [← subset_compl_iff_disjoint_right] at hDjsjointuv + have huvc : closure u ⊆ vᶜ := closure_minimal hDjsjointuv hvIsOpen.isClosed_compl +-- although `sᶜ` is not compact, `closure s` is compact and we can apply +-- `SeparatedNhds.of_isClosed_isCompact_closure_compl_isClosed`. To apply the condition +-- recursively, we need to make sure that `sᶜ ⊆ C`. + let P : Set X → Prop := fun C => sᶜ ⊆ C + set c : Urysohns.CU P := + { C := closure u + U := tᶜ + P_C := hscompl_subset_u.trans subset_closure + closed_C := isClosed_closure + open_U := ht.isOpen_compl + subset := subset_compl_comm.mp + (Subset.trans ht_subset_v (subset_compl_comm.mp huvc)) + hP := by + intro c u0 cIsClosed Pc u0IsOpen csubu0 + obtain ⟨u1, hu1⟩ := SeparatedNhds.of_isClosed_isCompact_closure_compl_isClosed cIsClosed + (IsCompact.of_isClosed_subset hscp isClosed_closure + (closure_mono (compl_subset_compl.mpr Pc))) + (isClosed_compl_iff.mpr u0IsOpen) (HasSubset.Subset.disjoint_compl_right csubu0) + simp_rw [← subset_compl_iff_disjoint_right, compl_subset_comm (s := u0)] at hu1 + obtain ⟨v1, hu1, hv1, hcu1, hv1u, hu1v1⟩ := hu1 + refine ⟨u1, hu1, hcu1, ?_, (Pc.trans hcu1).trans subset_closure⟩ + exact closure_minimal hu1v1 hv1.isClosed_compl |>.trans hv1u } +-- `c.lim = 0` on `closure u` and `c.lim = 1` on `t`, so that `tsupport c.lim ⊆ s`. + use ⟨c.lim, c.continuous_lim⟩ + simp only [ContinuousMap.coe_mk] + refine ⟨?_, ?_, Urysohns.CU.lim_mem_Icc c⟩ + · apply Subset.trans _ (compl_subset_comm.mp hscompl_subset_u) + rw [← IsClosed.closure_eq (isClosed_compl_iff.mpr huIsOpen)] + apply closure_mono + exact Disjoint.subset_compl_right (disjoint_of_subset_right subset_closure + (Disjoint.symm (Urysohns.CU.disjoint_C_support_lim c))) + · intro x hx + apply Urysohns.CU.lim_of_nmem_U + exact not_mem_compl_iff.mpr hx + theorem exists_continuous_nonneg_pos [RegularSpace X] [LocallyCompactSpace X] (x : X) : ∃ f : C(X, ℝ), HasCompactSupport f ∧ 0 ≤ (f : X → ℝ) ∧ f x ≠ 0 := by rcases exists_compact_mem_nhds x with ⟨k, hk, k_mem⟩ diff --git a/Mathlib/Topology/VectorBundle/Basic.lean b/Mathlib/Topology/VectorBundle/Basic.lean index f7f9be5e65667..cf55b20054f31 100644 --- a/Mathlib/Topology/VectorBundle/Basic.lean +++ b/Mathlib/Topology/VectorBundle/Basic.lean @@ -538,7 +538,7 @@ theorem coordChange_linear_comp (i j k : ι) : @[nolint unusedArguments] -- Porting note(#5171): was `nolint has_nonempty_instance` def Index := ι -/-- The base space of a vector bundle core, as a convenience function for dot notation-/ +/-- The base space of a vector bundle core, as a convenience function for dot notation -/ @[nolint unusedArguments, reducible] def Base := B diff --git a/Mathlib/Topology/VectorBundle/Hom.lean b/Mathlib/Topology/VectorBundle/Hom.lean index db2f9b8915afc..3b7a3339e4105 100644 --- a/Mathlib/Topology/VectorBundle/Hom.lean +++ b/Mathlib/Topology/VectorBundle/Hom.lean @@ -58,12 +58,6 @@ Porting note: after the port is done, we may want to remove this definition. protected abbrev Bundle.ContinuousLinearMap [∀ x, TopologicalSpace (E₁ x)] [∀ x, TopologicalSpace (E₂ x)] : B → Type _ := fun x => E₁ x →SL[σ] E₂ x --- Porting note: possibly remove after the port -instance Bundle.ContinuousLinearMap.module [∀ x, TopologicalSpace (E₁ x)] - [∀ x, TopologicalSpace (E₂ x)] [∀ x, TopologicalAddGroup (E₂ x)] - [∀ x, ContinuousConstSMul 𝕜₂ (E₂ x)] : ∀ x, Module 𝕜₂ (Bundle.ContinuousLinearMap σ E₁ E₂ x) := - fun _ => inferInstance - variable {E₁ E₂} variable [TopologicalSpace B] (e₁ e₁' : Trivialization F₁ (π F₁ E₁)) (e₂ e₂' : Trivialization F₂ (π F₂ E₂)) @@ -97,15 +91,9 @@ theorem continuousOn_continuousLinearMapCoordChange [RingHomIsometric σ] refine ((h₁.comp_continuousOn (h₄.mono ?_)).clm_comp (h₂.comp_continuousOn (h₃.mono ?_))).congr ?_ · mfld_set_tac · mfld_set_tac - · intro b _; ext L v - -- Porting note: was - -- simp only [continuousLinearMapCoordChange, ContinuousLinearEquiv.coe_coe, - -- ContinuousLinearEquiv.arrowCongrₛₗ_apply, LinearEquiv.toFun_eq_coe, coe_comp', - -- ContinuousLinearEquiv.arrowCongrSL_apply, comp_apply, Function.comp, compSL_apply, - -- flip_apply, ContinuousLinearEquiv.symm_symm] - -- Now `simp` fails to use `ContinuousLinearMap.comp_apply` in this case + · intro b _ + ext L v dsimp [continuousLinearMapCoordChange] - rw [ContinuousLinearEquiv.symm_symm] variable (σ e₁ e₁' e₂ e₂') variable [e₁.IsLinear 𝕜₁] [e₁'.IsLinear 𝕜₁] [e₂.IsLinear 𝕜₂] [e₂'.IsLinear 𝕜₂] diff --git a/Mathlib/Util/AssertExists.lean b/Mathlib/Util/AssertExists.lean index 910bc40c84fef..2995ff633ca25 100644 --- a/Mathlib/Util/AssertExists.lean +++ b/Mathlib/Util/AssertExists.lean @@ -5,6 +5,7 @@ Authors: Patrick Massot, Scott Morrison -/ import Mathlib.Init import Lean.Elab.Command +import Mathlib.Util.AssertExistsExt /-! # User commands for assert the (non-)existence of declaration or instances. @@ -22,6 +23,49 @@ Implement `assert_instance` and `assert_no_instance` section open Lean Elab Meta Command +namespace Mathlib.AssertNotExist + +/-- `#check_assertions` retrieves all declarations and all imports that were declared +not to exist so far (including in transitively imported files) and reports their current +status: +* ✓ means the declaration or import exists, +* × means the declaration or import does not exist. + +This means that the expectation is that all checks *succeed* by the time `#check_assertions` +is used, typically once all of `Mathlib` has been built. + +If all declarations and imports are available when `#check_assertions` is used, +then the command logs an info. Otherwise, it emits a warning. + +The variant `#check_assertions!` only prints declarations/imports that are not present in the +environment. In particular, it is silent if everything is imported, making it useful for testing. +-/ +elab "#check_assertions" tk:("!")?: command => do + let env ← getEnv + let entries := env.getSortedAssertExists + if entries.isEmpty && tk.isNone then logInfo "No assertions made." else + let allMods := env.allImportedModuleNames + let mut msgs := #[m!""] + let mut outcome := m!"" + let mut allExist? := true + for d in entries do + let type := if d.isDecl then "declaration" else "module" + let cond := if d.isDecl then env.contains d.givenName else allMods.contains d.givenName + outcome := if cond then m!"{checkEmoji}" else m!"{crossEmoji}" + allExist? := allExist? && cond + if tk.isNone || !cond then + msgs := msgs.push m!"{outcome} '{d.givenName}' ({type}) asserted in '{d.modName}'." + msgs := msgs.push m!"---" + |>.push m!"{checkEmoji} means the declaration or import exists." + |>.push m!"{crossEmoji} means the declaration or import does not exist." + let msg := MessageData.joinSep msgs.toList "\n" + if allExist? && tk.isNone then + logInfo msg + if !allExist? then + logWarning msg + +end Mathlib.AssertNotExist + /-- `assert_exists n` is a user command that asserts that a declaration named `n` exists in the current import scope. @@ -52,7 +96,11 @@ You should *not* delete the `assert_not_exists` statement without careful discus `assert_not_exists` statements should generally live at the top of the file, after the module doc. -/ elab "assert_not_exists " n:ident : command => do - let decl ← try liftCoreM <| realizeGlobalConstNoOverloadWithInfo n catch _ => return + let decl ← + try liftCoreM <| realizeGlobalConstNoOverloadWithInfo n + catch _ => + Mathlib.AssertNotExist.addDeclEntry true n.getId (← getMainModule) + return let env ← getEnv let c ← mkConstWithLevelParams decl let msg ← (do @@ -79,6 +127,9 @@ The command does not currently check whether the modules `m₁ m₂ ... mₙ` ac elab "assert_not_imported " ids:ident+ : command => do let mods := (← getEnv).allImportedModuleNames for id in ids do - if mods.contains id.getId then logWarningAt id m!"the module '{id}' is (transitively) imported" + if mods.contains id.getId then + logWarningAt id m!"the module '{id}' is (transitively) imported" + else + Mathlib.AssertNotExist.addDeclEntry false id.getId (← getMainModule) end diff --git a/Mathlib/Util/AssertExistsExt.lean b/Mathlib/Util/AssertExistsExt.lean new file mode 100644 index 0000000000000..e97a78563f4cf --- /dev/null +++ b/Mathlib/Util/AssertExistsExt.lean @@ -0,0 +1,57 @@ +/- +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.Environment + +/-! +# Environment extension for tracking existence of declarations and imports + +This is used by the `assert_not_exists` and `assert_not_imported` commands. +-/ + +section +open Lean Elab Meta + +namespace Mathlib.AssertNotExist + +/-- `AssertExists` is the structure that carries the data to check if a declaration or an +import are meant to exist somewhere in Mathlib. -/ +structure AssertExists where + /-- The type of the assertion: `true` means declaration, `false` means import. -/ + isDecl : Bool + /-- The fully qualified name of a declaration that is expected to exist. -/ + givenName : Name + /-- The name of the module where the assertion was made. -/ + modName : Name + deriving BEq, Hashable + +/-- Defines the `assertExistsExt` extension for adding a `HashSet` of `AssertExists`s +to the environment. -/ +initialize assertExistsExt : SimplePersistentEnvExtension AssertExists (Std.HashSet AssertExists) ← + registerSimplePersistentEnvExtension { + addImportedFn := fun as => as.foldl Std.HashSet.insertMany {} + addEntryFn := .insert + } + +/-- +`addDeclEntry isDecl declName mod` takes as input the `Bool`ean `isDecl` and the `Name`s of +a declaration or import, `declName`, and of a module, `mod`. +It extends the `AssertExists` environment extension with the data `isDecl, declName, mod`. +This information is used to capture declarations and modules that are required to not +exist/be imported at some point, but should eventually exist/be imported. +-/ +def addDeclEntry {m : Type → Type} [MonadEnv m] (isDecl : Bool) (declName mod : Name) : m Unit := + modifyEnv (assertExistsExt.addEntry · { isDecl := isDecl, givenName := declName, modName := mod }) + +end Mathlib.AssertNotExist + +open Mathlib.AssertNotExist + +/-- `getSortedAssertExists env` returns the array of `AssertExists`, placing first all declarations, +in alphabetical order, and then all modules, also in alphabetical order. -/ +def Lean.Environment.getSortedAssertExists (env : Environment) : Array AssertExists := + assertExistsExt.getState env |>.toArray.qsort fun d e => (e.isDecl < d.isDecl) || + (e.isDecl == d.isDecl && (d.givenName.toString < e.givenName.toString)) diff --git a/Mathlib/Util/CompileInductive.lean b/Mathlib/Util/CompileInductive.lean index 421224f1fa26e..5c98f82d30a38 100644 --- a/Mathlib/Util/CompileInductive.lean +++ b/Mathlib/Util/CompileInductive.lean @@ -7,6 +7,7 @@ import Mathlib.Init import Lean.Elab.Command import Lean.Compiler.CSimpAttr import Lean.Util.FoldConsts +import Lean.Data.AssocList /-! # Define the `compile_inductive%` command. diff --git a/Mathlib/Util/Delaborators.lean b/Mathlib/Util/Delaborators.lean index 561a55e9df20d..b45007dc4e2af 100644 --- a/Mathlib/Util/Delaborators.lean +++ b/Mathlib/Util/Delaborators.lean @@ -164,4 +164,4 @@ open Lean Lean.PrettyPrinter.Delaborator guard <| f.isAppOfArity ``Membership.mem 5 let stx₁ ← SubExpr.withAppArg <| SubExpr.withNaryArg 3 delab let stx₂ ← SubExpr.withAppArg <| SubExpr.withNaryArg 4 delab - return ← `($stx₁ ∉ $stx₂) + return ← `($stx₂ ∉ $stx₁) diff --git a/Mathlib/Util/Export.lean b/Mathlib/Util/Export.lean index 503e077034a09..cf8ba9f835a02 100644 --- a/Mathlib/Util/Export.lean +++ b/Mathlib/Util/Export.lean @@ -13,7 +13,8 @@ A rudimentary export format, adapted from with support for lean 4 kernel primitives. -/ -open Lean (HashMap HashSet) +open Lean +open Std (HashMap HashSet) namespace Lean @@ -36,15 +37,15 @@ instance : Coe Level Entry := ⟨Entry.level⟩ instance : Coe Expr Entry := ⟨Entry.expr⟩ structure Alloc (α) [BEq α] [Hashable α] where - map : HashMap α Nat + map : Std.HashMap α Nat next : Nat deriving Inhabited structure State where - names : Alloc Name := ⟨HashMap.empty.insert Name.anonymous 0, 1⟩ - levels : Alloc Level := ⟨HashMap.empty.insert levelZero 0, 1⟩ + names : Alloc Name := ⟨Std.HashMap.empty.insert Name.anonymous 0, 1⟩ + levels : Alloc Level := ⟨Std.HashMap.empty.insert levelZero 0, 1⟩ exprs : Alloc Expr - defs : HashSet Name + defs : Std.HashSet Name stk : Array (Bool × Entry) deriving Inhabited @@ -76,7 +77,7 @@ def alloc {α} [BEq α] [Hashable α] [OfState α] (a : α) : ExportM Nat := do pure n def exportName (n : Name) : ExportM Nat := do - match (← get).names.map.find? n with + match (← get).names.map[n]? with | some i => pure i | none => match n with | .anonymous => pure 0 @@ -84,7 +85,7 @@ def exportName (n : Name) : ExportM Nat := do | .str p s => let i ← alloc n; IO.println s!"{i} #NS {← exportName p} {s}"; pure i def exportLevel (L : Level) : ExportM Nat := do - match (← get).levels.map.find? L with + match (← get).levels.map[L]? with | some i => pure i | none => match L with | .zero => pure 0 @@ -108,7 +109,7 @@ open ConstantInfo in mutual partial def exportExpr (E : Expr) : ExportM Nat := do - match (← get).exprs.map.find? E with + match (← get).exprs.map[E]? with | some i => pure i | none => match E with | .bvar n => let i ← alloc E; IO.println s!"{i} #EV {n}"; pure i diff --git a/Mathlib/Util/LongNames.lean b/Mathlib/Util/LongNames.lean index 1551a5e5ae21e..43e6789218bc4 100644 --- a/Mathlib/Util/LongNames.lean +++ b/Mathlib/Util/LongNames.lean @@ -5,6 +5,7 @@ Authors: Scott Morrison -/ import Mathlib.Lean.Name import Mathlib.Lean.Expr.Basic +import Lean.Elab.Command /-! # Commands `#long_names` and `#long_instances` diff --git a/Mathlib/Util/MemoFix.lean b/Mathlib/Util/MemoFix.lean index 75a5d913d317d..0dead3fbcac55 100644 --- a/Mathlib/Util/MemoFix.lean +++ b/Mathlib/Util/MemoFix.lean @@ -3,8 +3,8 @@ Copyright (c) 2022 Gabriel Ebner. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Gabriel Ebner, Edward Ayers -/ +import Std.Data.HashMap.Basic import Mathlib.Init -import Lean.Data.HashMap /-! # Fixpoint function with memoisation @@ -12,15 +12,15 @@ import Lean.Data.HashMap -/ universe u v -open ShareCommon +open ShareCommon Std -private unsafe abbrev ObjectMap := @Lean.HashMap Object Object ⟨Object.ptrEq⟩ ⟨Object.hash⟩ +private unsafe abbrev ObjectMap := @Std.HashMap Object Object ⟨Object.ptrEq⟩ ⟨Object.hash⟩ private unsafe def memoFixImplObj (f : (Object → Object) → (Object → Object)) (a : Object) : Object := unsafeBaseIO do let cache : IO.Ref ObjectMap ← ST.mkRef ∅ let rec fix (a) := unsafeBaseIO do - if let some b := (← cache.get).find? a then + if let some b := (← cache.get)[a]? then return b let b := f fix a cache.modify (·.insert a b) diff --git a/Mathlib/Util/Notation3.lean b/Mathlib/Util/Notation3.lean index e7f520311181c..9ca6324227c12 100644 --- a/Mathlib/Util/Notation3.lean +++ b/Mathlib/Util/Notation3.lean @@ -97,12 +97,12 @@ structure MatchState where that have been found so far during the course of the matching algorithm. We store the contexts since we need to delaborate expressions after we leave scoping constructs. -/ - vars : HashMap Name (SubExpr × LocalContext × LocalInstances) + vars : Std.HashMap Name (SubExpr × LocalContext × LocalInstances) /-- The binders accumulated while matching a `scoped` expression. -/ scopeState : Option (Array (TSyntax ``extBinderParenthesized)) /-- The arrays of delaborated `Term`s accumulated while matching `foldl` and `foldr` expressions. For `foldl`, the arrays are stored in reverse order. -/ - foldState : HashMap Name (Array Term) + foldState : Std.HashMap Name (Array Term) /-- A matcher is a delaboration function that transforms `MatchState`s. -/ def Matcher := MatchState → DelabM MatchState @@ -118,7 +118,7 @@ def MatchState.empty : MatchState where saved context. Fails if the variable has no value. -/ def MatchState.withVar {α : Type} (s : MatchState) (name : Name) (m : DelabM α) : DelabM α := do - let some (se, lctx, linsts) := s.vars.find? name | failure + let some (se, lctx, linsts) := s.vars[name]? | failure withLCtx lctx linsts <| withTheReader SubExpr (fun _ => se) <| m /-- Delaborate the given variable's value. Fails if the variable has no value. @@ -138,7 +138,7 @@ def MatchState.captureSubexpr (s : MatchState) (name : Name) : DelabM MatchState /-- Get the accumulated array of delaborated terms for a given foldr/foldl. Returns `#[]` if nothing has been pushed yet. -/ def MatchState.getFoldArray (s : MatchState) (name : Name) : Array Term := - (s.foldState.find? name).getD #[] + s.foldState[name]?.getD #[] /-- Get the accumulated array of delaborated terms for a given foldr/foldl. Returns `#[]` if nothing has been pushed yet. -/ @@ -153,7 +153,7 @@ def MatchState.pushFold (s : MatchState) (name : Name) (t : Term) : MatchState : /-- Matcher that assigns the current `SubExpr` into the match state; if a value already exists, then it checks for equality. -/ def matchVar (c : Name) : Matcher := fun s => do - if let some (se, _, _) := s.vars.find? c then + if let some (se, _, _) := s.vars[c]? then guard <| se.expr == (← getExpr) return s else @@ -206,7 +206,7 @@ def matchLambda (matchDom : Matcher) (matchBody : Expr → Matcher) : Matcher := with types that are fresh metavariables. This is used for example when initializing `p` in `(scoped p => ...)` when elaborating `...`. -/ def setupLCtx (lctx : LocalContext) (boundNames : Array Name) : - MetaM (LocalContext × HashMap FVarId Name) := do + MetaM (LocalContext × Std.HashMap FVarId Name) := do let mut lctx := lctx let mut boundFVars := {} for name in boundNames do @@ -224,18 +224,18 @@ If it succeeds generating a matcher, returns 1. a list of keys that should be used for the `delab` attribute when defining the elaborator 2. a `Term` that represents a `Matcher` for the given expression `e`. -/ -partial def exprToMatcher (boundFVars : HashMap FVarId Name) (localFVars : HashMap FVarId Term) - (e : Expr) : +partial def exprToMatcher (boundFVars : Std.HashMap FVarId Name) + (localFVars : Std.HashMap FVarId Term) (e : Expr) : OptionT TermElabM (List Name × Term) := do match e with | .mvar .. => return ([], ← `(pure)) | .const n _ => return ([`app ++ n], ← ``(matchExpr (Expr.isConstOf · $(quote n)))) | .sort .. => return ([`sort], ← ``(matchExpr Expr.isSort)) | .fvar fvarId => - if let some n := boundFVars.find? fvarId then + if let some n := boundFVars[fvarId]? then -- This fvar is a pattern variable. return ([], ← ``(matchVar $(quote n))) - else if let some s := localFVars.find? fvarId then + else if let some s := localFVars[fvarId]? then -- This fvar is bound by a lambda or forall expression in the pattern itself return ([], ← ``(matchExpr (· == $s))) else @@ -377,7 +377,7 @@ partial def matchFoldl (lit x y : Name) (smatcher : Matcher) (sinit : Matcher) : -- y gives the next element of the list let s := s.pushFold lit (← s.delabVar y expr) -- x gives the next lit - let some newLit := s.vars.find? x | failure + let some newLit := s.vars[x]? | failure -- If progress was not made, fail if newLit.1.expr == expr then failure -- Progress was made, so recurse @@ -462,13 +462,13 @@ elab (name := notation3) doc:(docComment)? attrs?:(Parser.Term.attributes)? attr pp?:(ppSpace prettyPrintOpt)? items:(ppSpace notation3Item)+ " => " val:term : command => do -- We use raw `Name`s for variables. This maps variable names back to the -- identifiers that appear in `items` - let mut boundIdents : HashMap Name Ident := {} + let mut boundIdents : Std.HashMap Name Ident := {} -- Replacements to use for the `macro` - let mut boundValues : HashMap Name Syntax := {} + let mut boundValues : Std.HashMap Name Syntax := {} -- The names of the bound names in order, used when constructing patterns for delaboration. let mut boundNames : Array Name := #[] -- The normal/foldl/foldr type of each variable (for delaborator) - let mut boundType : HashMap Name BoundValueType := {} + let mut boundType : Std.HashMap Name BoundValueType := {} -- Function to update `syntaxArgs` and `pattArgs` using `macroArg` syntax let pushMacro (syntaxArgs : Array (TSyntax `stx)) (pattArgs : Array Syntax) (mac : TSyntax ``macroArg) := do @@ -506,8 +506,8 @@ elab (name := notation3) doc:(docComment)? attrs?:(Parser.Term.attributes)? attr (syntaxArgs, pattArgs) ← pushMacro syntaxArgs pattArgs <| ← `(macroArg| $id:ident:sepBy(term $(prec?)?, $sep:str)) -- N.B. `Syntax.getId` returns `.anonymous` for non-idents - let scopedTerm' ← scopedTerm.replaceM fun s => pure (boundValues.find? s.getId) - let init' ← init.replaceM fun s => pure (boundValues.find? s.getId) + let scopedTerm' ← scopedTerm.replaceM fun s => pure boundValues[s.getId]? + let init' ← init.replaceM fun s => pure boundValues[s.getId]? boundIdents := boundIdents.insert id.getId id match kind with | `(foldKind| foldl) => @@ -531,7 +531,7 @@ elab (name := notation3) doc:(docComment)? attrs?:(Parser.Term.attributes)? attr `(macroArg| $lit:ident:term $(prec?)?) matchers := matchers.push <| mkScopedMatcher lit.getId scopedId.getId scopedTerm boundNames - let scopedTerm' ← scopedTerm.replaceM fun s => pure (boundValues.find? s.getId) + let scopedTerm' ← scopedTerm.replaceM fun s => pure boundValues[s.getId]? boundIdents := boundIdents.insert lit.getId lit boundValues := boundValues.insert lit.getId <| ← `(expand_binders% ($scopedId => $scopedTerm') $$binders:extBinders, @@ -560,7 +560,7 @@ elab (name := notation3) doc:(docComment)? attrs?:(Parser.Term.attributes)? attr let fullName := currNamespace ++ name trace[notation3] "syntax declaration has name {fullName}" let pat : Term := ⟨mkNode fullName pattArgs⟩ - let val' ← val.replaceM fun s => pure (boundValues.find? s.getId) + let val' ← val.replaceM fun s => pure boundValues[s.getId]? let mut macroDecl ← `(macro_rules | `($pat) => `($val')) if isLocalAttrKind attrKind then -- For local notation, take section variables into account @@ -584,7 +584,7 @@ elab (name := notation3) doc:(docComment)? attrs?:(Parser.Term.attributes)? attr trace[notation3] "matcher:{indentD matcher}" let mut result ← `(`($pat)) for (name, id) in boundIdents.toArray do - match boundType.findD name .normal with + match boundType.getD name .normal with | .normal => result ← `(MatchState.delabVar s $(quote name) (some e) >>= fun $id => $result) | .foldl => result ← `(let $id := (MatchState.getFoldArray s $(quote name)).reverse; $result) diff --git a/Mathlib/Util/SleepHeartbeats.lean b/Mathlib/Util/SleepHeartbeats.lean index f6cb76c320e8d..7716e32f74a86 100644 --- a/Mathlib/Util/SleepHeartbeats.lean +++ b/Mathlib/Util/SleepHeartbeats.lean @@ -34,6 +34,7 @@ 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 0bf0bdb933aa2..a696144b7f9fe 100644 --- a/Mathlib/Util/Superscript.lean +++ b/Mathlib/Util/Superscript.lean @@ -29,7 +29,7 @@ universe u namespace Mathlib.Tactic -open Lean Parser PrettyPrinter +open Lean Parser PrettyPrinter Std namespace Superscript @@ -38,9 +38,9 @@ instance : Hashable Char := ⟨fun c => hash c.1⟩ /-- A bidirectional character mapping. -/ structure Mapping where /-- Map from "special" (e.g. superscript) characters to "normal" characters. -/ - toNormal : HashMap Char Char := {} + toNormal : Std.HashMap Char Char := {} /-- Map from "normal" text to "special" (e.g. superscript) characters. -/ - toSpecial : HashMap Char Char := {} + toSpecial : Std.HashMap Char Char := {} deriving Inhabited /-- Constructs a mapping (intended for compile time use). Panics on violated invariants. -/ @@ -128,7 +128,7 @@ partial def scriptFnNoAntiquot (m : Mapping) (errorMsg : String) (p : ParserFn) let mut pos := start while pos < stopTk do let c := input.get pos - let c' := m.toNormal.find! c + let c' := m.toNormal[c]! newStr := newStr.push c' pos := pos + c if c.utf8Size != c'.utf8Size then @@ -213,7 +213,7 @@ def scriptParser.formatter (name : String) (m : Mapping) (k : SyntaxNodeKind) (p Formatter.node.formatter k p let st ← get let transformed : Except String _ := st.stack.mapM (·.mapStringsM fun s => do - let .some s := s.toList.mapM (m.toSpecial.insert ' ' ' ').find? | .error s + let .some s := s.toList.mapM (m.toSpecial.insert ' ' ' ').get? | .error s .ok ⟨s⟩) match transformed with | .error err => diff --git a/Mathlib/Util/Time.lean b/Mathlib/Util/Time.lean deleted file mode 100644 index 26da53c0c13ce..0000000000000 --- a/Mathlib/Util/Time.lean +++ /dev/null @@ -1,36 +0,0 @@ -/- -Copyright (c) 2021 Mario Carneiro. All rights reserved. -Released under Apache 2.0 license as described in the file LICENSE. -Authors: Mario Carneiro --/ -import Mathlib.Init -import Lean - -/-! -# Defines `#time` command. - -Time the elaboration of a command, and print the result (in milliseconds). --/ - -section -open Lean Elab Command - -syntax (name := timeCmd) "#time " command : command - -/-- -Time the elaboration of a command, and print the result (in milliseconds). - -Example usage: -``` -set_option maxRecDepth 100000 in -#time example : (List.range 500).length = 500 := rfl -``` --/ -@[command_elab timeCmd] def timeCmdElab : CommandElab - | `(#time%$tk $stx:command) => do - let start ← IO.monoMsNow - elabCommand stx - logInfoAt tk m!"time: {(← IO.monoMsNow) - start}ms" - | _ => throwUnsupportedSyntax - -end diff --git a/Shake/Main.lean b/Shake/Main.lean index b6787a87fd6cf..e5b7645a31d81 100644 --- a/Shake/Main.lean +++ b/Shake/Main.lean @@ -81,7 +81,7 @@ abbrev Bitset := Nat /-- The main state of the checker, containing information on all loaded modules. -/ structure State where /-- Maps a module name to its index in the module list. -/ - toIdx : HashMap Name USize := {} + toIdx : Std.HashMap Name USize := {} /-- Maps a module index to the module name. -/ modNames : Array Name := #[] /-- Maps a module index to the module data. -/ @@ -96,7 +96,7 @@ structure State where /-- Maps a constant name to the module index containing it. A value of `none` means the constant was found in multiple modules, in which case we do not track it. -/ - constToIdx : HashMap Name (Option USize) := {} + constToIdx : Std.HashMap Name (Option USize) := {} /-- Returns `true` if this is a constant whose body should not be considered for dependency tracking purposes. -/ @@ -110,7 +110,7 @@ def isBlacklisted (name : Name) : Bool := /-- Calculates the value of the `needs[i]` bitset for a given module `mod`. Bit `j` is set in the result if some constant from module `j` is used in this module. -/ -def calcNeeds (constToIdx : HashMap Name (Option USize)) (mod : ModuleData) : Bitset := +def calcNeeds (constToIdx : Std.HashMap Name (Option USize)) (mod : ModuleData) : Bitset := mod.constants.foldl (init := 0) fun deps ci => if isBlacklisted ci.name then deps else let deps := visitExpr ci.type deps @@ -120,13 +120,13 @@ def calcNeeds (constToIdx : HashMap Name (Option USize)) (mod : ModuleData) : Bi where /-- Accumulate the results from expression `e` into `deps`. -/ visitExpr e deps := - Lean.Expr.foldConsts e deps fun c deps => match constToIdx.find? c with + Lean.Expr.foldConsts e deps fun c deps => match constToIdx[c]? with | some (some i) => deps ||| (1 <<< i.toNat) | _ => deps /-- Calculates the same as `calcNeeds` but tracing each module to a specific constant. -/ -def getExplanations (constToIdx : HashMap Name (Option USize)) (mod : ModuleData) : - HashMap USize (Name × Name) := +def getExplanations (constToIdx : Std.HashMap Name (Option USize)) (mod : ModuleData) : + Std.HashMap USize (Name × Name) := mod.constants.foldl (init := {}) fun deps ci => if isBlacklisted ci.name then deps else let deps := visitExpr ci.name ci.type deps @@ -136,10 +136,10 @@ def getExplanations (constToIdx : HashMap Name (Option USize)) (mod : ModuleData where /-- Accumulate the results from expression `e` into `deps`. -/ visitExpr name e deps := - Lean.Expr.foldConsts e deps fun c deps => match constToIdx.find? c with + Lean.Expr.foldConsts e deps fun c deps => match constToIdx[c]? with | some (some i) => if - if let some (name', _) := deps.find? i then + if let some (name', _) := deps[i]? then decide (name.toString.length < name'.toString.length) else true then @@ -159,7 +159,7 @@ partial def loadModules (imports : Array Import) : StateT State IO (Array USize let mut transImps := 0 for imp in imports do let s ← get - if let some i := s.toIdx.find? imp.module then + if let some i := s.toIdx[imp.module]? then imps := imps.push i transImps := transImps ||| s.transDeps[i]! else @@ -181,14 +181,14 @@ partial def loadModules (imports : Array Import) : StateT State IO (Array USize transDeps := s.transDeps.push transDeps needs := s.needs constToIdx := mod.constNames.foldl (init := s.constToIdx) fun m a => - match m.insertIfNew a n with - | (m, some (some _)) => + match m.getThenInsertIfNew? a n with + | (some (some _), m) => -- Note: If a constant is found in multiple modules, we assume it is an auto-generated -- definition which is created on demand, and therefore it is safe to ignore any -- dependencies via this definition because it will just be re-created in the current -- module if we don't import it. m.insert a none - | (m, _) => m + | (_, m) => m } return (imps, transImps) @@ -198,17 +198,17 @@ partial def loadModules (imports : Array Import) : StateT State IO (Array USize * If `j ∈ added` then we want to add module index `j` to the imports of `i`. We keep this as a bitset because we will do transitive reduction before applying it -/ -def Edits := HashMap Name (NameSet × Bitset) +def Edits := Std.HashMap Name (NameSet × Bitset) /-- Register that we want to remove `tgt` from the imports of `src`. -/ def Edits.remove (ed : Edits) (src tgt : Name) : Edits := - match ed.find? src with + match ed.get? src with | none => ed.insert src (RBTree.insert ∅ tgt, 0) | some (a, b) => ed.insert src (a.insert tgt, b) /-- Register that we want to add `tgt` to the imports of `src`. -/ def Edits.add (ed : Edits) (src : Name) (tgt : Nat) : Edits := - match ed.find? src with + match ed.get? src with | none => ed.insert src (∅, 1 <<< tgt) | some (a, b) => ed.insert src (a, b ||| (1 <<< tgt)) @@ -262,7 +262,7 @@ def visitModule (s : State) (srcSearchPath : SearchPath) (ignoreImps : Bitset) let mut toRemove := #[] let mut newDeps := 0 for imp in s.mods[i]!.imports do - let j := s.toIdx.find! imp.module + let j := s.toIdx[imp.module]! if transDeps &&& (1 <<< j.toNat) == 0 then toRemove := toRemove.push j else @@ -360,11 +360,11 @@ def visitModule (s : State) (srcSearchPath : SearchPath) (ignoreImps : Bitset) if explain then let explanation := getExplanations s.constToIdx s.mods[i]! let sanitize n := if n.hasMacroScopes then (sanitizeName n).run' { options := {} } else n - let run j := do - if let some (n, c) := explanation.find? j then + let run (j : USize) := do + if let some (n, c) := explanation[j]? then println! " note: {s.modNames[i]!} requires {s.modNames[j]!}\ \n because {sanitize n} refers to {sanitize c}" - for imp in s.mods[i]!.imports do run <| s.toIdx.find! imp.module + for imp in s.mods[i]!.imports do run <| s.toIdx[imp.module]! for i in toAdd do run i.toUSize return edits @@ -372,7 +372,7 @@ def visitModule (s : State) (srcSearchPath : SearchPath) (ignoreImps : Bitset) /-- Convert a list of module names to a bitset of module indexes -/ def toBitset (s : State) (ns : List Name) : Bitset := ns.foldl (init := 0) fun c name => - match s.toIdx.find? name with + match s.toIdx[name]? with | some i => c ||| (1 <<< i.toNat) | none => c @@ -470,7 +470,7 @@ def main (args : List String) : IO UInt32 := do -- Parse the config file let ignoreMods := toBitset s (cfg.ignoreAll?.getD []) let ignoreImps := toBitset s (cfg.ignoreImport?.getD []) - let ignore := (cfg.ignore?.getD {}).fold (init := mkHashMap) fun m a v => + let ignore := (cfg.ignore?.getD {}).fold (init := Std.HashMap.empty) fun m a v => m.insert a (toBitset s v.toList) let noIgnore (i : Nat) := @@ -493,11 +493,11 @@ def main (args : List String) : IO UInt32 := do println! "The following changes will be made automatically:" -- Check all selected modules - let mut edits : Edits := mkHashMap + let mut edits : Edits := Std.HashMap.empty for i in [0:s.mods.size], t in needs do if let some t := t then if noIgnore i then - let ignoreImps := ignoreImps ||| ignore.findD s.modNames[i]! 0 + let ignoreImps := ignoreImps ||| ignore.getD s.modNames[i]! 0 edits ← visitModule s srcSearchPath ignoreImps i t.get edits args.downstream args.githubStyle args.explain diff --git a/docs/overview.yaml b/docs/overview.yaml index 5d884c7e1cabb..be28612dbf810 100644 --- a/docs/overview.yaml +++ b/docs/overview.yaml @@ -231,7 +231,7 @@ Topology: Topological algebra: order topology: 'OrderTopology' intermediate value theorem: 'intermediate_value_Icc' - extreme value theorem: 'IsCompact.exists_forall_le' + extreme value theorem: 'IsCompact.exists_isMinOn' limit infimum and supremum: 'order/liminf_limsup.html' topological group: 'TopologicalGroup' completion of an abelian topological group: 'UniformSpace.Completion.instAddCommGroup' diff --git a/docs/references.bib b/docs/references.bib index b98a31a74d6fb..71178e6a2c7f3 100644 --- a/docs/references.bib +++ b/docs/references.bib @@ -944,6 +944,23 @@ @Misc{ conradQ eprint = {https://kconrad.math.uconn.edu/blurbs/gradnumthy/ostrowskiQ.pdf} } +@Book{ conway1990, + author = {Conway, John B.}, + title = {A course in functional analysis.}, + edition = {2nd ed.}, + fseries = {Graduate Texts in Mathematics}, + series = {Grad. Texts Math.}, + issn = {0072-5285}, + volume = {96}, + isbn = {0-387-97245-5}, + year = {1990}, + publisher = {New York etc.: Springer-Verlag}, + language = {English}, + keywords = {46-02,47-02,47A53}, + zbmath = {47995}, + zbl = {0706.46003} +} + @Book{ conway2001, author = {Conway, J. H.}, title = {On numbers and games}, @@ -1412,6 +1429,13 @@ @InProceedings{ fuerer-lochbihler-schneider-traytel2020 bibsource = {dblp computer science bibliography, https://dblp.org} } +@Book{ fulton2004, + title = {Representation theory: a first course}, + author = {Fulton, William and Harris, Joe}, + year = {2004}, + publisher = {Springer} +} + @Article{ furedi-loeb1994, author = {Zolt\'an {F\"uredi} and Peter A. {Loeb}}, journal = {{Proc. Am. Math. Soc.}}, diff --git a/lake-manifest.json b/lake-manifest.json index 717ed46f42568..e28dfa0386364 100644 --- a/lake-manifest.json +++ b/lake-manifest.json @@ -5,7 +5,7 @@ "type": "git", "subDir": null, "scope": "leanprover-community", - "rev": "a975dea2c4d8258a55b4f9861c537e2bb0f9ef63", + "rev": "8feac540abb781cb1349688c816dc02fae66b49c", "name": "batteries", "manifestFile": "lake-manifest.json", "inputRev": "main", @@ -15,7 +15,7 @@ "type": "git", "subDir": null, "scope": "leanprover-community", - "rev": "71f54425e6fe0fa75f3aef33a2813a7898392222", + "rev": "2c8ae451ce9ffc83554322b14437159c1a9703f9", "name": "Qq", "manifestFile": "lake-manifest.json", "inputRev": "master", @@ -25,7 +25,7 @@ "type": "git", "subDir": null, "scope": "leanprover-community", - "rev": "776a5a8f9c789395796e442d78a9d4cb9c4c9d03", + "rev": "e291aa4de57079b3d2199b9eb7b4b00922b85a7c", "name": "aesop", "manifestFile": "lake-manifest.json", "inputRev": "master", @@ -35,10 +35,10 @@ "type": "git", "subDir": null, "scope": "leanprover-community", - "rev": "a96aee5245720f588876021b6a0aa73efee49c76", + "rev": "eb08eee94098fe530ccd6d8751a86fe405473d4c", "name": "proofwidgets", "manifestFile": "lake-manifest.json", - "inputRev": "v0.0.41", + "inputRev": "v0.0.42", "inherited": false, "configFile": "lakefile.lean"}, {"url": "https://github.com/leanprover/lean4-cli", @@ -55,7 +55,7 @@ "type": "git", "subDir": null, "scope": "leanprover-community", - "rev": "57bd2065f1dbea5e9235646fb836c7cea9ab03b6", + "rev": "8ab24d4bb8b4c4a52af3f39027f255b1901669c9", "name": "importGraph", "manifestFile": "lake-manifest.json", "inputRev": "main", diff --git a/lakefile.lean b/lakefile.lean index 2d1665c48244d..0b406c4741783 100644 --- a/lakefile.lean +++ b/lakefile.lean @@ -2,27 +2,56 @@ import Lake open Lake DSL -package mathlib where - leanOptions := #[ - ⟨`pp.unicode.fun, true⟩, -- pretty-prints `fun a ↦ b` - ⟨`autoImplicit, false⟩ - ] - -- These are additional settings which do not affect the lake hash, - -- so they can be enabled in CI and disabled locally or vice versa. - -- Warning: Do not put any options here that actually change the olean files, - -- or inconsistent behavior may result - -- weakLeanArgs := #[] /-! -## Mathlib dependencies on upstream projects. +## Mathlib dependencies on upstream projects -/ require "leanprover-community" / "batteries" @ git "main" require "leanprover-community" / "Qq" @ git "master" require "leanprover-community" / "aesop" @ git "master" -require "leanprover-community" / "proofwidgets" @ git "v0.0.41" +require "leanprover-community" / "proofwidgets" @ git "v0.0.42" require "leanprover-community" / "importGraph" @ git "main" +/-! +## Options for building mathlib +-/ + +/-- These options are used +* as `leanOptions`, prefixed by `` `weak``, so that `lake build` uses them; +* as `moreServerArgs`, to set their default value in mathlib + (as well as `Archive`, `Counterexamples` and `test`). +-/ +abbrev mathlibOnlyLinters : Array LeanOption := #[ + ⟨`linter.hashCommand, true⟩, + ⟨`linter.oldObtain, true,⟩, + ⟨`linter.refine, true⟩, + ⟨`linter.style.cdot, true⟩, + ⟨`linter.style.dollarSyntax, true⟩, + ⟨`linter.style.lambdaSyntax, true⟩, + ⟨`linter.style.longLine, true⟩, + ⟨`linter.style.missingEnd, true⟩, + ⟨`linter.style.setOption, true⟩ +] + +/-- These options are passed as `leanOptions` to building mathlib, as well as the +`Archive` and `Counterexamples`. (`tests` omits the first two options.) -/ +abbrev mathlibLeanOptions := #[ + ⟨`pp.unicode.fun, true⟩, -- pretty-prints `fun a ↦ b` + ⟨`autoImplicit, false⟩ + ] ++ -- options that are used in `lake build` + mathlibOnlyLinters.map fun s ↦ { s with name := `weak ++ s.name } + +package mathlib where + leanOptions := mathlibLeanOptions + -- Mathlib also enforces these linter options, which are not active by default. + moreServerOptions := mathlibOnlyLinters + -- These are additional settings which do not affect the lake hash, + -- so they can be enabled in CI and disabled locally or vice versa. + -- Warning: Do not put any options here that actually change the olean files, + -- or inconsistent behavior may result + -- weakLeanArgs := #[] + /-! ## Mathlib libraries -/ @@ -34,8 +63,15 @@ lean_lib Mathlib -- `scripts/mk_all.lean`. lean_lib Cache lean_lib LongestPole -lean_lib Archive -lean_lib Counterexamples + +lean_lib Archive where + leanOptions := mathlibLeanOptions + moreServerOptions := mathlibOnlyLinters + +lean_lib Counterexamples where + leanOptions := mathlibLeanOptions + moreServerOptions := mathlibOnlyLinters + /-- Additional documentation in the form of modules that only contain module docstrings. -/ lean_lib docs where roots := #[`docs] @@ -88,6 +124,8 @@ You can also use it as e.g. `lake exe test conv eval_elab` to only run the named -/ @[test_driver] lean_exe test where + -- We could add the above `leanOptions` and `moreServerOptions`: currently, these do not take + -- effect as `test` is a `lean_exe`. With a `lean_lib`, it would work... srcDir := "scripts" /-! diff --git a/lean-toolchain b/lean-toolchain index e7a4f40b892b4..98556ba065e2a 100644 --- a/lean-toolchain +++ b/lean-toolchain @@ -1 +1 @@ -leanprover/lean4:v4.11.0-rc2 +leanprover/lean4:v4.12.0-rc1 diff --git a/scripts/create-adaptation-pr.sh b/scripts/create-adaptation-pr.sh index 416fbdd944766..08db7705144c9 100755 --- a/scripts/create-adaptation-pr.sh +++ b/scripts/create-adaptation-pr.sh @@ -16,7 +16,7 @@ set -e # abort whenever a command in the script fails if [ $# -ne 2 ]; then echo "Usage: $0 " - echo "BUMPVERSION: The upcoming release that we are targetting, e.g., 'v4.10.0'" + 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'" exit 1 fi @@ -70,20 +70,29 @@ if git diff --name-only --diff-filter=U | grep -q .; then echo "### Automatically choosing 'lean-toolchain' and 'lake-manifest.json' from the newer branch" echo "### In this case, the newer branch is 'bump/$BUMPVERSION'" git checkout bump/$BUMPVERSION -- lean-toolchain lake-manifest.json + git add lean-toolchain lake-manifest.json + + # Check if there are more merge conflicts after auto-resolution + if ! git diff --name-only --diff-filter=U | grep -q .; then + # Auto-commit the resolved conflicts if no other conflicts remain + git commit -m "Auto-resolved conflicts in lean-toolchain and lake-manifest.json" + fi fi -# Check if there are more merge conflicts -if git diff --name-only --diff-filter=U | grep -q .; then +# Loop until all conflicts are resolved and committed +while git diff --name-only --diff-filter=U | grep -q . || ! git diff-index --quiet HEAD --; do echo echo "### [user] Conflict resolution" echo "We are merging the latest changes from 'origin/master' into 'bump/$BUMPVERSION'" - echo "There seem to be conflicts: please resolve them" + echo "There seem to be conflicts or uncommitted files" echo "" echo " 1) Open `pwd` in a new terminal and run 'git status'" echo " 2) Make sure to commit the resolved conflicts, but do not push them" read -p " 3) Press enter to continue, when you are done" -fi +done +echo "All conflicts resolved and committed." +echo "Proceeding with git push..." git push echo @@ -99,6 +108,7 @@ if git diff --name-only --diff-filter=U | grep -q .; then 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 + git add lean-toolchain lake-manifest.json fi # Check if there are more merge conflicts @@ -117,7 +127,11 @@ echo echo "### [auto] commit the changes and push the branch" pr_title="chore: adaptations for nightly-$NIGHTLYDATE" -git commit -m "$pr_title" +# Create a commit with the PR title +# We allow an empty commit, +# as the user might have inadvertently already committed changes +# In general, we do not want this command to fail. +git commit --allow-empty -m "$pr_title" git push --set-upstream origin "bump/nightly-$NIGHTLYDATE" # Check if there is a diff between bump/nightly-$NIGHTLYDATE and bump/$BUMPVERSION @@ -172,20 +186,29 @@ if git diff --name-only --diff-filter=U | grep -q .; then echo "### Automatically choosing lean-toolchain and lake-manifest.json from the newer branch" echo "### In this case, the newer branch is 'bump/nightly-$NIGHTLYDATE'" git checkout bump/nightly-$NIGHTLYDATE -- lean-toolchain lake-manifest.json + git add lean-toolchain lake-manifest.json + + # Check if there are more merge conflicts after auto-resolution + if ! git diff --name-only --diff-filter=U | grep -q .; then + # Auto-commit the resolved conflicts if no other conflicts remain + git commit -m "Auto-resolved conflicts in lean-toolchain and lake-manifest.json" + fi fi -# Check if there are more merge conflicts -if git diff --name-only --diff-filter=U | grep -q .; then +# Loop until all conflicts are resolved and committed +while git diff --name-only --diff-filter=U | grep -q . || ! git diff-index --quiet HEAD --; do echo echo "### [user] Conflict resolution" echo "We are merging the new PR "bump/nightly-$NIGHTLYDATE" into 'nightly-testing'" - echo "There seem to be conflicts: please resolve them" + echo "There seem to be conflicts or uncommitted files" echo "" echo " 1) Open `pwd` in a new terminal and run 'git status'" echo " 2) Make sure to commit the resolved conflicts, but do not push them" read -p " 3) Press enter to continue, when you are done" -fi +done +echo "All conflicts resolved and committed." +echo "Proceeding with git push..." git push echo diff --git a/scripts/declarations_diff.sh b/scripts/declarations_diff.sh index d12f8de3182fa..d7a9d1c5ac2ec 100755 --- a/scripts/declarations_diff.sh +++ b/scripts/declarations_diff.sh @@ -42,7 +42,7 @@ The script uses some heuristics to guide this process. BASH_DOC_MODULE ## we narrow the diff to lines beginning with `theorem`, `lemma` and a few other commands -begs="(theorem|lemma|inductive|structure|def|class|instance|alias)" +begs="(theorem|lemma|inductive|structure|def|class|instance|alias|abbrev)" if [ "${1}" == "long" ] then @@ -181,4 +181,5 @@ def testingLongDiff2 im a def def testingLongDiff3 im a def @[trying to fool you] instance. the messing dot alias ⟨d1, d2⟩ := d check the "split an iff alias" +abbrev a_new_one := I was not here before ReferenceTest diff --git a/scripts/get_tlabel.sh b/scripts/get_tlabel.sh new file mode 100755 index 0000000000000..7672fcf5ca80e --- /dev/null +++ b/scripts/get_tlabel.sh @@ -0,0 +1,32 @@ +#!/usr/bin/env bash + + : <<'BASH_MODULE_DOCS' + +This script is used by the maintainer merge actions to extract +* either `t-xxx` if `t-xxx` is the unique `t-`label of the PR; +* or `generic` otherwise +and stores it in `tlabels`. + +In turn, the string `tlabels` extracted above is converted into the +topic name `maintainer merge: tlabels` for the post to the +`maintainer merge` stream. + +BASH_MODULE_DOCS + +PR="${1}" + +>&2 printf $'Using PR: \'%s\'\n' "${PR}" + +tlabels="$(gh api --jq '.labels.[].name' "${PR}" | grep -- '^t-' || printf 'generic\nlabel')" +# print to error, since the stdout is captured into `GITHUB_OUTPUT +>&2 printf 't-labels:\n---\n%s\n---\n' "${tlabels}" +# if there is exactly 1 `t-xxx` label, use `maintainer merge: t-xxx` +# if there isn't exactly 1 `t-xxx` label, use `maintainer merge` +if [[ "$(wc -l <<<"${tlabels}")" -ne 1 ]]; then + topicName="maintainer merge" +else + topicName="maintainer merge: ${tlabels}" +fi + +>&2 printf $'Post to topic: \'%s\'"\n' "${topicName}" +echo "topic=${topicName}" diff --git a/scripts/lint-style.lean b/scripts/lint-style.lean index 5c7ab0d34064f..36c079e643545 100644 --- a/scripts/lint-style.lean +++ b/scripts/lint-style.lean @@ -14,24 +14,26 @@ This files defines the `lint-style` executable which runs all text-based style l The linters themselves are defined in `Mathlib.Tactic.Linter.TextBased`. -/ -open Cli +open Cli Mathlib.Linter.TextBased /-- Implementation of the `lint-style` command line program. -/ def lintStyleCli (args : Cli.Parsed) : IO UInt32 := do - let mode : OutputSetting := match (args.hasFlag "update", args.hasFlag "github") with - | (true, _) => OutputSetting.update - | (false, true) => OutputSetting.print ErrorFormat.github - | (false, false) => OutputSetting.print ErrorFormat.humanReadable + let style : ErrorFormat := match args.hasFlag "github" with + | true => ErrorFormat.github + | false => ErrorFormat.humanReadable -- Read all module names to lint. let mut allModules := #[] for s in ["Archive.lean", "Counterexamples.lean", "Mathlib.lean"] do allModules := allModules.append ((← IO.FS.lines s).map (·.stripPrefix "import ")) -- note: since we manually add "Batteries" to "Mathlib.lean", we remove it here manually allModules := allModules.erase "Batteries" - let numberErrorFiles ← lintModules allModules mode (args.hasFlag "fix") - -- Make sure to return an exit code of at most 125, so this return value can be used further - -- in shell scripts. - return min numberErrorFiles 125 + let numberErrorFiles ← lintModules allModules style (args.hasFlag "fix") + -- If run with the `--fix` argument, return a zero exit code. + -- Otherwise, make sure to return an exit code of at most 125, + -- so this return value can be used further in shell scripts. + if args.hasFlag "fix" then + return 0 + else return min numberErrorFiles 125 /-- Setting up command line options and help text for `lake exe lint-style`. -/ -- so far, no help options or so: perhaps that is fine? @@ -43,11 +45,6 @@ def lintStyle : Cmd := `[Cli| FLAGS: github; "Print errors in a format suitable for github problem matchers\n\ otherwise, produce human-readable output" - update; "Also update the style exceptions file.\ - This adds entries for any new exceptions, removes any entries which are no longer necessary,\ - and tries to not modify exception entries unless necessary. - To fully regenerate the list of style exceptions, delete `style-exceptions.txt` - and run this script again with this flag." fix; "Automatically fix the style error, if possible" ] diff --git a/scripts/lint-style.py b/scripts/lint-style.py index b8b0ed4779a5b..285728fa4bcae 100755 --- a/scripts/lint-style.py +++ b/scripts/lint-style.py @@ -26,8 +26,6 @@ Do not add new linters here; please write them in Lean instead. To run all style linters, run `lake exe lint-style`. -To update the list of allowed/ignored style exceptions, use - $ lake exe lint-style --update """ # TODO: This is adapted from the linter for mathlib3. It should be rewritten in Lean. @@ -40,7 +38,6 @@ ERR_MOD = 2 # module docstring ERR_IBY = 11 # isolated by ERR_IWH = 22 # isolated where -ERR_DOT = 12 # isolated or low focusing dot ERR_SEM = 13 # the substring " ;" ERR_WIN = 14 # Windows line endings "\r\n" ERR_TWS = 15 # trailing whitespace @@ -50,25 +47,9 @@ ERR_NSP = 20 # non-terminal simp exceptions = [] - -SCRIPTS_DIR = Path(__file__).parent.resolve() -ROOT_DIR = SCRIPTS_DIR.parent - - -with SCRIPTS_DIR.joinpath("style-exceptions.txt").open(encoding="utf-8") as f: - for exline in f: - filename, _, _, _, _, errno, *extra = exline.split() - path = ROOT_DIR / filename - if errno == "ERR_MOD": - exceptions += [(ERR_MOD, path, None)] - elif errno in ["ERR_COP", "ERR_LIN", "ERR_ADN", "ERR_NUM_LIN"]: - pass # maintained by the Lean style linter now - else: - print(f"Error: unexpected errno in style-exceptions.txt: {errno}") - sys.exit(1) - new_exceptions = False + def annotate_comments(enumerate_lines): """ Take a list of tuples of enumerated lines of the form @@ -264,11 +245,6 @@ def isolated_by_dot_semicolon_check(lines, path): line = f"{indent}{line.lstrip()[3:]}" elif line.lstrip() == "where": errors += [(ERR_IWH, line_nr, path)] - if line.lstrip().startswith(". "): - errors += [(ERR_DOT, line_nr, path)] - line = line.replace(". ", "· ", 1) - if line.strip() in (".", "·"): - errors += [(ERR_DOT, line_nr, path)] if " ;" in line: errors += [(ERR_SEM, line_nr, path)] line = line.replace(" ;", ";") @@ -293,18 +269,10 @@ def left_arrow_check(lines, path): return errors, newlines def output_message(path, line_nr, code, msg): - if len(exceptions) == 0: - # we are generating a new exceptions file - # filename first, then line so that we can call "sort" on the output - print(f"{path} : line {line_nr} : {code} : {msg}") - else: - if code.startswith("ERR"): - msg_type = "error" - if code.startswith("WRN"): - msg_type = "warning" - # We are outputting for github. We duplicate path, line_nr and code, - # so that they are also visible in the plaintext output. - print(f"::{msg_type} file={path},line={line_nr},code={code}::{path}:{line_nr} {code}: {msg}") + # We are outputting for github. We duplicate path, line_nr and code, + # so that they are also visible in the plaintext output. + print(f"::error file={path},line={line_nr},code={code}::{path}:{line_nr} {code}: {msg}") + def format_errors(errors): global new_exceptions @@ -318,8 +286,6 @@ def format_errors(errors): output_message(path, line_nr, "ERR_IBY", "Line is an isolated 'by'") if errno == ERR_IWH: output_message(path, line_nr, "ERR_IWH", "Line is an isolated where") - if errno == ERR_DOT: - output_message(path, line_nr, "ERR_DOT", "Line is an isolated focusing dot or uses . instead of ·") if errno == ERR_SEM: output_message(path, line_nr, "ERR_SEM", "Line contains a space before a semicolon") if errno == ERR_WIN: diff --git a/scripts/mk_all.lean b/scripts/mk_all.lean index c33a957e6149d..309a4bf49d2c4 100644 --- a/scripts/mk_all.lean +++ b/scripts/mk_all.lean @@ -64,7 +64,8 @@ def mkAllCLI (args : Parsed) : IO UInt32 := do updates := updates + 1 else if (← IO.FS.readFile fileName) != fileContent then if check then - IO.println s!"The file '{fileName}' is out of date: run `lake exe mk_all{if git then " --git" else ""}` to update it" + IO.println s!"The file '{fileName}' is out of date: \ + run `lake exe mk_all{if git then " --git" else ""}` to update it" else IO.println s!"Updating '{fileName}'" IO.FS.writeFile fileName fileContent diff --git a/scripts/nolints-style.txt b/scripts/nolints-style.txt index 2b0bbbe992a8d..9467ae24e5650 100644 --- a/scripts/nolints-style.txt +++ b/scripts/nolints-style.txt @@ -1,9 +1,6 @@ -- Manual exceptions for the text-based linters. --- This file is to `style-exceptions.txt` what `nolints.json` is to `@nolint` attributes: --- The latter is supposed to become and stay mostly empty over time (though files longer than --- 1500 lines can be transient exceptions for some longer time period), --- the former could be necessary in the long term. --- In this case, it's a side-effect of making the linter stricter than its Python ancestor. +-- The entries in this file could be necessary in the long term. +-- In some cases, entries are a side effect of making the linter stricter than its Python ancestor. -- The `Mathlib/Init.lean` files does not have a copyright header Mathlib/Init.lean : line 2 : ERR_COP : Malformed or missing copyright header: Copyright line is malformed @@ -29,8 +26,9 @@ Mathlib/Tactic/AdaptationNote.lean : line 21 : ERR_ADN : Found the string "Adapt Mathlib/Tactic/AdaptationNote.lean : line 27 : ERR_ADN : Found the string "Adaptation note:", please use the #adaptation_note command instead Mathlib/Tactic/AdaptationNote.lean : line 39 : ERR_ADN : Found the string "Adaptation note:", please use the #adaptation_note command instead Mathlib/Tactic/AdaptationNote.lean : line 52 : ERR_ADN : Found the string "Adaptation note:", please use the #adaptation_note command instead -Mathlib/Tactic/Linter/TextBased.lean : line 33 : ERR_ADN : Found the string "Adaptation note:", please use the #adaptation_note command instead -Mathlib/Tactic/Linter/TextBased.lean : line 60 : ERR_ADN : Found the string "Adaptation note:", please use the #adaptation_note command instead -Mathlib/Tactic/Linter/TextBased.lean : line 222 : ERR_ADN : Found the string "Adaptation note:", please use the #adaptation_note command instead -Mathlib/Tactic/Linter/TextBased.lean : line 227 : ERR_ADN : Found the string "Adaptation note:", please use the #adaptation_note command instead -Mathlib/Tactic/Linter/TextBased.lean : line 228 : ERR_ADN : Found the string "Adaptation note:", please use the #adaptation_note command instead +Mathlib/Tactic/Linter/TextBased.lean : line 20 : ERR_ADN : Found the string "Adaptation note:", please use the #adaptation_note command instead +Mathlib/Tactic/Linter/TextBased.lean : line 49 : ERR_ADN : Found the string "Adaptation note:", please use the #adaptation_note command instead +Mathlib/Tactic/Linter/TextBased.lean : line 84 : ERR_ADN : Found the string "Adaptation note:", please use the #adaptation_note command instead +Mathlib/Tactic/Linter/TextBased.lean : line 274 : ERR_ADN : Found the string "Adaptation note:", please use the #adaptation_note command instead +Mathlib/Tactic/Linter/TextBased.lean : line 279 : ERR_ADN : Found the string "Adaptation note:", please use the #adaptation_note command instead +Mathlib/Tactic/Linter/TextBased.lean : line 280 : ERR_ADN : Found the string "Adaptation note:", please use the #adaptation_note command instead diff --git a/scripts/nolints.json b/scripts/nolints.json index b2ed89639f44c..cd10aac529d97 100644 --- a/scripts/nolints.json +++ b/scripts/nolints.json @@ -30,8 +30,6 @@ ["docBlame", "WriterT"], ["docBlame", "Xor'"], ["docBlame", "Zero"], - ["docBlame", "bit0"], - ["docBlame", "bit1"], ["docBlame", "cancelDenominators"], ["docBlame", "cancelDenominatorsAt"], ["docBlame", "cancelDenominatorsTarget"], @@ -51,7 +49,6 @@ ["docBlame", "«term_≃ᵃⁱ[_]_»"], ["docBlame", "«term_≃ᵈ_»"], ["docBlame", "«term_≡_[SMOD_]»"], - ["docBlame", "termℤ"], ["docBlame", "«termℤ√_»"], ["docBlame", "«term∫_In_.._,_»"], ["docBlame", "«term∫_In_.._,_∂_»"], @@ -80,7 +77,6 @@ ["docBlame", "Bitraversable.bitraverse"], ["docBlame", "BoundedContinuousFunction.«term_→ᵇ_»"], ["docBlame", "BoundedRandom.randomR"], - ["docBlame", "BumpCovering.toFun"], ["docBlame", "ByteSlice.arr"], ["docBlame", "ByteSlice.len"], ["docBlame", "ByteSlice.off"], @@ -283,7 +279,6 @@ ["docBlame", "One.one"], ["docBlame", "OptionT.callCC"], ["docBlame", "OptionT.mkLabel"], - ["docBlame", "PartitionOfUnity.toFun"], ["docBlame", "PicardLindelof.C"], ["docBlame", "PicardLindelof.L"], ["docBlame", "PicardLindelof.R"], @@ -337,7 +332,6 @@ ["docBlame", "SchwartzMap.toFun"], ["docBlame", "SemiRingCat.forget_obj_eq_coe"], ["docBlame", "Semigrp.forget_obj_eq_coe"], - ["docBlame", "Set.«term{_|_}»"], ["docBlame", "Shrink.rec"], ["docBlame", "SlashAction.map"], ["docBlame", "SlashInvariantForm.toFun"], @@ -427,8 +421,6 @@ ["docBlame", "CategoryTheory.Comma.right"], ["docBlame", "CategoryTheory.CommaMorphism.left"], ["docBlame", "CategoryTheory.CommaMorphism.right"], - ["docBlame", "CategoryTheory.Comonad.δ'"], - ["docBlame", "CategoryTheory.Comonad.ε'"], ["docBlame", "CategoryTheory.EnrichedCategory.Hom"], ["docBlame", "CategoryTheory.EnrichedCategory.comp"], ["docBlame", "CategoryTheory.EnrichedCategory.id"], @@ -441,8 +433,6 @@ ["docBlame", "CategoryTheory.GlueData.t"], ["docBlame", "CategoryTheory.GlueData.t'"], ["docBlame", "CategoryTheory.GradedNatTrans.app"], - ["docBlame", - "CategoryTheory.GrothendieckTopology.sheafificationIsoPresheafToSheafCompSheafToPreasheaf"], ["docBlame", "CategoryTheory.HalfBraiding.β"], ["docBlame", "CategoryTheory.Mat_.X"], ["docBlame", "CategoryTheory.Mat_.ι"], @@ -451,8 +441,6 @@ ["docBlame", "CategoryTheory.Monad.PreservesColimitOfIsReflexivePair"], ["docBlame", "CategoryTheory.Monad.PreservesColimitOfIsSplitPair"], ["docBlame", "CategoryTheory.Monad.ReflectsColimitOfIsSplitPair"], - ["docBlame", "CategoryTheory.Monad.η'"], - ["docBlame", "CategoryTheory.Monad.μ'"], ["docBlame", "CategoryTheory.Presieve.yonedaFamilyOfElements_fromCocone"], ["docBlame", "CategoryTheory.Pretopology.coverings"], ["docBlame", "CategoryTheory.ProjectivePresentation.f"], @@ -489,7 +477,6 @@ ["docBlame", "GromovHausdorff.AuxGluingStruct.Space"], ["docBlame", "GromovHausdorff.AuxGluingStruct.embed"], ["docBlame", "GromovHausdorff.AuxGluingStruct.metric"], - ["docBlame", "HahnSeries.SummableFamily.toFun"], ["docBlame", "HomogeneousLocalization.NumDenSameDeg.deg"], ["docBlame", "HomogeneousLocalization.NumDenSameDeg.den"], ["docBlame", "HomogeneousLocalization.NumDenSameDeg.num"], @@ -497,7 +484,6 @@ ["docBlame", "Ideal.Filtration.N"], ["docBlame", "IntermediateField.delabAdjoinNotation.delabInsertArray"], ["docBlame", "IsDedekindDomain.HeightOneSpectrum.asIdeal"], - ["docBlame", "Lean.Attr.substAttr"], ["docBlame", "Lean.Export.Alloc"], ["docBlame", "Lean.Export.Entry"], ["docBlame", "Lean.Export.OfState"], @@ -515,10 +501,6 @@ ["docBlame", "Lean.Expr.modifyRevArg"], ["docBlame", "Lean.MVarId.casesType"], ["docBlame", "Lean.MVarId.congrCore!"], - ["docBlame", "Lean.Meta.checkTypeIsProp"], - ["docBlame", "Lean.Meta.mkSimpTheoremCore"], - ["docBlame", "Lean.Meta.preprocess"], - ["docBlame", "Lean.Meta.shouldPreprocess"], ["docBlame", "Lean.Name.isBlackListed"], ["docBlame", "Lean.PHashSet.toList"], ["docBlame", "LocallyFinite.Realizer.bas"], @@ -785,4 +767,4 @@ ["docBlame", "Mathlib.Meta.NormNum.evalAdd.core.ratArm"], ["docBlame", "Mathlib.Meta.NormNum.evalMul.core.intArm"], ["docBlame", "Mathlib.Meta.NormNum.evalMul.core.ratArm"], - ["unusedArguments", "Combinator.K"]] + ["unusedArguments", "Combinator.K"]] \ No newline at end of file diff --git a/scripts/noshake.json b/scripts/noshake.json index 61f866068e7e1..d863e189c32b4 100644 --- a/scripts/noshake.json +++ b/scripts/noshake.json @@ -194,7 +194,7 @@ ["Batteries.Tactic.Basic", "Mathlib.Mathport.Syntax", "Mathlib.Tactic.Linter"], "ignore": {"Mathlib.Topology.Sheaves.Forget": ["Mathlib.Algebra.Category.Ring.Limits"], - "Mathlib.Topology.Order.LeftRightNhds": ["Mathlib.Data.Set.Pointwise.Basic"], + "Mathlib.Topology.Order.LeftRightNhds": ["Mathlib.Algebra.Ring.Pointwise.Set"], "Mathlib.Topology.Germ": ["Mathlib.Analysis.Normed.Module.Basic"], "Mathlib.Topology.Defs.Basic": ["Mathlib.Tactic.FunProp"], "Mathlib.Topology.Category.UniformSpace": @@ -300,6 +300,10 @@ "Mathlib.RingTheory.MvPolynomial.Homogeneous": ["Mathlib.Algebra.DirectSum.Internal"], "Mathlib.RingTheory.Binomial": ["Mathlib.Algebra.Order.Floor"], + "Mathlib.RepresentationTheory.FdRep": + ["Mathlib.CategoryTheory.Monoidal.Rigid.Braided"], + "Mathlib.RepresentationTheory.FDRep": + ["Mathlib.CategoryTheory.Monoidal.Rigid.Braided"], "Mathlib.Probability.Notation": ["Mathlib.MeasureTheory.Decomposition.Lebesgue", "Mathlib.MeasureTheory.Function.ConditionalExpectation.Basic"], @@ -323,14 +327,9 @@ "Mathlib.LinearAlgebra.AffineSpace.FiniteDimensional": ["Mathlib.Init.Core"], "Mathlib.LinearAlgebra.AffineSpace.Basic": ["Mathlib.Algebra.AddTorsor"], "Mathlib.Lean.Meta": ["Batteries.Logic"], - "Mathlib.Lean.Expr.ExtraRecognizers": ["Mathlib.Data.Set.Defs"], + "Mathlib.Lean.Expr.ExtraRecognizers": ["Mathlib.Data.Set.Operations"], "Mathlib.Lean.Expr.Basic": ["Batteries.Logic"], "Mathlib.Init.Data.Nat.Lemmas": ["Batteries.Data.Nat.Lemmas", "Batteries.WF"], - "Mathlib.Init.Data.List.Lemmas": ["Batteries.Data.List.Lemmas"], - "Mathlib.Init.Data.List.Basic": ["Batteries.Data.List.Basic"], - "Mathlib.Init.Data.Int.Order": ["Mathlib.Data.Int.Notation"], - "Mathlib.Init.Data.Int.Basic": ["Batteries.Data.Int.Order"], - "Mathlib.Init.Data.Bool.Lemmas": ["Mathlib.Tactic.AdaptationNote"], "Mathlib.GroupTheory.MonoidLocalization.Basic": ["Mathlib.Init.Data.Prod"], "Mathlib.Geometry.Manifold.Sheaf.Smooth": ["Mathlib.CategoryTheory.Sites.Whiskering"], @@ -353,10 +352,12 @@ "Mathlib.Data.List.Defs": ["Batteries.Data.RBMap.Basic"], "Mathlib.Data.List.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"], "Mathlib.Control.Monad.Cont": ["Batteries.Tactic.Congr"], @@ -374,6 +375,7 @@ "Mathlib.Analysis.InnerProductSpace.Basic": ["Mathlib.Algebra.Module.LinearMap.Basic"], "Mathlib.Analysis.Distribution.SchwartzSpace": ["Mathlib.Tactic.MoveAdd"], + "Mathlib.Analysis.Convex.Star": ["Mathlib.Algebra.Order.Module.Synonym"], "Mathlib.Analysis.Convex.Basic": ["Mathlib.Algebra.Order.BigOperators.Ring.Finset"], "Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.NonUnital": diff --git a/scripts/print-style-errors.sh b/scripts/print-style-errors.sh index f9a9e1c1b42c8..f9aad79d7e63d 100755 --- a/scripts/print-style-errors.sh +++ b/scripts/print-style-errors.sh @@ -2,10 +2,10 @@ # Print all errors of the python style linter. This script is temporary and should be removed # once the Python style linters have been rewritten in Lean. -# Humans should never run this directly, but at most through `lean exe lint-style --update` +# Humans should never run this directly, but at most through `lean exe lint-style --fix` # use C locale so that sorting is the same on macOS and Linux # see https://unix.stackexchange.com/questions/362728/why-does-gnu-sort-sort-differently-on-my-osx-machine-and-linux-machine -find Mathlib -name '*.lean' | xargs ./scripts/lint-style.py | LC_ALL=C sort -find Archive -name '*.lean' | xargs ./scripts/lint-style.py | LC_ALL=C sort -find Counterexamples -name '*.lean' | xargs ./scripts/lint-style.py | LC_ALL=C sort +find Mathlib -name '*.lean' | xargs ./scripts/lint-style.py "$@" | LC_ALL=C sort +find Archive -name '*.lean' | xargs ./scripts/lint-style.py "$@" | LC_ALL=C sort +find Counterexamples -name '*.lean' | xargs ./scripts/lint-style.py "$@" | LC_ALL=C sort diff --git a/scripts/style-exceptions.txt b/scripts/style-exceptions.txt deleted file mode 100644 index 1510a1e80cc85..0000000000000 --- a/scripts/style-exceptions.txt +++ /dev/null @@ -1,67 +0,0 @@ -Mathlib/Algebra/BigOperators/Group/Finset.lean : line 1 : ERR_NUM_LIN : 2400 file contains 2245 lines, try to split it up -Mathlib/Algebra/Group/Subgroup/Basic.lean : line 1 : ERR_NUM_LIN : 3000 file contains 2893 lines, try to split it up -Mathlib/Algebra/MonoidAlgebra/Basic.lean : line 1 : ERR_NUM_LIN : 2100 file contains 1965 lines, try to split it up -Mathlib/Algebra/MvPolynomial/Basic.lean : line 1 : ERR_NUM_LIN : 1700 file contains 1544 lines, try to split it up -Mathlib/Algebra/Order/Floor.lean : line 1 : ERR_NUM_LIN : 1700 file contains 1593 lines, try to split it up -Mathlib/AlgebraicGeometry/EllipticCurve/Jacobian.lean : line 1 : ERR_NUM_LIN : 1700 file contains 1511 lines, try to split it up -Mathlib/Analysis/Asymptotics/Asymptotics.lean : line 1 : ERR_NUM_LIN : 2100 file contains 1955 lines, try to split it up -Mathlib/Analysis/Calculus/ContDiff/Basic.lean : line 1 : ERR_NUM_LIN : 2100 file contains 1952 lines, try to split it up -Mathlib/Analysis/Calculus/ContDiff/Defs.lean : line 1 : ERR_NUM_LIN : 1700 file contains 1595 lines, try to split it up -Mathlib/Analysis/InnerProductSpace/Basic.lean : line 1 : ERR_NUM_LIN : 2500 file contains 2433 lines, try to split it up -Mathlib/CategoryTheory/Limits/Shapes/Biproducts.lean : line 1 : ERR_NUM_LIN : 2100 file contains 1998 lines, try to split it up -Mathlib/Computability/TMToPartrec.lean : line 1 : ERR_NUM_LIN : 2200 file contains 2071 lines, try to split it up -Mathlib/Computability/TuringMachine.lean : line 1 : ERR_NUM_LIN : 2700 file contains 2561 lines, try to split it up -Mathlib/Data/DFinsupp/Basic.lean : line 1 : ERR_NUM_LIN : 2200 file contains 2078 lines, try to split it up -Mathlib/Data/Fin/Basic.lean : line 1 : ERR_NUM_LIN : 1700 file contains 1524 lines, try to split it up -Mathlib/Data/Finset/Basic.lean : line 1 : ERR_NUM_LIN : 3200 file contains 3057 lines, try to split it up -Mathlib/Data/Finset/Lattice.lean : line 1 : ERR_NUM_LIN : 2100 file contains 1968 lines, try to split it up -Mathlib/Data/Finset/Pointwise/Basic.lean : line 1 : ERR_NUM_LIN : 2100 file contains 1997 lines, try to split it up -Mathlib/Data/Finsupp/Basic.lean : line 1 : ERR_NUM_LIN : 1900 file contains 1703 lines, try to split it up -Mathlib/Data/List/Basic.lean : line 1 : ERR_NUM_LIN : 2700 file contains 2598 lines, try to split it up -Mathlib/Data/Matrix/Basic.lean : line 1 : ERR_NUM_LIN : 2700 file contains 2519 lines, try to split it up -Mathlib/Data/Multiset/Basic.lean : line 1 : ERR_NUM_LIN : 2900 file contains 2725 lines, try to split it up -Mathlib/Data/Num/Lemmas.lean : line 1 : ERR_NUM_LIN : 1700 file contains 1576 lines, try to split it up -Mathlib/Data/Ordmap/Ordset.lean : line 1 : ERR_NUM_LIN : 1700 file contains 1580 lines, try to split it up -Mathlib/Data/QPF/Multivariate/Basic.lean : line 76 : ERR_LIN : Line has 127 characters, which is more than 100 -Mathlib/Data/Real/EReal.lean : line 1 : ERR_NUM_LIN : 1900 file contains 1778 lines, try to split it up -Mathlib/Data/Seq/WSeq.lean : line 1 : ERR_NUM_LIN : 1800 file contains 1622 lines, try to split it up -Mathlib/Data/Set/Basic.lean : line 1 : ERR_NUM_LIN : 2300 file contains 2170 lines, try to split it up -Mathlib/Data/Set/Finite.lean : line 1 : ERR_NUM_LIN : 1700 file contains 1535 lines, try to split it up -Mathlib/Data/Set/Function.lean : line 1 : ERR_NUM_LIN : 1900 file contains 1740 lines, try to split it up -Mathlib/Data/Set/Lattice.lean : line 1 : ERR_NUM_LIN : 2100 file contains 1932 lines, try to split it up -Mathlib/LinearAlgebra/AffineSpace/AffineSubspace.lean : line 1 : ERR_NUM_LIN : 1800 file contains 1693 lines, try to split it up -Mathlib/LinearAlgebra/Dual.lean : line 1 : ERR_NUM_LIN : 1900 file contains 1738 lines, try to split it up -Mathlib/LinearAlgebra/Multilinear/Basic.lean : line 1 : ERR_NUM_LIN : 1900 file contains 1775 lines, try to split it up -Mathlib/Logic/Equiv/Basic.lean : line 1 : ERR_NUM_LIN : 2000 file contains 1806 lines, try to split it up -Mathlib/MeasureTheory/Function/LpSpace.lean : line 1 : ERR_NUM_LIN : 2100 file contains 1978 lines, try to split it up -Mathlib/MeasureTheory/Function/StronglyMeasurable/Basic.lean : line 1 : ERR_NUM_LIN : 2000 file contains 1879 lines, try to split it up -Mathlib/MeasureTheory/Integral/Bochner.lean : line 1 : ERR_NUM_LIN : 2100 file contains 1947 lines, try to split it up -Mathlib/MeasureTheory/Integral/FundThmCalculus.lean : line 1 : ERR_NUM_LIN : 1800 file contains 1647 lines, try to split it up -Mathlib/MeasureTheory/Integral/Lebesgue.lean : line 1 : ERR_NUM_LIN : 2200 file contains 2051 lines, try to split it up -Mathlib/MeasureTheory/Integral/SetIntegral.lean : line 1 : ERR_NUM_LIN : 1700 file contains 1579 lines, try to split it up -Mathlib/MeasureTheory/Integral/SetToL1.lean : line 1 : ERR_NUM_LIN : 1800 file contains 1640 lines, try to split it up -Mathlib/MeasureTheory/Measure/MeasureSpace.lean : line 1 : ERR_NUM_LIN : 2200 file contains 2008 lines, try to split it up -Mathlib/Order/CompleteLattice.lean : line 1 : ERR_NUM_LIN : 1900 file contains 1709 lines, try to split it up -Mathlib/Order/ConditionallyCompleteLattice/Basic.lean : line 1 : ERR_NUM_LIN : 1700 file contains 1549 lines, try to split it up -Mathlib/Order/Filter/AtTopBot.lean : line 1 : ERR_NUM_LIN : 2000 file contains 1828 lines, try to split it up -Mathlib/Order/Filter/Basic.lean : line 1 : ERR_NUM_LIN : 3000 file contains 2898 lines, try to split it up -Mathlib/Order/Hom/Lattice.lean : line 1 : ERR_NUM_LIN : 1800 file contains 1661 lines, try to split it up -Mathlib/Order/Interval/Set/Basic.lean : line 1 : ERR_NUM_LIN : 1800 file contains 1652 lines, try to split it up -Mathlib/Order/LiminfLimsup.lean : line 1 : ERR_NUM_LIN : 1900 file contains 1791 lines, try to split it up -Mathlib/Order/UpperLower/Basic.lean : line 1 : ERR_NUM_LIN : 1900 file contains 1795 lines, try to split it up -Mathlib/RingTheory/UniqueFactorizationDomain.lean : line 1 : ERR_NUM_LIN : 2100 file contains 1982 lines, try to split it up -Mathlib/SetTheory/Cardinal/Basic.lean : line 1 : ERR_NUM_LIN : 2200 file contains 2004 lines, try to split it up -Mathlib/SetTheory/Game/PGame.lean : line 1 : ERR_NUM_LIN : 1900 file contains 1753 lines, try to split it up -Mathlib/SetTheory/Ordinal/Arithmetic.lean : line 1 : ERR_NUM_LIN : 2400 file contains 2269 lines, try to split it up -Mathlib/SetTheory/ZFC/Basic.lean : line 1 : ERR_NUM_LIN : 1700 file contains 1549 lines, try to split it up -Mathlib/Tactic/CC/Addition.lean : line 1 : ERR_NUM_LIN : 2300 file contains 2100 lines, try to split it up -Mathlib/Tactic/ToAdditive/Frontend.lean : line 1 : ERR_NUM_LIN : 1700 file contains 1502 lines, try to split it up -Mathlib/Topology/Algebra/Group/Basic.lean : line 1 : ERR_NUM_LIN : 2100 file contains 1932 lines, try to split it up -Mathlib/Topology/Algebra/Module/Basic.lean : line 1 : ERR_NUM_LIN : 2600 file contains 2405 lines, try to split it up -Mathlib/Topology/Basic.lean : line 1 : ERR_NUM_LIN : 1900 file contains 1731 lines, try to split it up -Mathlib/Topology/Category/Profinite/Nobeling.lean : line 1 : ERR_NUM_LIN : 2000 file contains 1806 lines, try to split it up -Mathlib/Topology/Constructions.lean : line 1 : ERR_NUM_LIN : 1700 file contains 1591 lines, try to split it up -Mathlib/Topology/ContinuousFunction/Bounded.lean : line 1 : ERR_NUM_LIN : 1800 file contains 1682 lines, try to split it up -Mathlib/Topology/Instances/ENNReal.lean : line 1 : ERR_NUM_LIN : 1700 file contains 1513 lines, try to split it up -Mathlib/Topology/Separation.lean : line 1 : ERR_NUM_LIN : 2900 file contains 2716 lines, try to split it up -Mathlib/Topology/UniformSpace/Basic.lean : line 1 : ERR_NUM_LIN : 1900 file contains 1768 lines, try to split it up diff --git a/scripts/technical-debt-metrics.sh b/scripts/technical-debt-metrics.sh index cd49fd69bfaa1..0d6a7018286bf 100755 --- a/scripts/technical-debt-metrics.sh +++ b/scripts/technical-debt-metrics.sh @@ -54,7 +54,8 @@ for i in ${!titlesAndRegexes[@]}; do done printf '%s|%s\n' "$(grep -c 'docBlame' scripts/nolints.json)" "documentation nolint entries" -printf '%s|%s\n' "$(grep -c 'ERR_NUM_LIN' scripts/style-exceptions.txt)" "large files" +# 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" diff --git a/scripts/update_nolints_CI.sh b/scripts/update_nolints_CI.sh index 42c50b9c2074e..ee3880c3a4aa2 100755 --- a/scripts/update_nolints_CI.sh +++ b/scripts/update_nolints_CI.sh @@ -1,7 +1,6 @@ #!/usr/bin/env bash -# Check if there are changes to `nolints.json` or `style-exceptions.txt`, -# and file a PR updating these files otherwise. +# Check if there are changes to `nolints.json` and file a PR updating it if necessary. # DO NOT run this as a human; this is meant only for automation usage! set -e @@ -12,17 +11,17 @@ branch_name=nolints owner_name=leanprover-community # Exit if the branch already exists -git fetch "$remote_name" +git fetch --quiet "$remote_name" git rev-parse --verify --quiet "refs/remotes/${remote_name}/${branch_name}" && exit 0 # Exit if there are no changes relative to master -git diff-index --quiet "refs/remotes/${remote_name}/master" -- scripts/nolints.json scripts/style-exceptions.txt && exit 0 +git diff-index --quiet "refs/remotes/${remote_name}/master" -- scripts/nolints.json && exit 0 -pr_title='chore(scripts): update nolints.json and style-exceptions.txt' +pr_title='chore(scripts): update nolints.json pr_body='I am happy to remove some nolints for you!' git checkout -b "$branch_name" -git add scripts/nolints.json scripts/style-exceptions.txt +git add scripts/nolints.json git commit -m "$pr_title" gh_api() { @@ -34,7 +33,7 @@ gh_api() { git push "${remote_name}" "HEAD:$branch_name" -pr_id=$(gh_api "repos/${owner_name}/mathlib/pulls" -X POST -d @- < 0 := by bound example (h : x < y) : Real.exp (y - x) > 1 := by bound example (h : x < y) (y0 : 0 < y) : x / y < 1 := by bound @@ -42,16 +43,17 @@ section guess_tests variable {a b c : ℝ} {n m : ℕ} example (h : a ≤ b) : a ≤ max b c := by bound example (h : a ≤ c) : a ≤ max b c := by bound -example (h : a < b) : a < max b c := by bound -example (h : a < c) : a < max b c := by bound example (h : a ≤ c) : min a b ≤ c := by bound example (h : b ≤ c) : min a b ≤ c := by bound +example (h : a < b) : a < max b c := by bound +example (h : a < c) : a < max b c := by bound example (h : a < c) : min a b < c := by bound example (h : b < c) : min a b < c := by bound example (a1 : 1 ≤ a) (h : m ≤ n) : a^m ≤ a^n := by bound example (a0 : 0 ≤ a) (a1 : a ≤ 1) (h : n ≤ m) : a^m ≤ a^n := by bound example (a1 : 1 ≤ a) (h : b ≤ c) : a^b ≤ a^c := by bound example (a0 : 0 < a) (a1 : a ≤ 1) (h : c ≤ b) : a^b ≤ a^c := by bound + end guess_tests section positive_tests @@ -108,6 +110,7 @@ example (h : x > 0) : x ≥ 0 := by bound example (hc : c ≥ 0) (h : a ≤ b) : a / c ≤ b / c := by bound example (ha : a ≥ 0) (hc : c > 0) (h : b ≥ c) : a / b ≤ a / c := by bound example (x y : ℝ) (x0 : 0 < x) (h : x ≤ y) : x.log ≤ y.log := by bound + end bound_tests /-- This broke without appropriate `g.withContext` use in an older implementation of `bound`. diff --git a/test/CategoryTheory/Elementwise.lean b/test/CategoryTheory/Elementwise.lean index 9117dd1581f56..c28cc0073a784 100644 --- a/test/CategoryTheory/Elementwise.lean +++ b/test/CategoryTheory/Elementwise.lean @@ -1,12 +1,11 @@ import Mathlib.Tactic.CategoryTheory.Elementwise ---import Mathlib.Algebra.Category.Mon.Basic +import Mathlib.Algebra.Category.MonCat.Basic set_option autoImplicit true namespace ElementwiseTest open CategoryTheory -set_option linter.existingAttributeWarning false in attribute [simp] Iso.hom_inv_id Iso.inv_hom_id IsIso.hom_inv_id IsIso.inv_hom_id attribute [local instance] ConcreteCategory.instFunLike ConcreteCategory.hasCoeToSort @@ -82,22 +81,20 @@ example {C : Type u} [Category.{v} C] [ConcreteCategory.{w} C] rw [this] section Mon --- TODO: switch to actual Mon when it is ported -variable (Mon : Type _) [Category Mon] [ConcreteCategory Mon] -lemma bar' {M N K : Mon} {f : M ⟶ N} {g : N ⟶ K} {h : M ⟶ K} (w : f ≫ g = h) (x : M) : +lemma bar' {M N K : MonCat} {f : M ⟶ N} {g : N ⟶ K} {h : M ⟶ K} (w : f ≫ g = h) (x : M) : g (f x) = h x := by exact foo_apply w x -lemma bar'' {M N K : Mon} {f : M ⟶ N} {g : N ⟶ K} {h : M ⟶ K} (w : f ≫ g = h) (x : M) : +lemma bar'' {M N K : MonCat} {f : M ⟶ N} {g : N ⟶ K} {h : M ⟶ K} (w : f ≫ g = h) (x : M) : g (f x) = h x := by apply foo_apply w -lemma bar''' {M N K : Mon} {f : M ⟶ N} {g : N ⟶ K} {h : M ⟶ K} (w : f ≫ g = h) (x : M) : +lemma bar''' {M N K : MonCat} {f : M ⟶ N} {g : N ⟶ K} {h : M ⟶ K} (w : f ≫ g = h) (x : M) : g (f x) = h x := by apply foo_apply w -example (M N K : Mon) (f : M ⟶ N) (g : N ⟶ K) (h : M ⟶ K) (w : f ≫ g = h) (m : M) : - 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 erw [elementwise_of% w]; rfl -- Porting note: was `rw`, switched to `erw; rfl` -example (M N K : Mon) (f : M ⟶ N) (g : N ⟶ K) (h : M ⟶ K) (w : f ≫ g = h) (m : M) : +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 -- Porting note: did not port `elementwise!` tactic replace w := elementwise_of% w diff --git a/test/Change.lean b/test/Change.lean index babc274c86b5c..a221341553ada 100644 --- a/test/Change.lean +++ b/test/Change.lean @@ -1,5 +1,6 @@ import Mathlib.Tactic.Change +set_option linter.style.setOption false set_option pp.unicode.fun true set_option autoImplicit true diff --git a/test/Check.lean b/test/Check.lean index 5deb44a3b1e48..baa5c95f009a5 100644 --- a/test/Check.lean +++ b/test/Check.lean @@ -6,6 +6,8 @@ open Lean PrettyPrinter Delaborator in @[delab mvar] def delabMVar : Delab := do unless kind.isNatural do failure `(?m) +set_option linter.unusedTactic false + /-! Basic check of `#check` -/ diff --git a/test/Clear!.lean b/test/Clear!.lean index 51a427231d9c3..cf2817c2edc17 100644 --- a/test/Clear!.lean +++ b/test/Clear!.lean @@ -13,7 +13,8 @@ example [delete_this : Inhabited Nat] : Inhabited Nat := by infer_instance -- Confirms clear! can clear the dependencies of multiple hypotheses -example (delete_this : Nat) (delete_this2 : Nat) (_delete_this_dep : delete_this = delete_this2) : Nat := by +example (delete_this : Nat) (delete_this2 : Nat) (_delete_this_dep : delete_this = delete_this2) : + Nat := by clear! delete_this delete_this2 fail_if_success assumption exact 0 diff --git a/test/ClearExcept.lean b/test/ClearExcept.lean index eb1c41a293f92..63bdec1685482 100644 --- a/test/ClearExcept.lean +++ b/test/ClearExcept.lean @@ -1,5 +1,7 @@ import Mathlib.Tactic.ClearExcept +set_option linter.unusedTactic false + -- Most basic test example (_delete_this : Nat) (dont_delete_this : Int) : Nat := by clear * - dont_delete_this @@ -12,13 +14,16 @@ example [dont_delete_this : Inhabited Nat] (dont_delete_this2 : Prop) : Inhabite assumption -- Confirms that clearExcept can clear hypotheses even when they have dependencies -example (delete_this : Nat) (_delete_this2 : delete_this = delete_this) (dont_delete_this : Int) : Nat := by +example (delete_this : Nat) (_delete_this2 : delete_this = delete_this) (dont_delete_this : Int) : + Nat := by clear * - dont_delete_this fail_if_success assumption exact dont_delete_this.toNat --- Confirms that clearExcept does not clear hypotheses when they have dependencies that should not be cleared -example (dont_delete_this : Nat) (dont_delete_this2 : dont_delete_this = dont_delete_this) : Nat := by +-- Confirms that clearExcept does not clear hypotheses +-- when they have dependencies that should not be cleared +example (dont_delete_this : Nat) (dont_delete_this2 : dont_delete_this = dont_delete_this) : + Nat := by clear * - dont_delete_this2 exact dont_delete_this diff --git a/test/Clear_.lean b/test/Clear_.lean index c3dfeefe0a60c..163790d5fb052 100644 --- a/test/Clear_.lean +++ b/test/Clear_.lean @@ -1,6 +1,8 @@ import Mathlib.Tactic.Clear_ import Mathlib.Tactic.Replace +set_option linter.unusedTactic false + -- Most basic test example (_delete_this : Nat) : Nat := by clear_ @@ -19,14 +21,16 @@ example (_delete_this : Nat) (dont_delete_this : Int) : Nat := by exact dont_delete_this.toNat -- Confirms that clear_ can clear hypotheses even when they have dependencies -example (_delete_this : Type) (_delete_this_dep : _delete_this) (_delete_this_rw : _delete_this = Nat) - (_delete_this_dep_dep : _delete_this_dep = _delete_this_dep) : Nat := by +example (_delete_this : Type) (_delete_this_dep : _delete_this) + (_delete_this_rw : _delete_this = Nat) + (_delete_this_dep_dep : _delete_this_dep = _delete_this_dep) : Nat := by clear_ fail_if_success rw [← _delete_this_rw] exact 0 --- Confirms that clear_ does not clear hypotheses when they have dependencies that should not be cleared +-- Confirms that clear_ does not clear hypotheses +-- when they have dependencies that should not be cleared example (_dont_delete_this : Type) (dep : _dont_delete_this) : _dont_delete_this := by clear_ assumption diff --git a/test/DefEqTransformations.lean b/test/DefEqTransformations.lean index dc01755e7f38c..c71039b544292 100644 --- a/test/DefEqTransformations.lean +++ b/test/DefEqTransformations.lean @@ -6,6 +6,8 @@ set_option autoImplicit true private axiom test_sorry : ∀ {α}, α namespace Tests +set_option linter.unusedTactic false + example : id (1 = 1) := by with_reducible whnf guard_target =ₛ id (1 = 1) diff --git a/test/DeriveToExpr.lean b/test/DeriveToExpr.lean index 7780eef44e28c..bed70062a0acb 100644 --- a/test/DeriveToExpr.lean +++ b/test/DeriveToExpr.lean @@ -57,6 +57,7 @@ instance {α : Type u} [ToExpr α] [ToLevel.{u+1}] : ToExpr (Bool → α) where deriving instance ToExpr for Bar +set_option linter.unusedTactic false in example : True := by run_tac do let f : Bool → Nat | false => 0 | true => 1 diff --git a/test/Explode.lean b/test/Explode.lean index 365331fea1844..e19fafdd43863 100644 --- a/test/Explode.lean +++ b/test/Explode.lean @@ -24,7 +24,7 @@ info: true_iff : ∀ (p : Prop), (True ↔ p) = p -/ #guard_msgs in #explode true_iff -set_option linter.setOption false +set_option linter.style.setOption false -- On command line, tests format functions with => rather than ↦ without this. set_option pp.unicode.fun true diff --git a/test/ExtractGoal.lean b/test/ExtractGoal.lean index a69a4e97db20b..c4bb2a70c7fb6 100644 --- a/test/ExtractGoal.lean +++ b/test/ExtractGoal.lean @@ -1,8 +1,8 @@ import Mathlib.Tactic.ExtractGoal -import Mathlib.Init.Data.Nat.Lemmas import Mathlib.Order.Basic import Mathlib.Data.Nat.Defs +set_option linter.style.setOption false set_option pp.unicode.fun true set_option autoImplicit true set_option linter.unusedVariables false diff --git a/test/ExtractLets.lean b/test/ExtractLets.lean index 1cbe0dcc7678c..b2ff5f1b6ecb4 100644 --- a/test/ExtractLets.lean +++ b/test/ExtractLets.lean @@ -32,7 +32,6 @@ example (h : let x := 1; let y := 2; x + 1 = y) : True := by example (h : let x := 1; let y := 2; x + 1 = y) : True := by extract_lets x at h - intros guard_hyp x : Nat := 1 guard_hyp h :ₛ let y := 2; x + 1 = y trivial diff --git a/test/GuardGoalNums.lean b/test/GuardGoalNums.lean index 89e219de17f11..143a75fa193c8 100644 --- a/test/GuardGoalNums.lean +++ b/test/GuardGoalNums.lean @@ -1,5 +1,7 @@ import Mathlib.Tactic.GuardGoalNums +set_option linter.unusedTactic false + example : true ∧ true := by constructor guard_goal_nums 2 diff --git a/test/GuardHypNums.lean b/test/GuardHypNums.lean index cafdfbdc05042..3498547c21238 100644 --- a/test/GuardHypNums.lean +++ b/test/GuardHypNums.lean @@ -1,5 +1,7 @@ import Mathlib.Tactic.GuardHypNums +set_option linter.unusedTactic false + example (a b c : Nat) (_ : a = b) (_ : c = 3) : true := by guard_hyp_nums 6 trivial diff --git a/test/HashCommandLinter.lean b/test/HashCommandLinter.lean index 28bd92ff090c3..203db4657db9e 100644 --- a/test/HashCommandLinter.lean +++ b/test/HashCommandLinter.lean @@ -2,6 +2,8 @@ import Lean.Elab.GuardMsgs import Mathlib.Tactic.AdaptationNote import Mathlib.Tactic.Linter.HashCommandLinter +set_option linter.hashCommand true + section ignored_commands -- `#guard_msgs in` without a doc-string triggers the linter, but with the `doc-string does not @@ -47,6 +49,7 @@ note: this linter can be disabled with `set_option linter.hashCommand false` #guard_msgs in #guard true +set_option linter.unusedTactic false in /-- warning: `#`-commands, such as '#check_tactic', are not allowed in 'Mathlib' note: this linter can be disabled with `set_option linter.hashCommand false` diff --git a/test/HaveLetLinter.lean b/test/HaveLetLinter.lean index 35accc8e607e7..ec7409b66ccde 100644 --- a/test/HaveLetLinter.lean +++ b/test/HaveLetLinter.lean @@ -1,6 +1,8 @@ import Mathlib.Tactic.Linter.HaveLetLinter import Mathlib.Tactic.Tauto +set_option linter.haveLet 1 + /-- A tactic that adds a vacuous `sorry`. Useful for testing the chattiness of the `haveLet` linter. -/ diff --git a/test/LibrarySearch/basic.lean b/test/LibrarySearch/basic.lean index be136b66c0983..ba5f6e3724172 100644 --- a/test/LibrarySearch/basic.lean +++ b/test/LibrarySearch/basic.lean @@ -6,7 +6,7 @@ import Mathlib.Data.Real.Basic set_option autoImplicit true -set_option linter.setOption false +set_option linter.style.setOption false -- Enable this option for tracing: -- set_option trace.Tactic.librarySearch true -- And this option to trace all candidate lemmas before application. diff --git a/test/Lint.lean b/test/Lint.lean index 423b30a42e594..8a0bb34a3dbb1 100644 --- a/test/Lint.lean +++ b/test/Lint.lean @@ -1,5 +1,6 @@ import Mathlib.Tactic.Linter.Lint import Mathlib.Tactic.ToAdditive +import Mathlib.Order.SetNotation -- TODO: the linter also runs on the #guard_msg, so disable it once -- See https://leanprover.zulipchat.com/#narrow/stream/348111-std4/topic/.23guard_msgs.20doesn't.20silence.20warnings/near/423534679 @@ -58,19 +59,23 @@ export Nat (add) end add -set_option linter.cdot false in +section cdotLinter + +set_option linter.style.cdot false + +set_option linter.globalAttributeIn false in /-- warning: Please, use '·' (typed as `\.`) instead of '.' as 'cdot'. -note: this linter can be disabled with `set_option linter.cdot false` +note: this linter can be disabled with `set_option linter.style.cdot false` --- warning: Please, use '·' (typed as `\.`) instead of '.' as 'cdot'. -note: this linter can be disabled with `set_option linter.cdot false` +note: this linter can be disabled with `set_option linter.style.cdot false` --- warning: Please, use '·' (typed as `\.`) instead of '.' as 'cdot'. -note: this linter can be disabled with `set_option linter.cdot false` +note: this linter can be disabled with `set_option linter.style.cdot false` -/ #guard_msgs in -set_option linter.cdot true in +set_option linter.style.cdot true in attribute [instance] Int.add in instance : Inhabited Nat where default := by @@ -78,34 +83,196 @@ instance : Inhabited Nat where · have : Nat → Nat → Nat := (· + .) . exact 0 -set_option linter.cdot false in +set_option linter.style.cdot false in /-- warning: Please, use '·' (typed as `\.`) instead of '.' as 'cdot'. -note: this linter can be disabled with `set_option linter.cdot false` +note: this linter can be disabled with `set_option linter.style.cdot false` -/ #guard_msgs in -set_option linter.cdot true in +set_option linter.style.cdot true in example : Add Nat where add := (. + ·) -set_option linter.longLine false +/-- +warning: Please, use '·' (typed as `\.`) instead of '.' as 'cdot'. +note: this linter can be disabled with `set_option linter.style.cdot false` +-/ +#guard_msgs in +set_option linter.style.cdot true in +example : Add Nat where add := (. + ·) + +/-- +warning: Please, use '·' (typed as `\.`) instead of '.' as 'cdot'. +note: this linter can be disabled with `set_option linter.style.cdot false` +--- +warning: This central dot `·` is isolated; please merge it with the next line. +--- +warning: This central dot `·` is isolated; please merge it with the next line. +-/ +#guard_msgs in +set_option linter.style.cdot true in +example : Nat := by + have : Nat := by + · + -- some empty have + have := 0 + · + + -- another + have := 1 + . exact 2 + exact 0 + +#guard_msgs in +set_option linter.style.cdot true in +example : True := by + have : Nat := by + -- This is how code should look: no error. + · -- comment + exact 37 + trivial + +end cdotLinter + +set_option linter.globalAttributeIn false in +set_option linter.style.dollarSyntax false in +/-- +warning: Please use '<|' instead of '$' for the pipe operator. +note: this linter can be disabled with `set_option linter.style.dollarSyntax false` +--- +warning: Please use '<|' instead of '$' for the pipe operator. +note: this linter can be disabled with `set_option linter.style.dollarSyntax false` +-/ +#guard_msgs in +set_option linter.style.dollarSyntax true in +attribute [instance] Int.add in +instance (f g : Nat → Nat) : Inhabited Nat where + default := by + · have := 0 + · have : Nat := f $ g $ 0 + · exact 0 + +section lambdaSyntaxLinter + +set_option linter.style.lambdaSyntax false + +/-- +warning: Please use 'fun' and not 'λ' to define anonymous functions. +The 'λ' syntax is deprecated in mathlib4. +note: this linter can be disabled with `set_option linter.style.lambdaSyntax false` +-/ +#guard_msgs in +set_option linter.style.lambdaSyntax true in +example : ℕ → ℕ := λ _ ↦ 0 + +/-- +warning: Please use 'fun' and not 'λ' to define anonymous functions. +The 'λ' syntax is deprecated in mathlib4. +note: this linter can be disabled with `set_option linter.style.lambdaSyntax false` +-/ +#guard_msgs in +set_option linter.style.lambdaSyntax true in +def foo : Bool := by + let _f : ℕ → ℕ := λ _ ↦ 0 + exact true + +example : ℕ → ℕ := fun n ↦ n - 1 + +/-- +warning: Please use 'fun' and not 'λ' to define anonymous functions. +The 'λ' syntax is deprecated in mathlib4. +note: this linter can be disabled with `set_option linter.style.lambdaSyntax false` +-/ +#guard_msgs in +set_option linter.style.lambdaSyntax true in +example : ℕ → ℕ := by exact λ n ↦ 3 * n + 1 + +/-- +warning: declaration uses 'sorry' +--- +warning: Please use 'fun' and not 'λ' to define anonymous functions. +The 'λ' syntax is deprecated in mathlib4. +note: this linter can be disabled with `set_option linter.style.lambdaSyntax false` +--- +warning: Please use 'fun' and not 'λ' to define anonymous functions. +The 'λ' syntax is deprecated in mathlib4. +note: this linter can be disabled with `set_option linter.style.lambdaSyntax false` +--- +warning: Please use 'fun' and not 'λ' to define anonymous functions. +The 'λ' syntax is deprecated in mathlib4. +note: this linter can be disabled with `set_option linter.style.lambdaSyntax false` +-/ +#guard_msgs in +set_option linter.style.lambdaSyntax true in +example : ℕ → ℕ → ℕ → ℕ := by + have (n : ℕ) : True := trivial + have : (Set.univ : Set ℕ) = ⋃ (i : ℕ), (Set.iUnion λ j ↦ ({0, j} : Set ℕ)) := sorry + have : ∃ m : ℕ, ⋃ i : ℕ, (Set.univ : Set ℕ) = ∅ := sorry + exact λ _a ↦ fun _b ↦ λ _c ↦ 0 + +/-- +warning: Please use 'fun' and not 'λ' to define anonymous functions. +The 'λ' syntax is deprecated in mathlib4. +note: this linter can be disabled with `set_option linter.style.lambdaSyntax false` +--- +warning: Please use 'fun' and not 'λ' to define anonymous functions. +The 'λ' syntax is deprecated in mathlib4. +note: this linter can be disabled with `set_option linter.style.lambdaSyntax false` +--- +warning: Please use 'fun' and not 'λ' to define anonymous functions. +The 'λ' syntax is deprecated in mathlib4. +note: this linter can be disabled with `set_option linter.style.lambdaSyntax false` +-/ +#guard_msgs in +set_option linter.style.lambdaSyntax true in +example : True := by + have : 0 = 0 ∧ 0 = 0 ∧ 1 + 3 = 4 := by + refine ⟨by trivial, by + let _f := λ n : ℕ ↦ 0; + have : ℕ := by + · -- comment + · have := λ k : ℕ ↦ -5 + · exact 0 + refine ⟨by trivial, have := λ k : ℕ ↦ -5; by simp⟩ + ⟩ + trivial + +-- Code such as the following would require walking the infotree instead: +-- the inner set_option is ignore (in either direction). +-- As this seems unlikely to occur by accident and its use is dubious, we don't worry about this. +/-- +warning: Please use 'fun' and not 'λ' to define anonymous functions. +The 'λ' syntax is deprecated in mathlib4. +note: this linter can be disabled with `set_option linter.style.lambdaSyntax false` +-/ +#guard_msgs in +set_option linter.style.lambdaSyntax true in +example : ℕ → ℕ := set_option linter.style.lambdaSyntax false in λ _ ↦ 0 + +set_option linter.style.lambdaSyntax false +#guard_msgs in +example : ℕ → ℕ := set_option linter.style.lambdaSyntax true in λ _ ↦ 0 + +end lambdaSyntaxLinter + +set_option linter.style.longLine false /-- warning: This line exceeds the 100 character limit, please shorten it! -note: this linter can be disabled with `set_option linter.longLine false` +note: this linter can be disabled with `set_option linter.style.longLine false` -/ #guard_msgs in -set_option linter.longLine true in +set_option linter.style.longLine true in /-! -/ #guard_msgs in -- Lines with more than 100 characters containing URLs are allowed. -set_option linter.longLine true in +set_option linter.style.longLine true in /-! http -/ -set_option linter.longLine true +set_option linter.style.longLine true -- The *argument* of `#guard_msgs` is *not* exempt from the linter. /-- warning: This line exceeds the 100 character limit, please shorten it! -note: this linter can be disabled with `set_option linter.longLine false` +note: this linter can be disabled with `set_option linter.style.longLine false` -/ #guard_msgs in #guard true @@ -116,3 +283,70 @@ info: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, -/ #guard_msgs in #eval List.range 27 + +/- +# 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 320 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 335 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 350 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/LintStyle.lean b/test/LintStyle.lean index 79df48ee1345e..7a58c6c946e9e 100644 --- a/test/LintStyle.lean +++ b/test/LintStyle.lean @@ -6,11 +6,11 @@ import Mathlib.Tactic.Common /-! Tests for the `setOption` linter -/ section setOption --- The warning generated by `linter.setOption` is not suppressed by `#guard_msgs`, +-- The warning generated by `linter.style.setOption` is not suppressed by `#guard_msgs`, -- because the linter is run on `#guard_msgs` itself. This is a known issue, see e.g. -- https://leanprover.zulipchat.com/#narrow/stream/348111-batteries/topic/unreachableTactic.20linter.20not.20suppressed.20by.20.60.23guard_msgs.60 -- We jump through an extra hoop here to silence the warning. -set_option linter.setOption false +set_option linter.style.setOption false -- All types of options are supported: boolean, numeric and string-valued. -- On the top level, i.e. as commands. @@ -19,60 +19,60 @@ set_option linter.setOption false warning: Setting options starting with 'debug', 'pp', 'profiler', 'trace' is only intended for development and not for final code. If you intend to submit this contribution to the Mathlib project, please remove 'set_option pp.all'. -note: this linter can be disabled with `set_option linter.setOption false` +note: this linter can be disabled with `set_option linter.style.setOption false` -/ #guard_msgs in -set_option linter.setOption true in +set_option linter.style.setOption true in set_option pp.all true /-- warning: Setting options starting with 'debug', 'pp', 'profiler', 'trace' is only intended for development and not for final code. If you intend to submit this contribution to the Mathlib project, please remove 'set_option profiler'. -note: this linter can be disabled with `set_option linter.setOption false` +note: this linter can be disabled with `set_option linter.style.setOption false` -/ #guard_msgs in -set_option linter.setOption true in +set_option linter.style.setOption true in set_option profiler false /-- warning: Setting options starting with 'debug', 'pp', 'profiler', 'trace' is only intended for development and not for final code. If you intend to submit this contribution to the Mathlib project, please remove 'set_option pp.all'. -note: this linter can be disabled with `set_option linter.setOption false` +note: this linter can be disabled with `set_option linter.style.setOption false` -/ #guard_msgs in -set_option linter.setOption true in +set_option linter.style.setOption true in set_option pp.all false /-- warning: Setting options starting with 'debug', 'pp', 'profiler', 'trace' is only intended for development and not for final code. If you intend to submit this contribution to the Mathlib project, please remove 'set_option profiler.threshold'. -note: this linter can be disabled with `set_option linter.setOption false` +note: this linter can be disabled with `set_option linter.style.setOption false` -/ #guard_msgs in -set_option linter.setOption true in +set_option linter.style.setOption true in set_option profiler.threshold 50 /-- warning: Setting options starting with 'debug', 'pp', 'profiler', 'trace' is only intended for development and not for final code. If you intend to submit this contribution to the Mathlib project, please remove 'set_option trace.profiler.output'. -note: this linter can be disabled with `set_option linter.setOption false` +note: this linter can be disabled with `set_option linter.style.setOption false` -/ #guard_msgs in -set_option linter.setOption true in +set_option linter.style.setOption true in set_option trace.profiler.output "foo" /-- warning: Setting options starting with 'debug', 'pp', 'profiler', 'trace' is only intended for development and not for final code. If you intend to submit this contribution to the Mathlib project, please remove 'set_option debug.moduleNameAtTimeout'. -note: this linter can be disabled with `set_option linter.setOption false` +note: this linter can be disabled with `set_option linter.style.setOption false` -/ #guard_msgs in -set_option linter.setOption true in +set_option linter.style.setOption true in set_option debug.moduleNameAtTimeout false -- The lint does not fire on arbitrary options. @@ -84,10 +84,10 @@ set_option autoImplicit false warning: Setting options starting with 'debug', 'pp', 'profiler', 'trace' is only intended for development and not for final code. If you intend to submit this contribution to the Mathlib project, please remove 'set_option pp.all'. -note: this linter can be disabled with `set_option linter.setOption false` +note: this linter can be disabled with `set_option linter.style.setOption false` -/ #guard_msgs in -set_option linter.setOption true in +set_option linter.style.setOption true in lemma tactic : True := by set_option pp.all true in trivial @@ -96,10 +96,10 @@ lemma tactic : True := by warning: Setting options starting with 'debug', 'pp', 'profiler', 'trace' is only intended for development and not for final code. If you intend to submit this contribution to the Mathlib project, please remove 'set_option pp.raw.maxDepth'. -note: this linter can be disabled with `set_option linter.setOption false` +note: this linter can be disabled with `set_option linter.style.setOption false` -/ #guard_msgs in -set_option linter.setOption true in +set_option linter.style.setOption true in lemma tactic2 : True := by set_option pp.raw.maxDepth 32 in trivial @@ -108,10 +108,10 @@ lemma tactic2 : True := by warning: Setting options starting with 'debug', 'pp', 'profiler', 'trace' is only intended for development and not for final code. If you intend to submit this contribution to the Mathlib project, please remove 'set_option pp.all'. -note: this linter can be disabled with `set_option linter.setOption false` +note: this linter can be disabled with `set_option linter.style.setOption false` -/ #guard_msgs in -set_option linter.setOption true in +set_option linter.style.setOption true in lemma tactic3 : True := by set_option pp.all false in trivial @@ -120,10 +120,10 @@ lemma tactic3 : True := by warning: Setting options starting with 'debug', 'pp', 'profiler', 'trace' is only intended for development and not for final code. If you intend to submit this contribution to the Mathlib project, please remove 'set_option trace.profiler.output'. -note: this linter can be disabled with `set_option linter.setOption false` +note: this linter can be disabled with `set_option linter.style.setOption false` -/ #guard_msgs in -set_option linter.setOption true in +set_option linter.style.setOption true in lemma tactic4 : True := by set_option trace.profiler.output "foo" in trivial diff --git a/test/MLList.lean b/test/MLList.lean deleted file mode 100644 index 48aa924f5d021..0000000000000 --- a/test/MLList.lean +++ /dev/null @@ -1,68 +0,0 @@ -/- -Copyright (c) 2019 Scott Morrison. All rights reserved. -Released under Apache 2.0 license as described in the file LICENSE. -Authors: Scott Morrison --/ -import Batteries.Data.MLList.Basic -import Mathlib.Control.Basic - -abbrev S (α : Type) := StateT (List Nat) Option α -def append (x : Nat) : S Unit := - fun s => some ((), x :: s) - -def F : Nat → S Nat - | 0 => failure - | (n+1) => do - append (n+1) - pure n - -open Lean - -run_cmd Lean.Elab.Command.liftTermElabM do - -- Note that `fix` fails if any invocation of `F` fails. - -- This is different from previous behaviour, where it just terminated the lazy list. - -- Hence we must use `.takeAsList 11` here rather than `.force`. - let x := ((MLList.fix F 10).takeAsList 11).run [] - guard <| x = some ([10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) - -example : ((MLList.fix F 10).takeAsList 4).run [] = some ([10, 9, 8, 7], [8, 9, 10]) := by - native_decide -example : - (((MLList.fix F 10).map fun n => n*n).takeAsList 3).run [] = - some ([100, 81, 64], [9, 10]) := by - native_decide - -def l1 : MLList S Nat := MLList.ofList [0,1,2] -def l2 : MLList S Nat := MLList.ofList [3,4,5] -def ll : MLList S Nat := (MLList.ofList [l1, l2]).join - -run_cmd Lean.Elab.Command.liftTermElabM do - let x := ll.force.run [] - guard <| x = some ([0, 1, 2, 3, 4, 5], []) - -def half_or_fail (n : Nat) : MetaM Nat := -do guard (n % 2 = 0) - pure (n / 2) - -run_cmd Lean.Elab.Command.liftTermElabM do - let x : MLList MetaM Nat := MLList.range - let y := x.filterMapM fun n => try? <| half_or_fail n - let z ← y.takeAsList 10 - guard <| z.length = 10 - -run_cmd Lean.Elab.Command.liftTermElabM do - let R : MLList MetaM Nat := MLList.range - let S : MLList MetaM Nat := R.filterMapM fun n => try? do - guard (n % 5 = 0) - pure n - let n ← R.takeAsList 5 - let m ← S.head - guard <| n = [0,1,2,3,4] - guard <| m = 0 - -run_cmd Lean.Elab.Command.liftTermElabM do - let R : MLList MetaM Nat := MLList.range - let n ← R.firstM fun n => try? do - guard (n = 5) - pure n - guard <| n = 5 diff --git a/test/MaxPowDiv.lean b/test/MaxPowDiv.lean index dd55a64f247cd..8ec14a17d24c2 100644 --- a/test/MaxPowDiv.lean +++ b/test/MaxPowDiv.lean @@ -1,4 +1,4 @@ -import Mathlib.NumberTheory.Padics.PadicVal +import Mathlib.NumberTheory.Padics.PadicVal.Basic /-- info: 100000 diff --git a/test/MfldSetTac.lean b/test/MfldSetTac.lean index ae6bf752c33cf..fd50fd05c2ca3 100644 --- a/test/MfldSetTac.lean +++ b/test/MfldSetTac.lean @@ -24,7 +24,8 @@ section stub_lemmas structure PartialHomeomorph (α : Type u) (β : Type u) extends PartialEquiv α β noncomputable -instance PartialHomeomorph.has_coe_to_fun : CoeFun (PartialHomeomorph α β) (fun _ ↦ α → β) := test_sorry +instance PartialHomeomorph.has_coe_to_fun : CoeFun (PartialHomeomorph α β) (fun _ ↦ α → β) := + test_sorry noncomputable def PartialHomeomorph.symm (_e : PartialHomeomorph α β) : PartialHomeomorph β α := test_sorry @@ -55,7 +56,8 @@ noncomputable def ModelWithCorners.symm (_I : ModelWithCorners 𝕜 E H) : PartialEquiv E H := test_sorry noncomputable -instance ModelWithCorners.has_coe_to_fun : CoeFun (ModelWithCorners 𝕜 E H) (fun _ ↦ H → E) := test_sorry +instance ModelWithCorners.has_coe_to_fun : CoeFun (ModelWithCorners 𝕜 E H) (fun _ ↦ H → E) := + test_sorry @[mfld_simps] lemma ModelWithCorners.left_inv (I : ModelWithCorners 𝕜 E H) (x : H) : I.symm (I x) = x := diff --git a/test/MinImports.lean b/test/MinImports.lean index 174943a1933b9..abf1594c8f565 100644 --- a/test/MinImports.lean +++ b/test/MinImports.lean @@ -1,4 +1,3 @@ -import Mathlib.Tactic.Linter.MinImports import Mathlib.Tactic.NormNum.Basic import Mathlib.Tactic.FunProp.Attr @@ -37,8 +36,7 @@ noncomputable instance : Semiring Nat := inferInstance /-- info: ℤ : Type --- -info: import Lean.Parser.Command -import Mathlib.Data.Int.Notation +info: import Mathlib.Data.Int.Notation -/ #guard_msgs in #min_imports in #check ℤ @@ -78,7 +76,7 @@ lemma hi (n : ℕ) : n = n := by extract_goal; rfl /-- warning: Imports increased to -[Init.Guard, Lean.Parser.Term, Mathlib.Data.Int.Notation] +[Init.Guard, Mathlib.Data.Int.Notation] note: this linter can be disabled with `set_option linter.minImports false` -/ #guard_msgs in @@ -95,7 +93,7 @@ set_option linter.minImports false in /-- warning: Imports increased to -[Init.Guard, Lean.Parser.Term, Mathlib.Data.Int.Notation] +[Init.Guard, Mathlib.Data.Int.Notation] note: this linter can be disabled with `set_option linter.minImports false` -/ #guard_msgs in @@ -118,7 +116,7 @@ note: this linter can be disabled with `set_option linter.minImports false` /-- warning: Imports increased to -[Mathlib.Tactic.FunProp.Attr, Mathlib.Tactic.Linter.MinImports, Mathlib.Tactic.NormNum.Basic] +[Mathlib.Tactic.FunProp.Attr, Mathlib.Tactic.NormNum.Basic] note: this linter can be disabled with `set_option linter.minImports false` -/ #guard_msgs in diff --git a/test/MoveAdd.lean b/test/MoveAdd.lean index e115ab0e6a48c..74d7a9fd44d70 100644 --- a/test/MoveAdd.lean +++ b/test/MoveAdd.lean @@ -1,5 +1,4 @@ import Mathlib.Tactic.MoveAdd -import Mathlib.Init.Data.Nat.Lemmas import Mathlib.Algebra.Ring.Nat universe u diff --git a/test/Recall.lean b/test/Recall.lean index 9f4a987ba1abd..198fed552b93d 100644 --- a/test/Recall.lean +++ b/test/Recall.lean @@ -3,7 +3,7 @@ import Mathlib.Analysis.Calculus.Deriv.Basic import Mathlib.Analysis.SpecialFunctions.Trigonometric.Basic import Mathlib.Data.Complex.Exponential -set_option linter.setOption false +set_option linter.style.setOption false -- Remark: When the test is run by make/CI, this option is not set, so we set it here. set_option pp.unicode.fun true set_option autoImplicit true diff --git a/test/RewriteSearch/Basic.lean b/test/RewriteSearch/Basic.lean index ef4fb08df014d..8b70141718832 100644 --- a/test/RewriteSearch/Basic.lean +++ b/test/RewriteSearch/Basic.lean @@ -17,7 +17,7 @@ example (xs ys : List α) : (xs ++ ys).length = ys.length + xs.length := by -- This worked in previous versions, but for now doesn't. -- There are of course better tools for AC rewriting, but it would be nice if `rw_search` -- could do a little of it in the course of a longer rewrite. -set_option linter.longLine false in +set_option linter.style.longLine false in /-! -- /- -- info: Try this: rw [← add_assoc, add_right_comm, add_assoc, add_add_add_comm, ← add_assoc, add_right_comm] @@ -35,7 +35,7 @@ example (xs ys : List α) : (xs ++ ys ++ ys).length = 2 * ys.length + xs.length := by rw_search -set_option linter.longLine false in +set_option linter.style.longLine false in /-! info: Try this: rw [List.length_append, List.length_append, Nat.two_mul, Nat.add_assoc, Nat.add_left_comm, Nat.add_right_comm, Nat.add_assoc] -/ @@ -44,7 +44,7 @@ example (xs ys : List α) : (xs ++ ys ++ ys).length = 2 * ys.length + xs.length := by rw_search [-add_rotate] -set_option linter.longLine false in +set_option linter.style.longLine false in /-! info: Try this: rw [Int.add_right_comm, add_right_cancel_iff, add_sub_left_comm, add_sub, Int.add_sub_cancel] -/ diff --git a/test/SimpRw.lean b/test/SimpRw.lean index bf5c80caee23a..466c3c32025e1 100644 --- a/test/SimpRw.lean +++ b/test/SimpRw.lean @@ -34,6 +34,7 @@ example {a : Nat} (∀ b, a - 1 ≤ b) = ∀ b c : Nat, c < a → c < b + 1 := by simp_rw [h1, h2] +set_option linter.unusedTactic false in -- `simp_rw` respects config options example : 1 = 2 := by let a := 2 diff --git a/test/SplitIfs.lean b/test/SplitIfs.lean index e8dbcd8c69649..1809a04cb709e 100644 --- a/test/SplitIfs.lean +++ b/test/SplitIfs.lean @@ -73,6 +73,7 @@ example (P Q : Prop) (w : if P then (if Q then true else true) else true = true) · trivial · trivial +set_option linter.unusedTactic false in example (u : Nat) : (if u = u then 0 else 1) = 0 := by have h : u = u := by rfl split_ifs diff --git a/test/StacksAttribute.lean b/test/StacksAttribute.lean new file mode 100644 index 0000000000000..6c50ed45a9269 --- /dev/null +++ b/test/StacksAttribute.lean @@ -0,0 +1,69 @@ +import Mathlib.Tactic.StacksAttribute + +/-- info: No tags found. -/ +#guard_msgs in +#stacks_tags + +namespace X + +@[stacks A04Q "A comment"] +theorem tagged : True := .intro + +end X + +#guard_msgs in +@[stacks 0BR2, stacks 0X12] +example : True := .intro + +@[stacks 0BR2, stacks 0X14 "I can also have a comment"] +example : True := .intro + +@[stacks 0X14 "I can also have a comment"] +example : True := .intro + +/-- +info: +[Stacks Tag A04Q](https://stacks.math.columbia.edu/tag/A04Q) corresponds to declaration 'X.tagged'. (A comment) +-/ +#guard_msgs in +#stacks_tags + +/-- +info: +[Stacks Tag A04Q](https://stacks.math.columbia.edu/tag/A04Q) corresponds to declaration 'X.tagged'. (A comment) +True +-/ +#guard_msgs in +#stacks_tags! + +section errors + +open Lean Parser Mathlib.Stacks + +def captureException (env : Environment) (s : ParserFn) (input : String) : Except String Syntax := + let ictx := mkInputContext input "" + let s := s.run ictx { env, options := {} } (getTokenTable env) (mkParserState input) + if !s.allErrors.isEmpty then + .error (s.toErrorMsg ictx) + else if ictx.input.atEnd s.pos then + .ok s.stxStack.back + else + .error ((s.mkError "end of input").toErrorMsg ictx) + +/-- error: :1:3: Stacks tags must be exactly 4 characters -/ +#guard_msgs in +run_cmd do + let _ ← Lean.ofExcept <| captureException (← getEnv) stacksTagFn "A05" + +/-- error: :1:4: Stacks tags must consist only of digits and uppercase letters. -/ +#guard_msgs in +run_cmd do + let _ ← Lean.ofExcept <| captureException (← getEnv) stacksTagFn "aaaa" + +/-- error: :1:0: expected stacks tag -/ +#guard_msgs in +run_cmd do + let env ← getEnv + let _ ← Lean.ofExcept <| captureException env stacksTagFn "\"A04Q\"" + +end errors diff --git a/test/StringDiagram.lean b/test/StringDiagram.lean index ec654cf09ce73..1933c6add2017 100644 --- a/test/StringDiagram.lean +++ b/test/StringDiagram.lean @@ -24,7 +24,7 @@ lemma left_triangle {X Y : C} (η : 𝟙_ _ ⟶ X ⊗ Y) (ε : Y ⊗ X ⟶ 𝟙_ /- Place the cursor here and shift-click the 2-morphisms in the tactic state. -/ exact w.elim -/- Instead of writing `with_panel_widgets` everywhere, you can also use this command. -/ +/- Instead of writing `with_panel_widgets` everywhere, you can also use this command. -/ show_panel_widgets [local StringDiagram, local SelectionPanel] lemma yang_baxter {V₁ V₂ V₃ : C} (R : ∀ V₁ V₂ : C, V₁ ⊗ V₂ ⟶ V₂ ⊗ V₁) (w : False) : diff --git a/test/TermBeta.lean b/test/TermBeta.lean index 30a3b74742f04..f54d02ecde615 100644 --- a/test/TermBeta.lean +++ b/test/TermBeta.lean @@ -1,5 +1,6 @@ import Mathlib.Util.TermBeta -- On command line, tests format functions with => rather than ↦ without this. +set_option linter.style.setOption false set_option pp.unicode.fun true /-- info: (fun x ↦ x) true : Bool -/ @@ -23,7 +24,7 @@ set_option pp.unicode.fun true /-- info: ∀ (i : Nat), 0 ≤ i : Prop -/ #guard_msgs in #check ∀ i : Nat, beta% (fun j => 0 ≤ j) i -/-- info: (fun x x_1 ↦ x && x_1) true false : Bool -/ +/-- info: (fun x1 x2 ↦ x1 && x2) true false : Bool -/ #guard_msgs in #check (· && ·) true false /-- info: true && false : Bool -/ diff --git a/test/TypeCheck.lean b/test/TypeCheck.lean index c707c493a6bd8..9d38a614053df 100644 --- a/test/TypeCheck.lean +++ b/test/TypeCheck.lean @@ -1,5 +1,7 @@ import Mathlib.Tactic.TypeCheck +set_option linter.unusedTactic false + /-- A term where `inferType` returns `Prop`, but which does not type check. -/ elab "wrong" : term => return Lean.mkApp2 (.const ``id [.zero]) (.sort .zero) (.app (.sort .zero) (.sort .zero)) diff --git a/test/UnsetOption.lean b/test/UnsetOption.lean index b6cbbe719b387..796a26191f37b 100644 --- a/test/UnsetOption.lean +++ b/test/UnsetOption.lean @@ -1,5 +1,7 @@ import Mathlib.Tactic.UnsetOption +set_option linter.style.setOption false +set_option linter.unusedTactic false set_option pp.all true example : True := by diff --git a/test/UnusedTactic.lean b/test/UnusedTactic.lean index 5dd2b6a81221b..e12d30af91f30 100644 --- a/test/UnusedTactic.lean +++ b/test/UnusedTactic.lean @@ -4,7 +4,7 @@ import Mathlib.Tactic.AdaptationNote def why2 : True → True := (by refine ·) example : True := by - #adaptation_note /--hi-/ + #adaptation_note /-- hi -/ exact .intro -- both `;` and `<;>` are unseen by the linter diff --git a/test/Use.lean b/test/Use.lean index a82114dfd2b85..94acfd37571ab 100644 --- a/test/Use.lean +++ b/test/Use.lean @@ -205,8 +205,8 @@ example (α : Type u) : Embedding α α × Unit := by -- Note(kmill): mathlib3 `use` would try to rewrite any lingering existentials with -- `exists_prop` to turn them into conjunctions. It did not do this recursively. --- example : ∃ (n : Nat) (h : n > 0), n = n := --- by +set_option linter.style.longLine false in +-- example : ∃ (n : Nat) (h : n > 0), n = n := by -- use 1 -- -- goal should now be `1 > 0 ∧ 1 = 1`, whereas it would be `∃ (H : 1 > 0), 1 = 1` after existsi 1. -- guard_target = 1 > 0 ∧ 1 = 1 diff --git a/test/Zify.lean b/test/Zify.lean index 0ff0f60de8ab5..a61537de310b2 100644 --- a/test/Zify.lean +++ b/test/Zify.lean @@ -29,11 +29,11 @@ example (a b : ℕ) (h : (a : ℤ) ≤ b) : a ≤ b := by guard_target = (a : ℤ) ≤ b exact h -/-example (a b : ℕ) (h : a = b ∧ b < a) : False := by +/- example (a b : ℕ) (h : a = b ∧ b < a) : False := by zify at h rcases h with ⟨ha, hb⟩ -- Preorder for `ℤ` is missing - exact ne_of_lt hb ha-/ + exact ne_of_lt hb ha -/ example (a b c : ℕ) (h : a - b < c) (hab : b ≤ a) : True := by zify [hab] at h diff --git a/test/basicTactics.lean b/test/basicTactics.lean index 87c0505900a57..2eaa3aee8ce7e 100644 --- a/test/basicTactics.lean +++ b/test/basicTactics.lean @@ -5,6 +5,7 @@ example : ∀ a b : Nat, a = b → b = a := by introv h exact h.symm +set_option linter.unusedTactic false in example (n : Nat) : n = n := by induction n exacts [rfl, rfl] @@ -45,6 +46,7 @@ example (n m : Nat) : Unit := by cases m iterate exact () +set_option linter.unusedTactic false in example (n : Nat) : Nat := by iterate exact () -- silently succeeds, after iterating 0 times iterate exact n diff --git a/test/byContra.lean b/test/byContra.lean index dd0d781abe597..56a378b97d1e6 100644 --- a/test/byContra.lean +++ b/test/byContra.lean @@ -2,7 +2,6 @@ import Mathlib.Tactic.ByContra import Mathlib.Tactic.Rename import Mathlib.Tactic.Set -import Mathlib.Init.Data.Nat.Lemmas import Mathlib.Order.Basic import Mathlib.Data.Nat.Defs diff --git a/test/casesm.lean b/test/casesm.lean index 5af4572b66196..327f1e0bda163 100644 --- a/test/casesm.lean +++ b/test/casesm.lean @@ -2,6 +2,7 @@ import Mathlib.Tactic.CasesM set_option autoImplicit true +set_option linter.unusedTactic false in example (h : a ∧ b ∨ c ∧ d) (h2 : e ∧ f) : True := by casesm* _∨_, _∧_ · clear ‹a› ‹b› ‹e› ‹f›; (fail_if_success clear ‹c›); trivial diff --git a/test/congr.lean b/test/congr.lean index 7dd402f4cb5dc..d1e2254a6dd4a 100644 --- a/test/congr.lean +++ b/test/congr.lean @@ -343,3 +343,16 @@ example {α : Type} (inst1 : BEq α) [LawfulBEq α] (inst2 : BEq α) [LawfulBEq α] (xs : List α) (x : α) : @List.erase _ inst1 xs x = @List.erase _ inst2 xs x := by congr! (config := { beqEq := false }) + + +/-! +Check that congruence theorem generator operates at default transparency. +Fixes error reported on Zulip: +https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/congr!.20internal.20error/near/464820779 +-/ + +def F := ∀ x : ℕ, x = 0 → ℕ +def F.A (_ : F) : ℕ := 0 +def F.B (_ : F) : ℕ := 0 +theorem bug (H : F) (hp : H.A = 0) (hp' : H.B = 0) : + H H.A hp = H H.B hp' := by with_reducible congr! diff --git a/test/convert.lean b/test/convert.lean index f00e2c3f65a52..4f404da7265ba 100644 --- a/test/convert.lean +++ b/test/convert.lean @@ -110,6 +110,7 @@ example : True := by -- Prior to https://github.com/leanprover/lean4/pull/4493 it did, -- because previously bodies of `example`s were (confusingly!) allowed to -- affect the elaboration of the signature! +set_option linter.unusedTactic false in example {α β : Type u} [Fintype α] [Fintype β] : Fintype.card α = Fintype.card β := by congr! guard_target = Fintype.card α = Fintype.card β diff --git a/test/delabLinearIndependent.lean b/test/delabLinearIndependent.lean index 68798c6dd1627..3dbfbf8b3fda9 100644 --- a/test/delabLinearIndependent.lean +++ b/test/delabLinearIndependent.lean @@ -1,6 +1,6 @@ import Mathlib.LinearAlgebra.LinearIndependent -set_option linter.setOption false +set_option linter.style.setOption false set_option pp.unicode.fun true variable {K V : Type*} [DivisionRing K] [AddCommGroup V] [Module K V] {s : Set V} {x : V} @@ -10,7 +10,7 @@ variable (h : LinearIndependent K (fun b => b : s → V)) in #guard_msgs in #check h variable (h : LinearIndependent K (Subtype.val : s → V)) in -/-- info: h : LinearIndependent (ι := { x // x ∈ s }) K Subtype.val -/ +/-- info: h : LinearIndependent K Subtype.val -/ #guard_msgs in #check h variable (h : LinearIndependent K (by exact Subtype.val : s → V)) in diff --git a/test/fail_if_no_progress.lean b/test/fail_if_no_progress.lean index a4284da8a7c3a..3a69c7344ef13 100644 --- a/test/fail_if_no_progress.lean +++ b/test/fail_if_no_progress.lean @@ -2,6 +2,7 @@ import Mathlib.Tactic.FailIfNoProgress import Mathlib.Tactic.Basic set_option linter.unusedVariables false +set_option linter.style.setOption false set_option pp.unicode.fun true section success diff --git a/test/finsupp_notation.lean b/test/finsupp_notation.lean index e713fedca935a..e042b67a8903f 100644 --- a/test/finsupp_notation.lean +++ b/test/finsupp_notation.lean @@ -21,7 +21,7 @@ info: reprStr (Finsupp.mk {1, 2} (fun | 1 | 2 => 3 | _ => 0) (fun x => by aesop)) = "fun₀ | 1 => 3 | 2 => 3" -/-! ## (computable) number theory examples-/ +/-! ## (computable) number theory examples -/ /-- info: fun₀ | 2 => 2 | 7 => 1 -/ #guard_msgs in diff --git a/test/fun_prop.lean b/test/fun_prop.lean index 5b7a7d504d31b..953fa071dd9a3 100644 --- a/test/fun_prop.lean +++ b/test/fun_prop.lean @@ -188,7 +188,7 @@ The theorem `Measurable.apply_continuousLinearMap` states measurability in `f` i form. -/ -set_option linter.longLine false in +set_option linter.style.longLine false in attribute [fun_prop] ContinuousLinearMap.measurable -- Measurable fun (x : E) => DFunLike.coe L x ContinuousLinearMap.measurable_comp -- Measurable φ → Measurable fun (x : E) => DFunLike.coe L (φ x) @@ -203,7 +203,7 @@ A silly example that everything together works as expected example (f : ℝ → ℝ → (ℝ →L[ℝ] ℝ)) (hf : Continuous (fun (x,y) => f x y)) : Measurable fun x => (f (x / x) (x * x) 1 + x) := by fun_prop -set_option linter.longLine false in +set_option linter.style.longLine false in /-! In the current state of `fun_prop`, morphism theorems **have to** be stated in compositional form. Sometimes they might work in uncurried form but `fun_prop` is not designed that way right now. diff --git a/test/fun_prop2.lean b/test/fun_prop2.lean index 4fcc1f27e7a48..e98b764c72c0a 100644 --- a/test/fun_prop2.lean +++ b/test/fun_prop2.lean @@ -38,11 +38,11 @@ example : Continuous fun ((_, _, z) : ℝ × ℝ × ℝ) ↦ z := by fun_prop @[fun_prop] theorem ContinuousOn.log' : ContinuousOn Real.log {0}ᶜ := ContinuousOn.log (by fun_prop) (by aesop) --- Notice that no theorems about measuability of log are used. It is infered from continuity. +-- Notice that no theorems about measuability of log are used. It is inferred from continuity. example : Measurable (fun x => x * (Real.log x) ^ 2 - Real.exp x / x) := by fun_prop --- Notice that no theorems about measuability of log are used. It is infered from continuity. +-- Notice that no theorems about measuability of log are used. It is inferred from continuity. example : AEMeasurable (fun x => x * (Real.log x) ^ 2 - Real.exp x / x) := by fun_prop (config:={maxTransitionDepth:=2}) diff --git a/test/fun_prop_dev.lean b/test/fun_prop_dev.lean index c9443462421a9..b00a9ac31730a 100644 --- a/test/fun_prop_dev.lean +++ b/test/fun_prop_dev.lean @@ -6,6 +6,7 @@ Authors: Tomáš Skřivan import Mathlib.Tactic.FunProp import Mathlib.Logic.Function.Basic import Mathlib.Data.FunLike.Basic +import Aesop /-! # Tests for the `fun_prop` tactic @@ -13,6 +14,8 @@ This file is designed for development of fun_prop and does not depend on most of two function properties `Con` and `Lin` which roughly correspond to `Continuity` and `IsLinearMap`. -/ +set_option linter.style.longLine false + open Function variable {α β γ δ ι : Type _} {E : α → Type _} @@ -25,18 +28,13 @@ set_option linter.unusedVariables false -- define function propositions -- ---------------------------------- -class Obj (α : Type _) : Type where - -instance [Obj α] [Obj β] : Obj (α × β) := ⟨⟩ -instance [∀ x, Obj (E x)] : Obj ((x' : α) → E x') := ⟨⟩ -instance : Obj Nat := ⟨⟩ - @[fun_prop] opaque Con {α β} (f : α → β) : Prop @[fun_prop] opaque Lin {α β} (f : α → β) : Prop -- state basic lambda calculus rules -- --------------------------------------- +-- variable [Obj α] [Obj β] [Obj γ] [Obj δ] [∀ x, Obj (E x)] @[fun_prop] theorem Con_id : Con (id : α → α) := silentSorry @[fun_prop] theorem Con_const (y : β) : Con (fun x : α => y) := silentSorry @@ -48,7 +46,7 @@ instance : Obj Nat := ⟨⟩ -- Lin is missing `const` theorem @[fun_prop] theorem Lin_id : Lin (fun x : α => x) := silentSorry -@[fun_prop] theorem Lin_const {β} [Obj β] [Zero β] : Lin (fun x : α => (0 : β)) := silentSorry +@[fun_prop] theorem Lin_const {β} [Zero β] : Lin (fun x : α => (0 : β)) := silentSorry @[fun_prop] theorem Lin_apply (x : α) : Lin (fun f : α → β => f x) := silentSorry @[fun_prop] theorem Lin_applyDep (x : α) : Lin (fun f : (x' : α) → E x' => f x) := silentSorry @[fun_prop] theorem Lin_comp (f : β → γ) (g : α → β) (hf : Lin f) (hg : Lin g) : Lin (f ∘ g) := silentSorry @@ -130,13 +128,10 @@ instance [HasUncurry β γ δ] : HasUncurry (α -o β) (α × γ) δ := ⟨fun f p ↦ (↿(f p.1)) p.2⟩ -instance : Obj (α ->> β) := ⟨⟩ -instance : Obj (α -o β) := ⟨⟩ - -- morphism theorems i.e. theorems about `FunLike.coe` -- --------------------------------------------------------- --- this is some form of cartesion closedness with homs `α ->> β` +-- this is some form of cartesian closedness with homs `α ->> β` @[fun_prop] theorem conHom_con' (f : α → β ->> γ) (g : α → β) (hf : Con f) (hg : Con g) : Con (fun x => (f x) (g x)) := silentSorry @[fun_prop] theorem conHom_lin_in_fn' (f : α → β ->> γ) (y : β) (hf : Lin f) : Lin (fun x => f x y) := silentSorry @@ -165,7 +160,7 @@ example [Add β] (f : α → β → γ) (hx : ∀ y, Lin (f · y)) (hy : ∀ x, example [Add α] (f : α → α → α → α) (hx : ∀ x y, Lin (f x y ·)) (hy : ∀ x z, Lin (f x · z)) (hz : ∀ y z, Lin (f · y z)) : Lin (fun x => fun y z ⊸ f z (x+x) y) := by fun_prop --- the only analoge is this theorem but that is alredy provable +-- the only analogue is this theorem but that is already provable example (f : α → β -o γ) (g : α → β) (hf : Lin (fun (x,y) => f x y)) (hg : Lin g) : Lin (fun x => (f x) (g x)) := by fun_prop @@ -317,7 +312,7 @@ example (x) : Con fun (f : α ->> α) => f (f x) := by fun_prop example (x) : Con fun (f : α ->> α) => f (f (f x)) := by fun_prop -example [Zero α] [Obj α] [Add α] : Lin (fun x : α => (0 : α) + x + (0 : α) + (0 : α) + x) := by fun_prop +example [Zero α] [Add α] : Lin (fun x : α => (0 : α) + x + (0 : α) + (0 : α) + x) := by fun_prop noncomputable def foo : α ->> α ->> α := silentSorry @@ -463,3 +458,26 @@ Issues: -/ #guard_msgs in example : Con (fun x : α => f3 x) := by fun_prop (config:={maxTransitionDepth:=0}) + + +@[fun_prop] opaque Dif (𝕜:Type) [Add 𝕜] {α β} (f : α → β) : Prop + +variable {𝕜 : Type} +@[fun_prop] theorem Dif_id [Add 𝕜] : Dif 𝕜 (id : α → α) := silentSorry +@[fun_prop] theorem Dif_const [Add 𝕜] (y : β) : Dif 𝕜 (fun x : α => y) := silentSorry +@[fun_prop] theorem Dif_apply [Add 𝕜] (x : α) : Dif 𝕜 (fun f : α → β => f x) := silentSorry +@[fun_prop] theorem Dif_applyDep [Add 𝕜] (x : α) : Dif 𝕜 (fun f : (x' : α) → E x' => f x) := silentSorry +@[fun_prop] theorem Dif_comp [Add 𝕜] (f : β → γ) (g : α → β) (hf : Dif 𝕜 f) (hg : Dif 𝕜 g) : Dif 𝕜 (fun x => f (g x)) := silentSorry +@[fun_prop] theorem Dif_pi [Add 𝕜] (f : β → (i : α) → (E i)) (hf : ∀ i, Dif 𝕜 (fun x => f x i)) : Dif 𝕜 (fun x i => f x i) := silentSorry + +@[fun_prop] +theorem Dif_Con [Add 𝕜] (f : α → β) (hf : Dif 𝕜 f) : Con f := silentSorry + +def f4 (a : α) := a + +example (hf : Dif Nat (f4 : α → α)) : Con (f4 : α → α) := by fun_prop (disch:=trace_state; aesop) + +@[fun_prop] +theorem f4_dif : Dif Nat (f4 : α → α) := silentSorry + +example (hf : Dif Nat (f4 : α → α)) : Con (f4 : α → α) := by fun_prop (disch:=aesop) diff --git a/test/instance_diamonds.lean b/test/instance_diamonds.lean index 7b746593fdb05..f26a6b719c7ff 100644 --- a/test/instance_diamonds.lean +++ b/test/instance_diamonds.lean @@ -141,7 +141,7 @@ example : @Monoid.toMulOneClass (Multiplicative ℕ) CommMonoid.toMonoid = end Multiplicative -/-! ## `Finsupp` instances-/ +/-! ## `Finsupp` instances -/ section Finsupp diff --git a/test/interactiveUnfold.lean b/test/interactiveUnfold.lean index 0d6bdbed1193f..7972cf5866271 100644 --- a/test/interactiveUnfold.lean +++ b/test/interactiveUnfold.lean @@ -64,7 +64,7 @@ info: Unfolds for 1 + 1: /-- info: Unfolds for 3 ∈ {1, 2, 3}: -· Set.Mem 3 {1, 2, 3} +· {1, 2, 3}.Mem 3 · {1, 2, 3} 3 · Set.insert 1 {2, 3} 3 · {b | b = 1 ∨ b ∈ {2, 3}} 3 @@ -85,7 +85,7 @@ variable (A B : Set Nat) (n : Nat) /-- info: Unfolds for 1 ∈ A ∪ B: -· Set.Mem 1 (A ∪ B) +· (A ∪ B).Mem 1 · (A ∪ B) 1 · A.union B 1 · {a | a ∈ A ∨ a ∈ B} 1 diff --git a/test/itauto.lean b/test/itauto.lean index b628906eca815..94353f251dd30 100644 --- a/test/itauto.lean +++ b/test/itauto.lean @@ -55,6 +55,7 @@ example (b : Bool) : ¬b ∨ b := by itauto * example (p : Prop) : ¬p ∨ p := by itauto! [p] example (p : Prop) : ¬p ∨ p := by itauto! * +set_option linter.unusedTactic false in -- failure tests example (p q r : Prop) : True := by haveI : p ∨ ¬p := by (fail_if_success itauto); sorry diff --git a/test/lift.lean b/test/lift.lean index a8c84bce02c83..979eed74ce45c 100644 --- a/test/lift.lean +++ b/test/lift.lean @@ -1,8 +1,8 @@ import Mathlib.Tactic.Lift import Batteries.Tactic.PermuteGoals import Mathlib.Tactic.Coe -import Mathlib.Init.Set -import Mathlib.Order.Basic +import Mathlib.Data.Set.Defs +import Mathlib.Order.WithBot import Mathlib.Algebra.Group.WithOne.Defs import Mathlib.Data.Set.Image import Mathlib.Data.Set.List diff --git a/test/linear_combination'.lean b/test/linear_combination'.lean new file mode 100644 index 0000000000000..14516504da879 --- /dev/null +++ b/test/linear_combination'.lean @@ -0,0 +1,294 @@ +import Mathlib.Tactic.LinearCombination' +import Mathlib.Tactic.Linarith + + +set_option autoImplicit true + +private axiom test_sorry : ∀ {α}, α + +-- We deliberately mock R here so that we don't have to import the deps +axiom Real : Type +notation "ℝ" => Real +@[instance] axiom Real.linearOrderedField : LinearOrderedField ℝ + +/-! ### Simple Cases with ℤ and two or less equations -/ + +example (x y : ℤ) (h1 : 3 * x + 2 * y = 10) : 3 * x + 2 * y = 10 := by + linear_combination' 1 * h1 + +example (x y : ℤ) (h1 : 3 * x + 2 * y = 10) : 3 * x + 2 * y = 10 := by + linear_combination' h1 + +example (x y : ℤ) (h1 : x + 2 = -3) (_h2 : y = 10) : 2 * x + 4 = -6 := by + linear_combination' 2 * h1 + +example (x y : ℤ) (h1 : x * y + 2 * x = 1) (h2 : x = y) : x * y = -2 * y + 1 := by + linear_combination' 1 * h1 - 2 * h2 + +example (x y : ℤ) (h1 : x * y + 2 * x = 1) (h2 : x = y) : x * y = -2 * y + 1 := by + linear_combination' -2 * h2 + h1 + +example (x y : ℤ) (h1 : x + 2 = -3) (h2 : y = 10) : 2 * x + 4 - y = -16 := by + linear_combination' 2 * h1 + -1 * h2 + +example (x y : ℤ) (h1 : x + 2 = -3) (h2 : y = 10) : -y + 2 * x + 4 = -16 := by + linear_combination' -h2 + 2 * h1 + +example (x y : ℤ) (h1 : 3 * x + 2 * y = 10) (h2 : 2 * x + 5 * y = 3) : 11 * y = -11 := by + linear_combination' -2 * h1 + 3 * h2 + +example (x y : ℤ) (h1 : 3 * x + 2 * y = 10) (h2 : 2 * x + 5 * y = 3) : -11 * y = 11 := by + linear_combination' 2 * h1 - 3 * h2 + +example (x y : ℤ) (h1 : 3 * x + 2 * y = 10) (h2 : 2 * x + 5 * y = 3) : -11 * y = 11 + 1 - 1 := by + linear_combination' 2 * h1 + -3 * h2 + +example (x y : ℤ) (h1 : 10 = 3 * x + 2 * y) (h2 : 3 = 2 * x + 5 * y) : 11 + 1 - 1 = -11 * y := by + linear_combination' 2 * h1 - 3 * h2 + +/-! ### More complicated cases with two equations -/ + +example (x y : ℤ) (h1 : x + 2 = -3) (h2 : y = 10) : -y + 2 * x + 4 = -16 := by + linear_combination' 2 * h1 - h2 + +example (x y : ℚ) (h1 : 3 * x + 2 * y = 10) (h2 : 2 * x + 5 * y = 3) : -11 * y + 1 = 11 + 1 := by + linear_combination' 2 * h1 - 3 * h2 + +example (a b : ℝ) (ha : 2 * a = 4) (hab : 2 * b = a - b) : b = 2 / 3 := by + linear_combination' ha / 6 + hab / 3 + +/-! ### Cases with more than 2 equations -/ + +example (a b : ℝ) (ha : 2 * a = 4) (hab : 2 * b = a - b) (hignore : 3 = a + b) : b = 2 / 3 := by + linear_combination' 1 / 6 * ha + 1 / 3 * hab + 0 * hignore + +example (x y z : ℝ) (ha : x + 2 * y - z = 4) (hb : 2 * x + y + z = -2) (hc : x + 2 * y + z = 2) : + -3 * x - 3 * y - 4 * z = 2 := by linear_combination' ha - hb - 2 * hc + +example (x y z : ℝ) (ha : x + 2 * y - z = 4) (hb : 2 * x + y + z = -2) (hc : x + 2 * y + z = 2) : + 6 * x = -10 := by + linear_combination' 1 * ha + 4 * hb - 3 * hc + +example (x y z : ℝ) (ha : x + 2 * y - z = 4) (hb : 2 * x + y + z = -2) (hc : x + 2 * y + z = 2) : + 10 = 6 * -x := by + linear_combination' ha + 4 * hb - 3 * hc + +example (w x y z : ℝ) (h1 : x + 2.1 * y + 2 * z = 2) (h2 : x + 8 * z + 5 * w = -6.5) + (h3 : x + y + 5 * z + 5 * w = 3) : x + 2.2 * y + 2 * z - 5 * w = -8.5 := by + linear_combination' 2 * h1 + 1 * h2 - 2 * h3 + +example (w x y z : ℝ) (h1 : x + 2.1 * y + 2 * z = 2) (h2 : x + 8 * z + 5 * w = -6.5) + (h3 : x + y + 5 * z + 5 * w = 3) : x + 2.2 * y + 2 * z - 5 * w = -8.5 := by + linear_combination' 2 * h1 + h2 - 2 * h3 + +example (a b c d : ℚ) (h1 : a = 4) (h2 : 3 = b) (h3 : c * 3 = d) (h4 : -d = a) : + 2 * a - 3 + 9 * c + 3 * d = 8 - b + 3 * d - 3 * a := by + linear_combination' 2 * h1 - 1 * h2 + 3 * h3 - 3 * h4 + +example (a b c d : ℚ) (h1 : a = 4) (h2 : 3 = b) (h3 : c * 3 = d) (h4 : -d = a) : + 6 - 3 * c + 3 * a + 3 * d = 2 * b - d + 12 - 3 * a := by + linear_combination' 2 * h2 - h3 + 3 * h1 - 3 * h4 + +/-! ### Cases with non-hypothesis inputs -/ + +axiom qc : ℚ +axiom hqc : qc = 2 * qc + +example (a b : ℚ) (h : ∀ p q : ℚ, p = q) : 3 * a + qc = 3 * b + 2 * qc := by + linear_combination' 3 * h a b + hqc + +axiom bad (q : ℚ) : q = 0 + +example (a b : ℚ) : a + b ^ 3 = 0 := by linear_combination' bad a + b * bad (b * b) + +/-! ### Cases with arbitrary coefficients -/ + +example (a b : ℤ) (h : a = b) : a * a = a * b := by linear_combination' a * h + +example (a b c : ℤ) (h : a = b) : a * c = b * c := by linear_combination' c * h + +example (a b c : ℤ) (h1 : a = b) (h2 : b = 1) : c * a + b = c * b + 1 := by + linear_combination' c * h1 + h2 + +example (x y : ℚ) (h1 : x + y = 3) (h2 : 3 * x = 7) : + x * x * y + y * x * y + 6 * x = 3 * x * y + 14 := by + linear_combination' x * y * h1 + 2 * h2 + +example {α} [h : CommRing α] {a b c d e f : α} (h1 : a * d = b * c) (h2 : c * f = e * d) : + c * (a * f - b * e) = 0 := by linear_combination' e * h1 + a * h2 + +example (x y z w : ℚ) (hzw : z = w) : x * z + 2 * y * z = x * w + 2 * y * w := by + linear_combination' (x + 2 * y) * hzw + +example (x : ℤ) : x ^ 2 = x ^ 2 := by linear_combination' x ^ 2 + +example (x y : ℤ) (h : x = 0) : y ^ 2 * x = 0 := by linear_combination' y ^ 2 * h + +/-! ### Cases that explicitly use a config -/ + +example (x y : ℚ) (h1 : 3 * x + 2 * y = 10) (h2 : 2 * x + 5 * y = 3) : -11 * y + 1 = 11 + 1 := by + linear_combination' (norm := ring) 2 * h1 - 3 * h2 + +example (x y : ℚ) (h1 : 3 * x + 2 * y = 10) (h2 : 2 * x + 5 * y = 3) : -11 * y + 1 = 11 + 1 := by + linear_combination' (norm := ring1) 2 * h1 + -3 * h2 + +example (a b : ℝ) (ha : 2 * a = 4) (hab : 2 * b = a - b) : b = 2 / 3 := by + linear_combination' (norm := ring_nf) 1 / 6 * ha + 1 / 3 * hab + +example (x y : ℤ) (h1 : 3 * x + 2 * y = 10) : 3 * x + 2 * y = 10 := by + linear_combination' (norm := simp) h1 + +/-! ### Cases that have linear_combination' skip normalization -/ + +example (a b : ℝ) (ha : 2 * a = 4) (hab : 2 * b = a - b) : b = 2 / 3 := by + linear_combination' (norm := skip) 1 / 6 * ha + 1 / 3 * hab + linarith + +example (x y : ℤ) (h1 : x = -3) (_h2 : y = 10) : 2 * x = -6 := by + linear_combination' (norm := skip) 2 * h1 + simp (config := {decide := true}) + +/-! ### Cases without any arguments provided -/ + +-- the corner case is "just apply the normalization procedure". +example {x y z w : ℤ} (_h₁ : 3 * x = 4 + y) (_h₂ : x + 2 * y = 1) : z + w = w + z := by + linear_combination' + +-- this interacts as expected with options +example {x y z w : ℤ} (_h₁ : 3 * x = 4 + y) (_h₂ : x + 2 * y = 1) : z + w = w + z := by + linear_combination' (norm := skip) + guard_target = z + w - (w + z) - (0 - 0) = 0 + simp [add_comm] + +example {x y z w : ℤ} (_h₁ : 3 * x = 4 + y) (_h₂ : x + 2 * y = 1) : z + w = w + z := by + linear_combination' (norm := simp [add_comm]) + +/-! ### Cases where the goal is not closed -/ + +example (x y : ℚ) (h1 : x + y = 3) (h2 : 3 * x = 7) : + x * x * y + y * x * y + 6 * x = 3 * x * y + 14 := by + linear_combination' (norm := ring_nf) x * y * h1 + h2 + guard_target = -7 + x * 3 = 0 + linear_combination' h2 + +example (a b c d : ℚ) (h1 : a = 4) (h2 : 3 = b) (h3 : c * 3 = d) (h4 : -d = a) : + 6 - 3 * c + 3 * a + 3 * d = 2 * b - d + 12 - 3 * a := by + linear_combination' (norm := ring_nf) 2 * h2 + linear_combination' (norm := ring_nf) -h3 + linear_combination' (norm := ring_nf) 3 * h1 + linear_combination' (norm := ring_nf) -3 * h4 + +example (x y : ℤ) (h1 : x * y + 2 * x = 1) (h2 : x = y) : x * y = -2 * y + 1 := by + linear_combination' (norm := ring_nf) + linear_combination' h1 - 2 * h2 + +/-! ### 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 + +-- This should fail because the second coefficient has a different type than +-- the equations it is being combined with. This was a design choice for the +-- sake of simplicity, but the tactic could potentially be modified to allow +-- this behavior. +/-- +error: application type mismatch + Mathlib.Tactic.LinearCombination'.c_mul_pf h2 0 +argument + 0 +has type + ℝ : Type +but is expected to have type + ℤ : Type +-/ +#guard_msgs in +example (x y : ℤ) (h1 : x * y + 2 * x = 1) (h2 : x = y) : x * y + 2 * x = 1 := by + linear_combination' h1 + (0 : ℝ) * h2 + +-- This fails because the linear_combination' tactic requires the equations +-- and coefficients to use a type that fulfills the add_group condition, +-- and ℕ does not. +example (a _b : ℕ) (h1 : a = 3) : a = 3 := by + fail_if_success linear_combination' h1 + linear_combination2 h1 + +example (a b : ℤ) (x y : ℝ) (hab : a = b) (hxy : x = y) : 2 * x = 2 * y := by + fail_if_success linear_combination' 2 * hab + linear_combination' 2 * hxy + +/-! ### Cases with exponent -/ + +example (x y z : ℚ) (h : x = y) (h2 : x * y = 0) : x + y*z = 0 := by + linear_combination' (exp := 2) (-y * z ^ 2 + x) * h + (z ^ 2 + 2 * z + 1) * h2 + +example (x y z : ℚ) (h : x = y) (h2 : x * y = 0) : y*z = -x := by + linear_combination' (norm := skip) (exp := 2) (-y * z ^ 2 + x) * h + (z ^ 2 + 2 * z + 1) * h2 + ring + +example (K : Type) + [Field K] + [CharZero K] + {x y z : K} + (h₂ : y ^ 3 + x * (3 * z ^ 2) = 0) + (h₁ : x ^ 3 + z * (3 * y ^ 2) = 0) + (h₀ : y * (3 * x ^ 2) + z ^ 3 = 0) + (h : x ^ 3 * y + y ^ 3 * z + z ^ 3 * x = 0) : + x = 0 := by + linear_combination' (exp := 6) 2 * y * z ^ 2 * h₂ / 7 + (x ^ 3 - y ^ 2 * z / 7) * h₁ - + x * y * z * h₀ + y * z * h / 7 + + +/-! ### Regression tests -/ + +def g (a : ℤ) : ℤ := a ^ 2 + +example (h : g a = g b) : a ^ 4 = b ^ 4 := by + dsimp [g] at h + linear_combination' (a ^ 2 + b ^ 2) * h + +example {r s a b : ℕ} (h₁ : (r : ℤ) = a + 1) (h₂ : (s : ℤ) = b + 1) : + r * s = (a + 1 : ℤ) * (b + 1) := by + linear_combination' (↑b + 1) * h₁ + ↑r * h₂ + +-- Implementation at the time of the port (Nov 2022) was 110,000 heartbeats. +-- Eagerly elaborating leaf nodes brings this to 7,540 heartbeats. +set_option maxHeartbeats 8000 in +example (K : Type*) [Field K] [CharZero K] {x y z p q : K} + (h₀ : 3 * x ^ 2 + z ^ 2 * p = 0) + (h₁ : z * (2 * y) = 0) + (h₂ : -y ^ 2 + p * x * (2 * z) + q * (3 * z ^ 2) = 0) : + ((27 * q ^ 2 + 4 * p ^ 3) * x) ^ 4 = 0 := by + linear_combination' (norm := skip) + (256 / 3 * p ^ 12 * x ^ 2 + 128 * q * p ^ 11 * x * z + 2304 * q ^ 2 * p ^ 9 * x ^ 2 + + 2592 * q ^ 3 * p ^ 8 * x * z - + 64 * q * p ^ 10 * y ^ 2 + + 23328 * q ^ 4 * p ^ 6 * x ^ 2 + + 17496 * q ^ 5 * p ^ 5 * x * z - + 1296 * q ^ 3 * p ^ 7 * y ^ 2 + + 104976 * q ^ 6 * p ^ 3 * x ^ 2 + + 39366 * q ^ 7 * p ^ 2 * x * z - + 8748 * q ^ 5 * p ^ 4 * y ^ 2 + + 177147 * q ^ 8 * x ^ 2 - + 19683 * q ^ 7 * p * y ^ 2) * + h₀ + + (-(64 / 3 * p ^ 12 * x * y) + 32 * q * p ^ 11 * z * y - 432 * q ^ 2 * p ^ 9 * x * y + + 648 * q ^ 3 * p ^ 8 * z * y - + 2916 * q ^ 4 * p ^ 6 * x * y + + 4374 * q ^ 5 * p ^ 5 * z * y - + 6561 * q ^ 6 * p ^ 3 * x * y + + 19683 / 2 * q ^ 7 * p ^ 2 * z * y) * + h₁ + + (-(128 / 3 * p ^ 12 * x * z) - 192 * q * p ^ 10 * x ^ 2 - 864 * q ^ 2 * p ^ 9 * x * z - + 3888 * q ^ 3 * p ^ 7 * x ^ 2 - + 5832 * q ^ 4 * p ^ 6 * x * z - + 26244 * q ^ 5 * p ^ 4 * x ^ 2 - + 13122 * q ^ 6 * p ^ 3 * x * z - + 59049 * q ^ 7 * p * x ^ 2) * + h₂ + exact test_sorry diff --git a/test/linear_combination.lean b/test/linear_combination.lean index c9e02f7fa847e..720e3be8dae8d 100644 --- a/test/linear_combination.lean +++ b/test/linear_combination.lean @@ -120,10 +120,53 @@ example {α} [h : CommRing α] {a b c d e f : α} (h1 : a * d = b * c) (h2 : c * example (x y z w : ℚ) (hzw : z = w) : x * z + 2 * y * z = x * w + 2 * y * w := by linear_combination (x + 2 * y) * hzw -example (x : ℤ) : x ^ 2 = x ^ 2 := by linear_combination x ^ 2 - example (x y : ℤ) (h : x = 0) : y ^ 2 * x = 0 := by linear_combination y ^ 2 * h +/-! ### Tests in semirings -/ + +example (a _b : ℕ) (h1 : a = 3) : a = 3 := by + linear_combination h1 + +example {a b : ℕ} (h1 : a = b + 4) (h2 : b = 2) : a = 6 := by + linear_combination h1 + h2 + +example {a : ℕ} (h : a = 3) : 3 = a := by linear_combination -h + +example {a b : ℕ} (h1 : 3 * a = b + 5) (h2 : 2 * a = b + 3) : a = 2 := by + linear_combination h1 - h2 + +/- Note: currently negation/subtraction is handled differently in "constants" than in "proofs", so +in particular negation/subtraction does not "distribute". The following four tests record the +current behaviour, without taking a stance on whether this should be considered a feature or a bug. +-/ + +example {a : ℕ} (h : a = 3) : a ^ 2 + 3 = 4 * a := by + linear_combination a * h - h + +/-- +error: ring failed, ring expressions not equal +a b : ℕ +h : a = 3 +⊢ 3 + a ^ 2 + (a - 1) * 3 = a * 4 + a * (a - 1) +-/ +#guard_msgs in +example {a b : ℕ} (h : a = 3) : a ^ 2 + 3 = 4 * a := by + linear_combination (a - 1) * h + +example {a b c : ℕ} (h1 : c = 1) (h2 : a - b = 4) : (a - b) * c = 4 := by + linear_combination (a - b) * h1 + h2 + +/-- +error: ring failed, ring expressions not equal +a b c : ℕ +h1 : c = 1 +h2 : a - b = 4 +⊢ 4 + (a - b) * c + c * b + a = 4 + (a - b) + c * a + b +-/ +#guard_msgs in +example {a b c : ℕ} (h1 : c = 1) (h2 : a - b = 4) : (a - b) * c = 4 := by + linear_combination a * h1 - b * h1 + h2 + /-! ### Cases that explicitly use a config -/ example (x y : ℚ) (h1 : 3 * x + 2 * y = 10) (h2 : 2 * x + 5 * y = 3) : -11 * y + 1 = 11 + 1 := by @@ -154,6 +197,8 @@ example (x y : ℤ) (h1 : x = -3) (_h2 : y = 10) : 2 * x = -6 := by example {x y z w : ℤ} (_h₁ : 3 * x = 4 + y) (_h₂ : x + 2 * y = 1) : z + w = w + z := by linear_combination +example (x : ℤ) : x ^ 2 = x ^ 2 := by linear_combination + -- this interacts as expected with options example {x y z w : ℤ} (_h₁ : 3 * x = 4 + y) (_h₂ : x + 2 * y = 1) : z + w = w + z := by linear_combination (norm := skip) @@ -211,17 +256,14 @@ but is expected to have type example (x y : ℤ) (h1 : x * y + 2 * x = 1) (h2 : x = y) : x * y + 2 * x = 1 := by linear_combination h1 + (0 : ℝ) * h2 --- This fails because the linear_combination tactic requires the equations --- and coefficients to use a type that fulfills the add_group condition, --- and ℕ does not. -example (a _b : ℕ) (h1 : a = 3) : a = 3 := by - fail_if_success linear_combination h1 - linear_combination2 h1 - example (a b : ℤ) (x y : ℝ) (hab : a = b) (hxy : x = y) : 2 * x = 2 * y := by fail_if_success linear_combination 2 * hab linear_combination 2 * hxy +/-- error: To run 'linear_combination' without hypotheses, call it without input -/ +#guard_msgs in +example (x : ℤ) : x ^ 2 = x ^ 2 := by linear_combination x ^ 2 + /-! ### Cases with exponent -/ example (x y z : ℚ) (h : x = y) (h2 : x * y = 0) : x + y*z = 0 := by diff --git a/test/meta.lean b/test/meta.lean index 5cd408d0b195a..3d5620d3af41c 100644 --- a/test/meta.lean +++ b/test/meta.lean @@ -11,6 +11,7 @@ namespace Tests open Lean Meta private axiom test_sorry : ∀ {α}, α +set_option linter.style.setOption false in set_option pp.unicode.fun true def eTrue := Expr.const ``True [] @@ -59,6 +60,8 @@ elab "test_forallNot_of_notExists" t:term : tactic => do unless ← isDefEq ety' (← inferType e') do throwError "bad proof" logInfo m!"{ety'}" +set_option linter.unusedTactic false + /-- info: ∀ (x : Nat), ¬0 < x -/ #guard_msgs in example (h : ¬ ∃ x, 0 < x) : False := by diff --git a/test/notation3.lean b/test/notation3.lean index eecf73b2e31a5..c4473b94e10e7 100644 --- a/test/notation3.lean +++ b/test/notation3.lean @@ -1,7 +1,7 @@ import Mathlib.Util.Notation3 -import Mathlib.Init.Data.Nat.Lemmas import Mathlib.Data.Nat.Defs +set_option linter.style.setOption false set_option pp.unicode.fun true set_option autoImplicit true @@ -151,6 +151,7 @@ matcher from the expansion. (Use `set_option trace.notation3 true` to get some d end section +set_option linter.unusedTactic false local notation3 (prettyPrint := false) "#" n => Fin.mk n (by decide) example : Fin 5 := #1 diff --git a/test/old_obtain.lean b/test/oldObtain.lean similarity index 92% rename from test/old_obtain.lean rename to test/oldObtain.lean index 254bb06f364ef..bdbf53e7e9e94 100644 --- a/test/old_obtain.lean +++ b/test/oldObtain.lean @@ -7,6 +7,8 @@ import Mathlib.Tactic.Linter.OldObtain /-! Tests for the `oldObtain` linter. -/ +set_option linter.oldObtain false + -- These cases are fine. theorem foo : True := by obtain := trivial @@ -17,7 +19,6 @@ theorem foo : True := by -- These cases are linted against. -set_option linter.oldObtain false in /-- warning: Please remove stream-of-conciousness `obtain` syntax note: this linter can be disabled with `set_option linter.oldObtain false` @@ -29,7 +30,6 @@ theorem foo' : True := by · trivial trivial -set_option linter.oldObtain false in /-- warning: Please remove stream-of-conciousness `obtain` syntax note: this linter can be disabled with `set_option linter.oldObtain false` diff --git a/test/polyrith.lean b/test/polyrith.lean index a0bd8b137e1f3..58c192b53bdc6 100644 --- a/test/polyrith.lean +++ b/test/polyrith.lean @@ -7,7 +7,7 @@ import Mathlib.Tactic.Polyrith -- Except for the `import`, the doc-modules and the following `set_option`, this file is just -- comments and whitespace. Once the file gets revived, the linting can start! -set_option linter.longLine false +set_option linter.style.longLine false /-! @@ -183,7 +183,7 @@ A full test suite is provided at the bottom of the file. -- "(((((2 * var0) - 3) + (9 * var1)) + (3 * var2)) - (((8 - var3) + (3 * var2)) - (3 * var0)))"] -- "linear_combination 2 * h1 - h2 + 3 * h3 - 3 * h4" --- /-! ### Case with ambiguous identifiers-/ +-- /-! ### Case with ambiguous identifiers -/ -- example («def evil» y : ℤ) (h1 : 3*«def evil» + 2*y = 10) : -- 3*«def evil» + 2*y = 10 := @@ -481,7 +481,7 @@ example (a b c d : ℚ) (h1 : a = 4) (h2 : 3 = b) (h3 : c*3 = d) (h4 : -d = a) : 2*a - 3 + 9*c + 3*d = 8 - b + 3*d - 3*a := by polyrith -/-! ### Case with ambiguous identifiers-/ +/-! ### Case with ambiguous identifiers -/ -- set_option trace.Meta.Tactic.polyrith true example («def evil» y : ℤ) (h1 : 3*«def evil» + 2*y = 10) : 3*«def evil» + 2*y = 10 := by @@ -631,7 +631,7 @@ example (a b c d : ℚ) (h1 : a = 4) (h2 : 3 = b) (h3 : c*3 = d) (h4 : -d = a) : 2*a - 3 + 9*c + 3*d = 8 - b + 3*d - 3*a := by create_polyrith_test -/-! ### Case with ambiguous identifiers-/ +/-! ### Case with ambiguous identifiers -/ example («def evil» y : ℤ) (h1 : 3*«def evil» + 2*y = 10) : 3*«def evil» + 2*y = 10 := by diff --git a/test/propose.lean b/test/propose.lean index bb39586ed5ccd..99c6ece1d4e46 100644 --- a/test/propose.lean +++ b/test/propose.lean @@ -11,9 +11,9 @@ set_option autoImplicit true theorem foo (L M : List α) (w : L.Disjoint M) (m : a ∈ L) : a ∉ M := fun h => w m h /-- -info: Try this: have : K.Disjoint M := List.disjoint_of_subset_left m w ---- info: Try this: have : M.Disjoint L := List.disjoint_symm w +--- +info: Try this: have : K.Disjoint M := List.disjoint_of_subset_left m w -/ #guard_msgs in example (K L M : List α) (w : L.Disjoint M) (m : K ⊆ L) : True := by @@ -70,16 +70,16 @@ info: Try this: have : IsUnit p := isUnit_of_dvd_one h --- info: Try this: have : ¬IsUnit p := not_unit hp --- -info: Try this: have : ¬p ∣ 1 := not_dvd_one hp +info: Try this: have : p ∣ p * p ↔ p ∣ p ∨ p ∣ p := Prime.dvd_mul hp --- info: Try this: have : p ∣ p ∨ p ∣ p := dvd_or_dvd hp (Exists.intro p (Eq.refl (p * p))) --- -info: Try this: have : p ≠ 0 := ne_zero hp ---- -info: Try this: have : p ∣ p * p ↔ p ∣ p ∨ p ∣ p := Prime.dvd_mul hp +info: Try this: have : ¬p ∣ 1 := not_dvd_one hp --- info: Try this: have : IsPrimal p := isPrimal hp --- +info: Try this: have : p ≠ 0 := ne_zero hp +--- info: Try this: have : p ≠ 1 := ne_one hp -/ #guard_msgs in diff --git a/test/recover.lean b/test/recover.lean index f31c6d95e8cca..72d81332f21b0 100644 --- a/test/recover.lean +++ b/test/recover.lean @@ -1,10 +1,12 @@ import Mathlib.Tactic.Recover +set_option linter.unusedTactic false + /-- problematic tactic for testing recovery -/ elab "this" "is" "a" "problem" : tactic => Lean.Elab.Tactic.setGoals [] -/- The main test-/ +/- The main test -/ example : 1 = 1 := by recover this is a problem rfl diff --git a/test/says.lean b/test/says.lean index 0124fb55fd94c..e2f9a3f834662 100644 --- a/test/says.lean +++ b/test/says.lean @@ -57,6 +57,7 @@ example (x y : List α) : (x ++ y).length = x.length + y.length := by simp? says simp only [] set_option linter.unreachableTactic false +set_option linter.unusedTactic false in -- Now we check that `says` does not consume following tactics unless they are indented. /-- error: Tactic `simp` did not produce any messages. diff --git a/test/search/DepthFirst.lean b/test/search/DepthFirst.lean deleted file mode 100644 index fb20922be969c..0000000000000 --- a/test/search/DepthFirst.lean +++ /dev/null @@ -1,11 +0,0 @@ -import Lean.Meta.Basic -import Mathlib.Data.MLList.DepthFirst - -/-- -info: --/ -#guard_msgs in --- We perform a depth first search of the "proper divisors in descending order" tree. -#eval show Lean.MetaM Unit from do - let r := depthFirstRemovingDuplicates' (fun n => List.range n |>.filter (n % · = 0) |>.reverse) 24 - guard <| r = [24, 12, 6, 3, 1, 2, 4, 8] diff --git a/test/set_like.lean b/test/set_like.lean index 284818ca75cd9..a322a2c96e894 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: ↥S → ↥S' : Type u -/ +/-- info: { x // x ∈ S } → { x // x ∈ S' } : Type u -/ #guard_msgs in #check S → S' -/-- info: ↥S : Type u -/ +/-- info: { x // x ∈ S } : Type u -/ #guard_msgs in #check {x // x ∈ S} /-- info: { x // 1 * x ∈ S } : Type u -/ @@ -51,7 +51,7 @@ example [Monoid M] (x y z : M) (S₁ S₂ : Submonoid M) (h : S₁ ≤ S₂) (hx x * y * z ∈ S₁ ⊔ S₂ := by aesop -example [Monoid M] (x y z : M) (S : Submonoid M) (hxy : x * y ∈ S) (hz : z ∈ S) : +example [Monoid M] (x y z : M) (S : Submonoid M) (hxy : x * y ∈ S) (hz : z ∈ S) : z * (x * y) ∈ S := by aesop diff --git a/test/symm.lean b/test/symm.lean index ac2bf3a8d6830..7d88a90868362 100644 --- a/test/symm.lean +++ b/test/symm.lean @@ -15,6 +15,7 @@ def sameParity : Nat → Nat → Prop example (a b : Nat) : sameParity a b → sameParity b a := by intros; symm; assumption +set_option linter.unusedTactic false in example (a b c : Nat) (ab : a = b) (bc : b = c) : c = a := by symm_saturate -- Run twice to check that we don't add repeated copies. @@ -43,7 +44,8 @@ infixl:25 " ≃* " => MulEquiv @[symm] def foo_symm {M N : Type _} [Mul M] [Mul N] (h : M ≃* N) : N ≃* M := - { h.toEquiv.symm with map_mul' := (h.toMulHom.inverse h.toEquiv.symm h.left_inv h.right_inv).map_mul } + { h.toEquiv.symm with map_mul' := + (h.toMulHom.inverse h.toEquiv.symm h.left_inv h.right_inv).map_mul } def MyEq (n m : Nat) := ∃ k, n + k = m ∧ m + k = n diff --git a/test/toAdditive.lean b/test/toAdditive.lean index 13390631ccf6c..cb1938438e035 100644 --- a/test/toAdditive.lean +++ b/test/toAdditive.lean @@ -1,6 +1,5 @@ import Mathlib.Algebra.Group.Defs import Mathlib.Lean.Exception -import Mathlib.Util.Time import Qq.MetaM open Qq Lean Meta Elab Command ToAdditive diff --git a/test/trace.lean b/test/trace.lean index 1ba2fcaed0693..829fd7ee45918 100644 --- a/test/trace.lean +++ b/test/trace.lean @@ -1,4 +1,7 @@ import Mathlib.Tactic.Trace + +set_option linter.unusedTactic false + /-- info: 7 -/ diff --git a/test/trans.lean b/test/trans.lean index 31f9e5506fb08..50b5bc01e7b20 100644 --- a/test/trans.lean +++ b/test/trans.lean @@ -90,6 +90,7 @@ example {A B C : Prop} (h : A → B) (g : B → C) : A → C := by · guard_target =ₛ B → C exact g +set_option linter.unusedTactic false in /-- `trans` for arrows between types. -/ example {A B C : Type} (h : A → B) (g : B → C) : A → C := by trans @@ -99,6 +100,7 @@ example {A B C : Type} (h : A → B) (g : B → C) : A → C := by universe u v w +set_option linter.unusedTactic false in /-- `trans` for arrows between types. -/ example {A : Type u} {B : Type v} {C : Type w} (h : A → B) (g : B → C) : A → C := by trans diff --git a/test/vec_notation.lean b/test/vec_notation.lean index 6828096e09696..6efacef50359c 100644 --- a/test/vec_notation.lean +++ b/test/vec_notation.lean @@ -8,7 +8,7 @@ open Lean open Lean.Meta open Qq -set_option linter.setOption false in +set_option linter.style.setOption false in set_option pp.unicode.fun false /-! These tests are testing `PiFin.toExpr` and fail with diff --git a/widget/src/penrose/commutative.sty b/widget/src/penrose/commutative.sty index f6e189f7b9164..ba276afa7f29c 100644 --- a/widget/src/penrose/commutative.sty +++ b/widget/src/penrose/commutative.sty @@ -18,7 +18,7 @@ const { layout = [Grid, Arrows, EnsureOnCanvas] forall Targettable x { - -- The `center` is the "root" position of a targettable. Cells targetting + -- The `center` is the "root" position of a targettable. Cells targeting -- this targettable start/end at positions relative to the center. -- HACK: The optimization variable has to be defined in terms of two separate -- floats to force Penrose to track dependencies at this granularity rather @@ -46,7 +46,7 @@ forall Targettable x { } -- NOTE: Not used anymore, we use the optimization engine instead. - -- Sides of a Targettable where the ends of cells targetting it are attached. + -- Sides of a Targettable where the ends of cells targeting it are attached. -- +-T-+ -- L C R -- +-B-+ @@ -136,7 +136,7 @@ where f := MakeCell(A, B) { -- in order to make convergence possible. override f.textBox.ensureOnCanvas = false - -- NOTE: This is only necessary for the playground. The Lean widget programatically positions + -- NOTE: This is only necessary for the playground. The Lean widget programmatically positions -- the diagram after optimization. -- ensure onCanvas(f.textBox, canvas.width, canvas.height) in EnsureOnCanvas -- ensure onCanvas(f.shape, canvas.width, canvas.height) in EnsureOnCanvas