diff --git a/.github/workflows/PR_summary.yml b/.github/workflows/PR_summary.yml index 09e8747fdd764..6b854a59292d0 100644 --- a/.github/workflows/PR_summary.yml +++ b/.github/workflows/PR_summary.yml @@ -5,6 +5,7 @@ on: jobs: build: + name: "post-or-update-summary-comment" runs-on: ubuntu-latest steps: diff --git a/.github/workflows/add_label_from_comment.yml b/.github/workflows/add_label_from_comment.yml deleted file mode 100644 index 30a161785134f..0000000000000 --- a/.github/workflows/add_label_from_comment.yml +++ /dev/null @@ -1,60 +0,0 @@ -name: Add "ready-to-merge" and "delegated" label from comment - -on: - issue_comment: - types: [created] - -jobs: - add_ready_to_merge_label: - name: Add ready-to-merge label - 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: - - id: user_permission - uses: actions-cool/check-user-permission@v2 - with: - require: 'admin' - - - if: (steps.user_permission.outputs.require-result == 'true') || (github.event.comment.user.login == 'leanprover-community-mathlib4-bot') || (github.event.comment.user.login == 'leanprover-community-bot-assistant') - uses: octokit/request-action@v2.x - id: add_label - name: Add label - with: - route: POST /repos/:repository/issues/:issue_number/labels - repository: ${{ github.repository }} - issue_number: ${{ github.event.issue.number }} - labels: '["ready-to-merge"]' - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - if: (steps.user_permission.outputs.require-result == 'true') || (github.event.comment.user.login == 'leanprover-community-mathlib4-bot') || (github.event.comment.user.login == 'leanprover-community-bot-assistant') - id: remove_labels - name: Remove "awaiting-author" - # we use curl rather than octokit/request-action so that the job won't fail - # (and send an annoying email) if the labels don't exist - run: | - curl --request DELETE \ - --url https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.issue.number }}/labels/awaiting-author \ - --header 'authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' - - add_delegated_label: - name: Add delegated label - 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: - - id: user_permission - uses: actions-cool/check-user-permission@v2 - with: - require: 'admin' - - - if: (steps.user_permission.outputs.require-result == 'true') || (github.event.comment.user.login == 'leanprover-community-mathlib4-bot') || (github.event.comment.user.login == 'leanprover-community-bot-assistant') - uses: octokit/request-action@v2.x - id: add_label - name: Add label - with: - route: POST /repos/:repository/issues/:issue_number/labels - repository: ${{ github.repository }} - issue_number: ${{ github.event.issue.number }} - labels: '["delegated"]' - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/add_label_from_review.yml b/.github/workflows/add_label_from_review.yml deleted file mode 100644 index 9406866ff214e..0000000000000 --- a/.github/workflows/add_label_from_review.yml +++ /dev/null @@ -1,62 +0,0 @@ -name: Add "ready-to-merge" and "delegated" label from PR review - -on: - pull_request_review: - types: [submitted] - -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), '\nbors r+') || startsWith(github.event.review.body, 'bors merge') || contains(toJSON(github.event.review.body), '\nbors merge')) - runs-on: ubuntu-latest - steps: - - id: user_permission - uses: actions-cool/check-user-permission@v2 - with: - require: 'write' - token: ${{ secrets.TRIAGE_TOKEN }} - - - if: (steps.user_permission.outputs.require-result == 'true') || (github.event.review.user.login == 'leanprover-community-mathlib4-bot') || (github.event.review.user.login == 'leanprover-community-bot-assistant') - uses: octokit/request-action@v2.x - id: add_label - name: Add label - with: - route: POST /repos/:repository/issues/:issue_number/labels - repository: ${{ github.repository }} - issue_number: ${{ github.event.pull_request.number }} - labels: '["ready-to-merge"]' - env: - GITHUB_TOKEN: ${{ secrets.TRIAGE_TOKEN }} - - - if: (steps.user_permission.outputs.require-result == 'true') || (github.event.review.user.login == 'leanprover-community-mathlib4-bot') || (github.event.review.user.login == 'leanprover-community-bot-assistant') - id: remove_labels - name: Remove "awaiting-author" - # we use curl rather than octokit/request-action so that the job won't fail - # (and send an annoying email) if the labels don't exist - run: | - curl --request DELETE \ - --url https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/labels/awaiting-author \ - --header 'authorization: Bearer ${{ secrets.TRIAGE_TOKEN }}' - - add_delegated_label: - name: Add delegated label - if: (startsWith(github.event.review.body, 'bors d') || contains(toJSON(github.event.review.body), '\nbors d')) - runs-on: ubuntu-latest - steps: - - id: user_permission - uses: actions-cool/check-user-permission@v2 - with: - require: 'write' - token: ${{ secrets.TRIAGE_TOKEN }} - - - if: (steps.user_permission.outputs.require-result == 'true') || (github.event.review.user.login == 'leanprover-community-mathlib4-bot') || (github.event.review.user.login == 'leanprover-community-bot-assistant') - uses: octokit/request-action@v2.x - id: add_label - name: Add label - with: - route: POST /repos/:repository/issues/:issue_number/labels - repository: ${{ github.repository }} - issue_number: ${{ github.event.pull_request.number }} - labels: '["delegated"]' - env: - GITHUB_TOKEN: ${{ secrets.TRIAGE_TOKEN }} diff --git a/.github/workflows/add_label_from_review_comment.yml b/.github/workflows/add_label_from_review_comment.yml deleted file mode 100644 index da8b643fb0ee4..0000000000000 --- a/.github/workflows/add_label_from_review_comment.yml +++ /dev/null @@ -1,62 +0,0 @@ -name: Add "ready-to-merge" and "delegated" label from PR review comment - -on: - pull_request_review_comment: - types: [created] - -jobs: - add_ready_to_merge_label: - name: Add ready-to-merge label - if: (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: - - id: user_permission - uses: actions-cool/check-user-permission@v2 - with: - require: 'write' - token: ${{ secrets.TRIAGE_TOKEN }} - - - if: (steps.user_permission.outputs.require-result == 'true') || (github.event.comment.user.login == 'leanprover-community-mathlib4-bot') || (github.event.comment.user.login == 'leanprover-community-bot-assistant') - uses: octokit/request-action@v2.x - id: add_label - name: Add label - with: - route: POST /repos/:repository/issues/:issue_number/labels - repository: ${{ github.repository }} - issue_number: ${{ github.event.pull_request.number }} - labels: '["ready-to-merge"]' - env: - GITHUB_TOKEN: ${{ secrets.TRIAGE_TOKEN }} - - - if: (steps.user_permission.outputs.require-result == 'true') || (github.event.comment.user.login == 'leanprover-community-mathlib4-bot') || (github.event.comment.user.login == 'leanprover-community-bot-assistant') - id: remove_labels - name: Remove "awaiting-author" - # we use curl rather than octokit/request-action so that the job won't fail - # (and send an annoying email) if the labels don't exist - run: | - curl --request DELETE \ - --url https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/labels/awaiting-author \ - --header 'authorization: Bearer ${{ secrets.TRIAGE_TOKEN }}' - - add_delegated_label: - name: Add delegated label - if: (startsWith(github.event.comment.body, 'bors d') || contains(toJSON(github.event.comment.body), '\nbors d')) - runs-on: ubuntu-latest - steps: - - id: user_permission - uses: actions-cool/check-user-permission@v2 - with: - require: 'write' - token: ${{ secrets.TRIAGE_TOKEN }} - - - if: (steps.user_permission.outputs.require-result == 'true') || (github.event.comment.user.login == 'leanprover-community-mathlib4-bot') || (github.event.comment.user.login == 'leanprover-community-bot-assistant') - uses: octokit/request-action@v2.x - id: add_label - name: Add label - with: - route: POST /repos/:repository/issues/:issue_number/labels - repository: ${{ github.repository }} - issue_number: ${{ github.event.pull_request.number }} - labels: '["delegated"]' - env: - GITHUB_TOKEN: ${{ secrets.TRIAGE_TOKEN }} diff --git a/.github/workflows/bench_summary_comment.yml b/.github/workflows/bench_summary_comment.yml index 6672fb8443e98..fe14ecdc32a79 100644 --- a/.github/workflows/bench_summary_comment.yml +++ b/.github/workflows/bench_summary_comment.yml @@ -27,7 +27,7 @@ jobs: run: | { cat scripts/bench_summary.lean - printf $'run_cmd BenchAction.addBenchSummaryComment %s "leanprover-community/mathlib4"' "${PR}" + printf $'run_cmd BenchAction.addBenchSummaryComment %s "leanprover-community/mathlib4" %s' "${PR}" "${{ github.run_id }}" } | lake env lean --stdin env: diff --git a/.github/workflows/discover-lean-pr-testing.yml b/.github/workflows/discover-lean-pr-testing.yml index 3c414d9e99689..349945a0ee8fe 100644 --- a/.github/workflows/discover-lean-pr-testing.yml +++ b/.github/workflows/discover-lean-pr-testing.yml @@ -24,6 +24,25 @@ jobs: git config --global user.name "github-actions" git config --global user.email "github-actions@github.com" + - name: Determine old and new lean-toolchain + id: determine-toolchains + run: | + # `lean-toolchain` contains a string of the form "leanprover/lean4:nightly-2024-11-20" + # We grab the part after the ":" + NEW=$(cut -f2 -d: lean-toolchain) + + # Find the commit hash of the previous change to `lean-toolchain` + PREV_COMMIT=$(git log -2 --format=format:%H -- lean-toolchain | tail -1) + + # Get the contents of `lean-toolchain` from the previous commit + # The "./" in front of the path is important for `git show` + OLD=$(git show "$PREV_COMMIT":./lean-toolchain | cut -f2 -d:) + + echo "old=$OLD" + echo "new=$NEW" + echo "old=$OLD" >> "$GITHUB_OUTPUT" + echo "new=$NEW" >> "$GITHUB_OUTPUT" + - name: Clone lean4 repository and get PRs id: get-prs run: | @@ -38,28 +57,37 @@ jobs: # Navigate to the cloned repository cd lean4-nightly || exit 1 - # Shallow fetch of the last two tags - LAST_TWO_TAGS=$(git ls-remote --tags | grep nightly | tail -2 | cut -f2) - OLD=$(echo "$LAST_TWO_TAGS" | head -1) - NEW=$(echo "$LAST_TWO_TAGS" | tail -1) + # Use the OLD and NEW toolchains determined in the previous step + OLD="${{ steps.determine-toolchains.outputs.old }}" + NEW="${{ steps.determine-toolchains.outputs.new }}" + + # Fetch the $OLD tag git fetch --depth=1 origin tag "$OLD" --no-tags - # Fetch the latest 100 commits prior to the $NEW tag. - # This should cover the terrain between $OLD and $NEW while still being a speedy download. - git fetch --depth=100 origin tag "$NEW" --no-tags + # Fetch the $NEW tag. + # This will only fetch commits newer than previously fetched commits (ie $OLD) + git fetch origin tag "$NEW" --no-tags - PRS=$(git log --oneline "$OLD..$NEW" | sed 's/.*(#\([0-9]\+\))$/\1/') + # Find all commits to lean4 between the $OLD and $NEW toolchains + # and extract the github PR numbers + # (drop anything that doesn't look like a PR number from the final result) + PRS=$(git log --oneline "$OLD..$NEW" | sed 's/.*(#\([0-9]\+\))$/\1/' | grep -E '^[0-9]+$') # Output the PRs echo "$PRS" - echo "prs=$PRS" >> "$GITHUB_OUTPUT" + printf "prs<> "$GITHUB_OUTPUT" - name: Use merged PRs information id: find-branches run: | # Use the PRs from the previous step PRS="${{ steps.get-prs.outputs.prs }}" + echo "=== PRS =========================" + echo "$PRS" echo "$PRS" | tr ' ' '\n' > prs.txt + echo "=== prs.txt =====================" + cat prs.txt MATCHING_BRANCHES=$(git branch -r | grep -f prs.txt) + echo "=== MATCHING_BRANCHES ===========" echo "$MATCHING_BRANCHES" # Initialize an empty variable to store branches with relevant diffs @@ -73,25 +101,26 @@ jobs: # Check if the diff contains files other than the specified ones if echo "$DIFF_FILES" | grep -v -e 'lake-manifest.json' -e 'lakefile.lean' -e 'lean-toolchain'; then # If it does, add the branch to RELEVANT_BRANCHES - RELEVANT_BRANCHES="$RELEVANT_BRANCHES $BRANCH" + RELEVANT_BRANCHES="$RELEVANT_BRANCHES"$'\n- '"$BRANCH" fi done # Output the relevant branches + echo "=== RELEVANT_BRANCHES ===========" echo "'$RELEVANT_BRANCHES'" - echo "branches=$RELEVANT_BRANCHES" >> "$GITHUB_OUTPUT" + printf "branches<> "$GITHUB_OUTPUT" - name: Check if there are relevant branches id: check-branches run: | if [ -z "${{ steps.find-branches.outputs.branches }}" ]; then - echo "no_branches=true" >> "$GITHUB_ENV" + echo "branches_exist=false" >> "$GITHUB_ENV" else - echo "no_branches=false" >> "$GITHUB_ENV" + echo "branches_exist=true" >> "$GITHUB_ENV" fi - name: Send message on Zulip - if: env.no_branches == 'false' + if: env.branches_exist == 'true' uses: zulip/github-actions-zulip/send-message@v1 with: api-key: ${{ secrets.ZULIP_API_KEY }} diff --git a/.github/workflows/maintainer_bors.yml b/.github/workflows/maintainer_bors.yml index 073477b4fa324..10a12e5f3a439 100644 --- a/.github/workflows/maintainer_bors.yml +++ b/.github/workflows/maintainer_bors.yml @@ -19,13 +19,8 @@ jobs: # both set simultaneously: depending on the event that triggers the PR, usually only one is set env: AUTHOR: ${{ github.event.comment.user.login }}${{ github.event.review.user.login }} - PR_NUMBER: ${{ github.event.issue.number }}${{ github.event.pull_request.number }} COMMENT_EVENT: ${{ github.event.comment.body }} COMMENT_REVIEW: ${{ github.event.review.body }} - PR_TITLE_ISSUE: ${{ github.event.issue.title }} - PR_TITLE_PR: ${{ github.event.pull_request.title }} - PR_URL: ${{ github.event.issue.html_url }}${{ github.event.pull_request.html_url }} - EVENT_NAME: ${{ github.event_name }} name: Add ready-to-merge or delegated label runs-on: ubuntu-latest steps: @@ -43,8 +38,7 @@ jobs: printf $'"bors delegate" or "bors merge" found? \'%s\'\n' "${m_or_d}" printf $'AUTHOR: \'%s\'\n' "${AUTHOR}" - printf $'PR_NUMBER: \'%s\'\n' "${PR_NUMBER}" - printf $'OTHER_NUMBER: \'%s\'\n' "${{ github.event.issue.number }}${{ github.event.pull_request.number }}" + printf $'PR_NUMBER: \'%s\'\n' "${{ github.event.issue.number }}${{ github.event.pull_request.number }}" printf $'%s' "${{ github.event.issue.number }}${{ github.event.pull_request.number }}" | hexdump -cC printf $'mOrD=%s\n' "${m_or_d}" >> "${GITHUB_OUTPUT}" @@ -64,9 +58,6 @@ jobs: uses: actions-cool/check-user-permission@v2 with: require: 'admin' - # review(_comment) use - # require: 'write' - # token: ${{ secrets.TRIAGE_TOKEN }} - name: Add ready-to-merge or delegated label id: add_label @@ -75,13 +66,12 @@ jobs: steps.merge_or_delegate.outputs.bot == 'true' ) }} uses: octokit/request-action@v2.x with: - # check is this ok? was /repos/:repository/issues/:issue_number/labels route: POST /repos/:repository/issues/:issue_number/labels repository: ${{ github.repository }} issue_number: ${{ github.event.issue.number }}${{ github.event.pull_request.number }} labels: '["${{ steps.merge_or_delegate.outputs.mOrD }}"]' env: - GITHUB_TOKEN: ${{ secrets.TRIAGE_TOKEN }} # comment uses ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ secrets.TRIAGE_TOKEN }} - if: ${{ ! steps.merge_or_delegate.outputs.mOrD == '' && ( steps.user_permission.outputs.require-result == 'true' || @@ -92,6 +82,37 @@ jobs: # (and send an annoying email) if the labels don't exist run: | curl --request DELETE \ - --url "https://api.github.com/repos/${{ github.repository }}/issues/${PR_NUMBER}/labels/awaiting-author" \ + --url "https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.issue.number }}${{ github.event.pull_request.number }}/labels/awaiting-author" \ --header 'authorization: Bearer ${{ secrets.TRIAGE_TOKEN }}' - # comment uses ${{ secrets.GITHUB_TOKEN }} + + - name: Set up Python + if: ${{ ! steps.merge_or_delegate.outputs.mOrD == '' && + ( steps.user_permission.outputs.require-result == 'true' || + steps.merge_or_delegate.outputs.bot == 'true' ) }} + uses: actions/setup-python@v5 + with: + python-version: '3.x' + + - name: Install dependencies + if: ${{ ! steps.merge_or_delegate.outputs.mOrD == '' && + ( steps.user_permission.outputs.require-result == 'true' || + steps.merge_or_delegate.outputs.bot == 'true' ) }} + run: | + python -m pip install --upgrade pip + pip install zulip + + - uses: actions/checkout@v4 + with: + sparse-checkout: | + scripts/zulip_emoji_merge_delegate.py + + - name: Run Zulip Emoji Merge Delegate Script + if: ${{ ! steps.merge_or_delegate.outputs.mOrD == '' && + ( steps.user_permission.outputs.require-result == 'true' || + steps.merge_or_delegate.outputs.bot == 'true' ) }} + env: + ZULIP_API_KEY: ${{ secrets.ZULIP_API_KEY }} + ZULIP_EMAIL: github-mathlib4-bot@leanprover.zulipchat.com + ZULIP_SITE: https://leanprover.zulipchat.com + run: | + python scripts/zulip_emoji_merge_delegate.py "$ZULIP_API_KEY" "$ZULIP_EMAIL" "$ZULIP_SITE" "${{ steps.merge_or_delegate.outputs.mOrD }}" "${{ github.event.issue.number }}${{ github.event.pull_request.number }}" diff --git a/.github/workflows/sync_closed_tasks.yaml b/.github/workflows/sync_closed_tasks.yaml index 9c73e7e8a24c6..6c5383d62099c 100644 --- a/.github/workflows/sync_closed_tasks.yaml +++ b/.github/workflows/sync_closed_tasks.yaml @@ -12,6 +12,7 @@ on: jobs: build: + name: "Cross off linked issues" runs-on: ubuntu-latest steps: - name: Cross off any linked issue and PR references diff --git a/.github/workflows/zulip_emoji_merge_delegate.yaml b/.github/workflows/zulip_emoji_merge_delegate.yaml index e44b4d07004d9..3de0bc2fd1aa4 100644 --- a/.github/workflows/zulip_emoji_merge_delegate.yaml +++ b/.github/workflows/zulip_emoji_merge_delegate.yaml @@ -1,19 +1,19 @@ name: Zulip Emoji Merge Delegate on: - schedule: - - cron: '0 * * * *' # Runs every hour + push: + branches: + - master jobs: - zulip-emoji-merge-delegate: + zulip-emoji-merged: runs-on: ubuntu-latest steps: - name: Checkout mathlib repository uses: actions/checkout@v4 with: - sparse-checkout: | - scripts + fetch-depth: 0 # donwload the full repository - name: Set up Python uses: actions/setup-python@v5 @@ -30,6 +30,13 @@ jobs: ZULIP_API_KEY: ${{ secrets.ZULIP_API_KEY }} ZULIP_EMAIL: github-mathlib4-bot@leanprover.zulipchat.com ZULIP_SITE: https://leanprover.zulipchat.com - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - python scripts/zulip_emoji_merge_delegate.py "$ZULIP_API_KEY" "$ZULIP_EMAIL" "$ZULIP_SITE" "$GITHUB_TOKEN" + # scan the commits of the past 10 minutes, assuming that the timezone of the current machine + # is the same that performed the commit + git log --since="10 minutes ago" --pretty=oneline + + printf $'Scanning commits:\n%s\n\nContinuing\n' "$(git log --since="10 minutes ago" --pretty=oneline)" + while read -r pr_number; do + printf $'Running the python script with pr "%s"\n' "${pr_number}" + python scripts/zulip_emoji_merge_delegate.py "$ZULIP_API_KEY" "$ZULIP_EMAIL" "$ZULIP_SITE" "[Merged by Bors]" "${pr_number}" + done < <(git log --oneline -n 10 | awk -F# '{ gsub(/)$/, ""); print $NF}') diff --git a/Archive/Hairer.lean b/Archive/Hairer.lean index e9b91c32132a8..6abb80f254220 100644 --- a/Archive/Hairer.lean +++ b/Archive/Hairer.lean @@ -26,6 +26,7 @@ noncomputable section open Metric Set MeasureTheory open MvPolynomial hiding support open Function hiding eval +open scoped ContDiff variable {ι : Type*} [Fintype ι] @@ -110,7 +111,7 @@ lemma inj_L : Injective (L ι) := apply subset_closure lemma hairer (N : ℕ) (ι : Type*) [Fintype ι] : - ∃ (ρ : EuclideanSpace ℝ ι → ℝ), tsupport ρ ⊆ closedBall 0 1 ∧ ContDiff ℝ ⊤ ρ ∧ + ∃ (ρ : EuclideanSpace ℝ ι → ℝ), tsupport ρ ⊆ closedBall 0 1 ∧ ContDiff ℝ ∞ ρ ∧ ∀ (p : MvPolynomial ι ℝ), p.totalDegree ≤ N → ∫ x : EuclideanSpace ℝ ι, eval x p • ρ x = eval 0 p := by have := (inj_L ι).comp (restrictTotalDegree ι ℝ N).injective_subtype diff --git a/Archive/Imo/Imo2008Q2.lean b/Archive/Imo/Imo2008Q2.lean index 0340c3f70479b..41687a4a977a0 100644 --- a/Archive/Imo/Imo2008Q2.lean +++ b/Archive/Imo/Imo2008Q2.lean @@ -106,12 +106,7 @@ theorem imo2008_q2b : Set.Infinite rationalSolutions := by exact ⟨rfl, rfl, rfl⟩ · have hg : -z = g (x, y, z) := rfl rw [hg, hz_def]; ring - have h₂ : q < t * (t + 1) := by - calc - q < q + 1 := by linarith - _ ≤ t := le_max_left (q + 1) 1 - _ ≤ t + t ^ 2 := by linarith [sq_nonneg t] - _ = t * (t + 1) := by ring + have h₂ : q < t * (t + 1) := by linarith [sq_nonneg t, le_max_left (q + 1) 1] exact ⟨h₁, h₂⟩ have hK_inf : Set.Infinite K := by intro h; apply hK_not_bdd; exact Set.Finite.bddAbove h exact hK_inf.of_image g diff --git a/Archive/Imo/Imo2013Q5.lean b/Archive/Imo/Imo2013Q5.lean index 225e64ae35b02..eb996b73633a4 100644 --- a/Archive/Imo/Imo2013Q5.lean +++ b/Archive/Imo/Imo2013Q5.lean @@ -65,15 +65,9 @@ theorem le_of_all_pow_lt_succ' {x y : ℝ} (hx : 1 < x) (hy : 0 < y) refine le_of_all_pow_lt_succ hx ?_ h by_contra! hy'' : y ≤ 1 -- Then there exists y' such that 0 < y ≤ 1 < y' < x. - let y' := (x + 1) / 2 - have h_y'_lt_x : y' < x := - calc - (x + 1) / 2 < x * 2 / 2 := by linarith - _ = x := by field_simp - have h1_lt_y' : 1 < y' := - calc - 1 = 1 * 2 / 2 := by field_simp - _ < (x + 1) / 2 := by linarith + have h_y'_lt_x : (x + 1) / 2 < x := by linarith + have h1_lt_y' : 1 < (x + 1) / 2 := by linarith + set y' := (x + 1) / 2 have h_y_lt_y' : y < y' := by linarith have hh : ∀ n, 0 < n → x ^ n - 1 < y' ^ n := by intro n hn diff --git a/Archive/Imo/Imo2024Q5.lean b/Archive/Imo/Imo2024Q5.lean index 8a20e5be7d721..4fa8394b08d3d 100644 --- a/Archive/Imo/Imo2024Q5.lean +++ b/Archive/Imo/Imo2024Q5.lean @@ -509,7 +509,7 @@ lemma Strategy.play_two (s : Strategy N) (m : MonsterData N) {k : ℕ} (hk : 2 < fin_cases i · rfl · have h : (1 : Fin 2) = Fin.last 1 := rfl - simp only [Fin.snoc_zero, Nat.reduceAdd, Fin.mk_one, Fin.isValue, Matrix.cons_val_one, + simp only [Fin.snoc_zero, Nat.reduceAdd, Fin.mk_one, Fin.isValue, id_eq, Matrix.cons_val_one, Matrix.head_cons] simp only [h, Fin.snoc_last] convert rfl diff --git a/Counterexamples/DirectSumIsInternal.lean b/Counterexamples/DirectSumIsInternal.lean index db6389188d856..7632fb6414a31 100644 --- a/Counterexamples/DirectSumIsInternal.lean +++ b/Counterexamples/DirectSumIsInternal.lean @@ -12,10 +12,10 @@ import Mathlib.Tactic.FinCases # Not all complementary decompositions of a module over a semiring make up a direct sum This shows that while `ℤ≤0` and `ℤ≥0` are complementary `ℕ`-submodules of `ℤ`, which in turn -implies as a collection they are `CompleteLattice.Independent` and that they span all of `ℤ`, they +implies as a collection they are `iSupIndep` and that they span all of `ℤ`, they do not form a decomposition into a direct sum. -This file demonstrates why `DirectSum.isInternal_submodule_of_independent_of_iSup_eq_top` must +This file demonstrates why `DirectSum.isInternal_submodule_of_iSupIndep_of_iSup_eq_top` must take `Ring R` and not `Semiring R`. -/ @@ -57,9 +57,9 @@ theorem withSign.isCompl : IsCompl ℤ≥0 ℤ≤0 := by · exact Submodule.mem_sup_left (mem_withSign_one.mpr hp) · exact Submodule.mem_sup_right (mem_withSign_neg_one.mpr hn) -def withSign.independent : CompleteLattice.Independent withSign := by +def withSign.independent : iSupIndep withSign := by apply - (CompleteLattice.independent_pair UnitsInt.one_ne_neg_one _).mpr withSign.isCompl.disjoint + (iSupIndep_pair UnitsInt.one_ne_neg_one _).mpr withSign.isCompl.disjoint intro i fin_cases i <;> simp diff --git a/Mathlib.lean b/Mathlib.lean index 5922aa04576e9..5785a8dab0524 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -164,6 +164,7 @@ import Mathlib.Algebra.CharP.ExpChar import Mathlib.Algebra.CharP.IntermediateField import Mathlib.Algebra.CharP.Invertible import Mathlib.Algebra.CharP.Lemmas +import Mathlib.Algebra.CharP.LinearMaps import Mathlib.Algebra.CharP.LocalRing import Mathlib.Algebra.CharP.MixedCharZero import Mathlib.Algebra.CharP.Pi @@ -222,6 +223,7 @@ import Mathlib.Algebra.Field.Subfield.Defs import Mathlib.Algebra.Field.ULift import Mathlib.Algebra.Free import Mathlib.Algebra.FreeAlgebra +import Mathlib.Algebra.FreeAlgebra.Cardinality import Mathlib.Algebra.FreeMonoid.Basic import Mathlib.Algebra.FreeMonoid.Count import Mathlib.Algebra.FreeMonoid.Symbols @@ -269,6 +271,7 @@ import Mathlib.Algebra.Group.Fin.Basic import Mathlib.Algebra.Group.Fin.Tuple import Mathlib.Algebra.Group.FiniteSupport import Mathlib.Algebra.Group.ForwardDiff +import Mathlib.Algebra.Group.Graph import Mathlib.Algebra.Group.Hom.Basic import Mathlib.Algebra.Group.Hom.CompTypeclasses import Mathlib.Algebra.Group.Hom.Defs @@ -280,8 +283,12 @@ import Mathlib.Algebra.Group.Int import Mathlib.Algebra.Group.Invertible.Basic import Mathlib.Algebra.Group.Invertible.Defs import Mathlib.Algebra.Group.MinimalAxioms -import Mathlib.Algebra.Group.Nat +import Mathlib.Algebra.Group.Nat.Basic +import Mathlib.Algebra.Group.Nat.Even +import Mathlib.Algebra.Group.Nat.TypeTags +import Mathlib.Algebra.Group.Nat.Units import Mathlib.Algebra.Group.NatPowAssoc +import Mathlib.Algebra.Group.Operations import Mathlib.Algebra.Group.Opposite import Mathlib.Algebra.Group.PNatPowAssoc import Mathlib.Algebra.Group.Pi.Basic @@ -289,7 +296,10 @@ import Mathlib.Algebra.Group.Pi.Lemmas import Mathlib.Algebra.Group.Pointwise.Finset.Basic import Mathlib.Algebra.Group.Pointwise.Finset.Interval import Mathlib.Algebra.Group.Pointwise.Set.Basic +import Mathlib.Algebra.Group.Pointwise.Set.BigOperators import Mathlib.Algebra.Group.Pointwise.Set.Card +import Mathlib.Algebra.Group.Pointwise.Set.Finite +import Mathlib.Algebra.Group.Pointwise.Set.ListOfFn import Mathlib.Algebra.Group.Prod import Mathlib.Algebra.Group.Semiconj.Basic import Mathlib.Algebra.Group.Semiconj.Defs @@ -298,6 +308,9 @@ import Mathlib.Algebra.Group.Subgroup.Actions import Mathlib.Algebra.Group.Subgroup.Basic import Mathlib.Algebra.Group.Subgroup.Defs import Mathlib.Algebra.Group.Subgroup.Finite +import Mathlib.Algebra.Group.Subgroup.Ker +import Mathlib.Algebra.Group.Subgroup.Lattice +import Mathlib.Algebra.Group.Subgroup.Map import Mathlib.Algebra.Group.Subgroup.MulOpposite import Mathlib.Algebra.Group.Subgroup.MulOppositeLemmas import Mathlib.Algebra.Group.Subgroup.Order @@ -318,7 +331,9 @@ import Mathlib.Algebra.Group.Subsemigroup.Membership import Mathlib.Algebra.Group.Subsemigroup.Operations import Mathlib.Algebra.Group.Support import Mathlib.Algebra.Group.Translate -import Mathlib.Algebra.Group.TypeTags +import Mathlib.Algebra.Group.TypeTags.Basic +import Mathlib.Algebra.Group.TypeTags.Finite +import Mathlib.Algebra.Group.TypeTags.Hom import Mathlib.Algebra.Group.ULift import Mathlib.Algebra.Group.UniqueProds.Basic import Mathlib.Algebra.Group.UniqueProds.VectorSpace @@ -505,6 +520,7 @@ import Mathlib.Algebra.Module.Equiv.Basic import Mathlib.Algebra.Module.Equiv.Defs import Mathlib.Algebra.Module.Equiv.Opposite import Mathlib.Algebra.Module.FinitePresentation +import Mathlib.Algebra.Module.FreeLocus import Mathlib.Algebra.Module.GradedModule import Mathlib.Algebra.Module.Hom import Mathlib.Algebra.Module.Injective @@ -639,6 +655,7 @@ import Mathlib.Algebra.Order.Group.CompleteLattice import Mathlib.Algebra.Order.Group.Cone import Mathlib.Algebra.Order.Group.Defs import Mathlib.Algebra.Order.Group.DenselyOrdered +import Mathlib.Algebra.Order.Group.Finset import Mathlib.Algebra.Order.Group.Indicator import Mathlib.Algebra.Order.Group.InjSurj import Mathlib.Algebra.Order.Group.Instances @@ -651,6 +668,7 @@ import Mathlib.Algebra.Order.Group.OrderIso import Mathlib.Algebra.Order.Group.PiLex import Mathlib.Algebra.Order.Group.Pointwise.Bounds import Mathlib.Algebra.Order.Group.Pointwise.CompleteLattice +import Mathlib.Algebra.Order.Group.Pointwise.Interval import Mathlib.Algebra.Order.Group.PosPart import Mathlib.Algebra.Order.Group.Prod import Mathlib.Algebra.Order.Group.Synonym @@ -661,6 +679,7 @@ 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.Finset import Mathlib.Algebra.Order.GroupWithZero.Submonoid import Mathlib.Algebra.Order.GroupWithZero.Synonym import Mathlib.Algebra.Order.GroupWithZero.Unbundled @@ -721,7 +740,6 @@ import Mathlib.Algebra.Order.Ring.Canonical import Mathlib.Algebra.Order.Ring.Cast import Mathlib.Algebra.Order.Ring.Cone import Mathlib.Algebra.Order.Ring.Defs -import Mathlib.Algebra.Order.Ring.Finset import Mathlib.Algebra.Order.Ring.InjSurj import Mathlib.Algebra.Order.Ring.Int import Mathlib.Algebra.Order.Ring.Nat @@ -914,6 +932,7 @@ import Mathlib.AlgebraicGeometry.AffineScheme import Mathlib.AlgebraicGeometry.AffineSpace import Mathlib.AlgebraicGeometry.Cover.MorphismProperty import Mathlib.AlgebraicGeometry.Cover.Open +import Mathlib.AlgebraicGeometry.Cover.Over import Mathlib.AlgebraicGeometry.EllipticCurve.Affine import Mathlib.AlgebraicGeometry.EllipticCurve.DivisionPolynomial.Basic import Mathlib.AlgebraicGeometry.EllipticCurve.DivisionPolynomial.Degree @@ -952,6 +971,7 @@ import Mathlib.AlgebraicGeometry.Morphisms.QuasiSeparated import Mathlib.AlgebraicGeometry.Morphisms.RingHomProperties import Mathlib.AlgebraicGeometry.Morphisms.Separated import Mathlib.AlgebraicGeometry.Morphisms.Smooth +import Mathlib.AlgebraicGeometry.Morphisms.SurjectiveOnStalks import Mathlib.AlgebraicGeometry.Morphisms.UnderlyingMap import Mathlib.AlgebraicGeometry.Morphisms.UniversallyClosed import Mathlib.AlgebraicGeometry.Morphisms.UniversallyInjective @@ -1014,6 +1034,7 @@ import Mathlib.AlgebraicTopology.FundamentalGroupoid.PUnit import Mathlib.AlgebraicTopology.FundamentalGroupoid.Product import Mathlib.AlgebraicTopology.FundamentalGroupoid.SimplyConnected import Mathlib.AlgebraicTopology.MooreComplex +import Mathlib.AlgebraicTopology.Quasicategory.Basic import Mathlib.AlgebraicTopology.SimplexCategory import Mathlib.AlgebraicTopology.SimplicialCategory.Basic import Mathlib.AlgebraicTopology.SimplicialCategory.SimplicialObject @@ -1023,7 +1044,6 @@ import Mathlib.AlgebraicTopology.SimplicialSet.KanComplex import Mathlib.AlgebraicTopology.SimplicialSet.Monoidal import Mathlib.AlgebraicTopology.SimplicialSet.Nerve import Mathlib.AlgebraicTopology.SimplicialSet.Path -import Mathlib.AlgebraicTopology.SimplicialSet.Quasicategory import Mathlib.AlgebraicTopology.SimplicialSet.StrictSegal import Mathlib.AlgebraicTopology.SingularSet import Mathlib.AlgebraicTopology.SplitSimplicialObject @@ -1753,6 +1773,7 @@ import Mathlib.CategoryTheory.Limits.Connected import Mathlib.CategoryTheory.Limits.Constructions.BinaryProducts import Mathlib.CategoryTheory.Limits.Constructions.EpiMono import Mathlib.CategoryTheory.Limits.Constructions.Equalizers +import Mathlib.CategoryTheory.Limits.Constructions.EventuallyConstant import Mathlib.CategoryTheory.Limits.Constructions.Filtered import Mathlib.CategoryTheory.Limits.Constructions.FiniteProductsOfBinaryProducts import Mathlib.CategoryTheory.Limits.Constructions.LimitsOfProductsAndEqualizers @@ -2432,6 +2453,7 @@ import Mathlib.Data.Finsupp.Fintype import Mathlib.Data.Finsupp.Indicator import Mathlib.Data.Finsupp.Interval import Mathlib.Data.Finsupp.Lex +import Mathlib.Data.Finsupp.MonomialOrder import Mathlib.Data.Finsupp.Multiset import Mathlib.Data.Finsupp.NeLocus import Mathlib.Data.Finsupp.Notation @@ -2497,7 +2519,6 @@ import Mathlib.Data.Int.Sqrt import Mathlib.Data.Int.Star import Mathlib.Data.Int.SuccPred import Mathlib.Data.Int.WithZero -import Mathlib.Data.LazyList.Basic import Mathlib.Data.List.AList import Mathlib.Data.List.Basic import Mathlib.Data.List.Chain @@ -2810,11 +2831,7 @@ 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.BigOperators -import Mathlib.Data.Set.Pointwise.Finite -import Mathlib.Data.Set.Pointwise.Interval import Mathlib.Data.Set.Pointwise.Iterate -import Mathlib.Data.Set.Pointwise.ListOfFn import Mathlib.Data.Set.Pointwise.SMul import Mathlib.Data.Set.Pointwise.Support import Mathlib.Data.Set.Prod @@ -2882,6 +2899,7 @@ import Mathlib.Deprecated.Combinator import Mathlib.Deprecated.Equiv import Mathlib.Deprecated.Group import Mathlib.Deprecated.HashMap +import Mathlib.Deprecated.LazyList import Mathlib.Deprecated.Logic import Mathlib.Deprecated.MinMax import Mathlib.Deprecated.NatLemmas @@ -2941,6 +2959,8 @@ import Mathlib.FieldTheory.IsAlgClosed.Classification import Mathlib.FieldTheory.IsAlgClosed.Spectrum import Mathlib.FieldTheory.IsPerfectClosure import Mathlib.FieldTheory.IsSepClosed +import Mathlib.FieldTheory.Isaacs +import Mathlib.FieldTheory.JacobsonNoether import Mathlib.FieldTheory.KrullTopology import Mathlib.FieldTheory.KummerExtension import Mathlib.FieldTheory.Laurent @@ -3767,6 +3787,7 @@ import Mathlib.NumberTheory.LSeries.Linearity import Mathlib.NumberTheory.LSeries.MellinEqDirichlet import Mathlib.NumberTheory.LSeries.Nonvanishing import Mathlib.NumberTheory.LSeries.Positivity +import Mathlib.NumberTheory.LSeries.PrimesInAP import Mathlib.NumberTheory.LSeries.RiemannZeta import Mathlib.NumberTheory.LSeries.ZMod import Mathlib.NumberTheory.LegendreSymbol.AddCharacter @@ -3902,6 +3923,7 @@ import Mathlib.Order.CompletePartialOrder import Mathlib.Order.CompleteSublattice import Mathlib.Order.Concept import Mathlib.Order.ConditionallyCompleteLattice.Basic +import Mathlib.Order.ConditionallyCompleteLattice.Defs import Mathlib.Order.ConditionallyCompleteLattice.Finset import Mathlib.Order.ConditionallyCompleteLattice.Group import Mathlib.Order.ConditionallyCompleteLattice.Indexed @@ -3938,6 +3960,7 @@ import Mathlib.Order.Filter.ENNReal import Mathlib.Order.Filter.EventuallyConst import Mathlib.Order.Filter.Extr import Mathlib.Order.Filter.FilterProduct +import Mathlib.Order.Filter.Finite import Mathlib.Order.Filter.Germ.Basic import Mathlib.Order.Filter.Germ.OrderedMonoid import Mathlib.Order.Filter.IndicatorFunction @@ -4194,6 +4217,7 @@ import Mathlib.RingTheory.Derivation.ToSquareZero import Mathlib.RingTheory.DiscreteValuationRing.Basic import Mathlib.RingTheory.DiscreteValuationRing.TFAE import Mathlib.RingTheory.Discriminant +import Mathlib.RingTheory.DividedPowers.Basic import Mathlib.RingTheory.DualNumber import Mathlib.RingTheory.EisensteinCriterion import Mathlib.RingTheory.EssentialFiniteness @@ -4304,6 +4328,7 @@ import Mathlib.RingTheory.LaurentSeries import Mathlib.RingTheory.LinearDisjoint import Mathlib.RingTheory.LittleWedderburn import Mathlib.RingTheory.LocalProperties.Basic +import Mathlib.RingTheory.LocalProperties.Exactness import Mathlib.RingTheory.LocalProperties.IntegrallyClosed import Mathlib.RingTheory.LocalProperties.Projective import Mathlib.RingTheory.LocalProperties.Reduced @@ -4364,6 +4389,7 @@ import Mathlib.RingTheory.Nakayama import Mathlib.RingTheory.Nilpotent.Basic import Mathlib.RingTheory.Nilpotent.Defs import Mathlib.RingTheory.Nilpotent.Lemmas +import Mathlib.RingTheory.Noetherian.Basic import Mathlib.RingTheory.Noetherian.Defs import Mathlib.RingTheory.Noetherian.Filter import Mathlib.RingTheory.Noetherian.Nilpotent diff --git a/Mathlib/Algebra/AddConstMap/Basic.lean b/Mathlib/Algebra/AddConstMap/Basic.lean index 7dc43d9c08e9a..25685a81e92e9 100644 --- a/Mathlib/Algebra/AddConstMap/Basic.lean +++ b/Mathlib/Algebra/AddConstMap/Basic.lean @@ -28,6 +28,8 @@ We use parameters `a` and `b` instead of `1` to accommodate for two use cases: including orientation-reversing maps. -/ +assert_not_exists Finset + open Function Set /-- A bundled map `f : G → H` such that `f (x + a) = f x + b` for all `x`. @@ -431,7 +433,7 @@ variable {G : Type*} [AddMonoid G] {a : G} as a monoid homomorphism from `Multiplicative G` to `G →+c[a, a] G`. -/ @[simps! (config := .asFn)] def addLeftHom : Multiplicative G →* (G →+c[a, a] G) where - toFun c := Multiplicative.toAdd c +ᵥ .id + toFun c := c.toAdd +ᵥ .id map_one' := by ext; apply zero_add map_mul' _ _ := by ext; apply add_assoc diff --git a/Mathlib/Algebra/AddConstMap/Equiv.lean b/Mathlib/Algebra/AddConstMap/Equiv.lean index ee4c37b716812..28779a4f482cc 100644 --- a/Mathlib/Algebra/AddConstMap/Equiv.lean +++ b/Mathlib/Algebra/AddConstMap/Equiv.lean @@ -5,6 +5,7 @@ Authors: Yury Kudryashov -/ import Mathlib.Algebra.AddConstMap.Basic import Mathlib.GroupTheory.Perm.Basic + /-! # Equivalences conjugating `(· + a)` to `(· + b)` @@ -14,6 +15,8 @@ to be the type of equivalences such that `∀ x, f (x + a) = f x + b`. We also define the corresponding typeclass and prove some basic properties. -/ +assert_not_exists Finset + open Function open scoped AddConstMap diff --git a/Mathlib/Algebra/AddTorsor.lean b/Mathlib/Algebra/AddTorsor.lean index 2ab53a91f84e3..5c7a2b005055b 100644 --- a/Mathlib/Algebra/AddTorsor.lean +++ b/Mathlib/Algebra/AddTorsor.lean @@ -358,7 +358,7 @@ theorem constVAdd_add (v₁ v₂ : G) : constVAdd P (v₁ + v₂) = constVAdd P /-- `Equiv.constVAdd` as a homomorphism from `Multiplicative G` to `Equiv.perm P` -/ def constVAddHom : Multiplicative G →* Equiv.Perm P where - toFun v := constVAdd P (Multiplicative.toAdd v) + toFun v := constVAdd P (v.toAdd) map_one' := constVAdd_zero G P map_mul' := constVAdd_add P @@ -404,13 +404,16 @@ theorem pointReflection_involutive (x : P) : Involutive (pointReflection x : P /-- `x` is the only fixed point of `pointReflection x`. This lemma requires `x + x = y + y ↔ x = y`. There is no typeclass to use here, so we add it as an explicit argument. -/ -theorem pointReflection_fixed_iff_of_injective_bit0 {x y : P} (h : Injective (2 • · : G → G)) : +theorem pointReflection_fixed_iff_of_injective_two_nsmul {x y : P} (h : Injective (2 • · : G → G)) : pointReflection x y = y ↔ y = x := by rw [pointReflection_apply, eq_comm, eq_vadd_iff_vsub_eq, ← neg_vsub_eq_vsub_rev, neg_eq_iff_add_eq_zero, ← two_nsmul, ← nsmul_zero 2, h.eq_iff, vsub_eq_zero_iff_eq, eq_comm] +@[deprecated (since := "2024-11-18")] alias pointReflection_fixed_iff_of_injective_bit0 := +pointReflection_fixed_iff_of_injective_two_nsmul + -- Porting note: need this to calm down CI -theorem injective_pointReflection_left_of_injective_bit0 {G P : Type*} [AddCommGroup G] +theorem injective_pointReflection_left_of_injective_two_nsmul {G P : Type*} [AddCommGroup G] [AddTorsor G P] (h : Injective (2 • · : G → G)) (y : P) : Injective fun x : P => pointReflection x y := fun x₁ x₂ (hy : pointReflection x₁ y = pointReflection x₂ y) => by @@ -418,6 +421,9 @@ theorem injective_pointReflection_left_of_injective_bit0 {G P : Type*} [AddCommG vsub_sub_vsub_cancel_right, ← neg_vsub_eq_vsub_rev, neg_eq_iff_add_eq_zero, ← two_nsmul, ← nsmul_zero 2, h.eq_iff, vsub_eq_zero_iff_eq] at hy +@[deprecated (since := "2024-11-18")] alias injective_pointReflection_left_of_injective_bit0 := +injective_pointReflection_left_of_injective_two_nsmul + end Equiv theorem AddTorsor.subsingleton_iff (G P : Type*) [AddGroup G] [AddTorsor G P] : diff --git a/Mathlib/Algebra/Algebra/Basic.lean b/Mathlib/Algebra/Algebra/Basic.lean index 3e1c923709bb3..98aab66f635a1 100644 --- a/Mathlib/Algebra/Algebra/Basic.lean +++ b/Mathlib/Algebra/Algebra/Basic.lean @@ -133,18 +133,24 @@ end CommSemiring section Ring -variable [CommRing R] -variable (R) - /-- A `Semiring` that is an `Algebra` over a commutative ring carries a natural `Ring` structure. See note [reducible non-instances]. -/ -abbrev semiringToRing [Semiring A] [Algebra R A] : Ring A := +abbrev semiringToRing (R : Type*) [CommRing R] [Semiring A] [Algebra R A] : Ring A := { __ := (inferInstance : Semiring A) __ := Module.addCommMonoidToAddCommGroup R intCast := fun z => algebraMap R A z intCast_ofNat := fun z => by simp only [Int.cast_natCast, map_natCast] intCast_negSucc := fun z => by simp } +instance {R : Type*} [Ring R] : Algebra (Subring.center R) R where + toFun := Subtype.val + map_one' := rfl + map_mul' _ _ := rfl + map_zero' := rfl + map_add' _ _ := rfl + commutes' r x := (Subring.mem_center_iff.1 r.2 x).symm + smul_def' _ _ := rfl + end Ring end Algebra diff --git a/Mathlib/Algebra/Algebra/Defs.lean b/Mathlib/Algebra/Algebra/Defs.lean index f21cc3fe2a3ef..40ac1bbeaf52e 100644 --- a/Mathlib/Algebra/Algebra/Defs.lean +++ b/Mathlib/Algebra/Algebra/Defs.lean @@ -175,6 +175,19 @@ def RingHom.toAlgebra' {R S} [CommSemiring R] [Semiring S] (i : R →+* S) smul_def' _ _ := rfl toRingHom := i +-- just simple lemmas for a declaration that is itself primed, no need for docstrings +set_option linter.docPrime false in +theorem RingHom.smul_toAlgebra' {R S} [CommSemiring R] [Semiring S] (i : R →+* S) + (h : ∀ c x, i c * x = x * i c) (r : R) (s : S) : + let _ := RingHom.toAlgebra' i h + r • s = i r * s := rfl + +set_option linter.docPrime false in +theorem RingHom.algebraMap_toAlgebra' {R S} [CommSemiring R] [Semiring S] (i : R →+* S) + (h : ∀ c x, i c * x = x * i c) : + @algebraMap R S _ _ (i.toAlgebra' h) = i := + rfl + /-- Creating an algebra from a morphism to a commutative semiring. -/ def RingHom.toAlgebra {R S} [CommSemiring R] [CommSemiring S] (i : R →+* S) : Algebra R S := i.toAlgebra' fun _ => mul_comm _ @@ -311,6 +324,36 @@ section end +section compHom + +variable (A) (f : S →+* R) + +/-- +Compose an `Algebra` with a `RingHom`, with action `f s • m`. + +This is the algebra version of `Module.compHom`. +-/ +abbrev compHom : Algebra S A where + smul s a := f s • a + toRingHom := (algebraMap R A).comp f + commutes' _ _ := Algebra.commutes _ _ + smul_def' _ _ := Algebra.smul_def _ _ + +theorem compHom_smul_def (s : S) (x : A) : + letI := compHom A f + s • x = f s • x := rfl + +theorem compHom_algebraMap_eq : + letI := compHom A f + algebraMap S A = (algebraMap R A).comp f := rfl + +theorem compHom_algebraMap_apply (s : S) : + letI := compHom A f + algebraMap S A s = (algebraMap R A) (f s) := rfl + +end compHom + + variable (R A) /-- The canonical ring homomorphism `algebraMap R A : R →+* A` for any `R`-algebra `A`, diff --git a/Mathlib/Algebra/Algebra/Operations.lean b/Mathlib/Algebra/Algebra/Operations.lean index de1a4621d5777..960f805fd05b7 100644 --- a/Mathlib/Algebra/Algebra/Operations.lean +++ b/Mathlib/Algebra/Algebra/Operations.lean @@ -6,9 +6,9 @@ Authors: Kenny Lau import Mathlib.Algebra.Algebra.Bilinear import Mathlib.Algebra.Algebra.Opposite import Mathlib.Algebra.Group.Pointwise.Finset.Basic +import Mathlib.Algebra.Group.Pointwise.Set.BigOperators import Mathlib.Algebra.GroupWithZero.NonZeroDivisors import Mathlib.Algebra.Module.Submodule.Pointwise -import Mathlib.Data.Set.Pointwise.BigOperators import Mathlib.Data.Set.Semiring import Mathlib.GroupTheory.GroupAction.SubMulAction.Pointwise diff --git a/Mathlib/Algebra/Algebra/Unitization.lean b/Mathlib/Algebra/Algebra/Unitization.lean index 42a25ab336b19..89f706b546d03 100644 --- a/Mathlib/Algebra/Algebra/Unitization.lean +++ b/Mathlib/Algebra/Algebra/Unitization.lean @@ -743,8 +743,7 @@ def starLift : (A →⋆ₙₐ[R] C) ≃ (Unitization R A →⋆ₐ[R] C) := right_inv := fun φ => Unitization.algHom_ext'' <| by simp } --- Note (#6057) : tagging simpNF because linter complains -@[simp high, nolint simpNF] +@[simp high] theorem starLift_symm_apply_apply (φ : Unitization R A →⋆ₐ[R] C) (a : A) : Unitization.starLift.symm φ a = φ a := rfl diff --git a/Mathlib/Algebra/BigOperators/Finsupp.lean b/Mathlib/Algebra/BigOperators/Finsupp.lean index a02b2d8a48142..dffd8f94b48be 100644 --- a/Mathlib/Algebra/BigOperators/Finsupp.lean +++ b/Mathlib/Algebra/BigOperators/Finsupp.lean @@ -86,22 +86,17 @@ theorem prod_ite_eq [DecidableEq α] (f : α →₀ M) (a : α) (b : α → M dsimp [Finsupp.prod] rw [f.support.prod_ite_eq] -/- Porting note: simpnf linter, added aux lemma below -Left-hand side simplifies from - Finsupp.sum f fun x v => if a = x then v else 0 -to - if ↑f a = 0 then 0 else ↑f a --/ --- @[simp] theorem sum_ite_self_eq [DecidableEq α] {N : Type*} [AddCommMonoid N] (f : α →₀ N) (a : α) : (f.sum fun x v => ite (a = x) v 0) = f a := by classical convert f.sum_ite_eq a fun _ => id simp [ite_eq_right_iff.2 Eq.symm] --- Porting note: Added this thm to replace the simp in the previous one. Need to add [DecidableEq N] +/-- +The left hand side of `sum_ite_self_eq` simplifies; this is the variant that is useful for `simp`. +-/ @[simp] -theorem sum_ite_self_eq_aux [DecidableEq α] {N : Type*} [AddCommMonoid N] (f : α →₀ N) (a : α) : +theorem if_mem_support [DecidableEq α] {N : Type*} [AddCommMonoid N] (f : α →₀ N) (a : α) : (if a ∈ f.support then f a else 0) = f a := by simp only [mem_support_iff, ne_eq, ite_eq_left_iff, not_not] exact fun h ↦ h.symm @@ -113,6 +108,7 @@ theorem prod_ite_eq' [DecidableEq α] (f : α →₀ M) (a : α) (b : α → M dsimp [Finsupp.prod] rw [f.support.prod_ite_eq'] +/-- A restatement of `sum_ite_self_eq` with the equality test reversed. -/ theorem sum_ite_self_eq' [DecidableEq α] {N : Type*} [AddCommMonoid N] (f : α →₀ N) (a : α) : (f.sum fun x v => ite (x = a) v 0) = f a := by classical diff --git a/Mathlib/Algebra/BigOperators/Group/Finset.lean b/Mathlib/Algebra/BigOperators/Group/Finset.lean index a8d12379bbcce..282177e1ba7c0 100644 --- a/Mathlib/Algebra/BigOperators/Group/Finset.lean +++ b/Mathlib/Algebra/BigOperators/Group/Finset.lean @@ -2197,7 +2197,7 @@ variable [Monoid α] theorem ofMul_list_prod (s : List α) : ofMul s.prod = (s.map ofMul).sum := by simp [ofMul]; rfl @[simp] -theorem toMul_list_sum (s : List (Additive α)) : toMul s.sum = (s.map toMul).prod := by +theorem toMul_list_sum (s : List (Additive α)) : s.sum.toMul = (s.map toMul).prod := by simp [toMul, ofMul]; rfl end Monoid @@ -2210,7 +2210,7 @@ variable [AddMonoid α] theorem ofAdd_list_prod (s : List α) : ofAdd s.sum = (s.map ofAdd).prod := by simp [ofAdd]; rfl @[simp] -theorem toAdd_list_sum (s : List (Multiplicative α)) : toAdd s.prod = (s.map toAdd).sum := by +theorem toAdd_list_sum (s : List (Multiplicative α)) : s.prod.toAdd = (s.map toAdd).sum := by simp [toAdd, ofAdd]; rfl end AddMonoid @@ -2224,7 +2224,7 @@ theorem ofMul_multiset_prod (s : Multiset α) : ofMul s.prod = (s.map ofMul).sum simp [ofMul]; rfl @[simp] -theorem toMul_multiset_sum (s : Multiset (Additive α)) : toMul s.sum = (s.map toMul).prod := by +theorem toMul_multiset_sum (s : Multiset (Additive α)) : s.sum.toMul = (s.map toMul).prod := by simp [toMul, ofMul]; rfl @[simp] @@ -2233,7 +2233,7 @@ theorem ofMul_prod (s : Finset ι) (f : ι → α) : ofMul (∏ i ∈ s, f i) = @[simp] theorem toMul_sum (s : Finset ι) (f : ι → Additive α) : - toMul (∑ i ∈ s, f i) = ∏ i ∈ s, toMul (f i) := + (∑ i ∈ s, f i).toMul = ∏ i ∈ s, (f i).toMul := rfl end CommMonoid @@ -2248,7 +2248,7 @@ theorem ofAdd_multiset_prod (s : Multiset α) : ofAdd s.sum = (s.map ofAdd).prod @[simp] theorem toAdd_multiset_sum (s : Multiset (Multiplicative α)) : - toAdd s.prod = (s.map toAdd).sum := by + s.prod.toAdd = (s.map toAdd).sum := by simp [toAdd, ofAdd]; rfl @[simp] @@ -2257,7 +2257,7 @@ theorem ofAdd_sum (s : Finset ι) (f : ι → α) : ofAdd (∑ i ∈ s, f i) = @[simp] theorem toAdd_prod (s : Finset ι) (f : ι → Multiplicative α) : - toAdd (∏ i ∈ s, f i) = ∑ i ∈ s, toAdd (f i) := + (∏ i ∈ s, f i).toAdd = ∑ i ∈ s, (f i).toAdd := rfl end AddCommMonoid diff --git a/Mathlib/Algebra/BigOperators/Group/List.lean b/Mathlib/Algebra/BigOperators/Group/List.lean index 3dde47cda9794..981bf33926d5a 100644 --- a/Mathlib/Algebra/BigOperators/Group/List.lean +++ b/Mathlib/Algebra/BigOperators/Group/List.lean @@ -634,7 +634,7 @@ end MonoidHom end MonoidHom set_option linter.deprecated false in -@[simp, deprecated (since := "2024-10-17")] +@[simp, deprecated "No deprecation message was provided." (since := "2024-10-17")] lemma Nat.sum_eq_listSum (l : List ℕ) : Nat.sum l = l.sum := rfl namespace List @@ -657,7 +657,8 @@ theorem ranges_nodup {l s : List ℕ} (hs : s ∈ ranges l) : s.Nodup := /-- Any entry of any member of `l.ranges` is strictly smaller than `l.sum`. -/ lemma mem_mem_ranges_iff_lt_sum (l : List ℕ) {n : ℕ} : - (∃ s ∈ l.ranges, n ∈ s) ↔ n < l.sum := by simp [mem_mem_ranges_iff_lt_natSum] + (∃ s ∈ l.ranges, n ∈ s) ↔ n < l.sum := by + rw [← mem_range, ← ranges_flatten, mem_flatten] @[simp] theorem length_flatMap (l : List α) (f : α → List β) : diff --git a/Mathlib/Algebra/Category/AlgebraCat/Basic.lean b/Mathlib/Algebra/Category/AlgebraCat/Basic.lean index 9c06d5e619d85..1053dac09d757 100644 --- a/Mathlib/Algebra/Category/AlgebraCat/Basic.lean +++ b/Mathlib/Algebra/Category/AlgebraCat/Basic.lean @@ -16,7 +16,6 @@ with the forgetful functors to `RingCat` and `ModuleCat`. We furthermore show th associating to a type the free `R`-algebra on that type is left adjoint to the forgetful functor. -/ - open CategoryTheory Limits universe v u @@ -25,6 +24,8 @@ variable (R : Type u) [CommRing R] /-- The category of R-algebras and their morphisms. -/ structure AlgebraCat where + private mk :: + /-- The underlying type. -/ carrier : Type v [isRing : Ring carrier] [isAlgebra : Algebra R carrier] @@ -46,22 +47,97 @@ instance : CoeSort (AlgebraCat R) (Type v) := attribute [coe] AlgebraCat.carrier +/-- The object in the category of R-algebras associated to a type equipped with the appropriate +typeclasses. This is the preferred way to construct a term of `AlgebraCat R`. -/ +abbrev of (X : Type v) [Ring X] [Algebra R X] : AlgebraCat.{v} R := + ⟨X⟩ + +lemma coe_of (X : Type v) [Ring X] [Algebra R X] : (of R X : Type v) = X := + rfl + +variable {R} in +/-- The type of morphisms in `AlgebraCat R`. -/ +@[ext] +structure Hom (A B : AlgebraCat.{v} R) where + private mk :: + /-- The underlying algebra map. -/ + hom : A →ₐ[R] B + instance : Category (AlgebraCat.{v} R) where - Hom A B := A →ₐ[R] B - id A := AlgHom.id R A - comp f g := g.comp f + Hom A B := Hom A B + id A := ⟨AlgHom.id R A⟩ + comp f g := ⟨g.hom.comp f.hom⟩ + +instance {M N : AlgebraCat.{v} R} : CoeFun (M ⟶ N) (fun _ ↦ M → N) where + coe f := f.hom -instance {M N : AlgebraCat.{v} R} : FunLike (M ⟶ N) M N := - AlgHom.funLike +@[simp] +lemma hom_id {A : AlgebraCat.{v} R} : (𝟙 A : A ⟶ A).hom = AlgHom.id R A := rfl + +/- Provided for rewriting. -/ +lemma id_apply (A : AlgebraCat.{v} R) (a : A) : + (𝟙 A : A ⟶ A) a = a := by simp + +@[simp] +lemma hom_comp {A B C : AlgebraCat.{v} R} (f : A ⟶ B) (g : B ⟶ C) : + (f ≫ g).hom = g.hom.comp f.hom := rfl + +/- Provided for rewriting. -/ +lemma comp_apply {A B C : AlgebraCat.{v} R} (f : A ⟶ B) (g : B ⟶ C) (a : A) : + (f ≫ g) a = g (f a) := by simp + +@[ext] +lemma hom_ext {A B : AlgebraCat.{v} R} {f g : A ⟶ B} (hf : f.hom = g.hom) : f = g := + Hom.ext hf + +/-- Typecheck an `AlgHom` as a morphism in `AlgebraCat R`. -/ +abbrev ofHom {R : Type u} [CommRing R] {X Y : Type v} [Ring X] [Algebra R X] [Ring Y] [Algebra R Y] + (f : X →ₐ[R] Y) : of R X ⟶ of R Y := + ⟨f⟩ -instance {M N : AlgebraCat.{v} R} : AlgHomClass (M ⟶ N) R M N := - AlgHom.algHomClass +lemma hom_ofHom {R : Type u} [CommRing R] {X Y : Type v} [Ring X] [Algebra R X] [Ring Y] + [Algebra R Y] (f : X →ₐ[R] Y) : (ofHom f).hom = f := rfl + +@[simp] +lemma ofHom_hom {A B : AlgebraCat.{v} R} (f : A ⟶ B) : + ofHom (Hom.hom f) = f := rfl + +@[simp] +lemma ofHom_id {X : Type v} [Ring X] [Algebra R X] : ofHom (AlgHom.id R X) = 𝟙 (of R X) := rfl + +@[simp] +lemma ofHom_comp {X Y Z : Type v} [Ring X] [Ring Y] [Ring Z] [Algebra R X] [Algebra R Y] + [Algebra R Z] (f : X →ₐ[R] Y) (g : Y →ₐ[R] Z) : + ofHom (g.comp f) = ofHom f ≫ ofHom g := + rfl + +lemma ofHom_apply {R : Type u} [CommRing R] {X Y : Type v} [Ring X] [Algebra R X] [Ring Y] + [Algebra R Y] (f : X →ₐ[R] Y) (x : X) : ofHom f x = f x := rfl + +@[simp] +lemma inv_hom_apply {A B : AlgebraCat.{v} R} (e : A ≅ B) (x : A) : e.inv (e.hom x) = x := by + rw [← comp_apply] + simp + +@[simp] +lemma hom_inv_apply {A B : AlgebraCat.{v} R} (e : A ≅ B) (x : B) : e.hom (e.inv x) = x := by + rw [← comp_apply] + simp + +instance : Inhabited (AlgebraCat R) := + ⟨of R R⟩ instance : ConcreteCategory.{v} (AlgebraCat.{v} R) where forget := { obj := fun R => R - map := fun f => f.toFun } - forget_faithful := ⟨fun h => AlgHom.ext (by intros x; dsimp at h; rw [h])⟩ + map := fun f => f.hom } + forget_faithful := ⟨fun h => by ext x; simpa using congrFun h x⟩ + +lemma forget_obj {A : AlgebraCat.{v} R} : (forget (AlgebraCat.{v} R)).obj A = A := rfl + +lemma forget_map {A B : AlgebraCat.{v} R} (f : A ⟶ B) : + (forget (AlgebraCat.{v} R)).map f = f := + rfl instance {S : AlgebraCat.{v} R} : Ring ((forget (AlgebraCat R)).obj S) := (inferInstance : Ring S.carrier) @@ -72,12 +148,12 @@ instance {S : AlgebraCat.{v} R} : Algebra R ((forget (AlgebraCat R)).obj S) := instance hasForgetToRing : HasForget₂ (AlgebraCat.{v} R) RingCat.{v} where forget₂ := { obj := fun A => RingCat.of A - map := fun f => RingCat.ofHom f.toRingHom } + map := fun f => RingCat.ofHom f.hom.toRingHom } instance hasForgetToModule : HasForget₂ (AlgebraCat.{v} R) (ModuleCat.{v} R) where forget₂ := { obj := fun M => ModuleCat.of R M - map := fun f => ModuleCat.asHom f.toLinearMap } + map := fun f => ModuleCat.asHom f.hom.toLinearMap } @[simp] lemma forget₂_module_obj (X : AlgebraCat.{v} R) : @@ -86,33 +162,10 @@ lemma forget₂_module_obj (X : AlgebraCat.{v} R) : @[simp] lemma forget₂_module_map {X Y : AlgebraCat.{v} R} (f : X ⟶ Y) : - (forget₂ (AlgebraCat.{v} R) (ModuleCat.{v} R)).map f = ModuleCat.asHom f.toLinearMap := - rfl - -/-- The object in the category of R-algebras associated to a type equipped with the appropriate -typeclasses. -/ -def of (X : Type v) [Ring X] [Algebra R X] : AlgebraCat.{v} R := - ⟨X⟩ - -/-- Typecheck a `AlgHom` as a morphism in `AlgebraCat R`. -/ -def ofHom {R : Type u} [CommRing R] {X Y : Type v} [Ring X] [Algebra R X] [Ring Y] [Algebra R Y] - (f : X →ₐ[R] Y) : of R X ⟶ of R Y := - f - -@[simp] -theorem ofHom_apply {R : Type u} [CommRing R] {X Y : Type v} [Ring X] [Algebra R X] [Ring Y] - [Algebra R Y] (f : X →ₐ[R] Y) (x : X) : ofHom f x = f x := + (forget₂ (AlgebraCat.{v} R) (ModuleCat.{v} R)).map f = ModuleCat.asHom f.hom.toLinearMap := rfl -instance : Inhabited (AlgebraCat R) := - ⟨of R R⟩ - -@[simp] -theorem coe_of (X : Type u) [Ring X] [Algebra R X] : (of R X : Type u) = X := - rfl - -variable {R} - +variable {R} in /-- Forgetting to the underlying type and then building the bundled object returns the original algebra. -/ @[simps] @@ -120,58 +173,20 @@ def ofSelfIso (M : AlgebraCat.{v} R) : AlgebraCat.of R M ≅ M where hom := 𝟙 M inv := 𝟙 M -variable {M N U : ModuleCat.{v} R} - -@[simp] -theorem id_apply (m : M) : (𝟙 M : M → M) m = m := - rfl - -@[simp] -theorem coe_comp (f : M ⟶ N) (g : N ⟶ U) : (f ≫ g : M → U) = g ∘ f := - rfl - -variable (R) - /-- The "free algebra" functor, sending a type `S` to the free algebra on `S`. -/ -@[simps!] +@[simps! obj map] def free : Type u ⥤ AlgebraCat.{u} R where - obj S := - { carrier := FreeAlgebra R S - isRing := Algebra.semiringToRing R } - map f := FreeAlgebra.lift _ <| FreeAlgebra.ι _ ∘ f - -- Porting note (https://github.com/leanprover-community/mathlib4/pull/11041): `apply FreeAlgebra.hom_ext` was `ext1`. - map_id := by intro X; apply FreeAlgebra.hom_ext; simp only [FreeAlgebra.ι_comp_lift]; rfl - map_comp := by - -- Porting note (https://github.com/leanprover-community/mathlib4/pull/11041): `apply FreeAlgebra.hom_ext` was `ext1`. - intros; apply FreeAlgebra.hom_ext; simp only [FreeAlgebra.ι_comp_lift]; ext1 - -- Porting node: this ↓ `erw` used to be handled by the `simp` below it - erw [CategoryTheory.coe_comp] - simp only [CategoryTheory.coe_comp, Function.comp_apply, types_comp_apply] - -- Porting node: this ↓ `erw` and `rfl` used to be handled by the `simp` above - erw [FreeAlgebra.lift_ι_apply, FreeAlgebra.lift_ι_apply] - rfl + obj S := of R (FreeAlgebra R S) + map f := ofHom <| FreeAlgebra.lift _ <| FreeAlgebra.ι _ ∘ f /-- The free/forget adjunction for `R`-algebras. -/ def adj : free.{u} R ⊣ forget (AlgebraCat.{u} R) := Adjunction.mkOfHomEquiv - { homEquiv := fun _ _ => (FreeAlgebra.lift _).symm - -- Relying on `obviously` to fill out these proofs is very slow :( - homEquiv_naturality_left_symm := by - -- Porting note (https://github.com/leanprover-community/mathlib4/pull/11041): `apply FreeAlgebra.hom_ext` was `ext1`. - intros; apply FreeAlgebra.hom_ext; simp only [FreeAlgebra.ι_comp_lift]; ext1 - simp only [free_map, Equiv.symm_symm, FreeAlgebra.lift_ι_apply, CategoryTheory.coe_comp, - Function.comp_apply, types_comp_apply] - -- Porting node: this ↓ `erw` and `rfl` used to be handled by the `simp` above - erw [FreeAlgebra.lift_ι_apply, CategoryTheory.comp_apply, FreeAlgebra.lift_ι_apply, - Function.comp_apply, FreeAlgebra.lift_ι_apply] - rfl - homEquiv_naturality_right := by - intros; ext - simp only [CategoryTheory.coe_comp, Function.comp_apply, - FreeAlgebra.lift_symm_apply, types_comp_apply] - -- Porting note: proof used to be done after this ↑ `simp`; added ↓ two lines - erw [FreeAlgebra.lift_symm_apply, FreeAlgebra.lift_symm_apply] - rfl } + { homEquiv := fun _ _ => + { toFun := fun f ↦ (FreeAlgebra.lift _).symm f.hom + invFun := fun f ↦ ofHom <| (FreeAlgebra.lift _) f + left_inv := fun f ↦ by aesop + right_inv := fun f ↦ by simp [forget_obj, forget_map] } } instance : (forget (AlgebraCat.{u} R)).IsRightAdjoint := (adj R).isRightAdjoint @@ -184,31 +199,19 @@ variable {X₁ X₂ : Type u} @[simps] def AlgEquiv.toAlgebraIso {g₁ : Ring X₁} {g₂ : Ring X₂} {m₁ : Algebra R X₁} {m₂ : Algebra R X₂} (e : X₁ ≃ₐ[R] X₂) : AlgebraCat.of R X₁ ≅ AlgebraCat.of R X₂ where - hom := (e : X₁ →ₐ[R] X₂) - inv := (e.symm : X₂ →ₐ[R] X₁) - hom_inv_id := by ext x; exact e.left_inv x - inv_hom_id := by ext x; exact e.right_inv x + hom := AlgebraCat.ofHom (e : X₁ →ₐ[R] X₂) + inv := AlgebraCat.ofHom (e.symm : X₂ →ₐ[R] X₁) namespace CategoryTheory.Iso /-- Build a `AlgEquiv` from an isomorphism in the category `AlgebraCat R`. -/ @[simps] def toAlgEquiv {X Y : AlgebraCat R} (i : X ≅ Y) : X ≃ₐ[R] Y := - { i.hom with + { i.hom.hom with toFun := i.hom invFun := i.inv - left_inv := fun x => by - -- Porting note: was `by tidy` - change (i.hom ≫ i.inv) x = x - simp only [hom_inv_id] - -- This used to be `rw`, but we need `erw` after https://github.com/leanprover/lean4/pull/2644 - erw [id_apply] - right_inv := fun x => by - -- Porting note: was `by tidy` - change (i.inv ≫ i.hom) x = x - simp only [inv_hom_id] - -- This used to be `rw`, but we need `erw` after https://github.com/leanprover/lean4/pull/2644 - erw [id_apply] } + left_inv := fun x ↦ by simp + right_inv := fun x ↦ by simp } end CategoryTheory.Iso @@ -223,18 +226,5 @@ def algEquivIsoAlgebraIso {X Y : Type u} [Ring X] [Ring Y] [Algebra R X] [Algebr instance AlgebraCat.forget_reflects_isos : (forget (AlgebraCat.{u} R)).ReflectsIsomorphisms where reflects {X Y} f _ := by let i := asIso ((forget (AlgebraCat.{u} R)).map f) - let e : X ≃ₐ[R] Y := { f, i.toEquiv with } + let e : X ≃ₐ[R] Y := { f.hom, i.toEquiv with } exact e.toAlgebraIso.isIso_hom - -/-! -`@[simp]` lemmas for `AlgHom.comp` and categorical identities. --/ - -@[simp] theorem AlgHom.comp_id_algebraCat - {R} [CommRing R] {G : AlgebraCat.{u} R} {H : Type u} [Ring H] [Algebra R H] (f : G →ₐ[R] H) : - f.comp (𝟙 G) = f := - Category.id_comp (AlgebraCat.ofHom f) -@[simp] theorem AlgHom.id_algebraCat_comp - {R} [CommRing R] {G : Type u} [Ring G] [Algebra R G] {H : AlgebraCat.{u} R} (f : G →ₐ[R] H) : - AlgHom.comp (𝟙 H) f = f := - Category.comp_id (AlgebraCat.ofHom f) diff --git a/Mathlib/Algebra/Category/AlgebraCat/Limits.lean b/Mathlib/Algebra/Category/AlgebraCat/Limits.lean index 94f312fee5673..ea39419a2442e 100644 --- a/Mathlib/Algebra/Category/AlgebraCat/Limits.lean +++ b/Mathlib/Algebra/Category/AlgebraCat/Limits.lean @@ -40,7 +40,7 @@ instance algebraObj (j) : def sectionsSubalgebra : Subalgebra R (∀ j, F.obj j) := { SemiRingCat.sectionsSubsemiring (F ⋙ forget₂ (AlgebraCat R) RingCat.{w} ⋙ forget₂ RingCat SemiRingCat.{w}) with - algebraMap_mem' := fun r _ _ f => (F.map f).commutes r } + algebraMap_mem' := fun r _ _ f => (F.map f).hom.commutes r } instance (F : J ⥤ AlgebraCat.{w} R) : Ring (F ⋙ forget _).sections := inferInstanceAs <| Ring (sectionsSubalgebra F) @@ -88,9 +88,10 @@ namespace HasLimits def limitCone : Cone F where pt := AlgebraCat.of R (Types.Small.limitCone (F ⋙ forget _)).pt π := - { app := limitπAlgHom F - naturality := fun _ _ f => - AlgHom.coe_fn_injective ((Types.Small.limitCone (F ⋙ forget _)).π.naturality f) } + { app := fun j ↦ ofHom <| limitπAlgHom F j + naturality := fun _ _ f => by + ext : 1 + exact AlgHom.coe_fn_injective ((Types.Small.limitCone (F ⋙ forget _)).π.naturality f) } /-- Witness that the limit cone in `AlgebraCat R` is a limit cone. (Internal use only; use the limits API.) @@ -101,41 +102,36 @@ def limitConeIsLimit : IsLimit (limitCone.{v, w} F) := by -- Porting note: in mathlib3 the function term -- `fun v => ⟨fun j => ((forget (AlgebraCat R)).mapCone s).π.app j v` -- was provided by unification, and the last argument `(fun s => _)` was `(fun s => rfl)`. - (fun s => { toFun := _, map_one' := ?_, map_mul' := ?_, map_zero' := ?_, map_add' := ?_, - commutes' := ?_ }) + (fun s => ofHom + { toFun := _, map_one' := ?_, map_mul' := ?_, map_zero' := ?_, map_add' := ?_, + commutes' := ?_ }) (fun s => rfl) · congr ext j - simp only [Functor.comp_obj, Functor.mapCone_pt, Functor.mapCone_π_app, - forget_map_eq_coe] - rw [map_one] - rfl + simp only [Functor.mapCone_π_app, forget_map, map_one, Pi.one_apply] · intro x y - simp only [Functor.comp_obj, Functor.mapCone_pt, Functor.mapCone_π_app] - rw [← equivShrink_mul] - apply congrArg ext j - simp only [Functor.comp_obj, Functor.mapCone_pt, Functor.mapCone_π_app, - forget_map_eq_coe, map_mul] - rfl - · simp only [Functor.mapCone_π_app, forget_map_eq_coe] - congr - funext j - simp only [map_zero, Pi.zero_apply] + simp only [Functor.comp_obj, forget_obj, Equiv.toFun_as_coe, Functor.mapCone_pt, + Functor.mapCone_π_app, forget_map, Equiv.symm_apply_apply, + Types.Small.limitCone_pt, equivShrink_symm_mul] + apply map_mul + · ext j + simp only [Functor.comp_obj, forget_obj, Equiv.toFun_as_coe, Functor.mapCone_pt, + Functor.mapCone_π_app, forget_map, Equiv.symm_apply_apply, + equivShrink_symm_zero] + apply map_zero · intro x y - simp only [Functor.mapCone_π_app] - rw [← equivShrink_add] - apply congrArg ext j - simp only [forget_map_eq_coe, map_add] - rfl + simp only [Functor.comp_obj, forget_obj, Equiv.toFun_as_coe, Functor.mapCone_pt, + Functor.mapCone_π_app, forget_map, Equiv.symm_apply_apply, + Types.Small.limitCone_pt, equivShrink_symm_add] + apply map_add · intro r - simp only [← Shrink.algEquiv_symm_apply _ R, limitCone, Equiv.algebraMap_def, - Equiv.symm_symm] + simp only [← Shrink.algEquiv_symm_apply _ R, limitCone, Equiv.algebraMap_def, Equiv.symm_symm] apply congrArg apply Subtype.ext ext j - exact (s.π.app j).commutes r + exact (s.π.app j).hom.commutes r end HasLimits diff --git a/Mathlib/Algebra/Category/AlgebraCat/Monoidal.lean b/Mathlib/Algebra/Category/AlgebraCat/Monoidal.lean index ac5df5ca0f2dd..fa16a8aac4bcd 100644 --- a/Mathlib/Algebra/Category/AlgebraCat/Monoidal.lean +++ b/Mathlib/Algebra/Category/AlgebraCat/Monoidal.lean @@ -37,7 +37,7 @@ noncomputable abbrev tensorObj (X Y : AlgebraCat.{u} R) : AlgebraCat.{u} R := `AlgebraCat.instMonoidalCategory`. -/ noncomputable abbrev tensorHom {W X Y Z : AlgebraCat.{u} R} (f : W ⟶ X) (g : Y ⟶ Z) : tensorObj W Y ⟶ tensorObj X Z := - Algebra.TensorProduct.map f g + ofHom <| Algebra.TensorProduct.map f.hom g.hom open MonoidalCategory diff --git a/Mathlib/Algebra/Category/BialgebraCat/Basic.lean b/Mathlib/Algebra/Category/BialgebraCat/Basic.lean index fb1f40ffe1018..59fe5b8fefba2 100644 --- a/Mathlib/Algebra/Category/BialgebraCat/Basic.lean +++ b/Mathlib/Algebra/Category/BialgebraCat/Basic.lean @@ -103,7 +103,7 @@ instance concreteCategory : ConcreteCategory.{v} (BialgebraCat.{v} R) where instance hasForgetToAlgebra : HasForget₂ (BialgebraCat R) (AlgebraCat R) where forget₂ := { obj := fun X => AlgebraCat.of R X - map := fun {X Y} f => (f.toBialgHom : X →ₐ[R] Y) } + map := fun {X Y} f => AlgebraCat.ofHom f.toBialgHom } @[simp] theorem forget₂_algebra_obj (X : BialgebraCat R) : @@ -112,7 +112,7 @@ theorem forget₂_algebra_obj (X : BialgebraCat R) : @[simp] theorem forget₂_algebra_map (X Y : BialgebraCat R) (f : X ⟶ Y) : - (forget₂ (BialgebraCat R) (AlgebraCat R)).map f = (f.toBialgHom : X →ₐ[R] Y) := + (forget₂ (BialgebraCat R) (AlgebraCat R)).map f = AlgebraCat.ofHom f.toBialgHom := rfl instance hasForgetToCoalgebra : HasForget₂ (BialgebraCat R) (CoalgebraCat R) where diff --git a/Mathlib/Algebra/Category/Grp/FiniteGrp.lean b/Mathlib/Algebra/Category/Grp/FiniteGrp.lean index b1f4d7ead61ee..ac01e3ac8ce3c 100644 --- a/Mathlib/Algebra/Category/Grp/FiniteGrp.lean +++ b/Mathlib/Algebra/Category/Grp/FiniteGrp.lean @@ -3,6 +3,7 @@ Copyright (c) 2024 Jujian Zhang. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jujian Zhang, Nailin Guan, Yuyang Zhao -/ +import Mathlib.Data.Finite.Defs import Mathlib.Algebra.Category.Grp.Basic /-! diff --git a/Mathlib/Algebra/Central/Defs.lean b/Mathlib/Algebra/Central/Defs.lean index c88a10b8b3aba..363464e22abef 100644 --- a/Mathlib/Algebra/Central/Defs.lean +++ b/Mathlib/Algebra/Central/Defs.lean @@ -19,7 +19,7 @@ is a (not necessarily commutative) `K`-algebra. ## Implementation notes We require the `K`-center of `D` to be smaller than or equal to the smallest subalgebra so that when -we prove something is central, there we don't need to prove `⊥ ≤ center K D` even though this +we prove something is central, we don't need to prove `⊥ ≤ center K D` even though this direction is trivial. ### Central Simple Algebras @@ -34,11 +34,11 @@ but an instance of `[Algebra.IsCentralSimple K D]` would not imply `[IsSimpleRin synthesization orders (`K` cannot be inferred). Thus, to obtain a central simple `K`-algebra `D`, one should use `Algebra.IsCentral K D` and `IsSimpleRing D` separately. -Note that the predicate `Albgera.IsCentral K D` and `IsSimpleRing D` makes sense just for `K` a +Note that the predicate `Algebra.IsCentral K D` and `IsSimpleRing D` makes sense just for `K` a `CommRing` but it doesn't give the right definition for central simple algebra; for a commutative ring base, one should use the theory of Azumaya algebras. In fact ideals of `K` immediately give rise to nontrivial quotients of `D` so there are no central simple algebras in this case according -to our definition, if K is not a field. +to our definition, if `K` is not a field. The theory of central simple algebras really is a theory over fields. Thus to declare a central simple algebra, one should use the following: diff --git a/Mathlib/Algebra/CharP/Defs.lean b/Mathlib/Algebra/CharP/Defs.lean index eb523f7e90fac..093c600a4a310 100644 --- a/Mathlib/Algebra/CharP/Defs.lean +++ b/Mathlib/Algebra/CharP/Defs.lean @@ -232,7 +232,7 @@ section NoZeroDivisors variable [NoZeroDivisors R] lemma char_is_prime_of_two_le (p : ℕ) [CharP R p] (hp : 2 ≤ p) : Nat.Prime p := - suffices ∀ (d) (_ : d ∣ p), d = 1 ∨ d = p from Nat.prime_def_lt''.mpr ⟨hp, this⟩ + suffices ∀ (d) (_ : d ∣ p), d = 1 ∨ d = p from Nat.prime_def.mpr ⟨hp, this⟩ fun (d : ℕ) (hdvd : ∃ e, p = d * e) => let ⟨e, hmul⟩ := hdvd have : (p : R) = 0 := (cast_eq_zero_iff R p p).mpr (dvd_refl p) diff --git a/Mathlib/Algebra/CharP/LinearMaps.lean b/Mathlib/Algebra/CharP/LinearMaps.lean new file mode 100644 index 0000000000000..36f3baf18a80d --- /dev/null +++ b/Mathlib/Algebra/CharP/LinearMaps.lean @@ -0,0 +1,60 @@ +/- +Copyright (c) 2024 Wanyi He. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Wanyi He, Huanyu Zheng +-/ +import Mathlib.Algebra.CharP.Algebra +/-! +# Characteristic of the ring of linear Maps + +This file contains properties of the characteristic of the ring of linear maps. +The characteristic of the ring of linear maps is determined by its base ring. + +## Main Results + +- `CharP_if` : For a commutative semiring `R` and a `R`-module `M`, + the characteristic of `R` is equal to the characteristic of the `R`-linear + endomorphisms of `M` when `M` contains an element `x` such that + `r • x = 0` implies `r = 0`. + +## Notations + +- `R` is a commutative semiring +- `M` is a `R`-module + +## Implementation Notes + +One can also deduce similar result via `charP_of_injective_ringHom` and + `R → (M →ₗ[R] M) : r ↦ (fun (x : M) ↦ r • x)`. But this will require stronger condition + compared to `CharP_if`. + +-/ + +namespace Module + +variable {R M : Type*} [CommSemiring R] [AddCommMonoid M] [Module R M] + +/-- For a commutative semiring `R` and a `R`-module `M`, if `M` contains an + element `x` such that `r • x = 0` implies `r = 0` (finding such element usually + depends on specific `•`), then the characteristic of `R` is equal to the + characteristic of the `R`-linear endomorphisms of `M`.-/ +theorem charP_end {p : ℕ} [hchar : CharP R p] + (hreduction : ∃ x : M, ∀ r : R, r • x = 0 → r = 0) : CharP (M →ₗ[R] M) p where + cast_eq_zero_iff' n := by + have exact : (n : M →ₗ[R] M) = (n : R) • 1 := by + simp only [Nat.cast_smul_eq_nsmul, nsmul_eq_mul, mul_one] + rw [exact, LinearMap.ext_iff, ← hchar.1] + exact ⟨fun h ↦ Exists.casesOn hreduction fun x hx ↦ hx n (h x), + fun h ↦ (congrArg (fun t ↦ ∀ x, t • x = 0) h).mpr fun x ↦ zero_smul R x⟩ + +end Module + +/-- For a division ring `D` with center `k`, the ring of `k`-linear endomorphisms + of `D` has the same characteristic as `D`-/ +instance {D : Type*} [DivisionRing D] {p : ℕ} [CharP D p] : + CharP (D →ₗ[(Subring.center D)] D) p := + charP_of_injective_ringHom (Algebra.lmul (Subring.center D) D).toRingHom.injective p + +instance {D : Type*} [DivisionRing D] {p : ℕ} [ExpChar D p] : + ExpChar (D →ₗ[Subring.center D] D) p := + expChar_of_injective_ringHom (Algebra.lmul (Subring.center D) D).toRingHom.injective p diff --git a/Mathlib/Algebra/CharP/Subring.lean b/Mathlib/Algebra/CharP/Subring.lean index e6d5faa37044a..23ed075efbeb1 100644 --- a/Mathlib/Algebra/CharP/Subring.lean +++ b/Mathlib/Algebra/CharP/Subring.lean @@ -3,8 +3,7 @@ Copyright (c) 2020 Kenny Lau. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kenny Lau -/ -import Mathlib.Algebra.CharP.Defs -import Mathlib.Algebra.Ring.Subring.Defs +import Mathlib.Algebra.CharP.Algebra /-! # Characteristic of subrings @@ -33,4 +32,18 @@ instance subring (R : Type u) [Ring R] (p : ℕ) [CharP R p] (S : Subring R) : C instance subring' (R : Type u) [CommRing R] (p : ℕ) [CharP R p] (S : Subring R) : CharP S p := CharP.subring R p S +/-- The characteristic of a division ring is equal to the characteristic + of its center-/ +theorem charP_center_iff {R : Type u} [Ring R] {p : ℕ} : + CharP (Subring.center R) p ↔ CharP R p := + (algebraMap (Subring.center R) R).charP_iff Subtype.val_injective p + end CharP + +namespace ExpChar + +theorem expChar_center_iff {R : Type u} [Ring R] {p : ℕ} : + ExpChar (Subring.center R) p ↔ ExpChar R p := + (algebraMap (Subring.center R) R).expChar_iff Subtype.val_injective p + +end ExpChar diff --git a/Mathlib/Algebra/ContinuedFractions/Computation/Basic.lean b/Mathlib/Algebra/ContinuedFractions/Computation/Basic.lean index 44e1c3d71de18..f269dd69e8670 100644 --- a/Mathlib/Algebra/ContinuedFractions/Computation/Basic.lean +++ b/Mathlib/Algebra/ContinuedFractions/Computation/Basic.lean @@ -58,6 +58,7 @@ with a head term (`seq1`) is then transformed to a generalized continued fractio numerics, number theory, approximations, fractions -/ +assert_not_exists Finset namespace GenContFract diff --git a/Mathlib/Algebra/ContinuedFractions/Computation/Translations.lean b/Mathlib/Algebra/ContinuedFractions/Computation/Translations.lean index d732ff25b6a7a..0b971d4795163 100644 --- a/Mathlib/Algebra/ContinuedFractions/Computation/Translations.lean +++ b/Mathlib/Algebra/ContinuedFractions/Computation/Translations.lean @@ -37,6 +37,7 @@ of three sections: parts. -/ +assert_not_exists Finset namespace GenContFract diff --git a/Mathlib/Algebra/DirectSum/Basic.lean b/Mathlib/Algebra/DirectSum/Basic.lean index 4aab3891bf560..50045a6c1ba5b 100644 --- a/Mathlib/Algebra/DirectSum/Basic.lean +++ b/Mathlib/Algebra/DirectSum/Basic.lean @@ -367,8 +367,8 @@ theorem coe_of_apply {M S : Type*} [DecidableEq ι] [AddCommMonoid M] [SetLike S `M` is said to be internal if the canonical map `(⨁ i, A i) →+ M` is bijective. For the alternate statement in terms of independence and spanning, see -`DirectSum.subgroup_isInternal_iff_independent_and_supr_eq_top` and -`DirectSum.isInternal_submodule_iff_independent_and_iSup_eq_top`. -/ +`DirectSum.subgroup_isInternal_iff_iSupIndep_and_supr_eq_top` and +`DirectSum.isInternal_submodule_iff_iSupIndep_and_iSup_eq_top`. -/ def IsInternal {M S : Type*} [DecidableEq ι] [AddCommMonoid M] [SetLike S M] [AddSubmonoidClass S M] (A : ι → S) : Prop := Function.Bijective (DirectSum.coeAddMonoidHom A) diff --git a/Mathlib/Algebra/DirectSum/Internal.lean b/Mathlib/Algebra/DirectSum/Internal.lean index 34fbe957a6174..a75722faa88dc 100644 --- a/Mathlib/Algebra/DirectSum/Internal.lean +++ b/Mathlib/Algebra/DirectSum/Internal.lean @@ -28,7 +28,7 @@ to represent this case, `(h : DirectSum.IsInternal A) [SetLike.GradedMonoid A]` needed. In the future there will likely be a data-carrying, constructive, typeclass version of `DirectSum.IsInternal` for providing an explicit decomposition function. -When `CompleteLattice.Independent (Set.range A)` (a weaker condition than +When `iSupIndep (Set.range A)` (a weaker condition than `DirectSum.IsInternal A`), these provide a grading of `⨆ i, A i`, and the mapping `⨁ i, A i →+ ⨆ i, A i` can be obtained as `DirectSum.toAddMonoid (fun i ↦ AddSubmonoid.inclusion <| le_iSup A i)`. diff --git a/Mathlib/Algebra/DirectSum/LinearMap.lean b/Mathlib/Algebra/DirectSum/LinearMap.lean index 25ffc82193de4..ff8f8b3d653a4 100644 --- a/Mathlib/Algebra/DirectSum/LinearMap.lean +++ b/Mathlib/Algebra/DirectSum/LinearMap.lean @@ -82,8 +82,8 @@ lemma trace_eq_zero_of_mapsTo_ne (h : IsInternal N) [IsNoetherian R M] (σ : ι → ι) (hσ : ∀ i, σ i ≠ i) {f : Module.End R M} (hf : ∀ i, MapsTo f (N i) (N <| σ i)) : trace R M f = 0 := by - have hN : {i | N i ≠ ⊥}.Finite := CompleteLattice.WellFoundedGT.finite_ne_bot_of_independent - h.submodule_independent + have hN : {i | N i ≠ ⊥}.Finite := WellFoundedGT.finite_ne_bot_of_iSupIndep + h.submodule_iSupIndep 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) @@ -109,10 +109,10 @@ lemma trace_comp_eq_zero_of_commute_of_trace_restrict_eq_zero (f.mapsTo_maxGenEigenspace_of_comm rfl μ) suffices ∀ μ, trace R _ ((g ∘ₗ f).restrict (hfg μ)) = 0 by classical - have hds := DirectSum.isInternal_submodule_of_independent_of_iSup_eq_top + have hds := DirectSum.isInternal_submodule_of_iSupIndep_of_iSup_eq_top f.independent_maxGenEigenspace hf have h_fin : {μ | f.maxGenEigenspace μ ≠ ⊥}.Finite := - CompleteLattice.WellFoundedGT.finite_ne_bot_of_independent f.independent_maxGenEigenspace + WellFoundedGT.finite_ne_bot_of_iSupIndep f.independent_maxGenEigenspace simp [trace_eq_sum_trace_restrict' hds h_fin hfg, this] intro μ replace h_comm : Commute (g.restrict (f.mapsTo_maxGenEigenspace_of_comm h_comm μ)) @@ -136,14 +136,14 @@ Note that it is important the statement gives the user definitional control over _type_ of the term `trace R p (f.restrict hp')` depends on `p`. -/ lemma trace_eq_sum_trace_restrict_of_eq_biSup [∀ i, Module.Finite R (N i)] [∀ i, Module.Free R (N i)] - (s : Finset ι) (h : CompleteLattice.Independent <| fun i : s ↦ N i) + (s : Finset ι) (h : iSupIndep <| fun i : s ↦ N i) {f : Module.End R M} (hf : ∀ i, MapsTo f (N i) (N i)) (p : Submodule R M) (hp : p = ⨆ i ∈ s, N i) (hp' : MapsTo f p p := hp ▸ mapsTo_biSup_of_mapsTo (s : Set ι) hf) : trace R p (f.restrict hp') = ∑ i ∈ s, trace R (N i) (f.restrict (hf i)) := by classical let N' : s → Submodule R p := fun i ↦ (N i).comap p.subtype - replace h : IsInternal N' := hp ▸ isInternal_biSup_submodule_of_independent (s : Set ι) h + replace h : IsInternal N' := hp ▸ isInternal_biSup_submodule_of_iSupIndep (s : Set ι) h have hf' : ∀ i, MapsTo (restrict f hp') (N' i) (N' i) := fun i x hx' ↦ by simpa using hf i hx' let e : (i : s) → N' i ≃ₗ[R] N i := fun ⟨i, hi⟩ ↦ (N i).comapSubtypeEquivOfLe (hp ▸ le_biSup N hi) have _i1 : ∀ i, Module.Finite R (N' i) := fun i ↦ Module.Finite.equiv (e i).symm diff --git a/Mathlib/Algebra/DirectSum/Module.lean b/Mathlib/Algebra/DirectSum/Module.lean index 299c5d4caad54..dba8c5158d5d0 100644 --- a/Mathlib/Algebra/DirectSum/Module.lean +++ b/Mathlib/Algebra/DirectSum/Module.lean @@ -319,8 +319,11 @@ theorem IsInternal.submodule_iSup_eq_top (h : IsInternal A) : iSup A = ⊤ := by exact Function.Bijective.surjective h /-- If a direct sum of submodules is internal then the submodules are independent. -/ -theorem IsInternal.submodule_independent (h : IsInternal A) : CompleteLattice.Independent A := - CompleteLattice.independent_of_dfinsupp_lsum_injective _ h.injective +theorem IsInternal.submodule_iSupIndep (h : IsInternal A) : iSupIndep A := + iSupIndep_of_dfinsupp_lsum_injective _ h.injective + +@[deprecated (since := "2024-11-24")] +alias IsInternal.submodule_independent := IsInternal.submodule_iSupIndep /-- Given an internal direct sum decomposition of a module `M`, and a basis for each of the components of the direct sum, the disjoint union of these bases is a basis for `M`. -/ @@ -374,7 +377,7 @@ the two submodules are complementary. Over a `Ring R`, this is true as an iff, a `DirectSum.isInternal_submodule_iff_isCompl`. -/ theorem IsInternal.isCompl {A : ι → Submodule R M} {i j : ι} (hij : i ≠ j) (h : (Set.univ : Set ι) = {i, j}) (hi : IsInternal A) : IsCompl (A i) (A j) := - ⟨hi.submodule_independent.pairwiseDisjoint hij, + ⟨hi.submodule_iSupIndep.pairwiseDisjoint hij, codisjoint_iff.mpr <| Eq.symm <| hi.submodule_iSup_eq_top.symm.trans <| by rw [← sSup_pair, iSup, ← Set.image_univ, h, Set.image_insert_eq, Set.image_singleton]⟩ @@ -387,60 +390,76 @@ variable {ι : Type v} [dec_ι : DecidableEq ι] variable {M : Type*} [AddCommGroup M] [Module R M] /-- Note that this is not generally true for `[Semiring R]`; see -`CompleteLattice.Independent.dfinsupp_lsum_injective` for details. -/ -theorem isInternal_submodule_of_independent_of_iSup_eq_top {A : ι → Submodule R M} - (hi : CompleteLattice.Independent A) (hs : iSup A = ⊤) : IsInternal A := +`iSupIndep.dfinsupp_lsum_injective` for details. -/ +theorem isInternal_submodule_of_iSupIndep_of_iSup_eq_top {A : ι → Submodule R M} + (hi : iSupIndep A) (hs : iSup A = ⊤) : IsInternal A := ⟨hi.dfinsupp_lsum_injective, -- Note: https://github.com/leanprover-community/mathlib4/pull/8386 had to specify value of `f` (LinearMap.range_eq_top (f := DFinsupp.lsum _ _)).1 <| (Submodule.iSup_eq_range_dfinsupp_lsum _).symm.trans hs⟩ -/-- `iff` version of `DirectSum.isInternal_submodule_of_independent_of_iSup_eq_top`, -`DirectSum.IsInternal.submodule_independent`, and `DirectSum.IsInternal.submodule_iSup_eq_top`. -/ -theorem isInternal_submodule_iff_independent_and_iSup_eq_top (A : ι → Submodule R M) : - IsInternal A ↔ CompleteLattice.Independent A ∧ iSup A = ⊤ := - ⟨fun i ↦ ⟨i.submodule_independent, i.submodule_iSup_eq_top⟩, - And.rec isInternal_submodule_of_independent_of_iSup_eq_top⟩ +@[deprecated (since := "2024-11-24")] +alias isInternal_submodule_of_independent_of_iSup_eq_top := + isInternal_submodule_of_iSupIndep_of_iSup_eq_top + +/-- `iff` version of `DirectSum.isInternal_submodule_of_iSupIndep_of_iSup_eq_top`, +`DirectSum.IsInternal.iSupIndep`, and `DirectSum.IsInternal.submodule_iSup_eq_top`. -/ +theorem isInternal_submodule_iff_iSupIndep_and_iSup_eq_top (A : ι → Submodule R M) : + IsInternal A ↔ iSupIndep A ∧ iSup A = ⊤ := + ⟨fun i ↦ ⟨i.submodule_iSupIndep, i.submodule_iSup_eq_top⟩, + And.rec isInternal_submodule_of_iSupIndep_of_iSup_eq_top⟩ + +@[deprecated (since := "2024-11-24")] +alias isInternal_submodule_iff_independent_and_iSup_eq_top := + isInternal_submodule_iff_iSupIndep_and_iSup_eq_top /-- If a collection of submodules has just two indices, `i` and `j`, then `DirectSum.IsInternal` is equivalent to `isCompl`. -/ theorem isInternal_submodule_iff_isCompl (A : ι → Submodule R M) {i j : ι} (hij : i ≠ j) (h : (Set.univ : Set ι) = {i, j}) : IsInternal A ↔ IsCompl (A i) (A j) := by have : ∀ k, k = i ∨ k = j := fun k ↦ by simpa using Set.ext_iff.mp h k - rw [isInternal_submodule_iff_independent_and_iSup_eq_top, iSup, ← Set.image_univ, h, - Set.image_insert_eq, Set.image_singleton, sSup_pair, CompleteLattice.independent_pair hij this] + rw [isInternal_submodule_iff_iSupIndep_and_iSup_eq_top, iSup, ← Set.image_univ, h, + Set.image_insert_eq, Set.image_singleton, sSup_pair, iSupIndep_pair hij this] exact ⟨fun ⟨hd, ht⟩ ↦ ⟨hd, codisjoint_iff.mpr ht⟩, fun ⟨hd, ht⟩ ↦ ⟨hd, ht.eq_top⟩⟩ @[simp] theorem isInternal_ne_bot_iff {A : ι → Submodule R M} : IsInternal (fun i : {i // A i ≠ ⊥} ↦ A i) ↔ IsInternal A := by - simp only [isInternal_submodule_iff_independent_and_iSup_eq_top] - exact Iff.and CompleteLattice.independent_ne_bot_iff_independent <| by simp + simp [isInternal_submodule_iff_iSupIndep_and_iSup_eq_top] -lemma isInternal_biSup_submodule_of_independent {A : ι → Submodule R M} (s : Set ι) - (h : CompleteLattice.Independent <| fun i : s ↦ A i) : +lemma isInternal_biSup_submodule_of_iSupIndep {A : ι → Submodule R M} (s : Set ι) + (h : iSupIndep <| fun i : s ↦ A i) : IsInternal <| fun (i : s) ↦ (A i).comap (⨆ i ∈ s, A i).subtype := by - refine (isInternal_submodule_iff_independent_and_iSup_eq_top _).mpr ⟨?_, by simp [iSup_subtype]⟩ + refine (isInternal_submodule_iff_iSupIndep_and_iSup_eq_top _).mpr ⟨?_, by simp [iSup_subtype]⟩ let p := ⨆ i ∈ s, A i have hp : ∀ i ∈ s, A i ≤ p := fun i hi ↦ le_biSup A hi let e : Submodule R p ≃o Set.Iic p := p.mapIic suffices (e ∘ fun i : s ↦ (A i).comap p.subtype) = fun i ↦ ⟨A i, hp i i.property⟩ by - rw [← CompleteLattice.independent_map_orderIso_iff e, this] - exact CompleteLattice.independent_of_independent_coe_Iic_comp h + rw [← iSupIndep_map_orderIso_iff e, this] + exact .of_coe_Iic_comp h ext i m change m ∈ ((A i).comap p.subtype).map p.subtype ↔ _ rw [Submodule.map_comap_subtype, inf_of_le_right (hp i i.property)] +@[deprecated (since := "2024-11-24")] +alias isInternal_biSup_submodule_of_independent := isInternal_biSup_submodule_of_iSupIndep + /-! Now copy the lemmas for subgroup and submonoids. -/ -theorem IsInternal.addSubmonoid_independent {M : Type*} [AddCommMonoid M] {A : ι → AddSubmonoid M} - (h : IsInternal A) : CompleteLattice.Independent A := - CompleteLattice.independent_of_dfinsupp_sumAddHom_injective _ h.injective +theorem IsInternal.addSubmonoid_iSupIndep {M : Type*} [AddCommMonoid M] {A : ι → AddSubmonoid M} + (h : IsInternal A) : iSupIndep A := + iSupIndep_of_dfinsupp_sumAddHom_injective _ h.injective + +@[deprecated (since := "2024-11-24")] +alias IsInternal.addSubmonoid_independent := IsInternal.addSubmonoid_iSupIndep + +theorem IsInternal.addSubgroup_iSupIndep {G : Type*} [AddCommGroup G] {A : ι → AddSubgroup G} + (h : IsInternal A) : iSupIndep A := + iSupIndep_of_dfinsupp_sumAddHom_injective' _ h.injective -theorem IsInternal.addSubgroup_independent {M : Type*} [AddCommGroup M] {A : ι → AddSubgroup M} - (h : IsInternal A) : CompleteLattice.Independent A := - CompleteLattice.independent_of_dfinsupp_sumAddHom_injective' _ h.injective +@[deprecated (since := "2024-11-24")] +alias IsInternal.addSubgroup_independent := IsInternal.addSubgroup_iSupIndep end Ring diff --git a/Mathlib/Algebra/DirectSum/Ring.lean b/Mathlib/Algebra/DirectSum/Ring.lean index aa5a84bec944c..883dc0bb086a7 100644 --- a/Mathlib/Algebra/DirectSum/Ring.lean +++ b/Mathlib/Algebra/DirectSum/Ring.lean @@ -63,9 +63,8 @@ instances for: * `A : ι → Submodule S`: `DirectSum.GSemiring.ofSubmodules`, `DirectSum.GCommSemiring.ofSubmodules`. -If `CompleteLattice.independent (Set.range A)`, these provide a gradation of `⨆ i, A i`, and the -mapping `⨁ i, A i →+ ⨆ i, A i` can be obtained as -`DirectSum.toMonoid (fun i ↦ AddSubmonoid.inclusion <| le_iSup A i)`. +If `sSupIndep A`, these provide a gradation of `⨆ i, A i`, and the mapping `⨁ i, A i →+ ⨆ i, A i` +can be obtained as `DirectSum.toMonoid (fun i ↦ AddSubmonoid.inclusion <| le_iSup A i)`. ## Tags diff --git a/Mathlib/Algebra/FreeAlgebra/Cardinality.lean b/Mathlib/Algebra/FreeAlgebra/Cardinality.lean new file mode 100644 index 0000000000000..801dea8a9298c --- /dev/null +++ b/Mathlib/Algebra/FreeAlgebra/Cardinality.lean @@ -0,0 +1,78 @@ +/- +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.Algebra.FreeAlgebra +import Mathlib.SetTheory.Cardinal.Free + +/-! +# Cardinality of free algebras + +This file contains some results about the cardinality of `FreeAlgebra`, +parallel to that of `MvPolynomial`. +-/ + +universe u v + +variable (R : Type u) [CommSemiring R] + +open Cardinal + +namespace FreeAlgebra + +variable (X : Type v) + +@[simp] +theorem cardinalMk_eq_max_lift [Nonempty X] [Nontrivial R] : + #(FreeAlgebra R X) = Cardinal.lift.{v} #R ⊔ Cardinal.lift.{u} #X ⊔ ℵ₀ := by + have hX := mk_freeMonoid X + haveI : Infinite (FreeMonoid X) := infinite_iff.2 (by simp [hX]) + rw [equivMonoidAlgebraFreeMonoid.toEquiv.cardinal_eq, MonoidAlgebra, + mk_finsupp_lift_of_infinite, hX, lift_max, lift_aleph0, sup_comm, ← sup_assoc] + +@[simp] +theorem cardinalMk_eq_lift [IsEmpty X] : #(FreeAlgebra R X) = Cardinal.lift.{v} #R := by + have := lift_mk_eq'.2 ⟨show (FreeMonoid X →₀ R) ≃ R from Equiv.finsuppUnique⟩ + rw [lift_id'.{u, v}, lift_umax] at this + rwa [equivMonoidAlgebraFreeMonoid.toEquiv.cardinal_eq, MonoidAlgebra] + +@[nontriviality] +theorem cardinalMk_eq_one [Subsingleton R] : #(FreeAlgebra R X) = 1 := by + rw [equivMonoidAlgebraFreeMonoid.toEquiv.cardinal_eq, MonoidAlgebra, mk_eq_one] + +theorem cardinalMk_le_max_lift : + #(FreeAlgebra R X) ≤ Cardinal.lift.{v} #R ⊔ Cardinal.lift.{u} #X ⊔ ℵ₀ := by + cases subsingleton_or_nontrivial R + · exact (cardinalMk_eq_one R X).trans_le (le_max_of_le_right one_le_aleph0) + cases isEmpty_or_nonempty X + · exact (cardinalMk_eq_lift R X).trans_le (le_max_of_le_left <| le_max_left _ _) + · exact (cardinalMk_eq_max_lift R X).le + +variable (X : Type u) + +theorem cardinalMk_eq_max [Nonempty X] [Nontrivial R] : #(FreeAlgebra R X) = #R ⊔ #X ⊔ ℵ₀ := by + simp + +theorem cardinalMk_eq [IsEmpty X] : #(FreeAlgebra R X) = #R := by + simp + +theorem cardinalMk_le_max : #(FreeAlgebra R X) ≤ #R ⊔ #X ⊔ ℵ₀ := by + simpa using cardinalMk_le_max_lift R X + +end FreeAlgebra + +namespace Algebra + +theorem lift_cardinalMk_adjoin_le {A : Type v} [Semiring A] [Algebra R A] (s : Set A) : + lift.{u} #(adjoin R s) ≤ lift.{v} #R ⊔ lift.{u} #s ⊔ ℵ₀ := by + have H := mk_range_le_lift (f := FreeAlgebra.lift R ((↑) : s → A)) + rw [lift_umax, lift_id'.{v, u}] at H + rw [Algebra.adjoin_eq_range_freeAlgebra_lift] + exact H.trans (FreeAlgebra.cardinalMk_le_max_lift R s) + +theorem cardinalMk_adjoin_le {A : Type u} [Semiring A] [Algebra R A] (s : Set A) : + #(adjoin R s) ≤ #R ⊔ #s ⊔ ℵ₀ := by + simpa using lift_cardinalMk_adjoin_le R s + +end Algebra diff --git a/Mathlib/Algebra/FreeMonoid/Count.lean b/Mathlib/Algebra/FreeMonoid/Count.lean index df4dcfd27f672..53b2c0e4c51c3 100644 --- a/Mathlib/Algebra/FreeMonoid/Count.lean +++ b/Mathlib/Algebra/FreeMonoid/Count.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov -/ import Mathlib.Algebra.FreeMonoid.Basic +import Mathlib.Algebra.Group.TypeTags.Hom /-! # `List.count` as a bundled homomorphism diff --git a/Mathlib/Algebra/Group/Action/Defs.lean b/Mathlib/Algebra/Group/Action/Defs.lean index 823dbf69f3586..294281be04be5 100644 --- a/Mathlib/Algebra/Group/Action/Defs.lean +++ b/Mathlib/Algebra/Group/Action/Defs.lean @@ -297,9 +297,15 @@ lemma smul_mul_smul_comm [Mul α] [Mul β] [SMul α β] [IsScalarTower α β β] (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"))] +@[to_additive] alias smul_mul_smul := smul_mul_smul_comm +-- `alias` doesn't add the deprecation suggestion to the `to_additive` version +-- see https://github.com/leanprover-community/mathlib4/issues/19424 +attribute [deprecated smul_mul_smul_comm (since := "2024-08-29")] smul_mul_smul +attribute [deprecated vadd_add_vadd_comm (since := "2024-08-29")] vadd_add_vadd + + /-- Note that the `IsScalarTower α β β` and `SMulCommClass α β β` typeclass arguments are usually satisfied by `Algebra α β`. -/ @[to_additive] diff --git a/Mathlib/Algebra/Group/Action/TypeTags.lean b/Mathlib/Algebra/Group/Action/TypeTags.lean index 0fa009b36d114..1e65ced1a6024 100644 --- a/Mathlib/Algebra/Group/Action/TypeTags.lean +++ b/Mathlib/Algebra/Group/Action/TypeTags.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes, Yury Kudryashov -/ import Mathlib.Algebra.Group.Action.End -import Mathlib.Algebra.Group.TypeTags +import Mathlib.Algebra.Group.TypeTags.Hom /-! # Additive and Multiplicative for group actions @@ -24,15 +24,15 @@ section open Additive Multiplicative -instance Additive.vadd [SMul α β] : VAdd (Additive α) β where vadd a := (toMul a • ·) +instance Additive.vadd [SMul α β] : VAdd (Additive α) β where vadd a := (a.toMul • ·) -instance Multiplicative.smul [VAdd α β] : SMul (Multiplicative α) β where smul a := (toAdd a +ᵥ ·) +instance Multiplicative.smul [VAdd α β] : SMul (Multiplicative α) β where smul a := (a.toAdd +ᵥ ·) -@[simp] lemma toMul_smul [SMul α β] (a) (b : β) : (toMul a : α) • b = a +ᵥ b := rfl +@[simp] lemma toMul_smul [SMul α β] (a:Additive α) (b : β) : (a.toMul : α) • b = a +ᵥ b := rfl @[simp] lemma ofMul_vadd [SMul α β] (a : α) (b : β) : ofMul a +ᵥ b = a • b := rfl -@[simp] lemma toAdd_vadd [VAdd α β] (a) (b : β) : (toAdd a : α) +ᵥ b = a • b := rfl +@[simp] lemma toAdd_vadd [VAdd α β] (a:Multiplicative α) (b : β) : (a.toAdd : α) +ᵥ b = a • b := rfl @[simp] lemma ofAdd_smul [VAdd α β] (a : α) (b : β) : ofAdd a • b = a +ᵥ b := rfl diff --git a/Mathlib/Algebra/Group/AddChar.lean b/Mathlib/Algebra/Group/AddChar.lean index 23505cff4f752..0279bc188d39a 100644 --- a/Mathlib/Algebra/Group/AddChar.lean +++ b/Mathlib/Algebra/Group/AddChar.lean @@ -115,7 +115,7 @@ def toMonoidHom (φ : AddChar A M) : Multiplicative A →* M where -- this instance was a bad idea and conflicted with `instFunLike` above @[simp] lemma toMonoidHom_apply (ψ : AddChar A M) (a : Multiplicative A) : - ψ.toMonoidHom a = ψ (Multiplicative.toAdd a) := + ψ.toMonoidHom a = ψ a.toAdd := rfl /-- An additive character maps multiples by natural numbers to powers. -/ @@ -142,7 +142,7 @@ def toMonoidHomEquiv : AddChar A M ≃ (Multiplicative A →* M) where ⇑(toMonoidHomEquiv.symm ψ) = ψ ∘ Multiplicative.ofAdd := rfl @[simp] lemma toMonoidHomEquiv_apply (ψ : AddChar A M) (a : Multiplicative A) : - toMonoidHomEquiv ψ a = ψ (Multiplicative.toAdd a) := rfl + toMonoidHomEquiv ψ a = ψ a.toAdd := rfl @[simp] lemma toMonoidHomEquiv_symm_apply (ψ : Multiplicative A →* M) (a : A) : toMonoidHomEquiv.symm ψ a = ψ (Multiplicative.ofAdd a) := rfl @@ -180,7 +180,7 @@ lemma coe_toAddMonoidHomEquiv (ψ : AddChar A M) : toAddMonoidHomEquiv ψ a = Additive.ofMul (ψ a) := rfl @[simp] lemma toAddMonoidHomEquiv_symm_apply (ψ : A →+ Additive M) (a : A) : - toAddMonoidHomEquiv.symm ψ a = Additive.toMul (ψ a) := rfl + toAddMonoidHomEquiv.symm ψ a = (ψ a).toMul := rfl /-- The trivial additive character (sending everything to `1`). -/ instance instOne : One (AddChar A M) := toMonoidHomEquiv.one @@ -253,7 +253,7 @@ 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")] +@[deprecated "No deprecation message was provided." (since := "2024-06-06")] def IsNontrivial (ψ : AddChar A M) : Prop := ∃ a : A, ψ a ≠ 1 set_option linter.deprecated false in diff --git a/Mathlib/Algebra/Group/Aut.lean b/Mathlib/Algebra/Group/Aut.lean index ac678be0258c9..012f362054268 100644 --- a/Mathlib/Algebra/Group/Aut.lean +++ b/Mathlib/Algebra/Group/Aut.lean @@ -260,9 +260,9 @@ theorem conj_symm_apply [AddGroup G] (g h : G) : (conj g).symm h = -g + h + g := -- Porting note: the exact translation of this mathlib3 lemma would be`(-conj g) h = -g + h + g`, -- but this no longer pass the simp_nf linter, as the LHS simplifies by `toMul_neg` to --- `(Additive.toMul (conj g))⁻¹`. +-- `(conj g).toMul⁻¹`. @[simp] -theorem conj_inv_apply [AddGroup G] (g h : G) : (Additive.toMul (conj g))⁻¹ h = -g + h + g := +theorem conj_inv_apply [AddGroup G] (g h : G) : (conj g).toMul⁻¹ h = -g + h + g := rfl /-- Isomorphic additive groups have isomorphic automorphism groups. -/ diff --git a/Mathlib/Algebra/Group/Defs.lean b/Mathlib/Algebra/Group/Defs.lean index 3abfe30a7d417..3d069aab663a3 100644 --- a/Mathlib/Algebra/Group/Defs.lean +++ b/Mathlib/Algebra/Group/Defs.lean @@ -6,12 +6,9 @@ Authors: Jeremy Avigad, Leonardo de Moura, Simon Hudon, Mario Carneiro import Mathlib.Data.Int.Notation import Mathlib.Data.Nat.BinaryRec import Mathlib.Algebra.Group.ZeroOne +import Mathlib.Algebra.Group.Operations import Mathlib.Logic.Function.Defs -import Mathlib.Tactic.Lemma -import Mathlib.Tactic.TypeStar import Mathlib.Tactic.Simps.Basic -import Mathlib.Tactic.ToAdditive -import Mathlib.Util.AssertExists import Batteries.Logic /-! @@ -29,21 +26,15 @@ The file does not contain any lemmas except for For basic lemmas about these classes see `Algebra.Group.Basic`. -We also introduce notation classes `SMul` and `VAdd` for multiplicative and additive -actions and register the following instances: +We register the following instances: - `Pow M ℕ`, for monoids `M`, and `Pow G ℤ` for groups `G`; - `SMul ℕ M` for additive monoids `M`, and `SMul ℤ G` for additive groups `G`. -`SMul` is typically, but not exclusively, used for scalar multiplication-like operators. -See the module `Algebra.AddTorsor` for a motivating example for the name `VAdd` (vector addition). - ## Notation - `+`, `-`, `*`, `/`, `^` : the usual arithmetic operations; the underlying functions are `Add.add`, `Neg.neg`/`Sub.sub`, `Mul.mul`, `Div.div`, and `HPow.hPow`. -- `a • b` is used as notation for `HSMul.hSMul a b`. -- `a +ᵥ b` is used as notation for `HVAdd.hVAdd a b`. -/ @@ -55,187 +46,8 @@ universe u v w open Function -/-- -The notation typeclass for heterogeneous additive actions. -This enables the notation `a +ᵥ b : γ` where `a : α`, `b : β`. --/ -class HVAdd (α : Type u) (β : Type v) (γ : outParam (Type w)) where - /-- `a +ᵥ b` computes the sum of `a` and `b`. - The meaning of this notation is type-dependent. -/ - hVAdd : α → β → γ - -/-- -The notation typeclass for heterogeneous scalar multiplication. -This enables the notation `a • b : γ` where `a : α`, `b : β`. - -It is assumed to represent a left action in some sense. -The notation `a • b` is augmented with a macro (below) to have it elaborate as a left action. -Only the `b` argument participates in the elaboration algorithm: the algorithm uses the type of `b` -when calculating the type of the surrounding arithmetic expression -and it tries to insert coercions into `b` to get some `b'` -such that `a • b'` has the same type as `b'`. -See the module documentation near the macro for more details. --/ -class HSMul (α : Type u) (β : Type v) (γ : outParam (Type w)) where - /-- `a • b` computes the product of `a` and `b`. - The meaning of this notation is type-dependent, but it is intended to be used for left actions. -/ - hSMul : α → β → γ - -attribute [notation_class smul Simps.copySecond] HSMul -attribute [notation_class nsmul Simps.nsmulArgs] HSMul -attribute [notation_class zsmul Simps.zsmulArgs] HSMul - -/-- Type class for the `+ᵥ` notation. -/ -class VAdd (G : Type u) (P : Type v) where - /-- `a +ᵥ b` computes the sum of `a` and `b`. The meaning of this notation is type-dependent, - but it is intended to be used for left actions. -/ - vadd : G → P → P - -/-- Type class for the `-ᵥ` notation. -/ -class VSub (G : outParam Type*) (P : Type*) where - /-- `a -ᵥ b` computes the difference of `a` and `b`. The meaning of this notation is - type-dependent, but it is intended to be used for additive torsors. -/ - vsub : P → P → G - -/-- Typeclass for types with a scalar multiplication operation, denoted `•` (`\bu`) -/ -@[to_additive (attr := ext)] -class SMul (M : Type u) (α : Type v) where - /-- `a • b` computes the product of `a` and `b`. The meaning of this notation is type-dependent, - but it is intended to be used for left actions. -/ - smul : M → α → α - -@[inherit_doc] infixl:65 " +ᵥ " => HVAdd.hVAdd -@[inherit_doc] infixl:65 " -ᵥ " => VSub.vsub -@[inherit_doc] infixr:73 " • " => HSMul.hSMul - -/-! -We have a macro to make `x • y` notation participate in the expression tree elaborator, -like other arithmetic expressions such as `+`, `*`, `/`, `^`, `=`, inequalities, etc. -The macro is using the `leftact%` elaborator introduced in -[this RFC](https://github.com/leanprover/lean4/issues/2854). - -As a concrete example of the effect of this macro, consider -```lean -variable [Ring R] [AddCommMonoid M] [Module R M] (r : R) (N : Submodule R M) (m : M) (n : N) -#check m + r • n -``` -Without the macro, the expression would elaborate as `m + ↑(r • n : ↑N) : M`. -With the macro, the expression elaborates as `m + r • (↑n : M) : M`. -To get the first interpretation, one can write `m + (r • n :)`. - -Here is a quick review of the expression tree elaborator: -1. It builds up an expression tree of all the immediately accessible operations - that are marked with `binop%`, `unop%`, `leftact%`, `rightact%`, `binrel%`, etc. -2. It elaborates every leaf term of this tree - (without an expected type, so as if it were temporarily wrapped in `(... :)`). -3. Using the types of each elaborated leaf, it computes a supremum type they can all be - coerced to, if such a supremum exists. -4. It inserts coercions around leaf terms wherever needed. - -The hypothesis is that individual expression trees tend to be calculations with respect -to a single algebraic structure. - -Note(kmill): If we were to remove `HSMul` and switch to using `SMul` directly, -then the expression tree elaborator would not be able to insert coercions within the right operand; -they would likely appear as `↑(x • y)` rather than `x • ↑y`, unlike other arithmetic operations. --/ - -@[inherit_doc HSMul.hSMul] -macro_rules | `($x • $y) => `(leftact% HSMul.hSMul $x $y) - -attribute [to_additive existing] Mul Div HMul instHMul HDiv instHDiv HSMul -attribute [to_additive (reorder := 1 2) SMul] Pow -attribute [to_additive (reorder := 1 2)] HPow -attribute [to_additive existing (reorder := 1 2, 5 6) hSMul] HPow.hPow -attribute [to_additive existing (reorder := 1 2, 4 5) smul] Pow.pow - -@[to_additive (attr := default_instance)] -instance instHSMul {α β} [SMul α β] : HSMul α β β where - hSMul := SMul.smul - -@[to_additive] -theorem SMul.smul_eq_hSMul {α β} [SMul α β] : (SMul.smul : α → β → β) = HSMul.hSMul := rfl - -attribute [to_additive existing (reorder := 1 2)] instHPow - variable {G : Type*} -/-- Class of types that have an inversion operation. -/ -@[to_additive, notation_class] -class Inv (α : Type u) where - /-- Invert an element of α. -/ - inv : α → α - -@[inherit_doc] -postfix:max "⁻¹" => Inv.inv - -section ite -variable {α : Type*} (P : Prop) [Decidable P] - -section Mul -variable [Mul α] - -@[to_additive] -lemma mul_dite (a : α) (b : P → α) (c : ¬ P → α) : - (a * if h : P then b h else c h) = if h : P then a * b h else a * c h := by split <;> rfl - -@[to_additive] -lemma mul_ite (a b c : α) : (a * if P then b else c) = if P then a * b else a * c := mul_dite .. - -@[to_additive] -lemma dite_mul (a : P → α) (b : ¬ P → α) (c : α) : - (if h : P then a h else b h) * c = if h : P then a h * c else b h * c := by split <;> rfl - -@[to_additive] -lemma ite_mul (a b c : α) : (if P then a else b) * c = if P then a * c else b * c := dite_mul .. - --- We make `mul_ite` and `ite_mul` simp lemmas, but not `add_ite` or `ite_add`. --- The problem we're trying to avoid is dealing with sums of the form `∑ x ∈ s, (f x + ite P 1 0)`, --- in which `add_ite` followed by `sum_ite` would needlessly slice up --- the `f x` terms according to whether `P` holds at `x`. --- There doesn't appear to be a corresponding difficulty so far with `mul_ite` and `ite_mul`. -attribute [simp] mul_dite dite_mul mul_ite ite_mul - -@[to_additive] -lemma dite_mul_dite (a : P → α) (b : ¬ P → α) (c : P → α) (d : ¬ P → α) : - ((if h : P then a h else b h) * if h : P then c h else d h) = - if h : P then a h * c h else b h * d h := by split <;> rfl - -@[to_additive] -lemma ite_mul_ite (a b c d : α) : - ((if P then a else b) * if P then c else d) = if P then a * c else b * d := by split <;> rfl - -end Mul - -section Div -variable [Div α] - -@[to_additive] -lemma div_dite (a : α) (b : P → α) (c : ¬ P → α) : - (a / if h : P then b h else c h) = if h : P then a / b h else a / c h := by split <;> rfl - -@[to_additive] -lemma div_ite (a b c : α) : (a / if P then b else c) = if P then a / b else a / c := div_dite .. - -@[to_additive] -lemma dite_div (a : P → α) (b : ¬ P → α) (c : α) : - (if h : P then a h else b h) / c = if h : P then a h / c else b h / c := by split <;> rfl - -@[to_additive] -lemma ite_div (a b c : α) : (if P then a else b) / c = if P then a / c else b / c := dite_div .. - -@[to_additive] -lemma dite_div_dite (a : P → α) (b : ¬ P → α) (c : P → α) (d : ¬ P → α) : - ((if h : P then a h else b h) / if h : P then c h else d h) = - if h : P then a h / c h else b h / d h := by split <;> rfl - -@[to_additive] -lemma ite_div_ite (a b c d : α) : - ((if P then a else b) / if P then c else d) = if P then a / c else b / d := dite_div_dite .. - -end Div -end ite - section Mul variable [Mul G] diff --git a/Mathlib/Algebra/Group/Equiv/Basic.lean b/Mathlib/Algebra/Group/Equiv/Basic.lean index 81aff3106d93e..b0b66218245be 100644 --- a/Mathlib/Algebra/Group/Equiv/Basic.lean +++ b/Mathlib/Algebra/Group/Equiv/Basic.lean @@ -45,37 +45,6 @@ theorem map_ne_one_iff {f : F} {x : M} : end EmbeddingLike -/-- Makes a `OneHom` inverse from the bijective inverse of a `OneHom` -/ -@[to_additive (attr := simps) - "Make a `ZeroHom` inverse from the bijective inverse of a `ZeroHom`"] -def OneHom.inverse [One M] [One N] - (f : OneHom M N) (g : N → M) - (h₁ : Function.LeftInverse g f) : - OneHom N M := - { toFun := g, - map_one' := by rw [← f.map_one, h₁] } - -/-- Makes a multiplicative inverse from a bijection which preserves multiplication. -/ -@[to_additive (attr := simps) - "Makes an additive inverse from a bijection which preserves addition."] -def MulHom.inverse [Mul M] [Mul N] (f : M →ₙ* N) (g : N → M) - (h₁ : Function.LeftInverse g f) - (h₂ : Function.RightInverse g f) : N →ₙ* M where - toFun := g - map_mul' x y := - calc - g (x * y) = g (f (g x) * f (g y)) := by rw [h₂ x, h₂ y] - _ = g (f (g x * g y)) := by rw [f.map_mul] - _ = g x * g y := h₁ _ - -/-- The inverse of a bijective `MonoidHom` is a `MonoidHom`. -/ -@[to_additive (attr := simps) - "The inverse of a bijective `AddMonoidHom` is an `AddMonoidHom`."] -def MonoidHom.inverse {A B : Type*} [Monoid A] [Monoid B] (f : A →* B) (g : B → A) - (h₁ : Function.LeftInverse g f) (h₂ : Function.RightInverse g f) : B →* A := - { (f : OneHom A B).inverse g h₁, - (f : A →ₙ* B).inverse g h₁ h₂ with toFun := g } - /-- `AddEquiv α β` is the type of an equiv `α ≃ β` which preserves addition. -/ structure AddEquiv (A B : Type*) [Add A] [Add B] extends A ≃ B, AddHom A B @@ -125,12 +94,28 @@ class MulEquivClass (F : Type*) (A B : outParam Type*) [Mul A] [Mul B] [EquivLik /-- Preserves multiplication. -/ map_mul : ∀ (f : F) (a b), f (a * b) = f a * f b -@[to_additive (attr := deprecated (since := "2024-11-10"))] +@[to_additive] alias MulEquivClass.map_eq_one_iff := EmbeddingLike.map_eq_one_iff -@[to_additive (attr := deprecated (since := "2024-11-10"))] +-- `alias` doesn't add the deprecation suggestion to the `to_additive` version +-- see https://github.com/leanprover-community/mathlib4/issues/19424 +attribute [deprecated EmbeddingLike.map_eq_one_iff (since := "2024-11-10")] +MulEquivClass.map_eq_one_iff +attribute [deprecated EmbeddingLike.map_eq_zero_iff (since := "2024-11-10")] +AddEquivClass.map_eq_zero_iff + + +@[to_additive] alias MulEquivClass.map_ne_one_iff := EmbeddingLike.map_ne_one_iff +-- `alias` doesn't add the deprecation suggestion to the `to_additive` version +-- see https://github.com/leanprover-community/mathlib4/issues/19424 +attribute [deprecated EmbeddingLike.map_ne_one_iff (since := "2024-11-10")] +MulEquivClass.map_ne_one_iff +attribute [deprecated EmbeddingLike.map_ne_zero_iff (since := "2024-11-10")] +AddEquivClass.map_ne_zero_iff + + namespace MulEquivClass variable (F) diff --git a/Mathlib/Algebra/Group/Equiv/TypeTags.lean b/Mathlib/Algebra/Group/Equiv/TypeTags.lean index 78c085f074666..12338d2419e5a 100644 --- a/Mathlib/Algebra/Group/Equiv/TypeTags.lean +++ b/Mathlib/Algebra/Group/Equiv/TypeTags.lean @@ -5,7 +5,7 @@ Authors: Johannes Hölzl, Callum Sutton, Yury Kudryashov -/ import Mathlib.Algebra.Group.Equiv.Basic import Mathlib.Algebra.Group.Prod -import Mathlib.Algebra.Group.TypeTags +import Mathlib.Algebra.Group.TypeTags.Hom /-! # Additive and multiplicative equivalences associated to `Multiplicative` and `Additive`. @@ -118,8 +118,8 @@ and multiplicative endomorphisms of `Multiplicative A`. -/ @[simps] def MulEquiv.piMultiplicative (K : ι → Type*) [∀ i, Add (K i)] : Multiplicative (∀ i : ι, K i) ≃* (∀ i : ι, Multiplicative (K i)) where - toFun x := fun i ↦ Multiplicative.ofAdd <| Multiplicative.toAdd x i - invFun x := Multiplicative.ofAdd fun i ↦ Multiplicative.toAdd (x i) + toFun x := fun i ↦ Multiplicative.ofAdd <| x.toAdd i + invFun x := Multiplicative.ofAdd fun i ↦ (x i).toAdd left_inv _ := rfl right_inv _ := rfl map_mul' _ _ := rfl @@ -134,8 +134,8 @@ abbrev MulEquiv.funMultiplicative [Add G] : @[simps] def AddEquiv.piAdditive (K : ι → Type*) [∀ i, Mul (K i)] : Additive (∀ i : ι, K i) ≃+ (∀ i : ι, Additive (K i)) where - toFun x := fun i ↦ Additive.ofMul <| Additive.toMul x i - invFun x := Additive.ofMul fun i ↦ Additive.toMul (x i) + toFun x := fun i ↦ Additive.ofMul <| x.toMul i + invFun x := Additive.ofMul fun i ↦ (x i).toMul left_inv _ := rfl right_inv _ := rfl map_add' _ _ := rfl @@ -164,9 +164,9 @@ def MulEquiv.multiplicativeAdditive [MulOneClass H] : Multiplicative (Additive H @[simps] def MulEquiv.prodMultiplicative [Add G] [Add H] : Multiplicative (G × H) ≃* Multiplicative G × Multiplicative H where - toFun x := (Multiplicative.ofAdd (Multiplicative.toAdd x).1, - Multiplicative.ofAdd (Multiplicative.toAdd x).2) - invFun := fun (x, y) ↦ Multiplicative.ofAdd (Multiplicative.toAdd x, Multiplicative.toAdd y) + toFun x := (Multiplicative.ofAdd x.toAdd.1, + Multiplicative.ofAdd x.toAdd.2) + invFun := fun (x, y) ↦ Multiplicative.ofAdd (x.toAdd, y.toAdd) left_inv _ := rfl right_inv _ := rfl map_mul' _ _ := rfl @@ -175,9 +175,9 @@ def MulEquiv.prodMultiplicative [Add G] [Add H] : @[simps] def AddEquiv.prodAdditive [Mul G] [Mul H] : Additive (G × H) ≃+ Additive G × Additive H where - toFun x := (Additive.ofMul (Additive.toMul x).1, - Additive.ofMul (Additive.toMul x).2) - invFun := fun (x, y) ↦ Additive.ofMul (Additive.toMul x, Additive.toMul y) + toFun x := (Additive.ofMul x.toMul.1, + Additive.ofMul x.toMul.2) + invFun := fun (x, y) ↦ Additive.ofMul (x.toMul, y.toMul) left_inv _ := rfl right_inv _ := rfl map_add' _ _ := rfl diff --git a/Mathlib/Algebra/Group/Even.lean b/Mathlib/Algebra/Group/Even.lean index 5bd24647c2f65..8df0d5b3613c9 100644 --- a/Mathlib/Algebra/Group/Even.lean +++ b/Mathlib/Algebra/Group/Even.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Damiano Testa -/ import Mathlib.Algebra.Group.Opposite -import Mathlib.Algebra.Group.TypeTags +import Mathlib.Algebra.Group.TypeTags.Basic /-! # Squares and even elements @@ -62,7 +62,7 @@ instance [DecidablePred (IsSquare : α → Prop)] : DecidablePred (IsSquare : α lemma even_ofMul_iff {a : α} : Even (Additive.ofMul a) ↔ IsSquare a := Iff.rfl @[simp] -lemma isSquare_toMul_iff {a : Additive α} : IsSquare (Additive.toMul a) ↔ Even a := Iff.rfl +lemma isSquare_toMul_iff {a : Additive α} : IsSquare (a.toMul) ↔ Even a := Iff.rfl instance Additive.instDecidablePredEven [DecidablePred (IsSquare : α → Prop)] : DecidablePred (Even : Additive α → Prop) := @@ -76,7 +76,7 @@ variable [Add α] @[simp] lemma isSquare_ofAdd_iff {a : α} : IsSquare (Multiplicative.ofAdd a) ↔ Even a := Iff.rfl @[simp] -lemma even_toAdd_iff {a : Multiplicative α} : Even (Multiplicative.toAdd a) ↔ IsSquare a := Iff.rfl +lemma even_toAdd_iff {a : Multiplicative α} : Even a.toAdd ↔ IsSquare a := Iff.rfl instance Multiplicative.instDecidablePredIsSquare [DecidablePred (Even : α → Prop)] : DecidablePred (IsSquare : Multiplicative α → Prop) := diff --git a/Mathlib/Algebra/Group/Graph.lean b/Mathlib/Algebra/Group/Graph.lean new file mode 100644 index 0000000000000..a3cf4bee29867 --- /dev/null +++ b/Mathlib/Algebra/Group/Graph.lean @@ -0,0 +1,231 @@ +/- +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, David Loeffler +-/ +import Mathlib.Algebra.Group.Subgroup.Ker + +/-! +# Vertical line test for group homs + +This file proves the vertical line test for monoid homomorphisms/isomorphisms. + +Let `f : G → H × I` be a homomorphism to a product of monoids. Assume that `f` is surjective on the +first factor and that the image of `f` intersects every "vertical line" `{(h, i) | i : I}` at most +once. Then the image of `f` is the graph of some monoid homomorphism `f' : H → I`. + +Furthermore, if `f` is also surjective on the second factor and its image intersects every +"horizontal line" `{(h, i) | h : H}` at most once, then `f'` is actually an isomorphism +`f' : H ≃ I`. + +We also prove specialised versions when `f` is the inclusion of a subgroup of the direct product. +(The version for general homomorphisms can easily be reduced to this special case, but the +homomorphism version is more flexible in applications.) +-/ + +open Function Set + +variable {G H I : Type*} + +section Monoid +variable [Monoid G] [Monoid H] [Monoid I] + +namespace MonoidHom + +/-- The graph of a monoid homomorphism as a submonoid. + +See also `MonoidHom.graph` for the graph as a subgroup. -/ +@[to_additive +"The graph of a monoid homomorphism as a submonoid. + +See also `AddMonoidHom.graph` for the graph as a subgroup."] +def mgraph (f : G →* H) : Submonoid (G × H) where + carrier := {x | f x.1 = x.2} + one_mem' := map_one f + mul_mem' {x y} := by simp +contextual + +-- TODO: Can `to_additive` be smarter about `simps`? +attribute [simps! coe] mgraph +attribute [simps! coe] AddMonoidHom.mgraph +set_option linter.existingAttributeWarning false in +attribute [to_additive existing] coe_mgraph + +@[to_additive (attr := simp)] +lemma mem_mgraph {f : G →* H} {x : G × H} : x ∈ f.mgraph ↔ f x.1 = x.2 := .rfl + +@[to_additive] +lemma mgraph_eq_mrange_prod (f : G →* H) : f.mgraph = mrange ((id _).prod f) := by aesop + +/-- **Vertical line test** for monoid homomorphisms. + +Let `f : G → H × I` be a homomorphism to a product of monoids. Assume that `f` is surjective on the +first factor and that the image of `f` intersects every "vertical line" `{(h, i) | i : I}` at most +once. Then the image of `f` is the graph of some monoid homomorphism `f' : H → I`. -/ +@[to_additive "**Vertical line test** for monoid homomorphisms. + +Let `f : G → H × I` be a homomorphism to a product of monoids. Assume that `f` is surjective on the +first factor and that the image of `f` intersects every \"vertical line\" `{(h, i) | i : I}` at most +once. Then the image of `f` is the graph of some monoid homomorphism `f' : H → I`."] +lemma exists_mrange_eq_mgraph {f : G →* H × I} (hf₁ : Surjective (Prod.fst ∘ f)) + (hf : ∀ g₁ g₂, (f g₁).1 = (f g₂).1 → (f g₁).2 = (f g₂).2) : + ∃ f' : H →* I, mrange f = f'.mgraph := by + obtain ⟨f', hf'⟩ := exists_range_eq_graphOn_univ hf₁ hf + simp only [Set.ext_iff, Set.mem_range, mem_graphOn, mem_univ, true_and, Prod.forall] at hf' + use + { toFun := f' + map_one' := (hf' _ _).1 ⟨1, map_one _⟩ + map_mul' := by + simp_rw [hf₁.forall] + rintro g₁ g₂ + exact (hf' _ _).1 ⟨g₁ * g₂, by simp [Prod.ext_iff, (hf' (f _).1 _).1 ⟨_, rfl⟩]⟩ } + simpa [SetLike.ext_iff] using hf' + +/-- **Line test** for monoid isomorphisms. + +Let `f : G → H × I` be a homomorphism to a product of monoids. Assume that `f` is surjective on both +factors and that the image of `f` intersects every "vertical line" `{(h, i) | i : I}` and every +"horizontal line" `{(h, i) | h : H}` at most once. Then the image of `f` is the graph of some monoid +isomorphism `f' : H ≃ I`. -/ +@[to_additive "**Line test** for monoid isomorphisms. + +Let `f : G → H × I` be a homomorphism to a product of monoids. Assume that `f` is surjective on both +factors and that the image of `f` intersects every \"vertical line\" `{(h, i) | i : I}` and every +\"horizontal line\" `{(h, i) | h : H}` at most once. Then the image of `f` is the graph of some +monoid isomorphism `f' : H ≃ I`."] +lemma exists_mulEquiv_mrange_eq_mgraph {f : G →* H × I} (hf₁ : Surjective (Prod.fst ∘ f)) + (hf₂ : Surjective (Prod.snd ∘ f)) (hf : ∀ g₁ g₂, (f g₁).1 = (f g₂).1 ↔ (f g₁).2 = (f g₂).2) : + ∃ e : H ≃* I, mrange f = e.toMonoidHom.mgraph := by + obtain ⟨e₁, he₁⟩ := f.exists_mrange_eq_mgraph hf₁ fun _ _ ↦ (hf _ _).1 + obtain ⟨e₂, he₂⟩ := (MulEquiv.prodComm.toMonoidHom.comp f).exists_mrange_eq_mgraph (by simpa) <| + by simp [hf] + have he₁₂ h i : e₁ h = i ↔ e₂ i = h := by + rw [SetLike.ext_iff] at he₁ he₂ + aesop (add simp [Prod.swap_eq_iff_eq_swap]) + exact ⟨ + { toFun := e₁ + map_mul' := e₁.map_mul' + invFun := e₂ + left_inv := fun h ↦ by rw [← he₁₂] + right_inv := fun i ↦ by rw [he₁₂] }, he₁⟩ + +end MonoidHom + +/-- **Vertical line test** for monoid homomorphisms. + +Let `G ≤ H × I` be a submonoid of a product of monoids. Assume that `G` maps bijectively to the +first factor. Then `G` is the graph of some monoid homomorphism `f : H → I`. -/ +@[to_additive "**Vertical line test** for additive monoid homomorphisms. + +Let `G ≤ H × I` be a submonoid of a product of monoids. Assume that `G` surjects onto the first +factor and `G` intersects every \"vertical line\" `{(h, i) | i : I}` at most once. Then `G` is the +graph of some monoid homomorphism `f : H → I`."] +lemma Submonoid.exists_eq_mgraph {G : Submonoid (H × I)} (hG₁ : Bijective (Prod.fst ∘ G.subtype)) : + ∃ f : H →* I, G = f.mgraph := by + simpa using MonoidHom.exists_mrange_eq_mgraph hG₁.surjective + fun a b h ↦ congr_arg (Prod.snd ∘ G.subtype) (hG₁.injective h) + +/-- **Goursat's lemma** for monoid isomorphisms. + +Let `G ≤ H × I` be a submonoid of a product of monoids. Assume that the natural maps from `G` to +both factors are bijective. Then `G` is the graph of some isomorphism `f : H ≃* I`. -/ +@[to_additive "**Goursat's lemma** for additive monoid isomorphisms. + +Let `G ≤ H × I` be a submonoid of a product of additive monoids. Assume that the natural maps from +`G` to both factors are bijective. Then `G` is the graph of some isomorphism `f : H ≃+ I`."] +lemma Submonoid.exists_mulEquiv_eq_mgraph {G : Submonoid (H × I)} + (hG₁ : Bijective (Prod.fst ∘ G.subtype)) (hG₂ : Bijective (Prod.snd ∘ G.subtype)) : + ∃ e : H ≃* I, G = e.toMonoidHom.mgraph := by + simpa using MonoidHom.exists_mulEquiv_mrange_eq_mgraph hG₁.surjective hG₂.surjective + fun _ _ ↦ hG₁.injective.eq_iff.trans hG₂.injective.eq_iff.symm + +end Monoid + +section Group +variable [Group G] [Group H] [Group I] + +namespace MonoidHom + +/-- The graph of a group homomorphism as a subgroup. + +See also `MonoidHom.mgraph` for the graph as a submonoid. -/ +@[to_additive +"The graph of a group homomorphism as a subgroup. + +See also `AddMonoidHom.mgraph` for the graph as a submonoid."] +def graph (f : G →* H) : Subgroup (G × H) where + toSubmonoid := f.mgraph + inv_mem' {x} := by simp +contextual + +-- TODO: Can `to_additive` be smarter about `simps`? +attribute [simps! coe toSubmonoid] graph +attribute [simps! coe toAddSubmonoid] AddMonoidHom.graph +set_option linter.existingAttributeWarning false in +attribute [to_additive existing] coe_graph graph_toSubmonoid + +@[to_additive] +lemma mem_graph {f : G →* H} {x : G × H} : x ∈ f.mgraph ↔ f x.1 = x.2 := .rfl + +@[to_additive] +lemma graph_eq_range_prod (f : G →* H) : f.graph = range ((id _).prod f) := by aesop + +/-- **Vertical line test** for group homomorphisms. + +Let `f : G → H × I` be a homomorphism to a product of groups. Assume that `f` is surjective on the +first factor and that the image of `f` intersects every "vertical line" `{(h, i) | i : I}` at most +once. Then the image of `f` is the graph of some group homomorphism `f' : H → I`. -/ +@[to_additive "**Vertical line test** for group homomorphisms. + +Let `f : G → H × I` be a homomorphism to a product of groups. Assume that `f` is surjective on the +first factor and that the image of `f` intersects every \"vertical line\" `{(h, i) | i : I}` at most +once. Then the image of `f` is the graph of some group homomorphism `f' : H → I`."] +lemma exists_range_eq_graph {f : G →* H × I} (hf₁ : Surjective (Prod.fst ∘ f)) + (hf : ∀ g₁ g₂, (f g₁).1 = (f g₂).1 → (f g₁).2 = (f g₂).2) : + ∃ f' : H →* I, range f = f'.graph := by + simpa [SetLike.ext_iff] using exists_mrange_eq_mgraph hf₁ hf + +/-- **Line test** for group isomorphisms. + +Let `f : G → H × I` be a homomorphism to a product of groups. Assume that `f` is surjective on both +factors and that the image of `f` intersects every "vertical line" `{(h, i) | i : I}` and every +"horizontal line" `{(h, i) | h : H}` at most once. Then the image of `f` is the graph of some group +isomorphism `f' : H ≃ I`. -/ +@[to_additive "**Line test** for monoid isomorphisms. + +Let `f : G → H × I` be a homomorphism to a product of groups. Assume that `f` is surjective on both +factors and that the image of `f` intersects every \"vertical line\" `{(h, i) | i : I}` and every +\"horizontal line\" `{(h, i) | h : H}` at most once. Then the image of `f` is the graph of some +group isomorphism `f' : H ≃ I`."] +lemma exists_mulEquiv_range_eq_graph {f : G →* H × I} (hf₁ : Surjective (Prod.fst ∘ f)) + (hf₂ : Surjective (Prod.snd ∘ f)) (hf : ∀ g₁ g₂, (f g₁).1 = (f g₂).1 ↔ (f g₁).2 = (f g₂).2) : + ∃ e : H ≃* I, range f = e.toMonoidHom.graph := by + simpa [SetLike.ext_iff] using exists_mulEquiv_mrange_eq_mgraph hf₁ hf₂ hf + +end MonoidHom + +/-- **Vertical line test** for group homomorphisms. + +Let `G ≤ H × I` be a subgroup of a product of monoids. Assume that `G` maps bijectively to the +first factor. Then `G` is the graph of some monoid homomorphism `f : H → I`. -/ +@[to_additive "**Vertical line test** for additive monoid homomorphisms. + +Let `G ≤ H × I` be a submonoid of a product of monoids. Assume that `G` surjects onto the first +factor and `G` intersects every \"vertical line\" `{(h, i) | i : I}` at most once. Then `G` is the +graph of some monoid homomorphism `f : H → I`."] +lemma Subgroup.exists_eq_graph {G : Subgroup (H × I)} (hG₁ : Bijective (Prod.fst ∘ G.subtype)) : + ∃ f : H →* I, G = f.graph := by + simpa [SetLike.ext_iff] using Submonoid.exists_eq_mgraph hG₁ + +/-- **Goursat's lemma** for monoid isomorphisms. + +Let `G ≤ H × I` be a submonoid of a product of monoids. Assume that the natural maps from `G` to +both factors are bijective. Then `G` is the graph of some isomorphism `f : H ≃* I`. -/ +@[to_additive "**Goursat's lemma** for additive monoid isomorphisms. + +Let `G ≤ H × I` be a submonoid of a product of additive monoids. Assume that the natural maps from +`G` to both factors are bijective. Then `G` is the graph of some isomorphism `f : H ≃+ I`."] +lemma Subgroup.exists_mulEquiv_eq_graph {G : Subgroup (H × I)} + (hG₁ : Bijective (Prod.fst ∘ G.subtype)) (hG₂ : Bijective (Prod.snd ∘ G.subtype)) : + ∃ e : H ≃* I, G = e.toMonoidHom.graph := by + simpa [SetLike.ext_iff] using Submonoid.exists_mulEquiv_eq_mgraph hG₁ hG₂ + +end Group diff --git a/Mathlib/Algebra/Group/Hom/Defs.lean b/Mathlib/Algebra/Group/Hom/Defs.lean index 14f51627f6d9d..ea061a0993f08 100644 --- a/Mathlib/Algebra/Group/Hom/Defs.lean +++ b/Mathlib/Algebra/Group/Hom/Defs.lean @@ -30,6 +30,7 @@ building blocks for other homomorphisms: * `→+`: Bundled `AddMonoid` homs. Also use for `AddGroup` homs. * `→*`: Bundled `Monoid` homs. Also use for `Group` homs. +* `→ₙ+`: Bundled `AddSemigroup` homs. * `→ₙ*`: Bundled `Semigroup` homs. ## Implementation notes @@ -95,7 +96,9 @@ end Zero section Add -/-- `AddHom M N` is the type of functions `M → N` that preserve addition. +/-- `M →ₙ+ N` is the type of functions `M → N` that preserve addition. The `ₙ` in the notation +stands for "non-unital" because it is intended to match the notation for `NonUnitalAlgHom` and +`NonUnitalRingHom`, so a `AddHom` is a non-unital additive monoid hom. When possible, instead of parametrizing results over `(f : AddHom M N)`, you should parametrize over `(F : Type*) [AddHomClass F M N] (f : F)`. @@ -108,6 +111,9 @@ structure AddHom (M : Type*) (N : Type*) [Add M] [Add N] where /-- The proposition that the function preserves addition -/ protected map_add' : ∀ x y, toFun (x + y) = toFun x + toFun y +/-- `M →ₙ+ N` denotes the type of addition-preserving maps from `M` to `N`. -/ +infixr:25 " →ₙ+ " => AddHom + /-- `AddHomClass F M N` states that `F` is a type of addition-preserving homomorphisms. You should declare an instance of this typeclass when you extend `AddHom`. -/ @@ -843,6 +849,37 @@ protected theorem MonoidHom.map_zpow' [DivInvMonoid M] [DivInvMonoid N] (f : M (hf : ∀ x, f x⁻¹ = (f x)⁻¹) (a : M) (n : ℤ) : f (a ^ n) = f a ^ n := map_zpow' f hf a n +/-- Makes a `OneHom` inverse from the bijective inverse of a `OneHom` -/ +@[to_additive (attr := simps) + "Make a `ZeroHom` inverse from the bijective inverse of a `ZeroHom`"] +def OneHom.inverse [One M] [One N] + (f : OneHom M N) (g : N → M) + (h₁ : Function.LeftInverse g f) : + OneHom N M := + { toFun := g, + map_one' := by rw [← f.map_one, h₁] } + +/-- Makes a multiplicative inverse from a bijection which preserves multiplication. -/ +@[to_additive (attr := simps) + "Makes an additive inverse from a bijection which preserves addition."] +def MulHom.inverse [Mul M] [Mul N] (f : M →ₙ* N) (g : N → M) + (h₁ : Function.LeftInverse g f) + (h₂ : Function.RightInverse g f) : N →ₙ* M where + toFun := g + map_mul' x y := + calc + g (x * y) = g (f (g x) * f (g y)) := by rw [h₂ x, h₂ y] + _ = g (f (g x * g y)) := by rw [f.map_mul] + _ = g x * g y := h₁ _ + +/-- The inverse of a bijective `MonoidHom` is a `MonoidHom`. -/ +@[to_additive (attr := simps) + "The inverse of a bijective `AddMonoidHom` is an `AddMonoidHom`."] +def MonoidHom.inverse {A B : Type*} [Monoid A] [Monoid B] (f : A →* B) (g : B → A) + (h₁ : Function.LeftInverse g f) (h₂ : Function.RightInverse g f) : B →* A := + { (f : OneHom A B).inverse g h₁, + (f : A →ₙ* B).inverse g h₁ h₂ with toFun := g } + section End namespace Monoid diff --git a/Mathlib/Algebra/Group/Int.lean b/Mathlib/Algebra/Group/Int.lean index 1fcf3f10ef98c..e9b98108c5110 100644 --- a/Mathlib/Algebra/Group/Int.lean +++ b/Mathlib/Algebra/Group/Int.lean @@ -3,7 +3,8 @@ Copyright (c) 2016 Jeremy Avigad. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad -/ -import Mathlib.Algebra.Group.Nat +import Mathlib.Algebra.Group.Nat.Even +import Mathlib.Algebra.Group.Nat.Units import Mathlib.Algebra.Group.Units.Basic import Mathlib.Data.Int.Sqrt @@ -73,9 +74,9 @@ section Multiplicative open Multiplicative -lemma toAdd_pow (a : Multiplicative ℤ) (b : ℕ) : toAdd (a ^ b) = toAdd a * b := mul_comm _ _ +lemma toAdd_pow (a : Multiplicative ℤ) (b : ℕ) : (a ^ b).toAdd = a.toAdd * b := mul_comm _ _ -lemma toAdd_zpow (a : Multiplicative ℤ) (b : ℤ) : toAdd (a ^ b) = toAdd a * b := mul_comm _ _ +lemma toAdd_zpow (a : Multiplicative ℤ) (b : ℤ) : (a ^ b).toAdd = a.toAdd * b := mul_comm _ _ @[simp] lemma ofAdd_mul (a b : ℤ) : ofAdd (a * b) = ofAdd a ^ b := (toAdd_zpow ..).symm diff --git a/Mathlib/Algebra/Group/Nat/Basic.lean b/Mathlib/Algebra/Group/Nat/Basic.lean new file mode 100644 index 0000000000000..75212737a122b --- /dev/null +++ b/Mathlib/Algebra/Group/Nat/Basic.lean @@ -0,0 +1,65 @@ +/- +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.Algebra.Group.Defs + +/-! +# The natural numbers form a monoid + +This file contains the additive and multiplicative monoid instances on the natural numbers. + +See note [foundational algebra order theory]. +-/ + +assert_not_exists MonoidWithZero +assert_not_exists DenselyOrdered + +namespace Nat + +/-! ### Instances -/ + +instance instAddCancelCommMonoid : AddCancelCommMonoid ℕ where + add := Nat.add + add_assoc := Nat.add_assoc + zero := Nat.zero + zero_add := Nat.zero_add + add_zero := Nat.add_zero + add_comm := Nat.add_comm + nsmul m n := m * n + nsmul_zero := Nat.zero_mul + nsmul_succ := succ_mul + add_left_cancel _ _ _ := Nat.add_left_cancel + +instance instCommMonoid : CommMonoid ℕ where + mul := Nat.mul + mul_assoc := Nat.mul_assoc + one := Nat.succ Nat.zero + one_mul := Nat.one_mul + mul_one := Nat.mul_one + mul_comm := Nat.mul_comm + npow m n := n ^ m + npow_zero := Nat.pow_zero + npow_succ _ _ := rfl + +/-! +### Extra instances to short-circuit type class resolution + +These also prevent non-computable instances being used to construct these instances non-computably. +-/ + +instance instAddCommMonoid : AddCommMonoid ℕ := by infer_instance +instance instAddMonoid : AddMonoid ℕ := by infer_instance +instance instMonoid : Monoid ℕ := by infer_instance +instance instCommSemigroup : CommSemigroup ℕ := by infer_instance +instance instSemigroup : Semigroup ℕ := by infer_instance +instance instAddCommSemigroup : AddCommSemigroup ℕ := by infer_instance +instance instAddSemigroup : AddSemigroup ℕ := by infer_instance + +/-! ### Miscellaneous lemmas -/ + +-- We set the simp priority slightly lower than default; later more general lemmas will replace it. +@[simp 900] protected lemma nsmul_eq_mul (m n : ℕ) : m • n = m * n := rfl + +end Nat diff --git a/Mathlib/Algebra/Group/Nat.lean b/Mathlib/Algebra/Group/Nat/Even.lean similarity index 60% rename from Mathlib/Algebra/Group/Nat.lean rename to Mathlib/Algebra/Group/Nat/Even.lean index 42bd89df34d7b..86fcfd3209c0d 100644 --- a/Mathlib/Algebra/Group/Nat.lean +++ b/Mathlib/Algebra/Group/Nat/Even.lean @@ -4,76 +4,18 @@ 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.Algebra.Group.Even -import Mathlib.Algebra.Group.Units.Defs +import Mathlib.Algebra.Group.Nat.Basic import Mathlib.Data.Nat.Sqrt /-! -# The natural numbers form a monoid - -This file contains the additive and multiplicative monoid instances on the natural numbers. - -See note [foundational algebra order theory]. +# `IsSquare` and `Even` for natural numbers -/ assert_not_exists MonoidWithZero assert_not_exists DenselyOrdered -open Multiplicative - namespace Nat -/-! ### Instances -/ - -instance instAddCancelCommMonoid : AddCancelCommMonoid ℕ where - add := Nat.add - add_assoc := Nat.add_assoc - zero := Nat.zero - zero_add := Nat.zero_add - add_zero := Nat.add_zero - add_comm := Nat.add_comm - nsmul m n := m * n - nsmul_zero := Nat.zero_mul - nsmul_succ := succ_mul - add_left_cancel _ _ _ := Nat.add_left_cancel - -instance instCommMonoid : CommMonoid ℕ where - mul := Nat.mul - mul_assoc := Nat.mul_assoc - one := Nat.succ Nat.zero - one_mul := Nat.one_mul - mul_one := Nat.mul_one - mul_comm := Nat.mul_comm - npow m n := n ^ m - npow_zero := Nat.pow_zero - npow_succ _ _ := rfl - -/-! -### Extra instances to short-circuit type class resolution - -These also prevent non-computable instances being used to construct these instances non-computably. --/ - -instance instAddCommMonoid : AddCommMonoid ℕ := by infer_instance -instance instAddMonoid : AddMonoid ℕ := by infer_instance -instance instMonoid : Monoid ℕ := by infer_instance -instance instCommSemigroup : CommSemigroup ℕ := by infer_instance -instance instSemigroup : Semigroup ℕ := by infer_instance -instance instAddCommSemigroup : AddCommSemigroup ℕ := by infer_instance -instance instAddSemigroup : AddSemigroup ℕ := by infer_instance - -/-! ### Miscellaneous lemmas -/ - --- We set the simp priority slightly lower than default; later more general lemmas will replace it. -@[simp 900] protected lemma nsmul_eq_mul (m n : ℕ) : m • n = m * n := rfl - -section Multiplicative - -lemma toAdd_pow (a : Multiplicative ℕ) (b : ℕ) : toAdd (a ^ b) = toAdd a * b := mul_comm _ _ - -@[simp] lemma ofAdd_mul (a b : ℕ) : ofAdd (a * b) = ofAdd a ^ b := (toAdd_pow _ _).symm - -end Multiplicative - /-! #### Parity -/ variable {m n : ℕ} @@ -158,23 +100,4 @@ example (m n : ℕ) (h : Even m) : ¬Even (n + 3) ↔ Even (m ^ 2 + m + n) := by -- Porting note: the `simp` lemmas about `bit*` no longer apply. example : ¬Even 25394535 := by decide -/-! #### Units -/ - -lemma units_eq_one (u : ℕˣ) : u = 1 := Units.ext <| Nat.eq_one_of_dvd_one ⟨u.inv, u.val_inv.symm⟩ - -lemma addUnits_eq_zero (u : AddUnits ℕ) : u = 0 := - AddUnits.ext <| (Nat.eq_zero_of_add_eq_zero u.val_neg).1 - -@[simp] protected lemma isUnit_iff {n : ℕ} : IsUnit n ↔ n = 1 where - mp := by rintro ⟨u, rfl⟩; obtain rfl := Nat.units_eq_one u; rfl - mpr h := h.symm ▸ ⟨1, rfl⟩ - -instance unique_units : Unique ℕˣ where - default := 1 - uniq := Nat.units_eq_one - -instance unique_addUnits : Unique (AddUnits ℕ) where - default := 0 - uniq := Nat.addUnits_eq_zero - end Nat diff --git a/Mathlib/Algebra/Group/Nat/TypeTags.lean b/Mathlib/Algebra/Group/Nat/TypeTags.lean new file mode 100644 index 0000000000000..a312f69a4aab7 --- /dev/null +++ b/Mathlib/Algebra/Group/Nat/TypeTags.lean @@ -0,0 +1,24 @@ +/- +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.Algebra.Group.Nat.Basic +import Mathlib.Algebra.Group.TypeTags.Basic + +/-! +# Lemmas about `Multiplicative ℕ` +-/ + +assert_not_exists MonoidWithZero +assert_not_exists DenselyOrdered + +open Multiplicative + +namespace Nat + +lemma toAdd_pow (a : Multiplicative ℕ) (b : ℕ) : (a ^ b).toAdd = a.toAdd * b := mul_comm _ _ + +@[simp] lemma ofAdd_mul (a b : ℕ) : ofAdd (a * b) = ofAdd a ^ b := (toAdd_pow _ _).symm + +end Nat diff --git a/Mathlib/Algebra/Group/Nat/Units.lean b/Mathlib/Algebra/Group/Nat/Units.lean new file mode 100644 index 0000000000000..edc5970d8d2e4 --- /dev/null +++ b/Mathlib/Algebra/Group/Nat/Units.lean @@ -0,0 +1,38 @@ +/- +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.Algebra.Group.Nat.Basic +import Mathlib.Algebra.Group.Units.Defs +import Mathlib.Logic.Unique + +/-! +# The unit of the natural numbers +-/ + +assert_not_exists MonoidWithZero +assert_not_exists DenselyOrdered + +namespace Nat + +/-! #### Units -/ + +lemma units_eq_one (u : ℕˣ) : u = 1 := Units.ext <| Nat.eq_one_of_dvd_one ⟨u.inv, u.val_inv.symm⟩ + +lemma addUnits_eq_zero (u : AddUnits ℕ) : u = 0 := + AddUnits.ext <| (Nat.eq_zero_of_add_eq_zero u.val_neg).1 + +@[simp] protected lemma isUnit_iff {n : ℕ} : IsUnit n ↔ n = 1 where + mp := by rintro ⟨u, rfl⟩; obtain rfl := Nat.units_eq_one u; rfl + mpr h := h.symm ▸ ⟨1, rfl⟩ + +instance unique_units : Unique ℕˣ where + default := 1 + uniq := Nat.units_eq_one + +instance unique_addUnits : Unique (AddUnits ℕ) where + default := 0 + uniq := Nat.addUnits_eq_zero + +end Nat diff --git a/Mathlib/Algebra/Group/Operations.lean b/Mathlib/Algebra/Group/Operations.lean new file mode 100644 index 0000000000000..dcc6957a258a7 --- /dev/null +++ b/Mathlib/Algebra/Group/Operations.lean @@ -0,0 +1,215 @@ +/- +Copyright (c) 2014 Jeremy Avigad. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Jeremy Avigad, Leonardo de Moura, Simon Hudon, Mario Carneiro +-/ + +import Mathlib.Tactic.Lemma +import Mathlib.Tactic.TypeStar +import Mathlib.Tactic.ToAdditive +import Mathlib.Util.AssertExists + +/-! +# Typeclasses for algebraic operations + +Notation typeclass for `Inv`, the multiplicative analogue of `Neg`. + +We also introduce notation classes `SMul` and `VAdd` for multiplicative and additive +actions. + +`SMul` is typically, but not exclusively, used for scalar multiplication-like operators. +See the module `Algebra.AddTorsor` for a motivating example for the name `VAdd` (vector addition). + +## Notation + +- `a • b` is used as notation for `HSMul.hSMul a b`. +- `a +ᵥ b` is used as notation for `HVAdd.hVAdd a b`. + +-/ + +assert_not_exists One +assert_not_exists Function.Injective + +universe u v w + + +/-- +The notation typeclass for heterogeneous additive actions. +This enables the notation `a +ᵥ b : γ` where `a : α`, `b : β`. +-/ +class HVAdd (α : Type u) (β : Type v) (γ : outParam (Type w)) where + /-- `a +ᵥ b` computes the sum of `a` and `b`. + The meaning of this notation is type-dependent. -/ + hVAdd : α → β → γ + +/-- +The notation typeclass for heterogeneous scalar multiplication. +This enables the notation `a • b : γ` where `a : α`, `b : β`. + +It is assumed to represent a left action in some sense. +The notation `a • b` is augmented with a macro (below) to have it elaborate as a left action. +Only the `b` argument participates in the elaboration algorithm: the algorithm uses the type of `b` +when calculating the type of the surrounding arithmetic expression +and it tries to insert coercions into `b` to get some `b'` +such that `a • b'` has the same type as `b'`. +See the module documentation near the macro for more details. +-/ +class HSMul (α : Type u) (β : Type v) (γ : outParam (Type w)) where + /-- `a • b` computes the product of `a` and `b`. + The meaning of this notation is type-dependent, but it is intended to be used for left actions. -/ + hSMul : α → β → γ + +attribute [notation_class smul Simps.copySecond] HSMul +attribute [notation_class nsmul Simps.nsmulArgs] HSMul +attribute [notation_class zsmul Simps.zsmulArgs] HSMul + +/-- Type class for the `+ᵥ` notation. -/ +class VAdd (G : Type u) (P : Type v) where + /-- `a +ᵥ b` computes the sum of `a` and `b`. The meaning of this notation is type-dependent, + but it is intended to be used for left actions. -/ + vadd : G → P → P + +/-- Type class for the `-ᵥ` notation. -/ +class VSub (G : outParam Type*) (P : Type*) where + /-- `a -ᵥ b` computes the difference of `a` and `b`. The meaning of this notation is + type-dependent, but it is intended to be used for additive torsors. -/ + vsub : P → P → G + +/-- Typeclass for types with a scalar multiplication operation, denoted `•` (`\bu`) -/ +@[to_additive (attr := ext)] +class SMul (M : Type u) (α : Type v) where + /-- `a • b` computes the product of `a` and `b`. The meaning of this notation is type-dependent, + but it is intended to be used for left actions. -/ + smul : M → α → α + +@[inherit_doc] infixl:65 " +ᵥ " => HVAdd.hVAdd +@[inherit_doc] infixl:65 " -ᵥ " => VSub.vsub +@[inherit_doc] infixr:73 " • " => HSMul.hSMul + +/-! +We have a macro to make `x • y` notation participate in the expression tree elaborator, +like other arithmetic expressions such as `+`, `*`, `/`, `^`, `=`, inequalities, etc. +The macro is using the `leftact%` elaborator introduced in +[this RFC](https://github.com/leanprover/lean4/issues/2854). + +As a concrete example of the effect of this macro, consider +```lean +variable [Ring R] [AddCommMonoid M] [Module R M] (r : R) (N : Submodule R M) (m : M) (n : N) +#check m + r • n +``` +Without the macro, the expression would elaborate as `m + ↑(r • n : ↑N) : M`. +With the macro, the expression elaborates as `m + r • (↑n : M) : M`. +To get the first interpretation, one can write `m + (r • n :)`. + +Here is a quick review of the expression tree elaborator: +1. It builds up an expression tree of all the immediately accessible operations + that are marked with `binop%`, `unop%`, `leftact%`, `rightact%`, `binrel%`, etc. +2. It elaborates every leaf term of this tree + (without an expected type, so as if it were temporarily wrapped in `(... :)`). +3. Using the types of each elaborated leaf, it computes a supremum type they can all be + coerced to, if such a supremum exists. +4. It inserts coercions around leaf terms wherever needed. + +The hypothesis is that individual expression trees tend to be calculations with respect +to a single algebraic structure. + +Note(kmill): If we were to remove `HSMul` and switch to using `SMul` directly, +then the expression tree elaborator would not be able to insert coercions within the right operand; +they would likely appear as `↑(x • y)` rather than `x • ↑y`, unlike other arithmetic operations. +-/ + +@[inherit_doc HSMul.hSMul] +macro_rules | `($x • $y) => `(leftact% HSMul.hSMul $x $y) + +attribute [to_additive existing] Mul Div HMul instHMul HDiv instHDiv HSMul +attribute [to_additive (reorder := 1 2) SMul] Pow +attribute [to_additive (reorder := 1 2)] HPow +attribute [to_additive existing (reorder := 1 2, 5 6) hSMul] HPow.hPow +attribute [to_additive existing (reorder := 1 2, 4 5) smul] Pow.pow + +@[to_additive (attr := default_instance)] +instance instHSMul {α β} [SMul α β] : HSMul α β β where + hSMul := SMul.smul + +@[to_additive] +theorem SMul.smul_eq_hSMul {α β} [SMul α β] : (SMul.smul : α → β → β) = HSMul.hSMul := rfl + +attribute [to_additive existing (reorder := 1 2)] instHPow + +variable {G : Type*} + +/-- Class of types that have an inversion operation. -/ +@[to_additive, notation_class] +class Inv (α : Type u) where + /-- Invert an element of α. -/ + inv : α → α + +@[inherit_doc] +postfix:max "⁻¹" => Inv.inv + +section ite +variable {α : Type*} (P : Prop) [Decidable P] + +section Mul +variable [Mul α] + +@[to_additive] +lemma mul_dite (a : α) (b : P → α) (c : ¬ P → α) : + (a * if h : P then b h else c h) = if h : P then a * b h else a * c h := by split <;> rfl + +@[to_additive] +lemma mul_ite (a b c : α) : (a * if P then b else c) = if P then a * b else a * c := mul_dite .. + +@[to_additive] +lemma dite_mul (a : P → α) (b : ¬ P → α) (c : α) : + (if h : P then a h else b h) * c = if h : P then a h * c else b h * c := by split <;> rfl + +@[to_additive] +lemma ite_mul (a b c : α) : (if P then a else b) * c = if P then a * c else b * c := dite_mul .. + +-- We make `mul_ite` and `ite_mul` simp lemmas, but not `add_ite` or `ite_add`. +-- The problem we're trying to avoid is dealing with sums of the form `∑ x ∈ s, (f x + ite P 1 0)`, +-- in which `add_ite` followed by `sum_ite` would needlessly slice up +-- the `f x` terms according to whether `P` holds at `x`. +-- There doesn't appear to be a corresponding difficulty so far with `mul_ite` and `ite_mul`. +attribute [simp] mul_dite dite_mul mul_ite ite_mul + +@[to_additive] +lemma dite_mul_dite (a : P → α) (b : ¬ P → α) (c : P → α) (d : ¬ P → α) : + ((if h : P then a h else b h) * if h : P then c h else d h) = + if h : P then a h * c h else b h * d h := by split <;> rfl + +@[to_additive] +lemma ite_mul_ite (a b c d : α) : + ((if P then a else b) * if P then c else d) = if P then a * c else b * d := by split <;> rfl + +end Mul + +section Div +variable [Div α] + +@[to_additive] +lemma div_dite (a : α) (b : P → α) (c : ¬ P → α) : + (a / if h : P then b h else c h) = if h : P then a / b h else a / c h := by split <;> rfl + +@[to_additive] +lemma div_ite (a b c : α) : (a / if P then b else c) = if P then a / b else a / c := div_dite .. + +@[to_additive] +lemma dite_div (a : P → α) (b : ¬ P → α) (c : α) : + (if h : P then a h else b h) / c = if h : P then a h / c else b h / c := by split <;> rfl + +@[to_additive] +lemma ite_div (a b c : α) : (if P then a else b) / c = if P then a / c else b / c := dite_div .. + +@[to_additive] +lemma dite_div_dite (a : P → α) (b : ¬ P → α) (c : P → α) (d : ¬ P → α) : + ((if h : P then a h else b h) / if h : P then c h else d h) = + if h : P then a h / c h else b h / d h := by split <;> rfl + +@[to_additive] +lemma ite_div_ite (a b c d : α) : + ((if P then a else b) / if P then c else d) = if P then a / c else b / d := dite_div_dite .. + +end Div +end ite diff --git a/Mathlib/Algebra/Group/Pointwise/Finset/Basic.lean b/Mathlib/Algebra/Group/Pointwise/Finset/Basic.lean index a7cd803e05c07..4330e3cf9abae 100644 --- a/Mathlib/Algebra/Group/Pointwise/Finset/Basic.lean +++ b/Mathlib/Algebra/Group/Pointwise/Finset/Basic.lean @@ -5,11 +5,11 @@ Authors: Floris van Doorn, Yaël Dillies -/ import Mathlib.Algebra.BigOperators.Group.Finset import Mathlib.Algebra.Group.Action.Pi +import Mathlib.Algebra.Group.Pointwise.Set.Finite +import Mathlib.Algebra.Group.Pointwise.Set.ListOfFn import Mathlib.Data.Finset.Density import Mathlib.Data.Finset.Max import Mathlib.Data.Finset.NAry -import Mathlib.Data.Set.Pointwise.Finite -import Mathlib.Data.Set.Pointwise.ListOfFn import Mathlib.Data.Set.Pointwise.SMul /-! diff --git a/Mathlib/Algebra/Group/Pointwise/Finset/Interval.lean b/Mathlib/Algebra/Group/Pointwise/Finset/Interval.lean index 479121a3d4a1b..d06c3e7259b13 100644 --- a/Mathlib/Algebra/Group/Pointwise/Finset/Interval.lean +++ b/Mathlib/Algebra/Group/Pointwise/Finset/Interval.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Eric Wieser -/ import Mathlib.Algebra.Group.Pointwise.Finset.Basic -import Mathlib.Data.Set.Pointwise.Interval +import Mathlib.Algebra.Order.Group.Pointwise.Interval import Mathlib.Order.Interval.Finset.Defs /-! # Pointwise operations on intervals diff --git a/Mathlib/Data/Set/Pointwise/BigOperators.lean b/Mathlib/Algebra/Group/Pointwise/Set/BigOperators.lean similarity index 100% rename from Mathlib/Data/Set/Pointwise/BigOperators.lean rename to Mathlib/Algebra/Group/Pointwise/Set/BigOperators.lean diff --git a/Mathlib/Algebra/Group/Pointwise/Set/Card.lean b/Mathlib/Algebra/Group/Pointwise/Set/Card.lean index 80a073b792385..d31f9773753a2 100644 --- a/Mathlib/Algebra/Group/Pointwise/Set/Card.lean +++ b/Mathlib/Algebra/Group/Pointwise/Set/Card.lean @@ -3,7 +3,8 @@ 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.Data.Set.Pointwise.Finite +import Mathlib.Algebra.Group.Pointwise.Set.Finite +import Mathlib.Data.Set.Card import Mathlib.SetTheory.Cardinal.Finite /-! @@ -32,12 +33,18 @@ lemma natCard_mul_le : Nat.card (s * t) ≤ Nat.card s * Nat.card t := by refine Cardinal.toNat_le_toNat Cardinal.mk_mul_le ?_ aesop (add simp [Cardinal.mul_lt_aleph0_iff, finite_mul]) -@[to_additive (attr := deprecated (since := "2024-09-30"))] alias card_mul_le := natCard_mul_le +@[to_additive] alias card_mul_le := natCard_mul_le + +-- `alias` doesn't add the deprecation suggestion to the `to_additive` version +-- see https://github.com/leanprover-community/mathlib4/issues/19424 +attribute [deprecated natCard_mul_le (since := "2024-09-30")] card_mul_le +attribute [deprecated natCard_add_le (since := "2024-09-30")] card_add_le + end Mul section InvolutiveInv -variable [InvolutiveInv G] {s t : Set G} +variable [InvolutiveInv G] @[to_additive (attr := simp)] lemma _root_.Cardinal.mk_inv (s : Set G) : #↥(s⁻¹) = #s := by @@ -47,7 +54,18 @@ lemma _root_.Cardinal.mk_inv (s : Set G) : #↥(s⁻¹) = #s := by lemma natCard_inv (s : Set G) : Nat.card ↥(s⁻¹) = Nat.card s := by rw [← image_inv, Nat.card_image_of_injective inv_injective] -@[to_additive (attr := deprecated (since := "2024-09-30"))] alias card_inv := natCard_inv +@[to_additive] alias card_inv := natCard_inv + +-- `alias` doesn't add the deprecation suggestion to the `to_additive` version +-- see https://github.com/leanprover-community/mathlib4/issues/19424 +attribute [deprecated natCard_inv (since := "2024-09-30")] card_inv +attribute [deprecated natCard_neg (since := "2024-09-30")] card_neg + +@[to_additive (attr := simp)] +lemma encard_inv (s : Set G) : s⁻¹.encard = s.encard := by simp [encard, PartENat.card] + +@[to_additive (attr := simp)] +lemma ncard_inv (s : Set G) : s⁻¹.ncard = s.ncard := by simp [ncard] end InvolutiveInv @@ -67,7 +85,12 @@ variable [Group G] {s t : Set G} lemma natCard_div_le : Nat.card (s / t) ≤ Nat.card s * Nat.card t := by rw [div_eq_mul_inv, ← natCard_inv t]; exact natCard_mul_le -@[to_additive (attr := deprecated (since := "2024-09-30"))] alias card_div_le := natCard_div_le +@[to_additive] alias card_div_le := natCard_div_le + +-- `alias` doesn't add the deprecation suggestion to the `to_additive` version +-- see https://github.com/leanprover-community/mathlib4/issues/19424 +attribute [deprecated natCard_div_le (since := "2024-09-30")] card_div_le +attribute [deprecated natCard_sub_le (since := "2024-09-30")] card_sub_le variable [MulAction G α] @@ -79,8 +102,20 @@ lemma _root_.Cardinal.mk_smul_set (a : G) (s : Set α) : #↥(a • s) = #s := lemma natCard_smul_set (a : G) (s : Set α) : Nat.card ↥(a • s) = Nat.card s := Nat.card_image_of_injective (MulAction.injective a) _ -@[to_additive (attr := deprecated (since := "2024-09-30"))] +@[to_additive] alias card_smul_set := Cardinal.mk_smul_set +-- `alias` doesn't add the deprecation suggestion to the `to_additive` version +-- see https://github.com/leanprover-community/mathlib4/issues/19424 +attribute [deprecated Cardinal.mk_smul_set (since := "2024-09-30")] card_smul_set +attribute [deprecated Cardinal.mk_vadd_set (since := "2024-09-30")] card_vadd_set + +@[to_additive (attr := simp)] +lemma encard_smul_set (a : G) (s : Set α) : (a • s).encard = s.encard := by + simp [encard, PartENat.card] + +@[to_additive (attr := simp)] +lemma ncard_smul_set (a : G) (s : Set α) : (a • s).ncard = s.ncard := by simp [ncard] + end Group end Set diff --git a/Mathlib/Data/Set/Pointwise/Finite.lean b/Mathlib/Algebra/Group/Pointwise/Set/Finite.lean similarity index 100% rename from Mathlib/Data/Set/Pointwise/Finite.lean rename to Mathlib/Algebra/Group/Pointwise/Set/Finite.lean diff --git a/Mathlib/Data/Set/Pointwise/ListOfFn.lean b/Mathlib/Algebra/Group/Pointwise/Set/ListOfFn.lean similarity index 100% rename from Mathlib/Data/Set/Pointwise/ListOfFn.lean rename to Mathlib/Algebra/Group/Pointwise/Set/ListOfFn.lean diff --git a/Mathlib/Algebra/Group/Prod.lean b/Mathlib/Algebra/Group/Prod.lean index 02781d10d0067..e6e9519ae6483 100644 --- a/Mathlib/Algebra/Group/Prod.lean +++ b/Mathlib/Algebra/Group/Prod.lean @@ -149,6 +149,8 @@ theorem mk_div_mk [Div G] [Div H] (x₁ x₂ : G) (y₁ y₂ : H) : theorem swap_div [Div G] [Div H] (a b : G × H) : (a / b).swap = a.swap / b.swap := rfl +@[to_additive] lemma div_def [Div M] [Div N] (a b : M × N) : a / b = (a.1 / b.1, a.2 / b.2) := rfl + @[to_additive] instance instSemigroup [Semigroup M] [Semigroup N] : Semigroup (M × N) := { mul_assoc := fun _ _ _ => mk.inj_iff.mpr ⟨mul_assoc _ _ _, mul_assoc _ _ _⟩ } diff --git a/Mathlib/Algebra/Group/Subgroup/Basic.lean b/Mathlib/Algebra/Group/Subgroup/Basic.lean index 6fc988e05de4b..c6b11e2b701e3 100644 --- a/Mathlib/Algebra/Group/Subgroup/Basic.lean +++ b/Mathlib/Algebra/Group/Subgroup/Basic.lean @@ -5,20 +5,13 @@ Authors: Kexing Ying -/ import Mathlib.Algebra.Group.Conj import Mathlib.Algebra.Group.Pi.Lemmas -import Mathlib.Algebra.Group.Submonoid.Operations -import Mathlib.Algebra.Group.Subgroup.Defs -import Mathlib.Data.Set.Image -import Mathlib.Tactic.ApplyFun +import Mathlib.Algebra.Group.Subgroup.Ker /-! -# Subgroups +# Basic results on subgroups -We prove subgroups of a group form a complete lattice, and results about images and preimages of -subgroups under group homomorphisms. The bundled subgroups use bundled monoid homomorphisms. - -There are also theorems about the subgroups generated by an element or a subset of a group, -defined both inductively and as the infimum of the set of subgroups containing a given -element/subset. +We prove basic results on the definitions of subgroups. The bundled subgroups use bundled monoid +homomorphisms. Special thanks goes to Amelia Livingston and Yury Kudryashov for their help and inspiration. @@ -40,31 +33,9 @@ Notation used here: Definitions in the file: -* `CompleteLattice (Subgroup G)` : the subgroups of `G` form a complete lattice - -* `Subgroup.closure k` : the minimal subgroup that includes the set `k` - -* `Subgroup.subtype` : the natural group homomorphism from a subgroup of group `G` to `G` - -* `Subgroup.gi` : `closure` forms a Galois insertion with the coercion to set - -* `Subgroup.comap H f` : the preimage of a subgroup `H` along the group homomorphism `f` is also a - subgroup - -* `Subgroup.map f H` : the image of a subgroup `H` along the group homomorphism `f` is also a - subgroup - * `Subgroup.prod H K` : the product of subgroups `H`, `K` of groups `G`, `N` respectively, `H × K` is a subgroup of `G × N` -* `MonoidHom.range f` : the range of the group homomorphism `f` is a subgroup - -* `MonoidHom.ker f` : the kernel of a group homomorphism `f` is the subgroup of elements `x : G` - such that `f x = 1` - -* `MonoidHom.eqLocus f g` : given group homomorphisms `f`, `g`, the elements of `G` such that - `f x = g x` form a subgroup of `G` - ## Implementation notes Subgroup inclusion is denoted `≤` rather than `⊆`, although `∈` is defined as @@ -96,43 +67,6 @@ theorem div_mem_comm_iff {a b : G} : a / b ∈ H ↔ b / a ∈ H := end SubgroupClass -/-! -### Conversion to/from `Additive`/`Multiplicative` --/ - - -section mul_add - -/-- Subgroups of a group `G` are isomorphic to additive subgroups of `Additive G`. -/ -@[simps!] -def Subgroup.toAddSubgroup : Subgroup G ≃o AddSubgroup (Additive G) where - toFun S := { Submonoid.toAddSubmonoid S.toSubmonoid with neg_mem' := S.inv_mem' } - invFun S := { AddSubmonoid.toSubmonoid S.toAddSubmonoid with inv_mem' := S.neg_mem' } - left_inv x := by cases x; rfl - right_inv x := by cases x; rfl - map_rel_iff' := Iff.rfl - -/-- Additive subgroup of an additive group `Additive G` are isomorphic to subgroup of `G`. -/ -abbrev AddSubgroup.toSubgroup' : AddSubgroup (Additive G) ≃o Subgroup G := - Subgroup.toAddSubgroup.symm - -/-- Additive subgroups of an additive group `A` are isomorphic to subgroups of `Multiplicative A`. --/ -@[simps!] -def AddSubgroup.toSubgroup : AddSubgroup A ≃o Subgroup (Multiplicative A) where - toFun S := { AddSubmonoid.toSubmonoid S.toAddSubmonoid with inv_mem' := S.neg_mem' } - invFun S := { Submonoid.toAddSubmonoid S.toSubmonoid with neg_mem' := S.inv_mem' } - left_inv x := by cases x; rfl - right_inv x := by cases x; rfl - map_rel_iff' := Iff.rfl - -/-- Subgroups of an additive group `Multiplicative A` are isomorphic to additive subgroups of `A`. --/ -abbrev Subgroup.toAddSubgroup' : Subgroup (Multiplicative A) ≃o AddSubgroup A := - AddSubgroup.toSubgroup.symm - -end mul_add - namespace Subgroup variable (H K : Subgroup G) @@ -141,691 +75,11 @@ variable (H K : Subgroup G) protected theorem div_mem_comm_iff {a b : G} : a / b ∈ H ↔ b / a ∈ H := div_mem_comm_iff -/-- The subgroup `G` of the group `G`. -/ -@[to_additive "The `AddSubgroup G` of the `AddGroup G`."] -instance : Top (Subgroup G) := - ⟨{ (⊤ : Submonoid G) with inv_mem' := fun _ => Set.mem_univ _ }⟩ - -/-- The top subgroup is isomorphic to the group. - -This is the group version of `Submonoid.topEquiv`. -/ -@[to_additive (attr := simps!) - "The top additive subgroup is isomorphic to the additive group. - - This is the additive group version of `AddSubmonoid.topEquiv`."] -def topEquiv : (⊤ : Subgroup G) ≃* G := - Submonoid.topEquiv - -/-- The trivial subgroup `{1}` of a group `G`. -/ -@[to_additive "The trivial `AddSubgroup` `{0}` of an `AddGroup` `G`."] -instance : Bot (Subgroup G) := - ⟨{ (⊥ : Submonoid G) with inv_mem' := by simp}⟩ - -@[to_additive] -instance : Inhabited (Subgroup G) := - ⟨⊥⟩ - -@[to_additive (attr := simp)] -theorem mem_bot {x : G} : x ∈ (⊥ : Subgroup G) ↔ x = 1 := - Iff.rfl - -@[to_additive (attr := simp)] -theorem mem_top (x : G) : x ∈ (⊤ : Subgroup G) := - Set.mem_univ x - -@[to_additive (attr := simp)] -theorem coe_top : ((⊤ : Subgroup G) : Set G) = Set.univ := - rfl - -@[to_additive (attr := simp)] -theorem coe_bot : ((⊥ : Subgroup G) : Set G) = {1} := - rfl - -@[to_additive] -instance : Unique (⊥ : Subgroup G) := - ⟨⟨1⟩, fun g => Subtype.ext g.2⟩ - -@[to_additive (attr := simp)] -theorem top_toSubmonoid : (⊤ : Subgroup G).toSubmonoid = ⊤ := - rfl - -@[to_additive (attr := simp)] -theorem bot_toSubmonoid : (⊥ : Subgroup G).toSubmonoid = ⊥ := - rfl - -@[to_additive] -theorem eq_bot_iff_forall : H = ⊥ ↔ ∀ x ∈ H, x = (1 : G) := - toSubmonoid_injective.eq_iff.symm.trans <| Submonoid.eq_bot_iff_forall _ - -@[to_additive] -theorem eq_bot_of_subsingleton [Subsingleton H] : H = ⊥ := by - rw [Subgroup.eq_bot_iff_forall] - intro y hy - rw [← Subgroup.coe_mk H y hy, Subsingleton.elim (⟨y, hy⟩ : H) 1, Subgroup.coe_one] - -@[to_additive (attr := simp, norm_cast)] -theorem coe_eq_univ {H : Subgroup G} : (H : Set G) = Set.univ ↔ H = ⊤ := - (SetLike.ext'_iff.trans (by rfl)).symm - -@[to_additive] -theorem coe_eq_singleton {H : Subgroup G} : (∃ g : G, (H : Set G) = {g}) ↔ H = ⊥ := - ⟨fun ⟨g, hg⟩ => - haveI : Subsingleton (H : Set G) := by - rw [hg] - infer_instance - H.eq_bot_of_subsingleton, - fun h => ⟨1, SetLike.ext'_iff.mp h⟩⟩ - -@[to_additive] -theorem nontrivial_iff_exists_ne_one (H : Subgroup G) : Nontrivial H ↔ ∃ x ∈ H, x ≠ (1 : G) := by - rw [Subtype.nontrivial_iff_exists_ne (fun x => x ∈ H) (1 : H)] - simp - -@[to_additive] -theorem exists_ne_one_of_nontrivial (H : Subgroup G) [Nontrivial H] : - ∃ x ∈ H, x ≠ 1 := by - rwa [← Subgroup.nontrivial_iff_exists_ne_one] - -@[to_additive] -theorem nontrivial_iff_ne_bot (H : Subgroup G) : Nontrivial H ↔ H ≠ ⊥ := by - rw [nontrivial_iff_exists_ne_one, ne_eq, eq_bot_iff_forall] - simp only [ne_eq, not_forall, exists_prop] - -/-- A subgroup is either the trivial subgroup or nontrivial. -/ -@[to_additive "A subgroup is either the trivial subgroup or nontrivial."] -theorem bot_or_nontrivial (H : Subgroup G) : H = ⊥ ∨ Nontrivial H := by - have := nontrivial_iff_ne_bot H - tauto - -/-- A subgroup is either the trivial subgroup or contains a non-identity element. -/ -@[to_additive "A subgroup is either the trivial subgroup or contains a nonzero element."] -theorem bot_or_exists_ne_one (H : Subgroup G) : H = ⊥ ∨ ∃ x ∈ H, x ≠ (1 : G) := by - convert H.bot_or_nontrivial - rw [nontrivial_iff_exists_ne_one] - -@[to_additive] -lemma ne_bot_iff_exists_ne_one {H : Subgroup G} : H ≠ ⊥ ↔ ∃ a : ↥H, a ≠ 1 := by - rw [← nontrivial_iff_ne_bot, nontrivial_iff_exists_ne_one] - simp only [ne_eq, Subtype.exists, mk_eq_one, exists_prop] - -/-- The inf of two subgroups is their intersection. -/ -@[to_additive "The inf of two `AddSubgroup`s is their intersection."] -instance : Min (Subgroup G) := - ⟨fun H₁ H₂ => - { H₁.toSubmonoid ⊓ H₂.toSubmonoid with - inv_mem' := fun ⟨hx, hx'⟩ => ⟨H₁.inv_mem hx, H₂.inv_mem hx'⟩ }⟩ - -@[to_additive (attr := simp)] -theorem coe_inf (p p' : Subgroup G) : ((p ⊓ p' : Subgroup G) : Set G) = (p : Set G) ∩ p' := - rfl - -@[to_additive (attr := simp)] -theorem mem_inf {p p' : Subgroup G} {x : G} : x ∈ p ⊓ p' ↔ x ∈ p ∧ x ∈ p' := - Iff.rfl - -@[to_additive] -instance : InfSet (Subgroup G) := - ⟨fun s => - { (⨅ S ∈ s, Subgroup.toSubmonoid S).copy (⋂ S ∈ s, ↑S) (by simp) with - inv_mem' := fun {x} hx => - Set.mem_biInter fun i h => i.inv_mem (by apply Set.mem_iInter₂.1 hx i h) }⟩ - -@[to_additive (attr := simp, norm_cast)] -theorem coe_sInf (H : Set (Subgroup G)) : ((sInf H : Subgroup G) : Set G) = ⋂ s ∈ H, ↑s := - rfl - -@[to_additive (attr := simp)] -theorem mem_sInf {S : Set (Subgroup G)} {x : G} : x ∈ sInf S ↔ ∀ p ∈ S, x ∈ p := - Set.mem_iInter₂ - -@[to_additive] -theorem mem_iInf {ι : Sort*} {S : ι → Subgroup G} {x : G} : (x ∈ ⨅ i, S i) ↔ ∀ i, x ∈ S i := by - simp only [iInf, mem_sInf, Set.forall_mem_range] - -@[to_additive (attr := simp, norm_cast)] -theorem coe_iInf {ι : Sort*} {S : ι → Subgroup G} : (↑(⨅ i, S i) : Set G) = ⋂ i, S i := by - simp only [iInf, coe_sInf, Set.biInter_range] - -/-- Subgroups of a group form a complete lattice. -/ -@[to_additive "The `AddSubgroup`s of an `AddGroup` form a complete lattice."] -instance : CompleteLattice (Subgroup G) := - { completeLatticeOfInf (Subgroup G) fun _s => - IsGLB.of_image SetLike.coe_subset_coe isGLB_biInf with - bot := ⊥ - bot_le := fun S _x hx => (mem_bot.1 hx).symm ▸ S.one_mem - top := ⊤ - le_top := fun _S x _hx => mem_top x - inf := (· ⊓ ·) - le_inf := fun _a _b _c ha hb _x hx => ⟨ha hx, hb hx⟩ - inf_le_left := fun _a _b _x => And.left - inf_le_right := fun _a _b _x => And.right } - -@[to_additive] -theorem mem_sup_left {S T : Subgroup G} : ∀ {x : G}, x ∈ S → x ∈ S ⊔ T := - have : S ≤ S ⊔ T := le_sup_left; fun h ↦ this h - -@[to_additive] -theorem mem_sup_right {S T : Subgroup G} : ∀ {x : G}, x ∈ T → x ∈ S ⊔ T := - have : T ≤ S ⊔ T := le_sup_right; fun h ↦ this h - -@[to_additive] -theorem mul_mem_sup {S T : Subgroup G} {x y : G} (hx : x ∈ S) (hy : y ∈ T) : x * y ∈ S ⊔ T := - (S ⊔ T).mul_mem (mem_sup_left hx) (mem_sup_right hy) - -@[to_additive] -theorem mem_iSup_of_mem {ι : Sort*} {S : ι → Subgroup G} (i : ι) : - ∀ {x : G}, x ∈ S i → x ∈ iSup S := - have : S i ≤ iSup S := le_iSup _ _; fun h ↦ this h - -@[to_additive] -theorem mem_sSup_of_mem {S : Set (Subgroup G)} {s : Subgroup G} (hs : s ∈ S) : - ∀ {x : G}, x ∈ s → x ∈ sSup S := - have : s ≤ sSup S := le_sSup hs; fun h ↦ this h - -@[to_additive (attr := simp)] -theorem subsingleton_iff : Subsingleton (Subgroup G) ↔ Subsingleton G := - ⟨fun _ => - ⟨fun x y => - have : ∀ i : G, i = 1 := fun i => - mem_bot.mp <| Subsingleton.elim (⊤ : Subgroup G) ⊥ ▸ mem_top i - (this x).trans (this y).symm⟩, - fun _ => ⟨fun x y => Subgroup.ext fun i => Subsingleton.elim 1 i ▸ by simp [Subgroup.one_mem]⟩⟩ - -@[to_additive (attr := simp)] -theorem nontrivial_iff : Nontrivial (Subgroup G) ↔ Nontrivial G := - not_iff_not.mp - ((not_nontrivial_iff_subsingleton.trans subsingleton_iff).trans - not_nontrivial_iff_subsingleton.symm) - -@[to_additive] -instance [Subsingleton G] : Unique (Subgroup G) := - ⟨⟨⊥⟩, fun a => @Subsingleton.elim _ (subsingleton_iff.mpr ‹_›) a _⟩ - -@[to_additive] -instance [Nontrivial G] : Nontrivial (Subgroup G) := - nontrivial_iff.mpr ‹_› - -@[to_additive] -theorem eq_top_iff' : H = ⊤ ↔ ∀ x : G, x ∈ H := - eq_top_iff.trans ⟨fun h m => h <| mem_top m, fun h m _ => h m⟩ - -/-- The `Subgroup` generated by a set. -/ -@[to_additive "The `AddSubgroup` generated by a set"] -def closure (k : Set G) : Subgroup G := - sInf { K | k ⊆ K } - variable {k : Set G} -@[to_additive] -theorem mem_closure {x : G} : x ∈ closure k ↔ ∀ K : Subgroup G, k ⊆ K → x ∈ K := - mem_sInf - -/-- The subgroup generated by a set includes the set. -/ -@[to_additive (attr := simp, aesop safe 20 apply (rule_sets := [SetLike])) - "The `AddSubgroup` generated by a set includes the set."] -theorem subset_closure : k ⊆ closure k := fun _ hx => mem_closure.2 fun _ hK => hK hx - -@[to_additive] -theorem not_mem_of_not_mem_closure {P : G} (hP : P ∉ closure k) : P ∉ k := fun h => - hP (subset_closure h) - open Set -/-- A subgroup `K` includes `closure k` if and only if it includes `k`. -/ -@[to_additive (attr := simp) - "An additive subgroup `K` includes `closure k` if and only if it includes `k`"] -theorem closure_le : closure k ≤ K ↔ k ⊆ K := - ⟨Subset.trans subset_closure, fun h => sInf_le h⟩ - -@[to_additive] -theorem closure_eq_of_le (h₁ : k ⊆ K) (h₂ : K ≤ closure k) : closure k = K := - le_antisymm ((closure_le <| K).2 h₁) h₂ - -/-- An induction principle for closure membership. If `p` holds for `1` and all elements of `k`, and -is preserved under multiplication and inverse, then `p` holds for all elements of the closure -of `k`. - -See also `Subgroup.closure_induction_left` and `Subgroup.closure_induction_right` for versions that -only require showing `p` is preserved by multiplication by elements in `k`. -/ -@[to_additive (attr := elab_as_elim) - "An induction principle for additive closure membership. If `p` - holds for `0` and all elements of `k`, and is preserved under addition and inverses, then `p` - holds for all elements of the additive closure of `k`. - - See also `AddSubgroup.closure_induction_left` and `AddSubgroup.closure_induction_left` for - versions that only require showing `p` is preserved by addition by elements in `k`."] -theorem closure_induction {p : (g : G) → g ∈ closure k → Prop} - (mem : ∀ x (hx : x ∈ k), p x (subset_closure hx)) (one : p 1 (one_mem _)) - (mul : ∀ x y hx hy, p x hx → p y hy → p (x * y) (mul_mem hx hy)) - (inv : ∀ x hx, p x hx → p x⁻¹ (inv_mem hx)) {x} (hx : x ∈ closure k) : p x hx := - let K : Subgroup G := - { carrier := { x | ∃ hx, p x hx } - mul_mem' := fun ⟨_, ha⟩ ⟨_, hb⟩ ↦ ⟨_, mul _ _ _ _ ha hb⟩ - one_mem' := ⟨_, one⟩ - inv_mem' := fun ⟨_, hb⟩ ↦ ⟨_, inv _ _ hb⟩ } - closure_le (K := K) |>.mpr (fun y hy ↦ ⟨subset_closure hy, mem y hy⟩) hx |>.elim fun _ ↦ id - -@[deprecated closure_induction (since := "2024-10-10")] -alias closure_induction' := closure_induction - -/-- 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 : (x y : G) → x ∈ closure k → y ∈ closure k → Prop} - (mem : ∀ (x) (y) (hx : x ∈ k) (hy : y ∈ k), p x y (subset_closure hx) (subset_closure hy)) - (one_left : ∀ x hx, p 1 x (one_mem _) hx) (one_right : ∀ x hx, p x 1 hx (one_mem _)) - (mul_left : ∀ x y z hx hy hz, p x z hx hz → p y z hy hz → p (x * y) z (mul_mem hx hy) hz) - (mul_right : ∀ y z x hy hz hx, p x y hx hy → p x z hx hz → p x (y * z) hx (mul_mem hy hz)) - (inv_left : ∀ x y hx hy, p x y hx hy → p x⁻¹ y (inv_mem hx) hy) - (inv_right : ∀ x y hx hy, p x y hx hy → p x y⁻¹ hx (inv_mem hy)) - {x y : G} (hx : x ∈ closure k) (hy : y ∈ closure k) : p x y hx hy := by - induction hy using closure_induction with - | mem z hz => induction hx using closure_induction with - | mem _ h => exact mem _ _ h hz - | one => exact one_left _ (subset_closure hz) - | mul _ _ _ _ h₁ h₂ => exact mul_left _ _ _ _ _ _ h₁ h₂ - | inv _ _ h => exact inv_left _ _ _ _ h - | one => exact one_right x hx - | mul _ _ _ _ h₁ h₂ => exact mul_right _ _ _ _ _ hx h₁ h₂ - | inv _ _ h => exact inv_right _ _ _ _ h - -@[to_additive (attr := simp)] -theorem closure_closure_coe_preimage {k : Set G} : closure (((↑) : closure k → G) ⁻¹' k) = ⊤ := - eq_top_iff.2 fun x _ ↦ Subtype.recOn x fun _ hx' ↦ - closure_induction (fun _ h ↦ subset_closure h) (one_mem _) (fun _ _ _ _ ↦ mul_mem) - (fun _ _ ↦ inv_mem) hx' - -variable (G) - -/-- `closure` forms a Galois insertion with the coercion to set. -/ -@[to_additive "`closure` forms a Galois insertion with the coercion to set."] -protected def gi : GaloisInsertion (@closure G _) (↑) where - choice s _ := closure s - gc s t := @closure_le _ _ t s - le_l_u _s := subset_closure - choice_eq _s _h := rfl - -variable {G} - -/-- Subgroup closure of a set is monotone in its argument: if `h ⊆ k`, -then `closure h ≤ closure k`. -/ -@[to_additive - "Additive subgroup closure of a set is monotone in its argument: if `h ⊆ k`, - then `closure h ≤ closure k`"] -theorem closure_mono ⦃h k : Set G⦄ (h' : h ⊆ k) : closure h ≤ closure k := - (Subgroup.gi G).gc.monotone_l h' - -/-- Closure of a subgroup `K` equals `K`. -/ -@[to_additive (attr := simp) "Additive closure of an additive subgroup `K` equals `K`"] -theorem closure_eq : closure (K : Set G) = K := - (Subgroup.gi G).l_u_eq K - -@[to_additive (attr := simp)] -theorem closure_empty : closure (∅ : Set G) = ⊥ := - (Subgroup.gi G).gc.l_bot - -@[to_additive (attr := simp)] -theorem closure_univ : closure (univ : Set G) = ⊤ := - @coe_top G _ ▸ closure_eq ⊤ - -@[to_additive] -theorem closure_union (s t : Set G) : closure (s ∪ t) = closure s ⊔ closure t := - (Subgroup.gi G).gc.l_sup - -@[to_additive] -theorem sup_eq_closure (H H' : Subgroup G) : H ⊔ H' = closure ((H : Set G) ∪ (H' : Set G)) := by - simp_rw [closure_union, closure_eq] - -@[to_additive] -theorem closure_iUnion {ι} (s : ι → Set G) : closure (⋃ i, s i) = ⨆ i, closure (s i) := - (Subgroup.gi G).gc.l_iSup - -@[to_additive (attr := simp)] -theorem closure_eq_bot_iff : closure k = ⊥ ↔ k ⊆ {1} := le_bot_iff.symm.trans <| closure_le _ - -@[to_additive] -theorem iSup_eq_closure {ι : Sort*} (p : ι → Subgroup G) : - ⨆ i, p i = closure (⋃ i, (p i : Set G)) := by simp_rw [closure_iUnion, closure_eq] - -/-- The subgroup generated by an element of a group equals the set of integer number powers of - the element. -/ -@[to_additive - "The `AddSubgroup` generated by an element of an `AddGroup` equals the set of - natural number multiples of the element."] -theorem mem_closure_singleton {x y : G} : y ∈ closure ({x} : Set G) ↔ ∃ n : ℤ, x ^ n = y := by - refine - ⟨fun hy => closure_induction ?_ ?_ ?_ ?_ hy, fun ⟨n, hn⟩ => - hn ▸ zpow_mem (subset_closure <| mem_singleton x) n⟩ - · intro y hy - rw [eq_of_mem_singleton hy] - exact ⟨1, zpow_one x⟩ - · exact ⟨0, zpow_zero x⟩ - · rintro _ _ _ _ ⟨n, rfl⟩ ⟨m, rfl⟩ - exact ⟨n + m, zpow_add x n m⟩ - rintro _ _ ⟨n, rfl⟩ - exact ⟨-n, zpow_neg x n⟩ - -@[to_additive] -theorem closure_singleton_one : closure ({1} : Set G) = ⊥ := by - simp [eq_bot_iff_forall, mem_closure_singleton] - -@[to_additive (attr := simp)] -lemma mem_closure_singleton_self (x : G) : x ∈ closure ({x} : Set G) := by - simpa [-subset_closure] using subset_closure (k := {x}) - -@[to_additive] -theorem le_closure_toSubmonoid (S : Set G) : Submonoid.closure S ≤ (closure S).toSubmonoid := - Submonoid.closure_le.2 subset_closure - -@[to_additive] -theorem closure_eq_top_of_mclosure_eq_top {S : Set G} (h : Submonoid.closure S = ⊤) : - closure S = ⊤ := - (eq_top_iff' _).2 fun _ => le_closure_toSubmonoid _ <| h.symm ▸ trivial - -@[to_additive] -theorem mem_iSup_of_directed {ι} [hι : Nonempty ι] {K : ι → Subgroup G} (hK : Directed (· ≤ ·) K) - {x : G} : x ∈ (iSup K : Subgroup G) ↔ ∃ i, x ∈ K i := by - refine ⟨?_, fun ⟨i, hi⟩ ↦ le_iSup K i hi⟩ - suffices x ∈ closure (⋃ i, (K i : Set G)) → ∃ i, x ∈ K i by - simpa only [closure_iUnion, closure_eq (K _)] using this - refine fun hx ↦ closure_induction (fun _ ↦ mem_iUnion.1) ?_ ?_ ?_ hx - · exact hι.elim fun i ↦ ⟨i, (K i).one_mem⟩ - · rintro x y _ _ ⟨i, hi⟩ ⟨j, hj⟩ - rcases hK i j with ⟨k, hki, hkj⟩ - exact ⟨k, mul_mem (hki hi) (hkj hj)⟩ - · rintro _ _ ⟨i, hi⟩ - exact ⟨i, inv_mem hi⟩ - -@[to_additive] -theorem coe_iSup_of_directed {ι} [Nonempty ι] {S : ι → Subgroup G} (hS : Directed (· ≤ ·) S) : - ((⨆ i, S i : Subgroup G) : Set G) = ⋃ i, S i := - Set.ext fun x ↦ by simp [mem_iSup_of_directed hS] - -@[to_additive] -theorem mem_sSup_of_directedOn {K : Set (Subgroup G)} (Kne : K.Nonempty) (hK : DirectedOn (· ≤ ·) K) - {x : G} : x ∈ sSup K ↔ ∃ s ∈ K, x ∈ s := by - haveI : Nonempty K := Kne.to_subtype - simp only [sSup_eq_iSup', mem_iSup_of_directed hK.directed_val, SetCoe.exists, Subtype.coe_mk, - exists_prop] - -variable {N : Type*} [Group N] {P : Type*} [Group P] - -/-- The preimage of a subgroup along a monoid homomorphism is a subgroup. -/ -@[to_additive - "The preimage of an `AddSubgroup` along an `AddMonoid` homomorphism - is an `AddSubgroup`."] -def comap {N : Type*} [Group N] (f : G →* N) (H : Subgroup N) : Subgroup G := - { H.toSubmonoid.comap f with - carrier := f ⁻¹' H - inv_mem' := fun {a} ha => show f a⁻¹ ∈ H by rw [f.map_inv]; exact H.inv_mem ha } - -@[to_additive (attr := simp)] -theorem coe_comap (K : Subgroup N) (f : G →* N) : (K.comap f : Set G) = f ⁻¹' K := - rfl - -@[simp] -theorem toAddSubgroup_comap {G₂ : Type*} [Group G₂] (f : G →* G₂) (s : Subgroup G₂) : - s.toAddSubgroup.comap (MonoidHom.toAdditive f) = Subgroup.toAddSubgroup (s.comap f) := rfl - -@[simp] -theorem _root_.AddSubgroup.toSubgroup_comap {A A₂ : Type*} [AddGroup A] [AddGroup A₂] - (f : A →+ A₂) (s : AddSubgroup A₂) : - s.toSubgroup.comap (AddMonoidHom.toMultiplicative f) = AddSubgroup.toSubgroup (s.comap f) := rfl - -@[to_additive (attr := simp)] -theorem mem_comap {K : Subgroup N} {f : G →* N} {x : G} : x ∈ K.comap f ↔ f x ∈ K := - Iff.rfl - -@[to_additive] -theorem comap_mono {f : G →* N} {K K' : Subgroup N} : K ≤ K' → comap f K ≤ comap f K' := - preimage_mono - -@[to_additive] -theorem comap_comap (K : Subgroup P) (g : N →* P) (f : G →* N) : - (K.comap g).comap f = K.comap (g.comp f) := - rfl - -@[to_additive (attr := simp)] -theorem comap_id (K : Subgroup N) : K.comap (MonoidHom.id _) = K := by - ext - rfl - -/-- The image of a subgroup along a monoid homomorphism is a subgroup. -/ -@[to_additive - "The image of an `AddSubgroup` along an `AddMonoid` homomorphism - is an `AddSubgroup`."] -def map (f : G →* N) (H : Subgroup G) : Subgroup N := - { H.toSubmonoid.map f with - carrier := f '' H - inv_mem' := by - rintro _ ⟨x, hx, rfl⟩ - exact ⟨x⁻¹, H.inv_mem hx, f.map_inv x⟩ } - -@[to_additive (attr := simp)] -theorem coe_map (f : G →* N) (K : Subgroup G) : (K.map f : Set N) = f '' K := - rfl - -@[to_additive (attr := simp)] -theorem mem_map {f : G →* N} {K : Subgroup G} {y : N} : y ∈ K.map f ↔ ∃ x ∈ K, f x = y := Iff.rfl - -@[to_additive] -theorem mem_map_of_mem (f : G →* N) {K : Subgroup G} {x : G} (hx : x ∈ K) : f x ∈ K.map f := - mem_image_of_mem f hx - -@[to_additive] -theorem apply_coe_mem_map (f : G →* N) (K : Subgroup G) (x : K) : f x ∈ K.map f := - mem_map_of_mem f x.prop - -@[to_additive] -theorem map_mono {f : G →* N} {K K' : Subgroup G} : K ≤ K' → map f K ≤ map f K' := - image_subset _ - -@[to_additive (attr := simp)] -theorem map_id : K.map (MonoidHom.id G) = K := - SetLike.coe_injective <| image_id _ - -@[to_additive] -theorem map_map (g : N →* P) (f : G →* N) : (K.map f).map g = K.map (g.comp f) := - SetLike.coe_injective <| image_image _ _ _ - -@[to_additive (attr := simp)] -theorem map_one_eq_bot : K.map (1 : G →* N) = ⊥ := - eq_bot_iff.mpr <| by - rintro x ⟨y, _, rfl⟩ - simp - -@[to_additive] -theorem mem_map_equiv {f : G ≃* N} {K : Subgroup G} {x : N} : - x ∈ K.map f.toMonoidHom ↔ f.symm x ∈ K := by - erw [@Set.mem_image_equiv _ _ (↑K) f.toEquiv x]; rfl - --- The simpNF linter says that the LHS can be simplified via `Subgroup.mem_map`. --- However this is a higher priority lemma. --- https://github.com/leanprover/std4/issues/207 -@[to_additive (attr := simp 1100, nolint simpNF)] -theorem mem_map_iff_mem {f : G →* N} (hf : Function.Injective f) {K : Subgroup G} {x : G} : - f x ∈ K.map f ↔ x ∈ K := - hf.mem_set_image - -@[to_additive] -theorem map_equiv_eq_comap_symm' (f : G ≃* N) (K : Subgroup G) : - K.map f.toMonoidHom = K.comap f.symm.toMonoidHom := - SetLike.coe_injective (f.toEquiv.image_eq_preimage K) - -@[to_additive] -theorem map_equiv_eq_comap_symm (f : G ≃* N) (K : Subgroup G) : - K.map f = K.comap (G := N) f.symm := - map_equiv_eq_comap_symm' _ _ - -@[to_additive] -theorem comap_equiv_eq_map_symm (f : N ≃* G) (K : Subgroup G) : - K.comap (G := N) f = K.map f.symm := - (map_equiv_eq_comap_symm f.symm K).symm - -@[to_additive] -theorem comap_equiv_eq_map_symm' (f : N ≃* G) (K : Subgroup G) : - K.comap f.toMonoidHom = K.map f.symm.toMonoidHom := - (map_equiv_eq_comap_symm f.symm K).symm - -@[to_additive] -theorem map_symm_eq_iff_map_eq {H : Subgroup N} {e : G ≃* N} : - H.map ↑e.symm = K ↔ K.map ↑e = H := by - constructor <;> rintro rfl - · rw [map_map, ← MulEquiv.coe_monoidHom_trans, MulEquiv.symm_trans_self, - MulEquiv.coe_monoidHom_refl, map_id] - · rw [map_map, ← MulEquiv.coe_monoidHom_trans, MulEquiv.self_trans_symm, - MulEquiv.coe_monoidHom_refl, map_id] - -@[to_additive] -theorem map_le_iff_le_comap {f : G →* N} {K : Subgroup G} {H : Subgroup N} : - K.map f ≤ H ↔ K ≤ H.comap f := - image_subset_iff - -@[to_additive] -theorem gc_map_comap (f : G →* N) : GaloisConnection (map f) (comap f) := fun _ _ => - map_le_iff_le_comap - -@[to_additive] -theorem map_sup (H K : Subgroup G) (f : G →* N) : (H ⊔ K).map f = H.map f ⊔ K.map f := - (gc_map_comap f).l_sup - -@[to_additive] -theorem map_iSup {ι : Sort*} (f : G →* N) (s : ι → Subgroup G) : - (iSup s).map f = ⨆ i, (s i).map f := - (gc_map_comap f).l_iSup - -@[to_additive] -theorem map_inf (H K : Subgroup G) (f : G →* N) (hf : Function.Injective f) : - (H ⊓ K).map f = H.map f ⊓ K.map f := SetLike.coe_injective (Set.image_inter hf) - -@[to_additive] -theorem map_iInf {ι : Sort*} [Nonempty ι] (f : G →* N) (hf : Function.Injective f) - (s : ι → Subgroup G) : (iInf s).map f = ⨅ i, (s i).map f := by - apply SetLike.coe_injective - simpa using (Set.injOn_of_injective hf).image_iInter_eq (s := SetLike.coe ∘ s) - -@[to_additive] -theorem comap_sup_comap_le (H K : Subgroup N) (f : G →* N) : - comap f H ⊔ comap f K ≤ comap f (H ⊔ K) := - Monotone.le_map_sup (fun _ _ => comap_mono) H K - -@[to_additive] -theorem iSup_comap_le {ι : Sort*} (f : G →* N) (s : ι → Subgroup N) : - ⨆ i, (s i).comap f ≤ (iSup s).comap f := - Monotone.le_map_iSup fun _ _ => comap_mono - -@[to_additive] -theorem comap_inf (H K : Subgroup N) (f : G →* N) : (H ⊓ K).comap f = H.comap f ⊓ K.comap f := - (gc_map_comap f).u_inf - -@[to_additive] -theorem comap_iInf {ι : Sort*} (f : G →* N) (s : ι → Subgroup N) : - (iInf s).comap f = ⨅ i, (s i).comap f := - (gc_map_comap f).u_iInf - -@[to_additive] -theorem map_inf_le (H K : Subgroup G) (f : G →* N) : map f (H ⊓ K) ≤ map f H ⊓ map f K := - le_inf (map_mono inf_le_left) (map_mono inf_le_right) - -@[to_additive] -theorem map_inf_eq (H K : Subgroup G) (f : G →* N) (hf : Function.Injective f) : - map f (H ⊓ K) = map f H ⊓ map f K := by - rw [← SetLike.coe_set_eq] - simp [Set.image_inter hf] - -@[to_additive (attr := simp)] -theorem map_bot (f : G →* N) : (⊥ : Subgroup G).map f = ⊥ := - (gc_map_comap f).l_bot - -@[to_additive (attr := simp)] -theorem map_top_of_surjective (f : G →* N) (h : Function.Surjective f) : Subgroup.map f ⊤ = ⊤ := by - rw [eq_top_iff] - intro x _ - obtain ⟨y, hy⟩ := h x - exact ⟨y, trivial, hy⟩ - -@[to_additive (attr := simp)] -theorem comap_top (f : G →* N) : (⊤ : Subgroup N).comap f = ⊤ := - (gc_map_comap f).u_top - -/-- For any subgroups `H` and `K`, view `H ⊓ K` as a subgroup of `K`. -/ -@[to_additive "For any subgroups `H` and `K`, view `H ⊓ K` as a subgroup of `K`."] -def subgroupOf (H K : Subgroup G) : Subgroup K := - H.comap K.subtype - -/-- If `H ≤ K`, then `H` as a subgroup of `K` is isomorphic to `H`. -/ -@[to_additive (attr := simps) "If `H ≤ K`, then `H` as a subgroup of `K` is isomorphic to `H`."] -def subgroupOfEquivOfLe {G : Type*} [Group G] {H K : Subgroup G} (h : H ≤ K) : - H.subgroupOf K ≃* H where - toFun g := ⟨g.1, g.2⟩ - invFun g := ⟨⟨g.1, h g.2⟩, g.2⟩ - left_inv _g := Subtype.ext (Subtype.ext rfl) - right_inv _g := Subtype.ext rfl - map_mul' _g _h := rfl - -@[to_additive (attr := simp)] -theorem comap_subtype (H K : Subgroup G) : H.comap K.subtype = H.subgroupOf K := - rfl - -@[to_additive (attr := simp)] -theorem comap_inclusion_subgroupOf {K₁ K₂ : Subgroup G} (h : K₁ ≤ K₂) (H : Subgroup G) : - (H.subgroupOf K₂).comap (inclusion h) = H.subgroupOf K₁ := - rfl - -@[to_additive] -theorem coe_subgroupOf (H K : Subgroup G) : (H.subgroupOf K : Set K) = K.subtype ⁻¹' H := - rfl - -@[to_additive] -theorem mem_subgroupOf {H K : Subgroup G} {h : K} : h ∈ H.subgroupOf K ↔ (h : G) ∈ H := - Iff.rfl - --- TODO(kmill): use `K ⊓ H` order for RHS to match `Subtype.image_preimage_coe` -@[to_additive (attr := simp)] -theorem subgroupOf_map_subtype (H K : Subgroup G) : (H.subgroupOf K).map K.subtype = H ⊓ K := - SetLike.ext' <| by refine Subtype.image_preimage_coe _ _ |>.trans ?_; apply Set.inter_comm - -@[to_additive (attr := simp)] -theorem bot_subgroupOf : (⊥ : Subgroup G).subgroupOf H = ⊥ := - Eq.symm (Subgroup.ext fun _g => Subtype.ext_iff) - -@[to_additive (attr := simp)] -theorem top_subgroupOf : (⊤ : Subgroup G).subgroupOf H = ⊤ := - rfl - -@[to_additive] -theorem subgroupOf_bot_eq_bot : H.subgroupOf ⊥ = ⊥ := - Subsingleton.elim _ _ - -@[to_additive] -theorem subgroupOf_bot_eq_top : H.subgroupOf ⊥ = ⊤ := - Subsingleton.elim _ _ - -@[to_additive (attr := simp)] -theorem subgroupOf_self : H.subgroupOf H = ⊤ := - top_unique fun g _hg => g.2 - -@[to_additive (attr := simp)] -theorem subgroupOf_inj {H₁ H₂ K : Subgroup G} : - H₁.subgroupOf K = H₂.subgroupOf K ↔ H₁ ⊓ K = H₂ ⊓ K := by - simpa only [SetLike.ext_iff, mem_inf, mem_subgroupOf, and_congr_left_iff] using Subtype.forall - -@[to_additive (attr := simp)] -theorem inf_subgroupOf_right (H K : Subgroup G) : (H ⊓ K).subgroupOf K = H.subgroupOf K := - subgroupOf_inj.2 (inf_right_idem _ _) - -@[to_additive (attr := simp)] -theorem inf_subgroupOf_left (H K : Subgroup G) : (K ⊓ H).subgroupOf K = H.subgroupOf K := by - rw [inf_comm, inf_subgroupOf_right] - -@[to_additive (attr := simp)] -theorem subgroupOf_eq_bot {H K : Subgroup G} : H.subgroupOf K = ⊥ ↔ Disjoint H K := by - rw [disjoint_iff, ← bot_subgroupOf, subgroupOf_inj, bot_inf_eq] - -@[to_additive (attr := simp)] -theorem subgroupOf_eq_top {H K : Subgroup G} : H.subgroupOf K = ⊤ ↔ K ≤ H := by - rw [← top_subgroupOf, subgroupOf_inj, top_inf_eq, inf_eq_right] +variable {N : Type*} [Group N] {P : Type*} [Group P] /-- Given `Subgroup`s `H`, `K` of groups `G`, `N` respectively, `H × K` as a subgroup of `G × N`. -/ @[to_additive prod @@ -1143,66 +397,8 @@ variable (H) end Normalizer -@[to_additive] -instance map_isCommutative (f : G →* G') [H.IsCommutative] : (H.map f).IsCommutative := - ⟨⟨by - rintro ⟨-, a, ha, rfl⟩ ⟨-, b, hb, rfl⟩ - rw [Subtype.ext_iff, coe_mul, coe_mul, Subtype.coe_mk, Subtype.coe_mk, ← map_mul, ← map_mul] - exact congr_arg f (Subtype.ext_iff.mp (mul_comm (⟨a, ha⟩ : H) ⟨b, hb⟩))⟩⟩ - -@[to_additive] -theorem comap_injective_isCommutative {f : G' →* G} (hf : Injective f) [H.IsCommutative] : - (H.comap f).IsCommutative := - ⟨⟨fun a b => - Subtype.ext - (by - have := mul_comm (⟨f a, a.2⟩ : H) (⟨f b, b.2⟩ : H) - rwa [Subtype.ext_iff, coe_mul, coe_mul, coe_mk, coe_mk, ← map_mul, ← map_mul, - hf.eq_iff] at this)⟩⟩ - -@[to_additive] -instance subgroupOf_isCommutative [H.IsCommutative] : (H.subgroupOf K).IsCommutative := - H.comap_injective_isCommutative Subtype.coe_injective - end Subgroup -namespace MulEquiv -variable {H : Type*} [Group H] - -/-- -An isomorphism of groups gives an order isomorphism between the lattices of subgroups, -defined by sending subgroups to their inverse images. - -See also `MulEquiv.mapSubgroup` which maps subgroups to their forward images. --/ -@[simps] -def comapSubgroup (f : G ≃* H) : Subgroup H ≃o Subgroup G where - toFun := Subgroup.comap f - invFun := Subgroup.comap f.symm - left_inv sg := by simp [Subgroup.comap_comap] - right_inv sh := by simp [Subgroup.comap_comap] - map_rel_iff' {sg1 sg2} := - ⟨fun h => by simpa [Subgroup.comap_comap] using - Subgroup.comap_mono (f := (f.symm : H →* G)) h, Subgroup.comap_mono⟩ - -/-- -An isomorphism of groups gives an order isomorphism between the lattices of subgroups, -defined by sending subgroups to their forward images. - -See also `MulEquiv.comapSubgroup` which maps subgroups to their inverse images. --/ -@[simps] -def mapSubgroup {H : Type*} [Group H] (f : G ≃* H) : Subgroup G ≃o Subgroup H where - toFun := Subgroup.map f - invFun := Subgroup.map f.symm - left_inv sg := by simp [Subgroup.map_map] - right_inv sh := by simp [Subgroup.map_map] - map_rel_iff' {sg1 sg2} := - ⟨fun h => by simpa [Subgroup.map_map] using - Subgroup.map_mono (f := (f.symm : H →* G)) h, Subgroup.map_mono⟩ - -end MulEquiv - namespace Group variable {s : Set G} @@ -1352,243 +548,10 @@ variable {N : Type*} {P : Type*} [Group N] [Group P] (K : Subgroup G) open Subgroup -/-- The range of a monoid homomorphism from a group is a subgroup. -/ -@[to_additive "The range of an `AddMonoidHom` from an `AddGroup` is an `AddSubgroup`."] -def range (f : G →* N) : Subgroup N := - Subgroup.copy ((⊤ : Subgroup G).map f) (Set.range f) (by simp [Set.ext_iff]) - -@[to_additive (attr := simp)] -theorem coe_range (f : G →* N) : (f.range : Set N) = Set.range f := - rfl - -@[to_additive (attr := simp)] -theorem mem_range {f : G →* N} {y : N} : y ∈ f.range ↔ ∃ x, f x = y := - Iff.rfl - -@[to_additive] -theorem range_eq_map (f : G →* N) : f.range = (⊤ : Subgroup G).map f := by ext; simp - -@[to_additive] -instance range_isCommutative {G : Type*} [CommGroup G] {N : Type*} [Group N] (f : G →* N) : - f.range.IsCommutative := - range_eq_map f ▸ Subgroup.map_isCommutative ⊤ f - -@[to_additive (attr := simp)] -theorem restrict_range (f : G →* N) : (f.restrict K).range = K.map f := by - simp_rw [SetLike.ext_iff, mem_range, mem_map, restrict_apply, SetLike.exists, - exists_prop, forall_const] - -/-- The canonical surjective group homomorphism `G →* f(G)` induced by a group -homomorphism `G →* N`. -/ -@[to_additive - "The canonical surjective `AddGroup` homomorphism `G →+ f(G)` induced by a group - homomorphism `G →+ N`."] -def rangeRestrict (f : G →* N) : G →* f.range := - codRestrict f _ fun x => ⟨x, rfl⟩ - -@[to_additive (attr := simp)] -theorem coe_rangeRestrict (f : G →* N) (g : G) : (f.rangeRestrict g : N) = f g := - rfl - -@[to_additive] -theorem coe_comp_rangeRestrict (f : G →* N) : - ((↑) : f.range → N) ∘ (⇑f.rangeRestrict : G → f.range) = f := - rfl - -@[to_additive] -theorem subtype_comp_rangeRestrict (f : G →* N) : f.range.subtype.comp f.rangeRestrict = f := - ext <| f.coe_rangeRestrict - -@[to_additive] -theorem rangeRestrict_surjective (f : G →* N) : Function.Surjective f.rangeRestrict := - fun ⟨_, g, rfl⟩ => ⟨g, rfl⟩ - -@[to_additive (attr := simp)] -lemma rangeRestrict_injective_iff {f : G →* N} : Injective f.rangeRestrict ↔ Injective f := by - convert Set.injective_codRestrict _ - -@[to_additive] -theorem map_range (g : N →* P) (f : G →* N) : f.range.map g = (g.comp f).range := by - rw [range_eq_map, range_eq_map]; exact (⊤ : Subgroup G).map_map g f - -@[to_additive] -theorem range_eq_top {N} [Group N] {f : G →* N} : - f.range = (⊤ : Subgroup N) ↔ Function.Surjective f := - SetLike.ext'_iff.trans <| Iff.trans (by rw [coe_range, coe_top]) Set.range_eq_univ - -@[deprecated (since := "2024-11-11")] alias range_top_iff_surjective := range_eq_top - -/-- The range of a surjective monoid homomorphism is the whole of the codomain. -/ -@[to_additive (attr := simp) - "The range of a surjective `AddMonoid` homomorphism is the whole of the codomain."] -theorem range_eq_top_of_surjective {N} [Group N] (f : G →* N) (hf : Function.Surjective f) : - f.range = (⊤ : Subgroup N) := - range_eq_top.2 hf - -@[deprecated (since := "2024-11-11")] alias range_top_of_surjective := range_eq_top_of_surjective - -@[to_additive (attr := simp)] -theorem range_one : (1 : G →* N).range = ⊥ := - SetLike.ext fun x => by simpa using @comm _ (· = ·) _ 1 x - -@[to_additive (attr := simp)] -theorem _root_.Subgroup.subtype_range (H : Subgroup G) : H.subtype.range = H := by - rw [range_eq_map, ← SetLike.coe_set_eq, coe_map, Subgroup.coeSubtype] - ext - simp - -@[to_additive (attr := simp)] -theorem _root_.Subgroup.inclusion_range {H K : Subgroup G} (h_le : H ≤ K) : - (inclusion h_le).range = H.subgroupOf K := - Subgroup.ext fun g => Set.ext_iff.mp (Set.range_inclusion h_le) g - -@[to_additive] -theorem subgroupOf_range_eq_of_le {G₁ G₂ : Type*} [Group G₁] [Group G₂] {K : Subgroup G₂} - (f : G₁ →* G₂) (h : f.range ≤ K) : - f.range.subgroupOf K = (f.codRestrict K fun x => h ⟨x, rfl⟩).range := by - ext k - refine exists_congr ?_ - simp [Subtype.ext_iff] - -@[simp] -theorem coe_toAdditive_range (f : G →* G') : - (MonoidHom.toAdditive f).range = Subgroup.toAddSubgroup f.range := rfl - -@[simp] -theorem coe_toMultiplicative_range {A A' : Type*} [AddGroup A] [AddGroup A'] (f : A →+ A') : - (AddMonoidHom.toMultiplicative f).range = AddSubgroup.toSubgroup f.range := rfl - -/-- Computable alternative to `MonoidHom.ofInjective`. -/ -@[to_additive "Computable alternative to `AddMonoidHom.ofInjective`."] -def ofLeftInverse {f : G →* N} {g : N →* G} (h : Function.LeftInverse g f) : G ≃* f.range := - { f.rangeRestrict with - toFun := f.rangeRestrict - invFun := g ∘ f.range.subtype - left_inv := h - right_inv := by - rintro ⟨x, y, rfl⟩ - apply Subtype.ext - rw [coe_rangeRestrict, Function.comp_apply, Subgroup.coeSubtype, Subtype.coe_mk, h] } - -@[to_additive (attr := simp)] -theorem ofLeftInverse_apply {f : G →* N} {g : N →* G} (h : Function.LeftInverse g f) (x : G) : - ↑(ofLeftInverse h x) = f x := - rfl - -@[to_additive (attr := simp)] -theorem ofLeftInverse_symm_apply {f : G →* N} {g : N →* G} (h : Function.LeftInverse g f) - (x : f.range) : (ofLeftInverse h).symm x = g x := - rfl - -/-- The range of an injective group homomorphism is isomorphic to its domain. -/ -@[to_additive "The range of an injective additive group homomorphism is isomorphic to its -domain."] -noncomputable def ofInjective {f : G →* N} (hf : Function.Injective f) : G ≃* f.range := - MulEquiv.ofBijective (f.codRestrict f.range fun x => ⟨x, rfl⟩) - ⟨fun _ _ h => hf (Subtype.ext_iff.mp h), by - rintro ⟨x, y, rfl⟩ - exact ⟨y, rfl⟩⟩ - -@[to_additive] -theorem ofInjective_apply {f : G →* N} (hf : Function.Injective f) {x : G} : - ↑(ofInjective hf x) = f x := - rfl - -@[to_additive (attr := simp)] -theorem apply_ofInjective_symm {f : G →* N} (hf : Function.Injective f) (x : f.range) : - f ((ofInjective hf).symm x) = x := - Subtype.ext_iff.1 <| (ofInjective hf).apply_symm_apply x - section Ker variable {M : Type*} [MulOneClass M] -/-- The multiplicative kernel of a monoid homomorphism is the subgroup of elements `x : G` such that -`f x = 1` -/ -@[to_additive - "The additive kernel of an `AddMonoid` homomorphism is the `AddSubgroup` of elements - such that `f x = 0`"] -def ker (f : G →* M) : Subgroup G := - { MonoidHom.mker f with - inv_mem' := fun {x} (hx : f x = 1) => - calc - f x⁻¹ = f x * f x⁻¹ := by rw [hx, one_mul] - _ = 1 := by rw [← map_mul, mul_inv_cancel, map_one] } - -@[to_additive (attr := simp)] -theorem mem_ker {f : G →* M} {x : G} : x ∈ f.ker ↔ f x = 1 := - Iff.rfl - -@[to_additive] -theorem div_mem_ker_iff (f : G →* N) {x y : G} : x / y ∈ ker f ↔ f x = f y := by - rw [mem_ker, map_div, div_eq_one] - -@[to_additive] -theorem coe_ker (f : G →* M) : (f.ker : Set G) = (f : G → M) ⁻¹' {1} := - rfl - -@[to_additive (attr := simp)] -theorem ker_toHomUnits {M} [Monoid M] (f : G →* M) : f.toHomUnits.ker = f.ker := by - ext x - simp [mem_ker, Units.ext_iff] - -@[to_additive] -theorem eq_iff (f : G →* M) {x y : G} : f x = f y ↔ y⁻¹ * x ∈ f.ker := by - constructor <;> intro h - · rw [mem_ker, map_mul, h, ← map_mul, inv_mul_cancel, map_one] - · rw [← one_mul x, ← mul_inv_cancel y, mul_assoc, map_mul, mem_ker.1 h, mul_one] - -@[to_additive] -instance decidableMemKer [DecidableEq M] (f : G →* M) : DecidablePred (· ∈ f.ker) := fun x => - decidable_of_iff (f x = 1) f.mem_ker - -@[to_additive] -theorem comap_ker (g : N →* P) (f : G →* N) : g.ker.comap f = (g.comp f).ker := - rfl - -@[to_additive (attr := simp)] -theorem comap_bot (f : G →* N) : (⊥ : Subgroup N).comap f = f.ker := - rfl - -@[to_additive (attr := simp)] -theorem ker_restrict (f : G →* N) : (f.restrict K).ker = f.ker.subgroupOf K := - rfl - -@[to_additive (attr := simp)] -theorem ker_codRestrict {S} [SetLike S N] [SubmonoidClass S N] (f : G →* N) (s : S) - (h : ∀ x, f x ∈ s) : (f.codRestrict s h).ker = f.ker := - SetLike.ext fun _x => Subtype.ext_iff - -@[to_additive (attr := simp)] -theorem ker_rangeRestrict (f : G →* N) : ker (rangeRestrict f) = ker f := - ker_codRestrict _ _ _ - -@[to_additive (attr := simp)] -theorem ker_one : (1 : G →* M).ker = ⊤ := - SetLike.ext fun _x => eq_self_iff_true _ - -@[to_additive (attr := simp)] -theorem ker_id : (MonoidHom.id G).ker = ⊥ := - rfl - -@[to_additive] -theorem ker_eq_bot_iff (f : G →* M) : f.ker = ⊥ ↔ Function.Injective f := - ⟨fun h x y hxy => by rwa [eq_iff, h, mem_bot, inv_mul_eq_one, eq_comm] at hxy, fun h => - bot_unique fun _ hx => h (hx.trans f.map_one.symm)⟩ - -@[to_additive (attr := simp)] -theorem _root_.Subgroup.ker_subtype (H : Subgroup G) : H.subtype.ker = ⊥ := - H.subtype.ker_eq_bot_iff.mpr Subtype.coe_injective - -@[to_additive (attr := simp)] -theorem _root_.Subgroup.ker_inclusion {H K : Subgroup G} (h : H ≤ K) : (inclusion h).ker = ⊥ := - (inclusion h).ker_eq_bot_iff.mpr (Set.inclusion_injective h) - -@[to_additive] -theorem ker_prod {M N : Type*} [MulOneClass M] [MulOneClass N] (f : G →* M) (g : G →* N) : - (f.prod g).ker = f.ker ⊓ g.ker := - SetLike.ext fun _ => Prod.mk_eq_one - @[to_additive] theorem prodMap_comap_prod {G' : Type*} {N' : Type*} [Group G'] [Group N'] (f : G →* N) (g : G' →* N') (S : Subgroup N) (S' : Subgroup N') : @@ -1600,74 +563,14 @@ theorem ker_prodMap {G' : Type*} {N' : Type*} [Group G'] [Group N'] (f : G →* (prodMap f g).ker = f.ker.prod g.ker := by rw [← comap_bot, ← comap_bot, ← comap_bot, ← prodMap_comap_prod, bot_prod_bot] -@[to_additive] -theorem range_le_ker_iff (f : G →* G') (g : G' →* G'') : f.range ≤ g.ker ↔ g.comp f = 1 := - ⟨fun h => ext fun x => h ⟨x, rfl⟩, by rintro h _ ⟨y, rfl⟩; exact DFunLike.congr_fun h y⟩ - -@[to_additive] -instance (priority := 100) normal_ker (f : G →* M) : f.ker.Normal := - ⟨fun x hx y => by - rw [mem_ker, map_mul, map_mul, mem_ker.1 hx, mul_one, map_mul_eq_one f (mul_inv_cancel y)]⟩ - @[to_additive (attr := simp)] lemma ker_fst : ker (fst G G') = .prod ⊥ ⊤ := SetLike.ext fun _ => (iff_of_eq (and_true _)).symm @[to_additive (attr := simp)] lemma ker_snd : ker (snd G G') = .prod ⊤ ⊥ := SetLike.ext fun _ => (iff_of_eq (true_and _)).symm -@[simp] -theorem coe_toAdditive_ker (f : G →* G') : - (MonoidHom.toAdditive f).ker = Subgroup.toAddSubgroup f.ker := rfl - -@[simp] -theorem coe_toMultiplicative_ker {A A' : Type*} [AddGroup A] [AddGroup A'] (f : A →+ A') : - (AddMonoidHom.toMultiplicative f).ker = AddSubgroup.toSubgroup f.ker := rfl - end Ker -section EqLocus - -variable {M : Type*} [Monoid M] - -/-- The subgroup of elements `x : G` such that `f x = g x` -/ -@[to_additive "The additive subgroup of elements `x : G` such that `f x = g x`"] -def eqLocus (f g : G →* M) : Subgroup G := - { eqLocusM f g with inv_mem' := eq_on_inv f g } - -@[to_additive (attr := simp)] -theorem eqLocus_same (f : G →* N) : f.eqLocus f = ⊤ := - SetLike.ext fun _ => eq_self_iff_true _ - -/-- If two monoid homomorphisms are equal on a set, then they are equal on its subgroup closure. -/ -@[to_additive - "If two monoid homomorphisms are equal on a set, then they are equal on its subgroup - closure."] -theorem eqOn_closure {f g : G →* M} {s : Set G} (h : Set.EqOn f g s) : Set.EqOn f g (closure s) := - show closure s ≤ f.eqLocus g from (closure_le _).2 h - -@[to_additive] -theorem eq_of_eqOn_top {f g : G →* M} (h : Set.EqOn f g (⊤ : Subgroup G)) : f = g := - ext fun _x => h trivial - -@[to_additive] -theorem eq_of_eqOn_dense {s : Set G} (hs : closure s = ⊤) {f g : G →* M} (h : s.EqOn f g) : f = g := - eq_of_eqOn_top <| hs ▸ eqOn_closure h - -end EqLocus - -@[to_additive] -theorem closure_preimage_le (f : G →* N) (s : Set N) : closure (f ⁻¹' s) ≤ (closure s).comap f := - (closure_le _).2 fun x hx => by rw [SetLike.mem_coe, mem_comap]; exact subset_closure hx - -/-- The image under a monoid homomorphism of the subgroup generated by a set equals the subgroup -generated by the image of the set. -/ -@[to_additive - "The image under an `AddMonoid` hom of the `AddSubgroup` generated by a set equals - the `AddSubgroup` generated by the image of the set."] -theorem map_closure (f : G →* N) (s : Set G) : (closure s).map f = closure (f '' s) := - Set.image_preimage.l_comm_of_u_comm (gc_map_comap f) (Subgroup.gi N).gc (Subgroup.gi G).gc - fun _ ↦ rfl - end MonoidHom namespace Subgroup @@ -1681,14 +584,6 @@ theorem Normal.map {H : Subgroup G} (h : H.Normal) (f : G →* N) (hf : Function normalizer_eq_top.2 h] exact le_normalizer_map _ -@[to_additive] -theorem map_eq_bot_iff {f : G →* N} : H.map f = ⊥ ↔ H ≤ f.ker := - (gc_map_comap f).l_eq_bot - -@[to_additive] -theorem map_eq_bot_iff_of_injective {f : G →* N} (hf : Function.Injective f) : - H.map f = ⊥ ↔ H = ⊥ := by rw [map_eq_bot_iff, f.ker_eq_bot_iff.mpr hf, le_bot_iff] - end Subgroup namespace Subgroup @@ -1697,166 +592,6 @@ open MonoidHom variable {N : Type*} [Group N] (f : G →* N) -@[to_additive] -theorem map_le_range (H : Subgroup G) : map f H ≤ f.range := - (range_eq_map f).symm ▸ map_mono le_top - -@[to_additive] -theorem map_subtype_le {H : Subgroup G} (K : Subgroup H) : K.map H.subtype ≤ H := - (K.map_le_range H.subtype).trans (le_of_eq H.subtype_range) - -@[to_additive] -theorem ker_le_comap (H : Subgroup N) : f.ker ≤ comap f H := - comap_bot f ▸ comap_mono bot_le - -@[to_additive] -theorem map_comap_le (H : Subgroup N) : map f (comap f H) ≤ H := - (gc_map_comap f).l_u_le _ - -@[to_additive] -theorem le_comap_map (H : Subgroup G) : H ≤ comap f (map f H) := - (gc_map_comap f).le_u_l _ - -@[to_additive] -theorem map_comap_eq (H : Subgroup N) : map f (comap f H) = f.range ⊓ H := - SetLike.ext' <| by - rw [coe_map, coe_comap, Set.image_preimage_eq_inter_range, coe_inf, coe_range, Set.inter_comm] - -@[to_additive] -theorem comap_map_eq (H : Subgroup G) : comap f (map f H) = H ⊔ f.ker := by - refine le_antisymm ?_ (sup_le (le_comap_map _ _) (ker_le_comap _ _)) - intro x hx; simp only [exists_prop, mem_map, mem_comap] at hx - rcases hx with ⟨y, hy, hy'⟩ - rw [← mul_inv_cancel_left y x] - exact mul_mem_sup hy (by simp [mem_ker, hy']) - -@[to_additive] -theorem map_comap_eq_self {f : G →* N} {H : Subgroup N} (h : H ≤ f.range) : - map f (comap f H) = H := by - rwa [map_comap_eq, inf_eq_right] - -@[to_additive] -theorem map_comap_eq_self_of_surjective {f : G →* N} (h : Function.Surjective f) (H : Subgroup N) : - map f (comap f H) = H := - map_comap_eq_self (range_eq_top.2 h ▸ le_top) - -@[to_additive] -theorem comap_le_comap_of_le_range {f : G →* N} {K L : Subgroup N} (hf : K ≤ f.range) : - K.comap f ≤ L.comap f ↔ K ≤ L := - ⟨(map_comap_eq_self hf).ge.trans ∘ map_le_iff_le_comap.mpr, comap_mono⟩ - -@[to_additive] -theorem comap_le_comap_of_surjective {f : G →* N} {K L : Subgroup N} (hf : Function.Surjective f) : - K.comap f ≤ L.comap f ↔ K ≤ L := - comap_le_comap_of_le_range (range_eq_top.2 hf ▸ le_top) - -@[to_additive] -theorem comap_lt_comap_of_surjective {f : G →* N} {K L : Subgroup N} (hf : Function.Surjective f) : - K.comap f < L.comap f ↔ K < L := by simp_rw [lt_iff_le_not_le, comap_le_comap_of_surjective hf] - -@[to_additive] -theorem comap_injective {f : G →* N} (h : Function.Surjective f) : Function.Injective (comap f) := - fun K L => by simp only [le_antisymm_iff, comap_le_comap_of_surjective h, imp_self] - -@[to_additive] -theorem comap_map_eq_self {f : G →* N} {H : Subgroup G} (h : f.ker ≤ H) : - comap f (map f H) = H := by - rwa [comap_map_eq, sup_eq_left] - -@[to_additive] -theorem comap_map_eq_self_of_injective {f : G →* N} (h : Function.Injective f) (H : Subgroup G) : - comap f (map f H) = H := - comap_map_eq_self (((ker_eq_bot_iff _).mpr h).symm ▸ bot_le) - -@[to_additive] -theorem map_le_map_iff {f : G →* N} {H K : Subgroup G} : H.map f ≤ K.map f ↔ H ≤ K ⊔ f.ker := by - rw [map_le_iff_le_comap, comap_map_eq] - -@[to_additive] -theorem map_le_map_iff' {f : G →* N} {H K : Subgroup G} : - H.map f ≤ K.map f ↔ H ⊔ f.ker ≤ K ⊔ f.ker := by - simp only [map_le_map_iff, sup_le_iff, le_sup_right, and_true] - -@[to_additive] -theorem map_eq_map_iff {f : G →* N} {H K : Subgroup G} : - H.map f = K.map f ↔ H ⊔ f.ker = K ⊔ f.ker := by simp only [le_antisymm_iff, map_le_map_iff'] - -@[to_additive] -theorem map_eq_range_iff {f : G →* N} {H : Subgroup G} : - H.map f = f.range ↔ Codisjoint H f.ker := by - rw [f.range_eq_map, map_eq_map_iff, codisjoint_iff, top_sup_eq] - -@[to_additive] -theorem map_le_map_iff_of_injective {f : G →* N} (hf : Function.Injective f) {H K : Subgroup G} : - H.map f ≤ K.map f ↔ H ≤ K := by rw [map_le_iff_le_comap, comap_map_eq_self_of_injective hf] - -@[to_additive (attr := simp)] -theorem map_subtype_le_map_subtype {G' : Subgroup G} {H K : Subgroup G'} : - H.map G'.subtype ≤ K.map G'.subtype ↔ H ≤ K := - map_le_map_iff_of_injective <| by apply Subtype.coe_injective - -@[to_additive] -theorem map_injective {f : G →* N} (h : Function.Injective f) : Function.Injective (map f) := - Function.LeftInverse.injective <| comap_map_eq_self_of_injective h - -@[to_additive] -theorem map_eq_comap_of_inverse {f : G →* N} {g : N →* G} (hl : Function.LeftInverse g f) - (hr : Function.RightInverse g f) (H : Subgroup G) : map f H = comap g H := - SetLike.ext' <| by rw [coe_map, coe_comap, Set.image_eq_preimage_of_inverse hl hr] - -/-- Given `f(A) = f(B)`, `ker f ≤ A`, and `ker f ≤ B`, deduce that `A = B`. -/ -@[to_additive "Given `f(A) = f(B)`, `ker f ≤ A`, and `ker f ≤ B`, deduce that `A = B`."] -theorem map_injective_of_ker_le {H K : Subgroup G} (hH : f.ker ≤ H) (hK : f.ker ≤ K) - (hf : map f H = map f K) : H = K := by - apply_fun comap f at hf - rwa [comap_map_eq, comap_map_eq, sup_of_le_left hH, sup_of_le_left hK] at hf - -@[to_additive] -theorem closure_preimage_eq_top (s : Set G) : closure ((closure s).subtype ⁻¹' s) = ⊤ := by - apply map_injective (closure s).subtype_injective - rw [MonoidHom.map_closure, ← MonoidHom.range_eq_map, subtype_range, - Set.image_preimage_eq_of_subset] - rw [coeSubtype, Subtype.range_coe_subtype] - exact subset_closure - -@[to_additive] -theorem comap_sup_eq_of_le_range {H K : Subgroup N} (hH : H ≤ f.range) (hK : K ≤ f.range) : - comap f H ⊔ comap f K = comap f (H ⊔ K) := - map_injective_of_ker_le f ((ker_le_comap f H).trans le_sup_left) (ker_le_comap f (H ⊔ K)) - (by - rw [map_comap_eq, map_sup, map_comap_eq, map_comap_eq, inf_eq_right.mpr hH, - inf_eq_right.mpr hK, inf_eq_right.mpr (sup_le hH hK)]) - -@[to_additive] -theorem comap_sup_eq (H K : Subgroup N) (hf : Function.Surjective f) : - comap f H ⊔ comap f K = comap f (H ⊔ K) := - comap_sup_eq_of_le_range f (range_eq_top.2 hf ▸ le_top) (range_eq_top.2 hf ▸ le_top) - -@[to_additive] -theorem sup_subgroupOf_eq {H K L : Subgroup G} (hH : H ≤ L) (hK : K ≤ L) : - H.subgroupOf L ⊔ K.subgroupOf L = (H ⊔ K).subgroupOf L := - comap_sup_eq_of_le_range L.subtype (hH.trans L.subtype_range.ge) (hK.trans L.subtype_range.ge) - -@[to_additive] -theorem codisjoint_subgroupOf_sup (H K : Subgroup G) : - Codisjoint (H.subgroupOf (H ⊔ K)) (K.subgroupOf (H ⊔ K)) := by - rw [codisjoint_iff, sup_subgroupOf_eq, subgroupOf_self] - exacts [le_sup_left, le_sup_right] - -/-- A subgroup is isomorphic to its image under an injective function. If you have an isomorphism, -use `MulEquiv.subgroupMap` for better definitional equalities. -/ -@[to_additive - "An additive subgroup is isomorphic to its image under an injective function. If you - have an isomorphism, use `AddEquiv.addSubgroupMap` for better definitional equalities."] -noncomputable def equivMapOfInjective (H : Subgroup G) (f : G →* N) (hf : Function.Injective f) : - H ≃* H.map f := - { Equiv.Set.image f H hf with map_mul' := fun _ _ => Subtype.ext (f.map_mul _ _) } - -@[to_additive (attr := simp)] -theorem coe_equivMapOfInjective_apply (H : Subgroup G) (f : G →* N) (hf : Function.Injective f) - (h : H) : (equivMapOfInjective H f hf h : N) = f h := - rfl - /-- The preimage of the normalizer is equal to the normalizer of the preimage of a surjective function. -/ @[to_additive @@ -2064,103 +799,6 @@ theorem Normal.of_map_subtype {K : Subgroup G} {L : Subgroup K} end Subgroup -namespace MonoidHom - -/-- The `MonoidHom` from the preimage of a subgroup to itself. -/ -@[to_additive (attr := simps!) "the `AddMonoidHom` from the preimage of an -additive subgroup to itself."] -def subgroupComap (f : G →* G') (H' : Subgroup G') : H'.comap f →* H' := - f.submonoidComap H'.toSubmonoid - -/-- The `MonoidHom` from a subgroup to its image. -/ -@[to_additive (attr := simps!) "the `AddMonoidHom` from an additive subgroup to its image"] -def subgroupMap (f : G →* G') (H : Subgroup G) : H →* H.map f := - f.submonoidMap H.toSubmonoid - -@[to_additive] -theorem subgroupMap_surjective (f : G →* G') (H : Subgroup G) : - Function.Surjective (f.subgroupMap H) := - f.submonoidMap_surjective H.toSubmonoid - -end MonoidHom - -namespace MulEquiv - -variable {H K : Subgroup G} - -/-- Makes the identity isomorphism from a proof two subgroups of a multiplicative - group are equal. -/ -@[to_additive - "Makes the identity additive isomorphism from a proof - two subgroups of an additive group are equal."] -def subgroupCongr (h : H = K) : H ≃* K := - { Equiv.setCongr <| congr_arg _ h with map_mul' := fun _ _ => rfl } - -@[to_additive (attr := simp)] -lemma subgroupCongr_apply (h : H = K) (x) : - (MulEquiv.subgroupCongr h x : G) = x := rfl - -@[to_additive (attr := simp)] -lemma subgroupCongr_symm_apply (h : H = K) (x) : - ((MulEquiv.subgroupCongr h).symm x : G) = x := rfl - -/-- A subgroup is isomorphic to its image under an isomorphism. If you only have an injective map, -use `Subgroup.equiv_map_of_injective`. -/ -@[to_additive - "An additive subgroup is isomorphic to its image under an isomorphism. If you only - have an injective map, use `AddSubgroup.equiv_map_of_injective`."] -def subgroupMap (e : G ≃* G') (H : Subgroup G) : H ≃* H.map (e : G →* G') := - MulEquiv.submonoidMap (e : G ≃* G') H.toSubmonoid - -@[to_additive (attr := simp)] -theorem coe_subgroupMap_apply (e : G ≃* G') (H : Subgroup G) (g : H) : - ((subgroupMap e H g : H.map (e : G →* G')) : G') = e g := - rfl - -@[to_additive (attr := simp)] -theorem subgroupMap_symm_apply (e : G ≃* G') (H : Subgroup G) (g : H.map (e : G →* G')) : - (e.subgroupMap H).symm g = ⟨e.symm g, SetLike.mem_coe.1 <| Set.mem_image_equiv.1 g.2⟩ := - rfl - -end MulEquiv - -namespace Subgroup - -@[to_additive (attr := simp)] -theorem equivMapOfInjective_coe_mulEquiv (H : Subgroup G) (e : G ≃* G') : - H.equivMapOfInjective (e : G →* G') (EquivLike.injective e) = e.subgroupMap H := by - ext - rfl - -variable {C : Type*} [CommGroup C] {s t : Subgroup C} {x : C} - -@[to_additive] -theorem mem_sup : x ∈ s ⊔ t ↔ ∃ y ∈ s, ∃ z ∈ t, y * z = x := - ⟨fun h => by - rw [sup_eq_closure] at h - refine Subgroup.closure_induction ?_ ?_ ?_ ?_ h - · rintro y (h | h) - · exact ⟨y, h, 1, t.one_mem, by simp⟩ - · exact ⟨1, s.one_mem, y, h, by simp⟩ - · exact ⟨1, s.one_mem, 1, ⟨t.one_mem, mul_one 1⟩⟩ - · rintro _ _ _ _ ⟨y₁, hy₁, z₁, hz₁, rfl⟩ ⟨y₂, hy₂, z₂, hz₂, rfl⟩ - exact ⟨_, mul_mem hy₁ hy₂, _, mul_mem hz₁ hz₂, by simp [mul_assoc, mul_left_comm]⟩ - · rintro _ _ ⟨y, hy, z, hz, rfl⟩ - exact ⟨_, inv_mem hy, _, inv_mem hz, mul_comm z y ▸ (mul_inv_rev z y).symm⟩, by - rintro ⟨y, hy, z, hz, rfl⟩; exact mul_mem_sup hy hz⟩ - -@[to_additive] -theorem mem_sup' : x ∈ s ⊔ t ↔ ∃ (y : s) (z : t), (y : C) * z = x := - mem_sup.trans <| by simp only [SetLike.exists, coe_mk, exists_prop] - -@[to_additive] -theorem mem_closure_pair {x y z : C} : - z ∈ closure ({x, y} : Set C) ↔ ∃ m n : ℤ, x ^ m * y ^ n = z := by - rw [← Set.singleton_union, Subgroup.closure_union, mem_sup] - simp_rw [mem_closure_singleton, exists_exists_eq_and] - -end Subgroup - namespace Subgroup section SubgroupNormal @@ -2208,15 +846,6 @@ theorem inf_subgroupOf_inf_normal_of_left {A' A : Subgroup G} (B : Subgroup G) ( instance normal_inf_normal (H K : Subgroup G) [hH : H.Normal] [hK : K.Normal] : (H ⊓ K).Normal := ⟨fun n hmem g => ⟨hH.conj_mem n hmem.1 g, hK.conj_mem n hmem.2 g⟩⟩ -@[to_additive] -theorem subgroupOf_sup (A A' B : Subgroup G) (hA : A ≤ B) (hA' : A' ≤ B) : - (A ⊔ A').subgroupOf B = A.subgroupOf B ⊔ A'.subgroupOf B := by - refine - map_injective_of_ker_le B.subtype (ker_le_comap _ _) - (le_trans (ker_le_comap B.subtype _) le_sup_left) ?_ - simp only [subgroupOf, map_comap_eq, map_sup, subtype_range] - rw [inf_of_le_right (sup_le hA hA'), inf_of_le_right hA', inf_of_le_right hA] - @[to_additive] theorem SubgroupNormal.mem_comm {H K : Subgroup G} (hK : H ≤ K) [hN : (H.subgroupOf K).Normal] {a b : G} (hb : b ∈ K) (h : a * b ∈ H) : b * a ∈ H := by @@ -2243,33 +872,6 @@ theorem commute_of_normal_of_disjoint (H₁ H₂ : Subgroup G) (hH₁ : H₁.Nor end SubgroupNormal -@[to_additive] -theorem disjoint_def {H₁ H₂ : Subgroup G} : Disjoint H₁ H₂ ↔ ∀ {x : G}, x ∈ H₁ → x ∈ H₂ → x = 1 := - disjoint_iff_inf_le.trans <| by simp only [Disjoint, SetLike.le_def, mem_inf, mem_bot, and_imp] - -@[to_additive] -theorem disjoint_def' {H₁ H₂ : Subgroup G} : - Disjoint H₁ H₂ ↔ ∀ {x y : G}, x ∈ H₁ → y ∈ H₂ → x = y → x = 1 := - disjoint_def.trans ⟨fun h _x _y hx hy hxy ↦ h hx <| hxy.symm ▸ hy, fun h _x hx hx' ↦ h hx hx' rfl⟩ - -@[to_additive] -theorem disjoint_iff_mul_eq_one {H₁ H₂ : Subgroup G} : - Disjoint H₁ H₂ ↔ ∀ {x y : G}, x ∈ H₁ → y ∈ H₂ → x * y = 1 → x = 1 ∧ y = 1 := - disjoint_def'.trans - ⟨fun h x y hx hy hxy => - let hx1 : x = 1 := h hx (H₂.inv_mem hy) (eq_inv_iff_mul_eq_one.mpr hxy) - ⟨hx1, by simpa [hx1] using hxy⟩, - fun h _ _ hx hy hxy => (h hx (H₂.inv_mem hy) (mul_inv_eq_one.mpr hxy)).1⟩ - -@[to_additive] -theorem mul_injective_of_disjoint {H₁ H₂ : Subgroup G} (h : Disjoint H₁ H₂) : - Function.Injective (fun g => g.1 * g.2 : H₁ × H₂ → G) := by - intro x y hxy - rw [← inv_mul_eq_iff_eq_mul, ← mul_assoc, ← mul_inv_eq_one, mul_assoc] at hxy - replace hxy := disjoint_iff_mul_eq_one.mp h (y.1⁻¹ * x.1).prop (x.2 * y.2⁻¹).prop hxy - rwa [coe_mul, coe_mul, coe_inv, coe_inv, inv_mul_eq_one, mul_inv_eq_one, ← Subtype.ext_iff, ← - Subtype.ext_iff, eq_comm, ← Prod.ext_iff] at hxy - end Subgroup namespace IsConj @@ -2310,5 +912,3 @@ def noncenter (G : Type*) [Monoid G] : Set (ConjClasses G) := g ∈ noncenter G ↔ g.carrier.Nontrivial := Iff.rfl end ConjClasses - -set_option linter.style.longFile 2500 diff --git a/Mathlib/Algebra/Group/Subgroup/Ker.lean b/Mathlib/Algebra/Group/Subgroup/Ker.lean new file mode 100644 index 0000000000000..8b9be58076933 --- /dev/null +++ b/Mathlib/Algebra/Group/Subgroup/Ker.lean @@ -0,0 +1,507 @@ +/- +Copyright (c) 2020 Kexing Ying. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Kexing Ying +-/ +import Mathlib.Algebra.Group.Subgroup.Map +import Mathlib.Tactic.ApplyFun + +/-! +# Kernel and range of group homomorphisms + +We define and prove results about the kernel and range of group homomorphisms. + +Special thanks goes to Amelia Livingston and Yury Kudryashov for their help and inspiration. + +## Main definitions + +Notation used here: + +- `G N` are `Group`s + +- `x` is an element of type `G` + +- `f g : N →* G` are group homomorphisms + +Definitions in the file: + +* `MonoidHom.range f` : the range of the group homomorphism `f` is a subgroup + +* `MonoidHom.ker f` : the kernel of a group homomorphism `f` is the subgroup of elements `x : G` + such that `f x = 1` + +* `MonoidHom.eqLocus f g` : given group homomorphisms `f`, `g`, the elements of `G` such that + `f x = g x` form a subgroup of `G` + +## Implementation notes + +Subgroup inclusion is denoted `≤` rather than `⊆`, although `∈` is defined as +membership of a subgroup's underlying set. + +## Tags +subgroup, subgroups +-/ + +assert_not_exists OrderedAddCommMonoid +assert_not_exists Multiset +assert_not_exists Ring + +open Function +open scoped Int + +variable {G G' G'' : Type*} [Group G] [Group G'] [Group G''] +variable {A : Type*} [AddGroup A] + +namespace MonoidHom + +variable {N : Type*} {P : Type*} [Group N] [Group P] (K : Subgroup G) + +open Subgroup + +/-- The range of a monoid homomorphism from a group is a subgroup. -/ +@[to_additive "The range of an `AddMonoidHom` from an `AddGroup` is an `AddSubgroup`."] +def range (f : G →* N) : Subgroup N := + Subgroup.copy ((⊤ : Subgroup G).map f) (Set.range f) (by simp [Set.ext_iff]) + +@[to_additive (attr := simp)] +theorem coe_range (f : G →* N) : (f.range : Set N) = Set.range f := + rfl + +@[to_additive (attr := simp)] +theorem mem_range {f : G →* N} {y : N} : y ∈ f.range ↔ ∃ x, f x = y := + Iff.rfl + +@[to_additive] +theorem range_eq_map (f : G →* N) : f.range = (⊤ : Subgroup G).map f := by ext; simp + +@[to_additive] +instance range_isCommutative {G : Type*} [CommGroup G] {N : Type*} [Group N] (f : G →* N) : + f.range.IsCommutative := + range_eq_map f ▸ Subgroup.map_isCommutative ⊤ f + +@[to_additive (attr := simp)] +theorem restrict_range (f : G →* N) : (f.restrict K).range = K.map f := by + simp_rw [SetLike.ext_iff, mem_range, mem_map, restrict_apply, SetLike.exists, + exists_prop, forall_const] + +/-- The canonical surjective group homomorphism `G →* f(G)` induced by a group +homomorphism `G →* N`. -/ +@[to_additive + "The canonical surjective `AddGroup` homomorphism `G →+ f(G)` induced by a group + homomorphism `G →+ N`."] +def rangeRestrict (f : G →* N) : G →* f.range := + codRestrict f _ fun x => ⟨x, rfl⟩ + +@[to_additive (attr := simp)] +theorem coe_rangeRestrict (f : G →* N) (g : G) : (f.rangeRestrict g : N) = f g := + rfl + +@[to_additive] +theorem coe_comp_rangeRestrict (f : G →* N) : + ((↑) : f.range → N) ∘ (⇑f.rangeRestrict : G → f.range) = f := + rfl + +@[to_additive] +theorem subtype_comp_rangeRestrict (f : G →* N) : f.range.subtype.comp f.rangeRestrict = f := + ext <| f.coe_rangeRestrict + +@[to_additive] +theorem rangeRestrict_surjective (f : G →* N) : Function.Surjective f.rangeRestrict := + fun ⟨_, g, rfl⟩ => ⟨g, rfl⟩ + +@[to_additive (attr := simp)] +lemma rangeRestrict_injective_iff {f : G →* N} : Injective f.rangeRestrict ↔ Injective f := by + convert Set.injective_codRestrict _ + +@[to_additive] +theorem map_range (g : N →* P) (f : G →* N) : f.range.map g = (g.comp f).range := by + rw [range_eq_map, range_eq_map]; exact (⊤ : Subgroup G).map_map g f + +@[to_additive] +theorem range_eq_top {N} [Group N] {f : G →* N} : + f.range = (⊤ : Subgroup N) ↔ Function.Surjective f := + SetLike.ext'_iff.trans <| Iff.trans (by rw [coe_range, coe_top]) Set.range_eq_univ + +@[deprecated (since := "2024-11-11")] alias range_top_iff_surjective := range_eq_top + +/-- The range of a surjective monoid homomorphism is the whole of the codomain. -/ +@[to_additive (attr := simp) + "The range of a surjective `AddMonoid` homomorphism is the whole of the codomain."] +theorem range_eq_top_of_surjective {N} [Group N] (f : G →* N) (hf : Function.Surjective f) : + f.range = (⊤ : Subgroup N) := + range_eq_top.2 hf + +@[deprecated (since := "2024-11-11")] alias range_top_of_surjective := range_eq_top_of_surjective + +@[to_additive (attr := simp)] +theorem range_one : (1 : G →* N).range = ⊥ := + SetLike.ext fun x => by simpa using @comm _ (· = ·) _ 1 x + +@[to_additive (attr := simp)] +theorem _root_.Subgroup.subtype_range (H : Subgroup G) : H.subtype.range = H := by + rw [range_eq_map, ← SetLike.coe_set_eq, coe_map, Subgroup.coeSubtype] + ext + simp + +@[to_additive (attr := simp)] +theorem _root_.Subgroup.inclusion_range {H K : Subgroup G} (h_le : H ≤ K) : + (inclusion h_le).range = H.subgroupOf K := + Subgroup.ext fun g => Set.ext_iff.mp (Set.range_inclusion h_le) g + +@[to_additive] +theorem subgroupOf_range_eq_of_le {G₁ G₂ : Type*} [Group G₁] [Group G₂] {K : Subgroup G₂} + (f : G₁ →* G₂) (h : f.range ≤ K) : + f.range.subgroupOf K = (f.codRestrict K fun x => h ⟨x, rfl⟩).range := by + ext k + refine exists_congr ?_ + simp [Subtype.ext_iff] + +/-- Computable alternative to `MonoidHom.ofInjective`. -/ +@[to_additive "Computable alternative to `AddMonoidHom.ofInjective`."] +def ofLeftInverse {f : G →* N} {g : N →* G} (h : Function.LeftInverse g f) : G ≃* f.range := + { f.rangeRestrict with + toFun := f.rangeRestrict + invFun := g ∘ f.range.subtype + left_inv := h + right_inv := by + rintro ⟨x, y, rfl⟩ + apply Subtype.ext + rw [coe_rangeRestrict, Function.comp_apply, Subgroup.coeSubtype, Subtype.coe_mk, h] } + +@[to_additive (attr := simp)] +theorem ofLeftInverse_apply {f : G →* N} {g : N →* G} (h : Function.LeftInverse g f) (x : G) : + ↑(ofLeftInverse h x) = f x := + rfl + +@[to_additive (attr := simp)] +theorem ofLeftInverse_symm_apply {f : G →* N} {g : N →* G} (h : Function.LeftInverse g f) + (x : f.range) : (ofLeftInverse h).symm x = g x := + rfl + +/-- The range of an injective group homomorphism is isomorphic to its domain. -/ +@[to_additive "The range of an injective additive group homomorphism is isomorphic to its +domain."] +noncomputable def ofInjective {f : G →* N} (hf : Function.Injective f) : G ≃* f.range := + MulEquiv.ofBijective (f.codRestrict f.range fun x => ⟨x, rfl⟩) + ⟨fun _ _ h => hf (Subtype.ext_iff.mp h), by + rintro ⟨x, y, rfl⟩ + exact ⟨y, rfl⟩⟩ + +@[to_additive] +theorem ofInjective_apply {f : G →* N} (hf : Function.Injective f) {x : G} : + ↑(ofInjective hf x) = f x := + rfl + +@[to_additive (attr := simp)] +theorem apply_ofInjective_symm {f : G →* N} (hf : Function.Injective f) (x : f.range) : + f ((ofInjective hf).symm x) = x := + Subtype.ext_iff.1 <| (ofInjective hf).apply_symm_apply x + +@[simp] +theorem coe_toAdditive_range (f : G →* G') : + (MonoidHom.toAdditive f).range = Subgroup.toAddSubgroup f.range := rfl + +@[simp] +theorem coe_toMultiplicative_range {A A' : Type*} [AddGroup A] [AddGroup A'] (f : A →+ A') : + (AddMonoidHom.toMultiplicative f).range = AddSubgroup.toSubgroup f.range := rfl + +section Ker + +variable {M : Type*} [MulOneClass M] + +/-- The multiplicative kernel of a monoid homomorphism is the subgroup of elements `x : G` such that +`f x = 1` -/ +@[to_additive + "The additive kernel of an `AddMonoid` homomorphism is the `AddSubgroup` of elements + such that `f x = 0`"] +def ker (f : G →* M) : Subgroup G := + { MonoidHom.mker f with + inv_mem' := fun {x} (hx : f x = 1) => + calc + f x⁻¹ = f x * f x⁻¹ := by rw [hx, one_mul] + _ = 1 := by rw [← map_mul, mul_inv_cancel, map_one] } + +@[to_additive (attr := simp)] +theorem mem_ker {f : G →* M} {x : G} : x ∈ f.ker ↔ f x = 1 := + Iff.rfl + +@[to_additive] +theorem div_mem_ker_iff (f : G →* N) {x y : G} : x / y ∈ ker f ↔ f x = f y := by + rw [mem_ker, map_div, div_eq_one] + +@[to_additive] +theorem coe_ker (f : G →* M) : (f.ker : Set G) = (f : G → M) ⁻¹' {1} := + rfl + +@[to_additive (attr := simp)] +theorem ker_toHomUnits {M} [Monoid M] (f : G →* M) : f.toHomUnits.ker = f.ker := by + ext x + simp [mem_ker, Units.ext_iff] + +@[to_additive] +theorem eq_iff (f : G →* M) {x y : G} : f x = f y ↔ y⁻¹ * x ∈ f.ker := by + constructor <;> intro h + · rw [mem_ker, map_mul, h, ← map_mul, inv_mul_cancel, map_one] + · rw [← one_mul x, ← mul_inv_cancel y, mul_assoc, map_mul, mem_ker.1 h, mul_one] + +@[to_additive] +instance decidableMemKer [DecidableEq M] (f : G →* M) : DecidablePred (· ∈ f.ker) := fun x => + decidable_of_iff (f x = 1) f.mem_ker + +@[to_additive] +theorem comap_ker (g : N →* P) (f : G →* N) : g.ker.comap f = (g.comp f).ker := + rfl + +@[to_additive (attr := simp)] +theorem comap_bot (f : G →* N) : (⊥ : Subgroup N).comap f = f.ker := + rfl + +@[to_additive (attr := simp)] +theorem ker_restrict (f : G →* N) : (f.restrict K).ker = f.ker.subgroupOf K := + rfl + +@[to_additive (attr := simp)] +theorem ker_codRestrict {S} [SetLike S N] [SubmonoidClass S N] (f : G →* N) (s : S) + (h : ∀ x, f x ∈ s) : (f.codRestrict s h).ker = f.ker := + SetLike.ext fun _x => Subtype.ext_iff + +@[to_additive (attr := simp)] +theorem ker_rangeRestrict (f : G →* N) : ker (rangeRestrict f) = ker f := + ker_codRestrict _ _ _ + +@[to_additive (attr := simp)] +theorem ker_one : (1 : G →* M).ker = ⊤ := + SetLike.ext fun _x => eq_self_iff_true _ + +@[to_additive (attr := simp)] +theorem ker_id : (MonoidHom.id G).ker = ⊥ := + rfl + +@[to_additive] +theorem ker_eq_bot_iff (f : G →* M) : f.ker = ⊥ ↔ Function.Injective f := + ⟨fun h x y hxy => by rwa [eq_iff, h, mem_bot, inv_mul_eq_one, eq_comm] at hxy, fun h => + bot_unique fun _ hx => h (hx.trans f.map_one.symm)⟩ + +@[to_additive (attr := simp)] +theorem _root_.Subgroup.ker_subtype (H : Subgroup G) : H.subtype.ker = ⊥ := + H.subtype.ker_eq_bot_iff.mpr Subtype.coe_injective + +@[to_additive (attr := simp)] +theorem _root_.Subgroup.ker_inclusion {H K : Subgroup G} (h : H ≤ K) : (inclusion h).ker = ⊥ := + (inclusion h).ker_eq_bot_iff.mpr (Set.inclusion_injective h) + +@[to_additive] +theorem ker_prod {M N : Type*} [MulOneClass M] [MulOneClass N] (f : G →* M) (g : G →* N) : + (f.prod g).ker = f.ker ⊓ g.ker := + SetLike.ext fun _ => Prod.mk_eq_one + +@[to_additive] +theorem range_le_ker_iff (f : G →* G') (g : G' →* G'') : f.range ≤ g.ker ↔ g.comp f = 1 := + ⟨fun h => ext fun x => h ⟨x, rfl⟩, by rintro h _ ⟨y, rfl⟩; exact DFunLike.congr_fun h y⟩ + +@[to_additive] +instance (priority := 100) normal_ker (f : G →* M) : f.ker.Normal := + ⟨fun x hx y => by + rw [mem_ker, map_mul, map_mul, mem_ker.1 hx, mul_one, map_mul_eq_one f (mul_inv_cancel y)]⟩ + +@[simp] +theorem coe_toAdditive_ker (f : G →* G') : + (MonoidHom.toAdditive f).ker = Subgroup.toAddSubgroup f.ker := rfl + +@[simp] +theorem coe_toMultiplicative_ker {A A' : Type*} [AddGroup A] [AddGroup A'] (f : A →+ A') : + (AddMonoidHom.toMultiplicative f).ker = AddSubgroup.toSubgroup f.ker := rfl + +end Ker + +section EqLocus + +variable {M : Type*} [Monoid M] + +/-- The subgroup of elements `x : G` such that `f x = g x` -/ +@[to_additive "The additive subgroup of elements `x : G` such that `f x = g x`"] +def eqLocus (f g : G →* M) : Subgroup G := + { eqLocusM f g with inv_mem' := eq_on_inv f g } + +@[to_additive (attr := simp)] +theorem eqLocus_same (f : G →* N) : f.eqLocus f = ⊤ := + SetLike.ext fun _ => eq_self_iff_true _ + +/-- If two monoid homomorphisms are equal on a set, then they are equal on its subgroup closure. -/ +@[to_additive + "If two monoid homomorphisms are equal on a set, then they are equal on its subgroup + closure."] +theorem eqOn_closure {f g : G →* M} {s : Set G} (h : Set.EqOn f g s) : Set.EqOn f g (closure s) := + show closure s ≤ f.eqLocus g from (closure_le _).2 h + +@[to_additive] +theorem eq_of_eqOn_top {f g : G →* M} (h : Set.EqOn f g (⊤ : Subgroup G)) : f = g := + ext fun _x => h trivial + +@[to_additive] +theorem eq_of_eqOn_dense {s : Set G} (hs : closure s = ⊤) {f g : G →* M} (h : s.EqOn f g) : f = g := + eq_of_eqOn_top <| hs ▸ eqOn_closure h + +end EqLocus + +end MonoidHom + +namespace Subgroup + +variable {N : Type*} [Group N] (H : Subgroup G) + +@[to_additive] +theorem map_eq_bot_iff {f : G →* N} : H.map f = ⊥ ↔ H ≤ f.ker := + (gc_map_comap f).l_eq_bot + +@[to_additive] +theorem map_eq_bot_iff_of_injective {f : G →* N} (hf : Function.Injective f) : + H.map f = ⊥ ↔ H = ⊥ := by rw [map_eq_bot_iff, f.ker_eq_bot_iff.mpr hf, le_bot_iff] + +open MonoidHom + +variable (f : G →* N) + +@[to_additive] +theorem map_le_range (H : Subgroup G) : map f H ≤ f.range := + (range_eq_map f).symm ▸ map_mono le_top + +@[to_additive] +theorem map_subtype_le {H : Subgroup G} (K : Subgroup H) : K.map H.subtype ≤ H := + (K.map_le_range H.subtype).trans (le_of_eq H.subtype_range) + +@[to_additive] +theorem ker_le_comap (H : Subgroup N) : f.ker ≤ comap f H := + comap_bot f ▸ comap_mono bot_le + +@[to_additive] +theorem map_comap_eq (H : Subgroup N) : map f (comap f H) = f.range ⊓ H := + SetLike.ext' <| by + rw [coe_map, coe_comap, Set.image_preimage_eq_inter_range, coe_inf, coe_range, Set.inter_comm] + +@[to_additive] +theorem comap_map_eq (H : Subgroup G) : comap f (map f H) = H ⊔ f.ker := by + refine le_antisymm ?_ (sup_le (le_comap_map _ _) (ker_le_comap _ _)) + intro x hx; simp only [exists_prop, mem_map, mem_comap] at hx + rcases hx with ⟨y, hy, hy'⟩ + rw [← mul_inv_cancel_left y x] + exact mul_mem_sup hy (by simp [mem_ker, hy']) + +@[to_additive] +theorem map_comap_eq_self {f : G →* N} {H : Subgroup N} (h : H ≤ f.range) : + map f (comap f H) = H := by + rwa [map_comap_eq, inf_eq_right] + +@[to_additive] +theorem map_comap_eq_self_of_surjective {f : G →* N} (h : Function.Surjective f) (H : Subgroup N) : + map f (comap f H) = H := + map_comap_eq_self (range_eq_top.2 h ▸ le_top) + +@[to_additive] +theorem comap_le_comap_of_le_range {f : G →* N} {K L : Subgroup N} (hf : K ≤ f.range) : + K.comap f ≤ L.comap f ↔ K ≤ L := + ⟨(map_comap_eq_self hf).ge.trans ∘ map_le_iff_le_comap.mpr, comap_mono⟩ + +@[to_additive] +theorem comap_le_comap_of_surjective {f : G →* N} {K L : Subgroup N} (hf : Function.Surjective f) : + K.comap f ≤ L.comap f ↔ K ≤ L := + comap_le_comap_of_le_range (range_eq_top.2 hf ▸ le_top) + +@[to_additive] +theorem comap_lt_comap_of_surjective {f : G →* N} {K L : Subgroup N} (hf : Function.Surjective f) : + K.comap f < L.comap f ↔ K < L := by simp_rw [lt_iff_le_not_le, comap_le_comap_of_surjective hf] + +@[to_additive] +theorem comap_injective {f : G →* N} (h : Function.Surjective f) : Function.Injective (comap f) := + fun K L => by simp only [le_antisymm_iff, comap_le_comap_of_surjective h, imp_self] + +@[to_additive] +theorem comap_map_eq_self {f : G →* N} {H : Subgroup G} (h : f.ker ≤ H) : + comap f (map f H) = H := by + rwa [comap_map_eq, sup_eq_left] + +@[to_additive] +theorem comap_map_eq_self_of_injective {f : G →* N} (h : Function.Injective f) (H : Subgroup G) : + comap f (map f H) = H := + comap_map_eq_self (((ker_eq_bot_iff _).mpr h).symm ▸ bot_le) + +@[to_additive] +theorem map_le_map_iff {f : G →* N} {H K : Subgroup G} : H.map f ≤ K.map f ↔ H ≤ K ⊔ f.ker := by + rw [map_le_iff_le_comap, comap_map_eq] + +@[to_additive] +theorem map_le_map_iff' {f : G →* N} {H K : Subgroup G} : + H.map f ≤ K.map f ↔ H ⊔ f.ker ≤ K ⊔ f.ker := by + simp only [map_le_map_iff, sup_le_iff, le_sup_right, and_true] + +@[to_additive] +theorem map_eq_map_iff {f : G →* N} {H K : Subgroup G} : + H.map f = K.map f ↔ H ⊔ f.ker = K ⊔ f.ker := by simp only [le_antisymm_iff, map_le_map_iff'] + +@[to_additive] +theorem map_eq_range_iff {f : G →* N} {H : Subgroup G} : + H.map f = f.range ↔ Codisjoint H f.ker := by + rw [f.range_eq_map, map_eq_map_iff, codisjoint_iff, top_sup_eq] + +@[to_additive] +theorem map_le_map_iff_of_injective {f : G →* N} (hf : Function.Injective f) {H K : Subgroup G} : + H.map f ≤ K.map f ↔ H ≤ K := by rw [map_le_iff_le_comap, comap_map_eq_self_of_injective hf] + +@[to_additive (attr := simp)] +theorem map_subtype_le_map_subtype {G' : Subgroup G} {H K : Subgroup G'} : + H.map G'.subtype ≤ K.map G'.subtype ↔ H ≤ K := + map_le_map_iff_of_injective <| by apply Subtype.coe_injective + +@[to_additive] +theorem map_injective {f : G →* N} (h : Function.Injective f) : Function.Injective (map f) := + Function.LeftInverse.injective <| comap_map_eq_self_of_injective h + +/-- Given `f(A) = f(B)`, `ker f ≤ A`, and `ker f ≤ B`, deduce that `A = B`. -/ +@[to_additive "Given `f(A) = f(B)`, `ker f ≤ A`, and `ker f ≤ B`, deduce that `A = B`."] +theorem map_injective_of_ker_le {H K : Subgroup G} (hH : f.ker ≤ H) (hK : f.ker ≤ K) + (hf : map f H = map f K) : H = K := by + apply_fun comap f at hf + rwa [comap_map_eq, comap_map_eq, sup_of_le_left hH, sup_of_le_left hK] at hf + +@[to_additive] +theorem closure_preimage_eq_top (s : Set G) : closure ((closure s).subtype ⁻¹' s) = ⊤ := by + apply map_injective (closure s).subtype_injective + rw [MonoidHom.map_closure, ← MonoidHom.range_eq_map, subtype_range, + Set.image_preimage_eq_of_subset] + rw [coeSubtype, Subtype.range_coe_subtype] + exact subset_closure + +@[to_additive] +theorem comap_sup_eq_of_le_range {H K : Subgroup N} (hH : H ≤ f.range) (hK : K ≤ f.range) : + comap f H ⊔ comap f K = comap f (H ⊔ K) := + map_injective_of_ker_le f ((ker_le_comap f H).trans le_sup_left) (ker_le_comap f (H ⊔ K)) + (by + rw [map_comap_eq, map_sup, map_comap_eq, map_comap_eq, inf_eq_right.mpr hH, + inf_eq_right.mpr hK, inf_eq_right.mpr (sup_le hH hK)]) + +@[to_additive] +theorem comap_sup_eq (H K : Subgroup N) (hf : Function.Surjective f) : + comap f H ⊔ comap f K = comap f (H ⊔ K) := + comap_sup_eq_of_le_range f (range_eq_top.2 hf ▸ le_top) (range_eq_top.2 hf ▸ le_top) + +@[to_additive] +theorem sup_subgroupOf_eq {H K L : Subgroup G} (hH : H ≤ L) (hK : K ≤ L) : + H.subgroupOf L ⊔ K.subgroupOf L = (H ⊔ K).subgroupOf L := + comap_sup_eq_of_le_range L.subtype (hH.trans L.subtype_range.ge) (hK.trans L.subtype_range.ge) + +@[to_additive] +theorem codisjoint_subgroupOf_sup (H K : Subgroup G) : + Codisjoint (H.subgroupOf (H ⊔ K)) (K.subgroupOf (H ⊔ K)) := by + rw [codisjoint_iff, sup_subgroupOf_eq, subgroupOf_self] + exacts [le_sup_left, le_sup_right] + +@[to_additive] +theorem subgroupOf_sup (A A' B : Subgroup G) (hA : A ≤ B) (hA' : A' ≤ B) : + (A ⊔ A').subgroupOf B = A.subgroupOf B ⊔ A'.subgroupOf B := by + refine + map_injective_of_ker_le B.subtype (ker_le_comap _ _) + (le_trans (ker_le_comap B.subtype _) le_sup_left) ?_ + simp only [subgroupOf, map_comap_eq, map_sup, subtype_range] + rw [inf_of_le_right (sup_le hA hA'), inf_of_le_right hA', inf_of_le_right hA] + +end Subgroup diff --git a/Mathlib/Algebra/Group/Subgroup/Lattice.lean b/Mathlib/Algebra/Group/Subgroup/Lattice.lean new file mode 100644 index 0000000000000..ea029ac82db4b --- /dev/null +++ b/Mathlib/Algebra/Group/Subgroup/Lattice.lean @@ -0,0 +1,558 @@ +/- +Copyright (c) 2020 Kexing Ying. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Kexing Ying +-/ +import Mathlib.Algebra.Group.Submonoid.Operations +import Mathlib.Algebra.Group.Subgroup.Defs + +/-! +# Lattice structure of subgroups + +We prove subgroups of a group form a complete lattice. + +There are also theorems about the subgroups generated by an element or a subset of a group, +defined both inductively and as the infimum of the set of subgroups containing a given +element/subset. + +Special thanks goes to Amelia Livingston and Yury Kudryashov for their help and inspiration. + +## Main definitions + +Notation used here: + +- `G` is a `Group` + +- `k` is a set of elements of type `G` + +Definitions in the file: + +* `CompleteLattice (Subgroup G)` : the subgroups of `G` form a complete lattice + +* `Subgroup.closure k` : the minimal subgroup that includes the set `k` + +* `Subgroup.gi` : `closure` forms a Galois insertion with the coercion to set + +## Implementation notes + +Subgroup inclusion is denoted `≤` rather than `⊆`, although `∈` is defined as +membership of a subgroup's underlying set. + +## Tags +subgroup, subgroups +-/ + +assert_not_exists OrderedAddCommMonoid +assert_not_exists Multiset +assert_not_exists Ring + +open Function +open scoped Int + +variable {G : Type*} [Group G] + +/-! +### Conversion to/from `Additive`/`Multiplicative` +-/ + +section mul_add + +variable {A : Type*} [AddGroup A] + +/-- Subgroups of a group `G` are isomorphic to additive subgroups of `Additive G`. -/ +@[simps!] +def Subgroup.toAddSubgroup : Subgroup G ≃o AddSubgroup (Additive G) where + toFun S := { Submonoid.toAddSubmonoid S.toSubmonoid with neg_mem' := S.inv_mem' } + invFun S := { AddSubmonoid.toSubmonoid S.toAddSubmonoid with inv_mem' := S.neg_mem' } + left_inv x := by cases x; rfl + right_inv x := by cases x; rfl + map_rel_iff' := Iff.rfl + +/-- Additive subgroup of an additive group `Additive G` are isomorphic to subgroup of `G`. -/ +abbrev AddSubgroup.toSubgroup' : AddSubgroup (Additive G) ≃o Subgroup G := + Subgroup.toAddSubgroup.symm + +/-- Additive subgroups of an additive group `A` are isomorphic to subgroups of `Multiplicative A`. +-/ +@[simps!] +def AddSubgroup.toSubgroup : AddSubgroup A ≃o Subgroup (Multiplicative A) where + toFun S := { AddSubmonoid.toSubmonoid S.toAddSubmonoid with inv_mem' := S.neg_mem' } + invFun S := { Submonoid.toAddSubmonoid S.toSubmonoid with neg_mem' := S.inv_mem' } + left_inv x := by cases x; rfl + right_inv x := by cases x; rfl + map_rel_iff' := Iff.rfl + +/-- Subgroups of an additive group `Multiplicative A` are isomorphic to additive subgroups of `A`. +-/ +abbrev Subgroup.toAddSubgroup' : Subgroup (Multiplicative A) ≃o AddSubgroup A := + AddSubgroup.toSubgroup.symm + +end mul_add + +namespace Subgroup + +variable (H K : Subgroup G) + +/-- The subgroup `G` of the group `G`. -/ +@[to_additive "The `AddSubgroup G` of the `AddGroup G`."] +instance : Top (Subgroup G) := + ⟨{ (⊤ : Submonoid G) with inv_mem' := fun _ => Set.mem_univ _ }⟩ + +/-- The top subgroup is isomorphic to the group. + +This is the group version of `Submonoid.topEquiv`. -/ +@[to_additive (attr := simps!) + "The top additive subgroup is isomorphic to the additive group. + + This is the additive group version of `AddSubmonoid.topEquiv`."] +def topEquiv : (⊤ : Subgroup G) ≃* G := + Submonoid.topEquiv + +/-- The trivial subgroup `{1}` of a group `G`. -/ +@[to_additive "The trivial `AddSubgroup` `{0}` of an `AddGroup` `G`."] +instance : Bot (Subgroup G) := + ⟨{ (⊥ : Submonoid G) with inv_mem' := by simp}⟩ + +@[to_additive] +instance : Inhabited (Subgroup G) := + ⟨⊥⟩ + +@[to_additive (attr := simp)] +theorem mem_bot {x : G} : x ∈ (⊥ : Subgroup G) ↔ x = 1 := + Iff.rfl + +@[to_additive (attr := simp)] +theorem mem_top (x : G) : x ∈ (⊤ : Subgroup G) := + Set.mem_univ x + +@[to_additive (attr := simp)] +theorem coe_top : ((⊤ : Subgroup G) : Set G) = Set.univ := + rfl + +@[to_additive (attr := simp)] +theorem coe_bot : ((⊥ : Subgroup G) : Set G) = {1} := + rfl + +@[to_additive] +instance : Unique (⊥ : Subgroup G) := + ⟨⟨1⟩, fun g => Subtype.ext g.2⟩ + +@[to_additive (attr := simp)] +theorem top_toSubmonoid : (⊤ : Subgroup G).toSubmonoid = ⊤ := + rfl + +@[to_additive (attr := simp)] +theorem bot_toSubmonoid : (⊥ : Subgroup G).toSubmonoid = ⊥ := + rfl + +@[to_additive] +theorem eq_bot_iff_forall : H = ⊥ ↔ ∀ x ∈ H, x = (1 : G) := + toSubmonoid_injective.eq_iff.symm.trans <| Submonoid.eq_bot_iff_forall _ + +@[to_additive] +theorem eq_bot_of_subsingleton [Subsingleton H] : H = ⊥ := by + rw [Subgroup.eq_bot_iff_forall] + intro y hy + rw [← Subgroup.coe_mk H y hy, Subsingleton.elim (⟨y, hy⟩ : H) 1, Subgroup.coe_one] + +@[to_additive (attr := simp, norm_cast)] +theorem coe_eq_univ {H : Subgroup G} : (H : Set G) = Set.univ ↔ H = ⊤ := + (SetLike.ext'_iff.trans (by rfl)).symm + +@[to_additive] +theorem coe_eq_singleton {H : Subgroup G} : (∃ g : G, (H : Set G) = {g}) ↔ H = ⊥ := + ⟨fun ⟨g, hg⟩ => + haveI : Subsingleton (H : Set G) := by + rw [hg] + infer_instance + H.eq_bot_of_subsingleton, + fun h => ⟨1, SetLike.ext'_iff.mp h⟩⟩ + +@[to_additive] +theorem nontrivial_iff_exists_ne_one (H : Subgroup G) : Nontrivial H ↔ ∃ x ∈ H, x ≠ (1 : G) := by + rw [Subtype.nontrivial_iff_exists_ne (fun x => x ∈ H) (1 : H)] + simp + +@[to_additive] +theorem exists_ne_one_of_nontrivial (H : Subgroup G) [Nontrivial H] : + ∃ x ∈ H, x ≠ 1 := by + rwa [← Subgroup.nontrivial_iff_exists_ne_one] + +@[to_additive] +theorem nontrivial_iff_ne_bot (H : Subgroup G) : Nontrivial H ↔ H ≠ ⊥ := by + rw [nontrivial_iff_exists_ne_one, ne_eq, eq_bot_iff_forall] + simp only [ne_eq, not_forall, exists_prop] + +/-- A subgroup is either the trivial subgroup or nontrivial. -/ +@[to_additive "A subgroup is either the trivial subgroup or nontrivial."] +theorem bot_or_nontrivial (H : Subgroup G) : H = ⊥ ∨ Nontrivial H := by + have := nontrivial_iff_ne_bot H + tauto + +/-- A subgroup is either the trivial subgroup or contains a non-identity element. -/ +@[to_additive "A subgroup is either the trivial subgroup or contains a nonzero element."] +theorem bot_or_exists_ne_one (H : Subgroup G) : H = ⊥ ∨ ∃ x ∈ H, x ≠ (1 : G) := by + convert H.bot_or_nontrivial + rw [nontrivial_iff_exists_ne_one] + +@[to_additive] +lemma ne_bot_iff_exists_ne_one {H : Subgroup G} : H ≠ ⊥ ↔ ∃ a : ↥H, a ≠ 1 := by + rw [← nontrivial_iff_ne_bot, nontrivial_iff_exists_ne_one] + simp only [ne_eq, Subtype.exists, mk_eq_one, exists_prop] + +/-- The inf of two subgroups is their intersection. -/ +@[to_additive "The inf of two `AddSubgroup`s is their intersection."] +instance : Min (Subgroup G) := + ⟨fun H₁ H₂ => + { H₁.toSubmonoid ⊓ H₂.toSubmonoid with + inv_mem' := fun ⟨hx, hx'⟩ => ⟨H₁.inv_mem hx, H₂.inv_mem hx'⟩ }⟩ + +@[to_additive (attr := simp)] +theorem coe_inf (p p' : Subgroup G) : ((p ⊓ p' : Subgroup G) : Set G) = (p : Set G) ∩ p' := + rfl + +@[to_additive (attr := simp)] +theorem mem_inf {p p' : Subgroup G} {x : G} : x ∈ p ⊓ p' ↔ x ∈ p ∧ x ∈ p' := + Iff.rfl + +@[to_additive] +instance : InfSet (Subgroup G) := + ⟨fun s => + { (⨅ S ∈ s, Subgroup.toSubmonoid S).copy (⋂ S ∈ s, ↑S) (by simp) with + inv_mem' := fun {x} hx => + Set.mem_biInter fun i h => i.inv_mem (by apply Set.mem_iInter₂.1 hx i h) }⟩ + +@[to_additive (attr := simp, norm_cast)] +theorem coe_sInf (H : Set (Subgroup G)) : ((sInf H : Subgroup G) : Set G) = ⋂ s ∈ H, ↑s := + rfl + +@[to_additive (attr := simp)] +theorem mem_sInf {S : Set (Subgroup G)} {x : G} : x ∈ sInf S ↔ ∀ p ∈ S, x ∈ p := + Set.mem_iInter₂ + +@[to_additive] +theorem mem_iInf {ι : Sort*} {S : ι → Subgroup G} {x : G} : (x ∈ ⨅ i, S i) ↔ ∀ i, x ∈ S i := by + simp only [iInf, mem_sInf, Set.forall_mem_range] + +@[to_additive (attr := simp, norm_cast)] +theorem coe_iInf {ι : Sort*} {S : ι → Subgroup G} : (↑(⨅ i, S i) : Set G) = ⋂ i, S i := by + simp only [iInf, coe_sInf, Set.biInter_range] + +/-- Subgroups of a group form a complete lattice. -/ +@[to_additive "The `AddSubgroup`s of an `AddGroup` form a complete lattice."] +instance : CompleteLattice (Subgroup G) := + { completeLatticeOfInf (Subgroup G) fun _s => + IsGLB.of_image SetLike.coe_subset_coe isGLB_biInf with + bot := ⊥ + bot_le := fun S _x hx => (mem_bot.1 hx).symm ▸ S.one_mem + top := ⊤ + le_top := fun _S x _hx => mem_top x + inf := (· ⊓ ·) + le_inf := fun _a _b _c ha hb _x hx => ⟨ha hx, hb hx⟩ + inf_le_left := fun _a _b _x => And.left + inf_le_right := fun _a _b _x => And.right } + +@[to_additive] +theorem mem_sup_left {S T : Subgroup G} : ∀ {x : G}, x ∈ S → x ∈ S ⊔ T := + have : S ≤ S ⊔ T := le_sup_left; fun h ↦ this h + +@[to_additive] +theorem mem_sup_right {S T : Subgroup G} : ∀ {x : G}, x ∈ T → x ∈ S ⊔ T := + have : T ≤ S ⊔ T := le_sup_right; fun h ↦ this h + +@[to_additive] +theorem mul_mem_sup {S T : Subgroup G} {x y : G} (hx : x ∈ S) (hy : y ∈ T) : x * y ∈ S ⊔ T := + (S ⊔ T).mul_mem (mem_sup_left hx) (mem_sup_right hy) + +@[to_additive] +theorem mem_iSup_of_mem {ι : Sort*} {S : ι → Subgroup G} (i : ι) : + ∀ {x : G}, x ∈ S i → x ∈ iSup S := + have : S i ≤ iSup S := le_iSup _ _; fun h ↦ this h + +@[to_additive] +theorem mem_sSup_of_mem {S : Set (Subgroup G)} {s : Subgroup G} (hs : s ∈ S) : + ∀ {x : G}, x ∈ s → x ∈ sSup S := + have : s ≤ sSup S := le_sSup hs; fun h ↦ this h + +@[to_additive (attr := simp)] +theorem subsingleton_iff : Subsingleton (Subgroup G) ↔ Subsingleton G := + ⟨fun _ => + ⟨fun x y => + have : ∀ i : G, i = 1 := fun i => + mem_bot.mp <| Subsingleton.elim (⊤ : Subgroup G) ⊥ ▸ mem_top i + (this x).trans (this y).symm⟩, + fun _ => ⟨fun x y => Subgroup.ext fun i => Subsingleton.elim 1 i ▸ by simp [Subgroup.one_mem]⟩⟩ + +@[to_additive (attr := simp)] +theorem nontrivial_iff : Nontrivial (Subgroup G) ↔ Nontrivial G := + not_iff_not.mp + ((not_nontrivial_iff_subsingleton.trans subsingleton_iff).trans + not_nontrivial_iff_subsingleton.symm) + +@[to_additive] +instance [Subsingleton G] : Unique (Subgroup G) := + ⟨⟨⊥⟩, fun a => @Subsingleton.elim _ (subsingleton_iff.mpr ‹_›) a _⟩ + +@[to_additive] +instance [Nontrivial G] : Nontrivial (Subgroup G) := + nontrivial_iff.mpr ‹_› + +@[to_additive] +theorem eq_top_iff' : H = ⊤ ↔ ∀ x : G, x ∈ H := + eq_top_iff.trans ⟨fun h m => h <| mem_top m, fun h m _ => h m⟩ + +/-- The `Subgroup` generated by a set. -/ +@[to_additive "The `AddSubgroup` generated by a set"] +def closure (k : Set G) : Subgroup G := + sInf { K | k ⊆ K } + +variable {k : Set G} + +@[to_additive] +theorem mem_closure {x : G} : x ∈ closure k ↔ ∀ K : Subgroup G, k ⊆ K → x ∈ K := + mem_sInf + +/-- The subgroup generated by a set includes the set. -/ +@[to_additive (attr := simp, aesop safe 20 apply (rule_sets := [SetLike])) + "The `AddSubgroup` generated by a set includes the set."] +theorem subset_closure : k ⊆ closure k := fun _ hx => mem_closure.2 fun _ hK => hK hx + +@[to_additive] +theorem not_mem_of_not_mem_closure {P : G} (hP : P ∉ closure k) : P ∉ k := fun h => + hP (subset_closure h) + +open Set + +/-- A subgroup `K` includes `closure k` if and only if it includes `k`. -/ +@[to_additive (attr := simp) + "An additive subgroup `K` includes `closure k` if and only if it includes `k`"] +theorem closure_le : closure k ≤ K ↔ k ⊆ K := + ⟨Subset.trans subset_closure, fun h => sInf_le h⟩ + +@[to_additive] +theorem closure_eq_of_le (h₁ : k ⊆ K) (h₂ : K ≤ closure k) : closure k = K := + le_antisymm ((closure_le <| K).2 h₁) h₂ + +/-- An induction principle for closure membership. If `p` holds for `1` and all elements of `k`, and +is preserved under multiplication and inverse, then `p` holds for all elements of the closure +of `k`. + +See also `Subgroup.closure_induction_left` and `Subgroup.closure_induction_right` for versions that +only require showing `p` is preserved by multiplication by elements in `k`. -/ +@[to_additive (attr := elab_as_elim) + "An induction principle for additive closure membership. If `p` + holds for `0` and all elements of `k`, and is preserved under addition and inverses, then `p` + holds for all elements of the additive closure of `k`. + + See also `AddSubgroup.closure_induction_left` and `AddSubgroup.closure_induction_left` for + versions that only require showing `p` is preserved by addition by elements in `k`."] +theorem closure_induction {p : (g : G) → g ∈ closure k → Prop} + (mem : ∀ x (hx : x ∈ k), p x (subset_closure hx)) (one : p 1 (one_mem _)) + (mul : ∀ x y hx hy, p x hx → p y hy → p (x * y) (mul_mem hx hy)) + (inv : ∀ x hx, p x hx → p x⁻¹ (inv_mem hx)) {x} (hx : x ∈ closure k) : p x hx := + let K : Subgroup G := + { carrier := { x | ∃ hx, p x hx } + mul_mem' := fun ⟨_, ha⟩ ⟨_, hb⟩ ↦ ⟨_, mul _ _ _ _ ha hb⟩ + one_mem' := ⟨_, one⟩ + inv_mem' := fun ⟨_, hb⟩ ↦ ⟨_, inv _ _ hb⟩ } + closure_le (K := K) |>.mpr (fun y hy ↦ ⟨subset_closure hy, mem y hy⟩) hx |>.elim fun _ ↦ id + +@[deprecated closure_induction (since := "2024-10-10")] +alias closure_induction' := closure_induction + +/-- 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 : (x y : G) → x ∈ closure k → y ∈ closure k → Prop} + (mem : ∀ (x) (y) (hx : x ∈ k) (hy : y ∈ k), p x y (subset_closure hx) (subset_closure hy)) + (one_left : ∀ x hx, p 1 x (one_mem _) hx) (one_right : ∀ x hx, p x 1 hx (one_mem _)) + (mul_left : ∀ x y z hx hy hz, p x z hx hz → p y z hy hz → p (x * y) z (mul_mem hx hy) hz) + (mul_right : ∀ y z x hy hz hx, p x y hx hy → p x z hx hz → p x (y * z) hx (mul_mem hy hz)) + (inv_left : ∀ x y hx hy, p x y hx hy → p x⁻¹ y (inv_mem hx) hy) + (inv_right : ∀ x y hx hy, p x y hx hy → p x y⁻¹ hx (inv_mem hy)) + {x y : G} (hx : x ∈ closure k) (hy : y ∈ closure k) : p x y hx hy := by + induction hy using closure_induction with + | mem z hz => induction hx using closure_induction with + | mem _ h => exact mem _ _ h hz + | one => exact one_left _ (subset_closure hz) + | mul _ _ _ _ h₁ h₂ => exact mul_left _ _ _ _ _ _ h₁ h₂ + | inv _ _ h => exact inv_left _ _ _ _ h + | one => exact one_right x hx + | mul _ _ _ _ h₁ h₂ => exact mul_right _ _ _ _ _ hx h₁ h₂ + | inv _ _ h => exact inv_right _ _ _ _ h + +@[to_additive (attr := simp)] +theorem closure_closure_coe_preimage {k : Set G} : closure (((↑) : closure k → G) ⁻¹' k) = ⊤ := + eq_top_iff.2 fun x _ ↦ Subtype.recOn x fun _ hx' ↦ + closure_induction (fun _ h ↦ subset_closure h) (one_mem _) (fun _ _ _ _ ↦ mul_mem) + (fun _ _ ↦ inv_mem) hx' + +variable (G) + +/-- `closure` forms a Galois insertion with the coercion to set. -/ +@[to_additive "`closure` forms a Galois insertion with the coercion to set."] +protected def gi : GaloisInsertion (@closure G _) (↑) where + choice s _ := closure s + gc s t := @closure_le _ _ t s + le_l_u _s := subset_closure + choice_eq _s _h := rfl + +variable {G} + +/-- Subgroup closure of a set is monotone in its argument: if `h ⊆ k`, +then `closure h ≤ closure k`. -/ +@[to_additive + "Additive subgroup closure of a set is monotone in its argument: if `h ⊆ k`, + then `closure h ≤ closure k`"] +theorem closure_mono ⦃h k : Set G⦄ (h' : h ⊆ k) : closure h ≤ closure k := + (Subgroup.gi G).gc.monotone_l h' + +/-- Closure of a subgroup `K` equals `K`. -/ +@[to_additive (attr := simp) "Additive closure of an additive subgroup `K` equals `K`"] +theorem closure_eq : closure (K : Set G) = K := + (Subgroup.gi G).l_u_eq K + +@[to_additive (attr := simp)] +theorem closure_empty : closure (∅ : Set G) = ⊥ := + (Subgroup.gi G).gc.l_bot + +@[to_additive (attr := simp)] +theorem closure_univ : closure (univ : Set G) = ⊤ := + @coe_top G _ ▸ closure_eq ⊤ + +@[to_additive] +theorem closure_union (s t : Set G) : closure (s ∪ t) = closure s ⊔ closure t := + (Subgroup.gi G).gc.l_sup + +@[to_additive] +theorem sup_eq_closure (H H' : Subgroup G) : H ⊔ H' = closure ((H : Set G) ∪ (H' : Set G)) := by + simp_rw [closure_union, closure_eq] + +@[to_additive] +theorem closure_iUnion {ι} (s : ι → Set G) : closure (⋃ i, s i) = ⨆ i, closure (s i) := + (Subgroup.gi G).gc.l_iSup + +@[to_additive (attr := simp)] +theorem closure_eq_bot_iff : closure k = ⊥ ↔ k ⊆ {1} := le_bot_iff.symm.trans <| closure_le _ + +@[to_additive] +theorem iSup_eq_closure {ι : Sort*} (p : ι → Subgroup G) : + ⨆ i, p i = closure (⋃ i, (p i : Set G)) := by simp_rw [closure_iUnion, closure_eq] + +/-- The subgroup generated by an element of a group equals the set of integer number powers of + the element. -/ +@[to_additive + "The `AddSubgroup` generated by an element of an `AddGroup` equals the set of + natural number multiples of the element."] +theorem mem_closure_singleton {x y : G} : y ∈ closure ({x} : Set G) ↔ ∃ n : ℤ, x ^ n = y := by + refine + ⟨fun hy => closure_induction ?_ ?_ ?_ ?_ hy, fun ⟨n, hn⟩ => + hn ▸ zpow_mem (subset_closure <| mem_singleton x) n⟩ + · intro y hy + rw [eq_of_mem_singleton hy] + exact ⟨1, zpow_one x⟩ + · exact ⟨0, zpow_zero x⟩ + · rintro _ _ _ _ ⟨n, rfl⟩ ⟨m, rfl⟩ + exact ⟨n + m, zpow_add x n m⟩ + rintro _ _ ⟨n, rfl⟩ + exact ⟨-n, zpow_neg x n⟩ + +@[to_additive] +theorem closure_singleton_one : closure ({1} : Set G) = ⊥ := by + simp [eq_bot_iff_forall, mem_closure_singleton] + +@[to_additive (attr := simp)] +lemma mem_closure_singleton_self (x : G) : x ∈ closure ({x} : Set G) := by + simpa [-subset_closure] using subset_closure (k := {x}) + +@[to_additive] +theorem le_closure_toSubmonoid (S : Set G) : Submonoid.closure S ≤ (closure S).toSubmonoid := + Submonoid.closure_le.2 subset_closure + +@[to_additive] +theorem closure_eq_top_of_mclosure_eq_top {S : Set G} (h : Submonoid.closure S = ⊤) : + closure S = ⊤ := + (eq_top_iff' _).2 fun _ => le_closure_toSubmonoid _ <| h.symm ▸ trivial + +@[to_additive] +theorem mem_iSup_of_directed {ι} [hι : Nonempty ι] {K : ι → Subgroup G} (hK : Directed (· ≤ ·) K) + {x : G} : x ∈ (iSup K : Subgroup G) ↔ ∃ i, x ∈ K i := by + refine ⟨?_, fun ⟨i, hi⟩ ↦ le_iSup K i hi⟩ + suffices x ∈ closure (⋃ i, (K i : Set G)) → ∃ i, x ∈ K i by + simpa only [closure_iUnion, closure_eq (K _)] using this + refine fun hx ↦ closure_induction (fun _ ↦ mem_iUnion.1) ?_ ?_ ?_ hx + · exact hι.elim fun i ↦ ⟨i, (K i).one_mem⟩ + · rintro x y _ _ ⟨i, hi⟩ ⟨j, hj⟩ + rcases hK i j with ⟨k, hki, hkj⟩ + exact ⟨k, mul_mem (hki hi) (hkj hj)⟩ + · rintro _ _ ⟨i, hi⟩ + exact ⟨i, inv_mem hi⟩ + +@[to_additive] +theorem coe_iSup_of_directed {ι} [Nonempty ι] {S : ι → Subgroup G} (hS : Directed (· ≤ ·) S) : + ((⨆ i, S i : Subgroup G) : Set G) = ⋃ i, S i := + Set.ext fun x ↦ by simp [mem_iSup_of_directed hS] + +@[to_additive] +theorem mem_sSup_of_directedOn {K : Set (Subgroup G)} (Kne : K.Nonempty) (hK : DirectedOn (· ≤ ·) K) + {x : G} : x ∈ sSup K ↔ ∃ s ∈ K, x ∈ s := by + haveI : Nonempty K := Kne.to_subtype + simp only [sSup_eq_iSup', mem_iSup_of_directed hK.directed_val, SetCoe.exists, Subtype.coe_mk, + exists_prop] + +variable {C : Type*} [CommGroup C] {s t : Subgroup C} {x : C} + +@[to_additive] +theorem mem_sup : x ∈ s ⊔ t ↔ ∃ y ∈ s, ∃ z ∈ t, y * z = x := + ⟨fun h => by + rw [sup_eq_closure] at h + refine Subgroup.closure_induction ?_ ?_ ?_ ?_ h + · rintro y (h | h) + · exact ⟨y, h, 1, t.one_mem, by simp⟩ + · exact ⟨1, s.one_mem, y, h, by simp⟩ + · exact ⟨1, s.one_mem, 1, ⟨t.one_mem, mul_one 1⟩⟩ + · rintro _ _ _ _ ⟨y₁, hy₁, z₁, hz₁, rfl⟩ ⟨y₂, hy₂, z₂, hz₂, rfl⟩ + exact ⟨_, mul_mem hy₁ hy₂, _, mul_mem hz₁ hz₂, by simp [mul_assoc, mul_left_comm]⟩ + · rintro _ _ ⟨y, hy, z, hz, rfl⟩ + exact ⟨_, inv_mem hy, _, inv_mem hz, mul_comm z y ▸ (mul_inv_rev z y).symm⟩, by + rintro ⟨y, hy, z, hz, rfl⟩; exact mul_mem_sup hy hz⟩ + +@[to_additive] +theorem mem_sup' : x ∈ s ⊔ t ↔ ∃ (y : s) (z : t), (y : C) * z = x := + mem_sup.trans <| by simp only [SetLike.exists, coe_mk, exists_prop] + +@[to_additive] +theorem mem_closure_pair {x y z : C} : + z ∈ closure ({x, y} : Set C) ↔ ∃ m n : ℤ, x ^ m * y ^ n = z := by + rw [← Set.singleton_union, Subgroup.closure_union, mem_sup] + simp_rw [mem_closure_singleton, exists_exists_eq_and] + +@[to_additive] +theorem disjoint_def {H₁ H₂ : Subgroup G} : Disjoint H₁ H₂ ↔ ∀ {x : G}, x ∈ H₁ → x ∈ H₂ → x = 1 := + disjoint_iff_inf_le.trans <| by simp only [Disjoint, SetLike.le_def, mem_inf, mem_bot, and_imp] + +@[to_additive] +theorem disjoint_def' {H₁ H₂ : Subgroup G} : + Disjoint H₁ H₂ ↔ ∀ {x y : G}, x ∈ H₁ → y ∈ H₂ → x = y → x = 1 := + disjoint_def.trans ⟨fun h _x _y hx hy hxy ↦ h hx <| hxy.symm ▸ hy, fun h _x hx hx' ↦ h hx hx' rfl⟩ + +@[to_additive] +theorem disjoint_iff_mul_eq_one {H₁ H₂ : Subgroup G} : + Disjoint H₁ H₂ ↔ ∀ {x y : G}, x ∈ H₁ → y ∈ H₂ → x * y = 1 → x = 1 ∧ y = 1 := + disjoint_def'.trans + ⟨fun h x y hx hy hxy => + let hx1 : x = 1 := h hx (H₂.inv_mem hy) (eq_inv_iff_mul_eq_one.mpr hxy) + ⟨hx1, by simpa [hx1] using hxy⟩, + fun h _ _ hx hy hxy => (h hx (H₂.inv_mem hy) (mul_inv_eq_one.mpr hxy)).1⟩ + +@[to_additive] +theorem mul_injective_of_disjoint {H₁ H₂ : Subgroup G} (h : Disjoint H₁ H₂) : + Function.Injective (fun g => g.1 * g.2 : H₁ × H₂ → G) := by + intro x y hxy + rw [← inv_mul_eq_iff_eq_mul, ← mul_assoc, ← mul_inv_eq_one, mul_assoc] at hxy + replace hxy := disjoint_iff_mul_eq_one.mp h (y.1⁻¹ * x.1).prop (x.2 * y.2⁻¹).prop hxy + rwa [coe_mul, coe_mul, coe_inv, coe_inv, inv_mul_eq_one, mul_inv_eq_one, ← Subtype.ext_iff, ← + Subtype.ext_iff, eq_comm, ← Prod.ext_iff] at hxy + +end Subgroup diff --git a/Mathlib/Algebra/Group/Subgroup/Map.lean b/Mathlib/Algebra/Group/Subgroup/Map.lean new file mode 100644 index 0000000000000..e1219dcd59203 --- /dev/null +++ b/Mathlib/Algebra/Group/Subgroup/Map.lean @@ -0,0 +1,528 @@ +/- +Copyright (c) 2020 Kexing Ying. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Kexing Ying +-/ +import Mathlib.Algebra.Group.Subgroup.Lattice +import Mathlib.Algebra.Group.TypeTags.Hom + +/-! +# `map` and `comap` for subgroups + +We prove results about images and preimages of subgroups under group homomorphisms. The bundled +subgroups use bundled monoid homomorphisms. + +Special thanks goes to Amelia Livingston and Yury Kudryashov for their help and inspiration. + +## Main definitions + +Notation used here: + +- `G N` are `Group`s + +- `H` is a `Subgroup` of `G` + +- `x` is an element of type `G` or type `A` + +- `f g : N →* G` are group homomorphisms + +- `s k` are sets of elements of type `G` + +Definitions in the file: + +* `Subgroup.comap H f` : the preimage of a subgroup `H` along the group homomorphism `f` is also a + subgroup + +* `Subgroup.map f H` : the image of a subgroup `H` along the group homomorphism `f` is also a + subgroup + +## Implementation notes + +Subgroup inclusion is denoted `≤` rather than `⊆`, although `∈` is defined as +membership of a subgroup's underlying set. + +## Tags +subgroup, subgroups +-/ + +assert_not_exists OrderedAddCommMonoid +assert_not_exists Multiset +assert_not_exists Ring + +open Function +open scoped Int + +variable {G G' G'' : Type*} [Group G] [Group G'] [Group G''] +variable {A : Type*} [AddGroup A] + +namespace Subgroup + +variable (H K : Subgroup G) {k : Set G} + +open Set + +variable {N : Type*} [Group N] {P : Type*} [Group P] + +/-- The preimage of a subgroup along a monoid homomorphism is a subgroup. -/ +@[to_additive + "The preimage of an `AddSubgroup` along an `AddMonoid` homomorphism + is an `AddSubgroup`."] +def comap {N : Type*} [Group N] (f : G →* N) (H : Subgroup N) : Subgroup G := + { H.toSubmonoid.comap f with + carrier := f ⁻¹' H + inv_mem' := fun {a} ha => show f a⁻¹ ∈ H by rw [f.map_inv]; exact H.inv_mem ha } + +@[to_additive (attr := simp)] +theorem coe_comap (K : Subgroup N) (f : G →* N) : (K.comap f : Set G) = f ⁻¹' K := + rfl + +@[to_additive (attr := simp)] +theorem mem_comap {K : Subgroup N} {f : G →* N} {x : G} : x ∈ K.comap f ↔ f x ∈ K := + Iff.rfl + +@[to_additive] +theorem comap_mono {f : G →* N} {K K' : Subgroup N} : K ≤ K' → comap f K ≤ comap f K' := + preimage_mono + +@[to_additive] +theorem comap_comap (K : Subgroup P) (g : N →* P) (f : G →* N) : + (K.comap g).comap f = K.comap (g.comp f) := + rfl + +@[to_additive (attr := simp)] +theorem comap_id (K : Subgroup N) : K.comap (MonoidHom.id _) = K := by + ext + rfl + +@[simp] +theorem toAddSubgroup_comap {G₂ : Type*} [Group G₂] (f : G →* G₂) (s : Subgroup G₂) : + s.toAddSubgroup.comap (MonoidHom.toAdditive f) = Subgroup.toAddSubgroup (s.comap f) := rfl + +@[simp] +theorem _root_.AddSubgroup.toSubgroup_comap {A A₂ : Type*} [AddGroup A] [AddGroup A₂] + (f : A →+ A₂) (s : AddSubgroup A₂) : + s.toSubgroup.comap (AddMonoidHom.toMultiplicative f) = AddSubgroup.toSubgroup (s.comap f) := rfl + +/-- The image of a subgroup along a monoid homomorphism is a subgroup. -/ +@[to_additive + "The image of an `AddSubgroup` along an `AddMonoid` homomorphism + is an `AddSubgroup`."] +def map (f : G →* N) (H : Subgroup G) : Subgroup N := + { H.toSubmonoid.map f with + carrier := f '' H + inv_mem' := by + rintro _ ⟨x, hx, rfl⟩ + exact ⟨x⁻¹, H.inv_mem hx, f.map_inv x⟩ } + +@[to_additive (attr := simp)] +theorem coe_map (f : G →* N) (K : Subgroup G) : (K.map f : Set N) = f '' K := + rfl + +@[to_additive (attr := simp)] +theorem mem_map {f : G →* N} {K : Subgroup G} {y : N} : y ∈ K.map f ↔ ∃ x ∈ K, f x = y := Iff.rfl + +@[to_additive] +theorem mem_map_of_mem (f : G →* N) {K : Subgroup G} {x : G} (hx : x ∈ K) : f x ∈ K.map f := + mem_image_of_mem f hx + +@[to_additive] +theorem apply_coe_mem_map (f : G →* N) (K : Subgroup G) (x : K) : f x ∈ K.map f := + mem_map_of_mem f x.prop + +@[to_additive] +theorem map_mono {f : G →* N} {K K' : Subgroup G} : K ≤ K' → map f K ≤ map f K' := + image_subset _ + +@[to_additive (attr := simp)] +theorem map_id : K.map (MonoidHom.id G) = K := + SetLike.coe_injective <| image_id _ + +@[to_additive] +theorem map_map (g : N →* P) (f : G →* N) : (K.map f).map g = K.map (g.comp f) := + SetLike.coe_injective <| image_image _ _ _ + +@[to_additive (attr := simp)] +theorem map_one_eq_bot : K.map (1 : G →* N) = ⊥ := + eq_bot_iff.mpr <| by + rintro x ⟨y, _, rfl⟩ + simp + +@[to_additive] +theorem mem_map_equiv {f : G ≃* N} {K : Subgroup G} {x : N} : + x ∈ K.map f.toMonoidHom ↔ f.symm x ∈ K := by + erw [@Set.mem_image_equiv _ _ (↑K) f.toEquiv x]; rfl + +-- The simpNF linter says that the LHS can be simplified via `Subgroup.mem_map`. +-- However this is a higher priority lemma. +-- https://github.com/leanprover/std4/issues/207 +@[to_additive (attr := simp 1100, nolint simpNF)] +theorem mem_map_iff_mem {f : G →* N} (hf : Function.Injective f) {K : Subgroup G} {x : G} : + f x ∈ K.map f ↔ x ∈ K := + hf.mem_set_image + +@[to_additive] +theorem map_equiv_eq_comap_symm' (f : G ≃* N) (K : Subgroup G) : + K.map f.toMonoidHom = K.comap f.symm.toMonoidHom := + SetLike.coe_injective (f.toEquiv.image_eq_preimage K) + +@[to_additive] +theorem map_equiv_eq_comap_symm (f : G ≃* N) (K : Subgroup G) : + K.map f = K.comap (G := N) f.symm := + map_equiv_eq_comap_symm' _ _ + +@[to_additive] +theorem comap_equiv_eq_map_symm (f : N ≃* G) (K : Subgroup G) : + K.comap (G := N) f = K.map f.symm := + (map_equiv_eq_comap_symm f.symm K).symm + +@[to_additive] +theorem comap_equiv_eq_map_symm' (f : N ≃* G) (K : Subgroup G) : + K.comap f.toMonoidHom = K.map f.symm.toMonoidHom := + (map_equiv_eq_comap_symm f.symm K).symm + +@[to_additive] +theorem map_symm_eq_iff_map_eq {H : Subgroup N} {e : G ≃* N} : + H.map ↑e.symm = K ↔ K.map ↑e = H := by + constructor <;> rintro rfl + · rw [map_map, ← MulEquiv.coe_monoidHom_trans, MulEquiv.symm_trans_self, + MulEquiv.coe_monoidHom_refl, map_id] + · rw [map_map, ← MulEquiv.coe_monoidHom_trans, MulEquiv.self_trans_symm, + MulEquiv.coe_monoidHom_refl, map_id] + +@[to_additive] +theorem map_le_iff_le_comap {f : G →* N} {K : Subgroup G} {H : Subgroup N} : + K.map f ≤ H ↔ K ≤ H.comap f := + image_subset_iff + +@[to_additive] +theorem gc_map_comap (f : G →* N) : GaloisConnection (map f) (comap f) := fun _ _ => + map_le_iff_le_comap + +@[to_additive] +theorem map_sup (H K : Subgroup G) (f : G →* N) : (H ⊔ K).map f = H.map f ⊔ K.map f := + (gc_map_comap f).l_sup + +@[to_additive] +theorem map_iSup {ι : Sort*} (f : G →* N) (s : ι → Subgroup G) : + (iSup s).map f = ⨆ i, (s i).map f := + (gc_map_comap f).l_iSup + +@[to_additive] +theorem map_inf (H K : Subgroup G) (f : G →* N) (hf : Function.Injective f) : + (H ⊓ K).map f = H.map f ⊓ K.map f := SetLike.coe_injective (Set.image_inter hf) + +@[to_additive] +theorem map_iInf {ι : Sort*} [Nonempty ι] (f : G →* N) (hf : Function.Injective f) + (s : ι → Subgroup G) : (iInf s).map f = ⨅ i, (s i).map f := by + apply SetLike.coe_injective + simpa using (Set.injOn_of_injective hf).image_iInter_eq (s := SetLike.coe ∘ s) + +@[to_additive] +theorem comap_sup_comap_le (H K : Subgroup N) (f : G →* N) : + comap f H ⊔ comap f K ≤ comap f (H ⊔ K) := + Monotone.le_map_sup (fun _ _ => comap_mono) H K + +@[to_additive] +theorem iSup_comap_le {ι : Sort*} (f : G →* N) (s : ι → Subgroup N) : + ⨆ i, (s i).comap f ≤ (iSup s).comap f := + Monotone.le_map_iSup fun _ _ => comap_mono + +@[to_additive] +theorem comap_inf (H K : Subgroup N) (f : G →* N) : (H ⊓ K).comap f = H.comap f ⊓ K.comap f := + (gc_map_comap f).u_inf + +@[to_additive] +theorem comap_iInf {ι : Sort*} (f : G →* N) (s : ι → Subgroup N) : + (iInf s).comap f = ⨅ i, (s i).comap f := + (gc_map_comap f).u_iInf + +@[to_additive] +theorem map_inf_le (H K : Subgroup G) (f : G →* N) : map f (H ⊓ K) ≤ map f H ⊓ map f K := + le_inf (map_mono inf_le_left) (map_mono inf_le_right) + +@[to_additive] +theorem map_inf_eq (H K : Subgroup G) (f : G →* N) (hf : Function.Injective f) : + map f (H ⊓ K) = map f H ⊓ map f K := by + rw [← SetLike.coe_set_eq] + simp [Set.image_inter hf] + +@[to_additive (attr := simp)] +theorem map_bot (f : G →* N) : (⊥ : Subgroup G).map f = ⊥ := + (gc_map_comap f).l_bot + +@[to_additive (attr := simp)] +theorem map_top_of_surjective (f : G →* N) (h : Function.Surjective f) : Subgroup.map f ⊤ = ⊤ := by + rw [eq_top_iff] + intro x _ + obtain ⟨y, hy⟩ := h x + exact ⟨y, trivial, hy⟩ + +@[to_additive (attr := simp)] +theorem comap_top (f : G →* N) : (⊤ : Subgroup N).comap f = ⊤ := + (gc_map_comap f).u_top + +/-- For any subgroups `H` and `K`, view `H ⊓ K` as a subgroup of `K`. -/ +@[to_additive "For any subgroups `H` and `K`, view `H ⊓ K` as a subgroup of `K`."] +def subgroupOf (H K : Subgroup G) : Subgroup K := + H.comap K.subtype + +/-- If `H ≤ K`, then `H` as a subgroup of `K` is isomorphic to `H`. -/ +@[to_additive (attr := simps) "If `H ≤ K`, then `H` as a subgroup of `K` is isomorphic to `H`."] +def subgroupOfEquivOfLe {G : Type*} [Group G] {H K : Subgroup G} (h : H ≤ K) : + H.subgroupOf K ≃* H where + toFun g := ⟨g.1, g.2⟩ + invFun g := ⟨⟨g.1, h g.2⟩, g.2⟩ + left_inv _g := Subtype.ext (Subtype.ext rfl) + right_inv _g := Subtype.ext rfl + map_mul' _g _h := rfl + +@[to_additive (attr := simp)] +theorem comap_subtype (H K : Subgroup G) : H.comap K.subtype = H.subgroupOf K := + rfl + +@[to_additive (attr := simp)] +theorem comap_inclusion_subgroupOf {K₁ K₂ : Subgroup G} (h : K₁ ≤ K₂) (H : Subgroup G) : + (H.subgroupOf K₂).comap (inclusion h) = H.subgroupOf K₁ := + rfl + +@[to_additive] +theorem coe_subgroupOf (H K : Subgroup G) : (H.subgroupOf K : Set K) = K.subtype ⁻¹' H := + rfl + +@[to_additive] +theorem mem_subgroupOf {H K : Subgroup G} {h : K} : h ∈ H.subgroupOf K ↔ (h : G) ∈ H := + Iff.rfl + +-- TODO(kmill): use `K ⊓ H` order for RHS to match `Subtype.image_preimage_coe` +@[to_additive (attr := simp)] +theorem subgroupOf_map_subtype (H K : Subgroup G) : (H.subgroupOf K).map K.subtype = H ⊓ K := + SetLike.ext' <| by refine Subtype.image_preimage_coe _ _ |>.trans ?_; apply Set.inter_comm + +@[to_additive (attr := simp)] +theorem bot_subgroupOf : (⊥ : Subgroup G).subgroupOf H = ⊥ := + Eq.symm (Subgroup.ext fun _g => Subtype.ext_iff) + +@[to_additive (attr := simp)] +theorem top_subgroupOf : (⊤ : Subgroup G).subgroupOf H = ⊤ := + rfl + +@[to_additive] +theorem subgroupOf_bot_eq_bot : H.subgroupOf ⊥ = ⊥ := + Subsingleton.elim _ _ + +@[to_additive] +theorem subgroupOf_bot_eq_top : H.subgroupOf ⊥ = ⊤ := + Subsingleton.elim _ _ + +@[to_additive (attr := simp)] +theorem subgroupOf_self : H.subgroupOf H = ⊤ := + top_unique fun g _hg => g.2 + +@[to_additive (attr := simp)] +theorem subgroupOf_inj {H₁ H₂ K : Subgroup G} : + H₁.subgroupOf K = H₂.subgroupOf K ↔ H₁ ⊓ K = H₂ ⊓ K := by + simpa only [SetLike.ext_iff, mem_inf, mem_subgroupOf, and_congr_left_iff] using Subtype.forall + +@[to_additive (attr := simp)] +theorem inf_subgroupOf_right (H K : Subgroup G) : (H ⊓ K).subgroupOf K = H.subgroupOf K := + subgroupOf_inj.2 (inf_right_idem _ _) + +@[to_additive (attr := simp)] +theorem inf_subgroupOf_left (H K : Subgroup G) : (K ⊓ H).subgroupOf K = H.subgroupOf K := by + rw [inf_comm, inf_subgroupOf_right] + +@[to_additive (attr := simp)] +theorem subgroupOf_eq_bot {H K : Subgroup G} : H.subgroupOf K = ⊥ ↔ Disjoint H K := by + rw [disjoint_iff, ← bot_subgroupOf, subgroupOf_inj, bot_inf_eq] + +@[to_additive (attr := simp)] +theorem subgroupOf_eq_top {H K : Subgroup G} : H.subgroupOf K = ⊤ ↔ K ≤ H := by + rw [← top_subgroupOf, subgroupOf_inj, top_inf_eq, inf_eq_right] + +variable (H : Subgroup G) + +@[to_additive] +instance map_isCommutative (f : G →* G') [H.IsCommutative] : (H.map f).IsCommutative := + ⟨⟨by + rintro ⟨-, a, ha, rfl⟩ ⟨-, b, hb, rfl⟩ + rw [Subtype.ext_iff, coe_mul, coe_mul, Subtype.coe_mk, Subtype.coe_mk, ← map_mul, ← map_mul] + exact congr_arg f (Subtype.ext_iff.mp (mul_comm (⟨a, ha⟩ : H) ⟨b, hb⟩))⟩⟩ + +@[to_additive] +theorem comap_injective_isCommutative {f : G' →* G} (hf : Injective f) [H.IsCommutative] : + (H.comap f).IsCommutative := + ⟨⟨fun a b => + Subtype.ext + (by + have := mul_comm (⟨f a, a.2⟩ : H) (⟨f b, b.2⟩ : H) + rwa [Subtype.ext_iff, coe_mul, coe_mul, coe_mk, coe_mk, ← map_mul, ← map_mul, + hf.eq_iff] at this)⟩⟩ + +@[to_additive] +instance subgroupOf_isCommutative [H.IsCommutative] : (H.subgroupOf K).IsCommutative := + H.comap_injective_isCommutative Subtype.coe_injective + +end Subgroup + +namespace MulEquiv +variable {H : Type*} [Group H] + +/-- +An isomorphism of groups gives an order isomorphism between the lattices of subgroups, +defined by sending subgroups to their inverse images. + +See also `MulEquiv.mapSubgroup` which maps subgroups to their forward images. +-/ +@[simps] +def comapSubgroup (f : G ≃* H) : Subgroup H ≃o Subgroup G where + toFun := Subgroup.comap f + invFun := Subgroup.comap f.symm + left_inv sg := by simp [Subgroup.comap_comap] + right_inv sh := by simp [Subgroup.comap_comap] + map_rel_iff' {sg1 sg2} := + ⟨fun h => by simpa [Subgroup.comap_comap] using + Subgroup.comap_mono (f := (f.symm : H →* G)) h, Subgroup.comap_mono⟩ + +/-- +An isomorphism of groups gives an order isomorphism between the lattices of subgroups, +defined by sending subgroups to their forward images. + +See also `MulEquiv.comapSubgroup` which maps subgroups to their inverse images. +-/ +@[simps] +def mapSubgroup {H : Type*} [Group H] (f : G ≃* H) : Subgroup G ≃o Subgroup H where + toFun := Subgroup.map f + invFun := Subgroup.map f.symm + left_inv sg := by simp [Subgroup.map_map] + right_inv sh := by simp [Subgroup.map_map] + map_rel_iff' {sg1 sg2} := + ⟨fun h => by simpa [Subgroup.map_map] using + Subgroup.map_mono (f := (f.symm : H →* G)) h, Subgroup.map_mono⟩ + +end MulEquiv + +namespace Subgroup + +open MonoidHom + +variable {N : Type*} [Group N] (f : G →* N) + +@[to_additive] +theorem map_comap_le (H : Subgroup N) : map f (comap f H) ≤ H := + (gc_map_comap f).l_u_le _ + +@[to_additive] +theorem le_comap_map (H : Subgroup G) : H ≤ comap f (map f H) := + (gc_map_comap f).le_u_l _ + +@[to_additive] +theorem map_eq_comap_of_inverse {f : G →* N} {g : N →* G} (hl : Function.LeftInverse g f) + (hr : Function.RightInverse g f) (H : Subgroup G) : map f H = comap g H := + SetLike.ext' <| by rw [coe_map, coe_comap, Set.image_eq_preimage_of_inverse hl hr] + +/-- A subgroup is isomorphic to its image under an injective function. If you have an isomorphism, +use `MulEquiv.subgroupMap` for better definitional equalities. -/ +@[to_additive + "An additive subgroup is isomorphic to its image under an injective function. If you + have an isomorphism, use `AddEquiv.addSubgroupMap` for better definitional equalities."] +noncomputable def equivMapOfInjective (H : Subgroup G) (f : G →* N) (hf : Function.Injective f) : + H ≃* H.map f := + { Equiv.Set.image f H hf with map_mul' := fun _ _ => Subtype.ext (f.map_mul _ _) } + +@[to_additive (attr := simp)] +theorem coe_equivMapOfInjective_apply (H : Subgroup G) (f : G →* N) (hf : Function.Injective f) + (h : H) : (equivMapOfInjective H f hf h : N) = f h := + rfl + +end Subgroup + +variable {N : Type*} [Group N] + +namespace MonoidHom + +/-- The `MonoidHom` from the preimage of a subgroup to itself. -/ +@[to_additive (attr := simps!) "the `AddMonoidHom` from the preimage of an +additive subgroup to itself."] +def subgroupComap (f : G →* G') (H' : Subgroup G') : H'.comap f →* H' := + f.submonoidComap H'.toSubmonoid + +/-- The `MonoidHom` from a subgroup to its image. -/ +@[to_additive (attr := simps!) "the `AddMonoidHom` from an additive subgroup to its image"] +def subgroupMap (f : G →* G') (H : Subgroup G) : H →* H.map f := + f.submonoidMap H.toSubmonoid + +@[to_additive] +theorem subgroupMap_surjective (f : G →* G') (H : Subgroup G) : + Function.Surjective (f.subgroupMap H) := + f.submonoidMap_surjective H.toSubmonoid + +end MonoidHom + +namespace MulEquiv + +variable {H K : Subgroup G} + +/-- Makes the identity isomorphism from a proof two subgroups of a multiplicative + group are equal. -/ +@[to_additive + "Makes the identity additive isomorphism from a proof + two subgroups of an additive group are equal."] +def subgroupCongr (h : H = K) : H ≃* K := + { Equiv.setCongr <| congr_arg _ h with map_mul' := fun _ _ => rfl } + +@[to_additive (attr := simp)] +lemma subgroupCongr_apply (h : H = K) (x) : + (MulEquiv.subgroupCongr h x : G) = x := rfl + +@[to_additive (attr := simp)] +lemma subgroupCongr_symm_apply (h : H = K) (x) : + ((MulEquiv.subgroupCongr h).symm x : G) = x := rfl + +/-- A subgroup is isomorphic to its image under an isomorphism. If you only have an injective map, +use `Subgroup.equiv_map_of_injective`. -/ +@[to_additive + "An additive subgroup is isomorphic to its image under an isomorphism. If you only + have an injective map, use `AddSubgroup.equiv_map_of_injective`."] +def subgroupMap (e : G ≃* G') (H : Subgroup G) : H ≃* H.map (e : G →* G') := + MulEquiv.submonoidMap (e : G ≃* G') H.toSubmonoid + +@[to_additive (attr := simp)] +theorem coe_subgroupMap_apply (e : G ≃* G') (H : Subgroup G) (g : H) : + ((subgroupMap e H g : H.map (e : G →* G')) : G') = e g := + rfl + +@[to_additive (attr := simp)] +theorem subgroupMap_symm_apply (e : G ≃* G') (H : Subgroup G) (g : H.map (e : G →* G')) : + (e.subgroupMap H).symm g = ⟨e.symm g, SetLike.mem_coe.1 <| Set.mem_image_equiv.1 g.2⟩ := + rfl + +end MulEquiv + +namespace MonoidHom + +open Subgroup + +@[to_additive] +theorem closure_preimage_le (f : G →* N) (s : Set N) : closure (f ⁻¹' s) ≤ (closure s).comap f := + (closure_le _).2 fun x hx => by rw [SetLike.mem_coe, mem_comap]; exact subset_closure hx + +/-- The image under a monoid homomorphism of the subgroup generated by a set equals the subgroup +generated by the image of the set. -/ +@[to_additive + "The image under an `AddMonoid` hom of the `AddSubgroup` generated by a set equals + the `AddSubgroup` generated by the image of the set."] +theorem map_closure (f : G →* N) (s : Set G) : (closure s).map f = closure (f '' s) := + Set.image_preimage.l_comm_of_u_comm (gc_map_comap f) (Subgroup.gi N).gc (Subgroup.gi G).gc + fun _ ↦ rfl + +end MonoidHom + +namespace Subgroup + +@[to_additive (attr := simp)] +theorem equivMapOfInjective_coe_mulEquiv (H : Subgroup G) (e : G ≃* G') : + H.equivMapOfInjective (e : G →* G') (EquivLike.injective e) = e.subgroupMap H := by + ext + rfl + +end Subgroup diff --git a/Mathlib/Algebra/Group/Subgroup/ZPowers/Basic.lean b/Mathlib/Algebra/Group/Subgroup/ZPowers/Basic.lean index cf8febc23281b..357b32013f358 100644 --- a/Mathlib/Algebra/Group/Subgroup/ZPowers/Basic.lean +++ b/Mathlib/Algebra/Group/Subgroup/ZPowers/Basic.lean @@ -3,7 +3,8 @@ Copyright (c) 2020 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes -/ -import Mathlib.Algebra.Group.Subgroup.Basic +import Mathlib.Algebra.Group.Int +import Mathlib.Algebra.Group.Subgroup.Map /-! # Subgroups generated by an element diff --git a/Mathlib/Algebra/Group/Submonoid/Membership.lean b/Mathlib/Algebra/Group/Submonoid/Membership.lean index cc9d5be5714ae..b48b123c3e191 100644 --- a/Mathlib/Algebra/Group/Submonoid/Membership.lean +++ b/Mathlib/Algebra/Group/Submonoid/Membership.lean @@ -8,6 +8,7 @@ import Mathlib.Algebra.FreeMonoid.Basic import Mathlib.Algebra.Group.Submonoid.MulOpposite import Mathlib.Algebra.Group.Submonoid.Operations import Mathlib.Algebra.GroupWithZero.Divisibility +import Mathlib.Algebra.Ring.Idempotents import Mathlib.Algebra.Ring.Int.Defs import Mathlib.Data.Finset.NoncommProd import Mathlib.Data.Nat.Cast.Basic @@ -420,6 +421,21 @@ lemma powers_le {n : M} {P : Submonoid M} : powers n ≤ P ↔ n ∈ P := by sim lemma powers_one : powers (1 : M) = ⊥ := bot_unique <| powers_le.2 <| one_mem _ +theorem _root_.IsIdempotentElem.coe_powers {a : M} (ha : IsIdempotentElem a) : + (Submonoid.powers a : Set M) = {1, a} := + let S : Submonoid M := + { carrier := {1, a}, + mul_mem' := by + rintro _ _ (rfl|rfl) (rfl|rfl) + · rw [one_mul]; exact .inl rfl + · rw [one_mul]; exact .inr rfl + · rw [mul_one]; exact .inr rfl + · rw [ha]; exact .inr rfl + one_mem' := .inl rfl } + suffices Submonoid.powers a = S from congr_arg _ this + le_antisymm (Submonoid.powers_le.mpr <| .inr rfl) + (by rintro _ (rfl|rfl); exacts [one_mem _, Submonoid.mem_powers _]) + /-- The submonoid generated by an element is a group if that element has finite order. -/ abbrev groupPowers {x : M} {n : ℕ} (hpos : 0 < n) (hx : x ^ n = 1) : Group (powers x) where inv x := x ^ (n - 1) @@ -475,7 +491,7 @@ when it is injective. The inverse is given by the logarithms. -/ @[simps] def powLogEquiv [DecidableEq M] {n : M} (h : Function.Injective fun m : ℕ => n ^ m) : Multiplicative ℕ ≃* powers n where - toFun m := pow n (Multiplicative.toAdd m) + toFun m := pow n m.toAdd invFun m := Multiplicative.ofAdd (log m) left_inv := log_pow_eq_self h right_inv := pow_log_eq_self diff --git a/Mathlib/Algebra/Group/Submonoid/Operations.lean b/Mathlib/Algebra/Group/Submonoid/Operations.lean index 46c96865817f9..36ee592c01e9d 100644 --- a/Mathlib/Algebra/Group/Submonoid/Operations.lean +++ b/Mathlib/Algebra/Group/Submonoid/Operations.lean @@ -5,9 +5,10 @@ Authors: Johannes Hölzl, Kenny Lau, Johan Commelin, Mario Carneiro, Kevin Buzza Amelia Livingston, Yury Kudryashov -/ import Mathlib.Algebra.Group.Action.Faithful -import Mathlib.Algebra.Group.Nat +import Mathlib.Algebra.Group.Nat.Basic import Mathlib.Algebra.Group.Prod import Mathlib.Algebra.Group.Submonoid.Basic +import Mathlib.Algebra.Group.TypeTags.Basic /-! # Operations on `Submonoid`s diff --git a/Mathlib/Algebra/Group/Submonoid/Units.lean b/Mathlib/Algebra/Group/Submonoid/Units.lean index 96ce6d155d1e4..111adf47e20ff 100644 --- a/Mathlib/Algebra/Group/Submonoid/Units.lean +++ b/Mathlib/Algebra/Group/Submonoid/Units.lean @@ -5,7 +5,7 @@ Authors: Wrenna Robson -/ import Mathlib.Algebra.Group.Submonoid.Operations import Mathlib.Algebra.Group.Submonoid.Pointwise -import Mathlib.Algebra.Group.Subgroup.Basic +import Mathlib.Algebra.Group.Subgroup.Lattice /-! diff --git a/Mathlib/Algebra/Group/Subsemigroup/Operations.lean b/Mathlib/Algebra/Group/Subsemigroup/Operations.lean index 8fc45916faae0..2c782614c04cf 100644 --- a/Mathlib/Algebra/Group/Subsemigroup/Operations.lean +++ b/Mathlib/Algebra/Group/Subsemigroup/Operations.lean @@ -6,7 +6,7 @@ Amelia Livingston, Yury Kudryashov, Yakov Pechersky, Jireh Loreaux -/ import Mathlib.Algebra.Group.Prod import Mathlib.Algebra.Group.Subsemigroup.Basic -import Mathlib.Algebra.Group.TypeTags +import Mathlib.Algebra.Group.TypeTags.Basic /-! # Operations on `Subsemigroup`s diff --git a/Mathlib/Algebra/Group/TypeTags.lean b/Mathlib/Algebra/Group/TypeTags/Basic.lean similarity index 71% rename from Mathlib/Algebra/Group/TypeTags.lean rename to Mathlib/Algebra/Group/TypeTags/Basic.lean index f6e2f9c2cc9e0..152313ad2ebc6 100644 --- a/Mathlib/Algebra/Group/TypeTags.lean +++ b/Mathlib/Algebra/Group/TypeTags/Basic.lean @@ -3,8 +3,12 @@ Copyright (c) 2018 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ -import Mathlib.Algebra.Group.Hom.Defs -import Mathlib.Data.Finite.Defs +import Mathlib.Algebra.Group.Pi.Basic +import Mathlib.Data.FunLike.Basic +import Mathlib.Logic.Function.Iterate +import Mathlib.Logic.Equiv.Defs +import Mathlib.Tactic.Set +import Mathlib.Util.AssertExists import Mathlib.Logic.Nontrivial.Basic /-! @@ -23,15 +27,12 @@ We also define instances `Additive.*` and `Multiplicative.*` that actually trans This file is similar to `Order.Synonym`. -## Porting notes - -- Since bundled morphism applications that rely on `CoeFun` currently don't work, they are ported - as `toFoo a` rather than `a.toFoo` for now. (https://github.com/leanprover/lean4/issues/1910) - -/ assert_not_exists MonoidWithZero assert_not_exists DenselyOrdered +assert_not_exists MonoidHom +assert_not_exists Finite universe u v @@ -71,7 +72,7 @@ protected lemma «exists» {p : Additive α → Prop} : (∃ a, p a) ↔ ∃ a, /-- Recursion principle for `Additive`, supported by `cases` and `induction`. -/ @[elab_as_elim, cases_eliminator, induction_eliminator] def rec {motive : Additive α → Sort*} (ofMul : ∀ a, motive (ofMul a)) : ∀ a, motive a := - fun a => ofMul (toMul a) + fun a => ofMul (a.toMul) end Additive @@ -101,7 +102,7 @@ protected lemma «exists» {p : Multiplicative α → Prop} : (∃ a, p a) ↔ /-- Recursion principle for `Multiplicative`, supported by `cases` and `induction`. -/ @[elab_as_elim, cases_eliminator, induction_eliminator] def rec {motive : Multiplicative α → Sort*} (ofAdd : ∀ a, motive (ofAdd a)) : ∀ a, motive a := - fun a => ofAdd (toAdd a) + fun a => ofAdd (a.toAdd) end Multiplicative @@ -109,19 +110,19 @@ open Additive (ofMul toMul) open Multiplicative (ofAdd toAdd) @[simp] -theorem toAdd_ofAdd (x : α) : toAdd (ofAdd x) = x := +theorem toAdd_ofAdd (x : α) : (ofAdd x).toAdd = x := rfl @[simp] -theorem ofAdd_toAdd (x : Multiplicative α) : ofAdd (toAdd x) = x := +theorem ofAdd_toAdd (x : Multiplicative α) : ofAdd x.toAdd = x := rfl @[simp] -theorem toMul_ofMul (x : α) : toMul (ofMul x) = x := +theorem toMul_ofMul (x : α) : (ofMul x).toMul = x := rfl @[simp] -theorem ofMul_toMul (x : Additive α) : ofMul (toMul x) = x := +theorem ofMul_toMul (x : Additive α) : ofMul x.toMul = x := rfl instance [Subsingleton α] : Subsingleton (Additive α) := toMul.injective.subsingleton @@ -136,16 +137,6 @@ instance [Inhabited α] : Inhabited (Multiplicative α) := instance [Unique α] : Unique (Additive α) := toMul.unique instance [Unique α] : Unique (Multiplicative α) := toAdd.unique -instance [Finite α] : Finite (Additive α) := - Finite.of_equiv α (by rfl) - -instance [Finite α] : Finite (Multiplicative α) := - Finite.of_equiv α (by rfl) - -instance [h : Infinite α] : Infinite (Additive α) := h - -instance [h : Infinite α] : Infinite (Multiplicative α) := h - instance [h : DecidableEq α] : DecidableEq (Multiplicative α) := h instance [h : DecidableEq α] : DecidableEq (Additive α) := h @@ -157,22 +148,22 @@ instance Multiplicative.instNontrivial [Nontrivial α] : Nontrivial (Multiplicat ofAdd.injective.nontrivial instance Additive.add [Mul α] : Add (Additive α) where - add x y := ofMul (toMul x * toMul y) + add x y := ofMul (x.toMul * y.toMul) instance Multiplicative.mul [Add α] : Mul (Multiplicative α) where - mul x y := ofAdd (toAdd x + toAdd y) + mul x y := ofAdd (x.toAdd + y.toAdd) @[simp] theorem ofAdd_add [Add α] (x y : α) : ofAdd (x + y) = ofAdd x * ofAdd y := rfl @[simp] -theorem toAdd_mul [Add α] (x y : Multiplicative α) : toAdd (x * y) = toAdd x + toAdd y := rfl +theorem toAdd_mul [Add α] (x y : Multiplicative α) : (x * y).toAdd = x.toAdd + y.toAdd := rfl @[simp] theorem ofMul_mul [Mul α] (x y : α) : ofMul (x * y) = ofMul x + ofMul y := rfl @[simp] -theorem toMul_add [Mul α] (x y : Additive α) : toMul (x + y) = toMul x * toMul y := rfl +theorem toMul_add [Mul α] (x y : Additive α) : (x + y).toMul = x.toMul * y.toMul := rfl instance Additive.addSemigroup [Semigroup α] : AddSemigroup (Additive α) := { Additive.add with add_assoc := @mul_assoc α _ } @@ -232,11 +223,11 @@ theorem ofMul_one [One α] : @Additive.ofMul α 1 = 0 := rfl theorem ofMul_eq_zero {A : Type*} [One A] {x : A} : Additive.ofMul x = 0 ↔ x = 1 := Iff.rfl @[simp] -theorem toMul_zero [One α] : toMul (0 : Additive α) = 1 := rfl +theorem toMul_zero [One α] : (0 : Additive α).toMul = 1 := rfl @[simp] lemma toMul_eq_one {α : Type*} [One α] {x : Additive α} : - Additive.toMul x = 1 ↔ x = 0 := + x.toMul = 1 ↔ x = 0 := Iff.rfl instance [Zero α] : One (Multiplicative α) := @@ -251,12 +242,12 @@ theorem ofAdd_eq_one {A : Type*} [Zero A] {x : A} : Multiplicative.ofAdd x = 1 Iff.rfl @[simp] -theorem toAdd_one [Zero α] : toAdd (1 : Multiplicative α) = 0 := +theorem toAdd_one [Zero α] : (1 : Multiplicative α).toAdd = 0 := rfl @[simp] lemma toAdd_eq_zero {α : Type*} [Zero α] {x : Multiplicative α} : - Multiplicative.toAdd x = 0 ↔ x = 1 := + x.toAdd = 0 ↔ x = 1 := Iff.rfl instance Additive.addZeroClass [MulOneClass α] : AddZeroClass (Additive α) where @@ -288,7 +279,7 @@ theorem ofMul_pow [Monoid α] (n : ℕ) (a : α) : ofMul (a ^ n) = n • ofMul a rfl @[simp] -theorem toMul_nsmul [Monoid α] (n : ℕ) (a : Additive α) : toMul (n • a) = toMul a ^ n := +theorem toMul_nsmul [Monoid α] (n : ℕ) (a : Additive α) : (n • a).toMul = a.toMul ^ n := rfl @[simp] @@ -296,7 +287,7 @@ theorem ofAdd_nsmul [AddMonoid α] (n : ℕ) (a : α) : ofAdd (n • a) = ofAdd rfl @[simp] -theorem toAdd_pow [AddMonoid α] (a : Multiplicative α) (n : ℕ) : toAdd (a ^ n) = n • toAdd a := +theorem toAdd_pow [AddMonoid α] (a : Multiplicative α) (n : ℕ) : (a ^ n).toAdd = n • a.toAdd := rfl instance Additive.addLeftCancelMonoid [LeftCancelMonoid α] : AddLeftCancelMonoid (Additive α) := @@ -320,39 +311,39 @@ instance Multiplicative.commMonoid [AddCommMonoid α] : CommMonoid (Multiplicati { Multiplicative.monoid, Multiplicative.commSemigroup with } instance Additive.neg [Inv α] : Neg (Additive α) := - ⟨fun x => ofAdd (toMul x)⁻¹⟩ + ⟨fun x => ofAdd x.toMul⁻¹⟩ @[simp] theorem ofMul_inv [Inv α] (x : α) : ofMul x⁻¹ = -ofMul x := rfl @[simp] -theorem toMul_neg [Inv α] (x : Additive α) : toMul (-x) = (toMul x)⁻¹ := +theorem toMul_neg [Inv α] (x : Additive α) : (-x).toMul = x.toMul⁻¹ := rfl instance Multiplicative.inv [Neg α] : Inv (Multiplicative α) := - ⟨fun x => ofMul (-toAdd x)⟩ + ⟨fun x => ofMul (-x.toAdd)⟩ @[simp] theorem ofAdd_neg [Neg α] (x : α) : ofAdd (-x) = (ofAdd x)⁻¹ := rfl @[simp] -theorem toAdd_inv [Neg α] (x : Multiplicative α) : toAdd x⁻¹ = -(toAdd x) := +theorem toAdd_inv [Neg α] (x : Multiplicative α) : x⁻¹.toAdd = -x.toAdd := rfl instance Additive.sub [Div α] : Sub (Additive α) where - sub x y := ofMul (toMul x / toMul y) + sub x y := ofMul (x.toMul / y.toMul) instance Multiplicative.div [Sub α] : Div (Multiplicative α) where - div x y := ofAdd (toAdd x - toAdd y) + div x y := ofAdd (x.toAdd - y.toAdd) @[simp] theorem ofAdd_sub [Sub α] (x y : α) : ofAdd (x - y) = ofAdd x / ofAdd y := rfl @[simp] -theorem toAdd_div [Sub α] (x y : Multiplicative α) : toAdd (x / y) = toAdd x - toAdd y := +theorem toAdd_div [Sub α] (x y : Multiplicative α) : (x / y).toAdd = x.toAdd - y.toAdd := rfl @[simp] @@ -360,7 +351,7 @@ theorem ofMul_div [Div α] (x y : α) : ofMul (x / y) = ofMul x - ofMul y := rfl @[simp] -theorem toMul_sub [Div α] (x y : Additive α) : toMul (x - y) = toMul x / toMul y := +theorem toMul_sub [Div α] (x y : Additive α) : (x - y).toMul = x.toMul / y.toMul := rfl instance Additive.involutiveNeg [InvolutiveInv α] : InvolutiveNeg (Additive α) := @@ -390,7 +381,7 @@ theorem ofMul_zpow [DivInvMonoid α] (z : ℤ) (a : α) : ofMul (a ^ z) = z • rfl @[simp] -theorem toMul_zsmul [DivInvMonoid α] (z : ℤ) (a : Additive α) : toMul (z • a) = toMul a ^ z := +theorem toMul_zsmul [DivInvMonoid α] (z : ℤ) (a : Additive α) : (z • a).toMul = a.toMul ^ z := rfl @[simp] @@ -398,7 +389,7 @@ theorem ofAdd_zsmul [SubNegMonoid α] (z : ℤ) (a : α) : ofAdd (z • a) = ofA rfl @[simp] -theorem toAdd_zpow [SubNegMonoid α] (a : Multiplicative α) (z : ℤ) : toAdd (a ^ z) = z • toAdd a := +theorem toAdd_zpow [SubNegMonoid α] (a : Multiplicative α) (z : ℤ) : (a ^ z).toAdd = z • a.toAdd := rfl instance Additive.subtractionMonoid [DivisionMonoid α] : SubtractionMonoid (Additive α) := @@ -431,110 +422,6 @@ instance Additive.addCommGroup [CommGroup α] : AddCommGroup (Additive α) := instance Multiplicative.commGroup [AddCommGroup α] : CommGroup (Multiplicative α) := { Multiplicative.group, Multiplicative.commMonoid with } -/-- Reinterpret `α →+ β` as `Multiplicative α →* Multiplicative β`. -/ -@[simps] -def AddMonoidHom.toMultiplicative [AddZeroClass α] [AddZeroClass β] : - (α →+ β) ≃ (Multiplicative α →* Multiplicative β) where - toFun f := { - toFun := fun a => ofAdd (f (toAdd a)) - map_mul' := f.map_add - map_one' := f.map_zero - } - invFun f := { - toFun := fun a => toAdd (f (ofAdd a)) - map_add' := f.map_mul - map_zero' := f.map_one - } - left_inv _ := rfl - right_inv _ := rfl - -@[simp, norm_cast] -lemma AddMonoidHom.coe_toMultiplicative [AddZeroClass α] [AddZeroClass β] (f : α →+ β) : - ⇑(toMultiplicative f) = ofAdd ∘ f ∘ toAdd := rfl - -/-- Reinterpret `α →* β` as `Additive α →+ Additive β`. -/ -@[simps] -def MonoidHom.toAdditive [MulOneClass α] [MulOneClass β] : - (α →* β) ≃ (Additive α →+ Additive β) where - toFun f := { - toFun := fun a => ofMul (f (toMul a)) - map_add' := f.map_mul - map_zero' := f.map_one - } - invFun f := { - toFun := fun a => toMul (f (ofMul a)) - map_mul' := f.map_add - map_one' := f.map_zero - } - left_inv _ := rfl - right_inv _ := rfl - -@[simp, norm_cast] -lemma MonoidHom.coe_toMultiplicative [MulOneClass α] [MulOneClass β] (f : α →* β) : - ⇑(toAdditive f) = ofMul ∘ f ∘ toMul := rfl - -/-- Reinterpret `Additive α →+ β` as `α →* Multiplicative β`. -/ -@[simps] -def AddMonoidHom.toMultiplicative' [MulOneClass α] [AddZeroClass β] : - (Additive α →+ β) ≃ (α →* Multiplicative β) where - toFun f := { - toFun := fun a => ofAdd (f (ofMul a)) - map_mul' := f.map_add - map_one' := f.map_zero - } - invFun f := { - toFun := fun a => toAdd (f (toMul a)) - map_add' := f.map_mul - map_zero' := f.map_one - } - left_inv _ := rfl - right_inv _ := rfl - -@[simp, norm_cast] -lemma AddMonoidHom.coe_toMultiplicative' [MulOneClass α] [AddZeroClass β] (f : Additive α →+ β) : - ⇑(toMultiplicative' f) = ofAdd ∘ f ∘ ofMul := rfl - -/-- Reinterpret `α →* Multiplicative β` as `Additive α →+ β`. -/ -@[simps!] -def MonoidHom.toAdditive' [MulOneClass α] [AddZeroClass β] : - (α →* Multiplicative β) ≃ (Additive α →+ β) := - AddMonoidHom.toMultiplicative'.symm - -@[simp, norm_cast] -lemma MonoidHom.coe_toAdditive' [MulOneClass α] [AddZeroClass β] (f : α →* Multiplicative β) : - ⇑(toAdditive' f) = toAdd ∘ f ∘ toMul := rfl - -/-- Reinterpret `α →+ Additive β` as `Multiplicative α →* β`. -/ -@[simps] -def AddMonoidHom.toMultiplicative'' [AddZeroClass α] [MulOneClass β] : - (α →+ Additive β) ≃ (Multiplicative α →* β) where - toFun f := { - toFun := fun a => toMul (f (toAdd a)) - map_mul' := f.map_add - map_one' := f.map_zero - } - invFun f := { - toFun := fun a => ofMul (f (ofAdd a)) - map_add' := f.map_mul - map_zero' := f.map_one - } - left_inv _ := rfl - right_inv _ := rfl - -@[simp, norm_cast] -lemma AddMonoidHom.coe_toMultiplicative'' [AddZeroClass α] [MulOneClass β] (f : α →+ Additive β) : - ⇑(toMultiplicative'' f) = toMul ∘ f ∘ toAdd := rfl - -/-- Reinterpret `Multiplicative α →* β` as `α →+ Additive β`. -/ -@[simps!] -def MonoidHom.toAdditive'' [AddZeroClass α] [MulOneClass β] : - (Multiplicative α →* β) ≃ (α →+ Additive β) := - AddMonoidHom.toMultiplicative''.symm - -@[simp, norm_cast] -lemma MonoidHom.coe_toAdditive'' [AddZeroClass α] [MulOneClass β] (f : Multiplicative α →* β) : - ⇑(toAdditive'' f) = ofMul ∘ f ∘ ofAdd := rfl - /-- If `α` has some multiplicative structure and coerces to a function, then `Additive α` should also coerce to the same function. @@ -542,8 +429,8 @@ This allows `Additive` to be used on bundled function types with a multiplicativ is often used for composition, without affecting the behavior of the function itself. -/ instance Additive.coeToFun {α : Type*} {β : α → Sort*} [CoeFun α β] : - CoeFun (Additive α) fun a => β (toMul a) := - ⟨fun a => CoeFun.coe (toMul a)⟩ + CoeFun (Additive α) fun a => β a.toMul := + ⟨fun a => CoeFun.coe a.toMul⟩ /-- If `α` has some additive structure and coerces to a function, then `Multiplicative α` should also coerce to the same function. @@ -552,8 +439,8 @@ This allows `Multiplicative` to be used on bundled function types with an additi is often used for composition, without affecting the behavior of the function itself. -/ instance Multiplicative.coeToFun {α : Type*} {β : α → Sort*} [CoeFun α β] : - CoeFun (Multiplicative α) fun a => β (toAdd a) := - ⟨fun a => CoeFun.coe (toAdd a)⟩ + CoeFun (Multiplicative α) fun a => β a.toAdd := + ⟨fun a => CoeFun.coe a.toAdd⟩ lemma Pi.mulSingle_multiplicativeOfAdd_eq {ι : Type*} [DecidableEq ι] {M : ι → Type*} [(i : ι) → AddMonoid (M i)] (i : ι) (a : M i) (j : ι) : diff --git a/Mathlib/Algebra/Group/TypeTags/Finite.lean b/Mathlib/Algebra/Group/TypeTags/Finite.lean new file mode 100644 index 0000000000000..e3885696b373b --- /dev/null +++ b/Mathlib/Algebra/Group/TypeTags/Finite.lean @@ -0,0 +1,28 @@ +/- +Copyright (c) 2018 Mario Carneiro. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Mario Carneiro +-/ +import Mathlib.Algebra.Group.TypeTags.Basic +import Mathlib.Data.Finite.Defs + +/-! +# `Finite` and `Infinite` are preserved by `Additive` and `Multiplicative`. +-/ + +assert_not_exists MonoidWithZero +assert_not_exists DenselyOrdered + +universe u v + +variable {α : Type u} + +instance [Finite α] : Finite (Additive α) := + Finite.of_equiv α (by rfl) + +instance [Finite α] : Finite (Multiplicative α) := + Finite.of_equiv α (by rfl) + +instance [h : Infinite α] : Infinite (Additive α) := h + +instance [h : Infinite α] : Infinite (Multiplicative α) := h diff --git a/Mathlib/Algebra/Group/TypeTags/Hom.lean b/Mathlib/Algebra/Group/TypeTags/Hom.lean new file mode 100644 index 0000000000000..909615b47da55 --- /dev/null +++ b/Mathlib/Algebra/Group/TypeTags/Hom.lean @@ -0,0 +1,123 @@ +/- +Copyright (c) 2018 Mario Carneiro. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Mario Carneiro +-/ +import Mathlib.Algebra.Group.Hom.Defs +import Mathlib.Algebra.Group.TypeTags.Basic + +/-! +# Transport algebra morphisms between additive and multiplicative types. +-/ + + +universe u v + +variable {α : Type u} {β : Type v} + +open Additive (ofMul toMul) +open Multiplicative (ofAdd toAdd) + +/-- Reinterpret `α →+ β` as `Multiplicative α →* Multiplicative β`. -/ +@[simps] +def AddMonoidHom.toMultiplicative [AddZeroClass α] [AddZeroClass β] : + (α →+ β) ≃ (Multiplicative α →* Multiplicative β) where + toFun f := { + toFun := fun a => ofAdd (f a.toAdd) + map_mul' := f.map_add + map_one' := f.map_zero + } + invFun f := { + toFun := fun a => f (ofAdd a) |>.toAdd + map_add' := f.map_mul + map_zero' := f.map_one + } + left_inv _ := rfl + right_inv _ := rfl + +@[simp, norm_cast] +lemma AddMonoidHom.coe_toMultiplicative [AddZeroClass α] [AddZeroClass β] (f : α →+ β) : + ⇑(toMultiplicative f) = ofAdd ∘ f ∘ toAdd := rfl + +/-- Reinterpret `α →* β` as `Additive α →+ Additive β`. -/ +@[simps] +def MonoidHom.toAdditive [MulOneClass α] [MulOneClass β] : + (α →* β) ≃ (Additive α →+ Additive β) where + toFun f := { + toFun := fun a => ofMul (f a.toMul) + map_add' := f.map_mul + map_zero' := f.map_one + } + invFun f := { + toFun := fun a => (f (ofMul a)).toMul + map_mul' := f.map_add + map_one' := f.map_zero + } + left_inv _ := rfl + right_inv _ := rfl + +@[simp, norm_cast] +lemma MonoidHom.coe_toMultiplicative [MulOneClass α] [MulOneClass β] (f : α →* β) : + ⇑(toAdditive f) = ofMul ∘ f ∘ toMul := rfl + +/-- Reinterpret `Additive α →+ β` as `α →* Multiplicative β`. -/ +@[simps] +def AddMonoidHom.toMultiplicative' [MulOneClass α] [AddZeroClass β] : + (Additive α →+ β) ≃ (α →* Multiplicative β) where + toFun f := { + toFun := fun a => ofAdd (f (ofMul a)) + map_mul' := f.map_add + map_one' := f.map_zero + } + invFun f := { + toFun := fun a => (f a.toMul).toAdd + map_add' := f.map_mul + map_zero' := f.map_one + } + left_inv _ := rfl + right_inv _ := rfl + +@[simp, norm_cast] +lemma AddMonoidHom.coe_toMultiplicative' [MulOneClass α] [AddZeroClass β] (f : Additive α →+ β) : + ⇑(toMultiplicative' f) = ofAdd ∘ f ∘ ofMul := rfl + +/-- Reinterpret `α →* Multiplicative β` as `Additive α →+ β`. -/ +@[simps!] +def MonoidHom.toAdditive' [MulOneClass α] [AddZeroClass β] : + (α →* Multiplicative β) ≃ (Additive α →+ β) := + AddMonoidHom.toMultiplicative'.symm + +@[simp, norm_cast] +lemma MonoidHom.coe_toAdditive' [MulOneClass α] [AddZeroClass β] (f : α →* Multiplicative β) : + ⇑(toAdditive' f) = toAdd ∘ f ∘ toMul := rfl + +/-- Reinterpret `α →+ Additive β` as `Multiplicative α →* β`. -/ +@[simps] +def AddMonoidHom.toMultiplicative'' [AddZeroClass α] [MulOneClass β] : + (α →+ Additive β) ≃ (Multiplicative α →* β) where + toFun f := { + toFun := fun a => (f a.toAdd).toMul + map_mul' := f.map_add + map_one' := f.map_zero + } + invFun f := { + toFun := fun a => ofMul (f (ofAdd a)) + map_add' := f.map_mul + map_zero' := f.map_one + } + left_inv _ := rfl + right_inv _ := rfl + +@[simp, norm_cast] +lemma AddMonoidHom.coe_toMultiplicative'' [AddZeroClass α] [MulOneClass β] (f : α →+ Additive β) : + ⇑(toMultiplicative'' f) = toMul ∘ f ∘ toAdd := rfl + +/-- Reinterpret `Multiplicative α →* β` as `α →+ Additive β`. -/ +@[simps!] +def MonoidHom.toAdditive'' [AddZeroClass α] [MulOneClass β] : + (Multiplicative α →* β) ≃ (α →+ Additive β) := + AddMonoidHom.toMultiplicative''.symm + +@[simp, norm_cast] +lemma MonoidHom.coe_toAdditive'' [AddZeroClass α] [MulOneClass β] (f : Multiplicative α →* β) : + ⇑(toAdditive'' f) = ofMul ∘ f ∘ ofAdd := rfl diff --git a/Mathlib/Algebra/Group/WithOne/Basic.lean b/Mathlib/Algebra/Group/WithOne/Basic.lean index 3dca5ba0dab77..b9d87ce1b04af 100644 --- a/Mathlib/Algebra/Group/WithOne/Basic.lean +++ b/Mathlib/Algebra/Group/WithOne/Basic.lean @@ -73,8 +73,7 @@ variable (f : α →ₙ* β) theorem lift_coe (x : α) : lift f x = f x := rfl --- Porting note (#11119): removed `simp` attribute to appease `simpNF` linter. -@[to_additive] +@[to_additive (attr := simp)] theorem lift_one : lift f 1 = 1 := rfl diff --git a/Mathlib/Algebra/GroupPower/IterateHom.lean b/Mathlib/Algebra/GroupPower/IterateHom.lean index 1a3170e11ac09..ae097ed297d67 100644 --- a/Mathlib/Algebra/GroupPower/IterateHom.lean +++ b/Mathlib/Algebra/GroupPower/IterateHom.lean @@ -5,7 +5,6 @@ Authors: Yury Kudryashov -/ import Mathlib.Algebra.Group.Action.Opposite import Mathlib.Algebra.Group.Int -import Mathlib.Algebra.Group.Nat import Mathlib.Logic.Function.Iterate import Mathlib.Tactic.Common diff --git a/Mathlib/Algebra/GroupWithZero/Conj.lean b/Mathlib/Algebra/GroupWithZero/Conj.lean index 17ccffc430192..6aea4c22972a7 100644 --- a/Mathlib/Algebra/GroupWithZero/Conj.lean +++ b/Mathlib/Algebra/GroupWithZero/Conj.lean @@ -14,9 +14,17 @@ assert_not_exists Multiset -- TODO -- assert_not_exists DenselyOrdered +namespace GroupWithZero + variable {α : Type*} [GroupWithZero α] {a b : α} @[simp] lemma isConj_iff₀ : IsConj a b ↔ ∃ c : α, c ≠ 0 ∧ c * a * c⁻¹ = b := by rw [IsConj, Units.exists_iff_ne_zero (p := (SemiconjBy · a b))] congr! 2 with c exact and_congr_right (mul_inv_eq_iff_eq_mul₀ · |>.symm) + +lemma conj_pow₀ {s : ℕ} {a d : α} (ha : a ≠ 0) : (a⁻¹ * d * a) ^ s = a⁻¹ * d ^ s * a := + let u : αˣ := ⟨a, a⁻¹, mul_inv_cancel₀ ha, inv_mul_cancel₀ ha⟩ + Units.conj_pow' u d s + +end GroupWithZero diff --git a/Mathlib/Algebra/GroupWithZero/Pointwise/Set/Card.lean b/Mathlib/Algebra/GroupWithZero/Pointwise/Set/Card.lean index 8466c8876f1c1..4e144b113a816 100644 --- a/Mathlib/Algebra/GroupWithZero/Pointwise/Set/Card.lean +++ b/Mathlib/Algebra/GroupWithZero/Pointwise/Set/Card.lean @@ -13,7 +13,7 @@ import Mathlib.SetTheory.Cardinal.Finite open scoped Cardinal Pointwise -variable {G G₀ M M₀ : Type*} +variable {G₀ M₀ : Type*} namespace Set variable [GroupWithZero G₀] [Zero M₀] [MulActionWithZero G₀ M₀] {a : G₀} diff --git a/Mathlib/Algebra/GroupWithZero/Units/Basic.lean b/Mathlib/Algebra/GroupWithZero/Units/Basic.lean index 4eed1a7034205..be6aebca0a776 100644 --- a/Mathlib/Algebra/GroupWithZero/Units/Basic.lean +++ b/Mathlib/Algebra/GroupWithZero/Units/Basic.lean @@ -422,9 +422,9 @@ instance (priority := 100) CommGroupWithZero.toDivisionCommMonoid : lemma div_mul_cancel_left₀ (ha : a ≠ 0) (b : G₀) : a / (a * b) = b⁻¹ := ha.isUnit.div_mul_cancel_left _ -set_option linter.deprecated false in @[deprecated div_mul_cancel_left₀ (since := "2024-03-22")] -lemma div_mul_right (b : G₀) (ha : a ≠ 0) : a / (a * b) = 1 / b := ha.isUnit.div_mul_right _ +lemma div_mul_right (b : G₀) (ha : a ≠ 0) : a / (a * b) = 1 / b := by + simp [div_mul_cancel_left₀ ha] lemma mul_div_cancel_left_of_imp (h : a = 0 → b = 0) : a * b / a = b := by rw [mul_comm, mul_div_cancel_of_imp h] diff --git a/Mathlib/Algebra/Homology/Additive.lean b/Mathlib/Algebra/Homology/Additive.lean index 5fbebb2c8beb9..1b14c45bf5b00 100644 --- a/Mathlib/Algebra/Homology/Additive.lean +++ b/Mathlib/Algebra/Homology/Additive.lean @@ -23,8 +23,8 @@ variable {ι : Type*} variable {V : Type u} [Category.{v} V] [Preadditive V] variable {W : Type*} [Category W] [Preadditive W] variable {W₁ W₂ : Type*} [Category W₁] [Category W₂] [HasZeroMorphisms W₁] [HasZeroMorphisms W₂] -variable {c : ComplexShape ι} {C D E : HomologicalComplex V c} -variable (f g : C ⟶ D) (h k : D ⟶ E) (i : ι) +variable {c : ComplexShape ι} {C D : HomologicalComplex V c} +variable (f : C ⟶ D) (i : ι) namespace HomologicalComplex diff --git a/Mathlib/Algebra/Homology/ShortComplex/Homology.lean b/Mathlib/Algebra/Homology/ShortComplex/Homology.lean index 25854245e340c..0c416a49f4df5 100644 --- a/Mathlib/Algebra/Homology/ShortComplex/Homology.lean +++ b/Mathlib/Algebra/Homology/ShortComplex/Homology.lean @@ -70,8 +70,6 @@ structure HomologyMapData where namespace HomologyMapData -attribute [nolint simpNF] mk.injEq - variable {φ h₁ h₂} @[reassoc] diff --git a/Mathlib/Algebra/Homology/ShortComplex/LeftHomology.lean b/Mathlib/Algebra/Homology/ShortComplex/LeftHomology.lean index 1022a52c7ab90..a8abcedd4972c 100644 --- a/Mathlib/Algebra/Homology/ShortComplex/LeftHomology.lean +++ b/Mathlib/Algebra/Homology/ShortComplex/LeftHomology.lean @@ -266,7 +266,6 @@ structure LeftHomologyMapData where namespace LeftHomologyMapData attribute [reassoc (attr := simp)] commi commf' commπ -attribute [nolint simpNF] mk.injEq /-- The left homology map data associated to the zero morphism between two short complexes. -/ @[simps] diff --git a/Mathlib/Algebra/Homology/ShortComplex/RightHomology.lean b/Mathlib/Algebra/Homology/ShortComplex/RightHomology.lean index 865ffa00b94fb..3592289533893 100644 --- a/Mathlib/Algebra/Homology/ShortComplex/RightHomology.lean +++ b/Mathlib/Algebra/Homology/ShortComplex/RightHomology.lean @@ -356,7 +356,6 @@ structure RightHomologyMapData where namespace RightHomologyMapData attribute [reassoc (attr := simp)] commp commg' commι -attribute [nolint simpNF] mk.injEq /-- The right homology map data associated to the zero morphism between two short complexes. -/ @[simps] diff --git a/Mathlib/Algebra/Lie/IdealOperations.lean b/Mathlib/Algebra/Lie/IdealOperations.lean index 75e9facacd878..459dce3dfdbf0 100644 --- a/Mathlib/Algebra/Lie/IdealOperations.lean +++ b/Mathlib/Algebra/Lie/IdealOperations.lean @@ -192,12 +192,10 @@ theorem sup_lie : ⁅I ⊔ J, N⁆ = ⁅I, N⁆ ⊔ ⁅J, N⁆ := by use ⁅((⟨x₂, hx₂⟩ : J) : L), (n : N)⁆; constructor; · apply lie_coe_mem_lie simp [← h, ← hx'] --- @[simp] -- Porting note: not in simpNF theorem lie_inf : ⁅I, N ⊓ N'⁆ ≤ ⁅I, N⁆ ⊓ ⁅I, N'⁆ := by rw [le_inf_iff]; constructor <;> apply mono_lie_right <;> [exact inf_le_left; exact inf_le_right] --- @[simp] -- Porting note: not in simpNF theorem inf_lie : ⁅I ⊓ J, N⁆ ≤ ⁅I, N⁆ ⊓ ⁅J, N⁆ := by rw [le_inf_iff]; constructor <;> apply mono_lie_left <;> [exact inf_le_left; exact inf_le_right] diff --git a/Mathlib/Algebra/Lie/Semisimple/Basic.lean b/Mathlib/Algebra/Lie/Semisimple/Basic.lean index fd912b2c8ef78..791f324394561 100644 --- a/Mathlib/Algebra/Lie/Semisimple/Basic.lean +++ b/Mathlib/Algebra/Lie/Semisimple/Basic.lean @@ -147,7 +147,7 @@ lemma isSimple_of_isAtom (I : LieIdeal R L) (hI : IsAtom I) : IsSimple R I where -- Finally `⁅b, y⁆ = 0`, by the independence of the atoms. · suffices ⁅b, y.val⁆ = 0 by erw [this]; simp only [zero_mem] rw [← LieSubmodule.mem_bot (R := R) (L := L), - ← (IsSemisimple.setIndependent_isAtom hI).eq_bot] + ← (IsSemisimple.sSupIndep_isAtom hI).eq_bot] exact ⟨lie_mem_right R L I b y y.2, lie_mem_left _ _ _ _ _ hb⟩ } -- Now that we know that `J` is an ideal of `L`, -- we start with the proof that `I` is a simple Lie algebra. @@ -244,7 +244,7 @@ lemma finitelyAtomistic : ∀ s : Finset (LieIdeal R L), ↑s ⊆ {I : LieIdeal constructor -- `j` brackets to `0` with `z`, since `⁅j, z⁆` is contained in `⁅J, K⁆ ≤ J ⊓ K`, -- and `J ⊓ K = ⊥` by the independence of the atoms. - · apply (setIndependent_isAtom.disjoint_sSup (hs hJs) hs'S (Finset.not_mem_erase _ _)).le_bot + · apply (sSupIndep_isAtom.disjoint_sSup (hs hJs) hs'S (Finset.not_mem_erase _ _)).le_bot apply LieSubmodule.lie_le_inf apply LieSubmodule.lie_mem_lie j.2 simpa only [K, Finset.sup_id_eq_sSup] using hz @@ -296,7 +296,7 @@ instance (priority := 100) IsSimple.instIsSemisimple [IsSimple R L] : IsSemisimple R L := by constructor · simp - · simpa using CompleteLattice.setIndependent_singleton _ + · simpa using sSupIndep_singleton _ · intro I hI₁ hI₂ apply IsSimple.non_abelian (R := R) (L := L) rw [IsSimple.isAtom_iff_eq_top] at hI₁ diff --git a/Mathlib/Algebra/Lie/Semisimple/Defs.lean b/Mathlib/Algebra/Lie/Semisimple/Defs.lean index 018f07cacb964..74db546a94643 100644 --- a/Mathlib/Algebra/Lie/Semisimple/Defs.lean +++ b/Mathlib/Algebra/Lie/Semisimple/Defs.lean @@ -72,7 +72,7 @@ class IsSemisimple : Prop where /-- In a semisimple Lie algebra, the supremum of the atoms is the whole Lie algebra. -/ sSup_atoms_eq_top : sSup {I : LieIdeal R L | IsAtom I} = ⊤ /-- In a semisimple Lie algebra, the atoms are independent. -/ - setIndependent_isAtom : CompleteLattice.SetIndependent {I : LieIdeal R L | IsAtom I} + sSupIndep_isAtom : sSupIndep {I : LieIdeal R L | IsAtom I} /-- In a semisimple Lie algebra, the atoms are non-abelian. -/ non_abelian_of_isAtom : ∀ I : LieIdeal R L, IsAtom I → ¬ IsLieAbelian I diff --git a/Mathlib/Algebra/Lie/Submodule.lean b/Mathlib/Algebra/Lie/Submodule.lean index c6fc1d659955f..1201232787862 100644 --- a/Mathlib/Algebra/Lie/Submodule.lean +++ b/Mathlib/Algebra/Lie/Submodule.lean @@ -514,9 +514,12 @@ theorem isCompl_iff_coe_toSubmodule : IsCompl N N' ↔ IsCompl (N : Submodule R M) (N' : Submodule R M) := by simp only [isCompl_iff, disjoint_iff_coe_toSubmodule, codisjoint_iff_coe_toSubmodule] -theorem independent_iff_coe_toSubmodule {ι : Type*} {N : ι → LieSubmodule R L M} : - CompleteLattice.Independent N ↔ CompleteLattice.Independent fun i ↦ (N i : Submodule R M) := by - simp [CompleteLattice.independent_def, disjoint_iff_coe_toSubmodule] +theorem iSupIndep_iff_coe_toSubmodule {ι : Type*} {N : ι → LieSubmodule R L M} : + iSupIndep N ↔ iSupIndep fun i ↦ (N i : Submodule R M) := by + simp [iSupIndep_def, disjoint_iff_coe_toSubmodule] + +@[deprecated (since := "2024-11-24")] +alias independent_iff_coe_toSubmodule := iSupIndep_iff_coe_toSubmodule theorem iSup_eq_top_iff_coe_toSubmodule {ι : Sort*} {N : ι → LieSubmodule R L M} : ⨆ i, N i = ⊤ ↔ ⨆ i, (N i : Submodule R M) = ⊤ := by diff --git a/Mathlib/Algebra/Lie/TraceForm.lean b/Mathlib/Algebra/Lie/TraceForm.lean index 2d1253e2b18c9..55ee3be037f29 100644 --- a/Mathlib/Algebra/Lie/TraceForm.lean +++ b/Mathlib/Algebra/Lie/TraceForm.lean @@ -227,8 +227,8 @@ lemma traceForm_eq_sum_genWeightSpaceOf convert finite_genWeightSpaceOf_ne_bot R L M z exact LieSubmodule.coeSubmodule_eq_bot_iff (genWeightSpaceOf M _ _) classical - have h := LieSubmodule.independent_iff_coe_toSubmodule.mp <| independent_genWeightSpaceOf R L M z - have hds := DirectSum.isInternal_submodule_of_independent_of_iSup_eq_top h <| by + have h := LieSubmodule.iSupIndep_iff_coe_toSubmodule.mp <| iSupIndep_genWeightSpaceOf R L M z + have hds := DirectSum.isInternal_submodule_of_iSupIndep_of_iSup_eq_top h <| by simp [← LieSubmodule.iSup_coe_toSubmodule] simp only [LinearMap.coeFn_sum, Finset.sum_apply, traceForm_apply_apply, LinearMap.trace_eq_sum_trace_restrict' hds hfin hxy] @@ -407,8 +407,8 @@ lemma traceForm_eq_sum_finrank_nsmul_mul (x y : L) : (genWeightSpace M χ) (genWeightSpace M χ) := fun χ m hm ↦ LieSubmodule.lie_mem _ <| LieSubmodule.lie_mem _ hm classical - have hds := DirectSum.isInternal_submodule_of_independent_of_iSup_eq_top - (LieSubmodule.independent_iff_coe_toSubmodule.mp <| independent_genWeightSpace' K L M) + have hds := DirectSum.isInternal_submodule_of_iSupIndep_of_iSup_eq_top + (LieSubmodule.iSupIndep_iff_coe_toSubmodule.mp <| iSupIndep_genWeightSpace' K L M) (LieSubmodule.iSup_eq_top_iff_coe_toSubmodule.mp <| iSup_genWeightSpace_eq_top' K L M) simp_rw [traceForm_apply_apply, LinearMap.trace_eq_sum_trace_restrict hds hxy, ← traceForm_genWeightSpace_eq K L M _ x y] diff --git a/Mathlib/Algebra/Lie/Weights/Basic.lean b/Mathlib/Algebra/Lie/Weights/Basic.lean index ce2e34ec7f66e..8ddf44e6372c7 100644 --- a/Mathlib/Algebra/Lie/Weights/Basic.lean +++ b/Mathlib/Algebra/Lie/Weights/Basic.lean @@ -33,7 +33,7 @@ Basic definitions and properties of the above ideas are provided in this file. * `LieModule.iSup_ucs_eq_genWeightSpace_zero` * `LieModule.iInf_lowerCentralSeries_eq_posFittingComp` * `LieModule.isCompl_genWeightSpace_zero_posFittingComp` - * `LieModule.independent_genWeightSpace` + * `LieModule.iSupIndep_genWeightSpace` * `LieModule.iSup_genWeightSpace_eq_top` ## References @@ -666,32 +666,39 @@ lemma injOn_genWeightSpace [NoZeroSMulDivisors R M] : /-- Lie module weight spaces are independent. -See also `LieModule.independent_genWeightSpace'`. -/ -lemma independent_genWeightSpace [NoZeroSMulDivisors R M] : - CompleteLattice.Independent fun χ : L → R ↦ genWeightSpace M χ := by - simp only [LieSubmodule.independent_iff_coe_toSubmodule, genWeightSpace, +See also `LieModule.iSupIndep_genWeightSpace'`. -/ +lemma iSupIndep_genWeightSpace [NoZeroSMulDivisors R M] : + iSupIndep fun χ : L → R ↦ genWeightSpace M χ := by + simp only [LieSubmodule.iSupIndep_iff_coe_toSubmodule, genWeightSpace, LieSubmodule.iInf_coe_toSubmodule] exact Module.End.independent_iInf_maxGenEigenspace_of_forall_mapsTo (toEnd R L M) (fun x y φ z ↦ (genWeightSpaceOf M φ y).lie_mem) -lemma independent_genWeightSpace' [NoZeroSMulDivisors R M] : - CompleteLattice.Independent fun χ : Weight R L M ↦ genWeightSpace M χ := - (independent_genWeightSpace R L M).comp <| +@[deprecated (since := "2024-11-24")] alias independent_genWeightSpace := iSupIndep_genWeightSpace + +lemma iSupIndep_genWeightSpace' [NoZeroSMulDivisors R M] : + iSupIndep fun χ : Weight R L M ↦ genWeightSpace M χ := + (iSupIndep_genWeightSpace R L M).comp <| Subtype.val_injective.comp (Weight.equivSetOf R L M).injective -lemma independent_genWeightSpaceOf [NoZeroSMulDivisors R M] (x : L) : - CompleteLattice.Independent fun (χ : R) ↦ genWeightSpaceOf M χ x := by - rw [LieSubmodule.independent_iff_coe_toSubmodule] +@[deprecated (since := "2024-11-24")] alias independent_genWeightSpace' := iSupIndep_genWeightSpace' + +lemma iSupIndep_genWeightSpaceOf [NoZeroSMulDivisors R M] (x : L) : + iSupIndep fun (χ : R) ↦ genWeightSpaceOf M χ x := by + rw [LieSubmodule.iSupIndep_iff_coe_toSubmodule] dsimp [genWeightSpaceOf] exact (toEnd R L M x).independent_genEigenspace _ +@[deprecated (since := "2024-11-24")] +alias independent_genWeightSpaceOf := iSupIndep_genWeightSpaceOf + lemma finite_genWeightSpaceOf_ne_bot [NoZeroSMulDivisors R M] [IsNoetherian R M] (x : L) : {χ : R | genWeightSpaceOf M χ x ≠ ⊥}.Finite := - CompleteLattice.WellFoundedGT.finite_ne_bot_of_independent (independent_genWeightSpaceOf R L M x) + WellFoundedGT.finite_ne_bot_of_iSupIndep (iSupIndep_genWeightSpaceOf R L M x) lemma finite_genWeightSpace_ne_bot [NoZeroSMulDivisors R M] [IsNoetherian R M] : {χ : L → R | genWeightSpace M χ ≠ ⊥}.Finite := - CompleteLattice.WellFoundedGT.finite_ne_bot_of_independent (independent_genWeightSpace R L M) + WellFoundedGT.finite_ne_bot_of_iSupIndep (iSupIndep_genWeightSpace R L M) instance Weight.instFinite [NoZeroSMulDivisors R M] [IsNoetherian R M] : Finite (Weight R L M) := by diff --git a/Mathlib/Algebra/Lie/Weights/Chain.lean b/Mathlib/Algebra/Lie/Weights/Chain.lean index 4107e1e4cd27f..1acfd102224c7 100644 --- a/Mathlib/Algebra/Lie/Weights/Chain.lean +++ b/Mathlib/Algebra/Lie/Weights/Chain.lean @@ -204,9 +204,9 @@ lemma exists_forall_mem_corootSpace_smul_add_eq_zero exact finrank_pos refine ⟨a, b, Int.ofNat_pos.mpr hb, fun x hx ↦ ?_⟩ let N : ℤ → Submodule R M := fun k ↦ genWeightSpace M (k • α + χ) - have h₁ : CompleteLattice.Independent fun (i : Finset.Ioo p q) ↦ N i := by - rw [← LieSubmodule.independent_iff_coe_toSubmodule] - refine (independent_genWeightSpace R H M).comp fun i j hij ↦ ?_ + have h₁ : iSupIndep fun (i : Finset.Ioo p q) ↦ N i := by + rw [← LieSubmodule.iSupIndep_iff_coe_toSubmodule] + refine (iSupIndep_genWeightSpace R H M).comp fun i j hij ↦ ?_ exact SetCoe.ext <| smul_left_injective ℤ hα <| by rwa [add_left_inj] at hij have h₂ : ∀ i, MapsTo (toEnd R H M x) ↑(N i) ↑(N i) := fun _ _ ↦ LieSubmodule.lie_mem _ have h₃ : genWeightSpaceChain M α χ p q = ⨆ i ∈ Finset.Ioo p q, N i := by diff --git a/Mathlib/Algebra/Lie/Weights/Killing.lean b/Mathlib/Algebra/Lie/Weights/Killing.lean index 3fe00e4149748..7c2b6ece5a6b5 100644 --- a/Mathlib/Algebra/Lie/Weights/Killing.lean +++ b/Mathlib/Algebra/Lie/Weights/Killing.lean @@ -112,8 +112,8 @@ lemma killingForm_apply_eq_zero_of_mem_rootSpace_of_add_ne_zero {α β : H → K (mapsTo_toEnd_genWeightSpace_add_of_mem_rootSpace K L H L α (β + γ) hx).comp <| mapsTo_toEnd_genWeightSpace_add_of_mem_rootSpace K L H L β γ hy classical - have hds := DirectSum.isInternal_submodule_of_independent_of_iSup_eq_top - (LieSubmodule.independent_iff_coe_toSubmodule.mp <| independent_genWeightSpace K H L) + have hds := DirectSum.isInternal_submodule_of_iSupIndep_of_iSup_eq_top + (LieSubmodule.iSupIndep_iff_coe_toSubmodule.mp <| iSupIndep_genWeightSpace K H L) (LieSubmodule.iSup_eq_top_iff_coe_toSubmodule.mp <| iSup_genWeightSpace_eq_top K H L) exact LinearMap.trace_eq_zero_of_mapsTo_ne hds σ hσ hf diff --git a/Mathlib/Algebra/Module/FinitePresentation.lean b/Mathlib/Algebra/Module/FinitePresentation.lean index a4d6e21f87576..b5737ac1b8e49 100644 --- a/Mathlib/Algebra/Module/FinitePresentation.lean +++ b/Mathlib/Algebra/Module/FinitePresentation.lean @@ -4,10 +4,13 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Andrew Yang -/ import Mathlib.LinearAlgebra.FreeModule.Finite.Basic +import Mathlib.LinearAlgebra.TensorProduct.RightExactness import Mathlib.LinearAlgebra.Isomorphisms import Mathlib.RingTheory.Finiteness.Projective -import Mathlib.RingTheory.Localization.Module -import Mathlib.RingTheory.Noetherian.Defs +import Mathlib.RingTheory.Finiteness.TensorProduct +import Mathlib.RingTheory.Localization.BaseChange +import Mathlib.RingTheory.Noetherian.Basic + /-! # Finitely Presented Modules @@ -232,6 +235,36 @@ section CommRing variable {R M N N'} [CommRing R] [AddCommGroup M] [Module R M] [AddCommGroup N] [Module R N] variable [AddCommGroup N'] [Module R N'] (S : Submonoid R) (f : N →ₗ[R] N') [IsLocalizedModule S f] +open TensorProduct in +instance {A} [CommRing A] [Algebra R A] [Module.FinitePresentation R M] : + Module.FinitePresentation A (A ⊗[R] M) := by + classical + obtain ⟨n, f, hf⟩ := Module.Finite.exists_fin' R M + have inst := Module.finitePresentation_of_projective A (A ⊗[R] (Fin n → R)) + apply Module.finitePresentation_of_surjective (f.baseChange A) + (LinearMap.lTensor_surjective A hf) + have : Function.Exact ((LinearMap.ker f).subtype.baseChange A) (f.baseChange A) := + lTensor_exact A f.exact_subtype_ker_map hf + rw [LinearMap.exact_iff] at this + rw [this, ← Submodule.map_top] + apply Submodule.FG.map + have : Module.Finite R (LinearMap.ker f) := + ⟨(Submodule.fg_top _).mpr (Module.FinitePresentation.fg_ker f hf)⟩ + exact Module.Finite.out (R := A) (M := A ⊗[R] LinearMap.ker f) + +open TensorProduct in +lemma FinitePresentation.of_isBaseChange + {A} [CommRing A] [Algebra R A] [Module A N] [IsScalarTower R A N] + (f : M →ₗ[R] N) (h : IsBaseChange A f) [Module.FinitePresentation R M] : + Module.FinitePresentation A N := + Module.finitePresentation_of_surjective + h.equiv.toLinearMap h.equiv.surjective (by simpa using Submodule.fg_bot) + +open TensorProduct in +instance (S : Submonoid R) [Module.FinitePresentation R M] : + Module.FinitePresentation (Localization S) (LocalizedModule S M) := + FinitePresentation.of_isBaseChange (LocalizedModule.mkLinearMap S M) + ((isLocalizedModule_iff_isBaseChange S _ _).mp inferInstance) lemma Module.FinitePresentation.exists_lift_of_isLocalizedModule [h : Module.FinitePresentation R M] (g : M →ₗ[R] N') : diff --git a/Mathlib/Algebra/Module/FreeLocus.lean b/Mathlib/Algebra/Module/FreeLocus.lean new file mode 100644 index 0000000000000..1487895fd48a4 --- /dev/null +++ b/Mathlib/Algebra/Module/FreeLocus.lean @@ -0,0 +1,227 @@ +/- +Copyright (c) 2024 Andrew Yang. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Andrew Yang +-/ +import Mathlib.AlgebraicGeometry.PrimeSpectrum.Basic +import Mathlib.RingTheory.Flat.Stability +import Mathlib.RingTheory.LocalProperties.Projective +import Mathlib.RingTheory.LocalRing.Module +import Mathlib.RingTheory.Localization.Free +import Mathlib.RingTheory.Localization.LocalizationLocalization +import Mathlib.Topology.LocallyConstant.Basic + +/-! + +# The free locus of a module + +## Main definitions and results + +Let `M` be a finitely presented `R`-module. +- `Module.freeLocus`: The set of points `x` in `Spec R` such that `Mₓ` is free over `Rₓ`. +- `Module.freeLocus_eq_univ_iff`: + The free locus is the whole `Spec R` if and only if `M` is projective. +- `Module.basicOpen_subset_freeLocus_iff`: `D(f)` is contained in the free locus if and only if + `M_f` is projective over `R_f`. +- `Module.rankAtStalk`: The function `Spec R → ℕ` sending `x` to `rank_{Rₓ} Mₓ`. +- `Module.isLocallyConstant_rankAtStalk`: + If `M` is flat over `R`, then `rankAtStalk` is locally constant. + +-/ + +universe uR uM + +variable (R : Type uR) (M : Type uM) [CommRing R] [AddCommGroup M] [Module R M] + +namespace Module + +open PrimeSpectrum TensorProduct + +/-- The free locus of a module, i.e. the set of primes `p` such that `Mₚ` is free over `Rₚ`. -/ +def freeLocus : Set (PrimeSpectrum R) := + { p | Module.Free (Localization.AtPrime p.asIdeal) (LocalizedModule p.asIdeal.primeCompl M) } + +variable {R M} + +lemma mem_freeLocus {p} : p ∈ freeLocus R M ↔ + Module.Free (Localization.AtPrime p.asIdeal) (LocalizedModule p.asIdeal.primeCompl M) := + Iff.rfl + +attribute [local instance] RingHomInvPair.of_ringEquiv in +lemma mem_freeLocus_of_isLocalization (p : PrimeSpectrum R) + (Rₚ Mₚ) [CommRing Rₚ] [Algebra R Rₚ] [IsLocalization.AtPrime Rₚ p.asIdeal] + [AddCommGroup Mₚ] [Module R Mₚ] (f : M →ₗ[R] Mₚ) [IsLocalizedModule p.asIdeal.primeCompl f] + [Module Rₚ Mₚ] [IsScalarTower R Rₚ Mₚ] : + p ∈ freeLocus R M ↔ Module.Free Rₚ Mₚ := by + apply Module.Free.iff_of_ringEquiv (IsLocalization.algEquiv p.asIdeal.primeCompl + (Localization.AtPrime p.asIdeal) Rₚ).toRingEquiv + refine { __ := IsLocalizedModule.iso p.asIdeal.primeCompl f, map_smul' := ?_ } + intro r x + obtain ⟨r, s, rfl⟩ := IsLocalization.mk'_surjective p.asIdeal.primeCompl r + apply ((Module.End_isUnit_iff _).mp (IsLocalizedModule.map_units f s)).1 + simp only [AddHom.toFun_eq_coe, LinearMap.coe_toAddHom, LinearEquiv.coe_coe, + algebraMap_end_apply, AlgEquiv.toRingEquiv_eq_coe, + AlgEquiv.toRingEquiv_toRingHom, RingHom.coe_coe, IsLocalization.algEquiv_apply, + IsLocalization.map_id_mk'] + simp only [← map_smul, ← smul_assoc, IsLocalization.smul_mk'_self, algebraMap_smul, + IsLocalization.map_id_mk'] + +attribute [local instance] RingHomInvPair.of_ringEquiv in +lemma mem_freeLocus_iff_tensor (p : PrimeSpectrum R) + (Rₚ) [CommRing Rₚ] [Algebra R Rₚ] [IsLocalization.AtPrime Rₚ p.asIdeal] : + p ∈ freeLocus R M ↔ Module.Free Rₚ (Rₚ ⊗[R] M) := by + have := (isLocalizedModule_iff_isBaseChange p.asIdeal.primeCompl _ _).mpr + (TensorProduct.isBaseChange R M Rₚ) + exact mem_freeLocus_of_isLocalization p Rₚ (f := TensorProduct.mk R Rₚ M 1) + +lemma freeLocus_congr {M'} [AddCommGroup M'] [Module R M'] (e : M ≃ₗ[R] M') : + freeLocus R M = freeLocus R M' := by + ext p + exact mem_freeLocus_of_isLocalization _ _ _ + (LocalizedModule.mkLinearMap p.asIdeal.primeCompl M' ∘ₗ e.toLinearMap) + +open TensorProduct in +lemma comap_freeLocus_le {A} [CommRing A] [Algebra R A] : + comap (algebraMap R A) ⁻¹' freeLocus R M ≤ freeLocus A (A ⊗[R] M) := by + intro p hp + let Rₚ := Localization.AtPrime (comap (algebraMap R A) p).asIdeal + let Aₚ := Localization.AtPrime p.asIdeal + rw [Set.mem_preimage, mem_freeLocus_iff_tensor _ Rₚ] at hp + rw [mem_freeLocus_iff_tensor _ Aₚ] + letI : Algebra Rₚ Aₚ := (Localization.localRingHom + (comap (algebraMap R A) p).asIdeal p.asIdeal (algebraMap R A) rfl).toAlgebra + have : IsScalarTower R Rₚ Aₚ := IsScalarTower.of_algebraMap_eq' + (by simp [RingHom.algebraMap_toAlgebra, Localization.localRingHom, + ← IsScalarTower.algebraMap_eq]) + let e := AlgebraTensorModule.cancelBaseChange R Rₚ Aₚ Aₚ M ≪≫ₗ + (AlgebraTensorModule.cancelBaseChange R A Aₚ Aₚ M).symm + exact .of_equiv e + +lemma freeLocus_localization (S : Submonoid R) : + freeLocus (Localization S) (LocalizedModule S M) = + comap (algebraMap R _) ⁻¹' freeLocus R M := by + ext p + simp only [Set.mem_preimage] + let p' := p.asIdeal.comap (algebraMap R _) + have hp' : S ≤ p'.primeCompl := fun x hx H ↦ + p.isPrime.ne_top (Ideal.eq_top_of_isUnit_mem _ H (IsLocalization.map_units _ ⟨x, hx⟩)) + let Rₚ := Localization.AtPrime p' + let Mₚ := LocalizedModule p'.primeCompl M + letI : Algebra (Localization S) Rₚ := + IsLocalization.localizationAlgebraOfSubmonoidLe _ _ S p'.primeCompl hp' + have : IsScalarTower R (Localization S) Rₚ := + IsLocalization.localization_isScalarTower_of_submonoid_le .. + have : IsLocalization.AtPrime Rₚ p.asIdeal := by + have := IsLocalization.isLocalization_of_submonoid_le (Localization S) Rₚ _ _ hp' + apply IsLocalization.isLocalization_of_is_exists_mul_mem _ + (Submonoid.map (algebraMap R (Localization S)) p'.primeCompl) + · rintro _ ⟨x, hx, rfl⟩; exact hx + · rintro ⟨x, hx⟩ + obtain ⟨x, s, rfl⟩ := IsLocalization.mk'_surjective S x + refine ⟨algebraMap _ _ s.1, x, fun H ↦ hx ?_, by simp⟩ + rw [IsLocalization.mk'_eq_mul_mk'_one] + exact Ideal.mul_mem_right _ _ H + letI : Module (Localization S) Mₚ := Module.compHom Mₚ (algebraMap _ Rₚ) + have : IsScalarTower R (Localization S) Mₚ := + ⟨fun r r' m ↦ show algebraMap _ Rₚ (r • r') • m = _ by + simp [Algebra.smul_def, ← IsScalarTower.algebraMap_apply, mul_smul]; rfl⟩ + have : IsScalarTower (Localization S) Rₚ Mₚ := + ⟨fun r r' m ↦ show _ = algebraMap _ Rₚ r • r' • m by rw [← mul_smul, ← Algebra.smul_def]⟩ + let l := (IsLocalizedModule.liftOfLE _ _ hp' (LocalizedModule.mkLinearMap S M) + (LocalizedModule.mkLinearMap p'.primeCompl M)).extendScalarsOfIsLocalization S + (Localization S) + have : IsLocalizedModule p.asIdeal.primeCompl l := by + have : IsLocalizedModule p'.primeCompl (l.restrictScalars R) := + inferInstanceAs (IsLocalizedModule p'.primeCompl + (IsLocalizedModule.liftOfLE _ _ hp' (LocalizedModule.mkLinearMap S M) + (LocalizedModule.mkLinearMap p'.primeCompl M))) + have : IsLocalizedModule (Algebra.algebraMapSubmonoid (Localization S) p'.primeCompl) l := + IsLocalizedModule.of_restrictScalars p'.primeCompl .. + apply IsLocalizedModule.of_exists_mul_mem + (Algebra.algebraMapSubmonoid (Localization S) p'.primeCompl) + · rintro _ ⟨x, hx, rfl⟩; exact hx + · rintro ⟨x, hx⟩ + obtain ⟨x, s, rfl⟩ := IsLocalization.mk'_surjective S x + refine ⟨algebraMap _ _ s.1, x, fun H ↦ hx ?_, by simp⟩ + rw [IsLocalization.mk'_eq_mul_mk'_one] + exact Ideal.mul_mem_right _ _ H + rw [mem_freeLocus_of_isLocalization (R := Localization S) p Rₚ Mₚ l] + rfl + +lemma freeLocus_eq_univ_iff [Module.FinitePresentation R M] : + freeLocus R M = Set.univ ↔ Module.Projective R M := by + simp_rw [Set.eq_univ_iff_forall, mem_freeLocus] + exact ⟨fun H ↦ Module.projective_of_localization_maximal fun I hI ↦ + have := H ⟨I, hI.isPrime⟩; .of_free, fun H x ↦ Module.free_of_flat_of_isLocalRing⟩ + +lemma freeLocus_eq_univ [Module.FinitePresentation R M] [Module.Flat R M] : + freeLocus R M = Set.univ := by + simp_rw [Set.eq_univ_iff_forall, mem_freeLocus] + exact fun x ↦ Module.free_of_flat_of_isLocalRing + +lemma basicOpen_subset_freeLocus_iff [Module.FinitePresentation R M] {f : R} : + (basicOpen f : Set (PrimeSpectrum R)) ⊆ freeLocus R M ↔ + Module.Projective (Localization.Away f) (LocalizedModule (.powers f) M) := by + rw [← freeLocus_eq_univ_iff, freeLocus_localization, + Set.preimage_eq_univ_iff, localization_away_comap_range _ f] + +lemma isOpen_freeLocus [Module.FinitePresentation R M] : + IsOpen (freeLocus R M) := by + refine isOpen_iff_forall_mem_open.mpr fun x hx ↦ ?_ + have : Module.Free _ _ := hx + obtain ⟨r, hr, hr', _⟩ := Module.FinitePresentation.exists_free_localizedModule_powers + x.asIdeal.primeCompl (LocalizedModule.mkLinearMap x.asIdeal.primeCompl M) + (Localization.AtPrime x.asIdeal) + exact ⟨basicOpen r, basicOpen_subset_freeLocus_iff.mpr inferInstance, (basicOpen r).2, hr⟩ + +variable (M) in +/-- The rank of `M` at the stalk of `p` is the rank of `Mₚ` as a `Rₚ`-module. -/ +noncomputable +def rankAtStalk (p : PrimeSpectrum R) : ℕ := + Module.finrank (Localization.AtPrime p.asIdeal) (LocalizedModule p.asIdeal.primeCompl M) + +lemma isLocallyConstant_rankAtStalk_freeLocus [Module.FinitePresentation R M] : + IsLocallyConstant (fun x : freeLocus R M ↦ rankAtStalk M x.1) := by + refine (IsLocallyConstant.iff_exists_open _).mpr fun ⟨x, hx⟩ ↦ ?_ + have : Module.Free _ _ := hx + obtain ⟨f, hf, hf', hf''⟩ := Module.FinitePresentation.exists_free_localizedModule_powers + x.asIdeal.primeCompl (LocalizedModule.mkLinearMap x.asIdeal.primeCompl M) + (Localization.AtPrime x.asIdeal) + refine ⟨Subtype.val ⁻¹' basicOpen f, (basicOpen f).2.preimage continuous_subtype_val, hf, ?_⟩ + rintro ⟨p, hp''⟩ hp + let p' := Algebra.algebraMapSubmonoid (Localization (.powers f)) p.asIdeal.primeCompl + have hp' : Submonoid.powers f ≤ p.asIdeal.primeCompl := by + simpa [Submonoid.powers_le, Ideal.primeCompl] + let Rₚ := Localization.AtPrime p.asIdeal + let Mₚ := LocalizedModule p.asIdeal.primeCompl M + letI : Algebra (Localization.Away f) Rₚ := + IsLocalization.localizationAlgebraOfSubmonoidLe _ _ (.powers f) p.asIdeal.primeCompl hp' + have : IsScalarTower R (Localization.Away f) Rₚ := + IsLocalization.localization_isScalarTower_of_submonoid_le .. + letI : Module (Localization.Away f) Mₚ := Module.compHom Mₚ (algebraMap _ Rₚ) + have : IsScalarTower R (Localization.Away f) Mₚ := + ⟨fun r r' m ↦ show algebraMap _ Rₚ (r • r') • m = _ by + simp [Algebra.smul_def, ← IsScalarTower.algebraMap_apply, mul_smul]; rfl⟩ + have : IsScalarTower (Localization.Away f) Rₚ Mₚ := + ⟨fun r r' m ↦ show _ = algebraMap _ Rₚ r • r' • m by rw [← mul_smul, ← Algebra.smul_def]⟩ + let l := (IsLocalizedModule.liftOfLE _ _ hp' (LocalizedModule.mkLinearMap (.powers f) M) + (LocalizedModule.mkLinearMap p.asIdeal.primeCompl M)).extendScalarsOfIsLocalization (.powers f) + (Localization.Away f) + have : IsLocalization p' Rₚ := + IsLocalization.isLocalization_of_submonoid_le (Localization.Away f) Rₚ _ _ hp' + have : IsLocalizedModule p.asIdeal.primeCompl (l.restrictScalars R) := + inferInstanceAs (IsLocalizedModule p.asIdeal.primeCompl + ((IsLocalizedModule.liftOfLE _ _ hp' (LocalizedModule.mkLinearMap (.powers f) M) + (LocalizedModule.mkLinearMap p.asIdeal.primeCompl M)))) + have : IsLocalizedModule (Algebra.algebraMapSubmonoid _ p.asIdeal.primeCompl) l := + IsLocalizedModule.of_restrictScalars p.asIdeal.primeCompl .. + have := Module.finrank_of_isLocalizedModule_of_free Rₚ p' l + simp [rankAtStalk, this, hf''] + +lemma isLocallyConstant_rankAtStalk [Module.FinitePresentation R M] [Module.Flat R M] : + IsLocallyConstant (rankAtStalk (R := R) M) := by + let e : freeLocus R M ≃ₜ PrimeSpectrum R := + (Homeomorph.setCongr freeLocus_eq_univ).trans (Homeomorph.Set.univ (PrimeSpectrum R)) + convert isLocallyConstant_rankAtStalk_freeLocus.comp_continuous e.symm.continuous + +end Module diff --git a/Mathlib/Algebra/Module/GradedModule.lean b/Mathlib/Algebra/Module/GradedModule.lean index 8adb7c6ada0a5..8797f2bbdd7b5 100644 --- a/Mathlib/Algebra/Module/GradedModule.lean +++ b/Mathlib/Algebra/Module/GradedModule.lean @@ -93,11 +93,9 @@ theorem smulAddMonoidHom_apply_of_of [DecidableEq ιA] [DecidableEq ιB] [GMonoi smulAddMonoidHom A M (DirectSum.of A i x) (of M j y) = of M (i +ᵥ j) (GSMul.smul x y) := by simp [smulAddMonoidHom] --- @[simp] -- Porting note: simpNF lint theorem of_smul_of [DecidableEq ιA] [DecidableEq ιB] [GMonoid A] [Gmodule A M] {i j} (x : A i) (y : M j) : - DirectSum.of A i x • of M j y = of M (i +ᵥ j) (GSMul.smul x y) := - smulAddMonoidHom_apply_of_of _ _ _ _ + DirectSum.of A i x • of M j y = of M (i +ᵥ j) (GSMul.smul x y) := by simp open AddMonoidHom diff --git a/Mathlib/Algebra/Module/LinearMap/Defs.lean b/Mathlib/Algebra/Module/LinearMap/Defs.lean index c6436036fb7c1..d4c25f58c52fb 100644 --- a/Mathlib/Algebra/Module/LinearMap/Defs.lean +++ b/Mathlib/Algebra/Module/LinearMap/Defs.lean @@ -596,14 +596,14 @@ variable [Semiring R] [Module R M] [Semiring S] [Module S M₂] [Module R M₃] variable {σ : R →+* S} /-- A `DistribMulActionHom` between two modules is a linear map. -/ -@[deprecated (since := "2024-11-08")] +@[deprecated "No deprecation message was provided." (since := "2024-11-08")] def toSemilinearMap (fₗ : M →ₑ+[σ.toMonoidHom] M₂) : M →ₛₗ[σ] M₂ := { fₗ with } instance : SemilinearMapClass (M →ₑ+[σ.toMonoidHom] M₂) σ M M₂ where /-- A `DistribMulActionHom` between two modules is a linear map. -/ -@[deprecated (since := "2024-11-08")] +@[deprecated "No deprecation message was provided." (since := "2024-11-08")] def toLinearMap (fₗ : M →+[R] M₃) : M →ₗ[R] M₃ := { fₗ with } diff --git a/Mathlib/Algebra/Module/LocalizedModule/Basic.lean b/Mathlib/Algebra/Module/LocalizedModule/Basic.lean index cd73b52dd3c65..efe62ee72caee 100644 --- a/Mathlib/Algebra/Module/LocalizedModule/Basic.lean +++ b/Mathlib/Algebra/Module/LocalizedModule/Basic.lean @@ -560,7 +560,7 @@ lemma IsLocalizedModule.eq_iff_exists [IsLocalizedModule S f] {x₁ x₂} : simp_rw [f.map_smul_of_tower, Submonoid.smul_def, ← Module.algebraMap_end_apply R R] at h exact ((Module.End_isUnit_iff _).mp <| map_units f c).1 h -theorem IsLocalizedModule.of_linearEquiv (e : M' ≃ₗ[R] M'') [hf : IsLocalizedModule S f] : +instance IsLocalizedModule.of_linearEquiv (e : M' ≃ₗ[R] M'') [hf : IsLocalizedModule S f] : IsLocalizedModule S (e ∘ₗ f : M →ₗ[R] M'') where map_units s := by rw [show algebraMap R (Module.End R M'') s = e ∘ₗ (algebraMap R (Module.End R M') s) ∘ₗ e.symm @@ -576,6 +576,18 @@ theorem IsLocalizedModule.of_linearEquiv (e : M' ≃ₗ[R] M'') [hf : IsLocalize EmbeddingLike.apply_eq_iff_eq] at h exact hf.exists_of_eq h +instance IsLocalizedModule.of_linearEquiv_right (e : M'' ≃ₗ[R] M) [hf : IsLocalizedModule S f] : + IsLocalizedModule S (f ∘ₗ e : M'' →ₗ[R] M') where + map_units s := hf.map_units s + surj' x := by + obtain ⟨⟨p, s⟩, h⟩ := hf.surj' x + exact ⟨⟨e.symm p, s⟩, by simpa using h⟩ + exists_of_eq h := by + simp_rw [LinearMap.coe_comp, LinearEquiv.coe_coe, Function.comp_apply] at h + obtain ⟨c, hc⟩ := hf.exists_of_eq h + exact ⟨c, by simpa only [Submonoid.smul_def, map_smul, e.symm_apply_apply] + using congr(e.symm $hc)⟩ + variable (M) in lemma isLocalizedModule_id (R') [CommSemiring R'] [Algebra R R'] [IsLocalization S R'] [Module R' M] [IsScalarTower R R' M] : IsLocalizedModule S (.id : M →ₗ[R] M) where @@ -703,6 +715,39 @@ instance localizedModuleIsLocalizedModule : LocalizedModule.mk_cancel t] exists_of_eq eq1 := by simpa only [eq_comm, one_smul] using LocalizedModule.mk_eq.mp eq1 +lemma IsLocalizedModule.of_restrictScalars (S : Submonoid R) + {N : Type*} [AddCommGroup N] [Module R N] [Module A M] [Module A N] + [IsScalarTower R A M] [IsScalarTower R A N] + (f : M →ₗ[A] N) [IsLocalizedModule S (f.restrictScalars R)] : + IsLocalizedModule (Algebra.algebraMapSubmonoid A S) f where + map_units x := by + obtain ⟨_, x, hx, rfl⟩ := x + have := IsLocalizedModule.map_units (f.restrictScalars R) ⟨x, hx⟩ + simp only [← IsScalarTower.algebraMap_apply, Module.End_isUnit_iff] at this ⊢ + exact this + surj' y := by + obtain ⟨⟨x, t⟩, e⟩ := IsLocalizedModule.surj S (f.restrictScalars R) y + exact ⟨⟨x, ⟨_, t, t.2, rfl⟩⟩, by simpa [Submonoid.smul_def] using e⟩ + exists_of_eq {x₁ x₂} e := by + obtain ⟨c, hc⟩ := IsLocalizedModule.exists_of_eq (S := S) (f := f.restrictScalars R) e + refine ⟨⟨_, c, c.2, rfl⟩, by simpa [Submonoid.smul_def]⟩ + +lemma IsLocalizedModule.of_exists_mul_mem {N : Type*} [AddCommGroup N] [Module R N] + (S T : Submonoid R) (h : S ≤ T) (h' : ∀ x : T, ∃ m : R, m * x ∈ S) + (f : M →ₗ[R] N) [IsLocalizedModule S f] : + IsLocalizedModule T f where + map_units x := by + obtain ⟨m, mx⟩ := h' x + have := IsLocalizedModule.map_units f ⟨_, mx⟩ + rw [map_mul, (Algebra.commute_algebraMap_left _ _).isUnit_mul_iff] at this + exact this.2 + surj' y := by + obtain ⟨⟨x, t⟩, e⟩ := IsLocalizedModule.surj S f y + exact ⟨⟨x, ⟨t, h t.2⟩⟩, e⟩ + exists_of_eq {x₁ x₂} e := by + obtain ⟨c, hc⟩ := IsLocalizedModule.exists_of_eq (S := S) (f := f) e + exact ⟨⟨c, h c.2⟩, hc⟩ + namespace IsLocalizedModule variable [IsLocalizedModule S f] diff --git a/Mathlib/Algebra/Module/LocalizedModule/Submodule.lean b/Mathlib/Algebra/Module/LocalizedModule/Submodule.lean index 650844736f7ca..0ec7f25bf02d7 100644 --- a/Mathlib/Algebra/Module/LocalizedModule/Submodule.lean +++ b/Mathlib/Algebra/Module/LocalizedModule/Submodule.lean @@ -189,31 +189,32 @@ instance (M' : Submodule R M) : IsLocalizedModule p (M'.toLocalizedQuotient p) : end Quotient -section LinearMap +namespace LinearMap -variable {P : Type*} [AddCommGroup P] [Module R P] -variable {Q : Type*} [AddCommGroup Q] [Module R Q] [Module S Q] [IsScalarTower R S Q] +variable {P : Type*} [AddCommMonoid P] [Module R P] +variable {Q : Type*} [AddCommMonoid Q] [Module R Q] [Module S Q] [IsScalarTower R S Q] variable (f' : P →ₗ[R] Q) [IsLocalizedModule p f'] -lemma LinearMap.localized'_ker_eq_ker_localizedMap (g : M →ₗ[R] P) : - Submodule.localized' S p f (LinearMap.ker g) = - LinearMap.ker ((IsLocalizedModule.map p f f' g).extendScalarsOfIsLocalization p S) := by +open Submodule IsLocalizedModule + +lemma ker_localizedMap_eq_localized₀_ker (g : M →ₗ[R] P) : + ker (map p f f' g) = (ker g).localized₀ p f := by ext x - simp only [Submodule.mem_localized', mem_ker, extendScalarsOfIsLocalization_apply'] - constructor - · rintro ⟨m, hm, a, ha, rfl⟩ - rw [IsLocalizedModule.map_mk', hm] - simp - · intro h - obtain ⟨⟨a, b⟩, rfl⟩ := IsLocalizedModule.mk'_surjective p f x - simp only [Function.uncurry_apply_pair, IsLocalizedModule.map_mk', - IsLocalizedModule.mk'_eq_zero, IsLocalizedModule.eq_zero_iff p f'] at h + simp only [Submodule.mem_localized₀, mem_ker] + refine ⟨fun h ↦ ?_, ?_⟩ + · obtain ⟨⟨a, b⟩, rfl⟩ := IsLocalizedModule.mk'_surjective p f x + simp only [Function.uncurry_apply_pair, map_mk', mk'_eq_zero, eq_zero_iff p f'] at h obtain ⟨c, hc⟩ := h refine ⟨c • a, by simpa, c * b, by simp⟩ + · rintro ⟨m, hm, a, ha, rfl⟩ + simp [IsLocalizedModule.map_mk', hm] -lemma LinearMap.ker_localizedMap_eq_localized'_ker (g : M →ₗ[R] P) : - LinearMap.ker (IsLocalizedModule.map p f f' g) = - ((LinearMap.ker g).localized' S p f).restrictScalars _ := by +lemma localized'_ker_eq_ker_localizedMap (g : M →ₗ[R] P) : + (ker g).localized' S p f = ker ((map p f f' g).extendScalarsOfIsLocalization p S) := + SetLike.ext (by apply SetLike.ext_iff.mp (f.ker_localizedMap_eq_localized₀_ker p f' g).symm) + +lemma ker_localizedMap_eq_localized'_ker (g : M →ₗ[R] P) : + ker (map p f f' g) = ((ker g).localized' S p f).restrictScalars _ := by ext simp [localized'_ker_eq_ker_localizedMap S p f f'] @@ -223,18 +224,27 @@ The canonical map from the kernel of `g` to the kernel of `g` localized at a sub This is a localization map by `LinearMap.toKerLocalized_isLocalizedModule`. -/ @[simps!] -noncomputable def LinearMap.toKerIsLocalized (g : M →ₗ[R] P) : - ker g →ₗ[R] ker (IsLocalizedModule.map p f f' g) := - f.restrict (fun x hx ↦ by simp [LinearMap.mem_ker, LinearMap.mem_ker.mp hx]) +noncomputable def toKerIsLocalized (g : M →ₗ[R] P) : + ker g →ₗ[R] ker (map p f f' g) := + f.restrict (fun x hx ↦ by simp [mem_ker, mem_ker.mp hx]) include S in /-- The canonical map to the kernel of the localization of `g` is localizing. In other words, localization commutes with kernels. -/ -lemma LinearMap.toKerLocalized_isLocalizedModule (g : M →ₗ[R] P) : +lemma toKerLocalized_isLocalizedModule (g : M →ₗ[R] P) : IsLocalizedModule p (toKerIsLocalized p f f' g) := let e : Submodule.localized' S p f (ker g) ≃ₗ[S] - ker ((IsLocalizedModule.map p f f' g).extendScalarsOfIsLocalization p S) := + ker ((map p f f' g).extendScalarsOfIsLocalization p S) := LinearEquiv.ofEq _ _ (localized'_ker_eq_ker_localizedMap S p f f' g) IsLocalizedModule.of_linearEquiv p (Submodule.toLocalized' S p f (ker g)) (e.restrictScalars R) +lemma range_localizedMap_eq_localized₀_range (g : M →ₗ[R] P) : + range (map p f f' g) = (range g).localized₀ p f' := by + ext; simp [mem_localized₀, mem_range, (mk'_surjective p f).exists] + +/-- Localization commutes with ranges. -/ +lemma localized'_range_eq_range_localizedMap (g : M →ₗ[R] P) : + (range g).localized' S p f' = range ((map p f f' g).extendScalarsOfIsLocalization p S) := + SetLike.ext (by apply SetLike.ext_iff.mp (f.range_localizedMap_eq_localized₀_range p f' g).symm) + end LinearMap diff --git a/Mathlib/Algebra/Module/Submodule/Ker.lean b/Mathlib/Algebra/Module/Submodule/Ker.lean index b291dd847675d..dfa7ba1ee50ad 100644 --- a/Mathlib/Algebra/Module/Submodule/Ker.lean +++ b/Mathlib/Algebra/Module/Submodule/Ker.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl, Mario Carneiro, Kevin Buzzard, Yury Kudryashov, Frédéric Dupuis, Heather Macbeth -/ +import Mathlib.Algebra.Group.Subgroup.Ker import Mathlib.Algebra.Module.Submodule.Map /-! diff --git a/Mathlib/Algebra/Module/Submodule/Lattice.lean b/Mathlib/Algebra/Module/Submodule/Lattice.lean index 8a537d9a01ba5..76744e1fa2be2 100644 --- a/Mathlib/Algebra/Module/Submodule/Lattice.lean +++ b/Mathlib/Algebra/Module/Submodule/Lattice.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, Mario Carneiro, Kevin Buzzard, Yury Kudryashov -/ -import Mathlib.Algebra.Group.Subgroup.Basic +import Mathlib.Algebra.Group.Subgroup.Lattice import Mathlib.Algebra.Group.Submonoid.Membership import Mathlib.Algebra.Module.Submodule.Defs import Mathlib.Algebra.Module.Equiv.Defs diff --git a/Mathlib/Algebra/Module/Submodule/Map.lean b/Mathlib/Algebra/Module/Submodule/Map.lean index bf9a103f9a34a..ac43875d2bd8a 100644 --- a/Mathlib/Algebra/Module/Submodule/Map.lean +++ b/Mathlib/Algebra/Module/Submodule/Map.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl, Mario Carneiro, Kevin Buzzard, Yury Kudryashov, Frédéric Dupuis, Heather Macbeth -/ - +import Mathlib.Algebra.Group.Subgroup.Map import Mathlib.Algebra.Module.Submodule.Basic import Mathlib.Algebra.Module.Submodule.Lattice import Mathlib.Algebra.Module.Submodule.LinearMap diff --git a/Mathlib/Algebra/Module/Submodule/Pointwise.lean b/Mathlib/Algebra/Module/Submodule/Pointwise.lean index ec25efdc44f71..99f269138c452 100644 --- a/Mathlib/Algebra/Module/Submodule/Pointwise.lean +++ b/Mathlib/Algebra/Module/Submodule/Pointwise.lean @@ -161,9 +161,7 @@ instance pointwiseAddCommMonoid : AddCommMonoid (Submodule R M) where theorem add_eq_sup (p q : Submodule R M) : p + q = p ⊔ q := rfl --- dsimp loops when applying this lemma to its LHS, --- probably https://github.com/leanprover/lean4/pull/2867 -@[simp, nolint simpNF] +@[simp] theorem zero_eq_bot : (0 : Submodule R M) = ⊥ := rfl diff --git a/Mathlib/Algebra/Module/Torsion.lean b/Mathlib/Algebra/Module/Torsion.lean index a993b226e188a..08b33bcef771a 100644 --- a/Mathlib/Algebra/Module/Torsion.lean +++ b/Mathlib/Algebra/Module/Torsion.lean @@ -67,7 +67,7 @@ variable (R M : Type*) [Semiring R] [AddCommMonoid M] [Module R M] /-- The torsion ideal of `x`, containing all `a` such that `a • x = 0`. -/ @[simps!] def torsionOf (x : M) : Ideal R := - -- Porting note (https://github.com/leanprover-community/mathlib4/issues/11036): broken dot notation on LinearMap.ker https://github.com/leanprover/lean4/issues/1910 + -- Porting note (https://github.com/leanprover-community/mathlib4/issues/11036): broken dot notation on LinearMap.ker https://github.com/leanprover/lean4/issues/1629 LinearMap.ker (LinearMap.toSpanSingleton R M x) @[simp] @@ -96,13 +96,13 @@ theorem torsionOf_eq_bot_iff_of_noZeroSMulDivisors [Nontrivial R] [NoZeroSMulDiv · rw [mem_torsionOf_iff, smul_eq_zero] at hr tauto -/-- See also `CompleteLattice.Independent.linearIndependent` which provides the same conclusion +/-- See also `iSupIndep.linearIndependent` which provides the same conclusion but requires the stronger hypothesis `NoZeroSMulDivisors R M`. -/ -theorem CompleteLattice.Independent.linear_independent' {ι R M : Type*} {v : ι → M} [Ring R] - [AddCommGroup M] [Module R M] (hv : CompleteLattice.Independent fun i => R ∙ v i) +theorem iSupIndep.linearIndependent' {ι R M : Type*} {v : ι → M} [Ring R] + [AddCommGroup M] [Module R M] (hv : iSupIndep fun i => R ∙ v i) (h_ne_zero : ∀ i, Ideal.torsionOf R M (v i) = ⊥) : LinearIndependent R v := by refine linearIndependent_iff_not_smul_mem_span.mpr fun i r hi => ?_ - replace hv := CompleteLattice.independent_def.mp hv i + replace hv := iSupIndep_def.mp hv i simp only [iSup_subtype', ← Submodule.span_range_eq_iSup (ι := Subtype _), disjoint_iff] at hv have : r • v i ∈ (⊥ : Submodule R M) := by rw [← hv, Submodule.mem_inf] @@ -113,6 +113,9 @@ theorem CompleteLattice.Independent.linear_independent' {ι R M : Type*} {v : ι rw [← Submodule.mem_bot R, ← h_ne_zero i] simpa using this +@[deprecated (since := "2024-11-24")] +alias CompleteLattice.Independent.linear_independent' := iSupIndep.linearIndependent' + end TorsionOf section @@ -148,7 +151,7 @@ namespace Submodule `a • x = 0`. -/ @[simps!] def torsionBy (a : R) : Submodule R M := - -- Porting note (https://github.com/leanprover-community/mathlib4/issues/11036): broken dot notation on LinearMap.ker https://github.com/leanprover/lean4/issues/1910 + -- Porting note (https://github.com/leanprover-community/mathlib4/issues/11036): broken dot notation on LinearMap.ker https://github.com/leanprover/lean4/issues/1629 LinearMap.ker (DistribMulAction.toLinearMap R M a) /-- The submodule containing all elements `x` of `M` such that `a • x = 0` for all `a` in `s`. -/ @@ -443,8 +446,8 @@ theorem torsionBySet_isInternal {p : ι → Ideal R} (hp : (S : Set ι).Pairwise fun i j => p i ⊔ p j = ⊤) (hM : Module.IsTorsionBySet R M (⨅ i ∈ S, p i : Ideal R)) : DirectSum.IsInternal fun i : S => torsionBySet R M <| p i := - DirectSum.isInternal_submodule_of_independent_of_iSup_eq_top - (CompleteLattice.independent_iff_supIndep.mpr <| supIndep_torsionBySet_ideal hp) + DirectSum.isInternal_submodule_of_iSupIndep_of_iSup_eq_top + (iSupIndep_iff_supIndep.mpr <| supIndep_torsionBySet_ideal hp) (by apply (iSup_subtype'' ↑S fun i => torsionBySet R M <| p i).trans -- Porting note: times out if we change apply below to <| diff --git a/Mathlib/Algebra/MonoidAlgebra/Basic.lean b/Mathlib/Algebra/MonoidAlgebra/Basic.lean index 07f16b5034f0f..1e0a8e01e33eb 100644 --- a/Mathlib/Algebra/MonoidAlgebra/Basic.lean +++ b/Mathlib/Algebra/MonoidAlgebra/Basic.lean @@ -463,7 +463,7 @@ theorem lift_def (F : Multiplicative G →* A) : @[simp] theorem lift_symm_apply (F : k[G] →ₐ[k] A) (x : Multiplicative G) : - (lift k G A).symm F x = F (single (Multiplicative.toAdd x) 1) := + (lift k G A).symm F x = F (single x.toAdd 1) := rfl theorem lift_of (F : Multiplicative G →* A) (x : Multiplicative G) : diff --git a/Mathlib/Algebra/MonoidAlgebra/Defs.lean b/Mathlib/Algebra/MonoidAlgebra/Defs.lean index 93e53c6c0603b..41e3c6d67e134 100644 --- a/Mathlib/Algebra/MonoidAlgebra/Defs.lean +++ b/Mathlib/Algebra/MonoidAlgebra/Defs.lean @@ -1300,7 +1300,7 @@ end @[simp] theorem of_apply [AddZeroClass G] (a : Multiplicative G) : - of k G a = single (Multiplicative.toAdd a) 1 := + of k G a = single a.toAdd 1 := rfl @[simp] @@ -1324,7 +1324,7 @@ Note the order of the elements of the product are reversed compared to the argum -/ @[simps] def singleHom [AddZeroClass G] : k × Multiplicative G →* k[G] where - toFun a := single (Multiplicative.toAdd a.2) a.1 + toFun a := single a.2.toAdd a.1 map_one' := rfl map_mul' _a _b := single_mul_single.symm diff --git a/Mathlib/Algebra/MonoidAlgebra/Division.lean b/Mathlib/Algebra/MonoidAlgebra/Division.lean index e0f57c1d1a2b2..7b63bd6d1bbd6 100644 --- a/Mathlib/Algebra/MonoidAlgebra/Division.lean +++ b/Mathlib/Algebra/MonoidAlgebra/Division.lean @@ -83,13 +83,13 @@ theorem divOf_add (x : k[G]) (a b : G) : x /ᵒᶠ (a + b) = x /ᵒᶠ a /ᵒᶠ @[simps] noncomputable def divOfHom : Multiplicative G →* AddMonoid.End k[G] where toFun g := - { toFun := fun x => divOf x (Multiplicative.toAdd g) + { toFun := fun x => divOf x g.toAdd map_zero' := zero_divOf _ - map_add' := fun x y => add_divOf x y (Multiplicative.toAdd g) } + map_add' := fun x y => add_divOf x y g.toAdd } map_one' := AddMonoidHom.ext divOf_zero map_mul' g₁ g₂ := AddMonoidHom.ext fun _x => - (congr_arg _ (add_comm (Multiplicative.toAdd g₁) (Multiplicative.toAdd g₂))).trans + (congr_arg _ (add_comm g₁.toAdd g₂.toAdd)).trans (divOf_add _ _ _) theorem of'_mul_divOf (a : G) (x : k[G]) : of' k G a * x /ᵒᶠ a = x := by diff --git a/Mathlib/Algebra/MonoidAlgebra/Grading.lean b/Mathlib/Algebra/MonoidAlgebra/Grading.lean index 39f3e606eae43..66092e7d7d662 100644 --- a/Mathlib/Algebra/MonoidAlgebra/Grading.lean +++ b/Mathlib/Algebra/MonoidAlgebra/Grading.lean @@ -110,8 +110,8 @@ variable [AddMonoid M] [DecidableEq ι] [AddMonoid ι] [CommSemiring R] (f : M def decomposeAux : R[M] →ₐ[R] ⨁ i : ι, gradeBy R f i := AddMonoidAlgebra.lift R M _ { toFun := fun m => - DirectSum.of (fun i : ι => gradeBy R f i) (f (Multiplicative.toAdd m)) - ⟨Finsupp.single (Multiplicative.toAdd m) 1, single_mem_gradeBy _ _ _⟩ + DirectSum.of (fun i : ι => gradeBy R f i) (f m.toAdd) + ⟨Finsupp.single m.toAdd 1, single_mem_gradeBy _ _ _⟩ map_one' := DirectSum.of_eq_of_gradedMonoid_eq (by congr 2 <;> simp) diff --git a/Mathlib/Algebra/MvPolynomial/Basic.lean b/Mathlib/Algebra/MvPolynomial/Basic.lean index dac73ae71fe7a..b649bbdca1c39 100644 --- a/Mathlib/Algebra/MvPolynomial/Basic.lean +++ b/Mathlib/Algebra/MvPolynomial/Basic.lean @@ -844,9 +844,8 @@ theorem constantCoeff_X (i : σ) : constantCoeff (X i : MvPolynomial σ R) = 0 : simp [constantCoeff_eq] variable {R} -/- porting note: increased priority because otherwise `simp` time outs when trying to simplify -the left-hand side. `simpNF` linter indicated this and it was verified. -/ -@[simp 1001] + +@[simp] theorem constantCoeff_smul {R : Type*} [SMulZeroClass R S₁] (a : R) (f : MvPolynomial σ S₁) : constantCoeff (a • f) = a • constantCoeff f := rfl @@ -920,6 +919,14 @@ theorem eval₂_C (a) : (C a).eval₂ f g = f a := by theorem eval₂_one : (1 : MvPolynomial σ R).eval₂ f g = 1 := (eval₂_C _ _ _).trans f.map_one +@[simp] theorem eval₂_natCast (n : Nat) : (n : MvPolynomial σ R).eval₂ f g = n := + (eval₂_C _ _ _).trans (map_natCast f n) + +-- See note [no_index around OfNat.ofNat] +@[simp] theorem eval₂_ofNat (n : Nat) [n.AtLeastTwo] : + (no_index (OfNat.ofNat n) : MvPolynomial σ R).eval₂ f g = OfNat.ofNat n := + eval₂_natCast f g n + @[simp] theorem eval₂_X (n) : (X n).eval₂ f g = g n := by simp [eval₂_monomial, f.map_one, X, prod_single_index, pow_one] @@ -1070,6 +1077,11 @@ theorem eval_C : ∀ a, eval f (C a) = a := theorem eval_X : ∀ n, eval f (X n) = f n := eval₂_X _ _ +-- See note [no_index around OfNat.ofNat] +@[simp] theorem eval_ofNat (n : Nat) [n.AtLeastTwo] : + (no_index (OfNat.ofNat n) : MvPolynomial σ R).eval f = OfNat.ofNat n := + map_ofNat _ n + @[simp] theorem smul_eval (x) (p : MvPolynomial σ R) (s) : eval x (s • p) = s * eval x p := by rw [smul_eq_C_mul, (eval x).map_mul, eval_C] @@ -1130,6 +1142,11 @@ theorem map_monomial (s : σ →₀ ℕ) (a : R) : map f (monomial s a) = monomi theorem map_C : ∀ a : R, map f (C a : MvPolynomial σ R) = C (f a) := map_monomial _ _ +-- See note [no_index around OfNat.ofNat] +@[simp] protected theorem map_ofNat (n : Nat) [n.AtLeastTwo] : + (no_index (OfNat.ofNat n) : MvPolynomial σ R).map f = OfNat.ofNat n := + _root_.map_ofNat _ _ + @[simp] theorem map_X : ∀ n : σ, map f (X n : MvPolynomial σ R) = X n := eval₂_X _ _ @@ -1345,6 +1362,11 @@ theorem aeval_X (s : σ) : aeval f (X s : MvPolynomial _ R) = f s := theorem aeval_C (r : R) : aeval f (C r) = algebraMap R S₁ r := eval₂_C _ _ _ +-- See note [no_index around OfNat.ofNat] +@[simp] theorem aeval_ofNat (n : Nat) [n.AtLeastTwo] : + aeval f (no_index (OfNat.ofNat n) : MvPolynomial σ R) = OfNat.ofNat n := + map_ofNat _ _ + theorem aeval_unique (φ : MvPolynomial σ R →ₐ[R] S₁) : φ = aeval (φ ∘ X) := by ext i simp @@ -1476,6 +1498,12 @@ theorem aevalTower_X (i : σ) : aevalTower g y (X i) = y i := theorem aevalTower_C (x : R) : aevalTower g y (C x) = g x := eval₂_C _ _ _ +-- See note [no_index around OfNat.ofNat] +@[simp] +theorem aevalTower_ofNat (n : Nat) [n.AtLeastTwo] : + aevalTower g y (no_index (OfNat.ofNat n) : MvPolynomial σ R) = OfNat.ofNat n := + _root_.map_ofNat _ _ + @[simp] theorem aevalTower_comp_C : (aevalTower g y : MvPolynomial σ R →+* A).comp C = g := RingHom.ext <| aevalTower_C _ _ diff --git a/Mathlib/Algebra/MvPolynomial/Cardinal.lean b/Mathlib/Algebra/MvPolynomial/Cardinal.lean index 3ee977de57b85..09b4c9e178b8c 100644 --- a/Mathlib/Algebra/MvPolynomial/Cardinal.lean +++ b/Mathlib/Algebra/MvPolynomial/Cardinal.lean @@ -40,7 +40,10 @@ theorem cardinalMk_eq_lift [IsEmpty σ] : #(MvPolynomial σ R) = Cardinal.lift.{ @[deprecated (since := "2024-11-10")] alias cardinal_mk_eq_lift := cardinalMk_eq_lift -theorem cardinal_lift_mk_le_max {σ : Type u} {R : Type v} [CommSemiring R] : #(MvPolynomial σ R) ≤ +@[nontriviality] +theorem cardinalMk_eq_one [Subsingleton R] : #(MvPolynomial σ R) = 1 := mk_eq_one _ + +theorem cardinalMk_le_max_lift {σ : Type u} {R : Type v} [CommSemiring R] : #(MvPolynomial σ R) ≤ max (max (Cardinal.lift.{u} #R) <| Cardinal.lift.{v} #σ) ℵ₀ := by cases subsingleton_or_nontrivial R · exact (mk_eq_one _).trans_le (le_max_of_le_right one_le_aleph0) @@ -48,6 +51,8 @@ theorem cardinal_lift_mk_le_max {σ : Type u} {R : Type v} [CommSemiring R] : #( · exact cardinalMk_eq_lift.trans_le (le_max_of_le_left <| le_max_left _ _) · exact cardinalMk_eq_max_lift.le +@[deprecated (since := "2024-11-21")] alias cardinal_lift_mk_le_max := cardinalMk_le_max_lift + end TwoUniverses variable {σ R : Type u} [CommSemiring R] @@ -57,10 +62,12 @@ theorem cardinalMk_eq_max [Nonempty σ] [Nontrivial R] : @[deprecated (since := "2024-11-10")] alias cardinal_mk_eq_max := cardinalMk_eq_max +theorem cardinalMk_eq [IsEmpty σ] : #(MvPolynomial σ R) = #R := by simp + /-- The cardinality of the multivariate polynomial ring, `MvPolynomial σ R` is at most the maximum of `#R`, `#σ` and `ℵ₀` -/ theorem cardinalMk_le_max : #(MvPolynomial σ R) ≤ max (max #R #σ) ℵ₀ := - cardinal_lift_mk_le_max.trans <| by rw [lift_id, lift_id] + cardinalMk_le_max_lift.trans <| by rw [lift_id, lift_id] @[deprecated (since := "2024-11-10")] alias cardinal_mk_le_max := cardinalMk_le_max diff --git a/Mathlib/Algebra/MvPolynomial/Equiv.lean b/Mathlib/Algebra/MvPolynomial/Equiv.lean index 6b77addf42b8d..ebcd5678aa4a4 100644 --- a/Mathlib/Algebra/MvPolynomial/Equiv.lean +++ b/Mathlib/Algebra/MvPolynomial/Equiv.lean @@ -336,7 +336,6 @@ theorem finSuccEquiv_eq : rfl · refine Fin.cases ?_ ?_ i <;> simp [finSuccEquiv] -@[simp] theorem finSuccEquiv_apply (p : MvPolynomial (Fin (n + 1)) R) : finSuccEquiv R n p = eval₂Hom (Polynomial.C.comp (C : R →+* MvPolynomial (Fin n) R)) @@ -356,10 +355,10 @@ theorem finSuccEquiv_comp_C_eq_C {R : Type u} [CommSemiring R] (n : ℕ) : variable {n} {R} -theorem finSuccEquiv_X_zero : finSuccEquiv R n (X 0) = Polynomial.X := by simp +theorem finSuccEquiv_X_zero : finSuccEquiv R n (X 0) = Polynomial.X := by simp [finSuccEquiv_apply] theorem finSuccEquiv_X_succ {j : Fin n} : finSuccEquiv R n (X j.succ) = Polynomial.C (X j) := by - simp + simp [finSuccEquiv_apply] /-- The coefficient of `m` in the `i`-th coefficient of `finSuccEquiv R n f` equals the coefficient of `Finsupp.cons i m` in `f`. -/ @@ -414,7 +413,7 @@ theorem coeff_eval_eq_eval_coeff (s' : Fin n → R) (f : Polynomial (MvPolynomia simp only [Polynomial.coeff_map] theorem support_coeff_finSuccEquiv {f : MvPolynomial (Fin (n + 1)) R} {i : ℕ} {m : Fin n →₀ ℕ} : - m ∈ (Polynomial.coeff ((finSuccEquiv R n) f) i).support ↔ Finsupp.cons i m ∈ f.support := by + m ∈ ((finSuccEquiv R n f).coeff i).support ↔ m.cons i ∈ f.support := by apply Iff.intro · intro h simpa [← finSuccEquiv_coeff_coeff] using h @@ -441,7 +440,7 @@ lemma totalDegree_coeff_finSuccEquiv_add_le (f : MvPolynomial (Fin (n + 1)) R) ( · rw [← support_coeff_finSuccEquiv] exact hσ1 -theorem finSuccEquiv_support (f : MvPolynomial (Fin (n + 1)) R) : +theorem support_finSuccEquiv (f : MvPolynomial (Fin (n + 1)) R) : (finSuccEquiv R n f).support = Finset.image (fun m : Fin (n + 1) →₀ ℕ => m 0) f.support := by ext i rw [Polynomial.mem_support_iff, Finset.mem_image, Finsupp.ne_iff] @@ -454,9 +453,14 @@ theorem finSuccEquiv_support (f : MvPolynomial (Fin (n + 1)) R) : refine ⟨tail m, ?_⟩ rwa [← coeff, zero_apply, ← mem_support_iff, support_coeff_finSuccEquiv, cons_tail] -theorem finSuccEquiv_support' {f : MvPolynomial (Fin (n + 1)) R} {i : ℕ} : - Finset.image (Finsupp.cons i) (Polynomial.coeff ((finSuccEquiv R n) f) i).support = - f.support.filter fun m => m 0 = i := by +@[deprecated (since := "2024-11-05")] alias finSuccEquiv_support := support_finSuccEquiv + +theorem mem_support_finSuccEquiv {f : MvPolynomial (Fin (n + 1)) R} {x} : + x ∈ (finSuccEquiv R n f).support ↔ x ∈ (fun m : Fin (n + 1) →₀ _ ↦ m 0) '' f.support := by + simpa using congr(x ∈ $(support_finSuccEquiv f)) + +theorem image_support_finSuccEquiv {f : MvPolynomial (Fin (n + 1)) R} {i : ℕ} : + ((finSuccEquiv R n f).coeff i).support.image (Finsupp.cons i) = {m ∈ f.support | m 0 = i} := by ext m rw [Finset.mem_filter, Finset.mem_image, mem_support_iff] conv_lhs => @@ -472,6 +476,19 @@ theorem finSuccEquiv_support' {f : MvPolynomial (Fin (n + 1)) R} {i : ℕ} : rw [← h.2, cons_tail] simp [h.1] +@[deprecated (since := "2024-11-05")] alias finSuccEquiv_support' := image_support_finSuccEquiv + +lemma mem_image_support_coeff_finSuccEquiv {f : MvPolynomial (Fin (n + 1)) R} {i : ℕ} {x} : + x ∈ Finsupp.cons i '' ((finSuccEquiv R n f).coeff i).support ↔ + x ∈ f.support ∧ x 0 = i := by + simpa using congr(x ∈ $image_support_finSuccEquiv) + +lemma mem_support_coeff_finSuccEquiv {f : MvPolynomial (Fin (n + 1)) R} {i : ℕ} {x} : + x ∈ ((finSuccEquiv R n f).coeff i).support ↔ x.cons i ∈ f.support := by + rw [← (Finsupp.cons_right_injective i).mem_finset_image (a := x), + image_support_finSuccEquiv] + simp only [Finset.mem_filter, mem_support_iff, ne_eq, cons_zero, and_true] + -- TODO: generalize `finSuccEquiv R n` to an arbitrary ZeroHom theorem support_finSuccEquiv_nonempty {f : MvPolynomial (Fin (n + 1)) R} (h : f ≠ 0) : (finSuccEquiv R n f).support.Nonempty := by @@ -485,7 +502,7 @@ theorem degree_finSuccEquiv {f : MvPolynomial (Fin (n + 1)) R} (h : f ≠ 0) : have h₂ : WithBot.some = Nat.cast := rfl have h' : ((finSuccEquiv R n f).support.sup fun x => x) = degreeOf 0 f := by - rw [degreeOf_eq_sup, finSuccEquiv_support f, Finset.sup_image, h₀] + rw [degreeOf_eq_sup, support_finSuccEquiv, Finset.sup_image, h₀] rw [Polynomial.degree, ← h', ← h₂, Finset.coe_sup_of_nonempty (support_finSuccEquiv_nonempty h), Finset.max_eq_sup_coe, h₁] @@ -524,8 +541,8 @@ lemma finSuccEquiv_rename_finSuccEquiv (e : σ ≃ Fin n) (φ : MvPolynomial (Op (Polynomial.mapRingHom (rename e).toRingHom).comp (optionEquivLeft R σ) by exact DFunLike.congr_fun this φ apply ringHom_ext - · simp [Polynomial.algebraMap_apply, algebraMap_eq] - · rintro (i|i) <;> simp + · simp [Polynomial.algebraMap_apply, algebraMap_eq, finSuccEquiv_apply] + · rintro (i|i) <;> simp [finSuccEquiv_apply] end diff --git a/Mathlib/Algebra/Order/Archimedean/Basic.lean b/Mathlib/Algebra/Order/Archimedean/Basic.lean index 7756989822b78..bf952ac20407b 100644 --- a/Mathlib/Algebra/Order/Archimedean/Basic.lean +++ b/Mathlib/Algebra/Order/Archimedean/Basic.lean @@ -30,6 +30,8 @@ number `n` such that `x ≤ n • y`. * `ℕ`, `ℤ`, and `ℚ` are archimedean. -/ +assert_not_exists Finset + open Int Set variable {α : Type*} @@ -62,11 +64,11 @@ instance OrderDual.instMulArchimedean [OrderedCommGroup α] [MulArchimedean α] instance Additive.instArchimedean [OrderedCommGroup α] [MulArchimedean α] : Archimedean (Additive α) := - ⟨fun x _ hy ↦ MulArchimedean.arch (toMul x) hy⟩ + ⟨fun x _ hy ↦ MulArchimedean.arch x.toMul hy⟩ instance Multiplicative.instMulArchimedean [OrderedAddCommGroup α] [Archimedean α] : MulArchimedean (Multiplicative α) := - ⟨fun x _ hy ↦ Archimedean.arch (toAdd x) hy⟩ + ⟨fun x _ hy ↦ Archimedean.arch x.toAdd hy⟩ variable {M : Type*} diff --git a/Mathlib/Algebra/Order/Archimedean/Hom.lean b/Mathlib/Algebra/Order/Archimedean/Hom.lean index c4e7b11c89739..03816d8b0f244 100644 --- a/Mathlib/Algebra/Order/Archimedean/Hom.lean +++ b/Mathlib/Algebra/Order/Archimedean/Hom.lean @@ -14,6 +14,8 @@ ordered field. Reciprocally, such an ordered ring homomorphism exists when the c conditionally complete. -/ +assert_not_exists Finset + variable {α β : Type*} /-- There is at most one ordered ring homomorphism from a linear ordered field to an archimedean diff --git a/Mathlib/Algebra/Order/Archimedean/Submonoid.lean b/Mathlib/Algebra/Order/Archimedean/Submonoid.lean index fccc02aa01ab0..b30d6bec3e7ff 100644 --- a/Mathlib/Algebra/Order/Archimedean/Submonoid.lean +++ b/Mathlib/Algebra/Order/Archimedean/Submonoid.lean @@ -22,6 +22,8 @@ submonoid of the ambient group. submonoid. -/ +assert_not_exists Finset + @[to_additive] instance SubmonoidClass.instMulArchimedean {M S : Type*} [SetLike S M] [OrderedCommMonoid M] [SubmonoidClass S M] [MulArchimedean M] (H : S) : MulArchimedean H := by diff --git a/Mathlib/Algebra/Order/BigOperators/Ring/Finset.lean b/Mathlib/Algebra/Order/BigOperators/Ring/Finset.lean index b51accd2d82ad..1c522e8948d04 100644 --- a/Mathlib/Algebra/Order/BigOperators/Ring/Finset.lean +++ b/Mathlib/Algebra/Order/BigOperators/Ring/Finset.lean @@ -14,9 +14,12 @@ import Mathlib.Tactic.Ring This file contains the results concerning the interaction of finset big operators with ordered rings. + +In particular, this file contains the standard form of the Cauchy-Schwarz inequality, as well as +some of its immediate consequences. -/ -variable {ι R : Type*} +variable {ι R S : Type*} namespace Finset @@ -120,41 +123,10 @@ lemma prod_add_prod_le {i : ι} {f g h : ι → R} (hi : i ∈ s) (h2i : g i + h end OrderedCommSemiring -section LinearOrderedCommSemiring -variable [LinearOrderedCommSemiring R] [ExistsAddOfLE R] - -/-- **Cauchy-Schwarz inequality** for finsets. -/ -lemma sum_mul_sq_le_sq_mul_sq (s : Finset ι) (f g : ι → R) : - (∑ i ∈ s, f i * g i) ^ 2 ≤ (∑ i ∈ s, f i ^ 2) * ∑ i ∈ s, g i ^ 2 := by - nontriviality R - obtain h' | h' := (sum_nonneg fun _ _ ↦ sq_nonneg <| g _).eq_or_lt - · have h'' : ∀ i ∈ s, g i = 0 := fun i hi ↦ by - simpa using (sum_eq_zero_iff_of_nonneg fun i _ ↦ sq_nonneg (g i)).1 h'.symm i hi - rw [← h', sum_congr rfl (show ∀ i ∈ s, f i * g i = 0 from fun i hi ↦ by simp [h'' i hi])] - simp - refine le_of_mul_le_mul_of_pos_left - (le_of_add_le_add_left (a := (∑ i ∈ s, g i ^ 2) * (∑ j ∈ s, f j * g j) ^ 2) ?_) h' - calc - _ = ∑ i ∈ s, 2 * (f i * ∑ j ∈ s, g j ^ 2) * (g i * ∑ j ∈ s, f j * g j) := by - simp_rw [mul_assoc (2 : R), mul_mul_mul_comm, ← mul_sum, ← sum_mul]; ring - _ ≤ ∑ i ∈ s, ((f i * ∑ j ∈ s, g j ^ 2) ^ 2 + (g i * ∑ j ∈ s, f j * g j) ^ 2) := - sum_le_sum fun i _ ↦ two_mul_le_add_sq (f i * ∑ j ∈ s, g j ^ 2) (g i * ∑ j ∈ s, f j * g j) - _ = _ := by simp_rw [sum_add_distrib, mul_pow, ← sum_mul]; ring - -theorem sum_mul_self_eq_zero_iff (s : Finset ι) (f : ι → R) : - ∑ i ∈ s, f i * f i = 0 ↔ ∀ i ∈ s, f i = 0 := by - induction s using Finset.cons_induction with - | empty => simp - | cons i s his ih => - simp only [Finset.sum_cons, Finset.mem_cons, forall_eq_or_imp] - refine ⟨fun hc => ?_, fun h => by simpa [h.1] using ih.mpr h.2⟩ - have hi : f i * f i ≤ 0 := by - rw [← hc, le_add_iff_nonneg_right] - exact Finset.sum_nonneg fun i _ ↦ mul_self_nonneg (f i) - have h : f i * f i = 0 := (eq_of_le_of_le (mul_self_nonneg (f i)) hi).symm - exact ⟨zero_eq_mul_self.mp h.symm, ih.mp (by rw [← hc, h, zero_add])⟩ - -end LinearOrderedCommSemiring +theorem sum_mul_self_eq_zero_iff [LinearOrderedSemiring R] [ExistsAddOfLE R] (s : Finset ι) + (f : ι → R) : ∑ i ∈ s, f i * f i = 0 ↔ ∀ i ∈ s, f i = 0 := by + rw [sum_eq_zero_iff_of_nonneg fun _ _ ↦ mul_self_nonneg _] + simp lemma abs_prod [LinearOrderedCommRing R] (s : Finset ι) (f : ι → R) : |∏ x ∈ s, f x| = ∏ x ∈ s, |f x| := @@ -184,11 +156,63 @@ lemma prod_add_prod_le' (hi : i ∈ s) (h2i : g i + h i ≤ f i) (hgf : ∀ j assumption end CanonicallyOrderedCommSemiring + +/-! ### Named inequalities -/ + +/-- **Cauchy-Schwarz inequality** for finsets. + +This is written in terms of sequences `f`, `g`, and `r`, where `r` is a stand-in for +`√(f i * g i)`. See `sum_mul_sq_le_sq_mul_sq` for the more usual form in terms of squared +sequences. -/ +lemma sum_sq_le_sum_mul_sum_of_sq_eq_mul [LinearOrderedCommSemiring R] [ExistsAddOfLE R] + (s : Finset ι) {r f g : ι → R} (hf : ∀ i ∈ s, 0 ≤ f i) (hg : ∀ i ∈ s, 0 ≤ g i) + (ht : ∀ i ∈ s, r i ^ 2 = f i * g i) : (∑ i ∈ s, r i) ^ 2 ≤ (∑ i ∈ s, f i) * ∑ i ∈ s, g i := by + obtain h | h := (sum_nonneg hg).eq_or_gt + · have ht' : ∑ i ∈ s, r i = 0 := sum_eq_zero fun i hi ↦ by + simpa [(sum_eq_zero_iff_of_nonneg hg).1 h i hi] using ht i hi + rw [h, ht'] + simp + · refine le_of_mul_le_mul_of_pos_left + (le_of_add_le_add_left (a := (∑ i ∈ s, g i) * (∑ i ∈ s, r i) ^ 2) ?_) h + calc + _ = ∑ i ∈ s, 2 * r i * (∑ j ∈ s, g j) * (∑ j ∈ s, r j) := by + simp_rw [mul_assoc, ← mul_sum, ← sum_mul]; ring + _ ≤ ∑ i ∈ s, (f i * (∑ j ∈ s, g j) ^ 2 + g i * (∑ j ∈ s, r j) ^ 2) := by + gcongr with i hi + have ht : (r i * (∑ j ∈ s, g j) * (∑ j ∈ s, r j)) ^ 2 = + (f i * (∑ j ∈ s, g j) ^ 2) * (g i * (∑ j ∈ s, r j) ^ 2) := by + conv_rhs => rw [mul_mul_mul_comm, ← ht i hi] + ring + refine le_of_eq_of_le ?_ (two_mul_le_add_of_sq_eq_mul + (mul_nonneg (hf i hi) (sq_nonneg _)) (mul_nonneg (hg i hi) (sq_nonneg _)) ht) + repeat rw [mul_assoc] + _ = _ := by simp_rw [sum_add_distrib, ← sum_mul]; ring + +/-- **Cauchy-Schwarz inequality** for finsets, squared version. -/ +lemma sum_mul_sq_le_sq_mul_sq [LinearOrderedCommSemiring R] [ExistsAddOfLE R] (s : Finset ι) + (f g : ι → R) : (∑ i ∈ s, f i * g i) ^ 2 ≤ (∑ i ∈ s, f i ^ 2) * ∑ i ∈ s, g i ^ 2 := + sum_sq_le_sum_mul_sum_of_sq_eq_mul s + (fun _ _ ↦ sq_nonneg _) (fun _ _ ↦ sq_nonneg _) (fun _ _ ↦ mul_pow ..) + +/-- **Sedrakyan's lemma**, aka **Titu's lemma** or **Engel's form**. + +This is a specialization of the Cauchy-Schwarz inequality with the sequences `f n / √(g n)` and +`√(g n)`, though here it is proven without relying on square roots. -/ +theorem sq_sum_div_le_sum_sq_div [LinearOrderedSemifield R] [ExistsAddOfLE R] (s : Finset ι) + (f : ι → R) {g : ι → R} (hg : ∀ i ∈ s, 0 < g i) : + (∑ i ∈ s, f i) ^ 2 / ∑ i ∈ s, g i ≤ ∑ i ∈ s, f i ^ 2 / g i := by + have hg' : ∀ i ∈ s, 0 ≤ g i := fun i hi ↦ (hg i hi).le + have H : ∀ i ∈ s, 0 ≤ f i ^ 2 / g i := fun i hi ↦ div_nonneg (sq_nonneg _) (hg' i hi) + refine div_le_of_le_mul₀ (sum_nonneg hg') (sum_nonneg H) + (sum_sq_le_sum_mul_sum_of_sq_eq_mul _ H hg' fun i hi ↦ ?_) + rw [div_mul_cancel₀] + exact (hg i hi).ne' + end Finset -section AbsoluteValue +/-! ### Absolute values -/ -variable {S : Type*} +section AbsoluteValue lemma AbsoluteValue.sum_le [Semiring R] [OrderedSemiring S] (abv : AbsoluteValue R S) (s : Finset ι) (f : ι → R) : abv (∑ i ∈ s, f i) ≤ ∑ i ∈ s, abv (f i) := @@ -212,6 +236,8 @@ lemma IsAbsoluteValue.map_prod [CommSemiring R] [Nontrivial R] [LinearOrderedCom end AbsoluteValue +/-! ### Positivity extension -/ + namespace Mathlib.Meta.Positivity open Qq Lean Meta Finset diff --git a/Mathlib/Algebra/Order/Chebyshev.lean b/Mathlib/Algebra/Order/Chebyshev.lean index b0be97b492f03..d359503ea08c9 100644 --- a/Mathlib/Algebra/Order/Chebyshev.lean +++ b/Mathlib/Algebra/Order/Chebyshev.lean @@ -7,8 +7,7 @@ import Mathlib.Algebra.Order.Monovary import Mathlib.Algebra.Order.Rearrangement import Mathlib.GroupTheory.Perm.Cycle.Basic import Mathlib.Tactic.GCongr -import Mathlib.Tactic.Positivity.Basic -import Mathlib.Tactic.Positivity.Finset +import Mathlib.Tactic.Positivity /-! # Chebyshev's sum inequality diff --git a/Mathlib/Algebra/Order/Field/Power.lean b/Mathlib/Algebra/Order/Field/Power.lean index d363f2170a5c4..9cec9ad4fcc29 100644 --- a/Mathlib/Algebra/Order/Field/Power.lean +++ b/Mathlib/Algebra/Order/Field/Power.lean @@ -73,13 +73,13 @@ theorem zpow_injective (h₀ : 0 < a) (h₁ : a ≠ 1) : Injective (a ^ · : ℤ theorem zpow_inj (h₀ : 0 < a) (h₁ : a ≠ 1) : a ^ m = a ^ n ↔ m = n := zpow_right_inj₀ h₀ h₁ -@[deprecated (since := "2024-10-08")] +@[deprecated "No deprecation message was provided." (since := "2024-10-08")] theorem zpow_le_max_of_min_le {x : α} (hx : 1 ≤ x) {a b c : ℤ} (h : min a b ≤ c) : x ^ (-c) ≤ max (x ^ (-a)) (x ^ (-b)) := have : Antitone fun n : ℤ => x ^ (-n) := fun _ _ h => zpow_le_zpow_right₀ hx (neg_le_neg h) (this h).trans_eq this.map_min -@[deprecated (since := "2024-10-08")] +@[deprecated "No deprecation message was provided." (since := "2024-10-08")] theorem zpow_le_max_iff_min_le {x : α} (hx : 1 < x) {a b c : ℤ} : x ^ (-c) ≤ max (x ^ (-a)) (x ^ (-b)) ↔ min a b ≤ c := by simp_rw [le_max_iff, min_le_iff, zpow_le_zpow_iff_right₀ hx, neg_le_neg_iff] diff --git a/Mathlib/Algebra/Order/Floor.lean b/Mathlib/Algebra/Order/Floor.lean index 5e5aaf78be137..0ec2dc284de96 100644 --- a/Mathlib/Algebra/Order/Floor.lean +++ b/Mathlib/Algebra/Order/Floor.lean @@ -13,7 +13,7 @@ import Mathlib.Order.GaloisConnection import Mathlib.Tactic.Abel import Mathlib.Tactic.FieldSimp import Mathlib.Tactic.Linarith -import Mathlib.Tactic.Positivity +import Mathlib.Tactic.Positivity.Basic /-! # Floor and ceil @@ -54,6 +54,8 @@ many lemmas. rounding, floor, ceil -/ +assert_not_exists Finset + open Set variable {F α β : Type*} @@ -1502,7 +1504,7 @@ theorem abs_sub_round_div_natCast_eq {m n : ℕ} : @[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] + rw [round_eq x, show x - 1 / 2 = x + 1 / 2 - 1 by linarith] exact Int.sub_one_lt_floor (x + 1 / 2) @[bound] diff --git a/Mathlib/Algebra/Order/Floor/Prime.lean b/Mathlib/Algebra/Order/Floor/Prime.lean index 506029de21811..8158125cc8e49 100644 --- a/Mathlib/Algebra/Order/Floor/Prime.lean +++ b/Mathlib/Algebra/Order/Floor/Prime.lean @@ -39,7 +39,7 @@ theorem exists_prime_mul_pow_div_factorial_lt_one [LinearOrderedField K] [FloorR letI := Preorder.topology K haveI : OrderTopology K := ⟨rfl⟩ ((Filter.frequently_atTop.mpr Nat.exists_infinite_primes).and_eventually - (eventually_lt_of_tendsto_lt zero_lt_one + (Filter.Tendsto.eventually_lt_const zero_lt_one (FloorSemiring.tendsto_mul_pow_div_factorial_sub_atTop a c 1))).forall_exists_of_atTop (n + 1) diff --git a/Mathlib/Algebra/Order/Group/Finset.lean b/Mathlib/Algebra/Order/Group/Finset.lean new file mode 100644 index 0000000000000..e08078aa0b808 --- /dev/null +++ b/Mathlib/Algebra/Order/Group/Finset.lean @@ -0,0 +1,81 @@ +/- +Copyright (c) 2024 Yaël Dillies, Andrew Yang. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yaël Dillies, Andrew Yang +-/ +import Mathlib.Algebra.Order.Group.OrderIso +import Mathlib.Algebra.Order.Monoid.Canonical.Defs +import Mathlib.Algebra.Order.Monoid.Unbundled.MinMax +import Mathlib.Algebra.Order.Monoid.Unbundled.Pow +import Mathlib.Algebra.Order.Monoid.Unbundled.WithTop +import Mathlib.Data.Finset.Lattice.Fold + +/-! +# `Finset.sup` in a group +-/ + +assert_not_exists MonoidWithZero + +namespace Finset +variable {ι κ M G : Type*} + +lemma fold_max_add [LinearOrder M] [Add M] [AddRightMono M] (s : Finset ι) (a : WithBot M) + (f : ι → M) : s.fold max ⊥ (fun i ↦ ↑(f i) + a) = s.fold max ⊥ ((↑) ∘ f) + a := by + classical + induction' s using Finset.induction_on with a s _ ih <;> simp [*, max_add_add_right] + +@[to_additive nsmul_inf'] +lemma inf'_pow [LinearOrder M] [Monoid M] [MulLeftMono M] [MulRightMono M] (s : Finset ι) + (f : ι → M) (n : ℕ) (hs) : s.inf' hs f ^ n = s.inf' hs fun a ↦ f a ^ n := + map_finset_inf' (OrderHom.mk _ <| pow_left_mono n) hs _ + +@[to_additive nsmul_sup'] +lemma sup'_pow [LinearOrder M] [Monoid M] [MulLeftMono M] [MulRightMono M] (s : Finset ι) + (f : ι → M) (n : ℕ) (hs) : s.sup' hs f ^ n = s.sup' hs fun a ↦ f a ^ n := + map_finset_sup' (OrderHom.mk _ <| pow_left_mono n) hs _ + +section Group +variable [Group G] [LinearOrder G] + +@[to_additive "Also see `Finset.sup'_add'` that works for canonically ordered monoids."] +lemma sup'_mul [MulRightMono G] (s : Finset ι) (f : ι → G) (a : G) (hs) : + s.sup' hs f * a = s.sup' hs fun i ↦ f i * a := map_finset_sup' (OrderIso.mulRight a) hs f + +set_option linter.docPrime false in +@[to_additive "Also see `Finset.add_sup''` that works for canonically ordered monoids."] +lemma mul_sup' [MulLeftMono G] (s : Finset ι) (f : ι → G) (a : G) (hs) : + a * s.sup' hs f = s.sup' hs fun i ↦ a * f i := map_finset_sup' (OrderIso.mulLeft a) hs f + +end Group + +section CanonicallyLinearOrderedAddCommMonoid +variable [CanonicallyLinearOrderedAddCommMonoid M] [Sub M] [AddLeftReflectLE M] [OrderedSub M] + {s : Finset ι} {t : Finset κ} + +/-- Also see `Finset.sup'_add` that works for ordered groups. -/ +lemma sup'_add' (s : Finset ι) (f : ι → M) (a : M) (hs : s.Nonempty) : + s.sup' hs f + a = s.sup' hs fun i ↦ f i + a := by + apply le_antisymm + · apply add_le_of_le_tsub_right_of_le + · exact Finset.le_sup'_of_le _ hs.choose_spec le_add_self + · exact Finset.sup'_le _ _ fun i hi ↦ le_tsub_of_add_le_right (Finset.le_sup' (f · + a) hi) + · exact Finset.sup'_le _ _ fun i hi ↦ add_le_add_right (Finset.le_sup' _ hi) _ + +/-- Also see `Finset.add_sup'` that works for ordered groups. -/ +lemma add_sup'' (hs : s.Nonempty) (f : ι → M) (a : M) : + a + s.sup' hs f = s.sup' hs fun i ↦ a + f i := by simp_rw [add_comm a, Finset.sup'_add'] + +protected lemma sup_add (hs : s.Nonempty) (f : ι → M) (a : M) : + s.sup f + a = s.sup fun i ↦ f i + a := by + rw [← Finset.sup'_eq_sup hs, ← Finset.sup'_eq_sup hs, sup'_add'] + +protected lemma add_sup (hs : s.Nonempty) (f : ι → M) (a : M) : + a + s.sup f = s.sup fun i ↦ a + f i := by + rw [← Finset.sup'_eq_sup hs, ← Finset.sup'_eq_sup hs, add_sup''] + +lemma sup_add_sup (hs : s.Nonempty) (ht : t.Nonempty) (f : ι → M) (g : κ → M) : + s.sup f + t.sup g = (s ×ˢ t).sup fun ij ↦ f ij.1 + g ij.2 := by + simp only [Finset.sup_add hs, Finset.add_sup ht, Finset.sup_product_left] + +end CanonicallyLinearOrderedAddCommMonoid +end Finset diff --git a/Mathlib/Algebra/Order/Group/Nat.lean b/Mathlib/Algebra/Order/Group/Nat.lean index 5d7b7628327fd..1385365e53779 100644 --- a/Mathlib/Algebra/Order/Group/Nat.lean +++ b/Mathlib/Algebra/Order/Group/Nat.lean @@ -3,7 +3,7 @@ Copyright (c) 2014 Floris van Doorn (c) 2016 Microsoft Corporation. All rights r Released under Apache 2.0 license as described in the file LICENSE. Authors: Floris van Doorn, Leonardo de Moura, Jeremy Avigad, Mario Carneiro -/ -import Mathlib.Algebra.Group.Nat +import Mathlib.Algebra.Group.Nat.Basic import Mathlib.Algebra.Order.Monoid.Canonical.Defs import Mathlib.Algebra.Order.Sub.Defs import Mathlib.Data.Nat.Defs diff --git a/Mathlib/Algebra/Order/Group/Pointwise/Bounds.lean b/Mathlib/Algebra/Order/Group/Pointwise/Bounds.lean index ceb329876b8e6..294f6be7c92df 100644 --- a/Mathlib/Algebra/Order/Group/Pointwise/Bounds.lean +++ b/Mathlib/Algebra/Order/Group/Pointwise/Bounds.lean @@ -48,7 +48,12 @@ lemma BddAbove.mul (hs : BddAbove s) (ht : BddAbove t) : BddAbove (s * t) := lemma BddBelow.mul (hs : BddBelow s) (ht : BddBelow t) : BddBelow (s * t) := (Nonempty.mul hs ht).mono (subset_lowerBounds_mul s t) -@[to_additive (attr := deprecated (since := "2024-11-13"))] alias Set.BddAbove.mul := BddAbove.mul +@[to_additive] alias Set.BddAbove.mul := BddAbove.mul + +-- `alias` doesn't add the deprecation suggestion to the `to_additive` version +-- see https://github.com/leanprover-community/mathlib4/issues/19424 +attribute [deprecated BddAbove.mul (since := "2024-11-13")] Set.BddAbove.mul +attribute [deprecated BddAbove.add (since := "2024-11-13")] Set.BddAbove.add @[to_additive] lemma BddAbove.range_mul (hf : BddAbove (range f)) (hg : BddAbove (range g)) : diff --git a/Mathlib/Data/Set/Pointwise/Interval.lean b/Mathlib/Algebra/Order/Group/Pointwise/Interval.lean similarity index 83% rename from Mathlib/Data/Set/Pointwise/Interval.lean rename to Mathlib/Algebra/Order/Group/Pointwise/Interval.lean index 535b6e9100c34..fb5b4cae02b8a 100644 --- a/Mathlib/Data/Set/Pointwise/Interval.lean +++ b/Mathlib/Algebra/Order/Group/Pointwise/Interval.lean @@ -114,6 +114,67 @@ theorem Ici_mul_Ioi_subset' (a b : α) : Ici a * Ioi b ⊆ Ioi (a * b) := by end ContravariantLT +section LinearOrderedCommMonoid +variable [LinearOrderedCommMonoid α] [MulLeftReflectLE α] [ExistsMulOfLE α] {a b c d : α} + +-- TODO: Generalise to arbitrary actions using a `smul` version of `MulLeftMono` +@[to_additive (attr := simp)] +lemma smul_Icc (a b c : α) : a • Icc b c = Icc (a * b) (a * c) := by + ext x + constructor + · rintro ⟨y, ⟨hby, hyc⟩, rfl⟩ + exact ⟨mul_le_mul_left' hby _, mul_le_mul_left' hyc _⟩ + · rintro ⟨habx, hxac⟩ + obtain ⟨y, hy, rfl⟩ := exists_one_le_mul_of_le habx + refine ⟨b * y, ⟨le_mul_of_one_le_right' hy, ?_⟩, (mul_assoc ..).symm⟩ + rwa [mul_assoc, mul_le_mul_iff_left] at hxac + +@[to_additive] +lemma Icc_mul_Icc (hab : a ≤ b) (hcd : c ≤ d) : Icc a b * Icc c d = Icc (a * c) (b * d) := by + refine (Icc_mul_Icc_subset' _ _ _ _).antisymm fun x ⟨hacx, hxbd⟩ ↦ ?_ + obtain hxbc | hbcx := le_total x (b * c) + · obtain ⟨y, hy, rfl⟩ := exists_one_le_mul_of_le hacx + refine ⟨a * y, ⟨le_mul_of_one_le_right' hy, ?_⟩, c, left_mem_Icc.2 hcd, mul_right_comm ..⟩ + rwa [mul_right_comm, mul_le_mul_iff_right] at hxbc + · obtain ⟨y, hy, rfl⟩ := exists_one_le_mul_of_le hbcx + refine ⟨b, right_mem_Icc.2 hab, c * y, ⟨le_mul_of_one_le_right' hy, ?_⟩, (mul_assoc ..).symm⟩ + rwa [mul_assoc, mul_le_mul_iff_left] at hxbd + +end LinearOrderedCommMonoid + +section OrderedCommGroup +variable [OrderedCommGroup α] + +@[to_additive (attr := simp)] lemma inv_Ici (a : α) : (Ici a)⁻¹ = Iic a⁻¹ := ext fun _x ↦ le_inv' +@[to_additive (attr := simp)] lemma inv_Iic (a : α) : (Iic a)⁻¹ = Ici a⁻¹ := ext fun _x ↦ inv_le' +@[to_additive (attr := simp)] lemma inv_Ioi (a : α) : (Ioi a)⁻¹ = Iio a⁻¹ := ext fun _x ↦ lt_inv' +@[to_additive (attr := simp)] lemma inv_Iio (a : α) : (Iio a)⁻¹ = Ioi a⁻¹ := ext fun _x ↦ inv_lt' + +@[to_additive (attr := simp)] +lemma inv_Icc (a b : α) : (Icc a b)⁻¹ = Icc b⁻¹ a⁻¹ := by simp [← Ici_inter_Iic, inter_comm] + +@[to_additive (attr := simp)] +lemma inv_Ico (a b : α) : (Ico a b)⁻¹ = Ioc b⁻¹ a⁻¹ := by + simp [← Ici_inter_Iio, ← Ioi_inter_Iic, inter_comm] + +@[to_additive (attr := simp)] +lemma inv_Ioc (a b : α) : (Ioc a b)⁻¹ = Ico b⁻¹ a⁻¹ := by + simp [← Ioi_inter_Iic, ← Ici_inter_Iio, inter_comm] + +@[to_additive (attr := simp)] +lemma inv_Ioo (a b : α) : (Ioo a b)⁻¹ = Ioo b⁻¹ a⁻¹ := by simp [← Ioi_inter_Iio, inter_comm] + +@[deprecated (since := "2024-11-23")] alias preimage_neg_Ici := neg_Ici +@[deprecated (since := "2024-11-23")] alias preimage_neg_Iic := neg_Iic +@[deprecated (since := "2024-11-23")] alias preimage_neg_Ioi := neg_Ioi +@[deprecated (since := "2024-11-23")] alias preimage_neg_Iio := neg_Iio +@[deprecated (since := "2024-11-23")] alias preimage_neg_Icc := neg_Icc +@[deprecated (since := "2024-11-23")] alias preimage_neg_Ico := neg_Ico +@[deprecated (since := "2024-11-23")] alias preimage_neg_Ioc := neg_Ioc +@[deprecated (since := "2024-11-23")] alias preimage_neg_Ioo := neg_Ioo + +end OrderedCommGroup + section OrderedAddCommGroup variable [OrderedAddCommGroup α] (a b c : α) @@ -192,41 +253,6 @@ theorem preimage_add_const_Ioc : (fun x => x + a) ⁻¹' Ioc b c = Ioc (b - a) ( theorem preimage_add_const_Ioo : (fun x => x + a) ⁻¹' Ioo b c = Ioo (b - a) (c - a) := by simp [← Ioi_inter_Iio] -/-! -### Preimages under `x ↦ -x` --/ - - -@[simp] -theorem preimage_neg_Ici : -Ici a = Iic (-a) := - ext fun _x => le_neg - -@[simp] -theorem preimage_neg_Iic : -Iic a = Ici (-a) := - ext fun _x => neg_le - -@[simp] -theorem preimage_neg_Ioi : -Ioi a = Iio (-a) := - ext fun _x => lt_neg - -@[simp] -theorem preimage_neg_Iio : -Iio a = Ioi (-a) := - ext fun _x => neg_lt - -@[simp] -theorem preimage_neg_Icc : -Icc a b = Icc (-b) (-a) := by simp [← Ici_inter_Iic, inter_comm] - -@[simp] -theorem preimage_neg_Ico : -Ico a b = Ioc (-b) (-a) := by - simp [← Ici_inter_Iio, ← Ioi_inter_Iic, inter_comm] - -@[simp] -theorem preimage_neg_Ioc : -Ioc a b = Ico (-b) (-a) := by - simp [← Ioi_inter_Iic, ← Ici_inter_Iio, inter_comm] - -@[simp] -theorem preimage_neg_Ioo : -Ioo a b = Ioo (-b) (-a) := by simp [← Ioi_inter_Iio, inter_comm] - /-! ### Preimages under `x ↦ x - a` -/ @@ -433,6 +459,15 @@ theorem Iio_add_bij : BijOn (· + a) (Iio b) (Iio (b + a)) := end OrderedAddCommGroup +section LinearOrderedCommGroup +variable [LinearOrderedCommGroup α] + +@[to_additive (attr := simp)] +lemma inv_uIcc (a b : α) : [[a, b]]⁻¹ = [[a⁻¹, b⁻¹]] := by + simp only [uIcc, inv_Icc, inv_sup, inv_inf] + +end LinearOrderedCommGroup + section LinearOrderedAddCommGroup variable [LinearOrderedAddCommGroup α] (a b c d : α) @@ -445,10 +480,9 @@ theorem preimage_const_add_uIcc : (fun x => a + x) ⁻¹' [[b, c]] = [[b - a, c theorem preimage_add_const_uIcc : (fun x => x + a) ⁻¹' [[b, c]] = [[b - a, c - a]] := by simpa only [add_comm] using preimage_const_add_uIcc a b c --- TODO: Why is the notation `-[[a, b]]` broken? -@[simp] -theorem preimage_neg_uIcc : @Neg.neg (Set α) Set.neg [[a, b]] = [[-a, -b]] := by - simp only [← Icc_min_max, preimage_neg_Icc, min_neg_neg, max_neg_neg] +@[deprecated neg_uIcc (since := "2024-11-23")] +theorem preimage_neg_uIcc : -[[a, b]] = [[-a, -b]] := by + simp only [← Icc_min_max, neg_Icc, min_neg_neg, max_neg_neg] @[simp] theorem preimage_sub_const_uIcc : (fun x => x - a) ⁻¹' [[b, c]] = [[b + a, c + a]] := by @@ -725,6 +759,22 @@ theorem image_mul_left_Ioo {a : α} (h : 0 < a) (b c : α) : (a * ·) '' Ioo b c = Ioo (a * b) (a * c) := by convert image_mul_right_Ioo b c h using 1 <;> simp only [mul_comm _ a] +theorem image_mul_right_Ico (a b : α) {c : α} (h : 0 < c) : + (fun x => x * c) '' Ico a b = Ico (a * c) (b * c) := + ((Units.mk0 c h.ne').mulRight.image_eq_preimage _).trans (by simp [h, division_def]) + +theorem image_mul_left_Ico {a : α} (h : 0 < a) (b c : α) : + (a * ·) '' Ico b c = Ico (a * b) (a * c) := by + convert image_mul_right_Ico b c h using 1 <;> simp only [mul_comm _ a] + +theorem image_mul_right_Ioc (a b : α) {c : α} (h : 0 < c) : + (fun x => x * c) '' Ioc a b = Ioc (a * c) (b * c) := + ((Units.mk0 c h.ne').mulRight.image_eq_preimage _).trans (by simp [h, division_def]) + +theorem image_mul_left_Ioc {a : α} (h : 0 < a) (b c : α) : + (a * ·) '' Ioc b c = Ioc (a * b) (a * c) := by + convert image_mul_right_Ioc b c h using 1 <;> simp only [mul_comm _ a] + /-- The (pre)image under `inv` of `Ioo 0 a` is `Ioi a⁻¹`. -/ theorem inv_Ioo_0_left {a : α} (ha : 0 < a) : (Ioo 0 a)⁻¹ = Ioi a⁻¹ := by ext x @@ -734,7 +784,7 @@ theorem inv_Ioo_0_left {a : α} (ha : 0 < a) : (Ioo 0 a)⁻¹ = Ioi a⁻¹ := by 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 +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] theorem image_const_mul_Ioi_zero {k : Type*} [LinearOrderedField k] {x : k} (hx : 0 < x) : @@ -754,6 +804,27 @@ theorem image_affine_Icc' {a : α} (h : 0 < a) (b c d : α) : rwa [Set.image_image] at this rw [image_mul_left_Icc' h, image_add_const_Icc] +@[simp] +theorem image_affine_Ico {a : α} (h : 0 < a) (b c d : α) : + (a * · + b) '' Ico c d = Ico (a * c + b) (a * d + b) := by + suffices (· + b) '' ((a * ·) '' Ico c d) = Ico (a * c + b) (a * d + b) by + rwa [Set.image_image] at this + rw [image_mul_left_Ico h, image_add_const_Ico] + +@[simp] +theorem image_affine_Ioc {a : α} (h : 0 < a) (b c d : α) : + (a * · + b) '' Ioc c d = Ioc (a * c + b) (a * d + b) := by + suffices (· + b) '' ((a * ·) '' Ioc c d) = Ioc (a * c + b) (a * d + b) by + rwa [Set.image_image] at this + rw [image_mul_left_Ioc h, image_add_const_Ioc] + +@[simp] +theorem image_affine_Ioo {a : α} (h : 0 < a) (b c d : α) : + (a * · + b) '' Ioo c d = Ioo (a * c + b) (a * d + b) := by + suffices (· + b) '' ((a * ·) '' Ioo c d) = Ioo (a * c + b) (a * d + b) by + rwa [Set.image_image] at this + rw [image_mul_left_Ioo h, image_add_const_Ioo] + end LinearOrderedField end Set diff --git a/Mathlib/Algebra/Order/GroupWithZero/Canonical.lean b/Mathlib/Algebra/Order/GroupWithZero/Canonical.lean index 95813028bae02..d26601f412fd7 100644 --- a/Mathlib/Algebra/Order/GroupWithZero/Canonical.lean +++ b/Mathlib/Algebra/Order/GroupWithZero/Canonical.lean @@ -85,7 +85,7 @@ instance instLinearOrderedAddCommMonoidWithTopAdditiveOrderDual : LinearOrderedAddCommMonoidWithTop (Additive αᵒᵈ) := { Additive.orderedAddCommMonoid, Additive.linearOrder with top := (0 : α) - top_add' := fun a ↦ zero_mul (Additive.toMul a) + top_add' := fun a ↦ zero_mul a.toMul le_top := fun _ ↦ zero_le' } variable [NoZeroDivisors α] @@ -195,7 +195,7 @@ instance : LinearOrderedAddCommGroupWithTop (Additive αᵒᵈ) := { Additive.subNegMonoid, instLinearOrderedAddCommMonoidWithTopAdditiveOrderDual, Additive.instNontrivial with neg_top := inv_zero (G₀ := α) - add_neg_cancel := fun a ha ↦ mul_inv_cancel₀ (G₀ := α) (id ha : Additive.toMul a ≠ 0) } + add_neg_cancel := fun a ha ↦ mul_inv_cancel₀ (G₀ := α) (id ha : a.toMul ≠ 0) } @[deprecated pow_lt_pow_right₀ (since := "2024-11-18")] lemma pow_lt_pow_succ (ha : 1 < a) : a ^ n < a ^ n.succ := pow_lt_pow_right₀ ha n.lt_succ_self @@ -219,7 +219,7 @@ theorem ofAdd_toDual_eq_zero_iff [LinearOrderedAddCommMonoidWithTop α] @[simp] theorem ofDual_toAdd_eq_top_iff [LinearOrderedAddCommMonoidWithTop α] - (x : Multiplicative αᵒᵈ) : OrderDual.ofDual (Multiplicative.toAdd x) = ⊤ ↔ x = 0 := Iff.rfl + (x : Multiplicative αᵒᵈ) : OrderDual.ofDual x.toAdd = ⊤ ↔ x = 0 := Iff.rfl @[simp] theorem ofAdd_bot [LinearOrderedAddCommMonoidWithTop α] : @@ -227,7 +227,7 @@ theorem ofAdd_bot [LinearOrderedAddCommMonoidWithTop α] : @[simp] theorem ofDual_toAdd_zero [LinearOrderedAddCommMonoidWithTop α] : - OrderDual.ofDual (Multiplicative.toAdd (0 : Multiplicative αᵒᵈ)) = ⊤ := rfl + OrderDual.ofDual (0 : Multiplicative αᵒᵈ).toAdd = ⊤ := rfl instance [LinearOrderedAddCommGroupWithTop α] : LinearOrderedCommGroupWithZero (Multiplicative αᵒᵈ) := diff --git a/Mathlib/Algebra/Order/GroupWithZero/Finset.lean b/Mathlib/Algebra/Order/GroupWithZero/Finset.lean new file mode 100644 index 0000000000000..0047881217ebf --- /dev/null +++ b/Mathlib/Algebra/Order/GroupWithZero/Finset.lean @@ -0,0 +1,64 @@ +/- +Copyright (c) 2022 Eric Wieser. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Eric Wieser, Yaël Dillies, Andrew Yang +-/ +import Mathlib.Algebra.Order.GroupWithZero.Canonical +import Mathlib.Algebra.Order.GroupWithZero.Unbundled.Lemmas +import Mathlib.Data.Finset.Lattice.Fold + +/-! +# `Finset.sup` in a group with zero +-/ + +namespace Finset +variable {ι M₀ G₀ : Type*} + +section MonoidWithZero +variable [MonoidWithZero M₀] {s : Finset ι} {a b : ι → M₀} + +lemma sup_mul_le_mul_sup_of_nonneg [SemilatticeSup M₀] [OrderBot M₀] [PosMulMono M₀] [MulPosMono M₀] + (ha : ∀ i ∈ s, 0 ≤ a i) (hb : ∀ i ∈ s, 0 ≤ b i) : s.sup (a * b) ≤ s.sup a * s.sup b := + Finset.sup_le fun _i hi ↦ + mul_le_mul (le_sup hi) (le_sup hi) (hb _ hi) ((ha _ hi).trans <| le_sup hi) + +lemma mul_inf_le_inf_mul_of_nonneg [SemilatticeInf M₀] [OrderTop M₀] [PosMulMono M₀] [MulPosMono M₀] + (ha : ∀ i ∈ s, 0 ≤ a i) (hb : ∀ i ∈ s, 0 ≤ b i) : s.inf a * s.inf b ≤ s.inf (a * b) := + Finset.le_inf fun i hi ↦ mul_le_mul (inf_le hi) (inf_le hi) (Finset.le_inf hb) (ha i hi) + +lemma sup'_mul_le_mul_sup'_of_nonneg [SemilatticeSup M₀] [PosMulMono M₀] [MulPosMono M₀] + (ha : ∀ i ∈ s, 0 ≤ a i) (hb : ∀ i ∈ s, 0 ≤ b i) (hs) : + s.sup' hs (a * b) ≤ s.sup' hs a * s.sup' hs b := + sup'_le _ _ fun _i hi ↦ + mul_le_mul (le_sup' _ hi) (le_sup' _ hi) (hb _ hi) ((ha _ hi).trans <| le_sup' _ hi) + +lemma inf'_mul_le_mul_inf'_of_nonneg [SemilatticeInf M₀] [PosMulMono M₀] [MulPosMono M₀] + (ha : ∀ i ∈ s, 0 ≤ a i) (hb : ∀ i ∈ s, 0 ≤ b i) (hs) : + s.inf' hs a * s.inf' hs b ≤ s.inf' hs (a * b) := + le_inf' _ _ fun _i hi ↦ mul_le_mul (inf'_le _ hi) (inf'_le _ hi) (le_inf' _ _ hb) (ha _ hi) + +end MonoidWithZero + +section GroupWithZero +variable [GroupWithZero G₀] [SemilatticeSup G₀] {s : Finset ι} {a : G₀} + +lemma sup'_mul₀ [MulPosMono G₀] [MulPosReflectLE G₀] (ha : 0 < a) (f : ι → G₀) (s : Finset ι) (hs) : + s.sup' hs f * a = s.sup' hs fun i ↦ f i * a := map_finset_sup' (OrderIso.mulRight₀ _ ha) hs f + +set_option linter.docPrime false in +lemma mul₀_sup' [PosMulMono G₀] [PosMulReflectLE G₀] (ha : 0 < a) (f : ι → G₀) (s : Finset ι) (hs) : + a * s.sup' hs f = s.sup' hs fun i ↦ a * f i := map_finset_sup' (OrderIso.mulLeft₀ _ ha) hs f + +lemma sup'_div₀ [ZeroLEOneClass G₀] [MulPosStrictMono G₀] [MulPosReflectLE G₀] [PosMulReflectLT G₀] + (ha : 0 < a) (f : ι → G₀) (s : Finset ι) (hs) : s.sup' hs f / a = s.sup' hs fun i ↦ f i / a := + map_finset_sup' (OrderIso.divRight₀ _ ha) hs f + +end GroupWithZero + +lemma sup_div₀ [LinearOrderedCommGroupWithZero G₀] [OrderBot G₀] {a : G₀} (ha : 0 < a) + (s : Finset ι) (f : ι → G₀) : s.sup f / a = s.sup fun i ↦ f i / a := by + obtain rfl | hs := s.eq_empty_or_nonempty + · simp [← show (0 : G₀) = ⊥ from bot_unique zero_le'] + rw [← Finset.sup'_eq_sup hs, ← Finset.sup'_eq_sup hs, sup'_div₀ (ha := ha)] + +end Finset diff --git a/Mathlib/Algebra/Order/GroupWithZero/Unbundled.lean b/Mathlib/Algebra/Order/GroupWithZero/Unbundled.lean index bbd7e7951179d..488d67de45348 100644 --- a/Mathlib/Algebra/Order/GroupWithZero/Unbundled.lean +++ b/Mathlib/Algebra/Order/GroupWithZero/Unbundled.lean @@ -983,6 +983,11 @@ lemma mul_lt_one_of_nonneg_of_lt_one_right [MulPosMono M₀] (ha : a ≤ 1) (hb section variable [ZeroLEOneClass M₀] [PosMulMono M₀] [MulPosMono M₀] +@[bound] +protected lemma Bound.one_lt_mul : 1 ≤ a ∧ 1 < b ∨ 1 < a ∧ 1 ≤ b → 1 < a * b := by + rintro (⟨ha, hb⟩ | ⟨ha, hb⟩); exacts [one_lt_mul ha hb, one_lt_mul_of_lt_of_le ha hb] + +@[bound] lemma mul_le_one₀ (ha : a ≤ 1) (hb₀ : 0 ≤ b) (hb : b ≤ 1) : a * b ≤ 1 := one_mul (1 : M₀) ▸ mul_le_mul ha hb hb₀ zero_le_one @@ -1358,6 +1363,8 @@ lemma inv_le_iff_one_le_mul₀' (ha : 0 < a) : a⁻¹ ≤ b ↔ 1 ≤ a * b := b lemma one_le_inv₀ (ha : 0 < a) : 1 ≤ a⁻¹ ↔ a ≤ 1 := by simpa using one_le_inv_mul₀ ha (b := 1) lemma inv_le_one₀ (ha : 0 < a) : a⁻¹ ≤ 1 ↔ 1 ≤ a := by simpa using inv_mul_le_one₀ ha (b := 1) +@[bound] alias ⟨_, Bound.one_le_inv₀⟩ := one_le_inv₀ + @[bound] lemma inv_le_one_of_one_le₀ (ha : 1 ≤ a) : a⁻¹ ≤ 1 := (inv_le_one₀ <| zero_lt_one.trans_le ha).2 ha diff --git a/Mathlib/Algebra/Order/Monoid/ToMulBot.lean b/Mathlib/Algebra/Order/Monoid/ToMulBot.lean index ab578ee5f849e..79f4fd7e4a107 100644 --- a/Mathlib/Algebra/Order/Monoid/ToMulBot.lean +++ b/Mathlib/Algebra/Order/Monoid/ToMulBot.lean @@ -33,7 +33,7 @@ theorem toMulBot_zero : toMulBot (0 : WithZero (Multiplicative α)) = Multiplica @[simp] theorem toMulBot_coe (x : Multiplicative α) : - toMulBot ↑x = Multiplicative.ofAdd (↑(Multiplicative.toAdd x) : WithBot α) := + toMulBot ↑x = Multiplicative.ofAdd (↑x.toAdd : WithBot α) := rfl @[simp] diff --git a/Mathlib/Algebra/Order/Monoid/Unbundled/TypeTags.lean b/Mathlib/Algebra/Order/Monoid/Unbundled/TypeTags.lean index 1647d43c6a434..8a7c336d6901c 100644 --- a/Mathlib/Algebra/Order/Monoid/Unbundled/TypeTags.lean +++ b/Mathlib/Algebra/Order/Monoid/Unbundled/TypeTags.lean @@ -3,9 +3,9 @@ Copyright (c) 2016 Jeremy Avigad. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad, Leonardo de Moura, Mario Carneiro, Johannes Hölzl -/ -import Mathlib.Algebra.Group.TypeTags import Mathlib.Algebra.Order.Monoid.Unbundled.ExistsOfLE import Mathlib.Order.BoundedOrder +import Mathlib.Algebra.Group.TypeTags.Basic /-! # Ordered monoid structures on `Multiplicative α` and `Additive α`. -/ @@ -79,11 +79,11 @@ theorem ofMul_lt {a b : α} : ofMul a < ofMul b ↔ a < b := Iff.rfl @[simp] -theorem toMul_le {a b : Additive α} : toMul a ≤ toMul b ↔ a ≤ b := +theorem toMul_le {a b : Additive α} : a.toMul ≤ b.toMul ↔ a ≤ b := Iff.rfl @[simp] -theorem toMul_lt {a b : Additive α} : toMul a < toMul b ↔ a < b := +theorem toMul_lt {a b : Additive α} : a.toMul < b.toMul ↔ a < b := Iff.rfl end Additive @@ -101,11 +101,11 @@ theorem ofAdd_lt {a b : α} : ofAdd a < ofAdd b ↔ a < b := Iff.rfl @[simp] -theorem toAdd_le {a b : Multiplicative α} : toAdd a ≤ toAdd b ↔ a ≤ b := +theorem toAdd_le {a b : Multiplicative α} : a.toAdd ≤ b.toAdd ↔ a ≤ b := Iff.rfl @[simp] -theorem toAdd_lt {a b : Multiplicative α} : toAdd a < toAdd b ↔ a < b := +theorem toAdd_lt {a b : Multiplicative α} : a.toAdd < b.toAdd ↔ a < b := Iff.rfl end Multiplicative diff --git a/Mathlib/Algebra/Order/Nonneg/Floor.lean b/Mathlib/Algebra/Order/Nonneg/Floor.lean index a3472c9dde95b..1fdd9eefd1892 100644 --- a/Mathlib/Algebra/Order/Nonneg/Floor.lean +++ b/Mathlib/Algebra/Order/Nonneg/Floor.lean @@ -19,6 +19,8 @@ This is used to derive algebraic structures on `ℝ≥0` and `ℚ≥0` automatic * `{x : α // 0 ≤ x}` is a `FloorSemiring` if `α` is. -/ +assert_not_exists Finset + namespace Nonneg variable {α : Type*} diff --git a/Mathlib/Algebra/Order/Ring/Abs.lean b/Mathlib/Algebra/Order/Ring/Abs.lean index 9948d23da4d4b..5552705b81dff 100644 --- a/Mathlib/Algebra/Order/Ring/Abs.lean +++ b/Mathlib/Algebra/Order/Ring/Abs.lean @@ -7,6 +7,7 @@ import Mathlib.Algebra.Order.Group.Abs import Mathlib.Algebra.Order.Ring.Basic import Mathlib.Algebra.Order.Ring.Int import Mathlib.Algebra.Ring.Divisibility.Basic +import Mathlib.Algebra.Ring.Int.Units import Mathlib.Data.Nat.Cast.Order.Ring /-! @@ -151,6 +152,9 @@ theorem abs_sub_sq (a b : α) : |a - b| * |a - b| = a * a + b * b - (1 + 1) * a simp only [mul_add, add_comm, add_left_comm, mul_comm, sub_eq_add_neg, mul_one, mul_neg, neg_add_rev, neg_neg, add_assoc] +lemma abs_unit_intCast (a : ℤˣ) : |((a : ℤ) : α)| = 1 := by + cases Int.units_eq_one_or a <;> simp_all + end LinearOrderedCommRing section diff --git a/Mathlib/Algebra/Order/Ring/Basic.lean b/Mathlib/Algebra/Order/Ring/Basic.lean index 65844e24d7f30..6f6a50a96337c 100644 --- a/Mathlib/Algebra/Order/Ring/Basic.lean +++ b/Mathlib/Algebra/Order/Ring/Basic.lean @@ -3,6 +3,7 @@ Copyright (c) 2015 Jeremy Avigad. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad, Robert Y. Lewis -/ +import Mathlib.Algebra.Group.Nat.Units import Mathlib.Algebra.Order.Monoid.Unbundled.Pow import Mathlib.Algebra.Order.Ring.Defs import Mathlib.Algebra.Ring.Parity diff --git a/Mathlib/Algebra/Order/Ring/Finset.lean b/Mathlib/Algebra/Order/Ring/Finset.lean deleted file mode 100644 index dd490e170eff4..0000000000000 --- a/Mathlib/Algebra/Order/Ring/Finset.lean +++ /dev/null @@ -1,34 +0,0 @@ -/- -Copyright (c) 2022 Eric Wieser. All rights reserved. -Released under Apache 2.0 license as described in the file LICENSE. -Authors: Eric Wieser --/ -import Mathlib.Algebra.Order.Ring.Defs -import Mathlib.Data.Finset.Lattice.Fold - -/-! -# Algebraic properties of finitary supremum --/ - -namespace Finset -variable {ι R : Type*} [LinearOrderedSemiring R] {a b : ι → R} - -theorem sup_mul_le_mul_sup_of_nonneg [OrderBot R] (s : Finset ι) (ha : ∀ i ∈ s, 0 ≤ a i) - (hb : ∀ i ∈ s, 0 ≤ b i) : s.sup (a * b) ≤ s.sup a * s.sup b := - Finset.sup_le fun _i hi ↦ - mul_le_mul (le_sup hi) (le_sup hi) (hb _ hi) ((ha _ hi).trans <| le_sup hi) - -theorem mul_inf_le_inf_mul_of_nonneg [OrderTop R] (s : Finset ι) (ha : ∀ i ∈ s, 0 ≤ a i) - (hb : ∀ i ∈ s, 0 ≤ b i) : s.inf a * s.inf b ≤ s.inf (a * b) := - Finset.le_inf fun i hi ↦ mul_le_mul (inf_le hi) (inf_le hi) (Finset.le_inf hb) (ha i hi) - -theorem sup'_mul_le_mul_sup'_of_nonneg (s : Finset ι) (H : s.Nonempty) (ha : ∀ i ∈ s, 0 ≤ a i) - (hb : ∀ i ∈ s, 0 ≤ b i) : s.sup' H (a * b) ≤ s.sup' H a * s.sup' H b := - (sup'_le _ _) fun _i hi ↦ - mul_le_mul (le_sup' _ hi) (le_sup' _ hi) (hb _ hi) ((ha _ hi).trans <| le_sup' _ hi) - -theorem inf'_mul_le_mul_inf'_of_nonneg (s : Finset ι) (H : s.Nonempty) (ha : ∀ i ∈ s, 0 ≤ a i) - (hb : ∀ i ∈ s, 0 ≤ b i) : s.inf' H a * s.inf' H b ≤ s.inf' H (a * b) := - (le_inf' _ _) fun _i hi ↦ mul_le_mul (inf'_le _ hi) (inf'_le _ hi) (le_inf' _ _ hb) (ha _ hi) - -end Finset diff --git a/Mathlib/Algebra/Order/Ring/Unbundled/Basic.lean b/Mathlib/Algebra/Order/Ring/Unbundled/Basic.lean index 06cc0315f08b0..99bd1f2cfd31c 100644 --- a/Mathlib/Algebra/Order/Ring/Unbundled/Basic.lean +++ b/Mathlib/Algebra/Order/Ring/Unbundled/Basic.lean @@ -764,7 +764,7 @@ alias two_mul_le_add_pow_two := two_mul_le_add_sq /-- Binary, squared, and division-free **arithmetic mean-geometric mean inequality** (aka AM-GM inequality) for linearly ordered commutative semirings. -/ lemma four_mul_le_sq_add [ExistsAddOfLE α] [MulPosStrictMono α] - [ContravariantClass α α (· + ·) (· ≤ ·)] [CovariantClass α α (· + ·) (· ≤ ·)] + [AddLeftReflectLE α] [AddLeftMono α] (a b : α) : 4 * a * b ≤ (a + b) ^ 2 := by calc 4 * a * b _ = 2 * a * b + 2 * a * b := by rw [mul_assoc, two_add_two_eq_four.symm, add_mul, mul_assoc] @@ -774,6 +774,16 @@ lemma four_mul_le_sq_add [ExistsAddOfLE α] [MulPosStrictMono α] alias four_mul_le_pow_two_add := four_mul_le_sq_add +/-- Binary and division-free **arithmetic mean-geometric mean inequality** +(aka AM-GM inequality) for linearly ordered commutative semirings. -/ +lemma two_mul_le_add_of_sq_eq_mul [ExistsAddOfLE α] [MulPosStrictMono α] [PosMulStrictMono α] + [AddLeftReflectLE α] [AddLeftMono α] {a b r : α} + (ha : 0 ≤ a) (hb : 0 ≤ b) (ht : r ^ 2 = a * b) : 2 * r ≤ a + b := by + apply nonneg_le_nonneg_of_sq_le_sq (Left.add_nonneg ha hb) + conv_rhs => rw [← pow_two] + convert four_mul_le_sq_add a b using 1 + rw [mul_mul_mul_comm, two_mul, two_add_two_eq_four, ← pow_two, ht, mul_assoc] + end LinearOrderedCommSemiring section LinearOrderedRing diff --git a/Mathlib/Algebra/Order/SuccPred/TypeTags.lean b/Mathlib/Algebra/Order/SuccPred/TypeTags.lean index 7c69e6dc40162..4ee0095a26d7c 100644 --- a/Mathlib/Algebra/Order/SuccPred/TypeTags.lean +++ b/Mathlib/Algebra/Order/SuccPred/TypeTags.lean @@ -36,15 +36,19 @@ namespace Order open Additive Multiplicative @[simp] lemma succ_ofMul [Preorder X] [SuccOrder X] (x : X) : succ (ofMul x) = ofMul (succ x) := rfl -@[simp] lemma succ_toMul [Preorder X] [SuccOrder X] (x : X) : succ (toMul x) = toMul (succ x) := rfl +@[simp] lemma succ_toMul [Preorder X] [SuccOrder X] (x : Additive X) : + succ x.toMul = (succ x).toMul := rfl @[simp] lemma succ_ofAdd [Preorder X] [SuccOrder X] (x : X) : succ (ofAdd x) = ofAdd (succ x) := rfl -@[simp] lemma succ_toAdd [Preorder X] [SuccOrder X] (x : X) : succ (toAdd x) = toAdd (succ x) := rfl +@[simp] lemma succ_toAdd [Preorder X] [SuccOrder X] (x : Multiplicative X) : + succ x.toAdd = (succ x).toAdd := rfl @[simp] lemma pred_ofMul [Preorder X] [PredOrder X] (x : X) : pred (ofMul x) = ofMul (pred x) := rfl -@[simp] lemma pred_toMul [Preorder X] [PredOrder X] (x : X) : pred (toMul x) = toMul (pred x) := rfl +@[simp] lemma pred_toMul [Preorder X] [PredOrder X] (x : Additive X) : + pred x.toMul = (pred x).toMul := rfl @[simp] lemma pred_ofAdd [Preorder X] [PredOrder X] (x : X) : pred (ofAdd x) = ofAdd (pred x) := rfl -@[simp] lemma pred_toAdd [Preorder X] [PredOrder X] (x : X) : pred (toAdd x) = toAdd (pred x) := rfl +@[simp] lemma pred_toAdd [Preorder X] [PredOrder X] (x : Multiplicative X) : + pred x.toAdd = (pred x).toAdd := rfl end Order diff --git a/Mathlib/Algebra/Polynomial/Basic.lean b/Mathlib/Algebra/Polynomial/Basic.lean index 56c5d26cab71c..72765a3a6e65a 100644 --- a/Mathlib/Algebra/Polynomial/Basic.lean +++ b/Mathlib/Algebra/Polynomial/Basic.lean @@ -4,8 +4,9 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes, Johannes Hölzl, Kim Morrison, Jens Wagemaker -/ import Mathlib.Algebra.GroupWithZero.Divisibility -import Mathlib.Data.Finset.Sort import Mathlib.Algebra.MonoidAlgebra.Defs +import Mathlib.Algebra.Order.Monoid.Unbundled.WithTop +import Mathlib.Data.Finset.Sort import Mathlib.Order.OmegaCompletePartialOrder /-! diff --git a/Mathlib/Algebra/Polynomial/Bivariate.lean b/Mathlib/Algebra/Polynomial/Bivariate.lean index a78e8ffa4e2c8..d9feee54b8b5c 100644 --- a/Mathlib/Algebra/Polynomial/Bivariate.lean +++ b/Mathlib/Algebra/Polynomial/Bivariate.lean @@ -17,10 +17,12 @@ the abbreviation `CC` to view a constant in the base ring `R` as a bivariate pol -/ /-- The notation `Y` for `X` in the `Polynomial` scope. -/ -scoped[Polynomial] notation3:max "Y" => Polynomial.X (R := Polynomial _) +scoped[Polynomial.Bivariate] notation3:max "Y" => Polynomial.X (R := Polynomial _) /-- The notation `R[X][Y]` for `R[X][X]` in the `Polynomial` scope. -/ -scoped[Polynomial] notation3:max R "[X][Y]" => Polynomial (Polynomial R) +scoped[Polynomial.Bivariate] notation3:max R "[X][Y]" => Polynomial (Polynomial R) + +open scoped Polynomial.Bivariate namespace Polynomial diff --git a/Mathlib/Algebra/Polynomial/Degree/Operations.lean b/Mathlib/Algebra/Polynomial/Degree/Operations.lean index b64a85909e805..21d80bcb9d741 100644 --- a/Mathlib/Algebra/Polynomial/Degree/Operations.lean +++ b/Mathlib/Algebra/Polynomial/Degree/Operations.lean @@ -29,7 +29,7 @@ variable {R : Type u} {S : Type v} {a b c d : R} {n m : ℕ} section Semiring -variable [Semiring R] {p q r : R[X]} +variable [Semiring R] [Semiring S] {p q r : R[X]} theorem supDegree_eq_degree (p : R[X]) : p.toFinsupp.supDegree WithBot.some = p.degree := max_eq_sup_coe @@ -65,12 +65,15 @@ theorem natDegree_eq_of_le_of_coeff_ne_zero (pn : p.natDegree ≤ n) (p1 : p.coe p.natDegree = n := pn.antisymm (le_natDegree_of_ne_zero p1) -theorem natDegree_lt_natDegree {p q : R[X]} (hp : p ≠ 0) (hpq : p.degree < q.degree) : +theorem natDegree_lt_natDegree {q : S[X]} (hp : p ≠ 0) (hpq : p.degree < q.degree) : p.natDegree < q.natDegree := by by_cases hq : q = 0 · exact (not_lt_bot <| hq ▸ hpq).elim rwa [degree_eq_natDegree hp, degree_eq_natDegree hq, Nat.cast_lt] at hpq +lemma natDegree_eq_natDegree {q : S[X]} (hpq : p.degree = q.degree) : + p.natDegree = q.natDegree := by simp [natDegree, hpq] + theorem coeff_eq_zero_of_degree_lt (h : degree p < n) : coeff p n = 0 := Classical.not_not.1 (mt le_degree_of_ne_zero (not_le_of_gt h)) diff --git a/Mathlib/Algebra/Prime/Lemmas.lean b/Mathlib/Algebra/Prime/Lemmas.lean index 96ee461f3831f..0211c3bbc8c5e 100644 --- a/Mathlib/Algebra/Prime/Lemmas.lean +++ b/Mathlib/Algebra/Prime/Lemmas.lean @@ -8,7 +8,7 @@ import Mathlib.Algebra.Group.Even import Mathlib.Algebra.Group.Units.Equiv import Mathlib.Algebra.GroupWithZero.Hom import Mathlib.Algebra.Prime.Defs -import Mathlib.Order.Lattice +import Mathlib.Order.Monotone.Basic /-! # Associated, prime, and irreducible elements. diff --git a/Mathlib/Algebra/Quaternion.lean b/Mathlib/Algebra/Quaternion.lean index 69ce497aff36a..1ee91c3592cc2 100644 --- a/Mathlib/Algebra/Quaternion.lean +++ b/Mathlib/Algebra/Quaternion.lean @@ -93,7 +93,7 @@ theorem equivTuple_apply {R : Type*} (c₁ c₂ : R) (x : ℍ[R,c₁,c₂]) : @[simp] theorem mk.eta {R : Type*} {c₁ c₂} (a : ℍ[R,c₁,c₂]) : mk a.1 a.2 a.3 a.4 = a := rfl -variable {S T R : Type*} {c₁ c₂ : R} (r x y z : R) (a b c : ℍ[R,c₁,c₂]) +variable {S T R : Type*} {c₁ c₂ : R} (r x y : R) (a b : ℍ[R,c₁,c₂]) instance [Subsingleton R] : Subsingleton ℍ[R, c₁, c₂] := (equivTuple c₁ c₂).subsingleton instance [Nontrivial R] : Nontrivial ℍ[R, c₁, c₂] := (equivTuple c₁ c₂).surjective.nontrivial @@ -742,7 +742,7 @@ instance {R : Type*} [One R] [Neg R] [Nontrivial R] : Nontrivial ℍ[R] := namespace Quaternion -variable {S T R : Type*} [CommRing R] (r x y z : R) (a b c : ℍ[R]) +variable {S T R : Type*} [CommRing R] (r x y : R) (a b : ℍ[R]) export QuaternionAlgebra (re imI imJ imK) diff --git a/Mathlib/Algebra/Ring/Idempotents.lean b/Mathlib/Algebra/Ring/Idempotents.lean index 80a2c2e0be568..8b7ce4e91aadd 100644 --- a/Mathlib/Algebra/Ring/Idempotents.lean +++ b/Mathlib/Algebra/Ring/Idempotents.lean @@ -67,6 +67,17 @@ theorem one_sub {p : R} (h : IsIdempotentElem p) : IsIdempotentElem (1 - p) := b theorem one_sub_iff {p : R} : IsIdempotentElem (1 - p) ↔ IsIdempotentElem p := ⟨fun h => sub_sub_cancel 1 p ▸ h.one_sub, IsIdempotentElem.one_sub⟩ +theorem add_sub_mul_of_commute {R} [Ring R] {p q : R} (h : Commute p q) + (hp : IsIdempotentElem p) (hq : IsIdempotentElem q) : + IsIdempotentElem (p + q - p * q) := by + convert (hp.one_sub.mul_of_commute ?_ hq.one_sub).one_sub using 1 + · simp_rw [sub_mul, mul_sub, one_mul, mul_one, sub_sub, sub_sub_cancel, add_sub, add_comm] + · simp_rw [commute_iff_eq, sub_mul, mul_sub, one_mul, mul_one, sub_sub, add_sub, add_comm, h.eq] + +theorem add_sub_mul {R} [CommRing R] {p q : R} (hp : IsIdempotentElem p) (hq : IsIdempotentElem q) : + IsIdempotentElem (p + q - p * q) := + add_sub_mul_of_commute (mul_comm p q) hp hq + theorem pow {p : N} (n : ℕ) (h : IsIdempotentElem p) : IsIdempotentElem (p ^ n) := Nat.recOn n ((pow_zero p).symm ▸ one) fun n _ => show p ^ n.succ * p ^ n.succ = p ^ n.succ by diff --git a/Mathlib/Algebra/Ring/Nat.lean b/Mathlib/Algebra/Ring/Nat.lean index 9b456d31dec8a..e2c57fc380685 100644 --- a/Mathlib/Algebra/Ring/Nat.lean +++ b/Mathlib/Algebra/Ring/Nat.lean @@ -4,7 +4,7 @@ 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.Algebra.CharZero.Defs -import Mathlib.Algebra.Group.Nat +import Mathlib.Algebra.Group.Nat.Basic import Mathlib.Algebra.Ring.Defs /-! @@ -15,8 +15,6 @@ This file contains the commutative semiring instance on the natural numbers. See note [foundational algebra order theory]. -/ -open Multiplicative - namespace Nat /-! ### Instances -/ diff --git a/Mathlib/Algebra/Ring/Parity.lean b/Mathlib/Algebra/Ring/Parity.lean index 72fdec393def4..7b3959696657a 100644 --- a/Mathlib/Algebra/Ring/Parity.lean +++ b/Mathlib/Algebra/Ring/Parity.lean @@ -3,6 +3,7 @@ Copyright (c) 2022 Damiano Testa. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Damiano Testa -/ +import Mathlib.Algebra.Group.Nat.Even import Mathlib.Data.Nat.Cast.Basic import Mathlib.Data.Nat.Cast.Commute import Mathlib.Data.Set.Operations @@ -88,7 +89,6 @@ lemma Even.pow_of_ne_zero (ha : Even a) : ∀ {n : ℕ}, n ≠ 0 → Even (a ^ n /-- An element `a` of a semiring is odd if there exists `k` such `a = 2*k + 1`. -/ def Odd (a : α) : Prop := ∃ k, a = 2 * k + 1 -set_option linter.deprecated false in lemma odd_iff_exists_bit1 : Odd a ↔ ∃ b, a = 2 * b + 1 := exists_congr fun b ↦ by rw [two_mul] alias ⟨Odd.exists_bit1, _⟩ := odd_iff_exists_bit1 @@ -113,6 +113,8 @@ lemma Odd.add_odd : Odd a → Odd b → Even (a + b) := by @[simp] lemma Even.add_one (h : Even a) : Odd (a + 1) := h.add_odd odd_one @[simp] lemma Even.one_add (h : Even a) : Odd (1 + a) := h.odd_add odd_one +@[simp] lemma Odd.add_one (h : Odd a) : Even (a + 1) := h.add_odd odd_one +@[simp] lemma Odd.one_add (h : Odd a) : Even (1 + a) := odd_one.add_odd h lemma odd_two_mul_add_one (a : α) : Odd (2 * a + 1) := ⟨_, rfl⟩ @@ -244,7 +246,6 @@ lemma mod_two_add_add_odd_mod_two (m : ℕ) {n : ℕ} (hn : Odd n) : m % 2 + (m lemma even_add' : Even (m + n) ↔ (Odd m ↔ Odd n) := by 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) := diff --git a/Mathlib/Algebra/Ring/Semiconj.lean b/Mathlib/Algebra/Ring/Semiconj.lean index 8b20e68a71a06..0ec9636ddebc6 100644 --- a/Mathlib/Algebra/Ring/Semiconj.lean +++ b/Mathlib/Algebra/Ring/Semiconj.lean @@ -61,13 +61,9 @@ section variable [MulOneClass R] [HasDistribNeg R] --- Porting note: `simpNF` told me to remove `simp` attribute -theorem neg_one_right (a : R) : SemiconjBy a (-1) (-1) := - (one_right a).neg_right +theorem neg_one_right (a : R) : SemiconjBy a (-1) (-1) := by simp --- Porting note: `simpNF` told me to remove `simp` attribute -theorem neg_one_left (x : R) : SemiconjBy (-1) x x := - (SemiconjBy.one_left x).neg_left +theorem neg_one_left (x : R) : SemiconjBy (-1) x x := by simp end diff --git a/Mathlib/Algebra/Star/Subsemiring.lean b/Mathlib/Algebra/Star/Subsemiring.lean index 8ef2bdd8fdd39..707ac11a068a8 100644 --- a/Mathlib/Algebra/Star/Subsemiring.lean +++ b/Mathlib/Algebra/Star/Subsemiring.lean @@ -53,7 +53,6 @@ instance starRing (s : StarSubsemiring R) : StarRing s := instance semiring (s : StarSubsemiring R) : NonAssocSemiring s := s.toSubsemiring.toNonAssocSemiring -@[simp, nolint simpNF] theorem mem_carrier {s : StarSubsemiring R} {x : R} : x ∈ s.carrier ↔ x ∈ s := Iff.rfl diff --git a/Mathlib/Algebra/Symmetrized.lean b/Mathlib/Algebra/Symmetrized.lean index 00c398aaf91dd..45a69d0768566 100644 --- a/Mathlib/Algebra/Symmetrized.lean +++ b/Mathlib/Algebra/Symmetrized.lean @@ -48,7 +48,7 @@ def sym : α ≃ αˢʸᵐ := /-- The element of `α` represented by `x : αˢʸᵐ`. -/ -- Porting note (kmill): `pp_nodot` has no affect here --- unless RFC https://github.com/leanprover/lean4/issues/1910 leads to dot notation for CoeFun +-- unless RFC https://github.com/leanprover/lean4/issues/6178 leads to dot notation pp for CoeFun @[pp_nodot] def unsym : αˢʸᵐ ≃ α := Equiv.refl _ diff --git a/Mathlib/Algebra/TrivSqZeroExt.lean b/Mathlib/Algebra/TrivSqZeroExt.lean index c40ab975c18d7..cc4239ab85e25 100644 --- a/Mathlib/Algebra/TrivSqZeroExt.lean +++ b/Mathlib/Algebra/TrivSqZeroExt.lean @@ -870,10 +870,9 @@ section Algebra variable (S : Type*) (R R' : Type u) (M : Type v) variable [CommSemiring S] [Semiring R] [CommSemiring R'] [AddCommMonoid M] -variable [Algebra S R] [Algebra S R'] [Module S M] -variable [Module R M] [Module Rᵐᵒᵖ M] [SMulCommClass R Rᵐᵒᵖ M] +variable [Algebra S R] [Module S M] [Module R M] [Module Rᵐᵒᵖ M] [SMulCommClass R Rᵐᵒᵖ M] variable [IsScalarTower S R M] [IsScalarTower S Rᵐᵒᵖ M] -variable [Module R' M] [Module R'ᵐᵒᵖ M] [IsCentralScalar R' M] [IsScalarTower S R' M] +variable [Module R' M] [Module R'ᵐᵒᵖ M] [IsCentralScalar R' M] instance algebra' : Algebra S (tsze R M) := { (TrivSqZeroExt.inlHom R M).comp (algebraMap S R) with diff --git a/Mathlib/AlgebraicGeometry/AffineScheme.lean b/Mathlib/AlgebraicGeometry/AffineScheme.lean index a83addf8247e5..96002facc9d47 100644 --- a/Mathlib/AlgebraicGeometry/AffineScheme.lean +++ b/Mathlib/AlgebraicGeometry/AffineScheme.lean @@ -67,12 +67,12 @@ def Scheme.isoSpec (X : Scheme) [IsAffine X] : X ≅ Spec Γ(X, ⊤) := @[reassoc] theorem Scheme.isoSpec_hom_naturality {X Y : Scheme} [IsAffine X] [IsAffine Y] (f : X ⟶ Y) : - X.isoSpec.hom ≫ Spec.map (f.app ⊤) = f ≫ Y.isoSpec.hom := by + X.isoSpec.hom ≫ Spec.map (f.appTop) = f ≫ Y.isoSpec.hom := by simp only [isoSpec, asIso_hom, Scheme.toSpecΓ_naturality] @[reassoc] theorem Scheme.isoSpec_inv_naturality {X Y : Scheme} [IsAffine X] [IsAffine Y] (f : X ⟶ Y) : - Spec.map (f.app ⊤) ≫ Y.isoSpec.inv = X.isoSpec.inv ≫ f := by + Spec.map (f.appTop) ≫ Y.isoSpec.inv = X.isoSpec.inv ≫ f := by rw [Iso.eq_inv_comp, isoSpec, asIso_hom, ← Scheme.toSpecΓ_naturality_assoc, isoSpec, asIso_inv, IsIso.hom_inv_id, Category.comp_id] @@ -112,13 +112,13 @@ theorem isAffine_of_isIso {X Y : Scheme} (f : X ⟶ Y) [IsIso f] [h : IsAffine Y to the arrow of the morphism on prime spectra induced by the map on global sections. -/ noncomputable def arrowIsoSpecΓOfIsAffine {X Y : Scheme} [IsAffine X] [IsAffine Y] (f : X ⟶ Y) : - Arrow.mk f ≅ Arrow.mk (Spec.map (Scheme.Γ.map f.op)) := + Arrow.mk f ≅ Arrow.mk (Spec.map f.appTop) := Arrow.isoMk X.isoSpec Y.isoSpec (ΓSpec.adjunction.unit_naturality _) /-- If `f : A ⟶ B` is a ring homomorphism, the corresponding arrow is isomorphic to the arrow of the morphism induced on global sections by the map on prime spectra. -/ def arrowIsoΓSpecOfIsAffine {A B : CommRingCat} (f : A ⟶ B) : - Arrow.mk f ≅ Arrow.mk ((Spec.map f).app ⊤) := + Arrow.mk f ≅ Arrow.mk ((Spec.map f).appTop) := Arrow.isoMk (Scheme.ΓSpecIso _).symm (Scheme.ΓSpecIso _).symm (Scheme.ΓSpecIso_inv_naturality f).symm @@ -134,7 +134,7 @@ theorem Scheme.isoSpec_Spec (R : CommRingCat.{u}) : (Spec R).isoSpec.inv = Spec.map (Scheme.ΓSpecIso R).inv := congr($(isoSpec_Spec R).inv) -lemma ext_of_isAffine {X Y : Scheme} [IsAffine Y] {f g : X ⟶ Y} (e : f.app ⊤ = g.app ⊤) : +lemma ext_of_isAffine {X Y : Scheme} [IsAffine Y] {f g : X ⟶ Y} (e : f.appTop = g.appTop) : f = g := by rw [← cancel_mono Y.toSpecΓ, Scheme.toSpecΓ_naturality, Scheme.toSpecΓ_naturality, e] @@ -315,21 +315,24 @@ lemma isoSpec_hom_base_apply (x : U) : congr 1 exact IsLocalRing.comap_closedPoint (U.stalkIso x).inv -lemma isoSpec_inv_app_top : - hU.isoSpec.inv.app ⊤ = U.topIso.hom ≫ (Scheme.ΓSpecIso Γ(X, U)).inv := by +lemma isoSpec_inv_appTop : + hU.isoSpec.inv.appTop = U.topIso.hom ≫ (Scheme.ΓSpecIso Γ(X, U)).inv := by simp only [Scheme.Opens.toScheme_presheaf_obj, isoSpec_inv, Scheme.isoSpec, asIso_inv, - Scheme.comp_coeBase, Opens.map_comp_obj, Opens.map_top, Scheme.comp_app, Scheme.inv_app_top, + Scheme.comp_coeBase, Opens.map_comp_obj, Opens.map_top, Scheme.comp_app, Scheme.inv_appTop, Scheme.Opens.topIso_hom, Scheme.ΓSpecIso_inv_naturality, IsIso.inv_comp_eq] - rw [Scheme.toSpecΓ_app_top] + rw [Scheme.toSpecΓ_appTop] erw [Iso.hom_inv_id_assoc] -lemma isoSpec_hom_app_top : - hU.isoSpec.hom.app ⊤ = (Scheme.ΓSpecIso Γ(X, U)).hom ≫ U.topIso.inv := by - have := congr(inv $hU.isoSpec_inv_app_top) +lemma isoSpec_hom_appTop : + hU.isoSpec.hom.appTop = (Scheme.ΓSpecIso Γ(X, U)).hom ≫ U.topIso.inv := by + have := congr(inv $hU.isoSpec_inv_appTop) rw [IsIso.inv_comp, IsIso.Iso.inv_inv, IsIso.Iso.inv_hom] at this have := (Scheme.Γ.map_inv hU.isoSpec.inv.op).trans this rwa [← op_inv, IsIso.Iso.inv_inv] at this +@[deprecated (since := "2024-11-16")] alias isoSpec_inv_app_top := isoSpec_inv_appTop +@[deprecated (since := "2024-11-16")] alias isoSpec_hom_app_top := isoSpec_hom_appTop + /-- The open immersion `Spec Γ(X, U) ⟶ X` for an affine `U`. -/ def fromSpec : Spec Γ(X, U) ⟶ X := @@ -364,7 +367,7 @@ theorem map_fromSpec {V : X.Opens} (hV : IsAffineOpen V) (f : op U ⟶ op V) : conv_rhs => rw [fromSpec, ← X.homOfLE_ι (V := U) f.unop.le, isoSpec_inv, Category.assoc, ← Scheme.isoSpec_inv_naturality_assoc, - ← Spec.map_comp_assoc, Scheme.homOfLE_app, ← Functor.map_comp] + ← Spec.map_comp_assoc, Scheme.homOfLE_appTop, ← Functor.map_comp] rw [fromSpec, isoSpec_inv, Category.assoc, ← Spec.map_comp_assoc, ← Functor.map_comp] rfl @@ -377,21 +380,22 @@ lemma Spec_map_appLE_fromSpec (f : X ⟶ Y) {V : X.Opens} {U : Y.Opens} simp_rw [← Scheme.homOfLE_ι _ i] rw [Category.assoc, ← morphismRestrict_ι, ← Category.assoc _ (f ∣_ U) U.ι, ← @Scheme.isoSpec_inv_naturality_assoc, - ← Spec.map_comp_assoc, ← Spec.map_comp_assoc, Scheme.comp_app, morphismRestrict_app, - Scheme.homOfLE_app, Scheme.Hom.app_eq_appLE, Scheme.Hom.appLE_map, + ← Spec.map_comp_assoc, ← Spec.map_comp_assoc, Scheme.comp_appTop, morphismRestrict_appTop, + Scheme.homOfLE_appTop, Scheme.Hom.app_eq_appLE, Scheme.Hom.appLE_map, Scheme.Hom.appLE_map, Scheme.Hom.appLE_map, Scheme.Hom.map_appLE] lemma fromSpec_top [IsAffine X] : (isAffineOpen_top X).fromSpec = X.isoSpec.inv := by - rw [fromSpec, isoSpec_inv, Category.assoc, ← @Scheme.isoSpec_inv_naturality, Scheme.Opens.ι_app, - ← Spec.map_comp_assoc, ← X.presheaf.map_comp, ← op_comp, eqToHom_comp_homOfLE, - ← eqToHom_eq_homOfLE rfl, eqToHom_refl, op_id, X.presheaf.map_id, Spec.map_id, Category.id_comp] + rw [fromSpec, isoSpec_inv, Category.assoc, ← @Scheme.isoSpec_inv_naturality, + ← Spec.map_comp_assoc, Scheme.Opens.ι_appTop, ← X.presheaf.map_comp, ← op_comp, + eqToHom_comp_homOfLE, ← eqToHom_eq_homOfLE rfl, eqToHom_refl, op_id, X.presheaf.map_id, + Spec.map_id, Category.id_comp] lemma fromSpec_app_of_le (V : X.Opens) (h : U ≤ V) : hU.fromSpec.app V = X.presheaf.map (homOfLE h).op ≫ (Scheme.ΓSpecIso Γ(X, U)).inv ≫ (Spec _).presheaf.map (homOfLE le_top).op := by have : U.ι ⁻¹ᵁ V = ⊤ := eq_top_iff.mpr fun x _ ↦ h x.2 rw [IsAffineOpen.fromSpec, Scheme.comp_app, Scheme.Opens.ι_app, Scheme.app_eq _ this, - IsAffineOpen.isoSpec_inv_app_top] + ← Scheme.Hom.appTop, IsAffineOpen.isoSpec_inv_appTop] simp only [Scheme.Opens.toScheme_presheaf_map, Scheme.Opens.topIso_hom, Category.assoc, ← X.presheaf.map_comp_assoc] rfl @@ -470,7 +474,7 @@ theorem ΓSpecIso_hom_fromSpec_app : simp only [fromSpec, Scheme.comp_coeBase, Opens.map_comp_obj, Scheme.comp_app, Scheme.Opens.ι_app_self, eqToHom_op, Scheme.app_eq _ U.ι_preimage_self, Scheme.Opens.toScheme_presheaf_map, eqToHom_unop, eqToHom_map U.ι.opensFunctor, Opens.map_top, - isoSpec_inv_app_top, Scheme.Opens.topIso_hom, Category.assoc, ← Functor.map_comp_assoc, + isoSpec_inv_appTop, Scheme.Opens.topIso_hom, Category.assoc, ← Functor.map_comp_assoc, eqToHom_trans, eqToHom_refl, X.presheaf.map_id, Category.id_comp, Iso.hom_inv_id_assoc] @[elementwise] @@ -953,10 +957,10 @@ lemma specTargetImageRingHom_surjective : Function.Surjective (specTargetImageRi Ideal.Quotient.mk_surjective lemma specTargetImageFactorization_app_injective : - Function.Injective <| (specTargetImageFactorization f).app ⊤ := by + Function.Injective <| (specTargetImageFactorization f).appTop := by let φ : A ⟶ Γ(X, ⊤) := (((ΓSpec.adjunction).homEquiv X (op A)).symm f).unop let φ' : specTargetImage f ⟶ Scheme.Γ.obj (op X) := RingHom.kerLift φ - show Function.Injective <| ((ΓSpec.adjunction.homEquiv X _) φ'.op).app ⊤ + show Function.Injective <| ((ΓSpec.adjunction.homEquiv X _) φ'.op).appTop rw [ΓSpec_adjunction_homEquiv_eq] apply (RingHom.kerLift_injective φ).comp exact ((ConcreteCategory.isIso_iff_bijective (Scheme.ΓSpecIso _).hom).mp inferInstance).injective @@ -993,7 +997,7 @@ def affineTargetImageInclusion (f : X ⟶ Y) : affineTargetImage f ⟶ Y := Spec.map (specTargetImageRingHom (f ≫ Y.isoSpec.hom)) ≫ Y.isoSpec.inv lemma affineTargetImageInclusion_app_surjective : - Function.Surjective <| (affineTargetImageInclusion f).app ⊤ := by + Function.Surjective <| (affineTargetImageInclusion f).appTop := by simp only [Scheme.comp_coeBase, Opens.map_comp_obj, Opens.map_top, Scheme.comp_app, CommRingCat.coe_comp, affineTargetImageInclusion] apply Function.Surjective.comp @@ -1013,7 +1017,7 @@ def affineTargetImageFactorization (f : X ⟶ Y) : X ⟶ affineTargetImage f := specTargetImageFactorization (f ≫ Y.isoSpec.hom) lemma affineTargetImageFactorization_app_injective : - Function.Injective <| (affineTargetImageFactorization f).app ⊤ := + Function.Injective <| (affineTargetImageFactorization f).appTop := specTargetImageFactorization_app_injective (f ≫ Y.isoSpec.hom) @[reassoc (attr := simp)] diff --git a/Mathlib/AlgebraicGeometry/AffineSpace.lean b/Mathlib/AlgebraicGeometry/AffineSpace.lean index 6374a6564ad9f..805e43c4928d2 100644 --- a/Mathlib/AlgebraicGeometry/AffineSpace.lean +++ b/Mathlib/AlgebraicGeometry/AffineSpace.lean @@ -71,7 +71,7 @@ Use `homOverEquiv` instead. -/ @[simps] def toSpecMvPolyIntEquiv : (X ⟶ Spec ℤ[n]) ≃ (n → Γ(X, ⊤)) where - toFun f i := f.app ⊤ ((Scheme.ΓSpecIso ℤ[n]).inv (.X i)) + toFun f i := f.appTop ((Scheme.ΓSpecIso ℤ[n]).inv (.X i)) invFun v := X.toSpecΓ ≫ Spec.map (MvPolynomial.eval₂Hom ((algebraMap ℤ _).comp ULift.ringEquiv.toRingHom) v) left_inv f := by @@ -80,7 +80,7 @@ def toSpecMvPolyIntEquiv : (X ⟶ Spec ℤ[n]) ≃ (n → Γ(X, ⊤)) where rw [Adjunction.homEquiv_symm_apply, Adjunction.homEquiv_symm_apply] simp only [Functor.rightOp_obj, Scheme.Γ_obj, Scheme.Spec_obj, algebraMap_int_eq, RingEquiv.toRingHom_eq_coe, TopologicalSpace.Opens.map_top, Functor.rightOp_map, op_comp, - Scheme.Γ_map, unop_comp, Quiver.Hom.unop_op, Scheme.comp_app, Scheme.toSpecΓ_app_top, + Scheme.Γ_map, unop_comp, Quiver.Hom.unop_op, Scheme.comp_app, Scheme.toSpecΓ_appTop, Scheme.ΓSpecIso_naturality, ΓSpec.adjunction_counit_app, Category.assoc, Iso.cancel_iso_inv_left, ← Iso.eq_inv_comp] apply of_mvPolynomial_int_ext @@ -91,13 +91,13 @@ def toSpecMvPolyIntEquiv : (X ⟶ Spec ℤ[n]) ≃ (n → Γ(X, ⊤)) where ext i simp only [algebraMap_int_eq, RingEquiv.toRingHom_eq_coe, Scheme.comp_coeBase, TopologicalSpace.Opens.map_comp_obj, TopologicalSpace.Opens.map_top, Scheme.comp_app, - Scheme.toSpecΓ_app_top, Scheme.ΓSpecIso_naturality, CommRingCat.comp_apply, + Scheme.toSpecΓ_appTop, Scheme.ΓSpecIso_naturality, CommRingCat.comp_apply, CommRingCat.coe_of] erw [Iso.hom_inv_id_apply] rw [coe_eval₂Hom, eval₂_X] lemma toSpecMvPolyIntEquiv_comp {X Y : Scheme} (f : X ⟶ Y) (g : Y ⟶ Spec ℤ[n]) (i) : - toSpecMvPolyIntEquiv n (f ≫ g) i = f.app ⊤ (toSpecMvPolyIntEquiv n g i) := rfl + toSpecMvPolyIntEquiv n (f ≫ g) i = f.appTop (toSpecMvPolyIntEquiv n g i) := rfl variable {n} in /-- The standard coordinates of `𝔸(n; S)`. -/ @@ -122,16 +122,16 @@ lemma homOfVector_toSpecMvPoly : homOfVector f v ≫ toSpecMvPoly n S = (toSpecMvPolyIntEquiv n).symm v := pullback.lift_snd _ _ _ -@[local simp] -lemma homOfVector_app_top_coord (i) : - (homOfVector f v).app ⊤ (coord S i) = v i := by +@[simp] +lemma homOfVector_appTop_coord (i) : + (homOfVector f v).appTop (coord S i) = v i := by rw [coord, ← toSpecMvPolyIntEquiv_comp, homOfVector_toSpecMvPoly, Equiv.apply_symm_apply] @[ext 1100] lemma hom_ext {f g : X ⟶ 𝔸(n; S)} (h₁ : f ≫ 𝔸(n; S) ↘ S = g ≫ 𝔸(n; S) ↘ S) - (h₂ : ∀ i, f.app ⊤ (coord S i) = g.app ⊤ (coord S i)) : f = g := by + (h₂ : ∀ i, f.appTop (coord S i) = g.appTop (coord S i)) : f = g := by apply pullback.hom_ext h₁ show f ≫ toSpecMvPoly _ _ = g ≫ toSpecMvPoly _ _ apply (toSpecMvPolyIntEquiv n).injective @@ -141,8 +141,8 @@ lemma hom_ext {f g : X ⟶ 𝔸(n; S)} @[reassoc] lemma comp_homOfVector {X Y : Scheme} (v : n → Γ(Y, ⊤)) (f : X ⟶ Y) (g : Y ⟶ S) : - f ≫ homOfVector g v = homOfVector (f ≫ g) (f.app ⊤ ∘ v) := by - ext1 <;> simp [-TopologicalSpace.Opens.map_top]; rfl + f ≫ homOfVector g v = homOfVector (f ≫ g) (f.appTop ∘ v) := by + ext1 <;> simp end homOfVector @@ -155,13 +155,13 @@ instance (v : n → Γ(X, ⊤)) : (homOfVector (X ↘ S) v).IsOver S where /-- `S`-morphisms into `Spec 𝔸(n; S)` are equivalent to the choice of `n` global sections. -/ @[simps] def homOverEquiv : { f : X ⟶ 𝔸(n; S) // f.IsOver S } ≃ (n → Γ(X, ⊤)) where - toFun f i := f.1.app ⊤ (coord S i) + toFun f i := f.1.appTop (coord S i) invFun v := ⟨homOfVector (X ↘ S) v, inferInstance⟩ left_inv f := by ext : 2 · simp [f.2.1] - · rw [homOfVector_app_top_coord] - right_inv v := by ext i; simp [-TopologicalSpace.Opens.map_top, homOfVector_app_top_coord] + · rw [homOfVector_appTop_coord] + right_inv v := by ext i; simp [-TopologicalSpace.Opens.map_top, homOfVector_appTop_coord] variable (n) in /-- @@ -171,7 +171,7 @@ Also see `AffineSpace.SpecIso`. @[simps (config := .lemmasOnly) hom inv] def isoOfIsAffine [IsAffine S] : 𝔸(n; S) ≅ Spec (.of (MvPolynomial n Γ(S, ⊤))) where - hom := 𝔸(n; S).toSpecΓ ≫ Spec.map (eval₂Hom ((𝔸(n; S) ↘ S).app ⊤) (coord S)) + hom := 𝔸(n; S).toSpecΓ ≫ Spec.map (eval₂Hom ((𝔸(n; S) ↘ S).appTop) (coord S)) inv := homOfVector (Spec.map C ≫ S.isoSpec.inv) ((Scheme.ΓSpecIso (.of (MvPolynomial n Γ(S, ⊤)))).inv ∘ MvPolynomial.X) hom_inv_id := by @@ -180,48 +180,43 @@ def isoOfIsAffine [IsAffine S] : rw [← Spec.map_comp_assoc, CommRingCat.comp_eq_ring_hom_comp, eval₂Hom_comp_C, ← Scheme.toSpecΓ_naturality_assoc] simp [Scheme.isoSpec] - · simp only [Scheme.comp_coeBase, TopologicalSpace.Opens.map_comp_obj, Scheme.comp_app, - CommRingCat.coe_comp_of, RingHom.coe_comp, Function.comp_apply, Scheme.id.base, - Scheme.id_app] - -- note: `rw [homOfVector_app_top_coord]` works but takes 3 more seconds - conv => enter [1, 2, 2]; rw [homOfVector_app_top_coord] - simp only [TopologicalSpace.Opens.map_top, Scheme.toSpecΓ_app_top, Function.comp_apply, + · simp only [Category.assoc, Scheme.comp_app, Scheme.comp_coeBase, + TopologicalSpace.Opens.map_comp_obj, TopologicalSpace.Opens.map_top, + Scheme.toSpecΓ_appTop, Scheme.ΓSpecIso_naturality, CommRingCat.comp_apply, + homOfVector_appTop_coord, Function.comp_apply, CommRingCat.coe_of, Scheme.id_app, CommRingCat.id_apply] - erw [elementwise_of% Scheme.ΓSpecIso_naturality, Iso.hom_inv_id_apply] + erw [Iso.hom_inv_id_apply] exact eval₂_X _ _ _ inv_hom_id := by apply ext_of_isAffine simp only [Scheme.comp_coeBase, TopologicalSpace.Opens.map_comp_obj, - TopologicalSpace.Opens.map_top, Scheme.comp_app, Scheme.toSpecΓ_app_top, + TopologicalSpace.Opens.map_top, Scheme.comp_app, Scheme.toSpecΓ_appTop, Scheme.ΓSpecIso_naturality, Category.assoc, Scheme.id_app, ← Iso.eq_inv_comp, Category.comp_id] apply ringHom_ext' · show _ = CommRingCat.ofHom C ≫ _ rw [CommRingCat.comp_eq_ring_hom_comp, RingHom.comp_assoc, eval₂Hom_comp_C, ← CommRingCat.comp_eq_ring_hom_comp, ← cancel_mono (Scheme.ΓSpecIso _).hom] - erw [← Scheme.comp_app] - rw [homOfVector_over, Scheme.comp_app] - simp only [TopologicalSpace.Opens.map_top, Category.assoc, Scheme.ΓSpecIso_naturality, ← - Scheme.toSpecΓ_app_top] - erw [← Scheme.comp_app_assoc] - rw [Scheme.isoSpec, asIso_inv, IsIso.hom_inv_id] + rw [← Scheme.comp_appTop, homOfVector_over, Scheme.comp_appTop] + simp only [Category.assoc, Scheme.ΓSpecIso_naturality, ← Scheme.toSpecΓ_appTop] + rw [← Scheme.comp_appTop_assoc, Scheme.isoSpec, asIso_inv, IsIso.hom_inv_id] simp rfl · intro i erw [CommRingCat.comp_apply, coe_eval₂Hom] simp only [eval₂_X] - exact homOfVector_app_top_coord _ _ _ + exact homOfVector_appTop_coord _ _ _ @[simp] -lemma isoOfIsAffine_hom_app_top [IsAffine S] : - (isoOfIsAffine n S).hom.app ⊤ = - (Scheme.ΓSpecIso _).hom ≫ eval₂Hom ((𝔸(n; S) ↘ S).app ⊤) (coord S) := by +lemma isoOfIsAffine_hom_appTop [IsAffine S] : + (isoOfIsAffine n S).hom.appTop = + (Scheme.ΓSpecIso _).hom ≫ eval₂Hom ((𝔸(n; S) ↘ S).appTop) (coord S) := by simp [isoOfIsAffine_hom] -@[local simp] -lemma isoOfIsAffine_inv_app_top_coord [IsAffine S] (i) : - (isoOfIsAffine n S).inv.app ⊤ (coord _ i) = (Scheme.ΓSpecIso (.of _)).inv (.X i) := - homOfVector_app_top_coord _ _ _ +@[simp] +lemma isoOfIsAffine_inv_appTop_coord [IsAffine S] (i) : + (isoOfIsAffine n S).inv.appTop (coord _ i) = (Scheme.ΓSpecIso (.of _)).inv (.X i) := + homOfVector_appTop_coord _ _ _ @[reassoc (attr := simp)] lemma isoOfIsAffine_inv_over [IsAffine S] : @@ -238,27 +233,27 @@ def SpecIso (R : CommRingCat.{max u v}) : (Scheme.ΓSpecIso R).symm.commRingCatIsoToRingEquiv).toCommRingCatIso.op @[simp] -lemma SpecIso_hom_app_top (R : CommRingCat.{max u v}) : - (SpecIso n R).hom.app ⊤ = (Scheme.ΓSpecIso _).hom ≫ - eval₂Hom ((Scheme.ΓSpecIso _).inv ≫ (𝔸(n; Spec R) ↘ Spec R).app ⊤) (coord (Spec R)) := by +lemma SpecIso_hom_appTop (R : CommRingCat.{max u v}) : + (SpecIso n R).hom.appTop = (Scheme.ΓSpecIso _).hom ≫ + eval₂Hom ((Scheme.ΓSpecIso _).inv ≫ (𝔸(n; Spec R) ↘ Spec R).appTop) (coord (Spec R)) := by simp only [SpecIso, Iso.trans_hom, Functor.mapIso_hom, Iso.op_hom, RingEquiv.toCommRingCatIso_hom, RingEquiv.toRingHom_eq_coe, Scheme.Spec_map, Quiver.Hom.unop_op, Scheme.comp_coeBase, TopologicalSpace.Opens.map_comp_obj, TopologicalSpace.Opens.map_top, Scheme.comp_app, - isoOfIsAffine_hom_app_top] + isoOfIsAffine_hom_appTop] erw [Scheme.ΓSpecIso_naturality_assoc] congr 1 apply ringHom_ext' - · ext; simp; rfl + · ext; simp · simp -@[local simp] -lemma SpecIso_inv_app_top_coord (R : CommRingCat.{max u v}) (i) : - (SpecIso n R).inv.app ⊤ (coord _ i) = (Scheme.ΓSpecIso (.of _)).inv (.X i) := by +@[simp] +lemma SpecIso_inv_appTop_coord (R : CommRingCat.{max u v}) (i) : + (SpecIso n R).inv.appTop (coord _ i) = (Scheme.ΓSpecIso (.of _)).inv (.X i) := by simp only [SpecIso, Iso.trans_inv, Functor.mapIso_inv, Iso.op_inv, RingEquiv.toCommRingCatIso_inv, mapEquiv_symm, RingEquiv.toRingHom_eq_coe, Scheme.Spec_map, Quiver.Hom.unop_op, Scheme.comp_coeBase, TopologicalSpace.Opens.map_comp_obj, TopologicalSpace.Opens.map_top, Scheme.comp_app, CommRingCat.comp_apply] - erw [isoOfIsAffine_inv_app_top_coord, ← CommRingCat.comp_apply] + erw [isoOfIsAffine_inv_appTop_coord, ← CommRingCat.comp_apply] rw [← Scheme.ΓSpecIso_inv_naturality] erw [CommRingCat.comp_apply] congr 1 @@ -286,14 +281,14 @@ def map {S T : Scheme.{max u v}} (f : S ⟶ T) : 𝔸(n; S) ⟶ 𝔸(n; T) := lemma map_over {S T : Scheme.{max u v}} (f : S ⟶ T) : map n f ≫ 𝔸(n; T) ↘ T = 𝔸(n; S) ↘ S ≫ f := pullback.lift_fst _ _ _ -@[local simp] -lemma map_app_top_coord {S T : Scheme.{max u v}} (f : S ⟶ T) (i) : - (map n f).app ⊤ (coord T i) = coord S i := - homOfVector_app_top_coord _ _ _ +@[simp] +lemma map_appTop_coord {S T : Scheme.{max u v}} (f : S ⟶ T) (i) : + (map n f).appTop (coord T i) = coord S i := + homOfVector_appTop_coord _ _ _ @[simp] lemma map_id : map n (𝟙 S) = 𝟙 𝔸(n; S) := by - ext1 <;> simp [-TopologicalSpace.Opens.map_top]; rfl + ext1 <;> simp @[reassoc, simp] lemma map_comp {S S' S'' : Scheme} (f : S ⟶ S') (g : S' ⟶ S'') : @@ -302,7 +297,7 @@ lemma map_comp {S S' S'' : Scheme} (f : S ⟶ S') (g : S' ⟶ S'') : · simp · simp only [TopologicalSpace.Opens.map_top, Scheme.comp_coeBase, TopologicalSpace.Opens.map_comp_obj, Scheme.comp_app, CommRingCat.comp_apply] - erw [map_app_top_coord, map_app_top_coord, map_app_top_coord] + erw [map_appTop_coord, map_appTop_coord, map_appTop_coord] lemma map_Spec_map {R S : CommRingCat.{max u v}} (φ : R ⟶ S) : map n (Spec.map φ) = @@ -314,9 +309,9 @@ lemma map_Spec_map {R S : CommRingCat.{max u v}} (φ : R ⟶ S) : rw [map_comp_C] · simp only [Scheme.comp_coeBase, TopologicalSpace.Opens.map_comp_obj, TopologicalSpace.Opens.map_top, Scheme.comp_app, CommRingCat.comp_apply] - conv_lhs => enter[2]; tactic => exact map_app_top_coord _ _ - conv_rhs => enter[2]; tactic => exact SpecIso_inv_app_top_coord _ _ - erw [SpecIso_inv_app_top_coord, ← CommRingCat.comp_apply] + conv_lhs => enter[2]; tactic => exact map_appTop_coord _ _ + conv_rhs => enter[2]; tactic => exact SpecIso_inv_appTop_coord _ _ + erw [SpecIso_inv_appTop_coord, ← CommRingCat.comp_apply] rw [← Scheme.ΓSpecIso_inv_naturality] erw [CommRingCat.comp_apply, map_X] rfl @@ -332,44 +327,34 @@ def mapSpecMap {R S : CommRingCat.{max u v}} (φ : R ⟶ S) : def reindex {n m : Type v} (i : m → n) (S : Scheme.{max u v}) : 𝔸(n; S) ⟶ 𝔸(m; S) := homOfVector (𝔸(n; S) ↘ S) (coord S ∘ i) -@[reassoc (attr := simp)] +@[simp, reassoc] lemma reindex_over {n m : Type v} (i : m → n) (S : Scheme.{max u v}) : reindex i S ≫ 𝔸(m; S) ↘ S = 𝔸(n; S) ↘ S := pullback.lift_fst _ _ _ -@[local simp] -lemma reindex_app_top_coord {n m : Type v} (i : m → n) (S : Scheme.{max u v}) (j : m) : - (reindex i S).app ⊤ (coord S j) = coord S (i j) := - homOfVector_app_top_coord _ _ _ +@[simp] +lemma reindex_appTop_coord {n m : Type v} (i : m → n) (S : Scheme.{max u v}) (j : m) : + (reindex i S).appTop (coord S j) = coord S (i j) := + homOfVector_appTop_coord _ _ _ @[simp] lemma reindex_id : reindex id S = 𝟙 𝔸(n; S) := by - ext1 <;> simp [-TopologicalSpace.Opens.map_top]; rfl + ext1 <;> simp +@[simp, reassoc] lemma reindex_comp {n₁ n₂ n₃ : Type v} (i : n₁ → n₂) (j : n₂ → n₃) (S : Scheme.{max u v}) : reindex (j ∘ i) S = reindex j S ≫ reindex i S := by have H₁ : reindex (j ∘ i) S ≫ 𝔸(n₁; S) ↘ S = (reindex j S ≫ reindex i S) ≫ 𝔸(n₁; S) ↘ S := by simp - have H₂ (k) : (reindex (j ∘ i) S).app ⊤ (coord S k) = - (reindex j S).app ⊤ ((reindex i S).app ⊤ (coord S k)) := by - rw [reindex_app_top_coord, reindex_app_top_coord, reindex_app_top_coord] + have H₂ (k) : (reindex (j ∘ i) S).appTop (coord S k) = + (reindex j S).appTop ((reindex i S).appTop (coord S k)) := by + rw [reindex_appTop_coord, reindex_appTop_coord, reindex_appTop_coord] rfl exact hom_ext H₁ H₂ --- These time out if added to `reindex_comp` directly. -attribute [reassoc] reindex_comp -attribute [simp] reindex_comp - +@[reassoc (attr := simp)] lemma map_reindex {n₁ n₂ : Type v} (i : n₁ → n₂) {S T : Scheme.{max u v}} (f : S ⟶ T) : map n₂ f ≫ reindex i T = reindex i S ≫ map n₁ f := by - apply hom_ext - · simp - · intro j - simp only [Scheme.comp_coeBase, TopologicalSpace.Opens.map_comp_obj, Scheme.comp_app, - CommRingCat.comp_apply, map_app_top_coord, reindex_app_top_coord] - simp only [TopologicalSpace.Opens.map_top] - erw [map_app_top_coord f (i j), reindex_app_top_coord i S] - -attribute [reassoc (attr := simp)] map_reindex + apply hom_ext <;> simp /-- The affine space as a functor. -/ @[simps] diff --git a/Mathlib/AlgebraicGeometry/Cover/MorphismProperty.lean b/Mathlib/AlgebraicGeometry/Cover/MorphismProperty.lean index e2226dd86717f..53a9c4dfd2092 100644 --- a/Mathlib/AlgebraicGeometry/Cover/MorphismProperty.lean +++ b/Mathlib/AlgebraicGeometry/Cover/MorphismProperty.lean @@ -73,6 +73,9 @@ theorem Cover.iUnion_range {X : Scheme.{u}} (𝒰 : X.Cover P) : rw [Set.mem_iUnion] exact ⟨𝒰.f x, 𝒰.covers x⟩ +lemma Cover.exists_eq (𝒰 : X.Cover P) (x : X) : ∃ i y, (𝒰.map i).base y = x := + ⟨_, 𝒰.covers x⟩ + /-- Given a family of schemes with morphisms to `X` satisfying `P` that jointly cover `X`, this an associated `P`-cover of `X`. -/ @[simps] diff --git a/Mathlib/AlgebraicGeometry/Cover/Over.lean b/Mathlib/AlgebraicGeometry/Cover/Over.lean new file mode 100644 index 0000000000000..e6b2a8b4e0e23 --- /dev/null +++ b/Mathlib/AlgebraicGeometry/Cover/Over.lean @@ -0,0 +1,183 @@ +/- +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.UnderlyingMap +import Mathlib.CategoryTheory.Limits.MorphismProperty + +/-! + +# Covers of schemes over a base + +In this file we define the typeclass `Cover.Over`. For a cover `𝒰` of an `S`-scheme `X`, +the datum `𝒰.Over S` contains `S`-scheme structures on the components of `𝒰` and asserts +that the component maps are morphisms of `S`-schemes. + +We provide instances of `𝒰.Over S` for standard constructions on covers. + +-/ + +universe v u + +noncomputable section + +open CategoryTheory Limits + +namespace AlgebraicGeometry.Scheme + +variable {P : MorphismProperty Scheme.{u}} (S : Scheme.{u}) + +/-- Bundle an `S`-scheme with `P` into an object of `P.Over ⊤ S`. -/ +abbrev asOverProp (X : Scheme.{u}) (S : Scheme.{u}) [X.Over S] (h : P (X ↘ S)) : P.Over ⊤ S := + ⟨X.asOver S, h⟩ + +/-- Bundle an `S`-morphism of `S`-scheme with `P` into a morphism in `P.Over ⊤ S`. -/ +abbrev Hom.asOverProp {X Y : Scheme.{u}} (f : X.Hom Y) (S : Scheme.{u}) [X.Over S] [Y.Over S] + [f.IsOver S] {hX : P (X ↘ S)} {hY : P (Y ↘ S)} : X.asOverProp S hX ⟶ Y.asOverProp S hY := + ⟨f.asOver S, trivial, trivial⟩ + +/-- A `P`-cover of a scheme `X` over `S` is a cover, where the components are over `S` and the +component maps commute with the structure morphisms. -/ +protected class Cover.Over {P : MorphismProperty Scheme.{u}} {X : Scheme.{u}} [X.Over S] + (𝒰 : X.Cover P) where + over (j : 𝒰.J) : (𝒰.obj j).Over S := by infer_instance + isOver_map (j : 𝒰.J) : (𝒰.map j).IsOver S := by infer_instance + +attribute [instance] Cover.Over.over Cover.Over.isOver_map + +instance [P.ContainsIdentities] [P.RespectsIso] {X Y : Scheme.{u}} (f : X ⟶ Y) [X.Over S] [Y.Over S] + [f.IsOver S] [IsIso f] : (coverOfIsIso (P := P) f).Over S where + over _ := inferInstanceAs <| X.Over S + isOver_map _ := inferInstanceAs <| f.IsOver S + +section + +variable [P.IsStableUnderBaseChange] [IsJointlySurjectivePreserving P] +variable {X W : Scheme.{u}} (𝒰 : X.Cover P) (f : W ⟶ X) [W.Over S] [X.Over S] + [𝒰.Over S] [f.IsOver S] + +/-- The pullback of a cover of `S`-schemes along a morphism of `S`-schemes. This is not +definitionally equal to `AlgebraicGeometry.Scheme.Cover.pullbackCover`, as here we take +the pullback in `Over S`, whose underlying scheme is only isomorphic but not equal to the +pullback in `Scheme`. -/ +@[simps] +def Cover.pullbackCoverOver : W.Cover P where + J := 𝒰.J + obj x := (pullback (f.asOver S) ((𝒰.map x).asOver S)).left + map x := (pullback.fst (f.asOver S) ((𝒰.map x).asOver S)).left + f x := 𝒰.f (f.base x) + covers x := (mem_range_iff_of_surjective ((𝒰.pullbackCover f).map (𝒰.f (f.base x))) _ + ((PreservesPullback.iso (Over.forget S) (f.asOver S) ((𝒰.map _).asOver S)).inv) + (PreservesPullback.iso_inv_fst _ _ _) x).mp ((𝒰.pullbackCover f).covers x) + map_prop j := by + dsimp only + rw [← Over.forget_map, ← PreservesPullback.iso_hom_fst, P.cancel_left_of_respectsIso] + exact P.pullback_fst _ _ (𝒰.map_prop j) + +instance (j : 𝒰.J) : ((𝒰.pullbackCoverOver S f).obj j).Over S where + hom := (pullback (f.asOver S) ((𝒰.map j).asOver S)).hom + +instance : (𝒰.pullbackCoverOver S f).Over S where + isOver_map j := { comp_over := by exact Over.w (pullback.fst (f.asOver S) ((𝒰.map j).asOver S)) } + +/-- A variant of `AlgebraicGeometry.Scheme.Cover.pullbackCoverOver` with the arguments in the +fiber products flipped. -/ +@[simps] +def Cover.pullbackCoverOver' : W.Cover P where + J := 𝒰.J + obj x := (pullback ((𝒰.map x).asOver S) (f.asOver S)).left + map x := (pullback.snd ((𝒰.map x).asOver S) (f.asOver S)).left + f x := 𝒰.f (f.base x) + covers x := (mem_range_iff_of_surjective ((𝒰.pullbackCover' f).map (𝒰.f (f.base x))) _ + ((PreservesPullback.iso (Over.forget S) ((𝒰.map _).asOver S) (f.asOver S)).inv) + (PreservesPullback.iso_inv_snd _ _ _) x).mp ((𝒰.pullbackCover' f).covers x) + map_prop j := by + dsimp only + rw [← Over.forget_map, ← PreservesPullback.iso_hom_snd, P.cancel_left_of_respectsIso] + exact P.pullback_snd _ _ (𝒰.map_prop j) + +instance (j : 𝒰.J) : ((𝒰.pullbackCoverOver' S f).obj j).Over S where + hom := (pullback ((𝒰.map j).asOver S) (f.asOver S)).hom + +instance : (𝒰.pullbackCoverOver' S f).Over S where + isOver_map j := { comp_over := by exact Over.w (pullback.snd ((𝒰.map j).asOver S) (f.asOver S)) } + +variable {Q : MorphismProperty Scheme.{u}} [Q.HasOfPostcompProperty Q] + [Q.IsStableUnderBaseChange] [Q.IsStableUnderComposition] + +variable (hX : Q (X ↘ S)) (hW : Q (W ↘ S)) (hQ : ∀ j, Q (𝒰.obj j ↘ S)) + +/-- The pullback of a cover of `S`-schemes with `Q` along a morphism of `S`-schemes. This is not +definitionally equal to `AlgebraicGeometry.Scheme.Cover.pullbackCover`, as here we take +the pullback in `Q.Over ⊤ S`, whose underlying scheme is only isomorphic but not equal to the +pullback in `Scheme`. -/ +@[simps (config := .lemmasOnly)] +def Cover.pullbackCoverOverProp : W.Cover P where + J := 𝒰.J + obj x := (pullback (f.asOverProp (hX := hW) (hY := hX) S) + ((𝒰.map x).asOverProp (hX := hQ x) (hY := hX) S)).left + map x := (pullback.fst (f.asOverProp S) ((𝒰.map x).asOverProp S)).left + f x := 𝒰.f (f.base x) + covers x := (mem_range_iff_of_surjective ((𝒰.pullbackCover f).map (𝒰.f (f.base x))) _ + ((PreservesPullback.iso (MorphismProperty.Over.forget Q _ _ ⋙ Over.forget S) + (f.asOverProp S) ((𝒰.map _).asOverProp S)).inv) + (PreservesPullback.iso_inv_fst _ _ _) x).mp ((𝒰.pullbackCover f).covers x) + map_prop j := by + dsimp only + rw [← Over.forget_map, MorphismProperty.Comma.toCommaMorphism_eq_hom, + ← MorphismProperty.Comma.forget_map, ← Functor.comp_map] + rw [← PreservesPullback.iso_hom_fst, P.cancel_left_of_respectsIso] + exact P.pullback_fst _ _ (𝒰.map_prop j) + +instance (j : 𝒰.J) : ((𝒰.pullbackCoverOverProp S f hX hW hQ).obj j).Over S where + hom := (pullback (f.asOverProp (hX := hW) (hY := hX) S) + ((𝒰.map j).asOverProp (hX := hQ j) (hY := hX) S)).hom + +instance : (𝒰.pullbackCoverOverProp S f hX hW hQ).Over S where + isOver_map j := + { comp_over := by exact (pullback.fst (f.asOverProp S) ((𝒰.map j).asOverProp S)).w } + +/-- A variant of `AlgebraicGeometry.Scheme.Cover.pullbackCoverOverProp` with the arguments in the +fiber products flipped. -/ +@[simps (config := .lemmasOnly)] +def Cover.pullbackCoverOverProp' : W.Cover P where + J := 𝒰.J + obj x := (pullback ((𝒰.map x).asOverProp (hX := hQ x) (hY := hX) S) + (f.asOverProp (hX := hW) (hY := hX) S)).left + map x := (pullback.snd ((𝒰.map x).asOverProp S) (f.asOverProp S)).left + f x := 𝒰.f (f.base x) + covers x := (mem_range_iff_of_surjective ((𝒰.pullbackCover' f).map (𝒰.f (f.base x))) _ + ((PreservesPullback.iso (MorphismProperty.Over.forget Q _ _ ⋙ Over.forget S) + ((𝒰.map _).asOverProp S) (f.asOverProp S)).inv) + (PreservesPullback.iso_inv_snd _ _ _) x).mp ((𝒰.pullbackCover' f).covers x) + map_prop j := by + dsimp only + rw [← Over.forget_map, MorphismProperty.Comma.toCommaMorphism_eq_hom, + ← MorphismProperty.Comma.forget_map, ← Functor.comp_map] + rw [← PreservesPullback.iso_hom_snd, P.cancel_left_of_respectsIso] + exact P.pullback_snd _ _ (𝒰.map_prop j) + +instance (j : 𝒰.J) : ((𝒰.pullbackCoverOverProp' S f hX hW hQ).obj j).Over S where + hom := (pullback ((𝒰.map j).asOverProp (hX := hQ j) (hY := hX) S) + (f.asOverProp (hX := hW) (hY := hX) S)).hom + +instance : (𝒰.pullbackCoverOverProp' S f hX hW hQ).Over S where + isOver_map j := + { comp_over := by exact (pullback.snd ((𝒰.map j).asOverProp S) (f.asOverProp S)).w } + +end + +variable [P.IsStableUnderComposition] +variable {X : Scheme.{u}} (𝒰 : X.Cover P) (𝒱 : ∀ x, (𝒰.obj x).Cover P) + [X.Over S] [𝒰.Over S] [∀ x, (𝒱 x).Over S] + +instance (j : (𝒰.bind 𝒱).J) : ((𝒰.bind 𝒱).obj j).Over S := + inferInstanceAs <| ((𝒱 j.1).obj j.2).Over S + +instance {X : Scheme.{u}} (𝒰 : X.Cover P) (𝒱 : ∀ x, (𝒰.obj x).Cover P) + [X.Over S] [𝒰.Over S] [∀ x, (𝒱 x).Over S] : (𝒰.bind 𝒱).Over S where + over := fun ⟨i, j⟩ ↦ inferInstanceAs <| ((𝒱 i).obj j).Over S + isOver_map := fun ⟨i, j⟩ ↦ { comp_over := by simp } + +end AlgebraicGeometry.Scheme diff --git a/Mathlib/AlgebraicGeometry/EllipticCurve/Affine.lean b/Mathlib/AlgebraicGeometry/EllipticCurve/Affine.lean index 5a23dde317010..231b6e92006e9 100644 --- a/Mathlib/AlgebraicGeometry/EllipticCurve/Affine.lean +++ b/Mathlib/AlgebraicGeometry/EllipticCurve/Affine.lean @@ -81,6 +81,7 @@ elliptic curve, rational point, affine coordinates -/ open Polynomial +open scoped Polynomial.Bivariate local macro "C_simp" : tactic => `(tactic| simp only [map_ofNat, C_0, C_1, C_neg, C_add, C_sub, C_mul, C_pow]) diff --git a/Mathlib/AlgebraicGeometry/EllipticCurve/DivisionPolynomial/Basic.lean b/Mathlib/AlgebraicGeometry/EllipticCurve/DivisionPolynomial/Basic.lean index 5fb7a921a4ae8..15a2fccfcd2b3 100644 --- a/Mathlib/AlgebraicGeometry/EllipticCurve/DivisionPolynomial/Basic.lean +++ b/Mathlib/AlgebraicGeometry/EllipticCurve/DivisionPolynomial/Basic.lean @@ -95,6 +95,7 @@ elliptic curve, division polynomial, torsion point -/ open Polynomial +open scoped Polynomial.Bivariate local macro "C_simp" : tactic => `(tactic| simp only [map_ofNat, C_0, C_1, C_neg, C_add, C_sub, C_mul, C_pow]) diff --git a/Mathlib/AlgebraicGeometry/EllipticCurve/Group.lean b/Mathlib/AlgebraicGeometry/EllipticCurve/Group.lean index 7020898f0efde..c01a58c13679a 100644 --- a/Mathlib/AlgebraicGeometry/EllipticCurve/Group.lean +++ b/Mathlib/AlgebraicGeometry/EllipticCurve/Group.lean @@ -62,6 +62,7 @@ elliptic curve, group law, class group -/ open Ideal nonZeroDivisors Polynomial +open scoped Polynomial.Bivariate local macro "C_simp" : tactic => `(tactic| simp only [map_ofNat, C_0, C_1, C_neg, C_add, C_sub, C_mul, C_pow]) diff --git a/Mathlib/AlgebraicGeometry/GammaSpecAdjunction.lean b/Mathlib/AlgebraicGeometry/GammaSpecAdjunction.lean index 6c8faa057ea86..87195c4877f61 100644 --- a/Mathlib/AlgebraicGeometry/GammaSpecAdjunction.lean +++ b/Mathlib/AlgebraicGeometry/GammaSpecAdjunction.lean @@ -415,12 +415,12 @@ theorem Scheme.toSpecΓ_base (X : Scheme.{u}) (x) : @[reassoc (attr := simp)] theorem Scheme.toSpecΓ_naturality {X Y : Scheme.{u}} (f : X ⟶ Y) : - f ≫ Y.toSpecΓ = X.toSpecΓ ≫ Spec.map (f.app ⊤) := + f ≫ Y.toSpecΓ = X.toSpecΓ ≫ Spec.map (f.appTop) := ΓSpec.adjunction.unit.naturality f @[simp] -theorem Scheme.toSpecΓ_app_top (X : Scheme.{u}) : - X.toSpecΓ.app ⊤ = (Scheme.ΓSpecIso Γ(X, ⊤)).hom := by +theorem Scheme.toSpecΓ_appTop (X : Scheme.{u}) : + X.toSpecΓ.appTop = (Scheme.ΓSpecIso Γ(X, ⊤)).hom := by have := ΓSpec.adjunction.left_triangle_components X dsimp at this rw [← IsIso.eq_comp_inv] at this @@ -428,6 +428,8 @@ theorem Scheme.toSpecΓ_app_top (X : Scheme.{u}) : Scheme.Γ_obj, Category.id_comp] at this rw [← Quiver.Hom.op_inj.eq_iff, this, ← op_inv, IsIso.Iso.inv_inv] +@[deprecated (since := "2024-11-23")] alias Scheme.toSpecΓ_app_top := Scheme.toSpecΓ_appTop + @[simp] theorem SpecMap_ΓSpecIso_hom (R : CommRingCat.{u}) : Spec.map ((Scheme.ΓSpecIso R).hom) = (Spec R).toSpecΓ := by @@ -437,9 +439,9 @@ theorem SpecMap_ΓSpecIso_hom (R : CommRingCat.{u}) : lemma Scheme.toSpecΓ_preimage_basicOpen (X : Scheme.{u}) (r : Γ(X, ⊤)) : X.toSpecΓ ⁻¹ᵁ (PrimeSpectrum.basicOpen r) = X.basicOpen r := by - rw [← basicOpen_eq_of_affine, Scheme.preimage_basicOpen] + rw [← basicOpen_eq_of_affine, Scheme.preimage_basicOpen, ← Scheme.Hom.appTop] congr - rw [Scheme.toSpecΓ_app_top] + rw [Scheme.toSpecΓ_appTop] exact Iso.inv_hom_id_apply _ _ -- Warning: this LHS of this lemma breaks the structure-sheaf abstraction. @@ -456,25 +458,24 @@ theorem toOpen_toSpecΓ_app {X : Scheme.{u}} (U) : exact Category.id_comp _ lemma ΓSpecIso_inv_ΓSpec_adjunction_homEquiv {X : Scheme.{u}} {B : CommRingCat} (φ : B ⟶ Γ(X, ⊤)) : - (Scheme.ΓSpecIso B).inv ≫ ((ΓSpec.adjunction.homEquiv X (op B)) φ.op).app ⊤ = φ := by + (Scheme.ΓSpecIso B).inv ≫ ((ΓSpec.adjunction.homEquiv X (op B)) φ.op).appTop = φ := by simp only [Adjunction.homEquiv_apply, Scheme.Spec_map, Opens.map_top, Scheme.comp_app] simp lemma ΓSpec_adjunction_homEquiv_eq {X : Scheme.{u}} {B : CommRingCat} (φ : B ⟶ Γ(X, ⊤)) : - (((ΓSpec.adjunction.homEquiv X (op B)) φ.op).app ⊤) = (Scheme.ΓSpecIso B).hom ≫ φ := by - simp_rw [← ΓSpecIso_inv_ΓSpec_adjunction_homEquiv φ] - simp + ((ΓSpec.adjunction.homEquiv X (op B)) φ.op).appTop = (Scheme.ΓSpecIso B).hom ≫ φ := by + rw [← Iso.inv_comp_eq, ΓSpecIso_inv_ΓSpec_adjunction_homEquiv] theorem ΓSpecIso_obj_hom {X : Scheme.{u}} (U : X.Opens) : - (Scheme.ΓSpecIso Γ(X, U)).hom = (Spec.map U.topIso.inv).app ⊤ ≫ - U.toScheme.toSpecΓ.app ⊤ ≫ U.topIso.hom := by simp + (Scheme.ΓSpecIso Γ(X, U)).hom = (Spec.map U.topIso.inv).appTop ≫ + U.toScheme.toSpecΓ.appTop ≫ U.topIso.hom := by simp @[deprecated (since := "2024-07-24")] alias ΓSpec.adjunction_unit_naturality := Scheme.toSpecΓ_naturality @[deprecated (since := "2024-07-24")] alias ΓSpec.adjunction_unit_naturality_assoc := Scheme.toSpecΓ_naturality_assoc @[deprecated (since := "2024-07-24")] -alias ΓSpec.adjunction_unit_app_app_top := Scheme.toSpecΓ_app_top +alias ΓSpec.adjunction_unit_app_app_top := Scheme.toSpecΓ_appTop @[deprecated (since := "2024-07-24")] alias ΓSpec.adjunction_unit_map_basicOpen := Scheme.toSpecΓ_preimage_basicOpen diff --git a/Mathlib/AlgebraicGeometry/Limits.lean b/Mathlib/AlgebraicGeometry/Limits.lean index 6c634b3aadaac..b4f7a0106ddca 100644 --- a/Mathlib/AlgebraicGeometry/Limits.lean +++ b/Mathlib/AlgebraicGeometry/Limits.lean @@ -48,7 +48,11 @@ instance : HasFiniteLimits Scheme := hasFiniteLimits_of_hasTerminal_and_pullbacks instance (X : Scheme.{u}) : X.Over (⊤_ _) := ⟨terminal.from _⟩ -instance {X Y : Scheme.{u}} (f : X ⟶ Y) : f.IsOver (⊤_ _) := ⟨terminal.hom_ext _ _⟩ +instance {X Y : Scheme.{u}} [X.Over (⊤_ Scheme)] [Y.Over (⊤_ Scheme)] (f : X ⟶ Y) : + @Scheme.Hom.IsOver _ _ f (⊤_ Scheme) ‹_› ‹_› := ⟨Subsingleton.elim _ _⟩ + +instance {X : Scheme} : Subsingleton (X.Over (⊤_ Scheme)) := + ⟨fun ⟨a⟩ ⟨b⟩ ↦ by simp [Subsingleton.elim a b]⟩ section Initial diff --git a/Mathlib/AlgebraicGeometry/Morphisms/Affine.lean b/Mathlib/AlgebraicGeometry/Morphisms/Affine.lean index 66b28ced66e1b..10aa7de982be9 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/Affine.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/Affine.lean @@ -158,7 +158,7 @@ instance : HasAffineProperty @IsAffineHom fun X _ _ _ ↦ IsAffine X where rw [Scheme.preimage_basicOpen] exact (isAffineOpen_top X).basicOpen _ · intro X Y _ f S hS hS' - apply_fun Ideal.map (f.app ⊤) at hS + apply_fun Ideal.map (f.appTop) at hS rw [Ideal.map_span, Ideal.map_top] at hS apply isAffine_of_isAffineOpen_basicOpen _ hS have : ∀ i : S, IsAffineOpen (f⁻¹ᵁ Y.basicOpen i.1) := hS' diff --git a/Mathlib/AlgebraicGeometry/Morphisms/AffineAnd.lean b/Mathlib/AlgebraicGeometry/Morphisms/AffineAnd.lean index 6eea058bd4042..632a366ca7236 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/AffineAnd.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/AffineAnd.lean @@ -35,11 +35,11 @@ variable (Q : ∀ {R S : Type u} [CommRing R] [CommRing S], (R →+* S) → Prop /-- This is the affine target morphism property where the source is affine and the induced map of rings on global sections satisfies `P`. -/ def affineAnd : AffineTargetMorphismProperty := - fun X _ f ↦ IsAffine X ∧ Q (f.app ⊤) + fun X _ f ↦ IsAffine X ∧ Q (f.appTop) @[simp] lemma affineAnd_apply {X Y : Scheme.{u}} (f : X ⟶ Y) [IsAffine Y] : - affineAnd Q f ↔ IsAffine X ∧ Q (f.app ⊤) := + affineAnd Q f ↔ IsAffine X ∧ Q (f.appTop) := Iff.rfl attribute [local simp] AffineTargetMorphismProperty.toProperty_apply @@ -64,28 +64,29 @@ lemma affineAnd_isLocal (hPi : RingHom.RespectsIso Q) (hQl : RingHom.Localizatio constructor · simp only [Scheme.preimage_basicOpen, Opens.map_top] exact (isAffineOpen_top X).basicOpen _ - · dsimp only [Opens.map_top] - rw [morphismRestrict_app, hPi.cancel_right_isIso, Scheme.Opens.ι_image_top] + · dsimp only + rw [morphismRestrict_appTop, hPi.cancel_right_isIso, Scheme.Opens.ι_image_top] rw [(isAffineOpen_top Y).app_basicOpen_eq_away_map f (isAffineOpen_top X), - hPi.cancel_right_isIso] - haveI := (isAffineOpen_top X).isLocalization_basicOpen (f.app ⊤ r) + hPi.cancel_right_isIso, ← Scheme.Hom.appTop] + dsimp only [Opens.map_top] + haveI := (isAffineOpen_top X).isLocalization_basicOpen (f.appTop r) apply hQl exact hf of_basicOpenCover {X Y _} f s hs hf := by dsimp [affineAnd] at hf haveI : IsAffine X := by - apply isAffine_of_isAffineOpen_basicOpen (f.app ⊤ '' s) - · apply_fun Ideal.map (f.app ⊤) at hs + apply isAffine_of_isAffineOpen_basicOpen (f.appTop '' s) + · apply_fun Ideal.map (f.appTop) at hs rwa [Ideal.map_span, Ideal.map_top] at hs · rintro - ⟨r, hr, rfl⟩ simp_rw [Scheme.preimage_basicOpen] at hf exact (hf ⟨r, hr⟩).left - refine ⟨inferInstance, hQs.ofIsLocalization' hPi (f.app ⊤) s hs fun a ↦ ?_⟩ - refine ⟨Γ(Y, Y.basicOpen a.val), Γ(X, X.basicOpen (f.app ⊤ a.val)), inferInstance, + refine ⟨inferInstance, hQs.ofIsLocalization' hPi (f.appTop) s hs fun a ↦ ?_⟩ + refine ⟨Γ(Y, Y.basicOpen a.val), Γ(X, X.basicOpen (f.appTop a.val)), inferInstance, inferInstance, inferInstance, inferInstance, inferInstance, ?_, ?_⟩ - · exact (isAffineOpen_top X).isLocalization_basicOpen (f.app ⊤ a.val) + · exact (isAffineOpen_top X).isLocalization_basicOpen (f.appTop a.val) · obtain ⟨_, hf⟩ := hf a - rw [morphismRestrict_app, hPi.cancel_right_isIso, Scheme.Opens.ι_image_top] at hf + rw [morphismRestrict_appTop, hPi.cancel_right_isIso, Scheme.Opens.ι_image_top] at hf rw [(isAffineOpen_top Y).app_basicOpen_eq_away_map _ (isAffineOpen_top X)] at hf rwa [hPi.cancel_right_isIso] at hf @@ -96,7 +97,7 @@ lemma affineAnd_isStableUnderBaseChange (hQi : RingHom.RespectsIso Q) haveI : (affineAnd Q).toProperty.RespectsIso := affineAnd_respectsIso hQi apply AffineTargetMorphismProperty.IsStableUnderBaseChange.mk intro X Y S _ _ f g ⟨hY, hg⟩ - exact ⟨inferInstance, hQb.pullback_fst_app_top _ hQi f _ hg⟩ + exact ⟨inferInstance, hQb.pullback_fst_appTop _ hQi f _ hg⟩ lemma targetAffineLocally_affineAnd_iff (hQi : RingHom.RespectsIso Q) {X Y : Scheme.{u}} (f : X ⟶ Y) : @@ -133,7 +134,7 @@ lemma targetAffineLocally_affineAnd_iff_affineLocally (hQ : RingHom.PropertyIsLo intro U have : IsAffine (f ⁻¹ᵁ U) := hf.isAffine_preimage U U.2 rw [HasRingHomProperty.iff_of_isAffine (P := affineLocally Q), - morphismRestrict_app, hQ.respectsIso.cancel_right_isIso] + morphismRestrict_appTop, hQ.respectsIso.cancel_right_isIso] apply h rw [Scheme.Opens.ι_image_top] exact U.2 diff --git a/Mathlib/AlgebraicGeometry/Morphisms/Basic.lean b/Mathlib/AlgebraicGeometry/Morphisms/Basic.lean index 51f9c3ccf41d9..070c60d31cc77 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/Basic.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/Basic.lean @@ -142,8 +142,7 @@ instance inf (P Q : MorphismProperty Scheme) [IsLocalAtTarget P] [IsLocalAtTarge fun h ↦ ⟨(iff_of_openCover' f 𝒰).mpr (fun i ↦ (h i).left), (iff_of_openCover' f 𝒰).mpr (fun i ↦ (h i).right)⟩⟩ -variable {P} [hP : IsLocalAtTarget P] -variable {X Y U V : Scheme.{u}} {f : X ⟶ Y} {g : U ⟶ Y} [IsOpenImmersion g] (𝒰 : Y.OpenCover) +variable {P} [hP : IsLocalAtTarget P] {X Y : Scheme.{u}} {f : X ⟶ Y} (𝒰 : Y.OpenCover) lemma of_isPullback {UX UY : Scheme.{u}} {iY : UY ⟶ Y} [IsOpenImmersion iY] {iX : UX ⟶ X} {f' : UX ⟶ UY} (h : IsPullback iX f' f iY) (H : P f) : P f' := by @@ -228,7 +227,7 @@ instance inf (P Q : MorphismProperty Scheme) [IsLocalAtSource P] [IsLocalAtSourc (iff_of_openCover' f 𝒰).mpr (fun i ↦ (h i).right)⟩⟩ variable {P} [IsLocalAtSource P] -variable {X Y U V : Scheme.{u}} {f : X ⟶ Y} {g : U ⟶ Y} [IsOpenImmersion g] (𝒰 : X.OpenCover) +variable {X Y : Scheme.{u}} {f : X ⟶ Y} (𝒰 : X.OpenCover) lemma comp {UX : Scheme.{u}} (H : P f) (i : UX ⟶ X) [IsOpenImmersion i] : P (i ≫ f) := diff --git a/Mathlib/AlgebraicGeometry/Morphisms/ClosedImmersion.lean b/Mathlib/AlgebraicGeometry/Morphisms/ClosedImmersion.lean index 1cb1635d9fcb0..0145a3045d5db 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/ClosedImmersion.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/ClosedImmersion.lean @@ -62,8 +62,8 @@ lemma eq_inf : @IsClosedImmersion = (topologically IsClosedEmbedding) ⊓ lemma iff_isPreimmersion {X Y : Scheme} {f : X ⟶ Y} : IsClosedImmersion f ↔ IsPreimmersion f ∧ IsClosed (Set.range f.base) := by - rw [and_comm, isClosedImmersion_iff, isPreimmersion_iff, ← and_assoc, isClosedEmbedding_iff, - @and_comm (IsEmbedding _)] + rw [isClosedImmersion_iff, isPreimmersion_iff, ← surjectiveOnStalks_iff, and_comm, and_assoc, + isClosedEmbedding_iff] lemma of_isPreimmersion {X Y : Scheme} (f : X ⟶ Y) [IsPreimmersion f] (hf : IsClosed (Set.range f.base)) : IsClosedImmersion f := @@ -117,7 +117,7 @@ instance spec_of_quotient_mk {R : CommRingCat.{u}} (I : Ideal R) : /-- Any morphism between affine schemes that is surjective on global sections is a closed immersion. -/ lemma of_surjective_of_isAffine {X Y : Scheme} [IsAffine X] [IsAffine Y] (f : X ⟶ Y) - (h : Function.Surjective (f.app ⊤)) : IsClosedImmersion f := by + (h : Function.Surjective (f.appTop)) : IsClosedImmersion f := by rw [MorphismProperty.arrow_mk_iso_iff @IsClosedImmersion (arrowIsoSpecΓOfIsAffine f)] apply spec_of_surjective exact h @@ -161,7 +161,7 @@ open IsClosedImmersion LocallyRingedSpace has a closed image and `f` induces an injection on global sections, then `f` is surjective. -/ lemma surjective_of_isClosed_range_of_injective [CompactSpace X] - (hfcl : IsClosed (Set.range f.base)) (hfinj : Function.Injective (f.app ⊤)) : + (hfcl : IsClosed (Set.range f.base)) (hfinj : Function.Injective (f.appTop)) : Function.Surjective f.base := by obtain ⟨I, hI⟩ := (Scheme.eq_zeroLocus_of_isClosed_of_isAffine Y (Set.range f.base)).mp hfcl let 𝒰 : X.OpenCover := X.affineCover.finiteSubcover @@ -186,12 +186,12 @@ lemma surjective_of_isClosed_range_of_injective [CompactSpace X] injective if it is injective on global sections. -/ lemma stalkMap_injective_of_isOpenMap_of_injective [CompactSpace X] (hfopen : IsOpenMap f.base) (hfinj₁ : Function.Injective f.base) - (hfinj₂ : Function.Injective (f.app ⊤)) (x : X) : + (hfinj₂ : Function.Injective (f.appTop)) (x : X) : Function.Injective (f.stalkMap x) := by - let φ : Γ(Y, ⊤) ⟶ Γ(X, ⊤) := f.app ⊤ + let φ : Γ(Y, ⊤) ⟶ Γ(X, ⊤) := f.appTop let 𝒰 : X.OpenCover := X.affineCover.finiteSubcover have (i : 𝒰.J) : IsAffine (𝒰.obj i) := Scheme.isAffine_affineCover X _ - let res (i : 𝒰.J) : Γ(X, ⊤) ⟶ Γ(𝒰.obj i, ⊤) := (𝒰.map i).app ⊤ + let res (i : 𝒰.J) : Γ(X, ⊤) ⟶ Γ(𝒰.obj i, ⊤) := (𝒰.map i).appTop refine stalkMap_injective_of_isAffine _ _ (fun (g : Γ(Y, ⊤)) h ↦ ?_) rw [TopCat.Presheaf.Γgerm, Scheme.stalkMap_germ_apply] at h obtain ⟨U, w, (hx : x ∈ U), hg⟩ := @@ -200,8 +200,8 @@ lemma stalkMap_injective_of_isOpenMap_of_injective [CompactSpace X] (show f.base x ∈ ⟨f.base '' U.carrier, hfopen U.carrier U.is_open'⟩ from ⟨x, by simpa⟩) let W (i : 𝒰.J) : TopologicalSpace.Opens (𝒰.obj i) := (𝒰.obj i).basicOpen ((res i) (φ s)) have hwle (i : 𝒰.J) : W i ≤ (𝒰.map i)⁻¹ᵁ U := by - show ((𝒰.obj i).basicOpen ((𝒰.map i ≫ f).app ⊤ s)) ≤ _ - rw [← Scheme.preimage_basicOpen, Scheme.comp_coeBase, Opens.map_comp_obj] + show (𝒰.obj i).basicOpen ((𝒰.map i ≫ f).appTop s) ≤ _ + rw [← Scheme.preimage_basicOpen_top, Scheme.comp_coeBase, Opens.map_comp_obj] refine Scheme.Hom.preimage_le_preimage_of_le _ (le_trans (f.preimage_le_preimage_of_le bsle) (le_of_eq ?_)) simp [Set.preimage_image_eq _ hfinj₁] @@ -229,7 +229,7 @@ namespace IsClosedImmersion /-- If `f` is a closed immersion with affine target such that the induced map on global sections is injective, `f` is an isomorphism. -/ theorem isIso_of_injective_of_isAffine [IsClosedImmersion f] - (hf : Function.Injective (f.app ⊤)) : IsIso f := (isIso_iff_stalk_iso f).mpr <| + (hf : Function.Injective (f.appTop)) : IsIso f := (isIso_iff_stalk_iso f).mpr <| have : CompactSpace X := f.isClosedEmbedding.compactSpace have hiso : IsIso f.base := TopCat.isIso_of_bijective_of_isClosedMap _ ⟨f.isClosedEmbedding.injective, @@ -244,7 +244,7 @@ variable (f) /-- If `f` is a closed immersion with affine target, the source is affine and the induced map on global sections is surjective. -/ theorem isAffine_surjective_of_isAffine [IsClosedImmersion f] : - IsAffine X ∧ Function.Surjective (f.app ⊤) := by + IsAffine X ∧ Function.Surjective (f.appTop) := by haveI i : IsClosedImmersion f := inferInstance rw [← affineTargetImageFactorization_comp f] at i ⊢ haveI := of_surjective_of_isAffine (affineTargetImageInclusion f) @@ -254,7 +254,7 @@ theorem isAffine_surjective_of_isAffine [IsClosedImmersion f] : haveI := isIso_of_injective_of_isAffine (affineTargetImageFactorization_app_injective f) exact ⟨isAffine_of_isIso (affineTargetImageFactorization f), (ConcreteCategory.bijective_of_isIso - ((affineTargetImageFactorization f).app ⊤)).surjective.comp <| + ((affineTargetImageFactorization f).appTop)).surjective.comp <| affineTargetImageInclusion_app_surjective f⟩ end IsClosedImmersion @@ -268,7 +268,7 @@ instance IsClosedImmersion.isLocalAtTarget : IsLocalAtTarget @IsClosedImmersion /-- On morphisms with affine target, being a closed immersion is precisely having affine source and being surjective on global sections. -/ instance IsClosedImmersion.hasAffineProperty : HasAffineProperty @IsClosedImmersion - (fun X _ f ↦ IsAffine X ∧ Function.Surjective (f.app ⊤)) := by + (fun X _ f ↦ IsAffine X ∧ Function.Surjective (f.appTop)) := by convert HasAffineProperty.of_isLocalAtTarget @IsClosedImmersion refine ⟨fun ⟨h₁, h₂⟩ ↦ of_surjective_of_isAffine _ h₂, by apply isAffine_surjective_of_isAffine⟩ @@ -290,7 +290,7 @@ instance IsClosedImmersion.isStableUnderBaseChange : haveI := HasAffineProperty.isLocal_affineProperty @IsClosedImmersion apply AffineTargetMorphismProperty.IsStableUnderBaseChange.mk intro X Y S _ _ f g ⟨ha, hsurj⟩ - exact ⟨inferInstance, RingHom.surjective_isStableUnderBaseChange.pullback_fst_app_top _ + exact ⟨inferInstance, RingHom.surjective_isStableUnderBaseChange.pullback_fst_appTop _ RingHom.surjective_respectsIso f _ hsurj⟩ /-- Closed immersions are locally of finite type. -/ @@ -320,13 +320,13 @@ lemma isIso_of_isClosedImmersion_of_surjective {X Y : Scheme.{u}} (f : X ⟶ Y) · infer_instance apply IsClosedImmersion.isIso_of_injective_of_isAffine obtain ⟨hX, hf⟩ := HasAffineProperty.iff_of_isAffine.mp ‹IsClosedImmersion f› - let φ := f.app ⊤ + let φ := f.appTop suffices RingHom.ker φ ≤ nilradical _ by rwa [nilradical_eq_zero, Submodule.zero_eq_bot, le_bot_iff, ← RingHom.injective_iff_ker_eq_bot] at this refine (PrimeSpectrum.zeroLocus_eq_top_iff _).mp ?_ rw [← range_specComap_of_surjective _ _ hf, Set.top_eq_univ, Set.range_eq_univ] - have : Surjective (Spec.map (f.app ⊤)) := + have : Surjective (Spec.map (f.appTop)) := (MorphismProperty.arrow_mk_iso_iff @Surjective (arrowIsoSpecΓOfIsAffine f)).mp (inferInstanceAs (Surjective f)) exact this.1 diff --git a/Mathlib/AlgebraicGeometry/Morphisms/Etale.lean b/Mathlib/AlgebraicGeometry/Morphisms/Etale.lean index 665513b4b09cb..35ee3280f7055 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/Etale.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/Etale.lean @@ -28,7 +28,7 @@ abbrev IsEtale {X Y : Scheme.{u}} (f : X ⟶ Y) := IsSmoothOfRelativeDimension 0 namespace IsEtale -variable {X Y : Scheme.{u}} (f : X ⟶ Y) +variable {X : Scheme.{u}} instance : IsStableUnderBaseChange @IsEtale := isSmoothOfRelativeDimension_isStableUnderBaseChange 0 diff --git a/Mathlib/AlgebraicGeometry/Morphisms/Finite.lean b/Mathlib/AlgebraicGeometry/Morphisms/Finite.lean index 0f054e90a059e..60115fff857f2 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/Finite.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/Finite.lean @@ -37,7 +37,7 @@ class IsFinite {X Y : Scheme} (f : X ⟶ Y) extends IsAffineHom f : Prop where namespace IsFinite -instance : HasAffineProperty @IsFinite (fun X _ f _ ↦ IsAffine X ∧ RingHom.Finite (f.app ⊤)) := by +instance : HasAffineProperty @IsFinite (fun X _ f _ ↦ IsAffine X ∧ RingHom.Finite (f.appTop)) := by show HasAffineProperty @IsFinite (affineAnd RingHom.Finite) rw [HasAffineProperty.affineAnd_iff _ RingHom.finite_respectsIso RingHom.finite_localizationPreserves RingHom.finite_ofLocalizationSpan] diff --git a/Mathlib/AlgebraicGeometry/Morphisms/IsIso.lean b/Mathlib/AlgebraicGeometry/Morphisms/IsIso.lean index 06cb129fa9785..ed9fb2ee4ca4d 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/IsIso.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/IsIso.lean @@ -36,10 +36,10 @@ lemma isomorphisms_eq_stalkwise : instance : IsLocalAtTarget (isomorphisms Scheme) := isomorphisms_eq_isOpenImmersion_inf_surjective ▸ inferInstance -instance : HasAffineProperty (isomorphisms Scheme) fun X _ f _ ↦ IsAffine X ∧ IsIso (f.app ⊤) := by +instance : HasAffineProperty (isomorphisms Scheme) fun X _ f _ ↦ IsAffine X ∧ IsIso (f.appTop) := by convert HasAffineProperty.of_isLocalAtTarget (isomorphisms Scheme) with X Y f hY exact ⟨fun ⟨_, _⟩ ↦ (arrow_mk_iso_iff (isomorphisms _) (arrowIsoSpecΓOfIsAffine f)).mpr - (inferInstanceAs (IsIso (Spec.map (f.app ⊤)))), + (inferInstanceAs (IsIso (Spec.map (f.appTop)))), fun (_ : IsIso f) ↦ ⟨isAffine_of_isIso f, inferInstance⟩⟩ instance : IsLocalAtTarget (monomorphisms Scheme) := diff --git a/Mathlib/AlgebraicGeometry/Morphisms/OpenImmersion.lean b/Mathlib/AlgebraicGeometry/Morphisms/OpenImmersion.lean index 880a1a62832f1..6cd62e8973f1b 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/OpenImmersion.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/OpenImmersion.lean @@ -26,7 +26,7 @@ universe u namespace AlgebraicGeometry -variable {X Y Z : Scheme.{u}} (f : X ⟶ Y) (g : Y ⟶ Z) +variable {X Y : Scheme.{u}} theorem isOpenImmersion_iff_stalk {f : X ⟶ Y} : IsOpenImmersion f ↔ IsOpenEmbedding f.base ∧ ∀ x, IsIso (f.stalkMap x) := by diff --git a/Mathlib/AlgebraicGeometry/Morphisms/Preimmersion.lean b/Mathlib/AlgebraicGeometry/Morphisms/Preimmersion.lean index 4d5503fe1dc7f..a2505954c2c6e 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/Preimmersion.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/Preimmersion.lean @@ -4,8 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Andrew Yang -/ import Mathlib.AlgebraicGeometry.Morphisms.UnderlyingMap -import Mathlib.RingTheory.RingHom.Surjective -import Mathlib.RingTheory.SurjectiveOnStalks +import Mathlib.AlgebraicGeometry.Morphisms.SurjectiveOnStalks /-! @@ -33,9 +32,8 @@ namespace AlgebraicGeometry /-- A morphism of schemes `f : X ⟶ Y` is a preimmersion if the underlying map of topological spaces is an embedding and the induced morphisms of stalks are all surjective. -/ @[mk_iff] -class IsPreimmersion {X Y : Scheme} (f : X ⟶ Y) : Prop where +class IsPreimmersion {X Y : Scheme} (f : X ⟶ Y) extends SurjectiveOnStalks f : Prop where base_embedding : IsEmbedding f.base - surj_on_stalks : ∀ x, Function.Surjective (f.stalkMap x) lemma Scheme.Hom.isEmbedding {X Y : Scheme} (f : Hom X Y) [IsPreimmersion f] : IsEmbedding f.base := IsPreimmersion.base_embedding @@ -43,12 +41,8 @@ lemma Scheme.Hom.isEmbedding {X Y : Scheme} (f : Hom X Y) [IsPreimmersion f] : I @[deprecated (since := "2024-10-26")] alias Scheme.Hom.embedding := Scheme.Hom.isEmbedding -lemma Scheme.Hom.stalkMap_surjective {X Y : Scheme} (f : Hom X Y) [IsPreimmersion f] (x) : - Function.Surjective (f.stalkMap x) := - IsPreimmersion.surj_on_stalks x - lemma isPreimmersion_eq_inf : - @IsPreimmersion = topologically IsEmbedding ⊓ stalkwise (Function.Surjective ·) := by + @IsPreimmersion = (@SurjectiveOnStalks ⊓ topologically IsEmbedding : MorphismProperty _) := by ext rw [isPreimmersion_iff] rfl @@ -69,10 +63,7 @@ instance (priority := 900) {X Y : Scheme} (f : X ⟶ Y) [IsOpenImmersion f] : Is instance : MorphismProperty.IsMultiplicative @IsPreimmersion where id_mem _ := inferInstance - comp_mem {X Y Z} f g hf hg := by - refine ⟨hg.base_embedding.comp hf.base_embedding, fun x ↦ ?_⟩ - rw [Scheme.stalkMap_comp] - exact (hf.surj_on_stalks x).comp (hg.surj_on_stalks (f.base x)) + comp_mem f g _ _ := ⟨g.isEmbedding.comp f.isEmbedding⟩ instance comp {X Y Z : Scheme} (f : X ⟶ Y) (g : Y ⟶ Z) [IsPreimmersion f] [IsPreimmersion g] : IsPreimmersion (f ≫ g) := @@ -104,14 +95,8 @@ lemma Spec_map_iff {R S : CommRingCat.{u}} (f : R ⟶ S) : haveI : (RingHom.toMorphismProperty <| fun f ↦ Function.Surjective f).RespectsIso := by rw [← RingHom.toMorphismProperty_respectsIso_iff] exact RingHom.surjective_respectsIso - refine ⟨fun ⟨h₁, h₂⟩ ↦ ⟨h₁, ?_⟩, fun ⟨h₁, h₂⟩ ↦ ⟨h₁, fun (x : PrimeSpectrum S) ↦ ?_⟩⟩ - · intro p hp - let e := Scheme.arrowStalkMapSpecIso f ⟨p, hp⟩ - apply ((RingHom.toMorphismProperty <| fun f ↦ Function.Surjective f).arrow_mk_iso_iff e).mp - exact h₂ ⟨p, hp⟩ - · let e := Scheme.arrowStalkMapSpecIso f x - apply ((RingHom.toMorphismProperty <| fun f ↦ Function.Surjective f).arrow_mk_iso_iff e).mpr - exact h₂ x.asIdeal x.isPrime + rw [← HasRingHomProperty.Spec_iff (P := @SurjectiveOnStalks), isPreimmersion_iff, and_comm] + rfl lemma mk_Spec_map {R S : CommRingCat.{u}} {f : R ⟶ S} (h₁ : IsEmbedding (PrimeSpectrum.comap f)) (h₂ : f.SurjectiveOnStalks) : @@ -125,6 +110,19 @@ lemma of_isLocalization {R S : Type u} [CommRing R] (M : Submonoid R) [CommRing (PrimeSpectrum.localization_comap_isEmbedding (R := R) S M) (RingHom.surjectiveOnStalks_of_isLocalization (M := M) S) +open Limits MorphismProperty in +instance : IsStableUnderBaseChange @IsPreimmersion := by + refine .mk' fun X Y Z f g _ _ ↦ ?_ + have := pullback_fst (P := @SurjectiveOnStalks) f g inferInstance + constructor + let L (x : (pullback f g : _)) : { x : X × Y | f.base x.1 = g.base x.2 } := + ⟨⟨(pullback.fst f g).base x, (pullback.snd f g).base x⟩, + by simp only [Set.mem_setOf, ← Scheme.comp_base_apply, pullback.condition]⟩ + have : IsEmbedding L := IsEmbedding.of_comp (by fun_prop) continuous_subtype_val + (SurjectiveOnStalks.isEmbedding_pullback f g) + exact IsEmbedding.subtypeVal.comp ((TopCat.pullbackHomeoPreimage _ f.continuous _ + g.isEmbedding).isEmbedding.comp this) + end IsPreimmersion end AlgebraicGeometry diff --git a/Mathlib/AlgebraicGeometry/Morphisms/RingHomProperties.lean b/Mathlib/AlgebraicGeometry/Morphisms/RingHomProperties.lean index 6a02465a5cb1a..4306631e05eb2 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/RingHomProperties.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/RingHomProperties.lean @@ -39,9 +39,9 @@ For `HasRingHomProperty P Q` and `f : X ⟶ Y`, we provide these API lemmas: - `AlgebraicGeometry.HasRingHomProperty.iff_appLE`: `P f` if and only if `Q (f.appLE U V _)` for all affine `U : Opens Y` and `V : Opens X`. - `AlgebraicGeometry.HasRingHomProperty.iff_of_source_openCover`: - If `Y` is affine, `P f ↔ ∀ i, Q ((𝒰.map i ≫ f).app ⊤)` for an affine open cover `𝒰` of `X`. + If `Y` is affine, `P f ↔ ∀ i, Q ((𝒰.map i ≫ f).appTop)` for an affine open cover `𝒰` of `X`. - `AlgebraicGeometry.HasRingHomProperty.iff_of_isAffine`: - If `X` and `Y` are affine, then `P f ↔ Q (f.app ⊤)`. + If `X` and `Y` are affine, then `P f ↔ Q (f.appTop)`. - `AlgebraicGeometry.HasRingHomProperty.Spec_iff`: `P (Spec.map φ) ↔ Q φ` - `AlgebraicGeometry.HasRingHomProperty.iff_of_iSup_eq_top`: @@ -66,14 +66,14 @@ namespace RingHom variable (P : ∀ {R S : Type u} [CommRing R] [CommRing S], (R →+* S) → Prop) -theorem IsStableUnderBaseChange.pullback_fst_app_top +theorem IsStableUnderBaseChange.pullback_fst_appTop (hP : IsStableUnderBaseChange P) (hP' : RespectsIso P) {X Y S : Scheme} [IsAffine X] [IsAffine Y] [IsAffine S] (f : X ⟶ S) (g : Y ⟶ S) - (H : P (g.app ⊤)) : P ((pullback.fst f g).app ⊤) := by + (H : P g.appTop) : P (pullback.fst f g).appTop := by -- Porting note (https://github.com/leanprover-community/mathlib4/issues/11224): change `rw` to `erw` erw [← PreservesPullback.iso_inv_fst AffineScheme.forgetToScheme (AffineScheme.ofHom f) (AffineScheme.ofHom g)] - rw [Scheme.comp_app, hP'.cancel_right_isIso, AffineScheme.forgetToScheme_map] + rw [Scheme.comp_appTop, hP'.cancel_right_isIso, AffineScheme.forgetToScheme_map] have := congr_arg Quiver.Hom.unop (PreservesPullback.iso_hom_fst AffineScheme.Γ.rightOp (AffineScheme.ofHom f) (AffineScheme.ofHom g)) @@ -83,6 +83,10 @@ theorem IsStableUnderBaseChange.pullback_fst_app_top rw [← this, hP'.cancel_right_isIso, ← pushoutIsoUnopPullback_inl_hom, hP'.cancel_right_isIso] exact hP.pushout_inl _ hP' _ _ H +@[deprecated (since := "2024-11-23")] +alias IsStableUnderBaseChange.pullback_fst_app_top := +IsStableUnderBaseChange.pullback_fst_appTop + end RingHom namespace AlgebraicGeometry @@ -268,10 +272,12 @@ theorem appLE (H : P f) (U : Y.affineOpens) (V : X.affineOpens) (e) : Q (f.appLE rw [eq_affineLocally P, affineLocally_iff_affineOpens_le] at H exact H _ _ _ -theorem app_top (H : P f) [IsAffine X] [IsAffine Y] : Q (f.app ⊤) := by - rw [Scheme.Hom.app_eq_appLE] +theorem appTop (H : P f) [IsAffine X] [IsAffine Y] : Q f.appTop := by + rw [Scheme.Hom.appTop, Scheme.Hom.app_eq_appLE] exact appLE P f H ⟨_, isAffineOpen_top _⟩ ⟨_, isAffineOpen_top _⟩ _ +@[deprecated (since := "2024-11-23")] alias app_top := appTop + include Q in theorem comp_of_isOpenImmersion [IsOpenImmersion f] (H : P g) : P (f ≫ g) := by @@ -291,7 +297,7 @@ lemma iff_appLE : P f ↔ ∀ (U : Y.affineOpens) (V : X.affineOpens) (e), Q (f. rw [eq_affineLocally P, affineLocally_iff_affineOpens_le] theorem of_source_openCover [IsAffine Y] - (𝒰 : X.OpenCover) [∀ i, IsAffine (𝒰.obj i)] (H : ∀ i, Q ((𝒰.map i ≫ f).app ⊤)) : + (𝒰 : X.OpenCover) [∀ i, IsAffine (𝒰.obj i)] (H : ∀ i, Q ((𝒰.map i ≫ f).appTop)) : P f := by rw [HasAffineProperty.iff_of_isAffine (P := P)] intro U @@ -313,17 +319,17 @@ theorem of_source_openCover [IsAffine Y] specialize H i rw [← (isLocal_ringHomProperty P).respectsIso.cancel_right_isIso _ ((IsOpenImmersion.isoOfRangeEq (𝒰.map i) (S i).1.ι - Subtype.range_coe.symm).inv.app _), ← Scheme.comp_app, - IsOpenImmersion.isoOfRangeEq_inv_fac_assoc, Scheme.comp_app, - Scheme.Opens.ι_app, Scheme.Hom.app_eq_appLE, Scheme.Hom.appLE_map] at H + Subtype.range_coe.symm).inv.app _), ← Scheme.comp_appTop, + IsOpenImmersion.isoOfRangeEq_inv_fac_assoc, Scheme.comp_appTop, + Scheme.Opens.ι_appTop, Scheme.Hom.appTop, Scheme.Hom.app_eq_appLE, Scheme.Hom.appLE_map] at H exact (f.appLE_congr _ rfl (by simp) Q).mp H theorem iff_of_source_openCover [IsAffine Y] (𝒰 : X.OpenCover) [∀ i, IsAffine (𝒰.obj i)] : - P f ↔ ∀ i, Q ((𝒰.map i ≫ f).app ⊤) := - ⟨fun H i ↦ app_top P _ (comp_of_isOpenImmersion P (𝒰.map i) f H), of_source_openCover 𝒰⟩ + P f ↔ ∀ i, Q ((𝒰.map i ≫ f).appTop) := + ⟨fun H i ↦ appTop P _ (comp_of_isOpenImmersion P (𝒰.map i) f H), of_source_openCover 𝒰⟩ theorem iff_of_isAffine [IsAffine X] [IsAffine Y] : - P f ↔ Q (f.app ⊤) := by + P f ↔ Q (f.appTop) := by rw [iff_of_source_openCover (P := P) (Scheme.coverOfIsIso.{u} (𝟙 _))] simp @@ -359,7 +365,7 @@ lemma containsIdentities (hP : RingHom.ContainsIdentities Q) : P.ContainsIdentit rw [IsLocalAtTarget.iff_of_iSup_eq_top (P := P) _ (iSup_affineOpens_eq_top _)] intro U have : IsAffine (𝟙 X ⁻¹ᵁ U.1) := U.2 - rw [morphismRestrict_id, iff_of_isAffine (P := P), Scheme.id_app] + rw [morphismRestrict_id, iff_of_isAffine (P := P), Scheme.id_appTop] apply hP variable (P) in @@ -504,7 +510,7 @@ lemma isStableUnderBaseChange (hP : RingHom.IsStableUnderBaseChange Q) : limit.lift_π, PullbackCone.mk_pt, PullbackCone.mk_π_app, Category.comp_id] apply this _ (comp_of_isOpenImmersion _ _ _ H) inferInstance rw [iff_of_isAffine (P := P)] at H ⊢ - exact hP.pullback_fst_app_top _ (isLocal_ringHomProperty P).respectsIso _ _ H + exact hP.pullback_fst_appTop _ (isLocal_ringHomProperty P).respectsIso _ _ H include Q in private lemma respects_isOpenImmersion_aux diff --git a/Mathlib/AlgebraicGeometry/Morphisms/Separated.lean b/Mathlib/AlgebraicGeometry/Morphisms/Separated.lean index a97b12f9fcc9c..c03365e68f13f 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/Separated.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/Separated.lean @@ -240,6 +240,16 @@ lemma ext_of_isDominant_of_isSeparated [IsReduced X] {f g : X ⟶ Y} rw [← cancel_epi (equalizer.ι f' g').left] exact congr($(equalizer.condition f' g').left) +variable (S) in +/-- +Suppose `X` is a reduced `S`-scheme and `Y` is a separated `S`-scheme. +For any `S`-morphisms `f g : X ⟶ Y`, `f = g` if `ι ≫ f = ι ≫ g` for some dominant `ι`. +-/ +lemma ext_of_isDominant_of_isSeparated' [X.Over S] [Y.Over S] [IsReduced X] [IsSeparated (Y ↘ S)] + {f g : X ⟶ Y} [f.IsOver S] [g.IsOver S] {W} (ι : W ⟶ X) [IsDominant ι] + (hU : ι ≫ f = ι ≫ g) : f = g := + ext_of_isDominant_of_isSeparated (Y ↘ S) (by simp) ι hU + namespace Scheme /-- A scheme `X` is separated if it is separated over `⊤_ Scheme`. -/ diff --git a/Mathlib/AlgebraicGeometry/Morphisms/SurjectiveOnStalks.lean b/Mathlib/AlgebraicGeometry/Morphisms/SurjectiveOnStalks.lean new file mode 100644 index 0000000000000..66aff1bb5a74d --- /dev/null +++ b/Mathlib/AlgebraicGeometry/Morphisms/SurjectiveOnStalks.lean @@ -0,0 +1,185 @@ +/- +Copyright (c) 2024 Andrew Yang. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Andrew Yang +-/ +import Mathlib.AlgebraicGeometry.Morphisms.RingHomProperties +import Mathlib.AlgebraicGeometry.PrimeSpectrum.TensorProduct +import Mathlib.Topology.LocalAtTarget + +/-! +# Morphisms surjective on stalks + +We define the classe of morphisms between schemes that are surjective on stalks. +We show that this class is stable under composition and base change. + +We also show that (`AlgebraicGeometry.SurjectiveOnStalks.isEmbedding_pullback`) +if `Y ⟶ S` is surjective on stalks, then for every `X ⟶ S`, `X ×ₛ Y` is a subset of +`X × Y` (cartesian product as topological spaces) with the induced topology. +-/ + +open CategoryTheory CategoryTheory.Limits Topology + +namespace AlgebraicGeometry + +universe u + +variable {X Y Z : Scheme.{u}} (f : X ⟶ Y) (g : Y ⟶ Z) + +/-- The class of morphisms `f : X ⟶ Y` between schemes such that +`𝒪_{Y, f x} ⟶ 𝒪_{X, x}` is surjective for all `x : X`. -/ +@[mk_iff] +class SurjectiveOnStalks : Prop where + surj_on_stalks : ∀ x, Function.Surjective (f.stalkMap x) + +theorem Scheme.Hom.stalkMap_surjective (f : X.Hom Y) [SurjectiveOnStalks f] (x) : + Function.Surjective (f.stalkMap x) := + SurjectiveOnStalks.surj_on_stalks x + +namespace SurjectiveOnStalks + +instance (priority := 900) [IsOpenImmersion f] : SurjectiveOnStalks f := + ⟨fun _ ↦ (ConcreteCategory.bijective_of_isIso _).2⟩ + +instance : MorphismProperty.IsMultiplicative @SurjectiveOnStalks where + id_mem _ := inferInstance + comp_mem {X Y Z} f g hf hg := by + refine ⟨fun x ↦ ?_⟩ + rw [Scheme.stalkMap_comp] + exact (hf.surj_on_stalks x).comp (hg.surj_on_stalks (f.base x)) + +instance comp {X Y Z : Scheme} (f : X ⟶ Y) (g : Y ⟶ Z) [SurjectiveOnStalks f] + [SurjectiveOnStalks g] : SurjectiveOnStalks (f ≫ g) := + MorphismProperty.IsStableUnderComposition.comp_mem f g inferInstance inferInstance + +lemma eq_stalkwise : + @SurjectiveOnStalks = stalkwise (Function.Surjective ·) := by + ext; exact surjectiveOnStalks_iff _ + +instance : IsLocalAtTarget @SurjectiveOnStalks := + eq_stalkwise ▸ stalkwiseIsLocalAtTarget_of_respectsIso RingHom.surjective_respectsIso + +instance : IsLocalAtSource @SurjectiveOnStalks := + eq_stalkwise ▸ stalkwise_isLocalAtSource_of_respectsIso RingHom.surjective_respectsIso + +lemma Spec_iff {R S : CommRingCat.{u}} {φ : R ⟶ S} : + SurjectiveOnStalks (Spec.map φ) ↔ RingHom.SurjectiveOnStalks φ := by + rw [eq_stalkwise, stalkwise_Spec_map_iff RingHom.surjective_respectsIso, + RingHom.SurjectiveOnStalks] + +instance : HasRingHomProperty @SurjectiveOnStalks RingHom.SurjectiveOnStalks := + eq_stalkwise ▸ .stalkwise RingHom.surjective_respectsIso + +variable {f} in +lemma iff_of_isAffine [IsAffine X] [IsAffine Y] : + SurjectiveOnStalks f ↔ RingHom.SurjectiveOnStalks (f.app ⊤) := by + rw [← Spec_iff, MorphismProperty.arrow_mk_iso_iff @SurjectiveOnStalks (arrowIsoSpecΓOfIsAffine f)] + +theorem of_comp [SurjectiveOnStalks (f ≫ g)] : SurjectiveOnStalks f := by + refine ⟨fun x ↦ ?_⟩ + have := (f ≫ g).stalkMap_surjective x + rw [Scheme.stalkMap_comp] at this + exact Function.Surjective.of_comp this + +instance stableUnderBaseChange : + MorphismProperty.IsStableUnderBaseChange @SurjectiveOnStalks := by + apply HasRingHomProperty.isStableUnderBaseChange + apply RingHom.IsStableUnderBaseChange.mk + · exact (HasRingHomProperty.isLocal_ringHomProperty @SurjectiveOnStalks).respectsIso + intros R S T _ _ _ _ _ H + exact H.baseChange + +/-- If `Y ⟶ S` is surjective on stalks, then for every `X ⟶ S`, `X ×ₛ Y` is a subset of +`X × Y` (cartesian product as topological spaces) with the induced topology. -/ +lemma isEmbedding_pullback {X Y S : Scheme.{u}} (f : X ⟶ S) (g : Y ⟶ S) [SurjectiveOnStalks g] : + IsEmbedding (fun x ↦ ((pullback.fst f g).base x, (pullback.snd f g).base x)) := by + let L := (fun x ↦ ((pullback.fst f g).base x, (pullback.snd f g).base x)) + have H : ∀ R A B (f' : Spec A ⟶ Spec R) (g' : Spec B ⟶ Spec R) (iX : Spec A ⟶ X) + (iY : Spec B ⟶ Y) (iS : Spec R ⟶ S) (e₁ e₂), IsOpenImmersion iX → IsOpenImmersion iY → + IsOpenImmersion iS → IsEmbedding (L ∘ (pullback.map f' g' f g iX iY iS e₁ e₂).base) := by + intro R A B f' g' iX iY iS e₁ e₂ _ _ _ + have H : SurjectiveOnStalks g' := + have : SurjectiveOnStalks (g' ≫ iS) := e₂ ▸ inferInstance + .of_comp _ iS + obtain ⟨φ, rfl⟩ : ∃ φ, Spec.map φ = f' := ⟨_, Spec.map_preimage _⟩ + obtain ⟨ψ, rfl⟩ : ∃ ψ, Spec.map ψ = g' := ⟨_, Spec.map_preimage _⟩ + letI := φ.toAlgebra + letI := ψ.toAlgebra + rw [HasRingHomProperty.Spec_iff (P := @SurjectiveOnStalks)] at H + convert ((iX.isOpenEmbedding.prodMap iY.isOpenEmbedding).isEmbedding.comp + (PrimeSpectrum.isEmbedding_tensorProductTo_of_surjectiveOnStalks R A B H)).comp + (Scheme.homeoOfIso (pullbackSpecIso R A B)).isEmbedding + ext1 x + obtain ⟨x, rfl⟩ := (Scheme.homeoOfIso (pullbackSpecIso R A B).symm).surjective x + simp only [Scheme.homeoOfIso_apply, Function.comp_apply] + ext + · simp only [← Scheme.comp_base_apply, pullback.lift_fst, Iso.symm_hom, Iso.inv_hom_id] + erw [← Scheme.comp_base_apply, pullbackSpecIso_inv_fst_assoc] + rfl + · simp only [← Scheme.comp_base_apply, pullback.lift_snd, Iso.symm_hom, Iso.inv_hom_id] + erw [← Scheme.comp_base_apply, pullbackSpecIso_inv_snd_assoc] + rfl + let 𝒰 := S.affineOpenCover.openCover + let 𝒱 (i) := ((𝒰.pullbackCover f).obj i).affineOpenCover.openCover + let 𝒲 (i) := ((𝒰.pullbackCover g).obj i).affineOpenCover.openCover + let U (ijk : Σ i, (𝒱 i).J × (𝒲 i).J) : TopologicalSpace.Opens (X.carrier × Y) := + ⟨{ P | P.1 ∈ ((𝒱 ijk.1).map ijk.2.1 ≫ (𝒰.pullbackCover f).map ijk.1).opensRange ∧ + P.2 ∈ ((𝒲 ijk.1).map ijk.2.2 ≫ (𝒰.pullbackCover g).map ijk.1).opensRange }, + (continuous_fst.1 _ ((𝒱 ijk.1).map ijk.2.1 ≫ + (𝒰.pullbackCover f).map ijk.1).opensRange.2).inter (continuous_snd.1 _ + ((𝒲 ijk.1).map ijk.2.2 ≫ (𝒰.pullbackCover g).map ijk.1).opensRange.2)⟩ + have : Set.range L ⊆ (iSup U : _) := by + simp only [Scheme.Cover.pullbackCover_J, Scheme.Cover.pullbackCover_obj, Set.range_subset_iff] + intro z + simp only [SetLike.mem_coe, TopologicalSpace.Opens.mem_iSup, Sigma.exists, Prod.exists] + obtain ⟨is, s, hsx⟩ := 𝒰.exists_eq (f.base ((pullback.fst f g).base z)) + have hsy : (𝒰.map is).base s = g.base ((pullback.snd f g).base z) := by + rwa [← Scheme.comp_base_apply, ← pullback.condition, Scheme.comp_base_apply] + obtain ⟨x : (𝒰.pullbackCover f).obj is, hx⟩ := + Scheme.IsJointlySurjectivePreserving.exists_preimage_fst_triplet_of_prop + (P := @IsOpenImmersion) inferInstance _ _ hsx.symm + obtain ⟨y : (𝒰.pullbackCover g).obj is, hy⟩ := + Scheme.IsJointlySurjectivePreserving.exists_preimage_fst_triplet_of_prop + (P := @IsOpenImmersion) inferInstance _ _ hsy.symm + obtain ⟨ix, x, rfl⟩ := (𝒱 is).exists_eq x + obtain ⟨iy, y, rfl⟩ := (𝒲 is).exists_eq y + refine ⟨is, ix, iy, ⟨x, hx⟩, ⟨y, hy⟩⟩ + let 𝓤 := (Scheme.Pullback.openCoverOfBase 𝒰 f g).bind + (fun i ↦ Scheme.Pullback.openCoverOfLeftRight (𝒱 i) (𝒲 i) _ _) + refine isEmbedding_of_iSup_eq_top_of_preimage_subset_range _ ?_ U this _ (fun i ↦ (𝓤.map i).base) + (fun i ↦ (𝓤.map i).continuous) ?_ ?_ + · fun_prop + · rintro i x ⟨⟨x₁, hx₁⟩, ⟨x₂, hx₂⟩⟩ + obtain ⟨x₁', hx₁'⟩ := + Scheme.IsJointlySurjectivePreserving.exists_preimage_fst_triplet_of_prop + (P := @IsOpenImmersion) inferInstance _ _ hx₁.symm + obtain ⟨x₂', hx₂'⟩ := + Scheme.IsJointlySurjectivePreserving.exists_preimage_fst_triplet_of_prop + (P := @IsOpenImmersion) inferInstance _ _ hx₂.symm + obtain ⟨z, hz⟩ := + Scheme.IsJointlySurjectivePreserving.exists_preimage_fst_triplet_of_prop + (P := @IsOpenImmersion) inferInstance _ _ (hx₁'.trans hx₂'.symm) + refine ⟨(pullbackFstFstIso _ _ _ _ _ _ (𝒰.map i.1) ?_ ?_).hom.base z, ?_⟩ + · simp [pullback.condition] + · simp [pullback.condition] + · dsimp only + rw [← hx₁', ← hz, ← Scheme.comp_base_apply] + erw [← Scheme.comp_base_apply] + congr 4 + apply pullback.hom_ext <;> simp [𝓤, ← pullback.condition, ← pullback.condition_assoc] + · intro i + have := H (S.affineOpenCover.obj i.1) (((𝒰.pullbackCover f).obj i.1).affineOpenCover.obj i.2.1) + (((𝒰.pullbackCover g).obj i.1).affineOpenCover.obj i.2.2) + ((𝒱 i.1).map i.2.1 ≫ 𝒰.pullbackHom f i.1) + ((𝒲 i.1).map i.2.2 ≫ 𝒰.pullbackHom g i.1) + ((𝒱 i.1).map i.2.1 ≫ (𝒰.pullbackCover f).map i.1) + ((𝒲 i.1).map i.2.2 ≫ (𝒰.pullbackCover g).map i.1) + (𝒰.map i.1) (by simp [pullback.condition]) (by simp [pullback.condition]) + inferInstance inferInstance inferInstance + convert this using 6 + apply pullback.hom_ext <;> + simp [𝓤, ← pullback.condition, ← pullback.condition_assoc, Scheme.Cover.pullbackHom] + +end SurjectiveOnStalks + +end AlgebraicGeometry diff --git a/Mathlib/AlgebraicGeometry/Morphisms/UnderlyingMap.lean b/Mathlib/AlgebraicGeometry/Morphisms/UnderlyingMap.lean index dbcc339026d05..065d25bd88b11 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/UnderlyingMap.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/UnderlyingMap.lean @@ -83,6 +83,18 @@ instance surjective_isLocalAtTarget : IsLocalAtTarget @Surjective := by obtain ⟨⟨y, _⟩, hy⟩ := hf i ⟨x, hxi⟩ exact ⟨y, congr(($hy).1)⟩ +@[simp] +lemma range_eq_univ [Surjective f] : Set.range f.base = Set.univ := by + simpa [Set.range_eq_univ] using f.surjective + +lemma range_eq_range_of_surjective {S : Scheme.{u}} (f : X ⟶ S) (g : Y ⟶ S) (e : X ⟶ Y) + [Surjective e] (hge : e ≫ g = f) : Set.range f.base = Set.range g.base := by + rw [← hge] + simp [Set.range_comp] + +lemma mem_range_iff_of_surjective {S : Scheme.{u}} (f : X ⟶ S) (g : Y ⟶ S) (e : X ⟶ Y) + [Surjective e] (hge : e ≫ g = f) (s : S) : s ∈ Set.range f.base ↔ s ∈ Set.range g.base := by + rw [range_eq_range_of_surjective f g e hge] end Surjective section Injective diff --git a/Mathlib/AlgebraicGeometry/Over.lean b/Mathlib/AlgebraicGeometry/Over.lean index c52efcbb93841..15349f1b13a3e 100644 --- a/Mathlib/AlgebraicGeometry/Over.lean +++ b/Mathlib/AlgebraicGeometry/Over.lean @@ -41,6 +41,17 @@ abbrev CanonicallyOver := CanonicallyOverClass X S `f.IsOver S` is the typeclass asserting `f` commutes with the structure morphisms. -/ abbrev Hom.IsOver (f : X.Hom Y) (S : Scheme.{u}) [X.Over S] [Y.Over S] := HomIsOver f S +@[simp] +lemma Hom.isOver_iff [X.Over S] [Y.Over S] {f : X ⟶ Y} : f.IsOver S ↔ f ≫ Y ↘ S = X ↘ S := + ⟨fun H ↦ H.1, fun h ↦ ⟨h⟩⟩ + /-! Also note the existence of `CategoryTheory.IsOverTower X Y S`. -/ +/-- Given `X.Over S`, this is the bundled object of `Over S`. -/ +abbrev asOver (X S : Scheme.{u}) [X.Over S] := OverClass.asOver X S + +/-- Given a morphism `X ⟶ Y` with `f.IsOver S`, this is the bundled morphism in `Over S`. -/ +abbrev Hom.asOver (f : X.Hom Y) (S : Scheme.{u}) [X.Over S] [Y.Over S] [f.IsOver S] := + OverClass.asOverHom S f + end AlgebraicGeometry.Scheme diff --git a/Mathlib/AlgebraicGeometry/PrimeSpectrum/Basic.lean b/Mathlib/AlgebraicGeometry/PrimeSpectrum/Basic.lean index 8121592d7b482..6a4899d2598b7 100644 --- a/Mathlib/AlgebraicGeometry/PrimeSpectrum/Basic.lean +++ b/Mathlib/AlgebraicGeometry/PrimeSpectrum/Basic.lean @@ -9,7 +9,7 @@ import Mathlib.RingTheory.Ideal.Over import Mathlib.RingTheory.KrullDimension.Basic import Mathlib.RingTheory.LocalRing.ResidueField.Defs import Mathlib.RingTheory.LocalRing.RingHom.Basic -import Mathlib.RingTheory.Localization.Away.Basic +import Mathlib.RingTheory.Localization.Away.Lemmas import Mathlib.Tactic.StacksAttribute import Mathlib.Topology.KrullDimension import Mathlib.Topology.Sober @@ -212,6 +212,31 @@ instance compactSpace : CompactSpace (PrimeSpectrum R) := by simp_rw [hI, ← zeroLocus_iSup, zeroLocus_empty_iff_eq_top, ← top_le_iff] at S_empty ⊢ exact Ideal.isCompactElement_top.exists_finset_of_le_iSup _ _ S_empty +/-- The prime spectrum of a semiring has discrete Zariski topology iff it is finite and +all primes are maximal. -/ +theorem discreteTopology_iff_finite_and_isPrime_imp_isMaximal : DiscreteTopology (PrimeSpectrum R) ↔ + Finite (PrimeSpectrum R) ∧ ∀ I : Ideal R, I.IsPrime → I.IsMaximal := + ⟨fun _ ↦ ⟨finite_of_compact_of_discrete, fun I hI ↦ (isClosed_singleton_iff_isMaximal ⟨I, hI⟩).mp + <| discreteTopology_iff_forall_isClosed.mp ‹_› _⟩, fun ⟨_, h⟩ ↦ .of_finite_of_isClosed_singleton + fun p ↦ (isClosed_singleton_iff_isMaximal p).mpr <| h _ p.2⟩ + +/-- The prime spectrum of a semiring has discrete Zariski topology iff there are only +finitely many maximal ideals and their intersection is contained in the nilradical. -/ +theorem discreteTopology_iff_finite_isMaximal_and_sInf_le_nilradical : + letI s := {I : Ideal R | I.IsMaximal} + DiscreteTopology (PrimeSpectrum R) ↔ Finite s ∧ sInf s ≤ nilradical R := + discreteTopology_iff_finite_and_isPrime_imp_isMaximal.trans <| by + rw [(equivSubtype R).finite_iff, ← Set.coe_setOf, Set.finite_coe_iff, Set.finite_coe_iff] + refine ⟨fun h ↦ ⟨h.1.subset fun _ h ↦ h.isPrime, nilradical_eq_sInf R ▸ sInf_le_sInf h.2⟩, + fun ⟨fin, le⟩ ↦ ?_⟩ + have hpm (I : Ideal R) (hI : I.IsPrime): I.IsMaximal := by + replace le := le.trans (nilradical_le_prime I) + rw [← fin.coe_toFinset, ← Finset.inf_id_eq_sInf, hI.inf_le'] at le + have ⟨M, hM, hMI⟩ := le + rw [fin.mem_toFinset] at hM + rwa [← hM.eq_of_le hI.1 hMI] + exact ⟨fin.subset hpm, hpm⟩ + section Comap variable {S' : Type*} [CommSemiring S'] @@ -501,6 +526,22 @@ lemma iSup_basicOpen_eq_top_iff' {s : Set R} : conv_rhs => rw [← Subtype.range_val (s := s), ← iSup_basicOpen_eq_top_iff] simp +theorem isLocalization_away_iff_atPrime_of_basicOpen_eq_singleton [Algebra R S] + {f : R} {p : PrimeSpectrum R} (h : (basicOpen f).1 = {p}) : + IsLocalization.Away f S ↔ IsLocalization.AtPrime S p.1 := + have : IsLocalization.AtPrime (Localization.Away f) p.1 := by + refine .of_le_of_exists_dvd (Submonoid.powers f) _ + (Submonoid.powers_le.mpr <| by apply h ▸ Set.mem_singleton p) fun r hr ↦ ?_ + contrapose! hr + simp_rw [← Ideal.mem_span_singleton] at hr + have ⟨q, prime, le, disj⟩ := Ideal.exists_le_prime_disjoint (Ideal.span {r}) + (Submonoid.powers f) (Set.disjoint_right.mpr hr) + have : ⟨q, prime⟩ ∈ (basicOpen f).1 := Set.disjoint_right.mp disj (Submonoid.mem_powers f) + rw [h, Set.mem_singleton_iff] at this + rw [← this] + exact not_not.mpr (q.span_singleton_le_iff_mem.mp le) + IsLocalization.isLocalization_iff_of_isLocalization _ _ (Localization.Away f) + end BasicOpen section Order @@ -669,14 +710,30 @@ lemma isCompact_isOpen_iff {s : Set (PrimeSpectrum R)} : fun ⟨s, e⟩ ↦ ⟨s, s.finite_toSet, by simpa using e.symm⟩⟩ lemma isCompact_isOpen_iff_ideal {s : Set (PrimeSpectrum R)} : - IsCompact s ∧ IsOpen s ↔ - ∃ I : Ideal R, I.FG ∧ (PrimeSpectrum.zeroLocus (I : Set R))ᶜ = s := by + IsCompact s ∧ IsOpen s ↔ ∃ I : Ideal R, I.FG ∧ (zeroLocus I)ᶜ = s := by rw [isCompact_isOpen_iff] exact ⟨fun ⟨s, e⟩ ↦ ⟨.span s, ⟨s, rfl⟩, by simpa using e⟩, fun ⟨I, ⟨s, hs⟩, e⟩ ↦ ⟨s, by simpa [hs.symm] using e⟩⟩ -lemma exists_idempotent_basicOpen_eq_of_is_clopen {s : Set (PrimeSpectrum R)} - (hs : IsClopen s) : ∃ e : R, IsIdempotentElem e ∧ s = basicOpen e := by +lemma basicOpen_injOn_isIdempotentElem : + {e : R | IsIdempotentElem e}.InjOn basicOpen := fun x hx y hy eq ↦ by + by_contra! ne + wlog ne' : x * y ≠ x generalizing x y + · apply this y hy x hx eq.symm ne.symm + rwa [mul_comm, of_not_not ne'] + have : x ∉ Ideal.span {y} := fun mem ↦ ne' <| by + obtain ⟨r, rfl⟩ := Ideal.mem_span_singleton'.mp mem + rw [mul_assoc, hy] + have ⟨p, prime, le, nmem⟩ := Ideal.exists_le_prime_nmem_of_isIdempotentElem _ x hx this + exact ne_of_mem_of_not_mem' (a := ⟨p, prime⟩) nmem + (not_not.mpr <| p.span_singleton_le_iff_mem.mp le) eq + +@[stacks 00EE] +lemma existsUnique_idempotent_basicOpen_eq_of_isClopen {s : Set (PrimeSpectrum R)} + (hs : IsClopen s) : ∃! e : R, IsIdempotentElem e ∧ s = basicOpen e := by + refine exists_unique_of_exists_of_unique ?_ ?_; swap + · rintro x y ⟨hx, rfl⟩ ⟨hy, eq⟩ + exact basicOpen_injOn_isIdempotentElem hx hy (SetLike.ext' eq) cases subsingleton_or_nontrivial R · exact ⟨0, Subsingleton.elim _ _, Subsingleton.elim _ _⟩ obtain ⟨I, hI, hI'⟩ := isCompact_isOpen_iff_ideal.mp ⟨hs.1.isCompact, hs.2⟩ @@ -712,6 +769,13 @@ lemma exists_idempotent_basicOpen_eq_of_is_clopen {s : Set (PrimeSpectrum R)} exact PrimeSpectrum.zeroLocus_anti_mono (Set.singleton_subset_iff.mpr <| Ideal.pow_le_self hnz hx) +lemma exists_idempotent_basicOpen_eq_of_isClopen {s : Set (PrimeSpectrum R)} + (hs : IsClopen s) : ∃ e : R, IsIdempotentElem e ∧ s = basicOpen e := + (existsUnique_idempotent_basicOpen_eq_of_isClopen hs).exists + +@[deprecated (since := "2024-11-11")] +alias exists_idempotent_basicOpen_eq_of_is_clopen := exists_idempotent_basicOpen_eq_of_isClopen + section IsIntegral open Polynomial @@ -939,7 +1003,10 @@ section Idempotent variable {R} [CommRing R] -lemma PrimeSpectrum.basicOpen_eq_zeroLocus_of_isIdempotentElem +namespace PrimeSpectrum + +@[stacks 00EC] +lemma basicOpen_eq_zeroLocus_of_isIdempotentElem (e : R) (he : IsIdempotentElem e) : basicOpen e = zeroLocus {1 - e} := by ext p @@ -951,24 +1018,123 @@ lemma PrimeSpectrum.basicOpen_eq_zeroLocus_of_isIdempotentElem rw [Ideal.eq_top_iff_one, ← sub_add_cancel 1 e] exact add_mem h₁ h₂ -lemma PrimeSpectrum.zeroLocus_eq_basicOpen_of_isIdempotentElem +@[stacks 00EC] +lemma zeroLocus_eq_basicOpen_of_isIdempotentElem (e : R) (he : IsIdempotentElem e) : zeroLocus {e} = basicOpen (1 - e) := by rw [basicOpen_eq_zeroLocus_of_isIdempotentElem _ he.one_sub, sub_sub_cancel] -lemma PrimeSpectrum.isClopen_iff {s : Set (PrimeSpectrum R)} : +lemma isClopen_iff {s : Set (PrimeSpectrum R)} : IsClopen s ↔ ∃ e : R, IsIdempotentElem e ∧ s = basicOpen e := by - refine ⟨PrimeSpectrum.exists_idempotent_basicOpen_eq_of_is_clopen, ?_⟩ + refine ⟨exists_idempotent_basicOpen_eq_of_isClopen, ?_⟩ rintro ⟨e, he, rfl⟩ refine ⟨?_, (basicOpen e).2⟩ rw [PrimeSpectrum.basicOpen_eq_zeroLocus_of_isIdempotentElem e he] exact isClosed_zeroLocus _ -lemma PrimeSpectrum.isClopen_iff_zeroLocus {s : Set (PrimeSpectrum R)} : - IsClopen s ↔ ∃ e : R, IsIdempotentElem e ∧ s = zeroLocus {e} := by - rw [isClopen_iff] - refine ⟨fun ⟨e, he, h⟩ ↦ ⟨1 - e, he.one_sub, - h.trans (basicOpen_eq_zeroLocus_of_isIdempotentElem e he)⟩, fun ⟨e, he, h⟩ ↦ - ⟨1 - e, he.one_sub, h.trans (zeroLocus_eq_basicOpen_of_isIdempotentElem e he)⟩⟩ +lemma isClopen_iff_zeroLocus {s : Set (PrimeSpectrum R)} : + IsClopen s ↔ ∃ e : R, IsIdempotentElem e ∧ s = zeroLocus {e} := + isClopen_iff.trans <| ⟨fun ⟨e, he, h⟩ ↦ ⟨1 - e, he.one_sub, + h.trans (basicOpen_eq_zeroLocus_of_isIdempotentElem e he)⟩, + fun ⟨e, he, h⟩ ↦ ⟨1 - e, he.one_sub, h.trans (zeroLocus_eq_basicOpen_of_isIdempotentElem e he)⟩⟩ + +open TopologicalSpace (Clopens Opens) + +/-- Clopen subsets in the prime spectrum of a commutative ring are in 1-1 correspondence +with idempotent elements in the ring. -/ +@[stacks 00EE] +def isIdempotentElemEquivClopens : + {e : R | IsIdempotentElem e} ≃ Clopens (PrimeSpectrum R) := + .ofBijective (fun e ↦ ⟨basicOpen e.1, isClopen_iff.mpr ⟨_, e.2, rfl⟩⟩) + ⟨fun x y eq ↦ Subtype.ext (basicOpen_injOn_isIdempotentElem x.2 y.2 <| + SetLike.ext' (congr_arg (·.1) eq)), fun s ↦ + have ⟨e, he, h⟩ := exists_idempotent_basicOpen_eq_of_isClopen s.2 + ⟨⟨e, he⟩, Clopens.ext h.symm⟩⟩ + +lemma basicOpen_isIdempotentElemEquivClopens_symm (s) : + basicOpen (isIdempotentElemEquivClopens (R := R).symm s).1 = s.toOpens := + Opens.ext <| congr_arg (·.1) (isIdempotentElemEquivClopens.apply_symm_apply s) + +lemma coe_isIdempotentElemEquivClopens_apply (e) : + (isIdempotentElemEquivClopens e : Set (PrimeSpectrum R)) = basicOpen (e.1 : R) := rfl + +lemma isIdempotentElemEquivClopens_apply_toOpens (e) : + (isIdempotentElemEquivClopens e).toOpens = basicOpen (e.1 : R) := rfl + +lemma isIdempotentElemEquivClopens_mul (e₁ e₂ : {e : R | IsIdempotentElem e}) : + isIdempotentElemEquivClopens ⟨_, e₁.2.mul e₂.2⟩ = + isIdempotentElemEquivClopens e₁ ⊓ isIdempotentElemEquivClopens e₂ := + Clopens.ext <| by simp_rw [coe_isIdempotentElemEquivClopens_apply, basicOpen_mul]; rfl + +lemma isIdempotentElemEquivClopens_one_sub (e : {e : R | IsIdempotentElem e}) : + isIdempotentElemEquivClopens ⟨_, e.2.one_sub⟩ = (isIdempotentElemEquivClopens e)ᶜ := + SetLike.ext' <| by + simp_rw [Clopens.coe_compl, coe_isIdempotentElemEquivClopens_apply] + rw [basicOpen_eq_zeroLocus_compl, basicOpen_eq_zeroLocus_of_isIdempotentElem _ e.2] + +lemma isIdempotentElemEquivClopens_symm_inf (s₁ s₂) : + letI e := isIdempotentElemEquivClopens (R := R).symm + e (s₁ ⊓ s₂) = ⟨_, (e s₁).2.mul (e s₂).2⟩ := + isIdempotentElemEquivClopens.symm_apply_eq.mpr <| by + simp_rw [isIdempotentElemEquivClopens_mul, Equiv.apply_symm_apply] + +lemma isIdempotentElemEquivClopens_symm_compl (s : Clopens (PrimeSpectrum R)) : + isIdempotentElemEquivClopens.symm sᶜ = ⟨_, (isIdempotentElemEquivClopens.symm s).2.one_sub⟩ := + isIdempotentElemEquivClopens.symm_apply_eq.mpr <| by + rw [isIdempotentElemEquivClopens_one_sub, Equiv.apply_symm_apply] + +lemma isIdempotentElemEquivClopens_symm_top : + isIdempotentElemEquivClopens.symm ⊤ = ⟨(1 : R), .one⟩ := + isIdempotentElemEquivClopens.symm_apply_eq.mpr <| Clopens.ext <| by + rw [coe_isIdempotentElemEquivClopens_apply, basicOpen_one]; rfl + +lemma isIdempotentElemEquivClopens_symm_bot : + isIdempotentElemEquivClopens.symm ⊥ = ⟨(0 : R), .zero⟩ := + isIdempotentElemEquivClopens.symm_apply_eq.mpr <| Clopens.ext <| by + rw [coe_isIdempotentElemEquivClopens_apply, basicOpen_zero]; rfl + +lemma isIdempotentElemEquivClopens_symm_sup (s₁ s₂ : Clopens (PrimeSpectrum R)) : + letI e := isIdempotentElemEquivClopens (R := R).symm + e (s₁ ⊔ s₂) = ⟨_, (e s₁).2.add_sub_mul (e s₂).2⟩ := Subtype.ext <| by + rw [← compl_compl (_ ⊔ _), compl_sup, isIdempotentElemEquivClopens_symm_compl] + simp_rw [isIdempotentElemEquivClopens_symm_inf, isIdempotentElemEquivClopens_symm_compl] + ring + +end PrimeSpectrum + +variable [DiscreteTopology (PrimeSpectrum R)] +open PrimeSpectrum + +variable (R) in +lemma RingHom.toLocalizationIsMaximal_surjective_of_discreteTopology : + Function.Surjective (RingHom.toLocalizationIsMaximal R) := fun x ↦ by + let idem I := isIdempotentElemEquivClopens (R := R).symm ⟨{I}, isClopen_discrete _⟩ + let ideal I := Ideal.span {1 - (idem I).1} + let toSpec (I : {I : Ideal R | I.IsMaximal}) : PrimeSpectrum R := ⟨I.1, I.2.isPrime⟩ + have loc I : IsLocalization.AtPrime (R ⧸ ideal I) I.1 := by + rw [← isLocalization_away_iff_atPrime_of_basicOpen_eq_singleton] + exacts [IsLocalization.Away.quotient_of_isIdempotentElem (idem I).2, + congr_arg (·.1) (basicOpen_isIdempotentElemEquivClopens_symm ⟨{I}, isClopen_discrete _⟩)] + let equiv I := IsLocalization.algEquiv I.1.primeCompl (Localization.AtPrime I.1) (R ⧸ ideal I) + have := (discreteTopology_iff_finite_isMaximal_and_sInf_le_nilradical.mp ‹_›).1 + have ⟨r, hr⟩ := Ideal.pi_quotient_surjective ?_ fun I ↦ equiv (toSpec I) (x I) + · refine ⟨r, funext fun I ↦ (equiv <| toSpec I).injective ?_⟩ + rw [← hr]; exact (equiv _).commutes r + refine fun I J ne ↦ Ideal.isCoprime_iff_exists.mpr ?_ + have := ((idem <| toSpec I).2.mul (idem <| toSpec J).2).eq_zero_of_isNilpotent <| by + simp_rw [← basicOpen_eq_bot_iff, basicOpen_mul, SetLike.ext'_iff, idem, + TopologicalSpace.Opens.coe_inf, basicOpen_isIdempotentElemEquivClopens_symm] + exact Set.singleton_inter_eq_empty.mpr fun h ↦ ne (Subtype.ext <| congr_arg (·.1) h) + simp_rw [ideal, Ideal.mem_span_singleton', exists_exists_eq_and] + exact ⟨1, idem (toSpec I), by simpa [mul_sub]⟩ + +/-- If the prime spectrum of a commutative ring R has discrete Zariski topology, then R is +canonically isomorphic to the product of its localizations at the (finitely many) maximal ideals. -/ +@[stacks 00JA +"See also `PrimeSpectrum.discreteTopology_iff_finite_isMaximal_and_sInf_le_nilradical`."] +def RingHom.toLocalizationIsMaximalEquiv : R ≃+* + Π I : {I : Ideal R // I.IsMaximal}, haveI : I.1.IsMaximal := I.2; Localization.AtPrime I.1 := + .ofBijective _ ⟨RingHom.toLocalizationIsMaximal_injective R, + RingHom.toLocalizationIsMaximal_surjective_of_discreteTopology R⟩ end Idempotent diff --git a/Mathlib/AlgebraicGeometry/RationalMap.lean b/Mathlib/AlgebraicGeometry/RationalMap.lean index aca42607f4a77..e9894ddfbcd61 100644 --- a/Mathlib/AlgebraicGeometry/RationalMap.lean +++ b/Mathlib/AlgebraicGeometry/RationalMap.lean @@ -5,6 +5,7 @@ Authors: Andrew Yang -/ import Mathlib.AlgebraicGeometry.SpreadingOut import Mathlib.AlgebraicGeometry.FunctionField +import Mathlib.AlgebraicGeometry.Morphisms.Separated /-! # Rational maps between schemes @@ -17,10 +18,12 @@ import Mathlib.AlgebraicGeometry.FunctionField Two partial maps are equivalent if they are equal on a dense open subscheme. * `AlgebraicGeometry.Scheme.RationalMap`: A rational map from `X` to `Y` (`X ⤏ Y`) is an equivalence class of partial maps. -* `AlgebraicGeometry.Scheme.RationalMap.equivFunctionField`: +* `AlgebraicGeometry.Scheme.RationalMap.equivFunctionFieldOver`: Given `S`-schemes `X` and `Y` such that `Y` is locally of finite type and `X` is integral, `S`-morphisms `Spec K(X) ⟶ Y` correspond bijectively to `S`-rational maps from `X` to `Y`. - +* `AlgebraicGeometry.Scheme.RationalMap.toPartialMap`: + If `X` is integral and `Y` is separated, then any `f : X ⤏ Y` can be realized as a partial + map on `f.domain`, the domain of definition of `f`. -/ universe u @@ -44,6 +47,11 @@ structure PartialMap (X Y : Scheme.{u}) where /-- The underlying morphism of a partial map. -/ hom : ↑domain ⟶ Y +variable (S) in +/-- A partial map is a `S`-map if the underlying morphism is. -/ +abbrev PartialMap.IsOver [X.Over S] [Y.Over S] (f : X.PartialMap Y) := + f.hom.IsOver S + namespace PartialMap lemma ext_iff (f g : X.PartialMap Y) : @@ -64,7 +72,7 @@ lemma ext (f g : X.PartialMap Y) (e : f.domain = g.domain) exact ⟨e, H⟩ /-- The restriction of a partial map to a smaller domain. -/ -@[simps hom, simps (config := .lemmasOnly) domain] +@[simps hom domain] noncomputable def restrict (f : X.PartialMap Y) (U : X.Opens) (hU : Dense (U : Set X)) (hU' : U ≤ f.domain) : X.PartialMap Y where @@ -93,6 +101,10 @@ lemma restrict_restrict_hom (f : X.PartialMap Y) ((f.restrict U hU hU').restrict V hV hV').hom = (f.restrict V hV (hV'.trans hU')).hom := by simp +instance [X.Over S] [Y.Over S] (f : X.PartialMap Y) [f.IsOver S] + (U : X.Opens) (hU : Dense (U : Set X)) (hU' : U ≤ f.domain) : + (f.restrict U hU hU').IsOver S where + /-- The composition of a partial map and a morphism on the right. -/ @[simps] def compHom (f : X.PartialMap Y) (g : Y ⟶ Z) : X.PartialMap Z where @@ -100,11 +112,24 @@ def compHom (f : X.PartialMap Y) (g : Y ⟶ Z) : X.PartialMap Z where dense_domain := f.dense_domain hom := f.hom ≫ g +instance [X.Over S] [Y.Over S] [Z.Over S] (f : X.PartialMap Y) (g : Y ⟶ Z) + [f.IsOver S] [g.IsOver S] : (f.compHom g).IsOver S where + /-- A scheme morphism as a partial map. -/ @[simps] def _root_.AlgebraicGeometry.Scheme.Hom.toPartialMap (f : X.Hom Y) : X.PartialMap Y := ⟨⊤, dense_univ, X.topIso.hom ≫ f⟩ +instance [X.Over S] [Y.Over S] (f : X ⟶ Y) [f.IsOver S] : f.toPartialMap.IsOver S where + +lemma isOver_iff [X.Over S] [Y.Over S] {f : X.PartialMap Y} : + f.IsOver S ↔ (f.compHom (Y ↘ S)).hom = f.domain.ι ≫ X ↘ S := by + simp + +lemma isOver_iff_eq_restrict [X.Over S] [Y.Over S] {f : X.PartialMap Y} : + f.IsOver S ↔ f.compHom (Y ↘ S) = (X ↘ S).toPartialMap.restrict _ f.dense_domain (by simp) := by + simp [isOver_iff, PartialMap.ext_iff] + /-- If `x` is in the domain of a partial map `f`, then `f` restricts to a map from `Spec 𝒪_x`. -/ noncomputable def fromSpecStalkOfMem (f : X.PartialMap Y) {x} (hx : x ∈ f.domain) : @@ -230,6 +255,58 @@ lemma equiv_of_fromSpecStalkOfMem_eq [IrreducibleSpace X] simpa only [fromSpecStalkOfMem, restrict_domain, Opens.fromSpecStalkOfMem, Spec.map_inv, restrict_hom, Category.assoc, IsIso.eq_inv_comp, IsIso.hom_inv_id_assoc] using H +instance (U : X.Opens) [IsReduced X] : IsReduced U := isReduced_of_isOpenImmersion U.ι + +lemma Opens.isDominant_ι {U : X.Opens} (hU : Dense (X := X) U) : IsDominant U.ι := + ⟨by simpa [DenseRange] using hU⟩ + +lemma Opens.isDominant_homOfLE {U V : X.Opens} (hU : Dense (X := X) U) (hU' : U ≤ V) : + IsDominant (X.homOfLE hU') := + have : IsDominant (X.homOfLE hU' ≫ Opens.ι _) := by simpa using Opens.isDominant_ι hU + IsDominant.of_comp_of_isOpenImmersion (g := Opens.ι _) _ + +/-- Two partial maps from reduced schemes to separated schemes are equivalent if and only if +they are equal on **any** open dense subset. -/ +lemma equiv_iff_of_isSeparated_of_le [X.Over S] [Y.Over S] [IsReduced X] + [IsSeparated (Y ↘ S)] {f g : X.PartialMap Y} [f.IsOver S] [g.IsOver S] + {W : X.Opens} (hW : Dense (X := X) W) (hWl : W ≤ f.domain) (hWr : W ≤ g.domain) : f.equiv g ↔ + (f.restrict W hW hWl).hom = (g.restrict W hW hWr).hom := by + refine ⟨fun ⟨V, hV, hVl, hVr, e⟩ ↦ ?_, fun e ↦ ⟨_, _, _, _, e⟩⟩ + have : IsDominant (X.homOfLE (inf_le_left : W ⊓ V ≤ W)) := + Opens.isDominant_homOfLE (hW.inter_of_isOpen_left hV W.2) _ + apply ext_of_isDominant_of_isSeparated' S (X.homOfLE (inf_le_left : W ⊓ V ≤ W)) + simpa using congr(X.homOfLE (inf_le_right : W ⊓ V ≤ V) ≫ $e) + +/-- Two partial maps from reduced schemes to separated schemes are equivalent if and only if +they are equal on the intersection of the domains. -/ +lemma equiv_iff_of_isSeparated [X.Over S] [Y.Over S] [IsReduced X] + [IsSeparated (Y ↘ S)] {f g : X.PartialMap Y} + [f.IsOver S] [g.IsOver S] : f.equiv g ↔ + (f.restrict _ (f.2.inter_of_isOpen_left g.2 f.domain.2) inf_le_left).hom = + (g.restrict _ (f.2.inter_of_isOpen_left g.2 f.domain.2) inf_le_right).hom := + equiv_iff_of_isSeparated_of_le (S := S) _ _ _ + +/-- Two partial maps from reduced schemes to separated schemes with the same domain are equivalent +if and only if they are equal. -/ +lemma equiv_iff_of_domain_eq_of_isSeparated [X.Over S] [Y.Over S] [IsReduced X] + [IsSeparated (Y ↘ S)] {f g : X.PartialMap Y} (hfg : f.domain = g.domain) + [f.IsOver S] [g.IsOver S] : f.equiv g ↔ f = g := by + rw [equiv_iff_of_isSeparated_of_le (S := S) f.dense_domain le_rfl hfg.le] + obtain ⟨Uf, _, f⟩ := f + obtain ⟨Ug, _, g⟩ := g + obtain rfl : Uf = Ug := hfg + simp + +/-- A partial map from a reduced scheme to a separated scheme is equivalent to a morphism +if and only if it is equal to the restriction of the morphism. -/ +lemma equiv_toPartialMap_iff_of_isSeparated [X.Over S] [Y.Over S] [IsReduced X] + [IsSeparated (Y ↘ S)] {f : X.PartialMap Y} {g : X ⟶ Y} + [f.IsOver S] [g.IsOver S] : f.equiv g.toPartialMap ↔ + f.hom = f.domain.ι ≫ g := by + rw [equiv_iff_of_isSeparated (S := S), ← cancel_epi (X.isoOfEq (inf_top_eq f.domain)).hom] + simp + rfl + end PartialMap /-- A rational map from `X` to `Y` (`X ⤏ Y`) is an equivalence class of partial maps, @@ -246,6 +323,11 @@ def PartialMap.toRationalMap (f : X.PartialMap Y) : X ⤏ Y := Quotient.mk _ f /-- A scheme morphism as a rational map. -/ abbrev Hom.toRationalMap (f : X.Hom Y) : X ⤏ Y := f.toPartialMap.toRationalMap +variable (S) in +/-- A rational map is a `S`-map if some partial map in the equivalence class is a `S`-map. -/ +class RationalMap.IsOver [X.Over S] [Y.Over S] (f : X ⤏ Y) : Prop where + exists_partialMap_over : ∃ g : X.PartialMap Y, g.IsOver S ∧ g.toRationalMap = f + lemma PartialMap.toRationalMap_surjective : Function.Surjective (@toRationalMap X Y) := Quotient.exists_rep @@ -262,6 +344,14 @@ lemma PartialMap.restrict_toRationalMap (f : X.PartialMap Y) (U : X.Opens) (f.restrict U hU hU').toRationalMap = f.toRationalMap := toRationalMap_eq_iff.mpr (f.restrict_equiv U hU hU') +instance [X.Over S] [Y.Over S] (f : X.PartialMap Y) [f.IsOver S] : f.toRationalMap.IsOver S := + ⟨f, ‹_›, rfl⟩ + +variable (S) in +lemma RationalMap.exists_partialMap_over [X.Over S] [Y.Over S] (f : X ⤏ Y) [f.IsOver S] : + ∃ g : X.PartialMap Y, g.IsOver S ∧ g.toRationalMap = f := + IsOver.exists_partialMap_over + /-- The composition of a rational map and a morphism on the right. -/ def RationalMap.compHom (f : X ⤏ Y) (g : Y ⟶ Z) : X ⤏ Z := by refine Quotient.map (PartialMap.compHom · g) ?_ f @@ -275,6 +365,42 @@ def RationalMap.compHom (f : X ⤏ Y) (g : Y ⟶ Z) : X ⤏ Z := by lemma RationalMap.compHom_toRationalMap (f : X.PartialMap Y) (g : Y ⟶ Z) : (f.compHom g).toRationalMap = f.toRationalMap.compHom g := rfl +instance [X.Over S] [Y.Over S] [Z.Over S] (f : X ⤏ Y) (g : Y ⟶ Z) + [f.IsOver S] [g.IsOver S] : (f.compHom g).IsOver S where + exists_partialMap_over := by + obtain ⟨f, hf, rfl⟩ := f.exists_partialMap_over S + exact ⟨f.compHom g, inferInstance, rfl⟩ + +variable (S) in +lemma PartialMap.exists_restrict_isOver [X.Over S] [Y.Over S] (f : X.PartialMap Y) + [f.toRationalMap.IsOver S] : ∃ U hU hU', (f.restrict U hU hU').IsOver S := by + obtain ⟨f', hf₁, hf₂⟩ := RationalMap.IsOver.exists_partialMap_over (S := S) (f := f.toRationalMap) + obtain ⟨U, hU, hUl, hUr, e⟩ := PartialMap.toRationalMap_eq_iff.mp hf₂ + exact ⟨U, hU, hUr, by rw [IsOver, ← e]; infer_instance⟩ + +lemma RationalMap.isOver_iff [X.Over S] [Y.Over S] {f : X ⤏ Y} : + f.IsOver S ↔ f.compHom (Y ↘ S) = (X ↘ S).toRationalMap := by + constructor + · intro h + obtain ⟨g, hg, e⟩ := f.exists_partialMap_over S + rw [← e, Hom.toRationalMap, ← compHom_toRationalMap, PartialMap.isOver_iff_eq_restrict.mp hg, + PartialMap.restrict_toRationalMap] + · intro e + obtain ⟨f, rfl⟩ := PartialMap.toRationalMap_surjective f + obtain ⟨U, hU, hUl, hUr, e⟩ := PartialMap.toRationalMap_eq_iff.mp e + exact ⟨⟨f.restrict U hU hUl, by simpa using e, by simp⟩⟩ + +lemma PartialMap.isOver_toRationalMap_iff_of_isSeparated [X.Over S] [Y.Over S] [IsReduced X] + [S.IsSeparated] {f : X.PartialMap Y} : + f.toRationalMap.IsOver S ↔ f.IsOver S := by + refine ⟨fun _ ↦ ?_, fun _ ↦ inferInstance⟩ + obtain ⟨U, hU, hU', H⟩ := f.exists_restrict_isOver (S := S) + rw [isOver_iff] + have : IsDominant (X.homOfLE hU') := Opens.isDominant_homOfLE hU _ + exact ext_of_isDominant (ι := X.homOfLE hU') (by simpa using H.1) + +section functionField + /-- A rational map restricts to a map from `Spec K(X)`. -/ noncomputable def RationalMap.fromFunctionField [IrreducibleSpace X] (f : X ⤏ Y) : @@ -328,6 +454,94 @@ def RationalMap.equivFunctionField [IsIntegral X] [LocallyOfFiniteType sY] : (ofFunctionField sX sY f.1.fromFunctionField _) f (RationalMap.fromFunctionField_ofFunctionField _ _ _ _)) +/-- +Given `S`-schemes `X` and `Y` such that `Y` is locally of finite type and `X` is integral, +`S`-morphisms `Spec K(X) ⟶ Y` correspond bijectively to `S`-rational maps from `X` to `Y`. +-/ +noncomputable +def RationalMap.equivFunctionFieldOver [X.Over S] [Y.Over S] [IsIntegral X] + [LocallyOfFiniteType (Y ↘ S)] : + { f : Spec X.functionField ⟶ Y // f.IsOver S } ≃ { f : X ⤏ Y // f.IsOver S } := + ((Equiv.subtypeEquivProp (by simp only [Hom.isOver_iff]; rfl)).trans + (RationalMap.equivFunctionField (X ↘ S) (Y ↘ S))).trans + (Equiv.subtypeEquivProp (by ext f; rw [RationalMap.isOver_iff])) + +end functionField + +section domain + +/-- The domain of definition of a rational map. -/ +def RationalMap.domain (f : X ⤏ Y) : X.Opens := + sSup { PartialMap.domain g | (g) (_ : g.toRationalMap = f) } + +lemma PartialMap.le_domain_toRationalMap (f : X.PartialMap Y) : + f.domain ≤ f.toRationalMap.domain := + le_sSup ⟨f, rfl, rfl⟩ + +lemma RationalMap.mem_domain {f : X ⤏ Y} {x} : + x ∈ f.domain ↔ ∃ g : X.PartialMap Y, x ∈ g.domain ∧ g.toRationalMap = f := + TopologicalSpace.Opens.mem_sSup.trans (by simp [@and_comm (x ∈ _)]) + +lemma RationalMap.dense_domain (f : X ⤏ Y) : Dense (X := X) f.domain := + f.inductionOn (fun g ↦ g.dense_domain.mono g.le_domain_toRationalMap) + +/-- The open cover of the domain of `f : X ⤏ Y`, +consisting of all the domains of the partial maps in the equivalence class. -/ +noncomputable +def RationalMap.openCoverDomain (f : X ⤏ Y) : f.domain.toScheme.OpenCover where + J := { PartialMap.domain g | (g) (_ : g.toRationalMap = f) } + obj U := U.1.toScheme + map U := X.homOfLE (le_sSup U.2) + f x := ⟨_, (TopologicalSpace.Opens.mem_sSup.mp x.2).choose_spec.1⟩ + covers x := ⟨⟨x.1, (TopologicalSpace.Opens.mem_sSup.mp x.2).choose_spec.2⟩, Subtype.ext (by simp)⟩ + +/-- If `f : X ⤏ Y` is a rational map from a reduced scheme to a separated scheme, +then `f` can be represented as a partial map on its domain of definition. -/ +noncomputable +def RationalMap.toPartialMap [IsReduced X] [Y.IsSeparated] (f : X ⤏ Y) : X.PartialMap Y := by + refine ⟨f.domain, f.dense_domain, f.openCoverDomain.glueMorphisms + (fun x ↦ (X.isoOfEq x.2.choose_spec.2).inv ≫ x.2.choose.hom) ?_⟩ + intros x y + let g (x : f.openCoverDomain.J) := x.2.choose + have hg₁ (x) : (g x).toRationalMap = f := x.2.choose_spec.1 + have hg₂ (x) : (g x).domain = x.1 := x.2.choose_spec.2 + refine (cancel_epi (isPullback_opens_inf_le (le_sSup x.2) (le_sSup y.2)).isoPullback.hom).mp ?_ + simp only [openCoverDomain, IsPullback.isoPullback_hom_fst_assoc, + IsPullback.isoPullback_hom_snd_assoc] + show _ ≫ _ ≫ (g x).hom = _ ≫ _ ≫ (g y).hom + simp_rw [← cancel_epi (X.isoOfEq congr($(hg₂ x) ⊓ $(hg₂ y))).hom, ← Category.assoc] + convert (PartialMap.equiv_iff_of_isSeparated (S := ⊤_ _) (f := g x) (g := g y)).mp ?_ using 1 + · dsimp; congr 1; simp [← cancel_mono (Opens.ι _)] + · dsimp; congr 1; simp [← cancel_mono (Opens.ι _)] + · rw [← PartialMap.toRationalMap_eq_iff, hg₁, hg₁] + +lemma PartialMap.toPartialMap_toRationalMap_restrict [IsReduced X] [Y.IsSeparated] + (f : X.PartialMap Y) : (f.toRationalMap.toPartialMap.restrict _ f.dense_domain + f.le_domain_toRationalMap).hom = f.hom := by + dsimp [RationalMap.toPartialMap] + refine (f.toRationalMap.openCoverDomain.ι_glueMorphisms _ _ ⟨_, f, rfl, rfl⟩).trans ?_ + generalize_proofs _ _ H _ + have : H.choose = f := (equiv_iff_of_domain_eq_of_isSeparated (S := ⊤_ _) H.choose_spec.2).mp + (toRationalMap_eq_iff.mp H.choose_spec.1) + exact ((ext_iff _ _).mp this.symm).choose_spec.symm + +@[simp] +lemma RationalMap.toRationalMap_toPartialMap [IsReduced X] [Y.IsSeparated] + (f : X ⤏ Y) : f.toPartialMap.toRationalMap = f := by + obtain ⟨f, rfl⟩ := PartialMap.toRationalMap_surjective f + trans (f.toRationalMap.toPartialMap.restrict _ + f.dense_domain f.le_domain_toRationalMap).toRationalMap + · simp + · congr 1 + exact PartialMap.ext _ f rfl (by simpa using f.toPartialMap_toRationalMap_restrict) + +instance [IsReduced X] [Y.IsSeparated] [S.IsSeparated] [X.Over S] [Y.Over S] + (f : X ⤏ Y) [f.IsOver S] : f.toPartialMap.IsOver S := by + rw [← PartialMap.isOver_toRationalMap_iff_of_isSeparated, f.toRationalMap_toPartialMap] + infer_instance + +end domain + end Scheme end AlgebraicGeometry diff --git a/Mathlib/AlgebraicGeometry/Restrict.lean b/Mathlib/AlgebraicGeometry/Restrict.lean index e1e6db017d998..1d336822caba3 100644 --- a/Mathlib/AlgebraicGeometry/Restrict.lean +++ b/Mathlib/AlgebraicGeometry/Restrict.lean @@ -52,8 +52,10 @@ def ι : ↑U ⟶ X := X.ofRestrict _ instance : IsOpenImmersion U.ι := inferInstanceAs (IsOpenImmersion (X.ofRestrict _)) -@[simps] instance : U.toScheme.Over X := ⟨U.ι⟩ @[simps! over] instance : U.toScheme.CanonicallyOver X where + hom := U.ι + +instance (U : X.Opens) : U.ι.IsOver X where lemma toScheme_carrier : (U : Type u) = (U : Set X) := rfl @@ -68,6 +70,11 @@ lemma ι_app (V) : U.ι.app V = X.presheaf.map (homOfLE (x := U.ι ''ᵁ U.ι ⁻¹ᵁ V) (Set.image_preimage_subset _ _)).op := rfl +@[simp] +lemma ι_appTop : + U.ι.appTop = X.presheaf.map (homOfLE (x := U.ι ''ᵁ ⊤) le_top).op := + rfl + @[simp] lemma ι_appLE (V W e) : U.ι.appLE V W e = @@ -168,7 +175,7 @@ def opensRestrict : instance ΓRestrictAlgebra {X : Scheme.{u}} (U : X.Opens) : Algebra (Γ(X, ⊤)) Γ(U, ⊤) := - (U.ι.app ⊤).toAlgebra + U.ι.appTop.toAlgebra lemma Scheme.map_basicOpen (r : Γ(U, ⊤)) : U.ι ''ᵁ U.toScheme.basicOpen r = X.basicOpen @@ -202,6 +209,8 @@ lemma Scheme.homOfLE_ι (X : Scheme.{u}) {U V : X.Opens} (e : U ≤ V) : X.homOfLE e ≫ V.ι = U.ι := IsOpenImmersion.lift_fac _ _ _ +instance {U V : X.Opens} (h : U ≤ V) : (X.homOfLE h).IsOver X where + @[simp] lemma Scheme.homOfLE_rfl (X : Scheme.{u}) (U : X.Opens) : X.homOfLE (refl U) = 𝟙 _ := by rw [← cancel_mono U.ι, Scheme.homOfLE_ι, Category.id_comp] @@ -242,6 +251,11 @@ theorem Scheme.homOfLE_app {U V : X.Opens} (e : U ≤ V) (W : Opens V) : rw [e₃, ← Functor.map_comp] congr 1 +theorem Scheme.homOfLE_appTop {U V : X.Opens} (e : U ≤ V) : + (X.homOfLE e).appTop = + X.presheaf.map (homOfLE <| X.ι_image_homOfLE_le_ι_image e ⊤).op := + homOfLE_app .. + instance (X : Scheme.{u}) {U V : X.Opens} (e : U ≤ V) : IsOpenImmersion (X.homOfLE e) := by delta Scheme.homOfLE infer_instance @@ -291,7 +305,7 @@ def Scheme.restrictFunctorΓ : X.restrictFunctor.op ⋙ (Over.forget X).op ⋙ S (by intro U V i dsimp - rw [X.homOfLE_app, ← Functor.map_comp, ← Functor.map_comp] + rw [X.homOfLE_appTop, ← Functor.map_comp, ← Functor.map_comp] congr 1) /-- `X ∣_ U ∣_ V` is isomorphic to `X ∣_ V ∣_ U` -/ @@ -444,6 +458,21 @@ theorem isPullback_morphismRestrict {X Y : Scheme.{u}} (f : X ⟶ Y) (U : Y.Open -- Porting note: changed `rw` to `erw` erw [pullbackRestrictIsoRestrict_inv_fst]; rw [Category.comp_id] +lemma isPullback_opens_inf_le {X : Scheme} {U V W : X.Opens} (hU : U ≤ W) (hV : V ≤ W) : + IsPullback (X.homOfLE inf_le_left) (X.homOfLE inf_le_right) (X.homOfLE hU) (X.homOfLE hV) := by + refine (isPullback_morphismRestrict (X.homOfLE hV) (W.ι ⁻¹ᵁ U)).of_iso (V.ι.isoImage _ ≪≫ + X.isoOfEq ?_) (W.ι.isoImage _ ≪≫ X.isoOfEq ?_) (Iso.refl _) (Iso.refl _) ?_ ?_ ?_ ?_ + · rw [← TopologicalSpace.Opens.map_comp_obj, ← Scheme.comp_base, Scheme.homOfLE_ι] + exact V.functor_map_eq_inf U + · exact (W.functor_map_eq_inf U).trans (by simpa) + all_goals { simp [← cancel_mono (Scheme.Opens.ι _)] } + +lemma isPullback_opens_inf {X : Scheme} (U V : X.Opens) : + IsPullback (X.homOfLE inf_le_left) (X.homOfLE inf_le_right) U.ι V.ι := + (isPullback_morphismRestrict V.ι U).of_iso (V.ι.isoImage _ ≪≫ X.isoOfEq + (V.functor_map_eq_inf U)) (Iso.refl _) (Iso.refl _) (Iso.refl _) (by simp [← cancel_mono U.ι]) + (by simp [← cancel_mono V.ι]) (by simp) (by simp) + @[simp] lemma morphismRestrict_id {X : Scheme.{u}} (U : X.Opens) : 𝟙 X ∣_ U = 𝟙 _ := by rw [← cancel_mono U.ι, morphismRestrict_ι, Category.comp_id, Category.id_comp] @@ -512,6 +541,11 @@ theorem morphismRestrict_app {X Y : Scheme.{u}} (f : X ⟶ Y) (U : Y.Opens) (V : Quiver.Hom.unop_op, Hom.opensFunctor_map_homOfLE] rw [this, Hom.appLE_map, Hom.appLE_map, Hom.appLE_map] +theorem morphismRestrict_appTop {X Y : Scheme.{u}} (f : X ⟶ Y) (U : Y.Opens) : + (f ∣_ U).appTop = f.app (U.ι ''ᵁ ⊤) ≫ + X.presheaf.map (eqToHom (image_morphismRestrict_preimage f U ⊤)).op := + morphismRestrict_app .. + @[simp] theorem morphismRestrict_app' {X Y : Scheme.{u}} (f : X ⟶ Y) (U : Y.Opens) (V : Opens U) : (f ∣_ U).app V = f.appLE _ _ (image_morphismRestrict_preimage f U V).le := @@ -528,7 +562,7 @@ theorem Γ_map_morphismRestrict {X Y : Scheme.{u}} (f : X ⟶ Y) (U : Y.Opens) : Scheme.Γ.map (f ∣_ U).op = Y.presheaf.map (eqToHom U.isOpenEmbedding_obj_top.symm).op ≫ f.app U ≫ X.presheaf.map (eqToHom (f ⁻¹ᵁ U).isOpenEmbedding_obj_top).op := by - rw [Scheme.Γ_map_op, morphismRestrict_app f U ⊤, f.naturality_assoc, ← X.presheaf.map_comp] + rw [Scheme.Γ_map_op, morphismRestrict_appTop f U, f.naturality_assoc, ← X.presheaf.map_comp] rfl /-- Restricting a morphism onto the image of an open immersion is isomorphic to the base change @@ -675,11 +709,11 @@ end Scheme.Hom /-- `f.resLE U V` induces `f.appLE U V` on global sections. -/ noncomputable def arrowResLEAppIso (f : X ⟶ Y) (U : Y.Opens) (V : X.Opens) (e : V ≤ f ⁻¹ᵁ U) : - Arrow.mk ((f.resLE U V e).app ⊤) ≅ Arrow.mk (f.appLE U V e) := + Arrow.mk ((f.resLE U V e).appTop) ≅ Arrow.mk (f.appLE U V e) := Arrow.isoMk U.topIso V.topIso <| by simp only [Opens.map_top, Arrow.mk_left, Arrow.mk_right, Functor.id_obj, Scheme.Opens.topIso_hom, eqToHom_op, Arrow.mk_hom, Scheme.Hom.map_appLE] - rw [← Scheme.Hom.appLE_eq_app, Scheme.Hom.resLE_appLE, Scheme.Hom.appLE_map] + rw [Scheme.Hom.appTop, ← Scheme.Hom.appLE_eq_app, Scheme.Hom.resLE_appLE, Scheme.Hom.appLE_map] end MorphismRestrict diff --git a/Mathlib/AlgebraicGeometry/Scheme.lean b/Mathlib/AlgebraicGeometry/Scheme.lean index f6caa6dd8c1f7..dc282d80303ad 100644 --- a/Mathlib/AlgebraicGeometry/Scheme.lean +++ b/Mathlib/AlgebraicGeometry/Scheme.lean @@ -108,6 +108,11 @@ this is the induced map `Γ(Y, U) ⟶ Γ(X, f ⁻¹ᵁ U)`. -/ abbrev app (U : Y.Opens) : Γ(Y, U) ⟶ Γ(X, f ⁻¹ᵁ U) := f.c.app (op U) +/-- Given a morphism of schemes `f : X ⟶ Y`, +this is the induced map `Γ(Y, ⊤) ⟶ Γ(X, ⊤)`. -/ +abbrev appTop : Γ(Y, ⊤) ⟶ Γ(X, ⊤) := + f.app ⊤ + @[reassoc] lemma naturality (i : op U' ⟶ op U) : Y.presheaf.map i ≫ f.app U = f.app U' ≫ X.presheaf.map ((Opens.map f.base).map i.unop).op := @@ -214,6 +219,14 @@ def forgetToTop : Scheme ⥤ TopCat := noncomputable def homeoOfIso {X Y : Scheme.{u}} (e : X ≅ Y) : X ≃ₜ Y := TopCat.homeoOfIso (forgetToTop.mapIso e) +@[simp] +lemma homeoOfIso_symm {X Y : Scheme} (e : X ≅ Y) : + (homeoOfIso e).symm = homeoOfIso e.symm := rfl + +@[simp] +lemma homeoOfIso_apply {X Y : Scheme} (e : X ≅ Y) (x : X) : + homeoOfIso e x = e.hom.base x := rfl + alias _root_.CategoryTheory.Iso.schemeIsoToHomeo := homeoOfIso /-- An isomorphism of schemes induces a homeomorphism of the underlying topological spaces. -/ @@ -221,6 +234,10 @@ noncomputable def Hom.homeomorph {X Y : Scheme.{u}} (f : X.Hom Y) [IsIso (C := S X ≃ₜ Y := (asIso f).schemeIsoToHomeo +@[simp] +lemma Hom.homeomorph_apply {X Y : Scheme.{u}} (f : X.Hom Y) [IsIso (C := Scheme) f] (x) : + f.homeomorph x = f.base x := rfl + -- Porting note: Lean seems not able to find this coercion any more instance hasCoeToTopCat : CoeOut Scheme TopCat where coe X := X.carrier @@ -238,6 +255,11 @@ theorem id.base (X : Scheme) : (𝟙 X : _).base = 𝟙 _ := theorem id_app {X : Scheme} (U : X.Opens) : (𝟙 X : _).app U = 𝟙 _ := rfl +@[simp] +theorem id_appTop {X : Scheme} : + (𝟙 X : _).appTop = 𝟙 _ := + rfl + @[reassoc] theorem comp_toLRSHom {X Y Z : Scheme} (f : X ⟶ Y) (g : Y ⟶ Z) : (f ≫ g).toLRSHom = f.toLRSHom ≫ g.toLRSHom := @@ -263,6 +285,11 @@ theorem comp_app {X Y Z : Scheme} (f : X ⟶ Y) (g : Y ⟶ Z) (U) : (f ≫ g).app U = g.app U ≫ f.app _ := rfl +@[simp, reassoc] -- reassoc lemma does not need `simp` +theorem comp_appTop {X Y Z : Scheme} (f : X ⟶ Y) (g : Y ⟶ Z) : + (f ≫ g).appTop = g.appTop ≫ f.appTop := + rfl + @[deprecated (since := "2024-06-23")] alias comp_val_c_app := comp_app @[deprecated (since := "2024-06-23")] alias comp_val_c_app_assoc := comp_app_assoc @@ -323,8 +350,10 @@ theorem inv_app {X Y : Scheme} (f : X ⟶ Y) [IsIso f] (U : X.Opens) : rw [IsIso.eq_comp_inv, ← Scheme.comp_app, Scheme.congr_app (IsIso.hom_inv_id f), Scheme.id_app, Category.id_comp] -theorem inv_app_top {X Y : Scheme} (f : X ⟶ Y) [IsIso f] : - (inv f).app ⊤ = inv (f.app ⊤) := by simp +theorem inv_appTop {X Y : Scheme} (f : X ⟶ Y) [IsIso f] : + (inv f).appTop = inv (f.appTop) := by simp + +@[deprecated (since := "2024-11-23")] alias inv_app_top := inv_appTop end Scheme @@ -428,10 +457,10 @@ theorem Γ_obj_op (X : Scheme) : Γ.obj (op X) = Γ(X, ⊤) := rfl @[simp] -theorem Γ_map {X Y : Schemeᵒᵖ} (f : X ⟶ Y) : Γ.map f = f.unop.app ⊤ := +theorem Γ_map {X Y : Schemeᵒᵖ} (f : X ⟶ Y) : Γ.map f = f.unop.appTop := rfl -theorem Γ_map_op {X Y : Scheme} (f : X ⟶ Y) : Γ.map f.op = f.app ⊤ := +theorem Γ_map_op {X Y : Scheme} (f : X ⟶ Y) : Γ.map f.op = f.appTop := rfl /-- @@ -454,13 +483,13 @@ def ΓSpecIso : Γ(Spec R, ⊤) ≅ R := SpecΓIdentity.app R @[reassoc (attr := simp)] lemma ΓSpecIso_naturality {R S : CommRingCat.{u}} (f : R ⟶ S) : - (Spec.map f).app ⊤ ≫ (ΓSpecIso S).hom = (ΓSpecIso R).hom ≫ f := SpecΓIdentity.hom.naturality f + (Spec.map f).appTop ≫ (ΓSpecIso S).hom = (ΓSpecIso R).hom ≫ f := SpecΓIdentity.hom.naturality f -- The RHS is not necessarily simpler than the LHS, but this direction coincides with the simp -- direction of `NatTrans.naturality`. @[reassoc (attr := simp)] lemma ΓSpecIso_inv_naturality {R S : CommRingCat.{u}} (f : R ⟶ S) : - f ≫ (ΓSpecIso S).inv = (ΓSpecIso R).inv ≫ (Spec.map f).app ⊤ := SpecΓIdentity.inv.naturality f + f ≫ (ΓSpecIso S).inv = (ΓSpecIso R).inv ≫ (Spec.map f).appTop := SpecΓIdentity.inv.naturality f -- This is not marked simp to respect the abstraction lemma ΓSpecIso_inv : (ΓSpecIso R).inv = StructureSheaf.toOpen R ⊤ := rfl @@ -526,6 +555,10 @@ theorem preimage_basicOpen {X Y : Scheme.{u}} (f : X ⟶ Y) {U : Y.Opens} (r : f ⁻¹ᵁ (Y.basicOpen r) = X.basicOpen (f.app U r) := LocallyRingedSpace.preimage_basicOpen f.toLRSHom r +theorem preimage_basicOpen_top {X Y : Scheme.{u}} (f : X ⟶ Y) (r : Γ(Y, ⊤)) : + f ⁻¹ᵁ (Y.basicOpen r) = X.basicOpen (f.appTop r) := + preimage_basicOpen .. + lemma basicOpen_appLE {X Y : Scheme.{u}} (f : X ⟶ Y) (U : X.Opens) (V : Y.Opens) (e : U ≤ f ⁻¹ᵁ V) (s : Γ(Y, V)) : X.basicOpen (f.appLE V U e s) = U ⊓ f ⁻¹ᵁ (Y.basicOpen s) := by simp only [preimage_basicOpen, Hom.appLE, CommRingCat.coe_comp_of, RingHom.coe_comp, diff --git a/Mathlib/AlgebraicGeometry/SpreadingOut.lean b/Mathlib/AlgebraicGeometry/SpreadingOut.lean index b5d7ef83b97b8..a327e1ae7ee02 100644 --- a/Mathlib/AlgebraicGeometry/SpreadingOut.lean +++ b/Mathlib/AlgebraicGeometry/SpreadingOut.lean @@ -49,8 +49,7 @@ open CategoryTheory namespace AlgebraicGeometry -variable {X Y S : Scheme.{u}} (f : X ⟶ Y) (sX : X ⟶ S) (sY : Y ⟶ S) (e : f ≫ sY = sX) -variable {R A : CommRingCat.{u}} +variable {X Y S : Scheme.{u}} (f : X ⟶ Y) (sX : X ⟶ S) (sY : Y ⟶ S) {R A : CommRingCat.{u}} /-- The germ map at `x` is injective if there exists some affine `U ∋ x` such that the map `Γ(X, U) ⟶ X_x` is injective -/ diff --git a/Mathlib/AlgebraicGeometry/Stalk.lean b/Mathlib/AlgebraicGeometry/Stalk.lean index 6f520c2514a8f..e06eb1b7ef0ca 100644 --- a/Mathlib/AlgebraicGeometry/Stalk.lean +++ b/Mathlib/AlgebraicGeometry/Stalk.lean @@ -112,6 +112,13 @@ lemma fromSpecStalk_app {x : X} (hxU : x ∈ U) : hV.fromSpec_app_of_le _ hVU, ← X.presheaf.germ_res (homOfLE hVU) x hxV] simp [Category.assoc, ← ΓSpecIso_inv_naturality_assoc] +lemma fromSpecStalk_appTop {x : X} : + (X.fromSpecStalk x).appTop = + X.presheaf.germ ⊤ x trivial ≫ + (ΓSpecIso (X.presheaf.stalk x)).inv ≫ + (Spec (X.presheaf.stalk x)).presheaf.map (homOfLE le_top).op := + fromSpecStalk_app .. + @[reassoc (attr := simp)] lemma Spec_map_stalkSpecializes_fromSpecStalk {x y : X} (h : x ⤳ y) : Spec.map (X.presheaf.stalkSpecializes h) ≫ X.fromSpecStalk y = X.fromSpecStalk x := by @@ -184,7 +191,7 @@ instance {X : Scheme.{u}} (U : X.Opens) (x : X) (hxU : x ∈ U) : lemma fromSpecStalk_toSpecΓ (X : Scheme.{u}) (x : X) : X.fromSpecStalk x ≫ X.toSpecΓ = Spec.map (X.presheaf.germ ⊤ x trivial) := by rw [Scheme.toSpecΓ_naturality, ← SpecMap_ΓSpecIso_hom, ← Spec.map_comp, - @Scheme.fromSpecStalk_app X ⊤ _ trivial] + Scheme.fromSpecStalk_appTop] simp @[reassoc (attr := simp)] diff --git a/Mathlib/AlgebraicGeometry/ValuativeCriterion.lean b/Mathlib/AlgebraicGeometry/ValuativeCriterion.lean index cb9082af37462..dbc4ac5a16007 100644 --- a/Mathlib/AlgebraicGeometry/ValuativeCriterion.lean +++ b/Mathlib/AlgebraicGeometry/ValuativeCriterion.lean @@ -275,7 +275,7 @@ lemma IsSeparated.valuativeCriterion [IsSeparated f] : ValuativeCriterion.Unique conv_lhs => rw [← pullback.lift_fst l₁ l₂ h, ← pullback.condition_assoc] conv_rhs => rw [← pullback.lift_snd l₁ l₂ h, ← pullback.condition_assoc] simp - suffices h : Function.Bijective (g.app ⊤) by + suffices h : Function.Bijective (g.appTop) by refine (HasAffineProperty.iff_of_isAffine (P := MorphismProperty.isomorphisms Scheme)).mpr ?_ exact ⟨hZ, (ConcreteCategory.isIso_iff_bijective _).mpr h⟩ constructor @@ -286,7 +286,7 @@ lemma IsSeparated.valuativeCriterion [IsSeparated f] : ValuativeCriterion.Unique simpa using hl₂.symm have hg : l ≫ g = Spec.map (CommRingCat.ofHom (algebraMap S.R S.K)) := pullback.lift_snd _ _ _ - have : Function.Injective ((l ≫ g).app ⊤) := by + have : Function.Injective ((l ≫ g).appTop) := by rw [hg] let e := arrowIsoΓSpecOfIsAffine (CommRingCat.ofHom <| algebraMap S.R S.K) let P : MorphismProperty CommRingCat := @@ -296,7 +296,7 @@ lemma IsSeparated.valuativeCriterion [IsSeparated f] : ValuativeCriterion.Unique show P _ rw [← MorphismProperty.arrow_mk_iso_iff (P := P) e] exact NoZeroSMulDivisors.algebraMap_injective S.R S.K - rw [Scheme.comp_app _ _] at this + rw [Scheme.comp_appTop] at this exact Function.Injective.of_comp this · rw [@HasAffineProperty.iff_of_isAffine @IsClosedImmersion] at this exact this.right diff --git a/Mathlib/AlgebraicTopology/SimplicialSet/Quasicategory.lean b/Mathlib/AlgebraicTopology/Quasicategory/Basic.lean similarity index 91% rename from Mathlib/AlgebraicTopology/SimplicialSet/Quasicategory.lean rename to Mathlib/AlgebraicTopology/Quasicategory/Basic.lean index 381e65660f632..55b27d884364c 100644 --- a/Mathlib/AlgebraicTopology/SimplicialSet/Quasicategory.lean +++ b/Mathlib/AlgebraicTopology/Quasicategory/Basic.lean @@ -13,13 +13,14 @@ In this file we define quasicategories, a common model of infinity categories. We show that every Kan complex is a quasicategory. -In `Mathlib/AlgebraicTopology/Nerve.lean` -we show (TODO) that the nerve of a category is a quasicategory. +In `Mathlib/AlgebraicTopology/SimplicialSet/StrictSegal.lean` +we show that the nerve of a category is a quasicategory. ## TODO - Generalize the definition to higher universes. - See the corresponding TODO in `Mathlib/AlgebraicTopology/KanComplex.lean`. + See the corresponding TODO in + `Mathlib/AlgebraicTopology/SimplicialSet/KanComplex.lean`. -/ diff --git a/Mathlib/AlgebraicTopology/SimplexCategory.lean b/Mathlib/AlgebraicTopology/SimplexCategory.lean index a2e26b4118880..7c9ce0278a0c3 100644 --- a/Mathlib/AlgebraicTopology/SimplexCategory.lean +++ b/Mathlib/AlgebraicTopology/SimplexCategory.lean @@ -564,6 +564,50 @@ lemma δ_one_mkOfSucc {n : ℕ} (i : Fin n) : fin_cases x aesop +/-- If `i + 1 < j`, `mkOfSucc i ≫ δ j` is the morphism `[1] ⟶ [n]` that +sends `0` and `1` to `i` and `i + 1`, respectively. -/ +lemma mkOfSucc_δ_lt {n : ℕ} {i : Fin n} {j : Fin (n + 2)} + (h : i.succ.castSucc < j) : + mkOfSucc i ≫ δ j = mkOfSucc i.castSucc := by + ext x + fin_cases x + · simp [δ, Fin.succAbove_of_castSucc_lt _ _ (Nat.lt_trans _ h)] + · simp [δ, Fin.succAbove_of_castSucc_lt _ _ h] + +/-- If `i + 1 > j`, `mkOfSucc i ≫ δ j` is the morphism `[1] ⟶ [n]` that +sends `0` and `1` to `i + 1` and `i + 2`, respectively. -/ +lemma mkOfSucc_δ_gt {n : ℕ} {i : Fin n} {j : Fin (n + 2)} + (h : j < i.succ.castSucc) : + mkOfSucc i ≫ δ j = mkOfSucc i.succ := by + ext x + simp only [δ, len_mk, mkHom, comp_toOrderHom, Hom.toOrderHom_mk, OrderHom.comp_coe, + OrderEmbedding.toOrderHom_coe, Function.comp_apply, Fin.succAboveOrderEmb_apply] + fin_cases x <;> rw [Fin.succAbove_of_le_castSucc] + · rfl + · exact Nat.le_of_lt_succ h + · rfl + · exact Nat.le_of_lt h + +/-- If `i + 1 = j`, `mkOfSucc i ≫ δ j` is the morphism `[1] ⟶ [n]` that +sends `0` and `1` to `i` and `i + 2`, respectively. -/ +lemma mkOfSucc_δ_eq {n : ℕ} {i : Fin n} {j : Fin (n + 2)} + (h : j = i.succ.castSucc) : + mkOfSucc i ≫ δ j = intervalEdge i 2 (by omega) := by + ext x + fin_cases x + · subst h + simp only [δ, len_mk, Nat.reduceAdd, mkHom, comp_toOrderHom, Hom.toOrderHom_mk, + Fin.zero_eta, OrderHom.comp_coe, OrderEmbedding.toOrderHom_coe, Function.comp_apply, + mkOfSucc_homToOrderHom_zero, Fin.succAboveOrderEmb_apply, + Fin.castSucc_succAbove_castSucc, Fin.succAbove_succ_self] + rfl + · simp only [δ, len_mk, Nat.reduceAdd, mkHom, comp_toOrderHom, Hom.toOrderHom_mk, Fin.mk_one, + OrderHom.comp_coe, OrderEmbedding.toOrderHom_coe, Function.comp_apply, + mkOfSucc_homToOrderHom_one, Fin.succAboveOrderEmb_apply] + subst h + rw [Fin.succAbove_castSucc_self] + rfl + theorem eq_of_one_to_two (f : ([1] : SimplexCategory) ⟶ [2]) : f = (δ (n := 1) 0) ∨ f = (δ (n := 1) 1) ∨ f = (δ (n := 1) 2) ∨ ∃ a, f = SimplexCategory.const _ _ a := by diff --git a/Mathlib/AlgebraicTopology/SimplicialSet/Basic.lean b/Mathlib/AlgebraicTopology/SimplicialSet/Basic.lean index 309fc78b1916a..8c329680dec88 100644 --- a/Mathlib/AlgebraicTopology/SimplicialSet/Basic.lean +++ b/Mathlib/AlgebraicTopology/SimplicialSet/Basic.lean @@ -106,6 +106,13 @@ def _root_.SSet.yonedaEquiv (X : SSet.{u}) (n : SimplexCategory) : (standardSimplex.obj n ⟶ X) ≃ X.obj (op n) := yonedaCompUliftFunctorEquiv X n +/-- The unique non-degenerate `n`-simplex in `Δ[n]`. -/ +def id (n : ℕ) : Δ[n] _[n] := yonedaEquiv Δ[n] [n] (𝟙 Δ[n]) + +lemma id_eq_objEquiv_symm (n : ℕ) : id n = (objEquiv _ _).symm (𝟙 _) := rfl + +lemma objEquiv_id (n : ℕ) : objEquiv _ _ (id n) = 𝟙 _ := rfl + /-- The (degenerate) `m`-simplex in the standard simplex concentrated in vertex `k`. -/ def const (n : ℕ) (k : Fin (n+1)) (m : SimplexCategoryᵒᵖ) : Δ[n].obj m := objMk (OrderHom.const _ k ) diff --git a/Mathlib/AlgebraicTopology/SimplicialSet/KanComplex.lean b/Mathlib/AlgebraicTopology/SimplicialSet/KanComplex.lean index 531bc99ebc39c..87cf0ca7bf9e5 100644 --- a/Mathlib/AlgebraicTopology/SimplicialSet/KanComplex.lean +++ b/Mathlib/AlgebraicTopology/SimplicialSet/KanComplex.lean @@ -10,7 +10,7 @@ import Mathlib.AlgebraicTopology.SimplicialSet.Basic # Kan complexes In this file we give the definition of Kan complexes. -In `Mathlib/AlgebraicTopology/Quasicategory.lean` +In `Mathlib/AlgebraicTopology/Quasicategory/Basic.lean` we show that every Kan complex is a quasicategory. ## TODO diff --git a/Mathlib/AlgebraicTopology/SimplicialSet/Path.lean b/Mathlib/AlgebraicTopology/SimplicialSet/Path.lean index 696d2c7aa9498..33e4d07da1bce 100644 --- a/Mathlib/AlgebraicTopology/SimplicialSet/Path.lean +++ b/Mathlib/AlgebraicTopology/SimplicialSet/Path.lean @@ -73,4 +73,66 @@ lemma spine_map_subinterval {n : ℕ} (j l : ℕ) (hjl : j + l ≤ n) (Δ : X _[ · simp only [spine_arrow, Path.interval, ← FunctorToTypes.map_comp_apply, ← op_comp, mkOfSucc_subinterval_eq] +/-- Two paths of the same nonzero length are equal if all of their arrows are equal. -/ +@[ext] +lemma Path.ext' {n : ℕ} {f g : Path X (n + 1)} + (h : ∀ i : Fin (n + 1), f.arrow i = g.arrow i) : + f = g := by + ext j + · rcases Fin.eq_castSucc_or_eq_last j with ⟨k, hk⟩ | hl + · rw [hk, ← f.arrow_src k, ← g.arrow_src k, h] + · simp only [hl, ← Fin.succ_last] + rw [← f.arrow_tgt (Fin.last n), ← g.arrow_tgt (Fin.last n), h] + · exact h j + +/-- Maps of simplicial sets induce maps of paths in a simplicial set.-/ +@[simps] +def Path.map {X Y : SSet.{u}} {n : ℕ} (f : X.Path n) (σ : X ⟶ Y) : Y.Path n where + vertex i := σ.app (Opposite.op [0]) (f.vertex i) + arrow i := σ.app (Opposite.op [1]) (f.arrow i) + arrow_src i := by + simp only [← f.arrow_src i] + exact congr (σ.naturality (δ 1).op) rfl |>.symm + arrow_tgt i := by + simp only [← f.arrow_tgt i] + exact congr (σ.naturality (δ 0).op) rfl |>.symm + +/-- `Path.map` respects subintervals of paths.-/ +lemma map_interval {X Y : SSet.{u}} {n : ℕ} (f : X.Path n) (σ : X ⟶ Y) + (j l : ℕ) (hjl : j + l ≤ n) : + (f.map σ).interval j l hjl = (f.interval j l hjl).map σ := rfl + +/-- The spine of the unique non-degenerate `n`-simplex in `Δ[n]`.-/ +def standardSimplex.spineId (n : ℕ) : Path Δ[n] n := + spine Δ[n] n (standardSimplex.id n) + +/-- Any inner horn contains the spine of the unique non-degenerate `n`-simplex +in `Δ[n]`.-/ +@[simps] +def horn.spineId {n : ℕ} (i : Fin (n + 3)) + (h₀ : 0 < i) (hₙ : i < Fin.last (n + 2)) : + Path Λ[n + 2, i] (n + 2) where + vertex j := ⟨standardSimplex.spineId _ |>.vertex j, (horn.const n i j _).property⟩ + arrow j := ⟨standardSimplex.spineId _ |>.arrow j, by + let edge := horn.primitiveEdge h₀ hₙ j + have ha : (standardSimplex.spineId _).arrow j = edge.val := by + dsimp only [edge, standardSimplex.spineId, standardSimplex.id, spine_arrow, + mkOfSucc, horn.primitiveEdge, horn.edge, standardSimplex.edge, + standardSimplex.map_apply] + aesop + rw [ha] + exact edge.property⟩ + arrow_src := by + simp only [horn, SimplicialObject.δ, Subtype.mk.injEq] + exact standardSimplex.spineId _ |>.arrow_src + arrow_tgt := by + simp only [horn, SimplicialObject.δ, Subtype.mk.injEq] + exact standardSimplex.spineId _ |>.arrow_tgt + +@[simp] +lemma horn.spineId_map_hornInclusion {n : ℕ} (i : Fin (n + 3)) + (h₀ : 0 < i) (hₙ : i < Fin.last (n + 2)) : + Path.map (horn.spineId i h₀ hₙ) (hornInclusion (n + 2) i) = + standardSimplex.spineId (n + 2) := rfl + end SSet diff --git a/Mathlib/AlgebraicTopology/SimplicialSet/StrictSegal.lean b/Mathlib/AlgebraicTopology/SimplicialSet/StrictSegal.lean index 13a41139b88ed..cef9a156cab5a 100644 --- a/Mathlib/AlgebraicTopology/SimplicialSet/StrictSegal.lean +++ b/Mathlib/AlgebraicTopology/SimplicialSet/StrictSegal.lean @@ -1,8 +1,9 @@ /- Copyright (c) 2024 Emily Riehl. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Mario Carneiro, Emily Riehl, Joël Riou +Authors: Mario Carneiro, Emily Riehl, Joël Riou, Johan Commelin, Nick Ward -/ +import Mathlib.AlgebraicTopology.Quasicategory.Basic import Mathlib.AlgebraicTopology.SimplicialSet.Nerve import Mathlib.AlgebraicTopology.SimplicialSet.Path import Mathlib.CategoryTheory.Functor.KanExtension.Adjunction @@ -86,6 +87,147 @@ theorem spineToSimplex_edge (f : Path X n) (j l : ℕ) (hjl : j + l ≤ n) : unfold diagonal simp only [← FunctorToTypes.map_comp_apply, ← op_comp, diag_subinterval_eq] +/-- For any `σ : X ⟶ Y` between `StrictSegal` simplicial sets, `spineToSimplex` +commutes with `Path.map`. -/ +lemma spineToSimplex_map {X Y : SSet.{u}} [StrictSegal X] [StrictSegal Y] + {n : ℕ} (f : Path X (n + 1)) (σ : X ⟶ Y) : + spineToSimplex (f.map σ) = σ.app _ (spineToSimplex f) := by + apply spineInjective + ext k + dsimp only [spineEquiv, Equiv.coe_fn_mk, Path.map, spine_arrow] + rw [← types_comp_apply (σ.app _) (Y.map _), ← σ.naturality] + simp only [types_comp_apply, spineToSimplex_arrow] + +/-- If we take the path along the spine of the `j`th face of a `spineToSimplex`, +the common vertices will agree with those of the original path `f`. In particular, +a vertex `i` with `i < j` can be identified with the same vertex in `f`. -/ +lemma spine_δ_vertex_lt (f : Path X (n + 1)) {i : Fin (n + 1)} {j : Fin (n + 2)} + (h : i.castSucc < j) : + (X.spine n (X.δ j (spineToSimplex f))).vertex i = f.vertex i.castSucc := by + simp only [SimplicialObject.δ, spine_vertex] + rw [← FunctorToTypes.map_comp_apply, ← op_comp, const_comp, spineToSimplex_vertex] + simp only [SimplexCategory.δ, Hom.toOrderHom, len_mk, mkHom, Hom.mk, + OrderEmbedding.toOrderHom_coe, Fin.succAboveOrderEmb_apply] + rw [Fin.succAbove_of_castSucc_lt j i h] + +/-- If we take the path along the spine of the `j`th face of a `spineToSimplex`, +a vertex `i` with `i ≥ j` can be identified with vertex `i + 1` in the original +path. -/ +lemma spine_δ_vertex_ge (f : Path X (n + 1)) {i : Fin (n + 1)} {j : Fin (n + 2)} + (h : j ≤ i.castSucc) : + (X.spine n (X.δ j (spineToSimplex f))).vertex i = f.vertex i.succ := by + simp only [SimplicialObject.δ, spine_vertex] + rw [← FunctorToTypes.map_comp_apply, ← op_comp, const_comp, spineToSimplex_vertex] + simp only [SimplexCategory.δ, Hom.toOrderHom, len_mk, mkHom, Hom.mk, + OrderEmbedding.toOrderHom_coe, Fin.succAboveOrderEmb_apply] + rw [Fin.succAbove_of_le_castSucc j i h] + +/-- If we take the path along the spine of the `j`th face of a `spineToSimplex`, +the common arrows will agree with those of the original path `f`. In particular, +an arrow `i` with `i + 1 < j` can be identified with the same arrow in `f`. -/ +lemma spine_δ_arrow_lt (f : Path X (n + 1)) {i : Fin n} {j : Fin (n + 2)} + (h : i.succ.castSucc < j) : + (X.spine n (X.δ j (spineToSimplex f))).arrow i = f.arrow i.castSucc := by + simp only [SimplicialObject.δ, spine_arrow] + rw [← FunctorToTypes.map_comp_apply, ← op_comp] + rw [mkOfSucc_δ_lt h, spineToSimplex_arrow] + +/-- If we take the path along the spine of the `j`th face of a `spineToSimplex`, +an arrow `i` with `i + 1 > j` can be identified with arrow `i + 1` in the +original path. -/ +lemma spine_δ_arrow_gt (f : Path X (n + 1)) {i : Fin n} {j : Fin (n + 2)} + (h : j < i.succ.castSucc) : + (X.spine n (X.δ j (spineToSimplex f))).arrow i = f.arrow i.succ := by + simp only [SimplicialObject.δ, spine_arrow] + rw [← FunctorToTypes.map_comp_apply, ← op_comp] + rw [mkOfSucc_δ_gt h, spineToSimplex_arrow] + +/-- If we take the path along the spine of a face of a `spineToSimplex`, the +arrows not contained in the original path can be recovered as the diagonal edge +of the `spineToSimplex` that "composes" arrows `i` and `i + 1`. -/ +lemma spine_δ_arrow_eq (f : Path X (n + 1)) {i : Fin n} {j : Fin (n + 2)} + (h : j = i.succ.castSucc) : + (X.spine n (X.δ j (spineToSimplex f))).arrow i = + spineToDiagonal (Path.interval f i 2 (by omega)) := by + simp only [SimplicialObject.δ, spine_arrow] + rw [← FunctorToTypes.map_comp_apply, ← op_comp] + rw [mkOfSucc_δ_eq h, spineToSimplex_edge] + +/-- Any `StrictSegal` simplicial set is a `Quasicategory`. -/ +instance : Quasicategory X := by + apply quasicategory_of_filler X + intro n i σ₀ h₀ hₙ + use spineToSimplex <| Path.map (horn.spineId i h₀ hₙ) σ₀ + intro j hj + apply spineInjective + ext k + · dsimp only [spineEquiv, spine_arrow, Function.comp_apply, Equiv.coe_fn_mk] + rw [← types_comp_apply (σ₀.app _) (X.map _), ← σ₀.naturality] + let ksucc := k.succ.castSucc + obtain hlt | hgt | heq : ksucc < j ∨ j < ksucc ∨ j = ksucc := by omega + · rw [← spine_arrow, spine_δ_arrow_lt _ hlt] + dsimp only [Path.map, spine_arrow, Fin.coe_eq_castSucc] + apply congr_arg + simp only [horn, horn.spineId, standardSimplex, uliftFunctor, Functor.comp_obj, + yoneda_obj_obj, whiskering_obj_obj_map, uliftFunctor_map, yoneda_obj_map, + standardSimplex.objEquiv, Equiv.ulift, Equiv.coe_fn_symm_mk, + Quiver.Hom.unop_op, horn.face_coe, Subtype.mk.injEq] + rw [mkOfSucc_δ_lt hlt] + rfl + · rw [← spine_arrow, spine_δ_arrow_gt _ hgt] + dsimp only [Path.map, spine_arrow, Fin.coe_eq_castSucc] + apply congr_arg + simp only [horn, horn.spineId, standardSimplex, uliftFunctor, Functor.comp_obj, + yoneda_obj_obj, whiskering_obj_obj_map, uliftFunctor_map, yoneda_obj_map, + standardSimplex.objEquiv, Equiv.ulift, Equiv.coe_fn_symm_mk, + Quiver.Hom.unop_op, horn.face_coe, Subtype.mk.injEq] + rw [mkOfSucc_δ_gt hgt] + rfl + · /- The only inner horn of `Δ[2]` does not contain the diagonal edge. -/ + have hn0 : n ≠ 0 := by + rintro rfl + obtain rfl : k = 0 := by omega + fin_cases i <;> contradiction + /- We construct the triangle in the standard simplex as a 2-simplex in + the horn. While the triangle is not contained in the inner horn `Λ[2, 1]`, + we can inhabit `Λ[n + 2, i] _[2]` by induction on `n`. -/ + let triangle : Λ[n + 2, i] _[2] := by + cases n with + | zero => contradiction + | succ _ => exact horn.primitiveTriangle i h₀ hₙ k (by omega) + /- The interval spanning from `k` to `k + 2` is equivalently the spine + of the triangle with vertices `k`, `k + 1`, and `k + 2`. -/ + have hi : ((horn.spineId i h₀ hₙ).map σ₀).interval k 2 (by omega) = + X.spine 2 (σ₀.app _ triangle) := by + ext m + dsimp [spine_arrow, Path.interval, Path.map] + rw [← types_comp_apply (σ₀.app _) (X.map _), ← σ₀.naturality] + apply congr_arg + simp only [horn, standardSimplex, uliftFunctor, Functor.comp_obj, + whiskering_obj_obj_obj, yoneda_obj_obj, uliftFunctor_obj, ne_eq, + whiskering_obj_obj_map, uliftFunctor_map, yoneda_obj_map, len_mk, + Nat.reduceAdd, Quiver.Hom.unop_op] + cases n with + | zero => contradiction + | succ _ => ext x; fin_cases x <;> fin_cases m <;> rfl + rw [← spine_arrow, spine_δ_arrow_eq _ heq, hi] + simp only [spineToDiagonal, diagonal, spineToSimplex_spine] + rw [← types_comp_apply (σ₀.app _) (X.map _), ← σ₀.naturality, types_comp_apply] + apply congr_arg + simp only [horn, standardSimplex, uliftFunctor, Functor.comp_obj, + whiskering_obj_obj_obj, yoneda_obj_obj, uliftFunctor_obj, + uliftFunctor_map, whiskering_obj_obj_map, yoneda_obj_map, horn.face_coe, + len_mk, Nat.reduceAdd, Quiver.Hom.unop_op, Subtype.mk.injEq, ULift.up_inj] + ext z + cases n with + | zero => contradiction + | succ _ => + fin_cases z <;> + · simp only [standardSimplex.objEquiv, uliftFunctor_map, yoneda_obj_map, + Quiver.Hom.unop_op, Equiv.ulift_symm_down] + rw [mkOfSucc_δ_eq heq] + rfl + end StrictSegal end SSet @@ -118,4 +260,8 @@ noncomputable instance strictSegal (C : Type u) [Category.{v} C] : StrictSegal ( · intro i hi apply ComposableArrows.mkOfObjOfMapSucc_map_succ +/-- By virtue of satisfying the `StrictSegal` condition, the nerve of a +category is a `Quasicategory`. -/ +instance : Quasicategory (nerve C) := inferInstance + end Nerve diff --git a/Mathlib/Analysis/Analytic/Inverse.lean b/Mathlib/Analysis/Analytic/Inverse.lean index c9a57e5bb6985..6efcaa447e727 100644 --- a/Mathlib/Analysis/Analytic/Inverse.lean +++ b/Mathlib/Analysis/Analytic/Inverse.lean @@ -5,7 +5,7 @@ Authors: Sébastien Gouëzel -/ import Mathlib.Analysis.Analytic.Composition import Mathlib.Analysis.Analytic.Linear -import Mathlib.Tactic.Positivity.Finset +import Mathlib.Tactic.Positivity /-! diff --git a/Mathlib/Analysis/Asymptotics/TVS.lean b/Mathlib/Analysis/Asymptotics/TVS.lean index f116d2b07113c..e4d49370e6a0a 100644 --- a/Mathlib/Analysis/Asymptotics/TVS.lean +++ b/Mathlib/Analysis/Asymptotics/TVS.lean @@ -125,7 +125,7 @@ lemma isLittleOTVS_one [ContinuousSMul 𝕜 E] {f : α → E} {l : Filter α} : rcases NormedField.exists_one_lt_norm 𝕜 with ⟨c, hc⟩ obtain ⟨ε, hε₀, hε⟩ : ∃ ε : ℝ≥0, 0 < ε ∧ (ε * ‖c‖₊ / r : ℝ≥0∞) < 1 := by apply Eventually.exists_gt - refine eventually_lt_of_tendsto_lt zero_lt_one <| Continuous.tendsto' ?_ _ _ (by simp) + refine Continuous.tendsto' ?_ _ _ (by simp) |>.eventually_lt_const zero_lt_one fun_prop (disch := intros; first | apply ENNReal.coe_ne_top | positivity) filter_upwards [hr ε hε₀.ne'] with x hx refine mem_of_egauge_lt_one hUb (hx.trans_lt ?_) diff --git a/Mathlib/Analysis/BoundedVariation.lean b/Mathlib/Analysis/BoundedVariation.lean index 4f281d9bfca6d..4a2fafb5a8000 100644 --- a/Mathlib/Analysis/BoundedVariation.lean +++ b/Mathlib/Analysis/BoundedVariation.lean @@ -180,7 +180,7 @@ theorem lowerSemicontinuous_aux {ι : Type*} {F : ι → α → E} {p : Filter (𝓝 (∑ i ∈ Finset.range n, edist (f (u (i + 1))) (f (u i)))) := by apply tendsto_finset_sum exact fun i _ => Tendsto.edist (Ffs (u i.succ) (us i.succ)) (Ffs (u i) (us i)) - exact (eventually_gt_of_tendsto_gt hlt this).mono fun i h => h.trans_le (sum_le (F i) n um us) + exact (this.eventually_const_lt hlt).mono fun i h => h.trans_le (sum_le (F i) n um us) /-- The map `(eVariationOn · s)` is lower semicontinuous for pointwise convergence *on `s`*. Pointwise convergence on `s` is encoded here as uniform convergence on the family consisting of the diff --git a/Mathlib/Analysis/Calculus/AddTorsor/AffineMap.lean b/Mathlib/Analysis/Calculus/AddTorsor/AffineMap.lean index 5eb7534bb2ff4..104a452fe5423 100644 --- a/Mathlib/Analysis/Calculus/AddTorsor/AffineMap.lean +++ b/Mathlib/Analysis/Calculus/AddTorsor/AffineMap.lean @@ -25,7 +25,7 @@ variable [NormedAddCommGroup V] [NormedSpace 𝕜 V] variable [NormedAddCommGroup W] [NormedSpace 𝕜 W] /-- A continuous affine map between normed vector spaces is smooth. -/ -theorem contDiff {n : ℕ∞} (f : V →ᴬ[𝕜] W) : ContDiff 𝕜 n f := by +theorem contDiff {n : WithTop ℕ∞} (f : V →ᴬ[𝕜] W) : ContDiff 𝕜 n f := by rw [f.decomp] apply f.contLinear.contDiff.add exact contDiff_const diff --git a/Mathlib/Analysis/Calculus/BumpFunction/Basic.lean b/Mathlib/Analysis/Calculus/BumpFunction/Basic.lean index 7c20ab571383f..922effc6f97d8 100644 --- a/Mathlib/Analysis/Calculus/BumpFunction/Basic.lean +++ b/Mathlib/Analysis/Calculus/BumpFunction/Basic.lean @@ -49,7 +49,7 @@ smooth function, smooth bump function noncomputable section open Function Set Filter -open scoped Topology Filter +open scoped Topology Filter ContDiff variable {E X : Type*} @@ -80,7 +80,7 @@ structure ContDiffBumpBase (E : Type*) [NormedAddCommGroup E] [NormedSpace ℝ E toFun : ℝ → E → ℝ mem_Icc : ∀ (R : ℝ) (x : E), toFun R x ∈ Icc (0 : ℝ) 1 symmetric : ∀ (R : ℝ) (x : E), toFun R (-x) = toFun R x - smooth : ContDiffOn ℝ ⊤ (uncurry toFun) (Ioi (1 : ℝ) ×ˢ (univ : Set E)) + smooth : ContDiffOn ℝ ∞ (uncurry toFun) (Ioi (1 : ℝ) ×ˢ (univ : Set E)) eq_one : ∀ R : ℝ, 1 < R → ∀ x : E, ‖x‖ ≤ 1 → toFun R x = 1 support : ∀ R : ℝ, 1 < R → Function.support (toFun R) = Metric.ball (0 : E) R @@ -178,7 +178,8 @@ protected theorem _root_.ContDiffWithinAt.contDiffBump {c g : X → E} {s : Set ContDiffWithinAt ℝ n (fun x => f x (g x)) s x := by change ContDiffWithinAt ℝ n (uncurry (someContDiffBumpBase E).toFun ∘ fun x : X => ((f x).rOut / (f x).rIn, (f x).rIn⁻¹ • (g x - c x))) s x - refine (((someContDiffBumpBase E).smooth.contDiffAt ?_).of_le le_top).comp_contDiffWithinAt x ?_ + refine (((someContDiffBumpBase E).smooth.contDiffAt ?_).of_le + (mod_cast le_top)).comp_contDiffWithinAt x ?_ · exact prod_mem_nhds (Ioi_mem_nhds (f x).one_lt_rOut_div_rIn) univ_mem · exact (hR.div hr (f x).rIn_pos.ne').prod ((hr.inv (f x).rIn_pos.ne').smul (hg.sub hc)) diff --git a/Mathlib/Analysis/Calculus/BumpFunction/FiniteDimension.lean b/Mathlib/Analysis/Calculus/BumpFunction/FiniteDimension.lean index d0f390973978c..2f3e0be74bdfb 100644 --- a/Mathlib/Analysis/Calculus/BumpFunction/FiniteDimension.lean +++ b/Mathlib/Analysis/Calculus/BumpFunction/FiniteDimension.lean @@ -28,7 +28,7 @@ noncomputable section open Set Metric TopologicalSpace Function Asymptotics MeasureTheory Module ContinuousLinearMap Filter MeasureTheory.Measure Bornology -open scoped Pointwise Topology NNReal Convolution +open scoped Pointwise Topology NNReal Convolution ContDiff variable {E : Type*} [NormedAddCommGroup E] @@ -40,7 +40,7 @@ variable [NormedSpace ℝ E] [FiniteDimensional ℝ E] values in `[0, 1]`, supported in `s` and with `f x = 1`. -/ theorem exists_smooth_tsupport_subset {s : Set E} {x : E} (hs : s ∈ 𝓝 x) : ∃ f : E → ℝ, - tsupport f ⊆ s ∧ HasCompactSupport f ∧ ContDiff ℝ ⊤ f ∧ range f ⊆ Icc 0 1 ∧ f x = 1 := by + tsupport f ⊆ s ∧ HasCompactSupport f ∧ ContDiff ℝ ∞ f ∧ range f ⊆ Icc 0 1 ∧ f x = 1 := by obtain ⟨d : ℝ, d_pos : 0 < d, hd : Euclidean.closedBall x d ⊆ s⟩ := Euclidean.nhds_basis_closedBall.mem_iff.1 hs let c : ContDiffBump (toEuclidean x) := @@ -73,7 +73,7 @@ theorem exists_smooth_tsupport_subset {s : Set E} {x : E} (hs : s ∈ 𝓝 x) : /-- Given an open set `s` in a finite-dimensional real normed vector space, there exists a smooth function with values in `[0, 1]` whose support is exactly `s`. -/ theorem IsOpen.exists_smooth_support_eq {s : Set E} (hs : IsOpen s) : - ∃ f : E → ℝ, f.support = s ∧ ContDiff ℝ ⊤ f ∧ Set.range f ⊆ Set.Icc 0 1 := by + ∃ f : E → ℝ, f.support = s ∧ ContDiff ℝ ∞ f ∧ Set.range f ⊆ Set.Icc 0 1 := by /- For any given point `x` in `s`, one can construct a smooth function with support in `s` and nonzero at `x`. By second-countability, it follows that we may cover `s` with the supports of countably many such functions, say `g i`. @@ -85,7 +85,7 @@ theorem IsOpen.exists_smooth_support_eq {s : Set E} (hs : IsOpen s) : · exact ⟨fun _ => 0, Function.support_zero, contDiff_const, by simp only [range_const, singleton_subset_iff, left_mem_Icc, zero_le_one]⟩ - let ι := { f : E → ℝ // f.support ⊆ s ∧ HasCompactSupport f ∧ ContDiff ℝ ⊤ f ∧ range f ⊆ Icc 0 1 } + let ι := { f : E → ℝ // f.support ⊆ s ∧ HasCompactSupport f ∧ ContDiff ℝ ∞ f ∧ range f ⊆ Icc 0 1 } obtain ⟨T, T_count, hT⟩ : ∃ T : Set ι, T.Countable ∧ ⋃ f ∈ T, support (f : E → ℝ) = s := by have : ⋃ f : ι, (f : E → ℝ).support = s := by refine Subset.antisymm (iUnion_subset fun f => f.2.1) ?_ @@ -116,7 +116,7 @@ theorem IsOpen.exists_smooth_support_eq {s : Set E} (hs : IsOpen s) : rcases iT with ⟨n, hn⟩ rw [← hn] at hi exact ⟨n, hi⟩ - have g_smooth : ∀ n, ContDiff ℝ ⊤ (g n) := fun n => (g0 n).2.2.2.1 + have g_smooth : ∀ n, ContDiff ℝ ∞ (g n) := fun n => (g0 n).2.2.2.1 have g_comp_supp : ∀ n, HasCompactSupport (g n) := fun n => (g0 n).2.2.1 have g_nonneg : ∀ n x, 0 ≤ g n x := fun n x => ((g0 n).2.2.2.2 (mem_range_self x)).1 obtain ⟨δ, δpos, c, δc, c_lt⟩ : @@ -127,8 +127,8 @@ theorem IsOpen.exists_smooth_support_eq {s : Set E} (hs : IsOpen s) : have : ∀ i, ∃ R, ∀ x, ‖iteratedFDeriv ℝ i (fun x => g n x) x‖ ≤ R := by intro i have : BddAbove (range fun x => ‖iteratedFDeriv ℝ i (fun x : E => g n x) x‖) := by - apply - ((g_smooth n).continuous_iteratedFDeriv le_top).norm.bddAbove_range_of_hasCompactSupport + apply ((g_smooth n).continuous_iteratedFDeriv + (mod_cast le_top)).norm.bddAbove_range_of_hasCompactSupport apply HasCompactSupport.comp_left _ norm_zero apply (g_comp_supp n).iteratedFDeriv rcases this with ⟨R, hR⟩ @@ -148,7 +148,8 @@ theorem IsOpen.exists_smooth_support_eq {s : Set E} (hs : IsOpen s) : refine ⟨M⁻¹ * δ n, by positivity, fun i hi x => ?_⟩ calc ‖iteratedFDeriv ℝ i ((M⁻¹ * δ n) • g n) x‖ = ‖(M⁻¹ * δ n) • iteratedFDeriv ℝ i (g n) x‖ := by - rw [iteratedFDeriv_const_smul_apply]; exact (g_smooth n).of_le le_top + rw [iteratedFDeriv_const_smul_apply] + exact (g_smooth n).of_le (mod_cast le_top) _ = M⁻¹ * δ n * ‖iteratedFDeriv ℝ i (g n) x‖ := by rw [norm_smul _ (iteratedFDeriv ℝ i (g n) x), Real.norm_of_nonneg]; positivity _ ≤ M⁻¹ * δ n * M := (mul_le_mul_of_nonneg_left ((hR i x).trans (IR i hi)) (by positivity)) @@ -207,10 +208,10 @@ variable (E) theorem u_exists : ∃ u : E → ℝ, - ContDiff ℝ ⊤ u ∧ (∀ x, u x ∈ Icc (0 : ℝ) 1) ∧ support u = ball 0 1 ∧ ∀ x, u (-x) = u x := by + ContDiff ℝ ∞ u ∧ (∀ x, u x ∈ Icc (0 : ℝ) 1) ∧ support u = ball 0 1 ∧ ∀ x, u (-x) = u x := by have A : IsOpen (ball (0 : E) 1) := isOpen_ball obtain ⟨f, f_support, f_smooth, f_range⟩ : - ∃ f : E → ℝ, f.support = ball (0 : E) 1 ∧ ContDiff ℝ ⊤ f ∧ Set.range f ⊆ Set.Icc 0 1 := + ∃ f : E → ℝ, f.support = ball (0 : E) 1 ∧ ContDiff ℝ ∞ f ∧ Set.range f ⊆ Set.Icc 0 1 := A.exists_smooth_support_eq have B : ∀ x, f x ∈ Icc (0 : ℝ) 1 := fun x => f_range (mem_range_self x) refine ⟨fun x => (f x + f (-x)) / 2, ?_, ?_, ?_, ?_⟩ @@ -243,7 +244,7 @@ def u (x : E) : ℝ := variable (E) -theorem u_smooth : ContDiff ℝ ⊤ (u : E → ℝ) := +theorem u_smooth : ContDiff ℝ ∞ (u : E → ℝ) := (Classical.choose_spec (u_exists E)).1 theorem u_continuous : Continuous (u : E → ℝ) := @@ -433,7 +434,7 @@ theorem y_pos_of_mem_ball {D : ℝ} {x : E} (Dpos : 0 < D) (D_lt_one : D < 1) variable (E) -theorem y_smooth : ContDiffOn ℝ ⊤ (uncurry y) (Ioo (0 : ℝ) 1 ×ˢ (univ : Set E)) := by +theorem y_smooth : ContDiffOn ℝ ∞ (uncurry y) (Ioo (0 : ℝ) 1 ×ˢ (univ : Set E)) := by have hs : IsOpen (Ioo (0 : ℝ) (1 : ℝ)) := isOpen_Ioo have hk : IsCompact (closedBall (0 : E) 1) := ProperSpace.isCompact_closedBall _ _ refine contDiffOn_convolution_left_with_param (lsmul ℝ ℝ) hs hk ?_ ?_ ?_ @@ -489,7 +490,7 @@ instance (priority := 100) {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E · rfl smooth := by suffices - ContDiffOn ℝ ⊤ + ContDiffOn ℝ ∞ (uncurry y ∘ fun p : ℝ × E => ((p.1 - 1) / (p.1 + 1), ((p.1 + 1) / 2)⁻¹ • p.2)) (Ioi 1 ×ˢ univ) by apply this.congr diff --git a/Mathlib/Analysis/Calculus/ContDiff/Basic.lean b/Mathlib/Analysis/Calculus/ContDiff/Basic.lean index 52ac217ea8cf2..ad3ed57edf02c 100644 --- a/Mathlib/Analysis/Calculus/ContDiff/Basic.lean +++ b/Mathlib/Analysis/Calculus/ContDiff/Basic.lean @@ -26,7 +26,7 @@ Similar results are given for `C^n` functions on domains. We use the notation `E [×n]→L[𝕜] F` for the space of continuous multilinear maps on `E^n` with values in `F`. This is the space in which the `n`-th derivative of a function from `E` to `F` lives. -In this file, we denote `⊤ : ℕ∞` with `∞`. +In this file, we denote `(⊤ : ℕ∞) : WithTop ℕ∞` with `∞` and `⊤ : WithTop ℕ∞` with `ω`. ## Tags @@ -35,9 +35,7 @@ derivative, differentiability, higher derivative, `C^n`, multilinear, Taylor ser noncomputable section -open scoped NNReal Nat - -local notation "∞" => (⊤ : ℕ∞) +open scoped NNReal Nat ContDiff universe u uE uF uG @@ -52,7 +50,7 @@ variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type uE} [NormedAddCommGroup E] [NormedSpace 𝕜 E] {F : Type uF} [NormedAddCommGroup F] [NormedSpace 𝕜 F] {G : Type uG} [NormedAddCommGroup G] [NormedSpace 𝕜 G] {X : Type*} [NormedAddCommGroup X] [NormedSpace 𝕜 X] {s t : Set E} {f : E → F} - {g : F → G} {x x₀ : E} {b : E × F → G} {m n : ℕ∞} {p : E → FormalMultilinearSeries 𝕜 E F} + {g : F → G} {x x₀ : E} {b : E × F → G} {m n : WithTop ℕ∞} {p : E → FormalMultilinearSeries 𝕜 E F} /-! ### Constants -/ @@ -72,16 +70,18 @@ theorem iteratedFDeriv_zero_fun {n : ℕ} : (iteratedFDeriv 𝕜 n fun _ : E ↦ funext fun x ↦ by simpa [← iteratedFDerivWithin_univ] using iteratedFDerivWithin_zero_fun uniqueDiffOn_univ (mem_univ x) -theorem contDiff_zero_fun : ContDiff 𝕜 n fun _ : E => (0 : F) := - contDiff_of_differentiable_iteratedFDeriv fun m _ => by - rw [iteratedFDeriv_zero_fun] - exact differentiable_const (0 : E[×m]→L[𝕜] F) +theorem contDiff_zero_fun : ContDiff 𝕜 n fun _ : E => (0 : F) := by + suffices ContDiff 𝕜 ω (fun _ : E => (0 : F)) from this.of_le le_top + rw [← contDiff_infty_iff_contDiff_omega] + apply contDiff_of_differentiable_iteratedFDeriv fun m _ ↦ ?_ + rw [iteratedFDeriv_zero_fun] + exact differentiable_const (0 : E[×m]→L[𝕜] F) /-- Constants are `C^∞`. -/ theorem contDiff_const {c : F} : ContDiff 𝕜 n fun _ : E => c := by - suffices h : ContDiff 𝕜 ∞ fun _ : E => c from h.of_le le_top - rw [contDiff_top_iff_fderiv] + suffices h : ContDiff 𝕜 ω fun _ : E => c from h.of_le le_top + rw [← contDiff_infty_iff_contDiff_omega, contDiff_top_iff_fderiv] refine ⟨differentiable_const c, ?_⟩ rw [fderiv_const] exact contDiff_zero_fun @@ -144,8 +144,8 @@ theorem contDiffWithinAt_singleton : ContDiffWithinAt 𝕜 n f {x} x := /-- Unbundled bounded linear functions are `C^∞`. -/ theorem IsBoundedLinearMap.contDiff (hf : IsBoundedLinearMap 𝕜 f) : ContDiff 𝕜 n f := by - suffices h : ContDiff 𝕜 ∞ f from h.of_le le_top - rw [contDiff_top_iff_fderiv] + suffices h : ContDiff 𝕜 ω f from h.of_le le_top + rw [← contDiff_infty_iff_contDiff_omega, contDiff_top_iff_fderiv] refine ⟨hf.differentiable, ?_⟩ simp_rw [hf.fderiv] exact contDiff_const @@ -179,8 +179,8 @@ theorem contDiffOn_id {s} : ContDiffOn 𝕜 n (id : E → E) s := /-- Bilinear functions are `C^∞`. -/ theorem IsBoundedBilinearMap.contDiff (hb : IsBoundedBilinearMap 𝕜 b) : ContDiff 𝕜 n b := by - suffices h : ContDiff 𝕜 ∞ b from h.of_le le_top - rw [contDiff_top_iff_fderiv] + suffices h : ContDiff 𝕜 ω b from h.of_le le_top + rw [← contDiff_infty_iff_contDiff_omega, contDiff_top_iff_fderiv] refine ⟨hb.differentiable, ?_⟩ simp only [hb.fderiv] exact hb.isBoundedLinearMap_deriv.contDiff @@ -883,8 +883,8 @@ section ClmApplyConst /-- Application of a `ContinuousLinearMap` to a constant commutes with `iteratedFDerivWithin`. -/ theorem iteratedFDerivWithin_clm_apply_const_apply - {s : Set E} (hs : UniqueDiffOn 𝕜 s) {n : ℕ∞} {c : E → F →L[𝕜] G} (hc : ContDiffOn 𝕜 n c s) - {i : ℕ} (hi : i ≤ n) {x : E} (hx : x ∈ s) {u : F} {m : Fin i → E} : + {s : Set E} (hs : UniqueDiffOn 𝕜 s) {c : E → F →L[𝕜] G} + (hc : ContDiffOn 𝕜 n c s) {i : ℕ} (hi : i ≤ n) {x : E} (hx : x ∈ s) {u : F} {m : Fin i → E} : (iteratedFDerivWithin 𝕜 i (fun y ↦ (c y) u) s x) m = (iteratedFDerivWithin 𝕜 i c s x) m u := by induction i generalizing x with | zero => simp @@ -905,7 +905,7 @@ theorem iteratedFDerivWithin_clm_apply_const_apply /-- Application of a `ContinuousLinearMap` to a constant commutes with `iteratedFDeriv`. -/ theorem iteratedFDeriv_clm_apply_const_apply - {n : ℕ∞} {c : E → F →L[𝕜] G} (hc : ContDiff 𝕜 n c) + {c : E → F →L[𝕜] G} (hc : ContDiff 𝕜 n c) {i : ℕ} (hi : i ≤ n) {x : E} {u : F} {m : Fin i → E} : (iteratedFDeriv 𝕜 i (fun y ↦ (c y) u) x) m = (iteratedFDeriv 𝕜 i c x) m u := by simp only [← iteratedFDerivWithin_univ] @@ -977,7 +977,7 @@ To show that `x ↦ D_yf(x,y)g(x)` (taken within `t`) is `C^m` at `x₀` within * `g` is `C^m` at `x₀` within `s`; * Derivatives are unique at `g(x)` within `t` for `x` sufficiently close to `x₀` within `s ∪ {x₀}`; * `t` is a neighborhood of `g(x₀)` within `g '' s`; -/ -theorem ContDiffWithinAt.fderivWithin'' {f : E → F → G} {g : E → F} {t : Set F} {n : ℕ∞} +theorem ContDiffWithinAt.fderivWithin'' {f : E → F → G} {g : E → F} {t : Set F} (hf : ContDiffWithinAt 𝕜 n (Function.uncurry f) (insert x₀ s ×ˢ t) (x₀, g x₀)) (hg : ContDiffWithinAt 𝕜 m g s x₀) (ht : ∀ᶠ x in 𝓝[insert x₀ s] x₀, UniqueDiffWithinAt 𝕜 t (g x)) (hmn : m + 1 ≤ n) @@ -990,14 +990,18 @@ theorem ContDiffWithinAt.fderivWithin'' {f : E → F → G} {g : E → F} {t : S refine hf'.congr_of_eventuallyEq_insert ?_ filter_upwards [hv, ht] exact fun y hy h2y => (hvf' y hy).fderivWithin h2y - induction' m with m - · obtain rfl := eq_top_iff.mpr hmn + match m with + | ω => + intro k hk + apply this k hk + exact le_rfl + | ∞ => rw [contDiffWithinAt_top] - exact fun m => this m le_top - exact this _ le_rfl + exact fun m => this m (mod_cast le_top) + | (m : ℕ) => exact this _ le_rfl /-- A special case of `ContDiffWithinAt.fderivWithin''` where we require that `s ⊆ g⁻¹(t)`. -/ -theorem ContDiffWithinAt.fderivWithin' {f : E → F → G} {g : E → F} {t : Set F} {n : ℕ∞} +theorem ContDiffWithinAt.fderivWithin' {f : E → F → G} {g : E → F} {t : Set F} (hf : ContDiffWithinAt 𝕜 n (Function.uncurry f) (insert x₀ s ×ˢ t) (x₀, g x₀)) (hg : ContDiffWithinAt 𝕜 m g s x₀) (ht : ∀ᶠ x in 𝓝[insert x₀ s] x₀, UniqueDiffWithinAt 𝕜 t (g x)) (hmn : m + 1 ≤ n) @@ -1006,7 +1010,7 @@ theorem ContDiffWithinAt.fderivWithin' {f : E → F → G} {g : E → F} {t : Se /-- A special case of `ContDiffWithinAt.fderivWithin'` where we require that `x₀ ∈ s` and there are unique derivatives everywhere within `t`. -/ -protected theorem ContDiffWithinAt.fderivWithin {f : E → F → G} {g : E → F} {t : Set F} {n : ℕ∞} +protected theorem ContDiffWithinAt.fderivWithin {f : E → F → G} {g : E → F} {t : Set F} (hf : ContDiffWithinAt 𝕜 n (Function.uncurry f) (s ×ˢ t) (x₀, g x₀)) (hg : ContDiffWithinAt 𝕜 m g s x₀) (ht : UniqueDiffOn 𝕜 t) (hmn : m + 1 ≤ n) (hx₀ : x₀ ∈ s) (hst : s ⊆ g ⁻¹' t) : ContDiffWithinAt 𝕜 m (fun x => fderivWithin 𝕜 (f x) t (g x)) s x₀ := by @@ -1016,7 +1020,7 @@ protected theorem ContDiffWithinAt.fderivWithin {f : E → F → G} {g : E → F exact eventually_of_mem self_mem_nhdsWithin fun x hx => ht _ (hst hx) /-- `x ↦ fderivWithin 𝕜 (f x) t (g x) (k x)` is smooth at a point within a set. -/ -theorem ContDiffWithinAt.fderivWithin_apply {f : E → F → G} {g k : E → F} {t : Set F} {n : ℕ∞} +theorem ContDiffWithinAt.fderivWithin_apply {f : E → F → G} {g k : E → F} {t : Set F} (hf : ContDiffWithinAt 𝕜 n (Function.uncurry f) (s ×ˢ t) (x₀, g x₀)) (hg : ContDiffWithinAt 𝕜 m g s x₀) (hk : ContDiffWithinAt 𝕜 m k s x₀) (ht : UniqueDiffOn 𝕜 t) (hmn : m + 1 ≤ n) (hx₀ : x₀ ∈ s) (hst : s ⊆ g ⁻¹' t) : @@ -1026,7 +1030,7 @@ theorem ContDiffWithinAt.fderivWithin_apply {f : E → F → G} {g k : E → F} /-- `fderivWithin 𝕜 f s` is smooth at `x₀` within `s`. -/ theorem ContDiffWithinAt.fderivWithin_right (hf : ContDiffWithinAt 𝕜 n f s x₀) - (hs : UniqueDiffOn 𝕜 s) (hmn : (m + 1 : ℕ∞) ≤ n) (hx₀s : x₀ ∈ s) : + (hs : UniqueDiffOn 𝕜 s) (hmn : m + 1 ≤ n) (hx₀s : x₀ ∈ s) : ContDiffWithinAt 𝕜 m (fderivWithin 𝕜 f s) s x₀ := ContDiffWithinAt.fderivWithin (ContDiffWithinAt.comp (x₀, x₀) hf contDiffWithinAt_snd <| prod_subset_preimage_snd s s) @@ -1036,7 +1040,7 @@ theorem ContDiffWithinAt.fderivWithin_right (hf : ContDiffWithinAt 𝕜 n f s x theorem ContDiffWithinAt.fderivWithin_right_apply {f : F → G} {k : F → F} {s : Set F} {n : ℕ∞} {x₀ : F} (hf : ContDiffWithinAt 𝕜 n f s x₀) (hk : ContDiffWithinAt 𝕜 m k s x₀) - (hs : UniqueDiffOn 𝕜 s) (hmn : (m + 1 : ℕ∞) ≤ n) (hx₀s : x₀ ∈ s) : + (hs : UniqueDiffOn 𝕜 s) (hmn : m + 1 ≤ n) (hx₀s : x₀ ∈ s) : ContDiffWithinAt 𝕜 m (fun x => fderivWithin 𝕜 f s x (k x)) s x₀ := ContDiffWithinAt.fderivWithin_apply (ContDiffWithinAt.comp (x₀, x₀) hf contDiffWithinAt_snd <| prod_subset_preimage_snd s s) @@ -1044,10 +1048,10 @@ theorem ContDiffWithinAt.fderivWithin_right_apply -- TODO: can we make a version of `ContDiffWithinAt.fderivWithin` for iterated derivatives? theorem ContDiffWithinAt.iteratedFderivWithin_right {i : ℕ} (hf : ContDiffWithinAt 𝕜 n f s x₀) - (hs : UniqueDiffOn 𝕜 s) (hmn : (m + i : ℕ∞) ≤ n) (hx₀s : x₀ ∈ s) : + (hs : UniqueDiffOn 𝕜 s) (hmn : m + i ≤ n) (hx₀s : x₀ ∈ s) : ContDiffWithinAt 𝕜 m (iteratedFDerivWithin 𝕜 i f s) s x₀ := by induction' i with i hi generalizing m - · rw [ENat.coe_zero, add_zero] at hmn + · simp only [CharP.cast_eq_zero, add_zero] at hmn exact (hf.of_le hmn).continuousLinearMap_comp ((continuousMultilinearCurryFin0 𝕜 E F).symm : _ →L[𝕜] E [×0]→L[𝕜] F) · rw [Nat.cast_succ, add_comm _ 1, ← add_assoc] at hmn @@ -1056,7 +1060,7 @@ theorem ContDiffWithinAt.iteratedFderivWithin_right {i : ℕ} (hf : ContDiffWith _ →L[𝕜] E [×(i+1)]→L[𝕜] F) /-- `x ↦ fderiv 𝕜 (f x) (g x)` is smooth at `x₀`. -/ -protected theorem ContDiffAt.fderiv {f : E → F → G} {g : E → F} {n : ℕ∞} +protected theorem ContDiffAt.fderiv {f : E → F → G} {g : E → F} (hf : ContDiffAt 𝕜 n (Function.uncurry f) (x₀, g x₀)) (hg : ContDiffAt 𝕜 m g x₀) (hmn : m + 1 ≤ n) : ContDiffAt 𝕜 m (fun x => fderiv 𝕜 (f x) (g x)) x₀ := by simp_rw [← fderivWithin_univ] @@ -1065,44 +1069,44 @@ protected theorem ContDiffAt.fderiv {f : E → F → G} {g : E → F} {n : ℕ rw [preimage_univ] /-- `fderiv 𝕜 f` is smooth at `x₀`. -/ -theorem ContDiffAt.fderiv_right (hf : ContDiffAt 𝕜 n f x₀) (hmn : (m + 1 : ℕ∞) ≤ n) : +theorem ContDiffAt.fderiv_right (hf : ContDiffAt 𝕜 n f x₀) (hmn : m + 1 ≤ n) : ContDiffAt 𝕜 m (fderiv 𝕜 f) x₀ := ContDiffAt.fderiv (ContDiffAt.comp (x₀, x₀) hf contDiffAt_snd) contDiffAt_id hmn theorem ContDiffAt.iteratedFDeriv_right {i : ℕ} (hf : ContDiffAt 𝕜 n f x₀) - (hmn : (m + i : ℕ∞) ≤ n) : ContDiffAt 𝕜 m (iteratedFDeriv 𝕜 i f) x₀ := by + (hmn : m + i ≤ n) : ContDiffAt 𝕜 m (iteratedFDeriv 𝕜 i f) x₀ := by rw [← iteratedFDerivWithin_univ, ← contDiffWithinAt_univ] at * exact hf.iteratedFderivWithin_right uniqueDiffOn_univ hmn trivial /-- `x ↦ fderiv 𝕜 (f x) (g x)` is smooth. -/ -protected theorem ContDiff.fderiv {f : E → F → G} {g : E → F} {n m : ℕ∞} +protected theorem ContDiff.fderiv {f : E → F → G} {g : E → F} (hf : ContDiff 𝕜 m <| Function.uncurry f) (hg : ContDiff 𝕜 n g) (hnm : n + 1 ≤ m) : ContDiff 𝕜 n fun x => fderiv 𝕜 (f x) (g x) := contDiff_iff_contDiffAt.mpr fun _ => hf.contDiffAt.fderiv hg.contDiffAt hnm /-- `fderiv 𝕜 f` is smooth. -/ -theorem ContDiff.fderiv_right (hf : ContDiff 𝕜 n f) (hmn : (m + 1 : ℕ∞) ≤ n) : +theorem ContDiff.fderiv_right (hf : ContDiff 𝕜 n f) (hmn : m + 1 ≤ n) : ContDiff 𝕜 m (fderiv 𝕜 f) := contDiff_iff_contDiffAt.mpr fun _x => hf.contDiffAt.fderiv_right hmn theorem ContDiff.iteratedFDeriv_right {i : ℕ} (hf : ContDiff 𝕜 n f) - (hmn : (m + i : ℕ∞) ≤ n) : ContDiff 𝕜 m (iteratedFDeriv 𝕜 i f) := + (hmn : m + i ≤ n) : ContDiff 𝕜 m (iteratedFDeriv 𝕜 i f) := contDiff_iff_contDiffAt.mpr fun _x => hf.contDiffAt.iteratedFDeriv_right hmn /-- `x ↦ fderiv 𝕜 (f x) (g x)` is continuous. -/ -theorem Continuous.fderiv {f : E → F → G} {g : E → F} {n : ℕ∞} +theorem Continuous.fderiv {f : E → F → G} {g : E → F} (hf : ContDiff 𝕜 n <| Function.uncurry f) (hg : Continuous g) (hn : 1 ≤ n) : Continuous fun x => fderiv 𝕜 (f x) (g x) := (hf.fderiv (contDiff_zero.mpr hg) hn).continuous /-- `x ↦ fderiv 𝕜 (f x) (g x) (k x)` is smooth. -/ -theorem ContDiff.fderiv_apply {f : E → F → G} {g k : E → F} {n m : ℕ∞} +theorem ContDiff.fderiv_apply {f : E → F → G} {g k : E → F} (hf : ContDiff 𝕜 m <| Function.uncurry f) (hg : ContDiff 𝕜 n g) (hk : ContDiff 𝕜 n k) (hnm : n + 1 ≤ m) : ContDiff 𝕜 n fun x => fderiv 𝕜 (f x) (g x) (k x) := (hf.fderiv hg hnm).clm_apply hk /-- The bundled derivative of a `C^{n+1}` function is `C^n`. -/ -theorem contDiffOn_fderivWithin_apply {m n : ℕ∞} {s : Set E} {f : E → F} (hf : ContDiffOn 𝕜 n f s) +theorem contDiffOn_fderivWithin_apply {s : Set E} {f : E → F} (hf : ContDiffOn 𝕜 n f s) (hs : UniqueDiffOn 𝕜 s) (hmn : m + 1 ≤ n) : ContDiffOn 𝕜 m (fun p : E × E => (fderivWithin 𝕜 f s p.1 : E →L[𝕜] F) p.2) (s ×ˢ univ) := ((hf.fderivWithin hs hmn).comp contDiffOn_fst (prod_subset_preimage_fst _ _)).clm_apply @@ -1176,7 +1180,7 @@ theorem contDiffAt_pi : ContDiffAt 𝕜 n Φ x ↔ ∀ i, ContDiffAt 𝕜 n (fun theorem contDiff_pi : ContDiff 𝕜 n Φ ↔ ∀ i, ContDiff 𝕜 n fun x => Φ x i := by simp only [← contDiffOn_univ, contDiffOn_pi] -theorem contDiff_update [DecidableEq ι] (k : ℕ∞) (x : ∀ i, F' i) (i : ι) : +theorem contDiff_update [DecidableEq ι] (k : WithTop ℕ∞) (x : ∀ i, F' i) (i : ι) : ContDiff 𝕜 k (update x i) := by rw [contDiff_pi] intro j @@ -1187,7 +1191,7 @@ theorem contDiff_update [DecidableEq ι] (k : ℕ∞) (x : ∀ i, F' i) (i : ι) · exact contDiff_const variable (F') in -theorem contDiff_single [DecidableEq ι] (k : ℕ∞) (i : ι) : +theorem contDiff_single [DecidableEq ι] (k : WithTop ℕ∞) (i : ι) : ContDiff 𝕜 k (Pi.single i : F' i → ∀ i, F' i) := contDiff_update k 0 i @@ -1207,7 +1211,7 @@ section Add theorem HasFTaylorSeriesUpToOn.add {n : WithTop ℕ∞} {q g} (hf : HasFTaylorSeriesUpToOn n f p s) (hg : HasFTaylorSeriesUpToOn n g q s) : HasFTaylorSeriesUpToOn n (f + g) (p + q) s := by - convert HasFTaylorSeriesUpToOn.continuousLinearMap_comp + exact HasFTaylorSeriesUpToOn.continuousLinearMap_comp (ContinuousLinearMap.fst 𝕜 F F + .snd 𝕜 F F) (hf.prod hg) -- The sum is smooth. @@ -1637,6 +1641,10 @@ invertible element. The proof is by induction, bootstrapping using an identity derivative of inversion as a bilinear map of inversion itself. -/ theorem contDiffAt_ring_inverse [CompleteSpace R] (x : Rˣ) : ContDiffAt 𝕜 n Ring.inverse (x : R) := by + suffices H : ∀ (n : ℕ∞), ContDiffAt 𝕜 n Ring.inverse (x : R) by + intro k hk + exact H ⊤ k (mod_cast le_top) + intro n induction' n using ENat.nat_induction with n IH Itop · intro m hm refine ⟨{ y : R | IsUnit y }, ?_, ?_⟩ @@ -1648,7 +1656,7 @@ theorem contDiffAt_ring_inverse [CompleteSpace R] (x : Rˣ) : · rintro _ ⟨x', rfl⟩ exact (inverse_continuousAt x').continuousWithinAt · simp [ftaylorSeriesWithin] - · rw [show (n.succ : ℕ∞) = n + 1 from rfl, contDiffAt_succ_iff_hasFDerivAt] + · rw [show ((n.succ : ℕ∞) : WithTop ℕ∞) = n + 1 from rfl, contDiffAt_succ_iff_hasFDerivAt] refine ⟨fun x : R => -mulLeftRight 𝕜 R (inverse x) (inverse x), ?_, ?_⟩ · refine ⟨{ y : R | IsUnit y }, x.nhds, ?_⟩ rintro _ ⟨y, rfl⟩ @@ -1671,36 +1679,36 @@ variable {𝕜} -- TODO: the next few lemmas don't need `𝕜` or `𝕜'` to be complete -- A good way to show this is to generalize `contDiffAt_ring_inverse` to the setting -- of a function `f` such that `∀ᶠ x in 𝓝 a, x * f x = 1`. -theorem ContDiffWithinAt.inv {f : E → 𝕜'} {n} (hf : ContDiffWithinAt 𝕜 n f s x) (hx : f x ≠ 0) : +theorem ContDiffWithinAt.inv {f : E → 𝕜'} (hf : ContDiffWithinAt 𝕜 n f s x) (hx : f x ≠ 0) : ContDiffWithinAt 𝕜 n (fun x => (f x)⁻¹) s x := (contDiffAt_inv 𝕜 hx).comp_contDiffWithinAt x hf -theorem ContDiffOn.inv {f : E → 𝕜'} {n} (hf : ContDiffOn 𝕜 n f s) (h : ∀ x ∈ s, f x ≠ 0) : +theorem ContDiffOn.inv {f : E → 𝕜'} (hf : ContDiffOn 𝕜 n f s) (h : ∀ x ∈ s, f x ≠ 0) : ContDiffOn 𝕜 n (fun x => (f x)⁻¹) s := fun x hx => (hf.contDiffWithinAt hx).inv (h x hx) -nonrec theorem ContDiffAt.inv {f : E → 𝕜'} {n} (hf : ContDiffAt 𝕜 n f x) (hx : f x ≠ 0) : +nonrec theorem ContDiffAt.inv {f : E → 𝕜'} (hf : ContDiffAt 𝕜 n f x) (hx : f x ≠ 0) : ContDiffAt 𝕜 n (fun x => (f x)⁻¹) x := hf.inv hx -theorem ContDiff.inv {f : E → 𝕜'} {n} (hf : ContDiff 𝕜 n f) (h : ∀ x, f x ≠ 0) : +theorem ContDiff.inv {f : E → 𝕜'} (hf : ContDiff 𝕜 n f) (h : ∀ x, f x ≠ 0) : ContDiff 𝕜 n fun x => (f x)⁻¹ := by rw [contDiff_iff_contDiffAt]; exact fun x => hf.contDiffAt.inv (h x) -- TODO: generalize to `f g : E → 𝕜'` -theorem ContDiffWithinAt.div [CompleteSpace 𝕜] {f g : E → 𝕜} {n} (hf : ContDiffWithinAt 𝕜 n f s x) +theorem ContDiffWithinAt.div [CompleteSpace 𝕜] {f g : E → 𝕜} (hf : ContDiffWithinAt 𝕜 n f s x) (hg : ContDiffWithinAt 𝕜 n g s x) (hx : g x ≠ 0) : ContDiffWithinAt 𝕜 n (fun x => f x / g x) s x := by simpa only [div_eq_mul_inv] using hf.mul (hg.inv hx) -theorem ContDiffOn.div [CompleteSpace 𝕜] {f g : E → 𝕜} {n} (hf : ContDiffOn 𝕜 n f s) +theorem ContDiffOn.div [CompleteSpace 𝕜] {f g : E → 𝕜} (hf : ContDiffOn 𝕜 n f s) (hg : ContDiffOn 𝕜 n g s) (h₀ : ∀ x ∈ s, g x ≠ 0) : ContDiffOn 𝕜 n (f / g) s := fun x hx => (hf x hx).div (hg x hx) (h₀ x hx) -nonrec theorem ContDiffAt.div [CompleteSpace 𝕜] {f g : E → 𝕜} {n} (hf : ContDiffAt 𝕜 n f x) +nonrec theorem ContDiffAt.div [CompleteSpace 𝕜] {f g : E → 𝕜} (hf : ContDiffAt 𝕜 n f x) (hg : ContDiffAt 𝕜 n g x) (hx : g x ≠ 0) : ContDiffAt 𝕜 n (fun x => f x / g x) x := hf.div hg hx -theorem ContDiff.div [CompleteSpace 𝕜] {f g : E → 𝕜} {n} (hf : ContDiff 𝕜 n f) (hg : ContDiff 𝕜 n g) +theorem ContDiff.div [CompleteSpace 𝕜] {f g : E → 𝕜} (hf : ContDiff 𝕜 n f) (hg : ContDiff 𝕜 n g) (h0 : ∀ x, g x ≠ 0) : ContDiff 𝕜 n fun x => f x / g x := by simp only [contDiff_iff_contDiffAt] at * exact fun x => (hf x).div (hg x) (h0 x) @@ -1738,23 +1746,17 @@ section FunctionInverse open ContinuousLinearMap -/-- If `f` is a local homeomorphism and the point `a` is in its target, -and if `f` is `n` times continuously differentiable at `f.symm a`, -and if the derivative at `f.symm a` is a continuous linear equivalence, -then `f.symm` is `n` times continuously differentiable at the point `a`. - -This is one of the easy parts of the inverse function theorem: it assumes that we already have -an inverse function. -/ -theorem PartialHomeomorph.contDiffAt_symm [CompleteSpace E] (f : PartialHomeomorph E F) +private theorem PartialHomeomorph.contDiffAt_symm_aux {n : ℕ∞} + [CompleteSpace E] (f : PartialHomeomorph E F) {f₀' : E ≃L[𝕜] F} {a : F} (ha : a ∈ f.target) (hf₀' : HasFDerivAt f (f₀' : E →L[𝕜] F) (f.symm a)) (hf : ContDiffAt 𝕜 n f (f.symm a)) : ContDiffAt 𝕜 n f.symm a := by - -- We prove this by induction on `n` + -- We prove this by induction on `n` induction' n using ENat.nat_induction with n IH Itop - · rw [contDiffAt_zero] + · apply contDiffAt_zero.2 exact ⟨f.target, IsOpen.mem_nhds f.open_target ha, f.continuousOn_invFun⟩ · obtain ⟨f', ⟨u, hu, hff'⟩, hf'⟩ := contDiffAt_succ_iff_hasFDerivAt.mp hf - rw [show (n.succ : ℕ∞) = n + 1 from rfl, contDiffAt_succ_iff_hasFDerivAt] + rw [show ((n.succ : ℕ∞) : WithTop ℕ∞) = n + 1 from rfl, contDiffAt_succ_iff_hasFDerivAt] -- For showing `n.succ` times continuous differentiability (the main inductive step), it -- suffices to produce the derivative and show that it is `n` times continuously differentiable have eq_f₀' : f' (f.symm a) = f₀' := (hff' (f.symm a) (mem_of_mem_nhds hu)).unique hf₀' @@ -1791,6 +1793,24 @@ theorem PartialHomeomorph.contDiffAt_symm [CompleteSpace E] (f : PartialHomeomor intro n exact Itop n (contDiffAt_top.mp hf n) +/-- If `f` is a local homeomorphism and the point `a` is in its target, +and if `f` is `n` times continuously differentiable at `f.symm a`, +and if the derivative at `f.symm a` is a continuous linear equivalence, +then `f.symm` is `n` times continuously differentiable at the point `a`. + +This is one of the easy parts of the inverse function theorem: it assumes that we already have +an inverse function. -/ +theorem PartialHomeomorph.contDiffAt_symm [CompleteSpace E] (f : PartialHomeomorph E F) + {f₀' : E ≃L[𝕜] F} {a : F} (ha : a ∈ f.target) + (hf₀' : HasFDerivAt f (f₀' : E →L[𝕜] F) (f.symm a)) (hf : ContDiffAt 𝕜 n f (f.symm a)) : + ContDiffAt 𝕜 n f.symm a := by + match n with + | ω => + intro k hk + exact f.contDiffAt_symm_aux ha hf₀' (hf.of_le (m := k) le_top) k le_rfl + | (n : ℕ∞) => + exact f.contDiffAt_symm_aux ha hf₀' hf + /-- If `f` is an `n` times continuously differentiable homeomorphism, and if the derivative of `f` at each point is a continuous linear equivalence, then `f.symm` is `n` times continuously differentiable. @@ -1905,14 +1925,14 @@ theorem contDiffOn_top_iff_derivWithin (hs : UniqueDiffOn 𝕜 s₂) : ContDiffOn 𝕜 ∞ f₂ s₂ ↔ DifferentiableOn 𝕜 f₂ s₂ ∧ ContDiffOn 𝕜 ∞ (derivWithin f₂ s₂) s₂ := by constructor · intro h - refine ⟨h.differentiableOn le_top, ?_⟩ + refine ⟨h.differentiableOn (mod_cast le_top), ?_⟩ refine contDiffOn_top.2 fun n => ((contDiffOn_succ_iff_derivWithin hs).1 ?_).2 - exact h.of_le le_top + exact h.of_le (mod_cast le_top) · intro h refine contDiffOn_top.2 fun n => ?_ - have A : (n : ℕ∞) ≤ ∞ := le_top + have A : (n : ℕ∞) ≤ ∞ := mod_cast le_top apply ((contDiffOn_succ_iff_derivWithin hs).2 ⟨h.1, h.2.of_le A⟩).of_le - exact WithTop.coe_le_coe.2 (Nat.le_succ n) + exact_mod_cast (Nat.le_succ n) /-- A function is `C^∞` on an open domain if and only if it is differentiable there, and its derivative (formulated with `deriv`) is `C^∞`. -/ @@ -1923,13 +1943,17 @@ theorem contDiffOn_top_iff_deriv_of_isOpen (hs : IsOpen s₂) : protected theorem ContDiffOn.derivWithin (hf : ContDiffOn 𝕜 n f₂ s₂) (hs : UniqueDiffOn 𝕜 s₂) (hmn : m + 1 ≤ n) : ContDiffOn 𝕜 m (derivWithin f₂ s₂) s₂ := by - cases m - · change ∞ + 1 ≤ n at hmn - have : n = ∞ := by simpa using hmn - rw [this] at hf - exact ((contDiffOn_top_iff_derivWithin hs).1 hf).2 - · change (Nat.succ _ : ℕ∞) ≤ n at hmn - exact ((contDiffOn_succ_iff_derivWithin hs).1 (hf.of_le hmn)).2 + rcases le_or_lt ∞ n with hn | hn + · have : ContDiffOn 𝕜 ∞ (derivWithin f₂ s₂) s₂ := + ((contDiffOn_top_iff_derivWithin hs).1 (hf.of_le hn)).2 + intro x hx k hk + exact this x hx k (mod_cast le_top) + · match m with + | ω => simpa using hmn.trans_lt hn + | ∞ => simpa using hmn.trans_lt hn + | (m : ℕ) => + change (m.succ : ℕ∞) ≤ n at hmn + exact ((contDiffOn_succ_iff_derivWithin hs).1 (hf.of_le hmn)).2 theorem ContDiffOn.deriv_of_isOpen (hf : ContDiffOn 𝕜 n f₂ s₂) (hs : IsOpen s₂) (hmn : m + 1 ≤ n) : ContDiffOn 𝕜 m (deriv f₂) s₂ := diff --git a/Mathlib/Analysis/Calculus/ContDiff/Bounds.lean b/Mathlib/Analysis/Calculus/ContDiff/Bounds.lean index 3d7d145291bee..fe52bff69b40d 100644 --- a/Mathlib/Analysis/Calculus/ContDiff/Bounds.lean +++ b/Mathlib/Analysis/Calculus/ContDiff/Bounds.lean @@ -53,7 +53,7 @@ theorem ContinuousLinearMap.norm_iteratedFDerivWithin_le_of_bilinear_aux {Du Eu · simp only [norm_iteratedFDerivWithin_zero, zero_add, Finset.range_one, Finset.sum_singleton, Nat.choose_self, Nat.cast_one, one_mul, Nat.sub_zero, ← mul_assoc] apply B.le_opNorm₂ - · have In : (n : ℕ∞) + 1 ≤ n.succ := by simp only [Nat.cast_succ, le_refl] + · have In : (n : WithTop ℕ∞) + 1 ≤ n.succ := by simp only [Nat.cast_succ, le_refl] -- Porting note: the next line is a hack allowing Lean to find the operator norm instance. let norm := @ContinuousLinearMap.hasOpNorm _ _ Eu ((Du →L[𝕜] Fu) →L[𝕜] Du →L[𝕜] Gu) _ _ _ _ _ _ (RingHom.id 𝕜) @@ -101,7 +101,7 @@ theorem ContinuousLinearMap.norm_iteratedFDerivWithin_le_of_bilinear_aux {Du Eu iteratedFDerivWithin 𝕜 n (fun y => B.precompR Du (f y) (fderivWithin 𝕜 g s y) + B.precompL Du (fderivWithin 𝕜 f s y) (g y)) s x := by apply iteratedFDerivWithin_congr (fun y hy => ?_) hx - have L : (1 : ℕ∞) ≤ n.succ := by + have L : (1 : WithTop ℕ∞) ≤ n.succ := by simpa only [ENat.coe_one, Nat.one_le_cast] using Nat.succ_pos n exact B.fderivWithin_of_bilinear (hf.differentiableOn L y hy) (hg.differentiableOn L y hy) (hs y hy) @@ -123,8 +123,8 @@ theorem ContinuousLinearMap.norm_iteratedFDerivWithin_le_of_bilinear_aux {Du Eu iterated derivatives of `f` and `g` when `B` is bilinear: `‖D^n (x ↦ B (f x) (g x))‖ ≤ ‖B‖ ∑_{k ≤ n} n.choose k ‖D^k f‖ ‖D^{n-k} g‖` -/ theorem ContinuousLinearMap.norm_iteratedFDerivWithin_le_of_bilinear (B : E →L[𝕜] F →L[𝕜] G) - {f : D → E} {g : D → F} {N : ℕ∞} {s : Set D} {x : D} (hf : ContDiffOn 𝕜 N f s) - (hg : ContDiffOn 𝕜 N g s) (hs : UniqueDiffOn 𝕜 s) (hx : x ∈ s) {n : ℕ} (hn : (n : ℕ∞) ≤ N) : + {f : D → E} {g : D → F} {N : WithTop ℕ∞} {s : Set D} {x : D} (hf : ContDiffOn 𝕜 N f s) + (hg : ContDiffOn 𝕜 N g s) (hs : UniqueDiffOn 𝕜 s) (hx : x ∈ s) {n : ℕ} (hn : n ≤ N) : ‖iteratedFDerivWithin 𝕜 n (fun y => B (f y) (g y)) s x‖ ≤ ‖B‖ * ∑ i ∈ Finset.range (n + 1), (n.choose i : ℝ) * ‖iteratedFDerivWithin 𝕜 i f s x‖ * ‖iteratedFDerivWithin 𝕜 (n - i) g s x‖ := by @@ -205,8 +205,8 @@ theorem ContinuousLinearMap.norm_iteratedFDerivWithin_le_of_bilinear (B : E →L iterated derivatives of `f` and `g` when `B` is bilinear: `‖D^n (x ↦ B (f x) (g x))‖ ≤ ‖B‖ ∑_{k ≤ n} n.choose k ‖D^k f‖ ‖D^{n-k} g‖` -/ theorem ContinuousLinearMap.norm_iteratedFDeriv_le_of_bilinear (B : E →L[𝕜] F →L[𝕜] G) {f : D → E} - {g : D → F} {N : ℕ∞} (hf : ContDiff 𝕜 N f) (hg : ContDiff 𝕜 N g) (x : D) {n : ℕ} - (hn : (n : ℕ∞) ≤ N) : + {g : D → F} {N : WithTop ℕ∞} (hf : ContDiff 𝕜 N f) (hg : ContDiff 𝕜 N g) (x : D) {n : ℕ} + (hn : n ≤ N) : ‖iteratedFDeriv 𝕜 n (fun y => B (f y) (g y)) x‖ ≤ ‖B‖ * ∑ i ∈ Finset.range (n + 1), (n.choose i : ℝ) * ‖iteratedFDeriv 𝕜 i f x‖ * ‖iteratedFDeriv 𝕜 (n - i) g x‖ := by simp_rw [← iteratedFDerivWithin_univ] @@ -217,9 +217,9 @@ theorem ContinuousLinearMap.norm_iteratedFDeriv_le_of_bilinear (B : E →L[𝕜] iterated derivatives of `f` and `g` when `B` is bilinear of norm at most `1`: `‖D^n (x ↦ B (f x) (g x))‖ ≤ ∑_{k ≤ n} n.choose k ‖D^k f‖ ‖D^{n-k} g‖` -/ theorem ContinuousLinearMap.norm_iteratedFDerivWithin_le_of_bilinear_of_le_one - (B : E →L[𝕜] F →L[𝕜] G) {f : D → E} {g : D → F} {N : ℕ∞} {s : Set D} {x : D} + (B : E →L[𝕜] F →L[𝕜] G) {f : D → E} {g : D → F} {N : WithTop ℕ∞} {s : Set D} {x : D} (hf : ContDiffOn 𝕜 N f s) (hg : ContDiffOn 𝕜 N g s) (hs : UniqueDiffOn 𝕜 s) (hx : x ∈ s) {n : ℕ} - (hn : (n : ℕ∞) ≤ N) (hB : ‖B‖ ≤ 1) : ‖iteratedFDerivWithin 𝕜 n (fun y => B (f y) (g y)) s x‖ ≤ + (hn : n ≤ N) (hB : ‖B‖ ≤ 1) : ‖iteratedFDerivWithin 𝕜 n (fun y => B (f y) (g y)) s x‖ ≤ ∑ i ∈ Finset.range (n + 1), (n.choose i : ℝ) * ‖iteratedFDerivWithin 𝕜 i f s x‖ * ‖iteratedFDerivWithin 𝕜 (n - i) g s x‖ := by apply (B.norm_iteratedFDerivWithin_le_of_bilinear hf hg hs hx hn).trans @@ -229,8 +229,9 @@ theorem ContinuousLinearMap.norm_iteratedFDerivWithin_le_of_bilinear_of_le_one iterated derivatives of `f` and `g` when `B` is bilinear of norm at most `1`: `‖D^n (x ↦ B (f x) (g x))‖ ≤ ∑_{k ≤ n} n.choose k ‖D^k f‖ ‖D^{n-k} g‖` -/ theorem ContinuousLinearMap.norm_iteratedFDeriv_le_of_bilinear_of_le_one (B : E →L[𝕜] F →L[𝕜] G) - {f : D → E} {g : D → F} {N : ℕ∞} (hf : ContDiff 𝕜 N f) (hg : ContDiff 𝕜 N g) (x : D) {n : ℕ} - (hn : (n : ℕ∞) ≤ N) (hB : ‖B‖ ≤ 1) : ‖iteratedFDeriv 𝕜 n (fun y => B (f y) (g y)) x‖ ≤ + {f : D → E} {g : D → F} {N : WithTop ℕ∞} (hf : ContDiff 𝕜 N f) (hg : ContDiff 𝕜 N g) + (x : D) {n : ℕ} (hn : n ≤ N) (hB : ‖B‖ ≤ 1) : + ‖iteratedFDeriv 𝕜 n (fun y => B (f y) (g y)) x‖ ≤ ∑ i ∈ Finset.range (n + 1), (n.choose i : ℝ) * ‖iteratedFDeriv 𝕜 i f x‖ * ‖iteratedFDeriv 𝕜 (n - i) g x‖ := by simp_rw [← iteratedFDerivWithin_univ] @@ -242,17 +243,17 @@ section variable {𝕜' : Type*} [NormedField 𝕜'] [NormedAlgebra 𝕜 𝕜'] [NormedSpace 𝕜' F] [IsScalarTower 𝕜 𝕜' F] -theorem norm_iteratedFDerivWithin_smul_le {f : E → 𝕜'} {g : E → F} {N : ℕ∞} +theorem norm_iteratedFDerivWithin_smul_le {f : E → 𝕜'} {g : E → F} {N : WithTop ℕ∞} (hf : ContDiffOn 𝕜 N f s) (hg : ContDiffOn 𝕜 N g s) (hs : UniqueDiffOn 𝕜 s) {x : E} (hx : x ∈ s) - {n : ℕ} (hn : (n : ℕ∞) ≤ N) : ‖iteratedFDerivWithin 𝕜 n (fun y => f y • g y) s x‖ ≤ + {n : ℕ} (hn : n ≤ N) : ‖iteratedFDerivWithin 𝕜 n (fun y => f y • g y) s x‖ ≤ ∑ i ∈ Finset.range (n + 1), (n.choose i : ℝ) * ‖iteratedFDerivWithin 𝕜 i f s x‖ * ‖iteratedFDerivWithin 𝕜 (n - i) g s x‖ := (ContinuousLinearMap.lsmul 𝕜 𝕜' : 𝕜' →L[𝕜] F →L[𝕜] F).norm_iteratedFDerivWithin_le_of_bilinear_of_le_one hf hg hs hx hn ContinuousLinearMap.opNorm_lsmul_le -theorem norm_iteratedFDeriv_smul_le {f : E → 𝕜'} {g : E → F} {N : ℕ∞} (hf : ContDiff 𝕜 N f) - (hg : ContDiff 𝕜 N g) (x : E) {n : ℕ} (hn : (n : ℕ∞) ≤ N) : +theorem norm_iteratedFDeriv_smul_le {f : E → 𝕜'} {g : E → F} {N : WithTop ℕ∞} (hf : ContDiff 𝕜 N f) + (hg : ContDiff 𝕜 N g) (x : E) {n : ℕ} (hn : n ≤ N) : ‖iteratedFDeriv 𝕜 n (fun y => f y • g y) x‖ ≤ ∑ i ∈ Finset.range (n + 1), (n.choose i : ℝ) * ‖iteratedFDeriv 𝕜 i f x‖ * ‖iteratedFDeriv 𝕜 (n - i) g x‖ := (ContinuousLinearMap.lsmul 𝕜 𝕜' : 𝕜' →L[𝕜] F →L[𝕜] F).norm_iteratedFDeriv_le_of_bilinear_of_le_one @@ -265,17 +266,18 @@ section variable {ι : Type*} {A : Type*} [NormedRing A] [NormedAlgebra 𝕜 A] {A' : Type*} [NormedCommRing A'] [NormedAlgebra 𝕜 A'] -theorem norm_iteratedFDerivWithin_mul_le {f : E → A} {g : E → A} {N : ℕ∞} (hf : ContDiffOn 𝕜 N f s) - (hg : ContDiffOn 𝕜 N g s) (hs : UniqueDiffOn 𝕜 s) {x : E} (hx : x ∈ s) {n : ℕ} - (hn : (n : ℕ∞) ≤ N) : ‖iteratedFDerivWithin 𝕜 n (fun y => f y * g y) s x‖ ≤ +theorem norm_iteratedFDerivWithin_mul_le {f : E → A} {g : E → A} {N : WithTop ℕ∞} + (hf : ContDiffOn 𝕜 N f s) (hg : ContDiffOn 𝕜 N g s) (hs : UniqueDiffOn 𝕜 s) + {x : E} (hx : x ∈ s) {n : ℕ} (hn : n ≤ N) : + ‖iteratedFDerivWithin 𝕜 n (fun y => f y * g y) s x‖ ≤ ∑ i ∈ Finset.range (n + 1), (n.choose i : ℝ) * ‖iteratedFDerivWithin 𝕜 i f s x‖ * ‖iteratedFDerivWithin 𝕜 (n - i) g s x‖ := (ContinuousLinearMap.mul 𝕜 A : A →L[𝕜] A →L[𝕜] A).norm_iteratedFDerivWithin_le_of_bilinear_of_le_one hf hg hs hx hn (ContinuousLinearMap.opNorm_mul_le _ _) -theorem norm_iteratedFDeriv_mul_le {f : E → A} {g : E → A} {N : ℕ∞} (hf : ContDiff 𝕜 N f) - (hg : ContDiff 𝕜 N g) (x : E) {n : ℕ} (hn : (n : ℕ∞) ≤ N) : +theorem norm_iteratedFDeriv_mul_le {f : E → A} {g : E → A} {N : WithTop ℕ∞} (hf : ContDiff 𝕜 N f) + (hg : ContDiff 𝕜 N g) (x : E) {n : ℕ} (hn : n ≤ N) : ‖iteratedFDeriv 𝕜 n (fun y => f y * g y) x‖ ≤ ∑ i ∈ Finset.range (n + 1), (n.choose i : ℝ) * ‖iteratedFDeriv 𝕜 i f x‖ * ‖iteratedFDeriv 𝕜 (n - i) g x‖ := by simp_rw [← iteratedFDerivWithin_univ] @@ -285,8 +287,8 @@ theorem norm_iteratedFDeriv_mul_le {f : E → A} {g : E → A} {N : ℕ∞} (hf -- TODO: Add `norm_iteratedFDeriv[Within]_list_prod_le` for non-commutative `NormedRing A`. theorem norm_iteratedFDerivWithin_prod_le [DecidableEq ι] [NormOneClass A'] {u : Finset ι} - {f : ι → E → A'} {N : ℕ∞} (hf : ∀ i ∈ u, ContDiffOn 𝕜 N (f i) s) (hs : UniqueDiffOn 𝕜 s) {x : E} - (hx : x ∈ s) {n : ℕ} (hn : (n : ℕ∞) ≤ N) : + {f : ι → E → A'} {N : WithTop ℕ∞} (hf : ∀ i ∈ u, ContDiffOn 𝕜 N (f i) s) + (hs : UniqueDiffOn 𝕜 s) {x : E} (hx : x ∈ s) {n : ℕ} (hn : n ≤ N) : ‖iteratedFDerivWithin 𝕜 n (∏ j ∈ u, f j ·) s x‖ ≤ ∑ p ∈ u.sym n, (p : Multiset ι).multinomial * ∏ j ∈ u, ‖iteratedFDerivWithin 𝕜 (Multiset.count j p) (f j) s x‖ := by @@ -309,7 +311,7 @@ theorem norm_iteratedFDerivWithin_prod_le [DecidableEq ι] [NormOneClass A'] {u simp only [comp_apply, Finset.symInsertEquiv_symm_apply_coe] refine Finset.sum_le_sum ?_ intro m _ - specialize IH hf.2 (n := n - m) (le_trans (WithTop.coe_le_coe.mpr (n.sub_le m)) hn) + specialize IH hf.2 (n := n - m) (le_trans (by exact_mod_cast n.sub_le m) hn) refine le_trans (mul_le_mul_of_nonneg_left IH (by simp [mul_nonneg])) ?_ rw [Finset.mul_sum, ← Finset.sum_coe_sort] refine Finset.sum_le_sum ?_ @@ -329,8 +331,8 @@ theorem norm_iteratedFDerivWithin_prod_le [DecidableEq ι] [NormOneClass A'] {u rw [Sym.count_coe_fill_of_ne hji] theorem norm_iteratedFDeriv_prod_le [DecidableEq ι] [NormOneClass A'] {u : Finset ι} - {f : ι → E → A'} {N : ℕ∞} (hf : ∀ i ∈ u, ContDiff 𝕜 N (f i)) {x : E} {n : ℕ} - (hn : (n : ℕ∞) ≤ N) : + {f : ι → E → A'} {N : WithTop ℕ∞} (hf : ∀ i ∈ u, ContDiff 𝕜 N (f i)) {x : E} {n : ℕ} + (hn : n ≤ N) : ‖iteratedFDeriv 𝕜 n (∏ j ∈ u, f j ·) x‖ ≤ ∑ p ∈ u.sym n, (p : Multiset ι).multinomial * ∏ j ∈ u, ‖iteratedFDeriv 𝕜 ((p : Multiset ι).count j) (f j) x‖ := by @@ -362,7 +364,7 @@ theorem norm_iteratedFDerivWithin_comp_le_aux {Fu Gu : Type u} [NormedAddCommGro induction' n using Nat.case_strong_induction_on with n IH generalizing Gu · simpa [norm_iteratedFDerivWithin_zero, Nat.factorial_zero, algebraMap.coe_one, one_mul, pow_zero, mul_one, comp_apply] using hC 0 le_rfl - have M : (n : ℕ∞) < n.succ := Nat.cast_lt.2 n.lt_succ_self + have M : (n : WithTop ℕ∞) < n.succ := Nat.cast_lt.2 n.lt_succ_self have Cnonneg : 0 ≤ C := (norm_nonneg _).trans (hC 0 bot_le) have Dnonneg : 0 ≤ D := by have : 1 ≤ n + 1 := by simp only [le_add_iff_nonneg_left, zero_le'] @@ -404,7 +406,8 @@ theorem norm_iteratedFDerivWithin_comp_le_aux {Fu Gu : Type u} [NormedAddCommGro LinearIsometryEquiv.norm_map] _ = ‖iteratedFDerivWithin 𝕜 n (fun y : E => ContinuousLinearMap.compL 𝕜 E Fu Gu (fderivWithin 𝕜 g t (f y)) (fderivWithin 𝕜 f s y)) s x‖ := by - have L : (1 : ℕ∞) ≤ n.succ := by simpa only [ENat.coe_one, Nat.one_le_cast] using n.succ_pos + have L : (1 : WithTop ℕ∞) ≤ n.succ := by + simpa only [ENat.coe_one, Nat.one_le_cast] using n.succ_pos congr 1 refine iteratedFDerivWithin_congr (fun y hy => ?_) hx _ apply fderivWithin_comp _ _ _ hst (hs y hy) @@ -459,7 +462,7 @@ theorem norm_iteratedFDerivWithin_comp_le_aux {Fu Gu : Type u} [NormedAddCommGro within a set of `f` at `x` is bounded by `D^i` for all `1 ≤ i ≤ n`, then the `n`-th derivative of `g ∘ f` is bounded by `n! * C * D^n`. -/ theorem norm_iteratedFDerivWithin_comp_le {g : F → G} {f : E → F} {n : ℕ} {s : Set E} {t : Set F} - {x : E} {N : ℕ∞} (hg : ContDiffOn 𝕜 N g t) (hf : ContDiffOn 𝕜 N f s) (hn : (n : ℕ∞) ≤ N) + {x : E} {N : WithTop ℕ∞} (hg : ContDiffOn 𝕜 N g t) (hf : ContDiffOn 𝕜 N f s) (hn : n ≤ N) (ht : UniqueDiffOn 𝕜 t) (hs : UniqueDiffOn 𝕜 s) (hst : MapsTo f s t) (hx : x ∈ s) {C : ℝ} {D : ℝ} (hC : ∀ i, i ≤ n → ‖iteratedFDerivWithin 𝕜 i g t (f x)‖ ≤ C) (hD : ∀ i, 1 ≤ i → i ≤ n → ‖iteratedFDerivWithin 𝕜 i f s x‖ ≤ D ^ i) : @@ -509,8 +512,8 @@ theorem norm_iteratedFDerivWithin_comp_le {g : F → G} {f : E → F} {n : ℕ} /-- If the derivatives of `g` at `f x` are bounded by `C`, and the `i`-th derivative of `f` at `x` is bounded by `D^i` for all `1 ≤ i ≤ n`, then the `n`-th derivative of `g ∘ f` is bounded by `n! * C * D^n`. -/ -theorem norm_iteratedFDeriv_comp_le {g : F → G} {f : E → F} {n : ℕ} {N : ℕ∞} (hg : ContDiff 𝕜 N g) - (hf : ContDiff 𝕜 N f) (hn : (n : ℕ∞) ≤ N) (x : E) {C : ℝ} {D : ℝ} +theorem norm_iteratedFDeriv_comp_le {g : F → G} {f : E → F} {n : ℕ} {N : WithTop ℕ∞} + (hg : ContDiff 𝕜 N g) (hf : ContDiff 𝕜 N f) (hn : n ≤ N) (x : E) {C : ℝ} {D : ℝ} (hC : ∀ i, i ≤ n → ‖iteratedFDeriv 𝕜 i g (f x)‖ ≤ C) (hD : ∀ i, 1 ≤ i → i ≤ n → ‖iteratedFDeriv 𝕜 i f x‖ ≤ D ^ i) : ‖iteratedFDeriv 𝕜 n (g ∘ f) x‖ ≤ n ! * C * D ^ n := by @@ -521,8 +524,9 @@ theorem norm_iteratedFDeriv_comp_le {g : F → G} {f : E → F} {n : ℕ} {N : section Apply theorem norm_iteratedFDerivWithin_clm_apply {f : E → F →L[𝕜] G} {g : E → F} {s : Set E} {x : E} - {N : ℕ∞} {n : ℕ} (hf : ContDiffOn 𝕜 N f s) (hg : ContDiffOn 𝕜 N g s) (hs : UniqueDiffOn 𝕜 s) - (hx : x ∈ s) (hn : ↑n ≤ N) : ‖iteratedFDerivWithin 𝕜 n (fun y => (f y) (g y)) s x‖ ≤ + {N : WithTop ℕ∞} {n : ℕ} (hf : ContDiffOn 𝕜 N f s) (hg : ContDiffOn 𝕜 N g s) + (hs : UniqueDiffOn 𝕜 s) (hx : x ∈ s) (hn : n ≤ N) : + ‖iteratedFDerivWithin 𝕜 n (fun y => (f y) (g y)) s x‖ ≤ ∑ i ∈ Finset.range (n + 1), ↑(n.choose i) * ‖iteratedFDerivWithin 𝕜 i f s x‖ * ‖iteratedFDerivWithin 𝕜 (n - i) g s x‖ := by let B : (F →L[𝕜] G) →L[𝕜] F →L[𝕜] G := ContinuousLinearMap.flip (ContinuousLinearMap.apply 𝕜 G) @@ -533,8 +537,8 @@ theorem norm_iteratedFDerivWithin_clm_apply {f : E → F →L[𝕜] G} {g : E rfl exact B.norm_iteratedFDerivWithin_le_of_bilinear_of_le_one hf hg hs hx hn hB -theorem norm_iteratedFDeriv_clm_apply {f : E → F →L[𝕜] G} {g : E → F} {N : ℕ∞} {n : ℕ} - (hf : ContDiff 𝕜 N f) (hg : ContDiff 𝕜 N g) (x : E) (hn : ↑n ≤ N) : +theorem norm_iteratedFDeriv_clm_apply {f : E → F →L[𝕜] G} {g : E → F} {N : WithTop ℕ∞} {n : ℕ} + (hf : ContDiff 𝕜 N f) (hg : ContDiff 𝕜 N g) (x : E) (hn : n ≤ N) : ‖iteratedFDeriv 𝕜 n (fun y : E => (f y) (g y)) x‖ ≤ ∑ i ∈ Finset.range (n + 1), ↑(n.choose i) * ‖iteratedFDeriv 𝕜 i f x‖ * ‖iteratedFDeriv 𝕜 (n - i) g x‖ := by simp only [← iteratedFDerivWithin_univ] @@ -542,7 +546,8 @@ theorem norm_iteratedFDeriv_clm_apply {f : E → F →L[𝕜] G} {g : E → F} { (Set.mem_univ x) hn theorem norm_iteratedFDerivWithin_clm_apply_const {f : E → F →L[𝕜] G} {c : F} {s : Set E} {x : E} - {N : ℕ∞} {n : ℕ} (hf : ContDiffOn 𝕜 N f s) (hs : UniqueDiffOn 𝕜 s) (hx : x ∈ s) (hn : ↑n ≤ N) : + {N : WithTop ℕ∞} {n : ℕ} (hf : ContDiffOn 𝕜 N f s) (hs : UniqueDiffOn 𝕜 s) + (hx : x ∈ s) (hn : n ≤ N) : ‖iteratedFDerivWithin 𝕜 n (fun y : E => (f y) c) s x‖ ≤ ‖c‖ * ‖iteratedFDerivWithin 𝕜 n f s x‖ := by let g : (F →L[𝕜] G) →L[𝕜] G := ContinuousLinearMap.apply 𝕜 G c @@ -553,8 +558,8 @@ theorem norm_iteratedFDerivWithin_clm_apply_const {f : E → F →L[𝕜] G} {c rw [ContinuousLinearMap.apply_apply, mul_comm] exact f.le_opNorm c -theorem norm_iteratedFDeriv_clm_apply_const {f : E → F →L[𝕜] G} {c : F} {x : E} {N : ℕ∞} {n : ℕ} - (hf : ContDiff 𝕜 N f) (hn : ↑n ≤ N) : +theorem norm_iteratedFDeriv_clm_apply_const {f : E → F →L[𝕜] G} {c : F} {x : E} + {N : WithTop ℕ∞} {n : ℕ} (hf : ContDiff 𝕜 N f) (hn : n ≤ N) : ‖iteratedFDeriv 𝕜 n (fun y : E => (f y) c) x‖ ≤ ‖c‖ * ‖iteratedFDeriv 𝕜 n f x‖ := by simp only [← iteratedFDerivWithin_univ] exact norm_iteratedFDerivWithin_clm_apply_const hf.contDiffOn uniqueDiffOn_univ diff --git a/Mathlib/Analysis/Calculus/ContDiff/Defs.lean b/Mathlib/Analysis/Calculus/ContDiff/Defs.lean index 968b9b7d7d1c3..180ea22be1a5e 100644 --- a/Mathlib/Analysis/Calculus/ContDiff/Defs.lean +++ b/Mathlib/Analysis/Calculus/ContDiff/Defs.lean @@ -93,7 +93,13 @@ noncomputable section open scoped Classical open NNReal Topology Filter -local notation "∞" => (⊤ : ℕ∞) +/-- Smoothness exponent for analytic functions. Not implemented yet, `ω` smoothness is equivalent +to `∞` smoothness in current mathlib. -/ +scoped [ContDiff] notation3 "ω" => (⊤ : WithTop ℕ∞) +/-- Smoothness exponent for infinitely differentiable functions. -/ +scoped [ContDiff] notation3 "∞" => ((⊤ : ℕ∞) : WithTop ℕ∞) + +open ContDiff /- Porting note: These lines are not required in Mathlib4. @@ -108,7 +114,7 @@ universe u uE uF uG uX variable {𝕜 : Type u} [NontriviallyNormedField 𝕜] {E : Type uE} [NormedAddCommGroup E] [NormedSpace 𝕜 E] {F : Type uF} [NormedAddCommGroup F] [NormedSpace 𝕜 F] {G : Type uG} [NormedAddCommGroup G] [NormedSpace 𝕜 G] {X : Type uX} [NormedAddCommGroup X] [NormedSpace 𝕜 X] - {s s₁ t u : Set E} {f f₁ : E → F} {g : F → G} {x x₀ : E} {c : F} {m n : ℕ∞} + {s s₁ t u : Set E} {f f₁ : E → F} {g : F → G} {x x₀ : E} {c : F} {m n : WithTop ℕ∞} {p : E → FormalMultilinearSeries 𝕜 E F} /-! ### Smooth functions within a set around a point -/ @@ -122,8 +128,11 @@ depend on the finite order we consider). For instance, a real function which is `C^m` on `(-1/m, 1/m)` for each natural `m`, but not better, is `C^∞` at `0` within `univ`. + +We take the exponent `n` in `WithTop ℕ∞` to allow for an extension to analytic functions in the +future, but currently the notion is the same for `n = ∞` and `n = ω`. -/ -def ContDiffWithinAt (n : ℕ∞) (f : E → F) (s : Set E) (x : E) : Prop := +def ContDiffWithinAt (n : WithTop ℕ∞) (f : E → F) (s : Set E) (x : E) : Prop := ∀ m : ℕ, m ≤ n → ∃ u ∈ 𝓝[insert x s] x, ∃ p : E → FormalMultilinearSeries 𝕜 E F, HasFTaylorSeriesUpToOn m f p u @@ -137,9 +146,9 @@ theorem contDiffWithinAt_nat {n : ℕ} : theorem ContDiffWithinAt.of_le (h : ContDiffWithinAt 𝕜 n f s x) (hmn : m ≤ n) : ContDiffWithinAt 𝕜 m f s x := fun k hk => h k (le_trans hk hmn) -theorem contDiffWithinAt_iff_forall_nat_le : +theorem contDiffWithinAt_iff_forall_nat_le {n : ℕ∞} : ContDiffWithinAt 𝕜 n f s x ↔ ∀ m : ℕ, ↑m ≤ n → ContDiffWithinAt 𝕜 m f s x := - ⟨fun H _m hm => H.of_le hm, fun H m hm => H m hm _ le_rfl⟩ + ⟨fun H _m hm => H.of_le (mod_cast hm), fun H m hm => H m (mod_cast hm) _ le_rfl⟩ theorem contDiffWithinAt_top : ContDiffWithinAt 𝕜 ∞ f s x ↔ ∀ n : ℕ, ContDiffWithinAt 𝕜 n f s x := contDiffWithinAt_iff_forall_nat_le.trans <| by simp only [forall_prop_of_true, le_top] @@ -308,7 +317,7 @@ theorem contDiffWithinAt_succ_iff_hasFDerivWithinAt {n : ℕ} : hasFTaylorSeriesUpToOn_succ_iff_right] at Hp exact Hp.2.2.of_le (mod_cast hm) · rintro ⟨u, hu, f', f'_eq_deriv, Hf'⟩ - rw [show (n : ℕ∞) + 1 = (n + 1 : ℕ) from rfl, contDiffWithinAt_nat] + rw [show (n : WithTop ℕ∞) + 1 = (n + 1 : ℕ) from rfl, contDiffWithinAt_nat] rcases Hf' n le_rfl with ⟨v, hv, p', Hp'⟩ refine ⟨v ∩ u, ?_, fun x => (p' x).unshift (f x), ?_⟩ · apply Filter.inter_mem _ hu @@ -370,7 +379,7 @@ admits continuous derivatives up to order `n` on a neighborhood of `x` in `s`. For `n = ∞`, we only require that this holds up to any finite order (where the neighborhood may depend on the finite order we consider). -/ -def ContDiffOn (n : ℕ∞) (f : E → F) (s : Set E) : Prop := +def ContDiffOn (n : WithTop ℕ∞) (f : E → F) (s : Set E) : Prop := ∀ x ∈ s, ContDiffWithinAt 𝕜 n f s x variable {𝕜} @@ -427,13 +436,15 @@ theorem ContDiffOn.of_succ {n : ℕ} (h : ContDiffOn 𝕜 (n + 1) f s) : ContDif theorem ContDiffOn.one_of_succ {n : ℕ} (h : ContDiffOn 𝕜 (n + 1) f s) : ContDiffOn 𝕜 1 f s := h.of_le <| WithTop.coe_le_coe.mpr le_add_self -theorem contDiffOn_iff_forall_nat_le : ContDiffOn 𝕜 n f s ↔ ∀ m : ℕ, ↑m ≤ n → ContDiffOn 𝕜 m f s := - ⟨fun H _ hm => H.of_le hm, fun H x hx m hm => H m hm x hx m le_rfl⟩ +theorem contDiffOn_iff_forall_nat_le {n : ℕ∞} : + ContDiffOn 𝕜 n f s ↔ ∀ m : ℕ, ↑m ≤ n → ContDiffOn 𝕜 m f s := + ⟨fun H _ hm => H.of_le (mod_cast hm), fun H x hx m hm => H m (mod_cast hm) x hx m le_rfl⟩ theorem contDiffOn_top : ContDiffOn 𝕜 ∞ f s ↔ ∀ n : ℕ, ContDiffOn 𝕜 n f s := contDiffOn_iff_forall_nat_le.trans <| by simp only [le_top, forall_prop_of_true] -theorem contDiffOn_all_iff_nat : (∀ n, ContDiffOn 𝕜 n f s) ↔ ∀ n : ℕ, ContDiffOn 𝕜 n f s := by +theorem contDiffOn_all_iff_nat : + (∀ (n : ℕ∞), ContDiffOn 𝕜 n f s) ↔ ∀ n : ℕ, ContDiffOn 𝕜 n f s := by refine ⟨fun H n => H n, ?_⟩ rintro H (_ | n) exacts [contDiffOn_top.2 H, H n] @@ -522,8 +533,8 @@ protected theorem ContDiffOn.ftaylorSeriesWithin (h : ContDiffOn 𝕜 n f s) (hs simp only [ftaylorSeriesWithin, ContinuousMultilinearMap.curry0_apply, iteratedFDerivWithin_zero_apply] · intro m hm x hx - have : m < n := mod_cast hm - rcases (h x hx) m.succ (Order.add_one_le_of_lt this) with ⟨u, hu, p, Hp⟩ + have : (m + 1 : ℕ) ≤ n := ENat.add_one_natCast_le_withTop_of_lt hm + rcases (h x hx).of_le this _ le_rfl with ⟨u, hu, p, Hp⟩ rw [insert_eq_of_mem hx] at hu rcases mem_nhdsWithin.1 hu with ⟨o, o_open, xo, ho⟩ rw [inter_comm] at ho @@ -557,7 +568,7 @@ protected theorem ContDiffOn.ftaylorSeriesWithin (h : ContDiffOn 𝕜 n f s) (hs exact (Hp.mono ho).eq_iteratedFDerivWithin_of_uniqueDiffOn le_rfl (hs.inter o_open) ⟨hy, yo⟩ exact ((Hp.mono ho).cont m le_rfl).congr fun y hy => (A y hy).symm -theorem contDiffOn_of_continuousOn_differentiableOn +theorem contDiffOn_of_continuousOn_differentiableOn {n : ℕ∞} (Hcont : ∀ m : ℕ, m ≤ n → ContinuousOn (fun x => iteratedFDerivWithin 𝕜 m f s x) s) (Hdiff : ∀ m : ℕ, m < n → DifferentiableOn 𝕜 (fun x => iteratedFDerivWithin 𝕜 m f s x) s) : @@ -570,11 +581,11 @@ theorem contDiffOn_of_continuousOn_differentiableOn simp only [ftaylorSeriesWithin, ContinuousMultilinearMap.curry0_apply, iteratedFDerivWithin_zero_apply] · intro k hk y hy - convert (Hdiff k (lt_of_lt_of_le (mod_cast hk) hm) y hy).hasFDerivWithinAt + convert (Hdiff k (lt_of_lt_of_le (mod_cast hk) (mod_cast hm)) y hy).hasFDerivWithinAt · intro k hk - exact Hcont k (le_trans (mod_cast hk) hm) + exact Hcont k (le_trans (mod_cast hk) (mod_cast hm)) -theorem contDiffOn_of_differentiableOn +theorem contDiffOn_of_differentiableOn {n : ℕ∞} (h : ∀ m : ℕ, m ≤ n → DifferentiableOn 𝕜 (iteratedFDerivWithin 𝕜 m f s) s) : ContDiffOn 𝕜 n f s := contDiffOn_of_continuousOn_differentiableOn (fun m hm => (h m hm).continuousOn) fun m hm => @@ -592,7 +603,7 @@ theorem ContDiffOn.differentiableOn_iteratedFDerivWithin {m : ℕ} (h : ContDiff theorem ContDiffWithinAt.differentiableWithinAt_iteratedFDerivWithin {m : ℕ} (h : ContDiffWithinAt 𝕜 n f s x) (hmn : m < n) (hs : UniqueDiffOn 𝕜 (insert x s)) : DifferentiableWithinAt 𝕜 (iteratedFDerivWithin 𝕜 m f s) s x := by - rcases h.contDiffOn' (Order.add_one_le_of_lt hmn) with ⟨u, uo, xu, hu⟩ + rcases h.contDiffOn' (ENat.add_one_natCast_le_withTop_of_lt hmn) with ⟨u, uo, xu, hu⟩ set t := insert x s ∩ u have A : t =ᶠ[𝓝[≠] x] s := by simp only [set_eventuallyEq_iff_inf_principal, ← nhdsWithin_inter'] @@ -607,12 +618,12 @@ theorem ContDiffWithinAt.differentiableWithinAt_iteratedFDerivWithin {m : ℕ} rw [differentiableWithinAt_congr_set' _ A] at C exact C.congr_of_eventuallyEq (B.filter_mono inf_le_left) B.self_of_nhds -theorem contDiffOn_iff_continuousOn_differentiableOn (hs : UniqueDiffOn 𝕜 s) : +theorem contDiffOn_iff_continuousOn_differentiableOn {n : ℕ∞} (hs : UniqueDiffOn 𝕜 s) : ContDiffOn 𝕜 n f s ↔ (∀ m : ℕ, m ≤ n → ContinuousOn (fun x => iteratedFDerivWithin 𝕜 m f s x) s) ∧ ∀ m : ℕ, m < n → DifferentiableOn 𝕜 (fun x => iteratedFDerivWithin 𝕜 m f s x) s := - ⟨fun h => ⟨fun _m hm => h.continuousOn_iteratedFDerivWithin hm hs, fun _m hm => - h.differentiableOn_iteratedFDerivWithin hm hs⟩, + ⟨fun h => ⟨fun _m hm => h.continuousOn_iteratedFDerivWithin (mod_cast hm) hs, fun _m hm => + h.differentiableOn_iteratedFDerivWithin (mod_cast hm) hs⟩, fun h => contDiffOn_of_continuousOn_differentiableOn h.1 h.2⟩ theorem contDiffOn_succ_of_fderivWithin {n : ℕ} (hf : DifferentiableOn 𝕜 f s) @@ -628,7 +639,7 @@ theorem contDiffOn_succ_iff_fderivWithin {n : ℕ} (hs : UniqueDiffOn 𝕜 s) : ContDiffOn 𝕜 (n + 1) f s ↔ DifferentiableOn 𝕜 f s ∧ ContDiffOn 𝕜 n (fun y => fderivWithin 𝕜 f s y) s := by refine ⟨fun H => ?_, fun h => contDiffOn_succ_of_fderivWithin h.1 h.2⟩ - refine ⟨H.differentiableOn (WithTop.coe_le_coe.2 (Nat.le_add_left 1 n)), fun x hx => ?_⟩ + refine ⟨H.differentiableOn le_add_self, fun x hx => ?_⟩ rcases contDiffWithinAt_succ_iff_hasFDerivWithinAt.1 (H x hx) with ⟨u, hu, f', hff', hf'⟩ rcases mem_nhdsWithin.1 hu with ⟨o, o_open, xo, ho⟩ rw [inter_comm, insert_eq_of_mem hx] at ho @@ -666,14 +677,14 @@ theorem contDiffOn_top_iff_fderivWithin (hs : UniqueDiffOn 𝕜 s) : DifferentiableOn 𝕜 f s ∧ ContDiffOn 𝕜 ∞ (fun y => fderivWithin 𝕜 f s y) s := by constructor · intro h - refine ⟨h.differentiableOn le_top, ?_⟩ + refine ⟨h.differentiableOn (mod_cast le_top), ?_⟩ refine contDiffOn_top.2 fun n => ((contDiffOn_succ_iff_fderivWithin hs).1 ?_).2 - exact h.of_le le_top + exact h.of_le (mod_cast le_top) · intro h refine contDiffOn_top.2 fun n => ?_ - have A : (n : ℕ∞) ≤ ∞ := le_top + have A : (n : ℕ∞) ≤ ∞ := mod_cast le_top apply ((contDiffOn_succ_iff_fderivWithin hs).2 ⟨h.1, h.2.of_le A⟩).of_le - exact WithTop.coe_le_coe.2 (Nat.le_succ n) + exact_mod_cast (Nat.le_succ n) /-- A function is `C^∞` on an open domain if and only if it is differentiable there, and its derivative (expressed with `fderiv`) is `C^∞`. -/ @@ -684,13 +695,17 @@ theorem contDiffOn_top_iff_fderiv_of_isOpen (hs : IsOpen s) : protected theorem ContDiffOn.fderivWithin (hf : ContDiffOn 𝕜 n f s) (hs : UniqueDiffOn 𝕜 s) (hmn : m + 1 ≤ n) : ContDiffOn 𝕜 m (fun y => fderivWithin 𝕜 f s y) s := by - cases' m with m - · change ∞ + 1 ≤ n at hmn - have : n = ∞ := by simpa using hmn - rw [this] at hf - exact ((contDiffOn_top_iff_fderivWithin hs).1 hf).2 - · change (m.succ : ℕ∞) ≤ n at hmn - exact ((contDiffOn_succ_iff_fderivWithin hs).1 (hf.of_le hmn)).2 + rcases le_or_lt ∞ n with hn | hn + · have : ContDiffOn 𝕜 ∞ (fun y ↦ fderivWithin 𝕜 f s y) s := + ((contDiffOn_top_iff_fderivWithin hs).1 (hf.of_le hn)).2 + intro x hx k hk + exact this x hx k (mod_cast le_top) + · match m with + | ω => simpa using hmn.trans_lt hn + | ∞ => simpa using hmn.trans_lt hn + | (m : ℕ) => + change (m.succ : ℕ∞) ≤ n at hmn + exact ((contDiffOn_succ_iff_fderivWithin hs).1 (hf.of_le hmn)).2 theorem ContDiffOn.fderiv_of_isOpen (hf : ContDiffOn 𝕜 n f s) (hs : IsOpen s) (hmn : m + 1 ≤ n) : ContDiffOn 𝕜 m (fun y => fderiv 𝕜 f y) s := @@ -704,6 +719,13 @@ theorem ContDiffOn.continuousOn_fderiv_of_isOpen (h : ContDiffOn 𝕜 n f s) (hs (hn : 1 ≤ n) : ContinuousOn (fun x => fderiv 𝕜 f x) s := ((contDiffOn_succ_iff_fderiv_of_isOpen hs).1 (h.of_le hn)).2.continuousOn +/-- The following lemma will be removed when the definition of `C^ω` will be corrected. For now, +it is only there as a convenient shortcut. -/ +theorem contDiffOn_infty_iff_contDiffOn_omega : + ContDiffOn 𝕜 ∞ f s ↔ ContDiffOn 𝕜 ω f s := by + have A (m : ℕ) : m ≤ ∞ := mod_cast le_top + simp [ContDiffOn, ContDiffWithinAt, hasFTaylorSeriesUpTo_top_iff, A] + /-! ### Smooth functions at a point -/ variable (𝕜) @@ -711,7 +733,7 @@ variable (𝕜) /-- A function is continuously differentiable up to `n` at a point `x` if, for any integer `k ≤ n`, there is a neighborhood of `x` where `f` admits derivatives up to order `n`, which are continuous. -/ -def ContDiffAt (n : ℕ∞) (f : E → F) (x : E) : Prop := +def ContDiffAt (n : WithTop ℕ∞) (f : E → F) (x : E) : Prop := ContDiffWithinAt 𝕜 n f univ x variable {𝕜} @@ -795,7 +817,7 @@ variable (𝕜) order `n`, which are continuous. Contrary to the case of definitions in domains (where derivatives might not be unique) we do not need to localize the definition in space or time. -/ -def ContDiff (n : ℕ∞) (f : E → F) : Prop := +def ContDiff (n : WithTop ℕ∞) (f : E → F) : Prop := ∃ p : E → FormalMultilinearSeries 𝕜 E F, HasFTaylorSeriesUpTo n f p variable {𝕜} @@ -824,10 +846,16 @@ theorem ContDiff.contDiffAt (h : ContDiff 𝕜 n f) : ContDiffAt 𝕜 n f x := theorem ContDiff.contDiffWithinAt (h : ContDiff 𝕜 n f) : ContDiffWithinAt 𝕜 n f s x := h.contDiffAt.contDiffWithinAt +/-- The following lemma will be removed when the definition of `C^ω` will be corrected. For now, +it is only there as a convenient shortcut. -/ +theorem contDiff_infty_iff_contDiff_omega : + ContDiff 𝕜 ∞ f ↔ ContDiff 𝕜 ω f := by + simp [ContDiff, hasFTaylorSeriesUpTo_top_iff] + theorem contDiff_top : ContDiff 𝕜 ∞ f ↔ ∀ n : ℕ, ContDiff 𝕜 n f := by simp [contDiffOn_univ.symm, contDiffOn_top] -theorem contDiff_all_iff_nat : (∀ n, ContDiff 𝕜 n f) ↔ ∀ n : ℕ, ContDiff 𝕜 n f := by +theorem contDiff_all_iff_nat : (∀ (n : ℕ∞), ContDiff 𝕜 n f) ↔ ∀ n : ℕ, ContDiff 𝕜 n f := by simp only [← contDiffOn_univ, contDiffOn_all_iff_nat] theorem ContDiff.contDiffOn (h : ContDiff 𝕜 n f) : ContDiffOn 𝕜 n f s := @@ -844,8 +872,8 @@ theorem contDiffAt_zero : ContDiffAt 𝕜 0 f x ↔ ∃ u ∈ 𝓝 x, Continuous theorem contDiffAt_one_iff : ContDiffAt 𝕜 1 f x ↔ ∃ f' : E → E →L[𝕜] F, ∃ u ∈ 𝓝 x, ContinuousOn f' u ∧ ∀ x ∈ u, HasFDerivAt f (f' x) x := by - rw [show (1 : ℕ∞) = (0 : ℕ) + 1 from rfl, contDiffAt_succ_iff_hasFDerivAt] - simp_rw [show ((0 : ℕ) : ℕ∞) = 0 from rfl, contDiffAt_zero, + rw [show (1 : WithTop ℕ∞) = (0 : ℕ) + 1 from rfl, contDiffAt_succ_iff_hasFDerivAt] + simp_rw [show ((0 : ℕ) : WithTop ℕ∞) = 0 from rfl, contDiffAt_zero, exists_mem_and_iff antitone_bforall antitone_continuousOn, and_comm] theorem ContDiff.of_le (h : ContDiff 𝕜 n f) (hmn : m ≤ n) : ContDiff 𝕜 m f := @@ -864,7 +892,8 @@ theorem ContDiff.continuous (h : ContDiff 𝕜 n f) : Continuous f := theorem ContDiff.differentiable (h : ContDiff 𝕜 n f) (hn : 1 ≤ n) : Differentiable 𝕜 f := differentiableOn_univ.1 <| (contDiffOn_univ.2 h).differentiableOn hn -theorem contDiff_iff_forall_nat_le : ContDiff 𝕜 n f ↔ ∀ m : ℕ, ↑m ≤ n → ContDiff 𝕜 m f := by +theorem contDiff_iff_forall_nat_le {n : ℕ∞} : + ContDiff 𝕜 n f ↔ ∀ m : ℕ, ↑m ≤ n → ContDiff 𝕜 m f := by simp_rw [← contDiffOn_univ]; exact contDiffOn_iff_forall_nat_le /-- A function is `C^(n+1)` iff it has a `C^n` derivative. -/ @@ -887,7 +916,7 @@ theorem contDiff_iff_ftaylorSeries : exact fun h => ContDiffOn.ftaylorSeriesWithin h uniqueDiffOn_univ · intro h; exact ⟨ftaylorSeries 𝕜 f, h⟩ -theorem contDiff_iff_continuous_differentiable : +theorem contDiff_iff_continuous_differentiable {n : ℕ∞} : ContDiff 𝕜 n f ↔ (∀ m : ℕ, m ≤ n → Continuous fun x => iteratedFDeriv 𝕜 m f x) ∧ ∀ m : ℕ, m < n → Differentiable 𝕜 fun x => iteratedFDeriv 𝕜 m f x := by @@ -897,14 +926,15 @@ theorem contDiff_iff_continuous_differentiable : /-- If `f` is `C^n` then its `m`-times iterated derivative is continuous for `m ≤ n`. -/ theorem ContDiff.continuous_iteratedFDeriv {m : ℕ} (hm : m ≤ n) (hf : ContDiff 𝕜 n f) : Continuous fun x => iteratedFDeriv 𝕜 m f x := - (contDiff_iff_continuous_differentiable.mp hf).1 m hm + (contDiff_iff_continuous_differentiable.mp (hf.of_le hm)).1 m le_rfl /-- If `f` is `C^n` then its `m`-times iterated derivative is differentiable for `m < n`. -/ theorem ContDiff.differentiable_iteratedFDeriv {m : ℕ} (hm : m < n) (hf : ContDiff 𝕜 n f) : Differentiable 𝕜 fun x => iteratedFDeriv 𝕜 m f x := - (contDiff_iff_continuous_differentiable.mp hf).2 m hm + (contDiff_iff_continuous_differentiable.mp + (hf.of_le (ENat.add_one_natCast_le_withTop_of_lt hm))).2 m (mod_cast lt_add_one m) -theorem contDiff_of_differentiable_iteratedFDeriv +theorem contDiff_of_differentiable_iteratedFDeriv {n : ℕ∞} (h : ∀ m : ℕ, m ≤ n → Differentiable 𝕜 (iteratedFDeriv 𝕜 m f)) : ContDiff 𝕜 n f := contDiff_iff_continuous_differentiable.2 ⟨fun m hm => (h m hm).continuous, fun m hm => h m (le_of_lt hm)⟩ diff --git a/Mathlib/Analysis/Calculus/ContDiff/FiniteDimension.lean b/Mathlib/Analysis/Calculus/ContDiff/FiniteDimension.lean index 555d81bb107e4..c399175ddd00d 100644 --- a/Mathlib/Analysis/Calculus/ContDiff/FiniteDimension.lean +++ b/Mathlib/Analysis/Calculus/ContDiff/FiniteDimension.lean @@ -20,6 +20,7 @@ variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {D : Type uD} [NormedAddCommGroup D] [NormedSpace 𝕜 D] {E : Type uE} [NormedAddCommGroup E] [NormedSpace 𝕜 E] {F : Type uF} [NormedAddCommGroup F] [NormedSpace 𝕜 F] + {n : WithTop ℕ∞} {f : D → E} {s : Set D} /-! ### Finite dimensional results -/ @@ -30,7 +31,7 @@ open Function Module variable [CompleteSpace 𝕜] /-- A family of continuous linear maps is `C^n` on `s` if all its applications are. -/ -theorem contDiffOn_clm_apply {n : ℕ∞} {f : D → E →L[𝕜] F} {s : Set D} [FiniteDimensional 𝕜 E] : +theorem contDiffOn_clm_apply {f : D → E →L[𝕜] F} {s : Set D} [FiniteDimensional 𝕜 E] : ContDiffOn 𝕜 n f s ↔ ∀ y, ContDiffOn 𝕜 n (fun x => f x y) s := by refine ⟨fun h y => h.clm_apply contDiffOn_const, fun h => ?_⟩ let d := finrank 𝕜 E @@ -40,7 +41,7 @@ theorem contDiffOn_clm_apply {n : ℕ∞} {f : D → E →L[𝕜] F} {s : Set D} rw [← id_comp f, ← e₂.symm_comp_self] exact e₂.symm.contDiff.comp_contDiffOn (contDiffOn_pi.mpr fun i => h _) -theorem contDiff_clm_apply_iff {n : ℕ∞} {f : D → E →L[𝕜] F} [FiniteDimensional 𝕜 E] : +theorem contDiff_clm_apply_iff {f : D → E →L[𝕜] F} [FiniteDimensional 𝕜 E] : ContDiff 𝕜 n f ↔ ∀ y, ContDiff 𝕜 n fun x => f x y := by simp_rw [← contDiffOn_univ, contDiffOn_clm_apply] @@ -48,7 +49,7 @@ theorem contDiff_clm_apply_iff {n : ℕ∞} {f : D → E →L[𝕜] F} [FiniteDi When you do induction on `n`, this gives a useful characterization of a function being `C^(n+1)`, assuming you have already computed the derivative. The advantage of this version over `contDiff_succ_iff_fderiv` is that both occurrences of `ContDiff` are for functions with the same -domain and codomain (`E` and `F`). This is not the case for `contDiff_succ_iff_fderiv`, which +domain and codomain (`D` and `E`). This is not the case for `contDiff_succ_iff_fderiv`, which often requires an inconvenient need to generalize `F`, which results in universe issues (see the discussion in the section of `ContDiff.comp`). diff --git a/Mathlib/Analysis/Calculus/ContDiff/RCLike.lean b/Mathlib/Analysis/Calculus/ContDiff/RCLike.lean index 5f8fdba324bcb..e87af872c43a2 100644 --- a/Mathlib/Analysis/Calculus/ContDiff/RCLike.lean +++ b/Mathlib/Analysis/Calculus/ContDiff/RCLike.lean @@ -24,8 +24,8 @@ section Real its extension fields such as `ℂ`). -/ -variable {n : ℕ∞} {𝕂 : Type*} [RCLike 𝕂] {E' : Type*} [NormedAddCommGroup E'] [NormedSpace 𝕂 E'] - {F' : Type*} [NormedAddCommGroup F'] [NormedSpace 𝕂 F'] +variable {n : WithTop ℕ∞} {𝕂 : Type*} [RCLike 𝕂] {E' : Type*} [NormedAddCommGroup E'] + [NormedSpace 𝕂 E'] {F' : Type*} [NormedAddCommGroup F'] [NormedSpace 𝕂 F'] /-- If a function has a Taylor series at order at least 1, then at points in the interior of the domain of definition, the term of order 1 of this series is a strict derivative of `f`. -/ @@ -41,7 +41,7 @@ us as `f'`, then `f'` is also a strict derivative. -/ theorem ContDiffAt.hasStrictFDerivAt' {f : E' → F'} {f' : E' →L[𝕂] F'} {x : E'} (hf : ContDiffAt 𝕂 n f x) (hf' : HasFDerivAt f f' x) (hn : 1 ≤ n) : HasStrictFDerivAt f f' x := by - rcases hf 1 hn with ⟨u, H, p, hp⟩ + rcases hf.of_le hn 1 le_rfl with ⟨u, H, p, hp⟩ simp only [nhdsWithin_univ, mem_univ, insert_eq_of_mem] at H have := hp.hasStrictFDerivAt le_rfl H rwa [hf'.unique this.hasFDerivAt] @@ -135,7 +135,7 @@ lemma ContDiff.locallyLipschitz {f : E' → F'} (hf : ContDiff 𝕂 1 f) : Local use K, t /-- A `C^1` function with compact support is Lipschitz. -/ -theorem ContDiff.lipschitzWith_of_hasCompactSupport {f : E' → F'} {n : ℕ∞} +theorem ContDiff.lipschitzWith_of_hasCompactSupport {f : E' → F'} (hf : HasCompactSupport f) (h'f : ContDiff 𝕂 n f) (hn : 1 ≤ n) : ∃ C, LipschitzWith C f := by obtain ⟨C, hC⟩ := (hf.fderiv 𝕂).exists_bound_of_continuous (h'f.continuous_fderiv hn) diff --git a/Mathlib/Analysis/Calculus/FDeriv/Analytic.lean b/Mathlib/Analysis/Calculus/FDeriv/Analytic.lean index 055c8cb25720e..9141ffab19f41 100644 --- a/Mathlib/Analysis/Calculus/FDeriv/Analytic.lean +++ b/Mathlib/Analysis/Calculus/FDeriv/Analytic.lean @@ -63,7 +63,7 @@ differentiability at points in a neighborhood of `s`. Therefore, the theorem tha open Filter Asymptotics Set -open scoped ENNReal Topology +open scoped ENNReal Topology ContDiff universe u v @@ -261,7 +261,7 @@ by the sequence of its derivatives. Note that, if the function were just analyti one would have to use instead the sequence of derivatives inside the set, as in `AnalyticOn.hasFTaylorSeriesUpToOn`. -/ lemma AnalyticOnNhd.hasFTaylorSeriesUpToOn [CompleteSpace F] - (n : ℕ∞) (h : AnalyticOnNhd 𝕜 f s) : + (n : WithTop ℕ∞) (h : AnalyticOnNhd 𝕜 f s) : HasFTaylorSeriesUpToOn n f (ftaylorSeries 𝕜 f) s := by refine ⟨fun x _hx ↦ rfl, fun m _hm x hx ↦ ?_, fun m _hm x hx ↦ ?_⟩ · apply HasFDerivAt.hasFDerivWithinAt @@ -270,25 +270,27 @@ lemma AnalyticOnNhd.hasFTaylorSeriesUpToOn [CompleteSpace F] exact (h.iteratedFDeriv m x hx).differentiableAt /-- An analytic function is infinitely differentiable. -/ -protected theorem AnalyticOnNhd.contDiffOn [CompleteSpace F] (h : AnalyticOnNhd 𝕜 f s) {n : ℕ∞} : - ContDiffOn 𝕜 n f s := +protected theorem AnalyticOnNhd.contDiffOn [CompleteSpace F] (h : AnalyticOnNhd 𝕜 f s) + {n : WithTop ℕ∞} : ContDiffOn 𝕜 n f s := by + suffices ContDiffOn 𝕜 ω f s from this.of_le le_top + rw [← contDiffOn_infty_iff_contDiffOn_omega] let t := { x | AnalyticAt 𝕜 f x } - suffices ContDiffOn 𝕜 n f t from this.mono h + suffices ContDiffOn 𝕜 ∞ f t from this.mono h have H : AnalyticOnNhd 𝕜 f t := fun _x hx ↦ hx have t_open : IsOpen t := isOpen_analyticAt 𝕜 f - contDiffOn_of_continuousOn_differentiableOn + exact contDiffOn_of_continuousOn_differentiableOn (fun m _ ↦ (H.iteratedFDeriv m).continuousOn.congr fun _ hx ↦ iteratedFDerivWithin_of_isOpen _ t_open hx) (fun m _ ↦ (H.iteratedFDeriv m).differentiableOn.congr fun _ hx ↦ iteratedFDerivWithin_of_isOpen _ t_open hx) /-- An analytic function on the whole space is infinitely differentiable there. -/ -theorem AnalyticOnNhd.contDiff [CompleteSpace F] (h : AnalyticOnNhd 𝕜 f univ) {n : ℕ∞} : +theorem AnalyticOnNhd.contDiff [CompleteSpace F] (h : AnalyticOnNhd 𝕜 f univ) {n : WithTop ℕ∞} : ContDiff 𝕜 n f := by rw [← contDiffOn_univ] exact h.contDiffOn -theorem AnalyticAt.contDiffAt [CompleteSpace F] (h : AnalyticAt 𝕜 f x) {n : ℕ∞} : +theorem AnalyticAt.contDiffAt [CompleteSpace F] (h : AnalyticAt 𝕜 f x) {n : WithTop ℕ∞} : ContDiffAt 𝕜 n f x := by obtain ⟨s, hs, hf⟩ := h.exists_mem_nhds_analyticOnNhd exact hf.contDiffOn.contDiffAt hs @@ -306,7 +308,7 @@ protected lemma AnalyticOn.contDiffOn [CompleteSpace F] {f : E → F} {s : Set E alias AnalyticWithinOn.contDiffOn := AnalyticOn.contDiffOn lemma AnalyticWithinAt.exists_hasFTaylorSeriesUpToOn [CompleteSpace F] - (n : ℕ∞) (h : AnalyticWithinAt 𝕜 f s x) : + (n : WithTop ℕ∞) (h : AnalyticWithinAt 𝕜 f s x) : ∃ u ∈ 𝓝[insert x s] x, ∃ (p : E → FormalMultilinearSeries 𝕜 E F), HasFTaylorSeriesUpToOn n f p u ∧ ∀ i, AnalyticOn 𝕜 (fun x ↦ p x i) u := by rcases h.exists_analyticAt with ⟨g, -, fg, hg⟩ @@ -545,19 +547,21 @@ theorem CPolynomialOn.iteratedFDeriv (h : CPolynomialOn 𝕜 f s) (n : ℕ) : simp /-- A polynomial function is infinitely differentiable. -/ -theorem CPolynomialOn.contDiffOn (h : CPolynomialOn 𝕜 f s) {n : ℕ∞} : - ContDiffOn 𝕜 n f s := +theorem CPolynomialOn.contDiffOn (h : CPolynomialOn 𝕜 f s) {n : WithTop ℕ∞} : + ContDiffOn 𝕜 n f s := by + suffices ContDiffOn 𝕜 ω f s from this.of_le le_top let t := { x | CPolynomialAt 𝕜 f x } - suffices ContDiffOn 𝕜 n f t from this.mono h + suffices ContDiffOn 𝕜 ω f t from this.mono h + rw [← contDiffOn_infty_iff_contDiffOn_omega] have H : CPolynomialOn 𝕜 f t := fun _x hx ↦ hx have t_open : IsOpen t := isOpen_cPolynomialAt 𝕜 f - contDiffOn_of_continuousOn_differentiableOn + exact contDiffOn_of_continuousOn_differentiableOn (fun m _ ↦ (H.iteratedFDeriv m).continuousOn.congr fun _ hx ↦ iteratedFDerivWithin_of_isOpen _ t_open hx) (fun m _ ↦ (H.iteratedFDeriv m).analyticOnNhd.differentiableOn.congr fun _ hx ↦ iteratedFDerivWithin_of_isOpen _ t_open hx) -theorem CPolynomialAt.contDiffAt (h : CPolynomialAt 𝕜 f x) {n : ℕ∞} : +theorem CPolynomialAt.contDiffAt (h : CPolynomialAt 𝕜 f x) {n : WithTop ℕ∞} : ContDiffAt 𝕜 n f x := let ⟨_, hs, hf⟩ := h.exists_mem_nhds_cPolynomialOn hf.contDiffOn.contDiffAt hs @@ -595,7 +599,7 @@ theorem changeOriginSeries_support {k l : ℕ} (h : k + l ≠ Fintype.card ι) : simp_rw [FormalMultilinearSeries.changeOriginSeriesTerm, toFormalMultilinearSeries, dif_neg h.symm, LinearIsometryEquiv.map_zero] -variable {n : ℕ∞} (x : ∀ i, E i) +variable {n : WithTop ℕ∞} (x : ∀ i, E i) open Finset in theorem changeOrigin_toFormalMultilinearSeries [DecidableEq ι] : diff --git a/Mathlib/Analysis/Calculus/FDeriv/Mul.lean b/Mathlib/Analysis/Calculus/FDeriv/Mul.lean index 6b5f7dc3f86f0..3bc95aa8d8223 100644 --- a/Mathlib/Analysis/Calculus/FDeriv/Mul.lean +++ b/Mathlib/Analysis/Calculus/FDeriv/Mul.lean @@ -678,7 +678,7 @@ theorem HasFDerivAt.list_prod' {l : List ι} {x : E} smulRight (f' l[i]) ((l.drop (.succ i)).map (f · x)).prod) x := by simp only [← List.finRange_map_get l, List.map_map] refine .congr_fderiv (hasFDerivAt_list_prod_finRange'.comp x - (hasFDerivAt_pi.mpr fun i ↦ h l[i] (List.getElem_mem i.isLt))) ?_ + (hasFDerivAt_pi.mpr fun i ↦ h l[i] (l.getElem_mem _))) ?_ ext m simp [← List.map_map] @@ -690,7 +690,7 @@ theorem HasFDerivWithinAt.list_prod' {l : List ι} {x : E} smulRight (f' l[i]) ((l.drop (.succ i)).map (f · x)).prod) s x := by simp only [← List.finRange_map_get l, List.map_map] refine .congr_fderiv (hasFDerivAt_list_prod_finRange'.comp_hasFDerivWithinAt x - (hasFDerivWithinAt_pi.mpr fun i ↦ h l[i] (l.getElem_mem i.isLt))) ?_ + (hasFDerivWithinAt_pi.mpr fun i ↦ h l[i] (l.getElem_mem _))) ?_ ext m simp [← List.map_map] diff --git a/Mathlib/Analysis/Calculus/FDeriv/Norm.lean b/Mathlib/Analysis/Calculus/FDeriv/Norm.lean index 4587f2bbf6dfc..fabdde33a4bfd 100644 --- a/Mathlib/Analysis/Calculus/FDeriv/Norm.lean +++ b/Mathlib/Analysis/Calculus/FDeriv/Norm.lean @@ -38,7 +38,7 @@ differentiability, norm open ContinuousLinearMap Filter NNReal Real Set variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] -variable {n : ℕ∞} {f : E →L[ℝ] ℝ} {x : E} {t : ℝ} +variable {n : WithTop ℕ∞} {f : E →L[ℝ] ℝ} {x : E} {t : ℝ} variable (E) in theorem not_differentiableAt_norm_zero [Nontrivial E] : @@ -72,15 +72,15 @@ theorem contDiffAt_norm_smul_iff (ht : t ≠ 0) : theorem ContDiffAt.contDiffAt_norm_of_smul (h : ContDiffAt ℝ n (‖·‖) (t • x)) : ContDiffAt ℝ n (‖·‖) x := by - obtain rfl | hn : n = 0 ∨ 1 ≤ n := by - rw [← ENat.lt_one_iff_eq_zero] - exact lt_or_le .. - · rw [contDiffAt_zero] + rcases eq_bot_or_bot_lt n with rfl | hn + · apply contDiffAt_zero.2 exact ⟨univ, univ_mem, continuous_norm.continuousOn⟩ + replace hn : 1 ≤ n := ENat.add_one_natCast_le_withTop_of_lt hn obtain rfl | ht := eq_or_ne t 0 · by_cases hE : Nontrivial E · rw [zero_smul] at h - exact (mt (ContDiffAt.differentiableAt · hn)) (not_differentiableAt_norm_zero E) h |>.elim + exact (mt (ContDiffAt.differentiableAt · (mod_cast hn))) + (not_differentiableAt_norm_zero E) h |>.elim · rw [not_nontrivial_iff_subsingleton] at hE rw [eq_const_of_subsingleton (‖·‖) 0] exact contDiffAt_const diff --git a/Mathlib/Analysis/Calculus/FDeriv/Symmetric.lean b/Mathlib/Analysis/Calculus/FDeriv/Symmetric.lean index 650429b33032d..dd21ecc35f751 100644 --- a/Mathlib/Analysis/Calculus/FDeriv/Symmetric.lean +++ b/Mathlib/Analysis/Calculus/FDeriv/Symmetric.lean @@ -446,7 +446,7 @@ theorem second_derivative_symmetric {f' : E → E →L[𝕜] F} {f'' : E →L[ second_derivative_symmetric_of_eventually (Filter.Eventually.of_forall hf) hx v w /-- If a function is `C^2` at a point, then its second derivative there is symmetric. -/ -theorem ContDiffAt.isSymmSndFDerivAt {n : ℕ∞} (hf : ContDiffAt 𝕜 n f x) (hn : 2 ≤ n) : +theorem ContDiffAt.isSymmSndFDerivAt {n : WithTop ℕ∞} (hf : ContDiffAt 𝕜 n f x) (hn : 2 ≤ n) : IsSymmSndFDerivAt 𝕜 f x := by intro v w apply second_derivative_symmetric_of_eventually (f := f) (f' := fderiv 𝕜 f) (x := x) @@ -464,7 +464,7 @@ theorem ContDiffAt.isSymmSndFDerivAt {n : ℕ∞} (hf : ContDiffAt 𝕜 n f x) ( /-- If a function is `C^2` within a set at a point, and accumulated by points in the interior of the set, then its second derivative there is symmetric. -/ -theorem ContDiffWithinAt.isSymmSndFDerivWithinAt {n : ℕ∞} (hf : ContDiffWithinAt 𝕜 n f s x) +theorem ContDiffWithinAt.isSymmSndFDerivWithinAt {n : WithTop ℕ∞} (hf : ContDiffWithinAt 𝕜 n f s x) (hn : 2 ≤ n) (hs : UniqueDiffOn 𝕜 s) (hx : x ∈ closure (interior s)) (h'x : x ∈ s) : IsSymmSndFDerivWithinAt 𝕜 f s x := by /- We argue that, at interior points, the second derivative is symmetric, and moreover by diff --git a/Mathlib/Analysis/Calculus/InverseFunctionTheorem/ContDiff.lean b/Mathlib/Analysis/Calculus/InverseFunctionTheorem/ContDiff.lean index 55e18e301150a..49b5c3a3c929c 100644 --- a/Mathlib/Analysis/Calculus/InverseFunctionTheorem/ContDiff.lean +++ b/Mathlib/Analysis/Calculus/InverseFunctionTheorem/ContDiff.lean @@ -20,46 +20,46 @@ namespace ContDiffAt variable {𝕂 : Type*} [RCLike 𝕂] variable {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕂 E] variable {F : Type*} [NormedAddCommGroup F] [NormedSpace 𝕂 F] -variable [CompleteSpace E] (f : E → F) {f' : E ≃L[𝕂] F} {a : E} +variable [CompleteSpace E] (f : E → F) {f' : E ≃L[𝕂] F} {a : E} {n : WithTop ℕ∞} /-- Given a `ContDiff` function over `𝕂` (which is `ℝ` or `ℂ`) with an invertible derivative at `a`, returns a `PartialHomeomorph` with `to_fun = f` and `a ∈ source`. -/ -def toPartialHomeomorph {n : ℕ∞} (hf : ContDiffAt 𝕂 n f a) (hf' : HasFDerivAt f (f' : E →L[𝕂] F) a) +def toPartialHomeomorph (hf : ContDiffAt 𝕂 n f a) (hf' : HasFDerivAt f (f' : E →L[𝕂] F) a) (hn : 1 ≤ n) : PartialHomeomorph E F := (hf.hasStrictFDerivAt' hf' hn).toPartialHomeomorph f variable {f} @[simp] -theorem toPartialHomeomorph_coe {n : ℕ∞} (hf : ContDiffAt 𝕂 n f a) +theorem toPartialHomeomorph_coe (hf : ContDiffAt 𝕂 n f a) (hf' : HasFDerivAt f (f' : E →L[𝕂] F) a) (hn : 1 ≤ n) : (hf.toPartialHomeomorph f hf' hn : E → F) = f := rfl -theorem mem_toPartialHomeomorph_source {n : ℕ∞} (hf : ContDiffAt 𝕂 n f a) +theorem mem_toPartialHomeomorph_source (hf : ContDiffAt 𝕂 n f a) (hf' : HasFDerivAt f (f' : E →L[𝕂] F) a) (hn : 1 ≤ n) : a ∈ (hf.toPartialHomeomorph f hf' hn).source := (hf.hasStrictFDerivAt' hf' hn).mem_toPartialHomeomorph_source -theorem image_mem_toPartialHomeomorph_target {n : ℕ∞} (hf : ContDiffAt 𝕂 n f a) +theorem image_mem_toPartialHomeomorph_target (hf : ContDiffAt 𝕂 n f a) (hf' : HasFDerivAt f (f' : E →L[𝕂] F) a) (hn : 1 ≤ n) : f a ∈ (hf.toPartialHomeomorph f hf' hn).target := (hf.hasStrictFDerivAt' hf' hn).image_mem_toPartialHomeomorph_target /-- Given a `ContDiff` function over `𝕂` (which is `ℝ` or `ℂ`) with an invertible derivative at `a`, returns a function that is locally inverse to `f`. -/ -def localInverse {n : ℕ∞} (hf : ContDiffAt 𝕂 n f a) (hf' : HasFDerivAt f (f' : E →L[𝕂] F) a) +def localInverse (hf : ContDiffAt 𝕂 n f a) (hf' : HasFDerivAt f (f' : E →L[𝕂] F) a) (hn : 1 ≤ n) : F → E := (hf.hasStrictFDerivAt' hf' hn).localInverse f f' a -theorem localInverse_apply_image {n : ℕ∞} (hf : ContDiffAt 𝕂 n f a) +theorem localInverse_apply_image (hf : ContDiffAt 𝕂 n f a) (hf' : HasFDerivAt f (f' : E →L[𝕂] F) a) (hn : 1 ≤ n) : hf.localInverse hf' hn (f a) = a := (hf.hasStrictFDerivAt' hf' hn).localInverse_apply_image /-- Given a `ContDiff` function over `𝕂` (which is `ℝ` or `ℂ`) with an invertible derivative at `a`, the inverse function (produced by `ContDiff.toPartialHomeomorph`) is also `ContDiff`. -/ -theorem to_localInverse {n : ℕ∞} (hf : ContDiffAt 𝕂 n f a) +theorem to_localInverse (hf : ContDiffAt 𝕂 n f a) (hf' : HasFDerivAt f (f' : E →L[𝕂] F) a) (hn : 1 ≤ n) : ContDiffAt 𝕂 n (hf.localInverse hf' hn) (f a) := by have := hf.localInverse_apply_image hf' hn diff --git a/Mathlib/Analysis/Calculus/IteratedDeriv/Defs.lean b/Mathlib/Analysis/Calculus/IteratedDeriv/Defs.lean index 9fcaa3d13a0cc..858642c83caa8 100644 --- a/Mathlib/Analysis/Calculus/IteratedDeriv/Defs.lean +++ b/Mathlib/Analysis/Calculus/IteratedDeriv/Defs.lean @@ -131,12 +131,13 @@ theorem contDiffOn_of_differentiableOn_deriv {n : ℕ∞} /-- On a set with unique derivatives, a `C^n` function has derivatives up to `n` which are continuous. -/ -theorem ContDiffOn.continuousOn_iteratedDerivWithin {n : ℕ∞} {m : ℕ} (h : ContDiffOn 𝕜 n f s) +theorem ContDiffOn.continuousOn_iteratedDerivWithin + {n : WithTop ℕ∞} {m : ℕ} (h : ContDiffOn 𝕜 n f s) (hmn : (m : ℕ∞) ≤ n) (hs : UniqueDiffOn 𝕜 s) : ContinuousOn (iteratedDerivWithin m f s) s := by simpa only [iteratedDerivWithin_eq_equiv_comp, LinearIsometryEquiv.comp_continuousOn_iff] using h.continuousOn_iteratedFDerivWithin hmn hs -theorem ContDiffWithinAt.differentiableWithinAt_iteratedDerivWithin {n : ℕ∞} {m : ℕ} +theorem ContDiffWithinAt.differentiableWithinAt_iteratedDerivWithin {n : WithTop ℕ∞} {m : ℕ} (h : ContDiffWithinAt 𝕜 n f s x) (hmn : (m : ℕ∞) < n) (hs : UniqueDiffOn 𝕜 (insert x s)) : DifferentiableWithinAt 𝕜 (iteratedDerivWithin m f s) s x := by simpa only [iteratedDerivWithin_eq_equiv_comp, @@ -145,8 +146,8 @@ theorem ContDiffWithinAt.differentiableWithinAt_iteratedDerivWithin {n : ℕ∞} /-- On a set with unique derivatives, a `C^n` function has derivatives less than `n` which are differentiable. -/ -theorem ContDiffOn.differentiableOn_iteratedDerivWithin {n : ℕ∞} {m : ℕ} (h : ContDiffOn 𝕜 n f s) - (hmn : (m : ℕ∞) < n) (hs : UniqueDiffOn 𝕜 s) : +theorem ContDiffOn.differentiableOn_iteratedDerivWithin {n : WithTop ℕ∞} {m : ℕ} + (h : ContDiffOn 𝕜 n f s) (hmn : m < n) (hs : UniqueDiffOn 𝕜 s) : DifferentiableOn 𝕜 (iteratedDerivWithin m f s) s := fun x hx => (h x hx).differentiableWithinAt_iteratedDerivWithin hmn <| by rwa [insert_eq_of_mem hx] @@ -238,13 +239,14 @@ theorem contDiff_of_differentiable_iteratedDeriv {n : ℕ∞} (h : ∀ m : ℕ, (m : ℕ∞) ≤ n → Differentiable 𝕜 (iteratedDeriv m f)) : ContDiff 𝕜 n f := contDiff_iff_iteratedDeriv.2 ⟨fun m hm => (h m hm).continuous, fun m hm => h m (le_of_lt hm)⟩ -theorem ContDiff.continuous_iteratedDeriv {n : ℕ∞} (m : ℕ) (h : ContDiff 𝕜 n f) - (hmn : (m : ℕ∞) ≤ n) : Continuous (iteratedDeriv m f) := - (contDiff_iff_iteratedDeriv.1 h).1 m hmn +theorem ContDiff.continuous_iteratedDeriv {n : WithTop ℕ∞} (m : ℕ) (h : ContDiff 𝕜 n f) + (hmn : m ≤ n) : Continuous (iteratedDeriv m f) := + (contDiff_iff_iteratedDeriv.1 (h.of_le hmn)).1 m le_rfl -theorem ContDiff.differentiable_iteratedDeriv {n : ℕ∞} (m : ℕ) (h : ContDiff 𝕜 n f) - (hmn : (m : ℕ∞) < n) : Differentiable 𝕜 (iteratedDeriv m f) := - (contDiff_iff_iteratedDeriv.1 h).2 m hmn +theorem ContDiff.differentiable_iteratedDeriv {n : WithTop ℕ∞} (m : ℕ) (h : ContDiff 𝕜 n f) + (hmn : m < n) : Differentiable 𝕜 (iteratedDeriv m f) := + (contDiff_iff_iteratedDeriv.1 (h.of_le (ENat.add_one_natCast_le_withTop_of_lt hmn))).2 m + (mod_cast (lt_add_one m)) /-- The `n+1`-th iterated derivative can be obtained by differentiating the `n`-th iterated derivative. -/ diff --git a/Mathlib/Analysis/Calculus/LHopital.lean b/Mathlib/Analysis/Calculus/LHopital.lean index f1e691d8342cf..66b0aac6e04cc 100644 --- a/Mathlib/Analysis/Calculus/LHopital.lean +++ b/Mathlib/Analysis/Calculus/LHopital.lean @@ -110,11 +110,11 @@ theorem lhopital_zero_left_on_Ioo (hab : a < b) (hff' : ∀ x ∈ Ioo a b, HasDe comp x (hff' (-x) hx) (hasDerivAt_neg x) have hdng : ∀ x ∈ -Ioo a b, HasDerivAt (g ∘ Neg.neg) (g' (-x) * -1) x := fun x hx => comp x (hgg' (-x) hx) (hasDerivAt_neg x) - rw [preimage_neg_Ioo] at hdnf - rw [preimage_neg_Ioo] at hdng + rw [neg_Ioo] at hdnf + rw [neg_Ioo] at hdng have := lhopital_zero_right_on_Ioo (neg_lt_neg hab) hdnf hdng (by intro x hx h - apply hg' _ (by rw [← preimage_neg_Ioo] at hx; exact hx) + apply hg' _ (by rw [← neg_Ioo] at hx; exact hx) rwa [mul_comm, ← neg_eq_neg_one_mul, neg_eq_zero] at h) (hfb.comp tendsto_neg_nhdsWithin_Ioi_neg) (hgb.comp tendsto_neg_nhdsWithin_Ioi_neg) (by @@ -176,12 +176,12 @@ theorem lhopital_zero_atBot_on_Iio (hff' : ∀ x ∈ Iio a, HasDerivAt f (f' x) comp x (hff' (-x) hx) (hasDerivAt_neg x) have hdng : ∀ x ∈ -Iio a, HasDerivAt (g ∘ Neg.neg) (g' (-x) * -1) x := fun x hx => comp x (hgg' (-x) hx) (hasDerivAt_neg x) - rw [preimage_neg_Iio] at hdnf - rw [preimage_neg_Iio] at hdng + rw [neg_Iio] at hdnf + rw [neg_Iio] at hdng have := lhopital_zero_atTop_on_Ioi hdnf hdng (by intro x hx h - apply hg' _ (by rw [← preimage_neg_Iio] at hx; exact hx) + apply hg' _ (by rw [← neg_Iio] at hx; exact hx) rwa [mul_comm, ← neg_eq_neg_one_mul, neg_eq_zero] at h) (hfbot.comp tendsto_neg_atTop_atBot) (hgbot.comp tendsto_neg_atTop_atBot) (by diff --git a/Mathlib/Analysis/Calculus/Monotone.lean b/Mathlib/Analysis/Calculus/Monotone.lean index 599a701b6b211..f54f48fe98117 100644 --- a/Mathlib/Analysis/Calculus/Monotone.lean +++ b/Mathlib/Analysis/Calculus/Monotone.lean @@ -108,7 +108,7 @@ theorem StieltjesFunction.ae_hasDerivAt (f : StieltjesFunction) : filter_upwards [this] rintro y ⟨hy : x - 1 < y, h'y : y < x⟩ rw [mem_Iio] - norm_num; nlinarith + nlinarith -- Deduce the correct limit on the left, by sandwiching. have L4 : Tendsto (fun y => (f y - f x) / (y - x)) (𝓝[<] x) (𝓝 (rnDeriv f.measure volume x).toReal) := by @@ -118,7 +118,7 @@ theorem StieltjesFunction.ae_hasDerivAt (f : StieltjesFunction) : refine div_le_div_of_nonpos_of_le (by linarith) ((sub_le_sub_iff_right _).2 ?_) apply f.mono.le_leftLim have : ↑0 < (x - y) ^ 2 := sq_pos_of_pos (sub_pos.2 hy) - norm_num; linarith + linarith · filter_upwards [self_mem_nhdsWithin] rintro y (hy : y < x) refine div_le_div_of_nonpos_of_le (by linarith) ?_ @@ -161,7 +161,7 @@ theorem Monotone.ae_hasDerivAt {f : ℝ → ℝ} (hf : Monotone f) : filter_upwards [this] rintro y ⟨hy : x < y, h'y : y < x + 1⟩ rw [mem_Ioi] - norm_num; nlinarith + nlinarith -- apply the sandwiching argument, with the helper function and `g` apply tendsto_of_tendsto_of_tendsto_of_le_of_le' this hx.2 · filter_upwards [self_mem_nhdsWithin] with y hy @@ -190,7 +190,7 @@ theorem Monotone.ae_hasDerivAt {f : ℝ → ℝ} (hf : Monotone f) : rintro y hy rw [mem_Ioo] at hy rw [mem_Iio] - norm_num; nlinarith + nlinarith -- apply the sandwiching argument, with `g` and the helper function apply tendsto_of_tendsto_of_tendsto_of_le_of_le' hx.1 this · filter_upwards [self_mem_nhdsWithin] @@ -203,7 +203,7 @@ theorem Monotone.ae_hasDerivAt {f : ℝ → ℝ} (hf : Monotone f) : rw [mem_Iio, ← sub_neg] at hy have : 0 < (y - x) ^ 2 := sq_pos_of_neg hy apply div_le_div_of_nonpos_of_le hy.le - exact (sub_le_sub_iff_right _).2 (hf.rightLim_le (by norm_num; linarith)) + exact (sub_le_sub_iff_right _).2 (hf.rightLim_le (by linarith)) -- conclude global differentiability rw [hasDerivAt_iff_tendsto_slope, slope_fun_def_field, (nhds_left'_sup_nhds_right' x).symm, tendsto_sup] diff --git a/Mathlib/Analysis/Calculus/Rademacher.lean b/Mathlib/Analysis/Calculus/Rademacher.lean index 28ad0559741a1..1c836a3a36f92 100644 --- a/Mathlib/Analysis/Calculus/Rademacher.lean +++ b/Mathlib/Analysis/Calculus/Rademacher.lean @@ -221,9 +221,9 @@ theorem ae_lineDeriv_sum_eq suffices S2 : ∫ x, (∑ i ∈ s, a i * fderiv ℝ g x (v i)) * f x ∂μ = ∑ i ∈ s, a i * ∫ x, fderiv ℝ g x (v i) * f x ∂μ by obtain ⟨D, g_lip⟩ : ∃ D, LipschitzWith D g := - ContDiff.lipschitzWith_of_hasCompactSupport g_comp g_smooth le_top + ContDiff.lipschitzWith_of_hasCompactSupport g_comp g_smooth (mod_cast le_top) simp_rw [integral_lineDeriv_mul_eq hf g_lip g_comp] - simp_rw [(g_smooth.differentiable le_top).differentiableAt.lineDeriv_eq_fderiv] + simp_rw [(g_smooth.differentiable (mod_cast le_top)).differentiableAt.lineDeriv_eq_fderiv] simp only [map_neg, _root_.map_sum, _root_.map_smul, smul_eq_mul, neg_mul] simp only [integral_neg, mul_neg, Finset.sum_neg_distrib, neg_inj] exact S2 @@ -233,7 +233,8 @@ theorem ae_lineDeriv_sum_eq let L : (E →L[ℝ] ℝ) → ℝ := fun f ↦ f (v i) change Integrable (fun x ↦ a i * ((L ∘ (fderiv ℝ g)) x * f x)) μ refine (Continuous.integrable_of_hasCompactSupport ?_ ?_).const_mul _ - · exact ((g_smooth.continuous_fderiv le_top).clm_apply continuous_const).mul hf.continuous + · exact ((g_smooth.continuous_fderiv (mod_cast le_top)).clm_apply continuous_const).mul + hf.continuous · exact ((g_comp.fderiv ℝ).comp_left rfl).mul_right /-! diff --git a/Mathlib/Analysis/Calculus/SmoothSeries.lean b/Mathlib/Analysis/Calculus/SmoothSeries.lean index 58d0f39d86c54..073a4b2192939 100644 --- a/Mathlib/Analysis/Calculus/SmoothSeries.lean +++ b/Mathlib/Analysis/Calculus/SmoothSeries.lean @@ -198,7 +198,8 @@ theorem iteratedFDeriv_tsum (hf : ∀ i, ContDiff 𝕜 N (f i)) have A : Summable fun n => iteratedFDeriv 𝕜 k (f n) 0 := .of_norm_bounded (v k) (hv k h'k.le) fun n => h'f k n 0 h'k.le simp_rw [iteratedFDeriv_succ_eq_comp_left, IH h'k.le] - rw [fderiv_tsum (hv _ hk) (fun n => (hf n).differentiable_iteratedFDeriv h'k) _ A] + rw [fderiv_tsum (hv _ hk) (fun n => (hf n).differentiable_iteratedFDeriv + (mod_cast h'k)) _ A] · ext1 x exact (continuousMultilinearCurryLeftEquiv 𝕜 (fun _ : Fin (k + 1) => E) F).symm.toContinuousLinearEquiv.map_tsum @@ -219,7 +220,7 @@ theorem iteratedFDeriv_tsum_apply (hf : ∀ i, ContDiff 𝕜 N (f i)) class `C^N`, and moreover there is a uniform summable upper bound on the `k`-th derivative for each `k ≤ N`. Then the series is also `C^N`. -/ theorem contDiff_tsum (hf : ∀ i, ContDiff 𝕜 N (f i)) (hv : ∀ k : ℕ, (k : ℕ∞) ≤ N → Summable (v k)) - (h'f : ∀ (k : ℕ) (i : α) (x : E), (k : ℕ∞) ≤ N → ‖iteratedFDeriv 𝕜 k (f i) x‖ ≤ v k i) : + (h'f : ∀ (k : ℕ) (i : α) (x : E), k ≤ N → ‖iteratedFDeriv 𝕜 k (f i) x‖ ≤ v k i) : ContDiff 𝕜 N fun x => ∑' i, f i x := by rw [contDiff_iff_continuous_differentiable] constructor @@ -227,16 +228,16 @@ theorem contDiff_tsum (hf : ∀ i, ContDiff 𝕜 N (f i)) (hv : ∀ k : ℕ, (k rw [iteratedFDeriv_tsum hf hv h'f hm] refine continuous_tsum ?_ (hv m hm) ?_ · intro i - exact ContDiff.continuous_iteratedFDeriv hm (hf i) + exact ContDiff.continuous_iteratedFDeriv (mod_cast hm) (hf i) · intro n x exact h'f _ _ _ hm · intro m hm have h'm : ((m + 1 : ℕ) : ℕ∞) ≤ N := by simpa only [ENat.coe_add, ENat.coe_one] using Order.add_one_le_of_lt hm rw [iteratedFDeriv_tsum hf hv h'f hm.le] - have A : - ∀ n x, HasFDerivAt (iteratedFDeriv 𝕜 m (f n)) (fderiv 𝕜 (iteratedFDeriv 𝕜 m (f n)) x) x := - fun n x => (ContDiff.differentiable_iteratedFDeriv hm (hf n)).differentiableAt.hasFDerivAt + have A n x : HasFDerivAt (iteratedFDeriv 𝕜 m (f n)) (fderiv 𝕜 (iteratedFDeriv 𝕜 m (f n)) x) x := + (ContDiff.differentiable_iteratedFDeriv (mod_cast hm) + (hf n)).differentiableAt.hasFDerivAt refine differentiable_tsum (hv _ h'm) A fun n x => ?_ rw [fderiv_iteratedFDeriv, comp_apply, LinearIsometryEquiv.norm_map] exact h'f _ _ _ h'm @@ -245,11 +246,9 @@ theorem contDiff_tsum (hf : ∀ i, ContDiff 𝕜 N (f i)) (hv : ∀ k : ℕ, (k class `C^N`, and moreover there is a uniform summable upper bound on the `k`-th derivative for each `k ≤ N` (except maybe for finitely many `i`s). Then the series is also `C^N`. -/ theorem contDiff_tsum_of_eventually (hf : ∀ i, ContDiff 𝕜 N (f i)) - (hv : ∀ k : ℕ, (k : ℕ∞) ≤ N → Summable (v k)) - (h'f : - ∀ k : ℕ, - (k : ℕ∞) ≤ N → - ∀ᶠ i in (Filter.cofinite : Filter α), ∀ x : E, ‖iteratedFDeriv 𝕜 k (f i) x‖ ≤ v k i) : + (hv : ∀ k : ℕ, k ≤ N → Summable (v k)) + (h'f : ∀ k : ℕ, k ≤ N → + ∀ᶠ i in (Filter.cofinite : Filter α), ∀ x : E, ‖iteratedFDeriv 𝕜 k (f i) x‖ ≤ v k i) : ContDiff 𝕜 N fun x => ∑' i, f i x := by classical refine contDiff_iff_forall_nat_le.2 fun m hm => ?_ @@ -274,10 +273,10 @@ theorem contDiff_tsum_of_eventually (hf : ∀ i, ContDiff 𝕜 N (f i)) filter_upwards [h'f 0 (zero_le _)] with i hi simpa only [norm_iteratedFDeriv_zero] using hi x rw [this] - apply (ContDiff.sum fun i _ => (hf i).of_le hm).add + apply (ContDiff.sum fun i _ => (hf i).of_le (mod_cast hm)).add have h'u : ∀ k : ℕ, (k : ℕ∞) ≤ m → Summable (v k ∘ ((↑) : { i // i ∉ T } → α)) := fun k hk => (hv k (hk.trans hm)).subtype _ - refine contDiff_tsum (fun i => (hf i).of_le hm) h'u ?_ + refine contDiff_tsum (fun i => (hf i).of_le (mod_cast hm)) h'u ?_ rintro k ⟨i, hi⟩ x hk simp only [t, T, Finite.mem_toFinset, mem_setOf_eq, Finset.mem_range, not_forall, not_le, exists_prop, not_exists, not_and, not_lt] at hi diff --git a/Mathlib/Analysis/Calculus/Taylor.lean b/Mathlib/Analysis/Calculus/Taylor.lean index 71293eb9d3058..8a56fcf0d80a4 100644 --- a/Mathlib/Analysis/Calculus/Taylor.lean +++ b/Mathlib/Analysis/Calculus/Taylor.lean @@ -119,7 +119,8 @@ theorem continuousOn_taylorWithinEval {f : ℝ → E} {x : ℝ} {n : ℕ} {s : S simp_rw [taylor_within_apply] refine continuousOn_finset_sum (Finset.range (n + 1)) fun i hi => ?_ refine (continuousOn_const.mul ((continuousOn_const.sub continuousOn_id).pow _)).smul ?_ - rw [contDiffOn_iff_continuousOn_differentiableOn_deriv hs] at hf + rw [show (n : WithTop ℕ∞) = (n : ℕ∞) by rfl, + contDiffOn_iff_continuousOn_differentiableOn_deriv hs] at hf cases' hf with hf_left specialize hf_left i simp only [Finset.mem_range] at hi @@ -179,7 +180,7 @@ theorem hasDerivWithinAt_taylorWithinEval {f : ℝ → E} {x y : ℝ} {n : ℕ} simp only [add_zero, Nat.factorial_succ, Nat.cast_mul, Nat.cast_add, Nat.cast_one] have coe_lt_succ : (k : WithTop ℕ) < k.succ := Nat.cast_lt.2 k.lt_succ_self have hdiff : DifferentiableOn ℝ (iteratedDerivWithin k f s) s' := - (hf.differentiableOn_iteratedDerivWithin coe_lt_succ hs_unique).mono h + (hf.differentiableOn_iteratedDerivWithin (mod_cast coe_lt_succ) hs_unique).mono h specialize hk hf.of_succ ((hdiff y hy).mono_of_mem_nhdsWithin hs') convert hk.add (hasDerivWithinAt_taylor_coeff_within hs'_unique (nhdsWithin_mono _ h self_mem_nhdsWithin) hf') using 1 @@ -305,7 +306,7 @@ theorem taylor_mean_remainder_bound {f : ℝ → E} {a b C x : ℝ} {n : ℕ} (h simp [hx] -- The nth iterated derivative is differentiable have hf' : DifferentiableOn ℝ (iteratedDerivWithin n f (Icc a b)) (Icc a b) := - hf.differentiableOn_iteratedDerivWithin (WithTop.coe_lt_coe.mpr n.lt_succ_self) + hf.differentiableOn_iteratedDerivWithin (mod_cast n.lt_succ_self) (uniqueDiffOn_Icc h) -- We can uniformly bound the derivative of the Taylor polynomial have h' : ∀ y ∈ Ico a x, diff --git a/Mathlib/Analysis/Calculus/VectorField.lean b/Mathlib/Analysis/Calculus/VectorField.lean index d4e54bc4485f9..ac4eb32fdc707 100644 --- a/Mathlib/Analysis/Calculus/VectorField.lean +++ b/Mathlib/Analysis/Calculus/VectorField.lean @@ -144,7 +144,7 @@ lemma lieBracket_swap : lieBracket 𝕜 V W x = - lieBracket 𝕜 W V x := by ext x; simp [lieBracket] lemma _root_.ContDiffWithinAt.lieBracketWithin_vectorField - {m n : ℕ∞} (hV : ContDiffWithinAt 𝕜 n V s x) + {m n : WithTop ℕ∞} (hV : ContDiffWithinAt 𝕜 n V s x) (hW : ContDiffWithinAt 𝕜 n W s x) (hs : UniqueDiffOn 𝕜 s) (hmn : m + 1 ≤ n) (hx : x ∈ s) : ContDiffWithinAt 𝕜 m (lieBracketWithin 𝕜 V W s) s x := by apply ContDiffWithinAt.sub @@ -153,19 +153,19 @@ lemma _root_.ContDiffWithinAt.lieBracketWithin_vectorField · exact ContDiffWithinAt.clm_apply (hV.fderivWithin_right hs hmn hx) (hW.of_le (le_trans le_self_add hmn)) -lemma _root_.ContDiffAt.lieBracket_vectorField {m n : ℕ∞} (hV : ContDiffAt 𝕜 n V x) +lemma _root_.ContDiffAt.lieBracket_vectorField {m n : WithTop ℕ∞} (hV : ContDiffAt 𝕜 n V x) (hW : ContDiffAt 𝕜 n W x) (hmn : m + 1 ≤ n) : ContDiffAt 𝕜 m (lieBracket 𝕜 V W) x := by rw [← contDiffWithinAt_univ] at hV hW ⊢ simp_rw [← lieBracketWithin_univ] exact hV.lieBracketWithin_vectorField hW uniqueDiffOn_univ hmn (mem_univ _) -lemma _root_.ContDiffOn.lieBracketWithin_vectorField {m n : ℕ∞} (hV : ContDiffOn 𝕜 n V s) +lemma _root_.ContDiffOn.lieBracketWithin_vectorField {m n : WithTop ℕ∞} (hV : ContDiffOn 𝕜 n V s) (hW : ContDiffOn 𝕜 n W s) (hs : UniqueDiffOn 𝕜 s) (hmn : m + 1 ≤ n) : ContDiffOn 𝕜 m (lieBracketWithin 𝕜 V W s) s := fun x hx ↦ (hV x hx).lieBracketWithin_vectorField (hW x hx) hs hmn hx -lemma _root_.ContDiff.lieBracket_vectorField {m n : ℕ∞} (hV : ContDiff 𝕜 n V) +lemma _root_.ContDiff.lieBracket_vectorField {m n : WithTop ℕ∞} (hV : ContDiff 𝕜 n V) (hW : ContDiff 𝕜 n W) (hmn : m + 1 ≤ n) : ContDiff 𝕜 m (lieBracket 𝕜 V W) := contDiff_iff_contDiffAt.2 (fun _ ↦ hV.contDiffAt.lieBracket_vectorField hW.contDiffAt hmn) diff --git a/Mathlib/Analysis/Complex/AbelLimit.lean b/Mathlib/Analysis/Complex/AbelLimit.lean index 25d7f649514c6..7e5aea15a8967 100644 --- a/Mathlib/Analysis/Complex/AbelLimit.lean +++ b/Mathlib/Analysis/Complex/AbelLimit.lean @@ -6,7 +6,7 @@ Authors: Jeremy Tan import Mathlib.Analysis.Complex.Basic import Mathlib.Analysis.SpecificLimits.Normed import Mathlib.Tactic.Peel -import Mathlib.Tactic.Positivity.Finset +import Mathlib.Tactic.Positivity /-! # Abel's limit theorem diff --git a/Mathlib/Analysis/Complex/Circle.lean b/Mathlib/Analysis/Complex/Circle.lean index 72e66ae46c1b7..e4a9a2e283278 100644 --- a/Mathlib/Analysis/Complex/Circle.lean +++ b/Mathlib/Analysis/Complex/Circle.lean @@ -41,17 +41,17 @@ open ComplexConjugate /-- The unit circle in `ℂ`, here given the structure of a submonoid of `ℂ`. Please use `Circle` when referring to the circle as a type. -/ -@[deprecated (since := "2024-07-24")] +@[deprecated "No deprecation message was provided." (since := "2024-07-24")] def circle : Submonoid ℂ := Submonoid.unitSphere ℂ set_option linter.deprecated false in -@[deprecated (since := "2024-07-24")] +@[deprecated "No deprecation message was provided." (since := "2024-07-24")] theorem mem_circle_iff_abs {z : ℂ} : z ∈ circle ↔ abs z = 1 := mem_sphere_zero_iff_norm set_option linter.deprecated false in -@[deprecated (since := "2024-07-24")] +@[deprecated "No deprecation message was provided." (since := "2024-07-24")] theorem mem_circle_iff_normSq {z : ℂ} : z ∈ circle ↔ normSq z = 1 := by simp [Complex.abs, mem_circle_iff_abs] diff --git a/Mathlib/Analysis/Complex/RealDeriv.lean b/Mathlib/Analysis/Complex/RealDeriv.lean index 3ce85a20eb6f5..1609fa5e357a4 100644 --- a/Mathlib/Analysis/Complex/RealDeriv.lean +++ b/Mathlib/Analysis/Complex/RealDeriv.lean @@ -77,14 +77,14 @@ theorem HasDerivAt.real_of_complex (h : HasDerivAt e e' z) : rw [ContinuousLinearMap.comp_apply, ContinuousLinearMap.comp_apply] simp -theorem ContDiffAt.real_of_complex {n : ℕ∞} (h : ContDiffAt ℂ n e z) : +theorem ContDiffAt.real_of_complex {n : WithTop ℕ∞} (h : ContDiffAt ℂ n e z) : ContDiffAt ℝ n (fun x : ℝ => (e x).re) z := by have A : ContDiffAt ℝ n ((↑) : ℝ → ℂ) z := ofRealCLM.contDiff.contDiffAt have B : ContDiffAt ℝ n e z := h.restrict_scalars ℝ have C : ContDiffAt ℝ n re (e z) := reCLM.contDiff.contDiffAt exact C.comp z (B.comp z A) -theorem ContDiff.real_of_complex {n : ℕ∞} (h : ContDiff ℂ n e) : +theorem ContDiff.real_of_complex {n : WithTop ℕ∞} (h : ContDiff ℂ n e) : ContDiff ℝ n fun x : ℝ => (e x).re := contDiff_iff_contDiffAt.2 fun _ => h.contDiffAt.real_of_complex diff --git a/Mathlib/Analysis/Complex/UpperHalfPlane/Basic.lean b/Mathlib/Analysis/Complex/UpperHalfPlane/Basic.lean index 0ac5af563ff8a..6a3125c87d0c9 100644 --- a/Mathlib/Analysis/Complex/UpperHalfPlane/Basic.lean +++ b/Mathlib/Analysis/Complex/UpperHalfPlane/Basic.lean @@ -243,9 +243,9 @@ theorem denom_cocycle (x y : GL(2, ℝ)⁺) (z : ℍ) : denom (x * y) z = denom x (smulAux y z) * denom y z := by change _ = (_ * (_ / _) + _) * _ field_simp [denom_ne_zero] - simp only [Matrix.mul_apply, dotProduct, Fin.sum_univ_succ, denom, num, Subgroup.coe_mul, - GeneralLinearGroup.coe_mul, Fintype.univ_ofSubsingleton, Fin.mk_zero, Finset.sum_singleton, - Fin.succ_zero_eq_one, Complex.ofReal_add, Complex.ofReal_mul] + simp only [denom, Subgroup.coe_mul, Fin.isValue, Units.val_mul, mul_apply, Fin.sum_univ_succ, + Finset.univ_unique, Fin.default_eq_zero, Finset.sum_singleton, Fin.succ_zero_eq_one, + Complex.ofReal_add, Complex.ofReal_mul, num] ring theorem mul_smul' (x y : GL(2, ℝ)⁺) (z : ℍ) : smulAux (x * y) z = smulAux x (smulAux y z) := by @@ -254,9 +254,9 @@ theorem mul_smul' (x y : GL(2, ℝ)⁺) (z : ℍ) : smulAux (x * y) z = smulAux change _ / _ = (_ * (_ / _) + _) / _ rw [denom_cocycle] field_simp [denom_ne_zero] - simp only [Matrix.mul_apply, dotProduct, Fin.sum_univ_succ, num, denom, Subgroup.coe_mul, - GeneralLinearGroup.coe_mul, Fintype.univ_ofSubsingleton, Fin.mk_zero, Finset.sum_singleton, - Fin.succ_zero_eq_one, Complex.ofReal_add, Complex.ofReal_mul] + simp only [num, Subgroup.coe_mul, Fin.isValue, Units.val_mul, mul_apply, Fin.sum_univ_succ, + Finset.univ_unique, Fin.default_eq_zero, Finset.sum_singleton, Fin.succ_zero_eq_one, + Complex.ofReal_add, Complex.ofReal_mul, denom] ring /-- The action of `GLPos 2 ℝ` on the upper half-plane by fractional linear transformations. -/ diff --git a/Mathlib/Analysis/Complex/UpperHalfPlane/Manifold.lean b/Mathlib/Analysis/Complex/UpperHalfPlane/Manifold.lean index c821c8feafdcb..9529dbcb764f2 100644 --- a/Mathlib/Analysis/Complex/UpperHalfPlane/Manifold.lean +++ b/Mathlib/Analysis/Complex/UpperHalfPlane/Manifold.lean @@ -26,15 +26,17 @@ instance : SmoothManifoldWithCorners 𝓘(ℂ) ℍ := UpperHalfPlane.isOpenEmbedding_coe.singleton_smoothManifoldWithCorners /-- The inclusion map `ℍ → ℂ` is a smooth map of manifolds. -/ -theorem smooth_coe : Smooth 𝓘(ℂ) 𝓘(ℂ) ((↑) : ℍ → ℂ) := fun _ => contMDiffAt_extChartAt +theorem contMDiff_coe : ContMDiff 𝓘(ℂ) 𝓘(ℂ) ⊤ ((↑) : ℍ → ℂ) := fun _ => contMDiffAt_extChartAt + +@[deprecated (since := "2024-11-20")] alias smooth_coe := contMDiff_coe /-- The inclusion map `ℍ → ℂ` is a differentiable map of manifolds. -/ theorem mdifferentiable_coe : MDifferentiable 𝓘(ℂ) 𝓘(ℂ) ((↑) : ℍ → ℂ) := - smooth_coe.mdifferentiable + contMDiff_coe.mdifferentiable (by simp) -lemma smoothAt_ofComplex {z : ℂ} (hz : 0 < z.im) : - SmoothAt 𝓘(ℂ) 𝓘(ℂ) ofComplex z := by - rw [SmoothAt, contMDiffAt_iff] +lemma contMDiffAt_ofComplex {z : ℂ} (hz : 0 < z.im) : + ContMDiffAt 𝓘(ℂ) 𝓘(ℂ) ⊤ ofComplex z := by + rw [contMDiffAt_iff] constructor · -- continuity at z rw [ContinuousAt, nhds_induced, tendsto_comap_iff] @@ -48,9 +50,11 @@ lemma smoothAt_ofComplex {z : ℂ} (hz : 0 < z.im) : Set.range_id, id_eq, contDiffWithinAt_univ] exact contDiffAt_id.congr_of_eventuallyEq (eventuallyEq_coe_comp_ofComplex hz) +@[deprecated (since := "2024-11-20")] alias smoothAt_ofComplex := contMDiffAt_ofComplex + lemma mdifferentiableAt_ofComplex {z : ℂ} (hz : 0 < z.im) : MDifferentiableAt 𝓘(ℂ) 𝓘(ℂ) ofComplex z := - (smoothAt_ofComplex hz).mdifferentiableAt + (contMDiffAt_ofComplex hz).mdifferentiableAt (by simp) lemma mdifferentiableAt_iff {f : ℍ → ℂ} {τ : ℍ} : MDifferentiableAt 𝓘(ℂ) 𝓘(ℂ) f τ ↔ DifferentiableAt ℂ (f ∘ ofComplex) ↑τ := by diff --git a/Mathlib/Analysis/Convex/Gauge.lean b/Mathlib/Analysis/Convex/Gauge.lean index 5ecb5e8b2c4cd..f9d037d23877a 100644 --- a/Mathlib/Analysis/Convex/Gauge.lean +++ b/Mathlib/Analysis/Convex/Gauge.lean @@ -41,7 +41,7 @@ open scoped Pointwise Topology NNReal noncomputable section -variable {𝕜 E F : Type*} +variable {𝕜 E : Type*} section AddCommGroup diff --git a/Mathlib/Analysis/Convex/Normed.lean b/Mathlib/Analysis/Convex/Normed.lean index fae3e58b55f18..9a305c1457de0 100644 --- a/Mathlib/Analysis/Convex/Normed.lean +++ b/Mathlib/Analysis/Convex/Normed.lean @@ -25,14 +25,14 @@ We prove the following facts: is bounded. -/ -variable {ι : Type*} {E P : Type*} +variable {E P : Type*} open AffineBasis Module Metric Set open scoped Convex Pointwise Topology section SeminormedAddCommGroup variable [SeminormedAddCommGroup E] [NormedSpace ℝ E] [PseudoMetricSpace P] [NormedAddTorsor E P] -variable {s t : Set E} +variable {s : Set E} /-- The norm on a real normed space is convex on any convex set. See also `Seminorm.convexOn` and `convexOn_univ_norm`. -/ diff --git a/Mathlib/Analysis/Convex/Slope.lean b/Mathlib/Analysis/Convex/Slope.lean index 1ecc6866a18aa..51a20a60734cd 100644 --- a/Mathlib/Analysis/Convex/Slope.lean +++ b/Mathlib/Analysis/Convex/Slope.lean @@ -40,7 +40,7 @@ theorem ConvexOn.slope_mono_adjacent (hf : ConvexOn 𝕜 s f) {x y z : 𝕜} (hx field_simp [a, b, mul_comm (z - x) _] at key ⊢ rw [div_le_div_iff_of_pos_right] · linarith - · nlinarith + · positivity /-- If `f : 𝕜 → 𝕜` is concave, then for any three points `x < y < z` the slope of the secant line of `f` on `[x, y]` is greater than the slope of the secant line of `f` on `[y, z]`. -/ @@ -73,7 +73,7 @@ theorem StrictConvexOn.slope_strict_mono_adjacent (hf : StrictConvexOn 𝕜 s f) field_simp [mul_comm (z - x) _] at key ⊢ rw [div_lt_div_iff_of_pos_right] · linarith - · nlinarith + · positivity /-- If `f : 𝕜 → 𝕜` is strictly concave, then for any three points `x < y < z` the slope of the secant line of `f` on `[x, y]` is strictly greater than the slope of the secant line of `f` on diff --git a/Mathlib/Analysis/Convex/StoneSeparation.lean b/Mathlib/Analysis/Convex/StoneSeparation.lean index 76a95705677f6..5a52d98fda2ea 100644 --- a/Mathlib/Analysis/Convex/StoneSeparation.lean +++ b/Mathlib/Analysis/Convex/StoneSeparation.lean @@ -67,8 +67,8 @@ theorem not_disjoint_segment_convexHull_triple {p q u v x y z : E} (hz : z ∈ s ((az * av * bu) • p + ((bz * au * bv) • q + (au * av) • (az • x + bz • y))) · module congr 3 - simp only [w, z, smul_add, List.foldr, Matrix.cons_val_succ', Fin.mk_one, - Matrix.cons_val_one, Matrix.head_cons, add_zero] + simp only [smul_add, List.foldr, Fin.reduceFinMk, id_eq, Fin.isValue, Matrix.cons_val_two, + Nat.succ_eq_add_one, Nat.reduceAdd, Matrix.tail_cons, Matrix.head_cons, add_zero, w, z] /-- **Stone's Separation Theorem** -/ theorem exists_convex_convex_compl_subset (hs : Convex 𝕜 s) (ht : Convex 𝕜 t) (hst : Disjoint s t) : diff --git a/Mathlib/Analysis/Convex/Topology.lean b/Mathlib/Analysis/Convex/Topology.lean index a38bd1386b8ea..86c3bddbec48e 100644 --- a/Mathlib/Analysis/Convex/Topology.lean +++ b/Mathlib/Analysis/Convex/Topology.lean @@ -360,8 +360,8 @@ theorem Convex.closure_subset_image_homothety_interior_of_one_lt {s : Set E} (hs refine ⟨homothety x t⁻¹ y, hs.openSegment_interior_closure_subset_interior hx hy ?_, (AffineEquiv.homothetyUnitsMulHom x (Units.mk0 t hne)).apply_symm_apply y⟩ - rw [openSegment_eq_image_lineMap, ← inv_one, ← inv_Ioi (zero_lt_one' ℝ), ← image_inv, image_image, - homothety_eq_lineMap] + rw [openSegment_eq_image_lineMap, ← inv_one, ← inv_Ioi₀ (zero_lt_one' ℝ), ← image_inv, + image_image, homothety_eq_lineMap] exact mem_image_of_mem _ ht /-- If we dilate a convex set about a point in its interior by a scale `t > 1`, the interior of diff --git a/Mathlib/Analysis/Convex/Uniform.lean b/Mathlib/Analysis/Convex/Uniform.lean index cbea3a0fbb080..5c0511976660c 100644 --- a/Mathlib/Analysis/Convex/Uniform.lean +++ b/Mathlib/Analysis/Convex/Uniform.lean @@ -96,16 +96,7 @@ theorem exists_forall_closed_ball_dist_add_le_two_sub (hε : 0 < ε) : _ ≤ 2 - δ + δ' + δ' := (add_le_add_three (h (h₁ _ hx') (h₁ _ hy') hxy') (h₂ _ hx hx'.le) (h₂ _ hy hy'.le)) _ ≤ 2 - δ' := by - dsimp only [δ'] - rw [← le_sub_iff_add_le, ← le_sub_iff_add_le, sub_sub, sub_sub] - refine sub_le_sub_left ?_ _ - ring_nf - rw [← mul_div_cancel₀ δ three_ne_zero] - norm_num - -- Porting note: these three extra lines needed to make `exact` work - have : 3 * (δ / 3) * (1 / 3) = δ / 3 := by linarith - rw [this, mul_comm] - gcongr + suffices δ' ≤ δ / 3 by linarith exact min_le_of_right_le <| min_le_right _ _ theorem exists_forall_closed_ball_dist_add_le_two_mul_sub (hε : 0 < ε) (r : ℝ) : diff --git a/Mathlib/Analysis/Convolution.lean b/Mathlib/Analysis/Convolution.lean index e3a80a3cd256e..f2e6fd1a550aa 100644 --- a/Mathlib/Analysis/Convolution.lean +++ b/Mathlib/Analysis/Convolution.lean @@ -1179,17 +1179,18 @@ theorem contDiffOn_convolution_right_with_param_aux {G : Type uP} {E' : Type uP} come from the same universe). -/ induction n using ENat.nat_induction generalizing g E' F with | h0 => - rw [contDiffOn_zero] at hg ⊢ + rw [WithTop.coe_zero, contDiffOn_zero] at hg ⊢ exact continuousOn_convolution_right_with_param L hk hgs hf hg | hsuc n ih => + simp only [Nat.succ_eq_add_one, Nat.cast_add, Nat.cast_one, WithTop.coe_add, + WithTop.coe_natCast, WithTop.coe_one] at hg ⊢ let f' : P → G → P × G →L[𝕜] F := fun p a => (f ⋆[L.precompR (P × G), μ] fun x : G => fderiv 𝕜 (uncurry g) (p, x)) a have A : ∀ q₀ : P × G, q₀.1 ∈ s → HasFDerivAt (fun q : P × G => (f ⋆[L, μ] g q.1) q.2) (f' q₀.1 q₀.2) q₀ := hasFDerivAt_convolution_right_with_param L hs hk hgs hf hg.one_of_succ - rw [show ((n + 1 : ℕ) : ℕ∞) = n + 1 from rfl, - contDiffOn_succ_iff_fderiv_of_isOpen (hs.prod (@isOpen_univ G _))] at hg ⊢ - constructor + rw [contDiffOn_succ_iff_fderiv_of_isOpen (hs.prod (@isOpen_univ G _))] at hg ⊢ + refine ⟨?_, ?_⟩ · rintro ⟨p, x⟩ ⟨hp, -⟩ exact (A (p, x) hp).differentiableAt.differentiableWithinAt · suffices H : ContDiffOn 𝕜 n (↿f') (s ×ˢ univ) by diff --git a/Mathlib/Analysis/Distribution/AEEqOfIntegralContDiff.lean b/Mathlib/Analysis/Distribution/AEEqOfIntegralContDiff.lean index fb4a816b271bc..8aa816c388f41 100644 --- a/Mathlib/Analysis/Distribution/AEEqOfIntegralContDiff.lean +++ b/Mathlib/Analysis/Distribution/AEEqOfIntegralContDiff.lean @@ -24,7 +24,7 @@ as `ae_eq_zero_of_integral_smooth_smul_eq_zero` and `ae_eq_of_integral_smooth_sm open MeasureTheory Filter Metric Function Set TopologicalSpace -open scoped Topology Manifold +open scoped Topology Manifold ContDiff variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] [FiniteDimensional ℝ E] {F : Type*} [NormedAddCommGroup F] [NormedSpace ℝ F] [CompleteSpace F] @@ -40,7 +40,7 @@ variable {H : Type*} [TopologicalSpace H] (I : ModelWithCorners ℝ E H) when multiplied by any smooth compactly supported function, then `f` vanishes almost everywhere. -/ theorem ae_eq_zero_of_integral_smooth_smul_eq_zero [SigmaCompactSpace M] (hf : LocallyIntegrable f μ) - (h : ∀ g : M → ℝ, Smooth I 𝓘(ℝ) g → HasCompactSupport g → ∫ x, g x • f x ∂μ = 0) : + (h : ∀ g : M → ℝ, ContMDiff I 𝓘(ℝ) ⊤ g → HasCompactSupport g → ∫ x, g x • f x ∂μ = 0) : ∀ᵐ x ∂μ, f x = 0 := by -- record topological properties of `M` have := I.locallyCompactSpace @@ -60,7 +60,7 @@ theorem ae_eq_zero_of_integral_smooth_smul_eq_zero [SigmaCompactSpace M] let v : ℕ → Set M := fun n ↦ thickening (u n) s obtain ⟨K, K_compact, vK⟩ : ∃ K, IsCompact K ∧ ∀ n, v n ⊆ K := ⟨_, hδ, fun n ↦ thickening_subset_cthickening_of_le (u_pos n).2.le _⟩ - have : ∀ n, ∃ (g : M → ℝ), support g = v n ∧ Smooth I 𝓘(ℝ) g ∧ Set.range g ⊆ Set.Icc 0 1 + have : ∀ n, ∃ (g : M → ℝ), support g = v n ∧ ContMDiff I 𝓘(ℝ) ⊤ g ∧ Set.range g ⊆ Set.Icc 0 1 ∧ ∀ x ∈ s, g x = 1 := by intro n rcases exists_msmooth_support_eq_eq_one_iff I isOpen_thickening hs.isClosed @@ -121,7 +121,7 @@ instance (U : Opens M) : BorelSpace U := inferInstanceAs (BorelSpace (U : Set M) nonrec theorem IsOpen.ae_eq_zero_of_integral_smooth_smul_eq_zero' {U : Set M} (hU : IsOpen U) (hSig : IsSigmaCompact U) (hf : LocallyIntegrableOn f U μ) (h : ∀ g : M → ℝ, - Smooth I 𝓘(ℝ) g → HasCompactSupport g → tsupport g ⊆ U → ∫ x, g x • f x ∂μ = 0) : + ContMDiff I 𝓘(ℝ) ⊤ g → HasCompactSupport g → tsupport g ⊆ U → ∫ x, g x • f x ∂μ = 0) : ∀ᵐ x ∂μ, x ∈ U → f x = 0 := by have meas_U := hU.measurableSet rw [← ae_restrict_iff' meas_U, ae_restrict_iff_subtype meas_U] @@ -146,7 +146,7 @@ variable [SigmaCompactSpace M] theorem IsOpen.ae_eq_zero_of_integral_smooth_smul_eq_zero {U : Set M} (hU : IsOpen U) (hf : LocallyIntegrableOn f U μ) (h : ∀ g : M → ℝ, - Smooth I 𝓘(ℝ) g → HasCompactSupport g → tsupport g ⊆ U → ∫ x, g x • f x ∂μ = 0) : + ContMDiff I 𝓘(ℝ) ⊤ g → HasCompactSupport g → tsupport g ⊆ U → ∫ x, g x • f x ∂μ = 0) : ∀ᵐ x ∂μ, x ∈ U → f x = 0 := haveI := I.locallyCompactSpace haveI := ChartedSpace.locallyCompactSpace H M @@ -160,7 +160,7 @@ theorem IsOpen.ae_eq_zero_of_integral_smooth_smul_eq_zero {U : Set M} (hU : IsOp when multiplied by any smooth compactly supported function, then they coincide almost everywhere. -/ theorem ae_eq_of_integral_smooth_smul_eq (hf : LocallyIntegrable f μ) (hf' : LocallyIntegrable f' μ) (h : ∀ (g : M → ℝ), - Smooth I 𝓘(ℝ) g → HasCompactSupport g → ∫ x, g x • f x ∂μ = ∫ x, g x • f' x ∂μ) : + ContMDiff I 𝓘(ℝ) ⊤ g → HasCompactSupport g → ∫ x, g x • f x ∂μ = ∫ x, g x • f' x ∂μ) : ∀ᵐ x ∂μ, f x = f' x := by have : ∀ᵐ x ∂μ, (f - f') x = 0 := by apply ae_eq_zero_of_integral_smooth_smul_eq_zero I (hf.sub hf') @@ -182,7 +182,7 @@ variable [MeasurableSpace E] [BorelSpace E] {f f' : E → F} {μ : Measure E} /-- If a locally integrable function `f` on a finite-dimensional real vector space has zero integral when multiplied by any smooth compactly supported function, then `f` vanishes almost everywhere. -/ theorem ae_eq_zero_of_integral_contDiff_smul_eq_zero (hf : LocallyIntegrable f μ) - (h : ∀ (g : E → ℝ), ContDiff ℝ ⊤ g → HasCompactSupport g → ∫ x, g x • f x ∂μ = 0) : + (h : ∀ (g : E → ℝ), ContDiff ℝ ∞ g → HasCompactSupport g → ∫ x, g x • f x ∂μ = 0) : ∀ᵐ x ∂μ, f x = 0 := ae_eq_zero_of_integral_smooth_smul_eq_zero 𝓘(ℝ, E) hf (fun g g_diff g_supp ↦ h g g_diff.contDiff g_supp) @@ -192,7 +192,7 @@ integral when multiplied by any smooth compactly supported function, then they c everywhere. -/ theorem ae_eq_of_integral_contDiff_smul_eq (hf : LocallyIntegrable f μ) (hf' : LocallyIntegrable f' μ) (h : ∀ (g : E → ℝ), - ContDiff ℝ ⊤ g → HasCompactSupport g → ∫ x, g x • f x ∂μ = ∫ x, g x • f' x ∂μ) : + ContDiff ℝ ∞ g → HasCompactSupport g → ∫ x, g x • f x ∂μ = ∫ x, g x • f' x ∂μ) : ∀ᵐ x ∂μ, f x = f' x := ae_eq_of_integral_smooth_smul_eq 𝓘(ℝ, E) hf hf' (fun g g_diff g_supp ↦ h g g_diff.contDiff g_supp) @@ -202,7 +202,7 @@ theorem ae_eq_of_integral_contDiff_smul_eq in an open set `U`, then `f` vanishes almost everywhere in `U`. -/ theorem IsOpen.ae_eq_zero_of_integral_contDiff_smul_eq_zero {U : Set E} (hU : IsOpen U) (hf : LocallyIntegrableOn f U μ) - (h : ∀ (g : E → ℝ), ContDiff ℝ ⊤ g → HasCompactSupport g → tsupport g ⊆ U → + (h : ∀ (g : E → ℝ), ContDiff ℝ ∞ g → HasCompactSupport g → tsupport g ⊆ U → ∫ x, g x • f x ∂μ = 0) : ∀ᵐ x ∂μ, x ∈ U → f x = 0 := hU.ae_eq_zero_of_integral_smooth_smul_eq_zero 𝓘(ℝ, E) hf diff --git a/Mathlib/Analysis/Distribution/SchwartzSpace.lean b/Mathlib/Analysis/Distribution/SchwartzSpace.lean index 6debdf4d51000..b1f19e08a826b 100644 --- a/Mathlib/Analysis/Distribution/SchwartzSpace.lean +++ b/Mathlib/Analysis/Distribution/SchwartzSpace.lean @@ -61,7 +61,7 @@ Schwartz space, tempered distributions noncomputable section -open scoped Nat NNReal +open scoped Nat NNReal ContDiff variable {𝕜 𝕜' D E F G V : Type*} variable [NormedAddCommGroup E] [NormedSpace ℝ E] @@ -72,7 +72,7 @@ variable (E F) any power of `‖x‖`. -/ structure SchwartzMap where toFun : E → F - smooth' : ContDiff ℝ ⊤ toFun + smooth' : ContDiff ℝ ∞ toFun decay' : ∀ k n : ℕ, ∃ C : ℝ, ∀ x, ‖x‖ ^ k * ‖iteratedFDeriv ℝ n toFun x‖ ≤ C /-- A function is a Schwartz function if it is smooth and all derivatives decay faster than @@ -98,7 +98,7 @@ theorem decay (f : 𝓢(E, F)) (k n : ℕ) : /-- Every Schwartz function is smooth. -/ theorem smooth (f : 𝓢(E, F)) (n : ℕ∞) : ContDiff ℝ n f := - f.smooth'.of_le le_top + f.smooth'.of_le (mod_cast le_top) /-- Every Schwartz function is continuous. -/ @[continuity] @@ -521,7 +521,7 @@ section TemperateGrowth /-- A function is called of temperate growth if it is smooth and all iterated derivatives are polynomially bounded. -/ def _root_.Function.HasTemperateGrowth (f : E → F) : Prop := - ContDiff ℝ ⊤ f ∧ ∀ n : ℕ, ∃ (k : ℕ) (C : ℝ), ∀ x, ‖iteratedFDeriv ℝ n f x‖ ≤ C * (1 + ‖x‖) ^ k + ContDiff ℝ ∞ f ∧ ∀ n : ℕ, ∃ (k : ℕ) (C : ℝ), ∀ x, ‖iteratedFDeriv ℝ n f x‖ ≤ C * (1 + ‖x‖) ^ k theorem _root_.Function.HasTemperateGrowth.norm_iteratedFDeriv_le_uniform_aux {f : E → F} (hf_temperate : f.HasTemperateGrowth) (n : ℕ) : @@ -680,7 +680,7 @@ variable {σ : 𝕜 →+* 𝕜'} Note: This is a helper definition for `mkCLM`. -/ def mkLM (A : (D → E) → F → G) (hadd : ∀ (f g : 𝓢(D, E)) (x), A (f + g) x = A f x + A g x) (hsmul : ∀ (a : 𝕜) (f : 𝓢(D, E)) (x), A (a • f) x = σ a • A f x) - (hsmooth : ∀ f : 𝓢(D, E), ContDiff ℝ ⊤ (A f)) + (hsmooth : ∀ f : 𝓢(D, E), ContDiff ℝ ∞ (A f)) (hbound : ∀ n : ℕ × ℕ, ∃ (s : Finset (ℕ × ℕ)) (C : ℝ), 0 ≤ C ∧ ∀ (f : 𝓢(D, E)) (x : F), ‖x‖ ^ n.fst * ‖iteratedFDeriv ℝ n.snd (A f) x‖ ≤ C * s.sup (schwartzSeminormFamily 𝕜 D E) f) : 𝓢(D, E) →ₛₗ[σ] 𝓢(F, G) where @@ -700,7 +700,7 @@ For an example of using this definition, see `fderivCLM`. -/ def mkCLM [RingHomIsometric σ] (A : (D → E) → F → G) (hadd : ∀ (f g : 𝓢(D, E)) (x), A (f + g) x = A f x + A g x) (hsmul : ∀ (a : 𝕜) (f : 𝓢(D, E)) (x), A (a • f) x = σ a • A f x) - (hsmooth : ∀ f : 𝓢(D, E), ContDiff ℝ ⊤ (A f)) + (hsmooth : ∀ f : 𝓢(D, E), ContDiff ℝ ∞ (A f)) (hbound : ∀ n : ℕ × ℕ, ∃ (s : Finset (ℕ × ℕ)) (C : ℝ), 0 ≤ C ∧ ∀ (f : 𝓢(D, E)) (x : F), ‖x‖ ^ n.fst * ‖iteratedFDeriv ℝ n.snd (A f) x‖ ≤ C * s.sup (schwartzSeminormFamily 𝕜 D E) f) : 𝓢(D, E) →SL[σ] 𝓢(F, G) where @@ -740,19 +740,16 @@ variable [NormedField 𝕜] [NormedSpace 𝕜 F] [SMulCommClass ℝ 𝕜 F] /-- The map applying a vector to Hom-valued Schwartz function as a continuous linear map. -/ protected def evalCLM (m : E) : 𝓢(E, E →L[ℝ] F) →L[𝕜] 𝓢(E, F) := mkCLM (fun f x => f x m) (fun _ _ _ => rfl) (fun _ _ _ => rfl) - (fun f => ContDiff.clm_apply f.2 contDiff_const) - (by - rintro ⟨k, n⟩ - use {(k, n)}, ‖m‖, norm_nonneg _ - intro f x - refine - le_trans - (mul_le_mul_of_nonneg_left (norm_iteratedFDeriv_clm_apply_const f.2 le_top) - (by positivity)) - ?_ - move_mul [‖m‖] - gcongr ?_ * ‖m‖ - simp only [Finset.sup_singleton, schwartzSeminormFamily_apply, le_seminorm]) + (fun f => ContDiff.clm_apply f.2 contDiff_const) <| by + rintro ⟨k, n⟩ + use {(k, n)}, ‖m‖, norm_nonneg _ + intro f x + refine le_trans + (mul_le_mul_of_nonneg_left (norm_iteratedFDeriv_clm_apply_const f.2 (mod_cast le_top)) + (by positivity)) ?_ + move_mul [‖m‖] + gcongr ?_ * ‖m‖ + simp only [Finset.sup_singleton, schwartzSeminormFamily_apply, le_seminorm] end EvalCLM @@ -764,53 +761,52 @@ variable [NormedAddCommGroup G] [NormedSpace ℝ G] /-- The map `f ↦ (x ↦ B (f x) (g x))` as a continuous `𝕜`-linear map on Schwartz space, where `B` is a continuous `𝕜`-linear map and `g` is a function of temperate growth. -/ def bilinLeftCLM (B : E →L[ℝ] F →L[ℝ] G) {g : D → F} (hg : g.HasTemperateGrowth) : - 𝓢(D, E) →L[ℝ] 𝓢(D, G) := + 𝓢(D, E) →L[ℝ] 𝓢(D, G) := by -- Todo (after port): generalize to `B : E →L[𝕜] F →L[𝕜] G` and `𝕜`-linear - mkCLM - (fun f x => B (f x) (g x)) + refine mkCLM (fun f x => B (f x) (g x)) (fun _ _ _ => by simp only [map_add, add_left_inj, Pi.add_apply, eq_self_iff_true, ContinuousLinearMap.add_apply]) (fun _ _ _ => by simp only [smul_apply, map_smul, ContinuousLinearMap.coe_smul', Pi.smul_apply, RingHom.id_apply]) - (fun f => (B.isBoundedBilinearMap.contDiff.restrict_scalars ℝ).comp (f.smooth'.prod hg.1)) - (by - rintro ⟨k, n⟩ - rcases hg.norm_iteratedFDeriv_le_uniform_aux n with ⟨l, C, hC, hgrowth⟩ - use - Finset.Iic (l + k, n), ‖B‖ * ((n : ℝ) + (1 : ℝ)) * n.choose (n / 2) * (C * 2 ^ (l + k)), - by positivity - intro f x - have hxk : 0 ≤ ‖x‖ ^ k := by positivity - have hnorm_mul := - ContinuousLinearMap.norm_iteratedFDeriv_le_of_bilinear B f.smooth' hg.1 x (n := n) le_top - refine le_trans (mul_le_mul_of_nonneg_left hnorm_mul hxk) ?_ - move_mul [← ‖B‖] - simp_rw [mul_assoc ‖B‖] - gcongr _ * ?_ - rw [Finset.mul_sum] - have : (∑ _x ∈ Finset.range (n + 1), (1 : ℝ)) = n + 1 := by simp - simp_rw [mul_assoc ((n : ℝ) + 1)] - rw [← this, Finset.sum_mul] - refine Finset.sum_le_sum fun i hi => ?_ - simp only [one_mul] - move_mul [(Nat.choose n i : ℝ), (Nat.choose n (n / 2) : ℝ)] - gcongr ?_ * ?_ - swap - · norm_cast - exact i.choose_le_middle n - specialize hgrowth (n - i) (by simp only [tsub_le_self]) x - refine le_trans (mul_le_mul_of_nonneg_left hgrowth (by positivity)) ?_ - move_mul [C] - gcongr ?_ * C - rw [Finset.mem_range_succ_iff] at hi - change i ≤ (l + k, n).snd at hi - refine le_trans ?_ (one_add_le_sup_seminorm_apply le_rfl hi f x) - rw [pow_add] - move_mul [(1 + ‖x‖) ^ l] - gcongr - simp) + (fun f => (B.isBoundedBilinearMap.contDiff.restrict_scalars ℝ).comp (f.smooth'.prod hg.1)) ?_ + rintro ⟨k, n⟩ + rcases hg.norm_iteratedFDeriv_le_uniform_aux n with ⟨l, C, hC, hgrowth⟩ + use + Finset.Iic (l + k, n), ‖B‖ * ((n : ℝ) + (1 : ℝ)) * n.choose (n / 2) * (C * 2 ^ (l + k)), + by positivity + intro f x + have hxk : 0 ≤ ‖x‖ ^ k := by positivity + have hnorm_mul := + ContinuousLinearMap.norm_iteratedFDeriv_le_of_bilinear B f.smooth' hg.1 x (n := n) + (mod_cast le_top) + refine le_trans (mul_le_mul_of_nonneg_left hnorm_mul hxk) ?_ + move_mul [← ‖B‖] + simp_rw [mul_assoc ‖B‖] + gcongr _ * ?_ + rw [Finset.mul_sum] + have : (∑ _x ∈ Finset.range (n + 1), (1 : ℝ)) = n + 1 := by simp + simp_rw [mul_assoc ((n : ℝ) + 1)] + rw [← this, Finset.sum_mul] + refine Finset.sum_le_sum fun i hi => ?_ + simp only [one_mul] + move_mul [(Nat.choose n i : ℝ), (Nat.choose n (n / 2) : ℝ)] + gcongr ?_ * ?_ + swap + · norm_cast + exact i.choose_le_middle n + specialize hgrowth (n - i) (by simp only [tsub_le_self]) x + refine le_trans (mul_le_mul_of_nonneg_left hgrowth (by positivity)) ?_ + move_mul [C] + gcongr ?_ * C + rw [Finset.mem_range_succ_iff] at hi + change i ≤ (l + k, n).snd at hi + refine le_trans ?_ (one_add_le_sup_seminorm_apply le_rfl hi f x) + rw [pow_add] + move_mul [(1 + ‖x‖) ^ l] + gcongr + simp end Multiplication @@ -824,68 +820,67 @@ variable [NormedSpace 𝕜 F] [SMulCommClass ℝ 𝕜 F] /-- Composition with a function on the right is a continuous linear map on Schwartz space provided that the function is temperate and growths polynomially near infinity. -/ def compCLM {g : D → E} (hg : g.HasTemperateGrowth) - (hg_upper : ∃ (k : ℕ) (C : ℝ), ∀ x, ‖x‖ ≤ C * (1 + ‖g x‖) ^ k) : 𝓢(E, F) →L[𝕜] 𝓢(D, F) := - mkCLM (fun f x => f (g x)) + (hg_upper : ∃ (k : ℕ) (C : ℝ), ∀ x, ‖x‖ ≤ C * (1 + ‖g x‖) ^ k) : 𝓢(E, F) →L[𝕜] 𝓢(D, F) := by + refine mkCLM (fun f x => f (g x)) (fun _ _ _ => by simp only [add_left_inj, Pi.add_apply, eq_self_iff_true]) (fun _ _ _ => rfl) - (fun f => f.smooth'.comp hg.1) - (by - rintro ⟨k, n⟩ - rcases hg.norm_iteratedFDeriv_le_uniform_aux n with ⟨l, C, hC, hgrowth⟩ - rcases hg_upper with ⟨kg, Cg, hg_upper'⟩ - have hCg : 1 ≤ 1 + Cg := by - refine le_add_of_nonneg_right ?_ - specialize hg_upper' 0 - rw [norm_zero] at hg_upper' - exact nonneg_of_mul_nonneg_left hg_upper' (by positivity) - let k' := kg * (k + l * n) - use Finset.Iic (k', n), (1 + Cg) ^ (k + l * n) * ((C + 1) ^ n * n ! * 2 ^ k'), by positivity - intro f x - let seminorm_f := ((Finset.Iic (k', n)).sup (schwartzSeminormFamily 𝕜 _ _)) f - have hg_upper'' : (1 + ‖x‖) ^ (k + l * n) ≤ (1 + Cg) ^ (k + l * n) * (1 + ‖g x‖) ^ k' := by - rw [pow_mul, ← mul_pow] - gcongr - rw [add_mul] - refine add_le_add ?_ (hg_upper' x) - nth_rw 1 [← one_mul (1 : ℝ)] - gcongr - apply one_le_pow₀ - simp only [le_add_iff_nonneg_right, norm_nonneg] - have hbound : - ∀ i, i ≤ n → ‖iteratedFDeriv ℝ i f (g x)‖ ≤ 2 ^ k' * seminorm_f / (1 + ‖g x‖) ^ k' := by - intro i hi - have hpos : 0 < (1 + ‖g x‖) ^ k' := by positivity - 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 → - ‖iteratedFDeriv ℝ N g x‖ ≤ ((C + 1) * (1 + ‖x‖) ^ l) ^ N := by - intro N hN₁ hN₂ - refine (hgrowth N hN₂ x).trans ?_ - rw [mul_pow] - have hN₁' := (lt_of_lt_of_le zero_lt_one hN₁).ne' - gcongr - · exact le_trans (by simp [hC]) (le_self_pow₀ (by simp [hC]) hN₁') - · refine le_self_pow₀ (one_le_pow₀ ?_) hN₁' - simp only [le_add_iff_nonneg_right, norm_nonneg] - have := norm_iteratedFDeriv_comp_le f.smooth' hg.1 le_top x hbound hgrowth' - have hxk : ‖x‖ ^ k ≤ (1 + ‖x‖) ^ k := - pow_le_pow_left₀ (norm_nonneg _) (by simp only [zero_le_one, le_add_iff_nonneg_left]) _ - refine le_trans (mul_le_mul hxk this (by positivity) (by positivity)) ?_ - have rearrange : - (1 + ‖x‖) ^ k * - (n ! * (2 ^ k' * seminorm_f / (1 + ‖g x‖) ^ k') * ((C + 1) * (1 + ‖x‖) ^ l) ^ n) = - (1 + ‖x‖) ^ (k + l * n) / (1 + ‖g x‖) ^ k' * - ((C + 1) ^ n * n ! * 2 ^ k' * seminorm_f) := by - rw [mul_pow, pow_add, ← pow_mul] - ring - rw [rearrange] - have hgxk' : 0 < (1 + ‖g x‖) ^ k' := by positivity - 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 - refine le_trans (mul_le_mul_of_nonneg_right hg_upper'' hpos) ?_ - rw [← mul_assoc]) + (fun f => f.smooth'.comp hg.1) ?_ + rintro ⟨k, n⟩ + rcases hg.norm_iteratedFDeriv_le_uniform_aux n with ⟨l, C, hC, hgrowth⟩ + rcases hg_upper with ⟨kg, Cg, hg_upper'⟩ + have hCg : 1 ≤ 1 + Cg := by + refine le_add_of_nonneg_right ?_ + specialize hg_upper' 0 + rw [norm_zero] at hg_upper' + exact nonneg_of_mul_nonneg_left hg_upper' (by positivity) + let k' := kg * (k + l * n) + use Finset.Iic (k', n), (1 + Cg) ^ (k + l * n) * ((C + 1) ^ n * n ! * 2 ^ k'), by positivity + intro f x + let seminorm_f := ((Finset.Iic (k', n)).sup (schwartzSeminormFamily 𝕜 _ _)) f + have hg_upper'' : (1 + ‖x‖) ^ (k + l * n) ≤ (1 + Cg) ^ (k + l * n) * (1 + ‖g x‖) ^ k' := by + rw [pow_mul, ← mul_pow] + gcongr + rw [add_mul] + refine add_le_add ?_ (hg_upper' x) + nth_rw 1 [← one_mul (1 : ℝ)] + gcongr + apply one_le_pow₀ + simp only [le_add_iff_nonneg_right, norm_nonneg] + have hbound : + ∀ i, i ≤ n → ‖iteratedFDeriv ℝ i f (g x)‖ ≤ 2 ^ k' * seminorm_f / (1 + ‖g x‖) ^ k' := by + intro i hi + have hpos : 0 < (1 + ‖g x‖) ^ k' := by positivity + 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 → + ‖iteratedFDeriv ℝ N g x‖ ≤ ((C + 1) * (1 + ‖x‖) ^ l) ^ N := by + intro N hN₁ hN₂ + refine (hgrowth N hN₂ x).trans ?_ + rw [mul_pow] + have hN₁' := (lt_of_lt_of_le zero_lt_one hN₁).ne' + gcongr + · exact le_trans (by simp [hC]) (le_self_pow₀ (by simp [hC]) hN₁') + · refine le_self_pow₀ (one_le_pow₀ ?_) hN₁' + simp only [le_add_iff_nonneg_right, norm_nonneg] + have := norm_iteratedFDeriv_comp_le f.smooth' hg.1 (mod_cast le_top) x hbound hgrowth' + have hxk : ‖x‖ ^ k ≤ (1 + ‖x‖) ^ k := + pow_le_pow_left₀ (norm_nonneg _) (by simp only [zero_le_one, le_add_iff_nonneg_left]) _ + refine le_trans (mul_le_mul hxk this (by positivity) (by positivity)) ?_ + have rearrange : + (1 + ‖x‖) ^ k * + (n ! * (2 ^ k' * seminorm_f / (1 + ‖g x‖) ^ k') * ((C + 1) * (1 + ‖x‖) ^ l) ^ n) = + (1 + ‖x‖) ^ (k + l * n) / (1 + ‖g x‖) ^ k' * + ((C + 1) ^ n * n ! * 2 ^ k' * seminorm_f) := by + rw [mul_pow, pow_add, ← pow_mul] + ring + rw [rearrange] + have hgxk' : 0 < (1 + ‖g x‖) ^ k' := by positivity + 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 + refine le_trans (mul_le_mul_of_nonneg_right hg_upper'' hpos) ?_ + rw [← mul_assoc] @[simp] lemma compCLM_apply {g : D → E} (hg : g.HasTemperateGrowth) (hg_upper : ∃ (k : ℕ) (C : ℝ), ∀ x, ‖x‖ ≤ C * (1 + ‖g x‖) ^ k) (f : 𝓢(E, F)) : @@ -1021,7 +1016,8 @@ theorem iteratedPDeriv_eq_iteratedFDeriv {n : ℕ} {m : Fin n → E} {f : 𝓢(E simp only [iteratedPDeriv_succ_left, iteratedFDeriv_succ_apply_left] rw [← fderiv_continuousMultilinear_apply_const_apply] · simp [← ih] - · exact f.smooth'.differentiable_iteratedFDeriv (WithTop.coe_lt_top n) _ + · exact f.smooth'.differentiable_iteratedFDeriv (mod_cast ENat.coe_lt_top n) x + end Derivatives @@ -1056,7 +1052,7 @@ lemma integrable_pow_mul_iteratedFDeriv (f : 𝓢(D, V)) (k n : ℕ) : Integrable (fun x ↦ ‖x‖ ^ k * ‖iteratedFDeriv ℝ n f x‖) μ := integrable_of_le_of_pow_mul_le (norm_iteratedFDeriv_le_seminorm ℝ _ _) (le_seminorm ℝ _ _ _) - ((f.smooth ⊤).continuous_iteratedFDeriv le_top).aestronglyMeasurable + ((f.smooth ⊤).continuous_iteratedFDeriv (mod_cast le_top)).aestronglyMeasurable variable (μ) in lemma integrable_pow_mul (f : 𝓢(D, V)) @@ -1070,25 +1066,22 @@ lemma integrable (f : 𝓢(D, V)) : Integrable f μ := variable (𝕜 μ) in /-- The integral as a continuous linear map from Schwartz space to the codomain. -/ -def integralCLM : 𝓢(D, V) →L[𝕜] V := - mkCLMtoNormedSpace (∫ x, · x ∂μ) - (fun f g ↦ by - exact integral_add f.integrable g.integrable) - (integral_smul · ·) - (by - rcases hμ.exists_integrable with ⟨n, h⟩ - let m := (n, 0) - use Finset.Iic m, 2 ^ n * ∫ x : D, (1 + ‖x‖) ^ (- (n : ℝ)) ∂μ - refine ⟨by positivity, fun f ↦ (norm_integral_le_integral_norm f).trans ?_⟩ - 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] - 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)] - rfl - apply h.mul_const) +def integralCLM : 𝓢(D, V) →L[𝕜] V := by + refine mkCLMtoNormedSpace (∫ x, · x ∂μ) + (fun f g ↦ integral_add f.integrable g.integrable) (integral_smul · ·) ?_ + rcases hμ.exists_integrable with ⟨n, h⟩ + let m := (n, 0) + use Finset.Iic m, 2 ^ n * ∫ x : D, (1 + ‖x‖) ^ (- (n : ℝ)) ∂μ + refine ⟨by positivity, fun f ↦ (norm_integral_le_integral_norm f).trans ?_⟩ + 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] + 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)] + rfl + apply h.mul_const variable (𝕜) in @[simp] @@ -1178,7 +1171,7 @@ instance instZeroAtInftyContinuousMapClass : ZeroAtInftyContinuousMapClass 𝓢( intro x hx rw [div_lt_iff₀ hε] at hx have hxpos : 0 < ‖x‖ := by - rw [norm_pos_iff'] + rw [norm_pos_iff] intro hxzero simp only [hxzero, norm_zero, zero_mul, ← not_le] at hx exact hx (apply_nonneg (SchwartzMap.seminorm ℝ 1 0) f) diff --git a/Mathlib/Analysis/Fourier/FourierTransformDeriv.lean b/Mathlib/Analysis/Fourier/FourierTransformDeriv.lean index 5b882dad07252..0151b54688137 100644 --- a/Mathlib/Analysis/Fourier/FourierTransformDeriv.lean +++ b/Mathlib/Analysis/Fourier/FourierTransformDeriv.lean @@ -81,7 +81,7 @@ noncomputable section open Real Complex MeasureTheory Filter TopologicalSpace -open scoped FourierTransform Topology +open scoped FourierTransform Topology ContDiff -- without this local instance, Lean tries first the instance -- `secondCountableTopologyEither_of_right` (whose priority is 100) and takes a very long time to @@ -310,7 +310,8 @@ lemma _root_.Continuous.fourierPowSMulRight {f : V → E} (hf : Continuous f) (n apply (smulRightL ℝ (fun (_ : Fin n) ↦ W) E).continuous₂.comp₂ _ hf exact Continuous.comp (map_continuous _) (continuous_pi (fun _ ↦ L.continuous)) -lemma _root_.ContDiff.fourierPowSMulRight {f : V → E} {k : ℕ∞} (hf : ContDiff ℝ k f) (n : ℕ) : +lemma _root_.ContDiff.fourierPowSMulRight + {f : V → E} {k : WithTop ℕ∞} (hf : ContDiff ℝ k f) (n : ℕ) : ContDiff ℝ k (fun v ↦ fourierPowSMulRight L f v n) := by simp_rw [fourierPowSMulRight_eq_comp] apply ContDiff.const_smul @@ -335,7 +336,7 @@ set_option maxSynthPendingDepth 2 in /-- The iterated derivative of a function multiplied by `(L v ⬝) ^ n` can be controlled in terms of the iterated derivatives of the initial function. -/ lemma norm_iteratedFDeriv_fourierPowSMulRight - {f : V → E} {K : ℕ∞} {C : ℝ} (hf : ContDiff ℝ K f) {n : ℕ} {k : ℕ} (hk : k ≤ K) + {f : V → E} {K : WithTop ℕ∞} {C : ℝ} (hf : ContDiff ℝ K f) {n : ℕ} {k : ℕ} (hk : k ≤ K) {v : V} (hv : ∀ i ≤ k, ∀ j ≤ n, ‖v‖ ^ j * ‖iteratedFDeriv ℝ i f v‖ ≤ C) : ‖iteratedFDeriv ℝ k (fun v ↦ fourierPowSMulRight L f v n) v‖ ≤ (2 * π) ^ n * (2 * n + 2) ^ k * ‖L‖ ^ n * C := by @@ -552,7 +553,8 @@ theorem fourierIntegral_iteratedFDeriv [FiniteDimensional ℝ V] ← fourierIntegral_continuousLinearMap_apply' J] exact H have h'n : n < N := (Nat.cast_lt.mpr n.lt_succ_self).trans_le hn - rw [fourierIntegral_fderiv _ (h'f n h'n.le) (hf.differentiable_iteratedFDeriv h'n) J] + rw [fourierIntegral_fderiv _ (h'f n h'n.le) + (hf.differentiable_iteratedFDeriv (mod_cast h'n)) J] simp only [ih h'n.le, fourierSMulRight_apply, ContinuousLinearMap.neg_apply, ContinuousLinearMap.flip_apply, neg_smul, smul_neg, neg_neg, smul_apply, fourierPowSMulRight_apply, ← coe_smul (E := E), smul_smul] @@ -583,9 +585,9 @@ theorem fourierPowSMulRight_iteratedFDeriv_fourierIntegral [FiniteDimensional simp only [Finset.mem_product, Finset.mem_range_succ_iff] at hp exact h'f _ _ ((Nat.cast_le.2 hp.1).trans hk) ((Nat.cast_le.2 hp.2).trans hm) apply (I.const_mul ((2 * π) ^ k * (2 * k + 2) ^ m * ‖L‖ ^ k)).mono' - ((hf.fourierPowSMulRight L k).continuous_iteratedFDeriv hm).aestronglyMeasurable + ((hf.fourierPowSMulRight L k).continuous_iteratedFDeriv (mod_cast hm)).aestronglyMeasurable filter_upwards with v - refine norm_iteratedFDeriv_fourierPowSMulRight _ hf hm (fun i hi j hj ↦ ?_) + refine norm_iteratedFDeriv_fourierPowSMulRight _ hf (mod_cast hm) (fun i hi j hj ↦ ?_) apply Finset.single_le_sum (f := fun p ↦ ‖v‖ ^ p.1 * ‖iteratedFDeriv ℝ p.2 f v‖) (a := (j, i)) · intro i _hi positivity @@ -616,7 +618,7 @@ theorem norm_fourierPowSMulRight_iteratedFDeriv_fourierIntegral_le [FiniteDimens · filter_upwards with v using norm_nonneg _ · exact (integrable_finset_sum _ I).const_mul _ · filter_upwards with v - apply norm_iteratedFDeriv_fourierPowSMulRight _ hf hn _ + apply norm_iteratedFDeriv_fourierPowSMulRight _ hf (mod_cast hn) _ intro i hi j hj apply Finset.single_le_sum (f := fun p ↦ ‖v‖ ^ p.1 * ‖iteratedFDeriv ℝ p.2 f v‖) (a := (j, i)) · intro i _hi diff --git a/Mathlib/Analysis/FunctionalSpaces/SobolevInequality.lean b/Mathlib/Analysis/FunctionalSpaces/SobolevInequality.lean index 12f3131cc2e8b..e18e2e98d3690 100644 --- a/Mathlib/Analysis/FunctionalSpaces/SobolevInequality.lean +++ b/Mathlib/Analysis/FunctionalSpaces/SobolevInequality.lean @@ -680,7 +680,10 @@ theorem eLpNorm_le_eLpNorm_fderiv_of_le [FiniteDimensional ℝ F] have hp' : p'⁻¹ = p⁻¹ - (finrank ℝ E : ℝ)⁻¹ := by rw [inv_inv, NNReal.coe_sub] · simp - · gcongr + · #adaptation_note + /-- This should just be `gcongr`, but this is not working as of nightly-2024-11-20. + Possibly related to #19262 (since this proof fails at `with_reducible_and_instances`). -/ + exact inv_anti₀ (by positivity) h2p.le have : (q : ℝ≥0∞) ≤ p' := by have H : (p' : ℝ)⁻¹ ≤ (↑q)⁻¹ := trans hp' hpq norm_cast at H ⊢ @@ -688,7 +691,10 @@ theorem eLpNorm_le_eLpNorm_fderiv_of_le [FiniteDimensional ℝ F] · dsimp have : 0 < p⁻¹ - (finrank ℝ E : ℝ≥0)⁻¹ := by simp only [tsub_pos_iff_lt] - gcongr + #adaptation_note + /-- This should just be `gcongr`, but this is not working as of nightly-2024-11-20. + Possibly related to #19262 (since this proof fails at `with_reducible_and_instances`). -/ + exact inv_strictAnti₀ (by positivity) h2p positivity · positivity set t := (μ s).toNNReal ^ (1 / q - 1 / p' : ℝ) diff --git a/Mathlib/Analysis/InnerProductSpace/Basic.lean b/Mathlib/Analysis/InnerProductSpace/Basic.lean index 4acfe80398b10..6f06b27cb078c 100644 --- a/Mathlib/Analysis/InnerProductSpace/Basic.lean +++ b/Mathlib/Analysis/InnerProductSpace/Basic.lean @@ -1600,9 +1600,7 @@ end ContinuousLinearMap section -variable {ι : Type*} {ι' : Type*} {ι'' : Type*} -variable {E' : Type*} [SeminormedAddCommGroup E'] [InnerProductSpace 𝕜 E'] -variable {E'' : Type*} [SeminormedAddCommGroup E''] [InnerProductSpace 𝕜 E''] +variable {ι : Type*} {ι' : Type*} {E' : Type*} [SeminormedAddCommGroup E'] [InnerProductSpace 𝕜 E'] @[simp] theorem Orthonormal.equiv_refl {v : Basis ι 𝕜 E} (hv : Orthonormal 𝕜 v) : @@ -1683,7 +1681,7 @@ open scoped InnerProductSpace variable [NormedAddCommGroup E] [InnerProductSpace 𝕜 E] variable [NormedAddCommGroup F] [InnerProductSpace ℝ F] -variable {ι : Type*} {ι' : Type*} {ι'' : Type*} +variable {ι : Type*} local notation "⟪" x ", " y "⟫" => @inner 𝕜 _ _ x y @@ -2188,18 +2186,16 @@ local notation "IK" => @RCLike.I 𝕜 _ local postfix:90 "†" => starRingEnd _ -variable {ι : Type*} -variable {G : ι → Type*} [∀ i, NormedAddCommGroup (G i)] [∀ i, InnerProductSpace 𝕜 (G i)] - {V : ∀ i, G i →ₗᵢ[𝕜] E} (hV : OrthogonalFamily 𝕜 G V) [dec_V : ∀ (i) (x : G i), Decidable (x ≠ 0)] +variable {ι : Type*} {G : ι → Type*} /-- An orthogonal family forms an independent family of subspaces; that is, any collection of elements each from a different subspace in the family is linearly independent. In particular, the pairwise intersections of elements of the family are 0. -/ theorem OrthogonalFamily.independent {V : ι → Submodule 𝕜 E} (hV : OrthogonalFamily 𝕜 (fun i => V i) fun i => (V i).subtypeₗᵢ) : - CompleteLattice.Independent V := by + iSupIndep V := by classical - apply CompleteLattice.independent_of_dfinsupp_lsum_injective + apply iSupIndep_of_dfinsupp_lsum_injective refine LinearMap.ker_eq_bot.mp ?_ rw [Submodule.eq_bot_iff] intro v hv diff --git a/Mathlib/Analysis/InnerProductSpace/Positive.lean b/Mathlib/Analysis/InnerProductSpace/Positive.lean index f49a0c4973a85..305ed79703826 100644 --- a/Mathlib/Analysis/InnerProductSpace/Positive.lean +++ b/Mathlib/Analysis/InnerProductSpace/Positive.lean @@ -109,7 +109,7 @@ lemma antilipschitz_of_forall_le_inner_map {H : Type*} [NormedAddCommGroup H] 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 + · 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) diff --git a/Mathlib/Analysis/InnerProductSpace/Projection.lean b/Mathlib/Analysis/InnerProductSpace/Projection.lean index c2ea3c5347107..6be13bb9ce5f1 100644 --- a/Mathlib/Analysis/InnerProductSpace/Projection.lean +++ b/Mathlib/Analysis/InnerProductSpace/Projection.lean @@ -1218,7 +1218,7 @@ theorem OrthogonalFamily.isInternal_iff_of_isComplete [DecidableEq ι] {V : ι (hV : OrthogonalFamily 𝕜 (fun i => V i) fun i => (V i).subtypeₗᵢ) (hc : IsComplete (↑(iSup V) : Set E)) : DirectSum.IsInternal V ↔ (iSup V)ᗮ = ⊥ := by haveI : CompleteSpace (↥(iSup V)) := hc.completeSpace_coe - simp only [DirectSum.isInternal_submodule_iff_independent_and_iSup_eq_top, hV.independent, + simp only [DirectSum.isInternal_submodule_iff_iSupIndep_and_iSup_eq_top, hV.independent, true_and, Submodule.orthogonal_eq_bot_iff] /-- An orthogonal family of subspaces of `E` satisfies `DirectSum.IsInternal` (that is, diff --git a/Mathlib/Analysis/InnerProductSpace/TwoDim.lean b/Mathlib/Analysis/InnerProductSpace/TwoDim.lean index b07b1d09381f7..afdbc274d603b 100644 --- a/Mathlib/Analysis/InnerProductSpace/TwoDim.lean +++ b/Mathlib/Analysis/InnerProductSpace/TwoDim.lean @@ -354,14 +354,16 @@ theorem inner_mul_inner_add_areaForm_mul_areaForm' (a x : E) : apply (o.basisRightAngleRotation a ha).ext intro i fin_cases i - · simp only [Fin.mk_zero, coe_basisRightAngleRotation, Matrix.cons_val_zero, LinearMap.add_apply, - LinearMap.smul_apply, innerₛₗ_apply, real_inner_self_eq_norm_sq, smul_eq_mul, - areaForm_apply_self, mul_zero, add_zero, Real.rpow_two, real_inner_comm] + · simp only [Fin.zero_eta, Fin.isValue, id_eq, coe_basisRightAngleRotation, Nat.succ_eq_add_one, + Nat.reduceAdd, Matrix.cons_val_zero, LinearMap.add_apply, LinearMap.smul_apply, innerₛₗ_apply, + real_inner_self_eq_norm_sq, smul_eq_mul, areaForm_apply_self, mul_zero, add_zero, + real_inner_comm] ring - · simp only [Fin.mk_one, coe_basisRightAngleRotation, Matrix.cons_val_one, Matrix.head_cons, - LinearMap.add_apply, LinearMap.smul_apply, innerₛₗ_apply, inner_rightAngleRotation_right, - areaForm_apply_self, neg_zero, smul_eq_mul, mul_zero, areaForm_rightAngleRotation_right, - real_inner_self_eq_norm_sq, zero_add, Real.rpow_two, mul_neg] + · simp only [Fin.mk_one, Fin.isValue, id_eq, coe_basisRightAngleRotation, Nat.succ_eq_add_one, + Nat.reduceAdd, Matrix.cons_val_one, Matrix.head_cons, LinearMap.add_apply, + LinearMap.smul_apply, innerₛₗ_apply, inner_rightAngleRotation_right, areaForm_apply_self, + neg_zero, smul_eq_mul, mul_zero, areaForm_rightAngleRotation_right, + real_inner_self_eq_norm_sq, zero_add, mul_neg] rw [o.areaForm_swap] ring @@ -381,15 +383,16 @@ theorem inner_mul_areaForm_sub' (a x : E) : ⟪a, x⟫ • ω a - ω a x • inn apply (o.basisRightAngleRotation a ha).ext intro i fin_cases i - · simp only [o.areaForm_swap a x, neg_smul, sub_neg_eq_add, Fin.mk_zero, - coe_basisRightAngleRotation, Matrix.cons_val_zero, LinearMap.add_apply, LinearMap.smul_apply, - areaForm_apply_self, smul_eq_mul, mul_zero, innerₛₗ_apply, real_inner_self_eq_norm_sq, - zero_add, Real.rpow_two] + · simp only [o.areaForm_swap a x, neg_smul, sub_neg_eq_add, Fin.zero_eta, Fin.isValue, id_eq, + coe_basisRightAngleRotation, Nat.succ_eq_add_one, Nat.reduceAdd, Matrix.cons_val_zero, + LinearMap.add_apply, LinearMap.smul_apply, areaForm_apply_self, smul_eq_mul, mul_zero, + innerₛₗ_apply, real_inner_self_eq_norm_sq, zero_add] ring - · simp only [Fin.mk_one, coe_basisRightAngleRotation, Matrix.cons_val_one, Matrix.head_cons, - LinearMap.sub_apply, LinearMap.smul_apply, areaForm_rightAngleRotation_right, - real_inner_self_eq_norm_sq, smul_eq_mul, innerₛₗ_apply, inner_rightAngleRotation_right, - areaForm_apply_self, neg_zero, mul_zero, sub_zero, Real.rpow_two, real_inner_comm] + · simp only [Fin.mk_one, Fin.isValue, id_eq, coe_basisRightAngleRotation, Nat.succ_eq_add_one, + Nat.reduceAdd, Matrix.cons_val_one, Matrix.head_cons, LinearMap.sub_apply, + LinearMap.smul_apply, areaForm_rightAngleRotation_right, real_inner_self_eq_norm_sq, + smul_eq_mul, innerₛₗ_apply, inner_rightAngleRotation_right, areaForm_apply_self, neg_zero, + mul_zero, sub_zero, real_inner_comm] ring /-- For vectors `a x y : E`, the identity `⟪a, x⟫ * ω a y - ω a x * ⟪a, y⟫ = ‖a‖ ^ 2 * ω x y`. -/ diff --git a/Mathlib/Analysis/Normed/Affine/ContinuousAffineMap.lean b/Mathlib/Analysis/Normed/Affine/ContinuousAffineMap.lean index 7491177284cf8..b948db9a803a4 100644 --- a/Mathlib/Analysis/Normed/Affine/ContinuousAffineMap.lean +++ b/Mathlib/Analysis/Normed/Affine/ContinuousAffineMap.lean @@ -175,7 +175,7 @@ noncomputable instance : NormedAddCommGroup (V →ᴬ[𝕜] W) := simp only [norm_eq_zero, coe_const, Function.const_apply] at h₁ rw [h₁] rfl - · rw [norm_eq_zero', contLinear_eq_zero_iff_exists_const] at h₁ + · rw [norm_eq_zero, contLinear_eq_zero_iff_exists_const] at h₁ obtain ⟨q, rfl⟩ := h₁ simp only [norm_le_zero_iff, coe_const, Function.const_apply] at h₂ rw [h₂] diff --git a/Mathlib/Analysis/Normed/Field/Basic.lean b/Mathlib/Analysis/Normed/Field/Basic.lean index a81ab41393a9d..00424d49f8973 100644 --- a/Mathlib/Analysis/Normed/Field/Basic.lean +++ b/Mathlib/Analysis/Normed/Field/Basic.lean @@ -5,10 +5,10 @@ Authors: Patrick Massot, Johannes Hölzl -/ import Mathlib.Algebra.Algebra.NonUnitalSubalgebra import Mathlib.Algebra.Algebra.Subalgebra.Basic +import Mathlib.Algebra.Field.Subfield.Defs +import Mathlib.Algebra.Order.Group.Pointwise.Interval import Mathlib.Analysis.Normed.Group.Constructions import Mathlib.Analysis.Normed.Group.Submodule -import Mathlib.Data.Set.Pointwise.Interval -import Mathlib.Algebra.Field.Subfield.Defs /-! # Normed fields @@ -955,7 +955,7 @@ theorem NormedAddCommGroup.tendsto_atTop' [Nonempty α] [Preorder α] [IsDirecte section RingHomIsometric -variable {R₁ : Type*} {R₂ : Type*} {R₃ : Type*} +variable {R₁ R₂ : Type*} /-- This class states that a ring homomorphism is isometric. This is a sufficient assumption for a continuous semilinear map to be bounded and this is the main use for this typeclass. -/ @@ -965,7 +965,7 @@ class RingHomIsometric [Semiring R₁] [Semiring R₂] [Norm R₁] [Norm R₂] ( attribute [simp] RingHomIsometric.is_iso -variable [SeminormedRing R₁] [SeminormedRing R₂] [SeminormedRing R₃] +variable [SeminormedRing R₁] instance RingHomIsometric.ids : RingHomIsometric (RingHom.id R₁) := ⟨rfl⟩ diff --git a/Mathlib/Analysis/Normed/Field/Lemmas.lean b/Mathlib/Analysis/Normed/Field/Lemmas.lean index e22f72874193c..2943b39e7e097 100644 --- a/Mathlib/Analysis/Normed/Field/Lemmas.lean +++ b/Mathlib/Analysis/Normed/Field/Lemmas.lean @@ -5,7 +5,8 @@ Authors: Patrick Massot, Johannes Hölzl -/ import Mathlib.Algebra.Group.AddChar -import Mathlib.Algebra.Order.Ring.Finset +import Mathlib.Algebra.Group.TypeTags.Finite +import Mathlib.Algebra.Order.GroupWithZero.Finset import Mathlib.Analysis.Normed.Field.Basic import Mathlib.Analysis.Normed.Group.Bounded import Mathlib.Analysis.Normed.Group.Rat @@ -59,7 +60,7 @@ instance Pi.nonUnitalSeminormedRing {π : ι → Type*} [Fintype ι] 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 _ + Finset.sup_mul_le_mul_sup_of_nonneg (fun _ _ => zero_le _) fun _ _ => zero_le _ } end NonUnitalSeminormedRing diff --git a/Mathlib/Analysis/Normed/Group/Basic.lean b/Mathlib/Analysis/Normed/Group/Basic.lean index 4242b77e0dfd6..da9bbaf0e7c48 100644 --- a/Mathlib/Analysis/Normed/Group/Basic.lean +++ b/Mathlib/Analysis/Normed/Group/Basic.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Patrick Massot, Johannes Hölzl, Yaël Dillies -/ import Mathlib.Algebra.CharP.Defs -import Mathlib.Algebra.Group.Subgroup.Basic +import Mathlib.Algebra.Group.Subgroup.Ker import Mathlib.Analysis.Normed.Group.Seminorm import Mathlib.Topology.Metrizable.Uniformity import Mathlib.Topology.Sequences @@ -44,7 +44,7 @@ normed group -/ -variable {𝓕 𝕜 α ι κ E F G : Type*} +variable {𝓕 α ι κ E F G : Type*} open Filter Function Metric Bornology @@ -337,7 +337,7 @@ abbrev GroupNorm.toNormedCommGroup [CommGroup E] (f : GroupNorm E) : NormedCommG section SeminormedGroup variable [SeminormedGroup E] [SeminormedGroup F] [SeminormedGroup G] {s : Set E} - {a a₁ a₂ b b₁ b₂ c : E} {r r₁ r₂ : ℝ} + {a a₁ a₂ b c : E} {r r₁ r₂ : ℝ} @[to_additive] theorem dist_eq_norm_div (a b : E) : dist a b = ‖a / b‖ := @@ -922,20 +922,6 @@ theorem SeminormedCommGroup.mem_closure_iff : a ∈ closure s ↔ ∀ ε, 0 < ε → ∃ b ∈ s, ‖a / b‖ < ε := by simp [Metric.mem_closure_iff, dist_eq_norm_div] -@[to_additive norm_le_zero_iff'] -theorem norm_le_zero_iff''' [T0Space E] {a : E} : ‖a‖ ≤ 0 ↔ a = 1 := by - letI : NormedGroup E := - { ‹SeminormedGroup E› with toMetricSpace := MetricSpace.ofT0PseudoMetricSpace E } - rw [← dist_one_right, dist_le_zero] - -@[to_additive norm_eq_zero'] -theorem norm_eq_zero''' [T0Space E] {a : E} : ‖a‖ = 0 ↔ a = 1 := - (norm_nonneg' a).le_iff_eq.symm.trans norm_le_zero_iff''' - -@[to_additive norm_pos_iff'] -theorem norm_pos_iff''' [T0Space E] {a : E} : 0 < ‖a‖ ↔ a ≠ 1 := by - rw [← not_le, norm_le_zero_iff'''] - @[to_additive] theorem SeminormedGroup.tendstoUniformlyOn_one {f : ι → κ → G} {s : Set κ} {l : Filter ι} : TendstoUniformlyOn f 1 l s ↔ ∀ ε > 0, ∀ᶠ i in l, ∀ x ∈ s, ‖f i x‖ < ε := by @@ -1024,7 +1010,7 @@ end Induced section SeminormedCommGroup -variable [SeminormedCommGroup E] [SeminormedCommGroup F] {a a₁ a₂ b b₁ b₂ : E} {r r₁ r₂ : ℝ} +variable [SeminormedCommGroup E] [SeminormedCommGroup F] {a b : E} {r : ℝ} @[to_additive] theorem dist_inv (x y : E) : dist x⁻¹ y = dist x y⁻¹ := by @@ -1290,26 +1276,28 @@ end SeminormedCommGroup section NormedGroup -variable [NormedGroup E] [NormedGroup F] {a b : E} +variable [NormedGroup E] {a b : E} + +@[to_additive (attr := simp) norm_le_zero_iff] +lemma norm_le_zero_iff' : ‖a‖ ≤ 0 ↔ a = 1 := by rw [← dist_one_right, dist_le_zero] + +@[to_additive (attr := simp) norm_pos_iff] +lemma norm_pos_iff' : 0 < ‖a‖ ↔ a ≠ 1 := by rw [← not_le, norm_le_zero_iff'] @[to_additive (attr := simp) norm_eq_zero] -theorem norm_eq_zero'' : ‖a‖ = 0 ↔ a = 1 := - norm_eq_zero''' +lemma norm_eq_zero' : ‖a‖ = 0 ↔ a = 1 := (norm_nonneg' a).le_iff_eq.symm.trans norm_le_zero_iff' @[to_additive norm_ne_zero_iff] -theorem norm_ne_zero_iff' : ‖a‖ ≠ 0 ↔ a ≠ 1 := - norm_eq_zero''.not +lemma norm_ne_zero_iff' : ‖a‖ ≠ 0 ↔ a ≠ 1 := norm_eq_zero'.not -@[to_additive (attr := simp) norm_pos_iff] -theorem norm_pos_iff'' : 0 < ‖a‖ ↔ a ≠ 1 := - norm_pos_iff''' - -@[to_additive (attr := simp) norm_le_zero_iff] -theorem norm_le_zero_iff'' : ‖a‖ ≤ 0 ↔ a = 1 := - norm_le_zero_iff''' +@[deprecated (since := "2024-11-24")] alias norm_le_zero_iff'' := norm_le_zero_iff' +@[deprecated (since := "2024-11-24")] alias norm_le_zero_iff''' := norm_le_zero_iff' +@[deprecated (since := "2024-11-24")] alias norm_pos_iff'' := norm_pos_iff' +@[deprecated (since := "2024-11-24")] alias norm_eq_zero'' := norm_eq_zero' +@[deprecated (since := "2024-11-24")] alias norm_eq_zero''' := norm_eq_zero' @[to_additive] -theorem norm_div_eq_zero_iff : ‖a / b‖ = 0 ↔ a = b := by rw [norm_eq_zero'', div_eq_one] +theorem norm_div_eq_zero_iff : ‖a / b‖ = 0 ↔ a = b := by rw [norm_eq_zero', div_eq_one] @[to_additive] theorem norm_div_pos_iff : 0 < ‖a / b‖ ↔ a ≠ b := by @@ -1318,7 +1306,7 @@ theorem norm_div_pos_iff : 0 < ‖a / b‖ ↔ a ≠ b := by @[to_additive eq_of_norm_sub_le_zero] theorem eq_of_norm_div_le_zero (h : ‖a / b‖ ≤ 0) : a = b := by - rwa [← div_eq_one, ← norm_le_zero_iff''] + rwa [← div_eq_one, ← norm_le_zero_iff'] alias ⟨eq_of_norm_div_eq_zero, _⟩ := norm_div_eq_zero_iff @@ -1334,7 +1322,7 @@ theorem eq_one_or_nnnorm_pos (a : E) : a = 1 ∨ 0 < ‖a‖₊ := @[to_additive (attr := simp) nnnorm_eq_zero] theorem nnnorm_eq_zero' : ‖a‖₊ = 0 ↔ a = 1 := by - rw [← NNReal.coe_eq_zero, coe_nnnorm', norm_eq_zero''] + rw [← NNReal.coe_eq_zero, coe_nnnorm', norm_eq_zero'] @[to_additive nnnorm_ne_zero_iff] theorem nnnorm_ne_zero_iff' : ‖a‖₊ ≠ 0 ↔ a ≠ 1 := @@ -1346,24 +1334,24 @@ lemma nnnorm_pos' : 0 < ‖a‖₊ ↔ a ≠ 1 := pos_iff_ne_zero.trans nnnorm_n /-- See `tendsto_norm_one` for a version with full neighborhoods. -/ @[to_additive "See `tendsto_norm_zero` for a version with full neighborhoods."] lemma tendsto_norm_one' : Tendsto (norm : E → ℝ) (𝓝[≠] 1) (𝓝[>] 0) := - tendsto_norm_one.inf <| tendsto_principal_principal.2 fun _ hx ↦ norm_pos_iff''.2 hx + tendsto_norm_one.inf <| tendsto_principal_principal.2 fun _ hx ↦ norm_pos_iff'.2 hx @[to_additive] theorem tendsto_norm_div_self_punctured_nhds (a : E) : Tendsto (fun x => ‖x / a‖) (𝓝[≠] a) (𝓝[>] 0) := (tendsto_norm_div_self a).inf <| - tendsto_principal_principal.2 fun _x hx => norm_pos_iff''.2 <| div_ne_one.2 hx + tendsto_principal_principal.2 fun _x hx => norm_pos_iff'.2 <| div_ne_one.2 hx @[to_additive] theorem tendsto_norm_nhdsWithin_one : Tendsto (norm : E → ℝ) (𝓝[≠] 1) (𝓝[>] 0) := - tendsto_norm_one.inf <| tendsto_principal_principal.2 fun _x => norm_pos_iff''.2 + tendsto_norm_one.inf <| tendsto_principal_principal.2 fun _x => norm_pos_iff'.2 variable (E) /-- The norm of a normed group as a group norm. -/ @[to_additive "The norm of a normed group as an additive group norm."] def normGroupNorm : GroupNorm E := - { normGroupSeminorm _ with eq_one_of_map_eq_zero' := fun _ => norm_eq_zero''.1 } + { normGroupSeminorm _ with eq_one_of_map_eq_zero' := fun _ => norm_eq_zero'.1 } @[simp] theorem coe_normGroupNorm : ⇑(normGroupNorm E) = norm := diff --git a/Mathlib/Analysis/Normed/Group/Bounded.lean b/Mathlib/Analysis/Normed/Group/Bounded.lean index bd28a0b52f340..0795999cb5541 100644 --- a/Mathlib/Analysis/Normed/Group/Bounded.lean +++ b/Mathlib/Analysis/Normed/Group/Bounded.lean @@ -6,7 +6,6 @@ Authors: Patrick Massot, Johannes Hölzl, Yaël Dillies import Mathlib.Analysis.Normed.Group.Basic import Mathlib.Topology.MetricSpace.Bounded import Mathlib.Order.Filter.Pointwise -import Mathlib.Order.LiminfLimsup /-! # Boundedness in normed groups @@ -21,11 +20,10 @@ normed group open Filter Metric Bornology open scoped Pointwise Topology -variable {α ι E F G : Type*} +variable {α E F G : Type*} section SeminormedGroup variable [SeminormedGroup E] [SeminormedGroup F] [SeminormedGroup G] {s : Set E} - {a a₁ a₂ b b₁ b₂ : E} {r r₁ r₂ : ℝ} @[to_additive (attr := simp) comap_norm_atTop] lemma comap_norm_atTop' : comap norm atTop = cobounded E := by diff --git a/Mathlib/Analysis/Normed/Group/Constructions.lean b/Mathlib/Analysis/Normed/Group/Constructions.lean index c9ee9cc5d178f..95eb19382e965 100644 --- a/Mathlib/Analysis/Normed/Group/Constructions.lean +++ b/Mathlib/Analysis/Normed/Group/Constructions.lean @@ -103,11 +103,11 @@ variable [Norm E] instance Additive.toNorm : Norm (Additive E) := ‹Norm E› instance Multiplicative.toNorm : Norm (Multiplicative E) := ‹Norm E› -@[simp] lemma norm_toMul (x) : ‖(toMul x : E)‖ = ‖x‖ := rfl +@[simp] lemma norm_toMul (x : Additive E) : ‖(x.toMul : E)‖ = ‖x‖ := rfl @[simp] lemma norm_ofMul (x : E) : ‖ofMul x‖ = ‖x‖ := rfl -@[simp] lemma norm_toAdd (x) : ‖(toAdd x : E)‖ = ‖x‖ := rfl +@[simp] lemma norm_toAdd (x : Multiplicative E) : ‖(x.toAdd : E)‖ = ‖x‖ := rfl @[simp] lemma norm_ofAdd (x : E) : ‖ofAdd x‖ = ‖x‖ := rfl @@ -120,23 +120,23 @@ instance Additive.toNNNorm : NNNorm (Additive E) := ‹NNNorm E› instance Multiplicative.toNNNorm : NNNorm (Multiplicative E) := ‹NNNorm E› -@[simp] lemma nnnorm_toMul (x) : ‖(toMul x : E)‖₊ = ‖x‖₊ := rfl +@[simp] lemma nnnorm_toMul (x : Additive E) : ‖(x.toMul : E)‖₊ = ‖x‖₊ := rfl @[simp] lemma nnnorm_ofMul (x : E) : ‖ofMul x‖₊ = ‖x‖₊ := rfl -@[simp] lemma nnnorm_toAdd (x) : ‖(toAdd x : E)‖₊ = ‖x‖₊ := rfl +@[simp] lemma nnnorm_toAdd (x : Multiplicative E) : ‖(x.toAdd : E)‖₊ = ‖x‖₊ := rfl @[simp] lemma nnnorm_ofAdd (x : E) : ‖ofAdd x‖₊ = ‖x‖₊ := rfl end NNNorm instance Additive.seminormedAddGroup [SeminormedGroup E] : SeminormedAddGroup (Additive E) where - dist_eq x y := dist_eq_norm_div (toMul x) (toMul y) + dist_eq x y := dist_eq_norm_div x.toMul y.toMul instance Multiplicative.seminormedGroup [SeminormedAddGroup E] : SeminormedGroup (Multiplicative E) where - dist_eq x y := dist_eq_norm_sub (toMul x) (toMul y) + dist_eq x y := dist_eq_norm_sub x.toAdd y.toAdd instance Additive.seminormedCommGroup [SeminormedCommGroup E] : SeminormedAddCommGroup (Additive E) := diff --git a/Mathlib/Analysis/Normed/Group/Seminorm.lean b/Mathlib/Analysis/Normed/Group/Seminorm.lean index 38c8d7fee64ca..e895bf01b8d3c 100644 --- a/Mathlib/Analysis/Normed/Group/Seminorm.lean +++ b/Mathlib/Analysis/Normed/Group/Seminorm.lean @@ -44,6 +44,7 @@ having a superfluous `add_le'` field in the resulting structure. The same applie norm, seminorm -/ +assert_not_exists Finset open Set diff --git a/Mathlib/Analysis/Normed/Group/Uniform.lean b/Mathlib/Analysis/Normed/Group/Uniform.lean index 8f4a7f9f06b4e..ca6dd25e1c9bb 100644 --- a/Mathlib/Analysis/Normed/Group/Uniform.lean +++ b/Mathlib/Analysis/Normed/Group/Uniform.lean @@ -15,13 +15,13 @@ This file proves lipschitzness of normed group operations and shows that normed groups. -/ -variable {𝓕 α E F : Type*} +variable {𝓕 E F : Type*} open Filter Function Metric Bornology open scoped ENNReal NNReal Uniformity Pointwise Topology section SeminormedGroup -variable [SeminormedGroup E] [SeminormedGroup F] {s : Set E} {a a₁ a₂ b b₁ b₂ : E} {r r₁ r₂ : ℝ} +variable [SeminormedGroup E] [SeminormedGroup F] {s : Set E} {a b : E} {r : ℝ} @[to_additive] instance NormedGroup.to_isometricSMul_right : IsometricSMul Eᵐᵒᵖ E := @@ -177,7 +177,7 @@ end SeminormedGroup section SeminormedCommGroup -variable [SeminormedCommGroup E] [SeminormedCommGroup F] {a a₁ a₂ b b₁ b₂ : E} {r r₁ r₂ : ℝ} +variable [SeminormedCommGroup E] [SeminormedCommGroup F] {a₁ a₂ b₁ b₂ : E} {r₁ r₂ : ℝ} @[to_additive] instance NormedGroup.to_isometricSMul_left : IsometricSMul E E := @@ -239,7 +239,7 @@ theorem edist_mul_mul_le (a₁ a₂ b₁ b₂ : E) : section PseudoEMetricSpace variable {α E : Type*} [SeminormedCommGroup E] [PseudoEMetricSpace α] {K Kf Kg : ℝ≥0} - {f g : α → E} {s : Set α} {x : α} + {f g : α → E} {s : Set α} @[to_additive (attr := simp)] lemma lipschitzWith_inv_iff : LipschitzWith K f⁻¹ ↔ LipschitzWith K f := by simp [LipschitzWith] @@ -381,7 +381,7 @@ instance : NormedCommGroup (SeparationQuotient E) where @[to_additive] theorem mk_eq_one_iff {p : E} : mk p = 1 ↔ ‖p‖ = 0 := by - rw [← norm_mk', norm_eq_zero''] + rw [← norm_mk', norm_eq_zero'] set_option linter.docPrime false in @[to_additive (attr := simp) nnnorm_mk] diff --git a/Mathlib/Analysis/Normed/Lp/lpSpace.lean b/Mathlib/Analysis/Normed/Lp/lpSpace.lean index 4797943bc7ec5..b2a36ecac89b5 100644 --- a/Mathlib/Analysis/Normed/Lp/lpSpace.lean +++ b/Mathlib/Analysis/Normed/Lp/lpSpace.lean @@ -183,7 +183,7 @@ theorem of_exponent_ge {p q : ℝ≥0∞} {f : ∀ i, E i} (hfq : Memℓp f q) ( have hf' := hfq.summable hq refine .of_norm_bounded_eventually _ hf' (@Set.Finite.subset _ { i | 1 ≤ ‖f i‖ } ?_ _ ?_) · have H : { x : α | 1 ≤ ‖f x‖ ^ q.toReal }.Finite := by - simpa using eventually_lt_of_tendsto_lt (by norm_num) hf'.tendsto_cofinite_zero + simpa using hf'.tendsto_cofinite_zero.eventually_lt_const (by norm_num) exact H.subset fun i hi => Real.one_le_rpow hi hq.le · show ∀ i, ¬|‖f i‖ ^ p.toReal| ≤ ‖f i‖ ^ q.toReal → 1 ≤ ‖f i‖ intro i hi diff --git a/Mathlib/Analysis/Normed/Module/FiniteDimension.lean b/Mathlib/Analysis/Normed/Module/FiniteDimension.lean index 303247548cea2..789c690f2042f 100644 --- a/Mathlib/Analysis/Normed/Module/FiniteDimension.lean +++ b/Mathlib/Analysis/Normed/Module/FiniteDimension.lean @@ -54,8 +54,7 @@ namespace LinearIsometry open LinearMap -variable {R : Type*} [Semiring R] -variable {F E₁ : Type*} [SeminormedAddCommGroup F] [NormedAddCommGroup E₁] [Module R E₁] +variable {F E₁ : Type*} [SeminormedAddCommGroup F] [NormedAddCommGroup E₁] variable {R₁ : Type*} [Field R₁] [Module R₁ E₁] [Module R₁ F] [FiniteDimensional R₁ E₁] [FiniteDimensional R₁ F] @@ -110,9 +109,7 @@ end AffineIsometry section CompleteField variable {𝕜 : Type u} [NontriviallyNormedField 𝕜] {E : Type v} [NormedAddCommGroup E] - [NormedSpace 𝕜 E] {F : Type w} [NormedAddCommGroup F] [NormedSpace 𝕜 F] {F' : Type x} - [AddCommGroup F'] [Module 𝕜 F'] [TopologicalSpace F'] [TopologicalAddGroup F'] - [ContinuousSMul 𝕜 F'] [CompleteSpace 𝕜] + [NormedSpace 𝕜 E] {F : Type w} [NormedAddCommGroup F] [NormedSpace 𝕜 F] [CompleteSpace 𝕜] section Affine diff --git a/Mathlib/Analysis/PSeries.lean b/Mathlib/Analysis/PSeries.lean index b077709ddf4da..38fe34d857d76 100644 --- a/Mathlib/Analysis/PSeries.lean +++ b/Mathlib/Analysis/PSeries.lean @@ -386,14 +386,10 @@ theorem sum_Ioc_inv_sq_le_sub {k n : ℕ} (hk : k ≠ 0) (h : k ≤ n) : simp only [sub_eq_add_neg, add_assoc, Nat.cast_add, Nat.cast_one, le_add_neg_iff_add_le, add_le_iff_nonpos_right, neg_add_le_iff_le_add, add_zero] have A : 0 < (n : α) := by simpa using hk.bot_lt.trans_le hn - have B : 0 < (n : α) + 1 := by linarith field_simp - rw [div_le_div_iff₀ _ A, ← sub_nonneg] - · ring_nf - rw [add_comm] - exact B.le - · -- Porting note: was `nlinarith` - positivity + rw [div_le_div_iff₀ _ A] + · linarith + · positivity theorem sum_Ioo_inv_sq_le (k n : ℕ) : (∑ i ∈ Ioo k n, (i ^ 2 : α)⁻¹) ≤ 2 / (k + 1) := calc diff --git a/Mathlib/Analysis/SpecialFunctions/ExpDeriv.lean b/Mathlib/Analysis/SpecialFunctions/ExpDeriv.lean index 3a485d339830b..846339ecb2f00 100644 --- a/Mathlib/Analysis/SpecialFunctions/ExpDeriv.lean +++ b/Mathlib/Analysis/SpecialFunctions/ExpDeriv.lean @@ -90,7 +90,7 @@ theorem iter_deriv_exp : ∀ n : ℕ, deriv^[n] exp = exp | 0 => rfl | n + 1 => by rw [iterate_succ_apply, deriv_exp, iter_deriv_exp n] -theorem contDiff_exp {n : ℕ∞} : ContDiff 𝕜 n exp := +theorem contDiff_exp {n : WithTop ℕ∞} : ContDiff 𝕜 n exp := analyticOnNhd_cexp.restrictScalars.contDiff theorem hasStrictDerivAt_exp (x : ℂ) : HasStrictDerivAt exp (exp x) x := @@ -230,7 +230,7 @@ theorem hasStrictDerivAt_exp (x : ℝ) : HasStrictDerivAt exp (exp x) x := theorem hasDerivAt_exp (x : ℝ) : HasDerivAt exp (exp x) x := (Complex.hasDerivAt_exp x).real_of_complex -theorem contDiff_exp {n : ℕ∞} : ContDiff ℝ n exp := +theorem contDiff_exp {n : WithTop ℕ∞} : ContDiff ℝ n exp := Complex.contDiff_exp.real_of_complex @[simp] diff --git a/Mathlib/Analysis/SpecialFunctions/Gamma/BohrMollerup.lean b/Mathlib/Analysis/SpecialFunctions/Gamma/BohrMollerup.lean index 86a1929d236cc..6a9a40ef2d4ff 100644 --- a/Mathlib/Analysis/SpecialFunctions/Gamma/BohrMollerup.lean +++ b/Mathlib/Analysis/SpecialFunctions/Gamma/BohrMollerup.lean @@ -57,7 +57,7 @@ theorem Gamma_mul_add_mul_le_rpow_Gamma_mul_rpow_Gamma {s t a b : ℝ} (hs : 0 < let f : ℝ → ℝ → ℝ → ℝ := fun c u x => exp (-c * x) * x ^ (c * (u - 1)) have e : IsConjExponent (1 / a) (1 / b) := Real.isConjExponent_one_div ha hb hab have hab' : b = 1 - a := by linarith - have hst : 0 < a * s + b * t := add_pos (mul_pos ha hs) (mul_pos hb ht) + have hst : 0 < a * s + b * t := by positivity -- some properties of f: have posf : ∀ c u x : ℝ, x ∈ Ioi (0 : ℝ) → 0 ≤ f c u x := fun c u x hx => mul_nonneg (exp_pos _).le (rpow_pos_of_pos hx _).le diff --git a/Mathlib/Analysis/SpecialFunctions/Gaussian/GaussianIntegral.lean b/Mathlib/Analysis/SpecialFunctions/Gaussian/GaussianIntegral.lean index 75fc9f00bf0db..b88d8363dabf7 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_def, neg_sq, neg_preimage, preimage_neg_Iio, neg_neg, neg_zero] + simp only [Function.comp_def, neg_sq, neg_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 diff --git a/Mathlib/Analysis/SpecialFunctions/Log/Deriv.lean b/Mathlib/Analysis/SpecialFunctions/Log/Deriv.lean index e9c7ca6362653..b886b2c966010 100644 --- a/Mathlib/Analysis/SpecialFunctions/Log/Deriv.lean +++ b/Mathlib/Analysis/SpecialFunctions/Log/Deriv.lean @@ -24,7 +24,7 @@ logarithm, derivative open Filter Finset Set -open scoped Topology +open scoped Topology ContDiff namespace Real @@ -66,12 +66,13 @@ theorem deriv_log (x : ℝ) : deriv log x = x⁻¹ := theorem deriv_log' : deriv log = Inv.inv := funext deriv_log -theorem contDiffOn_log {n : ℕ∞} : ContDiffOn ℝ n log {0}ᶜ := by - suffices ContDiffOn ℝ ⊤ log {0}ᶜ from this.of_le le_top +theorem contDiffOn_log {n : WithTop ℕ∞} : ContDiffOn ℝ n log {0}ᶜ := by + suffices ContDiffOn ℝ ω log {0}ᶜ from this.of_le le_top + rw [← contDiffOn_infty_iff_contDiffOn_omega] refine (contDiffOn_top_iff_deriv_of_isOpen isOpen_compl_singleton).2 ?_ simp [differentiableOn_log, contDiffOn_inv] -theorem contDiffAt_log {n : ℕ∞} : ContDiffAt ℝ n log x ↔ x ≠ 0 := +theorem contDiffAt_log {n : WithTop ℕ∞} : ContDiffAt ℝ n log x ↔ x ≠ 0 := ⟨fun h => continuousAt_log_iff.1 h.continuousAt, fun hx => (contDiffOn_log x hx).contDiffAt <| IsOpen.mem_nhds isOpen_compl_singleton hx⟩ diff --git a/Mathlib/Analysis/SpecialFunctions/Log/Monotone.lean b/Mathlib/Analysis/SpecialFunctions/Log/Monotone.lean index 5aa71529e87e1..c6b70bd4eaffa 100644 --- a/Mathlib/Analysis/SpecialFunctions/Log/Monotone.lean +++ b/Mathlib/Analysis/SpecialFunctions/Log/Monotone.lean @@ -53,11 +53,9 @@ theorem log_div_self_rpow_antitoneOn {a : ℝ} (ha : 0 < a) : intro x hex y _ hxy have x_pos : 0 < x := lt_of_lt_of_le (exp_pos (1 / a)) hex have y_pos : 0 < y := by linarith - have x_nonneg : 0 ≤ x := le_trans (le_of_lt (exp_pos (1 / a))) hex - have y_nonneg : 0 ≤ y := by linarith nth_rw 1 [← rpow_one y] nth_rw 1 [← rpow_one x] - rw [← div_self (ne_of_lt ha).symm, div_eq_mul_one_div a a, rpow_mul y_nonneg, rpow_mul x_nonneg, + rw [← div_self (ne_of_lt ha).symm, div_eq_mul_one_div a a, rpow_mul y_pos.le, rpow_mul x_pos.le, log_rpow (rpow_pos_of_pos y_pos a), log_rpow (rpow_pos_of_pos x_pos a), mul_div_assoc, mul_div_assoc, mul_le_mul_left (one_div_pos.mpr ha)] refine log_div_self_antitoneOn ?_ ?_ ?_ @@ -65,14 +63,14 @@ theorem log_div_self_rpow_antitoneOn {a : ℝ} (ha : 0 < a) : convert rpow_le_rpow _ hex (le_of_lt ha) using 1 · rw [← exp_mul] simp only [Real.exp_eq_exp] - field_simp [(ne_of_lt ha).symm] - exact le_of_lt (exp_pos (1 / a)) + field_simp + positivity · simp only [Set.mem_setOf_eq] convert rpow_le_rpow _ (_root_.trans hex hxy) (le_of_lt ha) using 1 · rw [← exp_mul] simp only [Real.exp_eq_exp] - field_simp [(ne_of_lt ha).symm] - exact le_of_lt (exp_pos (1 / a)) + field_simp + positivity gcongr theorem log_div_sqrt_antitoneOn : AntitoneOn (fun x : ℝ => log x / √x) { x | exp 2 ≤ x } := by diff --git a/Mathlib/Analysis/SpecialFunctions/Pow/Deriv.lean b/Mathlib/Analysis/SpecialFunctions/Pow/Deriv.lean index d05eed644c71c..0c619bd07f671 100644 --- a/Mathlib/Analysis/SpecialFunctions/Pow/Deriv.lean +++ b/Mathlib/Analysis/SpecialFunctions/Pow/Deriv.lean @@ -282,7 +282,7 @@ theorem hasStrictFDerivAt_rpow_of_neg (p : ℝ × ℝ) (hp : p.1 < 0) : rw [div_eq_mul_inv, add_comm]; congr 2 <;> ring /-- The function `fun (x, y) => x ^ y` is infinitely smooth at `(x, y)` unless `x = 0`. -/ -theorem contDiffAt_rpow_of_ne (p : ℝ × ℝ) (hp : p.1 ≠ 0) {n : ℕ∞} : +theorem contDiffAt_rpow_of_ne (p : ℝ × ℝ) (hp : p.1 ≠ 0) {n : WithTop ℕ∞} : ContDiffAt ℝ n (fun p : ℝ × ℝ => p.1 ^ p.2) p := by cases' hp.lt_or_lt with hneg hpos exacts @@ -358,7 +358,7 @@ theorem deriv_rpow_const' {p : ℝ} (h : 1 ≤ p) : (deriv fun x : ℝ => x ^ p) = fun x => p * x ^ (p - 1) := funext fun _ => deriv_rpow_const (Or.inr h) -theorem contDiffAt_rpow_const_of_ne {x p : ℝ} {n : ℕ∞} (h : x ≠ 0) : +theorem contDiffAt_rpow_const_of_ne {x p : ℝ} {n : WithTop ℕ∞} (h : x ≠ 0) : ContDiffAt ℝ n (fun x => x ^ p) x := (contDiffAt_rpow_of_ne (x, p) h).comp x (contDiffAt_id.prod contDiffAt_const) @@ -368,7 +368,8 @@ theorem contDiff_rpow_const_of_le {p : ℝ} {n : ℕ} (h : ↑n ≤ p) : · exact contDiff_zero.2 (continuous_id.rpow_const fun x => Or.inr <| by simpa using h) · have h1 : 1 ≤ p := le_trans (by simp) h rw [Nat.cast_succ, ← le_sub_iff_add_le] at h - rw [show ((n + 1 : ℕ) : ℕ∞) = n + 1 from rfl, contDiff_succ_iff_deriv, deriv_rpow_const' h1] + rw [show ((n + 1 : ℕ) : WithTop ℕ∞) = n + 1 from rfl, contDiff_succ_iff_deriv, + deriv_rpow_const' h1] exact ⟨differentiable_rpow_const h1, contDiff_const.mul (ihn h)⟩ theorem contDiffAt_rpow_const_of_le {x p : ℝ} {n : ℕ} (h : ↑n ≤ p) : @@ -589,10 +590,10 @@ open Real Filter theorem tendsto_one_plus_div_rpow_exp (t : ℝ) : Tendsto (fun x : ℝ => (1 + t / x) ^ x) atTop (𝓝 (exp t)) := by apply ((Real.continuous_exp.tendsto _).comp (tendsto_mul_log_one_plus_div_atTop t)).congr' _ - have h₁ : (1 : ℝ) / 2 < 1 := by linarith + have h₁ : (1 : ℝ) / 2 < 1 := by norm_num have h₂ : Tendsto (fun x : ℝ => 1 + t / x) atTop (𝓝 1) := by simpa using (tendsto_inv_atTop_zero.const_mul t).const_add 1 - refine (eventually_ge_of_tendsto_gt h₁ h₂).mono fun x hx => ?_ + refine (h₂.eventually_const_le h₁).mono fun x hx => ?_ have hx' : 0 < 1 + t / x := by linarith simp [mul_comm x, exp_mul, exp_log hx'] diff --git a/Mathlib/Analysis/SpecialFunctions/SmoothTransition.lean b/Mathlib/Analysis/SpecialFunctions/SmoothTransition.lean index 20b9a0ce94d94..a9815ec827dfa 100644 --- a/Mathlib/Analysis/SpecialFunctions/SmoothTransition.lean +++ b/Mathlib/Analysis/SpecialFunctions/SmoothTransition.lean @@ -113,7 +113,7 @@ theorem contDiff_polynomial_eval_inv_mul {n : ℕ∞} (p : ℝ[X]) : exact (hasDerivAt_polynomial_eval_inv_mul p _).deriv /-- The function `expNegInvGlue` is smooth. -/ -protected theorem contDiff {n} : ContDiff ℝ n expNegInvGlue := by +protected theorem contDiff {n : ℕ∞} : ContDiff ℝ n expNegInvGlue := by simpa using contDiff_polynomial_eval_inv_mul 1 end expNegInvGlue @@ -174,12 +174,12 @@ theorem lt_one_of_lt_one (h : x < 1) : smoothTransition x < 1 := theorem pos_of_pos (h : 0 < x) : 0 < smoothTransition x := div_pos (expNegInvGlue.pos_of_pos h) (pos_denom x) -protected theorem contDiff {n} : ContDiff ℝ n smoothTransition := +protected theorem contDiff {n : ℕ∞} : ContDiff ℝ n smoothTransition := expNegInvGlue.contDiff.div (expNegInvGlue.contDiff.add <| expNegInvGlue.contDiff.comp <| contDiff_const.sub contDiff_id) fun x => (pos_denom x).ne' -protected theorem contDiffAt {x n} : ContDiffAt ℝ n smoothTransition x := +protected theorem contDiffAt {x : ℝ} {n : ℕ∞} : ContDiffAt ℝ n smoothTransition x := smoothTransition.contDiff.contDiffAt protected theorem continuous : Continuous smoothTransition := diff --git a/Mathlib/Analysis/SpecialFunctions/Trigonometric/ComplexDeriv.lean b/Mathlib/Analysis/SpecialFunctions/Trigonometric/ComplexDeriv.lean index e414b1421381a..a06b4a537e039 100644 --- a/Mathlib/Analysis/SpecialFunctions/Trigonometric/ComplexDeriv.lean +++ b/Mathlib/Analysis/SpecialFunctions/Trigonometric/ComplexDeriv.lean @@ -62,7 +62,7 @@ theorem deriv_tan (x : ℂ) : deriv tan x = 1 / cos x ^ 2 := else (hasDerivAt_tan h).deriv @[simp] -theorem contDiffAt_tan {x : ℂ} {n : ℕ∞} : ContDiffAt ℂ n tan x ↔ cos x ≠ 0 := +theorem contDiffAt_tan {x : ℂ} {n : WithTop ℕ∞} : ContDiffAt ℂ n tan x ↔ cos x ≠ 0 := ⟨fun h => continuousAt_tan.1 h.continuousAt, contDiff_sin.contDiffAt.div contDiff_cos.contDiffAt⟩ end Complex diff --git a/Mathlib/Analysis/SpecialFunctions/Trigonometric/InverseDeriv.lean b/Mathlib/Analysis/SpecialFunctions/Trigonometric/InverseDeriv.lean index 6ade7f02ca336..d9efa5b942979 100644 --- a/Mathlib/Analysis/SpecialFunctions/Trigonometric/InverseDeriv.lean +++ b/Mathlib/Analysis/SpecialFunctions/Trigonometric/InverseDeriv.lean @@ -14,7 +14,7 @@ Derivatives of `arcsin` and `arccos`. noncomputable section -open scoped Topology Filter Real +open scoped Topology Filter Real ContDiff open Set namespace Real @@ -22,7 +22,7 @@ namespace Real section Arcsin theorem deriv_arcsin_aux {x : ℝ} (h₁ : x ≠ -1) (h₂ : x ≠ 1) : - HasStrictDerivAt arcsin (1 / √(1 - x ^ 2)) x ∧ ContDiffAt ℝ ⊤ arcsin x := by + HasStrictDerivAt arcsin (1 / √(1 - x ^ 2)) x ∧ ContDiffAt ℝ ω arcsin x := by cases' h₁.lt_or_lt with h₁ h₁ · have : 1 - x ^ 2 < 0 := by nlinarith [h₁] rw [sqrt_eq_zero'.2 this.le, div_zero] @@ -50,7 +50,8 @@ theorem hasDerivAt_arcsin {x : ℝ} (h₁ : x ≠ -1) (h₂ : x ≠ 1) : HasDerivAt arcsin (1 / √(1 - x ^ 2)) x := (hasStrictDerivAt_arcsin h₁ h₂).hasDerivAt -theorem contDiffAt_arcsin {x : ℝ} (h₁ : x ≠ -1) (h₂ : x ≠ 1) {n : ℕ∞} : ContDiffAt ℝ n arcsin x := +theorem contDiffAt_arcsin {x : ℝ} (h₁ : x ≠ -1) (h₂ : x ≠ 1) {n : WithTop ℕ∞} : + ContDiffAt ℝ n arcsin x := (deriv_arcsin_aux h₁ h₂).2.of_le le_top theorem hasDerivWithinAt_arcsin_Ici {x : ℝ} (h : x ≠ -1) : @@ -102,12 +103,13 @@ theorem differentiableOn_arcsin : DifferentiableOn ℝ arcsin {-1, 1}ᶜ := fun (differentiableAt_arcsin.2 ⟨fun h => hx (Or.inl h), fun h => hx (Or.inr h)⟩).differentiableWithinAt -theorem contDiffOn_arcsin {n : ℕ∞} : ContDiffOn ℝ n arcsin {-1, 1}ᶜ := fun _x hx => +theorem contDiffOn_arcsin {n : WithTop ℕ∞} : ContDiffOn ℝ n arcsin {-1, 1}ᶜ := fun _x hx => (contDiffAt_arcsin (mt Or.inl hx) (mt Or.inr hx)).contDiffWithinAt -theorem contDiffAt_arcsin_iff {x : ℝ} {n : ℕ∞} : ContDiffAt ℝ n arcsin x ↔ n = 0 ∨ x ≠ -1 ∧ x ≠ 1 := +theorem contDiffAt_arcsin_iff {x : ℝ} {n : WithTop ℕ∞} : + ContDiffAt ℝ n arcsin x ↔ n = 0 ∨ x ≠ -1 ∧ x ≠ 1 := ⟨fun h => or_iff_not_imp_left.2 fun hn => differentiableAt_arcsin.1 <| h.differentiableAt <| - ENat.one_le_iff_ne_zero.2 hn, + ENat.one_le_iff_ne_zero_withTop.mpr hn, fun h => h.elim (fun hn => hn.symm ▸ (contDiff_zero.2 continuous_arcsin).contDiffAt) fun hx => contDiffAt_arcsin hx.1 hx.2⟩ @@ -123,7 +125,8 @@ theorem hasDerivAt_arccos {x : ℝ} (h₁ : x ≠ -1) (h₂ : x ≠ 1) : HasDerivAt arccos (-(1 / √(1 - x ^ 2))) x := (hasDerivAt_arcsin h₁ h₂).const_sub (π / 2) -theorem contDiffAt_arccos {x : ℝ} (h₁ : x ≠ -1) (h₂ : x ≠ 1) {n : ℕ∞} : ContDiffAt ℝ n arccos x := +theorem contDiffAt_arccos {x : ℝ} (h₁ : x ≠ -1) (h₂ : x ≠ 1) {n : WithTop ℕ∞} : + ContDiffAt ℝ n arccos x := contDiffAt_const.sub (contDiffAt_arcsin h₁ h₂) theorem hasDerivWithinAt_arccos_Ici {x : ℝ} (h : x ≠ -1) : @@ -152,10 +155,10 @@ theorem deriv_arccos : deriv arccos = fun x => -(1 / √(1 - x ^ 2)) := theorem differentiableOn_arccos : DifferentiableOn ℝ arccos {-1, 1}ᶜ := differentiableOn_arcsin.const_sub _ -theorem contDiffOn_arccos {n : ℕ∞} : ContDiffOn ℝ n arccos {-1, 1}ᶜ := +theorem contDiffOn_arccos {n : WithTop ℕ∞} : ContDiffOn ℝ n arccos {-1, 1}ᶜ := contDiffOn_const.sub contDiffOn_arcsin -theorem contDiffAt_arccos_iff {x : ℝ} {n : ℕ∞} : +theorem contDiffAt_arccos_iff {x : ℝ} {n : WithTop ℕ∞} : ContDiffAt ℝ n arccos x ↔ n = 0 ∨ x ≠ -1 ∧ x ≠ 1 := by refine Iff.trans ⟨fun h => ?_, fun h => ?_⟩ contDiffAt_arcsin_iff <;> simpa [arccos] using (contDiffAt_const (c := π / 2)).sub h diff --git a/Mathlib/Analysis/SpecificLimits/Basic.lean b/Mathlib/Analysis/SpecificLimits/Basic.lean index 3d759d9f3fb33..e9bbbad7a0c52 100644 --- a/Mathlib/Analysis/SpecificLimits/Basic.lean +++ b/Mathlib/Analysis/SpecificLimits/Basic.lean @@ -623,7 +623,7 @@ theorem tendsto_factorial_div_pow_self_atTop : refine (eventually_gt_atTop 0).mono fun n hn ↦ ?_ rcases Nat.exists_eq_succ_of_ne_zero hn.ne.symm with ⟨k, rfl⟩ rw [← prod_range_add_one_eq_factorial, pow_eq_prod_const, div_eq_mul_inv, ← inv_eq_one_div, - prod_natCast, Nat.cast_succ, ← prod_inv_distrib, ← prod_mul_distrib, + prod_natCast, Nat.cast_succ, ← Finset.prod_inv_distrib, ← prod_mul_distrib, Finset.prod_range_succ'] simp only [prod_range_succ', one_mul, Nat.cast_add, zero_add, Nat.cast_one] refine diff --git a/Mathlib/Analysis/SpecificLimits/Normed.lean b/Mathlib/Analysis/SpecificLimits/Normed.lean index 69992fdb4a113..cf5f9286f5bd2 100644 --- a/Mathlib/Analysis/SpecificLimits/Normed.lean +++ b/Mathlib/Analysis/SpecificLimits/Normed.lean @@ -601,7 +601,7 @@ theorem summable_of_ratio_test_tendsto_lt_one {α : Type*} [NormedAddCommGroup (h : Tendsto (fun n ↦ ‖f (n + 1)‖ / ‖f n‖) atTop (𝓝 l)) : Summable f := by 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₁ + filter_upwards [h.eventually_le_const hr₀, hf] with _ _ h₁ rwa [← div_le_iff₀ (norm_pos_iff.mpr h₁)] theorem not_summable_of_ratio_norm_eventually_ge {α : Type*} [SeminormedAddCommGroup α] {f : ℕ → α} @@ -629,12 +629,12 @@ theorem not_summable_of_ratio_test_tendsto_gt_one {α : Type*} [SeminormedAddCom {f : ℕ → α} {l : ℝ} (hl : 1 < l) (h : Tendsto (fun n ↦ ‖f (n + 1)‖ / ‖f n‖) atTop (𝓝 l)) : ¬Summable f := by have key : ∀ᶠ n in atTop, ‖f n‖ ≠ 0 := by - filter_upwards [eventually_ge_of_tendsto_gt hl h] with _ hn hc + filter_upwards [h.eventually_const_le hl] with _ hn hc rw [hc, _root_.div_zero] at hn linarith 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₁ + filter_upwards [h.eventually_const_le hr₁, key] with _ _ h₁ rwa [← le_div_iff₀ (lt_of_le_of_ne (norm_nonneg _) h₁.symm)] section NormedDivisionRing diff --git a/Mathlib/CategoryTheory/Adjunction/Evaluation.lean b/Mathlib/CategoryTheory/Adjunction/Evaluation.lean index d11a3d4ac62c1..ffb59cad14a86 100644 --- a/Mathlib/CategoryTheory/Adjunction/Evaluation.lean +++ b/Mathlib/CategoryTheory/Adjunction/Evaluation.lean @@ -22,7 +22,6 @@ open CategoryTheory.Limits universe v₁ v₂ v₃ u₁ u₂ u₃ variable {C : Type u₁} [Category.{v₁} C] (D : Type u₂) [Category.{v₂} D] - (E : Type u₃) [Category.{v₃} E] noncomputable section diff --git a/Mathlib/CategoryTheory/Adjunction/Limits.lean b/Mathlib/CategoryTheory/Adjunction/Limits.lean index dd86591976534..2db2c795ef2c2 100644 --- a/Mathlib/CategoryTheory/Adjunction/Limits.lean +++ b/Mathlib/CategoryTheory/Adjunction/Limits.lean @@ -92,7 +92,7 @@ lemma leftAdjoint_preservesColimits : PreservesColimitsOfSize.{v, u} F where ((adj.functorialityAdjunction _).homEquiv _ _)⟩ } } include adj in -@[deprecated (since := "2024-11-19")] +@[deprecated "No deprecation message was provided." (since := "2024-11-19")] lemma leftAdjointPreservesColimits : PreservesColimitsOfSize.{v, u} F := adj.leftAdjoint_preservesColimits @@ -117,7 +117,7 @@ noncomputable instance (priority := 100) { reflects := fun t => ⟨(isColimitOfPreserves E.inv t).mapCoconeEquiv E.asEquivalence.unitIso.symm⟩ } } -@[deprecated (since := "2024-11-18")] +@[deprecated "No deprecation message was provided." (since := "2024-11-18")] lemma isEquivalenceReflectsColimits (E : D ⥤ C) [E.IsEquivalence] : ReflectsColimitsOfSize.{v, u} E := Functor.reflectsColimits_of_isEquivalence E @@ -216,7 +216,7 @@ lemma rightAdjoint_preservesLimits : PreservesLimitsOfSize.{v, u} G where ((adj.functorialityAdjunction' _).homEquiv _ _).symm⟩ } } include adj in -@[deprecated (since := "2024-11-19")] +@[deprecated "No deprecation message was provided." (since := "2024-11-19")] lemma rightAdjointPreservesLimits : PreservesLimitsOfSize.{v, u} G := adj.rightAdjoint_preservesLimits @@ -240,7 +240,7 @@ noncomputable instance (priority := 100) { reflects := fun t => ⟨(isLimitOfPreserves E.inv t).mapConeEquiv E.asEquivalence.unitIso.symm⟩ } } -@[deprecated (since := "2024-11-18")] +@[deprecated "No deprecation message was provided." (since := "2024-11-18")] lemma isEquivalenceReflectsLimits (E : D ⥤ C) [E.IsEquivalence] : ReflectsLimitsOfSize.{v, u} E := Functor.reflectsLimits_of_isEquivalence E diff --git a/Mathlib/CategoryTheory/Comma/Over.lean b/Mathlib/CategoryTheory/Comma/Over.lean index e37bf7ec99866..305664eb69cad 100644 --- a/Mathlib/CategoryTheory/Comma/Over.lean +++ b/Mathlib/CategoryTheory/Comma/Over.lean @@ -161,6 +161,13 @@ theorem map_map_left : ((map f).map g).left = g.left := rfl end +/-- If `f` is an isomorphism, `map f` is an equivalence of categories. -/ +def mapIso {Y : T} (f : X ≅ Y) : Over X ≌ Over Y := + Comma.mapRightIso _ <| Discrete.natIso fun _ ↦ f + +@[simp] lemma mapIso_functor {Y : T} (f : X ≅ Y) : (mapIso f).functor = map f.hom := rfl +@[simp] lemma mapIso_inverse {Y : T} (f : X ≅ Y) : (mapIso f).inverse = map f.inv := rfl + section coherences /-! This section proves various equalities between functors that @@ -186,6 +193,7 @@ theorem mapId_eq (Y : T) : map (𝟙 Y) = 𝟭 _ := by simp /-- The natural isomorphism arising from `mapForget_eq`. -/ +@[simps!] def mapId (Y : T) : map (𝟙 Y) ≅ 𝟭 _ := eqToIso (mapId_eq Y) -- NatIso.ofComponents fun X => isoMk (Iso.refl _) @@ -215,9 +223,16 @@ theorem mapComp_eq {X Y Z : T} (f : X ⟶ Y) (g : Y ⟶ Z) : simp /-- The natural isomorphism arising from `mapComp_eq`. -/ +@[simps!] def mapComp {X Y Z : T} (f : X ⟶ Y) (g : Y ⟶ Z) : map (f ≫ g) ≅ (map f) ⋙ (map g) := eqToIso (mapComp_eq f g) +/-- If `f = g`, then `map f` is naturally isomorphic to `map g`. -/ +@[simps!] +def mapCongr {X Y : T} (f g : X ⟶ Y) (h : f = g) : + map f ≅ map g := + NatIso.ofComponents (fun A ↦ eqToIso (by rw [h])) + variable (T) in /-- The functor defined by the over categories.-/ @[simps] def mapFunctor : T ⥤ Cat where @@ -317,6 +332,57 @@ 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]) +lemma post_comp {E : Type*} [Category E] (F : T ⥤ D) (G : D ⥤ E) : + post (X := X) (F ⋙ G) = post (X := X) F ⋙ post G := + rfl + +/-- `post (F ⋙ G)` is isomorphic (actually equal) to `post F ⋙ post G`. -/ +@[simps!] +def postComp {E : Type*} [Category E] (F : T ⥤ D) (G : D ⥤ E) : + post (X := X) (F ⋙ G) ≅ post F ⋙ post G := + NatIso.ofComponents (fun X ↦ Iso.refl _) + +/-- A natural transformation `F ⟶ G` induces a natural transformation on +`Over X` up to `Under.map`. -/ +@[simps] +def postMap {F G : T ⥤ D} (e : F ⟶ G) : post F ⋙ map (e.app X) ⟶ post G where + app Y := Over.homMk (e.app Y.left) + +/-- If `F` and `G` are naturally isomorphic, then `Over.post F` and `Over.post G` are also naturally +isomorphic up to `Over.map` -/ +@[simps!] +def postCongr {F G : T ⥤ D} (e : F ≅ G) : post F ⋙ map (e.hom.app X) ≅ post G := + NatIso.ofComponents (fun A ↦ Over.isoMk (e.app A.left)) + +variable (X) (F : T ⥤ D) + +instance [F.Faithful] : (Over.post (X := X) F).Faithful where + map_injective {A B} f g h := by + ext + exact F.map_injective (congrArg CommaMorphism.left h) + +instance [F.Faithful] [F.Full] : (Over.post (X := X) F).Full where + map_surjective {A B} f := by + obtain ⟨a, ha⟩ := F.map_surjective f.left + have w : a ≫ B.hom = A.hom := F.map_injective <| by simpa [ha] using Over.w _ + exact ⟨Over.homMk a, by ext; simpa⟩ + +instance [F.Full] [F.EssSurj] : (Over.post (X := X) F).EssSurj where + mem_essImage B := by + obtain ⟨A', ⟨e⟩⟩ := Functor.EssSurj.mem_essImage (F := F) B.left + obtain ⟨f, hf⟩ := F.map_surjective (e.hom ≫ B.hom) + exact ⟨Over.mk f, ⟨Over.isoMk e⟩⟩ + +instance [F.IsEquivalence] : (Over.post (X := X) F).IsEquivalence where + +/-- An equivalence of categories induces an equivalence on over categories. -/ +@[simps] +def postEquiv (F : T ≌ D) : Over X ≌ Over (F.functor.obj X) where + functor := Over.post F.functor + inverse := Over.post (X := F.functor.obj X) F.inverse ⋙ Over.map (F.unitIso.inv.app X) + unitIso := NatIso.ofComponents (fun A ↦ Over.isoMk (F.unitIso.app A.left)) + counitIso := NatIso.ofComponents (fun A ↦ Over.isoMk (F.counitIso.app A.left)) + end Over namespace CostructuredArrow @@ -457,6 +523,13 @@ theorem map_map_right : ((map f).map g).right = g.right := rfl end +/-- If `f` is an isomorphism, `map f` is an equivalence of categories. -/ +def mapIso {Y : T} (f : X ≅ Y) : Under Y ≌ Under X := + Comma.mapLeftIso _ <| Discrete.natIso fun _ ↦ f.symm + +@[simp] lemma mapIso_functor {Y : T} (f : X ≅ Y) : (mapIso f).functor = map f.hom := rfl +@[simp] lemma mapIso_inverse {Y : T} (f : X ≅ Y) : (mapIso f).inverse = map f.inv := rfl + section coherences /-! This section proves various equalities between functors that @@ -476,6 +549,7 @@ theorem mapId_eq (Y : T) : map (𝟙 Y) = 𝟭 _ := by simp /-- Mapping by the identity morphism is just the identity functor. -/ +@[simps!] def mapId (Y : T) : map (𝟙 Y) ≅ 𝟭 _ := eqToIso (mapId_eq Y) /-- Mapping by `f` and then forgetting is the same as forgetting. -/ @@ -504,9 +578,16 @@ theorem mapComp_eq {X Y Z : T} (f : X ⟶ Y) (g : Y ⟶ Z) : simp /-- The natural isomorphism arising from `mapComp_eq`. -/ +@[simps!] def mapComp {Y Z : T} (f : X ⟶ Y) (g : Y ⟶ Z) : map (f ≫ g) ≅ map g ⋙ map f := eqToIso (mapComp_eq f g) +/-- If `f = g`, then `map f` is naturally isomorphic to `map g`. -/ +@[simps!] +def mapCongr {X Y : T} (f g : X ⟶ Y) (h : f = g) : + map f ≅ map g := + NatIso.ofComponents (fun A ↦ eqToIso (by rw [h])) + variable (T) in /-- The functor defined by the under categories.-/ @[simps] def mapFunctor : Tᵒᵖ ⥤ Cat where @@ -570,6 +651,58 @@ 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]) +lemma post_comp {E : Type*} [Category E] (F : T ⥤ D) (G : D ⥤ E) : + post (X := X) (F ⋙ G) = post (X := X) F ⋙ post G := + rfl + +/-- `post (F ⋙ G)` is isomorphic (actually equal) to `post F ⋙ post G`. -/ +@[simps!] +def postComp {E : Type*} [Category E] (F : T ⥤ D) (G : D ⥤ E) : + post (X := X) (F ⋙ G) ≅ post F ⋙ post G := + NatIso.ofComponents (fun X ↦ Iso.refl _) + +/-- A natural transformation `F ⟶ G` induces a natural transformation on +`Under X` up to `Under.map`. -/ +@[simps] +def postMap {F G : T ⥤ D} (e : F ⟶ G) : post (X := X) F ⟶ post G ⋙ map (e.app X) where + app Y := Under.homMk (e.app Y.right) + +/-- If `F` and `G` are naturally isomorphic, then `Under.post F` and `Under.post G` are also +naturally isomorphic up to `Under.map` -/ +@[simps!] +def postCongr {F G : T ⥤ D} (e : F ≅ G) : post F ≅ post G ⋙ map (e.hom.app X) := + NatIso.ofComponents (fun A ↦ Under.isoMk (e.app A.right)) + +variable (X) (F : T ⥤ D) + +instance [F.Faithful] : (Under.post (X := X) F).Faithful where + map_injective {A B} f g h := by + ext + exact F.map_injective (congrArg CommaMorphism.right h) + +instance [F.Faithful] [F.Full] : (Under.post (X := X) F).Full where + map_surjective {A B} f := by + obtain ⟨a, ha⟩ := F.map_surjective f.right + dsimp at a + have w : A.hom ≫ a = B.hom := F.map_injective <| by simpa [ha] using Under.w f + exact ⟨Under.homMk a, by ext; simpa⟩ + +instance [F.Full] [F.EssSurj] : (Under.post (X := X) F).EssSurj where + mem_essImage B := by + obtain ⟨B', ⟨e⟩⟩ := Functor.EssSurj.mem_essImage (F := F) B.right + obtain ⟨f, hf⟩ := F.map_surjective (B.hom ≫ e.inv) + exact ⟨Under.mk f, ⟨Under.isoMk e⟩⟩ + +instance [F.IsEquivalence] : (Under.post (X := X) F).IsEquivalence where + +/-- An equivalence of categories induces an equivalence on under categories. -/ +@[simps] +def postEquiv (F : T ≌ D) : Under X ≌ Under (F.functor.obj X) where + functor := post F.functor + inverse := post (X := F.functor.obj X) F.inverse ⋙ Under.map (F.unitIso.hom.app X) + unitIso := NatIso.ofComponents (fun A ↦ Under.isoMk (F.unitIso.app A.right)) + counitIso := NatIso.ofComponents (fun A ↦ Under.isoMk (F.counitIso.app A.right)) + end Under namespace StructuredArrow @@ -774,4 +907,52 @@ def ofDiagEquivalence' (X : T × T) : end CostructuredArrow +section Opposite + +open Opposite + +variable (X : T) + +/-- The canonical functor by reversing structure arrows. -/ +@[simps] +def Over.opToOpUnder : Over (op X) ⥤ (Under X)ᵒᵖ where + obj Y := ⟨Under.mk Y.hom.unop⟩ + map {Z Y} f := ⟨Under.homMk (f.left.unop) (by dsimp; rw [← unop_comp, Over.w])⟩ + +/-- The canonical functor by reversing structure arrows. -/ +@[simps] +def Under.opToOverOp : (Under X)ᵒᵖ ⥤ Over (op X) where + obj Y := Over.mk (Y.unop.hom.op) + map {Z Y} f := Over.homMk f.unop.right.op <| by dsimp; rw [← Under.w f.unop, op_comp] + +/-- `Over.opToOpUnder` is an equivalence of categories. -/ +@[simps] +def Over.opEquivOpUnder : Over (op X) ≌ (Under X)ᵒᵖ where + functor := Over.opToOpUnder X + inverse := Under.opToOverOp X + unitIso := Iso.refl _ + counitIso := Iso.refl _ + +/-- The canonical functor by reversing structure arrows. -/ +@[simps] +def Under.opToOpOver : Under (op X) ⥤ (Over X)ᵒᵖ where + obj Y := ⟨Over.mk Y.hom.unop⟩ + map {Z Y} f := ⟨Over.homMk (f.right.unop) (by dsimp; rw [← unop_comp, Under.w])⟩ + +/-- The canonical functor by reversing structure arrows. -/ +@[simps] +def Over.opToUnderOp : (Over X)ᵒᵖ ⥤ Under (op X) where + obj Y := Under.mk (Y.unop.hom.op) + map {Z Y} f := Under.homMk f.unop.left.op <| by dsimp; rw [← Over.w f.unop, op_comp] + +/-- `Under.opToOpOver` is an equivalence of categories. -/ +@[simps] +def Under.opEquivOpOver : Under (op X) ≌ (Over X)ᵒᵖ where + functor := Under.opToOpOver X + inverse := Over.opToUnderOp X + unitIso := Iso.refl _ + counitIso := Iso.refl _ + +end Opposite + end CategoryTheory diff --git a/Mathlib/CategoryTheory/Comma/OverClass.lean b/Mathlib/CategoryTheory/Comma/OverClass.lean index bfe80651c0003..a6b1fc35caeb2 100644 --- a/Mathlib/CategoryTheory/Comma/OverClass.lean +++ b/Mathlib/CategoryTheory/Comma/OverClass.lean @@ -31,7 +31,7 @@ universe v u variable {C : Type u} [Category.{v} C] -variable {X Y : C} (f : X ⟶ Y) (S S' : C) +variable {X Y Z : C} (f : X ⟶ Y) (S S' : C) /-- `OverClass X S` is the typeclass containing the data of a structure morphism `X ↘ S : X ⟶ S`. @@ -68,27 +68,39 @@ def CanonicallyOverClass.Simps.over (X S : C) [CanonicallyOverClass X S] : X ⟶ initialize_simps_projections CanonicallyOverClass (hom → over) @[simps] -instance (priority := 100) : OverClass X X := ⟨𝟙 _⟩ +instance : OverClass X X := ⟨𝟙 _⟩ -@[simps] +instance : IsIso (S ↘ S) := inferInstanceAs (IsIso (𝟙 S)) + +-- This cannot be a simp lemma be cause it loops with `comp_over`. +@[simps (config := .lemmasOnly)] instance (priority := 900) [CanonicallyOverClass X Y] [OverClass Y S] : OverClass X S := ⟨X ↘ Y ≫ Y ↘ S⟩ /-- Given `OverClass X S` and `OverClass Y S` and `f : X ⟶ Y`, `HomIsOver f S` is the typeclass asserting `f` commutes with the structure morphisms. -/ class HomIsOver (f : X ⟶ Y) (S : C) [OverClass X S] [OverClass Y S] : Prop where - comp_over : f ≫ Y ↘ S = X ↘ S := by simp + comp_over : f ≫ Y ↘ S = X ↘ S := by aesop @[reassoc (attr := simp)] lemma comp_over [OverClass X S] [OverClass Y S] [HomIsOver f S] : f ≫ Y ↘ S = X ↘ S := HomIsOver.comp_over +instance [OverClass X S] : HomIsOver (𝟙 X) S where + +instance [OverClass X S] [OverClass Y S] [OverClass Z S] + (f : X ⟶ Y) (g : Y ⟶ Z) [HomIsOver f S] [HomIsOver g S] : + HomIsOver (f ≫ g) S where + /-- `Scheme.IsOverTower X Y S` is the typeclass asserting that the structure morphisms `X ↘ Y`, `Y ↘ S`, and `X ↘ S` commute. -/ abbrev IsOverTower (X Y S : C) [OverClass X S] [OverClass Y S] [OverClass X Y] := HomIsOver (X ↘ Y) S +instance [OverClass X S] : IsOverTower X X S where +instance [OverClass X S] : IsOverTower X S S where + instance [CanonicallyOverClass X Y] [OverClass Y S] : IsOverTower X Y S := ⟨rfl⟩ @@ -108,7 +120,22 @@ instance [OverClass X S] [IsOverTower X S S'] [IsOverTower Y S S'] [HomIsOver f S] : HomIsOver f S' := homIsOver_of_isOverTower f S S' +variable (X) in /-- Bundle `X` with an `OverClass X S` instance into `Over S`. -/ +@[simps! hom left] def OverClass.asOver [OverClass X S] : Over S := Over.mk (X ↘ S) +/-- Bundle a morphism `f : X ⟶ Y` with `HomIsOver f S` into a morphism in `Over S`. -/ +@[simps! left] +def OverClass.asOverHom [OverClass X S] [OverClass Y S] (f : X ⟶ Y) [HomIsOver f S] : + OverClass.asOver X S ⟶ OverClass.asOver Y S := + Over.homMk f (comp_over f S) + +@[simps] +instance OverClass.fromOver {S : C} (X : Over S) : OverClass X.left S where + hom := X.hom + +instance {S : C} {X Y : Over S} (f : X ⟶ Y) : HomIsOver f.left S where + comp_over := Over.w f + end CategoryTheory diff --git a/Mathlib/CategoryTheory/ConcreteCategory/Basic.lean b/Mathlib/CategoryTheory/ConcreteCategory/Basic.lean index 38882d4e9f448..ebeea719fe2dc 100644 --- a/Mathlib/CategoryTheory/ConcreteCategory/Basic.lean +++ b/Mathlib/CategoryTheory/ConcreteCategory/Basic.lean @@ -55,7 +55,7 @@ class ConcreteCategory (C : Type u) [Category.{v} C] where /-- That functor is faithful -/ [forget_faithful : forget.Faithful] -attribute [reducible] ConcreteCategory.forget +attribute [inline, reducible] ConcreteCategory.forget attribute [instance] ConcreteCategory.forget_faithful /-- The forgetful functor from a concrete category to `Type u`. -/ diff --git a/Mathlib/CategoryTheory/Filtered/Basic.lean b/Mathlib/CategoryTheory/Filtered/Basic.lean index 28de77ac9e3bb..584411d3326a4 100644 --- a/Mathlib/CategoryTheory/Filtered/Basic.lean +++ b/Mathlib/CategoryTheory/Filtered/Basic.lean @@ -616,6 +616,26 @@ theorem _root_.CategoryTheory.Functor.ranges_directed (F : C ⥤ Type*) (j : C) let ⟨l, li, lk, e⟩ := cospan ij kj refine ⟨⟨l, lk ≫ kj⟩, e ▸ ?_, ?_⟩ <;> simp_rw [F.map_comp] <;> apply Set.range_comp_subset_range +/-- Given a "bowtie" of morphisms +``` + k₁ k₂ + |\ /| + | \/ | + | /\ | + |/ \∣ + vv vv + j₁ j₂ +``` +in a cofiltered category, we can construct an object `s` and two morphisms +from `s` to `k₁` and `k₂`, making the resulting squares commute. +-/ +theorem bowtie {j₁ j₂ k₁ k₂ : C} (f₁ : k₁ ⟶ j₁) (g₁ : k₂ ⟶ j₁) (f₂ : k₁ ⟶ j₂) (g₂ : k₂ ⟶ j₂) : + ∃ (s : C) (α : s ⟶ k₁) (β : s ⟶ k₂), α ≫ f₁ = β ≫ g₁ ∧ α ≫ f₂ = β ≫ g₂ := by + obtain ⟨t, k₁t, k₂t, ht⟩ := cospan f₁ g₁ + obtain ⟨s, ts, hs⟩ := IsCofilteredOrEmpty.cone_maps (k₁t ≫ f₂) (k₂t ≫ g₂) + exact ⟨s, ts ≫ k₁t, ts ≫ k₂t, by simp only [Category.assoc, ht], + by simp only [Category.assoc, hs]⟩ + end AllowEmpty end IsCofiltered diff --git a/Mathlib/CategoryTheory/Functor/OfSequence.lean b/Mathlib/CategoryTheory/Functor/OfSequence.lean index ba70972cf1661..c1f5788cec33b 100644 --- a/Mathlib/CategoryTheory/Functor/OfSequence.lean +++ b/Mathlib/CategoryTheory/Functor/OfSequence.lean @@ -3,7 +3,6 @@ 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.Order.Group.Nat import Mathlib.CategoryTheory.Category.Preorder import Mathlib.CategoryTheory.EqToHom diff --git a/Mathlib/CategoryTheory/GradedObject.lean b/Mathlib/CategoryTheory/GradedObject.lean index b6e2df434c2b9..2bc160aeba95d 100644 --- a/Mathlib/CategoryTheory/GradedObject.lean +++ b/Mathlib/CategoryTheory/GradedObject.lean @@ -316,7 +316,7 @@ lemma hasMap_of_iso (e : X ≅ Y) (p: I → J) [HasMap X p] : HasMap Y p := fun exact hasColimitOfIso α.symm section -variable [X.HasMap p] [Y.HasMap p] [Z.HasMap p] +variable [X.HasMap p] [Y.HasMap p] /-- Given `X : GradedObject I C` and `p : I → J`, `X.mapObj p` is the graded object by `J` which in degree `j` consists of the coproduct of the `X i` such that `p i = j`. -/ diff --git a/Mathlib/CategoryTheory/Groupoid/Discrete.lean b/Mathlib/CategoryTheory/Groupoid/Discrete.lean index ffface4377069..3ce9a350831bf 100644 --- a/Mathlib/CategoryTheory/Groupoid/Discrete.lean +++ b/Mathlib/CategoryTheory/Groupoid/Discrete.lean @@ -12,7 +12,7 @@ import Mathlib.CategoryTheory.DiscreteCategory namespace CategoryTheory -variable {C : Type*} [Category C] +variable {C : Type*} instance : Groupoid (Discrete C) := { inv := fun h ↦ ⟨⟨h.1.1.symm⟩⟩ } diff --git a/Mathlib/CategoryTheory/GuitartExact/Basic.lean b/Mathlib/CategoryTheory/GuitartExact/Basic.lean index cb64500850d99..b697c1ee0f1a1 100644 --- a/Mathlib/CategoryTheory/GuitartExact/Basic.lean +++ b/Mathlib/CategoryTheory/GuitartExact/Basic.lean @@ -128,7 +128,6 @@ abbrev CostructuredArrowDownwards.mk (comm : R.map a ≫ w.app X₁ ≫ B.map b CostructuredArrow.mk (Y := StructuredArrow.mk a) (StructuredArrow.homMk b (by simpa using comm)) -variable (comm : R.map a ≫ w.app X₁ ≫ B.map b = g) variable {w g} lemma StructuredArrowRightwards.mk_surjective diff --git a/Mathlib/CategoryTheory/Idempotents/Karoubi.lean b/Mathlib/CategoryTheory/Idempotents/Karoubi.lean index 1c0f0936e00c6..d4b4fc8a4f69e 100644 --- a/Mathlib/CategoryTheory/Idempotents/Karoubi.lean +++ b/Mathlib/CategoryTheory/Idempotents/Karoubi.lean @@ -111,7 +111,7 @@ theorem comp_f {P Q R : Karoubi C} (f : P ⟶ Q) (g : Q ⟶ R) : (f ≫ g).f = f @[simp] theorem id_f {P : Karoubi C} : Hom.f (𝟙 P) = P.p := rfl -@[deprecated (since := "2024-07-15")] +@[deprecated "No deprecation message was provided." (since := "2024-07-15")] theorem id_eq {P : Karoubi C} : 𝟙 P = ⟨P.p, by repeat' rw [P.idem]⟩ := rfl /-- It is possible to coerce an object of `C` into an object of `Karoubi C`. diff --git a/Mathlib/CategoryTheory/Limits/Constructions/EventuallyConstant.lean b/Mathlib/CategoryTheory/Limits/Constructions/EventuallyConstant.lean new file mode 100644 index 0000000000000..9ae75d85d62ae --- /dev/null +++ b/Mathlib/CategoryTheory/Limits/Constructions/EventuallyConstant.lean @@ -0,0 +1,260 @@ +/- +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.Filtered.Basic +import Mathlib.CategoryTheory.Limits.HasLimits + +/-! +# Limits of eventually constant functors + +If `F : J ⥤ C` is a functor from a cofiltered category, and `j : J`, +we introduce a property `F.IsEventuallyConstantTo j` which says +that for any `f : i ⟶ j`, the induced morphism `F.map f` is an isomorphism. +Under this assumption, it is shown that `F` admits `F.obj j` as a limit +(`Functor.IsEventuallyConstantTo.isLimitCone`). + +A typeclass `Cofiltered.IsEventuallyConstant` is also introduced, and +the dual results for filtered categories and colimits are also obtained. + +-/ + +namespace CategoryTheory + +open Category Limits + +variable {J C : Type*} [Category J] [Category C] (F : J ⥤ C) + +namespace Functor + +/-- A functor `F : J ⥤ C` is eventually constant to `j : J` if +for any map `f : i ⟶ j`, the induced morphism `F.map f` is an isomorphism. +If `J` is cofiltered, this implies `F` has a limit. -/ +def IsEventuallyConstantTo (j : J) : Prop := + ∀ ⦃i : J⦄ (f : i ⟶ j), IsIso (F.map f) + +/-- A functor `F : J ⥤ C` is eventually constant from `i : J` if +for any map `f : i ⟶ j`, the induced morphism `F.map f` is an isomorphism. +If `J` is filtered, this implies `F` has a colimit. -/ +def IsEventuallyConstantFrom (i : J) : Prop := + ∀ ⦃j : J⦄ (f : i ⟶ j), IsIso (F.map f) + +namespace IsEventuallyConstantTo + +variable {F} {i₀ : J} (h : F.IsEventuallyConstantTo i₀) + +include h + +lemma isIso_map {i j : J} (φ : i ⟶ j) (π : j ⟶ i₀) : IsIso (F.map φ) := by + have := h π + have := h (φ ≫ π) + exact IsIso.of_isIso_fac_right (F.map_comp φ π).symm + +lemma precomp {j : J} (f : j ⟶ i₀) : F.IsEventuallyConstantTo j := + fun _ φ ↦ h.isIso_map φ f + +section + +variable {i j : J} (φ : i ⟶ j) (hφ : Nonempty (j ⟶ i₀)) + +/-- The isomorphism `F.obj i ≅ F.obj j` induced by `φ : i ⟶ j`, +when `h : F.IsEventuallyConstantTo i₀` and there exists a map `j ⟶ i₀`. -/ +@[simps! hom] +noncomputable def isoMap : F.obj i ≅ F.obj j := + have := h.isIso_map φ hφ.some + asIso (F.map φ) + +@[reassoc (attr := simp)] +lemma isoMap_hom_inv_id : F.map φ ≫ (h.isoMap φ hφ).inv = 𝟙 _ := + (h.isoMap φ hφ).hom_inv_id + +@[reassoc (attr := simp)] +lemma isoMap_inv_hom_id : (h.isoMap φ hφ).inv ≫ F.map φ = 𝟙 _ := + (h.isoMap φ hφ).inv_hom_id + +end + +variable [IsCofiltered J] +open IsCofiltered + +/-- Auxiliary definition for `IsEventuallyConstantTo.cone`. -/ +noncomputable def coneπApp (j : J) : F.obj i₀ ⟶ F.obj j := + (h.isoMap (minToLeft i₀ j) ⟨𝟙 _⟩).inv ≫ F.map (minToRight i₀ j) + +lemma coneπApp_eq (j j' : J) (α : j' ⟶ i₀) (β : j' ⟶ j) : + h.coneπApp j = (h.isoMap α ⟨𝟙 _⟩).inv ≫ F.map β := by + obtain ⟨s, γ, δ, h₁, h₂⟩ := IsCofiltered.bowtie + (IsCofiltered.minToRight i₀ j) β (IsCofiltered.minToLeft i₀ j) α + dsimp [coneπApp] + rw [← cancel_epi ((h.isoMap α ⟨𝟙 _⟩).hom), isoMap_hom, isoMap_hom_inv_id_assoc, + ← cancel_epi (h.isoMap δ ⟨α⟩).hom, isoMap_hom, + ← F.map_comp δ β, ← h₁, F.map_comp, ← F.map_comp_assoc, ← h₂, F.map_comp_assoc, + isoMap_hom_inv_id_assoc] + +@[simp] +lemma coneπApp_eq_id : h.coneπApp i₀ = 𝟙 _ := by + rw [h.coneπApp_eq i₀ i₀ (𝟙 _) (𝟙 _), h.isoMap_inv_hom_id] + +/-- Given `h : F.IsEventuallyConstantTo i₀`, this is the (limit) cone for `F` whose +point is `F.obj i₀`. -/ +@[simps] +noncomputable def cone : Cone F where + pt := F.obj i₀ + π := + { app := h.coneπApp + naturality := fun j j' φ ↦ by + dsimp + rw [id_comp] + let i := IsCofiltered.min i₀ j + let α : i ⟶ i₀ := IsCofiltered.minToLeft _ _ + let β : i ⟶ j := IsCofiltered.minToRight _ _ + rw [h.coneπApp_eq j _ α β, assoc, h.coneπApp_eq j' _ α (β ≫ φ), map_comp] } + +/-- When `h : F.IsEventuallyConstantTo i₀`, the limit of `F` exists and is `F.obj i₀`. -/ +def isLimitCone : IsLimit h.cone where + lift s := s.π.app i₀ + fac s j := by + dsimp [coneπApp] + rw [← s.w (IsCofiltered.minToLeft i₀ j), ← s.w (IsCofiltered.minToRight i₀ j), assoc, + isoMap_hom_inv_id_assoc] + uniq s m hm := by simp only [← hm i₀, cone_π_app, coneπApp_eq_id, cone_pt, comp_id] + +lemma hasLimit : HasLimit F := ⟨_, h.isLimitCone⟩ + +lemma isIso_π_of_isLimit {c : Cone F} (hc : IsLimit c) : + IsIso (c.π.app i₀) := by + simp only [← IsLimit.conePointUniqueUpToIso_hom_comp hc h.isLimitCone i₀, + cone_π_app, coneπApp_eq_id, cone_pt, comp_id] + infer_instance + +/-- More general version of `isIso_π_of_isLimit`. -/ +lemma isIso_π_of_isLimit' {c : Cone F} (hc : IsLimit c) (j : J) (π : j ⟶ i₀) : + IsIso (c.π.app j) := + (h.precomp π).isIso_π_of_isLimit hc + +end IsEventuallyConstantTo + +namespace IsEventuallyConstantFrom + +variable {F} {i₀ : J} (h : F.IsEventuallyConstantFrom i₀) + +include h + +lemma isIso_map {i j : J} (φ : i ⟶ j) (ι : i₀ ⟶ i) : IsIso (F.map φ) := by + have := h ι + have := h (ι ≫ φ) + exact IsIso.of_isIso_fac_left (F.map_comp ι φ).symm + +lemma postcomp {j : J} (f : i₀ ⟶ j) : F.IsEventuallyConstantFrom j := + fun _ φ ↦ h.isIso_map φ f + +section + +variable {i j : J} (φ : i ⟶ j) (hφ : Nonempty (i₀ ⟶ i)) + +/-- The isomorphism `F.obj i ≅ F.obj j` induced by `φ : i ⟶ j`, +when `h : F.IsEventuallyConstantFrom i₀` and there exists a map `i₀ ⟶ i`. -/ +@[simps! hom] +noncomputable def isoMap : F.obj i ≅ F.obj j := + have := h.isIso_map φ hφ.some + asIso (F.map φ) + +@[reassoc (attr := simp)] +lemma isoMap_hom_inv_id : F.map φ ≫ (h.isoMap φ hφ).inv = 𝟙 _ := + (h.isoMap φ hφ).hom_inv_id + +@[reassoc (attr := simp)] +lemma isoMap_inv_hom_id : (h.isoMap φ hφ).inv ≫ F.map φ = 𝟙 _ := + (h.isoMap φ hφ).inv_hom_id + +end + +variable [IsFiltered J] +open IsFiltered + +/-- Auxiliary definition for `IsEventuallyConstantFrom.cocone`. -/ +noncomputable def coconeιApp (j : J) : F.obj j ⟶ F.obj i₀ := + F.map (rightToMax i₀ j) ≫ (h.isoMap (leftToMax i₀ j) ⟨𝟙 _⟩).inv + +lemma coconeιApp_eq (j j' : J) (α : j ⟶ j') (β : i₀ ⟶ j') : + h.coconeιApp j = F.map α ≫ (h.isoMap β ⟨𝟙 _⟩).inv := by + obtain ⟨s, γ, δ, h₁, h₂⟩ := IsFiltered.bowtie + (IsFiltered.leftToMax i₀ j) β (IsFiltered.rightToMax i₀ j) α + dsimp [coconeιApp] + rw [← cancel_mono ((h.isoMap β ⟨𝟙 _⟩).hom), assoc, assoc, isoMap_hom, isoMap_inv_hom_id, + comp_id, ← cancel_mono (h.isoMap δ ⟨β⟩).hom, isoMap_hom, assoc, assoc, ← F.map_comp α δ, + ← h₂, F.map_comp, ← F.map_comp β δ, ← h₁, F.map_comp, isoMap_inv_hom_id_assoc] + +@[simp] +lemma coconeιApp_eq_id : h.coconeιApp i₀ = 𝟙 _ := by + rw [h.coconeιApp_eq i₀ i₀ (𝟙 _) (𝟙 _), h.isoMap_hom_inv_id] + +/-- Given `h : F.IsEventuallyConstantFrom i₀`, this is the (limit) cocone for `F` whose +point is `F.obj i₀`. -/ +@[simps] +noncomputable def cocone : Cocone F where + pt := F.obj i₀ + ι := + { app := h.coconeιApp + naturality := fun j j' φ ↦ by + dsimp + rw [comp_id] + let i := IsFiltered.max i₀ j' + let α : i₀ ⟶ i := IsFiltered.leftToMax _ _ + let β : j' ⟶ i := IsFiltered.rightToMax _ _ + rw [h.coconeιApp_eq j' _ β α, h.coconeιApp_eq j _ (φ ≫ β) α, map_comp, assoc] } + +/-- When `h : F.IsEventuallyConstantFrom i₀`, the colimit of `F` exists and is `F.obj i₀`. -/ +def isColimitCocone : IsColimit h.cocone where + desc s := s.ι.app i₀ + fac s j := by + dsimp [coconeιApp] + rw [← s.w (IsFiltered.rightToMax i₀ j), ← s.w (IsFiltered.leftToMax i₀ j), assoc, + isoMap_inv_hom_id_assoc] + uniq s m hm := by simp only [← hm i₀, cocone_ι_app, coconeιApp_eq_id, id_comp] + +lemma hasColimit : HasColimit F := ⟨_, h.isColimitCocone⟩ + +lemma isIso_ι_of_isColimit {c : Cocone F} (hc : IsColimit c) : + IsIso (c.ι.app i₀) := by + simp only [← IsColimit.comp_coconePointUniqueUpToIso_inv hc h.isColimitCocone i₀, + cocone_ι_app, coconeιApp_eq_id, id_comp] + infer_instance + +/-- More general version of `isIso_ι_of_isColimit`. -/ +lemma isIso_ι_of_isColimit' {c : Cocone F} (hc : IsColimit c) (j : J) (ι : i₀ ⟶ j) : + IsIso (c.ι.app j) := + (h.postcomp ι).isIso_ι_of_isColimit hc + +end IsEventuallyConstantFrom + +end Functor + +namespace IsCofiltered + +/-- A functor `F : J ⥤ C` from a cofiltered category is eventually constant if there +exists `j : J`, such that for any `f : i ⟶ j`, the induced map `F.map f` is an isomorphism. -/ +class IsEventuallyConstant : Prop where + exists_isEventuallyConstantTo : ∃ (j : J), F.IsEventuallyConstantTo j + +instance [hF : IsEventuallyConstant F] [IsCofiltered J] : HasLimit F := by + obtain ⟨j, h⟩ := hF.exists_isEventuallyConstantTo + exact h.hasLimit + +end IsCofiltered + +namespace IsFiltered + +/-- A functor `F : J ⥤ C` from a filtered category is eventually constant if there +exists `i : J`, such that for any `f : i ⟶ j`, the induced map `F.map f` is an isomorphism. -/ +class IsEventuallyConstant : Prop where + exists_isEventuallyConstantFrom : ∃ (i : J), F.IsEventuallyConstantFrom i + +instance [hF : IsEventuallyConstant F] [IsFiltered J] : HasColimit F := by + obtain ⟨j, h⟩ := hF.exists_isEventuallyConstantFrom + exact h.hasColimit + +end IsFiltered + +end CategoryTheory diff --git a/Mathlib/CategoryTheory/Limits/Creates.lean b/Mathlib/CategoryTheory/Limits/Creates.lean index 148eafbe8efa1..9769ea2520000 100644 --- a/Mathlib/CategoryTheory/Limits/Creates.lean +++ b/Mathlib/CategoryTheory/Limits/Creates.lean @@ -332,7 +332,7 @@ instance (priority := 100) preservesLimit_of_createsLimit_and_hasLimit (K : J ((liftedLimitMapsToOriginal (limit.isLimit _)).symm ≪≫ (Cones.functoriality K F).mapIso ((liftedLimitIsLimit (limit.isLimit _)).uniqueUpToIso t))⟩ -@[deprecated (since := "2024-11-19")] +@[deprecated "No deprecation message was provided." (since := "2024-11-19")] lemma preservesLimitOfCreatesLimitAndHasLimit (K : J ⥤ C) (F : C ⥤ D) [CreatesLimit K F] [HasLimit (K ⋙ F)] : PreservesLimit K F := preservesLimit_of_createsLimit_and_hasLimit _ _ @@ -342,7 +342,7 @@ lemma preservesLimitOfCreatesLimitAndHasLimit (K : J ⥤ C) (F : C ⥤ D) instance (priority := 100) preservesLimitOfShape_of_createsLimitsOfShape_and_hasLimitsOfShape (F : C ⥤ D) [CreatesLimitsOfShape J F] [HasLimitsOfShape J D] : PreservesLimitsOfShape J F where -@[deprecated (since := "2024-11-19")] +@[deprecated "No deprecation message was provided." (since := "2024-11-19")] lemma preservesLimitOfShapeOfCreatesLimitsOfShapeAndHasLimitsOfShape (F : C ⥤ D) [CreatesLimitsOfShape J F] [HasLimitsOfShape J D] : PreservesLimitsOfShape J F := @@ -354,7 +354,7 @@ instance (priority := 100) preservesLimits_of_createsLimits_and_hasLimits (F : C [CreatesLimitsOfSize.{w, w'} F] [HasLimitsOfSize.{w, w'} D] : PreservesLimitsOfSize.{w, w'} F where -@[deprecated (since := "2024-11-19")] +@[deprecated "No deprecation message was provided." (since := "2024-11-19")] lemma preservesLimitsOfCreatesLimitsAndHasLimits (F : C ⥤ D) [CreatesLimitsOfSize.{w, w'} F] [HasLimitsOfSize.{w, w'} D] : PreservesLimitsOfSize.{w, w'} F := @@ -466,7 +466,7 @@ instance (priority := 100) preservesColimit_of_createsColimit_and_hasColimit (K (Cocones.functoriality K F).mapIso ((liftedColimitIsColimit (colimit.isColimit _)).uniqueUpToIso t))⟩ -@[deprecated (since := "2024-11-19")] +@[deprecated "No deprecation message was provided." (since := "2024-11-19")] lemma preservesColimitOfCreatesColimitAndHasColimit (K : J ⥤ C) (F : C ⥤ D) [CreatesColimit K F] [HasColimit (K ⋙ F)] : PreservesColimit K F := preservesColimit_of_createsColimit_and_hasColimit _ _ @@ -477,7 +477,7 @@ instance (priority := 100) preservesColimitOfShape_of_createsColimitsOfShape_and (F : C ⥤ D) [CreatesColimitsOfShape J F] [HasColimitsOfShape J D] : PreservesColimitsOfShape J F where -@[deprecated (since := "2024-11-19")] +@[deprecated "No deprecation message was provided." (since := "2024-11-19")] lemma preservesColimitOfShapeOfCreatesColimitsOfShapeAndHasColimitsOfShape (F : C ⥤ D) [CreatesColimitsOfShape J F] [HasColimitsOfShape J D] : PreservesColimitsOfShape J F := @@ -489,7 +489,7 @@ instance (priority := 100) preservesColimits_of_createsColimits_and_hasColimits [CreatesColimitsOfSize.{w, w'} F] [HasColimitsOfSize.{w, w'} D] : PreservesColimitsOfSize.{w, w'} F where -@[deprecated (since := "2024-11-19")] +@[deprecated "No deprecation message was provided." (since := "2024-11-19")] lemma preservesColimitsOfCreatesColimitsAndHasColimits (F : C ⥤ D) [CreatesColimitsOfSize.{w, w'} F] [HasColimitsOfSize.{w, w'} D] : PreservesColimitsOfSize.{w, w'} F := diff --git a/Mathlib/CategoryTheory/Limits/Final.lean b/Mathlib/CategoryTheory/Limits/Final.lean index 69444f0842058..6719a13bc510a 100644 --- a/Mathlib/CategoryTheory/Limits/Final.lean +++ b/Mathlib/CategoryTheory/Limits/Final.lean @@ -65,7 +65,7 @@ Dualise condition 3 above and the implications 2 ⇒ 3 and 3 ⇒ 1 to initial fu noncomputable section -universe v v₁ v₂ v₃ u₁ u₂ u₃ +universe v v₁ v₂ v₃ v₄ u₁ u₂ u₃ u₄ namespace CategoryTheory @@ -305,6 +305,27 @@ def colimitCoconeComp (t : ColimitCocone G) : ColimitCocone (F ⋙ G) where instance (priority := 100) comp_hasColimit [HasColimit G] : HasColimit (F ⋙ G) := HasColimit.mk (colimitCoconeComp F (getColimitCocone G)) +instance (priority := 100) comp_preservesColimit {B : Type u₄} [Category.{v₄} B] {H : E ⥤ B} + [PreservesColimit G H] : PreservesColimit (F ⋙ G) H where + preserves {c} hc := by + refine ⟨isColimitExtendCoconeEquiv (G := G ⋙ H) F (H.mapCocone c) ?_⟩ + let hc' := isColimitOfPreserves H ((isColimitExtendCoconeEquiv F c).symm hc) + exact IsColimit.ofIsoColimit hc' (Cocones.ext (Iso.refl _) (by simp)) + +instance (priority := 100) comp_reflectsColimit {B : Type u₄} [Category.{v₄} B] {H : E ⥤ B} + [ReflectsColimit G H] : ReflectsColimit (F ⋙ G) H where + reflects {c} hc := by + refine ⟨isColimitExtendCoconeEquiv F _ (isColimitOfReflects H ?_)⟩ + let hc' := (isColimitExtendCoconeEquiv (G := G ⋙ H) F _).symm hc + exact IsColimit.ofIsoColimit hc' (Cocones.ext (Iso.refl _) (by simp)) + +instance (priority := 100) compCreatesColimit {B : Type u₄} [Category.{v₄} B] {H : E ⥤ B} + [CreatesColimit G H] : CreatesColimit (F ⋙ G) H where + lifts {c} hc := by + refine ⟨(liftColimit ((isColimitExtendCoconeEquiv F (G := G ⋙ H) _).symm hc)).whisker F, ?_⟩ + let i := liftedColimitMapsToOriginal ((isColimitExtendCoconeEquiv F (G := G ⋙ H) _).symm hc) + exact (Cocones.whiskering F).mapIso i ≪≫ ((coconesEquiv F (G ⋙ H)).unitIso.app _).symm + instance colimit_pre_isIso [HasColimit G] : IsIso (colimit.pre G F) := by rw [colimit.pre_eq (colimitCoconeComp F (getColimitCocone G)) (getColimitCocone G)] erw [IsColimit.desc_self] @@ -361,10 +382,51 @@ We can't make this an instance, because `F` is not determined by the goal. theorem hasColimit_of_comp [HasColimit (F ⋙ G)] : HasColimit G := HasColimit.mk (colimitCoconeOfComp F (getColimitCocone (F ⋙ G))) +theorem preservesColimit_of_comp {B : Type u₄} [Category.{v₄} B] {H : E ⥤ B} + [PreservesColimit (F ⋙ G) H] : PreservesColimit G H where + preserves {c} hc := by + refine ⟨isColimitWhiskerEquiv F _ ?_⟩ + let hc' := isColimitOfPreserves H ((isColimitWhiskerEquiv F _).symm hc) + exact IsColimit.ofIsoColimit hc' (Cocones.ext (Iso.refl _) (by simp)) + +theorem reflectsColimit_of_comp {B : Type u₄} [Category.{v₄} B] {H : E ⥤ B} + [ReflectsColimit (F ⋙ G) H] : ReflectsColimit G H where + reflects {c} hc := by + refine ⟨isColimitWhiskerEquiv F _ (isColimitOfReflects H ?_)⟩ + let hc' := (isColimitWhiskerEquiv F _).symm hc + exact IsColimit.ofIsoColimit hc' (Cocones.ext (Iso.refl _) (by simp)) + +/-- If `F` is final and `F ⋙ G` creates colimits of `H`, then so does `G`. -/ +def createsColimitOfComp {B : Type u₄} [Category.{v₄} B] {H : E ⥤ B} + [CreatesColimit (F ⋙ G) H] : CreatesColimit G H where + reflects := (reflectsColimit_of_comp F).reflects + lifts {c} hc := by + refine ⟨(extendCocone (F := F)).obj (liftColimit ((isColimitWhiskerEquiv F _).symm hc)), ?_⟩ + let i := liftedColimitMapsToOriginal (K := (F ⋙ G)) ((isColimitWhiskerEquiv F _).symm hc) + refine ?_ ≪≫ ((extendCocone (F := F)).mapIso i) ≪≫ ((coconesEquiv F (G ⋙ H)).counitIso.app _) + exact Cocones.ext (Iso.refl _) + include F in theorem hasColimitsOfShape_of_final [HasColimitsOfShape C E] : HasColimitsOfShape D E where has_colimit := fun _ => hasColimit_of_comp F +include F in +theorem preservesColimitsOfShape_of_final {B : Type u₄} [Category.{v₄} B] (H : E ⥤ B) + [PreservesColimitsOfShape C H] : PreservesColimitsOfShape D H where + preservesColimit := preservesColimit_of_comp F + +include F in +theorem reflectsColimitsOfShape_of_final {B : Type u₄} [Category.{v₄} B] (H : E ⥤ B) + [ReflectsColimitsOfShape C H] : ReflectsColimitsOfShape D H where + reflectsColimit := reflectsColimit_of_comp F + +include F in +/-- If `H` creates colimits of shape `C` and `F : C ⥤ D` is final, then `H` creates colimits of +shape `D`. -/ +def createsColimitsOfShapeOfFinal {B : Type u₄} [Category.{v₄} B] (H : E ⥤ B) + [CreatesColimitsOfShape C H] : CreatesColimitsOfShape D H where + CreatesColimit := createsColimitOfComp F + end Final end ArbitraryUniverse @@ -592,6 +654,27 @@ def limitConeComp (t : LimitCone G) : LimitCone (F ⋙ G) where instance (priority := 100) comp_hasLimit [HasLimit G] : HasLimit (F ⋙ G) := HasLimit.mk (limitConeComp F (getLimitCone G)) +instance (priority := 100) comp_preservesLimit {B : Type u₄} [Category.{v₄} B] {H : E ⥤ B} + [PreservesLimit G H] : PreservesLimit (F ⋙ G) H where + preserves {c} hc := by + refine ⟨isLimitExtendConeEquiv (G := G ⋙ H) F (H.mapCone c) ?_⟩ + let hc' := isLimitOfPreserves H ((isLimitExtendConeEquiv F c).symm hc) + exact IsLimit.ofIsoLimit hc' (Cones.ext (Iso.refl _) (by simp)) + +instance (priority := 100) comp_reflectsLimit {B : Type u₄} [Category.{v₄} B] {H : E ⥤ B} + [ReflectsLimit G H] : ReflectsLimit (F ⋙ G) H where + reflects {c} hc := by + refine ⟨isLimitExtendConeEquiv F _ (isLimitOfReflects H ?_)⟩ + let hc' := (isLimitExtendConeEquiv (G := G ⋙ H) F _).symm hc + exact IsLimit.ofIsoLimit hc' (Cones.ext (Iso.refl _) (by simp)) + +instance (priority := 100) compCreatesLimit {B : Type u₄} [Category.{v₄} B] {H : E ⥤ B} + [CreatesLimit G H] : CreatesLimit (F ⋙ G) H where + lifts {c} hc := by + refine ⟨(liftLimit ((isLimitExtendConeEquiv F (G := G ⋙ H) _).symm hc)).whisker F, ?_⟩ + let i := liftedLimitMapsToOriginal ((isLimitExtendConeEquiv F (G := G ⋙ H) _).symm hc) + exact (Cones.whiskering F).mapIso i ≪≫ ((conesEquiv F (G ⋙ H)).unitIso.app _).symm + instance limit_pre_isIso [HasLimit G] : IsIso (limit.pre G F) := by rw [limit.pre_eq (limitConeComp F (getLimitCone G)) (getLimitCone G)] erw [IsLimit.lift_self] @@ -637,10 +720,51 @@ We can't make this an instance, because `F` is not determined by the goal. theorem hasLimit_of_comp [HasLimit (F ⋙ G)] : HasLimit G := HasLimit.mk (limitConeOfComp F (getLimitCone (F ⋙ G))) +theorem preservesLimit_of_comp {B : Type u₄} [Category.{v₄} B] {H : E ⥤ B} + [PreservesLimit (F ⋙ G) H] : PreservesLimit G H where + preserves {c} hc := by + refine ⟨isLimitWhiskerEquiv F _ ?_⟩ + let hc' := isLimitOfPreserves H ((isLimitWhiskerEquiv F _).symm hc) + exact IsLimit.ofIsoLimit hc' (Cones.ext (Iso.refl _) (by simp)) + +theorem reflectsLimit_of_comp {B : Type u₄} [Category.{v₄} B] {H : E ⥤ B} + [ReflectsLimit (F ⋙ G) H] : ReflectsLimit G H where + reflects {c} hc := by + refine ⟨isLimitWhiskerEquiv F _ (isLimitOfReflects H ?_)⟩ + let hc' := (isLimitWhiskerEquiv F _).symm hc + exact IsLimit.ofIsoLimit hc' (Cones.ext (Iso.refl _) (by simp)) + +/-- If `F` is initial and `F ⋙ G` creates limits of `H`, then so does `G`. -/ +def createsLimitOfComp {B : Type u₄} [Category.{v₄} B] {H : E ⥤ B} + [CreatesLimit (F ⋙ G) H] : CreatesLimit G H where + reflects := (reflectsLimit_of_comp F).reflects + lifts {c} hc := by + refine ⟨(extendCone (F := F)).obj (liftLimit ((isLimitWhiskerEquiv F _).symm hc)), ?_⟩ + let i := liftedLimitMapsToOriginal (K := (F ⋙ G)) ((isLimitWhiskerEquiv F _).symm hc) + refine ?_ ≪≫ ((extendCone (F := F)).mapIso i) ≪≫ ((conesEquiv F (G ⋙ H)).counitIso.app _) + exact Cones.ext (Iso.refl _) + include F in theorem hasLimitsOfShape_of_initial [HasLimitsOfShape C E] : HasLimitsOfShape D E where has_limit := fun _ => hasLimit_of_comp F +include F in +theorem preservesLimitsOfShape_of_initial {B : Type u₄} [Category.{v₄} B] (H : E ⥤ B) + [PreservesLimitsOfShape C H] : PreservesLimitsOfShape D H where + preservesLimit := preservesLimit_of_comp F + +include F in +theorem reflectsLimitsOfShape_of_initial {B : Type u₄} [Category.{v₄} B] (H : E ⥤ B) + [ReflectsLimitsOfShape C H] : ReflectsLimitsOfShape D H where + reflectsLimit := reflectsLimit_of_comp F + +include F in +/-- If `H` creates limits of shape `C` and `F : C ⥤ D` is initial, then `H` creates limits of shape +`D`. -/ +def createsLimitsOfShapeOfInitial {B : Type u₄} [Category.{v₄} B] (H : E ⥤ B) + [CreatesLimitsOfShape C H] : CreatesLimitsOfShape D H where + CreatesLimit := createsLimitOfComp F + end Initial section diff --git a/Mathlib/CategoryTheory/Limits/FunctorCategory/Basic.lean b/Mathlib/CategoryTheory/Limits/FunctorCategory/Basic.lean index 357916b1fe01e..603001e9e6ce6 100644 --- a/Mathlib/CategoryTheory/Limits/FunctorCategory/Basic.lean +++ b/Mathlib/CategoryTheory/Limits/FunctorCategory/Basic.lean @@ -362,7 +362,7 @@ lemma preservesLimit_of_evaluation (F : D ⥤ K ⥤ C) (G : J ⥤ D) change IsLimit ((F ⋙ (evaluation K C).obj X).mapCone c) exact isLimitOfPreserves _ hc⟩⟩ -@[deprecated (since := "2024-11-19")] +@[deprecated "No deprecation message was provided." (since := "2024-11-19")] lemma preservesLimitOfEvaluation (F : D ⥤ K ⥤ C) (G : J ⥤ D) (H : ∀ k : K, PreservesLimit G (F ⋙ (evaluation K C).obj k : D ⥤ C)) : PreservesLimit G F := @@ -374,7 +374,7 @@ lemma preservesLimitsOfShape_of_evaluation (F : D ⥤ K ⥤ C) (J : Type*) [Cate PreservesLimitsOfShape J F := ⟨fun {G} => preservesLimit_of_evaluation F G fun _ => PreservesLimitsOfShape.preservesLimit⟩ -@[deprecated (since := "2024-11-19")] +@[deprecated "No deprecation message was provided." (since := "2024-11-19")] lemma preservesLimitsOfShapeOfEvaluation (F : D ⥤ K ⥤ C) (J : Type*) [Category J] (H : ∀ k : K, PreservesLimitsOfShape J (F ⋙ (evaluation K C).obj k)) : PreservesLimitsOfShape J F := @@ -387,7 +387,7 @@ lemma preservesLimits_of_evaluation (F : D ⥤ K ⥤ C) ⟨fun {L} _ => preservesLimitsOfShape_of_evaluation F L fun _ => PreservesLimitsOfSize.preservesLimitsOfShape⟩ -@[deprecated (since := "2024-11-19")] +@[deprecated "No deprecation message was provided." (since := "2024-11-19")] lemma preservesLimitsOfEvaluation (F : D ⥤ K ⥤ C) (H : ∀ k : K, PreservesLimitsOfSize.{w', w} (F ⋙ (evaluation K C).obj k)) : PreservesLimitsOfSize.{w', w} F := @@ -412,7 +412,7 @@ lemma preservesColimit_of_evaluation (F : D ⥤ K ⥤ C) (G : J ⥤ D) change IsColimit ((F ⋙ (evaluation K C).obj X).mapCocone c) exact isColimitOfPreserves _ hc⟩⟩ -@[deprecated (since := "2024-11-19")] +@[deprecated "No deprecation message was provided." (since := "2024-11-19")] lemma preservesColimitOfEvaluation (F : D ⥤ K ⥤ C) (G : J ⥤ D) (H : ∀ k, PreservesColimit G (F ⋙ (evaluation K C).obj k)) : PreservesColimit G F := preservesColimit_of_evaluation _ _ H diff --git a/Mathlib/CategoryTheory/Limits/MorphismProperty.lean b/Mathlib/CategoryTheory/Limits/MorphismProperty.lean index 8f764982cf362..b4bb842c72dd2 100644 --- a/Mathlib/CategoryTheory/Limits/MorphismProperty.lean +++ b/Mathlib/CategoryTheory/Limits/MorphismProperty.lean @@ -134,7 +134,7 @@ instance [P.ContainsIdentities] : HasTerminal (P.Over ⊤ X) := /-- If `P` is stable under composition, base change and satisfies post-cancellation, `Over.forget P ⊤ X` creates pullbacks. -/ -noncomputable def createsLimitsOfShape_walkingCospan [HasPullbacks T] +noncomputable instance createsLimitsOfShape_walkingCospan [HasPullbacks T] [P.IsStableUnderComposition] [P.IsStableUnderBaseChange] [P.HasOfPostcompProperty P] : CreatesLimitsOfShape WalkingCospan (Over.forget P ⊤ X) := haveI : HasLimitsOfShape WalkingCospan (Comma (𝟭 T) (Functor.fromPUnit X)) := diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Countable.lean b/Mathlib/CategoryTheory/Limits/Shapes/Countable.lean index a50342b46d933..6f0db0a360ddb 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Countable.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Countable.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Dagur Asgeirsson -/ import Mathlib.CategoryTheory.Limits.Final -import Mathlib.CategoryTheory.Limits.Shapes.FiniteLimits +import Mathlib.CategoryTheory.Limits.Shapes.FiniteProducts import Mathlib.CategoryTheory.Countable import Mathlib.Data.Countable.Defs /-! @@ -52,6 +52,29 @@ instance [Category.{v} J] [CountableCategory J] [HasCountableLimits C] : HasLimi have : HasLimitsOfShape (HomAsType J) C := HasCountableLimits.out (HomAsType J) hasLimitsOfShape_of_equivalence (homAsTypeEquiv J) +/-- A category has countable products if it has all products indexed by countable types. -/ +class HasCountableProducts where + out (J : Type) [Countable J] : HasProductsOfShape J C + +instance [HasCountableProducts C] : HasProductsOfShape J C := + have : Countable (Shrink.{0} J) := Countable.of_equiv _ (equivShrink.{0} J) + have : HasLimitsOfShape (Discrete (Shrink.{0} J)) C := HasCountableProducts.out _ + hasLimitsOfShape_of_equivalence (Discrete.equivalence (equivShrink.{0} J)).symm + +instance (priority := 100) hasCountableProducts_of_hasProducts [HasProducts C] : + HasCountableProducts C where + out _ := + have : HasProducts.{0} C := has_smallest_products_of_hasProducts + inferInstance + +instance (priority := 100) hasCountableProducts_of_hasCountableLimits [HasCountableLimits C] : + HasCountableProducts C where + out _ := inferInstance + +instance (priority := 100) hasFiniteProducts_of_hasCountableProducts [HasCountableProducts C] : + HasFiniteProducts C where + out _ := inferInstance + /-- A category has all countable colimits if every functor `J ⥤ C` with a `CountableCategory J` instance and `J : Type` has a colimit. @@ -74,8 +97,81 @@ instance [Category.{v} J] [CountableCategory J] [HasCountableColimits C] : HasCo have : HasColimitsOfShape (HomAsType J) C := HasCountableColimits.out (HomAsType J) hasColimitsOfShape_of_equivalence (homAsTypeEquiv J) +/-- A category has countable coproducts if it has all coproducts indexed by countable types. -/ +class HasCountableCoproducts where + out (J : Type) [Countable J] : HasCoproductsOfShape J C + +instance (priority := 100) hasCountableCoproducts_of_hasCoproducts [HasCoproducts C] : + HasCountableCoproducts C where + out _ := + have : HasCoproducts.{0} C := has_smallest_coproducts_of_hasCoproducts + inferInstance + +instance [HasCountableCoproducts C] : HasCoproductsOfShape J C := + have : Countable (Shrink.{0} J) := Countable.of_equiv _ (equivShrink.{0} J) + have : HasColimitsOfShape (Discrete (Shrink.{0} J)) C := HasCountableCoproducts.out _ + hasColimitsOfShape_of_equivalence (Discrete.equivalence (equivShrink.{0} J)).symm + +instance (priority := 100) hasCountableCoproducts_of_hasCountableColimits [HasCountableColimits C] : + HasCountableCoproducts C where + out _ := inferInstance + +instance (priority := 100) hasFiniteCoproducts_of_hasCountableCoproducts + [HasCountableCoproducts C] : HasFiniteCoproducts C where + out _ := inferInstance + section Preorder +namespace IsFiltered + +attribute [local instance] IsFiltered.nonempty + +variable {C} [Preorder J] [IsFiltered J] + +/-- The object part of the initial functor `ℕᵒᵖ ⥤ J` -/ +noncomputable def sequentialFunctor_obj : ℕ → J := fun + | .zero => (exists_surjective_nat _).choose 0 + | .succ n => (IsFilteredOrEmpty.cocone_objs ((exists_surjective_nat _).choose n) + (sequentialFunctor_obj n)).choose + +theorem sequentialFunctor_map : Monotone (sequentialFunctor_obj J) := + monotone_nat_of_le_succ fun n ↦ + leOfHom (IsFilteredOrEmpty.cocone_objs ((exists_surjective_nat _).choose n) + (sequentialFunctor_obj J n)).choose_spec.choose_spec.choose + +/-- +The initial functor `ℕᵒᵖ ⥤ J`, which allows us to turn cofiltered limits over countable preorders +into sequential limits. +-/ +noncomputable def sequentialFunctor : ℕ ⥤ J where + obj n := sequentialFunctor_obj J n + map h := homOfLE (sequentialFunctor_map J (leOfHom h)) + +theorem sequentialFunctor_final_aux (j : J) : ∃ (n : ℕ), j ≤ sequentialFunctor_obj J n := by + obtain ⟨m, h⟩ := (exists_surjective_nat _).choose_spec j + refine ⟨m + 1, ?_⟩ + simpa only [h] using leOfHom (IsFilteredOrEmpty.cocone_objs ((exists_surjective_nat _).choose m) + (sequentialFunctor_obj J m)).choose_spec.choose + +instance sequentialFunctor_final : (sequentialFunctor J).Final where + out d := by + obtain ⟨n, (g : d ≤ (sequentialFunctor J).obj n)⟩ := sequentialFunctor_final_aux J d + have : Nonempty (StructuredArrow d (sequentialFunctor J)) := + ⟨StructuredArrow.mk (homOfLE g)⟩ + apply isConnected_of_zigzag + refine fun i j ↦ ⟨[j], ?_⟩ + simp only [List.chain_cons, Zag, List.Chain.nil, and_true, ne_eq, not_false_eq_true, + List.getLast_cons, not_true_eq_false, List.getLast_singleton', reduceCtorEq] + clear! C + wlog h : j.right ≤ i.right + · exact or_comm.1 (this J d n g inferInstance j i (le_of_lt (not_le.mp h))) + · right + exact ⟨StructuredArrow.homMk (homOfLE h) rfl⟩ + +end IsFiltered + +namespace IsCofiltered + attribute [local instance] IsCofiltered.nonempty variable {C} [Preorder J] [IsCofiltered J] @@ -94,6 +190,9 @@ theorem sequentialFunctor_map : Antitone (sequentialFunctor_obj J) := /-- The initial functor `ℕᵒᵖ ⥤ J`, which allows us to turn cofiltered limits over countable preorders into sequential limits. + +TODO: redefine this as `(IsFiltered.sequentialFunctor Jᵒᵖ).leftOp`. This would need API for initial/ +final functors of the form `leftOp`/`rightOp`. -/ noncomputable def sequentialFunctor : ℕᵒᵖ ⥤ J where obj n := sequentialFunctor_obj J (unop n) @@ -153,6 +252,19 @@ For this we need to dualize this whole section. proof_wanted hasCountableColimits_of_hasFiniteColimits_and_hasSequentialColimits [HasFiniteColimits C] [HasLimitsOfShape ℕ C] : HasCountableColimits C +end IsCofiltered + end Preorder +@[deprecated (since := "2024-11-01")] alias sequentialFunctor := IsCofiltered.sequentialFunctor +@[deprecated (since := "2024-11-01")] alias sequentialFunctor_obj := + IsCofiltered.sequentialFunctor_obj +@[deprecated (since := "2024-11-01")] alias sequentialFunctor_map := + IsCofiltered.sequentialFunctor_map +@[deprecated (since := "2024-11-01")] alias sequentialFunctor_initial_aux := + IsCofiltered.sequentialFunctor_initial_aux +@[deprecated (since := "2024-11-01")] alias sequentialFunctor_initial := + IsCofiltered.sequentialFunctor_initial +attribute [nolint defLemma] sequentialFunctor_initial + end CategoryTheory.Limits diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Products.lean b/Mathlib/CategoryTheory/Limits/Shapes/Products.lean index 0bf114008f136..ed9bd8a77cbda 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Products.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Products.lean @@ -373,6 +373,10 @@ from a family of isomorphisms between the factors. abbrev Pi.mapIso {f g : β → C} [HasProductsOfShape β C] (p : ∀ b, f b ≅ g b) : ∏ᶜ f ≅ ∏ᶜ g := lim.mapIso (Discrete.natIso fun X => p X.as) +instance Pi.map_isIso {f g : β → C} [HasProductsOfShape β C] (p : ∀ b, f b ⟶ g b) + [∀ b, IsIso <| p b] : IsIso <| Pi.map p := + inferInstanceAs (IsIso (Pi.mapIso (fun b ↦ asIso (p b))).hom) + section /- In this section, we provide some API for products when we are given a functor @@ -487,6 +491,10 @@ from a family of isomorphisms between the factors. abbrev Sigma.mapIso {f g : β → C} [HasCoproductsOfShape β C] (p : ∀ b, f b ≅ g b) : ∐ f ≅ ∐ g := colim.mapIso (Discrete.natIso fun X => p X.as) +instance Sigma.map_isIso {f g : β → C} [HasCoproductsOfShape β C] (p : ∀ b, f b ⟶ g b) + [∀ b, IsIso <| p b] : IsIso (Sigma.map p) := + inferInstanceAs (IsIso (Sigma.mapIso (fun b ↦ asIso (p b))).hom) + section /- In this section, we provide some API for coproducts when we are given a functor @@ -660,6 +668,12 @@ theorem hasProducts_of_limit_fans (lf : ∀ {J : Type w} (f : J → C), Fan f) ⟨(Cones.postcompose Discrete.natIsoFunctor.inv).obj (lf fun j => F.obj ⟨j⟩), (IsLimit.postcomposeInvEquiv _ _).symm (lf_isLimit _)⟩ } +instance (priority := 100) hasProductsOfShape_of_hasProducts [HasProducts.{w} C] (J : Type w) : + HasProductsOfShape J C := inferInstance + +instance (priority := 100) hasCoproductsOfShape_of_hasCoproducts [HasCoproducts.{w} C] + (J : Type w) : HasCoproductsOfShape J C := inferInstance + /-! (Co)products over a type with a unique term. -/ diff --git a/Mathlib/CategoryTheory/Monoidal/Internal/Module.lean b/Mathlib/CategoryTheory/Monoidal/Internal/Module.lean index 5974753934292..9341953c58518 100644 --- a/Mathlib/CategoryTheory/Monoidal/Internal/Module.lean +++ b/Mathlib/CategoryTheory/Monoidal/Internal/Module.lean @@ -88,7 +88,7 @@ theorem algebraMap (A : Mon_ (ModuleCat.{u} R)) (r : R) : algebraMap R A.X r = A @[simps!] def functor : Mon_ (ModuleCat.{u} R) ⥤ AlgebraCat R where obj A := AlgebraCat.of R A.X - map {_ _} f := + map {_ _} f := AlgebraCat.ofHom { f.hom.toAddMonoidHom with toFun := f.hom map_one' := LinearMap.congr_fun f.one_hom (1 : R) @@ -134,9 +134,7 @@ def inverseObj (A : AlgebraCat.{u} R) : Mon_ (ModuleCat.{u} R) where -- Porting note (https://github.com/leanprover-community/mathlib4/issues/11041): `ext` did not pick up `TensorProduct.ext` refine TensorProduct.ext <| TensorProduct.ext <| LinearMap.ext fun x => LinearMap.ext fun y => LinearMap.ext fun z => ?_ - dsimp only [AlgebraCat.id_apply, TensorProduct.mk_apply, LinearMap.compr₂_apply, - Function.comp_apply, ModuleCat.MonoidalCategory.tensorHom_tmul, AlgebraCat.coe_comp, - MonoidalCategory.associator_hom_apply] + dsimp only [compr₂_apply, TensorProduct.mk_apply] rw [compr₂_apply, compr₂_apply] -- This used to be `rw`, but we need `erw` after https://github.com/leanprover/lean4/pull/2644 erw [CategoryTheory.comp_apply, @@ -152,9 +150,9 @@ def inverseObj (A : AlgebraCat.{u} R) : Mon_ (ModuleCat.{u} R) where def inverse : AlgebraCat.{u} R ⥤ Mon_ (ModuleCat.{u} R) where obj := inverseObj map f := - { hom := f.toLinearMap - one_hom := LinearMap.ext f.commutes - mul_hom := TensorProduct.ext <| LinearMap.ext₂ <| map_mul f } + { hom := f.hom.toLinearMap + one_hom := LinearMap.ext f.hom.commutes + mul_hom := TensorProduct.ext <| LinearMap.ext₂ <| map_mul f.hom } end MonModuleEquivalenceAlgebra @@ -193,14 +191,14 @@ def monModuleEquivalenceAlgebra : Mon_ (ModuleCat.{u} R) ≌ AlgebraCat R where counitIso := NatIso.ofComponents (fun A => - { hom := + { hom := AlgebraCat.ofHom { toFun := _root_.id map_zero' := rfl map_add' := fun _ _ => rfl map_one' := (algebraMap R A).map_one map_mul' := fun x y => @LinearMap.mul'_apply R _ _ _ _ _ _ x y commutes' := fun _ => rfl } - inv := + inv := AlgebraCat.ofHom { toFun := _root_.id map_zero' := rfl map_add' := fun _ _ => rfl @@ -208,9 +206,6 @@ def monModuleEquivalenceAlgebra : Mon_ (ModuleCat.{u} R) ≌ AlgebraCat R where map_mul' := fun x y => (@LinearMap.mul'_apply R _ _ _ _ _ _ x y).symm commutes' := fun _ => rfl } }) --- These lemmas have always been bad (https://github.com/leanprover-community/mathlib4/issues/7657), but https://github.com/leanprover/lean4/pull/2644 made `simp` start noticing -attribute [nolint simpNF] ModuleCat.MonModuleEquivalenceAlgebra.functor_map_apply - /-- The equivalence `Mon_ (ModuleCat R) ≌ AlgebraCat R` is naturally compatible with the forgetful functors to `ModuleCat R`. -/ diff --git a/Mathlib/CategoryTheory/MorphismProperty/Comma.lean b/Mathlib/CategoryTheory/MorphismProperty/Comma.lean index 0662c8046f120..6b093565af86f 100644 --- a/Mathlib/CategoryTheory/MorphismProperty/Comma.lean +++ b/Mathlib/CategoryTheory/MorphismProperty/Comma.lean @@ -117,6 +117,8 @@ instance : Category (P.Comma L R Q W) where id X := X.id comp f g := f.comp g +lemma toCommaMorphism_eq_hom {X Y : P.Comma L R Q W} (f : X ⟶ Y) : f.toCommaMorphism = f.hom := rfl + /-- Alternative `ext` lemma for `Comma.Hom`. -/ @[ext] lemma Hom.ext' {X Y : P.Comma L R Q W} {f g : X ⟶ Y} (h : f.hom = g.hom) : @@ -220,6 +222,9 @@ protected abbrev Over : Type _ := protected abbrev Over.forget : P.Over Q X ⥤ Over X := Comma.forget (Functor.id T) (Functor.fromPUnit.{0} X) P Q ⊤ +instance : (Over.forget P ⊤ X).Faithful := inferInstanceAs <| (Comma.forget _ _ _ _ _).Faithful +instance : (Over.forget P ⊤ X).Full := inferInstanceAs <| (Comma.forget _ _ _ _ _).Full + variable {P Q X} /-- Construct a morphism in `P.Over Q X` from a morphism in `Over.X`. -/ @@ -261,6 +266,9 @@ protected abbrev Under : Type _ := protected abbrev Under.forget : P.Under Q X ⥤ Under X := Comma.forget (Functor.fromPUnit.{0} X) (Functor.id T) P ⊤ Q +instance : (Under.forget P ⊤ X).Faithful := inferInstanceAs <| (Comma.forget _ _ _ _ _).Faithful +instance : (Under.forget P ⊤ X).Full := inferInstanceAs <| (Comma.forget _ _ _ _ _).Full + variable {P Q X} /-- Construct a morphism in `P.Under Q X` from a morphism in `Under.X`. -/ diff --git a/Mathlib/CategoryTheory/Sites/NonabelianCohomology/H1.lean b/Mathlib/CategoryTheory/Sites/NonabelianCohomology/H1.lean index 44a948a9222b1..b15c8b4f9117f 100644 --- a/Mathlib/CategoryTheory/Sites/NonabelianCohomology/H1.lean +++ b/Mathlib/CategoryTheory/Sites/NonabelianCohomology/H1.lean @@ -48,7 +48,7 @@ variable {C : Type u} [Category.{v} C] namespace PresheafOfGroups -variable (G : Cᵒᵖ ⥤ Grp.{w}) {X : C} {I : Type w'} (U : I → C) +variable (G : Cᵒᵖ ⥤ Grp.{w}) {I : Type w'} (U : I → C) /-- A zero cochain consists of a family of sections. -/ def ZeroCochain := ∀ (i : I), G.obj (Opposite.op (U i)) diff --git a/Mathlib/Combinatorics/Additive/PluenneckeRuzsa.lean b/Mathlib/Combinatorics/Additive/PluenneckeRuzsa.lean index aed53500fa639..88db5d1e3d0c9 100644 --- a/Mathlib/Combinatorics/Additive/PluenneckeRuzsa.lean +++ b/Mathlib/Combinatorics/Additive/PluenneckeRuzsa.lean @@ -10,7 +10,6 @@ import Mathlib.Combinatorics.Enumerative.DoubleCounting import Mathlib.Tactic.FieldSimp import Mathlib.Tactic.GCongr import Mathlib.Tactic.Positivity -import Mathlib.Tactic.Positivity.Finset import Mathlib.Tactic.Ring /-! diff --git a/Mathlib/Combinatorics/Derangements/Basic.lean b/Mathlib/Combinatorics/Derangements/Basic.lean index 9620588f45486..ac4e2f3b84276 100644 --- a/Mathlib/Combinatorics/Derangements/Basic.lean +++ b/Mathlib/Combinatorics/Derangements/Basic.lean @@ -7,6 +7,7 @@ import Mathlib.Dynamics.FixedPoints.Basic import Mathlib.GroupTheory.Perm.Option import Mathlib.Logic.Equiv.Defs import Mathlib.Logic.Equiv.Option +import Mathlib.Tactic.ApplyFun /-! # Derangements on types diff --git a/Mathlib/Combinatorics/Enumerative/Composition.lean b/Mathlib/Combinatorics/Enumerative/Composition.lean index 20b7c32701611..e1bf3970d658a 100644 --- a/Mathlib/Combinatorics/Enumerative/Composition.lean +++ b/Mathlib/Combinatorics/Enumerative/Composition.lean @@ -150,7 +150,7 @@ theorem sum_blocksFun : ∑ i, c.blocksFun i = n := by conv_rhs => rw [← c.blocks_sum, ← ofFn_blocksFun, sum_ofFn] theorem blocksFun_mem_blocks (i : Fin c.length) : c.blocksFun i ∈ c.blocks := - getElem_mem _ + get_mem _ _ @[simp] theorem one_le_blocks {i : ℕ} (h : i ∈ c.blocks) : 1 ≤ i := @@ -158,7 +158,7 @@ theorem one_le_blocks {i : ℕ} (h : i ∈ c.blocks) : 1 ≤ i := @[simp] theorem one_le_blocks' {i : ℕ} (h : i < c.length) : 1 ≤ c.blocks[i] := - c.one_le_blocks (getElem_mem h) + c.one_le_blocks (get_mem (blocks c) _) @[simp] theorem blocks_pos' (i : ℕ) (h : i < c.length) : 0 < c.blocks[i] := diff --git a/Mathlib/Combinatorics/SimpleGraph/Triangle/Basic.lean b/Mathlib/Combinatorics/SimpleGraph/Triangle/Basic.lean index a5d36c33b508b..2924a54b4d530 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Triangle/Basic.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Triangle/Basic.lean @@ -10,7 +10,6 @@ import Mathlib.Combinatorics.SimpleGraph.Clique import Mathlib.Data.Finset.Sym import Mathlib.Tactic.GCongr import Mathlib.Tactic.Positivity -import Mathlib.Tactic.Positivity.Finset /-! # Triangles in graphs @@ -35,8 +34,7 @@ open Fintype (card) namespace SimpleGraph -variable {α β 𝕜 : Type*} [LinearOrderedField 𝕜] {G H : SimpleGraph α} {ε δ : 𝕜} {n : ℕ} - {s : Finset α} +variable {α β 𝕜 : Type*} [LinearOrderedField 𝕜] {G H : SimpleGraph α} {ε δ : 𝕜} section LocallyLinear diff --git a/Mathlib/Combinatorics/SimpleGraph/Triangle/Counting.lean b/Mathlib/Combinatorics/SimpleGraph/Triangle/Counting.lean index bff996c3fa38c..3de98cd5194b3 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Triangle/Counting.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Triangle/Counting.lean @@ -23,7 +23,7 @@ attribute [-instance] decidableEq_of_subsingleton open Finset Fintype -variable {α : Type*} (G G' : SimpleGraph α) [DecidableRel G.Adj] {ε : ℝ} {s t u : Finset α} +variable {α : Type*} (G : SimpleGraph α) [DecidableRel G.Adj] {ε : ℝ} {s t u : Finset α} namespace SimpleGraph @@ -146,7 +146,7 @@ private lemma triple_eq_triple_of_mem (hst : Disjoint s t) (hsu : Disjoint s u) · rintro rfl solve_by_elim -variable [Fintype α] {P : Finpartition (univ : Finset α)} +variable [Fintype α] /-- The **Triangle Counting Lemma**. If `G` is a graph and `s`, `t`, `u` are disjoint sets of vertices such that each pair is `ε`-uniform and `2 * ε`-dense, then `G` contains at least diff --git a/Mathlib/Combinatorics/SimpleGraph/Triangle/Tripartite.lean b/Mathlib/Combinatorics/SimpleGraph/Triangle/Tripartite.lean index 3135218de5e3d..c911166bc53ac 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Triangle/Tripartite.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Triangle/Tripartite.lean @@ -38,7 +38,7 @@ This construction shows up unrelatedly twice in the theory of Roth numbers: open Finset Function Sum3 variable {α β γ 𝕜 : Type*} [LinearOrderedField 𝕜] {t : Finset (α × β × γ)} {a a' : α} {b b' : β} - {c c' : γ} {x : α × β × γ} {ε : 𝕜} + {c c' : γ} {x : α × β × γ} namespace SimpleGraph namespace TripartiteFromTriangles diff --git a/Mathlib/Computability/AkraBazzi/AkraBazzi.lean b/Mathlib/Computability/AkraBazzi/AkraBazzi.lean index 9cfbcd713b62a..7cd217fadb8cf 100644 --- a/Mathlib/Computability/AkraBazzi/AkraBazzi.lean +++ b/Mathlib/Computability/AkraBazzi/AkraBazzi.lean @@ -544,9 +544,9 @@ lemma tendsto_atTop_sumCoeffsExp : Tendsto (fun (p : ℝ) => ∑ i, a i * (b i) lemma one_mem_range_sumCoeffsExp : 1 ∈ Set.range (fun (p : ℝ) => ∑ i, a i * (b i) ^ p) := by refine mem_range_of_exists_le_of_exists_ge R.continuous_sumCoeffsExp ?le_one ?ge_one case le_one => - exact Eventually.exists <| eventually_le_of_tendsto_lt zero_lt_one R.tendsto_zero_sumCoeffsExp + exact R.tendsto_zero_sumCoeffsExp.eventually_le_const zero_lt_one |>.exists case ge_one => - exact Eventually.exists <| R.tendsto_atTop_sumCoeffsExp.eventually_ge_atTop _ + exact R.tendsto_atTop_sumCoeffsExp.eventually_ge_atTop _ |>.exists /-- The function x ↦ ∑ a_i b_i^x is injective. This implies the uniqueness of `p`. -/ lemma injective_sumCoeffsExp : Function.Injective (fun (p : ℝ) => ∑ i, a i * (b i) ^ p) := diff --git a/Mathlib/Computability/Halting.lean b/Mathlib/Computability/Halting.lean index 0bce012c8ecc0..7437dbc1b31ac 100644 --- a/Mathlib/Computability/Halting.lean +++ b/Mathlib/Computability/Halting.lean @@ -267,11 +267,12 @@ namespace Nat open Vector Part /-- A simplified basis for `Partrec`. -/ -inductive Partrec' : ∀ {n}, (Vector ℕ n →. ℕ) → Prop +inductive Partrec' : ∀ {n}, (Mathlib.Vector ℕ n →. ℕ) → Prop | prim {n f} : @Primrec' n f → @Partrec' n f - | comp {m n f} (g : Fin n → Vector ℕ m →. ℕ) : - Partrec' f → (∀ i, Partrec' (g i)) → Partrec' fun v => (Vector.mOfFn fun i => g i v) >>= f - | rfind {n} {f : Vector ℕ (n + 1) → ℕ} : + | comp {m n f} (g : Fin n → Mathlib.Vector ℕ m →. ℕ) : + Partrec' f → (∀ i, Partrec' (g i)) → + Partrec' fun v => (Mathlib.Vector.mOfFn fun i => g i v) >>= f + | rfind {n} {f : Mathlib.Vector ℕ (n + 1) → ℕ} : @Partrec' (n + 1) f → Partrec' fun v => rfind fun n => some (f (n ::ᵥ v) = 0) end Nat @@ -293,10 +294,11 @@ theorem to_part {n f} (pf : @Partrec' n f) : _root_.Partrec f := by this).to₂.partrec₂ exact _root_.Partrec.rfind this -theorem of_eq {n} {f g : Vector ℕ n →. ℕ} (hf : Partrec' f) (H : ∀ i, f i = g i) : Partrec' g := +theorem of_eq {n} {f g : Mathlib.Vector ℕ n →. ℕ} (hf : Partrec' f) (H : ∀ i, f i = g i) : + Partrec' g := (funext H : f = g) ▸ hf -theorem of_prim {n} {f : Vector ℕ n → ℕ} (hf : Primrec f) : @Partrec' n f := +theorem of_prim {n} {f : Mathlib.Vector ℕ n → ℕ} (hf : Primrec f) : @Partrec' n f := prim (Nat.Primrec'.of_prim hf) theorem head {n : ℕ} : @Partrec' n.succ (@head ℕ n) := @@ -313,21 +315,21 @@ protected theorem bind {n f g} (hf : @Partrec' n f) (hg : @Partrec' (n + 1) g) : exact prim (Nat.Primrec'.get _)).of_eq fun v => by simp [mOfFn, Part.bind_assoc, pure] -protected theorem map {n f} {g : Vector ℕ (n + 1) → ℕ} (hf : @Partrec' n f) +protected theorem map {n f} {g : Mathlib.Vector ℕ (n + 1) → ℕ} (hf : @Partrec' n f) (hg : @Partrec' (n + 1) g) : @Partrec' n fun v => (f v).map fun a => g (a ::ᵥ v) := by simpa [(Part.bind_some_eq_map _ _).symm] using hf.bind hg /-- Analogous to `Nat.Partrec'` for `ℕ`-valued functions, a predicate for partial recursive vector-valued functions. -/ -def Vec {n m} (f : Vector ℕ n → Vector ℕ m) := +def Vec {n m} (f : Mathlib.Vector ℕ n → Mathlib.Vector ℕ m) := ∀ i, Partrec' fun v => (f v).get i nonrec theorem Vec.prim {n m f} (hf : @Nat.Primrec'.Vec n m f) : Vec f := fun i => prim <| hf i protected theorem nil {n} : @Vec n 0 fun _ => nil := fun i => i.elim0 -protected theorem cons {n m} {f : Vector ℕ n → ℕ} {g} (hf : @Partrec' n f) (hg : @Vec n m g) : - Vec fun v => f v ::ᵥ g v := fun i => +protected theorem cons {n m} {f : Mathlib.Vector ℕ n → ℕ} {g} (hf : @Partrec' n f) + (hg : @Vec n m g) : Vec fun v => f v ::ᵥ g v := fun i => Fin.cases (by simpa using hf) (fun i => by simp only [hg i, get_cons_succ]) i theorem idv {n} : @Vec n n id := @@ -336,11 +338,11 @@ theorem idv {n} : @Vec n n id := theorem comp' {n m f g} (hf : @Partrec' m f) (hg : @Vec n m g) : Partrec' fun v => f (g v) := (hf.comp _ hg).of_eq fun v => by simp -theorem comp₁ {n} (f : ℕ →. ℕ) {g : Vector ℕ n → ℕ} (hf : @Partrec' 1 fun v => f v.head) +theorem comp₁ {n} (f : ℕ →. ℕ) {g : Mathlib.Vector ℕ n → ℕ} (hf : @Partrec' 1 fun v => f v.head) (hg : @Partrec' n g) : @Partrec' n fun v => f (g v) := by simpa using hf.comp' (Partrec'.cons hg Partrec'.nil) -theorem rfindOpt {n} {f : Vector ℕ (n + 1) → ℕ} (hf : @Partrec' (n + 1) f) : +theorem rfindOpt {n} {f : Mathlib.Vector ℕ (n + 1) → ℕ} (hf : @Partrec' (n + 1) f) : @Partrec' n fun v => Nat.rfindOpt fun a => ofNat (Option ℕ) (f (a ::ᵥ v)) := ((rfind <| (of_prim (Primrec.nat_sub.comp (_root_.Primrec.const 1) Primrec.vector_head)).comp₁ @@ -367,7 +369,7 @@ open Nat.Partrec.Code theorem of_part : ∀ {n f}, _root_.Partrec f → @Partrec' n f := @(suffices ∀ f, Nat.Partrec f → @Partrec' 1 fun v => f v.head from fun {n f} hf => by let g := fun n₁ => - (Part.ofOption (decode (α := Vector ℕ n) n₁)).bind (fun a => Part.map encode (f a)) + (Part.ofOption (decode (α := Mathlib.Vector ℕ n) n₁)).bind (fun a => Part.map encode (f a)) exact (comp₁ g (this g hf) (prim Nat.Primrec'.encode)).of_eq fun i => by dsimp only [g]; simp [encodek, Part.map_id'] diff --git a/Mathlib/Computability/Partrec.lean b/Mathlib/Computability/Partrec.lean index 63fdfb8565e1c..3ad33d20e77c5 100644 --- a/Mathlib/Computability/Partrec.lean +++ b/Mathlib/Computability/Partrec.lean @@ -314,25 +314,25 @@ theorem list_concat : Computable₂ fun l (a : α) => l ++ [a] := theorem list_length : Computable (@List.length α) := Primrec.list_length.to_comp -theorem vector_cons {n} : Computable₂ (@Vector.cons α n) := +theorem vector_cons {n} : Computable₂ (@Mathlib.Vector.cons α n) := Primrec.vector_cons.to_comp -theorem vector_toList {n} : Computable (@Vector.toList α n) := +theorem vector_toList {n} : Computable (@Mathlib.Vector.toList α n) := Primrec.vector_toList.to_comp -theorem vector_length {n} : Computable (@Vector.length α n) := +theorem vector_length {n} : Computable (@Mathlib.Vector.length α n) := Primrec.vector_length.to_comp -theorem vector_head {n} : Computable (@Vector.head α n) := +theorem vector_head {n} : Computable (@Mathlib.Vector.head α n) := Primrec.vector_head.to_comp -theorem vector_tail {n} : Computable (@Vector.tail α n) := +theorem vector_tail {n} : Computable (@Mathlib.Vector.tail α n) := Primrec.vector_tail.to_comp -theorem vector_get {n} : Computable₂ (@Vector.get α n) := +theorem vector_get {n} : Computable₂ (@Mathlib.Vector.get α n) := Primrec.vector_get.to_comp -theorem vector_ofFn' {n} : Computable (@Vector.ofFn α n) := +theorem vector_ofFn' {n} : Computable (@Mathlib.Vector.ofFn α n) := Primrec.vector_ofFn'.to_comp theorem fin_app {n} : Computable₂ (@id (Fin n → σ)) := @@ -523,7 +523,8 @@ end Partrec @[simp] theorem Vector.mOfFn_part_some {α n} : - ∀ f : Fin n → α, (Vector.mOfFn fun i => Part.some (f i)) = Part.some (Vector.ofFn f) := + ∀ f : Fin n → α, + (Mathlib.Vector.mOfFn fun i => Part.some (f i)) = Part.some (Mathlib.Vector.ofFn f) := Vector.mOfFn_pure namespace Computable @@ -642,7 +643,7 @@ theorem list_ofFn : exact list_cons.comp (hf 0) (list_ofFn fun i => hf i.succ) theorem vector_ofFn {n} {f : Fin n → α → σ} (hf : ∀ i, Computable (f i)) : - Computable fun a => Vector.ofFn fun i => f i a := + Computable fun a => Mathlib.Vector.ofFn fun i => f i a := (Partrec.vector_mOfFn hf).of_eq fun a => by simp end Computable diff --git a/Mathlib/Computability/Primrec.lean b/Mathlib/Computability/Primrec.lean index f7492a1e781aa..76aceca0eb52f 100644 --- a/Mathlib/Computability/Primrec.lean +++ b/Mathlib/Computability/Primrec.lean @@ -1101,7 +1101,7 @@ def subtype {p : α → Prop} [DecidablePred p] (hp : PrimrecPred p) : Primcodab instance fin {n} : Primcodable (Fin n) := @ofEquiv _ _ (subtype <| nat_lt.comp .id (const n)) Fin.equivSubtype -instance vector {n} : Primcodable (Vector α n) := +instance vector {n} : Primcodable (Mathlib.Vector α n) := subtype ((@Primrec.eq ℕ _ _).comp list_length (const _)) instance finArrow {n} : Primcodable (Fin n → α) := @@ -1184,25 +1184,26 @@ theorem fin_val {n} : Primrec (fun (i : Fin n) => (i : ℕ)) := theorem fin_succ {n} : Primrec (@Fin.succ n) := fin_val_iff.1 <| by simp [succ.comp fin_val] -theorem vector_toList {n} : Primrec (@Vector.toList α n) := +theorem vector_toList {n} : Primrec (@Mathlib.Vector.toList α n) := subtype_val -theorem vector_toList_iff {n} {f : α → Vector β n} : (Primrec fun a => (f a).toList) ↔ Primrec f := +theorem vector_toList_iff {n} {f : α → Mathlib.Vector β n} : + (Primrec fun a => (f a).toList) ↔ Primrec f := subtype_val_iff -theorem vector_cons {n} : Primrec₂ (@Vector.cons α n) := +theorem vector_cons {n} : Primrec₂ (@Mathlib.Vector.cons α n) := vector_toList_iff.1 <| by simpa using list_cons.comp fst (vector_toList_iff.2 snd) -theorem vector_length {n} : Primrec (@Vector.length α n) := +theorem vector_length {n} : Primrec (@Mathlib.Vector.length α n) := const _ -theorem vector_head {n} : Primrec (@Vector.head α n) := +theorem vector_head {n} : Primrec (@Mathlib.Vector.head α n) := option_some_iff.1 <| (list_head?.comp vector_toList).of_eq fun ⟨_ :: _, _⟩ => rfl -theorem vector_tail {n} : Primrec (@Vector.tail α n) := +theorem vector_tail {n} : Primrec (@Mathlib.Vector.tail α n) := vector_toList_iff.1 <| (list_tail.comp vector_toList).of_eq fun ⟨l, h⟩ => by cases l <;> rfl -theorem vector_get {n} : Primrec₂ (@Vector.get α n) := +theorem vector_get {n} : Primrec₂ (@Mathlib.Vector.get α n) := option_some_iff.1 <| (list_get?.comp (vector_toList.comp fst) (fin_val.comp snd)).of_eq fun a => by rw [Vector.get_eq_get, ← List.get?_eq_get] @@ -1215,13 +1216,13 @@ theorem list_ofFn : simpa [List.ofFn_succ] using list_cons.comp (hf 0) (list_ofFn fun i => hf i.succ) theorem vector_ofFn {n} {f : Fin n → α → σ} (hf : ∀ i, Primrec (f i)) : - Primrec fun a => Vector.ofFn fun i => f i a := + Primrec fun a => Mathlib.Vector.ofFn fun i => f i a := vector_toList_iff.1 <| by simp [list_ofFn hf] -theorem vector_get' {n} : Primrec (@Vector.get α n) := +theorem vector_get' {n} : Primrec (@Mathlib.Vector.get α n) := of_equiv_symm -theorem vector_ofFn' {n} : Primrec (@Vector.ofFn α n) := +theorem vector_ofFn' {n} : Primrec (@Mathlib.Vector.ofFn α n) := of_equiv theorem fin_app {n} : Primrec₂ (@id (Fin n → σ)) := @@ -1248,16 +1249,16 @@ open Mathlib.Vector work with n-ary functions on ℕ instead of unary functions. We prove that this is equivalent to the regular notion in `to_prim` and `of_prim`. -/ -inductive Primrec' : ∀ {n}, (Vector ℕ n → ℕ) → Prop +inductive Primrec' : ∀ {n}, (Mathlib.Vector ℕ n → ℕ) → Prop | zero : @Primrec' 0 fun _ => 0 | succ : @Primrec' 1 fun v => succ v.head | get {n} (i : Fin n) : Primrec' fun v => v.get i - | comp {m n f} (g : Fin n → Vector ℕ m → ℕ) : - Primrec' f → (∀ i, Primrec' (g i)) → Primrec' fun a => f (ofFn fun i => g i a) + | comp {m n f} (g : Fin n → Mathlib.Vector ℕ m → ℕ) : + Primrec' f → (∀ i, Primrec' (g i)) → Primrec' fun a => f (Mathlib.Vector.ofFn fun i => g i a) | prec {n f g} : @Primrec' n f → @Primrec' (n + 2) g → - Primrec' fun v : Vector ℕ (n + 1) => + Primrec' fun v : Mathlib.Vector ℕ (n + 1) => v.head.rec (f v.tail) fun y IH => g (y ::ᵥ IH ::ᵥ v.tail) end Nat @@ -1280,7 +1281,8 @@ theorem to_prim {n f} (pf : @Nat.Primrec' n f) : Primrec f := by Primrec.vector_cons.comp (Primrec.snd.comp .snd) <| (@Primrec.vector_tail _ _ (n + 1)).comp .fst).to₂ -theorem of_eq {n} {f g : Vector ℕ n → ℕ} (hf : Primrec' f) (H : ∀ i, f i = g i) : Primrec' g := +theorem of_eq {n} {f g : Mathlib.Vector ℕ n → ℕ} (hf : Primrec' f) (H : ∀ i, f i = g i) : + Primrec' g := (funext H : f = g) ▸ hf theorem const {n} : ∀ m, @Primrec' n fun _ => m @@ -1295,7 +1297,7 @@ theorem tail {n f} (hf : @Primrec' n f) : @Primrec' n.succ fun v => f v.tail := rw [← ofFn_get v.tail]; congr; funext i; simp /-- A function from vectors to vectors is primitive recursive when all of its projections are. -/ -def Vec {n m} (f : Vector ℕ n → Vector ℕ m) : Prop := +def Vec {n m} (f : Mathlib.Vector ℕ n → Mathlib.Vector ℕ m) : Prop := ∀ i, Primrec' fun v => (f v).get i protected theorem nil {n} : @Vec n 0 fun _ => nil := fun i => i.elim0 @@ -1390,7 +1392,7 @@ theorem unpair₂ {n f} (hf : @Primrec' n f) : @Primrec' n fun v => (f v).unpair theorem of_prim {n f} : Primrec f → @Primrec' n f := suffices ∀ f, Nat.Primrec f → @Primrec' 1 fun v => f v.head from fun hf => (pred.comp₁ _ <| - (this _ hf).comp₁ (fun m => Encodable.encode <| (@decode (Vector ℕ n) _ m).map f) + (this _ hf).comp₁ (fun m => Encodable.encode <| (@decode (Mathlib.Vector ℕ n) _ m).map f) Primrec'.encode).of_eq fun i => by simp [encodek] fun f hf => by diff --git a/Mathlib/Computability/TMToPartrec.lean b/Mathlib/Computability/TMToPartrec.lean index 17abd70e3ad66..effb93335081f 100644 --- a/Mathlib/Computability/TMToPartrec.lean +++ b/Mathlib/Computability/TMToPartrec.lean @@ -239,12 +239,14 @@ def prec (f g : Code) : Code := attribute [-simp] Part.bind_eq_bind Part.map_eq_map Part.pure_eq_some -theorem exists_code.comp {m n} {f : Vector ℕ n →. ℕ} {g : Fin n → Vector ℕ m →. ℕ} - (hf : ∃ c : Code, ∀ v : Vector ℕ n, c.eval v.1 = pure <$> f v) - (hg : ∀ i, ∃ c : Code, ∀ v : Vector ℕ m, c.eval v.1 = pure <$> g i v) : - ∃ c : Code, ∀ v : Vector ℕ m, c.eval v.1 = pure <$> ((Vector.mOfFn fun i => g i v) >>= f) := by +theorem exists_code.comp {m n} {f : Mathlib.Vector ℕ n →. ℕ} {g : Fin n → Mathlib.Vector ℕ m →. ℕ} + (hf : ∃ c : Code, ∀ v : Mathlib.Vector ℕ n, c.eval v.1 = pure <$> f v) + (hg : ∀ i, ∃ c : Code, ∀ v : Mathlib.Vector ℕ m, c.eval v.1 = pure <$> g i v) : + ∃ c : Code, ∀ v : Mathlib.Vector ℕ m, + c.eval v.1 = pure <$> ((Mathlib.Vector.mOfFn fun i => g i v) >>= f) := by rsuffices ⟨cg, hg⟩ : - ∃ c : Code, ∀ v : Vector ℕ m, c.eval v.1 = Subtype.val <$> Vector.mOfFn fun i => g i v + ∃ c : Code, ∀ v : Mathlib.Vector ℕ m, + c.eval v.1 = Subtype.val <$> Mathlib.Vector.mOfFn fun i => g i v · obtain ⟨cf, hf⟩ := hf exact ⟨cf.comp cg, fun v => by @@ -259,8 +261,8 @@ theorem exists_code.comp {m n} {f : Vector ℕ n →. ℕ} {g : Fin n → Vector simp [Vector.mOfFn, hg₁, map_bind, seq_bind_eq, bind_assoc, (· ∘ ·), hl] rfl⟩ -theorem exists_code {n} {f : Vector ℕ n →. ℕ} (hf : Nat.Partrec' f) : - ∃ c : Code, ∀ v : Vector ℕ n, c.eval v.1 = pure <$> f v := by +theorem exists_code {n} {f : Mathlib.Vector ℕ n →. ℕ} (hf : Nat.Partrec' f) : + ∃ c : Code, ∀ v : Mathlib.Vector ℕ n, c.eval v.1 = pure <$> f v := by induction hf with | prim hf => induction hf with diff --git a/Mathlib/Computability/TuringMachine.lean b/Mathlib/Computability/TuringMachine.lean index 4e3298c29a939..378d518d12b0c 100644 --- a/Mathlib/Computability/TuringMachine.lean +++ b/Mathlib/Computability/TuringMachine.lean @@ -1443,7 +1443,7 @@ open TM1 variable {Γ : Type*} theorem exists_enc_dec [Inhabited Γ] [Finite Γ] : - ∃ (n : ℕ) (enc : Γ → Vector Bool n) (dec : Vector Bool n → Γ), + ∃ (n : ℕ) (enc : Γ → Mathlib.Vector Bool n) (dec : Mathlib.Vector Bool n → Γ), enc default = Vector.replicate n false ∧ ∀ a, dec (enc a) = a := by rcases Finite.exists_equiv_fin Γ with ⟨n, ⟨e⟩⟩ letI : DecidableEq Γ := e.decidableEq @@ -1475,13 +1475,13 @@ local notation "Stmt'₁" => Stmt Bool Λ'₁ σ local notation "Cfg'₁" => Cfg Bool Λ'₁ σ /-- Read a vector of length `n` from the tape. -/ -def readAux : ∀ n, (Vector Bool n → Stmt'₁) → Stmt'₁ +def readAux : ∀ n, (Mathlib.Vector Bool n → Stmt'₁) → Stmt'₁ | 0, f => f Vector.nil | i + 1, f => Stmt.branch (fun a _ ↦ a) (Stmt.move Dir.right <| readAux i fun v ↦ f (true ::ᵥ v)) (Stmt.move Dir.right <| readAux i fun v ↦ f (false ::ᵥ v)) -variable {n : ℕ} (enc : Γ → Vector Bool n) (dec : Vector Bool n → Γ) +variable {n : ℕ} (enc : Γ → Mathlib.Vector Bool n) (dec : Mathlib.Vector Bool n → Γ) /-- A move left or right corresponds to `n` moves across the super-cell. -/ def move (d : Dir) (q : Stmt'₁) : Stmt'₁ := @@ -1530,7 +1530,8 @@ theorem supportsStmt_write {S : Finset Λ'₁} {l : List Bool} {q : Stmt'₁} : theorem supportsStmt_read {S : Finset Λ'₁} : ∀ {f : Γ → Stmt'₁}, (∀ a, SupportsStmt S (f a)) → SupportsStmt S (read dec f) := suffices - ∀ (i) (f : Vector Bool i → Stmt'₁), (∀ v, SupportsStmt S (f v)) → SupportsStmt S (readAux i f) + ∀ (i) (f : Mathlib.Vector Bool i → Stmt'₁), + (∀ v, SupportsStmt S (f v)) → SupportsStmt S (readAux i f) from fun hf ↦ this n _ (by intro; simp only [supportsStmt_move, hf]) fun i f hf ↦ by induction' i with i IH; · exact hf _ diff --git a/Mathlib/Data/Complex/Abs.lean b/Mathlib/Data/Complex/Abs.lean index 99319c9d298b3..18f2f48e1b525 100644 --- a/Mathlib/Data/Complex/Abs.lean +++ b/Mathlib/Data/Complex/Abs.lean @@ -199,7 +199,7 @@ theorem abs_im_div_abs_le_one (z : ℂ) : |z.im / Complex.abs z| ≤ 1 := @[simp, norm_cast] lemma abs_intCast (n : ℤ) : abs n = |↑n| := by rw [← ofReal_intCast, abs_ofReal] -@[deprecated (since := "2024-02-14")] +@[deprecated "No deprecation message was provided." (since := "2024-02-14")] lemma int_cast_abs (n : ℤ) : |↑n| = Complex.abs n := (abs_intCast _).symm theorem normSq_eq_abs (x : ℂ) : normSq x = (Complex.abs x) ^ 2 := by diff --git a/Mathlib/Data/Complex/Exponential.lean b/Mathlib/Data/Complex/Exponential.lean index 1054c7a046c4b..f789146aa2884 100644 --- a/Mathlib/Data/Complex/Exponential.lean +++ b/Mathlib/Data/Complex/Exponential.lean @@ -188,7 +188,7 @@ theorem exp_add : exp (x + y) = exp x * exp y := by /-- the exponential function as a monoid hom from `Multiplicative ℂ` to `ℂ` -/ @[simps] noncomputable def expMonoidHom : MonoidHom (Multiplicative ℂ) ℂ := - { toFun := fun z => exp (Multiplicative.toAdd z), + { toFun := fun z => exp z.toAdd, map_one' := by simp, map_mul' := by simp [exp_add] } @@ -689,7 +689,7 @@ nonrec theorem exp_add : exp (x + y) = exp x * exp y := by simp [exp_add, exp] /-- the exponential function as a monoid hom from `Multiplicative ℝ` to `ℝ` -/ @[simps] noncomputable def expMonoidHom : MonoidHom (Multiplicative ℝ) ℝ := - { toFun := fun x => exp (Multiplicative.toAdd x), + { toFun := fun x => exp x.toAdd, map_one' := by simp, map_mul' := by simp [exp_add] } diff --git a/Mathlib/Data/ENNReal/Basic.lean b/Mathlib/Data/ENNReal/Basic.lean index 96836f66517c4..120674ea5f000 100644 --- a/Mathlib/Data/ENNReal/Basic.lean +++ b/Mathlib/Data/ENNReal/Basic.lean @@ -85,6 +85,7 @@ context, or if we have `(f : α → ℝ≥0∞) (hf : ∀ x, f x ≠ ∞)`. -/ +assert_not_exists Finset open Function Set NNReal diff --git a/Mathlib/Data/ENNReal/Inv.lean b/Mathlib/Data/ENNReal/Inv.lean index 36003f724d580..bccdde7f1f4ab 100644 --- a/Mathlib/Data/ENNReal/Inv.lean +++ b/Mathlib/Data/ENNReal/Inv.lean @@ -173,6 +173,16 @@ protected theorem inv_div {a b : ℝ≥0∞} (htop : b ≠ ∞ ∨ a ≠ ∞) (h rw [← ENNReal.inv_ne_top] at hzero rw [ENNReal.div_eq_inv_mul, ENNReal.div_eq_inv_mul, ENNReal.mul_inv htop hzero, mul_comm, inv_inv] +lemma prod_inv_distrib {ι : Type*} {f : ι → ℝ≥0∞} {s : Finset ι} + (hf : s.toSet.Pairwise fun i j ↦ f i ≠ 0 ∨ f j ≠ ∞) : (∏ i ∈ s, f i)⁻¹ = ∏ i ∈ s, (f i)⁻¹ := by + induction' s using Finset.cons_induction with i s hi ih + · simp + simp [← ih (hf.mono <| by simp)] + refine ENNReal.mul_inv (not_or_of_imp fun hi₀ ↦ prod_ne_top fun j hj ↦ ?_) + (not_or_of_imp fun hi₀ ↦ Finset.prod_ne_zero_iff.2 fun j hj ↦ ?_) + · exact imp_iff_not_or.2 (hf (by simp) (by simp [hj]) <| .symm <| ne_of_mem_of_not_mem hj hi) hi₀ + · exact imp_iff_not_or.2 (hf (by simp [hj]) (by simp) <| ne_of_mem_of_not_mem hj hi).symm hi₀ + protected theorem mul_div_mul_left (a b : ℝ≥0∞) (hc : c ≠ 0) (hc' : c ≠ ⊤) : c * a / (c * b) = a / b := by rw [div_eq_mul_inv, div_eq_mul_inv, ENNReal.mul_inv (Or.inl hc) (Or.inl hc'), mul_mul_mul_comm, diff --git a/Mathlib/Data/ENat/Lattice.lean b/Mathlib/Data/ENat/Lattice.lean index d56040d7d9e21..fd0d60e48e317 100644 --- a/Mathlib/Data/ENat/Lattice.lean +++ b/Mathlib/Data/ENat/Lattice.lean @@ -106,7 +106,7 @@ lemma finite_of_sSup_lt_top (h : sSup s < ⊤) : s.Finite := by exact sSup_eq_top_of_infinite h lemma sSup_mem_of_nonempty_of_lt_top [Nonempty s] (hs' : sSup s < ⊤) : sSup s ∈ s := - Nonempty.csSup_mem nonempty_of_nonempty_subtype (finite_of_sSup_lt_top hs') + Nonempty.csSup_mem .of_subtype (finite_of_sSup_lt_top hs') lemma exists_eq_iSup_of_lt_top [Nonempty ι] (h : ⨆ i, f i < ⊤) : ∃ i, f i = ⨆ i, f i := diff --git a/Mathlib/Data/FP/Basic.lean b/Mathlib/Data/FP/Basic.lean index ebd1995796919..492cf4ffcd604 100644 --- a/Mathlib/Data/FP/Basic.lean +++ b/Mathlib/Data/FP/Basic.lean @@ -146,7 +146,6 @@ unsafe def nextUpPos (e m) (v : ValidFinite e m) : Float := Float.finite false e m' (by unfold ValidFinite at *; rw [ss]; exact v) else if h : e = emax then Float.inf false else Float.finite false e.succ (Nat.div2 m') lcProof -set_option linter.deprecated false in -- Porting note: remove this line when you dropped 'lcProof' set_option linter.unusedVariables false in @[nolint docBlame] diff --git a/Mathlib/Data/Fin/Basic.lean b/Mathlib/Data/Fin/Basic.lean index 21c9e27353985..4fcd646907769 100644 --- a/Mathlib/Data/Fin/Basic.lean +++ b/Mathlib/Data/Fin/Basic.lean @@ -1115,7 +1115,7 @@ lemma succAbove_ne_last {a : Fin (n + 2)} {b : Fin (n + 1)} (ha : a ≠ last _) lemma succAbove_last_apply (i : Fin n) : succAbove (last n) i = castSucc i := by rw [succAbove_last] -@[deprecated (since := "2024-05-30")] +@[deprecated "No deprecation message was provided." (since := "2024-05-30")] lemma succAbove_lt_ge (p : Fin (n + 1)) (i : Fin n) : castSucc i < p ∨ p ≤ castSucc i := Nat.lt_or_ge (castSucc i) p diff --git a/Mathlib/Data/Finset/Density.lean b/Mathlib/Data/Finset/Density.lean index b8d5585f00ed8..29e19adc50a21 100644 --- a/Mathlib/Data/Finset/Density.lean +++ b/Mathlib/Data/Finset/Density.lean @@ -7,7 +7,7 @@ import Mathlib.Algebra.Order.Field.Rat import Mathlib.Data.Fintype.Card import Mathlib.Data.NNRat.Order import Mathlib.Data.Rat.Cast.CharZero -import Mathlib.Tactic.Positivity +import Mathlib.Tactic.Positivity.Basic /-! # Density of a finite set diff --git a/Mathlib/Data/Finset/Fold.lean b/Mathlib/Data/Finset/Fold.lean index 931d4b86e5a6b..fb9ed13966a4d 100644 --- a/Mathlib/Data/Finset/Fold.lean +++ b/Mathlib/Data/Finset/Fold.lean @@ -3,8 +3,6 @@ Copyright (c) 2017 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ -import Mathlib.Algebra.Order.Monoid.Unbundled.MinMax -import Mathlib.Algebra.Order.Monoid.Unbundled.WithTop import Mathlib.Data.Finset.Image import Mathlib.Data.Multiset.Fold @@ -231,11 +229,6 @@ theorem fold_max_lt : s.fold max b f < c ↔ b < c ∧ ∀ x ∈ s, f x < c := b theorem lt_fold_max : c < s.fold max b f ↔ c < b ∨ ∃ x ∈ s, c < f x := fold_op_rel_iff_or lt_max_iff -theorem fold_max_add [Add β] [AddRightMono β] (n : WithBot β) - (s : Finset α) : (s.fold max ⊥ fun x : α => ↑(f x) + n) = s.fold max ⊥ ((↑) ∘ f) + n := by - classical - induction' s using Finset.induction_on with a s _ ih <;> simp [*, max_add_add_right] - end Order end Fold diff --git a/Mathlib/Data/Finset/Lattice/Fold.lean b/Mathlib/Data/Finset/Lattice/Fold.lean index 4c0a9c4e8b587..404b2ac9105b3 100644 --- a/Mathlib/Data/Finset/Lattice/Fold.lean +++ b/Mathlib/Data/Finset/Lattice/Fold.lean @@ -3,7 +3,6 @@ Copyright (c) 2018 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ -import Mathlib.Algebra.Order.Monoid.Unbundled.Pow import Mathlib.Data.Finset.Fold import Mathlib.Data.Finset.Pi import Mathlib.Data.Finset.Prod @@ -819,13 +818,6 @@ theorem _root_.map_finset_sup' [SemilatticeSup β] [FunLike F α β] [SupHomClas f (s.sup' hs g) = s.sup' hs (f ∘ g) := by refine hs.cons_induction ?_ ?_ <;> intros <;> simp [*] -lemma nsmul_sup' {α β : Type*} [AddMonoid β] [LinearOrder β] - [AddLeftMono β] [AddRightMono β] - {s : Finset α} (hs : s.Nonempty) (f : α → β) (n : ℕ) : - s.sup' hs (fun a => n • f a) = n • s.sup' hs f := - let ns : SupHom β β := { toFun := (n • ·), map_sup' := fun _ _ => (nsmul_right_mono n).map_max } - (map_finset_sup' ns hs _).symm - /-- To rewrite from right to left, use `Finset.sup'_comp_eq_image`. -/ @[simp] theorem sup'_image [DecidableEq β] {s : Finset γ} {f : γ → β} (hs : (s.image f).Nonempty) @@ -857,6 +849,11 @@ lemma sup'_comp_eq_map {s : Finset γ} {f : γ ↪ β} (g : β → α) (hs : s.N theorem sup'_mono {s₁ s₂ : Finset β} (h : s₁ ⊆ s₂) (h₁ : s₁.Nonempty) : s₁.sup' h₁ f ≤ s₂.sup' (h₁.mono h) f := Finset.sup'_le h₁ _ (fun _ hb => le_sup' _ (h hb)) + +@[gcongr] +lemma sup'_mono_fun {hs : s.Nonempty} {f g : β → α} (h : ∀ b ∈ s, f b ≤ g b) : + s.sup' hs f ≤ s.sup' hs g := sup'_le _ _ fun b hb ↦ (h b hb).trans (le_sup' _ hb) + end Sup' section Inf' @@ -974,13 +971,6 @@ theorem _root_.map_finset_inf' [SemilatticeInf β] [FunLike F α β] [InfHomClas f (s.inf' hs g) = s.inf' hs (f ∘ g) := by refine hs.cons_induction ?_ ?_ <;> intros <;> simp [*] -lemma nsmul_inf' {α β : Type*} [AddMonoid β] [LinearOrder β] - [AddLeftMono β] [AddRightMono β] - {s : Finset α} (hs : s.Nonempty) (f : α → β) (n : ℕ) : - s.inf' hs (fun a => n • f a) = n • s.inf' hs f := - let ns : InfHom β β := { toFun := (n • ·), map_inf' := fun _ _ => (nsmul_right_mono n).map_min } - (map_finset_inf' ns hs _).symm - /-- To rewrite from right to left, use `Finset.inf'_comp_eq_image`. -/ @[simp] theorem inf'_image [DecidableEq β] {s : Finset γ} {f : γ → β} (hs : (s.image f).Nonempty) diff --git a/Mathlib/Data/Finset/Sort.lean b/Mathlib/Data/Finset/Sort.lean index 486acd9c00f1b..d4354b5039a5b 100644 --- a/Mathlib/Data/Finset/Sort.lean +++ b/Mathlib/Data/Finset/Sort.lean @@ -113,7 +113,7 @@ theorem sorted_zero_eq_min'_aux (s : Finset α) (h : 0 < (s.sort (· ≤ ·)).le obtain ⟨i, hi⟩ : ∃ i, l.get i = s.min' H := List.mem_iff_get.1 this rw [← hi] exact (s.sort_sorted (· ≤ ·)).rel_get_of_le (Nat.zero_le i) - · have : l.get ⟨0, h⟩ ∈ s := (Finset.mem_sort (α := α) (· ≤ ·)).1 (List.getElem_mem h) + · have : l.get ⟨0, h⟩ ∈ s := (Finset.mem_sort (α := α) (· ≤ ·)).1 (List.get_mem l _) exact s.min'_le _ this theorem sorted_zero_eq_min' {s : Finset α} {h : 0 < (s.sort (· ≤ ·)).length} : @@ -130,7 +130,7 @@ theorem sorted_last_eq_max'_aux (s : Finset α) let l := s.sort (· ≤ ·) apply le_antisymm · have : l.get ⟨(s.sort (· ≤ ·)).length - 1, h⟩ ∈ s := - (Finset.mem_sort (α := α) (· ≤ ·)).1 (List.getElem_mem h) + (Finset.mem_sort (α := α) (· ≤ ·)).1 (List.get_mem l _) exact s.le_max' _ this · have : s.max' H ∈ l := (Finset.mem_sort (α := α) (· ≤ ·)).mpr (s.max'_mem H) obtain ⟨i, hi⟩ : ∃ i, l.get i = s.max' H := List.mem_iff_get.1 this diff --git a/Mathlib/Data/Finsupp/Defs.lean b/Mathlib/Data/Finsupp/Defs.lean index 7ac40e922fd7b..be9894c31daf0 100644 --- a/Mathlib/Data/Finsupp/Defs.lean +++ b/Mathlib/Data/Finsupp/Defs.lean @@ -7,6 +7,7 @@ import Mathlib.Algebra.Group.Indicator import Mathlib.Algebra.Group.Submonoid.Basic import Mathlib.Data.Finset.Max import Mathlib.Data.Set.Finite.Basic +import Mathlib.Algebra.Group.TypeTags.Hom /-! # Type of functions with finite support diff --git a/Mathlib/Data/Finsupp/Fin.lean b/Mathlib/Data/Finsupp/Fin.lean index b75198493ebe5..4e7868d955fcf 100644 --- a/Mathlib/Data/Finsupp/Fin.lean +++ b/Mathlib/Data/Finsupp/Fin.lean @@ -17,6 +17,7 @@ In this context, we prove some usual properties of `tail` and `cons`, analogous `Data.Fin.Tuple.Basic`. -/ +open Function noncomputable section @@ -86,4 +87,8 @@ lemma cons_support : (s.cons y).support ⊆ insert 0 (s.support.map (Fin.succEmb rintro i rfl simpa [Finsupp.mem_support_iff] using hi +lemma cons_right_injective {n : ℕ} {M : Type*} [Zero M] (y : M) : + Injective (Finsupp.cons y : (Fin n →₀ M) → Fin (n + 1) →₀ M) := + (equivFunOnFinite.symm.injective.comp ((Fin.cons_right_injective _).comp DFunLike.coe_injective)) + end Finsupp diff --git a/Mathlib/Data/Finsupp/MonomialOrder.lean b/Mathlib/Data/Finsupp/MonomialOrder.lean new file mode 100644 index 0000000000000..431fcb7d3ce34 --- /dev/null +++ b/Mathlib/Data/Finsupp/MonomialOrder.lean @@ -0,0 +1,156 @@ +/- +Copyright (c) 2024 Antoine Chambert-Loir. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Antoine Chambert-Loir +-/ +import Mathlib.Data.Finsupp.Lex +import Mathlib.Data.Finsupp.WellFounded +import Mathlib.Data.List.TFAE + +/-! # Monomial orders + +## Monomial orders + +A *monomial order* is well ordering relation on a type of the form `σ →₀ ℕ` which +is compatible with addition and for which `0` is the smallest element. +Since several monomial orders may have to be used simultaneously, one cannot +get them as instances. +In this formalization, they are presented as a structure `MonomialOrder` which encapsulates +`MonomialOrder.toSyn`, an additive and monotone isomorphism to a linearly ordered cancellative +additive commutative monoid. +The entry `MonomialOrder.wf` asserts that `MonomialOrder.syn` is well founded. + +The terminology comes from commutative algebra and algebraic geometry, especially Gröbner bases, +where `c : σ →₀ ℕ` are exponents of monomials. + +Given a monomial order `m : MonomialOrder σ`, we provide the notation +`c ≼[m] d` and `c ≺[m] d` to compare `c d : σ →₀ ℕ` with respect to `m`. +It is activated using `open scoped MonomialOrder`. + +## Examples + +Commutative algebra defines many monomial orders, with different usefulness ranges. +In this file, we provide the basic example of lexicographic ordering. +For the graded lexicographic ordering, see `Mathlib/Data/Finsupp/DegLex.lean` + +* `MonomialOrder.lex` : the lexicographic ordering on `σ →₀ ℕ`. +For this, `σ` needs to be embedded with an ordering relation which satisfies `WellFoundedGT σ`. +(This last property is automatic when `σ` is finite). + +The type synonym is `Lex (σ →₀ ℕ)` and the two lemmas `MonomialOrder.lex_le_iff` +and `MonomialOrder.lex_lt_iff` rewrite the ordering as comparisons in the type `Lex (σ →₀ ℕ)`. + +## References + +* [Cox, Little and O'Shea, *Ideals, varieties, and algorithms*][coxlittleoshea1997] +* [Becker and Weispfenning, *Gröbner bases*][Becker-Weispfenning1993] + +## Note + +In algebraic geometry, when the finitely many variables are indexed by integers, +it is customary to order them using the opposite order : `MvPolynomial.X 0 > MvPolynomial.X 1 > … ` + +-/ + +/-- Monomial orders : equivalence of `σ →₀ ℕ` with a well ordered type -/ +structure MonomialOrder (σ : Type*) where + /-- The synonym type -/ + syn : Type* + /-- `syn` is a linearly ordered cancellative additive commutative monoid -/ + locacm : LinearOrderedCancelAddCommMonoid syn := by infer_instance + /-- the additive equivalence from `σ →₀ ℕ` to `syn` -/ + toSyn : (σ →₀ ℕ) ≃+ syn + /-- `toSyn` is monotone -/ + toSyn_monotone : Monotone toSyn + /-- `syn` is a well ordering -/ + wf : WellFoundedLT syn := by infer_instance + +attribute [instance] MonomialOrder.locacm MonomialOrder.wf + +namespace MonomialOrder + +variable {σ : Type*} (m : MonomialOrder σ) + +lemma le_add_right (a b : σ →₀ ℕ) : + m.toSyn a ≤ m.toSyn a + m.toSyn b := by + rw [← map_add] + exact m.toSyn_monotone le_self_add + +instance orderBot : OrderBot (m.syn) where + bot := 0 + bot_le a := by + have := m.le_add_right 0 (m.toSyn.symm a) + simp [map_add, zero_add] at this + exact this + +@[simp] +theorem bot_eq_zero : (⊥ : m.syn) = 0 := rfl + +theorem eq_zero_iff {a : m.syn} : a = 0 ↔ a ≤ 0 := eq_bot_iff + +lemma toSyn_strictMono : StrictMono (m.toSyn) := by + apply m.toSyn_monotone.strictMono_of_injective m.toSyn.injective + +/-- Given a monomial order, notation for the corresponding strict order relation on `σ →₀ ℕ` -/ +scoped +notation:25 c "≺[" m:25 "]" d:25 => (MonomialOrder.toSyn m c < MonomialOrder.toSyn m d) + +/-- Given a monomial order, notation for the corresponding order relation on `σ →₀ ℕ` -/ +scoped +notation:25 c "≼[" m:25 "]" d:25 => (MonomialOrder.toSyn m c ≤ MonomialOrder.toSyn m d) + +end MonomialOrder + +section Lex + +open Finsupp + +open scoped MonomialOrder + +-- The linear order on `Finsupp`s obtained by the lexicographic ordering. -/ +noncomputable instance {α N : Type*} [LinearOrder α] [OrderedCancelAddCommMonoid N] : + OrderedCancelAddCommMonoid (Lex (α →₀ N)) where + le_of_add_le_add_left a b c h := by simpa only [add_le_add_iff_left] using h + add_le_add_left a b h c := by simpa only [add_le_add_iff_left] using h + +theorem Finsupp.lex_lt_iff {α N : Type*} [LinearOrder α] [LinearOrder N] [Zero N] + {a b : Lex (α →₀ N)} : + a < b ↔ ∃ i, (∀ j, j< i → ofLex a j = ofLex b j) ∧ ofLex a i < ofLex b i := + Finsupp.lex_def + +theorem Finsupp.lex_le_iff {α N : Type*} [LinearOrder α] [LinearOrder N] [Zero N] + {a b : Lex (α →₀ N)} : + a ≤ b ↔ a = b ∨ ∃ i, (∀ j, j< i → ofLex a j = ofLex b j) ∧ ofLex a i < ofLex b i := by + rw [le_iff_eq_or_lt, Finsupp.lex_lt_iff] + +/-- for the lexicographic ordering, X 0 * X 1 < X 0 ^ 2 -/ +example : toLex (Finsupp.single 0 2) > toLex (Finsupp.single 0 1 + Finsupp.single 1 1) := by + use 0; simp + +/-- for the lexicographic ordering, X 1 < X 0 -/ +example : toLex (Finsupp.single 1 1) < toLex (Finsupp.single 0 1) := by + use 0; simp + +/-- for the lexicographic ordering, X 1 < X 0 ^ 2 -/ +example : toLex (Finsupp.single 1 1) < toLex (Finsupp.single 0 2) := by + use 0; simp + + +variable {σ : Type*} [LinearOrder σ] + +/-- The lexicographic order on `σ →₀ ℕ`, as a `MonomialOrder` -/ +noncomputable def MonomialOrder.lex [WellFoundedGT σ] : + MonomialOrder σ where + syn := Lex (σ →₀ ℕ) + toSyn := + { toEquiv := toLex + map_add' := toLex_add } + toSyn_monotone := Finsupp.toLex_monotone + +theorem MonomialOrder.lex_le_iff [WellFoundedGT σ] {c d : σ →₀ ℕ} : + c ≼[lex] d ↔ toLex c ≤ toLex d := Iff.rfl + +theorem MonomialOrder.lex_lt_iff [WellFoundedGT σ] {c d : σ →₀ ℕ} : + c ≺[lex] d ↔ toLex c < toLex d := Iff.rfl + +end Lex diff --git a/Mathlib/Data/Fintype/Basic.lean b/Mathlib/Data/Fintype/Basic.lean index 3bda18e430ecb..d381a6d94e4b9 100644 --- a/Mathlib/Data/Fintype/Basic.lean +++ b/Mathlib/Data/Fintype/Basic.lean @@ -5,6 +5,7 @@ Authors: Mario Carneiro -/ import Mathlib.Data.Finset.Image import Mathlib.Data.List.FinRange +import Mathlib.Data.Finite.Defs /-! # Finite types @@ -139,7 +140,7 @@ theorem codisjoint_left : Codisjoint s t ↔ ∀ ⦃a⦄, a ∉ s → a ∈ t := classical simp [codisjoint_iff, eq_univ_iff_forall, or_iff_not_imp_left] theorem codisjoint_right : Codisjoint s t ↔ ∀ ⦃a⦄, a ∉ t → a ∈ s := - Codisjoint_comm.trans codisjoint_left + codisjoint_comm.trans codisjoint_left instance booleanAlgebra [DecidableEq α] : BooleanAlgebra (Finset α) := GeneralizedBooleanAlgebra.toBooleanAlgebra diff --git a/Mathlib/Data/Fintype/BigOperators.lean b/Mathlib/Data/Fintype/BigOperators.lean index 6c8241d4dd465..0825cf4335415 100644 --- a/Mathlib/Data/Fintype/BigOperators.lean +++ b/Mathlib/Data/Fintype/BigOperators.lean @@ -172,7 +172,8 @@ theorem Fintype.card_fun [DecidableEq α] [Fintype α] [Fintype β] : simp @[simp] -theorem card_vector [Fintype α] (n : ℕ) : Fintype.card (Vector α n) = Fintype.card α ^ n := by +theorem card_vector [Fintype α] (n : ℕ) : + Fintype.card (Mathlib.Vector α n) = Fintype.card α ^ n := by rw [Fintype.ofEquiv_card]; simp /-- It is equivalent to compute the product of a function over `Fin n` or `Finset.range n`. -/ diff --git a/Mathlib/Data/Fintype/Fin.lean b/Mathlib/Data/Fintype/Fin.lean index 8744f61e2f3ae..96b7ea32bd858 100644 --- a/Mathlib/Data/Fintype/Fin.lean +++ b/Mathlib/Data/Fintype/Fin.lean @@ -61,7 +61,7 @@ theorem card_filter_univ_succ' (p : Fin (n + 1) → Prop) [DecidablePred p] : #{x | p x} = ite (p 0) 1 0 + #{x | p (.succ x)}:= by rw [card_filter_univ_succ]; split_ifs <;> simp [add_comm] -theorem card_filter_univ_eq_vector_get_eq_count [DecidableEq α] (a : α) (v : Vector α n) : +theorem card_filter_univ_eq_vector_get_eq_count [DecidableEq α] (a : α) (v : Mathlib.Vector α n) : #{i | v.get i = a} = v.toList.count a := by induction' v with n x xs hxs · simp diff --git a/Mathlib/Data/Fintype/Vector.lean b/Mathlib/Data/Fintype/Vector.lean index 2e94be07c8dbd..9b833c039d387 100644 --- a/Mathlib/Data/Fintype/Vector.lean +++ b/Mathlib/Data/Fintype/Vector.lean @@ -14,7 +14,7 @@ open Mathlib (Vector) variable {α : Type*} -instance Vector.fintype [Fintype α] {n : ℕ} : Fintype (Vector α n) := +instance Vector.fintype [Fintype α] {n : ℕ} : Fintype (Mathlib.Vector α n) := Fintype.ofEquiv _ (Equiv.vectorEquivFin _ _).symm instance [DecidableEq α] [Fintype α] {n : ℕ} : Fintype (Sym.Sym' α n) := by diff --git a/Mathlib/Data/Int/Cast/Lemmas.lean b/Mathlib/Data/Int/Cast/Lemmas.lean index edf29c1a81e49..d887d52523d54 100644 --- a/Mathlib/Data/Int/Cast/Lemmas.lean +++ b/Mathlib/Data/Int/Cast/Lemmas.lean @@ -295,14 +295,14 @@ lemma zmultiplesHom_apply (x : β) (n : ℤ) : zmultiplesHom β x n = n • x := lemma zmultiplesHom_symm_apply (f : ℤ →+ β) : (zmultiplesHom β).symm f = f 1 := rfl @[to_additive existing (attr := simp)] -lemma zpowersHom_apply (x : α) (n : Multiplicative ℤ) : zpowersHom α x n = x ^ toAdd n := rfl +lemma zpowersHom_apply (x : α) (n : Multiplicative ℤ) : zpowersHom α x n = x ^ n.toAdd := rfl @[to_additive existing (attr := simp)] lemma zpowersHom_symm_apply (f : Multiplicative ℤ →* α) : (zpowersHom α).symm f = f (ofAdd 1) := rfl lemma MonoidHom.apply_mint (f : Multiplicative ℤ →* α) (n : Multiplicative ℤ) : - f n = f (ofAdd 1) ^ (toAdd n) := by + f n = f (ofAdd 1) ^ n.toAdd := by rw [← zpowersHom_symm_apply, ← zpowersHom_apply, Equiv.apply_symm_apply] lemma AddMonoidHom.apply_int (f : ℤ →+ β) (n : ℤ) : f n = n • f 1 := by @@ -324,7 +324,7 @@ def zpowersMulHom : α ≃* (Multiplicative ℤ →* α) := variable {α} @[simp] -lemma zpowersMulHom_apply (x : α) (n : Multiplicative ℤ) : zpowersMulHom α x n = x ^ toAdd n := rfl +lemma zpowersMulHom_apply (x : α) (n : Multiplicative ℤ) : zpowersMulHom α x n = x ^ n.toAdd := rfl @[simp] lemma zpowersMulHom_symm_apply (f : Multiplicative ℤ →* α) : diff --git a/Mathlib/Data/Int/GCD.lean b/Mathlib/Data/Int/GCD.lean index eccc02d840c40..e6b7b6ec9f4e8 100644 --- a/Mathlib/Data/Int/GCD.lean +++ b/Mathlib/Data/Int/GCD.lean @@ -7,8 +7,8 @@ import Mathlib.Algebra.Group.Int import Mathlib.Algebra.GroupWithZero.Semiconj import Mathlib.Algebra.Group.Commute.Units import Mathlib.Data.Nat.GCD.Basic -import Mathlib.Order.Lattice import Mathlib.Data.Set.Operations +import Mathlib.Order.Basic import Mathlib.Order.Bounds.Defs /-! diff --git a/Mathlib/Data/Int/Interval.lean b/Mathlib/Data/Int/Interval.lean index a93f1ff49aa84..cd94ea340d1c5 100644 --- a/Mathlib/Data/Int/Interval.lean +++ b/Mathlib/Data/Int/Interval.lean @@ -129,6 +129,11 @@ theorem card_Ioc_of_le (h : a ≤ b) : (#(Ioc a b) : ℤ) = b - a := by theorem card_Ioo_of_lt (h : a < b) : (#(Ioo a b) : ℤ) = b - a - 1 := by rw [card_Ioo, sub_sub, toNat_sub_of_le h] +theorem Icc_eq_pair : Finset.Icc a (a + 1) = {a, a + 1} := by + ext + simp + omega + -- Porting note (https://github.com/leanprover-community/mathlib4/issues/11119): removed `simp` attribute because `simpNF` says it can prove it theorem card_fintype_Icc : Fintype.card (Set.Icc a b) = (b + 1 - a).toNat := by rw [← card_Icc, Fintype.card_ofFinset] diff --git a/Mathlib/Data/Int/Log.lean b/Mathlib/Data/Int/Log.lean index e6f5f9f457159..4d5f3c0e38722 100644 --- a/Mathlib/Data/Int/Log.lean +++ b/Mathlib/Data/Int/Log.lean @@ -46,6 +46,7 @@ def digits (b : ℕ) (q : ℚ) (n : ℕ) : ℕ := * `Int.neg_log_inv_eq_clog`, `Int.neg_clog_inv_eq_log`: the link between the two definitions. -/ +assert_not_exists Finset variable {R : Type*} [LinearOrderedSemifield R] [FloorSemiring R] diff --git a/Mathlib/Data/Int/WithZero.lean b/Mathlib/Data/Int/WithZero.lean index 4a74559dbbf98..de4c3c4143538 100644 --- a/Mathlib/Data/Int/WithZero.lean +++ b/Mathlib/Data/Int/WithZero.lean @@ -14,7 +14,7 @@ the morphism `WithZeroMultInt.toNNReal`. ## Main Definitions * `WithZeroMultInt.toNNReal` : The `MonoidWithZeroHom` from `ℤₘ₀ → ℝ≥0` sending `0 ↦ 0` and - `x ↦ e^(Multiplicative.toAdd (WithZero.unzero hx)` when `x ≠ 0`, for a nonzero `e : ℝ≥0`. + `x ↦ e^((WithZero.unzero hx).toAdd)` when `x ≠ 0`, for a nonzero `e : ℝ≥0`. ## Main Results @@ -26,6 +26,8 @@ the morphism `WithZeroMultInt.toNNReal`. WithZero, multiplicative, nnreal -/ +assert_not_exists Finset + noncomputable section open scoped NNReal @@ -35,9 +37,9 @@ open Multiplicative WithZero namespace WithZeroMulInt /-- Given a nonzero `e : ℝ≥0`, this is the map `ℤₘ₀ → ℝ≥0` sending `0 ↦ 0` and - `x ↦ e^(Multiplicative.toAdd (WithZero.unzero hx)` when `x ≠ 0` as a `MonoidWithZeroHom`. -/ + `x ↦ e^(WithZero.unzero hx).toAdd` when `x ≠ 0` as a `MonoidWithZeroHom`. -/ def toNNReal {e : ℝ≥0} (he : e ≠ 0) : ℤₘ₀ →*₀ ℝ≥0 where - toFun := fun x ↦ if hx : x = 0 then 0 else e ^ Multiplicative.toAdd (WithZero.unzero hx) + toFun := fun x ↦ if hx : x = 0 then 0 else e ^ (WithZero.unzero hx).toAdd map_zero' := rfl map_one' := by simp only [dif_neg one_ne_zero] @@ -61,7 +63,7 @@ theorem toNNReal_pos_apply {e : ℝ≥0} (he : e ≠ 0) {x : ℤₘ₀} (hx : x split_ifs; rfl theorem toNNReal_neg_apply {e : ℝ≥0} (he : e ≠ 0) {x : ℤₘ₀} (hx : x ≠ 0) : - toNNReal he x = e ^ Multiplicative.toAdd (WithZero.unzero hx) := by + toNNReal he x = e ^ (WithZero.unzero hx).toAdd := by simp only [toNNReal, MonoidWithZeroHom.coe_mk, ZeroHom.coe_mk] split_ifs · tauto diff --git a/Mathlib/Data/List/Basic.lean b/Mathlib/Data/List/Basic.lean index 8e27205a4ec40..1f583b6d964c0 100644 --- a/Mathlib/Data/List/Basic.lean +++ b/Mathlib/Data/List/Basic.lean @@ -34,7 +34,7 @@ universe u v w variable {ι : Type*} {α : Type u} {β : Type v} {γ : Type w} {l₁ l₂ : List α} /-- `≤` implies not `>` for lists. -/ -@[deprecated (since := "2024-07-27")] +@[deprecated "No deprecation message was provided." (since := "2024-07-27")] theorem le_eq_not_gt [LT α] : ∀ l₁ l₂ : List α, (l₁ ≤ l₂) = ¬l₂ < l₁ := fun _ _ => rfl -- Porting note: Delete this attribute @@ -496,7 +496,7 @@ theorem get_tail (l : List α) (i) (h : i < l.tail.length) l.tail.get ⟨i, h⟩ = l.get ⟨i + 1, h'⟩ := by cases l <;> [cases h; rfl] -@[deprecated (since := "2024-08-22")] +@[deprecated "No deprecation message was provided." (since := "2024-08-22")] 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⟩ := @@ -627,7 +627,7 @@ 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 _ -@[deprecated (since := "2024-04-07")] +@[deprecated "No deprecation message was provided." (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 @@ -737,7 +737,6 @@ end IndexOf /-! ### nth element -/ section deprecated -set_option linter.deprecated false @[simp] theorem getElem?_length (l : List α) : l[l.length]? = none := getElem?_len_le le_rfl @@ -754,19 +753,20 @@ theorem getElem_map_rev (f : α → β) {l} {n : Nat} {h : n < l.length} : /-- A version of `get_map` that can be used for rewriting. -/ @[deprecated getElem_map_rev (since := "2024-06-12")] 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 _) + f (get l n) = get (map f l) ⟨n.1, (l.length_map f).symm ▸ n.2⟩ := Eq.symm (getElem_map _) 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 + (getLast_eq_getElem l _).symm 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] + rw [drop_eq_getElem_cons h, take, take] + simp theorem ext_get?' {l₁ l₂ : List α} (h' : ∀ n < max l₁.length l₂.length, l₁.get? n = l₂.get? n) : l₁ = l₂ := by - apply ext + apply ext_get? intro n rcases Nat.lt_or_ge n <| max l₁.length l₂.length with hn | hn · exact h' n hn @@ -831,6 +831,8 @@ theorem get_reverse (l : List α) (i : Nat) (h1 h2) : dsimp omega +set_option linter.deprecated false + theorem get_reverse' (l : List α) (n) (hn') : l.reverse.get n = l.get ⟨l.length - 1 - n, hn'⟩ := by rw [eq_comm] @@ -2257,7 +2259,7 @@ theorem length_dropSlice_lt (i j : ℕ) (hj : 0 < j) (xs : List α) (hi : i < xs simp; omega set_option linter.deprecated false in -@[deprecated (since := "2024-07-25")] +@[deprecated "No deprecation message was provided." (since := "2024-07-25")] theorem sizeOf_dropSlice_lt [SizeOf α] (i j : ℕ) (hj : 0 < j) (xs : List α) (hi : i < xs.length) : SizeOf.sizeOf (List.dropSlice i j xs) < SizeOf.sizeOf xs := by induction xs generalizing i j hj with diff --git a/Mathlib/Data/List/Cycle.lean b/Mathlib/Data/List/Cycle.lean index 876e1a2130482..34485c3ee467f 100644 --- a/Mathlib/Data/List/Cycle.lean +++ b/Mathlib/Data/List/Cycle.lean @@ -217,7 +217,7 @@ theorem prev_ne_cons_cons (y z : α) (h : x ∈ y :: z :: l) (hy : x ≠ y) (hz · rw [prev, dif_neg hy, if_neg hz] theorem next_mem (h : x ∈ l) : l.next x h ∈ l := - nextOr_mem (getElem_mem _) + nextOr_mem (get_mem _ _) theorem prev_mem (h : x ∈ l) : l.prev x h ∈ l := by cases' l with hd tl @@ -233,7 +233,7 @@ theorem prev_mem (h : x ∈ l) : l.prev x h ∈ l := by · exact mem_cons_of_mem _ (hl _ _) theorem next_get (l : List α) (h : Nodup l) (i : Fin l.length) : - next l (l.get i) (getElem_mem _) = + 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 @@ -254,7 +254,7 @@ theorem next_get (l : List α) (h : Nodup l) (i : Fin l.length) : · subst hi' rw [next_getLast_cons] · simp [hi', get] - · rw [get_cons_succ]; exact getElem_mem _ + · rw [get_cons_succ]; exact get_mem _ _ · exact hx' · simp [getLast_eq_getElem] · exact hn.of_cons @@ -271,12 +271,12 @@ theorem next_get (l : List α) (h : Nodup l) (i : Fin l.length) : intro h have := nodup_iff_injective_get.1 hn h simp at this; simp [this] at hi' - · rw [get_cons_succ]; exact getElem_mem _ + · rw [get_cons_succ]; exact get_mem _ _ -- 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) (getElem_mem _) = + 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 diff --git a/Mathlib/Data/List/Defs.lean b/Mathlib/Data/List/Defs.lean index 03674193faaec..4b86b7218cdfb 100644 --- a/Mathlib/Data/List/Defs.lean +++ b/Mathlib/Data/List/Defs.lean @@ -488,9 +488,17 @@ theorem length_mapAccumr₂ : end MapAccumr +/- #adaptation_note: this attribute should be removed after Mathlib moves to v4.15.0-rc1. -/ +set_option allowUnsafeReducibility true in +attribute [semireducible] Fin.foldr.loop + /-- All elements of `Fin n`, from `0` to `n-1`. The corresponding finset is `Finset.univ`. -/ -def finRange (n : ℕ) : List (Fin n) := - (range n).pmap Fin.mk fun _ => List.mem_range.1 +-- Note that we use `ofFn (fun x => x)` instead of `ofFn id` to avoid leaving `id` in the terms +-- for e.g. `Fintype (Fin n)`. +def finRange (n : Nat) : List (Fin n) := ofFn (fun x => x) + +-- Verify that `finRange` is semireducible. +example : finRange 3 = [0, 1, 2] := rfl section Deprecated diff --git a/Mathlib/Data/List/FinRange.lean b/Mathlib/Data/List/FinRange.lean index 62d8122999597..bf592cfe78937 100644 --- a/Mathlib/Data/List/FinRange.lean +++ b/Mathlib/Data/List/FinRange.lean @@ -4,8 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro, Kenny Lau, Kim Morrison, Alex Keizer -/ import Mathlib.Data.List.OfFn -import Mathlib.Data.List.Range import Batteries.Data.List.Perm +import Mathlib.Data.List.Nodup /-! # Lists of elements of `Fin n` @@ -21,10 +21,66 @@ namespace List variable {α : Type u} + +theorem finRange_eq_pmap_range (n : ℕ) : finRange n = (range n).pmap Fin.mk (by simp) := by + apply List.ext_getElem <;> simp [finRange] + +@[simp] +theorem finRange_zero : finRange 0 = [] := rfl + +@[simp] +theorem mem_finRange {n : ℕ} (a : Fin n) : a ∈ finRange n := by + rw [finRange_eq_pmap_range] + exact mem_pmap.2 + ⟨a.1, mem_range.2 a.2, by + cases a + rfl⟩ + +theorem nodup_finRange (n : ℕ) : (finRange n).Nodup := by + rw [finRange_eq_pmap_range] + exact (Pairwise.pmap (nodup_range n) _) fun _ _ _ _ => @Fin.ne_of_val_ne _ ⟨_, _⟩ ⟨_, _⟩ + +@[simp] +theorem length_finRange (n : ℕ) : (finRange n).length = n := by + simp [finRange] + +@[simp] +theorem finRange_eq_nil {n : ℕ} : finRange n = [] ↔ n = 0 := by + rw [← length_eq_zero, length_finRange] + +theorem pairwise_lt_finRange (n : ℕ) : Pairwise (· < ·) (finRange n) := by + rw [finRange_eq_pmap_range] + exact (List.pairwise_lt_range n).pmap (by simp) (by simp) + +theorem pairwise_le_finRange (n : ℕ) : Pairwise (· ≤ ·) (finRange n) := by + rw [finRange_eq_pmap_range] + exact (List.pairwise_le_range n).pmap (by simp) (by simp) + +@[simp] +theorem getElem_finRange {n : ℕ} {i : ℕ} (h) : + (finRange n)[i] = ⟨i, length_finRange n ▸ h⟩ := by + simp [finRange, getElem_range, getElem_pmap] + +-- Porting note (https://github.com/leanprover-community/mathlib4/issues/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_finRange := get_finRange + +@[simp] +theorem finRange_map_get (l : List α) : (finRange l.length).map l.get = l := + List.ext_get (by simp) (by simp) + +@[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 + have h₂ : (finRange k).get ⟨i, by simp⟩ = i := get_finRange _ + simpa using (Nodup.get_inj_iff (nodup_finRange k)).mp (Eq.trans h₁ h₂.symm) + @[simp] theorem map_coe_finRange (n : ℕ) : ((finRange n) : List (Fin n)).map (Fin.val) = List.range n := by - simp_rw [finRange, map_pmap, pmap_eq_map] - exact List.map_id _ + apply List.ext_getElem <;> simp theorem finRange_succ_eq_map (n : ℕ) : finRange n.succ = 0 :: (finRange n).map Fin.succ := by apply map_injective_iff.mpr Fin.val_injective @@ -45,7 +101,7 @@ theorem ofFn_eq_pmap {n} {f : Fin n → α} : exact ext_getElem (by simp) fun i hi1 hi2 => by simp [List.getElem_ofFn f i hi1] theorem ofFn_id (n) : ofFn id = finRange n := - ofFn_eq_pmap + rfl theorem ofFn_eq_map {n} {f : Fin n → α} : ofFn f = (finRange n).map f := by rw [← ofFn_id, map_ofFn, Function.comp_id] diff --git a/Mathlib/Data/List/Flatten.lean b/Mathlib/Data/List/Flatten.lean index f6fbc8e3044fc..797ba9dc5c297 100644 --- a/Mathlib/Data/List/Flatten.lean +++ b/Mathlib/Data/List/Flatten.lean @@ -158,7 +158,8 @@ theorem append_flatten_map_append (L : List (List α)) (x : List α) : @[deprecated (since := "2024-10-15")] alias append_join_map_append := append_flatten_map_append -@[deprecated (since := "2024-08-15")] theorem sublist_join {l} {L : List (List α)} (h : l ∈ L) : +@[deprecated "No deprecation message was provided." (since := "2024-08-15")] +theorem sublist_join {l} {L : List (List α)} (h : l ∈ L) : l <+ L.flatten := sublist_flatten_of_mem h diff --git a/Mathlib/Data/List/Indexes.lean b/Mathlib/Data/List/Indexes.lean index 6c8ce5ff6c794..af5d70ec012f2 100644 --- a/Mathlib/Data/List/Indexes.lean +++ b/Mathlib/Data/List/Indexes.lean @@ -3,7 +3,6 @@ Copyright (c) 2020 Jannis Limperg. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jannis Limperg -/ -import Mathlib.Order.Lattice import Mathlib.Data.List.Basic /-! @@ -84,7 +83,7 @@ theorem mapIdx_eq_ofFn (l : List α) (f : ℕ → α → β) : section deprecated /-- Lean3 `map_with_index` helper function -/ -@[deprecated (since := "2024-08-15")] +@[deprecated "No deprecation message was provided." (since := "2024-08-15")] protected def oldMapIdxCore (f : ℕ → α → β) : ℕ → List α → List β | _, [] => [] | k, a :: as => f k a :: List.oldMapIdxCore f (k + 1) as @@ -92,12 +91,12 @@ protected def oldMapIdxCore (f : ℕ → α → β) : ℕ → List α → List set_option linter.deprecated false in /-- Given a function `f : ℕ → α → β` and `as : List α`, `as = [a₀, a₁, ...]`, returns the list `[f 0 a₀, f 1 a₁, ...]`. -/ -@[deprecated (since := "2024-08-15")] +@[deprecated "No deprecation message was provided." (since := "2024-08-15")] protected def oldMapIdx (f : ℕ → α → β) (as : List α) : List β := List.oldMapIdxCore f 0 as set_option linter.deprecated false in -@[deprecated (since := "2024-08-15")] +@[deprecated "No deprecation message was provided." (since := "2024-08-15")] protected theorem oldMapIdxCore_eq (l : List α) (f : ℕ → α → β) (n : ℕ) : l.oldMapIdxCore f n = l.oldMapIdx fun i a ↦ f (i + n) a := by induction' l with hd tl hl generalizing f n @@ -106,7 +105,7 @@ protected theorem oldMapIdxCore_eq (l : List α) (f : ℕ → α → β) (n : simp only [List.oldMapIdxCore, hl, Nat.add_left_comm, Nat.add_comm, Nat.add_zero] set_option linter.deprecated false in -@[deprecated (since := "2024-08-15")] +@[deprecated "No deprecation message was provided." (since := "2024-08-15")] protected theorem oldMapIdxCore_append : ∀ (f : ℕ → α → β) (n : ℕ) (l₁ l₂ : List α), List.oldMapIdxCore f n (l₁ ++ l₂) = List.oldMapIdxCore f n l₁ ++ List.oldMapIdxCore f (n + l₁.length) l₂ := by @@ -134,7 +133,7 @@ protected theorem oldMapIdxCore_append : ∀ (f : ℕ → α → β) (n : ℕ) ( rw [Nat.add_assoc]; simp only [Nat.add_comm] set_option linter.deprecated false in -@[deprecated (since := "2024-08-15")] +@[deprecated "No deprecation message was provided." (since := "2024-08-15")] protected theorem oldMapIdx_append : ∀ (f : ℕ → α → β) (l : List α) (e : α), List.oldMapIdx f (l ++ [e]) = List.oldMapIdx f l ++ [f l.length e] := by intros f l e @@ -143,7 +142,7 @@ protected theorem oldMapIdx_append : ∀ (f : ℕ → α → β) (l : List α) ( simp only [Nat.zero_add]; rfl set_option linter.deprecated false in -@[deprecated (since := "2024-08-15")] +@[deprecated "No deprecation message was provided." (since := "2024-08-15")] protected theorem new_def_eq_old_def : ∀ (f : ℕ → α → β) (l : List α), l.mapIdx f = List.oldMapIdx f l := by intro f diff --git a/Mathlib/Data/List/Lex.lean b/Mathlib/Data/List/Lex.lean index fef097d96a69f..69566d9aa5d91 100644 --- a/Mathlib/Data/List/Lex.lean +++ b/Mathlib/Data/List/Lex.lean @@ -99,7 +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")] +@[deprecated "No deprecation message was provided." (since := "2024-07-30")] instance isStrictTotalOrder (r : α → α → Prop) [IsStrictTotalOrder α r] : IsStrictTotalOrder (List α) (Lex r) := { isStrictWeakOrder_of_isOrderConnected with } diff --git a/Mathlib/Data/List/NodupEquivFin.lean b/Mathlib/Data/List/NodupEquivFin.lean index fbcf74a9eec72..b355f9e72ed52 100644 --- a/Mathlib/Data/List/NodupEquivFin.lean +++ b/Mathlib/Data/List/NodupEquivFin.lean @@ -49,7 +49,7 @@ variable [DecidableEq α] the set of elements of `l`. -/ @[simps] def getEquiv (l : List α) (H : Nodup l) : Fin (length l) ≃ { x // x ∈ l } where - toFun i := ⟨get l i, getElem_mem i.2⟩ + toFun i := ⟨get l i, get_mem _ _⟩ invFun x := ⟨indexOf (↑x) l, indexOf_lt_length.2 x.2⟩ left_inv i := by simp only [List.get_indexOf, eq_self_iff_true, Fin.eta, Subtype.coe_mk, H] right_inv x := by simp diff --git a/Mathlib/Data/List/Pairwise.lean b/Mathlib/Data/List/Pairwise.lean index 4682916a610a0..be4f87bb84be6 100644 --- a/Mathlib/Data/List/Pairwise.lean +++ b/Mathlib/Data/List/Pairwise.lean @@ -50,7 +50,8 @@ theorem Pairwise.set_pairwise (hl : Pairwise R l) (hr : Symmetric R) : { x | x hl.forall hr -- Porting note: Duplicate of `pairwise_map` but with `f` explicit. -@[deprecated (since := "2024-02-25")] theorem pairwise_map' (f : β → α) : +@[deprecated "No deprecation message was provided." (since := "2024-02-25")] +theorem pairwise_map' (f : β → α) : ∀ {l : List β}, Pairwise R (map f l) ↔ Pairwise (R on f) l | [] => by simp only [map, Pairwise.nil] | b :: l => by diff --git a/Mathlib/Data/List/Permutation.lean b/Mathlib/Data/List/Permutation.lean index 74a32e39c3263..f436730690267 100644 --- a/Mathlib/Data/List/Permutation.lean +++ b/Mathlib/Data/List/Permutation.lean @@ -419,7 +419,7 @@ theorem length_permutations'Aux (s : List α) (x : α) : · simp · simpa using IH -@[deprecated (since := "2024-06-12")] +@[deprecated "No deprecation message was provided." (since := "2024-06-12")] theorem permutations'Aux_get_zero (s : List α) (x : α) (hn : 0 < length (permutations'Aux x s) := (by simp)) : (permutations'Aux x s).get ⟨0, hn⟩ = x :: s := diff --git a/Mathlib/Data/List/Range.lean b/Mathlib/Data/List/Range.lean index 6a342b20f3573..e133f0b507d6d 100644 --- a/Mathlib/Data/List/Range.lean +++ b/Mathlib/Data/List/Range.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro, Kenny Lau, Kim Morrison -/ import Mathlib.Data.List.Chain -import Mathlib.Data.List.Nodup /-! # Ranges of naturals as lists @@ -42,58 +41,10 @@ theorem chain_range_succ (r : ℕ → ℕ → Prop) (n a : ℕ) : rw [range_succ_eq_map, chain_cons, and_congr_right_iff, ← chain'_range_succ, range_succ_eq_map] exact fun _ => Iff.rfl -@[simp] -theorem finRange_zero : finRange 0 = [] := - rfl - -@[simp] -theorem mem_finRange {n : ℕ} (a : Fin n) : a ∈ finRange n := - mem_pmap.2 - ⟨a.1, mem_range.2 a.2, by - cases a - rfl⟩ - -theorem nodup_finRange (n : ℕ) : (finRange n).Nodup := - (Pairwise.pmap (nodup_range n) _) fun _ _ _ _ => @Fin.ne_of_val_ne _ ⟨_, _⟩ ⟨_, _⟩ - -@[simp] -theorem length_finRange (n : ℕ) : (finRange n).length = n := by - rw [finRange, length_pmap, length_range] - -@[simp] -theorem finRange_eq_nil {n : ℕ} : finRange n = [] ↔ n = 0 := by - rw [← length_eq_zero, length_finRange] - -theorem pairwise_lt_finRange (n : ℕ) : Pairwise (· < ·) (finRange n) := - (List.pairwise_lt_range n).pmap (by simp) (by simp) - -theorem pairwise_le_finRange (n : ℕ) : Pairwise (· ≤ ·) (finRange n) := - (List.pairwise_le_range n).pmap (by simp) (by simp) - -@[simp] -theorem getElem_finRange {n : ℕ} {i : ℕ} (h) : - (finRange n)[i] = ⟨i, length_finRange n ▸ h⟩ := by - simp [finRange, getElem_range, getElem_pmap] - --- Porting note (https://github.com/leanprover-community/mathlib4/issues/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) -@[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 - have h₂ : (finRange k).get ⟨i, by simp⟩ = i := get_finRange _ - simpa using (Nodup.get_inj_iff (nodup_finRange k)).mp (Eq.trans h₁ h₂.symm) section Ranges @@ -149,6 +100,7 @@ lemma ranges_flatten' : ∀ l : List ℕ, l.ranges.flatten = range (Nat.sum l) set_option linter.deprecated false in /-- Any entry of any member of `l.ranges` is strictly smaller than `Nat.sum l`. See `List.mem_mem_ranges_iff_lt_sum` for the version about `List.sum`. -/ +@[deprecated "Use `List.mem_mem_ranges_iff_lt_sum`." (since := "2024-11-18")] lemma mem_mem_ranges_iff_lt_natSum (l : List ℕ) {n : ℕ} : (∃ s ∈ l.ranges, n ∈ s) ↔ n < Nat.sum l := by rw [← mem_range, ← ranges_flatten', mem_flatten] diff --git a/Mathlib/Data/List/SplitLengths.lean b/Mathlib/Data/List/SplitLengths.lean index e41894fe16e0c..ae9a0052291fa 100644 --- a/Mathlib/Data/List/SplitLengths.lean +++ b/Mathlib/Data/List/SplitLengths.lean @@ -3,8 +3,8 @@ 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.Algebra.Group.Nat.Basic import Mathlib.Order.MinMax -import Mathlib.Algebra.Group.Nat /-! # Splitting a list to chunks of specified lengths diff --git a/Mathlib/Data/List/Sublists.lean b/Mathlib/Data/List/Sublists.lean index 108489251657e..aca81a62467f5 100644 --- a/Mathlib/Data/List/Sublists.lean +++ b/Mathlib/Data/List/Sublists.lean @@ -4,8 +4,9 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ import Mathlib.Data.Nat.Choose.Basic -import Mathlib.Data.List.Range +import Mathlib.Data.List.FinRange import Mathlib.Data.List.Perm.Basic +import Mathlib.Data.List.Lex /-! # sublists diff --git a/Mathlib/Data/Matrix/Block.lean b/Mathlib/Data/Matrix/Block.lean index d572c642d2bca..cb4875d44825f 100644 --- a/Mathlib/Data/Matrix/Block.lean +++ b/Mathlib/Data/Matrix/Block.lean @@ -40,7 +40,7 @@ dimensions. -/ @[pp_nodot] def fromBlocks (A : Matrix n l α) (B : Matrix n m α) (C : Matrix o l α) (D : Matrix o m α) : Matrix (n ⊕ o) (l ⊕ m) α := - of <| Sum.elim (fun i => Sum.elim (A i) (B i)) fun i => Sum.elim (C i) (D i) + of <| Sum.elim (fun i => Sum.elim (A i) (B i)) (fun j => Sum.elim (C j) (D j)) @[simp] theorem fromBlocks_apply₁₁ (A : Matrix n l α) (B : Matrix n m α) (C : Matrix o l α) diff --git a/Mathlib/Data/Multiset/Basic.lean b/Mathlib/Data/Multiset/Basic.lean index 4b30a22778c3a..83aedd9344065 100644 --- a/Mathlib/Data/Multiset/Basic.lean +++ b/Mathlib/Data/Multiset/Basic.lean @@ -3,13 +3,14 @@ Copyright (c) 2015 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ -import Mathlib.Algebra.Group.Nat +import Mathlib.Algebra.Group.Hom.Defs +import Mathlib.Algebra.Group.Nat.Basic import Mathlib.Algebra.Order.Sub.Unbundled.Basic +import Mathlib.Data.List.Perm.Basic +import Mathlib.Data.List.Perm.Lattice import Mathlib.Data.List.Perm.Subperm import Mathlib.Data.Set.List import Mathlib.Order.Hom.Basic -import Mathlib.Data.List.Perm.Lattice -import Mathlib.Data.List.Perm.Basic /-! # Multisets @@ -1719,15 +1720,10 @@ def filter (s : Multiset α) : Multiset α := theorem filter_zero : filter p 0 = 0 := rfl -#adaptation_note -/-- -Please re-enable the linter once we moved to `nightly-2024-06-22` or later. --/ -set_option linter.deprecated false in @[congr] theorem filter_congr {p q : α → Prop} [DecidablePred p] [DecidablePred q] {s : Multiset α} : (∀ x ∈ s, p x ↔ q x) → filter p s = filter q s := - Quot.inductionOn s fun _l h => congr_arg ofList <| filter_congr' <| by simpa using h + Quot.inductionOn s fun _l h => congr_arg ofList <| List.filter_congr <| by simpa using h @[simp] theorem filter_add (s t : Multiset α) : filter p (s + t) = filter p s + filter p t := diff --git a/Mathlib/Data/NNRat/Floor.lean b/Mathlib/Data/NNRat/Floor.lean index 9fffafbea6995..02d70c2c3d123 100644 --- a/Mathlib/Data/NNRat/Floor.lean +++ b/Mathlib/Data/NNRat/Floor.lean @@ -19,6 +19,8 @@ Note that we cannot talk about `Int.fract`, which currently only works for rings nnrat, rationals, ℚ≥0, floor -/ +assert_not_exists Finset + namespace NNRat instance : FloorSemiring ℚ≥0 where diff --git a/Mathlib/Data/NNReal/Defs.lean b/Mathlib/Data/NNReal/Defs.lean index 3b38d229cd409..c361f32478764 100644 --- a/Mathlib/Data/NNReal/Defs.lean +++ b/Mathlib/Data/NNReal/Defs.lean @@ -917,7 +917,7 @@ namespace Real /-- The absolute value on `ℝ` as a map to `ℝ≥0`. -/ -- Porting note (kmill): `pp_nodot` has no affect here --- unless RFC https://github.com/leanprover/lean4/issues/1910 leads to dot notation for CoeFun +-- unless RFC https://github.com/leanprover/lean4/issues/6178 leads to dot notation pp for CoeFun @[pp_nodot] def nnabs : ℝ →*₀ ℝ≥0 where toFun x := ⟨|x|, abs_nonneg x⟩ diff --git a/Mathlib/Data/NNReal/Star.lean b/Mathlib/Data/NNReal/Star.lean index c1f11b1539a4e..47c6a75c17849 100644 --- a/Mathlib/Data/NNReal/Star.lean +++ b/Mathlib/Data/NNReal/Star.lean @@ -10,6 +10,8 @@ import Mathlib.Data.Real.Star # The non-negative real numbers are a `*`-ring, with the trivial `*`-structure -/ +assert_not_exists Finset + open scoped NNReal instance : StarRing ℝ≥0 := starRingOfComm diff --git a/Mathlib/Data/Nat/Bits.lean b/Mathlib/Data/Nat/Bits.lean index 7079602da88d9..fcc0bc2b46077 100644 --- a/Mathlib/Data/Nat/Bits.lean +++ b/Mathlib/Data/Nat/Bits.lean @@ -3,8 +3,7 @@ Copyright (c) 2022 Praneeth Kolichala. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Praneeth Kolichala -/ -import Mathlib.Algebra.Group.Basic -import Mathlib.Algebra.Group.Nat +import Mathlib.Algebra.Group.Nat.Basic import Mathlib.Data.Nat.Defs import Mathlib.Data.Nat.BinaryRec import Mathlib.Data.List.Defs diff --git a/Mathlib/Data/Nat/Bitwise.lean b/Mathlib/Data/Nat/Bitwise.lean index 4c9b4b02ec2df..cf9e742f04bfc 100644 --- a/Mathlib/Data/Nat/Bitwise.lean +++ b/Mathlib/Data/Nat/Bitwise.lean @@ -3,7 +3,7 @@ Copyright (c) 2020 Markus Himmel. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Markus Himmel, Alex Keizer -/ -import Mathlib.Algebra.Group.Units.Basic +import Mathlib.Algebra.Group.Nat.Even import Mathlib.Algebra.NeZero import Mathlib.Algebra.Ring.Nat import Mathlib.Data.List.GetD diff --git a/Mathlib/Data/Nat/Cast/Basic.lean b/Mathlib/Data/Nat/Cast/Basic.lean index d4f2aa9e4fd08..c494b68c05067 100644 --- a/Mathlib/Data/Nat/Cast/Basic.lean +++ b/Mathlib/Data/Nat/Cast/Basic.lean @@ -4,6 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ import Mathlib.Algebra.Divisibility.Basic +import Mathlib.Algebra.Group.Even +import Mathlib.Algebra.Group.TypeTags.Hom import Mathlib.Algebra.Ring.Hom.Defs import Mathlib.Algebra.Ring.Nat @@ -157,6 +159,11 @@ theorem eq_natCast [FunLike F ℕ R] [RingHomClass F ℕ R] (f : F) : ∀ n, f n theorem map_natCast [FunLike F R S] [RingHomClass F R S] (f : F) : ∀ n : ℕ, f (n : R) = n := map_natCast' f <| map_one f +/-- This lemma is not marked `@[simp]` lemma because its `#discr_tree_key` (for the LHS) would just +be `DFunLike.coe _ _`, due to the `no_index` that https://github.com/leanprover/lean4/issues/2867 +forces us to include, and therefore it would negatively impact performance. + +If that issue is resolved, this can be marked `@[simp]`. -/ theorem map_ofNat [FunLike F R S] [RingHomClass F R S] (f : F) (n : ℕ) [Nat.AtLeastTwo n] : (f (no_index (OfNat.ofNat n)) : S) = OfNat.ofNat n := map_natCast f n @@ -220,7 +227,7 @@ lemma multiplesHom_apply (x : β) (n : ℕ) : multiplesHom β x n = n • x := r @[to_additive existing (attr := simp)] lemma powersHom_apply (x : α) (n : Multiplicative ℕ) : - powersHom α x n = x ^ Multiplicative.toAdd n := rfl + powersHom α x n = x ^ n.toAdd := rfl lemma multiplesHom_symm_apply (f : ℕ →+ β) : (multiplesHom β).symm f = f 1 := rfl @@ -229,7 +236,7 @@ lemma powersHom_symm_apply (f : Multiplicative ℕ →* α) : (powersHom α).symm f = f (Multiplicative.ofAdd 1) := rfl lemma MonoidHom.apply_mnat (f : Multiplicative ℕ →* α) (n : Multiplicative ℕ) : - f n = f (Multiplicative.ofAdd 1) ^ (Multiplicative.toAdd n) := by + f n = f (Multiplicative.ofAdd 1) ^ n.toAdd := by rw [← powersHom_symm_apply, ← powersHom_apply, Equiv.apply_symm_apply] @[ext] @@ -256,7 +263,7 @@ def powersMulHom : α ≃* (Multiplicative ℕ →* α) := @[simp] lemma multiplesAddHom_apply (x : β) (n : ℕ) : multiplesAddHom β x n = n • x := rfl @[simp] -lemma powersMulHom_apply (x : α) (n : Multiplicative ℕ) : powersMulHom α x n = x ^ toAdd n := rfl +lemma powersMulHom_apply (x : α) (n : Multiplicative ℕ) : powersMulHom α x n = x ^ n.toAdd := rfl @[simp] lemma multiplesAddHom_symm_apply (f : ℕ →+ β) : (multiplesAddHom β).symm f = f 1 := rfl diff --git a/Mathlib/Data/Nat/Defs.lean b/Mathlib/Data/Nat/Defs.lean index 9063d971434ff..20c3db731c333 100644 --- a/Mathlib/Data/Nat/Defs.lean +++ b/Mathlib/Data/Nat/Defs.lean @@ -72,6 +72,13 @@ instance instLinearOrder : LinearOrder ℕ where decidableLE := inferInstance decidableEq := inferInstance +-- Shortcut instances +instance : Preorder ℕ := inferInstance +instance : PartialOrder ℕ := inferInstance +instance : Min ℕ := inferInstance +instance : Max ℕ := inferInstance +instance : Ord ℕ := inferInstance + instance instNontrivial : Nontrivial ℕ := ⟨⟨0, 1, Nat.zero_ne_one⟩⟩ @[simp] theorem default_eq_zero : default = 0 := rfl @@ -1085,7 +1092,7 @@ lemma sub_mod_eq_zero_of_mod_eq (h : m % k = n % k) : (m - n) % k = 0 := by lemma one_mod_eq_one : ∀ {n : ℕ}, 1 % n = 1 ↔ n ≠ 1 | 0 | 1 | n + 2 => by simp -@[deprecated (since := "2024-08-28")] +@[deprecated "No deprecation message was provided." (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 := @@ -1161,7 +1168,6 @@ lemma mul_add_mod' (a b c : ℕ) : (a * b + c) % b = c % b := by rw [Nat.mul_com lemma mul_add_mod_of_lt (h : c < b) : (a * b + c) % b = c := by rw [Nat.mul_add_mod', Nat.mod_eq_of_lt h] -set_option linter.deprecated false in @[simp] protected theorem not_two_dvd_bit1 (n : ℕ) : ¬2 ∣ 2 * n + 1 := by omega diff --git a/Mathlib/Data/Nat/Factorization/PrimePow.lean b/Mathlib/Data/Nat/Factorization/PrimePow.lean index 3d33d3f1dbd08..be263eea0756e 100644 --- a/Mathlib/Data/Nat/Factorization/PrimePow.lean +++ b/Mathlib/Data/Nat/Factorization/PrimePow.lean @@ -145,3 +145,41 @@ theorem Nat.mul_divisors_filter_prime_pow {a b : ℕ} (hab : a.Coprime b) : simp only [ha, hb, Finset.mem_union, Finset.mem_filter, Nat.mul_eq_zero, and_true, Ne, and_congr_left_iff, not_false_iff, Nat.mem_divisors, or_self_iff] apply hab.isPrimePow_dvd_mul + +lemma IsPrimePow.factorization_minFac_ne_zero {n : ℕ} (hn : IsPrimePow n) : + n.factorization n.minFac ≠ 0 := by + refine mt (Nat.factorization_eq_zero_iff _ _).mp ?_ + push_neg + exact ⟨n.minFac_prime hn.ne_one, n.minFac_dvd, hn.ne_zero⟩ + +/-- The canonical equivalence between pairs `(p, k)` with `p` a prime and `k : ℕ` +and the set of prime powers given by `(p, k) ↦ p^(k+1)`. -/ +def Nat.Primes.prodNatEquiv : Nat.Primes × ℕ ≃ {n : ℕ // IsPrimePow n} where + toFun pk := + ⟨pk.1 ^ (pk.2 + 1), ⟨pk.1, pk.2 + 1, prime_iff.mp pk.1.prop, pk.2.add_one_pos, rfl⟩⟩ + invFun n := + (⟨n.val.minFac, minFac_prime n.prop.ne_one⟩, n.val.factorization n.val.minFac - 1) + left_inv := fun (p, k) ↦ by + simp only [p.prop.pow_minFac k.add_one_ne_zero, Subtype.coe_eta, factorization_pow, p.prop, + Prime.factorization, Finsupp.smul_single, smul_eq_mul, mul_one, Finsupp.single_add, + Finsupp.coe_add, Pi.add_apply, Finsupp.single_eq_same, add_tsub_cancel_right] + right_inv n := by + ext1 + dsimp only + rw [sub_one_add_one n.prop.factorization_minFac_ne_zero, n.prop.minFac_pow_factorization_eq] + +@[simp] +lemma Nat.Primes.prodNatEquiv_apply (p : Nat.Primes) (k : ℕ) : + prodNatEquiv (p, k) = ⟨p ^ (k + 1), p, k + 1, prime_iff.mp p.prop, k.add_one_pos, rfl⟩ := by + rfl + +@[simp] +lemma Nat.Primes.coe_prodNatEquiv_apply (p : Nat.Primes) (k : ℕ) : + (prodNatEquiv (p, k) : ℕ) = p ^ (k + 1) := + rfl + +@[simp] +lemma Nat.Primes.prodNatEquiv_symm_apply {n : ℕ} (hn : IsPrimePow n) : + prodNatEquiv.symm ⟨n, hn⟩ = + (⟨n.minFac, minFac_prime hn.ne_one⟩, n.factorization n.minFac - 1) := + rfl diff --git a/Mathlib/Data/Nat/GCD/Basic.lean b/Mathlib/Data/Nat/GCD/Basic.lean index ff926c64b4005..2adab886eac34 100644 --- a/Mathlib/Data/Nat/GCD/Basic.lean +++ b/Mathlib/Data/Nat/GCD/Basic.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad, Leonardo de Moura -/ import Batteries.Data.Nat.Gcd +import Mathlib.Algebra.Group.Nat.Units import Mathlib.Algebra.GroupWithZero.Divisibility import Mathlib.Algebra.Ring.Nat diff --git a/Mathlib/Data/Nat/Log.lean b/Mathlib/Data/Nat/Log.lean index fc11e395a0c41..1d16748dda19e 100644 --- a/Mathlib/Data/Nat/Log.lean +++ b/Mathlib/Data/Nat/Log.lean @@ -3,11 +3,11 @@ 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.Order.Interval.Set.Defs +import Mathlib.Order.Monotone.Basic import Mathlib.Tactic.Bound.Attribute -import Mathlib.Tactic.Monotonicity.Attr -import Mathlib.Order.Lattice import Mathlib.Tactic.Contrapose -import Mathlib.Order.Interval.Set.Defs +import Mathlib.Tactic.Monotonicity.Attr /-! # Natural number logarithms diff --git a/Mathlib/Data/Nat/Nth.lean b/Mathlib/Data/Nat/Nth.lean index 4cde210602f99..243d52d17d6f6 100644 --- a/Mathlib/Data/Nat/Nth.lean +++ b/Mathlib/Data/Nat/Nth.lean @@ -237,10 +237,21 @@ theorem nth_eq_zero {n} : · rintro (⟨h₀, rfl⟩ | ⟨hf, hle⟩) exacts [nth_zero_of_zero h₀, nth_of_card_le hf hle] +lemma lt_card_toFinset_of_nth_ne_zero {n : ℕ} (h : nth p n ≠ 0) (hf : (setOf p).Finite) : + n < #hf.toFinset := by + simp only [ne_eq, nth_eq_zero, not_or, not_exists, not_le] at h + exact h.2 hf + +lemma nth_mem_of_ne_zero {n : ℕ} (h : nth p n ≠ 0) : p (Nat.nth p n) := + nth_mem n (lt_card_toFinset_of_nth_ne_zero h) + theorem nth_eq_zero_mono (h₀ : ¬p 0) {a b : ℕ} (hab : a ≤ b) (ha : nth p a = 0) : nth p b = 0 := by simp only [nth_eq_zero, h₀, false_and, false_or] at ha ⊢ exact ha.imp fun hf hle => hle.trans hab +lemma nth_ne_zero_anti (h₀ : ¬p 0) {a b : ℕ} (hab : a ≤ b) (hb : nth p b ≠ 0) : nth p a ≠ 0 := + mt (nth_eq_zero_mono h₀ hab) hb + theorem le_nth_of_lt_nth_succ {k a : ℕ} (h : a < nth p (k + 1)) (ha : p a) : a ≤ nth p k := by cases' (setOf p).finite_or_infinite with hf hf · rcases exists_lt_card_finite_nth_eq hf ha with ⟨n, hn, rfl⟩ diff --git a/Mathlib/Data/Nat/PSub.lean b/Mathlib/Data/Nat/PSub.lean index e4d0b1efeaaae..dce691789a710 100644 --- a/Mathlib/Data/Nat/PSub.lean +++ b/Mathlib/Data/Nat/PSub.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ import Mathlib.Algebra.Group.Basic -import Mathlib.Algebra.Group.Nat +import Mathlib.Algebra.Group.Nat.Basic /-! # Partial predecessor and partial subtraction on the natural numbers diff --git a/Mathlib/Data/Nat/Prime/Defs.lean b/Mathlib/Data/Nat/Prime/Defs.lean index e6a3e5bd1a467..d062858f5ac79 100644 --- a/Mathlib/Data/Nat/Prime/Defs.lean +++ b/Mathlib/Data/Nat/Prime/Defs.lean @@ -4,9 +4,11 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Leonardo de Moura, Jeremy Avigad, Mario Carneiro -/ import Batteries.Data.Nat.Gcd +import Mathlib.Algebra.Group.Nat.Units import Mathlib.Algebra.Prime.Defs import Mathlib.Algebra.Ring.Nat -import Mathlib.Order.Lattice +import Mathlib.Data.Nat.Sqrt +import Mathlib.Order.Basic /-! # Prime numbers @@ -32,7 +34,8 @@ namespace Nat variable {n : ℕ} /-- `Nat.Prime p` means that `p` is a prime number, that is, a natural number - at least 2 whose only divisors are `p` and `1`. -/ + at least 2 whose only divisors are `p` and `1`. + The theorem `Nat.prime_def` witnesses this description of a prime number. -/ @[pp_nodot] def Prime (p : ℕ) := Irreducible p @@ -77,7 +80,8 @@ theorem Prime.eq_one_or_self_of_dvd {p : ℕ} (pp : p.Prime) (m : ℕ) (hm : m rintro rfl rw [hn, mul_one] -theorem prime_def_lt'' {p : ℕ} : Prime p ↔ 2 ≤ p ∧ ∀ m, m ∣ p → m = 1 ∨ m = p := by +@[inherit_doc Nat.Prime] +theorem prime_def {p : ℕ} : Prime p ↔ 2 ≤ p ∧ ∀ m, m ∣ p → m = 1 ∨ m = p := by refine ⟨fun h => ⟨h.two_le, h.eq_one_or_self_of_dvd⟩, fun h => ?_⟩ have h1 := Nat.one_lt_two.trans_le h.1 refine ⟨mt Nat.isUnit_iff.mp h1.ne', fun a b hab => ?_⟩ @@ -88,8 +92,11 @@ theorem prime_def_lt'' {p : ℕ} : Prime p ↔ 2 ≤ p ∧ ∀ m, m ∣ p → m · rw [hab] exact dvd_mul_right _ _ +@[deprecated (since := "2024-11-19")] +alias prime_def_lt'' := prime_def + theorem prime_def_lt {p : ℕ} : Prime p ↔ 2 ≤ p ∧ ∀ m < p, m ∣ p → m = 1 := - prime_def_lt''.trans <| + prime_def.trans <| and_congr_right fun p2 => forall_congr' fun _ => ⟨fun h l d => (h d).resolve_right (ne_of_lt l), fun h d => diff --git a/Mathlib/Data/Nat/Size.lean b/Mathlib/Data/Nat/Size.lean index fec3892450d06..63929ccf4f5d8 100644 --- a/Mathlib/Data/Nat/Size.lean +++ b/Mathlib/Data/Nat/Size.lean @@ -3,8 +3,8 @@ Copyright (c) 2014 Floris van Doorn (c) 2016 Microsoft Corporation. All rights r Released under Apache 2.0 license as described in the file LICENSE. Authors: Floris van Doorn, Leonardo de Moura, Jeremy Avigad, Mario Carneiro -/ +import Mathlib.Algebra.Group.Basic import Mathlib.Data.Nat.Bits -import Mathlib.Order.Lattice /-! Lemmas about `size`. -/ diff --git a/Mathlib/Data/Num/Bitwise.lean b/Mathlib/Data/Num/Bitwise.lean index b374f02e13946..57703e62a4600 100644 --- a/Mathlib/Data/Num/Bitwise.lean +++ b/Mathlib/Data/Num/Bitwise.lean @@ -409,7 +409,7 @@ end SNum namespace SNum /-- `a.bits n` is the vector of the `n` first bits of `a` (starting from the LSB). -/ -def bits : SNum → ∀ n, Vector Bool n +def bits : SNum → ∀ n, Mathlib.Vector Bool n | _, 0 => Vector.nil | p, n + 1 => head p ::ᵥ bits (tail p) n diff --git a/Mathlib/Data/Num/Lemmas.lean b/Mathlib/Data/Num/Lemmas.lean index 04f10c375c5b9..c7e98484c0e1c 100644 --- a/Mathlib/Data/Num/Lemmas.lean +++ b/Mathlib/Data/Num/Lemmas.lean @@ -308,7 +308,6 @@ theorem of_to_nat' : ∀ n : Num, Num.ofNat' (n : ℕ) = n | 0 => ofNat'_zero | pos p => p.of_to_nat' -set_option linter.deprecated false in lemma toNat_injective : Injective (castNum : Num → ℕ) := LeftInverse.injective of_to_nat' @[norm_cast] diff --git a/Mathlib/Data/Num/Prime.lean b/Mathlib/Data/Num/Prime.lean index 6b3a141d15139..c183f23216e12 100644 --- a/Mathlib/Data/Num/Prime.lean +++ b/Mathlib/Data/Num/Prime.lean @@ -37,7 +37,6 @@ def minFacAux (n : PosNum) : ℕ → PosNum → PosNum | fuel + 1, k => if n < k.bit1 * k.bit1 then n else if k.bit1 ∣ n then k.bit1 else minFacAux n fuel k.succ -set_option linter.deprecated false in theorem minFacAux_to_nat {fuel : ℕ} {n k : PosNum} (h : Nat.sqrt n < fuel + k.bit1) : (minFacAux n fuel k : ℕ) = Nat.minFacAux n k.bit1 := by induction' fuel with fuel ih generalizing k <;> rw [minFacAux, Nat.minFacAux] diff --git a/Mathlib/Data/Part.lean b/Mathlib/Data/Part.lean index 58395794466e5..842a941412357 100644 --- a/Mathlib/Data/Part.lean +++ b/Mathlib/Data/Part.lean @@ -5,7 +5,7 @@ Authors: Mario Carneiro, Jeremy Avigad, Simon Hudon -/ import Mathlib.Data.Set.Subsingleton import Mathlib.Logic.Equiv.Defs -import Mathlib.Algebra.Group.Defs +import Mathlib.Algebra.Group.Operations /-! # Partial values of a type diff --git a/Mathlib/Data/Prod/Basic.lean b/Mathlib/Data/Prod/Basic.lean index f42386ead9042..98f729aaec3e6 100644 --- a/Mathlib/Data/Prod/Basic.lean +++ b/Mathlib/Data/Prod/Basic.lean @@ -5,12 +5,13 @@ Authors: Johannes Hölzl -/ import Mathlib.Logic.Function.Defs import Mathlib.Logic.Function.Iterate +import Aesop import Mathlib.Tactic.Inhabit /-! # Extra facts about `Prod` -This file defines `Prod.swap : α × β → β × α` and proves various simple lemmas about `Prod`. +This file proves various simple lemmas about `Prod`. It also defines better delaborators for product projections. -/ @@ -20,6 +21,8 @@ variable {α : Type*} {β : Type*} {γ : Type*} {δ : Type*} namespace Prod +lemma swap_eq_iff_eq_swap {x : α × β} {y : β × α} : x.swap = y ↔ x = y.swap := by aesop + def mk.injArrow {x₁ : α} {y₁ : β} {x₂ : α} {y₂ : β} : (x₁, y₁) = (x₂, y₂) → ∀ ⦃P : Sort*⦄, (x₁ = x₂ → y₁ = y₂ → P) → P := fun h₁ _ h₂ ↦ Prod.noConfusion h₁ h₂ diff --git a/Mathlib/Data/Rat/Floor.lean b/Mathlib/Data/Rat/Floor.lean index 66006dd0fc062..7b67abd634887 100644 --- a/Mathlib/Data/Rat/Floor.lean +++ b/Mathlib/Data/Rat/Floor.lean @@ -21,6 +21,7 @@ division and modulo arithmetic are derived as well as some simple inequalities. rat, rationals, ℚ, floor -/ +assert_not_exists Finset open Int diff --git a/Mathlib/Data/Real/Archimedean.lean b/Mathlib/Data/Real/Archimedean.lean index 55226e28d84b8..a42f86a993916 100644 --- a/Mathlib/Data/Real/Archimedean.lean +++ b/Mathlib/Data/Real/Archimedean.lean @@ -14,6 +14,8 @@ import Mathlib.Order.Interval.Set.Disjoint -/ +assert_not_exists Finset + open scoped Classical open Pointwise CauSeq diff --git a/Mathlib/Data/Real/Cardinality.lean b/Mathlib/Data/Real/Cardinality.lean index b0a7e99a26fb2..b41af8e41d56f 100644 --- a/Mathlib/Data/Real/Cardinality.lean +++ b/Mathlib/Data/Real/Cardinality.lean @@ -3,9 +3,9 @@ Copyright (c) 2019 Floris van Doorn. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Floris van Doorn -/ +import Mathlib.Algebra.Order.Group.Pointwise.Interval import Mathlib.Analysis.SpecificLimits.Basic import Mathlib.Data.Rat.Cardinal -import Mathlib.Data.Set.Pointwise.Interval import Mathlib.SetTheory.Cardinal.Continuum /-! diff --git a/Mathlib/Data/Real/ENatENNReal.lean b/Mathlib/Data/Real/ENatENNReal.lean index 9385bd57ec211..f022dc59fe0b4 100644 --- a/Mathlib/Data/Real/ENatENNReal.lean +++ b/Mathlib/Data/Real/ENatENNReal.lean @@ -12,6 +12,7 @@ import Mathlib.Data.ENNReal.Basic In this file we define a coercion from `ℕ∞` to `ℝ≥0∞` and prove some basic lemmas about this map. -/ +assert_not_exists Finset open scoped Classical open NNReal ENNReal diff --git a/Mathlib/Data/Real/Pi/Irrational.lean b/Mathlib/Data/Real/Pi/Irrational.lean index e3884b774698d..afebb88a105b2 100644 --- a/Mathlib/Data/Real/Pi/Irrational.lean +++ b/Mathlib/Data/Real/Pi/Irrational.lean @@ -283,8 +283,8 @@ private lemma not_irrational_exists_rep {x : ℝ} : rwa [lt_div_iff₀ (by positivity), zero_mul] at this have k (n : ℕ) : 0 < (a : ℝ) ^ (2 * n + 1) / n ! := by positivity have j : ∀ᶠ n : ℕ in atTop, (a : ℝ) ^ (2 * n + 1) / n ! * I n (π / 2) < 1 := by - have := eventually_lt_of_tendsto_lt (show (0 : ℝ) < 1 / 2 by norm_num) - (tendsto_pow_div_factorial_at_top_aux a) + have := (tendsto_pow_div_factorial_at_top_aux a).eventually_lt_const + (show (0 : ℝ) < 1 / 2 by norm_num) filter_upwards [this] with n hn rw [lt_div_iff₀ (zero_lt_two : (0 : ℝ) < 2)] at hn exact hn.trans_le' (mul_le_mul_of_nonneg_left (I_le _) (by positivity)) diff --git a/Mathlib/Data/Real/Pointwise.lean b/Mathlib/Data/Real/Pointwise.lean index 8672dab314d36..e071edd0c5ddc 100644 --- a/Mathlib/Data/Real/Pointwise.lean +++ b/Mathlib/Data/Real/Pointwise.lean @@ -22,6 +22,7 @@ This is true more generally for conditionally complete linear order whose defaul don't have those yet. -/ +assert_not_exists Finset open Set diff --git a/Mathlib/Data/Real/Sqrt.lean b/Mathlib/Data/Real/Sqrt.lean index b07597c19deda..5b1193b70b404 100644 --- a/Mathlib/Data/Real/Sqrt.lean +++ b/Mathlib/Data/Real/Sqrt.lean @@ -39,7 +39,7 @@ variable {x y : ℝ≥0} /-- Square root of a nonnegative real number. -/ -- Porting note (kmill): `pp_nodot` has no affect here --- unless RFC https://github.com/leanprover/lean4/issues/1910 leads to dot notation for CoeFun +-- unless RFC https://github.com/leanprover/lean4/issues/6178 leads to dot notation pp for CoeFun @[pp_nodot] noncomputable def sqrt : ℝ≥0 ≃o ℝ≥0 := OrderIso.symm <| powOrderIso 2 two_ne_zero @@ -311,8 +311,6 @@ end Mathlib.Meta.Positivity namespace Real -variable {x y : ℝ} - @[simp] theorem sqrt_mul {x : ℝ} (hx : 0 ≤ x) (y : ℝ) : √(x * y) = √x * √y := by simp_rw [Real.sqrt, ← NNReal.coe_mul, NNReal.coe_inj, Real.toNNReal_mul hx, NNReal.sqrt_mul] diff --git a/Mathlib/Data/Set/Basic.lean b/Mathlib/Data/Set/Basic.lean index d5e0c9c761f33..8d28bac27f0b0 100644 --- a/Mathlib/Data/Set/Basic.lean +++ b/Mathlib/Data/Set/Basic.lean @@ -436,8 +436,9 @@ instance univ.nonempty [Nonempty α] : Nonempty (↥(Set.univ : Set α)) := instance instNonemptyTop [Nonempty α] : Nonempty (⊤ : Set α) := inferInstanceAs (Nonempty (univ : Set α)) -theorem nonempty_of_nonempty_subtype [Nonempty (↥s)] : s.Nonempty := - nonempty_subtype.mp ‹_› +theorem Nonempty.of_subtype [Nonempty (↥s)] : s.Nonempty := nonempty_subtype.mp ‹_› + +@[deprecated (since := "2024-11-23")] alias nonempty_of_nonempty_subtype := Nonempty.of_subtype /-! ### Lemmas about the empty set -/ @@ -1204,7 +1205,7 @@ theorem eq_empty_of_ssubset_singleton {s : Set α} {x : α} (hs : s ⊂ {x}) : s theorem eq_of_nonempty_of_subsingleton {α} [Subsingleton α] (s t : Set α) [Nonempty s] [Nonempty t] : s = t := - nonempty_of_nonempty_subtype.eq_univ.trans nonempty_of_nonempty_subtype.eq_univ.symm + Nonempty.of_subtype.eq_univ.trans Nonempty.of_subtype.eq_univ.symm theorem eq_of_nonempty_of_subsingleton' {α} [Subsingleton α] {s : Set α} (t : Set α) (hs : s.Nonempty) [Nonempty t] : s = t := diff --git a/Mathlib/Data/Set/Enumerate.lean b/Mathlib/Data/Set/Enumerate.lean index 908974989a9e3..c5858d0c5e375 100644 --- a/Mathlib/Data/Set/Enumerate.lean +++ b/Mathlib/Data/Set/Enumerate.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl -/ import Mathlib.Algebra.Group.Basic -import Mathlib.Algebra.Group.Nat +import Mathlib.Algebra.Group.Nat.Basic import Mathlib.Tactic.Common import Mathlib.Data.Set.Basic diff --git a/Mathlib/Data/Set/Function.lean b/Mathlib/Data/Set/Function.lean index 0a7bacfba799b..77dbaaa172001 100644 --- a/Mathlib/Data/Set/Function.lean +++ b/Mathlib/Data/Set/Function.lean @@ -1665,4 +1665,55 @@ lemma bijOn_swap (ha : a ∈ s) (hb : b ∈ s) : BijOn (swap a b) s s := end Equiv +/-! ### Vertical line test -/ + +namespace Set + +/-- **Vertical line test** for functions. + +Let `f : α → β × γ` be a function to a product. Assume that `f` is surjective on the first factor +and that the image of `f` intersects every "vertical line" `{(b, c) | c : γ}` at most once. +Then the image of `f` is the graph of some monoid homomorphism `f' : β → γ`. -/ +lemma exists_range_eq_graphOn_univ {f : α → β × γ} (hf₁ : Surjective (Prod.fst ∘ f)) + (hf : ∀ g₁ g₂, (f g₁).1 = (f g₂).1 → (f g₁).2 = (f g₂).2) : + ∃ f' : β → γ, range f = univ.graphOn f' := by + refine ⟨fun h ↦ (f (hf₁ h).choose).snd, ?_⟩ + ext x + simp only [mem_range, comp_apply, mem_graphOn, mem_univ, true_and] + refine ⟨?_, fun hi ↦ ⟨(hf₁ x.1).choose, Prod.ext (hf₁ x.1).choose_spec hi⟩⟩ + rintro ⟨g, rfl⟩ + exact hf _ _ (hf₁ (f g).1).choose_spec + +/-- **Line test** for equivalences. + +Let `f : α → β × γ` be a homomorphism to a product of monoids. Assume that `f` is surjective on both +factors and that the image of `f` intersects every "vertical line" `{(b, c) | c : γ}` and every +"horizontal line" `{(b, c) | b : β}` at most once. Then the image of `f` is the graph of some +equivalence `f' : β ≃ γ`. -/ +lemma exists_equiv_range_eq_graphOn_univ {f : α → β × γ} (hf₁ : Surjective (Prod.fst ∘ f)) + (hf₂ : Surjective (Prod.snd ∘ f)) (hf : ∀ g₁ g₂, (f g₁).1 = (f g₂).1 ↔ (f g₁).2 = (f g₂).2) : + ∃ e : β ≃ γ, range f = univ.graphOn e := by + obtain ⟨e₁, he₁⟩ := exists_range_eq_graphOn_univ hf₁ fun _ _ ↦ (hf _ _).1 + obtain ⟨e₂, he₂⟩ := exists_range_eq_graphOn_univ (f := Equiv.prodComm _ _ ∘ f) (by simpa) <| + by simp [hf] + have he₁₂ h i : e₁ h = i ↔ e₂ i = h := by + rw [Set.ext_iff] at he₁ he₂ + aesop (add simp [Prod.swap_eq_iff_eq_swap]) + exact ⟨ + { toFun := e₁ + invFun := e₂ + left_inv := fun h ↦ by rw [← he₁₂] + right_inv := fun i ↦ by rw [he₁₂] }, he₁⟩ + +/-- **Vertical line test** for functions. + +Let `s : Set (β × γ)` be a set in a product. Assume that `s` maps bijectively to the first factor. +Then `s` is the graph of some function `f : β → γ`. -/ +lemma exists_eq_mgraphOn_univ {s : Set (β × γ)} + (hs₁ : Bijective (Prod.fst ∘ (Subtype.val : s → β × γ))) : ∃ f : β → γ, s = univ.graphOn f := by + simpa using exists_range_eq_graphOn_univ hs₁.surjective + fun a b h ↦ congr_arg (Prod.snd ∘ (Subtype.val : s → β × γ)) (hs₁.injective h) + +end Set + set_option linter.style.longFile 1800 diff --git a/Mathlib/Data/Set/Image.lean b/Mathlib/Data/Set/Image.lean index 11aa60b7641a2..16c6dcc43e64f 100644 --- a/Mathlib/Data/Set/Image.lean +++ b/Mathlib/Data/Set/Image.lean @@ -408,7 +408,7 @@ theorem Nonempty.preimage {s : Set β} (hs : s.Nonempty) {f : α → β} (hf : S ⟨x, mem_preimage.2 <| hx.symm ▸ hy⟩ instance (f : α → β) (s : Set α) [Nonempty s] : Nonempty (f '' s) := - (Set.Nonempty.image f nonempty_of_nonempty_subtype).to_subtype + (Set.Nonempty.image f .of_subtype).to_subtype /-- image and preimage are a Galois connection -/ @[simp] diff --git a/Mathlib/Data/Set/Pointwise/SMul.lean b/Mathlib/Data/Set/Pointwise/SMul.lean index 1f4a5da3be5cd..e7008d4c67fbf 100644 --- a/Mathlib/Data/Set/Pointwise/SMul.lean +++ b/Mathlib/Data/Set/Pointwise/SMul.lean @@ -415,8 +415,13 @@ lemma disjoint_smul_set_left : Disjoint (a • s) t ↔ Disjoint s (a⁻¹ • t lemma disjoint_smul_set_right : Disjoint s (a • t) ↔ Disjoint (a⁻¹ • s) t := by simpa using disjoint_smul_set (a := a) (s := a⁻¹ • s) -@[to_additive (attr := deprecated (since := "2024-10-18"))] -alias smul_set_disjoint_iff := disjoint_smul_set +@[to_additive] alias smul_set_disjoint_iff := disjoint_smul_set + +-- `alias` doesn't add the deprecation suggestion to the `to_additive` version +-- see https://github.com/leanprover-community/mathlib4/issues/19424 +attribute [deprecated disjoint_smul_set (since := "2024-10-18")] smul_set_disjoint_iff +attribute [deprecated disjoint_vadd_set (since := "2024-10-18")] vadd_set_disjoint_iff + end Group diff --git a/Mathlib/Data/Setoid/Basic.lean b/Mathlib/Data/Setoid/Basic.lean index 2e75e96025a44..bbaa5b239fbfe 100644 --- a/Mathlib/Data/Setoid/Basic.lean +++ b/Mathlib/Data/Setoid/Basic.lean @@ -36,12 +36,12 @@ attribute [trans] Setoid.trans variable {α : Type*} {β : Type*} /-- A version of `Setoid.r` that takes the equivalence relation as an explicit argument. -/ -@[deprecated (since := "2024-08-29")] +@[deprecated "No deprecation message was provided." (since := "2024-08-29")] def Setoid.Rel (r : Setoid α) : α → α → Prop := @Setoid.r _ r set_option linter.deprecated false in -@[deprecated (since := "2024-10-09")] +@[deprecated "No deprecation message was provided." (since := "2024-10-09")] instance Setoid.decidableRel (r : Setoid α) [h : DecidableRel r.r] : DecidableRel r.Rel := h diff --git a/Mathlib/Data/Sym/Basic.lean b/Mathlib/Data/Sym/Basic.lean index ac156160cdcb8..32aca18c1b5c4 100644 --- a/Mathlib/Data/Sym/Basic.lean +++ b/Mathlib/Data/Sym/Basic.lean @@ -55,7 +55,7 @@ instance {α : Type*} {n : ℕ} [DecidableEq α] : DecidableEq (Sym α n) := See note [reducible non-instances]. -/ -abbrev Vector.Perm.isSetoid (α : Type*) (n : ℕ) : Setoid (Vector α n) := +abbrev Mathlib.Vector.Perm.isSetoid (α : Type*) (n : ℕ) : Setoid (Vector α n) := (List.isSetoid α).comap Subtype.val attribute [local instance] Vector.Perm.isSetoid @@ -119,20 +119,21 @@ theorem coe_cons (s : Sym α n) (a : α) : (a ::ₛ s : Multiset α) = a ::ₘ s /-- This is the quotient map that takes a list of n elements as an n-tuple and produces an nth symmetric power. -/ -def ofVector : Vector α n → Sym α n := +def ofVector : Mathlib.Vector α n → Sym α n := fun x => ⟨↑x.val, (Multiset.coe_card _).trans x.2⟩ /-- This is the quotient map that takes a list of n elements as an n-tuple and produces an nth symmetric power. -/ -instance : Coe (Vector α n) (Sym α n) where coe x := ofVector x +instance : Coe (Mathlib.Vector α n) (Sym α n) where coe x := ofVector x @[simp] -theorem ofVector_nil : ↑(Vector.nil : Vector α 0) = (Sym.nil : Sym α 0) := +theorem ofVector_nil : ↑(Vector.nil : Mathlib.Vector α 0) = (Sym.nil : Sym α 0) := rfl @[simp] -theorem ofVector_cons (a : α) (v : Vector α n) : ↑(Vector.cons a v) = a ::ₛ (↑v : Sym α n) := by +theorem ofVector_cons (a : α) (v : Mathlib.Vector α n) : + ↑(Vector.cons a v) = a ::ₛ (↑v : Sym α n) := by cases v rfl @@ -179,13 +180,13 @@ theorem mem_cons_of_mem (h : a ∈ s) : a ∈ b ::ₛ s := theorem mem_cons_self (a : α) (s : Sym α n) : a ∈ a ::ₛ s := Multiset.mem_cons_self a s.1 -theorem cons_of_coe_eq (a : α) (v : Vector α n) : a ::ₛ (↑v : Sym α n) = ↑(a ::ᵥ v) := +theorem cons_of_coe_eq (a : α) (v : Mathlib.Vector α n) : a ::ₛ (↑v : Sym α n) = ↑(a ::ᵥ v) := Subtype.ext <| by cases v rfl open scoped List in -theorem sound {a b : Vector α n} (h : a.val ~ b.val) : (↑a : Sym α n) = ↑b := +theorem sound {a b : Mathlib.Vector α n} (h : a.val ~ b.val) : (↑a : Sym α n) = ↑b := Subtype.ext <| Quotient.sound h /-- `erase s a h` is the sym that subtracts 1 from the diff --git a/Mathlib/Data/Sym/Sym2.lean b/Mathlib/Data/Sym/Sym2.lean index 28fbe8b4427a2..a827017219d56 100644 --- a/Mathlib/Data/Sym/Sym2.lean +++ b/Mathlib/Data/Sym/Sym2.lean @@ -586,7 +586,7 @@ section SymEquiv attribute [local instance] Vector.Perm.isSetoid -private def fromVector : Vector α 2 → α × α +private def fromVector : Mathlib.Vector α 2 → α × α | ⟨[a, b], _⟩ => (a, b) private theorem perm_card_two_iff {a₁ b₁ a₂ b₂ : α} : diff --git a/Mathlib/Data/Vector/Mem.lean b/Mathlib/Data/Vector/Mem.lean index 9cf9359b65623..dc09c5bb58415 100644 --- a/Mathlib/Data/Vector/Mem.lean +++ b/Mathlib/Data/Vector/Mem.lean @@ -22,7 +22,7 @@ namespace Vector variable {α β : Type*} {n : ℕ} (a a' : α) @[simp] -theorem get_mem (i : Fin n) (v : Vector α n) : v.get i ∈ v.toList := List.getElem_mem _ +theorem get_mem (i : Fin n) (v : Vector α n) : v.get i ∈ v.toList := List.get_mem _ _ theorem mem_iff_get (v : Vector α n) : a ∈ v.toList ↔ ∃ i, v.get i = a := by simp only [List.mem_iff_get, Fin.exists_iff, Vector.get_eq_get] diff --git a/Mathlib/Data/ZMod/IntUnitsPower.lean b/Mathlib/Data/ZMod/IntUnitsPower.lean index 3927a7e59bb96..4b5cace9f38cd 100644 --- a/Mathlib/Data/ZMod/IntUnitsPower.lean +++ b/Mathlib/Data/ZMod/IntUnitsPower.lean @@ -24,7 +24,7 @@ by using `Module R (Additive M)` in its place, especially since this already has -/ instance : SMul (ZMod 2) (Additive ℤˣ) where - smul z au := .ofMul <| Additive.toMul au ^ z.val + smul z au := .ofMul <| au.toMul ^ z.val lemma ZMod.smul_units_def (z : ZMod 2) (au : Additive ℤˣ) : z • au = z.val • au := rfl @@ -34,7 +34,7 @@ lemma ZMod.natCast_smul_units (n : ℕ) (au : Additive ℤˣ) : (n : ZMod 2) • /-- This is an indirect way of saying that `ℤˣ` has a power operation by `ZMod 2`. -/ instance : Module (ZMod 2) (Additive ℤˣ) where - smul z au := .ofMul <| Additive.toMul au ^ z.val + smul z au := .ofMul <| au.toMul ^ z.val one_smul _ := Additive.toMul.injective <| pow_one _ mul_smul z₁ z₂ au := Additive.toMul.injective <| by dsimp only [ZMod.smul_units_def, toMul_nsmul] @@ -44,7 +44,7 @@ instance : Module (ZMod 2) (Additive ℤˣ) where add_smul z₁ z₂ au := Additive.toMul.injective <| by dsimp only [ZMod.smul_units_def, toMul_nsmul, toMul_add] rw [← pow_add, ZMod.val_add, ← Int.units_pow_eq_pow_mod_two] - zero_smul au := Additive.toMul.injective <| pow_zero (Additive.toMul au) + zero_smul au := Additive.toMul.injective <| pow_zero au.toMul section CommSemiring variable {R : Type*} [CommSemiring R] [Module R (Additive ℤˣ)] @@ -55,7 +55,7 @@ In lemma names, this operations is called `uzpow` to match `zpow`. Notably this is satisfied by `R ∈ {ℕ, ℤ, ZMod 2}`. -/ instance Int.instUnitsPow : Pow ℤˣ R where - pow u r := Additive.toMul (r • Additive.ofMul u) + pow u r := (r • Additive.ofMul u).toMul -- The above instances form no typeclass diamonds with the standard power operators -- but we will need `reducible_and_instances` which currently fails https://github.com/leanprover-community/mathlib4/issues/10906 @@ -65,10 +65,10 @@ example : Int.instUnitsPow = DivInvMonoid.Pow := rfl @[simp] lemma ofMul_uzpow (u : ℤˣ) (r : R) : Additive.ofMul (u ^ r) = r • Additive.ofMul u := rfl @[simp] lemma toMul_uzpow (u : Additive ℤˣ) (r : R) : - Additive.toMul (r • u) = Additive.toMul u ^ r := rfl + (r • u).toMul = u.toMul ^ r := rfl @[norm_cast] lemma uzpow_natCast (u : ℤˣ) (n : ℕ) : u ^ (n : R) = u ^ n := by - change Additive.toMul ((n : R) • Additive.ofMul u) = _ + change ((n : R) • Additive.ofMul u).toMul = _ rw [Nat.cast_smul_eq_nsmul, toMul_nsmul, toMul_ofMul] -- See note [no_index around OfNat.ofNat] @@ -106,7 +106,7 @@ lemma uzpow_neg (s : ℤˣ) (x : R) : s ^ (-x) = (s ^ x)⁻¹ := Additive.ofMul.injective <| neg_smul x (Additive.ofMul s) @[norm_cast] lemma uzpow_intCast (u : ℤˣ) (z : ℤ) : u ^ (z : R) = u ^ z := by - change Additive.toMul ((z : R) • Additive.ofMul u) = _ + change ((z : R) • Additive.ofMul u).toMul = _ rw [Int.cast_smul_eq_zsmul, toMul_zsmul, toMul_ofMul] end CommRing diff --git a/Mathlib/Deprecated/AlgebraClasses.lean b/Mathlib/Deprecated/AlgebraClasses.lean index cc26f497422b2..bb6f948871913 100644 --- a/Mathlib/Deprecated/AlgebraClasses.lean +++ b/Mathlib/Deprecated/AlgebraClasses.lean @@ -25,16 +25,16 @@ universe u v variable {α : Sort u} -@[deprecated (since := "2024-09-11")] +@[deprecated "No deprecation message was provided." (since := "2024-09-11")] class IsLeftCancel (α : Sort u) (op : α → α → α) : Prop where left_cancel : ∀ a b c, op a b = op a c → b = c -@[deprecated (since := "2024-09-11")] +@[deprecated "No deprecation message was provided." (since := "2024-09-11")] class IsRightCancel (α : Sort u) (op : α → α → α) : Prop where right_cancel : ∀ a b c, op a b = op c b → a = c /-- `IsTotalPreorder X r` means that the binary relation `r` on `X` is total and a preorder. -/ -@[deprecated (since := "2024-07-30")] +@[deprecated "No deprecation message was provided." (since := "2024-07-30")] class IsTotalPreorder (α : Sort u) (r : α → α → Prop) extends IsTrans α r, IsTotal α r : Prop /-- Every total pre-order is a pre-order. -/ @@ -45,11 +45,11 @@ instance (priority := 100) isTotalPreorder_isPreorder (α : Sort u) (r : α → /-- `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")] +@[deprecated "No deprecation message was provided." (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 -@[deprecated (since := "2024-07-30")] +@[deprecated "No deprecation message was provided." (since := "2024-07-30")] instance (priority := 100) (α : Sort u) (lt : α → α → Prop) [IsStrictWeakOrder α lt] : IsIncompTrans α lt := { ‹IsStrictWeakOrder α lt› with } @@ -59,7 +59,7 @@ variable {r : α → α → Prop} local infixl:50 " ≺ " => r -@[deprecated (since := "2024-07-30")] +@[deprecated "No deprecation message was provided." (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 _ _ _ @@ -68,7 +68,8 @@ section ExplicitRelationVariants variable (r) -@[elab_without_expected_type, deprecated (since := "2024-07-30")] +@[elab_without_expected_type, + deprecated "No deprecation message was provided." (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 @@ -85,32 +86,32 @@ variable {r : α → α → Prop} local infixl:50 " ≺ " => r -@[deprecated (since := "2024-07-30")] +@[deprecated "No deprecation message was provided." (since := "2024-07-30")] def Equiv (a b : α) : Prop := ¬a ≺ b ∧ ¬b ≺ a local infixl:50 " ≈ " => @Equiv _ r -@[deprecated (since := "2024-07-30")] +@[deprecated "No deprecation message was provided." (since := "2024-07-30")] theorem esymm {a b : α} : a ≈ b → b ≈ a := fun ⟨h₁, h₂⟩ => ⟨h₂, h₁⟩ -@[deprecated (since := "2024-07-30")] +@[deprecated "No deprecation message was provided." (since := "2024-07-30")] theorem not_lt_of_equiv {a b : α} : a ≈ b → ¬a ≺ b := fun h => h.1 -@[deprecated (since := "2024-07-30")] +@[deprecated "No deprecation message was provided." (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")] +@[deprecated "No deprecation message was provided." (since := "2024-07-30")] theorem erefl (a : α) : a ≈ a := ⟨irrefl a, irrefl a⟩ -@[deprecated (since := "2024-07-30")] +@[deprecated "No deprecation message was provided." (since := "2024-07-30")] theorem etrans {a b c : α} : a ≈ b → b ≈ c → a ≈ c := incomp_trans -@[deprecated (since := "2024-07-30")] +@[deprecated "No deprecation message was provided." (since := "2024-07-30")] instance isEquiv : IsEquiv α (@Equiv _ r) where refl := erefl trans _ _ _ := etrans @@ -123,7 +124,7 @@ notation:50 a " ≈[" lt "]" b:50 => @Equiv _ lt a b end StrictWeakOrder -@[deprecated (since := "2024-07-30")] +@[deprecated "No deprecation message was provided." (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 := @@ -149,20 +150,20 @@ section LinearOrder variable {α : Type*} [LinearOrder α] set_option linter.deprecated false in -@[deprecated (since := "2024-07-30")] +@[deprecated "No deprecation message was provided." (since := "2024-07-30")] instance : IsTotalPreorder α (· ≤ ·) where trans := @le_trans _ _ total := le_total set_option linter.deprecated false in -@[deprecated (since := "2024-07-30")] +@[deprecated "No deprecation message was provided." (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")] +@[deprecated "No deprecation message was provided." (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⟩ => @@ -171,7 +172,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")] +@[deprecated "No deprecation message was provided." (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 => @@ -180,7 +181,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")] +@[deprecated "No deprecation message was provided." (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 @@ -188,17 +189,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")] +@[deprecated "No deprecation message was provided." (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")] +@[deprecated "No deprecation message was provided." (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")] +@[deprecated "No deprecation message was provided." (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 diff --git a/Mathlib/Deprecated/ByteArray.lean b/Mathlib/Deprecated/ByteArray.lean index c199be41b3f7c..b7146dbf289c6 100644 --- a/Mathlib/Deprecated/ByteArray.lean +++ b/Mathlib/Deprecated/ByteArray.lean @@ -19,7 +19,7 @@ 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")] +@[deprecated "No deprecation message was provided." (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⟩ @@ -28,13 +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")] +@[deprecated "No deprecation message was provided." (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")] +@[deprecated "No deprecation message was provided." (since := "2024-08-19")] structure ByteSliceT := (arr : ByteArray) (off : Nat) namespace ByteSliceT @@ -66,7 +66,7 @@ def toArray : ByteSlice → ByteArray universe u v /-- The inner loop of the `forIn` implementation for byte slices. -/ -@[deprecated (since := "2024-08-19")] +@[deprecated "No deprecation message was provided." (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 @@ -75,7 +75,7 @@ def forIn.loop {m : Type u → Type v} {β : Type u} [Monad m] (f : UInt8 → β | ForInStep.yield b => have := Nat.Up.next h; loop f arr off _end (i+1) b else pure b -@[deprecated (since := "2024-08-19")] +@[deprecated "No deprecation message was provided." (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⟩ diff --git a/Mathlib/Deprecated/Combinator.lean b/Mathlib/Deprecated/Combinator.lean index 5c79bf0837a59..366fd5997f982 100644 --- a/Mathlib/Deprecated/Combinator.lean +++ b/Mathlib/Deprecated/Combinator.lean @@ -15,8 +15,11 @@ namespace Combinator universe u v w variable {α : Sort u} {β : Sort v} {γ : Sort w} -@[deprecated (since := "2024-07-27")] def I (a : α) := a -@[deprecated (since := "2024-07-27")] def K (a : α) (_b : β) := a -@[deprecated (since := "2024-07-27")] def S (x : α → β → γ) (y : α → β) (z : α) := x z (y z) +@[deprecated "No deprecation message was provided." (since := "2024-07-27")] +def I (a : α) := a +@[deprecated "No deprecation message was provided." (since := "2024-07-27")] +def K (a : α) (_b : β) := a +@[deprecated "No deprecation message was provided." (since := "2024-07-27")] +def S (x : α → β → γ) (y : α → β) (z : α) := x z (y z) end Combinator diff --git a/Mathlib/Deprecated/Equiv.lean b/Mathlib/Deprecated/Equiv.lean index 74bc9b68ecdd3..b31fe578386cc 100644 --- a/Mathlib/Deprecated/Equiv.lean +++ b/Mathlib/Deprecated/Equiv.lean @@ -21,10 +21,10 @@ variable {α₁ β₁ : Type*} (e : α₁ ≃ β₁) (f : α₁ → α₁ → α set_option linter.deprecated false -@[deprecated (since := "2024-09-11")] +@[deprecated "No deprecation message was provided." (since := "2024-09-11")] instance [IsLeftCancel α₁ f] : IsLeftCancel β₁ (e.arrowCongr (e.arrowCongr e) f) := ⟨e.surjective.forall₃.2 fun x y z => by simpa using @IsLeftCancel.left_cancel _ f _ x y z⟩ -@[deprecated (since := "2024-09-11")] +@[deprecated "No deprecation message was provided." (since := "2024-09-11")] instance [IsRightCancel α₁ f] : IsRightCancel β₁ (e.arrowCongr (e.arrowCongr e) f) := ⟨e.surjective.forall₃.2 fun x y z => by simpa using @IsRightCancel.right_cancel _ f _ x y z⟩ diff --git a/Mathlib/Deprecated/Group.lean b/Mathlib/Deprecated/Group.lean index 539782f49e725..66bc94fe1317e 100644 --- a/Mathlib/Deprecated/Group.lean +++ b/Mathlib/Deprecated/Group.lean @@ -4,9 +4,9 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov -/ import Mathlib.Algebra.Group.Equiv.Basic -import Mathlib.Algebra.Group.TypeTags import Mathlib.Algebra.Group.Units.Hom import Mathlib.Algebra.Ring.Hom.Defs +import Mathlib.Algebra.Group.TypeTags.Basic /-! # Unbundled monoid and group homomorphisms diff --git a/Mathlib/Data/LazyList/Basic.lean b/Mathlib/Deprecated/LazyList.lean similarity index 91% rename from Mathlib/Data/LazyList/Basic.lean rename to Mathlib/Deprecated/LazyList.lean index 7a9b820336505..5ba81d38999a8 100644 --- a/Mathlib/Data/LazyList/Basic.lean +++ b/Mathlib/Deprecated/LazyList.lean @@ -24,7 +24,7 @@ namespace LazyList open Function /-- Isomorphism between strict and lazy lists. -/ -@[deprecated (since := "2024-07-22")] +@[deprecated "No deprecation message was provided." (since := "2024-07-22")] def listEquivLazyList (α : Type*) : List α ≃ LazyList α where toFun := LazyList.ofList invFun := LazyList.toList @@ -39,12 +39,12 @@ def listEquivLazyList (α : Type*) : List α ≃ LazyList α where · simp [toList, ofList] · simpa [ofList, toList] -@[deprecated (since := "2024-07-22")] +@[deprecated "No deprecation message was provided." (since := "2024-07-22")] instance : Traversable LazyList where map := @LazyList.traverse Id _ traverse := @LazyList.traverse -@[deprecated (since := "2024-07-22")] +@[deprecated "No deprecation message was provided." (since := "2024-07-22")] instance : LawfulTraversable LazyList := by apply Equiv.isLawfulTraversable' listEquivLazyList <;> intros <;> ext <;> rename_i f xs · induction xs using LazyList.rec with @@ -71,7 +71,7 @@ instance : LawfulTraversable LazyList := by Function.comp_def, Thunk.pure, ofList] | mk _ ih => apply ih -@[deprecated (since := "2024-07-22"), simp] +@[deprecated "No deprecation message was provided." (since := "2024-07-22"), simp] theorem bind_singleton {α} (x : LazyList α) : x.bind singleton = x := by induction x using LazyList.rec (motive_2 := fun xs => xs.get.bind singleton = xs.get) with | nil => simp [LazyList.bind] @@ -81,7 +81,7 @@ theorem bind_singleton {α} (x : LazyList α) : x.bind singleton = x := by simp [ih] | mk f ih => simp_all -@[deprecated (since := "2024-07-22")] +@[deprecated "No deprecation message was provided." (since := "2024-07-22")] instance : LawfulMonad LazyList := LawfulMonad.mk' (id_map := by intro α xs diff --git a/Mathlib/Deprecated/Logic.lean b/Mathlib/Deprecated/Logic.lean index f88642ec745a7..52d03620dc96a 100644 --- a/Mathlib/Deprecated/Logic.lean +++ b/Mathlib/Deprecated/Logic.lean @@ -37,43 +37,43 @@ local infix:65 (priority := high) " + " => g def Commutative := ∀ a b, a * b = b * a @[deprecated Std.Associative (since := "2024-09-13")] def Associative := ∀ a b c, (a * b) * c = a * (b * c) -@[deprecated (since := "2024-09-03")] -- unused in Mathlib +@[deprecated "No deprecation message was provided." (since := "2024-09-03")] -- unused in Mathlib def LeftIdentity := ∀ a, one * a = a -@[deprecated (since := "2024-09-03")] -- unused in Mathlib +@[deprecated "No deprecation message was provided." (since := "2024-09-03")] -- unused in Mathlib def RightIdentity := ∀ a, a * one = a -@[deprecated (since := "2024-09-03")] -- unused in Mathlib +@[deprecated "No deprecation message was provided." (since := "2024-09-03")] -- unused in Mathlib def RightInverse := ∀ a, a * a⁻¹ = one -@[deprecated (since := "2024-09-03")] -- unused in Mathlib +@[deprecated "No deprecation message was provided." (since := "2024-09-03")] -- unused in Mathlib def LeftCancelative := ∀ a b c, a * b = a * c → b = c -@[deprecated (since := "2024-09-03")] -- unused in Mathlib +@[deprecated "No deprecation message was provided." (since := "2024-09-03")] -- unused in Mathlib def RightCancelative := ∀ a b c, a * b = c * b → a = c -@[deprecated (since := "2024-09-03")] -- unused in Mathlib +@[deprecated "No deprecation message was provided." (since := "2024-09-03")] -- unused in Mathlib def LeftDistributive := ∀ a b c, a * (b + c) = a * b + a * c -@[deprecated (since := "2024-09-03")] -- unused in Mathlib +@[deprecated "No deprecation message was provided." (since := "2024-09-03")] -- unused in Mathlib def RightDistributive := ∀ a b c, (a + b) * c = a * c + b * c end Binary @[deprecated (since := "2024-09-03")] alias not_of_eq_false := of_eq_false -@[deprecated (since := "2024-09-03")] -- unused in Mathlib +@[deprecated "No deprecation message was provided." (since := "2024-09-03")] -- unused in Mathlib theorem cast_proof_irrel {β : Sort u} (h₁ h₂ : α = β) (a : α) : cast h₁ a = cast h₂ a := rfl @[deprecated (since := "2024-09-03")] alias eq_rec_heq := eqRec_heq @[deprecated (since := "2024-09-03")] alias heq_prop := proof_irrel_heq -@[deprecated (since := "2024-09-03")] -- unused in Mathlib +@[deprecated "No deprecation message was provided." (since := "2024-09-03")] -- unused in Mathlib theorem heq_of_eq_rec_left {φ : α → Sort v} {a a' : α} {p₁ : φ a} {p₂ : φ a'} : (e : a = a') → (h₂ : Eq.rec (motive := fun a _ ↦ φ a) p₁ e = p₂) → HEq p₁ p₂ | rfl, rfl => HEq.rfl -@[deprecated (since := "2024-09-03")] -- unused in Mathlib +@[deprecated "No deprecation message was provided." (since := "2024-09-03")] -- unused in Mathlib theorem heq_of_eq_rec_right {φ : α → Sort v} {a a' : α} {p₁ : φ a} {p₂ : φ a'} : (e : a' = a) → (h₂ : p₁ = Eq.rec (motive := fun a _ ↦ φ a) p₂ e) → HEq p₁ p₂ | rfl, rfl => HEq.rfl -@[deprecated (since := "2024-09-03")] -- unused in Mathlib +@[deprecated "No deprecation message was provided." (since := "2024-09-03")] -- unused in Mathlib theorem of_heq_true {a : Prop} (h : HEq a True) : a := of_eq_true (eq_of_heq h) -@[deprecated (since := "2024-09-03")] +@[deprecated "No deprecation message was provided." (since := "2024-09-03")] theorem eq_rec_compose {α β φ : Sort u} : ∀ (p₁ : β = φ) (p₂ : α = β) (a : α), (Eq.recOn p₁ (Eq.recOn p₂ a : β) : φ) = Eq.recOn (Eq.trans p₂ p₁) a @@ -114,20 +114,20 @@ theorem iff_self_iff (a : Prop) : (a ↔ a) ↔ True := iff_of_eq (iff_self _) /- decidable -/ -@[deprecated (since := "2024-09-03")] -- unused in Mathlib +@[deprecated "No deprecation message was provided." (since := "2024-09-03")] -- unused in Mathlib theorem decide_True' (h : Decidable True) : decide True = true := by simp -@[deprecated (since := "2024-09-03")] -- unused in Mathlib +@[deprecated "No deprecation message was provided." (since := "2024-09-03")] -- unused in Mathlib theorem decide_False' (h : Decidable False) : decide False = false := by simp namespace Decidable -@[deprecated (since := "2024-09-03")] -- unused in Mathlib +@[deprecated "No deprecation message was provided." (since := "2024-09-03")] -- unused in Mathlib def recOn_true [h : Decidable p] {h₁ : p → Sort u} {h₂ : ¬p → Sort u} (h₃ : p) (h₄ : h₁ h₃) : Decidable.recOn h h₂ h₁ := cast (by match h with | .isTrue _ => rfl) h₄ -@[deprecated (since := "2024-09-03")] -- unused in Mathlib +@[deprecated "No deprecation message was provided." (since := "2024-09-03")] -- unused in Mathlib def recOn_false [h : Decidable p] {h₁ : p → Sort u} {h₂ : ¬p → Sort u} (h₃ : ¬p) (h₄ : h₂ h₃) : Decidable.recOn h h₂ h₁ := cast (by match h with | .isFalse _ => rfl) h₄ @@ -145,25 +145,25 @@ end Decidable @[deprecated (since := "2024-09-03")] alias decidableTrue := instDecidableTrue @[deprecated (since := "2024-09-03")] alias decidableFalse := instDecidableFalse -@[deprecated (since := "2024-09-03")] -- unused in Mathlib +@[deprecated "No deprecation message was provided." (since := "2024-09-03")] -- unused in Mathlib def IsDecEq {α : Sort u} (p : α → α → Bool) : Prop := ∀ ⦃x y : α⦄, p x y = true → x = y -@[deprecated (since := "2024-09-03")] -- unused in Mathlib +@[deprecated "No deprecation message was provided." (since := "2024-09-03")] -- unused in Mathlib def IsDecRefl {α : Sort u} (p : α → α → Bool) : Prop := ∀ x, p x x = true -@[deprecated (since := "2024-09-03")] -- unused in Mathlib +@[deprecated "No deprecation message was provided." (since := "2024-09-03")] -- unused in Mathlib def decidableEq_of_bool_pred {α : Sort u} {p : α → α → Bool} (h₁ : IsDecEq p) (h₂ : IsDecRefl p) : DecidableEq α | x, y => if hp : p x y = true then isTrue (h₁ hp) else isFalse (fun hxy : x = y ↦ absurd (h₂ y) (by rwa [hxy] at hp)) -@[deprecated (since := "2024-09-03")] -- unused in Mathlib +@[deprecated "No deprecation message was provided." (since := "2024-09-03")] -- unused in Mathlib theorem decidableEq_inl_refl {α : Sort u} [h : DecidableEq α] (a : α) : h a a = isTrue (Eq.refl a) := match h a a with | isTrue _ => rfl -@[deprecated (since := "2024-09-03")] -- unused in Mathlib +@[deprecated "No deprecation message was provided." (since := "2024-09-03")] -- unused in Mathlib theorem decidableEq_inr_neg {α : Sort u} [h : DecidableEq α] {a b : α} (n : a ≠ b) : h a b = isFalse n := match h a b with @@ -171,7 +171,7 @@ theorem decidableEq_inr_neg {α : Sort u} [h : DecidableEq α] {a b : α} /- subsingleton -/ -@[deprecated (since := "2024-09-03")] -- unused in Mathlib +@[deprecated "No deprecation message was provided." (since := "2024-09-03")] -- unused in Mathlib theorem rec_subsingleton {p : Prop} [h : Decidable p] {h₁ : p → Sort u} {h₂ : ¬p → Sort u} [h₃ : ∀ h : p, Subsingleton (h₁ h)] [h₄ : ∀ h : ¬p, Subsingleton (h₂ h)] : Subsingleton (Decidable.recOn h h₂ h₁) := @@ -179,15 +179,15 @@ theorem rec_subsingleton {p : Prop} [h : Decidable p] {h₁ : p → Sort u} {h | isTrue h => h₃ h | isFalse h => h₄ h -@[deprecated (since := "2024-09-03")] -- unused in Mathlib +@[deprecated "No deprecation message was provided." (since := "2024-09-03")] -- unused in Mathlib theorem imp_of_if_pos {c t e : Prop} [Decidable c] (h : ite c t e) (hc : c) : t := (if_pos hc ▸ h :) -@[deprecated (since := "2024-09-03")] -- unused in Mathlib +@[deprecated "No deprecation message was provided." (since := "2024-09-03")] -- unused in Mathlib theorem imp_of_if_neg {c t e : Prop} [Decidable c] (h : ite c t e) (hnc : ¬c) : e := (if_neg hnc ▸ h :) -@[deprecated (since := "2024-09-11")] +@[deprecated "No deprecation message was provided." (since := "2024-09-11")] theorem dif_ctx_congr {α : Sort u} {b c : Prop} [dec_b : Decidable b] [dec_c : Decidable c] {x : b → α} {u : c → α} {y : ¬b → α} {v : ¬c → α} (h_c : b ↔ c) (h_t : ∀ h : c, x (Iff.mpr h_c h) = u h) @@ -199,7 +199,7 @@ theorem dif_ctx_congr {α : Sort u} {b c : Prop} [dec_b : Decidable b] [dec_c : | isFalse h₁, isTrue h₂ => absurd h₂ (Iff.mp (not_congr h_c) h₁) | isTrue h₁, isFalse h₂ => absurd h₁ (Iff.mpr (not_congr h_c) h₂) -@[deprecated (since := "2024-09-03")] -- unused in Mathlib +@[deprecated "No deprecation message was provided." (since := "2024-09-03")] -- unused in Mathlib theorem if_ctx_congr_prop {b c x y u v : Prop} [dec_b : Decidable b] [dec_c : Decidable c] (h_c : b ↔ c) (h_t : c → (x ↔ u)) (h_e : ¬c → (y ↔ v)) : ite b x y ↔ ite c u v := match dec_b, dec_c with @@ -209,12 +209,12 @@ theorem if_ctx_congr_prop {b c x y u v : Prop} [dec_b : Decidable b] [dec_c : De | isTrue h₁, isFalse h₂ => absurd h₁ (Iff.mpr (not_congr h_c) h₂) -- @[congr] -@[deprecated (since := "2024-09-03")] -- unused in Mathlib +@[deprecated "No deprecation message was provided." (since := "2024-09-03")] -- unused in Mathlib theorem if_congr_prop {b c x y u v : Prop} [Decidable b] [Decidable c] (h_c : b ↔ c) (h_t : x ↔ u) (h_e : y ↔ v) : ite b x y ↔ ite c u v := if_ctx_congr_prop h_c (fun _ ↦ h_t) (fun _ ↦ h_e) -@[deprecated (since := "2024-09-03")] -- unused in Mathlib +@[deprecated "No deprecation message was provided." (since := "2024-09-03")] -- unused in Mathlib theorem if_ctx_simp_congr_prop {b c x y u v : Prop} [Decidable b] (h_c : b ↔ c) (h_t : c → (x ↔ u)) -- FIXME: after https://github.com/leanprover/lean4/issues/1867 is fixed, -- this should be changed back to: @@ -222,7 +222,7 @@ theorem if_ctx_simp_congr_prop {b c x y u v : Prop} [Decidable b] (h_c : b ↔ c (h_e : ¬c → (y ↔ v)) : ite b x y ↔ @ite _ c (decidable_of_decidable_of_iff h_c) u v := if_ctx_congr_prop (dec_c := decidable_of_decidable_of_iff h_c) h_c h_t h_e -@[deprecated (since := "2024-09-03")] -- unused in Mathlib +@[deprecated "No deprecation message was provided." (since := "2024-09-03")] -- unused in Mathlib theorem if_simp_congr_prop {b c x y u v : Prop} [Decidable b] (h_c : b ↔ c) (h_t : x ↔ u) -- FIXME: after https://github.com/leanprover/lean4/issues/1867 is fixed, -- this should be changed back to: @@ -230,7 +230,7 @@ theorem if_simp_congr_prop {b c x y u v : Prop} [Decidable b] (h_c : b ↔ c) (h (h_e : y ↔ v) : ite b x y ↔ (@ite _ c (decidable_of_decidable_of_iff h_c) u v) := if_ctx_simp_congr_prop h_c (fun _ ↦ h_t) (fun _ ↦ h_e) -@[deprecated (since := "2024-09-03")] -- unused in Mathlib +@[deprecated "No deprecation message was provided." (since := "2024-09-03")] -- unused in Mathlib theorem dif_ctx_simp_congr {α : Sort u} {b c : Prop} [Decidable b] {x : b → α} {u : c → α} {y : ¬b → α} {v : ¬c → α} (h_c : b ↔ c) (h_t : ∀ h : c, x (Iff.mpr h_c h) = u h) @@ -241,31 +241,31 @@ theorem dif_ctx_simp_congr {α : Sort u} {b c : Prop} [Decidable b] dite b x y = @dite _ c (decidable_of_decidable_of_iff h_c) u v := dif_ctx_congr (dec_c := decidable_of_decidable_of_iff h_c) h_c h_t h_e -@[deprecated (since := "2024-09-03")] +@[deprecated "No deprecation message was provided." (since := "2024-09-03")] def AsTrue (c : Prop) [Decidable c] : Prop := if c then True else False -@[deprecated (since := "2024-09-03")] -- unused in Mathlib +@[deprecated "No deprecation message was provided." (since := "2024-09-03")] -- unused in Mathlib def AsFalse (c : Prop) [Decidable c] : Prop := if c then False else True -@[deprecated (since := "2024-09-03")] +@[deprecated "No deprecation message was provided." (since := "2024-09-03")] theorem AsTrue.get {c : Prop} [h₁ : Decidable c] (_ : AsTrue c) : c := match h₁ with | isTrue h_c => h_c /- Equalities for rewriting let-expressions -/ -@[deprecated (since := "2024-09-03")] -- unused in Mathlib +@[deprecated "No deprecation message was provided." (since := "2024-09-03")] -- unused in Mathlib theorem let_value_eq {α : Sort u} {β : Sort v} {a₁ a₂ : α} (b : α → β) (h : a₁ = a₂) : (let x : α := a₁; b x) = (let x : α := a₂; b x) := congrArg b h -@[deprecated (since := "2024-09-03")] -- unused in Mathlib +@[deprecated "No deprecation message was provided." (since := "2024-09-03")] -- unused in Mathlib theorem let_value_heq {α : Sort v} {β : α → Sort u} {a₁ a₂ : α} (b : ∀ x : α, β x) (h : a₁ = a₂) : HEq (let x : α := a₁; b x) (let x : α := a₂; b x) := by cases h; rfl -@[deprecated (since := "2024-09-03")] -- unused in Mathlib +@[deprecated "No deprecation message was provided." (since := "2024-09-03")] -- unused in Mathlib theorem let_body_eq {α : Sort v} {β : α → Sort u} (a : α) {b₁ b₂ : ∀ x : α, β x} (h : ∀ x, b₁ x = b₂ x) : (let x : α := a; b₁ x) = (let x : α := a; b₂ x) := by exact h _ ▸ rfl -@[deprecated (since := "2024-09-03")] -- unused in Mathlib +@[deprecated "No deprecation message was provided." (since := "2024-09-03")] -- unused in Mathlib theorem let_eq {α : Sort v} {β : Sort u} {a₁ a₂ : α} {b₁ b₂ : α → β} (h₁ : a₁ = a₂) (h₂ : ∀ x, b₁ x = b₂ x) : (let x : α := a₁; b₁ x) = (let x : α := a₂; b₂ x) := by simp [h₁, h₂] diff --git a/Mathlib/Deprecated/NatLemmas.lean b/Mathlib/Deprecated/NatLemmas.lean index 37fd557b3fec3..81b124b4476cd 100644 --- a/Mathlib/Deprecated/NatLemmas.lean +++ b/Mathlib/Deprecated/NatLemmas.lean @@ -28,7 +28,7 @@ namespace Nat /-! successor and predecessor -/ -@[deprecated (since := "2024-08-23")] +@[deprecated "No deprecation message was provided." (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 @@ -36,7 +36,7 @@ def discriminate {B : Sort u} {n : ℕ} (H1 : n = 0 → B) (H2 : ∀ m, n = succ -- Unused in Mathlib; -- if downstream projects find this essential please copy it or remove the deprecation. -@[deprecated (since := "2024-07-27")] +@[deprecated "No deprecation message was provided." (since := "2024-07-27")] theorem one_eq_succ_zero : 1 = succ 0 := rfl @@ -44,7 +44,7 @@ theorem one_eq_succ_zero : 1 = succ 0 := -- Unused in Mathlib; -- if downstream projects find this essential please copy it or remove the deprecation. -@[deprecated (since := "2024-07-27")] +@[deprecated "No deprecation message was provided." (since := "2024-07-27")] def subInduction {P : ℕ → ℕ → Sort u} (H1 : ∀ m, P 0 m) (H2 : ∀ n, P (succ n) 0) (H3 : ∀ n m, P n m → P (succ n) (succ m)) : ∀ n m : ℕ, P n m | 0, _m => H1 _ @@ -55,7 +55,7 @@ def subInduction {P : ℕ → ℕ → Sort u} (H1 : ∀ m, P 0 m) (H2 : ∀ n, P -- Unused in Mathlib; -- if downstream projects find this essential please copy it or remove the deprecation. -@[deprecated (since := "2024-07-27")] +@[deprecated "No deprecation message was provided." (since := "2024-07-27")] theorem cond_decide_mod_two (x : ℕ) [d : Decidable (x % 2 = 1)] : cond (@decide (x % 2 = 1) d) 1 0 = x % 2 := by simp only [cond_eq_if, decide_eq_true_eq] diff --git a/Mathlib/Deprecated/RelClasses.lean b/Mathlib/Deprecated/RelClasses.lean index 357b10283c2d5..8d5f647030d5d 100644 --- a/Mathlib/Deprecated/RelClasses.lean +++ b/Mathlib/Deprecated/RelClasses.lean @@ -27,12 +27,14 @@ variable {α : Type u} open Function -@[deprecated (since := "2024-07-30")] +@[deprecated "No deprecation message was provided." (since := "2024-07-30")] theorem IsTotalPreorder.swap (r) [IsTotalPreorder α r] : IsTotalPreorder α (swap r) := { @IsPreorder.swap α r _, @IsTotal.swap α r _ with } -@[deprecated (since := "2024-08-22")] instance [LinearOrder α] : IsTotalPreorder α (· ≤ ·) where -@[deprecated (since := "2024-08-22")] instance [LinearOrder α] : IsTotalPreorder α (· ≥ ·) where +@[deprecated "No deprecation message was provided." (since := "2024-08-22")] +instance [LinearOrder α] : IsTotalPreorder α (· ≤ ·) where +@[deprecated "No deprecation message was provided." (since := "2024-08-22")] +instance [LinearOrder α] : IsTotalPreorder α (· ≥ ·) where -@[deprecated (since := "2024-07-30")] +@[deprecated "No deprecation message was provided." (since := "2024-07-30")] instance [LinearOrder α] : IsIncompTrans α (· < ·) := by infer_instance diff --git a/Mathlib/Dynamics/Circle/RotationNumber/TranslationNumber.lean b/Mathlib/Dynamics/Circle/RotationNumber/TranslationNumber.lean index 0b03b2f6c460d..e403b3b59936a 100644 --- a/Mathlib/Dynamics/Circle/RotationNumber/TranslationNumber.lean +++ b/Mathlib/Dynamics/Circle/RotationNumber/TranslationNumber.lean @@ -253,7 +253,7 @@ theorem commute_iff_commute {f g : CircleDeg1Lift} : Commute f g ↔ Function.Co `translation (Multiplicative.ofAdd x)`. -/ def translate : Multiplicative ℝ →* CircleDeg1Liftˣ := MonoidHom.toHomUnits <| { toFun := fun x => - ⟨⟨fun y => Multiplicative.toAdd x + y, fun _ _ h => add_le_add_left h _⟩, fun _ => + ⟨⟨fun y => x.toAdd + y, fun _ _ h => add_le_add_left h _⟩, fun _ => (add_assoc _ _ _).symm⟩ map_one' := ext <| zero_add map_mul' := fun _ _ => ext <| add_assoc _ _ } diff --git a/Mathlib/Dynamics/Ergodic/Ergodic.lean b/Mathlib/Dynamics/Ergodic/Ergodic.lean index b7bd2016eeee4..cc9abb51e7198 100644 --- a/Mathlib/Dynamics/Ergodic/Ergodic.lean +++ b/Mathlib/Dynamics/Ergodic/Ergodic.lean @@ -80,6 +80,9 @@ theorem smul_measure {R : Type*} [SMul R ℝ≥0∞] [IsScalarTower R ℝ≥0∞ (hf : PreErgodic f μ) (c : R) : PreErgodic f (c • μ) where aeconst_set _s hs hfs := (hf.aeconst_set hs hfs).anti <| ae_smul_measure_le _ +theorem zero_measure (f : α → α) : @PreErgodic α m f 0 where + aeconst_set _ _ _ := by simp + end PreErgodic namespace MeasureTheory.MeasurePreserving @@ -137,6 +140,11 @@ theorem smul_measure {R : Type*} [SMul R ℝ≥0∞] [IsScalarTower R ℝ≥0∞ (hf : QuasiErgodic f μ) (c : R) : QuasiErgodic f (c • μ) := ⟨hf.1.smul_measure _, hf.2.smul_measure _⟩ +theorem zero_measure {f : α → α} (hf : Measurable f) : @QuasiErgodic α m f 0 where + measurable := hf + absolutelyContinuous := by simp + toPreErgodic := .zero_measure f + end QuasiErgodic namespace Ergodic @@ -171,6 +179,11 @@ theorem smul_measure {R : Type*} [SMul R ℝ≥0∞] [IsScalarTower R ℝ≥0∞ (hf : Ergodic f μ) (c : R) : Ergodic f (c • μ) := ⟨hf.1.smul_measure _, hf.2.smul_measure _⟩ +theorem zero_measure {f : α → α} (hf : Measurable f) : @Ergodic α m f 0 where + measurable := hf + map_eq := by simp + toPreErgodic := .zero_measure f + section IsFiniteMeasure variable [IsFiniteMeasure μ] diff --git a/Mathlib/FieldTheory/Adjoin.lean b/Mathlib/FieldTheory/Adjoin.lean index e53c89cf4befb..51d8f9c940bb7 100644 --- a/Mathlib/FieldTheory/Adjoin.lean +++ b/Mathlib/FieldTheory/Adjoin.lean @@ -11,6 +11,7 @@ import Mathlib.LinearAlgebra.Dimension.FreeAndStrongRankCondition import Mathlib.RingTheory.Adjoin.Dimension import Mathlib.RingTheory.Finiteness.TensorProduct import Mathlib.RingTheory.TensorProduct.Basic +import Mathlib.SetTheory.Cardinal.Subfield /-! # Adjoining Elements to Fields @@ -1663,6 +1664,44 @@ theorem algHom_fieldRange_eq_of_comp_eq_of_range_eq refine ringHom_fieldRange_eq_of_comp_eq_of_range_eq h ?_ rw [← Algebra.adjoin_eq_ring_closure, ← hs]; rfl +variable [IsScalarTower F A K] + +/-- The image of `IsFractionRing.liftAlgHom` is the intermediate field generated by the image +of the algebra hom. -/ +theorem liftAlgHom_fieldRange (hg : Function.Injective g) : + (liftAlgHom hg : K →ₐ[F] L).fieldRange = IntermediateField.adjoin F g.range := + algHom_fieldRange_eq_of_comp_eq (by ext; simp) + +/-- The image of `IsFractionRing.liftAlgHom` is the intermediate field generated by `s`, +if the image of the algebra hom is the subalgebra generated by `s`. -/ +theorem liftAlgHom_fieldRange_eq_of_range_eq (hg : Function.Injective g) + {s : Set L} (hs : g.range = Algebra.adjoin F s) : + (liftAlgHom hg : K →ₐ[F] L).fieldRange = IntermediateField.adjoin F s := + algHom_fieldRange_eq_of_comp_eq_of_range_eq (by ext; simp) hs + end IsFractionRing -set_option linter.style.longFile 1700 +namespace IntermediateField + +universe u v + +open Cardinal + +variable (F : Type u) [Field F] + +theorem lift_cardinalMk_adjoin_le {E : Type v} [Field E] [Algebra F E] (s : Set E) : + Cardinal.lift.{u} #(adjoin F s) ≤ Cardinal.lift.{v} #F ⊔ Cardinal.lift.{u} #s ⊔ ℵ₀ := by + rw [show ↥(adjoin F s) = (adjoin F s).toSubfield from rfl, adjoin_toSubfield] + apply (Cardinal.lift_le.mpr (Subfield.cardinalMk_closure_le_max _)).trans + rw [lift_max, sup_le_iff, lift_aleph0] + refine ⟨(Cardinal.lift_le.mpr ((mk_union_le _ _).trans <| add_le_max _ _)).trans ?_, le_sup_right⟩ + simp_rw [lift_max, lift_aleph0, sup_assoc] + exact sup_le_sup_right mk_range_le_lift _ + +theorem cardinalMk_adjoin_le {E : Type u} [Field E] [Algebra F E] (s : Set E) : + #(adjoin F s) ≤ #F ⊔ #s ⊔ ℵ₀ := by + simpa using lift_cardinalMk_adjoin_le F s + +end IntermediateField + +set_option linter.style.longFile 1800 diff --git a/Mathlib/FieldTheory/Extension.lean b/Mathlib/FieldTheory/Extension.lean index da3e16176910d..142e5ed48085b 100644 --- a/Mathlib/FieldTheory/Extension.lean +++ b/Mathlib/FieldTheory/Extension.lean @@ -1,8 +1,9 @@ /- Copyright (c) 2020 Thomas Browning. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Thomas Browning +Authors: Thomas Browning, Junyan Xu -/ +import Mathlib.Data.Fintype.Order import Mathlib.FieldTheory.Adjoin /-! @@ -12,6 +13,12 @@ import Mathlib.FieldTheory.Adjoin field extensions, K is another extension of F, and `f` is an embedding of L/F into K/F, such that the minimal polynomials of a set of generators of E/L splits in K (via `f`), then `f` extends to an embedding of E/F into K/F. + +## Reference + +[Isaacs1980] *Roots of Polynomials in Algebraic Extensions of Fields*, +The American Mathematical Monthly + -/ open Polynomial @@ -29,6 +36,8 @@ structure Lifts where variable {F E K} +namespace Lifts + instance : PartialOrder (Lifts F E K) where le L₁ L₂ := ∃ h : L₁.carrier ≤ L₂.carrier, ∀ x, L₂.emb (inclusion h x) = L₁.emb x le_refl L := ⟨le_rfl, by simp⟩ @@ -52,25 +61,144 @@ noncomputable instance : OrderBot (Lifts F E K) where noncomputable instance : Inhabited (Lifts F E K) := ⟨⊥⟩ -/-- A chain of lifts has an upper bound. -/ -theorem Lifts.exists_upper_bound (c : Set (Lifts F E K)) (hc : IsChain (· ≤ ·) c) : - ∃ ub, ∀ a ∈ c, a ≤ ub := by +variable {L₁ L₂ : Lifts F E K} + +theorem le_iff : L₁ ≤ L₂ ↔ + ∃ h : L₁.carrier ≤ L₂.carrier, L₂.emb.comp (inclusion h) = L₁.emb := by + simp_rw [AlgHom.ext_iff]; rfl + +theorem eq_iff_le_carrier_eq : L₁ = L₂ ↔ L₁ ≤ L₂ ∧ L₁.carrier = L₂.carrier := + ⟨fun eq ↦ ⟨eq.le, congr_arg _ eq⟩, fun ⟨le, eq⟩ ↦ le.antisymm ⟨eq.ge, fun x ↦ (le.2 ⟨x, _⟩).symm⟩⟩ + +theorem eq_iff : L₁ = L₂ ↔ + ∃ h : L₁.carrier = L₂.carrier, L₂.emb.comp (inclusion h.le) = L₁.emb := by + rw [eq_iff_le_carrier_eq, le_iff] + exact ⟨fun h ↦ ⟨h.2, h.1.2⟩, fun h ↦ ⟨⟨h.1.le, h.2⟩, h.1⟩⟩ + +theorem lt_iff_le_carrier_ne : L₁ < L₂ ↔ L₁ ≤ L₂ ∧ L₁.carrier ≠ L₂.carrier := by + rw [lt_iff_le_and_ne, and_congr_right]; intro h; simp_rw [Ne, eq_iff_le_carrier_eq, h, true_and] + +theorem lt_iff : L₁ < L₂ ↔ + ∃ h : L₁.carrier < L₂.carrier, L₂.emb.comp (inclusion h.le) = L₁.emb := by + rw [lt_iff_le_carrier_ne, le_iff] + exact ⟨fun h ↦ ⟨h.1.1.lt_of_ne h.2, h.1.2⟩, fun h ↦ ⟨⟨h.1.le, h.2⟩, h.1.ne⟩⟩ + +theorem le_of_carrier_le_iSup {ι} {ρ : ι → Lifts F E K} {σ τ : Lifts F E K} + (hσ : ∀ i, ρ i ≤ σ) (hτ : ∀ i, ρ i ≤ τ) (carrier_le : σ.carrier ≤ ⨆ i, (ρ i).carrier) : + σ ≤ τ := + le_iff.mpr ⟨carrier_le.trans (iSup_le fun i ↦ (hτ i).1), algHom_ext_of_eq_adjoin _ + (carrier_le.antisymm (iSup_le fun i ↦ (hσ i).1)|>.trans <| iSup_eq_adjoin _ _) fun x hx ↦ + have ⟨i, hx⟩ := Set.mem_iUnion.mp hx + ((hτ i).2 ⟨x, hx⟩).trans ((hσ i).2 ⟨x, hx⟩).symm⟩ + +/-- `σ : L →ₐ[F] K` is an extendible lift ("extendible pair" in [Isaacs1980]) if for every +intermediate field `M` that is finite-dimensional over `L`, `σ` extends to some `M →ₐ[F] K`. +In our definition we only require `M` to be finitely generated over `L`, which is equivalent +if the ambient field `E` is algebraic over `F` (which is the case in our main application). +We also allow the domain of the extension to be an intermediate field that properly contains `M`, +since one can always restrict the domain to `M`. -/ +def IsExtendible (σ : Lifts F E K) : Prop := + ∀ S : Finset E, ∃ τ ≥ σ, (S : Set E) ⊆ τ.carrier + +section Chain +variable (c : Set (Lifts F E K)) (hc : IsChain (· ≤ ·) c) + +/-- The union of a chain of lifts. -/ +noncomputable def union : Lifts F E K := let t (i : ↑(insert ⊥ c)) := i.val.carrier - let t' (i) := (t i).toSubalgebra have hc := hc.insert fun _ _ _ ↦ .inl bot_le have dir : Directed (· ≤ ·) t := hc.directedOn.directed_val.mono_comp _ fun _ _ h ↦ h.1 - refine ⟨⟨iSup t, (Subalgebra.iSupLift t' dir (fun i ↦ i.val.emb) (fun i j h ↦ ?_) _ rfl).comp - (Subalgebra.equivOfEq _ _ <| toSubalgebra_iSup_of_directed dir)⟩, - fun L hL ↦ have hL := Set.mem_insert_of_mem ⊥ hL; ⟨le_iSup t ⟨L, hL⟩, fun x ↦ ?_⟩⟩ - · refine AlgHom.ext fun x ↦ (hc.total i.2 j.2).elim (fun hij ↦ (hij.snd x).symm) fun hji ↦ ?_ - erw [AlgHom.comp_apply, ← hji.snd (Subalgebra.inclusion h x), - inclusion_inclusion, inclusion_self, AlgHom.id_apply x] - · dsimp only [AlgHom.comp_apply] - exact Subalgebra.iSupLift_inclusion (K := t') (i := ⟨L, hL⟩) x (le_iSup t' ⟨L, hL⟩) + ⟨iSup t, (Subalgebra.iSupLift (toSubalgebra <| t ·) dir (·.val.emb) (fun i j h ↦ + AlgHom.ext fun x ↦ (hc.total i.2 j.2).elim (fun hij ↦ (hij.snd x).symm) fun hji ↦ by + erw [AlgHom.comp_apply, ← hji.snd (Subalgebra.inclusion h x), + inclusion_inclusion, inclusion_self, AlgHom.id_apply x]) _ rfl).comp + (Subalgebra.equivOfEq _ _ <| toSubalgebra_iSup_of_directed dir)⟩ + +theorem le_union ⦃σ : Lifts F E K⦄ (hσ : σ ∈ c) : σ ≤ union c hc := + have hσ := Set.mem_insert_of_mem ⊥ hσ + let t (i : ↑(insert ⊥ c)) := i.val.carrier + ⟨le_iSup t ⟨σ, hσ⟩, fun x ↦ by + dsimp only [union, AlgHom.comp_apply] + exact Subalgebra.iSupLift_inclusion (K := (toSubalgebra <| t ·)) + (i := ⟨σ, hσ⟩) x (le_iSup (toSubalgebra <| t ·) ⟨σ, hσ⟩)⟩ + +theorem carrier_union : (union c hc).carrier = ⨆ i : c, i.1.carrier := + le_antisymm (iSup_le <| by rintro ⟨i, rfl|hi⟩; exacts [bot_le, le_iSup_of_le ⟨i, hi⟩ le_rfl]) <| + iSup_le fun i ↦ le_iSup_of_le ⟨i, .inr i.2⟩ le_rfl + +/-- A chain of lifts has an upper bound. -/ +theorem exists_upper_bound (c : Set (Lifts F E K)) (hc : IsChain (· ≤ ·) c) : + ∃ ub, ∀ a ∈ c, a ≤ ub := ⟨_, le_union c hc⟩ + +theorem union_isExtendible [alg : Algebra.IsAlgebraic F E] + [Nonempty c] (hext : ∀ σ ∈ c, σ.IsExtendible) : + (union c hc).IsExtendible := fun S ↦ by + let Ω := adjoin F (S : Set E) →ₐ[F] K + have ⟨ω, hω⟩ : ∃ ω : Ω, ∀ π : c, ∃ θ ≥ π.1, ⟨_, ω⟩ ≤ θ ∧ θ.carrier = π.1.1 ⊔ adjoin F S := by + by_contra!; choose π hπ using this + have := finiteDimensional_adjoin (S := (S : Set E)) fun _ _ ↦ (alg.isIntegral).1 _ + have ⟨π₀, hπ₀⟩ := hc.directed.finite_le π + have ⟨θ, hθπ, hθ⟩ := hext _ π₀.2 S + rw [← adjoin_le_iff] at hθ + let θ₀ := θ.emb.comp (inclusion hθ) + have := (hπ₀ θ₀).trans hθπ + exact hπ θ₀ ⟨_, θ.emb.comp <| inclusion <| sup_le this.1 hθ⟩ + ⟨le_sup_left, this.2⟩ ⟨le_sup_right, fun _ ↦ rfl⟩ rfl + choose θ ge hθ eq using hω + have : IsChain (· ≤ ·) (Set.range θ) := by + simp_rw [← restrictScalars_adjoin_eq_sup, restrictScalars_adjoin] at eq + rintro _ ⟨π₁, rfl⟩ _ ⟨π₂, rfl⟩ - + wlog h : π₁ ≤ π₂ generalizing π₁ π₂ + · exact (this _ _ <| (hc.total π₁.2 π₂.2).resolve_left h).symm + refine .inl (le_iff.mpr ⟨?_, algHom_ext_of_eq_adjoin _ (eq _) ?_⟩) + · rw [eq, eq]; exact adjoin.mono _ _ _ (Set.union_subset_union_left _ h.1) + rintro x (hx|hx) + · change (θ π₂).emb (inclusion (ge π₂).1 <| inclusion h.1 ⟨x, hx⟩) = + (θ π₁).emb (inclusion (ge π₁).1 ⟨x, hx⟩) + rw [(ge π₁).2, (ge π₂).2, h.2] + · change (θ π₂).emb (inclusion (hθ π₂).1 ⟨x, subset_adjoin _ _ hx⟩) = + (θ π₁).emb (inclusion (hθ π₁).1 ⟨x, subset_adjoin _ _ hx⟩) + rw [(hθ π₁).2, (hθ π₂).2] + refine ⟨union _ this, le_of_carrier_le_iSup (fun π ↦ le_union c hc π.2) + (fun π ↦ (ge π).trans <| le_union _ _ ⟨_, rfl⟩) (carrier_union _ _).le, ?_⟩ + simp_rw [carrier_union, iSup_range', eq] + exact (subset_adjoin _ _).trans (SetLike.coe_subset_coe.mpr <| + le_sup_right.trans <| le_iSup_of_le (Classical.arbitrary _) le_rfl) + +end Chain + +theorem nonempty_algHom_of_exist_lifts_finset [alg : Algebra.IsAlgebraic F E] + (h : ∀ S : Finset E, ∃ σ : Lifts F E K, (S : Set E) ⊆ σ.carrier) : + Nonempty (E →ₐ[F] K) := by + have : (⊥ : Lifts F E K).IsExtendible := fun S ↦ have ⟨σ, hσ⟩ := h S; ⟨σ, bot_le, hσ⟩ + have ⟨ϕ, hϕ⟩ := zorn_le₀ {ϕ : Lifts F E K | ϕ.IsExtendible} + fun c hext hc ↦ (isEmpty_or_nonempty c).elim + (fun _ ↦ ⟨⊥, this, fun ϕ hϕ ↦ isEmptyElim (⟨ϕ, hϕ⟩ : c)⟩) + fun _ ↦ ⟨_, union_isExtendible c hc hext, le_union c hc⟩ + suffices ϕ.carrier = ⊤ from ⟨ϕ.emb.comp <| ((equivOfEq this).trans topEquiv).symm⟩ + by_contra! + obtain ⟨α, -, hα⟩ := SetLike.exists_of_lt this.lt_top + let _ : Algebra ϕ.carrier K := ϕ.emb.toAlgebra + let Λ := ϕ.carrier⟮α⟯ →ₐ[ϕ.carrier] K + have := finiteDimensional_adjoin (S := {α}) fun _ _ ↦ ((alg.tower_top ϕ.carrier).isIntegral).1 _ + let L (σ : Λ) : Lifts F E K := ⟨ϕ.carrier⟮α⟯.restrictScalars F, σ.restrictScalars F⟩ + have hL (σ : Λ) : ϕ < L σ := lt_iff.mpr + ⟨by simpa only [restrictScalars_adjoin_eq_sup, left_lt_sup, adjoin_simple_le_iff], + AlgHom.coe_ringHom_injective σ.comp_algebraMap⟩ + have ⟨(ϕ_ext : ϕ.IsExtendible), ϕ_max⟩ := maximal_iff_forall_gt.mp hϕ + simp_rw [Set.mem_setOf, IsExtendible] at ϕ_max; push_neg at ϕ_max + choose S hS using fun σ : Λ ↦ ϕ_max (hL σ) + classical + have ⟨θ, hθϕ, hθ⟩ := ϕ_ext ({α} ∪ Finset.univ.biUnion S) + simp_rw [Finset.coe_union, Set.union_subset_iff, Finset.coe_singleton, Set.singleton_subset_iff, + Finset.coe_biUnion, Finset.coe_univ, Set.mem_univ, Set.iUnion_true, Set.iUnion_subset_iff] at hθ + have : ϕ.carrier⟮α⟯.restrictScalars F ≤ θ.carrier := by + rw [restrictScalars_adjoin_eq_sup, sup_le_iff, adjoin_simple_le_iff]; exact ⟨hθϕ.1, hθ.1⟩ + exact hS ⟨(θ.emb.comp <| inclusion this).toRingHom, hθϕ.2⟩ θ ⟨this, fun _ ↦ rfl⟩ (hθ.2 _) /-- Given a lift `x` and an integral element `s : E` over `x.carrier` whose conjugates over `x.carrier` are all in `K`, we can extend the lift to a lift whose carrier contains `s`. -/ -theorem Lifts.exists_lift_of_splits' (x : Lifts F E K) {s : E} (h1 : IsIntegral x.carrier s) +theorem exists_lift_of_splits' (x : Lifts F E K) {s : E} (h1 : IsIntegral x.carrier s) (h2 : (minpoly x.carrier s).Splits x.emb.toRingHom) : ∃ y, x ≤ y ∧ s ∈ y.carrier := have I2 := (minpoly.degree_pos h1).ne' letI : Algebra x.carrier K := x.emb.toRingHom.toAlgebra @@ -87,11 +215,13 @@ theorem Lifts.exists_lift_of_splits' (x : Lifts F E K) {s : E} (h1 : IsIntegral /-- Given an integral element `s : E` over `F` whose `F`-conjugates are all in `K`, any lift can be extended to one whose carrier contains `s`. -/ -theorem Lifts.exists_lift_of_splits (x : Lifts F E K) {s : E} (h1 : IsIntegral F s) +theorem exists_lift_of_splits (x : Lifts F E K) {s : E} (h1 : IsIntegral F s) (h2 : (minpoly F s).Splits (algebraMap F K)) : ∃ y, x ≤ y ∧ s ∈ y.carrier := - Lifts.exists_lift_of_splits' x h1.tower_top <| h1.minpoly_splits_tower_top' <| by + exists_lift_of_splits' x h1.tower_top <| h1.minpoly_splits_tower_top' <| by rwa [← x.emb.comp_algebraMap] at h2 +end Lifts + section private theorem exists_algHom_adjoin_of_splits'' {L : IntermediateField F E} diff --git a/Mathlib/FieldTheory/IsAlgClosed/Basic.lean b/Mathlib/FieldTheory/IsAlgClosed/Basic.lean index 2ec4275183cac..c164bdbac9521 100644 --- a/Mathlib/FieldTheory/IsAlgClosed/Basic.lean +++ b/Mathlib/FieldTheory/IsAlgClosed/Basic.lean @@ -32,10 +32,12 @@ polynomial in `k` splits. algebraic closure, algebraically closed -## TODO +## Main reults -- Prove that if `K / k` is algebraic, and any monic irreducible polynomial over `k` has a root - in `K`, then `K` is algebraically closed (in fact an algebraic closure of `k`). +- `IsAlgClosure.of_splits`: if `K / k` is algebraic, and every monic irreducible polynomial over + `k` splits in `K`, then `K` is algebraically closed (in fact an algebraic closure of `k`). + For the stronger fact that only requires every such polynomial has a root in `K`, + see `IsAlgClosure.of_exist_roots`. Reference: , Theorem 2 @@ -410,7 +412,7 @@ noncomputable def equivOfEquivAux (hSR : S ≃+* R) : haveI : IsScalarTower S R L := IsScalarTower.of_algebraMap_eq (by simp [RingHom.algebraMap_toAlgebra]) haveI : NoZeroSMulDivisors R S := NoZeroSMulDivisors.of_algebraMap_injective hSR.symm.injective - have : Algebra.IsAlgebraic R L := (IsAlgClosure.isAlgebraic.tower_top_of_injective + have : Algebra.IsAlgebraic R L := (IsAlgClosure.isAlgebraic.extendScalars (show Function.Injective (algebraMap S R) from hSR.injective)) refine ⟨equivOfAlgebraic' R S L M, ?_⟩ diff --git a/Mathlib/FieldTheory/Isaacs.lean b/Mathlib/FieldTheory/Isaacs.lean new file mode 100644 index 0000000000000..2219c66b3c027 --- /dev/null +++ b/Mathlib/FieldTheory/Isaacs.lean @@ -0,0 +1,115 @@ +/- +Copyright (c) 2024 Junyan Xu. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Junyan Xu +-/ +import Mathlib.FieldTheory.PrimitiveElement +import Mathlib.GroupTheory.CosetCover + +/-! +# Algebraic extensions are determined by their sets of minimal polynomials up to isomorphism + +## Main results + +`Field.nonempty_algHom_of_exist_roots` says if `E/F` and `K/F` are field extensions +with `E/F` algebraic, and if the minimal polynomial of every element of `E` over `F` has a root +in `K`, then there exists an `F`-embedding of `E` into `K`. If `E/F` and `K/F` have the same +set of minimal polynomials, then `E` and `K` are isomorphic as `F`-algebras. As a corollary: + +`IsAlgClosure.of_exist_roots`: if `E/F` is algebraic and every monic irreducible polynomial +in `F[X]` has a root in `E`, then `E` is an algebraic closure of `F`. + +## Reference + +[Isaacs1980] *Roots of Polynomials in Algebraic Extensions of Fields*, +The American Mathematical Monthly + +-/ + +namespace Field + +open Polynomial IntermediateField + +variable {F E K : Type*} [Field F] [Field E] [Field K] [Algebra F E] [Algebra F K] +variable [alg : Algebra.IsAlgebraic F E] + +theorem nonempty_algHom_of_exist_roots (h : ∀ x : E, ∃ y : K, aeval y (minpoly F x) = 0) : + Nonempty (E →ₐ[F] K) := by + refine Lifts.nonempty_algHom_of_exist_lifts_finset fun S ↦ ⟨⟨adjoin F S, ?_⟩, subset_adjoin _ _⟩ + let p := (S.prod <| minpoly F).map (algebraMap F K) + let K' := SplittingField p + have splits s (hs : s ∈ S) : (minpoly F s).Splits (algebraMap F K') := by + apply splits_of_splits_of_dvd _ + (Finset.prod_ne_zero_iff.mpr fun _ _ ↦ minpoly.ne_zero <| (alg.isIntegral).1 _) + ((splits_map_iff _ _).mp <| SplittingField.splits p) (Finset.dvd_prod_of_mem _ hs) + let K₀ := (⊥ : IntermediateField K K').restrictScalars F + let FS := adjoin F (S : Set E) + let Ω := FS →ₐ[F] K' + have := finiteDimensional_adjoin (S := (S : Set E)) fun _ _ ↦ (alg.isIntegral).1 _ + let M (ω : Ω) := Subalgebra.toSubmodule (K₀.comap ω).toSubalgebra + have : ⋃ ω : Ω, (M ω : Set FS) = Set.univ := + Set.eq_univ_of_forall fun ⟨α, hα⟩ ↦ Set.mem_iUnion.mpr <| by + have ⟨β, hβ⟩ := h α + let ϕ : F⟮α⟯ →ₐ[F] K' := (IsScalarTower.toAlgHom _ _ _).comp ((AdjoinRoot.liftHom _ _ hβ).comp + (adjoinRootEquivAdjoin F <| (alg.isIntegral).1 _).symm.toAlgHom) + have ⟨ω, hω⟩ := exists_algHom_adjoin_of_splits + (fun s hs ↦ ⟨(alg.isIntegral).1 _, splits s hs⟩) ϕ (adjoin_simple_le_iff.mpr hα) + refine ⟨ω, β, ((DFunLike.congr_fun hω <| AdjoinSimple.gen F α).trans ?_).symm⟩ + rw [AlgHom.comp_apply, AlgHom.comp_apply, AlgEquiv.coe_algHom, + adjoinRootEquivAdjoin_symm_apply_gen, AdjoinRoot.liftHom_root] + rfl + have ω : ∃ ω : Ω, ⊤ ≤ M ω := by + cases finite_or_infinite F + · have ⟨α, hα⟩ := exists_primitive_element_of_finite_bot F FS + have ⟨ω, hω⟩ := Set.mem_iUnion.mp (this ▸ Set.mem_univ α) + exact ⟨ω, show ⊤ ≤ K₀.comap ω by rwa [← hα, adjoin_simple_le_iff]⟩ + · simp_rw [top_le_iff, Subspace.exists_eq_top_of_iUnion_eq_univ this] + exact ((botEquiv K K').toAlgHom.restrictScalars F).comp + (ω.choose.codRestrict K₀.toSubalgebra fun x ↦ ω.choose_spec trivial) + +theorem nonempty_algHom_of_minpoly_eq + (h : ∀ x : E, ∃ y : K, minpoly F x = minpoly F y) : + Nonempty (E →ₐ[F] K) := + nonempty_algHom_of_exist_roots fun x ↦ have ⟨y, hy⟩ := h x; ⟨y, by rw [hy, minpoly.aeval]⟩ + +theorem nonempty_algHom_of_range_minpoly_subset + (h : Set.range (@minpoly F E _ _ _) ⊆ Set.range (@minpoly F K _ _ _)) : + Nonempty (E →ₐ[F] K) := + nonempty_algHom_of_minpoly_eq fun x ↦ have ⟨y, hy⟩ := h ⟨x, rfl⟩; ⟨y, hy.symm⟩ + +theorem nonempty_algEquiv_of_range_minpoly_eq + (h : Set.range (@minpoly F E _ _ _) = Set.range (@minpoly F K _ _ _)) : + Nonempty (E ≃ₐ[F] K) := + have ⟨σ⟩ := nonempty_algHom_of_range_minpoly_subset h.le + have : Algebra.IsAlgebraic F K := ⟨fun y ↦ IsIntegral.isAlgebraic <| by + by_contra hy + have ⟨x, hx⟩ := h.ge ⟨y, rfl⟩ + rw [minpoly.eq_zero hy] at hx + exact minpoly.ne_zero ((alg.isIntegral).1 x) hx⟩ + have ⟨τ⟩ := nonempty_algHom_of_range_minpoly_subset h.ge + ⟨.ofBijective _ (Algebra.IsAlgebraic.algHom_bijective₂ σ τ).1⟩ + +theorem nonempty_algHom_of_aeval_eq_zero_subset + (h : {p : F[X] | ∃ x : E, aeval x p = 0} ⊆ {p | ∃ y : K, aeval y p = 0}) : + Nonempty (E →ₐ[F] K) := + nonempty_algHom_of_minpoly_eq fun x ↦ + have ⟨y, hy⟩ := h ⟨_, minpoly.aeval F x⟩ + ⟨y, (minpoly.eq_iff_aeval_minpoly_eq_zero <| (alg.isIntegral).1 x).mpr hy⟩ + +theorem nonempty_algEquiv_of_aeval_eq_zero_eq [Algebra.IsAlgebraic F K] + (h : {p : F[X] | ∃ x : E, aeval x p = 0} = {p | ∃ y : K, aeval y p = 0}) : + Nonempty (E ≃ₐ[F] K) := + have ⟨σ⟩ := nonempty_algHom_of_aeval_eq_zero_subset h.le + have ⟨τ⟩ := nonempty_algHom_of_aeval_eq_zero_subset h.ge + ⟨.ofBijective _ (Algebra.IsAlgebraic.algHom_bijective₂ σ τ).1⟩ + +theorem _root_.IsAlgClosure.of_exist_roots + (h : ∀ p : F[X], p.Monic → Irreducible p → ∃ x : E, aeval x p = 0) : + IsAlgClosure F E := + .of_splits fun p _ _ ↦ + have ⟨σ⟩ := nonempty_algHom_of_exist_roots fun x : p.SplittingField ↦ + have := Algebra.IsAlgebraic.isIntegral (K := F).1 x + h _ (minpoly.monic this) (minpoly.irreducible this) + splits_of_algHom (SplittingField.splits _) σ + +end Field diff --git a/Mathlib/FieldTheory/JacobsonNoether.lean b/Mathlib/FieldTheory/JacobsonNoether.lean new file mode 100644 index 0000000000000..e019eaf9f4231 --- /dev/null +++ b/Mathlib/FieldTheory/JacobsonNoether.lean @@ -0,0 +1,195 @@ +/- +Copyright (c) 2024 F. Nuccio, H. Zheng, W. He, S. Wu, Y. Yuan, W. Jiao. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Filippo A. E. Nuccio, Huanyu Zheng, Sihan Wu, Wanyi He, Weichen Jiao, Yi Yuan +-/ +import Mathlib.Algebra.Central.Defs +import Mathlib.Algebra.CharP.LinearMaps +import Mathlib.Algebra.CharP.Subring +import Mathlib.Algebra.GroupWithZero.Conj +import Mathlib.Algebra.Lie.OfAssociative +import Mathlib.FieldTheory.PurelyInseparable + +/-! +# The Jacobson-Noether theorem + +This file contains a proof of the Jacobson-Noether theorem and some auxiliary lemmas. +Here we discuss different cases of characteristics of +the noncommutative division algebra `D` with center `k`. + +## Main Results + +- `exists_separable_and_not_isCentral` : (Jacobson-Noether theorem) For a + non-commutative algebraic division algebra `D` (with base ring + being its center `k`), then there exist an element `x` of + `D \ k` that is separable over its center. +- `exists_separable_and_not_isCentral'` : (Jacobson-Noether theorem) For a + non-commutative algebraic division algebra `D` (with base ring + being a field `L`), if the center of `D` over `L` is `L`, + then there exist an element `x` of `D \ L` that is separable over `L`. + +## Notations + +- `D` is a noncommutative division algebra +- `k` is the center of `D` + +## Implementation Notes + +Mathematically, `exists_separable_and_not_isCentral` and `exists_separable_and_not_isCentral'` +are equivalent. + +The difference however, is that the former takes `D` as the only variable +and fixing `D` would forces `k`. Whereas the later takes `D` and `L` as +separate variables constrained by certain relations. + +## Reference +* +-/ + +namespace JacobsonNoether + +variable {D : Type*} [DivisionRing D] [Algebra.IsAlgebraic (Subring.center D) D] + +local notation3 "k" => Subring.center D + +open Polynomial LinearMap LieAlgebra + +/-- If `D` is a purely inseparable extension of `k` with characteristic `p`, + then for every element `a` of `D`, there exists a natural number `n` + such that `a ^ (p ^ n)` is contained in `k`. -/ +lemma exists_pow_mem_center_of_inseparable (p : ℕ) [hchar : ExpChar D p] (a : D) + (hinsep : ∀ x : D, IsSeparable k x → x ∈ k) : ∃ n, a ^ (p ^ n) ∈ k := by + have := (@isPurelyInseparable_iff_pow_mem k D _ _ _ _ p (ExpChar.expChar_center_iff.2 hchar)).1 + have pure : IsPurelyInseparable k D := ⟨Algebra.IsAlgebraic.isIntegral, fun x hx ↦ by + rw [RingHom.mem_range, Subtype.exists] + exact ⟨x, ⟨hinsep x hx, rfl⟩⟩⟩ + obtain ⟨n, ⟨m, hm⟩⟩ := this pure a + have := Subalgebra.range_subset (R := k) ⟨(k).toSubsemiring, fun r ↦ r.2⟩ + exact ⟨n, Set.mem_of_subset_of_mem this <| Set.mem_range.2 ⟨m, hm⟩⟩ + +/-- If `D` is a purely inseparable extension of `k` with characteristic `p`, + then for every element `a` of `D \ k`, there exists a natural number `n` + **greater than 0** such that `a ^ (p ^ n)` is contained in `k`. -/ +lemma exists_pow_mem_center_of_inseparable' (p : ℕ) [ExpChar D p] {a : D} + (ha : a ∉ k) (hinsep : ∀ x : D, IsSeparable k x → x ∈ k) : ∃ n, 1 ≤ n ∧ a ^ (p ^ n) ∈ k := by + obtain ⟨n, hn⟩ := exists_pow_mem_center_of_inseparable p a hinsep + by_cases nzero : n = 0 + · rw [nzero, pow_zero, pow_one] at hn + exact (ha hn).elim + · exact ⟨n, ⟨Nat.one_le_iff_ne_zero.mpr nzero, hn⟩⟩ + +/-- If `D` is a purely inseparable extension of `k` of characteristic `p`, + then for every element `a` of `D \ k`, there exists a natural number `m` + greater than 0 such that `(a * x - x * a) ^ n = 0` (as linear maps) for + every `n` greater than `(p ^ m)`. -/ +lemma exist_pow_eq_zero_of_le (p : ℕ) [hchar : ExpChar D p] + {a : D} (ha : a ∉ k) (hinsep : ∀ x : D, IsSeparable k x → x ∈ k): + ∃ m, 1 ≤ m ∧ ∀ n, p ^ m ≤ n → (ad k D a)^[n] = 0 := by + obtain ⟨m, hm⟩ := exists_pow_mem_center_of_inseparable' p ha hinsep + refine ⟨m, ⟨hm.1, fun n hn ↦ ?_⟩⟩ + have inter : (ad k D a)^[p ^ m] = 0 := by + ext x + rw [ad_eq_lmul_left_sub_lmul_right, ← pow_apply, Pi.sub_apply, + sub_pow_expChar_pow_of_commute p m (commute_mulLeft_right a a), sub_apply, + pow_mulLeft, mulLeft_apply, pow_mulRight, mulRight_apply, Pi.zero_apply, + Subring.mem_center_iff.1 hm.2 x] + exact sub_eq_zero_of_eq rfl + rw [(Nat.sub_eq_iff_eq_add hn).1 rfl, Function.iterate_add, inter, Pi.comp_zero, + iterate_map_zero, Function.const_zero] + +variable (D) in +/-- Jacobson-Noether theorem: For a non-commutative division algebra + `D` that is algebraic over its center `k`, there exists an element + `x` of `D \ k` that is separable over `k`. -/ +theorem exists_separable_and_not_isCentral (H : k ≠ (⊤ : Subring D)) : + ∃ x : D, x ∉ k ∧ IsSeparable k x := by + obtain ⟨p, hp⟩ := ExpChar.exists D + by_contra! insep + replace insep : ∀ x : D, IsSeparable k x → x ∈ k := + fun x h ↦ Classical.byContradiction fun hx ↦ insep x hx h + -- The element `a` below is in `D` but not in `k`. + obtain ⟨a, ha⟩ := not_forall.mp <| mt (Subring.eq_top_iff' k).mpr H + have ha₀ : a ≠ 0 := fun nh ↦ nh ▸ ha <| Subring.zero_mem k + -- We construct another element `b` that does not commute with `a`. + obtain ⟨b, hb1⟩ : ∃ b : D , ad k D a b ≠ 0 := by + rw [Subring.mem_center_iff, not_forall] at ha + use ha.choose + show a * ha.choose - ha.choose * a ≠ 0 + simpa only [ne_eq, sub_eq_zero] using Ne.symm ha.choose_spec + -- We find a maximum natural number `n` such that `(a * x - x * a) ^ n b ≠ 0`. + obtain ⟨n, hn, hb⟩ : ∃ n, 0 < n ∧ (ad k D a)^[n] b ≠ 0 ∧ (ad k D a)^[n + 1] b = 0 := by + obtain ⟨m, -, hm2⟩ := exist_pow_eq_zero_of_le p ha insep + have h_exist : ∃ n, 0 < n ∧ (ad k D a)^[n + 1] b = 0 := ⟨p ^ m, + ⟨expChar_pow_pos D p m, by rw [hm2 (p ^ m + 1) (Nat.le_add_right _ _)]; rfl⟩⟩ + classical + refine ⟨Nat.find h_exist, ⟨(Nat.find_spec h_exist).1, ?_, (Nat.find_spec h_exist).2⟩⟩ + set t := (Nat.find h_exist - 1 : ℕ) with ht + by_cases h_pos : 0 < t + · convert (ne_eq _ _) ▸ not_and.mp (Nat.find_min h_exist (m := t) (by omega)) h_pos + omega + · suffices h_find: Nat.find h_exist = 1 by + rwa [h_find] + rw [not_lt, Nat.le_zero, ht, Nat.sub_eq_zero_iff_le] at h_pos + linarith [(Nat.find_spec h_exist).1] + -- We define `c` to be the value that we proved above to be non-zero. + set c := (ad k D a)^[n] b with hc_def + let _ : Invertible c := ⟨c⁻¹, inv_mul_cancel₀ hb.1, mul_inv_cancel₀ hb.1⟩ + -- We prove that `c` commutes with `a`. + have hc : a * c = c * a := by + apply eq_of_sub_eq_zero + rw [← mulLeft_apply (R := k), ← mulRight_apply (R := k)] + suffices ad k D a c = 0 from by + rw [← this]; rfl + rw [← Function.iterate_succ_apply' (ad k D a) n b, hb.2] + -- We now make some computation to obtain the final equation. + set d := c⁻¹ * a * (ad k D a)^[n - 1] b with hd_def + have hc': c⁻¹ * a = a * c⁻¹ := by + apply_fun (c⁻¹ * · * c⁻¹) at hc + rw [mul_assoc, mul_assoc, mul_inv_cancel₀ hb.1, mul_one, ← mul_assoc, + inv_mul_cancel₀ hb.1, one_mul] at hc + exact hc + have c_eq : a * (ad k D a)^[n - 1] b - (ad k D a)^[n - 1] b * a = c := by + rw [hc_def, ← Nat.sub_add_cancel hn, Function.iterate_succ_apply' (ad k D a) _ b]; rfl + have eq1 : c⁻¹ * a * (ad k D a)^[n - 1] b - c⁻¹ * (ad k D a)^[n - 1] b * a = 1 := by + simp_rw [mul_assoc, (mul_sub_left_distrib c⁻¹ _ _).symm, c_eq, inv_mul_cancel_of_invertible] + -- We show that `a` commutes with `d`. + have deq : a * d - d * a = a := by + nth_rw 3 [← mul_one a] + rw [hd_def, ← eq1, mul_sub, mul_assoc _ _ a, sub_right_inj, hc', + ← mul_assoc, ← mul_assoc, ← mul_assoc] + -- This then yields a contradiction. + apply_fun (a⁻¹ * · ) at deq + rw [mul_sub, ← mul_assoc, inv_mul_cancel₀ ha₀, one_mul, ← mul_assoc, sub_eq_iff_eq_add] at deq + obtain ⟨r, hr⟩ := exists_pow_mem_center_of_inseparable p d insep + apply_fun (· ^ (p ^ r)) at deq + rw [add_pow_expChar_pow_of_commute p r (Commute.one_left _) , one_pow, + GroupWithZero.conj_pow₀ ha₀, ← hr.comm, mul_assoc, inv_mul_cancel₀ ha₀, mul_one, + self_eq_add_left] at deq + exact one_ne_zero deq + +open Subring Algebra in +/-- Jacobson-Noether theorem: For a non-commutative division algebra `D` + that is algebraic over a field `L`, if the center of + `D` coincides with `L`, then there exist an element `x` of `D \ L` + that is separable over `L`. -/ +theorem exists_separable_and_not_isCentral' {L D : Type*} [Field L] [DivisionRing D] + [Algebra L D] [Algebra.IsAlgebraic L D] [Algebra.IsCentral L D] + (hneq : (⊥ : Subalgebra L D) ≠ ⊤) : + ∃ x : D, x ∉ (⊥ : Subalgebra L D) ∧ IsSeparable L x := by + have hcenter : Subalgebra.center L D = ⊥ := le_bot_iff.mp IsCentral.out + have ntrivial : Subring.center D ≠ ⊤ := + congr(Subalgebra.toSubring $hcenter).trans_ne (Subalgebra.toSubring_injective.ne hneq) + set φ := Subalgebra.equivOfEq (⊥ : Subalgebra L D) (.center L D) hcenter.symm + set equiv : L ≃+* (center D) := ((botEquiv L D).symm.trans φ).toRingEquiv + let _ : Algebra L (center D) := equiv.toRingHom.toAlgebra + let _ : Algebra (center D) L := equiv.symm.toRingHom.toAlgebra + have _ : IsScalarTower L (center D) D := .of_algebraMap_eq fun _ ↦ rfl + have _ : IsScalarTower (center D) L D := .of_algebraMap_eq fun x ↦ by + rw [IsScalarTower.algebraMap_apply L (center D)] + congr + exact (equiv.apply_symm_apply x).symm + have _ : Algebra.IsAlgebraic (center D) D := .tower_top (K := L) _ + obtain ⟨x, hxd, hx⟩ := exists_separable_and_not_isCentral D ntrivial + exact ⟨x, ⟨by rwa [← Subalgebra.center_toSubring L, hcenter] at hxd, IsSeparable.tower_top _ hx⟩⟩ + +end JacobsonNoether diff --git a/Mathlib/FieldTheory/Tower.lean b/Mathlib/FieldTheory/Tower.lean index dbe2c6efe3f02..59cdb775f2ec4 100644 --- a/Mathlib/FieldTheory/Tower.lean +++ b/Mathlib/FieldTheory/Tower.lean @@ -3,7 +3,7 @@ Copyright (c) 2020 Kenny Lau. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kenny Lau -/ -import Mathlib.RingTheory.Noetherian.Defs +import Mathlib.RingTheory.Noetherian.Basic /-! # Finiteness of `IsScalarTower` diff --git a/Mathlib/Geometry/Manifold/Algebra/LeftInvariantDerivation.lean b/Mathlib/Geometry/Manifold/Algebra/LeftInvariantDerivation.lean index 998cc71804f14..9e2358ae486b1 100644 --- a/Mathlib/Geometry/Manifold/Algebra/LeftInvariantDerivation.lean +++ b/Mathlib/Geometry/Manifold/Algebra/LeftInvariantDerivation.lean @@ -23,6 +23,9 @@ implementing one of the possible definitions of the Lie algebra attached to a Li noncomputable section open scoped LieGroup Manifold Derivation +/- Next line is necessary while the manifold smoothness class is not extended to `ω`. +Later, replace with `open scoped ContDiff`. -/ +local notation "∞" => (⊤ : ℕ∞) variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] {H : Type*} [TopologicalSpace H] (I : ModelWithCorners 𝕜 E H) (G : Type*) diff --git a/Mathlib/Geometry/Manifold/Algebra/LieGroup.lean b/Mathlib/Geometry/Manifold/Algebra/LieGroup.lean index c054be8efa60b..c9dd661d44afd 100644 --- a/Mathlib/Geometry/Manifold/Algebra/LieGroup.lean +++ b/Mathlib/Geometry/Manifold/Algebra/LieGroup.lean @@ -58,7 +58,7 @@ class LieAddGroup {𝕜 : Type*} [NontriviallyNormedField 𝕜] {H : Type*} [Top {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] (I : ModelWithCorners 𝕜 E H) (G : Type*) [AddGroup G] [TopologicalSpace G] [ChartedSpace H G] extends SmoothAdd I G : Prop where /-- Negation is smooth in an additive Lie group. -/ - smooth_neg : Smooth I I fun a : G => -a + smooth_neg : ContMDiff I I ⊤ fun a : G => -a -- See note [Design choices about smooth algebraic structures] /-- A (multiplicative) Lie group is a group and a smooth manifold at the same time in which @@ -68,7 +68,7 @@ class LieGroup {𝕜 : Type*} [NontriviallyNormedField 𝕜] {H : Type*} [Topolo {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] (I : ModelWithCorners 𝕜 E H) (G : Type*) [Group G] [TopologicalSpace G] [ChartedSpace H G] extends SmoothMul I G : Prop where /-- Inversion is smooth in a Lie group. -/ - smooth_inv : Smooth I I fun a : G => a⁻¹ + smooth_inv : ContMDiff I I ⊤ fun a : G => a⁻¹ /-! ### Smoothness of inversion, negation, division and subtraction @@ -91,28 +91,31 @@ variable (I) /-- In a Lie group, inversion is a smooth map. -/ @[to_additive "In an additive Lie group, inversion is a smooth map."] -theorem smooth_inv : Smooth I I fun x : G => x⁻¹ := +theorem contMDiff_inv : ContMDiff I I ⊤ fun x : G => x⁻¹ := LieGroup.smooth_inv +@[deprecated (since := "2024-11-21")] alias smooth_inv := contMDiff_inv +@[deprecated (since := "2024-11-21")] alias smooth_neg := contMDiff_neg + include I in /-- A Lie group is a topological group. This is not an instance for technical reasons, see note [Design choices about smooth algebraic structures]. -/ @[to_additive "An additive Lie group is an additive topological group. This is not an instance for technical reasons, see note [Design choices about smooth algebraic structures]."] theorem topologicalGroup_of_lieGroup : TopologicalGroup G := - { continuousMul_of_smooth I with continuous_inv := (smooth_inv I).continuous } + { continuousMul_of_smooth I with continuous_inv := (contMDiff_inv I).continuous } end @[to_additive] theorem ContMDiffWithinAt.inv {f : M → G} {s : Set M} {x₀ : M} (hf : ContMDiffWithinAt I' I n f s x₀) : ContMDiffWithinAt I' I n (fun x => (f x)⁻¹) s x₀ := - ((smooth_inv I).of_le le_top).contMDiffAt.contMDiffWithinAt.comp x₀ hf <| Set.mapsTo_univ _ _ + ((contMDiff_inv I).of_le le_top).contMDiffAt.contMDiffWithinAt.comp x₀ hf <| Set.mapsTo_univ _ _ @[to_additive] theorem ContMDiffAt.inv {f : M → G} {x₀ : M} (hf : ContMDiffAt I' I n f x₀) : ContMDiffAt I' I n (fun x => (f x)⁻¹) x₀ := - ((smooth_inv I).of_le le_top).contMDiffAt.comp x₀ hf + ((contMDiff_inv I).of_le le_top).contMDiffAt.comp x₀ hf @[to_additive] theorem ContMDiffOn.inv {f : M → G} {s : Set M} (hf : ContMDiffOn I' I n f s) : @@ -122,24 +125,15 @@ theorem ContMDiffOn.inv {f : M → G} {s : Set M} (hf : ContMDiffOn I' I n f s) theorem ContMDiff.inv {f : M → G} (hf : ContMDiff I' I n f) : ContMDiff I' I n fun x => (f x)⁻¹ := fun x => (hf x).inv -@[to_additive] -nonrec theorem SmoothWithinAt.inv {f : M → G} {s : Set M} {x₀ : M} - (hf : SmoothWithinAt I' I f s x₀) : SmoothWithinAt I' I (fun x => (f x)⁻¹) s x₀ := - hf.inv - -@[to_additive] -nonrec theorem SmoothAt.inv {f : M → G} {x₀ : M} (hf : SmoothAt I' I f x₀) : - SmoothAt I' I (fun x => (f x)⁻¹) x₀ := - hf.inv +@[deprecated (since := "2024-11-21")] alias SmoothWithinAt.inv := ContMDiffWithinAt.inv +@[deprecated (since := "2024-11-21")] alias SmoothAt.inv := ContMDiffAt.inv +@[deprecated (since := "2024-11-21")] alias SmoothOn.inv := ContMDiffOn.inv +@[deprecated (since := "2024-11-21")] alias Smooth.inv := ContMDiff.inv -@[to_additive] -nonrec theorem SmoothOn.inv {f : M → G} {s : Set M} (hf : SmoothOn I' I f s) : - SmoothOn I' I (fun x => (f x)⁻¹) s := - hf.inv - -@[to_additive] -nonrec theorem Smooth.inv {f : M → G} (hf : Smooth I' I f) : Smooth I' I fun x => (f x)⁻¹ := - hf.inv +@[deprecated (since := "2024-11-21")] alias SmoothWithinAt.neg := ContMDiffWithinAt.neg +@[deprecated (since := "2024-11-21")] alias SmoothAt.neg := ContMDiffAt.neg +@[deprecated (since := "2024-11-21")] alias SmoothOn.neg := ContMDiffOn.neg +@[deprecated (since := "2024-11-21")] alias Smooth.neg := ContMDiff.neg @[to_additive] theorem ContMDiffWithinAt.div {f g : M → G} {s : Set M} {x₀ : M} @@ -161,26 +155,15 @@ theorem ContMDiffOn.div {f g : M → G} {s : Set M} (hf : ContMDiffOn I' I n f s theorem ContMDiff.div {f g : M → G} (hf : ContMDiff I' I n f) (hg : ContMDiff I' I n g) : ContMDiff I' I n fun x => f x / g x := by simp_rw [div_eq_mul_inv]; exact hf.mul hg.inv -@[to_additive] -nonrec theorem SmoothWithinAt.div {f g : M → G} {s : Set M} {x₀ : M} - (hf : SmoothWithinAt I' I f s x₀) (hg : SmoothWithinAt I' I g s x₀) : - SmoothWithinAt I' I (fun x => f x / g x) s x₀ := - hf.div hg +@[deprecated (since := "2024-11-21")] alias SmoothWithinAt.div := ContMDiffWithinAt.div +@[deprecated (since := "2024-11-21")] alias SmoothAt.div := ContMDiffAt.div +@[deprecated (since := "2024-11-21")] alias SmoothOn.div := ContMDiffOn.div +@[deprecated (since := "2024-11-21")] alias Smooth.div := ContMDiff.div -@[to_additive] -nonrec theorem SmoothAt.div {f g : M → G} {x₀ : M} (hf : SmoothAt I' I f x₀) - (hg : SmoothAt I' I g x₀) : SmoothAt I' I (fun x => f x / g x) x₀ := - hf.div hg - -@[to_additive] -nonrec theorem SmoothOn.div {f g : M → G} {s : Set M} (hf : SmoothOn I' I f s) - (hg : SmoothOn I' I g s) : SmoothOn I' I (f / g) s := - hf.div hg - -@[to_additive] -nonrec theorem Smooth.div {f g : M → G} (hf : Smooth I' I f) (hg : Smooth I' I g) : - Smooth I' I (f / g) := - hf.div hg +@[deprecated (since := "2024-11-21")] alias SmoothWithinAt.sub := ContMDiffWithinAt.sub +@[deprecated (since := "2024-11-21")] alias SmoothAt.sub := ContMDiffAt.sub +@[deprecated (since := "2024-11-21")] alias SmoothOn.sub := ContMDiffOn.sub +@[deprecated (since := "2024-11-21")] alias Smooth.sub := ContMDiff.sub end PointwiseDivision @@ -195,7 +178,7 @@ instance {𝕜 : Type*} [NontriviallyNormedField 𝕜] {H : Type*} [TopologicalS [NormedAddCommGroup E'] [NormedSpace 𝕜 E'] {H' : Type*} [TopologicalSpace H'] {I' : ModelWithCorners 𝕜 E' H'} {G' : Type*} [TopologicalSpace G'] [ChartedSpace H' G'] [Group G'] [LieGroup I' G'] : LieGroup (I.prod I') (G × G') := - { SmoothMul.prod _ _ _ _ with smooth_inv := smooth_fst.inv.prod_mk smooth_snd.inv } + { SmoothMul.prod _ _ _ _ with smooth_inv := contMDiff_fst.inv.prod_mk contMDiff_snd.inv } end Product @@ -219,7 +202,7 @@ class SmoothInv₀ {𝕜 : Type*} [NontriviallyNormedField 𝕜] {H : Type*} [To {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] (I : ModelWithCorners 𝕜 E H) (G : Type*) [Inv G] [Zero G] [TopologicalSpace G] [ChartedSpace H G] : Prop where /-- Inversion is smooth away from `0`. -/ - smoothAt_inv₀ : ∀ ⦃x : G⦄, x ≠ 0 → SmoothAt I I (fun y ↦ y⁻¹) x + smoothAt_inv₀ : ∀ ⦃x : G⦄, x ≠ 0 → ContMDiffAt I I ⊤ (fun y ↦ y⁻¹) x instance {𝕜 : Type*} [NontriviallyNormedField 𝕜] [CompleteSpace 𝕜] : SmoothInv₀ 𝓘(𝕜) 𝕜 := { smoothAt_inv₀ := by @@ -235,28 +218,33 @@ variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {H : Type*} [TopologicalS {I' : ModelWithCorners 𝕜 E' H'} {M : Type*} [TopologicalSpace M] [ChartedSpace H' M] {n : ℕ∞} {f : M → G} -theorem smoothAt_inv₀ {x : G} (hx : x ≠ 0) : SmoothAt I I (fun y ↦ y⁻¹) x := +theorem contMDiffAt_inv₀ {x : G} (hx : x ≠ 0) : ContMDiffAt I I ⊤ (fun y ↦ y⁻¹) x := SmoothInv₀.smoothAt_inv₀ hx +@[deprecated (since := "2024-11-21")] alias smoothAt_inv₀ := contMDiffAt_inv₀ + include I in /-- In a manifold with smooth inverse away from `0`, the inverse is continuous away from `0`. This is not an instance for technical reasons, see note [Design choices about smooth algebraic structures]. -/ theorem hasContinuousInv₀_of_hasSmoothInv₀ : HasContinuousInv₀ G := - { continuousAt_inv₀ := fun _ hx ↦ (smoothAt_inv₀ I hx).continuousAt } + { continuousAt_inv₀ := fun _ hx ↦ (contMDiffAt_inv₀ I hx).continuousAt } -theorem SmoothOn_inv₀ : SmoothOn I I (Inv.inv : G → G) {0}ᶜ := fun _x hx => - (smoothAt_inv₀ I hx).smoothWithinAt +theorem contMDiffOn_inv₀ : ContMDiffOn I I ⊤ (Inv.inv : G → G) {0}ᶜ := fun _x hx => + (contMDiffAt_inv₀ I hx).contMDiffWithinAt + +@[deprecated (since := "2024-11-21")] alias smoothOn_inv₀ := contMDiffOn_inv₀ +@[deprecated (since := "2024-11-21")] alias SmoothOn_inv₀ := contMDiffOn_inv₀ variable {I} {s : Set M} {a : M} theorem ContMDiffWithinAt.inv₀ (hf : ContMDiffWithinAt I' I n f s a) (ha : f a ≠ 0) : ContMDiffWithinAt I' I n (fun x => (f x)⁻¹) s a := - (smoothAt_inv₀ I ha).contMDiffAt.comp_contMDiffWithinAt a hf + ((contMDiffAt_inv₀ I ha).of_le le_top).comp_contMDiffWithinAt a hf theorem ContMDiffAt.inv₀ (hf : ContMDiffAt I' I n f a) (ha : f a ≠ 0) : ContMDiffAt I' I n (fun x ↦ (f x)⁻¹) a := - (smoothAt_inv₀ I ha).contMDiffAt.comp a hf + ((contMDiffAt_inv₀ I ha).of_le le_top).comp a hf theorem ContMDiff.inv₀ (hf : ContMDiff I' I n f) (h0 : ∀ x, f x ≠ 0) : ContMDiff I' I n (fun x ↦ (f x)⁻¹) := @@ -266,20 +254,10 @@ theorem ContMDiffOn.inv₀ (hf : ContMDiffOn I' I n f s) (h0 : ∀ x ∈ s, f x ContMDiffOn I' I n (fun x => (f x)⁻¹) s := fun x hx ↦ ContMDiffWithinAt.inv₀ (hf x hx) (h0 x hx) -theorem SmoothWithinAt.inv₀ (hf : SmoothWithinAt I' I f s a) (ha : f a ≠ 0) : - SmoothWithinAt I' I (fun x => (f x)⁻¹) s a := - ContMDiffWithinAt.inv₀ hf ha - -theorem SmoothAt.inv₀ (hf : SmoothAt I' I f a) (ha : f a ≠ 0) : - SmoothAt I' I (fun x => (f x)⁻¹) a := - ContMDiffAt.inv₀ hf ha - -theorem Smooth.inv₀ (hf : Smooth I' I f) (h0 : ∀ x, f x ≠ 0) : Smooth I' I fun x => (f x)⁻¹ := - ContMDiff.inv₀ hf h0 - -theorem SmoothOn.inv₀ (hf : SmoothOn I' I f s) (h0 : ∀ x ∈ s, f x ≠ 0) : - SmoothOn I' I (fun x => (f x)⁻¹) s := - ContMDiffOn.inv₀ hf h0 +@[deprecated (since := "2024-11-21")] alias SmoothWithinAt.inv₀ := ContMDiffWithinAt.inv₀ +@[deprecated (since := "2024-11-21")] alias SmoothAt.inv₀ := ContMDiffAt.inv₀ +@[deprecated (since := "2024-11-21")] alias SmoothOn.inv₀ := ContMDiffOn.inv₀ +@[deprecated (since := "2024-11-21")] alias Smooth.inv₀ := ContMDiff.inv₀ end SmoothInv₀ @@ -313,20 +291,9 @@ theorem ContMDiffAt.div₀ (hf : ContMDiffAt I' I n f a) (hg : ContMDiffAt I' I theorem ContMDiff.div₀ (hf : ContMDiff I' I n f) (hg : ContMDiff I' I n g) (h₀ : ∀ x, g x ≠ 0) : ContMDiff I' I n (f / g) := by simpa only [div_eq_mul_inv] using hf.mul (hg.inv₀ h₀) -theorem SmoothWithinAt.div₀ (hf : SmoothWithinAt I' I f s a) - (hg : SmoothWithinAt I' I g s a) (h₀ : g a ≠ 0) : SmoothWithinAt I' I (f / g) s a := - ContMDiffWithinAt.div₀ hf hg h₀ - -theorem SmoothOn.div₀ (hf : SmoothOn I' I f s) (hg : SmoothOn I' I g s) (h₀ : ∀ x ∈ s, g x ≠ 0) : - SmoothOn I' I (f / g) s := - ContMDiffOn.div₀ hf hg h₀ - -theorem SmoothAt.div₀ (hf : SmoothAt I' I f a) (hg : SmoothAt I' I g a) (h₀ : g a ≠ 0) : - SmoothAt I' I (f / g) a := - ContMDiffAt.div₀ hf hg h₀ - -theorem Smooth.div₀ (hf : Smooth I' I f) (hg : Smooth I' I g) (h₀ : ∀ x, g x ≠ 0) : - Smooth I' I (f / g) := - ContMDiff.div₀ hf hg h₀ +@[deprecated (since := "2024-11-21")] alias SmoothWithinAt.div₀ := ContMDiffWithinAt.div₀ +@[deprecated (since := "2024-11-21")] alias SmoothAt.div₀ := ContMDiffAt.div₀ +@[deprecated (since := "2024-11-21")] alias SmoothOn.div₀ := ContMDiffOn.div₀ +@[deprecated (since := "2024-11-21")] alias Smooth.div₀ := ContMDiff.div₀ end Div diff --git a/Mathlib/Geometry/Manifold/Algebra/Monoid.lean b/Mathlib/Geometry/Manifold/Algebra/Monoid.lean index 5439b39e461ed..7e6a90b613a22 100644 --- a/Mathlib/Geometry/Manifold/Algebra/Monoid.lean +++ b/Mathlib/Geometry/Manifold/Algebra/Monoid.lean @@ -18,6 +18,9 @@ semigroups. open scoped Manifold +/- Next line is necessary while the manifold smoothness class is not extended to `ω`. +Later, replace with `open scoped ContDiff`. -/ +local notation "∞" => (⊤ : ℕ∞) library_note "Design choices about smooth algebraic structures"/-- 1. All smooth algebraic structures on `G` are `Prop`-valued classes that extend @@ -45,7 +48,7 @@ class SmoothAdd {𝕜 : Type*} [NontriviallyNormedField 𝕜] {H : Type*} [Topol {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] (I : ModelWithCorners 𝕜 E H) (G : Type*) [Add G] [TopologicalSpace G] [ChartedSpace H G] extends SmoothManifoldWithCorners I G : Prop where - smooth_add : Smooth (I.prod I) I fun p : G × G => p.1 + p.2 + smooth_add : ContMDiff (I.prod I) I ⊤ fun p : G × G => p.1 + p.2 -- See note [Design choices about smooth algebraic structures] /-- Basic hypothesis to talk about a smooth (Lie) monoid or a smooth semigroup. @@ -56,7 +59,7 @@ class SmoothMul {𝕜 : Type*} [NontriviallyNormedField 𝕜] {H : Type*} [Topol {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] (I : ModelWithCorners 𝕜 E H) (G : Type*) [Mul G] [TopologicalSpace G] [ChartedSpace H G] extends SmoothManifoldWithCorners I G : Prop where - smooth_mul : Smooth (I.prod I) I fun p : G × G => p.1 * p.2 + smooth_mul : ContMDiff (I.prod I) I ⊤ fun p : G × G => p.1 * p.2 section SmoothMul @@ -71,16 +74,19 @@ section variable (I) @[to_additive] -theorem smooth_mul : Smooth (I.prod I) I fun p : G × G => p.1 * p.2 := +theorem contMDiff_mul : ContMDiff (I.prod I) I ⊤ fun p : G × G => p.1 * p.2 := SmoothMul.smooth_mul +@[deprecated (since := "2024-11-20")] alias smooth_mul := contMDiff_mul +@[deprecated (since := "2024-11-20")] alias smooth_add := contMDiff_add + include I in /-- If the multiplication is smooth, then it is continuous. This is not an instance for technical reasons, see note [Design choices about smooth algebraic structures]. -/ @[to_additive "If the addition is smooth, then it is continuous. This is not an instance for technical reasons, see note [Design choices about smooth algebraic structures]."] theorem continuousMul_of_smooth : ContinuousMul G := - ⟨(smooth_mul I).continuous⟩ + ⟨(contMDiff_mul I).continuous⟩ end @@ -91,7 +97,7 @@ variable {f g : M → G} {s : Set M} {x : M} {n : ℕ∞} @[to_additive] theorem ContMDiffWithinAt.mul (hf : ContMDiffWithinAt I' I n f s x) (hg : ContMDiffWithinAt I' I n g s x) : ContMDiffWithinAt I' I n (f * g) s x := - ((smooth_mul I).smoothAt.of_le le_top).comp_contMDiffWithinAt x (hf.prod_mk hg) + ((contMDiff_mul I).contMDiffAt.of_le le_top).comp_contMDiffWithinAt x (hf.prod_mk hg) @[to_additive] nonrec theorem ContMDiffAt.mul (hf : ContMDiffAt I' I n f x) (hg : ContMDiffAt I' I n g x) : @@ -106,52 +112,51 @@ theorem ContMDiffOn.mul (hf : ContMDiffOn I' I n f s) (hg : ContMDiffOn I' I n g theorem ContMDiff.mul (hf : ContMDiff I' I n f) (hg : ContMDiff I' I n g) : ContMDiff I' I n (f * g) := fun x => (hf x).mul (hg x) -@[to_additive] -nonrec theorem SmoothWithinAt.mul (hf : SmoothWithinAt I' I f s x) - (hg : SmoothWithinAt I' I g s x) : SmoothWithinAt I' I (f * g) s x := - hf.mul hg - -@[to_additive] -nonrec theorem SmoothAt.mul (hf : SmoothAt I' I f x) (hg : SmoothAt I' I g x) : - SmoothAt I' I (f * g) x := - hf.mul hg +@[deprecated (since := "2024-11-21")] alias SmoothWithinAt.mul := ContMDiffWithinAt.mul +@[deprecated (since := "2024-11-21")] alias SmoothAt.mul := ContMDiffAt.mul +@[deprecated (since := "2024-11-21")] alias SmoothOn.mul := ContMDiffOn.mul +@[deprecated (since := "2024-11-21")] alias Smooth.mul := ContMDiff.mul -@[to_additive] -nonrec theorem SmoothOn.mul (hf : SmoothOn I' I f s) (hg : SmoothOn I' I g s) : - SmoothOn I' I (f * g) s := - hf.mul hg +@[deprecated (since := "2024-11-21")] alias SmoothWithinAt.add := ContMDiffWithinAt.add +@[deprecated (since := "2024-11-21")] alias SmoothAt.add := ContMDiffAt.add +@[deprecated (since := "2024-11-21")] alias SmoothOn.add := ContMDiffOn.add +@[deprecated (since := "2024-11-21")] alias Smooth.add := ContMDiff.add @[to_additive] -nonrec theorem Smooth.mul (hf : Smooth I' I f) (hg : Smooth I' I g) : Smooth I' I (f * g) := - hf.mul hg +theorem contMDiff_mul_left {a : G} : ContMDiff I I n (a * ·) := + contMDiff_const.mul contMDiff_id -@[to_additive] -theorem smooth_mul_left {a : G} : Smooth I I fun b : G => a * b := - smooth_const.mul smooth_id +@[deprecated (since := "2024-11-21")] alias smooth_mul_left := contMDiff_mul_left +@[deprecated (since := "2024-11-21")] alias smooth_add_left := contMDiff_add_left @[to_additive] -theorem smooth_mul_right {a : G} : Smooth I I fun b : G => b * a := - smooth_id.mul smooth_const - -theorem contMDiff_mul_left {a : G} : ContMDiff I I n (a * ·) := smooth_mul_left.contMDiff - theorem contMDiffAt_mul_left {a b : G} : ContMDiffAt I I n (a * ·) b := contMDiff_mul_left.contMDiffAt +@[to_additive] theorem mdifferentiable_mul_left {a : G} : MDifferentiable I I (a * ·) := contMDiff_mul_left.mdifferentiable le_rfl +@[to_additive] theorem mdifferentiableAt_mul_left {a b : G} : MDifferentiableAt I I (a * ·) b := contMDiffAt_mul_left.mdifferentiableAt le_rfl -theorem contMDiff_mul_right {a : G} : ContMDiff I I n (· * a) := smooth_mul_right.contMDiff +@[to_additive] +theorem contMDiff_mul_right {a : G} : ContMDiff I I n (· * a) := + contMDiff_id.mul contMDiff_const + +@[deprecated (since := "2024-11-21")] alias smooth_mul_right := contMDiff_mul_right +@[deprecated (since := "2024-11-21")] alias smooth_add_right := contMDiff_add_right +@[to_additive] theorem contMDiffAt_mul_right {a b : G} : ContMDiffAt I I n (· * a) b := contMDiff_mul_right.contMDiffAt +@[to_additive] theorem mdifferentiable_mul_right {a : G} : MDifferentiable I I (· * a) := contMDiff_mul_right.mdifferentiable le_rfl +@[to_additive] theorem mdifferentiableAt_mul_right {a b : G} : MDifferentiableAt I I (· * a) b := contMDiffAt_mul_right.mdifferentiableAt le_rfl @@ -163,13 +168,13 @@ variable (I) (g h : G) Lemmas involving `smoothLeftMul` with the notation `𝑳` usually use `L` instead of `𝑳` in the names. -/ def smoothLeftMul : C^∞⟮I, G; I, G⟯ := - ⟨leftMul g, smooth_mul_left⟩ + ⟨leftMul g, contMDiff_mul_left⟩ /-- Right multiplication by `g`. It is meant to mimic the usual notation in Lie groups. Lemmas involving `smoothRightMul` with the notation `𝑹` usually use `R` instead of `𝑹` in the names. -/ def smoothRightMul : C^∞⟮I, G; I, G⟯ := - ⟨rightMul g, smooth_mul_right⟩ + ⟨rightMul g, contMDiff_mul_right⟩ -- Left multiplication. The abbreviation is `MIL`. scoped[LieGroup] notation "𝑳" => smoothLeftMul @@ -222,8 +227,8 @@ instance SmoothMul.prod {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type* [ChartedSpace H' G'] [Mul G'] [SmoothMul I' G'] : SmoothMul (I.prod I') (G × G') := { SmoothManifoldWithCorners.prod G G' with smooth_mul := - ((smooth_fst.comp smooth_fst).smooth.mul (smooth_fst.comp smooth_snd)).prod_mk - ((smooth_snd.comp smooth_fst).smooth.mul (smooth_snd.comp smooth_snd)) } + ((contMDiff_fst.comp contMDiff_fst).mul (contMDiff_fst.comp contMDiff_snd)).prod_mk + ((contMDiff_snd.comp contMDiff_fst).mul (contMDiff_snd.comp contMDiff_snd)) } end SmoothMul @@ -236,16 +241,19 @@ variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {H : Type*} [TopologicalS {G' : Type*} [Monoid G'] [TopologicalSpace G'] [ChartedSpace H' G'] [SmoothMul I' G'] @[to_additive] -theorem smooth_pow : ∀ n : ℕ, Smooth I I fun a : G => a ^ n - | 0 => by simp only [pow_zero]; exact smooth_const - | k + 1 => by simpa [pow_succ] using (smooth_pow _).mul smooth_id +theorem contMDiff_pow : ∀ n : ℕ, ContMDiff I I ⊤ fun a : G => a ^ n + | 0 => by simp only [pow_zero]; exact contMDiff_const + | k + 1 => by simpa [pow_succ] using (contMDiff_pow _).mul contMDiff_id + +@[deprecated (since := "2024-11-21")] alias smooth_pow := contMDiff_pow +@[deprecated (since := "2024-11-21")] alias smooth_nsmul := contMDiff_nsmul /-- Morphism of additive smooth monoids. -/ structure SmoothAddMonoidMorphism (I : ModelWithCorners 𝕜 E H) (I' : ModelWithCorners 𝕜 E' H') (G : Type*) [TopologicalSpace G] [ChartedSpace H G] [AddMonoid G] [SmoothAdd I G] (G' : Type*) [TopologicalSpace G'] [ChartedSpace H' G'] [AddMonoid G'] [SmoothAdd I' G'] extends G →+ G' where - smooth_toFun : Smooth I I' toFun + smooth_toFun : ContMDiff I I' ⊤ toFun /-- Morphism of smooth monoids. -/ @[to_additive] @@ -253,11 +261,11 @@ structure SmoothMonoidMorphism (I : ModelWithCorners 𝕜 E H) (I' : ModelWithCo (G : Type*) [TopologicalSpace G] [ChartedSpace H G] [Monoid G] [SmoothMul I G] (G' : Type*) [TopologicalSpace G'] [ChartedSpace H' G'] [Monoid G'] [SmoothMul I' G'] extends G →* G' where - smooth_toFun : Smooth I I' toFun + smooth_toFun : ContMDiff I I' ⊤ toFun @[to_additive] instance : One (SmoothMonoidMorphism I I' G G') := - ⟨{ smooth_toFun := smooth_const + ⟨{ smooth_toFun := contMDiff_const toMonoidHom := 1 }⟩ @[to_additive] @@ -389,61 +397,43 @@ theorem contMDiff_finprod_cond (hc : ∀ i, p i → ContMDiff I' I n (f i)) simp only [← finprod_subtype_eq_finprod_cond] exact contMDiff_finprod (fun i => hc i i.2) (hf.comp_injective Subtype.coe_injective) -@[to_additive] -theorem smoothAt_finprod - (lf : LocallyFinite fun i ↦ mulSupport <| f i) (h : ∀ i, SmoothAt I' I (f i) x₀) : - SmoothAt I' I (fun x ↦ ∏ᶠ i, f i x) x₀ := - contMDiffWithinAt_finprod lf h +@[deprecated (since := "2024-11-21")] alias smoothAt_finprod := contMDiffAt_finprod +@[deprecated (since := "2024-11-21")] alias smoothAt_finsum := contMDiffAt_finsum -@[to_additive] -theorem smoothWithinAt_finset_prod' (h : ∀ i ∈ t, SmoothWithinAt I' I (f i) s x) : - SmoothWithinAt I' I (∏ i ∈ t, f i) s x := - contMDiffWithinAt_finset_prod' h +@[deprecated (since := "2024-11-21")] +alias smoothWithinAt_finset_prod' := contMDiffWithinAt_finset_prod' +@[deprecated (since := "2024-11-21")] +alias smoothWithinAt_finset_sum' := contMDiffWithinAt_finset_sum' -@[to_additive] -theorem smoothWithinAt_finset_prod (h : ∀ i ∈ t, SmoothWithinAt I' I (f i) s x) : - SmoothWithinAt I' I (fun x => ∏ i ∈ t, f i x) s x := - contMDiffWithinAt_finset_prod h -@[to_additive] -theorem smoothAt_finset_prod' (h : ∀ i ∈ t, SmoothAt I' I (f i) x) : - SmoothAt I' I (∏ i ∈ t, f i) x := - contMDiffAt_finset_prod' h +@[deprecated (since := "2024-11-21")] +alias smoothWithinAt_finset_prod := contMDiffWithinAt_finset_prod +@[deprecated (since := "2024-11-21")] +alias smoothWithinAt_finset_sum := contMDiffWithinAt_finset_sum -@[to_additive] -theorem smoothAt_finset_prod (h : ∀ i ∈ t, SmoothAt I' I (f i) x) : - SmoothAt I' I (fun x => ∏ i ∈ t, f i x) x := - contMDiffAt_finset_prod h +@[deprecated (since := "2024-11-21")] alias smoothAt_finset_prod' := contMDiffAt_finset_prod' +@[deprecated (since := "2024-11-21")] alias smoothAt_finset_sum' := contMDiffAt_finset_sum' -@[to_additive] -theorem smoothOn_finset_prod' (h : ∀ i ∈ t, SmoothOn I' I (f i) s) : - SmoothOn I' I (∏ i ∈ t, f i) s := - contMDiffOn_finset_prod' h +@[deprecated (since := "2024-11-21")] alias smoothAt_finset_prod := contMDiffAt_finset_prod +@[deprecated (since := "2024-11-21")] alias smoothAt_finset_sum := contMDiffAt_finset_sum -@[to_additive] -theorem smoothOn_finset_prod (h : ∀ i ∈ t, SmoothOn I' I (f i) s) : - SmoothOn I' I (fun x => ∏ i ∈ t, f i x) s := - contMDiffOn_finset_prod h +@[deprecated (since := "2024-11-21")] alias smoothOn_finset_prod' := contMDiffOn_finset_prod' +@[deprecated (since := "2024-11-21")] alias smoothOn_finset_sum' := contMDiffOn_finset_sum' -@[to_additive] -theorem smooth_finset_prod' (h : ∀ i ∈ t, Smooth I' I (f i)) : Smooth I' I (∏ i ∈ t, f i) := - contMDiff_finset_prod' h +@[deprecated (since := "2024-11-21")] alias smoothOn_finset_prod := contMDiffOn_finset_prod +@[deprecated (since := "2024-11-21")] alias smoothOn_finset_sum := contMDiffOn_finset_sum -@[to_additive] -theorem smooth_finset_prod (h : ∀ i ∈ t, Smooth I' I (f i)) : - Smooth I' I fun x => ∏ i ∈ t, f i x := - contMDiff_finset_prod h +@[deprecated (since := "2024-11-21")] alias smooth_finset_prod' := contMDiffOn_finset_prod' +@[deprecated (since := "2024-11-21")] alias smooth_finset_sum' := contMDiffOn_finset_sum' -@[to_additive] -theorem smooth_finprod (h : ∀ i, Smooth I' I (f i)) - (hfin : LocallyFinite fun i => mulSupport (f i)) : Smooth I' I fun x => ∏ᶠ i, f i x := - contMDiff_finprod h hfin +@[deprecated (since := "2024-11-21")] alias smooth_finset_prod := contMDiff_finset_prod +@[deprecated (since := "2024-11-21")] alias smooth_finset_sum := contMDiff_finset_sum -@[to_additive] -theorem smooth_finprod_cond (hc : ∀ i, p i → Smooth I' I (f i)) - (hf : LocallyFinite fun i => mulSupport (f i)) : - Smooth I' I fun x => ∏ᶠ (i) (_ : p i), f i x := - contMDiff_finprod_cond hc hf +@[deprecated (since := "2024-11-21")] alias smooth_finprod := contMDiff_finprod +@[deprecated (since := "2024-11-21")] alias smooth_finsum := contMDiff_finsum + +@[deprecated (since := "2024-11-21")] alias smooth_finprod_cond := contMDiff_finprod_cond +@[deprecated (since := "2024-11-21")] alias smooth_finsum_cond := contMDiff_finsum_cond end CommMonoid @@ -488,23 +478,9 @@ theorem ContMDiffOn.div_const (hf : ContMDiffOn I' I n f s) : theorem ContMDiff.div_const (hf : ContMDiff I' I n f) : ContMDiff I' I n (fun x ↦ f x / c) := fun x => (hf x).div_const c -@[to_additive] -nonrec theorem SmoothWithinAt.div_const (hf : SmoothWithinAt I' I f s x) : - SmoothWithinAt I' I (fun x ↦ f x / c) s x := - hf.div_const c - -@[to_additive] -nonrec theorem SmoothAt.div_const (hf : SmoothAt I' I f x) : - SmoothAt I' I (fun x ↦ f x / c) x := - hf.div_const c - -@[to_additive] -nonrec theorem SmoothOn.div_const (hf : SmoothOn I' I f s) : - SmoothOn I' I (fun x ↦ f x / c) s := - hf.div_const c - -@[to_additive] -nonrec theorem Smooth.div_const (hf : Smooth I' I f) : Smooth I' I (fun x ↦ f x / c) := - hf.div_const c +@[deprecated (since := "2024-11-21")] alias SmoothWithinAt.div_const := ContMDiffWithinAt.div_const +@[deprecated (since := "2024-11-21")] alias SmoothAt.div_const := ContMDiffAt.div_const +@[deprecated (since := "2024-11-21")] alias SmoothOn.div_const := ContMDiffOn.div_const +@[deprecated (since := "2024-11-21")] alias Smooth.div_const := ContMDiff.div_const end DivConst diff --git a/Mathlib/Geometry/Manifold/Algebra/SmoothFunctions.lean b/Mathlib/Geometry/Manifold/Algebra/SmoothFunctions.lean index 002ad1cf560cf..db675c91210d4 100644 --- a/Mathlib/Geometry/Manifold/Algebra/SmoothFunctions.lean +++ b/Mathlib/Geometry/Manifold/Algebra/SmoothFunctions.lean @@ -15,6 +15,9 @@ In this file, we define instances of algebraic structures over smooth functions. noncomputable section open scoped Manifold +/- Next line is necessary while the manifold smoothness class is not extended to `ω`. +Later, replace with `open scoped ContDiff`. -/ +local notation "∞" => (⊤ : ℕ∞) open TopologicalSpace @@ -30,7 +33,7 @@ namespace SmoothMap @[to_additive] protected instance instMul {G : Type*} [Mul G] [TopologicalSpace G] [ChartedSpace H' G] [SmoothMul I' G] : Mul C^∞⟮I, N; I', G⟯ := - ⟨fun f g => ⟨f * g, f.smooth.mul g.smooth⟩⟩ + ⟨fun f g => ⟨f * g, f.contMDiff.mul g.contMDiff⟩⟩ @[to_additive (attr := simp)] theorem coe_mul {G : Type*} [Mul G] [TopologicalSpace G] [ChartedSpace H' G] [SmoothMul I' G] @@ -54,12 +57,12 @@ theorem coe_one {G : Type*} [One G] [TopologicalSpace G] [ChartedSpace H' G] : instance instNSMul {G : Type*} [AddMonoid G] [TopologicalSpace G] [ChartedSpace H' G] [SmoothAdd I' G] : SMul ℕ C^∞⟮I, N; I', G⟯ where - smul n f := ⟨n • (f : N → G), (smooth_nsmul n).comp f.smooth⟩ + smul n f := ⟨n • (f : N → G), (contMDiff_nsmul n).comp f.contMDiff⟩ @[to_additive existing] instance instPow {G : Type*} [Monoid G] [TopologicalSpace G] [ChartedSpace H' G] [SmoothMul I' G] : Pow C^∞⟮I, N; I', G⟯ ℕ where - pow f n := ⟨(f : N → G) ^ n, (smooth_pow n).comp f.smooth⟩ + pow f n := ⟨(f : N → G) ^ n, (contMDiff_pow n).comp f.contMDiff⟩ @[to_additive (attr := simp)] theorem coe_pow {G : Type*} [Monoid G] [TopologicalSpace G] [ChartedSpace H' G] [SmoothMul I' G] @@ -104,9 +107,9 @@ variable (I N) `C^∞⟮I, N; I'', G''⟯`."] def compLeftMonoidHom {G' : Type*} [Monoid G'] [TopologicalSpace G'] [ChartedSpace H' G'] [SmoothMul I' G'] {G'' : Type*} [Monoid G''] [TopologicalSpace G''] [ChartedSpace H'' G''] - [SmoothMul I'' G''] (φ : G' →* G'') (hφ : Smooth I' I'' φ) : + [SmoothMul I'' G''] (φ : G' →* G'') (hφ : ContMDiff I' I'' ⊤ φ) : C^∞⟮I, N; I', G'⟯ →* C^∞⟮I, N; I'', G''⟯ where - toFun f := ⟨φ ∘ f, fun x => (hφ.smooth _).comp x (f.contMDiff x)⟩ + toFun f := ⟨φ ∘ f, hφ.comp f.contMDiff⟩ map_one' := by ext; show φ 1 = 1; simp map_mul' f g := by ext x; show φ (f x * g x) = φ (f x) * φ (g x); simp @@ -119,7 +122,7 @@ variable (I') {N} homomorphism from `C^∞⟮I, V; I', G⟯` to `C^∞⟮I, U; I', G⟯`."] def restrictMonoidHom (G : Type*) [Monoid G] [TopologicalSpace G] [ChartedSpace H' G] [SmoothMul I' G] {U V : Opens N} (h : U ≤ V) : C^∞⟮I, V; I', G⟯ →* C^∞⟮I, U; I', G⟯ where - toFun f := ⟨f ∘ Set.inclusion h, f.smooth.comp (smooth_inclusion h)⟩ + toFun f := ⟨f ∘ Set.inclusion h, f.contMDiff.comp (contMDiff_inclusion h)⟩ map_one' := rfl map_mul' _ _ := rfl @@ -134,9 +137,9 @@ instance commMonoid {G : Type*} [CommMonoid G] [TopologicalSpace G] [ChartedSpac instance group {G : Type*} [Group G] [TopologicalSpace G] [ChartedSpace H' G] [LieGroup I' G] : Group C^∞⟮I, N; I', G⟯ := { SmoothMap.monoid with - inv := fun f => ⟨fun x => (f x)⁻¹, f.smooth.inv⟩ + inv := fun f => ⟨fun x => (f x)⁻¹, f.contMDiff.inv⟩ inv_mul_cancel := fun a => by ext; exact inv_mul_cancel _ - div := fun f g => ⟨f / g, f.smooth.div g.smooth⟩ + div := fun f g => ⟨f / g, f.contMDiff.div g.contMDiff⟩ div_eq_mul_inv := fun f g => by ext; exact div_eq_mul_inv _ _ } @[to_additive (attr := simp)] @@ -189,11 +192,11 @@ variable (I N) 'left-composition-by-`φ`' ring homomorphism from `C^∞⟮I, N; I', R'⟯` to `C^∞⟮I, N; I'', R''⟯`. -/ def compLeftRingHom {R' : Type*} [Ring R'] [TopologicalSpace R'] [ChartedSpace H' R'] [SmoothRing I' R'] {R'' : Type*} [Ring R''] [TopologicalSpace R''] [ChartedSpace H'' R''] - [SmoothRing I'' R''] (φ : R' →+* R'') (hφ : Smooth I' I'' φ) : + [SmoothRing I'' R''] (φ : R' →+* R'') (hφ : ContMDiff I' I'' ⊤ φ) : C^∞⟮I, N; I', R'⟯ →+* C^∞⟮I, N; I'', R''⟯ := { SmoothMap.compLeftMonoidHom I N φ.toMonoidHom hφ, SmoothMap.compLeftAddMonoidHom I N φ.toAddMonoidHom hφ with - toFun := fun f => ⟨φ ∘ f, fun x => (hφ.smooth _).comp x (f.contMDiff x)⟩ } + toFun := fun f => ⟨φ ∘ f, hφ.comp f.contMDiff⟩ } variable (I') {N} @@ -202,7 +205,7 @@ variable (I') {N} def restrictRingHom (R : Type*) [Ring R] [TopologicalSpace R] [ChartedSpace H' R] [SmoothRing I' R] {U V : Opens N} (h : U ≤ V) : C^∞⟮I, V; I', R⟯ →+* C^∞⟮I, U; I', R⟯ := { SmoothMap.restrictMonoidHom I I' R h, SmoothMap.restrictAddMonoidHom I I' R h with - toFun := fun f => ⟨f ∘ Set.inclusion h, f.smooth.comp (smooth_inclusion h)⟩ } + toFun := fun f => ⟨f ∘ Set.inclusion h, f.contMDiff.comp (contMDiff_inclusion h)⟩ } variable {I I'} @@ -232,7 +235,7 @@ field `𝕜` inherit a vector space structure. instance instSMul {V : Type*} [NormedAddCommGroup V] [NormedSpace 𝕜 V] : SMul 𝕜 C^∞⟮I, N; 𝓘(𝕜, V), V⟯ := - ⟨fun r f => ⟨r • ⇑f, smooth_const.smul f.smooth⟩⟩ + ⟨fun r f => ⟨r • ⇑f, contMDiff_const.smul f.contMDiff⟩⟩ @[simp] theorem coe_smul {V : Type*} [NormedAddCommGroup V] [NormedSpace 𝕜 V] (r : 𝕜) @@ -272,7 +275,7 @@ variable {A : Type*} [NormedRing A] [NormedAlgebra 𝕜 A] [SmoothRing 𝓘(𝕜 /-- Smooth constant functions as a `RingHom`. -/ def C : 𝕜 →+* C^∞⟮I, N; 𝓘(𝕜, A), A⟯ where - toFun := fun c : 𝕜 => ⟨fun _ => (algebraMap 𝕜 A) c, smooth_const⟩ + toFun := fun c : 𝕜 => ⟨fun _ => (algebraMap 𝕜 A) c, contMDiff_const⟩ map_one' := by ext; exact (algebraMap 𝕜 A).map_one map_mul' c₁ c₂ := by ext; exact (algebraMap 𝕜 A).map_mul _ _ map_zero' := by ext; exact (algebraMap 𝕜 A).map_zero @@ -280,7 +283,7 @@ def C : 𝕜 →+* C^∞⟮I, N; 𝓘(𝕜, A), A⟯ where instance algebra : Algebra 𝕜 C^∞⟮I, N; 𝓘(𝕜, A), A⟯ := { --SmoothMap.semiring with -- Porting note: Commented this out. - smul := fun r f => ⟨r • f, smooth_const.smul f.smooth⟩ + smul := fun r f => ⟨r • f, contMDiff_const.smul f.contMDiff⟩ toRingHom := SmoothMap.C commutes' := fun c f => by ext x; exact Algebra.commutes' _ _ smul_def' := fun c f => by ext x; exact Algebra.smul_def' _ _ } @@ -309,7 +312,7 @@ is naturally a vector space over the ring of smooth functions from `N` to `𝕜` instance instSMul' {V : Type*} [NormedAddCommGroup V] [NormedSpace 𝕜 V] : SMul C^∞⟮I, N; 𝕜⟯ C^∞⟮I, N; 𝓘(𝕜, V), V⟯ := - ⟨fun f g => ⟨fun x => f x • g x, Smooth.smul f.2 g.2⟩⟩ + ⟨fun f g => ⟨fun x => f x • g x, ContMDiff.smul f.2 g.2⟩⟩ @[simp] theorem smul_comp' {V : Type*} [NormedAddCommGroup V] [NormedSpace 𝕜 V] (f : C^∞⟮I'', N'; 𝕜⟯) diff --git a/Mathlib/Geometry/Manifold/Algebra/Structures.lean b/Mathlib/Geometry/Manifold/Algebra/Structures.lean index 11c9d9b1a863a..a20f6b529acf8 100644 --- a/Mathlib/Geometry/Manifold/Algebra/Structures.lean +++ b/Mathlib/Geometry/Manifold/Algebra/Structures.lean @@ -12,7 +12,7 @@ In this file we define smooth structures that build on Lie groups. We prefer usi instead of Lie mainly because Lie ring has currently another use in mathematics. -/ -open scoped Manifold +open scoped Manifold ContDiff section SmoothRing @@ -24,7 +24,7 @@ variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {H : Type*} [TopologicalS If `R` is a ring, then negation is automatically smooth, as it is multiplication with `-1`. -/ class SmoothRing (I : ModelWithCorners 𝕜 E H) (R : Type*) [Semiring R] [TopologicalSpace R] [ChartedSpace H R] extends SmoothAdd I R : Prop where - smooth_mul : Smooth (I.prod I) I fun p : R × R => p.1 * p.2 + smooth_mul : ContMDiff (I.prod I) I ⊤ fun p : R × R => p.1 * p.2 -- see Note [lower instance priority] instance (priority := 100) SmoothRing.toSmoothMul (I : ModelWithCorners 𝕜 E H) (R : Type*) @@ -35,9 +35,9 @@ instance (priority := 100) SmoothRing.toSmoothMul (I : ModelWithCorners 𝕜 E H -- see Note [lower instance priority] instance (priority := 100) SmoothRing.toLieAddGroup (I : ModelWithCorners 𝕜 E H) (R : Type*) [Ring R] [TopologicalSpace R] [ChartedSpace H R] [SmoothRing I R] : LieAddGroup I R where - compatible := StructureGroupoid.compatible (contDiffGroupoid ⊤ I) - smooth_add := smooth_add I - smooth_neg := by simpa only [neg_one_mul] using @smooth_mul_left 𝕜 _ H _ E _ _ I R _ _ _ _ (-1) + compatible := StructureGroupoid.compatible (contDiffGroupoid ∞ I) + smooth_add := contMDiff_add I + smooth_neg := by simpa only [neg_one_mul] using contMDiff_mul_left (G := R) (a := -1) end SmoothRing @@ -46,7 +46,7 @@ instance (priority := 100) fieldSmoothRing {𝕜 : Type*} [NontriviallyNormedFie SmoothRing 𝓘(𝕜) 𝕜 := { normedSpaceLieAddGroup with smooth_mul := by - rw [smooth_iff] + rw [contMDiff_iff] refine ⟨continuous_mul, fun x y => ?_⟩ simp only [mfld_simps] rw [contDiffOn_univ] diff --git a/Mathlib/Geometry/Manifold/BumpFunction.lean b/Mathlib/Geometry/Manifold/BumpFunction.lean index fa6698b53773a..0c37faf328e8a 100644 --- a/Mathlib/Geometry/Manifold/BumpFunction.lean +++ b/Mathlib/Geometry/Manifold/BumpFunction.lean @@ -286,23 +286,28 @@ theorem nhds_basis_support {s : Set M} (hs : s ∈ 𝓝 c) : variable [SmoothManifoldWithCorners I M] /-- A smooth bump function is infinitely smooth. -/ -protected theorem smooth : Smooth I 𝓘(ℝ) f := by +protected theorem contMDiff : ContMDiff I 𝓘(ℝ) ⊤ f := by refine contMDiff_of_tsupport fun x hx => ?_ have : x ∈ (chartAt H c).source := f.tsupport_subset_chartAt_source hx refine ContMDiffAt.congr_of_eventuallyEq ?_ <| f.eqOn_source.eventuallyEq_of_mem <| (chartAt H c).open_source.mem_nhds this exact f.contDiffAt.contMDiffAt.comp _ (contMDiffAt_extChartAt' this) -protected theorem smoothAt {x} : SmoothAt I 𝓘(ℝ) f x := - f.smooth.smoothAt +@[deprecated (since := "2024-11-20")] alias smooth := SmoothBumpFunction.contMDiff + +protected theorem contMDiffAt {x} : ContMDiffAt I 𝓘(ℝ) ⊤ f x := + f.contMDiff.contMDiffAt + +@[deprecated (since := "2024-11-20")] alias smoothAt := SmoothBumpFunction.contMDiffAt protected theorem continuous : Continuous f := - f.smooth.continuous + f.contMDiff.continuous /-- If `f : SmoothBumpFunction I c` is a smooth bump function and `g : M → G` is a function smooth on the source of the chart at `c`, then `f • g` is smooth on the whole manifold. -/ -theorem smooth_smul {G} [NormedAddCommGroup G] [NormedSpace ℝ G] {g : M → G} - (hg : SmoothOn I 𝓘(ℝ, G) g (chartAt H c).source) : Smooth I 𝓘(ℝ, G) fun x => f x • g x := by +theorem contMDiff_smul {G} [NormedAddCommGroup G] [NormedSpace ℝ G] {g : M → G} + (hg : ContMDiffOn I 𝓘(ℝ, G) ⊤ g (chartAt H c).source) : + ContMDiff I 𝓘(ℝ, G) ⊤ fun x => f x • g x := by refine contMDiff_of_tsupport fun x hx => ?_ have : x ∈ (chartAt H c).source := -- Porting note: was a more readable `calc` @@ -311,6 +316,8 @@ theorem smooth_smul {G} [NormedAddCommGroup G] [NormedSpace ℝ G] {g : M → G} -- _ ⊆ tsupport f := tsupport_smul_subset_left _ _ -- _ ⊆ (chart_at _ c).source := f.tsupport_subset_chartAt_source f.tsupport_subset_chartAt_source <| tsupport_smul_subset_left _ _ hx - exact f.smoothAt.smul ((hg _ this).contMDiffAt <| (chartAt _ _).open_source.mem_nhds this) + exact f.contMDiffAt.smul ((hg _ this).contMDiffAt <| (chartAt _ _).open_source.mem_nhds this) + +@[deprecated (since := "2024-11-20")] alias smooth_smul := contMDiff_smul end SmoothBumpFunction diff --git a/Mathlib/Geometry/Manifold/ContMDiff/Atlas.lean b/Mathlib/Geometry/Manifold/ContMDiff/Atlas.lean index 5f68ad7682a06..31ff5e240b2d7 100644 --- a/Mathlib/Geometry/Manifold/ContMDiff/Atlas.lean +++ b/Mathlib/Geometry/Manifold/ContMDiff/Atlas.lean @@ -13,7 +13,7 @@ and that local structomorphisms are smooth with smooth inverses. -/ open Set ChartedSpace SmoothManifoldWithCorners -open scoped Manifold +open scoped Manifold ContDiff variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] -- declare a smooth manifold `M` over the pair `(E, H)`. @@ -46,18 +46,14 @@ theorem contMDiffOn_model_symm : ContMDiffOn 𝓘(𝕜, E) I n I.symm (range I) /-- An atlas member is `C^n` for any `n`. -/ theorem contMDiffOn_of_mem_maximalAtlas (h : e ∈ maximalAtlas I M) : ContMDiffOn I I n e e.source := - ContMDiffOn.of_le - ((contDiffWithinAt_localInvariantProp ∞).liftPropOn_of_mem_maximalAtlas - contDiffWithinAtProp_id h) - le_top + ContMDiffOn.of_le ((contDiffWithinAt_localInvariantProp ⊤).liftPropOn_of_mem_maximalAtlas + contDiffWithinAtProp_id h) le_top /-- The inverse of an atlas member is `C^n` for any `n`. -/ theorem contMDiffOn_symm_of_mem_maximalAtlas (h : e ∈ maximalAtlas I M) : ContMDiffOn I I n e.symm e.target := - ContMDiffOn.of_le - ((contDiffWithinAt_localInvariantProp ∞).liftPropOn_symm_of_mem_maximalAtlas - contDiffWithinAtProp_id h) - le_top + ContMDiffOn.of_le ((contDiffWithinAt_localInvariantProp ⊤).liftPropOn_symm_of_mem_maximalAtlas + contDiffWithinAtProp_id h) le_top theorem contMDiffAt_of_mem_maximalAtlas (h : e ∈ maximalAtlas I M) (hx : x ∈ e.source) : ContMDiffAt I I n e x := @@ -112,7 +108,7 @@ theorem contMDiffWithinAt_extChartAt_symm_range /-- An element of `contDiffGroupoid ⊤ I` is `C^n` for any `n`. -/ theorem contMDiffOn_of_mem_contDiffGroupoid {e' : PartialHomeomorph H H} - (h : e' ∈ contDiffGroupoid ⊤ I) : ContMDiffOn I I n e' e'.source := + (h : e' ∈ contDiffGroupoid ∞ I) : ContMDiffOn I I n e' e'.source := (contDiffWithinAt_localInvariantProp n).liftPropOn_of_mem_groupoid contDiffWithinAtProp_id h end Atlas @@ -124,8 +120,8 @@ section IsLocalStructomorph variable [ChartedSpace H M'] [IsM' : SmoothManifoldWithCorners I M'] theorem isLocalStructomorphOn_contDiffGroupoid_iff_aux {f : PartialHomeomorph M M'} - (hf : LiftPropOn (contDiffGroupoid ⊤ I).IsLocalStructomorphWithinAt f f.source) : - SmoothOn I I f f.source := by + (hf : LiftPropOn (contDiffGroupoid ∞ I).IsLocalStructomorphWithinAt f f.source) : + ContMDiffOn I I ⊤ f f.source := by -- It suffices to show smoothness near each `x` apply contMDiffOn_of_locally_contMDiffOn intro x hx @@ -170,8 +166,8 @@ theorem isLocalStructomorphOn_contDiffGroupoid_iff_aux {f : PartialHomeomorph M is a local structomorphism for `I`, if and only if it is manifold-smooth on the domain of definition in both directions. -/ theorem isLocalStructomorphOn_contDiffGroupoid_iff (f : PartialHomeomorph M M') : - LiftPropOn (contDiffGroupoid ⊤ I).IsLocalStructomorphWithinAt f f.source ↔ - SmoothOn I I f f.source ∧ SmoothOn I I f.symm f.target := by + LiftPropOn (contDiffGroupoid ∞ I).IsLocalStructomorphWithinAt f f.source ↔ + ContMDiffOn I I ⊤ f f.source ∧ ContMDiffOn I I ⊤ f.symm f.target := by constructor · intro h refine ⟨isLocalStructomorphOn_contDiffGroupoid_iff_aux h, @@ -186,7 +182,7 @@ theorem isLocalStructomorphOn_contDiffGroupoid_iff (f : PartialHomeomorph M M') refine ⟨(f.symm.continuousAt hX).continuousWithinAt, fun h2x => ?_⟩ obtain ⟨e, he, h2e, hef, hex⟩ : ∃ e : PartialHomeomorph H H, - e ∈ contDiffGroupoid ⊤ I ∧ + e ∈ contDiffGroupoid ∞ I ∧ e.source ⊆ (c.symm ≫ₕ f ≫ₕ c').source ∧ EqOn (c' ∘ f ∘ c.symm) e e.source ∧ c x ∈ e.source := by have h1 : c' = chartAt H (f x) := by simp only [f.right_inv hX] diff --git a/Mathlib/Geometry/Manifold/ContMDiff/Basic.lean b/Mathlib/Geometry/Manifold/ContMDiff/Basic.lean index 0b2a089aee1e6..bbe1eedcdb768 100644 --- a/Mathlib/Geometry/Manifold/ContMDiff/Basic.lean +++ b/Mathlib/Geometry/Manifold/ContMDiff/Basic.lean @@ -82,31 +82,21 @@ theorem ContMDiffWithinAt.comp_of_eq {t : Set M'} {g : M' → M''} {x : M} {y : (st : MapsTo f s t) (hx : f x = y) : ContMDiffWithinAt I I'' n (g ∘ f) s x := by subst hx; exact hg.comp x hf st -/-- The composition of `C^∞` functions within domains at points is `C^∞`. -/ -nonrec theorem SmoothWithinAt.comp {t : Set M'} {g : M' → M''} (x : M) - (hg : SmoothWithinAt I' I'' g t (f x)) (hf : SmoothWithinAt I I' f s x) (st : MapsTo f s t) : - SmoothWithinAt I I'' (g ∘ f) s x := - hg.comp x hf st +@[deprecated (since := "2024-11-20")] alias SmoothWithinAt.comp := ContMDiffWithinAt.comp /-- The composition of `C^n` functions on domains is `C^n`. -/ theorem ContMDiffOn.comp {t : Set M'} {g : M' → M''} (hg : ContMDiffOn I' I'' n g t) (hf : ContMDiffOn I I' n f s) (st : s ⊆ f ⁻¹' t) : ContMDiffOn I I'' n (g ∘ f) s := fun x hx => (hg _ (st hx)).comp x (hf x hx) st -/-- The composition of `C^∞` functions on domains is `C^∞`. -/ -nonrec theorem SmoothOn.comp {t : Set M'} {g : M' → M''} (hg : SmoothOn I' I'' g t) - (hf : SmoothOn I I' f s) (st : s ⊆ f ⁻¹' t) : SmoothOn I I'' (g ∘ f) s := - hg.comp hf st +@[deprecated (since := "2024-11-20")] alias SmoothOn.comp := ContMDiffOn.comp /-- The composition of `C^n` functions on domains is `C^n`. -/ theorem ContMDiffOn.comp' {t : Set M'} {g : M' → M''} (hg : ContMDiffOn I' I'' n g t) (hf : ContMDiffOn I I' n f s) : ContMDiffOn I I'' n (g ∘ f) (s ∩ f ⁻¹' t) := hg.comp (hf.mono inter_subset_left) inter_subset_right -/-- The composition of `C^∞` functions is `C^∞`. -/ -nonrec theorem SmoothOn.comp' {t : Set M'} {g : M' → M''} (hg : SmoothOn I' I'' g t) - (hf : SmoothOn I I' f s) : SmoothOn I I'' (g ∘ f) (s ∩ f ⁻¹' t) := - hg.comp' hf +@[deprecated (since := "2024-11-20")] alias SmoothOn.comp' := ContMDiffOn.comp' /-- The composition of `C^n` functions is `C^n`. -/ theorem ContMDiff.comp {g : M' → M''} (hg : ContMDiff I' I'' n g) (hf : ContMDiff I I' n f) : @@ -114,10 +104,7 @@ theorem ContMDiff.comp {g : M' → M''} (hg : ContMDiff I' I'' n g) (hf : ContMD rw [← contMDiffOn_univ] at hf hg ⊢ exact hg.comp hf subset_preimage_univ -/-- The composition of `C^∞` functions is `C^∞`. -/ -nonrec theorem Smooth.comp {g : M' → M''} (hg : Smooth I' I'' g) (hf : Smooth I I' f) : - Smooth I I'' (g ∘ f) := - hg.comp hf +@[deprecated (since := "2024-11-20")] alias Smooth.comp := ContMDiff.comp /-- The composition of `C^n` functions within domains at points is `C^n`. -/ theorem ContMDiffWithinAt.comp' {t : Set M'} {g : M' → M''} (x : M) @@ -125,11 +112,7 @@ theorem ContMDiffWithinAt.comp' {t : Set M'} {g : M' → M''} (x : M) ContMDiffWithinAt I I'' n (g ∘ f) (s ∩ f ⁻¹' t) x := hg.comp x (hf.mono inter_subset_left) inter_subset_right -/-- The composition of `C^∞` functions within domains at points is `C^∞`. -/ -nonrec theorem SmoothWithinAt.comp' {t : Set M'} {g : M' → M''} (x : M) - (hg : SmoothWithinAt I' I'' g t (f x)) (hf : SmoothWithinAt I I' f s x) : - SmoothWithinAt I I'' (g ∘ f) (s ∩ f ⁻¹' t) x := - hg.comp' x hf +@[deprecated (since := "2024-11-20")] alias SmoothWithinAt.comp' := ContMDiffWithinAt.comp' /-- `g ∘ f` is `C^n` within `s` at `x` if `g` is `C^n` at `f x` and `f` is `C^n` within `s` at `x`. -/ @@ -138,11 +121,8 @@ theorem ContMDiffAt.comp_contMDiffWithinAt {g : M' → M''} (x : M) ContMDiffWithinAt I I'' n (g ∘ f) s x := hg.comp x hf (mapsTo_univ _ _) -/-- `g ∘ f` is `C^∞` within `s` at `x` if `g` is `C^∞` at `f x` and -`f` is `C^∞` within `s` at `x`. -/ -theorem SmoothAt.comp_smoothWithinAt {g : M' → M''} (x : M) (hg : SmoothAt I' I'' g (f x)) - (hf : SmoothWithinAt I I' f s x) : SmoothWithinAt I I'' (g ∘ f) s x := - hg.comp_contMDiffWithinAt x hf +@[deprecated (since := "2024-11-20")] +alias SmoothAt.comp_smoothWithinAt := ContMDiffAt.comp_contMDiffWithinAt /-- The composition of `C^n` functions at points is `C^n`. -/ nonrec theorem ContMDiffAt.comp {g : M' → M''} (x : M) (hg : ContMDiffAt I' I'' n g (f x)) @@ -154,26 +134,19 @@ theorem ContMDiffAt.comp_of_eq {g : M' → M''} {x : M} {y : M'} (hg : ContMDiff (hf : ContMDiffAt I I' n f x) (hx : f x = y) : ContMDiffAt I I'' n (g ∘ f) x := by subst hx; exact hg.comp x hf -/-- The composition of `C^∞` functions at points is `C^∞`. -/ -nonrec theorem SmoothAt.comp {g : M' → M''} (x : M) (hg : SmoothAt I' I'' g (f x)) - (hf : SmoothAt I I' f x) : SmoothAt I I'' (g ∘ f) x := - hg.comp x hf +@[deprecated (since := "2024-11-20")] alias SmoothAt.comp := ContMDiffAt.comp theorem ContMDiff.comp_contMDiffOn {f : M → M'} {g : M' → M''} {s : Set M} (hg : ContMDiff I' I'' n g) (hf : ContMDiffOn I I' n f s) : ContMDiffOn I I'' n (g ∘ f) s := hg.contMDiffOn.comp hf Set.subset_preimage_univ -theorem Smooth.comp_smoothOn {f : M → M'} {g : M' → M''} {s : Set M} (hg : Smooth I' I'' g) - (hf : SmoothOn I I' f s) : SmoothOn I I'' (g ∘ f) s := - hg.smoothOn.comp hf Set.subset_preimage_univ +@[deprecated (since := "2024-11-20")] alias Smooth.comp_smoothOn := ContMDiff.comp_contMDiffOn theorem ContMDiffOn.comp_contMDiff {t : Set M'} {g : M' → M''} (hg : ContMDiffOn I' I'' n g t) (hf : ContMDiff I I' n f) (ht : ∀ x, f x ∈ t) : ContMDiff I I'' n (g ∘ f) := contMDiffOn_univ.mp <| hg.comp hf.contMDiffOn fun x _ => ht x -theorem SmoothOn.comp_smooth {t : Set M'} {g : M' → M''} (hg : SmoothOn I' I'' g t) - (hf : Smooth I I' f) (ht : ∀ x, f x ∈ t) : Smooth I I'' (g ∘ f) := - hg.comp_contMDiff hf ht +@[deprecated (since := "2024-11-20")] alias SmoothOn.comp_smooth := ContMDiffOn.comp_contMDiff end Composition @@ -183,28 +156,24 @@ section id theorem contMDiff_id : ContMDiff I I n (id : M → M) := ContMDiff.of_le - ((contDiffWithinAt_localInvariantProp ∞).liftProp_id contDiffWithinAtProp_id) le_top + ((contDiffWithinAt_localInvariantProp ⊤).liftProp_id contDiffWithinAtProp_id) le_top -theorem smooth_id : Smooth I I (id : M → M) := - contMDiff_id +@[deprecated (since := "2024-11-20")] alias smooth_id := contMDiff_id theorem contMDiffOn_id : ContMDiffOn I I n (id : M → M) s := contMDiff_id.contMDiffOn -theorem smoothOn_id : SmoothOn I I (id : M → M) s := - contMDiffOn_id +@[deprecated (since := "2024-11-20")] alias smoothOn_id := contMDiffOn_id theorem contMDiffAt_id : ContMDiffAt I I n (id : M → M) x := contMDiff_id.contMDiffAt -theorem smoothAt_id : SmoothAt I I (id : M → M) x := - contMDiffAt_id +@[deprecated (since := "2024-11-20")] alias smoothAt_id := contMDiffAt_id theorem contMDiffWithinAt_id : ContMDiffWithinAt I I n (id : M → M) s x := contMDiffAt_id.contMDiffWithinAt -theorem smoothWithinAt_id : SmoothWithinAt I I (id : M → M) s x := - contMDiffWithinAt_id +@[deprecated (since := "2024-11-20")] alias smoothWithinAt_id := contMDiffWithinAt_id end id @@ -223,11 +192,10 @@ theorem contMDiff_const : ContMDiff I I' n fun _ : M => c := by theorem contMDiff_one [One M'] : ContMDiff I I' n (1 : M → M') := by simp only [Pi.one_def, contMDiff_const] -theorem smooth_const : Smooth I I' fun _ : M => c := - contMDiff_const +@[deprecated (since := "2024-11-20")] alias smooth_const := contMDiff_const -@[to_additive] -theorem smooth_one [One M'] : Smooth I I' (1 : M → M') := by simp only [Pi.one_def, smooth_const] +@[deprecated (since := "2024-11-20")] alias smooth_one := contMDiff_one +@[deprecated (since := "2024-11-20")] alias smooth_zero := contMDiff_zero theorem contMDiffOn_const : ContMDiffOn I I' n (fun _ : M => c) s := contMDiff_const.contMDiffOn @@ -236,12 +204,11 @@ theorem contMDiffOn_const : ContMDiffOn I I' n (fun _ : M => c) s := theorem contMDiffOn_one [One M'] : ContMDiffOn I I' n (1 : M → M') s := contMDiff_one.contMDiffOn -theorem smoothOn_const : SmoothOn I I' (fun _ : M => c) s := - contMDiffOn_const +@[deprecated (since := "2024-11-20")] alias smoothOn_const := contMDiffOn_const + +@[deprecated (since := "2024-11-20")] alias smoothOn_one := contMDiffOn_one +@[deprecated (since := "2024-11-20")] alias smoothOn_zero := contMDiffOn_zero -@[to_additive] -theorem smoothOn_one [One M'] : SmoothOn I I' (1 : M → M') s := - contMDiffOn_one theorem contMDiffAt_const : ContMDiffAt I I' n (fun _ : M => c) x := contMDiff_const.contMDiffAt @@ -250,12 +217,10 @@ theorem contMDiffAt_const : ContMDiffAt I I' n (fun _ : M => c) x := theorem contMDiffAt_one [One M'] : ContMDiffAt I I' n (1 : M → M') x := contMDiff_one.contMDiffAt -theorem smoothAt_const : SmoothAt I I' (fun _ : M => c) x := - contMDiffAt_const +@[deprecated (since := "2024-11-20")] alias smoothAt_const := contMDiffAt_const -@[to_additive] -theorem smoothAt_one [One M'] : SmoothAt I I' (1 : M → M') x := - contMDiffAt_one +@[deprecated (since := "2024-11-20")] alias smoothAt_one := contMDiffAt_one +@[deprecated (since := "2024-11-20")] alias smoothAt_zero := contMDiffAt_zero theorem contMDiffWithinAt_const : ContMDiffWithinAt I I' n (fun _ : M => c) s x := contMDiffAt_const.contMDiffWithinAt @@ -264,12 +229,10 @@ theorem contMDiffWithinAt_const : ContMDiffWithinAt I I' n (fun _ : M => c) s x theorem contMDiffWithinAt_one [One M'] : ContMDiffWithinAt I I' n (1 : M → M') s x := contMDiffAt_const.contMDiffWithinAt -theorem smoothWithinAt_const : SmoothWithinAt I I' (fun _ : M => c) s x := - contMDiffWithinAt_const +@[deprecated (since := "2024-11-20")] alias smoothWithinAt_const := contMDiffWithinAt_const -@[to_additive] -theorem smoothWithinAt_one [One M'] : SmoothWithinAt I I' (1 : M → M') s x := - contMDiffWithinAt_one +@[deprecated (since := "2024-11-20")] alias smoothWithinAt_one := contMDiffWithinAt_one +@[deprecated (since := "2024-11-20")] alias smoothWithinAt_zero := contMDiffWithinAt_zero end id @@ -305,12 +268,14 @@ section Inclusion open TopologicalSpace -theorem contMdiffAt_subtype_iff {n : ℕ∞} {U : Opens M} {f : M → M'} {x : U} : +theorem contMDiffAt_subtype_iff {n : ℕ∞} {U : Opens M} {f : M → M'} {x : U} : ContMDiffAt I I' n (fun x : U ↦ f x) x ↔ ContMDiffAt I I' n f x := ((contDiffWithinAt_localInvariantProp n).liftPropAt_iff_comp_subtype_val _ _).symm +@[deprecated (since := "2024-11-20")] alias contMdiffAt_subtype_iff := contMDiffAt_subtype_iff + theorem contMDiff_subtype_val {n : ℕ∞} {U : Opens M} : ContMDiff I I n (Subtype.val : U → M) := - fun _ ↦ contMdiffAt_subtype_iff.mpr contMDiffAt_id + fun _ ↦ contMDiffAt_subtype_iff.mpr contMDiffAt_id @[to_additive] theorem ContMDiff.extend_one [T2Space M] [One M'] {n : ℕ∞} {U : Opens M} {f : U → M'} @@ -319,7 +284,7 @@ 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] + rw [← contMDiffAt_subtype_iff] simp_rw [← comp_def] rw [extend_comp Subtype.val_injective] exact diff.contMDiffAt @@ -333,19 +298,14 @@ theorem contMDiff_inclusion {n : ℕ∞} {U V : Opens M} (h : U ≤ V) : rw [Set.univ_inter] exact contDiffWithinAt_id.congr I.rightInvOn (congr_arg I (I.left_inv y)) -theorem smooth_subtype_iff {U : Opens M} {f : M → M'} {x : U} : - SmoothAt I I' (fun x : U ↦ f x) x ↔ SmoothAt I I' f x := contMdiffAt_subtype_iff +@[deprecated (since := "2024-11-20")] alias smooth_subtype_iff := contMDiffAt_subtype_iff -theorem smooth_subtype_val {U : Opens M} : Smooth I I (Subtype.val : U → M) := contMDiff_subtype_val +@[deprecated (since := "2024-11-20")] alias smooth_subtype_val := contMDiff_subtype_val -@[to_additive] -theorem Smooth.extend_one [T2Space M] [One M'] {U : Opens M} {f : U → M'} - (supp : HasCompactMulSupport f) (diff : Smooth I I' f) : Smooth I I' (Subtype.val.extend f 1) := - ContMDiff.extend_one supp diff +@[deprecated (since := "2024-11-20")] alias Smooth.extend_one := ContMDiff.extend_one +@[deprecated (since := "2024-11-20")] alias Smooth.extend_zero := ContMDiff.extend_zero -theorem smooth_inclusion {U V : Opens M} (h : U ≤ V) : - Smooth I I (Opens.inclusion h : U → V) := - contMDiff_inclusion h +@[deprecated (since := "2024-11-20")] alias smooth_inclusion := contMDiff_inclusion end Inclusion diff --git a/Mathlib/Geometry/Manifold/ContMDiff/Defs.lean b/Mathlib/Geometry/Manifold/ContMDiff/Defs.lean index f0917e558dc3c..49996ee7ba8cb 100644 --- a/Mathlib/Geometry/Manifold/ContMDiff/Defs.lean +++ b/Mathlib/Geometry/Manifold/ContMDiff/Defs.lean @@ -46,7 +46,7 @@ in terms of extended charts in `contMDiffOn_iff` and `contMDiff_iff`. open Set Function Filter ChartedSpace SmoothManifoldWithCorners -open scoped Topology Manifold +open scoped Topology Manifold ContDiff /-! ### Definition of smooth functions between manifolds -/ @@ -110,7 +110,8 @@ theorem contDiffWithinAt_localInvariantProp (n : ℕ∞) : rw [this] at h have : I (e x) ∈ I.symm ⁻¹' e.target ∩ range I := by simp only [hx, mfld_simps] have := (mem_groupoid_of_pregroupoid.2 he).2.contDiffWithinAt this - convert (h.comp_inter _ (this.of_le le_top)).mono_of_mem_nhdsWithin _ using 1 + convert (h.comp_inter _ (this.of_le (mod_cast le_top))).mono_of_mem_nhdsWithin _ + using 1 · ext y; simp only [mfld_simps] refine mem_nhdsWithin.mpr ⟨I.symm ⁻¹' e.target, e.open_target.preimage I.continuous_symm, by @@ -127,7 +128,7 @@ theorem contDiffWithinAt_localInvariantProp (n : ℕ∞) : have A : (I' ∘ f ∘ I.symm) (I x) ∈ I'.symm ⁻¹' e'.source ∩ range I' := by simp only [hx, mfld_simps] have := (mem_groupoid_of_pregroupoid.2 he').1.contDiffWithinAt A - convert (this.of_le le_top).comp _ h _ + convert (this.of_le (mod_cast le_top)).comp _ h _ · ext y; simp only [mfld_simps] · intro y hy; simp only [mfld_simps] at hy; simpa only [hy, mfld_simps] using hs hy.1 @@ -155,11 +156,7 @@ read in the preferred chart at this point. -/ def ContMDiffWithinAt (n : ℕ∞) (f : M → M') (s : Set M) (x : M) := LiftPropWithinAt (ContDiffWithinAtProp I I' n) f s x -variable (I I') in -/-- Abbreviation for `ContMDiffWithinAt I I' ⊤ f s x`. See also documentation for `Smooth`. --/ -abbrev SmoothWithinAt (f : M → M') (s : Set M) (x : M) := - ContMDiffWithinAt I I' ⊤ f s x +@[deprecated (since := "024-11-21")] alias SmoothWithinAt := ContMDiffWithinAt variable (I I') in /-- A function is `n` times continuously differentiable at a point in a manifold if @@ -175,10 +172,7 @@ theorem contMDiffAt_iff {n : ℕ∞} {f : M → M'} {x : M} : (extChartAt I x x) := liftPropAt_iff.trans <| by rw [ContDiffWithinAtProp, preimage_univ, univ_inter]; rfl -variable (I I') in -/-- Abbreviation for `ContMDiffAt I I' ⊤ f x`. See also documentation for `Smooth`. -/ -abbrev SmoothAt (f : M → M') (x : M) := - ContMDiffAt I I' ⊤ f x +@[deprecated (since := "024-11-21")] alias SmoothAt := ContMDiffAt variable (I I') in /-- A function is `n` times continuously differentiable in a set of a manifold if it is continuous @@ -187,10 +181,7 @@ around these points. -/ def ContMDiffOn (n : ℕ∞) (f : M → M') (s : Set M) := ∀ x ∈ s, ContMDiffWithinAt I I' n f s x -variable (I I') in -/-- Abbreviation for `ContMDiffOn I I' ⊤ f s`. See also documentation for `Smooth`. -/ -abbrev SmoothOn (f : M → M') (s : Set M) := - ContMDiffOn I I' ⊤ f s +@[deprecated (since := "024-11-21")] alias SmoothOn := ContMDiffOn variable (I I') in /-- A function is `n` times continuously differentiable in a manifold if it is continuous @@ -199,23 +190,15 @@ around these points. -/ def ContMDiff (n : ℕ∞) (f : M → M') := ∀ x, ContMDiffAt I I' n f x -variable (I I') in -/-- Abbreviation for `ContMDiff I I' ⊤ f`. -Short note to work with these abbreviations: a lemma of the form `ContMDiffFoo.bar` will -apply fine to an assumption `SmoothFoo` using dot notation or normal notation. -If the consequence `bar` of the lemma involves `ContDiff`, it is still better to restate -the lemma replacing `ContDiff` with `Smooth` both in the assumption and in the conclusion, -to make it possible to use `Smooth` consistently. -This also applies to `SmoothAt`, `SmoothOn` and `SmoothWithinAt`. -/ -abbrev Smooth (f : M → M') := - ContMDiff I I' ⊤ f +@[deprecated (since := "024-11-21")] alias Smooth := ContMDiff + /-! ### Deducing smoothness from higher smoothness -/ theorem ContMDiffWithinAt.of_le (hf : ContMDiffWithinAt I I' n f s x) (le : m ≤ n) : ContMDiffWithinAt I I' m f s x := by simp only [ContMDiffWithinAt, LiftPropWithinAt] at hf ⊢ - exact ⟨hf.1, hf.2.of_le le⟩ + exact ⟨hf.1, hf.2.of_le (mod_cast le)⟩ theorem ContMDiffAt.of_le (hf : ContMDiffAt I I' n f x) (le : m ≤ n) : ContMDiffAt I I' m f x := ContMDiffWithinAt.of_le hf le @@ -228,49 +211,38 @@ theorem ContMDiff.of_le (hf : ContMDiff I I' n f) (le : m ≤ n) : ContMDiff I I /-! ### Basic properties of smooth functions between manifolds -/ -theorem ContMDiff.smooth (h : ContMDiff I I' ⊤ f) : Smooth I I' f := - h +@[deprecated (since := "2024-11-20")] alias ContMDiff.smooth := ContMDiff.of_le -theorem Smooth.contMDiff (h : Smooth I I' f) : ContMDiff I I' n f := - h.of_le le_top +@[deprecated (since := "2024-11-20")] alias Smooth.contMDiff := ContMDiff.of_le -theorem ContMDiffOn.smoothOn (h : ContMDiffOn I I' ⊤ f s) : SmoothOn I I' f s := - h +@[deprecated (since := "2024-11-20")] alias ContMDiffOn.smoothOn := ContMDiffOn.of_le -theorem SmoothOn.contMDiffOn (h : SmoothOn I I' f s) : ContMDiffOn I I' n f s := - h.of_le le_top +@[deprecated (since := "2024-11-20")] alias SmoothOn.contMDiffOn := ContMDiffOn.of_le -theorem ContMDiffAt.smoothAt (h : ContMDiffAt I I' ⊤ f x) : SmoothAt I I' f x := - h +@[deprecated (since := "2024-11-20")] alias ContMDiffAt.smoothAt := ContMDiffAt.of_le -theorem SmoothAt.contMDiffAt (h : SmoothAt I I' f x) : ContMDiffAt I I' n f x := - h.of_le le_top +@[deprecated (since := "2024-11-20")] alias SmoothAt.contMDiffAt := ContMDiffOn.of_le -theorem ContMDiffWithinAt.smoothWithinAt (h : ContMDiffWithinAt I I' ⊤ f s x) : - SmoothWithinAt I I' f s x := - h +@[deprecated (since := "2024-11-20")] +alias ContMDiffWithinAt.smoothWithinAt := ContMDiffWithinAt.of_le -theorem SmoothWithinAt.contMDiffWithinAt (h : SmoothWithinAt I I' f s x) : - ContMDiffWithinAt I I' n f s x := - h.of_le le_top +@[deprecated (since := "2024-11-20")] +alias SmoothWithinAt.contMDiffWithinAt := ContMDiffWithinAt.of_le theorem ContMDiff.contMDiffAt (h : ContMDiff I I' n f) : ContMDiffAt I I' n f x := h x -theorem Smooth.smoothAt (h : Smooth I I' f) : SmoothAt I I' f x := - ContMDiff.contMDiffAt h +@[deprecated (since := "2024-11-20")] alias Smooth.smoothAt := ContMDiff.contMDiffAt theorem contMDiffWithinAt_univ : ContMDiffWithinAt I I' n f univ x ↔ ContMDiffAt I I' n f x := Iff.rfl -theorem smoothWithinAt_univ : SmoothWithinAt I I' f univ x ↔ SmoothAt I I' f x := - contMDiffWithinAt_univ +@[deprecated (since := "2024-11-20")] alias smoothWithinAt_univ := contMDiffWithinAt_univ theorem contMDiffOn_univ : ContMDiffOn I I' n f univ ↔ ContMDiff I I' n f := by simp only [ContMDiffOn, ContMDiff, contMDiffWithinAt_univ, forall_prop_of_true, mem_univ] -theorem smoothOn_univ : SmoothOn I I' f univ ↔ Smooth I I' f := - contMDiffOn_univ +@[deprecated (since := "2024-11-20")] alias smoothOn_univ := contMDiffOn_univ /-- One can reformulate smoothness within a set at a point as continuity within this set at this point, and smoothness in the corresponding extended chart. -/ @@ -315,26 +287,18 @@ theorem contMDiffWithinAt_iff_target : chartAt_self_eq, PartialHomeomorph.refl_apply, id_comp] rfl -theorem smoothWithinAt_iff : - SmoothWithinAt I I' f s x ↔ - ContinuousWithinAt f s x ∧ - ContDiffWithinAt 𝕜 ∞ (extChartAt I' (f x) ∘ f ∘ (extChartAt I x).symm) - ((extChartAt I x).symm ⁻¹' s ∩ range I) (extChartAt I x x) := - contMDiffWithinAt_iff +@[deprecated (since := "2024-11-20")] alias smoothWithinAt_iff := contMDiffWithinAt_iff -theorem smoothWithinAt_iff_target : - SmoothWithinAt I I' f s x ↔ - ContinuousWithinAt f s x ∧ SmoothWithinAt I 𝓘(𝕜, E') (extChartAt I' (f x) ∘ f) s x := - contMDiffWithinAt_iff_target +@[deprecated (since := "2024-11-20")] +alias smoothWithinAt_iff_target := contMDiffWithinAt_iff_target theorem contMDiffAt_iff_target {x : M} : ContMDiffAt I I' n f x ↔ ContinuousAt f x ∧ ContMDiffAt I 𝓘(𝕜, E') n (extChartAt I' (f x) ∘ f) x := by rw [ContMDiffAt, ContMDiffAt, contMDiffWithinAt_iff_target, continuousWithinAt_univ] -theorem smoothAt_iff_target {x : M} : - SmoothAt I I' f x ↔ ContinuousAt f x ∧ SmoothAt I 𝓘(𝕜, E') (extChartAt I' (f x) ∘ f) x := - contMDiffAt_iff_target +@[deprecated (since := "2024-11-20")] alias smoothAt_iff_target := contMDiffAt_iff_target + section SmoothManifoldWithCorners @@ -533,20 +497,10 @@ theorem contMDiffOn_iff_target : simp · exact fun h' x y => (h' y).2 x 0 -theorem smoothOn_iff : - SmoothOn I I' f s ↔ - ContinuousOn f s ∧ - ∀ (x : M) (y : M'), - ContDiffOn 𝕜 ⊤ (extChartAt I' y ∘ f ∘ (extChartAt I x).symm) - ((extChartAt I x).target ∩ - (extChartAt I x).symm ⁻¹' (s ∩ f ⁻¹' (extChartAt I' y).source)) := - contMDiffOn_iff +@[deprecated (since := "2024-11-20")] alias smoothOn_iff := contMDiffOn_iff + +@[deprecated (since := "2024-11-20")] alias smoothOn_iff_target := contMDiffOn_iff_target -theorem smoothOn_iff_target : - SmoothOn I I' f s ↔ - ContinuousOn f s ∧ - ∀ y : M', SmoothOn I 𝓘(𝕜, E') (extChartAt I' y ∘ f) (s ∩ f ⁻¹' (extChartAt I' y).source) := - contMDiffOn_iff_target /-- One can reformulate smoothness as continuity and smoothness in any extended chart. -/ theorem contMDiff_iff : @@ -567,20 +521,9 @@ theorem contMDiff_iff_target : rw [← contMDiffOn_univ, contMDiffOn_iff_target] simp [continuous_iff_continuousOn_univ] -theorem smooth_iff : - Smooth I I' f ↔ - Continuous f ∧ - ∀ (x : M) (y : M'), - ContDiffOn 𝕜 ⊤ (extChartAt I' y ∘ f ∘ (extChartAt I x).symm) - ((extChartAt I x).target ∩ - (extChartAt I x).symm ⁻¹' (f ⁻¹' (extChartAt I' y).source)) := - contMDiff_iff +@[deprecated (since := "2024-11-20")] alias smooth_iff := contMDiff_iff -theorem smooth_iff_target : - Smooth I I' f ↔ - Continuous f ∧ - ∀ y : M', SmoothOn I 𝓘(𝕜, E') (extChartAt I' y ∘ f) (f ⁻¹' (extChartAt I' y).source) := - contMDiff_iff_target +@[deprecated (since := "2024-11-20")] alias smooth_iff_target := contMDiff_iff_target end SmoothManifoldWithCorners @@ -619,17 +562,17 @@ theorem ContMDiff.continuous (hf : ContMDiff I I' n f) : Continuous f := /-! ### `C^∞` smoothness -/ theorem contMDiffWithinAt_top : - SmoothWithinAt I I' f s x ↔ ∀ n : ℕ, ContMDiffWithinAt I I' n f s x := + ContMDiffWithinAt I I' ⊤ f s x ↔ ∀ n : ℕ, ContMDiffWithinAt I I' n f s x := ⟨fun h n => ⟨h.1, contDiffWithinAt_top.1 h.2 n⟩, fun H => ⟨(H 0).1, contDiffWithinAt_top.2 fun n => (H n).2⟩⟩ -theorem contMDiffAt_top : SmoothAt I I' f x ↔ ∀ n : ℕ, ContMDiffAt I I' n f x := +theorem contMDiffAt_top : ContMDiffAt I I' ⊤ f x ↔ ∀ n : ℕ, ContMDiffAt I I' n f x := contMDiffWithinAt_top -theorem contMDiffOn_top : SmoothOn I I' f s ↔ ∀ n : ℕ, ContMDiffOn I I' n f s := +theorem contMDiffOn_top : ContMDiffOn I I' ⊤ f s ↔ ∀ n : ℕ, ContMDiffOn I I' n f s := ⟨fun h _ => h.of_le le_top, fun h x hx => contMDiffWithinAt_top.2 fun n => h n x hx⟩ -theorem contMDiff_top : Smooth I I' f ↔ ∀ n : ℕ, ContMDiff I I' n f := +theorem contMDiff_top : ContMDiff I I' ⊤ f ↔ ∀ n : ℕ, ContMDiff I I' n f := ⟨fun h _ => h.of_le le_top, fun h x => contMDiffWithinAt_top.2 fun n => h n x⟩ theorem contMDiffWithinAt_iff_nat : @@ -691,8 +634,7 @@ protected theorem ContMDiffAt.contMDiffWithinAt (hf : ContMDiffAt I I' n f x) : ContMDiffWithinAt I I' n f s x := ContMDiffWithinAt.mono hf (subset_univ _) -protected theorem SmoothAt.smoothWithinAt (hf : SmoothAt I I' f x) : SmoothWithinAt I I' f s x := - ContMDiffAt.contMDiffWithinAt hf +@[deprecated (since := "2024-11-20")] alias SmoothAt.smoothWithinAt := ContMDiffAt.contMDiffWithinAt theorem ContMDiffOn.mono (hf : ContMDiffOn I I' n f s) (hts : t ⊆ s) : ContMDiffOn I I' n f t := fun x hx => (hf x (hts hx)).mono hts @@ -700,8 +642,7 @@ theorem ContMDiffOn.mono (hf : ContMDiffOn I I' n f s) (hts : t ⊆ s) : ContMDi protected theorem ContMDiff.contMDiffOn (hf : ContMDiff I I' n f) : ContMDiffOn I I' n f s := fun x _ => (hf x).contMDiffWithinAt -protected theorem Smooth.smoothOn (hf : Smooth I I' f) : SmoothOn I I' f s := - ContMDiff.contMDiffOn hf +@[deprecated (since := "2024-11-20")] alias Smooth.smoothOn := ContMDiff.contMDiffOn theorem contMDiffWithinAt_inter' (ht : t ∈ 𝓝[s] x) : ContMDiffWithinAt I I' n f (s ∩ t) x ↔ ContMDiffWithinAt I I' n f s x := @@ -716,16 +657,13 @@ protected theorem ContMDiffWithinAt.contMDiffAt ContMDiffAt I I' n f x := (contDiffWithinAt_localInvariantProp n).liftPropAt_of_liftPropWithinAt h ht -protected theorem SmoothWithinAt.smoothAt (h : SmoothWithinAt I I' f s x) (ht : s ∈ 𝓝 x) : - SmoothAt I I' f x := - ContMDiffWithinAt.contMDiffAt h ht +@[deprecated (since := "2024-11-20")] alias SmoothWithinAt.smoothAt := ContMDiffWithinAt.contMDiffAt protected theorem ContMDiffOn.contMDiffAt (h : ContMDiffOn I I' n f s) (hx : s ∈ 𝓝 x) : ContMDiffAt I I' n f x := (h x (mem_of_mem_nhds hx)).contMDiffAt hx -protected theorem SmoothOn.smoothAt (h : SmoothOn I I' f s) (hx : s ∈ 𝓝 x) : SmoothAt I I' f x := - h.contMDiffAt hx +@[deprecated (since := "2024-11-20")] alias SmoothOn.smoothAt := ContMDiffOn.contMDiffAt theorem contMDiffOn_iff_source_of_mem_maximalAtlas [SmoothManifoldWithCorners I M] (he : e ∈ maximalAtlas I M) (hs : s ⊆ e.source) : diff --git a/Mathlib/Geometry/Manifold/ContMDiff/NormedSpace.lean b/Mathlib/Geometry/Manifold/ContMDiff/NormedSpace.lean index de822fbecd69c..e11bb6f43fe1c 100644 --- a/Mathlib/Geometry/Manifold/ContMDiff/NormedSpace.lean +++ b/Mathlib/Geometry/Manifold/ContMDiff/NormedSpace.lean @@ -105,7 +105,8 @@ theorem ContinuousLinearMap.contMDiffWithinAt (L : E →L[𝕜] F) {s x} : theorem ContinuousLinearMap.contMDiffOn (L : E →L[𝕜] F) {s} : ContMDiffOn 𝓘(𝕜, E) 𝓘(𝕜, F) n L s := L.contMDiff.contMDiffOn -theorem ContinuousLinearMap.smooth (L : E →L[𝕜] F) : Smooth 𝓘(𝕜, E) 𝓘(𝕜, F) L := L.contMDiff +@[deprecated (since := "2024-11-20")] +alias ContinuousLinearMap.smooth := ContinuousLinearMap.contMDiff theorem ContMDiffWithinAt.clm_precomp {f : M → F₁ →L[𝕜] F₂} {s : Set M} {x : M} (hf : ContMDiffWithinAt I 𝓘(𝕜, F₁ →L[𝕜] F₂) n f s x) : @@ -261,13 +262,15 @@ theorem ContMDiff.clm_prodMap {g : M → F₁ →L[𝕜] F₃} {f : M → F₂ variable {V : Type*} [NormedAddCommGroup V] [NormedSpace 𝕜 V] /-- On any vector space, multiplication by a scalar is a smooth operation. -/ -theorem smooth_smul : Smooth (𝓘(𝕜).prod 𝓘(𝕜, V)) 𝓘(𝕜, V) fun p : 𝕜 × V => p.1 • p.2 := - smooth_iff.2 ⟨continuous_smul, fun _ _ => contDiff_smul.contDiffOn⟩ +theorem contMDiff_smul : ContMDiff (𝓘(𝕜).prod 𝓘(𝕜, V)) 𝓘(𝕜, V) ⊤ fun p : 𝕜 × V => p.1 • p.2 := + contMDiff_iff.2 ⟨continuous_smul, fun _ _ => contDiff_smul.contDiffOn⟩ + +@[deprecated (since := "2024-11-20")] alias smooth_smul := contMDiff_smul theorem ContMDiffWithinAt.smul {f : M → 𝕜} {g : M → V} (hf : ContMDiffWithinAt I 𝓘(𝕜) n f s x) (hg : ContMDiffWithinAt I 𝓘(𝕜, V) n g s x) : ContMDiffWithinAt I 𝓘(𝕜, V) n (fun p => f p • g p) s x := - (smooth_smul.of_le le_top).contMDiffAt.comp_contMDiffWithinAt x (hf.prod_mk hg) + (contMDiff_smul.of_le le_top).contMDiffAt.comp_contMDiffWithinAt x (hf.prod_mk hg) nonrec theorem ContMDiffAt.smul {f : M → 𝕜} {g : M → V} (hf : ContMDiffAt I 𝓘(𝕜) n f x) (hg : ContMDiffAt I 𝓘(𝕜, V) n g x) : ContMDiffAt I 𝓘(𝕜, V) n (fun p => f p • g p) x := @@ -281,18 +284,10 @@ theorem ContMDiff.smul {f : M → 𝕜} {g : M → V} (hf : ContMDiff I 𝓘( (hg : ContMDiff I 𝓘(𝕜, V) n g) : ContMDiff I 𝓘(𝕜, V) n fun p => f p • g p := fun x => (hf x).smul (hg x) -nonrec theorem SmoothWithinAt.smul {f : M → 𝕜} {g : M → V} (hf : SmoothWithinAt I 𝓘(𝕜) f s x) - (hg : SmoothWithinAt I 𝓘(𝕜, V) g s x) : SmoothWithinAt I 𝓘(𝕜, V) (fun p => f p • g p) s x := - hf.smul hg +@[deprecated (since := "2024-11-20")] alias SmoothWithinAt.smul := ContMDiffWithinAt.smul -nonrec theorem SmoothAt.smul {f : M → 𝕜} {g : M → V} (hf : SmoothAt I 𝓘(𝕜) f x) - (hg : SmoothAt I 𝓘(𝕜, V) g x) : SmoothAt I 𝓘(𝕜, V) (fun p => f p • g p) x := - hf.smul hg +@[deprecated (since := "2024-11-20")] alias SmoothAt.smul := ContMDiffAt.smul -nonrec theorem SmoothOn.smul {f : M → 𝕜} {g : M → V} (hf : SmoothOn I 𝓘(𝕜) f s) - (hg : SmoothOn I 𝓘(𝕜, V) g s) : SmoothOn I 𝓘(𝕜, V) (fun p => f p • g p) s := - hf.smul hg +@[deprecated (since := "2024-11-20")] alias SmoothOn.smul := ContMDiffOn.smul -nonrec theorem Smooth.smul {f : M → 𝕜} {g : M → V} (hf : Smooth I 𝓘(𝕜) f) - (hg : Smooth I 𝓘(𝕜, V) g) : Smooth I 𝓘(𝕜, V) fun p => f p • g p := - hf.smul hg +@[deprecated (since := "2024-11-20")] alias Smooth.smul := ContMDiff.smul diff --git a/Mathlib/Geometry/Manifold/ContMDiff/Product.lean b/Mathlib/Geometry/Manifold/ContMDiff/Product.lean index 7e220374d4678..5562db2312500 100644 --- a/Mathlib/Geometry/Manifold/ContMDiff/Product.lean +++ b/Mathlib/Geometry/Manifold/ContMDiff/Product.lean @@ -81,38 +81,22 @@ theorem ContMDiff.prod_mk_space {f : M → E'} {g : M → F'} (hf : ContMDiff I (hg : ContMDiff I 𝓘(𝕜, F') n g) : ContMDiff I 𝓘(𝕜, E' × F') n fun x => (f x, g x) := fun x => (hf x).prod_mk_space (hg x) -nonrec theorem SmoothWithinAt.prod_mk {f : M → M'} {g : M → N'} (hf : SmoothWithinAt I I' f s x) - (hg : SmoothWithinAt I J' g s x) : SmoothWithinAt I (I'.prod J') (fun x => (f x, g x)) s x := - hf.prod_mk hg +@[deprecated (since := "2024-11-20")] alias SmoothWithinAt.prod_mk := ContMDiffWithinAt.prod_mk -nonrec theorem SmoothWithinAt.prod_mk_space {f : M → E'} {g : M → F'} - (hf : SmoothWithinAt I 𝓘(𝕜, E') f s x) (hg : SmoothWithinAt I 𝓘(𝕜, F') g s x) : - SmoothWithinAt I 𝓘(𝕜, E' × F') (fun x => (f x, g x)) s x := - hf.prod_mk_space hg +@[deprecated (since := "2024-11-20")] +alias SmoothWithinAt.prod_mk_space := ContMDiffWithinAt.prod_mk_space -nonrec theorem SmoothAt.prod_mk {f : M → M'} {g : M → N'} (hf : SmoothAt I I' f x) - (hg : SmoothAt I J' g x) : SmoothAt I (I'.prod J') (fun x => (f x, g x)) x := - hf.prod_mk hg +@[deprecated (since := "2024-11-20")] alias SmoothAt.prod_mk := ContMDiffAt.prod_mk -nonrec theorem SmoothAt.prod_mk_space {f : M → E'} {g : M → F'} (hf : SmoothAt I 𝓘(𝕜, E') f x) - (hg : SmoothAt I 𝓘(𝕜, F') g x) : SmoothAt I 𝓘(𝕜, E' × F') (fun x => (f x, g x)) x := - hf.prod_mk_space hg +@[deprecated (since := "2024-11-20")] alias SmoothAt.prod_mk_space := ContMDiffAt.prod_mk_space -nonrec theorem SmoothOn.prod_mk {f : M → M'} {g : M → N'} (hf : SmoothOn I I' f s) - (hg : SmoothOn I J' g s) : SmoothOn I (I'.prod J') (fun x => (f x, g x)) s := - hf.prod_mk hg +@[deprecated (since := "2024-11-20")] alias SmoothOn.prod_mk := ContMDiffOn.prod_mk -nonrec theorem SmoothOn.prod_mk_space {f : M → E'} {g : M → F'} (hf : SmoothOn I 𝓘(𝕜, E') f s) - (hg : SmoothOn I 𝓘(𝕜, F') g s) : SmoothOn I 𝓘(𝕜, E' × F') (fun x => (f x, g x)) s := - hf.prod_mk_space hg +@[deprecated (since := "2024-11-20")] alias SmoothOn.prod_mk_space := ContMDiffOn.prod_mk_space -nonrec theorem Smooth.prod_mk {f : M → M'} {g : M → N'} (hf : Smooth I I' f) (hg : Smooth I J' g) : - Smooth I (I'.prod J') fun x => (f x, g x) := - hf.prod_mk hg +@[deprecated (since := "2024-11-20")] alias Smooth.prod_mk := ContMDiff.prod_mk -nonrec theorem Smooth.prod_mk_space {f : M → E'} {g : M → F'} (hf : Smooth I 𝓘(𝕜, E') f) - (hg : Smooth I 𝓘(𝕜, F') g) : Smooth I 𝓘(𝕜, E' × F') fun x => (f x, g x) := - hf.prod_mk_space hg +@[deprecated (since := "2024-11-20")] alias Smooth.prod_mk_space := ContMDiff.prod_mk_space end ProdMk @@ -146,18 +130,13 @@ theorem contMDiffOn_fst {s : Set (M × N)} : ContMDiffOn (I.prod J) I n Prod.fst theorem contMDiff_fst : ContMDiff (I.prod J) I n (@Prod.fst M N) := fun _ => contMDiffAt_fst -theorem smoothWithinAt_fst {s : Set (M × N)} {p : M × N} : - SmoothWithinAt (I.prod J) I Prod.fst s p := - contMDiffWithinAt_fst +@[deprecated (since := "2024-11-20")] alias smoothWithinAt_fst := contMDiffWithinAt_fst -theorem smoothAt_fst {p : M × N} : SmoothAt (I.prod J) I Prod.fst p := - contMDiffAt_fst +@[deprecated (since := "2024-11-20")] alias smoothAt_fst := contMDiffAt_fst -theorem smoothOn_fst {s : Set (M × N)} : SmoothOn (I.prod J) I Prod.fst s := - contMDiffOn_fst +@[deprecated (since := "2024-11-20")] alias smoothOn_fst := contMDiffOn_fst -theorem smooth_fst : Smooth (I.prod J) I (@Prod.fst M N) := - contMDiff_fst +@[deprecated (since := "2024-11-20")] alias smooth_fst := contMDiff_fst theorem ContMDiffAt.fst {f : N → M × M'} {x : N} (hf : ContMDiffAt J (I.prod I') n f x) : ContMDiffAt J I n (fun x => (f x).1) x := @@ -167,12 +146,9 @@ theorem ContMDiff.fst {f : N → M × M'} (hf : ContMDiff J (I.prod I') n f) : ContMDiff J I n fun x => (f x).1 := contMDiff_fst.comp hf -theorem SmoothAt.fst {f : N → M × M'} {x : N} (hf : SmoothAt J (I.prod I') f x) : - SmoothAt J I (fun x => (f x).1) x := - smoothAt_fst.comp x hf +@[deprecated (since := "2024-11-20")] alias SmoothAt.fst := ContMDiffAt.fst -theorem Smooth.fst {f : N → M × M'} (hf : Smooth J (I.prod I') f) : Smooth J I fun x => (f x).1 := - smooth_fst.comp hf +@[deprecated (since := "2024-11-20")] alias Smooth.fst := ContMDiff.fst theorem contMDiffWithinAt_snd {s : Set (M × N)} {p : M × N} : ContMDiffWithinAt (I.prod J) J n Prod.snd s p := by @@ -202,18 +178,13 @@ theorem contMDiffOn_snd {s : Set (M × N)} : ContMDiffOn (I.prod J) J n Prod.snd theorem contMDiff_snd : ContMDiff (I.prod J) J n (@Prod.snd M N) := fun _ => contMDiffAt_snd -theorem smoothWithinAt_snd {s : Set (M × N)} {p : M × N} : - SmoothWithinAt (I.prod J) J Prod.snd s p := - contMDiffWithinAt_snd +@[deprecated (since := "2024-11-20")] alias smoothWithinAt_snd := contMDiffWithinAt_snd -theorem smoothAt_snd {p : M × N} : SmoothAt (I.prod J) J Prod.snd p := - contMDiffAt_snd +@[deprecated (since := "2024-11-20")] alias smoothAt_snd := contMDiffAt_snd -theorem smoothOn_snd {s : Set (M × N)} : SmoothOn (I.prod J) J Prod.snd s := - contMDiffOn_snd +@[deprecated (since := "2024-11-20")] alias smoothOn_snd := contMDiffOn_snd -theorem smooth_snd : Smooth (I.prod J) J (@Prod.snd M N) := - contMDiff_snd +@[deprecated (since := "2024-11-20")] alias smooth_snd := contMDiff_snd theorem ContMDiffAt.snd {f : N → M × M'} {x : N} (hf : ContMDiffAt J (I.prod I') n f x) : ContMDiffAt J I' n (fun x => (f x).2) x := @@ -223,12 +194,9 @@ theorem ContMDiff.snd {f : N → M × M'} (hf : ContMDiff J (I.prod I') n f) : ContMDiff J I' n fun x => (f x).2 := contMDiff_snd.comp hf -theorem SmoothAt.snd {f : N → M × M'} {x : N} (hf : SmoothAt J (I.prod I') f x) : - SmoothAt J I' (fun x => (f x).2) x := - smoothAt_snd.comp x hf +@[deprecated (since := "2024-11-20")] alias SmoothAt.snd := ContMDiffAt.snd -theorem Smooth.snd {f : N → M × M'} (hf : Smooth J (I.prod I') f) : Smooth J I' fun x => (f x).2 := - smooth_snd.comp hf +@[deprecated (since := "2024-11-20")] alias Smooth.snd := ContMDiff.snd end Projections @@ -279,17 +247,16 @@ theorem contMDiff_prod_module_iff (f : M → F₁ × F₂) : rw [modelWithCornersSelf_prod, ← chartedSpaceSelf_prod] exact contMDiff_prod_iff f -theorem smoothAt_prod_iff (f : M → M' × N') {x : M} : - SmoothAt I (I'.prod J') f x ↔ SmoothAt I I' (Prod.fst ∘ f) x ∧ SmoothAt I J' (Prod.snd ∘ f) x := - contMDiffAt_prod_iff f +theorem contMDiff_prod_assoc : + ContMDiff ((I.prod I').prod J) (I.prod (I'.prod J)) n + fun x : (M × M') × N => (x.1.1, x.1.2, x.2) := + contMDiff_fst.fst.prod_mk <| contMDiff_fst.snd.prod_mk contMDiff_snd + +@[deprecated (since := "2024-11-20")] alias smoothAt_prod_iff := contMDiffAt_prod_iff -theorem smooth_prod_iff (f : M → M' × N') : - Smooth I (I'.prod J') f ↔ Smooth I I' (Prod.fst ∘ f) ∧ Smooth I J' (Prod.snd ∘ f) := - contMDiff_prod_iff f +@[deprecated (since := "2024-11-20")] alias smooth_prod_iff := contMDiff_prod_iff -theorem smooth_prod_assoc : - Smooth ((I.prod I').prod J) (I.prod (I'.prod J)) fun x : (M × M') × N => (x.1.1, x.1.2, x.2) := - smooth_fst.fst.prod_mk <| smooth_fst.snd.prod_mk smooth_snd +@[deprecated (since := "2024-11-20")] alias smooth_prod_assoc := contMDiff_prod_assoc section prodMap @@ -329,22 +296,13 @@ theorem ContMDiff.prod_map (hf : ContMDiff I I' n f) (hg : ContMDiff J J' n g) : intro p exact (hf p.1).prod_map' (hg p.2) -nonrec theorem SmoothWithinAt.prod_map (hf : SmoothWithinAt I I' f s x) - (hg : SmoothWithinAt J J' g r y) : - SmoothWithinAt (I.prod J) (I'.prod J') (Prod.map f g) (s ×ˢ r) (x, y) := - hf.prod_map hg +@[deprecated (since := "2024-11-20")] alias SmoothWithinAt.prod_map := ContMDiffWithinAt.prod_map -nonrec theorem SmoothAt.prod_map (hf : SmoothAt I I' f x) (hg : SmoothAt J J' g y) : - SmoothAt (I.prod J) (I'.prod J') (Prod.map f g) (x, y) := - hf.prod_map hg +@[deprecated (since := "2024-11-20")] alias SmoothAt.prod_map := ContMDiffAt.prod_map -nonrec theorem SmoothOn.prod_map (hf : SmoothOn I I' f s) (hg : SmoothOn J J' g r) : - SmoothOn (I.prod J) (I'.prod J') (Prod.map f g) (s ×ˢ r) := - hf.prod_map hg +@[deprecated (since := "2024-11-20")] alias SmoothOn.prod_map := ContMDiffOn.prod_map -nonrec theorem Smooth.prod_map (hf : Smooth I I' f) (hg : Smooth J J' g) : - Smooth (I.prod J) (I'.prod J') (Prod.map f g) := - hf.prod_map hg +@[deprecated (since := "2024-11-20")] alias Smooth.prod_map := ContMDiff.prod_map end prodMap @@ -380,20 +338,12 @@ theorem contMDiff_pi_space : ContMDiff I 𝓘(𝕜, ∀ i, Fi i) n φ ↔ ∀ i, ContMDiff I 𝓘(𝕜, Fi i) n fun x => φ x i := ⟨fun h i x => contMDiffAt_pi_space.1 (h x) i, fun h x => contMDiffAt_pi_space.2 fun i => h i x⟩ -theorem smoothWithinAt_pi_space : - SmoothWithinAt I 𝓘(𝕜, ∀ i, Fi i) φ s x ↔ - ∀ i, SmoothWithinAt I 𝓘(𝕜, Fi i) (fun x => φ x i) s x := - contMDiffWithinAt_pi_space +@[deprecated (since := "2024-11-20")] alias smoothWithinAt_pi_space := contMDiffWithinAt_pi_space -theorem smoothOn_pi_space : - SmoothOn I 𝓘(𝕜, ∀ i, Fi i) φ s ↔ ∀ i, SmoothOn I 𝓘(𝕜, Fi i) (fun x => φ x i) s := - contMDiffOn_pi_space +@[deprecated (since := "2024-11-20")] alias smoothAt_pi_space := contMDiffAt_pi_space -theorem smoothAt_pi_space : - SmoothAt I 𝓘(𝕜, ∀ i, Fi i) φ x ↔ ∀ i, SmoothAt I 𝓘(𝕜, Fi i) (fun x => φ x i) x := - contMDiffAt_pi_space +@[deprecated (since := "2024-11-20")] alias smoothOn_pi_space := contMDiffOn_pi_space -theorem smooth_pi_space : Smooth I 𝓘(𝕜, ∀ i, Fi i) φ ↔ ∀ i, Smooth I 𝓘(𝕜, Fi i) fun x => φ x i := - contMDiff_pi_space +@[deprecated (since := "2024-11-20")] alias smooth_pi_space := contMDiff_pi_space end PiSpace diff --git a/Mathlib/Geometry/Manifold/ContMDiffMFDeriv.lean b/Mathlib/Geometry/Manifold/ContMDiffMFDeriv.lean index 9ab1a8b787d06..38b8fd8f39f73 100644 --- a/Mathlib/Geometry/Manifold/ContMDiffMFDeriv.lean +++ b/Mathlib/Geometry/Manifold/ContMDiffMFDeriv.lean @@ -113,7 +113,7 @@ protected theorem ContMDiffWithinAt.mfderivWithin {x₀ : N} {f : N → M → M' rw [contMDiffWithinAt_iff] at hf' hg' simp_rw [Function.comp_def, uncurry, extChartAt_prod, PartialEquiv.prod_coe_symm, ModelWithCorners.range_prod] at hf' ⊢ - apply ContDiffWithinAt.fderivWithin _ _ _ hmn + apply ContDiffWithinAt.fderivWithin _ _ _ (show (m : WithTop ℕ∞) + 1 ≤ n from mod_cast hmn ) · simp [hx₀, t'] · apply inter_subset_left.trans rw [preimage_subset_iff] @@ -343,10 +343,7 @@ theorem ContMDiff.continuous_tangentMap (hf : ContMDiff I I' n f) (hmn : 1 ≤ n convert hf.continuousOn_tangentMapWithin hmn uniqueMDiffOn_univ rw [tangentMapWithin_univ] -/-- If a function is smooth, then its bundled derivative is smooth. -/ -theorem Smooth.tangentMap (hf : Smooth I I' f) : - Smooth I.tangent I'.tangent (tangentMap I I' f) := - ContMDiff.contMDiff_tangentMap hf le_rfl +@[deprecated (since := "2024-11-21")] alias Smooth.tangentMap := ContMDiff.contMDiff_tangentMap end tangentMap @@ -376,9 +373,9 @@ theorem tangentMap_tangentBundle_pure [Is : SmoothManifoldWithCorners I M] (p : · apply (PartialHomeomorph.open_target _).preimage I.continuous_invFun · simp only [mfld_simps] have A : MDifferentiableAt I I.tangent (fun x => @TotalSpace.mk M E (TangentSpace I) x 0) x := - haveI : Smooth I (I.prod 𝓘(𝕜, E)) (zeroSection E (TangentSpace I : M → Type _)) := - Bundle.smooth_zeroSection 𝕜 (TangentSpace I : M → Type _) - this.mdifferentiableAt + haveI : ContMDiff I (I.prod 𝓘(𝕜, E)) ⊤ (zeroSection E (TangentSpace I : M → Type _)) := + Bundle.contMDiff_zeroSection 𝕜 (TangentSpace I : M → Type _) + this.mdifferentiableAt le_top have B : fderivWithin 𝕜 (fun x' : E ↦ (x', (0 : E))) (Set.range I) (I ((chartAt H x) x)) v = (v, 0) := by rw [fderivWithin_eq_fderiv, DifferentiableAt.fderiv_prod] @@ -407,6 +404,9 @@ namespace ContMDiffMap -- (However as a consequence we import `Mathlib/Geometry/Manifold/ContMDiffMap.lean` here now.) -- They could be moved to another file (perhaps a new file) if desired. open scoped Manifold +/- Next line is necessary while the manifold smoothness class is not extended to `ω`. +Later, replace with `open scoped ContDiff`. -/ +local notation "∞" => (⊤ : ℕ∞) protected theorem mdifferentiable' (f : C^n⟮I, M; I', M'⟯) (hn : 1 ≤ n) : MDifferentiable I I' f := f.contMDiff.mdifferentiable hn diff --git a/Mathlib/Geometry/Manifold/ContMDiffMap.lean b/Mathlib/Geometry/Manifold/ContMDiffMap.lean index 8566926007fa4..2be46a551a705 100644 --- a/Mathlib/Geometry/Manifold/ContMDiffMap.lean +++ b/Mathlib/Geometry/Manifold/ContMDiffMap.lean @@ -29,10 +29,7 @@ variable (I I') in def ContMDiffMap := { f : M → M' // ContMDiff I I' n f } -variable (I I') in -/-- Bundled smooth maps. -/ -abbrev SmoothMap := - ContMDiffMap I I' M M' ⊤ +@[deprecated (since := "024-11-21")] alias SmoothMap := ContMDiffMap @[inherit_doc] scoped[Manifold] notation "C^" n "⟮" I ", " M "; " I' ", " M' "⟯" => ContMDiffMap I I' M M' n @@ -42,6 +39,10 @@ scoped[Manifold] notation "C^" n "⟮" I ", " M "; " k "⟯" => ContMDiffMap I (modelWithCornersSelf k k) M k n open scoped Manifold +/- Next line is necessary while the manifold smoothness class is not extended to `ω`. +Later, replace with `open scoped ContDiff`. -/ +local notation "∞" => (⊤ : ℕ∞) + namespace ContMDiffMap @@ -54,8 +55,7 @@ instance instFunLike : FunLike C^n⟮I, M; I', M'⟯ M M' where protected theorem contMDiff (f : C^n⟮I, M; I', M'⟯) : ContMDiff I I' n f := f.prop -protected theorem smooth (f : C^∞⟮I, M; I', M'⟯) : Smooth I I' f := - f.prop +@[deprecated (since := "2024-11-20")] alias smooth := ContMDiffMap.contMDiff -- Porting note: use generic instance instead -- instance : Coe C^n⟮I, M; I', M'⟯ C(M, M') := diff --git a/Mathlib/Geometry/Manifold/DerivationBundle.lean b/Mathlib/Geometry/Manifold/DerivationBundle.lean index ca029181286c4..fb3dbd766186a 100644 --- a/Mathlib/Geometry/Manifold/DerivationBundle.lean +++ b/Mathlib/Geometry/Manifold/DerivationBundle.lean @@ -25,6 +25,9 @@ variable (𝕜 : Type*) [NontriviallyNormedField 𝕜] {E : Type*} [NormedAddCom [TopologicalSpace M] [ChartedSpace H M] (n : ℕ∞) open scoped Manifold +/- Next line is necessary while the manifold smoothness class is not extended to `ω`. +Later, replace with `open scoped ContDiff`. -/ +local notation "∞" => (⊤ : ℕ∞) -- the following two instances prevent poorly understood type class inference timeout problems instance smoothFunctionsAlgebra : Algebra 𝕜 C^∞⟮I, M; 𝕜⟯ := by infer_instance diff --git a/Mathlib/Geometry/Manifold/Diffeomorph.lean b/Mathlib/Geometry/Manifold/Diffeomorph.lean index 8a2f3e373a09a..6a6dd316cf875 100644 --- a/Mathlib/Geometry/Manifold/Diffeomorph.lean +++ b/Mathlib/Geometry/Manifold/Diffeomorph.lean @@ -44,7 +44,7 @@ diffeomorphism, manifold -/ -open scoped Manifold Topology +open scoped Manifold Topology ContDiff open Function Set @@ -125,7 +125,7 @@ protected theorem contMDiffWithinAt (h : M ≃ₘ^n⟮I, I'⟯ M') {s x} : ContM protected theorem contDiff (h : E ≃ₘ^n⟮𝓘(𝕜, E), 𝓘(𝕜, E')⟯ E') : ContDiff 𝕜 n h := h.contMDiff.contDiff -protected theorem smooth (h : M ≃ₘ⟮I, I'⟯ M') : Smooth I I' h := h.contMDiff +@[deprecated (since := "2024-11-21")] alias smooth := Diffeomorph.contDiff protected theorem mdifferentiable (h : M ≃ₘ^n⟮I, I'⟯ M') (hn : 1 ≤ n) : MDifferentiable I I' h := h.contMDiff.mdifferentiable hn @@ -491,7 +491,7 @@ instance smoothManifoldWithCorners_transDiffeomorph [SmoothManifoldWithCorners I SmoothManifoldWithCorners (I.transDiffeomorph e) M := by refine smoothManifoldWithCorners_of_contDiffOn (I.transDiffeomorph e) M fun e₁ e₂ h₁ h₂ => ?_ refine e.contDiff.comp_contDiffOn - (((contDiffGroupoid ⊤ I).compatible h₁ h₂).1.comp e.symm.contDiff.contDiffOn ?_) + (((contDiffGroupoid ∞ I).compatible h₁ h₂).1.comp e.symm.contDiff.contDiffOn ?_) simp only [mapsTo_iff_subset_preimage] mfld_set_tac @@ -539,9 +539,8 @@ theorem contMDiff_transDiffeomorph_right {f : M' → M} : ContMDiff I' (I.transDiffeomorph e) n f ↔ ContMDiff I' I n f := (toTransDiffeomorph I M e).contMDiff_diffeomorph_comp_iff le_top -theorem smooth_transDiffeomorph_right {f : M' → M} : - Smooth I' (I.transDiffeomorph e) f ↔ Smooth I' I f := - contMDiff_transDiffeomorph_right e +@[deprecated (since := "2024-11-21")] +alias smooth_transDiffeomorph_right := contMDiff_transDiffeomorph_right @[simp] theorem contMDiffWithinAt_transDiffeomorph_left {f : M → M'} {x s} : @@ -563,8 +562,7 @@ theorem contMDiff_transDiffeomorph_left {f : M → M'} : ContMDiff (I.transDiffeomorph e) I' n f ↔ ContMDiff I I' n f := ((toTransDiffeomorph I M e).contMDiff_comp_diffeomorph_iff le_top).symm -theorem smooth_transDiffeomorph_left {f : M → M'} : - Smooth (I.transDiffeomorph e) I' f ↔ Smooth I I' f := - e.contMDiff_transDiffeomorph_left +@[deprecated (since := "2024-11-21")] +alias smooth_transDiffeomorph_left := contMDiff_transDiffeomorph_left end Diffeomorph diff --git a/Mathlib/Geometry/Manifold/Instances/Real.lean b/Mathlib/Geometry/Manifold/Instances/Real.lean index 7871850496757..8e667f22b2b24 100644 --- a/Mathlib/Geometry/Manifold/Instances/Real.lean +++ b/Mathlib/Geometry/Manifold/Instances/Real.lean @@ -42,7 +42,7 @@ noncomputable section open Set Function -open scoped Manifold +open scoped Manifold ContDiff /-- 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. diff --git a/Mathlib/Geometry/Manifold/Instances/Sphere.lean b/Mathlib/Geometry/Manifold/Instances/Sphere.lean index 00100a2fdd4ed..a426774e69c58 100644 --- a/Mathlib/Geometry/Manifold/Instances/Sphere.lean +++ b/Mathlib/Geometry/Manifold/Instances/Sphere.lean @@ -69,7 +69,7 @@ noncomputable section open Metric Module Function -open scoped Manifold +open scoped Manifold ContDiff section StereographicProjection @@ -93,7 +93,7 @@ theorem stereoToFun_apply (x : E) : rfl theorem contDiffOn_stereoToFun : - ContDiffOn ℝ ⊤ (stereoToFun v) {x : E | innerSL _ v x ≠ (1 : ℝ)} := by + ContDiffOn ℝ ∞ (stereoToFun v) {x : E | innerSL _ v x ≠ (1 : ℝ)} := by refine ContDiffOn.smul ?_ (orthogonalProjection (ℝ ∙ v)ᗮ).contDiff.contDiffOn refine contDiff_const.contDiffOn.div ?_ ?_ · exact (contDiff_const.sub (innerSL ℝ v).contDiff).contDiffOn @@ -157,13 +157,13 @@ theorem hasFDerivAt_stereoInvFunAux_comp_coe (v : E) : hasFDerivAt_stereoInvFunAux v refine this.comp (0 : (ℝ ∙ v)ᗮ) (by apply ContinuousLinearMap.hasFDerivAt) -theorem contDiff_stereoInvFunAux : ContDiff ℝ ⊤ (stereoInvFunAux v) := by - have h₀ : ContDiff ℝ ⊤ fun w : E => ‖w‖ ^ 2 := contDiff_norm_sq ℝ - have h₁ : ContDiff ℝ ⊤ fun w : E => (‖w‖ ^ 2 + 4)⁻¹ := by +theorem contDiff_stereoInvFunAux : ContDiff ℝ ∞ (stereoInvFunAux v) := by + have h₀ : ContDiff ℝ ∞ fun w : E => ‖w‖ ^ 2 := contDiff_norm_sq ℝ + have h₁ : ContDiff ℝ ∞ fun w : E => (‖w‖ ^ 2 + 4)⁻¹ := by refine (h₀.add contDiff_const).inv ?_ intro x - positivity - have h₂ : ContDiff ℝ ⊤ fun w => (4 : ℝ) • w + (‖w‖ ^ 2 - 4) • v := by + nlinarith + have h₂ : ContDiff ℝ ∞ fun w => (4 : ℝ) • w + (‖w‖ ^ 2 - 4) • v := by refine (contDiff_const.smul contDiff_id).add ?_ exact (h₀.sub contDiff_const).smul contDiff_const exact h₁.smul h₂ @@ -389,7 +389,7 @@ instance EuclideanSpace.instSmoothManifoldWithCornersSphere {n : ℕ} [Fact (fin -- Porting note: need to help with implicit variables again have H₂ := (contDiff_stereoInvFunAux (v := v.val)|>.comp (ℝ ∙ (v : E))ᗮ.subtypeL.contDiff).comp U.symm.contDiff - convert H₁.comp_inter (H₂.contDiffOn : ContDiffOn ℝ ⊤ _ Set.univ) using 1 + convert H₁.comp_inter (H₂.contDiffOn : ContDiffOn ℝ ∞ _ Set.univ) using 1 -- -- squeezed from `ext, simp [sphere_ext_iff, stereographic'_symm_apply, real_inner_comm]` simp only [PartialHomeomorph.trans_toPartialEquiv, PartialHomeomorph.symm_toPartialEquiv, PartialEquiv.trans_source, PartialEquiv.symm_source, stereographic'_target, @@ -407,7 +407,7 @@ instance (n : ℕ) : /-- 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 + ContMDiff (𝓡 n) 𝓘(ℝ, E) ⊤ ((↑) : sphere (0 : E) 1 → E) := by -- Porting note: trouble with filling these implicit variables in the instance have := EuclideanSpace.instSmoothManifoldWithCornersSphere (E := E) (n := n) rw [contMDiff_iff] @@ -438,7 +438,7 @@ theorem ContMDiff.codRestrict_sphere {n : ℕ} [Fact (finrank ℝ E = n + 1)] {m (-- Again, partially removing type ascription... Weird that this helps! OrthonormalBasis.fromOrthogonalSpanSingleton n (ne_zero_of_mem_unit_sphere (-v))).repr - have h : ContDiffOn ℝ ⊤ _ Set.univ := U.contDiff.contDiffOn + have h : ContDiffOn ℝ ∞ _ Set.univ := U.contDiff.contDiffOn have H₁ := (h.comp_inter contDiffOn_stereoToFun).contMDiffOn have H₂ : ContMDiffOn _ _ _ _ Set.univ := hf.contMDiffOn convert (H₁.of_le le_top).comp' H₂ using 1 @@ -453,7 +453,7 @@ theorem ContMDiff.codRestrict_sphere {n : ℕ} [Fact (finrank ℝ E = n + 1)] {m /-- The antipodal map is smooth. -/ theorem contMDiff_neg_sphere {n : ℕ} [Fact (finrank ℝ E = n + 1)] : - ContMDiff (𝓡 n) (𝓡 n) ∞ fun x : sphere (0 : E) 1 => -x := by + ContMDiff (𝓡 n) (𝓡 n) ⊤ fun x : sphere (0 : E) 1 => -x := by -- this doesn't elaborate well in term mode apply ContMDiff.codRestrict_sphere apply contDiff_neg.contMDiff.comp _ @@ -555,7 +555,7 @@ instance : LieGroup (𝓡 1) Circle where smooth_mul := by apply ContMDiff.codRestrict_sphere let c : Circle → ℂ := (↑) - have h₂ : ContMDiff (𝓘(ℝ, ℂ).prod 𝓘(ℝ, ℂ)) 𝓘(ℝ, ℂ) ∞ fun z : ℂ × ℂ => z.fst * z.snd := by + have h₂ : ContMDiff (𝓘(ℝ, ℂ).prod 𝓘(ℝ, ℂ)) 𝓘(ℝ, ℂ) ⊤ fun z : ℂ × ℂ => z.fst * z.snd := by rw [contMDiff_iff] exact ⟨continuous_mul, fun x y => contDiff_mul.contDiffOn⟩ -- Porting note: needed to fill in first 3 arguments or could not figure out typeclasses @@ -569,7 +569,7 @@ instance : LieGroup (𝓡 1) Circle where exact Complex.conjCLE.contDiff.contMDiff.comp contMDiff_coe_sphere /-- The map `fun t ↦ exp (t * I)` from `ℝ` to the unit circle in `ℂ` is smooth. -/ -theorem contMDiff_circleExp : ContMDiff 𝓘(ℝ, ℝ) (𝓡 1) ∞ Circle.exp := +theorem contMDiff_circleExp : ContMDiff 𝓘(ℝ, ℝ) (𝓡 1) ⊤ Circle.exp := (contDiff_exp.comp (contDiff_id.smul contDiff_const)).contMDiff.codRestrict_sphere _ @[deprecated (since := "2024-07-25")] alias contMDiff_expMapCircle := contMDiff_circleExp diff --git a/Mathlib/Geometry/Manifold/Instances/UnitsOfNormedAlgebra.lean b/Mathlib/Geometry/Manifold/Instances/UnitsOfNormedAlgebra.lean index 8ee99e793fb7c..b66b8302d348a 100644 --- a/Mathlib/Geometry/Manifold/Instances/UnitsOfNormedAlgebra.lean +++ b/Mathlib/Geometry/Manifold/Instances/UnitsOfNormedAlgebra.lean @@ -27,6 +27,9 @@ example {V : Type*} [NormedAddCommGroup V] [NormedSpace 𝕜 V] [CompleteSpace V noncomputable section open scoped Manifold +/- Next line is necessary while the manifold smoothness class is not extended to `ω`. +Later, replace with `open scoped ContDiff`. -/ +local notation "∞" => (⊤ : ℕ∞) namespace Units diff --git a/Mathlib/Geometry/Manifold/MFDeriv/Atlas.lean b/Mathlib/Geometry/Manifold/MFDeriv/Atlas.lean index eb88f2a6c5c87..9386f8ad261ec 100644 --- a/Mathlib/Geometry/Manifold/MFDeriv/Atlas.lean +++ b/Mathlib/Geometry/Manifold/MFDeriv/Atlas.lean @@ -27,7 +27,7 @@ charts, differentiable, bijective noncomputable section -open scoped Manifold +open scoped Manifold ContDiff open Bundle Set Topology variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] @@ -99,7 +99,7 @@ theorem mdifferentiableAt_atlas (h : e ∈ atlas H M) {x : M} (hx : x ∈ e.sour ContDiffOn 𝕜 ∞ (I ∘ (chartAt H x).symm.trans e ∘ I.symm) (I.symm ⁻¹' ((chartAt H x).symm.trans e).source ∩ range I) := this.1 - have B := A.differentiableOn le_top (I ((chartAt H x : M → H) x)) mem + have B := A.differentiableOn (mod_cast le_top) (I ((chartAt H x : M → H) x)) mem simp only [mfld_simps] at B rw [inter_comm, differentiableWithinAt_inter] at B · simpa only [mfld_simps] @@ -120,7 +120,7 @@ theorem mdifferentiableAt_atlas_symm (h : e ∈ atlas H M) {x : H} (hx : x ∈ e ContDiffOn 𝕜 ∞ (I ∘ e.symm.trans (chartAt H (e.symm x)) ∘ I.symm) (I.symm ⁻¹' (e.symm.trans (chartAt H (e.symm x))).source ∩ range I) := this.1 - have B := A.differentiableOn le_top (I x) mem + have B := A.differentiableOn (mod_cast le_top) (I x) mem simp only [mfld_simps] at B rw [inter_comm, differentiableWithinAt_inter] at B · simpa only [mfld_simps] diff --git a/Mathlib/Geometry/Manifold/MFDeriv/Basic.lean b/Mathlib/Geometry/Manifold/MFDeriv/Basic.lean index 552b4986092f8..acf6be63394ec 100644 --- a/Mathlib/Geometry/Manifold/MFDeriv/Basic.lean +++ b/Mathlib/Geometry/Manifold/MFDeriv/Basic.lean @@ -467,7 +467,8 @@ theorem ContMDiffWithinAt.mdifferentiableWithinAt (hf : ContMDiffWithinAt I I' n apply hf.1.preimage_mem_nhdsWithin exact extChartAt_source_mem_nhds (f x) rw [mdifferentiableWithinAt_iff] - exact ⟨hf.1.mono inter_subset_left, (hf.2.differentiableWithinAt hn).mono (by mfld_set_tac)⟩ + exact ⟨hf.1.mono inter_subset_left, (hf.2.differentiableWithinAt (mod_cast hn)).mono + (by mfld_set_tac)⟩ theorem ContMDiffAt.mdifferentiableAt (hf : ContMDiffAt I I' n f x) (hn : 1 ≤ n) : MDifferentiableAt I I' f x := @@ -477,27 +478,30 @@ theorem ContMDiff.mdifferentiableAt (hf : ContMDiff I I' n f) (hn : 1 ≤ n) : MDifferentiableAt I I' f x := hf.contMDiffAt.mdifferentiableAt hn +theorem ContMDiff.mdifferentiableWithinAt (hf : ContMDiff I I' n f) (hn : 1 ≤ n) : + MDifferentiableWithinAt I I' f s x := + (hf.contMDiffAt.mdifferentiableAt hn).mdifferentiableWithinAt + theorem ContMDiffOn.mdifferentiableOn (hf : ContMDiffOn I I' n f s) (hn : 1 ≤ n) : MDifferentiableOn I I' f s := fun x hx => (hf x hx).mdifferentiableWithinAt hn -nonrec theorem SmoothWithinAt.mdifferentiableWithinAt (hf : SmoothWithinAt I I' f s x) : - MDifferentiableWithinAt I I' f s x := - hf.mdifferentiableWithinAt le_top +@[deprecated (since := "2024-11-20")] +alias SmoothWithinAt.mdifferentiableWithinAt := ContMDiffWithinAt.mdifferentiableWithinAt theorem ContMDiff.mdifferentiable (hf : ContMDiff I I' n f) (hn : 1 ≤ n) : MDifferentiable I I' f := fun x => (hf x).mdifferentiableAt hn -nonrec theorem SmoothAt.mdifferentiableAt (hf : SmoothAt I I' f x) : MDifferentiableAt I I' f x := - hf.mdifferentiableAt le_top +@[deprecated (since := "2024-11-20")] +alias SmoothAt.mdifferentiableAt := ContMDiffAt.mdifferentiableAt -nonrec theorem SmoothOn.mdifferentiableOn (hf : SmoothOn I I' f s) : MDifferentiableOn I I' f s := - hf.mdifferentiableOn le_top +@[deprecated (since := "2024-11-20")] +alias SmoothOn.mdifferentiableOn := ContMDiffOn.mdifferentiableOn -theorem Smooth.mdifferentiable (hf : Smooth I I' f) : MDifferentiable I I' f := - ContMDiff.mdifferentiable hf le_top +@[deprecated (since := "2024-11-20")] +alias Smooth.mdifferentiable := ContMDiff.mdifferentiable -theorem Smooth.mdifferentiableAt (hf : Smooth I I' f) : MDifferentiableAt I I' f x := - hf.mdifferentiable x +@[deprecated (since := "2024-11-20")] +alias Smooth.mdifferentiableAt := ContMDiff.mdifferentiableAt theorem MDifferentiableOn.continuousOn (h : MDifferentiableOn I I' f s) : ContinuousOn f s := fun x hx => (h x hx).continuousWithinAt @@ -505,8 +509,8 @@ theorem MDifferentiableOn.continuousOn (h : MDifferentiableOn I I' f s) : Contin theorem MDifferentiable.continuous (h : MDifferentiable I I' f) : Continuous f := continuous_iff_continuousAt.2 fun x => (h x).continuousAt -theorem Smooth.mdifferentiableWithinAt (hf : Smooth I I' f) : MDifferentiableWithinAt I I' f s x := - hf.mdifferentiableAt.mdifferentiableWithinAt +@[deprecated (since := "2024-11-20")] +alias Smooth.mdifferentiableWithinAt := ContMDiff.mdifferentiableWithinAt /-! ### Deriving continuity from differentiability on manifolds -/ diff --git a/Mathlib/Geometry/Manifold/MFDeriv/Defs.lean b/Mathlib/Geometry/Manifold/MFDeriv/Defs.lean index 79091c4619038..b7c3206ec3989 100644 --- a/Mathlib/Geometry/Manifold/MFDeriv/Defs.lean +++ b/Mathlib/Geometry/Manifold/MFDeriv/Defs.lean @@ -99,7 +99,7 @@ derivative, manifold noncomputable section -open scoped Topology +open scoped Topology ContDiff open Set ChartedSpace section DerivativesDefinitions @@ -147,7 +147,7 @@ theorem differentiableWithinAtProp_self_target {f : H → E'} {s : Set H} {x : H /-- Being differentiable in the model space is a local property, invariant under smooth maps. Therefore, it will lift nicely to manifolds. -/ theorem differentiableWithinAt_localInvariantProp : - (contDiffGroupoid ⊤ I).LocalInvariantProp (contDiffGroupoid ⊤ I') + (contDiffGroupoid ∞ I).LocalInvariantProp (contDiffGroupoid ∞ I') (DifferentiableWithinAtProp I I') := { is_local := by intro s x u f u_open xu @@ -167,7 +167,8 @@ theorem differentiableWithinAt_localInvariantProp : rw [this] at h have : I (e x) ∈ I.symm ⁻¹' e.target ∩ Set.range I := by simp only [hx, mfld_simps] have := (mem_groupoid_of_pregroupoid.2 he).2.contDiffWithinAt this - convert (h.comp' _ (this.differentiableWithinAt le_top)).mono_of_mem_nhdsWithin _ using 1 + convert (h.comp' _ (this.differentiableWithinAt (mod_cast le_top))).mono_of_mem_nhdsWithin _ + using 1 · ext y; simp only [mfld_simps] refine mem_nhdsWithin.mpr @@ -187,7 +188,7 @@ theorem differentiableWithinAt_localInvariantProp : have A : (I' ∘ f ∘ I.symm) (I x) ∈ I'.symm ⁻¹' e'.source ∩ Set.range I' := by simp only [hx, mfld_simps] have := (mem_groupoid_of_pregroupoid.2 he').1.contDiffWithinAt A - convert (this.differentiableWithinAt le_top).comp _ h _ + convert (this.differentiableWithinAt (mod_cast le_top)).comp _ h _ · ext y; simp only [mfld_simps] · intro y hy; simp only [mfld_simps] at hy; simpa only [hy, mfld_simps] using hs hy.1 } diff --git a/Mathlib/Geometry/Manifold/MFDeriv/UniqueDifferential.lean b/Mathlib/Geometry/Manifold/MFDeriv/UniqueDifferential.lean index 4facc7f820910..e090b101ab9e7 100644 --- a/Mathlib/Geometry/Manifold/MFDeriv/UniqueDifferential.lean +++ b/Mathlib/Geometry/Manifold/MFDeriv/UniqueDifferential.lean @@ -120,7 +120,7 @@ variable {F : Type*} [NormedAddCommGroup F] [NormedSpace 𝕜 F] {Z : M → Type theorem Trivialization.mdifferentiable (e : Trivialization F (π F Z)) [MemTrivializationAtlas e] : e.toPartialHomeomorph.MDifferentiable (I.prod 𝓘(𝕜, F)) (I.prod 𝓘(𝕜, F)) := - ⟨e.smoothOn.mdifferentiableOn, e.smoothOn_symm.mdifferentiableOn⟩ + ⟨e.contMDiffOn.mdifferentiableOn le_top, e.contMDiffOn_symm.mdifferentiableOn le_top⟩ theorem UniqueMDiffWithinAt.smooth_bundle_preimage {p : TotalSpace F Z} (hs : UniqueMDiffWithinAt I s p.proj) : diff --git a/Mathlib/Geometry/Manifold/PartitionOfUnity.lean b/Mathlib/Geometry/Manifold/PartitionOfUnity.lean index 35ffa8cfc8743..5a4131d403b71 100644 --- a/Mathlib/Geometry/Manifold/PartitionOfUnity.lean +++ b/Mathlib/Geometry/Manifold/PartitionOfUnity.lean @@ -59,6 +59,9 @@ universe uι uE uH uM uF open Function Filter Module Set open scoped Topology Manifold +/- Next line is necessary while the manifold smoothness class is not extended to `ω`. +Later, replace with `open scoped ContDiff`. -/ +local notation "∞" => (⊤ : ℕ∞) noncomputable section @@ -160,8 +163,10 @@ theorem sum_le_one (x : M) : ∑ᶠ i, f i x ≤ 1 := def toPartitionOfUnity : PartitionOfUnity ι M s := { f with toFun := fun i => f i } -theorem smooth_sum : Smooth I 𝓘(ℝ) fun x => ∑ᶠ i, f i x := - smooth_finsum (fun i => (f i).smooth) f.locallyFinite +theorem contMDiff_sum : ContMDiff I 𝓘(ℝ) ⊤ fun x => ∑ᶠ i, f i x := + contMDiff_finsum (fun i => (f i).contMDiff) f.locallyFinite + +@[deprecated (since := "2024-11-21")] alias smooth_sum := contMDiff_sum theorem le_one (i : ι) (x : M) : f i x ≤ 1 := f.toPartitionOfUnity.le_one i x @@ -178,9 +183,7 @@ theorem contMDiff_smul {g : M → F} {i} (hg : ∀ x ∈ tsupport (f i), ContMDi contMDiff_of_tsupport fun x hx => ((f i).contMDiff.contMDiffAt.of_le le_top).smul <| hg x <| tsupport_smul_subset_left _ _ hx -theorem smooth_smul {g : M → F} {i} (hg : ∀ x ∈ tsupport (f i), SmoothAt I 𝓘(ℝ, F) g x) : - Smooth I 𝓘(ℝ, F) fun x => f i x • g x := - f.contMDiff_smul hg +@[deprecated (since := "2024-11-21")] alias smooth_smul := contMDiff_smul /-- If `f` is a smooth partition of unity on a set `s : Set M` and `g : ι → M → F` is a family of functions such that `g i` is $C^n$ smooth at every point of the topological support of `f i`, then @@ -191,20 +194,14 @@ theorem contMDiff_finsum_smul {g : ι → M → F} (contMDiff_finsum fun i => f.contMDiff_smul (hg i)) <| f.locallyFinite.subset fun _ => support_smul_subset_left _ _ -/-- If `f` is a smooth partition of unity on a set `s : Set M` and `g : ι → M → F` is a family of -functions such that `g i` is smooth at every point of the topological support of `f i`, then the sum -`fun x ↦ ∑ᶠ i, f i x • g i x` is smooth on the whole manifold. -/ -theorem smooth_finsum_smul {g : ι → M → F} - (hg : ∀ (i), ∀ x ∈ tsupport (f i), SmoothAt I 𝓘(ℝ, F) (g i) x) : - Smooth I 𝓘(ℝ, F) fun x => ∑ᶠ i, f i x • g i x := - f.contMDiff_finsum_smul hg +@[deprecated (since := "2024-11-21")] alias smooth_finsum_smul := contMDiff_finsum_smul theorem contMDiffAt_finsum {x₀ : M} {g : ι → M → F} (hφ : ∀ i, x₀ ∈ tsupport (f i) → ContMDiffAt I 𝓘(ℝ, F) n (g i) x₀) : ContMDiffAt I 𝓘(ℝ, F) n (fun x ↦ ∑ᶠ i, f i x • g i x) x₀ := by refine _root_.contMDiffAt_finsum (f.locallyFinite.smul_left _) fun i ↦ ?_ by_cases hx : x₀ ∈ tsupport (f i) - · exact ContMDiffAt.smul ((f i).smooth.of_le le_top).contMDiffAt (hφ i hx) + · exact ContMDiffAt.smul ((f i).contMDiff.of_le le_top).contMDiffAt (hφ i hx) · exact contMDiffAt_of_not_mem (compl_subset_compl.mpr (tsupport_smul_subset_left (f i) (g i)) hx) n @@ -294,13 +291,8 @@ theorem IsSubordinate.contMDiff_finsum_smul {g : ι → M → F} (hf : f.IsSubor ContMDiff I 𝓘(ℝ, F) n fun x => ∑ᶠ i, f i x • g i x := f.contMDiff_finsum_smul fun i _ hx => (hg i).contMDiffAt <| (ho i).mem_nhds (hf i hx) -/-- If `f` is a smooth partition of unity on a set `s : Set M` subordinate to a family of open sets -`U : ι → Set M` and `g : ι → M → F` is a family of functions such that `g i` is smooth on `U i`, -then the sum `fun x ↦ ∑ᶠ i, f i x • g i x` is smooth on the whole manifold. -/ -theorem IsSubordinate.smooth_finsum_smul {g : ι → M → F} (hf : f.IsSubordinate U) - (ho : ∀ i, IsOpen (U i)) (hg : ∀ i, SmoothOn I 𝓘(ℝ, F) (g i) (U i)) : - Smooth I 𝓘(ℝ, F) fun x => ∑ᶠ i, f i x • g i x := - hf.contMDiff_finsum_smul ho hg +@[deprecated (since := "2024-11-21")] +alias IsSubordinate.smooth_finsum_smul := IsSubordinate.contMDiff_finsum_smul end IsSubordinate @@ -309,14 +301,17 @@ end SmoothPartitionOfUnity namespace BumpCovering -- Repeat variables to drop `[FiniteDimensional ℝ E]` and `[SmoothManifoldWithCorners I M]` -theorem smooth_toPartitionOfUnity {E : Type uE} [NormedAddCommGroup E] [NormedSpace ℝ E] +theorem contMDiff_toPartitionOfUnity {E : Type uE} [NormedAddCommGroup E] [NormedSpace ℝ E] {H : Type uH} [TopologicalSpace H] {I : ModelWithCorners ℝ E H} {M : Type uM} [TopologicalSpace M] [ChartedSpace H M] {s : Set M} (f : BumpCovering ι M s) - (hf : ∀ i, Smooth I 𝓘(ℝ) (f i)) (i : ι) : Smooth I 𝓘(ℝ) (f.toPartitionOfUnity i) := - (hf i).mul <| (smooth_finprod_cond fun j _ => smooth_const.sub (hf j)) <| by + (hf : ∀ i, ContMDiff I 𝓘(ℝ) ⊤ (f i)) (i : ι) : ContMDiff I 𝓘(ℝ) ⊤ (f.toPartitionOfUnity i) := + (hf i).mul <| (contMDiff_finprod_cond fun j _ => contMDiff_const.sub (hf j)) <| by simp only [Pi.sub_def, mulSupport_one_sub] exact f.locallyFinite +@[deprecated (since := "2024-11-21")] +alias smooth_toPartitionOfUnity := contMDiff_toPartitionOfUnity + variable {s : Set M} /-- A `BumpCovering` such that all functions in this covering are smooth generates a smooth @@ -326,24 +321,24 @@ In our formalization, not every `f : BumpCovering ι M s` with smooth functions `SmoothBumpCovering`; instead, a `SmoothBumpCovering` is a covering by supports of `SmoothBumpFunction`s. So, we define `BumpCovering.toSmoothPartitionOfUnity`, then reuse it in `SmoothBumpCovering.toSmoothPartitionOfUnity`. -/ -def toSmoothPartitionOfUnity (f : BumpCovering ι M s) (hf : ∀ i, Smooth I 𝓘(ℝ) (f i)) : +def toSmoothPartitionOfUnity (f : BumpCovering ι M s) (hf : ∀ i, ContMDiff I 𝓘(ℝ) ⊤ (f i)) : SmoothPartitionOfUnity ι I M s := { f.toPartitionOfUnity with - toFun := fun i => ⟨f.toPartitionOfUnity i, f.smooth_toPartitionOfUnity hf i⟩ } + toFun := fun i => ⟨f.toPartitionOfUnity i, f.contMDiff_toPartitionOfUnity hf i⟩ } @[simp] theorem toSmoothPartitionOfUnity_toPartitionOfUnity (f : BumpCovering ι M s) - (hf : ∀ i, Smooth I 𝓘(ℝ) (f i)) : + (hf : ∀ i, ContMDiff I 𝓘(ℝ) ⊤ (f i)) : (f.toSmoothPartitionOfUnity hf).toPartitionOfUnity = f.toPartitionOfUnity := rfl @[simp] -theorem coe_toSmoothPartitionOfUnity (f : BumpCovering ι M s) (hf : ∀ i, Smooth I 𝓘(ℝ) (f i)) +theorem coe_toSmoothPartitionOfUnity (f : BumpCovering ι M s) (hf : ∀ i, ContMDiff I 𝓘(ℝ) ⊤ (f i)) (i : ι) : ⇑(f.toSmoothPartitionOfUnity hf i) = f.toPartitionOfUnity i := rfl theorem IsSubordinate.toSmoothPartitionOfUnity {f : BumpCovering ι M s} {U : ι → Set M} - (h : f.IsSubordinate U) (hf : ∀ i, Smooth I 𝓘(ℝ) (f i)) : + (h : f.IsSubordinate U) (hf : ∀ i, ContMDiff I 𝓘(ℝ) ⊤ (f i)) : (f.toSmoothPartitionOfUnity hf).IsSubordinate U := h.toPartitionOfUnity @@ -457,7 +452,7 @@ alias ⟨_, IsSubordinate.toBumpCovering⟩ := isSubordinate_toBumpCovering /-- Every `SmoothBumpCovering` defines a smooth partition of unity. -/ def toSmoothPartitionOfUnity : SmoothPartitionOfUnity ι I M s := - fs.toBumpCovering.toSmoothPartitionOfUnity fun i => (fs i).smooth + fs.toBumpCovering.toSmoothPartitionOfUnity fun i => (fs i).contMDiff theorem toSmoothPartitionOfUnity_apply (i : ι) (x : M) : fs.toSmoothPartitionOfUnity i x = fs i x * ∏ᶠ (j) (_ : WellOrderingRel j i), (1 - fs j x) := @@ -511,7 +506,7 @@ theorem exists_smooth_zero_one_of_isClosed [T2Space M] [SigmaCompactSpace M] {s rcases SmoothBumpCovering.exists_isSubordinate I ht this with ⟨ι, f, hf⟩ set g := f.toSmoothPartitionOfUnity refine - ⟨⟨_, g.smooth_sum⟩, fun x hx => ?_, fun x => g.sum_eq_one, fun x => + ⟨⟨_, g.contMDiff_sum⟩, fun x hx => ?_, fun x => g.sum_eq_one, fun x => ⟨g.sum_nonneg x, g.sum_le_one x⟩⟩ suffices ∀ i, g i x = 0 by simp only [this, ContMDiffMap.coeFn_mk, finsum_zero, Pi.zero_apply] refine fun i => f.toSmoothPartitionOfUnity_zero_of_zero ?_ @@ -554,8 +549,9 @@ def single (i : ι) (s : Set M) : SmoothPartitionOfUnity ι I M s := (BumpCovering.single i s).toSmoothPartitionOfUnity fun j => by classical rcases eq_or_ne j i with (rfl | h) - · simp only [smooth_one, ContinuousMap.coe_one, BumpCovering.coe_single, Pi.single_eq_same] - · simp only [smooth_zero, BumpCovering.coe_single, Pi.single_eq_of_ne h, ContinuousMap.coe_zero] + · simp only [contMDiff_one, ContinuousMap.coe_one, BumpCovering.coe_single, Pi.single_eq_same] + · simp only [contMDiff_zero, BumpCovering.coe_single, Pi.single_eq_of_ne h, + ContinuousMap.coe_zero] instance [Inhabited ι] (s : Set M) : Inhabited (SmoothPartitionOfUnity ι I M s) := ⟨single I default s⟩ @@ -570,12 +566,12 @@ theorem exists_isSubordinate {s : Set M} (hs : IsClosed s) (U : ι → Set M) (h haveI : LocallyCompactSpace M := ChartedSpace.locallyCompactSpace H M -- porting note(https://github.com/leanprover/std4/issues/116): -- split `rcases` into `have` + `rcases` - have := BumpCovering.exists_isSubordinate_of_prop (Smooth I 𝓘(ℝ)) ?_ hs U ho hU + have := BumpCovering.exists_isSubordinate_of_prop (ContMDiff I 𝓘(ℝ) ⊤) ?_ hs U ho hU · rcases this with ⟨f, hf, hfU⟩ exact ⟨f.toSmoothPartitionOfUnity hf, hfU.toSmoothPartitionOfUnity hf⟩ · intro s t hs ht hd rcases exists_smooth_zero_one_of_isClosed I hs ht hd with ⟨f, hf⟩ - exact ⟨f, f.smooth, hf⟩ + exact ⟨f, f.contMDiff, hf⟩ theorem exists_isSubordinate_chartAt_source_of_isClosed {s : Set M} (hs : IsClosed s) : ∃ f : SmoothPartitionOfUnity s I M s, @@ -618,7 +614,7 @@ Then there exists a smooth function `g : C^∞⟮I, M; 𝓘(ℝ, F), F⟯` such See also `exists_contMDiffOn_forall_mem_convex_of_local` and `exists_smooth_forall_mem_convex_of_local_const`. -/ theorem exists_smooth_forall_mem_convex_of_local (ht : ∀ x, Convex ℝ (t x)) - (Hloc : ∀ x : M, ∃ U ∈ 𝓝 x, ∃ g : M → F, SmoothOn I 𝓘(ℝ, F) g U ∧ ∀ y ∈ U, g y ∈ t y) : + (Hloc : ∀ x : M, ∃ U ∈ 𝓝 x, ∃ g : M → F, ContMDiffOn I 𝓘(ℝ, F) ⊤ g U ∧ ∀ y ∈ U, g y ∈ t y) : ∃ g : C^∞⟮I, M; 𝓘(ℝ, F), F⟯, ∀ x, g x ∈ t x := exists_contMDiffOn_forall_mem_convex_of_local I ht Hloc @@ -631,7 +627,7 @@ theorem exists_smooth_forall_mem_convex_of_local_const (ht : ∀ x, Convex ℝ ( (Hloc : ∀ x : M, ∃ c : F, ∀ᶠ y in 𝓝 x, c ∈ t y) : ∃ g : C^∞⟮I, M; 𝓘(ℝ, F), F⟯, ∀ x, g x ∈ t x := exists_smooth_forall_mem_convex_of_local I ht fun x => let ⟨c, hc⟩ := Hloc x - ⟨_, hc, fun _ => c, smoothOn_const, fun _ => id⟩ + ⟨_, hc, fun _ => c, contMDiffOn_const, fun _ => id⟩ /-- Let `M` be a smooth σ-compact manifold with extended distance. Let `K : ι → Set M` be a locally finite family of closed sets, let `U : ι → Set M` be a family of open sets such that `K i ⊆ U i` for @@ -664,7 +660,7 @@ theorem Metric.exists_smooth_forall_closedBall_subset {M} [MetricSpace M] [Chart exact hδ i x hx lemma IsOpen.exists_msmooth_support_eq_aux {s : Set H} (hs : IsOpen s) : - ∃ f : H → ℝ, f.support = s ∧ Smooth I 𝓘(ℝ) f ∧ Set.range f ⊆ Set.Icc 0 1 := by + ∃ f : H → ℝ, f.support = s ∧ ContMDiff I 𝓘(ℝ) ⊤ f ∧ Set.range f ⊆ Set.Icc 0 1 := by have h's : IsOpen (I.symm ⁻¹' s) := I.continuous_symm.isOpen_preimage _ hs rcases h's.exists_smooth_support_eq with ⟨f, f_supp, f_diff, f_range⟩ refine ⟨f ∘ I, ?_, ?_, ?_⟩ @@ -676,11 +672,11 @@ lemma IsOpen.exists_msmooth_support_eq_aux {s : Set H} (hs : IsOpen s) : /-- Given an open set in a finite-dimensional real manifold, there exists a nonnegative smooth function with support equal to `s`. -/ theorem IsOpen.exists_msmooth_support_eq {s : Set M} (hs : IsOpen s) : - ∃ f : M → ℝ, f.support = s ∧ Smooth I 𝓘(ℝ) f ∧ ∀ x, 0 ≤ f x := by + ∃ f : M → ℝ, f.support = s ∧ ContMDiff I 𝓘(ℝ) ⊤ f ∧ ∀ x, 0 ≤ f x := by rcases SmoothPartitionOfUnity.exists_isSubordinate_chartAt_source I M with ⟨f, hf⟩ have A : ∀ (c : M), ∃ g : H → ℝ, g.support = (chartAt H c).target ∩ (chartAt H c).symm ⁻¹' s ∧ - Smooth I 𝓘(ℝ) g ∧ Set.range g ⊆ Set.Icc 0 1 := by + ContMDiff I 𝓘(ℝ) ⊤ g ∧ Set.range g ⊆ Set.Icc 0 1 := by intro i apply IsOpen.exists_msmooth_support_eq_aux exact PartialHomeomorph.isOpen_inter_preimage_symm _ hs @@ -714,7 +710,7 @@ theorem IsOpen.exists_msmooth_support_eq {s : Set M} (hs : IsOpen s) : · have : x ∉ support (f c) := by contrapose! Hx; exact subset_tsupport _ Hx rw [nmem_support] at this simp [this] - · apply SmoothPartitionOfUnity.smooth_finsum_smul + · apply SmoothPartitionOfUnity.contMDiff_finsum_smul intro c x hx apply (g_diff c (chartAt H c x)).comp exact contMDiffAt_of_mem_maximalAtlas (SmoothManifoldWithCorners.chart_mem_maximalAtlas _) @@ -727,7 +723,7 @@ exists a smooth function with support equal to `s`, taking values in `[0,1]`, an exactly on `t`. -/ theorem exists_msmooth_support_eq_eq_one_iff {s t : Set M} (hs : IsOpen s) (ht : IsClosed t) (h : t ⊆ s) : - ∃ f : M → ℝ, Smooth I 𝓘(ℝ) f ∧ range f ⊆ Icc 0 1 ∧ support f = s + ∃ f : M → ℝ, ContMDiff I 𝓘(ℝ) ⊤ f ∧ range f ⊆ Icc 0 1 ∧ support f = s ∧ (∀ x, x ∈ t ↔ f x = 1) := by /- Take `f` with support equal to `s`, and `g` with support equal to `tᶜ`. Then `f / (f + g)` satisfies the conclusion of the theorem. -/ @@ -765,7 +761,7 @@ there exists an infinitely smooth function that is equal to `0` exactly on `s` a exactly on `t`. See also `exists_smooth_zero_one_of_isClosed` for a slightly weaker version. -/ theorem exists_msmooth_zero_iff_one_iff_of_isClosed {s t : Set M} (hs : IsClosed s) (ht : IsClosed t) (hd : Disjoint s t) : - ∃ f : M → ℝ, Smooth I 𝓘(ℝ) f ∧ range f ⊆ Icc 0 1 ∧ (∀ x, x ∈ s ↔ f x = 0) + ∃ f : M → ℝ, ContMDiff I 𝓘(ℝ) ⊤ f ∧ range f ⊆ Icc 0 1 ∧ (∀ x, x ∈ s ↔ f x = 0) ∧ (∀ x, x ∈ t ↔ f x = 1) := by rcases exists_msmooth_support_eq_eq_one_iff I hs.isOpen_compl ht hd.subset_compl_left with ⟨f, f_diff, f_range, fs, ft⟩ diff --git a/Mathlib/Geometry/Manifold/Sheaf/LocallyRingedSpace.lean b/Mathlib/Geometry/Manifold/Sheaf/LocallyRingedSpace.lean index 889506e8609ea..5c91ede6dc259 100644 --- a/Mathlib/Geometry/Manifold/Sheaf/LocallyRingedSpace.lean +++ b/Mathlib/Geometry/Manifold/Sheaf/LocallyRingedSpace.lean @@ -31,6 +31,10 @@ smooth manifolds. noncomputable section universe u +/- Next line is necessary while the manifold smoothness class is not extended to `ω`. +Later, replace with `open scoped ContDiff`. -/ +local notation "∞" => (⊤ : ℕ∞) + variable {𝕜 : Type u} [NontriviallyNormedField 𝕜] [CompleteSpace 𝕜] {EM : Type*} [NormedAddCommGroup EM] [NormedSpace 𝕜 EM] {HM : Type*} [TopologicalSpace HM] (IM : ModelWithCorners 𝕜 EM HM) @@ -97,7 +101,7 @@ theorem smoothSheafCommRing.isUnit_stalk_iff {x : M} #adaptation_note /-- https://github.com/leanprover/lean4/pull/6024 was `exact`; somehow `convert` bypasess unification issues -/ convert ((contDiffAt_inv _ (hVf y)).contMDiffAt).comp y - (f.smooth.comp (smooth_inclusion hUV)).smoothAt + (f.contMDiff.comp (contMDiff_inclusion hUV)).contMDiffAt /-- The non-units of the stalk at `x` of the sheaf of smooth functions from `M` to `𝕜`, considered as a sheaf of commutative rings, are the functions whose values at `x` are zero. -/ diff --git a/Mathlib/Geometry/Manifold/Sheaf/Smooth.lean b/Mathlib/Geometry/Manifold/Sheaf/Smooth.lean index b25eee8e25950..d794651ff25d8 100644 --- a/Mathlib/Geometry/Manifold/Sheaf/Smooth.lean +++ b/Mathlib/Geometry/Manifold/Sheaf/Smooth.lean @@ -66,6 +66,10 @@ https://github.com/leanprover-community/mathlib4/pull/5726. noncomputable section open TopologicalSpace Opposite +/- Next line is necessary while the manifold smoothness class is not extended to `ω`. +Later, replace with `open scoped ContDiff`. -/ +local notation "∞" => (⊤ : ℕ∞) + universe u variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] @@ -126,7 +130,7 @@ def smoothSheaf.evalAt (x : TopCat.of M) (U : OpenNhds x) lemma smoothSheaf.eval_surjective (x : M) : Function.Surjective (smoothSheaf.eval IM I N x) := by apply TopCat.stalkToFiber_surjective intro n - exact ⟨⊤, fun _ ↦ n, smooth_const, rfl⟩ + exact ⟨⊤, fun _ ↦ n, contMDiff_const, rfl⟩ instance [Nontrivial N] (x : M) : Nontrivial ((smoothSheaf IM I M N).presheaf.stalk x) := (smoothSheaf.eval_surjective IM I N x).nontrivial @@ -138,11 +142,14 @@ variable {IM I N} smoothSheaf.eval IM I N (x : M) ((smoothSheaf IM I M N).presheaf.germ U x hx f) = f ⟨x, hx⟩ := TopCat.stalkToFiber_germ ((contDiffWithinAt_localInvariantProp ⊤).localPredicate M N) _ _ _ _ -lemma smoothSheaf.smooth_section {U : (Opens (TopCat.of M))ᵒᵖ} +lemma smoothSheaf.contMDiff_section {U : (Opens (TopCat.of M))ᵒᵖ} (f : (smoothSheaf IM I M N).presheaf.obj U) : - Smooth IM I f := + ContMDiff IM I ⊤ f := (contDiffWithinAt_localInvariantProp ⊤).section_spec _ _ _ _ +@[deprecated (since := "2024-11-21")] +alias smoothSheaf.smooth_section := smoothSheaf.contMDiff_section + end TypeCat section LieGroup @@ -213,7 +220,7 @@ noncomputable def smoothSheafCommGroup : TopCat.Sheaf CommGrp.{u} (TopCat.of M) @[to_additive "For a manifold `M` and a smooth homomorphism `φ` between abelian additive Lie groups `A`, `A'`, the 'left-composition-by-`φ`' morphism of sheaves from `smoothSheafAddCommGroup IM I M A` to `smoothSheafAddCommGroup IM I' M A'`."] -def smoothSheafCommGroup.compLeft (φ : A →* A') (hφ : Smooth I I' φ) : +def smoothSheafCommGroup.compLeft (φ : A →* A') (hφ : ContMDiff I I' ⊤ φ) : smoothSheafCommGroup IM I M A ⟶ smoothSheafCommGroup IM I' M A' := CategoryTheory.Sheaf.Hom.mk <| { app := fun _ ↦ CommGrp.ofHom <| SmoothMap.compLeftMonoidHom _ _ φ hφ diff --git a/Mathlib/Geometry/Manifold/SmoothManifoldWithCorners.lean b/Mathlib/Geometry/Manifold/SmoothManifoldWithCorners.lean index df9b1d40d1761..1e7be0aaf95d1 100644 --- a/Mathlib/Geometry/Manifold/SmoothManifoldWithCorners.lean +++ b/Mathlib/Geometry/Manifold/SmoothManifoldWithCorners.lean @@ -133,10 +133,7 @@ universe u v w u' v' w' open Set Filter Function -open scoped Manifold Filter Topology - -/-- The extended natural number `∞` -/ -scoped[Manifold] notation "∞" => (⊤ : ℕ∞) +open scoped Manifold Filter Topology ContDiff /-! ### Models with corners. -/ @@ -529,9 +526,9 @@ section contDiffGroupoid /-! ### Smooth functions on models with corners -/ -variable {m n : ℕ∞} {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} [NormedAddCommGroup E] - [NormedSpace 𝕜 E] {H : Type*} [TopologicalSpace H] {I : ModelWithCorners 𝕜 E H} {M : Type*} - [TopologicalSpace M] +variable {m n : WithTop ℕ∞} {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} + [NormedAddCommGroup E] [NormedSpace 𝕜 E] {H : Type*} [TopologicalSpace H] + {I : ModelWithCorners 𝕜 E H} {M : Type*} [TopologicalSpace M] variable (n I) in /-- Given a model with corners `(E, H)`, we define the pregroupoid of `C^n` transformations of `H` @@ -623,8 +620,8 @@ variable {E' H' : Type*} [NormedAddCommGroup E'] [NormedSpace 𝕜 E'] [Topologi /-- The product of two smooth partial homeomorphisms is smooth. -/ theorem contDiffGroupoid_prod {I : ModelWithCorners 𝕜 E H} {I' : ModelWithCorners 𝕜 E' H'} - {e : PartialHomeomorph H H} {e' : PartialHomeomorph H' H'} (he : e ∈ contDiffGroupoid ⊤ I) - (he' : e' ∈ contDiffGroupoid ⊤ I') : e.prod e' ∈ contDiffGroupoid ⊤ (I.prod I') := by + {e : PartialHomeomorph H H} {e' : PartialHomeomorph H' H'} (he : e ∈ contDiffGroupoid ∞ I) + (he' : e' ∈ contDiffGroupoid ∞ I') : e.prod e' ∈ contDiffGroupoid ∞ (I.prod I') := by cases' he with he he_symm cases' he' with he' he'_symm simp only at he he_symm he' he'_symm @@ -672,7 +669,7 @@ theorem smoothManifoldWithCorners_of_contDiffOn {𝕜 : Type*} [NontriviallyNorm {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] {H : Type*} [TopologicalSpace H] (I : ModelWithCorners 𝕜 E H) (M : Type*) [TopologicalSpace M] [ChartedSpace H M] (h : ∀ e e' : PartialHomeomorph M H, e ∈ atlas H M → e' ∈ atlas H M → - ContDiffOn 𝕜 ⊤ (I ∘ e.symm ≫ₕ e' ∘ I.symm) (I.symm ⁻¹' (e.symm ≫ₕ e').source ∩ range I)) : + ContDiffOn 𝕜 ∞ (I ∘ e.symm ≫ₕ e' ∘ I.symm) (I.symm ⁻¹' (e.symm ≫ₕ e').source ∩ range I)) : SmoothManifoldWithCorners I M where compatible := by haveI : HasGroupoid M (contDiffGroupoid ∞ I) := hasGroupoid_of_pregroupoid _ (h _ _) @@ -741,8 +738,8 @@ instance prod {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} [NormedA compatible := by rintro f g ⟨f1, hf1, f2, hf2, rfl⟩ ⟨g1, hg1, g2, hg2, rfl⟩ rw [PartialHomeomorph.prod_symm, PartialHomeomorph.prod_trans] - have h1 := (contDiffGroupoid ⊤ I).compatible hf1 hg1 - have h2 := (contDiffGroupoid ⊤ I').compatible hf2 hg2 + have h1 := (contDiffGroupoid ∞ I).compatible hf1 hg1 + have h2 := (contDiffGroupoid ∞ I').compatible hf2 hg2 exact contDiffGroupoid_prod h1 h2 end SmoothManifoldWithCorners @@ -1065,13 +1062,13 @@ open SmoothManifoldWithCorners theorem contDiffOn_extend_coord_change [ChartedSpace H M] (hf : f ∈ maximalAtlas I M) (hf' : f' ∈ maximalAtlas I M) : - ContDiffOn 𝕜 ⊤ (f.extend I ∘ (f'.extend I).symm) ((f'.extend I).symm ≫ f.extend I).source := by + ContDiffOn 𝕜 ∞ (f.extend I ∘ (f'.extend I).symm) ((f'.extend I).symm ≫ f.extend I).source := by rw [extend_coord_change_source, I.image_eq] exact (StructureGroupoid.compatible_of_mem_maximalAtlas hf' hf).1 theorem contDiffWithinAt_extend_coord_change [ChartedSpace H M] (hf : f ∈ maximalAtlas I M) (hf' : f' ∈ maximalAtlas I M) {x : E} (hx : x ∈ ((f'.extend I).symm ≫ f.extend I).source) : - ContDiffWithinAt 𝕜 ⊤ (f.extend I ∘ (f'.extend I).symm) (range I) x := by + ContDiffWithinAt 𝕜 ∞ (f.extend I ∘ (f'.extend I).symm) (range I) x := by apply (contDiffOn_extend_coord_change hf hf' x hx).mono_of_mem_nhdsWithin rw [extend_coord_change_source] at hx ⊢ obtain ⟨z, hz, rfl⟩ := hx @@ -1079,7 +1076,7 @@ theorem contDiffWithinAt_extend_coord_change [ChartedSpace H M] (hf : f ∈ maxi theorem contDiffWithinAt_extend_coord_change' [ChartedSpace H M] (hf : f ∈ maximalAtlas I M) (hf' : f' ∈ maximalAtlas I M) {x : M} (hxf : x ∈ f.source) (hxf' : x ∈ f'.source) : - ContDiffWithinAt 𝕜 ⊤ (f.extend I ∘ (f'.extend I).symm) (range I) (f'.extend I x) := by + ContDiffWithinAt 𝕜 ∞ (f.extend I ∘ (f'.extend I).symm) (range I) (f'.extend I x) := by refine contDiffWithinAt_extend_coord_change hf hf' ?_ rw [← extend_image_source_inter] exact mem_image_of_mem _ ⟨hxf', hxf⟩ @@ -1408,15 +1405,14 @@ theorem ext_coord_change_source (x x' : M) : open SmoothManifoldWithCorners theorem contDiffOn_ext_coord_change [SmoothManifoldWithCorners I M] (x x' : M) : - ContDiffOn 𝕜 ⊤ (extChartAt I x ∘ (extChartAt I x').symm) + ContDiffOn 𝕜 ∞ (extChartAt I x ∘ (extChartAt I x').symm) ((extChartAt I x').symm ≫ extChartAt I x).source := contDiffOn_extend_coord_change (chart_mem_maximalAtlas x) (chart_mem_maximalAtlas x') theorem contDiffWithinAt_ext_coord_change [SmoothManifoldWithCorners I M] (x x' : M) {y : E} (hy : y ∈ ((extChartAt I x').symm ≫ extChartAt I x).source) : - ContDiffWithinAt 𝕜 ⊤ (extChartAt I x ∘ (extChartAt I x').symm) (range I) y := - contDiffWithinAt_extend_coord_change (chart_mem_maximalAtlas x) (chart_mem_maximalAtlas x') - hy + ContDiffWithinAt 𝕜 ∞ (extChartAt I x ∘ (extChartAt I x').symm) (range I) y := + contDiffWithinAt_extend_coord_change (chart_mem_maximalAtlas x) (chart_mem_maximalAtlas x') hy variable (I I') in /-- Conjugating a function to write it in the preferred charts around `x`. diff --git a/Mathlib/Geometry/Manifold/VectorBundle/Basic.lean b/Mathlib/Geometry/Manifold/VectorBundle/Basic.lean index dab21687a47a9..3fd4222c1daba 100644 --- a/Mathlib/Geometry/Manifold/VectorBundle/Basic.lean +++ b/Mathlib/Geometry/Manifold/VectorBundle/Basic.lean @@ -212,34 +212,29 @@ theorem contMDiff_proj : ContMDiff (IB.prod 𝓘(𝕜, F)) IB n (π F E) := fun rw [contMDiffAt_totalSpace] at this exact this.1 -theorem smooth_proj : Smooth (IB.prod 𝓘(𝕜, F)) IB (π F E) := - contMDiff_proj E +@[deprecated (since := "2024-11-21")] alias smooth_proj := contMDiff_proj theorem contMDiffOn_proj {s : Set (TotalSpace F E)} : ContMDiffOn (IB.prod 𝓘(𝕜, F)) IB n (π F E) s := (Bundle.contMDiff_proj E).contMDiffOn -theorem smoothOn_proj {s : Set (TotalSpace F E)} : SmoothOn (IB.prod 𝓘(𝕜, F)) IB (π F E) s := - contMDiffOn_proj E +@[deprecated (since := "2024-11-21")] alias smoothOn_proj := contMDiffOn_proj theorem contMDiffAt_proj {p : TotalSpace F E} : ContMDiffAt (IB.prod 𝓘(𝕜, F)) IB n (π F E) p := (Bundle.contMDiff_proj E).contMDiffAt -theorem smoothAt_proj {p : TotalSpace F E} : SmoothAt (IB.prod 𝓘(𝕜, F)) IB (π F E) p := - Bundle.contMDiffAt_proj E +@[deprecated (since := "2024-11-21")] alias smoothAt_proj := contMDiffAt_proj theorem contMDiffWithinAt_proj {s : Set (TotalSpace F E)} {p : TotalSpace F E} : ContMDiffWithinAt (IB.prod 𝓘(𝕜, F)) IB n (π F E) s p := (Bundle.contMDiffAt_proj E).contMDiffWithinAt -theorem smoothWithinAt_proj {s : Set (TotalSpace F E)} {p : TotalSpace F E} : - SmoothWithinAt (IB.prod 𝓘(𝕜, F)) IB (π F E) s p := - Bundle.contMDiffWithinAt_proj E +@[deprecated (since := "2024-11-21")] alias smoothWithinAt_proj := contMDiffWithinAt_proj variable (𝕜) [∀ x, AddCommMonoid (E x)] variable [∀ x, Module 𝕜 (E x)] [VectorBundle 𝕜 F E] -theorem smooth_zeroSection : Smooth IB (IB.prod 𝓘(𝕜, F)) (zeroSection F E) := fun x ↦ by +theorem contMDiff_zeroSection : ContMDiff IB (IB.prod 𝓘(𝕜, F)) ⊤ (zeroSection F E) := fun x ↦ by unfold zeroSection rw [Bundle.contMDiffAt_section] apply (contMDiffAt_const (c := 0)).congr_of_eventuallyEq @@ -247,6 +242,8 @@ theorem smooth_zeroSection : Smooth IB (IB.prod 𝓘(𝕜, F)) (zeroSection F E) (mem_baseSet_trivializationAt F E x)] with y hy using congr_arg Prod.snd <| (trivializationAt F E x).zeroSection 𝕜 hy +@[deprecated (since := "2024-11-21")] alias smooth_zeroSection := contMDiff_zeroSection + end Bundle end @@ -272,9 +269,9 @@ topological vector bundle over `B` with fibers isomorphic to `F`, then `SmoothVe registers that the bundle is smooth, in the sense of having smooth transition functions. This is a mixin, not carrying any new data. -/ class SmoothVectorBundle : Prop where - protected smoothOn_coordChangeL : + protected contMDiffOn_coordChangeL : ∀ (e e' : Trivialization F (π F E)) [MemTrivializationAtlas e] [MemTrivializationAtlas e'], - SmoothOn IB 𝓘(𝕜, F →L[𝕜] F) (fun b : B => (e.coordChangeL 𝕜 e' b : F →L[𝕜] F)) + ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) ⊤ (fun b : B => (e.coordChangeL 𝕜 e' b : F →L[𝕜] F)) (e.baseSet ∩ e'.baseSet) variable [SmoothVectorBundle F E IB] @@ -284,27 +281,23 @@ section SmoothCoordChange variable {F E} variable (e e' : Trivialization F (π F E)) [MemTrivializationAtlas e] [MemTrivializationAtlas e'] -theorem smoothOn_coordChangeL : - SmoothOn IB 𝓘(𝕜, F →L[𝕜] F) (fun b : B => (e.coordChangeL 𝕜 e' b : F →L[𝕜] F)) +theorem contMDiffOn_coordChangeL : + ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) n (fun b : B => (e.coordChangeL 𝕜 e' b : F →L[𝕜] F)) (e.baseSet ∩ e'.baseSet) := - SmoothVectorBundle.smoothOn_coordChangeL e e' + (SmoothVectorBundle.contMDiffOn_coordChangeL e e').of_le le_top -theorem smoothOn_symm_coordChangeL : - SmoothOn IB 𝓘(𝕜, F →L[𝕜] F) (fun b : B => ((e.coordChangeL 𝕜 e' b).symm : F →L[𝕜] F)) +theorem contMDiffOn_symm_coordChangeL : + ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) n (fun b : B => ((e.coordChangeL 𝕜 e' b).symm : F →L[𝕜] F)) (e.baseSet ∩ e'.baseSet) := by + apply ContMDiffOn.of_le _ le_top rw [inter_comm] - refine (SmoothVectorBundle.smoothOn_coordChangeL e' e).congr fun b hb ↦ ?_ + refine (SmoothVectorBundle.contMDiffOn_coordChangeL e' e).congr fun b hb ↦ ?_ rw [e.symm_coordChangeL e' hb] -theorem contMDiffOn_coordChangeL : - ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) n (fun b : B => (e.coordChangeL 𝕜 e' b : F →L[𝕜] F)) - (e.baseSet ∩ e'.baseSet) := - (smoothOn_coordChangeL e e').of_le le_top +@[deprecated (since := "2024-11-21")] alias smoothOn_coordChangeL := contMDiffOn_coordChangeL +@[deprecated (since := "2024-11-21")] +alias smoothOn_symm_coordChangeL := contMDiffOn_symm_coordChangeL -theorem contMDiffOn_symm_coordChangeL : - ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) n (fun b : B => ((e.coordChangeL 𝕜 e' b).symm : F →L[𝕜] F)) - (e.baseSet ∩ e'.baseSet) := - (smoothOn_symm_coordChangeL e e').of_le le_top variable {e e'} @@ -313,9 +306,7 @@ theorem contMDiffAt_coordChangeL {x : B} (h : x ∈ e.baseSet) (h' : x ∈ e'.ba (contMDiffOn_coordChangeL e e').contMDiffAt <| (e.open_baseSet.inter e'.open_baseSet).mem_nhds ⟨h, h'⟩ -theorem smoothAt_coordChangeL {x : B} (h : x ∈ e.baseSet) (h' : x ∈ e'.baseSet) : - SmoothAt IB 𝓘(𝕜, F →L[𝕜] F) (fun b : B => (e.coordChangeL 𝕜 e' b : F →L[𝕜] F)) x := - contMDiffAt_coordChangeL h h' +@[deprecated (since := "2024-11-21")] alias smoothAt_coordChangeL := contMDiffAt_coordChangeL variable {s : Set M} {f : M → B} {g : M → F} {x : M} @@ -339,25 +330,17 @@ protected theorem ContMDiff.coordChangeL ContMDiff IM 𝓘(𝕜, F →L[𝕜] F) n (fun y ↦ (e.coordChangeL 𝕜 e' (f y) : F →L[𝕜] F)) := fun x ↦ (hf x).coordChangeL (he x) (he' x) -protected nonrec theorem SmoothWithinAt.coordChangeL - (hf : SmoothWithinAt IM IB f s x) (he : f x ∈ e.baseSet) (he' : f x ∈ e'.baseSet) : - SmoothWithinAt IM 𝓘(𝕜, F →L[𝕜] F) (fun y ↦ (e.coordChangeL 𝕜 e' (f y) : F →L[𝕜] F)) s x := - hf.coordChangeL he he' +@[deprecated (since := "2024-11-21")] +alias SmoothWithinAt.coordChangeL := ContMDiffWithinAt.coordChangeL -protected nonrec theorem SmoothAt.coordChangeL - (hf : SmoothAt IM IB f x) (he : f x ∈ e.baseSet) (he' : f x ∈ e'.baseSet) : - SmoothAt IM 𝓘(𝕜, F →L[𝕜] F) (fun y ↦ (e.coordChangeL 𝕜 e' (f y) : F →L[𝕜] F)) x := - hf.coordChangeL he he' +@[deprecated (since := "2024-11-21")] +alias SmoothAt.coordChangeL := ContMDiffAt.coordChangeL -protected nonrec theorem SmoothOn.coordChangeL - (hf : SmoothOn IM IB f s) (he : MapsTo f s e.baseSet) (he' : MapsTo f s e'.baseSet) : - SmoothOn IM 𝓘(𝕜, F →L[𝕜] F) (fun y ↦ (e.coordChangeL 𝕜 e' (f y) : F →L[𝕜] F)) s := - hf.coordChangeL he he' +@[deprecated (since := "2024-11-21")] +alias SmoothOn.coordChangeL := ContMDiffOn.coordChangeL -protected nonrec theorem Smooth.coordChangeL - (hf : Smooth IM IB f) (he : ∀ x, f x ∈ e.baseSet) (he' : ∀ x, f x ∈ e'.baseSet) : - Smooth IM 𝓘(𝕜, F →L[𝕜] F) (fun y ↦ (e.coordChangeL 𝕜 e' (f y) : F →L[𝕜] F)) := - hf.coordChangeL he he' +@[deprecated (since := "2024-11-21")] +alias Smooth.coordChangeL := ContMDiff.coordChangeL protected theorem ContMDiffWithinAt.coordChange (hf : ContMDiffWithinAt IM IB n f s x) (hg : ContMDiffWithinAt IM 𝓘(𝕜, F) n g s x) @@ -386,26 +369,17 @@ protected theorem ContMDiff.coordChange (hf : ContMDiff IM IB n f) ContMDiff IM 𝓘(𝕜, F) n (fun y ↦ e.coordChange e' (f y) (g y)) := fun x ↦ (hf x).coordChange (hg x) (he x) (he' x) -protected nonrec theorem SmoothWithinAt.coordChange - (hf : SmoothWithinAt IM IB f s x) (hg : SmoothWithinAt IM 𝓘(𝕜, F) g s x) - (he : f x ∈ e.baseSet) (he' : f x ∈ e'.baseSet) : - SmoothWithinAt IM 𝓘(𝕜, F) (fun y ↦ e.coordChange e' (f y) (g y)) s x := - hf.coordChange hg he he' +@[deprecated (since := "2024-11-21")] +alias SmoothWithinAt.coordChange := ContMDiffWithinAt.coordChange -protected nonrec theorem SmoothAt.coordChange (hf : SmoothAt IM IB f x) - (hg : SmoothAt IM 𝓘(𝕜, F) g x) (he : f x ∈ e.baseSet) (he' : f x ∈ e'.baseSet) : - SmoothAt IM 𝓘(𝕜, F) (fun y ↦ e.coordChange e' (f y) (g y)) x := - hf.coordChange hg he he' +@[deprecated (since := "2024-11-21")] +alias SmoothAt.coordChange := ContMDiffAt.coordChange -protected nonrec theorem SmoothOn.coordChange (hf : SmoothOn IM IB f s) - (hg : SmoothOn IM 𝓘(𝕜, F) g s) (he : MapsTo f s e.baseSet) (he' : MapsTo f s e'.baseSet) : - SmoothOn IM 𝓘(𝕜, F) (fun y ↦ e.coordChange e' (f y) (g y)) s := - hf.coordChange hg he he' +@[deprecated (since := "2024-11-21")] +alias SmoothOn.coordChange := ContMDiffOn.coordChange -protected theorem Smooth.coordChange (hf : Smooth IM IB f) - (hg : Smooth IM 𝓘(𝕜, F) g) (he : ∀ x, f x ∈ e.baseSet) (he' : ∀ x, f x ∈ e'.baseSet) : - Smooth IM 𝓘(𝕜, F) (fun y ↦ e.coordChange e' (f y) (g y)) := fun x ↦ - (hf x).coordChange (hg x) (he x) (he' x) +@[deprecated (since := "2024-11-21")] +alias Smooth.coordChange := ContMDiff.coordChange variable (e e') @@ -458,8 +432,8 @@ instance SmoothFiberwiseLinear.hasGroupoid : haveI : MemTrivializationAtlas e := ⟨he⟩ haveI : MemTrivializationAtlas e' := ⟨he'⟩ rw [mem_smoothFiberwiseLinear_iff] - refine ⟨_, _, e.open_baseSet.inter e'.open_baseSet, smoothOn_coordChangeL e e', - smoothOn_symm_coordChangeL e e', ?_⟩ + refine ⟨_, _, e.open_baseSet.inter e'.open_baseSet, contMDiffOn_coordChangeL e e', + contMDiffOn_symm_coordChangeL e e', ?_⟩ refine PartialHomeomorph.eqOnSourceSetoid.symm ⟨?_, ?_⟩ · simp only [e.symm_trans_source_eq e', FiberwiseLinear.partialHomeomorph, trans_toPartialEquiv, symm_toPartialEquiv] @@ -478,10 +452,10 @@ instance Bundle.TotalSpace.smoothManifoldWithCorners [SmoothManifoldWithCorners refine ⟨ContMDiffOn.congr ?_ (EqOnSource.eqOn heφ), ContMDiffOn.congr ?_ (EqOnSource.eqOn (EqOnSource.symm' heφ))⟩ · rw [EqOnSource.source_eq heφ] - apply smoothOn_fst.prod_mk + apply contMDiffOn_fst.prod_mk exact (hφ.comp contMDiffOn_fst <| prod_subset_preimage_fst _ _).clm_apply contMDiffOn_snd · rw [EqOnSource.target_eq heφ] - apply smoothOn_fst.prod_mk + apply contMDiffOn_fst.prod_mk exact (h2φ.comp contMDiffOn_fst <| prod_subset_preimage_fst _ _).clm_apply contMDiffOn_snd section @@ -517,41 +491,36 @@ theorem Trivialization.contMDiff_iff {f : M → TotalSpace F E} (he : ∀ x, f x ContMDiff IM 𝓘(𝕜, F) n (fun x ↦ (e (f x)).2) := (forall_congr' fun x ↦ e.contMDiffAt_iff (he x)).trans forall_and -theorem Trivialization.smoothWithinAt_iff {f : M → TotalSpace F E} {s : Set M} {x₀ : M} - (he : f x₀ ∈ e.source) : - SmoothWithinAt IM (IB.prod 𝓘(𝕜, F)) f s x₀ ↔ - SmoothWithinAt IM IB (fun x => (f x).proj) s x₀ ∧ - SmoothWithinAt IM 𝓘(𝕜, F) (fun x ↦ (e (f x)).2) s x₀ := - e.contMDiffWithinAt_iff he +@[deprecated (since := "2024-11-21")] +alias Trivialization.smoothWithinAt_iff := Trivialization.contMDiffWithinAt_iff -theorem Trivialization.smoothAt_iff {f : M → TotalSpace F E} {x₀ : M} (he : f x₀ ∈ e.source) : - SmoothAt IM (IB.prod 𝓘(𝕜, F)) f x₀ ↔ - SmoothAt IM IB (fun x => (f x).proj) x₀ ∧ SmoothAt IM 𝓘(𝕜, F) (fun x ↦ (e (f x)).2) x₀ := - e.contMDiffAt_iff he +@[deprecated (since := "2024-11-21")] +alias Trivialization.smoothAt_iff := Trivialization.contMDiffAt_iff -theorem Trivialization.smoothOn_iff {f : M → TotalSpace F E} {s : Set M} - (he : MapsTo f s e.source) : - SmoothOn IM (IB.prod 𝓘(𝕜, F)) f s ↔ - SmoothOn IM IB (fun x => (f x).proj) s ∧ SmoothOn IM 𝓘(𝕜, F) (fun x ↦ (e (f x)).2) s := - e.contMDiffOn_iff he - -theorem Trivialization.smooth_iff {f : M → TotalSpace F E} (he : ∀ x, f x ∈ e.source) : - Smooth IM (IB.prod 𝓘(𝕜, F)) f ↔ - Smooth IM IB (fun x => (f x).proj) ∧ Smooth IM 𝓘(𝕜, F) (fun x ↦ (e (f x)).2) := - e.contMDiff_iff he - -theorem Trivialization.smoothOn (e : Trivialization F (π F E)) [MemTrivializationAtlas e] : - SmoothOn (IB.prod 𝓘(𝕜, F)) (IB.prod 𝓘(𝕜, F)) e e.source := by - have : SmoothOn (IB.prod 𝓘(𝕜, F)) (IB.prod 𝓘(𝕜, F)) id e.source := smoothOn_id - rw [e.smoothOn_iff (mapsTo_id _)] at this +@[deprecated (since := "2024-11-21")] +alias Trivialization.smoothOn_iff := Trivialization.contMDiffOn_iff + +@[deprecated (since := "2024-11-21")] +alias Trivialization.smooth_iff := Trivialization.contMDiff_iff + +theorem Trivialization.contMDiffOn (e : Trivialization F (π F E)) [MemTrivializationAtlas e] : + ContMDiffOn (IB.prod 𝓘(𝕜, F)) (IB.prod 𝓘(𝕜, F)) ⊤ e e.source := by + have : ContMDiffOn (IB.prod 𝓘(𝕜, F)) (IB.prod 𝓘(𝕜, F)) ⊤ id e.source := contMDiffOn_id + rw [e.contMDiffOn_iff (mapsTo_id _)] at this exact (this.1.prod_mk this.2).congr fun x hx ↦ (e.mk_proj_snd hx).symm -theorem Trivialization.smoothOn_symm (e : Trivialization F (π F E)) [MemTrivializationAtlas e] : - SmoothOn (IB.prod 𝓘(𝕜, F)) (IB.prod 𝓘(𝕜, F)) e.toPartialHomeomorph.symm e.target := by - rw [e.smoothOn_iff e.toPartialHomeomorph.symm_mapsTo] - refine ⟨smoothOn_fst.congr fun x hx ↦ e.proj_symm_apply hx, smoothOn_snd.congr fun x hx ↦ ?_⟩ +theorem Trivialization.contMDiffOn_symm (e : Trivialization F (π F E)) [MemTrivializationAtlas e] : + ContMDiffOn (IB.prod 𝓘(𝕜, F)) (IB.prod 𝓘(𝕜, F)) ⊤ e.toPartialHomeomorph.symm e.target := by + rw [e.contMDiffOn_iff e.toPartialHomeomorph.symm_mapsTo] + refine ⟨contMDiffOn_fst.congr fun x hx ↦ e.proj_symm_apply hx, + contMDiffOn_snd.congr fun x hx ↦ ?_⟩ rw [e.apply_symm_apply hx] +@[deprecated (since := "2024-11-21")] alias Trivialization.smoothOn := Trivialization.contMDiffOn + +@[deprecated (since := "2024-11-21")] +alias Trivialization.smoothOn_symm := Trivialization.contMDiffOn_symm + end /-! ### Core construction for smooth vector bundles -/ @@ -563,21 +532,24 @@ variable {ι : Type*} (Z : VectorBundleCore 𝕜 B F ι) /-- Mixin for a `VectorBundleCore` stating smoothness (of transition functions). -/ class IsSmooth (IB : ModelWithCorners 𝕜 EB HB) : Prop where - smoothOn_coordChange : - ∀ i j, SmoothOn IB 𝓘(𝕜, F →L[𝕜] F) (Z.coordChange i j) (Z.baseSet i ∩ Z.baseSet j) + contMDiffOn_coordChange : + ∀ i j, ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) ⊤ (Z.coordChange i j) (Z.baseSet i ∩ Z.baseSet j) -theorem smoothOn_coordChange (IB : ModelWithCorners 𝕜 EB HB) [h : Z.IsSmooth IB] (i j : ι) : - SmoothOn IB 𝓘(𝕜, F →L[𝕜] F) (Z.coordChange i j) (Z.baseSet i ∩ Z.baseSet j) := +theorem contMDiffOn_coordChange (IB : ModelWithCorners 𝕜 EB HB) [h : Z.IsSmooth IB] (i j : ι) : + ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) ⊤ (Z.coordChange i j) (Z.baseSet i ∩ Z.baseSet j) := h.1 i j +@[deprecated (since := "2024-11-21")] +alias smoothOn_coordChange := contMDiffOn_coordChange + variable [Z.IsSmooth IB] /-- If a `VectorBundleCore` has the `IsSmooth` mixin, then the vector bundle constructed from it is a smooth vector bundle. -/ instance smoothVectorBundle : SmoothVectorBundle F Z.Fiber IB where - smoothOn_coordChangeL := by + contMDiffOn_coordChangeL := by rintro - - ⟨i, rfl⟩ ⟨i', rfl⟩ - refine (Z.smoothOn_coordChange IB i i').congr fun b hb ↦ ?_ + refine (Z.contMDiffOn_coordChange IB i i').congr fun b hb ↦ ?_ ext v exact Z.localTriv_coordChange_eq i i' hb v @@ -587,12 +559,12 @@ end VectorBundleCore /-- A trivial vector bundle over a smooth manifold is a smooth vector bundle. -/ instance Bundle.Trivial.smoothVectorBundle : SmoothVectorBundle F (Bundle.Trivial B F) IB where - smoothOn_coordChangeL := by + contMDiffOn_coordChangeL := by intro e e' he he' obtain rfl := Bundle.Trivial.eq_trivialization B F e obtain rfl := Bundle.Trivial.eq_trivialization B F e' simp_rw [Bundle.Trivial.trivialization.coordChangeL] - exact smooth_const.smoothOn + exact contMDiff_const.contMDiffOn /-! ### Direct sums of smooth vector bundles -/ @@ -613,15 +585,14 @@ variable [SmoothManifoldWithCorners IB B] /-- The direct sum of two smooth vector bundles over the same base is a smooth vector bundle. -/ instance Bundle.Prod.smoothVectorBundle : SmoothVectorBundle (F₁ × F₂) (E₁ ×ᵇ E₂) IB where - smoothOn_coordChangeL := by + contMDiffOn_coordChangeL := by rintro _ _ ⟨e₁, e₂, i₁, i₂, rfl⟩ ⟨e₁', e₂', i₁', i₂', rfl⟩ - rw [SmoothOn] refine ContMDiffOn.congr ?_ (e₁.coordChangeL_prod 𝕜 e₁' e₂ e₂') refine ContMDiffOn.clm_prodMap ?_ ?_ - · refine (smoothOn_coordChangeL e₁ e₁').mono ?_ + · refine (contMDiffOn_coordChangeL e₁ e₁').mono ?_ simp only [Trivialization.baseSet_prod, mfld_simps] mfld_set_tac - · refine (smoothOn_coordChangeL e₂ e₂').mono ?_ + · refine (contMDiffOn_coordChangeL e₂ e₂').mono ?_ simp only [Trivialization.baseSet_prod, mfld_simps] mfld_set_tac @@ -641,7 +612,7 @@ class IsSmooth (a : VectorPrebundle 𝕜 F E) : Prop where exists_smoothCoordChange : ∀ᵉ (e ∈ a.pretrivializationAtlas) (e' ∈ a.pretrivializationAtlas), ∃ f : B → F →L[𝕜] F, - SmoothOn IB 𝓘(𝕜, F →L[𝕜] F) f (e.baseSet ∩ e'.baseSet) ∧ + ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) ⊤ f (e.baseSet ∩ e'.baseSet) ∧ ∀ (b : B) (_ : b ∈ e.baseSet ∩ e'.baseSet) (v : F), f b v = (e' ⟨b, e.symm b v⟩).2 @@ -655,11 +626,14 @@ noncomputable def smoothCoordChange (he : e ∈ a.pretrivializationAtlas) (he' : e' ∈ a.pretrivializationAtlas) (b : B) : F →L[𝕜] F := Classical.choose (ha.exists_smoothCoordChange e he e' he') b -theorem smoothOn_smoothCoordChange (he : e ∈ a.pretrivializationAtlas) +theorem contMDiffOn_smoothCoordChange (he : e ∈ a.pretrivializationAtlas) (he' : e' ∈ a.pretrivializationAtlas) : - SmoothOn IB 𝓘(𝕜, F →L[𝕜] F) (a.smoothCoordChange IB he he') (e.baseSet ∩ e'.baseSet) := + ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) ⊤ (a.smoothCoordChange IB he he') (e.baseSet ∩ e'.baseSet) := (Classical.choose_spec (ha.exists_smoothCoordChange e he e' he')).1 +@[deprecated (since := "2024-11-21")] +alias smoothOn_smoothCoordChange := contMDiffOn_smoothCoordChange + theorem smoothCoordChange_apply (he : e ∈ a.pretrivializationAtlas) (he' : e' ∈ a.pretrivializationAtlas) {b : B} (hb : b ∈ e.baseSet ∩ e'.baseSet) (v : F) : a.smoothCoordChange IB he he' b v = (e' ⟨b, e.symm b v⟩).2 := @@ -678,9 +652,9 @@ variable (IB) in theorem smoothVectorBundle : @SmoothVectorBundle _ _ F E _ _ _ _ _ _ IB _ _ _ _ _ _ a.totalSpaceTopology _ a.toFiberBundle a.toVectorBundle := letI := a.totalSpaceTopology; letI := a.toFiberBundle; letI := a.toVectorBundle - { smoothOn_coordChangeL := by + { contMDiffOn_coordChangeL := by rintro _ _ ⟨e, he, rfl⟩ ⟨e', he', rfl⟩ - refine (a.smoothOn_smoothCoordChange he he').congr ?_ + refine (a.contMDiffOn_smoothCoordChange he he').congr ?_ intro b hb ext v rw [a.smoothCoordChange_apply he he' hb v, ContinuousLinearEquiv.coe_coe, diff --git a/Mathlib/Geometry/Manifold/VectorBundle/FiberwiseLinear.lean b/Mathlib/Geometry/Manifold/VectorBundle/FiberwiseLinear.lean index 2a0e077c860aa..0bc3d2285bba8 100644 --- a/Mathlib/Geometry/Manifold/VectorBundle/FiberwiseLinear.lean +++ b/Mathlib/Geometry/Manifold/VectorBundle/FiberwiseLinear.lean @@ -103,14 +103,14 @@ fiberwise linear partial homeomorphism. -/ theorem SmoothFiberwiseLinear.locality_aux₁ (e : PartialHomeomorph (B × F) (B × F)) (h : ∀ p ∈ e.source, ∃ s : Set (B × F), IsOpen s ∧ p ∈ s ∧ ∃ (φ : B → F ≃L[𝕜] F) (u : Set B) (hu : IsOpen u) - (hφ : SmoothOn IB 𝓘(𝕜, F →L[𝕜] F) (fun x => (φ x : F →L[𝕜] F)) u) - (h2φ : SmoothOn IB 𝓘(𝕜, F →L[𝕜] F) (fun x => ((φ x).symm : F →L[𝕜] F)) u), + (hφ : ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) ⊤ (fun x => (φ x : F →L[𝕜] F)) u) + (h2φ : ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) ⊤ (fun x => ((φ x).symm : F →L[𝕜] F)) u), (e.restr s).EqOnSource (FiberwiseLinear.partialHomeomorph φ hu hφ.continuousOn h2φ.continuousOn)) : ∃ U : Set B, e.source = U ×ˢ univ ∧ ∀ x ∈ U, ∃ (φ : B → F ≃L[𝕜] F) (u : Set B) (hu : IsOpen u) (_huU : u ⊆ U) (_hux : x ∈ u), - ∃ (hφ : SmoothOn IB 𝓘(𝕜, F →L[𝕜] F) (fun x => (φ x : F →L[𝕜] F)) u) - (h2φ : SmoothOn IB 𝓘(𝕜, F →L[𝕜] F) (fun x => ((φ x).symm : F →L[𝕜] F)) u), + ∃ (hφ : ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) ⊤ (fun x => (φ x : F →L[𝕜] F)) u) + (h2φ : ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) ⊤ (fun x => ((φ x).symm : F →L[𝕜] F)) u), (e.restr (u ×ˢ univ)).EqOnSource (FiberwiseLinear.partialHomeomorph φ hu hφ.continuousOn h2φ.continuousOn) := by rw [SetCoe.forall'] at h @@ -155,13 +155,13 @@ theorem SmoothFiberwiseLinear.locality_aux₂ (e : PartialHomeomorph (B × F) (B (hU : e.source = U ×ˢ univ) (h : ∀ x ∈ U, ∃ (φ : B → F ≃L[𝕜] F) (u : Set B) (hu : IsOpen u) (_hUu : u ⊆ U) (_hux : x ∈ u) - (hφ : SmoothOn IB 𝓘(𝕜, F →L[𝕜] F) (fun x => (φ x : F →L[𝕜] F)) u) - (h2φ : SmoothOn IB 𝓘(𝕜, F →L[𝕜] F) (fun x => ((φ x).symm : F →L[𝕜] F)) u), + (hφ : ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) ⊤ (fun x => (φ x : F →L[𝕜] F)) u) + (h2φ : ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) ⊤ (fun x => ((φ x).symm : F →L[𝕜] F)) u), (e.restr (u ×ˢ univ)).EqOnSource (FiberwiseLinear.partialHomeomorph φ hu hφ.continuousOn h2φ.continuousOn)) : ∃ (Φ : B → F ≃L[𝕜] F) (U : Set B) (hU₀ : IsOpen U) (hΦ : - SmoothOn IB 𝓘(𝕜, F →L[𝕜] F) (fun x => (Φ x : F →L[𝕜] F)) U) (h2Φ : - SmoothOn IB 𝓘(𝕜, F →L[𝕜] F) (fun x => ((Φ x).symm : F →L[𝕜] F)) U), + ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) ⊤ (fun x => (Φ x : F →L[𝕜] F)) U) (h2Φ : + ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) ⊤ (fun x => ((Φ x).symm : F →L[𝕜] F)) U), e.EqOnSource (FiberwiseLinear.partialHomeomorph Φ hU₀ hΦ.continuousOn h2Φ.continuousOn) := by classical rw [SetCoe.forall'] at h @@ -192,14 +192,14 @@ theorem SmoothFiberwiseLinear.locality_aux₂ (e : PartialHomeomorph (B × F) (B intro x y hyu refine (hΦ y (hUu x hyu)).trans ?_ exact iUnionLift_mk ⟨y, hyu⟩ _ - have hΦ : SmoothOn IB 𝓘(𝕜, F →L[𝕜] F) (fun y => (Φ y : F →L[𝕜] F)) U := by + have hΦ : ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) ⊤ (fun y => (Φ y : F →L[𝕜] F)) U := by apply contMDiffOn_of_locally_contMDiffOn intro x hx refine ⟨u ⟨x, hx⟩, hu ⟨x, hx⟩, hux _, ?_⟩ refine (ContMDiffOn.congr (hφ ⟨x, hx⟩) ?_).mono inter_subset_right intro y hy rw [hΦφ ⟨x, hx⟩ y hy] - have h2Φ : SmoothOn IB 𝓘(𝕜, F →L[𝕜] F) (fun y => ((Φ y).symm : F →L[𝕜] F)) U := by + have h2Φ : ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) ⊤ (fun y => ((Φ y).symm : F →L[𝕜] F)) U := by apply contMDiffOn_of_locally_contMDiffOn intro x hx refine ⟨u ⟨x, hx⟩, hu ⟨x, hx⟩, hux _, ?_⟩ @@ -221,13 +221,13 @@ variable {F B IB} in -- in `smoothFiberwiseLinear` are quite slow, even with this change) private theorem mem_aux {e : PartialHomeomorph (B × F) (B × F)} : (e ∈ ⋃ (φ : B → F ≃L[𝕜] F) (U : Set B) (hU : IsOpen U) - (hφ : SmoothOn IB 𝓘(𝕜, F →L[𝕜] F) (fun x => φ x : B → F →L[𝕜] F) U) - (h2φ : SmoothOn IB 𝓘(𝕜, F →L[𝕜] F) (fun x => (φ x).symm : B → F →L[𝕜] F) U), + (hφ : ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) ⊤ (fun x => φ x : B → F →L[𝕜] F) U) + (h2φ : ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) ⊤ (fun x => (φ x).symm : B → F →L[𝕜] F) U), {e | e.EqOnSource (FiberwiseLinear.partialHomeomorph φ hU hφ.continuousOn h2φ.continuousOn)}) ↔ ∃ (φ : B → F ≃L[𝕜] F) (U : Set B) (hU : IsOpen U) - (hφ : SmoothOn IB 𝓘(𝕜, F →L[𝕜] F) (fun x => φ x : B → F →L[𝕜] F) U) - (h2φ : SmoothOn IB 𝓘(𝕜, F →L[𝕜] F) (fun x => (φ x).symm : B → F →L[𝕜] F) U), + (hφ : ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) ⊤ (fun x => φ x : B → F →L[𝕜] F) U) + (h2φ : ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) ⊤ (fun x => (φ x).symm : B → F →L[𝕜] F) U), e.EqOnSource (FiberwiseLinear.partialHomeomorph φ hU hφ.continuousOn h2φ.continuousOn) := by simp only [mem_iUnion, mem_setOf_eq] @@ -239,8 +239,8 @@ to the vector bundle belong to this groupoid. -/ def smoothFiberwiseLinear : StructureGroupoid (B × F) where members := ⋃ (φ : B → F ≃L[𝕜] F) (U : Set B) (hU : IsOpen U) - (hφ : SmoothOn IB 𝓘(𝕜, F →L[𝕜] F) (fun x => φ x : B → F →L[𝕜] F) U) - (h2φ : SmoothOn IB 𝓘(𝕜, F →L[𝕜] F) (fun x => (φ x).symm : B → F →L[𝕜] F) U), + (hφ : ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) ⊤ (fun x => φ x : B → F →L[𝕜] F) U) + (h2φ : ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) ⊤ (fun x => (φ x).symm : B → F →L[𝕜] F) U), {e | e.EqOnSource (FiberwiseLinear.partialHomeomorph φ hU hφ.continuousOn h2φ.continuousOn)} trans' := by simp only [mem_aux] @@ -248,11 +248,11 @@ def smoothFiberwiseLinear : StructureGroupoid (B × F) where refine ⟨fun b => (φ b).trans (φ' b), _, hU.inter hU', ?_, ?_, Setoid.trans (PartialHomeomorph.EqOnSource.trans' heφ heφ') ⟨?_, ?_⟩⟩ · show - SmoothOn IB 𝓘(𝕜, F →L[𝕜] F) + ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) ⊤ (fun x : B => (φ' x).toContinuousLinearMap ∘L (φ x).toContinuousLinearMap) (U ∩ U') exact (hφ'.mono inter_subset_right).clm_comp (hφ.mono inter_subset_left) · show - SmoothOn IB 𝓘(𝕜, F →L[𝕜] F) + ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) ⊤ (fun x : B => (φ x).symm.toContinuousLinearMap ∘L (φ' x).symm.toContinuousLinearMap) (U ∩ U') exact (h2φ.mono inter_subset_left).clm_comp (h2φ'.mono inter_subset_right) @@ -267,8 +267,8 @@ def smoothFiberwiseLinear : StructureGroupoid (B × F) where exact hφ id_mem' := by simp_rw [mem_aux] - refine ⟨fun _ ↦ ContinuousLinearEquiv.refl 𝕜 F, univ, isOpen_univ, smoothOn_const, - smoothOn_const, ⟨?_, fun b _hb ↦ rfl⟩⟩ + refine ⟨fun _ ↦ ContinuousLinearEquiv.refl 𝕜 F, univ, isOpen_univ, contMDiffOn_const, + contMDiffOn_const, ⟨?_, fun b _hb ↦ rfl⟩⟩ simp only [FiberwiseLinear.partialHomeomorph, PartialHomeomorph.refl_partialEquiv, PartialEquiv.refl_source, univ_prod_univ] locality' := by @@ -286,7 +286,7 @@ def smoothFiberwiseLinear : StructureGroupoid (B × F) where theorem mem_smoothFiberwiseLinear_iff (e : PartialHomeomorph (B × F) (B × F)) : e ∈ smoothFiberwiseLinear B F IB ↔ ∃ (φ : B → F ≃L[𝕜] F) (U : Set B) (hU : IsOpen U) (hφ : - SmoothOn IB 𝓘(𝕜, F →L[𝕜] F) (fun x => φ x : B → F →L[𝕜] F) U) (h2φ : - SmoothOn IB 𝓘(𝕜, F →L[𝕜] F) (fun x => (φ x).symm : B → F →L[𝕜] F) U), + ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) ⊤ (fun x => φ x : B → F →L[𝕜] F) U) (h2φ : + ContMDiffOn IB 𝓘(𝕜, F →L[𝕜] F) ⊤ (fun x => (φ x).symm : B → F →L[𝕜] F) U), e.EqOnSource (FiberwiseLinear.partialHomeomorph φ hU hφ.continuousOn h2φ.continuousOn) := mem_aux diff --git a/Mathlib/Geometry/Manifold/VectorBundle/Hom.lean b/Mathlib/Geometry/Manifold/VectorBundle/Hom.lean index f56284f714605..d00cefedfa42b 100644 --- a/Mathlib/Geometry/Manifold/VectorBundle/Hom.lean +++ b/Mathlib/Geometry/Manifold/VectorBundle/Hom.lean @@ -41,16 +41,19 @@ variable {𝕜 B F₁ F₂ M : Type*} {E₁ : B → Type*} {E₂ : B → Type*} local notation "LE₁E₂" => TotalSpace (F₁ →L[𝕜] F₂) (Bundle.ContinuousLinearMap (RingHom.id 𝕜) E₁ E₂) -- Porting note (https://github.com/leanprover-community/mathlib4/issues/11083): moved slow parts to separate lemmas -theorem smoothOn_continuousLinearMapCoordChange +theorem contMDiffOn_continuousLinearMapCoordChange [SmoothVectorBundle F₁ E₁ IB] [SmoothVectorBundle F₂ E₂ IB] [MemTrivializationAtlas e₁] [MemTrivializationAtlas e₁'] [MemTrivializationAtlas e₂] [MemTrivializationAtlas e₂'] : - SmoothOn IB 𝓘(𝕜, (F₁ →L[𝕜] F₂) →L[𝕜] F₁ →L[𝕜] F₂) + ContMDiffOn IB 𝓘(𝕜, (F₁ →L[𝕜] F₂) →L[𝕜] F₁ →L[𝕜] F₂) ⊤ (continuousLinearMapCoordChange (RingHom.id 𝕜) e₁ e₁' e₂ e₂') (e₁.baseSet ∩ e₂.baseSet ∩ (e₁'.baseSet ∩ e₂'.baseSet)) := by - have h₁ := smoothOn_coordChangeL (IB := IB) e₁' e₁ - have h₂ := smoothOn_coordChangeL (IB := IB) e₂ e₂' + have h₁ := contMDiffOn_coordChangeL (IB := IB) e₁' e₁ (n := ⊤) + have h₂ := contMDiffOn_coordChangeL (IB := IB) e₂ e₂' (n := ⊤) refine (h₁.mono ?_).cle_arrowCongr (h₂.mono ?_) <;> mfld_set_tac +@[deprecated (since := "2024-11-21")] +alias smoothOn_continuousLinearMapCoordChange := contMDiffOn_continuousLinearMapCoordChange + variable [∀ x, TopologicalAddGroup (E₂ x)] [∀ x, ContinuousSMul 𝕜 (E₂ x)] theorem hom_chart (y₀ y : LE₁E₂) : @@ -67,12 +70,8 @@ theorem contMDiffAt_hom_bundle (f : M → LE₁E₂) {x₀ : M} {n : ℕ∞} : (fun x => inCoordinates F₁ E₁ F₂ E₂ (f x₀).1 (f x).1 (f x₀).1 (f x).1 (f x).2) x₀ := contMDiffAt_totalSpace .. -theorem smoothAt_hom_bundle (f : M → LE₁E₂) {x₀ : M} : - SmoothAt IM (IB.prod 𝓘(𝕜, F₁ →L[𝕜] F₂)) f x₀ ↔ - SmoothAt IM IB (fun x => (f x).1) x₀ ∧ - SmoothAt IM 𝓘(𝕜, F₁ →L[𝕜] F₂) - (fun x => inCoordinates F₁ E₁ F₂ E₂ (f x₀).1 (f x).1 (f x₀).1 (f x).1 (f x).2) x₀ := - contMDiffAt_hom_bundle f +@[deprecated (since := "2024-11-21")] alias smoothAt_hom_bundle := contMDiffAt_hom_bundle + variable [SmoothVectorBundle F₁ E₁ IB] [SmoothVectorBundle F₂ E₂ IB] @@ -81,7 +80,7 @@ instance Bundle.ContinuousLinearMap.vectorPrebundle.isSmooth : exists_smoothCoordChange := by rintro _ ⟨e₁, e₂, he₁, he₂, rfl⟩ _ ⟨e₁', e₂', he₁', he₂', rfl⟩ exact ⟨continuousLinearMapCoordChange (RingHom.id 𝕜) e₁ e₁' e₂ e₂', - smoothOn_continuousLinearMapCoordChange, + contMDiffOn_continuousLinearMapCoordChange, continuousLinearMapCoordChange_apply (RingHom.id 𝕜) e₁ e₁' e₂ e₂'⟩ instance SmoothVectorBundle.continuousLinearMap : diff --git a/Mathlib/Geometry/Manifold/VectorBundle/Pullback.lean b/Mathlib/Geometry/Manifold/VectorBundle/Pullback.lean index ef7514b05054c..7ba8cdb7b86d3 100644 --- a/Mathlib/Geometry/Manifold/VectorBundle/Pullback.lean +++ b/Mathlib/Geometry/Manifold/VectorBundle/Pullback.lean @@ -28,14 +28,14 @@ variable [NontriviallyNormedField 𝕜] [∀ x, AddCommMonoid (E x)] [∀ x, Mod [ChartedSpace HB B] {EB' : Type*} [NormedAddCommGroup EB'] [NormedSpace 𝕜 EB'] {HB' : Type*} [TopologicalSpace HB'] (IB' : ModelWithCorners 𝕜 EB' HB') [TopologicalSpace B'] [ChartedSpace HB' B'] [FiberBundle F E] - [VectorBundle 𝕜 F E] [SmoothVectorBundle F E IB] (f : SmoothMap IB' IB B' B) + [VectorBundle 𝕜 F E] [SmoothVectorBundle F E IB] (f : ContMDiffMap IB' IB B' B ⊤) /-- For a smooth vector bundle `E` over a manifold `B` and a smooth map `f : B' → B`, the pullback vector bundle `f *ᵖ E` is a smooth vector bundle. -/ instance SmoothVectorBundle.pullback : SmoothVectorBundle F (f *ᵖ E) IB' where - smoothOn_coordChangeL := by + contMDiffOn_coordChangeL := by rintro _ _ ⟨e, he, rfl⟩ ⟨e', he', rfl⟩ - refine ((smoothOn_coordChangeL e e').comp f.smooth.smoothOn fun b hb => hb).congr ?_ + refine ((contMDiffOn_coordChangeL e e').comp f.contMDiff.contMDiffOn fun b hb => hb).congr ?_ rintro b (hb : f b ∈ e.baseSet ∩ e'.baseSet); ext v show ((e.pullback f).coordChangeL 𝕜 (e'.pullback f) b) v = (e.coordChangeL 𝕜 e' (f b)) v rw [e.coordChangeL_apply e' hb, (e.pullback f).coordChangeL_apply' _] diff --git a/Mathlib/Geometry/Manifold/VectorBundle/SmoothSection.lean b/Mathlib/Geometry/Manifold/VectorBundle/SmoothSection.lean index 198e5170ad73e..60a27aee36286 100644 --- a/Mathlib/Geometry/Manifold/VectorBundle/SmoothSection.lean +++ b/Mathlib/Geometry/Manifold/VectorBundle/SmoothSection.lean @@ -19,6 +19,9 @@ sections of a smooth vector bundle over a manifold `M` and prove that it's a mod open Bundle Filter Function open scoped Bundle Manifold +/- Next line is necessary while the manifold smoothness class is not extended to `ω`. +Later, replace with `open scoped ContDiff`. -/ +local notation "∞" => (⊤ : ℕ∞) variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] {H : Type*} [TopologicalSpace H] (I : ModelWithCorners 𝕜 E H) @@ -39,9 +42,7 @@ structure ContMDiffSection where protected contMDiff_toFun : ContMDiff I (I.prod 𝓘(𝕜, F)) n fun x ↦ TotalSpace.mk' F x (toFun x) -/-- Bundled smooth sections of a vector bundle. -/ -abbrev SmoothSection := - ContMDiffSection I F ⊤ V +@[deprecated (since := "024-11-21")] alias SmoothSection := ContMDiffSection @[inherit_doc] scoped[Manifold] notation "Cₛ^" n "⟮" I "; " F ", " V "⟯" => ContMDiffSection I F n V @@ -65,9 +66,7 @@ protected theorem contMDiff (s : Cₛ^n⟮I; F, V⟯) : ContMDiff I (I.prod 𝓘(𝕜, F)) n fun x => TotalSpace.mk' F x (s x : V x) := s.contMDiff_toFun -protected theorem smooth (s : Cₛ^∞⟮I; F, V⟯) : - Smooth I (I.prod 𝓘(𝕜, F)) fun x => TotalSpace.mk' F x (s x : V x) := - s.contMDiff_toFun +@[deprecated (since := "2024-11-21")] alias smooth := ContMDiffSection.contMDiff theorem coe_inj ⦃s t : Cₛ^n⟮I; F, V⟯⦄ (h : (s : ∀ x, V x) = t) : s = t := DFunLike.ext' h @@ -114,7 +113,7 @@ theorem coe_sub (s t : Cₛ^n⟮I; F, V⟯) : ⇑(s - t) = s - t := rfl instance instZero : Zero Cₛ^n⟮I; F, V⟯ := - ⟨⟨fun _ => 0, (smooth_zeroSection 𝕜 V).of_le le_top⟩⟩ + ⟨⟨fun _ => 0, (contMDiff_zeroSection 𝕜 V).of_le le_top⟩⟩ instance inhabited : Inhabited Cₛ^n⟮I; F, V⟯ := ⟨0⟩ diff --git a/Mathlib/Geometry/Manifold/VectorBundle/Tangent.lean b/Mathlib/Geometry/Manifold/VectorBundle/Tangent.lean index fd5bda4a24a80..5931fefe4f64b 100644 --- a/Mathlib/Geometry/Manifold/VectorBundle/Tangent.lean +++ b/Mathlib/Geometry/Manifold/VectorBundle/Tangent.lean @@ -36,7 +36,7 @@ and a smooth manifold. open Bundle Set SmoothManifoldWithCorners PartialHomeomorph ContinuousLinearMap -open scoped Manifold Topology Bundle +open scoped Manifold Topology Bundle ContDiff noncomputable section @@ -49,7 +49,6 @@ variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} [NormedAddCom [SmoothManifoldWithCorners I M] {M' : Type*} [TopologicalSpace M'] [ChartedSpace H' M'] [SmoothManifoldWithCorners I' M'] {F : Type*} [NormedAddCommGroup F] [NormedSpace 𝕜 F] - /-- Auxiliary lemma for tangent spaces: the derivative of a coordinate change between two charts is smooth on its source. -/ theorem contDiffOn_fderiv_coord_change (i j : atlas H M) : @@ -58,12 +57,12 @@ theorem contDiffOn_fderiv_coord_change (i j : atlas H M) : have h : ((i.1.extend I).symm ≫ j.1.extend I).source ⊆ range I := by rw [i.1.extend_coord_change_source]; apply image_subset_range intro x hx - refine (ContDiffWithinAt.fderivWithin_right ?_ I.uniqueDiffOn le_top <| h hx).mono h + refine (ContDiffWithinAt.fderivWithin_right ?_ I.uniqueDiffOn (n := ∞) (mod_cast le_top) + <| h hx).mono h refine (PartialHomeomorph.contDiffOn_extend_coord_change (subset_maximalAtlas j.2) (subset_maximalAtlas i.2) x hx).mono_of_mem_nhdsWithin ?_ exact i.1.extend_coord_change_source_mem_nhdsWithin j.1 hx - open SmoothManifoldWithCorners variable (I M) in @@ -104,9 +103,9 @@ def tangentBundleCore : VectorBundleCore 𝕜 M E (atlas H M) where simp_rw [Function.comp_apply, (j.1.extend I).left_inv hy] · simp_rw [Function.comp_apply, i.1.extend_left_inv hxi, j.1.extend_left_inv hxj] · exact (contDiffWithinAt_extend_coord_change' (subset_maximalAtlas k.2) - (subset_maximalAtlas j.2) hxk hxj).differentiableWithinAt le_top + (subset_maximalAtlas j.2) hxk hxj).differentiableWithinAt (mod_cast le_top) · exact (contDiffWithinAt_extend_coord_change' (subset_maximalAtlas j.2) - (subset_maximalAtlas i.2) hxj hxi).differentiableWithinAt le_top + (subset_maximalAtlas i.2) hxj hxi).differentiableWithinAt (mod_cast le_top) · intro x _; exact mem_range_self _ · exact I.uniqueDiffWithinAt_image · rw [Function.comp_apply, i.1.extend_left_inv hxi] @@ -286,7 +285,7 @@ end TangentBundle instance tangentBundleCore.isSmooth : (tangentBundleCore I M).IsSmooth I := by refine ⟨fun i j => ?_⟩ - rw [SmoothOn, contMDiffOn_iff_source_of_mem_maximalAtlas (subset_maximalAtlas i.2), + rw [contMDiffOn_iff_source_of_mem_maximalAtlas (subset_maximalAtlas i.2), contMDiffOn_iff_contDiffOn] · refine ((contDiffOn_fderiv_coord_change (I := I) i j).congr fun x hx => ?_).mono ?_ · rw [PartialEquiv.trans_source'] at hx diff --git a/Mathlib/Geometry/Manifold/WhitneyEmbedding.lean b/Mathlib/Geometry/Manifold/WhitneyEmbedding.lean index 2c5558360b39f..a6416ab861ef1 100644 --- a/Mathlib/Geometry/Manifold/WhitneyEmbedding.lean +++ b/Mathlib/Geometry/Manifold/WhitneyEmbedding.lean @@ -33,6 +33,9 @@ variable {ι : Type uι} {E : Type uE} [NormedAddCommGroup E] [NormedSpace ℝ E open Function Filter Module Set Topology open scoped Manifold +/- Next line is necessary while the manifold smoothness class is not extended to `ω`. +Later, replace with `open scoped ContDiff`. -/ +local notation "∞" => (⊤ : ℕ∞) noncomputable section @@ -52,7 +55,7 @@ def embeddingPiTangent : C^∞⟮I, M; 𝓘(ℝ, ι → E × ℝ), ι → E × val x i := (f i x • extChartAt I (f.c i) x, f i x) property := contMDiff_pi_space.2 fun i => - ((f i).smooth_smul contMDiffOn_extChartAt).prod_mk_space (f i).smooth + ((f i).contMDiff_smul contMDiffOn_extChartAt).prod_mk_space (f i).contMDiff @[local simp] theorem embeddingPiTangent_coe : @@ -81,7 +84,8 @@ theorem comp_embeddingPiTangent_mfderiv (x : M) (hx : x ∈ s) : set L := (ContinuousLinearMap.fst ℝ E ℝ).comp (@ContinuousLinearMap.proj ℝ _ ι (fun _ => E × ℝ) _ _ (fun _ => inferInstance) (f.ind x hx)) - have := L.hasMFDerivAt.comp x f.embeddingPiTangent.smooth.mdifferentiableAt.hasMFDerivAt + have := L.hasMFDerivAt.comp x + (f.embeddingPiTangent.contMDiff.mdifferentiableAt le_top).hasMFDerivAt convert hasMFDerivAt_unique this _ refine (hasMFDerivAt_extChartAt (f.mem_chartAt_ind_source x hx)).congr_of_eventuallyEq ?_ refine (f.eventuallyEq_one x hx).mono fun y hy => ?_ @@ -106,7 +110,7 @@ supports of bump functions, then for some `n` it can be immersed into the `n`-di Euclidean space. -/ theorem exists_immersion_euclidean {ι : Type*} [Finite ι] (f : SmoothBumpCovering ι I M) : ∃ (n : ℕ) (e : M → EuclideanSpace ℝ (Fin n)), - Smooth I (𝓡 n) e ∧ Injective e ∧ ∀ x : M, Injective (mfderiv I (𝓡 n) e x) := by + ContMDiff I (𝓡 n) ⊤ e ∧ Injective e ∧ ∀ x : M, Injective (mfderiv I (𝓡 n) e x) := by cases nonempty_fintype ι set F := EuclideanSpace ℝ (Fin <| finrank ℝ (ι → E × ℝ)) letI : IsNoetherian ℝ (E × ℝ) := IsNoetherian.iff_fg.2 inferInstance @@ -114,10 +118,10 @@ theorem exists_immersion_euclidean {ι : Type*} [Finite ι] (f : SmoothBumpCover set eEF : (ι → E × ℝ) ≃L[ℝ] F := ContinuousLinearEquiv.ofFinrankEq finrank_euclideanSpace_fin.symm refine ⟨_, eEF ∘ f.embeddingPiTangent, - eEF.toDiffeomorph.smooth.comp f.embeddingPiTangent.smooth, + eEF.toDiffeomorph.contMDiff.comp f.embeddingPiTangent.contMDiff, eEF.injective.comp f.embeddingPiTangent_injective, fun x => ?_⟩ rw [mfderiv_comp _ eEF.differentiableAt.mdifferentiableAt - f.embeddingPiTangent.smooth.mdifferentiableAt, + (f.embeddingPiTangent.contMDiff.mdifferentiableAt le_top), eEF.mfderiv_eq] exact eEF.injective.comp (f.embeddingPiTangent_injective_mfderiv _ trivial) @@ -128,7 +132,7 @@ supports of bump functions, then for some `n` it can be embedded into the `n`-di Euclidean space. -/ theorem exists_embedding_euclidean_of_compact [T2Space M] [CompactSpace M] : ∃ (n : ℕ) (e : M → EuclideanSpace ℝ (Fin n)), - Smooth I (𝓡 n) e ∧ IsClosedEmbedding e ∧ ∀ x : M, Injective (mfderiv I (𝓡 n) e x) := by + ContMDiff I (𝓡 n) ⊤ e ∧ IsClosedEmbedding e ∧ ∀ x : M, Injective (mfderiv I (𝓡 n) e x) := by rcases SmoothBumpCovering.exists_isSubordinate I isClosed_univ fun (x : M) _ => univ_mem with ⟨ι, f, -⟩ haveI := f.fintype diff --git a/Mathlib/Geometry/RingedSpace/PresheafedSpace/Gluing.lean b/Mathlib/Geometry/RingedSpace/PresheafedSpace/Gluing.lean index 5c87be9ceb0bc..df614fe6a7795 100644 --- a/Mathlib/Geometry/RingedSpace/PresheafedSpace/Gluing.lean +++ b/Mathlib/Geometry/RingedSpace/PresheafedSpace/Gluing.lean @@ -92,7 +92,7 @@ that the `U i`'s are open subspaces of the glued space. -/ -- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): this linter isn't ported yet. -- @[nolint has_nonempty_instance] -structure GlueData extends GlueData (PresheafedSpace.{u, v, v} C) where +structure GlueData extends CategoryTheory.GlueData (PresheafedSpace.{u, v, v} C) where f_open : ∀ i j, IsOpenImmersion (f i j) attribute [instance] GlueData.f_open diff --git a/Mathlib/GroupTheory/Archimedean.lean b/Mathlib/GroupTheory/Archimedean.lean index c31b5072d4f20..e67010ff8ade4 100644 --- a/Mathlib/GroupTheory/Archimedean.lean +++ b/Mathlib/GroupTheory/Archimedean.lean @@ -31,6 +31,8 @@ The result is also used in `Topology.Instances.Real` as an ingredient in the cla subgroups of `ℝ`. -/ +assert_not_exists Finset + open Set variable {G : Type*} [LinearOrderedCommGroup G] [MulArchimedean G] diff --git a/Mathlib/GroupTheory/Coprod/Basic.lean b/Mathlib/GroupTheory/Coprod/Basic.lean index 084c569e85fa9..93e15e7696015 100644 --- a/Mathlib/GroupTheory/Coprod/Basic.lean +++ b/Mathlib/GroupTheory/Coprod/Basic.lean @@ -3,7 +3,7 @@ Copyright (c) 2023 Yury Kudryashov. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov -/ -import Mathlib.Algebra.Group.Subgroup.Basic +import Mathlib.Algebra.Group.Subgroup.Ker import Mathlib.Algebra.Group.Submonoid.Membership import Mathlib.Algebra.PUnitInstances.Algebra import Mathlib.GroupTheory.Congruence.Basic diff --git a/Mathlib/GroupTheory/Coset/Basic.lean b/Mathlib/GroupTheory/Coset/Basic.lean index a93c6f92a2109..4f8c575b67fcf 100644 --- a/Mathlib/GroupTheory/Coset/Basic.lean +++ b/Mathlib/GroupTheory/Coset/Basic.lean @@ -318,9 +318,15 @@ lemma orbit_eq_out_smul (x : α ⧸ s) : MulAction.orbitRel.Quotient.orbit x = x induction x using QuotientGroup.induction_on simp only [orbit_mk_eq_smul, ← eq_class_eq_leftCoset, Quotient.out_eq'] -@[to_additive (attr := deprecated (since := "2024-10-19"))] +@[to_additive] alias orbit_eq_out'_smul := orbit_eq_out_smul +-- `alias` doesn't add the deprecation suggestion to the `to_additive` version +-- see https://github.com/leanprover-community/mathlib4/issues/19424 +attribute [deprecated orbit_eq_out_smul (since := "2024-10-19")] orbit_eq_out'_smul +attribute [deprecated QuotientAddGroup.orbit_eq_out_vadd (since := "2024-10-19")] +QuotientAddGroup.orbit_eq_out'_vadd + end QuotientGroup namespace Subgroup diff --git a/Mathlib/GroupTheory/Coset/Defs.lean b/Mathlib/GroupTheory/Coset/Defs.lean index f43753df9ac06..c57164adfbaee 100644 --- a/Mathlib/GroupTheory/Coset/Defs.lean +++ b/Mathlib/GroupTheory/Coset/Defs.lean @@ -89,6 +89,10 @@ instance leftRelDecidable [DecidablePred (· ∈ s)] : DecidableRel (leftRel s). instance instHasQuotientSubgroup : HasQuotient α (Subgroup α) := ⟨fun s => Quotient (leftRel s)⟩ +@[to_additive] +instance [DecidablePred (· ∈ s)] : DecidableEq (α ⧸ s) := + @Quotient.decidableEq _ _ (leftRelDecidable _) + /-- The equivalence relation corresponding to the partition of a group by right cosets of a subgroup. -/ @[to_additive "The equivalence relation corresponding to the partition of a group by right cosets @@ -170,7 +174,13 @@ theorem induction_on {C : α ⧸ s → Prop} (x : α ⧸ s) (H : ∀ z, C (Quoti instance : Coe α (α ⧸ s) := ⟨mk⟩ -@[to_additive (attr := deprecated (since := "2024-08-04"))] alias induction_on' := induction_on +@[to_additive] alias induction_on' := induction_on + +-- `alias` doesn't add the deprecation suggestion to the `to_additive` version +-- see https://github.com/leanprover-community/mathlib4/issues/19424 +attribute [deprecated induction_on (since := "2024-08-04")] induction_on' +attribute [deprecated QuotientAddGroup.induction_on (since := "2024-08-04")] +QuotientAddGroup.induction_on' @[to_additive (attr := simp)] theorem quotient_liftOn_mk {β} (f : α → β) (h) (x : α) : Quotient.liftOn' (x : α ⧸ s) f h = f x := @@ -194,7 +204,8 @@ protected theorem eq {a b : α} : (a : α ⧸ s) = b ↔ a⁻¹ * b ∈ s := _ ↔ leftRel s a b := Quotient.eq'' _ ↔ _ := by rw [leftRel_apply] -@[to_additive (attr := deprecated (since := "2024-08-04"))] alias eq' := QuotientGroup.eq +@[to_additive (attr := deprecated "No deprecation message was provided." (since := "2024-08-04"))] +alias eq' := QuotientGroup.eq @[to_additive] theorem out_eq' (a : α ⧸ s) : mk a.out = a := @@ -209,9 +220,16 @@ variable (s) theorem mk_out_eq_mul (g : α) : ∃ h : s, (mk g : α ⧸ s).out = g * h := ⟨⟨g⁻¹ * (mk g).out, QuotientGroup.eq.mp (mk g).out_eq'.symm⟩, by rw [mul_inv_cancel_left]⟩ -@[to_additive (attr := deprecated (since := "2024-10-19")) QuotientAddGroup.mk_out'_eq_mul] +@[to_additive QuotientAddGroup.mk_out'_eq_mul] alias mk_out'_eq_mul := mk_out_eq_mul +-- `alias` doesn't add the deprecation suggestion to the `to_additive` version +-- see https://github.com/leanprover-community/mathlib4/issues/19424 +attribute [deprecated mk_out_eq_mul (since := "2024-10-19")] mk_out'_eq_mul +attribute [deprecated QuotientAddGroup.mk_out_eq_mul (since := "2024-10-19")] +QuotientAddGroup.mk_out'_eq_mul + + variable {s} {a b : α} @[to_additive (attr := simp)] diff --git a/Mathlib/GroupTheory/Exponent.lean b/Mathlib/GroupTheory/Exponent.lean index 6ee49e4b8a6ac..ea64a5ce67e5e 100644 --- a/Mathlib/GroupTheory/Exponent.lean +++ b/Mathlib/GroupTheory/Exponent.lean @@ -644,7 +644,8 @@ lemma inv_eq_self_of_orderOf_eq_two {x : G} (hx : orderOf x = 2) : -- TODO: delete /-- Any group of exponent two is abelian. -/ -@[to_additive (attr := reducible, deprecated (since := "2024-02-17")) +@[to_additive (attr := reducible, + deprecated "No deprecation message was provided." (since := "2024-02-17")) "Any additive group of exponent two is abelian."] def instCommGroupOfExponentTwo (hG : Monoid.exponent G = 2) : CommGroup G where mul_comm := mul_comm_of_exponent_two hG diff --git a/Mathlib/GroupTheory/FiniteAbelian/Basic.lean b/Mathlib/GroupTheory/FiniteAbelian/Basic.lean index def95dc958b3b..38fa544799b25 100644 --- a/Mathlib/GroupTheory/FiniteAbelian/Basic.lean +++ b/Mathlib/GroupTheory/FiniteAbelian/Basic.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Pierre-Alexandre Bazin -/ import Mathlib.Algebra.Module.PID +import Mathlib.Algebra.Group.TypeTags.Finite import Mathlib.Data.ZMod.Quotient /-! diff --git a/Mathlib/GroupTheory/FiniteAbelian/Duality.lean b/Mathlib/GroupTheory/FiniteAbelian/Duality.lean index 308c47949bf39..dafdda97bea03 100644 --- a/Mathlib/GroupTheory/FiniteAbelian/Duality.lean +++ b/Mathlib/GroupTheory/FiniteAbelian/Duality.lean @@ -42,9 +42,9 @@ lemma exists_apply_ne_one_aux (H : ∀ n : ℕ, n ∣ Monoid.exponent G → ∀ obtain ⟨i, hi⟩ : ∃ i : ι, e a i ≠ 1 := by contrapose! ha exact (MulEquiv.map_eq_one_iff e).mp <| funext ha - have hi : Multiplicative.toAdd (e a i) ≠ 0 := by + have hi : (e a i).toAdd ≠ 0 := by simp only [ne_eq, toAdd_eq_zero, hi, not_false_eq_true] - obtain ⟨φi, hφi⟩ := H (n i) (dvd_exponent e i) (Multiplicative.toAdd <| e a i) hi + obtain ⟨φi, hφi⟩ := H (n i) (dvd_exponent e i) ((e a i).toAdd) hi use (φi.comp (Pi.evalMonoidHom (fun (i : ι) ↦ Multiplicative (ZMod (n i))) i)).comp e simpa only [coe_comp, coe_coe, Function.comp_apply, Pi.evalMonoidHom_apply, ne_eq] using hφi diff --git a/Mathlib/GroupTheory/Finiteness.lean b/Mathlib/GroupTheory/Finiteness.lean index 80895c9fc92ee..bd31d6b8743b4 100644 --- a/Mathlib/GroupTheory/Finiteness.lean +++ b/Mathlib/GroupTheory/Finiteness.lean @@ -3,8 +3,8 @@ Copyright (c) 2021 Riccardo Brasca. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Riccardo Brasca -/ +import Mathlib.Algebra.Group.Pointwise.Set.Finite import Mathlib.Algebra.Group.Subgroup.Pointwise -import Mathlib.Data.Set.Pointwise.Finite import Mathlib.GroupTheory.QuotientGroup.Defs import Mathlib.SetTheory.Cardinal.Finite diff --git a/Mathlib/GroupTheory/FreeGroup/Basic.lean b/Mathlib/GroupTheory/FreeGroup/Basic.lean index 35f5a97da6e4a..2c47200b1ac4d 100644 --- a/Mathlib/GroupTheory/FreeGroup/Basic.lean +++ b/Mathlib/GroupTheory/FreeGroup/Basic.lean @@ -3,7 +3,7 @@ Copyright (c) 2018 Kenny Lau. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kenny Lau -/ -import Mathlib.Algebra.Group.Subgroup.Basic +import Mathlib.Algebra.Group.Subgroup.Ker import Mathlib.Data.Fintype.Basic import Mathlib.Data.List.Sublists @@ -48,6 +48,7 @@ free group, Newman's diamond lemma, Church-Rosser theorem -/ open Relation +open scoped List universe u v w @@ -906,6 +907,9 @@ def reduce : (L : List (α × Bool)) -> List (α × Bool) := List.casesOn ih [hd1] fun hd2 tl2 => if hd1.1 = hd2.1 ∧ hd1.2 = not hd2.2 then tl2 else hd1 :: hd2 :: tl2 +@[to_additive (attr := simp)] lemma reduce_nil : reduce ([] : List (α × Bool)) = [] := rfl +@[to_additive] lemma reduce_singleton (s : α × Bool) : reduce [s] = [s] := rfl + @[to_additive (attr := simp)] theorem reduce.cons (x) : reduce (x :: L) = @@ -1099,11 +1103,19 @@ theorem reduce_invRev {w : List (α × Bool)} : reduce (invRev w) = invRev (redu have : Red (invRev (invRev w)) (invRev (reduce (invRev w))) := reduce.red.invRev rwa [invRev_invRev] at this -@[to_additive] -theorem toWord_inv {x : FreeGroup α} : x⁻¹.toWord = invRev x.toWord := by +@[to_additive (attr := simp)] +theorem toWord_inv (x : FreeGroup α) : x⁻¹.toWord = invRev x.toWord := by rcases x with ⟨L⟩ rw [quot_mk_eq_mk, inv_mk, toWord_mk, toWord_mk, reduce_invRev] +@[to_additive] +lemma toWord_mul_sublist (x y : FreeGroup α) : (x * y).toWord <+ x.toWord ++ y.toWord := by + refine Red.sublist ?_ + have : x * y = FreeGroup.mk (x.toWord ++ y.toWord) := by + rw [← FreeGroup.mul_mk, FreeGroup.mk_toWord, FreeGroup.mk_toWord] + rw [this] + exact FreeGroup.reduce.red + /-- **Constructive Church-Rosser theorem** (compare `church_rosser`). -/ @[to_additive "**Constructive Church-Rosser theorem** (compare `church_rosser`)."] def reduce.churchRosser (H12 : Red L₁ L₂) (H13 : Red L₁ L₃) : { L₄ // Red L₂ L₄ ∧ Red L₃ L₄ } := diff --git a/Mathlib/GroupTheory/GroupAction/Basic.lean b/Mathlib/GroupTheory/GroupAction/Basic.lean index ed5ab1ed24c4a..ae7eaef28b78d 100644 --- a/Mathlib/GroupTheory/GroupAction/Basic.lean +++ b/Mathlib/GroupTheory/GroupAction/Basic.lean @@ -3,7 +3,7 @@ Copyright (c) 2018 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes -/ -import Mathlib.Algebra.Group.Subgroup.Basic +import Mathlib.Algebra.Group.Subgroup.Map import Mathlib.Data.Finite.Sigma import Mathlib.Data.Set.Finite.Basic import Mathlib.Data.Set.Finite.Range diff --git a/Mathlib/GroupTheory/GroupAction/Defs.lean b/Mathlib/GroupTheory/GroupAction/Defs.lean index 3848050964715..fa15f5e7d6253 100644 --- a/Mathlib/GroupTheory/GroupAction/Defs.lean +++ b/Mathlib/GroupTheory/GroupAction/Defs.lean @@ -312,9 +312,15 @@ variable {G α} theorem orbitRel_apply {a b : α} : orbitRel G α a b ↔ a ∈ orbit G b := Iff.rfl -@[to_additive (attr := deprecated (since := "2024-10-18"))] +@[to_additive] alias orbitRel_r_apply := orbitRel_apply +-- `alias` doesn't add the deprecation suggestion to the `to_additive` version +-- see https://github.com/leanprover-community/mathlib4/issues/19424 +attribute [deprecated orbitRel_apply (since := "2024-10-18")] orbitRel_r_apply +attribute [deprecated AddAction.orbitRel_apply (since := "2024-10-18")] AddAction.orbitRel_r_apply + + /-- When you take a set `U` in `α`, push it down to the quotient, and pull back, you get the union of the orbit of `U` under `G`. -/ @[to_additive diff --git a/Mathlib/GroupTheory/GroupAction/FixingSubgroup.lean b/Mathlib/GroupTheory/GroupAction/FixingSubgroup.lean index f968df45e92a9..38834797ad222 100644 --- a/Mathlib/GroupTheory/GroupAction/FixingSubgroup.lean +++ b/Mathlib/GroupTheory/GroupAction/FixingSubgroup.lean @@ -3,7 +3,7 @@ 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.Basic +import Mathlib.Algebra.Group.Subgroup.Lattice import Mathlib.GroupTheory.GroupAction.FixedPoints /-! diff --git a/Mathlib/GroupTheory/GroupAction/Hom.lean b/Mathlib/GroupTheory/GroupAction/Hom.lean index 95bd4983abab0..2ce20e3e8812b 100644 --- a/Mathlib/GroupTheory/GroupAction/Hom.lean +++ b/Mathlib/GroupTheory/GroupAction/Hom.lean @@ -15,6 +15,7 @@ import Mathlib.Algebra.Group.Hom.CompTypeclasses * `MulActionHom φ X Y`, the type of equivariant functions from `X` to `Y`, where `φ : M → N` is a map, `M` acting on the type `X` and `N` acting on the type of `Y`. + `AddActionHom φ X Y` is its additive version. * `DistribMulActionHom φ A B`, the type of equivariant additive monoid homomorphisms from `A` to `B`, where `φ : M → N` is a morphism of monoids, @@ -25,7 +26,8 @@ import Mathlib.Algebra.Group.Hom.CompTypeclasses The above types have corresponding classes: * `MulActionHomClass F φ X Y` states that `F` is a type of bundled `X → Y` homs - which are `φ`-equivariant + which are `φ`-equivariant; + `AddActionHomClass F φ X Y` is its additive version. * `DistribMulActionHomClass F φ A B` states that `F` is a type of bundled `A → B` homs preserving the additive monoid structure and `φ`-equivariant * `SMulSemiringHomClass F φ R S` states that `F` is a type of bundled `R → S` homs @@ -35,14 +37,19 @@ The above types have corresponding classes: We introduce the following notation to code equivariant maps (the subscript index `ₑ` is for *equivariant*) : -* `X →ₑ[φ] Y` is `MulActionHom φ X Y`. +* `X →ₑ[φ] Y` is `MulActionHom φ X Y` and `AddActionHom φ X Y` * `A →ₑ+[φ] B` is `DistribMulActionHom φ A B`. * `R →ₑ+*[φ] S` is `MulSemiringActionHom φ R S`. When `M = N` and `φ = MonoidHom.id M`, we provide the backward compatible notation : -* `X →[M] Y` is `MulActionHom (@id M) X Y` +* `X →[M] Y` is `MulActionHom (@id M) X Y` and `AddActionHom (@id M) X Y` * `A →+[M] B` is `DistribMulActionHom (MonoidHom.id M) A B` * `R →+*[M] S` is `MulSemiringActionHom (MonoidHom.id M) R S` + +The notation for `MulActionHom` and `AddActionHom` is the same, because it is unlikely +that it could lead to confusion — unless one needs types `M` and `X` with simultaneous +instances of `Mul M`, `Add M`, `SMul M X` and `VAdd M X`… + -/ assert_not_exists Submonoid @@ -56,11 +63,21 @@ variable (X : Type*) [SMul M X] [SMul M' X] variable (Y : Type*) [SMul N Y] [SMul M' Y] variable (Z : Type*) [SMul P Z] +/-- Equivariant functions : +When `φ : M → N` is a function, and types `X` and `Y` are endowed with additive actions +of `M` and `N`, a function `f : X → Y` is `φ`-equivariant if `f (m +ᵥ x) = (φ m) +ᵥ (f x)`. -/ +structure AddActionHom {M N : Type*} (φ: M → N) (X : Type*) [VAdd M X] (Y : Type*) [VAdd N Y] where + /-- The underlying function. -/ + protected toFun : X → Y + /-- The proposition that the function commutes with the additive actions. -/ + protected map_vadd' : ∀ (m : M) (x : X), toFun (m +ᵥ x) = (φ m) +ᵥ toFun x + /-- 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)`. -/ -- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): this linter isn't ported yet. -- @[nolint has_nonempty_instance] +@[to_additive] structure MulActionHom where /-- The underlying function. -/ protected toFun : X → Y @@ -70,20 +87,40 @@ structure MulActionHom where /- Porting note: local notation given a name, conflict with Algebra.Hom.GroupAction see https://github.com/leanprover/lean4/issues/2000 -/ /-- `φ`-equivariant functions `X → Y`, -where `φ : M → N`, where `M` and `N` act on `X` and `Y` respectively -/ +where `φ : M → N`, where `M` and `N` act on `X` and `Y` respectively.-/ notation:25 (name := «MulActionHomLocal≺») X " →ₑ[" φ:25 "] " Y:0 => MulActionHom φ X Y -/-- `M`-equivariant functions `X → Y` with respect to the action of `M` - -This is the same as `X →ₑ[@id M] Y` -/ +/-- `M`-equivariant functions `X → Y` with respect to the action of `M`. +This is the same as `X →ₑ[@id M] Y`. -/ notation:25 (name := «MulActionHomIdLocal≺») X " →[" M:25 "] " Y:0 => MulActionHom (@id M) X Y +/-- `φ`-equivariant functions `X → Y`, +where `φ : M → N`, where `M` and `N` act additively on `X` and `Y` respectively +We use the same notation as for multiplicative actions, as conflicts are unlikely. -/ +notation:25 (name := «AddActionHomLocal≺») X " →ₑ[" φ:25 "] " Y:0 => AddActionHom φ X Y + +/-- `M`-equivariant functions `X → Y` with respect to the additive action of `M`. +This is the same as `X →ₑ[@id M] Y`. + +We use the same notation as for multiplicative actions, as conflicts are unlikely. -/ +notation:25 (name := «AddActionHomIdLocal≺») X " →[" M:25 "] " Y:0 => AddActionHom (@id M) X Y + +/-- `AddActionSemiHomClass F φ X Y` states that + `F` is a type of morphisms which are `φ`-equivariant. + +You should extend this class when you extend `AddActionHom`. -/ +class AddActionSemiHomClass (F : Type*) + {M N : outParam Type*} (φ : outParam (M → N)) + (X Y : outParam Type*) [VAdd M X] [VAdd N Y] [FunLike F X Y] : Prop where + /-- The proposition that the function preserves the action. -/ + map_vaddₛₗ : ∀ (f : F) (c : M) (x : X), f (c +ᵥ x) = (φ c) +ᵥ (f x) /-- `MulActionSemiHomClass F φ X Y` states that `F` is a type of morphisms which are `φ`-equivariant. You should extend this class when you extend `MulActionHom`. -/ +@[to_additive] class MulActionSemiHomClass (F : Type*) {M N : outParam Type*} (φ : outParam (M → N)) (X Y : outParam Type*) [SMul M X] [SMul N Y] [FunLike F X Y] : Prop where @@ -91,19 +128,23 @@ class MulActionSemiHomClass (F : Type*) map_smulₛₗ : ∀ (f : F) (c : M) (x : X), f (c • x) = (φ c) • (f x) export MulActionSemiHomClass (map_smulₛₗ) +export AddActionSemiHomClass (map_vaddₛₗ) /-- `MulActionHomClass F M X Y` states that `F` is a type of morphisms which are equivariant with respect to actions of `M` This is an abbreviation of `MulActionSemiHomClass`. -/ +@[to_additive "`MulActionHomClass F M X Y` states that `F` is a type of +morphisms which are equivariant with respect to actions of `M` +This is an abbreviation of `MulActionSemiHomClass`."] abbrev MulActionHomClass (F : Type*) (M : outParam Type*) (X Y : outParam Type*) [SMul M X] [SMul M Y] [FunLike F X Y] := MulActionSemiHomClass F (@id M) X Y -instance : FunLike (MulActionHom φ X Y) X Y where +@[to_additive] instance : FunLike (MulActionHom φ X Y) X Y where coe := MulActionHom.toFun coe_injective' f g h := by cases f; cases g; congr -@[simp] +@[to_additive (attr := simp)] theorem map_smul {F M X Y : Type*} [SMul M X] [SMul M Y] [FunLike F X Y] [MulActionHomClass F M X Y] (f : F) (c : M) (x : X) : f (c • x) = c • f x := @@ -113,10 +154,12 @@ theorem map_smul {F M X Y : Type*} [SMul M X] [SMul M Y] -- Porting note: removed has_coe_to_fun instance, coercions handled differently now +@[to_additive] instance : MulActionSemiHomClass (X →ₑ[φ] Y) φ X Y where map_smulₛₗ := MulActionHom.map_smul' initialize_simps_projections MulActionHom (toFun → apply) +initialize_simps_projections AddActionHom (toFun → apply) namespace MulActionHom @@ -128,7 +171,10 @@ see also Algebra.Hom.Group -/ /-- Turn an element of a type `F` satisfying `MulActionSemiHomClass F φ X Y` into an actual `MulActionHom`. This is declared as the default coercion from `F` to `MulActionSemiHom φ X Y`. -/ -@[coe] +@[to_additive (attr := coe) + "Turn an element of a type `F` satisfying `AddActionSemiHomClass F φ X Y` + into an actual `AddActionHom`. + This is declared as the default coercion from `F` to `AddActionSemiHom φ X Y`."] def _root_.MulActionSemiHomClass.toMulActionHom [MulActionSemiHomClass F φ X Y] (f : F) : X →ₑ[φ] Y where toFun := DFunLike.coe f @@ -136,39 +182,44 @@ def _root_.MulActionSemiHomClass.toMulActionHom [MulActionSemiHomClass F φ X Y] /-- Any type satisfying `MulActionSemiHomClass` can be cast into `MulActionHom` via `MulActionHomSemiClass.toMulActionHom`. -/ +@[to_additive] instance [MulActionSemiHomClass F φ X Y] : CoeTC F (X →ₑ[φ] Y) := ⟨MulActionSemiHomClass.toMulActionHom⟩ variable (M' X Y F) in /-- If Y/X/M forms a scalar tower, any map X → Y preserving X-action also preserves M-action. -/ +@[to_additive] theorem _root_.IsScalarTower.smulHomClass [MulOneClass X] [SMul X Y] [IsScalarTower M' X Y] [MulActionHomClass F X X Y] : MulActionHomClass F M' X Y where map_smulₛₗ f m x := by rw [← mul_one (m • x), ← smul_eq_mul, map_smul, smul_assoc, ← map_smul, smul_eq_mul, mul_one, id_eq] +@[to_additive] protected theorem map_smul (f : X →[M'] Y) (m : M') (x : X) : f (m • x) = m • f x := map_smul f m x -@[ext] +@[to_additive (attr := ext)] theorem ext {f g : X →ₑ[φ] Y} : (∀ x, f x = g x) → f = g := DFunLike.ext f g +@[to_additive] protected theorem congr_fun {f g : X →ₑ[φ] Y} (h : f = g) (x : X) : f x = g x := DFunLike.congr_fun h _ /-- Two equal maps on scalars give rise to an equivariant map for identity -/ +@[to_additive "Two equal maps on scalars give rise to an equivariant map for identity"] def ofEq {φ' : M → N} (h : φ = φ') (f : X →ₑ[φ] Y) : X →ₑ[φ'] Y where toFun := f.toFun map_smul' m a := h ▸ f.map_smul' m a -@[simp] +@[to_additive (attr := simp)] theorem ofEq_coe {φ' : M → N} (h : φ = φ') (f : X →ₑ[φ] Y) : (f.ofEq h).toFun = f.toFun := rfl -@[simp] +@[to_additive (attr := simp)] theorem ofEq_apply {φ' : M → N} (h : φ = φ') (f : X →ₑ[φ] Y) (a : X) : (f.ofEq h) a = f a := rfl @@ -177,12 +228,13 @@ theorem ofEq_apply {φ' : M → N} (h : φ = φ') (f : X →ₑ[φ] Y) (a : X) : variable {ψ χ} (M N) /-- The identity map as an equivariant map. -/ +@[to_additive "The identity map as an equivariant map."] protected def id : X →[M] X := ⟨id, fun _ _ => rfl⟩ variable {M N Z} -@[simp] +@[to_additive (attr := simp)] theorem id_apply (x : X) : MulActionHom.id M x = x := rfl @@ -197,6 +249,7 @@ variable {φ ψ χ X Y Z} -- attribute [instance] CompTriple.id_comp CompTriple.comp_id /-- Composition of two equivariant maps. -/ +@[to_additive "Composition of two equivariant maps."] def comp (g : Y →ₑ[ψ] Z) (f : X →ₑ[φ] Y) [κ : CompTriple φ ψ χ] : X →ₑ[χ] Z := ⟨g ∘ f, fun m x => @@ -206,22 +259,22 @@ def comp (g : Y →ₑ[ψ] Z) (f : X →ₑ[φ] Y) [κ : CompTriple φ ψ χ] : _ = (ψ ∘ φ) m • g (f x) := rfl _ = χ m • g (f x) := by rw [κ.comp_eq] ⟩ -@[simp] +@[to_additive (attr := simp)] theorem comp_apply (g : Y →ₑ[ψ] Z) (f : X →ₑ[φ] Y) [CompTriple φ ψ χ] (x : X) : g.comp f x = g (f x) := rfl -@[simp] +@[to_additive (attr := simp)] theorem id_comp (f : X →ₑ[φ] Y) : (MulActionHom.id N).comp f = f := ext fun x => by rw [comp_apply, id_apply] -@[simp] +@[to_additive (attr := simp)] theorem comp_id (f : X →ₑ[φ] Y) : f.comp (MulActionHom.id M) = f := ext fun x => by rw [comp_apply, id_apply] -@[simp] +@[to_additive (attr := simp)] theorem comp_assoc {Q T : Type*} [SMul Q T] {η : P → Q} {θ : M → Q} {ζ : N → Q} (h : Z →ₑ[η] T) (g : Y →ₑ[ψ] Z) (f : X →ₑ[φ] Y) @@ -232,8 +285,9 @@ theorem comp_assoc {Q T : Type*} [SMul Q T] variable {φ' : N → M} variable {Y₁ : Type*} [SMul M Y₁] + /-- The inverse of a bijective equivariant map is equivariant. -/ -@[simps] +@[to_additive (attr := simps) "The inverse of a bijective equivariant map is equivariant."] def inverse (f : X →[M] Y₁) (g : Y₁ → X) (h₁ : Function.LeftInverse g f) (h₂ : Function.RightInverse g f) : Y₁ →[M] X where toFun := g @@ -245,7 +299,7 @@ def inverse (f : X →[M] Y₁) (g : Y₁ → X) /-- The inverse of a bijective equivariant map is equivariant. -/ -@[simps] +@[to_additive (attr := simps) "The inverse of a bijective equivariant map is equivariant."] def inverse' (f : X →ₑ[φ] Y) (g : Y → X) (k : Function.RightInverse φ' φ) (h₁ : Function.LeftInverse g f) (h₂ : Function.RightInverse g f) : Y →ₑ[φ'] X where @@ -257,11 +311,13 @@ def inverse' (f : X →ₑ[φ] Y) (g : Y → X) (k : Function.RightInverse φ' _ = g (f (φ' m • g x)) := by rw [map_smulₛₗ] _ = φ' m • g x := by rw [h₁] +@[to_additive] lemma inverse_eq_inverse' (f : X →[M] Y₁) (g : Y₁ → X) (h₁ : Function.LeftInverse g f) (h₂ : Function.RightInverse g f) : inverse f g h₁ h₂ = inverse' f g (congrFun rfl) h₁ h₂ := by rfl +@[to_additive] theorem inverse'_inverse' {f : X →ₑ[φ] Y} {g : Y → X} {k₁ : Function.LeftInverse φ' φ} {k₂ : Function.RightInverse φ' φ} @@ -269,6 +325,7 @@ theorem inverse'_inverse' inverse' (inverse' f g k₂ h₁ h₂) f k₁ h₂ h₁ = f := ext fun _ => rfl +@[to_additive] theorem comp_inverse' {f : X →ₑ[φ] Y} {g : Y → X} {k₁ : Function.LeftInverse φ' φ} {k₂ : Function.RightInverse φ' φ} {h₁ : Function.LeftInverse g f} {h₂ : Function.RightInverse g f} : @@ -279,6 +336,7 @@ theorem comp_inverse' {f : X →ₑ[φ] Y} {g : Y → X} simp only [comp_apply, inverse_apply, id_apply] exact h₁ x +@[to_additive] theorem inverse'_comp {f : X →ₑ[φ] Y} {g : Y → X} {k₂ : Function.RightInverse φ' φ} {h₁ : Function.LeftInverse g f} {h₂ : Function.RightInverse g f} : @@ -290,7 +348,8 @@ theorem inverse'_comp {f : X →ₑ[φ] Y} {g : Y → X} /-- If actions of `M` and `N` on `α` commute, then for `c : M`, `(c • · : α → α)` is an `N`-action homomorphism. -/ -@[simps] +@[to_additive (attr := simps) "If additive actions of `M` and `N` on `α` commute, + then for `c : M`, `(c • · : α → α)` is an `N`-additive action homomorphism."] def _root_.SMulCommClass.toMulActionHom {M} (N α : Type*) [SMul M α] [SMul N α] [SMulCommClass M N α] (c : M) : α →[N] α where diff --git a/Mathlib/GroupTheory/GroupAction/Quotient.lean b/Mathlib/GroupTheory/GroupAction/Quotient.lean index 4c15d5da76105..778fb1159400a 100644 --- a/Mathlib/GroupTheory/GroupAction/Quotient.lean +++ b/Mathlib/GroupTheory/GroupAction/Quotient.lean @@ -103,13 +103,26 @@ theorem _root_.QuotientGroup.out_conj_pow_minimalPeriod_mem (a : α) (q : α ⧸ rw [mul_assoc, ← QuotientGroup.eq, QuotientGroup.out_eq', ← smul_eq_mul, Quotient.mk_smul_out, eq_comm, pow_smul_eq_iff_minimalPeriod_dvd] -@[to_additive (attr := deprecated (since := "2024-10-19"))] +@[to_additive] alias Quotient.mk_smul_out' := Quotient.mk_smul_out +-- `alias` doesn't add the deprecation suggestion to the `to_additive` version +-- see https://github.com/leanprover-community/mathlib4/issues/19424 +attribute [deprecated Quotient.mk_smul_out (since := "2024-10-19")] Quotient.mk_smul_out' +attribute [deprecated AddAction.Quotient.mk_vadd_out (since := "2024-10-19")] +AddAction.Quotient.mk_vadd_out' + -- Porting note: removed simp attribute, simp can prove this -@[to_additive (attr := deprecated (since := "2024-10-19"))] +@[to_additive] alias Quotient.coe_smul_out' := Quotient.coe_smul_out +-- `alias` doesn't add the deprecation suggestion to the `to_additive` version +-- see https://github.com/leanprover-community/mathlib4/issues/19424 +attribute [deprecated Quotient.coe_smul_out (since := "2024-10-19")] Quotient.coe_smul_out' +attribute [deprecated AddAction.Quotient.coe_vadd_out (since := "2024-10-19")] +AddAction.Quotient.coe_vadd_out' + + @[deprecated (since := "2024-10-19")] alias _root_.QuotientGroup.out'_conj_pow_minimalPeriod_mem := QuotientGroup.out_conj_pow_minimalPeriod_mem diff --git a/Mathlib/GroupTheory/Index.lean b/Mathlib/GroupTheory/Index.lean index 8357feb56afc9..c31a41f62822f 100644 --- a/Mathlib/GroupTheory/Index.lean +++ b/Mathlib/GroupTheory/Index.lean @@ -554,6 +554,17 @@ variable {H K} theorem finiteIndex_of_le [FiniteIndex H] (h : H ≤ K) : FiniteIndex K := ⟨ne_zero_of_dvd_ne_zero FiniteIndex.finiteIndex (index_dvd_of_le h)⟩ +@[to_additive (attr := gcongr)] +lemma index_antitone (h : H ≤ K) [H.FiniteIndex] : K.index ≤ H.index := + Nat.le_of_dvd (Nat.zero_lt_of_ne_zero FiniteIndex.finiteIndex) (index_dvd_of_le h) + +@[to_additive (attr := gcongr)] +lemma index_strictAnti (h : H < K) [H.FiniteIndex] : K.index < H.index := by + have h0 : K.index ≠ 0 := (finiteIndex_of_le h.le).finiteIndex + apply lt_of_le_of_ne (index_antitone h.le) + rw [← relindex_mul_index h.le, Ne, eq_comm, mul_eq_right₀ h0, relindex_eq_one] + exact h.not_le + variable (H K) @[to_additive] diff --git a/Mathlib/GroupTheory/NoncommPiCoprod.lean b/Mathlib/GroupTheory/NoncommPiCoprod.lean index 3e22ae8416ac7..e5b14b7d09118 100644 --- a/Mathlib/GroupTheory/NoncommPiCoprod.lean +++ b/Mathlib/GroupTheory/NoncommPiCoprod.lean @@ -30,7 +30,7 @@ images of different morphisms commute, we obtain a canonical morphism * `MonoidHom.noncommPiCoprod_range`: The range of `MonoidHom.noncommPiCoprod` is `⨆ (i : ι), (ϕ i).range` * `Subgroup.noncommPiCoprod_range`: The range of `Subgroup.noncommPiCoprod` is `⨆ (i : ι), H i`. -* `MonoidHom.injective_noncommPiCoprod_of_independent`: in the case of groups, `pi_hom.hom` is +* `MonoidHom.injective_noncommPiCoprod_of_iSupIndep`: in the case of groups, `pi_hom.hom` is injective if the `ϕ` are injective and the ranges of the `ϕ` are independent. * `MonoidHom.independent_range_of_coprime_order`: If the `N i` have coprime orders, then the ranges of the `ϕ` are independent. @@ -48,8 +48,8 @@ variable {G : Type*} [Group G] generalizes (one direction of) `Subgroup.disjoint_iff_mul_eq_one`. -/ @[to_additive "`Finset.noncommSum` is “injective” in `f` if `f` maps into independent subgroups. This generalizes (one direction of) `AddSubgroup.disjoint_iff_add_eq_zero`. "] -theorem eq_one_of_noncommProd_eq_one_of_independent {ι : Type*} (s : Finset ι) (f : ι → G) (comm) - (K : ι → Subgroup G) (hind : CompleteLattice.Independent K) (hmem : ∀ x ∈ s, f x ∈ K x) +theorem eq_one_of_noncommProd_eq_one_of_iSupIndep {ι : Type*} (s : Finset ι) (f : ι → G) (comm) + (K : ι → Subgroup G) (hind : iSupIndep K) (hmem : ∀ x ∈ s, f x ∈ K x) (heq1 : s.noncommProd f comm = 1) : ∀ i ∈ s, f i = 1 := by classical revert heq1 @@ -73,6 +73,9 @@ theorem eq_one_of_noncommProd_eq_one_of_independent {ι : Type*} (s : Finset ι) · exact heq1i · refine ih hcomm hmem.2 heq1S _ h +@[deprecated (since := "2024-11-24")] +alias eq_one_of_noncommProd_eq_one_of_independent := eq_one_of_noncommProd_eq_one_of_iSupIndep + end Subgroup section FamilyOfMonoids @@ -200,27 +203,30 @@ theorem noncommPiCoprod_range [Fintype ι] exact ⟨Pi.mulSingle i y, noncommPiCoprod_mulSingle _ _ _⟩ @[to_additive] -theorem injective_noncommPiCoprod_of_independent [Fintype ι] +theorem injective_noncommPiCoprod_of_iSupIndep [Fintype ι] {hcomm : Pairwise fun i j : ι => ∀ (x : H i) (y : H j), Commute (ϕ i x) (ϕ j y)} - (hind : CompleteLattice.Independent fun i => (ϕ i).range) + (hind : iSupIndep fun i => (ϕ i).range) (hinj : ∀ i, Function.Injective (ϕ i)) : Function.Injective (noncommPiCoprod ϕ hcomm) := by classical apply (MonoidHom.ker_eq_bot_iff _).mp rw [eq_bot_iff] intro f heq1 have : ∀ i, i ∈ Finset.univ → ϕ i (f i) = 1 := - Subgroup.eq_one_of_noncommProd_eq_one_of_independent _ _ (fun _ _ _ _ h => hcomm h _ _) + Subgroup.eq_one_of_noncommProd_eq_one_of_iSupIndep _ _ (fun _ _ _ _ h => hcomm h _ _) _ hind (by simp) heq1 ext i apply hinj simp [this i (Finset.mem_univ i)] +@[deprecated (since := "2024-11-24")] +alias injective_noncommPiCoprod_of_independent := injective_noncommPiCoprod_of_iSupIndep + @[to_additive] theorem independent_range_of_coprime_order (hcomm : Pairwise fun i j : ι => ∀ (x : H i) (y : H j), Commute (ϕ i x) (ϕ j y)) [Finite ι] [∀ i, Fintype (H i)] (hcoprime : Pairwise fun i j => Nat.Coprime (Fintype.card (H i)) (Fintype.card (H j))) : - CompleteLattice.Independent fun i => (ϕ i).range := by + iSupIndep fun i => (ϕ i).range := by cases nonempty_fintype ι letI := Classical.decEq ι rintro i @@ -279,7 +285,7 @@ theorem independent_of_coprime_order (hcomm : Pairwise fun i j : ι => ∀ x y : G, x ∈ H i → y ∈ H j → Commute x y) [Finite ι] [∀ i, Fintype (H i)] (hcoprime : Pairwise fun i j => Nat.Coprime (Fintype.card (H i)) (Fintype.card (H j))) : - CompleteLattice.Independent H := by + iSupIndep H := by simpa using MonoidHom.independent_range_of_coprime_order (fun i => (H i).subtype) (commute_subtype_of_commute hcomm) hcoprime @@ -306,11 +312,11 @@ theorem noncommPiCoprod_range simp [noncommPiCoprod, MonoidHom.noncommPiCoprod_range] @[to_additive] -theorem injective_noncommPiCoprod_of_independent +theorem injective_noncommPiCoprod_of_iSupIndep {hcomm : Pairwise fun i j : ι => ∀ x y : G, x ∈ H i → y ∈ H j → Commute x y} - (hind : CompleteLattice.Independent H) : + (hind : iSupIndep H) : Function.Injective (noncommPiCoprod hcomm) := by - apply MonoidHom.injective_noncommPiCoprod_of_independent + apply MonoidHom.injective_noncommPiCoprod_of_iSupIndep · simpa using hind · intro i exact Subtype.coe_injective diff --git a/Mathlib/GroupTheory/OrderOfElement.lean b/Mathlib/GroupTheory/OrderOfElement.lean index b380c1f71c410..b18e30f62e781 100644 --- a/Mathlib/GroupTheory/OrderOfElement.lean +++ b/Mathlib/GroupTheory/OrderOfElement.lean @@ -88,9 +88,14 @@ theorem not_isOfFinOrder_of_injective_pow {x : G} (h : Injective fun n : ℕ => theorem IsOfFinOrder.one : IsOfFinOrder (1 : G) := isOfFinOrder_iff_pow_eq_one.mpr ⟨1, Nat.one_pos, one_pow 1⟩ -@[to_additive (attr := deprecated (since := "2024-10-11"))] +@[to_additive] alias isOfFinOrder_one := IsOfFinOrder.one +-- `alias` doesn't add the deprecation suggestion to the `to_additive` version +-- see https://github.com/leanprover-community/mathlib4/issues/19424 +attribute [deprecated IsOfFinOrder.one (since := "2024-10-11")] isOfFinOrder_one +attribute [deprecated IsOfFinAddOrder.zero (since := "2024-10-11")] isOfFinAddOrder_zero + @[to_additive] lemma IsOfFinOrder.pow {n : ℕ} : IsOfFinOrder a → IsOfFinOrder (a ^ n) := by simp_rw [isOfFinOrder_iff_pow_eq_one] diff --git a/Mathlib/GroupTheory/PGroup.lean b/Mathlib/GroupTheory/PGroup.lean index 9b119d28f05df..071291b214ad5 100644 --- a/Mathlib/GroupTheory/PGroup.lean +++ b/Mathlib/GroupTheory/PGroup.lean @@ -189,7 +189,7 @@ theorem card_modEq_card_fixedPoints : Nat.card α ≡ Nat.card (fixedPoints G α theorem nonempty_fixed_point_of_prime_not_dvd_card (α) [MulAction G α] (hpα : ¬p ∣ Nat.card α) : (fixedPoints G α).Nonempty := have : Finite α := Nat.finite_of_card_ne_zero (fun h ↦ (h ▸ hpα) (dvd_zero p)) - @Set.nonempty_of_nonempty_subtype _ _ + @Set.Nonempty.of_subtype _ _ (by rw [← Finite.card_pos_iff, pos_iff_ne_zero] contrapose! hpα diff --git a/Mathlib/GroupTheory/Perm/ClosureSwap.lean b/Mathlib/GroupTheory/Perm/ClosureSwap.lean index b00b89f6c6ce7..2256c8a2e0210 100644 --- a/Mathlib/GroupTheory/Perm/ClosureSwap.lean +++ b/Mathlib/GroupTheory/Perm/ClosureSwap.lean @@ -3,6 +3,7 @@ Copyright (c) 2024 Thomas Browning, Junyan Xu. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Thomas Browning, Junyan Xu -/ +import Mathlib.Algebra.Group.Subgroup.Ker import Mathlib.GroupTheory.GroupAction.Basic import Mathlib.GroupTheory.GroupAction.FixedPoints import Mathlib.GroupTheory.Perm.Support diff --git a/Mathlib/GroupTheory/Perm/Cycle/Type.lean b/Mathlib/GroupTheory/Perm/Cycle/Type.lean index 7b8e2f1c0b26d..b47673b955137 100644 --- a/Mathlib/GroupTheory/Perm/Cycle/Type.lean +++ b/Mathlib/GroupTheory/Perm/Cycle/Type.lean @@ -394,12 +394,12 @@ section Cauchy variable (G : Type*) [Group G] (n : ℕ) /-- The type of vectors with terms from `G`, length `n`, and product equal to `1:G`. -/ -def vectorsProdEqOne : Set (Vector G n) := +def vectorsProdEqOne : Set (Mathlib.Vector G n) := { v | v.toList.prod = 1 } namespace VectorsProdEqOne -theorem mem_iff {n : ℕ} (v : Vector G n) : v ∈ vectorsProdEqOne G n ↔ v.toList.prod = 1 := +theorem mem_iff {n : ℕ} (v : Mathlib.Vector G n) : v ∈ vectorsProdEqOne G n ↔ v.toList.prod = 1 := Iff.rfl theorem zero_eq : vectorsProdEqOne G 0 = {Vector.nil} := @@ -421,7 +421,7 @@ instance oneUnique : Unique (vectorsProdEqOne G 1) := by /-- Given a vector `v` of length `n`, make a vector of length `n + 1` whose product is `1`, by appending the inverse of the product of `v`. -/ @[simps] -def vectorEquiv : Vector G n ≃ vectorsProdEqOne G (n + 1) where +def vectorEquiv : Mathlib.Vector G n ≃ vectorsProdEqOne G (n + 1) where toFun v := ⟨v.toList.prod⁻¹ ::ᵥ v, by rw [mem_iff, Vector.toList_cons, List.prod_cons, inv_mul_cancel]⟩ invFun v := v.1.tail @@ -436,12 +436,12 @@ def vectorEquiv : Vector G n ≃ vectorsProdEqOne G (n + 1) where /-- Given a vector `v` of length `n` whose product is 1, make a vector of length `n - 1`, by deleting the last entry of `v`. -/ -def equivVector : ∀ n, vectorsProdEqOne G n ≃ Vector G (n - 1) +def equivVector : ∀ n, vectorsProdEqOne G n ≃ Mathlib.Vector G (n - 1) | 0 => (equivOfUnique (vectorsProdEqOne G 0) (vectorsProdEqOne G 1)).trans (vectorEquiv G 0).symm | (n + 1) => (vectorEquiv G n).symm instance [Fintype G] : Fintype (vectorsProdEqOne G n) := - Fintype.ofEquiv (Vector G (n - 1)) (equivVector G n).symm + Fintype.ofEquiv (Mathlib.Vector G (n - 1)) (equivVector G n).symm theorem card [Fintype G] : Fintype.card (vectorsProdEqOne G n) = Fintype.card G ^ (n - 1) := (Fintype.card_congr (equivVector G n)).trans (card_vector (n - 1)) diff --git a/Mathlib/GroupTheory/Perm/Sign.lean b/Mathlib/GroupTheory/Perm/Sign.lean index d09dd86518f64..bfb55453b7c78 100644 --- a/Mathlib/GroupTheory/Perm/Sign.lean +++ b/Mathlib/GroupTheory/Perm/Sign.lean @@ -3,14 +3,15 @@ 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.Subgroup.Basic +import Mathlib.Algebra.Group.Conj +import Mathlib.Algebra.Group.Subgroup.Lattice import Mathlib.Algebra.Group.Submonoid.Membership import Mathlib.Algebra.Ring.Int.Units import Mathlib.Data.Finset.Fin import Mathlib.Data.Finset.Sort +import Mathlib.Data.Fintype.Prod import Mathlib.Data.Fintype.Sum import Mathlib.Data.Int.Order.Units -import Mathlib.Data.Fintype.Prod import Mathlib.GroupTheory.Perm.Support import Mathlib.Logic.Equiv.Fin import Mathlib.Tactic.NormNum.Ineq diff --git a/Mathlib/GroupTheory/PresentedGroup.lean b/Mathlib/GroupTheory/PresentedGroup.lean index ddfb60a247e99..dccb34fb884fd 100644 --- a/Mathlib/GroupTheory/PresentedGroup.lean +++ b/Mathlib/GroupTheory/PresentedGroup.lean @@ -3,6 +3,7 @@ Copyright (c) 2019 Michael Howes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Michael Howes, Newell Jensen -/ +import Mathlib.Algebra.Group.Subgroup.Basic import Mathlib.GroupTheory.FreeGroup.Basic import Mathlib.GroupTheory.QuotientGroup.Defs diff --git a/Mathlib/GroupTheory/QuotientGroup/Defs.lean b/Mathlib/GroupTheory/QuotientGroup/Defs.lean index f193d7652942f..d33a94cc017c6 100644 --- a/Mathlib/GroupTheory/QuotientGroup/Defs.lean +++ b/Mathlib/GroupTheory/QuotientGroup/Defs.lean @@ -5,7 +5,7 @@ Authors: Kevin Buzzard, Patrick Massot -/ -- This file is to a certain extent based on `quotient_module.lean` by Johannes Hölzl. -import Mathlib.Algebra.Group.Subgroup.Basic +import Mathlib.Algebra.Group.Subgroup.Ker import Mathlib.GroupTheory.Congruence.Hom import Mathlib.GroupTheory.Coset.Defs diff --git a/Mathlib/GroupTheory/SemidirectProduct.lean b/Mathlib/GroupTheory/SemidirectProduct.lean index f3ac71a7ce4c7..f89efaef708f7 100644 --- a/Mathlib/GroupTheory/SemidirectProduct.lean +++ b/Mathlib/GroupTheory/SemidirectProduct.lean @@ -3,7 +3,8 @@ Copyright (c) 2020 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes -/ -import Mathlib.Algebra.Group.Subgroup.Basic +import Mathlib.Algebra.Group.Aut +import Mathlib.Algebra.Group.Subgroup.Ker /-! # Semidirect product diff --git a/Mathlib/GroupTheory/SpecificGroups/Alternating.lean b/Mathlib/GroupTheory/SpecificGroups/Alternating.lean index 982ee49d373ef..8b0f82d484a0d 100644 --- a/Mathlib/GroupTheory/SpecificGroups/Alternating.lean +++ b/Mathlib/GroupTheory/SpecificGroups/Alternating.lean @@ -78,7 +78,6 @@ theorem IsThreeCycle.mem_alternatingGroup {f : Perm α} (h : IsThreeCycle f) : f ∈ alternatingGroup α := Perm.mem_alternatingGroup.mpr h.sign -set_option linter.deprecated false in theorem finRotate_bit1_mem_alternatingGroup {n : ℕ} : finRotate (2 * n + 1) ∈ alternatingGroup (Fin (2 * n + 1)) := by rw [mem_alternatingGroup, sign_finRotate, pow_mul, pow_two, Int.units_mul_self, one_pow] diff --git a/Mathlib/GroupTheory/SpecificGroups/Cyclic.lean b/Mathlib/GroupTheory/SpecificGroups/Cyclic.lean index ca2a56cc761c7..d13254a943cc7 100644 --- a/Mathlib/GroupTheory/SpecificGroups/Cyclic.lean +++ b/Mathlib/GroupTheory/SpecificGroups/Cyclic.lean @@ -327,10 +327,17 @@ lemma isCyclic_iff_exists_ofOrder_eq_natCard [Finite α] : refine isCyclic_of_orderOf_eq_card g ?_ simp [hg] -@[to_additive (attr := deprecated (since := "2024-04-20"))] +@[to_additive] protected alias IsCyclic.iff_exists_ofOrder_eq_natCard_of_Fintype := isCyclic_iff_exists_ofOrder_eq_natCard +-- `alias` doesn't add the deprecation suggestion to the `to_additive` version +-- see https://github.com/leanprover-community/mathlib4/issues/19424 +attribute [deprecated isCyclic_iff_exists_ofOrder_eq_natCard (since := "2024-04-20")] +IsCyclic.iff_exists_ofOrder_eq_natCard_of_Fintype +attribute [deprecated isAddCyclic_iff_exists_ofOrder_eq_natCard (since := "2024-04-20")] +IsAddCyclic.iff_exists_ofOrder_eq_natCard_of_Fintype + section variable [Fintype α] @@ -551,7 +558,7 @@ instance (priority := 100) isCyclic : IsCyclic α := by theorem prime_card [Finite α] : (Nat.card α).Prime := by have h0 : 0 < Nat.card α := Nat.card_pos obtain ⟨g, hg⟩ := IsCyclic.exists_generator (α := α) - rw [Nat.prime_def_lt''] + rw [Nat.prime_def] refine ⟨Finite.one_lt_card_iff_nontrivial.2 inferInstance, fun n hn => ?_⟩ refine (IsSimpleOrder.eq_bot_or_eq_top (Subgroup.zpowers (g ^ n))).symm.imp ?_ ?_ · intro h diff --git a/Mathlib/GroupTheory/SpecificGroups/Quaternion.lean b/Mathlib/GroupTheory/SpecificGroups/Quaternion.lean index 3ce9f9ecba4d9..318e8a450260d 100644 --- a/Mathlib/GroupTheory/SpecificGroups/Quaternion.lean +++ b/Mathlib/GroupTheory/SpecificGroups/Quaternion.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Julian Kuelshammer -/ import Mathlib.Data.ZMod.Basic -import Mathlib.Algebra.Group.Nat import Mathlib.Tactic.IntervalCases import Mathlib.GroupTheory.SpecificGroups.Dihedral import Mathlib.GroupTheory.SpecificGroups.Cyclic diff --git a/Mathlib/GroupTheory/Subgroup/Saturated.lean b/Mathlib/GroupTheory/Subgroup/Saturated.lean index 6cbc7b2c45d71..e68e30ed0f303 100644 --- a/Mathlib/GroupTheory/Subgroup/Saturated.lean +++ b/Mathlib/GroupTheory/Subgroup/Saturated.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.Algebra.Group.Subgroup.Basic +import Mathlib.Algebra.Group.Subgroup.Ker import Mathlib.Algebra.NoZeroSMulDivisors.Defs /-! diff --git a/Mathlib/GroupTheory/Sylow.lean b/Mathlib/GroupTheory/Sylow.lean index 5521719559622..fdfa524a631b9 100644 --- a/Mathlib/GroupTheory/Sylow.lean +++ b/Mathlib/GroupTheory/Sylow.lean @@ -806,7 +806,7 @@ noncomputable def directProductOfNormal [Finite G] apply MulEquiv.ofBijective (Subgroup.noncommPiCoprod hcomm) apply (Fintype.bijective_iff_injective_and_card _).mpr constructor - · apply Subgroup.injective_noncommPiCoprod_of_independent + · apply Subgroup.injective_noncommPiCoprod_of_iSupIndep apply independent_of_coprime_order hcomm rintro ⟨p₁, hp₁⟩ ⟨p₂, hp₂⟩ hne haveI hp₁' := Fact.mk (Nat.prime_of_mem_primeFactors hp₁) diff --git a/Mathlib/LinearAlgebra/AffineSpace/AffineEquiv.lean b/Mathlib/LinearAlgebra/AffineSpace/AffineEquiv.lean index 20adcbf583239..75e11673b7d74 100644 --- a/Mathlib/LinearAlgebra/AffineSpace/AffineEquiv.lean +++ b/Mathlib/LinearAlgebra/AffineSpace/AffineEquiv.lean @@ -422,7 +422,7 @@ theorem constVAdd_symm (v : V₁) : (constVAdd k P₁ v).symm = constVAdd k P₁ /-- A more bundled version of `AffineEquiv.constVAdd`. -/ @[simps] def constVAddHom : Multiplicative V₁ →* P₁ ≃ᵃ[k] P₁ where - toFun v := constVAdd k P₁ (Multiplicative.toAdd v) + toFun v := constVAdd k P₁ v.toAdd map_one' := constVAdd_zero _ _ map_mul' := constVAdd_add _ P₁ @@ -486,22 +486,26 @@ theorem pointReflection_self (x : P₁) : pointReflection k x x = x := theorem pointReflection_involutive (x : P₁) : Involutive (pointReflection k x : P₁ → P₁) := Equiv.pointReflection_involutive x -set_option linter.deprecated false in /-- `x` is the only fixed point of `pointReflection x`. This lemma requires `x + x = y + y ↔ x = y`. There is no typeclass to use here, so we add it as an explicit argument. -/ -theorem pointReflection_fixed_iff_of_injective_bit0 {x y : P₁} (h : Injective (2 • · : V₁ → V₁)) : - pointReflection k x y = y ↔ y = x := - Equiv.pointReflection_fixed_iff_of_injective_bit0 h +theorem pointReflection_fixed_iff_of_injective_two_nsmul {x y : P₁} + (h : Injective (2 • · : V₁ → V₁)) : pointReflection k x y = y ↔ y = x := + Equiv.pointReflection_fixed_iff_of_injective_two_nsmul h + +@[deprecated (since := "2024-11-18")] alias pointReflection_fixed_iff_of_injective_bit0 := +pointReflection_fixed_iff_of_injective_two_nsmul -set_option linter.deprecated false in -theorem injective_pointReflection_left_of_injective_bit0 +theorem injective_pointReflection_left_of_injective_two_nsmul (h : Injective (2 • · : V₁ → V₁)) (y : P₁) : Injective fun x : P₁ => pointReflection k x y := - Equiv.injective_pointReflection_left_of_injective_bit0 h y + Equiv.injective_pointReflection_left_of_injective_two_nsmul h y + +@[deprecated (since := "2024-11-18")] alias injective_pointReflection_left_of_injective_bit0 := +injective_pointReflection_left_of_injective_two_nsmul theorem injective_pointReflection_left_of_module [Invertible (2 : k)] : ∀ y, Injective fun x : P₁ => pointReflection k x y := - injective_pointReflection_left_of_injective_bit0 k fun x y h => by + injective_pointReflection_left_of_injective_two_nsmul k fun x y h => by dsimp at h rwa [two_nsmul, two_nsmul, ← two_smul k x, ← two_smul k y, (isUnit_of_invertible (2 : k)).smul_left_cancel] at h diff --git a/Mathlib/LinearAlgebra/AffineSpace/AffineMap.lean b/Mathlib/LinearAlgebra/AffineSpace/AffineMap.lean index 71f99e5c85dde..259da107ba011 100644 --- a/Mathlib/LinearAlgebra/AffineSpace/AffineMap.lean +++ b/Mathlib/LinearAlgebra/AffineSpace/AffineMap.lean @@ -3,7 +3,7 @@ Copyright (c) 2020 Joseph Myers. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Joseph Myers -/ -import Mathlib.Data.Set.Pointwise.Interval +import Mathlib.Algebra.Order.Group.Pointwise.Interval import Mathlib.LinearAlgebra.AffineSpace.Basic import Mathlib.LinearAlgebra.BilinearMap import Mathlib.LinearAlgebra.Pi diff --git a/Mathlib/LinearAlgebra/AffineSpace/Independent.lean b/Mathlib/LinearAlgebra/AffineSpace/Independent.lean index 9476da73472ed..308268392107c 100644 --- a/Mathlib/LinearAlgebra/AffineSpace/Independent.lean +++ b/Mathlib/LinearAlgebra/AffineSpace/Independent.lean @@ -618,7 +618,7 @@ theorem affineIndependent_of_ne {p₁ p₂ : P} (h : p₁ ≠ p₂) : AffineInde ext fin_cases i · simp at hi - · simp only [Fin.val_one] + · simp haveI : Unique { x // x ≠ (0 : Fin 2) } := ⟨⟨i₁⟩, he'⟩ apply linearIndependent_unique rw [he' default] diff --git a/Mathlib/LinearAlgebra/BilinearForm/Basic.lean b/Mathlib/LinearAlgebra/BilinearForm/Basic.lean index 0768933dedc46..da171b8d6bfaa 100644 --- a/Mathlib/LinearAlgebra/BilinearForm/Basic.lean +++ b/Mathlib/LinearAlgebra/BilinearForm/Basic.lean @@ -58,7 +58,7 @@ namespace LinearMap namespace BilinForm -@[deprecated (since := "2024-04-14")] +@[deprecated "No deprecation message was provided." (since := "2024-04-14")] theorem coeFn_congr : ∀ {x x' y y' : M}, x = x' → y = y' → B x y = B x' y' | _, _, _, _, rfl, rfl => rfl @@ -101,7 +101,7 @@ theorem ext (H : ∀ x y : M, B x y = D x y) : B = D := ext₂ H theorem congr_fun (h : B = D) (x y : M) : B x y = D x y := congr_fun₂ h _ _ -@[deprecated (since := "2024-04-14")] +@[deprecated "No deprecation message was provided." (since := "2024-04-14")] theorem coe_zero : ⇑(0 : BilinForm R M) = 0 := rfl @@ -111,7 +111,7 @@ theorem zero_apply (x y : M) : (0 : BilinForm R M) x y = 0 := variable (B D B₁ D₁) -@[deprecated (since := "2024-04-14")] +@[deprecated "No deprecation message was provided." (since := "2024-04-14")] theorem coe_add : ⇑(B + D) = B + D := rfl @@ -119,7 +119,7 @@ theorem coe_add : ⇑(B + D) = B + D := theorem add_apply (x y : M) : (B + D) x y = B x y + D x y := rfl -@[deprecated (since := "2024-04-14")] +@[deprecated "No deprecation message was provided." (since := "2024-04-14")] theorem coe_neg : ⇑(-B₁) = -B₁ := rfl @@ -127,7 +127,7 @@ theorem coe_neg : ⇑(-B₁) = -B₁ := theorem neg_apply (x y : M₁) : (-B₁) x y = -B₁ x y := rfl -@[deprecated (since := "2024-04-14")] +@[deprecated "No deprecation message was provided." (since := "2024-04-14")] theorem coe_sub : ⇑(B₁ - D₁) = B₁ - D₁ := rfl diff --git a/Mathlib/LinearAlgebra/BilinearForm/Hom.lean b/Mathlib/LinearAlgebra/BilinearForm/Hom.lean index 9c011c36ed52b..c1b171f04d13e 100644 --- a/Mathlib/LinearAlgebra/BilinearForm/Hom.lean +++ b/Mathlib/LinearAlgebra/BilinearForm/Hom.lean @@ -58,16 +58,16 @@ section ToLin' def toLinHomAux₁ (A : BilinForm R M) (x : M) : M →ₗ[R] R := A x /-- Auxiliary definition to define `toLinHom`; see below. -/ -@[deprecated (since := "2024-04-26")] +@[deprecated "No deprecation message was provided." (since := "2024-04-26")] def toLinHomAux₂ (A : BilinForm R M) : M →ₗ[R] M →ₗ[R] R := A /-- The linear map obtained from a `BilinForm` by fixing the left co-ordinate and evaluating in the right. -/ -@[deprecated (since := "2024-04-26")] +@[deprecated "No deprecation message was provided." (since := "2024-04-26")] def toLinHom : BilinForm R M →ₗ[R] M →ₗ[R] M →ₗ[R] R := LinearMap.id set_option linter.deprecated false in -@[deprecated (since := "2024-04-26")] +@[deprecated "No deprecation message was provided." (since := "2024-04-26")] theorem toLin'_apply (A : BilinForm R M) (x : M) : toLinHom (M := M) A x = A x := rfl @@ -112,7 +112,7 @@ def LinearMap.toBilinAux (f : M →ₗ[R] M →ₗ[R] R) : BilinForm R M := f set_option linter.deprecated false in /-- Bilinear forms are linearly equivalent to maps with two arguments that are linear in both. -/ -@[deprecated (since := "2024-04-26")] +@[deprecated "No deprecation message was provided." (since := "2024-04-26")] def LinearMap.BilinForm.toLin : BilinForm R M ≃ₗ[R] M →ₗ[R] M →ₗ[R] R := { BilinForm.toLinHom with invFun := LinearMap.toBilinAux @@ -121,35 +121,35 @@ def LinearMap.BilinForm.toLin : BilinForm R M ≃ₗ[R] M →ₗ[R] M →ₗ[R] set_option linter.deprecated false in /-- A map with two arguments that is linear in both is linearly equivalent to bilinear form. -/ -@[deprecated (since := "2024-04-26")] +@[deprecated "No deprecation message was provided." (since := "2024-04-26")] def LinearMap.toBilin : (M →ₗ[R] M →ₗ[R] R) ≃ₗ[R] BilinForm R M := BilinForm.toLin.symm -@[deprecated (since := "2024-04-26")] +@[deprecated "No deprecation message was provided." (since := "2024-04-26")] theorem LinearMap.toBilinAux_eq (f : M →ₗ[R] M →ₗ[R] R) : LinearMap.toBilinAux f = f := rfl set_option linter.deprecated false in -@[deprecated (since := "2024-04-26")] +@[deprecated "No deprecation message was provided." (since := "2024-04-26")] theorem LinearMap.toBilin_symm : (LinearMap.toBilin.symm : BilinForm R M ≃ₗ[R] _) = BilinForm.toLin := rfl set_option linter.deprecated false in -@[deprecated (since := "2024-04-26")] +@[deprecated "No deprecation message was provided." (since := "2024-04-26")] theorem BilinForm.toLin_symm : (BilinForm.toLin.symm : _ ≃ₗ[R] BilinForm R M) = LinearMap.toBilin := LinearMap.toBilin.symm_symm set_option linter.deprecated false in -@[deprecated (since := "2024-04-26")] +@[deprecated "No deprecation message was provided." (since := "2024-04-26")] theorem LinearMap.toBilin_apply (f : M →ₗ[R] M →ₗ[R] R) (x y : M) : toBilin f x y = f x y := rfl set_option linter.deprecated false in -@[deprecated (since := "2024-04-26")] +@[deprecated "No deprecation message was provided." (since := "2024-04-26")] theorem BilinForm.toLin_apply (x : M) : BilinForm.toLin B x = B x := rfl diff --git a/Mathlib/LinearAlgebra/CliffordAlgebra/CategoryTheory.lean b/Mathlib/LinearAlgebra/CliffordAlgebra/CategoryTheory.lean index 2311b81349cc4..0b5239188f120 100644 --- a/Mathlib/LinearAlgebra/CliffordAlgebra/CategoryTheory.lean +++ b/Mathlib/LinearAlgebra/CliffordAlgebra/CategoryTheory.lean @@ -25,7 +25,7 @@ variable {R : Type u} [CommRing R] This is `CliffordAlgebra.map` through the lens of category theory. -/ @[simps] def QuadraticModuleCat.cliffordAlgebra : QuadraticModuleCat.{u} R ⥤ AlgebraCat.{u} R where - obj M := { carrier := CliffordAlgebra M.form } - map {_M _N} f := CliffordAlgebra.map f.toIsometry - map_id _M := CliffordAlgebra.map_id _ - map_comp {_M _N _P} f g := (CliffordAlgebra.map_comp_map g.toIsometry f.toIsometry).symm + obj M := AlgebraCat.of R (CliffordAlgebra M.form) + map {_M _N} f := AlgebraCat.ofHom <| CliffordAlgebra.map f.toIsometry + map_id _M := by simp + map_comp {_M _N _P} f g := by ext; simp diff --git a/Mathlib/LinearAlgebra/CliffordAlgebra/Grading.lean b/Mathlib/LinearAlgebra/CliffordAlgebra/Grading.lean index 39224b85617fe..d88ad52680183 100644 --- a/Mathlib/LinearAlgebra/CliffordAlgebra/Grading.lean +++ b/Mathlib/LinearAlgebra/CliffordAlgebra/Grading.lean @@ -75,7 +75,6 @@ nonrec theorem GradedAlgebra.ι_sq_scalar (m : M) : rw [GradedAlgebra.ι_apply Q, DirectSum.of_mul_of, DirectSum.algebraMap_apply] exact DirectSum.of_eq_of_gradedMonoid_eq (Sigma.subtype_ext rfl <| ι_sq_scalar _ _) -set_option linter.deprecated false in theorem GradedAlgebra.lift_ι_eq (i' : ZMod 2) (x' : evenOdd Q i') : -- Porting note: added a second `by apply` lift Q ⟨by apply GradedAlgebra.ι Q, by apply GradedAlgebra.ι_sq_scalar Q⟩ x' = @@ -85,29 +84,27 @@ theorem GradedAlgebra.lift_ι_eq (i' : ZMod 2) (x' : evenOdd Q i') : induction hx' using Submodule.iSup_induction' with | mem i x hx => obtain ⟨i, rfl⟩ := i - -- Porting note: `dsimp only [Subtype.coe_mk] at hx` doesn't work, use `change` instead - change x ∈ LinearMap.range (ι Q) ^ i at hx + dsimp only [Subtype.coe_mk] at hx induction hx using Submodule.pow_induction_on_left' with | algebraMap r => rw [AlgHom.commutes, DirectSum.algebraMap_apply]; rfl | add x y i hx hy ihx ihy => - -- Note: in https://github.com/leanprover-community/mathlib4/pull/8386 `map_add` had to be specialized to avoid a timeout - -- (the definition was already very slow) - rw [AlgHom.map_add, ihx, ihy, ← AddMonoidHom.map_add] + rw [map_add, ihx, ihy, ← AddMonoidHom.map_add] rfl | mem_mul m hm i x hx ih => obtain ⟨_, rfl⟩ := hm - rw [AlgHom.map_mul, ih, lift_ι_apply, GradedAlgebra.ι_apply Q, DirectSum.of_mul_of] + rw [map_mul, ih, lift_ι_apply, GradedAlgebra.ι_apply Q, DirectSum.of_mul_of] refine DirectSum.of_eq_of_gradedMonoid_eq (Sigma.subtype_ext ?_ ?_) <;> dsimp only [GradedMonoid.mk, Subtype.coe_mk] · rw [Nat.succ_eq_add_one, add_comm, Nat.cast_add, Nat.cast_one] rfl | zero => + set_option linter.deprecated false in rw [AlgHom.map_zero] apply Eq.symm apply DFinsupp.single_eq_zero.mpr; rfl | add x y hx hy ihx ihy => - rw [AlgHom.map_add, ihx, ihy, ← AddMonoidHom.map_add]; rfl + rw [map_add, ihx, ihy, ← AddMonoidHom.map_add]; rfl /-- The clifford algebra is graded by the even and odd parts. -/ instance gradedAlgebra : GradedAlgebra (evenOdd Q) := diff --git a/Mathlib/LinearAlgebra/DFinsupp.lean b/Mathlib/LinearAlgebra/DFinsupp.lean index 406aa08a4c032..f411c6bc0c1b5 100644 --- a/Mathlib/LinearAlgebra/DFinsupp.lean +++ b/Mathlib/LinearAlgebra/DFinsupp.lean @@ -390,8 +390,6 @@ theorem mem_iSup_finset_iff_exists_sum {s : Finset ι} (p : ι → Submodule R N end Submodule -namespace CompleteLattice - open DFinsupp section Semiring @@ -401,23 +399,26 @@ variable [DecidableEq ι] [Semiring R] [AddCommMonoid N] [Module R N] /-- Independence of a family of submodules can be expressed as a quantifier over `DFinsupp`s. This is an intermediate result used to prove -`CompleteLattice.independent_of_dfinsupp_lsum_injective` and -`CompleteLattice.Independent.dfinsupp_lsum_injective`. -/ -theorem independent_iff_forall_dfinsupp (p : ι → Submodule R N) : - Independent p ↔ +`iSupIndep_of_dfinsupp_lsum_injective` and +`iSupIndep.dfinsupp_lsum_injective`. -/ +theorem iSupIndep_iff_forall_dfinsupp (p : ι → Submodule R N) : + iSupIndep p ↔ ∀ (i) (x : p i) (v : Π₀ i : ι, ↥(p i)), lsum ℕ (M := fun i ↦ ↥(p i)) (fun i => (p i).subtype) (erase i v) = x → x = 0 := by - simp_rw [CompleteLattice.independent_def, Submodule.disjoint_def, + simp_rw [iSupIndep_def, Submodule.disjoint_def, Submodule.mem_biSup_iff_exists_dfinsupp, exists_imp, filter_ne_eq_erase] refine forall_congr' fun i => Subtype.forall'.trans ?_ simp_rw [Submodule.coe_eq_zero] +@[deprecated (since := "2024-11-24")] +alias independent_iff_forall_dfinsupp := iSupIndep_iff_forall_dfinsupp + /- If `DFinsupp.lsum` applied with `Submodule.subtype` is injective then the submodules are -independent. -/ -theorem independent_of_dfinsupp_lsum_injective (p : ι → Submodule R N) +iSupIndep. -/ +theorem iSupIndep_of_dfinsupp_lsum_injective (p : ι → Submodule R N) (h : Function.Injective (lsum ℕ (M := fun i ↦ ↥(p i)) fun i => (p i).subtype)) : - Independent p := by - rw [independent_iff_forall_dfinsupp] + iSupIndep p := by + rw [iSupIndep_iff_forall_dfinsupp] intro i x v hv replace hv : lsum ℕ (M := fun i ↦ ↥(p i)) (fun i => (p i).subtype) (erase i v) = lsum ℕ (M := fun i ↦ ↥(p i)) (fun i => (p i).subtype) (single i x) := by @@ -425,12 +426,18 @@ theorem independent_of_dfinsupp_lsum_injective (p : ι → Submodule R N) have := DFunLike.ext_iff.mp (h hv) i simpa [eq_comm] using this +@[deprecated (since := "2024-11-24")] +alias independent_of_dfinsupp_lsum_injective := iSupIndep_of_dfinsupp_lsum_injective + /- If `DFinsupp.sumAddHom` applied with `AddSubmonoid.subtype` is injective then the additive submonoids are independent. -/ -theorem independent_of_dfinsupp_sumAddHom_injective (p : ι → AddSubmonoid N) - (h : Function.Injective (sumAddHom fun i => (p i).subtype)) : Independent p := by - rw [← independent_map_orderIso_iff (AddSubmonoid.toNatSubmodule : AddSubmonoid N ≃o _)] - exact independent_of_dfinsupp_lsum_injective _ h +theorem iSupIndep_of_dfinsupp_sumAddHom_injective (p : ι → AddSubmonoid N) + (h : Function.Injective (sumAddHom fun i => (p i).subtype)) : iSupIndep p := by + rw [← iSupIndep_map_orderIso_iff (AddSubmonoid.toNatSubmodule : AddSubmonoid N ≃o _)] + exact iSupIndep_of_dfinsupp_lsum_injective _ h + +@[deprecated (since := "2024-11-24")] +alias independent_of_dfinsupp_sumAddHom_injective := iSupIndep_of_dfinsupp_sumAddHom_injective /-- Combining `DFinsupp.lsum` with `LinearMap.toSpanSingleton` is the same as `Finsupp.linearCombination` -/ @@ -450,24 +457,27 @@ section Ring variable [DecidableEq ι] [Ring R] [AddCommGroup N] [Module R N] -/- If `DFinsupp.sumAddHom` applied with `AddSubmonoid.subtype` is injective then the additive +/-- If `DFinsupp.sumAddHom` applied with `AddSubmonoid.subtype` is injective then the additive subgroups are independent. -/ -theorem independent_of_dfinsupp_sumAddHom_injective' (p : ι → AddSubgroup N) - (h : Function.Injective (sumAddHom fun i => (p i).subtype)) : Independent p := by - rw [← independent_map_orderIso_iff (AddSubgroup.toIntSubmodule : AddSubgroup N ≃o _)] - exact independent_of_dfinsupp_lsum_injective _ h +theorem iSupIndep_of_dfinsupp_sumAddHom_injective' (p : ι → AddSubgroup N) + (h : Function.Injective (sumAddHom fun i => (p i).subtype)) : iSupIndep p := by + rw [← iSupIndep_map_orderIso_iff (AddSubgroup.toIntSubmodule : AddSubgroup N ≃o _)] + exact iSupIndep_of_dfinsupp_lsum_injective _ h + +@[deprecated (since := "2024-11-24")] +alias independent_of_dfinsupp_sumAddHom_injective' := iSupIndep_of_dfinsupp_sumAddHom_injective' /-- The canonical map out of a direct sum of a family of submodules is injective when the submodules -are `CompleteLattice.Independent`. +are `iSupIndep`. Note that this is not generally true for `[Semiring R]`, for instance when `A` is the `ℕ`-submodules of the positive and negative integers. See `Counterexamples/DirectSumIsInternal.lean` for a proof of this fact. -/ -theorem Independent.dfinsupp_lsum_injective {p : ι → Submodule R N} (h : Independent p) : +theorem iSupIndep.dfinsupp_lsum_injective {p : ι → Submodule R N} (h : iSupIndep p) : Function.Injective (lsum ℕ (M := fun i ↦ ↥(p i)) fun i => (p i).subtype) := by -- simplify everything down to binders over equalities in `N` - rw [independent_iff_forall_dfinsupp] at h + rw [iSupIndep_iff_forall_dfinsupp] at h suffices LinearMap.ker (lsum ℕ (M := fun i ↦ ↥(p i)) fun i => (p i).subtype) = ⊥ by -- Lean can't find this without our help letI thisI : AddCommGroup (Π₀ i, p i) := inferInstance @@ -482,34 +492,46 @@ theorem Independent.dfinsupp_lsum_injective {p : ι → Submodule R N} (h : Inde rwa [← erase_add_single i m, LinearMap.map_add, lsum_single, Submodule.subtype_apply, add_eq_zero_iff_eq_neg, ← Submodule.coe_neg] at hm +@[deprecated (since := "2024-11-24")] +alias Independent.dfinsupp_lsum_injective := iSupIndep.dfinsupp_lsum_injective + /-- The canonical map out of a direct sum of a family of additive subgroups is injective when the -additive subgroups are `CompleteLattice.Independent`. -/ -theorem Independent.dfinsupp_sumAddHom_injective {p : ι → AddSubgroup N} (h : Independent p) : +additive subgroups are `iSupIndep`. -/ +theorem iSupIndep.dfinsupp_sumAddHom_injective {p : ι → AddSubgroup N} (h : iSupIndep p) : Function.Injective (sumAddHom fun i => (p i).subtype) := by - rw [← independent_map_orderIso_iff (AddSubgroup.toIntSubmodule : AddSubgroup N ≃o _)] at h + rw [← iSupIndep_map_orderIso_iff (AddSubgroup.toIntSubmodule : AddSubgroup N ≃o _)] at h exact h.dfinsupp_lsum_injective +@[deprecated (since := "2024-11-24")] +alias Independent.dfinsupp_sumAddHom_injective := iSupIndep.dfinsupp_sumAddHom_injective + /-- A family of submodules over an additive group are independent if and only iff `DFinsupp.lsum` applied with `Submodule.subtype` is injective. Note that this is not generally true for `[Semiring R]`; see -`CompleteLattice.Independent.dfinsupp_lsum_injective` for details. -/ -theorem independent_iff_dfinsupp_lsum_injective (p : ι → Submodule R N) : - Independent p ↔ Function.Injective (lsum ℕ (M := fun i ↦ ↥(p i)) fun i => (p i).subtype) := - ⟨Independent.dfinsupp_lsum_injective, independent_of_dfinsupp_lsum_injective p⟩ +`iSupIndep.dfinsupp_lsum_injective` for details. -/ +theorem iSupIndep_iff_dfinsupp_lsum_injective (p : ι → Submodule R N) : + iSupIndep p ↔ Function.Injective (lsum ℕ (M := fun i ↦ ↥(p i)) fun i => (p i).subtype) := + ⟨iSupIndep.dfinsupp_lsum_injective, iSupIndep_of_dfinsupp_lsum_injective p⟩ + +@[deprecated (since := "2024-11-24")] +alias independent_iff_dfinsupp_lsum_injective := iSupIndep_iff_dfinsupp_lsum_injective /-- A family of additive subgroups over an additive group are independent if and only if `DFinsupp.sumAddHom` applied with `AddSubgroup.subtype` is injective. -/ -theorem independent_iff_dfinsupp_sumAddHom_injective (p : ι → AddSubgroup N) : - Independent p ↔ Function.Injective (sumAddHom fun i => (p i).subtype) := - ⟨Independent.dfinsupp_sumAddHom_injective, independent_of_dfinsupp_sumAddHom_injective' p⟩ +theorem iSupIndep_iff_dfinsupp_sumAddHom_injective (p : ι → AddSubgroup N) : + iSupIndep p ↔ Function.Injective (sumAddHom fun i => (p i).subtype) := + ⟨iSupIndep.dfinsupp_sumAddHom_injective, iSupIndep_of_dfinsupp_sumAddHom_injective' p⟩ + +@[deprecated (since := "2024-11-24")] +alias independent_iff_dfinsupp_sumAddHom_injective := iSupIndep_iff_dfinsupp_sumAddHom_injective -/-- If a family of submodules is `Independent`, then a choice of nonzero vector from each submodule +/-- If a family of submodules is independent, then a choice of nonzero vector from each submodule forms a linearly independent family. -See also `CompleteLattice.Independent.linearIndependent'`. -/ -theorem Independent.linearIndependent [NoZeroSMulDivisors R N] {ι} (p : ι → Submodule R N) - (hp : Independent p) {v : ι → N} (hv : ∀ i, v i ∈ p i) (hv' : ∀ i, v i ≠ 0) : +See also `iSupIndep.linearIndependent'`. -/ +theorem iSupIndep.linearIndependent [NoZeroSMulDivisors R N] {ι} (p : ι → Submodule R N) + (hp : iSupIndep p) {v : ι → N} (hv : ∀ i, v i ∈ p i) (hv' : ∀ i, v i ≠ 0) : LinearIndependent R v := by let _ := Classical.decEq ι let _ := Classical.decEq R @@ -527,15 +549,19 @@ theorem Independent.linearIndependent [NoZeroSMulDivisors R N] {ι} (p : ι → simp only [coe_zero, Pi.zero_apply, ZeroMemClass.coe_zero, smul_eq_zero, ha] at this simpa -theorem independent_iff_linearIndependent_of_ne_zero [NoZeroSMulDivisors R N] {ι} {v : ι → N} - (h_ne_zero : ∀ i, v i ≠ 0) : (Independent fun i => R ∙ v i) ↔ LinearIndependent R v := +@[deprecated (since := "2024-11-24")] +alias Independent.linearIndependent := iSupIndep.linearIndependent + +theorem iSupIndep_iff_linearIndependent_of_ne_zero [NoZeroSMulDivisors R N] {ι} {v : ι → N} + (h_ne_zero : ∀ i, v i ≠ 0) : (iSupIndep fun i => R ∙ v i) ↔ LinearIndependent R v := let _ := Classical.decEq ι ⟨fun hv => hv.linearIndependent _ (fun i => Submodule.mem_span_singleton_self <| v i) h_ne_zero, - fun hv => hv.independent_span_singleton⟩ + fun hv => hv.iSupIndep_span_singleton⟩ -end Ring +@[deprecated (since := "2024-11-24")] +alias independent_iff_linearIndependent_of_ne_zero := iSupIndep_iff_linearIndependent_of_ne_zero -end CompleteLattice +end Ring namespace LinearMap diff --git a/Mathlib/LinearAlgebra/Dimension/Basic.lean b/Mathlib/LinearAlgebra/Dimension/Basic.lean index 254ddee6fae30..16bbd326c3112 100644 --- a/Mathlib/LinearAlgebra/Dimension/Basic.lean +++ b/Mathlib/LinearAlgebra/Dimension/Basic.lean @@ -353,13 +353,16 @@ theorem rank_subsingleton [Subsingleton R] : Module.rank R M = 1 := by subsingleton · exact hw.trans_eq (Cardinal.mk_singleton _).symm -lemma rank_le_of_smul_regular {S : Type*} [CommSemiring S] [Algebra S R] [Module S M] +lemma rank_le_of_isSMulRegular {S : Type*} [CommSemiring S] [Algebra S R] [Module S M] [IsScalarTower S R M] (L L' : Submodule R M) {s : S} (hr : IsSMulRegular M s) (h : ∀ x ∈ L, s • x ∈ L') : Module.rank R L ≤ Module.rank R L' := ((Algebra.lsmul S R M s).restrict h).rank_le_of_injective <| fun _ _ h ↦ by simpa using hr (Subtype.ext_iff.mp h) +@[deprecated (since := "2024-11-21")] +alias rank_le_of_smul_regular := rank_le_of_isSMulRegular + end end Module diff --git a/Mathlib/LinearAlgebra/Dimension/Finite.lean b/Mathlib/LinearAlgebra/Dimension/Finite.lean index 49fba6493d2d1..6c000a000aaf9 100644 --- a/Mathlib/LinearAlgebra/Dimension/Finite.lean +++ b/Mathlib/LinearAlgebra/Dimension/Finite.lean @@ -249,8 +249,8 @@ theorem Module.Finite.not_linearIndependent_of_infinite {ι : Type*} [Infinite section variable [NoZeroSMulDivisors R M] -theorem CompleteLattice.Independent.subtype_ne_bot_le_rank [Nontrivial R] - {V : ι → Submodule R M} (hV : CompleteLattice.Independent V) : +theorem iSupIndep.subtype_ne_bot_le_rank [Nontrivial R] + {V : ι → Submodule R M} (hV : iSupIndep V) : Cardinal.lift.{v} #{ i : ι // V i ≠ ⊥ } ≤ Cardinal.lift.{w} (Module.rank R M) := by set I := { i : ι // V i ≠ ⊥ } have hI : ∀ i : I, ∃ v ∈ V i, v ≠ (0 : M) := by @@ -261,10 +261,13 @@ theorem CompleteLattice.Independent.subtype_ne_bot_le_rank [Nontrivial R] have : LinearIndependent R v := (hV.comp Subtype.coe_injective).linearIndependent _ hvV hv exact this.cardinal_lift_le_rank +@[deprecated (since := "2024-11-24")] +alias CompleteLattice.Independent.subtype_ne_bot_le_rank := iSupIndep.subtype_ne_bot_le_rank + variable [Module.Finite R M] [StrongRankCondition R] -theorem CompleteLattice.Independent.subtype_ne_bot_le_finrank_aux - {p : ι → Submodule R M} (hp : CompleteLattice.Independent p) : +theorem iSupIndep.subtype_ne_bot_le_finrank_aux + {p : ι → Submodule R M} (hp : iSupIndep p) : #{ i // p i ≠ ⊥ } ≤ (finrank R M : Cardinal.{w}) := by suffices Cardinal.lift.{v} #{ i // p i ≠ ⊥ } ≤ Cardinal.lift.{v} (finrank R M : Cardinal.{w}) by rwa [Cardinal.lift_le] at this @@ -276,8 +279,8 @@ theorem CompleteLattice.Independent.subtype_ne_bot_le_finrank_aux /-- If `p` is an independent family of submodules of a `R`-finite module `M`, then the number of nontrivial subspaces in the family `p` is finite. -/ -noncomputable def CompleteLattice.Independent.fintypeNeBotOfFiniteDimensional - {p : ι → Submodule R M} (hp : CompleteLattice.Independent p) : +noncomputable def iSupIndep.fintypeNeBotOfFiniteDimensional + {p : ι → Submodule R M} (hp : iSupIndep p) : Fintype { i : ι // p i ≠ ⊥ } := by suffices #{ i // p i ≠ ⊥ } < (ℵ₀ : Cardinal.{w}) by rw [Cardinal.lt_aleph0_iff_fintype] at this @@ -289,9 +292,9 @@ noncomputable def CompleteLattice.Independent.fintypeNeBotOfFiniteDimensional number of nontrivial subspaces in the family `p` is bounded above by the dimension of `M`. Note that the `Fintype` hypothesis required here can be provided by -`CompleteLattice.Independent.fintypeNeBotOfFiniteDimensional`. -/ -theorem CompleteLattice.Independent.subtype_ne_bot_le_finrank - {p : ι → Submodule R M} (hp : CompleteLattice.Independent p) [Fintype { i // p i ≠ ⊥ }] : +`iSupIndep.fintypeNeBotOfFiniteDimensional`. -/ +theorem iSupIndep.subtype_ne_bot_le_finrank + {p : ι → Submodule R M} (hp : iSupIndep p) [Fintype { i // p i ≠ ⊥ }] : Fintype.card { i // p i ≠ ⊥ } ≤ finrank R M := by simpa using hp.subtype_ne_bot_le_finrank_aux end diff --git a/Mathlib/LinearAlgebra/Dimension/StrongRankCondition.lean b/Mathlib/LinearAlgebra/Dimension/StrongRankCondition.lean index 0e7836ca78bb4..71be346b20eaa 100644 --- a/Mathlib/LinearAlgebra/Dimension/StrongRankCondition.lean +++ b/Mathlib/LinearAlgebra/Dimension/StrongRankCondition.lean @@ -465,12 +465,15 @@ theorem LinearMap.finrank_range_le [Module.Finite R M] (f : M →ₗ[R] M') : finrank R (LinearMap.range f) ≤ finrank R M := finrank_le_finrank_of_rank_le_rank (lift_rank_range_le f) (rank_lt_aleph0 _ _) -theorem LinearMap.finrank_le_of_smul_regular {S : Type*} [CommSemiring S] [Algebra S R] [Module S M] - [IsScalarTower S R M] (L L' : Submodule R M) [Module.Finite R L'] {s : S} +theorem LinearMap.finrank_le_of_isSMulRegular {S : Type*} [CommSemiring S] [Algebra S R] + [Module S M] [IsScalarTower S R M] (L L' : Submodule R M) [Module.Finite R L'] {s : S} (hr : IsSMulRegular M s) (h : ∀ x ∈ L, s • x ∈ L') : Module.finrank R L ≤ Module.finrank R L' := by - refine finrank_le_finrank_of_rank_le_rank (lift_le.mpr <| rank_le_of_smul_regular L L' hr h) ?_ + refine finrank_le_finrank_of_rank_le_rank (lift_le.mpr <| rank_le_of_isSMulRegular L L' hr h) ?_ rw [← Module.finrank_eq_rank R L'] exact nat_lt_aleph0 (finrank R ↥L') +@[deprecated (since := "2024-11-21")] +alias LinearMap.finrank_le_of_smul_regular := LinearMap.finrank_le_of_isSMulRegular + end StrongRankCondition diff --git a/Mathlib/LinearAlgebra/Dual.lean b/Mathlib/LinearAlgebra/Dual.lean index 1ef8aede9c87b..a203905b0a8a2 100644 --- a/Mathlib/LinearAlgebra/Dual.lean +++ b/Mathlib/LinearAlgebra/Dual.lean @@ -339,11 +339,11 @@ theorem toDual_injective : Injective b.toDual := fun x y h ↦ b.ext_elem_iff.mp theorem toDual_inj (m : M) (a : b.toDual m = 0) : m = 0 := b.toDual_injective (by rwa [_root_.map_zero]) --- Porting note (https://github.com/leanprover-community/mathlib4/issues/11036): broken dot notation https://github.com/leanprover/lean4/issues/1910 LinearMap.ker +-- Porting note (https://github.com/leanprover-community/mathlib4/issues/11036): broken dot notation https://github.com/leanprover/lean4/issues/1629 LinearMap.ker theorem toDual_ker : LinearMap.ker b.toDual = ⊥ := ker_eq_bot'.mpr b.toDual_inj --- Porting note (https://github.com/leanprover-community/mathlib4/issues/11036): broken dot notation https://github.com/leanprover/lean4/issues/1910 LinearMap.range +-- Porting note (https://github.com/leanprover-community/mathlib4/issues/11036): broken dot notation https://github.com/leanprover/lean4/issues/1629 LinearMap.range 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) @@ -447,7 +447,7 @@ theorem eval_ker {ι : Type*} (b : Basis ι R M) : simp_rw [LinearMap.ext_iff, Dual.eval_apply, zero_apply] at hm exact (Basis.forall_coord_eq_zero_iff _).mp fun i => hm (b.coord i) --- Porting note (https://github.com/leanprover-community/mathlib4/issues/11036): broken dot notation https://github.com/leanprover/lean4/issues/1910 LinearMap.range +-- Porting note (https://github.com/leanprover-community/mathlib4/issues/11036): broken dot notation https://github.com/leanprover/lean4/issues/1629 LinearMap.range theorem eval_range {ι : Type*} [Finite ι] (b : Basis ι R M) : LinearMap.range (Dual.eval R M) = ⊤ := by classical @@ -501,7 +501,7 @@ section variable (K) (V) --- Porting note (https://github.com/leanprover-community/mathlib4/issues/11036): broken dot notation https://github.com/leanprover/lean4/issues/1910 LinearMap.ker +-- Porting note (https://github.com/leanprover-community/mathlib4/issues/11036): broken dot notation https://github.com/leanprover/lean4/issues/1629 LinearMap.ker theorem eval_ker : LinearMap.ker (eval K V) = ⊥ := have ⟨s, hs⟩ := Module.projective_def'.mp ‹Projective K V› ker_eq_bot.mpr <| .of_comp (f := s.dualMap.dualMap) <| (ker_eq_bot.mp <| @@ -595,7 +595,7 @@ instance (priority := 900) IsReflexive.of_finite_of_free [Module.Finite R M] [Fr variable [IsReflexive R M] --- Porting note (https://github.com/leanprover-community/mathlib4/issues/11036): broken dot notation https://github.com/leanprover/lean4/issues/1910 LinearMap.range +-- Porting note (https://github.com/leanprover-community/mathlib4/issues/11036): broken dot notation https://github.com/leanprover/lean4/issues/1629 LinearMap.range theorem erange_coe : LinearMap.range (eval R M) = ⊤ := range_eq_top.mpr (bijective_dual_eval _ _).2 @@ -943,7 +943,7 @@ theorem dualRestrict_apply (W : Submodule R M) (φ : Module.Dual R M) (x : W) : that `φ w = 0` for all `w ∈ W`. -/ def dualAnnihilator {R : Type u} {M : Type v} [CommSemiring R] [AddCommMonoid M] [Module R M] (W : Submodule R M) : Submodule R <| Module.Dual R M := --- Porting note (https://github.com/leanprover-community/mathlib4/issues/11036): broken dot notation https://github.com/leanprover/lean4/issues/1910 LinearMap.ker +-- Porting note (https://github.com/leanprover-community/mathlib4/issues/11036): broken dot notation https://github.com/leanprover/lean4/issues/1629 LinearMap.ker LinearMap.ker W.dualRestrict @[simp] @@ -955,7 +955,7 @@ theorem mem_dualAnnihilator (φ : Module.Dual R M) : φ ∈ W.dualAnnihilator /-- That $\operatorname{ker}(\iota^* : V^* \to W^*) = \operatorname{ann}(W)$. This is the definition of the dual annihilator of the submodule $W$. -/ theorem dualRestrict_ker_eq_dualAnnihilator (W : Submodule R M) : - -- Porting note (https://github.com/leanprover-community/mathlib4/issues/11036): broken dot notation https://github.com/leanprover/lean4/issues/1910 LinearMap.ker + -- Porting note (https://github.com/leanprover-community/mathlib4/issues/11036): broken dot notation https://github.com/leanprover/lean4/issues/1629 LinearMap.ker LinearMap.ker W.dualRestrict = W.dualAnnihilator := rfl @@ -1189,7 +1189,7 @@ theorem quotAnnihilatorEquiv_apply (W : Subspace K V) (φ : Module.Dual K V) : rfl /-- The natural isomorphism from the dual of a subspace `W` to `W.dualLift.range`. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/11036): broken dot notation https://github.com/leanprover/lean4/issues/1910 LinearMap.range +-- Porting note (https://github.com/leanprover-community/mathlib4/issues/11036): broken dot notation https://github.com/leanprover/lean4/issues/1629 LinearMap.range noncomputable def dualEquivDual (W : Subspace K V) : Module.Dual K W ≃ₗ[K] LinearMap.range W.dualLift := LinearEquiv.ofInjective _ dualLift_injective @@ -1228,7 +1228,7 @@ theorem dualAnnihilator_dualAnnihilator_eq (W : Subspace K V) : rwa [← OrderIso.symm_apply_eq] /-- The quotient by the dual is isomorphic to its dual annihilator. -/ --- Porting note (https://github.com/leanprover-community/mathlib4/issues/11036): broken dot notation https://github.com/leanprover/lean4/issues/1910 LinearMap.range +-- Porting note (https://github.com/leanprover-community/mathlib4/issues/11036): broken dot notation https://github.com/leanprover/lean4/issues/1629 LinearMap.range noncomputable def quotDualEquivAnnihilator (W : Subspace K V) : (Module.Dual K V ⧸ LinearMap.range W.dualLift) ≃ₗ[K] W.dualAnnihilator := LinearEquiv.quotEquivOfQuotEquiv <| LinearEquiv.trans W.quotAnnihilatorEquiv W.dualEquivDual @@ -1274,7 +1274,7 @@ variable {R : Type uR} [CommSemiring R] {M₁ : Type uM₁} {M₂ : Type uM₂} variable [AddCommMonoid M₁] [Module R M₁] [AddCommMonoid M₂] [Module R M₂] variable (f : M₁ →ₗ[R] M₂) --- Porting note (https://github.com/leanprover-community/mathlib4/issues/11036): broken dot notation https://github.com/leanprover/lean4/issues/1910 LinearMap.ker +-- Porting note (https://github.com/leanprover-community/mathlib4/issues/11036): broken dot notation https://github.com/leanprover/lean4/issues/1629 LinearMap.ker theorem ker_dualMap_eq_dualAnnihilator_range : LinearMap.ker f.dualMap = f.range.dualAnnihilator := by ext @@ -1282,7 +1282,7 @@ theorem ker_dualMap_eq_dualAnnihilator_range : ← SetLike.mem_coe, range_coe, Set.forall_mem_range] rfl --- Porting note (https://github.com/leanprover-community/mathlib4/issues/11036): broken dot notation https://github.com/leanprover/lean4/issues/1910 LinearMap.range +-- Porting note (https://github.com/leanprover-community/mathlib4/issues/11036): broken dot notation https://github.com/leanprover/lean4/issues/1629 LinearMap.range theorem range_dualMap_le_dualAnnihilator_ker : LinearMap.range f.dualMap ≤ f.ker.dualAnnihilator := by rintro _ ⟨ψ, rfl⟩ @@ -1338,7 +1338,7 @@ theorem dualPairing_apply {W : Submodule R M} (φ : Module.Dual R M) (x : W) : W.dualPairing (Quotient.mk φ) x = φ x := rfl --- Porting note (https://github.com/leanprover-community/mathlib4/issues/11036): broken dot notation https://github.com/leanprover/lean4/issues/1910 LinearMap.range +-- Porting note (https://github.com/leanprover-community/mathlib4/issues/11036): broken dot notation https://github.com/leanprover/lean4/issues/1629 LinearMap.range /-- That $\operatorname{im}(q^* : (V/W)^* \to V^*) = \operatorname{ann}(W)$. -/ theorem range_dualMap_mkQ_eq (W : Submodule R M) : LinearMap.range W.mkQ.dualMap = W.dualAnnihilator := by @@ -1360,7 +1360,7 @@ def dualQuotEquivDualAnnihilator (W : Submodule R M) : Module.Dual R (M ⧸ W) ≃ₗ[R] W.dualAnnihilator := LinearEquiv.ofLinear (W.mkQ.dualMap.codRestrict W.dualAnnihilator fun φ => --- Porting note (https://github.com/leanprover-community/mathlib4/issues/11036): broken dot notation https://github.com/leanprover/lean4/issues/1910 LinearMap.mem_range_self +-- Porting note (https://github.com/leanprover-community/mathlib4/issues/11036): broken dot notation https://github.com/leanprover/lean4/issues/1629 LinearMap.mem_range_self W.range_dualMap_mkQ_eq ▸ LinearMap.mem_range_self W.mkQ.dualMap φ) W.dualCopairing (by ext; rfl) (by ext; rfl) @@ -1415,7 +1415,7 @@ namespace LinearMap open Submodule --- Porting note (https://github.com/leanprover-community/mathlib4/issues/11036): broken dot notation https://github.com/leanprover/lean4/issues/1910 LinearMap.range +-- Porting note (https://github.com/leanprover-community/mathlib4/issues/11036): broken dot notation https://github.com/leanprover/lean4/issues/1629 LinearMap.range theorem range_dualMap_eq_dualAnnihilator_ker_of_surjective (f : M →ₗ[R] M') (hf : Function.Surjective f) : LinearMap.range f.dualMap = f.ker.dualAnnihilator := ((f.quotKerEquivOfSurjective hf).dualMap.range_comp _).trans f.ker.range_dualMap_mkQ_eq @@ -1429,7 +1429,7 @@ theorem range_dualMap_eq_dualAnnihilator_ker_of_subtype_range_surjective (f : M rw [← range_eq_top, range_rangeRestrict] have := range_dualMap_eq_dualAnnihilator_ker_of_surjective f.rangeRestrict rr_surj convert this using 1 - -- Porting note (https://github.com/leanprover-community/mathlib4/issues/11036): broken dot notation https://github.com/leanprover/lean4/issues/1910 + -- Porting note (https://github.com/leanprover-community/mathlib4/issues/11036): broken dot notation https://github.com/leanprover/lean4/issues/1629 · calc _ = range ((range f).subtype.comp f.rangeRestrict).dualMap := by simp _ = _ := ?_ @@ -1525,7 +1525,7 @@ theorem dualMap_surjective_of_injective {f : V₁ →ₗ[K] V₂} (hf : Function have ⟨f', hf'⟩ := f.exists_leftInverse_of_injective (ker_eq_bot.mpr hf) ⟨φ.comp f', ext fun x ↦ congr(φ <| $hf' x)⟩ - -- Porting note (https://github.com/leanprover-community/mathlib4/issues/11036): broken dot notation https://github.com/leanprover/lean4/issues/1910 LinearMap.range + -- Porting note (https://github.com/leanprover-community/mathlib4/issues/11036): broken dot notation https://github.com/leanprover/lean4/issues/1629 LinearMap.range theorem range_dualMap_eq_dualAnnihilator_ker (f : V₁ →ₗ[K] V₂) : LinearMap.range f.dualMap = f.ker.dualAnnihilator := range_dualMap_eq_dualAnnihilator_ker_of_subtype_range_surjective f <| @@ -1576,7 +1576,7 @@ theorem dualAnnihilator_inf_eq (W W' : Subspace K V₁) : (W ⊓ W').dualAnnihilator = W.dualAnnihilator ⊔ W'.dualAnnihilator := by refine le_antisymm ?_ (sup_dualAnnihilator_le_inf W W') let F : V₁ →ₗ[K] (V₁ ⧸ W) × V₁ ⧸ W' := (Submodule.mkQ W).prod (Submodule.mkQ W') - -- Porting note (https://github.com/leanprover-community/mathlib4/issues/11036): broken dot notation https://github.com/leanprover/lean4/issues/1910 LinearMap.ker + -- Porting note (https://github.com/leanprover-community/mathlib4/issues/11036): broken dot notation https://github.com/leanprover/lean4/issues/1629 LinearMap.ker have : LinearMap.ker F = W ⊓ W' := by simp only [F, LinearMap.ker_prod, ker_mkQ] rw [← this, ← LinearMap.range_dualMap_eq_dualAnnihilator_ker] intro φ @@ -1632,7 +1632,7 @@ namespace LinearMap @[simp] theorem finrank_range_dualMap_eq_finrank_range (f : V₁ →ₗ[K] V₂) : - -- Porting note (https://github.com/leanprover-community/mathlib4/issues/11036): broken dot notation https://github.com/leanprover/lean4/issues/1910 + -- Porting note (https://github.com/leanprover-community/mathlib4/issues/11036): broken dot notation https://github.com/leanprover/lean4/issues/1629 finrank K (LinearMap.range f.dualMap) = finrank K (LinearMap.range f) := by rw [congr_arg dualMap (show f = (range f).subtype.comp f.rangeRestrict by rfl), ← dualMap_comp_dualMap, range_comp, diff --git a/Mathlib/LinearAlgebra/Eigenspace/Basic.lean b/Mathlib/LinearAlgebra/Eigenspace/Basic.lean index 05c1324d366e9..3003ced8d18b7 100644 --- a/Mathlib/LinearAlgebra/Eigenspace/Basic.lean +++ b/Mathlib/LinearAlgebra/Eigenspace/Basic.lean @@ -664,11 +664,11 @@ lemma injOn_iSup_genEigenspace [NoZeroSMulDivisors R M] (f : End R M) : apply injOn_maxGenEigenspace theorem independent_genEigenspace [NoZeroSMulDivisors R M] (f : End R M) (k : ℕ∞) : - CompleteLattice.Independent (f.genEigenspace · k) := by + iSupIndep (f.genEigenspace · k) := by classical suffices ∀ μ₁ (s : Finset R), μ₁ ∉ s → Disjoint (f.genEigenspace μ₁ k) (s.sup fun μ ↦ f.genEigenspace μ k) by - simp_rw [CompleteLattice.independent_iff_supIndep_of_injOn (injOn_genEigenspace f k), + simp_rw [iSupIndep_iff_supIndep_of_injOn (injOn_genEigenspace f k), Finset.supIndep_iff_disjoint_erase] exact fun s μ _ ↦ this _ _ (s.not_mem_erase μ) intro μ₁ s @@ -703,27 +703,29 @@ theorem independent_genEigenspace [NoZeroSMulDivisors R M] (f : End R M) (k : rwa [ih.eq_bot, Submodule.mem_bot] at hyz theorem independent_maxGenEigenspace [NoZeroSMulDivisors R M] (f : End R M) : - CompleteLattice.Independent f.maxGenEigenspace := by + iSupIndep f.maxGenEigenspace := by apply independent_genEigenspace @[deprecated independent_genEigenspace (since := "2024-10-23")] theorem independent_iSup_genEigenspace [NoZeroSMulDivisors R M] (f : End R M) : - CompleteLattice.Independent (fun μ ↦ ⨆ k : ℕ, f.genEigenspace μ k) := by + iSupIndep (fun μ ↦ ⨆ k : ℕ, f.genEigenspace μ k) := by simp_rw [iSup_genEigenspace_eq] apply independent_maxGenEigenspace /-- The eigenspaces of a linear operator form an independent family of subspaces of `M`. That is, any eigenspace has trivial intersection with the span of all the other eigenspaces. -/ -theorem eigenspaces_independent [NoZeroSMulDivisors R M] (f : End R M) : - CompleteLattice.Independent f.eigenspace := +theorem eigenspaces_iSupIndep [NoZeroSMulDivisors R M] (f : End R M) : + iSupIndep f.eigenspace := (f.independent_genEigenspace 1).mono fun _ ↦ le_rfl +@[deprecated (since := "2024-11-24")] alias eigenspaces_independent := eigenspaces_iSupIndep + /-- Eigenvectors corresponding to distinct eigenvalues of a linear operator are linearly independent. -/ theorem eigenvectors_linearIndependent' {ι : Type*} [NoZeroSMulDivisors R M] (f : End R M) (μ : ι → R) (hμ : Function.Injective μ) (v : ι → M) (h_eigenvec : ∀ i, f.HasEigenvector (μ i) (v i)) : LinearIndependent R v := - f.eigenspaces_independent.comp hμ |>.linearIndependent _ + f.eigenspaces_iSupIndep.comp hμ |>.linearIndependent _ (fun i ↦ h_eigenvec i |>.left) (fun i ↦ h_eigenvec i |>.right) /-- Eigenvectors corresponding to distinct eigenvalues of a linear operator are linearly diff --git a/Mathlib/LinearAlgebra/Eigenspace/Matrix.lean b/Mathlib/LinearAlgebra/Eigenspace/Matrix.lean index 7ae63cc2e199b..0b327ae0fd03d 100644 --- a/Mathlib/LinearAlgebra/Eigenspace/Matrix.lean +++ b/Mathlib/LinearAlgebra/Eigenspace/Matrix.lean @@ -55,7 +55,7 @@ lemma hasEigenvalue_toLin_diagonal_iff (d : n → R) {μ : R} [NoZeroSMulDivisor rw [mem_eigenspace_iff] exact (hasEigenvector_toLin_diagonal d i b).apply_eq_smul have hμ_not_mem : μ ∉ Set.range d := by simpa using fun i ↦ (hμ i) - have := eigenspaces_independent (toLin b b (diagonal d)) |>.disjoint_biSup hμ_not_mem + have := eigenspaces_iSupIndep (toLin b b (diagonal d)) |>.disjoint_biSup hμ_not_mem rw [h_iSup, disjoint_top] at this exact h_eig this · rintro ⟨i, rfl⟩ diff --git a/Mathlib/LinearAlgebra/Eigenspace/Pi.lean b/Mathlib/LinearAlgebra/Eigenspace/Pi.lean index 9f089022d24ad..ddb8f9f9ea5ac 100644 --- a/Mathlib/LinearAlgebra/Eigenspace/Pi.lean +++ b/Mathlib/LinearAlgebra/Eigenspace/Pi.lean @@ -85,7 +85,7 @@ lemma injOn_iInf_maxGenEigenspace : lemma independent_iInf_maxGenEigenspace_of_forall_mapsTo (h : ∀ i j φ, MapsTo (f i) ((f j).maxGenEigenspace φ) ((f j).maxGenEigenspace φ)) : - CompleteLattice.Independent fun χ : ι → R ↦ ⨅ i, (f i).maxGenEigenspace (χ i) := by + iSupIndep fun χ : ι → R ↦ ⨅ i, (f i).maxGenEigenspace (χ i) := by replace h (l : ι) (χ : ι → R) : MapsTo (f l) (⨅ i, (f i).maxGenEigenspace (χ i)) (⨅ i, (f i).maxGenEigenspace (χ i)) := by intro x hx @@ -95,7 +95,7 @@ lemma independent_iInf_maxGenEigenspace_of_forall_mapsTo suffices ∀ χ (s : Finset (ι → R)) (_ : χ ∉ s), Disjoint (⨅ i, (f i).maxGenEigenspace (χ i)) (s.sup fun (χ : ι → R) ↦ ⨅ i, (f i).maxGenEigenspace (χ i)) by - simpa only [CompleteLattice.independent_iff_supIndep_of_injOn (injOn_iInf_maxGenEigenspace f), + simpa only [iSupIndep_iff_supIndep_of_injOn (injOn_iInf_maxGenEigenspace f), Finset.supIndep_iff_disjoint_erase] using fun s χ _ ↦ this _ _ (s.not_mem_erase χ) intro χ₁ s induction s using Finset.induction_on with diff --git a/Mathlib/LinearAlgebra/ExteriorAlgebra/Grading.lean b/Mathlib/LinearAlgebra/ExteriorAlgebra/Grading.lean index 81a29f1543817..d39a95c8a5d29 100644 --- a/Mathlib/LinearAlgebra/ExteriorAlgebra/Grading.lean +++ b/Mathlib/LinearAlgebra/ExteriorAlgebra/Grading.lean @@ -54,22 +54,16 @@ def GradedAlgebra.liftι : ExteriorAlgebra R M →ₐ[R] ⨁ i : ℕ, ⋀[R]^i M := lift R ⟨by apply GradedAlgebra.ι R M, GradedAlgebra.ι_sq_zero R M⟩ -set_option linter.deprecated false in theorem GradedAlgebra.liftι_eq (i : ℕ) (x : ⋀[R]^i M) : GradedAlgebra.liftι R M x = DirectSum.of (fun i => ⋀[R]^i M) i x := by cases' x with x hx dsimp only [Subtype.coe_mk, DirectSum.lof_eq_of] - -- Porting note: original statement was - -- refine Submodule.pow_induction_on_left' _ (fun r => ?_) (fun x y i hx hy ihx ihy => ?_) - -- (fun m hm i x hx ih => ?_) hx - -- but it created invalid goals induction hx using Submodule.pow_induction_on_left' with | algebraMap => simp_rw [AlgHom.commutes, DirectSum.algebraMap_apply]; rfl - -- FIXME: specialized `map_add` to avoid a (whole-declaration) timeout - | add _ _ _ _ _ ihx ihy => simp_rw [AlgHom.map_add, ihx, ihy, ← AddMonoidHom.map_add]; rfl + | add _ _ _ _ _ ihx ihy => simp_rw [map_add, ihx, ihy, ← AddMonoidHom.map_add]; rfl | mem_mul _ hm _ _ _ ih => obtain ⟨_, rfl⟩ := hm - simp_rw [AlgHom.map_mul, ih, GradedAlgebra.liftι, lift_ι_apply, GradedAlgebra.ι_apply R M, + simp_rw [map_mul, ih, GradedAlgebra.liftι, lift_ι_apply, GradedAlgebra.ι_apply R M, DirectSum.of_mul_of] exact DirectSum.of_eq_of_gradedMonoid_eq (Sigma.subtype_ext (add_comm _ _) rfl) diff --git a/Mathlib/LinearAlgebra/FreeModule/Basic.lean b/Mathlib/LinearAlgebra/FreeModule/Basic.lean index a53c69bdf4ff3..99e69913af94b 100644 --- a/Mathlib/LinearAlgebra/FreeModule/Basic.lean +++ b/Mathlib/LinearAlgebra/FreeModule/Basic.lean @@ -118,6 +118,27 @@ theorem of_equiv' {P : Type v} [AddCommMonoid P] [Module R P] (_ : Module.Free R (e : P ≃ₗ[R] N) : Module.Free R N := of_equiv e +attribute [local instance] RingHomInvPair.of_ringEquiv in +lemma of_ringEquiv {R R' M M'} [Semiring R] [AddCommMonoid M] [Module R M] + [Semiring R'] [AddCommMonoid M'] [Module R' M'] + (e₁ : R ≃+* R') (e₂ : M ≃ₛₗ[RingHomClass.toRingHom e₁] M') [Module.Free R M] : + Module.Free R' M' := by + let I := Module.Free.ChooseBasisIndex R M + obtain ⟨e₃ : M ≃ₗ[R] I →₀ R⟩ := Module.Free.chooseBasis R M + let e : M' ≃+ (I →₀ R') := + (e₂.symm.trans e₃).toAddEquiv.trans (Finsupp.mapRange.addEquiv (α := I) e₁.toAddEquiv) + have he (x) : e x = Finsupp.mapRange.addEquiv (α := I) e₁.toAddEquiv (e₃ (e₂.symm x)) := rfl + let e' : M' ≃ₗ[R'] (I →₀ R') := + { __ := e, map_smul' := fun m x ↦ Finsupp.ext fun i ↦ by simp [he, map_smulₛₗ] } + exact of_basis (.ofRepr e') + +attribute [local instance] RingHomInvPair.of_ringEquiv in +lemma iff_of_ringEquiv {R R' M M'} [Semiring R] [AddCommMonoid M] [Module R M] + [Semiring R'] [AddCommMonoid M'] [Module R' M'] + (e₁ : R ≃+* R') (e₂ : M ≃ₛₗ[RingHomClass.toRingHom e₁] M') : + Module.Free R M ↔ Module.Free R' M' := + ⟨fun _ ↦ of_ringEquiv e₁ e₂, fun _ ↦ of_ringEquiv e₁.symm e₂.symm⟩ + variable (R M N) /-- The module structure provided by `Semiring.toModule` is free. -/ diff --git a/Mathlib/LinearAlgebra/LinearIndependent.lean b/Mathlib/LinearAlgebra/LinearIndependent.lean index 39d2c59e03232..eedfde103f8a0 100644 --- a/Mathlib/LinearAlgebra/LinearIndependent.lean +++ b/Mathlib/LinearAlgebra/LinearIndependent.lean @@ -913,10 +913,10 @@ theorem linearIndependent_iff_not_smul_mem_span : simp [hij] · simp [hl]⟩ -/-- See also `CompleteLattice.independent_iff_linearIndependent_of_ne_zero`. -/ -theorem LinearIndependent.independent_span_singleton (hv : LinearIndependent R v) : - CompleteLattice.Independent fun i => R ∙ v i := by - refine CompleteLattice.independent_def.mp fun i => ?_ +/-- See also `iSupIndep_iff_linearIndependent_of_ne_zero`. -/ +theorem LinearIndependent.iSupIndep_span_singleton (hv : LinearIndependent R v) : + iSupIndep fun i => R ∙ v i := by + refine iSupIndep_def.mp fun i => ?_ rw [disjoint_iff_inf_le] intro m hm simp only [mem_inf, mem_span_singleton, iSup_subtype'] at hm @@ -928,6 +928,9 @@ theorem LinearIndependent.independent_span_singleton (hv : LinearIndependent R v ext simp +@[deprecated (since := "2024-11-24")] +alias LinearIndependent.independent_span_singleton := LinearIndependent.iSupIndep_span_singleton + variable (R) theorem exists_maximal_independent' (s : ι → M) : diff --git a/Mathlib/LinearAlgebra/Matrix/Determinant/Basic.lean b/Mathlib/LinearAlgebra/Matrix/Determinant/Basic.lean index 1001a688e6203..bd291498d65eb 100644 --- a/Mathlib/LinearAlgebra/Matrix/Determinant/Basic.lean +++ b/Mathlib/LinearAlgebra/Matrix/Determinant/Basic.lean @@ -209,7 +209,7 @@ theorem det_permute' (σ : Perm n) (M : Matrix n n R) : (M.submatrix id σ).det = Perm.sign σ * M.det := by rw [← det_transpose, transpose_submatrix, det_permute, det_transpose] -/-- Permuting rows and columns with the same equivalence has no effect. -/ +/-- Permuting rows and columns with the same equivalence does not change the determinant. -/ @[simp] theorem det_submatrix_equiv_self (e : n ≃ m) (A : Matrix m m R) : det (A.submatrix e e) = det A := by @@ -222,6 +222,17 @@ theorem det_submatrix_equiv_self (e : n ≃ m) (A : Matrix m m R) : intro i rw [Equiv.permCongr_apply, Equiv.symm_apply_apply, submatrix_apply] +/-- Permuting rows and columns with two equivalences does not change the absolute value of the +determinant. -/ +@[simp] +theorem abs_det_submatrix_equiv_equiv {R : Type*} [LinearOrderedCommRing R] + (e₁ e₂ : n ≃ m) (A : Matrix m m R) : + |(A.submatrix e₁ e₂).det| = |A.det| := by + have hee : e₂ = e₁.trans (e₁.symm.trans e₂) := by ext; simp + rw [hee] + show |((A.submatrix id (e₁.symm.trans e₂)).submatrix e₁ e₁).det| = |A.det| + rw [Matrix.det_submatrix_equiv_self, Matrix.det_permute', abs_mul, abs_unit_intCast, one_mul] + /-- Reindexing both indices along the same equivalence preserves the determinant. For the `simp` version of this lemma, see `det_submatrix_equiv_self`; this one is unsuitable because diff --git a/Mathlib/LinearAlgebra/Matrix/Determinant/TotallyUnimodular.lean b/Mathlib/LinearAlgebra/Matrix/Determinant/TotallyUnimodular.lean index 1c03274799f13..03da13b5d1757 100644 --- a/Mathlib/LinearAlgebra/Matrix/Determinant/TotallyUnimodular.lean +++ b/Mathlib/LinearAlgebra/Matrix/Determinant/TotallyUnimodular.lean @@ -5,6 +5,7 @@ Authors: Martin Dvorak, Vladimir Kolmogorov, Ivan Sergeev -/ import Mathlib.LinearAlgebra.Matrix.Determinant.Basic import Mathlib.Data.Matrix.ColumnRowPartitioned +import Mathlib.Data.Sign /-! # Totally unimodular matrices @@ -28,24 +29,21 @@ namespace Matrix variable {m n R : Type*} [CommRing R] -/-- Is the matrix `A` totally unimodular? -/ +/-- `A.IsTotallyUnimodular` means that every square submatrix of `A` (not necessarily contiguous) +has determinant `0` or `1` or `-1`; that is, the determinant is in the range of `SignType.cast`. -/ def IsTotallyUnimodular (A : Matrix m n R) : Prop := ∀ k : ℕ, ∀ f : Fin k → m, ∀ g : Fin k → n, f.Injective → g.Injective → - (A.submatrix f g).det = 0 ∨ - (A.submatrix f g).det = 1 ∨ - (A.submatrix f g).det = -1 + (A.submatrix f g).det ∈ Set.range SignType.cast lemma isTotallyUnimodular_iff (A : Matrix m n R) : A.IsTotallyUnimodular ↔ ∀ k : ℕ, ∀ f : Fin k → m, ∀ g : Fin k → n, - (A.submatrix f g).det = 0 ∨ - (A.submatrix f g).det = 1 ∨ - (A.submatrix f g).det = -1 := by + (A.submatrix f g).det ∈ Set.range SignType.cast := by constructor <;> intro hA · intro k f g - if h : f.Injective ∧ g.Injective then - exact hA k f g h.1 h.2 - else - left + by_cases h : f.Injective ∧ g.Injective + · exact hA k f g h.1 h.2 + · refine ⟨0, ?_⟩ + rw [SignType.coe_zero, eq_comm] simp_rw [not_and_or, Function.not_injective_iff] at h obtain ⟨i, j, hfij, hij⟩ | ⟨i, j, hgij, hij⟩ := h · rw [← det_transpose, transpose_submatrix] @@ -56,12 +54,24 @@ lemma isTotallyUnimodular_iff (A : Matrix m n R) : A.IsTotallyUnimodular ↔ · intro _ _ _ _ _ apply hA +lemma isTotallyUnimodular_iff_fintype.{w} (A : Matrix m n R) : A.IsTotallyUnimodular ↔ + ∀ (ι : Type w) [Fintype ι] [DecidableEq ι], ∀ f : ι → m, ∀ g : ι → n, + (A.submatrix f g).det ∈ Set.range SignType.cast := by + rw [isTotallyUnimodular_iff] + constructor + · intro hA ι _ _ f g + specialize hA (Fintype.card ι) (f ∘ (Fintype.equivFin ι).symm) (g ∘ (Fintype.equivFin ι).symm) + rwa [←submatrix_submatrix, det_submatrix_equiv_self] at hA + · intro hA k f g + specialize hA (ULift (Fin k)) (f ∘ Equiv.ulift) (g ∘ Equiv.ulift) + rwa [←submatrix_submatrix, det_submatrix_equiv_self] at hA + lemma IsTotallyUnimodular.apply {A : Matrix m n R} (hA : A.IsTotallyUnimodular) (i : m) (j : n) : - A i j = 0 ∨ A i j = 1 ∨ A i j = -1 := by + A i j ∈ Set.range SignType.cast := by let f : Fin 1 → m := (fun _ => i) let g : Fin 1 → n := (fun _ => j) - convert hA 1 f g (Function.injective_of_subsingleton f) (Function.injective_of_subsingleton g) <;> + convert hA 1 f g (Function.injective_of_subsingleton f) (Function.injective_of_subsingleton g) exact (det_fin_one (A.submatrix f g)).symm lemma IsTotallyUnimodular.submatrix {A : Matrix m n R} (hA : A.IsTotallyUnimodular) {k : ℕ} @@ -95,7 +105,8 @@ lemma fromRows_row0_isTotallyUnimodular_iff (A : Matrix m n R) {m' : Type*} : · exact hA k (Sum.inl ∘ f) g · if zerow : ∃ i, ∃ x', f i = Sum.inr x' then obtain ⟨i, _, _⟩ := zerow - left + use 0 + rw [eq_comm] apply det_eq_zero_of_row_eq_zero i intro simp_all diff --git a/Mathlib/LinearAlgebra/Multilinear/Basic.lean b/Mathlib/LinearAlgebra/Multilinear/Basic.lean index bef753458eb59..d12337d2b24a3 100644 --- a/Mathlib/LinearAlgebra/Multilinear/Basic.lean +++ b/Mathlib/LinearAlgebra/Multilinear/Basic.lean @@ -285,7 +285,6 @@ def constOfIsEmpty [IsEmpty ι] (m : M₂) : MultilinearMap R M₁ M₂ where end --- Porting note: Included `DFunLike.coe` to avoid strange CoeFun instance for Equiv /-- Given a multilinear map `f` on `n` variables (parameterized by `Fin n`) and a subset `s` of `k` of these variables, one gets a new multilinear map on `Fin k` by varying these variables, and fixing the other ones equal to a given value `z`. It is denoted by `f.restr s hk z`, where `hk` is a @@ -293,7 +292,7 @@ proof that the cardinality of `s` is `k`. The implicit identification between `F we use is the canonical (increasing) bijection. -/ def restr {k n : ℕ} (f : MultilinearMap R (fun _ : Fin n => M') M₂) (s : Finset (Fin n)) (hk : #s = k) (z : M') : MultilinearMap R (fun _ : Fin k => M') M₂ where - toFun v := f fun j => if h : j ∈ s then v ((DFunLike.coe (s.orderIsoOfFin hk).symm) ⟨j, h⟩) else z + toFun v := f fun j => if h : j ∈ s then v ((s.orderIsoOfFin hk).symm ⟨j, h⟩) else z /- Porting note: The proofs of the following two lemmas used to only use `erw` followed by `simp`, but it seems `erw` no longer unfolds or unifies well enough to work without more help. -/ map_update_add' v i x y := by @@ -1719,7 +1718,6 @@ theorem curryFinFinset_symm_apply {k l n : ℕ} {s : Finset (Fin n)} (hk : #s = m <| finSumEquivOfFinset hk hl (Sum.inr i) := rfl --- @[simp] -- Porting note: simpNF linter, lhs simplifies, added aux version below theorem curryFinFinset_symm_apply_piecewise_const {k l n : ℕ} {s : Finset (Fin n)} (hk : #s = k) (hl : #sᶜ = l) (f : MultilinearMap R (fun _ : Fin k => M') (MultilinearMap R (fun _ : Fin l => M') M₂)) @@ -1734,18 +1732,6 @@ theorem curryFinFinset_symm_apply_piecewise_const {k l n : ℕ} {s : Finset (Fin rw [finSumEquivOfFinset_inr, Finset.piecewise_eq_of_not_mem] exact Finset.mem_compl.1 (Finset.orderEmbOfFin_mem _ _ _) -@[simp] -theorem curryFinFinset_symm_apply_piecewise_const_aux {k l n : ℕ} {s : Finset (Fin n)} - (hk : #s = k) (hl : #sᶜ = l) - (f : MultilinearMap R (fun _ : Fin k => M') (MultilinearMap R (fun _ : Fin l => M') M₂)) - (x y : M') : - ((⇑f fun _ => x) (fun i => (Finset.piecewise s (fun _ => x) (fun _ => y) - ((sᶜ.orderEmbOfFin hl) i))) = f (fun _ => x) fun _ => y) := by - have := curryFinFinset_symm_apply_piecewise_const hk hl f x y - simp only [curryFinFinset_symm_apply, finSumEquivOfFinset_inl, Finset.orderEmbOfFin_mem, - Finset.piecewise_eq_of_mem, finSumEquivOfFinset_inr] at this - exact this - @[simp] theorem curryFinFinset_symm_apply_const {k l n : ℕ} {s : Finset (Fin n)} (hk : #s = k) (hl : #sᶜ = l) @@ -1753,23 +1739,14 @@ theorem curryFinFinset_symm_apply_const {k l n : ℕ} {s : Finset (Fin n)} (hk : (x : M') : ((curryFinFinset R M₂ M' hk hl).symm f fun _ => x) = f (fun _ => x) fun _ => x := rfl --- @[simp] -- Porting note: simpNF, lhs simplifies, added aux version below theorem curryFinFinset_apply_const {k l n : ℕ} {s : Finset (Fin n)} (hk : #s = k) (hl : #sᶜ = l) (f : MultilinearMap R (fun _ : Fin n => M') M₂) (x y : M') : (curryFinFinset R M₂ M' hk hl f (fun _ => x) fun _ => y) = f (s.piecewise (fun _ => x) fun _ => y) := by + -- Porting note: `rw` fails refine (curryFinFinset_symm_apply_piecewise_const hk hl _ _ _).symm.trans ?_ - -- `rw` fails rw [LinearEquiv.symm_apply_apply] -@[simp] -theorem curryFinFinset_apply_const_aux {k l n : ℕ} {s : Finset (Fin n)} (hk : #s = k) - (hl : #sᶜ = l) (f : MultilinearMap R (fun _ : Fin n => M') M₂) (x y : M') : - (f fun i => Sum.elim (fun _ => x) (fun _ => y) ((⇑ (Equiv.symm (finSumEquivOfFinset hk hl))) i)) - = f (s.piecewise (fun _ => x) fun _ => y) := by - rw [← curryFinFinset_apply] - apply curryFinFinset_apply_const - end MultilinearMap end Currying diff --git a/Mathlib/LinearAlgebra/Prod.lean b/Mathlib/LinearAlgebra/Prod.lean index 4a19736a68ba4..33f885c1bc407 100644 --- a/Mathlib/LinearAlgebra/Prod.lean +++ b/Mathlib/LinearAlgebra/Prod.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl, Mario Carneiro, Kevin Buzzard, Yury Kudryashov, Eric Wieser -/ import Mathlib.Algebra.Algebra.Prod +import Mathlib.Algebra.Group.Graph import Mathlib.LinearAlgebra.Span.Basic import Mathlib.Order.PartialSups @@ -834,17 +835,17 @@ set_option linter.deprecated false /-- An auxiliary construction for `tunnel`. The composition of `f`, followed by the isomorphism back to `K`, followed by the inclusion of this submodule back into `M`. -/ -@[deprecated (since := "2024-06-05")] +@[deprecated "No deprecation message was provided." (since := "2024-06-05")] def tunnelAux (f : M × N →ₗ[R] M) (Kφ : ΣK : Submodule R M, K ≃ₗ[R] M) : M × N →ₗ[R] M := (Kφ.1.subtype.comp Kφ.2.symm.toLinearMap).comp f -@[deprecated (since := "2024-06-05")] +@[deprecated "No deprecation message was provided." (since := "2024-06-05")] theorem tunnelAux_injective (f : M × N →ₗ[R] M) (i : Injective f) (Kφ : ΣK : Submodule R M, K ≃ₗ[R] M) : Injective (tunnelAux f Kφ) := (Subtype.val_injective.comp Kφ.2.symm.injective).comp i /-- Auxiliary definition for `tunnel`. -/ -@[deprecated (since := "2024-06-05")] +@[deprecated "No deprecation message was provided." (since := "2024-06-05")] def tunnel' (f : M × N →ₗ[R] M) (i : Injective f) : ℕ → ΣK : Submodule R M, K ≃ₗ[R] M | 0 => ⟨⊤, LinearEquiv.ofTop ⊤ rfl⟩ | n + 1 => @@ -855,7 +856,7 @@ def tunnel' (f : M × N →ₗ[R] M) (i : Injective f) : ℕ → ΣK : Submodule /-- Give an injective map `f : M × N →ₗ[R] M` we can find a nested sequence of submodules all isomorphic to `M`. -/ -@[deprecated (since := "2024-06-05")] +@[deprecated "No deprecation message was provided." (since := "2024-06-05")] def tunnel (f : M × N →ₗ[R] M) (i : Injective f) : ℕ →o (Submodule R M)ᵒᵈ := -- Note: the hint `(α := _)` had to be added in https://github.com/leanprover-community/mathlib4/pull/8386 ⟨fun n => OrderDual.toDual (α := Submodule R M) (tunnel' f i n).1, @@ -867,24 +868,24 @@ def tunnel (f : M × N →ₗ[R] M) (i : Injective f) : ℕ →o (Submodule R M) /-- Give an injective map `f : M × N →ₗ[R] M` we can find a sequence of submodules all isomorphic to `N`. -/ -@[deprecated (since := "2024-06-05")] +@[deprecated "No deprecation message was provided." (since := "2024-06-05")] def tailing (f : M × N →ₗ[R] M) (i : Injective f) (n : ℕ) : Submodule R M := (Submodule.snd R M N).map (tunnelAux f (tunnel' f i n)) /-- Each `tailing f i n` is a copy of `N`. -/ -@[deprecated (since := "2024-06-05")] +@[deprecated "No deprecation message was provided." (since := "2024-06-05")] def tailingLinearEquiv (f : M × N →ₗ[R] M) (i : Injective f) (n : ℕ) : tailing f i n ≃ₗ[R] N := ((Submodule.snd R M N).equivMapOfInjective _ (tunnelAux_injective f i (tunnel' f i n))).symm.trans (Submodule.sndEquiv R M N) -@[deprecated (since := "2024-06-05")] +@[deprecated "No deprecation message was provided." (since := "2024-06-05")] theorem tailing_le_tunnel (f : M × N →ₗ[R] M) (i : Injective f) (n : ℕ) : tailing f i n ≤ OrderDual.ofDual (α := Submodule R M) (tunnel f i n) := by dsimp [tailing, tunnelAux] rw [Submodule.map_comp, Submodule.map_comp] apply Submodule.map_subtype_le -@[deprecated (since := "2024-06-05")] +@[deprecated "No deprecation message was provided." (since := "2024-06-05")] theorem tailing_disjoint_tunnel_succ (f : M × N →ₗ[R] M) (i : Injective f) (n : ℕ) : Disjoint (tailing f i n) (OrderDual.ofDual (α := Submodule R M) <| tunnel f i (n + 1)) := by rw [disjoint_iff] @@ -893,7 +894,7 @@ theorem tailing_disjoint_tunnel_succ (f : M × N →ₗ[R] M) (i : Injective f) Submodule.comap_map_eq_of_injective (tunnelAux_injective _ i _), inf_comm, Submodule.fst_inf_snd, Submodule.map_bot] -@[deprecated (since := "2024-06-05")] +@[deprecated "No deprecation message was provided." (since := "2024-06-05")] theorem tailing_sup_tunnel_succ_le_tunnel (f : M × N →ₗ[R] M) (i : Injective f) (n : ℕ) : tailing f i n ⊔ (OrderDual.ofDual (α := Submodule R M) <| tunnel f i (n + 1)) ≤ (OrderDual.ofDual (α := Submodule R M) <| tunnel f i n) := by @@ -902,19 +903,19 @@ theorem tailing_sup_tunnel_succ_le_tunnel (f : M × N →ₗ[R] M) (i : Injectiv apply Submodule.map_subtype_le /-- The supremum of all the copies of `N` found inside the tunnel. -/ -@[deprecated (since := "2024-06-05")] +@[deprecated "No deprecation message was provided." (since := "2024-06-05")] def tailings (f : M × N →ₗ[R] M) (i : Injective f) : ℕ → Submodule R M := partialSups (tailing f i) -@[simp, deprecated (since := "2024-06-05")] +@[simp, deprecated "No deprecation message was provided." (since := "2024-06-05")] theorem tailings_zero (f : M × N →ₗ[R] M) (i : Injective f) : tailings f i 0 = tailing f i 0 := by simp [tailings] -@[simp, deprecated (since := "2024-06-05")] +@[simp, deprecated "No deprecation message was provided." (since := "2024-06-05")] theorem tailings_succ (f : M × N →ₗ[R] M) (i : Injective f) (n : ℕ) : tailings f i (n + 1) = tailings f i n ⊔ tailing f i (n + 1) := by simp [tailings] -@[deprecated (since := "2024-06-05")] +@[deprecated "No deprecation message was provided." (since := "2024-06-05")] theorem tailings_disjoint_tunnel (f : M × N →ₗ[R] M) (i : Injective f) (n : ℕ) : Disjoint (tailings f i n) (OrderDual.ofDual (α := Submodule R M) <| tunnel f i (n + 1)) := by induction' n with n ih @@ -926,7 +927,7 @@ theorem tailings_disjoint_tunnel (f : M × N →ₗ[R] M) (i : Injective f) (n : · apply Disjoint.mono_right _ ih apply tailing_sup_tunnel_succ_le_tunnel -@[deprecated (since := "2024-06-05")] +@[deprecated "No deprecation message was provided." (since := "2024-06-05")] theorem tailings_disjoint_tailing (f : M × N →ₗ[R] M) (i : Injective f) (n : ℕ) : Disjoint (tailings f i n) (tailing f i (n + 1)) := Disjoint.mono_right (tailing_le_tunnel f i _) (tailings_disjoint_tunnel f i _) @@ -965,3 +966,85 @@ theorem graph_eq_range_prod : f.graph = range (LinearMap.id.prod f) := by end Graph end LinearMap + +section LineTest + +open Set Function + +variable {R S G H I : Type*} + [Semiring R] [Semiring S] {σ : R →+* S} [RingHomSurjective σ] + [AddCommMonoid G] [Module R G] + [AddCommMonoid H] [Module S H] + [AddCommMonoid I] [Module S I] + +/-- **Vertical line test** for module homomorphisms. + +Let `f : G → H × I` be a linear (or semilinear) map to a product. Assume that `f` is surjective on +the first factor and that the image of `f` intersects every "vertical line" `{(h, i) | i : I}` at +most once. Then the image of `f` is the graph of some linear map `f' : H → I`. -/ +lemma LinearMap.exists_range_eq_graph {f : G →ₛₗ[σ] H × I} (hf₁ : Surjective (Prod.fst ∘ f)) + (hf : ∀ g₁ g₂, (f g₁).1 = (f g₂).1 → (f g₁).2 = (f g₂).2) : + ∃ f' : H →ₗ[S] I, LinearMap.range f = LinearMap.graph f' := by + obtain ⟨f', hf'⟩ := + AddMonoidHom.exists_mrange_eq_mgraph (G := G) (H := H) (I := I) (f := f) hf₁ hf + simp only [SetLike.ext_iff, AddMonoidHom.mem_mrange, AddMonoidHom.coe_coe, + AddMonoidHom.mem_mgraph] at hf' + use + { toFun := f'.toFun + map_add' := f'.map_add' + map_smul' := by + intro s h + simp only [ZeroHom.toFun_eq_coe, AddMonoidHom.toZeroHom_coe, RingHom.id_apply] + refine (hf' (s • h, _)).mp ?_ + rw [← Prod.smul_mk, ← LinearMap.mem_range] + apply Submodule.smul_mem + rw [LinearMap.mem_range, hf'] } + ext x + simpa only [mem_range, Eq.comm, ZeroHom.toFun_eq_coe, AddMonoidHom.toZeroHom_coe, mem_graph_iff, + coe_mk, AddHom.coe_mk, AddMonoidHom.coe_coe, Set.mem_range] using hf' x + +/-- **Vertical line test** for module homomorphisms. + +Let `G ≤ H × I` be a submodule of a product of modules. Assume that `G` maps bijectively to the +first factor. Then `G` is the graph of some module homomorphism `f : H →ₗ[R] I`. -/ +lemma Submodule.exists_eq_graph {G : Submodule S (H × I)} (hf₁ : Bijective (Prod.fst ∘ G.subtype)) : + ∃ f : H →ₗ[S] I, G = LinearMap.graph f := by + simpa only [range_subtype] using LinearMap.exists_range_eq_graph hf₁.surjective + (fun a b h ↦ congr_arg (Prod.snd ∘ G.subtype) (hf₁.injective h)) + +/-- **Line test** for module isomorphisms. + +Let `f : G → H × I` be a homomorphism to a product of modules. Assume that `f` is surjective onto +both factors and that the image of `f` intersects every "vertical line" `{(h, i) | i : I}` and every +"horizontal line" `{(h, i) | h : H}` at most once. Then the image of `f` is the graph of some +module isomorphism `f' : H ≃ I`. -/ +lemma LinearMap.exists_linearEquiv_eq_graph {f : G →ₛₗ[σ] H × I} (hf₁ : Surjective (Prod.fst ∘ f)) + (hf₂ : Surjective (Prod.snd ∘ f)) (hf : ∀ g₁ g₂, (f g₁).1 = (f g₂).1 ↔ (f g₁).2 = (f g₂).2) : + ∃ e : H ≃ₗ[S] I, range f = e.toLinearMap.graph := by + obtain ⟨e₁, he₁⟩ := f.exists_range_eq_graph hf₁ fun _ _ ↦ (hf _ _).1 + obtain ⟨e₂, he₂⟩ := ((LinearEquiv.prodComm _ _ _).toLinearMap.comp f).exists_range_eq_graph + (by simpa) <| by simp [hf] + have he₁₂ h i : e₁ h = i ↔ e₂ i = h := by + simp only [SetLike.ext_iff, LinearMap.mem_graph_iff] at he₁ he₂ + rw [Eq.comm, ← he₁ (h, i), Eq.comm, ← he₂ (i, h)] + simp only [mem_range, coe_comp, LinearEquiv.coe_coe, Function.comp_apply, + LinearEquiv.prodComm_apply, Prod.swap_eq_iff_eq_swap, Prod.swap_prod_mk] + exact ⟨ + { toFun := e₁ + map_smul' := e₁.map_smul' + map_add' := e₁.map_add' + invFun := e₂ + left_inv := fun h ↦ by rw [← he₁₂] + right_inv := fun i ↦ by rw [he₁₂] }, he₁⟩ + +/-- **Goursat's lemma** for module isomorphisms. + +Let `G ≤ H × I` be a submodule of a product of modules. Assume that the natural maps from `G` to +both factors are bijective. Then `G` is the graph of some module isomorphism `f : H ≃ I`. -/ +lemma Submodule.exists_equiv_eq_graph {G : Submodule S (H × I)} + (hG₁ : Bijective (Prod.fst ∘ G.subtype)) (hG₂ : Bijective (Prod.snd ∘ G.subtype)) : + ∃ e : H ≃ₗ[S] I, G = e.toLinearMap.graph := by + simpa only [range_subtype] using LinearMap.exists_linearEquiv_eq_graph + hG₁.surjective hG₂.surjective fun _ _ ↦ hG₁.injective.eq_iff.trans hG₂.injective.eq_iff.symm + +end LineTest diff --git a/Mathlib/LinearAlgebra/Projectivization/Independence.lean b/Mathlib/LinearAlgebra/Projectivization/Independence.lean index e9a6bf429c7e2..403138f8a84d9 100644 --- a/Mathlib/LinearAlgebra/Projectivization/Independence.lean +++ b/Mathlib/LinearAlgebra/Projectivization/Independence.lean @@ -56,17 +56,19 @@ theorem independent_iff : Independent f ↔ LinearIndependent K (Projectivizatio /-- A family of points in projective space is independent if and only if the family of submodules which the points determine is independent in the lattice-theoretic sense. -/ -theorem independent_iff_completeLattice_independent : - Independent f ↔ CompleteLattice.Independent fun i => (f i).submodule := by +theorem independent_iff_iSupIndep : Independent f ↔ iSupIndep fun i => (f i).submodule := by refine ⟨?_, fun h => ?_⟩ · rintro ⟨f, hf, hi⟩ simp only [submodule_mk] - exact (CompleteLattice.independent_iff_linearIndependent_of_ne_zero (R := K) hf).mpr hi + exact (iSupIndep_iff_linearIndependent_of_ne_zero (R := K) hf).mpr hi · rw [independent_iff] refine h.linearIndependent (Projectivization.submodule ∘ f) (fun i => ?_) fun i => ?_ · simpa only [Function.comp_apply, submodule_eq] using Submodule.mem_span_singleton_self _ · exact rep_nonzero (f i) +@[deprecated (since := "2024-11-24")] +alias independent_iff_completeLattice_independent := independent_iff_iSupIndep + /-- A linearly dependent family of nonzero vectors gives a dependent family of points in projective space. -/ inductive Dependent : (ι → ℙ K V) → Prop diff --git a/Mathlib/LinearAlgebra/QuadraticForm/Basic.lean b/Mathlib/LinearAlgebra/QuadraticForm/Basic.lean index bec420998fa64..9778e86170c13 100644 --- a/Mathlib/LinearAlgebra/QuadraticForm/Basic.lean +++ b/Mathlib/LinearAlgebra/QuadraticForm/Basic.lean @@ -526,8 +526,8 @@ variable [CommSemiring R] [CommSemiring S] [AddCommMonoid M] [Module R M] [AddCo [Module R N] [Module S M] [Module S N] [Algebra S R] variable [IsScalarTower S R M] [IsScalarTower S R N] -/-- If `B : M → N → Pₗ` is `R`-`S` bilinear and `R'` and `S'` are compatible scalar multiplications, -then the restriction of scalars is a `R'`-`S'` bilinear map. -/ +/-- If `Q : M → N` is a quadratic map of `R`-modules and `R` is an `S`-algebra, +then the restriction of scalars is a quadratic map of `S`-modules. -/ @[simps!] def restrictScalars (Q : QuadraticMap R M N) : QuadraticMap S M N where toFun x := Q x @@ -597,12 +597,13 @@ theorem _root_.LinearEquiv.congrQuadraticMap_symm (e : N ≃ₗ[R] P) : (LinearEquiv.congrQuadraticMap e (M := M)).symm = e.symm.congrQuadraticMap := rfl end Comp + section NonUnitalNonAssocSemiring variable [CommSemiring R] [NonUnitalNonAssocSemiring A] [AddCommMonoid M] [Module R M] variable [Module R A] [SMulCommClass R A A] [IsScalarTower R A A] -/-- The product of linear forms is a quadratic form. -/ +/-- The product of linear maps into an `R`-algebra is a quadratic map. -/ def linMulLin (f g : M →ₗ[R] A) : QuadraticMap R M A where toFun := f * g toFun_smul a x := by @@ -635,12 +636,12 @@ theorem linMulLin_comp (f g : M →ₗ[R] A) (h : N' →ₗ[R] M) : variable {n : Type*} -/-- `sq` is the quadratic form mapping the vector `x : A` to `x * x` -/ +/-- `sq` is the quadratic map sending the vector `x : A` to `x * x` -/ @[simps!] def sq : QuadraticMap R A A := linMulLin LinearMap.id LinearMap.id -/-- `proj i j` is the quadratic form mapping the vector `x : n → R` to `x i * x j` -/ +/-- `proj i j` is the quadratic map sending the vector `x : n → R` to `x i * x j` -/ def proj (i j : n) : QuadraticMap R (n → A) A := linMulLin (@LinearMap.proj _ _ _ (fun _ => A) _ _ i) (@LinearMap.proj _ _ _ (fun _ => A) _ _ j) @@ -655,10 +656,16 @@ end QuadraticMap /-! ### Associated bilinear maps -Over a commutative ring with an inverse of 2, the theory of quadratic maps is -basically identical to that of symmetric bilinear maps. The map from quadratic -maps to bilinear maps giving this identification is called the `QuadraticMap.associated` -quadratic map. +If multiplication by 2 is invertible on the target module `N` of +`QuadraticMap R M N`, then there is a linear bijection `QuadraticMap.associated` +between quadratic maps `Q` over `R` from `M` to `N` and symmetric bilinear maps +`B : M →ₗ[R] M →ₗ[R] → N` such that `BilinMap.toQuadraticMap B = Q` +(see `QuadraticMap.associated_rightInverse`). The associated bilinear map is half +`Q.polarBilin` (see `QuadraticMap.two_nsmul_associated`); this is where the invertibility condition +comes from. We spell the condition as `[Invertible (2 : Module.End R N)]`. + +Note that this makes the bijection available in more cases than the simpler condition +`Invertible (2 : R)`, e.g., when `R = ℤ` and `N = ℝ`. -/ namespace LinearMap @@ -711,14 +718,14 @@ section variable (S R M) -/-- `LinearMap.BilinForm.toQuadraticMap` as an additive homomorphism -/ +/-- `LinearMap.BilinMap.toQuadraticMap` as an additive homomorphism -/ @[simps] def toQuadraticMapAddMonoidHom : (BilinMap R M N) →+ QuadraticMap R M N where toFun := toQuadraticMap map_zero' := toQuadraticMap_zero _ _ map_add' := toQuadraticMap_add -/-- `LinearMap.BilinForm.toQuadraticMap` as a linear map -/ +/-- `LinearMap.BilinMap.toQuadraticMap` as a linear map -/ @[simps!] def toQuadraticMapLinearMap [Semiring S] [Module S N] [SMulCommClass S R N] [SMulCommClass R S N] : (BilinMap R M N) →ₗ[S] QuadraticMap R M N where @@ -818,43 +825,87 @@ namespace QuadraticMap open LinearMap (BilinMap) +section + +variable [Semiring R] [AddCommMonoid M] [Module R M] + +instance : SMulCommClass R (Submonoid.center R) M where + smul_comm r r' m := by + simp_rw [Submonoid.smul_def, smul_smul, (Set.mem_center_iff.1 r'.prop).1] + +/-- If `2` is invertible in `R`, then it is also invertible in `End R M`. -/ +instance [Invertible (2 : R)] : Invertible (2 : Module.End R M) where + invOf := (⟨⅟2, Set.invOf_mem_center (Set.ofNat_mem_center _ _)⟩ : Submonoid.center R) • + (1 : Module.End R M) + invOf_mul_self := by + ext m + dsimp [Submonoid.smul_def] + rw [← ofNat_smul_eq_nsmul R, invOf_smul_smul (2 : R) m] + mul_invOf_self := by + ext m + dsimp [Submonoid.smul_def] + rw [← ofNat_smul_eq_nsmul R, smul_invOf_smul (2 : R) m] + +/-- If `2` is invertible in `R`, then applying the inverse of `2` in `End R M` to an element +of `M` is the same as multiplying by the inverse of `2` in `R`. -/ +@[simp] +lemma half_moduleEnd_apply_eq_half_smul [Invertible (2 : R)] (x : M) : + ⅟ (2 : Module.End R M) x = ⅟ (2 : R) • x := + rfl + +end + section AssociatedHom -variable [CommRing R] [AddCommGroup M] [Module R M] [AddCommGroup N] [Module R N] -variable (S) [CommSemiring S] [Algebra S R] -variable [Module S N] [IsScalarTower S R N] -variable [Invertible (2 : R)] {B₁ : BilinMap R M R} +variable [CommRing R] [AddCommGroup M] [Module R M] +variable [AddCommGroup N] [Module R N] +variable (S) [CommSemiring S] [Algebra S R] [Module S N] [IsScalarTower S R N] + +-- the requirement that multiplication by `2` is invertible on the target module `N` +variable [Invertible (2 : Module.End R N)] /-- `associatedHom` is the map that sends a quadratic map on a module `M` over `R` to its associated symmetric bilinear map. As provided here, this has the structure of an `S`-linear map -where `S` is a commutative subring of `R`. +where `S` is a commutative ring and `R` is an `S`-algebra. Over a commutative ring, use `QuadraticMap.associated`, which gives an `R`-linear map. Over a general ring with no nontrivial distinguished commutative subring, use `QuadraticMap.associated'`, which gives an additive homomorphism (or more precisely a `ℤ`-linear map.) -/ -def associatedHom : QuadraticMap R M N →ₗ[S] (BilinMap R M N) := - -- TODO: this `center` stuff is vertigial from an incorrect non-commutative version, but we leave - -- it behind to make a future refactor to a *correct* non-commutative version easier in future. - (⟨⅟2, Set.invOf_mem_center (Set.ofNat_mem_center _ _)⟩ : Submonoid.center R) • - { toFun := polarBilin - map_add' := fun _x _y => LinearMap.ext₂ <| polar_add _ _ - map_smul' := fun _c _x => LinearMap.ext₂ <| polar_smul _ _ } +def associatedHom : QuadraticMap R M N →ₗ[S] (BilinMap R M N) where + toFun Q := ⅟ (2 : Module.End R N) • polarBilin Q + map_add' _ _ := + LinearMap.ext₂ fun _ _ ↦ by + simp only [LinearMap.smul_apply, polarBilin_apply_apply, coeFn_add, polar_add, + LinearMap.smul_def, LinearMap.map_add, LinearMap.add_apply] + map_smul' _ _ := + LinearMap.ext₂ fun _ _ ↦ by + simp only [LinearMap.smul_apply, polarBilin_apply_apply, coeFn_smul, polar_smul, + LinearMap.smul_def, LinearMap.map_smul_of_tower, RingHom.id_apply] variable (Q : QuadraticMap R M N) @[simp] -theorem associated_apply (x y : M) : associatedHom S Q x y = ⅟ (2 : R) • (Q (x + y) - Q x - Q y) := +theorem associated_apply (x y : M) : + associatedHom S Q x y = ⅟ (2 : Module.End R N) • (Q (x + y) - Q x - Q y) := rfl +/-- Twice the associated bilinear map of `Q` is the same as the polar of `Q`. -/ @[simp] theorem two_nsmul_associated : 2 • associatedHom S Q = Q.polarBilin := by ext dsimp - rw [← smul_assoc, two_nsmul, invOf_two_add_invOf_two, one_smul, polar] + rw [← LinearMap.smul_apply, nsmul_eq_mul, Nat.cast_ofNat, mul_invOf_self', LinearMap.one_apply, + polar] -theorem associated_isSymm (Q : QuadraticMap R M R) : (associatedHom S Q).IsSymm := fun x y => by - simp only [associated_apply, sub_eq_add_neg, add_assoc, map_mul, RingHom.id_apply, map_add, - _root_.map_neg, add_comm, add_left_comm] +theorem associated_isSymm (Q : QuadraticForm R M) [Invertible (2 : R)] : + (associatedHom S Q).IsSymm := fun x y ↦ by + simp only [associated_apply, sub_eq_add_neg, add_assoc, RingHom.id_apply, add_comm, add_left_comm] +/-- A version of `QuadraticMap.associated_isSymm` for general targets +(using `flip` because `IsSymm` does not apply here). -/ +lemma associated_flip : (associatedHom S Q).flip = associatedHom S Q := by + ext + simp only [LinearMap.flip_apply, associated_apply, add_comm, sub_eq_add_neg, add_left_comm, + add_assoc] @[simp] theorem associated_comp {N' : Type*} [AddCommGroup N'] [Module R N'] (f : N' →ₗ[R] M) : @@ -862,23 +913,29 @@ theorem associated_comp {N' : Type*} [AddCommGroup N'] [Module R N'] (f : N' → ext simp only [associated_apply, comp_apply, map_add, LinearMap.compl₁₂_apply] -theorem associated_toQuadraticMap (B : BilinMap R M R) (x y : M) : - associatedHom S B.toQuadraticMap x y = ⅟ (2 : R) • (B x y + B y x) := by - simp only [associated_apply, LinearMap.BilinMap.toQuadraticMap_apply, map_add, - LinearMap.add_apply, smul_eq_mul] +theorem associated_toQuadraticMap (B : BilinMap R M N) (x y : M) : + associatedHom S B.toQuadraticMap x y = ⅟ (2 : Module.End R N) • (B x y + B y x) := by + simp only [associated_apply, BilinMap.toQuadraticMap_apply, map_add, LinearMap.add_apply, + LinearMap.smul_def, _root_.map_sub] abel_nf -theorem associated_left_inverse (h : B₁.IsSymm) : associatedHom S B₁.toQuadraticMap = B₁ := - LinearMap.ext₂ fun x y => by - rw [associated_toQuadraticMap, ← h.eq x y, RingHom.id_apply] - match_scalars - linear_combination invOf_mul_self' (2:R) +theorem associated_left_inverse [Invertible (2 : R)] {B₁ : BilinMap R M R} (h : B₁.IsSymm) : + associatedHom S B₁.toQuadraticMap = B₁ := + LinearMap.ext₂ fun x y ↦ by + rw [associated_toQuadraticMap, ← h.eq x y, RingHom.id_apply, ← two_mul, ← smul_eq_mul, + invOf_smul_eq_iff, two_smul, two_smul] + +/-- A version of `QuadraticMap.associated_left_inverse` for general targets. -/ +lemma associated_left_inverse' {B₁ : BilinMap R M N} (hB₁ : B₁.flip = B₁) : + associatedHom S B₁.toQuadraticMap = B₁ := by + ext _ y + rw [associated_toQuadraticMap, ← LinearMap.flip_apply _ y, hB₁, invOf_smul_eq_iff, two_smul] -- Porting note: moved from below to golf the next theorem theorem associated_eq_self_apply (x : M) : associatedHom S Q x x = Q x := by - rw [associated_apply, map_add_self] - match_scalars - linear_combination invOf_mul_self' (2:R) + rw [associated_apply, map_add_self, ← three_add_one_eq_four, ← two_add_one_eq_three, add_smul, + add_smul, one_smul, add_sub_cancel_right, add_sub_cancel_right, two_smul, ← two_smul R, + invOf_smul_eq_iff, two_smul, two_smul] theorem toQuadraticMap_associated : (associatedHom S Q).toQuadraticMap = Q := QuadraticMap.ext <| associated_eq_self_apply S Q @@ -887,7 +944,7 @@ theorem toQuadraticMap_associated : (associatedHom S Q).toQuadraticMap = Q := -- with historical naming in this file. theorem associated_rightInverse : Function.RightInverse (associatedHom S) (BilinMap.toQuadraticMap : _ → QuadraticMap R M N) := - fun Q => toQuadraticMap_associated S Q + toQuadraticMap_associated S /-- `associated'` is the `ℤ`-linear map that sends a quadratic form on a module `M` over `R` to its associated symmetric bilinear form. -/ @@ -895,10 +952,15 @@ abbrev associated' : QuadraticMap R M N →ₗ[ℤ] BilinMap R M N := associatedHom ℤ /-- Symmetric bilinear forms can be lifted to quadratic forms -/ -instance canLift : +instance canLift [Invertible (2 : R)] : CanLift (BilinMap R M R) (QuadraticForm R M) (associatedHom ℕ) LinearMap.IsSymm where prf B hB := ⟨B.toQuadraticMap, associated_left_inverse _ hB⟩ +/-- Symmetric bilinear maps can be lifted to quadratic maps -/ +instance canLift' : + CanLift (BilinMap R M N) (QuadraticMap R M N) (associatedHom ℕ) fun B ↦ B.flip = B where + prf B hB := ⟨B.toQuadraticMap, associated_left_inverse' _ hB⟩ + /-- There exists a non-null vector with respect to any quadratic form `Q` whose associated bilinear form is non-zero, i.e. there exists `x` such that `Q x ≠ 0`. -/ theorem exists_quadraticMap_ne_zero {Q : QuadraticMap R M N} @@ -919,10 +981,11 @@ section Associated variable [CommSemiring S] [CommRing R] [AddCommGroup M] [Algebra S R] [Module R M] variable [AddCommGroup N] [Module R N] [Module S N] [IsScalarTower S R N] -variable [Invertible (2 : R)] +variable [Invertible (2 : Module.End R N)] -- Note: When possible, rather than writing lemmas about `associated`, write a lemma applying to -- the more general `associatedHom` and place it in the previous section. + /-- `associated` is the linear map that sends a quadratic map over a commutative ring to its associated symmetric bilinear map. -/ abbrev associated : QuadraticMap R M N →ₗ[R] BilinMap R M N := @@ -935,17 +998,19 @@ theorem coe_associatedHom : open LinearMap in @[simp] -theorem associated_linMulLin (f g : M →ₗ[R] R) : - associated (R := R) (linMulLin f g) = +theorem associated_linMulLin [Invertible (2 : R)] (f g : M →ₗ[R] R) : + associated (R := R) (N := R) (linMulLin f g) = ⅟ (2 : R) • ((mul R R).compl₁₂ f g + (mul R R).compl₁₂ g f) := by ext simp only [associated_apply, linMulLin_apply, map_add, smul_add, LinearMap.add_apply, - LinearMap.smul_apply, compl₁₂_apply, mul_apply', smul_eq_mul] + LinearMap.smul_apply, compl₁₂_apply, mul_apply', smul_eq_mul, invOf_smul_eq_iff] + simp only [smul_add, LinearMap.smul_def, Module.End.ofNat_apply, nsmul_eq_mul, Nat.cast_ofNat, + mul_invOf_cancel_left'] ring_nf open LinearMap in @[simp] -lemma associated_sq : associated (R := R) sq = mul R R := +lemma associated_sq [Invertible (2 : R)] : associated (R := R) sq = mul R R := (associated_linMulLin (id) (id)).trans <| by simp only [smul_add, invOf_two_smul_add_invOf_two_smul]; rfl @@ -1296,7 +1361,7 @@ theorem weightedSumSquares_apply [Monoid S] [DistribMulAction S R] [SMulCommClas /-- On an orthogonal basis, the basis representation of `Q` is just a sum of squares. -/ theorem basisRepr_eq_of_iIsOrtho {R M} [CommRing R] [AddCommGroup M] [Module R M] - [Invertible (2 : R)] (Q : QuadraticMap R M R) (v : Basis ι R M) + [Invertible (2 : R)] (Q : QuadraticForm R M) (v : Basis ι R M) (hv₂ : (associated (R := R) Q).IsOrthoᵢ v) : Q.basisRepr v = weightedSumSquares _ fun i => Q (v i) := by ext w @@ -1304,7 +1369,7 @@ theorem basisRepr_eq_of_iIsOrtho {R M} [CommRing R] [AddCommGroup M] [Module R M refine sum_congr rfl fun j hj => ?_ rw [← @associated_eq_self_apply R, LinearMap.map_sum₂, sum_eq_single_of_mem j hj] · rw [LinearMap.map_smul, LinearMap.map_smul₂, smul_eq_mul, associated_apply, smul_eq_mul, - smul_eq_mul, smul_eq_mul] + smul_eq_mul, LinearMap.smul_def, half_moduleEnd_apply_eq_half_smul] ring_nf · intro i _ hij rw [LinearMap.map_smul, LinearMap.map_smul₂, hv₂ hij] diff --git a/Mathlib/LinearAlgebra/QuadraticForm/Dual.lean b/Mathlib/LinearAlgebra/QuadraticForm/Dual.lean index 48db5f20ea5c2..803a8340d71e3 100644 --- a/Mathlib/LinearAlgebra/QuadraticForm/Dual.lean +++ b/Mathlib/LinearAlgebra/QuadraticForm/Dual.lean @@ -141,8 +141,11 @@ def toDualProd (Q : QuadraticForm R M) [Invertible (2 : R)] : LinearMap.coe_toAddHom, LinearMap.prod_apply, Pi.prod, LinearMap.add_apply, LinearMap.coe_comp, Function.comp_apply, LinearMap.fst_apply, LinearMap.snd_apply, LinearMap.sub_apply, dualProd_apply, polarBilin_apply_apply, prod_apply, neg_apply] - simp [polar_comm _ x.1 x.2, ← sub_add, mul_sub, sub_mul, smul_sub, Submonoid.smul_def, ← - sub_eq_add_neg (Q x.1) (Q x.2)] + simp only [polar_sub_right, polar_self, nsmul_eq_mul, Nat.cast_ofNat, polar_comm _ x.1 x.2, + smul_sub, LinearMap.smul_def, sub_add_sub_cancel, ← sub_eq_add_neg (Q x.1) (Q x.2)] + rw [← LinearMap.map_sub (⅟ 2 : Module.End R R), ← mul_sub, ← LinearMap.smul_def] + simp only [LinearMap.smul_def, half_moduleEnd_apply_eq_half_smul, smul_eq_mul, + invOf_mul_cancel_left'] /-! TODO: show that `QuadraticForm.toDualProd` is an `QuadraticForm.IsometryEquiv` diff --git a/Mathlib/LinearAlgebra/Ray.lean b/Mathlib/LinearAlgebra/Ray.lean index 7890952886f09..d569b5c080c98 100644 --- a/Mathlib/LinearAlgebra/Ray.lean +++ b/Mathlib/LinearAlgebra/Ray.lean @@ -6,7 +6,7 @@ Authors: Joseph Myers import Mathlib.Algebra.Order.Module.Algebra import Mathlib.LinearAlgebra.LinearIndependent import Mathlib.Algebra.Ring.Subring.Units -import Mathlib.Tactic.Positivity +import Mathlib.Tactic.Positivity.Basic /-! # Rays in modules diff --git a/Mathlib/LinearAlgebra/RootSystem/Finite/Nondegenerate.lean b/Mathlib/LinearAlgebra/RootSystem/Finite/Nondegenerate.lean index 734860e88627e..1efe86c29f24f 100644 --- a/Mathlib/LinearAlgebra/RootSystem/Finite/Nondegenerate.lean +++ b/Mathlib/LinearAlgebra/RootSystem/Finite/Nondegenerate.lean @@ -70,7 +70,7 @@ lemma finrank_rootSpan_map_polarization_eq_finrank_corootSpan : rw [← LinearMap.range_domRestrict] apply (Submodule.finrank_mono P.range_polarization_domRestrict_le_span_coroot).antisymm have : IsReflexive R N := PerfectPairing.reflexive_right P.toPerfectPairing - refine LinearMap.finrank_le_of_smul_regular P.corootSpan + refine LinearMap.finrank_le_of_isSMulRegular P.corootSpan (LinearMap.range (P.Polarization.domRestrict P.rootSpan)) (smul_right_injective N (Ne.symm (ne_of_lt P.prod_rootForm_root_self_pos))) fun _ hx => ?_ diff --git a/Mathlib/Logic/Basic.lean b/Mathlib/Logic/Basic.lean index 7a0eb1ff4d84f..89c3a8fe8a2f1 100644 --- a/Mathlib/Logic/Basic.lean +++ b/Mathlib/Logic/Basic.lean @@ -725,20 +725,21 @@ alias by_contradiction := byContradiction -- TODO: remove? rename in core? alias prop_complete := propComplete -- TODO: remove? rename in core? -@[elab_as_elim, deprecated (since := "2024-07-27")] theorem cases_true_false (p : Prop → Prop) +@[elab_as_elim, deprecated "No deprecation message was provided." (since := "2024-07-27")] +theorem cases_true_false (p : Prop → Prop) (h1 : p True) (h2 : p False) (a : Prop) : p a := Or.elim (prop_complete a) (fun ht : a = True ↦ ht.symm ▸ h1) fun hf : a = False ↦ hf.symm ▸ h2 -@[deprecated (since := "2024-07-27")] +@[deprecated "No deprecation message was provided." (since := "2024-07-27")] theorem eq_false_or_eq_true (a : Prop) : a = False ∨ a = True := (prop_complete a).symm set_option linter.deprecated false in -@[deprecated (since := "2024-07-27")] +@[deprecated "No deprecation message was provided." (since := "2024-07-27")] theorem cases_on (a : Prop) {p : Prop → Prop} (h1 : p True) (h2 : p False) : p a := @cases_true_false p h1 h2 a set_option linter.deprecated false in -@[deprecated (since := "2024-07-27")] +@[deprecated "No deprecation message was provided." (since := "2024-07-27")] theorem cases {p : Prop → Prop} (h1 : p True) (h2 : p False) (a) : p a := cases_on a h1 h2 end Classical diff --git a/Mathlib/Logic/Denumerable.lean b/Mathlib/Logic/Denumerable.lean index f96dccd8f839c..d6160e1858ab6 100644 --- a/Mathlib/Logic/Denumerable.lean +++ b/Mathlib/Logic/Denumerable.lean @@ -121,7 +121,6 @@ instance option : Denumerable (Option α) := · rw [decode_option_succ, decode_eq_ofNat, Option.map_some', Option.mem_def] rw [encode_some, encode_ofNat]⟩ -set_option linter.deprecated false in /-- If `α` and `β` are denumerable, then so is their sum. -/ instance sum : Denumerable (α ⊕ β) := ⟨fun n => by diff --git a/Mathlib/Logic/Equiv/List.lean b/Mathlib/Logic/Equiv/List.lean index c0753898bf0dc..6a6bb07e4ed21 100644 --- a/Mathlib/Logic/Equiv/List.lean +++ b/Mathlib/Logic/Equiv/List.lean @@ -127,11 +127,11 @@ noncomputable def _root_.Fintype.toEncodable (α : Type*) [Fintype α] : Encodab classical exact (Fintype.truncEncodable α).out /-- If `α` is encodable, then so is `Vector α n`. -/ -instance _root_.Vector.encodable [Encodable α] {n} : Encodable (Vector α n) := +instance Mathlib.Vector.encodable [Encodable α] {n} : Encodable (Mathlib.Vector α n) := Subtype.encodable /-- If `α` is countable, then so is `Vector α n`. -/ -instance _root_.Vector.countable [Countable α] {n} : Countable (Vector α n) := +instance Mathlib.Vector.countable [Countable α] {n} : Countable (Mathlib.Vector α n) := Subtype.countable /-- If `α` is encodable, then so is `Fin n → α`. -/ diff --git a/Mathlib/Logic/Equiv/Nat.lean b/Mathlib/Logic/Equiv/Nat.lean index 0bc17024d2609..69466efcdac2d 100644 --- a/Mathlib/Logic/Equiv/Nat.lean +++ b/Mathlib/Logic/Equiv/Nat.lean @@ -36,7 +36,6 @@ def boolProdNatEquivNat : Bool × ℕ ≃ ℕ where def natSumNatEquivNat : ℕ ⊕ ℕ ≃ ℕ := (boolProdEquivSum ℕ).symm.trans boolProdNatEquivNat -set_option linter.deprecated false in @[simp] theorem natSumNatEquivNat_apply : ⇑natSumNatEquivNat = Sum.elim (2 * ·) (2 * · + 1) := by ext (x | x) <;> rfl diff --git a/Mathlib/Logic/Small/List.lean b/Mathlib/Logic/Small/List.lean index 13b6fd0b0469a..f0706af610d10 100644 --- a/Mathlib/Logic/Small/List.lean +++ b/Mathlib/Logic/Small/List.lean @@ -18,9 +18,9 @@ universe u v open Mathlib -instance smallVector {α : Type v} {n : ℕ} [Small.{u} α] : Small.{u} (Vector α n) := +instance smallVector {α : Type v} {n : ℕ} [Small.{u} α] : Small.{u} (Mathlib.Vector α n) := small_of_injective (Equiv.vectorEquivFin α n).injective instance smallList {α : Type v} [Small.{u} α] : Small.{u} (List α) := by - let e : (Σn, Vector α n) ≃ List α := Equiv.sigmaFiberEquiv List.length + let e : (Σn, Mathlib.Vector α n) ≃ List α := Equiv.sigmaFiberEquiv List.length exact small_of_surjective e.surjective diff --git a/Mathlib/MeasureTheory/Constructions/Pi.lean b/Mathlib/MeasureTheory/Constructions/Pi.lean index aafd0f1b3c5ef..670e4e5bf0347 100644 --- a/Mathlib/MeasureTheory/Constructions/Pi.lean +++ b/Mathlib/MeasureTheory/Constructions/Pi.lean @@ -80,7 +80,7 @@ theorem isPiSystem_pi [∀ i, MeasurableSpace (α i)] : section Finite -variable [Finite ι] [Finite ι'] +variable [Finite ι] /-- Boxes of countably spanning sets are countably spanning. -/ theorem IsCountablySpanning.pi {C : ∀ i, Set (Set (α i))} (hC : ∀ i, IsCountablySpanning (C i)) : diff --git a/Mathlib/MeasureTheory/Function/AEEqOfIntegral.lean b/Mathlib/MeasureTheory/Function/AEEqOfIntegral.lean index ce393e78fea5c..10f195e4aacff 100644 --- a/Mathlib/MeasureTheory/Function/AEEqOfIntegral.lean +++ b/Mathlib/MeasureTheory/Function/AEEqOfIntegral.lean @@ -193,12 +193,12 @@ theorem ae_le_of_forall_setLIntegral_le_of_sigmaFinite₀ [SigmaFinite μ] have : Tendsto (fun n => g x + u n) atTop (𝓝 (g x + (0 : ℝ≥0))) := tendsto_const_nhds.add (ENNReal.tendsto_coe.2 u_lim) simp only [ENNReal.coe_zero, add_zero] at this - exact eventually_le_of_tendsto_lt hx this + exact this.eventually_le_const hx have L2 : ∀ᶠ n : ℕ in (atTop : Filter ℕ), g x ≤ (n : ℝ≥0) := - haveI : Tendsto (fun n : ℕ => ((n : ℝ≥0) : ℝ≥0∞)) atTop (𝓝 ∞) := by + have : Tendsto (fun n : ℕ => ((n : ℝ≥0) : ℝ≥0∞)) atTop (𝓝 ∞) := by simp only [ENNReal.coe_natCast] exact ENNReal.tendsto_nat_nhds_top - eventually_ge_of_tendsto_gt (hx.trans_le le_top) this + this.eventually_const_le (hx.trans_le le_top) apply Set.mem_iUnion.2 exact ((L1.and L2).and (eventually_mem_spanningSets μ x)).exists refine le_antisymm ?_ bot_le diff --git a/Mathlib/MeasureTheory/Function/L1Space.lean b/Mathlib/MeasureTheory/Function/L1Space.lean index 25e17db9f409b..b003cc9a9db03 100644 --- a/Mathlib/MeasureTheory/Function/L1Space.lean +++ b/Mathlib/MeasureTheory/Function/L1Space.lean @@ -443,7 +443,7 @@ lemma Integrable.of_finite [Finite α] [MeasurableSingletonClass α] [IsFiniteMe /-- This lemma is a special case of `Integrable.of_finite`. -/ -- Eternal deprecation for discoverability, don't remove -@[deprecated Integrable.of_finite, nolint deprecatedNoSince] +@[deprecated Integrable.of_finite (since := "2024-10-05"), nolint deprecatedNoSince] lemma Integrable.of_isEmpty [IsEmpty α] {f : α → β} : Integrable f μ := .of_finite @[deprecated (since := "2024-02-05")] alias integrable_of_fintype := Integrable.of_finite diff --git a/Mathlib/MeasureTheory/Function/LpSpace.lean b/Mathlib/MeasureTheory/Function/LpSpace.lean index 6d5ef3ffab106..41790feb62433 100644 --- a/Mathlib/MeasureTheory/Function/LpSpace.lean +++ b/Mathlib/MeasureTheory/Function/LpSpace.lean @@ -673,8 +673,7 @@ theorem exists_eLpNorm_indicator_le (hp : p ≠ ∞) (c : E) {ε : ℝ≥0∞} ( convert (NNReal.continuousAt_rpow_const (Or.inr hp₀')).tendsto.const_mul _ simp [hp₀''.ne'] have hε' : 0 < ε := hε.bot_lt - obtain ⟨δ, hδ, hδε'⟩ := - NNReal.nhds_zero_basis.eventually_iff.mp (eventually_le_of_tendsto_lt hε' this) + obtain ⟨δ, hδ, hδε'⟩ := NNReal.nhds_zero_basis.eventually_iff.mp (this.eventually_le_const hε') obtain ⟨η, hη, hηδ⟩ := exists_between hδ refine ⟨η, hη, ?_⟩ rw [← ENNReal.coe_rpow_of_nonneg _ hp₀', ← ENNReal.coe_mul] @@ -1193,7 +1192,7 @@ def compLpₗ (L : E →L[𝕜] F) : Lp E p μ →ₗ[𝕜] Lp F p μ where ext1 filter_upwards [Lp.coeFn_smul c f, coeFn_compLp L (c • f), Lp.coeFn_smul c (L.compLp f), coeFn_compLp L f] with _ ha1 ha2 ha3 ha4 - simp only [ha1, ha2, ha3, ha4, map_smul, Pi.smul_apply] + simp only [ha1, ha2, ha3, ha4, _root_.map_smul, Pi.smul_apply] /-- Composing `f : Lp E p μ` with `L : E →L[𝕜] F`, seen as a continuous `𝕜`-linear map on `Lp E p μ`. See also the similar diff --git a/Mathlib/MeasureTheory/Group/Action.lean b/Mathlib/MeasureTheory/Group/Action.lean index 0cb212b5273b1..cad802e003d1f 100644 --- a/Mathlib/MeasureTheory/Group/Action.lean +++ b/Mathlib/MeasureTheory/Group/Action.lean @@ -28,7 +28,7 @@ namespace MeasureTheory universe u v w -variable {G : Type u} {M : Type v} {α : Type w} {s : Set α} +variable {G : Type u} {M : Type v} {α : Type w} namespace SMulInvariantMeasure @@ -198,7 +198,7 @@ instance smulInvariantMeasure_map_smul [SMul M α] [SMul N α] [SMulCommClass N end SMulHomClass -variable (G) {m : MeasurableSpace α} [Group G] [MulAction G α] (c : G) (μ : Measure α) +variable (G) {m : MeasurableSpace α} [Group G] [MulAction G α] (μ : Measure α) variable [MeasurableSpace G] [MeasurableSMul G α] in /-- Equivalent definitions of a measure invariant under a multiplicative action of a group. diff --git a/Mathlib/MeasureTheory/Group/LIntegral.lean b/Mathlib/MeasureTheory/Group/LIntegral.lean index e0344acdeed93..74c8453b516af 100644 --- a/Mathlib/MeasureTheory/Group/LIntegral.lean +++ b/Mathlib/MeasureTheory/Group/LIntegral.lean @@ -20,7 +20,7 @@ open Measure TopologicalSpace open scoped ENNReal -variable {G : Type*} [MeasurableSpace G] {μ : Measure G} {g : G} +variable {G : Type*} [MeasurableSpace G] {μ : Measure G} section MeasurableMul diff --git a/Mathlib/MeasureTheory/Integral/Bochner.lean b/Mathlib/MeasureTheory/Integral/Bochner.lean index c85ae9df03c29..2cf72496737ad 100644 --- a/Mathlib/MeasureTheory/Integral/Bochner.lean +++ b/Mathlib/MeasureTheory/Integral/Bochner.lean @@ -638,7 +638,7 @@ theorem integral_sub (f g : α →₁[μ] E) : integral (f - g) = integral f - i theorem integral_smul (c : 𝕜) (f : α →₁[μ] E) : integral (c • f) = c • integral f := by simp only [integral] show (integralCLM' (E := E) 𝕜) (c • f) = c • (integralCLM' (E := E) 𝕜) f - exact map_smul (integralCLM' (E := E) 𝕜) c f + exact _root_.map_smul (integralCLM' (E := E) 𝕜) c f local notation "Integral" => @integralCLM α E _ _ μ _ _ diff --git a/Mathlib/MeasureTheory/Integral/IntegrableOn.lean b/Mathlib/MeasureTheory/Integral/IntegrableOn.lean index f9d75e6cfea42..d23df43813b60 100644 --- a/Mathlib/MeasureTheory/Integral/IntegrableOn.lean +++ b/Mathlib/MeasureTheory/Integral/IntegrableOn.lean @@ -489,7 +489,7 @@ lemma IntegrableAtFilter.eq_zero_of_tendsto (h : IntegrableAtFilter f l μ) (h' : ∀ s ∈ l, μ s = ∞) {a : E} (hf : Tendsto f l (𝓝 a)) : a = 0 := by by_contra H - obtain ⟨ε, εpos, hε⟩ : ∃ (ε : ℝ), 0 < ε ∧ ε < ‖a‖ := exists_between (norm_pos_iff'.mpr H) + obtain ⟨ε, εpos, hε⟩ : ∃ (ε : ℝ), 0 < ε ∧ ε < ‖a‖ := exists_between (norm_pos_iff.mpr H) rcases h with ⟨u, ul, hu⟩ let v := u ∩ {b | ε < ‖f b‖} have hv : IntegrableOn f v μ := hu.mono_set inter_subset_left diff --git a/Mathlib/MeasureTheory/Integral/IntegralEqImproper.lean b/Mathlib/MeasureTheory/Integral/IntegralEqImproper.lean index e2ec1a0114d79..9678b171ff3fc 100644 --- a/Mathlib/MeasureTheory/Integral/IntegralEqImproper.lean +++ b/Mathlib/MeasureTheory/Integral/IntegralEqImproper.lean @@ -388,9 +388,7 @@ theorem AECover.iSup_lintegral_eq_of_countably_generated [Nonempty ι] [l.NeBot] have := hφ.lintegral_tendsto_of_countably_generated hfm refine ciSup_eq_of_forall_le_of_forall_lt_exists_gt (fun i => lintegral_mono' Measure.restrict_le_self le_rfl) fun w hw => ?_ - rcases exists_between hw with ⟨m, hm₁, hm₂⟩ - rcases (eventually_ge_of_tendsto_gt hm₂ this).exists with ⟨i, hi⟩ - exact ⟨i, lt_of_lt_of_le hm₁ hi⟩ + exact (this.eventually_const_lt hw).exists end Lintegral diff --git a/Mathlib/MeasureTheory/Integral/Marginal.lean b/Mathlib/MeasureTheory/Integral/Marginal.lean index 76fcaa682df92..4e19390aa37fb 100644 --- a/Mathlib/MeasureTheory/Integral/Marginal.lean +++ b/Mathlib/MeasureTheory/Integral/Marginal.lean @@ -66,7 +66,7 @@ section LMarginal variable {δ δ' : Type*} {π : δ → Type*} [∀ x, MeasurableSpace (π x)] variable {μ : ∀ i, Measure (π i)} [DecidableEq δ] -variable {s t : Finset δ} {f g : (∀ i, π i) → ℝ≥0∞} {x y : ∀ i, π i} {i : δ} +variable {s t : Finset δ} {f : (∀ i, π i) → ℝ≥0∞} {x : ∀ i, π i} /-- Integrate `f(x₁,…,xₙ)` over all variables `xᵢ` where `i ∈ s`. Return a function in the remaining variables (it will be constant in the `xᵢ` for `i ∈ s`). diff --git a/Mathlib/MeasureTheory/MeasurableSpace/Basic.lean b/Mathlib/MeasureTheory/MeasurableSpace/Basic.lean index 4d2eb7fd31ab1..678a6983571d0 100644 --- a/Mathlib/MeasureTheory/MeasurableSpace/Basic.lean +++ b/Mathlib/MeasureTheory/MeasurableSpace/Basic.lean @@ -55,7 +55,7 @@ open Set Encodable Function Equiv Filter MeasureTheory universe uι -variable {α β γ δ δ' : Type*} {ι : Sort uι} {s t u : Set α} +variable {α β γ δ δ' : Type*} {ι : Sort uι} {s : Set α} namespace MeasurableSpace @@ -225,7 +225,7 @@ variable {f g : α → β} section TypeclassMeasurableSpace -variable [MeasurableSpace α] [MeasurableSpace β] [MeasurableSpace γ] +variable [MeasurableSpace α] [MeasurableSpace β] @[nontriviality, measurability] theorem Subsingleton.measurable [Subsingleton α] : Measurable f := fun _ _ => diff --git a/Mathlib/MeasureTheory/MeasurableSpace/Prod.lean b/Mathlib/MeasureTheory/MeasurableSpace/Prod.lean index e9f2db14bfc25..9dec6c3e39e9b 100644 --- a/Mathlib/MeasureTheory/MeasurableSpace/Prod.lean +++ b/Mathlib/MeasureTheory/MeasurableSpace/Prod.lean @@ -18,7 +18,7 @@ noncomputable section open Set MeasurableSpace -variable {α β γ : Type*} [MeasurableSpace α] [MeasurableSpace β] [MeasurableSpace γ] +variable {α β : Type*} [MeasurableSpace α] [MeasurableSpace β] /-- The product of generated σ-algebras is the one generated by rectangles, if both generating sets are countably spanning. -/ diff --git a/Mathlib/MeasureTheory/Measure/Count.lean b/Mathlib/MeasureTheory/Measure/Count.lean index b91e37e621e4a..6d5d487517d6d 100644 --- a/Mathlib/MeasureTheory/Measure/Count.lean +++ b/Mathlib/MeasureTheory/Measure/Count.lean @@ -98,33 +98,21 @@ theorem count_apply_lt_top [MeasurableSingletonClass α] : count s < ∞ ↔ s.F _ ↔ ¬s.Infinite := not_congr count_apply_eq_top _ ↔ s.Finite := Classical.not_not -theorem empty_of_count_eq_zero' (s_mble : MeasurableSet s) (hsc : count s = 0) : s = ∅ := by - have hs : s.Finite := by - rw [← count_apply_lt_top' s_mble, hsc] - exact WithTop.top_pos - simpa [count_apply_finite' hs s_mble] using hsc - -theorem empty_of_count_eq_zero [MeasurableSingletonClass α] (hsc : count s = 0) : s = ∅ := by - have hs : s.Finite := by - rw [← count_apply_lt_top, hsc] - exact WithTop.top_pos - simpa [count_apply_finite _ hs] using hsc - @[simp] -theorem count_eq_zero_iff' (s_mble : MeasurableSet s) : count s = 0 ↔ s = ∅ := - ⟨empty_of_count_eq_zero' s_mble, fun h => h.symm ▸ count_empty⟩ +theorem count_eq_zero_iff : count s = 0 ↔ s = ∅ where + mp h := eq_empty_of_forall_not_mem fun x hx ↦ by + simpa [hx] using ((ENNReal.le_tsum x).trans <| le_sum_apply _ _).trans_eq h + mpr := by rintro rfl; exact count_empty -@[simp] -theorem count_eq_zero_iff [MeasurableSingletonClass α] : count s = 0 ↔ s = ∅ := - ⟨empty_of_count_eq_zero, fun h => h.symm ▸ count_empty⟩ +lemma count_ne_zero_iff : count s ≠ 0 ↔ s.Nonempty := + count_eq_zero_iff.not.trans nonempty_iff_ne_empty.symm -theorem count_ne_zero' (hs' : s.Nonempty) (s_mble : MeasurableSet s) : count s ≠ 0 := by - rw [Ne, count_eq_zero_iff' s_mble] - exact hs'.ne_empty +alias ⟨_, count_ne_zero⟩ := count_ne_zero_iff -theorem count_ne_zero [MeasurableSingletonClass α] (hs' : s.Nonempty) : count s ≠ 0 := by - rw [Ne, count_eq_zero_iff] - exact hs'.ne_empty +@[deprecated (since := "2024-11-20")] alias ⟨empty_of_count_eq_zero, _⟩ := count_eq_zero_iff +@[deprecated (since := "2024-11-20")] alias empty_of_count_eq_zero' := empty_of_count_eq_zero +@[deprecated (since := "2024-11-20")] alias count_eq_zero_iff' := count_eq_zero_iff +@[deprecated (since := "2024-11-20")] alias count_ne_zero' := count_ne_zero @[simp] theorem count_singleton' {a : α} (ha : MeasurableSet ({a} : Set α)) : count ({a} : Set α) = 1 := by diff --git a/Mathlib/MeasureTheory/Measure/Haar/OfBasis.lean b/Mathlib/MeasureTheory/Measure/Haar/OfBasis.lean index 7f76b5cbe8048..a0db8d8e207b9 100644 --- a/Mathlib/MeasureTheory/Measure/Haar/OfBasis.lean +++ b/Mathlib/MeasureTheory/Measure/Haar/OfBasis.lean @@ -116,7 +116,7 @@ theorem parallelepiped_orthonormalBasis_one_dim (b : OrthonormalBasis ι ℝ ℝ · right simp_rw [H, parallelepiped, Algebra.id.smul_eq_mul, A] simp only [F, Finset.univ_unique, Fin.default_eq_zero, mul_neg, mul_one, Finset.sum_neg_distrib, - Finset.sum_singleton, ← image_comp, Function.comp, image_neg, preimage_neg_Icc, neg_zero] + Finset.sum_singleton, ← image_comp, Function.comp, image_neg, neg_Icc, neg_zero] theorem parallelepiped_eq_sum_segment (v : ι → E) : parallelepiped v = ∑ i, segment ℝ 0 (v i) := by ext diff --git a/Mathlib/MeasureTheory/Measure/Lebesgue/Integral.lean b/Mathlib/MeasureTheory/Measure/Lebesgue/Integral.lean index e4968335130b1..e72be147a0f25 100644 --- a/Mathlib/MeasureTheory/Measure/Lebesgue/Integral.lean +++ b/Mathlib/MeasureTheory/Measure/Lebesgue/Integral.lean @@ -83,7 +83,7 @@ theorem integral_comp_neg_Iic {E : Type*} [NormedAddCommGroup E] [NormedSpace (Homeomorph.neg ℝ).isClosedEmbedding.measurableEmbedding have := MeasurableEmbedding.setIntegral_map (μ := volume) A f (Ici (-c)) rw [Measure.map_neg_eq_self (volume : Measure ℝ)] at this - simp_rw [← integral_Ici_eq_integral_Ioi, this, neg_preimage, preimage_neg_Ici, neg_neg] + simp_rw [← integral_Ici_eq_integral_Ioi, this, neg_preimage, neg_Ici, neg_neg] /- @[simp] Porting note: Linter complains it does not apply to itself. Although it does apply to itself, it does not apply when `f` is more complicated -/ @@ -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_def, abs_neg, neg_preimage, preimage_neg_Iic, neg_zero] + simp_rw [Function.comp_def, abs_neg, neg_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/MeasureSpace.lean b/Mathlib/MeasureTheory/Measure/MeasureSpace.lean index 8cf14fc5dc9a6..3d62ba5101860 100644 --- a/Mathlib/MeasureTheory/Measure/MeasureSpace.lean +++ b/Mathlib/MeasureTheory/Measure/MeasureSpace.lean @@ -748,6 +748,11 @@ theorem coe_zero {_m : MeasurableSpace α} : ⇑(0 : Measure α) = 0 := ext s hs simp [hs] +@[simp] lemma _root_.MeasureTheory.OuterMeasure.toMeasure_eq_zero {ms : MeasurableSpace α} + {μ : OuterMeasure α} (h : ms ≤ μ.caratheodory) : μ.toMeasure h = 0 ↔ μ = 0 where + mp hμ := by ext s; exact le_bot_iff.1 <| (le_toMeasure_apply _ _ _).trans_eq congr($hμ s) + mpr := by rintro rfl; simp + @[nontriviality] lemma apply_eq_zero_of_isEmpty [IsEmpty α] {_ : MeasurableSpace α} (μ : Measure α) (s : Set α) : μ s = 0 := by @@ -1274,10 +1279,11 @@ theorem sum_apply₀ (f : ι → Measure α) {s : Set α} (hs : NullMeasurableSe /-! For the next theorem, the countability assumption is necessary. For a counterexample, consider an uncountable space, with a distinguished point `x₀`, and the sigma-algebra made of countable sets not containing `x₀`, and their complements. All points but `x₀` are measurable. -Consider the sum of the Dirac masses at points different from `x₀`, and `s = x₀`. For any Dirac mass -`δ_x`, we have `δ_x (x₀) = 0`, so `∑' x, δ_x (x₀) = 0`. On the other hand, the measure `sum δ_x` -gives mass one to each point different from `x₀`, so it gives infinite mass to any measurable set -containing `x₀` (as such a set is uncountable), and by outer regularity one get `sum δ_x {x₀} = ∞`. +Consider the sum of the Dirac masses at points different from `x₀`, and `s = {x₀}`. For any Dirac +mass `δ_x`, we have `δ_x (x₀) = 0`, so `∑' x, δ_x (x₀) = 0`. On the other hand, the measure +`sum δ_x` gives mass one to each point different from `x₀`, so it gives infinite mass to any +measurable set containing `x₀` (as such a set is uncountable), and by outer regularity one gets +`sum δ_x {x₀} = ∞`. -/ theorem sum_apply_of_countable [Countable ι] (f : ι → Measure α) (s : Set α) : sum f s = ∑' i, f i s := by diff --git a/Mathlib/MeasureTheory/Measure/MeasureSpaceDef.lean b/Mathlib/MeasureTheory/Measure/MeasureSpaceDef.lean index 8eb64f43a20e2..11481cc61993f 100644 --- a/Mathlib/MeasureTheory/Measure/MeasureSpaceDef.lean +++ b/Mathlib/MeasureTheory/Measure/MeasureSpaceDef.lean @@ -82,9 +82,9 @@ instance Measure.instFunLike [MeasurableSpace α] : FunLike (Measure α) (Set α coe μ := μ.toOuterMeasure coe_injective' | ⟨_, _, _⟩, ⟨_, _, _⟩, h => toOuterMeasure_injective <| DFunLike.coe_injective h -set_option linter.deprecated false in -- Not immediately obvious how to use `measure_empty` here. + instance Measure.instOuterMeasureClass [MeasurableSpace α] : OuterMeasureClass (Measure α) α where - measure_empty m := m.empty' + measure_empty m := measure_empty (μ := m.toOuterMeasure) measure_iUnion_nat_le m := m.iUnion_nat measure_mono m := m.mono diff --git a/Mathlib/MeasureTheory/Measure/Portmanteau.lean b/Mathlib/MeasureTheory/Measure/Portmanteau.lean index 4d82e897d1771..72fe3305828be 100644 --- a/Mathlib/MeasureTheory/Measure/Portmanteau.lean +++ b/Mathlib/MeasureTheory/Measure/Portmanteau.lean @@ -278,14 +278,14 @@ theorem FiniteMeasure.limsup_measure_closed_le_of_tendsto {Ω ι : Type*} {L : F HasOuterApproxClosed.tendsto_lintegral_apprSeq F_closed (μ : Measure Ω) have room₁ : (μ : Measure Ω) F < (μ : Measure Ω) F + ε / 2 := ENNReal.lt_add_right (measure_lt_top (μ : Measure Ω) F).ne ε_pos' - obtain ⟨M, hM⟩ := eventually_atTop.mp <| eventually_lt_of_tendsto_lt room₁ key₁ + obtain ⟨M, hM⟩ := eventually_atTop.mp <| key₁.eventually_lt_const room₁ have key₂ := FiniteMeasure.tendsto_iff_forall_lintegral_tendsto.mp μs_lim (fs M) have room₂ : (lintegral (μ : Measure Ω) fun a ↦ fs M a) < (lintegral (μ : Measure Ω) fun a ↦ fs M a) + ε / 2 := ENNReal.lt_add_right (ne_of_lt ((fs M).lintegral_lt_top_of_nnreal _)) ε_pos' - have ev_near := Eventually.mono (eventually_lt_of_tendsto_lt room₂ key₂) fun n ↦ le_of_lt - have ev_near' := Eventually.mono ev_near + have ev_near := key₂.eventually_le_const room₂ + have ev_near' := ev_near.mono (fun n ↦ le_trans (HasOuterApproxClosed.measure_le_lintegral F_closed (μs n) M)) apply (Filter.limsup_le_limsup ev_near').trans rw [limsup_const] diff --git a/Mathlib/MeasureTheory/Measure/Regular.lean b/Mathlib/MeasureTheory/Measure/Regular.lean index ed27aa6936522..91b924e0a4f30 100644 --- a/Mathlib/MeasureTheory/Measure/Regular.lean +++ b/Mathlib/MeasureTheory/Measure/Regular.lean @@ -446,7 +446,7 @@ protected theorem FiniteSpanningSetsIn.outerRegular namespace InnerRegularWRT -variable {p q : Set α → Prop} {U s : Set α} {ε r : ℝ≥0∞} +variable {p : Set α → Prop} /-- If the restrictions of a measure to a monotone sequence of sets covering the space are inner regular for some property `p` and all measurable sets, then the measure itself is @@ -637,7 +637,7 @@ end InnerRegularWRT namespace InnerRegular -variable {U : Set α} {ε : ℝ≥0∞} [TopologicalSpace α] +variable [TopologicalSpace α] /-- The measure of a measurable set is the supremum of the measures of compact sets it contains. -/ theorem _root_.MeasurableSet.measure_eq_iSup_isCompact ⦃U : Set α⦄ (hU : MeasurableSet U) diff --git a/Mathlib/MeasureTheory/Measure/Typeclasses.lean b/Mathlib/MeasureTheory/Measure/Typeclasses.lean index 7ab48f4222914..f8d833559d3e9 100644 --- a/Mathlib/MeasureTheory/Measure/Typeclasses.lean +++ b/Mathlib/MeasureTheory/Measure/Typeclasses.lean @@ -567,7 +567,7 @@ instance isFiniteMeasure_sfiniteSeq [h : SFinite μ] (n : ℕ) : IsFiniteMeasure h.1.choose_spec.1 n set_option linter.deprecated false in -@[deprecated (since := "2024-10-11")] +@[deprecated "No deprecation message was provided." (since := "2024-10-11")] instance isFiniteMeasure_sFiniteSeq [SFinite μ] (n : ℕ) : IsFiniteMeasure (sFiniteSeq μ n) := isFiniteMeasure_sfiniteSeq n @@ -800,7 +800,7 @@ theorem countable_meas_pos_of_disjoint_of_meas_iUnion_ne_top₀ {ι : Type*} {_ simp only [fairmeas] rfl simpa only [fairmeas_eq, posmeas_def, ← preimage_iUnion, - iUnion_Ici_eq_Ioi_of_lt_of_tendsto (0 : ℝ≥0∞) (fun n => (as_mem n).1) as_lim] + iUnion_Ici_eq_Ioi_of_lt_of_tendsto (fun n => (as_mem n).1) as_lim] rw [countable_union] refine countable_iUnion fun n => Finite.countable ?_ exact finite_const_le_meas_of_disjoint_iUnion₀ μ (as_mem n).1 As_mble As_disj Union_As_finite diff --git a/Mathlib/MeasureTheory/Measure/WithDensity.lean b/Mathlib/MeasureTheory/Measure/WithDensity.lean index d343307b3e3fc..f8c9285e8bbbf 100644 --- a/Mathlib/MeasureTheory/Measure/WithDensity.lean +++ b/Mathlib/MeasureTheory/Measure/WithDensity.lean @@ -669,7 +669,7 @@ lemma IsLocallyFiniteMeasure.withDensity_coe {f : α → ℝ≥0} (hf : Continuo IsLocallyFiniteMeasure (μ.withDensity fun x ↦ f x) := by refine ⟨fun x ↦ ?_⟩ rcases (μ.finiteAt_nhds x).exists_mem_basis ((nhds_basis_opens' x).restrict_subset - (eventually_le_of_tendsto_lt (lt_add_one _) (hf.tendsto x))) with ⟨U, ⟨⟨hUx, hUo⟩, hUf⟩, hμU⟩ + ((hf.tendsto x).eventually_le_const (lt_add_one _))) with ⟨U, ⟨⟨hUx, hUo⟩, hUf⟩, hμU⟩ refine ⟨U, hUx, ?_⟩ rw [withDensity_apply _ hUo.measurableSet] exact setLIntegral_lt_top_of_bddAbove hμU.ne ⟨f x + 1, forall_mem_image.2 hUf⟩ diff --git a/Mathlib/MeasureTheory/Measure/WithDensityFinite.lean b/Mathlib/MeasureTheory/Measure/WithDensityFinite.lean index 21abd06cd6cee..40b56846328c7 100644 --- a/Mathlib/MeasureTheory/Measure/WithDensityFinite.lean +++ b/Mathlib/MeasureTheory/Measure/WithDensityFinite.lean @@ -117,7 +117,7 @@ noncomputable def Measure.densityToFinite (μ : Measure α) [SFinite μ] (a : α μ.rnDeriv μ.toFinite a set_option linter.deprecated false in -@[deprecated (since := "2024-10-04")] +@[deprecated "No deprecation message was provided." (since := "2024-10-04")] lemma densityToFinite_def (μ : Measure α) [SFinite μ] : μ.densityToFinite = μ.rnDeriv μ.toFinite := rfl diff --git a/Mathlib/ModelTheory/Encoding.lean b/Mathlib/ModelTheory/Encoding.lean index 5395d5324a5a6..180cb86b870ed 100644 --- a/Mathlib/ModelTheory/Encoding.lean +++ b/Mathlib/ModelTheory/Encoding.lean @@ -181,13 +181,6 @@ or returns `default` if not possible. -/ def sigmaImp : (Σn, L.BoundedFormula α n) → (Σn, L.BoundedFormula α n) → Σn, L.BoundedFormula α n | ⟨m, φ⟩, ⟨n, ψ⟩ => if h : m = n then ⟨m, φ.imp (Eq.mp (by rw [h]) ψ)⟩ else default -#adaptation_note -/-- -`List.drop_sizeOf_le` is deprecated. -See https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/Why.20is.20.60Mathlib.2EModelTheory.2EEncoding.60.20using.20.60SizeOf.2EsizeOf.60.3F -for discussion about adapting this code. --/ -set_option linter.deprecated false in /-- Decodes a list of symbols as a list of formulas. -/ @[simp] lemma sigmaImp_apply {n} {φ ψ : L.BoundedFormula α n} : diff --git a/Mathlib/NumberTheory/ArithmeticFunction.lean b/Mathlib/NumberTheory/ArithmeticFunction.lean index 5c13f9d53ebe2..8b8038b188ab0 100644 --- a/Mathlib/NumberTheory/ArithmeticFunction.lean +++ b/Mathlib/NumberTheory/ArithmeticFunction.lean @@ -1291,7 +1291,8 @@ theorem _root_.Nat.card_divisors {n : ℕ} (hn : n ≠ 0) : exact Finset.prod_congr n.support_factorization fun _ h => sigma_zero_apply_prime_pow <| Nat.prime_of_mem_primeFactors h -@[deprecated (since := "2024-06-09")] theorem card_divisors (n : ℕ) (hn : n ≠ 0) : +@[deprecated "No deprecation message was provided." (since := "2024-06-09")] +theorem card_divisors (n : ℕ) (hn : n ≠ 0) : #n.divisors = n.primeFactors.prod (n.factorization · + 1) := Nat.card_divisors hn theorem _root_.Nat.sum_divisors {n : ℕ} (hn : n ≠ 0) : diff --git a/Mathlib/NumberTheory/ClassNumber/AdmissibleAbsoluteValue.lean b/Mathlib/NumberTheory/ClassNumber/AdmissibleAbsoluteValue.lean index 22fc2f2d46e5e..0d34bda52b147 100644 --- a/Mathlib/NumberTheory/ClassNumber/AdmissibleAbsoluteValue.lean +++ b/Mathlib/NumberTheory/ClassNumber/AdmissibleAbsoluteValue.lean @@ -102,7 +102,7 @@ theorem exists_approx_aux (n : ℕ) (h : abv.IsAdmissible) : /-- This proof was nicer prior to https://github.com/leanprover/lean4/pull/4400. Please feel welcome to improve it, by avoiding use of `List.get` in favour of `GetElem`. -/ have : ∀ i h, t ((Finset.univ.filter fun x ↦ t x = s).toList.get ⟨i, h⟩) = s := fun i h ↦ - (Finset.mem_filter.mp (Finset.mem_toList.mp (List.getElem_mem h))).2 + (Finset.mem_filter.mp (Finset.mem_toList.mp (List.get_mem _ ⟨i, h⟩))).2 simp only [Nat.succ_eq_add_one, Finset.length_toList, List.get_eq_getElem] at this simp only [Nat.succ_eq_add_one, List.get_eq_getElem, Fin.coe_castLE] rw [this _ (Nat.lt_of_le_of_lt (Nat.le_of_lt_succ i₁.2) hs), diff --git a/Mathlib/NumberTheory/Divisors.lean b/Mathlib/NumberTheory/Divisors.lean index e2bfeafb8e217..5d34808cc4719 100644 --- a/Mathlib/NumberTheory/Divisors.lean +++ b/Mathlib/NumberTheory/Divisors.lean @@ -391,7 +391,7 @@ theorem Prime.prod_divisors {α : Type*} [CommMonoid α] {p : ℕ} {f : ℕ → theorem properDivisors_eq_singleton_one_iff_prime : n.properDivisors = {1} ↔ n.Prime := by refine ⟨?_, ?_⟩ · intro h - refine Nat.prime_def_lt''.mpr ⟨?_, fun m hdvd => ?_⟩ + refine Nat.prime_def.mpr ⟨?_, fun m hdvd => ?_⟩ · match n with | 0 => contradiction | 1 => contradiction diff --git a/Mathlib/NumberTheory/Fermat.lean b/Mathlib/NumberTheory/Fermat.lean index 18c9ed47758f2..bdb8dd1117803 100644 --- a/Mathlib/NumberTheory/Fermat.lean +++ b/Mathlib/NumberTheory/Fermat.lean @@ -196,7 +196,7 @@ theorem prime_of_pow_sub_one_prime {a n : ℕ} (hn1 : n ≠ 1) (hP : (a ^ n - 1) rw [one_pow, hP.dvd_iff_eq (mt (Nat.sub_eq_iff_eq_add ha1.le).mp hn1), eq_comm] at h exact (pow_eq_self_iff ha1).mp (Nat.sub_one_cancel ha0 (pow_pos ha0 n) h).symm subst ha2 - refine ⟨rfl, Nat.prime_def_lt''.mpr ⟨(two_le_iff n).mpr ⟨hn0, hn1⟩, fun d hdn ↦ ?_⟩⟩ + refine ⟨rfl, Nat.prime_def.mpr ⟨(two_le_iff n).mpr ⟨hn0, hn1⟩, fun d hdn ↦ ?_⟩⟩ have hinj : ∀ x y, 2 ^ x - 1 = 2 ^ y - 1 → x = y := fun x y h ↦ Nat.pow_right_injective le_rfl (sub_one_cancel (pow_pos ha0 x) (pow_pos ha0 y) h) let h := nat_sub_dvd_pow_sub_pow (2 ^ d) 1 (n / d) diff --git a/Mathlib/NumberTheory/FermatPsp.lean b/Mathlib/NumberTheory/FermatPsp.lean index 9fc7ee0822135..31cdde409beb6 100644 --- a/Mathlib/NumberTheory/FermatPsp.lean +++ b/Mathlib/NumberTheory/FermatPsp.lean @@ -197,10 +197,8 @@ private theorem psp_from_prime_psp {b : ℕ} (b_ge_two : 2 ≤ b) {p : ℕ} (p_p have hi_p : 1 ≤ p := Nat.one_le_of_lt p_gt_two have hi_bsquared : 0 < b ^ 2 - 1 := by -- Porting note: was `by nlinarith [Nat.one_le_pow 2 b hi_b]` - have h0 := mul_le_mul b_ge_two b_ge_two zero_le_two hi_b.le - have h1 : 1 < 2 * 2 := by omega - have := tsub_pos_of_lt (h1.trans_le h0) - rwa [pow_two] + have := Nat.pow_le_pow_left b_ge_two 2 + omega have hi_bpowtwop : 1 ≤ b ^ (2 * p) := Nat.one_le_pow (2 * p) b hi_b have hi_bpowpsubone : 1 ≤ b ^ (p - 1) := Nat.one_le_pow (p - 1) b hi_b -- Other useful facts @@ -306,7 +304,7 @@ private theorem psp_from_prime_gt_p {b : ℕ} (b_ge_two : 2 ≤ b) {p : ℕ} (p_ suffices h : p * b ^ 2 < (b ^ 2) ^ (p - 1) * b ^ 2 by apply gt_of_ge_of_gt · exact tsub_le_tsub_left (one_le_of_lt p_gt_two) ((b ^ 2) ^ (p - 1) * b ^ 2) - · have : p ≤ p * b ^ 2 := Nat.le_mul_of_pos_right _ (show 0 < b ^ 2 by nlinarith) + · have : p ≤ p * b ^ 2 := Nat.le_mul_of_pos_right _ (show 0 < b ^ 2 by positivity) exact tsub_lt_tsub_right_of_le this h suffices h : p < (b ^ 2) ^ (p - 1) by have : 4 ≤ b ^ 2 := by nlinarith diff --git a/Mathlib/NumberTheory/Harmonic/Defs.lean b/Mathlib/NumberTheory/Harmonic/Defs.lean index 51c8f7036e358..29d3f5fa6bbe5 100644 --- a/Mathlib/NumberTheory/Harmonic/Defs.lean +++ b/Mathlib/NumberTheory/Harmonic/Defs.lean @@ -5,7 +5,7 @@ Authors: Koundinya Vajjha, Thomas Browning -/ import Mathlib.Algebra.BigOperators.Intervals import Mathlib.Algebra.Order.Field.Basic -import Mathlib.Tactic.Positivity.Finset +import Mathlib.Tactic.Positivity /-! diff --git a/Mathlib/NumberTheory/LSeries/Convergence.lean b/Mathlib/NumberTheory/LSeries/Convergence.lean index c5a161fa9aae9..5310dc93a15ed 100644 --- a/Mathlib/NumberTheory/LSeries/Convergence.lean +++ b/Mathlib/NumberTheory/LSeries/Convergence.lean @@ -119,3 +119,21 @@ lemma LSeries.abscissaOfAbsConv_le_one_of_isBigO_one {f : ℕ → ℂ} (h : f =O convert abscissaOfAbsConv_le_of_isBigO_rpow (x := 0) ?_ · simp only [EReal.coe_zero, zero_add] · simpa only [Real.rpow_zero] using h + +/-- If `f` is real-valued and `x` is strictly greater than the abscissa of absolute convergence +of `f`, then the real series `∑' n, f n / n ^ x` converges. -/ +lemma LSeries.summable_real_of_abscissaOfAbsConv_lt {f : ℕ → ℝ} {x : ℝ} + (h : abscissaOfAbsConv (f ·) < x) : + Summable fun n : ℕ ↦ f n / (n : ℝ) ^ x := by + have h' : abscissaOfAbsConv (f ·) < (x : ℂ).re := by simpa only [ofReal_re] using h + have := LSeriesSummable_of_abscissaOfAbsConv_lt_re h' + rw [LSeriesSummable, show term _ _ = fun n ↦ _ from rfl] at this + conv at this => + enter [1, n] + rw [term_def, show (n : ℂ) = (n : ℝ) from rfl, ← ofReal_cpow n.cast_nonneg, ← ofReal_div, + show (0 : ℂ) = (0 : ℝ) from rfl, ← apply_ite] + rw [summable_ofReal] at this + refine this.congr_cofinite ?_ + filter_upwards [Set.Finite.compl_mem_cofinite <| Set.finite_singleton 0] with n hn + simp only [Set.mem_compl_iff, Set.mem_singleton_iff] at hn + exact if_neg hn diff --git a/Mathlib/NumberTheory/LSeries/PrimesInAP.lean b/Mathlib/NumberTheory/LSeries/PrimesInAP.lean new file mode 100644 index 0000000000000..3cd0c083dd5d6 --- /dev/null +++ b/Mathlib/NumberTheory/LSeries/PrimesInAP.lean @@ -0,0 +1,492 @@ +/- +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.DirichletCharacter.Orthogonality +import Mathlib.NumberTheory.LSeries.Linearity +import Mathlib.NumberTheory.LSeries.Nonvanishing +import Mathlib.RingTheory.RootsOfUnity.AlgebraicallyClosed + +/-! +# Dirichlet's Theorem on primes in arithmetic progression + +The goal of this file is to prove **Dirichlet's Theorem**: If `q` is a positive natural number +and `a : ZMod q` is invertible, then there are infinitely many prime numbers `p` such that +`(p : ZMod q) = a`. + +The main steps of the proof are as follows. +1. Define `ArithmeticFunction.vonMangoldt.residueClass a` for `a : ZMod q`, which is + a function `ℕ → ℝ` taking the value zero when `(n : ℤMod q) ≠ a` and `Λ n` else + (where `Λ` is the von Mangoldt function `ArithmeticFunction.vonMangoldt`; we have + `Λ (p^k) = log p` for prime powers and `Λ n = 0` otherwise.) +2. Show that this function can be written as a linear combination of functions + of the form `χ * Λ` (pointwise product) with Dirichlet characters `χ` mod `q`. + See `ArithmeticFunction.vonMangoldt.residueClass_eq`. +3. This implies that the L-series of `ArithmeticFunction.vonMangoldt.residueClass a` + agrees (on `re s > 1`) with the corresponding linear combination of negative logarithmic + derivatives of Dirichlet L-functions. + See `ArithmeticFunction.vonMangoldt.LSeries_residueClass_eq`. +4. Define an auxiliary function `ArithmeticFunction.vonMangoldt.LfunctionResidueClassAux a` that is + this linear combination of negative logarithmic derivatives of L-functions minus + `(q.totient)⁻¹/(s-1)`, which cancels the pole at `s = 1`. + See `ArithmeticFunction.vonMangoldt.eqOn_LfunctionResidueClassAux` for the statement + that the auxiliary function agrees with the L-series of + `ArithmeticFunction.vonMangoldt.residueClass` up to the term `(q.totient)⁻¹/(s-1)`. +5. Show that the auxiliary function is continuous on `re s ≥ 1`; + see `ArithmeticFunction.vonMangoldt.continuousOn_LfunctionResidueClassAux`. + This relies heavily on the non-vanishing of Dirichlet L-functions on the *closed* + half-plane `re s ≥ 1` (`DirichletCharacter.LFunction_ne_zero_of_one_le_re`), which + in turn can only be stated since we know that the L-series of a Dirichlet character + extends to an entire function (unless the character is trivial; then there is a + simple pole at `s = 1`); see `DirichletCharacter.LFunction_eq_LSeries` + (contributed by David Loeffler). +6. Show that the sum of `Λ n / n` over any residue class, but *excluding* the primes, converges. + See `ArithmeticFunction.vonMangoldt.summable_residueClass_non_primes_div`. +7. Combining these ingredients, we can deduce that the sum of `Λ n / n` over + the *primes* in a residue class must diverge. + See `ArithmeticFunction.vonMangoldt.not_summable_residueClass_prime_div`. +8. This finally easily implies that there must be infinitely many primes in the residue class. + +## Definitions + +* `ArithmeticFunction.vonMangoldt.residueClass a` (see above). +* `ArithmeticFunction.vonMangoldt.continuousOn_LfunctionResidueClassAux` (see above). + +## Main Result + +We give two versions of **Dirichlet's Theorem**: +* `Nat.setOf_prime_and_eq_mod_infinite` states that the set of primes `p` + such that `(p : ZMod q) = a` is infinite (when `a` is invertible in `ZMod q`). +* `Nat.forall_exists_prime_gt_and_eq_mod` states that for any natural number `n` + there is a prime `p > n` such that `(p : ZMod q) = a`. + +## Tags + +prime number, arithmetic progression, residue class, Dirichlet's Theorem +-/ + +/-! +### Auxiliary statements + +An infinite product or sum over a function supported in prime powers can be written +as an iterated product or sum over primes and natural numbers. +-/ + +section auxiliary + +variable {α β γ : Type*} [CommGroup α] [UniformSpace α] [UniformGroup α] [CompleteSpace α] + [T0Space α] + +open Nat.Primes in +@[to_additive tsum_eq_tsum_primes_of_support_subset_prime_powers] +lemma tprod_eq_tprod_primes_of_mulSupport_subset_prime_powers {f : ℕ → α} + (hfm : Multipliable f) (hf : Function.mulSupport f ⊆ {n | IsPrimePow n}) : + ∏' n : ℕ, f n = ∏' (p : Nat.Primes) (k : ℕ), f (p ^ (k + 1)) := by + have hfm' : Multipliable fun pk : Nat.Primes × ℕ ↦ f (pk.fst ^ (pk.snd + 1)) := + prodNatEquiv.symm.multipliable_iff.mp <| by + simpa only [← coe_prodNatEquiv_apply, Prod.eta, Function.comp_def, Equiv.apply_symm_apply] + using hfm.subtype _ + simp only [← tprod_subtype_eq_of_mulSupport_subset hf, Set.coe_setOf, ← prodNatEquiv.tprod_eq, + ← tprod_prod hfm'] + refine tprod_congr fun (p, k) ↦ congrArg f <| coe_prodNatEquiv_apply .. + +@[to_additive tsum_eq_tsum_primes_add_tsum_primes_of_support_subset_prime_powers] +lemma tprod_eq_tprod_primes_mul_tprod_primes_of_mulSupport_subset_prime_powers {f : ℕ → α} + (hfm : Multipliable f) (hf : Function.mulSupport f ⊆ {n | IsPrimePow n}) : + ∏' n : ℕ, f n = (∏' p : Nat.Primes, f p) * ∏' (p : Nat.Primes) (k : ℕ), f (p ^ (k + 2)) := by + rw [tprod_eq_tprod_primes_of_mulSupport_subset_prime_powers hfm hf] + have hfs' (p : Nat.Primes) : Multipliable fun k : ℕ ↦ f (p ^ (k + 1)) := + hfm.comp_injective <| (strictMono_nat_of_lt_succ + fun k ↦ pow_lt_pow_right₀ p.prop.one_lt <| lt_add_one (k + 1)).injective + conv_lhs => + enter [1, p]; rw [tprod_eq_zero_mul (hfs' p), zero_add, pow_one] + enter [2, 1, k]; rw [add_assoc, one_add_one_eq_two] + exact tprod_mul (Multipliable.subtype hfm _) <| + Multipliable.prod (f := fun (pk : Nat.Primes × ℕ) ↦ f (pk.1 ^ (pk.2 + 2))) <| + hfm.comp_injective <| Subtype.val_injective |>.comp + Nat.Primes.prodNatEquiv.injective |>.comp <| + Function.Injective.prodMap (fun ⦃_ _⦄ a ↦ a) <| add_left_injective 1 + +end auxiliary + +/-! +### The L-series of the von Mangoldt function restricted to a residue class +-/ + +section arith_prog + +namespace ArithmeticFunction.vonMangoldt + +open Complex LSeries DirichletCharacter + +open scoped LSeries.notation + +variable {q : ℕ} (a : ZMod q) + +/-- The von Mangoldt function restricted to the residue class `a` mod `q`. -/ +noncomputable abbrev residueClass : ℕ → ℝ := + {n : ℕ | (n : ZMod q) = a}.indicator (vonMangoldt ·) + +lemma residueClass_nonneg (n : ℕ) : 0 ≤ residueClass a n := + Set.indicator_apply_nonneg fun _ ↦ vonMangoldt_nonneg + +lemma residueClass_le (n : ℕ) : residueClass a n ≤ vonMangoldt n := + Set.indicator_apply_le' (fun _ ↦ le_rfl) (fun _ ↦ vonMangoldt_nonneg) + +@[simp] +lemma residueClass_apply_zero : residueClass a 0 = 0 := by + simp only [Set.indicator_apply_eq_zero, Set.mem_setOf_eq, Nat.cast_zero, map_zero, ofReal_zero, + implies_true] + +lemma abscissaOfAbsConv_residueClass_le_one : + abscissaOfAbsConv ↗(residueClass a) ≤ 1 := by + refine abscissaOfAbsConv_le_of_forall_lt_LSeriesSummable fun y hy ↦ ?_ + unfold LSeriesSummable + have := LSeriesSummable_vonMangoldt <| show 1 < (y : ℂ).re by simp only [ofReal_re, hy] + convert this.indicator {n : ℕ | (n : ZMod q) = a} + ext1 n + by_cases hn : (n : ZMod q) = a + · simp +contextual only [term, Set.indicator, Set.mem_setOf_eq, hn, ↓reduceIte, apply_ite, + ite_self] + · simp +contextual only [term, Set.mem_setOf_eq, hn, not_false_eq_true, Set.indicator_of_not_mem, + ofReal_zero, zero_div, ite_self] + +/-- The set we are interested in (prime numbers in the residue class `a`) is the same as the support +of `ArithmeticFunction.vonMangoldt.residueClass` restricted to primes (and divided by `n`; +this is how this result is used later). -/ +lemma support_residueClass_prime_div : + Function.support (fun n : ℕ ↦ (if n.Prime then residueClass a n else 0) / n) = + {p : ℕ | p.Prime ∧ (p : ZMod q) = a} := by + simp only [Function.support, ne_eq, div_eq_zero_iff, ite_eq_right_iff, + Set.indicator_apply_eq_zero, Set.mem_setOf_eq, Nat.cast_eq_zero, not_or, Classical.not_imp] + ext1 p + simp only [Set.mem_setOf_eq] + exact ⟨fun H ↦ ⟨H.1.1, H.1.2.1⟩, + fun H ↦ ⟨⟨H.1, H.2, vonMangoldt_ne_zero_iff.mpr H.1.isPrimePow⟩, H.1.ne_zero⟩⟩ + +private noncomputable def F₀ (n : ℕ) : ℝ := (if n.Prime then 0 else vonMangoldt n) / n + +private noncomputable def F' (pk : Nat.Primes × ℕ) : ℝ := F₀ (pk.1 ^ (pk.2 + 1)) + +private noncomputable def F'' : Nat.Primes × ℕ → ℝ := F' ∘ (Prod.map _root_.id (· + 1)) + +private lemma F''_le (p : Nat.Primes) (k : ℕ) : F'' (p, k) ≤ 2 * (p : ℝ)⁻¹ ^ (k + 3 / 2 : ℝ) := + calc _ + _ = Real.log p * (p : ℝ)⁻¹ ^ (k + 2) := by + simp only [F'', Function.comp_apply, F', F₀, Prod.map_apply, id_eq, le_add_iff_nonneg_left, + zero_le, Nat.Prime.not_prime_pow, ↓reduceIte, vonMangoldt_apply_prime p.prop, + vonMangoldt_apply_pow (Nat.zero_ne_add_one _).symm, Nat.cast_pow, div_eq_mul_inv, + inv_pow (p : ℝ) (k + 2)] + _ ≤ (p: ℝ) ^ (1 / 2 : ℝ) / (1 / 2) * (p : ℝ)⁻¹ ^ (k + 2) := + mul_le_mul_of_nonneg_right (Real.log_le_rpow_div p.val.cast_nonneg one_half_pos) + (pow_nonneg (inv_nonneg_of_nonneg (Nat.cast_nonneg ↑p)) (k + 2)) + _ = 2 * (p : ℝ)⁻¹ ^ (-1 / 2 : ℝ) * (p : ℝ)⁻¹ ^ (k + 2) := by + simp only [← div_mul, div_one, mul_comm, neg_div, Real.inv_rpow p.val.cast_nonneg, + ← Real.rpow_neg p.val.cast_nonneg, neg_neg] + _ = _ := by + rw [mul_assoc, ← Real.rpow_natCast, + ← Real.rpow_add <| by have := p.prop.pos; positivity, Nat.cast_add, Nat.cast_two, + add_comm, add_assoc] + norm_num + +open Nat.Primes + +private lemma summable_F'' : Summable F'' := by + have hp₀ (p : Nat.Primes) : 0 < (p : ℝ)⁻¹ := inv_pos_of_pos (Nat.cast_pos.mpr p.prop.pos) + have hp₁ (p : Nat.Primes) : (p : ℝ)⁻¹ < 1 := + (inv_lt_one₀ <| mod_cast p.prop.pos).mpr <| Nat.one_lt_cast.mpr <| p.prop.one_lt + suffices Summable fun (pk : Nat.Primes × ℕ) ↦ (pk.1 : ℝ)⁻¹ ^ (pk.2 + 3 / 2 : ℝ) by + refine (Summable.mul_left 2 this).of_nonneg_of_le (fun pk ↦ ?_) (fun pk ↦ F''_le pk.1 pk.2) + simp only [F'', Function.comp_apply, F', F₀, Prod.map_fst, id_eq, Prod.map_snd, Nat.cast_pow] + have := vonMangoldt_nonneg (n := (pk.1 : ℕ) ^ (pk.2 + 2)) + positivity + conv => enter [1, pk]; rw [Real.rpow_add <| hp₀ pk.1, Real.rpow_natCast] + refine (summable_prod_of_nonneg (fun _ ↦ by positivity)).mpr ⟨(fun p ↦ ?_), ?_⟩ + · dsimp only -- otherwise the `exact` below times out + exact Summable.mul_right _ <| summable_geometric_of_lt_one (hp₀ p).le (hp₁ p) + · dsimp only + conv => enter [1, p]; rw [tsum_mul_right, tsum_geometric_of_lt_one (hp₀ p).le (hp₁ p)] + refine (summable_rpow.mpr (by norm_num : -(3 / 2 : ℝ) < -1)).mul_left 2 + |>.of_nonneg_of_le (fun p ↦ ?_) (fun p ↦ ?_) + · have := sub_pos.mpr (hp₁ p) + positivity + · rw [Real.inv_rpow p.val.cast_nonneg, Real.rpow_neg p.val.cast_nonneg] + gcongr + rw [inv_le_comm₀ (sub_pos.mpr (hp₁ p)) zero_lt_two, le_sub_comm, + show (1 : ℝ) - 2⁻¹ = 2⁻¹ by norm_num, inv_le_inv₀ (mod_cast p.prop.pos) zero_lt_two] + exact Nat.ofNat_le_cast.mpr p.prop.two_le + +/-- The function `n ↦ Λ n / n`, restriced to non-primes in a residue class, is summable. +This is used to convert results on `ArithmeticFunction.vonMangoldt.residueClass` to results +on primes in an arithmetic progression. -/ +lemma summable_residueClass_non_primes_div : + Summable fun n : ℕ ↦ (if n.Prime then 0 else residueClass a n) / n := by + have h₀ (n : ℕ) : 0 ≤ (if n.Prime then 0 else residueClass a n) / n := by + have := residueClass_nonneg a n + positivity + have hleF₀ (n : ℕ) : (if n.Prime then 0 else residueClass a n) / n ≤ F₀ n := by + refine div_le_div_of_nonneg_right ?_ n.cast_nonneg + split_ifs; exacts [le_rfl, residueClass_le a n] + refine Summable.of_nonneg_of_le h₀ hleF₀ ?_ + have hF₀ (p : Nat.Primes) : F₀ p.val = 0 := by + simp only [p.prop, ↓reduceIte, zero_div, F₀] + refine (summable_subtype_iff_indicator (s := {n | IsPrimePow n}).mp ?_).congr + fun n ↦ Set.indicator_apply_eq_self.mpr fun (hn : ¬ IsPrimePow n) ↦ ?_ + swap + · simp +contextual only [div_eq_zero_iff, ite_eq_left_iff, vonMangoldt_eq_zero_iff, hn, + not_false_eq_true, implies_true, Nat.cast_eq_zero, true_or, F₀] + have hFF' : + F₀ ∘ Subtype.val (p := fun n ↦ n ∈ {n | IsPrimePow n}) = F' ∘ ⇑prodNatEquiv.symm := by + refine (Equiv.eq_comp_symm prodNatEquiv (F₀ ∘ Subtype.val) F').mpr ?_ + ext1 n + simp only [Function.comp_apply, F'] + congr + rw [hFF'] + refine (Nat.Primes.prodNatEquiv.symm.summable_iff (f := F')).mpr ?_ + have hF'₀ (p : Nat.Primes) : F' (p, 0) = 0 := by simp only [zero_add, pow_one, hF₀, F'] + have hF'₁ : F'' = F' ∘ (Prod.map _root_.id (· + 1)) := by + ext1 + simp only [Function.comp_apply, Prod.map_fst, id_eq, Prod.map_snd, F'', F'] + refine (Function.Injective.summable_iff ?_ fun u hu ↦ ?_).mp <| hF'₁ ▸ summable_F'' + · exact Function.Injective.prodMap (fun ⦃a₁ a₂⦄ a ↦ a) <| add_left_injective 1 + · simp only [Set.range_prod_map, Set.range_id, Set.mem_prod, Set.mem_univ, Set.mem_range, + Nat.exists_add_one_eq, true_and, not_lt, nonpos_iff_eq_zero] at hu + rw [← hF'₀ u.1, ← hu] + +variable [NeZero q] {a} + +/-- We can express `ArithmeticFunction.vonMangoldt.residueClass` as a linear combination +of twists of the von Mangoldt function by Dirichlet charaters. -/ +lemma residueClass_apply (ha : IsUnit a) (n : ℕ) : + residueClass a n = + (q.totient : ℂ)⁻¹ * ∑ χ : DirichletCharacter ℂ q, χ a⁻¹ * χ n * vonMangoldt n := by + rw [eq_inv_mul_iff_mul_eq₀ <| mod_cast (Nat.totient_pos.mpr q.pos_of_neZero).ne'] + simp +contextual only [residueClass, Set.indicator_apply, Set.mem_setOf_eq, apply_ite, + ofReal_zero, mul_zero, ← Finset.sum_mul, sum_char_inv_mul_char_eq ℂ ha n, eq_comm (a := a), + ite_mul, zero_mul, ↓reduceIte, ite_self] + +/-- We can express `ArithmeticFunction.vonMangoldt.residueClass` as a linear combination +of twists of the von Mangoldt function by Dirichlet charaters. -/ +lemma residueClass_eq (ha : IsUnit a) : + ↗(residueClass a) = (q.totient : ℂ)⁻¹ • + ∑ χ : DirichletCharacter ℂ q, χ a⁻¹ • (fun n : ℕ ↦ χ n * vonMangoldt n) := by + ext1 n + simpa only [Pi.smul_apply, Finset.sum_apply, smul_eq_mul, ← mul_assoc] + using residueClass_apply ha n + +/-- The L-series of the von Mangoldt function restricted to the residue class `a` mod `q` +with `a` invertible in `ZMod q` is a linear combination of logarithmic derivatives of +L-functions of the Dirichlet characters mod `q` (on `re s > 1`). -/ +lemma LSeries_residueClass_eq (ha : IsUnit a) {s : ℂ} (hs : 1 < s.re) : + LSeries ↗(residueClass a) s = + -(q.totient : ℂ)⁻¹ * ∑ χ : DirichletCharacter ℂ q, χ a⁻¹ * + (deriv (LFunction χ) s / LFunction χ s) := by + simp only [deriv_LFunction_eq_deriv_LSeries _ hs, LFunction_eq_LSeries _ hs, neg_mul, ← mul_neg, + ← Finset.sum_neg_distrib, ← neg_div, ← LSeries_twist_vonMangoldt_eq _ hs] + rw [eq_inv_mul_iff_mul_eq₀ <| mod_cast (Nat.totient_pos.mpr q.pos_of_neZero).ne'] + simp_rw [← LSeries_smul, + ← LSeries_sum <| fun χ _ ↦ (LSeriesSummable_twist_vonMangoldt χ hs).smul _] + refine LSeries_congr s fun {n} _ ↦ ?_ + simp only [Pi.smul_apply, residueClass_apply ha, smul_eq_mul, ← mul_assoc, + mul_inv_cancel_of_invertible, one_mul, Finset.sum_apply, Pi.mul_apply] + +variable (a) + +open Classical in +/-- The auxiliary function used, e.g., with the Wiener-Ikehara Theorem to prove +Dirichlet's Theorem. On `re s > 1`, it agrees with the L-series of the von Mangoldt +function restricted to the residue class `a : ZMod q` minus the principal part +`(q.totient)⁻¹/(s-1)` of the pole at `s = 1`; +see `ArithmeticFunction.vonMangoldt.eqOn_LfunctionResidueClassAux`. -/ +noncomputable +abbrev LfunctionResidueClassAux (s : ℂ) : ℂ := + (q.totient : ℂ)⁻¹ * (-deriv (LFunctionTrivChar₁ q) s / LFunctionTrivChar₁ q s - + ∑ χ ∈ ({1}ᶜ : Finset (DirichletCharacter ℂ q)), χ a⁻¹ * deriv (LFunction χ) s / LFunction χ s) + +/-- The auxiliary function is continuous away from the zeros of the L-functions of the Dirichlet +characters mod `q` (including at `s = 1`). -/ +lemma continuousOn_LfunctionResidueClassAux' : + ContinuousOn (LfunctionResidueClassAux a) + {s | s = 1 ∨ ∀ χ : DirichletCharacter ℂ q, LFunction χ s ≠ 0} := by + rw [show LfunctionResidueClassAux a = fun s ↦ _ from rfl] + simp only [LfunctionResidueClassAux, sub_eq_add_neg] + refine continuousOn_const.mul <| ContinuousOn.add ?_ ?_ + · refine (continuousOn_neg_logDeriv_LFunctionTrivChar₁ q).mono fun s hs ↦ ?_ + have := LFunction_ne_zero_of_one_le_re (1 : DirichletCharacter ℂ q) (s := s) + simp only [ne_eq, Set.mem_setOf_eq] at hs + tauto + · simp only [← Finset.sum_neg_distrib, mul_div_assoc, ← mul_neg, ← neg_div] + refine continuousOn_finset_sum _ fun χ hχ ↦ continuousOn_const.mul ?_ + replace hχ : χ ≠ 1 := by simpa only [ne_eq, Finset.mem_compl, Finset.mem_singleton] using hχ + refine (continuousOn_neg_logDeriv_LFunction_of_nontriv hχ).mono fun s hs ↦ ?_ + simp only [ne_eq, Set.mem_setOf_eq] at hs + rcases hs with rfl | hs + · simp only [ne_eq, Set.mem_setOf_eq, one_re, le_refl, + LFunction_ne_zero_of_one_le_re χ (.inl hχ), not_false_eq_true] + · exact hs χ + +/-- The L-series of the von Mangoldt function restricted to the prime residue class `a` mod `q` +is continuous on `re s ≥ 1` except for a simple pole at `s = 1` with residue `(q.totient)⁻¹`. +The statement as given here in terms of `ArithmeticFunction.vonMangoldt.LfunctionResidueClassAux` +is equivalent. -/ +lemma continuousOn_LfunctionResidueClassAux : + ContinuousOn (LfunctionResidueClassAux a) {s | 1 ≤ s.re} := by + refine (continuousOn_LfunctionResidueClassAux' a).mono fun s hs ↦ ?_ + rcases eq_or_ne s 1 with rfl | hs₁ + · simp only [ne_eq, Set.mem_setOf_eq, true_or] + · simp only [ne_eq, Set.mem_setOf_eq, hs₁, false_or] + exact fun χ ↦ LFunction_ne_zero_of_one_le_re χ (.inr hs₁) <| Set.mem_setOf.mp hs + +variable {a} + +open scoped LSeries.notation + +/-- The auxiliary function agrees on `re s > 1` with the L-series of the von Mangoldt function +restricted to the residue class `a : ZMod q` minus the principal part `(q.totient)⁻¹/(s-1)` +of its pole at `s = 1`. -/ +lemma eqOn_LfunctionResidueClassAux (ha : IsUnit a) : + Set.EqOn (LfunctionResidueClassAux a) + (fun s ↦ L ↗(residueClass a) s - (q.totient : ℂ)⁻¹ / (s - 1)) + {s | 1 < s.re} := by + intro s hs + replace hs := Set.mem_setOf.mp hs + simp only [LSeries_residueClass_eq ha hs, LfunctionResidueClassAux] + rw [neg_div, ← neg_add', mul_neg, ← neg_mul, div_eq_mul_one_div (q.totient : ℂ)⁻¹, + sub_eq_add_neg, ← neg_mul, ← mul_add] + congrm (_ * ?_) + -- this should be easier, but `IsUnit.inv ha` does not work here + have ha' : IsUnit a⁻¹ := isUnit_of_dvd_one ⟨a, (ZMod.inv_mul_of_unit a ha).symm⟩ + classical -- for `Fintype.sum_eq_add_sum_compl` + rw [Fintype.sum_eq_add_sum_compl 1, MulChar.one_apply ha', one_mul, add_right_comm] + simp only [mul_div_assoc] + congrm (?_ + _) + have hs₁ : s ≠ 1 := fun h ↦ ((h ▸ hs).trans_eq one_re).false + rw [deriv_LFunctionTrivChar₁_apply_of_ne_one _ hs₁, LFunctionTrivChar₁, + Function.update_noteq hs₁, LFunctionTrivChar, add_div, + mul_div_mul_left _ _ (sub_ne_zero_of_ne hs₁)] + conv_lhs => enter [2, 1]; rw [← mul_one (LFunction ..)] + rw [mul_comm _ 1, mul_div_mul_right _ _ <| LFunction_ne_zero_of_one_le_re 1 (.inr hs₁) hs.le] + +/-- The auxiliary function takes real values for real arguments `x > 1`. -/ +lemma LfunctionResidueClassAux_real (ha : IsUnit a) {x : ℝ} (hx : 1 < x) : + LfunctionResidueClassAux a x = (LfunctionResidueClassAux a x).re := by + rw [eqOn_LfunctionResidueClassAux ha hx] + simp only [sub_re, ofReal_sub] + congr 1 + · rw [LSeries, re_tsum <| LSeriesSummable_of_abscissaOfAbsConv_lt_re <| + (abscissaOfAbsConv_residueClass_le_one a).trans_lt <| by norm_cast] + push_cast + refine tsum_congr fun n ↦ ?_ + rcases eq_or_ne n 0 with rfl | hn + · simp only [term_zero, zero_re, ofReal_zero] + · simp only [term_of_ne_zero hn, ← ofReal_natCast n, ← ofReal_cpow n.cast_nonneg, ← ofReal_div, + ofReal_re] + · rw [show (q.totient : ℂ) = (q.totient : ℝ) from rfl, ← ofReal_one, ← ofReal_sub, ← ofReal_inv, + ← ofReal_div, ofReal_re] + +variable {q : ℕ} [NeZero q] {a : ZMod q} + +/-- As `x` approaches `1` from the right along the real axis, the L-series of +`ArithmeticFunction.vonMangoldt.residueClass` is bounded below by `(q.totient)⁻¹/(x-1) - C`. -/ +lemma LSeries_residueClass_lower_bound (ha : IsUnit a) : + ∃ C : ℝ, ∀ {x : ℝ} (_ : x ∈ Set.Ioc 1 2), + (q.totient : ℝ)⁻¹ / (x - 1) - C ≤ ∑' n, residueClass a n / (n : ℝ) ^ x := by + have H {x : ℝ} (hx : 1 < x) : + ∑' n, residueClass a n / (n : ℝ) ^ x = + (LfunctionResidueClassAux a x).re + (q.totient : ℝ)⁻¹ / (x - 1) := by + refine ofReal_injective ?_ + simp only [ofReal_tsum, ofReal_div, ofReal_cpow (Nat.cast_nonneg _), ofReal_natCast, + ofReal_add, ofReal_inv, ofReal_sub, ofReal_one] + simp_rw [← LfunctionResidueClassAux_real ha hx, + eqOn_LfunctionResidueClassAux ha <| Set.mem_setOf.mpr (ofReal_re x ▸ hx), sub_add_cancel, + LSeries, term] + refine tsum_congr fun n ↦ ?_ + split_ifs with hn + · simp only [hn, residueClass_apply_zero, ofReal_zero, zero_div] + · rfl + have : ContinuousOn (fun x : ℝ ↦ (LfunctionResidueClassAux a x).re) (Set.Icc 1 2) := + continuous_re.continuousOn.comp (t := Set.univ) (continuousOn_LfunctionResidueClassAux a) + (fun ⦃x⦄ a ↦ trivial) |>.comp continuous_ofReal.continuousOn fun x hx ↦ by + simpa only [Set.mem_setOf_eq, ofReal_re] using hx.1 + obtain ⟨C, hC⟩ := bddBelow_def.mp <| IsCompact.bddBelow_image isCompact_Icc this + replace hC {x : ℝ} (hx : x ∈ Set.Icc 1 2) : C ≤ (LfunctionResidueClassAux a x).re := + hC (LfunctionResidueClassAux a x).re <| + Set.mem_image_of_mem (fun x : ℝ ↦ (LfunctionResidueClassAux a x).re) hx + refine ⟨-C, fun {x} hx ↦ ?_⟩ + rw [H hx.1, add_comm, sub_neg_eq_add, add_le_add_iff_left] + exact hC <| Set.mem_Icc_of_Ioc hx + +open vonMangoldt Filter Topology in +/-- The function `n ↦ Λ n / n` restricted to primes in an invertible residue class +is not summable. This then implies that there must be infinitely many such primes. -/ +lemma not_summable_residueClass_prime_div (ha : IsUnit a) : + ¬ Summable fun n : ℕ ↦ (if n.Prime then residueClass a n else 0) / n := by + intro H + have key : Summable fun n : ℕ ↦ residueClass a n / n := by + convert (summable_residueClass_non_primes_div a).add H using 2 with n + simp only [← add_div, ite_add_ite, zero_add, add_zero, ite_self] + let C := ∑' n, residueClass a n / n + have H₁ {x : ℝ} (hx : 1 < x) : ∑' n, residueClass a n / (n : ℝ) ^ x ≤ C := by + refine tsum_le_tsum (fun n ↦ ?_) ?_ key + · rcases n.eq_zero_or_pos with rfl | hn + · simp only [Nat.cast_zero, Real.zero_rpow (zero_lt_one.trans hx).ne', div_zero, le_refl] + · refine div_le_div_of_nonneg_left (residueClass_nonneg a _) (mod_cast hn) ?_ + conv_lhs => rw [← Real.rpow_one n] + exact Real.rpow_le_rpow_of_exponent_le (by norm_cast) hx.le + · exact summable_real_of_abscissaOfAbsConv_lt <| + (abscissaOfAbsConv_residueClass_le_one a).trans_lt <| mod_cast hx + obtain ⟨C', hC'⟩ := LSeries_residueClass_lower_bound ha + have H₁ {x} (hx : x ∈ Set.Ioc 1 2) : (q.totient : ℝ)⁻¹ ≤ (C + C') * (x - 1) := + (div_le_iff₀ <| sub_pos.mpr hx.1).mp <| + sub_le_iff_le_add.mp <| (hC' hx).trans (H₁ hx.1) + have hq : 0 < (q.totient : ℝ)⁻¹ := inv_pos.mpr (mod_cast q.totient.pos_of_neZero) + rcases le_or_lt (C + C') 0 with h₀ | h₀ + · have := hq.trans_le (H₁ (Set.right_mem_Ioc.mpr one_lt_two)) + rw [show (2 : ℝ) - 1 = 1 by norm_num, mul_one] at this + exact (this.trans_le h₀).false + · obtain ⟨ξ, hξ₁, hξ₂⟩ : ∃ ξ ∈ Set.Ioc 1 2, (C + C') * (ξ - 1) < (q.totient : ℝ)⁻¹ := by + refine ⟨min (1 + (q.totient : ℝ)⁻¹ / (C + C') / 2) 2, ⟨?_, min_le_right ..⟩, ?_⟩ + · simpa only [lt_inf_iff, lt_add_iff_pos_right, Nat.ofNat_pos, div_pos_iff_of_pos_right, + Nat.one_lt_ofNat, and_true] using div_pos hq h₀ + · rw [← min_sub_sub_right, add_sub_cancel_left, ← lt_div_iff₀' h₀] + exact (min_le_left ..).trans_lt <| div_lt_self (div_pos hq h₀) one_lt_two + exact ((H₁ hξ₁).trans_lt hξ₂).false + +end ArithmeticFunction.vonMangoldt + +end arith_prog + +/-! +### Dirichlet's Theorem +-/ + +section DirichletsTheorem + +namespace Nat + +open ArithmeticFunction vonMangoldt + +variable {q : ℕ} [NeZero q] {a : ZMod q} + +/-- **Dirichlet's Theorem** on primes in arithmetic progression: if `q` is a positive +integer and `a : ZMod q` is a unit, then there are infintely many prime numbers `p` +such that `(p : ZMod q) = a`. -/ +theorem setOf_prime_and_eq_mod_infinite (ha : IsUnit a) : + {p : ℕ | p.Prime ∧ (p : ZMod q) = a}.Infinite := by + by_contra H + rw [Set.not_infinite] at H + exact not_summable_residueClass_prime_div ha <| + summable_of_finite_support <| support_residueClass_prime_div a ▸ H + +/-- **Dirichlet's Theorem** on primes in arithmetic progression: if `q` is a positive +integer and `a : ZMod q` is a unit, then there are infintely many prime numbers `p` +such that `(p : ZMod q) = a`. -/ +theorem forall_exists_prime_gt_and_eq_mod (ha : IsUnit a) (n : ℕ) : + ∃ p > n, p.Prime ∧ (p : ZMod q) = a := by + obtain ⟨p, hp₁, hp₂⟩ := Set.infinite_iff_exists_gt.mp (setOf_prime_and_eq_mod_infinite ha) n + exact ⟨p, hp₂.gt, Set.mem_setOf.mp hp₁⟩ + +end Nat + +end DirichletsTheorem diff --git a/Mathlib/NumberTheory/Modular.lean b/Mathlib/NumberTheory/Modular.lean index f4c849d0063d4..59b083317b35b 100644 --- a/Mathlib/NumberTheory/Modular.lean +++ b/Mathlib/NumberTheory/Modular.lean @@ -180,9 +180,6 @@ def lcRow0Extend {cd : Fin 2 → ℤ} (hcd : IsCoprime (cd 0) (cd 1)) : rw [neg_sq] exact hcd.sq_add_sq_ne_zero, LinearEquiv.refl ℝ (Fin 2 → ℝ)] --- `simpNF` times out, but only in CI where all of `Mathlib` is imported -attribute [nolint simpNF] lcRow0Extend_apply lcRow0Extend_symm_apply - /-- The map `lcRow0` is proper, that is, preimages of cocompact sets are finite in `[[* , *], [c, d]]`. -/ theorem tendsto_lcRow0 {cd : Fin 2 → ℤ} (hcd : IsCoprime (cd 0) (cd 1)) : @@ -210,17 +207,19 @@ theorem tendsto_lcRow0 {cd : Fin 2 → ℤ} (hcd : IsCoprime (cd 0) (cd 1)) : ext ⟨g, rfl⟩ i j : 3 fin_cases i <;> [fin_cases j; skip] -- the following are proved by `simp`, but it is replaced by `simp only` to avoid timeouts. - · simp only [mB, mulVec, dotProduct, Fin.sum_univ_two, coe_matrix_coe, - Int.coe_castRingHom, lcRow0_apply, Function.comp_apply, cons_val_zero, lcRow0Extend_apply, + · simp only [Fin.isValue, Int.cast_one, map_apply_coe, RingHom.mapMatrix_apply, + Int.coe_castRingHom, lcRow0_apply, map_apply, Fin.zero_eta, id_eq, Function.comp_apply, + of_apply, cons_val', cons_val_zero, empty_val', cons_val_fin_one, lcRow0Extend_apply, LinearMap.GeneralLinearGroup.coeFn_generalLinearEquiv, GeneralLinearGroup.coe_toLinear, - val_planeConformalMatrix, neg_neg, mulVecLin_apply, cons_val_one, head_cons, of_apply, - Fin.mk_zero, Fin.mk_one] + val_planeConformalMatrix, neg_neg, mulVecLin_apply, mulVec, dotProduct, Fin.sum_univ_two, + cons_val_one, head_cons, mB, f₁] · convert congr_arg (fun n : ℤ => (-n : ℝ)) g.det_coe.symm using 1 - simp only [f₁, mulVec, dotProduct, Fin.sum_univ_two, Matrix.det_fin_two, Function.comp_apply, - Subtype.coe_mk, lcRow0Extend_apply, cons_val_zero, + simp only [Fin.zero_eta, id_eq, Function.comp_apply, lcRow0Extend_apply, cons_val_zero, LinearMap.GeneralLinearGroup.coeFn_generalLinearEquiv, GeneralLinearGroup.coe_toLinear, - val_planeConformalMatrix, mulVecLin_apply, cons_val_one, head_cons, map_apply, neg_mul, - Int.cast_sub, Int.cast_mul, neg_sub, of_apply, Fin.mk_zero, Fin.mk_one] + mulVecLin_apply, mulVec, dotProduct, det_fin_two, f₁] + simp only [Fin.isValue, Fin.mk_one, val_planeConformalMatrix, neg_neg, of_apply, cons_val', + empty_val', cons_val_fin_one, cons_val_one, head_fin_const, map_apply, Fin.sum_univ_two, + cons_val_zero, neg_mul, head_cons, Int.cast_sub, Int.cast_mul, neg_sub] ring · rfl @@ -458,11 +457,8 @@ theorem abs_c_le_one (hz : z ∈ 𝒟ᵒ) (hg : g • z ∈ 𝒟ᵒ) : |g 1 0| specialize this hc linarith intro hc - replace hc : 0 < c ^ 4 := by - change 0 < c ^ (2 * 2); rw [pow_mul]; apply sq_pos_of_pos (sq_pos_of_ne_zero hc) - have h₁ := mul_lt_mul_of_pos_right - (mul_lt_mul'' (three_lt_four_mul_im_sq_of_mem_fdo hg) (three_lt_four_mul_im_sq_of_mem_fdo hz) - (by norm_num) (by norm_num)) hc + have h₁ : 3 * 3 * c ^ 4 < 4 * (g • z).im ^ 2 * (4 * z.im ^ 2) * c ^ 4 := by + gcongr <;> apply three_lt_four_mul_im_sq_of_mem_fdo <;> assumption have h₂ : (c * z.im) ^ 4 / normSq (denom (↑g) z) ^ 2 ≤ 1 := div_le_one_of_le₀ (pow_four_le_pow_two_of_pow_two_le (z.c_mul_im_sq_le_normSq_denom g)) diff --git a/Mathlib/NumberTheory/ModularForms/SlashActions.lean b/Mathlib/NumberTheory/ModularForms/SlashActions.lean index bc52891b5dffc..ef9d1a0bcb146 100644 --- a/Mathlib/NumberTheory/ModularForms/SlashActions.lean +++ b/Mathlib/NumberTheory/ModularForms/SlashActions.lean @@ -143,10 +143,14 @@ theorem is_invariant_const (A : SL(2, ℤ)) (x : ℂ) : zpow_neg, zpow_one, inv_one, mul_one, neg_zero, zpow_zero] /-- The constant function 1 is invariant under any element of `SL(2, ℤ)`. -/ --- @[simp] -- Porting note: simpNF says LHS simplifies to something more complex theorem is_invariant_one (A : SL(2, ℤ)) : (1 : ℍ → ℂ) ∣[(0 : ℤ)] A = (1 : ℍ → ℂ) := is_invariant_const _ _ +/-- Variant of `is_invariant_one` with the left hand side in simp normal form. -/ +@[simp] +theorem is_invariant_one' (A : SL(2, ℤ)) : (1 : ℍ → ℂ) ∣[(0 : ℤ)] (A : GL(2, ℝ)⁺) = 1 := by + simpa using is_invariant_one A + /-- A function `f : ℍ → ℂ` is slash-invariant, of weight `k ∈ ℤ` and level `Γ`, if for every matrix `γ ∈ Γ` we have `f(γ • z)= (c*z+d)^k f(z)` where `γ= ![![a, b], ![c, d]]`, and it acts on `ℍ` via Möbius transformations. -/ diff --git a/Mathlib/NumberTheory/MulChar/Basic.lean b/Mathlib/NumberTheory/MulChar/Basic.lean index 2df970973c59d..7ddd95b920b4e 100644 --- a/Mathlib/NumberTheory/MulChar/Basic.lean +++ b/Mathlib/NumberTheory/MulChar/Basic.lean @@ -391,13 +391,13 @@ lemma ne_one_iff {χ : MulChar R R'} : χ ≠ 1 ↔ ∃ a : Rˣ, χ a ≠ 1 := b simp only [Ne, eq_one_iff, not_forall] /-- A multiplicative character is *nontrivial* if it takes a value `≠ 1` on a unit. -/ -@[deprecated (since := "2024-06-16")] +@[deprecated "No deprecation message was provided." (since := "2024-06-16")] def IsNontrivial (χ : MulChar R R') : Prop := ∃ a : Rˣ, χ a ≠ 1 set_option linter.deprecated false in /-- A multiplicative character is nontrivial iff it is not the trivial character. -/ -@[deprecated (since := "2024-06-16")] +@[deprecated "No deprecation message was provided." (since := "2024-06-16")] theorem isNontrivial_iff (χ : MulChar R R') : χ.IsNontrivial ↔ χ ≠ 1 := by simp only [IsNontrivial, Ne, MulChar.ext_iff, not_forall, one_apply_coe] @@ -573,7 +573,7 @@ theorem sum_eq_zero_of_ne_one [IsDomain R'] {χ : MulChar R R'} (hχ : χ ≠ 1) simpa only [Finset.mul_sum, ← map_mul] using b.mulLeft_bijective.sum_comp _ set_option linter.deprecated false in -@[deprecated (since := "2024-06-16")] +@[deprecated "No deprecation message was provided." (since := "2024-06-16")] lemma IsNontrivial.sum_eq_zero [IsDomain R'] {χ : MulChar R R'} (hχ : χ.IsNontrivial) : ∑ a, χ a = 0 := sum_eq_zero_of_ne_one ((isNontrivial_iff _).mp hχ) diff --git a/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/Basic.lean b/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/Basic.lean index 3cfe928f41764..3b10a1368dea7 100644 --- a/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/Basic.lean +++ b/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/Basic.lean @@ -367,8 +367,8 @@ theorem forall_normAtPlace_eq_zero_iff {x : mixedSpace K} : (∀ w, normAtPlace w x = 0) ↔ x = 0 := by refine ⟨fun h ↦ ?_, fun h ↦ ?_⟩ · ext w - · exact norm_eq_zero'.mp (normAtPlace_apply_isReal w.prop _ ▸ h w.1) - · exact norm_eq_zero'.mp (normAtPlace_apply_isComplex w.prop _ ▸ h w.1) + · exact norm_eq_zero.mp (normAtPlace_apply_isReal w.prop _ ▸ h w.1) + · exact norm_eq_zero.mp (normAtPlace_apply_isComplex w.prop _ ▸ h w.1) · simp_rw [h, map_zero, implies_true] @[deprecated (since := "2024-09-13")] alias normAtPlace_eq_zero := forall_normAtPlace_eq_zero_iff @@ -585,17 +585,17 @@ theorem stdBasis_repr_eq_matrixToStdBasis_mul (x : (K →+* ℂ) → ℂ) | inr c => rcases c with ⟨w, j⟩ fin_cases j - · simp_rw [Fin.mk_zero, stdBasis_apply_ofIsComplex_fst, fromBlocks_apply₂₁, - fromBlocks_apply₂₂, Matrix.zero_apply, submatrix_apply, - blockDiagonal_apply, Prod.swap_prod_mk, ite_mul, zero_mul, sum_const_zero, zero_add, - sum_add_distrib, sum_ite_eq, mem_univ, ite_true, of_apply, cons_val', cons_val_zero, - cons_val_one, head_cons, ← hx (embedding w), re_eq_add_conj] + · simp only [Fin.zero_eta, Fin.isValue, id_eq, stdBasis_apply_ofIsComplex_fst, re_eq_add_conj, + mul_neg, fromBlocks_apply₂₁, zero_apply, zero_mul, sum_const_zero, fromBlocks_apply₂₂, + submatrix_apply, Prod.swap_prod_mk, blockDiagonal_apply, of_apply, cons_val', cons_val_zero, + empty_val', cons_val_fin_one, ite_mul, cons_val_one, head_cons, sum_add_distrib, sum_ite_eq, + mem_univ, ↓reduceIte, ← hx (embedding w), zero_add] field_simp - · simp_rw [Fin.mk_one, stdBasis_apply_ofIsComplex_snd, fromBlocks_apply₂₁, - fromBlocks_apply₂₂, Matrix.zero_apply, submatrix_apply, blockDiagonal_apply, - Prod.swap_prod_mk, ite_mul, zero_mul, sum_const_zero, zero_add, sum_add_distrib, sum_ite_eq, - mem_univ, ite_true, of_apply, cons_val', cons_val_zero, cons_val_one, head_cons, - ← hx (embedding w), im_eq_sub_conj] + · simp only [Fin.mk_one, Fin.isValue, id_eq, stdBasis_apply_ofIsComplex_snd, im_eq_sub_conj, + mul_neg, fromBlocks_apply₂₁, zero_apply, zero_mul, sum_const_zero, fromBlocks_apply₂₂, + submatrix_apply, Prod.swap_prod_mk, blockDiagonal_apply, of_apply, cons_val', cons_val_zero, + empty_val', cons_val_fin_one, cons_val_one, head_fin_const, ite_mul, neg_mul, head_cons, + sum_add_distrib, sum_ite_eq, mem_univ, ↓reduceIte, ← hx (embedding w), zero_add] ring_nf; field_simp end stdBasis diff --git a/Mathlib/NumberTheory/NumberField/Units/DirichletTheorem.lean b/Mathlib/NumberTheory/NumberField/Units/DirichletTheorem.lean index 31c16252e0c0d..4fbfe52301fe9 100644 --- a/Mathlib/NumberTheory/NumberField/Units/DirichletTheorem.lean +++ b/Mathlib/NumberTheory/NumberField/Units/DirichletTheorem.lean @@ -75,7 +75,7 @@ variable (K) /-- The logarithmic embedding of the units (seen as an `Additive` group). -/ def _root_.NumberField.Units.logEmbedding : Additive ((𝓞 K)ˣ) →+ ({w : InfinitePlace K // w ≠ w₀} → ℝ) := -{ toFun := fun x w => mult w.val * Real.log (w.val ↑(Additive.toMul x)) +{ toFun := fun x w => mult w.val * Real.log (w.val ↑x.toMul) map_zero' := by simp; rfl map_add' := fun _ _ => by simp [Real.log_mul, mul_add]; rfl } @@ -465,7 +465,7 @@ def basisUnitLattice : Basis (Fin (rank K)) ℤ (unitLattice K) := units in `basisModTorsion`. -/ def fundSystem : Fin (rank K) → (𝓞 K)ˣ := -- `:)` prevents the `⧸` decaying to a quotient by `leftRel` when we unfold this later - fun i => Quotient.out (Additive.toMul (basisModTorsion K i):) + fun i => Quotient.out ((basisModTorsion K i).toMul:) theorem fundSystem_mk (i : Fin (rank K)) : Additive.ofMul (QuotientGroup.mk (fundSystem K i)) = (basisModTorsion K i) := by diff --git a/Mathlib/NumberTheory/Padics/MahlerBasis.lean b/Mathlib/NumberTheory/Padics/MahlerBasis.lean index 543eaf0533d7d..a6be858db5335 100644 --- a/Mathlib/NumberTheory/Padics/MahlerBasis.lean +++ b/Mathlib/NumberTheory/Padics/MahlerBasis.lean @@ -3,6 +3,7 @@ Copyright (c) 2024 David Loeffler. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Giulio Caflisch, David Loeffler -/ +import Mathlib.Algebra.Group.ForwardDiff import Mathlib.Analysis.Normed.Group.Ultra import Mathlib.NumberTheory.Padics.ProperSpace import Mathlib.RingTheory.Binomial @@ -15,15 +16,26 @@ import Mathlib.Topology.ContinuousMap.Compact In this file we introduce the Mahler basis function `mahler k`, for `k : ℕ`, which is the unique continuous map `ℤ_[p] → ℚ_[p]` agreeing with `n ↦ n.choose k` for `n ∈ ℕ`. -In future PR's, we will show that these functions give a Banach basis for the space of continuous -maps `ℤ_[p] → ℚ_[p]`. +We also show that for any continuous function `f` on `ℤ_[p]` (valued in a `p`-adic normed space), +the iterated forward differences `Δ^[n] f 0` tend to 0. For this, we follow the argument of +Bojanić [bojanic74]. + +In future PR's, we will show that the Mahler functions give a Banach basis for the space of +continuous maps `ℤ_[p] → ℚ_[p]`, with the basis coefficients of `f` given by the forward differences +`Δ^[n] f 0`. ## References +* [R. Bojanić, *A simple proof of Mahler's theorem on approximation of continuous functions of a + p-adic variable by polynomials*][bojanic74] * [P. Colmez, *Fonctions d'une variable p-adique*][colmez2010] + +## Tags + +Bojanic -/ -open Finset +open Finset fwdDiff IsUltrametricDist NNReal Filter Topology variable {p : ℕ} [hp : Fact p.Prime] @@ -95,3 +107,134 @@ The uniform norm of the `k`-th Mahler basis function is 1, for every `k`. · -- Show norm 1 is attained at `x = k` refine (le_of_eq ?_).trans ((mahler k).norm_coe_le_norm k) rw [mahler_natCast_eq, Nat.choose_self, Nat.cast_one, norm_one] + +section fwdDiff + +variable {M G : Type*} + +/-- Bound for iterated forward differences of a continuous function from a compact space to a +nonarchimedean seminormed group. -/ +lemma IsUltrametricDist.norm_fwdDiff_iter_apply_le [TopologicalSpace M] [CompactSpace M] + [AddCommMonoid M] [SeminormedAddCommGroup G] [IsUltrametricDist G] + (h : M) (f : C(M, G)) (m : M) (n : ℕ) : ‖Δ_[h]^[n] f m‖ ≤ ‖f‖ := by + -- A proof by induction on `n` would be possible but would involve some messing around to + -- define `Δ_[h]` as an operator on continuous maps (not just on bare functions). So instead we + -- use the formula for `Δ_[h]^[n] f` as a sum. + rw [fwdDiff_iter_eq_sum_shift] + refine norm_sum_le_of_forall_le_of_nonneg (norm_nonneg f) fun i _ ↦ ?_ + exact (norm_zsmul_le _ _).trans (f.norm_coe_le_norm _) + +/-- First step in Bojanić's proof of Mahler's theorem (equation (10) of [bojanic74]): rewrite +`Δ^[n + R] f 0` in a shape that makes it easy to bound `p`-adically. -/ +private lemma bojanic_mahler_step1 [AddCommMonoidWithOne M] [AddCommGroup G] (f : M → G) + (n : ℕ) {R : ℕ} (hR : 1 ≤ R) : + Δ_[1]^[n + R] f 0 = -∑ j ∈ range (R - 1), R.choose (j + 1) • Δ_[1]^[n + (j + 1)] f 0 + + ∑ k ∈ range (n + 1), ((-1 : ℤ) ^ (n - k) * n.choose k) • (f (k + R) - f k) := by + have aux : Δ_[1]^[n + R] f 0 = R.choose (R - 1 + 1) • Δ_[1]^[n + R] f 0 := by + rw [Nat.sub_add_cancel hR, Nat.choose_self, one_smul] + rw [neg_add_eq_sub, eq_sub_iff_add_eq, add_comm, aux, (by omega : n + R = (n + ((R - 1) + 1))), + ← sum_range_succ, Nat.sub_add_cancel hR, + ← sub_eq_iff_eq_add.mpr (sum_range_succ' (fun x ↦ R.choose x • Δ_[1]^[n + x] f 0) R), add_zero, + Nat.choose_zero_right, one_smul] + have : ∑ k ∈ Finset.range (R + 1), R.choose k • Δ_[1]^[n + k] f 0 = Δ_[1]^[n] f R := by + simpa only [← Function.iterate_add_apply, add_comm, nsmul_one, add_zero] using + (shift_eq_sum_fwdDiff_iter 1 (Δ_[1]^[n] f) R 0).symm + simp only [this, fwdDiff_iter_eq_sum_shift (1 : M) f n, mul_comm, nsmul_one, mul_smul, add_comm, + add_zero, smul_sub, sum_sub_distrib] + +end fwdDiff + +namespace PadicInt + +section norm_fwdDiff + +variable {p : ℕ} [hp : Fact p.Prime] {E : Type*} + [NormedAddCommGroup E] [NormedSpace ℚ_[p] E] [IsUltrametricDist E] + +/-- +Second step in Bojanić's proof of Mahler's theorem (equation (11) of [bojanic74]): show that values +`Δ_[1]^[n + p ^ t] f 0` for large enough `n` are bounded by the max of `(‖f‖ / p ^ s)` and `1 / p` +times a sup over values for smaller `n`. + +We use `nnnorm`s on the RHS since `Finset.sup` requires an order with a bottom element. +-/ +private lemma bojanic_mahler_step2 {f : C(ℤ_[p], E)} {s t : ℕ} + (hst : ∀ x y : ℤ_[p], ‖x - y‖ ≤ p ^ (-t : ℤ) → ‖f x - f y‖ ≤ ‖f‖ / p ^ s) (n : ℕ) : + ‖Δ_[1]^[n + p ^ t] f 0‖ ≤ max ↑((Finset.range (p ^ t - 1)).sup + fun j ↦ ‖Δ_[1]^[n + (j + 1)] f 0‖₊ / p) (‖f‖ / p ^ s) := by + -- Use previous lemma to rewrite in a convenient form. + rw [bojanic_mahler_step1 _ _ (one_le_pow₀ hp.out.one_le)] + -- Now use ultrametric property and bound each term separately. + refine (norm_add_le_max _ _).trans (max_le_max ?_ ?_) + · -- Bounding the sum over `range (p ^ t - 1)`: every term involves a value `Δ_[1]^[·] f 0` and + -- a binomial coefficient which is divisible by `p` + rw [norm_neg, ← coe_nnnorm, coe_le_coe] + refine nnnorm_sum_le_of_forall_le (fun i hi ↦ Finset.le_sup_of_le hi ?_) + rw [mem_range] at hi + rw [← Nat.cast_smul_eq_nsmul ℚ_[p], nnnorm_smul, div_eq_inv_mul] + refine mul_le_mul_of_nonneg_right ?_ (by simp only [zero_le]) + -- remains to show norm of binomial coeff is `≤ p⁻¹` + have : 0 < (p ^ t).choose (i + 1) := Nat.choose_pos (by omega) + rw [← zpow_neg_one, ← coe_le_coe, coe_nnnorm, Padic.norm_eq_pow_val (mod_cast this.ne'), + coe_zpow, NNReal.coe_natCast, (zpow_right_strictMono₀ (mod_cast hp.out.one_lt)).le_iff_le, + neg_le_neg_iff, Padic.valuation_natCast, Nat.one_le_cast] + exact one_le_padicValNat_of_dvd this <| hp.out.dvd_choose_pow (by omega) (by omega) + · -- Bounding the sum over `range (n + 1)`: every term is small by the choice of `t` + refine norm_sum_le_of_forall_le_of_nonempty nonempty_range_succ (fun i _ ↦ ?_) + calc ‖((-1 : ℤ) ^ (n - i) * n.choose i) • (f (i + ↑(p ^ t)) - f i)‖ + _ ≤ ‖f (i + ↑(p ^ t)) - f i‖ := by + rw [← Int.cast_smul_eq_zsmul ℚ_[p], norm_smul] + apply mul_le_of_le_one_left (norm_nonneg _) + simpa only [← coe_intCast] using norm_le_one _ + _ ≤ ‖f‖ / p ^ s := by + apply hst + rw [Nat.cast_pow, add_sub_cancel_left, norm_pow, norm_p, inv_pow, zpow_neg, zpow_natCast] + +/-- +Explicit bound for the decay rate of the Mahler coefficients of a continuous function on `ℤ_[p]`. +This will be used to prove Mahler's theorem. + -/ +lemma fwdDiff_iter_le_of_forall_le {f : C(ℤ_[p], E)} {s t : ℕ} + (hst : ∀ x y : ℤ_[p], ‖x - y‖ ≤ p ^ (-t : ℤ) → ‖f x - f y‖ ≤ ‖f‖ / p ^ s) (n : ℕ) : + ‖Δ_[1]^[n + s * p ^ t] f 0‖ ≤ ‖f‖ / p ^ s := by + -- We show the following more general statement by induction on `k`: + suffices ∀ {k : ℕ}, k ≤ s → ‖Δ_[1]^[n + k * p ^ t] f 0‖ ≤ ‖f‖ / p ^ k from this le_rfl + intro k hk + induction' k with k IH generalizing n + · -- base case just says that `‖Δ^[·] (⇑f) 0‖` is bounded by `‖f‖` + simpa only [zero_mul, pow_zero, add_zero, div_one] using norm_fwdDiff_iter_apply_le 1 f 0 n + · -- induction is the "step 2" lemma above + rw [add_mul, one_mul, ← add_assoc] + refine (bojanic_mahler_step2 hst (n + k * p ^ t)).trans (max_le ?_ ?_) + · rw [← coe_nnnorm, ← NNReal.coe_natCast, ← NNReal.coe_pow, ← NNReal.coe_div, NNReal.coe_le_coe] + refine Finset.sup_le fun j _ ↦ ?_ + rw [pow_succ, ← div_div, div_le_div_iff_of_pos_right (mod_cast hp.out.pos), add_right_comm] + exact_mod_cast IH (n + (j + 1)) (by omega) + · exact div_le_div_of_nonneg_left (norm_nonneg _) + (mod_cast pow_pos hp.out.pos _) (mod_cast pow_le_pow_right₀ hp.out.one_le hk) + +/-- Key lemma for Mahler's theorem: for `f` a continuous function on `ℤ_[p]`, the sequence +`n ↦ Δ^[n] f 0` tends to 0. See `PadicInt.fwdDiff_iter_le_of_forall_le` for an explicit +estimate of the decay rate. -/ +lemma fwdDiff_tendsto_zero (f : C(ℤ_[p], E)) : Tendsto (Δ_[1]^[·] f 0) atTop (𝓝 0) := by + -- first extract an `s` + refine NormedAddCommGroup.tendsto_nhds_zero.mpr (fun ε hε ↦ ?_) + have : Tendsto (fun s ↦ ‖f‖ / p ^ s) _ _ := tendsto_const_nhds.div_atTop + (tendsto_pow_atTop_atTop_of_one_lt (mod_cast hp.out.one_lt)) + obtain ⟨s, hs⟩ := (this.eventually_lt_const hε).exists + refine .mp ?_ (.of_forall fun x hx ↦ lt_of_le_of_lt hx hs) + -- use uniform continuity to find `t` + obtain ⟨t, ht⟩ : ∃ t : ℕ, ∀ x y, ‖x - y‖ ≤ p ^ (-t : ℤ) → ‖f x - f y‖ ≤ ‖f‖ / p ^ s := by + rcases eq_or_ne f 0 with rfl | hf + · -- silly case : f = 0 + simp + have : 0 < ‖f‖ / p ^ s := div_pos (norm_pos_iff.mpr hf) (mod_cast pow_pos hp.out.pos _) + obtain ⟨δ, hδpos, hδf⟩ := f.uniform_continuity _ this + obtain ⟨t, ht⟩ := PadicInt.exists_pow_neg_lt p hδpos + exact ⟨t, fun x y hxy ↦ by simpa only [dist_eq_norm_sub] using (hδf (hxy.trans_lt ht)).le⟩ + filter_upwards [eventually_ge_atTop (s * p ^ t)] with m hm + simpa only [Nat.sub_add_cancel hm] using fwdDiff_iter_le_of_forall_le ht (m - s * p ^ t) + +end norm_fwdDiff + +end PadicInt diff --git a/Mathlib/NumberTheory/Padics/PadicIntegers.lean b/Mathlib/NumberTheory/Padics/PadicIntegers.lean index 53e32586436a1..f9e0e0463f74b 100644 --- a/Mathlib/NumberTheory/Padics/PadicIntegers.lean +++ b/Mathlib/NumberTheory/Padics/PadicIntegers.lean @@ -153,8 +153,7 @@ def Coe.ringHom : ℤ_[p] →+* ℚ_[p] := (subring p).subtype @[simp, norm_cast] theorem coe_pow (x : ℤ_[p]) (n : ℕ) : (↑(x ^ n) : ℚ_[p]) = (↑x : ℚ_[p]) ^ n := rfl --- @[simp] -- Porting note: not in simpNF -theorem mk_coe (k : ℤ_[p]) : (⟨k, k.2⟩ : ℤ_[p]) = k := Subtype.coe_eta _ _ +theorem mk_coe (k : ℤ_[p]) : (⟨k, k.2⟩ : ℤ_[p]) = k := by simp /-- The inverse of a `p`-adic integer with norm equal to `1` is also a `p`-adic integer. Otherwise, the inverse is defined to be `0`. -/ @@ -165,10 +164,8 @@ instance : CharZero ℤ_[p] where 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 - suffices (z1 : ℚ_[p]) = z2 ↔ z1 = z2 from Iff.trans (by norm_cast) this - norm_cast +@[norm_cast] +theorem intCast_eq (z1 z2 : ℤ) : (z1 : ℤ_[p]) = z2 ↔ z1 = z2 := by simp @[deprecated (since := "2024-04-05")] alias coe_int_eq := intCast_eq @@ -280,8 +277,7 @@ theorem norm_eq_padic_norm {q : ℚ_[p]} (hq : ‖q‖ ≤ 1) : @norm ℤ_[p] _ @[simp] theorem norm_p : ‖(p : ℤ_[p])‖ = (p : ℝ)⁻¹ := padicNormE.norm_p --- @[simp] -- Porting note: not in simpNF -theorem norm_p_pow (n : ℕ) : ‖(p : ℤ_[p]) ^ n‖ = (p : ℝ) ^ (-n : ℤ) := padicNormE.norm_p_pow n +theorem norm_p_pow (n : ℕ) : ‖(p : ℤ_[p]) ^ n‖ = (p : ℝ) ^ (-n : ℤ) := by simp private def cauSeq_to_rat_cauSeq (f : CauSeq ℤ_[p] norm) : CauSeq ℚ_[p] fun a => ‖a‖ := ⟨fun n => f n, fun _ hε => by simpa [norm, norm_def] using f.cauchy hε⟩ @@ -413,10 +409,12 @@ theorem norm_lt_one_mul {z1 z2 : ℤ_[p]} (hz2 : ‖z2‖ < 1) : ‖z1 * z2‖ < ‖z1 * z2‖ = ‖z1‖ * ‖z2‖ := by simp _ < 1 := mul_lt_one_of_nonneg_of_lt_one_right (norm_le_one _) (norm_nonneg _) hz2 --- @[simp] -- Porting note: not in simpNF theorem mem_nonunits {z : ℤ_[p]} : z ∈ nonunits ℤ_[p] ↔ ‖z‖ < 1 := by rw [lt_iff_le_and_ne]; simp [norm_le_one z, nonunits, isUnit_iff] +theorem not_isUnit_iff {z : ℤ_[p]} : ¬IsUnit z ↔ ‖z‖ < 1 := by + simpa using mem_nonunits + /-- A `p`-adic number `u` with `‖u‖ = 1` is a unit of `ℤ_[p]`. -/ def mkUnits {u : ℚ_[p]} (h : ‖u‖ = 1) : ℤ_[p]ˣ := let z : ℤ_[p] := ⟨u, le_of_eq h⟩ diff --git a/Mathlib/NumberTheory/Padics/RingHoms.lean b/Mathlib/NumberTheory/Padics/RingHoms.lean index dab80d6e19bd6..b80610a74c52a 100644 --- a/Mathlib/NumberTheory/Padics/RingHoms.lean +++ b/Mathlib/NumberTheory/Padics/RingHoms.lean @@ -393,7 +393,7 @@ theorem ker_toZModPow (n : ℕ) : rw [zmod_congr_of_sub_mem_span n x _ 0 _ h, cast_zero] apply appr_spec --- @[simp] -- Porting note: not in simpNF +-- This is not a simp lemma; simp can't match the LHS. theorem zmod_cast_comp_toZModPow (m n : ℕ) (h : m ≤ n) : (ZMod.castHom (pow_dvd_pow p h) (ZMod (p ^ m))).comp (@toZModPow p _ n) = @toZModPow p _ m := by apply ZMod.ringHom_eq_of_ker_eq diff --git a/Mathlib/Order/BooleanAlgebra.lean b/Mathlib/Order/BooleanAlgebra.lean index a2918657eefb8..cbe13b58400f7 100644 --- a/Mathlib/Order/BooleanAlgebra.lean +++ b/Mathlib/Order/BooleanAlgebra.lean @@ -681,7 +681,7 @@ theorem codisjoint_himp_self_right : Codisjoint x (x ⇨ y) := @disjoint_sdiff_self_right αᵒᵈ _ _ _ theorem himp_le : x ⇨ y ≤ z ↔ y ≤ z ∧ Codisjoint x z := - (@le_sdiff αᵒᵈ _ _ _ _).trans <| and_congr_right' <| @Codisjoint_comm _ (_) _ _ _ + (@le_sdiff αᵒᵈ _ _ _ _).trans <| and_congr_right' <| @codisjoint_comm _ (_) _ _ _ @[simp] lemma himp_le_iff : x ⇨ y ≤ x ↔ x = ⊤ := ⟨fun h ↦ codisjoint_self.1 <| codisjoint_himp_self_right.mono_right h, fun h ↦ le_top.trans h.ge⟩ diff --git a/Mathlib/Order/Closure.lean b/Mathlib/Order/Closure.lean index b9c15b5db30cc..8fb5b69f0275c 100644 --- a/Mathlib/Order/Closure.lean +++ b/Mathlib/Order/Closure.lean @@ -387,7 +387,7 @@ variable [PartialOrder α] [PartialOrder β] {u : β → α} (l : LowerAdjoint u theorem mem_closed_iff_closure_le (x : α) : x ∈ l.closed ↔ u (l x) ≤ x := l.closureOperator.isClosed_iff_closure_le -@[simp, nolint simpNF] -- Porting note: lemma does prove itself, seems to be a linter error +@[simp] theorem closure_is_closed (x : α) : u (l x) ∈ l.closed := l.idempotent x diff --git a/Mathlib/Order/CompactlyGenerated/Basic.lean b/Mathlib/Order/CompactlyGenerated/Basic.lean index f3bc338a1d2ea..e802e01e3fb3e 100644 --- a/Mathlib/Order/CompactlyGenerated/Basic.lean +++ b/Mathlib/Order/CompactlyGenerated/Basic.lean @@ -273,13 +273,14 @@ alias ⟨_, IsSupClosedCompact.isSupFiniteCompact⟩ := isSupFiniteCompact_iff_i alias ⟨_, WellFoundedGT.isSupClosedCompact⟩ := isSupClosedCompact_iff_wellFoundedGT -variable {α} +end CompleteLattice + -theorem WellFoundedGT.finite_of_setIndependent [WellFoundedGT α] {s : Set α} - (hs : SetIndependent s) : s.Finite := by +theorem WellFoundedGT.finite_of_sSupIndep [WellFoundedGT α] {s : Set α} + (hs : sSupIndep s) : s.Finite := by classical refine Set.not_infinite.mp fun contra => ?_ - obtain ⟨t, ht₁, ht₂⟩ := WellFoundedGT.isSupFiniteCompact α s + obtain ⟨t, ht₁, ht₂⟩ := CompleteLattice.WellFoundedGT.isSupFiniteCompact α s replace contra : ∃ x : α, x ∈ s ∧ x ≠ ⊥ ∧ x ∉ t := by have : (s \ (insert ⊥ t : Finset α)).Infinite := contra.diff (Finset.finite_toSet _) obtain ⟨x, hx₁, hx₂⟩ := this.nonempty @@ -290,41 +291,59 @@ theorem WellFoundedGT.finite_of_setIndependent [WellFoundedGT α] {s : Set α} simpa [Disjoint, hx₂, ← t.sup_id_eq_sSup, ← ht₂] using this.eq_bot apply hx₁ rw [← hs, eq_comm, inf_eq_left] - exact le_sSup _ _ hx₀ + exact le_sSup hx₀ -theorem WellFoundedGT.finite_ne_bot_of_independent [WellFoundedGT α] - {ι : Type*} {t : ι → α} (ht : Independent t) : Set.Finite {i | t i ≠ ⊥} := by +@[deprecated (since := "2024-11-24")] +alias CompleteLattice.WellFoundedGT.finite_of_setIndependent := WellFoundedGT.finite_of_sSupIndep + +theorem WellFoundedGT.finite_ne_bot_of_iSupIndep [WellFoundedGT α] + {ι : Type*} {t : ι → α} (ht : iSupIndep t) : Set.Finite {i | t i ≠ ⊥} := by refine Finite.of_finite_image (Finite.subset ?_ (image_subset_range t _)) ht.injOn - exact WellFoundedGT.finite_of_setIndependent ht.setIndependent_range + exact WellFoundedGT.finite_of_sSupIndep ht.sSupIndep_range + +@[deprecated (since := "2024-11-24")] +alias CompleteLattice.WellFoundedGT.finite_ne_bot_of_independent := + WellFoundedGT.finite_ne_bot_of_iSupIndep -theorem WellFoundedGT.finite_of_independent [WellFoundedGT α] {ι : Type*} - {t : ι → α} (ht : Independent t) (h_ne_bot : ∀ i, t i ≠ ⊥) : Finite ι := - haveI := (WellFoundedGT.finite_of_setIndependent ht.setIndependent_range).to_subtype +theorem WellFoundedGT.finite_of_iSupIndep [WellFoundedGT α] {ι : Type*} + {t : ι → α} (ht : iSupIndep t) (h_ne_bot : ∀ i, t i ≠ ⊥) : Finite ι := + haveI := (WellFoundedGT.finite_of_sSupIndep ht.sSupIndep_range).to_subtype Finite.of_injective_finite_range (ht.injective h_ne_bot) -theorem WellFoundedLT.finite_of_setIndependent [WellFoundedLT α] {s : Set α} - (hs : SetIndependent s) : s.Finite := by +@[deprecated (since := "2024-11-24")] +alias CompleteLattice.WellFoundedGT.finite_of_independent := WellFoundedGT.finite_of_iSupIndep + +theorem WellFoundedLT.finite_of_sSupIndep [WellFoundedLT α] {s : Set α} + (hs : sSupIndep s) : s.Finite := by by_contra inf let e := (Infinite.diff inf <| finite_singleton ⊥).to_subtype.natEmbedding let a n := ⨆ i ≥ n, (e i).1 have sup_le n : (e n).1 ⊔ a (n + 1) ≤ a n := sup_le_iff.mpr ⟨le_iSup₂_of_le n le_rfl le_rfl, iSup₂_le fun i hi ↦ le_iSup₂_of_le i (n.le_succ.trans hi) le_rfl⟩ have lt n : a (n + 1) < a n := (Disjoint.right_lt_sup_of_left_ne_bot - ((hs (e n).2.1).mono_right <| iSup₂_le fun i hi ↦ le_sSup _ _ ?_) (e n).2.2).trans_le (sup_le n) + ((hs (e n).2.1).mono_right <| iSup₂_le fun i hi ↦ le_sSup ?_) (e n).2.2).trans_le (sup_le n) · exact (RelEmbedding.natGT a lt).not_wellFounded_of_decreasing_seq wellFounded_lt exact ⟨(e i).2.1, fun h ↦ n.lt_succ_self.not_le <| hi.trans_eq <| e.2 <| Subtype.val_injective h⟩ -theorem WellFoundedLT.finite_ne_bot_of_independent [WellFoundedLT α] - {ι : Type*} {t : ι → α} (ht : Independent t) : Set.Finite {i | t i ≠ ⊥} := by +@[deprecated (since := "2024-11-24")] +alias CompleteLattice.WellFoundedLT.finite_of_setIndependent := WellFoundedLT.finite_of_sSupIndep + +theorem WellFoundedLT.finite_ne_bot_of_iSupIndep [WellFoundedLT α] + {ι : Type*} {t : ι → α} (ht : iSupIndep t) : Set.Finite {i | t i ≠ ⊥} := by refine Finite.of_finite_image (Finite.subset ?_ (image_subset_range t _)) ht.injOn - exact WellFoundedLT.finite_of_setIndependent ht.setIndependent_range + exact WellFoundedLT.finite_of_sSupIndep ht.sSupIndep_range + +@[deprecated (since := "2024-11-24")] +alias CompleteLattice.WellFoundedLT.finite_ne_bot_of_independent := + WellFoundedLT.finite_ne_bot_of_iSupIndep -theorem WellFoundedLT.finite_of_independent [WellFoundedLT α] {ι : Type*} - {t : ι → α} (ht : Independent t) (h_ne_bot : ∀ i, t i ≠ ⊥) : Finite ι := - haveI := (WellFoundedLT.finite_of_setIndependent ht.setIndependent_range).to_subtype +theorem WellFoundedLT.finite_of_iSupIndep [WellFoundedLT α] {ι : Type*} + {t : ι → α} (ht : iSupIndep t) (h_ne_bot : ∀ i, t i ≠ ⊥) : Finite ι := + haveI := (WellFoundedLT.finite_of_sSupIndep ht.sSupIndep_range).to_subtype Finite.of_injective_finite_range (ht.injective h_ne_bot) -end CompleteLattice +@[deprecated (since := "2024-11-24")] +alias CompleteLattice.WellFoundedLT.finite_of_independent := WellFoundedLT.finite_of_iSupIndep /-- A complete lattice is said to be compactly generated if any element is the `sSup` of compact elements. -/ @@ -413,9 +432,9 @@ theorem inf_sSup_eq_iSup_inf_sup_finset : (iSup_le fun t => iSup_le fun h => inf_le_inf_left _ ((Finset.sup_id_eq_sSup t).symm ▸ sSup_le_sSup h)) -theorem CompleteLattice.setIndependent_iff_finite {s : Set α} : - CompleteLattice.SetIndependent s ↔ - ∀ t : Finset α, ↑t ⊆ s → CompleteLattice.SetIndependent (↑t : Set α) := +theorem sSupIndep_iff_finite {s : Set α} : + sSupIndep s ↔ + ∀ t : Finset α, ↑t ⊆ s → sSupIndep (↑t : Set α) := ⟨fun hs _ ht => hs.mono ht, fun h a ha => by rw [disjoint_iff, inf_sSup_eq_iSup_inf_sup_finset, iSup_eq_bot] intro t @@ -428,10 +447,13 @@ theorem CompleteLattice.setIndependent_iff_finite {s : Set α} : · rw [Finset.coe_insert, Set.insert_subset_iff] exact ⟨ha, Set.Subset.trans ht diff_subset⟩⟩ -lemma CompleteLattice.independent_iff_supIndep_of_injOn {ι : Type*} {f : ι → α} +@[deprecated (since := "2024-11-24")] +alias CompleteLattice.setIndependent_iff_finite := sSupIndep_iff_finite + +lemma iSupIndep_iff_supIndep_of_injOn {ι : Type*} {f : ι → α} (hf : InjOn f {i | f i ≠ ⊥}) : - CompleteLattice.Independent f ↔ ∀ (s : Finset ι), s.SupIndep f := by - refine ⟨fun h ↦ h.supIndep', fun h ↦ CompleteLattice.independent_def'.mpr fun i ↦ ?_⟩ + iSupIndep f ↔ ∀ (s : Finset ι), s.SupIndep f := by + refine ⟨fun h ↦ h.supIndep', fun h ↦ iSupIndep_def'.mpr fun i ↦ ?_⟩ simp_rw [disjoint_iff, inf_sSup_eq_iSup_inf_sup_finset, iSup_eq_bot, ← disjoint_iff] intro s hs classical @@ -451,11 +473,14 @@ lemma CompleteLattice.independent_iff_supIndep_of_injOn {ι : Type*} {f : ι → rw [Finset.supIndep_iff_disjoint_erase] at h exact h i (Finset.mem_insert_self i _) -theorem CompleteLattice.setIndependent_iUnion_of_directed {η : Type*} {s : η → Set α} - (hs : Directed (· ⊆ ·) s) (h : ∀ i, CompleteLattice.SetIndependent (s i)) : - CompleteLattice.SetIndependent (⋃ i, s i) := by +@[deprecated (since := "2024-11-24")] +alias CompleteLattice.independent_iff_supIndep_of_injOn := iSupIndep_iff_supIndep_of_injOn + +theorem sSupIndep_iUnion_of_directed {η : Type*} {s : η → Set α} + (hs : Directed (· ⊆ ·) s) (h : ∀ i, sSupIndep (s i)) : + sSupIndep (⋃ i, s i) := by by_cases hη : Nonempty η - · rw [CompleteLattice.setIndependent_iff_finite] + · rw [sSupIndep_iff_finite] intro t ht obtain ⟨I, fi, hI⟩ := Set.finite_subset_iUnion t.finite_toSet ht obtain ⟨i, hi⟩ := hs.finset_le fi.toFinset @@ -465,10 +490,16 @@ theorem CompleteLattice.setIndependent_iUnion_of_directed {η : Type*} {s : η exfalso exact hη ⟨i⟩ -theorem CompleteLattice.independent_sUnion_of_directed {s : Set (Set α)} (hs : DirectedOn (· ⊆ ·) s) - (h : ∀ a ∈ s, CompleteLattice.SetIndependent a) : CompleteLattice.SetIndependent (⋃₀ s) := by +@[deprecated (since := "2024-11-24")] +alias CompleteLattice.setIndependent_iUnion_of_directed := sSupIndep_iUnion_of_directed + +theorem iSupIndep_sUnion_of_directed {s : Set (Set α)} (hs : DirectedOn (· ⊆ ·) s) + (h : ∀ a ∈ s, sSupIndep a) : sSupIndep (⋃₀ s) := by rw [Set.sUnion_eq_iUnion] - exact CompleteLattice.setIndependent_iUnion_of_directed hs.directed_val (by simpa using h) + exact sSupIndep_iUnion_of_directed hs.directed_val (by simpa using h) + +@[deprecated (since := "2024-11-24")] +alias CompleteLattice.independent_sUnion_of_directed := iSupIndep_sUnion_of_directed end @@ -495,11 +526,11 @@ alias IsSupFiniteCompact.wellFounded := IsSupFiniteCompact.wellFoundedGT @[deprecated (since := "2024-10-07")] alias _root_.WellFounded.isSupClosedCompact := WellFoundedGT.isSupClosedCompact @[deprecated (since := "2024-10-07")] -alias WellFounded.finite_of_setIndependent := WellFoundedGT.finite_of_setIndependent +alias WellFounded.finite_of_setIndependent := WellFoundedGT.finite_of_sSupIndep @[deprecated (since := "2024-10-07")] -alias WellFounded.finite_ne_bot_of_independent := WellFoundedGT.finite_ne_bot_of_independent +alias WellFounded.finite_ne_bot_of_independent := WellFoundedGT.finite_ne_bot_of_iSupIndep @[deprecated (since := "2024-10-07")] -alias WellFounded.finite_of_independent := WellFoundedGT.finite_of_independent +alias WellFounded.finite_of_independent := WellFoundedGT.finite_of_iSupIndep @[deprecated (since := "2024-10-07")] alias isCompactlyGenerated_of_wellFounded := isCompactlyGenerated_of_wellFoundedGT @@ -578,16 +609,16 @@ Most explicitly, every element is the complement of a supremum of indepedendent /-- In an atomic lattice, every element `b` has a complement of the form `sSup s`, where each element of `s` is an atom. See also `complementedLattice_of_sSup_atoms_eq_top`. -/ -theorem exists_setIndependent_isCompl_sSup_atoms (h : sSup { a : α | IsAtom a } = ⊤) (b : α) : - ∃ s : Set α, CompleteLattice.SetIndependent s ∧ +theorem exists_sSupIndep_isCompl_sSup_atoms (h : sSup { a : α | IsAtom a } = ⊤) (b : α) : + ∃ s : Set α, sSupIndep s ∧ IsCompl b (sSup s) ∧ ∀ ⦃a⦄, a ∈ s → IsAtom a := by -- porting note(https://github.com/leanprover-community/mathlib4/issues/5732): -- `obtain` chokes on the placeholder. have zorn := zorn_subset - (S := {s : Set α | CompleteLattice.SetIndependent s ∧ Disjoint b (sSup s) ∧ ∀ a ∈ s, IsAtom a}) + (S := {s : Set α | sSupIndep s ∧ Disjoint b (sSup s) ∧ ∀ a ∈ s, IsAtom a}) fun c hc1 hc2 => ⟨⋃₀ c, - ⟨CompleteLattice.independent_sUnion_of_directed hc2.directedOn fun s hs => (hc1 hs).1, ?_, + ⟨iSupIndep_sUnion_of_directed hc2.directedOn fun s hs => (hc1 hs).1, ?_, fun a ⟨s, sc, as⟩ => (hc1 sc).2.2 a as⟩, fun _ => Set.subset_sUnion_of_mem⟩ swap @@ -633,16 +664,22 @@ theorem exists_setIndependent_isCompl_sSup_atoms (h : sSup { a : α | IsAtom a } · exact s_atoms x hx · exact ha -theorem exists_setIndependent_of_sSup_atoms_eq_top (h : sSup { a : α | IsAtom a } = ⊤) : - ∃ s : Set α, CompleteLattice.SetIndependent s ∧ sSup s = ⊤ ∧ ∀ ⦃a⦄, a ∈ s → IsAtom a := - let ⟨s, s_ind, s_top, s_atoms⟩ := exists_setIndependent_isCompl_sSup_atoms h ⊥ +@[deprecated (since := "2024-11-24")] +alias exists_setIndependent_isCompl_sSup_atoms := exists_sSupIndep_isCompl_sSup_atoms + +theorem exists_sSupIndep_of_sSup_atoms_eq_top (h : sSup { a : α | IsAtom a } = ⊤) : + ∃ s : Set α, sSupIndep s ∧ sSup s = ⊤ ∧ ∀ ⦃a⦄, a ∈ s → IsAtom a := + let ⟨s, s_ind, s_top, s_atoms⟩ := exists_sSupIndep_isCompl_sSup_atoms h ⊥ ⟨s, s_ind, eq_top_of_isCompl_bot s_top.symm, s_atoms⟩ +@[deprecated (since := "2024-11-24")] +alias exists_setIndependent_of_sSup_atoms_eq_top := exists_sSupIndep_of_sSup_atoms_eq_top + /-- See [Theorem 6.6][calugareanu]. -/ theorem complementedLattice_of_sSup_atoms_eq_top (h : sSup { a : α | IsAtom a } = ⊤) : ComplementedLattice α := ⟨fun b => - let ⟨s, _, s_top, _⟩ := exists_setIndependent_isCompl_sSup_atoms h b + let ⟨s, _, s_top, _⟩ := exists_sSupIndep_isCompl_sSup_atoms h b ⟨sSup s, s_top⟩⟩ /-- See [Theorem 6.6][calugareanu]. -/ diff --git a/Mathlib/Order/Compare.lean b/Mathlib/Order/Compare.lean index 9fd8b1100315f..5e29b6e29a069 100644 --- a/Mathlib/Order/Compare.lean +++ b/Mathlib/Order/Compare.lean @@ -137,8 +137,7 @@ theorem cmp_swap [Preorder α] [@DecidableRel α (· < ·)] (a b : α) : (cmp a by_cases h : a < b <;> by_cases h₂ : b < a <;> simp [h, h₂, Ordering.swap] exact lt_asymm h h₂ --- Porting note: Not sure why the simpNF linter doesn't like this. @semorrison -@[simp, nolint simpNF] +@[simp] theorem cmpLE_toDual [LE α] [@DecidableRel α (· ≤ ·)] (x y : α) : cmpLE (toDual x) (toDual y) = cmpLE y x := rfl @@ -148,8 +147,7 @@ theorem cmpLE_ofDual [LE α] [@DecidableRel α (· ≤ ·)] (x y : αᵒᵈ) : cmpLE (ofDual x) (ofDual y) = cmpLE y x := rfl --- Porting note: Not sure why the simpNF linter doesn't like this. @semorrison -@[simp, nolint simpNF] +@[simp] theorem cmp_toDual [LT α] [@DecidableRel α (· < ·)] (x y : α) : cmp (toDual x) (toDual y) = cmp y x := rfl diff --git a/Mathlib/Order/ConditionallyCompleteLattice/Basic.lean b/Mathlib/Order/ConditionallyCompleteLattice/Basic.lean index bf1aa9e9ffaec..437a1e3d52e13 100644 --- a/Mathlib/Order/ConditionallyCompleteLattice/Basic.lean +++ b/Mathlib/Order/ConditionallyCompleteLattice/Basic.lean @@ -3,11 +3,8 @@ Copyright (c) 2018 Sébastien Gouëzel. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Sébastien Gouëzel -/ -import Mathlib.Order.Bounds.Basic -import Mathlib.Order.WellFounded -import Mathlib.Data.Set.Image -import Mathlib.Order.Interval.Set.Basic import Mathlib.Data.Set.Lattice +import Mathlib.Order.ConditionallyCompleteLattice.Defs /-! # Theory of conditionally complete lattices @@ -119,50 +116,6 @@ theorem WithBot.coe_sInf' [InfSet α] {s : Set α} (hs : BddBelow s) : end -/-- A conditionally complete lattice is a lattice in which -every nonempty subset which is bounded above has a supremum, and -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 `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 - /-- `a ≤ sSup s` for all `a ∈ s`. -/ - le_csSup : ∀ s a, BddAbove s → a ∈ s → a ≤ sSup s - /-- `sSup s ≤ a` for all `a ∈ upperBounds s`. -/ - csSup_le : ∀ s a, Set.Nonempty s → a ∈ upperBounds s → sSup s ≤ a - /-- `sInf s ≤ a` for all `a ∈ s`. -/ - csInf_le : ∀ s a, BddBelow s → a ∈ s → sInf s ≤ a - /-- `a ≤ sInf s` for all `a ∈ lowerBounds s`. -/ - le_csInf : ∀ s a, Set.Nonempty s → a ∈ lowerBounds s → a ≤ sInf s - --- Porting note: mathlib3 used `renaming` -/-- A conditionally complete linear order is a linear order in which -every nonempty subset which is bounded above has a supremum, and -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 -hold in both worlds, sometimes with additional assumptions of nonemptiness or -boundedness. -/ -class ConditionallyCompleteLinearOrder (α : Type*) extends ConditionallyCompleteLattice α where - /-- A `ConditionallyCompleteLinearOrder` is total. -/ - le_total (a b : α) : a ≤ b ∨ b ≤ a - /-- In a `ConditionallyCompleteLinearOrder`, we assume the order relations are all decidable. -/ - decidableLE : DecidableRel (· ≤ · : α → α → Prop) - /-- In a `ConditionallyCompleteLinearOrder`, we assume the order relations are all decidable. -/ - decidableEq : DecidableEq α := @decidableEqOfDecidableLE _ _ decidableLE - /-- In a `ConditionallyCompleteLinearOrder`, we assume the order relations are all decidable. -/ - decidableLT : DecidableRel (· < · : α → α → Prop) := - @decidableLTOfDecidableLE _ _ decidableLE - /-- If a set is not bounded above, its supremum is by convention `sSup ∅`. -/ - csSup_of_not_bddAbove : ∀ s, ¬BddAbove s → sSup s = sSup (∅ : Set α) - /-- If a set is not bounded below, its infimum is by convention `sInf ∅`. -/ - csInf_of_not_bddBelow : ∀ s, ¬BddBelow s → sInf s = sInf (∅ : Set α) - instance ConditionallyCompleteLinearOrder.toLinearOrder [ConditionallyCompleteLinearOrder α] : LinearOrder α := { ‹ConditionallyCompleteLinearOrder α› with @@ -179,19 +132,6 @@ instance ConditionallyCompleteLinearOrder.toLinearOrder [ConditionallyCompleteLi · simp [h₁] · simp [show ¬(a ≤ b) from fun h => hab (le_antisymm h h₂), h₂] } -/-- A conditionally complete linear order with `Bot` is a linear order with least element, in which -every nonempty subset which is bounded above has a supremum, and every nonempty subset (necessarily -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 -hold in both worlds, sometimes with additional assumptions of nonemptiness or -boundedness. -/ -class ConditionallyCompleteLinearOrderBot (α : Type*) extends ConditionallyCompleteLinearOrder α, - OrderBot α where - /-- The supremum of the empty set is special-cased to `⊥` -/ - csSup_empty : sSup ∅ = ⊥ - -- see Note [lower instance priority] attribute [instance 100] ConditionallyCompleteLinearOrderBot.toOrderBot @@ -214,36 +154,6 @@ instance (priority := 100) CompleteLinearOrder.toConditionallyCompleteLinearOrde csSup_of_not_bddAbove := fun s H ↦ (H (OrderTop.bddAbove s)).elim csInf_of_not_bddBelow := fun s H ↦ (H (OrderBot.bddBelow s)).elim } -open scoped Classical in -/-- A well founded linear order is conditionally complete, with a bottom element. -/ -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 ⊥ - csInf_le := fun s a _ has => by - have s_ne : s.Nonempty := ⟨a, has⟩ - simpa [s_ne] using not_lt.1 (h.wf.not_lt_min s s_ne has) - le_csInf := fun s a hs has => by - simp only [hs, dif_pos] - exact has (h.wf.min_mem s hs) - sSup := fun s => if hs : (upperBounds s).Nonempty then h.wf.min _ hs else ⊥ - le_csSup := fun s a hs has => by - have h's : (upperBounds s).Nonempty := hs - simp only [h's, dif_pos] - exact h.wf.min_mem _ h's has - csSup_le := fun s a _ has => by - have h's : (upperBounds s).Nonempty := ⟨a, has⟩ - simp only [h's, dif_pos] - simpa using h.wf.not_lt_min _ h's has - csSup_empty := by simpa using eq_bot_iff.2 (not_lt.1 <| h.wf.not_lt_min _ _ <| mem_univ ⊥) - csSup_of_not_bddAbove := by - intro s H - have B : ¬((upperBounds s).Nonempty) := H - simp only [B, dite_false, upperBounds_empty, univ_nonempty, dite_true] - exact le_antisymm bot_le (WellFounded.min_le _ (mem_univ _)) - csInf_of_not_bddBelow := fun s H ↦ (H (OrderBot.bddBelow s)).elim } - namespace OrderDual instance instConditionallyCompleteLattice (α : Type*) [ConditionallyCompleteLattice α] : @@ -261,132 +171,6 @@ instance (α : Type*) [ConditionallyCompleteLinearOrder α] : ConditionallyCompl end OrderDual -/-- Create a `ConditionallyCompleteLattice` from a `PartialOrder` and `sup` function -that returns the least upper bound of a nonempty set which is bounded above. Usually this -constructor provides poor definitional equalities. If other fields are known explicitly, they -should be provided; for example, if `inf` is known explicitly, construct the -`ConditionallyCompleteLattice` instance as -``` -instance : ConditionallyCompleteLattice my_T := - { inf := better_inf, - le_inf := ..., - inf_le_right := ..., - inf_le_left := ... - -- don't care to fix sup, sInf - ..conditionallyCompleteLatticeOfsSup my_T _ } -``` --/ -def conditionallyCompleteLatticeOfsSup (α : Type*) [H1 : PartialOrder α] [H2 : SupSet α] - (bddAbove_pair : ∀ a b : α, BddAbove ({a, b} : Set α)) - (bddBelow_pair : ∀ a b : α, BddBelow ({a, b} : Set α)) - (isLUB_sSup : ∀ s : Set α, BddAbove s → s.Nonempty → IsLUB s (sSup s)) : - ConditionallyCompleteLattice α := - { H1, H2 with - sup := fun a b => sSup {a, b} - le_sup_left := fun a b => - (isLUB_sSup {a, b} (bddAbove_pair a b) (insert_nonempty _ _)).1 (mem_insert _ _) - le_sup_right := fun a b => - (isLUB_sSup {a, b} (bddAbove_pair a b) (insert_nonempty _ _)).1 - (mem_insert_of_mem _ (mem_singleton _)) - sup_le := fun a b _ hac hbc => - (isLUB_sSup {a, b} (bddAbove_pair a b) (insert_nonempty _ _)).2 - (forall_insert_of_forall (forall_eq.mpr hbc) hac) - inf := fun a b => sSup (lowerBounds {a, b}) - inf_le_left := fun a b => - (isLUB_sSup (lowerBounds {a, b}) (Nonempty.bddAbove_lowerBounds ⟨a, mem_insert _ _⟩) - (bddBelow_pair a b)).2 - fun _ hc => hc <| mem_insert _ _ - inf_le_right := fun a b => - (isLUB_sSup (lowerBounds {a, b}) (Nonempty.bddAbove_lowerBounds ⟨a, mem_insert _ _⟩) - (bddBelow_pair a b)).2 - fun _ hc => hc <| mem_insert_of_mem _ (mem_singleton _) - le_inf := fun c a b hca hcb => - (isLUB_sSup (lowerBounds {a, b}) (Nonempty.bddAbove_lowerBounds ⟨a, mem_insert _ _⟩) - ⟨c, forall_insert_of_forall (forall_eq.mpr hcb) hca⟩).1 - (forall_insert_of_forall (forall_eq.mpr hcb) hca) - sInf := fun s => sSup (lowerBounds s) - csSup_le := fun s a hs ha => (isLUB_sSup s ⟨a, ha⟩ hs).2 ha - le_csSup := fun s a hs ha => (isLUB_sSup s hs ⟨a, ha⟩).1 ha - csInf_le := fun s a hs ha => - (isLUB_sSup (lowerBounds s) (Nonempty.bddAbove_lowerBounds ⟨a, ha⟩) hs).2 fun _ hb => hb ha - le_csInf := fun s a hs ha => - (isLUB_sSup (lowerBounds s) hs.bddAbove_lowerBounds ⟨a, ha⟩).1 ha } - -/-- Create a `ConditionallyCompleteLattice` from a `PartialOrder` and `inf` function -that returns the greatest lower bound of a nonempty set which is bounded below. Usually this -constructor provides poor definitional equalities. If other fields are known explicitly, they -should be provided; for example, if `inf` is known explicitly, construct the -`ConditionallyCompleteLattice` instance as -``` -instance : ConditionallyCompleteLattice my_T := - { inf := better_inf, - le_inf := ..., - inf_le_right := ..., - inf_le_left := ... - -- don't care to fix sup, sSup - ..conditionallyCompleteLatticeOfsInf my_T _ } -``` --/ -def conditionallyCompleteLatticeOfsInf (α : Type*) [H1 : PartialOrder α] [H2 : InfSet α] - (bddAbove_pair : ∀ a b : α, BddAbove ({a, b} : Set α)) - (bddBelow_pair : ∀ a b : α, BddBelow ({a, b} : Set α)) - (isGLB_sInf : ∀ s : Set α, BddBelow s → s.Nonempty → IsGLB s (sInf s)) : - ConditionallyCompleteLattice α := - { H1, H2 with - inf := fun a b => sInf {a, b} - inf_le_left := fun a b => - (isGLB_sInf {a, b} (bddBelow_pair a b) (insert_nonempty _ _)).1 (mem_insert _ _) - inf_le_right := fun a b => - (isGLB_sInf {a, b} (bddBelow_pair a b) (insert_nonempty _ _)).1 - (mem_insert_of_mem _ (mem_singleton _)) - le_inf := fun _ a b hca hcb => - (isGLB_sInf {a, b} (bddBelow_pair a b) (insert_nonempty _ _)).2 - (forall_insert_of_forall (forall_eq.mpr hcb) hca) - sup := fun a b => sInf (upperBounds {a, b}) - le_sup_left := fun a b => - (isGLB_sInf (upperBounds {a, b}) (Nonempty.bddBelow_upperBounds ⟨a, mem_insert _ _⟩) - (bddAbove_pair a b)).2 - fun _ hc => hc <| mem_insert _ _ - le_sup_right := fun a b => - (isGLB_sInf (upperBounds {a, b}) (Nonempty.bddBelow_upperBounds ⟨a, mem_insert _ _⟩) - (bddAbove_pair a b)).2 - fun _ hc => hc <| mem_insert_of_mem _ (mem_singleton _) - sup_le := fun a b c hac hbc => - (isGLB_sInf (upperBounds {a, b}) (Nonempty.bddBelow_upperBounds ⟨a, mem_insert _ _⟩) - ⟨c, forall_insert_of_forall (forall_eq.mpr hbc) hac⟩).1 - (forall_insert_of_forall (forall_eq.mpr hbc) hac) - sSup := fun s => sInf (upperBounds s) - le_csInf := fun s a hs ha => (isGLB_sInf s ⟨a, ha⟩ hs).2 ha - csInf_le := fun s a hs ha => (isGLB_sInf s hs ⟨a, ha⟩).1 ha - le_csSup := fun s a hs ha => - (isGLB_sInf (upperBounds s) (Nonempty.bddBelow_upperBounds ⟨a, ha⟩) hs).2 fun _ hb => hb ha - csSup_le := fun s a hs ha => - (isGLB_sInf (upperBounds s) hs.bddBelow_upperBounds ⟨a, ha⟩).1 ha } - -/-- A version of `conditionallyCompleteLatticeOfsSup` when we already know that `α` is a lattice. - -This should only be used when it is both hard and unnecessary to provide `inf` explicitly. -/ -def conditionallyCompleteLatticeOfLatticeOfsSup (α : Type*) [H1 : Lattice α] [SupSet α] - (isLUB_sSup : ∀ s : Set α, BddAbove s → s.Nonempty → IsLUB s (sSup s)) : - ConditionallyCompleteLattice α := - { H1, - conditionallyCompleteLatticeOfsSup α - (fun a b => ⟨a ⊔ b, forall_insert_of_forall (forall_eq.mpr le_sup_right) le_sup_left⟩) - (fun a b => ⟨a ⊓ b, forall_insert_of_forall (forall_eq.mpr inf_le_right) inf_le_left⟩) - isLUB_sSup with } - -/-- A version of `conditionallyCompleteLatticeOfsInf` when we already know that `α` is a lattice. - -This should only be used when it is both hard and unnecessary to provide `sup` explicitly. -/ -def conditionallyCompleteLatticeOfLatticeOfsInf (α : Type*) [H1 : Lattice α] [InfSet α] - (isGLB_sInf : ∀ s : Set α, BddBelow s → s.Nonempty → IsGLB s (sInf s)) : - ConditionallyCompleteLattice α := - { H1, - conditionallyCompleteLatticeOfsInf α - (fun a b => ⟨a ⊔ b, forall_insert_of_forall (forall_eq.mpr le_sup_right) le_sup_left⟩) - (fun a b => ⟨a ⊓ b, forall_insert_of_forall (forall_eq.mpr inf_le_right) inf_le_left⟩) - isGLB_sInf with } - section ConditionallyCompleteLattice variable [ConditionallyCompleteLattice α] {s t : Set α} {a b : α} diff --git a/Mathlib/Order/ConditionallyCompleteLattice/Defs.lean b/Mathlib/Order/ConditionallyCompleteLattice/Defs.lean new file mode 100644 index 0000000000000..4a499bbdfdc7a --- /dev/null +++ b/Mathlib/Order/ConditionallyCompleteLattice/Defs.lean @@ -0,0 +1,251 @@ +/- +Copyright (c) 2018 Sébastien Gouëzel. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Sébastien Gouëzel +-/ +import Mathlib.Order.Bounds.Basic +import Mathlib.Order.SetNotation +import Mathlib.Order.WellFounded + +/-! +# Definitions of conditionally complete lattices + +A conditionally complete lattice is a lattice in which every non-empty bounded subset `s` +has a least upper bound and a greatest lower bound, denoted below by `sSup s` and `sInf s`. +Typical examples are `ℝ`, `ℕ`, and `ℤ` with their usual orders. + +The theory is very comparable to the theory of complete lattices, except that suitable +boundedness and nonemptiness assumptions have to be added to most statements. +We express these using the `BddAbove` and `BddBelow` predicates, which we use to prove +most useful properties of `sSup` and `sInf` in conditionally complete lattices. + +To differentiate the statements between complete lattices and conditionally complete +lattices, we prefix `sInf` and `sSup` in the statements by `c`, giving `csInf` and `csSup`. +For instance, `sInf_le` is a statement in complete lattices ensuring `sInf s ≤ x`, +while `csInf_le` is the same statement in conditionally complete lattices +with an additional assumption that `s` is bounded below. +-/ + +open Set + +variable {α β γ : Type*} {ι : Sort*} + +/-- A conditionally complete lattice is a lattice in which +every nonempty subset which is bounded above has a supremum, and +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 `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 + /-- `a ≤ sSup s` for all `a ∈ s`. -/ + le_csSup : ∀ s a, BddAbove s → a ∈ s → a ≤ sSup s + /-- `sSup s ≤ a` for all `a ∈ upperBounds s`. -/ + csSup_le : ∀ s a, Set.Nonempty s → a ∈ upperBounds s → sSup s ≤ a + /-- `sInf s ≤ a` for all `a ∈ s`. -/ + csInf_le : ∀ s a, BddBelow s → a ∈ s → sInf s ≤ a + /-- `a ≤ sInf s` for all `a ∈ lowerBounds s`. -/ + le_csInf : ∀ s a, Set.Nonempty s → a ∈ lowerBounds s → a ≤ sInf s + +-- Porting note: mathlib3 used `renaming` +/-- A conditionally complete linear order is a linear order in which +every nonempty subset which is bounded above has a supremum, and +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 +hold in both worlds, sometimes with additional assumptions of nonemptiness or +boundedness. -/ +class ConditionallyCompleteLinearOrder (α : Type*) extends ConditionallyCompleteLattice α where + /-- A `ConditionallyCompleteLinearOrder` is total. -/ + le_total (a b : α) : a ≤ b ∨ b ≤ a + /-- In a `ConditionallyCompleteLinearOrder`, we assume the order relations are all decidable. -/ + decidableLE : DecidableRel (· ≤ · : α → α → Prop) + /-- In a `ConditionallyCompleteLinearOrder`, we assume the order relations are all decidable. -/ + decidableEq : DecidableEq α := @decidableEqOfDecidableLE _ _ decidableLE + /-- In a `ConditionallyCompleteLinearOrder`, we assume the order relations are all decidable. -/ + decidableLT : DecidableRel (· < · : α → α → Prop) := + @decidableLTOfDecidableLE _ _ decidableLE + /-- If a set is not bounded above, its supremum is by convention `sSup ∅`. -/ + csSup_of_not_bddAbove : ∀ s, ¬BddAbove s → sSup s = sSup (∅ : Set α) + /-- If a set is not bounded below, its infimum is by convention `sInf ∅`. -/ + csInf_of_not_bddBelow : ∀ s, ¬BddBelow s → sInf s = sInf (∅ : Set α) + +/-- A conditionally complete linear order with `Bot` is a linear order with least element, in which +every nonempty subset which is bounded above has a supremum, and every nonempty subset (necessarily +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 +hold in both worlds, sometimes with additional assumptions of nonemptiness or +boundedness. -/ +class ConditionallyCompleteLinearOrderBot (α : Type*) extends ConditionallyCompleteLinearOrder α, + OrderBot α where + /-- The supremum of the empty set is special-cased to `⊥` -/ + csSup_empty : sSup ∅ = ⊥ + +-- see Note [lower instance priority] +attribute [instance 100] ConditionallyCompleteLinearOrderBot.toOrderBot + +open scoped Classical in +/-- A well founded linear order is conditionally complete, with a bottom element. -/ +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 ⊥ + csInf_le := fun s a _ has => by + have s_ne : s.Nonempty := ⟨a, has⟩ + simpa [s_ne] using not_lt.1 (h.wf.not_lt_min s s_ne has) + le_csInf := fun s a hs has => by + simp only [hs, dif_pos] + exact has (h.wf.min_mem s hs) + sSup := fun s => if hs : (upperBounds s).Nonempty then h.wf.min _ hs else ⊥ + le_csSup := fun s a hs has => by + have h's : (upperBounds s).Nonempty := hs + simp only [h's, dif_pos] + exact h.wf.min_mem _ h's has + csSup_le := fun s a _ has => by + have h's : (upperBounds s).Nonempty := ⟨a, has⟩ + simp only [h's, dif_pos] + simpa using h.wf.not_lt_min _ h's has + csSup_empty := by simpa using eq_bot_iff.2 (not_lt.1 <| h.wf.not_lt_min _ _ <| mem_univ ⊥) + csSup_of_not_bddAbove := by + intro s H + have B : ¬((upperBounds s).Nonempty) := H + simp only [B, dite_false, upperBounds_empty, univ_nonempty, dite_true] + exact le_antisymm bot_le (WellFounded.min_le _ (mem_univ _)) + csInf_of_not_bddBelow := fun s H ↦ (H (OrderBot.bddBelow s)).elim } + +namespace OrderDual + +end OrderDual + +/-- Create a `ConditionallyCompleteLattice` from a `PartialOrder` and `sup` function +that returns the least upper bound of a nonempty set which is bounded above. Usually this +constructor provides poor definitional equalities. If other fields are known explicitly, they +should be provided; for example, if `inf` is known explicitly, construct the +`ConditionallyCompleteLattice` instance as +``` +instance : ConditionallyCompleteLattice my_T := + { inf := better_inf, + le_inf := ..., + inf_le_right := ..., + inf_le_left := ... + -- don't care to fix sup, sInf + ..conditionallyCompleteLatticeOfsSup my_T _ } +``` +-/ +def conditionallyCompleteLatticeOfsSup (α : Type*) [H1 : PartialOrder α] [H2 : SupSet α] + (bddAbove_pair : ∀ a b : α, BddAbove ({a, b} : Set α)) + (bddBelow_pair : ∀ a b : α, BddBelow ({a, b} : Set α)) + (isLUB_sSup : ∀ s : Set α, BddAbove s → s.Nonempty → IsLUB s (sSup s)) : + ConditionallyCompleteLattice α := + { H1, H2 with + sup := fun a b => sSup {a, b} + le_sup_left := fun a b => + (isLUB_sSup {a, b} (bddAbove_pair a b) (insert_nonempty _ _)).1 (mem_insert _ _) + le_sup_right := fun a b => + (isLUB_sSup {a, b} (bddAbove_pair a b) (insert_nonempty _ _)).1 + (mem_insert_of_mem _ (mem_singleton _)) + sup_le := fun a b _ hac hbc => + (isLUB_sSup {a, b} (bddAbove_pair a b) (insert_nonempty _ _)).2 + (forall_insert_of_forall (forall_eq.mpr hbc) hac) + inf := fun a b => sSup (lowerBounds {a, b}) + inf_le_left := fun a b => + (isLUB_sSup (lowerBounds {a, b}) (Nonempty.bddAbove_lowerBounds ⟨a, mem_insert _ _⟩) + (bddBelow_pair a b)).2 + fun _ hc => hc <| mem_insert _ _ + inf_le_right := fun a b => + (isLUB_sSup (lowerBounds {a, b}) (Nonempty.bddAbove_lowerBounds ⟨a, mem_insert _ _⟩) + (bddBelow_pair a b)).2 + fun _ hc => hc <| mem_insert_of_mem _ (mem_singleton _) + le_inf := fun c a b hca hcb => + (isLUB_sSup (lowerBounds {a, b}) (Nonempty.bddAbove_lowerBounds ⟨a, mem_insert _ _⟩) + ⟨c, forall_insert_of_forall (forall_eq.mpr hcb) hca⟩).1 + (forall_insert_of_forall (forall_eq.mpr hcb) hca) + sInf := fun s => sSup (lowerBounds s) + csSup_le := fun s a hs ha => (isLUB_sSup s ⟨a, ha⟩ hs).2 ha + le_csSup := fun s a hs ha => (isLUB_sSup s hs ⟨a, ha⟩).1 ha + csInf_le := fun s a hs ha => + (isLUB_sSup (lowerBounds s) (Nonempty.bddAbove_lowerBounds ⟨a, ha⟩) hs).2 fun _ hb => hb ha + le_csInf := fun s a hs ha => + (isLUB_sSup (lowerBounds s) hs.bddAbove_lowerBounds ⟨a, ha⟩).1 ha } + +/-- Create a `ConditionallyCompleteLattice` from a `PartialOrder` and `inf` function +that returns the greatest lower bound of a nonempty set which is bounded below. Usually this +constructor provides poor definitional equalities. If other fields are known explicitly, they +should be provided; for example, if `inf` is known explicitly, construct the +`ConditionallyCompleteLattice` instance as +``` +instance : ConditionallyCompleteLattice my_T := + { inf := better_inf, + le_inf := ..., + inf_le_right := ..., + inf_le_left := ... + -- don't care to fix sup, sSup + ..conditionallyCompleteLatticeOfsInf my_T _ } +``` +-/ +def conditionallyCompleteLatticeOfsInf (α : Type*) [H1 : PartialOrder α] [H2 : InfSet α] + (bddAbove_pair : ∀ a b : α, BddAbove ({a, b} : Set α)) + (bddBelow_pair : ∀ a b : α, BddBelow ({a, b} : Set α)) + (isGLB_sInf : ∀ s : Set α, BddBelow s → s.Nonempty → IsGLB s (sInf s)) : + ConditionallyCompleteLattice α := + { H1, H2 with + inf := fun a b => sInf {a, b} + inf_le_left := fun a b => + (isGLB_sInf {a, b} (bddBelow_pair a b) (insert_nonempty _ _)).1 (mem_insert _ _) + inf_le_right := fun a b => + (isGLB_sInf {a, b} (bddBelow_pair a b) (insert_nonempty _ _)).1 + (mem_insert_of_mem _ (mem_singleton _)) + le_inf := fun _ a b hca hcb => + (isGLB_sInf {a, b} (bddBelow_pair a b) (insert_nonempty _ _)).2 + (forall_insert_of_forall (forall_eq.mpr hcb) hca) + sup := fun a b => sInf (upperBounds {a, b}) + le_sup_left := fun a b => + (isGLB_sInf (upperBounds {a, b}) (Nonempty.bddBelow_upperBounds ⟨a, mem_insert _ _⟩) + (bddAbove_pair a b)).2 + fun _ hc => hc <| mem_insert _ _ + le_sup_right := fun a b => + (isGLB_sInf (upperBounds {a, b}) (Nonempty.bddBelow_upperBounds ⟨a, mem_insert _ _⟩) + (bddAbove_pair a b)).2 + fun _ hc => hc <| mem_insert_of_mem _ (mem_singleton _) + sup_le := fun a b c hac hbc => + (isGLB_sInf (upperBounds {a, b}) (Nonempty.bddBelow_upperBounds ⟨a, mem_insert _ _⟩) + ⟨c, forall_insert_of_forall (forall_eq.mpr hbc) hac⟩).1 + (forall_insert_of_forall (forall_eq.mpr hbc) hac) + sSup := fun s => sInf (upperBounds s) + le_csInf := fun s a hs ha => (isGLB_sInf s ⟨a, ha⟩ hs).2 ha + csInf_le := fun s a hs ha => (isGLB_sInf s hs ⟨a, ha⟩).1 ha + le_csSup := fun s a hs ha => + (isGLB_sInf (upperBounds s) (Nonempty.bddBelow_upperBounds ⟨a, ha⟩) hs).2 fun _ hb => hb ha + csSup_le := fun s a hs ha => + (isGLB_sInf (upperBounds s) hs.bddBelow_upperBounds ⟨a, ha⟩).1 ha } + +/-- A version of `conditionallyCompleteLatticeOfsSup` when we already know that `α` is a lattice. + +This should only be used when it is both hard and unnecessary to provide `inf` explicitly. -/ +def conditionallyCompleteLatticeOfLatticeOfsSup (α : Type*) [H1 : Lattice α] [SupSet α] + (isLUB_sSup : ∀ s : Set α, BddAbove s → s.Nonempty → IsLUB s (sSup s)) : + ConditionallyCompleteLattice α := + { H1, + conditionallyCompleteLatticeOfsSup α + (fun a b => ⟨a ⊔ b, forall_insert_of_forall (forall_eq.mpr le_sup_right) le_sup_left⟩) + (fun a b => ⟨a ⊓ b, forall_insert_of_forall (forall_eq.mpr inf_le_right) inf_le_left⟩) + isLUB_sSup with } + +/-- A version of `conditionallyCompleteLatticeOfsInf` when we already know that `α` is a lattice. + +This should only be used when it is both hard and unnecessary to provide `sup` explicitly. -/ +def conditionallyCompleteLatticeOfLatticeOfsInf (α : Type*) [H1 : Lattice α] [InfSet α] + (isGLB_sInf : ∀ s : Set α, BddBelow s → s.Nonempty → IsGLB s (sInf s)) : + ConditionallyCompleteLattice α := + { H1, + conditionallyCompleteLatticeOfsInf α + (fun a b => ⟨a ⊔ b, forall_insert_of_forall (forall_eq.mpr le_sup_right) le_sup_left⟩) + (fun a b => ⟨a ⊓ b, forall_insert_of_forall (forall_eq.mpr inf_le_right) inf_le_left⟩) + isGLB_sInf with } diff --git a/Mathlib/Order/Defs.lean b/Mathlib/Order/Defs.lean index dc90cc7b0adbe..b97cdc2c979d6 100644 --- a/Mathlib/Order/Defs.lean +++ b/Mathlib/Order/Defs.lean @@ -206,11 +206,11 @@ theorem Equivalence.transitive (h : Equivalence r) : Transitive r := variable {β : Sort*} (r : β → β → Prop) (f : α → β) -@[deprecated (since := "2024-09-13")] +@[deprecated "No deprecation message was provided." (since := "2024-09-13")] theorem InvImage.trans (h : Transitive r) : Transitive (InvImage r f) := fun (a₁ a₂ a₃ : α) (h₁ : InvImage r f a₁ a₂) (h₂ : InvImage r f a₂ a₃) ↦ h h₁ h₂ -@[deprecated (since := "2024-09-13")] +@[deprecated "No deprecation message was provided." (since := "2024-09-13")] theorem InvImage.irreflexive (h : Irreflexive r) : Irreflexive (InvImage r f) := fun (a : α) (h₁ : InvImage r f a a) ↦ h (f a) h₁ @@ -276,7 +276,7 @@ lemma lt_iff_le_not_le : a < b ↔ a ≤ b ∧ ¬b ≤ a := Preorder.lt_iff_le_n 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")] +@[deprecated "No deprecation message was provided." (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 @@ -502,7 +502,7 @@ namespace Nat /-! Deprecated properties of inequality on `Nat` -/ -@[deprecated (since := "2024-08-23")] +@[deprecated "No deprecation message was provided." (since := "2024-08-23")] protected def ltGeByCases {a b : Nat} {C : Sort*} (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) diff --git a/Mathlib/Order/Disjoint.lean b/Mathlib/Order/Disjoint.lean index b024a335e595c..59bcd0815347d 100644 --- a/Mathlib/Order/Disjoint.lean +++ b/Mathlib/Order/Disjoint.lean @@ -205,12 +205,14 @@ arguments. -/ def Codisjoint (a b : α) : Prop := ∀ ⦃x⦄, a ≤ x → b ≤ x → ⊤ ≤ x -theorem Codisjoint_comm : Codisjoint a b ↔ Codisjoint b a := +theorem codisjoint_comm : Codisjoint a b ↔ Codisjoint b a := forall_congr' fun _ ↦ forall_swap +@[deprecated (since := "2024-11-23")] alias Codisjoint_comm := codisjoint_comm + @[symm] theorem Codisjoint.symm ⦃a b : α⦄ : Codisjoint a b → Codisjoint b a := - Codisjoint_comm.1 + codisjoint_comm.1 theorem symmetric_codisjoint : Symmetric (Codisjoint : α → α → Prop) := Codisjoint.symm diff --git a/Mathlib/Order/Filter/AtTopBot/Monoid.lean b/Mathlib/Order/Filter/AtTopBot/Monoid.lean index 0cfa275d9a426..02cdf596f5854 100644 --- a/Mathlib/Order/Filter/AtTopBot/Monoid.lean +++ b/Mathlib/Order/Filter/AtTopBot/Monoid.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov -/ import Mathlib.Algebra.Order.Monoid.OrderDual +import Mathlib.Algebra.Order.Monoid.Unbundled.Pow import Mathlib.Order.Filter.AtTopBot /-! diff --git a/Mathlib/Order/Filter/Bases.lean b/Mathlib/Order/Filter/Bases.lean index ffd5fe2a6c9e4..ab8dd13872eb6 100644 --- a/Mathlib/Order/Filter/Bases.lean +++ b/Mathlib/Order/Filter/Bases.lean @@ -5,7 +5,7 @@ Authors: Yury Kudryashov, Johannes Hölzl, Mario Carneiro, Patrick Massot -/ import Mathlib.Data.Prod.PProd import Mathlib.Data.Set.Countable -import Mathlib.Order.Filter.Basic +import Mathlib.Order.Filter.Finite /-! # Filter bases diff --git a/Mathlib/Order/Filter/Basic.lean b/Mathlib/Order/Filter/Basic.lean index ee7fd636ed470..65c9595abbf40 100644 --- a/Mathlib/Order/Filter/Basic.lean +++ b/Mathlib/Order/Filter/Basic.lean @@ -3,7 +3,10 @@ Copyright (c) 2017 Johannes Hölzl. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl, Jeremy Avigad -/ -import Mathlib.Data.Set.Finite.Lattice +import Mathlib.Algebra.Group.Basic +import Mathlib.Algebra.Group.Pi.Basic +import Mathlib.Control.Basic +import Mathlib.Data.Set.Lattice import Mathlib.Order.Filter.Defs /-! @@ -59,6 +62,7 @@ we do *not* require. This gives `Filter X` better formal properties, in particul -/ assert_not_exists OrderedSemiring +assert_not_exists Fintype open Function Set Order open scoped symmDiff @@ -103,27 +107,15 @@ theorem congr_sets (h : { x | x ∈ s ↔ x ∈ t } ∈ f) : s ∈ f ↔ t ∈ f lemma copy_eq {S} (hmem : ∀ s, s ∈ S ↔ s ∈ f) : f.copy S hmem = f := Filter.ext hmem -@[simp] -theorem biInter_mem {β : Type v} {s : β → Set α} {is : Set β} (hf : is.Finite) : - (⋂ i ∈ is, s i) ∈ f ↔ ∀ i ∈ is, s i ∈ f := - Finite.induction_on hf (by simp) fun _ _ hs => by simp [hs] - -@[simp] -theorem biInter_finset_mem {β : Type v} {s : β → Set α} (is : Finset β) : - (⋂ i ∈ is, s i) ∈ f ↔ ∀ i ∈ is, s i ∈ f := - biInter_mem is.finite_toSet - -alias _root_.Finset.iInter_mem_sets := biInter_finset_mem +/-- Weaker version of `Filter.biInter_mem` that assumes `Subsingleton β` rather than `Finite β`. -/ +theorem biInter_mem' {β : Type v} {s : β → Set α} {is : Set β} (hf : is.Subsingleton) : + (⋂ i ∈ is, s i) ∈ f ↔ ∀ i ∈ is, s i ∈ f := by + apply Subsingleton.induction_on hf <;> simp --- attribute [protected] Finset.iInter_mem_sets porting note: doesn't work - -@[simp] -theorem sInter_mem {s : Set (Set α)} (hfin : s.Finite) : ⋂₀ s ∈ f ↔ ∀ U ∈ s, U ∈ f := by - rw [sInter_eq_biInter, biInter_mem hfin] - -@[simp] -theorem iInter_mem {β : Sort v} {s : β → Set α} [Finite β] : (⋂ i, s i) ∈ f ↔ ∀ i, s i ∈ f := - (sInter_mem (finite_range _)).trans forall_mem_range +/-- Weaker version of `Filter.iInter_mem` that assumes `Subsingleton β` rather than `Finite β`. -/ +theorem iInter_mem' {β : Sort v} {s : β → Set α} [Subsingleton β] : + (⋂ i, s i) ∈ f ↔ ∀ i, s i ∈ f := by + rw [← sInter_range, sInter_eq_biInter, biInter_mem' (subsingleton_range s), forall_mem_range] theorem exists_mem_subset_iff : (∃ t ∈ f, t ⊆ s) ↔ s ∈ f := ⟨fun ⟨_, ht, ts⟩ => mem_of_superset ht ts, fun hs => ⟨s, hs, Subset.rfl⟩⟩ @@ -181,24 +173,6 @@ theorem le_generate_iff {s : Set (Set α)} {f : Filter α} : f ≤ generate s hu.recOn (fun h' => h h') univ_mem (fun _ hxy hx => mem_of_superset hx hxy) fun _ _ hx hy => inter_mem hx hy -theorem mem_generate_iff {s : Set <| Set α} {U : Set α} : - U ∈ generate s ↔ ∃ t ⊆ s, Set.Finite t ∧ ⋂₀ t ⊆ U := by - constructor <;> intro h - · induction h with - | @basic V V_in => - exact ⟨{V}, singleton_subset_iff.2 V_in, finite_singleton _, (sInter_singleton _).subset⟩ - | univ => exact ⟨∅, empty_subset _, finite_empty, subset_univ _⟩ - | superset _ hVW hV => - rcases hV with ⟨t, hts, ht, htV⟩ - exact ⟨t, hts, ht, htV.trans hVW⟩ - | inter _ _ hV hW => - rcases hV, hW with ⟨⟨t, hts, ht, htV⟩, u, hus, hu, huW⟩ - exact - ⟨t ∪ u, union_subset hts hus, ht.union hu, - (sInter_union _ _).subset.trans <| inter_subset_inter htV huW⟩ - · rcases h with ⟨t, hts, tfin, h⟩ - exact mem_of_superset ((sInter_mem tfin).2 fun V hV => GenerateSets.basic <| hts hV) h - @[simp] lemma generate_singleton (s : Set α) : generate {s} = 𝓟 s := le_antisymm (fun _t ht ↦ mem_of_superset (mem_generate_of_mem <| mem_singleton _) ht) <| le_generate_iff.2 <| singleton_subset_iff.2 Subset.rfl @@ -334,58 +308,6 @@ theorem iInf_eq_generate (s : ι → Filter α) : iInf s = generate (⋃ i, (s i theorem mem_iInf_of_mem {f : ι → Filter α} (i : ι) {s} (hs : s ∈ f i) : s ∈ ⨅ i, f i := 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 : 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 : 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 : I), V i ∈ s i := by - rintro i - have : ⋂₀ σ i ∈ s i := by - rw [sInter_mem (σfin _)] - apply σsub - exact mem_of_superset this subset_union_right - refine ⟨I, Ifin, V, V_in, ?_⟩ - rwa [hV, ← union_iInter, union_eq_self_of_subset_right] - · rintro ⟨I, Ifin, V, V_in, rfl⟩ - exact mem_iInf_of_iInter Ifin V_in Subset.rfl - -theorem mem_iInf' {ι} {s : ι → Filter α} {U : Set α} : - (U ∈ ⨅ i, s i) ↔ - ∃ I : Set ι, I.Finite ∧ ∃ V : ι → Set α, (∀ i, V i ∈ s i) ∧ - (∀ i ∉ I, V i = univ) ∧ (U = ⋂ i ∈ I, V i) ∧ U = ⋂ i, V i := by - classical - simp only [mem_iInf, SetCoe.forall', biInter_eq_iInter] - refine ⟨?_, fun ⟨I, If, V, hVs, _, hVU, _⟩ => ⟨I, If, fun i => V i, fun i => hVs i, hVU⟩⟩ - rintro ⟨I, If, V, hV, rfl⟩ - 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 ⟨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] - -theorem exists_iInter_of_mem_iInf {ι : Type*} {α : Type*} {f : ι → Filter α} {s} - (hs : s ∈ ⨅ i, f i) : ∃ t : ι → Set α, (∀ i, t i ∈ f i) ∧ s = ⋂ i, t i := - let ⟨_, _, V, hVs, _, _, hVU'⟩ := mem_iInf'.1 hs; ⟨V, hVs, hVU'⟩ - -theorem mem_iInf_of_finite {ι : Type*} [Finite ι] {α : Type*} {f : ι → Filter α} (s) : - (s ∈ ⨅ i, f i) ↔ ∃ t : ι → Set α, (∀ i, t i ∈ f i) ∧ s = ⋂ i, t i := by - refine ⟨exists_iInter_of_mem_iInf, ?_⟩ - rintro ⟨t, ht, rfl⟩ - exact iInter_mem.2 fun i => mem_iInf_of_mem i (ht i) - @[simp] theorem le_principal_iff {s : Set α} {f : Filter α} : f ≤ 𝓟 s ↔ s ∈ f := ⟨fun h => h Subset.rfl, fun hs _ ht => mem_of_superset hs ht⟩ @@ -453,26 +375,6 @@ theorem NeBot.not_disjoint (hf : f.NeBot) (hs : s ∈ f) (ht : t ∈ f) : ¬Disj theorem inf_eq_bot_iff {f g : Filter α} : f ⊓ g = ⊥ ↔ ∃ U ∈ f, ∃ V ∈ g, U ∩ V = ∅ := by simp only [← disjoint_iff, Filter.disjoint_iff, Set.disjoint_iff_inter_eq_empty] -theorem _root_.Pairwise.exists_mem_filter_of_disjoint {ι : Type*} [Finite ι] {l : ι → Filter α} - (hd : Pairwise (Disjoint on l)) : - ∃ s : ι → Set α, (∀ i, s i ∈ l i) ∧ Pairwise (Disjoint on s) := by - have : Pairwise fun i j => ∃ (s : {s // s ∈ l i}) (t : {t // t ∈ l j}), Disjoint s.1 t.1 := by - simpa only [Pairwise, Function.onFun, Filter.disjoint_iff, exists_prop, Subtype.exists] using hd - choose! s t hst using this - refine ⟨fun i => ⋂ j, @s i j ∩ @t j i, fun i => ?_, fun i j hij => ?_⟩ - exacts [iInter_mem.2 fun j => inter_mem (@s i j).2 (@t j i).2, - (hst hij).mono ((iInter_subset _ j).trans inter_subset_left) - ((iInter_subset _ i).trans inter_subset_right)] - -theorem _root_.Set.PairwiseDisjoint.exists_mem_filter {ι : Type*} {l : ι → Filter α} {t : Set ι} - (hd : t.PairwiseDisjoint l) (ht : t.Finite) : - ∃ s : ι → Set α, (∀ i, s i ∈ l i) ∧ t.PairwiseDisjoint s := by - haveI := ht.to_subtype - rcases (hd.subtype _ _).exists_mem_filter_of_disjoint with ⟨s, hsl, hsd⟩ - lift s to (i : t) → {s // s ∈ l i} using hsl - rcases @Subtype.exists_pi_extension ι (fun i => { s // s ∈ l i }) _ _ s with ⟨s, rfl⟩ - exact ⟨fun i => s i, fun i => (s i).2, hsd.set_of_subtype _ _⟩ - /-- There is exactly one filter on an empty type. -/ instance unique [IsEmpty α] : Unique (Filter α) where default := ⊥ @@ -548,23 +450,6 @@ theorem biInf_sets_eq {f : β → Filter α} {s : Set β} (h : DirectedOn (f ⁻ (ne : s.Nonempty) : (⨅ i ∈ s, f i).sets = ⋃ i ∈ s, (f i).sets := ext fun t => by simp [mem_biInf_of_directed h ne] -theorem iInf_sets_eq_finite {ι : Type*} (f : ι → Filter α) : - (⨅ i, f i).sets = ⋃ t : Finset ι, (⨅ i ∈ t, f i).sets := by - rw [iInf_eq_iInf_finset, iInf_sets_eq] - exact directed_of_isDirected_le fun _ _ => biInf_mono - -theorem iInf_sets_eq_finite' (f : ι → Filter α) : - (⨅ i, f i).sets = ⋃ t : Finset (PLift ι), (⨅ i ∈ t, f (PLift.down i)).sets := by - rw [← iInf_sets_eq_finite, ← Equiv.plift.surjective.iInf_comp, Equiv.plift_apply] - -theorem mem_iInf_finite {ι : Type*} {f : ι → Filter α} (s) : - s ∈ iInf f ↔ ∃ t : Finset ι, s ∈ ⨅ i ∈ t, f i := - (Set.ext_iff.1 (iInf_sets_eq_finite f) s).trans mem_iUnion - -theorem mem_iInf_finite' {f : ι → Filter α} (s) : - s ∈ iInf f ↔ ∃ t : Finset (PLift ι), s ∈ ⨅ i ∈ t, f (PLift.down i) := - (Set.ext_iff.1 (iInf_sets_eq_finite' f) s).trans mem_iUnion - @[simp] theorem sup_join {f₁ f₂ : Filter (Filter α)} : join f₁ ⊔ join f₂ = join (f₁ ⊔ f₂) := Filter.ext fun x => by simp only [mem_sup, mem_join] @@ -583,38 +468,6 @@ instance : DistribLattice (Filter α) := ⟨t₁, x.sets_of_superset hs inter_subset_left, ht₁, t₂, x.sets_of_superset hs inter_subset_right, ht₂, rfl⟩ } -/-- The dual version does not hold! `Filter α` is not a `CompleteDistribLattice`. -/ --- See note [reducible non-instances] -abbrev coframeMinimalAxioms : Coframe.MinimalAxioms (Filter α) := - { Filter.instCompleteLatticeFilter with - iInf_sup_le_sup_sInf := fun f s t ⟨h₁, h₂⟩ => by - classical - rw [iInf_subtype'] - rw [sInf_eq_iInf', ← Filter.mem_sets, iInf_sets_eq_finite, mem_iUnion] at h₂ - obtain ⟨u, hu⟩ := h₂ - rw [← Finset.inf_eq_iInf] at hu - suffices ⨅ i : s, f ⊔ ↑i ≤ f ⊔ u.inf fun i => ↑i from this ⟨h₁, hu⟩ - refine Finset.induction_on u (le_sup_of_le_right le_top) ?_ - rintro ⟨i⟩ u _ ih - rw [Finset.inf_insert, sup_inf_left] - exact le_inf (iInf_le _ _) ih } - -instance instCoframe : Coframe (Filter α) := .ofMinimalAxioms coframeMinimalAxioms - -theorem mem_iInf_finset {s : Finset α} {f : α → Filter β} {t : Set β} : - (t ∈ ⨅ a ∈ s, f a) ↔ ∃ p : α → Set β, (∀ a ∈ s, p a ∈ f a) ∧ t = ⋂ a ∈ s, p a := by - classical - simp only [← Finset.set_biInter_coe, biInter_eq_iInter, iInf_subtype'] - refine ⟨fun h => ?_, ?_⟩ - · rcases (mem_iInf_of_finite _).1 h with ⟨p, hp, rfl⟩ - refine ⟨fun a => if h : a ∈ s then p ⟨a, h⟩ else univ, - fun a ha => by simpa [ha] using hp ⟨a, ha⟩, ?_⟩ - refine iInter_congr_of_surjective id surjective_id ?_ - rintro ⟨a, ha⟩ - simp [ha] - · rintro ⟨p, hpf, rfl⟩ - exact iInter_mem.2 fun a => mem_iInf_of_mem a (hpf a a.2) - /-- If `f : ι → Filter α` is directed, `ι` is not empty, and `∀ i, f i ≠ ⊥`, then `iInf f ≠ ⊥`. See also `iInf_neBot_of_directed` for a version assuming `Nonempty α` instead of `Nonempty ι`. -/ theorem iInf_neBot_of_directed' {f : ι → Filter α} [Nonempty ι] (hd : Directed (· ≥ ·) f) : @@ -650,20 +503,6 @@ theorem iInf_neBot_iff_of_directed {f : ι → Filter α} [Nonempty α] (hd : Di NeBot (iInf f) ↔ ∀ i, NeBot (f i) := ⟨fun H i => H.mono (iInf_le _ i), iInf_neBot_of_directed hd⟩ -@[elab_as_elim] -theorem iInf_sets_induct {f : ι → Filter α} {s : Set α} (hs : s ∈ iInf f) {p : Set α → Prop} - (uni : p univ) (ins : ∀ {i s₁ s₂}, s₁ ∈ f i → p s₂ → p (s₁ ∩ s₂)) : p s := by - classical - rw [mem_iInf_finite'] at hs - simp only [← Finset.inf_eq_iInf] at hs - rcases hs with ⟨is, his⟩ - induction is using Finset.induction_on generalizing s with - | empty => rwa [mem_top.1 his] - | insert _ ih => - rw [Finset.inf_insert, mem_inf_iff] at his - rcases his with ⟨s₁, hs₁, s₂, hs₂, rfl⟩ - exact ins hs₁ (ih hs₂) - /-! #### `principal` equations -/ @[simp] @@ -719,29 +558,6 @@ theorem diff_mem_inf_principal_compl {f : Filter α} {s : Set α} (hs : s ∈ f) theorem principal_le_iff {s : Set α} {f : Filter α} : 𝓟 s ≤ f ↔ ∀ V ∈ f, s ⊆ V := by simp_rw [le_def, mem_principal] -@[simp] -theorem iInf_principal_finset {ι : Type w} (s : Finset ι) (f : ι → Set α) : - ⨅ i ∈ s, 𝓟 (f i) = 𝓟 (⋂ i ∈ s, f i) := by - classical - induction' s using Finset.induction_on with i s _ hs - · simp - · rw [Finset.iInf_insert, Finset.set_biInter_insert, hs, inf_principal] - -theorem iInf_principal {ι : Sort w} [Finite ι] (f : ι → Set α) : ⨅ i, 𝓟 (f i) = 𝓟 (⋂ i, f i) := by - cases nonempty_fintype (PLift ι) - rw [← iInf_plift_down, ← iInter_plift_down] - simpa using iInf_principal_finset Finset.univ (f <| PLift.down ·) - -/-- A special case of `iInf_principal` that is safe to mark `simp`. -/ -@[simp] -theorem iInf_principal' {ι : Type w} [Finite ι] (f : ι → Set α) : ⨅ i, 𝓟 (f i) = 𝓟 (⋂ i, f i) := - iInf_principal _ - -theorem iInf_principal_finite {ι : Type w} {s : Set ι} (hs : s.Finite) (f : ι → Set α) : - ⨅ i ∈ s, 𝓟 (f i) = 𝓟 (⋂ i ∈ s, f i) := by - lift s to Finset ι using hs - exact mod_cast iInf_principal_finset s f - end Lattice @[mono, gcongr] @@ -820,28 +636,6 @@ theorem eventually_congr {f : Filter α} {p q : α → Prop} (h : ∀ᶠ x in f, (∀ᶠ x in f, p x) ↔ ∀ᶠ x in f, q x := ⟨fun hp => hp.congr h, fun hq => hq.congr <| by simpa only [Iff.comm] using h⟩ -@[simp] -theorem eventually_all {ι : Sort*} [Finite ι] {l} {p : ι → α → Prop} : - (∀ᶠ x in l, ∀ i, p i x) ↔ ∀ i, ∀ᶠ x in l, p i x := by - simpa only [Filter.Eventually, setOf_forall] using iInter_mem - -@[simp] -theorem eventually_all_finite {ι} {I : Set ι} (hI : I.Finite) {l} {p : ι → α → Prop} : - (∀ᶠ x in l, ∀ i ∈ I, p i x) ↔ ∀ i ∈ I, ∀ᶠ x in l, p i x := by - simpa only [Filter.Eventually, setOf_forall] using biInter_mem hI - -alias _root_.Set.Finite.eventually_all := eventually_all_finite - --- attribute [protected] Set.Finite.eventually_all - -@[simp] theorem eventually_all_finset {ι} (I : Finset ι) {l} {p : ι → α → Prop} : - (∀ᶠ x in l, ∀ i ∈ I, p i x) ↔ ∀ i ∈ I, ∀ᶠ x in l, p i x := - I.finite_toSet.eventually_all - -alias _root_.Finset.eventually_all := eventually_all_finset - --- attribute [protected] Finset.eventually_all - @[simp] theorem eventually_or_distrib_left {f : Filter α} {p : Prop} {q : α → Prop} : (∀ᶠ x in f, p ∨ q x) ↔ p ∨ ∀ᶠ x in f, q x := @@ -852,10 +646,6 @@ theorem eventually_or_distrib_right {f : Filter α} {p : α → Prop} {q : Prop} (∀ᶠ x in f, p x ∨ q) ↔ (∀ᶠ x in f, p x) ∨ q := by simp only [@or_comm _ q, eventually_or_distrib_left] -theorem eventually_imp_distrib_left {f : Filter α} {p : Prop} {q : α → Prop} : - (∀ᶠ x in f, p → q x) ↔ p → ∀ᶠ x in f, q x := - eventually_all - @[simp] theorem eventually_bot {p : α → Prop} : ∀ᶠ x in ⊥, p x := ⟨⟩ @@ -895,6 +685,11 @@ theorem eventually_inf_principal {f : Filter α} {p : α → Prop} {s : Set α} (∀ᶠ x in f ⊓ 𝓟 s, p x) ↔ ∀ᶠ x in f, x ∈ s → p x := mem_inf_principal +theorem eventually_iff_all_subsets {f : Filter α} {p : α → Prop} : + (∀ᶠ x in f, p x) ↔ ∀ (s : Set α), ∀ᶠ x in f, x ∈ s → p x where + mp h _ := by filter_upwards [h] with _ pa _ using pa + mpr h := by filter_upwards [h univ] with _ pa using pa (by simp) + /-! ### Frequently -/ theorem Eventually.frequently {f : Filter α} [NeBot f] {p : α → Prop} (h : ∀ᶠ x in f, p x) : @@ -1003,16 +798,6 @@ theorem eventually_imp_distrib_right {f : Filter α} {p : α → Prop} {q : Prop (∀ᶠ x in f, p x → q) ↔ (∃ᶠ x in f, p x) → q := by simp only [imp_iff_not_or, eventually_or_distrib_right, not_frequently] -@[simp] -theorem frequently_and_distrib_left {f : Filter α} {p : Prop} {q : α → Prop} : - (∃ᶠ x in f, p ∧ q x) ↔ p ∧ ∃ᶠ x in f, q x := by - simp only [Filter.Frequently, not_and, eventually_imp_distrib_left, Classical.not_imp] - -@[simp] -theorem frequently_and_distrib_right {f : Filter α} {p : α → Prop} {q : Prop} : - (∃ᶠ x in f, p x ∧ q) ↔ (∃ᶠ x in f, p x) ∧ q := by - simp only [@and_comm _ q, frequently_and_distrib_left] - @[simp] theorem frequently_bot {p : α → Prop} : ¬∃ᶠ x in ⊥, p x := by simp @@ -1224,6 +1009,10 @@ theorem eventuallyEq_iff_sub [AddGroup β] {f g : α → β} {l : Filter α} : f =ᶠ[l] g ↔ f - g =ᶠ[l] 0 := ⟨fun h => h.sub_eq, fun h => by simpa using h.add (EventuallyEq.refl l g)⟩ +theorem eventuallyEq_iff_all_subsets {f g : α → β} {l : Filter α} : + f =ᶠ[l] g ↔ ∀ s : Set α, ∀ᶠ x in l, x ∈ s → f x = g x := + eventually_iff_all_subsets + section LE variable [LE β] {l : Filter α} @@ -1236,6 +1025,10 @@ theorem eventuallyLE_congr {f f' g g' : α → β} (hf : f =ᶠ[l] f') (hg : g = f ≤ᶠ[l] g ↔ f' ≤ᶠ[l] g' := ⟨fun H => H.congr hf hg, fun H => H.congr hf.symm hg.symm⟩ +theorem eventuallyLE_iff_all_subsets {f g : α → β} {l : Filter α} : + f ≤ᶠ[l] g ↔ ∀ s : Set α, ∀ᶠ x in l, x ∈ s → f x ≤ g x := + eventually_iff_all_subsets + end LE section Preorder @@ -1315,69 +1108,6 @@ theorem EventuallyLE.union {s t s' t' : Set α} {l : Filter α} (h : s ≤ᶠ[l] (s ∪ s' : Set α) ≤ᶠ[l] (t ∪ t' : Set α) := h'.mp <| h.mono fun _ => Or.imp -protected lemma EventuallyLE.iUnion [Finite ι] {s t : ι → Set α} - (h : ∀ i, s i ≤ᶠ[l] t i) : (⋃ i, s i) ≤ᶠ[l] ⋃ i, t i := - (eventually_all.2 h).mono fun _x hx hx' ↦ - let ⟨i, hi⟩ := mem_iUnion.1 hx'; mem_iUnion.2 ⟨i, hx i hi⟩ - -protected lemma EventuallyEq.iUnion [Finite ι] {s t : ι → Set α} - (h : ∀ i, s i =ᶠ[l] t i) : (⋃ i, s i) =ᶠ[l] ⋃ i, t i := - (EventuallyLE.iUnion fun i ↦ (h i).le).antisymm <| .iUnion fun i ↦ (h i).symm.le - -protected lemma EventuallyLE.iInter [Finite ι] {s t : ι → Set α} - (h : ∀ i, s i ≤ᶠ[l] t i) : (⋂ i, s i) ≤ᶠ[l] ⋂ i, t i := - (eventually_all.2 h).mono fun _x hx hx' ↦ mem_iInter.2 fun i ↦ hx i (mem_iInter.1 hx' i) - -protected lemma EventuallyEq.iInter [Finite ι] {s t : ι → Set α} - (h : ∀ i, s i =ᶠ[l] t i) : (⋂ i, s i) =ᶠ[l] ⋂ i, t i := - (EventuallyLE.iInter fun i ↦ (h i).le).antisymm <| .iInter fun i ↦ (h i).symm.le - -lemma _root_.Set.Finite.eventuallyLE_iUnion {ι : Type*} {s : Set ι} (hs : s.Finite) - {f g : ι → Set α} (hle : ∀ i ∈ s, f i ≤ᶠ[l] g i) : (⋃ i ∈ s, f i) ≤ᶠ[l] (⋃ i ∈ s, g i) := by - have := hs.to_subtype - rw [biUnion_eq_iUnion, biUnion_eq_iUnion] - exact .iUnion fun i ↦ hle i.1 i.2 - -alias EventuallyLE.biUnion := Set.Finite.eventuallyLE_iUnion - -lemma _root_.Set.Finite.eventuallyEq_iUnion {ι : Type*} {s : Set ι} (hs : s.Finite) - {f g : ι → Set α} (heq : ∀ i ∈ s, f i =ᶠ[l] g i) : (⋃ i ∈ s, f i) =ᶠ[l] (⋃ i ∈ s, g i) := - (EventuallyLE.biUnion hs fun i hi ↦ (heq i hi).le).antisymm <| - .biUnion hs fun i hi ↦ (heq i hi).symm.le - -alias EventuallyEq.biUnion := Set.Finite.eventuallyEq_iUnion - -lemma _root_.Set.Finite.eventuallyLE_iInter {ι : Type*} {s : Set ι} (hs : s.Finite) - {f g : ι → Set α} (hle : ∀ i ∈ s, f i ≤ᶠ[l] g i) : (⋂ i ∈ s, f i) ≤ᶠ[l] (⋂ i ∈ s, g i) := by - have := hs.to_subtype - rw [biInter_eq_iInter, biInter_eq_iInter] - exact .iInter fun i ↦ hle i.1 i.2 - -alias EventuallyLE.biInter := Set.Finite.eventuallyLE_iInter - -lemma _root_.Set.Finite.eventuallyEq_iInter {ι : Type*} {s : Set ι} (hs : s.Finite) - {f g : ι → Set α} (heq : ∀ i ∈ s, f i =ᶠ[l] g i) : (⋂ i ∈ s, f i) =ᶠ[l] (⋂ i ∈ s, g i) := - (EventuallyLE.biInter hs fun i hi ↦ (heq i hi).le).antisymm <| - .biInter hs fun i hi ↦ (heq i hi).symm.le - -alias EventuallyEq.biInter := Set.Finite.eventuallyEq_iInter - -lemma _root_.Finset.eventuallyLE_iUnion {ι : Type*} (s : Finset ι) {f g : ι → Set α} - (hle : ∀ i ∈ s, f i ≤ᶠ[l] g i) : (⋃ i ∈ s, f i) ≤ᶠ[l] (⋃ i ∈ s, g i) := - .biUnion s.finite_toSet hle - -lemma _root_.Finset.eventuallyEq_iUnion {ι : Type*} (s : Finset ι) {f g : ι → Set α} - (heq : ∀ i ∈ s, f i =ᶠ[l] g i) : (⋃ i ∈ s, f i) =ᶠ[l] (⋃ i ∈ s, g i) := - .biUnion s.finite_toSet heq - -lemma _root_.Finset.eventuallyLE_iInter {ι : Type*} (s : Finset ι) {f g : ι → Set α} - (hle : ∀ i ∈ s, f i ≤ᶠ[l] g i) : (⋂ i ∈ s, f i) ≤ᶠ[l] (⋂ i ∈ s, g i) := - .biInter s.finite_toSet hle - -lemma _root_.Finset.eventuallyEq_iInter {ι : Type*} (s : Finset ι) {f g : ι → Set α} - (heq : ∀ i ∈ s, f i =ᶠ[l] g i) : (⋂ i ∈ s, f i) =ᶠ[l] (⋂ i ∈ s, g i) := - .biInter s.finite_toSet heq - @[mono] theorem EventuallyLE.compl {s t : Set α} {l : Filter α} (h : s ≤ᶠ[l] t) : (tᶜ : Set α) ≤ᶠ[l] (sᶜ : Set α) := @@ -2359,4 +2089,4 @@ lemma compl_mem_comk {p : Set α → Prop} {he hmono hunion s} : end Filter -set_option linter.style.longFile 2500 +set_option linter.style.longFile 2200 diff --git a/Mathlib/Order/Filter/CardinalInter.lean b/Mathlib/Order/Filter/CardinalInter.lean index 22967d8a816b3..9a1e5bb744169 100644 --- a/Mathlib/Order/Filter/CardinalInter.lean +++ b/Mathlib/Order/Filter/CardinalInter.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Josha Dekker -/ import Mathlib.Order.Filter.Tendsto +import Mathlib.Order.Filter.Finite import Mathlib.Order.Filter.CountableInter import Mathlib.SetTheory.Cardinal.Arithmetic import Mathlib.SetTheory.Cardinal.Cofinality diff --git a/Mathlib/Order/Filter/Cocardinal.lean b/Mathlib/Order/Filter/Cocardinal.lean index 25e10e20a8fa3..d3da9a3ef6505 100644 --- a/Mathlib/Order/Filter/Cocardinal.lean +++ b/Mathlib/Order/Filter/Cocardinal.lean @@ -8,7 +8,6 @@ import Mathlib.Order.Filter.CountableInter import Mathlib.Order.Filter.CardinalInter import Mathlib.SetTheory.Cardinal.Arithmetic import Mathlib.SetTheory.Cardinal.Cofinality -import Mathlib.Order.Filter.Bases /-! # The cocardinal filter diff --git a/Mathlib/Order/Filter/CountableSeparatingOn.lean b/Mathlib/Order/Filter/CountableSeparatingOn.lean index b1f268cda8419..552a128f17bc5 100644 --- a/Mathlib/Order/Filter/CountableSeparatingOn.lean +++ b/Mathlib/Order/Filter/CountableSeparatingOn.lean @@ -167,7 +167,7 @@ theorem exists_subset_subsingleton_mem_of_forall_separating (p : Set α → Prop | inr hsl => simp only [hx.2 s hsS hsl, hy.2 s hsS hsl] · exact inter_mem (inter_mem hs ((countable_sInter_mem (hSc.mono inter_subset_left)).2 fun _ h ↦ h.2)) - ((countable_bInter_mem hSc).2 fun U hU ↦ iInter_mem.2 id) + ((countable_bInter_mem hSc).2 fun U hU ↦ iInter_mem'.2 id) theorem exists_mem_singleton_mem_of_mem_of_nonempty_of_forall_separating (p : Set α → Prop) {s : Set α} [HasCountableSeparatingOn α p s] (hs : s ∈ l) (hne : s.Nonempty) diff --git a/Mathlib/Order/Filter/Defs.lean b/Mathlib/Order/Filter/Defs.lean index f03e4c29d0296..d0a00823afb8a 100644 --- a/Mathlib/Order/Filter/Defs.lean +++ b/Mathlib/Order/Filter/Defs.lean @@ -32,6 +32,11 @@ abstract two related kinds of ideas: a tactic that takes a list of proofs `hᵢ : sᵢ ∈ f`, and replaces a goal `s ∈ f` with `∀ x, x ∈ s₁ → ... → x ∈ sₙ → x ∈ s`; * `Filter.NeBot f` : a utility class stating that `f` is a non-trivial filter. +* `Filter.IsBounded r f`: the filter `f` is eventually bounded w.r.t. the relation `r`, + i.e. eventually, it is bounded by some uniform bound. + `r` will be usually instantiated with `(· ≤ ·)` or `(· ≥ ·)`. +* `Filter.IsCobounded r f` states that the filter `f` does not tend to infinity w.r.t. `r`. + This is also called frequently bounded. Will be usually instantiated with `(· ≤ ·)` or `(· ≥ ·)`. ## Notations @@ -350,6 +355,36 @@ This is essentially a push-forward along a function mapping each set to a set. - protected def lift' (f : Filter α) (h : Set α → Set β) := f.lift (𝓟 ∘ h) +/-- `f.IsBounded r`: the filter `f` is eventually bounded w.r.t. the relation `r`, +i.e. eventually, it is bounded by some uniform bound. +`r` will be usually instantiated with `(· ≤ ·)` or `(· ≥ ·)`. -/ +def IsBounded (r : α → α → Prop) (f : Filter α) := + ∃ b, ∀ᶠ x in f, r x b + +/-- `f.IsBoundedUnder (≺) u`: the image of the filter `f` under `u` is eventually bounded w.r.t. +the relation `≺`, i.e. eventually, it is bounded by some uniform bound. -/ +def IsBoundedUnder (r : α → α → Prop) (f : Filter β) (u : β → α) := + (map u f).IsBounded r + +/-- `IsCobounded (≺) f` states that the filter `f` does not tend to infinity w.r.t. `≺`. This is +also called frequently bounded. Will be usually instantiated with `≤` or `≥`. + +There is a subtlety in this definition: we want `f.IsCobounded` to hold for any `f` in the case of +complete lattices. This will be relevant to deduce theorems on complete lattices from their +versions on conditionally complete lattices with additional assumptions. We have to be careful in +the edge case of the trivial filter containing the empty set: the other natural definition + `¬ ∀ a, ∀ᶠ n in f, a ≤ n` +would not work as well in this case. +-/ +def IsCobounded (r : α → α → Prop) (f : Filter α) := + ∃ b, ∀ a, (∀ᶠ x in f, r x a) → r b a + +/-- `IsCoboundedUnder (≺) f u` states that the image of the filter `f` under the map `u` does not +tend to infinity w.r.t. `≺`. This is also called frequently bounded. Will be usually instantiated +with `≤` or `≥`. -/ +def IsCoboundedUnder (r : α → α → Prop) (f : Filter β) (u : β → α) := + (map u f).IsCobounded r + end Filter namespace Mathlib.Tactic diff --git a/Mathlib/Order/Filter/Extr.lean b/Mathlib/Order/Filter/Extr.lean index ba1e7c93d0896..5f405e77557b1 100644 --- a/Mathlib/Order/Filter/Extr.lean +++ b/Mathlib/Order/Filter/Extr.lean @@ -6,6 +6,7 @@ Authors: Yury Kudryashov import Mathlib.Order.Filter.Tendsto import Mathlib.Order.ConditionallyCompleteLattice.Indexed import Mathlib.Algebra.Order.Group.Defs +import Mathlib.Data.Finset.Lattice.Fold /-! # Minimum and maximum w.r.t. a filter and on a set diff --git a/Mathlib/Order/Filter/Finite.lean b/Mathlib/Order/Filter/Finite.lean new file mode 100644 index 0000000000000..2c96231b9a89f --- /dev/null +++ b/Mathlib/Order/Filter/Finite.lean @@ -0,0 +1,359 @@ +/- +Copyright (c) 2017 Johannes Hölzl. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Johannes Hölzl, Jeremy Avigad +-/ +import Mathlib.Data.Set.Finite.Lattice +import Mathlib.Order.Filter.Basic + +/-! +# Results filters related to finiteness. + +-/ + + + +open Function Set Order +open scoped symmDiff + +universe u v w x y + +namespace Filter + +variable {α : Type u} {f g : Filter α} {s t : Set α} + +@[simp] +theorem biInter_mem {β : Type v} {s : β → Set α} {is : Set β} (hf : is.Finite) : + (⋂ i ∈ is, s i) ∈ f ↔ ∀ i ∈ is, s i ∈ f := + Finite.induction_on hf (by simp) fun _ _ hs => by simp [hs] + +@[simp] +theorem biInter_finset_mem {β : Type v} {s : β → Set α} (is : Finset β) : + (⋂ i ∈ is, s i) ∈ f ↔ ∀ i ∈ is, s i ∈ f := + biInter_mem is.finite_toSet + +alias _root_.Finset.iInter_mem_sets := biInter_finset_mem + +-- attribute [protected] Finset.iInter_mem_sets porting note: doesn't work + +@[simp] +theorem sInter_mem {s : Set (Set α)} (hfin : s.Finite) : ⋂₀ s ∈ f ↔ ∀ U ∈ s, U ∈ f := by + rw [sInter_eq_biInter, biInter_mem hfin] + +@[simp] +theorem iInter_mem {β : Sort v} {s : β → Set α} [Finite β] : (⋂ i, s i) ∈ f ↔ ∀ i, s i ∈ f := + (sInter_mem (finite_range _)).trans forall_mem_range + +end Filter + + +namespace Filter + +variable {α : Type u} {β : Type v} {γ : Type w} {δ : Type*} {ι : Sort x} + +section Lattice + +variable {f g : Filter α} {s t : Set α} + +theorem mem_generate_iff {s : Set <| Set α} {U : Set α} : + U ∈ generate s ↔ ∃ t ⊆ s, Set.Finite t ∧ ⋂₀ t ⊆ U := by + constructor <;> intro h + · induction h with + | @basic V V_in => + exact ⟨{V}, singleton_subset_iff.2 V_in, finite_singleton _, (sInter_singleton _).subset⟩ + | univ => exact ⟨∅, empty_subset _, finite_empty, subset_univ _⟩ + | superset _ hVW hV => + rcases hV with ⟨t, hts, ht, htV⟩ + exact ⟨t, hts, ht, htV.trans hVW⟩ + | inter _ _ hV hW => + rcases hV, hW with ⟨⟨t, hts, ht, htV⟩, u, hus, hu, huW⟩ + exact + ⟨t ∪ u, union_subset hts hus, ht.union hu, + (sInter_union _ _).subset.trans <| inter_subset_inter htV huW⟩ + · rcases h with ⟨t, hts, tfin, h⟩ + exact mem_of_superset ((sInter_mem tfin).2 fun V hV => GenerateSets.basic <| hts hV) h + +theorem mem_iInf_of_iInter {ι} {s : ι → Filter α} {U : Set α} {I : Set ι} (I_fin : I.Finite) + {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 : 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 : I), V i ∈ s i := by + rintro i + have : ⋂₀ σ i ∈ s i := by + rw [sInter_mem (σfin _)] + apply σsub + exact mem_of_superset this subset_union_right + refine ⟨I, Ifin, V, V_in, ?_⟩ + rwa [hV, ← union_iInter, union_eq_self_of_subset_right] + · rintro ⟨I, Ifin, V, V_in, rfl⟩ + exact mem_iInf_of_iInter Ifin V_in Subset.rfl + +theorem mem_iInf' {ι} {s : ι → Filter α} {U : Set α} : + (U ∈ ⨅ i, s i) ↔ + ∃ I : Set ι, I.Finite ∧ ∃ V : ι → Set α, (∀ i, V i ∈ s i) ∧ + (∀ i ∉ I, V i = univ) ∧ (U = ⋂ i ∈ I, V i) ∧ U = ⋂ i, V i := by + classical + simp only [mem_iInf, SetCoe.forall', biInter_eq_iInter] + refine ⟨?_, fun ⟨I, If, V, hVs, _, hVU, _⟩ => ⟨I, If, fun i => V i, fun i => hVs i, hVU⟩⟩ + rintro ⟨I, If, V, hV, rfl⟩ + 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 ⟨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] + +theorem exists_iInter_of_mem_iInf {ι : Type*} {α : Type*} {f : ι → Filter α} {s} + (hs : s ∈ ⨅ i, f i) : ∃ t : ι → Set α, (∀ i, t i ∈ f i) ∧ s = ⋂ i, t i := + let ⟨_, _, V, hVs, _, _, hVU'⟩ := mem_iInf'.1 hs; ⟨V, hVs, hVU'⟩ + +theorem mem_iInf_of_finite {ι : Type*} [Finite ι] {α : Type*} {f : ι → Filter α} (s) : + (s ∈ ⨅ i, f i) ↔ ∃ t : ι → Set α, (∀ i, t i ∈ f i) ∧ s = ⋂ i, t i := by + refine ⟨exists_iInter_of_mem_iInf, ?_⟩ + rintro ⟨t, ht, rfl⟩ + exact iInter_mem.2 fun i => mem_iInf_of_mem i (ht i) + +/-! ### Lattice equations -/ + +theorem _root_.Pairwise.exists_mem_filter_of_disjoint {ι : Type*} [Finite ι] {l : ι → Filter α} + (hd : Pairwise (Disjoint on l)) : + ∃ s : ι → Set α, (∀ i, s i ∈ l i) ∧ Pairwise (Disjoint on s) := by + have : Pairwise fun i j => ∃ (s : {s // s ∈ l i}) (t : {t // t ∈ l j}), Disjoint s.1 t.1 := by + simpa only [Pairwise, Function.onFun, Filter.disjoint_iff, exists_prop, Subtype.exists] using hd + choose! s t hst using this + refine ⟨fun i => ⋂ j, @s i j ∩ @t j i, fun i => ?_, fun i j hij => ?_⟩ + exacts [iInter_mem.2 fun j => inter_mem (@s i j).2 (@t j i).2, + (hst hij).mono ((iInter_subset _ j).trans inter_subset_left) + ((iInter_subset _ i).trans inter_subset_right)] + +theorem _root_.Set.PairwiseDisjoint.exists_mem_filter {ι : Type*} {l : ι → Filter α} {t : Set ι} + (hd : t.PairwiseDisjoint l) (ht : t.Finite) : + ∃ s : ι → Set α, (∀ i, s i ∈ l i) ∧ t.PairwiseDisjoint s := by + haveI := ht.to_subtype + rcases (hd.subtype _ _).exists_mem_filter_of_disjoint with ⟨s, hsl, hsd⟩ + lift s to (i : t) → {s // s ∈ l i} using hsl + rcases @Subtype.exists_pi_extension ι (fun i => { s // s ∈ l i }) _ _ s with ⟨s, rfl⟩ + exact ⟨fun i => s i, fun i => (s i).2, hsd.set_of_subtype _ _⟩ + + +theorem iInf_sets_eq_finite {ι : Type*} (f : ι → Filter α) : + (⨅ i, f i).sets = ⋃ t : Finset ι, (⨅ i ∈ t, f i).sets := by + rw [iInf_eq_iInf_finset, iInf_sets_eq] + exact directed_of_isDirected_le fun _ _ => biInf_mono + +theorem iInf_sets_eq_finite' (f : ι → Filter α) : + (⨅ i, f i).sets = ⋃ t : Finset (PLift ι), (⨅ i ∈ t, f (PLift.down i)).sets := by + rw [← iInf_sets_eq_finite, ← Equiv.plift.surjective.iInf_comp, Equiv.plift_apply] + +theorem mem_iInf_finite {ι : Type*} {f : ι → Filter α} (s) : + s ∈ iInf f ↔ ∃ t : Finset ι, s ∈ ⨅ i ∈ t, f i := + (Set.ext_iff.1 (iInf_sets_eq_finite f) s).trans mem_iUnion + +theorem mem_iInf_finite' {f : ι → Filter α} (s) : + s ∈ iInf f ↔ ∃ t : Finset (PLift ι), s ∈ ⨅ i ∈ t, f (PLift.down i) := + (Set.ext_iff.1 (iInf_sets_eq_finite' f) s).trans mem_iUnion + +/-- The dual version does not hold! `Filter α` is not a `CompleteDistribLattice`. -/ +-- See note [reducible non-instances] +abbrev coframeMinimalAxioms : Coframe.MinimalAxioms (Filter α) := + { Filter.instCompleteLatticeFilter with + iInf_sup_le_sup_sInf := fun f s t ⟨h₁, h₂⟩ => by + classical + rw [iInf_subtype'] + rw [sInf_eq_iInf', ← Filter.mem_sets, iInf_sets_eq_finite, mem_iUnion] at h₂ + obtain ⟨u, hu⟩ := h₂ + rw [← Finset.inf_eq_iInf] at hu + suffices ⨅ i : s, f ⊔ ↑i ≤ f ⊔ u.inf fun i => ↑i from this ⟨h₁, hu⟩ + refine Finset.induction_on u (le_sup_of_le_right le_top) ?_ + rintro ⟨i⟩ u _ ih + rw [Finset.inf_insert, sup_inf_left] + exact le_inf (iInf_le _ _) ih } + +instance instCoframe : Coframe (Filter α) := .ofMinimalAxioms coframeMinimalAxioms + +theorem mem_iInf_finset {s : Finset α} {f : α → Filter β} {t : Set β} : + (t ∈ ⨅ a ∈ s, f a) ↔ ∃ p : α → Set β, (∀ a ∈ s, p a ∈ f a) ∧ t = ⋂ a ∈ s, p a := by + classical + simp only [← Finset.set_biInter_coe, biInter_eq_iInter, iInf_subtype'] + refine ⟨fun h => ?_, ?_⟩ + · rcases (mem_iInf_of_finite _).1 h with ⟨p, hp, rfl⟩ + refine ⟨fun a => if h : a ∈ s then p ⟨a, h⟩ else univ, + fun a ha => by simpa [ha] using hp ⟨a, ha⟩, ?_⟩ + refine iInter_congr_of_surjective id surjective_id ?_ + rintro ⟨a, ha⟩ + simp [ha] + · rintro ⟨p, hpf, rfl⟩ + exact iInter_mem.2 fun a => mem_iInf_of_mem a (hpf a a.2) + + +@[elab_as_elim] +theorem iInf_sets_induct {f : ι → Filter α} {s : Set α} (hs : s ∈ iInf f) {p : Set α → Prop} + (uni : p univ) (ins : ∀ {i s₁ s₂}, s₁ ∈ f i → p s₂ → p (s₁ ∩ s₂)) : p s := by + classical + rw [mem_iInf_finite'] at hs + simp only [← Finset.inf_eq_iInf] at hs + rcases hs with ⟨is, his⟩ + induction is using Finset.induction_on generalizing s with + | empty => rwa [mem_top.1 his] + | insert _ ih => + rw [Finset.inf_insert, mem_inf_iff] at his + rcases his with ⟨s₁, hs₁, s₂, hs₂, rfl⟩ + exact ins hs₁ (ih hs₂) + +/-! #### `principal` equations -/ + +@[simp] +theorem iInf_principal_finset {ι : Type w} (s : Finset ι) (f : ι → Set α) : + ⨅ i ∈ s, 𝓟 (f i) = 𝓟 (⋂ i ∈ s, f i) := by + classical + induction' s using Finset.induction_on with i s _ hs + · simp + · rw [Finset.iInf_insert, Finset.set_biInter_insert, hs, inf_principal] + +theorem iInf_principal {ι : Sort w} [Finite ι] (f : ι → Set α) : ⨅ i, 𝓟 (f i) = 𝓟 (⋂ i, f i) := by + cases nonempty_fintype (PLift ι) + rw [← iInf_plift_down, ← iInter_plift_down] + simpa using iInf_principal_finset Finset.univ (f <| PLift.down ·) + +/-- A special case of `iInf_principal` that is safe to mark `simp`. -/ +@[simp] +theorem iInf_principal' {ι : Type w} [Finite ι] (f : ι → Set α) : ⨅ i, 𝓟 (f i) = 𝓟 (⋂ i, f i) := + iInf_principal _ + +theorem iInf_principal_finite {ι : Type w} {s : Set ι} (hs : s.Finite) (f : ι → Set α) : + ⨅ i ∈ s, 𝓟 (f i) = 𝓟 (⋂ i ∈ s, f i) := by + lift s to Finset ι using hs + exact mod_cast iInf_principal_finset s f + +end Lattice + +/-! ### Eventually -/ + +@[simp] +theorem eventually_all {ι : Sort*} [Finite ι] {l} {p : ι → α → Prop} : + (∀ᶠ x in l, ∀ i, p i x) ↔ ∀ i, ∀ᶠ x in l, p i x := by + simpa only [Filter.Eventually, setOf_forall] using iInter_mem + +@[simp] +theorem eventually_all_finite {ι} {I : Set ι} (hI : I.Finite) {l} {p : ι → α → Prop} : + (∀ᶠ x in l, ∀ i ∈ I, p i x) ↔ ∀ i ∈ I, ∀ᶠ x in l, p i x := by + simpa only [Filter.Eventually, setOf_forall] using biInter_mem hI + +alias _root_.Set.Finite.eventually_all := eventually_all_finite + +-- attribute [protected] Set.Finite.eventually_all + +@[simp] theorem eventually_all_finset {ι} (I : Finset ι) {l} {p : ι → α → Prop} : + (∀ᶠ x in l, ∀ i ∈ I, p i x) ↔ ∀ i ∈ I, ∀ᶠ x in l, p i x := + I.finite_toSet.eventually_all + +alias _root_.Finset.eventually_all := eventually_all_finset + +-- attribute [protected] Finset.eventually_all + +theorem eventually_imp_distrib_left {f : Filter α} {p : Prop} {q : α → Prop} : + (∀ᶠ x in f, p → q x) ↔ p → ∀ᶠ x in f, q x := + eventually_all + + +/-! ### Frequently -/ + +@[simp] +theorem frequently_and_distrib_left {f : Filter α} {p : Prop} {q : α → Prop} : + (∃ᶠ x in f, p ∧ q x) ↔ p ∧ ∃ᶠ x in f, q x := by + simp only [Filter.Frequently, not_and, eventually_imp_distrib_left, Classical.not_imp] + +@[simp] +theorem frequently_and_distrib_right {f : Filter α} {p : α → Prop} {q : Prop} : + (∃ᶠ x in f, p x ∧ q) ↔ (∃ᶠ x in f, p x) ∧ q := by + simp only [@and_comm _ q, frequently_and_distrib_left] + +/-! +### Relation “eventually equal” +-/ + +section EventuallyEq +variable {l : Filter α} {f g : α → β} + +variable {l : Filter α} + +protected lemma EventuallyLE.iUnion [Finite ι] {s t : ι → Set α} + (h : ∀ i, s i ≤ᶠ[l] t i) : (⋃ i, s i) ≤ᶠ[l] ⋃ i, t i := + (eventually_all.2 h).mono fun _x hx hx' ↦ + let ⟨i, hi⟩ := mem_iUnion.1 hx'; mem_iUnion.2 ⟨i, hx i hi⟩ + +protected lemma EventuallyEq.iUnion [Finite ι] {s t : ι → Set α} + (h : ∀ i, s i =ᶠ[l] t i) : (⋃ i, s i) =ᶠ[l] ⋃ i, t i := + (EventuallyLE.iUnion fun i ↦ (h i).le).antisymm <| .iUnion fun i ↦ (h i).symm.le + +protected lemma EventuallyLE.iInter [Finite ι] {s t : ι → Set α} + (h : ∀ i, s i ≤ᶠ[l] t i) : (⋂ i, s i) ≤ᶠ[l] ⋂ i, t i := + (eventually_all.2 h).mono fun _x hx hx' ↦ mem_iInter.2 fun i ↦ hx i (mem_iInter.1 hx' i) + +protected lemma EventuallyEq.iInter [Finite ι] {s t : ι → Set α} + (h : ∀ i, s i =ᶠ[l] t i) : (⋂ i, s i) =ᶠ[l] ⋂ i, t i := + (EventuallyLE.iInter fun i ↦ (h i).le).antisymm <| .iInter fun i ↦ (h i).symm.le + +lemma _root_.Set.Finite.eventuallyLE_iUnion {ι : Type*} {s : Set ι} (hs : s.Finite) + {f g : ι → Set α} (hle : ∀ i ∈ s, f i ≤ᶠ[l] g i) : (⋃ i ∈ s, f i) ≤ᶠ[l] (⋃ i ∈ s, g i) := by + have := hs.to_subtype + rw [biUnion_eq_iUnion, biUnion_eq_iUnion] + exact .iUnion fun i ↦ hle i.1 i.2 + +alias EventuallyLE.biUnion := Set.Finite.eventuallyLE_iUnion + +lemma _root_.Set.Finite.eventuallyEq_iUnion {ι : Type*} {s : Set ι} (hs : s.Finite) + {f g : ι → Set α} (heq : ∀ i ∈ s, f i =ᶠ[l] g i) : (⋃ i ∈ s, f i) =ᶠ[l] (⋃ i ∈ s, g i) := + (EventuallyLE.biUnion hs fun i hi ↦ (heq i hi).le).antisymm <| + .biUnion hs fun i hi ↦ (heq i hi).symm.le + +alias EventuallyEq.biUnion := Set.Finite.eventuallyEq_iUnion + +lemma _root_.Set.Finite.eventuallyLE_iInter {ι : Type*} {s : Set ι} (hs : s.Finite) + {f g : ι → Set α} (hle : ∀ i ∈ s, f i ≤ᶠ[l] g i) : (⋂ i ∈ s, f i) ≤ᶠ[l] (⋂ i ∈ s, g i) := by + have := hs.to_subtype + rw [biInter_eq_iInter, biInter_eq_iInter] + exact .iInter fun i ↦ hle i.1 i.2 + +alias EventuallyLE.biInter := Set.Finite.eventuallyLE_iInter + +lemma _root_.Set.Finite.eventuallyEq_iInter {ι : Type*} {s : Set ι} (hs : s.Finite) + {f g : ι → Set α} (heq : ∀ i ∈ s, f i =ᶠ[l] g i) : (⋂ i ∈ s, f i) =ᶠ[l] (⋂ i ∈ s, g i) := + (EventuallyLE.biInter hs fun i hi ↦ (heq i hi).le).antisymm <| + .biInter hs fun i hi ↦ (heq i hi).symm.le + +alias EventuallyEq.biInter := Set.Finite.eventuallyEq_iInter + +lemma _root_.Finset.eventuallyLE_iUnion {ι : Type*} (s : Finset ι) {f g : ι → Set α} + (hle : ∀ i ∈ s, f i ≤ᶠ[l] g i) : (⋃ i ∈ s, f i) ≤ᶠ[l] (⋃ i ∈ s, g i) := + .biUnion s.finite_toSet hle + +lemma _root_.Finset.eventuallyEq_iUnion {ι : Type*} (s : Finset ι) {f g : ι → Set α} + (heq : ∀ i ∈ s, f i =ᶠ[l] g i) : (⋃ i ∈ s, f i) =ᶠ[l] (⋃ i ∈ s, g i) := + .biUnion s.finite_toSet heq + +lemma _root_.Finset.eventuallyLE_iInter {ι : Type*} (s : Finset ι) {f g : ι → Set α} + (hle : ∀ i ∈ s, f i ≤ᶠ[l] g i) : (⋂ i ∈ s, f i) ≤ᶠ[l] (⋂ i ∈ s, g i) := + .biInter s.finite_toSet hle + +lemma _root_.Finset.eventuallyEq_iInter {ι : Type*} (s : Finset ι) {f g : ι → Set α} + (heq : ∀ i ∈ s, f i =ᶠ[l] g i) : (⋂ i ∈ s, f i) =ᶠ[l] (⋂ i ∈ s, g i) := + .biInter s.finite_toSet heq + +end EventuallyEq + +end Filter + +open Filter diff --git a/Mathlib/Order/Filter/Germ/Basic.lean b/Mathlib/Order/Filter/Germ/Basic.lean index 21eda99605828..c9ad7754c4946 100644 --- a/Mathlib/Order/Filter/Germ/Basic.lean +++ b/Mathlib/Order/Filter/Germ/Basic.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov, Abhimanyu Pallavi Sudhir -/ import Mathlib.Algebra.Module.Pi +import Mathlib.Algebra.Order.Monoid.Unbundled.ExistsOfLE import Mathlib.Data.Int.Cast.Lemmas import Mathlib.Order.Filter.Tendsto @@ -237,7 +238,7 @@ theorem coe_compTendsto (f : α → β) {lc : Filter γ} {g : γ → α} (hg : T rfl -- Porting note https://github.com/leanprover-community/mathlib4/issues/10959 --- simp cannot prove this +-- simp can't match the LHS. @[simp, nolint simpNF] theorem compTendsto'_coe (f : Germ l β) {lc : Filter γ} {g : γ → α} (hg : Tendsto g lc l) : f.compTendsto' _ hg.germ_tendsto = f.compTendsto g hg := diff --git a/Mathlib/Order/Filter/Pointwise.lean b/Mathlib/Order/Filter/Pointwise.lean index c76d14970e05a..05f1a4c1cf4e0 100644 --- a/Mathlib/Order/Filter/Pointwise.lean +++ b/Mathlib/Order/Filter/Pointwise.lean @@ -146,9 +146,8 @@ theorem pureOneHom_apply (a : α) : pureOneHom a = pure a := variable [One β] @[to_additive] --- Porting note (https://github.com/leanprover-community/mathlib4/issues/11119): removed `simp` attribute because `simpNF` says it can prove it. protected theorem map_one [FunLike F α β] [OneHomClass F α β] (φ : F) : map φ 1 = 1 := by - rw [Filter.map_one', map_one, pure_one] + simp end One @@ -303,9 +302,7 @@ theorem mul_pure : f * pure b = f.map (· * b) := map₂_pure_right @[to_additive] --- Porting note (https://github.com/leanprover-community/mathlib4/issues/11119): removed `simp` attribute because `simpNF` says it can prove it. -theorem pure_mul_pure : (pure a : Filter α) * pure b = pure (a * b) := - map₂_pure +theorem pure_mul_pure : (pure a : Filter α) * pure b = pure (a * b) := by simp @[to_additive (attr := simp)] theorem le_mul_iff : h ≤ f * g ↔ ∀ ⦃s⦄, s ∈ f → ∀ ⦃t⦄, t ∈ g → s * t ∈ h := @@ -408,9 +405,7 @@ theorem div_pure : f / pure b = f.map (· / b) := map₂_pure_right @[to_additive] --- Porting note (https://github.com/leanprover-community/mathlib4/issues/11119): removed `simp` attribute because `simpNF` says it can prove it. -theorem pure_div_pure : (pure a : Filter α) / pure b = pure (a / b) := - map₂_pure +theorem pure_div_pure : (pure a : Filter α) / pure b = pure (a / b) := by simp @[to_additive] protected theorem div_le_div : f₁ ≤ f₂ → g₁ ≤ g₂ → f₁ / g₁ ≤ f₂ / g₂ := @@ -826,9 +821,7 @@ theorem smul_pure : f • pure b = f.map (· • b) := map₂_pure_right @[to_additive] --- Porting note (https://github.com/leanprover-community/mathlib4/issues/11119): removed `simp` attribute because `simpNF` says it can prove it. -theorem pure_smul_pure : (pure a : Filter α) • (pure b : Filter β) = pure (a • b) := - map₂_pure +theorem pure_smul_pure : (pure a : Filter α) • (pure b : Filter β) = pure (a • b) := by simp @[to_additive] theorem smul_le_smul : f₁ ≤ f₂ → g₁ ≤ g₂ → f₁ • g₁ ≤ f₂ • g₂ := @@ -914,9 +907,7 @@ theorem pure_vsub : (pure a : Filter β) -ᵥ g = g.map (a -ᵥ ·) := theorem vsub_pure : f -ᵥ pure b = f.map (· -ᵥ b) := map₂_pure_right --- Porting note (https://github.com/leanprover-community/mathlib4/issues/11119): removed `simp` attribute because `simpNF` says it can prove it. -theorem pure_vsub_pure : (pure a : Filter β) -ᵥ pure b = (pure (a -ᵥ b) : Filter α) := - map₂_pure +theorem pure_vsub_pure : (pure a : Filter β) -ᵥ pure b = (pure (a -ᵥ b) : Filter α) := by simp theorem vsub_le_vsub : f₁ ≤ f₂ → g₁ ≤ g₂ → f₁ -ᵥ g₁ ≤ f₂ -ᵥ g₂ := map₂_mono diff --git a/Mathlib/Order/Filter/Subsingleton.lean b/Mathlib/Order/Filter/Subsingleton.lean index e079522700c04..c8d0816c3f17b 100644 --- a/Mathlib/Order/Filter/Subsingleton.lean +++ b/Mathlib/Order/Filter/Subsingleton.lean @@ -3,7 +3,6 @@ Copyright (c) 2023 Yury Kudryashov. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov -/ -import Mathlib.Order.Filter.Bases import Mathlib.Order.Filter.Ultrafilter /-! # Subsingleton filters diff --git a/Mathlib/Order/FixedPoints.lean b/Mathlib/Order/FixedPoints.lean index e6f40735b5ddc..20419434bbcf6 100644 --- a/Mathlib/Order/FixedPoints.lean +++ b/Mathlib/Order/FixedPoints.lean @@ -51,76 +51,73 @@ def gfp : (α →o α) →o α where toFun f := sSup { a | a ≤ f a } monotone' _ _ hle := sSup_le_sSup fun a ha => le_trans ha (hle a) -theorem lfp_le {a : α} (h : f a ≤ a) : lfp f ≤ a := +theorem lfp_le {a : α} (h : f a ≤ a) : f.lfp ≤ a := sInf_le h -theorem lfp_le_fixed {a : α} (h : f a = a) : lfp f ≤ a := +theorem lfp_le_fixed {a : α} (h : f a = a) : f.lfp ≤ a := f.lfp_le h.le -theorem le_lfp {a : α} (h : ∀ b, f b ≤ b → a ≤ b) : a ≤ lfp f := +theorem le_lfp {a : α} (h : ∀ b, f b ≤ b → a ≤ b) : a ≤ f.lfp := le_sInf h --- Porting note: for the rest of the file, replace the dot notation `_.lfp` with `lfp _` --- same for `_.gfp`, `_.dual` --- Probably related to https://github.com/leanprover/lean4/issues/1910 -theorem map_le_lfp {a : α} (ha : a ≤ lfp f) : f a ≤ lfp f := +theorem map_le_lfp {a : α} (ha : a ≤ f.lfp) : f a ≤ f.lfp := f.le_lfp fun _ hb => (f.mono <| le_sInf_iff.1 ha _ hb).trans hb @[simp] -theorem map_lfp : f (lfp f) = lfp f := - have h : f (lfp f) ≤ lfp f := f.map_le_lfp le_rfl +theorem map_lfp : f f.lfp = f.lfp := + have h : f f.lfp ≤ f.lfp := f.map_le_lfp le_rfl h.antisymm <| f.lfp_le <| f.mono h -theorem isFixedPt_lfp : IsFixedPt f (lfp f) := +theorem isFixedPt_lfp : IsFixedPt f f.lfp := f.map_lfp -theorem lfp_le_map {a : α} (ha : lfp f ≤ a) : lfp f ≤ f a := +theorem lfp_le_map {a : α} (ha : f.lfp ≤ a) : f.lfp ≤ f a := calc - lfp f = f (lfp f) := f.map_lfp.symm + f.lfp = f f.lfp := f.map_lfp.symm _ ≤ f a := f.mono ha -theorem isLeast_lfp_le : IsLeast { a | f a ≤ a } (lfp f) := +theorem isLeast_lfp_le : IsLeast { a | f a ≤ a } f.lfp := ⟨f.map_lfp.le, fun _ => f.lfp_le⟩ -theorem isLeast_lfp : IsLeast (fixedPoints f) (lfp f) := +theorem isLeast_lfp : IsLeast (fixedPoints f) f.lfp := ⟨f.isFixedPt_lfp, fun _ => f.lfp_le_fixed⟩ -theorem lfp_induction {p : α → Prop} (step : ∀ a, p a → a ≤ lfp f → p (f a)) - (hSup : ∀ s, (∀ a ∈ s, p a) → p (sSup s)) : p (lfp f) := by - set s := { a | a ≤ lfp f ∧ p a } +theorem lfp_induction {p : α → Prop} (step : ∀ a, p a → a ≤ f.lfp → p (f a)) + (hSup : ∀ s, (∀ a ∈ s, p a) → p (sSup s)) : p f.lfp := by + set s := { a | a ≤ f.lfp ∧ p a } specialize hSup s fun a => And.right - suffices sSup s = lfp f from this ▸ hSup - have h : sSup s ≤ lfp f := sSup_le fun b => And.left + suffices sSup s = f.lfp from this ▸ hSup + have h : sSup s ≤ f.lfp := sSup_le fun b => And.left have hmem : f (sSup s) ∈ s := ⟨f.map_le_lfp h, step _ hSup h⟩ exact h.antisymm (f.lfp_le <| le_sSup hmem) -theorem le_gfp {a : α} (h : a ≤ f a) : a ≤ gfp f := +theorem le_gfp {a : α} (h : a ≤ f a) : a ≤ f.gfp := le_sSup h -theorem gfp_le {a : α} (h : ∀ b, b ≤ f b → b ≤ a) : gfp f ≤ a := +theorem gfp_le {a : α} (h : ∀ b, b ≤ f b → b ≤ a) : f.gfp ≤ a := sSup_le h -theorem isFixedPt_gfp : IsFixedPt f (gfp f) := +theorem isFixedPt_gfp : IsFixedPt f f.gfp := f.dual.isFixedPt_lfp @[simp] -theorem map_gfp : f (gfp f) = gfp f := +theorem map_gfp : f f.gfp = f.gfp := f.dual.map_lfp -theorem map_le_gfp {a : α} (ha : a ≤ gfp f) : f a ≤ gfp f := +theorem map_le_gfp {a : α} (ha : a ≤ f.gfp) : f a ≤ f.gfp := f.dual.lfp_le_map ha -theorem gfp_le_map {a : α} (ha : gfp f ≤ a) : gfp f ≤ f a := +theorem gfp_le_map {a : α} (ha : f.gfp ≤ a) : f.gfp ≤ f a := f.dual.map_le_lfp ha -theorem isGreatest_gfp_le : IsGreatest { a | a ≤ f a } (gfp f) := +theorem isGreatest_gfp_le : IsGreatest { a | a ≤ f a } f.gfp := f.dual.isLeast_lfp_le -theorem isGreatest_gfp : IsGreatest (fixedPoints f) (gfp f) := +theorem isGreatest_gfp : IsGreatest (fixedPoints f) f.gfp := f.dual.isLeast_lfp -theorem gfp_induction {p : α → Prop} (step : ∀ a, p a → gfp f ≤ a → p (f a)) - (hInf : ∀ s, (∀ a ∈ s, p a) → p (sInf s)) : p (gfp f) := +theorem gfp_induction {p : α → Prop} (step : ∀ a, p a → f.gfp ≤ a → p (f a)) + (hInf : ∀ s, (∀ a ∈ s, p a) → p (sInf s)) : p f.gfp := f.dual.lfp_induction step hInf end Basic @@ -130,27 +127,26 @@ section Eqn variable [CompleteLattice α] [CompleteLattice β] (f : β →o α) (g : α →o β) -- Rolling rule -theorem map_lfp_comp : f (lfp (g.comp f)) = lfp (f.comp g) := +theorem map_lfp_comp : f (g.comp f).lfp = (f.comp g).lfp := le_antisymm ((f.comp g).map_lfp ▸ f.mono (lfp_le_fixed _ <| congr_arg g (f.comp g).map_lfp)) <| lfp_le _ (congr_arg f (g.comp f).map_lfp).le -theorem map_gfp_comp : f (gfp (g.comp f)) = gfp (f.comp g) := - f.dual.map_lfp_comp (OrderHom.dual g) +theorem map_gfp_comp : f (g.comp f).gfp = (f.comp g).gfp := + f.dual.map_lfp_comp g.dual -- Diagonal rule -theorem lfp_lfp (h : α →o α →o α) : lfp (lfp.comp h) = lfp h.onDiag := by - let a := lfp (lfp.comp h) +theorem lfp_lfp (h : α →o α →o α) : (lfp.comp h).lfp = h.onDiag.lfp := by + let a := (lfp.comp h).lfp refine (lfp_le _ ?_).antisymm (lfp_le _ (Eq.le ?_)) · exact lfp_le _ h.onDiag.map_lfp.le have ha : (lfp ∘ h) a = a := (lfp.comp h).map_lfp calc - h a a = h a (lfp (h a)) := congr_arg (h a) ha.symm - _ = lfp (h a) := (h a).map_lfp + h a a = h a (h a).lfp := congr_arg (h a) ha.symm + _ = (h a).lfp := (h a).map_lfp _ = a := ha -theorem gfp_gfp (h : α →o α →o α) : gfp (gfp.comp h) = gfp h.onDiag := - @lfp_lfp αᵒᵈ _ <| (OrderHom.dualIso αᵒᵈ αᵒᵈ).symm.toOrderEmbedding.toOrderHom.comp - (OrderHom.dual h) +theorem gfp_gfp (h : α →o α →o α) : (gfp.comp h).gfp = h.onDiag.gfp := + @lfp_lfp αᵒᵈ _ <| (OrderHom.dualIso αᵒᵈ αᵒᵈ).symm.toOrderEmbedding.toOrderHom.comp h.dual end Eqn @@ -158,25 +154,25 @@ section PrevNext variable [CompleteLattice α] (f : α →o α) -theorem gfp_const_inf_le (x : α) : gfp (const α x ⊓ f) ≤ x := +theorem gfp_const_inf_le (x : α) : (const α x ⊓ f).gfp ≤ x := (gfp_le _) fun _ hb => hb.trans inf_le_left /-- Previous fixed point of a monotone map. If `f` is a monotone self-map of a complete lattice and `x` is a point such that `f x ≤ x`, then `f.prevFixed x hx` is the greatest fixed point of `f` that is less than or equal to `x`. -/ def prevFixed (x : α) (hx : f x ≤ x) : fixedPoints f := - ⟨gfp (const α x ⊓ f), + ⟨(const α x ⊓ f).gfp, calc - f (gfp (const α x ⊓ f)) = x ⊓ f (gfp (const α x ⊓ f)) := + f (const α x ⊓ f).gfp = x ⊓ f (const α x ⊓ f).gfp := Eq.symm <| inf_of_le_right <| (f.mono <| f.gfp_const_inf_le x).trans hx - _ = gfp (const α x ⊓ f) := (const α x ⊓ f).map_gfp + _ = (const α x ⊓ f).gfp := (const α x ⊓ f).map_gfp ⟩ /-- Next fixed point of a monotone map. If `f` is a monotone self-map of a complete lattice and `x` is a point such that `x ≤ f x`, then `f.nextFixed x hx` is the least fixed point of `f` that is greater than or equal to `x`. -/ def nextFixed (x : α) (hx : x ≤ f x) : fixedPoints f := - { f.dual.prevFixed x hx with val := lfp (const α x ⊔ f) } + { f.dual.prevFixed x hx with val := (const α x ⊔ f).lfp } theorem prevFixed_le {x : α} (hx : f x ≤ x) : ↑(f.prevFixed x hx) ≤ x := f.gfp_const_inf_le x @@ -240,7 +236,7 @@ instance : SemilatticeSup (fixedPoints f) := /- porting note: removed `Subtype.partialOrder _` from mathlib3port version, threw `typeclass instance` error and was seemingly unnecessary?-/ instance : SemilatticeInf (fixedPoints f) := - { OrderDual.instSemilatticeInf (fixedPoints (OrderHom.dual f)) with + { OrderDual.instSemilatticeInf (fixedPoints f.dual) with inf := fun x y => f.prevFixed (x ⊓ y) (f.map_inf_fixedPoints_le x y) } -- Porting note: `coe` replaced with `Subtype.val` @@ -271,8 +267,8 @@ instance completeLattice : CompleteLattice (fixedPoints f) where __ := inferInstanceAs (SemilatticeSup (fixedPoints f)) __ := inferInstanceAs (CompleteSemilatticeInf (fixedPoints f)) __ := inferInstanceAs (CompleteSemilatticeSup (fixedPoints f)) - top := ⟨gfp f, f.isFixedPt_gfp⟩ - bot := ⟨lfp f, f.isFixedPt_lfp⟩ + top := ⟨f.gfp, f.isFixedPt_gfp⟩ + bot := ⟨f.lfp, f.isFixedPt_lfp⟩ le_top x := f.le_gfp x.2.ge bot_le x := f.lfp_le x.2.le @@ -281,7 +277,7 @@ 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 : ωScottContinuous f) : - lfp f = ⨆ n, f^[n] ⊥ := by + f.lfp = ⨆ n, f^[n] ⊥ := by apply le_antisymm · apply lfp_le_fixed exact Function.mem_fixedPoints.mp (ωSup_iterate_mem_fixedPoint @@ -290,8 +286,8 @@ theorem lfp_eq_sSup_iterate (h : ωScottContinuous f) : intro a h_a exact ωSup_iterate_le_prefixedPoint ⟨f, h.map_ωSup_of_orderHom⟩ ⊥ bot_le h_a bot_le -theorem gfp_eq_sInf_iterate (h : ωScottContinuous (OrderHom.dual f)) : - gfp f = ⨅ n, f^[n] ⊤ := - lfp_eq_sSup_iterate (OrderHom.dual f) h +theorem gfp_eq_sInf_iterate (h : ωScottContinuous f.dual) : + f.gfp = ⨅ n, f^[n] ⊤ := + lfp_eq_sSup_iterate f.dual h end fixedPoints diff --git a/Mathlib/Order/Heyting/Basic.lean b/Mathlib/Order/Heyting/Basic.lean index 4c1f777c64b8f..1252f8884377c 100644 --- a/Mathlib/Order/Heyting/Basic.lean +++ b/Mathlib/Order/Heyting/Basic.lean @@ -794,7 +794,7 @@ theorem hnot_le_iff_codisjoint_right : ¬a ≤ b ↔ Codisjoint a b := by rw [← top_sdiff', sdiff_le_iff, codisjoint_iff_le_sup] theorem hnot_le_iff_codisjoint_left : ¬a ≤ b ↔ Codisjoint b a := - hnot_le_iff_codisjoint_right.trans Codisjoint_comm + hnot_le_iff_codisjoint_right.trans codisjoint_comm theorem hnot_le_comm : ¬a ≤ b ↔ ¬b ≤ a := by rw [hnot_le_iff_codisjoint_right, hnot_le_iff_codisjoint_left] @@ -1084,11 +1084,11 @@ theorem top_eq : (⊤ : PUnit) = unit := theorem bot_eq : (⊥ : PUnit) = unit := rfl -@[simp, nolint simpNF] +@[simp] theorem sup_eq : a ⊔ b = unit := rfl -@[simp, nolint simpNF] +@[simp] theorem inf_eq : a ⊓ b = unit := rfl @@ -1096,16 +1096,15 @@ theorem inf_eq : a ⊓ b = unit := theorem compl_eq : aᶜ = unit := rfl -@[simp, nolint simpNF] +@[simp] theorem sdiff_eq : a \ b = unit := rfl -@[simp, nolint simpNF] +@[simp] theorem hnot_eq : ¬a = unit := rfl --- eligible for `dsimp` -@[simp, nolint simpNF] +@[simp] theorem himp_eq : a ⇨ b = unit := rfl diff --git a/Mathlib/Order/Hom/Basic.lean b/Mathlib/Order/Hom/Basic.lean index aaa22efefcb3e..ef9ebbb809b7f 100644 --- a/Mathlib/Order/Hom/Basic.lean +++ b/Mathlib/Order/Hom/Basic.lean @@ -488,16 +488,13 @@ protected def dual : (α →o β) ≃ (αᵒᵈ →o βᵒᵈ) where left_inv _ := rfl right_inv _ := rfl --- Porting note: We used to be able to write `(OrderHom.id : α →o α).dual` here rather than --- `OrderHom.dual (OrderHom.id : α →o α)`. --- See https://github.com/leanprover/lean4/issues/1910 @[simp] -theorem dual_id : OrderHom.dual (OrderHom.id : α →o α) = OrderHom.id := +theorem dual_id : (OrderHom.id : α →o α).dual = OrderHom.id := rfl @[simp] theorem dual_comp (g : β →o γ) (f : α →o β) : - OrderHom.dual (g.comp f) = (OrderHom.dual g).comp (OrderHom.dual f) := + (g.comp f).dual = g.dual.comp f.dual := rfl @[simp] diff --git a/Mathlib/Order/Hom/Bounded.lean b/Mathlib/Order/Hom/Bounded.lean index 00886351437d4..6466c90ddaf43 100644 --- a/Mathlib/Order/Hom/Bounded.lean +++ b/Mathlib/Order/Hom/Bounded.lean @@ -725,18 +725,18 @@ protected def dual : BoundedOrderHom α β ≃ BoundedOrderHom αᵒᵈ βᵒᵈ where - toFun f := ⟨OrderHom.dual f.toOrderHom, f.map_bot', f.map_top'⟩ + toFun f := ⟨f.toOrderHom.dual, f.map_bot', f.map_top'⟩ invFun f := ⟨OrderHom.dual.symm f.toOrderHom, f.map_bot', f.map_top'⟩ left_inv _ := ext fun _ => rfl right_inv _ := ext fun _ => rfl @[simp] -theorem dual_id : BoundedOrderHom.dual (BoundedOrderHom.id α) = BoundedOrderHom.id _ := +theorem dual_id : (BoundedOrderHom.id α).dual = BoundedOrderHom.id _ := rfl @[simp] theorem dual_comp (g : BoundedOrderHom β γ) (f : BoundedOrderHom α β) : - BoundedOrderHom.dual (g.comp f) = g.dual.comp (BoundedOrderHom.dual f) := + (g.comp f).dual = g.dual.comp f.dual := rfl @[simp] diff --git a/Mathlib/Order/Interval/Basic.lean b/Mathlib/Order/Interval/Basic.lean index 9ef57523db1f8..55171625e65d7 100644 --- a/Mathlib/Order/Interval/Basic.lean +++ b/Mathlib/Order/Interval/Basic.lean @@ -109,7 +109,6 @@ theorem mem_mk {hx : x.1 ≤ x.2} : a ∈ mk x hx ↔ x.1 ≤ a ∧ a ≤ x.2 := theorem mem_def : a ∈ s ↔ s.fst ≤ a ∧ a ≤ s.snd := Iff.rfl --- @[simp] -- Porting note: not in simpNF theorem coe_nonempty (s : NonemptyInterval α) : (s : Set α).Nonempty := nonempty_Icc.2 s.fst_le_snd @@ -153,7 +152,7 @@ theorem map_map (g : β →o γ) (f : α →o β) (a : NonemptyInterval α) : @[simp] theorem dual_map (f : α →o β) (a : NonemptyInterval α) : - dual (a.map f) = a.dual.map (OrderHom.dual f) := + dual (a.map f) = a.dual.map f.dual := rfl /-- Binary pushforward of nonempty intervals. -/ @@ -360,7 +359,7 @@ theorem map_map (g : β →o γ) (f : α →o β) (s : Interval α) : (s.map f). Option.map_map _ _ _ @[simp] -theorem dual_map (f : α →o β) (s : Interval α) : dual (s.map f) = s.dual.map (OrderHom.dual f) := by +theorem dual_map (f : α →o β) (s : Interval α) : dual (s.map f) = s.dual.map f.dual := by cases s · rfl · exact WithBot.map_comm rfl _ diff --git a/Mathlib/Order/LiminfLimsup.lean b/Mathlib/Order/LiminfLimsup.lean index 25404163646dc..6cdea2ca4d772 100644 --- a/Mathlib/Order/LiminfLimsup.lean +++ b/Mathlib/Order/LiminfLimsup.lean @@ -46,17 +46,6 @@ namespace Filter section Relation -/-- `f.IsBounded (≺)`: the filter `f` is eventually bounded w.r.t. the relation `≺`, i.e. -eventually, it is bounded by some uniform bound. -`r` will be usually instantiated with `≤` or `≥`. -/ -def IsBounded (r : α → α → Prop) (f : Filter α) := - ∃ b, ∀ᶠ x in f, r x b - -/-- `f.IsBoundedUnder (≺) u`: the image of the filter `f` under `u` is eventually bounded w.r.t. -the relation `≺`, i.e. eventually, it is bounded by some uniform bound. -/ -def IsBoundedUnder (r : α → α → Prop) (f : Filter β) (u : β → α) := - (map u f).IsBounded r - variable {r : α → α → Prop} {f g : Filter α} /-- `f` is eventually bounded if and only if, there exists an admissible set on which it is @@ -218,25 +207,6 @@ theorem IsBoundedUnder.bddBelow_range [Preorder β] [IsDirected β (· ≥ ·)] (hf : IsBoundedUnder (· ≥ ·) atTop f) : BddBelow (range f) := IsBoundedUnder.bddAbove_range (β := βᵒᵈ) hf -/-- `IsCobounded (≺) f` states that the filter `f` does not tend to infinity w.r.t. `≺`. This is -also called frequently bounded. Will be usually instantiated with `≤` or `≥`. - -There is a subtlety in this definition: we want `f.IsCobounded` to hold for any `f` in the case of -complete lattices. This will be relevant to deduce theorems on complete lattices from their -versions on conditionally complete lattices with additional assumptions. We have to be careful in -the edge case of the trivial filter containing the empty set: the other natural definition - `¬ ∀ a, ∀ᶠ n in f, a ≤ n` -would not work as well in this case. --/ -def IsCobounded (r : α → α → Prop) (f : Filter α) := - ∃ b, ∀ a, (∀ᶠ x in f, r x a) → r b a - -/-- `IsCoboundedUnder (≺) f u` states that the image of the filter `f` under the map `u` does not -tend to infinity w.r.t. `≺`. This is also called frequently bounded. Will be usually instantiated -with `≤` or `≥`. -/ -def IsCoboundedUnder (r : α → α → Prop) (f : Filter β) (u : β → α) := - (map u f).IsCobounded r - /-- To check that a filter is frequently bounded, it suffices to have a witness which bounds `f` at some point for every admissible set. @@ -829,15 +799,13 @@ theorem HasBasis.limsup_eq_sInf_univ_of_empty {f : ι → α} {v : Filter ι} limsup f v = sInf univ := HasBasis.liminf_eq_sSup_univ_of_empty (α := αᵒᵈ) hv i hi h'i --- Porting note: simp_nf linter incorrectly says: lhs does not simplify when using simp on itself. -@[simp, nolint simpNF] +@[simp] theorem liminf_nat_add (f : ℕ → α) (k : ℕ) : liminf (fun i => f (i + k)) atTop = liminf f atTop := by change liminf (f ∘ (· + k)) atTop = liminf f atTop rw [liminf, liminf, ← map_map, map_add_atTop_eq_nat] --- Porting note: simp_nf linter incorrectly says: lhs does not simplify when using simp on itself. -@[simp, nolint simpNF] +@[simp] theorem limsup_nat_add (f : ℕ → α) (k : ℕ) : limsup (fun i => f (i + k)) atTop = limsup f atTop := @liminf_nat_add αᵒᵈ _ f k diff --git a/Mathlib/Order/Max.lean b/Mathlib/Order/Max.lean index 36518a3cb4aa5..7cf8fc7da8e5c 100644 --- a/Mathlib/Order/Max.lean +++ b/Mathlib/Order/Max.lean @@ -200,6 +200,14 @@ protected theorem IsBot.isMin (h : IsBot a) : IsMin a := fun b _ => h b protected theorem IsTop.isMax (h : IsTop a) : IsMax a := fun b _ => h b +theorem IsTop.isMax_iff {α} [PartialOrder α] {i j : α} (h : IsTop i) : IsMax j ↔ j = i := by + simp_rw [le_antisymm_iff, h j, true_and] + exact ⟨(· (h j)), Function.swap (fun _ ↦ h · |>.trans ·)⟩ + +theorem IsBot.isMin_iff {α} [PartialOrder α] {i j : α} (h : IsBot i) : IsMin j ↔ j = i := by + simp_rw [le_antisymm_iff, h j, and_true] + exact ⟨fun a ↦ a (h j), fun a h' ↦ fun _ ↦ Preorder.le_trans j i h' a (h h')⟩ + @[simp] theorem isBot_toDual_iff : IsBot (toDual a) ↔ IsTop a := Iff.rfl diff --git a/Mathlib/Order/OmegaCompletePartialOrder.lean b/Mathlib/Order/OmegaCompletePartialOrder.lean index 309394381dfc2..c34eaa969055e 100644 --- a/Mathlib/Order/OmegaCompletePartialOrder.lean +++ b/Mathlib/Order/OmegaCompletePartialOrder.lean @@ -731,7 +731,7 @@ theorem apply_mono {f g : α →𝒄 β} {x y : α} (h₁ : f ≤ g) (h₂ : x OrderHom.apply_mono (show (f : α →o β) ≤ g from h₁) h₂ set_option linter.deprecated false in -@[deprecated (since := "2024-07-27")] +@[deprecated "No deprecation message was provided." (since := "2024-07-27")] theorem ite_continuous' {p : Prop} [hp : Decidable p] (f g : α → β) (hf : Continuous' f) (hg : Continuous' g) : Continuous' fun x => if p then f x else g x := by split_ifs <;> simp [*] @@ -802,11 +802,11 @@ theorem seq_continuous' {β γ : Type v} (f : α → Part (β → γ)) (g : α intro apply map_continuous' _ _ hg +set_option linter.deprecated true + theorem continuous (F : α →𝒄 β) (C : Chain α) : F (ωSup C) = ωSup (C.map F) := F.ωScottContinuous.map_ωSup _ -set_option linter.deprecated true - /-- Construct a continuous function from a bare function, a continuous function, and a proof that they are equal. -/ -- Porting note: removed `@[reducible]` diff --git a/Mathlib/Order/RelClasses.lean b/Mathlib/Order/RelClasses.lean index 6fb587d189e2c..0acae0e49466b 100644 --- a/Mathlib/Order/RelClasses.lean +++ b/Mathlib/Order/RelClasses.lean @@ -17,8 +17,6 @@ extend `LE` and/or `LT` while these classes take a relation as an explicit argum -/ -set_option linter.deprecated false - universe u v variable {α : Type u} {β : Type v} {r : α → α → Prop} {s : β → β → Prop} @@ -88,7 +86,7 @@ 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")] +@[deprecated "No deprecation message was provided." (since := "2024-07-30")] theorem IsLinearOrder.swap (r) [IsLinearOrder α r] : IsLinearOrder α (swap r) := { @IsPartialOrder.swap α r _, @IsTotal.swap α r _ with } @@ -214,7 +212,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")] +@[deprecated "No deprecation message was provided." (since := "2024-07-30")] instance (priority := 100) isStrictTotalOrder_of_isStrictTotalOrder [IsStrictTotalOrder α r] : IsStrictWeakOrder α r := { isStrictWeakOrder_of_isOrderConnected with } @@ -782,7 +780,7 @@ instance [LinearOrder α] : IsStrictTotalOrder α (· < ·) where instance [LinearOrder α] : IsOrderConnected α (· < ·) := by infer_instance -@[deprecated (since := "2024-07-30")] +@[deprecated "No deprecation message was provided." (since := "2024-07-30")] instance [LinearOrder α] : IsStrictWeakOrder α (· < ·) := by infer_instance theorem transitive_le [Preorder α] : Transitive (@LE.le α _) := diff --git a/Mathlib/Order/RelSeries.lean b/Mathlib/Order/RelSeries.lean index b2c41395b294b..e385b759958c2 100644 --- a/Mathlib/Order/RelSeries.lean +++ b/Mathlib/Order/RelSeries.lean @@ -112,9 +112,9 @@ corresponds to each other. -/ protected def Equiv : RelSeries r ≃ {x : List α | x ≠ [] ∧ x.Chain' r} where toFun x := ⟨_, x.toList_ne_nil, x.toList_chain'⟩ invFun x := fromListChain' _ x.2.1 x.2.2 - left_inv x := ext (by simp [toList]) <| by ext; apply List.get_ofFn + left_inv x := ext (by simp [toList]) <| by ext; dsimp; apply List.get_ofFn right_inv x := by - refine Subtype.ext (List.ext_get ?_ fun n hn1 _ => List.get_ofFn _ _) + refine Subtype.ext (List.ext_get ?_ fun n hn1 _ => by dsimp; apply List.get_ofFn) have := Nat.succ_pred_eq_of_pos <| List.length_pos.mpr x.2.1 simp_all [toList] diff --git a/Mathlib/Order/SupClosed.lean b/Mathlib/Order/SupClosed.lean index 61ddd8850360c..84fdcccc76f9d 100644 --- a/Mathlib/Order/SupClosed.lean +++ b/Mathlib/Order/SupClosed.lean @@ -79,6 +79,17 @@ lemma supClosed_pi {ι : Type*} {α : ι → Type*} [∀ i, SemilatticeSup (α i {t : ∀ i, Set (α i)} (ht : ∀ i ∈ s, SupClosed (t i)) : SupClosed (s.pi t) := fun _a ha _b hb _i hi ↦ ht _ hi (ha _ hi) (hb _ hi) +lemma SupClosed.insert_upperBounds {s : Set α} {a : α} (hs : SupClosed s) (ha : a ∈ upperBounds s) : + SupClosed (insert a s) := by + rw [SupClosed] + aesop + +lemma SupClosed.insert_lowerBounds {s : Set α} {a : α} (h : SupClosed s) (ha : a ∈ lowerBounds s) : + SupClosed (insert a s) := by + rw [SupClosed] + have ha' : ∀ b ∈ s, a ≤ b := fun _ a ↦ ha a + aesop + end Set section Finset @@ -144,6 +155,17 @@ lemma infClosed_pi {ι : Type*} {α : ι → Type*} [∀ i, SemilatticeInf (α i {t : ∀ i, Set (α i)} (ht : ∀ i ∈ s, InfClosed (t i)) : InfClosed (s.pi t) := fun _a ha _b hb _i hi ↦ ht _ hi (ha _ hi) (hb _ hi) +lemma InfClosed.insert_upperBounds {s : Set α} {a : α} (hs : InfClosed s) (ha : a ∈ upperBounds s) : + InfClosed (insert a s) := by + rw [InfClosed] + have ha' : ∀ b ∈ s, b ≤ a := fun _ a ↦ ha a + aesop + +lemma InfClosed.insert_lowerBounds {s : Set α} {a : α} (h : InfClosed s) (ha : a ∈ lowerBounds s) : + InfClosed (insert a s) := by + rw [InfClosed] + aesop + end Set section Finset diff --git a/Mathlib/Order/SupIndep.lean b/Mathlib/Order/SupIndep.lean index 7e9d4b4cdbb85..27770ea7eaa4a 100644 --- a/Mathlib/Order/SupIndep.lean +++ b/Mathlib/Order/SupIndep.lean @@ -18,19 +18,19 @@ sup-independent if, for all `a`, `f a` and the supremum of the rest are disjoint ## Main definitions * `Finset.SupIndep s f`: a family of elements `f` are supremum independent on the finite set `s`. -* `CompleteLattice.SetIndependent s`: a set of elements are supremum independent. -* `CompleteLattice.Independent f`: a family of elements are supremum independent. +* `sSupIndep s`: a set of elements are supremum independent. +* `iSupIndep f`: a family of elements are supremum independent. ## Main statements * In a distributive lattice, supremum independence is equivalent to pairwise disjointness: * `Finset.supIndep_iff_pairwiseDisjoint` - * `CompleteLattice.setIndependent_iff_pairwiseDisjoint` - * `CompleteLattice.independent_iff_pairwiseDisjoint` + * `CompleteLattice.sSupIndep_iff_pairwiseDisjoint` + * `CompleteLattice.iSupIndep_iff_pairwiseDisjoint` * Otherwise, supremum independence is stronger than pairwise disjointness: * `Finset.SupIndep.pairwiseDisjoint` - * `CompleteLattice.SetIndependent.pairwiseDisjoint` - * `CompleteLattice.Independent.pairwiseDisjoint` + * `sSupIndep.pairwiseDisjoint` + * `iSupIndep.pairwiseDisjoint` ## Implementation notes @@ -88,7 +88,7 @@ theorem SupIndep.le_sup_iff (hs : s.SupIndep f) (hts : t ⊆ s) (hi : i ∈ s) ( by_contra hit exact hf i (disjoint_self.1 <| (hs hts hi hit).mono_right h) -/-- The RHS looks like the definition of `CompleteLattice.Independent`. -/ +/-- The RHS looks like the definition of `iSupIndep`. -/ theorem supIndep_iff_disjoint_erase [DecidableEq ι] : s.SupIndep f ↔ ∀ i ∈ s, Disjoint (f i) ((s.erase i).sup f) := ⟨fun hs _ hi => hs (erase_subset _ _) hi (not_mem_erase _ _), fun hs _ ht i hi hit => @@ -180,19 +180,7 @@ theorem SupIndep.attach (hs : s.SupIndep f) : s.attach.SupIndep fun a => f a := obtain ⟨j, hj, hji⟩ := hi' rwa [Subtype.ext hji] at hj -/- -Porting note: simpNF linter returns - -"Left-hand side does not simplify, when using the simp lemma on itself." - -However, simp does indeed solve the following. - -example {α ι} [Lattice α] [OrderBot α] (s : Finset ι) (f : ι → α) : - (s.attach.SupIndep fun a => f a) ↔ s.SupIndep f := by simp - -See https://github.com/leanprover-community/batteries/issues/71 for the simpNF issue. --/ -@[simp, nolint simpNF] +@[simp] theorem supIndep_attach : (s.attach.SupIndep fun a => f a) ↔ s.SupIndep f := by refine ⟨fun h t ht i his hit => ?_, SupIndep.attach⟩ classical @@ -281,38 +269,48 @@ end Finset /-! ### On complete lattices via `sSup` -/ - -namespace CompleteLattice - +section CompleteLattice variable [CompleteLattice α] open Set Function /-- An independent set of elements in a complete lattice is one in which every element is disjoint from the `Sup` of the rest. -/ -def SetIndependent (s : Set α) : Prop := +def sSupIndep (s : Set α) : Prop := ∀ ⦃a⦄, a ∈ s → Disjoint a (sSup (s \ {a})) -variable {s : Set α} (hs : SetIndependent s) +@[deprecated (since := "2024-11-24")] alias CompleteLattice.SetIndependent := sSupIndep + +variable {s : Set α} (hs : sSupIndep s) @[simp] -theorem setIndependent_empty : SetIndependent (∅ : Set α) := fun x hx => +theorem sSupIndep_empty : sSupIndep (∅ : Set α) := fun x hx => (Set.not_mem_empty x hx).elim +@[deprecated (since := "2024-11-24")] alias CompleteLattice.setIndependent_empty := sSupIndep_empty + include hs in -theorem SetIndependent.mono {t : Set α} (hst : t ⊆ s) : SetIndependent t := fun _ ha => +theorem sSupIndep.mono {t : Set α} (hst : t ⊆ s) : sSupIndep t := fun _ ha => (hs (hst ha)).mono_right (sSup_le_sSup (diff_subset_diff_left hst)) +@[deprecated (since := "2024-11-24")] alias CompleteLattice.SetIndependent.mono := sSupIndep.mono + include hs in /-- If the elements of a set are independent, then any pair within that set is disjoint. -/ -theorem SetIndependent.pairwiseDisjoint : s.PairwiseDisjoint id := fun _ hx y hy h => +theorem sSupIndep.pairwiseDisjoint : s.PairwiseDisjoint id := fun _ hx y hy h => disjoint_sSup_right (hs hx) ((mem_diff y).mpr ⟨hy, h.symm⟩) -theorem setIndependent_singleton (a : α) : SetIndependent ({a} : Set α) := fun i hi ↦ by +@[deprecated (since := "2024-11-24")] +alias CompleteLattice.SetIndependent.pairwiseDisjoint := sSupIndep.pairwiseDisjoint + +theorem sSupIndep_singleton (a : α) : sSupIndep ({a} : Set α) := fun i hi ↦ by simp_all -theorem setIndependent_pair {a b : α} (hab : a ≠ b) : - SetIndependent ({a, b} : Set α) ↔ Disjoint a b := by +@[deprecated (since := "2024-11-24")] +alias CompleteLattice.setIndependent_singleton := sSupIndep_singleton + +theorem sSupIndep_pair {a b : α} (hab : a ≠ b) : + sSupIndep ({a, b} : Set α) ↔ Disjoint a b := by constructor · intro h exact h.pairwiseDisjoint (mem_insert _ _) (mem_insert_of_mem _ (mem_singleton _)) hab @@ -322,15 +320,20 @@ theorem setIndependent_pair {a b : α} (hab : a ≠ b) : · convert h.symm using 1 simp [hab, sSup_singleton] +@[deprecated (since := "2024-11-24")] alias CompleteLattice.setIndependent_pair := sSupIndep_pair + include hs in /-- If the elements of a set are independent, then any element is disjoint from the `sSup` of some subset of the rest. -/ -theorem SetIndependent.disjoint_sSup {x : α} {y : Set α} (hx : x ∈ s) (hy : y ⊆ s) (hxy : x ∉ y) : +theorem sSupIndep.disjoint_sSup {x : α} {y : Set α} (hx : x ∈ s) (hy : y ⊆ s) (hxy : x ∉ y) : Disjoint x (sSup y) := by have := (hs.mono <| insert_subset_iff.mpr ⟨hx, hy⟩) (mem_insert x _) rw [insert_diff_of_mem _ (mem_singleton _), diff_singleton_eq_self hxy] at this exact this +@[deprecated (since := "2024-11-24")] +alias CompleteLattice.SetIndependent.disjoint_sSup := sSupIndep.disjoint_sSup + /-- An independent indexed family of elements in a complete lattice is one in which every element is disjoint from the `iSup` of the rest. @@ -340,70 +343,96 @@ theorem SetIndependent.disjoint_sSup {x : α} {y : Set α} (hx : x ∈ s) (hy : Example: an indexed family of submodules of a module is independent in this sense if and only the natural map from the direct sum of the submodules to the module is injective. -/ -def Independent {ι : Sort*} {α : Type*} [CompleteLattice α] (t : ι → α) : Prop := +def iSupIndep {ι : Sort*} {α : Type*} [CompleteLattice α] (t : ι → α) : Prop := ∀ i : ι, Disjoint (t i) (⨆ (j) (_ : j ≠ i), t j) -theorem setIndependent_iff {α : Type*} [CompleteLattice α] (s : Set α) : - SetIndependent s ↔ Independent ((↑) : s → α) := by - simp_rw [Independent, SetIndependent, SetCoe.forall, sSup_eq_iSup] +@[deprecated (since := "2024-11-24")] alias CompleteLattice.Independent := iSupIndep + +theorem sSupIndep_iff {α : Type*} [CompleteLattice α] (s : Set α) : + sSupIndep s ↔ iSupIndep ((↑) : s → α) := by + simp_rw [iSupIndep, sSupIndep, SetCoe.forall, sSup_eq_iSup] refine forall₂_congr fun a ha => ?_ simp [iSup_subtype, iSup_and] -variable {t : ι → α} (ht : Independent t) +@[deprecated (since := "2024-11-24")] alias CompleteLattice.setIndependent_iff := sSupIndep_iff -theorem independent_def : Independent t ↔ ∀ i : ι, Disjoint (t i) (⨆ (j) (_ : j ≠ i), t j) := +variable {t : ι → α} (ht : iSupIndep t) + +theorem iSupIndep_def : iSupIndep t ↔ ∀ i, Disjoint (t i) (⨆ (j) (_ : j ≠ i), t j) := Iff.rfl -theorem independent_def' : Independent t ↔ ∀ i, Disjoint (t i) (sSup (t '' { j | j ≠ i })) := by +@[deprecated (since := "2024-11-24")] alias CompleteLattice.independent_def := iSupIndep_def + +theorem iSupIndep_def' : iSupIndep t ↔ ∀ i, Disjoint (t i) (sSup (t '' { j | j ≠ i })) := by simp_rw [sSup_image] rfl -theorem independent_def'' : - Independent t ↔ ∀ i, Disjoint (t i) (sSup { a | ∃ j ≠ i, t j = a }) := by - rw [independent_def'] +@[deprecated (since := "2024-11-24")] alias CompleteLattice.independent_def' := iSupIndep_def' + +theorem iSupIndep_def'' : + iSupIndep t ↔ ∀ i, Disjoint (t i) (sSup { a | ∃ j ≠ i, t j = a }) := by + rw [iSupIndep_def'] aesop +@[deprecated (since := "2024-11-24")] alias CompleteLattice.independent_def'' := iSupIndep_def'' + @[simp] -theorem independent_empty (t : Empty → α) : Independent t := +theorem iSupIndep_empty (t : Empty → α) : iSupIndep t := nofun +@[deprecated (since := "2024-11-24")] alias CompleteLattice.independent_empty := iSupIndep_empty + @[simp] -theorem independent_pempty (t : PEmpty → α) : Independent t := +theorem iSupIndep_pempty (t : PEmpty → α) : iSupIndep t := nofun +@[deprecated (since := "2024-11-24")] alias CompleteLattice.independent_pempty := iSupIndep_pempty + include ht in /-- If the elements of a set are independent, then any pair within that set is disjoint. -/ -theorem Independent.pairwiseDisjoint : Pairwise (Disjoint on t) := fun x y h => +theorem iSupIndep.pairwiseDisjoint : Pairwise (Disjoint on t) := fun x y h => disjoint_sSup_right (ht x) ⟨y, iSup_pos h.symm⟩ -theorem Independent.mono {s t : ι → α} (hs : Independent s) (hst : t ≤ s) : Independent t := +@[deprecated (since := "2024-11-24")] +alias CompleteLattice.Independent.pairwiseDisjoint := iSupIndep.pairwiseDisjoint + +theorem iSupIndep.mono {s t : ι → α} (hs : iSupIndep s) (hst : t ≤ s) : iSupIndep t := fun i => (hs i).mono (hst i) <| iSup₂_mono fun j _ => hst j +@[deprecated (since := "2024-11-24")] alias CompleteLattice.Independent.mono := iSupIndep.mono + /-- Composing an independent indexed family with an injective function on the index results in another indepedendent indexed family. -/ -theorem Independent.comp {ι ι' : Sort*} {t : ι → α} {f : ι' → ι} (ht : Independent t) - (hf : Injective f) : Independent (t ∘ f) := fun i => +theorem iSupIndep.comp {ι ι' : Sort*} {t : ι → α} {f : ι' → ι} (ht : iSupIndep t) + (hf : Injective f) : iSupIndep (t ∘ f) := fun i => (ht (f i)).mono_right <| by refine (iSup_mono fun i => ?_).trans (iSup_comp_le _ f) exact iSup_const_mono hf.ne -theorem Independent.comp' {ι ι' : Sort*} {t : ι → α} {f : ι' → ι} (ht : Independent <| t ∘ f) - (hf : Surjective f) : Independent t := by +@[deprecated (since := "2024-11-24")] alias CompleteLattice.Independent.comp := iSupIndep.comp + +theorem iSupIndep.comp' {ι ι' : Sort*} {t : ι → α} {f : ι' → ι} (ht : iSupIndep <| t ∘ f) + (hf : Surjective f) : iSupIndep t := by intro i obtain ⟨i', rfl⟩ := hf i rw [← hf.iSup_comp] exact (ht i').mono_right (biSup_mono fun j' hij => mt (congr_arg f) hij) -theorem Independent.setIndependent_range (ht : Independent t) : SetIndependent <| range t := by - rw [setIndependent_iff] +@[deprecated (since := "2024-11-24")] alias CompleteLattice.Independent.comp' := iSupIndep.comp' + +theorem iSupIndep.sSupIndep_range (ht : iSupIndep t) : sSupIndep <| range t := by + rw [sSupIndep_iff] rw [← coe_comp_rangeFactorization t] at ht exact ht.comp' surjective_onto_range +@[deprecated (since := "2024-11-24")] +alias CompleteLattice.Independent.setIndependent_range := iSupIndep.sSupIndep_range + @[simp] -theorem independent_ne_bot_iff_independent : - Independent (fun i : {i // t i ≠ ⊥} ↦ t i) ↔ Independent t := by +theorem iSupIndep_ne_bot : + iSupIndep (fun i : {i // t i ≠ ⊥} ↦ t i) ↔ iSupIndep t := by refine ⟨fun h ↦ ?_, fun h ↦ h.comp Subtype.val_injective⟩ - simp only [independent_def] at h ⊢ + simp only [iSupIndep_def] at h ⊢ intro i cases eq_or_ne (t i) ⊥ with | inl hi => simp [hi] @@ -414,7 +443,10 @@ theorem independent_ne_bot_iff_independent : simp only [iSup_comm (ι' := _ ≠ i), this, ne_eq, sup_of_le_right, Subtype.mk.injEq, iSup_bot, bot_le] -theorem Independent.injOn (ht : Independent t) : InjOn t {i | t i ≠ ⊥} := by +@[deprecated (since := "2024-11-24")] +alias CompleteLattice.independent_ne_bot_iff_independent := iSupIndep_ne_bot + +theorem iSupIndep.injOn (ht : iSupIndep t) : InjOn t {i | t i ≠ ⊥} := by rintro i _ j (hj : t j ≠ ⊥) h by_contra! contra apply hj @@ -425,12 +457,17 @@ theorem Independent.injOn (ht : Independent t) : InjOn t {i | t i ≠ ⊥} := by -- Porting note: needs explicit `f` exact le_iSup₂ (f := fun x _ ↦ t x) j contra -theorem Independent.injective (ht : Independent t) (h_ne_bot : ∀ i, t i ≠ ⊥) : Injective t := by +@[deprecated (since := "2024-11-24")] alias CompleteLattice.Independent.injOn := iSupIndep.injOn + +theorem iSupIndep.injective (ht : iSupIndep t) (h_ne_bot : ∀ i, t i ≠ ⊥) : Injective t := by suffices univ = {i | t i ≠ ⊥} by rw [injective_iff_injOn_univ, this]; exact ht.injOn aesop -theorem independent_pair {i j : ι} (hij : i ≠ j) (huniv : ∀ k, k = i ∨ k = j) : - Independent t ↔ Disjoint (t i) (t j) := by +@[deprecated (since := "2024-11-24")] +alias CompleteLattice.Independent.injective := iSupIndep.injective + +theorem iSupIndep_pair {i j : ι} (hij : i ≠ j) (huniv : ∀ k, k = i ∨ k = j) : + iSupIndep t ↔ Disjoint (t i) (t j) := by constructor · exact fun h => h.pairwiseDisjoint hij · rintro h k @@ -440,37 +477,49 @@ theorem independent_pair {i j : ι} (hij : i ≠ j) (huniv : ∀ k, k = i ∨ k · refine h.symm.mono_right (iSup_le fun j => iSup_le fun hj => Eq.le ?_) rw [(huniv j).resolve_right hj] +@[deprecated (since := "2024-11-24")] alias CompleteLattice.independent_pair := iSupIndep_pair + /-- Composing an independent indexed family with an order isomorphism on the elements results in another independent indexed family. -/ -theorem Independent.map_orderIso {ι : Sort*} {α β : Type*} [CompleteLattice α] - [CompleteLattice β] (f : α ≃o β) {a : ι → α} (ha : Independent a) : Independent (f ∘ a) := +theorem iSupIndep.map_orderIso {ι : Sort*} {α β : Type*} [CompleteLattice α] + [CompleteLattice β] (f : α ≃o β) {a : ι → α} (ha : iSupIndep a) : iSupIndep (f ∘ a) := fun i => ((ha i).map_orderIso f).mono_right (f.monotone.le_map_iSup₂ _) +@[deprecated (since := "2024-11-24")] +alias CompleteLattice.Independent.map_orderIso := iSupIndep.map_orderIso + @[simp] -theorem independent_map_orderIso_iff {ι : Sort*} {α β : Type*} [CompleteLattice α] - [CompleteLattice β] (f : α ≃o β) {a : ι → α} : Independent (f ∘ a) ↔ Independent a := +theorem iSupIndep_map_orderIso_iff {ι : Sort*} {α β : Type*} [CompleteLattice α] + [CompleteLattice β] (f : α ≃o β) {a : ι → α} : iSupIndep (f ∘ a) ↔ iSupIndep a := ⟨fun h => have hf : f.symm ∘ f ∘ a = a := congr_arg (· ∘ a) f.left_inv.comp_eq_id hf ▸ h.map_orderIso f.symm, fun h => h.map_orderIso f⟩ +@[deprecated (since := "2024-11-24")] +alias CompleteLattice.independent_map_orderIso_iff := iSupIndep_map_orderIso_iff + /-- If the elements of a set are independent, then any element is disjoint from the `iSup` of some subset of the rest. -/ -theorem Independent.disjoint_biSup {ι : Type*} {α : Type*} [CompleteLattice α] {t : ι → α} - (ht : Independent t) {x : ι} {y : Set ι} (hx : x ∉ y) : Disjoint (t x) (⨆ i ∈ y, t i) := +theorem iSupIndep.disjoint_biSup {ι : Type*} {α : Type*} [CompleteLattice α] {t : ι → α} + (ht : iSupIndep t) {x : ι} {y : Set ι} (hx : x ∉ y) : Disjoint (t x) (⨆ i ∈ y, t i) := Disjoint.mono_right (biSup_mono fun _ hi => (ne_of_mem_of_not_mem hi hx : _)) (ht x) -lemma independent_of_independent_coe_Iic_comp {ι : Sort*} {a : α} {t : ι → Set.Iic a} - (ht : Independent ((↑) ∘ t : ι → α)) : Independent t := by +@[deprecated (since := "2024-11-24")] +alias CompleteLattice.Independent.disjoint_biSup := iSupIndep.disjoint_biSup + +lemma iSupIndep.of_coe_Iic_comp {ι : Sort*} {a : α} {t : ι → Set.Iic a} + (ht : iSupIndep ((↑) ∘ t : ι → α)) : iSupIndep t := by intro i x specialize ht i simp_rw [Function.comp_apply, ← Set.Iic.coe_iSup] at ht exact @ht x -end CompleteLattice +@[deprecated (since := "2024-11-24")] +alias CompleteLattice.independent_of_independent_coe_Iic_comp := iSupIndep.of_coe_Iic_comp -theorem CompleteLattice.independent_iff_supIndep [CompleteLattice α] {s : Finset ι} {f : ι → α} : - CompleteLattice.Independent (f ∘ ((↑) : s → ι)) ↔ s.SupIndep f := by +theorem iSupIndep_iff_supIndep {s : Finset ι} {f : ι → α} : + iSupIndep (f ∘ ((↑) : s → ι)) ↔ s.SupIndep f := by classical rw [Finset.supIndep_iff_disjoint_erase] refine Subtype.forall.trans (forall₂_congr fun a b => ?_) @@ -480,39 +529,47 @@ theorem CompleteLattice.independent_iff_supIndep [CompleteLattice α] {s : Finse congr! 1 simp [iSup_and, @iSup_comm _ (_ ∈ s)] -alias ⟨CompleteLattice.Independent.supIndep, Finset.SupIndep.independent⟩ := - CompleteLattice.independent_iff_supIndep +@[deprecated (since := "2024-11-24")] +alias CompleteLattice.independent_iff_supIndep := iSupIndep_iff_supIndep + +alias ⟨iSupIndep.supIndep, Finset.SupIndep.independent⟩ := iSupIndep_iff_supIndep + +theorem iSupIndep.supIndep' {f : ι → α} (s : Finset ι) (h : iSupIndep f) : s.SupIndep f := + iSupIndep.supIndep (h.comp Subtype.coe_injective) -theorem CompleteLattice.Independent.supIndep' [CompleteLattice α] {f : ι → α} (s : Finset ι) - (h : CompleteLattice.Independent f) : s.SupIndep f := - CompleteLattice.Independent.supIndep (h.comp Subtype.coe_injective) +@[deprecated (since := "2024-11-24")] +alias CompleteLattice.Independent.supIndep' := iSupIndep.supIndep' -/-- A variant of `CompleteLattice.independent_iff_supIndep` for `Fintype`s. -/ -theorem CompleteLattice.independent_iff_supIndep_univ [CompleteLattice α] [Fintype ι] {f : ι → α} : - CompleteLattice.Independent f ↔ Finset.univ.SupIndep f := by +/-- A variant of `CompleteLattice.iSupIndep_iff_supIndep` for `Fintype`s. -/ +theorem iSupIndep_iff_supIndep_univ [Fintype ι] {f : ι → α} : + iSupIndep f ↔ Finset.univ.SupIndep f := by classical - simp [Finset.supIndep_iff_disjoint_erase, CompleteLattice.Independent, Finset.sup_eq_iSup] + simp [Finset.supIndep_iff_disjoint_erase, iSupIndep, Finset.sup_eq_iSup] -alias ⟨CompleteLattice.Independent.sup_indep_univ, Finset.SupIndep.independent_of_univ⟩ := - CompleteLattice.independent_iff_supIndep_univ +@[deprecated (since := "2024-11-24")] +alias CompleteLattice.independent_iff_supIndep_univ := iSupIndep_iff_supIndep_univ -section Frame +alias ⟨iSupIndep.sup_indep_univ, Finset.SupIndep.iSupIndep_of_univ⟩ := iSupIndep_iff_supIndep_univ -namespace CompleteLattice +end CompleteLattice +section Frame variable [Order.Frame α] -theorem setIndependent_iff_pairwiseDisjoint {s : Set α} : - SetIndependent s ↔ s.PairwiseDisjoint id := - ⟨SetIndependent.pairwiseDisjoint, fun hs _ hi => +theorem sSupIndep_iff_pairwiseDisjoint {s : Set α} : sSupIndep s ↔ s.PairwiseDisjoint id := + ⟨sSupIndep.pairwiseDisjoint, fun hs _ hi => disjoint_sSup_iff.2 fun _ hj => hs hi hj.1 <| Ne.symm hj.2⟩ -alias ⟨_, _root_.Set.PairwiseDisjoint.setIndependent⟩ := setIndependent_iff_pairwiseDisjoint +@[deprecated (since := "2024-11-24")] +alias setIndependent_iff_pairwiseDisjoint := sSupIndep_iff_pairwiseDisjoint -theorem independent_iff_pairwiseDisjoint {f : ι → α} : Independent f ↔ Pairwise (Disjoint on f) := - ⟨Independent.pairwiseDisjoint, fun hs _ => +alias ⟨_, _root_.Set.PairwiseDisjoint.sSupIndep⟩ := sSupIndep_iff_pairwiseDisjoint + +theorem iSupIndep_iff_pairwiseDisjoint {f : ι → α} : iSupIndep f ↔ Pairwise (Disjoint on f) := + ⟨iSupIndep.pairwiseDisjoint, fun hs _ => disjoint_iSup_iff.2 fun _ => disjoint_iSup_iff.2 fun hij => hs hij.symm⟩ -end CompleteLattice +@[deprecated (since := "2024-11-24")] +alias independent_iff_pairwiseDisjoint := iSupIndep_iff_pairwiseDisjoint end Frame diff --git a/Mathlib/Probability/ConditionalProbability.lean b/Mathlib/Probability/ConditionalProbability.lean index 6dcf1ba7c951b..4e4d89fc5ac91 100644 --- a/Mathlib/Probability/ConditionalProbability.lean +++ b/Mathlib/Probability/ConditionalProbability.lean @@ -70,8 +70,8 @@ and scaled by the inverse of `μ s` (to make it a probability measure): def cond (s : Set Ω) : Measure Ω := (μ s)⁻¹ • μ.restrict s -@[inherit_doc] scoped notation:max μ "[" t " | " s "]" => ProbabilityTheory.cond μ s t @[inherit_doc] scoped notation:max μ "[|" s "]" => ProbabilityTheory.cond μ s +@[inherit_doc cond] scoped notation3:max μ "[" t " | " s "]" => ProbabilityTheory.cond μ s t /-- The conditional probability measure of measure `μ` on `{ω | X ω ∈ s}`. @@ -172,7 +172,7 @@ theorem inter_pos_of_cond_ne_zero (hms : MeasurableSet s) (hcst : μ[t|s] ≠ 0) simp [hms, Set.inter_comm, cond] lemma cond_pos_of_inter_ne_zero [IsFiniteMeasure μ] (hms : MeasurableSet s) (hci : μ (s ∩ t) ≠ 0) : - 0 < μ[|s] t := by + 0 < μ[t | s] := by rw [cond_apply hms] refine ENNReal.mul_pos ?_ hci exact ENNReal.inv_ne_zero.mpr (measure_ne_top _ _) diff --git a/Mathlib/Probability/Independence/Basic.lean b/Mathlib/Probability/Independence/Basic.lean index cfa5d0c19e7b7..a7ef0fcd188d8 100644 --- a/Mathlib/Probability/Independence/Basic.lean +++ b/Mathlib/Probability/Independence/Basic.lean @@ -721,4 +721,61 @@ theorem iIndepSet.iIndepFun_indicator [Zero β] [One β] {m : MeasurableSpace β end IndepFun +variable {ι Ω α β : Type*} {mΩ : MeasurableSpace Ω} {mα : MeasurableSpace α} + {mβ : MeasurableSpace β} {μ : Measure Ω} {X : ι → Ω → α} {Y : ι → Ω → β} {f : _ → Set Ω} + {t : ι → Set β} {s : Finset ι} + +/-- The probability of an intersection of preimages conditioning on another intersection factors +into a product. -/ +lemma cond_iInter [Finite ι] (hY : ∀ i, Measurable (Y i)) + (hindep : iIndepFun (fun _ ↦ mα.prod mβ) (fun i ω ↦ (X i ω, Y i ω)) μ) + (hf : ∀ i ∈ s, MeasurableSet[mα.comap (X i)] (f i)) + (hy : ∀ i ∉ s, μ (Y i ⁻¹' t i) ≠ 0) (ht : ∀ i, MeasurableSet (t i)) : + μ[⋂ i ∈ s, f i | ⋂ i, Y i ⁻¹' t i] = ∏ i ∈ s, μ[f i | Y i in t i] := by + have : IsProbabilityMeasure (μ : Measure Ω) := hindep.isProbabilityMeasure + classical + cases nonempty_fintype ι + let g (i' : ι) := if i' ∈ s then Y i' ⁻¹' t i' ∩ f i' else Y i' ⁻¹' t i' + calc + _ = (μ (⋂ i, Y i ⁻¹' t i))⁻¹ * μ ((⋂ i, Y i ⁻¹' t i) ∩ ⋂ i ∈ s, f i) := by + rw [cond_apply]; exact .iInter fun i ↦ hY i (ht i) + _ = (μ (⋂ i, Y i ⁻¹' t i))⁻¹ * μ (⋂ i, g i) := by + congr + calc + _ = (⋂ i, Y i ⁻¹' t i) ∩ ⋂ i, if i ∈ s then f i else .univ := by + congr + simp only [Set.iInter_ite, Set.iInter_univ, Set.inter_univ] + _ = ⋂ i, Y i ⁻¹' t i ∩ (if i ∈ s then f i else .univ) := by rw [Set.iInter_inter_distrib] + _ = _ := Set.iInter_congr fun i ↦ by by_cases hi : i ∈ s <;> simp [hi, g] + _ = (∏ i, μ (Y i ⁻¹' t i))⁻¹ * μ (⋂ i, g i) := by + rw [hindep.meas_iInter] + exact fun i ↦ ⟨.univ ×ˢ t i, MeasurableSet.univ.prod (ht _), by ext; simp [eq_comm]⟩ + _ = (∏ i, μ (Y i ⁻¹' t i))⁻¹ * ∏ i, μ (g i) := by + rw [hindep.meas_iInter] + intro i + by_cases hi : i ∈ s <;> simp only [hi, ↓reduceIte, g] + · obtain ⟨A, hA, hA'⟩ := hf i hi + exact .inter ⟨.univ ×ˢ t i, MeasurableSet.univ.prod (ht _), by ext; simp [eq_comm]⟩ + ⟨A ×ˢ Set.univ, hA.prod .univ, by ext; simp [← hA']⟩ + · exact ⟨.univ ×ˢ t i, MeasurableSet.univ.prod (ht _), by ext; simp [eq_comm]⟩ + _ = ∏ i, (μ (Y i ⁻¹' t i))⁻¹ * μ (g i) := by + rw [Finset.prod_mul_distrib, ENNReal.prod_inv_distrib] + exact fun _ _ i _ _ ↦ .inr <| measure_ne_top _ _ + _ = ∏ i, if i ∈ s then μ[f i | Y i ⁻¹' t i] else 1 := by + refine Finset.prod_congr rfl fun i _ ↦ ?_ + by_cases hi : i ∈ s + · simp only [hi, ↓reduceIte, g, cond_apply (hY i (ht i))] + · simp only [hi, ↓reduceIte, g, ENNReal.inv_mul_cancel (hy i hi) (measure_ne_top μ _)] + _ = _ := by simp + +lemma iIndepFun.cond [Finite ι] (hY : ∀ i, Measurable (Y i)) + (hindep : iIndepFun (fun _ ↦ mα.prod mβ) (fun i ω ↦ (X i ω, Y i ω)) μ) + (hy : ∀ i, μ (Y i ⁻¹' t i) ≠ 0) (ht : ∀ i, MeasurableSet (t i)) : + iIndepFun (fun _ ↦ mα) X μ[|⋂ i, Y i ⁻¹' t i] := by + rw [iIndepFun_iff] + intro s f hf + convert cond_iInter hY hindep hf (fun i _ ↦ hy _) ht using 2 with i hi + simpa using cond_iInter hY hindep (fun j hj ↦ hf _ <| Finset.mem_singleton.1 hj ▸ hi) + (fun i _ ↦ hy _) ht + end ProbabilityTheory diff --git a/Mathlib/Probability/Independence/Kernel.lean b/Mathlib/Probability/Independence/Kernel.lean index 85ed49143dcc1..3f4c1971fcafe 100644 --- a/Mathlib/Probability/Independence/Kernel.lean +++ b/Mathlib/Probability/Independence/Kernel.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Rémy Degenne -/ import Mathlib.MeasureTheory.Constructions.Pi +import Mathlib.Probability.ConditionalProbability import Mathlib.Probability.Kernel.Basic import Mathlib.Tactic.Peel @@ -1212,4 +1213,56 @@ theorem iIndepSet.iIndepFun_indicator [Zero β] [One β] {m : MeasurableSpace β end IndepFun +variable {ι Ω α β : Type*} {mΩ : MeasurableSpace Ω} {mα : MeasurableSpace α} + {mβ : MeasurableSpace β} {κ : Kernel α Ω} {μ : Measure α} {X : ι → Ω → α} {Y : ι → Ω → β} + {f : _ → Set Ω} {t : ι → Set β} {s : Finset ι} + +/-- The probability of an intersection of preimages conditioning on another intersection factors +into a product. -/ +lemma iIndepFun.cond_iInter [Finite ι] (hY : ∀ i, Measurable (Y i)) + (hindep : iIndepFun (fun _ ↦ mα.prod mβ) (fun i ω ↦ (X i ω, Y i ω)) κ μ) + (hf : ∀ i ∈ s, MeasurableSet[mα.comap (X i)] (f i)) + (hy : ∀ᵐ a ∂μ, ∀ i ∉ s, κ a (Y i ⁻¹' t i) ≠ 0) (ht : ∀ i, MeasurableSet (t i)) : + ∀ᵐ a ∂μ, (κ a)[⋂ i ∈ s, f i | ⋂ i, Y i ⁻¹' t i] = ∏ i ∈ s, (κ a)[f i | Y i in t i] := by + classical + cases nonempty_fintype ι + let g (i' : ι) := if i' ∈ s then Y i' ⁻¹' t i' ∩ f i' else Y i' ⁻¹' t i' + have hYt i : MeasurableSet[(mα.prod mβ).comap fun ω ↦ (X i ω, Y i ω)] (Y i ⁻¹' t i) := + ⟨.univ ×ˢ t i, .prod .univ (ht _), by ext; simp [eq_comm]⟩ + have hg i : MeasurableSet[(mα.prod mβ).comap fun ω ↦ (X i ω, Y i ω)] (g i) := by + by_cases hi : i ∈ s <;> simp only [hi, ↓reduceIte, g] + · obtain ⟨A, hA, hA'⟩ := hf i hi + exact (hYt _).inter ⟨A ×ˢ .univ, hA.prod .univ, by ext; simp [← hA']⟩ + · exact hYt _ + filter_upwards [hy, hindep.ae_isProbabilityMeasure, hindep.meas_iInter hYt, hindep.meas_iInter hg] + with a hy _ hYt hg + calc + _ = (κ a (⋂ i, Y i ⁻¹' t i))⁻¹ * κ a ((⋂ i, Y i ⁻¹' t i) ∩ ⋂ i ∈ s, f i) := by + rw [cond_apply]; exact .iInter fun i ↦ hY i (ht i) + _ = (κ a (⋂ i, Y i ⁻¹' t i))⁻¹ * κ a (⋂ i, g i) := by + congr + calc + _ = (⋂ i, Y i ⁻¹' t i) ∩ ⋂ i, if i ∈ s then f i else .univ := by + congr + simp only [Set.iInter_ite, Set.iInter_univ, Set.inter_univ] + _ = ⋂ i, Y i ⁻¹' t i ∩ (if i ∈ s then f i else .univ) := by rw [Set.iInter_inter_distrib] + _ = _ := Set.iInter_congr fun i ↦ by by_cases hi : i ∈ s <;> simp [hi, g] + _ = (∏ i, κ a (Y i ⁻¹' t i))⁻¹ * κ a (⋂ i, g i) := by + rw [hYt] + _ = (∏ i, κ a (Y i ⁻¹' t i))⁻¹ * ∏ i, κ a (g i) := by + rw [hg] + _ = ∏ i, (κ a (Y i ⁻¹' t i))⁻¹ * κ a (g i) := by + rw [Finset.prod_mul_distrib, ENNReal.prod_inv_distrib] + exact fun _ _ i _ _ ↦ .inr <| measure_ne_top _ _ + _ = ∏ i, if i ∈ s then (κ a)[f i | Y i ⁻¹' t i] else 1 := by + refine Finset.prod_congr rfl fun i _ ↦ ?_ + by_cases hi : i ∈ s + · simp only [hi, ↓reduceIte, g, cond_apply (hY i (ht i))] + · simp only [hi, ↓reduceIte, g, ENNReal.inv_mul_cancel (hy i hi) (measure_ne_top _ _)] + _ = _ := by simp + +-- TODO: We can't state `Kernel.iIndepFun.cond` (the `Kernel` analogue of +-- `ProbabilityTheory.iIndepFun.cond`) because we don't have a version of `ProbabilityTheory.cond` +-- for kernels + end ProbabilityTheory.Kernel diff --git a/Mathlib/Probability/UniformOn.lean b/Mathlib/Probability/UniformOn.lean index 524e33e17554c..828768e8f1610 100644 --- a/Mathlib/Probability/UniformOn.lean +++ b/Mathlib/Probability/UniformOn.lean @@ -42,7 +42,7 @@ open MeasureTheory MeasurableSpace namespace ProbabilityTheory -variable {Ω : Type*} [MeasurableSpace Ω] +variable {Ω : Type*} [MeasurableSpace Ω] {s : Set Ω} /-- Given a set `s`, `uniformOn s` is the uniform measure on `s`, defined as the counting measure conditioned by `s`. One should think of `uniformOn s t` as the proportion of `s` that is contained @@ -70,6 +70,16 @@ theorem uniformOn_empty {s : Set Ω} : uniformOn s ∅ = 0 := by simp @[deprecated (since := "2024-10-09")] alias condCount_empty := uniformOn_empty +/-- See `uniformOn_eq_zero` for a version assuming `MeasurableSingletonClass Ω` instead of +`MeasurableSet s`. -/ +@[simp] lemma uniformOn_eq_zero' (hs : MeasurableSet s) : uniformOn s = 0 ↔ s.Infinite ∨ s = ∅ := by + simp [uniformOn, hs] + +/-- See `uniformOn_eq_zero'` for a version assuming `MeasurableSet s` instead of +`MeasurableSingletonClass Ω`. -/ +@[simp] lemma uniformOn_eq_zero [MeasurableSingletonClass Ω] : + uniformOn s = 0 ↔ s.Infinite ∨ s = ∅ := by simp [uniformOn] + theorem finite_of_uniformOn_ne_zero {s t : Set Ω} (h : uniformOn s t ≠ 0) : s.Finite := by by_contra hs' simp [uniformOn, cond, Measure.count_apply_infinite hs'] at h @@ -93,7 +103,7 @@ variable [MeasurableSingletonClass Ω] theorem uniformOn_isProbabilityMeasure {s : Set Ω} (hs : s.Finite) (hs' : s.Nonempty) : IsProbabilityMeasure (uniformOn s) := by apply cond_isProbabilityMeasure_of_finite - · exact fun h => hs'.ne_empty <| Measure.empty_of_count_eq_zero h + · rwa [Measure.count_ne_zero_iff] · exact (Measure.count_apply_lt_top.2 hs).ne @[deprecated (since := "2024-10-09")] @@ -120,7 +130,7 @@ alias condCount_inter_self := uniformOn_inter_self theorem uniformOn_self (hs : s.Finite) (hs' : s.Nonempty) : uniformOn s s = 1 := by rw [uniformOn, cond_apply hs.measurableSet, Set.inter_self, ENNReal.inv_mul_cancel] - · exact fun h => hs'.ne_empty <| Measure.empty_of_count_eq_zero h + · rwa [Measure.count_ne_zero_iff] · exact (Measure.count_apply_lt_top.2 hs).ne @[deprecated (since := "2024-10-09")] diff --git a/Mathlib/RepresentationTheory/Basic.lean b/Mathlib/RepresentationTheory/Basic.lean index fbac878c2ff51..f17cfb213b7e5 100644 --- a/Mathlib/RepresentationTheory/Basic.lean +++ b/Mathlib/RepresentationTheory/Basic.lean @@ -292,7 +292,7 @@ def ofMulDistribMulAction : Representation ℤ M (Additive G) := ((monoidEndToAdditive G : _ →* _).comp (MulDistribMulAction.toMonoidEnd M G)) @[simp] theorem ofMulDistribMulAction_apply_apply (g : M) (a : Additive G) : - ofMulDistribMulAction M G g a = Additive.ofMul (g • Additive.toMul a) := rfl + ofMulDistribMulAction M G g a = Additive.ofMul (g • a.toMul) := rfl end MulDistribMulAction section Group diff --git a/Mathlib/RepresentationTheory/GroupCohomology/LowDegree.lean b/Mathlib/RepresentationTheory/GroupCohomology/LowDegree.lean index b05641a81a752..24d8d8f5bd37c 100644 --- a/Mathlib/RepresentationTheory/GroupCohomology/LowDegree.lean +++ b/Mathlib/RepresentationTheory/GroupCohomology/LowDegree.lean @@ -710,7 +710,7 @@ theorem H1LequivOfIsTrivial_comp_H1_π [A.IsTrivial] : @[simp] theorem H1LequivOfIsTrivial_H1_π_apply_apply [A.IsTrivial] (f : oneCocycles A) (x : Additive G) : - H1LequivOfIsTrivial A (H1_π A f) x = f (Additive.toMul x) := rfl + H1LequivOfIsTrivial A (H1_π A f) x = f x.toMul := rfl @[simp] theorem H1LequivOfIsTrivial_symm_apply [A.IsTrivial] (f : Additive G →+ A) : (H1LequivOfIsTrivial A).symm f = H1_π A ((oneCocyclesLequivOfIsTrivial A).symm f) := diff --git a/Mathlib/RepresentationTheory/Rep.lean b/Mathlib/RepresentationTheory/Rep.lean index d4ddfa12b4c67..0a14328b88a96 100644 --- a/Mathlib/RepresentationTheory/Rep.lean +++ b/Mathlib/RepresentationTheory/Rep.lean @@ -254,7 +254,7 @@ variable (M G : Type) [Monoid M] [CommGroup G] [MulDistribMulAction M G] def ofMulDistribMulAction : Rep ℤ M := Rep.of (Representation.ofMulDistribMulAction M G) @[simp] theorem ofMulDistribMulAction_ρ_apply_apply (g : M) (a : Additive G) : - (ofMulDistribMulAction M G).ρ g a = Additive.ofMul (g • Additive.toMul a) := rfl + (ofMulDistribMulAction M G).ρ g a = Additive.ofMul (g • a.toMul) := rfl /-- Given an `R`-algebra `S`, the `ℤ`-linear representation associated to the natural action of `S ≃ₐ[R] S` on `Sˣ`. -/ diff --git a/Mathlib/RingTheory/Algebraic.lean b/Mathlib/RingTheory/Algebraic.lean index cbec0d5bf252c..4126d2b4b3753 100644 --- a/Mathlib/RingTheory/Algebraic.lean +++ b/Mathlib/RingTheory/Algebraic.lean @@ -499,31 +499,34 @@ variable [Algebra R S] [Algebra S A] [Algebra R A] [IsScalarTower R S A] /-- If `x` is algebraic over `R`, then `x` is algebraic over `S` when `S` is an extension of `R`, and the map from `R` to `S` is injective. -/ -theorem IsAlgebraic.tower_top_of_injective - (hinj : Function.Injective (algebraMap R S)) {x : A} +theorem IsAlgebraic.extendScalars (hinj : Function.Injective (algebraMap R S)) {x : A} (A_alg : IsAlgebraic R x) : IsAlgebraic S x := let ⟨p, hp₁, hp₂⟩ := A_alg ⟨p.map (algebraMap _ _), by rwa [Ne, ← degree_eq_bot, degree_map_eq_of_injective hinj, degree_eq_bot], by simpa⟩ -/-- A special case of `IsAlgebraic.tower_top_of_injective`. This is extracted as a theorem - because in some cases `IsAlgebraic.tower_top_of_injective` will just runs out of memory. -/ +@[deprecated (since := "2024-11-18")] +alias IsAlgebraic.tower_top_of_injective := IsAlgebraic.extendScalars + +/-- A special case of `IsAlgebraic.extendScalars`. This is extracted as a theorem + because in some cases `IsAlgebraic.extendScalars` will just runs out of memory. -/ theorem IsAlgebraic.tower_top_of_subalgebra_le {A B : Subalgebra R S} (hle : A ≤ B) {x : S} (h : IsAlgebraic A x) : IsAlgebraic B x := by letI : Algebra A B := (Subalgebra.inclusion hle).toAlgebra haveI : IsScalarTower A B S := .of_algebraMap_eq fun _ ↦ rfl - exact h.tower_top_of_injective (Subalgebra.inclusion_injective hle) + exact h.extendScalars (Subalgebra.inclusion_injective hle) /-- If `x` is transcendental over `S`, then `x` is transcendental over `R` when `S` is an extension of `R`, and the map from `R` to `S` is injective. -/ -theorem Transcendental.of_tower_top_of_injective - (hinj : Function.Injective (algebraMap R S)) {x : A} - (h : Transcendental S x) : Transcendental R x := - fun H ↦ h (H.tower_top_of_injective hinj) +theorem Transcendental.restrictScalars (hinj : Function.Injective (algebraMap R S)) {x : A} + (h : Transcendental S x) : Transcendental R x := fun H ↦ h (H.extendScalars hinj) + +@[deprecated (since := "2024-11-18")] +alias Transcendental.of_tower_top_of_injective := Transcendental.restrictScalars -/-- A special case of `Transcendental.of_tower_top_of_injective`. This is extracted as a theorem - because in some cases `Transcendental.of_tower_top_of_injective` will just runs out of memory. -/ +/-- A special case of `Transcendental.restrictScalars`. This is extracted as a theorem + because in some cases `Transcendental.restrictScalars` will just runs out of memory. -/ theorem Transcendental.of_tower_top_of_subalgebra_le {A B : Subalgebra R S} (hle : A ≤ B) {x : S} (h : Transcendental B x) : Transcendental A x := @@ -531,9 +534,12 @@ theorem Transcendental.of_tower_top_of_subalgebra_le /-- If A is an algebraic algebra over R, then A is algebraic over S when S is an extension of R, and the map from `R` to `S` is injective. -/ -theorem Algebra.IsAlgebraic.tower_top_of_injective (hinj : Function.Injective (algebraMap R S)) +theorem Algebra.IsAlgebraic.extendScalars (hinj : Function.Injective (algebraMap R S)) [Algebra.IsAlgebraic R A] : Algebra.IsAlgebraic S A := - ⟨fun _ ↦ _root_.IsAlgebraic.tower_top_of_injective hinj (Algebra.IsAlgebraic.isAlgebraic _)⟩ + ⟨fun _ ↦ _root_.IsAlgebraic.extendScalars hinj (Algebra.IsAlgebraic.isAlgebraic _)⟩ + +@[deprecated (since := "2024-11-18")] +alias Algebra.IsAlgebraic.tower_top_of_injective := Algebra.IsAlgebraic.extendScalars theorem Algebra.IsAlgebraic.tower_bot_of_injective [Algebra.IsAlgebraic R A] (hinj : Function.Injective (algebraMap S A)) : @@ -553,7 +559,7 @@ variable (L) @[stacks 09GF "part one"] theorem IsAlgebraic.tower_top {x : A} (A_alg : IsAlgebraic K x) : IsAlgebraic L x := - A_alg.tower_top_of_injective (algebraMap K L).injective + A_alg.extendScalars (algebraMap K L).injective variable {L} (K) in /-- If `x` is transcendental over `L`, then `x` is transcendental over `K` when @@ -564,7 +570,7 @@ theorem Transcendental.of_tower_top {x : A} (h : Transcendental L x) : /-- If A is an algebraic algebra over K, then A is algebraic over L when L is an extension of K -/ @[stacks 09GF "part two"] theorem Algebra.IsAlgebraic.tower_top [Algebra.IsAlgebraic K A] : Algebra.IsAlgebraic L A := - Algebra.IsAlgebraic.tower_top_of_injective (algebraMap K L).injective + Algebra.IsAlgebraic.extendScalars (algebraMap K L).injective variable (K) @@ -928,7 +934,7 @@ theorem transcendental_supported_polynomial_aeval_X_iff exact Algebra.adjoin_mono (Set.singleton_subset_iff.2 (Set.mem_image_of_mem _ h)) (Polynomial.aeval_mem_adjoin_singleton _ _) · rw [← transcendental_polynomial_aeval_X_iff R i] - refine h.of_tower_top_of_injective fun _ _ heq ↦ MvPolynomial.C_injective σ R ?_ + refine h.restrictScalars fun _ _ heq ↦ MvPolynomial.C_injective σ R ?_ simp_rw [← MvPolynomial.algebraMap_eq] exact congr($(heq).1) diff --git a/Mathlib/RingTheory/AlgebraicIndependent.lean b/Mathlib/RingTheory/AlgebraicIndependent.lean index 30a829ce1e7fb..c098643d77e52 100644 --- a/Mathlib/RingTheory/AlgebraicIndependent.lean +++ b/Mathlib/RingTheory/AlgebraicIndependent.lean @@ -724,8 +724,7 @@ theorem IsTranscendenceBasis.isAlgebraic_field {F E : Type*} {x : ι → E} (Subalgebra.inclusion (IntermediateField.algebra_adjoin_le_adjoin F S)).toRingHom.toAlgebra haveI : IsScalarTower (adjoin F S) (IntermediateField.adjoin F S) E := IsScalarTower.of_algebraMap_eq (congrFun rfl) - exact Algebra.IsAlgebraic.tower_top_of_injective (R := adjoin F S) - (Subalgebra.inclusion_injective _) + exact Algebra.IsAlgebraic.extendScalars (R := adjoin F S) (Subalgebra.inclusion_injective _) section Field diff --git a/Mathlib/RingTheory/Artinian.lean b/Mathlib/RingTheory/Artinian.lean index f61383992490d..2911d10aa8bb9 100644 --- a/Mathlib/RingTheory/Artinian.lean +++ b/Mathlib/RingTheory/Artinian.lean @@ -10,6 +10,7 @@ import Mathlib.Order.Filter.EventuallyConst import Mathlib.RingTheory.Nakayama import Mathlib.RingTheory.SimpleModule import Mathlib.Tactic.RSuffices +import Mathlib.Tactic.StacksAttribute /-! # Artinian rings and modules @@ -347,6 +348,7 @@ end CommRing Strictly speaking, this should be called `IsLeftArtinianRing` but we omit the `Left` for convenience in the commutative case. For a right Artinian ring, use `IsArtinian Rᵐᵒᵖ R`. -/ +@[stacks 00J5] abbrev IsArtinianRing (R) [Ring R] := IsArtinian R R @@ -418,6 +420,7 @@ open IsArtinian variable {R : Type*} [CommRing R] [IsArtinianRing R] +@[stacks 00J8] theorem isNilpotent_jacobson_bot : IsNilpotent (Ideal.jacobson (⊥ : Ideal R)) := by let Jac := Ideal.jacobson (⊥ : Ideal R) let f : ℕ →o (Ideal R)ᵒᵈ := ⟨fun n => Jac ^ n, fun _ _ h => Ideal.pow_le_pow_right h⟩ @@ -504,9 +507,7 @@ lemma primeSpectrum_finite : {I : Ideal R | I.IsPrime}.Finite := by rwa [← Subtype.ext <| (@isMaximal_of_isPrime _ _ _ _ q.2).eq_of_le p.2.1 hq2] variable (R) -/-- -[Stacks Lemma 00J7](https://stacks.math.columbia.edu/tag/00J7) --/ +@[stacks 00J7] lemma maximal_ideals_finite : {I : Ideal R | I.IsMaximal}.Finite := by simp_rw [← isPrime_iff_isMaximal] apply primeSpectrum_finite R diff --git a/Mathlib/RingTheory/Complex.lean b/Mathlib/RingTheory/Complex.lean index 68be8e6b337a3..1f3b98e14ae26 100644 --- a/Mathlib/RingTheory/Complex.lean +++ b/Mathlib/RingTheory/Complex.lean @@ -18,11 +18,11 @@ theorem Algebra.leftMulMatrix_complex (z : ℂ) : rw [Algebra.leftMulMatrix_eq_repr_mul, Complex.coe_basisOneI_repr, Complex.coe_basisOneI, mul_re, mul_im, Matrix.of_apply] fin_cases j - · simp only [Fin.mk_zero, Matrix.cons_val_zero, one_re, mul_one, one_im, mul_zero, sub_zero, - zero_add] + · simp only [Fin.zero_eta, id_eq, Matrix.cons_val_zero, one_re, mul_one, one_im, mul_zero, + sub_zero, zero_add, Matrix.cons_val_fin_one] fin_cases i <;> rfl - · simp only [Fin.mk_one, Matrix.cons_val_one, Matrix.head_cons, I_re, mul_zero, I_im, mul_one, - zero_sub, add_zero] + · simp only [Fin.mk_one, id_eq, Matrix.cons_val_one, Matrix.head_cons, I_re, mul_zero, I_im, + mul_one, zero_sub, add_zero, Matrix.cons_val_fin_one] fin_cases i <;> rfl theorem Algebra.trace_complex_apply (z : ℂ) : Algebra.trace ℝ ℂ z = 2 * z.re := by diff --git a/Mathlib/RingTheory/DedekindDomain/Ideal.lean b/Mathlib/RingTheory/DedekindDomain/Ideal.lean index 22365ec289413..2533459ec4771 100644 --- a/Mathlib/RingTheory/DedekindDomain/Ideal.lean +++ b/Mathlib/RingTheory/DedekindDomain/Ideal.lean @@ -129,7 +129,6 @@ open Submodule Submodule.IsPrincipal theorem spanSingleton_inv (x : K) : (spanSingleton R₁⁰ x)⁻¹ = spanSingleton _ x⁻¹ := one_div_spanSingleton x --- @[simp] -- Porting note: not in simpNF form theorem spanSingleton_div_spanSingleton (x y : K) : spanSingleton R₁⁰ x / spanSingleton R₁⁰ y = spanSingleton R₁⁰ (x / y) := by rw [div_spanSingleton, mul_comm, spanSingleton_mul_spanSingleton, div_eq_mul_inv] @@ -1058,7 +1057,6 @@ variable [IsDedekindDomain R] (f : R ⧸ I ≃+* A ⧸ J) /-- The bijection between ideals of `R` dividing `I` and the ideals of `A` dividing `J` induced by an isomorphism `f : R/I ≅ A/J`. -/ --- @[simps] -- Porting note: simpNF complains about the lemmas generated by simps def idealFactorsEquivOfQuotEquiv : { p : Ideal R | p ∣ I } ≃o { p : Ideal A | p ∣ J } := by have f_surj : Function.Surjective (f : R ⧸ I →+* A ⧸ J) := f.surjective have fsym_surj : Function.Surjective (f.symm : A ⧸ J →+* R ⧸ I) := f.symm.surjective @@ -1101,7 +1099,6 @@ theorem idealFactorsEquivOfQuotEquiv_mem_normalizedFactors_of_mem_normalizedFact /-- The bijection between the sets of normalized factors of I and J induced by a ring isomorphism `f : R/I ≅ A/J`. -/ --- @[simps apply] -- Porting note: simpNF complains about the lemmas generated by simps def normalizedFactorsEquivOfQuotEquiv (hI : I ≠ ⊥) (hJ : J ≠ ⊥) : { L : Ideal R | L ∈ normalizedFactors I } ≃ { M : Ideal A | M ∈ normalizedFactors J } where toFun j := @@ -1379,7 +1376,6 @@ variable [NormalizationMonoid R] /-- The bijection between the (normalized) prime factors of `r` and the (normalized) prime factors of `span {r}` -/ --- @[simps] -- Porting note: simpNF complains about the lemmas generated by simps noncomputable def normalizedFactorsEquivSpanNormalizedFactors {r : R} (hr : r ≠ 0) : { d : R | d ∈ normalizedFactors r } ≃ { I : Ideal R | I ∈ normalizedFactors (Ideal.span ({r} : Set R)) } := by diff --git a/Mathlib/RingTheory/DedekindDomain/IntegralClosure.lean b/Mathlib/RingTheory/DedekindDomain/IntegralClosure.lean index 77679db0fe1c6..f38e19b607e41 100644 --- a/Mathlib/RingTheory/DedekindDomain/IntegralClosure.lean +++ b/Mathlib/RingTheory/DedekindDomain/IntegralClosure.lean @@ -185,6 +185,14 @@ theorem IsIntegralClosure.isNoetherianRing [IsIntegrallyClosed A] [IsNoetherianR IsNoetherianRing C := isNoetherianRing_iff.mpr <| isNoetherian_of_tower A (IsIntegralClosure.isNoetherian A K L C) +/-- If `L` is a finite separable extension of `K = Frac(A)`, where `A` is +integrally closed and Noetherian, the integral closure `C` of `A` in `L` is +finite over `A`. -/ +theorem IsIntegralClosure.finite [IsIntegrallyClosed A] [IsNoetherianRing A] : + Module.Finite A C := by + haveI := IsIntegralClosure.isNoetherian A K L C + exact Module.IsNoetherian.finite A C + /-- If `L` is a finite separable extension of `K = Frac(A)`, where `A` is a principal ring and `L` has no zero smul divisors by `A`, the integral closure `C` of `A` in `L` is a free `A`-module. -/ diff --git a/Mathlib/RingTheory/DedekindDomain/SInteger.lean b/Mathlib/RingTheory/DedekindDomain/SInteger.lean index 83b4fe6cf9021..7568c704d46d4 100644 --- a/Mathlib/RingTheory/DedekindDomain/SInteger.lean +++ b/Mathlib/RingTheory/DedekindDomain/SInteger.lean @@ -96,7 +96,6 @@ theorem unit_valuation_eq_one (x : S.unit K) {v : HeightOneSpectrum R} (hv : v v.valuation ((x : Kˣ) : K) = 1 := x.property v hv --- Porting note: `apply_inv_coe` fails the simpNF linter /-- The group of `S`-units is the group of units of the ring of `S`-integers. -/ @[simps apply_val_coe symm_apply_coe] def unitEquivUnitsInteger : S.unit K ≃* (S.integer K)ˣ where diff --git a/Mathlib/RingTheory/DividedPowers/Basic.lean b/Mathlib/RingTheory/DividedPowers/Basic.lean new file mode 100644 index 0000000000000..b07b6b0ac8aea --- /dev/null +++ b/Mathlib/RingTheory/DividedPowers/Basic.lean @@ -0,0 +1,418 @@ +/- +Copyright (c) 2024 Antoine Chambert-Loir & María-Inés de Frutos—Fernández. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Antoine Chambert-Loir, María-Inés de Frutos—Fernández +-/ + +import Mathlib.RingTheory.PowerSeries.Basic +import Mathlib.Combinatorics.Enumerative.Bell +import Mathlib.Data.Nat.Choose.Multinomial + +/-! # Divided powers + +Let `A` be a commutative (semi)ring and `I` be an ideal of `A`. +A *divided power* structure on `I` is the datum of operations `a n ↦ dpow a n` +satisfying relations that model the intuitive formula `dpow n a = a ^ n / n !` and +collected by the structure `DividedPowers`. The list of axioms is embedded in the structure: +To avoid coercions, we rather consider `DividedPowers.dpow : ℕ → A → A`, extended by 0. + +* `DividedPowers.dpow_null` asserts that `dpow n x = 0` for `x ∉ I` + +* `DividedPowers.dpow_mem` : `dpow n x ∈ I` for `n ≠ 0` +For `x y : A` and `m n : ℕ` such that `x ∈ I` and `y ∈ I`, one has +* `DividedPowers.dpow_zero` : `dpow 0 x = 1` +* `DividedPowers.dpow_one` : `dpow 1 x = 1` +* `DividedPowers.dpow_add` : `dpow n (x + y) = +(antidiagonal n).sum fun k ↦ dpow k.1 x * dpow k.2 y`, +this is the binomial theorem without binomial coefficients. +* `DividedPowers.dpow_mul`: `dpow n (a * x) = a ^ n * dpow n x` +* `DividedPowers.mul_dpow` : `dpow m x * dpow n x = choose (m + n) m * dpow (m + n) x` +* `DividedPowers.dpow_comp` : `dpow m (dpow n x) = uniformBell m n * dpow (m * n) x` + +* `DividedPowers.dividedPowersBot` : the trivial divided powers structure on the zero ideal + +* `DividedPowers.prod_dpow`: a product of divided powers is a multinomial coefficients +times a divided power + +* `DividedPowers.dpow_sum`: the multinomial theorem for divided powers, +without multinomial coefficients. + +* `DividedPowers.ofRingEquiv`: transfer divided powers along `RingEquiv` + +* `DividedPowers.equiv`: the equivalence `DividedPowers I ≃ DividedPowers J`, +for `e : R ≃+* S`, and `I : Ideal R`, `J : Ideal S` such that `I.map e = J` + +* `DividedPowers.exp`: the power series `Σ (dpow n a) X ^n` + +* `DividedPowers.exp_add`: its multiplicativity + +## References + +* [P. Berthelot (1974), *Cohomologie cristalline des schémas de +caractéristique $p$ > 0*][Berthelot-1974] + +* [P. Berthelot and A. Ogus (1978), *Notes on crystalline +cohomology*][BerthelotOgus-1978] + +* [N. Roby (1963), *Lois polynomes et lois formelles en théorie des +modules*][Roby-1963] + +* [N. Roby (1965), *Les algèbres à puissances dividées*][Roby-1965] + +## Discussion + +* In practice, one often has a single such structure to handle on a given ideal, +but several ideals of the same ring might be considered. +Without any explicit mention of the ideal, it is not clear whether such structures +should be provided as instances. + +* We do not provide any notation such as `a ^[n]` for `dpow a n`. + +-/ + +open Finset Nat Ideal + +section DividedPowersDefinition +/- ## Definition of divided powers -/ + +variable {A : Type*} [CommSemiring A] (I : Ideal A) + +/-- The divided power structure on an ideal I of a commutative ring A -/ +structure DividedPowers where + /-- The divided power function underlying a divided power structure -/ + dpow : ℕ → A → A + dpow_null : ∀ {n x} (_ : x ∉ I), dpow n x = 0 + dpow_zero : ∀ {x} (_ : x ∈ I), dpow 0 x = 1 + dpow_one : ∀ {x} (_ : x ∈ I), dpow 1 x = x + dpow_mem : ∀ {n x} (_ : n ≠ 0) (_ : x ∈ I), dpow n x ∈ I + dpow_add : ∀ (n) {x y} (_ : x ∈ I) (_ : y ∈ I), + dpow n (x + y) = (antidiagonal n).sum fun k ↦ dpow k.1 x * dpow k.2 y + dpow_mul : ∀ (n) {a : A} {x} (_ : x ∈ I), + dpow n (a * x) = a ^ n * dpow n x + mul_dpow : ∀ (m n) {x} (_ : x ∈ I), + dpow m x * dpow n x = choose (m + n) m * dpow (m + n) x + dpow_comp : ∀ (m) {n x} (_ : n ≠ 0) (_ : x ∈ I), + dpow m (dpow n x) = uniformBell m n * dpow (m * n) x + +variable (A) in +/-- The canonical `DividedPowers` structure on the zero ideal -/ +def dividedPowersBot [DecidableEq A] : DividedPowers (⊥ : Ideal A) where + dpow n a := ite (a = 0 ∧ n = 0) 1 0 + dpow_null {n a} ha := by + simp only [mem_bot] at ha + dsimp + rw [if_neg] + exact not_and_of_not_left (n = 0) ha + dpow_zero {a} ha := by + rw [mem_bot.mp ha] + simp only [and_self, ite_true] + dpow_one {a} ha := by + simp [mem_bot.mp ha] + dpow_mem {n a} hn _ := by + simp only [mem_bot, ite_eq_right_iff, and_imp] + exact fun _ a ↦ False.elim (hn a) + dpow_add n a b ha hb := by + rw [mem_bot.mp ha, mem_bot.mp hb, add_zero] + simp only [true_and, ge_iff_le, tsub_eq_zero_iff_le, mul_ite, mul_one, mul_zero] + split_ifs with h + · simp [h] + · symm + apply sum_eq_zero + intro i hi + simp only [mem_antidiagonal] at hi + split_ifs with h2 h1 + · rw [h1, h2, add_zero] at hi + exfalso + exact h hi.symm + · rfl + · rfl + dpow_mul n {a x} hx := by + rw [mem_bot.mp hx] + simp only [mul_zero, true_and, mul_ite, mul_one] + by_cases hn : n = 0 + · rw [if_pos hn, hn, if_pos rfl, _root_.pow_zero] + · simp only [if_neg hn] + mul_dpow m n {x} hx := by + rw [mem_bot.mp hx] + simp only [true_and, mul_ite, mul_one, mul_zero, add_eq_zero] + by_cases hn : n = 0 + · simp only [hn, ite_true, and_true, add_zero, choose_self, cast_one] + · rw [if_neg hn, if_neg] + exact not_and_of_not_right (m = 0) hn + dpow_comp m {n a} hn ha := by + rw [mem_bot.mp ha] + simp only [true_and, ite_eq_right_iff, _root_.mul_eq_zero, mul_ite, mul_one, mul_zero] + by_cases hm: m = 0 + · simp only [hm, and_true, true_or, ite_true, uniformBell_zero_left, cast_one] + rw [if_pos] + exact fun h ↦ False.elim (hn h) + · simp only [hm, and_false, ite_false, false_or, if_neg hn] + +instance [DecidableEq A] : Inhabited (DividedPowers (⊥ : Ideal A)) := + ⟨dividedPowersBot A⟩ + +/-- The coercion from the divided powers structures to functions -/ +instance : CoeFun (DividedPowers I) fun _ ↦ ℕ → A → A := ⟨fun hI ↦ hI.dpow⟩ + +variable {I} in +@[ext] +theorem DividedPowers.ext (hI : DividedPowers I) (hI' : DividedPowers I) + (h_eq : ∀ (n : ℕ) {x : A} (_ : x ∈ I), hI.dpow n x = hI'.dpow n x) : + hI = hI' := by + obtain ⟨hI, h₀, _⟩ := hI + obtain ⟨hI', h₀', _⟩ := hI' + simp only [mk.injEq] + ext n x + by_cases hx : x ∈ I + · exact h_eq n hx + · rw [h₀ hx, h₀' hx] + +theorem DividedPowers.coe_injective : + Function.Injective (fun (h : DividedPowers I) ↦ (h : ℕ → A → A)) := fun hI hI' h ↦ by + ext n x + exact congr_fun (congr_fun h n) x + +end DividedPowersDefinition + +namespace DividedPowers + +section BasicLemmas + +/- ## Basic lemmas for divided powers -/ + +variable {A : Type*} [CommSemiring A] {I : Ideal A} {a b : A} + +/-- Variant of `DividedPowers.dpow_add` with a sum on `range (n + 1)` -/ +theorem dpow_add' (hI : DividedPowers I) (n : ℕ) (ha : a ∈ I) (hb : b ∈ I) : + hI.dpow n (a + b) = (range (n + 1)).sum fun k ↦ hI.dpow k a * hI.dpow (n - k) b := by + rw [hI.dpow_add n ha hb, sum_antidiagonal_eq_sum_range_succ_mk] + +/-- The exponential series of an element in the context of divided powers, +`Σ (dpow n a) X ^ n` -/ +def exp (hI : DividedPowers I) (a : A) : PowerSeries A := + PowerSeries.mk fun n ↦ hI.dpow n a + +/-- A more general of `DividedPowers.exp_add` -/ +theorem exp_add' (dp : ℕ → A → A) + (dp_add : ∀ n, dp n (a + b) = (antidiagonal n).sum fun k ↦ dp k.1 a * dp k.2 b) : + PowerSeries.mk (fun n ↦ dp n (a + b)) = + (PowerSeries.mk fun n ↦ dp n a) * (PowerSeries.mk fun n ↦ dp n b) := by + ext n + simp only [exp, PowerSeries.coeff_mk, PowerSeries.coeff_mul, dp_add n, + sum_antidiagonal_eq_sum_range_succ_mk] + +theorem exp_add (hI : DividedPowers I) (ha : a ∈ I) (hb : b ∈ I) : + hI.exp (a + b) = hI.exp a * hI.exp b := + exp_add' _ (fun n ↦ hI.dpow_add n ha hb) + +variable (hI : DividedPowers I) + +/- ## Rewriting lemmas -/ + +theorem dpow_smul (n : ℕ) (ha : a ∈ I) : + hI.dpow n (b • a) = b ^ n • hI.dpow n a := by + simp only [smul_eq_mul, hI.dpow_mul, ha] + +theorem dpow_mul_right (n : ℕ) (ha : a ∈ I) : + hI.dpow n (a * b) = hI.dpow n a * b ^ n := by + rw [mul_comm, hI.dpow_mul n ha, mul_comm] + +theorem dpow_smul_right (n : ℕ) (ha : a ∈ I) : + hI.dpow n (a • b) = hI.dpow n a • b ^ n := by + rw [smul_eq_mul, hI.dpow_mul_right n ha, smul_eq_mul] + +theorem factorial_mul_dpow_eq_pow (n : ℕ) (ha : a ∈ I) : + (n ! : A) * hI.dpow n a = a ^ n := by + induction n with + | zero => rw [factorial_zero, cast_one, one_mul, pow_zero, hI.dpow_zero ha] + | succ n ih => + rw [factorial_succ, mul_comm (n + 1)] + nth_rewrite 1 [← (n + 1).choose_one_right] + rw [← choose_symm_add, cast_mul, mul_assoc, + ← hI.mul_dpow n 1 ha, ← mul_assoc, ih, hI.dpow_one ha, pow_succ, mul_comm] + +theorem dpow_eval_zero {n : ℕ} (hn : n ≠ 0) : hI.dpow n 0 = 0 := by + rw [← MulZeroClass.mul_zero (0 : A), hI.dpow_mul n I.zero_mem, + zero_pow hn, zero_mul, zero_mul] + +/-- If an element of a divided power ideal is killed by multiplication +by some nonzero integer `n`, then its `n`th power is zero. + +Proposition 1.2.7 of [Berthelot-1974], part (i). -/ +theorem nilpotent_of_mem_dpIdeal {n : ℕ} (hn : n ≠ 0) (hnI : ∀ {y} (_ : y ∈ I), n • y = 0) + (hI : DividedPowers I) (ha : a ∈ I) : a ^ n = 0 := by + have h_fac : (n ! : A) * hI.dpow n a = + n • ((n - 1)! : A) * hI.dpow n a := by + rw [nsmul_eq_mul, ← cast_mul, mul_factorial_pred (Nat.pos_of_ne_zero hn)] + rw [← hI.factorial_mul_dpow_eq_pow n ha, h_fac, smul_mul_assoc] + exact hnI (I.mul_mem_left ((n - 1)! : A) (hI.dpow_mem hn ha)) + +/-- If J is another ideal of A with divided powers, +then the divided powers of I and J coincide on I • J + +[Berthelot-1974], 1.6.1 (ii) -/ +theorem coincide_on_smul {J : Ideal A} (hJ : DividedPowers J) {n : ℕ} (ha : a ∈ I • J) : + hI.dpow n a = hJ.dpow n a := by + induction ha using Submodule.smul_induction_on' generalizing n with + | smul a ha b hb => + rw [Algebra.id.smul_eq_mul, hJ.dpow_mul n hb, mul_comm a b, hI.dpow_mul n ha, ← + hJ.factorial_mul_dpow_eq_pow n hb, ← hI.factorial_mul_dpow_eq_pow n ha] + ring + | add x hx y hy hx' hy' => + rw [hI.dpow_add n (mul_le_right hx) (mul_le_right hy), + hJ.dpow_add n (mul_le_left hx) (mul_le_left hy)] + apply sum_congr rfl + intro k _ + rw [hx', hy'] + +/-- A product of divided powers is a multinomial coefficient times the divided power + +[Roby-1965], formula (III') -/ +theorem prod_dpow {ι : Type*} {s : Finset ι} (n : ι → ℕ) (ha : a ∈ I) : + (s.prod fun i ↦ hI.dpow (n i) a) = multinomial s n * hI.dpow (s.sum n) a := by + classical + induction s using Finset.induction with + | empty => + simp only [prod_empty, multinomial_empty, cast_one, sum_empty, one_mul] + rw [hI.dpow_zero ha] + | insert hi hrec => + rw [prod_insert hi, hrec, ← mul_assoc, mul_comm (hI.dpow (n _) a), + mul_assoc, mul_dpow _ _ _ ha, ← sum_insert hi, ← mul_assoc] + apply congr_arg₂ _ _ rfl + rw [multinomial_insert hi, mul_comm, cast_mul, sum_insert hi] + +-- TODO : can probably be simplified using `DividedPowers.exp` + +/-- Lemma towards `dpow_sum` when we only have partial information on a divided power ideal -/ +theorem dpow_sum' {M : Type*} [AddCommMonoid M] {I : AddSubmonoid M} (dpow : ℕ → M → A) + (dpow_zero : ∀ {x} (_ : x ∈ I), dpow 0 x = 1) + (dpow_add : ∀ (n) {x y} (_ : x ∈ I) (_ : y ∈ I), + dpow n (x + y) = (antidiagonal n).sum fun k ↦ dpow k.1 x * dpow k.2 y) + (dpow_eval_zero : ∀ {n : ℕ} (_ : n ≠ 0), dpow n 0 = 0) + {ι : Type*} [DecidableEq ι] {s : Finset ι} {x : ι → M} (hx : ∀ i ∈ s, x i ∈ I) (n : ℕ) : + dpow n (s.sum x) = (s.sym n).sum fun k ↦ s.prod fun i ↦ dpow (Multiset.count i k) (x i) := by + simp only [sum_antidiagonal_eq_sum_range_succ_mk] at dpow_add + induction s using Finset.induction generalizing n with + | empty => + simp only [sum_empty, prod_empty, sum_const, nsmul_eq_mul, mul_one] + by_cases hn : n = 0 + · rw [hn] + rw [dpow_zero I.zero_mem] + simp only [sym_zero, card_singleton, cast_one] + · rw [dpow_eval_zero hn, eq_comm, ← cast_zero] + apply congr_arg + rw [card_eq_zero, sym_eq_empty] + exact ⟨hn, rfl⟩ + | @insert a s ha ih => + -- This should be golfable using `Finset.symInsertEquiv` + have hx' : ∀ i, i ∈ s → x i ∈ I := fun i hi ↦ hx i (mem_insert_of_mem hi) + simp_rw [sum_insert ha, + dpow_add n (hx a (mem_insert_self a s)) (I.sum_mem fun i ↦ hx' i), + sum_range, ih hx', mul_sum, sum_sigma', eq_comm] + apply sum_bij' + (fun m _ ↦ m.filterNe a) + (fun m _ ↦ m.2.fill a m.1) + (fun m hm ↦ mem_sigma.2 ⟨mem_univ _, _⟩) + (fun m hm ↦ by + simp only [succ_eq_add_one, mem_sym_iff, mem_insert, Sym.mem_fill_iff] + simp only [mem_sigma, mem_univ, mem_sym_iff, true_and] at hm + intro b + apply Or.imp (fun h ↦ h.2) (fun h ↦ hm b h)) + (fun m _ ↦ m.fill_filterNe a) + · intro m hm + simp only [mem_sigma, mem_univ, mem_sym_iff, true_and] at hm + exact Sym.filter_ne_fill a m fun a_1 ↦ ha (hm a a_1) + · intro m hm + simp only [mem_sym_iff, mem_insert] at hm + rw [prod_insert ha] + apply congr_arg₂ _ rfl + apply prod_congr rfl + intro i hi + apply congr_arg₂ _ _ rfl + conv_lhs => rw [← m.fill_filterNe a] + exact Sym.count_coe_fill_of_ne (ne_of_mem_of_not_mem hi ha) + · intro m hm + convert sym_filterNe_mem a hm + rw [erase_insert ha] + +/-- A “multinomial” theorem for divided powers — without multinomial coefficients -/ +theorem dpow_sum {ι : Type*} [DecidableEq ι] {s : Finset ι} {x : ι → A} + (hx : ∀ i ∈ s, x i ∈ I) (n : ℕ) : + hI.dpow n (s.sum x) = + (s.sym n).sum fun k ↦ s.prod fun i ↦ hI.dpow (Multiset.count i k) (x i) := + dpow_sum' hI.dpow hI.dpow_zero hI.dpow_add hI.dpow_eval_zero hx n + +end BasicLemmas + +section Equiv +/- ## Relation of divided powers with ring equivalences -/ + +variable {A B : Type*} [CommSemiring A] {I : Ideal A} [CommSemiring B] {J : Ideal B} + {e : A ≃+* B} (h : I.map e = J) + +/-- Transfer divided powers under an equivalence -/ +def ofRingEquiv (hI : DividedPowers I) : DividedPowers J where + dpow n b := e (hI.dpow n (e.symm b)) + dpow_null {n} {x} hx := by + rw [EmbeddingLike.map_eq_zero_iff, hI.dpow_null] + rwa [symm_apply_mem_of_equiv_iff, h] + dpow_zero {x} hx := by + rw [EmbeddingLike.map_eq_one_iff, hI.dpow_zero] + rwa [symm_apply_mem_of_equiv_iff, h] + dpow_one {x} hx := by + simp only + rw [dpow_one, RingEquiv.apply_symm_apply] + rwa [I.symm_apply_mem_of_equiv_iff, h] + dpow_mem {n} {x} hn hx := by + simp only + rw [← h, I.apply_mem_of_equiv_iff] + apply hI.dpow_mem hn + rwa [I.symm_apply_mem_of_equiv_iff, h] + dpow_add n {x y} hx hy := by + simp only [map_add] + rw [hI.dpow_add n (symm_apply_mem_of_equiv_iff.mpr (h ▸ hx)) + (symm_apply_mem_of_equiv_iff.mpr (h ▸ hy))] + simp only [map_sum, _root_.map_mul] + dpow_mul n {a x} hx := by + simp only [_root_.map_mul] + rw [hI.dpow_mul n (symm_apply_mem_of_equiv_iff.mpr (h ▸ hx))] + rw [_root_.map_mul, map_pow] + simp only [RingEquiv.apply_symm_apply] + mul_dpow m n {x} hx := by + simp only + rw [← _root_.map_mul, hI.mul_dpow, _root_.map_mul] + · simp only [map_natCast] + · rwa [symm_apply_mem_of_equiv_iff, h] + dpow_comp m {n x} hn hx := by + simp only [RingEquiv.symm_apply_apply] + rw [hI.dpow_comp _ hn] + · simp only [_root_.map_mul, map_natCast] + · rwa [symm_apply_mem_of_equiv_iff, h] + +@[simp] +theorem ofRingEquiv_dpow (hI : DividedPowers I) (n : ℕ) (b : B) : + (ofRingEquiv h hI).dpow n b = e (hI.dpow n (e.symm b)) := rfl + +theorem ofRingEquiv_dpow_apply (hI : DividedPowers I) (n : ℕ) (a : A) : + (ofRingEquiv h hI).dpow n (e a) = e (hI.dpow n a) := by + simp + +/-- Transfer divided powers under an equivalence (Equiv version) -/ +def equiv : DividedPowers I ≃ DividedPowers J where + toFun := ofRingEquiv h + invFun := ofRingEquiv (show map e.symm J = I by rw [← h]; exact I.map_of_equiv e) + left_inv := fun hI ↦ by ext n a; simp [ofRingEquiv] + right_inv := fun hJ ↦ by ext n b; simp [ofRingEquiv] + +theorem equiv_apply (hI : DividedPowers I) (n : ℕ) (b : B) : + (equiv h hI).dpow n b = e (hI.dpow n (e.symm b)) := rfl + +/-- Variant of `DividedPowers.equiv_apply` -/ +theorem equiv_apply' (hI : DividedPowers I) (n : ℕ) (a : A) : + (equiv h hI).dpow n (e a) = e (hI.dpow n a) := + ofRingEquiv_dpow_apply h hI n a + +end Equiv + +end DividedPowers + diff --git a/Mathlib/RingTheory/FiniteLength.lean b/Mathlib/RingTheory/FiniteLength.lean index b1cf98eb550b8..8eea41b4e20e2 100644 --- a/Mathlib/RingTheory/FiniteLength.lean +++ b/Mathlib/RingTheory/FiniteLength.lean @@ -78,13 +78,13 @@ theorem isFiniteLength_iff_exists_compositionSeries : theorem IsSemisimpleModule.finite_tfae [IsSemisimpleModule R M] : List.TFAE [Module.Finite R M, IsNoetherian R M, IsArtinian R M, IsFiniteLength R M, - ∃ s : Set (Submodule R M), s.Finite ∧ CompleteLattice.SetIndependent s ∧ + ∃ s : Set (Submodule R M), s.Finite ∧ sSupIndep s ∧ sSup s = ⊤ ∧ ∀ m ∈ s, IsSimpleModule R m] := by rw [isFiniteLength_iff_isNoetherian_isArtinian] - obtain ⟨s, hs⟩ := IsSemisimpleModule.exists_setIndependent_sSup_simples_eq_top R M + obtain ⟨s, hs⟩ := IsSemisimpleModule.exists_sSupIndep_sSup_simples_eq_top R M tfae_have 1 ↔ 2 := ⟨fun _ ↦ inferInstance, fun _ ↦ inferInstance⟩ - tfae_have 2 → 5 := fun _ ↦ ⟨s, CompleteLattice.WellFoundedGT.finite_of_setIndependent hs.1, hs⟩ - tfae_have 3 → 5 := fun _ ↦ ⟨s, CompleteLattice.WellFoundedLT.finite_of_setIndependent hs.1, hs⟩ + tfae_have 2 → 5 := fun _ ↦ ⟨s, WellFoundedGT.finite_of_sSupIndep hs.1, hs⟩ + tfae_have 3 → 5 := fun _ ↦ ⟨s, WellFoundedLT.finite_of_sSupIndep hs.1, hs⟩ tfae_have 5 → 4 := fun ⟨s, fin, _, sSup_eq_top, simple⟩ ↦ by rw [← isNoetherian_top_iff, ← Submodule.topEquiv.isArtinian_iff, ← sSup_eq_top, sSup_eq_iSup, ← iSup_subtype''] diff --git a/Mathlib/RingTheory/Finiteness/Basic.lean b/Mathlib/RingTheory/Finiteness/Basic.lean index f68cde85ea80c..73248997ca909 100644 --- a/Mathlib/RingTheory/Finiteness/Basic.lean +++ b/Mathlib/RingTheory/Finiteness/Basic.lean @@ -119,6 +119,17 @@ theorem fg_restrictScalars {R S M : Type*} [CommSemiring R] [Semiring S] [Algebr use X exact (Submodule.restrictScalars_span R S h (X : Set M)).symm +lemma FG.of_restrictScalars (R) {A M} [CommSemiring R] [Semiring A] [AddCommMonoid M] + [Algebra R A] [Module R M] [Module A M] [IsScalarTower R A M] (S : Submodule A M) + (hS : (S.restrictScalars R).FG) : S.FG := by + obtain ⟨s, e⟩ := hS + refine ⟨s, Submodule.restrictScalars_injective R _ _ (le_antisymm ?_ ?_)⟩ + · show Submodule.span A s ≤ S + have := Submodule.span_le.mp e.le + rwa [Submodule.span_le] + · rw [← e] + exact Submodule.span_le_restrictScalars _ _ _ + theorem FG.stabilizes_of_iSup_eq {M' : Submodule R M} (hM' : M'.FG) (N : ℕ →o Submodule R M) (H : iSup N = M') : ∃ n, M' = N n := by obtain ⟨S, hS⟩ := hM' diff --git a/Mathlib/RingTheory/Finiteness/Defs.lean b/Mathlib/RingTheory/Finiteness/Defs.lean index 289071d1c7064..a56606fa8c8e9 100644 --- a/Mathlib/RingTheory/Finiteness/Defs.lean +++ b/Mathlib/RingTheory/Finiteness/Defs.lean @@ -100,7 +100,7 @@ section ModuleAndAlgebra variable (R A B M N : Type*) -/-- A module over a semiring is `Finite` if it is finitely generated as a module. -/ +/-- A module over a semiring is `Module.Finite` if it is finitely generated as a module. -/ protected class Module.Finite [Semiring R] [AddCommMonoid M] [Module R M] : Prop where out : (⊤ : Submodule R M).FG @@ -142,7 +142,7 @@ namespace RingHom variable {A B C : Type*} [CommRing A] [CommRing B] [CommRing C] -/-- A ring morphism `A →+* B` is `Finite` if `B` is finitely generated as `A`-module. -/ +/-- A ring morphism `A →+* B` is `RingHom.Finite` if `B` is finitely generated as `A`-module. -/ @[algebraize Module.Finite] def Finite (f : A →+* B) : Prop := letI : Algebra A B := f.toAlgebra diff --git a/Mathlib/RingTheory/FreeCommRing.lean b/Mathlib/RingTheory/FreeCommRing.lean index 6efc6c11c1cd6..e1b0736aa1404 100644 --- a/Mathlib/RingTheory/FreeCommRing.lean +++ b/Mathlib/RingTheory/FreeCommRing.lean @@ -134,7 +134,7 @@ private def liftToMultiset : (α → R) ≃ (Multiplicative (Multiset α) →* R left_inv f := funext fun x => show (Multiset.map f {x}).prod = _ by simp right_inv F := MonoidHom.ext fun x => let F' := MonoidHom.toAdditive'' F - let x' := Multiplicative.toAdd x + let x' := x.toAdd show (Multiset.map (fun a => F' {a}) x').sum = F' x' by erw [← Multiset.map_map (fun x => F' x) (fun x => {x}), ← AddMonoidHom.map_multiset_sum] exact DFunLike.congr_arg F (Multiset.sum_map_singleton x') diff --git a/Mathlib/RingTheory/GradedAlgebra/HomogeneousLocalization.lean b/Mathlib/RingTheory/GradedAlgebra/HomogeneousLocalization.lean index af6dc235b4928..82a5c54c0a72c 100644 --- a/Mathlib/RingTheory/GradedAlgebra/HomogeneousLocalization.lean +++ b/Mathlib/RingTheory/GradedAlgebra/HomogeneousLocalization.lean @@ -636,8 +636,7 @@ end section mapAway variable [AddCommMonoid ι] [DecidableEq ι] [GradedAlgebra 𝒜] -variable {d e : ι} {f : A} (hf : f ∈ 𝒜 d) {g : A} (hg : g ∈ 𝒜 e) -variable {x : A} (hx : x = f * g) +variable {e : ι} {f : A} {g : A} (hg : g ∈ 𝒜 e) {x : A} (hx : x = f * g) variable (𝒜) diff --git a/Mathlib/RingTheory/GradedAlgebra/Noetherian.lean b/Mathlib/RingTheory/GradedAlgebra/Noetherian.lean index cba8dab196628..9bd8cc5122295 100644 --- a/Mathlib/RingTheory/GradedAlgebra/Noetherian.lean +++ b/Mathlib/RingTheory/GradedAlgebra/Noetherian.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Fangming Li -/ import Mathlib.RingTheory.GradedAlgebra.Basic -import Mathlib.RingTheory.Noetherian.Defs +import Mathlib.RingTheory.Noetherian.Basic /-! # The properties of a graded Noetherian ring. diff --git a/Mathlib/RingTheory/HahnSeries/Basic.lean b/Mathlib/RingTheory/HahnSeries/Basic.lean index aa4ddc454c2dc..b074a86e1aa3b 100644 --- a/Mathlib/RingTheory/HahnSeries/Basic.lean +++ b/Mathlib/RingTheory/HahnSeries/Basic.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Aaron Anderson -/ import Mathlib.Algebra.Group.Support +import Mathlib.Algebra.Order.Monoid.Unbundled.WithTop import Mathlib.Order.WellFoundedSet /-! diff --git a/Mathlib/RingTheory/Ideal/Maps.lean b/Mathlib/RingTheory/Ideal/Maps.lean index 7a67ded065aff..e2a631a34c0a9 100644 --- a/Mathlib/RingTheory/Ideal/Maps.lean +++ b/Mathlib/RingTheory/Ideal/Maps.lean @@ -362,9 +362,20 @@ theorem comap_symm {I : Ideal R} (f : R ≃+* S) : I.comap f.symm = I.map f := /-- If `f : R ≃+* S` is a ring isomorphism and `I : Ideal R`, then `map f.symm I = comap f I`. -/ @[simp] + theorem map_symm {I : Ideal S} (f : R ≃+* S) : I.map f.symm = I.comap f := map_comap_of_equiv (RingEquiv.symm f) +@[simp] +theorem symm_apply_mem_of_equiv_iff {I : Ideal R} {f : R ≃+* S} {y : S} : + f.symm y ∈ I ↔ y ∈ I.map f := by + rw [← comap_symm, mem_comap] + +@[simp] +theorem apply_mem_of_equiv_iff {I : Ideal R} {f : R ≃+* S} {x : R} : + f x ∈ I.map f ↔ x ∈ I := by + rw [← comap_symm, Ideal.mem_comap, f.symm_apply_apply] + theorem mem_map_of_equiv {E : Type*} [EquivLike E R S] [RingEquivClass E R S] (e : E) {I : Ideal R} (y : S) : y ∈ map e I ↔ ∃ x ∈ I, e x = y := by constructor diff --git a/Mathlib/RingTheory/Ideal/Maximal.lean b/Mathlib/RingTheory/Ideal/Maximal.lean index 591bb5e34a064..c3cb20cf054d0 100644 --- a/Mathlib/RingTheory/Ideal/Maximal.lean +++ b/Mathlib/RingTheory/Ideal/Maximal.lean @@ -162,6 +162,15 @@ theorem IsMaximal.isPrime {I : Ideal α} (H : I.IsMaximal) : I.IsPrime := instance (priority := 100) IsMaximal.isPrime' (I : Ideal α) : ∀ [_H : I.IsMaximal], I.IsPrime := @IsMaximal.isPrime _ _ _ +theorem exists_disjoint_powers_of_span_eq_top (s : Set α) (hs : span s = ⊤) (I : Ideal α) + (hI : I ≠ ⊤) : ∃ r ∈ s, Disjoint (I : Set α) (Submonoid.powers r) := by + have ⟨M, hM, le⟩ := exists_le_maximal I hI + have := hM.1.1 + rw [Ne, eq_top_iff, ← hs, span_le, Set.not_subset] at this + have ⟨a, has, haM⟩ := this + exact ⟨a, has, Set.disjoint_left.mpr fun x hx ⟨n, hn⟩ ↦ + haM (hM.isPrime.mem_of_pow_mem _ (le <| hn ▸ hx))⟩ + theorem span_singleton_lt_span_singleton [IsDomain α] {x y : α} : span ({x} : Set α) < span ({y} : Set α) ↔ DvdNotUnit y x := by rw [lt_iff_le_not_le, span_singleton_le_span_singleton, span_singleton_le_span_singleton, @@ -191,6 +200,26 @@ lemma isPrime_of_maximally_disjoint (I : Ideal α) rw [← hr₁, ← hr₂] ring +theorem exists_le_prime_disjoint (S : Submonoid α) (disjoint : Disjoint (I : Set α) S) : + ∃ p : Ideal α, p.IsPrime ∧ I ≤ p ∧ Disjoint (p : Set α) S := by + have ⟨p, hIp, hp⟩ := zorn_le_nonempty₀ {p : Ideal α | Disjoint (p : Set α) S} + (fun c hc hc' x hx ↦ ?_) I disjoint + · exact ⟨p, isPrime_of_maximally_disjoint _ _ hp.1 (fun _ ↦ hp.not_prop_of_gt), hIp, hp.1⟩ + cases isEmpty_or_nonempty c + · exact ⟨I, disjoint, fun J hJ ↦ isEmptyElim (⟨J, hJ⟩ : c)⟩ + refine ⟨sSup c, Set.disjoint_left.mpr fun x hx ↦ ?_, fun _ ↦ le_sSup⟩ + have ⟨p, hp⟩ := (Submodule.mem_iSup_of_directed _ hc'.directed).mp (sSup_eq_iSup' c ▸ hx) + exact Set.disjoint_left.mp (hc p.2) hp + +theorem exists_le_prime_nmem_of_isIdempotentElem (a : α) (ha : IsIdempotentElem a) (haI : a ∉ I) : + ∃ p : Ideal α, p.IsPrime ∧ I ≤ p ∧ a ∉ p := + have : Disjoint (I : Set α) (Submonoid.powers a) := Set.disjoint_right.mpr <| by + rw [ha.coe_powers] + rintro _ (rfl|rfl) + exacts [I.ne_top_iff_one.mp (ne_of_mem_of_not_mem' Submodule.mem_top haI).symm, haI] + have ⟨p, h1, h2, h3⟩ := exists_le_prime_disjoint _ _ this + ⟨p, h1, h2, Set.disjoint_right.mp h3 (Submonoid.mem_powers a)⟩ + end Ideal end CommSemiring diff --git a/Mathlib/RingTheory/Ideal/Operations.lean b/Mathlib/RingTheory/Ideal/Operations.lean index fa9ad83e96b31..af540403ae860 100644 --- a/Mathlib/RingTheory/Ideal/Operations.lean +++ b/Mathlib/RingTheory/Ideal/Operations.lean @@ -287,9 +287,7 @@ variable {R : Type u} [Semiring R] theorem add_eq_sup {I J : Ideal R} : I + J = I ⊔ J := rfl --- dsimp loops when applying this lemma to its LHS, --- probably https://github.com/leanprover/lean4/pull/2867 -@[simp, nolint simpNF] +@[simp] theorem zero_eq_bot : (0 : Ideal R) = ⊥ := rfl @@ -453,9 +451,7 @@ lemma sup_pow_add_le_pow_sup_pow {n m : ℕ} : (I ⊔ J) ^ (n + m) ≤ I ^ n ⊔ ((Ideal.pow_le_pow_right hn).trans le_sup_left))) · refine (Ideal.mul_le_right.trans (Ideal.mul_le_left.trans ((Ideal.pow_le_pow_right ?_).trans le_sup_right))) - simp only [Finset.mem_range, Nat.lt_succ] at hi - rw [Nat.le_sub_iff_add_le hi] - nlinarith + omega variable (I J K) diff --git a/Mathlib/RingTheory/Ideal/Quotient/Noetherian.lean b/Mathlib/RingTheory/Ideal/Quotient/Noetherian.lean index abe698078c199..2f2f268de1998 100644 --- a/Mathlib/RingTheory/Ideal/Quotient/Noetherian.lean +++ b/Mathlib/RingTheory/Ideal/Quotient/Noetherian.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Anne Baanen -/ import Mathlib.RingTheory.Ideal.Quotient.Operations -import Mathlib.RingTheory.Noetherian.Defs +import Mathlib.RingTheory.Noetherian.Basic /-! # Noetherian quotient rings and quotient modules diff --git a/Mathlib/RingTheory/Ideal/Span.lean b/Mathlib/RingTheory/Ideal/Span.lean index e2f263723ce31..1b10889acf12f 100644 --- a/Mathlib/RingTheory/Ideal/Span.lean +++ b/Mathlib/RingTheory/Ideal/Span.lean @@ -237,3 +237,22 @@ theorem span_singleton_neg (x : α) : (span {-x} : Ideal α) = span {x} := by end Ideal end Ring + +namespace IsIdempotentElem + +variable {R} [CommRing R] {e : R} (he : IsIdempotentElem e) +include he + +theorem ker_toSpanSingleton_eq_span : + LinearMap.ker (LinearMap.toSpanSingleton R R e) = Ideal.span {1 - e} := SetLike.ext fun x ↦ by + rw [Ideal.mem_span_singleton'] + refine ⟨fun h ↦ ⟨x, by rw [mul_sub, show x * e = 0 from h, mul_one, sub_zero]⟩, fun h ↦ ?_⟩ + obtain ⟨x, rfl⟩ := h + show x * (1 - e) * e = 0 + rw [mul_assoc, sub_mul, one_mul, he, sub_self, mul_zero] + +theorem ker_toSpanSingleton_one_sub_eq_span : + LinearMap.ker (LinearMap.toSpanSingleton R R (1 - e)) = Ideal.span {e} := by + rw [ker_toSpanSingleton_eq_span he.one_sub, sub_sub_cancel] + +end IsIdempotentElem diff --git a/Mathlib/RingTheory/Idempotents.lean b/Mathlib/RingTheory/Idempotents.lean index ffc85853ec287..65b8c4836a131 100644 --- a/Mathlib/RingTheory/Idempotents.lean +++ b/Mathlib/RingTheory/Idempotents.lean @@ -7,6 +7,7 @@ import Mathlib.Algebra.GeomSum import Mathlib.Algebra.Polynomial.AlgebraMap import Mathlib.RingTheory.Ideal.Quotient.Operations import Mathlib.RingTheory.Nilpotent.Defs +import Mathlib.Tactic.StacksAttribute /-! @@ -346,6 +347,7 @@ theorem eq_of_isNilpotent_sub_of_isIdempotentElem {e₁ e₂ : R} e₁ = e₂ := eq_of_isNilpotent_sub_of_isIdempotentElem_of_commute he₁ he₂ H (.all _ _) +@[stacks 00J9] theorem existsUnique_isIdempotentElem_eq_of_ker_isNilpotent (h : ∀ x ∈ RingHom.ker f, IsNilpotent x) (e : S) (he : e ∈ f.range) (he' : IsIdempotentElem e) : ∃! e' : R, IsIdempotentElem e' ∧ f e' = e := by diff --git a/Mathlib/RingTheory/LaurentSeries.lean b/Mathlib/RingTheory/LaurentSeries.lean index d543b3fa95654..1e09014fa6640 100644 --- a/Mathlib/RingTheory/LaurentSeries.lean +++ b/Mathlib/RingTheory/LaurentSeries.lean @@ -869,7 +869,7 @@ theorem Cauchy.eventually_mem_nhds {ℱ : Filter K⸨X⸩} (hℱ : Cauchy ℱ) obtain ⟨γ, hU₁⟩ := Valued.mem_nhds.mp hU suffices ∀ᶠ f in ℱ, f ∈ {y : K⸨X⸩ | Valued.v (y - limit hℱ) < ↑γ} by apply this.mono fun _ hf ↦ hU₁ hf - set D := -(Multiplicative.toAdd (WithZero.unzero γ.ne_zero) - 1) with hD₀ + set D := -((WithZero.unzero γ.ne_zero).toAdd - 1) with hD₀ have hD : ((Multiplicative.ofAdd (-D) : Multiplicative ℤ) : ℤₘ₀) < γ := by rw [← WithZero.coe_unzero γ.ne_zero, WithZero.coe_lt_coe, hD₀, neg_neg, ofAdd_sub, ofAdd_toAdd, div_lt_comm, div_self', ← ofAdd_zero, Multiplicative.ofAdd_lt] @@ -933,7 +933,7 @@ theorem exists_ratFunc_val_lt (f : K⸨X⸩) (γ : ℤₘ₀ˣ) : · erw [hs, ← F_mul, PowerSeries.coe_pow, PowerSeries.coe_X, RatFunc.coe_mul, zpow_neg, zpow_ofNat, inv_eq_one_div (RatFunc.X ^ s), RatFunc.coe_div, RatFunc.coe_pow, RatFunc.coe_X, RatFunc.coe_one, ← inv_eq_one_div, ← mul_sub, map_mul, map_inv₀, ← PowerSeries.coe_X, - valuation_X_pow, ← hs, ← RatFunc.coe_coe, ← coe_sub, ← coe_algebraMap, + valuation_X_pow, ← hs, ← RatFunc.coe_coe, ← PowerSeries.coe_sub, ← coe_algebraMap, valuation_of_algebraMap, ← Units.val_mk0 (a := ((Multiplicative.ofAdd f.order : Multiplicative ℤ) : ℤₘ₀)), ← hη] apply inv_mul_lt_of_lt_mul₀ @@ -943,8 +943,8 @@ theorem exists_ratFunc_val_lt (f : K⸨X⸩) (γ : ℤₘ₀ˣ) : · obtain ⟨s, hs⟩ := Int.exists_eq_neg_ofNat (Int.neg_nonpos_of_nonneg (not_lt.mp ord_nonpos)) obtain ⟨P, hP⟩ := exists_Polynomial_intValuation_lt (PowerSeries.X ^ s * F) γ use P - erw [← X_order_mul_powerSeriesPart (neg_inj.1 hs).symm, ← RatFunc.coe_coe, ← coe_sub, - ← coe_algebraMap, valuation_of_algebraMap] + erw [← X_order_mul_powerSeriesPart (neg_inj.1 hs).symm, ← RatFunc.coe_coe, + ← PowerSeries.coe_sub, ← coe_algebraMap, valuation_of_algebraMap] exact hP theorem coe_range_dense : DenseRange ((↑) : RatFunc K → K⸨X⸩) := by @@ -981,7 +981,7 @@ theorem inducing_coe : IsUniformInducing ((↑) : RatFunc K → K⸨X⸩) := by refine ⟨⟨d, by rfl⟩, subset_trans (fun _ _ ↦ pre_R ?_) pre_T⟩ apply hd simp only [sub_zero, Set.mem_setOf_eq] - erw [← coe_sub, ← valuation_eq_LaurentSeries_valuation] + erw [← RatFunc.coe_sub, ← valuation_eq_LaurentSeries_valuation] assumption · rintro ⟨_, ⟨hT, pre_T⟩⟩ obtain ⟨d, hd⟩ := Valued.mem_nhds.mp hT @@ -993,7 +993,7 @@ theorem inducing_coe : IsUniformInducing ((↑) : RatFunc K → K⸨X⸩) := by · refine subset_trans (fun _ _ ↦ ?_) pre_T apply hd erw [Set.mem_setOf_eq, sub_zero, valuation_eq_LaurentSeries_valuation, - coe_sub] + RatFunc.coe_sub] assumption theorem continuous_coe : Continuous ((↑) : RatFunc K → K⸨X⸩) := diff --git a/Mathlib/RingTheory/LocalProperties/Exactness.lean b/Mathlib/RingTheory/LocalProperties/Exactness.lean new file mode 100644 index 0000000000000..3c6ae6bb837c7 --- /dev/null +++ b/Mathlib/RingTheory/LocalProperties/Exactness.lean @@ -0,0 +1,194 @@ +/- +Copyright (c) 2024 Sihan Su. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Sihan Su, Yongle Hu, Yi Song +-/ +import Mathlib.Algebra.Exact +import Mathlib.RingTheory.LocalProperties.Submodule +import Mathlib.RingTheory.Localization.Away.Basic + +/-! +# Local properties about linear maps + +In this file, we show that +injectivity, surjectivity, bijectivity and exactness of linear maps are local properties. +More precisely, we show that these can be checked at maximal ideals and on standard covers. + +-/ +open Submodule LocalizedModule Ideal LinearMap + +section isLocalized_maximal + +open IsLocalizedModule + +variable {R M N L : Type*} [CommSemiring R] [AddCommMonoid M] [Module R M] + [AddCommMonoid N] [Module R N] [AddCommMonoid L] [Module R L] + +variable + (Mₚ : ∀ (P : Ideal R) [P.IsMaximal], Type*) + [∀ (P : Ideal R) [P.IsMaximal], AddCommMonoid (Mₚ P)] + [∀ (P : Ideal R) [P.IsMaximal], Module R (Mₚ P)] + (f : ∀ (P : Ideal R) [P.IsMaximal], M →ₗ[R] Mₚ P) + [∀ (P : Ideal R) [P.IsMaximal], IsLocalizedModule P.primeCompl (f P)] + (Nₚ : ∀ (P : Ideal R) [P.IsMaximal], Type*) + [∀ (P : Ideal R) [P.IsMaximal], AddCommMonoid (Nₚ P)] + [∀ (P : Ideal R) [P.IsMaximal], Module R (Nₚ P)] + (g : ∀ (P : Ideal R) [P.IsMaximal], N →ₗ[R] Nₚ P) + [∀ (P : Ideal R) [P.IsMaximal], IsLocalizedModule P.primeCompl (g P)] + (Lₚ : ∀ (P : Ideal R) [P.IsMaximal], Type*) + [∀ (P : Ideal R) [P.IsMaximal], AddCommMonoid (Lₚ P)] + [∀ (P : Ideal R) [P.IsMaximal], Module R (Lₚ P)] + (h : ∀ (P : Ideal R) [P.IsMaximal], L →ₗ[R] Lₚ P) + [∀ (P : Ideal R) [P.IsMaximal], IsLocalizedModule P.primeCompl (h P)] + (F : M →ₗ[R] N) (G : N →ₗ[R] L) + +theorem injective_of_isLocalized_maximal + (H : ∀ (P : Ideal R) [P.IsMaximal], Function.Injective (map P.primeCompl (f P) (g P) F)) : + Function.Injective F := + fun x y eq ↦ Module.eq_of_localization_maximal _ f _ _ fun P _ ↦ H P <| by simp [eq] + +theorem surjective_of_isLocalized_maximal + (H : ∀ (P : Ideal R) [P.IsMaximal], Function.Surjective (map P.primeCompl (f P) (g P) F)) : + Function.Surjective F := + range_eq_top.mp <| eq_top_of_localization₀_maximal Nₚ g _ <| + fun P _ ↦ (range_localizedMap_eq_localized₀_range _ (f P) (g P) F).symm.trans <| + range_eq_top.mpr <| H P + +theorem bijective_of_isLocalized_maximal + (H : ∀ (P : Ideal R) [P.IsMaximal], Function.Bijective (map P.primeCompl (f P) (g P) F)) : + Function.Bijective F := + ⟨injective_of_isLocalized_maximal Mₚ f Nₚ g F fun J _ ↦ (H J).1, + surjective_of_isLocalized_maximal Mₚ f Nₚ g F fun J _ ↦ (H J).2⟩ + +theorem exact_of_isLocalized_maximal (H : ∀ (J : Ideal R) [J.IsMaximal], + Function.Exact (map J.primeCompl (f J) (g J) F) (map J.primeCompl (g J) (h J) G)) : + Function.Exact F G := by + simp only [LinearMap.exact_iff] at H ⊢ + apply eq_of_localization₀_maximal Nₚ g + intro J hJ + rw [← LinearMap.range_localizedMap_eq_localized₀_range _ (f J) (g J) F, + ← LinearMap.ker_localizedMap_eq_localized₀_ker J.primeCompl (g J) (h J) G] + have := SetLike.ext_iff.mp <| H J + ext x + simp only [mem_range, mem_ker] at this ⊢ + exact this x + +end isLocalized_maximal + +section localized_maximal + +variable {R M N L : Type*} [CommSemiring R] [AddCommMonoid M] [Module R M] + [AddCommMonoid N] [Module R N] [AddCommMonoid L] [Module R L] (f : M →ₗ[R] N) (g : N →ₗ[R] L) + +theorem injective_of_localized_maximal + (h : ∀ (J : Ideal R) [J.IsMaximal], Function.Injective (map J.primeCompl f)) : + Function.Injective f := + injective_of_isLocalized_maximal _ (fun _ _ ↦ mkLinearMap _ _) _ (fun _ _ ↦ mkLinearMap _ _) f h + +theorem surjective_of_localized_maximal + (h : ∀ (J : Ideal R) [J.IsMaximal], Function.Surjective (map J.primeCompl f)) : + Function.Surjective f := + surjective_of_isLocalized_maximal _ (fun _ _ ↦ mkLinearMap _ _) _ (fun _ _ ↦ mkLinearMap _ _) f h + +theorem bijective_of_localized_maximal + (h : ∀ (J : Ideal R) [J.IsMaximal], Function.Bijective (map J.primeCompl f)) : + Function.Bijective f := + ⟨injective_of_localized_maximal _ fun J _ ↦ (h J).1, + surjective_of_localized_maximal _ fun J _ ↦ (h J).2⟩ + +theorem exact_of_localized_maximal + (h : ∀ (J : Ideal R) [J.IsMaximal], Function.Exact (map J.primeCompl f) (map J.primeCompl g)) : + Function.Exact f g := + exact_of_isLocalized_maximal _ (fun _ _ ↦ mkLinearMap _ _) _ (fun _ _ ↦ mkLinearMap _ _) + _ (fun _ _ ↦ mkLinearMap _ _) f g h + +end localized_maximal + +section isLocalized_span + +open IsLocalizedModule + +variable {R M N L : Type*} [CommSemiring R] [AddCommMonoid M] [Module R M] + [AddCommMonoid N] [Module R N] [AddCommMonoid L] [Module R L] (s : Set R) (spn : Ideal.span s = ⊤) +include spn + +variable + (Mₚ : ∀ _ : s, Type*) + [∀ r : s, AddCommMonoid (Mₚ r)] + [∀ r : s, Module R (Mₚ r)] + (f : ∀ r : s, M →ₗ[R] Mₚ r) + [∀ r : s, IsLocalizedModule (.powers r.1) (f r)] + (Nₚ : ∀ _ : s, Type*) + [∀ r : s, AddCommMonoid (Nₚ r)] + [∀ r : s, Module R (Nₚ r)] + (g : ∀ r : s, N →ₗ[R] Nₚ r) + [∀ r : s, IsLocalizedModule (.powers r.1) (g r)] + (Lₚ : ∀ _ : s, Type*) + [∀ r : s, AddCommMonoid (Lₚ r)] + [∀ r : s, Module R (Lₚ r)] + (h : ∀ r : s, L →ₗ[R] Lₚ r) + [∀ r : s, IsLocalizedModule (.powers r.1) (h r)] + (F : M →ₗ[R] N) (G : N →ₗ[R] L) + +theorem injective_of_isLocalized_span + (H : ∀ r : s, Function.Injective (map (.powers r.1) (f r) (g r) F)) : + Function.Injective F := + fun x y eq ↦ Module.eq_of_isLocalized_span _ spn _ f _ _ fun P ↦ H P <| by simp [eq] + +theorem surjective_of_isLocalized_span + (H : ∀ r : s, Function.Surjective (map (.powers r.1) (f r) (g r) F)) : + Function.Surjective F := + range_eq_top.mp <| eq_top_of_isLocalized₀_span s spn Nₚ g fun r ↦ + (range_localizedMap_eq_localized₀_range _ (f r) (g r) F).symm.trans <| range_eq_top.mpr <| H r + +theorem bijective_of_isLocalized_span + (H : ∀ r : s, Function.Bijective (map (.powers r.1) (f r) (g r) F)) : + Function.Bijective F := + ⟨injective_of_isLocalized_span _ spn Mₚ f Nₚ g F fun r ↦ (H r).1, + surjective_of_isLocalized_span _ spn Mₚ f Nₚ g F fun r ↦ (H r).2⟩ + +lemma exact_of_isLocalized_span (H : ∀ r : s, Function.Exact + (map (.powers r.1) (f r) (g r) F) (map (.powers r.1) (g r) (h r) G)) : + Function.Exact F G := by + simp only [LinearMap.exact_iff] at H ⊢ + apply Submodule.eq_of_isLocalized₀_span s spn Nₚ g + intro r + rw [← LinearMap.range_localizedMap_eq_localized₀_range _ (f r) (g r) F] + rw [← LinearMap.ker_localizedMap_eq_localized₀_ker (.powers r.1) (g r) (h r) G] + have := SetLike.ext_iff.mp <| H r + ext x + simp only [mem_range, mem_ker] at this ⊢ + exact this x + +end isLocalized_span + +section localized_span + +variable {R M N L : Type*} [CommSemiring R] [AddCommMonoid M] [Module R M] + [AddCommMonoid N] [Module R N] [AddCommMonoid L] [Module R L] + (s : Set R) (spn : span s = ⊤) (f : M →ₗ[R] N) (g : N →ₗ[R] L) +include spn + +theorem injective_of_localized_span + (h : ∀ r : s, Function.Injective (map (.powers r.1) f)) : + Function.Injective f := + injective_of_isLocalized_span s spn _ (fun _ ↦ mkLinearMap _ _) _ (fun _ ↦ mkLinearMap _ _) f h + +theorem surjective_of_localized_span + (h : ∀ r : s, Function.Surjective (map (.powers r.1) f)) : + Function.Surjective f := + surjective_of_isLocalized_span s spn _ (fun _ ↦ mkLinearMap _ _) _ (fun _ ↦ mkLinearMap _ _) f h + +theorem bijective_of_localized_span + (h : ∀ r : s, Function.Bijective (map (.powers r.1) f)) : + Function.Bijective f := + ⟨injective_of_localized_span _ spn _ fun r ↦ (h r).1, + surjective_of_localized_span _ spn _ fun r ↦ (h r).2⟩ + +lemma exact_of_localized_span + (h : ∀ r : s, Function.Exact (map (.powers r.1) f) (map (.powers r.1) g)) : + Function.Exact f g := + exact_of_isLocalized_span s spn _ (fun _ ↦ mkLinearMap _ _) _ (fun _ ↦ mkLinearMap _ _) + _ (fun _ ↦ mkLinearMap _ _) f g h + +end localized_span diff --git a/Mathlib/RingTheory/LocalProperties/Projective.lean b/Mathlib/RingTheory/LocalProperties/Projective.lean index a2c4615a7942e..d6c0268663ed7 100644 --- a/Mathlib/RingTheory/LocalProperties/Projective.lean +++ b/Mathlib/RingTheory/LocalProperties/Projective.lean @@ -5,9 +5,9 @@ Authors: Andrew Yang, David Swinarski -/ import Mathlib.Algebra.Module.FinitePresentation import Mathlib.Algebra.Module.Projective -import Mathlib.LinearAlgebra.FreeModule.Basic +import Mathlib.LinearAlgebra.Dimension.Constructions +import Mathlib.LinearAlgebra.FreeModule.StrongRankCondition import Mathlib.RingTheory.LocalProperties.Submodule -import Mathlib.RingTheory.Localization.BaseChange /-! @@ -25,8 +25,43 @@ import Mathlib.RingTheory.Localization.BaseChange -/ -variable {R M N N'} [CommRing R] [AddCommGroup M] [Module R M] [AddCommGroup N] [Module R N] -variable [AddCommGroup N'] [Module R N'] (S : Submonoid R) +universe uM + +variable {R N N' : Type*} {M : Type uM} [CommRing R] [AddCommGroup M] [Module R M] [AddCommGroup N] +variable [Module R N] [AddCommGroup N'] [Module R N'] (S : Submonoid R) + +theorem Module.free_of_isLocalizedModule {Rₛ Mₛ} [AddCommGroup Mₛ] [Module R Mₛ] + [CommRing Rₛ] [Algebra R Rₛ] [Module Rₛ Mₛ] [IsScalarTower R Rₛ Mₛ] + (S) (f : M →ₗ[R] Mₛ) [IsLocalization S Rₛ] [IsLocalizedModule S f] [Module.Free R M] : + Module.Free Rₛ Mₛ := + Free.of_equiv (IsLocalizedModule.isBaseChange S Rₛ f).equiv + +universe uR' uM' in +/-- +Also see `IsLocalizedModule.lift_rank_eq` for a version for non-free modules, +but requires `S` to not contain any zero-divisors. +-/ +theorem Module.lift_rank_of_isLocalizedModule_of_free + (Rₛ : Type uR') {Mₛ : Type uM'} [AddCommGroup Mₛ] [Module R Mₛ] + [CommRing Rₛ] [Algebra R Rₛ] [Module Rₛ Mₛ] [IsScalarTower R Rₛ Mₛ] (S : Submonoid R) + (f : M →ₗ[R] Mₛ) [IsLocalization S Rₛ] [IsLocalizedModule S f] [Module.Free R M] + [Nontrivial Rₛ] : + Cardinal.lift.{uM} (Module.rank Rₛ Mₛ) = Cardinal.lift.{uM'} (Module.rank R M) := by + apply Cardinal.lift_injective.{max uM' uR'} + have := (algebraMap R Rₛ).domain_nontrivial + have := (IsLocalizedModule.isBaseChange S Rₛ f).equiv.lift_rank_eq.symm + simp only [rank_tensorProduct, rank_self, + Cardinal.lift_one, one_mul, Cardinal.lift_lift] at this ⊢ + convert this + exact Cardinal.lift_umax + +theorem Module.finrank_of_isLocalizedModule_of_free + (Rₛ : Type*) {Mₛ : Type*} [AddCommGroup Mₛ] [Module R Mₛ] + [CommRing Rₛ] [Algebra R Rₛ] [Module Rₛ Mₛ] [IsScalarTower R Rₛ Mₛ] (S : Submonoid R) + (f : M →ₗ[R] Mₛ) [IsLocalization S Rₛ] [IsLocalizedModule S f] [Module.Free R M] + [Nontrivial Rₛ] : + Module.finrank Rₛ Mₛ = Module.finrank R M := by + simpa using congr(Cardinal.toNat $(Module.lift_rank_of_isLocalizedModule_of_free Rₛ S f)) theorem Module.projective_of_isLocalizedModule {Rₛ Mₛ} [AddCommGroup Mₛ] [Module R Mₛ] [CommRing Rₛ] [Algebra R Rₛ] [Module Rₛ Mₛ] [IsScalarTower R Rₛ Mₛ] diff --git a/Mathlib/RingTheory/LocalProperties/Submodule.lean b/Mathlib/RingTheory/LocalProperties/Submodule.lean index 2ecaa20be887a..90ade41827edf 100644 --- a/Mathlib/RingTheory/LocalProperties/Submodule.lean +++ b/Mathlib/RingTheory/LocalProperties/Submodule.lean @@ -5,6 +5,7 @@ Authors: Andrew Yang, David Swinarski -/ import Mathlib.Algebra.Module.LocalizedModule.Submodule import Mathlib.RingTheory.Localization.AtPrime +import Mathlib.RingTheory.Localization.Away.Basic /-! # Local properties of modules and submodules @@ -80,8 +81,8 @@ theorem Submodule.eq_top_of_localization₀_maximal (N : Submodule R M) theorem Module.eq_of_localization_maximal (m m' : M) (h : ∀ (P : Ideal R) [P.IsMaximal], f P m = f P m') : m = m' := by - by_contra! ne - rw [← one_smul R m, ← one_smul R m'] at ne + rw [← one_smul R m, ← one_smul R m'] + by_contra ne have ⟨P, mP, le⟩ := (eqIdeal R m m').exists_le_maximal ((Ideal.ne_top_iff_one _).mpr ne) have ⟨s, hs⟩ := (IsLocalizedModule.eq_iff_exists P.primeCompl _).mp (h P) exact s.2 (le hs) @@ -124,3 +125,79 @@ theorem Submodule.eq_top_of_localization_maximal (N : Submodule R M) Submodule.eq_of_localization_maximal Rₚ Mₚ f fun P hP ↦ by simpa using h P end maximal + +section span + +open IsLocalizedModule LocalizedModule Ideal + +variable (s : Set R) (span_eq : Ideal.span s = ⊤) +include span_eq + +variable + (Rₚ : ∀ _ : s, Type*) + [∀ r : s, CommSemiring (Rₚ r)] + [∀ r : s, Algebra R (Rₚ r)] + [∀ r : s, IsLocalization.Away r.1 (Rₚ r)] + (Mₚ : ∀ _ : s, Type*) + [∀ r : s, AddCommMonoid (Mₚ r)] + [∀ r : s, Module R (Mₚ r)] + [∀ r : s, Module (Rₚ r) (Mₚ r)] + [∀ r : s, IsScalarTower R (Rₚ r) (Mₚ r)] + (f : ∀ r : s, M →ₗ[R] Mₚ r) + [∀ r : s, IsLocalizedModule (.powers r.1) (f r)] + +theorem Module.eq_of_isLocalized_span (x y : M) (h : ∀ r : s, f r x = f r y) : x = y := by + suffices Module.eqIdeal R x y = ⊤ by simpa [Module.eqIdeal] using (eq_top_iff_one _).mp this + by_contra ne + have ⟨r, hrs, disj⟩ := exists_disjoint_powers_of_span_eq_top s span_eq _ ne + let r : s := ⟨r, hrs⟩ + have ⟨⟨_, n, rfl⟩, eq⟩ := (IsLocalizedModule.eq_iff_exists (.powers r.1) _).mp (h r) + exact Set.disjoint_left.mp disj eq ⟨n, rfl⟩ + +theorem Module.eq_zero_of_isLocalized_span (x : M) (h : ∀ r : s, f r x = 0) : x = 0 := + eq_of_isLocalized_span s span_eq _ f x 0 <| by simpa only [map_zero] using h + +theorem Submodule.mem_of_isLocalized_span {m : M} {N : Submodule R M} + (h : ∀ r : s, f r m ∈ N.localized₀ (.powers r.1) (f r)) : m ∈ N := by + let I : Ideal R := N.comap (LinearMap.toSpanSingleton R M m) + suffices I = ⊤ by simpa [I] using I.eq_top_iff_one.mp this + by_contra! ne + have ⟨r, hrs, disj⟩ := exists_disjoint_powers_of_span_eq_top s span_eq _ ne + let r : s := ⟨r, hrs⟩ + obtain ⟨a, ha, t, e⟩ := h r + rw [← IsLocalizedModule.mk'_one (.powers r.1), IsLocalizedModule.mk'_eq_mk'_iff] at e + have ⟨u, hu⟩ := e + simp_rw [smul_smul] at hu + exact Set.disjoint_right.mp disj (u * t).2 (by apply hu ▸ smul_mem _ _ ha) + +theorem Submodule.le_of_isLocalized_span {N P : Submodule R M} + (h : ∀ r : s, N.localized₀ (.powers r.1) (f r) ≤ P.localized₀ (.powers r.1) (f r)) : N ≤ P := + fun m hm ↦ mem_of_isLocalized_span s span_eq _ f fun r ↦ h r ⟨m, hm, 1, by simp⟩ + +theorem Submodule.eq_of_isLocalized₀_span {N P : Submodule R M} + (h : ∀ r : s, N.localized₀ (.powers r.1) (f r) = P.localized₀ (.powers r.1) (f r)) : N = P := + le_antisymm (le_of_isLocalized_span s span_eq _ _ fun r ↦ (h r).le) + (le_of_isLocalized_span s span_eq _ _ fun r ↦ (h r).ge) + +theorem Submodule.eq_bot_of_isLocalized₀_span {N : Submodule R M} + (h : ∀ r : s, N.localized₀ (.powers r.1) (f r) = ⊥) : N = ⊥ := + eq_of_isLocalized₀_span s span_eq Mₚ f fun _ ↦ by simp only [h, Submodule.localized₀_bot] + +theorem Submodule.eq_top_of_isLocalized₀_span {N : Submodule R M} + (h : ∀ r : s, N.localized₀ (.powers r.1) (f r) = ⊤) : N = ⊤ := + eq_of_isLocalized₀_span s span_eq Mₚ f fun _ ↦ by simp only [h, Submodule.localized₀_top] + +theorem Submodule.eq_of_isLocalized'_span {N P : Submodule R M} + (h : ∀ r, N.localized' (Rₚ r) (.powers r.1) (f r) = P.localized' (Rₚ r) (.powers r.1) (f r)) : + N = P := + eq_of_isLocalized₀_span s span_eq _ f fun r ↦ congr(restrictScalars _ $(h r)) + +theorem Submodule.eq_bot_of_isLocalized'_span {N : Submodule R M} + (h : ∀ r : s, N.localized' (Rₚ r) (.powers r.1) (f r) = ⊥) : N = ⊥ := + eq_of_isLocalized'_span s span_eq Rₚ Mₚ f fun _ ↦ by simp only [h, Submodule.localized'_bot] + +theorem Submodule.eq_top_of_isLocalized'_span {N : Submodule R M} + (h : ∀ r : s, N.localized' (Rₚ r) (.powers r.1) (f r) = ⊤) : N = ⊤ := + eq_of_isLocalized'_span s span_eq Rₚ Mₚ f fun _ ↦ by simp only [h, Submodule.localized'_top] + +end span diff --git a/Mathlib/RingTheory/Localization/AtPrime.lean b/Mathlib/RingTheory/Localization/AtPrime.lean index 65cccdc214ca9..1337c943de11e 100644 --- a/Mathlib/RingTheory/Localization/AtPrime.lean +++ b/Mathlib/RingTheory/Localization/AtPrime.lean @@ -31,7 +31,7 @@ commutative ring, field of fractions -/ -variable {R : Type*} [CommSemiring R] (M : Submonoid R) (S : Type*) [CommSemiring S] +variable {R : Type*} [CommSemiring R] (S : Type*) [CommSemiring S] variable [Algebra R S] {P : Type*} [CommSemiring P] section AtPrime @@ -250,3 +250,23 @@ theorem localRingHom_comp {S : Type*} [CommSemiring S] (J : Ideal S) [hJ : J.IsP simp only [Function.comp_apply, RingHom.coe_comp, localRingHom_to_map] end Localization + +namespace RingHom + +variable (R) + +/-- The canonical ring homomorphism from a commutative semiring to the product of its +localizations at all maximal ideals. It is always injective. -/ +def toLocalizationIsMaximal : R →+* + Π I : {I : Ideal R // I.IsMaximal}, haveI : I.1.IsMaximal := I.2; Localization.AtPrime I.1 := + Pi.ringHom fun _ ↦ algebraMap R _ + +theorem toLocalizationIsMaximal_injective : + Function.Injective (RingHom.toLocalizationIsMaximal R) := fun r r' eq ↦ by + rw [← one_mul r, ← one_mul r'] + by_contra ne + have ⟨I, mI, hI⟩ := (Module.eqIdeal R r r').exists_le_maximal ((Ideal.ne_top_iff_one _).mpr ne) + have ⟨s, hs⟩ := (IsLocalization.eq_iff_exists I.primeCompl _).mp (congr_fun eq ⟨I, mI⟩) + exact s.2 (hI hs) + +end RingHom diff --git a/Mathlib/RingTheory/Localization/Away/Basic.lean b/Mathlib/RingTheory/Localization/Away/Basic.lean index 01a01a331e08b..ae069a4b51072 100644 --- a/Mathlib/RingTheory/Localization/Away/Basic.lean +++ b/Mathlib/RingTheory/Localization/Away/Basic.lean @@ -297,53 +297,42 @@ end AtUnits section Prod -lemma away_of_isIdempotentElem {R S} [CommRing R] [CommRing S] [Algebra R S] +lemma away_of_isIdempotentElem_of_mul {R S} [CommSemiring R] [CommSemiring S] [Algebra R S] {e : R} (he : IsIdempotentElem e) - (H : RingHom.ker (algebraMap R S) = Ideal.span {1 - e}) + (H : ∀ x y, algebraMap R S x = algebraMap R S y ↔ e * x = e * y) (H' : Function.Surjective (algebraMap R S)) : IsLocalization.Away e S where map_units' r := by - have : algebraMap R S e = 1 := by - rw [← (algebraMap R S).map_one, eq_comm, ← sub_eq_zero, ← map_sub, ← RingHom.mem_ker, - H, Ideal.mem_span_singleton] obtain ⟨r, n, rfl⟩ := r - simp [this] + simp [show algebraMap R S e = 1 by rw [← (algebraMap R S).map_one, H, mul_one, he]] surj' z := by obtain ⟨z, rfl⟩ := H' z exact ⟨⟨z, 1⟩, by simp⟩ - exists_of_eq {x y} h := by - rw [← sub_eq_zero, ← map_sub, ← RingHom.mem_ker, H, Ideal.mem_span_singleton] at h - obtain ⟨k, hk⟩ := h - refine ⟨⟨e, Submonoid.mem_powers e⟩, ?_⟩ - rw [← sub_eq_zero, ← mul_sub, hk, ← mul_assoc, mul_sub, mul_one, he.eq, sub_self, zero_mul] + exists_of_eq {x y} h := ⟨⟨e, Submonoid.mem_powers e⟩, (H x y).mp h⟩ -instance away_fst {R S} [CommRing R] [CommRing S] : +lemma away_of_isIdempotentElem {R S} [CommRing R] [CommRing S] [Algebra R S] + {e : R} (he : IsIdempotentElem e) + (H : RingHom.ker (algebraMap R S) = Ideal.span {1 - e}) + (H' : Function.Surjective (algebraMap R S)) : + IsLocalization.Away e S := + away_of_isIdempotentElem_of_mul he (fun x y ↦ by + rw [← sub_eq_zero, ← map_sub, ← RingHom.mem_ker, H, ← he.ker_toSpanSingleton_eq_span, + LinearMap.mem_ker, LinearMap.toSpanSingleton_apply, sub_smul, sub_eq_zero] + simp_rw [mul_comm e, smul_eq_mul]) H' + +instance away_fst {R S} [CommSemiring R] [CommSemiring S] : letI := (RingHom.fst R S).toAlgebra - IsLocalization.Away (R := R × S) (1, 0) R := by + IsLocalization.Away (R := R × S) (1, 0) R := letI := (RingHom.fst R S).toAlgebra - apply away_of_isIdempotentElem - · ext <;> simp - · ext x - simp only [RingHom.algebraMap_toAlgebra, RingHom.mem_ker, RingHom.coe_fst, - Ideal.mem_span_singleton, Prod.one_eq_mk, Prod.mk_sub_mk, sub_self, sub_zero] - constructor - · intro e; use x; ext <;> simp [e] - · rintro ⟨⟨i, j⟩, rfl⟩; simp - · exact Prod.fst_surjective - -instance away_snd {R S} [CommRing R] [CommRing S] : + away_of_isIdempotentElem_of_mul (by ext <;> simp) + (fun ⟨xR, xS⟩ ⟨yR, yS⟩ ↦ show xR = yR ↔ _ by simp) Prod.fst_surjective + +instance away_snd {R S} [CommSemiring R] [CommSemiring S] : letI := (RingHom.snd R S).toAlgebra - IsLocalization.Away (R := R × S) (0, 1) S := by + IsLocalization.Away (R := R × S) (0, 1) S := letI := (RingHom.snd R S).toAlgebra - apply away_of_isIdempotentElem - · ext <;> simp - · ext x - simp only [RingHom.algebraMap_toAlgebra, RingHom.mem_ker, RingHom.coe_snd, - Ideal.mem_span_singleton, Prod.one_eq_mk, Prod.mk_sub_mk, sub_self, sub_zero] - constructor - · intro e; use x; ext <;> simp [e] - · rintro ⟨⟨i, j⟩, rfl⟩; simp - · exact Prod.snd_surjective + away_of_isIdempotentElem_of_mul (by ext <;> simp) + (fun ⟨xR, xS⟩ ⟨yR, yS⟩ ↦ show xS = yS ↔ _ by simp) Prod.snd_surjective end Prod diff --git a/Mathlib/RingTheory/Localization/Away/Lemmas.lean b/Mathlib/RingTheory/Localization/Away/Lemmas.lean index 640763c874cbe..dc5d5600d2f7f 100644 --- a/Mathlib/RingTheory/Localization/Away/Lemmas.lean +++ b/Mathlib/RingTheory/Localization/Away/Lemmas.lean @@ -15,9 +15,7 @@ This file contains lemmas on localization away from an element requiring more im variable {R : Type*} [CommRing R] -namespace IsLocalization - -namespace Away +namespace IsLocalization.Away /-- Given a set `s` in a ring `R` and for every `t : s` a set `p t` of fractions in a localization of `R` at `t`, this is the function sending a pair `(t, y)`, with @@ -61,6 +59,8 @@ lemma span_range_mulNumerator_eq_top {s : Set R} use n + m simpa [pow_add, hc] using Ideal.mul_mem_left _ _ hy -end Away +lemma quotient_of_isIdempotentElem {e : R} (he : IsIdempotentElem e) : + IsLocalization.Away e (R ⧸ Ideal.span {1 - e}) := + away_of_isIdempotentElem he Ideal.mk_ker Quotient.mk_surjective -end IsLocalization +end IsLocalization.Away diff --git a/Mathlib/RingTheory/Localization/Basic.lean b/Mathlib/RingTheory/Localization/Basic.lean index f2d6adffdcf45..9159d55e9cdbd 100644 --- a/Mathlib/RingTheory/Localization/Basic.lean +++ b/Mathlib/RingTheory/Localization/Basic.lean @@ -73,7 +73,7 @@ open Function section CommSemiring -variable {R : Type*} [CommSemiring R] {M : Submonoid R} {S : Type*} [CommSemiring S] +variable {R : Type*} [CommSemiring R] {M N : Submonoid R} {S : Type*} [CommSemiring S] variable [Algebra R S] {P : Type*} [CommSemiring P] namespace IsLocalization @@ -237,7 +237,7 @@ end IsLocalization section -variable (M) +variable (M N) theorem isLocalization_of_algEquiv [Algebra R P] [IsLocalization M S] (h : S ≃ₐ[R] P) : IsLocalization M P := by @@ -265,6 +265,14 @@ theorem isLocalization_iff_of_ringEquiv (h : S ≃+* P) : letI := (h.toRingHom.comp <| algebraMap R S).toAlgebra isLocalization_iff_of_algEquiv M { h with commutes' := fun _ => rfl } +variable (S) in +/-- If an algebra is simultaneously localizations for two submonoids, then an arbitrary algebra +is a localization of one submonoid iff it is a localization of the other. -/ +theorem isLocalization_iff_of_isLocalization [IsLocalization M S] [IsLocalization N S] + [Algebra R P] : IsLocalization M P ↔ IsLocalization N P := + ⟨fun _ ↦ isLocalization_of_algEquiv N (algEquiv M S P), + fun _ ↦ isLocalization_of_algEquiv M (algEquiv N S P)⟩ + end variable (M) diff --git a/Mathlib/RingTheory/Localization/Defs.lean b/Mathlib/RingTheory/Localization/Defs.lean index 486cd6a8eb03e..60509638366d3 100644 --- a/Mathlib/RingTheory/Localization/Defs.lean +++ b/Mathlib/RingTheory/Localization/Defs.lean @@ -140,6 +140,11 @@ theorem of_le (N : Submonoid R) (h₁ : M ≤ N) (h₂ : ∀ r ∈ N, IsUnit (al rintro ⟨c, hc⟩ exact ⟨⟨c, h₁ c.2⟩, hc⟩ +theorem of_le_of_exists_dvd (N : Submonoid R) (h₁ : M ≤ N) (h₂ : ∀ n ∈ N, ∃ m ∈ M, n ∣ m) : + IsLocalization N S := + of_le M N h₁ fun n hn ↦ have ⟨m, hm, dvd⟩ := h₂ n hn + isUnit_of_dvd_unit (map_dvd _ dvd) (map_units S ⟨m, hm⟩) + variable (S) /-- `IsLocalization.toLocalizationWithZeroMap M S` shows `S` is the monoid localization of diff --git a/Mathlib/RingTheory/Localization/FractionRing.lean b/Mathlib/RingTheory/Localization/FractionRing.lean index fb9b40025a8df..155c5ec2966a3 100644 --- a/Mathlib/RingTheory/Localization/FractionRing.lean +++ b/Mathlib/RingTheory/Localization/FractionRing.lean @@ -39,7 +39,7 @@ variable [Algebra R S] {P : Type*} [CommRing P] variable {A : Type*} [CommRing A] (K : Type*) -- TODO: should this extend `Algebra` instead of assuming it? -/-- `IsFractionRing R K` states `K` is the field of fractions of an integral domain `R`. -/ +/-- `IsFractionRing R K` states `K` is the ring of fractions of a commutative ring `R`. -/ abbrev IsFractionRing [CommRing K] [Algebra R K] := IsLocalization (nonZeroDivisors R) K @@ -186,8 +186,8 @@ theorem mk'_eq_one_iff_eq {x : A} {y : nonZeroDivisors A} : mk' K x y = 1 ↔ x section Subfield variable (A K) in -/-- If `A` is a ring with fraction field `K`, then the subfield of `K` generated by the image of -`algebraMap A K` is equal to the whole field `K`. -/ +/-- If `A` is a commutative ring with fraction field `K`, then the subfield of `K` generated by +the image of `algebraMap A K` is equal to the whole field `K`. -/ theorem closure_range_algebraMap : Subfield.closure (Set.range (algebraMap A K)) = ⊤ := top_unique fun z _ ↦ by obtain ⟨_, _, -, rfl⟩ := div_surjective (A := A) z @@ -195,16 +195,16 @@ theorem closure_range_algebraMap : Subfield.closure (Set.range (algebraMap A K)) variable {L : Type*} [Field L] {g : A →+* L} {f : K →+* L} -/-- If `A` is a ring with fraction field `K`, `L` is a field, `g : A →+* L` lifts to `f : K →+* L`, -then the image of `f` is the field generated by the image of `g`. -/ +/-- If `A` is a commutative ring with fraction field `K`, `L` is a field, `g : A →+* L` lifts to +`f : K →+* L`, then the image of `f` is the subfield generated by the image of `g`. -/ theorem ringHom_fieldRange_eq_of_comp_eq (h : RingHom.comp f (algebraMap A K) = g) : f.fieldRange = Subfield.closure g.range := by rw [f.fieldRange_eq_map, ← closure_range_algebraMap A K, f.map_field_closure, ← Set.range_comp, ← f.coe_comp, h, g.coe_range] -/-- If `A` is a ring with fraction field `K`, `L` is a field, `g : A →+* L` lifts to `f : K →+* L`, -`s` is a set such that the image of `g` is the subring generated by `s`, -then the image of `f` is the field generated by `s`. -/ +/-- If `A` is a commutative ring with fraction field `K`, `L` is a field, `g : A →+* L` lifts to +`f : K →+* L`, `s` is a set such that the image of `g` is the subring generated by `s`, +then the image of `f` is the subfield generated by `s`. -/ theorem ringHom_fieldRange_eq_of_comp_eq_of_range_eq (h : RingHom.comp f (algebraMap A K) = g) {s : Set L} (hs : g.range = Subring.closure s) : f.fieldRange = Subfield.closure s := by rw [ringHom_fieldRange_eq_of_comp_eq h, hs] @@ -215,7 +215,7 @@ end Subfield open Function -/-- Given an integral domain `A` with field of fractions `K`, +/-- Given a commutative ring `A` with field of fractions `K`, and an injective ring hom `g : A →+* L` where `L` is a field, we get a field hom sending `z : K` to `g x * (g y)⁻¹`, where `(x, y) : A × (NonZeroDivisors A)` are such that `z = f x * (f y)⁻¹`. -/ @@ -241,7 +241,7 @@ theorem liftAlgHom_apply : liftAlgHom hg x = lift hg x := rfl end liftAlgHom -/-- Given an integral domain `A` with field of fractions `K`, +/-- Given a commutative ring `A` with field of fractions `K`, and an injective ring hom `g : A →+* L` where `L` is a field, the field hom induced from `K` to `L` maps `x` to `g x` for all `x : A`. -/ @@ -249,15 +249,28 @@ the field hom induced from `K` to `L` maps `x` to `g x` for all theorem lift_algebraMap (hg : Injective g) (x) : lift hg (algebraMap A K x) = g x := lift_eq _ _ -/-- Given an integral domain `A` with field of fractions `K`, +/-- The image of `IsFractionRing.lift` is the subfield generated by the image +of the ring hom. -/ +theorem lift_fieldRange (hg : Injective g) : + (lift hg : K →+* L).fieldRange = Subfield.closure g.range := + ringHom_fieldRange_eq_of_comp_eq (by ext; simp) + +/-- The image of `IsFractionRing.lift` is the subfield generated by `s`, if the image +of the ring hom is the subring generated by `s`. -/ +theorem lift_fieldRange_eq_of_range_eq (hg : Injective g) + {s : Set L} (hs : g.range = Subring.closure s) : + (lift hg : K →+* L).fieldRange = Subfield.closure s := + ringHom_fieldRange_eq_of_comp_eq_of_range_eq (by ext; simp) hs + +/-- Given a commutative ring `A` with field of fractions `K`, and an injective ring hom `g : A →+* L` where `L` is a field, field hom induced from `K` to `L` maps `f x / f y` to `g x / g y` for all `x : A, y ∈ NonZeroDivisors A`. -/ theorem lift_mk' (hg : Injective g) (x) (y : nonZeroDivisors A) : lift hg (mk' K x y) = g x / g y := by simp only [mk'_eq_div, map_div₀, lift_algebraMap] -/-- Given integral domains `A, B` with fields of fractions `K`, `L` -and an injective ring hom `j : A →+* B`, we get a field hom +/-- Given commutative rings `A, B` where `B` is an integral domain, with fraction rings `K`, `L` +and an injective ring hom `j : A →+* B`, we get a ring hom sending `z : K` to `g (j x) * (g (j y))⁻¹`, where `(x, y) : A × (NonZeroDivisors A)` are such that `z = f x * (f y)⁻¹`. -/ noncomputable def map {A B K L : Type*} [CommRing A] [CommRing B] [IsDomain B] [CommRing K] diff --git a/Mathlib/RingTheory/Localization/Integral.lean b/Mathlib/RingTheory/Localization/Integral.lean index d2b5cef36d5e2..ad327225f2383 100644 --- a/Mathlib/RingTheory/Localization/Integral.lean +++ b/Mathlib/RingTheory/Localization/Integral.lean @@ -25,7 +25,7 @@ commutative ring, field of fractions variable {R : Type*} [CommRing R] (M : Submonoid R) {S : Type*} [CommRing S] -variable [Algebra R S] {P : Type*} [CommRing P] +variable [Algebra R S] open Polynomial @@ -366,7 +366,7 @@ theorem isAlgebraic_iff' [Field K] [IsDomain R] [IsDomain S] [Algebra R K] [Alge rw [div_eq_mul_inv] refine IsIntegral.mul ?_ ?_ · rw [← isAlgebraic_iff_isIntegral] - refine .tower_top_of_injective + refine .extendScalars (NoZeroSMulDivisors.algebraMap_injective R (FractionRing R)) ?_ exact .algebraMap (h a) · rw [← isAlgebraic_iff_isIntegral] diff --git a/Mathlib/RingTheory/Localization/LocalizationLocalization.lean b/Mathlib/RingTheory/Localization/LocalizationLocalization.lean index 62db6f2a12761..0637b7cd2c470 100644 --- a/Mathlib/RingTheory/Localization/LocalizationLocalization.lean +++ b/Mathlib/RingTheory/Localization/LocalizationLocalization.lean @@ -27,8 +27,7 @@ namespace IsLocalization section LocalizationLocalization -variable {R : Type*} [CommSemiring R] (M : Submonoid R) {S : Type*} [CommSemiring S] -variable [Algebra R S] {P : Type*} [CommSemiring P] +variable {R : Type*} [CommSemiring R] (M : Submonoid R) {S : Type*} [CommSemiring S] [Algebra R S] variable (N : Submonoid S) (T : Type*) [CommSemiring T] [Algebra R T] @@ -251,7 +250,7 @@ end IsLocalization namespace IsFractionRing -variable {R : Type*} [CommRing R] (M : Submonoid R) {S : Type*} [CommRing S] +variable {R : Type*} [CommRing R] (M : Submonoid R) open IsLocalization diff --git a/Mathlib/RingTheory/Nilpotent/Basic.lean b/Mathlib/RingTheory/Nilpotent/Basic.lean index 9eddb6417010a..602de4bcb8dbd 100644 --- a/Mathlib/RingTheory/Nilpotent/Basic.lean +++ b/Mathlib/RingTheory/Nilpotent/Basic.lean @@ -91,6 +91,14 @@ lemma IsNilpotent.not_isUnit [Ring R] [Nontrivial R] {x : R} (hx : IsNilpotent x ¬ IsUnit x := mt IsUnit.not_isNilpotent (by simpa only [not_not] using hx) +lemma IsIdempotentElem.eq_zero_of_isNilpotent [MonoidWithZero R] {e : R} + (idem : IsIdempotentElem e) (nilp : IsNilpotent e) : e = 0 := by + obtain ⟨rfl | n, hn⟩ := nilp + · rw [pow_zero] at hn; rw [← one_mul e, hn, zero_mul] + · rw [← hn, idem.pow_succ_eq] + +alias IsNilpotent.eq_zero_of_isIdempotentElem := IsIdempotentElem.eq_zero_of_isNilpotent + instance [Zero R] [Pow R ℕ] [Zero S] [Pow S ℕ] [IsReduced R] [IsReduced S] : IsReduced (R × S) where eq_zero _ := fun ⟨n, hn⟩ ↦ have hn := Prod.ext_iff.1 hn Prod.ext (IsReduced.eq_zero _ ⟨n, hn.1⟩) (IsReduced.eq_zero _ ⟨n, hn.2⟩) diff --git a/Mathlib/RingTheory/Noetherian/Basic.lean b/Mathlib/RingTheory/Noetherian/Basic.lean new file mode 100644 index 0000000000000..38156a143989d --- /dev/null +++ b/Mathlib/RingTheory/Noetherian/Basic.lean @@ -0,0 +1,366 @@ +/- +Copyright (c) 2018 Mario Carneiro, Kevin Buzzard. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Mario Carneiro, Kevin Buzzard +-/ +import Mathlib.LinearAlgebra.Quotient.Basic +import Mathlib.RingTheory.Noetherian.Defs +import Mathlib.RingTheory.Finiteness.Cardinality +import Mathlib.RingTheory.Finiteness.Finsupp +import Mathlib.RingTheory.Ideal.Maps + +/-! +# Noetherian rings and modules + +The following are equivalent for a module M over a ring R: +1. Every increasing chain of submodules M₁ ⊆ M₂ ⊆ M₃ ⊆ ⋯ eventually stabilises. +2. Every submodule is finitely generated. + +A module satisfying these equivalent conditions is said to be a *Noetherian* R-module. +A ring is a *Noetherian ring* if it is Noetherian as a module over itself. + +(Note that we do not assume yet that our rings are commutative, +so perhaps this should be called "left Noetherian". +To avoid cumbersome names once we specialize to the commutative case, +we don't make this explicit in the declaration names.) + +## Main definitions + +Let `R` be a ring and let `M` and `P` be `R`-modules. Let `N` be an `R`-submodule of `M`. + +* `IsNoetherian R M` is the proposition that `M` is a Noetherian `R`-module. It is a class, + implemented as the predicate that all `R`-submodules of `M` are finitely generated. + +## Main statements + +* `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`. + +## References + +* [M. F. Atiyah and I. G. Macdonald, *Introduction to commutative algebra*][atiyah-macdonald] +* [samuel1967] + +## Tags + +Noetherian, noetherian, Noetherian ring, Noetherian module, noetherian ring, noetherian module + +-/ + +assert_not_exists Matrix + +open Set Pointwise + +section + +variable {R : Type*} {M : Type*} {P : Type*} +variable [Semiring R] [AddCommMonoid M] [AddCommMonoid P] +variable [Module R M] [Module R P] + +open IsNoetherian + +variable (M) + +theorem isNoetherian_of_surjective (f : M →ₗ[R] P) (hf : LinearMap.range f = ⊤) [IsNoetherian R M] : + IsNoetherian R P := + ⟨fun s => + have : (s.comap f).map f = s := Submodule.map_comap_eq_self <| hf.symm ▸ le_top + this ▸ (noetherian _).map _⟩ + +variable {M} + +instance isNoetherian_range (f : M →ₗ[R] P) [IsNoetherian R M] : + IsNoetherian R (LinearMap.range f) := + isNoetherian_of_surjective _ _ f.range_rangeRestrict + +instance isNoetherian_quotient {A M : Type*} [Ring A] [AddCommGroup M] [SMul R A] [Module R M] + [Module A M] [IsScalarTower R A M] (N : Submodule A M) [IsNoetherian R M] : + IsNoetherian R (M ⧸ N) := + isNoetherian_of_surjective M ((Submodule.mkQ N).restrictScalars R) <| + LinearMap.range_eq_top.mpr N.mkQ_surjective + +@[deprecated (since := "2024-04-27"), nolint defLemma] +alias Submodule.Quotient.isNoetherian := isNoetherian_quotient + +theorem isNoetherian_of_linearEquiv (f : M ≃ₗ[R] P) [IsNoetherian R M] : IsNoetherian R P := + isNoetherian_of_surjective _ f.toLinearMap f.range + +theorem LinearEquiv.isNoetherian_iff (f : M ≃ₗ[R] P) : IsNoetherian R M ↔ IsNoetherian R P := + ⟨fun _ ↦ isNoetherian_of_linearEquiv f, fun _ ↦ isNoetherian_of_linearEquiv f.symm⟩ + +theorem isNoetherian_top_iff : IsNoetherian R (⊤ : Submodule R M) ↔ IsNoetherian R M := + Submodule.topEquiv.isNoetherian_iff + +theorem isNoetherian_of_injective [IsNoetherian R P] (f : M →ₗ[R] P) (hf : Function.Injective f) : + IsNoetherian R M := + isNoetherian_of_linearEquiv (LinearEquiv.ofInjective f hf).symm + +theorem fg_of_injective [IsNoetherian R P] {N : Submodule R M} (f : M →ₗ[R] P) + (hf : Function.Injective f) : N.FG := + haveI := isNoetherian_of_injective f hf + IsNoetherian.noetherian N + +end + +namespace Module + +variable {R M N : Type*} +variable [Semiring R] [AddCommMonoid M] [AddCommMonoid N] [Module R M] [Module R N] +variable (R M) + +-- see Note [lower instance priority] +instance (priority := 80) _root_.isNoetherian_of_finite [Finite M] : IsNoetherian R M := + ⟨fun s => ⟨(s : Set M).toFinite.toFinset, by rw [Set.Finite.coe_toFinset, Submodule.span_eq]⟩⟩ + +-- see Note [lower instance priority] +instance (priority := 100) IsNoetherian.finite [IsNoetherian R M] : Module.Finite R M := + ⟨IsNoetherian.noetherian ⊤⟩ + +instance {R₁ S : Type*} [CommSemiring R₁] [Semiring S] [Algebra R₁ S] + [IsNoetherian R₁ S] (I : Ideal S) : Module.Finite R₁ I := + IsNoetherian.finite R₁ ((I : Submodule S S).restrictScalars R₁) + +variable {R M} + +theorem Finite.of_injective [IsNoetherian R N] (f : M →ₗ[R] N) (hf : Function.Injective f) : + Module.Finite R M := + ⟨fg_of_injective f hf⟩ + +end Module + +section + +variable {R : Type*} {M : Type*} {P : Type*} +variable [Ring R] [AddCommGroup M] [AddCommGroup P] +variable [Module R M] [Module R P] + +open IsNoetherian + +theorem isNoetherian_of_ker_bot [IsNoetherian R P] (f : M →ₗ[R] P) (hf : LinearMap.ker f = ⊥) : + IsNoetherian R M := + isNoetherian_of_linearEquiv (LinearEquiv.ofInjective f <| LinearMap.ker_eq_bot.mp hf).symm + +theorem fg_of_ker_bot [IsNoetherian R P] {N : Submodule R M} (f : M →ₗ[R] P) + (hf : LinearMap.ker f = ⊥) : N.FG := + haveI := isNoetherian_of_ker_bot f hf + IsNoetherian.noetherian N + +instance isNoetherian_prod [IsNoetherian R M] [IsNoetherian R P] : IsNoetherian R (M × P) := + ⟨fun s => + Submodule.fg_of_fg_map_of_fg_inf_ker (LinearMap.snd R M P) (noetherian _) <| + have : s ⊓ LinearMap.ker (LinearMap.snd R M P) ≤ LinearMap.range (LinearMap.inl R M P) := + fun x ⟨_, hx2⟩ => ⟨x.1, Prod.ext rfl <| Eq.symm <| LinearMap.mem_ker.1 hx2⟩ + Submodule.map_comap_eq_self this ▸ (noetherian _).map _⟩ + +instance isNoetherian_sup (M₁ M₂ : Submodule R P) [IsNoetherian R M₁] [IsNoetherian R M₂] : + IsNoetherian R ↥(M₁ ⊔ M₂) := by + have := isNoetherian_range (M₁.subtype.coprod M₂.subtype) + rwa [LinearMap.range_coprod, Submodule.range_subtype, Submodule.range_subtype] at this + +variable {ι : Type*} [Finite ι] + +instance isNoetherian_pi : + ∀ {M : ι → Type*} [∀ i, AddCommGroup (M i)] + [∀ i, Module R (M i)] [∀ i, IsNoetherian R (M i)], IsNoetherian R (∀ i, M i) := by + apply Finite.induction_empty_option _ _ _ ι + · exact fun e h ↦ isNoetherian_of_linearEquiv (LinearEquiv.piCongrLeft R _ e) + · infer_instance + · exact fun ih ↦ isNoetherian_of_linearEquiv (LinearEquiv.piOptionEquivProd R).symm + +/-- A version of `isNoetherian_pi` for non-dependent functions. We need this instance because +sometimes Lean fails to apply the dependent version in non-dependent settings (e.g., it fails to +prove that `ι → ℝ` is finite dimensional over `ℝ`). -/ +instance isNoetherian_pi' [IsNoetherian R M] : IsNoetherian R (ι → M) := + isNoetherian_pi + +instance isNoetherian_iSup : + ∀ {M : ι → Submodule R P} [∀ i, IsNoetherian R (M i)], IsNoetherian R ↥(⨆ i, M i) := by + apply Finite.induction_empty_option _ _ _ ι + · intro _ _ e h _ _; rw [← e.iSup_comp]; apply h + · intros; rw [iSup_of_empty]; infer_instance + · intro _ _ ih _ _; rw [iSup_option]; infer_instance + +end + +section CommRing + +variable (R M N : Type*) [CommRing R] [AddCommGroup M] [AddCommGroup N] [Module R M] [Module R N] + [IsNoetherian R M] [Module.Finite R N] + +instance isNoetherian_linearMap_pi {ι : Type*} [Finite ι] : IsNoetherian R ((ι → R) →ₗ[R] M) := + let _i : Fintype ι := Fintype.ofFinite ι; isNoetherian_of_linearEquiv (Module.piEquiv ι R M) + +instance isNoetherian_linearMap : IsNoetherian R (N →ₗ[R] M) := by + obtain ⟨n, f, hf⟩ := Module.Finite.exists_fin' R N + let g : (N →ₗ[R] M) →ₗ[R] (Fin n → R) →ₗ[R] M := (LinearMap.llcomp R (Fin n → R) N M).flip f + exact isNoetherian_of_injective g hf.injective_linearMapComp_right + +end CommRing + +open IsNoetherian Submodule Function + +section + +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] + +/-- 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 := + IsWellFounded.induction _ I hgt + +end + +section + +universe w + +variable {R M P : Type*} {N : Type w} [Ring R] [AddCommGroup M] [Module R M] [AddCommGroup N] + [Module R N] [AddCommGroup P] [Module R P] [IsNoetherian R M] + +lemma Submodule.finite_ne_bot_of_iSupIndep {ι : Type*} {N : ι → Submodule R M} + (h : iSupIndep N) : + Set.Finite {i | N i ≠ ⊥} := + WellFoundedGT.finite_ne_bot_of_iSupIndep h + +@[deprecated (since := "2024-11-24")] +alias Submodule.finite_ne_bot_of_independent := Submodule.finite_ne_bot_of_iSupIndep + +/-- A linearly-independent family of vectors in a module over a non-trivial ring must be finite if +the module is Noetherian. -/ +theorem LinearIndependent.finite_of_isNoetherian [Nontrivial R] {ι} {v : ι → M} + (hv : LinearIndependent R v) : Finite ι := by + refine WellFoundedGT.finite_of_iSupIndep + hv.iSupIndep_span_singleton + fun i contra => ?_ + apply hv.ne_zero i + have : v i ∈ R ∙ v i := Submodule.mem_span_singleton_self (v i) + rwa [contra, Submodule.mem_bot] at this + +theorem LinearIndependent.set_finite_of_isNoetherian [Nontrivial R] {s : Set M} + (hi : LinearIndependent R ((↑) : s → M)) : s.Finite := + @Set.toFinite _ _ hi.finite_of_isNoetherian + +/-- If the first and final modules in an exact sequence are Noetherian, + then the middle module is also Noetherian. -/ +theorem isNoetherian_of_range_eq_ker [IsNoetherian R P] + (f : M →ₗ[R] N) (g : N →ₗ[R] P) (h : LinearMap.range f = LinearMap.ker g) : + IsNoetherian R N := + isNoetherian_mk <| + wellFounded_gt_exact_sequence + (LinearMap.range f) + (Submodule.map (f.ker.liftQ f le_rfl)) + (Submodule.comap (f.ker.liftQ f le_rfl)) + (Submodule.comap g.rangeRestrict) (Submodule.map g.rangeRestrict) + (Submodule.gciMapComap <| LinearMap.ker_eq_bot.mp <| Submodule.ker_liftQ_eq_bot _ _ _ le_rfl) + (Submodule.giMapComap g.surjective_rangeRestrict) + (by simp [Submodule.map_comap_eq, inf_comm, Submodule.range_liftQ]) + (by simp [Submodule.comap_map_eq, h]) + +theorem isNoetherian_iff_submodule_quotient (S : Submodule R P) : + IsNoetherian R P ↔ IsNoetherian R S ∧ IsNoetherian R (P ⧸ S) := by + refine ⟨fun _ ↦ ⟨inferInstance, inferInstance⟩, fun ⟨_, _⟩ ↦ ?_⟩ + apply isNoetherian_of_range_eq_ker S.subtype S.mkQ + rw [Submodule.ker_mkQ, Submodule.range_subtype] + +/-- 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. -/ +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 + -- A little off-by-one cleanup first: + suffices t : ∃ n : ℕ, ∀ m, n ≤ m → f (m + 1) = ⊥ by + obtain ⟨n, w⟩ := t + use n + 1 + rintro (_ | m) p + · cases p + · apply w + exact Nat.succ_le_succ_iff.mp p + obtain ⟨n, w⟩ := monotone_stabilizes_iff_noetherian.mpr inferInstance (partialSups f) + exact + ⟨n, fun m p => + (h m).eq_bot_of_ge <| sup_eq_left.1 <| (w (m + 1) <| le_add_right p).symm.trans <| w m p⟩ + +end + +-- see Note [lower instance priority] +/-- Modules over the trivial ring are Noetherian. -/ +instance (priority := 100) isNoetherian_of_subsingleton (R M) [Subsingleton R] [Semiring R] + [AddCommMonoid M] [Module R M] : IsNoetherian R M := + haveI := Module.subsingleton R M + 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 := + 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 := + 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 + let ⟨s, hs⟩ := hN + haveI := Classical.decEq M + haveI := Classical.decEq R + have : ∀ x ∈ s, x ∈ N := fun x hx => hs ▸ Submodule.subset_span hx + refine + @isNoetherian_of_surjective + R ((↑s : Set M) → R) N _ _ _ (Pi.module _ _ _) _ ?_ ?_ isNoetherian_pi + · fapply LinearMap.mk + · fapply AddHom.mk + · exact fun f => ⟨∑ i ∈ s.attach, f i • i.1, N.sum_mem fun c _ => N.smul_mem _ <| this _ c.2⟩ + · intro f g + apply Subtype.eq + change (∑ i ∈ s.attach, (f i + g i) • _) = _ + simp only [add_smul, Finset.sum_add_distrib] + rfl + · intro c f + apply Subtype.eq + change (∑ i ∈ s.attach, (c • f i) • _) = _ + simp only [smul_eq_mul, mul_smul] + exact Finset.smul_sum.symm + · 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_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.linearCombination_apply, Finsupp.sum, eq_comm] + refine Finset.sum_subset hl1 fun x _ hx => ?_ + rw [Finsupp.not_mem_support_iff.1 hx, zero_smul] + +instance isNoetherian_of_isNoetherianRing_of_finite (R M : Type*) + [Ring R] [AddCommGroup M] [Module R M] [IsNoetherianRing R] [Module.Finite R M] : + IsNoetherian R M := + have : IsNoetherian R (⊤ : Submodule R M) := + isNoetherian_of_fg_of_noetherian _ <| Module.finite_def.mp inferInstance + isNoetherian_of_linearEquiv (LinearEquiv.ofTop (⊤ : Submodule R M) rfl) + +/-- In a module over a Noetherian ring, the submodule generated by finitely many vectors is +Noetherian. -/ +theorem isNoetherian_span_of_finite (R) {M} [Ring R] [AddCommGroup M] [Module R M] + [IsNoetherianRing R] {A : Set M} (hA : A.Finite) : IsNoetherian R (Submodule.span R A) := + 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 := + 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 := + isNoetherianRing_of_surjective R f.range f.rangeRestrict f.rangeRestrict_surjective + +theorem isNoetherianRing_of_ringEquiv (R) [Ring R] {S} [Ring S] (f : R ≃+* S) [IsNoetherianRing R] : + IsNoetherianRing S := + isNoetherianRing_of_surjective R S f.toRingHom f.toEquiv.surjective diff --git a/Mathlib/RingTheory/Noetherian/Defs.lean b/Mathlib/RingTheory/Noetherian/Defs.lean index 953d4b7265411..e14e88932c6a3 100644 --- a/Mathlib/RingTheory/Noetherian/Defs.lean +++ b/Mathlib/RingTheory/Noetherian/Defs.lean @@ -3,10 +3,7 @@ Copyright (c) 2018 Mario Carneiro, Kevin Buzzard. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro, Kevin Buzzard -/ -import Mathlib.LinearAlgebra.Quotient.Basic -import Mathlib.RingTheory.Finiteness.Cardinality -import Mathlib.RingTheory.Finiteness.Finsupp -import Mathlib.RingTheory.Ideal.Maps +import Mathlib.RingTheory.Finiteness.Basic /-! # Noetherian rings and modules @@ -49,6 +46,9 @@ Noetherian, noetherian, Noetherian ring, Noetherian module, noetherian ring, noe -/ +assert_not_exists Finsupp.linearCombination +assert_not_exists Matrix +assert_not_exists Pi.basis open Set Pointwise @@ -100,144 +100,8 @@ theorem isNoetherian_of_le {s t : Submodule R M} [ht : IsNoetherian R t] (h : s IsNoetherian R s := isNoetherian_submodule.mpr fun _ hs' => isNoetherian_submodule.mp ht _ (le_trans hs' h) -variable (M) - -theorem isNoetherian_of_surjective (f : M →ₗ[R] P) (hf : LinearMap.range f = ⊤) [IsNoetherian R M] : - IsNoetherian R P := - ⟨fun s => - have : (s.comap f).map f = s := Submodule.map_comap_eq_self <| hf.symm ▸ le_top - this ▸ (noetherian _).map _⟩ - -variable {M} - -instance isNoetherian_range (f : M →ₗ[R] P) [IsNoetherian R M] : - IsNoetherian R (LinearMap.range f) := - isNoetherian_of_surjective _ _ f.range_rangeRestrict - -instance isNoetherian_quotient {A M : Type*} [Ring A] [AddCommGroup M] [SMul R A] [Module R M] - [Module A M] [IsScalarTower R A M] (N : Submodule A M) [IsNoetherian R M] : - IsNoetherian R (M ⧸ N) := - isNoetherian_of_surjective M ((Submodule.mkQ N).restrictScalars R) <| - LinearMap.range_eq_top.mpr N.mkQ_surjective - -@[deprecated (since := "2024-04-27"), nolint defLemma] -alias Submodule.Quotient.isNoetherian := isNoetherian_quotient - -theorem isNoetherian_of_linearEquiv (f : M ≃ₗ[R] P) [IsNoetherian R M] : IsNoetherian R P := - isNoetherian_of_surjective _ f.toLinearMap f.range - -theorem LinearEquiv.isNoetherian_iff (f : M ≃ₗ[R] P) : IsNoetherian R M ↔ IsNoetherian R P := - ⟨fun _ ↦ isNoetherian_of_linearEquiv f, fun _ ↦ isNoetherian_of_linearEquiv f.symm⟩ - -theorem isNoetherian_top_iff : IsNoetherian R (⊤ : Submodule R M) ↔ IsNoetherian R M := - Submodule.topEquiv.isNoetherian_iff - -theorem isNoetherian_of_injective [IsNoetherian R P] (f : M →ₗ[R] P) (hf : Function.Injective f) : - IsNoetherian R M := - isNoetherian_of_linearEquiv (LinearEquiv.ofInjective f hf).symm - -theorem fg_of_injective [IsNoetherian R P] {N : Submodule R M} (f : M →ₗ[R] P) - (hf : Function.Injective f) : N.FG := - haveI := isNoetherian_of_injective f hf - IsNoetherian.noetherian N - -end - -namespace Module - -variable {R M N : Type*} -variable [Semiring R] [AddCommMonoid M] [AddCommMonoid N] [Module R M] [Module R N] -variable (R M) - --- see Note [lower instance priority] -instance (priority := 80) _root_.isNoetherian_of_finite [Finite M] : IsNoetherian R M := - ⟨fun s => ⟨(s : Set M).toFinite.toFinset, by rw [Set.Finite.coe_toFinset, Submodule.span_eq]⟩⟩ - --- see Note [lower instance priority] -instance (priority := 100) IsNoetherian.finite [IsNoetherian R M] : Module.Finite R M := - ⟨IsNoetherian.noetherian ⊤⟩ - -instance {R₁ S : Type*} [CommSemiring R₁] [Semiring S] [Algebra R₁ S] - [IsNoetherian R₁ S] (I : Ideal S) : Module.Finite R₁ I := - IsNoetherian.finite R₁ ((I : Submodule S S).restrictScalars R₁) - -variable {R M} - -theorem Finite.of_injective [IsNoetherian R N] (f : M →ₗ[R] N) (hf : Function.Injective f) : - Module.Finite R M := - ⟨fg_of_injective f hf⟩ - -end Module - -section - -variable {R : Type*} {M : Type*} {P : Type*} -variable [Ring R] [AddCommGroup M] [AddCommGroup P] -variable [Module R M] [Module R P] - -open IsNoetherian - -theorem isNoetherian_of_ker_bot [IsNoetherian R P] (f : M →ₗ[R] P) (hf : LinearMap.ker f = ⊥) : - IsNoetherian R M := - isNoetherian_of_linearEquiv (LinearEquiv.ofInjective f <| LinearMap.ker_eq_bot.mp hf).symm - -theorem fg_of_ker_bot [IsNoetherian R P] {N : Submodule R M} (f : M →ₗ[R] P) - (hf : LinearMap.ker f = ⊥) : N.FG := - haveI := isNoetherian_of_ker_bot f hf - IsNoetherian.noetherian N - -instance isNoetherian_prod [IsNoetherian R M] [IsNoetherian R P] : IsNoetherian R (M × P) := - ⟨fun s => - Submodule.fg_of_fg_map_of_fg_inf_ker (LinearMap.snd R M P) (noetherian _) <| - have : s ⊓ LinearMap.ker (LinearMap.snd R M P) ≤ LinearMap.range (LinearMap.inl R M P) := - fun x ⟨_, hx2⟩ => ⟨x.1, Prod.ext rfl <| Eq.symm <| LinearMap.mem_ker.1 hx2⟩ - Submodule.map_comap_eq_self this ▸ (noetherian _).map _⟩ - -instance isNoetherian_sup (M₁ M₂ : Submodule R P) [IsNoetherian R M₁] [IsNoetherian R M₂] : - IsNoetherian R ↥(M₁ ⊔ M₂) := by - have := isNoetherian_range (M₁.subtype.coprod M₂.subtype) - rwa [LinearMap.range_coprod, Submodule.range_subtype, Submodule.range_subtype] at this - -variable {ι : Type*} [Finite ι] - -instance isNoetherian_pi : - ∀ {M : ι → Type*} [∀ i, AddCommGroup (M i)] - [∀ i, Module R (M i)] [∀ i, IsNoetherian R (M i)], IsNoetherian R (∀ i, M i) := by - apply Finite.induction_empty_option _ _ _ ι - · exact fun e h ↦ isNoetherian_of_linearEquiv (LinearEquiv.piCongrLeft R _ e) - · infer_instance - · exact fun ih ↦ isNoetherian_of_linearEquiv (LinearEquiv.piOptionEquivProd R).symm - -/-- A version of `isNoetherian_pi` for non-dependent functions. We need this instance because -sometimes Lean fails to apply the dependent version in non-dependent settings (e.g., it fails to -prove that `ι → ℝ` is finite dimensional over `ℝ`). -/ -instance isNoetherian_pi' [IsNoetherian R M] : IsNoetherian R (ι → M) := - isNoetherian_pi - -instance isNoetherian_iSup : - ∀ {M : ι → Submodule R P} [∀ i, IsNoetherian R (M i)], IsNoetherian R ↥(⨆ i, M i) := by - apply Finite.induction_empty_option _ _ _ ι - · intro _ _ e h _ _; rw [← e.iSup_comp]; apply h - · intros; rw [iSup_of_empty]; infer_instance - · intro _ _ ih _ _; rw [iSup_option]; infer_instance - end -section CommRing - -variable (R M N : Type*) [CommRing R] [AddCommGroup M] [AddCommGroup N] [Module R M] [Module R N] - [IsNoetherian R M] [Module.Finite R N] - -instance isNoetherian_linearMap_pi {ι : Type*} [Finite ι] : IsNoetherian R ((ι → R) →ₗ[R] M) := - let _i : Fintype ι := Fintype.ofFinite ι; isNoetherian_of_linearEquiv (Module.piEquiv ι R M) - -instance isNoetherian_linearMap : IsNoetherian R (N →ₗ[R] M) := by - obtain ⟨n, f, hf⟩ := Module.Finite.exists_fin' R N - let g : (N →ₗ[R] M) →ₗ[R] (Fin n → R) →ₗ[R] M := (LinearMap.llcomp R (Fin n → R) N M).flip f - exact isNoetherian_of_injective g hf.injective_linearMapComp_right - -end CommRing - open IsNoetherian Submodule Function section @@ -299,81 +163,6 @@ 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.monotone_chain_condition] -/-- 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 := - IsWellFounded.induction _ I hgt - -end - -section - -universe w - -variable {R M P : Type*} {N : Type w} [Ring R] [AddCommGroup M] [Module R M] [AddCommGroup N] - [Module R N] [AddCommGroup P] [Module R P] [IsNoetherian R M] - -lemma Submodule.finite_ne_bot_of_independent {ι : Type*} {N : ι → Submodule R M} - (h : CompleteLattice.Independent N) : - Set.Finite {i | N i ≠ ⊥} := - CompleteLattice.WellFoundedGT.finite_ne_bot_of_independent h - -/-- A linearly-independent family of vectors in a module over a non-trivial ring must be finite if -the module is Noetherian. -/ -theorem LinearIndependent.finite_of_isNoetherian [Nontrivial R] {ι} {v : ι → M} - (hv : LinearIndependent R v) : Finite ι := by - refine CompleteLattice.WellFoundedGT.finite_of_independent - 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) - rwa [contra, Submodule.mem_bot] at this - -theorem LinearIndependent.set_finite_of_isNoetherian [Nontrivial R] {s : Set M} - (hi : LinearIndependent R ((↑) : s → M)) : s.Finite := - @Set.toFinite _ _ hi.finite_of_isNoetherian - -/-- If the first and final modules in an exact sequence are Noetherian, - then the middle module is also Noetherian. -/ -theorem isNoetherian_of_range_eq_ker [IsNoetherian R P] - (f : M →ₗ[R] N) (g : N →ₗ[R] P) (h : LinearMap.range f = LinearMap.ker g) : - IsNoetherian R N := - isNoetherian_mk <| - wellFounded_gt_exact_sequence - (LinearMap.range f) - (Submodule.map (f.ker.liftQ f le_rfl)) - (Submodule.comap (f.ker.liftQ f le_rfl)) - (Submodule.comap g.rangeRestrict) (Submodule.map g.rangeRestrict) - (Submodule.gciMapComap <| LinearMap.ker_eq_bot.mp <| Submodule.ker_liftQ_eq_bot _ _ _ le_rfl) - (Submodule.giMapComap g.surjective_rangeRestrict) - (by simp [Submodule.map_comap_eq, inf_comm, Submodule.range_liftQ]) - (by simp [Submodule.comap_map_eq, h]) - -theorem isNoetherian_iff_submodule_quotient (S : Submodule R P) : - IsNoetherian R P ↔ IsNoetherian R S ∧ IsNoetherian R (P ⧸ S) := by - refine ⟨fun _ ↦ ⟨inferInstance, inferInstance⟩, fun ⟨_, _⟩ ↦ ?_⟩ - apply isNoetherian_of_range_eq_ker S.subtype S.mkQ - rw [Submodule.ker_mkQ, Submodule.range_subtype] - -/-- 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. -/ -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 - -- A little off-by-one cleanup first: - suffices t : ∃ n : ℕ, ∀ m, n ≤ m → f (m + 1) = ⊥ by - obtain ⟨n, w⟩ := t - use n + 1 - rintro (_ | m) p - · cases p - · apply w - exact Nat.succ_le_succ_iff.mp p - obtain ⟨n, w⟩ := monotone_stabilizes_iff_noetherian.mpr inferInstance (partialSups f) - exact - ⟨n, fun m p => - (h m).eq_bot_of_ge <| sup_eq_left.1 <| (w (m + 1) <| le_add_right p).symm.trans <| w m p⟩ - end /-- A (semi)ring is Noetherian if it is Noetherian as a module over itself, @@ -388,79 +177,3 @@ theorem isNoetherianRing_iff {R} [Semiring R] : IsNoetherianRing R ↔ IsNoether theorem isNoetherianRing_iff_ideal_fg (R : Type*) [Semiring R] : IsNoetherianRing R ↔ ∀ I : Ideal R, I.FG := isNoetherianRing_iff.trans isNoetherian_def - --- see Note [lower instance priority] -/-- Modules over the trivial ring are Noetherian. -/ -instance (priority := 100) isNoetherian_of_subsingleton (R M) [Subsingleton R] [Semiring R] - [AddCommMonoid M] [Module R M] : IsNoetherian R M := - haveI := Module.subsingleton R M - 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 := - 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 := - 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 - let ⟨s, hs⟩ := hN - haveI := Classical.decEq M - haveI := Classical.decEq R - have : ∀ x ∈ s, x ∈ N := fun x hx => hs ▸ Submodule.subset_span hx - refine - @isNoetherian_of_surjective - R ((↑s : Set M) → R) N _ _ _ (Pi.module _ _ _) _ ?_ ?_ isNoetherian_pi - · fapply LinearMap.mk - · fapply AddHom.mk - · exact fun f => ⟨∑ i ∈ s.attach, f i • i.1, N.sum_mem fun c _ => N.smul_mem _ <| this _ c.2⟩ - · intro f g - apply Subtype.eq - change (∑ i ∈ s.attach, (f i + g i) • _) = _ - simp only [add_smul, Finset.sum_add_distrib] - rfl - · intro c f - apply Subtype.eq - change (∑ i ∈ s.attach, (c • f i) • _) = _ - simp only [smul_eq_mul, mul_smul] - exact Finset.smul_sum.symm - · 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_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.linearCombination_apply, Finsupp.sum, eq_comm] - refine Finset.sum_subset hl1 fun x _ hx => ?_ - rw [Finsupp.not_mem_support_iff.1 hx, zero_smul] - -instance isNoetherian_of_isNoetherianRing_of_finite (R M : Type*) - [Ring R] [AddCommGroup M] [Module R M] [IsNoetherianRing R] [Module.Finite R M] : - IsNoetherian R M := - have : IsNoetherian R (⊤ : Submodule R M) := - isNoetherian_of_fg_of_noetherian _ <| Module.finite_def.mp inferInstance - isNoetherian_of_linearEquiv (LinearEquiv.ofTop (⊤ : Submodule R M) rfl) - -/-- In a module over a Noetherian ring, the submodule generated by finitely many vectors is -Noetherian. -/ -theorem isNoetherian_span_of_finite (R) {M} [Ring R] [AddCommGroup M] [Module R M] - [IsNoetherianRing R] {A : Set M} (hA : A.Finite) : IsNoetherian R (Submodule.span R A) := - 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 := - 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 := - isNoetherianRing_of_surjective R f.range f.rangeRestrict f.rangeRestrict_surjective - -theorem isNoetherianRing_of_ringEquiv (R) [Ring R] {S} [Ring S] (f : R ≃+* S) [IsNoetherianRing R] : - IsNoetherianRing S := - isNoetherianRing_of_surjective R S f.toRingHom f.toEquiv.surjective diff --git a/Mathlib/RingTheory/Noetherian/Orzech.lean b/Mathlib/RingTheory/Noetherian/Orzech.lean index 8858b55202f80..da0b31cf04f08 100644 --- a/Mathlib/RingTheory/Noetherian/Orzech.lean +++ b/Mathlib/RingTheory/Noetherian/Orzech.lean @@ -6,7 +6,7 @@ Authors: Mario Carneiro, Kevin Buzzard import Mathlib.Algebra.Module.Submodule.IterateMapComap import Mathlib.Algebra.Order.Archimedean.Basic import Mathlib.Order.PartialSups -import Mathlib.RingTheory.Noetherian.Defs +import Mathlib.RingTheory.Noetherian.Basic import Mathlib.RingTheory.OrzechProperty import Mathlib.Order.Filter.AtTopBot diff --git a/Mathlib/RingTheory/Polynomial/Basic.lean b/Mathlib/RingTheory/Polynomial/Basic.lean index 99c10175f0d49..4bee44c7de8c5 100644 --- a/Mathlib/RingTheory/Polynomial/Basic.lean +++ b/Mathlib/RingTheory/Polynomial/Basic.lean @@ -8,7 +8,7 @@ import Mathlib.Algebra.GeomSum import Mathlib.Algebra.MvPolynomial.CommRing import Mathlib.Algebra.MvPolynomial.Equiv import Mathlib.Algebra.Polynomial.BigOperators -import Mathlib.RingTheory.Noetherian.Defs +import Mathlib.RingTheory.Noetherian.Basic /-! # Ring-theoretic supplement of Algebra.Polynomial. diff --git a/Mathlib/RingTheory/PowerSeries/Basic.lean b/Mathlib/RingTheory/PowerSeries/Basic.lean index 6030481adc2e7..85884f5a24154 100644 --- a/Mathlib/RingTheory/PowerSeries/Basic.lean +++ b/Mathlib/RingTheory/PowerSeries/Basic.lean @@ -758,6 +758,7 @@ namespace Polynomial open Finsupp Polynomial +section CommSemiring variable {R : Type*} [CommSemiring R] (φ ψ : R[X]) -- Porting note: added so we can add the `@[coe]` attribute @@ -877,6 +878,21 @@ theorem coeToPowerSeries.algHom_apply : coeToPowerSeries.algHom A φ = PowerSeries.map (algebraMap R A) ↑φ := rfl +end CommSemiring + +section CommRing +variable {R : Type*} [CommRing R] + +@[simp, norm_cast] +lemma coe_neg (p : R[X]) : ((- p : R[X]) : PowerSeries R) = - p := + coeToPowerSeries.ringHom.map_neg p + +@[simp, norm_cast] +lemma coe_sub (p q : R[X]) : ((p - q : R[X]) : PowerSeries R) = p - q := + coeToPowerSeries.ringHom.map_sub p q + +end CommRing + end Polynomial namespace PowerSeries diff --git a/Mathlib/RingTheory/PrimeSpectrum.lean b/Mathlib/RingTheory/PrimeSpectrum.lean index 29c25b19c2cf9..5ac44c10a7f5f 100644 --- a/Mathlib/RingTheory/PrimeSpectrum.lean +++ b/Mathlib/RingTheory/PrimeSpectrum.lean @@ -7,7 +7,7 @@ import Mathlib.LinearAlgebra.Finsupp.SumProd import Mathlib.RingTheory.Ideal.Prod import Mathlib.RingTheory.Localization.Ideal import Mathlib.RingTheory.Nilpotent.Lemmas -import Mathlib.RingTheory.Noetherian.Defs +import Mathlib.RingTheory.Noetherian.Basic /-! # Prime spectrum of a commutative (semi)ring as a type @@ -83,6 +83,14 @@ instance [Subsingleton R] : IsEmpty (PrimeSpectrum R) := variable (R S) +/-- The prime spectrum is in bijection with the set of prime ideals. -/ +@[simps] +def equivSubtype : PrimeSpectrum R ≃ {I : Ideal R // I.IsPrime} where + toFun I := ⟨I.asIdeal, I.2⟩ + invFun I := ⟨I, I.2⟩ + left_inv _ := rfl + right_inv _ := rfl + /-- The map from the direct sum of prime spectra to the prime spectrum of a direct product. -/ @[simp] def primeSpectrumProdOfSum : PrimeSpectrum R ⊕ PrimeSpectrum S → PrimeSpectrum (R × S) diff --git a/Mathlib/RingTheory/PrincipalIdealDomain.lean b/Mathlib/RingTheory/PrincipalIdealDomain.lean index 7cde766527865..5343a17c2253a 100644 --- a/Mathlib/RingTheory/PrincipalIdealDomain.lean +++ b/Mathlib/RingTheory/PrincipalIdealDomain.lean @@ -5,6 +5,7 @@ Authors: Chris Hughes, Morenikeji Neri -/ import Mathlib.Algebra.EuclideanDomain.Field import Mathlib.Algebra.GCDMonoid.Basic +import Mathlib.RingTheory.Ideal.Maps import Mathlib.RingTheory.Ideal.Nonunits import Mathlib.RingTheory.Noetherian.UniqueFactorizationDomain @@ -14,20 +15,21 @@ import Mathlib.RingTheory.Noetherian.UniqueFactorizationDomain A principal ideal ring (PIR) is a ring in which all left ideals are principal. A principal ideal domain (PID) is an integral domain which is a principal ideal ring. +The definition of `IsPrincipalIdealRing` can be found in `Mathlib.RingTheory.Ideal.Span`. + # Main definitions Note that for principal ideal domains, one should use `[IsDomain R] [IsPrincipalIdealRing R]`. There is no explicit definition of a PID. -Theorems about PID's are in the `principal_ideal_ring` namespace. +Theorems about PID's are in the `PrincipalIdealRing` namespace. -- `IsPrincipalIdealRing`: a predicate on rings, saying that every left ideal is principal. - `IsBezout`: the predicate saying that every finitely generated left ideal is principal. - `generator`: a generator of a principal ideal (or more generally submodule) - `to_uniqueFactorizationMonoid`: a PID is a unique factorization domain # Main results -- `to_maximal_ideal`: a non-zero prime ideal in a PID is maximal. +- `Ideal.IsPrime.to_maximal_ideal`: a non-zero prime ideal in a PID is maximal. - `EuclideanDomain.to_principal_ideal_domain` : a Euclidean domain is a PID. - `IsBezout.nonemptyGCDMonoid`: Every Bézout domain is a GCD domain. diff --git a/Mathlib/RingTheory/SimpleModule.lean b/Mathlib/RingTheory/SimpleModule.lean index 66282ba413b64..dbae9bcb743ed 100644 --- a/Mathlib/RingTheory/SimpleModule.lean +++ b/Mathlib/RingTheory/SimpleModule.lean @@ -198,12 +198,14 @@ theorem exists_simple_submodule [Nontrivial M] : ∃ m : Submodule R M, IsSimple theorem sSup_simples_eq_top : sSup { m : Submodule R M | IsSimpleModule R m } = ⊤ := by simpa only [isSimpleModule_iff_isAtom] using sSup_atoms_eq_top -theorem exists_setIndependent_sSup_simples_eq_top : - ∃ s : Set (Submodule R M), CompleteLattice.SetIndependent s ∧ - sSup s = ⊤ ∧ ∀ m ∈ s, IsSimpleModule R m := by +theorem exists_sSupIndep_sSup_simples_eq_top : + ∃ s : Set (Submodule R M), sSupIndep s ∧ sSup s = ⊤ ∧ ∀ m ∈ s, IsSimpleModule R m := by have := sSup_simples_eq_top R M simp_rw [isSimpleModule_iff_isAtom] at this ⊢ - exact exists_setIndependent_of_sSup_atoms_eq_top this + exact exists_sSupIndep_of_sSup_atoms_eq_top this + +@[deprecated (since := "2024-11-24")] +alias exists_setIndependent_sSup_simples_eq_top := exists_sSupIndep_sSup_simples_eq_top /-- The annihilator of a semisimple module over a commutative ring is a radical ideal. -/ theorem annihilator_isRadical (R) [CommRing R] [Module R M] [IsSemisimpleModule R M] : diff --git a/Mathlib/RingTheory/TensorProduct/Free.lean b/Mathlib/RingTheory/TensorProduct/Free.lean index 1f644e47cf568..a857cfdf874c6 100644 --- a/Mathlib/RingTheory/TensorProduct/Free.lean +++ b/Mathlib/RingTheory/TensorProduct/Free.lean @@ -30,7 +30,7 @@ namespace Algebra namespace TensorProduct -variable {R S A : Type*} +variable {R A : Type*} section Basis diff --git a/Mathlib/RingTheory/TwoSidedIdeal/Operations.lean b/Mathlib/RingTheory/TwoSidedIdeal/Operations.lean index 669cd38417774..a941b75c4e02a 100644 --- a/Mathlib/RingTheory/TwoSidedIdeal/Operations.lean +++ b/Mathlib/RingTheory/TwoSidedIdeal/Operations.lean @@ -3,12 +3,12 @@ Copyright (c) 2024 Jujian Zhang. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jujian Zhang, Jireh Loreaux -/ - +import Mathlib.Algebra.Group.Subgroup.Map +import Mathlib.Algebra.Module.Opposite import Mathlib.Algebra.Module.Submodule.Lattice import Mathlib.RingTheory.Congruence.Opposite import Mathlib.RingTheory.Ideal.Defs import Mathlib.RingTheory.TwoSidedIdeal.Lattice -import Mathlib.Algebra.Module.Opposite /-! # Operations on two-sided ideals diff --git a/Mathlib/RingTheory/UniqueFactorizationDomain/Nat.lean b/Mathlib/RingTheory/UniqueFactorizationDomain/Nat.lean index 680aa8f4249fe..4c69bfb655b75 100644 --- a/Mathlib/RingTheory/UniqueFactorizationDomain/Nat.lean +++ b/Mathlib/RingTheory/UniqueFactorizationDomain/Nat.lean @@ -15,8 +15,6 @@ import Mathlib.RingTheory.UniqueFactorizationDomain.NormalizedFactors * `Nat.instUniqueFactorizationMonoid`: the natural numbers have unique factorization -/ -variable {α : Type*} - namespace Nat instance instWfDvdMonoid : WfDvdMonoid ℕ where diff --git a/Mathlib/RingTheory/Valuation/Basic.lean b/Mathlib/RingTheory/Valuation/Basic.lean index e4f462f138500..fe79b5797d6c9 100644 --- a/Mathlib/RingTheory/Valuation/Basic.lean +++ b/Mathlib/RingTheory/Valuation/Basic.lean @@ -128,7 +128,7 @@ theorem coe_mk (f : R →*₀ Γ₀) (h) : ⇑(Valuation.mk f h) = f := rfl theorem toFun_eq_coe (v : Valuation R Γ₀) : v.toFun = v := rfl -@[simp] -- Porting note: requested by simpNF as toFun_eq_coe LHS simplifies +@[simp] theorem toMonoidWithZeroHom_coe_eq_coe (v : Valuation R Γ₀) : (v.toMonoidWithZeroHom : R → Γ₀) = v := rfl diff --git a/Mathlib/RingTheory/Valuation/ValuationSubring.lean b/Mathlib/RingTheory/Valuation/ValuationSubring.lean index 867c268d02ac5..813f07bdbde31 100644 --- a/Mathlib/RingTheory/Valuation/ValuationSubring.lean +++ b/Mathlib/RingTheory/Valuation/ValuationSubring.lean @@ -50,9 +50,6 @@ instance : SetLike (ValuationSubring K) K where replace h := SetLike.coe_injective' h congr --- Porting note https://github.com/leanprover-community/mathlib4/issues/10959 --- simp cannot prove this -@[simp, nolint simpNF] theorem mem_carrier (x : K) : x ∈ A.carrier ↔ x ∈ A := Iff.refl _ @[simp] @@ -668,9 +665,9 @@ def unitsModPrincipalUnitsEquivResidueFieldUnits : local instance : MulOneClass ({ x // x ∈ unitGroup A } ⧸ Subgroup.comap (Subgroup.subtype (unitGroup A)) (principalUnitGroup A)) := inferInstance --- @[simp] -- Porting note: not in simpNF theorem unitsModPrincipalUnitsEquivResidueFieldUnits_comp_quotientGroup_mk : - A.unitsModPrincipalUnitsEquivResidueFieldUnits.toMonoidHom.comp (QuotientGroup.mk' _) = + (A.unitsModPrincipalUnitsEquivResidueFieldUnits : _ ⧸ Subgroup.comap _ _ →* _).comp + (QuotientGroup.mk' (A.principalUnitGroup.subgroupOf A.unitGroup)) = A.unitGroupToResidueFieldUnits := rfl theorem unitsModPrincipalUnitsEquivResidueFieldUnits_comp_quotientGroup_mk_apply @@ -793,7 +790,6 @@ namespace Valuation variable {Γ : Type*} [LinearOrderedCommGroupWithZero Γ] (v : Valuation K Γ) (x : Kˣ) --- @[simp] -- Porting note: not in simpNF theorem mem_unitGroup_iff : x ∈ v.valuationSubring.unitGroup ↔ v x = 1 := IsEquiv.eq_one_iff_eq_one (Valuation.isEquiv_valuation_valuationSubring _).symm diff --git a/Mathlib/SetTheory/Cardinal/Aleph.lean b/Mathlib/SetTheory/Cardinal/Aleph.lean index 3970c6fc6cb57..ca79284dac29a 100644 --- a/Mathlib/SetTheory/Cardinal/Aleph.lean +++ b/Mathlib/SetTheory/Cardinal/Aleph.lean @@ -541,7 +541,7 @@ def alephIdx.relIso : @RelIso Cardinal.{u} Ordinal.{u} (· < ·) (· < ·) := def alephIdx : Cardinal → Ordinal := aleph'.symm -@[deprecated (since := "2024-08-28")] +@[deprecated "No deprecation message was provided." (since := "2024-08-28")] theorem alephIdx.relIso_coe : (alephIdx.relIso : Cardinal → Ordinal) = alephIdx := rfl @@ -555,7 +555,7 @@ theorem alephIdx.relIso_coe : (alephIdx.relIso : Cardinal → Ordinal) = alephId def Aleph'.relIso := aleph' -@[deprecated (since := "2024-08-28")] +@[deprecated "No deprecation message was provided." (since := "2024-08-28")] theorem aleph'.relIso_coe : (Aleph'.relIso : Ordinal → Cardinal) = aleph' := rfl @@ -571,11 +571,11 @@ theorem aleph'_le {o₁ o₂ : Ordinal} : aleph' o₁ ≤ aleph' o₂ ↔ o₁ theorem aleph'_max (o₁ o₂ : Ordinal) : aleph' (max o₁ o₂) = max (aleph' o₁) (aleph' o₂) := aleph'.monotone.map_max -@[deprecated (since := "2024-08-28")] +@[deprecated "No deprecation message was provided." (since := "2024-08-28")] theorem aleph'_alephIdx (c : Cardinal) : aleph' c.alephIdx = c := Cardinal.alephIdx.relIso.toEquiv.symm_apply_apply c -@[deprecated (since := "2024-08-28")] +@[deprecated "No deprecation message was provided." (since := "2024-08-28")] theorem alephIdx_aleph' (o : Ordinal) : (aleph' o).alephIdx = o := Cardinal.alephIdx.relIso.toEquiv.apply_symm_apply o @@ -608,7 +608,7 @@ theorem aleph'_limit {o : Ordinal} (ho : o.IsLimit) : aleph' o = ⨆ a : Iio o, theorem aleph'_omega0 : aleph' ω = ℵ₀ := preAleph_omega0 -@[deprecated (since := "2024-09-30")] +@[deprecated "No deprecation message was provided." (since := "2024-09-30")] alias aleph'_omega := aleph'_omega0 /-- `aleph'` and `aleph_idx` form an equivalence between `Ordinal` and `Cardinal` -/ @@ -616,6 +616,7 @@ alias aleph'_omega := aleph'_omega0 def aleph'Equiv : Ordinal ≃ Cardinal := ⟨aleph', alephIdx, alephIdx_aleph', aleph'_alephIdx⟩ +@[deprecated aleph_eq_preAleph (since := "2024-10-22")] theorem aleph_eq_aleph' (o : Ordinal) : ℵ_ o = preAleph (ω + o) := rfl @@ -637,7 +638,7 @@ theorem aleph'_isNormal : IsNormal (ord ∘ aleph') := -- They should also use `¬ BddAbove` instead of `Unbounded (· < ·)`. /-- Ordinals that are cardinals are unbounded. -/ -@[deprecated (since := "2024-09-24")] +@[deprecated "No deprecation message was provided." (since := "2024-09-24")] theorem ord_card_unbounded : Unbounded (· < ·) { b : Ordinal | b.card.ord = b } := unbounded_lt_iff.2 fun a => ⟨_, @@ -645,16 +646,16 @@ theorem ord_card_unbounded : Unbounded (· < ·) { b : Ordinal | b.card.ord = b dsimp rw [card_ord], (lt_ord_succ_card a).le⟩⟩ -@[deprecated (since := "2024-09-24")] +@[deprecated "No deprecation message was provided." (since := "2024-09-24")] theorem eq_aleph'_of_eq_card_ord {o : Ordinal} (ho : o.card.ord = o) : ∃ a, (aleph' a).ord = o := ⟨aleph'.symm o.card, by simpa using ho⟩ /-- Infinite ordinals that are cardinals are unbounded. -/ -@[deprecated (since := "2024-09-24")] +@[deprecated "No deprecation message was provided." (since := "2024-09-24")] theorem ord_card_unbounded' : Unbounded (· < ·) { b : Ordinal | b.card.ord = b ∧ ω ≤ b } := (unbounded_lt_inter_le ω).2 ord_card_unbounded -@[deprecated (since := "2024-09-24")] +@[deprecated "No deprecation message was provided." (since := "2024-09-24")] theorem eq_aleph_of_eq_card_ord {o : Ordinal} (ho : o.card.ord = o) (ho' : ω ≤ o) : ∃ a, (ℵ_ a).ord = o := by cases' eq_aleph'_of_eq_card_ord ho with a ha diff --git a/Mathlib/SetTheory/Cardinal/Basic.lean b/Mathlib/SetTheory/Cardinal/Basic.lean index b309bcdad858b..d4660d1f437be 100644 --- a/Mathlib/SetTheory/Cardinal/Basic.lean +++ b/Mathlib/SetTheory/Cardinal/Basic.lean @@ -14,7 +14,6 @@ import Mathlib.Order.ConditionallyCompleteLattice.Indexed import Mathlib.Order.InitialSeg import Mathlib.Order.SuccPred.CompleteLinearOrder import Mathlib.SetTheory.Cardinal.SchroederBernstein -import Mathlib.Algebra.Order.Group.Nat import Mathlib.Algebra.Order.GroupWithZero.Canonical import Mathlib.Algebra.Order.Ring.Canonical @@ -147,7 +146,7 @@ protected theorem eq : #α = #β ↔ Nonempty (α ≃ β) := Quotient.eq' /-- Avoid using `Quotient.mk` to construct a `Cardinal` directly -/ -@[deprecated (since := "2024-10-24")] +@[deprecated "No deprecation message was provided." (since := "2024-10-24")] theorem mk'_def (α : Type u) : @Eq Cardinal ⟦α⟧ #α := rfl @@ -1780,12 +1779,12 @@ theorem mk_plift_false : #(PLift False) = 0 := mk_eq_zero _ @[simp] -theorem mk_vector (α : Type u) (n : ℕ) : #(Vector α n) = #α ^ n := +theorem mk_vector (α : Type u) (n : ℕ) : #(Mathlib.Vector α n) = #α ^ n := (mk_congr (Equiv.vectorEquivFin α n)).trans <| by simp theorem mk_list_eq_sum_pow (α : Type u) : #(List α) = sum fun n : ℕ => #α ^ n := calc - #(List α) = #(Σn, Vector α n) := mk_congr (Equiv.sigmaFiberEquiv List.length).symm + #(List α) = #(Σn, Mathlib.Vector α n) := mk_congr (Equiv.sigmaFiberEquiv List.length).symm _ = sum fun n : ℕ => #α ^ n := by simp theorem mk_quot_le {α : Type u} {r : α → α → Prop} : #(Quot r) ≤ #α := diff --git a/Mathlib/SetTheory/Cardinal/Cofinality.lean b/Mathlib/SetTheory/Cardinal/Cofinality.lean index 4024caa0c1f7a..9a8363e186c9a 100644 --- a/Mathlib/SetTheory/Cardinal/Cofinality.lean +++ b/Mathlib/SetTheory/Cardinal/Cofinality.lean @@ -114,7 +114,7 @@ def StrictOrder.cof (r : α → α → Prop) : Cardinal := Order.cof (swap rᶜ) /-- The set in the definition of `Order.StrictOrder.cof` is nonempty. -/ -@[deprecated (since := "2024-10-22")] +@[deprecated "No deprecation message was provided." (since := "2024-10-22")] theorem StrictOrder.cof_nonempty (r : α → α → Prop) [IsIrrefl α r] : { c | ∃ S : Set α, Unbounded r S ∧ #S = c }.Nonempty := @Order.cof_nonempty α _ (IsRefl.swap rᶜ) @@ -287,7 +287,6 @@ theorem lsub_lt_ord {ι} {f : ι → Ordinal} {c : Ordinal} (hι : #ι < c.cof) (∀ i, f i < c) → lsub.{u, u} f < c := lsub_lt_ord_lift (by rwa [(#ι).lift_id]) -set_option linter.deprecated false in theorem cof_iSup_le_lift {ι} {f : ι → Ordinal} (H : ∀ i, f i < iSup f) : cof (iSup f) ≤ Cardinal.lift.{v, u} #ι := by rw [← Ordinal.sup] at * diff --git a/Mathlib/SetTheory/Cardinal/CountableCover.lean b/Mathlib/SetTheory/Cardinal/CountableCover.lean index 16eb4b46b329c..b3a0fe7e59ed2 100644 --- a/Mathlib/SetTheory/Cardinal/CountableCover.lean +++ b/Mathlib/SetTheory/Cardinal/CountableCover.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Sébastien Gouëzel -/ import Mathlib.SetTheory.Cardinal.Arithmetic -import Mathlib.Order.Filter.Basic +import Mathlib.Order.Filter.Finite /-! # Cardinality of a set with a countable cover diff --git a/Mathlib/SetTheory/Cardinal/SchroederBernstein.lean b/Mathlib/SetTheory/Cardinal/SchroederBernstein.lean index a5c9f5c018629..02acdbd1461b6 100644 --- a/Mathlib/SetTheory/Cardinal/SchroederBernstein.lean +++ b/Mathlib/SetTheory/Cardinal/SchroederBernstein.lean @@ -49,8 +49,7 @@ theorem schroeder_bernstein {f : α → β} {g : β → α} (hf : Function.Injec { toFun := fun s => (g '' (f '' s)ᶜ)ᶜ monotone' := fun s t hst => compl_subset_compl.mpr <| image_subset _ <| compl_subset_compl.mpr <| image_subset _ hst } - -- Porting note: dot notation `F.lfp` doesn't work here - set s : Set α := OrderHom.lfp F + set s : Set α := F.lfp have hs : (g '' (f '' s)ᶜ)ᶜ = s := F.map_lfp have hns : g '' (f '' s)ᶜ = sᶜ := compl_injective (by simp [hs]) set g' := invFun g diff --git a/Mathlib/SetTheory/Cardinal/Subfield.lean b/Mathlib/SetTheory/Cardinal/Subfield.lean index 604447735f1cc..37f45168df1dd 100644 --- a/Mathlib/SetTheory/Cardinal/Subfield.lean +++ b/Mathlib/SetTheory/Cardinal/Subfield.lean @@ -76,7 +76,7 @@ lemma cardinalMk_closure_le_max : #(closure s) ≤ max #s ℵ₀ := exact (add_lt_aleph0 this h).le · rw [max_eq_left h, add_eq_right h (this.le.trans h), max_eq_left h] rintro (n|_) - · fin_cases n <;> infer_instance + · fin_cases n <;> (dsimp only [id_eq]; infer_instance) infer_instance @[deprecated (since := "2024-11-10")] alias cardinal_mk_closure_le_max := cardinalMk_closure_le_max diff --git a/Mathlib/SetTheory/Game/Ordinal.lean b/Mathlib/SetTheory/Game/Ordinal.lean index d281b72b36a02..cf5a7e8f4cf97 100644 --- a/Mathlib/SetTheory/Game/Ordinal.lean +++ b/Mathlib/SetTheory/Game/Ordinal.lean @@ -35,7 +35,7 @@ noncomputable def toPGame (o : Ordinal.{u}) : PGame.{u} := termination_by o decreasing_by exact ((enumIsoToType o).symm x).prop -@[deprecated (since := "2024-09-22")] +@[deprecated "No deprecation message was provided." (since := "2024-09-22")] theorem toPGame_def (o : Ordinal) : o.toPGame = ⟨o.toType, PEmpty, fun x => ((enumIsoToType o).symm x).val.toPGame, PEmpty.elim⟩ := by rw [toPGame] diff --git a/Mathlib/SetTheory/Ordinal/Arithmetic.lean b/Mathlib/SetTheory/Ordinal/Arithmetic.lean index 6cc7dfe51df9e..3563908538d09 100644 --- a/Mathlib/SetTheory/Ordinal/Arithmetic.lean +++ b/Mathlib/SetTheory/Ordinal/Arithmetic.lean @@ -605,14 +605,14 @@ theorem one_add_omega0 : 1 + ω = ω := by cases a <;> cases b <;> intro H <;> cases' H with _ _ H _ _ H <;> [exact H.elim; exact Nat.succ_pos _; exact Nat.succ_lt_succ H] -@[deprecated (since := "2024-09-30")] +@[deprecated "No deprecation message was provided." (since := "2024-09-30")] alias one_add_omega := one_add_omega0 @[simp] theorem one_add_of_omega0_le {o} (h : ω ≤ o) : 1 + o = o := by rw [← Ordinal.add_sub_cancel_of_le h, ← add_assoc, one_add_omega0] -@[deprecated (since := "2024-09-30")] +@[deprecated "No deprecation message was provided." (since := "2024-09-30")] alias one_add_of_omega_le := one_add_of_omega0_le /-! ### Multiplication of ordinals -/ @@ -1185,7 +1185,7 @@ def sup {ι : Type u} (f : ι → Ordinal.{max u v}) : Ordinal.{max u v} := iSup f set_option linter.deprecated false in -@[deprecated (since := "2024-08-27")] +@[deprecated "No deprecation message was provided." (since := "2024-08-27")] theorem sSup_eq_sup {ι : Type u} (f : ι → Ordinal.{max u v}) : sSup (Set.range f) = sup.{_, v} f := rfl @@ -1252,14 +1252,15 @@ protected theorem lt_iSup_iff {ι} {f : ι → Ordinal.{u}} {a : Ordinal.{u}} [S a < iSup f ↔ ∃ i, a < f i := lt_ciSup_iff' (bddAbove_of_small _) -@[deprecated (since := "2024-11-12")] alias lt_iSup := lt_iSup_iff +@[deprecated "No deprecation message was provided." (since := "2024-11-12")] +alias lt_iSup := lt_iSup_iff set_option linter.deprecated false in @[deprecated Ordinal.lt_iSup (since := "2024-08-27")] theorem lt_sup {ι : Type u} {f : ι → Ordinal.{max u v}} {a} : a < sup.{_, v} f ↔ ∃ i, a < f i := by simpa only [not_forall, not_le] using not_congr (@sup_le_iff.{_, v} _ f a) -@[deprecated (since := "2024-08-27")] +@[deprecated "No deprecation message was provided." (since := "2024-08-27")] theorem ne_iSup_iff_lt_iSup {ι : Type u} {f : ι → Ordinal.{max u v}} : (∀ i, f i ≠ iSup f) ↔ ∀ i, f i < iSup f := forall_congr' fun i => (Ordinal.le_iSup f i).lt_iff_ne.symm @@ -1377,7 +1378,7 @@ theorem unbounded_range_of_sup_ge {α β : Type u} (r : α → α → Prop) [IsW unbounded_range_of_le_iSup r f h set_option linter.deprecated false in -@[deprecated (since := "2024-08-27")] +@[deprecated "No deprecation message was provided." (since := "2024-08-27")] theorem le_sup_shrink_equiv {s : Set Ordinal.{u}} (hs : Small.{u} s) (a) (ha : a ∈ s) : a ≤ sup.{u, u} fun x => ((@equivShrink s hs).symm x).val := by convert le_sup.{u, u} (fun x => ((@equivShrink s hs).symm x).val) ((@equivShrink s hs) ⟨a, ha⟩) @@ -1422,7 +1423,7 @@ theorem IsNormal.apply_of_isLimit {f : Ordinal.{u} → Ordinal.{v}} (H : IsNorma rw [← H.map_iSup, ho.iSup_Iio] set_option linter.deprecated false in -@[deprecated (since := "2024-08-27")] +@[deprecated "No deprecation message was provided." (since := "2024-08-27")] theorem sup_eq_sSup {s : Set Ordinal.{u}} (hs : Small.{u} s) : (sup.{u, u} fun x => (@equivShrink s hs).symm x) = sSup s := let hs' := bddAbove_iff_small.2 hs @@ -1986,12 +1987,12 @@ theorem IsNormal.eq_iff_zero_and_succ {f g : Ordinal.{u} → Ordinal.{u}} (hf : Deprecated. If you need this value explicitly, write it in terms of `iSup`. If you just want an upper bound for the image of `op`, use that `Iio a ×ˢ Iio b` is a small set. -/ -@[deprecated (since := "2024-10-11")] +@[deprecated "No deprecation message was provided." (since := "2024-10-11")] def blsub₂ (o₁ o₂ : Ordinal) (op : {a : Ordinal} → (a < o₁) → {b : Ordinal} → (b < o₂) → Ordinal) : Ordinal := lsub (fun x : o₁.toType × o₂.toType => op (typein_lt_self x.1) (typein_lt_self x.2)) -@[deprecated (since := "2024-10-11")] +@[deprecated "No deprecation message was provided." (since := "2024-10-11")] 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 @@ -2012,34 +2013,34 @@ set_option linter.deprecated false def mex {ι : Type u} (f : ι → Ordinal.{max u v}) : Ordinal := sInf (Set.range f)ᶜ -@[deprecated (since := "2024-09-20")] +@[deprecated "No deprecation message was provided." (since := "2024-09-20")] theorem mex_not_mem_range {ι : Type u} (f : ι → Ordinal.{max u v}) : mex.{_, v} f ∉ Set.range f := csInf_mem (nonempty_compl_range.{_, v} f) -@[deprecated (since := "2024-09-20")] +@[deprecated "No deprecation message was provided." (since := "2024-09-20")] theorem le_mex_of_forall {ι : Type u} {f : ι → Ordinal.{max u v}} {a : Ordinal} (H : ∀ b < a, ∃ i, f i = b) : a ≤ mex.{_, v} f := by by_contra! h exact mex_not_mem_range f (H _ h) -@[deprecated (since := "2024-09-20")] +@[deprecated "No deprecation message was provided." (since := "2024-09-20")] theorem ne_mex {ι : Type u} (f : ι → Ordinal.{max u v}) : ∀ i, f i ≠ mex.{_, v} f := by simpa using mex_not_mem_range.{_, v} f -@[deprecated (since := "2024-09-20")] +@[deprecated "No deprecation message was provided." (since := "2024-09-20")] theorem mex_le_of_ne {ι} {f : ι → Ordinal} {a} (ha : ∀ i, f i ≠ a) : mex f ≤ a := csInf_le' (by simp [ha]) -@[deprecated (since := "2024-09-20")] +@[deprecated "No deprecation message was provided." (since := "2024-09-20")] theorem exists_of_lt_mex {ι} {f : ι → Ordinal} {a} (ha : a < mex f) : ∃ i, f i = a := by by_contra! ha' exact ha.not_le (mex_le_of_ne ha') -@[deprecated (since := "2024-09-20")] +@[deprecated "No deprecation message was provided." (since := "2024-09-20")] theorem mex_le_lsub {ι : Type u} (f : ι → Ordinal.{max u v}) : mex.{_, v} f ≤ lsub.{_, v} f := csInf_le' (lsub_not_mem_range f) -@[deprecated (since := "2024-09-20")] +@[deprecated "No deprecation message was provided." (since := "2024-09-20")] theorem mex_monotone {α β : Type u} {f : α → Ordinal.{max u v}} {g : β → Ordinal.{max u v}} (h : Set.range f ⊆ Set.range g) : mex.{_, v} f ≤ mex.{_, v} g := by refine mex_le_of_ne fun i hi => ?_ @@ -2072,18 +2073,18 @@ theorem mex_lt_ord_succ_mk {ι : Type u} (f : ι → Ordinal.{u}) : def bmex (o : Ordinal) (f : ∀ a < o, Ordinal) : Ordinal := mex (familyOfBFamily o f) -@[deprecated (since := "2024-09-20")] +@[deprecated "No deprecation message was provided." (since := "2024-09-20")] theorem bmex_not_mem_brange {o : Ordinal} (f : ∀ a < o, Ordinal) : bmex o f ∉ brange o f := by rw [← range_familyOfBFamily] apply mex_not_mem_range -@[deprecated (since := "2024-09-20")] +@[deprecated "No deprecation message was provided." (since := "2024-09-20")] theorem le_bmex_of_forall {o : Ordinal} (f : ∀ a < o, Ordinal) {a : Ordinal} (H : ∀ b < a, ∃ i hi, f i hi = b) : a ≤ bmex o f := by by_contra! h exact bmex_not_mem_brange f (H _ h) -@[deprecated (since := "2024-09-20")] +@[deprecated "No deprecation message was provided." (since := "2024-09-20")] theorem ne_bmex {o : Ordinal.{u}} (f : ∀ a < o, Ordinal.{max u v}) {i} (hi) : f i hi ≠ bmex.{_, v} o f := by convert (config := {transparency := .default}) @@ -2091,23 +2092,23 @@ theorem ne_bmex {o : Ordinal.{u}} (f : ∀ a < o, Ordinal.{max u v}) {i} (hi) : -- Porting note: `familyOfBFamily_enum` → `typein_enum` rw [typein_enum] -@[deprecated (since := "2024-09-20")] +@[deprecated "No deprecation message was provided." (since := "2024-09-20")] theorem bmex_le_of_ne {o : Ordinal} {f : ∀ a < o, Ordinal} {a} (ha : ∀ i hi, f i hi ≠ a) : bmex o f ≤ a := mex_le_of_ne fun _i => ha _ _ -@[deprecated (since := "2024-09-20")] +@[deprecated "No deprecation message was provided." (since := "2024-09-20")] theorem exists_of_lt_bmex {o : Ordinal} {f : ∀ a < o, Ordinal} {a} (ha : a < bmex o f) : ∃ i hi, f i hi = a := by cases' exists_of_lt_mex ha with i hi exact ⟨_, typein_lt_self i, hi⟩ -@[deprecated (since := "2024-09-20")] +@[deprecated "No deprecation message was provided." (since := "2024-09-20")] theorem bmex_le_blsub {o : Ordinal.{u}} (f : ∀ a < o, Ordinal.{max u v}) : bmex.{_, v} o f ≤ blsub.{_, v} o f := mex_le_lsub _ -@[deprecated (since := "2024-09-20")] +@[deprecated "No deprecation message was provided." (since := "2024-09-20")] theorem bmex_monotone {o o' : Ordinal.{u}} {f : ∀ a < o, Ordinal.{max u v}} {g : ∀ a < o', Ordinal.{max u v}} (h : brange o f ⊆ brange o' g) : bmex.{_, v} o f ≤ bmex.{_, v} o' g := @@ -2165,7 +2166,7 @@ theorem one_add_natCast (m : ℕ) : 1 + (m : Ordinal) = succ m := by rw [← Nat.cast_one, ← Nat.cast_add, add_comm] rfl -@[deprecated (since := "2024-04-17")] +@[deprecated "No deprecation message was provided." (since := "2024-04-17")] alias one_add_nat_cast := one_add_natCast -- See note [no_index around OfNat.ofNat] @@ -2179,43 +2180,43 @@ theorem natCast_mul (m : ℕ) : ∀ n : ℕ, ((m * n : ℕ) : Ordinal) = m * n | 0 => by simp | n + 1 => by rw [Nat.mul_succ, Nat.cast_add, natCast_mul m n, Nat.cast_succ, mul_add_one] -@[deprecated (since := "2024-04-17")] +@[deprecated "No deprecation message was provided." (since := "2024-04-17")] alias nat_cast_mul := natCast_mul @[deprecated Nat.cast_le (since := "2024-10-17")] theorem natCast_le {m n : ℕ} : (m : Ordinal) ≤ n ↔ m ≤ n := Nat.cast_le -@[deprecated (since := "2024-04-17")] +@[deprecated "No deprecation message was provided." (since := "2024-04-17")] alias nat_cast_le := natCast_le @[deprecated Nat.cast_inj (since := "2024-10-17")] theorem natCast_inj {m n : ℕ} : (m : Ordinal) = n ↔ m = n := Nat.cast_inj -@[deprecated (since := "2024-04-17")] +@[deprecated "No deprecation message was provided." (since := "2024-04-17")] alias nat_cast_inj := natCast_inj @[deprecated Nat.cast_lt (since := "2024-10-17")] theorem natCast_lt {m n : ℕ} : (m : Ordinal) < n ↔ m < n := Nat.cast_lt -@[deprecated (since := "2024-04-17")] +@[deprecated "No deprecation message was provided." (since := "2024-04-17")] alias nat_cast_lt := natCast_lt @[deprecated Nat.cast_eq_zero (since := "2024-10-17")] theorem natCast_eq_zero {n : ℕ} : (n : Ordinal) = 0 ↔ n = 0 := Nat.cast_eq_zero -@[deprecated (since := "2024-04-17")] +@[deprecated "No deprecation message was provided." (since := "2024-04-17")] alias nat_cast_eq_zero := natCast_eq_zero @[deprecated Nat.cast_ne_zero (since := "2024-10-17")] theorem natCast_ne_zero {n : ℕ} : (n : Ordinal) ≠ 0 ↔ n ≠ 0 := Nat.cast_ne_zero -@[deprecated (since := "2024-04-17")] +@[deprecated "No deprecation message was provided." (since := "2024-04-17")] alias nat_cast_ne_zero := natCast_ne_zero @[deprecated Nat.cast_pos' (since := "2024-10-17")] theorem natCast_pos {n : ℕ} : (0 : Ordinal) < n ↔ 0 < n := Nat.cast_pos' -@[deprecated (since := "2024-04-17")] +@[deprecated "No deprecation message was provided." (since := "2024-04-17")] alias nat_cast_pos := natCast_pos @[simp, norm_cast] @@ -2226,7 +2227,7 @@ theorem natCast_sub (m n : ℕ) : ((m - n : ℕ) : Ordinal) = m - n := by · apply (add_left_cancel n).1 rw [← Nat.cast_add, add_tsub_cancel_of_le h, Ordinal.add_sub_cancel_of_le (Nat.cast_le.2 h)] -@[deprecated (since := "2024-04-17")] +@[deprecated "No deprecation message was provided." (since := "2024-04-17")] alias nat_cast_sub := natCast_sub @[simp, norm_cast] @@ -2241,7 +2242,7 @@ theorem natCast_div (m n : ℕ) : ((m / n : ℕ) : Ordinal) = m / n := by ← Nat.div_lt_iff_lt_mul (Nat.pos_of_ne_zero hn)] apply Nat.lt_succ_self -@[deprecated (since := "2024-04-17")] +@[deprecated "No deprecation message was provided." (since := "2024-04-17")] alias nat_cast_div := natCast_div @[simp, norm_cast] @@ -2249,7 +2250,7 @@ theorem natCast_mod (m n : ℕ) : ((m % n : ℕ) : Ordinal) = m % n := by rw [← add_left_cancel, div_add_mod, ← natCast_div, ← natCast_mul, ← Nat.cast_add, Nat.div_add_mod] -@[deprecated (since := "2024-04-17")] +@[deprecated "No deprecation message was provided." (since := "2024-04-17")] alias nat_cast_mod := natCast_mod @[simp] @@ -2257,7 +2258,7 @@ theorem lift_natCast : ∀ n : ℕ, lift.{u, v} n = n | 0 => by simp | n + 1 => by simp [lift_natCast n] -@[deprecated (since := "2024-04-17")] +@[deprecated "No deprecation message was provided." (since := "2024-04-17")] alias lift_nat_cast := lift_natCast -- See note [no_index around OfNat.ofNat] @@ -2292,13 +2293,13 @@ theorem lt_add_of_limit {a b c : Ordinal.{u}} (h : IsLimit c) : theorem lt_omega0 {o : Ordinal} : o < ω ↔ ∃ n : ℕ, o = n := by simp_rw [← Cardinal.ord_aleph0, Cardinal.lt_ord, lt_aleph0, card_eq_nat] -@[deprecated (since := "2024-09-30")] +@[deprecated "No deprecation message was provided." (since := "2024-09-30")] alias lt_omega := lt_omega0 theorem nat_lt_omega0 (n : ℕ) : ↑n < ω := lt_omega0.2 ⟨_, rfl⟩ -@[deprecated (since := "2024-09-30")] +@[deprecated "No deprecation message was provided." (since := "2024-09-30")] alias nat_lt_omega := nat_lt_omega0 theorem omega0_pos : 0 < ω := @@ -2307,12 +2308,12 @@ theorem omega0_pos : 0 < ω := theorem omega0_ne_zero : ω ≠ 0 := omega0_pos.ne' -@[deprecated (since := "2024-09-30")] +@[deprecated "No deprecation message was provided." (since := "2024-09-30")] alias omega_ne_zero := omega0_ne_zero theorem one_lt_omega0 : 1 < ω := by simpa only [Nat.cast_one] using nat_lt_omega0 1 -@[deprecated (since := "2024-09-30")] +@[deprecated "No deprecation message was provided." (since := "2024-09-30")] alias one_lt_omega := one_lt_omega0 theorem isLimit_omega0 : IsLimit ω := @@ -2320,10 +2321,10 @@ theorem isLimit_omega0 : IsLimit ω := let ⟨n, e⟩ := lt_omega0.1 h rw [e]; exact nat_lt_omega0 (n + 1)⟩ -@[deprecated (since := "2024-10-14")] +@[deprecated "No deprecation message was provided." (since := "2024-10-14")] alias omega0_isLimit := isLimit_omega0 -@[deprecated (since := "2024-09-30")] +@[deprecated "No deprecation message was provided." (since := "2024-09-30")] alias omega_isLimit := isLimit_omega0 theorem omega0_le {o : Ordinal} : ω ≤ o ↔ ∀ n : ℕ, ↑n ≤ o := @@ -2332,7 +2333,7 @@ theorem omega0_le {o : Ordinal} : ω ≤ o ↔ ∀ n : ℕ, ↑n ≤ o := let ⟨n, e⟩ := lt_omega0.1 h rw [e, ← succ_le_iff]; exact H (n + 1)⟩ -@[deprecated (since := "2024-09-30")] +@[deprecated "No deprecation message was provided." (since := "2024-09-30")] alias omega_le := omega0_le @[simp] @@ -2344,7 +2345,7 @@ set_option linter.deprecated false in theorem sup_natCast : sup Nat.cast = ω := iSup_natCast -@[deprecated (since := "2024-04-17")] +@[deprecated "No deprecation message was provided." (since := "2024-04-17")] alias sup_nat_cast := sup_natCast theorem nat_lt_limit {o} (h : IsLimit o) : ∀ n : ℕ, ↑n < o @@ -2354,7 +2355,7 @@ theorem nat_lt_limit {o} (h : IsLimit o) : ∀ n : ℕ, ↑n < o theorem omega0_le_of_isLimit {o} (h : IsLimit o) : ω ≤ o := omega0_le.2 fun n => le_of_lt <| nat_lt_limit h n -@[deprecated (since := "2024-09-30")] +@[deprecated "No deprecation message was provided." (since := "2024-09-30")] alias omega_le_of_isLimit := omega0_le_of_isLimit theorem isLimit_iff_omega0_dvd {a : Ordinal} : IsLimit a ↔ a ≠ 0 ∧ ω ∣ a := by @@ -2372,7 +2373,7 @@ theorem isLimit_iff_omega0_dvd {a : Ordinal} : IsLimit a ↔ a ≠ 0 ∧ ω ∣ intro e simp only [e, mul_zero] -@[deprecated (since := "2024-09-30")] +@[deprecated "No deprecation message was provided." (since := "2024-09-30")] alias isLimit_iff_omega_dvd := isLimit_iff_omega0_dvd theorem add_mul_limit_aux {a b c : Ordinal} (ba : b + a = a) (l : IsLimit c) @@ -2416,7 +2417,7 @@ theorem add_le_of_forall_add_lt {a b c : Ordinal} (hb : 0 < b) (h : ∀ d < b, a theorem IsNormal.apply_omega0 {f : Ordinal.{u} → Ordinal.{v}} (hf : IsNormal f) : ⨆ n : ℕ, f n = f ω := by rw [← iSup_natCast, hf.map_iSup] -@[deprecated (since := "2024-09-30")] +@[deprecated "No deprecation message was provided." (since := "2024-09-30")] alias IsNormal.apply_omega := IsNormal.apply_omega0 @[simp] @@ -2460,7 +2461,7 @@ theorem isLimit_ord {c} (co : ℵ₀ ≤ c) : (ord c).IsLimit := by · rw [ord_aleph0] exact Ordinal.isLimit_omega0 -@[deprecated (since := "2024-10-14")] +@[deprecated "No deprecation message was provided." (since := "2024-10-14")] alias ord_isLimit := isLimit_ord theorem noMaxOrder {c} (h : ℵ₀ ≤ c) : NoMaxOrder c.ord.toType := diff --git a/Mathlib/SetTheory/Ordinal/Basic.lean b/Mathlib/SetTheory/Ordinal/Basic.lean index 5a31bfe919ee9..ec9a34419fbf4 100644 --- a/Mathlib/SetTheory/Ordinal/Basic.lean +++ b/Mathlib/SetTheory/Ordinal/Basic.lean @@ -387,7 +387,7 @@ def typein (r : α → α → Prop) [IsWellOrder α r] : @PrincipalSeg α Ordina alias typein.principalSeg := typein set_option linter.deprecated false in -@[deprecated (since := "2024-10-09")] +@[deprecated "No deprecation message was provided." (since := "2024-10-09")] theorem typein.principalSeg_coe (r : α → α → Prop) [IsWellOrder α r] : (typein.principalSeg r : α → Ordinal) = typein r := rfl @@ -513,7 +513,7 @@ noncomputable def enumIsoToType (o : Ordinal) : Set.Iio o ≃o o.toType where right_inv _ := enum_typein _ _ map_rel_iff' := enum_le_enum' _ -@[deprecated (since := "2024-08-26")] +@[deprecated "No deprecation message was provided." (since := "2024-08-26")] alias enumIsoOut := enumIsoToType instance small_Iio (o : Ordinal.{u}) : Small.{u} (Iio o) := @@ -925,7 +925,7 @@ theorem card_succ (o : Ordinal) : card (succ o) = card o + 1 := by theorem natCast_succ (n : ℕ) : ↑n.succ = succ (n : Ordinal) := rfl -@[deprecated (since := "2024-04-17")] +@[deprecated "No deprecation message was provided." (since := "2024-04-17")] alias nat_cast_succ := natCast_succ instance uniqueIioOne : Unique (Iio (1 : Ordinal)) where @@ -1213,7 +1213,7 @@ 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")] +@[deprecated "No deprecation message was provided." (since := "2024-08-26")] alias mk_Iio_ord_out_α := mk_Iio_ord_toType theorem ord_injective : Injective ord := by diff --git a/Mathlib/SetTheory/Ordinal/Enum.lean b/Mathlib/SetTheory/Ordinal/Enum.lean index 4e5d4d38a7cf6..e8b3bb9314bc5 100644 --- a/Mathlib/SetTheory/Ordinal/Enum.lean +++ b/Mathlib/SetTheory/Ordinal/Enum.lean @@ -33,7 +33,7 @@ termination_by o variable {s : Set Ordinal.{u}} -@[deprecated (since := "2024-09-20")] +@[deprecated "No deprecation message was provided." (since := "2024-09-20")] theorem enumOrd_def (o : Ordinal.{u}) : enumOrd s o = sInf (s ∩ { b | ∀ c, c < o → enumOrd s c < b }) := by rw [enumOrd] diff --git a/Mathlib/SetTheory/Ordinal/FixedPoint.lean b/Mathlib/SetTheory/Ordinal/FixedPoint.lean index 36b50a052b83d..84f2f8db36b0d 100644 --- a/Mathlib/SetTheory/Ordinal/FixedPoint.lean +++ b/Mathlib/SetTheory/Ordinal/FixedPoint.lean @@ -52,7 +52,7 @@ least `a`, and `Ordinal.nfpFamily_le_fp` shows this is the least ordinal with th def nfpFamily (f : ι → Ordinal.{u} → Ordinal.{u}) (a : Ordinal.{u}) : Ordinal := ⨆ i, List.foldr f a i -@[deprecated (since := "2024-10-14")] +@[deprecated "No deprecation message was provided." (since := "2024-10-14")] theorem nfpFamily_eq_sup (f : ι → Ordinal.{u} → Ordinal.{u}) (a : Ordinal.{u}) : nfpFamily f a = ⨆ i, List.foldr f a i := rfl @@ -238,48 +238,48 @@ def nfpBFamily (o : Ordinal.{u}) (f : ∀ b < o, Ordinal.{max u v} → Ordinal.{ Ordinal.{max u v} → Ordinal.{max u v} := nfpFamily (familyOfBFamily o f) -@[deprecated (since := "2024-10-14")] +@[deprecated "No deprecation message was provided." (since := "2024-10-14")] theorem nfpBFamily_eq_nfpFamily {o : Ordinal} (f : ∀ b < o, Ordinal → Ordinal) : nfpBFamily.{u, v} o f = nfpFamily (familyOfBFamily o f) := rfl -@[deprecated (since := "2024-10-14")] +@[deprecated "No deprecation message was provided." (since := "2024-10-14")] theorem foldr_le_nfpBFamily {o : Ordinal} (f : ∀ b < o, Ordinal → Ordinal) (a l) : List.foldr (familyOfBFamily o f) a l ≤ nfpBFamily.{u, v} o f a := Ordinal.le_iSup _ _ -@[deprecated (since := "2024-10-14")] +@[deprecated "No deprecation message was provided." (since := "2024-10-14")] theorem le_nfpBFamily {o : Ordinal} (f : ∀ b < o, Ordinal → Ordinal) (a) : a ≤ nfpBFamily.{u, v} o f a := Ordinal.le_iSup (fun _ ↦ List.foldr _ a _) [] -@[deprecated (since := "2024-10-14")] +@[deprecated "No deprecation message was provided." (since := "2024-10-14")] theorem lt_nfpBFamily {a b} : a < nfpBFamily.{u, v} o f b ↔ ∃ l, a < List.foldr (familyOfBFamily o f) b l := Ordinal.lt_iSup_iff -@[deprecated (since := "2024-10-14")] +@[deprecated "No deprecation message was provided." (since := "2024-10-14")] theorem nfpBFamily_le_iff {o : Ordinal} {f : ∀ b < o, Ordinal → Ordinal} {a b} : nfpBFamily.{u, v} o f a ≤ b ↔ ∀ l, List.foldr (familyOfBFamily o f) a l ≤ b := Ordinal.iSup_le_iff -@[deprecated (since := "2024-10-14")] +@[deprecated "No deprecation message was provided." (since := "2024-10-14")] theorem nfpBFamily_le {o : Ordinal} {f : ∀ b < o, Ordinal → Ordinal} {a b} : (∀ l, List.foldr (familyOfBFamily o f) a l ≤ b) → nfpBFamily.{u, v} o f a ≤ b := Ordinal.iSup_le -@[deprecated (since := "2024-10-14")] +@[deprecated "No deprecation message was provided." (since := "2024-10-14")] theorem nfpBFamily_monotone (hf : ∀ i hi, Monotone (f i hi)) : Monotone (nfpBFamily.{u, v} o f) := nfpFamily_monotone fun _ => hf _ _ -@[deprecated (since := "2024-10-14")] +@[deprecated "No deprecation message was provided." (since := "2024-10-14")] theorem apply_lt_nfpBFamily (H : ∀ i hi, IsNormal (f i hi)) {a b} (hb : b < nfpBFamily.{u, v} o f a) (i hi) : f i hi b < nfpBFamily.{u, v} o f a := by rw [← familyOfBFamily_enum o f] apply apply_lt_nfpFamily (fun _ => H _ _) hb -@[deprecated (since := "2024-10-14")] +@[deprecated "No deprecation message was provided." (since := "2024-10-14")] 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 @@ -287,19 +287,19 @@ theorem apply_lt_nfpBFamily_iff (ho : o ≠ 0) (H : ∀ i hi, IsNormal (f i hi)) refine (apply_lt_nfpFamily_iff ?_).1 fun _ => h _ _ exact fun _ => H _ _, apply_lt_nfpBFamily H⟩ -@[deprecated (since := "2024-10-14")] +@[deprecated "No deprecation message was provided." (since := "2024-10-14")] theorem nfpBFamily_le_apply (ho : o ≠ 0) (H : ∀ i hi, IsNormal (f i hi)) {a b} : (∃ i hi, nfpBFamily.{u, v} o f a ≤ f i hi b) ↔ nfpBFamily.{u, v} o f a ≤ b := by rw [← not_iff_not] push_neg exact apply_lt_nfpBFamily_iff.{u, v} ho H -@[deprecated (since := "2024-10-14")] +@[deprecated "No deprecation message was provided." (since := "2024-10-14")] theorem nfpBFamily_le_fp (H : ∀ i hi, Monotone (f i hi)) {a b} (ab : a ≤ b) (h : ∀ i hi, f i hi b ≤ b) : nfpBFamily.{u, v} o f a ≤ b := nfpFamily_le_fp (fun _ => H _ _) ab fun _ => h _ _ -@[deprecated (since := "2024-10-14")] +@[deprecated "No deprecation message was provided." (since := "2024-10-14")] theorem nfpBFamily_fp {i hi} (H : IsNormal (f i hi)) (a) : f i hi (nfpBFamily.{u, v} o f a) = nfpBFamily.{u, v} o f a := by rw [← familyOfBFamily_enum o f] @@ -307,7 +307,7 @@ theorem nfpBFamily_fp {i hi} (H : IsNormal (f i hi)) (a) : rw [familyOfBFamily_enum] exact H -@[deprecated (since := "2024-10-14")] +@[deprecated "No deprecation message was provided." (since := "2024-10-14")] theorem apply_le_nfpBFamily (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 := by refine ⟨fun h => ?_, fun h i hi => ?_⟩ @@ -316,13 +316,13 @@ theorem apply_le_nfpBFamily (ho : o ≠ 0) (H : ∀ i hi, IsNormal (f i hi)) {a · rw [← nfpBFamily_fp (H i hi)] exact (H i hi).monotone h -@[deprecated (since := "2024-10-14")] +@[deprecated "No deprecation message was provided." (since := "2024-10-14")] theorem nfpBFamily_eq_self {a} (h : ∀ i hi, f i hi a = a) : nfpBFamily.{u, v} o f a = a := nfpFamily_eq_self fun _ => h _ _ /-- A generalization of the fixed point lemma for normal functions: any family of normal functions has an unbounded set of common fixed points. -/ -@[deprecated (since := "2024-10-14")] +@[deprecated "No deprecation message was provided." (since := "2024-10-14")] theorem not_bddAbove_fp_bfamily (H : ∀ i hi, IsNormal (f i hi)) : ¬ BddAbove (⋂ (i) (hi), Function.fixedPoints (f i hi)) := by rw [not_bddAbove_iff] @@ -347,12 +347,12 @@ def derivBFamily (o : Ordinal.{u}) (f : ∀ b < o, Ordinal.{max u v} → Ordinal Ordinal.{max u v} → Ordinal.{max u v} := derivFamily (familyOfBFamily o f) -@[deprecated (since := "2024-10-14")] +@[deprecated "No deprecation message was provided." (since := "2024-10-14")] theorem derivBFamily_eq_derivFamily {o : Ordinal} (f : ∀ b < o, Ordinal → Ordinal) : derivBFamily.{u, v} o f = derivFamily (familyOfBFamily o f) := rfl -@[deprecated (since := "2024-10-14")] +@[deprecated "No deprecation message was provided." (since := "2024-10-14")] theorem isNormal_derivBFamily {o : Ordinal} (f : ∀ b < o, Ordinal → Ordinal) : IsNormal (derivBFamily o f) := isNormal_derivFamily _ @@ -360,7 +360,7 @@ theorem isNormal_derivBFamily {o : Ordinal} (f : ∀ b < o, Ordinal → Ordinal) @[deprecated isNormal_derivBFamily (since := "2024-10-11")] alias derivBFamily_isNormal := isNormal_derivBFamily -@[deprecated (since := "2024-10-14")] +@[deprecated "No deprecation message was provided." (since := "2024-10-14")] theorem derivBFamily_fp {i hi} (H : IsNormal (f i hi)) (a : Ordinal) : f i hi (derivBFamily.{u, v} o f a) = derivBFamily.{u, v} o f a := by rw [← familyOfBFamily_enum o f] @@ -368,7 +368,7 @@ theorem derivBFamily_fp {i hi} (H : IsNormal (f i hi)) (a : Ordinal) : rw [familyOfBFamily_enum] exact H -@[deprecated (since := "2024-10-14")] +@[deprecated "No deprecation message was provided." (since := "2024-10-14")] theorem le_iff_derivBFamily (H : ∀ i hi, IsNormal (f i hi)) {a} : (∀ i hi, f i hi a ≤ a) ↔ ∃ b, derivBFamily.{u, v} o f b = a := by unfold derivBFamily @@ -378,7 +378,7 @@ theorem le_iff_derivBFamily (H : ∀ i hi, IsNormal (f i hi)) {a} : apply h · exact fun _ => H _ _ -@[deprecated (since := "2024-10-14")] +@[deprecated "No deprecation message was provided." (since := "2024-10-14")] theorem fp_iff_derivBFamily (H : ∀ i hi, IsNormal (f i hi)) {a} : (∀ i hi, f i hi a = a) ↔ ∃ b, derivBFamily.{u, v} o f b = a := by rw [← le_iff_derivBFamily H] @@ -387,7 +387,7 @@ theorem fp_iff_derivBFamily (H : ∀ i hi, IsNormal (f i hi)) {a} : exact h i hi /-- For a family of normal functions, `Ordinal.derivBFamily` enumerates the common fixed points. -/ -@[deprecated (since := "2024-10-14")] +@[deprecated "No deprecation message was provided." (since := "2024-10-14")] theorem derivBFamily_eq_enumOrd (H : ∀ i hi, IsNormal (f i hi)) : derivBFamily.{u, v} o f = enumOrd (⋂ (i) (hi), Function.fixedPoints (f i hi)) := by rw [eq_comm, eq_enumOrd _ (not_bddAbove_fp_bfamily H)] @@ -428,7 +428,7 @@ theorem iSup_iterate_eq_nfp (f : Ordinal.{u} → Ordinal.{u}) (a : Ordinal.{u}) exact Ordinal.le_iSup _ _ set_option linter.deprecated false in -@[deprecated (since := "2024-08-27")] +@[deprecated "No deprecation message was provided." (since := "2024-08-27")] theorem sup_iterate_eq_nfp (f : Ordinal.{u} → Ordinal.{u}) (a : Ordinal.{u}) : (sup fun n : ℕ => f^[n] a) = nfp f a := by refine le_antisymm ?_ (sup_le fun l => ?_) @@ -580,7 +580,7 @@ theorem nfp_add_eq_mul_omega0 {a b} (hba : b ≤ a * ω) : nfp (a + ·) b = a * exact nfp_monotone (isNormal_add_right a).monotone (Ordinal.zero_le b) · dsimp; rw [← mul_one_add, one_add_omega0] -@[deprecated (since := "2024-09-30")] +@[deprecated "No deprecation message was provided." (since := "2024-09-30")] alias nfp_add_eq_mul_omega := nfp_add_eq_mul_omega0 theorem add_eq_right_iff_mul_omega0_le {a b : Ordinal} : a + b = b ↔ a * ω ≤ b := by @@ -593,14 +593,14 @@ theorem add_eq_right_iff_mul_omega0_le {a b : Ordinal} : a + b = b ↔ a * ω nth_rw 1 [← this] rwa [← add_assoc, ← mul_one_add, one_add_omega0] -@[deprecated (since := "2024-09-30")] +@[deprecated "No deprecation message was provided." (since := "2024-09-30")] alias add_eq_right_iff_mul_omega_le := add_eq_right_iff_mul_omega0_le theorem add_le_right_iff_mul_omega0_le {a b : Ordinal} : a + b ≤ b ↔ a * ω ≤ b := by rw [← add_eq_right_iff_mul_omega0_le] exact (isNormal_add_right a).le_iff_eq -@[deprecated (since := "2024-09-30")] +@[deprecated "No deprecation message was provided." (since := "2024-09-30")] alias add_le_right_iff_mul_omega_le := add_le_right_iff_mul_omega0_le theorem deriv_add_eq_mul_omega0_add (a b : Ordinal.{u}) : deriv (a + ·) b = a * ω + b := by @@ -612,7 +612,7 @@ theorem deriv_add_eq_mul_omega0_add (a b : Ordinal.{u}) : deriv (a + ·) b = a * · rw [deriv_succ, h, add_succ] exact nfp_eq_self (add_eq_right_iff_mul_omega0_le.2 ((le_add_right _ _).trans (le_succ _))) -@[deprecated (since := "2024-09-30")] +@[deprecated "No deprecation message was provided." (since := "2024-09-30")] alias deriv_add_eq_mul_omega_add := deriv_add_eq_mul_omega0_add /-! ### Fixed points of multiplication -/ @@ -645,7 +645,7 @@ theorem nfp_mul_eq_opow_omega0 {a b : Ordinal} (hb : 0 < b) (hba : b ≤ a ^ ω) rw [← nfp_mul_one ha] exact nfp_monotone (isNormal_mul_right ha).monotone (one_le_iff_pos.2 hb) -@[deprecated (since := "2024-09-30")] +@[deprecated "No deprecation message was provided." (since := "2024-09-30")] alias nfp_mul_eq_opow_omega := nfp_mul_eq_opow_omega0 theorem eq_zero_or_opow_omega0_le_of_mul_eq_right {a b : Ordinal} (hab : a * b = b) : @@ -659,7 +659,7 @@ theorem eq_zero_or_opow_omega0_le_of_mul_eq_right {a b : Ordinal} (hab : a * b = rw [← Ne, ← one_le_iff_ne_zero] at hb exact nfp_le_fp (isNormal_mul_right ha).monotone hb (le_of_eq hab) -@[deprecated (since := "2024-09-30")] +@[deprecated "No deprecation message was provided." (since := "2024-09-30")] alias eq_zero_or_opow_omega_le_of_mul_eq_right := eq_zero_or_opow_omega0_le_of_mul_eq_right theorem mul_eq_right_iff_opow_omega0_dvd {a b : Ordinal} : a * b = b ↔ a ^ ω ∣ b := by @@ -677,7 +677,7 @@ theorem mul_eq_right_iff_opow_omega0_dvd {a b : Ordinal} : a * b = b ↔ a ^ ω cases' h with c hc rw [hc, ← mul_assoc, ← opow_one_add, one_add_omega0] -@[deprecated (since := "2024-09-30")] +@[deprecated "No deprecation message was provided." (since := "2024-09-30")] alias mul_eq_right_iff_opow_omega_dvd := mul_eq_right_iff_opow_omega0_dvd theorem mul_le_right_iff_opow_omega0_dvd {a b : Ordinal} (ha : 0 < a) : @@ -685,7 +685,7 @@ theorem mul_le_right_iff_opow_omega0_dvd {a b : Ordinal} (ha : 0 < a) : rw [← mul_eq_right_iff_opow_omega0_dvd] exact (isNormal_mul_right ha).le_iff_eq -@[deprecated (since := "2024-09-30")] +@[deprecated "No deprecation message was provided." (since := "2024-09-30")] alias mul_le_right_iff_opow_omega_dvd := mul_le_right_iff_opow_omega0_dvd theorem nfp_mul_opow_omega0_add {a c : Ordinal} (b) (ha : 0 < a) (hc : 0 < c) @@ -705,7 +705,7 @@ theorem nfp_mul_opow_omega0_add {a c : Ordinal} (b) (ha : 0 < a) (hc : 0 < c) rw [add_zero, mul_lt_mul_iff_left (opow_pos ω ha)] at this rwa [succ_le_iff] -@[deprecated (since := "2024-09-30")] +@[deprecated "No deprecation message was provided." (since := "2024-09-30")] alias nfp_mul_opow_omega_add := nfp_mul_opow_omega0_add theorem deriv_mul_eq_opow_omega0_mul {a : Ordinal.{u}} (ha : 0 < a) (b) : @@ -718,7 +718,7 @@ theorem deriv_mul_eq_opow_omega0_mul {a : Ordinal.{u}} (ha : 0 < a) (b) : · rw [deriv_succ, h] exact nfp_mul_opow_omega0_add c ha zero_lt_one (one_le_iff_pos.2 (opow_pos _ ha)) -@[deprecated (since := "2024-09-30")] +@[deprecated "No deprecation message was provided." (since := "2024-09-30")] alias deriv_mul_eq_opow_omega_mul := deriv_mul_eq_opow_omega0_mul end Ordinal diff --git a/Mathlib/SetTheory/Ordinal/FixedPointApproximants.lean b/Mathlib/SetTheory/Ordinal/FixedPointApproximants.lean index 97272de665f4f..4d1e937f10243 100644 --- a/Mathlib/SetTheory/Ordinal/FixedPointApproximants.lean +++ b/Mathlib/SetTheory/Ordinal/FixedPointApproximants.lean @@ -226,9 +226,9 @@ theorem lfpApprox_le_of_mem_fixedPoints {a : α} /-- The approximation sequence converges at the successor of the domain's cardinality to the least fixed point if starting from `⊥` -/ -theorem lfpApprox_ord_eq_lfp : lfpApprox f ⊥ (ord <| succ #α) = lfp f := by +theorem lfpApprox_ord_eq_lfp : lfpApprox f ⊥ (ord <| succ #α) = f.lfp := by apply le_antisymm - · have h_lfp : ∃ y : fixedPoints f, lfp f = y := by use ⊥; exact rfl + · have h_lfp : ∃ y : fixedPoints f, f.lfp = y := by use ⊥; exact rfl let ⟨y, h_y⟩ := h_lfp; rw [h_y] exact lfpApprox_le_of_mem_fixedPoints f ⊥ y.2 bot_le (ord <| succ #α) · have h_fix : ∃ y : fixedPoints f, lfpApprox f ⊥ (ord <| succ #α) = y := by @@ -238,7 +238,7 @@ theorem lfpApprox_ord_eq_lfp : lfpApprox f ⊥ (ord <| succ #α) = lfp f := by exact lfp_le_fixed f x.prop /-- Some approximation of the least fixed point starting from `⊥` is the least fixed point. -/ -theorem lfp_mem_range_lfpApprox : lfp f ∈ Set.range (lfpApprox f ⊥) := by +theorem lfp_mem_range_lfpApprox : f.lfp ∈ Set.range (lfpApprox f ⊥) := by use ord <| succ #α exact lfpApprox_ord_eq_lfp f @@ -256,52 +256,52 @@ decreasing_by exact h unseal gfpApprox lfpApprox theorem gfpApprox_antitone : Antitone (gfpApprox f x) := - lfpApprox_monotone (OrderHom.dual f) x + lfpApprox_monotone f.dual x theorem gfpApprox_le {a : Ordinal} : gfpApprox f x a ≤ x := - le_lfpApprox (OrderHom.dual f) x + le_lfpApprox f.dual x theorem gfpApprox_add_one (h : f x ≤ x) (a : Ordinal) : gfpApprox f x (a+1) = f (gfpApprox f x a) := - lfpApprox_add_one (OrderHom.dual f) x h a + lfpApprox_add_one f.dual x h a theorem gfpApprox_mono_left : Monotone (gfpApprox : (α →o α) → _) := by intro f g h - have : OrderHom.dual g ≤ OrderHom.dual f := h + have : g.dual ≤ f.dual := h exact lfpApprox_mono_left this theorem gfpApprox_mono_mid : Monotone (gfpApprox f) := - fun _ _ h => lfpApprox_mono_mid (OrderHom.dual f) h + fun _ _ h => lfpApprox_mono_mid f.dual h /-- The approximations of the greatest fixed point stabilize at a fixed point of `f` -/ theorem gfpApprox_eq_of_mem_fixedPoints {a b : Ordinal} (h_init : f x ≤ x) (h_ab : a ≤ b) (h : gfpApprox f x a ∈ fixedPoints f) : gfpApprox f x b = gfpApprox f x a := - lfpApprox_eq_of_mem_fixedPoints (OrderHom.dual f) x h_init h_ab h + lfpApprox_eq_of_mem_fixedPoints f.dual x h_init h_ab h /-- There are distinct indices smaller than the successor of the domain's cardinality yielding the same value -/ theorem exists_gfpApprox_eq_gfpApprox : ∃ a < ord <| succ #α, ∃ b < ord <| succ #α, a ≠ b ∧ gfpApprox f x a = gfpApprox f x b := - exists_lfpApprox_eq_lfpApprox (OrderHom.dual f) x + exists_lfpApprox_eq_lfpApprox f.dual x /-- The approximation at the index of the successor of the domain's cardinality is a fixed point -/ lemma gfpApprox_ord_mem_fixedPoint (h_init : f x ≤ x) : gfpApprox f x (ord <| succ #α) ∈ fixedPoints f := - lfpApprox_ord_mem_fixedPoint (OrderHom.dual f) x h_init + lfpApprox_ord_mem_fixedPoint f.dual x h_init /-- Every value of the approximation is greater or equal than every fixed point of `f` less or equal than the initial value -/ lemma le_gfpApprox_of_mem_fixedPoints {a : α} (h_a : a ∈ fixedPoints f) (h_le_init : a ≤ x) (i : Ordinal) : a ≤ gfpApprox f x i := - lfpApprox_le_of_mem_fixedPoints (OrderHom.dual f) x h_a h_le_init i + lfpApprox_le_of_mem_fixedPoints f.dual x h_a h_le_init i /-- The approximation sequence converges at the successor of the domain's cardinality to the greatest fixed point if starting from `⊥` -/ -theorem gfpApprox_ord_eq_gfp : gfpApprox f ⊤ (ord <| succ #α) = gfp f := - lfpApprox_ord_eq_lfp (OrderHom.dual f) +theorem gfpApprox_ord_eq_gfp : gfpApprox f ⊤ (ord <| succ #α) = f.gfp := + lfpApprox_ord_eq_lfp f.dual /-- Some approximation of the least fixed point starting from `⊤` is the greatest fixed point. -/ -theorem gfp_mem_range_gfpApprox : gfp f ∈ Set.range (gfpApprox f ⊤) := - lfp_mem_range_lfpApprox (OrderHom.dual f) +theorem gfp_mem_range_gfpApprox : f.gfp ∈ Set.range (gfpApprox f ⊤) := + lfp_mem_range_lfpApprox f.dual end OrdinalApprox diff --git a/Mathlib/SetTheory/Ordinal/Principal.lean b/Mathlib/SetTheory/Ordinal/Principal.lean index 5d6417f174042..194abeabc7c50 100644 --- a/Mathlib/SetTheory/Ordinal/Principal.lean +++ b/Mathlib/SetTheory/Ordinal/Principal.lean @@ -129,7 +129,7 @@ theorem not_bddAbove_principal (op : Ordinal → Ordinal → Ordinal) : exact ((le_nfp _ _).trans (ha (principal_nfp_iSup op (succ a)))).not_lt (lt_succ a) set_option linter.deprecated false in -@[deprecated (since := "2024-10-11")] +@[deprecated "No deprecation message was provided." (since := "2024-10-11")] 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) := by intro a b ha hb @@ -147,7 +147,7 @@ theorem principal_nfp_blsub₂ (op : Ordinal → Ordinal → Ordinal) (o : Ordin exact lt_blsub₂ (@fun a _ b _ => op a b) hm (hn.trans_le h) set_option linter.deprecated false in -@[deprecated (since := "2024-10-11")] +@[deprecated "No deprecation message was provided." (since := "2024-10-11")] 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⟩ diff --git a/Mathlib/SetTheory/ZFC/Basic.lean b/Mathlib/SetTheory/ZFC/Basic.lean index c7a0c35cdfcef..a2b3354096bf0 100644 --- a/Mathlib/SetTheory/ZFC/Basic.lean +++ b/Mathlib/SetTheory/ZFC/Basic.lean @@ -447,12 +447,12 @@ set_option linter.deprecated false /-- Function equivalence is defined so that `f ~ g` iff `∀ x y, x ~ y → f x ~ g y`. This extends to equivalence of `n`-ary functions. -/ -@[deprecated (since := "2024-09-02")] +@[deprecated "No deprecation message was provided." (since := "2024-09-02")] def Arity.Equiv : ∀ {n}, OfArity PSet.{u} PSet.{u} n → OfArity PSet.{u} PSet.{u} n → Prop | 0, a, b => PSet.Equiv a b | _ + 1, a, b => ∀ x y : PSet, PSet.Equiv x y → Arity.Equiv (a x) (b y) -@[deprecated (since := "2024-09-02")] +@[deprecated "No deprecation message was provided." (since := "2024-09-02")] theorem Arity.equiv_const {a : PSet.{u}} : ∀ n, Arity.Equiv (OfArity.const PSet.{u} a n) (OfArity.const PSet.{u} a n) | 0 => Equiv.rfl @@ -460,46 +460,46 @@ theorem Arity.equiv_const {a : PSet.{u}} : /-- `resp n` is the collection of n-ary functions on `PSet` that respect equivalence, i.e. when the inputs are equivalent the output is as well. -/ -@[deprecated (since := "2024-09-02")] +@[deprecated "No deprecation message was provided." (since := "2024-09-02")] def Resp (n) := { x : OfArity PSet.{u} PSet.{u} n // Arity.Equiv x x } -@[deprecated (since := "2024-09-02")] +@[deprecated "No deprecation message was provided." (since := "2024-09-02")] instance Resp.inhabited {n} : Inhabited (Resp n) := ⟨⟨OfArity.const _ default _, Arity.equiv_const _⟩⟩ /-- The `n`-ary image of a `(n + 1)`-ary function respecting equivalence as a function respecting equivalence. -/ -@[deprecated (since := "2024-09-02")] +@[deprecated "No deprecation message was provided." (since := "2024-09-02")] def Resp.f {n} (f : Resp (n + 1)) (x : PSet) : Resp n := ⟨f.1 x, f.2 _ _ <| Equiv.refl x⟩ /-- Function equivalence for functions respecting equivalence. See `PSet.Arity.Equiv`. -/ -@[deprecated (since := "2024-09-02")] +@[deprecated "No deprecation message was provided." (since := "2024-09-02")] def Resp.Equiv {n} (a b : Resp n) : Prop := Arity.Equiv a.1 b.1 -@[deprecated (since := "2024-09-02"), refl] +@[deprecated "No deprecation message was provided." (since := "2024-09-02"), refl] protected theorem Resp.Equiv.refl {n} (a : Resp n) : Resp.Equiv a a := a.2 -@[deprecated (since := "2024-09-02")] +@[deprecated "No deprecation message was provided." (since := "2024-09-02")] protected theorem Resp.Equiv.euc : ∀ {n} {a b c : Resp n}, Resp.Equiv a b → Resp.Equiv c b → Resp.Equiv a c | 0, _, _, _, hab, hcb => PSet.Equiv.euc hab hcb | n + 1, a, b, c, hab, hcb => fun x y h => @Resp.Equiv.euc n (a.f x) (b.f y) (c.f y) (hab _ _ h) (hcb _ _ <| PSet.Equiv.refl y) -@[deprecated (since := "2024-09-02"), symm] +@[deprecated "No deprecation message was provided." (since := "2024-09-02"), symm] protected theorem Resp.Equiv.symm {n} {a b : Resp n} : Resp.Equiv a b → Resp.Equiv b a := (Resp.Equiv.refl b).euc -@[deprecated (since := "2024-09-02"), trans] +@[deprecated "No deprecation message was provided." (since := "2024-09-02"), trans] protected theorem Resp.Equiv.trans {n} {x y z : Resp n} (h1 : Resp.Equiv x y) (h2 : Resp.Equiv y z) : Resp.Equiv x z := h1.euc h2.symm -@[deprecated (since := "2024-09-02")] +@[deprecated "No deprecation message was provided." (since := "2024-09-02")] instance Resp.setoid {n} : Setoid (Resp n) := ⟨Resp.Equiv, Resp.Equiv.refl, Resp.Equiv.symm, Resp.Equiv.trans⟩ @@ -611,7 +611,7 @@ set_option linter.deprecated false namespace Resp /-- Helper function for `PSet.eval`. -/ -@[deprecated (since := "2024-09-02")] +@[deprecated "No deprecation message was provided." (since := "2024-09-02")] def evalAux : ∀ {n}, { f : Resp n → OfArity ZFSet.{u} ZFSet.{u} n // ∀ a b : Resp n, Resp.Equiv a b → f a = f b } @@ -626,11 +626,11 @@ def evalAux : evalAux.2 (Resp.f b z) (Resp.f c z) (h _ _ (PSet.Equiv.refl z))⟩ /-- An equivalence-respecting function yields an n-ary ZFC set function. -/ -@[deprecated (since := "2024-09-02")] +@[deprecated "No deprecation message was provided." (since := "2024-09-02")] def eval (n) : Resp n → OfArity ZFSet.{u} ZFSet.{u} n := evalAux.1 -@[deprecated (since := "2024-09-02")] +@[deprecated "No deprecation message was provided." (since := "2024-09-02")] theorem eval_val {n f x} : (@eval (n + 1) f : ZFSet → OfArity ZFSet ZFSet n) ⟦x⟧ = eval n (Resp.f f x) := rfl @@ -640,24 +640,25 @@ end Resp /-- A set function is "definable" if it is the image of some n-ary pre-set function. This isn't exactly definability, but is useful as a sufficient condition for functions that have a computable image. -/ -@[deprecated (since := "2024-09-02")] +@[deprecated "No deprecation message was provided." (since := "2024-09-02")] class inductive Definable (n) : OfArity ZFSet.{u} ZFSet.{u} n → Type (u + 1) | mk (f) : Definable n (Resp.eval n f) -attribute [deprecated (since := "2024-09-02"), instance] Definable.mk +attribute [deprecated "No deprecation message was provided." (since := "2024-09-02"), instance] + Definable.mk /-- The evaluation of a function respecting equivalence is definable, by that same function. -/ -@[deprecated (since := "2024-09-02")] +@[deprecated "No deprecation message was provided." (since := "2024-09-02")] def Definable.EqMk {n} (f) : ∀ {s : OfArity ZFSet.{u} ZFSet.{u} n} (_ : Resp.eval _ f = s), Definable n s | _, rfl => ⟨f⟩ /-- Turns a definable function into a function that respects equivalence. -/ -@[deprecated (since := "2024-09-02")] +@[deprecated "No deprecation message was provided." (since := "2024-09-02")] def Definable.Resp {n} : ∀ (s : OfArity ZFSet.{u} ZFSet.{u} n) [Definable n s], Resp n | _, ⟨f⟩ => f -@[deprecated (since := "2024-09-02")] +@[deprecated "No deprecation message was provided." (since := "2024-09-02")] theorem Definable.eq {n} : ∀ (s : OfArity ZFSet.{u} ZFSet.{u} n) [H : Definable n s], (@Definable.Resp n s H).eval _ = s | _, ⟨_⟩ => rfl @@ -670,7 +671,7 @@ open PSet ZFSet set_option linter.deprecated false in /-- All functions are classically definable. -/ -@[deprecated (since := "2024-09-02")] +@[deprecated "No deprecation message was provided." (since := "2024-09-02")] noncomputable def allDefinable : ∀ {n} (F : OfArity ZFSet ZFSet n), Definable n F | 0, F => let p := @Quotient.exists_rep PSet _ F @@ -706,7 +707,7 @@ theorem exact {x y : PSet} : mk x = mk y → PSet.Equiv x y := Quotient.exact set_option linter.deprecated false in -@[deprecated (since := "2024-09-02"), simp] +@[deprecated "No deprecation message was provided." (since := "2024-09-02"), simp] theorem eval_mk {n f x} : (@Resp.eval (n + 1) f : ZFSet → OfArity ZFSet ZFSet n) (mk x) = Resp.eval n (Resp.f f x) := rfl diff --git a/Mathlib/Tactic/Abel.lean b/Mathlib/Tactic/Abel.lean index 3798b879812e6..0326607cfdb06 100644 --- a/Mathlib/Tactic/Abel.lean +++ b/Mathlib/Tactic/Abel.lean @@ -247,11 +247,11 @@ theorem term_atom_pfg {α} [AddCommGroup α] (x x' : α) (h : x = x') : x = term /-- Interpret an expression as an atom for `abel`'s normal form. -/ def evalAtom (e : Expr) : M (NormalExpr × Expr) := do let { expr := e', proof?, .. } ← (← readThe AtomM.Context).evalAtom e - let i ← AtomM.addAtom e' + let (i, a) ← AtomM.addAtom e' let p ← match proof? with | none => iapp ``term_atom #[e] - | some p => iapp ``term_atom_pf #[e, e', p] - return (← term' (← intToExpr 1, 1) (i, e') (← zero'), p) + | some p => iapp ``term_atom_pf #[e, a, p] + return (← term' (← intToExpr 1, 1) (i, a) (← zero'), p) theorem unfold_sub {α} [SubtractionMonoid α] (a b c : α) (h : a + -b = c) : a - b = c := by rw [sub_eq_add_neg, h] diff --git a/Mathlib/Tactic/Common.lean b/Mathlib/Tactic/Common.lean index 90340cd10a34e..3c61c4a884912 100644 --- a/Mathlib/Tactic/Common.lean +++ b/Mathlib/Tactic/Common.lean @@ -4,9 +4,10 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Kim Morrison -/ --- First import Aesop and Qq +-- First import Aesop, Qq, and Plausible import Aesop import Qq +import Plausible -- Tools for analysing imports, like `#find_home`, `#minimize_imports`, ... import ImportGraph.Imports diff --git a/Mathlib/Tactic/FBinop.lean b/Mathlib/Tactic/FBinop.lean index 96c3a9db63cb6..8e58cb0849763 100644 --- a/Mathlib/Tactic/FBinop.lean +++ b/Mathlib/Tactic/FBinop.lean @@ -185,18 +185,14 @@ private def toExprCore (t : Tree) : TermElabM Expr := do | .term _ trees e => modifyInfoState (fun s => { s with trees := s.trees ++ trees }); return e | .binop ref f lhs rhs => - withRef ref <| withInfoContext' ref (mkInfo := mkTermInfo .anonymous ref) (do + withRef ref <| withTermInfoContext' .anonymous ref do let lhs ← toExprCore lhs let mut rhs ← toExprCore rhs - mkBinOp f lhs rhs) - -- FIXME the signature of withInfoContext' has changed, not sure yet what to put here: - (do failure) + mkBinOp f lhs rhs | .macroExpansion macroName stx stx' nested => - withRef stx <| withInfoContext' stx (mkInfo := mkTermInfo macroName stx) (do + withRef stx <| withTermInfoContext' macroName stx do withMacroExpansion stx stx' do - toExprCore nested) - -- FIXME the signature of withInfoContext' has changed, not sure yet what to put here: - (do failure) + toExprCore nested /-- Try to coerce elements in the tree to `maxS` when needed. -/ private def applyCoe (t : Tree) (maxS : SRec) : TermElabM Tree := do diff --git a/Mathlib/Tactic/GCongr/Core.lean b/Mathlib/Tactic/GCongr/Core.lean index a47257466df27..90aeed7ba3815 100644 --- a/Mathlib/Tactic/GCongr/Core.lean +++ b/Mathlib/Tactic/GCongr/Core.lean @@ -367,7 +367,7 @@ partial def _root_.Lean.MVarId.gcongr 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) + Except.ok <$> withReducibleAndInstances (g.apply (← mkConstWithFreshMVarLevels lem.declName)) catch e => pure (Except.error e) match gs with | .error e => diff --git a/Mathlib/Tactic/ITauto.lean b/Mathlib/Tactic/ITauto.lean index f0449d9828b14..f87cbcddd6ec3 100644 --- a/Mathlib/Tactic/ITauto.lean +++ b/Mathlib/Tactic/ITauto.lean @@ -486,7 +486,7 @@ partial def reify (e : Q(Prop)) : AtomM IProp := | ~q(@Ne Prop $a $b) => return .not (.eq (← reify a) (← reify b)) | e => if e.isArrow then return .imp (← reify e.bindingDomain!) (← reify e.bindingBody!) - else return .var (← AtomM.addAtom e) + else return .var (← AtomM.addAtom e).1 /-- Once we have a proof object, we have to apply it to the goal. -/ partial def applyProof (g : MVarId) (Γ : NameMap Expr) (p : Proof) : MetaM Unit := diff --git a/Mathlib/Tactic/Linarith/Oracle/SimplexAlgorithm/Datatypes.lean b/Mathlib/Tactic/Linarith/Oracle/SimplexAlgorithm/Datatypes.lean index 8a5a9488ae1a9..2f6eb09ce7de1 100644 --- a/Mathlib/Tactic/Linarith/Oracle/SimplexAlgorithm/Datatypes.lean +++ b/Mathlib/Tactic/Linarith/Oracle/SimplexAlgorithm/Datatypes.lean @@ -69,7 +69,7 @@ instance : UsableInSimplexAlgorithm DenseMatrix where for ⟨i, j, v⟩ in vals do data := data.modify i fun row => row.set! j v return ⟨data⟩ - swapRows mat i j := ⟨mat.data.swap! i j⟩ + swapRows mat i j := ⟨mat.data.swapIfInBounds i j⟩ subtractRow mat i j coef := let newData : Array (Array Rat) := mat.data.modify j fun row => row.zipWith mat.data[i]! fun x y => x - coef * y @@ -101,7 +101,7 @@ instance : UsableInSimplexAlgorithm SparseMatrix where if v != 0 then data := data.modify i fun row => row.insert j v return ⟨data⟩ - swapRows mat i j := ⟨mat.data.swap! i j⟩ + swapRows mat i j := ⟨mat.data.swapIfInBounds i j⟩ subtractRow mat i j coef := let newData := mat.data.modify j fun row => mat.data[i]!.fold (fun cur k val => diff --git a/Mathlib/Tactic/Linarith/Oracle/SimplexAlgorithm/SimplexAlgorithm.lean b/Mathlib/Tactic/Linarith/Oracle/SimplexAlgorithm/SimplexAlgorithm.lean index 9858e94c23f14..4ecfb36c3cab1 100644 --- a/Mathlib/Tactic/Linarith/Oracle/SimplexAlgorithm/SimplexAlgorithm.lean +++ b/Mathlib/Tactic/Linarith/Oracle/SimplexAlgorithm/SimplexAlgorithm.lean @@ -48,8 +48,8 @@ def doPivotOperation (exitIdx enterIdx : Nat) : SimplexAlgorithmM matType Unit : let newBasic := s.basic.set! exitIdx s.free[enterIdx]! let newFree := s.free.set! enterIdx s.basic[exitIdx]! - have hb : newBasic.size = s.basic.size := by apply Array.size_setD - have hf : newFree.size = s.free.size := by apply Array.size_setD + have hb : newBasic.size = s.basic.size := by apply Array.size_setIfInBounds + have hf : newFree.size = s.free.size := by apply Array.size_setIfInBounds return (⟨newBasic, newFree, hb ▸ hf ▸ mat⟩ : Tableau matType) @@ -60,7 +60,7 @@ nonnegative. def checkSuccess : SimplexAlgorithmM matType Bool := do let lastIdx := (← get).free.size - 1 return (← get).mat[(0, lastIdx)]! > 0 && - (← Nat.allM (← get).basic.size (fun i => do return (← get).mat[(i, lastIdx)]! >= 0)) + (← (← get).basic.size.allM (fun i _ => do return (← get).mat[(i, lastIdx)]! ≥ 0)) /-- Chooses an entering variable: among the variables with a positive coefficient in the objective diff --git a/Mathlib/Tactic/Linarith/Preprocessing.lean b/Mathlib/Tactic/Linarith/Preprocessing.lean index 489ff96d9f25c..348309a7774af 100644 --- a/Mathlib/Tactic/Linarith/Preprocessing.lean +++ b/Mathlib/Tactic/Linarith/Preprocessing.lean @@ -274,12 +274,12 @@ partial def findSquares (s : RBSet (Nat × Bool) lexOrd.compare) (e : Expr) : | (``HPow.hPow, #[_, _, _, _, a, b]) => match b.numeral? with | some 2 => do let s ← findSquares s a - let ai ← AtomM.addAtom a + let (ai, _) ← AtomM.addAtom a return (s.insert (ai, true)) | _ => e.foldlM findSquares s | (``HMul.hMul, #[_, _, _, _, a, b]) => do - let ai ← AtomM.addAtom a - let bi ← AtomM.addAtom b + let (ai, _) ← AtomM.addAtom a + let (bi, _) ← AtomM.addAtom b if ai = bi then do let s ← findSquares s a return (s.insert (ai, false)) diff --git a/Mathlib/Tactic/Linter/DocPrime.lean b/Mathlib/Tactic/Linter/DocPrime.lean index 7221a12e1ad7f..c2a8a38fbcdcf 100644 --- a/Mathlib/Tactic/Linter/DocPrime.lean +++ b/Mathlib/Tactic/Linter/DocPrime.lean @@ -26,7 +26,7 @@ namespace Mathlib.Linter The "docPrime" linter emits a warning on declarations that have no doc-string and whose name ends with a `'`. -The file `scripts/no_lints_prime_decls.txt` contains a list of temporary exceptions to this linter. +The file `scripts/nolints_prime_decls.txt` contains a list of temporary exceptions to this linter. This list should not be appended to, and become emptied over time. -/ register_option linter.docPrime : Bool := { @@ -63,8 +63,8 @@ def docPrimeLinter : Linter where run := withSetOptionIn fun stx ↦ do relative to the unprimed version, or an explanation as to why no better naming scheme \ is possible." if docstring[0][1].getAtomVal.isEmpty && declName.toString.back == '\'' then - if ← System.FilePath.pathExists "scripts/no_lints_prime_decls.txt" then - if (← IO.FS.lines "scripts/no_lints_prime_decls.txt").contains declName.toString then + if ← System.FilePath.pathExists "scripts/nolints_prime_decls.txt" then + if (← IO.FS.lines "scripts/nolints_prime_decls.txt").contains declName.toString then return else Linter.logLint linter.docPrime declId msg diff --git a/Mathlib/Tactic/Linter/Header.lean b/Mathlib/Tactic/Linter/Header.lean index 3e2a44a3d836f..19b353da35598 100644 --- a/Mathlib/Tactic/Linter/Header.lean +++ b/Mathlib/Tactic/Linter/Header.lean @@ -218,6 +218,15 @@ def isInMathlib (modName : Name) : IO Bool := do return (ml.map (·.module == modName)).any (·) else return false +/-- `inMathlibRef` is +* `none` at initialization time; +* `some true` if the `header` linter has already discovered that the current file + is imported in `Mathlib.lean`; +* `some false` if the `header` linter has already discovered that the current file + is *not* imported in `Mathlib.lean`. +-/ +initialize inMathlibRef : IO.Ref (Option Bool) ← IO.mkRef none + /-- The "header" style linter checks that a file starts with ``` @@ -290,7 +299,18 @@ def duplicateImportsCheck (imports : Array Syntax) : CommandElabM Unit := do @[inherit_doc Mathlib.Linter.linter.style.header] def headerLinter : Linter where run := withSetOptionIn fun stx ↦ do let mainModule ← getMainModule - unless Linter.getLinterValue linter.style.header (← getOptions) || (← isInMathlib mainModule) do + let inMathlib? := ← match ← inMathlibRef.get with + | some d => return d + | none => do + let val ← isInMathlib mainModule + -- We store the answer to the question "is this file in `Mathlib.lean`?" in `inMathlibRef` + -- to avoid recomputing its value on every command. This is a performance optimisation. + inMathlibRef.set (some val) + return val + -- The linter skips files not imported in `Mathlib.lean`, to avoid linting "scratch files". + -- It is however active in the test file `MathlibTest.Header` for the linter itself. + unless inMathlib? || mainModule == `MathlibTest.Header do return + unless Linter.getLinterValue linter.style.header (← getOptions) do return if (← get).messages.hasErrors then return diff --git a/Mathlib/Tactic/Linter/PPRoundtrip.lean b/Mathlib/Tactic/Linter/PPRoundtrip.lean index dced1f5293546..df238e0927ee3 100644 --- a/Mathlib/Tactic/Linter/PPRoundtrip.lean +++ b/Mathlib/Tactic/Linter/PPRoundtrip.lean @@ -60,7 +60,7 @@ def polishSource (s : String) : String × Array Nat := let preWS := split.foldl (init := #[]) fun p q => let txt := q.trimLeft.length (p.push (q.length - txt)).push txt - let preWS := preWS.eraseIdx! 0 + let preWS := preWS.eraseIdxIfInBounds 0 let s := (split.map .trimLeft).filter (· != "") (" ".intercalate (s.filter (!·.isEmpty)), preWS) diff --git a/Mathlib/Tactic/Linter/TextBased.lean b/Mathlib/Tactic/Linter/TextBased.lean index a1d3a9955b489..aa2c455269b43 100644 --- a/Mathlib/Tactic/Linter/TextBased.lean +++ b/Mathlib/Tactic/Linter/TextBased.lean @@ -56,6 +56,8 @@ inductive StyleError where | adaptationNote /-- A line ends with windows line endings (\r\n) instead of unix ones (\n). -/ | windowsLineEnding + /-- A line contains trailing whitespace. -/ + | trailingWhitespace deriving BEq /-- How to format style errors -/ @@ -76,6 +78,7 @@ def StyleError.errorMessage (err : StyleError) : String := match err with "Found the string \"Adaptation note:\", please use the #adaptation_note command instead" | windowsLineEnding => "This line ends with a windows line ending (\r\n): please use Unix line\ endings (\n) instead" + | trailingWhitespace => "This line ends with some whitespace: please remove this" /-- 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; @@ -83,6 +86,7 @@ def StyleError.errorMessage (err : StyleError) : String := match err with def StyleError.errorCode (err : StyleError) : String := match err with | StyleError.adaptationNote => "ERR_ADN" | StyleError.windowsLineEnding => "ERR_WIN" + | StyleError.trailingWhitespace => "ERR_TWS" /-- Context for a style error: the actual error, the line number in the file we're reading and the path to the file. -/ @@ -160,6 +164,7 @@ 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_ADN" => some (StyleError.adaptationNote) + | "ERR_TWS" => some (StyleError.trailingWhitespace) | "ERR_WIN" => some (StyleError.windowsLineEnding) | _ => none match String.toNat? lineNumber with @@ -196,14 +201,24 @@ section /-- Lint on any occurrences of the string "Adaptation note:" or variants thereof. -/ def adaptationNoteLinter : TextbasedLinter := fun lines ↦ Id.run do let mut errors := Array.mkEmpty 0 - let mut lineNumber := 1 - for line in lines do + for (line, idx) in lines.zipWithIndex do -- We make this shorter to catch "Adaptation note", "adaptation note" and a missing colon. if line.containsSubstr "daptation note" then - errors := errors.push (StyleError.adaptationNote, lineNumber) - lineNumber := lineNumber + 1 + errors := errors.push (StyleError.adaptationNote, idx + 1) return (errors, none) + +/-- Lint a collection of input strings if one of them contains trailing whitespace. -/ +def trailingWhitespaceLinter : TextbasedLinter := fun lines ↦ Id.run do + let mut errors := Array.mkEmpty 0 + let mut fixedLines := lines + for (line, idx) in lines.zipWithIndex do + if line.back == ' ' then + errors := errors.push (StyleError.trailingWhitespace, idx + 1) + fixedLines := fixedLines.set! idx line.trimRight + return (errors, if errors.size > 0 then some fixedLines else none) + + /-- 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. -/ def isImportsOnlyFile (lines : Array String) : Bool := @@ -215,7 +230,7 @@ end /-- All text-based linters registered in this file. -/ def allLinters : Array TextbasedLinter := #[ - adaptationNoteLinter + adaptationNoteLinter, trailingWhitespaceLinter ] @@ -257,7 +272,6 @@ def lintFile (path : FilePath) (exceptions : Array ErrorContext) : (allOutput.flatten.filter (fun e ↦ (e.find?_comparable exceptions).isNone)) return (errors, if changes_made then some changed else none) - /-- Lint a collection of modules for style violations. Print formatted errors for all unexpected style violations to standard output; correct automatically fixable style errors if configured so. diff --git a/Mathlib/Tactic/Linter/UpstreamableDecl.lean b/Mathlib/Tactic/Linter/UpstreamableDecl.lean index 86f55dc84e8bd..59beda016bc47 100644 --- a/Mathlib/Tactic/Linter/UpstreamableDecl.lean +++ b/Mathlib/Tactic/Linter/UpstreamableDecl.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Damiano Testa, Anne Baanen -/ import ImportGraph.Imports -import Mathlib.Lean.Expr.Basic import Mathlib.Tactic.MinImports /-! # The `upstreamableDecl` linter @@ -21,8 +20,12 @@ def Lean.Name.isLocal (env : Environment) (decl : Name) : Bool := open Mathlib.Command.MinImports -/-- Does the declaration with this name depend on `def`s in the current file? -/ -def Lean.Environment.localDefDependencies (env : Environment) (stx id : Syntax) : +/-- Does the declaration with this name depend on definitions in the current file? + +Here, "definition" means everything that is not a theorem, and so includes `def`, +`structure`, `inductive`, etc. +-/ +def Lean.Environment.localDefinitionDependencies (env : Environment) (stx id : Syntax) : CommandElabM Bool := do let declName : NameSet ← try NameSet.ofList <$> resolveGlobalConst id @@ -37,7 +40,14 @@ def Lean.Environment.localDefDependencies (env : Environment) (stx id : Syntax) let deps ← liftCoreM <| immediateDeps.transitivelyUsedConstants let constInfos := deps.toList.filterMap env.find? - let defs := constInfos.filter (·.isDef) + -- We allow depending on theorems and constructors. + -- We explicitly allow constructors since `inductive` declarations are reported to depend on their + -- own constructors, and we want inductives to behave the same as definitions, so place one + -- warning on the inductive itself but nothing on its downstream uses. + -- (There does not seem to be an easy way to determine, given `Syntax` and `ConstInfo`, + -- whether the `ConstInfo` is a constructor declared in this piece of `Syntax`.) + let defs := constInfos.filter (fun constInfo => !(constInfo.isTheorem || constInfo.isCtor)) + return defs.any fun constInfo => !(declName.contains constInfo.name) && constInfo.name.isLocal env namespace Mathlib.Linter @@ -72,7 +82,7 @@ def upstreamableDeclLinter : Linter where run := withSetOptionIn fun stx ↦ do let minImports := getIrredundantImports env (← getAllImports stx id) match minImports with | ⟨(RBNode.node _ .leaf upstream _ .leaf), _⟩ => do - if !(← env.localDefDependencies stx id) then + if !(← env.localDefinitionDependencies stx id) then let p : GoToModuleLinkProps := { modName := upstream } let widget : MessageData := .ofWidget (← liftCoreM <| Widget.WidgetInstance.ofHash diff --git a/Mathlib/Tactic/Module.lean b/Mathlib/Tactic/Module.lean index 60209e345a89b..14274913e2c77 100644 --- a/Mathlib/Tactic/Module.lean +++ b/Mathlib/Tactic/Module.lean @@ -464,9 +464,9 @@ partial def parse (iM : Q(AddCommMonoid $M)) (x : Q($M)) : pure ⟨0, q(Nat), q(Nat.instSemiring), q(AddCommGroup.toNatModule), [], q(NF.zero_eq_eval $M)⟩ /- anything else should be treated as an atom -/ | _ => - let k : ℕ ← AtomM.addAtom x - pure ⟨0, q(Nat), q(Nat.instSemiring), q(AddCommGroup.toNatModule), [((q(1), x), k)], - q(NF.atom_eq_eval $x)⟩ + let (k, ⟨x', _⟩) ← AtomM.addAtomQ x + pure ⟨0, q(Nat), q(Nat.instSemiring), q(AddCommGroup.toNatModule), [((q(1), x'), k)], + q(NF.atom_eq_eval $x')⟩ /-- Given expressions `R` and `M` representing types such that `M`'s is a module over `R`'s, and given two terms `l₁`, `l₂` of type `qNF R M`, i.e. lists of `(Q($R) × Q($M)) × ℕ`s (two `Expr`s diff --git a/Mathlib/Tactic/Polyrith.lean b/Mathlib/Tactic/Polyrith.lean index 3164aab00a49d..91b368722375e 100644 --- a/Mathlib/Tactic/Polyrith.lean +++ b/Mathlib/Tactic/Polyrith.lean @@ -133,7 +133,7 @@ partial def parse {u : Level} {α : Q(Type u)} (sα : Q(CommSemiring $α)) (c : Ring.Cache sα) (e : Q($α)) : AtomM Poly := do let els := do try pure <| Poly.const (← (← NormNum.derive e).toRat) - catch _ => pure <| Poly.var (← addAtom e) + catch _ => pure <| Poly.var (← addAtom e).1 let .const n _ := (← withReducible <| whnf e).getAppFn | els match n, c.rα with | ``HAdd.hAdd, _ | ``Add.add, _ => match e with diff --git a/Mathlib/Tactic/Positivity.lean b/Mathlib/Tactic/Positivity.lean index 8d76b597bcf25..7b2a24e70ec16 100644 --- a/Mathlib/Tactic/Positivity.lean +++ b/Mathlib/Tactic/Positivity.lean @@ -1,3 +1,4 @@ import Mathlib.Tactic.Positivity.Basic +import Mathlib.Tactic.Positivity.Finset import Mathlib.Tactic.NormNum.Basic import Mathlib.Data.Int.Order.Basic diff --git a/Mathlib/Tactic/Ring/Basic.lean b/Mathlib/Tactic/Ring/Basic.lean index 84faee3f1a0d4..b5dacb13e9ab5 100644 --- a/Mathlib/Tactic/Ring/Basic.lean +++ b/Mathlib/Tactic/Ring/Basic.lean @@ -512,9 +512,8 @@ mutual partial def ExBase.evalNatCast {a : Q(ℕ)} (va : ExBase sℕ a) : AtomM (Result (ExBase sα) q($a)) := match va with | .atom _ => do - let a' : Q($α) := q($a) - let i ← addAtom a' - pure ⟨a', ExBase.atom i, (q(Eq.refl $a') : Expr)⟩ + let (i, ⟨b', _⟩) ← addAtomQ q($a) + pure ⟨b', ExBase.atom i, q(Eq.refl $b')⟩ | .sum va => do let ⟨_, vc, p⟩ ← va.evalNatCast pure ⟨_, .sum vc, p⟩ @@ -952,11 +951,11 @@ Evaluates an atom, an expression where `ring` can find no additional structure. def evalAtom (e : Q($α)) : AtomM (Result (ExSum sα) e) := do let r ← (← read).evalAtom e have e' : Q($α) := r.expr - let i ← addAtom e' - let ve' := (ExBase.atom i (e := e')).toProd (ExProd.mkNat sℕ 1).2 |>.toSum + let (i, ⟨a', _⟩) ← addAtomQ e' + let ve' := (ExBase.atom i (e := a')).toProd (ExProd.mkNat sℕ 1).2 |>.toSum pure ⟨_, ve', match r.proof? with | none => (q(atom_pf $e) : Expr) - | some (p : Q($e = $e')) => (q(atom_pf' $p) : Expr)⟩ + | some (p : Q($e = $a')) => (q(atom_pf' $p) : Expr)⟩ theorem inv_mul {R} [DivisionRing R] {a₁ a₂ a₃ b₁ b₃ c} (_ : (a₁⁻¹ : R) = b₁) (_ : (a₃⁻¹ : R) = b₃) @@ -977,9 +976,8 @@ variable (dα : Q(DivisionRing $α)) /-- Applies `⁻¹` to a polynomial to get an atom. -/ def evalInvAtom (a : Q($α)) : AtomM (Result (ExBase sα) q($a⁻¹)) := do - let a' : Q($α) := q($a⁻¹) - let i ← addAtom a' - pure ⟨a', ExBase.atom i, (q(Eq.refl $a') : Expr)⟩ + let (i, ⟨b', _⟩) ← addAtomQ q($a⁻¹) + pure ⟨b', ExBase.atom i, q(Eq.refl $b')⟩ /-- Inverts a polynomial `va` to get a normalized result polynomial. diff --git a/Mathlib/Tactic/Sat/FromLRAT.lean b/Mathlib/Tactic/Sat/FromLRAT.lean index c1962b10c84a8..db7f18cb54a91 100644 --- a/Mathlib/Tactic/Sat/FromLRAT.lean +++ b/Mathlib/Tactic/Sat/FromLRAT.lean @@ -3,7 +3,8 @@ Copyright (c) 2022 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ -import Mathlib.Algebra.Group.Nat +import Mathlib.Algebra.Group.Nat.Basic +import Mathlib.Tactic.ByContra /-! # `lrat_proof` command diff --git a/Mathlib/Tactic/TFAE.lean b/Mathlib/Tactic/TFAE.lean index 45405bfe5ad58..ac5f1114a8529 100644 --- a/Mathlib/Tactic/TFAE.lean +++ b/Mathlib/Tactic/TFAE.lean @@ -298,18 +298,18 @@ elab_rules : tactic goal.withContext do let (tfaeListQ, tfaeList) ← getTFAEList (← goal.getType) closeMainGoal `tfae_finish <|← AtomM.run .reducible do - let is ← tfaeList.mapM AtomM.addAtom + let is ← tfaeList.mapM (fun e ↦ Prod.fst <$> AtomM.addAtom e) let mut hyps := #[] for hyp in ← getLocalHyps do let ty ← whnfR <|← instantiateMVars <|← inferType hyp if let (``Iff, #[p1, p2]) := ty.getAppFnArgs then - let q1 ← AtomM.addAtom p1 - let q2 ← AtomM.addAtom p2 + let (q1, _) ← AtomM.addAtom p1 + let (q2, _) ← AtomM.addAtom p2 hyps := hyps.push (q1, q2, ← mkAppM ``Iff.mp #[hyp]) hyps := hyps.push (q2, q1, ← mkAppM ``Iff.mpr #[hyp]) else if ty.isArrow then - let q1 ← AtomM.addAtom ty.bindingDomain! - let q2 ← AtomM.addAtom ty.bindingBody! + let (q1, _) ← AtomM.addAtom ty.bindingDomain! + let (q2, _) ← AtomM.addAtom ty.bindingBody! hyps := hyps.push (q1, q2, hyp) proveTFAE hyps (← get).atoms is tfaeListQ diff --git a/Mathlib/Tactic/WLOG.lean b/Mathlib/Tactic/WLOG.lean index 461949d04ab7b..cad9a19bf5bfd 100644 --- a/Mathlib/Tactic/WLOG.lean +++ b/Mathlib/Tactic/WLOG.lean @@ -77,7 +77,8 @@ def _root_.Lean.MVarId.wlog (goal : MVarId) (h : Option Name) (P : Expr) let (revertedFVars, HType) ← liftMkBindingM fun ctx => (do let f ← collectForwardDeps lctx fvars let revertedFVars := filterOutImplementationDetails lctx (f.map Expr.fvarId!) - let HType ← withFreshCache do mkAuxMVarType lctx (revertedFVars.map Expr.fvar) .natural HSuffix + let HType ← withFreshCache do + mkAuxMVarType lctx (revertedFVars.map Expr.fvar) .natural HSuffix (usedLetOnly := true) return (revertedFVars, HType)) { preserveOrder := false, mainModule := ctx.mainModule } /- Set up the goal which will suppose `h`; this begins as a goal with type H (hence HExpr), and h diff --git a/Mathlib/Testing/Plausible/Functions.lean b/Mathlib/Testing/Plausible/Functions.lean index 080db229f9115..ba4209766edf6 100644 --- a/Mathlib/Testing/Plausible/Functions.lean +++ b/Mathlib/Testing/Plausible/Functions.lean @@ -40,9 +40,9 @@ their defining property is invariant through shrinking. Injective functions are an example of how complicated it can get. -/ -universe u v w +universe u v -variable {α : Type u} {β : Type v} {γ : Sort w} +variable {α : Type u} {β : Type v} namespace Plausible diff --git a/Mathlib/Topology/Algebra/ConstMulAction.lean b/Mathlib/Topology/Algebra/ConstMulAction.lean index 1da40dadc219d..10007257a47c5 100644 --- a/Mathlib/Topology/Algebra/ConstMulAction.lean +++ b/Mathlib/Topology/Algebra/ConstMulAction.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Alex Kontorovich, Heather Macbeth -/ import Mathlib.Algebra.Module.ULift +import Mathlib.Algebra.Order.Group.Synonym import Mathlib.Data.Set.Pointwise.SMul import Mathlib.GroupTheory.GroupAction.Defs import Mathlib.Topology.Algebra.Constructions @@ -266,7 +267,7 @@ theorem smul_mem_nhds_smul_iff {t : Set α} (g : G) {a : α} : g • t ∈ 𝓝 @[to_additive] alias ⟨_, smul_mem_nhds_smul⟩ := smul_mem_nhds_smul_iff -@[to_additive (attr := deprecated (since := "2024-08-06"))] +@[to_additive (attr := deprecated "No deprecation message was provided." (since := "2024-08-06"))] alias smul_mem_nhds := smul_mem_nhds_smul @[to_additive (attr := simp)] diff --git a/Mathlib/Topology/Algebra/ContinuousMonoidHom.lean b/Mathlib/Topology/Algebra/ContinuousMonoidHom.lean index 91b1a4ca3bcd4..f7373a1da6da0 100644 --- a/Mathlib/Topology/Algebra/ContinuousMonoidHom.lean +++ b/Mathlib/Topology/Algebra/ContinuousMonoidHom.lean @@ -65,7 +65,8 @@ homomorphisms. Deprecated and changed from a `class` to a `structure`. Use `[MonoidHomClass F A B] [ContinuousMapClass F A B]` instead. -/ -@[to_additive (attr := deprecated (since := "2024-10-08"))] +@[to_additive (attr := deprecated "Use `[MonoidHomClass F A B] [ContinuousMapClass F A B]` instead." + (since := "2024-10-08"))] structure ContinuousMonoidHomClass (A B : outParam Type*) [Monoid A] [Monoid B] [TopologicalSpace A] [TopologicalSpace B] [FunLike F A B] extends MonoidHomClass F A B, ContinuousMapClass F A B : Prop diff --git a/Mathlib/Topology/Algebra/Field.lean b/Mathlib/Topology/Algebra/Field.lean index 48b1183bc9f01..cc34c6223561e 100644 --- a/Mathlib/Topology/Algebra/Field.lean +++ b/Mathlib/Topology/Algebra/Field.lean @@ -5,6 +5,7 @@ Authors: Patrick Massot, Kim Morrison -/ import Mathlib.Algebra.Field.Subfield.Basic import Mathlib.Algebra.GroupWithZero.Divisibility +import Mathlib.Algebra.Order.Group.Pointwise.Interval import Mathlib.Topology.Algebra.GroupWithZero import Mathlib.Topology.Algebra.Ring.Basic import Mathlib.Topology.Order.LocalExtr @@ -91,6 +92,26 @@ def affineHomeomorph (a b : 𝕜) (h : a ≠ 0) : 𝕜 ≃ₜ 𝕜 where exact mul_div_cancel_left₀ x h right_inv y := by simp [mul_div_cancel₀ _ h] +theorem affineHomeomorph_image_Icc {𝕜 : Type*} [LinearOrderedField 𝕜] [TopologicalSpace 𝕜] + [TopologicalRing 𝕜] (a b c d : 𝕜) (h : 0 < a) : + affineHomeomorph a b h.ne' '' Set.Icc c d = Set.Icc (a * c + b) (a * d + b) := by + simp [h] + +theorem affineHomeomorph_image_Ico {𝕜 : Type*} [LinearOrderedField 𝕜] [TopologicalSpace 𝕜] + [TopologicalRing 𝕜] (a b c d : 𝕜) (h : 0 < a) : + affineHomeomorph a b h.ne' '' Set.Ico c d = Set.Ico (a * c + b) (a * d + b) := by + simp [h] + +theorem affineHomeomorph_image_Ioc {𝕜 : Type*} [LinearOrderedField 𝕜] [TopologicalSpace 𝕜] + [TopologicalRing 𝕜] (a b c d : 𝕜) (h : 0 < a) : + affineHomeomorph a b h.ne' '' Set.Ioc c d = Set.Ioc (a * c + b) (a * d + b) := by + simp [h] + +theorem affineHomeomorph_image_Ioo {𝕜 : Type*} [LinearOrderedField 𝕜] [TopologicalSpace 𝕜] + [TopologicalRing 𝕜] (a b c d : 𝕜) (h : 0 < a) : + affineHomeomorph a b h.ne' '' Set.Ioo c d = Set.Ioo (a * c + b) (a * d + b) := by + simp [h] + end affineHomeomorph section LocalExtr diff --git a/Mathlib/Topology/Algebra/Group/Quotient.lean b/Mathlib/Topology/Algebra/Group/Quotient.lean index 4a2b490786409..e46af523bf2ca 100644 --- a/Mathlib/Topology/Algebra/Group/Quotient.lean +++ b/Mathlib/Topology/Algebra/Group/Quotient.lean @@ -76,7 +76,7 @@ instance instLocallyCompactSpace [LocallyCompactSpace G] (N : Subgroup G) : LocallyCompactSpace (G ⧸ N) := QuotientGroup.isOpenQuotientMap_mk.locallyCompactSpace -@[to_additive (attr := deprecated (since := "2024-10-05"))] +@[to_additive (attr := deprecated "No deprecation message was provided." (since := "2024-10-05"))] theorem continuous_smul₁ (x : G ⧸ N) : Continuous fun g : G => g • x := continuous_id.smul continuous_const @@ -101,7 +101,7 @@ instance instSecondCountableTopology [SecondCountableTopology G] : SecondCountableTopology (G ⧸ N) := ContinuousConstSMul.secondCountableTopology -@[to_additive (attr := deprecated (since := "2024-08-05"))] +@[to_additive (attr := deprecated "No deprecation message was provided." (since := "2024-08-05"))] theorem nhds_one_isCountablyGenerated [FirstCountableTopology G] [N.Normal] : (𝓝 (1 : G ⧸ N)).IsCountablyGenerated := inferInstance @@ -117,7 +117,7 @@ instance instTopologicalGroup [N.Normal] : TopologicalGroup (G ⧸ N) where exact continuous_mk.comp continuous_mul continuous_inv := continuous_inv.quotient_map' _ -@[to_additive (attr := deprecated (since := "2024-08-05"))] +@[to_additive (attr := deprecated "No deprecation message was provided." (since := "2024-08-05"))] theorem _root_.topologicalGroup_quotient [N.Normal] : TopologicalGroup (G ⧸ N) := instTopologicalGroup N diff --git a/Mathlib/Topology/Algebra/InfiniteSum/Basic.lean b/Mathlib/Topology/Algebra/InfiniteSum/Basic.lean index 74529c1335d72..ba49c204bab72 100644 --- a/Mathlib/Topology/Algebra/InfiniteSum/Basic.lean +++ b/Mathlib/Topology/Algebra/InfiniteSum/Basic.lean @@ -21,12 +21,12 @@ noncomputable section open Filter Finset Function Topology -variable {α β γ δ : Type*} +variable {α β γ : Type*} section HasProd variable [CommMonoid α] [TopologicalSpace α] -variable {f g : β → α} {a b : α} {s : Finset β} +variable {f g : β → α} {a b : α} /-- Constant one function has product `1` -/ @[to_additive "Constant zero function has sum `0`"] @@ -355,7 +355,7 @@ end HasProd section tprod -variable [CommMonoid α] [TopologicalSpace α] {f g : β → α} {a a₁ a₂ : α} +variable [CommMonoid α] [TopologicalSpace α] {f g : β → α} @[to_additive] theorem tprod_congr_set_coe (f : β → α) {s t : Set β} (h : s = t) : diff --git a/Mathlib/Topology/Algebra/InfiniteSum/Constructions.lean b/Mathlib/Topology/Algebra/InfiniteSum/Constructions.lean index 47d09ed95c689..4386fe90f6bd1 100644 --- a/Mathlib/Topology/Algebra/InfiniteSum/Constructions.lean +++ b/Mathlib/Topology/Algebra/InfiniteSum/Constructions.lean @@ -20,7 +20,7 @@ open Filter Finset Function open scoped Topology -variable {α β γ δ : Type*} +variable {α β γ : Type*} /-! ## Product, Sigma and Pi types -/ @@ -192,6 +192,11 @@ theorem Multipliable.prod_factor {f : β × γ → α} (h : Multipliable f) (b : Multipliable fun c ↦ f (b, c) := h.comp_injective fun _ _ h ↦ (Prod.ext_iff.1 h).2 +@[to_additive Summable.prod] +lemma Multipliable.prod {f : β × γ → α} (h : Multipliable f) : + Multipliable fun b ↦ ∏' c, f (b, c) := + ((Equiv.sigmaEquivProd β γ).multipliable_iff.mpr h).sigma + @[to_additive] lemma HasProd.tprod_fiberwise [T2Space α] {f : β → α} {a : α} (hf : HasProd f a) (g : β → γ) : HasProd (fun c : γ ↦ ∏' b : g ⁻¹' {c}, f b) a := diff --git a/Mathlib/Topology/Algebra/InfiniteSum/Defs.lean b/Mathlib/Topology/Algebra/InfiniteSum/Defs.lean index 2bf685cd201e1..cc83507487809 100644 --- a/Mathlib/Topology/Algebra/InfiniteSum/Defs.lean +++ b/Mathlib/Topology/Algebra/InfiniteSum/Defs.lean @@ -111,7 +111,7 @@ notation3 "∏' "(...)", "r:67:(scoped f => tprod f) => r @[inherit_doc tsum] notation3 "∑' "(...)", "r:67:(scoped f => tsum f) => r -variable {f g : β → α} {a b : α} {s : Finset β} +variable {f : β → α} {a : α} {s : Finset β} @[to_additive] theorem HasProd.multipliable (h : HasProd f a) : Multipliable f := diff --git a/Mathlib/Topology/Algebra/InfiniteSum/Group.lean b/Mathlib/Topology/Algebra/InfiniteSum/Group.lean index 4c5353916aae3..937a415544928 100644 --- a/Mathlib/Topology/Algebra/InfiniteSum/Group.lean +++ b/Mathlib/Topology/Algebra/InfiniteSum/Group.lean @@ -20,7 +20,7 @@ open Filter Finset Function open scoped Topology -variable {α β γ δ : Type*} +variable {α β γ : Type*} section TopologicalGroup @@ -197,7 +197,7 @@ theorem multipliable_iff_cauchySeq_finset [CompleteSpace α] {f : β → α} : Multipliable f ↔ CauchySeq fun s : Finset β ↦ ∏ b ∈ s, f b := by classical exact cauchy_map_iff_exists_tendsto.symm -variable [UniformGroup α] {f g : β → α} {a a₁ a₂ : α} +variable [UniformGroup α] {f g : β → α} @[to_additive] theorem cauchySeq_finset_iff_prod_vanishing : diff --git a/Mathlib/Topology/Algebra/InfiniteSum/Ring.lean b/Mathlib/Topology/Algebra/InfiniteSum/Ring.lean index ea55550f54743..aa0cdf8f9a57d 100644 --- a/Mathlib/Topology/Algebra/InfiniteSum/Ring.lean +++ b/Mathlib/Topology/Algebra/InfiniteSum/Ring.lean @@ -19,12 +19,12 @@ This file provides lemmas about the interaction between infinite sums and multip open Filter Finset Function -variable {ι κ R α : Type*} +variable {ι κ α : Type*} section NonUnitalNonAssocSemiring -variable [NonUnitalNonAssocSemiring α] [TopologicalSpace α] [TopologicalSemiring α] {f g : ι → α} - {a a₁ a₂ : α} +variable [NonUnitalNonAssocSemiring α] [TopologicalSpace α] [TopologicalSemiring α] {f : ι → α} + {a₁ : α} theorem HasSum.mul_left (a₂) (h : HasSum f a₁) : HasSum (fun i ↦ a₂ * f i) (a₂ * a₁) := by simpa only using h.map (AddMonoidHom.mulLeft a₂) (continuous_const.mul continuous_id) @@ -63,8 +63,7 @@ end NonUnitalNonAssocSemiring section DivisionSemiring -variable [DivisionSemiring α] [TopologicalSpace α] [TopologicalSemiring α] {f g : ι → α} - {a a₁ a₂ : α} +variable [DivisionSemiring α] [TopologicalSpace α] [TopologicalSemiring α] {f : ι → α} {a a₁ a₂ : α} theorem HasSum.div_const (h : HasSum f a) (b : α) : HasSum (fun i ↦ f i / b) (a / b) := by simp only [div_eq_mul_inv, h.mul_right b⁻¹] diff --git a/Mathlib/Topology/Algebra/Order/Field.lean b/Mathlib/Topology/Algebra/Order/Field.lean index 51f7585e7e00c..29f1d4890fd66 100644 --- a/Mathlib/Topology/Algebra/Order/Field.lean +++ b/Mathlib/Topology/Algebra/Order/Field.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 Benjamin Davidson. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Benjamin Davidson, Devon Tuma, Eric Rodriguez, Oliver Nash -/ -import Mathlib.Data.Set.Pointwise.Interval +import Mathlib.Algebra.Order.Group.Pointwise.Interval import Mathlib.Order.Filter.AtTopBot.Field import Mathlib.Topology.Algebra.Field import Mathlib.Topology.Algebra.Order.Group @@ -114,7 +114,7 @@ theorem Filter.Tendsto.neg_mul_atBot {C : 𝕜} (hC : C < 0) (hf : Tendsto f l ( @[simp] lemma inv_atTop₀ : (atTop : Filter 𝕜)⁻¹ = 𝓝[>] 0 := (((atTop_basis_Ioi' (0 : 𝕜)).map _).comp_surjective inv_surjective).eq_of_same_basis <| - (nhdsWithin_Ioi_basis _).congr (by simp) fun a ha ↦ by simp [inv_Ioi (inv_pos.2 ha)] + (nhdsWithin_Ioi_basis _).congr (by simp) fun a ha ↦ by simp [inv_Ioi₀ (inv_pos.2 ha)] @[simp] lemma inv_nhdsWithin_Ioi_zero : (𝓝[>] (0 : 𝕜))⁻¹ = atTop := by rw [← inv_atTop₀, inv_inv] diff --git a/Mathlib/Topology/Algebra/Order/LiminfLimsup.lean b/Mathlib/Topology/Algebra/Order/LiminfLimsup.lean index 44fe760b02479..9f2b202d56789 100644 --- a/Mathlib/Topology/Algebra/Order/LiminfLimsup.lean +++ b/Mathlib/Topology/Algebra/Order/LiminfLimsup.lean @@ -130,20 +130,18 @@ instance (priority := 100) OrderTop.to_BoundedLENhdsClass [OrderTop α] : Bounde instance (priority := 100) OrderBot.to_BoundedGENhdsClass [OrderBot α] : BoundedGENhdsClass α := ⟨fun _a ↦ isBounded_ge_of_bot⟩ --- See note [lower instance priority] -instance (priority := 100) OrderTopology.to_BoundedLENhdsClass [IsDirected α (· ≤ ·)] - [OrderTopology α] : BoundedLENhdsClass α := - ⟨fun a ↦ - ((isTop_or_exists_gt a).elim fun h ↦ ⟨a, Eventually.of_forall h⟩) <| - Exists.imp fun _b ↦ ge_mem_nhds⟩ +end Preorder -- See note [lower instance priority] -instance (priority := 100) OrderTopology.to_BoundedGENhdsClass [IsDirected α (· ≥ ·)] - [OrderTopology α] : BoundedGENhdsClass α := - ⟨fun a ↦ ((isBot_or_exists_lt a).elim fun h ↦ ⟨a, Eventually.of_forall h⟩) <| - Exists.imp fun _b ↦ le_mem_nhds⟩ +instance (priority := 100) BoundedLENhdsClass.of_closedIciTopology [LinearOrder α] + [TopologicalSpace α] [ClosedIciTopology α] : BoundedLENhdsClass α := + ⟨fun a ↦ ((isTop_or_exists_gt a).elim fun h ↦ ⟨a, Eventually.of_forall h⟩) <| + Exists.imp fun _b ↦ eventually_le_nhds⟩ -end Preorder +-- See note [lower instance priority] +instance (priority := 100) BoundedGENhdsClass.of_closedIicTopology [LinearOrder α] + [TopologicalSpace α] [ClosedIicTopology α] : BoundedGENhdsClass α := + inferInstanceAs <| BoundedGENhdsClass αᵒᵈᵒᵈ section LiminfLimsup @@ -411,43 +409,6 @@ theorem Monotone.map_liminf_of_continuousAt {f : R → S} (f_incr : Monotone f) end Monotone -section InfiAndSupr - -open Topology - -open Filter Set - -variable [CompleteLinearOrder R] [TopologicalSpace R] [OrderTopology R] - -theorem iInf_eq_of_forall_le_of_tendsto {x : R} {as : ι → R} (x_le : ∀ i, x ≤ as i) {F : Filter ι} - [Filter.NeBot F] (as_lim : Filter.Tendsto as F (𝓝 x)) : ⨅ i, as i = x := by - refine iInf_eq_of_forall_ge_of_forall_gt_exists_lt (fun i ↦ x_le i) ?_ - apply fun w x_lt_w ↦ ‹Filter.NeBot F›.nonempty_of_mem (eventually_lt_of_tendsto_lt x_lt_w as_lim) - -theorem iSup_eq_of_forall_le_of_tendsto {x : R} {as : ι → R} (le_x : ∀ i, as i ≤ x) {F : Filter ι} - [Filter.NeBot F] (as_lim : Filter.Tendsto as F (𝓝 x)) : ⨆ i, as i = x := - iInf_eq_of_forall_le_of_tendsto (R := Rᵒᵈ) le_x as_lim - -theorem iUnion_Ici_eq_Ioi_of_lt_of_tendsto (x : R) {as : ι → R} (x_lt : ∀ i, x < as i) - {F : Filter ι} [Filter.NeBot F] (as_lim : Filter.Tendsto as F (𝓝 x)) : - ⋃ i : ι, Ici (as i) = Ioi x := by - have obs : x ∉ range as := by - intro maybe_x_is - rcases mem_range.mp maybe_x_is with ⟨i, hi⟩ - simpa only [hi, lt_self_iff_false] using x_lt i - -- Porting note: `rw at *` was too destructive. Let's only rewrite `obs` and the goal. - have := iInf_eq_of_forall_le_of_tendsto (fun i ↦ (x_lt i).le) as_lim - rw [← this] at obs - rw [← this] - exact iUnion_Ici_eq_Ioi_iInf obs - -theorem iUnion_Iic_eq_Iio_of_lt_of_tendsto (x : R) {as : ι → R} (lt_x : ∀ i, as i < x) - {F : Filter ι} [Filter.NeBot F] (as_lim : Filter.Tendsto as F (𝓝 x)) : - ⋃ i : ι, Iic (as i) = Iio x := - iUnion_Ici_eq_Ioi_of_lt_of_tendsto (R := Rᵒᵈ) x lt_x as_lim - -end InfiAndSupr - section Indicator theorem limsup_eq_tendsto_sum_indicator_nat_atTop (s : ℕ → Set α) : diff --git a/Mathlib/Topology/Bornology/Basic.lean b/Mathlib/Topology/Bornology/Basic.lean index 6b8a44d2bdedf..e8de59a17b369 100644 --- a/Mathlib/Topology/Bornology/Basic.lean +++ b/Mathlib/Topology/Bornology/Basic.lean @@ -261,7 +261,7 @@ open Bornology theorem Filter.HasBasis.disjoint_cobounded_iff [Bornology α] {ι : Sort*} {p : ι → Prop} {s : ι → Set α} {l : Filter α} (h : l.HasBasis p s) : - Disjoint l (cobounded α) ↔ ∃ i, p i ∧ IsBounded (s i) := + Disjoint l (cobounded α) ↔ ∃ i, p i ∧ Bornology.IsBounded (s i) := h.disjoint_iff_left theorem Set.Finite.isBounded [Bornology α] {s : Set α} (hs : s.Finite) : IsBounded s := diff --git a/Mathlib/Topology/Category/LightProfinite/Basic.lean b/Mathlib/Topology/Category/LightProfinite/Basic.lean index 362a23b4df054..bd67bbffa19ea 100644 --- a/Mathlib/Topology/Category/LightProfinite/Basic.lean +++ b/Mathlib/Topology/Category/LightProfinite/Basic.lean @@ -297,10 +297,11 @@ instance instCountableDiscreteQuotient (S : LightProfinite) : /-- A profinite space which is light gives rise to a light profinite space. -/ noncomputable def toLightDiagram (S : LightProfinite.{u}) : LightDiagram.{u} where - diagram := sequentialFunctor _ ⋙ (lightToProfinite.obj S).fintypeDiagram - cone := (Functor.Initial.limitConeComp (sequentialFunctor _) (lightToProfinite.obj S).lim).cone - isLimit := - (Functor.Initial.limitConeComp (sequentialFunctor _) (lightToProfinite.obj S).lim).isLimit + diagram := IsCofiltered.sequentialFunctor _ ⋙ (lightToProfinite.obj S).fintypeDiagram + cone := (Functor.Initial.limitConeComp (IsCofiltered.sequentialFunctor _) + (lightToProfinite.obj S).lim).cone + isLimit := (Functor.Initial.limitConeComp (IsCofiltered.sequentialFunctor _) + (lightToProfinite.obj S).lim).isLimit end LightProfinite diff --git a/Mathlib/Topology/Constructions.lean b/Mathlib/Topology/Constructions.lean index 7d92b1e682ec5..280967dfdc29d 100644 --- a/Mathlib/Topology/Constructions.lean +++ b/Mathlib/Topology/Constructions.lean @@ -115,9 +115,9 @@ theorem nhds_ofMul (x : X) : 𝓝 (ofMul x) = map ofMul (𝓝 x) := rfl theorem nhds_ofAdd (x : X) : 𝓝 (ofAdd x) = map ofAdd (𝓝 x) := rfl -theorem nhds_toMul (x : Additive X) : 𝓝 (toMul x) = map toMul (𝓝 x) := rfl +theorem nhds_toMul (x : Additive X) : 𝓝 x.toMul = map toMul (𝓝 x) := rfl -theorem nhds_toAdd (x : Multiplicative X) : 𝓝 (toAdd x) = map toAdd (𝓝 x) := rfl +theorem nhds_toAdd (x : Multiplicative X) : 𝓝 x.toAdd = map toAdd (𝓝 x) := rfl end diff --git a/Mathlib/Topology/ContinuousMap/Ordered.lean b/Mathlib/Topology/ContinuousMap/Ordered.lean index 5ef9876bb5f8c..7677b1c20ea56 100644 --- a/Mathlib/Topology/ContinuousMap/Ordered.lean +++ b/Mathlib/Topology/ContinuousMap/Ordered.lean @@ -13,8 +13,7 @@ import Mathlib.Topology.ContinuousMap.Defs -/ -variable {α : Type*} {β : Type*} {γ : Type*} -variable [TopologicalSpace α] [TopologicalSpace β] [TopologicalSpace γ] +variable {α β : Type*} [TopologicalSpace α] [TopologicalSpace β] namespace ContinuousMap diff --git a/Mathlib/Topology/EMetricSpace/Defs.lean b/Mathlib/Topology/EMetricSpace/Defs.lean index 445f6803e42d1..b791062fbf650 100644 --- a/Mathlib/Topology/EMetricSpace/Defs.lean +++ b/Mathlib/Topology/EMetricSpace/Defs.lean @@ -657,11 +657,11 @@ theorem edist_ofAdd (a b : X) : edist (ofAdd a) (ofAdd b) = edist a b := rfl @[simp] -theorem edist_toMul (a b : Additive X) : edist (toMul a) (toMul b) = edist a b := +theorem edist_toMul (a b : Additive X) : edist a.toMul b.toMul = edist a b := rfl @[simp] -theorem edist_toAdd (a b : Multiplicative X) : edist (toAdd a) (toAdd b) = edist a b := +theorem edist_toAdd (a b : Multiplicative X) : edist a.toAdd b.toAdd = edist a b := rfl end diff --git a/Mathlib/Topology/Gluing.lean b/Mathlib/Topology/Gluing.lean index c5385f98801ee..6c4f75721330d 100644 --- a/Mathlib/Topology/Gluing.lean +++ b/Mathlib/Topology/Gluing.lean @@ -83,7 +83,7 @@ Most of the times it would be easier to use the constructor `TopCat.GlueData.mk' conditions are stated in a less categorical way. -/ -- Porting note (https://github.com/leanprover-community/mathlib4/issues/5171): removed @[nolint has_nonempty_instance] -structure GlueData extends GlueData TopCat where +structure GlueData extends CategoryTheory.GlueData TopCat where f_open : ∀ i j, IsOpenEmbedding (f i j) f_mono i j := (TopCat.mono_iff_injective _).mpr (f_open i j).isEmbedding.injective diff --git a/Mathlib/Topology/Instances/ENNReal.lean b/Mathlib/Topology/Instances/ENNReal.lean index 94b73607b7f71..029ada7f6a78a 100644 --- a/Mathlib/Topology/Instances/ENNReal.lean +++ b/Mathlib/Topology/Instances/ENNReal.lean @@ -25,7 +25,7 @@ variable {α : Type*} {β : Type*} {γ : Type*} namespace ENNReal -variable {a b c d : ℝ≥0∞} {r p q : ℝ≥0} {x y z : ℝ≥0∞} {ε ε₁ ε₂ : ℝ≥0∞} {s : Set ℝ≥0∞} +variable {a b : ℝ≥0∞} {r : ℝ≥0} {x : ℝ≥0∞} {ε : ℝ≥0∞} section TopologicalSpace diff --git a/Mathlib/Topology/List.lean b/Mathlib/Topology/List.lean index 0620deab85315..4ca0d9581282a 100644 --- a/Mathlib/Topology/List.lean +++ b/Mathlib/Topology/List.lean @@ -184,16 +184,16 @@ open List open Mathlib (Vector) -instance (n : ℕ) : TopologicalSpace (Vector α n) := by unfold Vector; infer_instance +instance (n : ℕ) : TopologicalSpace (Mathlib.Vector α n) := by unfold Mathlib.Vector; infer_instance -theorem tendsto_cons {n : ℕ} {a : α} {l : Vector α n} : - Tendsto (fun p : α × Vector α n => p.1 ::ᵥ p.2) (𝓝 a ×ˢ 𝓝 l) (𝓝 (a ::ᵥ l)) := by +theorem tendsto_cons {n : ℕ} {a : α} {l : Mathlib.Vector α n} : + Tendsto (fun p : α × Mathlib.Vector α n => p.1 ::ᵥ p.2) (𝓝 a ×ˢ 𝓝 l) (𝓝 (a ::ᵥ l)) := by rw [tendsto_subtype_rng, Vector.cons_val] exact tendsto_fst.cons (Tendsto.comp continuousAt_subtype_val tendsto_snd) theorem tendsto_insertIdx {n : ℕ} {i : Fin (n + 1)} {a : α} : - ∀ {l : Vector α n}, - Tendsto (fun p : α × Vector α n => Vector.insertIdx p.1 i p.2) (𝓝 a ×ˢ 𝓝 l) + ∀ {l : Mathlib.Vector α n}, + Tendsto (fun p : α × Mathlib.Vector α n => Vector.insertIdx p.1 i p.2) (𝓝 a ×ˢ 𝓝 l) (𝓝 (Vector.insertIdx a i l)) | ⟨l, hl⟩ => by rw [Vector.insertIdx, tendsto_subtype_rng] @@ -204,29 +204,29 @@ theorem tendsto_insertIdx {n : ℕ} {i : Fin (n + 1)} {a : α} : /-- Continuity of `Vector.insertIdx`. -/ theorem continuous_insertIdx' {n : ℕ} {i : Fin (n + 1)} : - Continuous fun p : α × Vector α n => Vector.insertIdx p.1 i p.2 := + Continuous fun p : α × Mathlib.Vector α n => Vector.insertIdx p.1 i p.2 := continuous_iff_continuousAt.mpr fun ⟨a, l⟩ => by rw [ContinuousAt, nhds_prod_eq]; exact tendsto_insertIdx @[deprecated (since := "2024-10-21")] alias continuous_insertNth' := continuous_insertIdx' -theorem continuous_insertIdx {n : ℕ} {i : Fin (n + 1)} {f : β → α} {g : β → Vector α n} +theorem continuous_insertIdx {n : ℕ} {i : Fin (n + 1)} {f : β → α} {g : β → Mathlib.Vector α n} (hf : Continuous f) (hg : Continuous g) : Continuous fun b => Vector.insertIdx (f b) i (g b) := continuous_insertIdx'.comp (hf.prod_mk hg : _) @[deprecated (since := "2024-10-21")] alias continuous_insertNth := continuous_insertIdx theorem continuousAt_eraseIdx {n : ℕ} {i : Fin (n + 1)} : - ∀ {l : Vector α (n + 1)}, ContinuousAt (Vector.eraseIdx i) l + ∀ {l : Mathlib.Vector α (n + 1)}, ContinuousAt (Mathlib.Vector.eraseIdx i) l | ⟨l, hl⟩ => by - rw [ContinuousAt, Vector.eraseIdx, tendsto_subtype_rng] + rw [ContinuousAt, Mathlib.Vector.eraseIdx, tendsto_subtype_rng] simp only [Vector.eraseIdx_val] exact Tendsto.comp List.tendsto_eraseIdx continuousAt_subtype_val @[deprecated (since := "2024-05-04")] alias continuousAt_removeNth := continuousAt_eraseIdx theorem continuous_eraseIdx {n : ℕ} {i : Fin (n + 1)} : - Continuous (Vector.eraseIdx i : Vector α (n + 1) → Vector α n) := + Continuous (Mathlib.Vector.eraseIdx i : Mathlib.Vector α (n + 1) → Mathlib.Vector α n) := continuous_iff_continuousAt.mpr fun ⟨_a, _l⟩ => continuousAt_eraseIdx @[deprecated (since := "2024-05-04")] alias continuous_removeNth := continuous_eraseIdx diff --git a/Mathlib/Topology/LocalAtTarget.lean b/Mathlib/Topology/LocalAtTarget.lean index 9d801889f8176..af16705f2ce51 100644 --- a/Mathlib/Topology/LocalAtTarget.lean +++ b/Mathlib/Topology/LocalAtTarget.lean @@ -82,7 +82,7 @@ theorem IsClosedMap.restrictPreimage (H : IsClosedMap f) (s : Set β) : simpa [isClosed_induced_iff] exact fun u hu e => ⟨f '' u, H u hu, by simp [← e, image_restrictPreimage]⟩ -@[deprecated (since := "2024-04-02")] +@[deprecated "No deprecation message was provided." (since := "2024-04-02")] theorem Set.restrictPreimage_isClosedMap (s : Set β) (H : IsClosedMap f) : IsClosedMap (s.restrictPreimage f) := H.restrictPreimage s @@ -94,7 +94,7 @@ theorem IsOpenMap.restrictPreimage (H : IsOpenMap f) (s : Set β) : simpa [isOpen_induced_iff] exact fun u hu e => ⟨f '' u, H u hu, by simp [← e, image_restrictPreimage]⟩ -@[deprecated (since := "2024-04-02")] +@[deprecated "No deprecation message was provided." (since := "2024-04-02")] theorem Set.restrictPreimage_isOpenMap (s : Set β) (H : IsOpenMap f) : IsOpenMap (s.restrictPreimage f) := H.restrictPreimage s @@ -185,6 +185,47 @@ theorem isEmbedding_iff_of_iSup_eq_top (h : Continuous f) : convert congr_arg SetLike.coe hU simp +omit hU in +/-- +Given a continuous map `f : X → Y` between topological spaces. +Suppose we have an open cover `V i` of the range of `f`, and an open cover `U i` of `X` that is +coarser than the pullback of `V` under `f`. +To check that `f` is an embedding it suffices to check that `U i → Y` is an embedding for all `i`. +-/ +theorem isEmbedding_of_iSup_eq_top_of_preimage_subset_range + {X Y} [TopologicalSpace X] [TopologicalSpace Y] + (f : X → Y) (h : Continuous f) {ι : Type*} + (U : ι → Opens Y) (hU : Set.range f ⊆ (iSup U : _)) + (V : ι → Type*) [∀ i, TopologicalSpace (V i)] + (iV : ∀ i, V i → X) (hiV : ∀ i, Continuous (iV i)) (hV : ∀ i, f ⁻¹' U i ⊆ Set.range (iV i)) + (hV' : ∀ i, IsEmbedding (f ∘ iV i)) : IsEmbedding f := by + wlog hU' : iSup U = ⊤ + · let f₀ : X → Set.range f := fun x ↦ ⟨f x, ⟨x, rfl⟩⟩ + suffices IsEmbedding f₀ from IsEmbedding.subtypeVal.comp this + have hU'' : (⨆ i, (U i).comap ⟨Subtype.val, continuous_subtype_val⟩ : + Opens (Set.range f)) = ⊤ := by + rw [← top_le_iff] + simpa [Set.range_subset_iff, SetLike.le_def] using hU + refine this _ ?_ _ ?_ V iV hiV ?_ ?_ hU'' + · fun_prop + · rw [hU'']; simp + · exact hV + · exact fun i ↦ IsEmbedding.of_comp (by fun_prop) continuous_subtype_val (hV' i) + rw [isEmbedding_iff_of_iSup_eq_top hU' h] + intro i + let f' := (Subtype.val ∘ (f ⁻¹' U i).restrictPreimage (iV i)) + have : IsEmbedding f' := + IsEmbedding.subtypeVal.comp ((IsEmbedding.of_comp (hiV i) h (hV' _)).restrictPreimage _) + have hf' : Set.range f' = f ⁻¹' U i := by + simpa [f', Set.range_comp, Set.range_restrictPreimage] using hV i + let e := (Homeomorph.ofIsEmbedding _ this).trans (Homeomorph.setCongr hf') + refine IsEmbedding.of_comp (by fun_prop) continuous_subtype_val ?_ + convert ((hV' i).comp IsEmbedding.subtypeVal).comp e.symm.isEmbedding + ext x + obtain ⟨x, rfl⟩ := e.surjective x + simp + rfl + @[deprecated (since := "2024-10-26")] alias embedding_iff_embedding_of_iSup_eq_top := isEmbedding_iff_of_iSup_eq_top diff --git a/Mathlib/Topology/MetricSpace/Defs.lean b/Mathlib/Topology/MetricSpace/Defs.lean index 93866859fadb0..e678bdcfedb6b 100644 --- a/Mathlib/Topology/MetricSpace/Defs.lean +++ b/Mathlib/Topology/MetricSpace/Defs.lean @@ -197,9 +197,9 @@ instance : Dist (Multiplicative X) := ‹Dist X› @[simp] theorem dist_ofAdd (a b : X) : dist (ofAdd a) (ofAdd b) = dist a b := rfl -@[simp] theorem dist_toMul (a b : Additive X) : dist (toMul a) (toMul b) = dist a b := rfl +@[simp] theorem dist_toMul (a b : Additive X) : dist a.toMul b.toMul = dist a b := rfl -@[simp] theorem dist_toAdd (a b : Multiplicative X) : dist (toAdd a) (toAdd b) = dist a b := rfl +@[simp] theorem dist_toAdd (a b : Multiplicative X) : dist a.toAdd b.toAdd = dist a b := rfl end @@ -211,10 +211,10 @@ variable [PseudoMetricSpace X] @[simp] theorem nndist_ofAdd (a b : X) : nndist (ofAdd a) (ofAdd b) = nndist a b := rfl -@[simp] theorem nndist_toMul (a b : Additive X) : nndist (toMul a) (toMul b) = nndist a b := rfl +@[simp] theorem nndist_toMul (a b : Additive X) : nndist a.toMul b.toMul = nndist a b := rfl @[simp] -theorem nndist_toAdd (a b : Multiplicative X) : nndist (toAdd a) (toAdd b) = nndist a b := rfl +theorem nndist_toAdd (a b : Multiplicative X) : nndist a.toAdd b.toAdd = nndist a b := rfl end diff --git a/Mathlib/Topology/MetricSpace/Dilation.lean b/Mathlib/Topology/MetricSpace/Dilation.lean index 201c0e06799e3..6ab93147d696b 100644 --- a/Mathlib/Topology/MetricSpace/Dilation.lean +++ b/Mathlib/Topology/MetricSpace/Dilation.lean @@ -74,7 +74,7 @@ end Defs namespace Dilation -variable {α : Type*} {β : Type*} {γ : Type*} {F : Type*} {G : Type*} +variable {α : Type*} {β : Type*} {γ : Type*} {F : Type*} section Setup @@ -229,8 +229,8 @@ end Setup section PseudoEmetricDilation variable [PseudoEMetricSpace α] [PseudoEMetricSpace β] [PseudoEMetricSpace γ] -variable [FunLike F α β] [DilationClass F α β] [FunLike G β γ] [DilationClass G β γ] -variable (f : F) (g : G) {x y z : α} {s : Set α} +variable [FunLike F α β] [DilationClass F α β] +variable (f : F) /-- Every isometry is a dilation of ratio `1`. -/ @[simps] diff --git a/Mathlib/Topology/MetricSpace/IsometricSMul.lean b/Mathlib/Topology/MetricSpace/IsometricSMul.lean index 8bbc25f34f0ab..7af5ce1593cca 100644 --- a/Mathlib/Topology/MetricSpace/IsometricSMul.lean +++ b/Mathlib/Topology/MetricSpace/IsometricSMul.lean @@ -420,26 +420,26 @@ instance Pi.isometricSMul'' {ι} {M : ι → Type*} [Fintype ι] [∀ i, Mul (M ⟨fun c => .piMap (fun i (x : M i) => x * c.unop i) fun _ => isometry_mul_right _⟩ instance Additive.isometricVAdd : IsometricVAdd (Additive M) X := - ⟨fun c => isometry_smul X (toMul c)⟩ + ⟨fun c => isometry_smul X c.toMul⟩ instance Additive.isometricVAdd' [Mul M] [PseudoEMetricSpace M] [IsometricSMul M M] : IsometricVAdd (Additive M) (Additive M) := - ⟨fun c x y => edist_smul_left (toMul c) (toMul x) (toMul y)⟩ + ⟨fun c x y => edist_smul_left c.toMul x.toMul y.toMul⟩ instance Additive.isometricVAdd'' [Mul M] [PseudoEMetricSpace M] [IsometricSMul Mᵐᵒᵖ M] : IsometricVAdd (Additive M)ᵃᵒᵖ (Additive M) := - ⟨fun c x y => edist_smul_left (MulOpposite.op (toMul c.unop)) (toMul x) (toMul y)⟩ + ⟨fun c x y => edist_smul_left (MulOpposite.op c.unop.toMul) x.toMul y.toMul⟩ instance Multiplicative.isometricSMul {M X} [VAdd M X] [PseudoEMetricSpace X] [IsometricVAdd M X] : IsometricSMul (Multiplicative M) X := - ⟨fun c => isometry_vadd X (toAdd c)⟩ + ⟨fun c => isometry_vadd X c.toAdd⟩ instance Multiplicative.isometricSMul' [Add M] [PseudoEMetricSpace M] [IsometricVAdd M M] : IsometricSMul (Multiplicative M) (Multiplicative M) := - ⟨fun c x y => edist_vadd_left (toAdd c) (toAdd x) (toAdd y)⟩ + ⟨fun c x y => edist_vadd_left c.toAdd x.toAdd y.toAdd⟩ instance Multiplicative.isometricVAdd'' [Add M] [PseudoEMetricSpace M] [IsometricVAdd Mᵃᵒᵖ M] : IsometricSMul (Multiplicative M)ᵐᵒᵖ (Multiplicative M) := - ⟨fun c x y => edist_vadd_left (AddOpposite.op (toAdd c.unop)) (toAdd x) (toAdd y)⟩ + ⟨fun c x y => edist_vadd_left (AddOpposite.op c.unop.toAdd) x.toAdd y.toAdd⟩ end Instances diff --git a/Mathlib/Topology/MetricSpace/Isometry.lean b/Mathlib/Topology/MetricSpace/Isometry.lean index 5e434b37434df..a987f5c09f284 100644 --- a/Mathlib/Topology/MetricSpace/Isometry.lean +++ b/Mathlib/Topology/MetricSpace/Isometry.lean @@ -62,7 +62,7 @@ namespace Isometry section PseudoEmetricIsometry variable [PseudoEMetricSpace α] [PseudoEMetricSpace β] [PseudoEMetricSpace γ] -variable {f : α → β} {x y z : α} {s : Set α} +variable {f : α → β} {x : α} /-- An isometry preserves edistances. -/ theorem edist_eq (hf : Isometry f) (x y : α) : edist (f x) (f y) = edist x y := diff --git a/Mathlib/Topology/MetricSpace/Kuratowski.lean b/Mathlib/Topology/MetricSpace/Kuratowski.lean index 5a21609d09845..a0fa5566df6e3 100644 --- a/Mathlib/Topology/MetricSpace/Kuratowski.lean +++ b/Mathlib/Topology/MetricSpace/Kuratowski.lean @@ -68,15 +68,12 @@ theorem embeddingOfSubset_isometry (H : DenseRange x) : Isometry (embeddingOfSub apply_rules [add_le_add_left, le_abs_self] _ ≤ 2 * (e / 2) + |embeddingOfSubset x b n - embeddingOfSubset x a n| := by rw [C] - apply_rules [add_le_add, mul_le_mul_of_nonneg_left, hn.le, le_refl] - norm_num + gcongr _ ≤ 2 * (e / 2) + dist (embeddingOfSubset x b) (embeddingOfSubset x a) := by - have : |embeddingOfSubset x b n - embeddingOfSubset x a n| ≤ - dist (embeddingOfSubset x b) (embeddingOfSubset x a) := by - simp only [dist_eq_norm] - exact lp.norm_apply_le_norm ENNReal.top_ne_zero - (embeddingOfSubset x b - embeddingOfSubset x a) n - nlinarith + gcongr + simp only [dist_eq_norm] + exact lp.norm_apply_le_norm ENNReal.top_ne_zero + (embeddingOfSubset x b - embeddingOfSubset x a) n _ = dist (embeddingOfSubset x b) (embeddingOfSubset x a) + e := by ring simpa [dist_comm] using this diff --git a/Mathlib/Topology/MetricSpace/Polish.lean b/Mathlib/Topology/MetricSpace/Polish.lean index d1e851e3c7d44..93c053adc16d7 100644 --- a/Mathlib/Topology/MetricSpace/Polish.lean +++ b/Mathlib/Topology/MetricSpace/Polish.lean @@ -102,7 +102,7 @@ instance (priority := 100) instMetrizableSpace (α : Type*) [TopologicalSpace α letI := upgradePolishSpace α infer_instance -@[deprecated (since := "2024-02-23")] +@[deprecated "No deprecation message was provided." (since := "2024-02-23")] theorem t2Space (α : Type*) [TopologicalSpace α] [PolishSpace α] : T2Space α := inferInstance /-- A countable product of Polish spaces is Polish. -/ diff --git a/Mathlib/Topology/MetricSpace/Pseudo/Real.lean b/Mathlib/Topology/MetricSpace/Pseudo/Real.lean index ae477178577c5..6183ec868a947 100644 --- a/Mathlib/Topology/MetricSpace/Pseudo/Real.lean +++ b/Mathlib/Topology/MetricSpace/Pseudo/Real.lean @@ -3,7 +3,7 @@ Copyright (c) 2015, 2017 Jeremy Avigad. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad, Robert Y. Lewis, Johannes Hölzl, Mario Carneiro, Sébastien Gouëzel -/ -import Mathlib.Data.Set.Pointwise.Interval +import Mathlib.Algebra.Order.Group.Pointwise.Interval import Mathlib.Topology.MetricSpace.Pseudo.Pi /-! @@ -15,7 +15,7 @@ open scoped NNReal Topology namespace Real -variable {ι α : Type*} [PseudoMetricSpace α] +variable {ι : Type*} lemma dist_left_le_of_mem_uIcc {x y z : ℝ} (h : y ∈ uIcc x z) : dist x y ≤ dist x z := by simpa only [dist_comm x] using abs_sub_left_of_mem_uIcc h @@ -35,7 +35,7 @@ lemma dist_le_of_mem_Icc {x y x' y' : ℝ} (hx : x ∈ Icc x' y') (hy : y ∈ Ic lemma dist_le_of_mem_Icc_01 {x y : ℝ} (hx : x ∈ Icc (0 : ℝ) 1) (hy : y ∈ Icc (0 : ℝ) 1) : dist x y ≤ 1 := by simpa only [sub_zero] using Real.dist_le_of_mem_Icc hx hy -variable {π : ι → Type*} [Fintype ι] [∀ i, PseudoMetricSpace (π i)] {x y x' y' : ι → ℝ} +variable [Fintype ι] {x y x' y' : ι → ℝ} lemma dist_le_of_mem_pi_Icc (hx : x ∈ Icc x' y') (hy : y ∈ Icc x' y') : dist x y ≤ dist x' y' := by refine (dist_pi_le_iff dist_nonneg).2 fun b => diff --git a/Mathlib/Topology/NoetherianSpace.lean b/Mathlib/Topology/NoetherianSpace.lean index 64689fd04f3f0..931e8748cbfce 100644 --- a/Mathlib/Topology/NoetherianSpace.lean +++ b/Mathlib/Topology/NoetherianSpace.lean @@ -98,7 +98,7 @@ theorem noetherianSpace_iff_isCompact : NoetherianSpace α ↔ ∀ s : Set α, I instance [NoetherianSpace α] : WellFoundedLT (Closeds α) := Iff.mp ((noetherianSpace_TFAE α).out 0 1) ‹_› -@[deprecated (since := "2024-10-07")] +@[deprecated "No deprecation message was provided." (since := "2024-10-07")] theorem NoetherianSpace.wellFounded_closeds [NoetherianSpace α] : WellFounded fun s t : Closeds α => s < t := wellFounded_lt diff --git a/Mathlib/Topology/Order.lean b/Mathlib/Topology/Order.lean index 789c64a0b0511..168716335f5dc 100644 --- a/Mathlib/Topology/Order.lean +++ b/Mathlib/Topology/Order.lean @@ -305,6 +305,11 @@ theorem singletons_open_iff_discrete {X : Type*} [TopologicalSpace X] : (∀ a : X, IsOpen ({a} : Set X)) ↔ DiscreteTopology X := ⟨fun h => ⟨eq_bot_of_singletons_open h⟩, fun a _ => @isOpen_discrete _ _ a _⟩ +theorem DiscreteTopology.of_finite_of_isClosed_singleton [TopologicalSpace α] [Finite α] + (h : ∀ a : α, IsClosed {a}) : DiscreteTopology α := + discreteTopology_iff_forall_isClosed.mpr fun s ↦ + s.iUnion_of_singleton_coe ▸ isClosed_iUnion_of_finite fun _ ↦ h _ + theorem discreteTopology_iff_singleton_mem_nhds [TopologicalSpace α] : DiscreteTopology α ↔ ∀ x : α, {x} ∈ 𝓝 x := by simp only [← singletons_open_iff_discrete, isOpen_iff_mem_nhds, mem_singleton_iff, forall_eq] diff --git a/Mathlib/Topology/Order/ExtrClosure.lean b/Mathlib/Topology/Order/ExtrClosure.lean index d1b2049789057..31b06abf781bd 100644 --- a/Mathlib/Topology/Order/ExtrClosure.lean +++ b/Mathlib/Topology/Order/ExtrClosure.lean @@ -20,7 +20,7 @@ open Filter Set open Topology variable {X Y : Type*} [TopologicalSpace X] [TopologicalSpace Y] [Preorder Y] - [OrderClosedTopology Y] {f g : X → Y} {s : Set X} {a : X} + [OrderClosedTopology Y] {f : X → Y} {s : Set X} {a : X} protected theorem IsMaxOn.closure (h : IsMaxOn f s a) (hc : ContinuousOn f (closure s)) : IsMaxOn f (closure s) a := fun x hx => diff --git a/Mathlib/Topology/Order/IntermediateValue.lean b/Mathlib/Topology/Order/IntermediateValue.lean index 81446ea8fdf08..ef73d422348e1 100644 --- a/Mathlib/Topology/Order/IntermediateValue.lean +++ b/Mathlib/Topology/Order/IntermediateValue.lean @@ -122,21 +122,20 @@ theorem IsPreconnected.intermediate_value {s : Set X} (hs : IsPreconnected s) {a theorem IsPreconnected.intermediate_value_Ico {s : Set X} (hs : IsPreconnected s) {a : X} {l : Filter X} (ha : a ∈ s) [NeBot l] (hl : l ≤ 𝓟 s) {f : X → α} (hf : ContinuousOn f s) {v : α} (ht : Tendsto f l (𝓝 v)) : Ico (f a) v ⊆ f '' s := fun _ h => - hs.intermediate_value₂_eventually₁ ha hl hf continuousOn_const h.1 - (eventually_ge_of_tendsto_gt h.2 ht) + hs.intermediate_value₂_eventually₁ ha hl hf continuousOn_const h.1 (ht.eventually_const_le h.2) theorem IsPreconnected.intermediate_value_Ioc {s : Set X} (hs : IsPreconnected s) {a : X} {l : Filter X} (ha : a ∈ s) [NeBot l] (hl : l ≤ 𝓟 s) {f : X → α} (hf : ContinuousOn f s) {v : α} (ht : Tendsto f l (𝓝 v)) : Ioc v (f a) ⊆ f '' s := fun _ h => (hs.intermediate_value₂_eventually₁ ha hl continuousOn_const hf h.2 - (eventually_le_of_tendsto_lt h.1 ht)).imp fun _ h => h.imp_right Eq.symm + (ht.eventually_le_const h.1)).imp fun _ h => h.imp_right Eq.symm theorem IsPreconnected.intermediate_value_Ioo {s : Set X} (hs : IsPreconnected s) {l₁ l₂ : Filter X} [NeBot l₁] [NeBot l₂] (hl₁ : l₁ ≤ 𝓟 s) (hl₂ : l₂ ≤ 𝓟 s) {f : X → α} (hf : ContinuousOn f s) {v₁ v₂ : α} (ht₁ : Tendsto f l₁ (𝓝 v₁)) (ht₂ : Tendsto f l₂ (𝓝 v₂)) : Ioo v₁ v₂ ⊆ f '' s := fun _ h => hs.intermediate_value₂_eventually₂ hl₁ hl₂ hf continuousOn_const - (eventually_le_of_tendsto_lt h.1 ht₁) (eventually_ge_of_tendsto_gt h.2 ht₂) + (ht₁.eventually_le_const h.1) (ht₂.eventually_const_le h.2) theorem IsPreconnected.intermediate_value_Ici {s : Set X} (hs : IsPreconnected s) {a : X} {l : Filter X} (ha : a ∈ s) [NeBot l] (hl : l ≤ 𝓟 s) {f : X → α} (hf : ContinuousOn f s) @@ -153,19 +152,19 @@ theorem IsPreconnected.intermediate_value_Ioi {s : Set X} (hs : IsPreconnected s [NeBot l₁] [NeBot l₂] (hl₁ : l₁ ≤ 𝓟 s) (hl₂ : l₂ ≤ 𝓟 s) {f : X → α} (hf : ContinuousOn f s) {v : α} (ht₁ : Tendsto f l₁ (𝓝 v)) (ht₂ : Tendsto f l₂ atTop) : Ioi v ⊆ f '' s := fun y h => hs.intermediate_value₂_eventually₂ hl₁ hl₂ hf continuousOn_const - (eventually_le_of_tendsto_lt h ht₁) (tendsto_atTop.1 ht₂ y) + (ht₁.eventually_le_const h) (ht₂.eventually_ge_atTop y) theorem IsPreconnected.intermediate_value_Iio {s : Set X} (hs : IsPreconnected s) {l₁ l₂ : Filter X} [NeBot l₁] [NeBot l₂] (hl₁ : l₁ ≤ 𝓟 s) (hl₂ : l₂ ≤ 𝓟 s) {f : X → α} (hf : ContinuousOn f s) {v : α} (ht₁ : Tendsto f l₁ atBot) (ht₂ : Tendsto f l₂ (𝓝 v)) : Iio v ⊆ f '' s := fun y h => - hs.intermediate_value₂_eventually₂ hl₁ hl₂ hf continuousOn_const (tendsto_atBot.1 ht₁ y) - (eventually_ge_of_tendsto_gt h ht₂) + hs.intermediate_value₂_eventually₂ hl₁ hl₂ hf continuousOn_const (ht₁.eventually_le_atBot y) + (ht₂.eventually_const_le h) theorem IsPreconnected.intermediate_value_Iii {s : Set X} (hs : IsPreconnected s) {l₁ l₂ : Filter X} [NeBot l₁] [NeBot l₂] (hl₁ : l₁ ≤ 𝓟 s) (hl₂ : l₂ ≤ 𝓟 s) {f : X → α} (hf : ContinuousOn f s) (ht₁ : Tendsto f l₁ atBot) (ht₂ : Tendsto f l₂ atTop) : univ ⊆ f '' s := fun y _ => - hs.intermediate_value₂_eventually₂ hl₁ hl₂ hf continuousOn_const (tendsto_atBot.1 ht₁ y) - (tendsto_atTop.1 ht₂ y) + hs.intermediate_value₂_eventually₂ hl₁ hl₂ hf continuousOn_const (ht₁.eventually_le_atBot y) + (ht₂.eventually_ge_atTop y) /-- **Intermediate Value Theorem** for continuous functions on connected spaces. -/ theorem intermediate_value_univ [PreconnectedSpace X] (a b : X) {f : X → α} (hf : Continuous f) : diff --git a/Mathlib/Topology/Order/MonotoneConvergence.lean b/Mathlib/Topology/Order/MonotoneConvergence.lean index bad7ee58b291e..7936b81bae9f3 100644 --- a/Mathlib/Topology/Order/MonotoneConvergence.lean +++ b/Mathlib/Topology/Order/MonotoneConvergence.lean @@ -107,7 +107,7 @@ end IsGLB section CiSup -variable [ConditionallyCompleteLattice α] [SupConvergenceClass α] {f : ι → α} {a : α} +variable [ConditionallyCompleteLattice α] [SupConvergenceClass α] {f : ι → α} theorem tendsto_atTop_ciSup (h_mono : Monotone f) (hbdd : BddAbove <| range f) : Tendsto f atTop (𝓝 (⨆ i, f i)) := by @@ -121,7 +121,7 @@ end CiSup section CiInf -variable [ConditionallyCompleteLattice α] [InfConvergenceClass α] {f : ι → α} {a : α} +variable [ConditionallyCompleteLattice α] [InfConvergenceClass α] {f : ι → α} theorem tendsto_atBot_ciInf (h_mono : Monotone f) (hbdd : BddBelow <| range f) : Tendsto f atBot (𝓝 (⨅ i, f i)) := by convert tendsto_atTop_ciSup h_mono.dual hbdd.dual using 1 @@ -133,7 +133,7 @@ end CiInf section iSup -variable [CompleteLattice α] [SupConvergenceClass α] {f : ι → α} {a : α} +variable [CompleteLattice α] [SupConvergenceClass α] {f : ι → α} theorem tendsto_atTop_iSup (h_mono : Monotone f) : Tendsto f atTop (𝓝 (⨆ i, f i)) := tendsto_atTop_ciSup h_mono (OrderTop.bddAbove _) @@ -145,7 +145,7 @@ end iSup section iInf -variable [CompleteLattice α] [InfConvergenceClass α] {f : ι → α} {a : α} +variable [CompleteLattice α] [InfConvergenceClass α] {f : ι → α} theorem tendsto_atBot_iInf (h_mono : Monotone f) : Tendsto f atBot (𝓝 (⨅ i, f i)) := tendsto_atBot_ciInf h_mono (OrderBot.bddBelow _) diff --git a/Mathlib/Topology/Order/OrderClosed.lean b/Mathlib/Topology/Order/OrderClosed.lean index 07a4ecd8f0010..46e8626f54295 100644 --- a/Mathlib/Topology/Order/OrderClosed.lean +++ b/Mathlib/Topology/Order/OrderClosed.lean @@ -150,6 +150,10 @@ theorem disjoint_nhds_atBot_iff : Disjoint (𝓝 a) atBot ↔ ¬IsBot a := by refine disjoint_of_disjoint_of_mem disjoint_compl_left ?_ (Iic_mem_atBot b) exact isClosed_Iic.isOpen_compl.mem_nhds hb +theorem IsLUB.range_of_tendsto {F : Filter β} [F.NeBot] (hle : ∀ i, f i ≤ a) + (hlim : Tendsto f F (𝓝 a)) : IsLUB (range f) a := + ⟨forall_mem_range.mpr hle, fun _c hc ↦ le_of_tendsto' hlim fun i ↦ hc <| mem_range_self i⟩ + end Preorder section NoBotOrder @@ -170,6 +174,23 @@ theorem not_tendsto_atBot_of_tendsto_nhds (hf : Tendsto f l (𝓝 a)) : ¬Tendst end NoBotOrder +theorem iSup_eq_of_forall_le_of_tendsto {ι : Type*} {F : Filter ι} [Filter.NeBot F] + [ConditionallyCompleteLattice α] [TopologicalSpace α] [ClosedIicTopology α] + {a : α} {f : ι → α} (hle : ∀ i, f i ≤ a) (hlim : Filter.Tendsto f F (𝓝 a)) : + ⨆ i, f i = a := + have := F.nonempty_of_neBot + (IsLUB.range_of_tendsto hle hlim).ciSup_eq + +theorem iUnion_Iic_eq_Iio_of_lt_of_tendsto {ι : Type*} {F : Filter ι} [F.NeBot] + [ConditionallyCompleteLinearOrder α] [TopologicalSpace α] [ClosedIicTopology α] + {a : α} {f : ι → α} (hlt : ∀ i, f i < a) (hlim : Tendsto f F (𝓝 a)) : + ⋃ i : ι, Iic (f i) = Iio a := by + have obs : a ∉ range f := by + rw [mem_range] + rintro ⟨i, rfl⟩ + exact (hlt i).false + rw [← biUnion_range, (IsLUB.range_of_tendsto (le_of_lt <| hlt ·) hlim).biUnion_Iic_eq_Iio obs] + section LinearOrder variable [TopologicalSpace α] [LinearOrder α] [ClosedIicTopology α] [TopologicalSpace β] @@ -192,14 +213,20 @@ theorem Ici_mem_nhds (h : a < b) : Ici a ∈ 𝓝 b := theorem eventually_ge_nhds (hab : b < a) : ∀ᶠ x in 𝓝 a, b ≤ x := Ici_mem_nhds hab -theorem eventually_gt_of_tendsto_gt {l : Filter γ} {f : γ → α} {u v : α} (hv : u < v) +theorem Filter.Tendsto.eventually_const_lt {l : Filter γ} {f : γ → α} {u v : α} (hv : u < v) (h : Filter.Tendsto f l (𝓝 v)) : ∀ᶠ a in l, u < f a := h.eventually <| eventually_gt_nhds hv -theorem eventually_ge_of_tendsto_gt {l : Filter γ} {f : γ → α} {u v : α} (hv : u < v) +@[deprecated (since := "2024-11-17")] +alias eventually_gt_of_tendsto_gt := Filter.Tendsto.eventually_const_lt + +theorem Filter.Tendsto.eventually_const_le {l : Filter γ} {f : γ → α} {u v : α} (hv : u < v) (h : Tendsto f l (𝓝 v)) : ∀ᶠ a in l, u ≤ f a := h.eventually <| eventually_ge_nhds hv +@[deprecated (since := "2024-11-17")] +alias eventually_ge_of_tendsto_gt := Filter.Tendsto.eventually_const_le + protected theorem Dense.exists_gt [NoMaxOrder α] {s : Set α} (hs : Dense s) (x : α) : ∃ y ∈ s, x < y := hs.exists_mem_open isOpen_Ioi (exists_gt x) @@ -341,7 +368,7 @@ variable [TopologicalSpace α] [Preorder α] [ClosedIciTopology α] {f : β → theorem isClosed_Ici {a : α} : IsClosed (Ici a) := ClosedIciTopology.isClosed_Ici a -@[deprecated (since := "2024-02-15")] +@[deprecated "No deprecation message was provided." (since := "2024-02-15")] lemma ClosedIciTopology.isClosed_ge' (a : α) : IsClosed {x | a ≤ x} := isClosed_Ici a export ClosedIciTopology (isClosed_ge') @@ -376,6 +403,10 @@ protected alias ⟨_, BddBelow.closure⟩ := bddBelow_closure theorem disjoint_nhds_atTop_iff : Disjoint (𝓝 a) atTop ↔ ¬IsTop a := disjoint_nhds_atBot_iff (α := αᵒᵈ) +theorem IsGLB.range_of_tendsto {F : Filter β} [F.NeBot] (hle : ∀ i, a ≤ f i) + (hlim : Tendsto f F (𝓝 a)) : IsGLB (range f) a := + IsLUB.range_of_tendsto (α := αᵒᵈ) hle hlim + end Preorder section NoTopOrder @@ -396,6 +427,18 @@ theorem not_tendsto_atTop_of_tendsto_nhds (hf : Tendsto f l (𝓝 a)) : ¬Tendst end NoTopOrder +theorem iInf_eq_of_forall_le_of_tendsto {ι : Type*} {F : Filter ι} [F.NeBot] + [ConditionallyCompleteLattice α] [TopologicalSpace α] [ClosedIciTopology α] + {a : α} {f : ι → α} (hle : ∀ i, a ≤ f i) (hlim : Tendsto f F (𝓝 a)) : + ⨅ i, f i = a := + iSup_eq_of_forall_le_of_tendsto (α := αᵒᵈ) hle hlim + +theorem iUnion_Ici_eq_Ioi_of_lt_of_tendsto {ι : Type*} {F : Filter ι} [F.NeBot] + [ConditionallyCompleteLinearOrder α] [TopologicalSpace α] [ClosedIciTopology α] + {a : α} {f : ι → α} (hlt : ∀ i, a < f i) (hlim : Tendsto f F (𝓝 a)) : + ⋃ i : ι, Ici (f i) = Ioi a := + iUnion_Iic_eq_Iio_of_lt_of_tendsto (α := αᵒᵈ) hlt hlim + section LinearOrder variable [TopologicalSpace α] [LinearOrder α] [ClosedIciTopology α] [TopologicalSpace β] @@ -414,14 +457,20 @@ theorem Iic_mem_nhds (h : a < b) : Iic b ∈ 𝓝 a := theorem eventually_le_nhds (hab : a < b) : ∀ᶠ x in 𝓝 a, x ≤ b := Iic_mem_nhds hab -theorem eventually_lt_of_tendsto_lt {l : Filter γ} {f : γ → α} {u v : α} (hv : v < u) +theorem Filter.Tendsto.eventually_lt_const {l : Filter γ} {f : γ → α} {u v : α} (hv : v < u) (h : Filter.Tendsto f l (𝓝 v)) : ∀ᶠ a in l, f a < u := h.eventually <| eventually_lt_nhds hv -theorem eventually_le_of_tendsto_lt {l : Filter γ} {f : γ → α} {u v : α} (hv : v < u) +@[deprecated (since := "2024-11-17")] +alias eventually_lt_of_tendsto_lt := Filter.Tendsto.eventually_lt_const + +theorem Filter.Tendsto.eventually_le_const {l : Filter γ} {f : γ → α} {u v : α} (hv : v < u) (h : Tendsto f l (𝓝 v)) : ∀ᶠ a in l, f a ≤ u := h.eventually <| eventually_le_nhds hv +@[deprecated (since := "2024-11-17")] +alias eventually_le_of_tendsto_lt := Filter.Tendsto.eventually_le_const + protected theorem Dense.exists_lt [NoMinOrder α] {s : Set α} (hs : Dense s) (x : α) : ∃ y ∈ s, y < x := hs.orderDual.exists_gt x diff --git a/Mathlib/Topology/Order/T5.lean b/Mathlib/Topology/Order/T5.lean index 39e0d08dc9b0a..597085db3f109 100644 --- a/Mathlib/Topology/Order/T5.lean +++ b/Mathlib/Topology/Order/T5.lean @@ -16,8 +16,7 @@ topological space. open Filter Set Function OrderDual Topology Interval -variable {X : Type*} [LinearOrder X] [TopologicalSpace X] [OrderTopology X] {a b c : X} - {s t : Set X} +variable {X : Type*} [LinearOrder X] [TopologicalSpace X] [OrderTopology X] {a : X} {s t : Set X} namespace Set diff --git a/Mathlib/Topology/ShrinkingLemma.lean b/Mathlib/Topology/ShrinkingLemma.lean index 8f03eeab6a068..65f6b72889730 100644 --- a/Mathlib/Topology/ShrinkingLemma.lean +++ b/Mathlib/Topology/ShrinkingLemma.lean @@ -206,7 +206,7 @@ section NormalSpace open ShrinkingLemma -variable {u : ι → Set X} {s : Set X} {p : Set X → Prop} [NormalSpace X] +variable {u : ι → Set X} {s : Set X} [NormalSpace X] /-- **Shrinking lemma**. A point-finite open cover of a closed subset of a normal space can be "shrunk" to a new open cover so that the closure of each new open set is contained in the diff --git a/Mathlib/Topology/UniformSpace/OfCompactT2.lean b/Mathlib/Topology/UniformSpace/OfCompactT2.lean index 5eaf71a852f4f..c9d49e9474570 100644 --- a/Mathlib/Topology/UniformSpace/OfCompactT2.lean +++ b/Mathlib/Topology/UniformSpace/OfCompactT2.lean @@ -26,7 +26,7 @@ uniform space, uniform continuity, compact space open Uniformity Topology Filter UniformSpace Set -variable {α β γ : Type*} [UniformSpace α] [UniformSpace β] +variable {γ : Type*} /-! ### Uniformity on compact spaces diff --git a/Mathlib/Util/AtomM.lean b/Mathlib/Util/AtomM.lean index 0b829028c0b11..bc85531a753a4 100644 --- a/Mathlib/Util/AtomM.lean +++ b/Mathlib/Util/AtomM.lean @@ -5,6 +5,7 @@ Authors: Mario Carneiro -/ import Mathlib.Init import Lean.Meta.Tactic.Simp.Types +import Qq /-! # A monad for tracking and deduplicating atoms @@ -44,13 +45,33 @@ def AtomM.run {α : Type} (red : TransparencyMode) (m : AtomM α) MetaM α := (m { red, evalAtom }).run' {} -/-- Get the index corresponding to an atomic expression, if it has already been encountered, or -put it in the list of atoms and return the new index, otherwise. -/ -def AtomM.addAtom (e : Expr) : AtomM Nat := do +/-- If an atomic expression has already been encountered, get the index and the stored form of the +atom (which will be defeq at the specified transparency, but not necessarily syntactically equal). +If the atomic expression has *not* already been encountered, store it in the list of atoms, and +return the new index (and the stored form of the atom, which will be itself). + +In a normalizing tactic, the expression returned by `addAtom` should be considered the normal form. +-/ +def AtomM.addAtom (e : Expr) : AtomM (Nat × Expr) := do let c ← get for h : i in [:c.atoms.size] do if ← withTransparency (← read).red <| isDefEq e c.atoms[i] then - return i - modifyGet fun c ↦ (c.atoms.size, { c with atoms := c.atoms.push e }) + return (i, c.atoms[i]) + modifyGet fun c ↦ ((c.atoms.size, e), { c with atoms := c.atoms.push e }) + +open Qq in +/-- If an atomic expression has already been encountered, get the index and the stored form of the +atom (which will be defeq at the specified transparency, but not necessarily syntactically equal). +If the atomic expression has *not* already been encountered, store it in the list of atoms, and +return the new index (and the stored form of the atom, which will be itself). + +In a normalizing tactic, the expression returned by `addAtomQ` should be considered the normal form. + +This is a strongly-typed version of `AtomM.addAtom` for code using `Qq`. +-/ +def AtomM.addAtomQ {u : Level} {α : Q(Type u)} (e : Q($α)) : + AtomM (Nat × {e' : Q($α) // $e =Q $e'}) := do + let (n, e') ← AtomM.addAtom e + return (n, ⟨e', ⟨⟩⟩) end Mathlib.Tactic diff --git a/MathlibTest/CategoryTheory/ConcreteCategory/AlgebraCat.lean b/MathlibTest/CategoryTheory/ConcreteCategory/AlgebraCat.lean new file mode 100644 index 0000000000000..406d12cc89de4 --- /dev/null +++ b/MathlibTest/CategoryTheory/ConcreteCategory/AlgebraCat.lean @@ -0,0 +1,53 @@ +import Mathlib + +universe v u + +open CategoryTheory AlgebraCat + +set_option maxHeartbeats 10000 +set_option synthInstance.maxHeartbeats 2000 + +variable (R : Type u) [CommRing R] + +/- We test if all the coercions and `map_add` lemmas trigger correctly. -/ + +example (X : Type u) [Ring X] [Algebra R X] : ⇑(𝟙 (of R X)) = id := by simp + +example {X Y : Type v} [Ring X] [Algebra R X] [Ring Y] [Algebra R Y] (f : X →ₐ[R] Y) : + ⇑(ofHom f) = ⇑f := by simp + +example {X Y : Type v} [Ring X] [Algebra R X] [Ring Y] [Algebra R Y] (f : X →ₐ[R] Y) + (x : X) : (ofHom f) x = f x := by simp + +example {X Y Z : AlgebraCat R} (f : X ⟶ Y) (g : Y ⟶ Z) : ⇑(f ≫ g) = ⇑g ∘ ⇑f := by simp + +example {X Y Z : Type v} [Ring X] [Algebra R X] [Ring Y] [Algebra R Y] [Ring Z] + [Algebra R Z] (f : X →ₐ[R] Y) (g : Y →ₐ[R] Z) : + ⇑(ofHom f ≫ ofHom g) = g ∘ f := by simp + +example {X Y : Type v} [Ring X] [Algebra R X] [Ring Y] [Algebra R Y] {Z : AlgebraCat R} + (f : X →ₐ[R] Y) (g : of R Y ⟶ Z) : + ⇑(ofHom f ≫ g) = g ∘ f := by simp + +example {X Y : AlgebraCat R} {Z : Type v} [Ring Z] [Algebra R Z] (f : X ⟶ Y) (g : Y ⟶ of R Z) : + ⇑(f ≫ g) = g ∘ f := by simp + +example {Y Z : AlgebraCat R} {X : Type v} [Ring X] [Algebra R X] (f : of R X ⟶ Y) (g : Y ⟶ Z) : + ⇑(f ≫ g) = g ∘ f := by simp + +example {X Y Z : AlgebraCat R} (f : X ⟶ Y) (g : Y ⟶ Z) (x : X) : (f ≫ g) x = g (f x) := by simp + +example {X Y : AlgebraCat R} (e : X ≅ Y) (x : X) : e.inv (e.hom x) = x := by simp + +example {X Y : AlgebraCat R} (e : X ≅ Y) (y : Y) : e.hom (e.inv y) = y := by simp + +example (X : AlgebraCat R) : ⇑(𝟙 X) = id := by simp + +example {M N : AlgebraCat.{v} R} (f : M ⟶ N) (x y : M) : f (x + y) = f x + f y := by + simp + +example {M N : AlgebraCat.{v} R} (f : M ⟶ N) : f 0 = 0 := by + simp + +example {M N : AlgebraCat.{v} R} (f : M ⟶ N) (r : R) (m : M) : f (r • m) = r • f m := by + simp diff --git a/MathlibTest/Expr.lean b/MathlibTest/Expr.lean index 1e4b9fd11388d..84efba4ecb2f9 100644 --- a/MathlibTest/Expr.lean +++ b/MathlibTest/Expr.lean @@ -13,7 +13,7 @@ def reorderLastArguments : Expr → Expr := Expr.replaceRec fun r e ↦ let n := e.getAppNumArgs if n ≥ 2 then - mkAppN e.getAppFn <| e.getAppArgs.map r |>.swap! (n - 1) (n - 2) + mkAppN e.getAppFn <| e.getAppArgs.map r |>.swapIfInBounds (n - 1) (n - 2) else none diff --git a/MathlibTest/MinImports.lean b/MathlibTest/MinImports.lean index 43ee73fa011e9..87a0a011d07ad 100644 --- a/MathlibTest/MinImports.lean +++ b/MathlibTest/MinImports.lean @@ -165,4 +165,28 @@ def def_with_multiple_dependencies := let _ := Mathlib.Meta.NormNum.evalNatDvd false +/-! Structures and inductives should be treated just like definitions. -/ + +/-- + +warning: Consider moving this declaration to the module Mathlib.Data.Nat.Notation. +note: this linter can be disabled with `set_option linter.upstreamableDecl false` +-/ +#guard_msgs in +structure ProposeToMoveThisStructure where + foo : ℕ + +/-- +warning: Consider moving this declaration to the module Mathlib.Data.Nat.Notation. +note: this linter can be disabled with `set_option linter.upstreamableDecl false` +-/ +#guard_msgs in +inductive ProposeToMoveThisInductive where +| foo : ℕ → ProposeToMoveThisInductive +| bar : ℕ → ProposeToMoveThisInductive → ProposeToMoveThisInductive + +-- This theorem depends on a local inductive, so should not be moved. +#guard_msgs in +theorem theorem_with_local_inductive : Nonempty ProposeToMoveThisInductive := ⟨.foo 0⟩ + end Linter.UpstreamableDecl diff --git a/MathlibTest/NthRewrite.lean b/MathlibTest/NthRewrite.lean index 287039007dce6..3b82ffdb5998a 100644 --- a/MathlibTest/NthRewrite.lean +++ b/MathlibTest/NthRewrite.lean @@ -16,7 +16,7 @@ example [AddZeroClass G] {a : G} : a + a = a + (a + 0) := by structure F where (a : ℕ) - (v : Vector ℕ a) + (v : Mathlib.Vector ℕ a) (p : v.val = []) example (f : F) : f.v.val = [] := by diff --git a/MathlibTest/Simps.lean b/MathlibTest/Simps.lean index 8def1aa96d6ef..2c3e0d2f69483 100644 --- a/MathlibTest/Simps.lean +++ b/MathlibTest/Simps.lean @@ -1203,7 +1203,7 @@ structure Foo where @[simps field field_2 field_9_fst] def myFoo : Foo := ⟨1, ⟨1, 1⟩, 1⟩ -structure Prod (X Y : Type _) extends Prod X Y +structure Prod (X Y : Type _) extends _root_.Prod X Y structure Prod2 (X Y : Type _) extends Prod X Y diff --git a/MathlibTest/abel.lean b/MathlibTest/abel.lean index d59304f17cbfb..f2235b46071cf 100644 --- a/MathlibTest/abel.lean +++ b/MathlibTest/abel.lean @@ -141,3 +141,32 @@ example [AddCommGroup α] (x y z : α) (h : False) (w : x - x = y + z) : False : abel_nf at * guard_hyp w : 0 = y + z assumption + +section +abbrev myId (a : ℤ) : ℤ := a + +/- +Test that when `abel_nf` normalizes multiple expressions which contain a particular atom, it uses a +form for that atom which is consistent between expressions. + +We can't use `guard_hyp h :ₛ` here, as while it does tell apart `x` and `myId x`, it also complains +about differing instance paths. +-/ +/-- +info: α : Type _ +a b : α +x : ℤ +R : ℤ → ℤ → Prop +hR : Reflexive R +h : R (2 • myId x) (2 • myId x) +⊢ True +-/ +#guard_msgs (info) in +set_option pp.mvars false in +example (x : ℤ) (R : ℤ → ℤ → Prop) (hR : Reflexive R) : True := by + have h : R (myId x + x) (x + myId x) := hR .. + abel_nf at h + trace_state + trivial + +end diff --git a/MathlibTest/cc.lean b/MathlibTest/cc.lean index 4d0f3eb630b40..26e0d6ac83f4d 100644 --- a/MathlibTest/cc.lean +++ b/MathlibTest/cc.lean @@ -220,17 +220,21 @@ universe u open Mathlib -axiom app : {α : Type u} → {n m : Nat} → Vector α m → Vector α n → Vector α (m + n) +axiom app : {α : Type u} → {n m : Nat} → + Mathlib.Vector α m → Mathlib.Vector α n → Mathlib.Vector α (m + n) -example (n1 n2 n3 : Nat) (v1 w1 : Vector Nat n1) (w1' : Vector Nat n3) (v2 w2 : Vector Nat n2) : +example (n1 n2 n3 : Nat) + (v1 w1 : Mathlib.Vector Nat n1) (w1' : Mathlib.Vector Nat n3) (v2 w2 : Mathlib.Vector Nat n2) : n1 = n3 → v1 = w1 → HEq w1 w1' → v2 = w2 → HEq (app v1 v2) (app w1' w2) := by cc -example (n1 n2 n3 : Nat) (v1 w1 : Vector Nat n1) (w1' : Vector Nat n3) (v2 w2 : Vector Nat n2) : +example (n1 n2 n3 : Nat) + (v1 w1 : Mathlib.Vector Nat n1) (w1' : Mathlib.Vector Nat n3) (v2 w2 : Mathlib.Vector Nat n2) : HEq n1 n3 → v1 = w1 → HEq w1 w1' → HEq v2 w2 → HEq (app v1 v2) (app w1' w2) := by cc -example (n1 n2 n3 : Nat) (v1 w1 v : Vector Nat n1) (w1' : Vector Nat n3) (v2 w2 w : Vector Nat n2) : +example (n1 n2 n3 : Nat) + (v1 w1 v : Mathlib.Vector Nat n1) (w1' : Mathlib.Vector Nat n3) (v2 w2 w : Mathlib.Vector Nat n2) : HEq n1 n3 → v1 = w1 → HEq w1 w1' → HEq v2 w2 → HEq (app w1' w2) (app v w) → app v1 v2 = app v w := by cc diff --git a/MathlibTest/fun_prop2.lean b/MathlibTest/fun_prop2.lean index e98b764c72c0a..8a5d906d3f74b 100644 --- a/MathlibTest/fun_prop2.lean +++ b/MathlibTest/fun_prop2.lean @@ -76,7 +76,7 @@ example : AEMeasurable T := by fun_prop -private theorem t1 : (5: ℕ) + (1 : ℕ∞) ≤ (12 : ℕ∞) := by norm_cast +private theorem t1 : (5: ℕ) + (1 : ℕ∞) ≤ (12 : WithTop ℕ∞) := by norm_cast example {f : ℝ → ℝ} (hf : ContDiff ℝ 12 f) : Differentiable ℝ (iteratedDeriv 5 (fun x => f (2*(f (x + x))) + x)) := by diff --git a/MathlibTest/levenshtein.lean b/MathlibTest/levenshtein.lean index 5d2c2d34f0d48..53932d20b2d56 100644 --- a/MathlibTest/levenshtein.lean +++ b/MathlibTest/levenshtein.lean @@ -1,5 +1,5 @@ import Mathlib.Data.List.EditDistance.Defs -import Mathlib.Algebra.Group.Nat +import Mathlib.Algebra.Group.Nat.Basic #guard (suffixLevenshtein Levenshtein.defaultCost "kitten".toList "sitting".toList).1 = diff --git a/MathlibTest/positivity.lean b/MathlibTest/positivity.lean index da296d8d2860f..b3f2b9b7af6ba 100644 --- a/MathlibTest/positivity.lean +++ b/MathlibTest/positivity.lean @@ -1,10 +1,10 @@ +import Mathlib.Tactic.Positivity import Mathlib.Data.Complex.Exponential import Mathlib.Data.Real.Sqrt import Mathlib.Analysis.Normed.Group.Basic import Mathlib.Analysis.SpecialFunctions.Pow.Real import Mathlib.Analysis.SpecialFunctions.Log.Basic import Mathlib.MeasureTheory.Integral.Bochner -import Mathlib.Tactic.Positivity.Finset /-! # Tests for the `positivity` tactic diff --git a/MathlibTest/ring.lean b/MathlibTest/ring.lean index ffdfe755e4dec..8a0a07fea0178 100644 --- a/MathlibTest/ring.lean +++ b/MathlibTest/ring.lean @@ -178,3 +178,28 @@ example {n : ℝ} (_hn : 0 ≤ n) : (n + 1 / 2) ^ 2 * (n + 1 + 1 / 3) ≤ (n + 1 ring_nf trace_state exact test_sorry + +section +abbrev myId (a : ℤ) : ℤ := a + +/- +Test that when `ring_nf` normalizes multiple expressions which contain a particular atom, it uses a +form for that atom which is consistent between expressions. + +We can't use `guard_hyp h :ₛ` here, as while it does tell apart `x` and `myId x`, it also complains +about differing instance paths. +-/ +/-- +info: x : ℤ +R : ℤ → ℤ → Prop +h : R (myId x * 2) (myId x * 2) +⊢ True +-/ +#guard_msgs (info) in +example (x : ℤ) (R : ℤ → ℤ → Prop) : True := by + have h : R (myId x + x) (x + myId x) := test_sorry + ring_nf at h + trace_state + trivial + +end diff --git a/MathlibTest/symm.lean b/MathlibTest/symm.lean index 7d88a90868362..ae72925a5b7a4 100644 --- a/MathlibTest/symm.lean +++ b/MathlibTest/symm.lean @@ -23,15 +23,6 @@ example (a b c : Nat) (ab : a = b) (bc : b = c) : c = a := by symm_saturate apply Eq.trans <;> assumption -def MulHom.inverse [Mul M] [Mul N] (f : M →ₙ* N) (g : N → M) (h₁ : Function.LeftInverse g f) - (h₂ : Function.RightInverse g f) : N →ₙ* M where - toFun := g - map_mul' x y := - calc - g (x * y) = g (f (g x) * f (g y)) := by rw [h₂ x, h₂ y] - _ = g (f (g x * g y)) := by rw [f.map_mul] - _ = g x * g y := h₁ _ - structure MulEquiv (M N : Type u) [Mul M] [Mul N] extends M ≃ N, M →ₙ* N /-- diff --git a/docs/100.yaml b/docs/100.yaml index 31f5837e872ca..550cf7682b392 100644 --- a/docs/100.yaml +++ b/docs/100.yaml @@ -182,6 +182,8 @@ title : The Central Limit Theorem 48: title : Dirichlet’s Theorem + decl : Nat.setOf_prime_and_eq_mod_infinite + author : David Loeffler, Michael Stoll 49: title : The Cayley-Hamilton Theorem decl : Matrix.aeval_self_charpoly diff --git a/docs/references.bib b/docs/references.bib index 6603b6a5466fe..0e5ce6b9bd094 100644 --- a/docs/references.bib +++ b/docs/references.bib @@ -247,6 +247,21 @@ @Book{ beals2004 year = {2004} } +@Book{ Becker-Weispfenning1993, + address = {New York, NY}, + series = {Graduate Texts in Mathematics}, + title = {Gröbner Bases}, + volume = {141}, + isbn = {978-1-4612-6944-1}, + url = {http://link.springer.com/10.1007/978-1-4612-0913-3}, + doi = {10.1007/978-1-4612-0913-3}, + publisher = {Springer New York}, + author = {Becker, Thomas and Weispfenning, Volker}, + year = {1993}, + collection = {Graduate Texts in Mathematics}, + language = {en} +} + @Book{ behrends1979, author = {Ehrhard {Behrends}}, title = {{M-structure and the Banach-Stone theorem}}, @@ -305,6 +320,31 @@ @Article{ bernstein1912 number = {1–2} } +@Book{ Berthelot-1974, + author = {Berthelot, Pierre}, + year = {1974}, + series = {Lecture {{Notes}} in {{Mathematics}}}, + number = {407}, + publisher = {sv}, + keywords = {nosource}, + file = {/Users/chambert/Zotero/storage/WHF5R9LQ/Berthelot - 1974 - + Cohomologie cristalline des schémas de caractérist.djvu}, + title = {Cohomologie Cristalline Des Schémas de Caractéristique + {$p>0$}} +} + +@Book{ BerthelotOgus-1978, + title = {Notes on Crystalline Cohomology}, + author = {Berthelot, Pierre and Ogus, Arthur}, + year = {1978}, + series = {Math. {{Notes}}}, + number = {21}, + publisher = {pup}, + keywords = {nosource}, + file = {/Users/chambert/Zotero/storage/I3FNJEDB/Berthelot et Ogus + - 1978 - Notes on crystalline cohomology.djvu} +} + @InProceedings{ beylin1996, author = "Beylin, Ilya and Dybjer, Peter", editor = "Berardi, Stefano and Coppo, Mario", @@ -398,6 +438,19 @@ @Book{ bogachev2007 url = {https://doi.org/10.1007/978-3-540-34514-5} } +@Article{ bojanic74, + author = {Bojani\'c, Ranko}, + title = {A simple proof of {M}ahler's theorem on approximation of + continuous functions of a p-adic variable by polynomials}, + journal = {Journal of Number Theory}, + volume = {6}, + pages = {412-415}, + year = {1974}, + issn = {0022-314X}, + doi = {10.1016/0022-314X(74)90038-9}, + url = {https://doi.org/10.1016/0022-314X(74)90038-9} +} + @Book{ bollobas1986, author = {Bollob\'{a}s, B\'{e}la}, title = {Combinatorics: Set Systems, Hypergraphs, Families of @@ -2058,6 +2111,19 @@ @Book{ IrelandRosen1990 url = {https://doi.org/10.1007/978-1-4757-2103-4} } +@Article{ Isaacs1980, + author = {Isaacs, I. M.}, + title = {Roots of Polynomials in Algebraic Extensions of Fields}, + publisher = {Taylor \& Francis}, + year = {1980}, + pages = {543--544}, + journal = {The American Mathematical Monthly}, + volume = {87}, + number = {7}, + doi = {10.1080/00029890.1980.11995085}, + url = {https://doi.org/10.1080/00029890.1980.11995085} +} + @Book{ iversen, title = {Generic Local Structure of the Morphisms in Commutative Algebra}, @@ -3036,6 +3102,28 @@ @Misc{ RisingSea url = "https://math.stanford.edu/~vakil/216blog/" } +@Article{ Roby-1963, + title = {Lois polynomes et lois formelles en théorie des modules}, + author = {Roby, Norbert}, + year = {1963}, + journal = {Annales scientifiques de l'École Normale Supérieure}, + volume = {80}, + number = {3}, + pages = {213--348}, + doi = {10.24033/asens.1124}, + urldate = {2022-09-15}, + langid = {french} +} + +@Article{ Roby-1965, + title = {Les Algèbres à Puissances Divisées}, + author = {Roby, Norbert}, + year = {1965}, + journal = {Bulletin des Sciences Mathématiques. Deuxième Série}, + volume = {89}, + pages = {75--91} +} + @Article{ Rosenlicht_1972, author = {Rosenlicht, Maxwell}, title = {Integration in finite terms}, diff --git a/lake-manifest.json b/lake-manifest.json index 8c908bbffe75e..0268064157515 100644 --- a/lake-manifest.json +++ b/lake-manifest.json @@ -65,7 +65,7 @@ "type": "git", "subDir": null, "scope": "leanprover-community", - "rev": "e652e51c0a2588af8e989e8f7c77a5755e44c364", + "rev": "1c9af2d671f59cbaadde311c4856f8924340c0c7", "name": "batteries", "manifestFile": "lake-manifest.json", "inputRev": "lean-pr-testing-6083", diff --git a/scripts/README.md b/scripts/README.md index 8f55ce30822bb..3962da0193667 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -80,8 +80,7 @@ to learn about it as well! **Data files with linter exceptions** - `nolints.json` contains exceptions for all `env_linter`s in mathlib. For permanent and deliberate exceptions, add a `@[nolint lintername]` in the .lean file instead. -- `no_lints_prime_decls.txt` - contains temporary exceptions for the `docPrime` linter +- `nolints_prime_decls.txt` contains temporary exceptions for the `docPrime` linter Both of these files should tend to zero over time; please do not add new entries to these files. PRs removing (the need for) entries are welcome. @@ -94,9 +93,12 @@ please do not add new entries to these files. PRs removing (the need for) entrie to the appropriate topic on zulip. - `count-trans-deps.py`, `import-graph-report.py` and `import_trans_difference.sh` produce various summaries of changes in transitive imports that the `PR_summary` message incorporates. -- `zulip_emoji_merge_delegate.py` is called every hour by a Github action cronjob. - It looks through the latest 200 zulip posts: if a message mentions a PR that is delegated, or sent to bors, or merged, - then this script will post an emoji reaction `:peace_sign:`, or `:bors:`, or `:merge:` respectively to the message. +- `zulip_emoji_merge_delegate.py` is called + * every time a `bors d`, `bors merge` or `bors r+` comment is added to a PR and + * on every push to `master`. + It looks through all zulip posts containing a reference to the relevant PR + (delegated, or sent to bors, or merged) and it will post an emoji reaction + `:peace_sign:`, or `:bors:`, or `:merge:` respectively to the message. - `late_importers.sh` is the main script used by the `latest_import.yml` action: it formats the `linter.minImports` output, summarizing the data in a table. See the module docs of `late_importers.sh` for further details. diff --git a/scripts/bench_summary.lean b/scripts/bench_summary.lean index 9c9407ea066f4..17f0467b2ef97 100644 --- a/scripts/bench_summary.lean +++ b/scripts/bench_summary.lean @@ -147,6 +147,7 @@ open Lean Elab Command in as a comment to a pull request. It takes as input * the number `PR` and the name `repo` as a `String` containing the relevant pull-request (it reads and posts comments there) +* the optional `jobID` string for reporting the action that produced the output * the `String` `tempFile` of a temporary file where the command stores transient information. The code itself interfaces with the shell to retrieve and process json data and eventually @@ -162,9 +163,10 @@ Here is a summary of the steps: * process the final string to produce a summary (using `benchOutput`), * finally post the resulting output to the PR (using `gh pr comment ...`). -/ -def addBenchSummaryComment (PR : Nat) (repo : String) +def addBenchSummaryComment (PR : Nat) (repo : String) (jobID : String := "") (author : String := "leanprover-bot") (tempFile : String := "benchOutput.json") : CommandElabM Unit := do + let job_msg := s!"\n[CI run](https://github.com/{repo}/actions/runs/{jobID})" let PR := s!"{PR}" let jq := s!".comments | last | select(.author.login==\"{author}\") | .body" @@ -197,10 +199,10 @@ def addBenchSummaryComment (PR : Nat) (repo : String) IO.FS.writeFile (tempFile ++ ".src") bench -- Extract all instruction changes whose magnitude is larger than `threshold`. - let threshold := s!"{10 ^ 9}" + let threshold := 10 ^ 9 let jq1 : IO.Process.SpawnArgs := { cmd := "jq" - args := #["-r", "--arg", "thr", threshold, + args := #["-r", "--arg", "thr", s!"{threshold}", ".differences | .[] | ($thr|tonumber) as $th | select(.dimension.metric == \"instructions\" and ((.diff >= $th) or (.diff <= -$th)))", (tempFile ++ ".src")] } @@ -220,6 +222,12 @@ def addBenchSummaryComment (PR : Nat) (repo : String) jq -c '[\{file: .dimension.benchmark, diff: .diff, reldiff: .reldiff}]' {tempFile} > \ {tempFile}.2" let secondFilter ← IO.Process.run jq2 + if secondFilter == "" then + let _ ← IO.Process.run + { cmd := "gh", args := #["pr", "comment", PR, "--repo", repo, "--body", + s!"No benchmark entry differed by at least {formatDiff threshold} instructions." ++ + job_msg] } + else IO.FS.writeFile tempFile secondFilter let jq3 : IO.Process.SpawnArgs := { cmd := "jq", args := #["-n", "reduce inputs as $in (null; . + $in)", tempFile] } @@ -230,7 +238,7 @@ def addBenchSummaryComment (PR : Nat) (repo : String) IO.println report -- Post the computed summary as a github comment. let add_comment : IO.Process.SpawnArgs := - { cmd := "gh", args := #["pr", "comment", PR, "--repo", repo, "--body", report] } + { cmd := "gh", args := #["pr", "comment", PR, "--repo", repo, "--body", report ++ job_msg] } let _ ← IO.Process.run add_comment end BenchAction diff --git a/scripts/create-adaptation-pr.sh b/scripts/create-adaptation-pr.sh index b8ae7cf37b28f..f8b5deb203b7e 100755 --- a/scripts/create-adaptation-pr.sh +++ b/scripts/create-adaptation-pr.sh @@ -198,7 +198,7 @@ if git diff --name-only bump/$BUMPVERSION bump/nightly-$NIGHTLYDATE | grep -q .; echo "### [auto] post a link to the PR on Zulip" zulip_title="#$pr_number adaptations for nightly-$NIGHTLYDATE" - zulip_body="> $pr_title #$pr_number\\\n\\\nPlease review this PR. At the end of the month this diff will land in \\\`master\\\`." + zulip_body="> $pr_title #$pr_number"$'\n\nPlease review this PR. At the end of the month this diff will land in `master`.' echo "Posting the link to the PR in a new thread on the #nightly-testing channel on Zulip" echo "Here is the message:" diff --git a/scripts/import_trans_difference.sh b/scripts/import_trans_difference.sh index 9c103e3eabdae..a13bebc4957cf 100755 --- a/scripts/import_trans_difference.sh +++ b/scripts/import_trans_difference.sh @@ -67,7 +67,16 @@ git checkout "${currCommit}" printf '\n\n
Import changes for all files\n\n%s\n\n
\n' "$( printf "|Files|Import difference|\n|-|-|\n" - (awk -F, -v all="${all}" -v ghLimit='261752' '{ diff[$1]+=$2 } END { + (awk -F, -v all="${all}" -v ghLimit='261752' -v newFiles="$( + # we pass the "A"dded files with respect to master, converting them to module names + git diff --name-only --diff-filter=A master | tr '\n' , | sed 's=\.lean,=,=g; s=/=.=g' + )" ' + BEGIN{ + # `arrayNewModules` maps integers to module names + split(newFiles, arrayNewModules, ",") + # `newModules` "just" stores the module names + for(v in arrayNewModules) { newModules[arrayNewModules[v]]=0 } + } { diff[$1]+=$2 } END { fileCount=0 outputLength=0 for(fil in diff) { @@ -75,7 +84,8 @@ printf '\n\n
Import changes for all files\n\n%s\n\n