diff --git a/.codecov.yml b/.codecov.yml new file mode 100644 index 00000000000..69cb76019a4 --- /dev/null +++ b/.codecov.yml @@ -0,0 +1 @@ +comment: false diff --git a/.github/workflows/ci-cygwin-minimal.yml b/.github/workflows/ci-cygwin-minimal.yml new file mode 100644 index 00000000000..fa8f5db4f81 --- /dev/null +++ b/.github/workflows/ci-cygwin-minimal.yml @@ -0,0 +1,1042 @@ +name: CI cygwin-minimal + +on: + push: + tags: + - '*' + workflow_dispatch: + # Allow to run manually + +env: + MAKE: make -j8 + SAGE_NUM_THREADS: 3 + CYGWIN: winsymlinks:native + EXTRA_CONFIGURE_ARGS: --enable-fat-binary + SAGE_LOCAL: /opt/sage-${{ github.sha }} + +jobs: + +############################################## stage-i ########################################## + + cygwin-stage-i-a: + env: + STAGE: i-a + # builds openblas + TARGETS: iml gsl + LOCAL_ARTIFACT_NAME: sage-local-commit-${{ github.sha }}-cygwin-${{ matrix.pkgs }} + LOGS_ARTIFACT_NAME: logs-commit-${{ github.sha }}-cygwin-${{ matrix.pkgs }} + + runs-on: windows-latest + + strategy: + fail-fast: false + matrix: + pkgs: [minimal] + steps: + - run: | + git config --global core.autocrlf false + git config --global core.symlinks true + - uses: actions/checkout@v1 + - name: install cygwin and test prerequisites with choco + shell: bash {0} + run: | + choco --version + PACKAGES="python39 python39-pip" + choco install $PACKAGES --source cygwin + - name: tox + run: | + C:\\tools\\cygwin\\bin\\bash -l -x -c 'cat /proc/cpuinfo' + C:\\tools\\cygwin\\bin\\bash -l -x -c 'python3.8 -m pip install tox' + C:\\tools\\cygwin\\bin\\bash -l -x -c 'cd $(cygpath -u "$GITHUB_WORKSPACE") && PREFIX="${{ env.SAGE_LOCAL }}" tox -e local-cygwin-choco-${{ matrix.pkgs }} -- $TARGETS' + - name: Prepare logs artifact + shell: bash + run: | + mkdir -p "artifacts/$LOGS_ARTIFACT_NAME"; for a in "${{ env.SAGE_LOCAL }}"/var/tmp/sage/build/*; do if [ -d "$a" ]; then tar -c --remove-files -f "artifacts/$LOGS_ARTIFACT_NAME/$(basename "$a").tar" "$a"; fi; done; cp -r logs/* "artifacts/$LOGS_ARTIFACT_NAME" + if: always() + - uses: actions/upload-artifact@v2 + with: + path: artifacts + name: ${{ env.LOGS_ARTIFACT_NAME }} + if: always() + - name: Print out logs for immediate inspection + # The markup in the output is a GitHub Actions logging command + # https://help.github.com/en/actions/automating-your-workflow-with-github-actions/development-tools-for-github-actions + shell: bash + run: | + find "artifacts/$LOGS_ARTIFACT_NAME" -type f -name "*.log" -exec sh -c 'if tail -20 "{}" 2>/dev/null | grep "^Error" >/dev/null; then echo :":"error file={}:":" ==== LOG FILE {} CONTAINS AN ERROR ====; cat {} ; fi' \; + if: always() + - name: Prepare sage-local artifact + # We specifically use the cygwin tar so that symlinks are saved/restored correctly on Windows. + # We remove the $SAGE_LOCAL/lib64 link, which will be recreated by the next stage. + run: | + C:\\tools\\cygwin\\bin\\bash -l -c 'cd $(cygpath -u "$GITHUB_WORKSPACE") && rm -f "${{ env.SAGE_LOCAL }}"/lib64; tar -cf /tmp/sage-local-${{ env.STAGE }}.tar --remove-files "${{ env.SAGE_LOCAL }}"' + if: always() + - uses: actions/upload-artifact@v2 + # upload-artifact@v2 does not support whitespace in file names. + # so we tar up the directory ourselves + with: + path: C:\\tools\\cygwin\\tmp\\sage-local-${{ env.STAGE }}.tar + name: ${{ env.LOCAL_ARTIFACT_NAME }} + if: always() + + cygwin-stage-i-b: + env: + STAGE: i-b + TARGETS: cython setuptools_scm kiwisolver dateutil cycler pyparsing certifi pkgconfig pplpy + LOCAL_ARTIFACT_NAME: sage-local-commit-${{ github.sha }}-cygwin-${{ matrix.pkgs }} + LOGS_ARTIFACT_NAME: logs-commit-${{ github.sha }}-cygwin-${{ matrix.pkgs }} + + runs-on: windows-latest + + strategy: + fail-fast: false + matrix: + pkgs: [minimal] + steps: + - run: | + git config --global core.autocrlf false + git config --global core.symlinks true + - uses: actions/checkout@v1 + - name: install cygwin and test prerequisites with choco + shell: bash {0} + run: | + choco --version + PACKAGES="python39 python39-pip" + choco install $PACKAGES --source cygwin + - name: tox + run: | + C:\\tools\\cygwin\\bin\\bash -l -x -c 'cat /proc/cpuinfo' + C:\\tools\\cygwin\\bin\\bash -l -x -c 'python3.8 -m pip install tox' + C:\\tools\\cygwin\\bin\\bash -l -x -c 'cd $(cygpath -u "$GITHUB_WORKSPACE") && PREFIX="${{ env.SAGE_LOCAL }}" tox -e local-cygwin-choco-${{ matrix.pkgs }} -- $TARGETS' + - name: Prepare logs artifact + shell: bash + run: | + mkdir -p "artifacts/$LOGS_ARTIFACT_NAME"; for a in "${{ env.SAGE_LOCAL }}"/var/tmp/sage/build/*; do if [ -d "$a" ]; then tar -c --remove-files -f "artifacts/$LOGS_ARTIFACT_NAME/$(basename "$a").tar" "$a"; fi; done; cp -r logs/* "artifacts/$LOGS_ARTIFACT_NAME" + if: always() + - uses: actions/upload-artifact@v2 + with: + path: artifacts + name: ${{ env.LOGS_ARTIFACT_NAME }} + if: always() + - name: Print out logs for immediate inspection + # The markup in the output is a GitHub Actions logging command + # https://help.github.com/en/actions/automating-your-workflow-with-github-actions/development-tools-for-github-actions + shell: bash + run: | + find "artifacts/$LOGS_ARTIFACT_NAME" -type f -name "*.log" -exec sh -c 'if tail -20 "{}" 2>/dev/null | grep "^Error" >/dev/null; then echo :":"error file={}:":" ==== LOG FILE {} CONTAINS AN ERROR ====; cat {} ; fi' \; + if: always() + - name: Prepare sage-local artifact + # We specifically use the cygwin tar so that symlinks are saved/restored correctly on Windows. + # We remove the $SAGE_LOCAL/lib64 link, which will be recreated by the next stage. + run: | + C:\\tools\\cygwin\\bin\\bash -l -c 'cd $(cygpath -u "$GITHUB_WORKSPACE") && rm -f "${{ env.SAGE_LOCAL }}"/lib64; tar -cf /tmp/sage-local-${{ env.STAGE }}.tar --remove-files "${{ env.SAGE_LOCAL }}"' + if: always() + - uses: actions/upload-artifact@v2 + # upload-artifact@v2 does not support whitespace in file names. + # so we tar up the directory ourselves + with: + path: C:\\tools\\cygwin\\tmp\\sage-local-${{ env.STAGE }}.tar + name: ${{ env.LOCAL_ARTIFACT_NAME }} + if: always() + +############################################## stage-ii ########################################## + + cygwin-stage-ii-a: + env: + STAGE: ii-a + PREVIOUS_STAGES: i-* + TARGETS: cvxopt rpy2 + LOCAL_ARTIFACT_NAME: sage-local-commit-${{ github.sha }}-cygwin-${{ matrix.pkgs }} + LOGS_ARTIFACT_NAME: logs-commit-${{ github.sha }}-cygwin-${{ matrix.pkgs }} + + needs: [cygwin-stage-i-a, cygwin-stage-i-b] + + runs-on: windows-latest + + strategy: + fail-fast: false + matrix: + pkgs: [minimal] + steps: + - run: | + git config --global core.autocrlf false + git config --global core.symlinks true + - uses: actions/checkout@v1 + - name: install cygwin and test prerequisites with choco + shell: bash {0} + run: | + choco --version + PACKAGES="python39 python39-pip" + choco install $PACKAGES --source cygwin + - uses: actions/download-artifact@v2 + with: + name: ${{ env.LOCAL_ARTIFACT_NAME }} + path: C:\\tools\\cygwin\\tmp + - name: Extract sage-local artifact + run: | + C:\\tools\\cygwin\\bin\\dash -l -c 'cd $(cygpath -u "$GITHUB_WORKSPACE") && .github/workflows/extract-sage-local.sh /tmp/sage-local-*.tar && tar --create --listed-incremental=/tmp/sage-local.snar --file /dev/null "${{ env.SAGE_LOCAL }}"' + - name: tox + run: | + C:\\tools\\cygwin\\bin\\bash -l -x -c 'cat /proc/cpuinfo' + C:\\tools\\cygwin\\bin\\bash -l -x -c 'python3.8 -m pip install tox' + C:\\tools\\cygwin\\bin\\bash -l -x -c 'cd $(cygpath -u "$GITHUB_WORKSPACE") && PREFIX="${{ env.SAGE_LOCAL }}" tox -e local-cygwin-choco-${{ matrix.pkgs }} -- $TARGETS' + - name: Prepare logs artifact + shell: bash + run: | + mkdir -p "artifacts/$LOGS_ARTIFACT_NAME"; for a in "${{ env.SAGE_LOCAL }}"/var/tmp/sage/build/*; do if [ -d "$a" ]; then tar -c --remove-files -f "artifacts/$LOGS_ARTIFACT_NAME/$(basename "$a").tar" "$a"; fi; done; cp -r logs/* "artifacts/$LOGS_ARTIFACT_NAME" + if: always() + - uses: actions/upload-artifact@v2 + with: + path: artifacts + name: ${{ env.LOGS_ARTIFACT_NAME }} + if: always() + - name: Print out logs for immediate inspection + # The markup in the output is a GitHub Actions logging command + # https://help.github.com/en/actions/automating-your-workflow-with-github-actions/development-tools-for-github-actions + shell: bash + run: | + find "artifacts/$LOGS_ARTIFACT_NAME" -type f -name "*.log" -exec sh -c 'if tail -20 "{}" 2>/dev/null | grep "^Error" >/dev/null; then echo :":"error file={}:":" ==== LOG FILE {} CONTAINS AN ERROR ====; cat {} ; fi' \; + if: always() + - name: Prepare sage-local artifact + # We specifically use the cygwin tar so that symlinks are saved/restored correctly on Windows. + # We remove the $SAGE_LOCAL/lib64 link, which will be recreated by the next stage. + run: | + C:\\tools\\cygwin\\bin\\bash -l -c 'cd $(cygpath -u "$GITHUB_WORKSPACE") && rm -f "${{ env.SAGE_LOCAL }}"/lib64; tar -cf /tmp/sage-local-${{ env.STAGE }}.tar --listed-incremental=/tmp/sage-local.snar "${{ env.SAGE_LOCAL }}"' + if: always() + - uses: actions/upload-artifact@v2 + # upload-artifact@v2 does not support whitespace in file names. + # so we tar up the directory ourselves + with: + path: C:\\tools\\cygwin\\tmp\\sage-local-${{ env.STAGE }}.tar + name: ${{ env.LOCAL_ARTIFACT_NAME }} + if: always() + + cygwin-stage-ii-b: + env: + STAGE: ii-b + PREVIOUS_STAGES: i-* + TARGETS: singular maxima gap pari gfan palp flintqs arb ecm givaro + LOCAL_ARTIFACT_NAME: sage-local-commit-${{ github.sha }}-cygwin-${{ matrix.pkgs }} + LOGS_ARTIFACT_NAME: logs-commit-${{ github.sha }}-cygwin-${{ matrix.pkgs }} + + needs: [cygwin-stage-i-a, cygwin-stage-i-b] + + runs-on: windows-latest + + strategy: + fail-fast: false + matrix: + pkgs: [minimal] + steps: + - run: | + git config --global core.autocrlf false + git config --global core.symlinks true + - uses: actions/checkout@v1 + - name: install cygwin and test prerequisites with choco + shell: bash {0} + run: | + choco --version + PACKAGES="python39 python39-pip" + choco install $PACKAGES --source cygwin + - uses: actions/download-artifact@v2 + with: + name: ${{ env.LOCAL_ARTIFACT_NAME }} + path: C:\\tools\\cygwin\\tmp + - name: Extract sage-local artifact + run: | + C:\\tools\\cygwin\\bin\\dash -l -c 'cd $(cygpath -u "$GITHUB_WORKSPACE") && .github/workflows/extract-sage-local.sh /tmp/sage-local-*.tar && tar --create --listed-incremental=/tmp/sage-local.snar --file /dev/null "${{ env.SAGE_LOCAL }}"' + - name: tox + run: | + C:\\tools\\cygwin\\bin\\bash -l -x -c 'cat /proc/cpuinfo' + C:\\tools\\cygwin\\bin\\bash -l -x -c 'python3.8 -m pip install tox' + C:\\tools\\cygwin\\bin\\bash -l -x -c 'cd $(cygpath -u "$GITHUB_WORKSPACE") && PREFIX="${{ env.SAGE_LOCAL }}" tox -e local-cygwin-choco-${{ matrix.pkgs }} -- $TARGETS' + - name: Prepare logs artifact + shell: bash + run: | + mkdir -p "artifacts/$LOGS_ARTIFACT_NAME"; for a in "${{ env.SAGE_LOCAL }}"/var/tmp/sage/build/*; do if [ -d "$a" ]; then tar -c --remove-files -f "artifacts/$LOGS_ARTIFACT_NAME/$(basename "$a").tar" "$a"; fi; done; cp -r logs/* "artifacts/$LOGS_ARTIFACT_NAME" + if: always() + - uses: actions/upload-artifact@v2 + with: + path: artifacts + name: ${{ env.LOGS_ARTIFACT_NAME }} + if: always() + - name: Print out logs for immediate inspection + # The markup in the output is a GitHub Actions logging command + # https://help.github.com/en/actions/automating-your-workflow-with-github-actions/development-tools-for-github-actions + shell: bash + run: | + find "artifacts/$LOGS_ARTIFACT_NAME" -type f -name "*.log" -exec sh -c 'if tail -20 "{}" 2>/dev/null | grep "^Error" >/dev/null; then echo :":"error file={}:":" ==== LOG FILE {} CONTAINS AN ERROR ====; cat {} ; fi' \; + if: always() + - name: Prepare sage-local artifact + # We specifically use the cygwin tar so that symlinks are saved/restored correctly on Windows. + # We remove the $SAGE_LOCAL/lib64 link, which will be recreated by the next stage. + run: | + C:\\tools\\cygwin\\bin\\bash -l -c 'cd $(cygpath -u "$GITHUB_WORKSPACE") && rm -f "${{ env.SAGE_LOCAL }}"/lib64; tar -cf /tmp/sage-local-${{ env.STAGE }}.tar --listed-incremental=/tmp/sage-local.snar "${{ env.SAGE_LOCAL }}"' + if: always() + - uses: actions/upload-artifact@v2 + with: + path: C:\\tools\\cygwin\\tmp\\sage-local-${{ env.STAGE }}.tar + name: ${{ env.LOCAL_ARTIFACT_NAME }} + if: always() + + cygwin-stage-ii-c: + env: + STAGE: ii-c + PREVIOUS_STAGES: i-* + TARGETS: cypari eclib fplll linbox giac + LOCAL_ARTIFACT_NAME: sage-local-commit-${{ github.sha }}-cygwin-${{ matrix.pkgs }} + LOGS_ARTIFACT_NAME: logs-commit-${{ github.sha }}-cygwin-${{ matrix.pkgs }} + + needs: [cygwin-stage-i-a, cygwin-stage-i-b] + + runs-on: windows-latest + + strategy: + fail-fast: false + matrix: + pkgs: [minimal] + steps: + - run: | + git config --global core.autocrlf false + git config --global core.symlinks true + - uses: actions/checkout@v1 + - name: install cygwin and test prerequisites with choco + shell: bash {0} + run: | + choco --version + PACKAGES="python39 python39-pip" + choco install $PACKAGES --source cygwin + - uses: actions/download-artifact@v2 + with: + name: ${{ env.LOCAL_ARTIFACT_NAME }} + path: C:\\tools\\cygwin\\tmp + - name: Extract sage-local artifact + run: | + C:\\tools\\cygwin\\bin\\dash -l -c 'cd $(cygpath -u "$GITHUB_WORKSPACE") && .github/workflows/extract-sage-local.sh /tmp/sage-local-*.tar && tar --create --listed-incremental=/tmp/sage-local.snar --file /dev/null "${{ env.SAGE_LOCAL }}"' + - name: tox + run: | + C:\\tools\\cygwin\\bin\\bash -l -x -c 'cat /proc/cpuinfo' + C:\\tools\\cygwin\\bin\\bash -l -x -c 'python3.8 -m pip install tox' + C:\\tools\\cygwin\\bin\\bash -l -x -c 'cd $(cygpath -u "$GITHUB_WORKSPACE") && PREFIX="${{ env.SAGE_LOCAL }}" tox -e local-cygwin-choco-${{ matrix.pkgs }} -- $TARGETS' + - name: Prepare logs artifact + shell: bash + run: | + mkdir -p "artifacts/$LOGS_ARTIFACT_NAME"; for a in "${{ env.SAGE_LOCAL }}"/var/tmp/sage/build/*; do if [ -d "$a" ]; then tar -c --remove-files -f "artifacts/$LOGS_ARTIFACT_NAME/$(basename "$a").tar" "$a"; fi; done; cp -r logs/* "artifacts/$LOGS_ARTIFACT_NAME" + if: always() + - uses: actions/upload-artifact@v2 + with: + path: artifacts + name: ${{ env.LOGS_ARTIFACT_NAME }} + if: always() + - name: Print out logs for immediate inspection + # The markup in the output is a GitHub Actions logging command + # https://help.github.com/en/actions/automating-your-workflow-with-github-actions/development-tools-for-github-actions + shell: bash + run: | + find "artifacts/$LOGS_ARTIFACT_NAME" -type f -name "*.log" -exec sh -c 'if tail -20 "{}" 2>/dev/null | grep "^Error" >/dev/null; then echo :":"error file={}:":" ==== LOG FILE {} CONTAINS AN ERROR ====; cat {} ; fi' \; + if: always() + - name: Prepare sage-local artifact + # We specifically use the cygwin tar so that symlinks are saved/restored correctly on Windows. + # We remove the $SAGE_LOCAL/lib64 link, which will be recreated by the next stage. + run: | + C:\\tools\\cygwin\\bin\\bash -l -c 'cd $(cygpath -u "$GITHUB_WORKSPACE") && rm -f "${{ env.SAGE_LOCAL }}"/lib64; tar -cf /tmp/sage-local-${{ env.STAGE }}.tar --listed-incremental=/tmp/sage-local.snar "${{ env.SAGE_LOCAL }}"' + if: always() + - uses: actions/upload-artifact@v2 + with: + path: C:\\tools\\cygwin\\tmp\\sage-local-${{ env.STAGE }}.tar + name: ${{ env.LOCAL_ARTIFACT_NAME }} + if: always() + + cygwin-stage-ii-d: + env: + STAGE: ii-d + PREVIOUS_STAGES: i-* + TARGETS: ipython ipywidgets notebook + LOCAL_ARTIFACT_NAME: sage-local-commit-${{ github.sha }}-cygwin-${{ matrix.pkgs }} + LOGS_ARTIFACT_NAME: logs-commit-${{ github.sha }}-cygwin-${{ matrix.pkgs }} + + needs: [cygwin-stage-i-a, cygwin-stage-i-b] + + runs-on: windows-latest + + strategy: + fail-fast: false + matrix: + pkgs: [minimal] + steps: + - run: | + git config --global core.autocrlf false + git config --global core.symlinks true + - uses: actions/checkout@v1 + - name: install cygwin and test prerequisites with choco + shell: bash {0} + run: | + choco --version + PACKAGES="python39 python39-pip" + choco install $PACKAGES --source cygwin + - uses: actions/download-artifact@v2 + with: + name: ${{ env.LOCAL_ARTIFACT_NAME }} + path: C:\\tools\\cygwin\\tmp + - name: Extract sage-local artifact + run: | + C:\\tools\\cygwin\\bin\\dash -l -c 'cd $(cygpath -u "$GITHUB_WORKSPACE") && .github/workflows/extract-sage-local.sh /tmp/sage-local-*.tar && tar --create --listed-incremental=/tmp/sage-local.snar --file /dev/null "${{ env.SAGE_LOCAL }}"' + - name: tox + run: | + C:\\tools\\cygwin\\bin\\bash -l -x -c 'cat /proc/cpuinfo' + C:\\tools\\cygwin\\bin\\bash -l -x -c 'python3.8 -m pip install tox' + C:\\tools\\cygwin\\bin\\bash -l -x -c 'cd $(cygpath -u "$GITHUB_WORKSPACE") && PREFIX="${{ env.SAGE_LOCAL }}" tox -e local-cygwin-choco-${{ matrix.pkgs }} -- $TARGETS' + - name: Prepare logs artifact + shell: bash + run: | + mkdir -p "artifacts/$LOGS_ARTIFACT_NAME"; for a in "${{ env.SAGE_LOCAL }}"/var/tmp/sage/build/*; do if [ -d "$a" ]; then tar -c --remove-files -f "artifacts/$LOGS_ARTIFACT_NAME/$(basename "$a").tar" "$a"; fi; done; cp -r logs/* "artifacts/$LOGS_ARTIFACT_NAME" + if: always() + - uses: actions/upload-artifact@v2 + with: + path: artifacts + name: ${{ env.LOGS_ARTIFACT_NAME }} + if: always() + - name: Print out logs for immediate inspection + # The markup in the output is a GitHub Actions logging command + # https://help.github.com/en/actions/automating-your-workflow-with-github-actions/development-tools-for-github-actions + shell: bash + run: | + find "artifacts/$LOGS_ARTIFACT_NAME" -type f -name "*.log" -exec sh -c 'if tail -20 "{}" 2>/dev/null | grep "^Error" >/dev/null; then echo :":"error file={}:":" ==== LOG FILE {} CONTAINS AN ERROR ====; cat {} ; fi' \; + if: always() + - name: Prepare sage-local artifact + # We specifically use the cygwin tar so that symlinks are saved/restored correctly on Windows. + # We remove the $SAGE_LOCAL/lib64 link, which will be recreated by the next stage. + run: | + C:\\tools\\cygwin\\bin\\bash -l -c 'cd $(cygpath -u "$GITHUB_WORKSPACE") && rm -f "${{ env.SAGE_LOCAL }}"/lib64; tar -cf /tmp/sage-local-${{ env.STAGE }}.tar --listed-incremental=/tmp/sage-local.snar "${{ env.SAGE_LOCAL }}"' + if: always() + - uses: actions/upload-artifact@v2 + with: + path: C:\\tools\\cygwin\\tmp\\sage-local-${{ env.STAGE }}.tar + name: ${{ env.LOCAL_ARTIFACT_NAME }} + if: always() + + cygwin-stage-ii-e: + env: + STAGE: ii-e + PREVIOUS_STAGES: i-* + TARGETS: threejs tachyon pillow jmol m4rie sympy lrcalc lcalc symmetrica cliquer libbraiding planarity rw elliptic_curves combinatorial_designs sympow + LOCAL_ARTIFACT_NAME: sage-local-commit-${{ github.sha }}-cygwin-${{ matrix.pkgs }} + LOGS_ARTIFACT_NAME: logs-commit-${{ github.sha }}-cygwin-${{ matrix.pkgs }} + + needs: [cygwin-stage-i-a, cygwin-stage-i-b] + + runs-on: windows-latest + + strategy: + fail-fast: false + matrix: + pkgs: [minimal] + steps: + - run: | + git config --global core.autocrlf false + git config --global core.symlinks true + - uses: actions/checkout@v1 + - name: install cygwin and test prerequisites with choco + shell: bash {0} + run: | + choco --version + PACKAGES="python39 python39-pip" + choco install $PACKAGES --source cygwin + - uses: actions/download-artifact@v2 + with: + name: ${{ env.LOCAL_ARTIFACT_NAME }} + path: C:\\tools\\cygwin\\tmp + - name: Extract sage-local artifact + run: | + C:\\tools\\cygwin\\bin\\dash -l -c 'cd $(cygpath -u "$GITHUB_WORKSPACE") && .github/workflows/extract-sage-local.sh /tmp/sage-local-*.tar && tar --create --listed-incremental=/tmp/sage-local.snar --file /dev/null "${{ env.SAGE_LOCAL }}"' + - name: tox + run: | + C:\\tools\\cygwin\\bin\\bash -l -x -c 'cat /proc/cpuinfo' + C:\\tools\\cygwin\\bin\\bash -l -x -c 'python3.8 -m pip install tox' + C:\\tools\\cygwin\\bin\\bash -l -x -c 'cd $(cygpath -u "$GITHUB_WORKSPACE") && PREFIX="${{ env.SAGE_LOCAL }}" tox -e local-cygwin-choco-${{ matrix.pkgs }} -- $TARGETS' + - name: Prepare logs artifact + shell: bash + run: | + mkdir -p "artifacts/$LOGS_ARTIFACT_NAME"; for a in "${{ env.SAGE_LOCAL }}"/var/tmp/sage/build/*; do if [ -d "$a" ]; then tar -c --remove-files -f "artifacts/$LOGS_ARTIFACT_NAME/$(basename "$a").tar" "$a"; fi; done; cp -r logs/* "artifacts/$LOGS_ARTIFACT_NAME" + if: always() + - uses: actions/upload-artifact@v2 + with: + path: artifacts + name: ${{ env.LOGS_ARTIFACT_NAME }} + if: always() + - name: Print out logs for immediate inspection + # The markup in the output is a GitHub Actions logging command + # https://help.github.com/en/actions/automating-your-workflow-with-github-actions/development-tools-for-github-actions + shell: bash + run: | + find "artifacts/$LOGS_ARTIFACT_NAME" -type f -name "*.log" -exec sh -c 'if tail -20 "{}" 2>/dev/null | grep "^Error" >/dev/null; then echo :":"error file={}:":" ==== LOG FILE {} CONTAINS AN ERROR ====; cat {} ; fi' \; + if: always() + - name: Prepare sage-local artifact + # We specifically use the cygwin tar so that symlinks are saved/restored correctly on Windows. + # We remove the $SAGE_LOCAL/lib64 link, which will be recreated by the next stage. + run: | + C:\\tools\\cygwin\\bin\\bash -l -c 'cd $(cygpath -u "$GITHUB_WORKSPACE") && rm -f "${{ env.SAGE_LOCAL }}"/lib64; tar -cf /tmp/sage-local-${{ env.STAGE }}.tar --listed-incremental=/tmp/sage-local.snar "${{ env.SAGE_LOCAL }}"' + if: always() + - uses: actions/upload-artifact@v2 + with: + path: C:\\tools\\cygwin\\tmp\\sage-local-${{ env.STAGE }}.tar + name: ${{ env.LOCAL_ARTIFACT_NAME }} + if: always() + +############################################## stage-iii ########################################## + + cygwin-stage-iii-a: + env: + STAGE: iii-a + PREVIOUS_STAGES: ii-* + TARGETS: sagelib + LOCAL_ARTIFACT_NAME: sage-local-commit-${{ github.sha }}-cygwin-${{ matrix.pkgs }} + LOGS_ARTIFACT_NAME: logs-commit-${{ github.sha }}-cygwin-${{ matrix.pkgs }} + + needs: [cygwin-stage-ii-a, cygwin-stage-ii-b, cygwin-stage-ii-c, cygwin-stage-ii-d, cygwin-stage-ii-e] + + runs-on: windows-latest + + continue-on-error: true + + strategy: + fail-fast: false + matrix: + pkgs: [minimal] + steps: + - run: | + git config --global core.autocrlf false + git config --global core.symlinks true + - uses: actions/checkout@v1 + - name: install cygwin and test prerequisites with choco + shell: bash {0} + run: | + choco --version + PACKAGES="python39 python39-pip" + choco install $PACKAGES --source cygwin + - uses: actions/download-artifact@v2 + with: + name: ${{ env.LOCAL_ARTIFACT_NAME }} + path: C:\\tools\\cygwin\\tmp + - name: Extract sage-local artifact + run: | + C:\\tools\\cygwin\\bin\\dash -l -c 'cd $(cygpath -u "$GITHUB_WORKSPACE") && .github/workflows/extract-sage-local.sh /tmp/sage-local-*.tar && tar --create --listed-incremental=/tmp/sage-local.snar --file /dev/null "${{ env.SAGE_LOCAL }}"' + - name: tox + run: | + C:\\tools\\cygwin\\bin\\bash -l -x -c 'cat /proc/cpuinfo' + C:\\tools\\cygwin\\bin\\bash -l -x -c 'python3.8 -m pip install tox' + C:\\tools\\cygwin\\bin\\bash -l -x -c 'cd $(cygpath -u "$GITHUB_WORKSPACE") && PREFIX="${{ env.SAGE_LOCAL }}" tox -e local-cygwin-choco-${{ matrix.pkgs }} -- $TARGETS' + - name: Prepare logs artifact + shell: bash + run: | + mkdir -p "artifacts/$LOGS_ARTIFACT_NAME"; for a in "${{ env.SAGE_LOCAL }}"/var/tmp/sage/build/*; do if [ -d "$a" ]; then tar -c --remove-files -f "artifacts/$LOGS_ARTIFACT_NAME/$(basename "$a").tar" "$a"; fi; done; cp -r logs/* "artifacts/$LOGS_ARTIFACT_NAME" + if: always() + - uses: actions/upload-artifact@v2 + with: + path: artifacts + name: ${{ env.LOGS_ARTIFACT_NAME }} + if: always() + - name: Print out logs for immediate inspection + # The markup in the output is a GitHub Actions logging command + # https://help.github.com/en/actions/automating-your-workflow-with-github-actions/development-tools-for-github-actions + shell: bash + run: | + find "artifacts/$LOGS_ARTIFACT_NAME" -type f -name "*.log" -exec sh -c 'if tail -20 "{}" 2>/dev/null | grep "^Error" >/dev/null; then echo :":"error file={}:":" ==== LOG FILE {} CONTAINS AN ERROR ====; cat {} ; fi' \; + if: always() + - name: Prepare sage-local artifact + # We specifically use the cygwin tar so that symlinks are saved/restored correctly on Windows. + # We remove the $SAGE_LOCAL/lib64 link, which will be recreated by the next stage. + run: | + C:\\tools\\cygwin\\bin\\bash -l -c 'cd $(cygpath -u "$GITHUB_WORKSPACE") && rm -f "${{ env.SAGE_LOCAL }}"/lib64; tar -cf /tmp/sage-local-${{ env.STAGE }}.tar --listed-incremental=/tmp/sage-local.snar "${{ env.SAGE_LOCAL }}"' + if: always() + - uses: actions/upload-artifact@v2 + # upload-artifact@v2 does not support whitespace in file names. + # so we tar up the directory ourselves + with: + path: C:\\tools\\cygwin\\tmp\\sage-local-${{ env.STAGE }}.tar + name: ${{ env.LOCAL_ARTIFACT_NAME }} + if: always() + + cygwin-stage-iii-b: + env: + STAGE: iii-b + PREVIOUS_STAGES: ii-* + TARGETS: networkx + LOCAL_ARTIFACT_NAME: sage-local-commit-${{ github.sha }}-cygwin-${{ matrix.pkgs }} + LOGS_ARTIFACT_NAME: logs-commit-${{ github.sha }}-cygwin-${{ matrix.pkgs }} + + needs: [cygwin-stage-ii-a, cygwin-stage-ii-b, cygwin-stage-ii-c, cygwin-stage-ii-d, cygwin-stage-ii-e] + + runs-on: windows-latest + + continue-on-error: true + + strategy: + fail-fast: false + matrix: + pkgs: [minimal] + steps: + - run: | + git config --global core.autocrlf false + git config --global core.symlinks true + - uses: actions/checkout@v1 + - name: install cygwin and test prerequisites with choco + shell: bash {0} + run: | + choco --version + PACKAGES="python39 python39-pip" + choco install $PACKAGES --source cygwin + - uses: actions/download-artifact@v2 + with: + name: ${{ env.LOCAL_ARTIFACT_NAME }} + path: C:\\tools\\cygwin\\tmp + - name: Extract sage-local artifact + run: | + C:\\tools\\cygwin\\bin\\dash -l -c 'cd $(cygpath -u "$GITHUB_WORKSPACE") && .github/workflows/extract-sage-local.sh /tmp/sage-local-*.tar && tar --create --listed-incremental=/tmp/sage-local.snar --file /dev/null "${{ env.SAGE_LOCAL }}"' + - name: tox + run: | + C:\\tools\\cygwin\\bin\\bash -l -x -c 'cat /proc/cpuinfo' + C:\\tools\\cygwin\\bin\\bash -l -x -c 'python3.8 -m pip install tox' + C:\\tools\\cygwin\\bin\\bash -l -x -c 'cd $(cygpath -u "$GITHUB_WORKSPACE") && PREFIX="${{ env.SAGE_LOCAL }}" tox -e local-cygwin-choco-${{ matrix.pkgs }} -- $TARGETS' + - name: Prepare logs artifact + shell: bash + run: | + mkdir -p "artifacts/$LOGS_ARTIFACT_NAME"; for a in "${{ env.SAGE_LOCAL }}"/var/tmp/sage/build/*; do if [ -d "$a" ]; then tar -c --remove-files -f "artifacts/$LOGS_ARTIFACT_NAME/$(basename "$a").tar" "$a"; fi; done; cp -r logs/* "artifacts/$LOGS_ARTIFACT_NAME" + if: always() + - uses: actions/upload-artifact@v2 + with: + path: artifacts + name: ${{ env.LOGS_ARTIFACT_NAME }} + if: always() + - name: Print out logs for immediate inspection + # The markup in the output is a GitHub Actions logging command + # https://help.github.com/en/actions/automating-your-workflow-with-github-actions/development-tools-for-github-actions + shell: bash + run: | + find "artifacts/$LOGS_ARTIFACT_NAME" -type f -name "*.log" -exec sh -c 'if tail -20 "{}" 2>/dev/null | grep "^Error" >/dev/null; then echo :":"error file={}:":" ==== LOG FILE {} CONTAINS AN ERROR ====; cat {} ; fi' \; + if: always() + - name: Prepare sage-local artifact + # We specifically use the cygwin tar so that symlinks are saved/restored correctly on Windows. + # We remove the $SAGE_LOCAL/lib64 link, which will be recreated by the next stage. + run: | + C:\\tools\\cygwin\\bin\\bash -l -c 'cd $(cygpath -u "$GITHUB_WORKSPACE") && rm -f "${{ env.SAGE_LOCAL }}"/lib64; tar -cf /tmp/sage-local-${{ env.STAGE }}.tar --listed-incremental=/tmp/sage-local.snar "${{ env.SAGE_LOCAL }}"' + if: always() + - uses: actions/upload-artifact@v2 + with: + path: C:\\tools\\cygwin\\tmp\\sage-local-${{ env.STAGE }}.tar + name: ${{ env.LOCAL_ARTIFACT_NAME }} + if: always() + +############################################## stage-iv ########################################## + + cygwin-stage-iv: + env: + STAGE: iv + PREVIOUS_STAGES: iii-* + TARGETS: build + LOCAL_ARTIFACT_NAME: sage-local-commit-${{ github.sha }}-cygwin-${{ matrix.pkgs }} + LOGS_ARTIFACT_NAME: logs-commit-${{ github.sha }}-cygwin-${{ matrix.pkgs }} + + needs: [cygwin-stage-iii-a, cygwin-stage-iii-b] + + runs-on: windows-latest + + continue-on-error: true + + strategy: + fail-fast: false + matrix: + pkgs: [minimal] + steps: + - run: | + git config --global core.autocrlf false + git config --global core.symlinks true + - uses: actions/checkout@v1 + - name: install cygwin and test prerequisites with choco + shell: bash {0} + run: | + choco --version + PACKAGES="python39 python39-pip" + choco install $PACKAGES --source cygwin + - uses: actions/download-artifact@v2 + with: + name: ${{ env.LOCAL_ARTIFACT_NAME }} + path: C:\\tools\\cygwin\\tmp + - name: Extract sage-local artifact + run: | + C:\\tools\\cygwin\\bin\\dash -l -c 'cd $(cygpath -u "$GITHUB_WORKSPACE") && .github/workflows/extract-sage-local.sh /tmp/sage-local-*.tar && tar --create --listed-incremental=/tmp/sage-local.snar --file /dev/null "${{ env.SAGE_LOCAL }}"' + - name: tox + run: | + C:\\tools\\cygwin\\bin\\bash -l -x -c 'cat /proc/cpuinfo' + C:\\tools\\cygwin\\bin\\bash -l -x -c 'python3.8 -m pip install tox' + C:\\tools\\cygwin\\bin\\bash -l -x -c 'cd $(cygpath -u "$GITHUB_WORKSPACE") && PREFIX="${{ env.SAGE_LOCAL }}" tox -e local-cygwin-choco-${{ matrix.pkgs }} -- $TARGETS' + - name: Prepare logs artifact + shell: bash + run: | + mkdir -p "artifacts/$LOGS_ARTIFACT_NAME"; for a in "${{ env.SAGE_LOCAL }}"/var/tmp/sage/build/*; do if [ -d "$a" ]; then tar -c --remove-files -f "artifacts/$LOGS_ARTIFACT_NAME/$(basename "$a").tar" "$a"; fi; done; cp -r logs/* "artifacts/$LOGS_ARTIFACT_NAME" + if: always() + - uses: actions/upload-artifact@v2 + with: + path: artifacts + name: ${{ env.LOGS_ARTIFACT_NAME }} + if: always() + - name: Print out logs for immediate inspection + # The markup in the output is a GitHub Actions logging command + # https://help.github.com/en/actions/automating-your-workflow-with-github-actions/development-tools-for-github-actions + shell: bash + run: | + find "artifacts/$LOGS_ARTIFACT_NAME" -type f -name "*.log" -exec sh -c 'if tail -20 "{}" 2>/dev/null | grep "^Error" >/dev/null; then echo :":"error file={}:":" ==== LOG FILE {} CONTAINS AN ERROR ====; cat {} ; fi' \; + if: always() + - name: Prepare sage-local artifact + # We specifically use the cygwin tar so that symlinks are saved/restored correctly on Windows. + # We remove the $SAGE_LOCAL/lib64 link, which will be recreated by the next stage. + run: | + C:\\tools\\cygwin\\bin\\bash -l -c 'cd $(cygpath -u "$GITHUB_WORKSPACE") && rm -f "${{ env.SAGE_LOCAL }}"/lib64; tar -cf /tmp/sage-local-${{ env.STAGE }}.tar --listed-incremental=/tmp/sage-local.snar "${{ env.SAGE_LOCAL }}"' + if: always() + - uses: actions/upload-artifact@v2 + with: + path: C:\\tools\\cygwin\\tmp\\sage-local-${{ env.STAGE }}.tar + name: ${{ env.LOCAL_ARTIFACT_NAME }} + if: always() + +############################################## stage-v ########################################### + + cygwin-stage-v-a: + env: + STAGE: v-a + PREVIOUS_STAGES: iv + TARGETS: ptest-nodoc + LOCAL_ARTIFACT_NAME: sage-local-commit-${{ github.sha }}-cygwin-${{ matrix.pkgs }} + LOGS_ARTIFACT_NAME: logs-commit-${{ github.sha }}-cygwin-${{ matrix.pkgs }} + + needs: [cygwin-stage-iv] + + runs-on: windows-latest + + strategy: + fail-fast: false + matrix: + pkgs: [minimal] + steps: + - run: | + git config --global core.autocrlf false + git config --global core.symlinks true + - uses: actions/checkout@v1 + - name: install cygwin and test prerequisites with choco + shell: bash {0} + run: | + choco --version + PACKAGES="python39 python39-pip" + choco install $PACKAGES --source cygwin + - uses: actions/download-artifact@v2 + with: + name: ${{ env.LOCAL_ARTIFACT_NAME }} + path: C:\\tools\\cygwin\\tmp + - name: Extract sage-local artifact + run: | + C:\\tools\\cygwin\\bin\\dash -l -c 'cd $(cygpath -u "$GITHUB_WORKSPACE") && .github/workflows/extract-sage-local.sh /tmp/sage-local-*.tar && tar --create --listed-incremental=/tmp/sage-local.snar --file /dev/null "${{ env.SAGE_LOCAL }}"' + - name: tox + run: | + C:\\tools\\cygwin\\bin\\bash -l -x -c 'cat /proc/cpuinfo' + C:\\tools\\cygwin\\bin\\bash -l -x -c 'python3.8 -m pip install tox' + C:\\tools\\cygwin\\bin\\bash -l -x -c 'cd $(cygpath -u "$GITHUB_WORKSPACE") && PREFIX="${{ env.SAGE_LOCAL }}" tox -e local-cygwin-choco-${{ matrix.pkgs }} -- $TARGETS' + - name: Prepare logs artifact + shell: bash + run: | + mkdir -p "artifacts/$LOGS_ARTIFACT_NAME"; for a in "${{ env.SAGE_LOCAL }}"/var/tmp/sage/build/*; do if [ -d "$a" ]; then tar -c --remove-files -f "artifacts/$LOGS_ARTIFACT_NAME/$(basename "$a").tar" "$a"; fi; done; cp -r logs/* "artifacts/$LOGS_ARTIFACT_NAME" + if: always() + - uses: actions/upload-artifact@v2 + with: + path: artifacts + name: ${{ env.LOGS_ARTIFACT_NAME }} + if: always() + - name: Print out logs for immediate inspection + # The markup in the output is a GitHub Actions logging command + # https://help.github.com/en/actions/automating-your-workflow-with-github-actions/development-tools-for-github-actions + shell: bash + run: | + find "artifacts/$LOGS_ARTIFACT_NAME" -type f -name "*.log" -exec sh -c 'if tail -20 "{}" 2>/dev/null | grep "^Error" >/dev/null; then echo :":"error file={}:":" ==== LOG FILE {} CONTAINS AN ERROR ====; cat {} ; fi' \; + if: always() + - name: Prepare sage-local artifact + # We specifically use the cygwin tar so that symlinks are saved/restored correctly on Windows. + # We remove the $SAGE_LOCAL/lib64 link, which will be recreated by the next stage. + run: | + C:\\tools\\cygwin\\bin\\bash -l -c 'cd $(cygpath -u "$GITHUB_WORKSPACE") && rm -f "${{ env.SAGE_LOCAL }}"/lib64; tar -cf /tmp/sage-local-${{ env.STAGE }}.tar --listed-incremental=/tmp/sage-local.snar "${{ env.SAGE_LOCAL }}"' + if: always() + - uses: actions/upload-artifact@v2 + with: + path: C:\\tools\\cygwin\\tmp\\sage-local-${{ env.STAGE }}.tar + name: ${{ env.LOCAL_ARTIFACT_NAME }} + if: always() + + cygwin-stage-v-b: + env: + STAGE: v-b + PREVIOUS_STAGES: iv + TARGETS: 4ti2 pynormaliz topcom lrslib latte_int cryptominisat + LOCAL_ARTIFACT_NAME: sage-local-commit-${{ github.sha }}-cygwin-${{ matrix.pkgs }} + LOGS_ARTIFACT_NAME: logs-commit-${{ github.sha }}-cygwin-${{ matrix.pkgs }} + + needs: [cygwin-stage-iv] + + runs-on: windows-latest + + strategy: + fail-fast: false + matrix: + pkgs: [minimal] + steps: + - run: | + git config --global core.autocrlf false + git config --global core.symlinks true + - uses: actions/checkout@v1 + - name: install cygwin and test prerequisites with choco + shell: bash {0} + run: | + choco --version + PACKAGES="python39 python39-pip" + choco install $PACKAGES --source cygwin + - uses: actions/download-artifact@v2 + with: + name: ${{ env.LOCAL_ARTIFACT_NAME }} + path: C:\\tools\\cygwin\\tmp + - name: Extract sage-local artifact + run: | + C:\\tools\\cygwin\\bin\\dash -l -c 'cd $(cygpath -u "$GITHUB_WORKSPACE") && .github/workflows/extract-sage-local.sh /tmp/sage-local-*.tar && tar --create --listed-incremental=/tmp/sage-local.snar --file /dev/null "${{ env.SAGE_LOCAL }}"' + - name: tox + run: | + C:\\tools\\cygwin\\bin\\bash -l -x -c 'cat /proc/cpuinfo' + C:\\tools\\cygwin\\bin\\bash -l -x -c 'python3.8 -m pip install tox' + C:\\tools\\cygwin\\bin\\bash -l -x -c 'cd $(cygpath -u "$GITHUB_WORKSPACE") && PREFIX="${{ env.SAGE_LOCAL }}" tox -e local-cygwin-choco-${{ matrix.pkgs }} -- $TARGETS' + - name: Prepare logs artifact + shell: bash + run: | + mkdir -p "artifacts/$LOGS_ARTIFACT_NAME"; for a in "${{ env.SAGE_LOCAL }}"/var/tmp/sage/build/*; do if [ -d "$a" ]; then tar -c --remove-files -f "artifacts/$LOGS_ARTIFACT_NAME/$(basename "$a").tar" "$a"; fi; done; cp -r logs/* "artifacts/$LOGS_ARTIFACT_NAME" + if: always() + - uses: actions/upload-artifact@v2 + with: + path: artifacts + name: ${{ env.LOGS_ARTIFACT_NAME }} + if: always() + - name: Print out logs for immediate inspection + # The markup in the output is a GitHub Actions logging command + # https://help.github.com/en/actions/automating-your-workflow-with-github-actions/development-tools-for-github-actions + shell: bash + run: | + find "artifacts/$LOGS_ARTIFACT_NAME" -type f -name "*.log" -exec sh -c 'if tail -20 "{}" 2>/dev/null | grep "^Error" >/dev/null; then echo :":"error file={}:":" ==== LOG FILE {} CONTAINS AN ERROR ====; cat {} ; fi' \; + if: always() + - name: Prepare sage-local artifact + # We specifically use the cygwin tar so that symlinks are saved/restored correctly on Windows. + # We remove the $SAGE_LOCAL/lib64 link, which will be recreated by the next stage. + run: | + C:\\tools\\cygwin\\bin\\bash -l -c 'cd $(cygpath -u "$GITHUB_WORKSPACE") && rm -f "${{ env.SAGE_LOCAL }}"/lib64; tar -cf /tmp/sage-local-${{ env.STAGE }}.tar --listed-incremental=/tmp/sage-local.snar "${{ env.SAGE_LOCAL }}"' + if: always() + - uses: actions/upload-artifact@v2 + with: + path: C:\\tools\\cygwin\\tmp\\sage-local-${{ env.STAGE }}.tar + name: ${{ env.LOCAL_ARTIFACT_NAME }} + if: always() + + cygwin-stage-v-c: + env: + STAGE: v-c + PREVIOUS_STAGES: iv + TARGETS: sage_numerical_backends_coin + LOCAL_ARTIFACT_NAME: sage-local-commit-${{ github.sha }}-cygwin-${{ matrix.pkgs }} + LOGS_ARTIFACT_NAME: logs-commit-${{ github.sha }}-cygwin-${{ matrix.pkgs }} + + needs: [cygwin-stage-iv] + + runs-on: windows-latest + + strategy: + fail-fast: false + matrix: + pkgs: [minimal] + steps: + - run: | + git config --global core.autocrlf false + git config --global core.symlinks true + - uses: actions/checkout@v1 + - name: install cygwin and test prerequisites with choco + shell: bash {0} + run: | + choco --version + PACKAGES="python39 python39-pip" + choco install $PACKAGES --source cygwin + - uses: actions/download-artifact@v2 + with: + name: ${{ env.LOCAL_ARTIFACT_NAME }} + path: C:\\tools\\cygwin\\tmp + - name: Extract sage-local artifact + run: | + C:\\tools\\cygwin\\bin\\dash -l -c 'cd $(cygpath -u "$GITHUB_WORKSPACE") && .github/workflows/extract-sage-local.sh /tmp/sage-local-*.tar && tar --create --listed-incremental=/tmp/sage-local.snar --file /dev/null "${{ env.SAGE_LOCAL }}"' + - name: tox + run: | + C:\\tools\\cygwin\\bin\\bash -l -x -c 'cat /proc/cpuinfo' + C:\\tools\\cygwin\\bin\\bash -l -x -c 'python3.8 -m pip install tox' + C:\\tools\\cygwin\\bin\\bash -l -x -c 'cd $(cygpath -u "$GITHUB_WORKSPACE") && PREFIX="${{ env.SAGE_LOCAL }}" tox -e local-cygwin-choco-${{ matrix.pkgs }} -- $TARGETS' + - name: Prepare logs artifact + shell: bash + run: | + mkdir -p "artifacts/$LOGS_ARTIFACT_NAME"; for a in "${{ env.SAGE_LOCAL }}"/var/tmp/sage/build/*; do if [ -d "$a" ]; then tar -c --remove-files -f "artifacts/$LOGS_ARTIFACT_NAME/$(basename "$a").tar" "$a"; fi; done; cp -r logs/* "artifacts/$LOGS_ARTIFACT_NAME" + if: always() + - uses: actions/upload-artifact@v2 + with: + path: artifacts + name: ${{ env.LOGS_ARTIFACT_NAME }} + if: always() + - name: Print out logs for immediate inspection + # The markup in the output is a GitHub Actions logging command + # https://help.github.com/en/actions/automating-your-workflow-with-github-actions/development-tools-for-github-actions + shell: bash + run: | + find "artifacts/$LOGS_ARTIFACT_NAME" -type f -name "*.log" -exec sh -c 'if tail -20 "{}" 2>/dev/null | grep "^Error" >/dev/null; then echo :":"error file={}:":" ==== LOG FILE {} CONTAINS AN ERROR ====; cat {} ; fi' \; + if: always() + - name: Prepare sage-local artifact + # We specifically use the cygwin tar so that symlinks are saved/restored correctly on Windows. + # We remove the $SAGE_LOCAL/lib64 link, which will be recreated by the next stage. + run: | + C:\\tools\\cygwin\\bin\\bash -l -c 'cd $(cygpath -u "$GITHUB_WORKSPACE") && rm -f "${{ env.SAGE_LOCAL }}"/lib64; tar -cf /tmp/sage-local-${{ env.STAGE }}.tar --listed-incremental=/tmp/sage-local.snar "${{ env.SAGE_LOCAL }}"' + if: always() + - uses: actions/upload-artifact@v2 + with: + path: C:\\tools\\cygwin\\tmp\\sage-local-${{ env.STAGE }}.tar + name: ${{ env.LOCAL_ARTIFACT_NAME }} + if: always() + + cygwin-stage-v-d: + env: + STAGE: v-d + PREVIOUS_STAGES: iv + TARGETS: qepcad barvinok isl qhull primecount plantri kenzo libsemigroups mcqd meataxe mpfrcx openssl p_group_cohomology rst2ipynb sirocco tdlib tides + LOCAL_ARTIFACT_NAME: sage-local-commit-${{ github.sha }}-cygwin-${{ matrix.pkgs }} + LOGS_ARTIFACT_NAME: logs-commit-${{ github.sha }}-cygwin-${{ matrix.pkgs }} + + needs: [cygwin-stage-iv] + + runs-on: windows-latest + + strategy: + fail-fast: false + matrix: + pkgs: [minimal] + steps: + - run: | + git config --global core.autocrlf false + git config --global core.symlinks true + - uses: actions/checkout@v1 + - name: install cygwin and test prerequisites with choco + shell: bash {0} + run: | + choco --version + PACKAGES="python39 python39-pip" + choco install $PACKAGES --source cygwin + - uses: actions/download-artifact@v2 + with: + name: ${{ env.LOCAL_ARTIFACT_NAME }} + path: C:\\tools\\cygwin\\tmp + - name: Extract sage-local artifact + run: | + C:\\tools\\cygwin\\bin\\dash -l -c 'cd $(cygpath -u "$GITHUB_WORKSPACE") && .github/workflows/extract-sage-local.sh /tmp/sage-local-*.tar && tar --create --listed-incremental=/tmp/sage-local.snar --file /dev/null "${{ env.SAGE_LOCAL }}"' + - name: tox + run: | + C:\\tools\\cygwin\\bin\\bash -l -x -c 'cat /proc/cpuinfo' + C:\\tools\\cygwin\\bin\\bash -l -x -c 'python3.8 -m pip install tox' + C:\\tools\\cygwin\\bin\\bash -l -x -c 'cd $(cygpath -u "$GITHUB_WORKSPACE") && PREFIX="${{ env.SAGE_LOCAL }}" tox -e local-cygwin-choco-${{ matrix.pkgs }} -- $TARGETS' + - name: Prepare logs artifact + shell: bash + run: | + mkdir -p "artifacts/$LOGS_ARTIFACT_NAME"; for a in "${{ env.SAGE_LOCAL }}"/var/tmp/sage/build/*; do if [ -d "$a" ]; then tar -c --remove-files -f "artifacts/$LOGS_ARTIFACT_NAME/$(basename "$a").tar" "$a"; fi; done; cp -r logs/* "artifacts/$LOGS_ARTIFACT_NAME" + if: always() + - uses: actions/upload-artifact@v2 + with: + path: artifacts + name: ${{ env.LOGS_ARTIFACT_NAME }} + if: always() + - name: Print out logs for immediate inspection + # The markup in the output is a GitHub Actions logging command + # https://help.github.com/en/actions/automating-your-workflow-with-github-actions/development-tools-for-github-actions + shell: bash + run: | + find "artifacts/$LOGS_ARTIFACT_NAME" -type f -name "*.log" -exec sh -c 'if tail -20 "{}" 2>/dev/null | grep "^Error" >/dev/null; then echo :":"error file={}:":" ==== LOG FILE {} CONTAINS AN ERROR ====; cat {} ; fi' \; + if: always() + - name: Prepare sage-local artifact + # We specifically use the cygwin tar so that symlinks are saved/restored correctly on Windows. + # We remove the local/lib64 link, which will be recreated by the next stage. + run: | + C:\\tools\\cygwin\\bin\\bash -l -c 'cd $(cygpath -u "$GITHUB_WORKSPACE") && rm -f "${{ env.SAGE_LOCAL }}"/lib64; tar -cf /tmp/sage-local-${{ env.STAGE }}.tar --listed-incremental=/tmp/sage-local.snar "${{ env.SAGE_LOCAL }}"' + if: always() + - uses: actions/upload-artifact@v2 + with: + path: C:\\tools\\cygwin\\tmp\\sage-local-${{ env.STAGE }}.tar + name: ${{ env.LOCAL_ARTIFACT_NAME }} + if: always() + + cygwin-stage-v-e: + env: + STAGE: v-e + PREVIOUS_STAGES: iv + TARGETS: doc-html + LOCAL_ARTIFACT_NAME: sage-local-commit-${{ github.sha }}-cygwin-${{ matrix.pkgs }} + LOGS_ARTIFACT_NAME: logs-commit-${{ github.sha }}-cygwin-${{ matrix.pkgs }} + + needs: [cygwin-stage-iv] + + runs-on: windows-latest + + strategy: + fail-fast: false + matrix: + pkgs: [minimal] + steps: + - run: | + git config --global core.autocrlf false + git config --global core.symlinks true + - uses: actions/checkout@v1 + - name: install cygwin and test prerequisites with choco + shell: bash {0} + run: | + choco --version + PACKAGES="python39 python39-pip" + choco install $PACKAGES --source cygwin + - uses: actions/download-artifact@v2 + with: + name: ${{ env.LOCAL_ARTIFACT_NAME }} + path: C:\\tools\\cygwin\\tmp + - name: Extract sage-local artifact + run: | + C:\\tools\\cygwin\\bin\\dash -l -c 'cd $(cygpath -u "$GITHUB_WORKSPACE") && .github/workflows/extract-sage-local.sh /tmp/sage-local-*.tar && tar --create --listed-incremental=/tmp/sage-local.snar --file /dev/null "${{ env.SAGE_LOCAL }}"' + - name: tox + run: | + C:\\tools\\cygwin\\bin\\bash -l -x -c 'cat /proc/cpuinfo' + C:\\tools\\cygwin\\bin\\bash -l -x -c 'python3.8 -m pip install tox' + C:\\tools\\cygwin\\bin\\bash -l -x -c 'cd $(cygpath -u "$GITHUB_WORKSPACE") && PREFIX="${{ env.SAGE_LOCAL }}" tox -e local-cygwin-choco-${{ matrix.pkgs }} -- $TARGETS' + - name: Prepare logs artifact + shell: bash + run: | + mkdir -p "artifacts/$LOGS_ARTIFACT_NAME"; for a in "${{ env.SAGE_LOCAL }}"/var/tmp/sage/build/*; do if [ -d "$a" ]; then tar -c --remove-files -f "artifacts/$LOGS_ARTIFACT_NAME/$(basename "$a").tar" "$a"; fi; done; cp -r logs/* "artifacts/$LOGS_ARTIFACT_NAME" + if: always() + - uses: actions/upload-artifact@v2 + with: + path: artifacts + name: ${{ env.LOGS_ARTIFACT_NAME }} + if: always() + - name: Print out logs for immediate inspection + # The markup in the output is a GitHub Actions logging command + # https://help.github.com/en/actions/automating-your-workflow-with-github-actions/development-tools-for-github-actions + shell: bash + run: | + find "artifacts/$LOGS_ARTIFACT_NAME" -type f -name "*.log" -exec sh -c 'if tail -20 "{}" 2>/dev/null | grep "^Error" >/dev/null; then echo :":"error file={}:":" ==== LOG FILE {} CONTAINS AN ERROR ====; cat {} ; fi' \; + if: always() + - name: Prepare sage-local artifact + # We specifically use the cygwin tar so that symlinks are saved/restored correctly on Windows. + # We remove the local/lib64 link, which will be recreated by the next stage. + run: | + C:\\tools\\cygwin\\bin\\bash -l -c 'cd $(cygpath -u "$GITHUB_WORKSPACE") && rm -f "${{ env.SAGE_LOCAL }}"/lib64; tar -cf /tmp/sage-local-${{ env.STAGE }}.tar --listed-incremental=/tmp/sage-local.snar "${{ env.SAGE_LOCAL }}"' + if: always() + - uses: actions/upload-artifact@v2 + with: + path: C:\\tools\\cygwin\\tmp\\sage-local-${{ env.STAGE }}.tar + name: ${{ env.LOCAL_ARTIFACT_NAME }} + if: always() diff --git a/.github/workflows/ci-cygwin-standard.yml b/.github/workflows/ci-cygwin-standard.yml index 53c674028ef..32efd7f8a4a 100644 --- a/.github/workflows/ci-cygwin-standard.yml +++ b/.github/workflows/ci-cygwin-standard.yml @@ -59,11 +59,13 @@ jobs: needs: [cygwin-stage-i-a, cygwin-stage-i-b] cygwin-stage-ii-e: - uses: ./.github/workflows/cygwin.yml - with: - stage: ii-e - previous_stages: i-* - targets: threejs tachyon pillow jmol m4rie sympy lrcalc lcalc symmetrica cliquer libbraiding planarity rw elliptic_curves combinatorial_designs sympow + env: + STAGE: ii-e + PREVIOUS_STAGES: i-* + TARGETS: threejs tachyon pillow jmol m4rie sympy lrcalc lcalc symmetrica cliquer libbraiding planarity rw elliptic_curves combinatorial_designs sympow + LOCAL_ARTIFACT_NAME: sage-local-commit-${{ github.sha }}-cygwin-${{ matrix.pkgs }} + LOGS_ARTIFACT_NAME: logs-commit-${{ github.sha }}-cygwin-${{ matrix.pkgs }} + needs: [cygwin-stage-i-a, cygwin-stage-i-b] ############################################## stage-iii ########################################## diff --git a/.github/workflows/ci-linux.yml b/.github/workflows/ci-linux.yml index aca56f9b49c..bd9821c1e0c 100644 --- a/.github/workflows/ci-linux.yml +++ b/.github/workflows/ci-linux.yml @@ -162,3 +162,41 @@ jobs: ["maximal"] docker_targets: "with-targets-optional" targets_optional: '$(echo $(export PATH=build/bin:$PATH && sage-package list :experimental: --has-file "spkg-install.in|spkg-install|requirements.txt" --no-file "huge|has_nonfree_dependencies" | grep -v sagemath_doc | grep ^[p-z]))' + + local-ubuntu: + + runs-on: ubuntu-latest + strategy: + fail-fast: false + max-parallel: 1 + matrix: + tox_system_factor: [conda-forge-ubuntu] + tox_packages_factor: [minimal, standard, environment, environment-optional] + env: + TOX_ENV: local-${{ matrix.tox_system_factor }}-${{ matrix.tox_packages_factor }} + LOGS_ARTIFACT_NAME: logs-commit-${{ github.sha }}-tox-local-${{ matrix.tox_system_factor }}-${{ matrix.tox_packages_factor }} + steps: + - uses: actions/checkout@v3 + - name: Install test prerequisites + run: | + sudo DEBIAN_FRONTEND=noninteractive apt-get update + sudo DEBIAN_FRONTEND=noninteractive apt-get install tox + - name: Build and test with tox + # We use a high parallelization on purpose in order to catch possible parallelization bugs in the build scripts. + # For doctesting, we use a lower parallelization to avoid timeouts. + run: | + MAKE="make -j12" tox -e $TOX_ENV -- SAGE_NUM_THREADS=4 $TARGETS + - name: Prepare logs artifact + run: | + mkdir -p "artifacts/$LOGS_ARTIFACT_NAME"; cp -r .tox/*/log "artifacts/$LOGS_ARTIFACT_NAME" + if: always() + - uses: actions/upload-artifact@v3 + with: + path: artifacts + name: ${{ env.LOGS_ARTIFACT_NAME }} + if: always() + - name: Print out logs for immediate inspection + # and markup the output with GitHub Actions logging commands + run: | + .github/workflows/scan-logs.sh "artifacts/$LOGS_ARTIFACT_NAME" + if: always() diff --git a/.github/workflows/doc-build.yml b/.github/workflows/doc-build.yml index 1cc9cf8cd3f..0b17c199ac4 100644 --- a/.github/workflows/doc-build.yml +++ b/.github/workflows/doc-build.yml @@ -15,13 +15,14 @@ jobs: build-docs: runs-on: ubuntu-latest container: ghcr.io/sagemath/sage/sage-docker-ubuntu-focal-standard-with-targets:dev + env: + CAN_DEPLOY: ${{ secrets.NETLIFY_AUTH_TOKEN != '' }} steps: - name: Checkout uses: actions/checkout@v3 - name: Prepare run: | - apt-get update && apt-get install -y zip # Reuse built SAGE_LOCAL contained in the Docker image ./bootstrap ./configure --enable-build-as-root --prefix=/sage/local --with-sage-venv --enable-download-from-upstream-url @@ -33,17 +34,43 @@ jobs: SAGE_NUM_THREADS: 2 - name: Copy docs + if: env.CAN_DEPLOY == 'true' run: | # For some reason the deploy step below cannot find /sage/... # So copy everything from there to local folder # We also need to replace the symlinks because netlify is not following them mkdir -p ./docs cp -r -L /sage/local/share/doc/sage/html/en/* ./docs - # Zip everything for increased performance - zip -r docs.zip docs - - name: Upload docs - uses: actions/upload-artifact@v3 + - name: Deploy to Netlify preview + id: preview-netlify + if: env.CAN_DEPLOY == 'true' && github.ref != 'refs/heads/develop' + uses: netlify/actions/cli@master with: - name: docs - path: docs.zip + args: deploy --dir=docs --alias="${NETLIFY_ALIAS}" + env: + # Set deployment url to commit hash to easily link from the trac. + # We could also set NETLIFY_ALIAS to the branch name. + # However, netlify currently doesn't support updates to a deployment with the same alias + # https://github.com/netlify/cli/issues/948 + # https://github.com/netlify/cli/issues/1984 + # Note that even if this feature is implemented, one would also need to first process the branch name + # to workaround the bug https://github.com/netlify/cli/issues/969. + NETLIFY_ALIAS: ${{ github.sha }} + NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} + NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} + + - name: Deploy to Netlify production + id: deploy-netlify + if: env.CAN_DEPLOY == 'true' && github.ref == 'refs/heads/develop' + uses: netlify/actions/cli@master + with: + args: deploy --dir=docs --prod + env: + NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} + NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} + + - name: Report deployment url + if: env.CAN_DEPLOY == 'true' + run: | + echo "::notice::The documentation has being automatically deployed to Netlify. %0A ✅ Preview: ${{ steps.preview-netlify.outputs.NETLIFY_URL || steps.deploy-netlify.outputs.NETLIFY_URL }}" diff --git a/.github/workflows/doc-publish.yml b/.github/workflows/doc-publish.yml deleted file mode 100644 index c7be4a46d3b..00000000000 --- a/.github/workflows/doc-publish.yml +++ /dev/null @@ -1,95 +0,0 @@ -# Triggers after the documentation build has finished, -# taking the artifact and uploading it to netlify -name: Publish documentation - -on: - workflow_run: - workflows: ["Build documentation"] - types: - - completed - -permissions: - statuses: write - checks: write - pull-requests: write - -jobs: - upload-docs: - runs-on: ubuntu-latest - if: github.event.workflow_run.conclusion == 'success' - steps: - - name: Get information about workflow origin - uses: potiuk/get-workflow-origin@v1_5 - id: source-run-info - with: - token: ${{ secrets.GITHUB_TOKEN }} - sourceRunId: ${{ github.event.workflow_run.id }} - - # Once https://github.com/actions/download-artifact/issues/172 and/or https://github.com/actions/download-artifact/issues/60 is implemented, we can use the official download-artifact action - # For now use the solution from https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#using-data-from-the-triggering-workflow - - name: Download docs - uses: actions/github-script@v3.1.0 - with: - script: | - var artifacts = await github.actions.listWorkflowRunArtifacts({ - owner: context.repo.owner, - repo: context.repo.repo, - run_id: ${{github.event.workflow_run.id }}, - }); - var matchArtifact = artifacts.data.artifacts.filter((artifact) => { - return artifact.name == "docs" - })[0]; - var download = await github.actions.downloadArtifact({ - owner: context.repo.owner, - repo: context.repo.repo, - artifact_id: matchArtifact.id, - archive_format: 'zip', - }); - var fs = require('fs'); - fs.writeFileSync('${{github.workspace}}/docs.zip', Buffer.from(download.data)); - - - name: Extract docs - run: unzip docs.zip -d docs && unzip docs/docs.zip -d docs/docs - - - name: Deploy to Netlify - id: deploy-netlify - uses: netlify/actions/cli@master - with: - args: deploy --dir=docs/docs/docs ${NETLIFY_PRODUCTION:+"--prod"} --message ${NETLIFY_MESSAGE} --alias ${NETLIFY_ALIAS} - env: - NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} - NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} - NETLIFY_PRODUCTION: ${{ github.ref == 'refs/heads/develop' }} - NETLIFY_MESSAGE: ${{ steps.source-run-info.outputs.pullRequestNumber }} - NETLIFY_ALIAS: deploy-preview-${{ steps.source-run-info.outputs.pullRequestNumber }} - - # Add deployment as status check, PR comment and annotation - # we could use the nwtgck/actions-netlify action for that, except for that it is not (yet) working in workflow_run context: https://github.com/nwtgck/actions-netlify/issues/545 - - name: Add/Update deployment status PR comment - uses: marocchino/sticky-pull-request-comment@v2 - with: - number: ${{ steps.source-run-info.outputs.pullRequestNumber }} - header: preview-comment - recreate: true - message: | - [Documentation preview for this PR](${{ steps.deploy-netlify.outputs.NETLIFY_URL }}) is ready! :tada: - Built with commit: ${{ steps.source-run-info.outputs.sourceHeadSha }} - - - name: Update deployment status PR check - uses: myrotvorets/set-commit-status-action@1.1.6 - if: ${{ always() }} - env: - DEPLOY_SUCCESS: Successfully deployed preview. - DEPLOY_FAILURE: Failed to deploy preview. - with: - token: ${{ secrets.GITHUB_TOKEN }} - status: ${{ job.status == 'success' && 'success' || 'failure' }} - sha: ${{ github.event.workflow_run.head_sha }} - context: Deploy Documentation - targetUrl: ${{ steps.deploy-netlify.outputs.NETLIFY_URL }} - description: ${{ job.status == 'success' && env.DEPLOY_SUCCESS || env.DEPLOY_FAILURE }} - - - name: Report deployment url - run: | - echo "::notice::The documentation has being automatically deployed to Netlify. %0A ✅ Preview: ${{ steps.deploy-netlify.outputs.NETLIFY_URL }}" - diff --git a/.zenodo.json b/.zenodo.json index da76244bfa7..f0ae104bab6 100644 --- a/.zenodo.json +++ b/.zenodo.json @@ -1,10 +1,10 @@ { "description": "Mirror of the Sage https://sagemath.org/ source tree", "license": "other-open", - "title": "sagemath/sage: 10.0.beta0", - "version": "10.0.beta0", + "title": "sagemath/sage: 9.8.rc1", + "version": "9.8.rc1", "upload_type": "software", - "publication_date": "2023-02-12", + "publication_date": "2023-02-05", "creators": [ { "affiliation": "SageMath.org", @@ -15,7 +15,7 @@ "related_identifiers": [ { "scheme": "url", - "identifier": "https://github.com/sagemath/sage/tree/10.0.beta0", + "identifier": "https://github.com/sagemath/sage/tree/9.8.rc1", "relation": "isSupplementTo" }, { diff --git a/VERSION.txt b/VERSION.txt index ec675a255a2..37dcf746e46 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -SageMath version 10.0.beta0, Release Date: 2023-02-12 +SageMath version 9.8.rc1, Release Date: 2023-02-05 diff --git a/build/bin/sage-bootstrap-python b/build/bin/sage-bootstrap-python index db4cea35dfd..f78e5e62a1d 100755 --- a/build/bin/sage-bootstrap-python +++ b/build/bin/sage-bootstrap-python @@ -53,7 +53,7 @@ if [ "$LC_ALL" = "C" -o "$LANG" = "C" -o "$LC_CTYPE" = "C" ]; then export LANG fi -PYTHONS="python python3 python3.12 python3.11 python3.10 python3.9 python3.8 python3.7 python2.7 python3.6 python2" +PYTHONS="python python3 python3.10 python3.9 python3.8 python3.7 python2.7 python3.6 python2" # Trac #32405: Prefer a Python that provides ssl with SNI, which allows developers # to download from upstream URLs (configure --enable-download-from-upstream-url), # in particular from PyPI, which requires SNI. diff --git a/build/pkgs/configure/checksums.ini b/build/pkgs/configure/checksums.ini index 92c2ef9e108..c51606741ff 100644 --- a/build/pkgs/configure/checksums.ini +++ b/build/pkgs/configure/checksums.ini @@ -1,4 +1,4 @@ tarball=configure-VERSION.tar.gz -sha1=fc9c71ad5be4e3197007ddb150cba47d15716d89 -md5=0a707bcc4316b8c3e3faca6330fc5dc2 -cksum=3972886119 +sha1=6e536cb217dd823f547403263fc7d1b21578eaef +md5=83b833531d8bf1689f3368c47374f5e1 +cksum=2145026758 diff --git a/build/pkgs/configure/package-version.txt b/build/pkgs/configure/package-version.txt index 61bc327050c..a471ba864c0 100644 --- a/build/pkgs/configure/package-version.txt +++ b/build/pkgs/configure/package-version.txt @@ -1 +1 @@ -785ddef6338073b27082bb675446e3ae111b3b5d +2d3c71b03b2c11caceac69da380dab3ef4374519 diff --git a/build/pkgs/ore_algebra/requirements.txt b/build/pkgs/ore_algebra/requirements.txt index 3b6d6cc56ff..656286fce86 100644 --- a/build/pkgs/ore_algebra/requirements.txt +++ b/build/pkgs/ore_algebra/requirements.txt @@ -1 +1 @@ -git+https://github.com/mkauers/ore_algebra@01c357f590685ff362c008229681ee08269457da#egg=ore_algebra +git+https://github.com/mkauers/ore_algebra@cfcb386f2cc1d3e044c71dfb149444355b16d775#egg=ore_algebra diff --git a/build/pkgs/sage_conf/install-requires.txt b/build/pkgs/sage_conf/install-requires.txt index 819432d90ff..8e67bd2cc59 100644 --- a/build/pkgs/sage_conf/install-requires.txt +++ b/build/pkgs/sage_conf/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sage-conf ~= 10.0b0 +sage-conf ~= 9.8rc1 diff --git a/build/pkgs/sage_docbuild/install-requires.txt b/build/pkgs/sage_docbuild/install-requires.txt index 73f499affef..4beda62dc3b 100644 --- a/build/pkgs/sage_docbuild/install-requires.txt +++ b/build/pkgs/sage_docbuild/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sage-docbuild ~= 10.0b0 +sage-docbuild ~= 9.8rc1 diff --git a/build/pkgs/sage_setup/install-requires.txt b/build/pkgs/sage_setup/install-requires.txt index 169a4c5d9cc..22a71c8635b 100644 --- a/build/pkgs/sage_setup/install-requires.txt +++ b/build/pkgs/sage_setup/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sage-setup ~= 10.0b0 +sage-setup ~= 9.8rc1 diff --git a/build/pkgs/sage_sws2rst/install-requires.txt b/build/pkgs/sage_sws2rst/install-requires.txt index e2b85444aca..1fae5153044 100644 --- a/build/pkgs/sage_sws2rst/install-requires.txt +++ b/build/pkgs/sage_sws2rst/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sage-sws2rst ~= 10.0b0 +sage-sws2rst ~= 9.8rc1 diff --git a/build/pkgs/sagelib/install-requires.txt b/build/pkgs/sagelib/install-requires.txt index 565dfde8395..34d23241704 100644 --- a/build/pkgs/sagelib/install-requires.txt +++ b/build/pkgs/sagelib/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagelib ~= 10.0b0 +sagelib ~= 9.8rc1 diff --git a/build/pkgs/sagemath_categories/install-requires.txt b/build/pkgs/sagemath_categories/install-requires.txt index 15c1dfbcc42..0508e16fde5 100644 --- a/build/pkgs/sagemath_categories/install-requires.txt +++ b/build/pkgs/sagemath_categories/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-categories ~= 10.0b0 +sagemath-categories ~= 9.8rc1 diff --git a/build/pkgs/sagemath_environment/install-requires.txt b/build/pkgs/sagemath_environment/install-requires.txt index 73ef51c4e92..4324c3c7f23 100644 --- a/build/pkgs/sagemath_environment/install-requires.txt +++ b/build/pkgs/sagemath_environment/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-environment ~= 10.0b0 +sagemath-environment ~= 9.8rc1 diff --git a/build/pkgs/sagemath_objects/install-requires.txt b/build/pkgs/sagemath_objects/install-requires.txt index a03b35802fe..85d759ddcfe 100644 --- a/build/pkgs/sagemath_objects/install-requires.txt +++ b/build/pkgs/sagemath_objects/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-objects ~= 10.0b0 +sagemath-objects ~= 9.8rc1 diff --git a/build/pkgs/sagemath_repl/install-requires.txt b/build/pkgs/sagemath_repl/install-requires.txt index 306890d9db9..753d8f14b63 100644 --- a/build/pkgs/sagemath_repl/install-requires.txt +++ b/build/pkgs/sagemath_repl/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-repl ~= 10.0b0 +sagemath-repl ~= 9.8rc1 diff --git a/build/pkgs/singular/checksums.ini b/build/pkgs/singular/checksums.ini index 313463d2fea..2e33a405d36 100644 --- a/build/pkgs/singular/checksums.ini +++ b/build/pkgs/singular/checksums.ini @@ -1,5 +1,5 @@ tarball=singular-VERSION.tar.gz -sha1=28bb3ee97ef48d04dfa96de182fd93eebe08426c -md5=fc0a4f5720dadba45a52ee94324ce00c -cksum=1573851737 +sha1=6c2b622d3681e2de3d58d30c654d43d3e32b720c +md5=abb1e37c794472e7760655358ab66054 +cksum=17455733 upstream_url=ftp://jim.mathematik.uni-kl.de/pub/Math/Singular/SOURCES/4-3-1/singular-VERSION.tar.gz diff --git a/build/pkgs/singular/package-version.txt b/build/pkgs/singular/package-version.txt index 66e2bede53a..11300c77e7d 100644 --- a/build/pkgs/singular/package-version.txt +++ b/build/pkgs/singular/package-version.txt @@ -1 +1 @@ -4.3.1p3 +4.3.1p1 diff --git a/pkgs/sage-conf/VERSION.txt b/pkgs/sage-conf/VERSION.txt index 39516ebfda0..6659f15b775 100644 --- a/pkgs/sage-conf/VERSION.txt +++ b/pkgs/sage-conf/VERSION.txt @@ -1 +1 @@ -10.0.beta0 +9.8.rc1 diff --git a/pkgs/sage-conf_pypi/VERSION.txt b/pkgs/sage-conf_pypi/VERSION.txt index 39516ebfda0..6659f15b775 100644 --- a/pkgs/sage-conf_pypi/VERSION.txt +++ b/pkgs/sage-conf_pypi/VERSION.txt @@ -1 +1 @@ -10.0.beta0 +9.8.rc1 diff --git a/pkgs/sage-docbuild/VERSION.txt b/pkgs/sage-docbuild/VERSION.txt index 39516ebfda0..6659f15b775 100644 --- a/pkgs/sage-docbuild/VERSION.txt +++ b/pkgs/sage-docbuild/VERSION.txt @@ -1 +1 @@ -10.0.beta0 +9.8.rc1 diff --git a/pkgs/sage-setup/VERSION.txt b/pkgs/sage-setup/VERSION.txt index 39516ebfda0..6659f15b775 100644 --- a/pkgs/sage-setup/VERSION.txt +++ b/pkgs/sage-setup/VERSION.txt @@ -1 +1 @@ -10.0.beta0 +9.8.rc1 diff --git a/pkgs/sage-sws2rst/VERSION.txt b/pkgs/sage-sws2rst/VERSION.txt index 39516ebfda0..6659f15b775 100644 --- a/pkgs/sage-sws2rst/VERSION.txt +++ b/pkgs/sage-sws2rst/VERSION.txt @@ -1 +1 @@ -10.0.beta0 +9.8.rc1 diff --git a/pkgs/sagemath-categories/VERSION.txt b/pkgs/sagemath-categories/VERSION.txt index 39516ebfda0..6659f15b775 100644 --- a/pkgs/sagemath-categories/VERSION.txt +++ b/pkgs/sagemath-categories/VERSION.txt @@ -1 +1 @@ -10.0.beta0 +9.8.rc1 diff --git a/pkgs/sagemath-environment/VERSION.txt b/pkgs/sagemath-environment/VERSION.txt index 39516ebfda0..6659f15b775 100644 --- a/pkgs/sagemath-environment/VERSION.txt +++ b/pkgs/sagemath-environment/VERSION.txt @@ -1 +1 @@ -10.0.beta0 +9.8.rc1 diff --git a/pkgs/sagemath-objects/VERSION.txt b/pkgs/sagemath-objects/VERSION.txt index 39516ebfda0..6659f15b775 100644 --- a/pkgs/sagemath-objects/VERSION.txt +++ b/pkgs/sagemath-objects/VERSION.txt @@ -1 +1 @@ -10.0.beta0 +9.8.rc1 diff --git a/pkgs/sagemath-repl/VERSION.txt b/pkgs/sagemath-repl/VERSION.txt index 39516ebfda0..6659f15b775 100644 --- a/pkgs/sagemath-repl/VERSION.txt +++ b/pkgs/sagemath-repl/VERSION.txt @@ -1 +1 @@ -10.0.beta0 +9.8.rc1 diff --git a/src/.relint.yml b/src/.relint.yml index 2b49c758dc0..abadae0de28 100644 --- a/src/.relint.yml +++ b/src/.relint.yml @@ -46,9 +46,7 @@ - name: 'namespace_pkg_all_import: import from .all of a namespace package' hint: | Sage library code should not import from sage.PAC.KAGE.all when sage.PAC.KAGE is an implicit - Hint: namespace package. Type import_statements("SOME_IDENTIFIER") to find a more specific import, - Hint: or use 'sage --fiximports' to fix automatically in the source file. - # Keep in sync with SAGE_ROOT/src/sage/misc/replace_dot_all.py + Hint: namespace package. Type import_statements("SOME_IDENTIFIER") to find a more specific import. pattern: 'from\s+sage(|[.](arith|categories|combinat|ext|graphs(|[.]decompositions)|interfaces|libs|matrix|misc|numerical(|[.]backends)|rings|sets))[.]all\s+import' filePattern: '.*[.](py|pyx|pxi)$' error: false # Make this a warning instead of an error for now diff --git a/src/VERSION.txt b/src/VERSION.txt index 39516ebfda0..6659f15b775 100644 --- a/src/VERSION.txt +++ b/src/VERSION.txt @@ -1 +1 @@ -10.0.beta0 +9.8.rc1 diff --git a/src/bin/sage b/src/bin/sage index 03aec9cfbfc..e4d97835bb1 100755 --- a/src/bin/sage +++ b/src/bin/sage @@ -479,13 +479,6 @@ usage_advanced() { echo " Sage documentation for \"string\"." echo " --search_src ... -- same as --grep" echo " --search_doc ... -- same as --grepdoc" - echo " --fixdoctests file.py" - echo " -- Run doctests and replace output of failing doctests" - echo " with actual output." - echo " --fiximports " - echo " -- Replace imports from sage.PAC.KAGE.all by specific" - echo " imports when sage.PAC.KAGE is an implicit namespace" - echo " package" fi echo " --sh [...] -- run a shell with Sage environment variables" echo " as they are set in the runtime of Sage" @@ -981,11 +974,6 @@ if [ "$1" = '-startuptime' -o "$1" = '--startuptime' ]; then exec sage-startuptime.py "$@" fi -if [ "$1" = '-fiximports' -o "$1" = '--fiximports' ]; then - shift - exec sage-python -m sage.misc.replace_dot_all "$@" -fi - if [ "$1" = '-tox' -o "$1" = '--tox' ]; then shift if [ -n "$SAGE_SRC" -a -f "$SAGE_SRC/tox.ini" ]; then diff --git a/src/bin/sage-notebook b/src/bin/sage-notebook index 2e8b12e1a1c..24c7f735c2f 100755 --- a/src/bin/sage-notebook +++ b/src/bin/sage-notebook @@ -7,19 +7,20 @@ import ast import argparse import logging import textwrap + +from contextlib import contextmanager + logging.basicConfig() logger = logging.getLogger() from sage.misc.banner import banner - _system_jupyter_url = "https://doc.sagemath.org/html/en/installation/launching.html#setting-up-sagemath-as-a-jupyter-kernel-in-an-existing-jupyter-notebook-or-jupyterlab-installation" class NotebookJupyter(): def print_banner(self): - banner() print('Please wait while the Sage Jupyter Notebook server starts...') @classmethod @@ -45,7 +46,6 @@ class NotebookJupyter(): class NotebookJupyterlab(): def print_banner(self): - banner() print('Please wait while the Jupyterlab server starts...') @classmethod @@ -71,7 +71,6 @@ class NotebookJupyterlab(): class NotebookNbclassic(): def print_banner(self): - banner() print('Please wait while the Jupyterlab server starts...') @classmethod @@ -94,7 +93,6 @@ class NotebookNbclassic(): class NotebookRetrolab(): def print_banner(self): - banner() print('Please wait while the Jupyterlab server starts...') @classmethod @@ -118,7 +116,6 @@ class NotebookRetrolab(): class SageNBExport(NotebookJupyter): def print_banner(self): - banner() print('Please wait while the SageNB export server starts...') @classmethod @@ -172,7 +169,6 @@ EXAMPLES: """ - notebook_launcher = { 'default': NotebookJupyter, # change this to change the default 'ipython': NotebookJupyter, @@ -183,7 +179,6 @@ notebook_launcher = { 'export': SageNBExport, } - notebook_names = ', '.join(notebook_launcher.keys()) @@ -230,6 +225,34 @@ def trac_23428_browser_workaround(): os.environ['BROWSER'] = 'open' +@contextmanager +def sage_doc_server(): + from sage.env import SAGE_DOC_SERVER_URL + + if SAGE_DOC_SERVER_URL: + print(f'Sage doc server running at {SAGE_DOC_SERVER_URL}') + yield + else: + from functools import partial + from http.server import SimpleHTTPRequestHandler, ThreadingHTTPServer + from threading import Thread + + from sage.env import SAGE_DOC, SAGE_DOC_LOCAL_PORT as port + + server = ThreadingHTTPServer(('localhost', int(port)), + partial(SimpleHTTPRequestHandler, directory=SAGE_DOC)) + server_thread = Thread(target=server.serve_forever, name="sage_doc_server") + server_thread.start() + print(f'Sage doc server started running at http://localhost:{port}') + + try: + yield + finally: + server.shutdown() + server_thread.join() + print(f'Sage doc server stopped runnning at http://localhost:{port}') + + if __name__ == '__main__': parser = make_parser() args, unknown = parser.parse_known_args(sys.argv[1:]) @@ -270,4 +293,7 @@ if __name__ == '__main__': launcher.print_help() sys.exit(0) - launcher(unknown) + banner() + + with sage_doc_server(): + launcher(unknown) diff --git a/src/bin/sage-version.sh b/src/bin/sage-version.sh index 127b827342d..dac1c4045ef 100644 --- a/src/bin/sage-version.sh +++ b/src/bin/sage-version.sh @@ -4,6 +4,6 @@ # which stops "setup.py develop" from rewriting it as a Python file. : # This file is auto-generated by the sage-update-version script, do not edit! -SAGE_VERSION='10.0.beta0' -SAGE_RELEASE_DATE='2023-02-12' -SAGE_VERSION_BANNER='SageMath version 10.0.beta0, Release Date: 2023-02-12' +SAGE_VERSION='9.8.rc1' +SAGE_RELEASE_DATE='2023-02-05' +SAGE_VERSION_BANNER='SageMath version 9.8.rc1, Release Date: 2023-02-05' diff --git a/src/doc/en/developer/packaging_sage_library.rst b/src/doc/en/developer/packaging_sage_library.rst index 7e7a5cde56f..c792b8ee68e 100644 --- a/src/doc/en/developer/packaging_sage_library.rst +++ b/src/doc/en/developer/packaging_sage_library.rst @@ -274,10 +274,6 @@ distribution -- which then must be declared as a run-time dependency. the ``sage:`` prompt. In particular, no Sage library code should import from :mod:`sage.rings.all`. - To audit the Sage library for such imports, use ``sage --tox -e relint``. - In most cases, the imports can be fixed automatically using the - tool ``sage --fiximports``. - - Replace module-level imports by method-level imports. Note that this comes with a small runtime overhead, which can become noticeable if the method is called in tight inner loops. diff --git a/src/doc/en/reference/combinat/module_list.rst b/src/doc/en/reference/combinat/module_list.rst index 3bfa10ed3f7..cdb81324b4c 100644 --- a/src/doc/en/reference/combinat/module_list.rst +++ b/src/doc/en/reference/combinat/module_list.rst @@ -145,7 +145,6 @@ Comprehensive Module List sage/combinat/k_regular_sequence sage/combinat/k_tableau sage/combinat/kazhdan_lusztig - sage/combinat/key_polynomial sage/combinat/knutson_tao_puzzles sage/combinat/matrices/all sage/combinat/matrices/dancing_links diff --git a/src/doc/en/reference/groups/index.rst b/src/doc/en/reference/groups/index.rst index e3df953c29a..09d05d78aff 100644 --- a/src/doc/en/reference/groups/index.rst +++ b/src/doc/en/reference/groups/index.rst @@ -19,13 +19,11 @@ Groups sage/groups/cubic_braid sage/groups/indexed_free_group sage/groups/raag - sage/groups/cactus_group sage/groups/group_exp sage/groups/group_semidirect_product sage/groups/misc_gps/misc_groups sage/groups/semimonomial_transformations/semimonomial_transformation_group sage/groups/semimonomial_transformations/semimonomial_transformation - sage/groups/kernel_subgroup sage/groups/class_function sage/groups/conjugacy_classes diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst index 5a7eb0a163c..e747b14139d 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -450,10 +450,6 @@ REFERENCES: .. [BCDM2019] \T. Beyne, Y. L. Chen, C. Dobraunig, B. Mennink. *Elephant v1* (2019) https://csrc.nist.gov/CSRC/media/Projects/Lightweight-Cryptography/documents/round-1/spec-doc/elephant-spec.pdf -.. [BCL2022] Paolo Bellingeri, Hugo Chemin, and Victoria Lebed. - *Cactus groups, twin groups, and right-angled Artin groups*. - Preprint, :arxiv:`2209.08813` (2022). - .. [BeBo2009] Olivier Bernardi and Nicolas Bonichon, *Intervals in Catalan lattices and realizers of triangulations*, JCTA 116 (2009) @@ -1879,11 +1875,6 @@ REFERENCES: *Introduction to Lattices and Order*, Cambridge University Press, 1997. -.. [DJS2003] \M. Davis, T. Januszkiewicz, and R. Scott. - *Fundamental groups of blow-ups*. Selecta Math., - Adv. Math. ***177** no. 1 (2002) pp. 115-179. - :arxiv:`math/0203127`. - .. [DB1996] K. Duggal, A. Bejancu, *Lightlike Submanifolds of Semi-Riemannian Manifolds and Applications*, Mathematics and Its Applications, 1996. @@ -4489,11 +4480,6 @@ REFERENCES: of graphs*, Linear Algebra and its Applications 103 (1988), 119–131. -.. [Most2019] Jacob Mostovoy. - *The pure cactus group is residually nilpotent*. - Archiv der Math., **113** (2019). pp. 229-235. - :arxiv:`1804.09165`. - .. [MNO1994] Alexander Molev, Maxim Nazarov, and Grigori Olshanski. *Yangians and classical Lie algebras*. (1994) :arxiv:`hep-th/9409025` @@ -6113,11 +6099,6 @@ REFERENCES: pages 150--168, 1932, `available on JSTOR `_ -.. [White2015] Noah White. - *The monodromy of real Bethe vectors for the Gaudin model*. - J. Combin. Algebra, **2** no. 3 (2018). pp. 259-300. - :arxiv:`1511.04740`. - .. [Wich1997] Tim Wichmann. Der FGLM Algorithmus - verallgemeinert und implementiert in Singular Diploma Thesis (University of Kaiserslautern), 1997. @@ -6232,9 +6213,6 @@ REFERENCES: .. [Yu2007] \K. Yu, *p-adic logarithmic forms and group varieties. III.* Forum Math., 19(2):187–280, 2007. -.. [Yu2022] Runze Yu. *linearity of generalized cactus groups*. - Preprint, :arxiv:`2202.00860` (2022). - .. [Yun1976] Yun, David YY. On square-free decomposition algorithms. In Proceedings of the third ACM symposium on Symbolic and algebraic computation, pp. 26-35. ACM, 1976. diff --git a/src/doc/en/thematic_tutorials/group_theory.rst b/src/doc/en/thematic_tutorials/group_theory.rst index e9e6b23953f..9a4edca73c2 100644 --- a/src/doc/en/thematic_tutorials/group_theory.rst +++ b/src/doc/en/thematic_tutorials/group_theory.rst @@ -204,7 +204,7 @@ Experiment by running the following code several times:: sage: m = random_prime(10000) sage: n = random_prime(10000) - sage: euler_phi(m*n) == euler_phi(m) * euler_phi(n) or m == n + sage: euler_phi(m*n) == euler_phi(m) * euler_phi(n) True Feel a conjecture coming on? Can you generalize this result? diff --git a/src/sage/arith/misc.py b/src/sage/arith/misc.py index 8be5f952d68..9e2139f1841 100644 --- a/src/sage/arith/misc.py +++ b/src/sage/arith/misc.py @@ -559,7 +559,7 @@ def is_prime(n): if not isinstance(R, NumberField_generic): import warnings s = f'Testing primality in {R}, which is a field, ' \ - 'hence the result will always be False. ' + 'hence the result will always be False. ' if R is QQ: s += 'To test whether n is a prime integer, use ' \ 'is_prime(ZZ(n)) or ZZ(n).is_prime(). ' @@ -568,7 +568,6 @@ def is_prime(n): return ret - def is_pseudoprime(n): r""" Test whether ``n`` is a pseudo-prime @@ -2694,7 +2693,7 @@ def radical(n, *args, **kwds): sage: radical(0) Traceback (most recent call last): ... - ArithmeticError: radical of 0 is not defined + ArithmeticError: Radical of 0 not defined. sage: K. = QuadraticField(-1) sage: radical(K(2)) i + 1 diff --git a/src/sage/categories/coxeter_groups.py b/src/sage/categories/coxeter_groups.py index 98fe35a0ab3..0b353313517 100644 --- a/src/sage/categories/coxeter_groups.py +++ b/src/sage/categories/coxeter_groups.py @@ -236,11 +236,11 @@ def braid_group_as_finitely_presented_group(self): sage: W.braid_group_as_finitely_presented_group() Finitely presented group < S1, S2 | (S1*S2)^2*(S1^-1*S2^-1)^2 > - sage: W = ReflectionGroup(['B',3], index_set=["AA","BB","5"]) # optional - gap3 - sage: W.braid_group_as_finitely_presented_group() # optional - gap3 + sage: W = ReflectionGroup(['B',3], index_set=["AA","BB",5]) # optional - gap3 + sage: W.braid_group_as_finitely_presented_group() # optional - gap3 Finitely presented group < SAA, SBB, S5 | - (SAA*SBB)^2*(SAA^-1*SBB^-1)^2, SAA*S5*SAA^-1*S5^-1, - SBB*S5*SBB*S5^-1*SBB^-1*S5^-1 > + SAA*SBB*SAA*SBB^-1*SAA^-1*SBB^-1, SAA*S5*SAA^-1*S5^-1, + (SBB*S5)^2*(SBB^-1*S5^-1)^2 > """ from sage.groups.free_group import FreeGroup from sage.misc.misc_c import prod @@ -285,25 +285,25 @@ def braid_orbit(self, word): sage: sorted(W.braid_orbit([2,1,1,2,1])) [[1, 2, 1, 1, 2], [2, 1, 1, 2, 1], [2, 1, 2, 1, 2], [2, 2, 1, 2, 2]] - sage: W = ReflectionGroup(['A',3], index_set=["AA","BB","5"]) # optional - gap3 - sage: w = W.long_element() # optional - gap3 - sage: W.braid_orbit(w.reduced_word()) # optional - gap3 - [['BB', '5', 'AA', 'BB', '5', 'AA'], - ['5', 'BB', '5', 'AA', 'BB', '5'], - ['BB', 'AA', 'BB', '5', 'BB', 'AA'], - ['AA', '5', 'BB', 'AA', '5', 'BB'], - ['5', 'AA', 'BB', 'AA', '5', 'BB'], - ['AA', 'BB', '5', 'AA', 'BB', 'AA'], - ['AA', 'BB', 'AA', '5', 'BB', 'AA'], - ['AA', 'BB', '5', 'BB', 'AA', 'BB'], - ['BB', 'AA', '5', 'BB', 'AA', '5'], - ['BB', '5', 'AA', 'BB', 'AA', '5'], - ['AA', '5', 'BB', '5', 'AA', 'BB'], - ['5', 'BB', 'AA', '5', 'BB', '5'], - ['5', 'BB', 'AA', 'BB', '5', 'BB'], - ['5', 'AA', 'BB', '5', 'AA', 'BB'], - ['BB', '5', 'BB', 'AA', 'BB', '5'], - ['BB', 'AA', '5', 'BB', '5', 'AA']] + sage: W = ReflectionGroup(['A',3], index_set=["AA","BB",5]) # optional - gap3 + sage: w = W.long_element() # optional - gap3 + sage: W.braid_orbit(w.reduced_word()) # optional - gap3 + [['AA', 5, 'BB', 5, 'AA', 'BB'], + ['AA', 'BB', 5, 'BB', 'AA', 'BB'], + [5, 'BB', 'AA', 5, 'BB', 5], + ['BB', 5, 'AA', 'BB', 5, 'AA'], + [5, 'BB', 5, 'AA', 'BB', 5], + ['BB', 5, 'AA', 'BB', 'AA', 5], + [5, 'AA', 'BB', 'AA', 5, 'BB'], + ['BB', 'AA', 5, 'BB', 5, 'AA'], + ['AA', 'BB', 'AA', 5, 'BB', 'AA'], + [5, 'BB', 'AA', 'BB', 5, 'BB'], + ['BB', 'AA', 5, 'BB', 'AA', 5], + [5, 'AA', 'BB', 5, 'AA', 'BB'], + ['AA', 'BB', 5, 'AA', 'BB', 'AA'], + ['BB', 5, 'BB', 'AA', 'BB', 5], + ['AA', 5, 'BB', 'AA', 5, 'BB'], + ['BB', 'AA', 'BB', 5, 'BB', 'AA']] .. TODO:: @@ -1608,25 +1608,25 @@ def reduced_words(self): sage: sorted(w.reduced_words()) [[2, 3, 4, 2], [3, 2, 4, 2], [3, 4, 2, 4]] - sage: W = ReflectionGroup(['A',3], index_set=["AA","BB","5"]) # optional - gap3 - sage: w = W.long_element() # optional - gap3 - sage: w.reduced_words() # optional - gap3 - [['BB', '5', 'AA', 'BB', '5', 'AA'], - ['5', 'BB', '5', 'AA', 'BB', '5'], - ['BB', 'AA', 'BB', '5', 'BB', 'AA'], - ['AA', '5', 'BB', 'AA', '5', 'BB'], - ['5', 'AA', 'BB', 'AA', '5', 'BB'], - ['AA', 'BB', '5', 'AA', 'BB', 'AA'], - ['AA', 'BB', 'AA', '5', 'BB', 'AA'], - ['AA', 'BB', '5', 'BB', 'AA', 'BB'], - ['BB', 'AA', '5', 'BB', 'AA', '5'], - ['BB', '5', 'AA', 'BB', 'AA', '5'], - ['AA', '5', 'BB', '5', 'AA', 'BB'], - ['5', 'BB', 'AA', '5', 'BB', '5'], - ['5', 'BB', 'AA', 'BB', '5', 'BB'], - ['5', 'AA', 'BB', '5', 'AA', 'BB'], - ['BB', '5', 'BB', 'AA', 'BB', '5'], - ['BB', 'AA', '5', 'BB', '5', 'AA']] + sage: W = ReflectionGroup(['A',3], index_set=["AA","BB",5]) # optional - gap3 + sage: w = W.long_element() # optional - gap3 + sage: w.reduced_words() # optional - gap3 + [['AA', 5, 'BB', 5, 'AA', 'BB'], + ['AA', 'BB', 5, 'BB', 'AA', 'BB'], + [5, 'BB', 'AA', 5, 'BB', 5], + ['BB', 5, 'AA', 'BB', 5, 'AA'], + [5, 'BB', 5, 'AA', 'BB', 5], + ['BB', 5, 'AA', 'BB', 'AA', 5], + [5, 'AA', 'BB', 'AA', 5, 'BB'], + ['BB', 'AA', 5, 'BB', 5, 'AA'], + ['AA', 'BB', 'AA', 5, 'BB', 'AA'], + [5, 'BB', 'AA', 'BB', 5, 'BB'], + ['BB', 'AA', 5, 'BB', 'AA', 5], + [5, 'AA', 'BB', 5, 'AA', 'BB'], + ['AA', 'BB', 5, 'AA', 'BB', 'AA'], + ['BB', 5, 'BB', 'AA', 'BB', 5], + ['AA', 5, 'BB', 'AA', 5, 'BB'], + ['BB', 'AA', 'BB', 5, 'BB', 'AA']] .. TODO:: diff --git a/src/sage/categories/fields.py b/src/sage/categories/fields.py index 4bbbd08ae95..0ea91e393ff 100644 --- a/src/sage/categories/fields.py +++ b/src/sage/categories/fields.py @@ -2,7 +2,7 @@ r""" Fields """ -# **************************************************************************** +#***************************************************************************** # Copyright (C) 2005 David Kohel # William Stein # 2008 Teresa Gomez-Diaz (CNRS) @@ -10,8 +10,8 @@ # 2012-2014 Julian Rueth # # Distributed under the terms of the GNU General Public License (GPL) -# https://www.gnu.org/licenses/ -# ***************************************************************************** +# http://www.gnu.org/licenses/ +#****************************************************************************** from sage.misc.lazy_attribute import lazy_class_attribute from sage.misc.lazy_import import LazyImport @@ -22,7 +22,6 @@ from sage.structure.element import coerce_binop - class Fields(CategoryWithAxiom): """ The category of (commutative) fields, i.e. commutative rings where @@ -475,7 +474,7 @@ def _squarefree_decomposition_univariate_polynomial(self, f): if f.degree() == 0: return Factorization([], unit=f[0]) if self.characteristic() != 0: - raise NotImplementedError("square-free decomposition not implemented for this polynomial") + raise NotImplementedError("square-free decomposition not implemented for this polynomial.") factors = [] cur = f diff --git a/src/sage/categories/finite_posets.py b/src/sage/categories/finite_posets.py index b5422adfd4e..caf76e44893 100644 --- a/src/sage/categories/finite_posets.py +++ b/src/sage/categories/finite_posets.py @@ -9,17 +9,16 @@ - An *order ideal* (or *lower set*) of a poset `P` is a subset `S` of `P` such that if `x \leq y` and `y\in S` then `x\in S`. """ -# **************************************************************************** +#***************************************************************************** # Copyright (C) 2011 Nicolas M. Thiery # # Distributed under the terms of the GNU General Public License (GPL) -# https://www.gnu.org/licenses/ -# ***************************************************************************** +# http://www.gnu.org/licenses/ +#****************************************************************************** from sage.misc.abstract_method import abstract_method from sage.categories.category_with_axiom import CategoryWithAxiom - class FinitePosets(CategoryWithAxiom): r""" The category of finite posets i.e. finite sets with a partial @@ -1950,5 +1949,5 @@ def directed_subsets(self, direction): [[]] """ if direction != 'up' and direction != 'down': - raise ValueError("direction must be either 'up' or 'down'") + raise ValueError("Direction must be either 'up' or 'down'.") return self.antichains().map(lambda elements: self.directed_subset(elements, direction)) diff --git a/src/sage/categories/homset.py b/src/sage/categories/homset.py index 1b488a03b69..1c954e76201 100644 --- a/src/sage/categories/homset.py +++ b/src/sage/categories/homset.py @@ -81,7 +81,6 @@ from sage.structure.coerce_dict import TripleDict _cache = TripleDict(weak_values=True) - def Hom(X, Y, category=None, check=True): """ Create the space of homomorphisms from X to Y in the category ``category``. @@ -1142,7 +1141,7 @@ def identity(self): sage: H.identity() Traceback (most recent call last): ... - TypeError: identity map only defined for endomorphisms; try natural_map() instead + TypeError: Identity map only defined for endomorphisms. Try natural_map() instead. sage: H.natural_map() Natural morphism: From: Integer Ring @@ -1150,7 +1149,8 @@ def identity(self): """ if self.is_endomorphism_set(): return morphism.IdentityMorphism(self) - raise TypeError("identity map only defined for endomorphisms; try natural_map() instead") + else: + raise TypeError("Identity map only defined for endomorphisms. Try natural_map() instead.") def one(self): """ diff --git a/src/sage/categories/map.pyx b/src/sage/categories/map.pyx index a569cc83849..1bb34eabf3b 100644 --- a/src/sage/categories/map.pyx +++ b/src/sage/categories/map.pyx @@ -11,15 +11,16 @@ AUTHORS: - Sebastian Oehms (2019-01-19): :meth:`section` added to :class:`FormalCompositeMap`. See :trac:`27081`. """ -# **************************************************************************** + +#***************************************************************************** # Copyright (C) 2008 Robert Bradshaw # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. -# https://www.gnu.org/licenses/ -# **************************************************************************** +# http://www.gnu.org/licenses/ +#***************************************************************************** from . import homset import weakref @@ -51,7 +52,6 @@ def unpickle_map(_class, parent, _dict, _slots): mor.__dict__ = _dict return mor - def is_Map(x): """ Auxiliary function: Is the argument a map? @@ -66,7 +66,6 @@ def is_Map(x): """ return isinstance(x, Map) - cdef class Map(Element): """ Basic class for all maps. @@ -1215,7 +1214,7 @@ cdef class Map(Element): sage: psi^2 Traceback (most recent call last): ... - TypeError: self must be an endomorphism + TypeError: self must be an endomorphism. sage: K. = NumberField(x^4 - 5*x + 5) sage: C5. = CyclotomicField(5) @@ -1231,7 +1230,7 @@ cdef class Map(Element): Defn: z |--> 3/11*a^3 + 4/11*a^2 + 9/11*a - 14/11 """ if self.domain() is not self._codomain and n != 1 and n != -1: - raise TypeError("self must be an endomorphism") + raise TypeError("self must be an endomorphism.") if n == 0: from sage.categories.morphism import IdentityMorphism return IdentityMorphism(self._parent) @@ -1871,7 +1870,7 @@ cdef class FormalCompositeMap(Map): sage: c2.is_injective() Traceback (most recent call last): ... - NotImplementedError: not enough information to deduce injectivity + NotImplementedError: Not enough information to deduce injectivity. If the first map is surjective and the second map is not injective, then the composition is not injective:: @@ -1912,7 +1911,7 @@ cdef class FormalCompositeMap(Map): if all(f.is_surjective() for f in injectives): return False - raise NotImplementedError("not enough information to deduce injectivity") + raise NotImplementedError("Not enough information to deduce injectivity.") def is_surjective(self): """ @@ -1954,7 +1953,7 @@ cdef class FormalCompositeMap(Map): ....: V2.hom(Matrix([[1], [1]]), V1)).is_surjective() Traceback (most recent call last): ... - NotImplementedError: not enough information to deduce surjectivity + NotImplementedError: Not enough information to deduce surjectivity. """ try: # we try the category first @@ -1978,7 +1977,7 @@ cdef class FormalCompositeMap(Map): if all(f.is_injective() for f in surjectives): return False - raise NotImplementedError("not enough information to deduce surjectivity") + raise NotImplementedError("Not enough information to deduce surjectivity.") def domains(self): """ diff --git a/src/sage/categories/posets.py b/src/sage/categories/posets.py index b1a2ba1942d..b09d920c863 100644 --- a/src/sage/categories/posets.py +++ b/src/sage/categories/posets.py @@ -1,19 +1,19 @@ r""" Posets """ -# **************************************************************************** +#***************************************************************************** # Copyright (C) 2011 Nicolas M. Thiery # # Distributed under the terms of the GNU General Public License (GPL) -# https://www.gnu.org/licenses/ -# ***************************************************************************** +# http://www.gnu.org/licenses/ +#****************************************************************************** + from sage.misc.cachefunc import cached_method from sage.misc.abstract_method import abstract_method from sage.misc.lazy_import import LazyImport from sage.categories.category import Category from sage.categories.sets_cat import Sets - class Posets(Category): r""" The category of posets i.e. sets with a partial order structure. @@ -326,20 +326,12 @@ def directed_subset(self, elements, direction): [3, 7, 8, 9, 10, 11, 12, 13, 14, 15] sage: B.directed_subset([7, 10], 'down') [0, 1, 2, 3, 4, 5, 6, 7, 8, 10] - - TESTS:: - - sage: B = posets.BooleanLattice(3) - sage: B.directed_subset([3, 1], 'banana') - Traceback (most recent call last): - ... - ValueError: direction must be either 'up' or 'down' """ if direction == 'up': return self.order_filter(elements) if direction == 'down': return self.order_ideal(elements) - raise ValueError("direction must be either 'up' or 'down'") + raise ValueError("Direction must be either 'up' or 'down'.") def principal_order_ideal(self, x): r""" diff --git a/src/sage/categories/pushout.py b/src/sage/categories/pushout.py index 86e33e45b1e..56ff1b12a92 100644 --- a/src/sage/categories/pushout.py +++ b/src/sage/categories/pushout.py @@ -1,6 +1,7 @@ """ Coercion via construction functors """ + # **************************************************************************** # Copyright (C) 2007-2014 Robert Bradshaw # 2007-2018 David Roe @@ -1292,9 +1293,10 @@ def _apply_functor_to_morphism(self, f): sage: R.construction()[0](f) # indirect doctest Traceback (most recent call last): ... - NotImplementedError: morphisms for infinite polynomial rings are not implemented yet + NotImplementedError: Morphisms for infinite polynomial rings are not implemented yet. + """ - raise NotImplementedError("morphisms for infinite polynomial rings are not implemented yet") + raise NotImplementedError("Morphisms for infinite polynomial rings are not implemented yet.") def _apply_functor(self, R): """ @@ -3023,7 +3025,7 @@ def merge(self, other): # quotient by I would result in the trivial ring/group/... # Rather than create the zero ring, we claim they can't be merged # TODO: Perhaps this should be detected at a higher level... - raise TypeError("trivial quotient intersection") + raise TypeError("Trivial quotient intersection.") # GF(p) has a coercion from Integers(p). Hence, merging should # yield a field if either self or other yields a field. return QuotientFunctor(I, names=self.names, as_field=as_field, @@ -4732,10 +4734,10 @@ def type_to_parent(P): sage: type_to_parent(list) Traceback (most recent call last): ... - TypeError: not a scalar type + TypeError: Not a scalar type. """ from sage.structure.coerce import py_scalar_parent parent = py_scalar_parent(P) if parent is None: - raise TypeError("not a scalar type") + raise TypeError("Not a scalar type.") return parent diff --git a/src/sage/categories/unique_factorization_domains.py b/src/sage/categories/unique_factorization_domains.py index 280320474d8..ccc96acbf80 100644 --- a/src/sage/categories/unique_factorization_domains.py +++ b/src/sage/categories/unique_factorization_domains.py @@ -1,12 +1,12 @@ r""" Unique factorization domains """ -# **************************************************************************** +#***************************************************************************** # Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) # # Distributed under the terms of the GNU General Public License (GPL) -# https://www.gnu.org/licenses/ -# ***************************************************************************** +# http://www.gnu.org/licenses/ +#****************************************************************************** from sage.misc.lazy_attribute import lazy_class_attribute from sage.misc.misc_c import prod @@ -14,7 +14,6 @@ from sage.categories.category_singleton import Category_contains_method_by_parent_class from sage.categories.gcd_domains import GcdDomains - class UniqueFactorizationDomains(Category_singleton): """ The category of (constructive) unique factorization domains. @@ -243,7 +242,7 @@ def radical(self, *args, **kwds): sage: Integer(0).radical() Traceback (most recent call last): ... - ArithmeticError: radical of 0 is not defined + ArithmeticError: Radical of 0 not defined. The next example shows how to compute the radical of a number, assuming no prime > 100000 has exponent > 1 in the factorization:: @@ -260,7 +259,7 @@ def radical(self, *args, **kwds): 10 """ if self.is_zero(): - raise ArithmeticError("radical of 0 is not defined") + raise ArithmeticError("Radical of 0 not defined.") try: decomp = self.squarefree_decomposition() except AttributeError: diff --git a/src/sage/combinat/algebraic_combinatorics.py b/src/sage/combinat/algebraic_combinatorics.py index 6a6a25b0907..b8f01700156 100644 --- a/src/sage/combinat/algebraic_combinatorics.py +++ b/src/sage/combinat/algebraic_combinatorics.py @@ -41,7 +41,6 @@ - :class:`~sage.combinat.symmetric_group_representations.SymmetricGroupRepresentation` - :ref:`sage.combinat.yang_baxter_graph` - :ref:`sage.combinat.hall_polynomial` -- :ref:`sage.combinat.key_polynomial` Operads and their algebras -------------------------- diff --git a/src/sage/combinat/all.py b/src/sage/combinat/all.py index 47cd721e0a5..e0450a1fbe3 100644 --- a/src/sage/combinat/all.py +++ b/src/sage/combinat/all.py @@ -87,7 +87,6 @@ from .debruijn_sequence import DeBruijnSequences from .schubert_polynomial import SchubertPolynomialRing -lazy_import('sage.combinat.key_polynomial', 'KeyPolynomialBasis', as_='KeyPolynomials') from .symmetric_group_algebra import SymmetricGroupAlgebra, HeckeAlgebraSymmetricGroupT from .symmetric_group_representations import SymmetricGroupRepresentation, SymmetricGroupRepresentations from .yang_baxter_graph import YangBaxterGraph diff --git a/src/sage/combinat/diagram.py b/src/sage/combinat/diagram.py index d2213120724..ad13779d19f 100644 --- a/src/sage/combinat/diagram.py +++ b/src/sage/combinat/diagram.py @@ -1013,28 +1013,15 @@ def peelable_tableaux(self): This implementation uses the algorithm suggested in Remark 25 of [RS1995]_. - - TESTS: - - Corner case:: - - sage: from sage.combinat.diagram import NorthwestDiagram - sage: D = NorthwestDiagram([]) - sage: D.peelable_tableaux() - {[]} """ # TODO: There is a condition on the first column (if the rows in Dhat # are a subset of the rows in the first column) which simplifies the # description without performing JDT, so we should implement that - # empty diagram case - if not self: - return set([Tableau([])]) - # if there is a single column in the diagram then there is only # one posslbe peelable tableau. if self._n_nonempty_cols == 1: - return set([Tableau([[i+1] for i, j in self.cells()])]) + return {Tableau([[i+1] for i, j in self.cells()])} first_col = min(j for i, j in self._cells) diff --git a/src/sage/combinat/key_polynomial.py b/src/sage/combinat/key_polynomial.py deleted file mode 100644 index be4d5aa8c04..00000000000 --- a/src/sage/combinat/key_polynomial.py +++ /dev/null @@ -1,865 +0,0 @@ -r""" -Key polynomials - -Key polynomials (also known as type A Demazure characters) are defined by -applying the divided difference operator `\pi_\sigma`, where `\sigma` is -a permutation, to a monomial corresponding to an integer partition -`\mu \vdash n`. - -.. SEEALSO:: - - For Demazure characters in other types, see - - - :meth:`sage.combinat.root_system.weyl_characters.WeylCharacterRing.demazure_character` - - :meth:`sage.categories.classical_crystals.ClassicalCrystals.ParentMethods.demazure_character` - -AUTHORS: - -- Trevor K. Karn (2022-08-17): initial version -""" - -# **************************************************************************** -# Copyright (C) 2022 Trevor K. Karn -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 2 of the License, or -# (at your option) any later version. -# https://www.gnu.org/licenses/ -# **************************************************************************** - -from sage.categories.graded_algebras_with_basis import GradedAlgebrasWithBasis -from sage.combinat.integer_vector import IntegerVectors -from sage.combinat.free_module import CombinatorialFreeModule -from sage.combinat.permutation import Permutation -from sage.structure.element import parent -from sage.rings.integer_ring import ZZ -from sage.rings.polynomial.infinite_polynomial_ring import InfinitePolynomialRing, InfinitePolynomialRing_sparse -from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing -from sage.rings.polynomial.polynomial_ring import PolynomialRing_commutative -from sage.rings.polynomial.multi_polynomial_ring_base import MPolynomialRing_base - -from collections.abc import Collection - - -class KeyPolynomial(CombinatorialFreeModule.Element): - r""" - A key polynomial. - - Key polynomials are polynomials that form a basis for a polynomial ring - and are indexed by weak compositions. - - Elements should be created by first creating the basis - :class:`KeyPolynomialBasis` and passing a list representing the indexing - composition. - - EXAMPLES:: - - sage: k = KeyPolynomials(QQ) - sage: f = k([4,3,2,1]) + k([1,2,3,4]); f - k[1, 2, 3, 4] + k[4, 3, 2, 1] - sage: f in k - True - """ - def _mul_(self, other): - r""" - Multiply the elements ``self`` and ``other``. - - EXAMPLES:: - - sage: k = KeyPolynomials(QQ) - sage: k([4,3,2]) * k([1,1,1]) - k[5, 4, 3] - - sage: k = KeyPolynomials(QQ, 4) - sage: k([4,3,2,0]) * k([1,1,1,0]) - k[5, 4, 3, 0] - """ - return self.parent().from_polynomial(self.expand() * other.expand()) - - def expand(self): - r""" - Return ``self`` written in the monomial basis (i.e., as an element - in the corresponding polynomial ring). - - EXAMPLES:: - - sage: k = KeyPolynomials(QQ) - sage: f = k([4,3,2,1]) - sage: f.expand() - z_3*z_2^2*z_1^3*z_0^4 - - sage: f = k([1,2,3]) - sage: f.expand() - z_2^3*z_1^2*z_0 + z_2^3*z_1*z_0^2 + z_2^2*z_1^3*z_0 - + 2*z_2^2*z_1^2*z_0^2 + z_2^2*z_1*z_0^3 + z_2*z_1^3*z_0^2 - + z_2*z_1^2*z_0^3 - """ - P = self.parent() - R = P._polynomial_ring - out = R.zero() - z = P.poly_gens() - - for m, c in self.monomial_coefficients().items(): - # find the permutation sorting mu into m - w, mu = sorting_word(m) - - # create the monomial to apply - monom = R.prod(z[i] ** mi for i, mi in enumerate(mu) if mi) - - out += c * isobaric_divided_difference(monom, w) - - return out - - to_polynomial = expand - - def pi(self, w): - r""" - Apply the operator `\pi_w` to ``self``. - - ``w`` may be either a ``Permutation`` or a list of indices of simple - transpositions (1-based). - - The convention is to apply from left to right so if - ``w = [w1, w2, ..., wm]`` then we apply - `\pi_{w_2 \cdots w_m} \circ \pi_{w_1}` - - EXAMPLES:: - - sage: k = KeyPolynomials(QQ) - sage: k([3,2,1]).pi(2) - k[3, 1, 2] - sage: k([3,2,1]).pi([2,1]) - k[1, 3, 2] - sage: k([3,2,1]).pi(Permutation([3,2,1])) - k[1, 2, 3] - sage: f = k([3,2,1]) + k([3,2,1,1]) - sage: f.pi(2) - k[3, 1, 2] + k[3, 1, 2, 1] - sage: k.one().pi(1) - k[] - - sage: k([3,2,1,0]).pi(2).pi(2) - k[3, 1, 2] - sage: (-k([3,2,1,0]) + 4*k([3,1,2,0])).pi(2) - 3*k[3, 1, 2] - - sage: k = KeyPolynomials(QQ, 4) - sage: k([3,2,1,0]).pi(2) - k[3, 1, 2, 0] - sage: k([3,2,1,0]).pi([2,1]) - k[1, 3, 2, 0] - sage: k([3,2,1,0]).pi(Permutation([3,2,1,4])) - k[1, 2, 3, 0] - sage: f = k([3,2,1,0]) + k([3,2,1,1]) - sage: f.pi(2) - k[3, 1, 2, 0] + k[3, 1, 2, 1] - sage: k.one().pi(1) - k[0, 0, 0, 0] - - TESTS: - - We check that this is consistent with the definition via the - isobaric divided difference oerators:: - - sage: from sage.combinat.key_polynomial import isobaric_divided_difference as idd - sage: k = KeyPolynomials(QQ, 4) - sage: S4 = Permutations(4) - sage: f = k([4,2,2,0]) - sage: all(idd(f.expand(), w.reduced_word()) == f.pi(w).expand() for w in S4) - True - - sage: f = k([4,2,0,1]) - 3 * k([2,0,1,2]) - sage: all(idd(f.expand(), w.reduced_word()) == f.pi(w).expand() for w in S4) - True - """ - P = self.parent() - if isinstance(w, Permutation): - w = w.reduced_word() - if not isinstance(w, Collection): - w = [w] - - if not w or not self: - return self - - N = max(w) + 1 - - if P._k is not None and N > P._k: - raise ValueError(f"pi_{N-1} does not exist for this polynomial ring") - - ret = P.element_class(P, {}) - for m, c in self._monomial_coefficients.items(): - m = list(m) - n = len(m) - for i in w: - if i > n: - continue - if i == n: - m += [0] - n += 1 - if m[i-1] <= m[i]: - continue - m[i-1], m[i] = m[i], m[i-1] - m = P._indices(m) - if P._k is None: - m = m.trim() - if m in ret._monomial_coefficients: - ret._monomial_coefficients[m] += c - else: - ret._monomial_coefficients[m] = c - if not ret._monomial_coefficients[m]: - del ret._monomial_coefficients - return ret - - isobaric_divided_difference = pi - - def divided_difference(self, w): - r""" - Apply the divided difference operator `\partial_w` to ``self``. - - The convention is to apply from left to right so if - ``w = [w1, w2, ..., wm]`` then we apply - `\partial_{w_2 \cdots w_m} \circ \partial_{w_1}` - - EXAMPLES:: - - sage: k = KeyPolynomials(QQ) - sage: k([3,2,1]).divided_difference(2) - k[3, 1, 1] - sage: k([3,2,1]).divided_difference([2,3]) - k[3, 1] - - sage: k = KeyPolynomials(QQ, 4) - sage: k([3,2,1,0]).divided_difference(2) - k[3, 1, 1, 0] - """ - if not isinstance(w, Collection): - w = [w] - f = self.expand() - for wi in w: - f = divided_difference(f, wi) - return self.parent().from_polynomial(f) - - -class KeyPolynomialBasis(CombinatorialFreeModule): - r""" - The key polynomial basis for a polynomial ring. - - For a full definition, see - `SymmetricFunctions.com `_. - Key polynomials are indexed by weak compositions with no trailing zeros, - and `\sigma` is the permutation of shortest length which sorts the - indexing composition into a partition. - - EXAMPLES: - - Key polynomials are a basis, indexed by (weak) compositions, - for polynomial rings:: - - sage: k = KeyPolynomials(QQ) - sage: k([3,0,1,2]) - k[3, 0, 1, 2] - sage: k([3,0,1,2])/2 - 1/2*k[3, 0, 1, 2] - sage: R = k.polynomial_ring(); R - Infinite polynomial ring in z over Rational Field - - sage: K = KeyPolynomials(GF(5)); K - Key polynomial basis over Finite Field of size 5 - sage: 2*K([3,0,1,2]) - 2*k[3, 0, 1, 2] - sage: 5*(K([3,0,1,2]) + K([3,1,1])) - 0 - - We can expand them in the standard monomial basis:: - - sage: k([3,0,1,2]).expand() - z_3^2*z_2*z_0^3 + z_3^2*z_1*z_0^3 + z_3*z_2^2*z_0^3 - + 2*z_3*z_2*z_1*z_0^3 + z_3*z_1^2*z_0^3 + z_2^2*z_1*z_0^3 - + z_2*z_1^2*z_0^3 - - sage: k([0,0,2]).expand() - z_2^2 + z_2*z_1 + z_2*z_0 + z_1^2 + z_1*z_0 + z_0^2 - - If we have a polynomial, we can express it in the key basis:: - - sage: z = R.gen() - sage: k.from_polynomial(z[2]^2*z[1]*z[0]) - k[1, 1, 2] - k[1, 2, 1] - - sage: f = z[3]^2*z[2]*z[0]^3 + z[3]^2*z[1]*z[0]^3 + z[3]*z[2]^2*z[0]^3 + \ - ....: 2*z[3]*z[2]*z[1]*z[0]^3 + z[3]*z[1]^2*z[0]^3 + z[2]^2*z[1]*z[0]^3 + \ - ....: z[2]*z[1]^2*z[0]^3 - sage: k.from_polynomial(f) - k[3, 0, 1, 2] - - Since the ring of key polynomials may be regarded as a different choice of - basis for a polynomial ring, it forms an algebra, so we have - multiplication:: - - sage: k([10,5,2])*k([1,1,1]) - k[11, 6, 3] - - We can also multiply by polynomials in the monomial basis:: - - sage: k([10,9,1])*z[0] - k[11, 9, 1] - sage: z[0] * k([10,9,1]) - k[11, 9, 1] - sage: k([10,9,1])*(z[0] + z[3]) - k[10, 9, 1, 1] + k[11, 9, 1] - - When the sorting permutation is the longest element, the key polynomial - agrees with the Schur polynomial:: - - sage: s = SymmetricFunctions(QQ).schur() - sage: k([1,2,3]).expand() - z_2^3*z_1^2*z_0 + z_2^3*z_1*z_0^2 + z_2^2*z_1^3*z_0 - + 2*z_2^2*z_1^2*z_0^2 + z_2^2*z_1*z_0^3 + z_2*z_1^3*z_0^2 - + z_2*z_1^2*z_0^3 - sage: s[3,2,1].expand(3) - x0^3*x1^2*x2 + x0^2*x1^3*x2 + x0^3*x1*x2^2 + 2*x0^2*x1^2*x2^2 - + x0*x1^3*x2^2 + x0^2*x1*x2^3 + x0*x1^2*x2^3 - - The polynomial expansions can be computed using crystals and expressed in - terms of the key basis:: - - sage: T = crystals.Tableaux(['A',3],shape=[2,1]) - sage: f = T.demazure_character([3,2,1]) - sage: k.from_polynomial(f) - k[1, 0, 0, 2] - - The default behavior is to work in a polynomial ring with infinitely many - variables. One can work in a specicfied number of variables:: - - sage: k = KeyPolynomials(QQ, 4) - sage: k([3,0,1,2]).expand() - z_0^3*z_1^2*z_2 + z_0^3*z_1*z_2^2 + z_0^3*z_1^2*z_3 - + 2*z_0^3*z_1*z_2*z_3 + z_0^3*z_2^2*z_3 + z_0^3*z_1*z_3^2 + z_0^3*z_2*z_3^2 - - sage: k([0,0,2,0]).expand() - z_0^2 + z_0*z_1 + z_1^2 + z_0*z_2 + z_1*z_2 + z_2^2 - - sage: k([0,0,2,0]).expand().parent() - Multivariate Polynomial Ring in z_0, z_1, z_2, z_3 over Rational Field - - If working in a specified number of variables, the length of the indexing - composition must be the same as the number of variables:: - - sage: k([0,0,2]) - Traceback (most recent call last): - ... - TypeError: do not know how to make x (= [0, 0, 2]) an element of self - (=Key polynomial basis over Rational Field) - - One can also work in a specified polynomial ring:: - - sage: k = KeyPolynomials(QQ['x0', 'x1', 'x2', 'x3']) - sage: k([0,2,0,0]) - k[0, 2, 0, 0] - sage: k([4,0,0,0]).expand() - x0^4 - - If one wishes to use a polynomial ring as coefficients for the key - polynomials, pass the keyword argument ``poly_coeffs=True``:: - - sage: k = KeyPolynomials(QQ['q'], poly_coeffs=True) - sage: R = k.base_ring(); R - Univariate Polynomial Ring in q over Rational Field - sage: R.inject_variables() - Defining q - sage: (q^2 + q + 1)*k([0,2,2,0,3,2]) - (q^2+q+1)*k[0, 2, 2, 0, 3, 2] - """ - Element = KeyPolynomial - - @staticmethod - def __classcall_private__(cls, R=None, k=None, poly_ring=None, poly_coeffs=False): - r""" - Normalize input. - - EXAMPLES:: - - sage: KeyPolynomials(InfinitePolynomialRing(QQ, ['x', 'y'])) - Traceback (most recent call last): - ... - ValueError: polynomial ring has too many generators - - sage: KeyPolynomials(QQ['t0','t1','t2','t3']) - Key polynomial basis over Rational Field - - sage: KeyPolynomials(QQ['t']) - Key polynomial basis over Rational Field - - sage: KeyPolynomials(InfinitePolynomialRing(QQ['t'], 'z')) - Key polynomial basis over Univariate Polynomial Ring in t over Rational Field - - sage: KeyPolynomials(QQ) - Key polynomial basis over Rational Field - - sage: KeyPolynomials(QQ, 3) - Key polynomial basis over Rational Field - """ - poly_type = (PolynomialRing_commutative, - MPolynomialRing_base, - InfinitePolynomialRing_sparse) - - if isinstance(R, poly_type): - # if a polynomial ring is provided, we need to determine - # if it is meant to be self.polynomial_ring() or self.base_ring() - if isinstance(R, poly_type[0:2]): - k = R.ngens() - if isinstance(R, InfinitePolynomialRing_sparse) and R.ngens() > 1: - raise ValueError("polynomial ring has too many generators") - if isinstance(R.base_ring(), poly_type[0:2]): - # if R is of the form K[t_1, ..., t_n][z_*] - # or K[t_1, ..., t_n][z_1, ..., z_k] - return cls.__classcall__(cls, k=k, poly_ring=R) - if poly_coeffs: - # if R is a polynomial ring, but its base ring is not - # and poly_coeffs is true, then we should interpret - # R as the base ring - return cls.__classcall__(cls, R=R) - return cls.__classcall__(cls, k=k, poly_ring=R) - else: - # if R is not a polynomial ring, we know it is self.base_ring() - return cls.__classcall__(cls, R=R, k=k) - - def __init__(self, R=None, k=None, poly_ring=None): - r""" - Initialize ``self``. - - EXAMPLES:: - - sage: R = GF(3)['t'].fraction_field() - sage: k = KeyPolynomials(QQ) - sage: TestSuite(k).run() - sage: k = KeyPolynomials(R) - sage: TestSuite(k).run() - - sage: k = KeyPolynomials(QQ, 4) - sage: TestSuite(k).run() - sage: k = KeyPolynomials(R, 4) - sage: TestSuite(k).run() - """ - self._k = k - - if self._k is not None: - def build_index(m): - return self._indices(m) - else: - def build_index(m): - return self._indices(reversed(m)).trim() - - self._build_index = build_index - - if R is not None: - if poly_ring: - raise ValueError("specify only one of base_ring or poly_ring (not both)") - if k: - self._polynomial_ring = PolynomialRing(R, 'z_', k) - else: - self._polynomial_ring = InfinitePolynomialRing(R, 'z') - if poly_ring is not None: - if R is not None: - raise ValueError("specify only one of base_ring or poly_ring (not both)") - R = poly_ring.base_ring() - self._polynomial_ring = poly_ring - - self._name = "Key polynomial basis" - - CombinatorialFreeModule.__init__(self, R, IntegerVectors(k=k), - category=GradedAlgebrasWithBasis(R), - prefix='k', bracket=False) - - def _coerce_map_from_(self, R): - r""" - Return the coercion map from ``R`` if it exists. - - EXAMPLES:: - - sage: k = KeyPolynomials(QQ) - sage: m1 = k([3, 2, 4, 0]); m1 - k[3, 2, 4] - sage: m2 = k(Composition([3, 2, 4])); m2 - k[3, 2, 4] - sage: m1 == m2 - True - - sage: R = k.polynomial_ring() - sage: z = R.gen() - sage: z[0] * k([4, 3, 3, 2]) - k[5, 3, 3, 2] - - sage: X = SchubertPolynomialRing(QQ) - sage: k(X([4, 3, 2, 1])) - k[3, 2, 1] - """ - P = self._polynomial_ring - if R is P: - return self.from_polynomial - - from sage.combinat.schubert_polynomial import SchubertPolynomialRing_xbasis - if isinstance(R, SchubertPolynomialRing_xbasis): - return self.from_schubert_polynomial - - phi = P.coerce_map_from(R) - if phi is not None: - return self.coerce_map_from(P) * phi - return None - - def _monomial(self, x): - r""" - EXAMPLES:: - - sage: k = KeyPolynomials(QQ) - sage: k([3, 2, 3, 4, 0]) - k[3, 2, 3, 4] - sage: k = KeyPolynomials(QQ, 5) - sage: k([3, 2, 3, 4, 0]) - k[3, 2, 3, 4, 0] - """ - if self._k: - return self._from_dict({x: self.base_ring().one()}, remove_zeros=False) - return self._from_dict({x.trim(): self.base_ring().one()}, remove_zeros=False) - - def __getitem__(self, c): - """ - This method implements the abuses of notations ``k[2,1]``, - ``k[[2,1]]``, etc. - - INPUT: - - - ``c`` -- anything that can represent an index of a basis element - - EXAMPLES:: - - sage: k = KeyPolynomials(QQ) - sage: k[3] - k[3] - sage: k[3, 0, 2] - k[3, 0, 2] - sage: k[3, 1, 2, 0, 0] - k[3, 1, 2] - - sage: k = KeyPolynomials(QQ, 4) - sage: k[3, 0, 1, 0] - k[3, 0, 1, 0] - sage: k[3] - Traceback (most recent call last): - ... - ValueError: [3] doesn't satisfy correct constraints - """ - C = self._indices - if not isinstance(c, C.element_class): - if c in ZZ: - c = C([c]) - else: - c = C(c) - return self._monomial(c) - - def one_basis(self): - r""" - Return the basis element indexing the identity. - - EXAMPLES:: - - sage: k = KeyPolynomials(QQ) - sage: k.one_basis() - [] - - sage: k = KeyPolynomials(QQ, 4) - sage: k.one_basis() - [0, 0, 0, 0] - """ - if self._k: - return self._indices([0] * self._k) - return self._indices([]) - - def polynomial_ring(self): - r""" - Return the polynomial ring associated to ``self``. - - EXAMPLES:: - - sage: k = KeyPolynomials(QQ) - sage: k.polynomial_ring() - Infinite polynomial ring in z over Rational Field - - sage: k = KeyPolynomials(QQ, 4) - sage: k.polynomial_ring() - Multivariate Polynomial Ring in z_0, z_1, z_2, z_3 over Rational Field - """ - return self._polynomial_ring - - def poly_gens(self): - r""" - Return the polynomial generators for the polynomial ring - associated to ``self``. - - EXAMPLES:: - - sage: k = KeyPolynomials(QQ) - sage: k.poly_gens() - z_* - - sage: k = KeyPolynomials(QQ, 4) - sage: k.poly_gens() - (z_0, z_1, z_2, z_3) - """ - if self._k: - return self._polynomial_ring.gens() - return self._polynomial_ring.gen() - - def from_polynomial(self, f): - r""" - Expand a polynomial in terms of the key basis. - - EXAMPLES:: - - sage: k = KeyPolynomials(QQ) - sage: z = k.poly_gens(); z - z_* - sage: p = z[0]^4*z[1]^2*z[2]*z[3] + z[0]^4*z[1]*z[2]^2*z[3] - sage: k.from_polynomial(p) - k[4, 1, 2, 1] - - sage: all(k(c) == k.from_polynomial(k(c).expand()) for c in IntegerVectors(n=5, k=4)) - True - - sage: T = crystals.Tableaux(['A', 4], shape=[4,2,1,1]) - sage: k.from_polynomial(T.demazure_character([2])) - k[4, 1, 2, 1] - - """ - if f not in self._polynomial_ring: - try: # to accept elements of SymbolicRing - from sage.calculus.var import var - f = f.substitute(list(d == var(f'z_{i}') - for i, d in enumerate(f.variables()))) - f = self._polynomial_ring(f) - except AttributeError: - raise ValueError(f"f must be an element of {self._polynomial_ring}") - - out = self.zero() - - while f: - M = f.monomials()[0] - c = f.monomial_coefficient(M) - - new_term = self._from_dict({self._build_index(*M.exponents()): c}) - - f -= new_term.expand() - out += new_term - - return out - - def from_schubert_polynomial(self, x): - r""" - Expand a Schubert polynomial in the key basis. - - EXAMPLES:: - - sage: k = KeyPolynomials(ZZ) - sage: X = SchubertPolynomialRing(ZZ) - sage: f = X([2,1,5,4,3]) - sage: k.from_schubert_polynomial(f) - k[1, 0, 2, 1] + k[2, 0, 2] + k[3, 0, 0, 1] - sage: k.from_schubert_polynomial(2) - 2*k[] - sage: k(f) - k[1, 0, 2, 1] + k[2, 0, 2] + k[3, 0, 0, 1] - - sage: k = KeyPolynomials(GF(7), 4) - sage: k.from_schubert_polynomial(f) - k[1, 0, 2, 1] + k[2, 0, 2, 0] + k[3, 0, 0, 1] - - TESTS:: - - sage: k = KeyPolynomials(ZZ) - sage: k.from_schubert_polynomial(k([3,2])) - Traceback (most recent call last): - ... - ValueError: not a Schubert polynomial - - sage: k = KeyPolynomials(ZZ) - sage: X = SchubertPolynomialRing(ZZ) - sage: it = iter(Compositions()) - sage: for _ in range(50): - ....: C = next(it) - ....: assert k.from_schubert_polynomial(X(k[C])) == k[C], C - - sage: k = KeyPolynomials(ZZ, 4) - sage: X = SchubertPolynomialRing(ZZ) - sage: it = iter(k.basis().keys()) - sage: for _ in range(50): - ....: C = next(it) - ....: assert k.from_schubert_polynomial(X(k[C])) == k[C], C - """ - if x in self.base_ring(): - return self(x) - - from sage.combinat.schubert_polynomial import SchubertPolynomial_class - if not isinstance(x, SchubertPolynomial_class): - raise ValueError('not a Schubert polynomial') - - from sage.combinat.diagram import RotheDiagram - out = self.zero() - if self._k is not None: - def build_elt(wt): - wt = list(wt) - wt += [0] * (self._k - len(wt)) - return self[wt] - else: - def build_elt(wt): - return self[wt] - - for m, c in x.monomial_coefficients().items(): - D = RotheDiagram(m) - a = self.zero() - for d in D.peelable_tableaux(): - a += build_elt(d.left_key_tableau().weight()) - out += c * a - - return out - - -def divided_difference(f, i): - r""" - Apply the ``i``-th divided difference operator to the polynomial ``f``. - - EXAMPLES:: - - sage: from sage.combinat.key_polynomial import divided_difference - sage: k = KeyPolynomials(QQ) - sage: z = k.poly_gens() - sage: f = z[1]*z[2]^3 + z[1]*z[2]*z[3] - sage: divided_difference(f, 3) - z_3^2*z_1 + z_3*z_2*z_1 + z_2^2*z_1 - - sage: k = KeyPolynomials(QQ, 4) - sage: z = k.poly_gens() - sage: f = z[1]*z[2]^3 + z[1]*z[2]*z[3] - sage: divided_difference(f, 3) - z_1*z_2^2 + z_1*z_2*z_3 + z_1*z_3^2 - - sage: k = KeyPolynomials(QQ) - sage: R = k.polynomial_ring(); R - Infinite polynomial ring in z over Rational Field - sage: z = R.gen() - sage: divided_difference(z[1]*z[2]^3, 2) - -z_2^2*z_1 - z_2*z_1^2 - sage: divided_difference(z[1]*z[2]*z[3], 3) - 0 - sage: divided_difference(z[1]*z[2]*z[3], 4) - z_2*z_1 - sage: divided_difference(z[1]*z[2]*z[4], 4) - -z_2*z_1 - - sage: k = KeyPolynomials(QQ, 5) - sage: z = k.polynomial_ring().gens() - sage: divided_difference(z[1]*z[2]^3, 2) - -z_1^2*z_2 - z_1*z_2^2 - sage: divided_difference(z[1]*z[2]*z[3], 3) - 0 - sage: divided_difference(z[1]*z[2]*z[3], 4) - z_1*z_2 - sage: divided_difference(z[1]*z[2]*z[4], 4) - -z_1*z_2 - """ - P = parent(f) - if isinstance(P, InfinitePolynomialRing_sparse): - z = P.gen() - else: - z = P.gens() - - si_f = f.subs({z[i]: z[i-1], z[i-1]: z[i]}) - return (si_f - f) // (z[i] - z[i-1]) - -def isobaric_divided_difference(f, w): - r""" - Apply the isobaric divided difference operator `\pi_w` to the - polynomial `f`. - - ``w`` may be either a single index or a list of - indices of simple transpositions. - - .. WARNING:: - - The simple transpositions should be applied from left to right. - - EXAMPLES:: - - sage: from sage.combinat.key_polynomial import isobaric_divided_difference as idd - sage: R. = InfinitePolynomialRing(GF(3)) - sage: idd(z[1]^4*z[2]^2*z[4], 4) - 0 - - sage: idd(z[1]^4*z[2]^2*z[3]*z[4], 3) - z_4*z_3^2*z_2*z_1^4 + z_4*z_3*z_2^2*z_1^4 - - sage: idd(z[1]^4*z[2]^2*z[3]*z[4], [3, 4]) - z_4^2*z_3*z_2*z_1^4 + z_4*z_3^2*z_2*z_1^4 + z_4*z_3*z_2^2*z_1^4 - - sage: idd(z[1]^4*z[2]^2*z[3]*z[4], [4, 3]) - z_4*z_3^2*z_2*z_1^4 + z_4*z_3*z_2^2*z_1^4 - - sage: idd(z[1]^2*z[2], [3, 2]) - z_3*z_2^2 + z_3*z_2*z_1 + z_3*z_1^2 + z_2^2*z_1 + z_2*z_1^2 - """ - P = parent(f) - if isinstance(P, InfinitePolynomialRing_sparse): - z = P.gen() - else: - z = P.gens() - - if not hasattr(w, "__iter__"): # this allows us to pass i instead of a word - w = [w] - for i in w: - fp = z[i-1] * f - si_fp = fp.subs({z[i]: z[i-1], z[i-1]: z[i]}) - f = (si_fp - fp) // (z[i] - z[i-1]) - return f - -def sorting_word(alpha): - r""" - Get a reduced word for the permutation which sorts ``alpha`` - into a partition. - - The result is a list ``l = [i0, i1, i2, ...]`` where each ``ij`` - is a positive integer such that it applies the simple - transposition `(i_j, i_j+1)`. The transpositions are applied - starting with ``i0``, then ``i1`` is applied, followed by ``i2``, - and so on. See :meth:`sage.combinat.permutation.Permutation.reduced_words` - for the convention used. - - EXAMPLES:: - - sage: IV = IntegerVectors() - sage: from sage.combinat.key_polynomial import sorting_word - sage: list(sorting_word(IV([2,3,2]))[0]) - [1] - sage: sorting_word(IV([2,3,2]))[1] - [3, 2, 2] - sage: list(sorting_word(IV([5,6,7]))[0]) - [1, 2, 1] - sage: list(sorting_word(IV([0,3,2]))[0]) - [2, 1] - sage: list(sorting_word(IV([0,3,0,2]))[0]) - [2, 3, 1] - sage: list(sorting_word(IV([3,2,1]))[0]) - [] - sage: list(sorting_word(IV([2,3,3]))[0]) - [2, 1] - """ - w = [] - L = list(alpha) - n = len(L) - - # bubble sort to get the shortest sorting word - for i in range(n-1): - for j in range(n-i-1): - if L[j] < L[j + 1]: - w.append(j+1) - L[j], L[j + 1] = L[j + 1], L[j] - return reversed(w), L diff --git a/src/sage/combinat/permutation.py b/src/sage/combinat/permutation.py index a237f2398a9..e64650bde6e 100644 --- a/src/sage/combinat/permutation.py +++ b/src/sage/combinat/permutation.py @@ -6817,11 +6817,6 @@ def _coerce_map_from_(self, G): True sage: P.has_coerce_map_from(Permutations(7)) False - - sage: P.has_coerce_map_from(groups.misc.Cactus(5)) - True - sage: P.has_coerce_map_from(groups.misc.Cactus(7)) - False """ if isinstance(G, SymmetricGroup): D = G.domain() @@ -6830,9 +6825,6 @@ def _coerce_map_from_(self, G): return self._from_permutation_group_element if isinstance(G, StandardPermutations_n) and G.n <= self.n: return True - from sage.groups.cactus_group import CactusGroup - if isinstance(G, CactusGroup) and G.n() <= self.n: - return self._from_cactus_group_element return super()._coerce_map_from_(G) def _from_permutation_group_element(self, x): @@ -6849,21 +6841,6 @@ def _from_permutation_group_element(self, x): """ return self(x.domain()) - def _from_cactus_group_element(self, x): - """ - Return an element of ``self`` from a cactus group element. - - EXAMPLES:: - - sage: J3 = groups.misc.Cactus(3) - sage: s12,s13,s23 = J3.gens() - sage: elt = s12 * s23 * s13 - sage: P5 = Permutations(5) - sage: P5._from_cactus_group_element(elt) - [1, 3, 2, 4, 5] - """ - return self(x.to_permutation()) - def as_permutation_group(self): """ Return ``self`` as a permutation group. diff --git a/src/sage/combinat/posets/lattices.py b/src/sage/combinat/posets/lattices.py index 43bd9f83fdc..dba3c15c549 100644 --- a/src/sage/combinat/posets/lattices.py +++ b/src/sage/combinat/posets/lattices.py @@ -1903,8 +1903,8 @@ def breadth(self, certificate=False): any join of elements `x_1, x_2, \ldots, x_{n+1}` is join of a proper subset of `x_i`. - This can be also characterized by subposets: a lattice - of breadth at least `n` contains a subposet isomorphic to the + This can be also characterized by sublattices: a lattice + of breadth at least `n` contains a sublattice isomorphic to the Boolean lattice of `2^n` elements. INPUT: @@ -4300,7 +4300,7 @@ def is_constructible_by_doublings(self, type): return True if (type == 'interval' and len(self.join_irreducibles()) != - len(self.meet_irreducibles())): + len(self.meet_irreducibles())): return False if type == 'upper' or type == 'interval': diff --git a/src/sage/combinat/root_system/reflection_group_complex.py b/src/sage/combinat/root_system/reflection_group_complex.py index 626c7e2c2a8..1e139f1dd23 100644 --- a/src/sage/combinat/root_system/reflection_group_complex.py +++ b/src/sage/combinat/root_system/reflection_group_complex.py @@ -205,7 +205,6 @@ from sage.sets.family import Family from sage.structure.unique_representation import UniqueRepresentation from sage.groups.perm_gps.permgroup import PermutationGroup_generic -from sage.combinat.permutation import Permutation from sage.rings.integer_ring import ZZ from sage.rings.rational_field import QQ from sage.matrix.all import Matrix, identity_matrix @@ -368,21 +367,17 @@ def _repr_(self): type_str = type_str[:-3] return 'Reducible complex reflection group of rank %s and type %s' % (self._rank, type_str) - def iteration_tracking_words(self): + def __iter__(self): r""" - Return an iterator going through all elements in ``self`` that - tracks the reduced expressions. - - This can be much slower than using the iteration as a permutation - group with strong generating set. + Return an iterator going through all elements in ``self``. EXAMPLES:: sage: W = ReflectionGroup((1,1,3)) # optional - gap3 - sage: for w in W.iteration_tracking_words(): w # optional - gap3 + sage: for w in W: w # optional - gap3 () - (1,4)(2,3)(5,6) (1,3)(2,5)(4,6) + (1,4)(2,3)(5,6) (1,6,2)(3,5,4) (1,2,6)(3,4,5) (1,5)(2,4)(3,6) diff --git a/src/sage/combinat/root_system/reflection_group_element.pyx b/src/sage/combinat/root_system/reflection_group_element.pyx index 02761726799..b724132637b 100644 --- a/src/sage/combinat/root_system/reflection_group_element.pyx +++ b/src/sage/combinat/root_system/reflection_group_element.pyx @@ -71,21 +71,8 @@ cdef class ComplexReflectionGroupElement(PermutationGroupElement): sage: WB_hash.intersection(WC_hash) # optional - gap3 set() - - Check that :trac:`34912` is fixed:: - - sage: G4 = ReflectionGroup(4) # optional - gap3 - sage: g0, g1 = G4.gens() # optional - gap3 - sage: elt = g0^2 * g1 * g0^2 * g1 # optional - gap3 - sage: elt # optional - gap3 - (1,12)(2,24)(3,19)(4,22)(5,17)(6,20)(7,23)(8,9)(10,21)(11,13)(14,18)(15,16) - sage: y = (elt * G4.gen(1)) * G4.gen(1) * G4.gen(1) # optional - gap3 - sage: elt == y # optional - gap3 - True - sage: hash(elt) == hash(y) # optional - gap3 - True """ - return hash(self._parent) | super().__hash__() + return hash(self._parent) | hash(tuple(self._reduced_word)) def reduced_word(self): r""" @@ -149,7 +136,7 @@ cdef class ComplexReflectionGroupElement(PermutationGroupElement): EXAMPLES:: sage: W = ReflectionGroup(4) # optional - gap3 - sage: for w in W.iteration_tracking_words(): # optional - gap3 + sage: for w in W: # optional - gap3 ....: print("{} {}".format(w.reduced_word(), w.length())) [] 0 [1] 1 @@ -175,11 +162,6 @@ cdef class ComplexReflectionGroupElement(PermutationGroupElement): [1, 2, 2, 1, 1] 5 [1, 1, 2, 1, 1, 2] 6 [1, 1, 2, 2, 1, 1] 6 - - sage: data = {w: (len(w.reduced_word()), w.length()) # optional - gap3 - ....: for w in W.iteration_tracking_words()} - sage: for w in W: # optional - gap3 - ....: assert data[w] == (w.length(), w.length()), w """ return ZZ(len(self.reduced_word())) @@ -196,13 +178,10 @@ cdef class ComplexReflectionGroupElement(PermutationGroupElement): EXAMPLES:: - sage: W = ReflectionGroup((3,1,2)) # optional - gap3 - sage: data = {w: [w.to_matrix(), w.to_matrix(on_space="dual")] for w in W} # optional - gap3 - sage: for w in W.iteration_tracking_words(): # optional - gap3 - ....: w.reduced_word() # optional - gap3 - ....: mats = [w.to_matrix(), w.to_matrix(on_space="dual")] # optional - gap3 - ....: mats - ....: assert data[w] == mats + sage: W = ReflectionGroup((3,1,2)) # optional - gap3 + sage: for w in W: # optional - gap3 + ....: w.reduced_word() # optional - gap3 + ....: [w.to_matrix(), w.to_matrix(on_space="dual")] # optional - gap3 [] [ [1 0] [1 0] @@ -546,8 +525,7 @@ cdef class ComplexReflectionGroupElement(PermutationGroupElement): EXAMPLES:: sage: W = ReflectionGroup(4) # optional - gap3 - sage: for w in W.iteration_tracking_words(): # optional - gap3 - ....: w.reflection_eigenvalues() + sage: for w in W: w.reflection_eigenvalues() # optional - gap3 [0, 0] [1/3, 0] [1/3, 0] @@ -572,10 +550,6 @@ cdef class ComplexReflectionGroupElement(PermutationGroupElement): [2/3, 0] [1/2, 1/2] [1/4, 3/4] - - sage: data = {w: w.reflection_eigenvalues() for w in W} # optional - gap3 - sage: all(w.reflection_eigenvalues() == data[w] for w in W.iteration_tracking_words()) # optional - gap3 - True """ return self._parent.reflection_eigenvalues(self, is_class_representative=is_class_representative) @@ -587,8 +561,7 @@ cdef class ComplexReflectionGroupElement(PermutationGroupElement): EXAMPLES:: sage: W = ReflectionGroup(4) # optional - gap3 - sage: for w in W.iteration_tracking_words(): # optional - gap3 - ....: print(w.galois_conjugates()) + sage: for w in W: print(w.galois_conjugates()) # optional - gap3 [[1 0] [0 1]] [[ 1 0] @@ -677,10 +650,6 @@ cdef class ComplexReflectionGroupElement(PermutationGroupElement): [ 2/3*E(3) - 2/3*E(3)^2 1/3*E(3) - 1/3*E(3)^2], [ 1/3*E(3) - 1/3*E(3)^2 -1/3*E(3) + 1/3*E(3)^2] [-2/3*E(3) + 2/3*E(3)^2 -1/3*E(3) + 1/3*E(3)^2]] - - sage: data = {w: w.galois_conjugates() for w in W} # optional - gap3 - sage: all(w.galois_conjugates() == data[w] for w in W.iteration_tracking_words()) # optional - gap3 - True """ rk = self._parent.rank() M = self.to_matrix().list() diff --git a/src/sage/combinat/root_system/reflection_group_real.py b/src/sage/combinat/root_system/reflection_group_real.py index 9d7c9a92bbf..559e40e73c5 100644 --- a/src/sage/combinat/root_system/reflection_group_real.py +++ b/src/sage/combinat/root_system/reflection_group_real.py @@ -609,7 +609,7 @@ def coxeter_diagram(self): EXAMPLES:: sage: G = ReflectionGroup(['B',3]) # optional - gap3 - sage: G.coxeter_diagram().edges(labels=True, sort=True) # optional - gap3 + sage: sorted(G.coxeter_diagram().edges(labels=True)) # optional - gap3 [(1, 2, 4), (2, 3, 3)] """ from sage.graphs.graph import Graph diff --git a/src/sage/combinat/schubert_polynomial.py b/src/sage/combinat/schubert_polynomial.py index 7e9164db5de..07d679ac65d 100644 --- a/src/sage/combinat/schubert_polynomial.py +++ b/src/sage/combinat/schubert_polynomial.py @@ -73,18 +73,15 @@ # # https://www.gnu.org/licenses/ # **************************************************************************** -from sage.categories.all import GradedAlgebrasWithBasis from sage.combinat.free_module import CombinatorialFreeModule -from sage.combinat.key_polynomial import KeyPolynomial -from sage.combinat.permutation import Permutations, Permutation -from sage.misc.cachefunc import cached_method +from sage.categories.all import GradedAlgebrasWithBasis from sage.rings.integer import Integer from sage.rings.integer_ring import ZZ -from sage.rings.polynomial.infinite_polynomial_element import InfinitePolynomial_sparse from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.rings.polynomial.multi_polynomial import is_MPolynomial - +from sage.combinat.permutation import Permutations, Permutation import sage.libs.symmetrica.all as symmetrica +from sage.misc.cachefunc import cached_method def SchubertPolynomialRing(R): @@ -417,17 +414,6 @@ def _element_constructor_(self, x): sage: X(x1^2*x2) X[3, 2, 1] - sage: S. = InfinitePolynomialRing(QQ) - sage: X(x[0]^2*x[1]) - X[3, 2, 1] - sage: X(x[0]*x[1]^2*x[2]^2*x[3] + x[0]^2*x[1]^2*x[2]*x[3] + x[0]^2*x[1]*x[2]^2*x[3]) - X[2, 4, 5, 3, 1] - - sage: from sage.combinat.key_polynomial import KeyPolynomialBasis - sage: k = KeyPolynomialBasis(QQ) - sage: X(k([3,2,1])) - X[4, 3, 2, 1] - TESTS: We check that :trac:`12924` is fixed:: @@ -443,15 +429,6 @@ def _element_constructor_(self, x): sage: X([]) X[1] - - Check the round trip from key polynomials:: - - sage: k = KeyPolynomials(ZZ) - sage: X = SchubertPolynomialRing(ZZ) - sage: it = iter(Permutations()) - sage: for _ in range(50): - ....: P = next(it) - ....: assert X(k(X(P))) == X(P), P """ if isinstance(x, list): # checking the input to avoid symmetrica crashing Sage, see trac 12924 @@ -464,14 +441,6 @@ def _element_constructor_(self, x): return self._from_dict({perm: self.base_ring().one()}) elif is_MPolynomial(x): return symmetrica.t_POLYNOM_SCHUBERT(x) - elif isinstance(x, InfinitePolynomial_sparse): - R = x.polynomial().parent() - # massage the term order to be what symmetrica expects - S = PolynomialRing(R.base_ring(), - names=list(map(repr, reversed(R.gens())))) - return symmetrica.t_POLYNOM_SCHUBERT(S(x.polynomial())) - elif isinstance(x, KeyPolynomial): - return self(x.expand()) else: raise TypeError diff --git a/src/sage/combinat/subword_complex.py b/src/sage/combinat/subword_complex.py index b5455260aaa..15af1d67ba0 100644 --- a/src/sage/combinat/subword_complex.py +++ b/src/sage/combinat/subword_complex.py @@ -90,7 +90,7 @@ sage: Q = I + W.w0.coxeter_sorting_word(I) sage: S = SubwordComplex(Q,W.w0) sage: S.brick_polytope() - doctest:...: RuntimeWarning: the polytope is built with rational vertices + doctest:...: RuntimeWarning: the polytope is build with rational vertices A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 32 vertices AUTHORS: @@ -768,7 +768,7 @@ def plot(self, list_colors=None, labels=[], thickness=3, fontsize=14, sage: Q = c.reduced_word()*2 + W.w0.coxeter_sorting_word(c) # optional - gap3 sage: SC = SubwordComplex(Q, W.w0) # optional - gap3 sage: F = SC[15]; F.plot() # optional - gap3 - Graphics object consisting of 53 graphics primitives + Graphics object consisting of 52 graphics primitives TESTS:: @@ -1696,7 +1696,7 @@ def minkowski_summand(self, i): else: from sage.rings.cc import CC from warnings import warn - warn("the polytope is built with rational vertices", RuntimeWarning) + warn("the polytope is build with rational vertices", RuntimeWarning) min_sum = [[QQ(CC(v)) for v in F.extended_weight_configuration()[i]] for F in self] return Polyhedron(min_sum) @@ -1737,8 +1737,6 @@ def brick_polytope(self, coefficients=None): sage: c = W.index_set(); Q = c + tuple(W.w0.coxeter_sorting_word(c)) # optional - gap3 sage: SC = SubwordComplex(Q,W.w0) # optional - gap3 sage: SC.brick_polytope() # optional - gap3 - doctest:...: - RuntimeWarning: the polytope is built with rational vertices A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 32 vertices """ BV = self.brick_vectors(coefficients=coefficients) @@ -1749,7 +1747,7 @@ def brick_polytope(self, coefficients=None): else: from sage.rings.cc import CC from warnings import warn - warn("the polytope is built with rational vertices", RuntimeWarning) + warn("the polytope is build with rational vertices", RuntimeWarning) BV = [[QQ(CC(v).real()) for v in V] for V in BV] return Polyhedron(BV) diff --git a/src/sage/env.py b/src/sage/env.py index ac279ed5da3..4bbc674e7c6 100644 --- a/src/sage/env.py +++ b/src/sage/env.py @@ -11,8 +11,7 @@ sage: env = {k:v for (k,v) in os.environ.items() if not k.startswith("SAGE_")} sage: from subprocess import check_output - sage: environment = "sage.all" - sage: cmd = f"from {environment} import SAGE_ROOT, SAGE_LOCAL; print((SAGE_ROOT, SAGE_LOCAL))" + sage: cmd = "from sage.all import SAGE_ROOT, SAGE_LOCAL; print((SAGE_ROOT, SAGE_LOCAL))" sage: out = check_output([sys.executable, "-c", cmd], env=env).decode().strip() # long time sage: out == repr((SAGE_ROOT, SAGE_LOCAL)) # long time True @@ -185,6 +184,10 @@ def var(key: str, *fallbacks: Optional[str], force: bool = False) -> Optional[st SAGE_PKGS = var("SAGE_PKGS", join(SAGE_ROOT, "build", "pkgs")) SAGE_ROOT_GIT = var("SAGE_ROOT_GIT", join(SAGE_ROOT, ".git")) +# Sage doc server (local server with PORT if URL is not given) +SAGE_DOC_SERVER_URL = var("SAGE_DOC_SERVER_URL") +SAGE_DOC_LOCAL_PORT = var("SAGE_DOC_LOCAL_PORT", "8000") + # ~/.sage DOT_SAGE = var("DOT_SAGE", join(os.environ.get("HOME"), ".sage")) SAGE_STARTUP_FILE = var("SAGE_STARTUP_FILE", join(DOT_SAGE, "init.sage")) diff --git a/src/sage/geometry/cone.py b/src/sage/geometry/cone.py index c8a59a8b2a8..3d9cb0766fc 100644 --- a/src/sage/geometry/cone.py +++ b/src/sage/geometry/cone.py @@ -205,8 +205,7 @@ from copy import copy from warnings import warn -from sage.arith.misc import GCD as gcd -from sage.arith.functions import lcm +from sage.arith.all import gcd, lcm from sage.combinat.posets.posets import FinitePoset from sage.geometry.point_collection import PointCollection from sage.geometry.polyhedron.constructor import Polyhedron diff --git a/src/sage/geometry/hyperplane_arrangement/library.py b/src/sage/geometry/hyperplane_arrangement/library.py index 0334593a889..cfa2fbeb083 100644 --- a/src/sage/geometry/hyperplane_arrangement/library.py +++ b/src/sage/geometry/hyperplane_arrangement/library.py @@ -22,7 +22,7 @@ from sage.combinat.combinat import stirling_number2 from sage.combinat.root_system.cartan_type import CartanType from sage.combinat.root_system.root_system import RootSystem -from sage.arith.misc import binomial +from sage.arith.all import binomial from sage.rings.polynomial.polynomial_ring import polygen from sage.geometry.hyperplane_arrangement.arrangement import HyperplaneArrangements diff --git a/src/sage/geometry/integral_points.pyx b/src/sage/geometry/integral_points.pyx index 8b2e54b2d5d..4d39b436cae 100644 --- a/src/sage/geometry/integral_points.pyx +++ b/src/sage/geometry/integral_points.pyx @@ -22,8 +22,7 @@ from sage.rings.integer_ring import ZZ from sage.rings.rational_field import QQ from sage.rings.real_mpfr import RR from sage.rings.integer cimport Integer -from sage.arith.misc import GCD as gcd -from sage.arith.functions import lcm +from sage.arith.all import gcd, lcm from sage.combinat.permutation import Permutation from sage.misc.misc_c import prod from sage.modules.free_module import FreeModule diff --git a/src/sage/geometry/lattice_polytope.py b/src/sage/geometry/lattice_polytope.py index 1c3115213ca..0b30f206cbe 100644 --- a/src/sage/geometry/lattice_polytope.py +++ b/src/sage/geometry/lattice_polytope.py @@ -103,7 +103,7 @@ # https://www.gnu.org/licenses/ # **************************************************************************** -from sage.arith.misc import GCD as gcd +from sage.arith.all import gcd from sage.combinat.posets.posets import FinitePoset from sage.env import POLYTOPE_DATA_DIR from sage.geometry.cone import _ambient_space_point, integral_length diff --git a/src/sage/geometry/point_collection.pyx b/src/sage/geometry/point_collection.pyx index 3a67de459ed..12d0ff2465d 100644 --- a/src/sage/geometry/point_collection.pyx +++ b/src/sage/geometry/point_collection.pyx @@ -955,23 +955,23 @@ def read_palp_point_collection(f, lattice=None, permutation=False): Read and return a point collection from an opened file. Data must be in PALP format: - + * the first input line starts with two integers `m` and `n`, the number of points and the number of components of each; - + * the rest of the first line may contain a permutation; - + * the next `m` lines contain `n` numbers each. - + .. NOTE:: - + If `m` < `n`, it is assumed (for compatibility with PALP) that the matrix is transposed, i.e. that each column is a point. INPUT: - ``f`` -- an opened file with PALP output. - + - ``lattice`` -- the lattice for points. If not given, the :class:`toric lattice ` `M` of dimension `n` will be used. diff --git a/src/sage/geometry/polyhedron/generating_function.py b/src/sage/geometry/polyhedron/generating_function.py index 9fadd8f3e13..c476461da8a 100644 --- a/src/sage/geometry/polyhedron/generating_function.py +++ b/src/sage/geometry/polyhedron/generating_function.py @@ -1492,7 +1492,7 @@ def generate_mods(equations): sage: _TransformMod.generate_mods([(0, 1, 1, -2)]) ({0: (2, 0), 1: (2, 0)}, {0: (2, 1), 1: (2, 1)}) """ - from sage.arith.functions import lcm + from sage.arith.all import lcm from sage.matrix.constructor import matrix from sage.rings.integer_ring import ZZ from sage.rings.rational_field import QQ diff --git a/src/sage/geometry/triangulation/element.py b/src/sage/geometry/triangulation/element.py index a436b40d441..29de26bbc13 100644 --- a/src/sage/geometry/triangulation/element.py +++ b/src/sage/geometry/triangulation/element.py @@ -878,7 +878,7 @@ def normal_cone(self): raise NotImplementedError('Only base rings ZZ and QQ are supported') from ppl import Constraint_System, Linear_Expression, C_Polyhedron from sage.matrix.constructor import matrix - from sage.arith.functions import lcm + from sage.arith.all import lcm pc = self.point_configuration() cs = Constraint_System() for facet in self.interior_facets(): diff --git a/src/sage/graphs/digraph.py b/src/sage/graphs/digraph.py index 66a14bd30fb..3cccf81c956 100644 --- a/src/sage/graphs/digraph.py +++ b/src/sage/graphs/digraph.py @@ -3472,7 +3472,7 @@ def period(self): :meth:`is_aperiodic` """ - from sage.arith.misc import GCD as gcd + from sage.arith.all import gcd g = 0 diff --git a/src/sage/graphs/digraph_generators.py b/src/sage/graphs/digraph_generators.py index c0a0a0ef926..f1d88178ebb 100644 --- a/src/sage/graphs/digraph_generators.py +++ b/src/sage/graphs/digraph_generators.py @@ -393,7 +393,7 @@ def Paley(self, q): """ from sage.rings.finite_rings.integer_mod import mod from sage.rings.finite_rings.finite_field_constructor import FiniteField - from sage.arith.misc import is_prime_power + from sage.arith.all import is_prime_power if not is_prime_power(q): raise ValueError("parameter q must be a prime power") if not mod(q, 4) == 3: diff --git a/src/sage/graphs/edge_connectivity.pyx b/src/sage/graphs/edge_connectivity.pyx index 5263e712db5..54152821203 100644 --- a/src/sage/graphs/edge_connectivity.pyx +++ b/src/sage/graphs/edge_connectivity.pyx @@ -61,14 +61,14 @@ cdef class GabowEdgeConnectivity: ....: D = DiGraph(graphs.RandomRegular(6, 50)) sage: GabowEdgeConnectivity(D).edge_connectivity() 6 - + A complete digraph with `n` vertices is `n-1`-edge-connected:: sage: from sage.graphs.edge_connectivity import GabowEdgeConnectivity sage: D = DiGraph(digraphs.Complete(10)) sage: GabowEdgeConnectivity(D, use_rec = True).edge_connectivity() 9 - + Check that we get the same result when with and without the DFS-based speed-up initialization proposed in [GKLP2021]_:: @@ -79,7 +79,7 @@ cdef class GabowEdgeConnectivity: sage: ec3 = GabowEdgeConnectivity(D, dfs_preprocessing=True, use_rec=True).edge_connectivity() sage: ec1 == ec2 and ec2 == ec3 True - + TESTS: :trac:`32169`:: @@ -158,9 +158,9 @@ cdef class GabowEdgeConnectivity: cdef int augmenting_root cdef bint* tree_flag # indicate whether a tree Ti has been touched cdef int* root # current root vertex of f_tree i - cdef int* L_roots # L_roots of the trees + cdef int* L_roots # L_roots of the trees cdef bint* forests # indicate whether the f_tree is active or inactive - cdef bint** labeled # + cdef bint** labeled # cdef int** parent_1 # parent of v in tree/forest Ti cdef int** parent_2 # parent of v in tree/forest Ti @@ -176,7 +176,7 @@ cdef class GabowEdgeConnectivity: cdef vector[int] A_path cdef vector[int] left_traverse cdef vector[int] right_traverse - + cdef bint* seen # for method re_init cdef int* stack # stack of vertices for DFS in re_init cdef vector[vector[int]] tree_edges # used to organise the edges of the trees @@ -243,7 +243,7 @@ cdef class GabowEdgeConnectivity: self.n = G.order() self.m = G.size() self.mem = MemoryAllocator() - + # Build compact graph data structure with out and in adjacencies. # Loops are removed from the graph. self.build_graph_data_structure() @@ -420,7 +420,7 @@ cdef class GabowEdgeConnectivity: if self.dfs_preprocessing and self.num_start_f_trees < self.n - 1: self.re_init(tree) - # There are n f-trees, and we try to join them + # There are n f-trees, and we try to join them while njoins < self.num_start_f_trees-1: # Get the root of an active subtree or INT_MAX if none exists z = self.choose_root() @@ -469,7 +469,7 @@ cdef class GabowEdgeConnectivity: self.my_depth[tree] = self.mem.calloc(self.n, sizeof(int)) if not self.my_parent_edge_id[tree]: self.my_parent_edge_id[tree] = self.mem.calloc(self.n, sizeof(int)) - + cdef int j for j in range(self.n): self.my_parent[tree][j] = 0 @@ -478,9 +478,9 @@ cdef class GabowEdgeConnectivity: self.labeled[tree][j] = False self.root[j] = j self.forests[j] = True - + self.num_joins = 0 - + # Initialize T_k to be a DFS spanning forest of G \ T if self.dfs_preprocessing: self.compute_dfs_tree() @@ -490,7 +490,7 @@ cdef class GabowEdgeConnectivity: self.L_roots[tree] = self.UNUSED self.tree_flag[tree] = False - + cdef void compute_dfs_tree(self): r""" Find a DFS spanning forest of `G \backslash T`. @@ -525,7 +525,7 @@ cdef class GabowEdgeConnectivity: self.find_dfs_tree(r) # Each call of find_dfs_tree creates an f-tree self.num_start_f_trees += 1 - + cdef void find_dfs_tree(self, int r): r""" Find more vertices of the f-tree rooted at `r`. @@ -604,7 +604,7 @@ cdef class GabowEdgeConnectivity: self.num_joins += 1 # recursively find more vertices and grow the subtree rooted at r self.find_dfs_tree_rec(v, r) - + cdef int choose_root(self): """ Return the root of an active f_tree, or INT_MAX if none exists. diff --git a/src/sage/graphs/generators/classical_geometries.py b/src/sage/graphs/generators/classical_geometries.py index 059d46d0c7f..4450192573d 100644 --- a/src/sage/graphs/generators/classical_geometries.py +++ b/src/sage/graphs/generators/classical_geometries.py @@ -19,7 +19,7 @@ # **************************************************************************** from sage.graphs.graph import Graph -from sage.arith.misc import is_prime_power +from sage.arith.all import is_prime_power from sage.rings.finite_rings.finite_field_constructor import FiniteField diff --git a/src/sage/graphs/generators/families.py b/src/sage/graphs/generators/families.py index ec6a5c19e60..9837fe3a5fa 100644 --- a/src/sage/graphs/generators/families.py +++ b/src/sage/graphs/generators/families.py @@ -2558,7 +2558,7 @@ def PaleyGraph(q): """ from sage.rings.finite_rings.integer_mod import mod from sage.rings.finite_rings.finite_field_constructor import FiniteField - from sage.arith.misc import is_prime_power + from sage.arith.all import is_prime_power if not is_prime_power(q): raise ValueError("parameter q must be a prime power") if not mod(q, 4) == 1: @@ -3933,7 +3933,7 @@ def MathonPseudocyclicStronglyRegularGraph(t, G=None, L=None): from sage.rings.integer_ring import ZZ from sage.matrix.constructor import matrix, block_matrix, \ ones_matrix, identity_matrix - from sage.arith.misc import two_squares + from sage.arith.all import two_squares p = 4*t + 1 try: x = two_squares(p) diff --git a/src/sage/graphs/hyperbolicity.pyx b/src/sage/graphs/hyperbolicity.pyx index a76b5477961..cb728e3b4e1 100644 --- a/src/sage/graphs/hyperbolicity.pyx +++ b/src/sage/graphs/hyperbolicity.pyx @@ -155,7 +155,7 @@ from cysignals.signals cimport sig_on, sig_off from memory_allocator cimport MemoryAllocator from sage.graphs.distances_all_pairs cimport c_distances_all_pairs -from sage.arith.misc import binomial +from sage.arith.all import binomial from sage.rings.integer_ring import ZZ from sage.rings.real_mpfr import RR from sage.data_structures.bitset import Bitset diff --git a/src/sage/graphs/strongly_regular_db.pyx b/src/sage/graphs/strongly_regular_db.pyx index 945b2301159..8cf2c73c957 100644 --- a/src/sage/graphs/strongly_regular_db.pyx +++ b/src/sage/graphs/strongly_regular_db.pyx @@ -32,9 +32,7 @@ import os from sage.categories.sets_cat import EmptySetError from sage.misc.unknown import Unknown -from sage.arith.misc import is_square -from sage.arith.misc import is_prime_power -from sage.arith.misc import divisors +from sage.arith.all import is_square, is_prime_power, divisors from sage.misc.cachefunc import cached_function from sage.combinat.designs.orthogonal_arrays import orthogonal_array from sage.combinat.designs.bibd import balanced_incomplete_block_design diff --git a/src/sage/groups/additive_abelian/additive_abelian_group.py b/src/sage/groups/additive_abelian/additive_abelian_group.py index 49f0dc97a4b..3efc1d7621c 100644 --- a/src/sage/groups/additive_abelian/additive_abelian_group.py +++ b/src/sage/groups/additive_abelian/additive_abelian_group.py @@ -352,7 +352,7 @@ def exponent(self): 1 """ if not self.invariants(): - return ZZ(1) + return 1 else: ann = self.annihilator().gen() if ann: diff --git a/src/sage/groups/cactus_group.py b/src/sage/groups/cactus_group.py deleted file mode 100644 index 9a481cc783c..00000000000 --- a/src/sage/groups/cactus_group.py +++ /dev/null @@ -1,999 +0,0 @@ -r""" -Cactus Groups - -AUTHORS: - -- Travis Scrimshaw (1-2023): initial version -""" - -# **************************************************************************** -# Copyright (C) 2023 Travis Scrimshaw -# -# Distributed under the terms of the GNU General Public License (GPL) -# https://www.gnu.org/licenses/ -# **************************************************************************** - -from sage.misc.cachefunc import cached_method -from sage.misc.lazy_attribute import lazy_attribute -from sage.structure.element import MultiplicativeGroupElement, parent -from sage.structure.unique_representation import UniqueRepresentation -from sage.structure.richcmp import richcmp -from sage.matrix.constructor import matrix -from sage.categories.groups import Groups -from sage.groups.group import Group -from sage.groups.kernel_subgroup import KernelSubgroup -from sage.combinat.permutation import Permutations -from sage.sets.family import Family -from sage.graphs.graph import Graph -from itertools import combinations - - -class CactusGroup(UniqueRepresentation, Group): - r""" - The cactus group. - - The `n`-fruit cactus group `J_n` is the group generated by `s_{pq}` - for `1 \leq p < q \leq n` with relations: - - - `s_{pq}^2 = 1` - - `s_{pq} s_{kl} = s_{kl} s_{pq}` if the intervals `[p, q]` and `[k, l]` - are disjoint, and - - `s_{pq} s_{kl} = s_{p+q-l,p+q-k} s_{pq}` if `[k, l] \subseteq [p, q]`. - - INPUT: - - - ``n`` -- an integer - - EXAMPLES: - - We construct the cactus group `J_3` and do some basic computations:: - - sage: J3 = groups.misc.Cactus(3) - sage: s12,s13,s23 = J3.group_generators() - sage: s12 * s13 - s[1,2]*s[1,3] - sage: x = s12 * s23; x - s[1,2]*s[2,3] - sage: x^4 - s[1,2]*s[2,3]*s[1,2]*s[2,3]*s[1,2]*s[2,3]*s[1,2]*s[2,3] - sage: s12 * s13 == s13 * s23 - True - - We verify the key equality in Lemma 2.3 in [White2015]_, which shows - that `J_5` is generated by `s_{1q}`:: - - sage: J5 = groups.misc.Cactus(5) - sage: gens = J5.group_generators() - sage: all(gens[(p,q)] == gens[(1,q)] * gens[(1,q-p+1)] * gens[(1,q)] - ....: for p in range(1, 6) for q in range(p+1, 6)) - True - """ - def __init__(self, n): - r""" - Initialize ``self``. - - TESTS:: - - sage: J3 = groups.misc.Cactus(3) - sage: it = iter(J3) - sage: elts = [next(it) for _ in range(100)] - sage: TestSuite(J3).run(elements=elts[::7], skip="_test_enumerated_set_contains") - - We run this test separately because the words grow very long, very - quickly. This means the code needs to check a lot of normalizations, - so we limit the number of tests:: - - sage: J3._test_enumerated_set_contains(max_runs=500) - - :: - - sage: J4 = groups.misc.Cactus(4) - sage: it = iter(J4) - sage: elts = [next(it) for _ in range(100)] - sage: TestSuite(J4).run(elements=elts[::8]) - """ - self._n = n - ell = len(str(n)) - names = ['s{}{}'.format('0' * (ell - len(str(i))) + str(i), - '0' * (ell - len(str(j))) + str(j)) - for i in range(1, self._n + 1) - for j in range(i + 1, self._n + 1)] - cat = Groups().FinitelyGeneratedAsMagma() - if n > 2: - cat = cat.Infinite() - else: - cat = cat.Finite() - Group.__init__(self, category=cat) - # Group.__init__ doesn't take a "names" parameter - self._assign_names(names) - - @lazy_attribute - def _WG(self): - r""" - Get the graph for the right-angled Coxeter group that ``self`` - embeds into (set theoretically) and set the ``_subsets`` and - ``_subsets_inv`` attributes. - - We do this initialization lazily in order to make the creation of - the parent quick. However, this is used to normalize the product - of elements. - - EXAMPLES:: - - sage: J4 = groups.misc.Cactus(4) - sage: J4._WG - Graph on 11 vertices - sage: J4._subsets - [frozenset({1, 2}), frozenset({1, 3}), frozenset({1, 4}), frozenset({2, 3}), - frozenset({2, 4}), frozenset({3, 4}), frozenset({1, 2, 3}), frozenset({1, 2, 4}), - frozenset({1, 3, 4}), frozenset({2, 3, 4}), frozenset({1, 2, 3, 4})] - """ - n = self._n - I = list(range(1, n+1)) - PS = sum(([frozenset(A) for A in combinations(I, k)] for k in range(2,n+1)), []) - G = Graph([list(range(len(PS))), - [[i,j,-1] for j in range(1, len(PS)) for i in range(j) - if PS[i] & PS[j] not in [frozenset(), PS[i], PS[j]]] - ], format="vertices_and_edges") - self._subsets = PS - self._subsets_inv = {X: i for i,X in enumerate(PS)} - return G - - def right_angled_coxeter_group(self): - r""" - Return the right-angled Coxeter group that ``self`` - (set-theoretically) embeds into. - - This is defined following [Most2019]_, where it was called the - diagram group. It has generators (of order `2`) indexed by subsets - of `\{1, \ldots, n\}` that commute if and only if one subset is - contained in the other or they are disjoint. For the pure cactus - group, this is also a group homomorphism, otherwise it is a - group 1-cocycle [BCL2022]_. - - EXAMPLES:: - - sage: J3 = groups.misc.Cactus(3) - sage: J3.right_angled_coxeter_group() - Coxeter group over Rational Field with Coxeter matrix: - [ 1 -1 -1 2] - [-1 1 -1 2] - [-1 -1 1 2] - [ 2 2 2 1] - """ - from sage.rings.rational_field import QQ - from sage.combinat.root_system.coxeter_group import CoxeterGroup - from sage.combinat.root_system.coxeter_matrix import CoxeterMatrix - return CoxeterGroup(CoxeterMatrix(self._WG), base_ring=QQ) - - def _repr_(self): - """ - Return a string representation of ``self``. - - EXAMPLES:: - - sage: groups.misc.Cactus(3) - Cactus Group with 3 fruit - """ - return "Cactus Group with {} fruit".format(self._n) - - def _latex_(self): - r""" - Return a latex representation of ``self``. - - EXAMPLES:: - - sage: J3 = groups.misc.Cactus(3) - sage: latex(J3) - J_{3} - """ - return "J_{{{}}}".format(self._n) - - def n(self): - """ - Return the value `n`. - - EXAMPLES:: - - sage: J3 = groups.misc.Cactus(3) - sage: J3.n() - 3 - """ - return self._n - - @cached_method - def group_generators(self): - """ - Return the group generators of ``self``. - - EXAMPLES:: - - sage: J3 = groups.misc.Cactus(3) - sage: J3.group_generators() - Finite family {(1, 2): s[1,2], (1, 3): s[1,3], (2, 3): s[2,3]} - """ - l = [(i, j) for i in range(1, self._n + 1) - for j in range(i + 1, self._n + 1)] - return Family(l, lambda x: self.element_class(self, [x])) - - @cached_method - def gens(self): - """ - Return the generators of ``self`` as a tuple. - - EXAMPLES:: - - sage: J3 = groups.misc.Cactus(3) - sage: J3.gens() - (s[1,2], s[1,3], s[2,3]) - """ - return tuple(self.group_generators()) - - def gen(self, i, j=None): - r""" - Return the `i`-th generator of ``self`` or the generator `s_{ij}`. - - EXAMPLES:: - - sage: J3 = groups.misc.Cactus(3) - sage: J3.gen(1) - s[1,3] - sage: J3.gen(1,2) - s[1,2] - sage: J3.gen(0,2) - Traceback (most recent call last): - ... - ValueError: s[0,2] is not a valid generator - sage: J3.gen(1,4) - Traceback (most recent call last): - ... - ValueError: s[1,4] is not a valid generator - sage: J3.gen(2,1) - Traceback (most recent call last): - ... - ValueError: s[2,1] is not a valid generator - """ - if j is None: - return self.gens()[i] - if not (1 <= i < j <= self._n): - raise ValueError(f"s[{i},{j}] is not a valid generator") - return self.element_class(self, [(i,j)]) - - @cached_method - def one(self): - r""" - Return the identity element in ``self``. - - EXAMPLES:: - - sage: J3 = groups.misc.Cactus(3) - sage: J3.one() - 1 - """ - return self.element_class(self, []) - - def _coerce_map_from_(self, G): - r""" - Return if there is a coerce map from ``G``. - - EXAMPLES:: - - sage: J3 = groups.misc.Cactus(3) - sage: J5 = groups.misc.Cactus(5) - sage: PJ3 = groups.misc.PureCactus(3) - sage: PJ5 = groups.misc.PureCactus(5) - - sage: J3._coerce_map_from_(J5) - False - sage: J5._coerce_map_from_(J3) - True - sage: J3._coerce_map_from_(PJ3) - True - sage: J3._coerce_map_from_(PJ5) - False - sage: J5._coerce_map_from_(PJ3) - True - sage: J5._coerce_map_from_(PJ5) - True - """ - if isinstance(G, CactusGroup): - return G._n <= self._n - elif isinstance(G, PureCactusGroup): - return G.n() <= self._n - return super()._coerce_map_from_(G) - - def _element_constructor_(self, x): - r""" - Construct an element of ``self`` from ``x``. - - EXAMPLES:: - - sage: J3 = groups.misc.Cactus(3) - sage: J5 = groups.misc.Cactus(5) - sage: PJ3 = groups.misc.PureCactus(3) - - sage: J5(J3.an_element()) - s[1,2]*s[2,3]*s[1,3] - sage: J3(J5.an_element()) - s[1,2]*s[2,3]*s[1,3] - sage: it = iter(PJ3) - sage: [J3(next(it)) for _ in range(3)] - [1, s[1,2]*s[2,3]*s[1,2]*s[1,3], s[2,3]*s[1,2]*s[2,3]*s[1,3]] - - sage: J3([[1,2], [1,3], [2,3]]) - s[1,3] - """ - if parent(x) is self: - return x - if isinstance(x, PureCactusGroup.Element): - x = x.value - if isinstance(x, CactusGroup.Element): - if any(d[1] > self._n for d in x._data): - raise ValueError(f"{x} is not an element of {self}") - return self.element_class(self, x._data) - ret = self.element_class(self, x) - ret._normalize() - return ret - - def _an_element_(self): - r""" - Return an element of ``self``. - - TESTS:: - - sage: J1 = groups.misc.Cactus(1) - sage: J1._an_element_() - 1 - sage: J2 = groups.misc.Cactus(2) - sage: J2._an_element_() - s[1,2] - sage: J3 = groups.misc.Cactus(3) - sage: x = J3._an_element_(); x - s[1,2]*s[2,3]*s[1,3] - - sage: x._normalize() - sage: x - s[1,2]*s[2,3]*s[1,3] - """ - if self._n <= 1: - return self.one() - if self._n == 2: - return self.element_class(self, [(1, 2)]) - return self.element_class(self, [(1, 2), (2, 3), (1, 3)]) - - def random_element(self, max_length=10): - r""" - Return a random element of ``self`` of length at most ``max_length``. - - EXAMPLES:: - - sage: J3 = groups.misc.Cactus(3) - sage: J3.random_element() # random - s[1,2]*s[2,3]*s[1,2]*s[1,3] - """ - from sage.misc.prandom import randint - l = randint(0, max_length) - gens = list(self.group_generators()) - ret = self.one() - for _ in range(l): - ret *= gens[randint(0, len(gens) - 1)] - return ret - - def bilinear_form(self, t=None): - r""" - Return the ``t``-bilinear form of ``self``. - - We define a bilinear form `B` on the group algebra by - - .. MATH:: - - B(s_{ij}, s_{pq}) = \begin{cases} - 1 & \text{if } i = p, j = q, \\ - -t & \text{if } [i, j] \not\subseteq [p, q] \text{ and } - [p, q] \not\subseteq [i, j], \\ - 0 & \text{otherwise}. - \end{cases} - - In other words, it is `1` if `s_{ij} = s_{pq}`, `-t` if `s_{ij}` - and `s_{pq}` generate a free group, and `0` otherwise (they commute - or almost commute). - - INPUT: - - - ``t`` -- (default: `t` in `\ZZ[t]`) the variable `t` - - EXAMPLES:: - - sage: J = groups.misc.Cactus(4) - sage: B = J.bilinear_form() - sage: B - [ 1 0 0 -t -t 0] - [ 0 1 0 0 -t -t] - [ 0 0 1 0 0 0] - [-t 0 0 1 0 -t] - [-t -t 0 0 1 0] - [ 0 -t 0 -t 0 1] - - We reorder the generators so the bilinear form is more - "Coxeter-like". In particular, when we remove the generator - `s_{1,4}`, we recover the bilinear form in Example 6.2.5 - of [DJS2003]_:: - - sage: J.gens() - (s[1,2], s[1,3], s[1,4], s[2,3], s[2,4], s[3,4]) - sage: S = SymmetricGroup(6) - sage: g = S([1,4,6,2,5,3]) - sage: B.permute_rows_and_columns(g, g) - sage: B - [ 1 -t 0 0 -t 0] - [-t 1 -t 0 0 0] - [ 0 -t 1 -t 0 0] - [ 0 0 -t 1 -t 0] - [-t 0 0 -t 1 0] - [ 0 0 0 0 0 1] - """ - if t is None: - from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing - from sage.rings.integer_ring import ZZ - t = PolynomialRing(ZZ, 't').gen() - R = t.parent() - ret = [] - K = self.group_generators().keys() - for x in K: - for y in K: - if x is y: - ret.append(R.one()) - elif (x[1] < y[0] or x[0] > y[1] or # Disjoint - (x[0] <= y[0] and y[1] <= x[1]) or # y <= x - (y[0] <= x[0] and x[1] <= y[1])): # x <= y - ret.append(R.zero()) - else: - ret.append(-t) - return matrix(R, len(K), len(K), ret) - - def geometric_representation_generators(self, t=None): - r""" - Return the matrices corresponding to the generators of ``self``. - - We construct a representation over `R = \ZZ[t]` of `J_n` as follows. - Let `E` be the vector space over `R` spanned by `\{\epsilon_v\}_v`, - where `v` is a generator of `J_n`. Fix some generator `v`, and - let `E_v` denote the span of `\epsilon_u - \epsilon_{u'}`, - where `u'` is the reflected interval of `u` in `v`, over all - `u` such that `u \subset v`. Let `F_v` denote the orthogonal - complement of `R \epsilon_v \oplus E_v` with respect to the - :meth:`bilinear form ` `B`. We define the action - of `v` on `E` by - - .. MATH:: - - \rho(v) = -I |_{R\epsilon_v \oplus E_v} \oplus I |_{F_v}. - - By Theorem 6.2.3 of [DJS2003]_, this defines a representation of `J_n`. - It is expected that this is a faithful representation (see - Remark 6.2.4 of [DJS2003]_). As this arises from a blow-up and an - analog of the geometric representation of the corresponding - Coxeter group (the symmetric group), we call this the - *geometric representation*. - - INPUT: - - - ``t`` -- (default: `t` in `\ZZ[t]`) the variable `t` - - EXAMPLES:: - - sage: J3 = groups.misc.Cactus(3) - sage: list(J3.geometric_representation_generators()) - [ - [ -1 0 2*t] [ 0 0 1] [ 1 0 0] - [ 0 1 0] [ 0 -1 0] [ 0 1 0] - [ 0 0 1], [ 1 0 0], [2*t 0 -1] - ] - - We ran the following code with ``max_tests = 15000`` and did - not find a counterexample to the faithfulness of this representation:: - - sage: visited = set([J3.one()]) - sage: cur = set([(J3.one(), J3.one().to_matrix())]) - sage: mats = set([J3.one().to_matrix()]) - sage: RG = list(J3.geometric_representation_generators()) - sage: count = 0 - sage: max_tests = 1000 - sage: while cur: - ....: count += 1 - ....: if count >= max_tests: - ....: break - ....: elt, mat = cur.pop() - ....: for g,r in zip(J3, RG): - ....: val = elt * g - ....: if val in visited: - ....: continue - ....: visited.add(val) - ....: matp = mat * r - ....: matp.set_immutable() - ....: assert matp not in mats, f"not injective {val} \n{matp}" - ....: mats.add(matp) - ....: cur.add((val, matp)) - """ - B = self.bilinear_form(t) - F = B.base_ring().fraction_field() - K = self.group_generators().keys() - from sage.modules.free_module import FreeModule - V = FreeModule(F, len(K)) - basis = V.basis() - ret = {} - for ik, k in enumerate(K): - E = [basis[ik]] - ME = matrix(E) - # The only non-trivial elements are those reflected by the interval k - for low in range(k[0], k[1] + 1): - for high in range(low + 1, k[1] + 1): - v = (low, high) - vp = (k[0] + k[1] - high, k[0] + k[1] - low) - if v == vp: - continue - elt = basis[K.index(v)] - basis[K.index(vp)] - if elt not in ME.row_space(): - E.append(elt) - ME = ME.stack(elt) - # Get the orthogonal complement wrt to the bilinear form B - Fv = (ME * B).right_kernel().basis_matrix() - T = ME.stack(Fv).transpose() - rho = matrix.diagonal(F, [-1] * len(E) + [1] * (len(K) - len(E))) - ret[k] = T * rho * ~T - return Family(K, lambda k: ret[k]) - - class Element(MultiplicativeGroupElement): - """ - An element of a cactus group. - """ - def __init__(self, parent, data): - """ - Initialize ``self``. - - EXAMPLES:: - - sage: J3 = groups.misc.Cactus(3) - sage: elt = J3.an_element() - sage: TestSuite(elt).run() - """ - self._data = tuple(data) - MultiplicativeGroupElement.__init__(self, parent) - - def _repr_(self): - """ - Return a string representation of ``self``. - - EXAMPLES:: - - sage: J3 = groups.misc.Cactus(3) - sage: J3.one() - 1 - sage: J3.an_element() - s[1,2]*s[2,3]*s[1,3] - """ - if not self._data: - return '1' - return '*'.join(f"s[{i},{j}]" for i,j in self._data) - - def _latex_(self): - """ - Return a latex representation of ``self``. - - EXAMPLES:: - - sage: J3 = groups.misc.Cactus(3) - sage: latex(J3.one()) - 1 - sage: latex(J3.an_element()) - s_{1,2} s_{2,3} s_{1,3} - """ - if not self._data: - return '1' - return " ".join(f"s_{{{i},{j}}}" for i,j in self._data) - - def _unicode_art_(self): - """ - Return unicode art of ``self``. - - EXAMPLES:: - - sage: J4 = groups.misc.Cactus(4) - sage: s12,s13,s14,s23,s24,s34 = J4.gens() - sage: unicode_art(s12 * s23 * s13) - s₁₂ s₂₃ s₁₃ - sage: unicode_art(J4.one()) - 1 - sage: J12 = groups.misc.Cactus(12) - sage: unicode_art(J12.gen(1,3)) - s₁,₃ - sage: unicode_art(J12.gen(3,11)) - s₃,₁₁ - """ - from sage.typeset.unicode_art import unicode_subscript, unicode_art - if not self._data: - return unicode_art('1') - if self.parent()._n < 10: - return unicode_art(' '.join('s{}{}'.format(unicode_subscript(p), unicode_subscript(q)) for p,q in self._data)) - return unicode_art(' '.join('s{},{}'.format(unicode_subscript(p), unicode_subscript(q)) for p,q in self._data)) - - def __hash__(self): - r""" - Return the hash of ``self``. - - EXAMPLES:: - - sage: J3 = groups.misc.Cactus(3) - sage: elt = J3.gen(1,2) * J3.gen(2,3) * J3.gen(1,3) - sage: hash(elt) == hash((((1,2), (2,3), (1,3)))) - True - """ - return hash(self._data) - - def _richcmp_(self, other, op): - r""" - Compare ``self`` and ``other``. - - EXAMPLES:: - - sage: J3 = groups.misc.Cactus(3) - sage: elt = J3.an_element() - sage: elt == J3.one() - False - sage: elt != J3.one() - True - sage: s12,s13,s23 = J3.gens() - sage: elt == s12*s23*s13 - True - """ - return richcmp(self._data, other._data, op) - - def _mul_(self, other): - r""" - Return the product of ``self`` and ``other``. - - EXAMPLES:: - - sage: J3 = groups.misc.Cactus(3) - sage: s12,s13,s23 = J3.gens() - sage: s12*s23 - s[1,2]*s[2,3] - sage: s12*s13 - s[1,2]*s[1,3] - sage: s13*s12 - s[2,3]*s[1,3] - sage: J3.one() * (s13*s12*s13*s12*s23*s13) - s[2,3]*s[1,2]*s[2,3]*s[1,3] - """ - ret = type(self)(self.parent(), self._data + other._data) - ret._normalize() - return ret - - def __invert__(self): - r""" - Return the inverse of ``self``. - - EXAMPLES:: - - sage: J3 = groups.misc.Cactus(3) - sage: s12,s13,s23 = J3.gens() - sage: elt = s12*s23*s13 - sage: ~elt - s[1,2]*s[2,3]*s[1,3] - sage: elt * elt - 1 - """ - ret = type(self)(self.parent(), reversed(self._data)) - ret._normalize() - return ret - - def to_permutation(self): - r""" - Return the image of ``self`` under the canonical projection - to the permutation group. - - EXAMPLES:: - - sage: J3 = groups.misc.Cactus(3) - sage: s12,s13,s23 = J3.gens() - sage: s12.to_permutation() - [2, 1, 3] - sage: s23.to_permutation() - [1, 3, 2] - sage: s13.to_permutation() - [3, 2, 1] - sage: elt = s12*s23*s13 - sage: elt.to_permutation() - [1, 3, 2] - - sage: J7 = groups.misc.Cactus(7) - sage: J7.group_generators()[3,6].to_permutation() - [1, 2, 6, 5, 4, 3, 7] - - We check that this respects the multiplication order - of permutations:: - - sage: P3 = Permutations(3) - sage: elt = s12*s23 - sage: elt.to_permutation() == P3(s12) * P3(s23) - True - sage: Permutations.options.mult='r2l' - sage: elt.to_permutation() == P3(s12) * P3(s23) - True - sage: Permutations.options.mult='l2r' - """ - n = self.parent().n() - P = Permutations(n) - ret = P.one() - for x in self._data: - lst = list(range(1, n + 1)) - lst[x[0] - 1:x[1]] = list(reversed(lst[x[0] - 1:x[1]])) - ret *= P(lst) - return ret - - def _matrix_(self): - r""" - Return ``self`` as a matrix. - - The resulting matrix is the :meth:`geometric representation - ` - of ``self``. - - EXAMPLES:: - - sage: J3 = groups.misc.Cactus(3) - sage: s12,s13,s23 = J3.gens() - sage: s12.to_matrix() - [ -1 0 2*t] - [ 0 1 0] - [ 0 0 1] - sage: (s12*s13).to_matrix() - [2*t 0 -1] - [ 0 -1 0] - [ 1 0 0] - sage: (s13*s23).to_matrix() - [2*t 0 -1] - [ 0 -1 0] - [ 1 0 0] - sage: (s13*s12).to_matrix() - [ 0 0 1] - [ 0 -1 0] - [ -1 0 2*t] - sage: all(x.to_matrix() * y.to_matrix() == (x*y).to_matrix() - ....: for x in J3.gens() for y in J3.gens()) - True - """ - G = self.parent().geometric_representation_generators() - ret = G[(1,2)].parent().one() - for x in self._data: - ret *= G[x] - ret.set_immutable() - return ret - - to_matrix = _matrix_ - - def _normalize(self): - r""" - Return the word for ``self`` in normalized form. - - ALGORITHM: - - We perform the normalization by using the lexicographically - minimum reduced word for the corresponding right-angled Coxeter - group (RACG) element under the (set-theoretic) embedding - introduced by [Most2019]_. This embedding is a group 1-cocycle - and also realizes the cactus group as a subgroup of `W \rtimes S_n`, - where `W` is the RACG (see also [Yu2022]_). See Section 2 - of [BCL2022]_ for precise statements. - - TESTS:: - - sage: J6 = groups.misc.Cactus(6) - sage: s26 = J6.gen(2,6) - sage: s45 = J6.gen(4,5) - sage: s13 = J6.gen(1,3) - sage: s26 * s45 * s13 == s26 * s45 * s13 # indirect doctest - True - - sage: J4 = groups.misc.Cactus(4) - sage: s12,s13,s14,s23,s24,s34 = J4.gens() - sage: s12 * (s12 * s23) - s[2,3] - sage: (s12 * s23) * s23 - s[1,2] - sage: s23 * s13 * s34 - s[2,3]*s[1,3]*s[3,4] - """ - P = self.parent() - n = P._n - G = P._WG # The defining graph - - # Convert to an element in the right-angled Coxeter group - perm = list(range(1,n+1)) - word = [] - for p,q in self._data: - word.append(P._subsets_inv[frozenset(perm[p-1:q])]) - perm[p-1:q] = reversed(perm[p-1:q]) - - # Normalize the word - # This code works for any right-angled Coxeter group - pos = 0 - supp = sorted(set(word)) - while pos < len(word) - 1: - cur = word[pos] - for i in supp: - if i > cur: - break - if G.has_edge(cur, i): - continue - did_swap = False - for j in range(pos+1, len(word)): - if word[j] == i: - word.pop(j) - if cur == i: # canceling s_i s_i = 1 - word.pop(pos) - pos = -1 # start again at the beginning - break - word.insert(pos, i) - did_swap = True - break - if G.has_edge(i, word[j]): - break - if did_swap: - break - pos += 1 - - # Convert back - ret = [] - perm = list(range(1,n+1)) - for i in word: - X = P._subsets[i] - pos = [j for j,val in enumerate(perm) if val in X] - for j in range(len(pos)//2): - perm[pos[j]], perm[pos[-j-1]] = perm[pos[-j-1]], perm[pos[j]] - pos.sort() - assert all(pos[k] + 1 == pos[k+1] for k in range(len(pos)-1)) - ret.append((pos[0]+1, pos[-1]+1)) - - self._data = tuple(ret) - - -class PureCactusGroup(KernelSubgroup): - r""" - The pure cactus group. - - The *pure cactus group* `PJ_n` is the kernel of the natural - surjection of the cactus group `J_n` onto the symmetric group - `S_n`. In particular, we have the following (non-split) exact sequence: - - .. MATH:: - - 1 \longrightarrow PJ_n \longrightarrow J_n \longrightarrow S_n - \longrightarrow 1. - """ - def __init__(self, n): - r""" - Initialize ``self``. - - EXAMPLES:: - - sage: PJ3 = groups.misc.PureCactus(3) - sage: it = iter(PJ3) - sage: elts = [next(it) for _ in range(10)] - sage: TestSuite(PJ3).run(elements=elts) - """ - J = CactusGroup(n) - from sage.groups.perm_gps.permgroup_named import SymmetricGroup - S = SymmetricGroup(n) - KernelSubgroup.__init__(self, S.coerce_map_from(J)) - - def _repr_(self): - """ - Return a string representation of ``self``. - - EXAMPLES:: - - sage: groups.misc.PureCactus(3) - Pure Cactus Group with 3 fruit - """ - return "Pure Cactus Group with {} fruit".format(self.n()) - - def _latex_(self): - r""" - Return a latex representation of ``self``. - - EXAMPLES:: - - sage: PJ3 = groups.misc.PureCactus(3) - sage: latex(PJ3) - PJ_{3} - """ - return "PJ_{{{}}}".format(self.n()) - - @cached_method - def n(self): - """ - Return the value `n`. - - EXAMPLES:: - - sage: PJ3 = groups.misc.PureCactus(3) - sage: PJ3.n() - 3 - """ - return self.ambient().n() - - def gen(self, i): - r""" - Return the ``i``-th generator of ``self``. - - EXAMPLES:: - - sage: PJ3 = groups.misc.PureCactus(3) - sage: PJ3.gen(0) - s[2,3]*s[1,2]*s[2,3]*s[1,3] - sage: PJ3.gen(1) - s[1,2]*s[2,3]*s[1,2]*s[1,3] - sage: PJ3.gen(5) - Traceback (most recent call last): - ... - IndexError: tuple index out of range - """ - return self.gens()[i] - - @cached_method - def gens(self): - r""" - Return the generators of ``self``. - - ALGORITHM: - - We use :wikipedia:`Schreier's_lemma` and compute the traversal - using the lex minimum elements (defined by the order of the - generators of the ambient cactus group). - - EXAMPLES: - - We verify Corollary A.2 of [BCL2022]_:: - - sage: PJ3 = groups.misc.PureCactus(3) - sage: PJ3.gens() - (s[2,3]*s[1,2]*s[2,3]*s[1,3], s[1,2]*s[2,3]*s[1,2]*s[1,3]) - sage: a, b = PJ3.gens() - sage: a * b # they are inverses of each other - 1 - - sage: J3 = groups.misc.Cactus(3) - sage: gen = (J3.gen(1,2)*J3.gen(1,3))^3 - sage: gen - s[1,2]*s[2,3]*s[1,2]*s[1,3] - sage: gen == b - True - """ - from sage.functions.other import factorial - J = self.ambient() - G = J.gens() - one = J.one() - n = self.n() - nfac = factorial(n) - reprs = {one.to_permutation(): one} - next_level = [one] - while len(reprs) < nfac: - cur = next_level - next_level = [] - for val in cur: - for g in G: - temp = val * g - p = temp.to_permutation() - if p in reprs: - continue - reprs[p] = temp - next_level.append(temp) - gens = [] - for s in reprs.values(): - for g in G: - val = s * g * ~(reprs[(s*g).to_permutation()]) - if val == one or val in gens: - continue - gens.append(val) - return tuple([self(g) for g in gens]) diff --git a/src/sage/groups/finitely_presented_catalog.py b/src/sage/groups/finitely_presented_catalog.py index 512e851628b..06d80ab7c0c 100644 --- a/src/sage/groups/finitely_presented_catalog.py +++ b/src/sage/groups/finitely_presented_catalog.py @@ -23,4 +23,3 @@ from .finitely_presented_named import QuaternionPresentation as Quaternion from .finitely_presented_named import AlternatingPresentation as Alternating from .finitely_presented_named import BinaryDihedralPresentation as BinaryDihedral -from .finitely_presented_named import CactusPresentation as Cactus diff --git a/src/sage/groups/finitely_presented_named.py b/src/sage/groups/finitely_presented_named.py index 248049fadb7..ef34854de8b 100644 --- a/src/sage/groups/finitely_presented_named.py +++ b/src/sage/groups/finitely_presented_named.py @@ -12,9 +12,6 @@ - Alternating group, `A_n` of order `n!/2` -- :func:`groups.presentation.Alternating ` -- the `n`-fruit Cactus group, a standard notation for which is `J_n` -- - :func:`groups.presentation.Cactus ` - - Cyclic group, `C_n` of order `n` -- :func:`groups.presentation.Cyclic ` @@ -563,35 +560,3 @@ def BinaryDihedralPresentation(n): x,y,z = F.gens() rls = (x**-2 * y**2, x**-2 * z**n, x**-2 * x*y*z) return FinitelyPresentedGroup(F, rls) - -def CactusPresentation(n): - r""" - Build the `n`-fruit cactus group as a finitely presented group. - - OUTPUT: - - Cactus group `J_n` as a finitely presented group. - - EXAMPLES:: - - sage: J3 = groups.presentation.Cactus(3); J3 - Finitely presented group < s12, s13, s23 | - s12^2, s13^2, s23^2, s13*s12*s13^-1*s23^-1, s13*s23*s13^-1*s12^-1 > - """ - from sage.groups.cactus_group import CactusGroup - G = CactusGroup(n) - F = FreeGroup(G.variable_names()) - gens = F.gens() - rls = [g**2 for g in gens] - Gg = G.group_generators() - K = Gg.keys() - for i,key in enumerate(K): - for j,key2 in enumerate(K): - if i == j: - continue - x,y = (Gg[key] * Gg[key2])._data - if key == x and key2 == y: - continue - elt = gens[i] * gens[j] * ~gens[K.index(y)] * ~gens[K.index(x)] - rls.append(elt) - return FinitelyPresentedGroup(F, tuple(rls)) diff --git a/src/sage/groups/groups_catalog.py b/src/sage/groups/groups_catalog.py index 47e6e230508..e3da7f10780 100644 --- a/src/sage/groups/groups_catalog.py +++ b/src/sage/groups/groups_catalog.py @@ -43,7 +43,6 @@ - Finitely Presented Groups (``groups.presentation.``) - :func:`groups.presentation.Alternating ` - - :func:`groups.presentation.Cactus ` - :func:`groups.presentation.Cyclic ` - :func:`groups.presentation.Dihedral ` - :func:`groups.presentation.DiCyclic ` @@ -66,9 +65,7 @@ - Coxeter, reflection and related groups - :func:`groups.misc.Braid ` - - :func:`groups.misc.Cactus ` - :func:`groups.misc.CoxeterGroup ` - - :func:`groups.misc.PureCactus ` - :func:`groups.misc.ReflectionGroup ` - :class:`groups.misc.RightAngledArtin ` - :func:`groups.misc.WeylGroup ` diff --git a/src/sage/groups/kernel_subgroup.py b/src/sage/groups/kernel_subgroup.py deleted file mode 100644 index 024e8f47b3b..00000000000 --- a/src/sage/groups/kernel_subgroup.py +++ /dev/null @@ -1,225 +0,0 @@ -r""" -Kernel Subgroups - -The kernel of a homomorphism implemented as a subgroup. - -AUTHORS: - -- Travis Scrimshaw (1-2023): Initial version -""" - -# **************************************************************************** -# Copyright (C) 2023 Travis Scrimshaw -# -# Distributed under the terms of the GNU General Public License (GPL) -# https://www.gnu.org/licenses/ -# **************************************************************************** - -from sage.misc.cachefunc import cached_method -from sage.categories.groups import Groups -from sage.structure.element_wrapper import ElementWrapper -from sage.structure.parent import Parent -from sage.structure.unique_representation import UniqueRepresentation - -class KernelSubgroup(UniqueRepresentation, Parent): - r""" - The kernel (normal) subgroup. - - Let `\phi : G \to H` be a group homomorphism. The kernel - `K = \{\phi(g) = 1 | g \in G\}` is a normal subgroup of `G`. - """ - def __init__(self, morphism): - r""" - Initialize ``self``. - - EXAMPLES:: - - sage: S2 = SymmetricGroup(2) - sage: S3 = SymmetricGroup(3) - sage: H = Hom(S3, S2) - sage: phi = H(S2.__call__) - sage: from sage.groups.kernel_subgroup import KernelSubgroup - sage: K = KernelSubgroup(phi) - sage: TestSuite(K).run() - """ - self._morphism = morphism - cat = Groups().Subobjects() - base_cat = morphism.domain().category() - if base_cat in Groups().Finite(): - cat = cat.Finite() - elif base_cat in Groups().Enumerated(): - cat = cat.Enumerated() - Parent.__init__(self, category=cat) - - def _repr_(self): - r""" - Return a string representation of ``self``. - - EXAMPLES:: - - sage: S2 = SymmetricGroup(2) - sage: S3 = SymmetricGroup(3) - sage: H = Hom(S3, S2) - sage: phi = H(S2.__call__) - sage: from sage.groups.kernel_subgroup import KernelSubgroup - sage: KernelSubgroup(phi) - Kernel subgroup defined by Generic morphism: - From: Symmetric group of order 3! as a permutation group - To: Symmetric group of order 2! as a permutation group - """ - return "Kernel subgroup defined by {}".format(self._morphism) - - def gens(self): - r""" - Return the generators of ``self``. - - EXAMPLES:: - - sage: S2 = SymmetricGroup(2) - sage: S3 = SymmetricGroup(3) - sage: H = Hom(S3, S2) - sage: phi = H(S2.__call__) - sage: from sage.groups.kernel_subgroup import KernelSubgroup - sage: K = KernelSubgroup(phi) - sage: K.gens() - ((),) - """ - if self.ambient() in Groups().Finite(): - return tuple(self) - raise NotImplementedError("only implemented for finite groups") - - def defining_morphism(self): - r""" - Return the defining morphism of ``self``. - - EXAMPLES:: - - sage: PJ3 = groups.misc.PureCactus(3) - sage: PJ3.defining_morphism() - Conversion via _from_cactus_group_element map: - From: Cactus Group with 3 fruit - To: Symmetric group of order 3! as a permutation group - """ - return self._morphism - - @cached_method - def ambient(self): - r""" - Return the ambient group of ``self``. - - EXAMPLES:: - - sage: PJ3 = groups.misc.PureCactus(3) - sage: PJ3.ambient() - Cactus Group with 3 fruit - """ - return self._morphism.domain() - - def _an_element_(self): - r""" - Return an element of ``self``. - - EXAMPLES:: - - sage: PJ3 = groups.misc.PureCactus(3) - sage: PJ3.an_element() - 1 - """ - return self.element_class(self, self.ambient().one()) - - def lift(self, x): - r""" - Lift ``x`` to the ambient group of ``self``. - - EXAMPLES:: - - sage: PJ3 = groups.misc.PureCactus(3) - sage: PJ3.lift(PJ3.an_element()).parent() - Cactus Group with 3 fruit - """ - return x.value - - def retract(self, x): - r""" - Convert ``x`` to an element of ``self``. - - EXAMPLES:: - - sage: J3 = groups.misc.Cactus(3) - sage: s12,s13,s23 = J3.group_generators() - sage: PJ3 = groups.misc.PureCactus(3) - sage: elt = PJ3.retract(s23*s12*s23*s13); elt - s[2,3]*s[1,2]*s[2,3]*s[1,3] - sage: elt.parent() is PJ3 - True - """ - return self._element_constructor_(x) - - def _element_constructor_(self, x): - r""" - Construct an element of ``self`` from ``x``. - - EXAMPLES:: - - sage: J3 = groups.misc.Cactus(3) - sage: s12,s13,s23 = J3.group_generators() - sage: PJ3 = groups.misc.PureCactus(3) - sage: elt = PJ3(s23*s12*s23*s13) - sage: elt.parent() is PJ3 - True - """ - if self._morphism(x) != self._morphism.codomain().one(): - raise ValueError("{} is not in the kernel of {}".format(x, self._morphism)) - return self.element_class(self, x) - - def __iter__(self): - r""" - Iterate through ``self``. - - EXAMPLES:: - - sage: S2 = SymmetricGroup(2) - sage: S3 = SymmetricGroup(3) - sage: H = Hom(S3, S2) - sage: phi = H(S2.__call__) - sage: from sage.groups.kernel_subgroup import KernelSubgroup - sage: K = KernelSubgroup(phi) - sage: list(K) - [()] - """ - for g in self.ambient(): - try: - yield self(g) - except ValueError: - pass - - class Element(ElementWrapper): - def _mul_(self, other): - r""" - Multiply ``self`` and ``other``. - - EXAMPLES:: - - sage: J3 = groups.misc.Cactus(3) - sage: s12,s13,s23 = J3.group_generators() - sage: PJ3 = groups.misc.PureCactus(3) - sage: elt = PJ3(s23*s12*s23*s13) - sage: elt * elt - s[2,3]*s[1,2]*s[2,3]*s[1,2]*s[2,3]*s[1,2] - """ - return type(self)(self.parent(), self.value * other.value) - - def __invert__(self): - r""" - Return the inverse of ``self``. - - EXAMPLES:: - - sage: J3 = groups.misc.Cactus(3) - sage: s12,s13,s23 = J3.group_generators() - sage: PJ3 = groups.misc.PureCactus(3) - sage: elt = PJ3(s23*s12*s23*s13) - sage: ~elt - s[1,2]*s[2,3]*s[1,2]*s[1,3] - """ - return type(self)(self.parent(), ~self.value) diff --git a/src/sage/groups/misc_gps/misc_groups_catalog.py b/src/sage/groups/misc_gps/misc_groups_catalog.py index 5396677d0b1..40d9d66d15d 100644 --- a/src/sage/groups/misc_gps/misc_groups_catalog.py +++ b/src/sage/groups/misc_gps/misc_groups_catalog.py @@ -23,5 +23,3 @@ from sage.combinat.root_system.weyl_group import WeylGroup from sage.groups.raag import RightAngledArtinGroup as RightAngledArtin from sage.combinat.root_system.reflection_group_real import ReflectionGroup -from sage.groups.cactus_group import CactusGroup as Cactus -from sage.groups.cactus_group import PureCactusGroup as PureCactus diff --git a/src/sage/groups/perm_gps/permgroup_named.py b/src/sage/groups/perm_gps/permgroup_named.py index 0381e1912a1..a3be9f974fe 100644 --- a/src/sage/groups/perm_gps/permgroup_named.py +++ b/src/sage/groups/perm_gps/permgroup_named.py @@ -331,42 +331,6 @@ def _repr_(self): """ return "Symmetric group of order {}! as a permutation group".format(self.degree()) - def _coerce_map_from_(self, G): - """ - Return if there is a coercion map from ``G`` into ``self``. - - EXAMPLES:: - - sage: J3 = groups.misc.Cactus(3) - sage: S5 = SymmetricGroup(5) - sage: S5.coerce_map_from(J3) - Conversion via _from_cactus_group_element map: - From: Cactus Group with 3 fruit - To: Symmetric group of order 5! as a permutation group - sage: S2 = SymmetricGroup(2) - sage: S2._coerce_map_from_(J3) is None - True - """ - from sage.groups.cactus_group import CactusGroup - if isinstance(G, CactusGroup) and G._n <= self._deg: - return self._from_cactus_group_element - return super()._coerce_map_from_(G) - - def _from_cactus_group_element(self, x): - """ - Return an element of ``self`` from a cactus group element. - - EXAMPLES:: - - sage: J3 = groups.misc.Cactus(3) - sage: s12,s13,s23 = J3.gens() - sage: elt = s12*s23*s13 - sage: S5 = SymmetricGroup(5) - sage: S5._from_cactus_group_element(elt) - (2,3) - """ - return self(x.to_permutation()) - def cartan_type(self): r""" Return the Cartan type of ``self`` diff --git a/src/sage/interfaces/fricas.py b/src/sage/interfaces/fricas.py index 6097c850862..dc2ce71f26a 100644 --- a/src/sage/interfaces/fricas.py +++ b/src/sage/interfaces/fricas.py @@ -891,10 +891,10 @@ def __reduce__(self): """ EXAMPLES:: - sage: FriCAS().__reduce__() + sage: fricas.__reduce__() # optional - fricas (, ()) - sage: f, args = _ - sage: f(*args) + sage: f, args = _ # optional - fricas + sage: f(*args) # optional - fricas FriCAS """ return reduce_load_fricas, tuple([]) @@ -2132,8 +2132,8 @@ def reduce_load_fricas(): EXAMPLES:: - sage: from sage.interfaces.fricas import reduce_load_fricas - sage: reduce_load_fricas() + sage: from sage.interfaces.fricas import reduce_load_fricas # optional - fricas + sage: reduce_load_fricas() # optional - fricas FriCAS """ return fricas diff --git a/src/sage/libs/giac/giac.pyx b/src/sage/libs/giac/giac.pyx index ccad5169836..4e451dba5e7 100644 --- a/src/sage/libs/giac/giac.pyx +++ b/src/sage/libs/giac/giac.pyx @@ -374,7 +374,8 @@ def _giac(s): sage: x = libgiac('x') sage: (1+2*sin(3*x)).solve(x).simplify() - ...list[-pi/18,7*pi/18] + Warning, argument is not an equation, solving 1+2*sin(3*x)=0 + list[-pi/18,7*pi/18] sage: libgiac.solve('sin(3*x)>2*sin(x)',x) Traceback (most recent call last): diff --git a/src/sage/libs/singular/decl.pxd b/src/sage/libs/singular/decl.pxd index 747a6b1e2fb..8e3ac314b67 100644 --- a/src/sage/libs/singular/decl.pxd +++ b/src/sage/libs/singular/decl.pxd @@ -574,7 +574,7 @@ cdef extern from "singular/Singular/libsingular.h": # gets a component out of a polynomial vector - poly *pTakeOutComp(poly **, int) + poly *pTakeOutComp1(poly **, int) # deep copy p diff --git a/src/sage/libs/singular/singular.pyx b/src/sage/libs/singular/singular.pyx index 3a1271cd59f..d8ea7b07f3c 100644 --- a/src/sage/libs/singular/singular.pyx +++ b/src/sage/libs/singular/singular.pyx @@ -1726,21 +1726,20 @@ cdef int overflow_check(unsigned long e, ring *_ring) except -1: Whether an overflow occurs or not partially depends on the number of variables in the ring. See trac ticket - :trac:`11856`. + :trac:`11856`. With Singular 4, it is by default optimized + for at least 4 variables on 64-bit and 2 variables on 32-bit, + which in both cases makes a maximal default exponent of + 2^16-1. EXAMPLES:: sage: P. = QQ[] - sage: y^(2^30) - Traceback (most recent call last): # 32-bit - ... # 32-bit - OverflowError: exponent overflow (1073741824) # 32-bit - y^1073741824 # 64-bit - sage: y^2^32 + sage: y^(2^16-1) + y^65535 + sage: y^2^16 Traceback (most recent call last): ... - OverflowError: Python int too large to convert to C unsigned long # 32-bit - OverflowError: exponent overflow (4294967296) # 64-bit + OverflowError: exponent overflow (65536) """ if unlikely(e > _ring.bitmask): raise OverflowError("exponent overflow (%d)"%(e)) diff --git a/src/sage/misc/cachefunc.pyx b/src/sage/misc/cachefunc.pyx index 78c70a2fb69..cea3071115d 100644 --- a/src/sage/misc/cachefunc.pyx +++ b/src/sage/misc/cachefunc.pyx @@ -69,7 +69,7 @@ approach is still needed for cpdef methods:: sage: cython_code = ['cpdef test_meth(self,x):', ....: ' "some doc for a wrapped cython method"', ....: ' return -x', - ....: 'from sage.misc.cachefunc import cached_method', + ....: 'from sage.all import cached_method', ....: 'from sage.structure.parent cimport Parent', ....: 'cdef class MyClass(Parent):', ....: ' @cached_method', @@ -107,10 +107,7 @@ By :trac:`11115`, even if a parent does not allow attribute assignment, it can inherit a cached method from the parent class of a category (previously, the cache would have been broken):: - sage: cython_code = ["from sage.misc.cachefunc import cached_method", - ....: "from sage.misc.cachefunc import cached_in_parent_method", - ....: "from sage.categories.category import Category", - ....: "from sage.categories.objects import Objects", + sage: cython_code = ["from sage.all import cached_method, cached_in_parent_method, Category, Objects", ....: "class MyCategory(Category):", ....: " @cached_method", ....: " def super_categories(self):", diff --git a/src/sage/misc/fast_methods.pyx b/src/sage/misc/fast_methods.pyx index d3fd260f55f..800bd798fb6 100644 --- a/src/sage/misc/fast_methods.pyx +++ b/src/sage/misc/fast_methods.pyx @@ -311,7 +311,7 @@ class Singleton(WithEqualityById, metaclass=ClasscallMetaclass): EXAMPLES:: sage: from sage.misc.fast_methods import Singleton - sage: class C(Singleton, Parent): + sage: class C(Singleton, Parent): ....: def __init__(self): ....: print("creating singleton") ....: Parent.__init__(self, base=ZZ, category=Rings()) @@ -321,7 +321,7 @@ class Singleton(WithEqualityById, metaclass=ClasscallMetaclass): sage: __main__.C = C # ... in doctests sage: loads(dumps(c)) is copy(c) is C() # indirect doctest True - """ + """ return self def __reduce__(self): @@ -332,7 +332,7 @@ class Singleton(WithEqualityById, metaclass=ClasscallMetaclass): EXAMPLES:: sage: from sage.misc.fast_methods import Singleton - sage: class C(Singleton, Parent): + sage: class C(Singleton, Parent): ....: def __init__(self): ....: print("creating singleton") ....: Parent.__init__(self, base=ZZ, category=Rings()) @@ -349,5 +349,5 @@ class Singleton(WithEqualityById, metaclass=ClasscallMetaclass): instance.If the class is replaced by a sub-sub-class after creation of the instance, pickling fails. See the doctest in :class:`Singleton`. - """ + """ return self.__class__, () diff --git a/src/sage/misc/functional.py b/src/sage/misc/functional.py index 40683070269..7d2ee692e13 100644 --- a/src/sage/misc/functional.py +++ b/src/sage/misc/functional.py @@ -1822,7 +1822,7 @@ def squarefree_part(x): return x.squarefree_part() except AttributeError: pass - from sage.arith.misc import factor + from sage.arith.all import factor from sage.structure.all import parent F = factor(x) n = parent(x)(1) diff --git a/src/sage/misc/latex.py b/src/sage/misc/latex.py index 5dc3fbe5ecd..04df1b0a4b3 100644 --- a/src/sage/misc/latex.py +++ b/src/sage/misc/latex.py @@ -409,7 +409,7 @@ def float_function(x): sage: latex(float(2e-13)) 2 \times 10^{-13} """ - from sage.rings.real_double import RDF + from sage.all import RDF return latex(RDF(x)) diff --git a/src/sage/misc/lazy_import.pyx b/src/sage/misc/lazy_import.pyx index a60c26e1b90..a5bc788d386 100644 --- a/src/sage/misc/lazy_import.pyx +++ b/src/sage/misc/lazy_import.pyx @@ -9,7 +9,7 @@ use. EXAMPLES:: - sage: lazy_import('sage.rings.integer_ring', 'ZZ') + sage: lazy_import('sage.rings.all', 'ZZ') sage: type(ZZ) sage: ZZ(4.0) @@ -20,7 +20,7 @@ during Sage's startup. In case a lazy import's sole purpose is to break a circular reference and it is known to be resolved at startup time, one can use the ``at_startup`` option:: - sage: lazy_import('sage.rings.integer_ring', 'ZZ', at_startup=True) + sage: lazy_import('sage.rings.all', 'ZZ', at_startup=True) This option can also be used as an intermediate step toward not importing by default a module that is used in several places, some of @@ -156,7 +156,7 @@ cpdef test_fake_startup(): EXAMPLES:: sage: sage.misc.lazy_import.test_fake_startup() - sage: lazy_import('sage.rings.integer_ring', 'ZZ', 'my_ZZ') + sage: lazy_import('sage.rings.all', 'ZZ', 'my_ZZ') sage: my_ZZ(123) doctest:warning... UserWarning: Resolving lazy import ZZ during startup @@ -174,7 +174,7 @@ cdef class LazyImport(): EXAMPLES:: sage: from sage.misc.lazy_import import LazyImport - sage: my_integer = LazyImport('sage.rings.integer', 'Integer') + sage: my_integer = LazyImport('sage.rings.all', 'Integer') sage: my_integer(4) 4 sage: my_integer('101', base=2) @@ -199,7 +199,7 @@ cdef class LazyImport(): EXAMPLES:: sage: from sage.misc.lazy_import import LazyImport - sage: lazy_ZZ = LazyImport('sage.rings.integer_ring', 'ZZ') + sage: lazy_ZZ = LazyImport('sage.rings.all', 'ZZ') sage: type(lazy_ZZ) sage: lazy_ZZ._get_object() is ZZ @@ -235,7 +235,7 @@ cdef class LazyImport(): EXAMPLES:: sage: from sage.misc.lazy_import import LazyImport - sage: my_integer_ring = LazyImport('sage.rings.integer_ring', 'ZZ') + sage: my_integer_ring = LazyImport('sage.rings.all', 'ZZ') sage: my_integer_ring._object is None True sage: my_integer_ring._get_object() @@ -316,7 +316,7 @@ cdef class LazyImport(): EXAMPLES:: sage: from sage.misc.lazy_import import LazyImport - sage: my_isprime = LazyImport('sage.arith.misc', 'is_prime') + sage: my_isprime = LazyImport('sage.all', 'is_prime') sage: my_isprime.__doc__ is is_prime.__doc__ True @@ -336,7 +336,7 @@ cdef class LazyImport(): EXAMPLES:: sage: from sage.misc.lazy_import import LazyImport - sage: my_isprime = LazyImport('sage.arith.misc', 'is_prime') + sage: my_isprime = LazyImport('sage.all', 'is_prime') sage: 'def is_prime(' in my_isprime._sage_src_() True """ @@ -349,7 +349,7 @@ cdef class LazyImport(): EXAMPLES:: sage: from sage.misc.lazy_import import LazyImport - sage: rm = LazyImport('sage.matrix.special', 'random_matrix') + sage: rm = LazyImport('sage.all', 'random_matrix') sage: rm._sage_argspec_() FullArgSpec(args=['ring', 'nrows', 'ncols', 'algorithm', 'implementation'], varargs='args', varkw='kwds', defaults=(None, 'randomize', None), @@ -365,7 +365,7 @@ cdef class LazyImport(): EXAMPLES:: sage: from sage.misc.lazy_import import LazyImport - sage: my_integer = LazyImport('sage.rings.integer', 'Integer') + sage: my_integer = LazyImport('sage.rings.all', 'Integer') sage: my_integer.sqrt is Integer.sqrt True """ @@ -382,7 +382,7 @@ cdef class LazyImport(): EXAMPLES:: sage: from sage.misc.lazy_import import LazyImport - sage: lazy_ZZ = LazyImport('sage.rings.integer_ring', 'ZZ') + sage: lazy_ZZ = LazyImport('sage.rings.all', 'ZZ') sage: dir(lazy_ZZ) == dir(ZZ) True """ @@ -395,7 +395,7 @@ cdef class LazyImport(): EXAMPLES:: sage: from sage.misc.lazy_import import LazyImport - sage: my_isprime = LazyImport('sage.arith.misc', 'is_prime') + sage: my_isprime = LazyImport('sage.all', 'is_prime') sage: is_prime(12) == my_isprime(12) True sage: is_prime(13) == my_isprime(13) @@ -408,7 +408,7 @@ cdef class LazyImport(): TESTS:: sage: from sage.misc.lazy_import import LazyImport - sage: lazy_ZZ = LazyImport('sage.rings.integer_ring', 'ZZ') + sage: lazy_ZZ = LazyImport('sage.rings.all', 'ZZ') sage: repr(lazy_ZZ) == repr(ZZ) True """ @@ -423,7 +423,7 @@ cdef class LazyImport(): TESTS:: sage: from sage.misc.lazy_import import LazyImport - sage: lazy_ZZ = LazyImport('sage.rings.integer_ring', 'ZZ') + sage: lazy_ZZ = LazyImport('sage.rings.all', 'ZZ') sage: str(lazy_ZZ) == str(ZZ) True """ @@ -434,7 +434,7 @@ cdef class LazyImport(): TESTS:: sage: from sage.misc.lazy_import import LazyImport - sage: lazy_ZZ = LazyImport('sage.rings.integer_ring', 'ZZ') + sage: lazy_ZZ = LazyImport('sage.rings.all', 'ZZ') sage: bool(lazy_ZZ) == bool(ZZ) True """ @@ -445,7 +445,7 @@ cdef class LazyImport(): TESTS:: sage: from sage.misc.lazy_import import LazyImport - sage: lazy_ZZ = LazyImport('sage.rings.integer_ring', 'ZZ') + sage: lazy_ZZ = LazyImport('sage.rings.all', 'ZZ') sage: hash(lazy_ZZ) == hash(ZZ) True """ @@ -456,7 +456,7 @@ cdef class LazyImport(): TESTS:: sage: from sage.misc.lazy_import import LazyImport - sage: lazy_ZZ = LazyImport('sage.rings.integer_ring', 'ZZ') + sage: lazy_ZZ = LazyImport('sage.rings.all', 'ZZ') sage: lazy_ZZ == ZZ True sage: lazy_ZZ == RR @@ -482,17 +482,16 @@ cdef class LazyImport(): Here we show how to take a function in a module, and lazy import it as a method of a class. For the sake of this - example, we add manually a function in :mod:`sage.all__sagemath_objects`:: + example, we add manually a function in sage.all:: sage: def my_method(self): return self - sage: import sage.all__sagemath_objects - sage: sage.all__sagemath_objects.my_method = my_method + sage: sage.all.my_method = my_method Now we lazy import it as a method of a new class ``Foo``:: sage: from sage.misc.lazy_import import LazyImport sage: class Foo(): - ....: my_method = LazyImport('sage.all__sagemath_objects', 'my_method') + ....: my_method = LazyImport('sage.all', 'my_method') Now we can use it as a usual method:: @@ -518,7 +517,7 @@ cdef class LazyImport(): ``__get__`` needs to manually modify the class dict:: sage: class Foo(): - ....: lazy_import('sage.plot.plot', 'plot') + ....: lazy_import('sage.all', 'plot') sage: class Bar(Foo): ....: pass sage: type(Foo.__dict__['plot']) @@ -569,13 +568,12 @@ cdef class LazyImport(): TESTS:: sage: from sage.misc.lazy_import import LazyImport - sage: import sage.all__sagemath_objects - sage: sage.all__sagemath_objects.foo = list(range(10)) - sage: lazy_foo = LazyImport('sage.all__sagemath_objects', 'foo') + sage: sage.all.foo = list(range(10)) + sage: lazy_foo = LazyImport('sage.all', 'foo') sage: lazy_foo[1] = 100 sage: print(lazy_foo) [0, 100, 2, 3, 4, 5, 6, 7, 8, 9] - sage: sage.all__sagemath_objects.foo + sage: sage.all.foo [0, 100, 2, 3, 4, 5, 6, 7, 8, 9] """ self.get_object()[key] = value @@ -585,13 +583,12 @@ cdef class LazyImport(): TESTS:: sage: from sage.misc.lazy_import import LazyImport - sage: import sage.all__sagemath_objects - sage: sage.all__sagemath_objects.foo = list(range(10)) - sage: lazy_foo = LazyImport('sage.all__sagemath_objects', 'foo') + sage: sage.all.foo = list(range(10)) + sage: lazy_foo = LazyImport('sage.all', 'foo') sage: del lazy_foo[1] sage: print(lazy_foo) [0, 2, 3, 4, 5, 6, 7, 8, 9] - sage: print(sage.all__sagemath_objects.foo) + sage: print(sage.all.foo) [0, 2, 3, 4, 5, 6, 7, 8, 9] """ del self.get_object()[key] @@ -626,9 +623,8 @@ cdef class LazyImport(): """ TESTS:: - sage: import sage.all__sagemath_objects - sage: sage.all__sagemath_objects.foo = 10 - sage: lazy_import('sage.all__sagemath_objects', 'foo') + sage: sage.all.foo = 10 + sage: lazy_import('sage.all', 'foo') sage: foo + 1 11 """ @@ -638,9 +634,8 @@ cdef class LazyImport(): """ TESTS:: - sage: import sage.all__sagemath_objects - sage: sage.all__sagemath_objects.foo = 10 - sage: lazy_import('sage.all__sagemath_objects', 'foo') + sage: sage.all.foo = 10 + sage: lazy_import('sage.all', 'foo') sage: foo - 1 9 """ @@ -650,9 +645,8 @@ cdef class LazyImport(): """ TESTS:: - sage: import sage.all__sagemath_objects - sage: sage.all__sagemath_objects.foo = 10 - sage: lazy_import('sage.all__sagemath_objects', 'foo') + sage: sage.all.foo = 10 + sage: lazy_import('sage.all', 'foo') sage: foo * 2 20 """ @@ -663,9 +657,8 @@ cdef class LazyImport(): TESTS:: sage: from sympy import Matrix - sage: import sage.all__sagemath_objects - sage: sage.all__sagemath_objects.foo = Matrix([[1,1],[0,1]]) - sage: lazy_import('sage.all__sagemath_objects', 'foo') + sage: sage.all.foo = Matrix([[1,1],[0,1]]) + sage: lazy_import('sage.all', 'foo') sage: foo.__matmul__(foo) Matrix([ [1, 2], @@ -677,9 +670,8 @@ cdef class LazyImport(): """ TESTS:: - sage: import sage.all__sagemath_objects - sage: sage.all__sagemath_objects.foo = 10 - sage: lazy_import('sage.all__sagemath_objects', 'foo') + sage: sage.all.foo = 10 + sage: lazy_import('sage.all', 'foo') sage: foo // 3 3 """ @@ -689,9 +681,8 @@ cdef class LazyImport(): """ TESTS:: - sage: import sage.all__sagemath_objects - sage: sage.all__sagemath_objects.foo = 10 - sage: lazy_import('sage.all__sagemath_objects', 'foo') + sage: sage.all.foo = 10 + sage: lazy_import('sage.all', 'foo') sage: operator.truediv(foo, 3) 10/3 """ @@ -701,9 +692,8 @@ cdef class LazyImport(): """ TESTS:: - sage: import sage.all__sagemath_objects - sage: sage.all__sagemath_objects.foo = 10 - sage: lazy_import('sage.all__sagemath_objects', 'foo') + sage: sage.all.foo = 10 + sage: lazy_import('sage.all', 'foo') sage: foo ** 2 100 """ @@ -713,9 +703,8 @@ cdef class LazyImport(): """ TESTS:: - sage: import sage.all__sagemath_objects - sage: sage.all__sagemath_objects.foo = 10 - sage: lazy_import('sage.all__sagemath_objects', 'foo') + sage: sage.all.foo = 10 + sage: lazy_import('sage.all', 'foo') sage: foo % 7 3 """ @@ -725,9 +714,8 @@ cdef class LazyImport(): """ TESTS:: - sage: import sage.all__sagemath_objects - sage: sage.all__sagemath_objects.foo = 10 - sage: lazy_import('sage.all__sagemath_objects', 'foo') + sage: sage.all.foo = 10 + sage: lazy_import('sage.all', 'foo') sage: foo << 3 80 """ @@ -737,9 +725,8 @@ cdef class LazyImport(): """ TESTS:: - sage: import sage.all__sagemath_objects - sage: sage.all__sagemath_objects.foo = 10 - sage: lazy_import('sage.all__sagemath_objects', 'foo') + sage: sage.all.foo = 10 + sage: lazy_import('sage.all', 'foo') sage: foo >> 2 2 """ @@ -749,9 +736,8 @@ cdef class LazyImport(): """ TESTS:: - sage: import sage.all__sagemath_objects - sage: sage.all__sagemath_objects.foo = 10 - sage: lazy_import('sage.all__sagemath_objects', 'foo') + sage: sage.all.foo = 10 + sage: lazy_import('sage.all', 'foo') sage: foo & 7 2 """ @@ -761,9 +747,8 @@ cdef class LazyImport(): """ TESTS:: - sage: import sage.all__sagemath_objects - sage: sage.all__sagemath_objects.foo = 10 - sage: lazy_import('sage.all__sagemath_objects', 'foo') + sage: sage.all.foo = 10 + sage: lazy_import('sage.all', 'foo') sage: foo | 7 15 """ @@ -773,9 +758,8 @@ cdef class LazyImport(): """ TESTS:: - sage: import sage.all__sagemath_objects - sage: sage.all__sagemath_objects.foo = 10 - sage: lazy_import('sage.all__sagemath_objects', 'foo') + sage: sage.all.foo = 10 + sage: lazy_import('sage.all', 'foo') sage: foo ^^ 7 13 """ @@ -785,9 +769,8 @@ cdef class LazyImport(): """ TESTS:: - sage: import sage.all__sagemath_objects - sage: sage.all__sagemath_objects.foo = 10 - sage: lazy_import('sage.all__sagemath_objects', 'foo') + sage: sage.all.foo = 10 + sage: lazy_import('sage.all', 'foo') sage: -foo -10 """ @@ -797,9 +780,8 @@ cdef class LazyImport(): """ TESTS:: - sage: import sage.all__sagemath_objects - sage: sage.all__sagemath_objects.foo = 10 - sage: lazy_import('sage.all__sagemath_objects', 'foo') + sage: sage.all.foo = 10 + sage: lazy_import('sage.all', 'foo') sage: +foo 10 """ @@ -809,9 +791,8 @@ cdef class LazyImport(): """ TESTS:: - sage: import sage.all__sagemath_objects - sage: sage.all__sagemath_objects.foo = -1000 - sage: lazy_import('sage.all__sagemath_objects', 'foo') + sage: sage.all.foo = -1000 + sage: lazy_import('sage.all', 'foo') sage: abs(foo) 1000 """ @@ -821,9 +802,8 @@ cdef class LazyImport(): """ TESTS:: - sage: import sage.all__sagemath_objects - sage: sage.all__sagemath_objects.foo = 10 - sage: lazy_import('sage.all__sagemath_objects', 'foo') + sage: sage.all.foo = 10 + sage: lazy_import('sage.all', 'foo') sage: ~foo 1/10 """ @@ -833,9 +813,8 @@ cdef class LazyImport(): """ TESTS:: - sage: import sage.all__sagemath_objects - sage: sage.all__sagemath_objects.foo = 10 - sage: lazy_import('sage.all__sagemath_objects', 'foo') + sage: sage.all.foo = 10 + sage: lazy_import('sage.all', 'foo') sage: complex(foo) (10+0j) """ @@ -845,9 +824,8 @@ cdef class LazyImport(): """ TESTS:: - sage: import sage.all__sagemath_objects - sage: sage.all__sagemath_objects.foo = 10 - sage: lazy_import('sage.all__sagemath_objects', 'foo') + sage: sage.all.foo = 10 + sage: lazy_import('sage.all', 'foo') sage: int(foo) 10 """ @@ -857,9 +835,8 @@ cdef class LazyImport(): """ TESTS:: - sage: import sage.all__sagemath_objects - sage: sage.all__sagemath_objects.foo = 10 - sage: lazy_import('sage.all__sagemath_objects', 'foo') + sage: sage.all.foo = 10 + sage: lazy_import('sage.all', 'foo') sage: float(foo) 10.0 """ @@ -869,9 +846,8 @@ cdef class LazyImport(): """ TESTS:: - sage: import sage.all__sagemath_objects - sage: sage.all__sagemath_objects.foo = 10 - sage: lazy_import('sage.all__sagemath_objects', 'foo') + sage: sage.all.foo = 10 + sage: lazy_import('sage.all', 'foo') sage: oct(foo) '0o12' """ @@ -881,9 +857,8 @@ cdef class LazyImport(): """ TESTS:: - sage: import sage.all__sagemath_objects - sage: sage.all__sagemath_objects.foo = 10 - sage: lazy_import('sage.all__sagemath_objects', 'foo') + sage: sage.all.foo = 10 + sage: lazy_import('sage.all', 'foo') sage: hex(foo) '0xa' """ @@ -893,9 +868,8 @@ cdef class LazyImport(): """ TESTS:: - sage: import sage.all__sagemath_objects - sage: sage.all__sagemath_objects.foo = 10 - sage: lazy_import('sage.all__sagemath_objects', 'foo') + sage: sage.all.foo = 10 + sage: lazy_import('sage.all', 'foo') sage: list(range(100))[foo] 10 """ @@ -907,14 +881,14 @@ cdef class LazyImport(): TESTS:: + sage: from sage.misc.lazy_import import LazyImport - sage: import sage.all__sagemath_objects - sage: sage.all__sagemath_objects.foo = [[1,2], 3] - sage: lazy_foo = LazyImport('sage.all__sagemath_objects', 'foo') + sage: sage.all.foo = [[1,2], 3] + sage: lazy_foo = LazyImport('sage.all', 'foo') sage: a = copy(lazy_foo) - sage: a is sage.all__sagemath_objects.foo # copy + sage: a is sage.all.foo # copy False - sage: a[0] is sage.all__sagemath_objects.foo[0] # copy but not deep + sage: a[0] is sage.all.foo[0] # copy but not deep True sage: type(lazy_foo) is LazyImport True @@ -929,13 +903,12 @@ cdef class LazyImport(): TESTS:: sage: from sage.misc.lazy_import import LazyImport - sage: import sage.all__sagemath_objects - sage: sage.all__sagemath_objects.foo = [[1,2], 3] - sage: lazy_foo = LazyImport('sage.all__sagemath_objects', 'foo') + sage: sage.all.foo = [[1,2], 3] + sage: lazy_foo = LazyImport('sage.all', 'foo') sage: a = deepcopy(lazy_foo) - sage: a is sage.all__sagemath_objects.foo # copy + sage: a is sage.all.foo # copy False - sage: a[0] is sage.all__sagemath_objects.foo[0] # deep copy + sage: a[0] is sage.all.foo[0] # deep copy False sage: type(lazy_foo) is LazyImport True @@ -1023,27 +996,27 @@ def lazy_import(module, names, as_=None, *, EXAMPLES:: - sage: lazy_import('sage.rings.integer_ring', 'ZZ') + sage: lazy_import('sage.rings.all', 'ZZ') sage: type(ZZ) sage: ZZ(4.0) 4 - sage: lazy_import('sage.rings.real_double', 'RDF', 'my_RDF') + sage: lazy_import('sage.rings.all', 'RDF', 'my_RDF') sage: my_RDF._get_object() is RDF True sage: my_RDF(1/2) 0.5 - sage: lazy_import('sage.rings.rational_field', ['QQ', 'frac'], ['my_QQ', 'my_frac']) + sage: lazy_import('sage.all', ['QQ', 'RR'], ['my_QQ', 'my_RR']) sage: my_QQ._get_object() is QQ True - sage: my_frac._get_object() is sage.rings.rational_field.frac + sage: my_RR._get_object() is RR True Upon the first use, the object is injected directly into the calling namespace:: - sage: lazy_import('sage.rings.integer_ring', 'ZZ', 'my_ZZ') + sage: lazy_import('sage.all', 'ZZ', 'my_ZZ') sage: my_ZZ is ZZ False sage: my_ZZ(37) @@ -1054,7 +1027,7 @@ def lazy_import(module, names, as_=None, *, We check that :func:`lazy_import` also works for methods:: sage: class Foo(): - ....: lazy_import('sage.plot.plot', 'plot') + ....: lazy_import('sage.all', 'plot') sage: class Bar(Foo): ....: pass sage: type(Foo.__dict__['plot']) @@ -1066,16 +1039,16 @@ def lazy_import(module, names, as_=None, *, If deprecated then a deprecation warning is issued:: - sage: lazy_import('sage.rings.padics.factory', 'Qp', 'my_Qp', deprecation=14275) + sage: lazy_import('sage.all', 'Qp', 'my_Qp', deprecation=14275) sage: my_Qp(5) doctest:...: DeprecationWarning: - Importing my_Qp from here is deprecated; please use "from sage.rings.padics.factory import Qp as my_Qp" instead. + Importing my_Qp from here is deprecated; please use "from sage.all import Qp as my_Qp" instead. See http://trac.sagemath.org/14275 for details. 5-adic Field with capped relative precision 20 An example of deprecation with a message:: - sage: lazy_import('sage.rings.padics.factory', 'Qp', 'my_Qp_msg', deprecation=(14275, "This is an example.")) + sage: lazy_import('sage.all', 'Qp', 'my_Qp_msg', deprecation=(14275, "This is an example.")) sage: my_Qp_msg(5) doctest:...: DeprecationWarning: This is an example. See http://trac.sagemath.org/14275 for details. @@ -1202,7 +1175,7 @@ def attributes(a): EXAMPLES:: sage: from sage.misc.lazy_import import attributes - sage: lazy_import("sage.structure.unique_representation", "foo") + sage: lazy_import("sage.all", "foo") sage: attributes(foo)['_namespace'] is globals() True sage: D = attributes(foo) @@ -1211,7 +1184,7 @@ def attributes(a): {'_as_name': 'foo', '_at_startup': False, '_deprecation': None, - '_module': 'sage.structure.unique_representation', + '_module': 'sage.all', '_name': 'foo', '_object': None} """ diff --git a/src/sage/misc/persist.pyx b/src/sage/misc/persist.pyx index cbdbeadeb80..3ac5f1cc2b0 100644 --- a/src/sage/misc/persist.pyx +++ b/src/sage/misc/persist.pyx @@ -298,7 +298,7 @@ def _base_dumps(obj, compress=True): global already_pickled gherkin = SagePickler.dumps(obj) - already_pickled = { } + already_pickled = { } if compress: return comp.compress(gherkin) diff --git a/src/sage/misc/replace_dot_all.py b/src/sage/misc/replace_dot_all.py deleted file mode 100644 index 320a5a15c06..00000000000 --- a/src/sage/misc/replace_dot_all.py +++ /dev/null @@ -1,464 +0,0 @@ -r""" -Implementation of the command ``sage --fiximports``. - -This file provides a tool to fix the modularization antipattern ``namespace_pkg_all_import`` -reported by ``tox -e relint``. Sage library code should not import from ``sage.PAC.KAGE.all`` -when ``sage.PAC.KAGE`` is an implicit namespace package. - -AUTHORS: - -- Alex Chandler -- Matthias Köppe - -INSTRUCTIONS: - -To fix the above issue for all Python and Cython source files (``.py``, ``.pyx``, ``.pxi``) files in the ``src/sage`` directory, -run the following from a terminal in ``SAGE_ROOT`` :: - - ./sage -python src/sage/misc/replace_dot_all.py - -or :: - - ./sage --fiximports - -Running replace_dot_all.py will call the function :func:`walkdir_replace_dot_all` which walks through all Python and Cython source files -and replaces certain ``from sage.PAC.KAGE.all import something`` (those matching the pattern above) -with the correct ``import`` statement by applying the function :func:`~sage.misc.dev_tools.import_statements`. - -The user can also pass subdirectories of ``src/sage`` or specific files to fix. For example :: - - ./sage -python src/sage/misc/replace_dot_all.py src/sage/arith - -will fix all files in ``src/sage/arith`` and :: - - ./sage -python src/sage/misc/replace_dot_all.py src/sage/arith/functions.pyx - -will fix the file ``src/sage/arith/functions.py``. The file extension is necessary in the case of a specific file. The user can also -pass the verbose flag ``-v`` to print out the files being fixed. For example :: - - ./sage -python src/sage/misc/replace_dot_all.py -v src/sage/arith - -will fix all files in ``src/sage/arith`` and print out the unusual examples of ``import`` statements it finds. - -In some rare cases, such as ``import`` statements appearing in doctests, the program will not be able to fix the ``import`` statement. The program will -print out the location of the file and the line number of the exceptional ``import`` statement. The user can then manually fix the ``import`` statement. -The program will also (usually) print out the suggested replacement for the ``import`` statement. The user can then copy and paste this replacement -into the file. In the cases a suggested replacement is not printed out, the user should use the function :func:`~sage.misc.dev_tools.import_statements` -to find the correct ``import`` statement. -""" - -# **************************************************************************** -# Copyright (C) 2022-2023 Alex Chandler -# 2023 Matthias Koeppe -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 2 of the License, or -# (at your option) any later version. -# https://www.gnu.org/licenses/ -# **************************************************************************** - -# Importing packages - -from sage.misc.dev_tools import import_statements -import os -import re -import argparse - -# We import this using __import__ so that "tox -e relint" does not complain about this source file. -__import__("sage.all", globals(), locals(), ["*"]) - - -# Keep in sync with SAGE_ROOT/src/.relint.yml (namespace_pkg_all_import) - -default_package_regex = (r"sage(" - r"|[.](arith|categories|combinat|ext|graphs(|[.]decompositions)|interfaces|libs|matrix|misc|numerical(|[.]backends)|rings|sets)" - r")[.]all") - - -# Global variables - -examples = list('ABCDEFGHIJ') # controls how we print out interesting examples to the console -interesting_examples = dict(zip(examples, [0]*len(examples))) -log_messages = '' -number_examples_to_print = 100 # controls how many examples we print out to the console (100 effectively allows all unusual examples to be printed) -numberFiles, numberFilesMatchingRegex, numberFilesChanged, numberStatementsReplaced = 0, 0, 0, 0 # to print report on number of files changed - - -# Functions - -def find_replacements(location, package_regex=None, verbose=False): - r""" - Locate the lines in the file at ``location`` which contain an ``import`` statement. - - INPUT: - - - ``location`` -- a file path - - ``package_regex`` -- (default: :obj:`default_package_regex`) a regular expression matching - the ``sage.PAC.KAGE.all`` package names from which we do not want to import. - - ``verbose`` -- a parameter which if used will issue print statements when interesting examples are found - - OUTPUT: - - an array [row_index,import_index,replaced_commands,lines_spanned (optional)] with entries - - - ``row_index`` -- the row index (zero indexed) in the file which needs replacing - - ``import_index`` -- the index of row row_index which marks the beginning of the word ``import`` in the line - - ``replaced_commands`` -- the string which will replace the current line - - ``lines_spanned`` -- the number of lines the original statement spans - - This output can be processed by the function :func:`process_line`. - - EXAMPLES:: - - sage: from sage.misc.replace_dot_all import * - sage: location = os.path.join(sage.env.SAGE_SRC, 'sage/plot/arc.py') - sage: find_replacements(location, package_regex='sage[.]plot[.]all', verbose=True) - [[..., ..., 'from sage.plot.graphics import Graphics']] - """ - if package_regex is None: - package_regex = default_package_regex - regex = r"from\s+" + package_regex + r"\s+import" - pattern = re.compile(regex) - replacements = [] - global log_messages, interesting_examples - with open(location, "r") as fp: - skip_line = False - lines = fp.readlines() # read all lines using readline() - row_index = 0 - for row in lines: # iterate over all lines of python file - if pattern.search(row): # (match the regex also do not want to mess with documentation) - prefix = '' - if '*' in row or 'SAGE_ROOT' in row: - if verbose and interesting_examples['J'] < number_examples_to_print: - interesting_examples['J'] += 1 - log_messages += (f'J. Match but no changes made (import statement uses *) at {location}:{row_index + 1}. ' - f'Not applying any changes here.\n') - continue - elif not (row.lstrip()[0:4] == 'from'): - skip_line = True - if '"' not in row and "'" not in row: - print(f'\n' - f'NEED TO CHANGE MANUALLY \n' - f' Issue: line with import statement does not start with "from" \n' - f' Location: at {location} \n' - f' Line number: {row_index + 1}. \n' - f' Giving correct import statements:\n') - leading_space = 0 - while len(row) > 0 and row[leading_space] == ' ' and leading_space < len(row)-1: - leading_space += 1 - prefix_space = leading_space - while row[prefix_space:prefix_space+4] != 'from': - prefix_space += 1 - prefix = row[leading_space:prefix_space] - row = row[prefix_space:] - else: - print(f'\n' - f'NEED TO CHANGE MANUALLY \n' - f' Issue: import statement does not start with "from" and contains quotation marks \n' - f' Location: at {location}:{row_index + 1}. \n' - f' Not able to suggest correct import statements. User must use the function import_statements().') - continue - # find() method returns -1 if the value is not found, or if found it returns index of the first occurrence of the substring - import_index = row.find('import ') - modules = '' - to_exec = row.strip() # the import statement itself which we will clean and call to import modules e.g. "import (aa as a, bb, cc as c)" - to_eval = row[import_index + 7:-1].strip() # tuple of modules in import statement but e.g. "(aa as a, bb, cc as c)" is saved as "(a,bb,c)" - to_eval_raw = row[import_index + 7:-1].strip() # same as to_eval but we don't get rid of " as " parts e.g. "(aa as a, bb, cc as c)" - span = 0 # keeps track of how many lines the import statement spans - - if '(' in row: # for examples where we import a tuple of modules and the statement spans several lines - while ')' not in lines[row_index + span]: # finding the line which closes the import statement - span += 1 - to_exec += lines[row_index + span].strip() - to_eval += lines[row_index + span].strip() - to_eval_raw += lines[row_index + span].strip() - if span and verbose: # useful to see these multiline examples for debugging - if " as " in to_eval_raw and interesting_examples['D'] < number_examples_to_print: - log_messages += f'D. Interesting example (spans multiple lines and has " as ") at {location}:{row_index + 1}\n' - interesting_examples['D'] += 1 - elif interesting_examples['B'] < number_examples_to_print: - log_messages += f'B. Interesting example (spans multiple lines) at {location}:{row_index + 1}\n' - interesting_examples['B'] += 1 - - # if there is an "as" statement inside to_eval, we want to keep only the new name for the module e.g. "(aa as a, bb, cc as c)" becomes "(a,bb,c)" - while " as " in to_eval: - as_ind = to_eval.find(" as ") - j = as_ind - 1 - while to_eval[j] not in [',', ' '] and j >= 0: - j -= 1 - to_eval = to_eval[0:j+1] + to_eval[as_ind+4:] - - try: # trying to execute the import statement so we can eval the modules and feed them to the function import_statements - to_exec = to_exec.replace("'", '').replace('"', '') - if (to_exec[-1] == ','): - to_exec = to_exec[:-1] - exec(to_exec) - except ModuleNotFoundError as err: - print(f'ModuleNotFoundError: {err} found when trying to execute {to_exec}') - except ImportError as err: - print(f'ImportError: {err} found when trying to execute {to_exec}') - - try: # try to evaluate the list of module names to get a list of the modules themselves which we can call import_statements on - modules = eval(to_eval) - except NameError as err: - print(f'NameError: {err} found when trying to evaluate {to_eval} at {location}:{row_index + 1}') - except SyntaxError as err: - print(f'SyntaxError: {err} found when trying to evaluate {to_eval} at {location}:{row_index + 1}') - - # Need module to be a list of modules we are importing. If a single module was given, we make it a 1-element list. - if not isinstance(modules, tuple): - modules = [modules] - - to_eval_list = to_eval.replace('(', '').replace(')', '').split(',') # convert comma separated string to_eval to a list - to_eval_list_raw = to_eval_raw.replace('(', '').replace(')', '').split(',') # convert comma separated string to_eval_raw to a list - to_eval_list_index = 0 - - change_to = '' - # constructs the appropriate replacement for the import statement and stores it (along with location data) in list replacements - for mod in modules: - postfix = '' - as_index = -1 - # saves the callable name of module in variable postfix (e.g. for module "b" called by "bb as b" we set postfix = " as b") - if " as " in to_eval_list_raw[to_eval_list_index]: - if verbose and interesting_examples['C'] < number_examples_to_print: - log_messages += f'C. Interesting example (" as " in tuple import) at {location}:{row_index + 1}\n' - interesting_examples['C'] += 1 - as_index = to_eval_list_raw[to_eval_list_index].index(" as ") - postfix = to_eval_list_raw[to_eval_list_index][as_index:] - new_import_statement = import_statements(mod, answer_as_str=True, verbose=False) # import statement for the current mod in the list module - import_index = new_import_statement.find('import') - new_mod_as_string = new_import_statement[import_index + 7:].strip() # the name for the module given by the function import_statements - if as_index >= 0: - # the name for the module as originally called in the document (when there is an " as " statement) - original_mod_string = to_eval_list_raw[to_eval_list_index].strip()[:as_index] - else: - original_mod_string = to_eval_list[to_eval_list_index].strip() # the name for the module as originally called in the document - if original_mod_string != new_mod_as_string: # if the names differ, we use the original name as it was called in the document - if verbose and interesting_examples['A'] < number_examples_to_print: - log_messages += (f'A. Interesting example (module has multiple names) at {location}:{row_index + 1}. ' - f'Names: {original_mod_string}, {new_mod_as_string}. ' - f'Replacing new {new_mod_as_string} by original {original_mod_string}.\n') - interesting_examples['A'] += 1 - new_import_statement = new_import_statement.replace(' ' + new_mod_as_string, ' ' + new_mod_as_string + ' as ' + original_mod_string) - if " as " in postfix and interesting_examples['G'] < number_examples_to_print: - log_messages += (f'G. Interesting example (module has multiple names) at {location}:{row_index + 1}. ' - f'Names: {original_mod_string}, {new_mod_as_string}. ' - f'Replacing new {new_mod_as_string} by original {original_mod_string}.\n') - interesting_examples['G'] += 1 - if len(postfix.strip()) > 0: # if module was called with " as " statement, we put that back in by adding the string "postfix" - # if " as " in new_import_statement locate the index of " as ", remove the end after this, and add the postfix there - if " as " in new_import_statement: - new_import_statement = new_import_statement[:new_import_statement.index(" as ")] + ' ' + postfix.strip() - else: - new_import_statement += (' ' + postfix.strip()) - change_to += (prefix + new_import_statement + '\n') - to_eval_list_index += 1 - # [:-1] on change_to gets rid of the last '\n' we added which adds an unnecessary new line - replacement = [row_index, import_index, change_to[:-1]].copy() - if span: - # if original statement spanned multiple lines, we store that information to signal that we need to skip lines - # as we read the document in the function make_replacements_in_file - replacement.append(span) - if not skip_line: - replacements.append(replacement) - row_index += 1 - skip_line = False - # keeping track of the numbers of files changed and statements replaced - global numberStatementsReplaced, numberFilesChanged - numberStatementsReplaced += len(replacements) - if replacements: - numberFilesChanged += 1 - return replacements - - -def process_line(location, line, replacements, row_index, verbose=False): - r""" - Modify a single source code ``line`` according to the given ``replacements``. - - INPUTS: - - - ``location`` -- a file path; only used for logging - - ``line`` -- a source code line - - ``replacements`` -- the array output from :func:`find_replacements` - - ``row_index`` -- the line number where ``import`` appears - - ``verbose`` -- if True, issue print statements when interesting examples are found - - OUTPUT: - - an array ``[new_line, replacements]`` with entries - - - ``new_line`` -- the modified import statement (possibly now on several lines) - - ``replacements`` -- just returns the original replacements with its index 0 element removed if ``replacements`` is nonempty - - EXAMPLES: - - Replacing the first line which needs a replacement in the source file with filepath ``src/sage/plot/arc.py``:: - - sage: from sage.misc.replace_dot_all import * - sage: location = os.path.join(sage.env.SAGE_SRC, 'sage/plot/arc.py') - sage: replacements = find_replacements(location, package_regex='sage[.]plot[.]all', verbose=True); replacements - [[471, 24, 'from sage.plot.graphics import Graphics']] - sage: with open(location, "r") as file: - ....: lines = file.readlines() - sage: row_index, col_number, *_ = replacements[0] - sage: line = lines[row_index] - sage: print(line.rstrip()) - from sage.plot.all import Graphics - sage: new_line, replacements = process_line(location, line, replacements, row_index) - sage: print(new_line) - from sage.plot.graphics import Graphics - sage: replacements - [] - """ - line = line.rstrip() # stripping line break - new_line = '' - global log_messages, interesting_examples - if len(replacements) == 0: - return line, replacements - if row_index == replacements[0][0]: # if line marked as containing .all - replacement = replacements.pop(0) - leading_space = 0 - while line and line[leading_space] == ' ' and leading_space < len(line)-1: - leading_space += 1 - new_line = ' '*leading_space + replacement[2] # adds leading space to first line (which may or may not start with 'from') - new_line = new_line.replace('\n', '\n'+' '*leading_space) # adds correct amount of indentation to the replacement at each line - # new_line = replacement[2].replace('from ',' '*leading_space + 'from ') # adds correct amount of indentation to the replacement at each line - if verbose and leading_space > 0: - if len(replacement) == 4 and interesting_examples['F'] < number_examples_to_print: - log_messages += f'F. Interesting example (has leading space and multiline) at {location}:{replacement[0] + 1}\n' - interesting_examples['F'] += 1 - elif interesting_examples['E'] < number_examples_to_print: - log_messages += f'E. Interesting example (has leading space) at {location}:{replacement[0] + 1}\n' - interesting_examples['E'] += 1 - - else: # if line does not contain .all - new_line = line - return new_line, replacements - - -def make_replacements_in_file(location, package_regex=None, verbose=False, output=None): - r""" - Replace ``import`` statements in the file with filepath "location". - - INPUT: - - - ``location`` -- a file path - - ``package_regex`` -- (default: :obj:`default_package_regex`) a regular expression matching - the ``sage.PAC.KAGE.all`` package names from which we do not want to import. - - ``verbose`` -- if True, issue print statements when interesting examples are found - - ``output`` -- a file path; if ``None``, overwrite the file given by ``location`` - - EXAMPLES:: - - sage: from sage.misc.replace_dot_all import * - sage: import tempfile - sage: with tempfile.TemporaryDirectory() as d: - ....: location = os.path.join(d, "input.py") - ....: with open(location, "w") as input: - ....: _ = input.write("from sage.plot.all import point2d\n") - ....: _ = input.write("from sage.plot.line import line\n") - ....: make_replacements_in_file(location, 'sage[.]plot[.]all', True) - ....: with open(location, "r") as output: - ....: for line in output: - ....: print(line.strip()) - from sage.plot.point import point2d - from sage.plot.line import line - """ - replacements = find_replacements(location, package_regex, verbose) - with open(location, "r") as file: - lines = file.readlines() - replaced_content = "" - row_index = 0 # keeps track of the line number - while row_index < len(lines): # looping through the file - line = lines[row_index] - span = 0 # keeps track of number of lines import statement spans - if replacements and row_index == replacements[0][0] and len(replacements[0]) == 4: - span = replacements[0][3] # if import statement spans span lines - # returns the line if no replacements are needed and returns the processed line otherwise - new_line, replacements = process_line(location, line, replacements, row_index, verbose=verbose) - replaced_content += new_line + "\n" # concatenate the new string and add an end-line break - row_index += 1 + span - if output is None: - output = location - with open(output, "w") as write_file: # Open file in write mode - write_file.write(replaced_content) # overwriting the old file contents with the new/replaced content - - -def walkdir_replace_dot_all(dir, file_regex=r'.*[.](py|pyx|pxi)$', package_regex=None, verbose=False): - r""" - Replace ``import`` statements in the files in directory ``dir`` matching the regex pattern ``file_regex``. - - INPUTS: - - - ``dir`` -- a directory path - - ``file_regex`` -- a regular expression matching the file names to process - - ``package_regex`` -- (default: :obj:`default_package_regex`) a regular expression matching - the ``sage.PAC.KAGE.all`` package names from which we do not want to import. - - ``verbose`` -- if True, print statements when interesting examples are found - - EXAMPLES:: - - sage: from sage.misc.replace_dot_all import * - sage: walkdir_replace_dot_all(os.path.join(sage.env.SAGE_SRC, 'sage')) # not tested - """ - global numberFiles, numberFilesMatchingRegex - file_regex = re.compile(file_regex) - for root, dirs, files in os.walk(dir, topdown=False): - for name in files: - numberFiles += 1 - if file_regex.search(name): - numberFilesMatchingRegex += 1 - location = os.path.join(root, name) - if location.find('replace_dot_all') == -1: # to avoid changing anything in this file itself - make_replacements_in_file(location, package_regex, verbose) - - -# ******************************************************** EXECUTES MAIN FUNCTION ********************************************************************** -# this executes the main function in this file which writes over all import statements matching regex in files in specified location matching fileRegex: -if __name__ == "__main__": - # Create argument parser - parser = argparse.ArgumentParser() - # Optional arguments - parser.add_argument( - "location", - metavar='files or directories', - nargs='*', - help=("Names of source directories or source files. " - "If none given, walks through all files in src/sage."), - type=str) - parser.add_argument( - "-v", "--verbose", - help="Increase output verbosity. Shows locations of any unusual cases of import statements and the corresponding changes.", - action="store_true") # Parse arguments - args = parser.parse_args() - verbosity = args.verbose - # Declare regular expressions - file_regex = r'.*[.](py|pyx|pxi)$' - package_regex = None - # Execute the main function based on the specified location and verbosity - if not args.location: - args.location = [os.path.join(sage.env.SAGE_SRC, 'sage')] - try: - for location in args.location: - if not (location.endswith('.py') or location.endswith('.pxi')): - # Assume directory - walkdir_replace_dot_all(location, file_regex, package_regex, verbose=verbosity) - else: - # make replacements in file specified by location argument - make_replacements_in_file(location, package_regex, verbose=verbosity) - finally: - # Print report also when interrupted - if verbosity: - log_messages = sorted(log_messages.rstrip().split('\n')) - for i, message in enumerate(log_messages, start=1): - # add index to each line - print(f'{i}. {message.rstrip()}') - report = 'REPORT:\n' - report += f'Number of files checked: {numberFiles}\n' - report += f'Number of files matching regex: {numberFilesMatchingRegex}\n' - report += f'Number of files changed: {numberFilesChanged}\n' - report += f'Number of import statements replaced: {numberStatementsReplaced}' - print('*'*100 + '\n' + report + '\n' + '*'*100) - -# ****************************************************************************************************************************************************** diff --git a/src/sage/misc/sage_eval.py b/src/sage/misc/sage_eval.py index 4e2a9968f24..ebd9ad6f3d1 100644 --- a/src/sage/misc/sage_eval.py +++ b/src/sage/misc/sage_eval.py @@ -22,10 +22,10 @@ def sage_eval(source, locals=None, cmds='', preparse=True): INPUT: - - ``source`` - a string or object with a ``_sage_`` + - ``source`` - a string or object with a _sage_ method - - ``locals`` - evaluate in namespace of :mod:`sage.all` plus + - ``locals`` - evaluate in namespace of sage.all plus the locals dictionary - ``cmds`` - string; sequence of commands to be run @@ -59,10 +59,10 @@ def sage_eval(source, locals=None, cmds='', preparse=True): x^2 + 1 This example illustrates that evaluation occurs in the context of - ``from sage.all import *``. Even though ``bernoulli`` has + ``from sage.all import *``. Even though bernoulli has been redefined in the local scope, when calling - :func:`sage_eval` the default value meaning of :func:`bernoulli` - is used. Likewise for ``QQ`` below. + ``sage_eval`` the default value meaning of bernoulli + is used. Likewise for QQ below. :: @@ -125,7 +125,7 @@ def sage_eval(source, locals=None, cmds='', preparse=True): sage: vars['rt2'] 1.41421356237310 - This example illustrates how :mod:`sage_eval` can be + This example illustrates how ``sage_eval`` can be useful when evaluating the output of other computer algebra systems. @@ -144,8 +144,8 @@ def sage_eval(source, locals=None, cmds='', preparse=True): RuntimeError: Use ** for exponentiation, not '^', which means xor in Python, and has the wrong precedence. - Here you can see that :func:`eval` simply will not work but - :func:`sage_eval` will. + Here you can see eval simply will not work but + ``sage_eval`` will. TESTS: @@ -201,14 +201,14 @@ def sage_eval(source, locals=None, cmds='', preparse=True): def sageobj(x, vars=None): """ - Return a native Sage object associated to ``x``, if possible and + Return a native Sage object associated to x, if possible and implemented. - If the object has a ``_sage_`` method it is called and the value is - returned. Otherwise, :func:`str` is called on the object, and all preparsing + If the object has an _sage_ method it is called and the value is + returned. Otherwise str is called on the object, and all preparsing is applied and the resulting expression is evaluated in the context of ``from sage.all import *``. To evaluate the - expression with certain variables set, use the ``vars`` argument, which + expression with certain variables set, use the vars argument, which should be a dictionary. EXAMPLES:: diff --git a/src/sage/modular/modform/element.py b/src/sage/modular/modform/element.py index a2ac0b1d1fa..9936fbdd88e 100644 --- a/src/sage/modular/modform/element.py +++ b/src/sage/modular/modform/element.py @@ -3395,18 +3395,6 @@ def _repr_(self): """ return str(self.q_expansion()) - def _latex_(self): - r""" - Return a latex representation of ``self``. - - TESTS:: - - sage: M = ModularFormsRing(1) - sage: latex(M.0) - 1 + 240 q + 2160 q^{2} + 6720 q^{3} + 17520 q^{4} + 30240 q^{5} + O(q^{6}) - """ - return self.q_expansion()._latex_() - def __getitem__(self, weight): r""" Return the homogeneous component of the given graded modular form. diff --git a/src/sage/modular/quasimodform/element.py b/src/sage/modular/quasimodform/element.py index 6821f3e97bf..37f5b51ed7a 100644 --- a/src/sage/modular/quasimodform/element.py +++ b/src/sage/modular/quasimodform/element.py @@ -157,18 +157,6 @@ def _repr_(self): """ return str(self.q_expansion()) - def _latex_(self): - r""" - Return a latex representation of ``self``. - - TESTS:: - - sage: QM = QuasiModularForms(1) - sage: latex(QM.0) - 1 - 24 q - 72 q^{2} - 96 q^{3} - 168 q^{4} - 144 q^{5} + O(q^{6}) - """ - return self.q_expansion()._latex_() - def _richcmp_(self, other, op): r""" Compare self with other. diff --git a/src/sage/modules/fg_pid/fgp_element.py b/src/sage/modules/fg_pid/fgp_element.py index faf255b2ded..dadf8745f88 100644 --- a/src/sage/modules/fg_pid/fgp_element.py +++ b/src/sage/modules/fg_pid/fgp_element.py @@ -448,7 +448,7 @@ def additive_order(self): from sage.rings.infinity import infinity from sage.rings.finite_rings.integer_mod import Mod from sage.rings.integer import Integer - from sage.arith.functions import lcm + from sage.arith.all import lcm n = Integer(1) for i, a in enumerate(I): if a == 0: diff --git a/src/sage/modules/fg_pid/fgp_morphism.py b/src/sage/modules/fg_pid/fgp_morphism.py index 71b43dcdc1a..5f61c221d93 100644 --- a/src/sage/modules/fg_pid/fgp_morphism.py +++ b/src/sage/modules/fg_pid/fgp_morphism.py @@ -510,7 +510,7 @@ def __init__(self, X, Y, category=None): from sage.categories.modules_with_basis import ModulesWithBasis category = ModulesWithBasis(X.base_ring()) else: - from sage.categories.modules import Modules + from sage.categories.all import Modules category = Modules(X.base_ring()) Homset.__init__(self, X, Y, category) diff --git a/src/sage/modules/filtered_vector_space.py b/src/sage/modules/filtered_vector_space.py index a4a32815197..aac6625d377 100644 --- a/src/sage/modules/filtered_vector_space.py +++ b/src/sage/modules/filtered_vector_space.py @@ -99,20 +99,16 @@ in Vector space of dimension 3 over Algebraic Field """ -# *************************************************************************** +#***************************************************************************** # Copyright (C) 2013 Volker Braun # # Distributed under the terms of the GNU General Public License (GPL) # as published by the Free Software Foundation; either version 2 of # the License, or (at your option) any later version. -# https://www.gnu.org/licenses/ -# *************************************************************************** - -from sage.rings.rational_field import QQ -from sage.rings.integer_ring import ZZ -from sage.rings.real_double import RDF -from sage.rings.real_mpfr import RR -from sage.rings.integer import Integer +# http://www.gnu.org/licenses/ +#***************************************************************************** + +from sage.rings.all import QQ, ZZ, RDF, RR, Integer from sage.rings.infinity import InfinityRing, infinity, minus_infinity from sage.categories.fields import Fields from sage.modules.free_module import FreeModule_ambient_field, VectorSpace @@ -279,7 +275,7 @@ def construct_from_dim_degree(dim, max_degree, base_ring, check): dim = ZZ(dim) from sage.matrix.constructor import identity_matrix generators = identity_matrix(base_ring, dim).columns() - filtration = {} + filtration = dict() if max_degree is None: max_degree = infinity filtration[normalize_degree(max_degree)] = range(dim) @@ -318,7 +314,7 @@ def normalize_gen(v): generators = tuple(sorted(generators)) # normalize filtration data - normalized = {} + normalized = dict() for deg, gens_deg in filtration.items(): indices = [generators.index(normalize_gen(v)) for v in gens_deg] normalized[deg] = tuple(indices) @@ -377,13 +373,13 @@ def construct_from_generators_indices(generators, filtration, base_ring, check): v.set_immutable() # normalize filtration data - normalized = {} + normalized = dict() for deg, gens in filtration.items(): deg = normalize_degree(deg) - gens = tuple(sorted(ZZ(i) for i in gens)) - if gens and (gens[0] < 0 or gens[-1] >= len(generators)): + gens = [ZZ(i) for i in gens] + if any(i < 0 or i >= len(generators) for i in gens): raise ValueError('generator index out of bounds') - normalized[deg] = gens + normalized[deg] = tuple(sorted(gens)) try: del normalized[minus_infinity] except KeyError: @@ -393,6 +389,8 @@ def construct_from_generators_indices(generators, filtration, base_ring, check): return FilteredVectorSpace_class(base_ring, dim, generators, filtration, check=check) + + class FilteredVectorSpace_class(FreeModule_ambient_field): def __init__(self, base_ring, dim, generators, filtration, check=True): @@ -736,7 +734,7 @@ def graded(self, d): Basis matrix: [1 1] """ - return self.get_degree(d).quotient(self.get_degree(d + 1)) + return self.get_degree(d).quotient(self.get_degree(d+1)) def presentation(self): """ @@ -762,7 +760,7 @@ def presentation(self): generators.update(V.echelonized_basis()) generators = tuple(sorted(generators)) - filtration = {} + filtration = dict() for d, V in filt: indices = [ZZ(generators.index(v)) for v in V.echelonized_basis()] filtration[d] = tuple(indices) @@ -772,8 +770,6 @@ def _repr_field_name(self): """ Return an abbreviated field name as string - .. NOTE: This should rather be a method of fields and rings. - RAISES: ``NotImplementedError``: The field does not have an @@ -1005,15 +1001,15 @@ def direct_sum(self, other): self_gens, self_filt = self.presentation() other_gens, other_filt = other.presentation() generators = \ - [list(v) + [base_ring.zero()] * other.dimension() for v in self_gens] + \ - [[base_ring.zero()] * self.dimension() + list(v) for v in other_gens] + [ list(v) + [base_ring.zero()]*other.dimension() for v in self_gens ] + \ + [ [base_ring.zero()]*self.dimension() + list(v) for v in other_gens ] # construct the filtration dictionary def join_indices(self_indices, other_indices): self_indices = tuple(self_indices) other_indices = tuple(i + len(self_gens) for i in other_indices) return self_indices + other_indices - filtration = {} + filtration = dict() self_indices = set() other_indices = set() degrees = list(self_filt) + list(other_filt) @@ -1075,7 +1071,7 @@ def tensor_product(self, other): W_coll = VectorCollection(W_generators, base_ring, W.dimension()) T = TensorOperation([V_coll, W_coll], 'product') - filtration = {} + filtration = dict() for V_deg in V.support(): for W_deg in W.support(): deg = V_deg + W_deg @@ -1116,7 +1112,7 @@ def _power_operation(self, n, operation): T = TensorOperation([V] * n, operation) iters = [self.support()] * n - filtration = {} + filtration = dict() from sage.categories.cartesian_product import cartesian_product for degrees in cartesian_product(iters): deg = sum(degrees) @@ -1128,6 +1124,7 @@ def _power_operation(self, n, operation): filtration[deg] = filt_deg return FilteredVectorSpace(T.vectors(), filtration, base_ring=self.base_ring()) + def exterior_power(self, n): """ Return the `n`-th graded exterior power. @@ -1207,7 +1204,7 @@ def dual(self): sage: F.dual().support() (-2, 0) """ - filtration = {} + filtration = dict() prev_deg = minus_infinity for deg, V in self._filt[1:]: filtration[-prev_deg] = V.complement().echelonized_basis() @@ -1229,7 +1226,7 @@ def shift(self, deg): (-5, -3) """ generators, filtration = self.presentation() - shifted = {} + shifted = dict() for d, indices in filtration.items(): shifted[d + deg] = indices return FilteredVectorSpace(generators, shifted, base_ring=self.base_ring()) @@ -1272,7 +1269,7 @@ def random_deformation(self, epsilon=None): R = self.base_ring() if epsilon is None: epsilon = R.one() - filtration = {} + filtration = dict() for deg, filt in self._filt[1:]: generators = [v + epsilon * random_vector(R, self.rank()) for v in filt.echelonized_basis()] diff --git a/src/sage/modules/free_module.py b/src/sage/modules/free_module.py index 743fc2fbbcc..cd0cfdde32d 100644 --- a/src/sage/modules/free_module.py +++ b/src/sage/modules/free_module.py @@ -4611,7 +4611,7 @@ def span_of_basis(self, basis, base_ring=None, check=True, already_echelonized=F M = self.change_ring(base_ring) except TypeError: raise ValueError("Argument base_ring (= %s) is not compatible with the base field (= %s)." % ( - base_ring, self.base_field())) + base_ring, self.base_field() )) try: return M.span_of_basis(basis) except TypeError: @@ -5653,7 +5653,7 @@ def basis(self): """ try: return self.__basis - except AttributeError: + except AttributeError: ZERO = self(0) one = self.coordinate_ring().one() w = [] @@ -6600,7 +6600,7 @@ def _echelon_matrix_richcmp(self, other, op): lx = self.ambient_vector_space() rx = other.ambient_vector_space() if lx != rx: - return lx._echelon_matrix_richcmp(rx, op) + return lx._echelon_matrix_richcmp( rx, op) lx = self.dimension() rx = other.dimension() @@ -6718,7 +6718,7 @@ def _denominator(self, B): if not B: return 1 d = B[0].denominator() - from sage.arith.functions import lcm + from sage.arith.all import lcm for x in B[1:]: d = lcm(d,x.denominator()) return d diff --git a/src/sage/modules/free_module_element.pyx b/src/sage/modules/free_module_element.pyx index 6c1c5083682..2cc6ed44104 100644 --- a/src/sage/modules/free_module_element.pyx +++ b/src/sage/modules/free_module_element.pyx @@ -1602,7 +1602,7 @@ cdef class FreeModuleElement(Vector): # abstract base class if isinstance(ord, AnInfinity): return ord v.append(ord) - from sage.arith.functions import lcm + from sage.arith.all import lcm return lcm(v) def items(self): diff --git a/src/sage/modules/free_quadratic_module_integer_symmetric.py b/src/sage/modules/free_quadratic_module_integer_symmetric.py index 0902a272f39..aeb19ab669d 100644 --- a/src/sage/modules/free_quadratic_module_integer_symmetric.py +++ b/src/sage/modules/free_quadratic_module_integer_symmetric.py @@ -349,7 +349,7 @@ def IntegralLatticeDirectSum(Lattices, return_embeddings=False): basis = [matrix.block(1, 3, [matrix.zero(dims[i], sum_degree[i]), Lattices[i].basis_matrix(), matrix.zero(dims[i], sum_degree[-1] - sum_degree[i+1]) - ]) for i in range(N)] + ]) for i in range(N)] basis_matrix = matrix.block(N, 1, basis) ipm = ambient.inner_product_matrix() direct_sum = FreeQuadraticModule_integer_symmetric(ambient=ambient, @@ -363,7 +363,6 @@ def IntegralLatticeDirectSum(Lattices, return_embeddings=False): for i in range(N)] return [direct_sum, phi] - def IntegralLatticeGluing(Lattices, glue, return_embeddings=False): r""" Return an overlattice of the direct sum as defined by ``glue``. @@ -1093,7 +1092,7 @@ def maximal_overlattice(self, p=None): for t in D: if t != 0 and t.q() == 0: break - if t.q() != 0: + if t.q() != 0 : # no isotropic vector left break L = L.overlattice([t.lift()]) diff --git a/src/sage/modules/matrix_morphism.py b/src/sage/modules/matrix_morphism.py index c725989f2fc..a6412620892 100644 --- a/src/sage/modules/matrix_morphism.py +++ b/src/sage/modules/matrix_morphism.py @@ -1236,7 +1236,7 @@ def is_identity(self): # testing for the identity matrix will only work for # endomorphisms which have the same basis for domain and codomain # so we test equality on a basis, which is sufficient - return all(self(u) == u for u in self.domain().basis()) + return all( self(u) == u for u in self.domain().basis() ) def is_zero(self): r""" @@ -1369,7 +1369,7 @@ def is_equal_function(self, other): if self.codomain() != other.codomain(): return False # check agreement on any basis of the domain - return all(self(u) == other(u) for u in self.domain().basis()) + return all( self(u) == other(u) for u in self.domain().basis() ) def restrict_domain(self, sub): """ diff --git a/src/sage/modules/module.pyx b/src/sage/modules/module.pyx index 180222b8b18..9d76034a926 100644 --- a/src/sage/modules/module.pyx +++ b/src/sage/modules/module.pyx @@ -254,7 +254,7 @@ cdef class Module(Parent): sage: M.endomorphism_ring() Set of Morphisms from to in Category of modules over Integer Ring """ - from sage.categories.homset import End + from sage.categories.all import End return End(self) def is_Module(x): diff --git a/src/sage/modules/multi_filtered_vector_space.py b/src/sage/modules/multi_filtered_vector_space.py index e3f551b9e4b..ddc83eb87dd 100644 --- a/src/sage/modules/multi_filtered_vector_space.py +++ b/src/sage/modules/multi_filtered_vector_space.py @@ -39,9 +39,7 @@ # https://www.gnu.org/licenses/ # **************************************************************************** -from sage.rings.rational_field import QQ -from sage.rings.integer_ring import ZZ -from sage.rings.integer import Integer +from sage.rings.all import QQ, ZZ, Integer from sage.rings.infinity import infinity, minus_infinity from sage.categories.fields import Fields from sage.modules.free_module import FreeModule_ambient_field, VectorSpace diff --git a/src/sage/modules/torsion_quadratic_module.py b/src/sage/modules/torsion_quadratic_module.py index 45a6699a0cc..3414c487a80 100644 --- a/src/sage/modules/torsion_quadratic_module.py +++ b/src/sage/modules/torsion_quadratic_module.py @@ -20,10 +20,7 @@ from sage.modules.fg_pid.fgp_element import FGP_Element from sage.modules.free_quadratic_module import FreeQuadraticModule from sage.arith.misc import gcd -from sage.rings.integer_ring import ZZ -from sage.rings.padics.factory import Zp -from sage.rings.rational_field import QQ -from sage.rings.finite_rings.integer_mod_ring import IntegerModRing +from sage.rings.all import ZZ, Zp, QQ, IntegerModRing from sage.groups.additive_abelian.qmodnz import QmodnZ from sage.matrix.constructor import matrix from sage.matrix.special import diagonal_matrix @@ -147,7 +144,7 @@ def _mul_(self, other): 1/4 """ value_module = self.parent().value_module() - return value_module(self.lift().inner_product(other.lift())) + return value_module( self.lift().inner_product(other.lift()) ) inner_product = _mul_ b = _mul_ @@ -299,6 +296,7 @@ def __init__(self, V, W, gens, modulus, modulus_qf): self._modulus = modulus self._modulus_qf = modulus_qf + def _repr_(self): r""" Return a string representation of ``self``. @@ -315,10 +313,10 @@ def _repr_(self): [0 0 0] [0 0 0] """ - return ("Finite quadratic module over %s with invariants %s\n" - % (self.base_ring(), self.invariants()) + - "Gram matrix of the quadratic form with values in %r:\n%r" - % (self.value_module_qf(), self.gram_matrix_quadratic())) + return ( "Finite quadratic module over %s with invariants %s\n" + % (self.base_ring(), self.invariants()) + + "Gram matrix of the quadratic form with values in %r:\n%r" + % (self.value_module_qf(), self.gram_matrix_quadratic())) def _module_constructor(self, V, W, check=False): r""" diff --git a/src/sage/modules/with_basis/cell_module.py b/src/sage/modules/with_basis/cell_module.py index c51d43c32b6..a17882b4e9e 100644 --- a/src/sage/modules/with_basis/cell_module.py +++ b/src/sage/modules/with_basis/cell_module.py @@ -12,7 +12,7 @@ #***************************************************************************** from sage.misc.cachefunc import cached_method -from sage.categories.modules_with_basis import ModulesWithBasis +from sage.categories.all import ModulesWithBasis from sage.structure.element import Element from sage.combinat.free_module import CombinatorialFreeModule from sage.data_structures.blas_dict import linear_combination @@ -357,7 +357,7 @@ def _acted_upon_(self, scalar, self_on_left=False): # Temporary needed by coercion (see Polynomial/FractionField tests). if not P._algebra.has_coerce_map_from(scalar.parent()): return None - scalar = P._algebra(scalar) + scalar = P._algebra( scalar ) if self_on_left: raise NotImplementedError diff --git a/src/sage/modules/with_basis/indexed_element.pyx b/src/sage/modules/with_basis/indexed_element.pyx index e16268a4aa8..d5ccebde9ef 100644 --- a/src/sage/modules/with_basis/indexed_element.pyx +++ b/src/sage/modules/with_basis/indexed_element.pyx @@ -28,9 +28,7 @@ from sage.misc.lazy_attribute import lazy_attribute from sage.misc.superseded import deprecation from sage.typeset.ascii_art import AsciiArt, empty_ascii_art, ascii_art from sage.typeset.unicode_art import UnicodeArt, empty_unicode_art, unicode_art -from sage.categories.category import Category -from sage.categories.sets_cat import Sets -from sage.categories.modules_with_basis import ModulesWithBasis +from sage.categories.all import Category, Sets, ModulesWithBasis from sage.data_structures.blas_dict cimport add, negate, scal, axpy diff --git a/src/sage/modules/with_basis/morphism.py b/src/sage/modules/with_basis/morphism.py index 6a43cab1461..3cd841629a9 100644 --- a/src/sage/modules/with_basis/morphism.py +++ b/src/sage/modules/with_basis/morphism.py @@ -403,11 +403,11 @@ def __call__(self, *args): mc = x.monomial_coefficients(copy=False) if self._is_module_with_basis_over_same_base_ring: return self.codomain().linear_combination( - (self._on_basis(*(before + (index,) + after)), coeff) - for (index, coeff) in mc.items()) + (self._on_basis(*(before+(index,)+after)), coeff ) + for (index, coeff) in mc.items()) else: - return sum((coeff * self._on_basis(*(before + (index,) + after)) - for (index, coeff) in mc.items()), self._zero) + return sum((coeff * self._on_basis(*(before+(index,)+after)) + for (index, coeff) in mc.items()), self._zero) # As per the specs of Map, we should in fact implement _call_. # However we currently need to abuse Map.__call__ (which strict @@ -415,7 +415,6 @@ def __call__(self, *args): # To be cleaned up _call_ = __call__ - class TriangularModuleMorphism(ModuleMorphism): r""" An abstract class for triangular module morphisms @@ -684,9 +683,10 @@ def __init__(self, triangular="upper", unitriangular=False, self._inverse = inverse if inverse_on_support == "compute": - inverse_on_support = {self._dominant_item(on_basis(i))[0]: i - for i in self.domain().basis().keys() - }.get + inverse_on_support = { + self._dominant_item(on_basis(i))[0] : i + for i in self.domain().basis().keys() + }.get self._inverse_on_support = inverse_on_support @@ -883,7 +883,7 @@ def _invert_on_basis(self, i): sage: phi._invert_on_basis(2) B[2] - B[3] """ - return self.preimage(self.codomain().monomial(i)) + return self.preimage( self.codomain().monomial(i) ) def preimage(self, f): r""" @@ -1351,13 +1351,13 @@ def __init__(self, domain, matrix, codomain=None, category=None, side="left"): matrix = matrix.transpose() if matrix.nrows() != len(indices): raise ValueError("The dimension of the matrix (%s) does not match with the dimension of the domain (%s)" - % (matrix.nrows(), len(indices))) + %(matrix.nrows(), len(indices))) if matrix.ncols() != codomain.dimension(): raise ValueError("The dimension of the matrix (%s) does not match with the dimension of the codomain (%s)" - % (matrix.ncols(), codomain.dimension())) + %(matrix.ncols(), codomain.dimension())) self._matrix = matrix - d = {xt: codomain.from_vector(matrix.row(rank_domain(xt))) - for xt in domain.basis().keys()} + d = { xt: codomain.from_vector(matrix.row(rank_domain(xt))) + for xt in domain.basis().keys() } ModuleMorphismByLinearity.__init__(self, on_basis=d.__getitem__, domain=domain, codomain=codomain, diff --git a/src/sage/modules/with_basis/subquotient.py b/src/sage/modules/with_basis/subquotient.py index 0918c5a8b19..29cc4e963a8 100644 --- a/src/sage/modules/with_basis/subquotient.py +++ b/src/sage/modules/with_basis/subquotient.py @@ -12,7 +12,7 @@ from sage.sets.family import Family from sage.combinat.free_module import CombinatorialFreeModule from sage.misc.lazy_attribute import lazy_attribute -from sage.categories.modules_with_basis import ModulesWithBasis +from sage.categories.all import ModulesWithBasis class QuotientModuleWithBasis(CombinatorialFreeModule): diff --git a/src/sage/monoids/string_monoid.py b/src/sage/monoids/string_monoid.py index 5f4e3819b5e..49c2d3c26e9 100644 --- a/src/sage/monoids/string_monoid.py +++ b/src/sage/monoids/string_monoid.py @@ -521,7 +521,7 @@ def __init__(self): sage: S([ i for i in range(26) ]) ABCDEFGHIJKLMNOPQRSTUVWXYZ """ - from sage.rings.real_mpfr import RealField + from sage.rings.all import RealField RR = RealField() # The characteristic frequency probability distribution of # Robert Edward Lewand. diff --git a/src/sage/monoids/string_monoid_element.py b/src/sage/monoids/string_monoid_element.py index 185aa901a07..c3032e463f9 100644 --- a/src/sage/monoids/string_monoid_element.py +++ b/src/sage/monoids/string_monoid_element.py @@ -22,7 +22,7 @@ # import operator from sage.rings.integer import Integer -from sage.rings.real_mpfr import RealField +from sage.rings.all import RealField from .free_monoid_element import FreeMonoidElement from sage.structure.richcmp import richcmp diff --git a/src/sage/monoids/string_ops.py b/src/sage/monoids/string_ops.py index 8f822f98cc8..9a23ba82bfd 100644 --- a/src/sage/monoids/string_ops.py +++ b/src/sage/monoids/string_ops.py @@ -8,7 +8,7 @@ # http://www.gnu.org/licenses/ #***************************************************************************** -from sage.rings.real_mpfr import RealField +from sage.rings.all import RealField from .string_monoid_element import StringMonoidElement def strip_encoding(S): diff --git a/src/sage/repl/ipython_kernel/kernel.py b/src/sage/repl/ipython_kernel/kernel.py index a4642014e90..bbd7399245f 100644 --- a/src/sage/repl/ipython_kernel/kernel.py +++ b/src/sage/repl/ipython_kernel/kernel.py @@ -96,37 +96,44 @@ def help_links(self): 'url': 'kernelspecs/sagemath/doc/html/en/index.html'}, ...] """ - from sage.repl.ipython_kernel.install import SageKernelSpec - identifier = SageKernelSpec.identifier() - kernel_url = lambda x: 'kernelspecs/{0}/{1}'.format(identifier, x) + from sage.env import SAGE_DOC_SERVER_URL as url + + if url: + def doc_url(path): + return '{}/{}'.format(url, path) + else: + from sage.env import SAGE_DOC_LOCAL_PORT as port + def doc_url(path): + return 'http://localhost:{}/{}'.format(port, path) + return [ { 'text': 'Sage Documentation', - 'url': kernel_url('doc/html/en/index.html'), + 'url': doc_url("html/en/index.html"), }, { 'text': 'Tutorial', - 'url': kernel_url('doc/html/en/tutorial/index.html'), + 'url': doc_url('html/en/tutorial/index.html'), }, { 'text': 'Thematic Tutorials', - 'url': kernel_url('doc/html/en/thematic_tutorials/index.html'), + 'url': doc_url('html/en/thematic_tutorials/index.html'), }, { 'text': 'FAQs', - 'url': kernel_url('doc/html/en/faq/index.html'), + 'url': doc_url('html/en/faq/index.html'), }, { 'text': 'PREP Tutorials', - 'url': kernel_url('doc/html/en/prep/index.html'), + 'url': doc_url('html/en/prep/index.html'), }, { 'text': 'Reference', - 'url': kernel_url('doc/html/en/reference/index.html'), + 'url': doc_url('html/en/reference/index.html'), }, { 'text': "Developer's Guide", - 'url': kernel_url('doc/html/en/developer/index.html'), + 'url': doc_url('html/en/developer/index.html'), }, { 'text': "Python", diff --git a/src/sage/rings/algebraic_closure_finite_field.py b/src/sage/rings/algebraic_closure_finite_field.py index d45c3ec2cb0..a0d5bac9d76 100644 --- a/src/sage/rings/algebraic_closure_finite_field.py +++ b/src/sage/rings/algebraic_closure_finite_field.py @@ -956,7 +956,7 @@ def _roots_univariate_polynomial(self, p, ring=None, multiplicities=None, algori ....: assert p(r).is_zero(), "r={} is not a root of p={}".format(r,p) """ - from sage.arith.functions import lcm + from sage.arith.all import lcm from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing # first build a polynomial over some finite field diff --git a/src/sage/rings/asymptotic/asymptotic_expansion_generators.py b/src/sage/rings/asymptotic/asymptotic_expansion_generators.py index 2a3d10df757..4f4c506bc40 100644 --- a/src/sage/rings/asymptotic/asymptotic_expansion_generators.py +++ b/src/sage/rings/asymptotic/asymptotic_expansion_generators.py @@ -363,7 +363,7 @@ def _log_StirlingNegativePowers_(var, precision): return A.zero() n = A.gen() - from sage.arith.misc import bernoulli + from sage.arith.all import bernoulli from sage.arith.srange import srange result = sum((bernoulli(k) / k / (k-1) / n**(k-1) @@ -462,7 +462,7 @@ def HarmonicNumber(var, precision=None, skip_constant_summand=False): result += 1 / (2 * n) from sage.arith.srange import srange - from sage.arith.misc import bernoulli + from sage.arith.all import bernoulli for k in srange(2, 2*precision - 4, 2): result += -bernoulli(k) / k / n**k @@ -912,7 +912,7 @@ def SingularityAnalysis(var, zeta=1, alpha=0, beta=0, delta=0, from .asymptotic_ring import AsymptoticRing from .growth_group import ExponentialGrowthGroup, \ MonomialGrowthGroup, GenericNonGrowthGroup - from sage.arith.misc import falling_factorial + from sage.arith.all import falling_factorial from sage.categories.cartesian_product import cartesian_product from sage.functions.other import binomial from sage.functions.gamma import gamma diff --git a/src/sage/rings/asymptotic/asymptotics_multivariate_generating_functions.py b/src/sage/rings/asymptotic/asymptotics_multivariate_generating_functions.py index 0622d78c9c8..ec4c5ce878f 100644 --- a/src/sage/rings/asymptotic/asymptotics_multivariate_generating_functions.py +++ b/src/sage/rings/asymptotic/asymptotics_multivariate_generating_functions.py @@ -1345,7 +1345,7 @@ def cohomology_decomposition(self): (1/3, [(x*y - 1, 1), (x^2 + y^2 - 1, 1)]) """ from sage.calculus.functions import jacobian - from sage.arith.misc import XGCD as xgcd + from sage.arith.all import xgcd from sage.sets.set import Set R = self.denominator_ring diff --git a/src/sage/rings/cfinite_sequence.py b/src/sage/rings/cfinite_sequence.py index 8681fc3f263..02520ec2efb 100644 --- a/src/sage/rings/cfinite_sequence.py +++ b/src/sage/rings/cfinite_sequence.py @@ -851,7 +851,7 @@ def closed_form(self, n='n'): sage: CFiniteSequence((x/(1-x-x^2))^2).closed_form() 1/5*(n - sqrt(1/5))*(1/2*sqrt(5) + 1/2)^n + 1/5*(n + sqrt(1/5))*(-1/2*sqrt(5) + 1/2)^n """ - from sage.arith.misc import binomial + from sage.arith.all import binomial from sage.rings.qqbar import QQbar from sage.symbolic.ring import SR diff --git a/src/sage/rings/complex_double.pyx b/src/sage/rings/complex_double.pyx index ba0ec2b37d3..152455de809 100644 --- a/src/sage/rings/complex_double.pyx +++ b/src/sage/rings/complex_double.pyx @@ -2482,7 +2482,7 @@ cdef class ComplexDoubleElement(FieldElement): sage: CDF(1,5).algdep(2) x^2 - 2*x + 26 """ - from sage.arith.misc import algdep + from sage.arith.all import algdep return algdep(self, n) cdef class FloatToCDF(Morphism): diff --git a/src/sage/rings/complex_mpc.pyx b/src/sage/rings/complex_mpc.pyx index 456883bb17a..97f8c1db5a0 100644 --- a/src/sage/rings/complex_mpc.pyx +++ b/src/sage/rings/complex_mpc.pyx @@ -1371,7 +1371,7 @@ cdef class MPComplexNumber(sage.structure.element.FieldElement): sage: p(z) 1.11022302462516e-16 """ - from sage.arith.misc import algdep + from sage.arith.all import algdep return algdep(self, n, **kwds) ################################ diff --git a/src/sage/rings/complex_mpfr.pyx b/src/sage/rings/complex_mpfr.pyx index bf88e122fee..5a3c6b764cc 100644 --- a/src/sage/rings/complex_mpfr.pyx +++ b/src/sage/rings/complex_mpfr.pyx @@ -3279,7 +3279,7 @@ cdef class ComplexNumber(sage.structure.element.FieldElement): sage: p(z) 1.11022302462516e-16 """ - from sage.arith.misc import algdep + from sage.arith.all import algdep return algdep(self, n, **kwds) # Alias diff --git a/src/sage/rings/factorint.pyx b/src/sage/rings/factorint.pyx index 3a7e4a3648b..e46fe9b052f 100644 --- a/src/sage/rings/factorint.pyx +++ b/src/sage/rings/factorint.pyx @@ -75,7 +75,7 @@ cpdef aurifeuillian(n, m, F=None, bint check=True): There is no need to set `F`. It's only for increasing speed of :meth:`factor_aurifeuillian()`. """ - from sage.arith.misc import euler_phi + from sage.arith.all import euler_phi from sage.rings.real_mpfi import RealIntervalField if check: if not n.is_squarefree(): diff --git a/src/sage/rings/fast_arith.pyx b/src/sage/rings/fast_arith.pyx index df9b592cf97..8736e8dc416 100644 --- a/src/sage/rings/fast_arith.pyx +++ b/src/sage/rings/fast_arith.pyx @@ -207,7 +207,7 @@ cpdef prime_range(start, stop=None, algorithm=None, bint py_ints=False): res = pari_prime_range(start, stop, py_ints) elif (algorithm == "pari_isprime") or (algorithm == "pari_primes"): - from sage.arith.misc import primes + from sage.arith.all import primes res = list(primes(start, stop)) else: raise ValueError('algorithm must be "pari_primes" or "pari_isprime"') diff --git a/src/sage/rings/finite_rings/finite_field_base.pyx b/src/sage/rings/finite_rings/finite_field_base.pyx index 285412aa5bd..4c4f3cdb2e6 100644 --- a/src/sage/rings/finite_rings/finite_field_base.pyx +++ b/src/sage/rings/finite_rings/finite_field_base.pyx @@ -762,7 +762,7 @@ cdef class FiniteField(Field): a + 12 """ if self.degree() == 1: - from sage.arith.misc import primitive_root + from sage.arith.all import primitive_root return self(primitive_root(self.order())) F, = self.factored_unit_order() return self._element_of_factored_order(F) diff --git a/src/sage/rings/finite_rings/integer_mod.pyx b/src/sage/rings/finite_rings/integer_mod.pyx index 97ae92d867b..7c67cef951f 100644 --- a/src/sage/rings/finite_rings/integer_mod.pyx +++ b/src/sage/rings/finite_rings/integer_mod.pyx @@ -108,8 +108,7 @@ from sage.misc.persist import register_unpickle_override from sage.structure.parent cimport Parent -from sage.arith.misc import CRT as crt -from sage.arith.functions import lcm +from sage.arith.all import crt, lcm from sage.groups.generic import discrete_log @@ -1299,7 +1298,7 @@ cdef class IntegerMod_abstract(FiniteRingElement): vmod.append(w) moduli.append(k) # Now combine in all possible ways using the CRT - from sage.arith.misc import CRT_basis + from sage.arith.all import CRT_basis basis = CRT_basis(moduli) from sage.misc.mrange import cartesian_product_iterator v = [] @@ -4465,7 +4464,7 @@ cdef class IntegerMod_to_Integer(Map): Set of Morphisms from Finite Field of size 2 to Integer Ring in Category of sets """ import sage.categories.homset - from sage.categories.sets_cat import Sets + from sage.categories.all import Sets Morphism.__init__(self, sage.categories.homset.Hom(R, integer_ring.ZZ, Sets())) cpdef Element _call_(self, x): diff --git a/src/sage/rings/finite_rings/integer_mod_ring.py b/src/sage/rings/finite_rings/integer_mod_ring.py index 01b498eda92..54b7840e488 100644 --- a/src/sage/rings/finite_rings/integer_mod_ring.py +++ b/src/sage/rings/finite_rings/integer_mod_ring.py @@ -62,9 +62,7 @@ import sage.misc.prandom as random -from sage.arith.misc import factor -from sage.arith.misc import primitive_root -from sage.arith.misc import CRT_basis +from sage.arith.all import factor, primitive_root, CRT_basis import sage.rings.ring as ring import sage.rings.abc from . import integer_mod diff --git a/src/sage/rings/finite_rings/residue_field.pyx b/src/sage/rings/finite_rings/residue_field.pyx index 83436bd6582..cae2b97af70 100644 --- a/src/sage/rings/finite_rings/residue_field.pyx +++ b/src/sage/rings/finite_rings/residue_field.pyx @@ -870,7 +870,7 @@ cdef class ReductionMap(Map): self._PBinv = PBinv self._to_order = to_order # used for lift self._PB = PB # used for lift - from sage.categories.sets_with_partial_maps import SetsWithPartialMaps + from sage.categories.all import SetsWithPartialMaps self._repr_type_str = "Partially defined reduction" Map.__init__(self, Hom(K, F, SetsWithPartialMaps())) diff --git a/src/sage/rings/fraction_field.py b/src/sage/rings/fraction_field.py index 3f1964b13d2..45ef3e63ae0 100644 --- a/src/sage/rings/fraction_field.py +++ b/src/sage/rings/fraction_field.py @@ -1138,7 +1138,7 @@ def section(self): """ from sage.categories.sets_with_partial_maps import SetsWithPartialMaps - from sage.categories.homset import Hom + from sage.categories.all import Hom parent = Hom(self.codomain(), self.domain(), SetsWithPartialMaps()) return parent.__make_element_class__(FractionFieldEmbeddingSection)(self) diff --git a/src/sage/rings/function_field/divisor.py b/src/sage/rings/function_field/divisor.py index 10e06c248cd..5ad77420b5d 100644 --- a/src/sage/rings/function_field/divisor.py +++ b/src/sage/rings/function_field/divisor.py @@ -51,7 +51,7 @@ from sage.misc.cachefunc import cached_method from sage.misc.latex import latex -from sage.arith.functions import lcm +from sage.arith.all import lcm from sage.structure.unique_representation import UniqueRepresentation from sage.structure.parent import Parent diff --git a/src/sage/rings/function_field/function_field.py b/src/sage/rings/function_field/function_field.py index 782aa99cc42..e8cf51beda6 100644 --- a/src/sage/rings/function_field/function_field.py +++ b/src/sage/rings/function_field/function_field.py @@ -225,7 +225,7 @@ from sage.interfaces.singular import singular -from sage.arith.functions import lcm +from sage.arith.all import lcm from sage.rings.integer import Integer from sage.rings.ring import Field diff --git a/src/sage/rings/function_field/order.py b/src/sage/rings/function_field/order.py index 2ba5cd9ac66..745690401cd 100644 --- a/src/sage/rings/function_field/order.py +++ b/src/sage/rings/function_field/order.py @@ -108,8 +108,7 @@ from sage.misc.cachefunc import cached_method from sage.modules.free_module_element import vector -from sage.arith.functions import lcm -from sage.arith.misc import GCD as gcd +from sage.arith.all import lcm, gcd from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.algebras.all import FiniteDimensionalAlgebra diff --git a/src/sage/rings/function_field/place.py b/src/sage/rings/function_field/place.py index 69993a4b744..a05d9ae3fae 100644 --- a/src/sage/rings/function_field/place.py +++ b/src/sage/rings/function_field/place.py @@ -57,7 +57,7 @@ from sage.misc.cachefunc import cached_method -from sage.arith.functions import lcm +from sage.arith.all import lcm from sage.rings.integer_ring import ZZ from sage.rings.qqbar import QQbar diff --git a/src/sage/rings/morphism.pyx b/src/sage/rings/morphism.pyx index 70fc5aacc73..eb54dc4a900 100644 --- a/src/sage/rings/morphism.pyx +++ b/src/sage/rings/morphism.pyx @@ -412,7 +412,7 @@ def is_RingHomomorphism(phi): sage.misc.superseded.deprecation(23204, "is_RingHomomorphism() should not be used anymore. Check whether the category_for() your morphism is a subcategory of Rings() instead.") # We use the category framework to determine whether something is a ring homomorphism. from sage.categories.map import Map - from sage.categories.rings import Rings + from sage.categories.all import Rings return isinstance(phi, Map) and phi.category_for().is_subcategory(Rings()) diff --git a/src/sage/rings/noncommutative_ideals.pyx b/src/sage/rings/noncommutative_ideals.pyx index 0661987be2a..5ef8a83a1d2 100644 --- a/src/sage/rings/noncommutative_ideals.pyx +++ b/src/sage/rings/noncommutative_ideals.pyx @@ -385,7 +385,7 @@ class Ideal_nc(Ideal_generic): of Full MatrixSpace of 2 by 2 dense matrices over Rational Field sage: IL * IR - Twosided Ideal + Twosided Ideal ( [0 3] [0 0] diff --git a/src/sage/rings/number_field/homset.py b/src/sage/rings/number_field/homset.py index 6353353afe1..7072a4ddf8a 100644 --- a/src/sage/rings/number_field/homset.py +++ b/src/sage/rings/number_field/homset.py @@ -51,8 +51,7 @@ def __init__(self, R, S, category=None): Category of homsets of number fields """ if category is None: - from sage.categories.fields import Fields - from sage.categories.number_fields import NumberFields + from sage.categories.all import Fields, NumberFields if S in NumberFields(): category = NumberFields() elif S in Fields(): @@ -103,8 +102,7 @@ def _element_constructor_(self, x, check=True): """ if not isinstance(x, NumberFieldHomomorphism_im_gens): return self.element_class(self, x, check=check) - from sage.categories.number_fields import NumberFields - from sage.categories.rings import Rings + from sage.categories.all import NumberFields, Rings if (x.parent() == self or (x.domain() == self.domain() and x.codomain() == self.codomain() and # This would be the better check, however it returns False currently: diff --git a/src/sage/rings/number_field/number_field.py b/src/sage/rings/number_field/number_field.py index 1dd1bcbc973..8c02fa8e494 100644 --- a/src/sage/rings/number_field/number_field.py +++ b/src/sage/rings/number_field/number_field.py @@ -4142,7 +4142,7 @@ def completely_split_primes(self, B=200): from sage.rings.fast_arith import prime_range from sage.rings.finite_rings.finite_field_constructor import GF from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing - from sage.arith.misc import factor + from sage.arith.all import factor split_primes = [] for p in prime_range(B): Fp = GF(p) @@ -9358,7 +9358,7 @@ def closure_map(x, prec=53): r1, r2 = K.signature() r = r1 + r2 - 1 - from sage.rings.real_mpfr import RealField + from sage.rings.all import RealField Reals = RealField(prec) if x == 0: diff --git a/src/sage/rings/number_field/number_field_ideal.py b/src/sage/rings/number_field/number_field_ideal.py index d5f7157217f..33481fead06 100644 --- a/src/sage/rings/number_field/number_field_ideal.py +++ b/src/sage/rings/number_field/number_field_ideal.py @@ -42,8 +42,7 @@ import sage.rings.rational_field as rational_field import sage.rings.integer_ring as integer_ring -from sage.arith.misc import kronecker as kronecker_symbol -from sage.arith.misc import GCD as gcd +from sage.arith.all import kronecker_symbol, gcd import sage.misc.misc as misc from sage.rings.finite_rings.finite_field_constructor import FiniteField @@ -2074,7 +2073,7 @@ def reduce(self, f): Rbasis = R.basis() n = len(Rbasis) - from sage.matrix.matrix_space import MatrixSpace + from sage.matrix.all import MatrixSpace M = MatrixSpace(ZZ,n)([R.coordinates(y) for y in self.basis()]) D = M.hermite_form() @@ -2143,7 +2142,7 @@ def residues(self): R = self.number_field().maximal_order() Rbasis = R.basis() n = len(Rbasis) - from sage.matrix.matrix_space import MatrixSpace + from sage.matrix.all import MatrixSpace M = MatrixSpace(ZZ, n)([R.coordinates(_) for _ in self.basis()]) D = M.hermite_form() @@ -2284,8 +2283,7 @@ def invertible_residues_mod(self, subgp_gens=[], reduce=True): g = G.gens_values() n = G.ngens() - from sage.matrix.constructor import Matrix - from sage.matrix.special import diagonal_matrix + from sage.matrix.all import Matrix, diagonal_matrix M = diagonal_matrix(ZZ, invs) if subgp_gens: @@ -2713,11 +2711,7 @@ def ideallog(self, x, gens=None, check=True): G = self.idealstar(2) invs = G.invariants() - from sage.matrix.constructor import Matrix as matrix - from sage.matrix.special import identity_matrix - from sage.matrix.special import zero_matrix - from sage.matrix.special import diagonal_matrix - from sage.matrix.special import block_matrix + from sage.matrix.all import matrix, identity_matrix, zero_matrix, diagonal_matrix, block_matrix # We use Hermite normal form twice: once to express the standard # generators in terms of the new ones (independently of x) and once to diff --git a/src/sage/rings/number_field/number_field_morphisms.pyx b/src/sage/rings/number_field/number_field_morphisms.pyx index 34a51a97c62..f0f3d447dc8 100644 --- a/src/sage/rings/number_field/number_field_morphisms.pyx +++ b/src/sage/rings/number_field/number_field_morphisms.pyx @@ -715,10 +715,10 @@ cdef class CyclotomicFieldConversion(Map): EXAMPLES:: sage: from sage.rings.number_field.number_field_morphisms import CyclotomicFieldConversion - sage: K1. = CyclotomicField(12) + sage: K1. = CyclotomicField(12) sage: K2. = CyclotomicField(18) - sage: f = CyclotomicFieldConversion(K1, K2) - sage: f(z1^2) + sage: f = CyclotomicFieldConversion(K1, K2) + sage: f(z1^2) z2^3 sage: f(z1) Traceback (most recent call last): diff --git a/src/sage/rings/number_field/number_field_rel.py b/src/sage/rings/number_field/number_field_rel.py index 8ecb87fce28..5b14f034b8c 100644 --- a/src/sage/rings/number_field/number_field_rel.py +++ b/src/sage/rings/number_field/number_field_rel.py @@ -104,9 +104,7 @@ from sage.modules.free_module import VectorSpace from sage.modules.free_module_element import vector -from sage.rings.real_mpfr import RR -from sage.rings.rational_field import QQ -from sage.rings.integer_ring import ZZ +from sage.rings.all import RR, QQ, ZZ def is_RelativeNumberField(x): @@ -2118,7 +2116,7 @@ def closure_map(x, prec=53): r1, r2 = K.signature() r = r1 + r2 - 1 - from sage.rings.real_mpfr import RealField + from sage.rings.all import RealField Reals = RealField(prec) if x == 0: diff --git a/src/sage/rings/number_field/splitting_field.py b/src/sage/rings/number_field/splitting_field.py index 14871fecc05..d61b9f25226 100644 --- a/src/sage/rings/number_field/splitting_field.py +++ b/src/sage/rings/number_field/splitting_field.py @@ -19,7 +19,7 @@ #***************************************************************************** from sage.rings.integer import Integer -from sage.arith.misc import factorial +from sage.arith.all import factorial from sage.rings.number_field.all import NumberField from sage.rings.polynomial.all import PolynomialRing from sage.rings.rational_field import RationalField, is_RationalField diff --git a/src/sage/rings/number_field/totallyreal_data.pyx b/src/sage/rings/number_field/totallyreal_data.pyx index adc52e6cfab..35786842573 100644 --- a/src/sage/rings/number_field/totallyreal_data.pyx +++ b/src/sage/rings/number_field/totallyreal_data.pyx @@ -27,8 +27,7 @@ AUTHORS: from libc.math cimport sqrt from cysignals.memory cimport sig_malloc, sig_free -from sage.arith.misc import binomial -from sage.arith.misc import GCD as gcd +from sage.arith.all import binomial, gcd from sage.libs.gmp.mpz cimport * from sage.rings.rational_field import RationalField from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing diff --git a/src/sage/rings/number_field/totallyreal_rel.py b/src/sage/rings/number_field/totallyreal_rel.py index 07477c46f8f..008edfd4e0b 100644 --- a/src/sage/rings/number_field/totallyreal_rel.py +++ b/src/sage/rings/number_field/totallyreal_rel.py @@ -90,9 +90,7 @@ # https://www.gnu.org/licenses/ # **************************************************************************** -from sage.arith.misc import binomial -from sage.arith.misc import GCD as gcd -from sage.arith.misc import divisors +from sage.arith.all import binomial, gcd, divisors from sage.rings.integer import Integer from sage.rings.integer_ring import IntegerRing from sage.rings.number_field.totallyreal_data import ZZx, lagrange_degree_3, int_has_small_square_divisor, hermite_constant diff --git a/src/sage/rings/padics/common_conversion.pyx b/src/sage/rings/padics/common_conversion.pyx index 4ed5570d306..7ad0554072d 100644 --- a/src/sage/rings/padics/common_conversion.pyx +++ b/src/sage/rings/padics/common_conversion.pyx @@ -42,7 +42,7 @@ from sage.structure.element cimport parent cdef long maxordp = (1L << (sizeof(long) * 8 - 2)) - 1 cdef long minusmaxordp = -maxordp -# The following Integer (resp. Rational) is used so that +# The following Integer (resp. Rational) is used so that # the functions here don't need to initialize an mpz_t (resp. mpq_t) cdef Integer temp = PY_NEW(Integer) cdef Rational rat_temp = PY_NEW(Rational) diff --git a/src/sage/rings/padics/local_generic_element.pyx b/src/sage/rings/padics/local_generic_element.pyx index cf7df2f2541..0571aa5cf4c 100644 --- a/src/sage/rings/padics/local_generic_element.pyx +++ b/src/sage/rings/padics/local_generic_element.pyx @@ -202,9 +202,9 @@ cdef class LocalGenericElement(CommutativeRingElement): def slice(self, i, j, k = 1, lift_mode='simple'): r""" Returns the sum of the `pi^{i + l \cdot k}` terms of the series - expansion of this element, where pi is the uniformizer, - for `i + l \cdot k` between ``i`` and ``j-1`` inclusive, and - nonnegative integers `l`. Behaves analogously to the slice + expansion of this element, where pi is the uniformizer, + for `i + l \cdot k` between ``i`` and ``j-1`` inclusive, and + nonnegative integers `l`. Behaves analogously to the slice function for lists. INPUT: @@ -300,7 +300,7 @@ cdef class LocalGenericElement(CommutativeRingElement): 5^2 + O(5^8) Test that slices also work over eisenstein extensions:: - + sage: F = Qp(5) sage: H. = F[] sage: T. = F.extension(x^2-5) @@ -313,7 +313,7 @@ cdef class LocalGenericElement(CommutativeRingElement): 3*t^-2 + 4*t + O(t^6) Test that slices also work over unramified extensions:: - + sage: F = Qp(5) sage: H. = F[] sage: T. = F.extension(x^2-2) @@ -326,7 +326,7 @@ cdef class LocalGenericElement(CommutativeRingElement): 3*5^-1 + (3*t + 4)*5^2 + O(5^6) Test that slices also work over 2-step extensions (unramified followed by eisenstein):: - + sage: F = Qp(5) sage: H. = F[] sage: T. = F.extension(x^2-3) @@ -337,7 +337,7 @@ cdef class LocalGenericElement(CommutativeRingElement): (2*t + 2)*w^-23 + O(w^2) sage: a.slice(0, 1) O(w) - + Verify that :trac:`14106` has been fixed:: sage: R = Zp(5,7) @@ -1001,7 +1001,7 @@ cdef class LocalGenericElement(CommutativeRingElement): # so that this test doesn't take too long for large precision cap prec_cutoff = int(min((10000 / (1 + self.precision_relative())).ceil(), 100)) - from sage.categories.fields import Fields + from sage.categories.all import Fields if self.parent() in Fields(): v = self.valuation() from sage.rings.infinity import infinity diff --git a/src/sage/rings/padics/padic_ZZ_pX_element.pyx b/src/sage/rings/padics/padic_ZZ_pX_element.pyx index ec33070be49..d8a44de80f1 100644 --- a/src/sage/rings/padics/padic_ZZ_pX_element.pyx +++ b/src/sage/rings/padics/padic_ZZ_pX_element.pyx @@ -483,12 +483,12 @@ cdef class pAdicZZpXElement(pAdicExtElement): 4*5 + 5^2 + 5^3 + 2*5^4 sage: (a+b).trace() 4*5 + 5^2 + 5^3 + 2*5^4 - + TESTS: We check that :trac:`32072` is resolved:: - sage: F = Qp(2) + sage: F = Qp(2) sage: S. = F[] sage: L. = F.ext(x^2 - 2) sage: L(0, 20).trace() diff --git a/src/sage/rings/padics/padic_generic_element.pyx b/src/sage/rings/padics/padic_generic_element.pyx index 3785ac7a3d6..82d77b94b9b 100644 --- a/src/sage/rings/padics/padic_generic_element.pyx +++ b/src/sage/rings/padics/padic_generic_element.pyx @@ -1171,7 +1171,7 @@ cdef class pAdicGenericElement(LocalGenericElement): x^4 - x^3 + x^2 - x + 1 """ # TODO: figure out if this works for extension rings. If not, move this to padic_base_generic_element. - from sage.arith.misc import algdep + from sage.arith.all import algdep return algdep(self, n) def algebraic_dependency(self, n): @@ -2220,7 +2220,7 @@ cdef class pAdicGenericElement(LocalGenericElement): p = self.parent().prime() alpha = self.unit_part().lift() m = Integer(p**self.precision_relative()) - from sage.arith.misc import rational_reconstruction + from sage.arith.all import rational_reconstruction r = rational_reconstruction(alpha, m) return (Rational(p)**self.valuation())*r diff --git a/src/sage/rings/padics/padic_valuation.py b/src/sage/rings/padics/padic_valuation.py index 2d444d0e676..883e36f5c96 100644 --- a/src/sage/rings/padics/padic_valuation.py +++ b/src/sage/rings/padics/padic_valuation.py @@ -368,7 +368,7 @@ def _normalize_number_field_data(self, R): G = L.relative_polynomial() K = L.base_ring() elif is_PolynomialQuotientRing(R): - from sage.categories.number_fields import NumberFields + from sage.categories.all import NumberFields if R.base_ring().fraction_field() not in NumberFields(): raise NotImplementedError("cannot normalize quotients over %r"%(R.base_ring(),)) L = R.fraction_field() @@ -798,7 +798,7 @@ def extensions(self, ring): base_extensions = self._base_valuation.extensions(self._base_valuation.domain().change_ring(self._base_valuation.domain().base_ring().fraction_field())) return [pAdicValuation(ring, base._initial_approximation) for base in base_extensions] if ring.base_ring() is self.domain(): - from sage.categories.integral_domains import IntegralDomains + from sage.categories.all import IntegralDomains if ring in IntegralDomains(): return self._extensions_to_quotient(ring) elif self.domain().is_subring(ring.base_ring()): @@ -843,7 +843,7 @@ def value_semigroup(self): Additive Abelian Semigroup generated by 1/2 """ - from sage.categories.fields import Fields + from sage.categories.all import Fields v = self(self.uniformizer()) if self.domain() in Fields(): return DiscreteValueSemigroup([-v,v]) @@ -1265,7 +1265,7 @@ def simplify(self, x, error=None, force=False, size_heuristic_bound=32): # algorithm (based on the extended Euclidean algorithm) here. We do not # get the uniqueness properties but we do not need them actually. # This is certainly slower than the implementation in Cython. - from sage.categories.fields import Fields + from sage.categories.all import Fields m = self.p()**(QQ(error).floor() + 1 - v) if self.domain() in Fields(): r = (m, lift) @@ -1274,7 +1274,7 @@ def simplify(self, x, error=None, force=False, size_heuristic_bound=32): qq, rr = r[0].quo_rem(r[1]) r = r[1], rr s = s[1], s[0] - qq*s[1] - from sage.arith.misc import GCD as gcd + from sage.arith.all import gcd if s[1] != 0 and gcd(s[1], r[1]) == 1: rational = self.domain()(r[1]) / self.domain()(s[1]) * self.p()**v if self._relative_size(rational) < self._relative_size(best): @@ -1446,13 +1446,13 @@ def _fraction_field(ring): Univariate Quotient Polynomial Ring in xbar over Rational Field with modulus x^2 + 1 """ - from sage.categories.fields import Fields + from sage.categories.all import Fields if ring in Fields(): return ring from sage.rings.polynomial.polynomial_quotient_ring import is_PolynomialQuotientRing if is_PolynomialQuotientRing(ring): - from sage.categories.integral_domains import IntegralDomains + from sage.categories.all import IntegralDomains if ring in IntegralDomains(): return ring.base().change_ring(ring.base_ring().fraction_field()).quo(ring.modulus()) return ring.fraction_field() diff --git a/src/sage/rings/padics/relative_ramified_CA.pyx b/src/sage/rings/padics/relative_ramified_CA.pyx index 0a2df891f87..3c5d95b02ff 100644 --- a/src/sage/rings/padics/relative_ramified_CA.pyx +++ b/src/sage/rings/padics/relative_ramified_CA.pyx @@ -4,7 +4,7 @@ include "CA_template.pxi" cdef class RelativeRamifiedCappedAbsoluteElement(CAElement): def _poly_rep(self): """ - Return the underlying polynomial representation of this element + Return the underlying polynomial representation of this element (which is used for computations). For debugging and printing purpose. @@ -22,7 +22,7 @@ cdef class RelativeRamifiedCappedAbsoluteElement(CAElement): The coefficients of P are floating point p-adics:: sage: P = W.random_element()._poly_rep() - sage: ring = P.parent().base_ring() + sage: ring = P.parent().base_ring() sage: ring 5-adic Unramified Extension Ring in a defined by x^3 + 3*x + 3 sage: ring._prec_type() diff --git a/src/sage/rings/polynomial/complex_roots.py b/src/sage/rings/polynomial/complex_roots.py index 0d84a9c757b..cf63cba4bce 100644 --- a/src/sage/rings/polynomial/complex_roots.py +++ b/src/sage/rings/polynomial/complex_roots.py @@ -40,7 +40,7 @@ from sage.rings.complex_mpfr import ComplexField from sage.rings.complex_interval_field import ComplexIntervalField from sage.rings.qqbar import AA, QQbar -from sage.arith.misc import sort_complex_numbers_for_display +from sage.arith.all import sort_complex_numbers_for_display from sage.rings.polynomial.refine_root import refine_root diff --git a/src/sage/rings/polynomial/cyclotomic.pyx b/src/sage/rings/polynomial/cyclotomic.pyx index 1053f471a7a..cc588f0ec05 100644 --- a/src/sage/rings/polynomial/cyclotomic.pyx +++ b/src/sage/rings/polynomial/cyclotomic.pyx @@ -32,7 +32,7 @@ from cysignals.signals cimport sig_on, sig_off from sage.structure.element cimport parent -from sage.arith.misc import factor +from sage.arith.all import factor from sage.rings.integer_ring import ZZ from sage.misc.misc_c import prod from sage.misc.misc import subsets diff --git a/src/sage/rings/polynomial/infinite_polynomial_ring.py b/src/sage/rings/polynomial/infinite_polynomial_ring.py index ff237743f4a..1bc126c1e00 100644 --- a/src/sage/rings/polynomial/infinite_polynomial_ring.py +++ b/src/sage/rings/polynomial/infinite_polynomial_ring.py @@ -1348,19 +1348,6 @@ def order(self): from sage.rings.infinity import Infinity return Infinity - # Other bases - def key_basis(self): - r""" - Return the basis of ``self`` given by key polynomials. - - EXAMPLES:: - - sage: R. = InfinitePolynomialRing(GF(2)) - sage: R.key_basis() - Key polynomial basis over Finite Field of size 2 - """ - from sage.combinat.key_polynomial import KeyPolynomialBasis - return KeyPolynomialBasis(self) class InfinitePolynomialGen(SageObject): """ diff --git a/src/sage/rings/polynomial/multi_polynomial.pyx b/src/sage/rings/polynomial/multi_polynomial.pyx index 7bb03631661..49e4c52d365 100644 --- a/src/sage/rings/polynomial/multi_polynomial.pyx +++ b/src/sage/rings/polynomial/multi_polynomial.pyx @@ -1210,7 +1210,7 @@ cdef class MPolynomial(CommutativeRingElement): Rational Field """ - from sage.arith.misc import GCD as gcd + from sage.arith.all import gcd return gcd(self.coefficients()) def content_ideal(self): diff --git a/src/sage/rings/polynomial/multi_polynomial_ideal.py b/src/sage/rings/polynomial/multi_polynomial_ideal.py index 71494eddbc0..7dc058a22f0 100644 --- a/src/sage/rings/polynomial/multi_polynomial_ideal.py +++ b/src/sage/rings/polynomial/multi_polynomial_ideal.py @@ -60,7 +60,7 @@ Note that the result of a computation is not necessarily reduced:: sage: (a+b)^17 - a*b^16 + b^17 + 256*a*b^16 + 256*b^17 sage: S(17) == 0 True diff --git a/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx b/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx index 81d266f499f..f3c0bc09542 100644 --- a/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx +++ b/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx @@ -193,7 +193,7 @@ from sage.libs.singular.decl cimport ( p_IsUnit, p_IsOne, p_Series, p_Head, idInit, fast_map_common_subexp, id_Delete, p_IsHomogeneous, p_Homogen, p_Totaldegree,pLDeg1_Totaldegree, singclap_pdivide, singclap_factorize, idLift, IDELEMS, On, Off, SW_USE_CHINREM_GCD, SW_USE_EZGCD, - p_LmIsConstant, pTakeOutComp, singclap_gcd, pp_Mult_qq, p_GetMaxExp, + p_LmIsConstant, pTakeOutComp1, singclap_gcd, pp_Mult_qq, p_GetMaxExp, pLength, kNF, p_Neg, p_Minus_mm_Mult_qq, p_Plus_mm_Mult_qq, pDiff, singclap_resultant, p_Normalize, prCopyR, prCopyR_NoSort) @@ -247,7 +247,7 @@ from sage.structure.factorization import Factorization from sage.structure.sequence import Sequence from sage.rings.fraction_field import FractionField -from sage.rings.real_mpfr import RealField +from sage.rings.all import RealField import sage.interfaces.abc @@ -1590,8 +1590,7 @@ cdef class MPolynomialRing_libsingular(MPolynomialRing_base): 9/4 sage: P.monomial_quotient(x,y) # Note the wrong result - x*y^65535*z^65535 # 32-bit - x*y^1048575*z^1048575 # 64-bit + x*y^65535*z^65535 sage: P.monomial_quotient(x,P(1)) x @@ -2251,11 +2250,10 @@ cdef class MPolynomial_libsingular(MPolynomial): 9/4*x^2 - 1/4*y^2 - y - 1 sage: P. = PolynomialRing(QQ,order='lex') - sage: (x^2^32) * x^2^32 + sage: (x^2^15) * x^2^15 Traceback (most recent call last): ... - OverflowError: Python int too large to convert to C unsigned long # 32-bit - OverflowError: exponent overflow (...) # 64-bit + OverflowError: exponent overflow (...) """ # all currently implemented rings are commutative cdef poly *_p @@ -2376,11 +2374,10 @@ cdef class MPolynomial_libsingular(MPolynomial): ValueError: not a 2nd power sage: P. = PolynomialRing(QQ,order='lex') - sage: (x+y^2^32)^10 + sage: (x+y^2^15)^10 Traceback (most recent call last): .... - OverflowError: Python int too large to convert to C unsigned long # 32-bit - OverflowError: exponent overflow (...) # 64-bit + OverflowError: exponent overflow (...) Test fractional powers (:trac:`22329`):: @@ -3467,7 +3464,7 @@ cdef class MPolynomial_libsingular(MPolynomial): x^10000 no overflow - sage: n = 100000 + sage: n = 1000 sage: try: ....: f = x^n ....: f.subs(x = x^n) @@ -4573,7 +4570,7 @@ cdef class MPolynomial_libsingular(MPolynomial): l = [] for i from 0 <= i < IDELEMS(res): for j from 1 <= j <= IDELEMS(_I): - l.append( new_MP(parent, pTakeOutComp(&res.m[i], 1)) ) + l.append( new_MP(parent, pTakeOutComp1(&res.m[i], j)) ) id_Delete(&fI, r) id_Delete(&_I, r) @@ -4641,7 +4638,7 @@ cdef class MPolynomial_libsingular(MPolynomial): sage: f = 3*x sage: f.reduce([2*x,y]) - x + 3*x The reduction is not canonical when ``I`` is not a Groebner basis:: diff --git a/src/sage/rings/polynomial/multi_polynomial_ring_base.pyx b/src/sage/rings/polynomial/multi_polynomial_ring_base.pyx index 6e8ca561e2a..f6a46ac4898 100644 --- a/src/sage/rings/polynomial/multi_polynomial_ring_base.pyx +++ b/src/sage/rings/polynomial/multi_polynomial_ring_base.pyx @@ -21,7 +21,7 @@ from sage.categories.morphism import IdentityMorphism from sage.categories.commutative_rings import CommutativeRings _CommutativeRings = CommutativeRings() -from sage.arith.misc import binomial +from sage.arith.all import binomial from sage.combinat.integer_vector import IntegerVectors @@ -444,7 +444,7 @@ cdef class MPolynomialRing_base(sage.rings.ring.CommutativeRing): 1/2*x^3 + x*y + z^2 - 1/2*x + y + 25 .. SEEALSO:: - + :meth:`lagrange_polynomial` """ # get ring and number of variables diff --git a/src/sage/rings/polynomial/omega.py b/src/sage/rings/polynomial/omega.py index f2ab5232b2e..3421ef04126 100644 --- a/src/sage/rings/polynomial/omega.py +++ b/src/sage/rings/polynomial/omega.py @@ -556,8 +556,7 @@ def Omega_ge(a, exponents): logger = logging.getLogger(__name__) logger.info('Omega_ge: a=%s, exponents=%s', a, exponents) - from sage.arith.functions import lcm - from sage.arith.srange import srange + from sage.arith.all import lcm, srange from sage.rings.integer_ring import ZZ from sage.rings.polynomial.laurent_polynomial_ring import LaurentPolynomialRing from sage.rings.number_field.number_field import CyclotomicField diff --git a/src/sage/rings/polynomial/pbori/pbori.pyx b/src/sage/rings/polynomial/pbori/pbori.pyx index dbd5defb793..ee658dec9e4 100644 --- a/src/sage/rings/polynomial/pbori/pbori.pyx +++ b/src/sage/rings/polynomial/pbori/pbori.pyx @@ -1221,7 +1221,7 @@ cdef class BooleanPolynomialRing(MPolynomialRing_base): sage: r = B.random_element(terms=(n/2)**2) """ from sage.rings.integer import Integer - from sage.arith.misc import binomial + from sage.arith.all import binomial if not vars_set: vars_set=range(self.ngens()) diff --git a/src/sage/rings/polynomial/plural.pyx b/src/sage/rings/polynomial/plural.pyx index d019a89d99e..2c4e83952e9 100644 --- a/src/sage/rings/polynomial/plural.pyx +++ b/src/sage/rings/polynomial/plural.pyx @@ -1619,10 +1619,10 @@ cdef class NCPolynomial_plural(RingElement): sage: P = A.g_algebra(relations={y*x:-x*y + z}, order='lex') sage: P.inject_variables() Defining x, z, y - sage: (x^2^31) * x^2^31 + sage: (x^2^15) * x^2^15 Traceback (most recent call last): ... - OverflowError: exponent overflow (2147483648) + OverflowError: exponent overflow (65536) """ # all currently implemented rings are commutative cdef poly *_p @@ -1689,10 +1689,10 @@ cdef class NCPolynomial_plural(RingElement): sage: P = A.g_algebra(relations={y*x:-x*y + z}, order='lex') sage: P.inject_variables() Defining x, z, y - sage: (x+y^2^31)^10 + sage: (x+y^2^15)^10 Traceback (most recent call last): .... - OverflowError: exponent overflow (2147483648) + OverflowError: exponent overflow (327680) """ if type(exp) is not Integer: try: diff --git a/src/sage/rings/polynomial/polynomial_element.pyx b/src/sage/rings/polynomial/polynomial_element.pyx index 09807019d6c..d2649163d48 100644 --- a/src/sage/rings/polynomial/polynomial_element.pyx +++ b/src/sage/rings/polynomial/polynomial_element.pyx @@ -116,8 +116,8 @@ from sage.structure.category_object cimport normalize_names from sage.misc.derivative import multi_derivative -from sage.arith.misc import sort_complex_numbers_for_display, power_mod, is_prime -from sage.arith.functions import lcm +from sage.arith.all import (sort_complex_numbers_for_display, + power_mod, lcm, is_prime) from . import polynomial_fateman @@ -7217,7 +7217,7 @@ cdef class Polynomial(CommutativeAlgebraElement): return x - c if k > n - k: # use (n-k)'th symmetric power g = self.symmetric_power(n - k, monic=monic) - from sage.arith.misc import binomial + from sage.arith.all import binomial g = ((-x)**binomial(n,k) * g(c/x) / c**binomial(n-1,k)).numerator() if monic: g = g.monic() diff --git a/src/sage/rings/polynomial/polynomial_integer_dense_flint.pyx b/src/sage/rings/polynomial/polynomial_integer_dense_flint.pyx index 1d5a863e899..2df63d29c14 100644 --- a/src/sage/rings/polynomial/polynomial_integer_dense_flint.pyx +++ b/src/sage/rings/polynomial/polynomial_integer_dense_flint.pyx @@ -59,7 +59,7 @@ from sage.libs.pari.all import pari, pari_gen from sage.structure.factorization import Factorization from sage.rings.fraction_field_element import FractionFieldElement -from sage.arith.functions import lcm +from sage.arith.all import lcm from sage.libs.arb.arb_fmpz_poly cimport arb_fmpz_poly_evaluate_arb, arb_fmpz_poly_evaluate_acb from sage.libs.flint.fmpz cimport * diff --git a/src/sage/rings/polynomial/polynomial_integer_dense_ntl.pyx b/src/sage/rings/polynomial/polynomial_integer_dense_ntl.pyx index c2db35e0bf7..41ddaa92e51 100644 --- a/src/sage/rings/polynomial/polynomial_integer_dense_ntl.pyx +++ b/src/sage/rings/polynomial/polynomial_integer_dense_ntl.pyx @@ -67,7 +67,7 @@ from sage.structure.factorization import Factorization from sage.structure.element import coerce_binop from sage.rings.fraction_field_element import FractionFieldElement -from sage.arith.functions import lcm +from sage.arith.all import lcm import sage.rings.polynomial.polynomial_ring from sage.libs.ntl.ZZX cimport * diff --git a/src/sage/rings/polynomial/polynomial_quotient_ring.py b/src/sage/rings/polynomial/polynomial_quotient_ring.py index ab35434ca30..db07f68fd67 100644 --- a/src/sage/rings/polynomial/polynomial_quotient_ring.py +++ b/src/sage/rings/polynomial/polynomial_quotient_ring.py @@ -235,8 +235,7 @@ def create_object(self, version, key): ring, polynomial, names = key R = ring.base_ring() - from sage.categories.integral_domains import IntegralDomains - from sage.categories.fields import Fields + from sage.categories.all import IntegralDomains, Fields if R in IntegralDomains(): try: is_irreducible = polynomial.is_irreducible() @@ -1057,7 +1056,7 @@ def is_field(self, proof = True): ret = False if ret: - from sage.categories.fields import Fields + from sage.categories.all import Fields self._refine_category_(Fields()) return ret @@ -1113,7 +1112,7 @@ def is_integral_domain(self, proof = True): Unfortunately, the program above is already unable to determine that the modulus is irreducible. """ - from sage.categories.integral_domains import IntegralDomains + from sage.categories.all import IntegralDomains if self.category().is_subcategory(IntegralDomains()): return True ret = self.base_ring().is_integral_domain(proof) @@ -1978,7 +1977,7 @@ def _isomorphic_ring(self): # interface which we cannot provide (e.g. NumberFields). # So we just check some important special cases here (note that # integral domains is already handled elsewhere.) - from sage.categories.fields import Fields + from sage.categories.all import Fields if isomorphic_ring in Fields(): self._refine_category_(Fields()) @@ -2024,7 +2023,7 @@ def _isomorphic_ring(self): return from_isomorphic_ring, to_isomorphic_ring, isomorphic_ring - from sage.categories.number_fields import NumberFields + from sage.categories.all import NumberFields if self.base_ring() in NumberFields(): try: isomorphic_ring = self.base_ring().extension(self.modulus(), names=self.variable_names()) @@ -2067,8 +2066,7 @@ def _test_isomorphic_ring(self, **options): tester.assertNotIsInstance(ring, PolynomialQuotientRing_generic) - from sage.categories.fields import Fields - from sage.categories.integral_domains import IntegralDomains + from sage.categories.all import Fields, IntegralDomains if ring.category().is_subcategory(IntegralDomains()): category = IntegralDomains() if ring.category().is_subcategory(Fields()): diff --git a/src/sage/rings/polynomial/polynomial_rational_flint.pyx b/src/sage/rings/polynomial/polynomial_rational_flint.pyx index ea0469386dc..88cccdfb537 100644 --- a/src/sage/rings/polynomial/polynomial_rational_flint.pyx +++ b/src/sage/rings/polynomial/polynomial_rational_flint.pyx @@ -2513,25 +2513,25 @@ cdef class Polynomial_rational_flint(Polynomial): def galois_group_davenport_smith_test(self, num_trials=50, assume_irreducible=False): """ Use the Davenport-Smith test to attempt to certify that `f` has Galois group A_n or S_n. - + Return 1 if the Galois group is certified as S_n, 2 if A_n, or 0 if no conclusion is reached. - + By default, we first check that `f` is irreducible. For extra efficiency, one can override this by specifying `assume_irreducible=True`; this yields undefined results if `f` is not irreducible. - + A corresponding function in Magma is `IsEasySnAn`. EXAMPLES:: sage: P. = QQ[] sage: u = x^7 + x + 1 - sage: u.galois_group_davenport_smith_test() + sage: u.galois_group_davenport_smith_test() 1 - sage: u = x^7 - x^4 - x^3 + 3*x^2 - 1 - sage: u.galois_group_davenport_smith_test() + sage: u = x^7 - x^4 - x^3 + 3*x^2 - 1 + sage: u.galois_group_davenport_smith_test() 2 sage: u = x^7 - 2 - sage: u.galois_group_davenport_smith_test() + sage: u.galois_group_davenport_smith_test() 0 """ diff --git a/src/sage/rings/polynomial/toy_d_basis.py b/src/sage/rings/polynomial/toy_d_basis.py index 07f83100df7..15cfd4eea52 100644 --- a/src/sage/rings/polynomial/toy_d_basis.py +++ b/src/sage/rings/polynomial/toy_d_basis.py @@ -116,8 +116,7 @@ - Martin Albrecht (2008-08): initial version """ from sage.rings.integer_ring import ZZ -from sage.arith.functions import lcm -from sage.arith.misc import XGCD as xgcd, GCD as gcd +from sage.arith.all import xgcd, lcm, gcd from sage.rings.polynomial.toy_buchberger import inter_reduction from sage.structure.sequence import Sequence diff --git a/src/sage/rings/polynomial/weil/weil_polynomials.pyx b/src/sage/rings/polynomial/weil/weil_polynomials.pyx index 2e2d6974fb7..f2544ed77c8 100755 --- a/src/sage/rings/polynomial/weil/weil_polynomials.pyx +++ b/src/sage/rings/polynomial/weil/weil_polynomials.pyx @@ -83,7 +83,7 @@ cdef class dfs_manager: """ Data structure to manage depth-first search. - Such a structure is created and managed by an instance of `WeilPolynomials_iter`. + Such a structure is created and managed by an instance of `WeilPolynomials_iter`. There is generally no need for a user to manipulate it directly. """ cdef int d @@ -424,15 +424,15 @@ class WeilPolynomials(): - ``node_limit`` -- integer (default ``None``) - If set, imposes an upper bound on the number of terminal nodes during the search + If set, imposes an upper bound on the number of terminal nodes during the search (will raise a ``RuntimeError`` if exceeded). - ``parallel`` -- boolean (default ``False``), whether to use multiple processes - If set, will raise an error unless this file was compiled with OpenMP support + If set, will raise an error unless this file was compiled with OpenMP support (see instructions at the top of :mod:`sage.rings.polynomial.weil.weil_polynomials`). - - ``squarefree`` -- boolean (default ``False``), + - ``squarefree`` -- boolean (default ``False``), If set, only squarefree polynomials will be returned. @@ -526,10 +526,10 @@ class WeilPolynomials(): Test that :trac:`31809` is resolved:: - sage: from sage.rings.polynomial.weil.weil_polynomials import WeilPolynomials - sage: foo = list(WeilPolynomials(12, 3, lead=(1,0,9,2,46), squarefree=False)) + sage: from sage.rings.polynomial.weil.weil_polynomials import WeilPolynomials + sage: foo = list(WeilPolynomials(12, 3, lead=(1,0,9,2,46), squarefree=False)) sage: bar = list(WeilPolynomials(12, 3, lead=(1,0,9,2,46), squarefree=True)) - sage: bar == [f for f in foo if f.is_squarefree()] + sage: bar == [f for f in foo if f.is_squarefree()] True Test that :trac:`32348` is resolved:: diff --git a/src/sage/rings/qqbar.py b/src/sage/rings/qqbar.py index 6db4b9cd6fd..18228844684 100644 --- a/src/sage/rings/qqbar.py +++ b/src/sage/rings/qqbar.py @@ -578,7 +578,7 @@ from sage.rings.rational_field import QQ from sage.rings.number_field.number_field import NumberField, GaussianField, CyclotomicField from sage.rings.number_field.number_field_element_quadratic import NumberFieldElement_gaussian -from sage.arith.misc import factor +from sage.arith.all import factor from . import infinity from sage.categories.action import Action diff --git a/src/sage/rings/rational.pyx b/src/sage/rings/rational.pyx index 2263d549aef..6964d3a17d1 100644 --- a/src/sage/rings/rational.pyx +++ b/src/sage/rings/rational.pyx @@ -1135,8 +1135,7 @@ cdef class Rational(sage.structure.element.FieldElement): seq.append(self) nums = [x.numerator() for x in seq] denoms = [x.denominator() for x in seq] - from sage.arith.misc import GCD as gcd - from sage.arith.functions import lcm + from sage.arith.all import gcd, lcm return gcd(nums) / lcm(denoms) def valuation(self, p): @@ -1760,7 +1759,7 @@ cdef class Rational(sage.structure.element.FieldElement): if p == 2: return ((m % 8) == 1) - from sage.arith.misc import kronecker as kronecker_symbol + from sage.arith.all import kronecker_symbol return (kronecker_symbol(m, p) == 1) def val_unit(self, p): diff --git a/src/sage/rings/ring_extension.pyx b/src/sage/rings/ring_extension.pyx index 9c24c55d535..b493f57bed9 100644 --- a/src/sage/rings/ring_extension.pyx +++ b/src/sage/rings/ring_extension.pyx @@ -1801,7 +1801,7 @@ cdef class RingExtension_generic(CommutativeAlgebra): sage: L = GF(5^12).over(F) sage: K.Hom(L) # indirect doctest - Set of Homomorphisms from Field in z4 with defining polynomial x^2 + (4*z2 + 3)*x + z2 over its base + Set of Homomorphisms from Field in z4 with defining polynomial x^2 + (4*z2 + 3)*x + z2 over its base to Field in z12 with defining polynomial x^6 + (4*z2 + 3)*x^5 + x^4 + (3*z2 + 1)*x^3 + x^2 + (4*z2 + 1)*x + z2 over its base sage: K.Hom(L, category=Sets()) diff --git a/src/sage/rings/ring_extension_conversion.pyx b/src/sage/rings/ring_extension_conversion.pyx index 9d94fb7567d..36e12b8fcac 100644 --- a/src/sage/rings/ring_extension_conversion.pyx +++ b/src/sage/rings/ring_extension_conversion.pyx @@ -306,7 +306,7 @@ cpdef from_backend_morphism(f, RingExtension_generic E): - ``x`` -- a morphism - - ``E`` -- a ring extension + - ``E`` -- a ring extension EXAMPLES:: @@ -392,14 +392,14 @@ cpdef to_backend(arg): cpdef from_backend(arg, E): r""" - Try to reconstruct something (somehow related to ``E``) + Try to reconstruct something (somehow related to ``E``) whose backend is ``arg``. INPUT: - ``arg`` -- any argument - - ``E`` -- a ring extension + - ``E`` -- a ring extension EXAMPLES:: diff --git a/src/sage/rings/tate_algebra_ideal.pyx b/src/sage/rings/tate_algebra_ideal.pyx index 17031adcec2..58025c6069d 100644 --- a/src/sage/rings/tate_algebra_ideal.pyx +++ b/src/sage/rings/tate_algebra_ideal.pyx @@ -82,20 +82,20 @@ class TateAlgebraIdeal(Ideal_generic): of these algorithms. - ``options`` -- extra arguments that are passed in to the - algorithm; this notably include the keyword ``verbose`` (only + algorithm; this notably include the keyword ``verbose`` (only available for ``PoTe`` and ``VaPoTe``) which is an integer defining the verbosity level: - ``0``: no verbosity (quiet) - - ``1``: print each new generator and a notification each time a + - ``1``: print each new generator and a notification each time a J-pair is popped - ``2``: in addition, print the outcome of the treatment of a J-pair - ``3``: in addition, print all added J-pairs - - ``4``: print entire series instead of only their leading terms + - ``4``: print entire series instead of only their leading terms OUTPUT: @@ -142,7 +142,7 @@ class TateAlgebraIdeal(Ideal_generic): sage: h = 2*x^6*y^4 + 2*x^4 + 4*x^5*y^2 + 8*x^8*y^2 + 8*x^7*y^3 + 8*x^6*y sage: I = A.ideal([f,g,h]) sage: I.groebner_basis(algorithm="buchberger-integral") - [...0001*x^4 + O(2^4 * ), + [...0001*x^4 + O(2^4 * ), ...0001*x^2*y + O(2^4 * ), ...0001*y^2 + O(2^4 * )] sage: I.groebner_basis(algorithm='buchberger') @@ -487,7 +487,7 @@ def groebner_basis_buchberger(I, prec, py_integral): # Main loop of Buchberger algorithm # Loop invariant: - # the S-polynomials of pairs of elements in rgb + # the S-polynomials of pairs of elements in rgb # all reduce to zero modulo (rgb,S) while S: sig_check() @@ -599,7 +599,7 @@ cdef Jpair(p1, p2): t2 = t // sv2 su1 = t1*s1 if s2 is None: - return su1, t1*v1 + return su1, t1*v1 su2 = t2*s2 if su1 > su2: return su1, t1*v1 @@ -773,7 +773,7 @@ def print_pair(p, verbose): sage: s = v.leading_term() sage: p = (s,v) - When ``verbose`` is less than 4, only the leading term of + When ``verbose`` is less than 4, only the leading term of the series is printed:: sage: print_pair(p, 0) @@ -924,7 +924,7 @@ def groebner_basis_pote(I, prec, verbose=0): print("| skip: sygyzy criterium; signature = %s" % syzygy) continue - # We check if (s,v) is covered by + # We check if (s,v) is covered by # the current strong Grobner basis cover = None for S, V in sgb: @@ -1210,7 +1210,7 @@ def groebner_basis_vapote(I, prec, verbose=0, interrupt_red_with_val=False, inte print("| skip: sygyzy criterium; signature = %s" % syzygy) continue - # We check if (s,v) is covered by + # We check if (s,v) is covered by # the current strong Grobner basis cover = None for S, V in sgb: diff --git a/src/sage/rings/tests.py b/src/sage/rings/tests.py index c6f1a9ecbbf..56cb05ba256 100644 --- a/src/sage/rings/tests.py +++ b/src/sage/rings/tests.py @@ -93,8 +93,7 @@ def integer_mod_ring(): sage: R.cardinality() <= 50000 True """ - from sage.rings.integer_ring import ZZ - from sage.rings.finite_rings.integer_mod_ring import IntegerModRing + from sage.all import ZZ, IntegerModRing n = ZZ.random_element(x=2, y=50000) return IntegerModRing(n) @@ -110,8 +109,7 @@ def padic_field(): sage: sage.rings.tests.padic_field() ...-adic Field with capped relative precision ... """ - from sage.rings.integer_ring import ZZ - from sage.rings.padics.factory import Qp + from sage.all import ZZ, Qp prec = ZZ.random_element(x=10, y=100) p = ZZ.random_element(x=2, y=10**4 - 30).next_prime() return Qp(p, prec) @@ -127,8 +125,7 @@ def quadratic_number_field(): sage: K = sage.rings.tests.quadratic_number_field(); K Number Field in a with defining polynomial x^2 ... with a = ... """ - from sage.rings.integer_ring import ZZ - from sage.rings.number_field.number_field import QuadraticField + from sage.all import ZZ, QuadraticField while True: d = ZZ.random_element(x=-10**5, y=10**5) if not d.is_square(): @@ -147,8 +144,7 @@ def absolute_number_field(maxdeg=10): sage: K.degree() <= 10 True """ - from sage.rings.integer_ring import ZZ - from sage.rings.number_field.number_field import NumberField + from sage.all import ZZ, NumberField R = ZZ['x'] while True: f = R.random_element(degree=ZZ.random_element(x=1, y=maxdeg), @@ -235,8 +231,7 @@ def rings0(): sage: type(sage.rings.tests.rings0()) <... 'list'> """ - from sage.rings.integer_ring import IntegerRing - from sage.rings.rational_field import RationalField + from sage.all import IntegerRing, RationalField v = [(IntegerRing, 'ring of integers'), (RationalField, 'field of rational numbers'), (integer_mod_ring, 'integers modulo n for n at most 50000'), @@ -275,10 +270,8 @@ def rings1(): """ v = rings0() X = random_rings(level=0) - from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing - from sage.rings.power_series_ring import PowerSeriesRing - from sage.rings.polynomial.laurent_polynomial_ring import LaurentPolynomialRing - from sage.rings.integer_ring import ZZ + from sage.all import (PolynomialRing, PowerSeriesRing, + LaurentPolynomialRing, ZZ) v = [(lambda: PolynomialRing(next(X), names='x'), 'univariate polynomial ring over level 0 ring'), (lambda: PowerSeriesRing(next(X), names='x'), @@ -455,8 +448,7 @@ def test_karatsuba_multiplication(base_ring, maxdeg1, maxdeg2, sage: sage.rings.tests.test_karatsuba_multiplication(ZZ, 10000, 10000, ref_mul=lambda f,g: f*g, base_ring_random_elt_args=[100000]) """ - from sage.misc.prandom import randint - from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing + from sage.all import randint, PolynomialRing threshold = randint(0, min(maxdeg1, maxdeg2)) R = PolynomialRing(base_ring, 'x') if verbose: diff --git a/src/sage/rings/valuation/valuation_space.py b/src/sage/rings/valuation/valuation_space.py index ffb13d82917..ed142b15485 100644 --- a/src/sage/rings/valuation/valuation_space.py +++ b/src/sage/rings/valuation/valuation_space.py @@ -115,7 +115,7 @@ def __init__(self, domain): from .value_group import DiscreteValuationCodomain # A valuation is a map from an additive semigroup to an additive semigroup, however, it # does not preserve that structure. It is therefore only a morphism in the category of sets. - from sage.categories.sets_cat import Sets + from sage.categories.all import Sets UniqueRepresentation.__init__(self) Homset.__init__(self, domain, DiscreteValuationCodomain(), category=Sets()) @@ -343,7 +343,7 @@ def is_negative_pseudo_valuation(self): False """ - from sage.categories.fields import Fields + from sage.categories.all import Fields if self.is_discrete_valuation(): return False elif self.domain() in Fields(): @@ -1175,7 +1175,7 @@ def _test_shift(self, **options): y = self.shift(x, s) if s >= 0: tester.assertGreaterEqual(self(y),self(x)) - from sage.categories.fields import Fields + from sage.categories.all import Fields if self.domain().is_exact() and self.domain() in Fields(): # the shift here sometimes fails if elements implement # __floordiv__ incorrectly, see #23971 diff --git a/src/sage/rings/valuation/value_group.py b/src/sage/rings/valuation/value_group.py index 159bb675664..f7265ef52d7 100644 --- a/src/sage/rings/valuation/value_group.py +++ b/src/sage/rings/valuation/value_group.py @@ -486,7 +486,7 @@ def __init__(self, generators): True """ - from sage.categories.additive_magmas import AdditiveMagmas + from sage.categories.all import AdditiveMagmas self._generators = generators category = AdditiveMagmas().AdditiveAssociative().AdditiveUnital() diff --git a/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py b/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py index 68194f600c2..fe80879bc15 100644 --- a/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py +++ b/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py @@ -3145,7 +3145,7 @@ def _composition_impl(left, right): return NotImplemented -def compute_isogeny_stark(E1, E2, ell): +def compute_isogeny_starks(E1, E2, ell): r""" Return the kernel polynomial of an isogeny of degree ``ell`` from ``E1`` to ``E2``. @@ -3170,7 +3170,7 @@ def compute_isogeny_stark(E1, E2, ell): ALGORITHM: - This function uses Stark's algorithm as presented in Section 6.2 + This function uses Starks' algorithm as presented in Section 6.2 of [BMSS2006]_. .. NOTE:: @@ -3181,14 +3181,14 @@ def compute_isogeny_stark(E1, E2, ell): EXAMPLES:: - sage: from sage.schemes.elliptic_curves.ell_curve_isogeny import compute_isogeny_stark, compute_sequence_of_maps + sage: from sage.schemes.elliptic_curves.ell_curve_isogeny import compute_isogeny_starks, compute_sequence_of_maps sage: E = EllipticCurve(GF(97), [1,0,1,1,0]) sage: R. = GF(97)[]; f = x^5 + 27*x^4 + 61*x^3 + 58*x^2 + 28*x + 21 sage: phi = EllipticCurveIsogeny(E, f) sage: E2 = phi.codomain() sage: (isom1, isom2, E1pr, E2pr, ker_poly) = compute_sequence_of_maps(E, E2, 11) - sage: compute_isogeny_stark(E1pr, E2pr, 11) + sage: compute_isogeny_starks(E1pr, E2pr, 11) x^10 + 37*x^9 + 53*x^8 + 66*x^7 + 66*x^6 + 17*x^5 + 57*x^4 + 6*x^3 + 89*x^2 + 53*x + 8 sage: E = EllipticCurve(GF(37), [0,0,0,1,8]) @@ -3196,7 +3196,7 @@ def compute_isogeny_stark(E1, E2, ell): sage: f = (x + 14) * (x + 30) sage: phi = EllipticCurveIsogeny(E, f) sage: E2 = phi.codomain() - sage: compute_isogeny_stark(E, E2, 5) + sage: compute_isogeny_starks(E, E2, 5) x^4 + 14*x^3 + x^2 + 34*x + 21 sage: f**2 x^4 + 14*x^3 + x^2 + 34*x + 21 @@ -3206,7 +3206,7 @@ def compute_isogeny_stark(E1, E2, ell): sage: f = x sage: phi = EllipticCurveIsogeny(E, f) sage: E2 = phi.codomain() - sage: compute_isogeny_stark(E, E2, 2) + sage: compute_isogeny_starks(E, E2, 2) x """ K = E1.base_field() @@ -3252,9 +3252,6 @@ def compute_isogeny_stark(E1, E2, ell): qn /= qn.leading_coefficient() return qn -from sage.misc.superseded import deprecated_function_alias -compute_isogeny_starks = deprecated_function_alias(34871, compute_isogeny_stark) - def split_kernel_polynomial(poly): r""" Obsolete internal helper function formerly used by @@ -3295,7 +3292,7 @@ def split_kernel_polynomial(poly): from sage.misc.misc_c import prod return prod([p for p,e in poly.squarefree_decomposition()]) -def compute_isogeny_kernel_polynomial(E1, E2, ell, algorithm="stark"): +def compute_isogeny_kernel_polynomial(E1, E2, ell, algorithm="starks"): r""" Return the kernel polynomial of an isogeny of degree ``ell`` from ``E1`` to ``E2``. @@ -3308,7 +3305,7 @@ def compute_isogeny_kernel_polynomial(E1, E2, ell, algorithm="stark"): - ``ell`` -- the degree of an isogeny from ``E1`` to ``E2`` - - ``algorithm`` -- currently only ``"stark"`` (default) is implemented + - ``algorithm`` -- currently only ``"starks"`` (default) is implemented OUTPUT: @@ -3350,8 +3347,8 @@ def compute_isogeny_kernel_polynomial(E1, E2, ell, algorithm="stark"): sage: f = (x + 10) * (x + 12) * (x + 16) sage: phi = EllipticCurveIsogeny(E, f) sage: E2 = phi.codomain() - sage: from sage.schemes.elliptic_curves.ell_curve_isogeny import compute_isogeny_stark - sage: ker_poly = compute_isogeny_stark(E, E2, 7); ker_poly + sage: from sage.schemes.elliptic_curves.ell_curve_isogeny import compute_isogeny_starks + sage: ker_poly = compute_isogeny_starks(E, E2, 7); ker_poly x^6 + 2*x^5 + 20*x^4 + 11*x^3 + 36*x^2 + 35*x + 16 sage: ker_poly.factor() (x + 10)^2 * (x + 12)^2 * (x + 16)^2 @@ -3360,13 +3357,9 @@ def compute_isogeny_kernel_polynomial(E1, E2, ell, algorithm="stark"): sage: poly.factor() (x + 10) * (x + 12) * (x + 16) """ - if algorithm == 'starks': - from sage.misc.superseded import deprecation - deprecation(34871, 'The "starks" algorithm is being renamed to "stark".') - algorithm = 'stark' - if algorithm != "stark": - raise NotImplementedError(f'unknown algorithm {algorithm}') - return compute_isogeny_stark(E1, E2, ell).radical() + if algorithm != "starks": + raise NotImplementedError + return compute_isogeny_starks(E1, E2, ell).radical() def compute_intermediate_curves(E1, E2): r""" diff --git a/src/sage/schemes/toric/sheaf/klyachko.py b/src/sage/schemes/toric/sheaf/klyachko.py index 77fae4b7545..b1304a16913 100644 --- a/src/sage/schemes/toric/sheaf/klyachko.py +++ b/src/sage/schemes/toric/sheaf/klyachko.py @@ -26,7 +26,7 @@ (0, 0, 18, 16, 1) sage: Gtilde = G_sum.random_deformation() sage: V = Gtilde.wedge(2) * K # long time - sage: V.cohomology(dim=True, weight=(0,0,0,0)) # long time # random failure (see #32773) + sage: V.cohomology(dim=True, weight=(0,0,0,0)) # long time (0, 0, 3, 0, 0) REFERENCES: @@ -948,7 +948,7 @@ def random_deformation(self, epsilon=None): sage: V.cohomology(dim=True, weight=(0,)) (1, 0) sage: Vtilde = V.random_deformation() - sage: Vtilde.cohomology(dim=True, weight=(0,)) # random failure (see #32773) + sage: Vtilde.cohomology(dim=True, weight=(0,)) (1, 0) """ filt = self._filt.random_deformation(epsilon) diff --git a/src/sage/sets/disjoint_set.pyx b/src/sage/sets/disjoint_set.pyx index eb6b04f4b9c..aaa12438f15 100644 --- a/src/sage/sets/disjoint_set.pyx +++ b/src/sage/sets/disjoint_set.pyx @@ -237,7 +237,7 @@ cdef class DisjointSet_class(SageObject): sage: e == d True """ - from sage.sets.set import Set + from sage.sets.all import Set s = Set(map(Set, self.root_to_elements_dict().values())) try: t = Set(map(Set, other.root_to_elements_dict().values())) diff --git a/src/sage/sets/primes.py b/src/sage/sets/primes.py index 96558ba9215..1c36c3a2563 100644 --- a/src/sage/sets/primes.py +++ b/src/sage/sets/primes.py @@ -17,7 +17,7 @@ from sage.rings.integer_ring import ZZ from .set import Set_generic from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets -from sage.arith.misc import nth_prime +from sage.arith.all import nth_prime from sage.structure.unique_representation import UniqueRepresentation diff --git a/src/sage/structure/element.pyx b/src/sage/structure/element.pyx index 78fe97f1507..e9430f0b086 100644 --- a/src/sage/structure/element.pyx +++ b/src/sage/structure/element.pyx @@ -2704,10 +2704,10 @@ cdef class RingElement(ModuleElement): with Singular 4:: sage: K. = ZZ[] - sage: (x^123456)^654321 + sage: (x^12345)^54321 Traceback (most recent call last): ... - OverflowError: exponent overflow (...) + OverflowError: exponent overflow (670592745) """ return arith_generic_power(self, n) diff --git a/src/sage/symbolic/relation.py b/src/sage/symbolic/relation.py index b8896a94be9..e9dbc0fea30 100644 --- a/src/sage/symbolic/relation.py +++ b/src/sage/symbolic/relation.py @@ -935,7 +935,8 @@ def solve(f, *args, **kwds): sage: f = (sin(x) - 8*cos(x)*sin(x))*(sin(x)^2 + cos(x)) - (2*cos(x)*sin(x) - sin(x))*(-2*sin(x)^2 + 2*cos(x)^2 - cos(x)) sage: solve(f, x, algorithm='giac') - ...[-2*arctan(sqrt(2)), 0, 2*arctan(sqrt(2)), pi] + ... + [-2*arctan(sqrt(2)), 0, 2*arctan(sqrt(2)), pi] sage: x, y = SR.var('x,y') sage: solve([x+y-4,x*y-3],[x,y],algorithm='giac') @@ -1439,15 +1440,19 @@ def _giac_solver(f, x, solution_dict=False): EXAMPLES:: sage: solve([(2/3)^x-2], [x], algorithm='giac') - ...[[-log(2)/(log(3) - log(2))]] + ... + [[-log(2)/(log(3) - log(2))]] sage: solve([(2/3)^x-2], [x], algorithm='giac', solution_dict=True) - ...[{x: -log(2)/(log(3) - log(2))}] + ... + [{x: -log(2)/(log(3) - log(2))}] sage: f = (sin(x) - 8*cos(x)*sin(x))*(sin(x)^2 + cos(x)) - (2*cos(x)*sin(x) - sin(x))*(-2*sin(x)^2 + 2*cos(x)^2 - cos(x)) sage: solve(f, x, algorithm='giac') - ...[-2*arctan(sqrt(2)), 0, 2*arctan(sqrt(2)), pi] + ... + [-2*arctan(sqrt(2)), 0, 2*arctan(sqrt(2)), pi] sage: solve(f, x, algorithm='giac', solution_dict=True) - ...[{x: -2*arctan(sqrt(2))}, {x: 0}, {x: 2*arctan(sqrt(2))}, {x: pi}] + ... + [{x: -2*arctan(sqrt(2))}, {x: 0}, {x: 2*arctan(sqrt(2))}, {x: pi}] sage: x, y = SR.var('x,y') sage: solve([x+y-7,x*y-10],[x,y],algorithm='giac') diff --git a/src/sage/tests/startup.py b/src/sage/tests/startup.py index 70629908446..debc9e6c37e 100644 --- a/src/sage/tests/startup.py +++ b/src/sage/tests/startup.py @@ -6,8 +6,7 @@ not work. Instead, we test this by starting a new Python process:: sage: from sage.tests.cmdline import test_executable - sage: environment = "sage.all" - sage: cmd = f"from {environment} import *\nprint('IPython' in sys.modules)\n" + sage: cmd = "from sage.all import *\nprint('IPython' in sys.modules)\n" sage: print(test_executable(["sage", "--python"], cmd)[0]) # long time False diff --git a/src/sage/version.py b/src/sage/version.py index 5c277db17d7..ff7a5bbbf73 100644 --- a/src/sage/version.py +++ b/src/sage/version.py @@ -1,5 +1,5 @@ # Sage version information for Python scripts # This file is auto-generated by the sage-update-version script, do not edit! -version = '10.0.beta0' -date = '2023-02-12' -banner = 'SageMath version 10.0.beta0, Release Date: 2023-02-12' +version = '9.8.rc1' +date = '2023-02-05' +banner = 'SageMath version 9.8.rc1, Release Date: 2023-02-05' diff --git a/tox.ini b/tox.ini index 1d17c7d175f..5eb3e79633b 100644 --- a/tox.ini +++ b/tox.ini @@ -272,6 +272,7 @@ setenv = fedora-31: BASE_TAG=31 fedora-32: BASE_TAG=32 fedora-33: BASE_TAG=33 + fedora-33: IGNORE_MISSING_SYSTEM_PACKAGES=no fedora-34: BASE_TAG=34 fedora-34: IGNORE_MISSING_SYSTEM_PACKAGES=no fedora-35: BASE_TAG=35