diff --git a/.devcontainer/build_apple_silicon/devcontainer.json b/.devcontainer/build_apple_silicon/devcontainer.json new file mode 100644 index 0000000000000..386e9b7d883e5 --- /dev/null +++ b/.devcontainer/build_apple_silicon/devcontainer.json @@ -0,0 +1,61 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at: +// https://github.com/microsoft/vscode-dev-containers/tree/v0.236.0/containers/docker-existing-dockerfile +{ + "name": "Ivy Apple Silicon Development Environment (build)", + + "build": { + "dockerfile": "../../docker/DockerfileAppleSilicon", + "context": "../..", + "args": { + "pycon": ["3.10"] + } + }, + + "customizations": { + "vscode": { + "extensions": [ + "ms-python.python" + ], + "settings": { + "python.defaultInterpreterPath": "/opt/miniconda/envs/multienv/bin/python3" + } + } + }, + + "postCreateCommand": { + "post_create": "bash .devcontainer/post_create_commands.sh", + "bashrc": "echo \"alias python=python3\" >> ~/.bashrc" + }, + + // Use 'forwardPorts' to make a list of ports inside the container available locally. + // "forwardPorts": [], + + // Uncomment the next line to run commands after the container is created - for example installing curl. + + // Uncomment when using a ptrace-based debugger like C++, Go, and Rust + // "runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined" ], + + // Uncomment to use the Docker CLI from inside the container. See https://aka.ms/vscode-remote/samples/docker-from-docker. + // "mounts": [ "source=/var/run/docker.sock,target=/var/run/docker.sock,type=bind" ], + + // Uncomment to connect as a non-root user if you've added one. See https://aka.ms/vscode-remote/containers/non-root. + // "remoteUser": "vscode", + "features": { + "ghcr.io/devcontainers/features/common-utils:2": { + "installZsh": true, + "configureZshAsDefaultShell": true, + "installOhMyZsh": true, + "upgradePackages": false + }, + "ghcr.io/devcontainers/features/docker-outside-of-docker:1": { + "moby": true, + "installDockerBuildx": true, + "version": "20.10", + "dockerDashComposeVersion": "v2" + }, + "ghcr.io/devcontainers/features/github-cli:1": { + "installDirectlyFromGitHubRelease": true, + "version": "latest" + } + } +} diff --git a/.devcontainer/build_gpu/devcontainer.json b/.devcontainer/build_gpu/devcontainer.json index 399fc8cf8d1b5..b74cb231c4a78 100644 --- a/.devcontainer/build_gpu/devcontainer.json +++ b/.devcontainer/build_gpu/devcontainer.json @@ -2,11 +2,11 @@ "name": "Ivy GPU Development Environment (build)", "build": { - "dockerfile": "../../docker/DockerfileGPUMultiCuda", + "dockerfile": "../../docker/DockerfileGPU", "context": "../..", "args": { - "IMAGE_NAME": "unifyai/multicuda", - "IMAGE_TAG": "base_and_requirements" + "IMAGE_NAME": "unifyai/ivy", + "IMAGE_TAG": "latest-gpu" } }, diff --git a/.devcontainer/image_gpu/devcontainer.json b/.devcontainer/image_gpu/devcontainer.json index 6824d7ca80037..ca899e132de7b 100644 --- a/.devcontainer/image_gpu/devcontainer.json +++ b/.devcontainer/image_gpu/devcontainer.json @@ -1,7 +1,7 @@ { "name": "Ivy GPU Development Environment (image)", - "image": "unifyai/multicuda:base_and_requirements", + "image": "unifyai/ivy:latest-gpu", "customizations": { "vscode": { "extensions": [ diff --git a/.github/ISSUE_TEMPLATE/sub-task.md b/.github/ISSUE_TEMPLATE/sub-task.md index 34374422b3f2d..21c1855bc4283 100644 --- a/.github/ISSUE_TEMPLATE/sub-task.md +++ b/.github/ISSUE_TEMPLATE/sub-task.md @@ -2,7 +2,7 @@ name: ๐Ÿฐ Sub-Task about: Reserve a sub-task from a ToDo list issue title: "" -labels: Sub Task, hacktoberfest +labels: Sub Task assignees: '' --- diff --git a/.github/workflows/array-api-det-coverage.yml b/.github/workflows/array-api-det-coverage.yml index 11c5d88b7fc08..254fb28e548a0 100644 --- a/.github/workflows/array-api-det-coverage.yml +++ b/.github/workflows/array-api-det-coverage.yml @@ -9,6 +9,10 @@ permissions: jobs: determine_coverage: runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + branch: [ 1, 2, 3, 4 ] steps: - name: Checkout Ivy ๐Ÿ›Ž uses: actions/checkout@v2 @@ -22,7 +26,7 @@ jobs: run: | pip install pydriller tqdm cd ivy - python scripts/determine_tests/array_api_det_coverage.py + python scripts/determine_tests/array_api_det_coverage.py ${{ matrix.branch }} cd .. mkdir tests cp ivy/tests.pbz2 tests/ @@ -37,4 +41,4 @@ jobs: destination-repository-name: 'Mapping' user-email: ivy.branch@lets-unify.ai commit-message: Update Array API Tests Mapping - target-branch: main + target-branch: main${{ matrix.branch }} diff --git a/.github/workflows/array-api-intelligent-tests-pr.yml b/.github/workflows/array-api-intelligent-tests-pr.yml index 5345703c5e6e1..e67478445676e 100644 --- a/.github/workflows/array-api-intelligent-tests-pr.yml +++ b/.github/workflows/array-api-intelligent-tests-pr.yml @@ -1,37 +1,84 @@ name: array-api-intelligent-tests-pr on: pull_request: - types: [ labeled, opened, synchronize, reopened, review_requested ] + types: [opened, synchronize, reopened, review_requested ] permissions: actions: read + jobs: + display_test_results: + if: ${{ always() }} + runs-on: ubuntu-latest + needs: + - run_tests + + steps: + - name: Download all test results + uses: actions/download-artifact@v3 + + - name: Combined Test Results + run: | + find . -name "test_results_*.txt" -exec cat {} + > combined_test_results.txt + echo "Test results summary:" + cat combined_test_results.txt + + - name: New Failures Introduced + run: | + find . -name "new_failures_*.txt" -exec cat {} + > combined_failures.txt + if [ -s combined_failures.txt ] + then + echo "This PR introduces the following new failing tests:" + cat combined_failures.txt + else + echo "This PR does not introduce any new test failures! Yippee!" + fi + run_tests: runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + branch: [ 1, 2, 3, 4 ] + steps: - name: Checkout Ivy ๐Ÿ›Ž - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: path: ivy persist-credentials: false submodules: "recursive" fetch-depth: 100 - - name: Determine Tests + - name: Get Job URL + uses: Tiryoh/gha-jobid-action@v0 + id: jobs + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + job_name: ${{ github.job }} + + - name: Determine and Run Tests run: | - git clone -b main https://github.com/unifyai/Mapping.git --depth 1 + git clone -b main${{ matrix.branch }} https://github.com/unifyai/Mapping.git --depth 1 pip install pydriller cp Mapping/tests.pbz2 ivy/ cd ivy python scripts/determine_tests/array_api_determine_tests.py + python scripts/run_tests/array_api_run_tests_pr.py new_failures_${{ matrix.branch }}.txt | tee test_results_${{ matrix.branch }}.txt + cd .. continue-on-error: true - - name: Run Tests - id: tests - run: | - cd ivy - python scripts/run_tests/array_api_run_tests_pr.py - continue-on-error: true + - name: Upload test results + uses: actions/upload-artifact@v3 + with: + name: test_results_${{ matrix.branch }} + path: ivy/test_results_${{ matrix.branch }}.txt + + - name: Upload New Failures + uses: actions/upload-artifact@v3 + with: + name: new_failures_${{ matrix.branch }} + path: ivy/new_failures_${{ matrix.branch }}.txt - name: Check on failures if: steps.tests.outcome != 'success' diff --git a/.github/workflows/array-api-intelligent-tests.yml b/.github/workflows/array-api-intelligent-tests.yml index 7cb92eab1a105..576bbe9475e16 100644 --- a/.github/workflows/array-api-intelligent-tests.yml +++ b/.github/workflows/array-api-intelligent-tests.yml @@ -7,11 +7,32 @@ on: permissions: actions: read jobs: + display_test_results: + if: ${{ always() }} + runs-on: ubuntu-latest + needs: + - run_tests + + steps: + - name: Download all test results + uses: actions/download-artifact@v3 + + - name: Combined Test Results + run: | + find . -name "test_results_*.txt" -exec cat {} + > combined_test_results.txt + echo "Test results summary:" + cat combined_test_results.txt + run_tests: runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + branch: [ 1, 2, 3, 4 ] + steps: - name: Checkout Ivy ๐Ÿ›Ž - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: path: ivy persist-credentials: false @@ -29,26 +50,33 @@ jobs: env: SSH_DEPLOY_KEY: ${{ secrets.SSH_DEPLOY_KEY }} run: | - source ./ivy/scripts/shell/clone_mapping.sh main + source ./ivy/scripts/shell/clone_mapping.sh main${{ matrix.branch }} pip install pydriller pymongo cp Mapping/tests.pbz2 ivy/ cd ivy - python scripts/determine_tests/array_api_determine_tests.py + python scripts/determine_tests/array_api_determine_tests.py ${{ matrix.branch }} cd .. cp ivy/tests.pbz2 Mapping/ cd Mapping git add . git commit -m "Update Mapping" - git push origin main + git push origin main${{ matrix.branch }} continue-on-error: true - name: Run Tests id: tests run: | cd ivy - python scripts/run_tests/array_api_run_tests.py ${{ secrets.REDIS_CONNECTION_URL }} ${{ secrets.REDIS_PASSWORD }} ${{ secrets.MONGODB_PASSWORD }} ${{ github.run_id }} ${{ steps.jobs.outputs.html_url }} + set -o pipefail + python scripts/run_tests/array_api_run_tests.py ${{ secrets.REDIS_CONNECTION_URL }} ${{ secrets.REDIS_PASSWORD }} ${{ secrets.MONGODB_PASSWORD }} ${{ github.run_id }} ${{ steps.jobs.outputs.html_url }} | tee test_results_${{ matrix.branch }}.txt continue-on-error: true + - name: Upload test results + uses: actions/upload-artifact@v3 + with: + name: test_results_${{ matrix.branch }} + path: ivy/test_results_${{ matrix.branch }}.txt + - name: Check on failures if: steps.tests.outcome != 'success' run: exit 1 diff --git a/.github/workflows/binaries.yml b/.github/workflows/binaries.yml index 51dd639e700d0..9520707a2bd18 100644 --- a/.github/workflows/binaries.yml +++ b/.github/workflows/binaries.yml @@ -6,11 +6,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout ๐Ÿ›Ž๏ธBinaries - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: repository: unifyai/binaries + token: ${{ secrets.IVY_BRANCH_TOKEN }} path: binaries - persist-credentials: false - name: Add Tag to Binaries run: | diff --git a/.github/workflows/dockerfile-gpu-push.yml b/.github/workflows/dockerfile-gpu-push.yml new file mode 100644 index 0000000000000..df978d2ee95a9 --- /dev/null +++ b/.github/workflows/dockerfile-gpu-push.yml @@ -0,0 +1,26 @@ +name: GPU Dockerfile Push + +on: + schedule: + - cron: '0 0 * * *' + workflow_dispatch: + +jobs: + + build: + runs-on: ubuntu-latest-4-cores + + steps: + - name: Checkout ๐Ÿ›Ž Ivy + uses: actions/checkout@v3 + + - name: Login to Docker Hub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Build and push GPU image + run: | + docker build --progress=plain --no-cache -t unifyai/ivy:latest-gpu -f docker/DockerfileGPU . + docker push unifyai/ivy:latest-gpu diff --git a/.github/workflows/dockerfile-image.yml b/.github/workflows/dockerfile-image.yml index 9c5be23f40475..fd19c2b90ab7c 100644 --- a/.github/workflows/dockerfile-image.yml +++ b/.github/workflows/dockerfile-image.yml @@ -4,14 +4,14 @@ on: push: branches: [ "main" ] pull_request: - types: [labeled, review_requested] + types: [review_requested] branches: [ "main" ] jobs: build: if: ${{(github.event_name == 'push') || contains(github.event.pull_request.labels.*.name, 'Exhaustive CI') || contains(github.event.pull_request.labels.*.name, 'Build Docker Files')}} - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 diff --git a/.github/workflows/dockerfile-multicuda-push.yml b/.github/workflows/dockerfile-multicuda-push.yml deleted file mode 100644 index 1ace6afdc4b36..0000000000000 --- a/.github/workflows/dockerfile-multicuda-push.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: Dockerfile MultiCUDA Push - -on: - schedule: - - cron: '0 0 * * *' - workflow_dispatch: - -jobs: - - build: - runs-on: ubuntu-latest-4-cores - - steps: - - name: Checkout ๐Ÿ›Ž Ivy - uses: actions/checkout@v3 - - - name: Login to Docker Hub - uses: docker/login-action@v2 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - - name: Build and push base image - run: | - docker build --progress=plain --no-cache -t unifyai/multicuda:base -f docker/DockerfileGPUMultiCuda-base . - docker push unifyai/multicuda:base - - - name: Build and push base_and_requirements image - run: | - docker build --progress=plain --no-cache -t unifyai/multicuda:base_and_requirements -f docker/DockerfileGPUMultiCuda . - docker push unifyai/multicuda:base_and_requirements diff --git a/.github/workflows/dockerfile-push.yml b/.github/workflows/dockerfile-push.yml index 06be15ea1e427..3a4e9959b6847 100644 --- a/.github/workflows/dockerfile-push.yml +++ b/.github/workflows/dockerfile-push.yml @@ -10,7 +10,7 @@ jobs: build: - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest steps: - diff --git a/.github/workflows/intelligent-tests-pr.yml b/.github/workflows/intelligent-tests-pr.yml index 9f3137fd4463c..91e08239a9d23 100644 --- a/.github/workflows/intelligent-tests-pr.yml +++ b/.github/workflows/intelligent-tests-pr.yml @@ -1,12 +1,11 @@ name: intelligent-tests-pr on: workflow_dispatch: - pull_request_target: - types: [labeled, opened, synchronize, reopened, review_requested] + pull_request: + types: [opened, synchronize, reopened, review_requested] permissions: actions: read - pull-requests: write jobs: display_test_results: @@ -19,51 +18,37 @@ jobs: - name: Download all test results uses: actions/download-artifact@v3 + - name: Checkout Ivy ๐Ÿ›Ž + uses: actions/checkout@v3 + with: + path: ivy + persist-credentials: false + submodules: "recursive" + fetch-depth: 1 + - name: Combined Test Results run: | find . -name "test_results_*.txt" -exec cat {} + > combined_test_results.txt echo "Test results summary:" cat combined_test_results.txt - - name: New Failures Introduced - id: ci_output + - name: Label Test Failures run: | - find . -name "new_failures_*.txt" -exec cat {} + > combined_failures.txt - if [ -s combined_failures.txt ] + find . -name "test_failures_*.txt" -exec cat {} + > ivy/combined_failures.txt + pip install pymongo + cd ivy + python3 scripts/run_tests/label_failures.py combined_failures.txt labeled_combined_failures.txt + + - name: Display Test Failures + run: | + cd ivy + if [ -s labeled_combined_failures.txt ] then - echo "This PR introduces the following new failing tests:" - cat combined_failures.txt - { - echo 'MESSAGE<> "$GITHUB_OUTPUT" + echo "The CI captured the following failing tests based on your changes:" + cat labeled_combined_failures.txt else - echo "MESSAGE=This pull request does not result in any additional test failures. Congratulations!" >> "$GITHUB_OUTPUT" + echo "No test failures found based on your changes!" fi - - name: Find Comment - uses: peter-evans/find-comment@v2 - id: fc - with: - issue-number: ${{ github.event.pull_request.number }} - comment-author: 'github-actions[bot]' - body-includes: - - - name: Create or update comment - uses: peter-evans/create-or-update-comment@v3 - with: - comment-id: ${{ steps.fc.outputs.comment-id }} - issue-number: ${{ github.event.pull_request.number }} - body: | - Thank you for this PR, here is the CI results: - - ------------- - ${{ steps.ci_output.outputs.MESSAGE}} - - - edit-mode: replace run_tests: runs-on: ubuntu-latest @@ -93,20 +78,34 @@ jobs: submodules: "recursive" fetch-depth: 100 + - name: Install ivy and fetch binaries + run: | + cd ivy + sudo pip3 install -e . + mkdir .ivy + touch .ivy/key.pem + echo -n ${{ secrets.USER_API_KEY }} > .ivy/key.pem + cd .. + + - name: Get Job URL + uses: Tiryoh/gha-jobid-action@v0 + id: jobs + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + job_name: ${{ github.job }} + - name: Determine and Run Tests id: tests run: | - git clone -b master${{ matrix.branch }} https://github.com/unifyai/Mapping.git --depth 200 + git clone -b master${{ matrix.branch }} https://github.com/unifyai/Mapping.git --depth 1 pip install pydriller GitPython python ivy/scripts/setup_tests/clone-mapping.py cp Mapping/tests.pbz2 ivy/ cd ivy - mkdir .ivy - touch .ivy/key.pem - echo -n ${{ secrets.USER_API_KEY }} > .ivy/key.pem python scripts/determine_tests/determine_tests.py ${{ matrix.branch }} pr set -o pipefail - python scripts/run_tests/run_tests_pr.py new_failures_${{ matrix.branch }}.txt | tee test_results_${{ matrix.branch }}.txt + python scripts/run_tests/run_tests_pr.py test_failures_${{ matrix.branch }}.txt | tee test_results_${{ matrix.branch }}.txt + cd .. continue-on-error: true - name: Upload test results @@ -118,8 +117,8 @@ jobs: - name: Upload New Failures uses: actions/upload-artifact@v3 with: - name: new_failures_${{ matrix.branch }} - path: ivy/new_failures_${{ matrix.branch }}.txt + name: test_failures_${{ matrix.branch }} + path: ivy/test_failures_${{ matrix.branch }}.txt - name: Check on failures if: steps.tests.outcome != 'success' diff --git a/.github/workflows/intelligent-tests.yml b/.github/workflows/intelligent-tests.yml index a9215fbbacf9b..23a6e2171d83f 100644 --- a/.github/workflows/intelligent-tests.yml +++ b/.github/workflows/intelligent-tests.yml @@ -24,7 +24,7 @@ jobs: cat combined_test_results.txt run_tests: - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest strategy: fail-fast: false matrix: @@ -54,7 +54,7 @@ jobs: - name: Install ivy and fetch binaries run: | cd ivy - pip3 install -e . + sudo pip3 install -e . mkdir .ivy touch .ivy/key.pem echo -n ${{ secrets.USER_API_KEY }} > .ivy/key.pem @@ -89,7 +89,7 @@ jobs: run: | cd ivy set -o pipefail - python scripts/run_tests/run_tests.py ${{ secrets.REDIS_CONNECTION_URL }} ${{ secrets.REDIS_PASSWORD }} ${{ secrets.MONGODB_PASSWORD }} 'false' 'false' ${{ github.run_id }} 'false' ${{ steps.jobs.outputs.html_url }} | tee test_results_${{ matrix.branch }}.txt + python scripts/run_tests/run_tests.py ${{ secrets.REDIS_CONNECTION_URL }} ${{ secrets.REDIS_PASSWORD }} ${{ secrets.MONGODB_PASSWORD }} 'false' 'false' ${{ github.run_id }} 'false' 'false' 'false' ${{ steps.jobs.outputs.html_url }} | tee test_results_${{ matrix.branch }}.txt continue-on-error: true - name: Upload test results diff --git a/.github/workflows/manual-tests.yml b/.github/workflows/manual-tests.yml index 819ff6cccc31e..6bb0b423712d1 100644 --- a/.github/workflows/manual-tests.yml +++ b/.github/workflows/manual-tests.yml @@ -17,6 +17,16 @@ on: default: false required: false + tracer: + description: 'Tracer Testing :' + default: false + required: false + + tracer_each: + description: 'Tracer Testing Each :' + default: false + required: false + permissions: actions: read @@ -40,7 +50,7 @@ jobs: - name: Install ivy and fetch binaries run: | cd ivy - pip3 install -e . + sudo pip3 install -e . mkdir .ivy touch .ivy/key.pem echo -n ${{ secrets.USER_API_KEY }} > .ivy/key.pem @@ -59,7 +69,7 @@ jobs: pip3 install pymongo cd ivy python3 scripts/setup_tests/setup_tests.py ${{ github.event.inputs.test }} - python3 scripts/run_tests/run_tests.py ${{ secrets.REDIS_CONNECTION_URL }} ${{ secrets.REDIS_PASSWORD }} ${{ secrets.MONGODB_PASSWORD }} 'false' ${{ github.event.inputs.gpu }} ${{ github.run_id }} 'false' ${{ steps.jobs.outputs.html_url }} + python3 scripts/run_tests/run_tests.py ${{ secrets.REDIS_CONNECTION_URL }} ${{ secrets.REDIS_PASSWORD }} ${{ secrets.MONGODB_PASSWORD }} 'false' ${{ github.event.inputs.gpu }} ${{ github.run_id }} 'false' ${{ github.event.inputs.tracer }} ${{ github.event.inputs.tracer_each }} ${{ steps.jobs.outputs.html_url }} continue-on-error: true - name: Check on failures @@ -81,7 +91,7 @@ jobs: - name: Install ivy and fetch binaries run: | cd ivy - pip3 install -e . + sudo pip3 install -e . mkdir .ivy touch .ivy/key.pem echo -n ${{ secrets.USER_API_KEY }} > .ivy/key.pem @@ -99,9 +109,9 @@ jobs: run: | pip3 install pymongo cd ivy - pip3 install -e . + sudo pip3 install -e . python scripts/setup_tests/setup_tests.py "${{ github.event.inputs.test }}" - python scripts/run_tests/run_tests.py ${{ secrets.REDIS_CONNECTION_URL }} ${{ secrets.REDIS_PASSWORD }} ${{ secrets.MONGODB_PASSWORD }} ${{ github.event.inputs.version}} 'false' ${{ github.run_id }} 'false' ${{ steps.jobs.outputs.html_url }} + python scripts/run_tests/run_tests.py ${{ secrets.REDIS_CONNECTION_URL }} ${{ secrets.REDIS_PASSWORD }} ${{ secrets.MONGODB_PASSWORD }} ${{ github.event.inputs.version}} 'false' ${{ github.run_id }} 'false' ${{ github.event.inputs.tracer }} ${{ github.event.inputs.tracer_each }} ${{ steps.jobs.outputs.html_url }} continue-on-error: true - name: Check on failures diff --git a/.github/workflows/pre-release.yml b/.github/workflows/pre-release.yml index 483440add140b..246f99d88207e 100644 --- a/.github/workflows/pre-release.yml +++ b/.github/workflows/pre-release.yml @@ -1,6 +1,16 @@ name: Pre-release Testing Workflow on: workflow_dispatch: + inputs: + tracer: + description: 'Tracer Testing :' + default: false + required: false + + tracer_each: + description: 'Tracer Testing Each :' + default: false + required: false permissions: actions: read @@ -27,17 +37,14 @@ jobs: run: | pip3 install pymongo cd ivy + sudo pip3 install -e . mkdir .ivy touch .ivy/key.pem echo -n ${{ secrets.USER_API_KEY }} > .ivy/key.pem - python scripts/setup_tests/setup_priority_tests.py ${{ secrets.MONGODB_PASSWORD }} + python scripts/setup_tests/setup_priority_tests.py + cd .. - name: Run CPU Tests run: | cd ivy - python scripts/run_tests/run_tests.py ${{ secrets.REDIS_CONNECTION_URL }} ${{ secrets.REDIS_PASSWORD }} ${{ secrets.MONGODB_PASSWORD }} 'false' 'false' ${{ github.run_id }} 'true' ${{ steps.jobs.outputs.html_url }} - - - name: Run GPU Tests - run: | - cd ivy - python scripts/run_tests/run_tests.py ${{ secrets.REDIS_CONNECTION_URL }} ${{ secrets.REDIS_PASSWORD }} ${{ secrets.MONGODB_PASSWORD }} 'false' 'true' ${{ github.run_id }} 'true' ${{ steps.jobs.outputs.html_url }} + python scripts/run_tests/run_tests.py ${{ secrets.REDIS_CONNECTION_URL }} ${{ secrets.REDIS_PASSWORD }} ${{ secrets.MONGODB_PASSWORD }} 'false' 'false' ${{ github.run_id }} 'true' ${{ github.event.inputs.tracer }} ${{ github.event.inputs.tracer_each }} ${{ steps.jobs.outputs.html_url }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f29e7b8bbf2c8..98f08e09360a6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,7 +12,7 @@ jobs: publish-binaries: name: Publish Binaries - uses: unifyai/workflows/.github/workflows/binaries.yml@main + uses: ./.github/workflows/binaries.yml secrets: inherit deploy: diff --git a/.github/workflows/run-all-tests.yml b/.github/workflows/run-all-tests.yml index 64153d06ffa31..7fb8304e0f52d 100644 --- a/.github/workflows/run-all-tests.yml +++ b/.github/workflows/run-all-tests.yml @@ -45,7 +45,7 @@ jobs: - name: Install ivy and fetch binaries run: | cd ivy - pip3 install -e . + sudo pip3 install -e . mkdir .ivy touch .ivy/key.pem echo -n ${{ secrets.USER_API_KEY }} > .ivy/key.pem @@ -64,7 +64,7 @@ jobs: cd ivy python scripts/setup_tests/filter_tests.py ${{ matrix.branch }} set -o pipefail - python scripts/run_tests/run_tests.py ${{ secrets.REDIS_CONNECTION_URL }} ${{ secrets.REDIS_PASSWORD }} ${{ secrets.MONGODB_PASSWORD }} 'false' 'false' ${{ github.run_id }} 'false' ${{ steps.jobs.outputs.html_url }} | tee test_results_${{ matrix.branch }}.txt + python scripts/run_tests/run_tests.py ${{ secrets.REDIS_CONNECTION_URL }} ${{ secrets.REDIS_PASSWORD }} ${{ secrets.MONGODB_PASSWORD }} 'false' 'false' ${{ github.run_id }} 'false' 'false' 'false' ${{ steps.jobs.outputs.html_url }} | tee test_results_${{ matrix.branch }}.txt continue-on-error: true - name: Upload test results diff --git a/.github/workflows/run-failing-tests.yml b/.github/workflows/run-failing-tests.yml new file mode 100644 index 0000000000000..cbd95ca62b532 --- /dev/null +++ b/.github/workflows/run-failing-tests.yml @@ -0,0 +1,76 @@ +name: Run Failing Tests +on: + workflow_dispatch: + inputs: + priority: + description: 'Priority:' + default: true + required: false + +permissions: + actions: read +jobs: + display_test_results: + if: ${{ always() }} + runs-on: ubuntu-latest + needs: + - run_tests + + steps: + - name: Download all test results + uses: actions/download-artifact@v3 + + - name: Combined Test Results + run: | + find . -name "test_results_*.txt" -exec cat {} + > combined_test_results.txt + echo "Test results summary:" + cat combined_test_results.txt + + run_tests: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + branch: [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, + 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, + 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, + 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, + 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, + 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, + 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, + 121, 122, 123, 124, 125, 126, 127, 128 ] + steps: + - name: Checkout Ivy ๐Ÿ›Ž + uses: actions/checkout@v3 + with: + path: ivy + persist-credentials: false + submodules: "recursive" + fetch-depth: 1 + + - name: Get Job URL + uses: Tiryoh/gha-jobid-action@v0 + id: jobs + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + job_name: ${{ github.job }} + + - name: Setup Tests + run: | + pip3 install pymongo + cd ivy + mkdir .ivy + touch .ivy/key.pem + echo -n ${{ secrets.USER_API_KEY }} > .ivy/key.pem + python scripts/setup_tests/setup_failing_tests.py ${{ github.event.inputs.priority }} ${{ matrix.branch }} + + - name: Run Tests + run: | + cd ivy + python scripts/run_tests/run_tests.py ${{ secrets.REDIS_CONNECTION_URL }} ${{ secrets.REDIS_PASSWORD }} ${{ secrets.MONGODB_PASSWORD }} 'false' 'false' ${{ github.run_id }} 'false' 'false' 'false' ${{ steps.jobs.outputs.html_url }} + continue-on-error: true diff --git a/.github/workflows/synchronize-db.yml b/.github/workflows/synchronize-db.yml deleted file mode 100644 index f5632e4f6ded0..0000000000000 --- a/.github/workflows/synchronize-db.yml +++ /dev/null @@ -1,22 +0,0 @@ -name: Synchronize DB -on: - workflow_dispatch: -permissions: - actions: read -jobs: - synchronize-db: - runs-on: ubuntu-latest - steps: - - name: Checkout Ivy ๐Ÿ›Ž - uses: actions/checkout@v3 - with: - path: ivy - persist-credentials: false - submodules: "recursive" - fetch-depth: 1 - - - name: Synchronize DB - run: | - pip install pymongo - cd ivy - python scripts/setup_tests/synchronize_db.py ${{ secrets.MONGODB_PASSWORD }} diff --git a/.github/workflows/test-array-api.yml b/.github/workflows/test-array-api.yml deleted file mode 100644 index 7db65e56a0379..0000000000000 --- a/.github/workflows/test-array-api.yml +++ /dev/null @@ -1,80 +0,0 @@ -name: test-array-api -on: - workflow_dispatch: - -jobs: - run-array-api-tests: - if: contains(github.event.pull_request.labels.*.name, 'Array API') - strategy: - matrix: - backends: [numpy, torch, jax, tensorflow] - submodules: [array_object, constants, creation_functions, data_type_functions, - has_names, linalg, manipulation_functions, operators_and_elementwise_functions, - searching_functions, set_functions, signatures, sorting_functions, - special_cases, statistical_functions, utility_functions] - continue-on-error: true - runs-on: ubuntu-latest - steps: - - name: Checkout ๐Ÿ›Ž๏ธIvy - uses: actions/checkout@v2 - with: - path: ivy - persist-credentials: false - submodules: 'recursive' - - - name: Download artifact - if: github.event_name == 'pull_request' - uses: dawidd6/action-download-artifact@v2 - with: - workflow: test-array-api.yml - workflow_conclusion: completed - name: 'hypothesis_${{ matrix.backends }}_${{ matrix.submodules }}_zip' - path: | - ivy/.hypothesis/ - continue-on-error: true - - - name: Unzip Hypothesis Examples - if: github.event_name == 'pull_request' - id: unzip - run: | - cd ivy/.hypothesis - unzip examples.zip - rm examples.zip - continue-on-error: true - - - name: Create Hypothesis Directory - if: steps.unzip.outcome != 'success' && github.event_name == 'pull_request' - run: | - cd ivy - mkdir -p .hypothesis - cd .hypothesis - mkdir -p examples - continue-on-error: true - - - name: Run Array API Tests - id: tests - run: | - cd ivy - ./scripts/shell/test_array_api.sh ${{matrix.backends}} test_${{matrix.submodules}} ${{ secrets.REDIS_CONNECTION_URL }} ${{ secrets.REDIS_PASSWORD}} - continue-on-error: true - - - name: Zip Hypothesis Examples - if: github.event_name == 'pull_request' - run: | - cd ivy/.hypothesis - zip -r examples.zip examples - continue-on-error: true - - - name: Upload hypothesis - if: github.event_name == 'pull_request' - uses: actions/upload-artifact@v3 - with: - name: 'hypothesis_${{ matrix.backends }}_${{ matrix.submodules }}_zip' - path: | - ivy/.hypothesis/examples.zip - continue-on-error: true - - - - name: Check on failures - if: steps.tests.outcome != 'success' - run: exit 1 diff --git a/.github/workflows/test-docstrings.yml b/.github/workflows/test-docstrings.yml index c8b7f6bf519f1..77be6f4e6c969 100644 --- a/.github/workflows/test-docstrings.yml +++ b/.github/workflows/test-docstrings.yml @@ -2,7 +2,7 @@ name: test-docstrings on: push: pull_request: - types: [labeled, opened, synchronize, reopened, review_requested] + types: [opened, synchronize, reopened, review_requested] workflow_dispatch: jobs: run-docstring-tests: diff --git a/.github/workflows/test-frontend-jax.yml b/.github/workflows/test-frontend-jax.yml deleted file mode 100644 index 7724876d33b7e..0000000000000 --- a/.github/workflows/test-frontend-jax.yml +++ /dev/null @@ -1,82 +0,0 @@ -name: test-frontend-jax -on: - workflow_dispatch: -# pull_request: -# types: [labeled, opened, synchronize, reopened, review_requested] - -jobs: - run-nightly-tests: - if: github.event_name == 'push' || contains(github.event.pull_request.labels.*.name, 'Exhaustive CI') || contains(github.event.pull_request.labels.*.name, 'JAX Frontend') - runs-on: ubuntu-latest - steps: - - name: Checkout ๐Ÿ›Ž๏ธIvy - uses: actions/checkout@v2 - with: - path: ivy - persist-credentials: false - submodules: "recursive" - - - name: Install ivy and fetch binaries - run: | - cd ivy - pip3 install -e . - mkdir .ivy - touch .ivy/key.pem - echo -n ${{ secrets.USER_API_KEY }} > .ivy/key.pem - cd .. - - - name: Download artifact - if: github.event_name == 'pull_request' - uses: dawidd6/action-download-artifact@v2 - with: - workflow: test-frontend-jax.yml - workflow_conclusion: completed - name: hypothesis_frontend_jax_zip - path: | - ivy/.hypothesis/ - continue-on-error: true - - - name: Unzip Hypothesis Examples - if: github.event_name == 'pull_request' - id: unzip - run: | - cd ivy/.hypothesis - unzip examples.zip - rm examples.zip - continue-on-error: true - - - name: Create Hypothesis Directory - if: steps.unzip.outcome != 'success' && github.event_name == 'pull_request' - run: | - cd ivy - mkdir -p .hypothesis - cd .hypothesis - mkdir -p examples - continue-on-error: true - - - name: Run Frontend Tests - id: tests - run: | - cd ivy - docker run --rm -v `pwd`:/ivy -v `pwd`/.hypothesis:/.hypothesis unifyai/ivy:latest python3 -m pytest --backend all ivy_tests/test_ivy/test_frontends/test_jax - continue-on-error: true - - - name: Zip Hypothesis Examples - if: github.event_name == 'pull_request' - run: | - cd ivy/.hypothesis - zip -r examples.zip examples - continue-on-error: true - - - name: Upload hypothesis - if: github.event_name == 'pull_request' - uses: actions/upload-artifact@v3 - with: - name: hypothesis_frontend_jax_zip - path: | - ivy/.hypothesis/examples.zip - continue-on-error: true - - - name: Check on failures - if: steps.tests.outcome != 'success' - run: exit 1 diff --git a/.github/workflows/test-frontend-numpy.yml b/.github/workflows/test-frontend-numpy.yml deleted file mode 100644 index d99000c459b95..0000000000000 --- a/.github/workflows/test-frontend-numpy.yml +++ /dev/null @@ -1,82 +0,0 @@ -name: test-frontend-numpy -on: - workflow_dispatch: -# pull_request: -# types: [labeled, opened, synchronize, reopened, review_requested] - -jobs: - run-nightly-tests: - if: contains(github.event.pull_request.labels.*.name, 'Exhaustive CI') ||contains(github.event.pull_request.labels.*.name, 'NumPy Frontend') - runs-on: ubuntu-latest - steps: - - name: Checkout ๐Ÿ›Ž๏ธIvy - uses: actions/checkout@v2 - with: - path: ivy - persist-credentials: false - submodules: "recursive" - - - name: Install ivy and fetch binaries - run: | - cd ivy - pip3 install -e . - mkdir .ivy - touch .ivy/key.pem - echo -n ${{ secrets.USER_API_KEY }} > .ivy/key.pem - cd .. - - - name: Download artifact - if: github.event_name == 'pull_request' - uses: dawidd6/action-download-artifact@v2 - with: - workflow: test-frontend-numpy.yml - workflow_conclusion: completed - name: hypothesis_frontend_numpy_zip - path: | - ivy/.hypothesis/ - continue-on-error: true - - - name: Unzip Hypothesis Examples - if: github.event_name == 'pull_request' - id: unzip - run: | - cd ivy/.hypothesis - unzip examples.zip - rm examples.zip - continue-on-error: true - - - name: Create Hypothesis Directory - if: steps.unzip.outcome != 'success' && github.event_name == 'pull_request' - run: | - cd ivy - mkdir -p .hypothesis - cd .hypothesis - mkdir -p examples - continue-on-error: true - - - name: Run Frontend Tests - id: tests - run: | - cd ivy - docker run --rm -v `pwd`:/ivy -v `pwd`/.hypothesis:/.hypothesis unifyai/ivy:latest python3 -m pytest --backend all ivy_tests/test_ivy/test_frontends/test_numpy - continue-on-error: true - - - name: Zip Hypothesis Examples - if: github.event_name == 'pull_request' - run: | - cd ivy/.hypothesis - zip -r examples.zip examples - continue-on-error: true - - - name: Upload hypothesis - if: github.event_name == 'pull_request' - uses: actions/upload-artifact@v3 - with: - name: hypothesis_frontend_numpy_zip - path: | - ivy/.hypothesis/examples.zip - continue-on-error: true - - - name: Check on failures - if: steps.tests.outcome != 'success' - run: exit 1 diff --git a/.github/workflows/test-frontend-tensorflow.yml b/.github/workflows/test-frontend-tensorflow.yml deleted file mode 100644 index f5a03dcef7e1a..0000000000000 --- a/.github/workflows/test-frontend-tensorflow.yml +++ /dev/null @@ -1,82 +0,0 @@ -name: test-frontend-tensorflow -on: - workflow_dispatch: -# pull_request: -# types: [labeled, opened, synchronize, reopened, review_requested] - -jobs: - run-nightly-tests: - if: contains(github.event.pull_request.labels.*.name, 'Exhaustive CI') || contains(github.event.pull_request.labels.*.name, 'TensorFlow Frontend') - runs-on: ubuntu-latest - steps: - - name: Checkout ๐Ÿ›Ž๏ธIvy - uses: actions/checkout@v2 - with: - path: ivy - persist-credentials: false - submodules: "recursive" - - - name: Install ivy and fetch binaries - run: | - cd ivy - pip3 install -e . - mkdir .ivy - touch .ivy/key.pem - echo -n ${{ secrets.USER_API_KEY }} > .ivy/key.pem - cd .. - - - name: Download artifact - if: github.event_name == 'pull_request' - uses: dawidd6/action-download-artifact@v2 - with: - workflow: test-frontend-tensorflow.yml - workflow_conclusion: completed - name: hypothesis_frontend_tensorflow_zip - path: | - ivy/.hypothesis/ - continue-on-error: true - - - name: Unzip Hypothesis Examples - if: github.event_name == 'pull_request' - id: unzip - run: | - cd ivy/.hypothesis - unzip examples.zip - rm examples.zip - continue-on-error: true - - - name: Create Hypothesis Directory - if: steps.unzip.outcome != 'success' && github.event_name == 'pull_request' - run: | - cd ivy - mkdir -p .hypothesis - cd .hypothesis - mkdir -p examples - continue-on-error: true - - - name: Run Frontend Tests - id: tests - run: | - cd ivy - docker run --rm -v `pwd`:/ivy -v `pwd`/.hypothesis:/.hypothesis unifyai/ivy:latest python3 -m pytest --backend all ivy_tests/test_ivy/test_frontends/test_tensorflow - continue-on-error: true - - - name: Zip Hypothesis Examples - if: github.event_name == 'pull_request' - run: | - cd ivy/.hypothesis - zip -r examples.zip examples - continue-on-error: true - - - name: Upload hypothesis - if: github.event_name == 'pull_request' - uses: actions/upload-artifact@v3 - with: - name: hypothesis_frontend_tensorflow_zip - path: | - ivy/.hypothesis/examples.zip - continue-on-error: true - - - name: Check on failures - if: steps.tests.outcome != 'success' - run: exit 1 diff --git a/.github/workflows/test-frontend-torch.yml b/.github/workflows/test-frontend-torch.yml deleted file mode 100644 index 732958fd972a4..0000000000000 --- a/.github/workflows/test-frontend-torch.yml +++ /dev/null @@ -1,82 +0,0 @@ -name: test-frontend-torch -on: - workflow_dispatch: -# pull_request: -# types: [labeled, opened, synchronize, reopened, review_requested] - -jobs: - run-nightly-tests: - if: contains(github.event.pull_request.labels.*.name, 'Exhaustive CI') ||contains(github.event.pull_request.labels.*.name, 'PyTorch Frontend') - runs-on: ubuntu-latest - steps: - - name: Checkout ๐Ÿ›Ž๏ธIvy - uses: actions/checkout@v2 - with: - path: ivy - persist-credentials: false - submodules: "recursive" - - - name: Install ivy and fetch binaries - run: | - cd ivy - pip3 install -e . - mkdir .ivy - touch .ivy/key.pem - echo -n ${{ secrets.USER_API_KEY }} > .ivy/key.pem - cd .. - - - name: Download artifact - if: github.event_name == 'pull_request' - uses: dawidd6/action-download-artifact@v2 - with: - workflow: test-frontend-torch.yml - workflow_conclusion: completed - name: hypothesis_frontend_torch_zip - path: | - ivy/.hypothesis/ - continue-on-error: true - - - name: Unzip Hypothesis Examples - if: github.event_name == 'pull_request' - id: unzip - run: | - cd ivy/.hypothesis - unzip examples.zip - rm examples.zip - continue-on-error: true - - - name: Create Hypothesis Directory - if: steps.unzip.outcome != 'success' && github.event_name == 'pull_request' - run: | - cd ivy - mkdir -p .hypothesis - cd .hypothesis - mkdir -p examples - continue-on-error: true - - - name: Run Frontend Tests - id: tests - run: | - cd ivy - docker run --rm -v `pwd`:/ivy -v `pwd`/.hypothesis:/.hypothesis unifyai/ivy:latest python3 -m pytest --backend=all ivy_tests/test_ivy/test_frontends/test_torch - continue-on-error: true - - - name: Zip Hypothesis Examples - if: github.event_name == 'pull_request' - run: | - cd ivy/.hypothesis - zip -r examples.zip examples - continue-on-error: true - - - name: Upload hypothesis - if: github.event_name == 'pull_request' - uses: actions/upload-artifact@v3 - with: - name: hypothesis_frontend_torch_zip - path: | - ivy/.hypothesis/examples.zip - continue-on-error: true - - - name: Check on failures - if: steps.tests.outcome != 'success' - run: exit 1 diff --git a/.github/workflows/test-ivy-core.yml b/.github/workflows/test-ivy-core.yml deleted file mode 100644 index f87a42a0abb43..0000000000000 --- a/.github/workflows/test-ivy-core.yml +++ /dev/null @@ -1,131 +0,0 @@ -name: test-core-ivy -on: - workflow_dispatch: -# push: -# pull_request: -# types: [labeled, opened, synchronize, reopened, review_requested] - -permissions: - actions: read -jobs: - run-nightly-tests: - if: ${{(github.event_name == 'push') || contains(github.event.pull_request.labels.*.name, 'Exhaustive CI') || contains(github.event.pull_request.labels.*.name, 'Ivy Functional API')}} - strategy: - matrix: - backends: [ numpy, torch, jax, tensorflow ] - submodules: [ creation, device, dtype, elementwise, general, gradients, linalg, - manipulation, meta, nest, random, searching, set, sorting, statistical, - utility ] - continue-on-error: true - runs-on: ubuntu-latest - steps: - - name: Checkout ๐Ÿ›Ž๏ธIvy - uses: actions/checkout@v2 - with: - path: ivy - persist-credentials: false - submodules: "recursive" - fetch-depth: 2 - - - name: Install ivy and fetch binaries - run: | - cd ivy - pip3 install -e . - mkdir .ivy - touch .ivy/key.pem - echo -n ${{ secrets.USER_API_KEY }} > .ivy/key.pem - cd .. - - - name: Check Files Changed - if: ${{(github.event_name == 'push') || !contains(github.event.pull_request.labels.*.name, 'Exhaustive CI') }} - shell: pwsh - id: check_file_changed - run: | - cd ivy - $diff = git diff --name-only HEAD^ HEAD - $SourceDiff = $diff | Where-Object { ` - $_ -match 'ivy_tests/test_ivy/test_functional/test_core/test_${{ matrix.submodules }}.py' ` - -or $_ -match 'ivy_tests/test_ivy/helpers.py' ` - -or $_ -match 'ivy/array/${{ matrix.submodules }}.py' ` - -or $_ -match 'ivy/container/${{ matrix.submodules }}.py' ` - -or $_ -match 'ivy/functional/backends/${{ matrix.backends }}/${{ matrix.submodules }}.py' ` - -or $_ -match 'ivy/functional/ivy/${{ matrix.submodules }}.py' ` - } - $HasDiff = $SourceDiff.Length -gt 0 - Write-Host "::set-output name=changed::$HasDiff" - - - name: Download artifact - uses: dawidd6/action-download-artifact@v2 - if: (steps.check_file_changed.outputs.changed == 'True' || steps.check_file_changed.conclusion == 'skipped') && github.event_name == 'pull_request' - with: - github_token: ${{secrets.GITHUB_TOKEN}} - workflow: test-ivy-core.yml - workflow_conclusion: "" - search_artifacts: true - name: hypothesis_${{ matrix.backends }}_test_${{ matrix.submodules }}_zip - path: | - ivy/.hypothesis/ - continue-on-error: true - - - name: Unzip Hypothesis Examples - id: unzip - if: (steps.check_file_changed.outputs.changed == 'True' || steps.check_file_changed.conclusion == 'skipped') && github.event_name == 'pull_request' - run: | - cd ivy/.hypothesis - unzip examples.zip - rm examples.zip - continue-on-error: true - - - name: Create Hypothesis Directory - if: (steps.check_file_changed.outputs.changed == 'True' || steps.check_file_changed.conclusion == 'skipped') && steps.unzip.outcome != 'success' && github.event_name == 'pull_request' - run: | - cd ivy - mkdir -p .hypothesis - cd .hypothesis - mkdir -p examples - continue-on-error: true - - - name: Run Functional-Core Tests - id: tests - if: steps.check_file_changed.outputs.changed == 'True' || steps.check_file_changed.conclusion == 'skipped' - run: | - cd ivy - ./scripts/shell/test_ivy_core.sh ${{ matrix.backends }} test_${{ matrix.submodules }} ${{ secrets.REDIS_CONNECTION_URL }} ${{ secrets.REDIS_PASSWORD}} - continue-on-error: true - - - name: Zip Hypothesis Examples - if: (steps.check_file_changed.outputs.changed == 'True' || steps.check_file_changed.conclusion == 'skipped') && github.event_name == 'pull_request' - run: | - cd ivy/.hypothesis - zip -r examples.zip examples - continue-on-error: true - - - name: Upload hypothesis - uses: actions/upload-artifact@v3 - if: (steps.check_file_changed.outputs.changed == 'True' || steps.check_file_changed.conclusion == 'skipped') && github.event_name == 'pull_request' - with: - name: hypothesis_${{ matrix.backends }}_test_${{ matrix.submodules }}_zip - path: | - ivy/.hypothesis/examples.zip - continue-on-error: true - - - name: Install Mongo Python Client - if: (steps.check_file_changed.outputs.changed == 'True' && github.event_name == 'push' && github.ref == 'refs/heads/main') - uses: BSFishy/pip-action@v1 - with: - packages: | - pymongo[srv] - - - name: Update Database - if: (steps.check_file_changed.outputs.changed == 'True' && github.event_name == 'push' && github.ref == 'refs/heads/main') - env: - MONGODB_PASSWORD: ${{ secrets.MONGODB_PASSWORD }} - run: | - cd ivy/automation_tools/dashboard_automation/ - python3 update_db.py "$MONGODB_PASSWORD" ${{ github.workflow }} "${{ matrix.backends }}-${{ matrix.submodules }}" ${{ steps.tests.outcome }} ${{ github.run_id }} - continue-on-error: true - - - - name: Check on failures - if: (steps.check_file_changed.outputs.changed == 'True' || steps.check_file_changed.conclusion == 'skipped') && steps.tests.outcome != 'success' - run: exit 1 diff --git a/.github/workflows/test-ivy-cron-gpu.yml b/.github/workflows/test-ivy-cron-gpu.yml index fd1c3b592a06b..f4209e776b030 100644 --- a/.github/workflows/test-ivy-cron-gpu.yml +++ b/.github/workflows/test-ivy-cron-gpu.yml @@ -1,30 +1,62 @@ name: test-ivy-cron-gpu on: workflow_dispatch: - schedule: - - cron: '25 * * * *' + # schedule: + # - cron: '25 * * * *' permissions: actions: read +concurrency: + group: ${{ github.workflow }} + cancel-in-progress: false jobs: + start-vm: + runs-on: ubuntu-latest + if: always() # Run this job always, regardless of the status of run-test-basics + steps: + - name: Checkout Demos๐Ÿ›Ž + uses: actions/checkout@v4 + with: + repository: unifyai/demos + path: demos + persist-credentials: false + submodules: "recursive" + fetch-depth: 1 + + - name: Install clients for GCP/Mongo + run: | + pip3 install pymongo google-api-python-client paramiko + + - name: Start GPU VM + run: | + cd demos/tests/auth + mkdir -p ~/.ssh + touch ~/.ssh/id_rsa + echo -n "${{ secrets.GPU_SSH_KEY }}" > ~/.ssh/id_rsa + chmod +x ~/.ssh/id_rsa + python3 db_auth.py ${{ secrets.GPU_DB_ENDPOINT }} ${{ secrets.GPU_DB_OBJ_ID }} + python3 vm_auth.py ${{ secrets.GPU_SSH_USERNAME }} ${{ secrets.GPU_SSH_PASSPHRASE }} "false" "ivy-repo-gpu-testing" + run-gpu-tests: + needs: start-vm runs-on: self-hosted steps: - name: Clean Repository run: sudo rm -fr $GITHUB_WORKSPACE && mkdir $GITHUB_WORKSPACE - - name: Checkout Ivy ๐Ÿ›Ž + - name: Checkout ๐Ÿ›Ž๏ธIvy uses: actions/checkout@v2 with: path: ivy persist-credentials: false submodules: "recursive" - set-safe-directory: false + fetch-depth: 2 - name: Install ivy and fetch binaries run: | cd ivy - pip3 install -e . + export TAG="cp310-cp310-manylinux_2_17_x86_64" + sudo pip3 install -e . mkdir .ivy touch .ivy/key.pem echo -n ${{ secrets.USER_API_KEY }} > .ivy/key.pem @@ -42,10 +74,29 @@ jobs: run: | pip3 install pymongo cd ivy - python3 scripts/setup_tests/cron_tests.py ${{ github.run_number }} - python3 scripts/run_tests/run_tests.py ${{ secrets.REDIS_CONNECTION_URL }} ${{ secrets.REDIS_PASSWORD }} ${{ secrets.MONGODB_PASSWORD }} 'false' 'true' ${{ github.run_id }} 'false' ${{ steps.jobs.outputs.html_url }} - continue-on-error: true + python3 scripts/setup_tests/cron_tests.py ${{ github.run_number }} true false + python3 scripts/run_tests/run_tests.py ${{ secrets.REDIS_CONNECTION_URL }} ${{ secrets.REDIS_PASSWORD }} ${{ secrets.MONGODB_PASSWORD }} 'false' 'true' ${{ github.run_id }} 'false' 'false' 'false' ${{ steps.jobs.outputs.html_url }} + + stop-vm: + needs: run-gpu-tests + runs-on: ubuntu-latest + if: always() # Run this job always, regardless of the status of run-test + steps: + - name: Checkout Demos๐Ÿ›Ž + uses: actions/checkout@v4 + with: + repository: unifyai/demos + path: demos + persist-credentials: false + submodules: "recursive" + fetch-depth: 1 + + - name: Install clients for GCP/Mongo + run: | + pip3 install pymongo google-api-python-client paramiko - - name: Check on failures - if: steps.tests.outcome != 'success' - run: exit 1 + - name: Stop GPU VM + run: | + cd demos/tests/auth + python3 db_auth.py ${{ secrets.GPU_DB_ENDPOINT }} ${{ secrets.GPU_DB_OBJ_ID }} + python3 vm_auth.py ${{ secrets.GPU_SSH_USERNAME }} ${{ secrets.GPU_SSH_PASSPHRASE }} "true" "ivy-repo-gpu-testing" diff --git a/.github/workflows/test-ivy-cron-multi-version.yml b/.github/workflows/test-ivy-cron-multi-version.yml index fd36dd585d175..d4aaee594b6e6 100644 --- a/.github/workflows/test-ivy-cron-multi-version.yml +++ b/.github/workflows/test-ivy-cron-multi-version.yml @@ -19,7 +19,7 @@ jobs: - name: Install ivy and fetch binaries run: | cd ivy - pip3 install -e . + sudo pip3 install -e . mkdir .ivy touch .ivy/key.pem echo -n ${{ secrets.USER_API_KEY }} > .ivy/key.pem @@ -38,7 +38,7 @@ jobs: cd ivy pip3 install pymongo python scripts/setup_tests/cron_tests_multi_version.py ${{ github.run_number }} - python scripts/run_tests/run_tests.py ${{ secrets.REDIS_CONNECTION_URL }} ${{ secrets.REDIS_PASSWORD }} ${{ secrets.MONGODB_PASSWORD }} 'true' 'false' ${{ github.run_id }} 'false' ${{ steps.jobs.outputs.html_url }} + python scripts/run_tests/run_tests.py ${{ secrets.REDIS_CONNECTION_URL }} ${{ secrets.REDIS_PASSWORD }} ${{ secrets.MONGODB_PASSWORD }} 'true' 'false' ${{ github.run_id }} 'false' 'false' 'false' ${{ steps.jobs.outputs.html_url }} continue-on-error: true - name: Check on failures diff --git a/.github/workflows/test-ivy-cron.yml b/.github/workflows/test-ivy-cron.yml index c5ca96ab9dbfb..c79ac18644b5b 100644 --- a/.github/workflows/test-ivy-cron.yml +++ b/.github/workflows/test-ivy-cron.yml @@ -19,7 +19,7 @@ jobs: - name: Install ivy and fetch binaries run: | cd ivy - pip3 install -e . + sudo pip3 install -e . mkdir .ivy touch .ivy/key.pem echo -n ${{ secrets.USER_API_KEY }} > .ivy/key.pem @@ -37,8 +37,8 @@ jobs: run: | cd ivy pip3 install pymongo - python scripts/setup_tests/cron_tests.py ${{ github.run_number }} - python scripts/run_tests/run_tests.py ${{ secrets.REDIS_CONNECTION_URL }} ${{ secrets.REDIS_PASSWORD }} ${{ secrets.MONGODB_PASSWORD }} 'false' 'false' ${{ github.run_id }} 'false' ${{ steps.jobs.outputs.html_url }} + python scripts/setup_tests/cron_tests.py ${{ github.run_number }} false false + python scripts/run_tests/run_tests.py ${{ secrets.REDIS_CONNECTION_URL }} ${{ secrets.REDIS_PASSWORD }} ${{ secrets.MONGODB_PASSWORD }} 'false' 'false' ${{ github.run_id }} 'false' 'false' 'false' ${{ steps.jobs.outputs.html_url }} continue-on-error: true - name: Check on failures diff --git a/.github/workflows/test-ivy-experimental-core.yml b/.github/workflows/test-ivy-experimental-core.yml deleted file mode 100644 index 8f8117978b2f5..0000000000000 --- a/.github/workflows/test-ivy-experimental-core.yml +++ /dev/null @@ -1,122 +0,0 @@ -name: test-experimental-core-ivy -on: - workflow_dispatch: -# push: -# pull_request: -# types: [labeled, opened, synchronize, reopened, review_requested] -permissions: - actions: read -jobs: - run-nightly-tests: - if: ${{(github.event_name == 'push') || contains(github.event.pull_request.labels.*.name, 'Exhaustive CI') || contains(github.event.pull_request.labels.*.name, 'Ivy API Experimental')}} - strategy: - matrix: - backends: [ numpy, torch, jax, tensorflow ] - submodules: [ creation, device, dtype, elementwise, general, gradients, linalg, - manipulation, meta, nest, random, searching, set, sorting, sparse_array, - statistical, utility ] - continue-on-error: true - runs-on: ubuntu-latest - steps: - - name: Checkout ๐Ÿ›Ž๏ธIvy - uses: actions/checkout@v2 - with: - path: ivy - persist-credentials: false - submodules: "recursive" - fetch-depth: 2 - - - name: Install ivy and fetch binaries - run: | - cd ivy - pip3 install -e . - mkdir .ivy - touch .ivy/key.pem - echo -n ${{ secrets.USER_API_KEY }} > .ivy/key.pem - cd .. - - - name: Check Files Changed - shell: pwsh - id: check_file_changed - run: | - cd ivy - $diff = git diff --name-only HEAD^ HEAD - $SourceDiff = $diff | Where-Object { ` - $_ -match 'ivy_tests/test_ivy/test_functional/test_experimental/test_core/test_${{ matrix.submodules }}.py' ` - } - $HasDiff = $SourceDiff.Length -gt 0 - Write-Host "::set-output name=changed::$HasDiff" - - name: Download artifact - uses: dawidd6/action-download-artifact@v2 - if: github.event_name == 'pull_request' && steps.check_file_changed.outputs.changed == 'True' - with: - github_token: ${{secrets.GITHUB_TOKEN}} - workflow: test-ivy-experimental.yml - workflow_conclusion: "" - search_artifacts: true - name: hypothesis_${{ matrix.backends }}_test_experimental_zip - path: | - ivy/.hypothesis/ - continue-on-error: true - - - name: Unzip Hypothesis Examples - id: unzip - if: github.event_name == 'pull_request' - run: | - cd ivy/.hypothesis - unzip examples.zip - rm examples.zip - continue-on-error: true - - - name: Create Hypothesis Directory - if: github.event_name == 'pull_request' && steps.check_file_changed.outputs.changed == 'True' - run: | - cd ivy - mkdir -p .hypothesis - cd .hypothesis - mkdir -p examples - continue-on-error: true - - - name: Run Experimental Test - if: steps.check_file_changed.outputs.changed == 'True' - id: tests - run: | - cd ivy - ./scripts/shell/test_experimental_core.sh ${{ matrix.backends }} test_${{ matrix.submodules }} ${{ secrets.REDIS_CONNECTION_URL }} ${{ secrets.REDIS_PASSWORD}} - continue-on-error: true - - - name: Zip Hypothesis Examples - if: github.event_name == 'pull_request' && steps.check_file_changed.outputs.changed == 'True' - run: | - cd ivy/.hypothesis - zip -r examples.zip examples - continue-on-error: true - - - name: Upload hypothesis - uses: actions/upload-artifact@v3 - if: github.event_name == 'pull_request' - with: - name: hypothesis_${{ matrix.backends }}_test_${{ matrix.submodules }}_zip - path: | - ivy/.hypothesis/examples.zip - continue-on-error: true - - - name: Install Mongo Python Client - if: github.event_name == 'push' && github.ref == 'refs/heads/main' && steps.check_file_changed.outputs.changed == 'True' - uses: BSFishy/pip-action@v1 - with: - packages: | - pymongo[srv] - - name: Update Database - if: github.event_name == 'push' && github.ref == 'refs/heads/main' && steps.check_file_changed.outputs.changed == 'True' - env: - MONGODB_PASSWORD: ${{ secrets.MONGODB_PASSWORD }} - run: | - cd ivy/automation_tools/dashboard_automation/ - python3 update_db.py "$MONGODB_PASSWORD" ${{ github.workflow }} "${{ matrix.backends }}-${{ matrix.submodules }}" ${{ steps.tests.outcome }} ${{ github.run_id }} - continue-on-error: true - - - - name: Check on failures - if: (steps.check_file_changed.outputs.changed == 'True' || steps.check_file_changed.conclusion == 'skipped') && steps.tests.outcome != 'success' - run: exit 1 diff --git a/.github/workflows/test-ivy-experimental-nn.yml b/.github/workflows/test-ivy-experimental-nn.yml deleted file mode 100644 index ef5ebe1c294b1..0000000000000 --- a/.github/workflows/test-ivy-experimental-nn.yml +++ /dev/null @@ -1,120 +0,0 @@ -name: test-experimental-nn-ivy -on: - workflow_dispatch: -# push: -# pull_request: -# types: [labeled, opened, synchronize, reopened, review_requested] -permissions: - actions: read -jobs: - run-nightly-tests: - if: ${{(github.event_name == 'push') || contains(github.event.pull_request.labels.*.name, 'Exhaustive CI') || contains(github.event.pull_request.labels.*.name, 'Ivy API Experimental')}} - strategy: - matrix: - backends: [ numpy, torch, jax, tensorflow ] - submodules: [ activations, layers, losses, norms ] - continue-on-error: true - runs-on: ubuntu-latest - steps: - - name: Checkout ๐Ÿ›Ž๏ธIvy - uses: actions/checkout@v2 - with: - path: ivy - persist-credentials: false - submodules: "recursive" - fetch-depth: 2 - - - name: Install ivy and fetch binaries - run: | - cd ivy - pip3 install -e . - mkdir .ivy - touch .ivy/key.pem - echo -n ${{ secrets.USER_API_KEY }} > .ivy/key.pem - cd .. - - - name: Check Files Changed - shell: pwsh - id: check_file_changed - run: | - cd ivy - $diff = git diff --name-only HEAD^ HEAD - $SourceDiff = $diff | Where-Object { ` - $_ -match 'ivy_tests/test_ivy/test_functional/test_experimental/test_nn/test_${{ matrix.submodules }}.py' ` - } - $HasDiff = $SourceDiff.Length -gt 0 - Write-Host "::set-output name=changed::$HasDiff" - - name: Download artifact - uses: dawidd6/action-download-artifact@v2 - if: github.event_name == 'pull_request' && steps.check_file_changed.outputs.changed == 'True' - with: - github_token: ${{secrets.GITHUB_TOKEN}} - workflow: test-ivy-experimental.yml - workflow_conclusion: "" - search_artifacts: true - name: hypothesis_${{ matrix.backends }}_test_experimental_zip - path: | - ivy/.hypothesis/ - continue-on-error: true - - - name: Unzip Hypothesis Examples - id: unzip - if: github.event_name == 'pull_request' && steps.check_file_changed.outputs.changed == 'True' - run: | - cd ivy/.hypothesis - unzip examples.zip - rm examples.zip - continue-on-error: true - - - name: Create Hypothesis Directory - if: github.event_name == 'pull_request' && steps.check_file_changed.outputs.changed == 'True' - run: | - cd ivy - mkdir -p .hypothesis - cd .hypothesis - mkdir -p examples - continue-on-error: true - - - name: Run Experimental Test - if: steps.check_file_changed.outputs.changed == 'True' - id: tests - run: | - cd ivy - ./scripts/shell/test_experimental_nn.sh ${{ matrix.backends }} test_${{ matrix.submodules }} ${{ secrets.REDIS_CONNECTION_URL }} ${{ secrets.REDIS_PASSWORD}} - continue-on-error: true - - - name: Zip Hypothesis Examples - if: github.event_name == 'pull_request' && steps.check_file_changed.outputs.changed == 'True' - run: | - cd ivy/.hypothesis - zip -r examples.zip examples - continue-on-error: true - - - name: Upload hypothesis - uses: actions/upload-artifact@v3 - if: github.event_name == 'pull_request' && steps.check_file_changed.outputs.changed == 'True' - with: - name: hypothesis_${{ matrix.backends }}_test_${{ matrix.submodules }}_zip - path: | - ivy/.hypothesis/examples.zip - continue-on-error: true - - - name: Install Mongo Python Client - if: github.event_name == 'push' && github.ref == 'refs/heads/main' && steps.check_file_changed.outputs.changed == 'True' - uses: BSFishy/pip-action@v1 - with: - packages: | - pymongo[srv] - - name: Update Database - if: github.event_name == 'push' && github.ref == 'refs/heads/main' && steps.check_file_changed.outputs.changed == 'True' - env: - MONGODB_PASSWORD: ${{ secrets.MONGODB_PASSWORD }} - run: | - cd ivy/automation_tools/dashboard_automation/ - python3 update_db.py "$MONGODB_PASSWORD" ${{ github.workflow }} "${{ matrix.backends }}-${{ matrix.submodules }}" ${{ steps.tests.outcome }} ${{ github.run_id }} - continue-on-error: true - - - - name: Check on failures - if: (steps.check_file_changed.outputs.changed == 'True' || steps.check_file_changed.conclusion == 'skipped') && steps.tests.outcome != 'success' - run: exit 1 diff --git a/.github/workflows/test-ivy-nn.yml b/.github/workflows/test-ivy-nn.yml deleted file mode 100644 index 9f213e1e013bd..0000000000000 --- a/.github/workflows/test-ivy-nn.yml +++ /dev/null @@ -1,128 +0,0 @@ -name: test-nn-ivy -on: - workflow_dispatch: -# push: -# pull_request: -# types: [labeled, opened, synchronize, reopened, review_requested] -permissions: - actions: read -jobs: - run-nightly-tests: - if: ${{(github.event_name == 'push') || contains(github.event.pull_request.labels.*.name, 'Exhaustive CI') || contains(github.event.pull_request.labels.*.name, 'Ivy Functional API')}} - strategy: - matrix: - backends: [ numpy, torch, jax, tensorflow ] - submodules: [ activations, layers, losses, norms ] - continue-on-error: true - runs-on: ubuntu-latest - steps: - - name: Checkout ๐Ÿ›Ž๏ธIvy - uses: actions/checkout@v2 - with: - path: ivy - persist-credentials: false - submodules: "recursive" - fetch-depth: 2 - - - name: Install ivy and fetch binaries - run: | - cd ivy - pip3 install -e . - mkdir .ivy - touch .ivy/key.pem - echo -n ${{ secrets.USER_API_KEY }} > .ivy/key.pem - cd .. - - - name: Check Files Changed - if: ${{ (github.event_name == 'push') || !contains(github.event.pull_request.labels.*.name, 'Exhaustive CI') }} - shell: pwsh - id: check_file_changed - run: | - cd ivy - $diff = git diff --name-only HEAD^ HEAD - $SourceDiff = $diff | Where-Object { ` - $_ -match 'ivy_tests/test_ivy/test_functional/test_nn/test_${{ matrix.submodules }}.py' ` - -or $_ -match 'ivy_tests/test_ivy/helpers.py' ` - -or $_ -match 'ivy/array/${{ matrix.submodules }}.py' ` - -or $_ -match 'ivy/container/${{ matrix.submodules }}.py' ` - -or $_ -match 'ivy/functional/backends/${{ matrix.backends }}/${{ matrix.submodules }}.py' ` - -or $_ -match 'ivy/functional/ivy/${{ matrix.submodules }}.py' ` - } - $HasDiff = $SourceDiff.Length -gt 0 - Write-Host "::set-output name=changed::$HasDiff" - - - name: Download artifact - uses: dawidd6/action-download-artifact@v2 - if: (steps.check_file_changed.outputs.changed == 'True' || steps.check_file_changed.conclusion == 'skipped') && github.event_name == 'pull_request' - with: - github_token: ${{secrets.GITHUB_TOKEN}} - workflow: test-ivy-nn.yml - workflow_conclusion: "" - search_artifacts: true - name: hypothesis_${{ matrix.backends }}_test_${{ matrix.submodules }}_zip - path: | - ivy/.hypothesis/ - continue-on-error: true - - - name: Unzip Hypothesis Examples - id: unzip - if: (steps.check_file_changed.outputs.changed == 'True' || steps.check_file_changed.conclusion == 'skipped') && github.event_name == 'pull_request' - run: | - cd ivy/.hypothesis - unzip examples.zip - rm examples.zip - continue-on-error: true - - - name: Create Hypothesis Directory - if: (steps.check_file_changed.outputs.changed == 'True' || steps.check_file_changed.conclusion == 'skipped') && steps.unzip.outcome != 'success' && github.event_name == 'pull_request' - run: | - cd ivy - mkdir -p .hypothesis - cd .hypothesis - mkdir -p examples - continue-on-error: true - - - name: Run Functional-NN Tests - id: tests - if: steps.check_file_changed.outputs.changed == 'True' || steps.check_file_changed.conclusion == 'skipped' - run: | - cd ivy - ./scripts/shell/test_ivy_nn.sh ${{ matrix.backends }} test_${{ matrix.submodules }} ${{ secrets.REDIS_CONNECTION_URL }} ${{ secrets.REDIS_PASSWORD}} - continue-on-error: true - - - name: Zip Hypothesis Examples - if: (steps.check_file_changed.outputs.changed == 'True' || steps.check_file_changed.conclusion == 'skipped') && github.event_name == 'pull_request' - run: | - cd ivy/.hypothesis - zip -r examples.zip examples - continue-on-error: true - - - name: Upload hypothesis - uses: actions/upload-artifact@v3 - if: (steps.check_file_changed.outputs.changed == 'True' || steps.check_file_changed.conclusion == 'skipped') && github.event_name == 'pull_request' - with: - name: hypothesis_${{ matrix.backends }}_test_${{ matrix.submodules }}_zip - path: | - ivy/.hypothesis/examples.zip - continue-on-error: true - - - name: Install Mongo Python Client - if: (steps.check_file_changed.outputs.changed == 'True' && github.event_name == 'push' && github.ref == 'refs/heads/main') - uses: BSFishy/pip-action@v1 - with: - packages: | - pymongo[srv] - - - name: Update Database - if: (steps.check_file_changed.outputs.changed == 'True' && github.event_name == 'push' && github.ref == 'refs/heads/main') - env: - MONGODB_PASSWORD: ${{ secrets.MONGODB_PASSWORD }} - run: | - cd ivy/automation_tools/dashboard_automation/ - python3 update_db.py "$MONGODB_PASSWORD" ${{ github.workflow }} "${{ matrix.backends }}-${{ matrix.submodules }}" ${{ steps.tests.outcome }} ${{ github.run_id }} - continue-on-error: true - - - - name: Check on failures - if: (steps.check_file_changed.outputs.changed == 'True' || steps.check_file_changed.conclusion == 'skipped') && steps.tests.outcome != 'success' - run: exit 1 diff --git a/.github/workflows/test-ivy-stateful.yml b/.github/workflows/test-ivy-stateful.yml deleted file mode 100644 index c4aeeb690f0b4..0000000000000 --- a/.github/workflows/test-ivy-stateful.yml +++ /dev/null @@ -1,129 +0,0 @@ -name: test-stateful-ivy -on: - workflow_dispatch: -# push: -# pull_request: -# types: [labeled, opened, synchronize, reopened, review_requested] -permissions: - actions: read -jobs: - run-nightly-tests: - if: ${{(github.event_name == 'push') || contains(github.event.pull_request.labels.*.name, 'Exhaustive CI') || contains(github.event.pull_request.labels.*.name, 'Ivy Stateful API') }} - strategy: - matrix: - backends: [ numpy, torch, jax, tensorflow ] - submodules: [ activations, converters, layers, modules, norms, optimizers, - sequential ] - continue-on-error: true - runs-on: ubuntu-latest - steps: - - name: Checkout ๐Ÿ›Ž๏ธIvy - uses: actions/checkout@v2 - with: - path: ivy - persist-credentials: false - submodules: "recursive" - fetch-depth: 2 - - - name: Install ivy and fetch binaries - run: | - cd ivy - pip3 install -e . - mkdir .ivy - touch .ivy/key.pem - echo -n ${{ secrets.USER_API_KEY }} > .ivy/key.pem - cd .. - - - name: Check Files Changed - if: ${{ (github.event_name == 'push') || !contains(github.event.pull_request.labels.*.name, 'Exhaustive CI') }} - shell: pwsh - id: check_file_changed - run: | - cd ivy - $diff = git diff --name-only HEAD^ HEAD - $SourceDiff = $diff | Where-Object { ` - $_ -match 'ivy_tests/test_ivy/test_stateful/test_${{ matrix.submodules }}.py' ` - -or $_ -match 'ivy_tests/test_ivy/helpers.py' ` - -or $_ -match 'ivy/array/${{ matrix.submodules }}.py' ` - -or $_ -match 'ivy/container/${{ matrix.submodules }}.py' ` - -or $_ -match 'ivy/functional/backends/${{ matrix.backends }}/${{ matrix.submodules }}.py' ` - -or $_ -match 'ivy/functional/ivy/${{ matrix.submodules }}.py' ` - -or $_ -match 'ivy/stateful/${{ matrix.submodules }}.py' ` - } - $HasDiff = $SourceDiff.Length -gt 0 - Write-Host "::set-output name=changed::$HasDiff" - - - name: Download artifact - uses: dawidd6/action-download-artifact@v2 - if: (steps.check_file_changed.outputs.changed == 'True' || steps.check_file_changed.conclusion == 'skipped') && github.event_name == 'pull_request' - with: - github_token: ${{secrets.GITHUB_TOKEN}} - workflow: test-ivy-stateful.yml - workflow_conclusion: "" - search_artifacts: true - name: hypothesis_${{ matrix.backends }}_test_${{ matrix.submodules }}_zip - path: | - ivy/.hypothesis/ - continue-on-error: true - - - name: Unzip Hypothesis Examples - id: unzip - if: (steps.check_file_changed.outputs.changed == 'True' || steps.check_file_changed.conclusion == 'skipped') && github.event_name == 'pull_request' - run: | - cd ivy/.hypothesis - unzip examples.zip - rm examples.zip - continue-on-error: true - - - name: Create Hypothesis Directory - if: (steps.check_file_changed.outputs.changed == 'True' || steps.check_file_changed.conclusion == 'skipped') && steps.unzip.outcome != 'success' && github.event_name == 'pull_request' - run: | - cd ivy - mkdir -p .hypothesis - cd .hypothesis - mkdir -p examples - continue-on-error: true - - - name: Run Stateful Tests - id: tests - if: steps.check_file_changed.outputs.changed == 'True' || steps.check_file_changed.conclusion == 'skipped' - run: | - cd ivy - ./scripts/shell/test_ivy_stateful.sh ${{ matrix.backends }} test_${{ matrix.submodules }} ${{ secrets.REDIS_CONNECTION_URL }} ${{ secrets.REDIS_PASSWORD}} - continue-on-error: true - - - name: Zip Hypothesis Examples - if: (steps.check_file_changed.outputs.changed == 'True' || steps.check_file_changed.conclusion == 'skipped') && github.event_name == 'pull_request' - run: | - cd ivy/.hypothesis - zip -r examples.zip examples - continue-on-error: true - - - name: Upload hypothesis - uses: actions/upload-artifact@v3 - if: (steps.check_file_changed.outputs.changed == 'True' || steps.check_file_changed.conclusion == 'skipped') && github.event_name == 'pull_request' - with: - name: hypothesis_${{ matrix.backends }}_test_${{ matrix.submodules }}_zip - path: | - ivy/.hypothesis/examples.zip - continue-on-error: true - - - name: Install Mongo Python Client - if: (steps.check_file_changed.outputs.changed == 'True' && github.event_name == 'push' && github.ref == 'refs/heads/main') - uses: BSFishy/pip-action@v1 - with: - packages: | - pymongo[srv] - - - name: Update Database - if: (steps.check_file_changed.outputs.changed == 'True' && github.event_name == 'push' && github.ref == 'refs/heads/main') - env: - MONGODB_PASSWORD: ${{ secrets.MONGODB_PASSWORD }} - run: | - cd ivy/automation_tools/dashboard_automation/ - python3 update_db.py "$MONGODB_PASSWORD" ${{ github.workflow }} "${{ matrix.backends }}-${{ matrix.submodules }}" ${{ steps.tests.outcome }} ${{ github.run_id }} - continue-on-error: true - - - name: Check on failures - if: (steps.check_file_changed.outputs.changed == 'True' || steps.check_file_changed.conclusion == 'skipped') && steps.tests.outcome != 'success' - run: exit 1 diff --git a/.github/workflows/test-ivy-tracer-cron.yml b/.github/workflows/test-ivy-tracer-cron.yml new file mode 100644 index 0000000000000..3039d90f9ec42 --- /dev/null +++ b/.github/workflows/test-ivy-tracer-cron.yml @@ -0,0 +1,46 @@ +name: test-ivy-tracer-cron +on: + workflow_dispatch: + schedule: + - cron: '15 * * * *' +permissions: + actions: read +jobs: + run-nightly-tests: + runs-on: ubuntu-latest + steps: + - name: Checkout ๐Ÿ›Ž๏ธIvy + uses: actions/checkout@v2 + with: + path: ivy + persist-credentials: false + submodules: "recursive" + + - name: Install ivy and fetch binaries + run: | + cd ivy + sudo pip3 install -e . + mkdir .ivy + touch .ivy/key.pem + echo -n ${{ secrets.USER_API_KEY }} > .ivy/key.pem + cd .. + + - name: Get Job URL + uses: Tiryoh/gha-jobid-action@v0 + id: jobs + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + job_name: ${{ github.job }} + + - name: Run Tests + id: tests + run: | + cd ivy + pip3 install pymongo + python scripts/setup_tests/cron_tests.py ${{ github.run_number }} false true + python scripts/run_tests/run_tests.py ${{ secrets.REDIS_CONNECTION_URL }} ${{ secrets.REDIS_PASSWORD }} ${{ secrets.MONGODB_PASSWORD }} 'false' 'false' ${{ github.run_id }} 'false' 'true' 'false' ${{ steps.jobs.outputs.html_url }} + continue-on-error: true + + - name: Check on failures + if: steps.tests.outcome != 'success' + run: exit 1 diff --git a/.gitignore b/.gitignore index fef9e99694c8c..9d225dc28b7ff 100644 --- a/.gitignore +++ b/.gitignore @@ -20,8 +20,8 @@ with_time_logs/ *.ods *.jpg *.jpeg -*.png *.gif +*.so .hypothesis .array_api_tests_k_flag* internal_automation_tools/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9dc902caeca49..cbf4307237040 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,33 +6,34 @@ repos: - id: trailing-whitespace - id: check-toml - id: end-of-file-fixer + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.3.0 + hooks: + # Run the linter. + - id: ruff + args: [ --fix ] - repo: https://github.com/psf/black-pre-commit-mirror - rev: 23.10.0 + rev: 24.2.0 hooks: - id: black language_version: python3 args: - "--preview" + exclude: > + (?x) + ( + ivy/functional/frontends/(?!.*(?:config\.py|__init__\.py)$).* | + ivy_tests/test_ivy/(?!.*(?:__init__\.py|conftest\.py|helpers/.*|test_frontends/config/.*$)).* + ) - repo: https://github.com/PyCQA/autoflake - rev: v2.2.1 + rev: v2.3.0 hooks: - id: autoflake - - repo: https://github.com/pycqa/flake8 - rev: 6.1.0 - hooks: - - id: flake8 - exclude: ^.*__init__.py$ - repo: https://github.com/PyCQA/docformatter rev: v1.7.5 hooks: - id: docformatter - - repo: https://github.com/pycqa/pydocstyle - rev: 6.3.0 - hooks: - - id: pydocstyle - # Exclude everything in frontends except __init__.py, and func_wrapper.py - exclude: 'ivy/functional/(frontends|backends)/(?!.*/func_wrapper\.py$).*(?!__init__\.py$)' - repo: https://github.com/unifyai/lint-hook - rev: 2ea80bc854c7f74b09620151028579083ff92ec2 + rev: a72ffb17562d919311653d7f593cb537d1245c19 hooks: - id: ivy-lint diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 85913821888c8..1655ef485e509 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -9,8 +9,8 @@ Please, follow the next process when you work on your subtask: 1. **Choosing a Task:** - Choose a task to work on which: - - is not marked as completed with a tick - - does not have an issue created + - is not marked as completed with a tick. + - does not have an issue created. - is not mentioned in the comments. Currently, there are three open tasks: @@ -39,7 +39,7 @@ Please, follow the next process when you work on your subtask: ### Important Notes -- if your PR is not created within 7 days of creating the issue, then a warning message will appear on the issue, we do this in order to keep our ToDo lists moving quickly, +- If your PR is not created within 7 days of creating the issue, then a warning message will appear on the issue, we do this in order to keep our ToDo lists moving quickly, - Please don't take it personally if your issue or PR gets closed because of this 7-day inactivity time limit. - Finally, we limit the maximum number of open and incomplete sub-task issues to three per person. @@ -48,4 +48,4 @@ Please, follow the next process when you work on your subtask: [![Video](https://img.youtube.com/vi/wBKTOGmwfbo/0.jpg)](https://www.youtube.com/embed/wBKTOGmwfbo) -For questions, please reach out on [discord](https://discord.gg/sd2yYCha) in the [todo list issues channel](https://discord.com/channels/799879767196958751/982728618469912627)! +For questions, please reach out on [discord](https://discord.gg/MDK979Ga) in the [todo list issues thread](https://discord.com/channels/799879767196958751/1189903501011202128)! diff --git a/MANIFEST.in b/MANIFEST.in index e0a363d10c6ec..8003b02e6779e 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -4,3 +4,4 @@ include ivy/compiler/*.so include ivy/compiler/*.py include binaries.json include available_configs.json +include wrappers.json diff --git a/README.md b/README.md index 9164b0f96d5f0..f526fd1c0535b 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -> ๐Ÿš€ We are granting pilot access to **Ivy\'s Tracer and Transpiler** -> to some users, [join the waitlist](https://console.unify.ai/) if you +> ๐Ÿš€ We are granting access to **Ivy\'s Tracer and Transpiler** +> to all of our users, [sign up on our console](https://console.unify.ai/) if you > want to test them out! @@ -202,8 +202,8 @@ After installing Ivy, you can start using it straight away, for example: b = jax.numpy.mean(x) return x * a + b - jax_x = jax.numpy.array([1, 2, 3]) - torch_x = torch.tensor([1, 2, 3]) + jax_x = jax.numpy.array([1., 2., 3.]) + torch_x = torch.tensor([1., 2., 3.]) torch_fn = ivy.transpile(jax_fn, source="jax", to="torch", args=(jax_x,)) ret = torch_fn(torch_x) ``` @@ -237,7 +237,7 @@ After installing Ivy, you can start using it straight away, for example: # Documentation -You can find Ivy's documentation in the [Docs page](https://unify.ai/docs/ivy/), which includes: +You can find Ivy's documentation on the [Docs page](https://unify.ai/docs/ivy/), which includes: - [Motivation](https://unify.ai/docs/ivy/overview/background.html): This contextualizes the problem Ivy is trying to solve by going over - The current [ML Explosion](https://unify.ai/docs/ivy/overview/background/ml_explosion.html#ml-explosion). - Explaining why it is important [to solve this problem](https://unify.ai/docs/ivy/overview/background/why_unify.html#why-unify). @@ -1337,7 +1337,7 @@ train(images, classes, num_epochs, model, device, num_classes = num_classes, bat # Diving deeper -Although the [Docs](https://unify.ai/docs/ivy/) are the best place to learn more, in the next section we will take a look at how Ivy works as both a transpiler and a framework in a bit more of detail to get an idea of why and where to use it. +Although the [Docs](https://unify.ai/docs/ivy/) are the best place to learn more, in the next section we will take a look at how Ivy works both as a transpiler and a framework in a bit more detail to get an idea of why and where to use it.
Ivy as a transpiler @@ -1589,9 +1589,9 @@ our journey to unify all ML frameworks! # Community -In order to achieve the ambitious goal of unifying AI we definitely need +In order to achieve the ambitious goal of unifying AI, we definitely need as many hands as possible on it! Whether you are a seasoned developer or -just starting out, you\'ll find a place here! Join the Ivy community in +just starting out, you\'ll find a place here! Join the Ivy community on our [Discord](https://discord.gg/sXyFF8tDtm) ๐Ÿ‘พ server, which is the perfect place to ask questions, share ideas, and get help from both fellow developers and the Ivy Team directly! diff --git a/available_configs.json b/available_configs.json index da04c67cda05a..a0697c63b5791 100644 --- a/available_configs.json +++ b/available_configs.json @@ -1,11 +1,14 @@ { "compiler": [ "cp38-cp38-manylinux_2_17_x86_64", + "cp38-cp38-win_amd64", "cp39-cp39-manylinux_2_17_x86_64", + "cp39-cp39-win_amd64", "cp310-cp310-manylinux_2_17_x86_64", - "cp311-cp311-manylinux_2_17_x86_64" - ], - "engines": [ - "cp310-cp310-manylinux_2_17_x86_64" + "cp310-cp310-win_amd64", + "cp310-cp310-macosx_12_0_arm64", + "cp311-cp311-manylinux_2_17_x86_64", + "cp311-cp311-win_amd64", + "cp311-cp311-macosx_12_0_arm64" ] } diff --git a/binaries.json b/binaries.json index f77586c81524f..86406c4fc4a82 100644 --- a/binaries.json +++ b/binaries.json @@ -1,95 +1,75 @@ { "ivy": { "compiler": [ - "_compiler.so", + "_compiler", { "utils": [ - "CC.so", - "CD.so", - "CI.so", - "CL.so", - "CM.so", - "CV.so", - "CX.so", - "C.so", - - "DC.so", - "DD.so", - "DI.so", - "DL.so", - "DM.so", - "DV.so", - "DX.so", - "D.so", - - "IC.so", - "ID.so", - "II.so", - "IL.so", - "IM.so", - "IV.so", - "IX.so", - "I.so", - - "LC.so", - "LD.so", - "LI.so", - "LL.so", - "LM.so", - "LV.so", - "LX.so", - "L.so", - - "MI.so", - "ML.so", - "MV.so", - "MX.so", - "M.so", - - "VC.so", - "VD.so", - "VI.so", - "VL.so", - "VM.so", - "VV.so", - "VX.so", - "V.so", - - "XC.so", - "XD.so", - "XI.so", - "XL.so", - "XM.so", - "XV.so", - "XX.so", - "X.so" + "C", + "CC", + "CD", + "CI", + "CL", + "CM", + "CV", + "CX", + "D", + "DC", + "DD", + "DI", + "DL", + "DM", + "DV", + "DX", + "I", + "IC", + "ID", + "II", + "IIC", + "IID", + "III", + "IIL", + "IIM", + "IIV", + "IIX", + "IL", + "IM", + "IV", + "IVI", + "IX", + "L", + "LC", + "LD", + "LI", + "LL", + "LM", + "LV", + "LX", + "M", + "MC", + "MD", + "MI", + "ML", + "MM", + "MV", + "MX", + "V", + "VC", + "VD", + "VI", + "VL", + "VM", + "VV", + "VX", + "X", + "XC", + "XD", + "XI", + "XL", + "XM", + "XV", + "XX" ] } - ], - "engines": [ - "ivy2xla.so", - { - "XLA": { - "rust_api": { - "python_frontend": [ - "activations.so", - "creation.so", - "elementwise.so", - "general.so", - "ivy2xla.so", - "layers.so", - "linear_algebra.so", - "manipulation.so", - "norms.so", - "stateful_activations.so", - "stateful_layers.so", - "stateful_norms.so", - "statistical.so", - "xla_core.so" - ] - } - } - } ] } } diff --git a/docker/DockerfileAppleSilicon b/docker/DockerfileAppleSilicon index 1c0f5926cf3c9..b0d258ad19646 100644 --- a/docker/DockerfileAppleSilicon +++ b/docker/DockerfileAppleSilicon @@ -234,9 +234,3 @@ RUN python3 test_dependencies.py -fp requirements.txt && \ rm -rf tmp.txt && \ rm -rf test_dependencies.py && \ rm -rf requirement_mappings_apple_silicon.json - -# Post installation steps -COPY .devcontainer/post_create_commands.sh . -RUN chmod +x post_create_commands.sh && \ - bash post_create_commands.sh && \ - rm -rf post_create_commands.sh diff --git a/docker/DockerfileGPUMultiCuda b/docker/DockerfileGPU similarity index 75% rename from docker/DockerfileGPUMultiCuda rename to docker/DockerfileGPU index 46ea25929c4a5..7cef64508c005 100644 --- a/docker/DockerfileGPUMultiCuda +++ b/docker/DockerfileGPU @@ -1,16 +1,33 @@ -# uses the base image which has cuda and cudnn installed(multiple versions) and then installs the +# installs multiple versions of cuda and cudnn and then installs the # latest frameworks and the requirements -FROM unifyai/multicuda:base +FROM debian:buster WORKDIR /ivy -ARG fw +# arguments +ARG fw ARG pycon=3.10 +# environment variables ENV DEBIAN_FRONTEND=noninteractive - -# Install miniconda +ENV TZ=Europe/Moscow ENV CONDA_DIR /opt/miniconda/ + +# install base libraries +RUN grep security /etc/apt/sources.list | tee /etc/apt/security.sources.list && \ + apt-get update && \ + apt-get upgrade -o Dir::Etc::SourceList=/etc/apt/security.sources.list -y &&\ + apt-get -y update && \ + apt-get install -y gnupg \ + curl \ + wget \ + software-properties-common \ + gcc \ + nano \ + procps + + +# install miniconda RUN apt clean && \ rm -rf /var/lib/apt/lists/* && \ apt-get update && \ @@ -21,10 +38,12 @@ RUN apt clean && \ /bin/bash ~/miniconda.sh -b -p /opt/miniconda +# create conda environment ENV PATH=$CONDA_DIR/bin:$PATH RUN conda create --name multienv python==$pycon -y -# to fix protobuf conflicts + +# fix protobuf conflicts ENV PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION python ENV PATH=/opt/miniconda/envs/multienv/bin:$PATH RUN apt-get update && \ @@ -38,44 +57,42 @@ RUN apt-get update && \ pip3 install setuptools==58.5.3 -# Install Ivy Upstream +# install Ivy Upstream RUN git clone --progress --recurse-submodules https://github.com/unifyai/ivy --depth 1 && \ cd ivy && \ cd ivy_tests/array_api_testing/test_array_api && \ pip3 install --no-cache-dir -r requirements.txt -# Install local optional -COPY /docker/multicuda_framework_directory.py . + +# copy library files to workdir +COPY docker/gpu_framework_directory.py . COPY requirements/optional_gpu.txt . COPY requirements/requirements.txt . -#setting torch path early on because torch-scatter needs it +# setting torch path early on because torch-scatter needs it ENV PYTHONPATH "/opt/fw/torch:/opt/miniconda/envs/multienv/bin" + # requirement mappings directs which dependency to be installed and where COPY /docker/requirement_mappings_gpu.json . SHELL ["/bin/bash", "-c"] - -RUN python3 multicuda_framework_directory.py $fw &&\ +# install all libraries based on the mappings +RUN python3 gpu_framework_directory.py $fw &&\ jq -r 'to_entries[] | select(.value != [""]) | .key as $dir | .value[] | @sh "/opt/fw/\($dir) \(.)"' requirement_mappings_gpu.json | xargs -I {} sh -c 'printf "Installing %s\n" $2 && pip install --ignore-installed --target $1 $2 --extra-index-url https://download.pytorch.org/whl/cu118' sh {} - - - RUN sed -i '/numpy/d' requirements.txt &&\ pip install -r requirements.txt &&\ cp ./optional_gpu.txt tmp.txt &&\ jq -r 'to_entries[] | [.key] + .value | select(length > 0 or (. == "")) | .[]' requirement_mappings_gpu.json | sort -u | xargs -I {} sed -i '/{}/d;/jaxlib/d' tmp.txt && pip install -r tmp.txt - - # add all the directories to environment path so that python knows where to find them ENV PYTHONPATH "/opt/fw/mxnet:/opt/fw/numpy:/opt/fw/tensorflow:/opt/fw/jax:/opt/fw/torch:/opt/fw/paddle:/opt/miniconda/envs/multienv/bin" +# test dependencies COPY scripts/test_dependencies.py . RUN python3 test_dependencies.py -fp requirements.txt,optional_gpu.txt && \ rm -rf requirements.txt && \ diff --git a/docker/DockerfileGPUMultiCuda-base b/docker/DockerfileGPUMultiCuda-base deleted file mode 100644 index fa8c4c9895f53..0000000000000 --- a/docker/DockerfileGPUMultiCuda-base +++ /dev/null @@ -1,20 +0,0 @@ -# is used to create a base image where we then manually install cuda and cudnn -FROM debian:buster -WORKDIR /ivy - - -COPY ../docker/multicuda_framework_directory.py . -COPY ../docker/multicuda_requirements.txt . - -ENV DEBIAN_FRONTEND=noninteractive -ENV TZ=Europe/Moscow -RUN grep security /etc/apt/sources.list | tee /etc/apt/security.sources.list && \ - apt-get update && \ - apt-get upgrade -o Dir::Etc::SourceList=/etc/apt/security.sources.list -y &&\ - apt-get -y update && \ - apt-get install -y gnupg \ - curl \ - wget \ - software-properties-common \ - gcc \ - nano diff --git a/docker/build_DockerfileGPUMultiCuda.sh b/docker/build_DockerfileGPUMultiCuda.sh deleted file mode 100644 index f9e0ff9da5d9f..0000000000000 --- a/docker/build_DockerfileGPUMultiCuda.sh +++ /dev/null @@ -1 +0,0 @@ -docker build --progress=plain --no-cache -t unifyai/multicuda:base_and_requirements -f DockerfileGPUMultiCuda .. diff --git a/docker/build_gpu_dockerfile.sh b/docker/build_gpu_dockerfile.sh new file mode 100644 index 0000000000000..ec946c8b97e89 --- /dev/null +++ b/docker/build_gpu_dockerfile.sh @@ -0,0 +1 @@ +docker build --progress=plain --no-cache -t unifyai/ivy:latest-gpu -f DockerfileGPU .. diff --git a/docker/multicuda_framework_directory.py b/docker/gpu_framework_directory.py similarity index 78% rename from docker/multicuda_framework_directory.py rename to docker/gpu_framework_directory.py index 9ff00d59353b2..3dee4b7bf7750 100644 --- a/docker/multicuda_framework_directory.py +++ b/docker/gpu_framework_directory.py @@ -15,7 +15,7 @@ def get_latest_package_version(package_name): try: url = f"https://pypi.org/pypi/{package_name}/json" - response = requests.get(url) + response = requests.get(url, timeout=10) response.raise_for_status() package_info = response.json() return package_info["info"]["version"] @@ -40,7 +40,14 @@ def install_pkg(path, pkg, base="fw/"): subprocess.run( f"yes |pip3 install --upgrade {pkg} --target" f" {path} --default-timeout=100 --extra-index-url" - " https://download.pytorch.org/whl/cu118 --no-cache-dir", + " --no-cache-dir", + shell=True, + ) + subprocess.run( + f"yes |pip3 install --upgrade torchvision --index-url" + f" https://download.pytorch.org/whl/cu121 --target" + f" {path} --default-timeout=100 --extra-index-url" + " --no-cache-dir", shell=True, ) elif pkg.split("==")[0] if "==" in pkg else pkg == "jax": @@ -53,12 +60,16 @@ def install_pkg(path, pkg, base="fw/"): elif pkg.split("==")[0] if "==" in pkg else pkg == "paddle": subprocess.run( "yes |pip install " - f" paddlepaddle-gpu=={get_latest_package_version('paddlepaddle')}.post117" - f" --target {path} -f" - " https://www.paddlepaddle.org.cn/whl/linux/mkl/avx/stable.html " + f" paddlepaddle-gpu=={get_latest_package_version('paddlepaddle')}" + f" --target {path} -f https://mirror.baidu.com/pypi/simple " " --no-cache-dir", shell=True, ) + elif pkg.split("==")[0] if "==" in pkg else pkg == "tensorflow": + subprocess.run( + f"yes |pip install tensorflow[and-cuda] --target {path}", + shell=True, + ) else: subprocess.run( f"yes |pip3 install --upgrade {pkg} --target" diff --git a/docker/rebuild_all_dockerfiles.sh b/docker/rebuild_all_dockerfiles.sh index 7af9cb5c2170e..386faff74fae5 100755 --- a/docker/rebuild_all_dockerfiles.sh +++ b/docker/rebuild_all_dockerfiles.sh @@ -1,4 +1,4 @@ #!/bin/bash docker build -t unifyai/ivy:latest --no-cache -f Dockerfile .. -docker build -t unifyai/multicuda:base_and_requirements --no-cache -f DockerfileGPUMultiCuda .. +docker build -t unifyai/ivy:latest-gpu --no-cache -f DockerfileGPU .. diff --git a/docker/requirement_mappings_apple_silicon.json b/docker/requirement_mappings_apple_silicon.json index ea1d78d80539d..789a2e6e36789 100644 --- a/docker/requirement_mappings_apple_silicon.json +++ b/docker/requirement_mappings_apple_silicon.json @@ -1,6 +1,6 @@ { "tensorflow": ["tensorflow-macos", "tensorflow-probability"], "jax": ["jaxlib", "dm-haiku", "flax"], - "torch": ["torch-scatter", "functorch"], + "torch": ["torch-scatter"], "mxnet": ["mxnet"] } diff --git a/docker/requirement_mappings_gpu.json b/docker/requirement_mappings_gpu.json index 89586215a8504..ade51df83cc09 100644 --- a/docker/requirement_mappings_gpu.json +++ b/docker/requirement_mappings_gpu.json @@ -1,7 +1,7 @@ { - "tensorflow": ["tensorflow-probability"], "jax": ["dm-haiku", "flax"], "numpy": ["numpy"], "mxnet": ["mxnet"], - "torch": ["torch-scatter", "torchvision"] + "torch": ["torchvision", "torch-scatter"], + "tensorflow": ["tensorflow-probability"] } diff --git a/docs/demos b/docs/demos index c068c12656952..d3fa2b9c2a7ff 160000 --- a/docs/demos +++ b/docs/demos @@ -1 +1 @@ -Subproject commit c068c12656952b7c223c9d34308efc9d58a71157 +Subproject commit d3fa2b9c2a7ffa93573bb63d2e66abbe3dd198fc diff --git a/docs/index.rst b/docs/index.rst index e88f08969b560..02a4eefdf723a 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -46,6 +46,7 @@ overview/design.rst overview/contributing.rst + overview/volunteer_ranks.rst overview/deep_dive.rst overview/glossary.rst overview/faq.rst diff --git a/docs/overview/contributing.rst b/docs/overview/contributing.rst index 6e988bba87b52..53a98e9417dc0 100644 --- a/docs/overview/contributing.rst +++ b/docs/overview/contributing.rst @@ -21,19 +21,25 @@ The contributor guide is split into the sections below, it's best to go from sta | (b) `The Basics `_ | Managing your fork ๐Ÿ‡พ, creating issues โญ•, and creating pull-requests โฌ†๏ธ | -| (c) `Building the Docs `_ +| (c) `Open Tasks `_ +| See where you can help us out! ๐Ÿ™‹ +| +| (d) `Contributor Rewards `_ +| Check out our contributor badges and achievements! ๐Ÿ… +| +| (e) `Contributor Program `_ +| How to climb up the ranks in our Contributor program ๐Ÿง— +| +| (f) `Building the Docs `_ | How to build the documentation locally ๐Ÿ—๏ธ | -| (d) `Deep Dive `_ +| (g) `Deep Dive `_ | Take a deep dive into the codebase ๐Ÿคฟ | -| (e) `Open Tasks `_ -| See where you can help us out! ๐Ÿ™‹ -| -| (f) `Helpful Resources `_ +| (h) `Helpful Resources `_ | Resources you would find useful when learning Ivy ๐Ÿ“– | -| (g) `Error Handling `_ +| (i) `Error Handling `_ | Common errors you will be facing contributing to Ivy โŒ .. toctree:: @@ -46,6 +52,8 @@ The contributor guide is split into the sections below, it's best to go from sta contributing/building_the_docs.rst Deep Dive contributing/open_tasks.rst + contributing/volunteer_program.rst + contributing/contributor_rewards.rst contributing/helpful_resources.rst contributing/error_handling.rst diff --git a/docs/overview/contributing/contributor_rewards.rst b/docs/overview/contributing/contributor_rewards.rst new file mode 100644 index 0000000000000..07dd0f6b6db4b --- /dev/null +++ b/docs/overview/contributing/contributor_rewards.rst @@ -0,0 +1,82 @@ +Contributor Rewards +=================== + +We award a range of badges, each designed to formally recognize the specific achievements of our contributors in various key areas of ivy's development. + +Badges +~~~~~~~ + +**Debugging Dynamos** - These badges are earned by creating useful issues. If you find a problem that isn't listed as an open task, report it by creating a new issue. Make sure to describe the problem thoroughly. If your issue is confirmed as useful and marked as a "Useful Issue" by our team, you'll receive the badge as recognition for your valuable contribution to improving our codebase. + +**Merging Master** - These badges are formal recognitions for contributors whose pull requests consistently meet our standards of quality and are successfully merged into the main codebase. + +**Merging Wizard** - These exclusive badges are awarded to contributors who successfully get *priority* pull requests merged. This recognition is for handling complex, high-priority tasks that have a substantial impact on the project's progress and success. Priority pull requests are those that close `"Priority Open" issues `_ found within each framework. + +**Ivy Inspectors** - These badges are given in acknowledgment of the essential role played by those who review our pull requests. It honours the commitment to quality and diligence in ensuring that each code merge aligns with our standards. + +Each badge comes in four distinct tiers โ€“ Initial, Bronze, Silver, and Gold, mirroring your growing expertise and commitment in these areas. + +Badge Tiers +~~~~~~~~~~~~ + +.. list-table:: + :widths: 50 25 30 30 30 + :header-rows: 1 + + * - GitHub Badge + - Initial (1 Task) + - Bronze (5 Tasks) + - Silver (15 Tasks) + - Gold (30 Tasks) + * - Debugging Dynamos + - .. image:: https://raw.githubusercontent.com/unifyai/ivy/main/.vaunt/badges/badge_01-00.png + :width: 110 + :alt: Alternative text + - .. image:: https://raw.githubusercontent.com/unifyai/ivy/main/.vaunt/badges/badge_01-02.png + :width: 110 + :alt: Alternative text + - .. image:: https://raw.githubusercontent.com/unifyai/ivy/main/.vaunt/badges/badge_01-03.png + :width: 110 + :alt: Alternative text + - .. image:: https://raw.githubusercontent.com/unifyai/ivy/main/.vaunt/badges/badge_01-04.png + :width: 110 + :alt: Alternative text + * - Merging Master + - .. image:: https://raw.githubusercontent.com/unifyai/ivy/main/.vaunt/badges/badge_04-00.png + :width: 110 + :alt: Alternative text + - .. image:: https://raw.githubusercontent.com/unifyai/ivy/main/.vaunt/badges/badge_04-02.png + :width: 110 + :alt: Alternative text + - .. image:: https://raw.githubusercontent.com/unifyai/ivy/main/.vaunt/badges/badge_04-03.png + :width: 110 + :alt: Alternative text + - .. image:: https://raw.githubusercontent.com/unifyai/ivy/main/.vaunt/badges/badge_04-04.png + :width: 110 + :alt: Alternative text + * - Merging Wizard + - .. image:: https://raw.githubusercontent.com/unifyai/ivy/main/.vaunt/badges/badge_05-00.png + :width: 110 + :alt: Alternative text + - .. image:: https://raw.githubusercontent.com/unifyai/ivy/main/.vaunt/badges/badge_05-02.png + :width: 110 + :alt: Alternative text + - .. image:: https://raw.githubusercontent.com/unifyai/ivy/main/.vaunt/badges/badge_05-03.png + :width: 110 + :alt: Alternative text + - .. image:: https://raw.githubusercontent.com/unifyai/ivy/main/.vaunt/badges/badge_05-04.png + :width: 110 + :alt: Alternative text + * - Ivy Inspectors + - .. image:: https://raw.githubusercontent.com/unifyai/ivy/main/.vaunt/badges/badge_06-00.png + :width: 110 + :alt: Alternative text + - .. image:: https://raw.githubusercontent.com/unifyai/ivy/main/.vaunt/badges/badge_06-02.png + :width: 110 + :alt: Alternative text + - .. image:: https://raw.githubusercontent.com/unifyai/ivy/main/.vaunt/badges/badge_06-03.png + :width: 110 + :alt: Alternative text + - .. image:: https://raw.githubusercontent.com/unifyai/ivy/main/.vaunt/badges/badge_06-04.png + :width: 110 + :alt: Alternative text diff --git a/docs/overview/contributing/error_handling.rst b/docs/overview/contributing/error_handling.rst index 2ddfa6be2c4ca..75f7e300e5432 100644 --- a/docs/overview/contributing/error_handling.rst +++ b/docs/overview/contributing/error_handling.rst @@ -2,11 +2,11 @@ Error Handling ============== .. _`discord`: https://discord.gg/sXyFF8tDtm -.. _`pycharm channel`: https://discord.com/channels/799879767196958751/942114831039856730 -.. _`docker channel`: https://discord.com/channels/799879767196958751/942114744691740772 -.. _`pre-commit channel`: https://discord.com/channels/799879767196958751/982725464110034944 -.. _`pip packages channel`: https://discord.com/channels/799879767196958751/942114789642080317 -.. _`ivy tests channel`: https://discord.com/channels/799879767196958751/982738436383445073 +.. _`pycharm thread`: https://discord.com/channels/799879767196958751/1186628916522262629 +.. _`docker thread`: https://discord.com/channels/799879767196958751/1186629067966009424 +.. _`pre-commit thread`: https://discord.com/channels/799879767196958751/1186629635694399539 +.. _`pip packages thread`: https://discord.com/channels/799879767196958751/1186629837515935765 +.. _`ivy tests thread`: https://discord.com/channels/799879767196958751/1189907526226034698 This section, "Error Handling" aims to assist you in navigating through some common errors you might encounter while working with the Ivy's Functional API. We'll go through some common errors which you might encounter while working as a contributor or a developer. @@ -150,4 +150,4 @@ This section is specifically targeted towards dealing with the Ivy Functional AP This should have hopefully given you an understanding of how to deal with common errors while working with the the functional API. -If you have any questions, please feel free to reach out on `discord`_ in the `ivy tests channel`_, `pycharm channel`_, `docker channel`_, `pre-commit channel`_, `pip packages channel`_ depending on the question! +If you have any questions, please feel free to reach out on `discord`_ in the `ivy tests thread`_, `pycharm thread`_, `docker thread`_, `pre-commit thread`_, `pip packages thread`_ depending on the question! diff --git a/docs/overview/contributing/helpful_resources.rst b/docs/overview/contributing/helpful_resources.rst index c70e30f30795d..bacdfde8f99cb 100644 --- a/docs/overview/contributing/helpful_resources.rst +++ b/docs/overview/contributing/helpful_resources.rst @@ -20,11 +20,11 @@ Useful when working on almost any section in the Deep Dive. **Co-Pilot** GitHub Co-Pilot can be used to write any bit of code in Ivy. -They are often very useful when developing code and also helps gets things done faster. +They are often very useful when developing code and also help get things done faster. **GitHub - Reference** -Git docs is the first place you must head to when you are stuck which any issue related to git. +`Git docs `_ is the first place you must head to when you are stuck with any issue related to git. **IDE extension for spell checking** @@ -36,4 +36,4 @@ Though this may sound odd, a spell-checking extension is very useful to people c **Github Actions** -GitHub Actions can be the best place to understand Continuous Integration and how testing is done to keep our repo error free. +`GitHub Actions `_ can be the best place to understand Continuous Integration and how testing is done to keep our repo error free. diff --git a/docs/overview/contributing/open_tasks.rst b/docs/overview/contributing/open_tasks.rst index 081f7946d6488..4420295b0d893 100644 --- a/docs/overview/contributing/open_tasks.rst +++ b/docs/overview/contributing/open_tasks.rst @@ -3,7 +3,7 @@ Open Tasks .. _`repo`: https://github.com/unifyai/ivy .. _`discord`: https://discord.gg/sXyFF8tDtm -.. _`open tasks channel`: https://discord.com/channels/799879767196958751/985156466963021854 +.. _`open tasks thread`: https://discord.com/channels/799879767196958751/1189903501011202128 .. _`issue description`: https://github.com/unifyai/ivy/issues/1526 .. _`reference API`: https://numpy.org/doc/stable/reference/routines.linalg.html .. _`imports`: https://github.com/unifyai/ivy/blob/38dbb607334cb32eb513630c4496ad0024f80e1c/ivy/functional/frontends/numpy/__init__.py#L27 @@ -20,89 +20,55 @@ We make no mention of task selection and allocation in the explanations below, w The tasks currently open are: +#. Fixing Failing Tests #. Function Formatting #. Frontend APIs #. Ivy Experimental API -We try to explain these tasks as clearly as possible, but in cases where things are not clear, then please feel free to reach out on `discord`_ in the `open tasks channel`_! +We try to explain these tasks as clearly as possible, but in cases where things are not clear, then please feel free to reach out on `discord`_ in the `open tasks thread`_! Please always use the latest commit on GitHub when working on any of these tasks, **DO NOT** develop your code using the latest PyPI release of :code:`ivy`. -Function Formatting -------------------- - -Currently, we have many ToDo list issues `open `_ for a general function formatting task, which is explained below. - -Each function in each submodule should be updated to follow the implementation instructions given in the `Deep Dive`_ section. -The updates should be applied for the: - -#. ivy API -#. all backend APIs -#. array instance methods -#. container instance methods -#. array operators -#. array reverse operators -#. container operators -#. container reverse operators - -The `Deep Dive`_ is an **essential** resource for learning how each of these functions/methods should be implemented. -Before starting any contribution task, you should go through the `Deep Dive`_, and familiarize yourself with the content. - -At the time of writing, many of the functions are not implemented as they should be. -You will need to make changes to the current implementations, but you do not need to address *all* sections of the `Deep Dive`_ in detail. -Specifically, you **do not** need to address the following: - -#. Implement the hypothesis testing for the function -#. Get the tests passing for your function, if they are failing before you start - -However, everything else covered in the `Deep Dive`_ must be addressed. -Some common important tasks are: - -#. Remove all :code:`lambda` and direct bindings for the backend functions (in :code:`ivy.functional.backends`), with each function instead defined using :code:`def`. -#. Implement the following if they don't exist but should do: :class:`ivy.Array` instance method, :class:`ivy.Container` instance method, :class:`ivy.Array` special method, :class:`ivy.Array` reverse special method, :class:`ivy.Container` special method, :class:`ivy.Container` reverse special method. -#. Make sure that the aforementioned methods are added into the correct category-specific parent class, such as :class:`ivy.ArrayWithElementwise`, :class:`ivy.ContainerWithManipulation` etc. -#. Correct all of the `Function Arguments <../deep_dive/function_arguments.rst>`_ and the type hints for every function **and** its *relevant methods*, including those you did not implement yourself. -#. Add the correct `Docstrings <../deep_dive/docstrings.rst>`_ to every function **and** its *relevant methods*, including those you did not implement yourself. -#. Add thorough `Docstring Examples <../deep_dive/docstring_examples.rst>`_ for every function **and** its *relevant methods* and ensure they pass the docstring tests. +Fixing Failing Tests +-------------------- -Formatting checklist -~~~~~~~~~~~~~~~~~~~~ +We've identified a range of functions and tests that fail the tests. +The root of these issues is not always straightforward. +In some instances, the problem may lie within the function implementations, while in others, it could be the way the tests were added previously. +Certain failing tests are more urgent to fix than others, as mentioned in the sub-section below. +We encourage contributions from the community to help tackle these challenges. -After creating your Pull Request on github, you should then produce the checklist for the formatting task as follows: +How to Contribute +~~~~~~~~~~~~~~~~~ -1. Add a comment with the following format: :code:`add_reformatting_checklist_` on your PR, where ** is the name of the category that the function belongs to. - An example of this is shown below. +**Identifying Issues** -.. image:: https://github.com/unifyai/unifyai.github.io/blob/main/img/externally_linked/contributing/open_tasks/checklist_generator.png?raw=true - :width: 420 +To get started, visit our issues page: `Failing Tests `_. +Here, you will find a list of open issues labeled as "Failing Test" and "ToDo". +These issues are categorised under various frameworks supported by our repository. +We encourage you to select a framework you're comfortable with or interested in contributing to. -Using this formatting will then trigger our github automation bots to update your comment with the proper markdown text for the checklist. -These updates might take a few moments to take effect, so please be patient ๐Ÿ™‚. +**Selecting a Test** -2. After adding the checklist to your PR, you should then modify this checklist with the status of each item according to the symbols(emojis) within the LEGEND section. +Within each framework, tests are classified as either "Priority Open" or "Other Open." +While we prioritize fixing the "Priority Open" tests, contributions towards any test, including those labeled "Other Open," are highly valuable. +Each test issue is linked directly to the specific failing workflow. +This linkage provides you with immediate access to the details of what exactly is failing and the context around it. -.. image:: https://github.com/unifyai/unifyai.github.io/blob/main/img/externally_linked/contributing/open_tasks/checklist_legend.png?raw=true - :width: 420 +**Making Your Contribution** -3. When all check items are marked as (โœ…, โฉ, or ๐Ÿ†—), you should request a review for your PR and we will start checking your implementation and marking the items as complete using the checkboxes next to them. +After selecting a test to work on, please make the necessary changes and create a PR referring to `the basics `_. +Ensure that your solution addresses the issue effectively and doesn't introduce new errors. +Once you're confident in your fix, submit a pull request to the main repository. +Our team will review your contribution, provide feedback if necessary, and then merge your changes once we're good to go. -.. image:: https://github.com/unifyai/unifyai.github.io/blob/main/img/externally_linked/contributing/open_tasks/checklist_checked.png?raw=true - :width: 420 +**Video** -4. In case you are stuck or need help with one of the checklist items, please add the ๐Ÿ†˜ symbol next to the item on the checklist, and proceed to add a comment elaborating on your point of struggle with this item. -The PR assignee will then see this comment and address your issues. - -.. image:: https://github.com/unifyai/unifyai.github.io/blob/main/img/externally_linked/contributing/open_tasks/checklist_SOS.png?raw=true - :width: 420 - -**Notes**: - -1. It is important that the PR author is the one to add the checklist generating comment in order to ensure they will have access to edit and update it later. -2. The checklist items' statuses should be manually updated by the PR author. - It does not automatically run any tests to update them! -3. Do not edit the checklist text, only the emoji symbols. ๐Ÿ˜… -4. Please refrain from using the checkboxes next to checklist items. +.. raw:: html + Frontend APIs ------------- @@ -222,6 +188,83 @@ However, you can still use the checklist as a reference in cases where you do un 2. Do not edit the checklist text, only the emoji symbols. 3. Please refrain from using the checkboxes next to checklist items. + +Function Formatting +------------------- + +Currently, we have many ToDo list issues `open `_ for a general function formatting task, which is explained below. + +Each function in each submodule should be updated to follow the implementation instructions given in the `Deep Dive`_ section. +The updates should be applied for the: + +#. ivy API +#. all backend APIs +#. array instance methods +#. container instance methods +#. array operators +#. array reverse operators +#. container operators +#. container reverse operators + +The `Deep Dive`_ is an **essential** resource for learning how each of these functions/methods should be implemented. +Before starting any contribution task, you should go through the `Deep Dive`_, and familiarize yourself with the content. + +At the time of writing, many of the functions are not implemented as they should be. +You will need to make changes to the current implementations, but you do not need to address *all* sections of the `Deep Dive`_ in detail. +Specifically, you **do not** need to address the following: + +#. Implement the hypothesis testing for the function +#. Get the tests passing for your function, if they are failing before you start + +However, everything else covered in the `Deep Dive`_ must be addressed. +Some common important tasks are: + +#. Remove all :code:`lambda` and direct bindings for the backend functions (in :code:`ivy.functional.backends`), with each function instead defined using :code:`def`. +#. Implement the following if they don't exist but should do: :class:`ivy.Array` instance method, :class:`ivy.Container` instance method, :class:`ivy.Array` special method, :class:`ivy.Array` reverse special method, :class:`ivy.Container` special method, :class:`ivy.Container` reverse special method. +#. Make sure that the aforementioned methods are added into the correct category-specific parent class, such as :class:`ivy.ArrayWithElementwise`, :class:`ivy.ContainerWithManipulation` etc. +#. Correct all of the `Function Arguments <../deep_dive/function_arguments.rst>`_ and the type hints for every function **and** its *relevant methods*, including those you did not implement yourself. +#. Add the correct `Docstrings <../deep_dive/docstrings.rst>`_ to every function **and** its *relevant methods*, including those you did not implement yourself. +#. Add thorough `Docstring Examples <../deep_dive/docstring_examples.rst>`_ for every function **and** its *relevant methods* and ensure they pass the docstring tests. + +Formatting checklist +~~~~~~~~~~~~~~~~~~~~ + +After creating your Pull Request on github, you should then produce the checklist for the formatting task as follows: + +1. Add a comment with the following format: :code:`add_reformatting_checklist_` on your PR, where ** is the name of the category that the function belongs to. + An example of this is shown below. + +.. image:: https://github.com/unifyai/unifyai.github.io/blob/main/img/externally_linked/contributing/open_tasks/checklist_generator.png?raw=true + :width: 420 + +Using this formatting will then trigger our github automation bots to update your comment with the proper markdown text for the checklist. +These updates might take a few moments to take effect, so please be patient ๐Ÿ™‚. + +2. After adding the checklist to your PR, you should then modify this checklist with the status of each item according to the symbols(emojis) within the LEGEND section. + +.. image:: https://github.com/unifyai/unifyai.github.io/blob/main/img/externally_linked/contributing/open_tasks/checklist_legend.png?raw=true + :width: 420 + +3. When all check items are marked as (โœ…, โฉ, or ๐Ÿ†—), you should request a review for your PR and we will start checking your implementation and marking the items as complete using the checkboxes next to them. + +.. image:: https://github.com/unifyai/unifyai.github.io/blob/main/img/externally_linked/contributing/open_tasks/checklist_checked.png?raw=true + :width: 420 + +4. In case you are stuck or need help with one of the checklist items, please add the ๐Ÿ†˜ symbol next to the item on the checklist, and proceed to add a comment elaborating on your point of struggle with this item. +The PR assignee will then see this comment and address your issues. + +.. image:: https://github.com/unifyai/unifyai.github.io/blob/main/img/externally_linked/contributing/open_tasks/checklist_SOS.png?raw=true + :width: 420 + +**Notes**: + +1. It is important that the PR author is the one to add the checklist generating comment in order to ensure they will have access to edit and update it later. +2. The checklist items' statuses should be manually updated by the PR author. + It does not automatically run any tests to update them! +3. Do not edit the checklist text, only the emoji symbols. ๐Ÿ˜… +4. Please refrain from using the checkboxes next to checklist items. + + Ivy Experimental API -------------------- @@ -316,4 +359,4 @@ Creating an Issue on Ivy's GitHub using a Template This should have hopefully given you a good understanding of the basics for contributing. -If you have any questions, please feel free to reach out on `discord`_ in the `open tasks channel`_! +If you have any questions, please feel free to reach out on `discord`_ in the `open tasks thread`_! diff --git a/docs/overview/contributing/setting_up.rst b/docs/overview/contributing/setting_up.rst index 0a541c646a24d..fa329b7358713 100644 --- a/docs/overview/contributing/setting_up.rst +++ b/docs/overview/contributing/setting_up.rst @@ -3,10 +3,10 @@ Setting Up .. _`repo`: https://github.com/unifyai/ivy .. _`discord`: https://discord.gg/sXyFF8tDtm -.. _`pycharm channel`: https://discord.com/channels/799879767196958751/942114831039856730 -.. _`docker channel`: https://discord.com/channels/799879767196958751/942114744691740772 -.. _`pre-commit channel`: https://discord.com/channels/799879767196958751/982725464110034944 -.. _`pip packages channel`: https://discord.com/channels/799879767196958751/942114789642080317 +.. _`pycharm thread`: https://discord.com/channels/799879767196958751/1186628916522262629 +.. _`docker thread`: https://discord.com/channels/799879767196958751/1186629067966009424 +.. _`pre-commit thread`: https://discord.com/channels/799879767196958751/1186629635694399539 +.. _`pip packages thread`: https://discord.com/channels/799879767196958751/1186629837515935765 .. _`miniconda`: https://docs.conda.io/en/latest/miniconda.html .. _`venv`: https://docs.python.org/3/library/venv.html .. _`ivy/scripts`: https://github.com/unifyai/ivy/tree/bcddc79978afe447958dfa3ea660716845c85846/scripts @@ -66,7 +66,7 @@ In order to install and properly set up pre-commit, these steps should be follow That's it! Now when you make a commit, the pre-commit hooks will all be run correctly, as explained above. -For questions, please reach out on `discord`_ in the `pre-commit channel`_! +For questions, please reach out on `discord`_ in the `pre-commit thread`_! PyCharm @@ -83,7 +83,7 @@ Many people seem to miss this option, so we thought we would add an explicit rem #. To continue using PyCharm Professional, you can use the trial version making a jetbrains account but that would be only valid for 1 month. #. After the trial expires you have to buy the paid version of PyCharm Professional. -For questions, please reach out on `discord`_ in the `pycharm channel`_! +For questions, please reach out on `discord`_ in the `pycharm thread`_! Virtual environments - No Docker -------------------------------- @@ -231,8 +231,8 @@ This is a builtin package and doesn't require explicit installation. .. code-block:: none - wget http://nz2.archive.ubuntu.com/ubuntu/pool/main/o/openssl/libssl1.1_1.1.1f-1ubuntu2.19_amd64.deb - sudo dpkg -i libssl1.1_1.1.1f-1ubuntu2.19_amd64.deb + wget http://nz2.archive.ubuntu.com/ubuntu/pool/main/o/openssl/libssl1.1_1.1.1f-1ubuntu2.20_amd64.deb + sudo dpkg -i libssl1.1_1.1.1f-1ubuntu2.20_amd64.deb PS: If the link gets expired at some point in the future, check http://nz2.archive.ubuntu.com/ubuntu/pool/main/o/openssl/?C=M;O=D for a valid one. @@ -445,7 +445,7 @@ This is a common error which you might face. If you are not successfully able to sudo chmod a+rwx /var/run/docker.pid -For questions, please reach out on `discord`_ in the `docker channel`_! +For questions, please reach out on `discord`_ in the `docker thread`_! **Video** @@ -560,7 +560,7 @@ Now, if Hypothesis detects an error in the code it will return more detailed inf .. image:: https://raw.githubusercontent.com/unifyai/unifyai.github.io/main/img/externally_linked/contributing/setting_up/more_detailed_hypothesis_logs/detailed_hypothesis_example.png?raw=true :width: 420 -For questions, please reach out on `discord`_ in the `docker channel`_! +For questions, please reach out on `discord`_ in the `docker thread`_! **"Empty Suite" error fix:** @@ -650,7 +650,7 @@ the steps explained below will help you in setting up a less resource-intensive pip install git+https://github.com/unifyai/ivy.git -#. If you want to set up a local repository, you can do so by following :ref:`this guide ` +#. Or else, if you want to set up a local repository, you can do so by following :ref:`this guide ` as explained above and install the required development dependencies by running: .. code-block:: none @@ -660,6 +660,7 @@ the steps explained below will help you in setting up a less resource-intensive .. code-block:: none pip install -r requirements/requirements.txt + pip install -r requirements/optional.txt #. Once done, you can now open VSCode right from your terminal and get started with your development by just running: @@ -715,7 +716,7 @@ Just follow the steps outlined below: - :code:`Default project configuration` - This is the default option, it will set up with the default codespaces environment. - :code:`Ivy Development Environment (build)` - This will set up the development environment of ivy for CPU and build image from :code:`ivy/docker/Dockerfile`. - - :code:`Ivy GPU Development Environment (build)` - This will set up the development environment of ivy for GPU and build image from :code:`ivy/docker/DockerfileGPUMultiCuda`. + - :code:`Ivy GPU Development Environment (build)` - This will set up the development environment of ivy for GPU and build image from :code:`ivy/docker/DockerfileGPU`. - :code:`Ivv Development Environment for Multiver...` - This will set up the development environment of multiversion support with ivy and build image from :code:`ivy/docker/DockerfileMultiversion`. - :code:`Ivy Development Environment (image)` - This will set up the development environment of ivy for CPU and build image from the latest image from dockerhub. - :code:`Ivy GPU Development Environment (image)` - This will set up the development environment of ivy for GPU and build image from the latest image from dockerhub. @@ -893,4 +894,4 @@ Running a :code:`pip install -e .` is sufficient to download the binaries if the This should have hopefully given you a good understanding of how to get things properly set up. -If you have any questions, please feel free to reach out on `discord`_ in the `pycharm channel`_, `docker channel`_, `pre-commit channel`_, `pip packages channel`_ depending on the question! +If you have any questions, please feel free to reach out on `discord`_ in the `pycharm thread`_, `docker thread`_, `pre-commit thread`_, `pip packages thread`_ depending on the question! diff --git a/docs/overview/contributing/the_basics.rst b/docs/overview/contributing/the_basics.rst index dd43ce0ae0a19..7f2add42f6967 100644 --- a/docs/overview/contributing/the_basics.rst +++ b/docs/overview/contributing/the_basics.rst @@ -3,11 +3,10 @@ The Basics .. _`repo`: https://github.com/unifyai/ivy .. _`discord`: https://discord.gg/sXyFF8tDtm -.. _`todo list issues channel`: https://discord.com/channels/799879767196958751/982728618469912627 +.. _`todo list issues thread`: https://discord.com/channels/799879767196958751/1189903501011202128 .. _`Atlassian tutorial`: https://www.atlassian.com/git/tutorials/saving-changes/git-stash -.. _`fork management channel`: https://discord.com/channels/799879767196958751/982728689408167956 +.. _`fork management thread`: https://discord.com/channels/799879767196958751/1189903708465672272 .. _`pull requests channel`: https://discord.com/channels/799879767196958751/982728733859414056 -.. _`commit frequency channel`: https://discord.com/channels/799879767196958751/982728822317256712 .. _`PyCharm blog`: https://www.jetbrains.com/help/pycharm/finding-and-replacing-text-in-file.html .. _`Debugging`: https://www.jetbrains.com/help/pycharm/debugging-code.html @@ -53,7 +52,7 @@ We make extensive use of `ToDo list issues `_ as a Contributor. +Let's innovate together! + +We've created a promotion workflow to help you advance through the different tiers of contribution, +from Contributor to Core Contributor, Rising Contributor, and finally, Top Contributor. + +Our promotion structure is based on our badge system. +Check out `Contributor Rewards `_ for more information about them! + +Contributor +----------- +Start as a Contributor by earning any of the Initial Badges. +It's straightforward โ€” complete one of the open tasks listed and you're in! +This first step opens the door for you to become an integral part of our community. + +Core Contributor +---------------- +Get elevated to Core Contributor status by earning a Bronze Badge. +As a Core Contributor, you're recognized not just for your skills but also for your growing commitment to our mission. +You'll have the opportunity to engage more deeply with our projects and play an important role in shaping the future of our initiatives. +This tier is a testament to your dedication and a stepping stone to even greater achievements within our community. +As a token of appreciation, you'll be eligible for a $25 welcome gift. + +Rising Contributor +------------------ +Ascend to the Rising Contributor level by acquiring a Silver Badge. +This tier will allow you to be more deeply involved with our core group. +You'll join our GitHub team, enabling you to directly commit changes to :code:`main`, manage PRs made by others in the community, etc. +You'll also be invited to all our internal meetings to be able to follow along with everything happening in the team. +As a Rising Contributor, you're encouraged to tackle complex tasks, pushing your skills to new heights. + +Top Contributor +--------------- +Achieve a Gold Badge to reach the peak of our program as a Top Contributor. +This tier is for those who demonstrate exceptional dedication and expertise. +You'll gain the privilege of engaging with bounty-holding internal tasks and join our Bounty Program, +where completing top-priority issues can earn you cash rewards. +Upon reaching this level, we will be delighted to acknowledge your contributions with a special token of appreciation. diff --git a/docs/overview/deep_dive/array_api_tests.rst b/docs/overview/deep_dive/array_api_tests.rst index 3a6aa29a8d67b..383c3e30098a0 100644 --- a/docs/overview/deep_dive/array_api_tests.rst +++ b/docs/overview/deep_dive/array_api_tests.rst @@ -7,7 +7,7 @@ Array API Tests .. _`for each backend`: https://github.com/unifyai/ivy/tree/20d07d7887766bb0d1707afdabe6e88df55f27a5/.github/workflows .. _`repo`: https://github.com/unifyai/ivy .. _`discord`: https://discord.gg/sXyFF8tDtm -.. _`array api tests channel`: https://discord.com/channels/799879767196958751/982738404611592256 +.. _`array api tests thread`: https://discord.com/channels/799879767196958751/1189907361494741073 .. _`scripts/shell/test_array_api.sh`: https://github.com/unifyai/ivy/blob/bcddc79978afe447958dfa3ea660716845c85846/scripts/shell/test_array_api.sh .. _`array-api test repository`: https://github.com/data-apis/array-api/tree/main .. _`issue`: https://github.com/numpy/numpy/issues/21213 @@ -204,7 +204,7 @@ The fact that the skip instruction itself contains the exact input conditions th This should have hopefully given you a good understanding of how the Array API test suite is used for testing Ivy. -If you have any questions, please feel free to reach out on `discord`_ in the `array api tests channel`_! +If you have any questions, please feel free to reach out on `discord`_ in the `array api tests thread`_! **Video** diff --git a/docs/overview/deep_dive/arrays.rst b/docs/overview/deep_dive/arrays.rst index 02dccc5352c56..83ee85f9d9026 100644 --- a/docs/overview/deep_dive/arrays.rst +++ b/docs/overview/deep_dive/arrays.rst @@ -21,7 +21,7 @@ Arrays .. _`__truediv__`: https://github.com/unifyai/ivy/blob/e4d9247266f5d99faad59543923bb24b88a968d9/ivy/array/__init__.py#L319 .. _`repo`: https://github.com/unifyai/ivy .. _`discord`: https://discord.gg/sXyFF8tDtm -.. _`arrays channel`: https://discord.com/channels/799879767196958751/933380487353872454 +.. _`arrays thread`: https://discord.com/channels/799879767196958751/1189905906905919609 .. _`wrapped logic`: https://github.com/unifyai/ivy/blob/6a729004c5e0db966412b00aa2fce174482da7dd/ivy/func_wrapper.py#L95 .. _`NumPy's`: https://numpy.org/doc/stable/user/basics.dispatch.html#basics-dispatch .. _`PyTorch's`: https://pytorch.org/docs/stable/notes/extending.html#extending-torch @@ -176,7 +176,7 @@ It is relevant to mention again that any function not stored inside the dict :co This should have hopefully given you a good feel for the different types of arrays, and how these are handled in Ivy. -If you have any questions, please feel free to reach out on `discord`_ in the `arrays channel`_! +If you have any questions, please feel free to reach out on `discord`_ in the `arrays thread`_! **Video** diff --git a/docs/overview/deep_dive/backend_setting.rst b/docs/overview/deep_dive/backend_setting.rst index b2be3a2f0a7a5..18e89197b684c 100644 --- a/docs/overview/deep_dive/backend_setting.rst +++ b/docs/overview/deep_dive/backend_setting.rst @@ -8,7 +8,7 @@ Backend Setting .. _`wrap the functions`: https://github.com/unifyai/ivy/blob/1eb841cdf595e2bb269fce084bd50fb79ce01a69/ivy/backend_handler.py#L204 .. _`repo`: https://github.com/unifyai/ivy .. _`discord`: https://discord.gg/sXyFF8tDtm -.. _`backend setting channel`: https://discord.com/channels/799879767196958751/982737886963187772 +.. _`backend setting thread`: https://discord.com/channels/799879767196958751/1189905734645850254 The backend framework can either be set by calling :code:`ivy.set_backend(backend_name)` or it can inferred from the arguments. For the latter, a global variable `implicit_backend`_ is located in the file which is initialized as numpy, and is always used to infer the backend in cases where: (a) no backend has been set using the :code:`set_backend` function and (b) the backend cannot be inferred from the inputs. @@ -57,22 +57,19 @@ In addition, all the previously set backends can be cleared by calling :func:`iv Dynamic Backend Setting ----------------------- -.. _`ivy.set_dynamic_backend`: https://github.com/unifyai/ivy/blob/main/ivy/__init__.py#L1134. -.. _`ivy.unset_dynamic_backend`: https://github.com/unifyai/ivy/blob/main/ivy/__init__.py#L1143. -.. _`ivy.dynamic_backend_as`: https://github.com/unifyai/ivy/blob/main/ivy/__init__.py#L1174. -.. _`ivy.Array`: https://github.com/unifyai/ivy/blob/main/ivy/data_classes/array/array.py#L186. -.. _`ivy.Container`: https://github.com/unifyai/ivy/blob/main/ivy/data_classes/container/base.py#L4166. -.. _`converted to numpy`: https://github.com/unifyai/ivy/blob/main/ivy/utils/backend/handler.py#L283. -.. _`converted from numpy`: https://github.com/unifyai/ivy/blob/main/ivy/utils/backend/handler.py#L363. +.. _`ivy.set_dynamic_backend`: https://github.com/unifyai/ivy/blob/e2b0b1d7fcd454f12bfae94b03213457460276c8/ivy/__init__.py#L1150. +.. _`ivy.unset_dynamic_backend`: https://github.com/unifyai/ivy/blob/e2b0b1d7fcd454f12bfae94b03213457460276c8/ivy/__init__.py#L1187. +.. _`ivy.dynamic_backend_as`: https://github.com/unifyai/ivy/blob/e2b0b1d7fcd454f12bfae94b03213457460276c8/ivy/__init__.py#L1190. +.. _`ivy.Array`: https://github.com/unifyai/ivy/blob/e2b0b1d7fcd454f12bfae94b03213457460276c8/ivy/data_classes/array/array.py#L190. +.. _`ivy.Container`: https://github.com/unifyai/ivy/blob/e2b0b1d7fcd454f12bfae94b03213457460276c8/ivy/data_classes/container/base.py#L4285. +.. _`dynamic_backend_converter`: https://github.com/unifyai/ivy/blob/e2b0b1d7fcd454f12bfae94b03213457460276c8/ivy/utils/backend/handler.py#L252. Working with different backends in Ivy can be challenging, especially when you need to switch between backends frequently. To make this easier, users can make use of the dynamic backend attribute of :class:`ivy.Array` and :class:`ivy.Container` classes which allow you to automatically convert ivy arrays to the new backend whenever the backend is changed. Essentially, when the user calls :code:`ivy.set_backend(, dynamic=True)`, the following steps are performed: #. First, all live objects in the current project scope are found and then filtered to only include :class:`ivy.Array`/:class:`ivy.Container` objects. -#. Then, these objects are iterated through and `converted to numpy`_ as an intermediary using the current backend. -#. Next, the global :code:`ivy.__dict__` is updated to the new backend as mentioned in the Backend Setting section above. -#. Finally, the objects are `converted from numpy`_ to the target backend using the newly set backend. +#. Then, these objects are iterated through and converted to the target backend using DLPack or numpy as an intermediary. By default, the dynamic backend attribute is set to True when you create an ivy array (e.g., :code:`x = ivy.array([1,2,3])`), but the attribute is mutable and can be changed after the ivy array is created (e.g., :code:`x.dynamic_backend= True`). Here's an example to illustrate how this works in practice: @@ -91,7 +88,7 @@ Here's an example to illustrate how this works in practice: x.data # will be a jax array y.data # will still be a torch tensor since dynamic_backend=False -In addition to setting the dynamic backend attribute for individual ivy arrays, you can also set or unset the dynamic backend feature globally for all such instances using `ivy.set_dynamic_backend`_ and `ivy.unset_dynamic_backend`_ respectively. +Setting the attribute to True converts the array to the current backend even if the backend was set with `dynamic=False`. In addition to setting the dynamic backend attribute for individual ivy arrays, you can also set or unset the dynamic backend feature globally for all such instances using `ivy.set_dynamic_backend`_ and `ivy.unset_dynamic_backend`_ respectively. Another useful feature of the dynamic backend is the `ivy.dynamic_backend_as`_ context manager. This allows you to write code like this: @@ -107,25 +104,6 @@ Another useful feature of the dynamic backend is the `ivy.dynamic_backend_as`_ c This makes it easy to define different sections of your project with different settings, without having to explicitly call :code:`ivy.set_` and :code:`ivy.unset_` etc. -There is one technical point to keep in mind when using the dynamic backend attribute. Consider the following example: - -.. code-block:: python - - ivy.set_backend("tensorflow") - arr = ivy.array([1,2,3]) - arr.dynamic_backend= False - - ivy.set_backend("torch") - - # arr.data should still be a tf.Tensor - - arr.dynamic_backend = True - - ivy.set_backend("jax") - - # This would cause a problem since the conversion goes from TF -> JAX, whereas the backend stack goes from Torch -> Jax. - -To avoid the above issue, we update the :attr:`.data` attribute to be a native array for the current set backend framework in the setter method for dynamic_backend attribute for `ivy.Array`_ and `ivy.Container`_ classes. So after the line :code:`arr.dynamic_backend = True` in the example above, then :attr:`arr.data` would be a torch.Tensor and not a tf.Tensor. Backend and Frontend Version Support ------------------------------------ @@ -151,7 +129,7 @@ If the user's system doesn't have the backend framework installed, we default to This should have hopefully given you a good feel for how the backend framework is set. -If you have any questions, please feel free to reach out on `discord`_ in the `backend setting channel`_! +If you have any questions, please feel free to reach out on `discord`_ in the `backend setting thread`_! **Video** diff --git a/docs/overview/deep_dive/containers.rst b/docs/overview/deep_dive/containers.rst index bfcc94e048bbe..5ffa466429872 100644 --- a/docs/overview/deep_dive/containers.rst +++ b/docs/overview/deep_dive/containers.rst @@ -31,7 +31,7 @@ Containers .. _`__truediv__`: https://github.com/unifyai/ivy/blob/b725ed10bca15f6f10a0e5154af10231ca842da2/ivy/container/container.py#L399 .. _`repo`: https://github.com/unifyai/ivy .. _`discord`: https://discord.gg/sXyFF8tDtm -.. _`containers channel`: https://discord.com/channels/799879767196958751/982738042886422598 +.. _`containers thread`: https://discord.com/channels/799879767196958751/1189906066549506048 The `ivy.Container`_ inherits from `dict`_, and is useful for storing nested data. @@ -334,7 +334,7 @@ This is for three reasons, (a) the key chain :code:`g` is not shared by any cont This should have hopefully given you a good feel for containers, and how these are handled in Ivy. -If you have any questions, please feel free to reach out on `discord`_ in the `containers channel`_! +If you have any questions, please feel free to reach out on `discord`_ in the `containers thread`_! **Video** diff --git a/docs/overview/deep_dive/continuous_integration.rst b/docs/overview/deep_dive/continuous_integration.rst index 9653ddd175da9..09c63c4fd4f5b 100644 --- a/docs/overview/deep_dive/continuous_integration.rst +++ b/docs/overview/deep_dive/continuous_integration.rst @@ -1,7 +1,7 @@ Continuous Integration ====================== -.. _`continuous integration channel`: https://discord.com/channels/799879767196958751/1028268051776413759 +.. _`continuous integration channel`: https://discord.com/channels/799879767196958751/1189908611208597544 .. _`discord`: https://discord.gg/sXyFF8tDtm We follow the practice of Continuous Integration (CI), in order to regularly build and test code at Ivy. @@ -397,7 +397,7 @@ You can filter tests by selecting choices from the various dropdowns. The link c This should have hopefully given you a good feel for how Continuous Integration works in Ivy. -If you have any questions, please feel free to reach out on `discord`_ in the `continuous integration channel`_! +If you have any questions, please feel free to reach out on `discord`_ in the `continuous integration thread`_! **Video** diff --git a/docs/overview/deep_dive/data_types.rst b/docs/overview/deep_dive/data_types.rst index 8e2c7a596c635..bbf15ebd1839e 100644 --- a/docs/overview/deep_dive/data_types.rst +++ b/docs/overview/deep_dive/data_types.rst @@ -24,7 +24,7 @@ Data Types .. _`ivy.set_default_dtype`: https://github.com/unifyai/ivy/blob/8482eb3fcadd0721f339a1a55c3f3b9f5c86d8ba/ivy/functional/ivy/data_type.py#L1555 .. _`repo`: https://github.com/unifyai/ivy .. _`discord`: https://discord.gg/sXyFF8tDtm -.. _`data types channel`: https://discord.com/channels/799879767196958751/982738078445760532 +.. _`data type thread`: https://discord.com/channels/799879767196958751/1190234670806351892 The data types supported by Ivy are as follows: @@ -423,7 +423,7 @@ set of dtypes is not supported by a certain device. .. code-block:: python - @with_unsupported_device_and_dtypes({"2.5.1 and below": {"cpu": ("int8", "int16", "uint8")}}, backend_version) + @with_unsupported_device_and_dtypes({"2.6.0 and below": {"cpu": ("int8", "int16", "uint8")}}, backend_version) def gcd( x1: Union[paddle.Tensor, int, list, tuple], x2: Union[paddle.Tensor, float, list, tuple], @@ -739,7 +739,7 @@ As with all superset design decisions, this behavior makes it much easier to sup This should have hopefully given you a good feel for data types, and how these are handled in Ivy. -If you have any questions, please feel free to reach out on `discord`_ in the `data types channel`_! +If you have any questions, please feel free to reach out on `discord`_ in the `data types thread`_! **Video** diff --git a/docs/overview/deep_dive/devices.rst b/docs/overview/deep_dive/devices.rst index 2b68f1bbabec1..33636fdee3b6f 100644 --- a/docs/overview/deep_dive/devices.rst +++ b/docs/overview/deep_dive/devices.rst @@ -25,7 +25,7 @@ Devices .. _`ivy.unset_default_device()`: https://github.com/unifyai/ivy/blob/2f90ce7b6a4c8ddb7227348d58363cd2a3968602/ivy/functional/ivy/device.py#L869 .. _`repo`: https://github.com/unifyai/ivy .. _`discord`: https://discord.gg/sXyFF8tDtm -.. _`devices channel`: https://discord.com/channels/799879767196958751/982738108166602752 +.. _`devices thread`: https://discord.com/channels/799879767196958751/1189906353653817354 The devices currently supported by Ivy are as follows: @@ -270,7 +270,7 @@ There are some functions(mostly creation function) which accept a :code:`device` This should have hopefully given you a good feel for devices, and how these are handled in Ivy. -If you have any questions, please feel free to reach out on `discord`_ in the `devices channel`_! +If you have any questions, please feel free to reach out on `discord`_ in the `devices thread`_! **Video** diff --git a/docs/overview/deep_dive/docstring_examples.rst b/docs/overview/deep_dive/docstring_examples.rst index 1debbc8d67963..5ca12840e0534 100644 --- a/docs/overview/deep_dive/docstring_examples.rst +++ b/docs/overview/deep_dive/docstring_examples.rst @@ -3,7 +3,7 @@ Docstring Examples .. _`repo`: https://github.com/unifyai/ivy .. _`discord`: https://discord.gg/sXyFF8tDtm -.. _`docstring examples channel`: https://discord.com/channels/799879767196958751/982738352103129098 +.. _`docstring examples thread`: https://discord.com/channels/799879767196958751/1189906990307233822 After writing the general docstrings, the final step is to add helpful examples to the docstrings. @@ -747,7 +747,7 @@ Passing docstring tests is a necessary but not sufficient condition for the comp These three examples should give you a good understanding of what is required when adding docstring examples. -If you have any questions, please feel free to reach out on `discord`_ in the `docstring examples channel`_! +If you have any questions, please feel free to reach out on `discord`_ in the `docstring examples thread`_! **Video** diff --git a/docs/overview/deep_dive/docstrings.rst b/docs/overview/deep_dive/docstrings.rst index ead0f7a5b19c4..5e83f4face088 100644 --- a/docs/overview/deep_dive/docstrings.rst +++ b/docs/overview/deep_dive/docstrings.rst @@ -5,7 +5,7 @@ Docstrings .. _`spec/API_specification/array_api`: https://github.com/data-apis/array-api/blob/main .. _`repo`: https://github.com/unifyai/ivy .. _`discord`: https://discord.gg/sXyFF8tDtm -.. _`docstrings channel`: https://discord.com/channels/799879767196958751/982738313897197600 +.. _`docstrings thread`: https://discord.com/channels/799879767196958751/1189906836426596412 All functions in the Ivy API at :mod:`ivy/functional/ivy/category_name.py` should have full and thorough docstrings. @@ -193,7 +193,7 @@ Therefore, with the exception of the :class:`ivy.Array` and :class:`ivy.Containe These examples should hopefully give you a good understanding of what is required when adding docstings. -If you have any questions, please feel free to reach out on `discord`_ in the `docstrings channel`_! +If you have any questions, please feel free to reach out on `discord`_ in the `docstrings thread`_! **Video** diff --git a/docs/overview/deep_dive/exception_handling.rst b/docs/overview/deep_dive/exception_handling.rst index 55313c46b00a4..2ad306b06f03a 100644 --- a/docs/overview/deep_dive/exception_handling.rst +++ b/docs/overview/deep_dive/exception_handling.rst @@ -1,7 +1,7 @@ Exception Handling ================== -.. _`exception handling channel`: https://discord.com/channels/799879767196958751/1028267924043092068 +.. _`exception handling thread`: https://discord.com/channels/799879767196958751/1189908450570928149 .. _`discord`: https://discord.gg/sXyFF8tDtm As Ivy is unifying multiple backends, various issues are seen during exception handling: @@ -545,7 +545,7 @@ Instead of coding a conditional block and raising an exception if the conditions This should have hopefully given you a good feel for how function wrapping is applied to functions in Ivy. -If you have any questions, please feel free to reach out on `discord`_ in the `exception handling channel`_! +If you have any questions, please feel free to reach out on `discord`_ in the `exception handling thread`_! **Video** diff --git a/docs/overview/deep_dive/fix_failing_tests.rst b/docs/overview/deep_dive/fix_failing_tests.rst index c2dc97832636c..f86dfc62cc99e 100644 --- a/docs/overview/deep_dive/fix_failing_tests.rst +++ b/docs/overview/deep_dive/fix_failing_tests.rst @@ -5,17 +5,17 @@ Fix Failing Tests: .. _`issues`: https://github.com/unifyai/ivy/issues?q=is%3Aopen+is%3Aissue+label%3A%22Failing+Test%22 .. _`issue`: https://github.com/unifyai/ivy/issues/25849 .. _`discord`: https://discord.gg/sXyFF8tDtm -.. _`docker channel`: https://discord.com/channels/799879767196958751/942114744691740772 +.. _`docker thread`: https://discord.com/channels/799879767196958751/1186629067966009424 .. _`miniconda`: https://docs.conda.io/en/latest/miniconda.html .. _`venv`: https://docs.python.org/3/library/venv.html .. _`ivy/scripts/shell`: https://github.com/unifyai/ivy/tree/f71a414417646e1dfecb5de27fb555f80333932c/scripts/shell .. _`platform compatibility tags`: https://packaging.python.org/en/latest/specifications/platform-compatibility-tags/ .. _`logging level`: https://docs.python.org/3/library/logging.html#logging.Logger.setLevel -.. _`pycharm channel`: https://discord.com/channels/799879767196958751/942114831039856730 -.. _`pre-commit channel`: https://discord.com/channels/799879767196958751/982725464110034944 -.. _`pip packages channel`: https://discord.com/channels/799879767196958751/942114789642080317 -.. _`ivy tests channel`: https://discord.com/channels/799879767196958751/982738436383445073 -.. _`ivy frontend tests channel`: https://discord.com/channels/799879767196958751/1028267758028337193 +.. _`pycharm thread`: https://discord.com/channels/799879767196958751/1186628916522262629 +.. _`pre-commit thread`: https://discord.com/channels/799879767196958751/1186629635694399539 +.. _`pip packages thread`: https://discord.com/channels/799879767196958751/1186629837515935765 +.. _`ivy tests thread`: https://discord.com/channels/799879767196958751/1189907526226034698 +.. _`ivy frontend tests thread`: https://discord.com/channels/799879767196958751/1190246804940402738 We're really happy you'd like to learn how to contribute towards Ivy ๐Ÿ™‚ @@ -307,4 +307,4 @@ This section aims to assist you in navigating through some common errors you mig Where to ask for Help ********************* -The best place to ask for help is our `discord`_ server in the relevant channels. For instance, lets say you're facing an issue with :code:`test_jax_transpose` function, in this case you should post your query in the `ivy frontend tests channel`_. +The best place to ask for help is our `discord`_ server in the relevant channels. For instance, lets say you're facing an issue with :code:`test_jax_transpose` function, in this case you should post your query in the `ivy frontend tests thread`_. diff --git a/docs/overview/deep_dive/formatting.rst b/docs/overview/deep_dive/formatting.rst index f970f8e0c24d2..9cb5d4b15cbf4 100644 --- a/docs/overview/deep_dive/formatting.rst +++ b/docs/overview/deep_dive/formatting.rst @@ -3,7 +3,7 @@ Formatting .. _`flake8`: https://flake8.pycqa.org/en/latest/index.html .. _`black`: https://black.readthedocs.io/en/stable/index.html -.. _`formatting channel`: https://discord.com/channels/799879767196958751/1028266706436624456 +.. _`formatting thread`: https://discord.com/channels/799879767196958751/1190247322626572408 .. _`discord`: https://discord.gg/sXyFF8tDtm Currently, Ivy follows the `black`_ code style, and `flake8`_ formatter in order to ensure that our code is consistent, @@ -192,7 +192,7 @@ another try, or manually resolve the formatting errors by committing the changes This should have hopefully given you a good feel for what is our coding style and how to format your code to contribute to Ivy. -If you have any questions, please feel free to reach out on `discord`_ in the `formatting channel`_! +If you have any questions, please feel free to reach out on `discord`_ in the `formatting thread`_! **Video** diff --git a/docs/overview/deep_dive/function_arguments.rst b/docs/overview/deep_dive/function_arguments.rst index 988db211600ec..60888fdb0335e 100644 --- a/docs/overview/deep_dive/function_arguments.rst +++ b/docs/overview/deep_dive/function_arguments.rst @@ -5,7 +5,7 @@ Function Arguments .. _`spec/API_specification/signatures`: https://github.com/data-apis/array-api/tree/main/spec/2022.12/API_specification .. _`repo`: https://github.com/unifyai/ivy .. _`discord`: https://discord.gg/sXyFF8tDtm -.. _`function arguments channel`: https://discord.com/channels/799879767196958751/982738240354254898 +.. _`function arguments thread`: https://discord.com/channels/799879767196958751/1190247823275470978 .. _`Array API Standard convention`: https://data-apis.org/array-api/2021.12/API_specification/array_object.html#api-specification-array-object--page-root Here, we explain how the function arguments differ between the placeholder implementation at :mod:`ivy/functional/ivy/category_name.py`, and the backend-specific implementation at :mod:`ivy/functional/backends/backend_name/category_name.py`. @@ -210,7 +210,7 @@ Therefore, we simply omit these :class:`ivy.Container` type hints from *nestable These examples should hopefully give you a good understanding of what is required when adding function arguments. -If you have any questions, please feel free to reach out on `discord`_ in the `function arguments channel`_! +If you have any questions, please feel free to reach out on `discord`_ in the `function arguments thread`_! **Video** diff --git a/docs/overview/deep_dive/function_types.rst b/docs/overview/deep_dive/function_types.rst index d2bc16af271f8..c00d2839c73b5 100644 --- a/docs/overview/deep_dive/function_types.rst +++ b/docs/overview/deep_dive/function_types.rst @@ -33,7 +33,7 @@ Function Types .. _`handle`: https://github.com/unifyai/ivy/blob/0ef2888cbabeaa8f61ce8aaea4f1175071f7c396/ivy/func_wrapper.py#L1027-L1030 .. _`repo`: https://github.com/unifyai/ivy .. _`discord`: https://discord.gg/sXyFF8tDtm -.. _`function types channel`: https://discord.com/channels/799879767196958751/982737839861145630 +.. _`function types thread`: https://discord.com/channels/799879767196958751/1189905318650576896 Firstly, we explain the difference between *primary*, *compositional*, *mixed* and *standalone* functions. These four function categorizations are all **mutually exclusive**, and combined they constitute the set of **all** functions in Ivy, as outlined in the simple Venn diagram below. @@ -249,7 +249,7 @@ Feel free to have a look through all of the `submodules`_, you should be able to This should have hopefully given you a good feel for the different function types. -If you have any questions, please feel free to reach out on `discord`_ in the `function types channel`_! +If you have any questions, please feel free to reach out on `discord`_ in the `function types thread`_! **Video** diff --git a/docs/overview/deep_dive/function_wrapping.rst b/docs/overview/deep_dive/function_wrapping.rst index 8a585244222e6..5cee12cd1a25d 100644 --- a/docs/overview/deep_dive/function_wrapping.rst +++ b/docs/overview/deep_dive/function_wrapping.rst @@ -24,7 +24,7 @@ Function Wrapping .. _`handle_complex_input`: https://github.com/unifyai/ivy/blob/bd9b5b1080d33004e821a48c486b3a879b9d6616/ivy/func_wrapper.py#L1393 .. _`repo`: https://github.com/unifyai/ivy .. _`discord`: https://discord.gg/sXyFF8tDtm -.. _`function wrapping channel`: https://discord.com/channels/799879767196958751/982737993028755496 +.. _`function wrapping thread`: https://discord.com/channels/799879767196958751/1189906704775794688 .. _`handle_partial_mixed_function`: https://github.com/unifyai/ivy/blob/5658401b266352d3bf72c95e4af6ae9233115722/ivy/func_wrapper.py#L944 .. _`stored as an attribute`: https://github.com/unifyai/ivy/blob/5658401b266352d3bf72c95e4af6ae9233115722/ivy/func_wrapper.py#L1054 .. _`ivy.linear`: https://github.com/unifyai/ivy/blob/5658401b266352d3bf72c95e4af6ae9233115722/ivy/functional/ivy/layers.py#L81 @@ -151,7 +151,7 @@ For now, suffice it to say that they do quite a lot. This should have hopefully given you a good feel for how function wrapping is applied to functions in Ivy. -If you have any questions, please feel free to reach out on `discord`_ in the `function wrapping channel`_! +If you have any questions, please feel free to reach out on `discord`_ in the `function wrapping thread`_! **Video** diff --git a/docs/overview/deep_dive/gradients.rst b/docs/overview/deep_dive/gradients.rst index bd502228f5031..2ae91e75aedf1 100644 --- a/docs/overview/deep_dive/gradients.rst +++ b/docs/overview/deep_dive/gradients.rst @@ -2,7 +2,7 @@ Gradients ========= .. _`discord`: https://discord.gg/sXyFF8tDtm -.. _`gradients channel`: https://discord.com/channels/799879767196958751/1000043921633722509 +.. _`gradients thread`: https://discord.com/channels/799879767196958751/1190235826806853672 Overview -------- @@ -172,7 +172,7 @@ Framework-specific Considerations This should have hopefully given you a good feel for how the gradient API is implemented in Ivy. -If you have any questions, please feel free to reach out on `discord`_ in the `gradients channel`_! +If you have any questions, please feel free to reach out on `discord`_ in the `gradients thread`_! **Video** diff --git a/docs/overview/deep_dive/inplace_updates.rst b/docs/overview/deep_dive/inplace_updates.rst index a2a4019a8e106..17bfa0aca2c7b 100644 --- a/docs/overview/deep_dive/inplace_updates.rst +++ b/docs/overview/deep_dive/inplace_updates.rst @@ -18,7 +18,7 @@ Inplace Updates .. _`ivy.asarray`: https://github.com/unifyai/ivy/blob/8482eb3fcadd0721f339a1a55c3f3b9f5c86d8ba/ivy/functional/ivy/creation.py#L114 .. _`repo`: https://github.com/unifyai/ivy .. _`discord`: https://discord.gg/sXyFF8tDtm -.. _`inplace updates channel`: https://discord.com/channels/799879767196958751/1028681763947552778 +.. _`inplace updates thread`: https://discord.com/channels/799879767196958751/1189906590166437938 .. _`example`: https://github.com/unifyai/ivy/blob/0ef2888cbabeaa8f61ce8aaea4f1175071f7c396/ivy/functional/ivy/layers.py#L169-L176 @@ -511,7 +511,7 @@ Here's a brief description of what happens during an inplace operation with a Py This should have hopefully given you a good feel for inplace updates, and how these are handled in Ivy. -If you have any questions, please feel free to reach out on `discord`_ in the `inplace updates channel`_! +If you have any questions, please feel free to reach out on `discord`_ in the `inplace updates thread`_! **Video** diff --git a/docs/overview/deep_dive/ivy_frontends.rst b/docs/overview/deep_dive/ivy_frontends.rst index ac7f1aab1ea14..c13c69169ae62 100644 --- a/docs/overview/deep_dive/ivy_frontends.rst +++ b/docs/overview/deep_dive/ivy_frontends.rst @@ -16,7 +16,7 @@ Ivy Frontends .. _`torch.tan`: https://pytorch.org/docs/stable/generated/torch.tan.html#torch.tan .. _`YouTube tutorial series`: https://www.youtube.com/watch?v=72kBVJTpzIw&list=PLwNuX3xB_tv-wTpVDMSJr7XW6IP_qZH0t .. _`discord`: https://discord.gg/sXyFF8tDtm -.. _`ivy frontends channel`: https://discord.com/channels/799879767196958751/998782045494976522 +.. _`ivy frontends thread`: https://discord.com/channels/799879767196958751/1189908295041941514 .. _`Array manipulation routines`: https://numpy.org/doc/stable/reference/routines.array-manipulation.html# .. _`Array creation routines`: https://numpy.org/doc/stable/reference/routines.array-creation.html @@ -676,7 +676,7 @@ Unit tests should be written for all aliases. This is arguably a duplication, bu This should hopefully have given you a better grasp on what the Ivy Frontend APIs are for, how they should be implemented, and the things to watch out for! We also have a short `YouTube tutorial series`_ on this as well if you prefer a video explanation! -If you have any questions, please feel free to reach out on `discord`_ in the `ivy frontends channel`_! +If you have any questions, please feel free to reach out on `discord`_ in the `ivy frontends thread`_! **Video** diff --git a/docs/overview/deep_dive/ivy_frontends_tests.rst b/docs/overview/deep_dive/ivy_frontends_tests.rst index 6cdad3a87772d..aacc3c6eefe42 100644 --- a/docs/overview/deep_dive/ivy_frontends_tests.rst +++ b/docs/overview/deep_dive/ivy_frontends_tests.rst @@ -2,7 +2,7 @@ Ivy Frontend Tests ================== .. _`here`: ../design/ivy_as_a_transpiler.rst -.. _`ivy frontends tests channel`: https://discord.com/channels/799879767196958751/1028267758028337193 +.. _`ivy frontends tests thread`: https://discord.com/channels/799879767196958751/1190246804940402738 .. _`test ivy`: https://github.com/unifyai/ivy/tree/db9a22d96efd3820fb289e9997eb41dda6570868/ivy_tests/test_ivy .. _`test_frontend_function`: https://github.com/unifyai/ivy/blob/591ac37a664ebdf2ca50a5b0751a3a54ee9d5934/ivy_tests/test_ivy/helpers.py#L1047 .. _`discord`: https://discord.gg/sXyFF8tDtm @@ -816,7 +816,7 @@ The configuration files are located at: :code:`ivy_tests/test_ivy/test_frontends This should have hopefully given you a good understanding of Ivy Frontend Tests! -If you have any questions, please feel free to reach out on `discord`_ in the `ivy frontends tests channel`_! +If you have any questions, please feel free to reach out on `discord`_ in the `ivy frontends tests thread`_! **Video** diff --git a/docs/overview/deep_dive/ivy_lint.rst b/docs/overview/deep_dive/ivy_lint.rst index a777f110a7470..1ac74dbd30979 100644 --- a/docs/overview/deep_dive/ivy_lint.rst +++ b/docs/overview/deep_dive/ivy_lint.rst @@ -55,4 +55,4 @@ Round Up ``ivy-lint`` stands as a testament to Ivy's commitment to code clarity and uniformity. As the landscape of our needs shifts, we foresee further refining and expanding our suite of formatters. -For all discussions or inquiries, you're always welcome on `discord `_ in the `formatting channel `_. +For all discussions or inquiries, you're always welcome on `discord `_ in the `formatting thread `_. diff --git a/docs/overview/deep_dive/ivy_tests.rst b/docs/overview/deep_dive/ivy_tests.rst index be78008687a57..9b3639dd385df 100644 --- a/docs/overview/deep_dive/ivy_tests.rst +++ b/docs/overview/deep_dive/ivy_tests.rst @@ -47,7 +47,7 @@ Ivy Tests .. _`artifact`: https://docs.github.com/en/actions/using-workflows/storing-workflow-data-as-artifacts .. _`repo`: https://github.com/unifyai/ivy .. _`discord`: https://discord.gg/sXyFF8tDtm -.. _`ivy tests channel`: https://discord.com/channels/799879767196958751/982738436383445073 +.. _`ivy tests thread`: https://discord.com/channels/799879767196958751/1189907526226034698 .. _`test helpers`: https://github.com/unifyai/ivy/tree/main/ivy_tests/test_ivy/helpers/hypothesis_helpers .. _`get_dtypes`: https://github.com/unifyai/ivy/blob/e50f71e283313caa9737f3c284496022ac67b58b/ivy_tests/test_ivy/helpers/hypothesis_helpers/dtype_helpers.py#L60 .. _`dtype_and_values`: https://github.com/unifyai/ivy/blob/e50f71e283313caa9737f3c284496022ac67b58b/ivy_tests/test_ivy/helpers/hypothesis_helpers/array_helpers.py#L83 @@ -63,6 +63,7 @@ Ivy Tests .. _`num_positional_args`: https://github.com/unifyai/ivy/blob/e50f71e283313caa9737f3c284496022ac67b58b/ivy_tests/test_ivy/helpers/testing_helpers.py#L78 .. _`CI Pipeline`: continuous_integration.rst .. _`Hypothesis docs`: https://hypothesis.readthedocs.io/en/latest/data.html#core-strategies +.. _`this`: https://github.com/unifyai/ivy/blob/8dcc33b895240395686db165c710ac31708aa691/ivy_tests/test_ivy/test_functional/test_core/test_general.py#L1650 On top of the Array API `test suite`_, which is included as a submodule mapped to the folder :code:`test_array_api`, there is also a collection of Ivy tests, located in subfolder `test_ivy`_. @@ -221,7 +222,7 @@ Ivy Test Decorators - Why do we need to handle test decorators? -In order to run a test, a lot of pre-processing must be done, e.g. import the function, does it support complex data type? does it run on CPU? how many parameters does it take? are they positional or keyword only, or both? and a lot of information about the function that is being tested, this allows us later to run the test efficiently and in a **complete** way. all of this happens at collecting time. +In order to run a test, a lot of pre-processing must be done, e.g. import the function, does it support complex data type? does it run on CPU? how many parameters does it take? are they positional or keyword only, or both? and a lot of information about the function that is being tested, this allows us later to run the test efficiently and in a **complete** way. All of this happens at collecting time. - What do the handle test decorators do? @@ -241,14 +242,15 @@ This is not an exhaustive list of what the :code:`handle_test` decorators actual - Why do we have multiple handle test decorators? -Having multiple test decorators is mainly for efficiency, `handle_test` could do what `handle_frontend_test` does, it just handles the parameters slightly different, and this can be inferred at run time, but we choose to separate the decorator for general different usages, currently we have 4 separate decorators +Having multiple test decorators is mainly for efficiency, `handle_test` could do what `handle_frontend_test` does, it just handles the parameters slightly different, and this can be inferred at run time, but we choose to separate the decorator for general different usages, currently we have 5 separate decorators 1. :code:`handle_test` 2. :code:`handle_method` 3. :code:`handle_frontend_test` 4. :code:`handle_frontend_method` +5. :code:`handle_example` -One of the few differences between the 4 decorators is that they generate different kinds of flags, some generate more or less, but they all share the same general structure. +One of the few differences between the 5 decorators is that they generate different kinds of flags, some generate more or less, but they all share the same general structure. - Integration @@ -359,6 +361,49 @@ Let's look at the data produced by this strategy -: These values are then unpacked, converted to :class:`ivy.Array` class, with corresponding dtypes. The test then runs on the newly created arrays with specified data types. +Adding Explicit Examples to tests +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In certain cases where we'd like to test certain examples explicitly which are outliers and it isn't feasible to define them as a strategy, +we can use the :code:`@handle_example` decorator. One such example is `this`_ where we need to test `ivy.set_item` with slice objects. + +Hypothesis allows us to test with an explicit example deterministically using the `@example`_ decorator. Our :code:`@handle_example` decorator is a wrapper around this. +Which helps us to use the default values of the test_flags, method_flags allowing us to easily test explicit examples for the ivy functional tests, frontend_tests, methods, and frontend_methods. + +We have to pass one of the following 4 arguments as `True` to the :code:`@handle_example` decorator depending on what test we are dealing with. +1. `test_example` +2. `test_frontend_example` +3. `test_method_example` +4. `test_frontend_method_example` + +The following example shows, how we can use the :code:`@handle_example` decorator to test the one of the frontend functions by adding an explicit example. + +.. code-block:: python + @handle_frontend_test( + fn_tree="paddle.acos", + dtype_and_x=helpers.dtype_and_values(available_dtypes=helpers.get_dtypes("float"),), + ) + @handle_example( + test_frontend_example=True, + dtype_and_x=(["float32"], [np.array(9.0, dtype=np.float32)]), + fn_tree="ivy.functional.frontends.paddle.acos", + test_flags={ + "native_arrays": [True], + "with_copy": True, + "with_out": True, + }, + ) + def test_some_function( + *, + dtype_and_x, + fn_tree, + frontend, + test_flags, + backend_fw, + ): + pass + + Why do we need helper functions? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -895,7 +940,7 @@ This ensures that the given example is always tested while running the test, all This should have hopefully given you a good feel for how the tests are implemented in Ivy. -If you have any questions, please feel free to reach out on `discord`_ in the `ivy tests channel`_! +If you have any questions, please feel free to reach out on `discord`_ in the `ivy tests thread`_! **Video** diff --git a/docs/overview/deep_dive/navigating_the_code.rst b/docs/overview/deep_dive/navigating_the_code.rst index 1fe0e6f256cd7..0bdb82f9418c0 100644 --- a/docs/overview/deep_dive/navigating_the_code.rst +++ b/docs/overview/deep_dive/navigating_the_code.rst @@ -4,7 +4,7 @@ Navigating the Code .. _`Array API Standard`: https://data-apis.org/array-api/latest/ .. _`repo`: https://github.com/unifyai/ivy .. _`discord`: https://discord.gg/sXyFF8tDtm -.. _`navigating the code channel`: https://discord.com/channels/799879767196958751/982737793476345888 +.. _`navigating the code thread`: https://discord.com/channels/799879767196958751/1189905165373935616 .. _`Array API Standard convention`: https://data-apis.org/array-api/2021.12/API_specification/array_object.html#api-specification-array-object--page-root .. _`flake8`: https://flake8.pycqa.org/en/latest/index.html @@ -199,7 +199,7 @@ To have a better idea on this, let's look at an example! In the :func:`full_like` function in :mod:`creation.py`, the types of :code:`fill_value` and :code:`dtype` has to be verified to avoid errors. This check has to be applied to all backends, which means the related code is common and identical. In this case, we can extract the code to be a helper function on its own, placed in its related submodule (:mod:`creation.py` here). -In this example, the helper function is named as :func:`_assert_fill_value_and_dtype_are_compatible`. +In this example, the helper function is named as :func:`check_fill_value_and_dtype_are_compatible`. Then, we import this submodule-specific helper function to the respective backends, where examples for each backend is shown below. @@ -299,7 +299,7 @@ This helps to prevent our work from culminating over a fixed version while strid This should have hopefully given you a good feel for how to navigate the Ivy codebase. -If you have any questions, please feel free to reach out on `discord`_ in the `navigating the code channel`_! +If you have any questions, please feel free to reach out on `discord`_ in the `navigating the code thread`_! **Video** diff --git a/docs/overview/deep_dive/superset_behaviour.rst b/docs/overview/deep_dive/superset_behaviour.rst index 8a68e61eed23d..d2e9e940cdc44 100644 --- a/docs/overview/deep_dive/superset_behaviour.rst +++ b/docs/overview/deep_dive/superset_behaviour.rst @@ -3,7 +3,7 @@ Superset Behaviour .. _`Array API Standard`: https://data-apis.org/array-api/latest/ .. _`discord`: https://discord.gg/sXyFF8tDtm -.. _`superset behavior channel`: https://discord.com/channels/799879767196958751/1018954266322419732 +.. _`superset behavior thread`: https://discord.com/channels/799879767196958751/1189905520686014514 .. _`partial_mixed_handler`: https://github.com/unifyai/ivy/blob/a07919ebf64181852a3564c4d994bc1c25bd9a6f/ivy/functional/backends/tensorflow/experimental/layers.py#L817 .. _`handle_partial_mixed_function`: https://github.com/unifyai/ivy/blob/a07919ebf64181852a3564c4d994bc1c25bd9a6f/ivy/func_wrapper.py#L981 @@ -241,7 +241,7 @@ Ivy allows this using the `partial_mixed_handler`_ attribute on the backend-spec interpolate.partial_mixed_handler = lambda *args, mode="linear", **kwargs: mode not in [ "tf_area", - "bicubic_tensorflow", + "tf_bicubic", "mitchellcubic", "lanczos3", "lanczos5", @@ -266,7 +266,7 @@ This should have hopefully given you a good feel of what should and should not b In many cases, there is not a clear right and wrong answer, and we arrive at the final decision via open discussion. If you find yourself proposing the addition of a new function in Ivy, then we will most likely have this discussion on your Pull Request! -If you have any questions, please feel free to reach out on `discord`_ in the `superset behavior channel`_! +If you have any questions, please feel free to reach out on `discord`_ in the `superset behavior thread`_! **Video** diff --git a/docs/overview/design/building_blocks.rst b/docs/overview/design/building_blocks.rst index 249e48050e006..ca520798d67c2 100644 --- a/docs/overview/design/building_blocks.rst +++ b/docs/overview/design/building_blocks.rst @@ -11,7 +11,7 @@ These are the 4 parts labelled as (a) in the image below: Backend Functional APIs โœ… -------------------------- -The first important point to make is that, Ivy does not implement itโ€™s own C++ or CUDA backend. +The first important point to make is that, Ivy does not implement its own C++ or CUDA backend. Instead, Ivy **wraps** the functional APIs of existing frameworks, bringing them into syntactic and semantic alignment. Letโ€™s take the function :func:`ivy.stack` as an example. diff --git a/docs/overview/get_started.rst b/docs/overview/get_started.rst index 42b3e1e1f12c3..50d66ffe7ceb7 100644 --- a/docs/overview/get_started.rst +++ b/docs/overview/get_started.rst @@ -59,9 +59,8 @@ where OS-specific and IDE-specific instructions and video tutorials to install I Ivy's tracer and transpiler ----------------------------- -To use Ivy's tracer and transpiler, you'll need an **API key**. We are starting to -grant pilot access to certain users, so you can `join the waitlist `_ -if you want to get one! +To use Ivy's tracer and transpiler, you'll need an **API key**. If you don't have one yet, you can +register in `the console `_ to get it! Ivy Folder ~~~~~~~~~~ diff --git a/docs/overview/related_work/api_standards.rst b/docs/overview/related_work/api_standards.rst index 04d6939840436..31ebe5da5dbee 100644 --- a/docs/overview/related_work/api_standards.rst +++ b/docs/overview/related_work/api_standards.rst @@ -16,8 +16,24 @@ This standard can be considered as โ€œhigher levelโ€ than the ML frameworks the The Array API Standard takes the lowest common denominator approach, whereby each function in the standard represents the minimum behaviors of the function without restricting extensions to the function. This means that two very different libraries can adhere to the same standard, despite having very different extended behaviors for some of the functions in the standard. The standard is also not exhaustive. -For example, there are functions defined in the standard, whereas the functions defined in each framework are as follows: +For example, there are 64 functions defined in the standard, whereas the functions defined in each framework are as follows: - +Table: +__________________________________________________________________________________ +| | | +| Framework | Functions | +|-------------|------------------------------------------------------------------| +| NumPy | all, any, argmax, argmin, around, clip, cumprod, cumsum, max, | +| | mean, min, prod, round, std, sum, var | +|-------------|------------------------------------------------------------------| +| Pandas | append, diff, fillna, head, isin, loc, mean, min, pct_change, | +| | prod, quantile, rolling, shift, tail, to_numpy | +|-------------|------------------------------------------------------------------| +| TensorFlow | cast, clip_by_value, equal, greater, greater_equal, less, | +| | less_equal, maximum, minimum, not_equal, ones_like, reshape, | +| | sum | +|-------------|------------------------------------------------------------------| +| PyTorch | abs, add, mean, max, min, pow, sum | +|_____________|__________________________________________________________________| Therefore, two frameworks which adhere to the standard will still have major differences by virtue of the extra functions they support which are not present in the standard. diff --git a/docs/overview/volunteer_ranks.rst b/docs/overview/volunteer_ranks.rst new file mode 100644 index 0000000000000..e091024c3fab2 --- /dev/null +++ b/docs/overview/volunteer_ranks.rst @@ -0,0 +1,113 @@ +Contributor Leaderboard +======================= + +This page lists all of our amazing Contributors who have contributed to the project! We are grateful for your contributions and we hope to see you grow with the project! The ranks listed here are based on the `level of contribution `_\. + +Top Contributors +---------------- +.. list-table:: + :widths: 50 50 50 + :header-rows: 1 + + * - Name + - Github ID + - Badges + * - samunder singh + - `samthakur587 `_ + - Merging Master Gold, Merging Wizard, Ivy Inspector Silver + * - V\. Sai Suraj + - `Sai-Suraj-27 `_ + - Merging Master Gold, Ivy Inspector Bronze +Rising Contributors +------------------- +.. list-table:: + :widths: 50 50 50 + :header-rows: 1 + + * - Name + - Github ID + - Badges + * - Muhammad ishaque + - `MuhammadNizamani `_ + - Merging Master Silver, Merging Wizard, Ivy Inspector +Core Contributors +----------------- +.. list-table:: + :widths: 50 50 50 + :header-rows: 1 + + * - Name + - Github ID + - Badges + * - Suyash Gupta + - `sgalpha01 `_ + - Debugging Dynamo, Merging Master Bronze, Merging Wizard Bronze + * - Sanjay Suthar + - `Sanjay8602 `_ + - Merging Master Bronze, Ivy Inspector Bronze + * - R E Zera Marveen Lyngkhoi + - `fleventy-5 `_ + - Merging Master Bronze + * - nitesh kesharwani + - `NiteshK84 `_ + - Ivy Inspector Bronze + * - sarvesh kesharwani + - `Sarvesh-Kesharwani `_ + - Ivy Inspector Bronze +Contributors +------------ +.. list-table:: + :widths: 50 50 50 + :header-rows: 1 + + * - Name + - Github ID + - Badges + * - Jackson McClintock + - `jacksondm33 `_ + - Merging Master, Merging Wizard, Ivy Inspector + * - David Adlai Nettey + - `Adlai-1 `_ + - Merging Master, Ivy Inspector + * - Garima Saroj + - `AndroGari `_ + - Merging Master, Ivy Inspector + * - Lee Bissessar + - `leebissessar5 `_ + - Merging Master, Ivy Inspector + * - Mostafa Gamal + - `Mr-Array22 `_ + - Merging Master, Ivy Inspector + * - Ogban Ugot + - `ogbanugot `_ + - Merging Master, Ivy Inspector + * - Rahul Prem + - `rp097 `_ + - Merging Master, Ivy Inspector + * - Rohit Kumar Salla + - `rohitsalla `_ + - Merging Master, Ivy Inspector + * - Srikar Vedantam + - `shruzki `_ + - Merging Master, Merging Wizard + * - Waqar Ahmed + - `waqaarahmed `_ + - Merging Master, Ivy Inspector + * - Aryan Pandey + - `Aryan8912 `_ + - Merging Master + * - Dhruv Sharma + - `druvdub `_ + - Merging Master + * - Kacper Koลผdoล„ + - `Kacper-W-Kozdon `_ + - Merging Master + * - Mehmet Bilgehan Bezcioglu + - `BilgehanMehmet `_ + - Merging Master + * - Sheroz Khan + - `ksheroz `_ + - Merging Master + * - Syed Muzakkir Hussain + - `muzakkirhussain011 `_ + - Merging Master diff --git a/install_dependencies.sh b/install_dependencies.sh index d5dbcc660307b..911662965c6e3 100755 --- a/install_dependencies.sh +++ b/install_dependencies.sh @@ -1,12 +1,13 @@ # This shell script is required by the doc-builder. Moving it might break # the doc-building pipeline - -sudo apt-get update -sudo apt-get install pandoc -y +pip install -e . pip install -r requirements/requirements.txt if [[ $(arch) == 'arm64' ]]; then + brew install pandoc pip install -r requirements/optional_apple_silicon_1.txt pip install -r requirements/optional_apple_silicon_2.txt else + sudo apt-get update + sudo apt-get install pandoc -y pip install -r requirements/optional.txt fi diff --git a/ivy/__init__.py b/ivy/__init__.py index 2addeeaaa06dc..d40ab10bfb12d 100644 --- a/ivy/__init__.py +++ b/ivy/__init__.py @@ -7,6 +7,7 @@ import numpy as np import sys import inspect +import importlib import os from collections.abc import Sequence @@ -69,6 +70,10 @@ class NativeShape: pass +class NativeModule: + pass + + class Container: pass @@ -259,6 +264,11 @@ def __repr__(self): f"ivy.Shape({shape_repr})" if self._shape is not None else "ivy.Shape(None)" ) + def __deepcopy__(self, memo): + ret = self.__class__.__new__(self.__class__) + ret._shape = self.shape + return ret + def __iter__(self): return iter(self._shape) @@ -277,15 +287,24 @@ def __radd__(self, other): return self def __mul__(self, other): - self._shape = self._shape * other + if ivy.current_backend_str() == "tensorflow": + shape_tup = builtins.tuple(self._shape) * other + self._shape = ivy.to_native_shape(shape_tup) + else: + self._shape = self._shape * other return self def __rmul__(self, other): - self._shape = other * self._shape + # handle tensorflow case as tf.TensorShape doesn't support multiplications + if ivy.current_backend_str() == "tensorflow": + shape_tup = other * builtins.tuple(self._shape) + self._shape = ivy.to_native_shape(shape_tup) + else: + self._shape = other * self._shape return self def __bool__(self): - return self._shape.__bool__() + return builtins.bool(self._shape) def __div__(self, other): return self._shape // other @@ -303,7 +322,7 @@ def __rmod__(self, other): return other % self._shape def __reduce__(self): - return (self._shape,) + return (self.__class__, (self._shape,)) def as_dimension(self, other): if isinstance(other, self._shape): @@ -424,6 +443,7 @@ def assert_has_rank(self, rank): if self.rank not in (None, rank): raise ValueError(f"Shape {self} must have rank {rank}") + @staticmethod def unknown_shape(rank=None, **kwargs): if rank is None and "ndims" in kwargs: rank = kwargs.pop("ndims") @@ -436,9 +456,9 @@ def unknown_shape(rank=None, **kwargs): def with_rank(self, rank): try: - return self.merge_with(unknown_shape(rank=rank)) - except ValueError: - raise ValueError(f"Shape {self} must have rank {rank}") + return self.merge_with(self.unknown_shape(rank=rank)) + except ValueError as e: + raise ValueError(f"Shape {self} must have rank {rank}") from e def with_rank_at_least(self, rank): if self.rank is not None and self.rank < rank: @@ -452,6 +472,7 @@ def with_rank_at_most(self, rank): else: return self + @staticmethod def as_shape(shape): if isinstance(shape, Shape): return shape @@ -475,8 +496,7 @@ def is_fully_defined(self): shape is not None for shape in self._shape ) - property - + @property def num_elements(self): if not self.is_fully_defined(): return None @@ -585,7 +605,7 @@ class Node(str): nan_policy_stack = [] dynamic_backend_stack = [] warn_to_regex = {"all": "!.*", "ivy_only": "^(?!.*ivy).*$", "none": ".*"} - +cython_wrappers_stack = [] # local import threading @@ -735,7 +755,7 @@ class Node(str): locks = {"backend_setter": threading.Lock()} - +from .wrappers import * from .func_wrapper import * from .data_classes.array import Array, add_ivy_array_instance_methods from .data_classes.array.conversions import * @@ -770,6 +790,7 @@ class Node(str): choose_random_backend, unset_backend, ) +from . import wrappers from . import func_wrapper from .utils import assertions, exceptions, verbosity from .utils.backend import handler @@ -792,6 +813,10 @@ class Node(str): from .compiler.compiler import transpile, trace_graph, unify except: # noqa: E722 pass # Added for the finally statement +try: + from .compiler.replace_with import replace_with, transform_function +except: # noqa: E722 + pass finally: # Skip framework imports done by Ivy compiler for now for backend_framework in _not_imported_backends.copy(): @@ -939,9 +964,7 @@ def __deepcopy__(self, memo): "inplace_mode_stack": general.inplace_mode_stack, "soft_device_mode_stack": device.soft_device_mode_stack, "shape_array_mode_stack": general.shape_array_mode_stack, - "show_func_wrapper_trace_mode_stack": ( - general.show_func_wrapper_trace_mode_stack - ), + "show_func_wrapper_trace_mode_stack": general.show_func_wrapper_trace_mode_stack, "min_denominator_stack": general.min_denominator_stack, "min_base_stack": general.min_base_stack, "tmp_dir_stack": general.tmp_dir_stack, @@ -954,6 +977,7 @@ def __deepcopy__(self, memo): "default_uint_dtype_stack": data_type.default_uint_dtype_stack, "nan_policy_stack": nan_policy_stack, "dynamic_backend_stack": dynamic_backend_stack, + "cython_wrappers_stack": cython_wrappers_stack, } ) @@ -1008,8 +1032,7 @@ def vec_sig_fig(x, sig_fig=3): def set_array_significant_figures(sig_figs): - """ - Summary. + """Summary. Parameters ---------- @@ -1049,8 +1072,7 @@ def _assert_array_decimal_values_formatting(dec_vals): def set_array_decimal_values(dec_vals): - """ - Summary. + """Summary. Parameters ---------- @@ -1076,8 +1098,7 @@ def unset_array_decimal_values(): def set_warning_level(warn_level): - """ - Summary. + """Summary. Parameters ---------- @@ -1109,8 +1130,7 @@ def warn(warning_message, stacklevel=0): def set_nan_policy(warn_level): - """ - Summary. + """Summary. Parameters ---------- @@ -1142,8 +1162,9 @@ def unset_nan_policy(): ivy.dynamic_backend = dynamic_backend_stack[-1] if dynamic_backend_stack else True -def set_dynamic_backend(flag): - """Set the global dynamic backend setting to the provided flag (True or False)""" +def set_dynamic_backend(flag): # noqa: D209 + """Set the global dynamic backend setting to the provided flag (True or + False)""" global dynamic_backend_stack if flag not in [True, False]: raise ValueError("dynamic_backend must be a boolean value (True or False)") @@ -1152,8 +1173,7 @@ def set_dynamic_backend(flag): def unset_dynamic_backend(): - """ - Remove the current dynamic backend setting. + """Remove the current dynamic backend setting. Also restore the previous setting (if any) """ @@ -1164,6 +1184,37 @@ def unset_dynamic_backend(): ivy.__setattr__("dynamic_backend", flag, True) +# Cython wrappers + +ivy.cython_wrappers_mode = cython_wrappers_stack[-1] if cython_wrappers_stack else False + + +@handle_exceptions +def set_cython_wrappers_mode(flag: bool = True) -> None: + """Set the mode of whether to use cython wrappers for functions. + + Parameter + --------- + flag + boolean whether to use cython wrappers for functions + + Examples + -------- + >>> ivy.set_cython_wrappers_mode(False) + >>> ivy.cython_wrappers_mode + False + + >>> ivy.set_cython_wrappers_mode(True) + >>> ivy.cython_wrappers_mode + True + """ + global cython_wrappers_stack + if flag not in [True, False]: + raise ValueError("cython_wrappers_mode must be a boolean value (True or False)") + cython_wrappers_stack.append(flag) + ivy.__setattr__("cython_wrappers_mode", flag, True) + + # Context Managers @@ -1211,7 +1262,10 @@ def dynamic_backend_as(value): downcast_dtypes = False upcast_dtypes = False crosscast_dtypes = False -cast_dtypes = lambda: downcast_dtypes and upcast_dtypes and crosscast_dtypes + + +def cast_dtypes(): + return downcast_dtypes and upcast_dtypes and crosscast_dtypes def downcast_data_types(val=True): @@ -1433,6 +1487,7 @@ def cast_data_types(val=True): "default_int_dtype", "default_complex_dtype", "default_uint_dtype", + "cython_wrappers_mode", ] @@ -1462,8 +1517,7 @@ def __init__(self): self.logging_mode_stack.append(logging.WARNING) def set_logging_mode(self, mode): - """ - Set the current logging mode for Ivy. + """Set the current logging mode for Ivy. Possible modes are 'DEBUG', 'INFO', 'WARNING', 'ERROR'. """ @@ -1475,8 +1529,9 @@ def set_logging_mode(self, mode): logging.getLogger().setLevel(mode) self.logging_mode_stack.append(mode) - def unset_logging_mode(self): - """Remove the most recently set logging mode, returning to the previous one.""" + def unset_logging_mode(self): # noqa: D209 + """Remove the most recently set logging mode, returning to the previous + one.""" if len(self.logging_mode_stack) > 1: # Remove the current mode self.logging_mode_stack.pop() @@ -1497,6 +1552,14 @@ def __setattr__(self, name, value, internal=False): ) self.__dict__[name] = value + def __reduce__(self): + def _get_module_and_replace_name(module_name: str): + module = importlib.import_module(module_name) + module.__class__ = self.__class__ + return module + + return (_get_module_and_replace_name, (self.__name__,)) + if ( "ivy" in sys.modules diff --git a/ivy/_version.py b/ivy/_version.py index d1bfff206d3b1..c8de1df2308a4 100644 --- a/ivy/_version.py +++ b/ivy/_version.py @@ -1 +1 @@ -__version__ = "0.0.4.0" +__version__ = "0.0.7.5" diff --git a/ivy/compiler/compiler.py b/ivy/compiler/compiler.py index a89084d8b0dbe..4bd5ae74aeb45 100644 --- a/ivy/compiler/compiler.py +++ b/ivy/compiler/compiler.py @@ -1,4 +1,4 @@ -from typing import Callable, Optional, List, Union, Iterable, Tuple, Mapping +from typing import Callable, Optional, List, Union, Iterable, Sequence, Mapping def trace_graph( @@ -10,18 +10,19 @@ def trace_graph( include_generators: bool = True, array_caching: bool = True, with_numpy: bool = True, + modes_to_trace: str = "all", backend_compile: bool = False, static_argnums: Optional[Union[int, Iterable[int]]] = None, static_argnames: Optional[Union[str, Iterable[str]]] = None, - mode: Optional[str] = None, + compile_mode: Optional[str] = None, graph_caching: bool = False, - args: Optional[Tuple] = None, + args: Optional[Sequence] = None, kwargs: Optional[Mapping] = None, params_v=None, v=None ): - """ - Takes `fn` and traces it into a more efficient composition of backend operations. + """Takes `fn` and traces it into a more efficient composition of backend + operations. Parameters ---------- @@ -37,14 +38,17 @@ def trace_graph( include array creation/generation functions as part of the graph array_caching cache the constant arrays that appear as arguments to the functions in the graph + modes_to_trace + the module mode(s) which should be traced when tracing a trainable module + can be either "all", "train" or "eval". backend_compile whether to apply the native compilers, i.e. tf.function, after ivy's tracing static_argnums for jax's jit compilation static_argnames for jax's jit compilation - mode - for torch's compilation + compile_mode + mode for torch's compilation graph_caching whether to cache the traced graph args @@ -90,7 +94,6 @@ def trace_graph( >>> print(time.time() - start) 0.0001785755157470703 """ - from ._compiler import trace_graph as _trace_graph return _trace_graph( @@ -102,10 +105,11 @@ def trace_graph( include_generators=include_generators, array_caching=array_caching, with_numpy=with_numpy, + modes_to_trace=modes_to_trace, backend_compile=backend_compile, static_argnums=static_argnums, static_argnames=static_argnames, - mode=mode, + compile_mode=compile_mode, graph_caching=graph_caching, args=args, kwargs=kwargs, @@ -122,19 +126,21 @@ def transpile( backend_compile: bool = False, static_argnums: Optional[Union[int, Iterable[int]]] = None, static_argnames: Optional[Union[str, Iterable[str]]] = None, - mode: Optional[str] = None, + compile_mode: Optional[str] = None, graph_caching: bool = False, + graph_optimizations: bool = True, + modes_to_trace: str = "all", stateful: Optional[List] = None, arg_stateful_idxs: Optional[List] = None, kwarg_stateful_idxs: Optional[List] = None, - args: Optional[Tuple] = None, + args: Optional[Sequence] = None, kwargs: Optional[Mapping] = None, params_v=None, v=None ): - """ - Transpiles Callable objects passed as arguments. If args and kwargs are specified, - transpilation is performed eagerly, otherwise, transpilation will happen lazily. + """Transpiles Callable objects passed as arguments. If args and kwargs are + specified, transpilation is performed eagerly, otherwise, transpilation + will happen lazily. Parameters ---------- @@ -153,7 +159,6 @@ def transpile( ------- Either a transpiled Graph or a non-initialized LazyGraph. """ - from ._compiler import transpile as _transpile return _transpile( @@ -164,8 +169,10 @@ def transpile( backend_compile=backend_compile, static_argnums=static_argnums, static_argnames=static_argnames, - mode=mode, + compile_mode=compile_mode, graph_caching=graph_caching, + graph_optimizations=graph_optimizations, + modes_to_trace=modes_to_trace, stateful=stateful, arg_stateful_idxs=arg_stateful_idxs, kwarg_stateful_idxs=kwarg_stateful_idxs, @@ -180,19 +187,24 @@ def unify( *objs: Callable, source: Optional[str] = None, graph_caching: bool = False, - args: Optional[Tuple] = None, + graph_optimizations: bool = True, + args: Optional[Sequence] = None, kwargs: Optional[Mapping] = None, with_numpy: bool = True, + modes_to_trace: str = "all", **transpile_kwargs ): + from ._compiler import unify as _unify return _unify( *objs, source=source, graph_caching=graph_caching, + graph_optimizations=graph_optimizations, args=args, kwargs=kwargs, with_numpy=with_numpy, + modes_to_trace=modes_to_trace, **transpile_kwargs, ) diff --git a/ivy/compiler/replace_with.py b/ivy/compiler/replace_with.py new file mode 100644 index 0000000000000..2bfdd8140b7b5 --- /dev/null +++ b/ivy/compiler/replace_with.py @@ -0,0 +1,81 @@ +import ast +import astunparse +import inspect + +replace_map = {} + + +def replace_with(new_func): + """Decorate a function/method/attribute to be replaced by another. + + Parameters + ---------- + new_func + The function that will replace the original. + """ + + def decorator(original_func): + if not callable(original_func) or not callable(new_func): + raise TypeError( + f"Both '{original_func.__name__}' and '{new_func.__name__}' should be" + " callable." + ) + + if inspect.getfullargspec(original_func) != inspect.getfullargspec(new_func): + raise ValueError( + f"Replacement function '{new_func.__name__}' arguments don't match" + f" '{original_func.__name__}' arguments." + ) + + new_func_name = f"{original_func.__name__}_replacement" + + if new_func_name in globals(): + raise NameError( + f"Name '{new_func_name}' already exists in global namespace." + ) + + globals()[new_func_name] = new_func + replace_map[original_func.__name__] = new_func_name + return original_func + + return decorator + + +class ReplaceFunction(ast.NodeTransformer): + """AST Node Transformer to replace function calls, methods, and + attributes.""" + + def visit_Attribute(self, node): + if ( + isinstance(node.value, ast.Name) + and f"{node.value.id}.{node.attr}" in replace_map + ): + return ast.copy_location( + ast.Name(replace_map[f"{node.value.id}.{node.attr}"], node.ctx), node + ) + return node + + def visit_Call(self, node): + if ( + isinstance(node.func, ast.Attribute) + and f"{node.func.value.id}.{node.func.attr}" in replace_map + ): + node.func = ast.Name( + replace_map[f"{node.func.value.id}.{node.func.attr}"], node.func.ctx + ) + elif isinstance(node.func, ast.Name) and node.func.id in replace_map: + node.func.id = replace_map[node.func.id] + return node + + +def transform_function(func): + """Transform the function by replacing its calls based on the + replace_map.""" + source = inspect.getsource(func) + tree = ast.parse(source) + transformed_tree = ReplaceFunction().visit(tree) + transformed_code = astunparse.unparse(transformed_tree) + + namespace = {} + exec(transformed_code, globals(), namespace) + return namespace[func.__name__] diff --git a/ivy/data_classes/array/activations.py b/ivy/data_classes/array/activations.py index 950dd0512b6f7..6fcdafe056a19 100644 --- a/ivy/data_classes/array/activations.py +++ b/ivy/data_classes/array/activations.py @@ -17,10 +17,9 @@ def relu( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.relu. This method simply wraps the - function, and so the docstring for ivy.relu also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.relu. This method simply + wraps the function, and so the docstring for ivy.relu also applies to + this method with minimal changes. Parameters ---------- @@ -55,10 +54,9 @@ def leaky_relu( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.leaky_relu. This method simply wraps - the function, and so the docstring for ivy.leaky_relu also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.leaky_relu. This method + simply wraps the function, and so the docstring for ivy.leaky_relu also + applies to this method with minimal changes. Parameters ---------- @@ -97,10 +95,9 @@ def gelu( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.gelu. This method simply wraps the - function, and so the docstring for ivy.gelu also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.gelu. This method simply + wraps the function, and so the docstring for ivy.gelu also applies to + this method with minimal changes. Parameters ---------- @@ -138,8 +135,7 @@ def sigmoid( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.sigmoid. + """ivy.Array instance method variant of ivy.sigmoid. This method simply wraps the function, and so the docstring for ivy.sigmoid also applies to this method with minimal changes. @@ -178,10 +174,9 @@ def softmax( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.softmax. This method simply wraps the - function, and so the docstring for ivy.softmax also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.softmax. This method simply + wraps the function, and so the docstring for ivy.softmax also applies + to this method with minimal changes. Parameters ---------- @@ -219,10 +214,9 @@ def softplus( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.softplus. This method simply wraps the - function, and so the docstring for ivy.softplus also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.softplus. This method + simply wraps the function, and so the docstring for ivy.softplus also + applies to this method with minimal changes. Parameters ---------- @@ -276,10 +270,9 @@ def log_softmax( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.log_softmax. This method simply wraps - the function, and so the docstring for ivy.log_softmax also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.log_softmax. This method + simply wraps the function, and so the docstring for ivy.log_softmax + also applies to this method with minimal changes. Parameters ---------- @@ -324,10 +317,9 @@ def mish( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.mish. This method simply wraps the - function, and so the docstring for ivy.mish also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.mish. This method simply + wraps the function, and so the docstring for ivy.mish also applies to + this method with minimal changes. Parameters ---------- @@ -356,8 +348,7 @@ def hardswish( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Apply the hardswish activation function element-wise. + """Apply the hardswish activation function element-wise. Parameters ---------- diff --git a/ivy/data_classes/array/array.py b/ivy/data_classes/array/array.py index 0694b3dada2f6..4d8a3e27def1c 100644 --- a/ivy/data_classes/array/array.py +++ b/ivy/data_classes/array/array.py @@ -1,9 +1,7 @@ # flake8: noqa # global import copy -import functools import numpy as np -from operator import mul from typing import Optional # local @@ -144,6 +142,8 @@ def _init(self, data, dynamic_backend=None): self._data = data elif isinstance(data, np.ndarray): self._data = ivy.asarray(data)._data + elif isinstance(data, (list, tuple)): + self._data = ivy.asarray(data)._data elif ivy.is_ivy_sparse_array(data): self._data = data._data elif ivy.is_native_sparse_array(data): @@ -160,7 +160,7 @@ def _init(self, data, dynamic_backend=None): self._dev_str = None self._pre_repr = None self._post_repr = None - self._backend = ivy.backend + self._backend = ivy.current_backend(self._data).backend if dynamic_backend is not None: self._dynamic_backend = dynamic_backend else: @@ -188,28 +188,27 @@ def dynamic_backend(self): @dynamic_backend.setter def dynamic_backend(self, value): - from ivy.functional.ivy.gradients import _variable, _is_variable, _variable_data - from ivy.utils.backend.handler import _determine_backend_from_args - - if value == False: - self._backend = _determine_backend_from_args(self).backend + from ivy.functional.ivy.gradients import _variable + from ivy.utils.backend.handler import _data_to_new_backend, _get_backend_for_arg - else: + if value: ivy_backend = ivy.with_backend(self._backend) - to_numpy = ivy_backend.to_numpy - if _is_variable(self.data) and self._backend not in ["jax", "numpy"]: - native_data = _variable_data(self.data) - np_data = to_numpy(native_data) - new_arr = ivy.array(np_data) - self._data = _variable(new_arr).data + if ivy_backend.gradients._is_variable(self.data): + native_var = ivy_backend.gradients._variable_data( + self, + ) + data = _data_to_new_backend(native_var, ivy_backend).data + self._data = _variable(data).data else: - np_data = to_numpy(self.data) - self._data = ivy.array(np_data).data + self._data = _data_to_new_backend(self, ivy_backend).data self._backend = ivy.backend + else: + self._backend = _get_backend_for_arg(self.data.__class__.__module__).backend + self._dynamic_backend = value @property @@ -233,8 +232,7 @@ def device(self) -> ivy.Device: @property def mT(self) -> ivy.Array: - """ - Transpose of a matrix (or a stack of matrices). + """Transpose of a matrix (or a stack of matrices). Returns ------- @@ -262,13 +260,7 @@ def shape(self) -> ivy.Shape: @property def size(self) -> Optional[int]: """Number of elements in the array.""" - if self._size is None: - self._size = ( - functools.reduce(mul, self._data.shape) - if len(self._data.shape) > 0 - else 1 - ) - return self._size + return ivy.size(self) @property def itemsize(self) -> Optional[int]: @@ -288,8 +280,7 @@ def strides(self) -> Optional[int]: @property def T(self) -> ivy.Array: - """ - Transpose of the array. + """Transpose of the array. Returns ------- @@ -307,8 +298,7 @@ def base(self) -> ivy.Array: @property def real(self) -> ivy.Array: - """ - Real part of the array. + """Real part of the array. Returns ------- @@ -321,8 +311,7 @@ def real(self) -> ivy.Array: @property def imag(self) -> ivy.Array: - """ - Imaginary part of the array. + """Imaginary part of the array. Returns ------- @@ -349,7 +338,7 @@ def data(self, data): @classmethod def __torch_function__(cls, func, types, args=(), kwargs={}): args, kwargs = args_to_native(*args, **kwargs) - return func(*args, **kwargs) + return to_ivy(func(*args, **kwargs)) def __ivy_array_function__(self, func, types, args, kwargs): # Cannot handle items that have __ivy_array_function__ other than those of @@ -382,7 +371,7 @@ def __array_prepare__(self, *args, **kwargs): def __array_ufunc__(self, *args, **kwargs): args, kwargs = args_to_native(*args, **kwargs) - return self._data.__array_ufunc__(*args, **kwargs) + return to_ivy(self._data.__array_ufunc__(*args, **kwargs)) def __array_wrap__(self, *args, **kwargs): args, kwargs = args_to_native(*args, **kwargs) @@ -483,10 +472,9 @@ def __neg__(self): return ivy.negative(self._data) def __pow__(self, power): - """ - ivy.Array special method variant of ivy.pow. This method simply wraps the - function, and so the docstring for ivy.pow also applies to this method with - minimal changes. + """ivy.Array special method variant of ivy.pow. This method simply + wraps the function, and so the docstring for ivy.pow also applies to + this method with minimal changes. Parameters ---------- @@ -525,10 +513,9 @@ def __ipow__(self, power): return ivy.pow(self._data, power) def __add__(self, other): - """ - ivy.Array special method variant of ivy.add. This method simply wraps the - function, and so the docstring for ivy.add also applies to this method with - minimal changes. + """ivy.Array special method variant of ivy.add. This method simply + wraps the function, and so the docstring for ivy.add also applies to + this method with minimal changes. Parameters ---------- @@ -555,10 +542,9 @@ def __add__(self, other): return ivy.add(self._data, other) def __radd__(self, other): - """ - ivy.Array reverse special method variant of ivy.add. This method simply wraps - the function, and so the docstring for ivy.add also applies to this method with - minimal changes. + """ivy.Array reverse special method variant of ivy.add. This method + simply wraps the function, and so the docstring for ivy.add also + applies to this method with minimal changes. Parameters ---------- @@ -588,10 +574,9 @@ def __iadd__(self, other): return ivy.add(self._data, other) def __sub__(self, other): - """ - ivy.Array special method variant of ivy.subtract. This method simply wraps the - function, and so the docstring for ivy.subtract also applies to this method with - minimal changes. + """ivy.Array special method variant of ivy.subtract. This method simply + wraps the function, and so the docstring for ivy.subtract also applies + to this method with minimal changes. Parameters ---------- @@ -620,10 +605,9 @@ def __sub__(self, other): return ivy.subtract(self._data, other) def __rsub__(self, other): - """ - ivy.Array reverse special method variant of ivy.subtract. This method simply - wraps the function, and so the docstring for ivy.subtract also applies to this - method with minimal changes. + """ivy.Array reverse special method variant of ivy.subtract. This + method simply wraps the function, and so the docstring for ivy.subtract + also applies to this method with minimal changes. Parameters ---------- @@ -671,16 +655,15 @@ def __imod__(self, other): return ivy.remainder(self._data, other) def __divmod__(self, other): - return tuple([ivy.divide(self._data, other), ivy.remainder(self._data, other)]) + return ivy.divide(self._data, other), ivy.remainder(self._data, other) def __rdivmod__(self, other): - return tuple([ivy.divide(other, self._data), ivy.remainder(other, self._data)]) + return ivy.divide(other, self._data), ivy.remainder(other, self._data) def __truediv__(self, other): - """ - ivy.Array reverse special method variant of ivy.divide. This method simply wraps - the function, and so the docstring for ivy.divide also applies to this method - with minimal changes. + """ivy.Array reverse special method variant of ivy.divide. This method + simply wraps the function, and so the docstring for ivy.divide also + applies to this method with minimal changes. Parameters ---------- @@ -731,10 +714,9 @@ def __imatmul__(self, other): return ivy.matmul(self._data, other) def __abs__(self): - """ - ivy.Array special method variant of ivy.abs. This method simply wraps the - function, and so the docstring for ivy.abs also applies to this method with - minimal changes. + """ivy.Array special method variant of ivy.abs. This method simply + wraps the function, and so the docstring for ivy.abs also applies to + this method with minimal changes. Parameters ---------- @@ -807,10 +789,9 @@ def __dlpack_device__(self): return self._data.__dlpack_device__() def __lt__(self, other): - """ - ivy.Array special method variant of ivy.less. This method simply wraps the - function, and so the docstring for ivy.less also applies to this method with - minimal changes. + """ivy.Array special method variant of ivy.less. This method simply + wraps the function, and so the docstring for ivy.less also applies to + this method with minimal changes. Parameters ---------- @@ -837,10 +818,9 @@ def __lt__(self, other): return ivy.less(self._data, other) def __le__(self, other): - """ - ivy.Array special method variant of ivy.less_equal. This method simply wraps the - function, and so the docstring for ivy.less_equal also applies to this method - with minimal changes. + """ivy.Array special method variant of ivy.less_equal. This method + simply wraps the function, and so the docstring for ivy.less_equal also + applies to this method with minimal changes. Parameters ---------- @@ -867,10 +847,9 @@ def __le__(self, other): return ivy.less_equal(self._data, other) def __eq__(self, other): - """ - ivy.Array special method variant of ivy.equal. This method simply wraps the - function, and so the docstring for ivy.equal also applies to this method with - minimal changes. + """ivy.Array special method variant of ivy.equal. This method simply + wraps the function, and so the docstring for ivy.equal also applies to + this method with minimal changes. Parameters ---------- @@ -905,10 +884,9 @@ def __eq__(self, other): return ivy.equal(self._data, other) def __ne__(self, other): - """ - ivy.Array special method variant of ivy.not_equal. This method simply wraps the - function, and so the docstring for ivy.not_equal also applies to this method - with minimal changes. + """ivy.Array special method variant of ivy.not_equal. This method + simply wraps the function, and so the docstring for ivy.not_equal also + applies to this method with minimal changes. Parameters ---------- @@ -943,10 +921,9 @@ def __ne__(self, other): return ivy.not_equal(self._data, other) def __gt__(self, other): - """ - ivy.Array special method variant of ivy.greater. This method simply wraps the - function, and so the docstring for ivy.greater also applies to this method with - minimal changes. + """ivy.Array special method variant of ivy.greater. This method simply + wraps the function, and so the docstring for ivy.greater also applies + to this method with minimal changes. Parameters ---------- @@ -990,10 +967,9 @@ def __gt__(self, other): return ivy.greater(self._data, other) def __ge__(self, other): - """ - ivy.Array special method variant of ivy.greater_equal. This method simply wraps - the function, and so the docstring for ivy.bitwise_xor also applies to this - method with minimal changes. + """ivy.Array special method variant of ivy.greater_equal. This method + simply wraps the function, and so the docstring for ivy.bitwise_xor + also applies to this method with minimal changes. Parameters ---------- @@ -1058,10 +1034,9 @@ def __invert__(self): return ivy.bitwise_invert(self._data) def __xor__(self, other): - """ - ivy.Array special method variant of ivy.bitwise_xor. This method simply wraps - the function, and so the docstring for ivy.bitwise_xor also applies to this - method with minimal changes. + """ivy.Array special method variant of ivy.bitwise_xor. This method + simply wraps the function, and so the docstring for ivy.bitwise_xor + also applies to this method with minimal changes. Parameters ---------- @@ -1116,10 +1091,10 @@ def __ilshift__(self, other): return ivy.bitwise_left_shift(self._data, other) def __rshift__(self, other): - """ - ivy.Array special method variant of ivy.bitwise_right_shift. This method simply - wraps the function, and so the docstring for ivy.bitwise_right_shift also - applies to this method with minimal changes. + """ivy.Array special method variant of ivy.bitwise_right_shift. This + method simply wraps the function, and so the docstring for + ivy.bitwise_right_shift also applies to this method with minimal + changes. Parameters ---------- @@ -1149,10 +1124,10 @@ def __rshift__(self, other): return ivy.bitwise_right_shift(self._data, other) def __rrshift__(self, other): - """ - ivy.Array reverse special method variant of ivy.bitwise_right_shift. This method - simply wraps the function, and so the docstring for ivy.bitwise_right_shift also - applies to this method with minimal changes. + """ivy.Array reverse special method variant of ivy.bitwise_right_shift. + This method simply wraps the function, and so the docstring for + ivy.bitwise_right_shift also applies to this method with minimal + changes. Parameters ---------- diff --git a/ivy/data_classes/array/conversions.py b/ivy/data_classes/array/conversions.py index a78e7bdae4311..67898f34951cd 100644 --- a/ivy/data_classes/array/conversions.py +++ b/ivy/data_classes/array/conversions.py @@ -1,5 +1,4 @@ -""" -Ivy wrapping functions for conversions. +"""Ivy wrapping functions for conversions. Collection of Ivy functions for wrapping functions to accept and return ivy.Array instances. @@ -17,6 +16,92 @@ # --------# +ARRAY_TO_BACKEND = { + "ndarray": "numpy", + "Tensor": ["torch", "paddle"], + "Parameter": "torch", + "EagerTensor": "tensorflow", + "ResourceVariable": "tensorflow", + "DeviceArray": "jax", + "Array": "jax", + "ArrayImpl": "jax", + "EagerParamBase": "paddle", +} + + +def _array_to_new_backend( + x: Union[ivy.Array, ivy.NativeArray], native: bool = False +) -> Union[ivy.Array, ivy.NativeArray]: + # Frontend instances + if hasattr(x, "_ivy_array"): + return x + + # ivy.Array instances + native_x = x.data if isinstance(x, ivy.Array) else x + native_x_type = type(native_x).__name__ + + # Modify native_type here since @tf.function converts tf.EagerTensor into + # tf.Tensor when running @tf.function enclosed function + if ivy.backend == "tensorflow": + import tensorflow as tf + + native_x_type = ( + "EagerTensor" + if not tf.executing_eagerly() and isinstance(native_x, tf.Tensor) + else native_x_type + ) + + if native_x_type not in ARRAY_TO_BACKEND: + return x + + # Check if the other possible backends match with the native data type + native_x_backend = ARRAY_TO_BACKEND[native_x_type] + + # Handle the `Tensor` name clash in paddle and torch + if not isinstance(native_x_backend, str): + native_x_backend = "torch" if "torch" in str(native_x.__class__) else "paddle" + + # If the current backend and the backend for the given array match, + # simply return the array as is + if ivy.backend == native_x_backend: + if native: + return native_x + np_intermediary = ivy.to_numpy(native_x) + return ivy.array(np_intermediary) + + # Otherwise, convert to the new backend + else: + native_x_backend = ivy.with_backend(native_x_backend) + # Handle native variable instances here + if native_x_backend.gradients._is_variable(native_x): + x_data = native_x_backend.gradients._variable_data(native_x) + # x_data = _array_to_new_backend(x_data, native=True) + from ivy.functional.ivy.gradients import _variable + + return _variable(x_data).data if native else _variable(x_data) + + np_intermediary = native_x_backend.to_numpy(native_x) + ret = ivy.array(np_intermediary) + return ret.data if native else ret + + +def _to_new_backend( + x: Any, + native: bool = False, + inplace: bool = False, + to_ignore: tuple = (), +) -> Any: + if isinstance(x, ivy.Container): + to_ignore = ivy.default(to_ignore, ()) + return x.cont_map( + lambda x_, _: _to_new_backend( + x_, native=native, inplace=inplace, to_ignore=to_ignore + ), + inplace=inplace, + ) + return _array_to_new_backend(x, native=native) + + def _to_native(x: Any, inplace: bool = False, to_ignore: tuple = ()) -> Any: to_ignore = ivy.default(to_ignore, ()) if isinstance(x, to_ignore): @@ -55,10 +140,10 @@ def to_ivy( nested: bool = False, include_derived: Optional[Dict[str, bool]] = None, ) -> Union[ivy.Array, ivy.NativeArray, Iterable]: - """ - Return the input array converted to an ivy.Array instance if it is a native array - type, otherwise the input is returned unchanged. If nested is set, the check is - applied to all nested leafs of tuples, lists and dicts contained within x. + """Return the input array converted to an ivy.Array instance if it is a + native array type, otherwise the input is returned unchanged. If nested is + set, the check is applied to all nested leafs of tuples, lists and dicts + contained within x. Parameters ---------- @@ -87,9 +172,8 @@ def args_to_ivy( include_derived: Optional[Dict[str, bool]] = None, **kwargs: Dict[str, Any], ) -> Tuple[Iterable[Any], Dict[str, Any]]: - """ - Return args and keyword args in their ivy.Array or form for all nested instances, - otherwise the arguments are returned unchanged. + """Return args and keyword args in their ivy.Array or form for all nested + instances, otherwise the arguments are returned unchanged. Parameters ---------- @@ -119,10 +203,10 @@ def to_native( cont_inplace: bool = False, to_ignore: Optional[Union[type, Tuple[type]]] = None, ) -> Union[ivy.Array, ivy.NativeArray, Iterable]: - """ - Return the input item in its native backend framework form if it is an ivy.Array - instance, otherwise the input is returned unchanged. If nested is set, the check is - applied to all nested leaves of tuples, lists and dicts contained within ``x``. + """Return the input item in its native backend framework form if it is an + ivy.Array instance, otherwise the input is returned unchanged. If nested is + set, the check is applied to all nested leaves of tuples, lists and dicts + contained within ``x``. Parameters ---------- @@ -157,14 +241,14 @@ def to_native( def args_to_native( *args: Iterable[Any], - include_derived: Dict[str, bool] = None, + include_derived: Optional[Dict[str, bool]] = None, cont_inplace: bool = False, to_ignore: Optional[Union[type, Tuple[type]]] = None, **kwargs: Dict[str, Any], ) -> Tuple[Iterable[Any], Dict[str, Any]]: - """ - Return args and keyword args in their native backend framework form for all nested - ivy.Array instances, otherwise the arguments are returned unchanged. + """Return args and keyword args in their native backend framework form for + all nested ivy.Array instances, otherwise the arguments are returned + unchanged. Parameters ---------- @@ -200,3 +284,110 @@ def args_to_native( shallow=False, ) return native_args, native_kwargs + + +def to_new_backend( + x: Union[ivy.Array, ivy.NativeArray, Iterable], + native: bool = True, + nested: bool = False, + include_derived: Optional[Dict[str, bool]] = None, + cont_inplace: bool = False, + to_ignore: Optional[Union[type, Tuple[type]]] = None, +) -> Union[ivy.Array, ivy.NativeArray, Iterable]: + """Return the input array converted to new backend framework form if it is + an `ivy.Array`, `ivy.NativeArray` or NativeVariable instance. If nested is + set, the check is applied to all nested leaves of tuples, lists and dicts + contained within ``x``. + + Parameters + ---------- + x + The input to maybe convert. + native + Whether to return the new array as a `ivy.NativeArray`, NativeVariable + or an `ivy.Array`. Default is ``True``. + nested + Whether to apply the conversion on arguments in a nested manner. If so, all + dicts, lists and tuples will be traversed to their lowest leaves in search of + ivy.Array instances. Default is ``False``. + include_derived + Whether to also recursive for classes derived from tuple, list and dict. + Default is ``False``. + cont_inplace + Whether to update containers in place. Default is ``False`` + to_ignore + Types to ignore when deciding whether to go deeper into the nest or not + + Returns + ------- + ret + the input in the new backend framework form in the case of array instances. + """ + if nested: + return ivy.nested_map( + lambda x: _to_new_backend( + x, native=native, inplace=cont_inplace, to_ignore=to_ignore + ), + x, + include_derived, + shallow=False, + ) + return _to_new_backend(x, native=native, inplace=cont_inplace, to_ignore=to_ignore) + + +def args_to_new_backend( + *args: Iterable[Any], + native: bool = True, + shallow: bool = True, + include_derived: Optional[Dict[str, bool]] = None, + cont_inplace: bool = False, + to_ignore: Optional[Union[type, Tuple[type]]] = None, + **kwargs: Dict[str, Any], +) -> Tuple[Iterable[Any], Dict[str, Any]]: + """Return args and keyword args in the new current backend framework for + all nested ivy.Array, ivy.NativeArray or NativeVariable instances. + + Parameters + ---------- + args + The positional arguments to check + native + Whether to return the new array as a ivy.NativeArray, NativeVariable + or an ivy.Array. Default is ``True``. + include_derived + Whether to also recursive for classes derived from tuple, list and dict. + Default is ``False``. + cont_inplace + Whether to update containers in place. + Default is ``False`` + to_ignore + Types to ignore when deciding whether to go deeper into the nest or not + shallow + Whether to inplace update the input nest or not + Only works if nest is a mutable type. Default is ``True``. + kwargs + The key-word arguments to check + + Returns + ------- + ret + The same arguments, with any nested array instances converted + to the new backend. + """ + new_args = ivy.nested_map( + lambda x: _to_new_backend( + x, native=native, inplace=cont_inplace, to_ignore=to_ignore + ), + args, + include_derived, + shallow=shallow, + ) + new_kwargs = ivy.nested_map( + lambda x: _to_new_backend( + x, native=native, inplace=cont_inplace, to_ignore=to_ignore + ), + kwargs, + include_derived, + shallow=shallow, + ) + return new_args, new_kwargs diff --git a/ivy/data_classes/array/creation.py b/ivy/data_classes/array/creation.py index 94e2ab7a096d3..6486096f38b13 100644 --- a/ivy/data_classes/array/creation.py +++ b/ivy/data_classes/array/creation.py @@ -21,10 +21,9 @@ def asarray( device: Optional[Union[ivy.Device, ivy.NativeDevice]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.asarray. This method simply wraps the - function, and so the docstring for ivy.asarray also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.asarray. This method simply + wraps the function, and so the docstring for ivy.asarray also applies + to this method with minimal changes. Parameters ---------- @@ -87,10 +86,9 @@ def full_like( device: Optional[Union[ivy.Device, ivy.NativeDevice]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.full_like. This method simply wraps the - function, and so the docstring for ivy.full_like also applies to this method - with minimal changes. + """ivy.Array instance method variant of ivy.full_like. This method + simply wraps the function, and so the docstring for ivy.full_like also + applies to this method with minimal changes. Parameters ---------- @@ -151,10 +149,9 @@ def ones_like( device: Optional[Union[ivy.Device, ivy.NativeDevice]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.ones_like. This method simply wraps the - function, and so the docstring for ivy.ones_like also applies to this method - with minimal changes. + """ivy.Array instance method variant of ivy.ones_like. This method + simply wraps the function, and so the docstring for ivy.ones_like also + applies to this method with minimal changes. Parameters ---------- @@ -185,10 +182,9 @@ def zeros_like( device: Optional[Union[ivy.Device, ivy.NativeDevice]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.zeros_like. This method simply wraps - the function, and so the docstring for ivy.zeros_like also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.zeros_like. This method + simply wraps the function, and so the docstring for ivy.zeros_like also + applies to this method with minimal changes. Parameters ---------- @@ -214,10 +210,9 @@ def zeros_like( def tril( self: ivy.Array, /, *, k: int = 0, out: Optional[ivy.Array] = None ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.tril. This method simply wraps the - function, and so the docstring for ivy.tril also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.tril. This method simply + wraps the function, and so the docstring for ivy.tril also applies to + this method with minimal changes. Parameters ---------- @@ -245,10 +240,9 @@ def tril( def triu( self: ivy.Array, /, *, k: int = 0, out: Optional[ivy.Array] = None ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.triu. This method simply wraps the - function, and so the docstring for ivy.triu also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.triu. This method simply + wraps the function, and so the docstring for ivy.triu also applies to + this method with minimal changes. Parameters ---------- @@ -281,10 +275,9 @@ def empty_like( device: Optional[Union[ivy.Device, ivy.NativeDevice]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.empty_like. This method simply wraps - the function, and so the docstring for ivy.empty_like also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.empty_like. This method + simply wraps the function, and so the docstring for ivy.empty_like also + applies to this method with minimal changes. Parameters ---------- @@ -315,10 +308,9 @@ def meshgrid( sparse: bool = False, indexing: str = "xy", ) -> List[ivy.Array]: - """ - ivy.Array instance method variant of ivy.meshgrid. This method simply wraps the - function, and so the docstring for ivy.meshgrid also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.meshgrid. This method + simply wraps the function, and so the docstring for ivy.meshgrid also + applies to this method with minimal changes. Parameters ---------- @@ -351,10 +343,9 @@ def from_dlpack( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.from_dlpack. This method simply wraps - the function, and so the docstring for ivy.from_dlpack also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.from_dlpack. This method + simply wraps the function, and so the docstring for ivy.from_dlpack + also applies to this method with minimal changes. Parameters ---------- @@ -381,10 +372,9 @@ def copy_array( to_ivy_array: bool = True, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.copy_array. This method simply wraps - the function, and so the docstring for ivy.copy_array also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.copy_array. This method + simply wraps the function, and so the docstring for ivy.copy_array also + applies to this method with minimal changes. Parameters ---------- @@ -412,10 +402,9 @@ def native_array( dtype: Optional[Union[ivy.Dtype, ivy.NativeDtype]] = None, device: Optional[Union[ivy.Device, ivy.NativeDevice]] = None, ) -> ivy.NativeArray: - """ - ivy.Array instance method variant of ivy.native_array. This method simply wraps - the function, and so the docstring for ivy.native_array also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.native_array. This method + simply wraps the function, and so the docstring for ivy.native_array + also applies to this method with minimal changes. Parameters ---------- @@ -445,10 +434,9 @@ def one_hot( device: Optional[Union[ivy.Device, ivy.NativeDevice]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.one_hot. This method simply wraps the - function, and so the docstring for ivy.one_hot also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.one_hot. This method simply + wraps the function, and so the docstring for ivy.one_hot also applies + to this method with minimal changes. Parameters ---------- @@ -549,10 +537,9 @@ def logspace( device: Optional[Union[ivy.Device, ivy.NativeDevice]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.logspace. This method simply wraps the - function, and so the docstring for ivy.logspace also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.logspace. This method + simply wraps the function, and so the docstring for ivy.logspace also + applies to this method with minimal changes. Parameters ---------- diff --git a/ivy/data_classes/array/data_type.py b/ivy/data_classes/array/data_type.py index 01cdedea04c58..afaaade47303c 100644 --- a/ivy/data_classes/array/data_type.py +++ b/ivy/data_classes/array/data_type.py @@ -18,9 +18,8 @@ def astype( copy: bool = True, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Copy an array to a specified data type irrespective of :ref:`type- promotion` - rules. + """Copy an array to a specified data type irrespective of :ref:`type- + promotion` rules. .. note:: Casting floating-point ``NaN`` and ``infinity`` values to integral data types @@ -69,10 +68,10 @@ def astype( def broadcast_arrays( self: ivy.Array, *arrays: Union[ivy.Array, ivy.NativeArray] ) -> List[ivy.Array]: - """ - `ivy.Array` instance method variant of `ivy.broadcast_arrays`. This method - simply wraps the function, and so the docstring for `ivy.broadcast_arrays` also - applies to this method with minimal changes. + """`ivy.Array` instance method variant of `ivy.broadcast_arrays`. This + method simply wraps the function, and so the docstring for + `ivy.broadcast_arrays` also applies to this method with minimal + changes. Parameters ---------- @@ -113,10 +112,9 @@ def broadcast_arrays( def broadcast_to( self: ivy.Array, /, shape: Tuple[int, ...], *, out: Optional[ivy.Array] = None ) -> ivy.Array: - """ - `ivy.Array` instance method variant of `ivy.broadcast_to`. This method simply - wraps the function, and so the docstring for `ivy.broadcast_to` also applies to - this method with minimal changes. + """`ivy.Array` instance method variant of `ivy.broadcast_to`. This + method simply wraps the function, and so the docstring for + `ivy.broadcast_to` also applies to this method with minimal changes. Parameters ---------- @@ -146,10 +144,9 @@ def broadcast_to( return ivy.broadcast_to(self._data, shape=shape, out=out) def can_cast(self: ivy.Array, to: ivy.Dtype) -> bool: - """ - `ivy.Array` instance method variant of `ivy.can_cast`. This method simply wraps - the function, and so the docstring for `ivy.can_cast` also applies to this - method with minimal changes. + """`ivy.Array` instance method variant of `ivy.can_cast`. This method + simply wraps the function, and so the docstring for `ivy.can_cast` also + applies to this method with minimal changes. Parameters ---------- @@ -179,9 +176,8 @@ def can_cast(self: ivy.Array, to: ivy.Dtype) -> bool: def dtype( self: ivy.Array, as_native: bool = False ) -> Union[ivy.Dtype, ivy.NativeDtype]: - """ - `ivy.Array` instance method variant of `ivy.dtype`. This method helps to get the - data type of the array. + """`ivy.Array` instance method variant of `ivy.dtype`. This method + helps to get the data type of the array. Parameters ---------- @@ -212,8 +208,7 @@ def dtype( return ivy.dtype(self._data, as_native=as_native) def finfo(self: ivy.Array, /) -> Finfo: - """ - Array instance method variant of `ivy.finfo`. + """Array instance method variant of `ivy.finfo`. Parameters ---------- @@ -235,10 +230,9 @@ def finfo(self: ivy.Array, /) -> Finfo: return ivy.finfo(self._data) def iinfo(self: ivy.Array, /) -> Iinfo: - """ - `ivy.Array` instance method variant of `ivy.iinfo`. This method simply wraps the - function, and so the docstring for `ivy.iinfo` also applies to this method with - minimal changes. + """`ivy.Array` instance method variant of `ivy.iinfo`. This method + simply wraps the function, and so the docstring for `ivy.iinfo` also + applies to this method with minimal changes. Parameters ---------- @@ -267,9 +261,8 @@ def is_bool_dtype(self: ivy.Array) -> bool: return ivy.is_bool_dtype(self._data) def is_float_dtype(self: ivy.Array) -> bool: - """ - `ivy.Array` instance method variant of `ivy.is_float_dtype`. This method simply - checks to see if the array is of type `float`. + """`ivy.Array` instance method variant of `ivy.is_float_dtype`. This + method simply checks to see if the array is of type `float`. Parameters ---------- @@ -303,10 +296,9 @@ def result_type( self: ivy.Array, *arrays_and_dtypes: Union[ivy.Array, ivy.NativeArray, ivy.Dtype], ) -> ivy.Dtype: - """ - `ivy.Array` instance method variant of `ivy.result_type`. This method simply - wraps the function, and so the docstring for `ivy.result_type` also applies to - this method with minimal changes. + """`ivy.Array` instance method variant of `ivy.result_type`. This + method simply wraps the function, and so the docstring for + `ivy.result_type` also applies to this method with minimal changes. Parameters ---------- diff --git a/ivy/data_classes/array/device.py b/ivy/data_classes/array/device.py index f0eb01d3b048f..18ac9887abd27 100644 --- a/ivy/data_classes/array/device.py +++ b/ivy/data_classes/array/device.py @@ -12,10 +12,9 @@ class _ArrayWithDevice(abc.ABC): def dev( self: ivy.Array, *, as_native: bool = False ) -> Union[ivy.Device, ivy.NativeDevice]: - """ - ivy.Array instance method variant of ivy.dev. This method simply wraps the - function, and so the docstring for ivy.dev also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.dev. This method simply + wraps the function, and so the docstring for ivy.dev also applies to + this method with minimal changes. Parameters ---------- @@ -40,10 +39,9 @@ def to_device( stream: Optional[Union[int, Any]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.to_device. This method simply wraps the - function, and so the docstring for ivy.to_device also applies to this method - with minimal changes. + """ivy.Array instance method variant of ivy.to_device. This method + simply wraps the function, and so the docstring for ivy.to_device also + applies to this method with minimal changes. Parameters ---------- diff --git a/ivy/data_classes/array/elementwise.py b/ivy/data_classes/array/elementwise.py index f33601eac27da..35a79eb00ee3d 100644 --- a/ivy/data_classes/array/elementwise.py +++ b/ivy/data_classes/array/elementwise.py @@ -14,10 +14,9 @@ def abs( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: # noqa - """ - ivy.Array instance method variant of ivy.abs. This method simply wraps the - function, and so the docstring for ivy.abs also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.abs. This method simply + wraps the function, and so the docstring for ivy.abs also applies to + this method with minimal changes. Parameters ---------- @@ -43,10 +42,9 @@ def abs( return ivy.abs(self, out=out) def acosh(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.acosh. This method simply wraps the - function, and so the docstring for ivy.acosh also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.acosh. This method simply + wraps the function, and so the docstring for ivy.acosh also applies to + this method with minimal changes. Parameters ---------- @@ -74,10 +72,9 @@ def acosh(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: return ivy.acosh(self._data, out=out) def acos(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.acos. This method simply wraps the - function, and so the docstring for ivy.acos also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.acos. This method simply + wraps the function, and so the docstring for ivy.acos also applies to + this method with minimal changes. Parameters ---------- @@ -110,10 +107,9 @@ def add( alpha: Optional[Union[int, float]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.add. This method simply wraps the - function, and so the docstring for ivy.add also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.add. This method simply + wraps the function, and so the docstring for ivy.add also applies to + this method with minimal changes. Parameters ---------- @@ -151,10 +147,9 @@ def add( return ivy.add(self._data, x2, alpha=alpha, out=out) def asin(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.asin. This method simply wraps the - function, and so the docstring for ivy.asin also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.asin. This method simply + wraps the function, and so the docstring for ivy.asin also applies to + this method with minimal changes. Parameters ---------- @@ -188,10 +183,9 @@ def asin(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: return ivy.asin(self._data, out=out) def asinh(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.asinh. This method simply wraps the - function, and so the docstring for ivy.asinh also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.asinh. This method simply + wraps the function, and so the docstring for ivy.asinh also applies to + this method with minimal changes. Parameters ---------- @@ -219,10 +213,9 @@ def asinh(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: return ivy.asinh(self._data, out=out) def atan(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.atan. This method simply wraps the - function, and so the docstring for ivy.atan also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.atan. This method simply + wraps the function, and so the docstring for ivy.atan also applies to + this method with minimal changes. Parameters ---------- @@ -254,10 +247,9 @@ def atan2( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.atan2. This method simply wraps the - function, and so the docstring for ivy.atan2 also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.atan2. This method simply + wraps the function, and so the docstring for ivy.atan2 also applies to + this method with minimal changes. Parameters ---------- @@ -329,10 +321,9 @@ def atan2( return ivy.atan2(self._data, x2, out=out) def atanh(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.atanh. This method simply wraps the - function, and so the docstring for ivy.atanh also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.atanh. This method simply + wraps the function, and so the docstring for ivy.atanh also applies to + this method with minimal changes. Parameters ---------- @@ -366,10 +357,9 @@ def bitwise_and( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.bitwise_and. This method simply wraps - the function, and so the docstring for ivy.bitwise_and also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.bitwise_and. This method + simply wraps the function, and so the docstring for ivy.bitwise_and + also applies to this method with minimal changes. Parameters ---------- @@ -412,10 +402,10 @@ def bitwise_left_shift( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.bitwise_left_shift. This method simply - wraps the function, and so the docstring for ivy.bitwise_left_shift also applies - to this method with minimal changes. + """ivy.Array instance method variant of ivy.bitwise_left_shift. This + method simply wraps the function, and so the docstring for + ivy.bitwise_left_shift also applies to this method with minimal + changes. Parameters ---------- @@ -441,10 +431,9 @@ def bitwise_left_shift( def bitwise_invert( self: ivy.Array, *, out: Optional[ivy.Array] = None ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.bitwise_invert. This method simply - wraps the function, and so the docstring for ivy.bitiwse_invert also applies to - this method with minimal changes. + """ivy.Array instance method variant of ivy.bitwise_invert. This method + simply wraps the function, and so the docstring for ivy.bitiwse_invert + also applies to this method with minimal changes. Parameters ---------- @@ -482,10 +471,9 @@ def bitwise_or( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.bitwise_or. This method simply wraps - the function, and so the docstring for ivy.bitwise_or also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.bitwise_or. This method + simply wraps the function, and so the docstring for ivy.bitwise_or also + applies to this method with minimal changes. Parameters ---------- @@ -521,10 +509,10 @@ def bitwise_right_shift( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.bitwise_right_shift. This method simply - wraps the function, and so the docstring for ivy.bitwise_right_shift also - applies to this method with minimal changes. + """ivy.Array instance method variant of ivy.bitwise_right_shift. This + method simply wraps the function, and so the docstring for + ivy.bitwise_right_shift also applies to this method with minimal + changes. Parameters ---------- @@ -562,10 +550,9 @@ def bitwise_xor( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.bitwise_xor. This method simply wraps - the function, and so the docstring for ivy.bitwise_xor also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.bitwise_xor. This method + simply wraps the function, and so the docstring for ivy.bitwise_xor + also applies to this method with minimal changes. Parameters ---------- @@ -597,10 +584,9 @@ def bitwise_xor( return ivy.bitwise_xor(self._data, x2, out=out) def ceil(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.ceil. This method simply wraps the - function, and so the docstring for ivy.ceil also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.ceil. This method simply + wraps the function, and so the docstring for ivy.ceil also applies to + this method with minimal changes. Parameters ---------- @@ -626,10 +612,9 @@ def ceil(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: return ivy.ceil(self._data, out=out) def cos(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.cos. This method simply wraps the - function, and so the docstring for ivy.cos also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.cos. This method simply + wraps the function, and so the docstring for ivy.cos also applies to + this method with minimal changes. Parameters ---------- @@ -670,10 +655,9 @@ def cos(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: return ivy.cos(self._data, out=out) def cosh(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.cosh. This method simply wraps the - function, and so the docstring for ivy.cosh also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.cosh. This method simply + wraps the function, and so the docstring for ivy.cosh also applies to + this method with minimal changes. Parameters ---------- @@ -711,10 +695,9 @@ def divide( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.divide. This method simply wraps the - function, and so the docstring for ivy.divide also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.divide. This method simply + wraps the function, and so the docstring for ivy.divide also applies to + this method with minimal changes. Parameters ---------- @@ -762,10 +745,9 @@ def equal( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.equal. This method simply wraps the - function, and so the docstring for ivy.equal also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.equal. This method simply + wraps the function, and so the docstring for ivy.equal also applies to + this method with minimal changes. Parameters ---------- @@ -825,10 +807,9 @@ def equal( return ivy.equal(self._data, x2, out=out) def exp(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.exp. This method simply wraps the - function, and so the docstring for ivy.exp also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.exp. This method simply + wraps the function, and so the docstring for ivy.exp also applies to + this method with minimal changes. Parameters ---------- @@ -854,10 +835,9 @@ def exp(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: return ivy.exp(self._data, out=out) def expm1(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.expm1. This method simply wraps the - function, and so the docstring for ivy.expm1 also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.expm1. This method simply + wraps the function, and so the docstring for ivy.expm1 also applies to + this method with minimal changes. Parameters ---------- @@ -890,10 +870,9 @@ def expm1(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: return ivy.expm1(self._data, out=out) def floor(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.floor. This method simply wraps the - function, and so the docstring for ivy.floor also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.floor. This method simply + wraps the function, and so the docstring for ivy.floor also applies to + this method with minimal changes. Parameters ---------- @@ -925,10 +904,9 @@ def floor_divide( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.floor_divide. This method simply wraps - the function, and so the docstring for ivy.floor_divide also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.floor_divide. This method + simply wraps the function, and so the docstring for ivy.floor_divide + also applies to this method with minimal changes. Parameters ---------- @@ -976,10 +954,9 @@ def fmin( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.fmin. This method simply wraps the - function, and so the docstring for ivy.fmin also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.fmin. This method simply + wraps the function, and so the docstring for ivy.fmin also applies to + this method with minimal changes. Parameters ---------- @@ -1016,10 +993,9 @@ def greater( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.greater. This method simply wraps the - function, and so the docstring for ivy.greater also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.greater. This method simply + wraps the function, and so the docstring for ivy.greater also applies + to this method with minimal changes. Parameters ---------- @@ -1056,10 +1032,9 @@ def greater_equal( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.greater_equal. This method simply wraps - the function, and so the docstring for ivy.greater_equal also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.greater_equal. This method + simply wraps the function, and so the docstring for ivy.greater_equal + also applies to this method with minimal changes. Parameters ---------- @@ -1090,10 +1065,9 @@ def greater_equal( return ivy.greater_equal(self._data, x2, out=out) def isfinite(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.isfinite. This method simply wraps the - function, and so the docstring for ivy.isfinite also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.isfinite. This method + simply wraps the function, and so the docstring for ivy.isfinite also + applies to this method with minimal changes. Parameters ---------- @@ -1126,10 +1100,9 @@ def isinf( detect_negative: bool = True, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.isinf. This method simply wraps the - function, and so the docstring for ivy.isinf also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.isinf. This method simply + wraps the function, and so the docstring for ivy.isinf also applies to + this method with minimal changes. Parameters ---------- @@ -1184,10 +1157,9 @@ def isinf( ) def isnan(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.isnan. This method simply wraps the - function, and so the docstring for ivy.isnan also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.isnan. This method simply + wraps the function, and so the docstring for ivy.isnan also applies to + this method with minimal changes. Parameters ---------- @@ -1245,10 +1217,9 @@ def less( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.less. This method simply wraps the - function, and so the docstring for ivy.less also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.less. This method simply + wraps the function, and so the docstring for ivy.less also applies to + this method with minimal changes. Parameters ---------- @@ -1285,10 +1256,9 @@ def less_equal( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.less_equal. This method simply wraps - the function, and so the docstring for ivy.less_equal also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.less_equal. This method + simply wraps the function, and so the docstring for ivy.less_equal also + applies to this method with minimal changes. Parameters ---------- @@ -1340,10 +1310,9 @@ def less_equal( return ivy.less_equal(self._data, x2, out=out) def log(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.log. This method simply wraps the - function, and so the docstring for ivy.log also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.log. This method simply + wraps the function, and so the docstring for ivy.log also applies to + this method with minimal changes. Parameters ---------- @@ -1384,10 +1353,9 @@ def log(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: return ivy.log(self._data, out=out) def log1p(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.log1p. This method simply wraps the - function, and so the docstring for ivy.log1p also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.log1p. This method simply + wraps the function, and so the docstring for ivy.log1p also applies to + this method with minimal changes. Parameters ---------- @@ -1419,10 +1387,9 @@ def log1p(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: return ivy.log1p(self._data, out=out) def log2(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.log2. This method simply wraps the - function, and so the docstring for ivy.log2 also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.log2. This method simply + wraps the function, and so the docstring for ivy.log2 also applies to + this method with minimal changes. Parameters ---------- @@ -1463,10 +1430,9 @@ def log2(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: return ivy.log2(self._data, out=out) def log10(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.log10. This method simply wraps the - function, and so the docstring for ivy.log10 also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.log10. This method simply + wraps the function, and so the docstring for ivy.log10 also applies to + this method with minimal changes. Parameters ---------- @@ -1513,10 +1479,9 @@ def logaddexp( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.logaddexp. This method simply wraps the - function, and so the docstring for ivy.logaddexp also applies to this method - with minimal changes. + """ivy.Array instance method variant of ivy.logaddexp. This method + simply wraps the function, and so the docstring for ivy.logaddexp also + applies to this method with minimal changes. Parameters ---------- @@ -1554,10 +1519,9 @@ def logaddexp2( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.logaddexp2. This method simply wraps - the function, and so the docstring for ivy.logaddexp2 also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.logaddexp2. This method + simply wraps the function, and so the docstring for ivy.logaddexp2 also + applies to this method with minimal changes. Parameters ---------- @@ -1588,10 +1552,9 @@ def logical_and( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.logical_and. This method simply wraps - the function, and so the docstring for ivy.logical_and also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.logical_and. This method + simply wraps the function, and so the docstring for ivy.logical_and + also applies to this method with minimal changes. Parameters ---------- @@ -1624,10 +1587,9 @@ def logical_and( return ivy.logical_and(self._data, x2, out=out) def logical_not(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.logical_not. This method simply wraps - the function, and so the docstring for ivy.logical_not also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.logical_not. This method + simply wraps the function, and so the docstring for ivy.logical_not + also applies to this method with minimal changes. Parameters ---------- @@ -1664,10 +1626,9 @@ def logical_or( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.logical_or. This method simply wraps - the function, and so the docstring for ivy.logical_or also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.logical_or. This method + simply wraps the function, and so the docstring for ivy.logical_or also + applies to this method with minimal changes. Parameters ---------- @@ -1716,10 +1677,9 @@ def logical_xor( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.logical_xor. This method simply wraps - the function, and so the docstring for ivy.logical_xor also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.logical_xor. This method + simply wraps the function, and so the docstring for ivy.logical_xor + also applies to this method with minimal changes. Parameters ---------- @@ -1756,10 +1716,9 @@ def multiply( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.multiply. This method simply wraps the - function, and so the docstring for ivy.multiply also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.multiply. This method + simply wraps the function, and so the docstring for ivy.multiply also + applies to this method with minimal changes. Parameters ---------- @@ -1808,10 +1767,9 @@ def maximum( use_where: bool = True, out: Optional[ivy.Array] = None, ): - """ - ivy.Array instance method variant of ivy.maximum. This method simply wraps the - function, and so the docstring for ivy.maximum also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.maximum. This method simply + wraps the function, and so the docstring for ivy.maximum also applies + to this method with minimal changes. Parameters ---------- @@ -1867,10 +1825,9 @@ def minimum( use_where: bool = True, out: Optional[ivy.Array] = None, ): - """ - ivy.Array instance method variant of ivy.minimum. This method simply wraps the - function, and so the docstring for ivy.minimum also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.minimum. This method simply + wraps the function, and so the docstring for ivy.minimum also applies + to this method with minimal changes. Parameters ---------- @@ -1919,10 +1876,9 @@ def minimum( return ivy.minimum(self, x2, use_where=use_where, out=out) def negative(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.negative. This method simply wraps the - function, and so the docstring for ivy.negative also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.negative. This method + simply wraps the function, and so the docstring for ivy.negative also + applies to this method with minimal changes. Parameters ---------- @@ -1969,10 +1925,9 @@ def not_equal( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.not_equal. This method simply wraps the - function, and so the docstring for ivy.not_equal also applies to this method - with minimal changes. + """ivy.Array instance method variant of ivy.not_equal. This method + simply wraps the function, and so the docstring for ivy.not_equal also + applies to this method with minimal changes. Parameters ---------- @@ -2031,10 +1986,9 @@ def not_equal( return ivy.not_equal(self._data, x2, out=out) def positive(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.positive. This method simply wraps the - function, and so the docstring for ivy.positive also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.positive. This method + simply wraps the function, and so the docstring for ivy.positive also + applies to this method with minimal changes. Parameters ---------- @@ -2081,10 +2035,9 @@ def pow( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.pow. This method simply wraps the - function, and so the docstring for ivy.pow also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.pow. This method simply + wraps the function, and so the docstring for ivy.pow also applies to + this method with minimal changes. Parameters ---------- @@ -2124,10 +2077,9 @@ def pow( return ivy.pow(self._data, x2, out=out) def real(self: ivy.Array, /, *, out: Optional[ivy.Array] = None) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.real. This method simply wraps the - function, and so the docstring for ivy.real also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.real. This method simply + wraps the function, and so the docstring for ivy.real also applies to + this method with minimal changes. Parameters ---------- @@ -2160,10 +2112,9 @@ def remainder( modulus: bool = True, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.remainder. This method simply wraps the - function, and so the docstring for ivy.remainder also applies to this method - with minimal changes. + """ivy.Array instance method variant of ivy.remainder. This method + simply wraps the function, and so the docstring for ivy.remainder also + applies to this method with minimal changes. Parameters ---------- @@ -2211,10 +2162,9 @@ def remainder( def round( self: ivy.Array, *, decimals: int = 0, out: Optional[ivy.Array] = None ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.round. This method simply wraps the - function, and so the docstring for ivy.round also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.round. This method simply + wraps the function, and so the docstring for ivy.round also applies to + this method with minimal changes. Parameters ---------- @@ -2266,10 +2216,9 @@ def sign( np_variant: Optional[bool] = True, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.sign. This method simply wraps the - function, and so the docstring for ivy.sign also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.sign. This method simply + wraps the function, and so the docstring for ivy.sign also applies to + this method with minimal changes. Parameters ---------- @@ -2306,10 +2255,9 @@ def sign( return ivy.sign(self._data, np_variant=np_variant, out=out) def sin(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.sin. This method simply wraps the - function, and so the docstring for ivy.sin also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.sin. This method simply + wraps the function, and so the docstring for ivy.sin also applies to + this method with minimal changes. Parameters ---------- @@ -2337,10 +2285,9 @@ def sin(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: return ivy.sin(self._data, out=out) def sinh(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.sinh. This method simply wraps the - function, and so the docstring for ivy.sinh also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.sinh. This method simply + wraps the function, and so the docstring for ivy.sinh also applies to + this method with minimal changes. Parameters ---------- @@ -2372,10 +2319,9 @@ def sinh(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: return ivy.sinh(self._data, out=out) def square(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.square. This method simply wraps the - function, and so the docstring for ivy.square also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.square. This method simply + wraps the function, and so the docstring for ivy.square also applies to + this method with minimal changes. Parameters ---------- @@ -2409,10 +2355,9 @@ def square(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: return ivy.square(self._data, out=out) def sqrt(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.sqrt. This method simply wraps the - function, and so the docstring for ivy.sqrt also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.sqrt. This method simply + wraps the function, and so the docstring for ivy.sqrt also applies to + this method with minimal changes. Parameters ---------- @@ -2449,10 +2394,9 @@ def subtract( alpha: Optional[Union[int, float]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.subtract. This method simply wraps the - function, and so the docstring for ivy.subtract also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.subtract. This method + simply wraps the function, and so the docstring for ivy.subtract also + applies to this method with minimal changes. Parameters ---------- @@ -2499,10 +2443,9 @@ def trapz( axis: int = -1, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.trapz. This method simply wraps the - function, and so the docstring for ivy.trapz also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.trapz. This method simply + wraps the function, and so the docstring for ivy.trapz also applies to + this method with minimal changes. Parameters ---------- @@ -2543,10 +2486,9 @@ def trapz( return ivy.trapz(self._data, x=x, dx=dx, axis=axis, out=out) def tan(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.tan. This method simply wraps the - function, and so the docstring for ivy.tan also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.tan. This method simply + wraps the function, and so the docstring for ivy.tan also applies to + this method with minimal changes. Parameters ---------- @@ -2579,10 +2521,9 @@ def tanh( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.tanh. This method simply wraps the - function, and so the docstring for ivy.tanh also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.tanh. This method simply + wraps the function, and so the docstring for ivy.tanh also applies to + this method with minimal changes. Parameters ---------- @@ -2613,10 +2554,9 @@ def tanh( return ivy.tanh(self._data, complex_mode=complex_mode, out=out) def trunc(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.trunc. This method simply wraps the - function, and so the docstring for ivy.trunc also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.trunc. This method simply + wraps the function, and so the docstring for ivy.trunc also applies to + this method with minimal changes. Parameters ---------- @@ -2642,10 +2582,9 @@ def trunc(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: return ivy.trunc(self._data, out=out) def erf(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.erf. This method simply wraps the - function, and so the docstring for ivy.erf also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.erf. This method simply + wraps the function, and so the docstring for ivy.erf also applies to + this method with minimal changes. Parameters ---------- @@ -2674,10 +2613,9 @@ def exp2( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.exp2. This method simply wraps the - function, and so the docstring for ivy.exp2 also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.exp2. This method simply + wraps the function, and so the docstring for ivy.exp2 also applies to + this method with minimal changes. Parameters ---------- @@ -2709,10 +2647,9 @@ def gcd( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.gcd. This method simply wraps the - function, and so the docstring for ivy.gcd also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.gcd. This method simply + wraps the function, and so the docstring for ivy.gcd also applies to + this method with minimal changes. Parameters ---------- @@ -2750,10 +2687,9 @@ def nan_to_num( neginf: Optional[Union[float, int]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.nan_to_num. This method simply wraps - the function, and so the docstring for ivy.nan_to_num also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.nan_to_num. This method + simply wraps the function, and so the docstring for ivy.nan_to_num also + applies to this method with minimal changes. Parameters ---------- @@ -2795,41 +2731,6 @@ def nan_to_num( self._data, copy=copy, nan=nan, posinf=posinf, neginf=neginf, out=out ) - def imag( - self: ivy.Array, - /, - *, - out: Optional[ivy.Array] = None, - ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.imag. This method simply wraps the - function, and so the docstring for ivy.imag also applies to this method with - minimal changes. - - Parameters - ---------- - self - Array-like input. - out - optional output array, for writing the result to. - - Returns - ------- - ret - Returns an array with the imaginary part of complex numbers. - - Examples - -------- - >>> b = ivy.array(np.array([1+2j, 3+4j, 5+6j])) - >>> b - ivy.array([1.+2.j, 3.+4.j, 5.+6.j]) - >>> ivy.imag(b) - ivy.array([2., 4., 6.]) - >>> b.imag() - ivy.array([2., 4., 6.]) - """ - return ivy.imag(self._data, out=out) - def angle( self: ivy.Array, /, @@ -2837,10 +2738,9 @@ def angle( deg: bool = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.angle. This method simply wraps the - function, and so the docstring for ivy.angle also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.angle. This method simply + wraps the function, and so the docstring for ivy.angle also applies to + this method with minimal changes. Parameters ---------- @@ -2878,10 +2778,9 @@ def reciprocal( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.reciprocal.This method simply wraps the - function, and so the docstring for ivy.reciprocal also applies to this method - with minimal changes. + """ivy.Array instance method variant of ivy.reciprocal.This method + simply wraps the function, and so the docstring for ivy.reciprocal also + applies to this method with minimal changes. Parameters ---------- @@ -2906,10 +2805,9 @@ def reciprocal( return ivy.reciprocal(self._data, out=out) def deg2rad(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.deg2rad. This method simply wraps the - function, and so the docstring for ivy.deg2rad also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.deg2rad. This method simply + wraps the function, and so the docstring for ivy.deg2rad also applies + to this method with minimal changes. Parameters ---------- @@ -2936,10 +2834,9 @@ def deg2rad(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: return ivy.deg2rad(self._data, out=out) def rad2deg(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.rad2deg. This method simply wraps the - function, and so the docstring for ivy.rad2deg also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.rad2deg. This method simply + wraps the function, and so the docstring for ivy.rad2deg also applies + to this method with minimal changes. Parameters ---------- @@ -2972,10 +2869,9 @@ def trunc_divide( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.trunc_divide. This method simply wraps - the function, and so the docstring for ivy.trunc_divide also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.trunc_divide. This method + simply wraps the function, and so the docstring for ivy.trunc_divide + also applies to this method with minimal changes. Parameters ---------- @@ -3009,10 +2905,9 @@ def trunc_divide( return ivy.trunc_divide(self._data, x2, out=out) def isreal(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.isreal. This method simply wraps the - function, and so the docstring for ivy.isreal also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.isreal. This method simply + wraps the function, and so the docstring for ivy.isreal also applies to + this method with minimal changes. Parameters ---------- @@ -3040,10 +2935,9 @@ def isreal(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: def lcm( self: ivy.Array, x2: ivy.Array, *, out: Optional[ivy.Array] = None ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.lcm. This method simply wraps the - function, and so the docstring for ivy.lcm also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.lcm. This method simply + wraps the function, and so the docstring for ivy.lcm also applies to + this method with minimal changes. Parameters ---------- diff --git a/ivy/data_classes/array/experimental/activations.py b/ivy/data_classes/array/experimental/activations.py index 881c0f4b537c4..5798896266b90 100644 --- a/ivy/data_classes/array/experimental/activations.py +++ b/ivy/data_classes/array/experimental/activations.py @@ -15,10 +15,9 @@ def logit( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.logit. This method simply wraps the - function, and so the docstring for ivy.logit also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.logit. This method simply + wraps the function, and so the docstring for ivy.logit also applies to + this method with minimal changes. Parameters ---------- @@ -60,10 +59,9 @@ def thresholded_relu( threshold: Union[int, float] = 0, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.thresholded_relu. This method simply - wraps the function, and so the docstring for ivy.thresholded_relu also applies - to this method with minimal changes. + """ivy.Array instance method variant of ivy.thresholded_relu. This + method simply wraps the function, and so the docstring for + ivy.thresholded_relu also applies to this method with minimal changes. Parameters ---------- @@ -97,8 +95,7 @@ def prelu( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Prelu takes input data (Array) and slope array as input, + """Prelu takes input data (Array) and slope array as input, and produces one output data (array) where the function f(x) = slope * x for x < 0, f(x) = x for x >= 0., is applied @@ -130,8 +127,7 @@ def relu6( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Apply the rectified linear unit 6 function element-wise. + """Apply the rectified linear unit 6 function element-wise. Parameters ---------- @@ -171,10 +167,9 @@ def logsigmoid( self: ivy.Array, complex_mode: Literal["split", "magnitude", "jax"] = "jax", ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.logsigmoid. This method simply wraps - the function, and so the docstring for ivy.logsigmoid also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.logsigmoid. This method + simply wraps the function, and so the docstring for ivy.logsigmoid also + applies to this method with minimal changes. Parameters ---------- @@ -203,8 +198,7 @@ def logsigmoid( return ivy.logsigmoid(self._data, complex_mode=complex_mode) def selu(self, /, *, out: Optional[ivy.Array] = None) -> ivy.Array: - """ - Apply the scaled exponential linear unit function element-wise. + """Apply the scaled exponential linear unit function element-wise. Parameters ---------- @@ -240,10 +234,9 @@ def selu(self, /, *, out: Optional[ivy.Array] = None) -> ivy.Array: return ivy.selu(self._data, out=out) def silu(self: ivy.Array, /, *, out: Optional[ivy.Array] = None) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.silu. This method simply wraps the - function, and so the docstring for ivy.silu also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.silu. This method simply + wraps the function, and so the docstring for ivy.silu also applies to + this method with minimal changes. Parameters ---------- @@ -269,10 +262,9 @@ def elu( alpha: float = 1.0, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Ivy.Array instance method variant of ivy.elu. This method simply wraps the - function, and so the docstring for ivy.elu also applies to this method with - minimal. + """Ivy.Array instance method variant of ivy.elu. This method simply + wraps the function, and so the docstring for ivy.elu also applies to + this method with minimal. Parameters ---------- @@ -306,10 +298,9 @@ def hardtanh( min_val: float = -1, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.hardtanh. This method simply wraps the - function, and so the docstring for ivy.hardtanh also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.hardtanh. This method + simply wraps the function, and so the docstring for ivy.hardtanh also + applies to this method with minimal changes. Parameters ---------- @@ -334,15 +325,14 @@ def hardtanh( >>> x = ivy.array([-1., .2, 1.]) >>> y = x.hardtanh() >>> print(y) - ivy.array([-1., 1., 1.]) + ivy.array([-1. , 0.2, 1. ]) """ return ivy.hardtanh(self._data, min_val=min_val, max_val=max_val, out=out) def tanhshrink(self: ivy.Array, /, *, out: Optional[ivy.Array] = None) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.tanhshrink. This method simply wraps - the function, and so the docstring for ivy.tanhshrink also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.tanhshrink. This method + simply wraps the function, and so the docstring for ivy.tanhshrink also + applies to this method with minimal changes. Parameters ---------- @@ -361,6 +351,44 @@ def tanhshrink(self: ivy.Array, /, *, out: Optional[ivy.Array] = None) -> ivy.Ar """ return ivy.tanhshrink(self._data, out=out) + def threshold( + self: ivy.Array, + /, + *, + threshold: Union[int, float], + value: Union[int, float], + out: Optional[ivy.Array] = None, + ) -> ivy.Array: + """ivy.Array instance method variant of ivy.threshold. This method + simply wraps the function, and so the docstring for ivy.threshold also + applies to this method with minimal changes. + + Parameters + ---------- + self + input array. + threshold + threshold value for thresholding operation. + value + value to replace with if thresholding condition is not met. + out + optional output array, for writing the result to. It must have a shape + that the inputs broadcast to. + + Returns + ------- + ret + an array with the thresholding function applied element-wise. + + Examples + -------- + >>> x = ivy.array([-1., 0., 1.]) + >>> y = x.hreshold(threshold=0.5, value=0.0) + >>> print(y) + ivy.array([0.5, 0.5 , 1. ]) + """ + return ivy.threshold(self._data, threshold=threshold, value=value, out=out) + def softshrink( self: ivy.Array, /, @@ -368,10 +396,9 @@ def softshrink( lambd: float = 0.5, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.softshrink. This method simply wraps - the function, and so the docstring for ivy.softshrink also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.softshrink. This method + simply wraps the function, and so the docstring for ivy.softshrink also + applies to this method with minimal changes. Parameters ---------- @@ -409,10 +436,9 @@ def celu( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.celu. This method simply wraps the - function, and so the docstring for ivy.celu also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.celu. This method simply + wraps the function, and so the docstring for ivy.celu also applies to + this method with minimal changes. Parameters ---------- @@ -449,10 +475,9 @@ def scaled_tanh( beta: float = 0.67, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.scaled_tanh. This method simply wraps - the function, and so the docstring for ivy.scaled_tanh also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.scaled_tanh. This method + simply wraps the function, and so the docstring for ivy.scaled_tanh + also applies to this method with minimal changes. Parameters ---------- @@ -498,10 +523,9 @@ def hardshrink( lambd: float = 0.5, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.hardshrink. This method simply wraps - the function, and so the docstring for ivy.hardshrink also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.hardshrink. This method + simply wraps the function, and so the docstring for ivy.hardshrink also + applies to this method with minimal changes. Parameters ---------- @@ -530,3 +554,28 @@ def hardshrink( ivy.array([0., 0., 0.]) """ return ivy.hardshrink(self._data, lambd=lambd, out=out) + + def hardsilu(self, out: Optional[ivy.Array] = None) -> ivy.Array: + """ivy.Array instance method which acts as a wrapper for ivy.hardsilu. + + Parameters + ---------- + self + input array + out + optional output array, for writing the result to. It must have a shape + that the inputs broadcast to. + + Returns + ------- + an array containing the output of the hardsilu/hardswish function applied + to each element in ``x``. + + Examples + -------- + >>> x = ivy.array([1., 2., 3.]) + >>> y = x.hardsilu() + >>> print(y) + ivy.array([0.66666667, 1.66666667, 3.]) + """ + return ivy.hardsilu(self._data, out=out) diff --git a/ivy/data_classes/array/experimental/creation.py b/ivy/data_classes/array/experimental/creation.py index 8fc3459e5cd2b..589f7d9168ace 100644 --- a/ivy/data_classes/array/experimental/creation.py +++ b/ivy/data_classes/array/experimental/creation.py @@ -16,10 +16,9 @@ def eye_like( device: Optional[Union[ivy.Device, ivy.NativeDevice]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.eye_like. This method simply wraps the - function, and so the docstring for ivy.eye_like also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.eye_like. This method + simply wraps the function, and so the docstring for ivy.eye_like also + applies to this method with minimal changes. Parameters ---------- @@ -60,10 +59,10 @@ def unsorted_segment_min( segment_ids: ivy.Array, num_segments: Union[int, ivy.Array], ) -> ivy.Array: - r""" - ivy.Array instance method variant of ivy.unsorted_segment_min. This method - simply wraps the function, and so the docstring for ivy.unsorted_segment_min - also applies to this method with minimal changes. + r"""ivy.Array instance method variant of ivy.unsorted_segment_min. This + method simply wraps the function, and so the docstring for + ivy.unsorted_segment_min also applies to this method with minimal + changes. Note ---- @@ -97,10 +96,10 @@ def unsorted_segment_sum( segment_ids: ivy.Array, num_segments: Union[int, ivy.Array], ) -> ivy.Array: - r""" - ivy.Array instance method variant of ivy.unsorted_segment_sum. This method - simply wraps the function, and so the docstring for ivy.unsorted_segment_sum - also applies to this method with minimal changes. + r"""ivy.Array instance method variant of ivy.unsorted_segment_sum. This + method simply wraps the function, and so the docstring for + ivy.unsorted_segment_sum also applies to this method with minimal + changes. Parameters ---------- @@ -133,10 +132,9 @@ def blackman_window( device: Optional[Union[ivy.Device, ivy.NativeDevice]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.blackman_window. This method simply - wraps the function, and so the docstring for ivy.blackman_window also applies to - this method with minimal changes. + """ivy.Array instance method variant of ivy.blackman_window. This + method simply wraps the function, and so the docstring for + ivy.blackman_window also applies to this method with minimal changes. Parameters ---------- @@ -169,9 +167,7 @@ def blackman_window( ivy.array([-1.38777878e-17, 1.30000000e-01, 6.30000000e-01, 1.00000000e+00, 6.30000000e-01, 1.30000000e-01, -1.38777878e-17]) """ - return ivy.blackman_window( - self._data, periodic=periodic, dtype=dtype, device=device, out=out - ) + return ivy.blackman_window(self._data, periodic=periodic, dtype=dtype, out=out) def trilu( self: ivy.Array, @@ -181,10 +177,9 @@ def trilu( upper: bool = True, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.trilu. This method simply wraps the - function, and so the docstring for ivy.trilu also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.trilu. This method simply + wraps the function, and so the docstring for ivy.trilu also applies to + this method with minimal changes. Parameters ---------- @@ -220,10 +215,10 @@ def mel_weight_matrix( lower_edge_hertz: Optional[Union[float, ivy.Array]] = 0.0, upper_edge_hertz: Optional[Union[float, ivy.Array]] = 3000.0, ): - """ - Generate a MelWeightMatrix that can be used to re-weight a Tensor containing a - linearly sampled frequency spectra (from DFT or STFT) into num_mel_bins - frequency information based on the [lower_edge_hertz, upper_edge_hertz] + """Generate a MelWeightMatrix that can be used to re-weight a Tensor + containing a linearly sampled frequency spectra (from DFT or STFT) into + num_mel_bins frequency information based on the [lower_edge_hertz, + upper_edge_hertz] range on the mel scale. This function defines the mel scale in terms of a frequency in hertz according to the following @@ -265,6 +260,50 @@ def mel_weight_matrix( upper_edge_hertz, ) + def unsorted_segment_mean( + self: ivy.Array, + segment_ids: ivy.Array, + num_segments: Union[int, ivy.Array], + ) -> ivy.Array: + """Compute the mean of values in the array 'self' based on segment + identifiers. + + Parameters + ---------- + self : ivy.Array + The array from which to gather values. + segment_ids : ivy.Array + Must be in the same size with the first dimension of `self`. Has to be + of integer data type. The index-th element of `segment_ids` array is + the segment identifier for the index-th element of `self`. + num_segments : Union[int, ivy.Array] + An integer or array representing the total number of distinct segment IDs. + + Returns + ------- + ret : ivy.Array + The output array, representing the result of a segmented mean operation. + For each segment, it computes the mean of values in `self` where + `segment_ids` equals to segment ID. + + Examples + -------- + >>> data = ivy.array([1.0, 2.0, 3.0, 4.0]) + >>> segment_ids = ivy.array([0, 0, 0, 0]) + >>> num_segments = 1 + >>> result = ivy.unsorted_segment_mean(data, segment_ids, num_segments) + >>> result + ivy.array([2.5]) + + >>> data = ivy.array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0]) + >>> segment_ids = ivy.array([0, 0, 1, 1, 2, 2]) + >>> num_segments = 3 + >>> result = ivy.unsorted_segment_mean(data, segment_ids, num_segments) + >>> result + ivy.array([[1.5, 3.5, 5.5],[1.5, 3.5, 5.5],[1.5, 3.5, 5.5]]) + """ + return ivy.unsorted_segment_mean(self._data, segment_ids, num_segments) + def polyval( coeffs=ivy.Array, @@ -274,9 +313,9 @@ def polyval( dtype: Optional[Union[ivy.Dtype, ivy.NativeDtype]] = None, device: Optional[Union[ivy.Device, ivy.NativeDevice]] = None, ) -> ivy.Array: - """ - ivy.Array instance method of polyval. This method simply wraps the function, and so - the docstring for ivy.polyval also applies to this method with minimal changes. + """ivy.Array instance method of polyval. This method simply wraps the + function, and so the docstring for ivy.polyval also applies to this method + with minimal changes. Evaluate and return a polynomial at specific given values. @@ -291,7 +330,7 @@ def polyval( Returns ------- ret - Simplified result of substituing x in the coefficients - final value of + Simplified result of substituting x in the coefficients - final value of polynomial. Examples @@ -303,6 +342,4 @@ def polyval( return ivy.polyval( coeffs, x, - dtype=dtype, - device=device, ) diff --git a/ivy/data_classes/array/experimental/elementwise.py b/ivy/data_classes/array/experimental/elementwise.py index 31e4245b01f15..80eb526cb7093 100644 --- a/ivy/data_classes/array/experimental/elementwise.py +++ b/ivy/data_classes/array/experimental/elementwise.py @@ -16,10 +16,9 @@ def amax( keepdims: bool = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.amax. This method simply wraps the - function, and so the docstring for ivy.amax also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.amax. This method simply + wraps the function, and so the docstring for ivy.amax also applies to + this method with minimal changes. Parameters ---------- @@ -78,10 +77,9 @@ def amin( keepdims: bool = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.amin. This method simply wraps the - function, and so the docstring for ivy.amin also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.amin. This method simply + wraps the function, and so the docstring for ivy.amin also applies to + this method with minimal changes. Parameters ---------- @@ -133,10 +131,9 @@ def amin( return ivy.amin(self._data, axis=axis, keepdims=keepdims, out=out) def lgamma(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.lgamma. This method simply wraps the - function, and so the docstring for ivy.lgamma also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.lgamma. This method simply + wraps the function, and so the docstring for ivy.lgamma also applies to + this method with minimal changes. Parameters ---------- @@ -168,10 +165,9 @@ def lgamma(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: return ivy.lgamma(self._data, out=out) def sinc(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.sinc. This method simply wraps the - function, and so the docstring for ivy.sinc also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.sinc. This method simply + wraps the function, and so the docstring for ivy.sinc also applies to + this method with minimal changes. Parameters ---------- @@ -205,10 +201,9 @@ def fmod( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.fmod. This method simply wraps the - function, and so the docstring for ivy.fmod also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.fmod. This method simply + wraps the function, and so the docstring for ivy.fmod also applies to + this method with minimal changes. Parameters ---------- @@ -245,10 +240,9 @@ def fmax( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.fmax. This method simply wraps the - function, and so the docstring for ivy.fmax also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.fmax. This method simply + wraps the function, and so the docstring for ivy.fmax also applies to + this method with minimal changes. Parameters ---------- @@ -285,10 +279,9 @@ def float_power( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.float_power. This method simply wraps - the function, and so the docstring for ivy.float_power also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.float_power. This method + simply wraps the function, and so the docstring for ivy.float_power + also applies to this method with minimal changes. Parameters ---------- @@ -326,10 +319,9 @@ def copysign( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.copysign. This method simply wraps the - function, and so the docstring for ivy.copysign also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.copysign. This method + simply wraps the function, and so the docstring for ivy.copysign also + applies to this method with minimal changes. Parameters ---------- @@ -367,10 +359,9 @@ def count_nonzero( dtype: Optional[Union[ivy.Dtype, ivy.NativeDtype]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.count_nonzero. This method simply wraps - the function, and so the docstring for ivy.count_nonzero also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.count_nonzero. This method + simply wraps the function, and so the docstring for ivy.count_nonzero + also applies to this method with minimal changes. Parameters ---------- @@ -421,10 +412,9 @@ def nansum( keepdims: bool = False, out: Optional[ivy.Container] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.nansum. This method simply wraps the - function, and so the docstring for ivy.nansum also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.nansum. This method simply + wraps the function, and so the docstring for ivy.nansum also applies to + this method with minimal changes. Parameters ---------- @@ -473,10 +463,9 @@ def isclose( equal_nan: bool = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.isclose. This method simply wraps the - function, and so the docstring for ivy.isclose also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.isclose. This method simply + wraps the function, and so the docstring for ivy.isclose also applies + to this method with minimal changes. Parameters ---------- @@ -528,10 +517,9 @@ def signbit( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.signbit. This method simply wraps the - function, and so the docstring for ivy.signbit also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.signbit. This method simply + wraps the function, and so the docstring for ivy.signbit also applies + to this method with minimal changes. Parameters ---------- @@ -560,10 +548,9 @@ def hypot( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.hypot. This method simply wraps the - function, and so the docstring for ivy.hypot also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.hypot. This method simply + wraps the function, and so the docstring for ivy.hypot also applies to + this method with minimal changes. Parameters ---------- @@ -600,10 +587,9 @@ def allclose( equal_nan: bool = False, out: Optional[ivy.Container] = None, ) -> bool: - """ - ivy.Array instance method variant of ivy.allclose. This method simply wraps the - function, and so the docstring for ivy.allclose also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.allclose. This method + simply wraps the function, and so the docstring for ivy.allclose also + applies to this method with minimal changes. Parameters ---------- @@ -662,10 +648,9 @@ def diff( append: Optional[Union[ivy.Array, ivy.NativeArray, int, list, tuple]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.diff. This method simply wraps the - function, and so the docstring for ivy.diff also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.diff. This method simply + wraps the function, and so the docstring for ivy.diff also applies to + this method with minimal changes. Parameters ---------- @@ -705,10 +690,9 @@ def fix( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.fix. This method simply wraps the - function, and so the docstring for ivy.fix also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.fix. This method simply + wraps the function, and so the docstring for ivy.fix also applies to + this method with minimal changes. Parameters ---------- @@ -738,10 +722,9 @@ def nextafter( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.nextafter. This method simply wraps the - function, and so the docstring for ivy.nextafter also applies to this method - with minimal changes. + """ivy.Array instance method variant of ivy.nextafter. This method + simply wraps the function, and so the docstring for ivy.nextafter also + applies to this method with minimal changes. Parameters ---------- @@ -774,10 +757,9 @@ def zeta( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.zeta. This method simply wraps the - function, and so the docstring for ivy.zeta also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.zeta. This method simply + wraps the function, and so the docstring for ivy.zeta also applies to + this method with minimal changes. Parameters ---------- @@ -812,8 +794,7 @@ def gradient( edge_order: int = 1, axis: Optional[Union[int, list, tuple]] = None, ) -> Union[ivy.Array, List[ivy.Array]]: - """ - Calculate gradient of x with respect to (w.r.t.) spacing. + """Calculate gradient of x with respect to (w.r.t.) spacing. Parameters ---------- @@ -885,10 +866,9 @@ def xlogy( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.xlogy. This method simply wraps the - function, and so the docstring for ivy.xlogy also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.xlogy. This method simply + wraps the function, and so the docstring for ivy.xlogy also applies to + this method with minimal changes. Parameters ---------- @@ -922,9 +902,8 @@ def xlogy( def binarizer( self: ivy.Array, /, *, threshold: float = 0, out: Optional[ivy.Array] = None ) -> ivy.Array: - """ - Map the values of the input tensor to either 0 or 1, element-wise, based on the - outcome of a comparison against a threshold value. + """Map the values of the input tensor to either 0 or 1, element-wise, + based on the outcome of a comparison against a threshold value. Parameters ---------- @@ -945,10 +924,9 @@ def binarizer( return ivy.binarizer(self._data, threshold=threshold, out=out) def conj(self: ivy.Array, /, *, out: Optional[ivy.Array] = None) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.conj. This method simply wraps the - function, and so the docstring for ivy.conj also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.conj. This method simply + wraps the function, and so the docstring for ivy.conj also applies to + this method with minimal changes. Parameters ---------- @@ -980,10 +958,9 @@ def lerp( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.lerp. This method simply wraps the - function, and so the docstring for ivy.lerp also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.lerp. This method simply + wraps the function, and so the docstring for ivy.lerp also applies to + this method with minimal changes. Parameters ---------- @@ -1021,10 +998,9 @@ def ldexp( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.ldexp. This method simply wraps the - function, and so the docstring for ivy.ldexp also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.ldexp. This method simply + wraps the function, and so the docstring for ivy.ldexp also applies to + this method with minimal changes. Parameters ---------- @@ -1053,10 +1029,9 @@ def ldexp( def frexp( self: ivy.Array, /, *, out: Optional[Tuple[ivy.Array, ivy.Array]] = None ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.frexp. This method simply wraps the - function, and so the docstring for ivy.frexp also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.frexp. This method simply + wraps the function, and so the docstring for ivy.frexp also applies to + this method with minimal changes. Parameters ---------- @@ -1082,10 +1057,9 @@ def frexp( def modf( self: ivy.Array, /, *, out: Optional[Tuple[ivy.Array, ivy.Array]] = None ) -> Tuple[ivy.Array, ivy.Array]: - """ - ivy.Array instance method variant of ivy.modf. This method simply wraps the - function, and so the docstring for ivy.modf also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.modf. This method simply + wraps the function, and so the docstring for ivy.modf also applies to + this method with minimal changes. Parameters ---------- @@ -1114,10 +1088,9 @@ def digamma( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.digamma. This method simply wraps the - function, and so the docstring for ivy.digamma also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.digamma. This method simply + wraps the function, and so the docstring for ivy.digamma also applies + to this method with minimal changes. Note ---- @@ -1152,10 +1125,9 @@ def sparsify_tensor( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array class method variant of ivy.sparsify_tensor. This method simply wraps - the function, and so the docstring for ivy.sparsify_tensor also applies to this - method with minimal changes. + """ivy.Array class method variant of ivy.sparsify_tensor. This method + simply wraps the function, and so the docstring for ivy.sparsify_tensor + also applies to this method with minimal changes. Parameters ---------- @@ -1195,10 +1167,9 @@ def erfc( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.erfc. This method simply wraps the - function, and so the docstring for ivy.erfc also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.erfc. This method simply + wraps the function, and so the docstring for ivy.erfc also applies to + this method with minimal changes. Parameters ---------- @@ -1220,3 +1191,34 @@ def erfc( ivy.array([1.00000000e+00, 1.84270084e+00, 2.80259693e-45]) """ return ivy.erfc(self._data, out=out) + + def erfinv( + self: ivy.Array, + /, + *, + out: Optional[ivy.Array] = None, + ) -> ivy.Array: + """ivy.Array instance method variant of ivy.erfinv. This method simply + wraps the function, and so the docstring for ivy.erfinv also applies to + this method with minimal changes. + + Parameters + ---------- + self + Input array with real or complex valued argument. + out + Alternate output array in which to place the result. + The default is None. + + Returns + ------- + ret + Values of the inverse error function. + + Examples + -------- + >>> x = ivy.array([0, -1., 10.]) + >>> x.erfinv() + ivy.array([1.00000000e+00, 1.84270084e+00, 2.80259693e-45]) + """ + return ivy.erfinv(self._data, out=out) diff --git a/ivy/data_classes/array/experimental/general.py b/ivy/data_classes/array/experimental/general.py index d07f50f94981c..c51957e6b51bb 100644 --- a/ivy/data_classes/array/experimental/general.py +++ b/ivy/data_classes/array/experimental/general.py @@ -16,10 +16,9 @@ def reduce( axes: Union[int, Sequence[int]] = 0, keepdims: bool = False, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.reduce. This method simply wraps the - function, and so the docstring for ivy.reduce also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.reduce. This method simply + wraps the function, and so the docstring for ivy.reduce also applies to + this method with minimal changes. Parameters ---------- diff --git a/ivy/data_classes/array/experimental/layers.py b/ivy/data_classes/array/experimental/layers.py index eefb667184fb4..daee018c7e382 100644 --- a/ivy/data_classes/array/experimental/layers.py +++ b/ivy/data_classes/array/experimental/layers.py @@ -19,10 +19,9 @@ def max_pool1d( ceil_mode: bool = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of `ivy.max_pool1d`. This method simply wraps - the function, and so the docstring for `ivy.max_pool1d` also applies to this - method with minimal changes. + """ivy.Array instance method variant of `ivy.max_pool1d`. This method + simply wraps the function, and so the docstring for `ivy.max_pool1d` + also applies to this method with minimal changes. Parameters ---------- @@ -87,10 +86,9 @@ def max_pool2d( ceil_mode: bool = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of `ivy.max_pool2d`. This method simply wraps - the function, and so the docstring for `ivy.max_pool2d` also applies to this - method with minimal changes. + """ivy.Array instance method variant of `ivy.max_pool2d`. This method + simply wraps the function, and so the docstring for `ivy.max_pool2d` + also applies to this method with minimal changes. Parameters ---------- @@ -166,8 +164,7 @@ def max_pool3d( ceil_mode: bool = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute a 3-D max pool given 5-D input x. + """Compute a 3-D max pool given 5-D input x. Parameters ---------- @@ -231,10 +228,9 @@ def avg_pool1d( ceil_mode: bool = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of `ivy.avg_pool1d`. This method simply wraps - the function, and so the docstring for `ivy.avg_pool1d` also applies to this - method with minimal changes. + """ivy.Array instance method variant of `ivy.avg_pool1d`. This method + simply wraps the function, and so the docstring for `ivy.avg_pool1d` + also applies to this method with minimal changes. Parameters ---------- @@ -300,10 +296,9 @@ def avg_pool2d( divisor_override: Optional[int] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of `ivy.avg_pool2d`. This method simply wraps - the function, and so the docstring for `ivy.avg_pool2d` also applies to this - method with minimal changes. + """ivy.Array instance method variant of `ivy.avg_pool2d`. This method + simply wraps the function, and so the docstring for `ivy.avg_pool2d` + also applies to this method with minimal changes. Parameters ---------- @@ -377,8 +372,7 @@ def avg_pool3d( divisor_override: Optional[int] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute a 3-D max pool given 5-D input x. + """Compute a 3-D max pool given 5-D input x. Parameters ---------- @@ -443,10 +437,9 @@ def dct( norm: Optional[Literal["ortho"]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.dct. This method simply wraps the - function, and so the docstring for ivy.dct also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.dct. This method simply + wraps the function, and so the docstring for ivy.dct also applies to + this method with minimal changes. Parameters ---------- @@ -492,10 +485,9 @@ def idct( norm: Optional[Literal["ortho"]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.idct. This method simply wraps the - function, and so the docstring for ivy.idct also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.idct. This method simply + wraps the function, and so the docstring for ivy.idct also applies to + this method with minimal changes. Parameters ---------- @@ -541,10 +533,9 @@ def fft( n: Optional[Union[int, Tuple[int]]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.ifft. This method simply wraps the - function, and so the docstring for ivy.ifft also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.ifft. This method simply + wraps the function, and so the docstring for ivy.ifft also applies to + this method with minimal changes. Parameters ---------- @@ -597,10 +588,9 @@ def ifft( n: Optional[Union[int, Tuple[int]]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.ifft. This method simply wraps the - function, and so the docstring for ivy.ifft also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.ifft. This method simply + wraps the function, and so the docstring for ivy.ifft also applies to + this method with minimal changes. Parameters ---------- @@ -666,8 +656,7 @@ def dft( norm: str = "backward", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the discrete Fourier transform of input. + """Compute the discrete Fourier transform of input. Parameters ---------- @@ -751,8 +740,7 @@ def interpolate( antialias: bool = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Down/up samples the input to the given size. The algorithm used for + """Down/up samples the input to the given size. The algorithm used for interpolation is determined by mode. Parameters @@ -811,9 +799,8 @@ def adaptive_avg_pool1d( self: ivy.Array, output_size: int, ) -> ivy.Array: - """ - Apply a 1D adaptive average pooling over an input signal composed of several - input planes. + """Apply a 1D adaptive average pooling over an input signal composed of + several input planes. Parameters ---------- @@ -837,19 +824,21 @@ def adaptive_avg_pool1d( def adaptive_avg_pool2d( self: ivy.Array, output_size: Union[Sequence[int], int], + /, + *, + data_format: str = "NHWC", ) -> ivy.Array: - """ - Apply a 2D adaptive average pooling over an input signal composed of several - input planes. + """Apply a 2D adaptive average pooling over an input signal composed of + several input planes. Parameters ---------- self - Input array. Must have shape (N, C, H_in, W_in) or (C, H_in, W_in) where N - is the batch dimension, C is the feature dimension, and H_in and W_in are - the 2 spatial dimensions. + A 3D or 4D input array. Should have a floating-point data type. output_size Spatial output size. + data_format + "NHWC" or "NCHW". Defaults to "NHWC". Returns ------- @@ -859,15 +848,15 @@ def adaptive_avg_pool2d( return ivy.adaptive_avg_pool2d( self._data, output_size, + data_format=data_format, ) def adaptive_max_pool2d( self: ivy.Array, output_size: Union[Sequence[int], int], ) -> ivy.Array: - """ - Apply a 2D adaptive maximum pooling over an input signal composed of several - input planes. + """Apply a 2D adaptive maximum pooling over an input signal composed of + several input planes. Parameters ---------- @@ -888,6 +877,15 @@ def adaptive_max_pool2d( output_size, ) + def adaptive_max_pool3d( + self: ivy.Array, + output_size: Union[Sequence[int], int], + ) -> ivy.Array: + return ivy.adaptive_max_pool3d( + self._data, + output_size, + ) + def reduce_window( self: ivy.Array, init_value: Union[int, float], @@ -900,8 +898,8 @@ def reduce_window( base_dilation: Union[int, Sequence[int]] = 1, window_dilation: Union[int, Sequence[int]] = 1, ) -> ivy.Array: - """ - Apply a reduction function to all elements in each window of an array. + """Apply a reduction function to all elements in each window of an + array. Parameters ---------- @@ -952,13 +950,12 @@ def reduce_window( def fft2( self: ivy.Array, *, - s: Sequence[int] = None, + s: Optional[Sequence[int]] = None, dim: Sequence[int] = (-2, -1), norm: str = "backward", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the 2-dimensional discrete Fourier Transform. + """Compute the 2-dimensional discrete Fourier Transform. Parameters ---------- @@ -1022,8 +1019,7 @@ def ifftn( norm: str = "backward", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the N-dimensional inverse discrete Fourier Transform. + """Compute the N-dimensional inverse discrete Fourier Transform. Parameters ---------- @@ -1095,10 +1091,9 @@ def rfft( norm: Literal["backward", "ortho", "forward"] = "backward", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.rfft. This method simply wraps the - function, and so the docstring for ivy.rfft also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.rfft. This method simply + wraps the function, and so the docstring for ivy.rfft also applies to + this method with minimal changes. Parameters ---------- @@ -1144,14 +1139,13 @@ def rfft( def rfftn( self: ivy.Array, - s: Sequence[int] = None, - axes: Sequence[int] = None, + s: Optional[Sequence[int]] = None, + axes: Optional[Sequence[int]] = None, *, norm: str = "backward", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the n-dimensional discrete Fourier Transform. + """Compute the n-dimensional discrete Fourier Transform. Parameters ---------- @@ -1186,8 +1180,7 @@ def stft( name: Optional[str] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the Short-time Fourier Transform of signals. + """Compute the Short-time Fourier Transform of signals. Parameters ---------- @@ -1239,8 +1232,7 @@ def sliding_window( dilation: Union[int, Tuple[int, int]] = 1, padding: Union[str, int, Sequence[Tuple[int, int]]] = "VALID", ) -> ivy.Array: - """ - Slide a window of specified dimension over all elements of an array. + """Slide a window of specified dimension over all elements of an array. Parameters ---------- @@ -1291,12 +1283,12 @@ def max_unpool1d( kernel_size: Union[Tuple[int], int], /, *, - strides: Union[int, Tuple[int]] = None, + strides: Optional[Union[int, Tuple[int]]] = None, padding: Union[int, Tuple[int]] = 0, data_format: Optional[str] = "NCW", ) -> ivy.Array: - """ - Compute a 1-D max unpooling given the 1-D pooled input x and its indices. + """Compute a 1-D max unpooling given the 1-D pooled input x and its + indices. Parameters ---------- diff --git a/ivy/data_classes/array/experimental/linear_algebra.py b/ivy/data_classes/array/experimental/linear_algebra.py index 0fe58b0dc3513..865c4a1296942 100644 --- a/ivy/data_classes/array/experimental/linear_algebra.py +++ b/ivy/data_classes/array/experimental/linear_algebra.py @@ -19,10 +19,9 @@ def eigh_tridiagonal( ] = None, tol: Optional[float] = None, ) -> Union[ivy.Array, Tuple[ivy.Array, ivy.Array]]: - """ - ivy.Array instance method variant of ivy.eigh_tridiagonal. This method simply - wraps the function, and so the docstring for ivy.eigh_tridiagonal also applies - to this method with minimal changes. + """ivy.Array instance method variant of ivy.eigh_tridiagonal. This + method simply wraps the function, and so the docstring for + ivy.eigh_tridiagonal also applies to this method with minimal changes. Parameters ---------- @@ -89,10 +88,9 @@ def diagflat( num_cols: int = -1, out: Optional[Union[ivy.Array, ivy.NativeArray]] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.diagflat. This method simply wraps the - function, and so the docstring for ivy.diagflat also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.diagflat. This method + simply wraps the function, and so the docstring for ivy.diagflat also + applies to this method with minimal changes. Examples -------- @@ -119,10 +117,9 @@ def kron( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.kron. This method simply wraps the - function, and so the docstring for ivy.kron also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.kron. This method simply + wraps the function, and so the docstring for ivy.kron also applies to + this method with minimal changes. Examples -------- @@ -134,10 +131,9 @@ def kron( return ivy.kron(self._data, b, out=out) def matrix_exp(self: ivy.Array, /, *, out: Optional[ivy.Array] = None) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.kron. This method simply wraps the - function, and so the docstring for ivy.matrix_exp also applies to this method - with minimal changes. + """ivy.Array instance method variant of ivy.kron. This method simply + wraps the function, and so the docstring for ivy.matrix_exp also + applies to this method with minimal changes. Examples -------- @@ -157,10 +153,9 @@ def eig( self: ivy.Array, /, ) -> Tuple[ivy.Array, ...]: - """ - ivy.Array instance method variant of ivy.eig. This method simply wraps the - function, and so the docstring for ivy.eig also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.eig. This method simply + wraps the function, and so the docstring for ivy.eig also applies to + this method with minimal changes. Examples -------- @@ -178,10 +173,9 @@ def eigvals( self: ivy.Array, /, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.eigvals. This method simply wraps the - function, and so the docstring for ivy.eigvals also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.eigvals. This method simply + wraps the function, and so the docstring for ivy.eigvals also applies + to this method with minimal changes. Examples -------- @@ -197,10 +191,9 @@ def adjoint( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.adjoint. This method simply wraps the - function, and so the docstring for ivy.adjoint also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.adjoint. This method simply + wraps the function, and so the docstring for ivy.adjoint also applies + to this method with minimal changes. Examples -------- @@ -223,10 +216,9 @@ def multi_dot( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.multi_dot. This method simply wraps the - function, and so the docstring for ivy.multi_dot also applies to this method - with minimal changes. + """ivy.Array instance method variant of ivy.multi_dot. This method + simply wraps the function, and so the docstring for ivy.multi_dot also + applies to this method with minimal changes. Examples -------- @@ -242,10 +234,9 @@ def multi_dot( def cond( self: ivy.Array, /, *, p: Optional[Union[int, float, str]] = None ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.cond. This method simply wraps the - function, and so the docstring for ivy.cond also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.cond. This method simply + wraps the function, and so the docstring for ivy.cond also applies to + this method with minimal changes. Examples -------- @@ -268,10 +259,9 @@ def mode_dot( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.mode_dot. This method simply wraps the - function, and so the docstring for ivy.mode_dot also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.mode_dot. This method + simply wraps the function, and so the docstring for ivy.mode_dot also + applies to this method with minimal changes. Parameters ---------- @@ -310,10 +300,9 @@ def multi_mode_dot( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - r""" - ivy.Array instance method variant of ivy.multi_mode_dot. This method simply - wraps the function, and so the docstring for ivy.multi_mode_dot also applies to - this method with minimal changes. + r"""ivy.Array instance method variant of ivy.multi_mode_dot. This method + simply wraps the function, and so the docstring for ivy.multi_mode_dot + also applies to this method with minimal changes. Parameters ---------- @@ -334,8 +323,8 @@ def multi_mode_dot( If True, the matrices or vectors in in the list are transposed. For complex tensors, the conjugate transpose is used. out - optional output array, for writing the result to. It must have a shape that the - result can broadcast to. + optional output array, for writing the result to. + It must have a shape that the result can broadcast to. Returns ------- @@ -345,8 +334,8 @@ def multi_mode_dot( Notes ----- If no modes are specified, just assumes there is one matrix or vector per mode and returns: - :math:`\\text{x }\\times_0 \\text{ matrix or vec list[0] }\\times_1 \\cdots \\times_n \\text{ matrix or vec list[n] }` # noqa - """ + :math:`\\text{x }\\times_0 \\text{ matrix or vec list[0] }\\times_1 \\cdots \\times_n \\text{ matrix or vec list[n] }` + """ # noqa: E501 return ivy.multi_mode_dot( self._data, mat_or_vec_list, modes, skip, transpose, out=out ) @@ -357,10 +346,9 @@ def svd_flip( /, u_based_decision: Optional[bool] = True, ) -> Tuple[ivy.Array, ivy.Array]: - """ - ivy.Array instance method variant of ivy.svd_flip. This method simply wraps the - function, and so the docstring for ivy.svd_flip also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.svd_flip. This method + simply wraps the function, and so the docstring for ivy.svd_flip also + applies to this method with minimal changes. Parameters ---------- @@ -388,10 +376,10 @@ def make_svd_non_negative( *, nntype: Optional[Literal["nndsvd", "nndsvda"]] = "nndsvd", ) -> Tuple[ivy.Array, ivy.Array]: - """ - ivy.Array instance method variant of ivy.make_svd_non_negative. This method - simply wraps the function, and so the docstring for ivy.make_svd_non_negative - also applies to this method with minimal changes. + """ivy.Array instance method variant of ivy.make_svd_non_negative. This + method simply wraps the function, and so the docstring for + ivy.make_svd_non_negative also applies to this method with minimal + changes. Parameters ---------- @@ -418,10 +406,9 @@ def tensor_train( svd: Optional[Literal["truncated_svd"]] = "truncated_svd", verbose: Optional[bool] = False, ) -> ivy.TTTensor: - """ - ivy.Array instance method variant of ivy.tensor_train. This method simply wraps - the function, and so the docstring for ivy.tensor_train also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.tensor_train. This method + simply wraps the function, and so the docstring for ivy.tensor_train + also applies to this method with minimal changes. Parameters ---------- @@ -448,10 +435,10 @@ def truncated_svd( compute_uv: bool = True, n_eigenvecs: Optional[int] = None, ) -> Union[ivy.Array, Tuple[ivy.Array, ivy.Array, ivy.Array]]: - """ - ivy.Array instance method variant of ivy.make_svd_non_negative. This method - simply wraps the function, and so the docstring for ivy.make_svd_non_negative - also applies to this method with minimal changes. + """ivy.Array instance method variant of ivy.make_svd_non_negative. This + method simply wraps the function, and so the docstring for + ivy.make_svd_non_negative also applies to this method with minimal + changes. Parameters ---------- @@ -487,10 +474,9 @@ def initialize_tucker( mask: Optional[Union[ivy.Array, ivy.NativeArray]] = None, svd_mask_repeats: Optional[int] = 5, ) -> Tuple[ivy.Array, Sequence[ivy.Array]]: - """ - ivy.Array instance method variant of ivy.initialize_tucker. This method simply - wraps the function, and so the docstring for ivy.initialize_tucker also applies - to this method with minimal changes. + """ivy.Array instance method variant of ivy.initialize_tucker. This + method simply wraps the function, and so the docstring for + ivy.initialize_tucker also applies to this method with minimal changes. Parameters ---------- @@ -553,10 +539,9 @@ def partial_tucker( verbose: Optional[bool] = False, return_errors: Optional[bool] = False, ) -> Tuple[ivy.Array, Sequence[ivy.Array]]: - """ - ivy.Array instance method variant of ivy.partial_tucker. This method simply - wraps the function, and so the docstring for ivy.partial_tucker also applies to - this method with minimal changes. + """ivy.Array instance method variant of ivy.partial_tucker. This method + simply wraps the function, and so the docstring for ivy.partial_tucker + also applies to this method with minimal changes. Parameters ---------- @@ -635,10 +620,9 @@ def tucker( verbose: Optional[bool] = False, return_errors: Optional[bool] = False, ): - """ - ivy.Array instance method variant of ivy.tucker. This method simply wraps the - function, and so the docstring for ivy.tucker also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.tucker. This method simply + wraps the function, and so the docstring for ivy.tucker also applies to + this method with minimal changes. Parameters ---------- @@ -713,10 +697,10 @@ def tt_matrix_to_tensor( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Ivy.Array instance method variant of ivy.tt_matrix_to_tensor. This method simply - wraps the function, and so the docstring for ivy.tt_matrix_to_tensor also - applies to this method with minimal changes. + """Ivy.Array instance method variant of ivy.tt_matrix_to_tensor. This + method simply wraps the function, and so the docstring for + ivy.tt_matrix_to_tensor also applies to this method with minimal + changes. Parameters ---------- @@ -766,10 +750,9 @@ def dot( *, out: Optional[ivy.Array] = None, ): - """ - Compute the dot product between two arrays `a` and `b` using the current - backend's implementation. The dot product is defined as the sum of the element- - wise product of the input arrays. + """Compute the dot product between two arrays `a` and `b` using the + current backend's implementation. The dot product is defined as the sum + of the element- wise product of the input arrays. Parameters ---------- @@ -820,10 +803,10 @@ def general_inner_product( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.general_inner_product. This method - simply wraps the function, and so the docstring for ivy.general_inner_product - also applies to this method with minimal changes. + """ivy.Array instance method variant of ivy.general_inner_product. This + method simply wraps the function, and so the docstring for + ivy.general_inner_product also applies to this method with minimal + changes. Parameters ---------- @@ -849,7 +832,7 @@ def general_inner_product( >>> a = ivy.array([1, 2, 3]) >>> b = ivy.array([4, 5, 6]) - >>> result = a.general_inner_product(b, n_modes=1) + >>> result = a.general_inner_product(b, 1) >>> print(result) ivy.array(32) @@ -861,7 +844,7 @@ def general_inner_product( >>> a = ivy.array([[1, 1], [1, 1]]) >>> b = ivy.array([[1, 2, 3, 4],[1, 1, 1, 1]]) - >>> result = a.general_inner_product(b, n_modes=1) + >>> result = a.general_inner_product(b, 1) >>> print(result) ivy.array([[2, 3, 4, 5], [2, 3, 4, 5]]) @@ -875,10 +858,10 @@ def higher_order_moment( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.higher_order_moment. This method simply - wraps the function, and so the docstring for ivy.higher_order_moment also - applies to this method with minimal changes. + """ivy.Array instance method variant of ivy.higher_order_moment. This + method simply wraps the function, and so the docstring for + ivy.higher_order_moment also applies to this method with minimal + changes. Parameters ---------- @@ -916,10 +899,9 @@ def batched_outer( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Ivy Array instance method variant of ivy.batched_outer. This method simply wraps - the function, and so the docstring for ivy.batched_outer also applies to this - method with minimal changes. + """Ivy Array instance method variant of ivy.batched_outer. This method + simply wraps the function, and so the docstring for ivy.batched_outer + also applies to this method with minimal changes. Parameters ---------- diff --git a/ivy/data_classes/array/experimental/losses.py b/ivy/data_classes/array/experimental/losses.py index daedf43d09d7e..8912d815ff5a0 100644 --- a/ivy/data_classes/array/experimental/losses.py +++ b/ivy/data_classes/array/experimental/losses.py @@ -15,10 +15,9 @@ def l1_loss( reduction: Optional[str] = "mean", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.l1_loss. This method simply wraps the - function, and so the docstring for ivy.l1_loss also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.l1_loss. This method simply + wraps the function, and so the docstring for ivy.l1_loss also applies + to this method with minimal changes. Parameters ---------- @@ -59,10 +58,9 @@ def log_poisson_loss( reduction: str = "none", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.log_poisson_loss. This method simply - wraps the function, and so the docstring for ivy.l1_loss also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.log_poisson_loss. This + method simply wraps the function, and so the docstring for ivy.l1_loss + also applies to this method with minimal changes. Parameters ---------- @@ -100,7 +98,7 @@ def log_poisson_loss( ivy.array([1.28402555, 1.28402555, 1.03402555, 1.28402555]) >>> z = ivy.array([0.1, 0.1, 0.7, 0.1]) - >>> loss = x.x.log_poisson_loss(z, reduction='mean') + >>> loss = x.log_poisson_loss(z, reduction='mean') >>> print(loss) ivy.array(1.1573164) """ @@ -122,10 +120,9 @@ def huber_loss( delta: Optional[float] = 1.0, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of huber_loss. This method simply wraps the - function, and so the docstring for huber_loss also applies to this method with - minimal changes. + """ivy.Array instance method variant of huber_loss. This method simply + wraps the function, and so the docstring for huber_loss also applies to + this method with minimal changes. Parameters ---------- @@ -170,10 +167,9 @@ def smooth_l1_loss( reduction: Optional[str] = "mean", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy. smooth_l1_loss. This method simply - wraps the function, and so the docstring for ivy.smooth_l1_loss also applies to - this method with minimal changes. + """ivy.Array instance method variant of ivy. smooth_l1_loss. This + method simply wraps the function, and so the docstring for + ivy.smooth_l1_loss also applies to this method with minimal changes. Parameters ---------- @@ -218,10 +214,9 @@ def soft_margin_loss( reduction: Optional[str] = "mean", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.soft_margin_loss. This method simply - wraps the function, and so the docstring for ivy.soft_margin_loss also applies - to this method with minimal changes. + """ivy.Array instance method variant of ivy.soft_margin_loss. This + method simply wraps the function, and so the docstring for + ivy.soft_margin_loss also applies to this method with minimal changes. Parameters ---------- @@ -261,10 +256,9 @@ def kl_div( log_target=False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.kl_div. This method simply wraps the - function, and so the docstring for ivy.kl_div also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.kl_div. This method simply + wraps the function, and so the docstring for ivy.kl_div also applies to + this method with minimal changes. Parameters ---------- @@ -308,8 +302,7 @@ def poisson_nll_loss( eps: float = 1e-8, reduction: str = "mean", ) -> ivy.Array: - r""" - Compute the Poisson Negative Log Likelihood Loss. + r"""Compute the Poisson Negative Log Likelihood Loss. This function calculates the negative log likelihood loss between the `input` and `target`under the assumption that @@ -360,9 +353,9 @@ def poisson_nll_loss( -------- >>> input_tensor = ivy.array([1, 2, 3, 4], dtype=ivy.float64) >>> target_tensor = ivy.array([2, 2, 2, 2], dtype=ivy.float64) - >>> loss = poisson_nll_loss(input_tensor, target_tensor, log_input=True) + >>> loss = input_tensor.poisson_nll_loss(target_tensor, log_input=True) >>> print(loss) - ivy.array(16.1978) + ivy.array(16.1977562) """ return ivy.poisson_nll_loss( self._data, @@ -372,3 +365,84 @@ def poisson_nll_loss( eps=eps, reduction=reduction, ) + + def hinge_embedding_loss( + self: Union[ivy.Array, ivy.NativeArray], + target: Union[ivy.Array, ivy.NativeArray], + *, + margin: float = 1.0, + reduction: str = "mean", + ) -> ivy.Array: + r"""Measures loss from input `x` and label `y` with values 1 or -1. It + evaluates if two inputs are similar or not, often used for embedding or + semi-supervised learning. + + Loss for the `n`-th sample: + .. math:: + l_n = \begin{cases} + x_n, & \text{if}\; y_n = 1,\\ + \max \{0, margin - x_n\}, & \text{if}\; y_n = -1, + \end{cases} + + Total loss: + .. math:: + \ell(x, y) = \begin{cases} + \operatorname{mean}(L), & \text{if reduction} = \text{`mean';}\\ + \operatorname{sum}(L), & \text{if reduction} = \text{`sum'.} + \end{cases} + + where :math:`L = \{l_1,\dots,l_N\}^\top` + + Parameters + ---------- + input + Input tensor with dtype float. + The shape is [N, \*], where N is batch size and `\*` represents + any number of additional dimensions. + label + Label tensor containing 1 or -1 with dtype float32 or float64. + Its shape matches that of the input. + margin + Sets the hyperparameter margin. Determines the necessary input size + for hinge_embedding_loss calculations when label is -1. Inputs smaller + than the margin are minimized with hinge_embedding_loss. + Default is 1.0. + reduction + Specifies how to aggregate the loss across the batch. Options are: + - ``'none'``: Returns the unreduced loss. + - ``'mean'``: Returns the mean loss. + - ``'sum'``: Returns the summed loss. + Default is ``'mean'``. + + Shape + ----- + - Input: :math:`(*)` where :math:`*` means, any number of dimensions. \ + The sum operation operates over all the elements. + - Target: :math:`(*)`, same shape as the input + - Output: scalar. If :attr:`reduction` is ``'none'``, + then same shape as the input + + Returns + ------- + ret + Hinge embedding loss calculated from the input and label, + shaped based on the reduction method. + + Examples + -------- + >>> input_tensor = ivy.array([1, 2, 3, 4], dtype=ivy.float64) + >>> target_tensor = ivy.array([1, 1, 1, 1], dtype=ivy.float64) + >>> input_tensor.hinge_embedding_loss(target_tensor,reduction="sum") + ivy.array(10.) + + >>> input_tensor = ivy.array([1, 2, 3], dtype=ivy.float64) + >>> target_tensor = ivy.array([1, -1, -1], dtype=ivy.float64) + >>> input_tensor.hinge_embedding_loss(target_tensor, margin=2.0) + ivy.array(0.33333333) + """ + return ivy.hinge_embedding_loss( + self._data, + target, + margin=margin, + reduction=reduction, + ) diff --git a/ivy/data_classes/array/experimental/manipulation.py b/ivy/data_classes/array/experimental/manipulation.py index f63c94adc5c1c..af3292542a678 100644 --- a/ivy/data_classes/array/experimental/manipulation.py +++ b/ivy/data_classes/array/experimental/manipulation.py @@ -29,10 +29,9 @@ def moveaxis( copy: Optional[bool] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.moveaxis. This method simply wraps the - function, and so the docstring for ivy.unstack also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.moveaxis. This method + simply wraps the function, and so the docstring for ivy.unstack also + applies to this method with minimal changes. Parameters ---------- @@ -74,10 +73,9 @@ def heaviside( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.heaviside. This method simply wraps the - function, and so the docstring for ivy.heaviside also applies to this method - with minimal changes. + """ivy.Array instance method variant of ivy.heaviside. This method + simply wraps the function, and so the docstring for ivy.heaviside also + applies to this method with minimal changes. Parameters ---------- @@ -116,10 +114,9 @@ def flipud( copy: Optional[bool] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.flipud. This method simply wraps the - function, and so the docstring for ivy.flipud also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.flipud. This method simply + wraps the function, and so the docstring for ivy.flipud also applies to + this method with minimal changes. Parameters ---------- @@ -160,10 +157,9 @@ def vstack( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.vstack. This method simply wraps the - function, and so the docstring for ivy.vstack also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.vstack. This method simply + wraps the function, and so the docstring for ivy.vstack also applies to + this method with minimal changes. Examples -------- @@ -192,10 +188,9 @@ def hstack( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.hstack. This method simply wraps the - function, and so the docstring for ivy.hstack also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.hstack. This method simply + wraps the function, and so the docstring for ivy.hstack also applies to + this method with minimal changes. Examples -------- @@ -217,15 +212,14 @@ def rot90( self: ivy.Array, /, *, - copy: bool = None, + copy: Optional[bool] = None, k: int = 1, axes: Tuple[int, int] = (0, 1), out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.rot90. This method simply wraps the - function, and so the docstring for ivy.rot90 also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.rot90. This method simply + wraps the function, and so the docstring for ivy.rot90 also applies to + this method with minimal changes. Parameters ---------- @@ -284,10 +278,9 @@ def top_k( sorted: bool = True, out: Optional[tuple] = None, ) -> Tuple[ivy.Array, ivy.NativeArray]: - """ - ivy.Array instance method variant of ivy.top_k. This method simply wraps the - function, and so the docstring for ivy.top_k also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.top_k. This method simply + wraps the function, and so the docstring for ivy.top_k also applies to + this method with minimal changes. Parameters ---------- @@ -329,10 +322,9 @@ def fliplr( copy: Optional[bool] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.fliplr. This method simply wraps the - function, and so the docstring for ivy.fliplr also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.fliplr. This method simply + wraps the function, and so the docstring for ivy.fliplr also applies to + this method with minimal changes. Parameters ---------- @@ -369,10 +361,9 @@ def i0( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.i0. This method simply wraps the - function, and so the docstring for ivy.i0 also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.i0. This method simply + wraps the function, and so the docstring for ivy.i0 also applies to + this method with minimal changes. Parameters ---------- @@ -404,10 +395,9 @@ def flatten( order: str = "C", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.flatten. This method simply wraps the - function, and so the docstring for ivy.flatten also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.flatten. This method simply + wraps the function, and so the docstring for ivy.flatten also applies + to this method with minimal changes. Parameters ---------- @@ -540,8 +530,7 @@ def pad( out: Optional[ivy.Array] = None, **kwargs: Optional[Any], ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.pad. + """ivy.Array instance method variant of ivy.pad. This method simply wraps the function, and so the docstring for ivy.pad also applies to this method with minimal changes. @@ -566,10 +555,9 @@ def vsplit( *, copy: Optional[bool] = None, ) -> List[ivy.Array]: - """ - ivy.Array instance method variant of ivy.vsplit. This method simply wraps the - function, and so the docstring for ivy.vsplit also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.vsplit. This method simply + wraps the function, and so the docstring for ivy.vsplit also applies to + this method with minimal changes. Parameters ---------- @@ -613,10 +601,9 @@ def dsplit( *, copy: Optional[bool] = None, ) -> List[ivy.Array]: - """ - ivy.Array instance method variant of ivy.dsplit. This method simply wraps the - function, and so the docstring for ivy.dsplit also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.dsplit. This method simply + wraps the function, and so the docstring for ivy.dsplit also applies to + this method with minimal changes. Parameters ---------- @@ -659,10 +646,9 @@ def atleast_1d( *arys: Union[ivy.Array, bool, Number], copy: Optional[bool] = None, ) -> List[ivy.Array]: - """ - ivy.Array instance method variant of ivy.atleast_1d. This method simply wraps - the function, and so the docstring for ivy.atleast_1d also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.atleast_1d. This method + simply wraps the function, and so the docstring for ivy.atleast_1d also + applies to this method with minimal changes. Parameters ---------- @@ -702,10 +688,9 @@ def dstack( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.dstack. This method simply wraps the - function, and so the docstring for ivy.dstack also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.dstack. This method simply + wraps the function, and so the docstring for ivy.dstack also applies to + this method with minimal changes. Examples -------- @@ -730,10 +715,9 @@ def atleast_2d( *arys: ivy.Array, copy: Optional[bool] = None, ) -> List[ivy.Array]: - """ - ivy.Array instance method variant of ivy.atleast_2d. This method simply wraps - the function, and so the docstring for ivy.atleast_2d also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.atleast_2d. This method + simply wraps the function, and so the docstring for ivy.atleast_2d also + applies to this method with minimal changes. Parameters ---------- @@ -769,10 +753,9 @@ def atleast_3d( *arys: Union[ivy.Array, bool, Number], copy: Optional[bool] = None, ) -> List[ivy.Array]: - """ - ivy.Array instance method variant of ivy.atleast_3d. This method simply wraps - the function, and so the docstring for ivy.atleast_3d also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.atleast_3d. This method + simply wraps the function, and so the docstring for ivy.atleast_3d also + applies to this method with minimal changes. Parameters ---------- @@ -816,10 +799,9 @@ def take_along_axis( mode: str = "fill", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.take_along_axis. This method simply - wraps the function, and so the docstring for ivy.take_along_axis also applies to - this method with minimal changes. + """ivy.Array instance method variant of ivy.take_along_axis. This + method simply wraps the function, and so the docstring for + ivy.take_along_axis also applies to this method with minimal changes. Parameters ---------- @@ -858,10 +840,9 @@ def hsplit( *, copy: Optional[bool] = None, ) -> List[ivy.Array]: - """ - ivy.Array instance method variant of ivy.hsplit. This method simply wraps the - function, and so the docstring for ivy.hsplit also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.hsplit. This method simply + wraps the function, and so the docstring for ivy.hsplit also applies to + this method with minimal changes. Parameters ---------- @@ -913,8 +894,8 @@ def expand( copy: Optional[bool] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Broadcast the input Array following the given shape and the broadcast rule. + """Broadcast the input Array following the given shape and the + broadcast rule. Parameters ---------- @@ -945,8 +926,7 @@ def as_strided( strides: Sequence[int], /, ) -> ivy.Array: - """ - Create a copy of the input array with the given shape and strides. + """Create a copy of the input array with the given shape and strides. Parameters ---------- @@ -977,8 +957,7 @@ def concat_from_sequence( axis: int = 0, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Concatenate a sequence of arrays along a new or an existing axis. + """Concatenate a sequence of arrays along a new or an existing axis. Parameters ---------- @@ -1025,8 +1004,7 @@ def associative_scan( reverse: bool = False, axis: int = 0, ) -> ivy.Array: - """ - Perform an associative scan over the given array. + """Perform an associative scan over the given array. Parameters ---------- @@ -1052,8 +1030,7 @@ def unique_consecutive( *, axis: Optional[int] = None, ) -> Tuple[ivy.Array, ivy.Array, ivy.Array]: - """ - ivy.Array instance method variant of ivy.unique_consecutive. + """ivy.Array instance method variant of ivy.unique_consecutive. This method simply wraps the function, and so the docstring for ivy.unique_consecutive also applies to this method with minimal @@ -1068,8 +1045,7 @@ def fill_diagonal( *, wrap: bool = False, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.fill_diag. + """ivy.Array instance method variant of ivy.fill_diag. This method simply wraps the function, and so the docstring for ivy.fill_diag also applies to this method with minimal changes. @@ -1086,8 +1062,7 @@ def take( fill_value: Optional[Number] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.take. + """ivy.Array instance method variant of ivy.take. This method simply wraps the function, and so the docstring for ivy.take also applies to this method with minimal changes. @@ -1159,14 +1134,71 @@ def take( self, indices, axis=axis, mode=mode, fill_value=fill_value, out=out ) + def unflatten( + self: ivy.Array, + /, + shape: Union[Tuple[int], ivy.Array, ivy.NativeArray], + dim: Optional[int] = 0, + *, + out: Optional[ivy.Array] = None, + ) -> ivy.Array: + """ivy.Array instance method variant of ivy.unflatten. This method + simply wraps the function, and so the docstring for ivy.unflatten also + applies to this method with minimal changes. + + Parameters + ---------- + self + input array + shape + array indices. Must have an integer data type. + dim + axis over which to unflatten. If `axis` is negative, + the function must determine the axis along which to select values + by counting from the last dimension. + By default, the flattened input array is used. + out + optional output array, for writing the result to. It must + have a shape that the inputs broadcast to. + + Returns + ------- + ret + an array having the same data type as `x`. + The output array must have the same rank + (i.e., number of dimensions) as `x` and + must have the same shape as `x`, + except for the axis specified by `dim` + which is replaced with a tuple specified in `shape`. + + + Examples + -------- + With 'ivy.Array' input: + + >>> x = ivy.array([[1.2, 2.3, 3.4, 4.5], + ... [5.6, 6.7, 7.8, 8.9]]) + >>> dim = 1 + >>> shape = (2, 2) + >>> y = ivy.zeros([2, 2, 2]) + >>> x.unflatten(shape=shape, dim=dim, out=y) + >>> print(y) + ivy.array([[[1.2, 2.3], [3.4, 4.5]], [[5.6, 6.7], [7.8, 8.9]]]) + """ + return ivy.unflatten( + self._data, + shape=shape, + dim=dim, + out=out, + ) + def trim_zeros( self: ivy.Array, /, *, trim: Optional[str] = "fb", ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.trim_zeros. + """ivy.Array instance method variant of ivy.trim_zeros. This method simply wraps the function, and so the docstring for ivy.trim_zeros also applies to this method with minimal changes. @@ -1197,7 +1229,7 @@ def trim_zeros( >>> ivy.trim_zeros([0, 8, 3, 0, 0]) [8, 3] """ - return ivy.trim_zeros(self, trim) + return ivy.trim_zeros(self, trim=trim) def unfold( self: Union[ivy.Array, ivy.NativeArray], @@ -1206,10 +1238,9 @@ def unfold( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.unfold. This method simply wraps the - function, and so the docstring for ivy.unfold also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.unfold. This method simply + wraps the function, and so the docstring for ivy.unfold also applies to + this method with minimal changes. Parameters ---------- @@ -1235,10 +1266,9 @@ def fold( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.fold. This method simply wraps the - function, and so the docstring for ivy.fold also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.fold. This method simply + wraps the function, and so the docstring for ivy.fold also applies to + this method with minimal changes. Parameters ---------- @@ -1268,10 +1298,9 @@ def partial_unfold( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.partial_unfold. This method simply - wraps the function, and so the docstring for ivy.partial_unfold also applies to - this method with minimal changes. + """ivy.Array instance method variant of ivy.partial_unfold. This method + simply wraps the function, and so the docstring for ivy.partial_unfold + also applies to this method with minimal changes. Parameters ---------- @@ -1311,10 +1340,9 @@ def partial_fold( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.partial_fold. This method simply wraps - the function, and so the docstring for ivy.partial_fold also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.partial_fold. This method + simply wraps the function, and so the docstring for ivy.partial_fold + also applies to this method with minimal changes. Parameters ---------- @@ -1343,10 +1371,10 @@ def partial_tensor_to_vec( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.partial_tensor_to_vec. This method - simply wraps the function, and so the docstring for ivy.partial_tensor_to_vec - also applies to this method with minimal changes. + """ivy.Array instance method variant of ivy.partial_tensor_to_vec. This + method simply wraps the function, and so the docstring for + ivy.partial_tensor_to_vec also applies to this method with minimal + changes. Parameters ---------- @@ -1374,10 +1402,10 @@ def partial_vec_to_tensor( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.partial_vec_to_tensor. This method - simply wraps the function, and so the docstring for ivy.partial_vec_to_tensor - also applies to this method with minimal changes. + """ivy.Array instance method variant of ivy.partial_vec_to_tensor. This + method simply wraps the function, and so the docstring for + ivy.partial_vec_to_tensor also applies to this method with minimal + changes. Parameters ---------- @@ -1405,10 +1433,9 @@ def matricize( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.matricize. This method simply wraps the - function, and so the docstring for ivy.matricize also applies to this method - with minimal changes. + """ivy.Array instance method variant of ivy.matricize. This method + simply wraps the function, and so the docstring for ivy.matricize also + applies to this method with minimal changes. Parameters ---------- @@ -1435,10 +1462,9 @@ def soft_thresholding( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.soft_thresholding. This method simply - wraps the function, and so the docstring for ivy.soft_thresholding also applies - to this method with minimal changes. + """ivy.Array instance method variant of ivy.soft_thresholding. This + method simply wraps the function, and so the docstring for + ivy.soft_thresholding also applies to this method with minimal changes. Parameters ---------- @@ -1465,8 +1491,7 @@ def column_stack( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.column_stack. + """ivy.Array instance method variant of ivy.column_stack. This method simply wraps the function, and so the docstring for ivy.column_stack also applies to this method with minimal @@ -1504,8 +1529,7 @@ def put_along_axis( mode: Literal["sum", "min", "max", "mul", "mean", "replace"] = "replace", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.put_along_axis. + """ivy.Array instance method variant of ivy.put_along_axis. This method simply wraps the function, and so the docstring for ivy.put_along_axis also applies to this method with minimal diff --git a/ivy/data_classes/array/experimental/norms.py b/ivy/data_classes/array/experimental/norms.py index 916c63a32a521..6d8be11765f95 100644 --- a/ivy/data_classes/array/experimental/norms.py +++ b/ivy/data_classes/array/experimental/norms.py @@ -12,8 +12,7 @@ def l1_normalize( axis: Optional[Union[int, Tuple[int, ...]]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Normalize the array to have unit L1 norm. + """Normalize the array to have unit L1 norm. Parameters ---------- @@ -46,8 +45,7 @@ def l2_normalize( axis: Optional[int] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Normalize the array to have unit L2 norm. + """Normalize the array to have unit L2 norm. Parameters ---------- @@ -89,10 +87,9 @@ def batch_norm( data_format: str = "NSC", out: Optional[Tuple[ivy.Array, ivy.Array, ivy.Array]] = None, ) -> Tuple[ivy.Array, ivy.Array, ivy.Array]: - """ - ivy.Array instance method variant of ivy.batch_norm. This method simply wraps - the function, and so the docstring for ivy.batch_norm also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.batch_norm. This method + simply wraps the function, and so the docstring for ivy.batch_norm also + applies to this method with minimal changes. Parameters ---------- @@ -160,10 +157,9 @@ def instance_norm( data_format: str = "NSC", out: Optional[Tuple[ivy.Array, ivy.Array, ivy.Array]] = None, ) -> Tuple[ivy.Array, ivy.Array, ivy.Array]: - """ - ivy.Array instance method variant of ivy.instance_norm. This method simply wraps - the function, and so the docstring for ivy.instance_norm also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.instance_norm. This method + simply wraps the function, and so the docstring for ivy.instance_norm + also applies to this method with minimal changes. Parameters ---------- @@ -226,10 +222,9 @@ def group_norm( data_format: Optional[str] = "NSC", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.group_norm. This method simply wraps - the function, and so the docstring for ivy.group_norm also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.group_norm. This method + simply wraps the function, and so the docstring for ivy.group_norm also + applies to this method with minimal changes. Parameters ---------- @@ -277,8 +272,7 @@ def lp_normalize( axis: Optional[int] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Normalize the array to have Lp norm. + """Normalize the array to have Lp norm. Parameters ---------- diff --git a/ivy/data_classes/array/experimental/random.py b/ivy/data_classes/array/experimental/random.py index cd067cd304ba2..8c5f407e350e0 100644 --- a/ivy/data_classes/array/experimental/random.py +++ b/ivy/data_classes/array/experimental/random.py @@ -16,10 +16,9 @@ def dirichlet( seed: Optional[int] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.dirichlet. This method simply wraps the - function, and so the docstring for ivy.shuffle also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.dirichlet. This method + simply wraps the function, and so the docstring for ivy.shuffle also + applies to this method with minimal changes. Parameters ---------- @@ -71,10 +70,9 @@ def beta( seed: Optional[int] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.beta. This method simply wraps the - function, and so the docstring for ivy.beta also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.beta. This method simply + wraps the function, and so the docstring for ivy.beta also applies to + this method with minimal changes. Parameters ---------- @@ -122,10 +120,9 @@ def gamma( seed: Optional[int] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.gamma. This method simply wraps the - function, and so the docstring for ivy.gamma also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.gamma. This method simply + wraps the function, and so the docstring for ivy.gamma also applies to + this method with minimal changes. Parameters ---------- diff --git a/ivy/data_classes/array/experimental/searching.py b/ivy/data_classes/array/experimental/searching.py index 6dc82e7b1716a..99b5925179417 100644 --- a/ivy/data_classes/array/experimental/searching.py +++ b/ivy/data_classes/array/experimental/searching.py @@ -14,10 +14,9 @@ def unravel_index( *, out: Optional[ivy.Array] = None, ) -> Tuple[ivy.Array]: - """ - ivy.Array instance method variant of ivy.unravel_index. This method simply wraps - the function, and so the docstring for ivy.unravel_index also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.unravel_index. This method + simply wraps the function, and so the docstring for ivy.unravel_index + also applies to this method with minimal changes. Parameters ---------- diff --git a/ivy/data_classes/array/experimental/sorting.py b/ivy/data_classes/array/experimental/sorting.py index e3aa93f401e0b..a073f02fd812e 100644 --- a/ivy/data_classes/array/experimental/sorting.py +++ b/ivy/data_classes/array/experimental/sorting.py @@ -15,10 +15,9 @@ def lexsort( axis: int = -1, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.lexsort. This method simply wraps the - function, and so the docstring for ivy.lexsort also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.lexsort. This method simply + wraps the function, and so the docstring for ivy.lexsort also applies + to this method with minimal changes. Parameters ---------- diff --git a/ivy/data_classes/array/experimental/statistical.py b/ivy/data_classes/array/experimental/statistical.py index d206ff796fae0..8b8570f8d885d 100644 --- a/ivy/data_classes/array/experimental/statistical.py +++ b/ivy/data_classes/array/experimental/statistical.py @@ -21,10 +21,9 @@ def histogram( density: Optional[bool] = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.histogram. This method simply wraps the - function, and so the docstring for ivy.histogram also applies to this method - with minimal changes. + """ivy.Array instance method variant of ivy.histogram. This method + simply wraps the function, and so the docstring for ivy.histogram also + applies to this method with minimal changes. Parameters ---------- @@ -97,10 +96,9 @@ def median( keepdims: bool = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.median. This method simply wraps the - function, and so the docstring for ivy.median also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.median. This method simply + wraps the function, and so the docstring for ivy.median also applies to + this method with minimal changes. Parameters ---------- @@ -139,10 +137,9 @@ def nanmean( dtype: Optional[Union[ivy.Dtype, ivy.NativeDtype]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.nanmean. This method simply wraps the - function, and so the docstring for ivy.nanmean also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.nanmean. This method simply + wraps the function, and so the docstring for ivy.nanmean also applies + to this method with minimal changes. Parameters ---------- @@ -190,10 +187,9 @@ def nanmin( where: Optional[ivy.Array] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.nanmin. This method simply wraps the - function, and so the docstring for ivy.min also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.nanmin. This method simply + wraps the function, and so the docstring for ivy.min also applies to + this method with minimal changes. Parameters ---------- @@ -246,10 +242,9 @@ def nanprod( initial: Optional[Union[int, float, complex]] = None, where: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.nanprod. This method simply wraps the - function, and so the docstring for ivy.prod also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.nanprod. This method simply + wraps the function, and so the docstring for ivy.prod also applies to + this method with minimal changes. Parameters ---------- @@ -305,10 +300,9 @@ def quantile( interpolation: str = "linear", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.quantile. This method simply wraps the - function, and so the docstring for ivy.quantile also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.quantile. This method + simply wraps the function, and so the docstring for ivy.quantile also + applies to this method with minimal changes. Parameters ---------- @@ -389,10 +383,9 @@ def corrcoef( rowvar: bool = True, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.corrcoef. This method simply wraps the - function, and so the docstring for ivy.corrcoef also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.corrcoef. This method + simply wraps the function, and so the docstring for ivy.corrcoef also + applies to this method with minimal changes. Parameters ---------- @@ -433,10 +426,9 @@ def nanmedian( overwrite_input: bool = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.nanmedian. This method simply wraps the - function, and so the docstring for ivy.nanmedian also applies to this method - with minimal changes. + """ivy.Array instance method variant of ivy.nanmedian. This method + simply wraps the function, and so the docstring for ivy.nanmedian also + applies to this method with minimal changes. Parameters ---------- @@ -496,10 +488,9 @@ def bincount( minlength: int = 0, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.bincount. This method simply wraps the - function, and so the docstring for ivy.bincount also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.bincount. This method + simply wraps the function, and so the docstring for ivy.bincount also + applies to this method with minimal changes. Parameters ---------- @@ -542,10 +533,9 @@ def igamma( x: Union[ivy.Array, ivy.NativeArray], out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.igamma. This method simply wraps the - function, and so the docstring for ivy.igamma also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.igamma. This method simply + wraps the function, and so the docstring for ivy.igamma also applies to + this method with minimal changes. Parameters ---------- @@ -587,10 +577,9 @@ def cov( aweights: Optional[ivy.Array] = None, dtype: Optional[type] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.cov. This method simply wraps the - function, and so the docstring for ivy.cov also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.cov. This method simply + wraps the function, and so the docstring for ivy.cov also applies to + this method with minimal changes. Parameters ---------- @@ -672,10 +661,9 @@ def cummax( dtype: Optional[Union[ivy.Dtype, ivy.NativeDtype]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.cummax. This method simply wraps the - function, and so the docstring for ivy.cummax also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.cummax. This method simply + wraps the function, and so the docstring for ivy.cummax also applies to + this method with minimal changes. Parameters ---------- @@ -742,10 +730,9 @@ def cummin( dtype: Optional[Union[ivy.Dtype, ivy.NativeDtype]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.cummin. This method simply wraps the - function, and so the docstring for ivy.cummin also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.cummin. This method simply + wraps the function, and so the docstring for ivy.cummin also applies to + this method with minimal changes. Parameters ---------- diff --git a/ivy/data_classes/array/experimental/utility.py b/ivy/data_classes/array/experimental/utility.py index 46aaccd3510ad..d8f8c8e8554c1 100644 --- a/ivy/data_classes/array/experimental/utility.py +++ b/ivy/data_classes/array/experimental/utility.py @@ -13,11 +13,10 @@ def optional_get_element( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - If the input is a tensor or sequence type, it returns the input. If the input is - an optional type, it outputs the element in the input. It is an error if the - input is an empty optional-type (i.e. does not have an element) and the behavior - is undefined in this case. + """If the input is a tensor or sequence type, it returns the input. If + the input is an optional type, it outputs the element in the input. It + is an error if the input is an empty optional-type (i.e. does not have + an element) and the behavior is undefined in this case. Parameters ---------- diff --git a/ivy/data_classes/array/general.py b/ivy/data_classes/array/general.py index b17c29e0168d5..8aa3194c8caf2 100644 --- a/ivy/data_classes/array/general.py +++ b/ivy/data_classes/array/general.py @@ -17,10 +17,9 @@ def is_native_array( *, exclusive: bool = False, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.is_native_array. This method simply - wraps the function, and so the docstring for ivy.is_native_array also applies to - this method with minimal changes. + """ivy.Array instance method variant of ivy.is_native_array. This + method simply wraps the function, and so the docstring for + ivy.is_native_array also applies to this method with minimal changes. Parameters ---------- @@ -45,10 +44,9 @@ def is_native_array( return ivy.is_native_array(self, exclusive=exclusive) def is_ivy_array(self: ivy.Array, /, *, exclusive: bool = False) -> bool: - """ - ivy.Array instance method variant of ivy.is_ivy_array. This method simply wraps - the function, and so the docstring for ivy.is_ivy_array also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.is_ivy_array. This method + simply wraps the function, and so the docstring for ivy.is_ivy_array + also applies to this method with minimal changes. Parameters ---------- @@ -73,10 +71,9 @@ def is_ivy_array(self: ivy.Array, /, *, exclusive: bool = False) -> bool: return ivy.is_ivy_array(self, exclusive=exclusive) def is_array(self: ivy.Array, /, *, exclusive: bool = False) -> bool: - """ - ivy.Array instance method variant of ivy.is_array. This method simply wraps the - function, and so the docstring for ivy.is_array also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.is_array. This method + simply wraps the function, and so the docstring for ivy.is_array also + applies to this method with minimal changes. Parameters ---------- @@ -100,10 +97,9 @@ def is_array(self: ivy.Array, /, *, exclusive: bool = False) -> bool: return ivy.is_array(self, exclusive=exclusive) def is_ivy_container(self: ivy.Array) -> bool: - """ - ivy.Array instance method variant of ivy.is_ivy_container. This method simply - wraps the function, and so the docstring for ivy.is_ivy_container also applies - to this method with minimal changes. + """ivy.Array instance method variant of ivy.is_ivy_container. This + method simply wraps the function, and so the docstring for + ivy.is_ivy_container also applies to this method with minimal changes. Parameters ---------- @@ -126,10 +122,9 @@ def is_ivy_container(self: ivy.Array) -> bool: def all_equal( self: ivy.Array, *x2: Iterable[Any], equality_matrix: bool = False ) -> Union[bool, ivy.Array, ivy.NativeArray]: - """ - ivy.Array instance method variant of ivy.all_equal. This method simply wraps the - function, and so the docstring for ivy.all_equal also applies to this method - with minimal changes. + """ivy.Array instance method variant of ivy.all_equal. This method + simply wraps the function, and so the docstring for ivy.all_equal also + applies to this method with minimal changes. Parameters ---------- @@ -168,10 +163,9 @@ def all_equal( return ivy.all_equal(*arrays, equality_matrix=equality_matrix) def has_nans(self: ivy.Array, /, *, include_infs: bool = True): - """ - ivy.Array instance method variant of ivy.has_nans. This method simply wraps the - function, and so the docstring for ivy.has_nans also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.has_nans. This method + simply wraps the function, and so the docstring for ivy.has_nans also + applies to this method with minimal changes. Parameters ---------- @@ -204,10 +198,9 @@ def gather( batch_dims: int = 0, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.gather. This method simply wraps the - function, and so the docstring for ivy.gather also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.gather. This method simply + wraps the function, and so the docstring for ivy.gather also applies to + this method with minimal changes. Parameters ---------- @@ -219,9 +212,10 @@ def gather( axis The axis from which the indices will be gathered. Default is ``-1``. batch_dims - optional int, lets you gather different items from each element of a batch. + Optional int, lets you gather different items from each element of a batch. + Default is ``0``. out - optional array, for writing the result to. It must have a shape + Optional array, for writing the result to. It must have a shape that the inputs broadcast to. Returns @@ -237,6 +231,33 @@ def gather( >>> gather = x.gather(y) >>> print(gather) ivy.array([0., 1.]) + + >>> x = ivy.array([[0., 1., 2.],[3., 4., 5.]]) + >>> y = ivy.array([[0, 1],[1, 2]]) + >>> z = ivy.zeros((2, 2, 2)) + >>> gather = x.gather(y, out=z) + >>> print(z) + ivy.array([[[0., 1.],[1., 2.]],[[3., 4.],[4., 5.]]]) + + >>> x = ivy.array([[[0., 1.], [2., 3.]], + ... [[8., 9.], [10., 11.]]]) + >>> y = ivy.array([[0, 1]]) + >>> z = ivy.zeros((1, 2, 2, 2)) + >>> gather = x.gather(y, axis=0, out=z) + >>> print(z) + ivy.array( + [[[[ 0., 1.], + [ 2., 3.]], + [[ 8., 9.], + [10., 11.]]]]) + + >>> x = ivy.array([[0, 10, 20, 0, 0], + ... [0, 0, 0, 30, 40], + ... [0, 10, 0, 0, 40]]) + >>> y = ivy.array([[1, 2],[3, 4],[1, 4]]) + >>> gather = x.gather(y, batch_dims=1) + >>> print(gather) + ivy.array([[10, 20], [30, 40],[10, 40]]) """ return ivy.gather(self, indices, axis=axis, batch_dims=batch_dims, out=out) @@ -249,8 +270,7 @@ def scatter_nd( reduction: str = "sum", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Scatter updates into an array according to indices. + """Scatter updates into an array according to indices. Parameters ---------- @@ -303,10 +323,9 @@ def gather_nd( batch_dims: int = 0, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.gather_nd. This method simply wraps the - function, and so the docstring for ivy.gather_nd also applies to this method - with minimal changes. + """ivy.Array instance method variant of ivy.gather_nd. This method + simply wraps the function, and so the docstring for ivy.gather_nd also + applies to this method with minimal changes. Parameters ---------- @@ -343,10 +362,9 @@ def einops_rearrange( out: Optional[ivy.Array] = None, **axes_lengths: Dict[str, int], ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.einops_rearrange. This method simply - wraps the function, and so the docstring for ivy.einops_rearrange also applies - to this method with minimal changes. + """ivy.Array instance method variant of ivy.einops_rearrange. This + method simply wraps the function, and so the docstring for + ivy.einops_rearrange also applies to this method with minimal changes. Parameters ---------- @@ -405,10 +423,9 @@ def einops_reduce( out: Optional[ivy.Array] = None, **axes_lengths: Dict[str, int], ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.einops_reduce. This method simply wraps - the function, and so the docstring for ivy.einops_reduce also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.einops_reduce. This method + simply wraps the function, and so the docstring for ivy.einops_reduce + also applies to this method with minimal changes. Parameters ---------- @@ -467,10 +484,9 @@ def einops_repeat( out: Optional[ivy.Array] = None, **axes_lengths: Dict[str, int], ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.einops_repeat. This method simply wraps - the function, and so the docstring for ivy.einops_repeat also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.einops_repeat. This method + simply wraps the function, and so the docstring for ivy.einops_repeat + also applies to this method with minimal changes. Parameters ---------- @@ -512,10 +528,9 @@ def einops_repeat( return ivy.einops_repeat(self._data, pattern, out=out, **axes_lengths) def to_numpy(self: ivy.Array, /, *, copy: bool = True) -> np.ndarray: - """ - ivy.Array instance method variant of ivy.to_numpy. This method simply wraps the - function, and so the docstring for ivy.to_numpy also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.to_numpy. This method + simply wraps the function, and so the docstring for ivy.to_numpy also + applies to this method with minimal changes. Parameters ---------- @@ -548,10 +563,9 @@ def to_numpy(self: ivy.Array, /, *, copy: bool = True) -> np.ndarray: return ivy.to_numpy(self, copy=copy) def to_list(self: ivy.Array, /) -> List: - """ - ivy.Array instance method variant of ivy.to_list. This method simply wraps the - function, and so the docstring for ivy.to_list also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.to_list. This method simply + wraps the function, and so the docstring for ivy.to_list also applies + to this method with minimal changes. Parameters ---------- @@ -577,9 +591,8 @@ def to_list(self: ivy.Array, /) -> List: def to_file( self: ivy.Array, fid: Union[str, bytes, int], sep: str = "", format_: str = "%s" ) -> None: - """ - ivy.Array instance method variant of to_file. Write array to a file as text or - binary. The data is always written in 'C' order. + """ivy.Array instance method variant of to_file. Write array to a file + as text or binary. The data is always written in 'C' order. Parameters ---------- @@ -612,10 +625,10 @@ def to_file( return ivy.to_file(self, fid, sep, format_) def supports_inplace_updates(self: ivy.Array, /) -> bool: - """ - ivy.Array instance method variant of ivy.supports_inplace_updates. This method - simply wraps the function, and so the docstring for ivy.supports_inplace_updates - also applies to this method with minimal changes. + """ivy.Array instance method variant of ivy.supports_inplace_updates. + This method simply wraps the function, and so the docstring for + ivy.supports_inplace_updates also applies to this method with minimal + changes. Parameters ---------- @@ -649,10 +662,9 @@ def supports_inplace_updates(self: ivy.Array, /) -> bool: def inplace_decrement( self: Union[ivy.Array, ivy.NativeArray], val: Union[ivy.Array, ivy.NativeArray] ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.inplace_decrement. This method simply - wraps the function, and so the docstring for ivy.inplace_decrement also applies - to this method with minimal changes. + """ivy.Array instance method variant of ivy.inplace_decrement. This + method simply wraps the function, and so the docstring for + ivy.inplace_decrement also applies to this method with minimal changes. Parameters ---------- @@ -691,10 +703,9 @@ def stable_divide( Union[Number, ivy.Array, ivy.NativeArray, ivy.Container] ] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.stable_divide. This method simply wraps - the function, and so the docstring for ivy.stable_divide also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.stable_divide. This method + simply wraps the function, and so the docstring for ivy.stable_divide + also applies to this method with minimal changes. Parameters ---------- @@ -742,10 +753,9 @@ def clip_vector_norm( p: float = 2.0, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.clip_vector_norm. This method simply - wraps the function, and so the docstring for ivy.clip_vector_norm also applies - to this method with minimal changes. + """ivy.Array instance method variant of ivy.clip_vector_norm. This + method simply wraps the function, and so the docstring for + ivy.clip_vector_norm also applies to this method with minimal changes. Parameters ---------- @@ -777,10 +787,9 @@ def clip_vector_norm( return ivy.clip_vector_norm(self, max_norm, p=p, out=out) def array_equal(self: ivy.Array, x: Union[ivy.Array, ivy.NativeArray], /) -> bool: - """ - ivy.Array instance method variant of ivy.array_equal. This method simply wraps - the function, and so the docstring for ivy.array_equal also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.array_equal. This method + simply wraps the function, and so the docstring for ivy.array_equal + also applies to this method with minimal changes. Parameters ---------- @@ -817,10 +826,10 @@ def array_equal(self: ivy.Array, x: Union[ivy.Array, ivy.NativeArray], /) -> boo return ivy.array_equal(self, x) def assert_supports_inplace(self: ivy.Array, /) -> bool: - """ - ivy.Array instance method variant of ivy.assert_supports_inplace. This method - simply wraps the function, and so the docstring for ivy.assert_supports_inplace - also applies to this method with minimal changes. + """ivy.Array instance method variant of ivy.assert_supports_inplace. + This method simply wraps the function, and so the docstring for + ivy.assert_supports_inplace also applies to this method with minimal + changes. Parameters ---------- @@ -851,10 +860,9 @@ def assert_supports_inplace(self: ivy.Array, /) -> bool: return ivy.assert_supports_inplace(self) def to_scalar(self: ivy.Array) -> Number: - """ - ivy.Array instance method variant of ivy.to_scalar. This method simply wraps the - function, and so the docstring for ivy.to_scalar also applies to this method - with minimal changes. + """ivy.Array instance method variant of ivy.to_scalar. This method + simply wraps the function, and so the docstring for ivy.to_scalar also + applies to this method with minimal changes. Parameters ---------- @@ -887,10 +895,9 @@ def fourier_encode( concat: bool = True, flatten: bool = False, ) -> Union[ivy.Array, ivy.NativeArray, Tuple]: - """ - ivy.Array instance method variant of ivy.fourier_encode. This method simply - wraps the function, and so the docstring for ivy.fourier_encode also applies to - this method with minimal changes. + """ivy.Array instance method variant of ivy.fourier_encode. This method + simply wraps the function, and so the docstring for ivy.fourier_encode + also applies to this method with minimal changes. Parameters ---------- @@ -951,10 +958,9 @@ def fourier_encode( ) def value_is_nan(self: ivy.Array, /, *, include_infs: bool = True) -> bool: - """ - ivy.Array instance method variant of ivy.value_is_nan. This method simply wraps - the function, and so the docstring for ivy.value_is_nan also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.value_is_nan. This method + simply wraps the function, and so the docstring for ivy.value_is_nan + also applies to this method with minimal changes. Parameters ---------- @@ -995,10 +1001,9 @@ def value_is_nan(self: ivy.Array, /, *, include_infs: bool = True) -> bool: return ivy.value_is_nan(self, include_infs=include_infs) def exists(self: ivy.Array, /) -> bool: - """ - ivy.Array instance method variant of ivy.exists. This method simply wraps the - function, and so the docstring for ivy.exists also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.exists. This method simply + wraps the function, and so the docstring for ivy.exists also applies to + this method with minimal changes. Parameters ---------- @@ -1033,10 +1038,9 @@ def default( rev: bool = False, with_callable: bool = False, ) -> Any: - """ - ivy.Array instance method variant of ivy.default. This method simply wraps the - function, and so the docstring for ivy.default also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.default. This method simply + wraps the function, and so the docstring for ivy.default also applies + to this method with minimal changes. Parameters ---------- @@ -1079,10 +1083,9 @@ def stable_pow( *, min_base: Optional[float] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.stable_pow. This method simply wraps - the function, and so the docstring for ivy.stable_pow also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.stable_pow. This method + simply wraps the function, and so the docstring for ivy.stable_pow also + applies to this method with minimal changes. Parameters ---------- @@ -1124,10 +1127,9 @@ def inplace_update( ensure_in_backend: bool = False, keep_input_dtype: bool = False, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.inplace_update. This method simply - wraps the function, and so the docstring for ivy.inplace_update also applies to - this method with minimal changes. + """ivy.Array instance method variant of ivy.inplace_update. This method + simply wraps the function, and so the docstring for ivy.inplace_update + also applies to this method with minimal changes. Parameters ---------- @@ -1192,10 +1194,9 @@ def inplace_update( def inplace_increment( self: ivy.Array, val: Union[ivy.Array, ivy.NativeArray] ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.inplace_increment. This method wraps - the function, and so the docstring for ivy.inplace_increment also applies to - this method with minimal changes. + """ivy.Array instance method variant of ivy.inplace_increment. This + method wraps the function, and so the docstring for + ivy.inplace_increment also applies to this method with minimal changes. Parameters ---------- @@ -1233,10 +1234,9 @@ def clip_matrix_norm( p: float = 2.0, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.clip_matrix_norm. This method simply - wraps the function, and so the docstring for ivy.clip_matrix_norm also applies - to this method with minimal changes. + """ivy.Array instance method variant of ivy.clip_matrix_norm. This + method simply wraps the function, and so the docstring for + ivy.clip_matrix_norm also applies to this method with minimal changes. Parameters ---------- @@ -1275,10 +1275,9 @@ def scatter_flat( reduction: str = "sum", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.scatter_flat. This method simply wraps - the function, and so the docstring for ivy.scatter_flat also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.scatter_flat. This method + simply wraps the function, and so the docstring for ivy.scatter_flat + also applies to this method with minimal changes. Parameters ---------- @@ -1323,10 +1322,9 @@ def scatter_flat( return ivy.scatter_flat(self, updates, size=size, reduction=reduction, out=out) def get_num_dims(self: ivy.Array, /, *, as_array: bool = False) -> int: - """ - ivy.Array instance method variant of ivy.shape. This method simply wraps the - function, and so the docstring for ivy.shape also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.shape. This method simply + wraps the function, and so the docstring for ivy.shape also applies to + this method with minimal changes. Parameters ---------- @@ -1368,10 +1366,9 @@ def isin( assume_unique: bool = False, invert: bool = False, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.isin. This method simply wraps the - function, and so the docstring for ivy.isin also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.isin. This method simply + wraps the function, and so the docstring for ivy.isin also applies to + this method with minimal changes. Parameters ---------- diff --git a/ivy/data_classes/array/gradients.py b/ivy/data_classes/array/gradients.py index 3f0cb0fda507f..bb0b7164d95d4 100644 --- a/ivy/data_classes/array/gradients.py +++ b/ivy/data_classes/array/gradients.py @@ -16,10 +16,9 @@ def stop_gradient( preserve_type: bool = True, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.stop_gradient. This method simply wraps - the function, and so the docstring for ivy.stop_gradient also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.stop_gradient. This method + simply wraps the function, and so the docstring for ivy.stop_gradient + also applies to this method with minimal changes. Parameters ---------- @@ -58,10 +57,9 @@ def adam_step( epsilon: float = 1e-7, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.adam_step. This method simply wraps the - function, and so the docstring for ivy.adam_step also applies to this method - with minimal changes. + """ivy.Array instance method variant of ivy.adam_step. This method + simply wraps the function, and so the docstring for ivy.adam_step also + applies to this method with minimal changes. Parameters ---------- @@ -116,10 +114,9 @@ def optimizer_update( stop_gradients: bool = True, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.optimizer_update. This method simply - wraps the function, and so the docstring for ivy.optimizer_update also applies - to this method with minimal changes. + """ivy.Array instance method variant of ivy.optimizer_update. This + method simply wraps the function, and so the docstring for + ivy.optimizer_update also applies to this method with minimal changes. Parameters ---------- @@ -165,10 +162,10 @@ def gradient_descent_update( stop_gradients: bool = True, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.gradient_descent_update. This method - simply wraps the function, and so the docstring for ivy.gradient_descent_update - also applies to this method with minimal changes. + """ivy.Array instance method variant of ivy.gradient_descent_update. + This method simply wraps the function, and so the docstring for + ivy.gradient_descent_update also applies to this method with minimal + changes. Parameters ---------- @@ -222,10 +219,9 @@ def lars_update( stop_gradients: bool = True, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.lars_update. This method simply wraps - the function, and so the docstring for ivy.lars_update also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.lars_update. This method + simply wraps the function, and so the docstring for ivy.lars_update + also applies to this method with minimal changes. Parameters ---------- @@ -288,10 +284,9 @@ def adam_update( stop_gradients: bool = True, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.adam_update. This method simply wraps - the function, and so the docstring for ivy.adam_update also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.adam_update. This method + simply wraps the function, and so the docstring for ivy.adam_update + also applies to this method with minimal changes. Parameters ---------- @@ -376,10 +371,9 @@ def lamb_update( stop_gradients: bool = True, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.lamb_update. This method simply wraps - the function, and so the docstring for ivy.lamb_update also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.lamb_update. This method + simply wraps the function, and so the docstring for ivy.lamb_update + also applies to this method with minimal changes. Parameters ---------- diff --git a/ivy/data_classes/array/layers.py b/ivy/data_classes/array/layers.py index fd1a9a22dc968..3ecec50f7bc0e 100644 --- a/ivy/data_classes/array/layers.py +++ b/ivy/data_classes/array/layers.py @@ -20,10 +20,9 @@ def linear( bias: Optional[Union[ivy.Array, ivy.NativeArray]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.linear. This method simply wraps the - function, and so the docstring for ivy.linear also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.linear. This method simply + wraps the function, and so the docstring for ivy.linear also applies to + this method with minimal changes. Parameters ---------- @@ -78,10 +77,9 @@ def dropout( noise_shape: Optional[Sequence[int]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.dropout. This method simply wraps the - function, and so the docstring for ivy.dropout also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.dropout. This method simply + wraps the function, and so the docstring for ivy.dropout also applies + to this method with minimal changes. Parameters ---------- @@ -157,10 +155,9 @@ def dropout1d( data_format: str = "NWC", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.dropout1d. This method simply wraps the - function, and so the docstring for ivy.droput1d also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.dropout1d. This method + simply wraps the function, and so the docstring for ivy.droput1d also + applies to this method with minimal changes. Parameters ---------- @@ -205,10 +202,9 @@ def dropout2d( data_format: str = "NHWC", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.dropout2d. This method simply wraps the - function, and so the docstring for ivy.droput1d also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.dropout2d. This method + simply wraps the function, and so the docstring for ivy.droput1d also + applies to this method with minimal changes. Parameters ---------- @@ -254,10 +250,9 @@ def dropout3d( data_format: str = "NDHWC", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.dropout3d. This method simply wraps the - function, and so the docstring for ivy.droput3d also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.dropout3d. This method + simply wraps the function, and so the docstring for ivy.droput3d also + applies to this method with minimal changes. Parameters ---------- @@ -299,11 +294,10 @@ def scaled_dot_product_attention( training: Optional[bool] = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.scaled_dot_product_attention. This - method simply wraps the function, and so the docstring for - ivy.scaled_dot_product_attention also applies to this method with minimal - changes. + """ivy.Array instance method variant of + ivy.scaled_dot_product_attention. This method simply wraps the + function, and so the docstring for ivy.scaled_dot_product_attention + also applies to this method with minimal changes. Parameters ---------- @@ -463,10 +457,9 @@ def conv1d( bias: Optional[ivy.Array] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.conv1d. This method simply wraps the - function, and so the docstring for ivy.conv1d also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.conv1d. This method simply + wraps the function, and so the docstring for ivy.conv1d also applies to + this method with minimal changes. Parameters ---------- @@ -530,22 +523,22 @@ def conv1d_transpose( /, *, output_shape: Optional[Union[ivy.Shape, ivy.NativeShape]] = None, + filter_format: str = "channel_last", data_format: str = "NWC", dilations: Union[int, Tuple[int]] = 1, bias: Optional[ivy.Array] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.conv1d_transpose. This method simply - wraps the function, and so the docstring for ivy.conv1d_transpose also applies - to this method with minimal changes. + """ivy.Array instance method variant of ivy.conv1d_transpose. This + method simply wraps the function, and so the docstring for + ivy.conv1d_transpose also applies to this method with minimal changes. Parameters ---------- self Input image *[batch_size,w,d_in]* or *[batch_size,d_in,w]*. filters - Convolution filters *[fw,d_in,d_out]*. + Convolution filters *[fw,d_out,d_in]*. strides The stride of the sliding window for each dimension of input. padding @@ -554,6 +547,9 @@ def conv1d_transpose( to apply before and after each spatial dimension. output_shape Shape of the output (Default value = None) + filter_format + Either "channel_first" or "channel_last". "channel_first" corresponds + to "IOW",input data formats, while "channel_last" corresponds to "WOI". data_format The ordering of the dimensions in the input, one of "NWC" or "NCW". "NWC" corresponds to input with shape (batch_size, width, channels), while "NCW" @@ -588,6 +584,7 @@ def conv1d_transpose( strides, padding, output_shape=output_shape, + filter_format=filter_format, data_format=data_format, dilations=dilations, bias=bias, @@ -605,10 +602,9 @@ def depthwise_conv2d( dilations: Union[int, Tuple[int], Tuple[int, int]] = 1, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.depthwise_conv2d. This method simply - wraps the function, and so the docstring for ivy.depthwise_conv2d also applies - to this method with minimal changes. + """ivy.Array instance method variant of ivy.depthwise_conv2d. This + method simply wraps the function, and so the docstring for + ivy.depthwise_conv2d also applies to this method with minimal changes. Parameters ---------- @@ -666,10 +662,9 @@ def conv2d( bias: Optional[ivy.Container] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of `ivy.conv2d`. This method simply wraps the - function, and so the docstring for `ivy.conv2d` also applies to this method with - minimal changes. + """ivy.Array instance method variant of `ivy.conv2d`. This method + simply wraps the function, and so the docstring for `ivy.conv2d` also + applies to this method with minimal changes. Parameters ---------- @@ -739,22 +734,23 @@ def conv2d_transpose( /, *, output_shape: Optional[Union[ivy.Shape, ivy.NativeShape]] = None, + filter_format: str = "channel_last", data_format: str = "NHWC", dilations: Union[int, Tuple[int, int]] = 1, out: Optional[ivy.Array] = None, bias: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of `ivy.conv2d_transpose`. This method simply - wraps the function, and so the docstring for `ivy.conv2d_transpose` also applies - to this method with minimal changes. + """ivy.Array instance method variant of `ivy.conv2d_transpose`. This + method simply wraps the function, and so the docstring for + `ivy.conv2d_transpose` also applies to this method with minimal + changes. Parameters ---------- self Input image *[batch_size,h,w,d_in]* or *[batch_size,d_in,h,w]*. filters - Convolution filters *[fh,fw,d_in,d_out]*. + Convolution filters *[fh,fw,d_out,d_in]*. strides The stride of the sliding window for each dimension of input. padding @@ -762,6 +758,9 @@ def conv2d_transpose( per-dimension paddings. output_shape Shape of the output (Default value = None) + filter_format + Either "channel_first" or "channel_last". "channel_first" corresponds + to "IOHW",input data formats, while "channel_last" corresponds to "HWOI". data_format The ordering of the dimensions in the input, one of "NHWC" or "NCHW". "NHWC" corresponds to inputs with shape (batch_size, height, width, channels), @@ -783,7 +782,7 @@ def conv2d_transpose( Examples -------- >>> x = ivy.random_normal(mean=0, std=1, shape=[1, 28, 28, 3]) - >>> filters = ivy.random_normal(mean=0, std=1, shape=[3, 3, 3, 6]) + >>> filters = ivy.random_normal(mean=0, std=1, shape=[3, 3, 6, 3]) >>> y = x.conv2d_transpose(filters,2,'SAME',) >>> print(y.shape) (1, 56, 56, 6) @@ -794,6 +793,7 @@ def conv2d_transpose( strides, padding, output_shape=output_shape, + filter_format=filter_format, data_format=data_format, dilations=dilations, out=out, @@ -814,10 +814,9 @@ def conv3d( bias: Optional[ivy.Array] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of `ivy.conv3d`. This method simply wraps the - function, and so the docstring for `ivy.conv3d` also applies to this method with - minimal changes. + """ivy.Array instance method variant of `ivy.conv3d`. This method + simply wraps the function, and so the docstring for `ivy.conv3d` also + applies to this method with minimal changes. Parameters ---------- @@ -880,22 +879,23 @@ def conv3d_transpose( /, *, output_shape: Optional[Union[ivy.Shape, ivy.NativeShape]] = None, + filter_format: str = "channel_last", data_format: str = "NDHWC", dilations: Union[int, Tuple[int], Tuple[int, int], Tuple[int, int, int]] = 1, bias: Optional[ivy.Array] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of `ivy.conv3d_transpose`. This method simply - wraps the function, and so the docstring for `ivy.conv3d_transpose` also applies - to this method with minimal changes. + """ivy.Array instance method variant of `ivy.conv3d_transpose`. This + method simply wraps the function, and so the docstring for + `ivy.conv3d_transpose` also applies to this method with minimal + changes. Parameters ---------- self Input volume *[batch_size,d,h,w,d_in]* or *[batch_size,d_in,d,h,w]*. filters - Convolution filters *[fd,fh,fw,d_in,d_out]*. + Convolution filters *[fd,fh,fw,d_out,d_in]*. strides The stride of the sliding window for each dimension of input. padding @@ -903,6 +903,9 @@ def conv3d_transpose( the per-dimension paddings. output_shape Shape of the output (Default value = None) + filter_format + Either "channel_first" or "channel_last". "channel_first" corresponds + to "IODHW",input data formats, while "channel_last" corresponds to "DHWOI". data_format The ordering of the dimensions in the input, one of "NDHWC" or "NCDHW". "NDHWC" corresponds to inputs with shape (batch_size, @@ -925,7 +928,7 @@ def conv3d_transpose( Examples -------- >>> x = ivy.random_normal(mean=0, std=1, shape=[1, 3, 28, 28, 3]) - >>> filters = ivy.random_normal(mean=0, std=1, shape=[3, 3, 3, 3, 6]) + >>> filters = ivy.random_normal(mean=0, std=1, shape=[3, 3, 3, 6, 3]) >>> y = x.conv3d_transpose(filters, 2, 'SAME') >>> print(y.shape) (1, 6, 56, 56, 6) @@ -936,6 +939,7 @@ def conv3d_transpose( strides, padding, output_shape=output_shape, + filter_format=filter_format, data_format=data_format, dilations=dilations, bias=bias, @@ -953,10 +957,9 @@ def lstm_update( bias: Optional[Union[ivy.Array, ivy.NativeArray]] = None, recurrent_bias: Optional[Union[ivy.Array, ivy.NativeArray]] = None, ) -> Tuple[ivy.Array, ivy.Array]: - """ - ivy.Array instance method variant of ivy.lstm_update. This method simply wraps - the function, and so the docstring for ivy.lstm_update also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.lstm_update. This method + simply wraps the function, and so the docstring for ivy.lstm_update + also applies to this method with minimal changes. Parameters ---------- diff --git a/ivy/data_classes/array/linear_algebra.py b/ivy/data_classes/array/linear_algebra.py index a25df9d4cabb7..025932fa11f0c 100644 --- a/ivy/data_classes/array/linear_algebra.py +++ b/ivy/data_classes/array/linear_algebra.py @@ -21,10 +21,9 @@ def matmul( adjoint_b: bool = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.matmul. This method simply wraps the - function, and so the docstring for ivy.matmul also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.matmul. This method simply + wraps the function, and so the docstring for ivy.matmul also applies to + this method with minimal changes. Parameters ---------- @@ -82,10 +81,9 @@ def cholesky( upper: bool = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.cholesky. This method simply wraps the - function, and so the docstring for ivy.cholesky also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.cholesky. This method + simply wraps the function, and so the docstring for ivy.cholesky also + applies to this method with minimal changes. Parameters ---------- @@ -135,10 +133,9 @@ def cross( axis: int = -1, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.cross. This method simply wraps the - function, and so the docstring for ivy.cross also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.cross. This method simply + wraps the function, and so the docstring for ivy.cross also applies to + this method with minimal changes. Parameters ---------- @@ -194,10 +191,9 @@ def diagonal( axis2: int = -1, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.diagonal. This method simply wraps the - function, and so the docstring for ivy.diagonal also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.diagonal. This method + simply wraps the function, and so the docstring for ivy.diagonal also + applies to this method with minimal changes. Parameters ---------- @@ -274,10 +270,9 @@ def diag( k: int = 0, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.diag. This method simply wraps the - function, and so the docstring for ivy.diag also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.diag. This method simply + wraps the function, and so the docstring for ivy.diag also applies to + this method with minimal changes. Examples -------- @@ -313,10 +308,9 @@ def eigvalsh( UPLO: str = "L", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.eigvalsh. This method simply wraps the - function, and so the docstring for ivy.eigvalsh also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.eigvalsh. This method + simply wraps the function, and so the docstring for ivy.eigvalsh also + applies to this method with minimal changes. Parameters ---------- @@ -362,8 +356,7 @@ def inner( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return the inner product of two vectors ``self`` and ``x2``. + """Return the inner product of two vectors ``self`` and ``x2``. Parameters ---------- @@ -421,10 +414,9 @@ def inner( def inv( self: ivy.Array, /, *, adjoint: bool = False, out: Optional[ivy.Array] = None ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.inv. This method simply wraps the - function, and so the docstring for ivy.inv also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.inv. This method simply + wraps the function, and so the docstring for ivy.inv also applies to + this method with minimal changes. Parameters ---------- @@ -463,10 +455,9 @@ def matrix_norm( keepdims: bool = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.matrix_norm. This method simply wraps - the function, and so the docstring for ivy.matrix_norm also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.matrix_norm. This method + simply wraps the function, and so the docstring for ivy.matrix_norm + also applies to this method with minimal changes. Parameters ---------- @@ -525,10 +516,9 @@ def matrix_rank( hermitian: Optional[bool] = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.matrix_rank. This method returns the - rank (i.e., number of non-zero singular values) of a matrix (or a stack of - matrices). + """ivy.Array instance method variant of ivy.matrix_rank. This method + returns the rank (i.e., number of non-zero singular values) of a matrix + (or a stack of matrices). Parameters ---------- @@ -599,8 +589,7 @@ def matrix_rank( def matrix_transpose( self: ivy.Array, /, *, conjugate: bool = False, out: Optional[ivy.Array] = None ) -> ivy.Array: - """ - Transpose a matrix (or a stack of matrices) ``x``. + """Transpose a matrix (or a stack of matrices) ``x``. Parameters ---------- @@ -637,8 +626,7 @@ def outer( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the outer product between two arrays. + """Compute the outer product between two arrays. Parameters ---------- @@ -674,10 +662,9 @@ def pinv( rtol: Optional[Union[float, Tuple[float]]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.pinv. This method simply wraps the - function, and so the docstring for ivy.pinv also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.pinv. This method simply + wraps the function, and so the docstring for ivy.pinv also applies to + this method with minimal changes. Parameters ---------- @@ -719,10 +706,9 @@ def qr( mode: str = "reduced", out: Optional[Tuple[ivy.Array, ivy.Array]] = None, ) -> Tuple[ivy.Array, ivy.Array]: - """ - ivy.Array instance method variant of ivy.qr. This method simply wraps the - function, and so the docstring for ivy.qr also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.qr. This method simply + wraps the function, and so the docstring for ivy.qr also applies to + this method with minimal changes. Returns the qr decomposition x = QR of a full column rank matrix (or a stack of matrices), where Q is an orthonormal matrix (or a stack of matrices) and R is an @@ -779,10 +765,9 @@ def qr( def slogdet( self: ivy.Array, ) -> Tuple[ivy.Array, ivy.Array]: - """ - ivy.Array instance method variant of ivy.slogdet. This method simply wraps the - function, and so the docstring for ivy.slogdet also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.slogdet. This method simply + wraps the function, and so the docstring for ivy.slogdet also applies + to this method with minimal changes. Parameters ---------- @@ -836,10 +821,9 @@ def svd( compute_uv: bool = True, full_matrices: bool = True, ) -> Union[ivy.Array, Tuple[ivy.Array, ...]]: - """ - ivy.Array instance method variant of ivy.svf. This method simply wraps the - function, and so the docstring for ivy.svd also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.svf. This method simply + wraps the function, and so the docstring for ivy.svd also applies to + this method with minimal changes. Parameters ---------- @@ -924,9 +908,9 @@ def trace( axis2: int = 1, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.trace. This method Returns the sum - along the specified diagonals of a matrix (or a stack of matrices). + """ivy.Array instance method variant of ivy.trace. This method Returns + the sum along the specified diagonals of a matrix (or a stack of + matrices). Parameters ---------- @@ -996,9 +980,8 @@ def vector_norm( dtype: Optional[Union[ivy.Dtype, ivy.NativeDtype]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.vector_norm. This method computes the - vector norm of a vector (or batch of vectors). + """ivy.Array instance method variant of ivy.vector_norm. This method + computes the vector norm of a vector (or batch of vectors). Parameters ---------- @@ -1089,9 +1072,8 @@ def vander( increasing: bool = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.vander. This method Returns the - Vandermonde matrix of the input array. + """ivy.Array instance method variant of ivy.vander. This method Returns + the Vandermonde matrix of the input array. Parameters ---------- diff --git a/ivy/data_classes/array/losses.py b/ivy/data_classes/array/losses.py index 214c05ac5a189..216ef9e4e2322 100644 --- a/ivy/data_classes/array/losses.py +++ b/ivy/data_classes/array/losses.py @@ -17,10 +17,9 @@ def cross_entropy( reduction: str = "mean", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.cross_entropy. This method simply wraps - the function, and so the docstring for ivy.cross_entropy also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.cross_entropy. This method + simply wraps the function, and so the docstring for ivy.cross_entropy + also applies to this method with minimal changes. Parameters ---------- @@ -51,7 +50,7 @@ def cross_entropy( >>> y = ivy.array([0.25, 0.25, 0.25, 0.25]) >>> z = x.cross_entropy(y) >>> print(z) - ivy.array(1.3862944) + ivy.array(0.34657359) """ return ivy.cross_entropy( self._data, pred, axis=axis, epsilon=epsilon, reduction=reduction, out=out @@ -69,10 +68,10 @@ def binary_cross_entropy( axis: Optional[int] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.binary_cross_entropy. This method - simply wraps the function, and so the docstring for ivy.binary_cross_entropy - also applies to this method with minimal changes. + """ivy.Array instance method variant of ivy.binary_cross_entropy. This + method simply wraps the function, and so the docstring for + ivy.binary_cross_entropy also applies to this method with minimal + changes. Parameters ---------- @@ -111,7 +110,7 @@ def binary_cross_entropy( >>> y = ivy.array([0.7, 0.8, 0.2]) >>> z = x.binary_cross_entropy(y) >>> print(z) - ivy.array([0.357, 0.223, 0.223]) + ivy.array(0.26765382) """ return ivy.binary_cross_entropy( self._data, @@ -134,10 +133,10 @@ def sparse_cross_entropy( reduction: str = "mean", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.sparse_cross_entropy. This method - simply wraps the function, and so the docstring for ivy.sparse_cross_entropy - also applies to this method with minimal changes. + """ivy.Array instance method variant of ivy.sparse_cross_entropy. This + method simply wraps the function, and so the docstring for + ivy.sparse_cross_entropy also applies to this method with minimal + changes. Parameters ---------- @@ -171,7 +170,7 @@ def sparse_cross_entropy( >>> y = ivy.array([0.7, 0.8, 0.2]) >>> z = x.sparse_cross_entropy(y) >>> print(z) - ivy.array([0.223, 0.223, 0.357]) + ivy.array([0.07438118, 0.07438118, 0.11889165]) """ return ivy.sparse_cross_entropy( self._data, pred, axis=axis, epsilon=epsilon, reduction=reduction, out=out diff --git a/ivy/data_classes/array/manipulation.py b/ivy/data_classes/array/manipulation.py index f9055f928ff2f..231a356ca6be4 100644 --- a/ivy/data_classes/array/manipulation.py +++ b/ivy/data_classes/array/manipulation.py @@ -32,10 +32,9 @@ def concat( axis: int = 0, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.concat. This method simply wraps the - function, and so the docstring for ivy.concat also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.concat. This method simply + wraps the function, and so the docstring for ivy.concat also applies to + this method with minimal changes. Parameters ---------- @@ -69,10 +68,9 @@ def expand_dims( axis: Union[int, Sequence[int]] = 0, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.expand_dims. This method simply wraps - the function, and so the docstring for ivy.expand_dims also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.expand_dims. This method + simply wraps the function, and so the docstring for ivy.expand_dims + also applies to this method with minimal changes. Parameters ---------- @@ -116,10 +114,9 @@ def flip( axis: Optional[Union[int, Sequence[int]]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.flip. This method simply wraps the - function, and so the docstring for ivy.flip also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.flip. This method simply + wraps the function, and so the docstring for ivy.flip also applies to + this method with minimal changes. Parameters ---------- @@ -170,10 +167,9 @@ def permute_dims( copy: Optional[bool] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.permute_dims. This method simply wraps - the function, and so the docstring for ivy.permute_dims also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.permute_dims. This method + simply wraps the function, and so the docstring for ivy.permute_dims + also applies to this method with minimal changes. Parameters ---------- @@ -229,10 +225,9 @@ def reshape( allowzero: bool = True, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.reshape. This method simply wraps the - function, and so the docstring for ivy.reshape also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.reshape. This method simply + wraps the function, and so the docstring for ivy.reshape also applies + to this method with minimal changes. Parameters ---------- @@ -297,10 +292,9 @@ def roll( axis: Optional[Union[int, Sequence[int]]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.roll. This method simply wraps the - function, and so the docstring for ivy.roll also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.roll. This method simply + wraps the function, and so the docstring for ivy.roll also applies to + this method with minimal changes. Parameters ---------- @@ -354,10 +348,9 @@ def squeeze( copy: Optional[bool] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.squeeze. This method simply wraps the - function, and so the docstring for ivy.squeeze also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.squeeze. This method simply + wraps the function, and so the docstring for ivy.squeeze also applies + to this method with minimal changes. Parameters ---------- @@ -403,10 +396,9 @@ def stack( axis: int = 0, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.stack. This method simply wraps the - function, and so the docstring for ivy.stack also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.stack. This method simply + wraps the function, and so the docstring for ivy.stack also applies to + this method with minimal changes. Parameters ---------- @@ -448,16 +440,15 @@ def stack( def clip( self: ivy.Array, + /, x_min: Optional[Union[Number, ivy.Array, ivy.NativeArray]] = None, x_max: Optional[Union[Number, ivy.Array, ivy.NativeArray]] = None, - /, *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.clip. This method simply wraps the - function, and so the docstring for ivy.clip also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.clip. This method simply + wraps the function, and so the docstring for ivy.clip also applies to + this method with minimal changes. Parameters ---------- @@ -494,10 +485,9 @@ def constant_pad( value: Number = 0, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.constant_pad. This method simply wraps - the function, and so the docstring for ivy.constant_pad also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.constant_pad. This method + simply wraps the function, and so the docstring for ivy.constant_pad + also applies to this method with minimal changes. Parameters ---------- @@ -536,10 +526,9 @@ def repeat( axis: Optional[Union[int, Sequence[int]]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.repeat. This method simply wraps the - function, and so the docstring for ivy.repeat also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.repeat. This method simply + wraps the function, and so the docstring for ivy.repeat also applies to + this method with minimal changes. Parameters ---------- @@ -581,10 +570,9 @@ def split( axis: int = 0, with_remainder: bool = False, ) -> List[ivy.Array]: - """ - ivy.Array instance method variant of ivy.split. This method simply wraps the - function, and so the docstring for ivy.split also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.split. This method simply + wraps the function, and so the docstring for ivy.split also applies to + this method with minimal changes. Parameters ---------- @@ -636,10 +624,9 @@ def swapaxes( copy: Optional[bool] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.swap_axes. This method simply wraps the - function, and so the docstring for ivy.split also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.swap_axes. This method + simply wraps the function, and so the docstring for ivy.split also + applies to this method with minimal changes. Parameters ---------- @@ -692,10 +679,9 @@ def tile( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.tile. This method simply wraps the - function, and so the docstring for ivy.tile also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.tile. This method simply + wraps the function, and so the docstring for ivy.tile also applies to + this method with minimal changes. Parameters ---------- @@ -738,10 +724,9 @@ def unstack( axis: int = 0, keepdims: bool = False, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.unstack. This method simply wraps the - function, and so the docstring for ivy.unstack also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.unstack. This method simply + wraps the function, and so the docstring for ivy.unstack also applies + to this method with minimal changes. Parameters ---------- @@ -786,10 +771,9 @@ def zero_pad( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.zero_pad. This method simply wraps the - function, and so the docstring for ivy.zero_pad also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.zero_pad. This method + simply wraps the function, and so the docstring for ivy.zero_pad also + applies to this method with minimal changes. Parameters ---------- diff --git a/ivy/data_classes/array/norms.py b/ivy/data_classes/array/norms.py index 3c66c85517c20..d3116b4d0cf43 100644 --- a/ivy/data_classes/array/norms.py +++ b/ivy/data_classes/array/norms.py @@ -20,10 +20,9 @@ def layer_norm( new_std: float = 1.0, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.layer_norm. This method simply wraps - the function, and so the docstring for ivy.layer_norm also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.layer_norm. This method + simply wraps the function, and so the docstring for ivy.layer_norm also + applies to this method with minimal changes. Parameters ---------- diff --git a/ivy/data_classes/array/random.py b/ivy/data_classes/array/random.py index 047386ee6779f..2835b7690c798 100644 --- a/ivy/data_classes/array/random.py +++ b/ivy/data_classes/array/random.py @@ -18,10 +18,9 @@ def random_uniform( seed: Optional[int] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.random_uniform. This method simply - wraps the function, and so the docstring for ivy.random_uniform also applies to - this method with minimal changes. + """ivy.Array instance method variant of ivy.random_uniform. This method + simply wraps the function, and so the docstring for ivy.random_uniform + also applies to this method with minimal changes. Parameters ---------- @@ -117,10 +116,9 @@ def random_normal( seed: Optional[int] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.random_normal. This method simply wraps - the function, and so the docstring for ivy.random_normal also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.random_normal. This method + simply wraps the function, and so the docstring for ivy.random_normal + also applies to this method with minimal changes. Parameters ---------- @@ -215,10 +213,9 @@ def multinomial( seed: Optional[int] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.multinomial. This method simply wraps - the function, and so the docstring for ivy.multinomial also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.multinomial. This method + simply wraps the function, and so the docstring for ivy.multinomial + also applies to this method with minimal changes. Parameters ---------- @@ -269,10 +266,9 @@ def randint( seed: Optional[int] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.randint. This method simply wraps the - function, and so the docstring for ivy.randint also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.randint. This method simply + wraps the function, and so the docstring for ivy.randint also applies + to this method with minimal changes. Parameters ---------- @@ -363,10 +359,9 @@ def shuffle( seed: Optional[int] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.shuffle. This method simply wraps the - function, and so the docstring for ivy.shuffle also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.shuffle. This method simply + wraps the function, and so the docstring for ivy.shuffle also applies + to this method with minimal changes. Parameters ---------- diff --git a/ivy/data_classes/array/searching.py b/ivy/data_classes/array/searching.py index 15537fa4b2005..527132b4248fa 100644 --- a/ivy/data_classes/array/searching.py +++ b/ivy/data_classes/array/searching.py @@ -18,10 +18,9 @@ def argmax( select_last_index: bool = False, out: Optional[ivy.Array] = None, ) -> Union[ivy.Array, int]: - """ - ivy.Array instance method variant of ivy.argmax. This method simply wraps the - function, and so the docstring for ivy.argmax also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.argmax. This method simply + wraps the function, and so the docstring for ivy.argmax also applies to + this method with minimal changes. Parameters ---------- @@ -94,10 +93,9 @@ def argmin( select_last_index: bool = False, out: Optional[ivy.Array] = None, ) -> Union[ivy.Array, int]: - """ - ivy.Array instance method variant of ivy.argmin. This method simply wraps the - function, and so the docstring for ivy.argmin also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.argmin. This method simply + wraps the function, and so the docstring for ivy.argmin also applies to + this method with minimal changes. Parameters ---------- @@ -162,10 +160,9 @@ def nonzero( size: Optional[int] = None, fill_value: Number = 0, ) -> Union[Tuple[ivy.Array], ivy.Array]: - """ - ivy.Array instance method variant of ivy.nonzero. This method simply wraps the - function, and so the docstring for ivy.nonzero also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.nonzero. This method simply + wraps the function, and so the docstring for ivy.nonzero also applies + to this method with minimal changes. Parameters ---------- @@ -202,10 +199,9 @@ def where( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.where. This method simply wraps the - function, and so the docstring for ivy.where also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.where. This method simply + wraps the function, and so the docstring for ivy.where also applies to + this method with minimal changes. Parameters ---------- @@ -238,10 +234,9 @@ def where( return ivy.where(self._data, x1._data, x2._data, out=out) def argwhere(self: ivy.Array, *, out: Optional[ivy.Array] = None) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.argwhere. This method simply wraps the - function, and so the docstring for ivy.argwhere also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.argwhere. This method + simply wraps the function, and so the docstring for ivy.argwhere also + applies to this method with minimal changes. Parameters ---------- diff --git a/ivy/data_classes/array/set.py b/ivy/data_classes/array/set.py index cde03cfce2555..83e2aefdfbc67 100644 --- a/ivy/data_classes/array/set.py +++ b/ivy/data_classes/array/set.py @@ -8,10 +8,9 @@ class _ArrayWithSet(abc.ABC): def unique_counts(self: ivy.Array) -> Tuple[ivy.Array, ivy.Array]: - """ - ivy.Array instance method variant of ivy.unique_counts. This method simply wraps - the function, and so the docstring for ivy.unique_counts also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.unique_counts. This method + simply wraps the function, and so the docstring for ivy.unique_counts + also applies to this method with minimal changes. Parameters ---------- @@ -108,10 +107,9 @@ def unique_all( axis: Optional[int] = None, by_value: bool = True, ) -> Tuple[ivy.Array, ivy.Array, ivy.Array, ivy.Array]: - """ - ivy.Array instance method variant of ivy.unique_all. This method simply wraps - the function, and so the docstring for ivy.unique_all also applies to this - method with minimal changes. + """ivy.Array instance method variant of ivy.unique_all. This method + simply wraps the function, and so the docstring for ivy.unique_all also + applies to this method with minimal changes. Parameters ---------- @@ -146,10 +144,9 @@ def unique_all( return ivy.unique_all(self._data, axis=axis, by_value=by_value) def unique_inverse(self: ivy.Array) -> Tuple[ivy.Array, ivy.Array]: - """ - ivy.Array instance method variant of ivy.unique_inverse. This method simply - wraps the function, and so the docstring for ivy.unique_inverse also applies to - this method with minimal changes. + """ivy.Array instance method variant of ivy.unique_inverse. This method + simply wraps the function, and so the docstring for ivy.unique_inverse + also applies to this method with minimal changes. Parameters ---------- diff --git a/ivy/data_classes/array/sorting.py b/ivy/data_classes/array/sorting.py index ceb6cfddd0566..b32929c132296 100644 --- a/ivy/data_classes/array/sorting.py +++ b/ivy/data_classes/array/sorting.py @@ -17,10 +17,9 @@ def argsort( stable: bool = True, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.argsort. This method simply wraps the - function, and so the docstring for ivy.argsort also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.argsort. This method simply + wraps the function, and so the docstring for ivy.argsort also applies + to this method with minimal changes. Parameters ---------- @@ -76,10 +75,9 @@ def sort( stable: bool = True, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.sort. This method simply wraps the - function, and so the docstring for ivy.sort also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.sort. This method simply + wraps the function, and so the docstring for ivy.sort also applies to + this method with minimal changes. Examples -------- @@ -103,10 +101,9 @@ def msort( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.msort. This method simply wraps the - function, and so the docstring for ivy.msort also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.msort. This method simply + wraps the function, and so the docstring for ivy.msort also applies to + this method with minimal changes. Parameters ---------- @@ -141,8 +138,7 @@ def searchsorted( ret_dtype: Union[ivy.Dtype, ivy.NativeDtype] = ivy.int64, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.searchsorted. + """ivy.Array instance method variant of ivy.searchsorted. This method simply wraps the function, and so the docstring for ivy.searchsorted also applies to this method with minimal diff --git a/ivy/data_classes/array/statistical.py b/ivy/data_classes/array/statistical.py index e6cf071dd2319..b07294c52696e 100644 --- a/ivy/data_classes/array/statistical.py +++ b/ivy/data_classes/array/statistical.py @@ -15,10 +15,11 @@ def min( *, axis: Optional[Union[int, Sequence[int]]] = None, keepdims: bool = False, + initial: Optional[Union[int, float, complex]] = None, + where: Optional[ivy.Array] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Calculate the minimum value of the input array ``x``. + """Calculate the minimum value of the input array ``x``. Parameters ---------- @@ -37,6 +38,11 @@ def min( array (see :ref:`broadcasting`). Otherwise, if ``False``, the reduced axes (dimensions) must not be included in the result. Default: ``False``. + initial + The maximum value of an output element. + Must be present to allow computation on empty slice. + where + Elements to compare for minimum out optional output array, for writing the result to. @@ -69,7 +75,14 @@ def min( >>> print(y) ivy.array(0.1) """ - return ivy.min(self._data, axis=axis, keepdims=keepdims, out=out) + return ivy.min( + self._data, + axis=axis, + keepdims=keepdims, + initial=initial, + where=where, + out=out, + ) def max( self: ivy.Array, @@ -79,10 +92,9 @@ def max( keepdims: bool = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.max. This method simply wraps the - function, and so the docstring for ivy.max also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.max. This method simply + wraps the function, and so the docstring for ivy.max also applies to + this method with minimal changes. Parameters ---------- @@ -142,10 +154,9 @@ def mean( keepdims: bool = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.mean. This method simply wraps the - function, and so the docstring for ivy.mean also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.mean. This method simply + wraps the function, and so the docstring for ivy.mean also applies to + this method with minimal changes. **Special Cases** @@ -230,10 +241,9 @@ def var( keepdims: bool = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.var. This method simply wraps the - function, and so the docstring for ivy.var also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.var. This method simply + wraps the function, and so the docstring for ivy.var also applies to + this method with minimal changes. **Special Cases** @@ -316,10 +326,9 @@ def prod( dtype: Optional[Union[ivy.Dtype, ivy.NativeDtype]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.array instance method variant of ivy.prod. This method simply wraps the - function, and so the docstring for ivy.prod also applies to this method with - minimal changes. + """ivy.array instance method variant of ivy.prod. This method simply + wraps the function, and so the docstring for ivy.prod also applies to + this method with minimal changes. Parameters ---------- @@ -402,10 +411,9 @@ def std( keepdims: bool = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.array instance method variant of ivy.std. This method simply wraps the - function, and so the docstring for ivy.std also applies to this method with - minimal changes. + """ivy.array instance method variant of ivy.std. This method simply + wraps the function, and so the docstring for ivy.std also applies to + this method with minimal changes. Parameters ---------- @@ -497,10 +505,9 @@ def cumsum( dtype: Optional[Union[ivy.Dtype, ivy.NativeDtype]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.cumsum. This method simply wraps the - function, and so the docstring for ivy.cumsum also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.cumsum. This method simply + wraps the function, and so the docstring for ivy.cumsum also applies to + this method with minimal changes. Parameters ---------- @@ -572,10 +579,9 @@ def cumprod( dtype: Optional[Union[ivy.Dtype, ivy.NativeDtype]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.cumprod. This method simply wraps the - function, and so the docstring for ivy.cumprod also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.cumprod. This method simply + wraps the function, and so the docstring for ivy.cumprod also applies + to this method with minimal changes. Parameters ---------- @@ -643,10 +649,9 @@ def einsum( *operands: Union[ivy.Array, ivy.NativeArray], out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.einsum. This method simply wraps the - function, and so the docstring for ivy.einsum also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.einsum. This method simply + wraps the function, and so the docstring for ivy.einsum also applies to + this method with minimal changes. Parameters ---------- diff --git a/ivy/data_classes/array/utility.py b/ivy/data_classes/array/utility.py index 089b99918be1b..a711dfd46f1f8 100644 --- a/ivy/data_classes/array/utility.py +++ b/ivy/data_classes/array/utility.py @@ -15,10 +15,9 @@ def all( keepdims: bool = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.all. This method simply wraps the - function, and so the docstring for ivy.all also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.all. This method simply + wraps the function, and so the docstring for ivy.all also applies to + this method with minimal changes. Parameters ---------- @@ -76,10 +75,9 @@ def any( keepdims: bool = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.any. This method simply wraps the - function, and so the docstring for ivy.any also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.any. This method simply + wraps the function, and so the docstring for ivy.any also applies to + this method with minimal changes. Parameters ---------- diff --git a/ivy/data_classes/array/wrapping.py b/ivy/data_classes/array/wrapping.py index 74105ef566edc..f79ad5a07191a 100644 --- a/ivy/data_classes/array/wrapping.py +++ b/ivy/data_classes/array/wrapping.py @@ -9,8 +9,7 @@ def _wrap_function(function_name: str) -> Callable: - """ - Wrap the function called `function_name`. + """Wrap the function called `function_name`. Parameters ---------- @@ -33,9 +32,8 @@ def _wrap_function(function_name: str) -> Callable: """ def new_function(self, *args, **kwargs): - """ - Add the data of the current array from which the instance function is invoked as - the first arg parameter or kwarg parameter. + """Add the data of the current array from which the instance function + is invoked as the first arg parameter or kwarg parameter. Return the new function with the name function_name and the new args variable or kwargs as the new inputs. @@ -63,9 +61,8 @@ def new_function(self, *args, **kwargs): def add_ivy_array_instance_methods( cls: Type[ivy.Array], modules: List[ModuleType], to_ignore: Iterable = () ): - """ - Loop over all ivy modules such as activations, general, etc. and add the module - functions to ivy arrays as instance methods using _wrap_function. + """Loop over all ivy modules such as activations, general, etc. and add the + module functions to ivy arrays as instance methods using _wrap_function. Parameters ---------- diff --git a/ivy/data_classes/container/activations.py b/ivy/data_classes/container/activations.py index 9d5883bd1d213..c8499ef9d6f91 100644 --- a/ivy/data_classes/container/activations.py +++ b/ivy/data_classes/container/activations.py @@ -21,10 +21,9 @@ def _static_relu( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.relu. This method simply wraps the - function, and so the docstring for ivy.relu also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.relu. This method simply + wraps the function, and so the docstring for ivy.relu also applies to + this method with minimal changes. Parameters ---------- @@ -86,10 +85,9 @@ def relu( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.relu. This method simply wraps the - function, and so the docstring for ivy.relu also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.relu. This method + simply wraps the function, and so the docstring for ivy.relu also + applies to this method with minimal changes. Parameters ---------- @@ -152,10 +150,9 @@ def _static_leaky_relu( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.leaky_relu. This method simply wraps - the function, and so the docstring for ivy.leaky_relu also applies to this - method with minimal changes. + """ivy.Container static method variant of ivy.leaky_relu. This method + simply wraps the function, and so the docstring for ivy.leaky_relu also + applies to this method with minimal changes. Parameters ---------- @@ -220,10 +217,9 @@ def leaky_relu( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.leaky_relu. This method simply - wraps the function, and so the docstring for ivy.leaky_relu also applies to this - method with minimal changes. + """ivy.Container instance method variant of ivy.leaky_relu. This method + simply wraps the function, and so the docstring for ivy.leaky_relu also + applies to this method with minimal changes. Parameters ---------- @@ -288,10 +284,9 @@ def _static_gelu( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.gelu. This method simply wraps the - function, and so the docstring for ivy.gelu also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.gelu. This method simply + wraps the function, and so the docstring for ivy.gelu also applies to + this method with minimal changes. Parameters ---------- @@ -355,10 +350,9 @@ def gelu( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.gelu. This method simply wraps the - function, and so the docstring for ivy.gelu also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.gelu. This method + simply wraps the function, and so the docstring for ivy.gelu also + applies to this method with minimal changes. Parameters ---------- @@ -422,10 +416,9 @@ def _static_sigmoid( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.sigmoid. This method simply wraps the - function, and so the docstring for ivy.sigmoid also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.sigmoid. This method + simply wraps the function, and so the docstring for ivy.sigmoid also + applies to this method with minimal changes. Parameters ---------- @@ -486,10 +479,9 @@ def sigmoid( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.sigmoid. This method simply wraps - the function, and so the docstring for ivy.sigmoid also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.sigmoid. This method + simply wraps the function, and so the docstring for ivy.sigmoid also + applies to this method with minimal changes. Parameters ---------- @@ -551,10 +543,9 @@ def _static_softmax( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.softmax. This method simply wraps the - function, and so the docstring for ivy.softmax also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.softmax. This method + simply wraps the function, and so the docstring for ivy.softmax also + applies to this method with minimal changes. Parameters ---------- @@ -619,10 +610,9 @@ def softmax( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.softmax. This method simply wraps - the function, and so the docstring for ivy.softmax also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.softmax. This method + simply wraps the function, and so the docstring for ivy.softmax also + applies to this method with minimal changes. Parameters ---------- @@ -688,10 +678,9 @@ def _static_softplus( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.softplus. This method simply wraps - the function, and so the docstring for ivy.softplus also applies to this method - with minimal changes. + """ivy.Container static method variant of ivy.softplus. This method + simply wraps the function, and so the docstring for ivy.softplus also + applies to this method with minimal changes. Parameters ---------- @@ -767,10 +756,9 @@ def softplus( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.softplus. This method simply wraps - the function, and so the docstring for ivy.softplus also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.softplus. This method + simply wraps the function, and so the docstring for ivy.softplus also + applies to this method with minimal changes. Parameters ---------- @@ -844,10 +832,9 @@ def _static_log_softmax( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.log_softmax. This method simply wraps - the function, and so the docstring for ivy.log_softmax also applies to this - method with minimal changes. + """ivy.Container static method variant of ivy.log_softmax. This method + simply wraps the function, and so the docstring for ivy.log_softmax + also applies to this method with minimal changes. Parameters ---------- @@ -919,10 +906,9 @@ def log_softmax( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ): - """ - ivy.Container instance method variant of ivy.log_softmax. This method simply - wraps the function, and so the docstring for ivy.log_softmax also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.log_softmax. This + method simply wraps the function, and so the docstring for + ivy.log_softmax also applies to this method with minimal changes. Parameters ---------- @@ -993,10 +979,9 @@ def _static_mish( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.mish. This method simply wraps the - function, and so the docstring for ivy.mish also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.mish. This method simply + wraps the function, and so the docstring for ivy.mish also applies to + this method with minimal changes. Parameters ---------- @@ -1058,10 +1043,9 @@ def mish( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.mish. This method simply wraps the - function, and so the docstring for ivy.mish also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.mish. This method + simply wraps the function, and so the docstring for ivy.mish also + applies to this method with minimal changes. Parameters ---------- @@ -1123,10 +1107,9 @@ def _static_hardswish( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.hardswish. This method simply wraps - the function, and so the docstring for ivy.hardswish also applies to this method - with minimal changes. + """ivy.Container static method variant of ivy.hardswish. This method + simply wraps the function, and so the docstring for ivy.hardswish also + applies to this method with minimal changes. Parameters ---------- @@ -1188,10 +1171,9 @@ def hardswish( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.hardswish. This method simply wraps - the function, and so the docstring for ivy.hardswish also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.hardswish. This method + simply wraps the function, and so the docstring for ivy.hardswish also + applies to this method with minimal changes. Parameters ---------- diff --git a/ivy/data_classes/container/base.py b/ivy/data_classes/container/base.py index ea9ebfce7853e..bb004b709a37f 100644 --- a/ivy/data_classes/container/base.py +++ b/ivy/data_classes/container/base.py @@ -72,8 +72,7 @@ def __init__( build_callable=False, **kwargs, ): - """ - Initialize container object from input dict representation. + """Initialize container object from input dict representation. Parameters ---------- @@ -151,19 +150,19 @@ def __init__( "dict_in and **kwargs cannot both be specified for ivy.Container " "constructor, please specify one or the other, not both." ) - self._config_in = dict( - print_limit=print_limit, - print_indent=print_indent, - key_length_limit=key_length_limit, - print_line_spacing=print_line_spacing, - ivyh=ivyh, - default_key_color=default_key_color, - keyword_color_dict=keyword_color_dict, - rebuild_child_containers=rebuild_child_containers, - build_callable=build_callable, - types_to_iteratively_nest=types_to_iteratively_nest, - alphabetical_keys=alphabetical_keys, - ) + self._config_in = { + "print_limit": print_limit, + "print_indent": print_indent, + "key_length_limit": key_length_limit, + "print_line_spacing": print_line_spacing, + "ivyh": ivyh, + "default_key_color": default_key_color, + "keyword_color_dict": keyword_color_dict, + "rebuild_child_containers": rebuild_child_containers, + "build_callable": build_callable, + "types_to_iteratively_nest": types_to_iteratively_nest, + "alphabetical_keys": alphabetical_keys, + } self._config = {} self.cont_inplace_update(dict_in, **self._config_in) @@ -272,9 +271,8 @@ def map_fn(vals, _): @staticmethod def cont_handle_inplace(ret, out): - """ - Return an inplace update of out, provided it is not None, by updating with the - values in ret. + """Return an inplace update of out, provided it is not None, by + updating with the values in ret. Parameters ---------- @@ -295,8 +293,7 @@ def cont_handle_inplace(ret, out): @staticmethod def cont_list_join(containers, config=None): - """ - Join containers of lists together along the specified dimension. + """Join containers of lists together along the specified dimension. Parameters ---------- @@ -328,8 +325,7 @@ def cont_list_join(containers, config=None): @staticmethod def cont_list_stack(containers, dim, config=None): - """ - List stack containers together along the specified dimension. + """List stack containers together along the specified dimension. Parameters ---------- @@ -379,9 +375,8 @@ def _cont_mean_unify(containers, device, _=None, _1=None): @staticmethod def cont_unify(containers, device, mode, axis=0): - """ - Unify a list of containers, on arbitrary devices, to a single container on the - specified device. + """Unify a list of containers, on arbitrary devices, to a single + container on the specified device. Parameters ---------- @@ -407,9 +402,8 @@ def cont_unify(containers, device, mode, axis=0): @staticmethod def cont_combine(*containers, config=None): - """ - Combine keys and values in a sequence of containers, with priority given to the - right-most container in the case of duplicates. + """Combine keys and values in a sequence of containers, with priority + given to the right-most container in the case of duplicates. Parameters ---------- @@ -466,10 +460,9 @@ def cont_diff( detect_shape_diffs=True, config=None, ): - """ - Compare keys and values in a sequence of containers, returning the single shared - values where they are the same, and new nested sub-dicts with all values where - they are different. + """Compare keys and values in a sequence of containers, returning the + single shared values where they are the same, and new nested sub-dicts + with all values where they are different. Parameters ---------- @@ -613,10 +606,9 @@ def cont_structural_diff( detect_shape_diffs=True, config=None, ): - """ - Compare keys and shapes in a sequence of containers, returning the single shared - values where they are the same, and new nested sub-dicts with all values where - they are different. + """Compare keys and shapes in a sequence of containers, returning the + single shared values where they are the same, and new nested sub-dicts + with all values where they are different. Parameters ---------- @@ -666,8 +658,7 @@ def cont_multi_map( map_nests=False, assert_identical=False, ): - """ - Apply function to all array values from a collection of containers. + """Apply function to all array values from a collection of containers. Parameters ---------- @@ -786,8 +777,7 @@ def _found_in_key_chains(this_key_chain, key_chains): @staticmethod def cont_common_key_chains(containers): - """ - Return the key-chains common across all containers. + """Return the key-chains common across all containers. Parameters ---------- @@ -816,9 +806,8 @@ def cont_identical( key_chain="", assert_and_assign=False, ): - """ - Return a single boolean as to whether the input containers have identical key- - chains and data types. + """Return a single boolean as to whether the input containers have + identical key- chains and data types. Parameters ---------- @@ -848,6 +837,7 @@ def cont_identical( assert_and_assign if true, then the container being compared with is updated with the value in the container being compared to given that the structures are congruent + Returns ------- Boolean @@ -929,9 +919,8 @@ def cont_assert_identical( to_apply=True, partial=False, ): - """ - Assert whether the input containers are identical. Otherwise, the diff is shown - in an exception. + """Assert whether the input containers are identical. Otherwise, the + diff is shown in an exception. Parameters ---------- @@ -982,9 +971,8 @@ def cont_identical_structure( key_chain="", assert_and_assign=False, ): - """ - Return a single boolean as to whether the input containers have identical - structure. + """Return a single boolean as to whether the input containers have + identical structure. Parameters ---------- @@ -1009,6 +997,7 @@ def cont_identical_structure( assert_and_assign if true, then the container being compared with is updated with the value in the container being compared to given that the structures are congruent + Returns ------- Boolean @@ -1036,9 +1025,8 @@ def cont_assert_identical_structure( partial=False, assert_and_assign=False, ): - """ - Assert whether the input containers have identical structure. Otherwise, the - diff is shown in an exception. + """Assert whether the input containers have identical structure. + Otherwise, the diff is shown in an exception. Parameters ---------- @@ -1078,9 +1066,8 @@ def cont_assert_identical_structure( @staticmethod def cont_identical_configs(containers): - """ - Return a single boolean as to whether the input containers all have identical - configs. + """Return a single boolean as to whether the input containers all have + identical configs. Parameters ---------- @@ -1096,9 +1083,9 @@ def cont_identical_configs(containers): @staticmethod def cont_identical_array_shapes(containers, exclusive=False): - """ - Determine whether all of the containers have identical number of arrays and - identical array shapes, regardless of their key-chain structures. + """Determine whether all of the containers have identical number of + arrays and identical array shapes, regardless of their key-chain + structures. Parameters ---------- @@ -1140,9 +1127,8 @@ def cont_load(filepath, format="h5py"): def cont_from_disk_as_hdf5( h5_obj_or_filepath, slice_obj=slice(None), alphabetical_keys=True, ivyh=None ): - """ - Load container object from disk, as an h5py file, at the specified hdf5 - filepath. + """Load container object from disk, as an h5py file, at the specified + hdf5 filepath. Parameters ---------- @@ -1169,7 +1155,7 @@ def cont_from_disk_as_hdf5( ), ) container_dict = {} - if type(h5_obj_or_filepath) is str: + if isinstance(h5_obj_or_filepath, str): h5_obj = h5py.File(h5_obj_or_filepath, "r") else: h5_obj = h5_obj_or_filepath @@ -1191,8 +1177,7 @@ def cont_from_disk_as_hdf5( @staticmethod def cont_from_disk_as_pickled(pickle_filepath, ivyh=None): - """ - Load container object from disk at the specified pickle filepath. + """Load container object from disk at the specified pickle filepath. Parameters ---------- @@ -1214,9 +1199,9 @@ def cont_from_disk_as_pickled(pickle_filepath, ivyh=None): @staticmethod def cont_from_disk_as_json(json_filepath, ivyh=None): - """ - Load container object from disk at the specified json filepath. If some objects - were not json-able during saving, then they will be loaded as strings. + """Load container object from disk at the specified json filepath. If + some objects were not json-able during saving, then they will be loaded + as strings. Parameters ---------- @@ -1235,8 +1220,7 @@ def cont_from_disk_as_json(json_filepath, ivyh=None): @staticmethod def h5_file_size(h5_obj_or_filepath): - """ - Get file size of h5 file contents. + """Get file size of h5 file contents. Parameters ---------- @@ -1254,14 +1238,14 @@ def h5_file_size(h5_obj_or_filepath): "the size of hdf5 files." ), ) - if type(h5_obj_or_filepath) is str: + if isinstance(h5_obj_or_filepath, str): h5_obj = h5py.File(h5_obj_or_filepath, "r") else: h5_obj = h5_obj_or_filepath size = 0 batch_size = 0 - for key, value in h5_obj.items(): + for value in h5_obj.values(): if isinstance(value, h5py.Group): size_to_add, batch_size = ivy.Container.h5_file_size(value) size += size_to_add @@ -1277,9 +1261,8 @@ def h5_file_size(h5_obj_or_filepath): @staticmethod def shuffle_h5_file(h5_obj_or_filepath, seed_value=0): - """ - Shuffle entries in all datasets of h5 file, such that they are still aligned - along axis 0. + """Shuffle entries in all datasets of h5 file, such that they are still + aligned along axis 0. Parameters ---------- @@ -1297,12 +1280,12 @@ def shuffle_h5_file(h5_obj_or_filepath, seed_value=0): ) if seed_value is None: seed_value = random.randint(0, 1000) - if type(h5_obj_or_filepath) is str: + if isinstance(h5_obj_or_filepath, str): h5_obj = h5py.File(h5_obj_or_filepath, "a") else: h5_obj = h5_obj_or_filepath - for key, value in h5_obj.items(): + for value in h5_obj.values(): if isinstance(value, h5py.Group): ivy.Container.shuffle_h5_file(value, seed_value) elif isinstance(value, h5py.Dataset): @@ -1318,8 +1301,7 @@ def shuffle_h5_file(h5_obj_or_filepath, seed_value=0): @staticmethod def cont_reduce(containers, reduction, config=None): - """ - Reduce containers. + """Reduce containers. Parameters ---------- @@ -1361,8 +1343,7 @@ def cont_reduce(containers, reduction, config=None): def cont_flatten_key_chain( key_chain, replacement="__", above_height=None, below_depth=None ): - """ - Summary. + """Summary. Parameters ---------- @@ -1400,8 +1381,7 @@ def cont_flatten_key_chain( @staticmethod def cont_trim_key(key, max_length): - """ - Summary. Returns a trimmed key with a maximum length of max_length. + """Summary. Returns a trimmed key with a maximum length of max_length. Parameters ---------- @@ -1602,7 +1582,7 @@ def _cont_prune_key_chains_input_as_dict(self, key_chains, return_cont=None): # ---------------# def cont_duplicate_array_keychains(self): - duplciates = () + duplicates = () key_chains = self.cont_all_key_chains() skips = set() for i in range(len(key_chains)): @@ -1618,9 +1598,9 @@ def cont_duplicate_array_keychains(self): if key_chains[j] not in temp_duplicates: temp_duplicates += (key_chains[j],) if len(temp_duplicates) > 0: - duplciates += (temp_duplicates,) - skips = chain.from_iterable(duplciates) - return duplciates + duplicates += (temp_duplicates,) + skips = chain.from_iterable(duplicates) + return duplicates def cont_update_config(self, **config): new_config = {} @@ -1641,9 +1621,8 @@ def cont_update_config(self, **config): def cont_inplace_update( self, dict_in: Union[ivy.Container, dict], **config ) -> ivy.Container: - """ - Update the contents of this container inplace, using either a new dict or - container. + """Update the contents of this container inplace, using either a new + dict or container. Parameters ---------- @@ -1695,8 +1674,8 @@ def cont_all_true( prune_unapplied=False, map_sequences=False, ): - """ - Determine whether all the entries in the container boolean evaluate to True. + """Determine whether all the entries in the container boolean evaluate + to True. Parameters ---------- @@ -1742,8 +1721,8 @@ def cont_all_false( prune_unapplied=False, map_sequences=False, ): - """ - Determine whether all the entries in the container boolean evaluate to False. + """Determine whether all the entries in the container boolean evaluate + to False. Parameters ---------- @@ -1782,8 +1761,7 @@ def cont_all_false( ) def cont_slice_via_key(self, slice_key): - """ - Get slice of container, based on key. + """Get slice of container, based on key. Parameters ---------- @@ -1812,8 +1790,7 @@ def cont_as_bools( prune_unapplied=False, map_sequences=False, ): - """ - Return boolean evaluation for all nested items in the container. + """Return boolean evaluation for all nested items in the container. Parameters ---------- @@ -1852,8 +1829,7 @@ def _ret_bool(x): ) def cont_unstack_conts(self, axis, keepdims=False, dim_size=None): - """ - Unstack containers along specified dimension. + """Unstack containers along specified dimension. Parameters ---------- @@ -1900,8 +1876,7 @@ def split_conts( prune_unapplied=False, map_sequences=False, ): - """ - Split a container into multiple sub-containers. + """Split a container into multiple sub-containers. The function does that by splitting their constituent arrays. @@ -1956,9 +1931,8 @@ def split_conts( ).cont_unstack_conts(0, dim_size=dim_size) def cont_num_arrays(self, exclusive=False): - """ - Compute the number of arrays present at the leaf nodes, including variables by - default. + """Compute the number of arrays present at the leaf nodes, including + variables by default. Parameters ---------- @@ -1973,9 +1947,8 @@ def cont_num_arrays(self, exclusive=False): ) def cont_size_ordered_arrays(self, exclusive=False): - """ - Return a container with keychains mapped to flat keys, and arrays given in order - of smallest to largest. + """Return a container with keychains mapped to flat keys, and arrays + given in order of smallest to largest. Parameters ---------- @@ -2010,8 +1983,8 @@ def cont_save(self, filepath, format="h5py"): def cont_to_disk_as_hdf5( self, h5_obj_or_filepath, starting_index=0, mode="a", max_batch_size=None ): - """ - Save container object to disk, as an h5py file, at the specified filepath. + """Save container object to disk, as an h5py file, at the specified + filepath. Parameters ---------- @@ -2034,7 +2007,7 @@ def cont_to_disk_as_hdf5( "containers to disk as hdf5 files." ), ) - if type(h5_obj_or_filepath) is str: + if isinstance(h5_obj_or_filepath, str): h5_obj = h5py.File(h5_obj_or_filepath, mode) else: h5_obj = h5_obj_or_filepath @@ -2052,9 +2025,9 @@ def cont_to_disk_as_hdf5( value_shape = value_as_np.shape this_batch_size = value_shape[0] max_bs = ( - starting_index + this_batch_size - if not max_batch_size - else max_batch_size + max_batch_size + if max_batch_size + else starting_index + this_batch_size ) if key not in h5_obj.keys(): dataset_shape = [max_bs] + list(value_shape[1:]) @@ -2070,8 +2043,8 @@ def cont_to_disk_as_hdf5( ) def cont_to_disk_as_pickled(self, pickle_filepath): - """ - Save container object to disk, as an pickled file, at the specified filepath. + """Save container object to disk, as an pickled file, at the specified + filepath. Parameters ---------- @@ -2100,8 +2073,8 @@ def cont_to_jsonable(self, return_dict=None): return return_dict def cont_to_disk_as_json(self, json_filepath): - """ - Save container object to disk, as an json file, at the specified filepath. + """Save container object to disk, as an json file, at the specified + filepath. Parameters ---------- @@ -2121,8 +2094,7 @@ def cont_to_nested_list(self): return return_list def cont_to_raw(self): - """ - Convert container to its original form. + """Convert container to its original form. Returns ------- @@ -2130,24 +2102,21 @@ def cont_to_raw(self): Container data in its raw form. """ return_item = {} - for i, (key, value) in enumerate(self.items()): + for key, value in self.items(): if isinstance(value, ivy.Container): return_item[key] = value.cont_to_raw() elif key[0:3] == "it_" and tuple(self._types_to_iteratively_nest): - return_item = list( - [ - v.cont_to_raw() if isinstance(v, ivy.Container) else v - for v in self.values() - ] - ) + return_item = [ + v.cont_to_raw() if isinstance(v, ivy.Container) else v + for v in self.values() + ] break else: return_item[key] = value return return_item def cont_to_dict(self): - """ - Summary. + """Summary. Returns ------- @@ -2201,7 +2170,7 @@ def cont_to_iterator_values(self, include_empty=False): Iterator for the container values. """ - for key, value in self.items(): + for value in self.values(): if isinstance(value, ivy.Container) and (not include_empty or value): # noinspection PyCompatibility yield from value.cont_to_iterator_values(include_empty) @@ -2241,20 +2210,18 @@ def cont_to_iterator_keys( yield kc def cont_to_flat_list(self): - """ - Summary. + """Summary. Returns ------- ret Container as flat list. """ - return list([item for key, item in self.cont_to_iterator()]) + return [item for key, item in self.cont_to_iterator()] def cont_from_flat_list(self, flat_list): - """ - Return new container object with the same hierarchy, but with values replaced - from flat list. + """Return new container object with the same hierarchy, but with values + replaced from flat list. Parameters ---------- @@ -2275,9 +2242,8 @@ def cont_from_flat_list(self, flat_list): return ivy.Container(new_dict, **self._config) def cont_has_key(self, query_key): - """ - Determine whether container object has specified key somewhere in the nested - structure. + """Determine whether container object has specified key somewhere in + the nested structure. Parameters ---------- @@ -2310,8 +2276,7 @@ def map_fn(x, kc): return has_key def cont_has_key_chain(self, key_chain): - """ - Determine whether container object has specified key-chain. + """Determine whether container object has specified key-chain. Parameters ---------- @@ -2333,8 +2298,7 @@ def cont_has_key_chain(self, key_chain): return True def cont_find_sub_container(self, sub_cont_to_find, partial=False): - """ - Find the sub-container in the current container if it exists. + """Find the sub-container in the current container if it exists. Parameters ---------- @@ -2365,9 +2329,8 @@ def _check_sub_cont(sub_cont, kc): return key_chain_found def cont_contains_sub_container(self, sub_cont, partial=False): - """ - Determine whether the current container contains the sub-container, with - matching structure and array values. + """Determine whether the current container contains the sub-container, + with matching structure and array values. Parameters ---------- @@ -2384,9 +2347,8 @@ def cont_contains_sub_container(self, sub_cont, partial=False): return isinstance(self.cont_find_sub_container(sub_cont, partial), str) def cont_assert_contains_sub_container(self, sub_cont, partial=False): - """ - Assert that the current container contains the sub-container, otherwise - exception raised with the diff printed to screen. + """Assert that the current container contains the sub-container, + otherwise exception raised with the diff printed to screen. Parameters ---------- @@ -2415,8 +2377,8 @@ def cont_assert_contains_sub_container(self, sub_cont, partial=False): def cont_find_sub_structure( self, sub_struc_to_find, check_shapes=True, partial=False ): - """ - Find the sub-container structure in the current container if it exists. + """Find the sub-container structure in the current container if it + exists. Parameters ---------- @@ -2460,8 +2422,8 @@ def _check_sub_cont(sub_cont, kc): return key_chain_found def cont_contains_sub_structure(self, sub_cont, check_shapes=True, partial=False): - """ - Determine whether the current container contains the sub-container structure. + """Determine whether the current container contains the sub-container + structure. Parameters ---------- @@ -2480,9 +2442,8 @@ def cont_contains_sub_structure(self, sub_cont, check_shapes=True, partial=False def cont_assert_contains_sub_structure( self, sub_cont, check_shapes=True, partial=False ): - """ - Assert that the current container contains the sub-container structure, - otherwise exception raised with the diff printed to screen. + """Assert that the current container contains the sub-container + structure, otherwise exception raised with the diff printed to screen. Parameters ---------- @@ -2520,8 +2481,8 @@ def cont_assert_contains_sub_structure( def cont_at_keys( self, queries, ignore_none=True, containing=False, ignore_key_errors=False ): - """ - Query container object at specified keys, either as list or nested dict. + """Query container object at specified keys, either as list or nested + dict. Parameters ---------- @@ -2564,8 +2525,7 @@ def map_fn(x, kc): ) def cont_at_key_chain(self, key_chain, ignore_key_errors=False): - """ - Query container object at a specified key-chain. + """Query container object at a specified key-chain. Parameters ---------- @@ -2591,8 +2551,8 @@ def cont_at_key_chain(self, key_chain, ignore_key_errors=False): return ret def cont_at_key_chains(self, key_chains, ignore_none=True, ignore_key_errors=False): - """ - Query container object at specified key-chains, either as list or nested dict. + """Query container object at specified key-chains, either as list or + nested dict. Parameters ---------- @@ -2657,8 +2617,7 @@ def cont_key_chains_containing(self, sub_str, include_empty=False): ] def cont_set_at_keys(self, target_dict): - """ - Set values of container object at specified keys. + """Set values of container object at specified keys. Parameters ---------- @@ -2681,8 +2640,7 @@ def cont_set_at_keys(self, target_dict): return ivy.Container(return_dict, **self._config) def cont_set_at_key_chain(self, key_chain, val, inplace=False): - """ - Set value of container object at a specified key-chain. + """Set value of container object at a specified key-chain. Parameters ---------- @@ -2712,8 +2670,7 @@ def cont_set_at_key_chain(self, key_chain, val, inplace=False): return cont def cont_overwrite_at_key_chain(self, key_chain, val, inplace=False): - """ - Overwrite value of container object at a specified key-chain. + """Overwrite value of container object at a specified key-chain. Parameters ---------- @@ -2757,8 +2714,7 @@ def cont_overwrite_at_key_chain(self, key_chain, val, inplace=False): return cont def cont_set_at_key_chains(self, target_dict, return_dict=None, inplace=False): - """ - Set values of container object at specified key-chains. + """Set values of container object at specified key-chains. Parameters ---------- @@ -2789,8 +2745,7 @@ def cont_set_at_key_chains(self, target_dict, return_dict=None, inplace=False): def cont_overwrite_at_key_chains( self, target_dict, return_dict=None, inplace=False ): - """ - Overwrite values of container object at specified key-chains. + """Overwrite values of container object at specified key-chains. Parameters ---------- @@ -2830,8 +2785,7 @@ def cont_overwrite_at_key_chains( return return_dict def cont_prune_keys(self, query_keys, ignore_none=True): - """ - Recursively prune set of keys. + """Recursively prune set of keys. Parameters ---------- @@ -2871,8 +2825,7 @@ def map_fn(x, kc): return self.cont_prune_key_chains(key_chains_to_prune) def cont_prune_key_chain(self, key_chain): - """ - Recursively prune chain of keys, specified as 'key1/key2/key3/...'. + """Recursively prune chain of keys, specified as 'key1/key2/key3/...'. Parameters ---------- @@ -2906,8 +2859,7 @@ def cont_prune_key_chain(self, key_chain): return ivy.Container(out_dict, **self._config) def cont_prune_key_chains(self, key_chains, ignore_none=True): - """ - Recursively prune set of key chains. + """Recursively prune set of key chains. Parameters ---------- @@ -2936,8 +2888,7 @@ def cont_prune_key_chains(self, key_chains, ignore_none=True): ) def cont_format_key_chains(self, format_fn): - """ - Format all key-chains, using the formatting function. + """Format all key-chains, using the formatting function. Parameters ---------- @@ -2962,9 +2913,8 @@ def cont_sort_by_key(self): return ivy.Container(new_dict, **self._config) def cont_prune_empty(self, keep_nones=False, base=True): - """ - Recursively prunes empty keys from the container dict structure. Returns None if - the entire container is empty. + """Recursively prunes empty keys from the container dict structure. + Returns None if the entire container is empty. Parameters ---------- @@ -2993,9 +2943,8 @@ def cont_prune_empty(self, keep_nones=False, base=True): return def cont_prune_key_from_key_chains(self, absolute=None, containing=None): - """ - Recursively prune absolute key or key containing a certain substring from all - key chains. + """Recursively prune absolute key or key containing a certain substring + from all key chains. Parameters ---------- @@ -3035,9 +2984,8 @@ def cont_prune_key_from_key_chains(self, absolute=None, containing=None): return out_cont def cont_prune_keys_from_key_chains(self, absolute=None, containing=None): - """ - Recursively prune absolute keys or keys containing certain substrings from all - key chains. + """Recursively prune absolute keys or keys containing certain + substrings from all key chains. Parameters ---------- @@ -3083,9 +3031,9 @@ def cont_prune_keys_from_key_chains(self, absolute=None, containing=None): def cont_restructure_key_chains( self, keychain_mapping, keep_orig=True, replace=True ): - """ - Create a new container with the same contents, but a new key-chain structure. - Given by the mapping with keys as old key-chains and values as new key-chains. + """Create a new container with the same contents, but a new key-chain + structure. Given by the mapping with keys as old key-chains and values + as new key-chains. Parameters ---------- @@ -3107,10 +3055,9 @@ def cont_restructure_key_chains( return new_cont def cont_restructure(self, mapping, keep_orig=True, replace=True): - """ - Create a new container with the same contents, but a new key-chain structure, - and transposes and/or reshaped arrays. Given by the mapping with keys as old - key-chains and values as new key-chains. + """Create a new container with the same contents, but a new key-chain + structure, and transposes and/or reshaped arrays. Given by the mapping + with keys as old key-chains and values as new key-chains. Parameters ---------- @@ -3146,8 +3093,7 @@ def cont_restructure(self, mapping, keep_orig=True, replace=True): def cont_flatten_key_chains( self, include_empty=False, above_height=None, below_depth=None ): - """ - Summary. + """Summary. Parameters ---------- @@ -3169,8 +3115,7 @@ def cont_flatten_key_chains( ) def cont_copy(self): - """ - Create a copy of this container. + """Create a copy of this container. Returns ------- @@ -3179,8 +3124,7 @@ def cont_copy(self): return ivy.Container(self.cont_to_dict(), **self._config) def cont_deep_copy(self): - """ - Create a deep copy (copying all internal tensors) of this container. + """Create a deep copy (copying all internal tensors) of this container. return: A deep copy of the container """ @@ -3203,8 +3147,7 @@ def cont_map( inplace=False, key_chain="", ): - """ - Apply function to all array values of container. + """Apply function to all array values of container. Parameters ---------- @@ -3279,8 +3222,7 @@ def cont_map_sub_conts( key_chain="", include_self=True, ): - """ - Apply function to all sub-contains in the container. + """Apply function to all sub-contains in the container. Parameters ---------- @@ -3342,9 +3284,8 @@ def to_list(x, _=""): return self.cont_map(to_list) def cont_reshape_like(self, target_dict, leading_shape=None, return_cont=None): - """ - Set shapes of container entries to shapes specified by new container with the - same key structure. + """Set shapes of container entries to shapes specified by new container + with the same key structure. Parameters ---------- @@ -3375,9 +3316,8 @@ def cont_reshape_like(self, target_dict, leading_shape=None, return_cont=None): return ivy.Container(return_cont, **self._config) def cont_create_if_absent(self, key, value, inplace=True): - """ - Add a key to the container with corresponding value, if it is not already - present. otherwise, do nothing. + """Add a key to the container with corresponding value, if it is not + already present. otherwise, do nothing. Parameters ---------- @@ -3392,8 +3332,8 @@ def cont_create_if_absent(self, key, value, inplace=True): self.cont_set_at_key_chain(key, value, inplace) def cont_if_exists(self, key): - """ - Return the sub-container at the following key if it exists, otherwise None. + """Return the sub-container at the following key if it exists, + otherwise None. Parameters ---------- @@ -3405,8 +3345,7 @@ def cont_if_exists(self, key): return def cont_try_kc(self, key): - """ - Try the following key or key chain, returning self if not present. + """Try the following key or key chain, returning self if not present. Parameters ---------- @@ -3418,8 +3357,7 @@ def cont_try_kc(self, key): return self def cont_cutoff_at_depth(self, depth_cutoff, inplace=False): - """ - Summary. + """Summary. Parameters ---------- @@ -3444,8 +3382,7 @@ def _maybe_cutoff(cont, kc): return ret def cont_cutoff_at_height(self, height_cutoff, inplace=False): - """ - Summary. + """Summary. Parameters ---------- @@ -3484,8 +3421,7 @@ def _cont_slice_keys(self, key_slice): return ret.cont_at_key_chains(desired_keys) def cont_slice_keys(self, key_slice, all_depths=False): - """ - Summary. + """Summary. Parameters ---------- @@ -3516,8 +3452,7 @@ def _fn(cont, kc): return self._cont_slice_keys(key_slice) def cont_with_print_limit(self, print_limit, inplace=False): - """ - Summary. + """Summary. Parameters ---------- @@ -3538,8 +3473,7 @@ def _update_print_limit(cont, _): # noinspection PyTypeChecker def cont_remove_print_limit(self, inplace=False): - """ - Summary. + """Summary. Parameters ---------- @@ -3549,8 +3483,7 @@ def cont_remove_print_limit(self, inplace=False): return self.cont_with_print_limit(None, inplace) def cont_with_key_length_limit(self, key_length_limit, inplace=False): - """ - Summary. + """Summary. Parameters ---------- @@ -3570,8 +3503,7 @@ def _update_key_length_limit(cont, _): return ret def cont_remove_key_length_limit(self, inplace=False): - """ - Summary. + """Summary. Parameters ---------- @@ -3581,8 +3513,7 @@ def cont_remove_key_length_limit(self, inplace=False): return self.cont_with_key_length_limit(None, inplace) def cont_with_print_indent(self, print_indent, inplace=False): - """ - Summary. + """Summary. Parameters ---------- @@ -3602,8 +3533,7 @@ def _update_print_indent(cont, _): return ret def cont_with_print_line_spacing(self, print_line_spacing, inplace=False): - """ - Summary. + """Summary. Parameters ---------- @@ -3623,8 +3553,7 @@ def _update_print_line_spacing(cont, _): return ret def cont_with_default_key_color(self, default_key_color, inplace=False): - """ - Summary. + """Summary. Parameters ---------- @@ -3644,8 +3573,7 @@ def _update_default_key_color(cont, _): return ret def cont_with_ivy_backend(self, ivy_backend: str, inplace=False): - """ - Summary. + """Summary. Parameters ---------- @@ -3668,8 +3596,7 @@ def cont_show(self): # noinspection PyUnresolvedReferences def cont_show_sub_container(self, sub_cont_or_keychain): - """ - Summary. + """Summary. Parameters ---------- @@ -3803,7 +3730,7 @@ def _pre_pad_alpha_line(str_in): s[0].isnumeric() or s[0] == "-" or s[0:3] == "..." - or max([ss in s[0:6] for ss in ["nan, ", "inf, "]]) + or max(ss in s[0:6] for ss in ["nan, ", "inf, "]) ) else ( indent_str + indented_key_str + s @@ -3997,7 +3924,7 @@ def _add_newline(str_in): return new_dict def __dir__(self): - return list(super.__dir__(self)) + list(self.keys()) + return list(super().__dir__()) + list(self.keys()) # noinspection PyProtectedMember def __getattr__(self, item, *args, **kwargs): @@ -4024,7 +3951,7 @@ def __setattr__(self, name, value): if name[0] != "_": self[name] = value else: - super.__setattr__(self, name, value) + super().__setattr__(name, value) def _get_queue_item(self, query): if isinstance(query, int): @@ -4070,8 +3997,7 @@ def _get_queue_item(self, query): return combined_cont[shifted_query] def __getitem__(self, query): - """ - Get slice, key or key chain of container object. + """Get slice, key or key chain of container object. Parameters ---------- @@ -4099,7 +4025,7 @@ def __getitem__(self, query): return_dict[key] = value[query] else: # noinspection PyBroadException - if isinstance(value, list) or isinstance(value, tuple): + if isinstance(value, (list, tuple)): if len(value) == 0: return_dict[key] = value else: @@ -4112,8 +4038,7 @@ def __getitem__(self, query): return ret def __setitem__(self, query, val): - """ - Set key or key chain of container object. + """Set key or key chain of container object. Parameters ---------- @@ -4222,8 +4147,7 @@ def _cont_ivy(self, local_ivy): @property def cont_shape(self): - """ - The shape of the arrays in the container. + """The shape of the arrays in the container. None is placed in indices which are not consistent across arrays. @@ -4232,8 +4156,7 @@ def cont_shape(self): @property def cont_dtype(self): - """ - The dtype of the arrays in the container. + """The dtype of the arrays in the container. None is returned if the dtypes are not consistent. """ @@ -4241,8 +4164,7 @@ def cont_dtype(self): @property def cont_shapes(self): - """ - The shapes of each array in the container. + """The shapes of each array in the container. None is placed in leaf entries without a shape attribute. """ @@ -4250,8 +4172,7 @@ def cont_shapes(self): @property def cont_dev(self): - """ - The device to which the arrays in the container belong. + """The device to which the arrays in the container belong. None returned if the devices are not consistent. """ @@ -4259,8 +4180,7 @@ def cont_dev(self): @property def cont_dev_str(self): - """ - The device to which the arrays in the container belong. + """The device to which the arrays in the container belong. None returned if the devices are not consistent. """ @@ -4279,7 +4199,7 @@ def cont_max_depth(self): kcs = [kc for kc in self.cont_to_iterator_keys(include_empty=True)] if not kcs: return 0 - return max([len(kc.split("/")) for kc in kcs]) + return max(len(kc.split("/")) for kc in kcs) @property def dynamic_backend(self): diff --git a/ivy/data_classes/container/container.py b/ivy/data_classes/container/container.py index 2c16ee729687a..2c430ec1d3426 100644 --- a/ivy/data_classes/container/container.py +++ b/ivy/data_classes/container/container.py @@ -141,9 +141,9 @@ def __neg__(self): return self.cont_map(lambda x, kc: -x, map_sequences=True) def __pow__(self, power): - """ - ivy.Container special method for the power operator, calling - :code:`operator.pow` for each of the corresponding leaves of the two containers. + """ivy.Container special method for the power operator, calling + :code:`operator.pow` for each of the corresponding leaves of the two + containers. Parameters ---------- @@ -196,9 +196,9 @@ def __ipow__(self, power): return self.cont_map(lambda x, _: operator.ipow(x, power), map_sequences=True) def __add__(self, other): - """ - ivy.Container special method for the add operator, calling :code:`operator.add` - for each of the corresponding leaves of the two containers. + """ivy.Container special method for the add operator, calling + :code:`operator.add` for each of the corresponding leaves of the two + containers. Parameters ---------- @@ -261,9 +261,9 @@ def __add__(self, other): ) def __radd__(self, other): - """ - ivy.Container reverse special method for the add operator, calling - :code:`operator.add` for each of the corresponding leaves of the two containers. + """ivy.Container reverse special method for the add operator, calling + :code:`operator.add` for each of the corresponding leaves of the two + containers. Parameters ---------- @@ -300,9 +300,9 @@ def __iadd__(self, other): ) def __sub__(self, other): - """ - ivy.Container special method for the subtract operator, calling - :code:`operator.sub` for each of the corresponding leaves of the two containers. + """ivy.Container special method for the subtract operator, calling + :code:`operator.sub` for each of the corresponding leaves of the two + containers. Parameters ---------- @@ -370,9 +370,9 @@ def __isub__(self, other): ) def __rsub__(self, other): - """ - ivy.Container reverse special method for the subtract operator, calling - :code:`operator.sub` for each of the corresponding leaves of the two containers. + """ivy.Container reverse special method for the subtract operator, + calling :code:`operator.sub` for each of the corresponding leaves of + the two containers. Parameters ---------- @@ -435,27 +435,22 @@ def __imod__(self, other): def __divmod__(self, other): return ivy.Container.cont_multi_map( - lambda xs, _: tuple( - [operator.truediv(xs[0], xs[1]), operator.mod(xs[0], xs[1])] - ), + lambda xs, _: (operator.truediv(xs[0], xs[1]), operator.mod(xs[0], xs[1])), [self, other], map_nests=True, ) def __rdivmod__(self, other): return ivy.Container.cont_multi_map( - lambda xs, _: tuple( - [operator.truediv(xs[0], xs[1]), operator.mod(xs[0], xs[1])] - ), + lambda xs, _: (operator.truediv(xs[0], xs[1]), operator.mod(xs[0], xs[1])), [other, self], map_nests=True, ) def __truediv__(self, other): - """ - ivy.Container special method for the divide operator, calling - :code:`operator.truediv` for each of the corresponding leaves of the two - containers. + """ivy.Container special method for the divide operator, calling + :code:`operator.truediv` for each of the corresponding leaves of the + two containers. Parameters ---------- @@ -568,9 +563,9 @@ def __imatmul__(self, other): ) def __abs__(self): - """ - ivy.Container special method for the abs operator, calling :code:`operator.abs` - for each of the corresponding leaves of the two containers. + """ivy.Container special method for the abs operator, calling + :code:`operator.abs` for each of the corresponding leaves of the two + containers. Parameters ---------- @@ -598,9 +593,9 @@ def __abs__(self): return self.cont_map(lambda x, kc: operator.abs(x), map_sequences=True) def __lt__(self, other): - """ - ivy.Container special method for the less operator, calling :code:`operator.lt` - for each of the corresponding leaves of the two containers. + """ivy.Container special method for the less operator, calling + :code:`operator.lt` for each of the corresponding leaves of the two + containers. Parameters ---------- @@ -636,9 +631,9 @@ def __lt__(self, other): return self.cont_map(lambda x, kc: x < other, map_sequences=True) def __le__(self, other): - """ - ivy.Container special method for the less_equal operator, calling - :code:`operator.le` for each of the corresponding leaves of the two containers. + """ivy.Container special method for the less_equal operator, calling + :code:`operator.le` for each of the corresponding leaves of the two + containers. Parameters ---------- @@ -674,9 +669,9 @@ def __le__(self, other): return self.cont_map(lambda x, kc: x <= other, map_sequences=True) def __eq__(self, other): - """ - ivy.Container special method for the equal operator, calling :code:`operator.eq` - for each of the corresponding leaves of the two containers. + """ivy.Container special method for the equal operator, calling + :code:`operator.eq` for each of the corresponding leaves of the two + containers. Parameters ---------- @@ -736,9 +731,9 @@ def __eq__(self, other): return self.cont_map(lambda x, kc: x == other, map_sequences=True) def __ne__(self, other): - """ - ivy.Container special method for the not_equal operator, calling - :code:`operator.ne` for each of the corresponding leaves of the two containers. + """ivy.Container special method for the not_equal operator, calling + :code:`operator.ne` for each of the corresponding leaves of the two + containers. Parameters ---------- @@ -798,9 +793,9 @@ def __ne__(self, other): return self.cont_map(lambda x, kc: x != other, map_sequences=True) def __gt__(self, other): - """ - ivy.Container special method for the greater operator, calling - :code:`operator.gt` for each of the corresponding leaves of the two containers. + """ivy.Container special method for the greater operator, calling + :code:`operator.gt` for each of the corresponding leaves of the two + containers. Parameters ---------- @@ -836,9 +831,9 @@ def __gt__(self, other): return self.cont_map(lambda x, kc: x > other, map_sequences=True) def __ge__(self, other): - """ - ivy.Container special method for the greater_equal operator, calling - :code:`operator.ge` for each of the corresponding leaves of the two containers. + """ivy.Container special method for the greater_equal operator, calling + :code:`operator.ge` for each of the corresponding leaves of the two + containers. Parameters ---------- @@ -909,9 +904,9 @@ def __invert__(self): return self.cont_map(lambda x, kc: operator.not_(x), map_sequences=True) def __xor__(self, other): - """ - ivy.Container special method for the ge operator, calling :code:`operator.ge` - for each of the corresponding leaves of the two containers. + """ivy.Container special method for the ge operator, calling + :code:`operator.ge` for each of the corresponding leaves of the two + containers. Parameters ---------- @@ -984,8 +979,7 @@ def __ilshift__(self, other): ) def __rshift__(self, other): - """ - ivy.Container special method for the right shift operator, calling + """ivy.Container special method for the right shift operator, calling :code:`operator.rshift` for each of the corresponding leaves of the two containers. @@ -1053,10 +1047,9 @@ def __rshift__(self, other): ) def __rrshift__(self, other): - """ - ivy.Container reverse special method for the right shift operator, calling - :code:`operator.rshift` for each of the corresponding leaves of the two - containers. + """ivy.Container reverse special method for the right shift operator, + calling :code:`operator.rshift` for each of the corresponding leaves of + the two containers. Parameters ---------- diff --git a/ivy/data_classes/container/conversions.py b/ivy/data_classes/container/conversions.py index 00cdf6cdcfef8..f57bc6b58b2c8 100644 --- a/ivy/data_classes/container/conversions.py +++ b/ivy/data_classes/container/conversions.py @@ -1,5 +1,4 @@ -""" -Ivy wrapping functions for conversions. +"""Ivy wrapping functions for conversions. Collection of Ivy functions for wrapping functions to accept and return ivy.Array instances. @@ -26,8 +25,7 @@ def _static_to_native( *, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.to_native. + """ivy.Container static method variant of ivy.to_native. This method simply wraps the function, and so the docstring for ivy.to_native also applies to this method with minimal changes. @@ -86,8 +84,7 @@ def to_native( *, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.to_native. + """ivy.Container instance method variant of ivy.to_native. This method simply wraps the function, and so the docstring for ivy.to_native also applies to this method with minimal changes. @@ -146,8 +143,7 @@ def _static_to_ivy( *, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.to_ivy. + """ivy.Container static method variant of ivy.to_ivy. This method simply wraps the function, and so the docstring for ivy.to_ivy also applies to this method with minimal changes. @@ -207,8 +203,7 @@ def to_ivy( *, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.to_ivy. + """ivy.Container instance method variant of ivy.to_ivy. This method simply wraps the function, and so the docstring for ivy.to_ivy also applies to this method with minimal changes. diff --git a/ivy/data_classes/container/creation.py b/ivy/data_classes/container/creation.py index ea238eb55c733..f66a19fc9d2b0 100644 --- a/ivy/data_classes/container/creation.py +++ b/ivy/data_classes/container/creation.py @@ -59,10 +59,9 @@ def _static_asarray( device: Optional[Union[ivy.Device, ivy.NativeDevice, ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.asarray. This method simply wraps the - function, and so the docstring for ivy.asarray also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.asarray. This method + simply wraps the function, and so the docstring for ivy.asarray also + applies to this method with minimal changes. Parameters ---------- @@ -257,10 +256,9 @@ def _static_full_like( device: Optional[Union[ivy.Device, ivy.NativeDevice, ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.full_like. This method simply wraps - the function, and so the docstring for ivy.full_like also applies to this method - with minimal changes. + """ivy.Container static method variant of ivy.full_like. This method + simply wraps the function, and so the docstring for ivy.full_like also + applies to this method with minimal changes. Parameters ---------- @@ -343,10 +341,9 @@ def full_like( dtype: Optional[Union[ivy.Dtype, ivy.NativeDtype, ivy.Container]] = None, device: Optional[Union[ivy.Device, ivy.NativeDevice, ivy.Container]] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.full_like. This method simply wraps - the function, and so the docstring for ivy.full_like also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.full_like. This method + simply wraps the function, and so the docstring for ivy.full_like also + applies to this method with minimal changes. Parameters ---------- @@ -428,10 +425,9 @@ def _static_ones_like( device: Optional[Union[ivy.Device, ivy.NativeDevice, ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.ones_like. This method simply wraps - the function, and so the docstring for ivy.ones_like also applies to this method - with minimal changes. + """ivy.Container static method variant of ivy.ones_like. This method + simply wraps the function, and so the docstring for ivy.ones_like also + applies to this method with minimal changes. Parameters ---------- @@ -487,10 +483,9 @@ def ones_like( device: Optional[Union[ivy.Device, ivy.NativeDevice, ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.ones_like. This method simply wraps - the function, and so the docstring for ivy.ones_like also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.ones_like. This method + simply wraps the function, and so the docstring for ivy.ones_like also + applies to this method with minimal changes. Parameters ---------- @@ -546,10 +541,9 @@ def _static_zeros_like( device: Optional[Union[ivy.Device, ivy.NativeDevice, ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.zeros_like. This method simply wraps - the function, and so the docstring for ivy.zeros_like also applies to this - method with minimal changes. + """ivy.Container static method variant of ivy.zeros_like. This method + simply wraps the function, and so the docstring for ivy.zeros_like also + applies to this method with minimal changes. Parameters ---------- @@ -605,10 +599,9 @@ def zeros_like( device: Optional[Union[ivy.Device, ivy.NativeDevice, ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.zeros_like. This method simply - wraps the function, and so the docstring for ivy.zeros_like also applies to this - method with minimal changes. + """ivy.Container instance method variant of ivy.zeros_like. This method + simply wraps the function, and so the docstring for ivy.zeros_like also + applies to this method with minimal changes. Parameters ---------- @@ -1081,10 +1074,9 @@ def _static_logspace( device: Optional[Union[ivy.Device, ivy.NativeDevice, ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.logspace. This method simply wraps - the function, and so the docstring for ivy.logspace also applies to this method - with minimal changes. + """ivy.Container static method variant of ivy.logspace. This method + simply wraps the function, and so the docstring for ivy.logspace also + applies to this method with minimal changes. Parameters ---------- @@ -1164,10 +1156,9 @@ def logspace( device: Optional[Union[ivy.Device, ivy.NativeDevice, ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.logspace. This method simply wraps - the function, and so the docstring for ivy.logspace also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.logspace. This method + simply wraps the function, and so the docstring for ivy.logspace also + applies to this method with minimal changes. Parameters ---------- @@ -1266,10 +1257,9 @@ def _static_one_hot( device: Optional[Union[ivy.Device, ivy.NativeDevice, ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.one_hot. This method simply wraps the - function, and so the docstring for ivy.one_hot also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.one_hot. This method + simply wraps the function, and so the docstring for ivy.one_hot also + applies to this method with minimal changes. Parameters ---------- @@ -1366,10 +1356,9 @@ def one_hot( device: Optional[Union[ivy.Device, ivy.NativeDevice, ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.one_hot. This method simply wraps - the function, and so the docstring for ivy.one_hot also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.one_hot. This method + simply wraps the function, and so the docstring for ivy.one_hot also + applies to this method with minimal changes. Parameters ---------- @@ -1463,10 +1452,9 @@ def static_frombuffer( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - r""" - ivy.Container static method variant of ivy.frombuffer. This method simply wraps - the function, and so the docstring for ivy.frombuffer also applies to this - method with minimal changes. + r"""ivy.Container static method variant of ivy.frombuffer. This method + simply wraps the function, and so the docstring for ivy.frombuffer also + applies to this method with minimal changes. Parameters ---------- @@ -1543,10 +1531,9 @@ def frombuffer( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - r""" - ivy.Container instance method variant of ivy.frombuffer. This method simply - wraps the function, and so the docstring for ivy.frombuffer also applies to this - method with minimal changes. + r"""ivy.Container instance method variant of ivy.frombuffer. This method + simply wraps the function, and so the docstring for ivy.frombuffer also + applies to this method with minimal changes. Parameters ---------- @@ -1654,7 +1641,6 @@ def triu_indices( out: Optional[Union[Tuple[ivy.Array], ivy.Container]] = None, ) -> ivy.Container: return self.static_triu_indices( - self, n_rows, n_cols, k, diff --git a/ivy/data_classes/container/data_type.py b/ivy/data_classes/container/data_type.py index b5a911d5e4407..7e45fe10c6b7d 100644 --- a/ivy/data_classes/container/data_type.py +++ b/ivy/data_classes/container/data_type.py @@ -22,9 +22,8 @@ def _static_astype( copy: Union[bool, ivy.Container] = True, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - Copy an array to a specified data type irrespective of :ref:`type- promotion` - rules. + """Copy an array to a specified data type irrespective of :ref:`type- + promotion` rules. .. note:: Casting floating-point ``NaN`` and ``infinity`` values to integral data types @@ -93,9 +92,8 @@ def astype( copy: Union[bool, ivy.Container] = True, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - Copy an array to a specified data type irrespective of :ref:`type- promotion` - rules. + """Copy an array to a specified data type irrespective of :ref:`type- + promotion` rules. .. note:: Casting floating-point ``NaN`` and ``infinity`` values to integral data types @@ -156,16 +154,16 @@ def astype( @staticmethod def _static_broadcast_arrays( - *arrays: Union[ivy.Container, ivy.Array, ivy.NativeArray, ivy.Container], + *arrays: Union[ivy.Container, ivy.Array, ivy.NativeArray], key_chains: Optional[Union[List[str], Dict[str, str], ivy.Container]] = None, to_apply: Union[bool, ivy.Container] = True, prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - `ivy.Container` static method variant of `ivy.broadcast_arrays`. This method - simply wraps the function, and so the docstring for `ivy.broadcast_arrays` also - applies to this method with minimal changes. + """`ivy.Container` static method variant of `ivy.broadcast_arrays`. + This method simply wraps the function, and so the docstring for + `ivy.broadcast_arrays` also applies to this method with minimal + changes. Parameters ---------- @@ -232,16 +230,16 @@ def _static_broadcast_arrays( def broadcast_arrays( self: ivy.Container, - *arrays: Union[ivy.Container, ivy.Array, ivy.NativeArray, ivy.Container], + *arrays: Union[ivy.Container, ivy.Array, ivy.NativeArray], key_chains: Optional[Union[List[str], Dict[str, str], ivy.Container]] = None, to_apply: Union[bool, ivy.Container] = True, prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - `ivy.Container` instance method variant of `ivy.broadcast_arrays`. This method - simply wraps the function, and so the docstring for `ivy.broadcast_arrays` also - applies to this method with minimal changes. + """`ivy.Container` instance method variant of `ivy.broadcast_arrays`. + This method simply wraps the function, and so the docstring for + `ivy.broadcast_arrays` also applies to this method with minimal + changes. Parameters ---------- @@ -315,10 +313,9 @@ def _static_broadcast_to( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - `ivy.Container` static method variant of `ivy.broadcast_to`. This method simply - wraps the function, and so the docstring for `ivy.broadcast_to` also applies to - this method with minimal changes. + """`ivy.Container` static method variant of `ivy.broadcast_to`. This + method simply wraps the function, and so the docstring for + `ivy.broadcast_to` also applies to this method with minimal changes. Parameters ---------- @@ -373,10 +370,9 @@ def broadcast_to( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - `ivy.Container` instance method variant of `ivy.broadcast_to`. This method - simply wraps the function, and so the docstring for `ivy.broadcast_to` also - applies to this method with minimal changes. + """`ivy.Container` instance method variant of `ivy.broadcast_to`. This + method simply wraps the function, and so the docstring for + `ivy.broadcast_to` also applies to this method with minimal changes. Parameters ---------- @@ -428,10 +424,9 @@ def _static_can_cast( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - `ivy.Container` static method variant of `ivy.can_cast`. This method simply - wraps the function, and so the docstring for `ivy.can_cast` also applies to this - method with minimal changes. + """`ivy.Container` static method variant of `ivy.can_cast`. This method + simply wraps the function, and so the docstring for `ivy.can_cast` also + applies to this method with minimal changes. Parameters ---------- @@ -488,10 +483,9 @@ def can_cast( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - `ivy.Container` instance method variant of `ivy.can_cast`. This method simply - wraps the function, and so the docstring for `ivy.can_cast` also applies to this - method with minimal changes. + """`ivy.Container` instance method variant of `ivy.can_cast`. This + method simply wraps the function, and so the docstring for + `ivy.can_cast` also applies to this method with minimal changes. Parameters ---------- @@ -679,8 +673,7 @@ def _static_finfo( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - `ivy.Container` static method variant of `ivy.finfo`. + """`ivy.Container` static method variant of `ivy.finfo`. Parameters ---------- @@ -725,8 +718,7 @@ def finfo( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - `ivy.Container` instance method variant of `ivy.finfo`. + """`ivy.Container` instance method variant of `ivy.finfo`. Parameters ---------- @@ -770,10 +762,9 @@ def _static_iinfo( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - `ivy.Container` static method variant of `ivy.iinfo`. This method simply wraps - the function, and so the docstring for `ivy.iinfo` also applies to this method - with minimal changes. + """`ivy.Container` static method variant of `ivy.iinfo`. This method + simply wraps the function, and so the docstring for `ivy.iinfo` also + applies to this method with minimal changes. Parameters ---------- @@ -830,10 +821,9 @@ def iinfo( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - `ivy.Container` instance method variant of `ivy.iinfo`. This method simply wraps - the function, and so the docstring for `ivy.iinfo` also applies to this method - with minimal changes. + """`ivy.Container` instance method variant of `ivy.iinfo`. This method + simply wraps the function, and so the docstring for `ivy.iinfo` also + applies to this method with minimal changes. Parameters ---------- @@ -932,10 +922,9 @@ def _static_is_float_dtype( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - `ivy.Container` static method variant of `is_float_dtype`. This method simply - wraps this function, so the docstring of `is_float_dtype` roughly applies to - this method. + """`ivy.Container` static method variant of `is_float_dtype`. This + method simply wraps this function, so the docstring of `is_float_dtype` + roughly applies to this method. Parameters ---------- @@ -1003,10 +992,9 @@ def is_float_dtype( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - `ivy.Container` instance method variant of `ivy.is_float_dtype`. This method - simply wraps the function, and so the docstring for `ivy.is_float_dtype` also - applies to this method with minimal changes. + """`ivy.Container` instance method variant of `ivy.is_float_dtype`. + This method simply wraps the function, and so the docstring for + `ivy.is_float_dtype` also applies to this method with minimal changes. Parameters ---------- @@ -1143,10 +1131,9 @@ def _static_is_complex_dtype( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - `ivy.Container` static method variant of `is_complex_dtype`. This method simply - wraps this function, so the docstring of `is_complex_dtype` roughly applies to - this method. + """`ivy.Container` static method variant of `is_complex_dtype`. This + method simply wraps this function, so the docstring of + `is_complex_dtype` roughly applies to this method. Parameters ---------- @@ -1202,10 +1189,10 @@ def is_complex_dtype( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - `ivy.Container` instance method variant of `ivy.is_complex_dtype`. This method - simply wraps the function, and so the docstring for `ivy.is_complex_dtype` also - applies to this method with minimal changes. + """`ivy.Container` instance method variant of `ivy.is_complex_dtype`. + This method simply wraps the function, and so the docstring for + `ivy.is_complex_dtype` also applies to this method with minimal + changes. Parameters ---------- @@ -1263,10 +1250,9 @@ def _static_result_type( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - `ivy.Container` static method variant of `ivy.result_type`. This method simply - wraps the function, and so the docstring for `ivy.result_type` also applies to - this method with minimal changes. + """`ivy.Container` static method variant of `ivy.result_type`. This + method simply wraps the function, and so the docstring for + `ivy.result_type` also applies to this method with minimal changes. Parameters ---------- @@ -1319,10 +1305,9 @@ def result_type( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - `ivy.Container` instance method variant of `ivy.result_type`. This method simply - wraps the function, and so the docstring for `ivy.result_type` also applies to - this method with minimal changes. + """`ivy.Container` instance method variant of `ivy.result_type`. This + method simply wraps the function, and so the docstring for + `ivy.result_type` also applies to this method with minimal changes. Parameters ---------- diff --git a/ivy/data_classes/container/device.py b/ivy/data_classes/container/device.py index 3960c59d83f1f..9012fd4f4e989 100644 --- a/ivy/data_classes/container/device.py +++ b/ivy/data_classes/container/device.py @@ -13,10 +13,9 @@ class _ContainerWithDevice(ContainerBase): def _static_dev( x: ivy.Container, /, *, as_native: Union[bool, ivy.Container] = False ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.dev. This method simply wraps the - function, and so the docstring for ivy.dev also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.dev. This method simply + wraps the function, and so the docstring for ivy.dev also applies to + this method with minimal changes. Examples -------- @@ -35,10 +34,9 @@ def _static_dev( def dev( self: ivy.Container, as_native: Union[bool, ivy.Container] = False ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.dev. This method simply wraps the - function, and so the docstring for ivy.dev also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.dev. This method simply + wraps the function, and so the docstring for ivy.dev also applies to + this method with minimal changes. Parameters ---------- @@ -74,10 +72,9 @@ def _static_to_device( stream: Optional[Union[int, Any, ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.to_device. This method simply wraps - the function, and so the docstring for ivy.to_device also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.to_device. This method + simply wraps the function, and so the docstring for ivy.to_device also + applies to this method with minimal changes. Parameters ---------- @@ -141,10 +138,9 @@ def to_device( stream: Optional[Union[int, Any, ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.to_device. This method simply wraps - the function, and so the docstring for ivy.to_device also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.to_device. This method + simply wraps the function, and so the docstring for ivy.to_device also + applies to this method with minimal changes. Parameters ---------- diff --git a/ivy/data_classes/container/elementwise.py b/ivy/data_classes/container/elementwise.py index fc417b47a0ea4..8932ae067e331 100644 --- a/ivy/data_classes/container/elementwise.py +++ b/ivy/data_classes/container/elementwise.py @@ -9,7 +9,7 @@ class _ContainerWithElementwise(ContainerBase): @staticmethod def _static_abs( - x: Union[ivy.Container, ivy.Array, ivy.NativeArray, ivy.Container], + x: Union[ivy.Container, ivy.Array, ivy.NativeArray], /, *, key_chains: Optional[Union[List[str], Dict[str, str], ivy.Container]] = None, @@ -18,10 +18,9 @@ def _static_abs( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: # noqa - """ - ivy.Container static method variant of ivy.abs. This method simply wraps the - function, and so the docstring for ivy.abs also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.abs. This method simply + wraps the function, and so the docstring for ivy.abs also applies to + this method with minimal changes. Parameters ---------- @@ -59,7 +58,6 @@ def _static_abs( b: ivy.array([4.5, 5.3, 0, 2.3]) } """ - return ContainerBase.cont_multi_map_in_function( "abs", x, @@ -79,10 +77,9 @@ def abs( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.abs. This method simply wraps the - function, and so the docstring for ivy.abs also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.abs. This method simply + wraps the function, and so the docstring for ivy.abs also applies to + this method with minimal changes. Parameters ---------- @@ -141,10 +138,9 @@ def _static_acosh( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.cosh. This method simply wraps the - function, and so the docstring for ivy.cosh also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.cosh. This method simply + wraps the function, and so the docstring for ivy.cosh also applies to + this method with minimal changes. Parameters ---------- @@ -203,10 +199,9 @@ def acosh( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.acosh. This method simply wraps the - function, and so the docstring for ivy.acosh also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.acosh. This method + simply wraps the function, and so the docstring for ivy.acosh also + applies to this method with minimal changes. Parameters ---------- @@ -266,10 +261,9 @@ def _static_acos( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.acos. This method simply wraps the - function, and so the docstring for ivy.acos also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.acos. This method simply + wraps the function, and so the docstring for ivy.acos also applies to + this method with minimal changes. Parameters ---------- @@ -330,10 +324,9 @@ def _static_add( alpha: Optional[Union[int, float, ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.add. This method simply wraps the - function, and so the docstring for ivy.add also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.add. This method simply + wraps the function, and so the docstring for ivy.add also applies to + this method with minimal changes. Parameters ---------- @@ -429,10 +422,9 @@ def acos( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.acos. This method simply wraps the - function, and so the docstring for ivy.acos also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.acos. This method + simply wraps the function, and so the docstring for ivy.acos also + applies to this method with minimal changes. Parameters ---------- @@ -491,10 +483,9 @@ def add( alpha: Optional[Union[int, float, ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.add. This method simply wraps the - function, and so the docstring for ivy.add also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.add. This method simply + wraps the function, and so the docstring for ivy.add also applies to + this method with minimal changes. Parameters ---------- @@ -570,10 +561,9 @@ def _static_asin( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.asin. This method simply wraps the - function, and so the docstring for ivy.asin also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.asin. This method simply + wraps the function, and so the docstring for ivy.asin also applies to + this method with minimal changes. Parameters ---------- @@ -641,10 +631,9 @@ def asin( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.asin. This method simply wraps the - function, and so the docstring for ivy.asin also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.asin. This method + simply wraps the function, and so the docstring for ivy.asin also + applies to this method with minimal changes. Parameters ---------- @@ -713,10 +702,9 @@ def _static_asinh( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.asinh. This method simply wraps the - function, and so the docstring for ivy.asinh also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.asinh. This method simply + wraps the function, and so the docstring for ivy.asinh also applies to + this method with minimal changes. Parameters ---------- @@ -775,10 +763,9 @@ def asinh( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.asinh. This method simply wraps the - function, and so the docstring for ivy.asinh also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.asinh. This method + simply wraps the function, and so the docstring for ivy.asinh also + applies to this method with minimal changes. Parameters ---------- @@ -838,10 +825,9 @@ def _static_atan( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.atan. This method simply wraps the - function, and so the docstring for ivy.atan also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.atan. This method simply + wraps the function, and so the docstring for ivy.atan also applies to + this method with minimal changes. Parameters ---------- @@ -898,10 +884,9 @@ def atan( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.atan. This method simply wraps the - function, and so the docstring for ivy.atan also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.atan. This method + simply wraps the function, and so the docstring for ivy.atan also + applies to this method with minimal changes. Parameters ---------- @@ -960,10 +945,9 @@ def _static_atan2( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.atan2. This method simply wraps the - function, and so the docstring for ivy.atan2 also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.atan2. This method simply + wraps the function, and so the docstring for ivy.atan2 also applies to + this method with minimal changes. Parameters ---------- @@ -1041,10 +1025,9 @@ def atan2( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.atan2. This method simply wraps the - function, and so the docstring for ivy.atan2 also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.atan2. This method + simply wraps the function, and so the docstring for ivy.atan2 also + applies to this method with minimal changes. Parameters ---------- @@ -1120,10 +1103,9 @@ def _static_atanh( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.atanh. This method simply wraps the - function, and so the docstring for ivy.atanh also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.atanh. This method simply + wraps the function, and so the docstring for ivy.atanh also applies to + this method with minimal changes. Parameters ---------- @@ -1181,10 +1163,9 @@ def atanh( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.atanh. This method simply wraps the - function, and so the docstring for ivy.atanh also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.atanh. This method + simply wraps the function, and so the docstring for ivy.atanh also + applies to this method with minimal changes. Parameters ---------- @@ -1244,10 +1225,9 @@ def _static_bitwise_and( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.bitwise_and. This method simply wraps - the function, and so the docstring for ivy.bitwise_and also applies to this - method with minimal changes. + """ivy.Container static method variant of ivy.bitwise_and. This method + simply wraps the function, and so the docstring for ivy.bitwise_and + also applies to this method with minimal changes. Parameters ---------- @@ -1329,10 +1309,9 @@ def bitwise_and( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.bitwise_and. This method simply - wraps the function, and so the docstring for ivy.bitwise_and also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.bitwise_and. This + method simply wraps the function, and so the docstring for + ivy.bitwise_and also applies to this method with minimal changes. Parameters ---------- @@ -1398,10 +1377,10 @@ def _static_bitwise_left_shift( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.bitwise_left_shift. This method - simply wraps the function, and so the docstring for ivy.bitwise_left_shift also - applies to this method with minimal changes. + """ivy.Container static method variant of ivy.bitwise_left_shift. This + method simply wraps the function, and so the docstring for + ivy.bitwise_left_shift also applies to this method with minimal + changes. Parameters ---------- @@ -1456,10 +1435,10 @@ def bitwise_left_shift( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.bitwise_left_shift. This method - simply wraps the function, and so the docstring for ivy.bitwise_left_shift also - applies to this method with minimal changes. + """ivy.Container instance method variant of ivy.bitwise_left_shift. + This method simply wraps the function, and so the docstring for + ivy.bitwise_left_shift also applies to this method with minimal + changes. Parameters ---------- @@ -1512,10 +1491,9 @@ def _static_bitwise_invert( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.bitwise_invert. This method simply - wraps the function, and so the docstring for ivy.bitwise_invert also applies to - this method with minimal changes. + """ivy.Container static method variant of ivy.bitwise_invert. This + method simply wraps the function, and so the docstring for + ivy.bitwise_invert also applies to this method with minimal changes. Parameters ---------- @@ -1579,10 +1557,9 @@ def bitwise_invert( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.bitwise_invert. This method simply - wraps the function, and so the docstring for ivy.bitwise_invert also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.bitwise_invert. This + method simply wraps the function, and so the docstring for + ivy.bitwise_invert also applies to this method with minimal changes. Parameters ---------- @@ -1649,10 +1626,9 @@ def _static_cos( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.cos. This method simply wraps the - function, and so the docstring for ivy.cos also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.cos. This method simply + wraps the function, and so the docstring for ivy.cos also applies to + this method with minimal changes. Parameters ---------- @@ -1712,10 +1688,9 @@ def cos( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.cos. This method simply wraps the - function, and so the docstring for ivy.cos also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.cos. This method simply + wraps the function, and so the docstring for ivy.cos also applies to + this method with minimal changes. Parameters ---------- @@ -1777,10 +1752,9 @@ def _static_bitwise_or( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.bitwise_or. This method simply wraps - the function, and so the docstring for ivy.bitwise_or also applies to this - method with minimal changes. + """ivy.Container static method variant of ivy.bitwise_or. This method + simply wraps the function, and so the docstring for ivy.bitwise_or also + applies to this method with minimal changes. Parameters ---------- @@ -1854,10 +1828,9 @@ def bitwise_or( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.bitwise_or. This method simply - wraps the function, and so the docstring for ivy.bitwise_or also applies to this - method with minimal changes. + """ivy.Container instance method variant of ivy.bitwise_or. This method + simply wraps the function, and so the docstring for ivy.bitwise_or also + applies to this method with minimal changes. Parameters ---------- @@ -1921,10 +1894,10 @@ def _static_bitwise_right_shift( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.bitwise_right_shift. This method - simply wraps the function, and so the docstring for ivy.bitwise_right_shift also - applies to this method with minimal changes. + """ivy.Container static method variant of ivy.bitwise_right_shift. This + method simply wraps the function, and so the docstring for + ivy.bitwise_right_shift also applies to this method with minimal + changes. Parameters ---------- @@ -2002,10 +1975,10 @@ def bitwise_right_shift( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.bitwise_right_shift. This method - simply wraps the function, and so the docstring for ivy.bitwise_right_shift also - applies to this method with minimal changes. + """ivy.Container instance method variant of ivy.bitwise_right_shift. + This method simply wraps the function, and so the docstring for + ivy.bitwise_right_shift also applies to this method with minimal + changes. Parameters ---------- @@ -2069,10 +2042,9 @@ def _static_bitwise_xor( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.bitwise_xor. This method simply wraps - the function, and so the docstring for ivy.bitwise_xor also applies to this - method with minimal changes. + """ivy.Container static method variant of ivy.bitwise_xor. This method + simply wraps the function, and so the docstring for ivy.bitwise_xor + also applies to this method with minimal changes. Parameters ---------- @@ -2138,10 +2110,9 @@ def bitwise_xor( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.bitwise_xor. This method simply - wraps the function, and so the docstring for ivy.bitwise_xor also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.bitwise_xor. This + method simply wraps the function, and so the docstring for + ivy.bitwise_xor also applies to this method with minimal changes. Parameters ---------- @@ -2206,10 +2177,9 @@ def _static_ceil( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.ceil. This method simply wraps the - function, and so the docstring for ivy.ceil also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.ceil. This method simply + wraps the function, and so the docstring for ivy.ceil also applies to + this method with minimal changes. Parameters ---------- @@ -2266,10 +2236,9 @@ def ceil( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.ceil. This method simply wraps the - function, and so the docstring for ivy.ceil also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.ceil. This method + simply wraps the function, and so the docstring for ivy.ceil also + applies to this method with minimal changes. Parameters ---------- @@ -2327,10 +2296,9 @@ def _static_cosh( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.cosh. This method simply wraps the - function, and so the docstring for ivy.cosh also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.cosh. This method simply + wraps the function, and so the docstring for ivy.cosh also applies to + this method with minimal changes. Parameters ---------- @@ -2400,10 +2368,9 @@ def cosh( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.cosh. This method simply wraps the - function, and so the docstring for ivy.cosh also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.cosh. This method + simply wraps the function, and so the docstring for ivy.cosh also + applies to this method with minimal changes. Parameters ---------- @@ -2475,10 +2442,9 @@ def _static_divide( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.divide. This method simply wraps the - function, and so the docstring for ivy.divide also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.divide. This method + simply wraps the function, and so the docstring for ivy.divide also + applies to this method with minimal changes. Parameters ---------- @@ -2545,10 +2511,9 @@ def divide( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.divide. This method simply wraps - the function, and so the docstring for ivy.divide also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.divide. This method + simply wraps the function, and so the docstring for ivy.divide also + applies to this method with minimal changes. Parameters ---------- @@ -2627,10 +2592,9 @@ def _static_equal( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.equal. This method simply wraps the - function, and so the docstring for ivy.equal also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.equal. This method simply + wraps the function, and so the docstring for ivy.equal also applies to + this method with minimal changes. Parameters ---------- @@ -2696,10 +2660,9 @@ def equal( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.equal. This method simply wraps the - function, and so the docstring for ivy.equal also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.equal. This method + simply wraps the function, and so the docstring for ivy.equal also + applies to this method with minimal changes. Parameters ---------- @@ -2777,10 +2740,9 @@ def static_nan_to_num( neginf: Optional[Union[float, int, ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.nan_to_num. This method simply wraps - the function, and so the docstring for ivy.nan_to_num also applies to this - method with minimal changes. + """ivy.Container static method variant of ivy.nan_to_num. This method + simply wraps the function, and so the docstring for ivy.nan_to_num also + applies to this method with minimal changes. Parameters ---------- @@ -2842,10 +2804,9 @@ def nan_to_num( neginf: Optional[Union[float, int, ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.nan_to_num. This method simply - wraps the function, and so the docstring for ivy.nan_to_num also applies to this - method with minimal changes. + """ivy.Container instance method variant of ivy.nan_to_num. This method + simply wraps the function, and so the docstring for ivy.nan_to_num also + applies to this method with minimal changes. Parameters ---------- @@ -2900,10 +2861,9 @@ def static_imag( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.imag. This method simply wraps the - function, and so the docstring for ivy.imag also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.imag. This method simply + wraps the function, and so the docstring for ivy.imag also applies to + this method with minimal changes. Parameters ---------- @@ -2949,10 +2909,9 @@ def imag( *, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.imag. This method simply wraps the - function, and so the docstring for ivy.imag also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.imag. This method + simply wraps the function, and so the docstring for ivy.imag also + applies to this method with minimal changes. Parameters ---------- @@ -2996,10 +2955,9 @@ def static_angle( deg: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.angle. This method simply wraps the - function, and so the docstring for ivy.angle also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.angle. This method simply + wraps the function, and so the docstring for ivy.angle also applies to + this method with minimal changes. Parameters ---------- @@ -3057,10 +3015,9 @@ def angle( deg: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.angle. This method simply wraps the - function, and so the docstring for ivy.angle also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.angle. This method + simply wraps the function, and so the docstring for ivy.angle also + applies to this method with minimal changes. Parameters ---------- @@ -3114,10 +3071,9 @@ def static_gcd( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.gcd. This method simply wraps the - function, and so the docstring for ivy.gcd also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.gcd. This method simply + wraps the function, and so the docstring for ivy.gcd also applies to + this method with minimal changes. Parameters ---------- @@ -3163,10 +3119,9 @@ def gcd( *, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.gcd. This method simply wraps the - function, and so the docstring for ivy.gcd also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.gcd. This method simply + wraps the function, and so the docstring for ivy.gcd also applies to + this method with minimal changes. Parameters ---------- @@ -3207,10 +3162,9 @@ def static_exp2( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.exp2. This method simply wraps the - function, and so the docstring for ivy.exp2 also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.exp2. This method simply + wraps the function, and so the docstring for ivy.exp2 also applies to + this method with minimal changes. Parameters ---------- @@ -3251,10 +3205,9 @@ def exp2( *, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.exp2. This method simply wraps the - function, and so the docstring for ivy.exp2 also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.exp2. This method + simply wraps the function, and so the docstring for ivy.exp2 also + applies to this method with minimal changes. Parameters ---------- @@ -3292,10 +3245,9 @@ def _static_exp( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.exp. This method simply wraps the - function, and so the docstring for ivy.exp also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.exp. This method simply + wraps the function, and so the docstring for ivy.exp also applies to + this method with minimal changes. Parameters ---------- @@ -3352,10 +3304,9 @@ def exp( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.exp. This method simply wraps the - function, and so the docstring for ivy.exp also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.exp. This method simply + wraps the function, and so the docstring for ivy.exp also applies to + this method with minimal changes. Parameters ---------- @@ -3413,10 +3364,9 @@ def _static_expm1( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.expm1. This method simply wraps - thefunction, and so the docstring for ivy.expm1 also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.expm1. This method simply + wraps thefunction, and so the docstring for ivy.expm1 also applies to + this method with minimal changes. Parameters ---------- @@ -3474,10 +3424,9 @@ def expm1( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.expm1. This method simply wraps the - function, and so the docstring for ivy.expm1 also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.expm1. This method + simply wraps the function, and so the docstring for ivy.expm1 also + applies to this method with minimal changes. Parameters ---------- @@ -3544,10 +3493,9 @@ def _static_floor( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.floor. This method simply wraps - thefunction, and so the docstring for ivy.floor also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.floor. This method simply + wraps thefunction, and so the docstring for ivy.floor also applies to + this method with minimal changes. Parameters ---------- @@ -3604,10 +3552,9 @@ def floor( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.floor. This method simply wraps the - function, and so the docstring for ivy.floor also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.floor. This method + simply wraps the function, and so the docstring for ivy.floor also + applies to this method with minimal changes. Parameters ---------- @@ -3666,10 +3613,9 @@ def _static_floor_divide( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.floor_divide. This method simply - wraps the function, and so the docstring for ivy.floor_divide also applies to - this method with minimal changes. + """ivy.Container static method variant of ivy.floor_divide. This method + simply wraps the function, and so the docstring for ivy.floor_divide + also applies to this method with minimal changes. Parameters ---------- @@ -3747,10 +3693,9 @@ def floor_divide( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.floor_divide. This method simply - wraps the function, and so the docstring for ivy.floor_divide also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.floor_divide. This + method simply wraps the function, and so the docstring for + ivy.floor_divide also applies to this method with minimal changes. Parameters ---------- @@ -3829,10 +3774,9 @@ def static_fmin( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.fmin. This method simply wraps the - function, and so the docstring for ivy.fmin also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.fmin. This method simply + wraps the function, and so the docstring for ivy.fmin also applies to + this method with minimal changes. Parameters ---------- @@ -3878,10 +3822,9 @@ def fmin( *, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.fmin. This method simply wraps the - function, and so the docstring for ivy.fmin also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.fmin. This method + simply wraps the function, and so the docstring for ivy.fmin also + applies to this method with minimal changes. Parameters ---------- @@ -3923,10 +3866,9 @@ def _static_greater( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.greater. This method simply wraps the - function, and so the docstring for ivy.greater also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.greater. This method + simply wraps the function, and so the docstring for ivy.greater also + applies to this method with minimal changes. Parameters ---------- @@ -3992,10 +3934,9 @@ def greater( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.greater. This method simply wraps - the function, and so the docstring for ivy.greater also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.greater. This method + simply wraps the function, and so the docstring for ivy.greater also + applies to this method with minimal changes. Parameters ---------- @@ -4061,10 +4002,9 @@ def _static_greater_equal( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.greater_equal. This method simply - wraps the function, and so the docstring for ivy.greater_equal also applies to - this method with minimal changes. + """ivy.Container static method variant of ivy.greater_equal. This + method simply wraps the function, and so the docstring for + ivy.greater_equal also applies to this method with minimal changes. Parameters ---------- @@ -4130,10 +4070,9 @@ def greater_equal( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.greater_equal. This method simply - wraps the function, and so the docstring for ivy.greater_equal also applies to - this metho with minimal changes. + """ivy.Container instance method variant of ivy.greater_equal. This + method simply wraps the function, and so the docstring for + ivy.greater_equal also applies to this metho with minimal changes. Parameters ---------- @@ -4198,10 +4137,9 @@ def _static_isfinite( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.isfinite. This method simply wraps - the function, and so the docstring for ivy.isfinite also applies to this method - with minimal changes. + """ivy.Container static method variant of ivy.isfinite. This method + simply wraps the function, and so the docstring for ivy.isfinite also + applies to this method with minimal changes. Parameters ---------- @@ -4259,10 +4197,9 @@ def isfinite( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.isfinite. This method simply wraps - the function, and so the docstring for ivy.isfinite also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.isfinite. This method + simply wraps the function, and so the docstring for ivy.isfinite also + applies to this method with minimal changes. Parameters ---------- @@ -4323,10 +4260,9 @@ def _static_isinf( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.isinf. This method simply wraps the - function, and so the docstring for ivy.isinf also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.isinf. This method simply + wraps the function, and so the docstring for ivy.isinf also applies to + this method with minimal changes. Parameters ---------- @@ -4394,10 +4330,9 @@ def isinf( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.isinf. This method simply wraps the - function, and so the docstring for ivy.isinf also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.isinf. This method + simply wraps the function, and so the docstring for ivy.isinf also + applies to this method with minimal changes. Parameters ---------- @@ -4464,10 +4399,9 @@ def _static_isnan( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.isnan. This method simply wraps the - function, and so the docstring for ivy.isnan also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.isnan. This method simply + wraps the function, and so the docstring for ivy.isnan also applies to + this method with minimal changes. Parameters ---------- @@ -4527,10 +4461,9 @@ def isnan( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.isnan. This method simply wraps the - function, and so the docstring for ivy.isnan also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.isnan. This method + simply wraps the function, and so the docstring for ivy.isnan also + applies to this method with minimal changes. Parameters ---------- @@ -4590,10 +4523,9 @@ def _static_less( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.less. This method simply wraps the - function, and so the docstring for ivy.less also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.less. This method simply + wraps the function, and so the docstring for ivy.less also applies to + this method with minimal changes. Parameters ---------- @@ -4659,10 +4591,9 @@ def less( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.less. This method simply wraps the - function, and so the docstring for ivy.less also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.less. This method + simply wraps the function, and so the docstring for ivy.less also + applies to this method with minimal changes. Parameters ---------- @@ -4728,10 +4659,9 @@ def _static_less_equal( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.less_equal. This method simply wraps - the function, and so the docstring for ivy.less_equal also applies to this - method with minimal changes. + """ivy.Container static method variant of ivy.less_equal. This method + simply wraps the function, and so the docstring for ivy.less_equal also + applies to this method with minimal changes. Parameters ---------- @@ -4797,10 +4727,9 @@ def less_equal( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.less_equal. This method simply - wraps the function, and so the docstring for ivy.less_equal also applies to this - method with minimal changes. + """ivy.Container instance method variant of ivy.less_equal. This method + simply wraps the function, and so the docstring for ivy.less_equal also + applies to this method with minimal changes. Parameters ---------- @@ -4876,10 +4805,9 @@ def _static_log( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.log. This method simply wraps the - function, and so the docstring for ivy.log also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.log. This method simply + wraps the function, and so the docstring for ivy.log also applies to + this method with minimal changes. Parameters ---------- @@ -4941,10 +4869,9 @@ def log( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.log. This method simply wraps the - function, and so the docstring for ivy.log also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.log. This method simply + wraps the function, and so the docstring for ivy.log also applies to + this method with minimal changes. Parameters ---------- @@ -5007,10 +4934,9 @@ def _static_log1p( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.log1p. This method simply wraps the - function, and so the docstring for ivy.log1p also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.log1p. This method simply + wraps the function, and so the docstring for ivy.log1p also applies to + this method with minimal changes. Parameters ---------- @@ -5075,10 +5001,9 @@ def log1p( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.log1p. This method simply wraps the - function, and so the docstring for ivy.log1p also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.log1p. This method + simply wraps the function, and so the docstring for ivy.log1p also + applies to this method with minimal changes. Parameters ---------- @@ -5137,10 +5062,9 @@ def _static_log2( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.log2. This method simply wraps the - function, and so the docstring for ivy.log2 also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.log2. This method simply + wraps the function, and so the docstring for ivy.log2 also applies to + this method with minimal changes. Parameters ---------- @@ -5202,10 +5126,9 @@ def log2( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.log2. This method simply wraps the - function, and so the docstring for ivy.log2 also applies to this metho with - minimal changes. + """ivy.Container instance method variant of ivy.log2. This method + simply wraps the function, and so the docstring for ivy.log2 also + applies to this metho with minimal changes. Parameters ---------- @@ -5268,10 +5191,9 @@ def _static_log10( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.log10. This method simply wraps the - function, and so the docstring for ivy.log10 also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.log10. This method simply + wraps the function, and so the docstring for ivy.log10 also applies to + this method with minimal changes. Parameters ---------- @@ -5333,10 +5255,9 @@ def log10( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.log10. This method simply wraps the - function, and so the docstring for ivy.log10 also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.log10. This method + simply wraps the function, and so the docstring for ivy.log10 also + applies to this method with minimal changes. Parameters ---------- @@ -5400,10 +5321,9 @@ def _static_logaddexp( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.greater_equal. This method simply - wraps the function, and so the docstring for ivy.greater_equal also applies to - this method with minimal changes. + """ivy.Container static method variant of ivy.greater_equal. This + method simply wraps the function, and so the docstring for + ivy.greater_equal also applies to this method with minimal changes. Parameters ---------- @@ -5472,10 +5392,9 @@ def logaddexp( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.greater_equal. This method simply - wraps the function, and so the docstring for ivy.greater_equal also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.greater_equal. This + method simply wraps the function, and so the docstring for + ivy.greater_equal also applies to this method with minimal changes. Parameters ---------- @@ -5544,10 +5463,9 @@ def static_logaddexp2( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.logaddexp2. This method simply wraps - the function, and so the docstring for ivy.logaddexp2 also applies to this - method with minimal changes. + """ivy.Container static method variant of ivy.logaddexp2. This method + simply wraps the function, and so the docstring for ivy.logaddexp2 also + applies to this method with minimal changes. Parameters ---------- @@ -5593,10 +5511,9 @@ def logaddexp2( *, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.logaddexp2. This method simply - wraps the function, and so the docstring for ivy.logaddexp2 also applies to this - method with minimal changes. + """ivy.Container instance method variant of ivy.logaddexp2. This method + simply wraps the function, and so the docstring for ivy.logaddexp2 also + applies to this method with minimal changes. Parameters ---------- @@ -5638,10 +5555,9 @@ def _static_logical_and( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.logical_and. This method simply wraps - the function, and so the docstring for ivy.logical_and also applies to this - method with minimal changes. + """ivy.Container static method variant of ivy.logical_and. This method + simply wraps the function, and so the docstring for ivy.logical_and + also applies to this method with minimal changes. Parameters ---------- @@ -5726,10 +5642,9 @@ def logical_and( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.logical_and. This method simply - wraps the function, and so the docstring for ivy.logical_and also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.logical_and. This + method simply wraps the function, and so the docstring for + ivy.logical_and also applies to this method with minimal changes. Parameters ---------- @@ -5812,10 +5727,9 @@ def _static_logical_not( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.logical_not. This method simply wraps - the function, and so the docstring for ivy.logical_not also applies to this - method with minimal changes. + """ivy.Container static method variant of ivy.logical_not. This method + simply wraps the function, and so the docstring for ivy.logical_not + also applies to this method with minimal changes. Parameters ---------- @@ -5872,10 +5786,9 @@ def logical_not( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.logical_not. This method simply - wraps the function, and so the docstring for ivy.logical_not also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.logical_not. This + method simply wraps the function, and so the docstring for + ivy.logical_not also applies to this method with minimal changes. Parameters ---------- @@ -5943,10 +5856,9 @@ def _static_logical_or( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.logical_or. This method simply wraps - the function, and so the docstring for ivy.logical_or also applies to this - method with minimal changes. + """ivy.Container static method variant of ivy.logical_or. This method + simply wraps the function, and so the docstring for ivy.logical_or also + applies to this method with minimal changes. Parameters ---------- @@ -6012,10 +5924,9 @@ def logical_or( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.logical_or. This method simply - wraps the function, and so the docstring for ivy.logical_or also applies to this - method with minimal changes. + """ivy.Container instance method variant of ivy.logical_or. This method + simply wraps the function, and so the docstring for ivy.logical_or also + applies to this method with minimal changes. Parameters ---------- @@ -6092,10 +6003,9 @@ def _static_logical_xor( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.logical_xor. This method simply wraps - the function, and so the docstring for ivy.logical_xor also applies to this - method with minimal changes. + """ivy.Container static method variant of ivy.logical_xor. This method + simply wraps the function, and so the docstring for ivy.logical_xor + also applies to this method with minimal changes. Parameters ---------- @@ -6172,10 +6082,9 @@ def logical_xor( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.logical_xor. This method simply - wraps the function, and so the docstring for ivy.logical_xor also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.logical_xor. This + method simply wraps the function, and so the docstring for + ivy.logical_xor also applies to this method with minimal changes. Parameters ---------- @@ -6239,10 +6148,9 @@ def _static_multiply( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.multiply. This method simply wraps - the function, and so the docstring for ivy.multiply also applies to this method - with minimal changes. + """ivy.Container static method variant of ivy.multiply. This method + simply wraps the function, and so the docstring for ivy.multiply also + applies to this method with minimal changes. Parameters ---------- @@ -6311,10 +6219,9 @@ def multiply( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.multiply. This method simply wraps - the function, and so the docstring for ivy.multiply also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.multiply. This method + simply wraps the function, and so the docstring for ivy.multiply also + applies to this method with minimal changes. Parameters ---------- @@ -6394,10 +6301,9 @@ def _static_negative( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.negative. This method simply wraps - the function, and so the docstring for ivy.negative also applies to this method - with minimal changes. + """ivy.Container static method variant of ivy.negative. This method + simply wraps the function, and so the docstring for ivy.negative also + applies to this method with minimal changes. Parameters ---------- @@ -6456,10 +6362,9 @@ def negative( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.negative. This method simply wraps - the function, and so the docstring for ivy.negative also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.negative. This method + simply wraps the function, and so the docstring for ivy.negative also + applies to this method with minimal changes. Parameters ---------- @@ -6520,10 +6425,9 @@ def _static_not_equal( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.not_equal. This method simply wraps - the function, and so the docstring for ivy.not_equal also applies to this method - with minimal changes. + """ivy.Container static method variant of ivy.not_equal. This method + simply wraps the function, and so the docstring for ivy.not_equal also + applies to this method with minimal changes. Parameters ---------- @@ -6589,10 +6493,9 @@ def not_equal( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.not_equal. This method simply wraps - the function, and so the docstring for ivy.not_equal also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.not_equal. This method + simply wraps the function, and so the docstring for ivy.not_equal also + applies to this method with minimal changes. Parameters ---------- @@ -6668,10 +6571,9 @@ def _static_positive( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.positive. This method simply wraps - the function, and so the docstring for ivy.positive also applies to this method - with minimal changes. + """ivy.Container static method variant of ivy.positive. This method + simply wraps the function, and so the docstring for ivy.positive also + applies to this method with minimal changes. Parameters ---------- @@ -6730,10 +6632,9 @@ def positive( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.positive. This method simply wraps - the function, and so the docstring for ivy.positive also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.positive. This method + simply wraps the function, and so the docstring for ivy.positive also + applies to this method with minimal changes. Parameters ---------- @@ -6794,10 +6695,9 @@ def _static_pow( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.pow. This method simply wraps the - function, and so the docstring for ivy.pow also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.pow. This method simply + wraps the function, and so the docstring for ivy.pow also applies to + this method with minimal changes. Parameters ---------- @@ -6862,10 +6762,9 @@ def pow( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.pow. This method simply wraps the - function, and so the docstring for ivy.pow also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.pow. This method simply + wraps the function, and so the docstring for ivy.pow also applies to + this method with minimal changes. Parameters ---------- @@ -6929,10 +6828,9 @@ def static_real( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.real. This method simply wraps the - function, and so the docstring for ivy.real also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.real. This method simply + wraps the function, and so the docstring for ivy.real also applies to + this method with minimal changes. Parameters ---------- @@ -6991,10 +6889,9 @@ def real( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.real. This method simply wraps the - function, and so the docstring for ivy.real also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.real. This method + simply wraps the function, and so the docstring for ivy.real also + applies to this method with minimal changes. Parameters ---------- @@ -7056,10 +6953,9 @@ def _static_remainder( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.remainder. This method simply wraps - the function, and so the docstring for ivy.remainder also applies to this method - with minimal changes. + """ivy.Container static method variant of ivy.remainder. This method + simply wraps the function, and so the docstring for ivy.remainder also + applies to this method with minimal changes. Parameters ---------- @@ -7152,10 +7048,9 @@ def remainder( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.remainder. This method simply wraps - the function, and so the docstring for ivy.remainder also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.remainder. This method + simply wraps the function, and so the docstring for ivy.remainder also + applies to this method with minimal changes. Parameters ---------- @@ -7247,10 +7142,9 @@ def _static_round( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.round. This method simply wraps - thevfunction, and so the docstring for ivy.round also applies to this method - with minimal changes. + """ivy.Container static method variant of ivy.round. This method simply + wraps thevfunction, and so the docstring for ivy.round also applies to + this method with minimal changes. Parameters ---------- @@ -7313,10 +7207,9 @@ def round( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.round. This method simply wraps the - function, and so the docstring for ivy.round also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.round. This method + simply wraps the function, and so the docstring for ivy.round also + applies to this method with minimal changes. Parameters ---------- @@ -7380,10 +7273,9 @@ def _static_sign( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.sign. This method simply wraps the - function, and so the docstring for ivy.sign also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.sign. This method simply + wraps the function, and so the docstring for ivy.sign also applies to + this method with minimal changes. Parameters ---------- @@ -7442,10 +7334,9 @@ def sign( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.sign. This method simply wraps the - function, and so the docstring for ivy.sign also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.sign. This method + simply wraps the function, and so the docstring for ivy.sign also + applies to this method with minimal changes. Parameters ---------- @@ -7506,10 +7397,9 @@ def _static_sin( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.sin. This method simply wraps the - function, and so the docstring for ivy.sin also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.sin. This method simply + wraps the function, and so the docstring for ivy.sin also applies to + this method with minimal changes. Parameters ---------- @@ -7568,10 +7458,9 @@ def sin( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.sin. This method simply wraps the - function, and so the docstring for ivy.sin also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.sin. This method simply + wraps the function, and so the docstring for ivy.sin also applies to + this method with minimal changes. Parameters ---------- @@ -7631,10 +7520,9 @@ def _static_sinh( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.sinh. This method simply wraps the - function, and so the docstring for ivy.sinh also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.sinh. This method simply + wraps the function, and so the docstring for ivy.sinh also applies to + this method with minimal changes. Parameters ---------- @@ -7702,10 +7590,9 @@ def sinh( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.sinh. This method simply wraps the - function, and so the docstring for ivy.sinh also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.sinh. This method + simply wraps the function, and so the docstring for ivy.sinh also + applies to this method with minimal changes. Parameters ---------- @@ -7774,10 +7661,9 @@ def _static_square( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.square. This method simply wraps the - function, and so the docstring for ivy.square also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.square. This method + simply wraps the function, and so the docstring for ivy.square also + applies to this method with minimal changes. Parameters ---------- @@ -7834,10 +7720,9 @@ def square( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.square. This method simply wraps - the function, and so the docstring for ivy.square also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.square. This method + simply wraps the function, and so the docstring for ivy.square also + applies to this method with minimal changes. Parameters ---------- @@ -7895,10 +7780,9 @@ def _static_sqrt( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.sqrt. This method simply wraps the - function, and so the docstring for ivy.sqrt also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.sqrt. This method simply + wraps the function, and so the docstring for ivy.sqrt also applies to + this method with minimal changes. Parameters ---------- @@ -7958,10 +7842,9 @@ def sqrt( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.sqrt. This method simply wraps the - function, and so the docstring for ivy.sqrt also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.sqrt. This method + simply wraps the function, and so the docstring for ivy.sqrt also + applies to this method with minimal changes. Parameters ---------- @@ -8024,10 +7907,9 @@ def _static_subtract( alpha: Optional[Union[int, float, ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.subtract. This method simply wraps - the function, and so the docstring for ivy.subtract also applies to this method - with minimal changes. + """ivy.Container static method variant of ivy.subtract. This method + simply wraps the function, and so the docstring for ivy.subtract also + applies to this method with minimal changes. Parameters ---------- @@ -8104,10 +7986,9 @@ def subtract( alpha: Optional[Union[int, float, ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.subtract. This method simply wraps - the function, and so the docstring for ivy.subtract also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.subtract. This method + simply wraps the function, and so the docstring for ivy.subtract also + applies to this method with minimal changes. Parameters ---------- @@ -8182,10 +8063,9 @@ def _static_tan( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.tan. This method simply wraps the - function, and so the docstring for ivy.tan also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.tan. This method simply + wraps the function, and so the docstring for ivy.tan also applies to + this method with minimal changes. Parameters ---------- @@ -8243,10 +8123,9 @@ def tan( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.tan. This method simply wraps the - function, and so the docstring for ivy.tan also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.tan. This method simply + wraps the function, and so the docstring for ivy.tan also applies to + this method with minimal changes. Parameters ---------- @@ -8306,10 +8185,9 @@ def _static_tanh( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.tanh. This method simply wraps the - function, and so the docstring for ivy.tanh also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.tanh. This method simply + wraps the function, and so the docstring for ivy.tanh also applies to + this method with minimal changes. Parameters ---------- @@ -8372,10 +8250,9 @@ def tanh( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.tanh. This method simply wraps the - function, and so the docstring for ivy.tanh also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.tanh. This method + simply wraps the function, and so the docstring for ivy.tanh also + applies to this method with minimal changes. Parameters ---------- @@ -8439,10 +8316,9 @@ def _static_trunc( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.trunc. This method simply wraps the - function, and so the docstring for ivy.trunc also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.trunc. This method simply + wraps the function, and so the docstring for ivy.trunc also applies to + this method with minimal changes. Parameters ---------- @@ -8501,10 +8377,9 @@ def trunc( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.trunc. This method simply wraps the - function, and so the docstring for ivy.trunc also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.trunc. This method + simply wraps the function, and so the docstring for ivy.trunc also + applies to this method with minimal changes. Parameters ---------- @@ -8562,10 +8437,9 @@ def _static_erf( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.erf. This method simply wraps the - function, and so the docstring for ivy.erf also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.erf. This method simply + wraps the function, and so the docstring for ivy.erf also applies to + this method with minimal changes. Parameters ---------- @@ -8621,10 +8495,9 @@ def erf( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.erf. This method simply wraps - thefunction, and so the docstring for ivy.erf also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.erf. This method simply + wraps thefunction, and so the docstring for ivy.erf also applies to + this method with minimal changes. Parameters ---------- @@ -8683,10 +8556,9 @@ def _static_minimum( use_where: Union[bool, ivy.Container] = True, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.minimum. This method simply wraps the - function, and so the docstring for ivy.minimum also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.minimum. This method + simply wraps the function, and so the docstring for ivy.minimum also + applies to this method with minimal changes. Parameters ---------- @@ -8756,10 +8628,9 @@ def minimum( use_where: Union[bool, ivy.Container] = True, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.minimum. This method simply wraps - the function, and so the docstring for ivy.minimum also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.minimum. This method + simply wraps the function, and so the docstring for ivy.minimum also + applies to this method with minimal changes. Parameters ---------- @@ -8829,10 +8700,9 @@ def _static_maximum( use_where: Union[bool, ivy.Container] = True, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.maximum. This method simply wraps the - function, and so the docstring for ivy.maximum also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.maximum. This method + simply wraps the function, and so the docstring for ivy.maximum also + applies to this method with minimal changes. Parameters ---------- @@ -8907,10 +8777,9 @@ def maximum( use_where: Union[bool, ivy.Container] = True, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.maximum. This method simply wraps - the function, and so the docstring for ivy.maximum also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.maximum. This method + simply wraps the function, and so the docstring for ivy.maximum also + applies to this method with minimal changes. Parameters ---------- @@ -8983,10 +8852,9 @@ def _static_reciprocal( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.reciprocal. This method simply wraps - the function, and so the docstring for ivy.reciprocal also applies to this - method with minimal changes. + """ivy.Container static method variant of ivy.reciprocal. This method + simply wraps the function, and so the docstring for ivy.reciprocal also + applies to this method with minimal changes. Parameters ---------- @@ -9041,10 +8909,9 @@ def reciprocal( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.reciprocal. This method simply - wraps the function, and so the docstring for ivy.reciprocal also applies to this - method with minimal changes. + """ivy.Container instance method variant of ivy.reciprocal. This method + simply wraps the function, and so the docstring for ivy.reciprocal also + applies to this method with minimal changes. Parameters ---------- @@ -9100,10 +8967,9 @@ def _static_deg2rad( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.deg2rad. This method simply wraps the - function, and so the docstring for ivy.deg2rad also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.deg2rad. This method + simply wraps the function, and so the docstring for ivy.deg2rad also + applies to this method with minimal changes. Parameters ---------- @@ -9159,10 +9025,9 @@ def deg2rad( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.deg2rad. This method simply wraps - the function, and so the docstring for ivy.deg2rad also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.deg2rad. This method + simply wraps the function, and so the docstring for ivy.deg2rad also + applies to this method with minimal changes. Parameters ---------- @@ -9221,10 +9086,9 @@ def _static_rad2deg( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.rad2deg. This method simply wraps the - function, and so the docstring for ivy.rad2deg also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.rad2deg. This method + simply wraps the function, and so the docstring for ivy.rad2deg also + applies to this method with minimal changes. Parameters ---------- @@ -9280,10 +9144,9 @@ def rad2deg( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.rad2deg. This method simply wraps - the function, and so the docstring for ivy.rad2deg also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.rad2deg. This method + simply wraps the function, and so the docstring for ivy.rad2deg also + applies to this method with minimal changes. Parameters ---------- @@ -9343,10 +9206,9 @@ def _static_trunc_divide( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.trunc_divide. This method simply - wraps the function, and so the docstring for ivy.trunc_divide also applies to - this method with minimal changes. + """ivy.Container static method variant of ivy.trunc_divide. This method + simply wraps the function, and so the docstring for ivy.trunc_divide + also applies to this method with minimal changes. Parameters ---------- @@ -9413,10 +9275,9 @@ def trunc_divide( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.trunc_divide. This method simply - wraps the function, and so the docstring for ivy.trunc_divide also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.trunc_divide. This + method simply wraps the function, and so the docstring for + ivy.trunc_divide also applies to this method with minimal changes. Parameters ---------- @@ -9483,10 +9344,9 @@ def _static_isreal( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.isreal. This method simply wraps the - function, and so the docstring for ivy.isreal also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.isreal. This method + simply wraps the function, and so the docstring for ivy.isreal also + applies to this method with minimal changes. Parameters ---------- @@ -9544,10 +9404,9 @@ def isreal( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.isreal. This method simply wraps - the function, and so the docstring for ivy.isreal also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.isreal. This method + simply wraps the function, and so the docstring for ivy.isreal also + applies to this method with minimal changes. Parameters ---------- @@ -9609,10 +9468,9 @@ def _static_trapz( axis: Union[int, ivy.Container] = -1, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.trapz. This method simply wraps the - function, and so the docstring for ivy.trapz also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.trapz. This method simply + wraps the function, and so the docstring for ivy.trapz also applies to + this method with minimal changes. Parameters ---------- @@ -9667,10 +9525,9 @@ def trapz( axis: Union[int, ivy.Container] = -1, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.trapz. This method simply wraps the - function, and so the docstring for ivy.trapz also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.trapz. This method + simply wraps the function, and so the docstring for ivy.trapz also + applies to this method with minimal changes. Parameters ---------- @@ -9717,10 +9574,9 @@ def _static_lcm( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.lcm. This method simply wraps the - function, and so the docstring for ivy.lcm also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.lcm. This method simply + wraps the function, and so the docstring for ivy.lcm also applies to + this method with minimal changes. Parameters ---------- @@ -9770,10 +9626,9 @@ def lcm( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.lcm. This method simply wraps the - function, and so the docstring for ivy.lcm also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.lcm. This method simply + wraps the function, and so the docstring for ivy.lcm also applies to + this method with minimal changes. Parameters ---------- diff --git a/ivy/data_classes/container/experimental/activations.py b/ivy/data_classes/container/experimental/activations.py index c6a7cb689379e..02f174d8d9a49 100644 --- a/ivy/data_classes/container/experimental/activations.py +++ b/ivy/data_classes/container/experimental/activations.py @@ -16,10 +16,9 @@ def static_logit( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.logit. This method simply wraps the - function, and so the docstring for ivy.logit also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.logit. This method simply + wraps the function, and so the docstring for ivy.logit also applies to + this method with minimal changes. Parameters ---------- @@ -78,10 +77,9 @@ def logit( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.logit. This method simply wraps the - function, and so the docstring for ivy.logit also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.logit. This method + simply wraps the function, and so the docstring for ivy.logit also + applies to this method with minimal changes. Parameters ---------- @@ -138,10 +136,9 @@ def static_thresholded_relu( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.thresholded_relu. This method simply - wraps the function, and so the docstring for ivy.thresholded_relu also applies - to this method with minimal changes. + """ivy.Container static method variant of ivy.thresholded_relu. This + method simply wraps the function, and so the docstring for + ivy.thresholded_relu also applies to this method with minimal changes. Parameters ---------- @@ -202,10 +199,9 @@ def thresholded_relu( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.thresholded_relu. This method - simply wraps the function, and so the docstring for ivy.thresholded_relu also - applies to this method with minimal changes. + """ivy.Container instance method variant of ivy.thresholded_relu. This + method simply wraps the function, and so the docstring for + ivy.thresholded_relu also applies to this method with minimal changes. Parameters ---------- @@ -332,10 +328,9 @@ def static_relu6( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.relu6. This method simply wraps the - function, and so the docstring for ivy.relu6 also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.relu6. This method simply + wraps the function, and so the docstring for ivy.relu6 also applies to + this method with minimal changes. Parameters ---------- @@ -398,10 +393,9 @@ def relu6( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.relu6. This method simply wraps the - function, and so the docstring for ivy.relu6 also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.relu6. This method + simply wraps the function, and so the docstring for ivy.relu6 also + applies to this method with minimal changes. Parameters ---------- @@ -463,10 +457,9 @@ def static_logsigmoid( map_sequences: Union[bool, ivy.Container] = False, complex_mode: Literal["split", "magnitude", "jax"] = "jax", ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.logsigmoid. This method simply wraps - the function, and so the docstring for ivy.logsigmoid also applies to this - method with minimal changes. + """ivy.Container static method variant of ivy.logsigmoid. This method + simply wraps the function, and so the docstring for ivy.logsigmoid also + applies to this method with minimal changes. Parameters ---------- @@ -533,8 +526,7 @@ def logsigmoid( map_sequences: Union[bool, ivy.Container] = False, complex_mode: Literal["split", "magnitude", "jax"] = "jax", ) -> ivy.Container: - """ - Apply element-wise Log-sigmoid of x i.e. log(1 / (1 + exp(-x)). + """Apply element-wise Log-sigmoid of x i.e. log(1 / (1 + exp(-x)). Parameters ---------- @@ -579,10 +571,9 @@ def static_selu( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.selu. This method simply wraps the - function, and so the docstring for ivy.selu also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.selu. This method simply + wraps the function, and so the docstring for ivy.selu also applies to + this method with minimal changes. Parameters ---------- @@ -639,10 +630,9 @@ def selu( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.selu. This method simply wraps the - function, and so the docstring for ivy.selu also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.selu. This method + simply wraps the function, and so the docstring for ivy.selu also + applies to this method with minimal changes. Parameters ---------- @@ -699,10 +689,9 @@ def _static_silu( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.silu. This method simply wraps the - function, and so the docstring for ivy.silu also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.silu. This method simply + wraps the function, and so the docstring for ivy.silu also applies to + this method with minimal changes. Parameters ---------- @@ -759,10 +748,9 @@ def silu( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.silu. This method simply wraps the - function, and so the docstring for ivy.silu also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.silu. This method + simply wraps the function, and so the docstring for ivy.silu also + applies to this method with minimal changes. Parameters ---------- @@ -820,10 +808,9 @@ def _static_elu( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.elu. This method simply wraps the - function, and so the docstring for ivy.elu also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.elu. This method simply + wraps the function, and so the docstring for ivy.elu also applies to + this method with minimal changes. Parameters ---------- @@ -883,10 +870,9 @@ def elu( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.elu. This method simply wraps the - function, and so the docstring for ivy.elu also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.elu. This method simply + wraps the function, and so the docstring for ivy.elu also applies to + this method with minimal changes. Parameters ---------- @@ -947,10 +933,9 @@ def _static_hardtanh( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.hardtanh.This method simply wrap the - function,the docstring for ivy.hardtanh also applies to this method with minimal - changes. + """ivy.Container static method variant of ivy.hardtanh.This method + simply wrap the function,the docstring for ivy.hardtanh also applies to + this method with minimal changes. Parameters ---------- @@ -983,10 +968,10 @@ def _static_hardtanh( Examples -------- >>> x = x = ivy.Container(a=ivy.array([0.39, -2.0]), b=ivy.array([2., -0.2])) - >>> y = ivy.Container.static_hardtanh(x) + >>> y = ivy.Container._static_hardtanh(x) >>> print(y) { - a: ivy.array([0.39, -1.]), + a: ivy.array([0.3899, -1.]), b: ivy.array([1., -0.2]) } """ @@ -1014,10 +999,9 @@ def hardtanh( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.hardtanh.This method simply wraps - the function, so the docstring for ivy.elu also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.hardtanh.This method + simply wraps the function, so the docstring for ivy.elu also applies to + this method with minimal changes. Parameters ---------- @@ -1049,11 +1033,11 @@ def hardtanh( Examples -------- - >>> x = x = ivy.Container(a=ivy.array([0.39, -2.0]), b=ivy.array([2., -0.2])) - >>> y = ivy.Container.static_hardtanh(x) + >>> x = ivy.Container(a=ivy.array([0.39, -2.0]), b=ivy.array([2., -0.2])) + >>> y = ivy.Container.hardtanh(x) >>> print(y) { - a: ivy.array([0.39, -1.]), + a: ivy.array([0.389999, -1.]), b: ivy.array([1., -0.2]) } """ @@ -1079,10 +1063,9 @@ def _static_tanhshrink( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.tanhshrink. This method simply wraps - the function, and so the docstring for ivy.tanhshrink also applies to this - method with minimal changes. + """ivy.Container static method variant of ivy.tanhshrink. This method + simply wraps the function, and so the docstring for ivy.tanhshrink also + applies to this method with minimal changes. Parameters ---------- @@ -1139,10 +1122,9 @@ def tanhshrink( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.tanhshrink. This method simply - wraps the function, and so the docstring for ivy.tanhshrink also applies to this - method with minimal changes. + """ivy.Container instance method variant of ivy.tanhshrink. This method + simply wraps the function, and so the docstring for ivy.tanhshrink also + applies to this method with minimal changes. Parameters ---------- @@ -1188,6 +1170,136 @@ def tanhshrink( out=out, ) + @staticmethod + def _static_threshold( + x: Union[ivy.Array, ivy.NativeArray, ivy.Container], + /, + *, + threshold: ivy.Container, + value: ivy.Container, + key_chains: Optional[Union[List[str], Dict[str, str], ivy.Container]] = None, + to_apply: Union[bool, ivy.Container] = True, + prune_unapplied: Union[bool, ivy.Container] = False, + map_sequences: Union[bool, ivy.Container] = False, + out: Optional[ivy.Container] = None, + ) -> ivy.Container: + """ivy.Container static method variant of ivy.threshold. This method + simply wraps the function, and so the docstring for ivy.threshold also + applies to this method with minimal changes. + + Parameters + ---------- + x + input container. + threshold + threshold value for thresholding operation. + value + value to replace with if thresholding condition is not met. + key_chains + The key-chains to apply or not apply the method to. + to_apply + If True, the method will be applied to key_chains, otherwise key_chains + will be skipped. + prune_unapplied + Whether to prune key_chains for which the function was not applied. + map_sequences + Whether to also map method to sequences (lists, tuples). + out + optional output container, for writing the result to. It must have a shape + that the inputs broadcast to. + + Returns + ------- + ret + a container with the threshold activation unit function + applied element-wise. + + Examples + -------- + >>> x = ivy.Container(a=ivy.array([1.0, -1.2]), b=ivy.array([0.4, -0.2])) + >>> y = x._static_threshold(threshold=0.5, value=0.0) + >>> print(y) + { + a: ivy.array([1., 0.]), + b: ivy.array([0., 0.]) + } + """ + return ContainerBase.cont_multi_map_in_function( + "threshold", + x, + threshold=threshold, + value=value, + key_chains=key_chains, + to_apply=to_apply, + prune_unapplied=prune_unapplied, + map_sequences=map_sequences, + out=out, + ) + + def threshold( + self: ivy.Container, + /, + *, + threshold: ivy.Container, + value: ivy.Container, + key_chains: Optional[Union[List[str], Dict[str, str], ivy.Container]] = None, + to_apply: Union[bool, ivy.Container] = True, + prune_unapplied: Union[bool, ivy.Container] = False, + map_sequences: Union[bool, ivy.Container] = False, + out: Optional[ivy.Container] = None, + ) -> ivy.Container: + """ivy.Container instance method variant of ivy.threshold. This method + simply wraps the function, and so the docstring for ivy.threshold also + applies to this method with minimal changes. + + Parameters + ---------- + self + input container. + threshold + threshold value for thresholding operation. + value + value to replace with if thresholding condition is not met. + key_chains + The key-chains to apply or not apply the method to. + to_apply + If True, the method will be applied to key_chains, otherwise key_chains + will be skipped. + prune_unapplied + Whether to prune key_chains for which the function was not applied. + map_sequences + Whether to also map method to sequences (lists, tuples). + out + optional output container, for writing the result to. It must have a shape + that the inputs broadcast to. + + Returns + ------- + ret + a container with the threshold activation unit function + applied element-wise. + + Examples + -------- + >>> x = ivy.Container(a=ivy.array([1.0, -1.2]), b=ivy.array([0.4, -0.2])) + >>> y = x.threshold(threshold=0.5, value=0.0) + >>> print(y) + { + a: ivy.array([1., 0.]), + b: ivy.array([0., 0.]) + } + """ + return self._static_threshold( + self, + threshold=threshold, + value=value, + key_chains=key_chains, + to_apply=to_apply, + prune_unapplied=prune_unapplied, + map_sequences=map_sequences, + out=out, + ) + @staticmethod def _static_softshrink( x: Union[ivy.Array, ivy.NativeArray, ivy.Container], @@ -1200,10 +1312,9 @@ def _static_softshrink( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.softshrink. This method simply wraps - the function, and so the docstring for ivy.softshrink also applies to this - method with minimal changes. + """ivy.Container static method variant of ivy.softshrink. This method + simply wraps the function, and so the docstring for ivy.softshrink also + applies to this method with minimal changes. Parameters ---------- @@ -1220,6 +1331,9 @@ def _static_softshrink( Whether to prune key_chains for which the function was not applied. map_sequences Whether to also map method to sequences (lists, tuples). + out + optional output container, for writing the result to. It must have a shape + that the inputs broadcast to. Returns ------- @@ -1258,8 +1372,7 @@ def softshrink( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - Apply the soft shrinkage function element-wise. + """Apply the soft shrinkage function element-wise. Parameters ---------- @@ -1319,10 +1432,9 @@ def _static_celu( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.celu. This method simply wraps the - function, and so the docstring for ivy.celu also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.celu. This method simply + wraps the function, and so the docstring for ivy.celu also applies to + this method with minimal changes. Parameters ---------- @@ -1387,10 +1499,9 @@ def celu( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.leaky_relu. This method simply - wraps the function, and so the docstring for ivy.leaky_relu also applies to this - method with minimal changes. + """ivy.Container instance method variant of ivy.leaky_relu. This method + simply wraps the function, and so the docstring for ivy.leaky_relu also + applies to this method with minimal changes. Parameters ---------- @@ -1456,10 +1567,9 @@ def _static_scaled_tanh( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.scaled_tanh. This method simply wraps - the function, and so the docstring for ivy.scaled_tanh also applies to this - method with minimal changes. + """ivy.Container static method variant of ivy.scaled_tanh. This method + simply wraps the function, and so the docstring for ivy.scaled_tanh + also applies to this method with minimal changes. Parameters ---------- @@ -1543,10 +1653,9 @@ def scaled_tanh( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.scaled_tanh. This method - simplywraps the function, and so the docstring for ivy.scaled_tanh also applies - to this method with minimal changes. + """ivy.Container instance method variant of ivy.scaled_tanh. This + method simplywraps the function, and so the docstring for + ivy.scaled_tanh also applies to this method with minimal changes. Parameters ---------- @@ -1626,10 +1735,9 @@ def _static_hardshrink( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.hardshrink. This method simply wraps - the function, and so the docstring for ivy.hardshrink also applies to this - method with minimal changes. + """ivy.Container static method variant of ivy.hardshrink. This method + simply wraps the function, and so the docstring for ivy.hardshrink also + applies to this method with minimal changes. Parameters ---------- @@ -1684,8 +1792,7 @@ def hardshrink( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - Apply the hard shrinkage function element-wise. + """Apply the hard shrinkage function element-wise. Parameters ---------- @@ -1713,8 +1820,7 @@ def hardshrink( Examples -------- - >>> import ivy.numpy as np - >>> x = ivy.Container(a=np.array([1., -2.]), b=np.array([0.4, -0.2])) + >>> x = ivy.Container(a=ivy.array([1., -2.]), b=ivy.array([0.4, -0.2])) >>> y = ivy.Container.hardshrink(x) >>> print(y) { @@ -1731,3 +1837,117 @@ def hardshrink( map_sequences=map_sequences, out=out, ) + + @staticmethod + def _static_hardsilu( + x: Union[ivy.Array, ivy.NativeArray, ivy.Container], + /, + *, + key_chains: Optional[Union[List[str], Dict[str, str], ivy.Container]] = None, + to_apply: Union[bool, ivy.Container] = True, + prune_unapplied: Union[bool, ivy.Container] = False, + map_sequences: Union[bool, ivy.Container] = False, + out: Optional[ivy.Container] = None, + ) -> ivy.Container: + """ivy.Container static method which acts as a wrapper for + ivy.hardsilu. + + Parameters + ---------- + x + input container + key_chains + The keychains to apply or not apply the method to. Default is ``None``. + to_apply + If True, the method will be applied to key_chains, otherwise key_chains + will be skipped. Default is ``True``. + prune_unapplied + Whether to prune key_chains for which the function was not applied. + Default is ``False``. + map_sequences + Whether to also map method to sequences (lists, tuples). + Default is ``False``. + out + optional output container, for writing the result to. It must have a shape + that the inputs broadcast to. + + Returns + ------- + a container containing the output of the hardsilu/hardswish function applied + to each element in ``x``. + + Examples + -------- + >>> x = ivy.Container(a=ivy.array([-0.5, -1, 0]), b=ivy.array([0.5, 1., 2])) + >>> y = ivy.Container._static_hardsilu(x) + >>> print(y) + { + a: ivy.array([-0.20833333, -0.33333334, 0.]), + b: ivy.array([0.29166666, 0.66666669, 1.66666663]) + } + """ + return ContainerBase.cont_multi_map_in_function( + "hardsilu", + x, + key_chains=key_chains, + to_apply=to_apply, + prune_unapplied=prune_unapplied, + map_sequences=map_sequences, + out=out, + ) + + def hardsilu( + self, + /, + *, + key_chains: Optional[Union[List[str], Dict[str, str], ivy.Container]] = None, + to_apply: Union[bool, ivy.Container] = True, + prune_unapplied: Union[bool, ivy.Container] = False, + map_sequences: Union[bool, ivy.Container] = False, + out: Optional[ivy.Container] = None, + ) -> ivy.Container: + """ivy.Container instance method which acts as a wrapper for + ivy.hardsilu. + + Parameters + ---------- + self + input container + key_chains + The keychains to apply or not apply the method to. Default is ``None``. + to_apply + If True, the method will be applied to key_chains, otherwise key_chains + will be skipped. Default is ``True``. + prune_unapplied + Whether to prune key_chains for which the function was not applied. + Default is ``False``. + map_sequences + Whether to also map method to sequences (lists, tuples). + Default is ``False``. + out + optional output container, for writing the result to. It must have a shape + that the inputs broadcast to. + + Returns + ------- + a container containing the output of the hardsilu/hardswish function applied + to each element in the input container. + + Examples + -------- + >>> x = ivy.Container(a=ivy.array([-0.5, -1, 0]), b=ivy.array([0.5, 1., 2])) + >>> y = x.hardsilu() + >>> print(y) + { + a: ivy.array([-0.20833333, -0.33333334, 0.]), + b: ivy.array([0.29166666, 0.66666669, 1.66666663]) + } + """ + return self._static_hardsilu( + self, + key_chains=key_chains, + to_apply=to_apply, + prune_unapplied=prune_unapplied, + map_sequences=map_sequences, + out=out, + ) diff --git a/ivy/data_classes/container/experimental/creation.py b/ivy/data_classes/container/experimental/creation.py index b708253e7adfb..e563d358474c2 100644 --- a/ivy/data_classes/container/experimental/creation.py +++ b/ivy/data_classes/container/experimental/creation.py @@ -19,10 +19,9 @@ def static_hann_window( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.hann_window. This method simply wraps - the function, and so the docstring for ivy.hann_window also applies to this - method with minimal changes. + """ivy.Container static method variant of ivy.hann_window. This method + simply wraps the function, and so the docstring for ivy.hann_window + also applies to this method with minimal changes. Parameters ---------- @@ -71,10 +70,9 @@ def hann_window( *, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.hann_window. This method simply - wraps the function, and so the docstring for ivy.hann_window also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.hann_window. This + method simply wraps the function, and so the docstring for + ivy.hann_window also applies to this method with minimal changes. Parameters ---------- @@ -119,10 +117,9 @@ def static_kaiser_window( dtype: Optional[Union[ivy.Array, ivy.NativeArray, ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.kaiser_window. This method simply - wraps the function, and so the docstring for ivy.kaiser_window also applies to - this method with minimal changes. + """ivy.Container static method variant of ivy.kaiser_window. This + method simply wraps the function, and so the docstring for + ivy.kaiser_window also applies to this method with minimal changes. Parameters ---------- @@ -177,10 +174,9 @@ def kaiser_window( dtype: Optional[Union[ivy.Array, ivy.NativeArray, ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.kaiser_window. This method simply - wraps the function, and so the docstring for ivy.kaiser_window also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.kaiser_window. This + method simply wraps the function, and so the docstring for + ivy.kaiser_window also applies to this method with minimal changes. Parameters ---------- @@ -235,11 +231,10 @@ def static_kaiser_bessel_derived_window( dtype: Optional[Union[ivy.Array, ivy.NativeArray, ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.kaiser_bessel_derived_window. This - method simply wraps the function, and so the docstring for - ivy.kaiser_bessel_derived_window also applies to this method with minimal - changes. + """ivy.Container static method variant of + ivy.kaiser_bessel_derived_window. This method simply wraps the + function, and so the docstring for ivy.kaiser_bessel_derived_window + also applies to this method with minimal changes. Parameters ---------- @@ -294,11 +289,10 @@ def kaiser_bessel_derived_window( dtype: Optional[Union[ivy.Array, ivy.NativeArray, ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.kaiser_bessel_derived_window. This - method simply wraps the function, and so the docstring for - ivy.kaiser_bessel_derived_window also applies to this method with minimal - changes. + """ivy.Container instance method variant of + ivy.kaiser_bessel_derived_window. This method simply wraps the + function, and so the docstring for ivy.kaiser_bessel_derived_window + also applies to this method with minimal changes. Parameters ---------- @@ -355,10 +349,9 @@ def static_hamming_window( dtype: Optional[Union[ivy.Array, ivy.NativeArray, ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.hamming_window. This method simply - wraps the function, and so the docstring for ivy.hamming_window also applies to - this method with minimal changes. + """ivy.Container static method variant of ivy.hamming_window. This + method simply wraps the function, and so the docstring for + ivy.hamming_window also applies to this method with minimal changes. Parameters ---------- @@ -417,10 +410,9 @@ def hamming_window( dtype: Optional[Union[ivy.Array, ivy.NativeArray, ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.hamming_window. This method simply - wraps the function, and so the docstring for ivy.hamming_window also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.hamming_window. This + method simply wraps the function, and so the docstring for + ivy.hamming_window also applies to this method with minimal changes. Parameters ---------- @@ -468,10 +460,9 @@ def static_vorbis_window( dtype: Optional[Union[ivy.Array, ivy.NativeArray, ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.vorbis_window. This method simply - wraps the function, and so the docstring for ivy.vorbis_window also applies to - this method with minimal changes. + """ivy.Container static method variant of ivy.vorbis_window. This + method simply wraps the function, and so the docstring for + ivy.vorbis_window also applies to this method with minimal changes. Parameters ---------- @@ -520,10 +511,9 @@ def vorbis_window( dtype: Optional[Union[ivy.Array, ivy.NativeArray, ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.vorbis_window. This method simply - wraps the function, and so the docstring for ivy.vorbis_window also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.vorbis_window. This + method simply wraps the function, and so the docstring for + ivy.vorbis_window also applies to this method with minimal changes. Parameters ---------- @@ -599,7 +589,6 @@ def tril_indices( device: Optional[Union[ivy.Device, ivy.NativeDevice, ivy.Container]] = None, ) -> ivy.Container: return self.static_tril_indices( - self, n_rows, n_cols, k, @@ -624,10 +613,9 @@ def static_eye_like( dtype: Optional[Union[ivy.Dtype, ivy.NativeDtype, ivy.Container]] = None, device: Optional[Union[ivy.Device, ivy.NativeDevice, ivy.Container]] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.eye_like. This method simply wraps - the function, and so the docstring for ivy.eye_like also applies to this method - with minimal changes. + """ivy.Container static method variant of ivy.eye_like. This method + simply wraps the function, and so the docstring for ivy.eye_like also + applies to this method with minimal changes. Parameters ---------- @@ -701,10 +689,9 @@ def eye_like( dtype: Optional[Union[ivy.Dtype, ivy.NativeDtype, ivy.Container]] = None, device: Optional[Union[ivy.Device, ivy.NativeDevice, ivy.Container]] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.eye_like. This method simply wraps - the function, and so the docstring for ivy.eye_like also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.eye_like. This method + simply wraps the function, and so the docstring for ivy.eye_like also + applies to this method with minimal changes. Parameters ---------- @@ -776,10 +763,10 @@ def static_unsorted_segment_min( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - r""" - ivy.Container instance method variant of ivy.unsorted_segment_min. This method - simply wraps the function, and so the docstring for ivy.unsorted_segment_min - also applies to this method with minimal changes. + r"""ivy.Container instance method variant of ivy.unsorted_segment_min. + This method simply wraps the function, and so the docstring for + ivy.unsorted_segment_min also applies to this method with minimal + changes. Note ---- @@ -831,10 +818,10 @@ def unsorted_segment_min( segment_ids: ivy.Container, num_segments: Union[int, ivy.Container], ): - r""" - ivy.Container instance method variant of ivy.unsorted_segment_min. This method - simply wraps the function, and so the docstring for ivy.unsorted_segment_min - also applies to this method with minimal changes. + r"""ivy.Container instance method variant of ivy.unsorted_segment_min. + This method simply wraps the function, and so the docstring for + ivy.unsorted_segment_min also applies to this method with minimal + changes. Note ---- @@ -876,10 +863,10 @@ def static_unsorted_segment_sum( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - r""" - ivy.Container instance method variant of ivy.unsorted_segment_sum. This method - simply wraps the function, and so the docstring for ivy.unsorted_segment_sum - also applies to this method with minimal changes. + r"""ivy.Container instance method variant of ivy.unsorted_segment_sum. + This method simply wraps the function, and so the docstring for + ivy.unsorted_segment_sum also applies to this method with minimal + changes. Parameters ---------- @@ -926,10 +913,10 @@ def unsorted_segment_sum( segment_ids: ivy.Container, num_segments: Union[int, ivy.Container], ): - r""" - ivy.Container instance method variant of ivy.unsorted_segment_sum. This method - simply wraps the function, and so the docstring for ivy.unsorted_segment_sum - also applies to this method with minimal changes. + r"""ivy.Container instance method variant of ivy.unsorted_segment_sum. + This method simply wraps the function, and so the docstring for + ivy.unsorted_segment_sum also applies to this method with minimal + changes. Parameters ---------- @@ -967,10 +954,9 @@ def static_blackman_window( map_sequences: bool = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.blackman_window. This method simply - wraps the function, and so the docstring for ivy.blackman_window also applies to - this method with minimal changes. + """ivy.Container static method variant of ivy.blackman_window. This + method simply wraps the function, and so the docstring for + ivy.blackman_window also applies to this method with minimal changes. Parameters ---------- @@ -1019,10 +1005,9 @@ def blackman_window( *, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.blackman_window. This method simply - wraps the function, and so the docstring for ivy.blackman_window also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.blackman_window. This + method simply wraps the function, and so the docstring for + ivy.blackman_window also applies to this method with minimal changes. Parameters ---------- @@ -1115,10 +1100,9 @@ def static_mel_weight_matrix( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - r""" - ivy.Container instance method variant of ivy.mel_weight_matrix. This method - simply wraps the function, and so the docstring for ivy.mel_weight_matrix also - applies to this method with minimal changes. + r"""ivy.Container instance method variant of ivy.mel_weight_matrix. This + method simply wraps the function, and so the docstring for + ivy.mel_weight_matrix also applies to this method with minimal changes. Parameters ---------- @@ -1170,10 +1154,9 @@ def mel_weight_matrix( lower_edge_hertz: Optional[float] = 0.0, upper_edge_hertz: Optional[float] = 3000.0, ): - r""" - ivy.Container instance method variant of ivy.mel_weight_matrix. This method - simply wraps the function, and so the docstring for ivy.mel_weight_matrix also - applies to this method with minimal changes. + r"""ivy.Container instance method variant of ivy.mel_weight_matrix. This + method simply wraps the function, and so the docstring for + ivy.mel_weight_matrix also applies to this method with minimal changes. Parameters ---------- @@ -1201,6 +1184,113 @@ def mel_weight_matrix( upper_edge_hertz, ) + @staticmethod + def static_unsorted_segment_mean( + data: ivy.Container, + segment_ids: Union[ivy.Array, ivy.Container], + num_segments: Union[int, ivy.Container], + *, + key_chains: Optional[Union[List[str], Dict[str, str], ivy.Container]] = None, + to_apply: Union[bool, ivy.Container] = True, + prune_unapplied: Union[bool, ivy.Container] = False, + map_sequences: Union[bool, ivy.Container] = False, + ) -> ivy.Container: + """Compute the mean of values in the input data based on segment + identifiers. + + Parameters + ---------- + data : ivy.Container + Input array or container from which to gather the input. + segment_ids : ivy.Container + An array of integers indicating the segment identifier for each element in + 'data'. + num_segments : Union[int, ivy.Container] + An integer or array representing the total number of distinct segment IDs. + key_chains : Optional[Union[List[str], Dict[str, str], ivy.Container]], optional + The key-chains to apply or not apply the method to. Default is None. + to_apply : Union[bool, ivy.Container], optional + If True, the method will be applied to key-chains, otherwise key-chains will + be skipped. Default is True. + prune_unapplied : Union[bool, ivy.Container], optional + Whether to prune key-chains for which the function was not applied. + Default is False. + map_sequences : Union[bool, ivy.Container], optional + Whether to also map method to sequences (lists, tuples). Default is False. + + Returns + ------- + ivy.Container + A container representing the result of a segmented mean operation. + For each segment, it computes the mean of values in 'data' where + 'segment_ids' equals the segment ID. + """ + return ContainerBase.cont_multi_map_in_function( + "unsorted_segment_mean", + data, + segment_ids, + num_segments, + key_chains=key_chains, + to_apply=to_apply, + prune_unapplied=prune_unapplied, + map_sequences=map_sequences, + ) + + def unsorted_segment_mean( + self: ivy.Container, + segment_ids: Union[ivy.Array, ivy.Container], + num_segments: Union[int, ivy.Container], + ) -> ivy.Container: + """Compute the mean of values in the input array or container based on + segment identifiers. + + Parameters + ---------- + self : ivy.Container + Input array or container from which to gather the input. + segment_ids : ivy.Container + An array of integers indicating the segment identifier for each element + in 'self'. + num_segments : Union[int, ivy.Container] + An integer or array representing the total number of distinct segment IDs. + + Returns + ------- + ivy.Container + A container representing the result of a segmented mean operation. + For each segment, it computes the mean of values in 'self' where + 'segment_ids' equals the segment ID. + + Example + -------- + >>> data = ivy.Container(a=ivy.array([0., 1., 2., 4.]), + ... b=ivy.array([3., 4., 5., 6.])) + >>> segment_ids = ivy.array([0, 0, 1, 1]) + >>> num_segments = 2 + >>> result = ivy.unsorted_segment_mean(data, segment_ids, num_segments) + >>> print(result) + { + a: ivy.array([0.5, 3.0]), + b: ivy.array([3.5, 5.5]) + } + + >>> data = ivy.Container(a=ivy.array([0., 1., 2., 4., 5., 6.]), + ... b=ivy.array([3., 4., 5., 6., 7., 8.])) + >>> segment_ids = ivy.array([0, 0, 1, 1, 2, 2]) + >>> num_segments = 3 + >>> result = ivy.unsorted_segment_mean(data, segment_ids, num_segments) + >>> print(result) + { + a: ivy.array([0.5, 3.0, 5.5]), + b: ivy.array([3.5, 5.5, 7.5]) + } + """ + return self.static_unsorted_segment_mean( + self, + segment_ids, + num_segments, + ) + @staticmethod def static_polyval( coeffs: ivy.Container, @@ -1211,10 +1301,9 @@ def static_polyval( prune_unapplied: bool = False, map_sequences: bool = False, ) -> ivy.Container: - r""" - ivy.Container static method variant of ivy.polyval. This method simply wraps the - function, and so the docstring for ivy.polyval also applies to this method with - minimal changes. + r"""ivy.Container static method variant of ivy.polyval. This method + simply wraps the function, and so the docstring for ivy.polyval also + applies to this method with minimal changes. Evaluate and return a polynomial at specific given values. @@ -1240,7 +1329,7 @@ def static_polyval( Returns ------- ret - Output container containing simplified result of substituing x in the + Output container containing simplified result of substituting x in the coefficients - final value of polynomial. """ return ContainerBase.cont_multi_map_in_function( @@ -1258,10 +1347,9 @@ def polyval( coeffs: ivy.Container, x: ivy.Container, ) -> ivy.Container: - r""" - ivy.Container instance method variant of ivy.polyval. This method simply wraps - the function, and so the docstring for ivy.polyval also applies to this method - with minimal changes. + r"""ivy.Container instance method variant of ivy.polyval. This method + simply wraps the function, and so the docstring for ivy.polyval also + applies to this method with minimal changes. Evaluate and return a polynomial at specific given values. @@ -1279,7 +1367,7 @@ def polyval( Returns ------- ret - Output container containing simplified result of substituing x in the + Output container containing simplified result of substituting x in the coefficients - final value of polynomial. """ - return self.static_polyval(self, coeffs, x) + return self.static_polyval(coeffs, x) diff --git a/ivy/data_classes/container/experimental/elementwise.py b/ivy/data_classes/container/experimental/elementwise.py index f334e74ef5dff..402e0fa1fac1e 100644 --- a/ivy/data_classes/container/experimental/elementwise.py +++ b/ivy/data_classes/container/experimental/elementwise.py @@ -21,10 +21,9 @@ def static_amax( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.amax. This method simply wraps the - function, and so the docstring for ivy.amax also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.amax. This method simply + wraps the function, and so the docstring for ivy.amax also applies to + this method with minimal changes. Parameters ---------- @@ -117,10 +116,9 @@ def amax( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.amax. This method simply wraps the - function, and so the docstring for ivy.amax also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.amax. This method + simply wraps the function, and so the docstring for ivy.amax also + applies to this method with minimal changes. Parameters ---------- @@ -213,10 +211,9 @@ def static_amin( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.amin. This method simply wraps the - function, and so the docstring for ivy.amin also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.amin. This method simply + wraps the function, and so the docstring for ivy.amin also applies to + this method with minimal changes. Parameters ---------- @@ -308,10 +305,9 @@ def amin( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.amin. This method simply wraps the - function, and so the docstring for ivy.amin also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.amin. This method + simply wraps the function, and so the docstring for ivy.amin also + applies to this method with minimal changes. Parameters ---------- @@ -401,10 +397,9 @@ def static_sinc( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.sinc. This method simply wraps the - function, and so the docstring for ivy.sinc also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.sinc. This method simply + wraps the function, and so the docstring for ivy.sinc also applies to + this method with minimal changes. Parameters ---------- @@ -463,10 +458,9 @@ def sinc( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.sinc. This method simply wraps the - function, and so the docstring for ivy.sinc also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.sinc. This method + simply wraps the function, and so the docstring for ivy.sinc also + applies to this method with minimal changes. Parameters ---------- @@ -527,10 +521,9 @@ def static_fmod( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.fmod. This method simply wraps the - function, and so the docstring for ivy.fmod also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.fmod. This method simply + wraps the function, and so the docstring for ivy.fmod also applies to + this method with minimal changes. Parameters ---------- @@ -576,10 +569,9 @@ def fmod( *, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.fmod. This method simply wraps the - function, and so the docstring for ivy.fmod also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.fmod. This method + simply wraps the function, and so the docstring for ivy.fmod also + applies to this method with minimal changes. Parameters ---------- @@ -621,10 +613,9 @@ def static_fmax( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.fmax. This method simply wraps the - function, and so the docstring for ivy.fmax also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.fmax. This method simply + wraps the function, and so the docstring for ivy.fmax also applies to + this method with minimal changes. Parameters ---------- @@ -670,10 +661,9 @@ def fmax( *, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.fmax. This method simply wraps the - function, and so the docstring for ivy.fmax also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.fmax. This method + simply wraps the function, and so the docstring for ivy.fmax also + applies to this method with minimal changes. Parameters ---------- @@ -715,10 +705,9 @@ def static_float_power( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.float_power. This method simply wraps - the function, and so the docstring for ivy.float_power also applies to this - method with minimal changes. + """ivy.Container static method variant of ivy.float_power. This method + simply wraps the function, and so the docstring for ivy.float_power + also applies to this method with minimal changes. Parameters ---------- @@ -764,10 +753,9 @@ def float_power( *, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.float_power. This method simply - wraps the function, and so the docstring for ivy.float_power also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.float_power. This + method simply wraps the function, and so the docstring for + ivy.float_power also applies to this method with minimal changes. Parameters ---------- @@ -809,10 +797,9 @@ def static_copysign( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.copysign. This method simply wraps - the function, and so the docstring for ivy.copysign also applies to this method - with minimal changes. + """ivy.Container static method variant of ivy.copysign. This method + simply wraps the function, and so the docstring for ivy.copysign also + applies to this method with minimal changes. Parameters ---------- @@ -863,10 +850,9 @@ def copysign( *, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.copysign. This method simply wraps - the function, and so the docstring for ivy.copysign also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.copysign. This method + simply wraps the function, and so the docstring for ivy.copysign also + applies to this method with minimal changes. Parameters ---------- @@ -915,10 +901,9 @@ def static_count_nonzero( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.count_nonzero. This method simply - wraps the function, and so the docstring for ivy.count_nonzero also applies to - this method with minimal changes. + """ivy.Container static method variant of ivy.count_nonzero. This + method simply wraps the function, and so the docstring for + ivy.count_nonzero also applies to this method with minimal changes. Parameters ---------- @@ -1005,10 +990,9 @@ def count_nonzero( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.count_nonzero. This method simply - wraps the function, and so the docstring for ivy.count_nonzero also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.count_nonzero. This + method simply wraps the function, and so the docstring for + ivy.count_nonzero also applies to this method with minimal changes. Parameters ---------- @@ -1096,10 +1080,9 @@ def static_nansum( map_sequences: Union[bool, ivy.Container] = False, out: Optional[Union[ivy.Array, ivy.Container]] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.nansum. This method simply wraps the - function, and so the docstring for ivy.nansum also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.nansum. This method + simply wraps the function, and so the docstring for ivy.nansum also + applies to this method with minimal changes. Parameters ---------- @@ -1167,10 +1150,9 @@ def nansum( keepdims: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.nansum. This method simply wraps - the function, and so the docstring for ivy.nansum also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.nansum. This method + simply wraps the function, and so the docstring for ivy.nansum also + applies to this method with minimal changes. Parameters ---------- @@ -1230,10 +1212,9 @@ def static_isclose( map_sequences: Union[bool, ivy.Container] = False, out: Optional[Union[ivy.Array, ivy.Container]] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.isclose. This method simply wraps the - function, and so the docstring for ivy.isclose also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.isclose. This method + simply wraps the function, and so the docstring for ivy.isclose also + applies to this method with minimal changes. Parameters ---------- @@ -1329,10 +1310,9 @@ def isclose( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.isclose. This method simply wraps - the function, and so the docstring for ivy.isclose also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.isclose. This method + simply wraps the function, and so the docstring for ivy.isclose also + applies to this method with minimal changes. Parameters ---------- @@ -1424,10 +1404,9 @@ def static_signbit( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.signbit. This method simply wraps the - function, and so the docstring for ivy.signbit also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.signbit. This method + simply wraps the function, and so the docstring for ivy.signbit also + applies to this method with minimal changes. Parameters ---------- @@ -1467,10 +1446,9 @@ def signbit( *, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.signbit. This method simply wraps - the function, and so the docstring for ivy.signbit also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.signbit. This method + simply wraps the function, and so the docstring for ivy.signbit also + applies to this method with minimal changes. Parameters ---------- @@ -1508,10 +1486,9 @@ def static_hypot( map_sequences: Union[bool, ivy.Container] = False, out: Optional[Union[ivy.Array, ivy.Container]] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.hypot. This method simply wraps the - function, and so the docstring for ivy.hypot also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.hypot. This method simply + wraps the function, and so the docstring for ivy.hypot also applies to + this method with minimal changes. Parameters ---------- @@ -1573,10 +1550,9 @@ def hypot( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.hypot. This method simply wraps the - function, and so the docstring for ivy.hypot also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.hypot. This method + simply wraps the function, and so the docstring for ivy.hypot also + applies to this method with minimal changes. Parameters ---------- @@ -1641,10 +1617,9 @@ def static_allclose( map_sequences: Union[bool, ivy.Container] = False, out: Optional[Union[ivy.Array, ivy.Container]] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.allclose. This method simply wraps - the function, and so the docstring for ivy.allclose also applies to this method - with minimal changes. + """ivy.Container static method variant of ivy.allclose. This method + simply wraps the function, and so the docstring for ivy.allclose also + applies to this method with minimal changes. Parameters ---------- @@ -1732,10 +1707,9 @@ def allclose( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.allclose. This method simply wraps - the function, and so the docstring for ivy.allclose also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.allclose. This method + simply wraps the function, and so the docstring for ivy.allclose also + applies to this method with minimal changes. Parameters ---------- @@ -1825,10 +1799,9 @@ def static_diff( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.diff. This method simply wraps the - function, and so the docstring for ivy.diff also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.diff. This method simply + wraps the function, and so the docstring for ivy.diff also applies to + this method with minimal changes. Parameters ---------- @@ -1902,10 +1875,9 @@ def diff( ] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.diff. This method simply wraps the - function, and so the docstring for ivy.diff also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.diff. This method + simply wraps the function, and so the docstring for ivy.diff also + applies to this method with minimal changes. Parameters ---------- @@ -1955,10 +1927,9 @@ def static_fix( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.fix. This method simply wraps the - function, and so the docstring for ivy.fix also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.fix. This method simply + wraps the function, and so the docstring for ivy.fix also applies to + this method with minimal changes. Parameters ---------- @@ -1999,10 +1970,9 @@ def fix( *, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.fix. This method simply wraps the - function, and so the docstring for ivy.fix also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.fix. This method simply + wraps the function, and so the docstring for ivy.fix also applies to + this method with minimal changes. Parameters ---------- @@ -2041,10 +2011,9 @@ def static_nextafter( map_sequences: Union[bool, ivy.Container] = False, out: Optional[Union[ivy.Array, ivy.Container]] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.nextafter. This method simply wraps - the function, and so the docstring for ivy.nextafter also applies to this method - with minimal changes. + """ivy.Container static method variant of ivy.nextafter. This method + simply wraps the function, and so the docstring for ivy.nextafter also + applies to this method with minimal changes. Parameters ---------- @@ -2107,10 +2076,9 @@ def nextafter( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.nextafter. This method simply wraps - the function, and so the docstring for ivy.nextafter also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.nextafter. This method + simply wraps the function, and so the docstring for ivy.nextafter also + applies to this method with minimal changes. Parameters ---------- @@ -2173,10 +2141,9 @@ def static_zeta( map_sequences: Union[bool, ivy.Container] = False, out: Optional[Union[ivy.Array, ivy.Container]] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.zeta. This method simply wraps the - function, and so the docstring for ivy.zeta also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.zeta. This method simply + wraps the function, and so the docstring for ivy.zeta also applies to + this method with minimal changes. Parameters ---------- @@ -2238,10 +2205,9 @@ def zeta( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.zeta. This method simply wraps the - function, and so the docstring for ivy.zeta also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.zeta. This method + simply wraps the function, and so the docstring for ivy.zeta also + applies to this method with minimal changes. Parameters ---------- @@ -2324,8 +2290,7 @@ def gradient( edge_order: Union[int, ivy.Container] = 1, axis: Optional[Union[int, list, tuple, ivy.Container]] = None, ) -> ivy.Container: - """ - Calculate gradient of x with respect to (w.r.t.) spacing. + """Calculate gradient of x with respect to (w.r.t.) spacing. Parameters ---------- @@ -2465,10 +2430,9 @@ def static_xlogy( map_sequences: Union[bool, ivy.Container] = False, out: Optional[Union[ivy.Array, ivy.Container]] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.xlogy. This method simply wraps the - function, and so the docstring for ivy.xlogy also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.xlogy. This method simply + wraps the function, and so the docstring for ivy.xlogy also applies to + this method with minimal changes. Parameters ---------- @@ -2531,10 +2495,9 @@ def xlogy( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.xlogy. This method simply wraps the - function, and so the docstring for ivy.xlogy also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.xlogy. This method + simply wraps the function, and so the docstring for ivy.xlogy also + applies to this method with minimal changes. Parameters ---------- @@ -2597,9 +2560,8 @@ def static_binarizer( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - Map the values of the input tensor to either 0 or 1, element-wise, based on the - outcome of a comparison against a threshold value. + """Map the values of the input tensor to either 0 or 1, element-wise, + based on the outcome of a comparison against a threshold value. Parameters ---------- @@ -2649,9 +2611,8 @@ def binarizer( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - Map the values of the input tensor to either 0 or 1, element-wise, based on the - outcome of a comparison against a threshold value. + """Map the values of the input tensor to either 0 or 1, element-wise, + based on the outcome of a comparison against a threshold value. Parameters ---------- @@ -2699,10 +2660,9 @@ def static_conj( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.conj. This method simply wraps the - function, and so the docstring for ivy.conj also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.conj. This method simply + wraps the function, and so the docstring for ivy.conj also applies to + this method with minimal changes. Parameters ---------- @@ -2762,10 +2722,9 @@ def conj( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.conj. This method simply wraps the - function, and so the docstring for ivy.conj also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.conj. This method + simply wraps the function, and so the docstring for ivy.conj also + applies to this method with minimal changes. Parameters ---------- @@ -2826,10 +2785,9 @@ def static_ldexp( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.ldexp. This method simply wraps the - function, and so the docstring for ivy.ldexp also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.ldexp. This method simply + wraps the function, and so the docstring for ivy.ldexp also applies to + this method with minimal changes. Parameters ---------- @@ -2886,10 +2844,9 @@ def ldexp( *, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.ldexp. This method simply wraps the - function, and so the docstring for ivy.ldexp also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.ldexp. This method + simply wraps the function, and so the docstring for ivy.ldexp also + applies to this method with minimal changes. Parameters ---------- @@ -2931,10 +2888,9 @@ def static_lerp( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.lerp. This method simply wraps the - function, and so the docstring for ivy.lerp also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.lerp. This method simply + wraps the function, and so the docstring for ivy.lerp also applies to + this method with minimal changes. Parameters ---------- @@ -3007,10 +2963,9 @@ def lerp( *, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.lerp. This method simply wraps the - function, and so the docstring for ivy.lerp also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.lerp. This method + simply wraps the function, and so the docstring for ivy.lerp also + applies to this method with minimal changes. Parameters ---------- @@ -3053,10 +3008,9 @@ def static_frexp( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.frexp. This method simply wraps the - function, and so the docstring for ivy.frexp also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.frexp. This method simply + wraps the function, and so the docstring for ivy.frexp also applies to + this method with minimal changes. Parameters ---------- @@ -3107,10 +3061,9 @@ def frexp( *, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.frexp. This method simply wraps the - function, and so the docstring for ivy.frexp also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.frexp. This method + simply wraps the function, and so the docstring for ivy.frexp also + applies to this method with minimal changes. Parameters ---------- @@ -3148,10 +3101,9 @@ def static_modf( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.modf. This method simply wraps the - function, and so the docstring for ivy.modf also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.modf. This method simply + wraps the function, and so the docstring for ivy.modf also applies to + this method with minimal changes. Parameters ---------- @@ -3204,10 +3156,9 @@ def modf( *, out: Optional[ivy.Container] = None, ) -> ivy.Container: - r""" - ivy.Container instance method variant of ivy.modf. This method simply wraps the - function, and so the docstring for ivy.modf also applies to this method with - minimal changes. + r"""ivy.Container instance method variant of ivy.modf. This method + simply wraps the function, and so the docstring for ivy.modf also + applies to this method with minimal changes. Parameters ---------- @@ -3246,10 +3197,9 @@ def static_digamma( map_sequences: bool = False, out: Optional[ivy.Array] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.digamma. This method simply wraps the - function, and so the docstring for ivy.digamma also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.digamma. This method + simply wraps the function, and so the docstring for ivy.digamma also + applies to this method with minimal changes. Note ---- @@ -3278,6 +3228,7 @@ def static_digamma( ------- ret container including the digamma function computed element-wise + Examples -------- >>> x = ivy.Container(a=ivy.array([1, 0.5]),\ @@ -3308,10 +3259,9 @@ def digamma( map_sequences: bool = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.digamma. This method simply wraps - the function, and so the docstring for ivy.digamma also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.digamma. This method + simply wraps the function, and so the docstring for ivy.digamma also + applies to this method with minimal changes. Note ---- @@ -3340,6 +3290,7 @@ def digamma( ------- ret container including the digamma function computed element-wise + Examples -------- >>> x = ivy.Container(a=ivy.array([1, 0.5]), b=ivy.array([2.0, 3.0]) @@ -3370,10 +3321,9 @@ def static_sparsify_tensor( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.sparsify_tensor. This method simply - wraps the function, and so the docstring for ivy.sparsify_tensor also applies to - this method with minimal changes. + """ivy.Container static method variant of ivy.sparsify_tensor. This + method simply wraps the function, and so the docstring for + ivy.sparsify_tensor also applies to this method with minimal changes. Parameters ---------- @@ -3400,6 +3350,7 @@ def static_sparsify_tensor( ------- ret container including the sparsified tensor computed element-wise + Examples -------- >>> x = ivy.Container( @@ -3434,8 +3385,7 @@ def sparsify_tensor( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.sparsify_tensor. + """ivy.Container instance method variant of ivy.sparsify_tensor. This method simply wraps the function, and so the docstring for ivy.sparsify_tensor also applies to this method with minimal @@ -3462,10 +3412,9 @@ def static_erfc( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.erfc. This method simply wraps the - function, and so the docstring for ivy.erfc also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.erfc. This method simply + wraps the function, and so the docstring for ivy.erfc also applies to + this method with minimal changes. Parameters ---------- @@ -3515,10 +3464,9 @@ def erfc( *, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.erfc. This method simply wraps the - function, and so the docstring for ivy.erfc also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.erfc. This method + simply wraps the function, and so the docstring for ivy.erfc also + applies to this method with minimal changes. Parameters ---------- @@ -3543,3 +3491,94 @@ def erfc( } """ return self.static_erfc(self, out=out) + + @staticmethod + def static_erfinv( + x: Union[ivy.Array, ivy.NativeArray, ivy.Container], + /, + *, + key_chains: Optional[Union[List[str], Dict[str, str], ivy.Container]] = None, + to_apply: Union[bool, ivy.Container] = True, + prune_unapplied: Union[bool, ivy.Container] = False, + map_sequences: Union[bool, ivy.Container] = False, + out: Optional[ivy.Container] = None, + ) -> ivy.Container: + """ivy.Container static method variant of ivy.erfinv. This method + simply wraps the function, and so the docstring for ivy.erfinv also + applies to this method with minimal changes. + + Parameters + ---------- + x + The container whose array contains real or complex valued argument. + key_chains + The key-chains to apply or not apply the method to. Default is ``None``. + to_apply + If True, the method will be applied to key_chains, otherwise key_chains + will be skipped. Default is ``True``. + prune_unapplied + Whether to prune key_chains for which the function was not applied. + Default is ``False``. + map_sequences + Whether to also map method to sequences (lists, tuples). + Default is ``False``. + out + optional output container, for writing the result to. + + Returns + ------- + ret + container with values of the inverse error function. + + Examples + -------- + >>> x = ivy.Container(a=ivy.array([1., 2.]), b=ivy.array([-3., -4.])) + >>> ivy.Container.static_erfinv(x) + { + a: ivy.array([0.15729921, 0.00467773]), + b: ivy.array([1.99997795, 2.]) + } + """ + return ContainerBase.cont_multi_map_in_function( + "erfinv", + x, + key_chains=key_chains, + to_apply=to_apply, + prune_unapplied=prune_unapplied, + map_sequences=map_sequences, + out=out, + ) + + def erfinv( + self: ivy.Container, + /, + *, + out: Optional[ivy.Container] = None, + ) -> ivy.Container: + """ivy.Container instance method variant of ivy.erfinv. This method + simply wraps the function, and so the docstring for ivy.erfinv also + applies to this method with minimal changes. + + Parameters + ---------- + self + The container whose array contains real or complex valued argument. + out + optional output container, for writing the result to. + + Returns + ------- + ret + container with values of the inverse error function. + + Examples + -------- + With one :class:`ivy.Container` input: + >>> x = ivy.Container(a=ivy.array([1., 2., 3.]), b=ivy.array([-1., -2., -3.])) + >>> x.erfinv() + { + a: ivy.array([1.57299206e-01, 4.67773480e-03, 2.20904985e-05]), + b: ivy.array([1.84270084, 1.99532223, 1.99997795]) + } + """ + return self.static_erfinv(self, out=out) diff --git a/ivy/data_classes/container/experimental/general.py b/ivy/data_classes/container/experimental/general.py index af380102a50ce..e44bc1fc8e506 100644 --- a/ivy/data_classes/container/experimental/general.py +++ b/ivy/data_classes/container/experimental/general.py @@ -21,10 +21,9 @@ def _static_reduce( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.reduce. This method simply wraps the - function, and so the docstring for ivy.reduce also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.reduce. This method + simply wraps the function, and so the docstring for ivy.reduce also + applies to this method with minimal changes. Parameters ---------- @@ -95,10 +94,9 @@ def reduce( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.reduce. This method simply wraps - the function, and so the docstring for ivy.reduce also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.reduce. This method + simply wraps the function, and so the docstring for ivy.reduce also + applies to this method with minimal changes. Parameters ---------- diff --git a/ivy/data_classes/container/experimental/layers.py b/ivy/data_classes/container/experimental/layers.py index fc61b0caa19dd..cba584f2686e0 100644 --- a/ivy/data_classes/container/experimental/layers.py +++ b/ivy/data_classes/container/experimental/layers.py @@ -24,10 +24,9 @@ def static_max_pool1d( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.max_pool1d. This method simply wraps - the function, and so the docstring for ivy.max_pool1d also applies to this - method with minimal changes. + """ivy.Container static method variant of ivy.max_pool1d. This method + simply wraps the function, and so the docstring for ivy.max_pool1d also + applies to this method with minimal changes. Parameters ---------- @@ -101,10 +100,9 @@ def max_pool1d( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of `ivy.max_pool1d`. This method simply - wraps the function, and so the docstring for `ivy.max_pool1d` also applies to - this method with minimal changes. + """ivy.Container instance method variant of `ivy.max_pool1d`. This + method simply wraps the function, and so the docstring for + `ivy.max_pool1d` also applies to this method with minimal changes. Parameters ---------- @@ -178,10 +176,9 @@ def static_max_pool2d( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.max_pool2dd. This method simply wraps - the function, and so the docstring for ivy.max_pool2d also applies to this - method with minimal changes. + """ivy.Container static method variant of ivy.max_pool2dd. This method + simply wraps the function, and so the docstring for ivy.max_pool2d also + applies to this method with minimal changes. Parameters ---------- @@ -253,10 +250,9 @@ def max_pool2d( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of `ivy.max_pool2d`. This method simply - wraps the function, and so the docstring for `ivy.max_pool2d` also applies to - this method with minimal changes. + """ivy.Container instance method variant of `ivy.max_pool2d`. This + method simply wraps the function, and so the docstring for + `ivy.max_pool2d` also applies to this method with minimal changes. Parameters ---------- @@ -332,10 +328,9 @@ def static_max_pool3d( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.max_pool3d. This method simply wraps - the function, and so the docstring for ivy.max_pool3d also applies to this - method with minimal changes. + """ivy.Container static method variant of ivy.max_pool3d. This method + simply wraps the function, and so the docstring for ivy.max_pool3d also + applies to this method with minimal changes. Parameters ---------- @@ -410,10 +405,9 @@ def max_pool3d( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.max_pool3d. This method simply wraps - the function, and so the docstring for ivy.max_pool3d also applies to this - method with minimal changes. + """ivy.Container static method variant of ivy.max_pool3d. This method + simply wraps the function, and so the docstring for ivy.max_pool3d also + applies to this method with minimal changes. Parameters ---------- @@ -485,10 +479,9 @@ def static_avg_pool1d( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.avg_pool1d. This method simply wraps - the function, and so the docstring for ivy.avg_pool1d also applies to this - method with minimal changes. + """ivy.Container static method variant of ivy.avg_pool1d. This method + simply wraps the function, and so the docstring for ivy.avg_pool1d also + applies to this method with minimal changes. Parameters ---------- @@ -561,10 +554,9 @@ def avg_pool1d( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of `ivy.avg_pool1d`. This method simply - wraps the function, and so the docstring for `ivy.avg_pool1d` also applies to - this method with minimal changes. + """ivy.Container instance method variant of `ivy.avg_pool1d`. This + method simply wraps the function, and so the docstring for + `ivy.avg_pool1d` also applies to this method with minimal changes. Parameters ---------- @@ -638,10 +630,9 @@ def static_avg_pool2d( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.avg_pool2d. This method simply wraps - the function, and so the docstring for ivy.avg_pool2d also applies to this - method with minimal changes. + """ivy.Container static method variant of ivy.avg_pool2d. This method + simply wraps the function, and so the docstring for ivy.avg_pool2d also + applies to this method with minimal changes. Parameters ---------- @@ -718,10 +709,9 @@ def avg_pool2d( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of `ivy.avg_pool2d`. This method simply - wraps the function, and so the docstring for `ivy.avg_pool2d` also applies to - this method with minimal changes. + """ivy.Container instance method variant of `ivy.avg_pool2d`. This + method simply wraps the function, and so the docstring for + `ivy.avg_pool2d` also applies to this method with minimal changes. Parameters ---------- @@ -798,10 +788,9 @@ def static_avg_pool3d( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.avg_pool3d. This method simply wraps - the function, and so the docstring for ivy.avg_pool3d also applies to this - method with minimal changes. + """ivy.Container static method variant of ivy.avg_pool3d. This method + simply wraps the function, and so the docstring for ivy.avg_pool3d also + applies to this method with minimal changes. Parameters ---------- @@ -879,10 +868,9 @@ def avg_pool3d( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.avg_pool3d. This method simply wraps - the function, and so the docstring for ivy.avg_pool3d also applies to this - method with minimal changes. + """ivy.Container static method variant of ivy.avg_pool3d. This method + simply wraps the function, and so the docstring for ivy.avg_pool3d also + applies to this method with minimal changes. Parameters ---------- @@ -959,10 +947,9 @@ def static_dct( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.dct. This method simply wraps the - function, and so the docstring for ivy.dct also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.dct. This method simply + wraps the function, and so the docstring for ivy.dct also applies to + this method with minimal changes. Parameters ---------- @@ -1035,10 +1022,9 @@ def dct( norm: Optional[Union[Literal["ortho"], ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.dct. This method simply wraps the - function, and so the docstring for ivy.dct also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.dct. This method simply + wraps the function, and so the docstring for ivy.dct also applies to + this method with minimal changes. Parameters ---------- @@ -1095,10 +1081,9 @@ def static_idct( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.idct. This method simply wraps the - function, and so the docstring for ivy.idct also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.idct. This method simply + wraps the function, and so the docstring for ivy.idct also applies to + this method with minimal changes. Parameters ---------- @@ -1173,10 +1158,9 @@ def idct( norm: Optional[Union[Literal["ortho"], ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.idct. This method simply wraps the - function, and so the docstring for ivy.idct also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.idct. This method + simply wraps the function, and so the docstring for ivy.idct also + applies to this method with minimal changes. Parameters ---------- @@ -1232,10 +1216,9 @@ def _static_fft( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.fft. This method simply wraps the - function, and so the docstring for ivy.fft also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.fft. This method simply + wraps the function, and so the docstring for ivy.fft also applies to + this method with minimal changes. Parameters ---------- @@ -1304,10 +1287,9 @@ def fft( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.fft. This method simply wraps the - function, and so the docstring for ivy.fft also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.fft. This method simply + wraps the function, and so the docstring for ivy.fft also applies to + this method with minimal changes. Parameters ---------- @@ -1375,10 +1357,9 @@ def static_ifft( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ): - """ - ivy.Container static method variant of ivy.ifft. This method simply wraps the - function, and so the docstring for ivy.ifft also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.ifft. This method simply + wraps the function, and so the docstring for ivy.ifft also applies to + this method with minimal changes. Parameters ---------- @@ -1442,10 +1423,9 @@ def ifft( n: Optional[Union[int, Tuple[int], ivy.Container]] = None, out: Optional[Union[ivy.Array, ivy.Container]] = None, ): - """ - ivy.Container instance method variant of ivy.ifft. This method simply wraps the - function, and so the docstring for ivy.ifft also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.ifft. This method + simply wraps the function, and so the docstring for ivy.ifft also + applies to this method with minimal changes. Parameters ---------- @@ -1666,8 +1646,7 @@ def static_interpolate( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - Down/up samples the input to the given size. The algorithm used for + """Down/up samples the input to the given size. The algorithm used for interpolation is determined by mode. Parameters @@ -1755,8 +1734,7 @@ def interpolate( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - Down/up samples the input to the given size. The algorithm used for + """Down/up samples the input to the given size. The algorithm used for interpolation is determined by mode. Parameters @@ -1825,10 +1803,10 @@ def static_adaptive_avg_pool1d( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.adaptive_avg_pool1d. This method - simply wraps the function, and so the docstring for ivy.adaptive_avg_pool1d also - applies to this method with minimal changes. + """ivy.Container static method variant of ivy.adaptive_avg_pool1d. This + method simply wraps the function, and so the docstring for + ivy.adaptive_avg_pool1d also applies to this method with minimal + changes. Parameters ---------- @@ -1863,9 +1841,8 @@ def adaptive_avg_pool1d( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - Apply a 1D adaptive average pooling over an input signal composed of several - input planes. + """Apply a 1D adaptive average pooling over an input signal composed of + several input planes. Parameters ---------- @@ -1891,25 +1868,27 @@ def adaptive_avg_pool1d( def static_adaptive_avg_pool2d( input: Union[ivy.Array, ivy.NativeArray, ivy.Container], output_size: Union[Sequence[int], int, ivy.Container], + /, *, key_chains: Optional[Union[List[str], Dict[str, str], ivy.Container]] = None, to_apply: Union[bool, ivy.Container] = True, prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, + data_format: str = "NHWC", ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.adaptive_avg_pool2d. This method - simply wraps the function, and so the docstring for ivy.adaptive_avg_pool2d also - applies to this method with minimal changes. + """ivy.Container static method variant of ivy.adaptive_avg_pool2d. This + method simply wraps the function, and so the docstring for + ivy.adaptive_avg_pool2d also applies to this method with minimal + changes. Parameters ---------- input - Input array. Must have shape (N, C, H_in, W_in) or (C, H_in, W_in) where N - is the batch dimension, C is the feature dimension, and H_in and W_in are - the 2 spatial dimensions. + A 3D or 4D input array. Should have a floating-point data type. output_size Spatial output size. + data_format + "NHWC" or "NCHW". Defaults to "NHWC". Returns ------- @@ -1924,20 +1903,22 @@ def static_adaptive_avg_pool2d( to_apply=to_apply, prune_unapplied=prune_unapplied, map_sequences=map_sequences, + data_format=data_format, ) def adaptive_avg_pool2d( self: ivy.Container, output_size: Union[int, ivy.Container], + /, *, key_chains: Optional[Union[List[str], Dict[str, str], ivy.Container]] = None, to_apply: Union[bool, ivy.Container] = True, prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, + data_format: str = "NHWC", ) -> ivy.Container: - """ - Apply a 2D adaptive average pooling over an input signal composed of several - input planes. + """Apply a 2D adaptive average pooling over an input signal composed of + several input planes. Parameters ---------- @@ -1945,6 +1926,8 @@ def adaptive_avg_pool2d( Input container. output_size Spatial output size. + data_format + "NHWC" or "NCHW". Defaults to "NHWC". Returns ------- @@ -1957,6 +1940,7 @@ def adaptive_avg_pool2d( to_apply=to_apply, prune_unapplied=prune_unapplied, map_sequences=map_sequences, + data_format=data_format, ) @staticmethod @@ -1969,10 +1953,10 @@ def static_adaptive_max_pool2d( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.adaptive_max_pool2d. This method - simply wraps the function, and so the docstring for ivy.adaptive_max_pool2d also - applies to this method with minimal changes. + """ivy.Container static method variant of ivy.adaptive_max_pool2d. This + method simply wraps the function, and so the docstring for + ivy.adaptive_max_pool2d also applies to this method with minimal + changes. Parameters ---------- @@ -2007,9 +1991,8 @@ def adaptive_max_pool2d( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - Apply a 2D adaptive maximum pooling over an input signal composed of several - input planes. + """Apply a 2D adaptive maximum pooling over an input signal composed of + several input planes. Parameters ---------- @@ -2031,6 +2014,44 @@ def adaptive_max_pool2d( map_sequences=map_sequences, ) + @staticmethod + def static_adaptive_max_pool3d( + input: Union[ivy.Array, ivy.NativeArray, ivy.Container], + output_size: Union[Sequence[int], int, ivy.Container], + *, + key_chains: Optional[Union[List[str], Dict[str, str], ivy.Container]] = None, + to_apply: Union[bool, ivy.Container] = True, + prune_unapplied: Union[bool, ivy.Container] = False, + map_sequences: Union[bool, ivy.Container] = False, + ) -> ivy.Container: + return ContainerBase.cont_multi_map_in_function( + "adaptive_max_pool3d", + input, + output_size, + key_chains=key_chains, + to_apply=to_apply, + prune_unapplied=prune_unapplied, + map_sequences=map_sequences, + ) + + def adaptive_max_pool3d( + self: ivy.Container, + output_size: Union[int, ivy.Container], + *, + key_chains: Optional[Union[List[str], Dict[str, str], ivy.Container]] = None, + to_apply: Union[bool, ivy.Container] = True, + prune_unapplied: Union[bool, ivy.Container] = False, + map_sequences: Union[bool, ivy.Container] = False, + ) -> ivy.Container: + return self.static_adaptive_max_pool3d( + self, + output_size, + key_chains=key_chains, + to_apply=to_apply, + prune_unapplied=prune_unapplied, + map_sequences=map_sequences, + ) + @staticmethod def static_ifftn( x: ivy.Container, @@ -2044,8 +2065,7 @@ def static_ifftn( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ): - """ - ivy.Container static method variant of ivy.ifftn. + """ivy.Container static method variant of ivy.ifftn. This method simply wraps the function, and so the docstring for ivy.ifftn also applies to this method with minimal changes. @@ -2103,8 +2123,7 @@ def ifftn( norm: Union[str, ivy.Container] = "backward", out: Optional[Union[ivy.Array, ivy.Container]] = None, ): - """ - ivy.Container static method variant of ivy.ifftn. + """ivy.Container static method variant of ivy.ifftn. This method simply wraps the function, and so the docstring for ivy.ifftn also applies to this method with minimal changes. @@ -2188,8 +2207,7 @@ def static_rfft( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.rfft. + """ivy.Container static method variant of ivy.rfft. This method simply wraps the function, and so the docstring for ivy.rfft also applies to this method with minimal changes. @@ -2278,10 +2296,9 @@ def rfft( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ): - """ - ivy.Container instance method variant of ivy.rfft. This method simply wraps the - function, and so the docstring for ivy.rfft also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.rfft. This method + simply wraps the function, and so the docstring for ivy.rfft also + applies to this method with minimal changes. Parameters ---------- @@ -2364,8 +2381,7 @@ def static_rfftn( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.rfftn. + """ivy.Container static method variant of ivy.rfftn. This method simply wraps the function, and so the docstring for ivy.rfftn also applies to this method with minimal changes. @@ -2429,8 +2445,7 @@ def rfftn( norm: Union[str, ivy.Container] = "backward", out: Optional[Union[ivy.Array, ivy.Container]] = None, ) -> ivy.Container: - """ - Compute the n-dimensional discrete Fourier Transform for real input. + """Compute the n-dimensional discrete Fourier Transform for real input. Parameters ---------- @@ -2477,8 +2492,7 @@ def static_stft( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.stft. + """ivy.Container static method variant of ivy.stft. This method simply wraps the function, and so the docstring for ivy.stft also applies to this method with minimal changes. @@ -2542,8 +2556,7 @@ def stft( name: Optional[Union[str, ivy.Container]] = None, out: Optional[Union[ivy.Array, ivy.Container]] = None, ) -> ivy.Container: - """ - Compute the Short-time Fourier Transform of signals. + """Compute the Short-time Fourier Transform of signals. Parameters ---------- @@ -2600,10 +2613,9 @@ def _static_sliding_window( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.sliding_window. This method simply - wraps the function, and so the docstring for ivy.sliding_window also applies to - this method with minimal changes. + """ivy.Container static method variant of ivy.sliding_window. This + method simply wraps the function, and so the docstring for + ivy.sliding_window also applies to this method with minimal changes. Parameters ---------- @@ -2682,10 +2694,9 @@ def sliding_window( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.sliding_window. This method simply - wraps the function, and so the docstring for ivy.sliding_window also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.sliding_window. This + method simply wraps the function, and so the docstring for + ivy.sliding_window also applies to this method with minimal changes. Parameters ---------- @@ -2753,7 +2764,7 @@ def static_max_unpool1d( kernel_size: Union[Tuple[int], int], /, *, - strides: Union[int, Tuple[int]] = None, + strides: Optional[Union[int, Tuple[int]]] = None, padding: Union[int, Tuple[int]] = 0, data_format: Union[str, ivy.Container] = "NCW", key_chains: Optional[Union[List[str], Dict[str, str], ivy.Container]] = None, @@ -2761,8 +2772,7 @@ def static_max_unpool1d( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.max_unpool1d. + """ivy.Container static method variant of ivy.max_unpool1d. Parameters ---------- @@ -2817,12 +2827,12 @@ def max_unpool1d( kernel_size: Union[Tuple[int], int], /, *, - strides: Union[int, Tuple[int]] = None, + strides: Optional[Union[int, Tuple[int]]] = None, padding: Union[int, Tuple[int]] = 0, data_format: Optional[str] = "NCW", ) -> ivy.Container: - """ - Compute a 1-D max unpooling given the 1-D pooled input x and its indices. + """Compute a 1-D max unpooling given the 1-D pooled input x and its + indices. Parameters ---------- @@ -2854,3 +2864,78 @@ def max_unpool1d( padding=padding, data_format=data_format, ) + + @staticmethod + def static_rnn( + step_function: Callable, + inputs: ivy.Array, + initial_states: List[ivy.Array], + /, + *, + go_backwards: bool = False, + mask: Optional[ivy.Array] = None, + constants: Optional[ivy.Array] = None, + unroll: bool = False, + input_length: Optional[int] = None, + time_major: bool = False, + zero_output_for_mask: bool = False, + return_all_outputs: bool = True, + ) -> ivy.Container: + """ivy.Container static method variant of ivy.rnn. + + Parameters + ---------- + step_function + RNN step function. + inputs + Array of temporal data of shape (samples, time, ...). + initial_states + Array with shape (samples, state_size). + go_backwards + If True, do the iteration over the time dimension in reverse order and + return the reversed sequence. + mask + Binary array with shape (samples, time, 1), with a zero for every element + that is masked. + constants + List of constant values passed at each step. + unroll + Whether to use a pythonic while loop or ivy.while_loop + input_length + An integer or 1-D array, depending on whether the time dimension is + fixed-length. In case of variable length input, it is used for masking in + case there is no mask specified. + time_major + If True, the inputs and outputs will be in shape (timesteps, batch, ...) + whereas in the False case, it will be (batch, timesteps, ...). + zero_output_for_mask + If True, the otput for masked timestep will be zeros, whereas in the False + case, output from previous timestep is returned + return_all_outputs + If True, return the recurrent outputs for all timesteps in the sequence. If + False, only return the output for the last timestep. + + Returns + ------- + ret + A tuple of + - the latest output of the rnn of shape (samples, ...) + - the output of the rnn of shape (samples, time, ...) if + return_all_outputs=True else (samples, 1, ...) + - list of tensors, latest states returned by the step funciton, of shape + (samples, ...) + """ + return ContainerBase.cont_multi_map_in_function( + "rnn", + step_function, + inputs, + initial_states, + go_backwards=go_backwards, + mask=mask, + constants=constants, + unroll=unroll, + input_length=input_length, + time_major=time_major, + zero_output_for_mask=zero_output_for_mask, + return_all_outputs=return_all_outputs, + ) diff --git a/ivy/data_classes/container/experimental/linear_algebra.py b/ivy/data_classes/container/experimental/linear_algebra.py index b7f2d2ae67435..697d0ef749e52 100644 --- a/ivy/data_classes/container/experimental/linear_algebra.py +++ b/ivy/data_classes/container/experimental/linear_algebra.py @@ -24,10 +24,9 @@ def static_eigh_tridiagonal( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> Union[ivy.Container, Tuple[ivy.Container, ivy.Container]]: - """ - ivy.Container static method variant of ivy.eigh_tridiagonal. This method simply - wraps the function, and so the docstring for ivy.eigh_tridiagonal also applies - to this method with minimal changes. + """ivy.Container static method variant of ivy.eigh_tridiagonal. This + method simply wraps the function, and so the docstring for + ivy.eigh_tridiagonal also applies to this method with minimal changes. Parameters ---------- @@ -118,10 +117,9 @@ def eigh_tridiagonal( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> Union[ivy.Container, Tuple[ivy.Container, ivy.Container]]: - """ - ivy.Container instance method variant of ivy.eigh_tridiagonal. This method - simply wraps the function, and so the docstring for ivy.eigh_tridiagonal also - applies to this method with minimal changes. + """ivy.Container instance method variant of ivy.eigh_tridiagonal. This + method simply wraps the function, and so the docstring for + ivy.eigh_tridiagonal also applies to this method with minimal changes. Parameters ---------- @@ -236,10 +234,9 @@ def diagflat( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.diagflat. This method simply wraps - the function, and so the docstring for ivy.diagflat also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.diagflat. This method + simply wraps the function, and so the docstring for ivy.diagflat also + applies to this method with minimal changes. Examples -------- @@ -277,10 +274,9 @@ def static_kron( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.kron. This method simply wraps the - function, and so the docstring for ivy.kron also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.kron. This method simply + wraps the function, and so the docstring for ivy.kron also applies to + this method with minimal changes. Parameters ---------- @@ -329,10 +325,9 @@ def kron( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.kron. This method simply wraps the - function, and so the docstring for ivy.kron also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.kron. This method + simply wraps the function, and so the docstring for ivy.kron also + applies to this method with minimal changes. Examples -------- @@ -379,10 +374,9 @@ def matrix_exp( to_apply: Union[bool, ivy.Container] = True, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.diagflat. This method simply wraps - the function, and so the docstring for ivy.diagflat also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.diagflat. This method + simply wraps the function, and so the docstring for ivy.diagflat also + applies to this method with minimal changes. Examples -------- @@ -413,10 +407,9 @@ def static_eig( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.eig. This method simply wraps the - function, and so the docstring for ivy.eig also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.eig. This method simply + wraps the function, and so the docstring for ivy.eig also applies to + this method with minimal changes. Parameters ---------- @@ -466,10 +459,9 @@ def eig( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.eig. This method simply wraps the - function, and so the docstring for ivy.eig also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.eig. This method simply + wraps the function, and so the docstring for ivy.eig also applies to + this method with minimal changes. Parameters ---------- @@ -519,10 +511,9 @@ def static_eigvals( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.eigvals. This method simply wraps the - function, and so the docstring for ivy.eigvals also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.eigvals. This method + simply wraps the function, and so the docstring for ivy.eigvals also + applies to this method with minimal changes. Parameters ---------- @@ -566,10 +557,9 @@ def eigvals( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.eigvals. This method simply wraps - the function, and so the docstring for ivy.eigvals also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.eigvals. This method + simply wraps the function, and so the docstring for ivy.eigvals also + applies to this method with minimal changes. Parameters ---------- @@ -612,10 +602,9 @@ def static_adjoint( to_apply: Union[bool, ivy.Container] = True, out: Optional[ivy.Container] = None, ): - """ - ivy.Container static method variant of ivy.adjoint. This method simply wraps the - function, and so the docstring for ivy.adjoint also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.adjoint. This method + simply wraps the function, and so the docstring for ivy.adjoint also + applies to this method with minimal changes. Parameters ---------- @@ -661,10 +650,9 @@ def adjoint( to_apply: Union[bool, ivy.Container] = True, out: Optional[ivy.Container] = None, ): - """ - ivy.Container instance method variant of ivy.adjoint. This method simply wraps - the function, and so the docstring for ivy.adjoint also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.adjoint. This method + simply wraps the function, and so the docstring for ivy.adjoint also + applies to this method with minimal changes. Examples -------- @@ -692,10 +680,9 @@ def static_multi_dot( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.multi_dot. This method simply wraps - the function, and so the docstring for ivy.multi_dot also applies to this method - with minimal changes. + """ivy.Container static method variant of ivy.multi_dot. This method + simply wraps the function, and so the docstring for ivy.multi_dot also + applies to this method with minimal changes. Parameters ---------- @@ -750,10 +737,9 @@ def multi_dot( map_sequences: Union[bool, ivy.Container] = True, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.multi_dot. This method simply wraps - the function, and so the docstring for ivy.multi_dot also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.multi_dot. This method + simply wraps the function, and so the docstring for ivy.multi_dot also + applies to this method with minimal changes. Examples -------- @@ -782,7 +768,7 @@ def multi_dot( @staticmethod def static_cond( - self: ivy.Container, + x: ivy.Container, /, *, key_chains: Optional[Union[List[str], Dict[str, str], ivy.Container]] = None, @@ -792,14 +778,13 @@ def static_cond( p: Optional[Union[int, float, None, ivy.Container]] = None, out: Optional[ivy.Container] = None, ): - """ - ivy.Container static method variant of ivy.cond. This method simply wraps the - function, and so the docstring for ivy.cond also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.cond. This method simply + wraps the function, and so the docstring for ivy.cond also applies to + this method with minimal changes. Parameters ---------- - self + x container with input arrays. p order of the norm of the matrix (see ivy.norm). @@ -818,7 +803,7 @@ def static_cond( """ return ContainerBase.cont_multi_map_in_function( "cond", - self, + x, p=p, out=out, key_chains=key_chains, @@ -837,10 +822,9 @@ def cond( map_sequences: Union[bool, ivy.Container] = False, p: Optional[Union[int, float, None, ivy.Container]] = None, ): - """ - ivy.Container instance method variant of ivy.cond. This method simply wraps the - function, and so the docstring for ivy.cond also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.cond. This method + simply wraps the function, and so the docstring for ivy.cond also + applies to this method with minimal changes. Parameters ---------- @@ -900,10 +884,9 @@ def static_mode_dot( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.mode_dot. This method simply wraps - the function, and so the docstring for ivy.mode_dot also applies to this method - with minimal changes. + """ivy.Container static method variant of ivy.mode_dot. This method + simply wraps the function, and so the docstring for ivy.mode_dot also + applies to this method with minimal changes. Parameters ---------- @@ -956,10 +939,9 @@ def mode_dot( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ): - """ - ivy.Container instance method variant of ivy.mode_dot. This method simply wraps - the function, and so the docstring for ivy.mode_dot also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.mode_dot. This method + simply wraps the function, and so the docstring for ivy.mode_dot also + applies to this method with minimal changes. Parameters ---------- @@ -1013,10 +995,9 @@ def static_multi_mode_dot( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.multi_mode_dot. This method simply - wraps the function, and so the docstring for ivy.multi_mode_dot also applies to - this method with minimal changes. + """ivy.Container static method variant of ivy.multi_mode_dot. This + method simply wraps the function, and so the docstring for + ivy.multi_mode_dot also applies to this method with minimal changes. Parameters ---------- @@ -1073,10 +1054,9 @@ def multi_mode_dot( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.multi_mode_dot. This method simply - wraps the function, and so the docstring for ivy.multi_mode_dot also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.multi_mode_dot. This + method simply wraps the function, and so the docstring for + ivy.multi_mode_dot also applies to this method with minimal changes. Parameters ---------- @@ -1130,10 +1110,9 @@ def static_svd_flip( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> Tuple[ivy.Container, ivy.Container]: - """ - ivy.Container static method variant of ivy.svd_flip. This method simply wraps - the function, and so the docstring for ivy.svd_flip also applies to this method - with minimal changes. + """ivy.Container static method variant of ivy.svd_flip. This method + simply wraps the function, and so the docstring for ivy.svd_flip also + applies to this method with minimal changes. Parameters ---------- @@ -1172,10 +1151,9 @@ def svd_flip( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> Tuple[ivy.Container, ivy.Container]: - """ - ivy.Container instance method variant of ivy.svd_flip. This method simply wraps - the function, and so the docstring for ivy.svd_flip applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.svd_flip. This method + simply wraps the function, and so the docstring for ivy.svd_flip + applies to this method with minimal changes. Parameters ---------- @@ -1216,10 +1194,10 @@ def static_make_svd_non_negative( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> Tuple[ivy.Container, ivy.Container]: - """ - ivy.Container static method variant of ivy.make_svd_non_negative. This method - simply wraps the function, and so the docstring for ivy.make_svd_non_negative - also applies to this method with minimal changes. + """ivy.Container static method variant of ivy.make_svd_non_negative. + This method simply wraps the function, and so the docstring for + ivy.make_svd_non_negative also applies to this method with minimal + changes. Parameters ---------- @@ -1263,10 +1241,9 @@ def make_svd_non_negative( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> Tuple[ivy.Container, ivy.Container]: - """ - ivy.Container instance method variant of ivy.make_svd_non_negative. This method - simply wraps the function, and so the docstring for ivy.make_svd_non_negative - applies to this method with minimal changes. + """ivy.Container instance method variant of ivy.make_svd_non_negative. + This method simply wraps the function, and so the docstring for + ivy.make_svd_non_negative applies to this method with minimal changes. Parameters ---------- @@ -1309,10 +1286,9 @@ def static_tensor_train( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> Tuple[ivy.Container, Sequence[ivy.Container]]: - """ - ivy.Container static method variant of ivy.tensor_train. This method simply - wraps the function, and so the docstring for ivy.tensor_train also applies to - this method with minimal changes. + """ivy.Container static method variant of ivy.tensor_train. This method + simply wraps the function, and so the docstring for ivy.tensor_train + also applies to this method with minimal changes. Parameters ---------- @@ -1349,10 +1325,9 @@ def tensor_train( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> Tuple[ivy.Container, Sequence[ivy.Container]]: - """ - ivy.Container instance method variant of ivy.tensor_train. This method simply - wraps the function, and so the docstring for ivy.tensor_train also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.tensor_train. This + method simply wraps the function, and so the docstring for + ivy.tensor_train also applies to this method with minimal changes. Parameters ---------- @@ -1388,10 +1363,9 @@ def static_truncated_svd( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> Union[ivy.Container, Tuple[ivy.Container, ivy.Container, ivy.Container]]: - """ - ivy.Container static method variant of ivy.truncated_svd. This method simply - wraps the function, and so the docstring for ivy.truncated_svd also applies to - this method with minimal changes. + """ivy.Container static method variant of ivy.truncated_svd. This + method simply wraps the function, and so the docstring for + ivy.truncated_svd also applies to this method with minimal changes. Parameters ---------- @@ -1435,10 +1409,9 @@ def truncated_svd( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> Union[ivy.Container, Tuple[ivy.Container, ivy.Container, ivy.Container]]: - """ - ivy.Container instance method variant of ivy.truncated_svd. This method simply - wraps the function, and so the docstring for ivy.truncated_svd also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.truncated_svd. This + method simply wraps the function, and so the docstring for + ivy.truncated_svd also applies to this method with minimal changes. Parameters ---------- @@ -1490,10 +1463,9 @@ def static_initialize_tucker( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> Tuple[ivy.Container, Sequence[ivy.Container]]: - """ - ivy.Container static method variant of ivy.initialize_tucker. This method simply - wraps the function, and so the docstring for ivy.initialize_tucker also applies - to this method with minimal changes. + """ivy.Container static method variant of ivy.initialize_tucker. This + method simply wraps the function, and so the docstring for + ivy.initialize_tucker also applies to this method with minimal changes. Parameters ---------- @@ -1564,10 +1536,9 @@ def initialize_tucker( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> Tuple[ivy.Container, Sequence[ivy.Container]]: - """ - ivy.Container instance method variant of ivy.initialize_tucker. This method - simply wraps the function, and so the docstring for ivy.initialize_tucker also - applies to this method with minimal changes. + """ivy.Container instance method variant of ivy.initialize_tucker. This + method simply wraps the function, and so the docstring for + ivy.initialize_tucker also applies to this method with minimal changes. Parameters ---------- @@ -1641,10 +1612,9 @@ def static_partial_tucker( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> Tuple[ivy.Container, Sequence[ivy.Container]]: - """ - ivy.Container static method variant of ivy.partial_tucker. This method simply - wraps the function, and so the docstring for ivy.partial_tucker also applies to - this method with minimal changes. + """ivy.Container static method variant of ivy.partial_tucker. This + method simply wraps the function, and so the docstring for + ivy.partial_tucker also applies to this method with minimal changes. Parameters ---------- @@ -1719,10 +1689,9 @@ def partial_tucker( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> Tuple[ivy.Container, Sequence[ivy.Container]]: - """ - ivy.Container static method variant of ivy.partial_tucker. This method simply - wraps the function, and so the docstring for ivy.partial_tucker also applies to - this method with minimal changes. + """ivy.Container static method variant of ivy.partial_tucker. This + method simply wraps the function, and so the docstring for + ivy.partial_tucker also applies to this method with minimal changes. Parameters ---------- @@ -1797,10 +1766,9 @@ def static_tucker( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> Tuple[ivy.Container, Sequence[ivy.Container]]: - """ - ivy.Container static method variant of ivy.tucker. This method simply wraps the - function, and so the docstring for ivy.tucker also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.tucker. This method + simply wraps the function, and so the docstring for ivy.tucker also + applies to this method with minimal changes. Parameters ---------- @@ -1895,10 +1863,9 @@ def tucker( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> Tuple[ivy.Container, Sequence[ivy.Container]]: - """ - ivy.Container static method variant of ivy.tucker. This method simply wraps the - function, and so the docstring for ivy.tucker also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.tucker. This method + simply wraps the function, and so the docstring for ivy.tucker also + applies to this method with minimal changes. Parameters ---------- @@ -1982,10 +1949,9 @@ def static_dot( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> Union[ivy.Array, ivy.Container]: - """ - Compute the dot product between two arrays `a` and `b` using the current - backend's implementation. The dot product is defined as the sum of the element- - wise product of the input arrays. + """Compute the dot product between two arrays `a` and `b` using the + current backend's implementation. The dot product is defined as the sum + of the element- wise product of the input arrays. Parameters ---------- @@ -2048,10 +2014,9 @@ def dot( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> Union[ivy.Array, ivy.Container]: - """ - Compute the dot product between two arrays `a` and `b` using the current - backend's implementation. The dot product is defined as the sum of the element- - wise product of the input arrays. + """Compute the dot product between two arrays `a` and `b` using the + current backend's implementation. The dot product is defined as the sum + of the element- wise product of the input arrays. Parameters ---------- @@ -2113,10 +2078,10 @@ def static_tt_matrix_to_tensor( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.tt_matrix_to_tensor. This method - simply wraps the function, and so the docstring for ivy.tt_matrix_to_tensor also - applies to this method with minimal changes. + """ivy.Container static method variant of ivy.tt_matrix_to_tensor. This + method simply wraps the function, and so the docstring for + ivy.tt_matrix_to_tensor also applies to this method with minimal + changes. Parameters ---------- @@ -2180,10 +2145,10 @@ def tt_matrix_to_tensor( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.tt_matrix_to_tensor. This method - simply wraps the function, and so the docstring for ivy.tt_matrix_to_tensor also - applies to this method with minimal changes. + """ivy.Container instance method variant of ivy.tt_matrix_to_tensor. + This method simply wraps the function, and so the docstring for + ivy.tt_matrix_to_tensor also applies to this method with minimal + changes. Parameters ---------- @@ -2248,10 +2213,10 @@ def static_higher_order_moment( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.higher_order_moment. This method - simply wraps the function, and so the docstring for ivy.higher_order_moment also - applies to this method with minimal changes. + """ivy.Container static method variant of ivy.higher_order_moment. This + method simply wraps the function, and so the docstring for + ivy.higher_order_moment also applies to this method with minimal + changes. Parameters ---------- @@ -2290,10 +2255,10 @@ def higher_order_moment( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.higher_order_moment. This method - simply wraps the function, and so the docstring for ivy.higher_order_moment also - applies to this method with minimal changes. + """ivy.Container instance method variant of ivy.higher_order_moment. + This method simply wraps the function, and so the docstring for + ivy.higher_order_moment also applies to this method with minimal + changes. Parameters ---------- @@ -2343,10 +2308,9 @@ def static_batched_outer( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.batched_outer. This method simply - wraps the function, and so the docstring for ivy.batched_outer also applies to - this method with minimal changes. + """ivy.Container static method variant of ivy.batched_outer. This + method simply wraps the function, and so the docstring for + ivy.batched_outer also applies to this method with minimal changes. Parameters ---------- @@ -2403,10 +2367,9 @@ def batched_outer( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.batched_outer. This method simply - wraps the function, and so the docstring for ivy.batched_outer also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.batched_outer. This + method simply wraps the function, and so the docstring for + ivy.batched_outer also applies to this method with minimal changes. Parameters ---------- diff --git a/ivy/data_classes/container/experimental/losses.py b/ivy/data_classes/container/experimental/losses.py index e2bae0e848991..6247eb3a3dcf7 100644 --- a/ivy/data_classes/container/experimental/losses.py +++ b/ivy/data_classes/container/experimental/losses.py @@ -20,10 +20,9 @@ def _static_l1_loss( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.l1_loss. This method simply wraps the - function, and so the docstring for ivy.l1_loss also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.l1_loss. This method + simply wraps the function, and so the docstring for ivy.l1_loss also + applies to this method with minimal changes. Parameters ---------- @@ -103,10 +102,9 @@ def l1_loss( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.l1_loss. This method simply wraps - the function, and so the docstring for ivy.l1_loss also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.l1_loss. This method + simply wraps the function, and so the docstring for ivy.l1_loss also + applies to this method with minimal changes. Parameters ---------- @@ -145,7 +143,7 @@ def l1_loss( >>> z = x.l1_loss(y) >>> print(z) { - a: ivy.array(1.), + a: ivy.array(0.), b: ivy.array(0.) } """ @@ -175,10 +173,9 @@ def _static_log_poisson_loss( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.log_poisson_loss. This method simply - wraps the function, and so the docstring for ivy.log_poisson_loss also applies - to this method with minimal changes. + """ivy.Container static method variant of ivy.log_poisson_loss. This + method simply wraps the function, and so the docstring for + ivy.log_poisson_loss also applies to this method with minimal changes. Parameters ---------- @@ -269,10 +266,9 @@ def log_poisson_loss( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.log_poisson_loss. This method - simply wraps the function, and so the docstring for ivy.log_poisson_loss also - applies to this method with minimal changes. + """ivy.Container instance method variant of ivy.log_poisson_loss. This + method simply wraps the function, and so the docstring for + ivy.log_poisson_loss also applies to this method with minimal changes. Parameters ---------- @@ -318,8 +314,8 @@ def log_poisson_loss( >>> z = x.log_poisson_loss(y) >>> print(z) { - a: ivy.array(1.), - b: ivy.array(0.) + a: ivy.array(3.3890561), + b: ivy.array(123.413159) } """ return self._static_log_poisson_loss( @@ -349,10 +345,9 @@ def _static_smooth_l1_loss( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.smooth_l1_loss. This method simply - wraps the function, and so the docstring for ivy. smooth_l1_loss also applies to - this method with minimal changes. + """ivy.Container static method variant of ivy.smooth_l1_loss. This + method simply wraps the function, and so the docstring for ivy. + smooth_l1_loss also applies to this method with minimal changes. Parameters ---------- @@ -439,10 +434,9 @@ def smooth_l1_loss( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.smooth_l1_loss. This method simply - wraps the function, and so the docstring for ivy. smooth_l1_loss also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.smooth_l1_loss. This + method simply wraps the function, and so the docstring for ivy. + smooth_l1_loss also applies to this method with minimal changes. Parameters ---------- @@ -484,12 +478,12 @@ def smooth_l1_loss( -------- >>> x = ivy.Container(a=ivy.array([1, 0, 2]), b=ivy.array([3, 2, 1])) >>> y = ivy.Container(a=ivy.array([0.6, 0.2, 0.3]), - b=ivy.array([0.8, 0.2, 0.2])) + ... b=ivy.array([0.8, 0.2, 0.2])) >>> z = x.smooth_l1_loss(y) >>> print(z) { - a: ivy.array(0.9), - b: ivy.array(0.25) + a: ivy.array(0.43333333), + b: ivy.array(1.10666666) } """ return self._static_smooth_l1_loss( @@ -518,10 +512,9 @@ def _static_huber_loss( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of huber_loss. This method simply wraps the - function, and so the docstring for huber_loss also applies to this method with - minimal changes. + """ivy.Container static method variant of huber_loss. This method + simply wraps the function, and so the docstring for huber_loss also + applies to this method with minimal changes. Parameters ---------- @@ -608,10 +601,9 @@ def huber_loss( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of huber_loss. This method simply wraps - the function, and so the docstring for huber_loss also applies to this method - with minimal changes. + """ivy.Container instance method variant of huber_loss. This method + simply wraps the function, and so the docstring for huber_loss also + applies to this method with minimal changes. Parameters ---------- @@ -683,10 +675,9 @@ def _static_soft_margin_loss( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.soft_margin_loss. This method simply - wraps the function, and so the docstring for ivy.soft_margin_loss also applies - to this method with minimal changes. + """ivy.Container static method variant of ivy.soft_margin_loss. This + method simply wraps the function, and so the docstring for + ivy.soft_margin_loss also applies to this method with minimal changes. # Insert the docstring here @@ -742,10 +733,9 @@ def soft_margin_loss( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.soft_margin_loss. This method - simply wraps the function, and so the docstring for ivy.soft_margin_loss also - applies to this method with minimal changes. + """ivy.Container instance method variant of ivy.soft_margin_loss. This + method simply wraps the function, and so the docstring for + ivy.soft_margin_loss also applies to this method with minimal changes. # Insert the docstring here @@ -802,10 +792,9 @@ def _static_kl_div( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.kl_div. This method simply wraps the - function, and so the docstring for ivy.kl_div also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.kl_div. This method + simply wraps the function, and so the docstring for ivy.kl_div also + applies to this method with minimal changes. Parameters ---------- @@ -861,10 +850,9 @@ def kl_div( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.kl_div. This method simply wraps - the function, and so the docstring for ivy.kl_div also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.kl_div. This method + simply wraps the function, and so the docstring for ivy.kl_div also + applies to this method with minimal changes. Parameters ---------- @@ -920,10 +908,9 @@ def _static_poisson_nll_loss( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - r""" - ivy.Container static method variant of ivy.poisson_nll_loss. This method - simplywraps the function, and so the docstring for ivy.poisson_nll_loss also - applies to this method with minimal changes. + r"""ivy.Container static method variant of ivy.poisson_nll_loss. This + method simplywraps the function, and so the docstring for + ivy.poisson_nll_loss also applies to this method with minimal changes. Parameters ---------- @@ -1026,10 +1013,9 @@ def poisson_nll_loss( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - r""" - ivy.Container instance method variant of ivy.poisson_nll_loss. This method - simply wraps the function, and so the docstring for ivy. poisson_nll_loss also - applies to this method with minimal changes. + r"""ivy.Container instance method variant of ivy.poisson_nll_loss. This + method simply wraps the function, and so the docstring for ivy. + poisson_nll_loss also applies to this method with minimal changes. Parameters ---------- @@ -1103,3 +1089,186 @@ def poisson_nll_loss( prune_unapplied=prune_unapplied, map_sequences=map_sequences, ) + + @staticmethod + def _static_hinge_embedding_loss( + input: Union[ivy.Container, ivy.Array, ivy.NativeArray], + target: Union[ivy.Container, ivy.Array, ivy.NativeArray], + *, + margin: [Union[float, ivy.Container]] = 1.0, + reduction: [Union[str, ivy.Container]] = "mean", + key_chains: Optional[Union[List[str], Dict[str, str], ivy.Container]] = None, + to_apply: Union[bool, ivy.Container] = True, + prune_unapplied: Union[bool, ivy.Container] = False, + map_sequences: Union[bool, ivy.Container] = False, + ) -> ivy.Container: + r"""ivy.Container static method variant of ivy.hinge_embedding_loss. + This method simplywraps the function, and so the docstring for + ivy.hinge_embedding_loss also applies to this method with minimal + changes. + + Parameters + ---------- + input + input array or container containing input labels. + target + input array or container containing the target labels. + margin + Sets the hyperparameter margin. Determines the necessary input size + for hinge_embedding_loss calculations when label is -1. Inputs smaller + than the margin are minimized with hinge_embedding_loss. + Default is 1.0. + reduction + Specifies how to aggregate the loss across the batch. Options are: + - ``'none'``: Returns the unreduced loss. + - ``'mean'``: Returns the mean loss. + - ``'sum'``: Returns the summed loss. + Default is ``'mean'``. + key_chains + The key-chains to apply or not apply the method to. Default is ``None``. + to_apply + If input, the method will be applied to key_chains, otherwise key_chains + will be skipped. Default is ``input``. + prune_unapplied + Whether to prune key_chains for which the function was not applied. + Default is ``False``. + map_sequences + Whether to also map method to sequences (lists, tuples). + Default is ``False``. + + Shape + ----- + - Input: :math:`(*)` where :math:`*` means, any number of dimensions. \ + The sum operation operates over all the elements. + - Target: :math:`(*)`, same shape as the input + - Output: scalar. If :attr:`reduction` is ``'none'``, + then same shape as the input + + Returns + ------- + ret + Hinge embedding loss calculated from the input and label, + shaped based on the reduction method. + + Examples + -------- + With :class:`ivy.Container` inputs: + + >>> x = ivy.Container(a=ivy.array([[1, 0, 2]], dtype=ivy.float32), + ... b=ivy.array([[-1, 1, 1]], dtype=ivy.float32)) + >>> y = ivy.Container(a=ivy.array([[0.6, 0.2, 0.3]], dtype=ivy.float32), + ... b=ivy.array([[1, 1, 1]], dtype=ivy.float32)) + >>> z = ivy.Container._static_hinge_embedding_loss(x, y, reduction="none") + >>> z + { + a: ivy.array([[0., 0., 0.]]), + b: ivy.array([[-1., 1., 1.]]) + } + + With a mix of :class:`ivy.Array` and :class:`ivy.Container` inputs: + + >>> x = ivy.array([[10, 20, 32]], dtype=ivy.float32) + >>> y = ivy.Container(a=ivy.array([[-1, -1, -1]], dtype=ivy.float32), + ... b=ivy.array([[1, 1, 1]], dtype=ivy.float32)) + >>> z = ivy.Container._static_hinge_embedding_loss(x, y, + ... reduction="sum", margin=2.0) + >>> z + { + a: ivy.array(0.), + b: ivy.array(62.) + } + """ + return ContainerBase.cont_multi_map_in_function( + "hinge_embedding_loss", + input, + target, + margin=margin, + reduction=reduction, + key_chains=key_chains, + to_apply=to_apply, + prune_unapplied=prune_unapplied, + map_sequences=map_sequences, + ) + + def hinge_embedding_loss( + self: Union[ivy.Container, ivy.Array, ivy.NativeArray], + target: Union[ivy.Container, ivy.Array, ivy.NativeArray], + *, + margin: [Union[float, ivy.Container]] = 1.0, + reduction: [Union[str, ivy.Container]] = "mean", + key_chains: Optional[Union[List[str], Dict[str, str], ivy.Container]] = None, + to_apply: Union[bool, ivy.Container] = True, + prune_unapplied: Union[bool, ivy.Container] = False, + map_sequences: Union[bool, ivy.Container] = False, + ) -> ivy.Container: + r"""ivy.Container instance method variant of ivy.hinge_embedding_loss. + This method simply wraps the function, and so the docstring for + ivy.hinge_embedding_loss also applies to this method with minimal + changes. + + Parameters + ---------- + input + input array or container containing input labels. + target + input array or container containing the target labels. + margin + Sets the hyperparameter margin. Determines the necessary input size + for hinge_embedding_loss calculations when label is -1. Inputs smaller + than the margin are minimized with hinge_embedding_loss. + Default is 1.0. + reduction + Specifies how to aggregate the loss across the batch. Options are: + - ``'none'``: Returns the unreduced loss. + - ``'mean'``: Returns the mean loss. + - ``'sum'``: Returns the summed loss. + Default is ``'mean'``. + key_chains + The key-chains to apply or not apply the method to. Default is ``None``. + to_apply + If input, the method will be applied to key_chains, otherwise key_chains + will be skipped. Default is ``input``. + prune_unapplied + Whether to prune key_chains for which the function was not applied. + Default is ``False``. + map_sequences + Whether to also map method to sequences (lists, tuples). + Default is ``False``. + + Shape + ----- + - Input: :math:`(*)` where :math:`*` means, any number of dimensions. \ + The sum operation operates over all the elements. + - Target: :math:`(*)`, same shape as the input + - Output: scalar. If :attr:`reduction` is ``'none'``, + then same shape as the input + + Returns + ------- + ret + Hinge embedding loss calculated from the input and label, + shaped based on the reduction method. + + + Examples + -------- + >>> x = ivy.Container(a=ivy.array([[1, 0, 2]], dtype=ivy.float32), + ... b=ivy.array([[3, 2, 1]], dtype=ivy.float32)) + >>> y = ivy.Container(a=ivy.array([[-1, -1, -1]], dtype=ivy.float32), + ... b=ivy.array([[1, 1, 1]], dtype=ivy.float32)) + >>> x.hinge_embedding_loss(y, reduction="none", margin=0.5) + { + a: ivy.array([[0., 0.5, 0.]]), + b: ivy.array([[3., 2., 1.]]) + } + """ + return self._static_hinge_embedding_loss( + self, + target, + margin=margin, + reduction=reduction, + key_chains=key_chains, + to_apply=to_apply, + prune_unapplied=prune_unapplied, + map_sequences=map_sequences, + ) diff --git a/ivy/data_classes/container/experimental/manipulation.py b/ivy/data_classes/container/experimental/manipulation.py index 0621ae4be3267..0c54a775d5a43 100644 --- a/ivy/data_classes/container/experimental/manipulation.py +++ b/ivy/data_classes/container/experimental/manipulation.py @@ -33,10 +33,9 @@ def static_moveaxis( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.moveaxis. This method simply wraps - the function, and so the docstring for ivy.moveaxis also applies to this method - with minimal changes. + """ivy.Container static method variant of ivy.moveaxis. This method + simply wraps the function, and so the docstring for ivy.moveaxis also + applies to this method with minimal changes. Parameters ---------- @@ -94,10 +93,9 @@ def moveaxis( copy: Optional[Union[bool, ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.moveaxis. This method simply wraps - the function, and so the docstring for ivy.flatten also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.moveaxis. This method + simply wraps the function, and so the docstring for ivy.flatten also + applies to this method with minimal changes. Parameters ---------- @@ -147,10 +145,9 @@ def static_heaviside( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.heaviside. This method simply wraps - the function, and so the docstring for ivy.heaviside also applies to this method - with minimal changes. + """ivy.Container static method variant of ivy.heaviside. This method + simply wraps the function, and so the docstring for ivy.heaviside also + applies to this method with minimal changes. Parameters ---------- @@ -195,10 +192,9 @@ def heaviside( *, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.heaviside. This method simply wraps - the function, and so the docstring for ivy.heaviside also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.heaviside. This method + simply wraps the function, and so the docstring for ivy.heaviside also + applies to this method with minimal changes. Parameters ---------- @@ -239,10 +235,9 @@ def static_flipud( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.flipud. This method simply wraps the - function, and so the docstring for ivy.flipud also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.flipud. This method + simply wraps the function, and so the docstring for ivy.flipud also + applies to this method with minimal changes. Parameters ---------- @@ -297,10 +292,9 @@ def flipud( copy: Optional[Union[bool, ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.flipud. This method simply wraps - the function, and so the docstring for ivy.flipud also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.flipud. This method + simply wraps the function, and so the docstring for ivy.flipud also + applies to this method with minimal changes. Parameters ---------- @@ -353,10 +347,9 @@ def vstack( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.stack. This method simply wraps the - function, and so the docstring for ivy.stack also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.stack. This method + simply wraps the function, and so the docstring for ivy.stack also + applies to this method with minimal changes. Examples -------- @@ -397,10 +390,9 @@ def static_vstack( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.stack. This method simply wraps the - function, and so the docstring for ivy.vstack also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.stack. This method simply + wraps the function, and so the docstring for ivy.vstack also applies to + this method with minimal changes. Examples -------- @@ -442,10 +434,9 @@ def hstack( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.hstack. This method simply wraps - the function, and so the docstring for ivy.hstack also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.hstack. This method + simply wraps the function, and so the docstring for ivy.hstack also + applies to this method with minimal changes. Examples -------- @@ -484,10 +475,9 @@ def static_hstack( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.hstack. This method simply wraps the - function, and so the docstring for ivy.hstack also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.hstack. This method + simply wraps the function, and so the docstring for ivy.hstack also + applies to this method with minimal changes. Examples -------- @@ -522,10 +512,9 @@ def static_rot90( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.rot90. This method simply wraps the - function, and so the docstring for ivy.rot90 also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.rot90. This method simply + wraps the function, and so the docstring for ivy.rot90 also applies to + this method with minimal changes. Parameters ---------- @@ -597,10 +586,9 @@ def rot90( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.rot90. This method simply wraps the - function, and so the docstring for ivy.rot90 also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.rot90. This method simply + wraps the function, and so the docstring for ivy.rot90 also applies to + this method with minimal changes. Parameters ---------- @@ -672,10 +660,9 @@ def static_top_k( map_sequences: Union[bool, ivy.Container] = False, out: Optional[Union[Tuple[ivy.Container, ivy.Container], ivy.Container]] = None, ) -> Tuple[ivy.Container, ivy.Container]: - """ - ivy.Container static method variant of ivy.top_k. This method simply wraps the - function, and so the docstring for ivy.top_k also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.top_k. This method simply + wraps the function, and so the docstring for ivy.top_k also applies to + this method with minimal changes. Parameters ---------- @@ -755,10 +742,9 @@ def top_k( map_sequences: Union[bool, ivy.Container] = False, out: Optional[Tuple[ivy.Container, ivy.Container]] = None, ) -> Tuple[ivy.Container, ivy.Container]: - """ - ivy.Container instance method variant of ivy.top_k. This method simply wraps the - function, and so the docstring for ivy.top_k also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.top_k. This method + simply wraps the function, and so the docstring for ivy.top_k also + applies to this method with minimal changes. Parameters ---------- @@ -832,10 +818,9 @@ def static_fliplr( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.fliplr. This method simply wraps the - function, and so the docstring for ivy.fliplr also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.fliplr. This method + simply wraps the function, and so the docstring for ivy.fliplr also + applies to this method with minimal changes. Parameters ---------- @@ -900,10 +885,9 @@ def fliplr( copy: Optional[Union[bool, ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.fliplr. This method simply wraps - the function, and so the docstring for ivy.fliplr also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.fliplr. This method + simply wraps the function, and so the docstring for ivy.fliplr also + applies to this method with minimal changes. Parameters ---------- @@ -953,10 +937,9 @@ def static_i0( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.i0. This method simply wraps the - function, and so the docstring for ivy.i0 also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.i0. This method simply + wraps the function, and so the docstring for ivy.i0 also applies to + this method with minimal changes. Parameters ---------- @@ -998,10 +981,9 @@ def i0( *, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.i0. This method simply wraps the - function, and so the docstring for ivy.i0 also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.i0. This method simply + wraps the function, and so the docstring for ivy.i0 also applies to + this method with minimal changes. Parameters ---------- @@ -1044,10 +1026,9 @@ def static_flatten( order: Union[str, ivy.Container] = "C", out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.flatten. This method simply wraps the - function, and so the docstring for ivy.flatten also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.flatten. This method + simply wraps the function, and so the docstring for ivy.flatten also + applies to this method with minimal changes. Parameters ---------- @@ -1124,10 +1105,9 @@ def flatten( order: Union[str, ivy.Container] = "C", out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.flatten. This method simply wraps - the function, and so the docstring for ivy.flatten also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.flatten. This method + simply wraps the function, and so the docstring for ivy.flatten also + applies to this method with minimal changes. Parameters ---------- @@ -1220,8 +1200,7 @@ def static_pad( out: Optional[ivy.Container] = None, **kwargs: Optional[Union[Any, ivy.Container]], ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.pad. + """ivy.Container static method variant of ivy.pad. This method simply wraps the function, and so the docstring for ivy.pad also applies to this method with minimal changes. @@ -1277,8 +1256,7 @@ def pad( out: Optional[ivy.Container] = None, **kwargs: Optional[Union[Any, ivy.Container]], ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.pad. + """ivy.Container instance method variant of ivy.pad. This method simply wraps the function, and so the docstring for ivy.pad also applies to this method with minimal changes. @@ -1313,10 +1291,9 @@ def static_vsplit( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> List[ivy.Container]: - """ - ivy.Container static method variant of ivy.vsplit. This method simply wraps the - function, and so the docstring for ivy.vsplit also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.vsplit. This method + simply wraps the function, and so the docstring for ivy.vsplit also + applies to this method with minimal changes. Parameters ---------- @@ -1399,10 +1376,9 @@ def vsplit( *, copy: Optional[Union[bool, ivy.Container]] = None, ) -> List[ivy.Container]: - """ - ivy.Container instance method variant of ivy.vsplit. This method simply wraps - the function, and so the docstring for ivy.vsplit also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.vsplit. This method + simply wraps the function, and so the docstring for ivy.vsplit also + applies to this method with minimal changes. Parameters ---------- @@ -1471,10 +1447,9 @@ def static_dsplit( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> List[ivy.Container]: - """ - ivy.Container static method variant of ivy.dsplit. This method simply wraps the - function, and so the docstring for ivy.dsplit also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.dsplit. This method + simply wraps the function, and so the docstring for ivy.dsplit also + applies to this method with minimal changes. Parameters ---------- @@ -1555,10 +1530,9 @@ def dsplit( *, copy: Optional[Union[bool, ivy.Container]] = None, ) -> List[ivy.Container]: - """ - ivy.Container instance method variant of ivy.dsplit. This method simply wraps - the function, and so the docstring for ivy.dsplit also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.dsplit. This method + simply wraps the function, and so the docstring for ivy.dsplit also + applies to this method with minimal changes. Parameters ---------- @@ -1620,10 +1594,9 @@ def static_atleast_1d( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> List[ivy.Container]: - """ - ivy.Container static method variant of ivy.atleast_1d. This method simply wraps - the function, and so the docstring for ivy.atleast_1d also applies to this - method with minimal changes. + """ivy.Container static method variant of ivy.atleast_1d. This method + simply wraps the function, and so the docstring for ivy.atleast_1d also + applies to this method with minimal changes. Parameters ---------- @@ -1684,10 +1657,9 @@ def atleast_1d( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> List[ivy.Container]: - """ - ivy.Container instance method variant of ivy.atleast_1d. This method simply - wraps the function, and so the docstring for ivy.atleast_1d also applies to this - method with minimal changes. + """ivy.Container instance method variant of ivy.atleast_1d. This method + simply wraps the function, and so the docstring for ivy.atleast_1d also + applies to this method with minimal changes. Parameters ---------- @@ -1761,10 +1733,9 @@ def dstack( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.stack. This method simply wraps the - function, and so the docstring for ivy.stack also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.stack. This method + simply wraps the function, and so the docstring for ivy.stack also + applies to this method with minimal changes. Examples -------- @@ -1805,10 +1776,9 @@ def static_dstack( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.stack. This method simply wraps the - function, and so the docstring for ivy.dstack also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.stack. This method simply + wraps the function, and so the docstring for ivy.dstack also applies to + this method with minimal changes. Examples -------- @@ -1842,10 +1812,9 @@ def static_atleast_2d( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> List[ivy.Container]: - """ - ivy.Container static method variant of ivy.atleast_2d. This method simply wraps - the function, and so the docstring for ivy.atleast_2d also applies to this - method with minimal changes. + """ivy.Container static method variant of ivy.atleast_2d. This method + simply wraps the function, and so the docstring for ivy.atleast_2d also + applies to this method with minimal changes. Parameters ---------- @@ -1906,10 +1875,9 @@ def atleast_2d( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> List[ivy.Container]: - """ - ivy.Container instance method variant of ivy.atleast_2d. This method simply - wraps the function, and so the docstring for ivy.atleast_2d also applies to this - method with minimal changes. + """ivy.Container instance method variant of ivy.atleast_2d. This method + simply wraps the function, and so the docstring for ivy.atleast_2d also + applies to this method with minimal changes. Parameters ---------- @@ -1978,10 +1946,9 @@ def static_atleast_3d( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> List[ivy.Container]: - """ - ivy.Container static method variant of ivy.atleast_3d. This method simply wraps - the function, and so the docstring for ivy.atleast_3d also applies to this - method with minimal changes. + """ivy.Container static method variant of ivy.atleast_3d. This method + simply wraps the function, and so the docstring for ivy.atleast_3d also + applies to this method with minimal changes. Parameters ---------- @@ -2046,10 +2013,9 @@ def atleast_3d( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> List[ivy.Container]: - """ - ivy.Container instance method variant of ivy.atleast_3d. This method simply - wraps the function, and so the docstring for ivy.atleast_3d also applies to this - method with minimal changes. + """ivy.Container instance method variant of ivy.atleast_3d. This method + simply wraps the function, and so the docstring for ivy.atleast_3d also + applies to this method with minimal changes. Parameters ---------- @@ -2118,10 +2084,9 @@ def static_take_along_axis( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.take_along_axis. This method simply - wraps the function, and so the docstring for ivy.take_along_axis also applies to - this method with minimal changes. + """ivy.Container static method variant of ivy.take_along_axis. This + method simply wraps the function, and so the docstring for + ivy.take_along_axis also applies to this method with minimal changes. Parameters ---------- @@ -2192,10 +2157,9 @@ def take_along_axis( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.take_along_axis. This method simply - wraps the function, and so the docstring for ivy.take_along_axis also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.take_along_axis. This + method simply wraps the function, and so the docstring for + ivy.take_along_axis also applies to this method with minimal changes. Parameters ---------- @@ -2268,10 +2232,9 @@ def static_hsplit( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> List[ivy.Container]: - """ - ivy.Container static method variant of ivy.hsplit. This method simply wraps the - function, and so the docstring for ivy.hsplit also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.hsplit. This method + simply wraps the function, and so the docstring for ivy.hsplit also + applies to this method with minimal changes. Parameters ---------- @@ -2345,10 +2308,9 @@ def hsplit( copy: Optional[Union[bool, ivy.Container]] = None, /, ) -> List[ivy.Container]: - """ - ivy.Container instance method variant of ivy.hsplit. This method simply wraps - the function, and so the docstring for ivy.hsplit also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.hsplit. This method + simply wraps the function, and so the docstring for ivy.hsplit also + applies to this method with minimal changes. Parameters ---------- @@ -2405,10 +2367,9 @@ def static_broadcast_shapes( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.broadcast_shapes. This method simply - wraps the function, and so the docstring for ivy.hsplit also applies to this - method with minimal changes. + """ivy.Container static method variant of ivy.broadcast_shapes. This + method simply wraps the function, and so the docstring for ivy.hsplit + also applies to this method with minimal changes. Parameters ---------- @@ -2462,10 +2423,9 @@ def broadcast_shapes( *, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.broadcast_shapes. This method - simply wraps the function, and so the docstring for ivy.broadcast_shapes also - applies to this method with minimal changes. + """ivy.Container instance method variant of ivy.broadcast_shapes. This + method simply wraps the function, and so the docstring for + ivy.broadcast_shapes also applies to this method with minimal changes. Parameters ---------- @@ -2602,10 +2562,9 @@ def static_as_strided( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.as_strided. This method simply - wraps the function, and so the docstring for ivy.as_strided also applies to this - method with minimal changes. + """ivy.Container instance method variant of ivy.as_strided. This method + simply wraps the function, and so the docstring for ivy.as_strided also + applies to this method with minimal changes. Parameters ---------- @@ -2649,10 +2608,9 @@ def as_strided( strides: Union[Sequence[int], ivy.Container], /, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.as_strided. This method simply - wraps the function, and so the docstring for ivy.as_strided also applies to this - method with minimal changes. + """ivy.Container instance method variant of ivy.as_strided. This method + simply wraps the function, and so the docstring for ivy.as_strided also + applies to this method with minimal changes. Parameters ---------- @@ -2686,10 +2644,10 @@ def static_concat_from_sequence( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.concat_from_sequence. This method - simply wraps the function, and so the docstring for ivy.concat_from_sequence - also applies to this method with minimal changes. + """ivy.Container static method variant of ivy.concat_from_sequence. + This method simply wraps the function, and so the docstring for + ivy.concat_from_sequence also applies to this method with minimal + changes. Parameters ---------- @@ -2790,10 +2748,9 @@ def concat_from_sequence( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.stack. This method simply wraps the - function, and so the docstring for ivy.stack also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.stack. This method + simply wraps the function, and so the docstring for ivy.stack also + applies to this method with minimal changes. Parameters ---------- @@ -2871,10 +2828,9 @@ def associative_scan( reverse: Union[bool, ivy.Container] = False, axis: Union[int, ivy.Container] = 0, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.associative_scan. This method - simply wraps the function, and so the docstring for ivy.associative_scan also - applies to this method with minimal changes. + """ivy.Container instance method variant of ivy.associative_scan. This + method simply wraps the function, and so the docstring for + ivy.associative_scan also applies to this method with minimal changes. Parameters ---------- @@ -2905,8 +2861,7 @@ def _static_unique_consecutive( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.unique_consecutive. + """ivy.Container static method variant of ivy.unique_consecutive. This method simply wraps the function, and so the docstring for ivy.unique_consecutive also applies to this method with minimal @@ -2932,8 +2887,7 @@ def unique_consecutive( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.unique_consecutive. + """ivy.Container instance method variant of ivy.unique_consecutive. This method simply wraps the function, and so the docstring for ivy.unique_consecutive also applies to this method with minimal @@ -2956,8 +2910,7 @@ def _static_fill_diagonal( *, wrap: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.fill_diagonal. + """ivy.Container static method variant of ivy.fill_diagonal. This method simply wraps the function, and so the docstring for ivy.fill_diagonal also applies to this method with minimal @@ -2977,8 +2930,7 @@ def fill_diagonal( *, wrap: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.fill_diagonal. + """ivy.Container instance method variant of ivy.fill_diagonal. This method simply wraps the function, and so the docstring for ivy.fill_diagonal also applies to this method with minimal @@ -3002,8 +2954,7 @@ def static_unfold( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.unfold. + """ivy.Container static method variant of ivy.unfold. This method simply wraps the function, and so the docstring for ivy.unfold also applies to this method with minimal @@ -3042,8 +2993,7 @@ def unfold( *, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.unfold. + """ivy.Container instance method variant of ivy.unfold. This method simply wraps the function, and so the docstring for ivy.unfold also applies to this method with minimal @@ -3079,8 +3029,7 @@ def static_fold( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.fold. + """ivy.Container static method variant of ivy.fold. This method simply wraps the function, and so the docstring for ivy.fold also applies to this method with minimal @@ -3121,8 +3070,7 @@ def fold( *, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.fold. + """ivy.Container instance method variant of ivy.fold. This method simply wraps the function, and so the docstring for ivy.fold also applies to this method with minimal @@ -3161,8 +3109,7 @@ def static_partial_unfold( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.partial_unfold. + """ivy.Container static method variant of ivy.partial_unfold. This method simply wraps the function, and so the docstring for ivy.partial_unfold also applies to this method with minimal @@ -3213,8 +3160,7 @@ def partial_unfold( *, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.partial_unfold. + """ivy.Container instance method variant of ivy.partial_unfold. This method simply wraps the function, and so the docstring for ivy.partial_unfold also applies to this method with minimal @@ -3259,8 +3205,7 @@ def static_partial_fold( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.partial_fold. + """ivy.Container static method variant of ivy.partial_fold. This method simply wraps the function, and so the docstring for ivy.partial_fold also applies to this method with minimal @@ -3311,8 +3256,7 @@ def partial_fold( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.partial_fold. + """ivy.Container instance method variant of ivy.partial_fold. This method simply wraps the function, and so the docstring for ivy.partial_fold also applies to this method with minimal @@ -3352,8 +3296,7 @@ def static_partial_tensor_to_vec( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.partial_tensor_to_vec. + """ivy.Container static method variant of ivy.partial_tensor_to_vec. This method simply wraps the function, and so the docstring for ivy.partial_tensor_to_vec also applies to this method with minimal @@ -3401,8 +3344,7 @@ def partial_tensor_to_vec( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.partial_tensor_to_vec. + """ivy.Container instance method variant of ivy.partial_tensor_to_vec. This method simply wraps the function, and so the docstring for ivy.partial_tensor_to_vec also applies to this method with minimal @@ -3440,8 +3382,7 @@ def static_partial_vec_to_tensor( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.partial_vec_to_tensor. + """ivy.Container static method variant of ivy.partial_vec_to_tensor. This method simply wraps the function, and so the docstring for ivy.partial_vec_to_tensor also applies to this method with minimal @@ -3487,8 +3428,7 @@ def partial_vec_to_tensor( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.partial_vec_to_tensor. + """ivy.Container instance method variant of ivy.partial_vec_to_tensor. This method simply wraps the function, and so the docstring for ivy.partial_vec_to_tensor also applies to this method with minimal @@ -3526,8 +3466,7 @@ def static_matricize( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.matricize. + """ivy.Container static method variant of ivy.matricize. This method simply wraps the function, and so the docstring for ivy.matricize also applies to this method with minimal @@ -3573,8 +3512,7 @@ def matricize( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.matricize. + """ivy.Container instance method variant of ivy.matricize. This method simply wraps the function, and so the docstring for ivy.matricize also applies to this method with minimal @@ -3609,8 +3547,7 @@ def static_soft_thresholding( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.soft_thresholding. + """ivy.Container static method variant of ivy.soft_thresholding. This method simply wraps the function, and so the docstring for ivy.soft_thresholding also applies to this method with minimal @@ -3654,8 +3591,7 @@ def soft_thresholding( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.soft_thresholding. + """ivy.Container instance method variant of ivy.soft_thresholding. This method simply wraps the function, and so the docstring for ivy.soft_thresholding also applies to this method with minimal @@ -3690,8 +3626,7 @@ def static_column_stack( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.column_stack. + """ivy.Container static method variant of ivy.column_stack. This method simply wraps the function, and so the docstring for ivy.column_stack also applies to this method with minimal @@ -3742,8 +3677,7 @@ def column_stack( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.column_stack. + """ivy.Container instance method variant of ivy.column_stack. This method simply wraps the function, and so the docstring for ivy.column_stack also applies to this method with minimal @@ -3803,8 +3737,7 @@ def _static_put_along_axis( map_sequences: bool = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.put_along_axis. + """ivy.Container static method variant of ivy.put_along_axis. This method simply wraps the function, and so the docstring for ivy.put_along_axis also applies to this method with minimal @@ -3840,8 +3773,7 @@ def put_along_axis( map_sequences: bool = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.put_along_axis. + """ivy.Container instance method variant of ivy.put_along_axis. This method simply wraps the function, and so the docstring for ivy.put_along_axis also applies to this method with minimal @@ -3875,8 +3807,7 @@ def _static_take( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.take. + """ivy.Container static method variant of ivy.take. This method simply wraps the function, and so the docstring for ivy.take also applies to this method with minimal changes. @@ -3976,8 +3907,7 @@ def take( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.take. + """ivy.Container instance method variant of ivy.take. This method simply wraps the function, and so the docstring for ivy.take also applies to this method with minimal changes. @@ -4069,10 +3999,9 @@ def _static_trim_zeros( *, trim: Optional[str] = "fb", ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.trim_zeros. This method simply wraps - the function, and so the docstring for ivy.trim_zeros also applies to this - method with minimal changes. + """ivy.Container static method variant of ivy.trim_zeros. This method + simply wraps the function, and so the docstring for ivy.trim_zeros also + applies to this method with minimal changes. Parameters ---------- @@ -4106,10 +4035,9 @@ def trim_zeros( *, trim: Optional[str] = "fb", ) -> ivy.Array: - """ - ivy.Container instance method variant of ivy.trim_zeros. This method simply - wraps the function, and so the docstring for ivy.trim_zeros also applies to this - method with minimal changes. + """ivy.Container instance method variant of ivy.trim_zeros. This method + simply wraps the function, and so the docstring for ivy.trim_zeros also + applies to this method with minimal changes. Parameters ---------- @@ -4137,6 +4065,180 @@ def trim_zeros( """ return self._static_trim_zeros(self, trim=trim) + @staticmethod + def _static_unflatten( + x: Union[int, ivy.Array, ivy.NativeArray, ivy.Container], + /, + shape: Union[Tuple[int], ivy.Array, ivy.NativeArray, ivy.Container], + dim: Optional[Union[int, ivy.Container]] = 0, + *, + out: Optional[Union[ivy.Array, ivy.Container]] = None, + key_chains: Optional[Union[List[str], Dict[str, str], ivy.Container]] = None, + to_apply: Union[bool, ivy.Container] = True, + prune_unapplied: Union[bool, ivy.Container] = False, + map_sequences: Union[bool, ivy.Container] = False, + ) -> ivy.Container: + """ivy.Container static method variant of ivy.unflatten. This method + simply wraps the function, and so the docstring for ivy.unflatten also + applies to this method with minimal changes. + + Parameters + ---------- + x + input array + shape + array indices. Must have an integer data type. + dim + axis over which to select values. If `axis` is negative, + the function must determine the axis along which to select values + by counting from the last dimension. + By default, the flattened input array is used. + out + optional output array, for writing the result to. It must + have a shape that the inputs broadcast to. + key_chains + The key-chains to apply or not apply the method to. + Default is ``None``. + to_apply + If True, the method will be applied to key_chains, + otherwise key_chains will be skipped. Default is ``True``. + prune_unapplied + Whether to prune key_chains for which the function was + not applied. Default is ``False``. + map_sequences + Whether to also map method to sequences (lists, tuples). + Default is ``False``. + + Returns + ------- + ret + an array having the same data type as `x`. + The output array must have the same rank + (i.e., number of dimensions) as `x` and + must have the same shape as `x`, + except for the axis specified by `axis` + whose size must equal the number of elements in `indices`. + + + Examples + -------- + With 'ivy.Container' input: + + >>> x = ivy.Container(a = ivy.array([[True, False, False, True], + [False, True, False, True]])), + ... b = ivy.array([[1.2, 2.3, 3.4, 4.5], + [5.6, 6.7, 7.8, 8.9]]), + ... c = ivy.array([[1, 2, 3, 4], + [5, 6, 7, 8]])) + >>> dim = 1 + >>> shape = (2, 2) + >>> y = ivy.Container._static_unflatten(x, shape=shape, dim=dim) + >>> print(y) + { + a: ivy.array([[[True, False], [False, True]], + [[False, True], [False, True]]]) + b: ivy.array([[[1.2, 2.3], [3.4, 4.5]], [[5.6, 6.7], [7.8, 8.9]]]) + c: ivy.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]]) + } + """ + return ContainerBase.cont_multi_map_in_function( + "unflatten", + x, + shape=shape, + dim=dim, + out=out, + key_chains=key_chains, + to_apply=to_apply, + prune_unapplied=prune_unapplied, + map_sequences=map_sequences, + ) + + def unflatten( + self: ivy.Container, + /, + shape: Union[Tuple[int], ivy.Array, ivy.NativeArray, ivy.Container], + dim: Optional[Union[int, ivy.Container]] = 0, + *, + out: Optional[Union[ivy.Array, ivy.Container]] = None, + key_chains: Optional[Union[List[str], Dict[str, str], ivy.Container]] = None, + to_apply: Union[bool, ivy.Container] = True, + prune_unapplied: Union[bool, ivy.Container] = False, + map_sequences: Union[bool, ivy.Container] = False, + ) -> ivy.Container: + """ivy.Container instance method variant of ivy.unflatten. This method + simply wraps the function, and so the docstring for ivy.unflatten also + applies to this method with minimal changes. + + Parameters + ---------- + self + input array + shape + array indices. Must have an integer data type. + dim + axis over which to unflatten. If `axis` is negative, + the function must determine the axis along which to select values + by counting from the last dimension. + By default, the flattened input array is used. + out + optional output array, for writing the result to. It must + have a shape that the inputs broadcast to. + key_chains + The key-chains to apply or not apply the method to. + Default is ``None``. + to_apply + If True, the method will be applied to key_chains, + otherwise key_chains will be skipped. Default is ``True``. + prune_unapplied + Whether to prune key_chains for which the function was + not applied. Default is ``False``. + map_sequences + Whether to also map method to sequences (lists, tuples). + Default is ``False``. + + Returns + ------- + ret + an array having the same data type as `x`. + The output array must have the same rank + (i.e., number of dimensions) as `x` and + must have the same shape as `x`, + except for the axis specified by `dim` + which is replaced with a tuple specified in `shape`. + + + Examples + -------- + With 'ivy.Container' input: + + >>> x = ivy.Container(a = ivy.array([[True, False, False, True], + ... [False, True, False, True]]), + ... b = ivy.array([[1.2, 2.3, 3.4, 4.5], + ... [5.6, 6.7, 7.8, 8.9]]), + ... c = ivy.array([[1, 2, 3, 4], + ... [5, 6, 7, 8]])) + >>> dim = 1 + >>> shape = (2, 2) + >>> y = x.unflatten(shape=shape, dim=dim) + >>> print(y) + { + a: ivy.array([[[True, False], [False, True]], + [[False, True], [False, True]]]), + b: ivy.array([[[1.2, 2.3], [3.4, 4.5]], [[5.6, 6.7], [7.8, 8.9]]]), + c: ivy.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]]) + } + """ + return self._static_unflatten( + self, + shape=shape, + dim=dim, + out=out, + key_chains=key_chains, + to_apply=to_apply, + prune_unapplied=prune_unapplied, + map_sequences=map_sequences, + ) + def concat_from_sequence( self: ivy.Container, @@ -4154,10 +4256,9 @@ def concat_from_sequence( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.stack. This method simply wraps the - function, and so the docstring for ivy.stack also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.stack. This method simply + wraps the function, and so the docstring for ivy.stack also applies to this + method with minimal changes. Parameters ---------- @@ -4203,11 +4304,11 @@ def concat_from_sequence( >>> print(z) { 'a': ivy.array([[[0, 1], - [3, 2]], - [[2, 3], - [1, 0]]]), + [3, 2]], + [[2, 3], + [1, 0]]]), 'b': ivy.array([[[4, 5], - [1, 0]]]) + [1, 0]]]) } """ new_input_sequence = ( diff --git a/ivy/data_classes/container/experimental/norms.py b/ivy/data_classes/container/experimental/norms.py index aab171d3242df..72d8e3d7485da 100644 --- a/ivy/data_classes/container/experimental/norms.py +++ b/ivy/data_classes/container/experimental/norms.py @@ -14,10 +14,9 @@ def static_l1_normalize( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.l1_normalize. This method simply - wraps the function, and so the docstring for ivy.l1_normalize also applies to - this method with minimal changes. + """ivy.Container static method variant of ivy.l1_normalize. This method + simply wraps the function, and so the docstring for ivy.l1_normalize + also applies to this method with minimal changes. Parameters ---------- @@ -78,10 +77,9 @@ def l1_normalize( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.l1_normalize. This method simply - wraps the function, and so the docstring for ivy.l1_normalize also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.l1_normalize. This + method simply wraps the function, and so the docstring for + ivy.l1_normalize also applies to this method with minimal changes. Parameters ---------- @@ -129,10 +127,9 @@ def static_l2_normalize( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.l2_normalize. This method simply - wraps the function, and so the docstring for ivy.l2_normalize also applies to - this method with minimal changes. + """ivy.Container static method variant of ivy.l2_normalize. This method + simply wraps the function, and so the docstring for ivy.l2_normalize + also applies to this method with minimal changes. Parameters ---------- @@ -193,10 +190,9 @@ def l2_normalize( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.l2_normalize. This method simply - wraps the function, and so the docstring for ivy.l2_normalize also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.l2_normalize. This + method simply wraps the function, and so the docstring for + ivy.l2_normalize also applies to this method with minimal changes. Parameters ---------- @@ -272,10 +268,9 @@ def static_batch_norm( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> Tuple[ivy.Container, ivy.Container, ivy.Container]: - """ - ivy.Container static method variant of ivy.batch_norm. This method simply wraps - the function, and so the docstring for ivy.batch_norm also applies to this - method with minimal changes. + """ivy.Container static method variant of ivy.batch_norm. This method + simply wraps the function, and so the docstring for ivy.batch_norm also + applies to this method with minimal changes. Parameters ---------- @@ -369,10 +364,9 @@ def batch_norm( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> Tuple[ivy.Container, ivy.Container, ivy.Container]: - """ - ivy.Container instance method variant of ivy.batch_norm. This method simply - wraps the function, and so the docstring for ivy.batch_norm also applies to this - method with minimal changes. + """ivy.Container instance method variant of ivy.batch_norm. This method + simply wraps the function, and so the docstring for ivy.batch_norm also + applies to this method with minimal changes. Parameters ---------- @@ -466,10 +460,9 @@ def static_instance_norm( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> Tuple[ivy.Container, ivy.Container, ivy.Container]: - """ - ivy.Container static method variant of ivy.instance_norm. This method simply - wraps the function, and so the docstring for ivy.instance_norm also applies to - this method with minimal changes. + """ivy.Container static method variant of ivy.instance_norm. This + method simply wraps the function, and so the docstring for + ivy.instance_norm also applies to this method with minimal changes. Parameters ---------- @@ -561,10 +554,9 @@ def instance_norm( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> Tuple[ivy.Container, ivy.Container, ivy.Container]: - """ - ivy.Container instance method variant of ivy.instance_norm. This method simply - wraps the function, and so the docstring for ivy.instance_norm also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.instance_norm. This + method simply wraps the function, and so the docstring for + ivy.instance_norm also applies to this method with minimal changes. Parameters ---------- @@ -647,10 +639,9 @@ def static_group_norm( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.group_norm. This method simply wraps - the function, and so the docstring for ivy.group_norm also applies to this - method with minimal changes. + """ivy.Container static method variant of ivy.group_norm. This method + simply wraps the function, and so the docstring for ivy.group_norm also + applies to this method with minimal changes. Parameters ---------- @@ -710,10 +701,9 @@ def group_norm( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.group_norm. This method simply wraps - the function, and so the docstring for ivy.group_norm also applies to this - method with minimal changes. + """ivy.Container static method variant of ivy.group_norm. This method + simply wraps the function, and so the docstring for ivy.group_norm also + applies to this method with minimal changes. Parameters ---------- @@ -768,10 +758,9 @@ def static_lp_normalize( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.lp_normalize. This method simply - wraps the function, and so the docstring for ivy.lp_normalize also applies to - this method with minimal changes. + """ivy.Container static method variant of ivy.lp_normalize. This method + simply wraps the function, and so the docstring for ivy.lp_normalize + also applies to this method with minimal changes. Parameters ---------- @@ -836,10 +825,9 @@ def lp_normalize( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.l2_normalize. This method simply - wraps the function, and so the docstring for ivy.l2_normalize also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.l2_normalize. This + method simply wraps the function, and so the docstring for + ivy.l2_normalize also applies to this method with minimal changes. Parameters ---------- diff --git a/ivy/data_classes/container/experimental/random.py b/ivy/data_classes/container/experimental/random.py index 7544f92d3fafa..9a991587eba55 100644 --- a/ivy/data_classes/container/experimental/random.py +++ b/ivy/data_classes/container/experimental/random.py @@ -22,10 +22,9 @@ def static_dirichlet( seed: Optional[Union[int, ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.dirichlet. This method simply wraps - the function, and so the docstring for ivy.dirichlet also applies to this method - with minimal changes. + """ivy.Container static method variant of ivy.dirichlet. This method + simply wraps the function, and so the docstring for ivy.dirichlet also + applies to this method with minimal changes. Parameters ---------- @@ -89,10 +88,9 @@ def dirichlet( seed: Optional[Union[int, ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.dirichlet. This method simply wraps - the function, and so the docstring for ivy.shuffle also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.dirichlet. This method + simply wraps the function, and so the docstring for ivy.shuffle also + applies to this method with minimal changes. Parameters ---------- @@ -158,10 +156,9 @@ def static_beta( seed: Optional[Union[int, ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.beta. This method simply wraps the - function, and so the docstring for ivy.beta also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.beta. This method simply + wraps the function, and so the docstring for ivy.beta also applies to + this method with minimal changes. Parameters ---------- @@ -229,10 +226,9 @@ def beta( seed: Optional[Union[int, ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.beta. This method simply wraps the - function, and so the docstring for ivy.beta also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.beta. This method + simply wraps the function, and so the docstring for ivy.beta also + applies to this method with minimal changes. Parameters ---------- @@ -299,10 +295,9 @@ def static_poisson( fill_value: Optional[Union[float, int, ivy.Container]] = 0, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.poisson. This method simply wraps the - function, and so the docstring for ivy.poisson also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.poisson. This method + simply wraps the function, and so the docstring for ivy.poisson also + applies to this method with minimal changes. Parameters ---------- @@ -369,10 +364,9 @@ def poisson( fill_value: Optional[Union[float, int, ivy.Container]] = 0, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.poisson. This method simply wraps - the function, and so the docstring for ivy.poisson also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.poisson. This method + simply wraps the function, and so the docstring for ivy.poisson also + applies to this method with minimal changes. Parameters ---------- @@ -575,10 +569,9 @@ def static_gamma( seed: Optional[Union[int, ivy.Container]] = None, out: Optional[ivy.Container] = None, ): - """ - ivy.Container static method variant of ivy.gamma. This method simply wraps the - function, and so the docstring for ivy.gamma also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.gamma. This method simply + wraps the function, and so the docstring for ivy.gamma also applies to + this method with minimal changes. Parameters ---------- @@ -646,10 +639,9 @@ def gamma( seed: Optional[Union[int, ivy.Container]] = None, out: Optional[ivy.Container] = None, ): - """ - ivy.Container method variant of ivy.gamma. This method simply wraps the - function, and so the docstring for ivy.gamma also applies to this method with - minimal changes. + """ivy.Container method variant of ivy.gamma. This method simply wraps + the function, and so the docstring for ivy.gamma also applies to this + method with minimal changes. Parameters ---------- diff --git a/ivy/data_classes/container/experimental/searching.py b/ivy/data_classes/container/experimental/searching.py index d261dd6637716..0886c307e45e0 100644 --- a/ivy/data_classes/container/experimental/searching.py +++ b/ivy/data_classes/container/experimental/searching.py @@ -19,10 +19,9 @@ def static_unravel_index( map_sequences: Union[bool, ivy.Container] = False, out: Optional[Union[ivy.Array, ivy.Container]] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.unravel_index. This method simply - wraps the function, and so the docstring for ivy.unravel_index also applies to - this method with minimal changes. + """ivy.Container static method variant of ivy.unravel_index. This + method simply wraps the function, and so the docstring for + ivy.unravel_index also applies to this method with minimal changes. Parameters ---------- @@ -67,10 +66,9 @@ def unravel_index( *, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.unravel_index. This method simply - wraps the function, and so the docstring for ivy.unravel_index also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.unravel_index. This + method simply wraps the function, and so the docstring for + ivy.unravel_index also applies to this method with minimal changes. Parameters ---------- diff --git a/ivy/data_classes/container/experimental/sorting.py b/ivy/data_classes/container/experimental/sorting.py index a79109ea555e3..dc7c74258edb8 100644 --- a/ivy/data_classes/container/experimental/sorting.py +++ b/ivy/data_classes/container/experimental/sorting.py @@ -17,8 +17,7 @@ def static_invert_permutation( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.invert_permutation. + """ivy.Container static method variant of ivy.invert_permutation. This method simply wraps the function, and so the docstring for ivy.invert_permutation also applies to this method with minimal @@ -42,8 +41,7 @@ def invert_permutation( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.invert_permutation. + """ivy.Container instance method variant of ivy.invert_permutation. This method simply wraps the function, and so the docstring for ivy.invert_permutation also applies to this method with minimal @@ -69,10 +67,9 @@ def static_lexsort( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.lexsort. This method simply wraps the - function, and so the docstring for ivy.lexsort also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.lexsort. This method + simply wraps the function, and so the docstring for ivy.lexsort also + applies to this method with minimal changes. Parameters ---------- @@ -123,10 +120,9 @@ def lexsort( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.lexsort. This method simply wraps - the function, and so the docstring for ivy.lexsort also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.lexsort. This method + simply wraps the function, and so the docstring for ivy.lexsort also + applies to this method with minimal changes. Parameters ---------- diff --git a/ivy/data_classes/container/experimental/statistical.py b/ivy/data_classes/container/experimental/statistical.py index d7fa55b44c924..8c88175c9a543 100644 --- a/ivy/data_classes/container/experimental/statistical.py +++ b/ivy/data_classes/container/experimental/statistical.py @@ -28,10 +28,9 @@ def static_histogram( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.. This method simply wraps - the function, and so the docstring for ivy.histogram also applies to this method - with minimal changes. + """ivy.Container static method variant of ivy.. This method + simply wraps the function, and so the docstring for ivy.histogram also + applies to this method with minimal changes. Parameters ---------- @@ -135,10 +134,9 @@ def histogram( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.. This method simply - wraps the function, and so the docstring for ivy.histogram also applies to this - method with minimal changes. + """ivy.Container instance method variant of ivy.. This + method simply wraps the function, and so the docstring for + ivy.histogram also applies to this method with minimal changes. Parameters ---------- @@ -235,10 +233,9 @@ def static_median( map_sequences: Union[bool, ivy.Container] = False, out: Optional[Union[ivy.Array, ivy.Container]] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.median. This method simply wraps the - function, and so the docstring for ivy.median also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.median. This method + simply wraps the function, and so the docstring for ivy.median also + applies to this method with minimal changes. Parameters ---------- @@ -288,10 +285,9 @@ def median( keepdims: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.median. This method simply wraps - the function, and so the docstring for ivy.median also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.median. This method + simply wraps the function, and so the docstring for ivy.median also + applies to this method with minimal changes. Parameters ---------- @@ -340,10 +336,9 @@ def static_nanmean( map_sequences: Union[bool, ivy.Container] = False, out: Optional[Union[ivy.Array, ivy.Container]] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.nanmean. This method simply wraps the - function, and so the docstring for ivy.nanmean also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.nanmean. This method + simply wraps the function, and so the docstring for ivy.nanmean also + applies to this method with minimal changes. Parameters ---------- @@ -401,10 +396,9 @@ def nanmean( dtype: Optional[Union[ivy.Dtype, ivy.NativeDtype, ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.nanmean. This method simply wraps - the function, and so the docstring for ivy.nanmean also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.nanmean. This method + simply wraps the function, and so the docstring for ivy.nanmean also + applies to this method with minimal changes. Parameters ---------- @@ -459,10 +453,9 @@ def _static_nanmin( where: Optional[Union[ivy.Array, ivy.Container]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.nanmin. This method simply wraps the - function, and so the docstring for ivy.nanmin also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.nanmin. This method + simply wraps the function, and so the docstring for ivy.nanmin also + applies to this method with minimal changes. Parameters ---------- @@ -521,10 +514,9 @@ def nanmin( initial: Optional[Union[int, float, complex, ivy.Container]] = None, where: Optional[Union[ivy.Array, ivy.Container]] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.nanmin. This method simply wraps - the function, and so the docstring for ivy.nanmin also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.nanmin. This method + simply wraps the function, and so the docstring for ivy.nanmin also + applies to this method with minimal changes. Parameters ---------- @@ -584,10 +576,9 @@ def static_nanprod( initial: Optional[Union[int, float, complex, ivy.Container]] = 1, where: Optional[Union[ivy.Array, ivy.Container]] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.nanprod. This method simply wraps the - function, and so the docstring for ivy.nanprod also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.nanprod. This method + simply wraps the function, and so the docstring for ivy.nanprod also + applies to this method with minimal changes. Parameters ---------- @@ -651,10 +642,9 @@ def nanprod( initial: Optional[Union[int, float, complex, ivy.Container]] = None, where: Optional[Union[ivy.Array, ivy.Container]] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.nanprod. This method simply wraps - the function, and so the docstring for ivy.nanprod also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.nanprod. This method + simply wraps the function, and so the docstring for ivy.nanprod also + applies to this method with minimal changes. Parameters ---------- @@ -717,10 +707,9 @@ def static_quantile( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.quantile. This method simply wraps - the function, and so the docstring for ivy.quantile also applies to this method - with minimal changes. + """ivy.Container static method variant of ivy.quantile. This method + simply wraps the function, and so the docstring for ivy.quantile also + applies to this method with minimal changes. Parameters ---------- @@ -842,10 +831,9 @@ def quantile( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.quantile. This method simply wraps - the function, and so the docstring for ivy.quantile also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.quantile. This method + simply wraps the function, and so the docstring for ivy.quantile also + applies to this method with minimal changes. Parameters ---------- @@ -966,10 +954,9 @@ def static_corrcoef( map_sequences: Union[bool, ivy.Container] = False, out: Optional[Union[ivy.Array, ivy.Container]] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.corrcoef. This method simply wraps - the function, and so the docstring for ivy.corrcoef also applies to this method - with minimal changes. + """ivy.Container static method variant of ivy.corrcoef. This method + simply wraps the function, and so the docstring for ivy.corrcoef also + applies to this method with minimal changes. Parameters ---------- @@ -1019,10 +1006,9 @@ def corrcoef( rowvar: Union[bool, ivy.Container] = True, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.corrcoef. This method simply wraps - the function, and so the docstring for ivy.corrcoef also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.corrcoef. This method + simply wraps the function, and so the docstring for ivy.corrcoef also + applies to this method with minimal changes. Parameters ---------- @@ -1068,10 +1054,9 @@ def static_nanmedian( map_sequences: Union[bool, ivy.Container] = False, out: Optional[Union[ivy.Array, ivy.Container]] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.median. This method simply wraps the - function, and so the docstring for ivy.median also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.median. This method + simply wraps the function, and so the docstring for ivy.median also + applies to this method with minimal changes. Parameters ---------- @@ -1124,10 +1109,9 @@ def nanmedian( overwrite_input: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.nanmedian. This method simply wraps - the function, and so the docstring for ivy.nanmedian also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.nanmedian. This method + simply wraps the function, and so the docstring for ivy.nanmedian also + applies to this method with minimal changes. Parameters ---------- @@ -1193,10 +1177,9 @@ def static_bincount( map_sequences: Union[bool, ivy.Container] = False, out: Optional[Union[ivy.Array, ivy.Container]] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.bincount. This method simply wraps - the function, and so the docstring for ivy.bincount also applies to this method - with minimal changes. + """ivy.Container static method variant of ivy.bincount. This method + simply wraps the function, and so the docstring for ivy.bincount also + applies to this method with minimal changes. Parameters ---------- @@ -1243,10 +1226,9 @@ def bincount( minlength: Union[int, ivy.Container] = 0, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Array instance method variant of ivy.bincount. This method simply wraps the - function, and so the docstring for ivy.bincount also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.bincount. This method + simply wraps the function, and so the docstring for ivy.bincount also + applies to this method with minimal changes. Parameters ---------- @@ -1284,10 +1266,9 @@ def static_igamma( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.igamma. This method simply wraps the - function, and so the docstring for ivy.igamma also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.igamma. This method + simply wraps the function, and so the docstring for ivy.igamma also + applies to this method with minimal changes. Parameters ---------- @@ -1329,10 +1310,9 @@ def igamma( x: Union[ivy.Container, ivy.Array, ivy.NativeArray], out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.igamma. This method simply wraps - the function, and so the docstring for ivy.igamma also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.igamma. This method + simply wraps the function, and so the docstring for ivy.igamma also + applies to this method with minimal changes. Parameters ---------- @@ -1358,6 +1338,35 @@ def igamma( """ return self.static_igamma(self, x=x, out=out) + @staticmethod + def static_lgamma( + a: Union[ivy.Container, ivy.Array, ivy.NativeArray], + /, + *, + key_chains: Optional[Union[List[str], Dict[str, str], ivy.Container]] = None, + to_apply: Union[bool, ivy.Container] = True, + prune_unapplied: Union[bool, ivy.Container] = False, + map_sequences: Union[bool, ivy.Container] = False, + out: Optional[ivy.Container] = None, + ) -> ivy.Container: + return ContainerBase.cont_multi_map_in_function( + "lgamma", + a, + key_chains=key_chains, + to_apply=to_apply, + prune_unapplied=prune_unapplied, + map_sequences=map_sequences, + out=out, + ) + + def lgamma( + self: ivy.Container, + /, + *, + out: Optional[ivy.Container] = None, + ) -> ivy.Container: + return self.static_lgamma(self, out=out) + @staticmethod def static_cov( x1: Union[ivy.Array, ivy.NativeArray, ivy.Container], @@ -1375,10 +1384,9 @@ def static_cov( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.cov. This method simply wraps the - function, and so the docstring for ivy.cov also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.cov. This method simply + wraps the function, and so the docstring for ivy.cov also applies to + this method with minimal changes. Parameters ---------- @@ -1492,10 +1500,9 @@ def cov( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.cov. This method simply wraps the - function, and so the docstring for ivy.cov also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.cov. This method simply + wraps the function, and so the docstring for ivy.cov also applies to + this method with minimal changes. Parameters ---------- @@ -1594,10 +1601,9 @@ def cummax( dtype: Optional[Union[ivy.Dtype, ivy.NativeDtype, ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.cummax. This method simply wraps - the function, and so the docstring for ivy.cummax also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.cummax. This method + simply wraps the function, and so the docstring for ivy.cummax also + applies to this method with minimal changes. Parameters ---------- @@ -1684,10 +1690,9 @@ def cummin( dtype: Optional[Union[ivy.Dtype, ivy.NativeDtype, ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.cummin. This method simply wraps - the function, and so the docstring for ivy.cummin also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.cummin. This method + simply wraps the function, and so the docstring for ivy.cummin also + applies to this method with minimal changes. Parameters ---------- @@ -1772,10 +1777,9 @@ def _static_cummax( dtype: Optional[Union[ivy.Dtype, ivy.NativeDtype, ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.cummax. This method simply wraps the - function, and so the docstring for ivy.cummax also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.cummax. This method + simply wraps the function, and so the docstring for ivy.cummax also + applies to this method with minimal changes. Parameters ---------- @@ -1862,10 +1866,9 @@ def _static_cummin( dtype: Optional[Union[ivy.Dtype, ivy.NativeDtype, ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.cummin. This method simply wraps the - function, and so the docstring for ivy.cummin also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.cummin. This method + simply wraps the function, and so the docstring for ivy.cummin also + applies to this method with minimal changes. Parameters ---------- diff --git a/ivy/data_classes/container/experimental/utility.py b/ivy/data_classes/container/experimental/utility.py index 876a9fad339e5..4218b878b282c 100644 --- a/ivy/data_classes/container/experimental/utility.py +++ b/ivy/data_classes/container/experimental/utility.py @@ -18,10 +18,10 @@ def static_optional_get_element( map_sequences: bool = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.optional_get_element. This method - simply wraps the function, and so the docstring for ivy.optional_get_element - also applies to this method with minimal changes. + """ivy.Container static method variant of ivy.optional_get_element. + This method simply wraps the function, and so the docstring for + ivy.optional_get_element also applies to this method with minimal + changes. Parameters ---------- @@ -62,10 +62,10 @@ def optional_get_element( *, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.optional_get_element. This method - simply wraps the function, and so the docstring for ivy.optional_get_element - also applies to this method with minimal changes. + """ivy.Container instance method variant of ivy.optional_get_element. + This method simply wraps the function, and so the docstring for + ivy.optional_get_element also applies to this method with minimal + changes. Parameters ---------- diff --git a/ivy/data_classes/container/general.py b/ivy/data_classes/container/general.py index 54c798a70d165..b1debe2fb187e 100644 --- a/ivy/data_classes/container/general.py +++ b/ivy/data_classes/container/general.py @@ -22,10 +22,9 @@ def _static_is_native_array( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.is_native_array. This method simply - wraps the function, and so the docstring for ivy.is_native_array also applies to - this method with minimal changes. + """ivy.Container static method variant of ivy.is_native_array. This + method simply wraps the function, and so the docstring for + ivy.is_native_array also applies to this method with minimal changes. Parameters ---------- @@ -81,10 +80,10 @@ def is_native_array( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.is_native_array. This method simply - wraps the function, and so the docstring for ivy.ivy.is_native_array also - applies to this method with minimal changes. + """ivy.Container instance method variant of ivy.is_native_array. This + method simply wraps the function, and so the docstring for + ivy.ivy.is_native_array also applies to this method with minimal + changes. Parameters ---------- @@ -140,10 +139,9 @@ def _static_is_ivy_array( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.is_ivy_array. This method simply - wraps the function, and so the docstring for ivy.is_ivy_array also applies to - this method with minimal changes. + """ivy.Container static method variant of ivy.is_ivy_array. This method + simply wraps the function, and so the docstring for ivy.is_ivy_array + also applies to this method with minimal changes. Parameters ---------- @@ -197,10 +195,10 @@ def is_ivy_array( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.is_native_array. This method simply - wraps the function, and so the docstring for ivy.ivy.is_native_array also - applies to this method with minimal changes. + """ivy.Container instance method variant of ivy.is_native_array. This + method simply wraps the function, and so the docstring for + ivy.ivy.is_native_array also applies to this method with minimal + changes. Parameters ---------- @@ -254,10 +252,9 @@ def _static_is_array( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.is_array. This method simply wraps - the function, and so the docstring for ivy.ivy.is_array also applies to this - method with minimal changes. + """ivy.Container static method variant of ivy.is_array. This method + simply wraps the function, and so the docstring for ivy.ivy.is_array + also applies to this method with minimal changes. Parameters ---------- @@ -316,10 +313,9 @@ def is_array( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.is_array. This method simply wraps - the function, and so the docstring for ivy.is_array also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.is_array. This method + simply wraps the function, and so the docstring for ivy.is_array also + applies to this method with minimal changes. Parameters ---------- @@ -377,10 +373,9 @@ def _static_clip_vector_norm( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.clip_vector_norm. This method - simply wraps the function, and so the docstring for ivy.clip_vector_norm also - applies to this method with minimal changes. + """ivy.Container instance method variant of ivy.clip_vector_norm. This + method simply wraps the function, and so the docstring for + ivy.clip_vector_norm also applies to this method with minimal changes. Parameters ---------- @@ -449,10 +444,9 @@ def clip_vector_norm( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.clip_vector_norm. This method - simply wraps the function, and so the docstring for ivy.clip_vector_norm also - applies to this method with minimal changes. + """ivy.Container instance method variant of ivy.clip_vector_norm. This + method simply wraps the function, and so the docstring for + ivy.clip_vector_norm also applies to this method with minimal changes. Parameters ---------- @@ -523,10 +517,9 @@ def _static_inplace_update( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.inplace_update. This method simply - wraps the function, and so the docstring for ivy.inplace_update also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.inplace_update. This + method simply wraps the function, and so the docstring for + ivy.inplace_update also applies to this method with minimal changes. Parameters ---------- @@ -592,10 +585,9 @@ def inplace_update( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.inplace_update. This method simply - wraps the function, and so the docstring for ivy.inplace_update also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.inplace_update. This + method simply wraps the function, and so the docstring for + ivy.inplace_update also applies to this method with minimal changes. Parameters ---------- @@ -666,10 +658,9 @@ def _static_inplace_decrement( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.inplace_decrement. This method simply - wraps the function, and so the docstring for ivy.inplace_decrement also applies - to this method with minimal changes. + """ivy.Container static method variant of ivy.inplace_decrement. This + method simply wraps the function, and so the docstring for + ivy.inplace_decrement also applies to this method with minimal changes. Parameters ---------- @@ -746,10 +737,9 @@ def inplace_decrement( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.inplace_decrement. This method - simply wraps the function, and so the docstring for ivy.inplace_decrement also - applies to this method with minimal changes. + """ivy.Container instance method variant of ivy.inplace_decrement. This + method simply wraps the function, and so the docstring for + ivy.inplace_decrement also applies to this method with minimal changes. Parameters ---------- @@ -808,10 +798,9 @@ def _static_inplace_increment( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.inplace_increment. This method simply - wraps the function, and so the docstring for ivy.inplace_increment also applies - to this method with minimal changes. + """ivy.Container static method variant of ivy.inplace_increment. This + method simply wraps the function, and so the docstring for + ivy.inplace_increment also applies to this method with minimal changes. Parameters ---------- @@ -888,10 +877,9 @@ def inplace_increment( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.inplace_increment. This method - wraps the function, and so the docstring for ivy.inplace_increment also applies - to this method with minimal changes. + """ivy.Container instance method variant of ivy.inplace_increment. This + method wraps the function, and so the docstring for + ivy.inplace_increment also applies to this method with minimal changes. Parameters ---------- @@ -949,10 +937,10 @@ def _static_assert_supports_inplace( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.assert_supports_inplace. This method - simply wraps the function, and so the docstring for ivy.assert_supports_inplace - also applies to this method with minimal changes. + """ivy.Container static method variant of ivy.assert_supports_inplace. + This method simply wraps the function, and so the docstring for + ivy.assert_supports_inplace also applies to this method with minimal + changes. Parameters ---------- @@ -993,10 +981,10 @@ def assert_supports_inplace( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.assert_supports_inplace. This - method simply wraps the function, and so the docstring for - ivy.assert_supports_inplace also applies to this method with minimal changes. + """ivy.Container instance method variant of + ivy.assert_supports_inplace. This method simply wraps the function, and + so the docstring for ivy.assert_supports_inplace also applies to this + method with minimal changes. Parameters ---------- @@ -1019,6 +1007,7 @@ def assert_supports_inplace( ret An ivy.Container instance of True bool values if nodes of the Container \ support in-place operations, raises IvyBackendException otherwise + Examples -------- >>> ivy.set_backend("numpy") @@ -1047,10 +1036,9 @@ def _static_all_equal( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.all_equal. This method simply wraps - the function, and so the docstring for ivy.all_equal also applies to this method - with minimal changes. + """ivy.Container static method variant of ivy.all_equal. This method + simply wraps the function, and so the docstring for ivy.all_equal also + applies to this method with minimal changes. Parameters ---------- @@ -1125,10 +1113,9 @@ def all_equal( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.all_equal. This method simply wraps - the function, and so the docstring for ivy.all_equal also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.all_equal. This method + simply wraps the function, and so the docstring for ivy.all_equal also + applies to this method with minimal changes. Parameters ---------- @@ -1227,10 +1214,9 @@ def _static_fourier_encode( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.fourier_encode. This method simply - wraps the function, and so the docstring for ivy.fourier_encode also applies to - this method with minimal changes. + """ivy.Container static method variant of ivy.fourier_encode. This + method simply wraps the function, and so the docstring for + ivy.fourier_encode also applies to this method with minimal changes. Parameters ---------- @@ -1319,10 +1305,9 @@ def fourier_encode( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.fourier_encode. This method simply - wraps the function, and so the docstring for ivy.fourier_encode also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.fourier_encode. This + method simply wraps the function, and so the docstring for + ivy.fourier_encode also applies to this method with minimal changes. Parameters ---------- @@ -1408,10 +1393,9 @@ def _static_gather( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.gather. This method simply wraps the - function, and so the docstring for ivy.gather also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.gather. This method + simply wraps the function, and so the docstring for ivy.gather also + applies to this method with minimal changes. Parameters ---------- @@ -1436,7 +1420,7 @@ def _static_gather( Whether to also map method to sequences (lists, tuples). Default is ``False``. out - optional array, for writing the result to. It must have a shape + Optional array, for writing the result to. It must have a shape that the inputs broadcast to. @@ -1498,10 +1482,9 @@ def gather( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.gather. This method simply wraps - the function, and so the docstring for ivy.gather also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.gather. This method + simply wraps the function, and so the docstring for ivy.gather also + applies to this method with minimal changes. Parameters ---------- @@ -1526,7 +1509,7 @@ def gather( Whether to also map method to sequences (lists, tuples). Default is False. out - optional array, for writing the result to. It must have a shape + Optional array, for writing the result to. It must have a shape that the inputs broadcast to. Returns @@ -1562,7 +1545,7 @@ def gather( @staticmethod def _static_has_nans( - self: ivy.Container, + x: ivy.Container, /, *, include_infs: Union[bool, ivy.Container] = True, @@ -1577,7 +1560,7 @@ def _static_has_nans( Parameters ---------- - self + x The container to check for nans. include_infs Whether to include infs and -infs in the check. Default is True. @@ -1610,7 +1593,7 @@ def _static_has_nans( """ return ContainerBase.cont_multi_map_in_function( "has_nans", - self, + x, include_infs=include_infs, key_chains=key_chains, to_apply=to_apply, @@ -1685,10 +1668,9 @@ def _static_scatter_nd( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.scatter_nd. This method simply wraps - the function, and so the docstring for ivy.scatter_nd also applies to this - method with minimal changes. + """ivy.Container static method variant of ivy.scatter_nd. This method + simply wraps the function, and so the docstring for ivy.scatter_nd also + applies to this method with minimal changes. Parameters ---------- @@ -1781,10 +1763,9 @@ def scatter_nd( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.scatter_nd. This method simply - wraps the function, and so the docstring for ivy.scatter_nd also applies to this - method with minimal changes. + """ivy.Container instance method variant of ivy.scatter_nd. This method + simply wraps the function, and so the docstring for ivy.scatter_nd also + applies to this method with minimal changes. Parameters ---------- @@ -1876,10 +1857,9 @@ def _static_scatter_flat( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.scatter_flat. This method simply - wraps the function, and so the docstring for ivy.scatter_flat also applies to - this method with minimal changes. + """ivy.Container static method variant of ivy.scatter_flat. This method + simply wraps the function, and so the docstring for ivy.scatter_flat + also applies to this method with minimal changes. Parameters ---------- @@ -1939,10 +1919,9 @@ def scatter_flat( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.scatter_flat. This method simply - wraps the function, and so the docstring for ivy.scatter_flat also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.scatter_flat. This + method simply wraps the function, and so the docstring for + ivy.scatter_flat also applies to this method with minimal changes. Parameters ---------- @@ -2015,9 +1994,8 @@ def _static_gather_nd( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - Gather slices from all container params into a arrays with shape specified by - indices. + """Gather slices from all container params into a arrays with shape + specified by indices. Parameters ---------- @@ -2082,10 +2060,9 @@ def gather_nd( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.gather_nd. This method simply wraps - the function, and so the docstring for ivy.gather_nd also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.gather_nd. This method + simply wraps the function, and so the docstring for ivy.gather_nd also + applies to this method with minimal changes. Parameters ---------- @@ -2156,8 +2133,7 @@ def _static_einops_reduce( out: Optional[ivy.Container] = None, **axes_lengths: Union[Dict[str, int], ivy.Container], ) -> ivy.Container: - """ - Perform einops reduce operation on each sub array in the container. + """Perform einops reduce operation on each sub array in the container. Parameters ---------- @@ -2228,10 +2204,9 @@ def einops_reduce( out: Optional[ivy.Container] = None, **axes_lengths: Union[Dict[str, int], ivy.Container], ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.einops_reduce. This method simply - wraps the function, and so the docstring for ivy.einops_reduce also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.einops_reduce. This + method simply wraps the function, and so the docstring for + ivy.einops_reduce also applies to this method with minimal changes. Parameters ---------- @@ -2311,8 +2286,7 @@ def _static_einops_repeat( out: Optional[ivy.Container] = None, **axes_lengths: Union[Dict[str, int], ivy.Container], ) -> ivy.Container: - """ - Perform einops repeat operation on each sub array in the container. + """Perform einops repeat operation on each sub array in the container. Parameters ---------- @@ -2381,10 +2355,9 @@ def einops_repeat( out: Optional[ivy.Container] = None, **axes_lengths: Union[Dict[str, int], ivy.Container], ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.einops_repeat. This method simply - wraps the function, and so the docstring for ivy.einops_repeat also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.einops_repeat. This + method simply wraps the function, and so the docstring for + ivy.einops_repeat also applies to this method with minimal changes. Parameters ---------- @@ -2449,10 +2422,9 @@ def _static_value_is_nan( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.value_is_nan. This method simply - wraps the function, and so the docstring for ivy.value_is_nan also applies to - this method with minimal changes. + """ivy.Container static method variant of ivy.value_is_nan. This method + simply wraps the function, and so the docstring for ivy.value_is_nan + also applies to this method with minimal changes. Parameters ---------- @@ -2530,10 +2502,9 @@ def value_is_nan( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.value_is_nan. This method simply - wraps the function, and so the docstring for ivy.value_is_nan also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.value_is_nan. This + method simply wraps the function, and so the docstring for + ivy.value_is_nan also applies to this method with minimal changes. Parameters ---------- @@ -2605,10 +2576,9 @@ def _static_to_numpy( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.to_numpy. This method simply wraps - the function, and so the docstring for ivy.to_numpy also applies to this method - with minimal changes. + """ivy.Container static method variant of ivy.to_numpy. This method + simply wraps the function, and so the docstring for ivy.to_numpy also + applies to this method with minimal changes. Parameters ---------- @@ -2676,10 +2646,9 @@ def to_numpy( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.to_numpy. This method simply wraps - the function, and so the docstring for ivy.to_numpy also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.to_numpy. This method + simply wraps the function, and so the docstring for ivy.to_numpy also + applies to this method with minimal changes. Parameters ---------- @@ -2749,10 +2718,9 @@ def _static_to_scalar( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.to_scalar. This method simply wraps - the function, and so the docstring for ivy.to_scalar also applies to this method - with minimal changes. + """ivy.Container static method variant of ivy.to_scalar. This method + simply wraps the function, and so the docstring for ivy.to_scalar also + applies to this method with minimal changes. Parameters ---------- @@ -2806,10 +2774,9 @@ def to_scalar( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.to_scalar. This method simply wraps - the function, and so the docstring for ivy.to_scalar also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.to_scalar. This method + simply wraps the function, and so the docstring for ivy.to_scalar also + applies to this method with minimal changes. Parameters ---------- @@ -2866,10 +2833,9 @@ def _static_to_list( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.to_list. This method simply wraps the - function, and so the docstring for ivy.to_list also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.to_list. This method + simply wraps the function, and so the docstring for ivy.to_list also + applies to this method with minimal changes. Parameters ---------- @@ -2919,10 +2885,9 @@ def to_list( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.to_list. This method simply wraps - the function, and so the docstring for ivy.to_list also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.to_list. This method + simply wraps the function, and so the docstring for ivy.to_list also + applies to this method with minimal changes. Parameters ---------- @@ -2977,10 +2942,9 @@ def _static_stable_divide( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.stable_divide. This method simply - wraps the function, and so the docstring for ivy.stable_divide also applies to - this method with minimal changes. + """ivy.Container static method variant of ivy.stable_divide. This + method simply wraps the function, and so the docstring for + ivy.stable_divide also applies to this method with minimal changes. Parameters ---------- @@ -3081,10 +3045,9 @@ def stable_divide( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.stable_divide. This method simply - wraps the function, and so the docstring for ivy.stable_divide also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.stable_divide. This + method simply wraps the function, and so the docstring for + ivy.stable_divide also applies to this method with minimal changes. Parameters ---------- @@ -3167,10 +3130,9 @@ def _static_stable_pow( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.stable_pow. This method simply wraps - the function, and so the docstring for ivy.stable_pow also applies to this - method with minimal changes. + """ivy.Container static method variant of ivy.stable_pow. This method + simply wraps the function, and so the docstring for ivy.stable_pow also + applies to this method with minimal changes. Parameters ---------- @@ -3256,10 +3218,9 @@ def stable_pow( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.stable_pow. This method simply - wraps the function, and so the docstring for ivy.stable_pow also applies to this - method with minimal changes. + """ivy.Container instance method variant of ivy.stable_pow. This method + simply wraps the function, and so the docstring for ivy.stable_pow also + applies to this method with minimal changes. Parameters ---------- @@ -3346,10 +3307,9 @@ def _static_einops_rearrange( out: Optional[ivy.Container] = None, **axes_lengths: Union[Dict[str, int], ivy.Container], ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.einops_rearrange. This method simply - wraps the function, and so the docstring for ivy.einops_rearrange also applies - to this method with minimal changes. + """ivy.Container static method variant of ivy.einops_rearrange. This + method simply wraps the function, and so the docstring for + ivy.einops_rearrange also applies to this method with minimal changes. Parameters ---------- @@ -3434,10 +3394,9 @@ def einops_rearrange( out: Optional[ivy.Container] = None, **axes_lengths: Union[Dict[str, int], ivy.Container], ): - """ - ivy.Container instance method variant of ivy.einops_rearrange. This method - simply wraps the function, and so the docstring for ivy.einops_rearrange also - applies to this method with minimal changes. + """ivy.Container instance method variant of ivy.einops_rearrange. This + method simply wraps the function, and so the docstring for + ivy.einops_rearrange also applies to this method with minimal changes. Parameters ---------- @@ -3522,10 +3481,9 @@ def _static_clip_matrix_norm( p: Union[float, ivy.Container] = 2.0, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.clip_matrix_norm. This method simply - wraps the function, and so the docstring for ivy.clip_matrix_norm also applies - to this method with minimal changes. + """ivy.Container static method variant of ivy.clip_matrix_norm. This + method simply wraps the function, and so the docstring for + ivy.clip_matrix_norm also applies to this method with minimal changes. Parameters ---------- @@ -3592,10 +3550,9 @@ def clip_matrix_norm( p: Union[float, ivy.Container] = 2.0, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.clip_matrix_norm. This method - simply wraps the function, and so the docstring for ivy.clip_matrix_norm also - applies to this method with minimal changes. + """ivy.Container instance method variant of ivy.clip_matrix_norm. This + method simply wraps the function, and so the docstring for + ivy.clip_matrix_norm also applies to this method with minimal changes. Parameters ---------- @@ -3659,10 +3616,10 @@ def _static_supports_inplace_updates( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.supports_inplace_updates. This method - simply wraps the function, and so the docstring for ivy.supports_inplace_updates - also applies to this method with minimal changes. + """ivy.Container static method variant of ivy.supports_inplace_updates. + This method simply wraps the function, and so the docstring for + ivy.supports_inplace_updates also applies to this method with minimal + changes. Parameters ---------- @@ -3706,10 +3663,10 @@ def supports_inplace_updates( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.supports_inplace_updates. This - method simply wraps the static function, and so the docstring for the static - variant also applies to this method with minimal changes. + """ivy.Container instance method variant of + ivy.supports_inplace_updates. This method simply wraps the static + function, and so the docstring for the static variant also applies to + this method with minimal changes. Parameters ---------- @@ -3776,10 +3733,9 @@ def _static_get_num_dims( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.get_num_dims. This method simply - wraps the function, and so the docstring for ivy.get_num_dims also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.get_num_dims. This + method simply wraps the function, and so the docstring for + ivy.get_num_dims also applies to this method with minimal changes. Parameters ---------- @@ -3853,10 +3809,9 @@ def get_num_dims( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.get_num_dims. This method simply - wraps the function, and so the docstring for ivy.get_num_dims also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.get_num_dims. This + method simply wraps the function, and so the docstring for + ivy.get_num_dims also applies to this method with minimal changes. Parameters ---------- @@ -3919,6 +3874,140 @@ def get_num_dims( map_sequences=map_sequences, ) + @staticmethod + def _static_size( + x: Union[ivy.Array, ivy.NativeArray, ivy.Container], + /, + *, + key_chains: Optional[Union[List[str], Dict[str, str], ivy.Container]] = None, + to_apply: Union[bool, ivy.Container] = True, + prune_unapplied: Union[bool, ivy.Container] = False, + map_sequences: Union[bool, ivy.Container] = False, + ) -> ivy.Container: + """ivy.Container instance method variant of ivy.size. This method + simply wraps the function, and so the docstring for ivy.size also + applies to this method with minimal changes. + + Parameters + ---------- + x + ivy.Container to infer the number of elements for + key_chains + The key-chains to apply or not apply the method to. Default is ``None``. + to_apply + If True, the method will be applied to key_chains, otherwise key_chains + will be skipped. Default is ``True``. + prune_unapplied + Whether to prune key_chains for which the function was not applied. + Default is ``False``. + map_sequences + Whether to also map method to sequences (lists, tuples). + Default is ``False``. + + + Returns + ------- + ret + Number of elements of the array + + Examples + -------- + >>> x = ivy.Container(b = ivy.asarray([[0.,1.,1.],[1.,0.,0.],[8.,2.,3.]])) + >>> ivy.Container.static_size(x) + { + b: 9 + } + >>> x = ivy.Container(b = ivy.array([[[0,0,0],[0,0,0],[0,0,0]] + ... [[0,0,0],[0,0,0],[0,0,0]], + ... [[0,0,0],[0,0,0],[0,0,0]]])) + >>> ivy.Container.static_size(x) + { + b: 27 + } + >>> x = ivy.Container(b = ivy.array([[[0,0,0],[0,0,0],[0,0,0]], + ... [[0,0,0],[0,0,0],[0,0,0]]]), + ... c = ivy.asarray([[0.,1.,1.],[8.,2.,3.]])) + >>> ivy.Container.static_size(x) + { + b: 18, + c: 6, + } + """ + return ContainerBase.cont_multi_map_in_function( + "size", + x, + key_chains=key_chains, + to_apply=to_apply, + prune_unapplied=prune_unapplied, + map_sequences=map_sequences, + ) + + def size( + self: ivy.Container, + /, + *, + key_chains: Optional[Union[List[str], Dict[str, str], ivy.Container]] = None, + to_apply: Union[bool, ivy.Container] = True, + prune_unapplied: Union[bool, ivy.Container] = False, + map_sequences: Union[bool, ivy.Container] = False, + ) -> ivy.Container: + """ivy.Container instance method variant of ivy.size. This method + simply wraps the function, and so the docstring for ivy.size also + applies to this method with minimal changes. + + Parameters + ---------- + self + ivy.Container to infer the number of elements for + key_chains + The key-chains to apply or not apply the method to. Default is ``None``. + to_apply + If True, the method will be applied to key_chains, otherwise key_chains + will be skipped. Default is ``True``. + prune_unapplied + Whether to prune key_chains for which the function was not applied. + Default is ``False``. + map_sequences + Whether to also map method to sequences (lists, tuples). + Default is ``False``. + + + Returns + ------- + ret + Number of elements of the array + + Examples + -------- + >>> a = ivy.Container(b = ivy.asarray([[0.,1.,1.],[1.,0.,0.],[8.,2.,3.]])) + >>> a.size() + { + b: 9 + } + >>> a = ivy.Container(b = ivy.array([[[0,0,0],[0,0,0],[0,0,0]], + ... [[0,0,0],[0,0,0],[0,0,0]], + ... [[0,0,0],[0,0,0],[0,0,0]]])) + >>> a.size() + { + b: 27 + } + >>> a = ivy.Container(b = ivy.array([[[0,0,0],[0,0,0],[0,0,0]], + ... [[0,0,0],[0,0,0],[0,0,0]]]), + ... c = ivy.asarray([[0.,1.,1.],[8.,2.,3.]])) + >>> a.size() + { + b: 18, + c: 6, + } + """ + return _ContainerWithGeneral._static_size( + self, + key_chains=key_chains, + to_apply=to_apply, + prune_unapplied=prune_unapplied, + map_sequences=map_sequences, + ) + @staticmethod def _static_array_equal( x0: Union[ivy.Array, ivy.NativeArray, ivy.Container], @@ -3930,10 +4019,9 @@ def _static_array_equal( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.array_equal. This method simply - wraps the function, and so the docstring for ivy.array_equal also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.array_equal. This + method simply wraps the function, and so the docstring for + ivy.array_equal also applies to this method with minimal changes. Parameters ---------- @@ -3995,10 +4083,9 @@ def array_equal( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.array_equal. This method simply - wraps the function, and so the docstring for ivy.array_equal also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.array_equal. This + method simply wraps the function, and so the docstring for + ivy.array_equal also applies to this method with minimal changes. Parameters ---------- @@ -4069,10 +4156,9 @@ def static_isin( assume_unique: Union[bool, ivy.Container] = False, invert: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - Container instance method variant of ivy.isin. This method simply wraps the - function, and so the docstring for ivy.isin also applies to this method with - minimal changes. + """Container instance method variant of ivy.isin. This method simply + wraps the function, and so the docstring for ivy.isin also applies to + this method with minimal changes. Parameters ---------- @@ -4119,10 +4205,9 @@ def isin( assume_unique: Union[bool, ivy.Container] = False, invert: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - Container instance method variant of ivy.isin. This method simply wraps the - function, and so the docstring for ivy.isin also applies to this method with - minimal changes. + """Container instance method variant of ivy.isin. This method simply + wraps the function, and so the docstring for ivy.isin also applies to + this method with minimal changes. Parameters ---------- @@ -4162,10 +4247,9 @@ def static_itemsize( x: ivy.Container, /, ) -> ivy.Container: - """ - Container instance method variant of ivy.itemsize. This method simply wraps the - function, and so the docstring for ivy.itemsize also applies to this method with - minimal changes. + """Container instance method variant of ivy.itemsize. This method + simply wraps the function, and so the docstring for ivy.itemsize also + applies to this method with minimal changes. Parameters ---------- @@ -4190,10 +4274,9 @@ def itemsize( self: ivy.Container, /, ) -> ivy.Container: - """ - Container instance method variant of ivy.itemsize. This method simply wraps the - function, and so the docstring for ivy.itemsize also applies to this method with - minimal changes. + """Container instance method variant of ivy.itemsize. This method + simply wraps the function, and so the docstring for ivy.itemsize also + applies to this method with minimal changes. Parameters ---------- @@ -4212,10 +4295,9 @@ def static_strides( x: ivy.Container, /, ) -> ivy.Container: - """ - Container instance method variant of ivy.strides. This method simply wraps the - function, and so the docstring for ivy.strides also applies to this method with - minimal changes. + """Container instance method variant of ivy.strides. This method simply + wraps the function, and so the docstring for ivy.strides also applies + to this method with minimal changes. Parameters ---------- @@ -4240,10 +4322,9 @@ def strides( self: ivy.Container, /, ) -> ivy.Container: - """ - Container instance method variant of ivy.strides. This method simply wraps the - function, and so the docstring for ivy.strides also applies to this method with - minimal changes. + """Container instance method variant of ivy.strides. This method simply + wraps the function, and so the docstring for ivy.strides also applies + to this method with minimal changes. Parameters ---------- @@ -4267,10 +4348,9 @@ def _static_exists( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.exists. This method simply wraps - the function, and so the docstring for ivy.exists also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.exists. This method + simply wraps the function, and so the docstring for ivy.exists also + applies to this method with minimal changes. Parameters ---------- @@ -4329,10 +4409,9 @@ def exists( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.exists. This method simply wraps - the function, and so the docstring for ivy.exists also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.exists. This method + simply wraps the function, and so the docstring for ivy.exists also + applies to this method with minimal changes. Parameters ---------- diff --git a/ivy/data_classes/container/gradients.py b/ivy/data_classes/container/gradients.py index 94a51f311c380..a1848f648913f 100644 --- a/ivy/data_classes/container/gradients.py +++ b/ivy/data_classes/container/gradients.py @@ -19,10 +19,9 @@ def _static_stop_gradient( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.stop_gradient. This method simply - wraps the function, and so the docstring for ivy.stop_gradient also applies to - this method with minimal changes. + """ivy.Container static method variant of ivy.stop_gradient. This + method simply wraps the function, and so the docstring for + ivy.stop_gradient also applies to this method with minimal changes. Parameters ---------- @@ -97,10 +96,9 @@ def stop_gradient( preserve_type: Union[bool, ivy.Container] = True, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.stop_gradient. This method simply - wraps the function, and so the docstring for ivy.stop_gradient also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.stop_gradient. This + method simply wraps the function, and so the docstring for + ivy.stop_gradient also applies to this method with minimal changes. Parameters ---------- @@ -175,10 +173,9 @@ def adam_step( epsilon: Union[float, ivy.Container] = 1e-7, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.adam_step. This method simply wraps - the function, and so the docstring for ivy.adam_step also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.adam_step. This method + simply wraps the function, and so the docstring for ivy.adam_step also + applies to this method with minimal changes. Parameters ---------- @@ -271,9 +268,8 @@ def optimizer_update( stop_gradients: Union[bool, ivy.Container] = True, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - Update weights ws of some function, given the true or effective derivatives of - some cost c with respect to ws, [dc/dw for w in ws]. + """Update weights ws of some function, given the true or effective + derivatives of some cost c with respect to ws, [dc/dw for w in ws]. Parameters ---------- @@ -351,10 +347,10 @@ def gradient_descent_update( stop_gradients: Union[bool, ivy.Container] = True, out: ivy.Container = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.gradient_descent_update. This - method simply wraps the function, and so the docstring for - ivy.gradient_descent_update also applies to this method with minimal changes. + """ivy.Container instance method variant of + ivy.gradient_descent_update. This method simply wraps the function, and + so the docstring for ivy.gradient_descent_update also applies to this + method with minimal changes. Parameters ---------- @@ -435,10 +431,9 @@ def lars_update( stop_gradients: Union[bool, ivy.Container] = True, out: Optional[ivy.Container] = None, ): - """ - Update weights ws of some function, given the derivatives of some cost c with - respect to ws, [dc/dw for w in ws], by applying Layerwise Adaptive Rate Scaling - (LARS) method. + """Update weights ws of some function, given the derivatives of some + cost c with respect to ws, [dc/dw for w in ws], by applying Layerwise + Adaptive Rate Scaling (LARS) method. Parameters ---------- @@ -516,9 +511,8 @@ def adam_update( stop_gradients: Union[bool, ivy.Container] = True, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - Update weights ws of some function, given the derivatives of some cost c with - respect to ws, using ADAM update. `[reference] + """Update weights ws of some function, given the derivatives of some + cost c with respect to ws, using ADAM update. `[reference] `_ @@ -637,9 +631,9 @@ def lamb_update( stop_gradients: Union[bool, ivy.Container] = True, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - Update weights ws of some function, given the derivatives of some cost c with - respect to ws, [dc/dw for w in ws], by applying LAMB method. + """Update weights ws of some function, given the derivatives of some + cost c with respect to ws, [dc/dw for w in ws], by applying LAMB + method. Parameters ---------- diff --git a/ivy/data_classes/container/layers.py b/ivy/data_classes/container/layers.py index b2740bd33dbe2..6d3e681cfbf2d 100644 --- a/ivy/data_classes/container/layers.py +++ b/ivy/data_classes/container/layers.py @@ -26,10 +26,9 @@ def _static_linear( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.linear. This method simply wraps the - function, and so the docstring for ivy.linear also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.linear. This method + simply wraps the function, and so the docstring for ivy.linear also + applies to this method with minimal changes. Parameters ---------- @@ -120,10 +119,9 @@ def linear( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.linear. This method simply wraps - the function, and so the docstring for ivy.linear also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.linear. This method + simply wraps the function, and so the docstring for ivy.linear also + applies to this method with minimal changes. Parameters ---------- @@ -203,10 +201,9 @@ def _static_dropout( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.dropout. This method simply wraps the - function, and so the docstring for ivy.dropout also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.dropout. This method + simply wraps the function, and so the docstring for ivy.dropout also + applies to this method with minimal changes. Parameters ---------- @@ -291,10 +288,9 @@ def dropout( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.dropout. This method simply wraps - the function, and so the docstring for ivy.dropout also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.dropout. This method + simply wraps the function, and so the docstring for ivy.dropout also + applies to this method with minimal changes. Parameters ---------- @@ -376,10 +372,9 @@ def _static_dropout1d( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.dropout1d. This method simply wraps - the function, and so the docstring for ivy.dropout1d also applies to this method - with minimal changes. + """ivy.Container static method variant of ivy.dropout1d. This method + simply wraps the function, and so the docstring for ivy.dropout1d also + applies to this method with minimal changes. Parameters ---------- @@ -448,10 +443,9 @@ def dropout1d( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.dropout1d. This method simply wraps - the function, and so the docstring for ivy.dropout1d also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.dropout1d. This method + simply wraps the function, and so the docstring for ivy.dropout1d also + applies to this method with minimal changes. Parameters ---------- @@ -520,10 +514,9 @@ def _static_dropout2d( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.dropout2d. This method simply wraps - the function, and so the docstring for ivy.dropout2d also applies to this method - with minimal changes. + """ivy.Container static method variant of ivy.dropout2d. This method + simply wraps the function, and so the docstring for ivy.dropout2d also + applies to this method with minimal changes. Parameters ---------- @@ -581,10 +574,9 @@ def dropout2d( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.dropout2d. This method simply wraps - the function, and so the docstring for ivy.dropout2d also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.dropout2d. This method + simply wraps the function, and so the docstring for ivy.dropout2d also + applies to this method with minimal changes. Parameters ---------- @@ -653,10 +645,9 @@ def _static_dropout3d( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.dropout3d. This method simply wraps - the function, and so the docstring for ivy.dropout3d also applies to this method - with minimal changes. + """ivy.Container static method variant of ivy.dropout3d. This method + simply wraps the function, and so the docstring for ivy.dropout3d also + applies to this method with minimal changes. Parameters ---------- @@ -714,10 +705,9 @@ def dropout3d( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.dropout3d. This method simply wraps - the function, and so the docstring for ivy.dropout3d also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.dropout3d. This method + simply wraps the function, and so the docstring for ivy.dropout3d also + applies to this method with minimal changes. Parameters ---------- @@ -779,11 +769,10 @@ def _static_scaled_dot_product_attention( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.scaled_dot_product_attention. This - method simply wraps the function, and so the docstring for - ivy.scaled_dot_product_attention also applies to this method with minimal - changes. + """ivy.Container static method variant of + ivy.scaled_dot_product_attention. This method simply wraps the + function, and so the docstring for ivy.scaled_dot_product_attention + also applies to this method with minimal changes. Parameters ---------- @@ -902,11 +891,10 @@ def scaled_dot_product_attention( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.scaled_dot_product_attention. This - method simply wraps the function, and so the docstring for - ivy.scaled_dot_product_attention also applies to this method with minimal - changes. + """ivy.Container instance method variant of + ivy.scaled_dot_product_attention. This method simply wraps the + function, and so the docstring for ivy.scaled_dot_product_attention + also applies to this method with minimal changes. Parameters ---------- @@ -1206,10 +1194,9 @@ def _static_conv1d( bias: Optional[ivy.Container] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.conv1d. This method simply wraps the - function, and so the docstring for ivy.conv1d also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.conv1d. This method + simply wraps the function, and so the docstring for ivy.conv1d also + applies to this method with minimal changes. Parameters ---------- @@ -1302,10 +1289,9 @@ def conv1d( bias: Optional[ivy.Container] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.conv1d. This method simply wraps - the function, and so the docstring for ivy.conv1d also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.conv1d. This method + simply wraps the function, and so the docstring for ivy.conv1d also + applies to this method with minimal changes. Parameters ---------- @@ -1398,10 +1384,9 @@ def _static_conv2d( bias: Optional[ivy.Container] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.conv2d. This method simply wraps the - function, and so the docstring for ivy.conv2d also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.conv2d. This method + simply wraps the function, and so the docstring for ivy.conv2d also + applies to this method with minimal changes. Parameters ---------- @@ -1488,10 +1473,9 @@ def conv2d( bias: Optional[ivy.Container] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of `ivy.conv2d`. This method simply wraps - the function, and so the docstring for `ivy.conv2d` also applies to this method - with minimal changes. + """ivy.Container instance method variant of `ivy.conv2d`. This method + simply wraps the function, and so the docstring for `ivy.conv2d` also + applies to this method with minimal changes. Parameters ---------- @@ -1568,6 +1552,7 @@ def _static_conv1d_transpose( /, *, output_shape: Optional[Union[ivy.Array, ivy.NativeArray, ivy.Container]] = None, + filter_format: str = "channel_last", data_format: str = "NWC", dilations: Union[int, Tuple[int]] = 1, key_chains: Optional[Union[List[str], Dict[str, str]]] = None, @@ -1577,17 +1562,16 @@ def _static_conv1d_transpose( bias: Optional[ivy.Container] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.conv1d_transpose. This method simply - wraps the function, and so the docstring for ivy.conv1d_transpose also applies - to this method with minimal changes. + """ivy.Container static method variant of ivy.conv1d_transpose. This + method simply wraps the function, and so the docstring for + ivy.conv1d_transpose also applies to this method with minimal changes. Parameters ---------- x Input image *[batch_size,w,d_in]* or *[batch_size,d_in,w]*. filters - Convolution filters *[fw,d_in,d_out]*. + Convolution filters *[fw,d_out,d_in]*. strides The stride of the sliding window for each dimension of input. padding @@ -1596,6 +1580,9 @@ def _static_conv1d_transpose( to apply before and after each spatial dimension. output_shape Shape of the output (Default value = None) + filter_format + Either "channel_first" or "channel_last". "channel_first" corresponds + to "IOW",input data formats, while "channel_last" corresponds to "WOI". data_format The ordering of the dimensions in the input, one of "NWC" or "NCW". "NWC" corresponds to input with shape (batch_size, width, channels), while "NCW" @@ -1628,7 +1615,7 @@ def _static_conv1d_transpose( -------- >>> x = ivy.Container(a=ivy.random_normal(mean=0, std=1, shape=[1, 28, 3]), ... b=ivy.random_normal(mean=0, std=1, shape=[1, 56, 3])) - >>> filters = ivy.random_normal(mean=0, std=1, shape=[3, 3, 6]) + >>> filters = ivy.random_normal(mean=0, std=1, shape=[3, 6, 3]) >>> y = ivy.Container.static_conv1d_transpose(x, filters, 2, 'SAME') >>> print(y.shape) { @@ -1643,6 +1630,7 @@ def _static_conv1d_transpose( strides, padding, output_shape=output_shape, + filter_format=filter_format, data_format=data_format, dilations=dilations, key_chains=key_chains, @@ -1661,6 +1649,7 @@ def conv1d_transpose( /, *, output_shape: Optional[Union[ivy.Array, ivy.NativeArray, ivy.Container]] = None, + filter_format: str = "channel_last", data_format: str = "NWC", dilations: int = 1, key_chains: Optional[Union[List[str], Dict[str, str]]] = None, @@ -1670,17 +1659,16 @@ def conv1d_transpose( bias: Optional[ivy.Container] = None, out: Optional[Union[ivy.Array, ivy.Container]] = None, ) -> Union[ivy.Array, ivy.NativeArray, ivy.Container]: - """ - ivy.Container instance method variant of ivy.conv1d_transpose. This method - simply wraps the function, and so the docstring for ivy.conv1d_transpose also - applies to this method with minimal changes. + """ivy.Container instance method variant of ivy.conv1d_transpose. This + method simply wraps the function, and so the docstring for + ivy.conv1d_transpose also applies to this method with minimal changes. Parameters ---------- self Input image *[batch_size,w,d_in]* or *[batch_size,d_in,w]*. filters - Convolution filters *[fw,d_in,d_out]*. + Convolution filters *[fw,d_out,d_in]*. strides The stride of the sliding window for each dimension of input. padding @@ -1689,6 +1677,9 @@ def conv1d_transpose( to apply before and after each spatial dimension. output_shape Shape of the output (Default value = None) + filter_format + Either "channel_first" or "channel_last". "channel_first" corresponds + to "IOW",input data formats, while "channel_last" corresponds to "WOI". data_format The ordering of the dimensions in the input, one of "NWC" or "NCW". "NWC" corresponds to input with shape (batch_size, width, channels), while "NCW" @@ -1721,7 +1712,7 @@ def conv1d_transpose( -------- >>> x = ivy.Container(a=ivy.random_normal(mean=0, std=1, shape=[1, 28, 3]), ... b=ivy.random_normal(mean=0, std=1, shape=[1, 56, 3])) - >>> filters = ivy.random_normal(mean=0, std=1, shape=[3, 3, 6]) + >>> filters = ivy.random_normal(mean=0, std=1, shape=[3, 6, 3]) >>> y = x.conv1d_transpose(filters, 2, 'SAME') >>> print(y.shape) { @@ -1735,6 +1726,7 @@ def conv1d_transpose( strides, padding, output_shape=output_shape, + filter_format=filter_format, data_format=data_format, dilations=dilations, key_chains=key_chains, @@ -1754,6 +1746,7 @@ def _static_conv2d_transpose( /, *, output_shape: Optional[Union[ivy.Array, ivy.NativeArray, ivy.Container]] = None, + filter_format: str = "channel_last", data_format: str = "NHWC", dilations: Union[int, Tuple[int, int]] = 1, key_chains: Optional[Union[List[str], Dict[str, str]]] = None, @@ -1763,17 +1756,16 @@ def _static_conv2d_transpose( bias: Optional[ivy.Container] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.conv2d_transpose. This method simply - wraps the function, and so the docstring for ivy.conv2d also applies to this - method with minimal changes. + """ivy.Container static method variant of ivy.conv2d_transpose. This + method simply wraps the function, and so the docstring for ivy.conv2d + also applies to this method with minimal changes. Parameters ---------- x Input image *[batch_size,h,w,d_in]*. filters - Convolution filters *[fh,fw,d_in,d_out]*. + Convolution filters *[fh,fw,d_out,d_in]*. strides The stride of the sliding window for each dimension of input. padding @@ -1781,6 +1773,9 @@ def _static_conv2d_transpose( the per-dimension paddings. output_shape Shape of the output (Default value = None) + filter_format + Either "channel_first" or "channel_last". "channel_first" corresponds + to "IOHW",input data formats, while "channel_last" corresponds to "HWOI". data_format "NHWC" or "NCHW". Defaults to "NHWC". dilations @@ -1811,8 +1806,8 @@ def _static_conv2d_transpose( -------- >>> a = ivy.random_normal(mean=0, std=1, shape=[1, 14, 14, 3]) >>> b = ivy.random_normal(mean=0, std=1, shape=[1, 28, 28, 3]) - >>> c = ivy.random_normal(mean=0, std=1, shape=[3, 3, 3, 6]) - >>> d = ivy.random_normal(mean=0, std=1, shape=[3, 3, 3, 6]) + >>> c = ivy.random_normal(mean=0, std=1, shape=[3, 3, 6, 3]) + >>> d = ivy.random_normal(mean=0, std=1, shape=[3, 3, 6, 3]) >>> x = ivy.Container(a=a, b=b) >>> filters = ivy.Container(c=c, d=d) >>> y = ivy.Container.static_conv2d_transpose(x, filters, 2, 'SAME') @@ -1835,6 +1830,7 @@ def _static_conv2d_transpose( strides, padding, output_shape=output_shape, + filter_format=filter_format, data_format=data_format, dilations=dilations, key_chains=key_chains, @@ -1853,6 +1849,7 @@ def conv2d_transpose( /, *, output_shape: Optional[Union[ivy.Array, ivy.NativeArray, ivy.Container]] = None, + filter_format: str = "channel_last", data_format: str = "NHWC", dilations: Union[int, Tuple[int, int]] = 1, key_chains: Optional[Union[List[str], Dict[str, str]]] = None, @@ -1862,17 +1859,16 @@ def conv2d_transpose( bias: Optional[ivy.Container] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.conv2d_transpose. This method - simply wraps the function, and so the docstring for ivy.conv2d also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.conv2d_transpose. This + method simply wraps the function, and so the docstring for ivy.conv2d + also applies to this method with minimal changes. Parameters ---------- self Input image *[batch_size,h,w,d_in]*. filters - Convolution filters *[fh,fw,d_in,d_out]*. + Convolution filters *[fh,fw,d_out,d_in]*. strides The stride of the sliding window for each dimension of input. padding @@ -1880,6 +1876,9 @@ def conv2d_transpose( the per-dimension paddings. output_shape Shape of the output (Default value = None) + filter_format + Either "channel_first" or "channel_last". "channel_first" corresponds + to "IOHW",input data formats, while "channel_last" corresponds to "HWOI". data_format "NHWC" or "NCHW". Defaults to "NHWC". dilations @@ -1941,6 +1940,7 @@ def conv2d_transpose( strides, padding, output_shape=output_shape, + filter_format=filter_format, data_format=data_format, dilations=dilations, key_chains=key_chains, @@ -1967,10 +1967,9 @@ def _static_depthwise_conv2d( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.depthwise_conv2d. This method simply - wraps the function, and so the docstring for ivy.depthwise_conv2d also applies - to this method with minimal changes. + """ivy.Container static method variant of ivy.depthwise_conv2d. This + method simply wraps the function, and so the docstring for + ivy.depthwise_conv2d also applies to this method with minimal changes. Parameters ---------- @@ -2040,10 +2039,9 @@ def depthwise_conv2d( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.depthwise_conv2d. This method - simply wraps the function, and so the docstring for ivy.depthwise_conv2d also - applies to this method with minimal changes. + """ivy.Container instance method variant of ivy.depthwise_conv2d. This + method simply wraps the function, and so the docstring for + ivy.depthwise_conv2d also applies to this method with minimal changes. Parameters ---------- @@ -2112,10 +2110,9 @@ def _static_conv3d( bias: Optional[ivy.Container] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.conv3d. This method simply wraps the - function, and so the docstring for ivy.conv3d also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.conv3d. This method + simply wraps the function, and so the docstring for ivy.conv3d also + applies to this method with minimal changes. Parameters ---------- @@ -2197,10 +2194,9 @@ def conv3d( bias: Optional[ivy.Container] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.conv3d. This method simply wraps - the function, and so the docstring for ivy.conv3d also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.conv3d. This method + simply wraps the function, and so the docstring for ivy.conv3d also + applies to this method with minimal changes. Parameters ---------- @@ -2274,6 +2270,7 @@ def _static_conv3d_transpose( /, *, output_shape: Optional[Union[ivy.Array, ivy.NativeArray, ivy.Container]] = None, + filter_format: str = "channel_last", data_format: str = "NDHWC", dilations: Union[int, Tuple[int], Tuple[int, int], Tuple[int, int, int]] = 1, key_chains: Optional[Union[List[str], Dict[str, str]]] = None, @@ -2283,10 +2280,9 @@ def _static_conv3d_transpose( bias: Optional[ivy.Container] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.conv3d_transpose. This method simply - wraps the function, and so the docstring for ivy.conv3d_transpose also applies - to this method with minimal changes. + """ivy.Container static method variant of ivy.conv3d_transpose. This + method simply wraps the function, and so the docstring for + ivy.conv3d_transpose also applies to this method with minimal changes. Parameters ---------- @@ -2294,7 +2290,7 @@ def _static_conv3d_transpose( Input container with leaves of volume *[batch_size,d,h,w,d_in]* or *[batch_size,d_in,d,h,w]*. filters - Convolution filters *[fd,fh,fw,d_in,d_out]*. + Convolution filters *[fd,fh,fw,d_out,d_in]*. strides The stride of the sliding window for each dimension of input. padding @@ -2302,6 +2298,9 @@ def _static_conv3d_transpose( the per-dimension paddings. output_shape Shape of the output (Default value = None) + filter_format + Either "channel_first" or "channel_last". "channel_first" corresponds + to "IODHW",input data formats, while "channel_last" corresponds to "DHWOI". data_format The ordering of the dimensions in the input, one of "NDHWC" or "NCDHW". "NDHWC" corresponds to inputs with shape (batch_size, @@ -2323,8 +2322,8 @@ def _static_conv3d_transpose( >>> a = ivy.random_normal(mean=0, std=1, shape=[1, 3, 14, 14, 3]) >>> b = ivy.random_normal(mean=0, std=1, shape=[1, 3, 28, 28, 3])) - >>> c = ivy.random_normal(mean=0, std=1, shape=[3, 3, 3, 3, 6]) - >>> d = ivy.random_normal(mean=0, std=1, shape=[3, 3, 3, 3, 6])) + >>> c = ivy.random_normal(mean=0, std=1, shape=[3, 3, 3, 6, 3]) + >>> d = ivy.random_normal(mean=0, std=1, shape=[3, 3, 3, 6, 3])) >>> x = ivy.Container(a=a, b=b) >>> filters = ivy.Container(c=c, d=d) >>> y = ivy.Container.static_conv3d_transpose(x, filters, 2, 'SAME') @@ -2347,6 +2346,7 @@ def _static_conv3d_transpose( strides, padding, output_shape=output_shape, + filter_format=filter_format, data_format=data_format, dilations=dilations, key_chains=key_chains, @@ -2367,6 +2367,7 @@ def conv3d_transpose( /, *, output_shape: Optional[Union[ivy.Array, ivy.NativeArray, ivy.Container]] = None, + filter_format: str = "channel_last", data_format: str = "NDHWC", dilations: Union[int, Tuple[int], Tuple[int, int], Tuple[int, int, int]] = 1, key_chains: Optional[Union[List[str], Dict[str, str]]] = None, @@ -2376,10 +2377,9 @@ def conv3d_transpose( bias: Optional[ivy.Container] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.conv3d_transpose. This method - simply wraps the function, and so the docstring for ivy.conv3d_transpose also - applies to this method with minimal changes. + """ivy.Container instance method variant of ivy.conv3d_transpose. This + method simply wraps the function, and so the docstring for + ivy.conv3d_transpose also applies to this method with minimal changes. Parameters ---------- @@ -2387,7 +2387,7 @@ def conv3d_transpose( Input container with leaves of volume *[batch_size,d,h,w,d_in]* or *[batch_size,d_in,d,h,w]*. filters - Convolution filters *[fd,fh,fw,d_in,d_out]*. + Convolution filters *[fd,fh,fw,d_out,d_in]*. strides The stride of the sliding window for each dimension of input. padding @@ -2395,6 +2395,9 @@ def conv3d_transpose( the per-dimension paddings. output_shape Shape of the output (Default value = None) + filter_format + Either "channel_first" or "channel_last". "channel_first" corresponds + to "IODHW",input data formats, while "channel_last" corresponds to "DHWOI". data_format The ordering of the dimensions in the input, one of "NDHWC" or "NCDHW". "NDHWC" corresponds to inputs with shape (batch_size, @@ -2437,6 +2440,7 @@ def conv3d_transpose( strides, padding, output_shape=output_shape, + filter_format=filter_format, data_format=data_format, dilations=dilations, key_chains=key_chains, @@ -2497,10 +2501,9 @@ def lstm_update( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> Tuple[ivy.Container, ivy.Container]: - """ - ivy.Container instance method variant of ivy.lstm_update. This method simply - wraps the function, and so the docstring for ivy.lstm_update also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.lstm_update. This + method simply wraps the function, and so the docstring for + ivy.lstm_update also applies to this method with minimal changes. Parameters ---------- @@ -2603,10 +2606,9 @@ def reduce_window( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.reduce_window. This method simply - wraps the function, and so the docstring for ivy.reduce_window also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.reduce_window. This + method simply wraps the function, and so the docstring for + ivy.reduce_window also applies to this method with minimal changes. Parameters ---------- diff --git a/ivy/data_classes/container/linear_algebra.py b/ivy/data_classes/container/linear_algebra.py index 20a30dc92b22e..464b7be1fff7e 100644 --- a/ivy/data_classes/container/linear_algebra.py +++ b/ivy/data_classes/container/linear_algebra.py @@ -30,10 +30,9 @@ def _static_matmul( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.matmul. This method simply wraps the - function, and so the docstring for ivy.matul also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.matmul. This method + simply wraps the function, and so the docstring for ivy.matul also + applies to this method with minimal changes. Parameters ---------- @@ -104,10 +103,9 @@ def matmul( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.matmul. This method simply wraps - the function, and so the docstring for ivy.matmul also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.matmul. This method + simply wraps the function, and so the docstring for ivy.matmul also + applies to this method with minimal changes. Parameters ---------- @@ -174,10 +172,9 @@ def _static_cholesky( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.cholesky. This method simply wraps - the function, and so the docstring for ivy.cholesky also applies to this method - with minimal changes. + """ivy.Container static method variant of ivy.cholesky. This method + simply wraps the function, and so the docstring for ivy.cholesky also + applies to this method with minimal changes. Parameters ---------- @@ -261,10 +258,9 @@ def cholesky( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.cholesky. This method simply wraps - the function, and so the docstring for ivy.cholesky also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.cholesky. This method + simply wraps the function, and so the docstring for ivy.cholesky also + applies to this method with minimal changes. Parameters ---------- @@ -336,10 +332,9 @@ def _static_cross( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.cross. This method simply wraps the - function, and so the docstring for ivy.cross also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.cross. This method simply + wraps the function, and so the docstring for ivy.cross also applies to + this method with minimal changes. Parameters ---------- @@ -422,10 +417,9 @@ def cross( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.cross. This method simply wraps the - function, and so the docstring for ivy.cross also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.cross. This method + simply wraps the function, and so the docstring for ivy.cross also + applies to this method with minimal changes. Parameters ---------- @@ -545,10 +539,9 @@ def _static_diagonal( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.diagonal. This method simply wraps - the function, and so the docstring for ivy.diagonal also applies to this method - with minimal changes. + """ivy.Container static method variant of ivy.diagonal. This method + simply wraps the function, and so the docstring for ivy.diagonal also + applies to this method with minimal changes. Parameters ---------- @@ -631,10 +624,9 @@ def diagonal( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.diagonal. This method simply wraps - the function, and so the docstring for ivy.diagonal also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.diagonal. This method + simply wraps the function, and so the docstring for ivy.diagonal also + applies to this method with minimal changes. Parameters ---------- @@ -737,10 +729,9 @@ def diag( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.diag. This method simply wraps the - function, and so the docstring for ivy.diag also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.diag. This method + simply wraps the function, and so the docstring for ivy.diag also + applies to this method with minimal changes. Examples -------- @@ -796,10 +787,9 @@ def eigh( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.eigh. This method simply wraps the - function, and so the docstring for ivy.eigh also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.eigh. This method + simply wraps the function, and so the docstring for ivy.eigh also + applies to this method with minimal changes. Parameters ---------- @@ -868,10 +858,9 @@ def _static_eigvalsh( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.eigvalsh. This method simply wraps - the function, and so the docstring for ivy.eigvalsh also applies to this method - with minimal changes. + """ivy.Container static method variant of ivy.eigvalsh. This method + simply wraps the function, and so the docstring for ivy.eigvalsh also + applies to this method with minimal changes. Parameters ---------- @@ -938,10 +927,9 @@ def eigvalsh( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.eigvalsh. This method simply wraps - the function, and so the docstring for ivy.eigvalsh also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.eigvalsh. This method + simply wraps the function, and so the docstring for ivy.eigvalsh also + applies to this method with minimal changes. Parameters ---------- @@ -1006,10 +994,9 @@ def _static_inner( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.inner. This method simply wraps the - function, and so the docstring for ivy.inner also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.inner. This method simply + wraps the function, and so the docstring for ivy.inner also applies to + this method with minimal changes. Return the inner product of two vectors ``x1`` and ``x2``. @@ -1079,10 +1066,9 @@ def inner( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.inner. This method simply wraps the - function, and so the docstring for ivy.inner also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.inner. This method + simply wraps the function, and so the docstring for ivy.inner also + applies to this method with minimal changes. Return the inner product of two vectors ``self`` and ``x2``. @@ -1150,10 +1136,9 @@ def _static_inv( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.inv. This method simply wraps the - function, and so the docstring for ivy.inv also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.inv. This method simply + wraps the function, and so the docstring for ivy.inv also applies to + this method with minimal changes. Parameters ---------- @@ -1219,10 +1204,9 @@ def inv( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.inv. This method simply wraps the - function, and so the docstring for ivy.inv also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.inv. This method simply + wraps the function, and so the docstring for ivy.inv also applies to + this method with minimal changes. Parameters ---------- @@ -1284,10 +1268,9 @@ def _static_pinv( rtol: Optional[Union[float, Tuple[float], ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container special method variant of ivy.pinv. This method simply wraps the - function, and so the docstring for ivy.pinv also applies to this method with - minimal changes. + """ivy.Container special method variant of ivy.pinv. This method simply + wraps the function, and so the docstring for ivy.pinv also applies to + this method with minimal changes. Parameters ---------- @@ -1343,10 +1326,9 @@ def pinv( rtol: Optional[Union[float, Tuple[float], ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.pinv. This method simply wraps the - function, and so the docstring for ivy.pinv also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.pinv. This method + simply wraps the function, and so the docstring for ivy.pinv also + applies to this method with minimal changes. Parameters ---------- @@ -1409,10 +1391,9 @@ def _static_matrix_norm( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.matrix_norm. This method simply wraps - the function, and so the docstring for ivy.matrix_norm also applies to this - method with minimal changes. + """ivy.Container static method variant of ivy.matrix_norm. This method + simply wraps the function, and so the docstring for ivy.matrix_norm + also applies to this method with minimal changes. Parameters ---------- @@ -1497,10 +1478,9 @@ def matrix_norm( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.matrix_norm. This method simply - wraps the function, and so the docstring for ivy.matrix_norm also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.matrix_norm. This + method simply wraps the function, and so the docstring for + ivy.matrix_norm also applies to this method with minimal changes. Parameters ---------- @@ -1630,10 +1610,9 @@ def _static_matrix_rank( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.matrix_rank. This method returns the - rank (i.e., number of non-zero singular values) of a matrix (or a stack of - matrices). + """ivy.Container static method variant of ivy.matrix_rank. This method + returns the rank (i.e., number of non-zero singular values) of a matrix + (or a stack of matrices). Parameters ---------- @@ -1725,10 +1704,9 @@ def matrix_rank( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.matrix_rank. This method returns - the rank (i.e., number of non-zero singular values) of a matrix (or a stack of - matrices). + """ivy.Container instance method variant of ivy.matrix_rank. This + method returns the rank (i.e., number of non-zero singular values) of a + matrix (or a stack of matrices). Parameters ---------- @@ -1815,8 +1793,7 @@ def _static_matrix_transpose( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - Transpose a matrix (or a stack of matrices) ``x``. + """Transpose a matrix (or a stack of matrices) ``x``. Parameters ---------- @@ -1872,8 +1849,7 @@ def matrix_transpose( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - Transpose a matrix (or a stack of matrices) ``x``. + """Transpose a matrix (or a stack of matrices) ``x``. Parameters ---------- @@ -1928,10 +1904,9 @@ def _static_outer( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.outer. This method simply wraps the - function, and so the docstring for ivy.outer also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.outer. This method simply + wraps the function, and so the docstring for ivy.outer also applies to + this method with minimal changes. Computes the outer product of two arrays, x1 and x2, by computing the tensor product along the last dimension of both arrays. @@ -2003,8 +1978,7 @@ def outer( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - Return the outer product of two arrays or containers. + """Return the outer product of two arrays or containers. The instance method implementation of the static method static_outer of the ivy.Container class. It calculates the outer product of two input arrays or @@ -2076,10 +2050,9 @@ def _static_qr( map_sequences: Union[bool, ivy.Container] = False, out: Optional[Tuple[ivy.Container, ivy.Container]] = None, ) -> Tuple[ivy.Container, ivy.Container]: - """ - ivy.Container static method variant of ivy.qr. This method simply wraps the - function, and so the docstring for ivy.qr also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.qr. This method simply + wraps the function, and so the docstring for ivy.qr also applies to + this method with minimal changes. Returns the qr decomposition x = QR of a full column rank matrix (or a stack of matrices), where Q is an orthonormal matrix (or a stack of matrices) and R is an @@ -2172,10 +2145,9 @@ def qr( map_sequences: Union[bool, ivy.Container] = False, out: Optional[Tuple[ivy.Container, ivy.Container]] = None, ) -> Tuple[ivy.Container, ivy.Container]: - """ - ivy.Container instance method variant of ivy.qr. This method simply wraps the - function, and so the docstring for ivy.qr also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.qr. This method simply + wraps the function, and so the docstring for ivy.qr also applies to + this method with minimal changes. Returns the qr decomposition x = QR of a full column rank matrix (or a stack of matrices), where Q is an orthonormal matrix (or a stack of matrices) and R is an @@ -2266,10 +2238,9 @@ def _static_slogdet( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.slogdet. This method simply wraps the - function, and so the docstring for ivy.slogdet also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.slogdet. This method + simply wraps the function, and so the docstring for ivy.slogdet also + applies to this method with minimal changes. Parameters ---------- @@ -2338,10 +2309,9 @@ def slogdet( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.slogdet. This method simply wraps - the function, and so the docstring for ivy.slogdet also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.slogdet. This method + simply wraps the function, and so the docstring for ivy.slogdet also + applies to this method with minimal changes. Parameters ---------- @@ -2458,10 +2428,9 @@ def _static_svd( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> Union[ivy.Container, Tuple[ivy.Container, ...]]: - """ - ivy.Container static method variant of ivy.svd. This method simply wraps the - function, and so the docstring for ivy.svd also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.svd. This method simply + wraps the function, and so the docstring for ivy.svd also applies to + this method with minimal changes. Parameters ---------- @@ -2531,10 +2500,9 @@ def svd( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.svd. This method simply wraps the - function, and so the docstring for ivy.svd also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.svd. This method simply + wraps the function, and so the docstring for ivy.svd also applies to + this method with minimal changes. Parameters ---------- @@ -2749,9 +2717,9 @@ def _static_trace( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.trace. This method Returns the sum - along the specified diagonals of a matrix (or a stack of matrices). + """ivy.Container static method variant of ivy.trace. This method + Returns the sum along the specified diagonals of a matrix (or a stack + of matrices). Parameters ---------- @@ -2842,9 +2810,9 @@ def trace( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.trace. This method Returns the sum - along the specified diagonals of a matrix (or a stack of matrices). + """ivy.Container instance method variant of ivy.trace. This method + Returns the sum along the specified diagonals of a matrix (or a stack + of matrices). Parameters ---------- @@ -2983,10 +2951,9 @@ def _static_vector_norm( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.vector_norm. This method simply wraps - the function, and so the docstring for ivy.vector_norm also applies to this - method with minimal changes. + """ivy.Container static method variant of ivy.vector_norm. This method + simply wraps the function, and so the docstring for ivy.vector_norm + also applies to this method with minimal changes. Parameters ---------- @@ -3098,10 +3065,9 @@ def vector_norm( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - r""" - ivy.Container instance method variant of ivy.vector_norm. This method simply - wraps the function, and so the docstring for ivy.vector_norm also applies to - this method with minimal changes. + r"""ivy.Container instance method variant of ivy.vector_norm. This + method simply wraps the function, and so the docstring for + ivy.vector_norm also applies to this method with minimal changes. Parameters ---------- @@ -3249,10 +3215,9 @@ def _static_vander( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.vander. This method simply wraps the - function, and so the docstring for ivy.vander also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.vander. This method + simply wraps the function, and so the docstring for ivy.vander also + applies to this method with minimal changes. Parameters ---------- @@ -3317,9 +3282,8 @@ def vander( increasing: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.vander. This method Returns the - Vandermonde matrix of the input array. + """ivy.Container instance method variant of ivy.vander. This method + Returns the Vandermonde matrix of the input array. Parameters ---------- @@ -3384,10 +3348,10 @@ def static_general_inner_product( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.general_inner_product. This method - simply wraps the function, and so the docstring for ivy.general_inner_product - also applies to this method with minimal changes. + """ivy.Container static method variant of ivy.general_inner_product. + This method simply wraps the function, and so the docstring for + ivy.general_inner_product also applies to this method with minimal + changes. Parameters ---------- @@ -3456,8 +3420,7 @@ def general_inner_product( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.general_inner_product. + """ivy.Container instance method variant of ivy.general_inner_product. This method simply wraps the function, and so the docstring for ivy.general_inner_product also applies to this method with diff --git a/ivy/data_classes/container/losses.py b/ivy/data_classes/container/losses.py index 4f3b65b47a39f..52c31b3b7f175 100644 --- a/ivy/data_classes/container/losses.py +++ b/ivy/data_classes/container/losses.py @@ -22,10 +22,9 @@ def _static_cross_entropy( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.cross_entropy. This method simply - wraps the function, and so the docstring for ivy.cross_entropy also applies to - this method with minimal changes. + """ivy.Container static method variant of ivy.cross_entropy. This + method simply wraps the function, and so the docstring for + ivy.cross_entropy also applies to this method with minimal changes. Parameters ---------- @@ -113,10 +112,9 @@ def cross_entropy( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.cross_entropy. This method simply - wraps the function, and so the docstring for ivy.cross_entropy also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.cross_entropy. This + method simply wraps the function, and so the docstring for + ivy.cross_entropy also applies to this method with minimal changes. Parameters ---------- @@ -159,8 +157,8 @@ def cross_entropy( >>> z = x.cross_entropy(y) >>> print(z) { - a:ivy.array(0.5108256), - b:ivy.array(1.609438) + a: ivy.array(0.17027519), + b: ivy.array(0.53647931) } """ return self._static_cross_entropy( @@ -193,10 +191,10 @@ def _static_binary_cross_entropy( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.binary_cross_entropy. This method - simply wraps the function, and so the docstring for ivy.binary_cross_entropy - also applies to this method with minimal changes. + """ivy.Container static method variant of ivy.binary_cross_entropy. + This method simply wraps the function, and so the docstring for + ivy.binary_cross_entropy also applies to this method with minimal + changes. Parameters ---------- @@ -295,10 +293,10 @@ def binary_cross_entropy( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.binary_cross_entropy. This method - simply wraps the function, and so the docstring for ivy.binary_cross_entropy - also applies to this method with minimal changes. + """ivy.Container instance method variant of ivy.binary_cross_entropy. + This method simply wraps the function, and so the docstring for + ivy.binary_cross_entropy also applies to this method with minimal + changes. Parameters ---------- @@ -350,8 +348,8 @@ def binary_cross_entropy( >>> z = x.binary_cross_entropy(y) >>> print(z) { - a: ivy.array([0.511, 0.223, 0.357]), - b: ivy.array([1.61, 0.223, 1.61]) + a: ivy.array(0.36354783), + b: ivy.array(1.14733934) } """ return self._static_binary_cross_entropy( @@ -384,10 +382,10 @@ def _static_sparse_cross_entropy( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.sparse_cross_entropy. This method - simply wraps the function, and so the docstring for ivy.sparse_cross_entropy - also applies to this method with minimal changes. + """ivy.Container static method variant of ivy.sparse_cross_entropy. + This method simply wraps the function, and so the docstring for + ivy.sparse_cross_entropy also applies to this method with minimal + changes. Parameters ---------- @@ -474,10 +472,10 @@ def sparse_cross_entropy( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.sparse_cross_entropy. This method - simply wraps the function, and so the docstring for ivy.sparse_cross_entropy - also applies to this method with minimal changes. + """ivy.Container instance method variant of ivy.sparse_cross_entropy. + This method simply wraps the function, and so the docstring for + ivy.sparse_cross_entropy also applies to this method with minimal + changes. Parameters ---------- @@ -519,8 +517,8 @@ def sparse_cross_entropy( >>> z = x.sparse_cross_entropy(y) >>> print(z) { - a: ivy.array([1.61, 0.511, 0.511]), - b: ivy.array([0.223, 0.223, 1.61]) + a: ivy.array([0.53647929, 0.1702752, 0.1702752]), + b: ivy.array([0.07438118, 0.07438118, 0.53647929]) } """ return self._static_sparse_cross_entropy( diff --git a/ivy/data_classes/container/manipulation.py b/ivy/data_classes/container/manipulation.py index 8c76a746a66d5..2b22319bacb04 100644 --- a/ivy/data_classes/container/manipulation.py +++ b/ivy/data_classes/container/manipulation.py @@ -32,8 +32,7 @@ def _static_concat( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.concat. + """ivy.Container static method variant of ivy.concat. This method simply wraps the function, and so the docstring for ivy.concat also applies to this method with minimal changes. @@ -64,8 +63,7 @@ def concat( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.concat. + """ivy.Container instance method variant of ivy.concat. This method simply wraps the function, and so the docstring for ivy.concat also applies to this method with minimal changes. @@ -95,10 +93,9 @@ def _static_expand_dims( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.expand_dims. This method simply wraps - the function, and so the docstring for ivy.expand_dims also applies to this - method with minimal changes. + """ivy.Container static method variant of ivy.expand_dims. This method + simply wraps the function, and so the docstring for ivy.expand_dims + also applies to this method with minimal changes. Parameters ---------- @@ -194,10 +191,9 @@ def expand_dims( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.expand_dims. This method simply - wraps the function, and so the docstring for ivy.expand_dims also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.expand_dims. This + method simply wraps the function, and so the docstring for + ivy.expand_dims also applies to this method with minimal changes. Parameters ---------- @@ -266,10 +262,9 @@ def _static_split( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> List[ivy.Container]: - """ - ivy.Container static method variant of ivy.split. This method simply wraps the - function, and so the docstring for ivy.split also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.split. This method simply + wraps the function, and so the docstring for ivy.split also applies to + this method with minimal changes. Parameters ---------- @@ -349,10 +344,9 @@ def split( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> List[ivy.Container]: - """ - ivy.Container instance method variant of ivy.split. This method simply wraps the - function, and so the docstring for ivy.split also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.split. This method + simply wraps the function, and so the docstring for ivy.split also + applies to this method with minimal changes. Parameters ---------- @@ -429,10 +423,9 @@ def _static_permute_dims( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.permute_dims. This method simply - wraps the function, and so the docstring for ivy.permute_dims also applies to - this method with minimal changes. + """ivy.Container static method variant of ivy.permute_dims. This method + simply wraps the function, and so the docstring for ivy.permute_dims + also applies to this method with minimal changes. Parameters ---------- @@ -491,10 +484,9 @@ def permute_dims( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.permute_dims. This method simply - wraps the function, and so the docstring for ivy.permute_dims also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.permute_dims. This + method simply wraps the function, and so the docstring for + ivy.permute_dims also applies to this method with minimal changes. Parameters ---------- @@ -553,10 +545,9 @@ def _static_flip( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.flip. This method simply wraps the - function, and so the docstring for ivy.flip also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.flip. This method simply + wraps the function, and so the docstring for ivy.flip also applies to + this method with minimal changes. Parameters ---------- @@ -640,10 +631,9 @@ def flip( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.flip. This method simply wraps the - function, and so the docstring for ivy.flip also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.flip. This method + simply wraps the function, and so the docstring for ivy.flip also + applies to this method with minimal changes. Parameters ---------- @@ -729,10 +719,9 @@ def _static_reshape( order: Union[str, ivy.Container] = "C", allowzero: Union[bool, ivy.Container] = True, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.reshape. This method simply wraps the - function, and so the docstring for ivy.reshape also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.reshape. This method + simply wraps the function, and so the docstring for ivy.reshape also + applies to this method with minimal changes. Parameters ---------- @@ -847,10 +836,9 @@ def reshape( allowzero: Union[bool, ivy.Container] = True, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.reshape. This method simply wraps - the function, and so the docstring for ivy.reshape also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.reshape. This method + simply wraps the function, and so the docstring for ivy.reshape also + applies to this method with minimal changes. Parameters ---------- @@ -956,10 +944,9 @@ def _static_roll( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.roll. This method simply wraps the - function, and so the docstring for ivy.roll also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.roll. This method simply + wraps the function, and so the docstring for ivy.roll also applies to + this method with minimal changes. Parameters ---------- @@ -1048,10 +1035,9 @@ def roll( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.roll. This method simply wraps the - function, and so the docstring for ivy.roll also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.roll. This method + simply wraps the function, and so the docstring for ivy.roll also + applies to this method with minimal changes. Parameters ---------- @@ -1125,10 +1111,9 @@ def _static_squeeze( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.squeeze. This method simply wraps the - function, and so the docstring for ivy.squeeze also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.squeeze. This method + simply wraps the function, and so the docstring for ivy.squeeze also + applies to this method with minimal changes. Parameters ---------- @@ -1207,10 +1192,9 @@ def squeeze( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.squeeze. This method simply wraps - the function, and so the docstring for ivy.squeeze also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.squeeze. This method + simply wraps the function, and so the docstring for ivy.squeeze also + applies to this method with minimal changes. Parameters ---------- @@ -1293,10 +1277,9 @@ def _static_stack( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.stack. This method simply wraps the - function, and so the docstring for ivy.stack also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.stack. This method simply + wraps the function, and so the docstring for ivy.stack also applies to + this method with minimal changes. Parameters ---------- @@ -1390,10 +1373,9 @@ def stack( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.stack. This method simply wraps the - function, and so the docstring for ivy.stack also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.stack. This method + simply wraps the function, and so the docstring for ivy.stack also + applies to this method with minimal changes. Parameters ---------- @@ -1465,10 +1447,9 @@ def _static_repeat( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.repeat. This method simply wraps the - function, and so the docstring for ivy.repeat also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.repeat. This method + simply wraps the function, and so the docstring for ivy.repeat also + applies to this method with minimal changes. Examples -------- @@ -1504,10 +1485,9 @@ def repeat( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.repeat. This method simply wraps - the function, and so the docstring for ivy.repeat also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.repeat. This method + simply wraps the function, and so the docstring for ivy.repeat also + applies to this method with minimal changes. Parameters ---------- @@ -1561,10 +1541,9 @@ def _static_tile( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.tile. This method simply wraps the - function, and so the docstring for ivy.tile also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.tile. This method simply + wraps the function, and so the docstring for ivy.tile also applies to + this method with minimal changes. Parameters ---------- @@ -1617,10 +1596,9 @@ def tile( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.tile. This method simply wraps the - function, and so the docstring for ivy.tile also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.tile. This method + simply wraps the function, and so the docstring for ivy.tile also + applies to this method with minimal changes. Parameters ---------- @@ -1670,10 +1648,9 @@ def _static_constant_pad( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.constant_pad. This method simply - wraps the function, and so the docstring for ivy.constant_pad also applies to - this method with minimal changes. + """ivy.Container static method variant of ivy.constant_pad. This method + simply wraps the function, and so the docstring for ivy.constant_pad + also applies to this method with minimal changes. Parameters ---------- @@ -1729,10 +1706,9 @@ def constant_pad( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.constant_pad. This method simply - wraps the function, and so the docstring for ivy.constant_pad also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.constant_pad. This + method simply wraps the function, and so the docstring for + ivy.constant_pad also applies to this method with minimal changes. Parameters ---------- @@ -1787,10 +1763,9 @@ def _static_zero_pad( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.zero_pad. This method simply wraps - the function, and so the docstring for ivy.zero_pad also applies to this method - with minimal changes. + """ivy.Container static method variant of ivy.zero_pad. This method + simply wraps the function, and so the docstring for ivy.zero_pad also + applies to this method with minimal changes. Parameters ---------- @@ -1854,10 +1829,9 @@ def zero_pad( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.zero_pad. This method simply wraps - the function, and so the docstring for ivy.zero_pad also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.zero_pad. This method + simply wraps the function, and so the docstring for ivy.zero_pad also + applies to this method with minimal changes. Parameters ---------- @@ -1923,10 +1897,9 @@ def _static_swapaxes( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.swapaxes. This method simply wraps - the function, and so the docstring for ivy.swapaxes also applies to this method - with minimal changes. + """ivy.Container static method variant of ivy.swapaxes. This method + simply wraps the function, and so the docstring for ivy.swapaxes also + applies to this method with minimal changes. Parameters ---------- @@ -1992,10 +1965,9 @@ def swapaxes( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.swapaxes. This method simply wraps - the function, and so the docstring for ivy.swapaxes also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.swapaxes. This method + simply wraps the function, and so the docstring for ivy.swapaxes also + applies to this method with minimal changes. Parameters ---------- @@ -2062,10 +2034,9 @@ def _static_unstack( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.unstack. This method simply wraps the - function, and so the docstring for ivy.unstack also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.unstack. This method + simply wraps the function, and so the docstring for ivy.unstack also + applies to this method with minimal changes. Parameters ---------- @@ -2160,10 +2131,9 @@ def unstack( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.unstack. This method simply wraps - the function, and so the docstring for ivy.unstack also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.unstack. This method + simply wraps the function, and so the docstring for ivy.unstack also + applies to this method with minimal changes. Parameters ---------- @@ -2244,10 +2214,9 @@ def _static_clip( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.clip. This method simply wraps the - function, and so the docstring for ivy.clip also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.clip. This method simply + wraps the function, and so the docstring for ivy.clip also applies to + this method with minimal changes. Parameters ---------- @@ -2318,13 +2287,13 @@ def _static_clip( def clip( self: ivy.Container, + /, x_min: Optional[ Union[Number, ivy.Array, ivy.NativeArray, ivy.Container] ] = None, x_max: Optional[ Union[Number, ivy.Array, ivy.NativeArray, ivy.Container] ] = None, - /, *, key_chains: Optional[Union[List[str], Dict[str, str], ivy.Container]] = None, to_apply: Union[bool, ivy.Container] = True, @@ -2332,10 +2301,9 @@ def clip( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.clip. This method simply wraps the - function, and so the docstring for ivy.clip also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.clip. This method + simply wraps the function, and so the docstring for ivy.clip also + applies to this method with minimal changes. Parameters ---------- diff --git a/ivy/data_classes/container/norms.py b/ivy/data_classes/container/norms.py index 948ff38dfbb94..39369ceba4e38 100644 --- a/ivy/data_classes/container/norms.py +++ b/ivy/data_classes/container/norms.py @@ -21,10 +21,9 @@ def layer_norm( new_std: Union[float, ivy.Container] = 1.0, out: Optional[Union[ivy.Array, ivy.Container]] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.layer_norm. This method simply - wraps the function, and so the docstring for ivy.layer_norm also applies to this - method with minimal changes. + """ivy.Container instance method variant of ivy.layer_norm. This method + simply wraps the function, and so the docstring for ivy.layer_norm also + applies to this method with minimal changes. Parameters ---------- diff --git a/ivy/data_classes/container/random.py b/ivy/data_classes/container/random.py index bb7aa8c69dcc6..2932594f3fc43 100644 --- a/ivy/data_classes/container/random.py +++ b/ivy/data_classes/container/random.py @@ -23,10 +23,9 @@ def _static_random_uniform( seed: Optional[Union[int, ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.random_uniform. This method simply - wraps the function, and so the docstring for ivy.random_uniform also applies to - this method with minimal changes. + """ivy.Container static method variant of ivy.random_uniform. This + method simply wraps the function, and so the docstring for + ivy.random_uniform also applies to this method with minimal changes. Parameters ---------- @@ -127,10 +126,9 @@ def random_uniform( seed: Optional[Union[int, ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.random_uniform. This method simply - wraps the function, and so the docstring for ivy.random_uniform also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.random_uniform. This + method simply wraps the function, and so the docstring for + ivy.random_uniform also applies to this method with minimal changes. Parameters ---------- @@ -314,10 +312,9 @@ def _static_random_normal( seed: Optional[Union[int, ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.random_normal. This method simply - wraps the function, and so the docstring for ivy.random_normal also applies to - this method with minimal changes. + """ivy.Container static method variant of ivy.random_normal. This + method simply wraps the function, and so the docstring for + ivy.random_normal also applies to this method with minimal changes. Parameters ---------- @@ -416,10 +413,9 @@ def random_normal( seed: Optional[Union[int, ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.random_normal. This method simply - wraps the function, and so the docstring for ivy.random_normal also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.random_normal. This + method simply wraps the function, and so the docstring for + ivy.random_normal also applies to this method with minimal changes. Parameters ---------- @@ -604,10 +600,9 @@ def _static_multinomial( seed: Optional[Union[int, ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.multinomial. This method simply wraps - the function, and so the docstring for ivy.multinomial also applies to this - method with minimal changes. + """ivy.Container static method variant of ivy.multinomial. This method + simply wraps the function, and so the docstring for ivy.multinomial + also applies to this method with minimal changes. Parameters ---------- @@ -679,10 +674,9 @@ def multinomial( seed: Optional[Union[int, ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.multinomial. This method simply - wraps the function, and so the docstring for ivy.multinomial also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.multinomial. This + method simply wraps the function, and so the docstring for + ivy.multinomial also applies to this method with minimal changes. Parameters ---------- @@ -753,10 +747,9 @@ def _static_randint( seed: Optional[Union[int, ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.randint. This method simply wraps the - function, and so the docstring for ivy.randint also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.randint. This method + simply wraps the function, and so the docstring for ivy.randint also + applies to this method with minimal changes. Parameters ---------- @@ -854,10 +847,9 @@ def randint( seed: Optional[Union[int, ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.randint. This method simply wraps - the function, and so the docstring for ivy.randint also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.randint. This method + simply wraps the function, and so the docstring for ivy.randint also + applies to this method with minimal changes. Parameters ---------- @@ -1038,10 +1030,9 @@ def _static_shuffle( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.shuffle. This method simply wraps the - function, and so the docstring for ivy.shuffle also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.shuffle. This method + simply wraps the function, and so the docstring for ivy.shuffle also + applies to this method with minimal changes. Parameters ---------- @@ -1105,10 +1096,9 @@ def shuffle( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.shuffle. This method simply wraps - the function, and so the docstring for ivy.shuffle also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.shuffle. This method + simply wraps the function, and so the docstring for ivy.shuffle also + applies to this method with minimal changes. Parameters ---------- diff --git a/ivy/data_classes/container/searching.py b/ivy/data_classes/container/searching.py index c007d1f67cc8e..d8ceb13e8910c 100644 --- a/ivy/data_classes/container/searching.py +++ b/ivy/data_classes/container/searching.py @@ -20,10 +20,9 @@ def _static_argmax( select_last_index: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.argmax. This method simply wraps the - function, and so the docstring for ivy.argmax also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.argmax. This method + simply wraps the function, and so the docstring for ivy.argmax also + applies to this method with minimal changes. Parameters ---------- @@ -81,10 +80,9 @@ def argmax( select_last_index: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.argmax. This method simply wraps - the function, and so the docstring for ivy.argmax also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.argmax. This method + simply wraps the function, and so the docstring for ivy.argmax also + applies to this method with minimal changes. Parameters ---------- @@ -143,10 +141,9 @@ def _static_argmin( select_last_index: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.argmin. This method simply wraps the - function, and so the docstring for ivy.argmin also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.argmin. This method + simply wraps the function, and so the docstring for ivy.argmin also + applies to this method with minimal changes. Parameters ---------- @@ -205,10 +202,9 @@ def argmin( select_last_index: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.argmin. This method simply wraps - the function, and so the docstring for ivy.argmin also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.argmin. This method + simply wraps the function, and so the docstring for ivy.argmin also + applies to this method with minimal changes. Parameters ---------- @@ -275,10 +271,9 @@ def _static_nonzero( size: Optional[Union[int, ivy.Container]] = None, fill_value: Union[Number, ivy.Container] = 0, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.nonzero. This method simply wraps the - function, and so the docstring for ivy.nonzero also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.nonzero. This method + simply wraps the function, and so the docstring for ivy.nonzero also + applies to this method with minimal changes. Parameters ---------- @@ -315,10 +310,9 @@ def nonzero( size: Optional[Union[int, ivy.Container]] = None, fill_value: Union[Number, ivy.Container] = 0, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.nonzero. This method simply wraps - the function, and so the docstring for ivy.nonzero also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.nonzero. This method + simply wraps the function, and so the docstring for ivy.nonzero also + applies to this method with minimal changes. Parameters ---------- @@ -356,10 +350,9 @@ def _static_where( *, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.where. This method simply wraps the - function, and so the docstring for ivy.where also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.where. This method simply + wraps the function, and so the docstring for ivy.where also applies to + this method with minimal changes. Parameters ---------- @@ -402,10 +395,9 @@ def where( *, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.where. This method simply wraps the - function, and so the docstring for ivy.where also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.where. This method + simply wraps the function, and so the docstring for ivy.where also + applies to this method with minimal changes. Parameters ---------- @@ -452,10 +444,9 @@ def _static_argwhere( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.argwhere. This method simply wraps - the function, and so the docstring for ivy.argwhere also applies to this method - with minimal changes. + """ivy.Container static method variant of ivy.argwhere. This method + simply wraps the function, and so the docstring for ivy.argwhere also + applies to this method with minimal changes. Parameters ---------- @@ -518,10 +509,9 @@ def argwhere( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ): - """ - ivy.Container instance method variant of ivy.argwhere. This method simply wraps - the function, and so the docstring for ivy.argwhere also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.argwhere. This method + simply wraps the function, and so the docstring for ivy.argwhere also + applies to this method with minimal changes. Parameters ---------- diff --git a/ivy/data_classes/container/set.py b/ivy/data_classes/container/set.py index e45c0e748ff86..e388499e07c52 100644 --- a/ivy/data_classes/container/set.py +++ b/ivy/data_classes/container/set.py @@ -19,10 +19,9 @@ def _static_unique_all( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.unique_all. This method simply wraps - the function, and so the docstring for ivy.unique_all also applies to this - method with minimal changes. + """ivy.Container static method variant of ivy.unique_all. This method + simply wraps the function, and so the docstring for ivy.unique_all also + applies to this method with minimal changes. Parameters ---------- @@ -97,10 +96,9 @@ def unique_all( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.unique_all. This method simply - wraps the function, and so the docstring for ivy.unique_all also applies to this - method with minimal changes. + """ivy.Container instance method variant of ivy.unique_all. This method + simply wraps the function, and so the docstring for ivy.unique_all also + applies to this method with minimal changes. Parameters ---------- @@ -172,10 +170,9 @@ def _static_unique_counts( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.unique_counts. This method simply - wraps the function, and so the docstring for ivy.unique_counts also applies to - this method with minimal changes. + """ivy.Container static method variant of ivy.unique_counts. This + method simply wraps the function, and so the docstring for + ivy.unique_counts also applies to this method with minimal changes. Parameters ---------- @@ -236,10 +233,9 @@ def unique_counts( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.unique_counts. This method simply - wraps the function, and so the docstring for ivy.unique_counts also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.unique_counts. This + method simply wraps the function, and so the docstring for + ivy.unique_counts also applies to this method with minimal changes. Parameters ---------- @@ -326,9 +322,8 @@ def unique_values( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.unique_values. This method simply - wraps the function and applies it on the container. + """ivy.Container instance method variant of ivy.unique_values. This + method simply wraps the function and applies it on the container. Parameters ---------- @@ -404,10 +399,9 @@ def _static_unique_inverse( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.unique_inverse. This method simply - wraps the function, and so the docstring for ivy.unique_inverse also applies to - this method with minimal changes. + """ivy.Container static method variant of ivy.unique_inverse. This + method simply wraps the function, and so the docstring for + ivy.unique_inverse also applies to this method with minimal changes. Parameters ---------- @@ -469,10 +463,9 @@ def unique_inverse( prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.unique_inverse. This method simply - wraps the function, and so the docstring for ivy.unique_inverse also applies to - this method with minimal changes. + """ivy.Container instance method variant of ivy.unique_inverse. This + method simply wraps the function, and so the docstring for + ivy.unique_inverse also applies to this method with minimal changes. Parameters ---------- @@ -518,6 +511,18 @@ def unique_inverse( a: ivy.array([1, 3, 0, 2, 4, 1]), b: ivy.array([5, 4, 2, 3, 4, 1, 0]) }] + + >>> x = ivy.Container(a=ivy.array([1., 4., 3. , 5. , 3. , 7.]), + ... b=ivy.array([3, 2, 6, 3, 7, 4, 9])) + >>> y = ivy.ivy.unique_inverse(x) + >>> print(y) + [{ + a: ivy.array([1., 3., 4., 5., 7.]), + b: ivy.array([2, 3, 4, 6, 7, 9]) + }, { + a: ivy.array([0, 2, 1, 3, 1, 4]), + b: ivy.array([1, 0, 3, 1, 4, 2, 5]) + }] """ return self._static_unique_inverse( self, diff --git a/ivy/data_classes/container/sorting.py b/ivy/data_classes/container/sorting.py index 8b1938b5ad7c8..a6409a5f176c8 100644 --- a/ivy/data_classes/container/sorting.py +++ b/ivy/data_classes/container/sorting.py @@ -24,10 +24,9 @@ def _static_argsort( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.argsort. This method simply wraps the - function, and so the docstring for ivy.argsort also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.argsort. This method + simply wraps the function, and so the docstring for ivy.argsort also + applies to this method with minimal changes. Parameters ---------- @@ -138,10 +137,9 @@ def argsort( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.argsort. This method simply wraps - the function, and so the docstring for ivy.argsort also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.argsort. This method + simply wraps the function, and so the docstring for ivy.argsort also + applies to this method with minimal changes. Parameters ---------- @@ -222,10 +220,9 @@ def _static_sort( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.sort. This method simply wraps the - function, and so the docstring for ivy.sort also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.sort. This method simply + wraps the function, and so the docstring for ivy.sort also applies to + this method with minimal changes. Examples -------- @@ -275,10 +272,9 @@ def sort( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.sort. This method simply wraps the - function, and so the docstring for ivy.sort also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.sort. This method + simply wraps the function, and so the docstring for ivy.sort also + applies to this method with minimal changes. Examples -------- @@ -341,10 +337,9 @@ def static_msort( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.msort. This method simply wraps the - function, and so the docstring for ivy.msort also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.msort. This method simply + wraps the function, and so the docstring for ivy.msort also applies to + this method with minimal changes. Parameters ---------- @@ -396,10 +391,9 @@ def msort( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.msort. This method simply wraps the - function, and so the docstring for ivy.msort also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.msort. This method + simply wraps the function, and so the docstring for ivy.msort also + applies to this method with minimal changes. Parameters ---------- @@ -455,8 +449,7 @@ def _static_searchsorted( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.searchsorted. + """ivy.Container static method variant of ivy.searchsorted. This method simply wraps the function, and so the docstring for ivy.searchsorted also applies to this method with minimal @@ -492,8 +485,7 @@ def searchsorted( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.searchsorted. + """ivy.Container instance method variant of ivy.searchsorted. This method simply wraps the function, and so the docstring for ivy.searchsorted also applies to this method with minimal diff --git a/ivy/data_classes/container/statistical.py b/ivy/data_classes/container/statistical.py index 2d527a7a46b09..26db9e83fab4b 100644 --- a/ivy/data_classes/container/statistical.py +++ b/ivy/data_classes/container/statistical.py @@ -9,22 +9,110 @@ class _ContainerWithStatistical(ContainerBase): + @staticmethod + def _static_min( + x: ivy.Container, + /, + *, + axis: Optional[Union[int, Sequence[int], ivy.Container]] = None, + keepdims: Union[bool, ivy.Container] = False, + initial: Optional[Union[int, float, complex, ivy.Container]] = None, + where: Optional[Union[ivy.Array, ivy.Container]] = None, + key_chains: Optional[Union[List[str], Dict[str, str], ivy.Container]] = None, + to_apply: Union[bool, ivy.Container] = True, + prune_unapplied: Union[bool, ivy.Container] = False, + map_sequences: Union[bool, ivy.Container] = False, + out: Optional[ivy.Container] = None, + ): + """ivy.Container static method variant of ivy.min. This method simply + wraps the function, and so the docstring for ivy.min also applies to + this method with minimal changes. + + Parameters + ---------- + self + Input container. Should have a real-valued data type. + axis + axis or axes along which minimum values must be computed. + By default, the minimum value must be computed over the + entire array. If a tuple of integers, minimum values must + be computed over multiple axes. Default: ``None``. + keepdims + optional boolean, if ``True``, the reduced axes + (dimensions) must be included in the result as + singleton dimensions, and, accordingly, the result + must be compatible with the input array + (see :ref:`broadcasting`). Otherwise, if ``False``, the + reduced axes (dimensions) must not be included in the + result. Default: ``False``. + initial + The maximum value of an output element. + Must be present to allow computation on empty slice. + where + Elements to compare for minimum + out + optional output array, for writing the result to. + + Returns + ------- + ret + if the minimum value was computed over the entire array, + a zero-dimensional array containing the minimum value; + otherwise, a non-zero-dimensional array containing the + minimum values. The returned array must have the same data type + as ``x``. + + Examples + -------- + With :class:`ivy.Container` input: + >> > x = ivy.Container(a=ivy.array([1, 2, 3]), \ + b=ivy.array([2, 3, 4])) + >> > z = x.min() + >> > print(z) + { + a: ivy.array(1), + b: ivy.array(2) + } + >>> x = ivy.Container(a=ivy.array([[1, 2, 3],[-1,0,2]]), + ... b=ivy.array([[2, 3, 4], [0, 1, 2]])) + >>> z = x.min(axis=1) + >>> print(z) + { + a:ivy.array([1,-1]), + b:ivy.array([2,0]) + } + """ + return ContainerBase.cont_multi_map_in_function( + "min", + x, + axis=axis, + keepdims=keepdims, + initial=initial, + where=where, + key_chains=key_chains, + to_apply=to_apply, + prune_unapplied=prune_unapplied, + map_sequences=map_sequences, + out=out, + ) + def min( self: ivy.Container, /, *, axis: Optional[Union[int, Sequence[int], ivy.Container]] = None, keepdims: Union[bool, ivy.Container] = False, + initial: Optional[Union[int, float, complex, ivy.Container]] = None, + where: Optional[Union[ivy.Array, ivy.Container]] = None, key_chains: Optional[Union[List[str], Dict[str, str], ivy.Container]] = None, to_apply: Union[bool, ivy.Container] = True, prune_unapplied: Union[bool, ivy.Container] = False, map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.min. This method simply wraps the - function, and so the docstring for ivy.min also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.min. This method simply + wraps the function, and so the docstring for ivy.min also applies to + this method with minimal changes. Parameters ---------- @@ -43,6 +131,11 @@ def min( (see :ref:`broadcasting`). Otherwise, if ``False``, the reduced axes (dimensions) must not be included in the result. Default: ``False``. + initial + The maximum value of an output element. + Must be present to allow computation on empty slice. + where + Elements to compare for minimum out optional output array, for writing the result to. @@ -77,18 +170,16 @@ def min( b:ivy.array([2,0]) } """ - return self.cont_handle_inplace( - self.cont_map( - lambda x_, _: ( - ivy.min(x_, axis=axis, keepdims=keepdims) - if ivy.is_array(x_) - else x_ - ), - key_chains=key_chains, - to_apply=to_apply, - prune_unapplied=prune_unapplied, - map_sequences=map_sequences, - ), + return self._static_min( + self, + axis=axis, + keepdims=keepdims, + initial=initial, + where=where, + key_chains=key_chains, + to_apply=to_apply, + prune_unapplied=prune_unapplied, + map_sequences=map_sequences, out=out, ) @@ -104,10 +195,9 @@ def max( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.max. This method simply wraps the - function, and so the docstring for ivy.max also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.max. This method simply + wraps the function, and so the docstring for ivy.max also applies to + this method with minimal changes. Parameters ---------- @@ -184,10 +274,9 @@ def mean( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.mean. This method simply wraps the - function, and so the docstring for ivy.mean also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.mean. This method + simply wraps the function, and so the docstring for ivy.mean also + applies to this method with minimal changes. Parameters ---------- @@ -319,10 +408,9 @@ def var( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.var. This method simply wraps the - function, and so the docstring for ivy.var also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.var. This method simply + wraps the function, and so the docstring for ivy.var also applies to + this method with minimal changes. Parameters ---------- @@ -437,10 +525,9 @@ def _static_var( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.var. This method simply wraps the - function, and so the docstring for ivy.var also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.var. This method simply + wraps the function, and so the docstring for ivy.var also applies to + this method with minimal changes. Parameters ---------- @@ -509,10 +596,9 @@ def _static_prod( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ): - """ - ivy.Container static method variant of ivy.prod. This method simply wraps the - function, and so the docstring for ivy.prod also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.prod. This method simply + wraps the function, and so the docstring for ivy.prod also applies to + this method with minimal changes. Parameters ---------- @@ -648,10 +734,9 @@ def prod( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.prod. This method simply wraps the - function, and so the docstring for ivy.prod also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.prod. This method + simply wraps the function, and so the docstring for ivy.prod also + applies to this method with minimal changes. Parameters ---------- @@ -840,10 +925,9 @@ def std( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.std. This method simply wraps the - function, and so the docstring for ivy.std also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.std. This method simply + wraps the function, and so the docstring for ivy.std also applies to + this method with minimal changes. Parameters ---------- @@ -990,10 +1074,9 @@ def _static_cumsum( dtype: Optional[Union[ivy.Dtype, ivy.NativeDtype, ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.cumsum. This method simply wraps the - function, and so the docstring for ivy.cumsum also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.cumsum. This method + simply wraps the function, and so the docstring for ivy.cumsum also + applies to this method with minimal changes. Parameters ---------- @@ -1132,10 +1215,9 @@ def cumsum( dtype: Optional[Union[ivy.Dtype, ivy.NativeDtype, ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.cumsum. This method simply wraps - the function, and so the docstring for ivy.cumsum also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.cumsum. This method + simply wraps the function, and so the docstring for ivy.cumsum also + applies to this method with minimal changes. Parameters ---------- @@ -1289,10 +1371,9 @@ def _static_cumprod( dtype: Optional[Union[ivy.Dtype, ivy.NativeDtype, ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.cumprod. This method simply wraps the - function, and so the docstring for ivy.cumprod also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.cumprod. This method + simply wraps the function, and so the docstring for ivy.cumprod also + applies to this method with minimal changes. Parameters ---------- @@ -1381,10 +1462,9 @@ def cumprod( dtype: Optional[Union[ivy.Dtype, ivy.NativeDtype, ivy.Container]] = None, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.cumprod. This method simply wraps - the function, and so the docstring for ivy.cumprod also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.cumprod. This method + simply wraps the function, and so the docstring for ivy.cumprod also + applies to this method with minimal changes. Parameters ---------- diff --git a/ivy/data_classes/container/utility.py b/ivy/data_classes/container/utility.py index d6298db810436..4be1c16810d91 100644 --- a/ivy/data_classes/container/utility.py +++ b/ivy/data_classes/container/utility.py @@ -23,10 +23,9 @@ def _static_all( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.all. This method simply wraps the - function, and so the docstring for ivy.all also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.all. This method simply + wraps the function, and so the docstring for ivy.all also applies to + this method with minimal changes. Parameters ---------- @@ -108,10 +107,9 @@ def all( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.all. This method simply wraps the - function, and so the docstring for ivy.all also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.all. This method simply + wraps the function, and so the docstring for ivy.all also applies to + this method with minimal changes. Parameters ---------- @@ -193,10 +191,9 @@ def _static_any( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container static method variant of ivy.any. This method simply wraps the - function, and so the docstring for ivy.any also applies to this method with - minimal changes. + """ivy.Container static method variant of ivy.any. This method simply + wraps the function, and so the docstring for ivy.any also applies to + this method with minimal changes. Parameters ---------- @@ -278,10 +275,9 @@ def any( map_sequences: Union[bool, ivy.Container] = False, out: Optional[ivy.Container] = None, ) -> ivy.Container: - """ - ivy.Container instance method variant of ivy.any. This method simply wraps the - function, and so the docstring for ivy.any also applies to this method with - minimal changes. + """ivy.Container instance method variant of ivy.any. This method simply + wraps the function, and so the docstring for ivy.any also applies to + this method with minimal changes. Parameters ---------- diff --git a/ivy/data_classes/container/wrapping.py b/ivy/data_classes/container/wrapping.py index c4c500cb8e04b..8bbb2b30b5809 100644 --- a/ivy/data_classes/container/wrapping.py +++ b/ivy/data_classes/container/wrapping.py @@ -9,8 +9,7 @@ def _wrap_function(function_name: str, static: bool) -> Callable: - """ - Wrap the function called `function_name`. + """Wrap the function called `function_name`. Parameters ---------- @@ -83,9 +82,8 @@ def add_ivy_container_instance_methods( static: Union[bool, ivy.Container] = False, to_ignore: Union[Iterable, ivy.Container] = (), ): - """ - Loop over all ivy modules such as activations, general, etc. and add the module - functions to ivy container as instance methods using _wrap_function. + """Loop over all ivy modules such as activations, general, etc. and add the + module functions to ivy container as instance methods using _wrap_function. Parameters ---------- diff --git a/ivy/data_classes/factorized_tensor/cp_tensor.py b/ivy/data_classes/factorized_tensor/cp_tensor.py index 72d72d7242641..7def7d8288202 100644 --- a/ivy/data_classes/factorized_tensor/cp_tensor.py +++ b/ivy/data_classes/factorized_tensor/cp_tensor.py @@ -76,8 +76,8 @@ def cp_copy(self): ) def mode_dot(self, matrix_or_vector, mode, keep_dim=False, copy=True): - """ - N-mode product of a CP tensor and a matrix or vector at the specified mode. + """N-mode product of a CP tensor and a matrix or vector at the + specified mode. Parameters ---------- @@ -107,8 +107,7 @@ def mode_dot(self, matrix_or_vector, mode, keep_dim=False, copy=True): ) def norm(self): - """ - Return the l2 norm of a CP tensor. + """Return the l2 norm of a CP tensor. Parameters ---------- @@ -130,8 +129,7 @@ def norm(self): return ivy.CPTensor.cp_norm(self) def normalize(self, inplace=True): - """ - Normalize the factors to unit length. + """Normalize the factors to unit length. Turns ``factors = [|U_1, ... U_n|]`` into ``[weights; |V_1, ... V_n|]``, where the columns of each `V_k` are normalized to unit Euclidean length @@ -179,8 +177,7 @@ def n_param(self): # ---------------# @staticmethod def validate_cp_tensor(cp_tensor): - """ - Validate a cp_tensor in the form (weights, factors) + """Validate a cp_tensor in the form (weights, factors) Return the rank and shape of the validated tensor @@ -239,9 +236,8 @@ def validate_cp_tensor(cp_tensor): @staticmethod def cp_n_param(tensor_shape, rank, weights=False): - """ - Return number of parameters of a CP decomposition for a given `rank` and full - `tensor_shape`. + """Return number of parameters of a CP decomposition for a given `rank` + and full `tensor_shape`. Parameters ---------- @@ -264,8 +260,7 @@ def cp_n_param(tensor_shape, rank, weights=False): @staticmethod def validate_cp_rank(tensor_shape, rank="same", rounding="round"): - """ - Return the rank of a CP Decomposition. + """Return the rank of a CP Decomposition. Parameters ---------- @@ -308,8 +303,7 @@ def validate_cp_rank(tensor_shape, rank="same", rounding="round"): @staticmethod def cp_normalize(cp_tensor): - """ - Return cp_tensor with factors normalised to unit length. + """Return cp_tensor with factors normalised to unit length. Turns ``factors = [|U_1, ... U_n|]`` into ``[weights; |V_1, ... V_n|]``, where the columns of each `V_k` are @@ -357,10 +351,10 @@ def cp_normalize(cp_tensor): @staticmethod def cp_flip_sign(cp_tensor, mode=0, func=None): - """ - Return cp_tensor with factors flipped to have positive signs. The sign of a - given column is determined by `func`, which is the mean by default. Any negative - signs are assigned to the mode indicated by `mode`. + """Return cp_tensor with factors flipped to have positive signs. The + sign of a given column is determined by `func`, which is the mean by + default. Any negative signs are assigned to the mode indicated by + `mode`. Parameters ---------- @@ -412,16 +406,15 @@ def cp_flip_sign(cp_tensor, mode=0, func=None): @staticmethod def cp_lstsq_grad(cp_tensor, tensor, return_loss=False, mask=None): - r""" - Compute (for a third-order tensor) + r"""Compute (for a third-order tensor) .. math:: - \nabla 0.5 ||\\mathcal{X} - [\\mathbf{w}; \\mathbf{A}, \\mathbf{B}, \\mathbf{C}]||^2 # noqa + \nabla 0.5 ||\\mathcal{X} - [\\mathbf{w}; \\mathbf{A}, \\mathbf{B}, \\mathbf{C}]||^2 where :math:`[\\mathbf{w}; \\mathbf{A}, \\mathbf{B}, \\mathbf{C}]` is the CP decomposition with weights - :math:`\\mathbf{w}` and factor matrices :math:`\\mathbf{A}`, :math:`\\mathbf{B}` and :math:`\\mathbf{C}`. # noqa + :math:`\\mathbf{w}` and factor matrices :math:`\\mathbf{A}`, :math:`\\mathbf{B}` and :math:`\\mathbf{C}`. Note that this does not return the gradient with respect to the weights even if CP is normalized. @@ -453,7 +446,7 @@ def cp_lstsq_grad(cp_tensor, tensor, return_loss=False, mask=None): loss : float Scalar quantity of the loss function corresponding to cp_gradient. Only returned if return_loss = True. - """ + """ # noqa: E501 ivy.CPTensor.validate_cp_tensor(cp_tensor) _, factors = cp_tensor @@ -474,8 +467,7 @@ def cp_lstsq_grad(cp_tensor, tensor, return_loss=False, mask=None): @staticmethod def cp_to_tensor(cp_tensor, mask=None): - """ - Turn the Khatri-product of matrices into a full tensor. + """Turn the Khatri-product of matrices into a full tensor. ``factor_matrices = [|U_1, ... U_n|]`` becomes a tensor shape ``(U[1].shape[0], U[2].shape[0], ... U[-1].shape[0])`` @@ -532,8 +524,7 @@ def cp_to_tensor(cp_tensor, mask=None): @staticmethod def cp_to_unfolded(cp_tensor, mode): - """ - Turn the khatri-product of matrices into an unfolded tensor. + """Turn the khatri-product of matrices into an unfolded tensor. turns ``factors = [|U_1, ... U_n|]`` into a mode-`mode` unfolding of the tensor @@ -573,8 +564,7 @@ def cp_to_unfolded(cp_tensor, mode): @staticmethod def cp_to_vec(cp_tensor): - """ - Turn the khatri-product of matrices into a vector. + """Turn the khatri-product of matrices into a vector. (the tensor ``factors = [|U_1, ... U_n|]`` is converted into a raveled mode-0 unfolding) @@ -599,8 +589,8 @@ def cp_to_vec(cp_tensor): @staticmethod def cp_mode_dot(cp_tensor, matrix_or_vector, mode, keep_dim=False, copy=False): - """ - N-mode product of a CP tensor and a matrix or vector at the specified mode. + """N-mode product of a CP tensor and a matrix or vector at the + specified mode. Parameters ---------- @@ -671,8 +661,7 @@ def cp_mode_dot(cp_tensor, matrix_or_vector, mode, keep_dim=False, copy=False): @staticmethod def cp_norm(cp_tensor): - """ - Return the l2 norm of a CP tensor. + """Return the l2 norm of a CP tensor. Parameters ---------- @@ -764,8 +753,7 @@ def cp_norm(cp_tensor): @staticmethod def unfolding_dot_khatri_rao(x, cp_tensor, mode): - """ - Mode-n unfolding times khatri-rao product of factors. + """Mode-n unfolding times khatri-rao product of factors. Parameters ---------- diff --git a/ivy/data_classes/factorized_tensor/parafac2_tensor.py b/ivy/data_classes/factorized_tensor/parafac2_tensor.py index c2a211ee5924f..78d07a91ff6ce 100644 --- a/ivy/data_classes/factorized_tensor/parafac2_tensor.py +++ b/ivy/data_classes/factorized_tensor/parafac2_tensor.py @@ -90,8 +90,7 @@ def n_param(self): @classmethod def from_CPTensor(cls, cp_tensor, parafac2_tensor_ok=False): - """ - Create a Parafac2Tensor from a CPTensor. + """Create a Parafac2Tensor from a CPTensor. Parameters ---------- @@ -124,9 +123,8 @@ def from_CPTensor(cls, cp_tensor, parafac2_tensor_ok=False): # ---------------# @staticmethod def validate_parafac2_tensor(parafac2_tensor): - """ - Validate a parafac2_tensor in the form (weights, factors) Return the rank and - shape of the validated tensor. + """Validate a parafac2_tensor in the form (weights, factors) Return the + rank and shape of the validated tensor. Parameters ---------- @@ -210,8 +208,7 @@ def validate_parafac2_tensor(parafac2_tensor): @staticmethod def parafac2_normalise(parafac2_tensor): - """ - Return parafac2_tensor with factors normalised to unit length. + """Return parafac2_tensor with factors normalised to unit length. Turns ``factors = [|U_1, ... U_n|]`` into ``[weights; |V_1, ... V_n|]``, where the columns of each `V_k` are normalized to unit Euclidean length @@ -267,8 +264,7 @@ def parafac2_normalise(parafac2_tensor): @staticmethod def apply_parafac2_projections(parafac2_tensor): - """ - Apply the projection matrices to the evolving factor. + """Apply the projection matrices to the evolving factor. Parameters ---------- @@ -297,8 +293,8 @@ def apply_parafac2_projections(parafac2_tensor): @staticmethod def parafac2_to_slice(parafac2_tensor, slice_idx, validate=True): - """ - Generate a single slice along the first mode from the PARAFAC2 tensor. + """Generate a single slice along the first mode from the PARAFAC2 + tensor. The decomposition is on the form :math:`(A [B_i] C)` such that the i-th frontal slice, :math:`X_i`, of :math:`X` is given by @@ -362,8 +358,7 @@ def parafac2_to_slice(parafac2_tensor, slice_idx, validate=True): @staticmethod def parafac2_to_slices(parafac2_tensor, validate=True): - """ - Generate all slices along the first mode from a PARAFAC2 tensor. + """Generate all slices along the first mode from a PARAFAC2 tensor. Generates a list of all slices from a PARAFAC2 tensor. A list is returned since the tensor might have varying size along the second mode. To return @@ -424,15 +419,15 @@ def parafac2_to_slices(parafac2_tensor, validate=True): weights = None decomposition = weights, (A, B, C), projections - I, _ = A.shape + I, _ = A.shape # noqa: E741 return [ ivy.Parafac2Tensor.parafac2_to_slice(decomposition, i, validate=False) for i in range(I) ] + @staticmethod def parafac2_to_tensor(parafac2_tensor): - """ - Construct a full tensor from a PARAFAC2 decomposition. + """Construct a full tensor from a PARAFAC2 decomposition. The decomposition is on the form :math:`(A [B_i] C)` such that the i-th frontal slice, :math:`X_i`, of :math:`X` is given by @@ -491,10 +486,10 @@ def parafac2_to_tensor(parafac2_tensor): tensor[i, :length] = slice_ return tensor + @staticmethod def parafac2_to_unfolded(parafac2_tensor, mode): - """ - Construct an unfolded tensor from a PARAFAC2 decomposition. Uneven slices are - padded by zeros. + """Construct an unfolded tensor from a PARAFAC2 decomposition. Uneven + slices are padded by zeros. The decomposition is on the form :math:`(A [B_i] C)` such that the i-th frontal slice, :math:`X_i`, of :math:`X` is given by @@ -543,10 +538,10 @@ def parafac2_to_unfolded(parafac2_tensor, mode): """ return ivy.unfold(ivy.Parafac2Tensor.parafac2_to_tensor(parafac2_tensor), mode) + @staticmethod def parafac2_to_vec(parafac2_tensor): - """ - Construct a vectorized tensor from a PARAFAC2 decomposition. Uneven slices are - padded by zeros. + """Construct a vectorized tensor from a PARAFAC2 decomposition. Uneven + slices are padded by zeros. The decomposition is on the form :math:`(A [B_i] C)` such that the i-th frontal slice, :math:`X_i`, of :math:`X` is given by diff --git a/ivy/data_classes/factorized_tensor/tt_tensor.py b/ivy/data_classes/factorized_tensor/tt_tensor.py index 176f3b1fb5b23..c226155527441 100644 --- a/ivy/data_classes/factorized_tensor/tt_tensor.py +++ b/ivy/data_classes/factorized_tensor/tt_tensor.py @@ -106,10 +106,9 @@ def validate_tt_tensor(tt_tensor): @staticmethod def tt_to_tensor(factors): - """ - Return the full tensor whose TT decomposition is given by 'factors'. + """Return the full tensor whose TT decomposition is given by 'factors'. - Re-assembles 'factors', which represent a tensor in TT/Matrix-Product-State format # noqa: E501 + Re-assembles 'factors', which represent a tensor in TT/Matrix-Product-State format into the corresponding full tensor Parameters @@ -121,7 +120,7 @@ def tt_to_tensor(factors): ------- output_tensor tensor whose TT/MPS decomposition was given by 'factors' - """ + """ # noqa: E501 if isinstance(factors, (float, int)): return factors @@ -138,8 +137,8 @@ def tt_to_tensor(factors): @staticmethod def tt_to_unfolded(factors, mode): - """ - Return the unfolding matrix of a tensor given in TT (or Tensor- Train) format. + """Return the unfolding matrix of a tensor given in TT (or Tensor- + Train) format. Reassembles a full tensor from 'factors' and returns its unfolding matrix with mode given by 'mode' @@ -160,9 +159,8 @@ def tt_to_unfolded(factors, mode): @staticmethod def tt_to_vec(factors): - """ - Return the tensor defined by its TT format ('factors') into its vectorized - format. + """Return the tensor defined by its TT format ('factors') into its + vectorized format. Parameters ---------- @@ -178,9 +176,8 @@ def tt_to_vec(factors): @staticmethod def _tt_n_param(tensor_shape, rank): - """ - Return the number of parameters of a MPS decomposition for a given `rank` and - full `tensor_shape`. + """Return the number of parameters of a MPS decomposition for a given + `rank` and full `tensor_shape`. Parameters ---------- @@ -208,8 +205,7 @@ def validate_tt_rank( rounding="round", allow_overparametrization=True, ): - """ - Return the rank of a TT Decomposition. + """Return the rank of a TT Decomposition. Parameters ---------- @@ -217,8 +213,8 @@ def validate_tt_rank( shape of the tensor to decompose rank way to determine the rank, by default 'same' - if 'same': rank is computed to keep the number of parameters (at most) the same # noqa: E501 - if float, computes a rank so as to keep rank percent of the original number of parameters # noqa: E501 + if 'same': rank is computed to keep the number of parameters (at most) the same + if float, computes a rank so as to keep rank percent of the original number of parameters if int or tuple, just returns rank constant_rank if True, the *same* rank will be chosen for each modes @@ -237,7 +233,7 @@ def validate_tt_rank( ------- rank rank of the decomposition - """ + """ # noqa: E501 if rounding == "ceil": rounding_fn = ivy.ceil elif rounding == "floor": @@ -333,9 +329,8 @@ def validate_tt_rank( @staticmethod def pad_tt_rank(factor_list, n_padding=1, pad_boundaries=False): - """ - Pad the factors of a Tensor-Train so as to increase its rank without changing - its reconstruction. + """Pad the factors of a Tensor-Train so as to increase its rank without + changing its reconstruction. The tensor-train (ring) will be padded with 0s to increase its rank only but not the underlying tensor it represents. diff --git a/ivy/data_classes/nested_array/base.py b/ivy/data_classes/nested_array/base.py index 188f1c731cfa2..21accbd881094 100644 --- a/ivy/data_classes/nested_array/base.py +++ b/ivy/data_classes/nested_array/base.py @@ -128,7 +128,9 @@ def map_fn(vals): return inspect_fn(*a, **kw) if num_nest == 0: - raise Exception(f"No RaggedArrays found in args or kwargs of function {fn}") + raise ValueError( + f"No RaggedArrays found in args or kwargs of function {fn}" + ) ret = ivy.NestedArray.ragged_multi_map(map_fn, nests) return ret diff --git a/ivy/engines/XLA/__init__.py b/ivy/engines/XLA/__init__.py index 45a9584091f50..f5b736bcb5bec 100644 --- a/ivy/engines/XLA/__init__.py +++ b/ivy/engines/XLA/__init__.py @@ -7,7 +7,6 @@ # from .rust_api.python_frontend.sequential_handler import * from .rust_api.python_frontend.general import * -from .rust_api.python_frontend.manipulation import * from .rust_api.python_frontend.creation import * from .rust_api.python_frontend.linear_algebra import * from .rust_api.python_frontend.elementwise import * diff --git a/ivy/engines/XLA/rust_api/xla_rs/xla_rs.cc b/ivy/engines/XLA/rust_api/xla_rs/xla_rs.cc index 6fa315da050fe..e4f19d746b0e6 100644 --- a/ivy/engines/XLA/rust_api/xla_rs/xla_rs.cc +++ b/ivy/engines/XLA/rust_api/xla_rs/xla_rs.cc @@ -1188,7 +1188,7 @@ status execute(const pjrt_loaded_executable exe, const literal *inputs, ASSIGN_OR_RETURN_STATUS(buffer, client->BufferFromHostLiteral(*inputs[i], device)); // Wait for the transfer to have completed to avoid the literal potentially - // getting out of scope before it has been transfered. + // getting out of scope before it has been transferred. MAYBE_RETURN_STATUS(buffer->GetReadyFuture().Await()); input_buffer_ptrs.push_back(buffer.release()); } diff --git a/ivy/func_wrapper.py b/ivy/func_wrapper.py index d13bdf675606e..5e02cb26cde62 100644 --- a/ivy/func_wrapper.py +++ b/ivy/func_wrapper.py @@ -46,7 +46,7 @@ casting_modes_dict = { "uint": lambda: ivy.valid_uint_dtypes, "int": lambda: sorted( - tuple(set(ivy.valid_int_dtypes).difference(set(ivy.valid_uint_dtypes))) + set(ivy.valid_int_dtypes).difference(set(ivy.valid_uint_dtypes)) ), "float": lambda: ivy.valid_float_dtypes, "complex": lambda: ivy.valid_complex_dtypes, @@ -91,91 +91,41 @@ def caster(dtype, intersect): return ret_dtype +def cast_helper(arg, dtype, intersect, is_upcast=True): + step = 1 if is_upcast else -1 + index = casting_modes_dict[arg]().index(dtype) + step + result = "" + while 0 <= index < len(casting_modes_dict[arg]()): + if casting_modes_dict[arg]()[index] not in intersect: + result = casting_modes_dict[arg]()[index] + break + index += step + + return result + + def upcaster(dtype, intersect): # upcasting is enabled, we upcast to the highest if "uint" in str(dtype): - index = casting_modes_dict["uint"]().index(dtype) + 1 - result = "" - while index < len(casting_modes_dict["uint"]()): - if casting_modes_dict["uint"]()[index] not in intersect: - result = casting_modes_dict["uint"]()[index] - break - index += 1 - return result - + return cast_helper("uint", dtype, intersect, is_upcast=True) if "int" in dtype: - index = casting_modes_dict["int"]().index(dtype) + 1 - result = "" - while index < len(casting_modes_dict["int"]()): - if casting_modes_dict["int"]()[index] not in intersect: - result = casting_modes_dict["int"]()[index] - break - index += 1 - return result - + return cast_helper("int", dtype, intersect, is_upcast=True) if "float" in dtype: - index = casting_modes_dict["float"]().index(dtype) + 1 - result = "" - while index < len(casting_modes_dict["float"]()): - if casting_modes_dict["float"]()[index] not in intersect: - result = casting_modes_dict["float"]()[index] - break - index += 1 - return result - + return cast_helper("float", dtype, intersect, is_upcast=True) if "complex" in dtype: - index = casting_modes_dict["complex"]().index(dtype) + 1 - result = "" - while index < len(casting_modes_dict["complex"]()): - if casting_modes_dict["complex"]()[index] not in intersect: - result = casting_modes_dict["complex"]()[index] - break - index += 1 - return result + return cast_helper("complex", dtype, intersect, is_upcast=True) def downcaster(dtype, intersect): # downcasting is enabled, we upcast to the highest if "uint" in str(dtype): - index = casting_modes_dict["uint"]().index(dtype) - 1 - result = "" - while index >= 0: - if casting_modes_dict["int"]()[index] not in intersect: - result = casting_modes_dict["uint"]()[index] - break - index -= 1 - return result - + return cast_helper("uint", dtype, intersect, is_upcast=False) if "int" in dtype: - index = casting_modes_dict["int"]().index(dtype) - 1 - result = "" - while index >= 0: - if casting_modes_dict["int"]()[index] not in intersect: - result = casting_modes_dict["int"]()[index] - break - index -= 1 - return result - + return cast_helper("int", dtype, intersect, is_upcast=False) if "float" in dtype: - index = casting_modes_dict["float"]().index(dtype) - 1 - - result = "" - while index >= 0: - if casting_modes_dict["float"]()[index] not in intersect: - result = casting_modes_dict["float"]()[index] - break - index -= 1 - return result - + return cast_helper("float", dtype, intersect, is_upcast=False) if "complex" in dtype: - index = casting_modes_dict["complex"]().index(dtype) - 1 - result = "" - while index >= 0: - if casting_modes_dict["complex"]()[index] not in intersect: - result = casting_modes_dict["complex"]()[index] - break - index -= 1 - return result + return cast_helper("complex", dtype, intersect, is_upcast=False) def cross_caster(intersect): @@ -224,7 +174,14 @@ def try_array_function_override(func, overloaded_args, types, args, kwargs): def _get_first_array(*args, **kwargs): # ToDo: make this more efficient, with function ivy.nested_nth_index_where - array_fn = ivy.is_array if "array_fn" not in kwargs else kwargs["array_fn"] + def array_fn(x): + return ( + ivy.is_array(x) + if not hasattr(x, "_ivy_array") + else ivy.is_array(x.ivy_array) + ) + + array_fn = array_fn if "array_fn" not in kwargs else kwargs["array_fn"] arr = None if args: arr_idxs = ivy.nested_argwhere(args, array_fn, stop_after_n_found=1) @@ -270,8 +227,7 @@ def _build_view(original, view, fn, args, kwargs, index=None): def _check_in_nested_sequence(sequence, value=None, _type=None): - """ - Check `sequence` for either a `value` or a value of type `_type`. + """Check `sequence` for either a `value` or a value of type `_type`. Helper to recursively check if a N-level nested `sequence` contains either a `value` or contains a value of type `_type` and return a @@ -311,8 +267,7 @@ def _get_preferred_device(args, kwargs): def handle_array_function(fn): - """ - Wrap a function `fn` to be passed to array_function method. + """Wrap a function `fn` to be passed to array_function method. Wrap a function to extract the relevant argument types to be passed to array_function method. @@ -423,10 +378,9 @@ def _handle_array_like_without_promotion(*args, **kwargs): def inputs_to_native_arrays(fn: Callable) -> Callable: @functools.wraps(fn) def _inputs_to_native_arrays(*args, **kwargs): - """ - Convert all `ivy.Array` instances in both the positional and keyword arguments - into `ivy.NativeArray` instances, and then calls the function with the updated - arguments. + """Convert all `ivy.Array` instances in both the positional and keyword + arguments into `ivy.NativeArray` instances, and then calls the function + with the updated arguments. Parameters ---------- @@ -463,10 +417,9 @@ def _inputs_to_native_arrays(*args, **kwargs): def inputs_to_ivy_arrays(fn: Callable) -> Callable: @functools.wraps(fn) def _inputs_to_ivy_arrays(*args, **kwargs): - """ - Convert all `ivy.NativeArray` instances in both the positional and keyword - arguments into `ivy.Array` instances, and then calls the function with the - updated arguments. + """Convert all `ivy.NativeArray` instances in both the positional and + keyword arguments into `ivy.Array` instances, and then calls the + function with the updated arguments. Parameters ---------- @@ -530,8 +483,7 @@ def _outputs_to_ivy_shapes(*args, **kwargs): def to_native_shapes_and_back(fn: Callable) -> Callable: - """ - Make `fn` receive `ivy.NativeShape` and return `ivy.Shape`. + """Make `fn` receive `ivy.NativeShape` and return `ivy.Shape`. Wrap `fn` so that input shapes are all converted to `ivy.NativeShape` instances and return shapes are all converted to @@ -543,9 +495,8 @@ def to_native_shapes_and_back(fn: Callable) -> Callable: def outputs_to_ivy_arrays(fn: Callable) -> Callable: @functools.wraps(fn) def _outputs_to_ivy_arrays(*args, **kwargs): - """ - Call the function, and then converts all `ivy.NativeArray` instances in the - function return into `ivy.Array` instances. + """Call the function, and then converts all `ivy.NativeArray` instances + in the function return into `ivy.Array` instances. Parameters ---------- @@ -573,9 +524,8 @@ def _outputs_to_ivy_arrays(*args, **kwargs): def output_to_native_arrays(fn: Callable) -> Callable: - """ - Call the function, and then converts all `ivy.Array` instances in the function - return into `ivy.NativeArray` instances. + """Call the function, and then converts all `ivy.Array` instances in the + function return into `ivy.NativeArray` instances. Parameters ---------- @@ -600,8 +550,7 @@ def _output_to_native_arrays(*args, **kwargs): def to_ivy_arrays_and_back(fn: Callable) -> Callable: - """ - Make `fn` receive `ivy.Array` and return `ivy.NativeArray`. + """Make `fn` receive `ivy.Array` and return `ivy.NativeArray`. Wrap `fn` so that input arrays are all converted to `ivy.Array` instances and return arrays are all converted to `ivy.NativeArray` @@ -611,8 +560,7 @@ def to_ivy_arrays_and_back(fn: Callable) -> Callable: def to_native_arrays_and_back(fn: Callable) -> Callable: - """ - Make `fn` receive `ivy.NativeArray` and return `ivy.Array`. + """Make `fn` receive `ivy.NativeArray` and return `ivy.Array`. Wrap `fn` so that input arrays are all converted to `ivy.NativeArray` instances and return arrays are all converted to @@ -622,8 +570,7 @@ def to_native_arrays_and_back(fn: Callable) -> Callable: def frontend_outputs_to_ivy_arrays(fn: Callable) -> Callable: - """ - Wrap `fn` and convert all frontend arrays in its return to ivy arrays. + """Wrap `fn` and convert all frontend arrays in its return to ivy arrays. Used in cases when a frontend function receives a callable (frontend function) argument. To be able to use that callable in a composition @@ -643,8 +590,7 @@ def _outputs_to_ivy_arrays(*args, **kwargs): def handle_view(fn: Callable) -> Callable: - """ - Wrap `fn` and performs view handling if copy is False. + """Wrap `fn` and performs view handling if copy is False. Used for functional backends (Jax and TensorFlow). Checks if the first arg is a view or original array by checking if the ._base @@ -675,8 +621,7 @@ def _handle_view(*args, **kwargs): def handle_view_indexing(fn: Callable) -> Callable: - """ - Wrap `fn` and performs view handling specifically for indexing. + """Wrap `fn` and performs view handling specifically for indexing. As with NumPy it returns a copy if advanced indexing is performed. Used for functional backends (Jax and TensorFlow). Checks if the @@ -719,8 +664,8 @@ def _convert_numpy_arrays_to_backend_specific(*args): def handle_numpy_arrays_in_specific_backend(fn: Callable) -> Callable: - """ - Wrap `fn` and converts all `numpy.ndarray` inputs to `torch.Tensor` instances. + """Wrap `fn` and converts all `numpy.ndarray` inputs to `torch.Tensor` + instances. Used for functional backends (PyTorch). Converts all `numpy.ndarray` inputs to `torch.Tensor` instances. @@ -743,9 +688,8 @@ def _handle_numpy_array_in_torch(*args, **kwargs): def infer_dtype(fn: Callable) -> Callable: @functools.wraps(fn) def _infer_dtype(*args, dtype=None, **kwargs): - """ - Determine the correct `dtype`, and then calls the function with the `dtype` - passed explicitly. + """Determine the correct `dtype`, and then calls the function with the + `dtype` passed explicitly. Parameters ---------- @@ -781,8 +725,7 @@ def _infer_dtype(*args, dtype=None, **kwargs): def handle_device(fn: Callable) -> Callable: @functools.wraps(fn) def _handle_device(*args, **kwargs): - """ - Move all array inputs of the function to `ivy.default_device()`. + """Move all array inputs of the function to `ivy.default_device()`. Parameters ---------- @@ -802,7 +745,7 @@ def _handle_device(*args, **kwargs): with ivy.DefaultDevice(ivy.default_device(dev)): return ivy.handle_soft_device_variable(*args, fn=fn, **kwargs) inputs = args + tuple(kwargs.values()) - devices = tuple(ivy.dev(x) for x in inputs if ivy.is_native_array(x)) + devices = tuple(ivy.dev(x) for x in inputs if ivy.is_array(x)) unique_devices = set(devices) # check if arrays are on the same device if len(unique_devices) <= 1: @@ -836,9 +779,8 @@ def handle_out_argument(fn: Callable) -> Callable: @functools.wraps(fn) def _handle_out_argument(*args, out=None, **kwargs): - """ - Call `fn` with the `out` argument handled correctly for performing an inplace - update. + """Call `fn` with the `out` argument handled correctly for performing + an inplace update. Parameters ---------- @@ -930,10 +872,9 @@ def handle_nestable(fn: Callable) -> Callable: @functools.wraps(fn) def _handle_nestable(*args, **kwargs): - """ - Call `fn` with the *nestable* property of the function correctly handled. This - means mapping the function to the container leaves if any containers are passed - in the input. + """Call `fn` with the *nestable* property of the function correctly + handled. This means mapping the function to the container leaves if any + containers are passed in the input. Parameters ---------- @@ -974,10 +915,9 @@ def cont_fn(*args, **kwargs): def handle_ragged(fn: Callable) -> Callable: @functools.wraps(fn) def _handle_ragged(*args, **kwargs): - """ - Call `fn` with the *ragged* property of the function correctly handled. This - means mapping the function to the RaggedArray arrays if any RaggedArrays are - passed in the input. + """Call `fn` with the *ragged* property of the function correctly + handled. This means mapping the function to the RaggedArray arrays if + any RaggedArrays are passed in the input. Parameters ---------- @@ -1035,8 +975,7 @@ def _handle_partial_mixed_function(*args, **kwargs): def temp_asarray_wrapper(fn: Callable) -> Callable: @functools.wraps(fn) def _temp_asarray_wrapper(*args, **kwargs): - """ - Convert `Tensor` into `ivy.Array` instances. + """Convert `Tensor` into `ivy.Array` instances. Convert all `Tensor` instances in both the positional and keyword arguments into `ivy.Array` instances, and then call the function with the updated @@ -1063,18 +1002,40 @@ def _to_ivy_array(x): return _temp_asarray_wrapper +# Download compiled cython wrapper wrapper + + +def download_cython_wrapper_wrapper(fn: Callable) -> Callable: + @functools.wraps(fn) + def _download_cython_wrapper_wrapper(*args, **kwargs): + """Wrap the function to download compiled cython wrapper for the + function and re- wraps it with the downloaded wrapper. + + Download the compiled cython wrapper by calling + ivy.wrappers.get_wrapper(func_name: str) and then wrap the + function with the downloaded wrapper. + """ + ivy.wrappers.download_cython_wrapper(fn.__name__) + ivy.wrappers.load_one_wrapper(fn.__name__) + ivy.functional.__dict__[fn.__name__] = getattr( + ivy.wrappers, fn.__name__ + "_wrapper" + )(fn) + return ivy.functional.__dict__[fn.__name__](*args, **kwargs) + + return _download_cython_wrapper_wrapper + + # Functions # def _wrap_function( key: str, to_wrap: Callable, original: Callable, compositional: bool = False ) -> Callable: - """ - Apply wrapping to backend implementation `to_wrap` if the original implementation - `original` is also wrapped, and if `to_wrap` is not already wrapped. Attributes - `handle_nestable` etc are set during wrapping, hence indicate to us whether a - certain function has been wrapped or not. Also handles wrapping of the `linalg` - namespace. + """Apply wrapping to backend implementation `to_wrap` if the original + implementation `original` is also wrapped, and if `to_wrap` is not already + wrapped. Attributes `handle_nestable` etc are set during wrapping, hence + indicate to us whether a certain function has been wrapped or not. Also + handles wrapping of the `linalg` namespace. Parameters ---------- @@ -1108,6 +1069,12 @@ def _wrap_function( ) return to_wrap if isinstance(to_wrap, FunctionType): + if ivy.cython_wrappers_mode and ivy.wrappers.wrapper_exists(to_wrap.__name__): + if to_wrap.__name__ + "_wrapper" in ivy.wrappers.__all__: + to_wrap = getattr(ivy.wrappers, to_wrap.__name__ + "_wrapper")(to_wrap) + return to_wrap + else: + return download_cython_wrapper_wrapper(to_wrap) # set attributes for attr in original.__dict__.keys(): # private attribute or decorator @@ -1246,7 +1213,7 @@ def _dtype_from_version(dic, version): # If version dict is empty, then there is an error if not dic: - raise Exception("No version found in the dictionary") + raise ValueError("No version found in the dictionary") # If key is already in the dictionary, return the value if version in dic: @@ -1269,14 +1236,14 @@ def _dtype_from_version(dic, version): if "to" in key and k1 <= version_tuple <= tuple(map(int, kl[2].split("."))): return dic[key] - # if no version is found, we return empty tuple - return () + # if no version is found, return the last version + return dic[list(dic.keys())[-1]] def _versioned_attribute_factory(attribute_function, base): class VersionedAttributes(base): - """ - Class which add versioned attributes to a class, inheriting from `base`. + """Class which add versioned attributes to a class, inheriting from + `base`. Create a class which inherits `base` this way if isinstance is called on an instance of the class, it will return True if @@ -1305,8 +1272,7 @@ def __bool__(self): def _dtype_device_wrapper_creator(attrib, t): - """ - Create a wrapper for a dtype or device attribute. + """Create a wrapper for a dtype or device attribute. The wrapper returns the correct dtype or device for the current version of the backend. @@ -1406,8 +1372,8 @@ def _nest_has_nans(x): def handle_nans(fn: Callable) -> Callable: @functools.wraps(fn) def _handle_nans(*args, **kwargs): - """ - Check for the existence of nans in all arrays in the `args` and `kwargs`. + """Check for the existence of nans in all arrays in the `args` and + `kwargs`. The presence of nans is then handled depending on the enabled `nan_policy`. @@ -1461,9 +1427,8 @@ def _handle_complex_input( complex_mode: Literal["split", "magnitude", "jax"] = "jax", **kwargs, ): - """ - Check whether the first positional argument is an array of complex type, and if - so handle it according to the provided `complex_mode`. + """Check whether the first positional argument is an array of complex + type, and if so handle it according to the provided `complex_mode`. The options are: `"jax"` (default): emulate the behaviour of the JAX framework. If the function @@ -1590,10 +1555,9 @@ def _handle_complex_input( def handle_backend_invalid(fn: Callable) -> Callable: @functools.wraps(fn) def _handle_backend_invalid(*args, **kwargs): - """ - Check if any of the arguments (or nested arguments) passed to the function are - instances of ivy.Array or ivy.NativeArray. If so, it returns the function. If - not, it raises an InvalidBackendException. + """Check if any of the arguments (or nested arguments) passed to the + function are instances of ivy.Array or ivy.NativeArray. If so, it + returns the function. If not, it raises an InvalidBackendException. Parameters ---------- diff --git a/ivy/functional/backends/jax/__init__.py b/ivy/functional/backends/jax/__init__.py index 74d697ec9be9c..6168ec1b4ac84 100644 --- a/ivy/functional/backends/jax/__init__.py +++ b/ivy/functional/backends/jax/__init__.py @@ -4,6 +4,7 @@ import jaxlib import jax import jax.numpy as jnp +import importlib from typing import Union # make ivy.Container compatible with jax pytree traversal @@ -101,7 +102,7 @@ def _array_unflatten(aux_data, children): # update these to add new dtypes valid_dtypes = { - "0.4.19 and below": ( + "0.4.24 and below": ( ivy.int8, ivy.int16, ivy.int32, @@ -120,7 +121,7 @@ def _array_unflatten(aux_data, children): ) } valid_numeric_dtypes = { - "0.4.19 and below": ( + "0.4.24 and below": ( ivy.int8, ivy.int16, ivy.int32, @@ -139,7 +140,7 @@ def _array_unflatten(aux_data, children): } valid_int_dtypes = { - "0.4.19 and below": ( + "0.4.24 and below": ( ivy.int8, ivy.int16, ivy.int32, @@ -152,12 +153,12 @@ def _array_unflatten(aux_data, children): } valid_uint_dtypes = { - "0.4.19 and below": (ivy.uint8, ivy.uint16, ivy.uint32, ivy.uint64) + "0.4.24 and below": (ivy.uint8, ivy.uint16, ivy.uint32, ivy.uint64) } valid_float_dtypes = { - "0.4.19 and below": (ivy.bfloat16, ivy.float16, ivy.float32, ivy.float64) + "0.4.24 and below": (ivy.bfloat16, ivy.float16, ivy.float32, ivy.float64) } -valid_complex_dtypes = {"0.4.19 and below": (ivy.complex64, ivy.complex128)} +valid_complex_dtypes = {"0.4.24 and below": (ivy.complex64, ivy.complex128)} # leave these untouched @@ -172,12 +173,12 @@ def _array_unflatten(aux_data, children): # invalid data types # update these to add new dtypes -invalid_dtypes = {"0.4.19 and below": ()} -invalid_numeric_dtypes = {"0.4.19 and below": ()} -invalid_int_dtypes = {"0.4.19 and below": ()} -invalid_float_dtypes = {"0.4.19 and below": ()} -invalid_uint_dtypes = {"0.4.19 and below": ()} -invalid_complex_dtypes = {"0.4.19 and below": ()} +invalid_dtypes = {"0.4.24 and below": ()} +invalid_numeric_dtypes = {"0.4.24 and below": ()} +invalid_int_dtypes = {"0.4.24 and below": ()} +invalid_float_dtypes = {"0.4.24 and below": ()} +invalid_uint_dtypes = {"0.4.24 and below": ()} +invalid_complex_dtypes = {"0.4.24 and below": ()} # leave these untouched invalid_dtypes = _dtype_from_version(invalid_dtypes, backend_version) @@ -240,8 +241,22 @@ def closest_valid_dtype(type=None, /, as_native=False): from .experimental import * from . import control_flow_ops from .control_flow_ops import * +from . import module +from .module import * # sub-backends from . import sub_backends from .sub_backends import * + + +if importlib.util.find_spec("flax"): + import flax + + NativeModule = flax.linen.Module +elif importlib.util.find_spec("haiku"): + import haiku as hk + + NativeModule = hk.Module +else: + NativeModule = None diff --git a/ivy/functional/backends/jax/activations.py b/ivy/functional/backends/jax/activations.py index 1120af0466f64..cdb9340436cf6 100644 --- a/ivy/functional/backends/jax/activations.py +++ b/ivy/functional/backends/jax/activations.py @@ -1,4 +1,5 @@ -"""Collection of Jax activation functions, wrapped to fit Ivy syntax and signature.""" +"""Collection of Jax activation functions, wrapped to fit Ivy syntax and +signature.""" # global @@ -36,7 +37,7 @@ def leaky_relu( def relu( x: JaxArray, /, *, complex_mode="jax", out: Optional[JaxArray] = None ) -> JaxArray: - return jnp.maximum(x, 0) + return jax.nn.relu(x) def sigmoid( diff --git a/ivy/functional/backends/jax/control_flow_ops.py b/ivy/functional/backends/jax/control_flow_ops.py index ba981aadf58b4..3331fc7bef0c8 100644 --- a/ivy/functional/backends/jax/control_flow_ops.py +++ b/ivy/functional/backends/jax/control_flow_ops.py @@ -16,7 +16,8 @@ def body_fn_wrapper(loop_vars): def test_fn_wrapper(loop_vars): return test_fn(*loop_vars) - vars = list(vars.values()) + if isinstance(vars, dict): + vars = list(vars.values()) with jax.disable_jit(): final_loop_vars = jax.lax.while_loop(test_fn_wrapper, body_fn_wrapper, vars) return final_loop_vars diff --git a/ivy/functional/backends/jax/creation.py b/ivy/functional/backends/jax/creation.py index ee3804bab9759..17ade3b74b32e 100644 --- a/ivy/functional/backends/jax/creation.py +++ b/ivy/functional/backends/jax/creation.py @@ -12,6 +12,7 @@ import ivy from ivy import as_native_dtype from ivy.functional.backends.jax import JaxArray +from ivy.functional.backends.jax.device import dev from ivy.functional.ivy.creation import ( _asarray_to_native_arrays_and_back, _asarray_infer_device, @@ -73,10 +74,13 @@ def asarray( out: Optional[JaxArray] = None, ) -> JaxArray: ivy.utils.assertions._check_jax_x64_flag(dtype) - if copy is True: - return jnp.array(obj, dtype=dtype, copy=True) - else: - return jnp.asarray(obj, dtype=dtype) + ret = jnp.asarray(obj, dtype=dtype) + # jnp.copy is used to ensure correct device placement + # it's slower than jax.device_put before JIT, but it's necessary to use since + # jax device objects aren't serializable and prevent saving transpiled graphs + # this workaround only works because we are inside jax.default_device context + # invoked in @handle_device decorator + return jnp.copy(ret) if (dev(ret, as_native=True) != device or copy) else ret def empty( diff --git a/ivy/functional/backends/jax/data_type.py b/ivy/functional/backends/jax/data_type.py index e25e54e745bbe..1a84e9ad456e3 100644 --- a/ivy/functional/backends/jax/data_type.py +++ b/ivy/functional/backends/jax/data_type.py @@ -133,7 +133,7 @@ def broadcast_arrays(*arrays: JaxArray) -> List[JaxArray]: try: return jnp.broadcast_arrays(*arrays) except ValueError as e: - raise ivy.utils.exceptions.IvyBroadcastShapeError(e) + raise ivy.utils.exceptions.IvyBroadcastShapeError(e) from e def broadcast_to( @@ -267,7 +267,4 @@ def dtype_bits(dtype_in: Union[jnp.dtype, str, np.dtype], /) -> int: def is_native_dtype(dtype_in: Union[jnp.dtype, str], /) -> bool: if not ivy.is_hashable_dtype(dtype_in): return False - if dtype_in in ivy_dtype_dict: - return True - else: - return False + return dtype_in in ivy_dtype_dict diff --git a/ivy/functional/backends/jax/device.py b/ivy/functional/backends/jax/device.py index 7cd30e045142e..f21d9aa0cb66a 100644 --- a/ivy/functional/backends/jax/device.py +++ b/ivy/functional/backends/jax/device.py @@ -1,4 +1,5 @@ -"""Collection of Jax device functions, wrapped to fit Ivy syntax and signature.""" +"""Collection of Jax device functions, wrapped to fit Ivy syntax and +signature.""" # global import os @@ -41,14 +42,11 @@ def dev( ) -> Union[ivy.Device, jaxlib.xla_extension.Device]: if isinstance(x, jax.interpreters.partial_eval.DynamicJaxprTracer): return "" - try: - dv = _to_array(x).device_buffer.device - dv = dv() - except Exception: + if hasattr(x, "device_buffer"): + dv = _to_array(x).device_buffer.device() + else: dv = jax.devices()[0] - if as_native: - return dv - return as_ivy_dev(dv) + return dv if as_native else as_ivy_dev(dv) def to_device( diff --git a/ivy/functional/backends/jax/elementwise.py b/ivy/functional/backends/jax/elementwise.py index f00c00b4443bf..dc2089baf89ec 100644 --- a/ivy/functional/backends/jax/elementwise.py +++ b/ivy/functional/backends/jax/elementwise.py @@ -28,6 +28,7 @@ def abs( return jnp.where(x != 0, jnp.absolute(x), 0) +@with_unsupported_dtypes({"0.4.24 and below": ("complex",)}, backend_version) def acos(x: JaxArray, /, *, out: Optional[JaxArray] = None) -> JaxArray: return jnp.arccos(x) @@ -51,10 +52,12 @@ def add( return jnp.add(x1, x2) +@with_unsupported_dtypes({"0.4.24 and below": ("complex",)}, backend_version) def asin(x: JaxArray, /, *, out: Optional[JaxArray] = None) -> JaxArray: return jnp.arcsin(x) +@with_unsupported_dtypes({"0.4.24 and below": ("complex",)}, backend_version) def asinh(x: JaxArray, /, *, out: Optional[JaxArray] = None) -> JaxArray: return jnp.arcsinh(x) @@ -68,11 +71,12 @@ def atan2(x1: JaxArray, x2: JaxArray, /, *, out: Optional[JaxArray] = None) -> J return jnp.arctan2(x1, x2) +@with_unsupported_dtypes({"0.4.24 and below": ("complex",)}, backend_version) def atanh(x: JaxArray, /, *, out: Optional[JaxArray] = None) -> JaxArray: return jnp.arctanh(x) -@with_unsupported_dtypes({"0.4.19 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"0.4.24 and below": ("complex",)}, backend_version) def bitwise_and( x1: Union[int, JaxArray], x2: Union[int, JaxArray], @@ -84,14 +88,14 @@ def bitwise_and( return jnp.bitwise_and(x1, x2) -@with_unsupported_dtypes({"0.4.19 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"0.4.24 and below": ("complex",)}, backend_version) def bitwise_invert( x: Union[int, JaxArray], /, *, out: Optional[JaxArray] = None ) -> JaxArray: return jnp.bitwise_not(x) -@with_unsupported_dtypes({"0.4.19 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"0.4.24 and below": ("complex",)}, backend_version) def bitwise_left_shift( x1: Union[int, JaxArray], x2: Union[int, JaxArray], @@ -103,7 +107,7 @@ def bitwise_left_shift( return jnp.left_shift(x1, x2) -@with_unsupported_dtypes({"0.4.19 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"0.4.24 and below": ("complex",)}, backend_version) def bitwise_or( x1: Union[int, JaxArray], x2: Union[int, JaxArray], @@ -115,7 +119,7 @@ def bitwise_or( return jnp.bitwise_or(x1, x2) -@with_unsupported_dtypes({"0.4.19 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"0.4.24 and below": ("complex",)}, backend_version) def bitwise_right_shift( x1: Union[int, JaxArray], x2: Union[int, JaxArray], @@ -127,7 +131,7 @@ def bitwise_right_shift( return jnp.right_shift(x1, x2) -@with_unsupported_dtypes({"0.4.19 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"0.4.24 and below": ("complex",)}, backend_version) def bitwise_xor( x1: Union[int, JaxArray], x2: Union[int, JaxArray], @@ -139,7 +143,7 @@ def bitwise_xor( return jnp.bitwise_xor(x1, x2) -@with_unsupported_dtypes({"0.4.19 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"0.4.24 and below": ("complex",)}, backend_version) def ceil(x: JaxArray, /, *, out: Optional[JaxArray] = None) -> JaxArray: if "int" in str(x.dtype): return x @@ -151,7 +155,7 @@ def cos(x: JaxArray, /, *, out: Optional[JaxArray] = None) -> JaxArray: return jnp.cos(x) -@with_unsupported_dtypes({"0.4.19 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"0.4.24 and below": ("float16",)}, backend_version) def cosh(x: JaxArray, /, *, out: Optional[JaxArray] = None) -> JaxArray: return jnp.cosh(x) @@ -191,7 +195,7 @@ def expm1(x: JaxArray, /, *, out: Optional[JaxArray] = None) -> JaxArray: return jnp.expm1(x) -@with_unsupported_dtypes({"0.4.19 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"0.4.24 and below": ("complex",)}, backend_version) def floor(x: JaxArray, /, *, out: Optional[JaxArray] = None) -> JaxArray: if "int" in str(x.dtype): return x @@ -199,7 +203,7 @@ def floor(x: JaxArray, /, *, out: Optional[JaxArray] = None) -> JaxArray: return jnp.floor(x) -@with_unsupported_dtypes({"0.4.19 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"0.4.24 and below": ("complex",)}, backend_version) def floor_divide( x1: Union[float, JaxArray], x2: Union[float, JaxArray], @@ -247,6 +251,7 @@ def isfinite(x: JaxArray, /, *, out: Optional[JaxArray] = None) -> JaxArray: return jnp.isfinite(x) +@with_unsupported_dtypes({"0.4.24 and below": ("complex",)}, backend_version) def isinf( x: JaxArray, /, @@ -427,7 +432,7 @@ def pow( return jnp.power(x1, x2) -@with_unsupported_dtypes({"0.4.19 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"0.4.24 and below": ("complex",)}, backend_version) def remainder( x1: Union[float, JaxArray], x2: Union[float, JaxArray], @@ -514,6 +519,9 @@ def trapz( return jnp.trapz(y, x=x, dx=dx, axis=axis) +@with_unsupported_dtypes( + {"0.4.24 and below": ("complex", "float16", "bfloat16")}, backend_version +) def tan(x: JaxArray, /, *, out: Optional[JaxArray] = None) -> JaxArray: return jnp.tan(x) @@ -524,7 +532,7 @@ def tanh( return jnp.tanh(x) -@with_unsupported_dtypes({"0.4.19 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"0.4.24 and below": ("complex",)}, backend_version) def trunc(x: JaxArray, /, *, out: Optional[JaxArray] = None) -> JaxArray: if "int" in str(x.dtype): return x @@ -564,7 +572,7 @@ def angle( # ------# -@with_unsupported_dtypes({"0.4.19 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"0.4.24 and below": ("complex",)}, backend_version) def erf(x: JaxArray, /, *, out: Optional[JaxArray] = None) -> JaxArray: return jax.scipy.special.erf(x) @@ -615,7 +623,7 @@ def isreal(x: JaxArray, /, *, out: Optional[JaxArray] = None) -> JaxArray: return jnp.isreal(x) -@with_unsupported_dtypes({"0.4.19 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"0.4.24 and below": ("complex",)}, backend_version) def fmod( x1: JaxArray, x2: JaxArray, diff --git a/ivy/functional/backends/jax/experimental/activations.py b/ivy/functional/backends/jax/experimental/activations.py index c21f9c034e369..f8a87fc7607f1 100644 --- a/ivy/functional/backends/jax/experimental/activations.py +++ b/ivy/functional/backends/jax/experimental/activations.py @@ -35,7 +35,7 @@ def relu6( # https://github.com/google/jax/pull/14682 def custom_grad_func(x_and_grad, one): return lax.select( - (6 > x_and_grad[0]) & (x_and_grad[0] > 0), one, lax.full_like(one, 0) + (x_and_grad[0] < 6) & (x_and_grad[0] > 0), one, lax.full_like(one, 0) ) new_func = ivy.bind_custom_gradient_function(relu6_func, custom_grad_func) @@ -73,6 +73,7 @@ def silu(x: JaxArray, /, *, out: Optional[JaxArray] = None) -> JaxArray: return ret +@with_unsupported_dtypes({"0.4.14 and below": ("float16", "bfloat16")}, backend_version) def elu( x: JaxArray, /, *, alpha: float = 1.0, out: Optional[JaxArray] = None ) -> JaxArray: @@ -115,6 +116,20 @@ def tanhshrink(x: JaxArray, /, *, out: Optional[JaxArray] = None) -> JaxArray: return ret +def threshold( + x: JaxArray, + /, + *, + threshold: Union[int, float], + value: Union[int, float], + out: Optional[JaxArray] = None, +) -> JaxArray: + ret = jnp.where(x > threshold, x, value).astype(x.dtype) + if ivy.exists(out): + return ivy.inplace_update(out, ret).astype(x.dtype) # type: ignore + return ret + + @with_unsupported_dtypes({"0.4.16 and below": ("float16", "bfloat16")}, backend_version) def softshrink( x: JaxArray, /, *, lambd: float = 0.5, out: Optional[JaxArray] = None @@ -145,3 +160,11 @@ def hardshrink( if ivy.exists(out): return ivy.inplace_update(out, ret).astype(x.dtype) return ret + + +@with_unsupported_dtypes({"0.4.16 and below": ("float16", "bfloat16")}, backend_version) +def hardsilu(x: JaxArray, /, *, out: Optional[JaxArray] = None) -> JaxArray: + ret = jax.nn.hard_silu(x) + if ivy.exists(out): + return ivy.inplace_update(out, ret).astype(x.dtype) + return ret diff --git a/ivy/functional/backends/jax/experimental/creation.py b/ivy/functional/backends/jax/experimental/creation.py index 85c018578c38d..42d285a045f95 100644 --- a/ivy/functional/backends/jax/experimental/creation.py +++ b/ivy/functional/backends/jax/experimental/creation.py @@ -83,7 +83,7 @@ def unsorted_segment_min( num_segments: int, ) -> JaxArray: # added this check to keep the same behaviour as tensorflow - ivy.utils.assertions.check_unsorted_segment_min_valid_params( + ivy.utils.assertions.check_unsorted_segment_valid_params( data, segment_ids, num_segments ) return jax.ops.segment_min(data, segment_ids, num_segments) @@ -98,7 +98,7 @@ def unsorted_segment_sum( # the check should be same # Might require to change the assertion function name to # check_unsorted_segment_valid_params - ivy.utils.assertions.check_unsorted_segment_min_valid_params( + ivy.utils.assertions.check_unsorted_segment_valid_params( data, segment_ids, num_segments ) return jax.ops.segment_sum(data, segment_ids, num_segments) @@ -156,15 +156,32 @@ def hz_to_mel(f): dtype=jnp.float32, ) mel_edges = jnp.stack([mel_edges[i : i + 3] for i in range(num_mel_bins)]) - lower_edge_mel, center_mel, upper_edge_mel = [ + lower_edge_mel, center_mel, upper_edge_mel = ( t.reshape((1, num_mel_bins)) for t in jnp.split(mel_edges, 3, axis=1) - ] + ) lower_slopes = (spec_bin_mels - lower_edge_mel) / (center_mel - lower_edge_mel) upper_slopes = (upper_edge_mel - spec_bin_mels) / (upper_edge_mel - center_mel) mel_weights = jnp.maximum(zero, jnp.minimum(lower_slopes, upper_slopes)) return jnp.pad(mel_weights, [[1, 0], [0, 0]]) +def unsorted_segment_mean( + data: JaxArray, + segment_ids: JaxArray, + num_segments: int, +) -> JaxArray: + ivy.utils.assertions.check_unsorted_segment_valid_params( + data, segment_ids, num_segments + ) + segment_sum = jax.ops.segment_sum(data, segment_ids, num_segments) + + segment_count = jax.ops.segment_sum(jnp.ones_like(data), segment_ids, num_segments) + + segment_mean = segment_sum / segment_count + + return segment_mean + + def polyval( coeffs: JaxArray, x: JaxArray, diff --git a/ivy/functional/backends/jax/experimental/elementwise.py b/ivy/functional/backends/jax/experimental/elementwise.py index c39c5910f34f1..8ea92a5094b85 100644 --- a/ivy/functional/backends/jax/experimental/elementwise.py +++ b/ivy/functional/backends/jax/experimental/elementwise.py @@ -50,7 +50,7 @@ def sinc(x: JaxArray, /, *, out: Optional[JaxArray] = None) -> JaxArray: @with_supported_dtypes( - {"0.4.19 and below": ("float16", "float32", "float64")}, backend_version + {"0.4.24 and below": ("float16", "float32", "float64")}, backend_version ) def lgamma(x: JaxArray, /, *, out: Optional[JaxArray] = None) -> JaxArray: return jlax.lgamma(x) @@ -253,7 +253,7 @@ def _normalize_axis_tuple(axis: Union[int, list, tuple], ndim: int) -> Tuple[int axis = [operator.index(axis)] except TypeError: pass - axis = tuple([_normalize_axis_index(ax, ndim) for ax in axis]) + axis = tuple(_normalize_axis_index(ax, ndim) for ax in axis) if len(set(axis)) != len(axis): raise ValueError("repeated axis") return axis @@ -499,3 +499,12 @@ def erfc( out: Optional[JaxArray] = None, ) -> JaxArray: return js.special.erfc(x) + + +def erfinv( + x: JaxArray, + /, + *, + out: Optional[JaxArray] = None, +) -> JaxArray: + return js.special.erfinv(x) diff --git a/ivy/functional/backends/jax/experimental/layers.py b/ivy/functional/backends/jax/experimental/layers.py index 84224b0e59928..335b0745e2ce2 100644 --- a/ivy/functional/backends/jax/experimental/layers.py +++ b/ivy/functional/backends/jax/experimental/layers.py @@ -83,10 +83,8 @@ def general_pool( # shape of window after dilation new_window_shape = tuple( - [ - window_shape[i - 1] + (dilation[i] - 1) * (window_shape[i - 1] - 1) - for i in range(1, len(dims) - 1) - ] + window_shape[i - 1] + (dilation[i] - 1) * (window_shape[i - 1] - 1) + for i in range(1, len(dims) - 1) ) inputs, window_shape, strides, depth_pooling = _determine_depth_max_pooling( inputs, window_shape, strides, dim, data_format="channel_last" @@ -136,20 +134,20 @@ def general_pool( # because they are counted in average calculation inputs = jnp.pad(inputs, pad_list, mode="constant", constant_values=1.0) pad_list = [(0, 0)] * len(pad_list) + elif isinstance(padding, list) and any( + item != 0 for sublist in padding for item in sublist + ): + raise NotImplementedError( + "Nonzero explicit padding is not supported for depthwise max pooling" + ) else: - if isinstance(padding, list) and any( - [item != 0 for sublist in padding for item in sublist] - ): - raise NotImplementedError( - "Nonzero explicit padding is not supported for depthwise max pooling" - ) pad_list = [(0, 0)] * (dim + 2) if not ivy.is_array(inputs): # if dtype is not set here, jax casts it to float64 inputs = jnp.array(inputs, dtype=jnp.float32) if not ivy.is_array(init): - init = jnp.array(init, dtype=jnp.float32) + init = jnp.array(init, dtype=inputs.dtype) promoted_type = jnp.promote_types(inputs.dtype, init.dtype) inputs = inputs.astype(promoted_type) init = init.astype(promoted_type) @@ -291,12 +289,13 @@ def avg_pool1d( x: JaxArray, kernel: Union[int, Tuple[int]], strides: Union[int, Tuple[int]], - padding: str, + padding: Union[str, int, List[Tuple[int, int]]], /, *, data_format: str = "NWC", count_include_pad: bool = False, ceil_mode: bool = False, + divisor_override: Optional[int] = None, out: Optional[JaxArray] = None, ) -> JaxArray: if data_format in ("NCW", "NCL"): @@ -341,7 +340,7 @@ def avg_pool2d( x: JaxArray, kernel: Union[int, Tuple[int], Tuple[int, int]], strides: Union[int, Tuple[int], Tuple[int, int]], - padding: str, + padding: Union[str, int, List[Tuple[int, int]]], /, *, data_format: str = "NHWC", @@ -393,7 +392,7 @@ def avg_pool3d( x: JaxArray, kernel: Union[int, Tuple[int], Tuple[int, int, int]], strides: Union[int, Tuple[int], Tuple[int, int, int]], - padding: str, + padding: Union[str, int, List[Tuple[int, int]]], /, *, data_format: str = "NDHWC", @@ -441,7 +440,7 @@ def avg_pool3d( return res -@with_supported_dtypes({"0.4.19 and below": ("float32", "float64")}, backend_version) +@with_supported_dtypes({"0.4.24 and below": ("float32", "float64")}, backend_version) def dct( x: JaxArray, /, @@ -455,7 +454,7 @@ def dct( if norm not in (None, "ortho"): raise ValueError("Norm must be either None or 'ortho'") if axis < 0: - axis = axis + len(x.shape) + axis += len(x.shape) if n is not None: signal_len = x.shape[axis] if n <= signal_len: @@ -558,7 +557,7 @@ def fft( raise ivy.utils.exceptions.IvyError( f"Invalid data points {n}, expecting more than 1" ) - if norm != "backward" and norm != "ortho" and norm != "forward": + if norm not in {"backward", "ortho", "forward"}: raise ivy.utils.exceptions.IvyError(f"Unrecognized normalization mode {norm}") return jnp.fft.fft(x, n, dim, norm) @@ -670,7 +669,7 @@ def ifft( raise ivy.utils.exceptions.IvyError( f"Invalid data points {n}, expecting more than 1" ) - if norm != "backward" and norm != "ortho" and norm != "forward": + if norm not in {"backward", "ortho", "forward"}: raise ivy.utils.exceptions.IvyError(f"Unrecognized normalization mode {norm}") return jnp.fft.ifft(x, n, dim, norm) @@ -689,7 +688,8 @@ def interpolate( "area", "nearest_exact", "tf_area", - "bicubic_tensorflow" "bicubic", + "tf_bicubic", + "bicubic", "mitchellcubic", "lanczos3", "lanczos5", @@ -697,29 +697,35 @@ def interpolate( ] = "linear", scale_factor: Optional[Union[Sequence[int], int]] = None, recompute_scale_factor: Optional[bool] = None, - align_corners: Optional[bool] = None, + align_corners: bool = False, antialias: bool = False, out: Optional[JaxArray] = None, ): - dims = len(x.shape) - 2 - size = _get_size(scale_factor, size, dims, x.shape) - mode = ( - "nearest" - if mode == "nearest-exact" - else "bicubic" if mode == "bicubic_tensorflow" else mode - ) + input_size = ivy.shape(x)[2:] + dims = len(input_size) + size, _ = _get_size(scale_factor, size, dims, input_size) + if all(a == b for a, b in zip(size, input_size)): + ret = x + else: + mode = ( + "nearest" + if mode == "nearest-exact" + else "bicubic" if mode == "tf_bicubic" else mode + ) - size = [x.shape[0], *size, x.shape[1]] - x = jnp.transpose(x, (0, *range(2, dims + 2), 1)) - return jnp.transpose( - jax.image.resize(x, shape=size, method=mode, antialias=antialias), - (0, dims + 1, *range(1, dims + 1)), - ) + size = [x.shape[0], *size, x.shape[1]] + x = jnp.transpose(x, (0, *range(2, dims + 2), 1)) + ret = jnp.transpose( + jax.image.resize(x, shape=size, method=mode, antialias=antialias), + (0, dims + 1, *range(1, dims + 1)), + ) + if ivy.exists(out): + return ivy.inplace_update(out, ret) + return ret -interpolate.partial_mixed_handler = lambda *args, mode="linear", scale_factor=None, recompute_scale_factor=None, align_corners=None, **kwargs: ( # noqa: E501 - (align_corners is None or not align_corners) - and mode +interpolate.partial_mixed_handler = ( + lambda *args, mode="linear", recompute_scale_factor=None, align_corners=None, **kwargs: mode # noqa: E501 not in [ "area", "nearest", @@ -729,7 +735,8 @@ def interpolate( "gaussian", "bicubic", ] - and (scale_factor is None or ivy.all(ivy.array(scale_factor) > 1)) + and not align_corners + and recompute_scale_factor ) @@ -771,7 +778,7 @@ def reduce_window( def fft2( x: JaxArray, *, - s: Sequence[int] = None, + s: Optional[Sequence[int]] = None, dim: Sequence[int] = (-2, -1), norm: str = "backward", out: Optional[JaxArray] = None, @@ -815,7 +822,7 @@ def ifftn( @with_unsupported_dtypes( - {"0.4.19 and below": ("bfloat16", "float16", "complex")}, backend_version + {"0.4.24 and below": ("bfloat16", "float16", "complex")}, backend_version ) def embedding( weights: JaxArray, @@ -863,11 +870,11 @@ def rfft( return ret -@with_unsupported_dtypes({"0.4.19 and below": ("float16", "complex")}, backend_version) +@with_unsupported_dtypes({"0.4.24 and below": ("float16", "complex")}, backend_version) def rfftn( x: JaxArray, - s: Sequence[int] = None, - axes: Sequence[int] = None, + s: Optional[Sequence[int]] = None, + axes: Optional[Sequence[int]] = None, *, norm: str = "backward", out: Optional[JaxArray] = None, @@ -891,7 +898,7 @@ def rfftn( raise ivy.utils.exceptions.IvyError( f"Invalid data points {s}, expecting s points larger than 1" ) - if norm != "backward" and norm != "ortho" and norm != "forward": + if norm not in {"backward", "ortho", "forward"}: raise ivy.utils.exceptions.IvyError(f"Unrecognized normalization mode {norm}") return jnp.fft.rfftn(x, s, axes, norm).astype(jnp.complex128) @@ -985,7 +992,7 @@ def stft_1D(signals, frame_length, frame_step, fft_length, pad_end): windowed_frame = jnp.asarray(windowed_frame, dtype=dtype) fft_frame = jnp.fft.fft(windowed_frame, axis=-1) - slit = int((fft_length // 2 + 1)) + slit = int(fft_length // 2 + 1) stft_result.append(fft_frame[..., 0:slit]) stft = jnp.stack(stft_result, axis=0) diff --git a/ivy/functional/backends/jax/experimental/linear_algebra.py b/ivy/functional/backends/jax/experimental/linear_algebra.py index 0f1841e41f1a6..d5b6aa3d31174 100644 --- a/ivy/functional/backends/jax/experimental/linear_algebra.py +++ b/ivy/functional/backends/jax/experimental/linear_algebra.py @@ -2,14 +2,13 @@ from typing import Optional, Tuple, Sequence, Union import jax.numpy as jnp import jax.scipy.linalg as jla - +from collections import namedtuple from ivy.func_wrapper import with_supported_dtypes from ivy.functional.backends.jax import JaxArray import ivy from ivy.functional.ivy.experimental.linear_algebra import _check_valid_dimension_size -from ivy.utils.exceptions import IvyNotImplementedException from . import backend_version @@ -180,8 +179,22 @@ def lu_factor( *, pivot: Optional[bool] = True, out: Optional[JaxArray] = None, -) -> Tuple[JaxArray]: - raise IvyNotImplementedException() +) -> Tuple[JaxArray, JaxArray]: + ret = jla.lu(x) + ret_tuple = namedtuple("lu_factor", ["LU", "p"]) + ret_1 = ret[1] + return ret_tuple((ret_1 - jnp.eye(*ret_1.shape)) + ret[2], ret[0]) + + +def lu_solve( + lu: Tuple[JaxArray, JaxArray], + p: JaxArray, + b: JaxArray, + /, + *, + out: Optional[JaxArray] = None, +) -> JaxArray: + return jla.lu_solve((lu, p), b) def dot( diff --git a/ivy/functional/backends/jax/experimental/losses.py b/ivy/functional/backends/jax/experimental/losses.py index bb7e3e3020d50..8456c3e1defcf 100644 --- a/ivy/functional/backends/jax/experimental/losses.py +++ b/ivy/functional/backends/jax/experimental/losses.py @@ -1,5 +1,4 @@ import jax.numpy as jnp -from typing import Optional from ivy.functional.backends.jax import JaxArray # local @@ -30,8 +29,8 @@ def smooth_l1_loss( target: JaxArray, /, *, - beta: Optional[float] = 1.0, - reduction: Optional[str] = "mean", + beta: float = 1.0, + reduction: str = "mean", ) -> JaxArray: if beta < 1e-5: loss = jnp.abs(input - target) @@ -52,7 +51,7 @@ def soft_margin_loss( target: JaxArray, /, *, - reduction: Optional[str] = "mean", + reduction: str = "mean", ) -> JaxArray: loss = jnp.sum(jnp.log1p(jnp.exp(-input * target))) / jnp.size(input) @@ -64,11 +63,11 @@ def soft_margin_loss( return loss -def _apply_loss_reduction(loss: JaxArray, reduction: str, axis=None) -> JaxArray: +def _apply_loss_reduction(loss: JaxArray, reduction: str) -> JaxArray: if reduction == "sum": - return jnp.sum(loss, axis=axis) + return jnp.sum(loss) elif reduction == "mean": - return jnp.mean(loss, axis=axis) + return jnp.mean(loss) else: # reduction == "none" return loss @@ -83,30 +82,30 @@ def _validate_poisson_nll_params( # Validate dtypes for parameter, name in zip([input, label], ["input", "label"]): if parameter.dtype not in allowed_dtypes: - raise ValueError( - "The dtype of '%s' in poisson_nll_loss should be one of %s, but" - " received %s." % (name, allowed_dtypes, parameter.dtype) + raise TypeError( + f"The dtype of '{name}' in poisson_nll_loss should be one of" + f" {allowed_dtypes}, but received {parameter.dtype}." ) # Validate epsilon if epsilon <= 0: raise ValueError( "The value of `epsilon` in poisson_nll_loss should be positive, but" - " received %f, which is not allowed" % epsilon + f" received {epsilon}, which is not allowed." ) # Validate reduction if reduction not in ["sum", "mean", "none"]: raise ValueError( "The value of 'reduction' in poisson_nll_loss should be 'sum', 'mean' or" - " 'none', but received %s, which is not allowed." % reduction + f" 'none', but received {reduction}, which is not allowed." ) # Validate shape if input.shape != label.shape: raise ValueError( - "The shape of 'input' (%s) must be the same as the shape of 'label' (%s)." - % (input.shape, label.shape) + f"The shape of 'input' ({input.shape}) must be the same as the shape of" + f" 'label' ({label.shape})." ) return True @@ -114,7 +113,7 @@ def _validate_poisson_nll_params( @with_supported_device_and_dtypes( { - "0.4.14 and below": { + "0.4.18 and below": { "cpu": ("float16", "float32", "float64"), } }, @@ -153,3 +152,28 @@ def poisson_nll_loss( cond = jnp.logical_and(target_arr >= zeroes, target_arr <= ones) loss = loss + jnp.where(cond, zeroes, striling_approx_term) return _apply_loss_reduction(loss, reduction) + + +@with_supported_device_and_dtypes( + { + "0.4.18 and below": { + "cpu": ("float32", "float64"), + } + }, + backend_version, +) +def hinge_embedding_loss( + input: JaxArray, + target: JaxArray, + *, + margin: float = 1.0, + reduction: str = "mean", +) -> JaxArray: + zero_ = jnp.zeros([1], dtype=input.dtype) + + relu_part = jnp.maximum(margin - input, 0) + + loss = jnp.where(target == 1.0, input, zero_) + jnp.where( + target == -1.0, relu_part, zero_ + ) + return _apply_loss_reduction(loss, reduction) diff --git a/ivy/functional/backends/jax/experimental/manipulation.py b/ivy/functional/backends/jax/experimental/manipulation.py index fc760a9929655..59ee341ab7870 100644 --- a/ivy/functional/backends/jax/experimental/manipulation.py +++ b/ivy/functional/backends/jax/experimental/manipulation.py @@ -1,5 +1,6 @@ # local from typing import ( + Iterable, Optional, Union, Sequence, @@ -14,6 +15,7 @@ import jax.lax as jlax from numbers import Number from collections import namedtuple +from ivy.func_wrapper import handle_out_argument # local import ivy @@ -146,7 +148,7 @@ def _to_nested_tuple(nested_list): def pad( input: JaxArray, - pad_width: Union[Sequence[Sequence[int]], JaxArray, int], + pad_width: Union[Iterable[Tuple[int]], int], /, *, mode: Union[ @@ -166,9 +168,9 @@ def pad( ], Callable, ] = "constant", - stat_length: Union[Sequence[Sequence[int]], int] = 1, - constant_values: Union[Sequence[Sequence[Number]], Number] = 0, - end_values: Union[Sequence[Sequence[Number]], Number] = 0, + stat_length: Union[Iterable[Tuple[int]], int] = 1, + constant_values: Union[Iterable[Tuple[Number]], Number] = 0, + end_values: Union[Iterable[Tuple[Number]], Number] = 0, reflect_type: Literal["even", "odd"] = "even", **kwargs: Optional[Any], ) -> JaxArray: @@ -441,11 +443,11 @@ def take( if ivy.exists(axis): try: x_shape = x.shape[axis] - except Exception: + except Exception as e: raise ValueError( f"axis {axis} is out of bounds for array of dimension" f" {len(x.shape)}" - ) + ) from e else: x_shape = jnp.prod(x.shape) @@ -461,9 +463,25 @@ def take( # clip, wrap, fill ret = jnp.take(x, indices, axis=axis, mode=mode, fill_value=fill_value) if ivy.exists(out): - ivy.inplace_update(out) + ivy.inplace_update(out, ret) return ret def trim_zeros(a: JaxArray, /, *, trim: Optional[str] = "bf") -> JaxArray: return jnp.trim_zeros(a, trim=trim) + + +@handle_out_argument +def unflatten( + x: JaxArray, + /, + shape: Tuple[int] = None, + dim: int = 0, + *, + out: Optional[JaxArray] = None, + order: Optional[str] = None, +) -> JaxArray: + dim = abs(len(x.shape) + dim) if dim < 0 else dim + res_shape = x.shape[:dim] + shape + x.shape[dim + 1 :] + res = jnp.reshape(x, res_shape) + return res diff --git a/ivy/functional/backends/jax/experimental/random.py b/ivy/functional/backends/jax/experimental/random.py index b0148cc1ca30b..9dc36ed0fb3bb 100644 --- a/ivy/functional/backends/jax/experimental/random.py +++ b/ivy/functional/backends/jax/experimental/random.py @@ -56,7 +56,7 @@ def beta( return jax.random.beta(rng_input, a, b, shape, dtype) -@with_unsupported_dtypes({"0.4.19 and below": ("bfloat16",)}, backend_version) +@with_unsupported_dtypes({"0.4.24 and below": ("bfloat16",)}, backend_version) def gamma( alpha: Union[float, JaxArray], beta: Union[float, JaxArray], @@ -117,6 +117,7 @@ def bernoulli( seed: Optional[int] = None, out: Optional[JaxArray] = None, ) -> JaxArray: + dtype = dtype if dtype is not None else probs.dtype if seed: rng_input = jax.random.PRNGKey(seed) else: @@ -126,4 +127,4 @@ def bernoulli( probs = jax.nn.softmax(logits, axis=-1) if hasattr(probs, "shape") and not _check_shapes_broadcastable(shape, probs.shape): shape = probs.shape - return jax.random.bernoulli(rng_input, probs, shape=shape) + return jax.random.bernoulli(rng_input, probs, shape=shape).astype(dtype) diff --git a/ivy/functional/backends/jax/experimental/sorting.py b/ivy/functional/backends/jax/experimental/sorting.py index 27f7994429c51..b6255d7919ef3 100644 --- a/ivy/functional/backends/jax/experimental/sorting.py +++ b/ivy/functional/backends/jax/experimental/sorting.py @@ -23,7 +23,7 @@ def invert_permutation( # lexsort -@with_unsupported_dtypes({"0.4.19 and below": ("bfloat16",)}, backend_version) +@with_unsupported_dtypes({"0.4.24 and below": ("bfloat16",)}, backend_version) def lexsort( keys: JaxArray, /, diff --git a/ivy/functional/backends/jax/experimental/statistical.py b/ivy/functional/backends/jax/experimental/statistical.py index 305eb9649829c..0f67e8c5e7c28 100644 --- a/ivy/functional/backends/jax/experimental/statistical.py +++ b/ivy/functional/backends/jax/experimental/statistical.py @@ -10,7 +10,7 @@ @with_unsupported_dtypes( - {"0.4.19 and below": ("bfloat16",)}, + {"0.4.24 and below": ("bfloat16",)}, backend_version, ) def histogram( @@ -121,7 +121,7 @@ def histogram( @with_unsupported_dtypes( - {"0.4.19 and below": ("complex64", "complex128")}, backend_version + {"0.4.24 and below": ("complex64", "complex128")}, backend_version ) def median( input: JaxArray, @@ -406,7 +406,7 @@ def __get_index(lst, indices=None, prefix=None): @with_unsupported_dtypes( { - "0.4.19 and below": ( + "0.4.24 and below": ( "bfloat16", "bool", ) diff --git a/ivy/functional/backends/jax/general.py b/ivy/functional/backends/jax/general.py index e783eb26fbcbb..538788b21af30 100644 --- a/ivy/functional/backends/jax/general.py +++ b/ivy/functional/backends/jax/general.py @@ -1,24 +1,26 @@ -"""Collection of Jax general functions, wrapped to fit Ivy syntax and signature.""" +"""Collection of Jax general functions, wrapped to fit Ivy syntax and +signature.""" -# global -import jax -import numpy as np -import jax.numpy as jnp +import importlib +import multiprocessing as _multiprocessing +from functools import reduce as _reduce from numbers import Number from operator import mul -from functools import reduce as _reduce -from typing import Optional, Union, Sequence, Callable, Tuple -import multiprocessing as _multiprocessing -import importlib +from typing import Callable, Optional, Sequence, Tuple, Union +# global +import jax +import jax.numpy as jnp +import numpy as np # local import ivy from ivy.func_wrapper import with_unsupported_dtypes +from ivy.functional.backends.jax import JaxArray, NativeArray from ivy.functional.backends.jax.device import _to_array, _to_device from ivy.functional.ivy.general import _broadcast_to -from ivy.functional.backends.jax import JaxArray, NativeArray from ivy.utils.exceptions import _check_inplace_update_support + from . import backend_version @@ -57,8 +59,7 @@ def _mask_to_index(query, x): raise ivy.exceptions.IvyException("too many indices") elif not len(query.shape): query = jnp.tile(query, x.shape[0]) - expected_shape = x[query].shape - return jnp.where(query), expected_shape + return jnp.where(query) def get_item( @@ -66,15 +67,17 @@ def get_item( /, query: Union[JaxArray, Tuple], *, - copy: bool = None, + copy: Optional[bool] = None, ) -> JaxArray: + if copy: + x = x.copy() if ivy.is_array(query) and ivy.is_bool_dtype(query): if not len(query.shape): if not query: return jnp.array([], dtype=x.dtype) else: return jnp.expand_dims(x, 0) - query, _ = _mask_to_index(query, x) + query = _mask_to_index(query, x) elif isinstance(query, list): query = (query,) return x.__getitem__(query) @@ -89,7 +92,9 @@ def set_item( copy: Optional[bool] = False, ) -> JaxArray: if ivy.is_array(query) and ivy.is_bool_dtype(query): - query, expected_shape = _mask_to_index(query, x) + query = _mask_to_index(query, x) + expected_shape = x[query].shape + if ivy.is_array(val): val = _broadcast_to(val, expected_shape)._data ret = x.at[query].set(val) if copy: @@ -101,7 +106,7 @@ def array_equal(x0: JaxArray, x1: JaxArray, /) -> bool: return bool(jnp.array_equal(x0, x1)) -@with_unsupported_dtypes({"0.4.19 and below": ("bfloat16",)}, backend_version) +@with_unsupported_dtypes({"0.4.24 and below": ("bfloat16",)}, backend_version) def to_numpy(x: JaxArray, /, *, copy: bool = True) -> np.ndarray: if copy: return np.array(_to_array(x)) @@ -217,6 +222,10 @@ def get_num_dims(x: JaxArray, /, *, as_array: bool = False) -> Union[JaxArray, i return jnp.asarray(len(jnp.shape(x))) if as_array else len(x.shape) +def size(x: JaxArray, /) -> int: + return x.size + + def inplace_arrays_supported(): return False @@ -420,7 +429,7 @@ def vmap( ) -@with_unsupported_dtypes({"0.4.19 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"0.4.24 and below": ("float16", "bfloat16")}, backend_version) def isin( elements: JaxArray, test_elements: JaxArray, diff --git a/ivy/functional/backends/jax/gradients.py b/ivy/functional/backends/jax/gradients.py index 13ee80730c2b4..5e96bdd28c101 100644 --- a/ivy/functional/backends/jax/gradients.py +++ b/ivy/functional/backends/jax/gradients.py @@ -1,4 +1,5 @@ -"""Collection of Jax gradient functions, wrapped to fit Ivy syntax and signature.""" +"""Collection of Jax gradient functions, wrapped to fit Ivy syntax and +signature.""" # global import jax diff --git a/ivy/functional/backends/jax/layers.py b/ivy/functional/backends/jax/layers.py index fe6a369ba8d24..02e980559fd37 100644 --- a/ivy/functional/backends/jax/layers.py +++ b/ivy/functional/backends/jax/layers.py @@ -1,4 +1,5 @@ -"""Collection of Jax network layers, wrapped to fit Ivy syntax and signature.""" +"""Collection of Jax network layers, wrapped to fit Ivy syntax and +signature.""" # global import jax.lax as jlax @@ -63,7 +64,7 @@ def _get_new_padding_before_conv( dilations, x_dilations, ): - if not len(x_dilations) == x_dilations.count(1): + if len(x_dilations) != x_dilations.count(1): new_pad = [0] * dims x_shape = ( list(x.shape[1 : dims + 1]) @@ -130,6 +131,7 @@ def conv1d_transpose( /, *, output_shape: Optional[Union[ivy.NativeShape, Sequence[int]]] = None, + filter_format: str = "channel_last", data_format: str = "NWC", dilations: Union[int, Tuple[int]] = 1, bias: Optional[JaxArray] = None, @@ -141,7 +143,8 @@ def conv1d_transpose( x_shape = list(x.shape[1:2]) else: x_shape = list(x.shape[2:]) - filters = jnp.swapaxes(filters, -1, -2) + if filter_format == "channel_first": + filters = jnp.transpose(filters, (2, 1, 0)) padding = _get_tranpose_padding( x_shape, filters.shape, strides, padding, 1, dilations, output_shape ) @@ -198,6 +201,7 @@ def conv2d_transpose( /, *, output_shape: Optional[Union[ivy.NativeShape, Sequence[int]]] = None, + filter_format: str = "channel_last", data_format: str = "NHWC", dilations: Union[int, Tuple[int, int]] = 1, bias: Optional[JaxArray] = None, @@ -209,7 +213,8 @@ def conv2d_transpose( x_shape = list(x.shape[1:3]) else: x_shape = list(x.shape[2:]) - filters = jnp.swapaxes(filters, -1, -2) + if filter_format == "channel_first": + filters = jnp.transpose(filters, (2, 3, 1, 0)) padding = _get_tranpose_padding( x_shape, filters.shape, strides, padding, 2, dilations, output_shape ) @@ -299,13 +304,15 @@ def conv3d_transpose( *, output_shape: Optional[Union[ivy.NativeShape, Sequence[int]]] = None, dilations: Union[int, Tuple[int, int, int]] = 1, + filter_format: str = "channel_last", data_format: str = "NDHWC", bias: Optional[JaxArray] = None, out: Optional[JaxArray] = None, ) -> JaxArray: strides = [strides] * 3 if isinstance(strides, int) else strides dilations = [dilations] * 3 if isinstance(dilations, int) else dilations - filters = jnp.swapaxes(filters, -1, -2) + if filter_format == "channel_first": + filters = jnp.transpose(filters, (2, 3, 4, 1, 0)) if data_format == "NDHWC": x_shape = list(x.shape[1:4]) else: @@ -332,11 +339,11 @@ def conv3d_transpose( def _get_filter_dataformat(dims: int = 2, filter_format: str = "channel_last"): first = True if filter_format == "channel_first" else False if dims == 1: - return "WIO" if not first else "OIW" + return "OIW" if first else "WIO" if dims == 2: - return "HWIO" if not first else "OIHW" + return "OIHW" if first else "HWIO" elif dims == 3: - return "DHWIO" if not first else "OIDHW" + return "OIDHW" if first else "DHWIO" def conv_general_dilated( @@ -361,7 +368,7 @@ def conv_general_dilated( if isinstance(padding, int): padding = [(padding, padding)] * dims filter_df = _get_filter_dataformat(dims, filter_format) - if not len(x_dilations) == x_dilations.count(1): + if len(x_dilations) != x_dilations.count(1): new_pad = [0] * dims x_shape = ( list(x.shape[1 : dims + 1]) @@ -417,15 +424,17 @@ def conv_general_transpose( *, dims: int = 2, output_shape: Optional[Union[ivy.NativeShape, Sequence[int]]] = None, + filter_format: str = "channel_last", data_format: str = "channel_last", dilations: Union[int, Tuple[int], Tuple[int, int], Tuple[int, int, int]] = 1, - feature_group_count: Optional[int] = 1, + feature_group_count: int = 1, bias: Optional[JaxArray] = None, out: Optional[JaxArray] = None, ): strides = [strides] * dims if isinstance(strides, int) else strides dilations = [dilations] * dims if isinstance(dilations, int) else dilations - filters = jnp.swapaxes(filters, -1, -2) + if filter_format == "channel_first": + filters = jnp.transpose(filters, (*range(2, dims + 2), 1, 0)) df = _get_x_data_format(dims, "channel_last") filter_df = _get_filter_dataformat(dims) if data_format == "channel_first": @@ -464,7 +473,7 @@ def nms( score_threshold=float("-inf"), ): change_id = False - if score_threshold is not float("-inf") and scores is not None: + if score_threshold != float("-inf") and scores is not None: keep_idx = scores > score_threshold boxes = boxes[keep_idx] scores = scores[keep_idx] @@ -480,7 +489,7 @@ def nms( ret = jnp.array([], dtype=ivy.int64) else: areas = jnp.prod(boxes[:, 2:4] - boxes[:, :2], axis=1) - order = jnp.argsort((-1 * scores)) # get boxes with more ious first + order = jnp.argsort(-1 * scores) # get boxes with more ious first boxes = boxes[order] areas = areas[order] size = order.size @@ -492,7 +501,8 @@ def nms( keep = jnp.zeros((size,), dtype=jnp.int64) keep_idx = 0 - while jnp.unique(order).size > 1: + def body_fn(loop_vars): + keep, keep_idx, boxes, areas, order = loop_vars max_iou_idx = order[0] keep = keep.at[keep_idx].set(max_iou_idx) keep_idx += 1 @@ -513,6 +523,15 @@ def nms( boxes = boxes.at[forward].set(boxes[forward[::-1]]) areas = areas.at[forward].set(areas[forward[::-1]]) + return keep, keep_idx, boxes, areas, order + + def cond_fn(loop_vars): + _, _, _, _, order = loop_vars + return jnp.min(order) != jnp.max(order) + + init_vars = (keep, keep_idx, boxes, areas, order) + keep, keep_idx, boxes, _, _ = jlax.while_loop(cond_fn, body_fn, init_vars) + ret = jnp.array(keep[:keep_idx], dtype=jnp.int64) if len(ret) > 1 and scores is not None: diff --git a/ivy/functional/backends/jax/linear_algebra.py b/ivy/functional/backends/jax/linear_algebra.py index dea93a65efc0b..886d159961ef1 100644 --- a/ivy/functional/backends/jax/linear_algebra.py +++ b/ivy/functional/backends/jax/linear_algebra.py @@ -20,7 +20,7 @@ @with_unsupported_dtypes( - {"0.4.19 and below": ("bfloat16", "float16", "complex")}, + {"0.4.24 and below": ("bfloat16", "float16", "complex")}, backend_version, ) def cholesky( @@ -34,7 +34,7 @@ def cholesky( return ret -@with_unsupported_dtypes({"0.4.19 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"0.4.24 and below": ("complex",)}, backend_version) def cross( x1: JaxArray, x2: JaxArray, @@ -51,14 +51,14 @@ def cross( @with_unsupported_dtypes( - {"0.4.19 and below": ("bfloat16", "float16", "complex")}, + {"0.4.24 and below": ("bfloat16", "float16", "complex")}, backend_version, ) def det(x: JaxArray, /, *, out: Optional[JaxArray] = None) -> JaxArray: return jnp.linalg.det(x) -@with_unsupported_dtypes({"0.4.19 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"0.4.24 and below": ("float16", "bfloat16")}, backend_version) def eig(x: JaxArray, /, *, out: Optional[JaxArray] = None) -> Tuple[JaxArray]: result_tuple = NamedTuple( "eig", [("eigenvalues", JaxArray), ("eigenvectors", JaxArray)] @@ -67,7 +67,7 @@ def eig(x: JaxArray, /, *, out: Optional[JaxArray] = None) -> Tuple[JaxArray]: return result_tuple(eigenvalues, eigenvectors) -@with_unsupported_dtypes({"0.4.19 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"0.4.24 and below": ("complex",)}, backend_version) def diagonal( x: JaxArray, /, @@ -77,7 +77,7 @@ def diagonal( axis2: int = -1, out: Optional[JaxArray] = None, ) -> JaxArray: - if not x.dtype == bool and not jnp.issubdtype(x.dtype, jnp.integer): + if x.dtype != bool and not jnp.issubdtype(x.dtype, jnp.integer): ret = jnp.diagonal(x, offset=offset, axis1=axis1, axis2=axis2) ret_edited = jnp.diagonal( x.at[1 / x == -jnp.inf].set(-jnp.inf), @@ -104,7 +104,7 @@ def tensorsolve( @with_unsupported_dtypes( - {"0.4.19 and below": ("bfloat16", "float16", "complex")}, + {"0.4.24 and below": ("bfloat16", "float16", "complex")}, backend_version, ) def eigh( @@ -118,7 +118,7 @@ def eigh( @with_unsupported_dtypes( - {"0.4.19 and below": ("bfloat16", "float16", "complex")}, + {"0.4.24 and below": ("bfloat16", "float16", "complex")}, backend_version, ) def eigvalsh( @@ -127,14 +127,14 @@ def eigvalsh( return jnp.linalg.eigvalsh(x, UPLO=UPLO) -@with_unsupported_dtypes({"0.4.19 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"0.4.24 and below": ("complex",)}, backend_version) def inner(x1: JaxArray, x2: JaxArray, /, *, out: Optional[JaxArray] = None) -> JaxArray: x1, x2 = ivy.promote_types_of_inputs(x1, x2) return jnp.inner(x1, x2) @with_unsupported_dtypes( - {"0.4.19 and below": ("bfloat16", "float16", "complex")}, + {"0.4.24 and below": ("bfloat16", "float16", "complex")}, backend_version, ) def inv( @@ -155,7 +155,7 @@ def inv( @with_unsupported_dtypes( - {"0.4.19 and below": ("bfloat16", "float16", "complex")}, + {"0.4.24 and below": ("bfloat16", "float16", "complex")}, backend_version, ) def matmul( @@ -181,7 +181,7 @@ def matmul( @with_unsupported_dtypes( - {"0.4.19 and below": ("bfloat16", "float16", "complex")}, + {"0.4.24 and below": ("bfloat16", "float16", "complex")}, backend_version, ) def matrix_norm( @@ -191,8 +191,11 @@ def matrix_norm( ord: Union[int, float, Literal[inf, -inf, "fro", "nuc"]] = "fro", axis: Tuple[int, int] = (-2, -1), keepdims: bool = False, + dtype: Optional[jnp.dtype] = None, out: Optional[JaxArray] = None, ) -> JaxArray: + if dtype is not None: + x = ivy.astype(x, dtype) if hasattr(axis, "__iter__"): if not isinstance(axis, tuple): axis = tuple(axis) @@ -202,13 +205,13 @@ def matrix_norm( return jnp.linalg.norm(x, ord=ord, axis=axis, keepdims=keepdims) -@with_unsupported_dtypes({"0.4.19 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"0.4.24 and below": ("complex",)}, backend_version) def matrix_power(x: JaxArray, n: int, /, *, out: Optional[JaxArray] = None) -> JaxArray: return jnp.linalg.matrix_power(x, n) @with_unsupported_dtypes( - {"0.4.19 and below": ("bfloat16", "float16", "complex")}, + {"0.4.24 and below": ("bfloat16", "float16", "complex")}, backend_version, ) def matrix_rank( @@ -239,7 +242,7 @@ def matrix_rank( @with_unsupported_dtypes( - {"0.4.19 and below": ("int", "float16", "complex")}, + {"0.4.24 and below": ("int", "float16", "complex")}, backend_version, ) def matrix_transpose( @@ -251,7 +254,7 @@ def matrix_transpose( @with_unsupported_dtypes( - {"0.4.19 and below": ("bfloat16", "float16", "complex")}, + {"0.4.24 and below": ("bfloat16", "float16", "complex")}, backend_version, ) def outer( @@ -266,7 +269,7 @@ def outer( @with_unsupported_dtypes( - {"0.4.19 and below": ("bfloat16", "float16", "complex")}, + {"0.4.24 and below": ("bfloat16", "float16", "complex")}, backend_version, ) def pinv( @@ -284,7 +287,7 @@ def pinv( @with_unsupported_dtypes( - {"0.4.19 and below": ("bfloat16", "float16", "complex")}, + {"0.4.24 and below": ("bfloat16", "float16", "complex")}, backend_version, ) def qr( @@ -296,7 +299,7 @@ def qr( @with_unsupported_dtypes( - {"0.4.19 and below": ("bfloat16", "float16", "complex")}, + {"0.4.24 and below": ("bfloat16", "float16", "complex")}, backend_version, ) def slogdet( @@ -309,7 +312,7 @@ def slogdet( @with_unsupported_dtypes( - {"0.4.19 and below": ("bfloat16", "float16", "complex")}, + {"0.4.24 and below": ("bfloat16", "float16", "complex")}, backend_version, ) def solve( @@ -351,7 +354,7 @@ def solve( @with_unsupported_dtypes( - {"0.4.19 and below": ("bfloat16", "float16", "complex")}, + {"0.4.24 and below": ("bfloat16", "float16", "complex")}, backend_version, ) def svd( @@ -368,7 +371,7 @@ def svd( @with_unsupported_dtypes( - {"0.4.19 and below": ("bfloat16", "float16", "complex")}, + {"0.4.24 and below": ("bfloat16", "float16", "complex")}, backend_version, ) def svdvals( @@ -378,7 +381,7 @@ def svdvals( return jnp.linalg.svd(x, compute_uv=False) -@with_unsupported_dtypes({"0.4.19 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"0.4.24 and below": ("complex",)}, backend_version) def tensordot( x1: JaxArray, x2: JaxArray, @@ -392,7 +395,7 @@ def tensordot( @with_unsupported_dtypes( - {"0.4.19 and below": ("bfloat16", "float16", "complex")}, + {"0.4.24 and below": ("bfloat16", "float16", "complex")}, backend_version, ) def trace( @@ -407,7 +410,7 @@ def trace( return jnp.trace(x, offset=offset, axis1=axis1, axis2=axis2, out=out) -@with_unsupported_dtypes({"0.4.19 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"0.4.24 and below": ("complex",)}, backend_version) def vecdot( x1: JaxArray, x2: JaxArray, /, *, axis: int = -1, out: Optional[JaxArray] = None ) -> JaxArray: @@ -415,7 +418,7 @@ def vecdot( return jnp.tensordot(x1, x2, axes=(axis, axis)) -@with_unsupported_dtypes({"0.4.19 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"0.4.24 and below": ("complex",)}, backend_version) def vector_norm( x: JaxArray, /, @@ -445,7 +448,7 @@ def vector_norm( # ------# -@with_unsupported_dtypes({"0.4.19 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"0.4.24 and below": ("complex",)}, backend_version) def diag( x: JaxArray, /, @@ -457,7 +460,7 @@ def diag( @with_unsupported_dtypes( - {"0.4.19 and below": ("bfloat16", "float16", "complex")}, + {"0.4.24 and below": ("bfloat16", "float16", "complex")}, backend_version, ) def vander( @@ -473,7 +476,7 @@ def vander( @with_unsupported_dtypes( { - "0.4.19 and below": ( + "0.4.24 and below": ( "complex", "unsigned", ) diff --git a/ivy/functional/backends/jax/manipulation.py b/ivy/functional/backends/jax/manipulation.py index f2e54c5ddfd51..a792afa21b6eb 100644 --- a/ivy/functional/backends/jax/manipulation.py +++ b/ivy/functional/backends/jax/manipulation.py @@ -1,7 +1,8 @@ # global import math from numbers import Number -from typing import Union, Tuple, Optional, List, Sequence, Iterable +from typing import Iterable, List, Optional, Sequence, Tuple, Union + import jax.numpy as jnp import numpy as np @@ -9,6 +10,7 @@ import ivy from ivy.func_wrapper import with_unsupported_dtypes from ivy.functional.backends.jax import JaxArray + from . import backend_version @@ -39,7 +41,7 @@ def concat( try: return jnp.concatenate(xs, axis) except ValueError as error: - raise ivy.utils.exceptions.IvyIndexError(error) + raise ivy.utils.exceptions.IvyIndexError(error) from error def expand_dims( @@ -54,7 +56,7 @@ def expand_dims( ret = jnp.expand_dims(x, axis) return ret except ValueError as error: - raise ivy.utils.exceptions.IvyIndexError(error) + raise ivy.utils.exceptions.IvyIndexError(error) from error def flip( @@ -76,6 +78,9 @@ def permute_dims( copy: Optional[bool] = None, out: Optional[JaxArray] = None, ) -> JaxArray: + if copy: + newarr = jnp.copy(x) + return jnp.transpose(newarr, axes) return jnp.transpose(x, axes) @@ -122,6 +127,8 @@ def squeeze( copy: Optional[bool] = None, out: Optional[JaxArray] = None, ) -> JaxArray: + if copy: + x = jnp.copy(x) if x.shape == (): if axis is None or axis == 0 or axis == -1: return x @@ -143,7 +150,7 @@ def stack( try: return jnp.stack(arrays, axis=axis) except ValueError as error: - raise ivy.utils.exceptions.IvyIndexError(error) + raise ivy.utils.exceptions.IvyIndexError(error) from error # Extra # @@ -226,7 +233,7 @@ def clip( return x -@with_unsupported_dtypes({"0.4.19 and below": ("uint64",)}, backend_version) +@with_unsupported_dtypes({"0.4.24 and below": ("uint64",)}, backend_version) def constant_pad( x: JaxArray, /, diff --git a/ivy/functional/backends/jax/module.py b/ivy/functional/backends/jax/module.py new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/ivy/functional/backends/jax/random.py b/ivy/functional/backends/jax/random.py index 9abba4d7bb617..ef0555fabf6d7 100644 --- a/ivy/functional/backends/jax/random.py +++ b/ivy/functional/backends/jax/random.py @@ -1,4 +1,5 @@ -"""Collection of Jax random functions, wrapped to fit Ivy syntax and signature.""" +"""Collection of Jax random functions, wrapped to fit Ivy syntax and +signature.""" # global import jax @@ -82,7 +83,7 @@ def random_normal( return jax.random.normal(rng_input, shape, dtype=dtype) * std + mean -@with_unsupported_dtypes({"0.4.19 and below": ("bfloat16",)}, backend_version) +@with_unsupported_dtypes({"0.4.24 and below": ("bfloat16",)}, backend_version) def multinomial( population_size: int, num_samples: int, diff --git a/ivy/functional/backends/jax/searching.py b/ivy/functional/backends/jax/searching.py index ffdd22b03e098..b149e64cc38d1 100644 --- a/ivy/functional/backends/jax/searching.py +++ b/ivy/functional/backends/jax/searching.py @@ -12,7 +12,7 @@ # ------------------ # -@with_unsupported_dtypes({"0.4.19 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"0.4.24 and below": ("complex",)}, backend_version) def argmax( x: JaxArray, /, @@ -38,7 +38,7 @@ def argmax( return ret -@with_unsupported_dtypes({"0.4.19 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"0.4.24 and below": ("complex",)}, backend_version) def argmin( x: JaxArray, /, diff --git a/ivy/functional/backends/jax/set.py b/ivy/functional/backends/jax/set.py index d8b1864435912..d61f0234bccdd 100644 --- a/ivy/functional/backends/jax/set.py +++ b/ivy/functional/backends/jax/set.py @@ -96,7 +96,7 @@ def unique_inverse( values = jnp.append(values, jnp.full(nan_count - 1, jnp.nan), axis=0).astype( x.dtype ) - inverse_indices = jnp.reshape(inverse_indices, x.shape, axis=0) + inverse_indices = jnp.reshape(inverse_indices, x.shape) return Results(values, inverse_indices) diff --git a/ivy/functional/backends/jax/sorting.py b/ivy/functional/backends/jax/sorting.py index 4edfc258954ab..fc54befcf72ce 100644 --- a/ivy/functional/backends/jax/sorting.py +++ b/ivy/functional/backends/jax/sorting.py @@ -20,7 +20,7 @@ def argsort( ) -> JaxArray: kind = "stable" if stable else "quicksort" return ( - jnp.argsort(-x, axis=axis, kind=kind) + jnp.argsort(x, axis=axis, kind=kind, descending=descending) if descending else jnp.argsort(x, axis=axis, kind=kind) ) @@ -56,9 +56,7 @@ def searchsorted( "only Integer data types are supported for ret_dtype." ) if sorter is not None: - assert ivy.is_int_dtype(sorter.dtype) and not ivy.is_uint_dtype( - sorter.dtype - ), TypeError( + assert ivy.is_int_dtype(sorter.dtype), TypeError( f"Only signed integer data type for sorter is allowed, got {sorter.dtype}." ) x = jnp.take_along_axis(x, sorter, axis=-1) @@ -80,7 +78,7 @@ def searchsorted( # msort -@with_unsupported_dtypes({"0.4.19 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"0.4.24 and below": ("complex",)}, backend_version) def msort( a: Union[JaxArray, list, tuple], /, diff --git a/ivy/functional/backends/jax/statistical.py b/ivy/functional/backends/jax/statistical.py index f4d9ad910256e..b9e0610698256 100644 --- a/ivy/functional/backends/jax/statistical.py +++ b/ivy/functional/backends/jax/statistical.py @@ -19,10 +19,14 @@ def min( *, axis: Optional[Union[int, Sequence[int]]] = None, keepdims: bool = False, + initial: Optional[Union[int, float, complex]] = None, + where: Optional[JaxArray] = None, out: Optional[JaxArray] = None, ) -> JaxArray: axis = tuple(axis) if isinstance(axis, list) else axis - return jnp.min(a=jnp.asarray(x), axis=axis, keepdims=keepdims) + return jnp.min( + a=jnp.asarray(x), axis=axis, keepdims=keepdims, initial=initial, where=where + ) def max( @@ -37,7 +41,10 @@ def max( return jnp.max(a=jnp.asarray(x), axis=axis, keepdims=keepdims) -@with_unsupported_dtypes({"0.4.14 and below": "bfloat16"}, backend_version) +@with_unsupported_dtypes( + {"0.4.24 and below": "bfloat16"}, + backend_version, +) def mean( x: JaxArray, /, @@ -47,7 +54,7 @@ def mean( out: Optional[JaxArray] = None, ) -> JaxArray: axis = tuple(axis) if isinstance(axis, list) else axis - return jnp.mean(x, axis=axis, keepdims=keepdims) + return jnp.mean(x, axis=axis, keepdims=keepdims, dtype=x.dtype) def _infer_dtype(dtype: jnp.dtype): @@ -140,7 +147,7 @@ def var( # ------# -@with_unsupported_dtypes({"0.4.19 and below": "bfloat16"}, backend_version) +@with_unsupported_dtypes({"0.4.24 and below": ("bfloat16", "bool")}, backend_version) def cumprod( x: JaxArray, /, @@ -176,6 +183,7 @@ def cumprod( return jnp.flip(x, axis=axis) +@with_unsupported_dtypes({"0.4.24 and below": "bool"}, backend_version) def cumsum( x: JaxArray, axis: int = 0, diff --git a/ivy/functional/backends/jax/utility.py b/ivy/functional/backends/jax/utility.py index 8fac7a2afbca6..6d2293ef45913 100644 --- a/ivy/functional/backends/jax/utility.py +++ b/ivy/functional/backends/jax/utility.py @@ -19,7 +19,7 @@ def all( try: return jnp.all(x, axis, keepdims=keepdims) except ValueError as error: - raise ivy.utils.exceptions.IvyIndexError(error) + raise ivy.utils.exceptions.IvyIndexError(error) from error def any( @@ -34,4 +34,4 @@ def any( try: return jnp.any(x, axis, keepdims=keepdims, out=out) except ValueError as error: - raise ivy.utils.exceptions.IvyIndexError(error) + raise ivy.utils.exceptions.IvyIndexError(error) from error diff --git a/ivy/functional/backends/mxnet/__init__.py b/ivy/functional/backends/mxnet/__init__.py index 3e0bef791040a..9a73876faa148 100644 --- a/ivy/functional/backends/mxnet/__init__.py +++ b/ivy/functional/backends/mxnet/__init__.py @@ -201,3 +201,8 @@ def closest_valid_dtype(type=None, /, as_native=False): from .control_flow_ops import * from . import sub_backends from .sub_backends import * +from . import module +from .module import * + + +NativeModule = mx.gluon.nn.Block diff --git a/ivy/functional/backends/mxnet/activations.py b/ivy/functional/backends/mxnet/activations.py index 96bd23c3ca96f..b72a333da33f1 100644 --- a/ivy/functional/backends/mxnet/activations.py +++ b/ivy/functional/backends/mxnet/activations.py @@ -1,5 +1,4 @@ -""" -MXNet activation functions. +"""MXNet activation functions. Collection of MXNet activation functions, wrapped to fit Ivy syntax and signature. diff --git a/ivy/functional/backends/mxnet/data_type.py b/ivy/functional/backends/mxnet/data_type.py index 1ec0e1174ceec..74ab7b6cb71dd 100644 --- a/ivy/functional/backends/mxnet/data_type.py +++ b/ivy/functional/backends/mxnet/data_type.py @@ -129,9 +129,7 @@ def iinfo(type: Union[str, mx.ndarray.NDArray, np.dtype], /) -> np.iinfo: return np.iinfo(ivy.as_native_dtype(type)) -def result_type( - *arrays_and_dtypes: Union[(None, mx.ndarray.NDArray, None)] -) -> ivy.Dtype: +def result_type(*arrays_and_dtypes: Union[(None, mx.ndarray.NDArray)]) -> ivy.Dtype: raise IvyNotImplementedException() diff --git a/ivy/functional/backends/mxnet/device.py b/ivy/functional/backends/mxnet/device.py index ece458d2d7c20..1064e52b7aa21 100644 --- a/ivy/functional/backends/mxnet/device.py +++ b/ivy/functional/backends/mxnet/device.py @@ -1,5 +1,4 @@ -""" -MXNet device functions. +"""MXNet device functions. Collection of MXNet general functions, wrapped to fit Ivy syntax and signature. @@ -51,7 +50,7 @@ def as_native_dev(device: str, /): elif "gpu" in device: mx_dev = "gpu" else: - raise Exception(f"dev input {device} not supported.") + raise ValueError(f"dev input {device} not supported.") if device.find(":") != -1: mx_dev_id = int(device[device.find(":") + 1 :]) else: diff --git a/ivy/functional/backends/mxnet/experimental/gradients.py b/ivy/functional/backends/mxnet/experimental/gradients.py index e952f2264ccbb..bcd6d00b7e2e7 100644 --- a/ivy/functional/backends/mxnet/experimental/gradients.py +++ b/ivy/functional/backends/mxnet/experimental/gradients.py @@ -46,7 +46,7 @@ def vjpfun(x_in): ) return _rebuild_flattened_containers( - ivy.to_ivy(grads, nested=True, include_derived=True) + ivy.to_ivy(grads, nested=True, include_derived=True), ret_idxs ) return (ivy.to_ivy(primals_out, nested=True, include_derived=True), vjpfun) diff --git a/ivy/functional/backends/mxnet/experimental/layers.py b/ivy/functional/backends/mxnet/experimental/layers.py index 40ca4c4cec935..854cc5d46dfbb 100644 --- a/ivy/functional/backends/mxnet/experimental/layers.py +++ b/ivy/functional/backends/mxnet/experimental/layers.py @@ -1,9 +1,8 @@ # global -from typing import Optional, Union, Tuple, Literal, Sequence +from typing import List, Optional, Union, Tuple, Literal, Sequence import mxnet as mx # local -from ivy.func_wrapper import handle_partial_mixed_function from ivy.utils.exceptions import IvyNotImplementedException @@ -75,12 +74,13 @@ def avg_pool1d( x: mx.nd.NDArray, kernel: Union[int, Tuple[int]], strides: Union[int, Tuple[int]], - padding: str, + padding: Union[str, int, List[Tuple[int, int]]], /, *, data_format: str = "NWC", count_include_pad: bool = False, ceil_mode: bool = False, + divisor_override: Optional[int] = None, out: Optional[mx.nd.NDArray] = None, ) -> mx.nd.NDArray: raise IvyNotImplementedException() @@ -90,7 +90,7 @@ def avg_pool2d( x: mx.nd.NDArray, kernel: Union[int, Tuple[int], Tuple[int, int]], strides: Union[int, Tuple[int], Tuple[int, int]], - padding: str, + padding: Union[str, int, List[Tuple[int, int]]], /, *, data_format: str = "NHWC", @@ -106,7 +106,7 @@ def avg_pool3d( x: mx.nd.NDArray, kernel: Union[int, Tuple[int], Tuple[int, int, int]], strides: Union[int, Tuple[int], Tuple[int, int, int]], - padding: str, + padding: Union[str, int, List[Tuple[int, int]]], /, *, data_format: str = "NDHWC", @@ -190,21 +190,6 @@ def ifft( raise IvyNotImplementedException() -@handle_partial_mixed_function( - lambda *args, mode="linear", scale_factor=None, recompute_scale_factor=None, align_corners=None, **kwargs: ( # noqa: E501 - not align_corners - and mode - not in [ - "area", - "nearest", - "tf_area", - "mitchellcubic", - "gaussian", - "bicubic", - ] - and recompute_scale_factor - ) -) def interpolate( x: mx.nd.NDArray, size: Union[Sequence[int], int], @@ -214,11 +199,13 @@ def interpolate( "linear", "bilinear", "trilinear", + "nd", "nearest", "area", "nearest_exact", "tf_area", - "bicubic_tensorflow" "bicubic", + "tf_bicubic", + "bicubic", "mitchellcubic", "lanczos3", "lanczos5", @@ -226,7 +213,7 @@ def interpolate( ] = "linear", scale_factor: Optional[Union[Sequence[int], int]] = None, recompute_scale_factor: Optional[bool] = None, - align_corners: Optional[bool] = None, + align_corners: bool = False, antialias: bool = False, out: Optional[mx.nd.NDArray] = None, ): diff --git a/ivy/functional/backends/mxnet/general.py b/ivy/functional/backends/mxnet/general.py index c469b517c47c1..9f8e0e707cc8f 100644 --- a/ivy/functional/backends/mxnet/general.py +++ b/ivy/functional/backends/mxnet/general.py @@ -18,7 +18,7 @@ def is_native_array( if exclusive: return isinstance(x, mx.ndarray.NDArray) else: - return isinstance(x, mx.ndarray.NDArray) or isinstance(x, np.ndarray) + return isinstance(x, (mx.ndarray.NDArray, np.ndarray)) def to_numpy(x: mx.ndarray.NDArray, /, *, copy: bool = True) -> np.ndarray: diff --git a/ivy/functional/backends/mxnet/gradients.py b/ivy/functional/backends/mxnet/gradients.py index 97577e8634e6f..203640b7df2ef 100644 --- a/ivy/functional/backends/mxnet/gradients.py +++ b/ivy/functional/backends/mxnet/gradients.py @@ -1,4 +1,5 @@ -"""Collection of MXNet gradient functions, wrapped to fit Ivy syntax and signature.""" +"""Collection of MXNet gradient functions, wrapped to fit Ivy syntax and +signature.""" # global from typing import Sequence, Union diff --git a/ivy/functional/backends/mxnet/layers.py b/ivy/functional/backends/mxnet/layers.py index a30c494799fbd..2450a2555131b 100644 --- a/ivy/functional/backends/mxnet/layers.py +++ b/ivy/functional/backends/mxnet/layers.py @@ -1,4 +1,5 @@ -"""Collection of MXNet network layers, wrapped to fit Ivy syntax and signature.""" +"""Collection of MXNet network layers, wrapped to fit Ivy syntax and +signature.""" # global import mxnet as mx @@ -31,6 +32,7 @@ def conv1d_transpose( /, *, output_shape: Optional[Union[(ivy.NativeShape, Sequence[int])]] = None, + filter_format: str = "channel_last", data_format: str = "NWC", dilations: Union[(int, Tuple[int])] = 1, out: Optional[Union[(None, mx.ndarray.NDArray)]] = None, @@ -60,6 +62,7 @@ def conv2d_transpose( /, *, output_shape: Optional[Union[(ivy.NativeShape, Sequence[int])]] = None, + filter_format: str = "channel_last", data_format: str = "NHWC", dilations: Union[(int, Tuple[(int, int)])] = 1, out: Optional[Union[(None, mx.ndarray.NDArray)]] = None, @@ -103,6 +106,7 @@ def conv3d_transpose( /, *, output_shape: Optional[Union[(ivy.NativeShape, Sequence[int])]] = None, + filter_format: str = "channel_last", data_format: str = "NDHWC", dilations: Union[(int, Tuple[(int, int, int)])] = 1, out: Optional[Union[(None, mx.ndarray.NDArray)]] = None, @@ -138,6 +142,7 @@ def conv_general_transpose( /, *, dims: int = 2, + filter_format: str = "channel_last", data_format: str = "channel_last", output_shape: Optional[Union[(ivy.NativeShape, Sequence[int])]] = None, dilations: Union[(int, Tuple[int], Tuple[(int, int)], Tuple[(int, int, int)])] = 1, diff --git a/ivy/functional/backends/mxnet/manipulation.py b/ivy/functional/backends/mxnet/manipulation.py index feb262db2a152..7c07a7435c9cb 100644 --- a/ivy/functional/backends/mxnet/manipulation.py +++ b/ivy/functional/backends/mxnet/manipulation.py @@ -111,7 +111,7 @@ def repeat( /, repeats: Union[(int, List[int])], *, - axis: int = None, + axis: Optional[int] = None, out: Optional[Union[(None, mx.ndarray.NDArray)]] = None, ) -> Union[(None, mx.ndarray.NDArray)]: raise IvyNotImplementedException() diff --git a/ivy/functional/backends/mxnet/module.py b/ivy/functional/backends/mxnet/module.py new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/ivy/functional/backends/mxnet/random.py b/ivy/functional/backends/mxnet/random.py index 875fc1ce304cb..033a6b26cce5d 100644 --- a/ivy/functional/backends/mxnet/random.py +++ b/ivy/functional/backends/mxnet/random.py @@ -1,5 +1,4 @@ -""" -MXNet random functions. +"""MXNet random functions. Collection of MXNet random functions, wrapped to fit Ivy syntax and signature. diff --git a/ivy/functional/backends/numpy/__init__.py b/ivy/functional/backends/numpy/__init__.py index 8752de1a73117..d343709a92a00 100644 --- a/ivy/functional/backends/numpy/__init__.py +++ b/ivy/functional/backends/numpy/__init__.py @@ -16,36 +16,6 @@ use = ivy.utils.backend.ContextManager(_module_in_memory) -# wrap __array_ufunc__ method of ivy.Array to prioritize Ivy array methods when using numpu backend - - -def wrap__array_ufunc__(func): - def rep_method(self, ufunc, method, *inputs, **kwargs): - methods = { - "not_equal": "not_equal", - "greater": "greater", - "less": "less", - "greater_equal": "greater_equal", - "less_equal": "less_equal", - "multiply": "multiply", - "divide": "divide", - "remainder": "remainder", - "equal": "equal", - "bitwise_and": "bitwise_and", - "matmul": "matmul", - "power": "pow", - "subtract": "subtract", - "add": "add", - } - if ufunc.__name__ in methods.keys(): - return eval("ivy." + methods[ufunc.__name__] + "(*inputs, **kwargs)") - return func(self, ufunc, method, *inputs, **kwargs) - - return rep_method - - -ivy.Array.__array_ufunc__ = wrap__array_ufunc__(ivy.Array.__array_ufunc__) - NativeArray = np.ndarray NativeDevice = str NativeDtype = np.dtype @@ -81,7 +51,7 @@ def rep_method(self, ufunc, method, *inputs, **kwargs): # update these to add new dtypes valid_dtypes = { - "1.26.1 and below": ( + "1.26.3 and below": ( ivy.int8, ivy.int16, ivy.int32, @@ -99,7 +69,7 @@ def rep_method(self, ufunc, method, *inputs, **kwargs): ) } valid_numeric_dtypes = { - "1.26.1 and below": ( + "1.26.3 and below": ( ivy.int8, ivy.int16, ivy.int32, @@ -116,7 +86,7 @@ def rep_method(self, ufunc, method, *inputs, **kwargs): ) } valid_int_dtypes = { - "1.26.1 and below": ( + "1.26.3 and below": ( ivy.int8, ivy.int16, ivy.int32, @@ -127,11 +97,11 @@ def rep_method(self, ufunc, method, *inputs, **kwargs): ivy.uint64, ) } -valid_float_dtypes = {"1.26.1 and below": (ivy.float16, ivy.float32, ivy.float64)} +valid_float_dtypes = {"1.26.3 and below": (ivy.float16, ivy.float32, ivy.float64)} valid_uint_dtypes = { - "1.26.1 and below": (ivy.uint8, ivy.uint16, ivy.uint32, ivy.uint64) + "1.26.3 and below": (ivy.uint8, ivy.uint16, ivy.uint32, ivy.uint64) } -valid_complex_dtypes = {"1.26.1 and below": (ivy.complex64, ivy.complex128)} +valid_complex_dtypes = {"1.26.3 and below": (ivy.complex64, ivy.complex128)} # leave these untouched valid_dtypes = _dtype_from_version(valid_dtypes, backend_version) @@ -143,12 +113,12 @@ def rep_method(self, ufunc, method, *inputs, **kwargs): # invalid data types # update these to add new dtypes -invalid_dtypes = {"1.26.1 and below": (ivy.bfloat16,)} -invalid_numeric_dtypes = {"1.26.1 and below": (ivy.bfloat16,)} -invalid_int_dtypes = {"1.26.1 and below": ()} -invalid_float_dtypes = {"1.26.1 and below": (ivy.bfloat16,)} -invalid_uint_dtypes = {"1.26.1 and below": ()} -invalid_complex_dtypes = {"1.26.1 and below": ()} +invalid_dtypes = {"1.26.3 and below": (ivy.bfloat16,)} +invalid_numeric_dtypes = {"1.26.3 and below": (ivy.bfloat16,)} +invalid_int_dtypes = {"1.26.3 and below": ()} +invalid_float_dtypes = {"1.26.3 and below": (ivy.bfloat16,)} +invalid_uint_dtypes = {"1.26.3 and below": ()} +invalid_complex_dtypes = {"1.26.3 and below": ()} # leave these untouched @@ -213,9 +183,14 @@ def closest_valid_dtype(type=None, /, as_native=False): from .experimental import * from . import control_flow_ops from .control_flow_ops import * +from . import module +from .module import * # sub-backends from . import sub_backends from .sub_backends import * + + +NativeModule = None diff --git a/ivy/functional/backends/numpy/activations.py b/ivy/functional/backends/numpy/activations.py index cb9f698df3d39..7f396edb7da5d 100644 --- a/ivy/functional/backends/numpy/activations.py +++ b/ivy/functional/backends/numpy/activations.py @@ -1,4 +1,5 @@ -"""Collection of Numpy activation functions, wrapped to fit Ivy syntax and signature.""" +"""Collection of Numpy activation functions, wrapped to fit Ivy syntax and +signature.""" # global from typing import Optional, Union, Literal @@ -7,8 +8,20 @@ # local import ivy from ivy.functional.backends.numpy.helpers import _scalar_output_to_0d_array +from ivy.func_wrapper import with_supported_dtypes +from . import backend_version +@with_supported_dtypes( + { + "1.26.3 and below": ( + "float", + "int", + "complex", + ) + }, + backend_version, +) @_scalar_output_to_0d_array def relu( x: np.ndarray, /, *, complex_mode="jax", out: Optional[np.ndarray] = None diff --git a/ivy/functional/backends/numpy/control_flow_ops.py b/ivy/functional/backends/numpy/control_flow_ops.py index 0a80ff33a461e..97d3b91dcc53e 100644 --- a/ivy/functional/backends/numpy/control_flow_ops.py +++ b/ivy/functional/backends/numpy/control_flow_ops.py @@ -14,7 +14,9 @@ def cond(*_): def while_loop(test_fn, body_fn, vars): - result = list(vars.values()) + result = vars + if isinstance(vars, dict): + result = list(vars.values()) while test_fn(*result): result = body_fn(*result) if not isinstance(result, tuple): diff --git a/ivy/functional/backends/numpy/creation.py b/ivy/functional/backends/numpy/creation.py index 1e7ad6d3aaa0d..8c238118f24ad 100644 --- a/ivy/functional/backends/numpy/creation.py +++ b/ivy/functional/backends/numpy/creation.py @@ -6,7 +6,6 @@ # local import ivy -from ivy.functional.backends.numpy.device import _to_device from ivy.functional.ivy.creation import ( _asarray_to_native_arrays_and_back, _asarray_infer_device, @@ -30,12 +29,12 @@ def arange( step: float = 1, *, dtype: Optional[np.dtype] = None, - device: str = None, + device: Optional[str] = None, out: Optional[np.ndarray] = None, ) -> np.ndarray: if dtype: dtype = as_native_dtype(dtype) - res = _to_device(np.arange(start, stop, step, dtype=dtype), device=device) + res = np.arange(start, stop, step, dtype=dtype) if not dtype: if res.dtype == np.float64: return res.astype(np.float32) @@ -57,10 +56,10 @@ def asarray( *, copy: Optional[bool] = None, dtype: Optional[np.dtype] = None, - device: str = None, + device: Optional[str] = None, out: Optional[np.ndarray] = None, ) -> np.ndarray: - ret = _to_device(np.asarray(obj, dtype=dtype), device=device) + ret = np.asarray(obj, dtype=dtype) return np.copy(ret) if copy else ret @@ -68,10 +67,10 @@ def empty( shape: Union[ivy.NativeShape, Sequence[int]], *, dtype: np.dtype, - device: str = None, + device: Optional[str] = None, out: Optional[np.ndarray] = None, ) -> np.ndarray: - return _to_device(np.empty(shape, dtype), device=device) + return np.empty(shape, dtype) def empty_like( @@ -79,10 +78,10 @@ def empty_like( /, *, dtype: np.dtype, - device: str = None, + device: Optional[str] = None, out: Optional[np.ndarray] = None, ) -> np.ndarray: - return _to_device(np.empty_like(x, dtype=dtype), device=device) + return np.empty_like(x, dtype=dtype) def eye( @@ -93,27 +92,39 @@ def eye( k: int = 0, batch_shape: Optional[Union[int, Sequence[int]]] = None, dtype: np.dtype, - device: str = None, + device: Optional[str] = None, out: Optional[np.ndarray] = None, ) -> np.ndarray: if n_cols is None: n_cols = n_rows i = np.eye(n_rows, n_cols, k, dtype) if batch_shape is None: - return _to_device(i, device=device) + return i else: reshape_dims = [1] * len(batch_shape) + [n_rows, n_cols] tile_dims = list(batch_shape) + [1, 1] return_mat = np.tile(np.reshape(i, reshape_dims), tile_dims) - return _to_device(return_mat, device=device) + return return_mat def to_dlpack(x, /, *, out: Optional[np.ndarray] = None): return x.__dlpack__() +class _dlpack_wrapper: + def __init__(self, capsule) -> None: + self.capsule = capsule + + def dlpack(self): + return self.capsule + + def from_dlpack(x, /, *, out: Optional[np.ndarray] = None): - return np.from_dlpack(x) + if not hasattr(x, "__dlpack__"): + capsule = _dlpack_wrapper(x) + else: + capsule = x + return np.from_dlpack(capsule) def full( @@ -121,14 +132,11 @@ def full( fill_value: Union[int, float, bool], *, dtype: Optional[Union[ivy.Dtype, np.dtype]] = None, - device: str = None, + device: Optional[str] = None, out: Optional[np.ndarray] = None, ) -> np.ndarray: dtype = ivy.default_dtype(dtype=dtype, item=fill_value, as_native=True) - return _to_device( - np.full(shape, fill_value, dtype), - device=device, - ) + return np.full(shape, fill_value, dtype) def full_like( @@ -137,10 +145,10 @@ def full_like( fill_value: Number, *, dtype: np.dtype, - device: str = None, + device: Optional[str] = None, out: Optional[np.ndarray] = None, ) -> np.ndarray: - return _to_device(np.full_like(x, fill_value, dtype=dtype), device=device) + return np.full_like(x, fill_value, dtype=dtype) def linspace( @@ -152,7 +160,7 @@ def linspace( axis: Optional[int] = None, endpoint: bool = True, dtype: np.dtype, - device: str = None, + device: Optional[str] = None, out: Optional[np.ndarray] = None, ) -> np.ndarray: if axis is None: @@ -165,7 +173,7 @@ def linspace( and (not isinstance(stop, np.ndarray)) ): ans[0] = start - return _to_device(ans, device=device) + return ans def meshgrid( @@ -181,10 +189,10 @@ def ones( shape: Union[ivy.NativeShape, Sequence[int]], *, dtype: np.dtype, - device: str = None, + device: Optional[str] = None, out: Optional[np.ndarray] = None, ) -> np.ndarray: - return _to_device(np.ones(shape, dtype), device=device) + return np.ones(shape, dtype) def ones_like( @@ -192,10 +200,10 @@ def ones_like( /, *, dtype: np.dtype, - device: str = None, + device: Optional[str] = None, out: Optional[np.ndarray] = None, ) -> np.ndarray: - return _to_device(np.ones_like(x, dtype=dtype), device=device) + return np.ones_like(x, dtype=dtype) def tril( @@ -214,10 +222,10 @@ def zeros( shape: Union[ivy.NativeShape, Sequence[int]], *, dtype: np.dtype, - device: str = None, + device: Optional[str] = None, out: Optional[np.ndarray] = None, ) -> np.ndarray: - return _to_device(np.zeros(shape, dtype), device=device) + return np.zeros(shape, dtype) def zeros_like( @@ -225,10 +233,10 @@ def zeros_like( /, *, dtype: np.dtype, - device: str = None, + device: Optional[str] = None, out: Optional[np.ndarray] = None, ) -> np.ndarray: - return _to_device(np.zeros_like(x, dtype=dtype), device=device) + return np.zeros_like(x, dtype=dtype) # Extra # @@ -258,7 +266,7 @@ def one_hot( off_value: Optional[Number] = None, axis: Optional[int] = None, dtype: Optional[np.dtype] = None, - device: str = None, + device: Optional[str] = None, out: Optional[np.ndarray] = None, ) -> np.ndarray: on_none = on_value is None @@ -302,8 +310,6 @@ def triu_indices( k: int = 0, /, *, - device: str = None, + device: Optional[str] = None, ) -> Tuple[np.ndarray]: - return tuple( - _to_device(np.asarray(np.triu_indices(n=n_rows, k=k, m=n_cols)), device=device) - ) + return tuple(np.asarray(np.triu_indices(n=n_rows, k=k, m=n_cols))) diff --git a/ivy/functional/backends/numpy/data_type.py b/ivy/functional/backends/numpy/data_type.py index 4246f695a2493..342eed678a793 100644 --- a/ivy/functional/backends/numpy/data_type.py +++ b/ivy/functional/backends/numpy/data_type.py @@ -130,10 +130,10 @@ def broadcast_arrays(*arrays: np.ndarray) -> List[np.ndarray]: try: return np.broadcast_arrays(*arrays) except ValueError as e: - raise ivy.utils.exceptions.IvyBroadcastShapeError(e) + raise ivy.utils.exceptions.IvyBroadcastShapeError(e) from e -@with_unsupported_dtypes({"1.26.1 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("complex",)}, backend_version) def broadcast_to( x: np.ndarray, /, @@ -216,7 +216,7 @@ def as_ivy_dtype( ) -@with_unsupported_dtypes({"1.26.1 and below": ("bfloat16",)}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("bfloat16",)}, backend_version) def as_native_dtype(dtype_in: Union[np.dtype, str, bool, int, float], /) -> np.dtype: if dtype_in is int: return ivy.default_int_dtype(as_native=True) @@ -260,7 +260,4 @@ def dtype_bits(dtype_in: Union[np.dtype, str], /) -> int: def is_native_dtype(dtype_in: Union[np.dtype, str], /) -> bool: if not ivy.is_hashable_dtype(dtype_in): return False - if dtype_in in ivy_dtype_dict: - return True - else: - return False + return dtype_in in ivy_dtype_dict diff --git a/ivy/functional/backends/numpy/device.py b/ivy/functional/backends/numpy/device.py index 54eb13e61dc46..b173e50154f92 100644 --- a/ivy/functional/backends/numpy/device.py +++ b/ivy/functional/backends/numpy/device.py @@ -1,8 +1,10 @@ -"""Collection of Numpy general functions, wrapped to fit Ivy syntax and signature.""" +"""Collection of Numpy general functions, wrapped to fit Ivy syntax and +signature.""" # global import os import time +import logging import numpy as np from typing import Union, Optional, Any @@ -18,10 +20,18 @@ def dev(x: np.ndarray, /, *, as_native: bool = False) -> Union[ivy.Device, str]: def as_ivy_dev(device: str, /): + if "gpu" in device: + logging.warning( + "Native Numpy does not support GPU placement, consider using Jax instead" + ) return ivy.Device("cpu") def as_native_dev(device: str, /): + if "gpu" in device: + logging.warning( + "Native Numpy does not support GPU placement, consider using Jax instead" + ) return "cpu" @@ -41,25 +51,6 @@ def gpu_is_available() -> bool: return False -# private version of to_device to be used in backend implementations -def _to_device(x: np.ndarray, device=None) -> np.ndarray: - """Private version of `to_device` to be used in backend implementations.""" - if device is not None: - if "gpu" in device: - raise ivy.utils.exceptions.IvyException( - "Native Numpy does not support GPU placement, " - "consider using Jax instead" - ) - elif "cpu" in device: - pass - else: - raise ivy.utils.exceptions.IvyException( - "Invalid device specified, must be in the form [ 'cpu:idx' | 'gpu:idx'" - f" ], but found {device}" - ) - return x - - def to_device( x: np.ndarray, device: str, @@ -70,18 +61,6 @@ def to_device( ) -> np.ndarray: if device is not None: device = as_native_dev(device) - if "gpu" in device: - raise ivy.utils.exceptions.IvyException( - "Native Numpy does not support GPU placement, " - "consider using Jax instead" - ) - elif "cpu" in device: - pass - else: - raise ivy.utils.exceptions.IvyException( - "Invalid device specified, must be in the form [ 'cpu:idx' | 'gpu:idx'" - f" ], but found {device}" - ) return x diff --git a/ivy/functional/backends/numpy/elementwise.py b/ivy/functional/backends/numpy/elementwise.py index 9a6dfde82b98a..5275c963ffebf 100644 --- a/ivy/functional/backends/numpy/elementwise.py +++ b/ivy/functional/backends/numpy/elementwise.py @@ -83,7 +83,7 @@ def atan(x: np.ndarray, /, *, out: Optional[np.ndarray] = None) -> np.ndarray: @_scalar_output_to_0d_array -@with_unsupported_dtypes({"1.26.1 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("complex",)}, backend_version) def atan2( x1: np.ndarray, x2: np.ndarray, /, *, out: Optional[np.ndarray] = None ) -> np.ndarray: @@ -103,7 +103,7 @@ def atanh(x: np.ndarray, /, *, out: Optional[np.ndarray] = None) -> np.ndarray: @_scalar_output_to_0d_array -@with_unsupported_dtypes({"1.26.1 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("complex",)}, backend_version) def bitwise_and( x1: Union[int, bool, np.ndarray], x2: Union[int, bool, np.ndarray], @@ -119,7 +119,7 @@ def bitwise_and( @_scalar_output_to_0d_array -@with_unsupported_dtypes({"1.26.1 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("complex",)}, backend_version) def bitwise_invert( x: Union[int, bool, np.ndarray], /, *, out: Optional[np.ndarray] = None ) -> np.ndarray: @@ -130,7 +130,7 @@ def bitwise_invert( @_scalar_output_to_0d_array -@with_unsupported_dtypes({"1.26.1 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("complex",)}, backend_version) def bitwise_left_shift( x1: Union[int, bool, np.ndarray], x2: Union[int, bool, np.ndarray], @@ -146,7 +146,7 @@ def bitwise_left_shift( @_scalar_output_to_0d_array -@with_unsupported_dtypes({"1.26.1 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("complex",)}, backend_version) def bitwise_or( x1: Union[int, bool, np.ndarray], x2: Union[int, bool, np.ndarray], @@ -162,7 +162,7 @@ def bitwise_or( @_scalar_output_to_0d_array -@with_unsupported_dtypes({"1.26.1 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("complex",)}, backend_version) def bitwise_right_shift( x1: Union[int, bool, np.ndarray], x2: Union[int, bool, np.ndarray], @@ -178,7 +178,7 @@ def bitwise_right_shift( @_scalar_output_to_0d_array -@with_unsupported_dtypes({"1.26.1 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("complex",)}, backend_version) def bitwise_xor( x1: Union[int, bool, np.ndarray], x2: Union[int, bool, np.ndarray], @@ -193,7 +193,7 @@ def bitwise_xor( bitwise_xor.support_native_out = True -@with_unsupported_dtypes({"1.26.1 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("complex",)}, backend_version) @_scalar_output_to_0d_array def ceil(x: np.ndarray, /, *, out: Optional[np.ndarray] = None) -> np.ndarray: if "int" in str(x.dtype): @@ -216,7 +216,7 @@ def cos(x: np.ndarray, /, *, out: Optional[np.ndarray] = None) -> np.ndarray: cos.support_native_out = True -@with_unsupported_dtypes({"1.26.1 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("float16",)}, backend_version) @_scalar_output_to_0d_array def cosh(x: np.ndarray, /, *, out: Optional[np.ndarray] = None) -> np.ndarray: return np.cosh(x, out=out) @@ -289,7 +289,7 @@ def expm1(x: np.ndarray, /, *, out: Optional[np.ndarray] = None) -> np.ndarray: @_scalar_output_to_0d_array -@with_unsupported_dtypes({"1.26.1 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("complex",)}, backend_version) def floor(x: np.ndarray, /, *, out: Optional[np.ndarray] = None) -> np.ndarray: if "int" in str(x.dtype): ret = np.copy(x) @@ -304,7 +304,7 @@ def floor(x: np.ndarray, /, *, out: Optional[np.ndarray] = None) -> np.ndarray: @_scalar_output_to_0d_array -@with_unsupported_dtypes({"1.26.1 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("complex",)}, backend_version) def floor_divide( x1: Union[float, np.ndarray], x2: Union[float, np.ndarray], @@ -378,6 +378,7 @@ def isfinite(x: np.ndarray, /, *, out: Optional[np.ndarray] = None) -> np.ndarra isfinite.support_native_out = True +@with_unsupported_dtypes({"1.26.3 and below": ("complex",)}, backend_version) @_scalar_output_to_0d_array def isinf( x: np.ndarray, @@ -486,7 +487,7 @@ def log2(x: np.ndarray, /, *, out: Optional[np.ndarray] = None) -> np.ndarray: @_scalar_output_to_0d_array -@with_unsupported_dtypes({"1.26.1 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("complex",)}, backend_version) def logaddexp( x1: np.ndarray, x2: np.ndarray, /, *, out: Optional[np.ndarray] = None ) -> np.ndarray: @@ -623,7 +624,7 @@ def pow( @_scalar_output_to_0d_array -@with_unsupported_dtypes({"1.26.1 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("complex",)}, backend_version) def remainder( x1: Union[float, np.ndarray], x2: Union[float, np.ndarray], @@ -865,7 +866,7 @@ def reciprocal( @_scalar_output_to_0d_array -@with_unsupported_dtypes({"1.26.1 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("complex",)}, backend_version) def deg2rad(x: np.ndarray, /, *, out: Optional[np.ndarray] = None) -> np.ndarray: return np.deg2rad(x, out=out) @@ -874,7 +875,7 @@ def deg2rad(x: np.ndarray, /, *, out: Optional[np.ndarray] = None) -> np.ndarray @_scalar_output_to_0d_array -@with_unsupported_dtypes({"1.26.1 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("complex",)}, backend_version) def rad2deg(x: np.ndarray, /, *, out: Optional[np.ndarray] = None) -> np.ndarray: return np.rad2deg(x, out=out) @@ -891,7 +892,7 @@ def isreal(x: np.ndarray, /, *, out: Optional[np.ndarray] = None) -> np.ndarray: @_scalar_output_to_0d_array -@with_unsupported_dtypes({"1.26.1 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("complex",)}, backend_version) def fmod( x1: np.ndarray, x2: np.ndarray, diff --git a/ivy/functional/backends/numpy/experimental/activations.py b/ivy/functional/backends/numpy/experimental/activations.py index b84c15cb7a062..3acf91898788c 100644 --- a/ivy/functional/backends/numpy/experimental/activations.py +++ b/ivy/functional/backends/numpy/experimental/activations.py @@ -55,7 +55,7 @@ def relu6( relu6.support_native_out = True -@with_unsupported_dtypes({"1.26.1 and below": ("bool",)}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("bool",)}, backend_version) @_scalar_output_to_0d_array def logsigmoid( input: np.ndarray, /, *, complex_mode="jax", out: Optional[np.ndarray] = None @@ -148,6 +148,24 @@ def tanhshrink(x: np.ndarray, /, *, out: Optional[np.ndarray] = None) -> np.ndar tanhshrink.support_native_out = True +@_scalar_output_to_0d_array +def threshold( + x: np.ndarray, + /, + *, + threshold: float, + value: float, + out: Optional[np.ndarray] = None, +) -> np.ndarray: + ret = np.where(x > threshold, x, value) + if ivy.exists(out): + return ivy.inplace_update(out, ret).astype(x.dtype) + return ivy.astype(ret, x.dtype) + + +threshold.support_native_out = True + + @_scalar_output_to_0d_array def softshrink( x: np.ndarray, /, *, lambd: float = 0.5, out: Optional[np.ndarray] = None @@ -184,3 +202,15 @@ def hardshrink( hardshrink.support_native_out = True + + +@with_unsupported_dtypes({"2.14.0 and below": ("complex",)}, backend_version) +@_scalar_output_to_0d_array +def hardsilu(x: np.ndarray, /, *, out: Optional[np.ndarray] = None) -> np.ndarray: + ret = x * np.divide(relu6(x + 3), 6) + if ivy.exists(out): + return ivy.inplace_update(out, ret).astype(x.dtype) + return ivy.astype(ret, x.dtype) + + +hardsilu.support_native_out = True diff --git a/ivy/functional/backends/numpy/experimental/creation.py b/ivy/functional/backends/numpy/experimental/creation.py index 1a8d604ef6d94..8add9faa6c67e 100644 --- a/ivy/functional/backends/numpy/experimental/creation.py +++ b/ivy/functional/backends/numpy/experimental/creation.py @@ -4,7 +4,6 @@ import numpy as np # local -from ivy.functional.backends.numpy.device import _to_device import ivy # Array API Standard # @@ -33,11 +32,9 @@ def tril_indices( k: int = 0, /, *, - device: str = None, + device: Optional[str] = None, ) -> Tuple[np.ndarray, ...]: - return tuple( - _to_device(np.asarray(np.tril_indices(n=n_rows, k=k, m=n_cols)), device=device) - ) + return tuple(np.asarray(np.tril_indices(n=n_rows, k=k, m=n_cols))) def hann_window( @@ -92,7 +89,7 @@ def unsorted_segment_min( segment_ids: np.ndarray, num_segments: int, ) -> np.ndarray: - ivy.utils.assertions.check_unsorted_segment_min_valid_params( + ivy.utils.assertions.check_unsorted_segment_valid_params( data, segment_ids, num_segments ) @@ -101,7 +98,7 @@ def unsorted_segment_min( elif data.dtype in [np.int32, np.int64, np.int8, np.int16, np.uint8]: init_val = np.iinfo(data.dtype).max else: - raise ValueError("Unsupported data type") + raise TypeError("Unsupported data type") res = np.full((num_segments,) + data.shape[1:], init_val, dtype=data.dtype) @@ -146,7 +143,7 @@ def unsorted_segment_sum( # check should be same # Might require to change the assertion function name to # check_unsorted_segment_valid_params - ivy.utils.assertions.check_unsorted_segment_min_valid_params( + ivy.utils.assertions.check_unsorted_segment_valid_params( data, segment_ids, num_segments ) @@ -197,15 +194,43 @@ def hz_to_mel(f): dtype=np.float32, ) mel_edges = np.stack([mel_edges[i : i + 3] for i in range(num_mel_bins)]) - lower_edge_mel, center_mel, upper_edge_mel = [ + lower_edge_mel, center_mel, upper_edge_mel = ( t.reshape((1, num_mel_bins)) for t in np.split(mel_edges, 3, axis=1) - ] + ) lower_slopes = (spec_bin_mels - lower_edge_mel) / (center_mel - lower_edge_mel) upper_slopes = (upper_edge_mel - spec_bin_mels) / (upper_edge_mel - center_mel) mel_weights = np.maximum(zero, np.minimum(lower_slopes, upper_slopes)) return np.pad(mel_weights, [[1, 0], [0, 0]]) +def unsorted_segment_mean( + data: np.ndarray, + segment_ids: np.ndarray, + num_segments: int, +) -> np.ndarray: + ivy.utils.assertions.check_unsorted_segment_valid_params( + data, segment_ids, num_segments + ) + + if len(segment_ids) == 0: + # If segment_ids is empty, return an empty array of the correct shape + return np.zeros((num_segments,) + data.shape[1:], dtype=data.dtype) + + # Initialize an array to store the sum of elements for each segment + res = np.zeros((num_segments,) + data.shape[1:], dtype=data.dtype) + + # Initialize an array to keep track of the number of elements in each segment + counts = np.zeros(num_segments, dtype=np.int64) + + for i in range(len(segment_ids)): + seg_id = segment_ids[i] + if seg_id < num_segments: + res[seg_id] += data[i] + counts[seg_id] += 1 + + return res / counts[:, np.newaxis] + + def polyval(coeffs: np.ndarray, x: np.ndarray) -> np.ndarray: with ivy.PreciseMode(True): promoted_type = ivy.promote_types(ivy.dtype(coeffs[0]), ivy.dtype(x[0])) diff --git a/ivy/functional/backends/numpy/experimental/elementwise.py b/ivy/functional/backends/numpy/experimental/elementwise.py index 35022ad6b77b2..821c287a722b5 100644 --- a/ivy/functional/backends/numpy/experimental/elementwise.py +++ b/ivy/functional/backends/numpy/experimental/elementwise.py @@ -42,7 +42,7 @@ def amin( @_scalar_output_to_0d_array -@with_unsupported_dtypes({"1.26.1 and below": ("bfloat16",)}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("bfloat16",)}, backend_version) def sinc(x: np.ndarray, /, *, out: Optional[np.ndarray] = None) -> np.ndarray: return np.sinc(x).astype(x.dtype) @@ -438,7 +438,8 @@ def digamma( def sinpi(x): y = np.abs(x) % 2.0 n = np.round(2.0 * y) - assert 0 <= n and n <= 4 + assert n >= 0 + assert n <= 4 if n == 0: r = np.sin(np.pi * y) @@ -584,7 +585,7 @@ def erfc( out: Optional[np.ndarray] = None, ) -> np.ndarray: if x.dtype not in [np.float16, np.float32, np.float64]: - raise ValueError("Input must be of type float16, float32, or float64.") + raise TypeError("Input must be of type float16, float32, or float64.") input_dtype = x.dtype @@ -615,3 +616,15 @@ def is_pos_inf(op): return np.where(underflow, result_underflow, result_no_underflow).astype( input_dtype ) + + +# TODO: Remove this once native function is available. +# Compute an approximation of the error function complement (1 - erf(x)). +def erfinv( + x: np.ndarray, + /, + *, + out: Optional[np.ndarray] = None, +) -> np.ndarray: + with ivy.ArrayMode(False): + return np.sqrt(2) * erfc(x) diff --git a/ivy/functional/backends/numpy/experimental/general.py b/ivy/functional/backends/numpy/experimental/general.py index 74fe96dd63423..acd4ba7321d4a 100644 --- a/ivy/functional/backends/numpy/experimental/general.py +++ b/ivy/functional/backends/numpy/experimental/general.py @@ -7,7 +7,7 @@ from ivy import with_unsupported_dtypes -@with_unsupported_dtypes({"1.26.1 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("complex",)}, backend_version) def reduce( operand: np.ndarray, init_value: Union[int, float], diff --git a/ivy/functional/backends/numpy/experimental/layers.py b/ivy/functional/backends/numpy/experimental/layers.py index e549c93fc53a6..8e8344a78d166 100644 --- a/ivy/functional/backends/numpy/experimental/layers.py +++ b/ivy/functional/backends/numpy/experimental/layers.py @@ -97,7 +97,7 @@ def max_pool1d( ) else: if isinstance(padding, list) and any( - [item != 0 for sublist in padding for item in sublist] + item != 0 for sublist in padding for item in sublist ): raise NotImplementedError( "Nonzero explicit padding is not supported for depthwise max pooling" @@ -203,7 +203,7 @@ def max_pool2d( ) else: if isinstance(padding, list) and any( - [item != 0 for sublist in padding for item in sublist] + item != 0 for sublist in padding for item in sublist ): raise NotImplementedError( "Nonzero explicit padding is not supported for depthwise max pooling" @@ -317,7 +317,7 @@ def max_pool3d( ) else: if isinstance(padding, list) and any( - [item != 0 for sublist in padding for item in sublist] + item != 0 for sublist in padding for item in sublist ): raise NotImplementedError( "Nonzero explicit padding is not supported for depthwise max pooling" @@ -369,6 +369,8 @@ def _get_padded_values(x_shape, kernel, strides, padding, ceil_mode, dim): for i in range(dim) ] else: + if isinstance(padding, int): + padding = [(padding,) * 2] * dim pad_specific = [sum(padding[i]) for i in range(dim)] c = [] @@ -386,12 +388,13 @@ def avg_pool1d( x: np.ndarray, kernel: Union[int, Tuple[int]], strides: Union[int, Tuple[int]], - padding: str, + padding: Union[str, int, List[Tuple[int, int]]], /, *, data_format: str = "NWC", count_include_pad: bool = False, ceil_mode: bool = False, + divisor_override: Optional[int] = None, out: Optional[np.ndarray] = None, ) -> np.ndarray: if isinstance(kernel, int): @@ -470,7 +473,7 @@ def avg_pool2d( x: np.ndarray, kernel: Union[int, Tuple[int], Tuple[int, int]], strides: Union[int, Tuple[int], Tuple[int, int]], - padding: str, + padding: Union[str, int, List[Tuple[int, int]]], /, *, data_format: str = "NHWC", @@ -577,7 +580,7 @@ def avg_pool3d( x: np.ndarray, kernel: Union[int, Tuple[int], Tuple[int, int, int]], strides: Union[int, Tuple[int], Tuple[int, int, int]], - padding: str, + padding: Union[str, int, List[Tuple[int, int]]], /, *, data_format: str = "NDHWC", @@ -717,7 +720,7 @@ def fft( raise ivy.utils.exceptions.IvyError( f"Invalid data points {n}, expecting more than 1" ) - if norm != "backward" and norm != "ortho" and norm != "forward": + if norm not in {"backward", "ortho", "forward"}: raise ivy.utils.exceptions.IvyError(f"Unrecognized normalization mode {norm}") if x.dtype in [np.uint64, np.int64, np.float64, np.complex128]: out_dtype = np.complex128 @@ -726,7 +729,7 @@ def fft( return np.fft.fft(x, n, dim, norm).astype(out_dtype) -@with_supported_dtypes({"1.26.1 and below": ("float32", "float64")}, backend_version) +@with_supported_dtypes({"1.26.3 and below": ("float32", "float64")}, backend_version) def dct( x: np.ndarray, /, @@ -940,7 +943,7 @@ def ifft( raise ivy.utils.exceptions.IvyError( f"Invalid data points {n}, expecting more than 1" ) - if norm != "backward" and norm != "ortho" and norm != "forward": + if norm not in {"backward", "ortho", "forward"}: raise ivy.utils.exceptions.IvyError(f"Unrecognized normalization mode {norm}") return np.asarray(np.fft.ifft(x, n, dim, norm), dtype=x.dtype) @@ -948,7 +951,7 @@ def ifft( def fft2( x: np.ndarray, *, - s: Sequence[int] = None, + s: Optional[Sequence[int]] = None, dim: Sequence[int] = (-2, -1), norm: str = "backward", out: Optional[np.ndarray] = None, @@ -991,7 +994,7 @@ def ifftn( return np.fft.ifftn(x, s, axes, norm).astype(x.dtype) -@with_unsupported_dtypes({"1.26.1 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("complex",)}, backend_version) def embedding( weights: np.ndarray, indices: np.ndarray, @@ -1038,8 +1041,8 @@ def rfft( def rfftn( x: np.ndarray, - s: Sequence[int] = None, - axes: Sequence[int] = None, + s: Optional[Sequence[int]] = None, + axes: Optional[Sequence[int]] = None, *, norm: str = "backward", out: Optional[np.ndarray] = None, @@ -1063,7 +1066,7 @@ def rfftn( raise ivy.utils.exceptions.IvyError( f"Invalid data points {s}, expecting s points larger than 1" ) - if norm != "backward" and norm != "ortho" and norm != "forward": + if norm not in {"backward", "ortho", "forward"}: raise ivy.utils.exceptions.IvyError(f"Unrecognized normalization mode {norm}") return np.fft.rfftn(x, s, axes, norm).astype(np.complex128) @@ -1157,7 +1160,7 @@ def stft_1D(signals, frame_length, frame_step, fft_length, pad_end): windowed_frame = np.array(windowed_frame, dtype=dtype) fft_frame = np.fft.fft(windowed_frame, axis=-1) - slit = int((fft_length // 2 + 1)) + slit = int(fft_length // 2 + 1) stft_result.append(fft_frame[..., 0:slit]) stft = np.stack(stft_result, axis=0) diff --git a/ivy/functional/backends/numpy/experimental/linear_algebra.py b/ivy/functional/backends/numpy/experimental/linear_algebra.py index 2f054e1cb586b..2224dcad492e1 100644 --- a/ivy/functional/backends/numpy/experimental/linear_algebra.py +++ b/ivy/functional/backends/numpy/experimental/linear_algebra.py @@ -90,7 +90,7 @@ def kron( @with_supported_dtypes( - {"1.26.1 and below": ("float32", "float64", "complex64", "complex128")}, + {"1.26.3 and below": ("float32", "float64", "complex64", "complex128")}, backend_version, ) def matrix_exp( @@ -106,7 +106,7 @@ def matrix_exp( return exp_mat.astype(x.dtype) -@with_unsupported_dtypes({"1.26.1 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("float16",)}, backend_version) def eig( x: np.ndarray, /, @@ -120,7 +120,7 @@ def eig( eig.support_native_out = False -@with_unsupported_dtypes({"1.26.1 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("float16",)}, backend_version) def eigvals(x: np.ndarray, /) -> np.ndarray: e = np.linalg.eigvals(x) return e.astype(complex) @@ -217,6 +217,17 @@ def lu_factor( raise IvyNotImplementedException() +def lu_solve( + lu: Tuple[np.ndarray], + p: np.ndarray, + b: np.ndarray, + /, + *, + out: Optional[np.ndarray] = None, +) -> np.ndarray: + raise IvyNotImplementedException() + + def dot( a: np.ndarray, b: np.ndarray, diff --git a/ivy/functional/backends/numpy/experimental/losses.py b/ivy/functional/backends/numpy/experimental/losses.py index 363916ca62353..359d69c4f30e0 100644 --- a/ivy/functional/backends/numpy/experimental/losses.py +++ b/ivy/functional/backends/numpy/experimental/losses.py @@ -1,5 +1,4 @@ import numpy as np -from typing import Optional from ivy.functional.backends.numpy.helpers import _scalar_output_to_0d_array from ivy.func_wrapper import ( with_unsupported_dtypes, @@ -8,15 +7,15 @@ from . import backend_version -@with_unsupported_dtypes({"1.26.1 and below": ("bool",)}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("bool",)}, backend_version) @_scalar_output_to_0d_array def huber_loss( input: np.ndarray, target: np.ndarray, /, *, - delta: Optional[float] = 1.0, - reduction: Optional[str] = "mean", + delta: float = 1.0, + reduction: str = "mean", ) -> np.ndarray: abs_diff = np.abs(input - target) quadratic_loss = 0.5 * (abs_diff**2) @@ -32,15 +31,15 @@ def huber_loss( # Implementation of smooth_l1_loss in the given format -@with_unsupported_dtypes({"1.26.1 and below": ("bool",)}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("bool",)}, backend_version) @_scalar_output_to_0d_array def smooth_l1_loss( input: np.ndarray, target: np.ndarray, /, *, - beta: Optional[float] = 1.0, - reduction: Optional[str] = "mean", + beta: float = 1.0, + reduction: str = "mean", ) -> np.ndarray: if beta < 1e-5: loss = np.abs(input - target) @@ -56,14 +55,14 @@ def smooth_l1_loss( return loss -@with_unsupported_dtypes({"1.26.1 and below": ("bool",)}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("bool",)}, backend_version) @_scalar_output_to_0d_array def soft_margin_loss( input: np.ndarray, target: np.ndarray, /, *, - reduction: Optional[str] = "mean", + reduction: str = "mean", ) -> np.ndarray: loss = np.sum(np.log1p(np.exp(-input * target))) / input.size @@ -75,15 +74,12 @@ def soft_margin_loss( return loss -def _apply_loss_reduction(loss: np.ndarray, reduction: str, axis, out) -> np.ndarray: +def _apply_loss_reduction(loss: np.ndarray, reduction: str) -> np.ndarray: if reduction == "sum": - return np.sum(loss, axis=axis, out=out) + return np.sum(loss) elif reduction == "mean": - return np.mean(loss, axis=axis, out=out) + return np.mean(loss) else: # reduction == "none" - if out is not None: - out[...] = loss - return out return loss @@ -97,30 +93,30 @@ def _validate_poisson_nll_params( # Validate dtypes for parameter, name in zip([input, label], ["input", "label"]): if parameter.dtype not in allowed_dtypes: - raise ValueError( - "The dtype of '%s' in poisson_nll_loss should be one of %s, but" - " received %s." % (name, allowed_dtypes, parameter.dtype) + raise TypeError( + f"The dtype of '{name}' in poisson_nll_loss should be one of" + f" {allowed_dtypes}, but received {parameter.dtype}." ) # Validate epsilon if epsilon <= 0: raise ValueError( "The value of `epsilon` in poisson_nll_loss should be positive, but" - " received %f, which is not allowed" % epsilon + f" received {epsilon}, which is not allowed." ) # Validate reduction if reduction not in ["sum", "mean", "none"]: raise ValueError( "The value of 'reduction' in poisson_nll_loss should be 'sum', 'mean' or" - " 'none', but received %s, which is not allowed." % reduction + f" 'none', but received {reduction}, which is not allowed." ) # Validate shape if input.shape != label.shape: raise ValueError( - "The shape of 'input' (%s) must be the same as the shape of 'label' (%s)." - % (input.shape, label.shape) + f"The shape of 'input' ({input.shape}) must be the same as the shape of" + f" 'label' ({label.shape})." ) return True @@ -128,7 +124,7 @@ def _validate_poisson_nll_params( @with_supported_device_and_dtypes( { - "1.25.2 and below": { + "1.26.0 and below": { "cpu": ("float16", "float32", "float64"), } }, @@ -167,3 +163,29 @@ def poisson_nll_loss( cond = np.logical_and(target_arr >= zeroes, target_arr <= ones) loss = loss + np.where(cond, zeroes, striling_approx_term) return _apply_loss_reduction(loss, reduction) + + +@with_supported_device_and_dtypes( + { + "1.26.0 and below": { + "cpu": ("float32", "float64"), + } + }, + backend_version, +) +def hinge_embedding_loss( + input: np.ndarray, + target: np.ndarray, + *, + margin: float = 1.0, + reduction: str = "mean", +) -> np.ndarray: + zero_ = np.zeros([1], dtype=input.dtype) + + relu_part = np.maximum(margin - input, 0) + + loss = np.where(target == 1.0, input, zero_) + np.where( + target == -1.0, relu_part, zero_ + ) + + return _apply_loss_reduction(loss, reduction) diff --git a/ivy/functional/backends/numpy/experimental/manipulation.py b/ivy/functional/backends/numpy/experimental/manipulation.py index cefc371fedb26..17b57a75f0f33 100644 --- a/ivy/functional/backends/numpy/experimental/manipulation.py +++ b/ivy/functional/backends/numpy/experimental/manipulation.py @@ -1,5 +1,6 @@ # global from typing import ( + Iterable, Optional, Union, Sequence, @@ -17,7 +18,7 @@ # local import ivy from ivy.functional.backends.numpy.helpers import _scalar_output_to_0d_array -from ivy.func_wrapper import with_supported_dtypes +from ivy.func_wrapper import with_supported_dtypes, handle_out_argument # noinspection PyProtectedMember from . import backend_version @@ -201,7 +202,7 @@ def _interior_pad(operand, padding_value, padding_config): def pad( input: np.ndarray, - pad_width: Union[Sequence[Sequence[int]], np.ndarray, int], + pad_width: Union[Iterable[Tuple[int]], int], /, *, mode: Union[ @@ -221,9 +222,9 @@ def pad( ], Callable, ] = "constant", - stat_length: Union[Sequence[Sequence[int]], int] = 1, - constant_values: Union[Sequence[Sequence[Number]], Number] = 0, - end_values: Union[Sequence[Sequence[Number]], Number] = 0, + stat_length: Union[Iterable[Tuple[int]], int] = 1, + constant_values: Union[Iterable[Tuple[Number]], Number] = 0, + end_values: Union[Iterable[Tuple[Number]], Number] = 0, reflect_type: Literal["even", "odd"] = "even", **kwargs: Optional[Any], ) -> np.ndarray: @@ -401,6 +402,9 @@ def expand( out: Optional[np.ndarray] = None, ) -> np.ndarray: shape = list(shape) + n_extra_dims = len(shape) - x.ndim + if n_extra_dims > 0: + x = np.expand_dims(x, tuple(range(n_extra_dims))) for i, dim in enumerate(shape): if dim < 0: shape[i] = x.shape[i] @@ -597,3 +601,19 @@ def put_along_axis( put_along_axis.partial_mixed_handler = lambda *args, mode=None, **kwargs: mode in [ "replace", ] + + +@handle_out_argument +def unflatten( + x: np.ndarray, + /, + shape: Tuple[int] = None, + dim: Optional[int] = 0, + *, + out: Optional[np.ndarray] = None, + order: Optional[str] = None, +) -> np.ndarray: + dim = abs(len(x.shape) + dim) if dim < 0 else dim + res_shape = x.shape[:dim] + shape + x.shape[dim + 1 :] + res = np.reshape(x, res_shape) + return res diff --git a/ivy/functional/backends/numpy/experimental/norms.py b/ivy/functional/backends/numpy/experimental/norms.py index 3d1b549283d13..54a7bfe5362f5 100644 --- a/ivy/functional/backends/numpy/experimental/norms.py +++ b/ivy/functional/backends/numpy/experimental/norms.py @@ -4,7 +4,7 @@ from . import backend_version -@with_unsupported_dtypes({"1.26.1 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("float16",)}, backend_version) def l1_normalize( x: np.ndarray, /, diff --git a/ivy/functional/backends/numpy/experimental/random.py b/ivy/functional/backends/numpy/experimental/random.py index 16293d4eac407..34960431a3210 100644 --- a/ivy/functional/backends/numpy/experimental/random.py +++ b/ivy/functional/backends/numpy/experimental/random.py @@ -99,6 +99,7 @@ def bernoulli( seed: Optional[int] = None, out: Optional[np.ndarray] = None, ) -> np.ndarray: + dtype = dtype if dtype is not None else probs.dtype if seed is not None: np.random.seed(seed) if logits is not None: diff --git a/ivy/functional/backends/numpy/experimental/searching.py b/ivy/functional/backends/numpy/experimental/searching.py index ce66a03b0b2b9..191e15681caf9 100644 --- a/ivy/functional/backends/numpy/experimental/searching.py +++ b/ivy/functional/backends/numpy/experimental/searching.py @@ -7,7 +7,7 @@ from . import backend_version -@with_supported_dtypes({"1.26.1 and below": ("int32", "int64")}, backend_version) +@with_supported_dtypes({"1.26.3 and below": ("int32", "int64")}, backend_version) def unravel_index( indices: np.ndarray, shape: Tuple[int], diff --git a/ivy/functional/backends/numpy/experimental/statistical.py b/ivy/functional/backends/numpy/experimental/statistical.py index fcbb77c0afb37..e2dffa696bc2a 100644 --- a/ivy/functional/backends/numpy/experimental/statistical.py +++ b/ivy/functional/backends/numpy/experimental/statistical.py @@ -9,7 +9,7 @@ @with_unsupported_dtypes( - {"1.26.1 and below": ("bfloat16",)}, + {"1.26.3 and below": ("bfloat16",)}, backend_version, ) def histogram( @@ -226,7 +226,7 @@ def _validate_quantile(q): if not (0.0 <= q[i] <= 1.0): return False else: - if not (np.all(0 <= q) and np.all(q <= 1)): + if not (np.all(q >= 0) and np.all(q <= 1)): return False return True @@ -534,7 +534,7 @@ def __get_index(lst, indices=None, prefix=None): return indices -@with_unsupported_dtypes({"1.26.1 and below": "bfloat16"}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": "bfloat16"}, backend_version) def cummin( x: np.ndarray, /, diff --git a/ivy/functional/backends/numpy/general.py b/ivy/functional/backends/numpy/general.py index d0b0e8ce8b3cd..e185ef08998c8 100644 --- a/ivy/functional/backends/numpy/general.py +++ b/ivy/functional/backends/numpy/general.py @@ -1,20 +1,23 @@ -"""Collection of Numpy general functions, wrapped to fit Ivy syntax and signature.""" +"""Collection of Numpy general functions, wrapped to fit Ivy syntax and +signature.""" -# global -from typing import Optional, Union, Sequence, Callable, Tuple -import numpy as np -from operator import mul -from functools import reduce as _reduce import multiprocessing as _multiprocessing +from functools import reduce as _reduce from numbers import Number +from operator import mul + +# global +from typing import Callable, Optional, Sequence, Tuple, Union + +import numpy as np # local import ivy -from ivy.functional.backends.numpy.device import _to_device -from ivy.functional.backends.numpy.helpers import _scalar_output_to_0d_array from ivy.func_wrapper import with_unsupported_dtypes -from . import backend_version +from ivy.functional.backends.numpy.helpers import _scalar_output_to_0d_array + from ...ivy.general import _broadcast_to +from . import backend_version def array_equal(x0: np.ndarray, x1: np.ndarray, /) -> bool: @@ -35,8 +38,10 @@ def get_item( /, query: Union[np.ndarray, Tuple], *, - copy: bool = None, + copy: Optional[bool] = None, ) -> np.ndarray: + if copy: + x = x.copy() return x.__getitem__(query) @@ -47,7 +52,7 @@ def set_item( val: np.ndarray, /, *, - copy: Optional[bool] = False, + copy: bool = False, ) -> np.ndarray: if copy: x = np.copy(x) @@ -101,7 +106,7 @@ def gather( result.append(r) result = np.array(result) result = result.reshape([*params.shape[0:batch_dims], *result.shape[1:]]) - return _to_device(result) + return result def gather_nd_helper(params, indices): @@ -162,13 +167,17 @@ def gather_nd( result.append(r) result = np.array(result) result = result.reshape([*params.shape[0:batch_dims], *result.shape[1:]]) - return _to_device(result) + return result def get_num_dims(x, /, *, as_array=False): return np.asarray(len(np.shape(x))) if as_array else len(x.shape) +def size(x, /) -> int: + return x.size + + def inplace_arrays_supported(): return True @@ -330,8 +339,8 @@ def scatter_nd( ' "mul" or "replace"' ) if ivy.exists(out): - return ivy.inplace_update(out, _to_device(target)) - return _to_device(target) + return ivy.inplace_update(out, target) + return target scatter_nd.support_native_out = True @@ -435,7 +444,7 @@ def _vmap(*args): return _vmap -@with_unsupported_dtypes({"1.26.1 and below": ("bfloat16",)}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("bfloat16",)}, backend_version) def isin( elements: np.ndarray, test_elements: np.ndarray, diff --git a/ivy/functional/backends/numpy/gradients.py b/ivy/functional/backends/numpy/gradients.py index 1f930d0ebe687..d6ba1e9b55bd7 100644 --- a/ivy/functional/backends/numpy/gradients.py +++ b/ivy/functional/backends/numpy/gradients.py @@ -1,4 +1,5 @@ -"""Collection of NumPy gradient functions, wrapped to fit Ivy syntax and signature.""" +"""Collection of NumPy gradient functions, wrapped to fit Ivy syntax and +signature.""" # global import logging diff --git a/ivy/functional/backends/numpy/helpers.py b/ivy/functional/backends/numpy/helpers.py index b5ae02d3a09f0..965bb5067baca 100644 --- a/ivy/functional/backends/numpy/helpers.py +++ b/ivy/functional/backends/numpy/helpers.py @@ -4,8 +4,7 @@ def _scalar_output_to_0d_array(function: Callable) -> Callable: - """ - Convert scalar outputs to 0d arrays. + """Convert scalar outputs to 0d arrays. Sometimes NumPy functions return scalars e.g. `np.add` does when the inputs are both 0 dimensional. diff --git a/ivy/functional/backends/numpy/layers.py b/ivy/functional/backends/numpy/layers.py index 52ad223304735..5fe2e909e5e76 100644 --- a/ivy/functional/backends/numpy/layers.py +++ b/ivy/functional/backends/numpy/layers.py @@ -1,4 +1,5 @@ -"""Collection of Numpy network layers, wrapped to fit Ivy syntax and signature.""" +"""Collection of Numpy network layers, wrapped to fit Ivy syntax and +signature.""" # global import numpy as np @@ -174,6 +175,7 @@ def conv1d_transpose( /, *, output_shape: Optional[Union[ivy.NativeShape, Sequence[int]]] = None, + filter_format: str = "channel_last", data_format: str = "NWC", dilations: Union[int, Tuple[int]] = 1, bias: Optional[np.ndarray] = None, @@ -181,6 +183,10 @@ def conv1d_transpose( ) -> np.ndarray: if data_format == "NCW": x = np.transpose(x, (0, 2, 1)) + if filter_format == "channel_last": + filters = np.transpose(filters, (0, 2, 1)) + else: + filters = np.transpose(filters, (2, 0, 1)) x, filters = _dilate_pad_conv_tranpose( x, filters, strides, padding, 1, dilations, output_shape ) @@ -259,6 +265,7 @@ def conv2d_transpose( /, *, output_shape: Optional[Union[ivy.NativeShape, Sequence[int]]] = None, + filter_format: str = "channel_last", data_format: str = "NHWC", dilations: Union[int, Tuple[int, int]] = 1, bias: Optional[np.ndarray] = None, @@ -266,6 +273,10 @@ def conv2d_transpose( ): if data_format == "NCHW": x = np.transpose(x, (0, 2, 3, 1)) + if filter_format == "channel_last": + filters = np.transpose(filters, (0, 1, 3, 2)) + else: + filters = np.transpose(filters, (2, 3, 0, 1)) x, filters = _dilate_pad_conv_tranpose( x, filters, strides, padding, 2, dilations, output_shape ) @@ -403,6 +414,7 @@ def conv3d_transpose( /, *, output_shape: Optional[Union[ivy.NativeShape, Sequence[int]]] = None, + filter_format: str = "channel_last", data_format: str = "NDHWC", dilations: Union[int, Tuple[int, int, int]] = 1, bias: Optional[np.ndarray] = None, @@ -410,6 +422,10 @@ def conv3d_transpose( ): if data_format == "NCDHW": x = np.transpose(x, (0, 2, 3, 4, 1)) + if filter_format == "channel_last": + filters = np.transpose(filters, (0, 1, 2, 4, 3)) + else: + filters = np.transpose(filters, (2, 3, 4, 0, 1)) x, filters = _dilate_pad_conv_tranpose( x, filters, strides, padding, 3, dilations, output_shape ) @@ -511,6 +527,7 @@ def conv_general_transpose( *, dims: int = 2, output_shape: Optional[Union[ivy.NativeShape, Sequence[int]]] = None, + filter_format: str = "channel_last", data_format: str = "channel_last", dilations: Union[int, Tuple[int], Tuple[int, int], Tuple[int, int, int]] = 1, feature_group_count: int = 1, @@ -519,6 +536,10 @@ def conv_general_transpose( ) -> np.ndarray: if data_format == "channel_first": x = np.transpose(x, (0, *range(2, dims + 2), 1)) + if filter_format == "channel_last": + filters = np.transpose(filters, (*range(dims), dims + 1, dims)) + else: + filters = np.transpose(filters, (*range(2, dims + 2), 0, 1)) x, filters = _dilate_pad_conv_tranpose( x, filters, strides, padding, dims, dilations, output_shape diff --git a/ivy/functional/backends/numpy/linear_algebra.py b/ivy/functional/backends/numpy/linear_algebra.py index 26257efbba19f..98b5096a7c33c 100644 --- a/ivy/functional/backends/numpy/linear_algebra.py +++ b/ivy/functional/backends/numpy/linear_algebra.py @@ -18,7 +18,7 @@ # -------------------# -@with_unsupported_dtypes({"1.26.1 and below": ("float16", "complex")}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("float16", "complex")}, backend_version) def cholesky( x: np.ndarray, /, *, upper: bool = False, out: Optional[np.ndarray] = None ) -> np.ndarray: @@ -30,7 +30,7 @@ def cholesky( return ret -@with_unsupported_dtypes({"1.26.1 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("float16",)}, backend_version) def cross( x1: np.ndarray, x2: np.ndarray, @@ -46,7 +46,7 @@ def cross( @_scalar_output_to_0d_array -@with_unsupported_dtypes({"1.26.1 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("float16",)}, backend_version) def det(x: np.ndarray, /, *, out: Optional[np.ndarray] = None) -> np.ndarray: return np.linalg.det(x) @@ -63,7 +63,7 @@ def diagonal( return np.diagonal(x, offset=offset, axis1=axis1, axis2=axis2) -@with_unsupported_dtypes({"1.26.1 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("float16",)}, backend_version) def eigh( x: np.ndarray, /, *, UPLO: str = "L", out: Optional[np.ndarray] = None ) -> Tuple[np.ndarray]: @@ -74,7 +74,7 @@ def eigh( return result_tuple(eigenvalues, eigenvectors) -@with_unsupported_dtypes({"1.26.1 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("float16",)}, backend_version) def eigvalsh( x: np.ndarray, /, *, UPLO: str = "L", out: Optional[np.ndarray] = None ) -> np.ndarray: @@ -90,7 +90,7 @@ def inner( @with_unsupported_dtypes( - {"1.26.1 and below": ("bfloat16", "float16", "complex")}, + {"1.26.3 and below": ("bfloat16", "float16", "complex")}, backend_version, ) def inv( @@ -110,7 +110,7 @@ def inv( return np.linalg.inv(x) -@with_unsupported_dtypes({"1.26.1 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("float16", "bfloat16")}, backend_version) def matmul( x1: np.ndarray, x2: np.ndarray, @@ -140,7 +140,7 @@ def matmul( @_scalar_output_to_0d_array -@with_unsupported_dtypes({"1.26.1 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("float16", "bfloat16")}, backend_version) def matrix_norm( x: np.ndarray, /, @@ -148,8 +148,11 @@ def matrix_norm( ord: Union[int, float, Literal[inf, -inf, "fro", "nuc"]] = "fro", axis: Tuple[int, int] = (-2, -1), keepdims: bool = False, + dtype: Optional[np.dtype] = None, out: Optional[np.ndarray] = None, ) -> np.ndarray: + if dtype is not None: + x = ivy.astype(x, dtype) if not isinstance(axis, tuple): axis = tuple(axis) return np.linalg.norm(x, ord=ord, axis=axis, keepdims=keepdims) @@ -162,7 +165,7 @@ def matrix_power( @with_unsupported_dtypes( - {"1.26.1 and below": ("float16", "bfloat16", "complex")}, + {"1.26.3 and below": ("float16", "bfloat16", "complex")}, backend_version, ) @_scalar_output_to_0d_array @@ -201,7 +204,7 @@ def matrix_transpose( return np.swapaxes(x, -1, -2) -@with_unsupported_dtypes({"1.26.1 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("float16",)}, backend_version) def outer( x1: np.ndarray, x2: np.ndarray, @@ -216,7 +219,7 @@ def outer( outer.support_native_out = True -@with_unsupported_dtypes({"1.26.1 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("float16",)}, backend_version) def pinv( x: np.ndarray, /, @@ -230,7 +233,7 @@ def pinv( return np.linalg.pinv(x, rtol) -@with_unsupported_dtypes({"1.26.1 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("float16",)}, backend_version) def qr( x: np.ndarray, /, @@ -243,7 +246,7 @@ def qr( return res(q, r) -@with_unsupported_dtypes({"1.26.1 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("float16",)}, backend_version) def slogdet( x: np.ndarray, /, @@ -258,7 +261,7 @@ def slogdet( return results(sign, logabsdet) -@with_unsupported_dtypes({"1.26.1 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("float16",)}, backend_version) def solve( x1: np.ndarray, x2: np.ndarray, @@ -283,7 +286,7 @@ def solve( return ret -@with_unsupported_dtypes({"1.26.1 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("float16",)}, backend_version) def svd( x: np.ndarray, /, *, compute_uv: bool = True, full_matrices: bool = True ) -> Union[np.ndarray, Tuple[np.ndarray, ...]]: @@ -297,7 +300,7 @@ def svd( return results(D) -@with_unsupported_dtypes({"1.26.1 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("float16",)}, backend_version) def svdvals( x: np.ndarray, /, *, driver: Optional[str] = None, out: Optional[np.ndarray] = None ) -> np.ndarray: @@ -330,7 +333,7 @@ def tensordot( @_scalar_output_to_0d_array -@with_unsupported_dtypes({"1.26.1 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("float16", "bfloat16")}, backend_version) def trace( x: np.ndarray, /, @@ -358,7 +361,7 @@ def vecdot( return np.tensordot(x1, x2, axes=(axis, axis)) -@with_unsupported_dtypes({"1.26.1 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("float16",)}, backend_version) def eig(x: np.ndarray, /, *, out: Optional[np.ndarray] = None) -> Tuple[np.ndarray]: result_tuple = NamedTuple( "eig", [("eigenvalues", np.ndarray), ("eigenvectors", np.ndarray)] @@ -435,7 +438,7 @@ def vander( @with_unsupported_dtypes( { - "1.26.1 and below": ( + "1.26.3 and below": ( "complex", "unsigned", ) diff --git a/ivy/functional/backends/numpy/manipulation.py b/ivy/functional/backends/numpy/manipulation.py index 2bc593bfcbe37..ee2084c7d3b8e 100644 --- a/ivy/functional/backends/numpy/manipulation.py +++ b/ivy/functional/backends/numpy/manipulation.py @@ -1,12 +1,14 @@ # global import math from numbers import Number -from typing import Union, Tuple, Optional, List, Sequence +from typing import List, Optional, Sequence, Tuple, Union + import numpy as np # local import ivy from ivy.func_wrapper import with_unsupported_dtypes + from . import backend_version @@ -70,7 +72,7 @@ def flip( return x if axis is None: axis = list(range(num_dims)) - if type(axis) is int: + if isinstance(axis, int): axis = [axis] axis = [item + num_dims if item < 0 else item for item in axis] return np.flip(x, axis) @@ -84,6 +86,9 @@ def permute_dims( copy: Optional[bool] = None, out: Optional[np.ndarray] = None, ) -> np.ndarray: + if copy: + newarr = np.copy(x) + return np.transpose(newarr, axes) return np.transpose(x, axes) @@ -103,6 +108,8 @@ def reshape( new_s if con else old_s for new_s, con, old_s in zip(shape, np.array(shape) != 0, x.shape) ] + if copy: + x = x.copy() return np.reshape(x, shape, order=order) @@ -127,6 +134,8 @@ def squeeze( ) -> np.ndarray: if isinstance(axis, list): axis = tuple(axis) + if copy: + x = x.copy() if x.shape == (): if axis is None or axis == 0 or axis == -1: return x @@ -189,7 +198,7 @@ def split( return np.split(x, num_or_size_splits, axis) -@with_unsupported_dtypes({"1.26.1 and below": ("uint64",)}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("uint64",)}, backend_version) def repeat( x: np.ndarray, /, @@ -233,6 +242,8 @@ def swapaxes( copy: Optional[bool] = None, out: Optional[np.ndarray] = None, ) -> np.ndarray: + if copy: + x = x.copy() return np.swapaxes(x, axis0, axis1) diff --git a/ivy/functional/backends/numpy/module.py b/ivy/functional/backends/numpy/module.py new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/ivy/functional/backends/numpy/random.py b/ivy/functional/backends/numpy/random.py index a398c6a63db41..17a9d19fc4698 100644 --- a/ivy/functional/backends/numpy/random.py +++ b/ivy/functional/backends/numpy/random.py @@ -1,4 +1,5 @@ -"""Collection of Numpy random functions, wrapped to fit Ivy syntax and signature.""" +"""Collection of Numpy random functions, wrapped to fit Ivy syntax and +signature.""" # global import numpy as np @@ -24,7 +25,7 @@ def random_uniform( high: Union[float, np.ndarray] = 1.0, shape: Optional[Union[ivy.NativeShape, Sequence[int], np.ndarray]] = None, dtype: np.dtype, - device: str = None, + device: Optional[str] = None, out: Optional[np.ndarray] = None, seed: Optional[int] = None, ) -> np.ndarray: @@ -39,7 +40,7 @@ def random_normal( mean: Union[float, np.ndarray] = 0.0, std: Union[float, np.ndarray] = 1.0, shape: Optional[Union[ivy.NativeShape, Sequence[int]]] = None, - device: str = None, + device: Optional[str] = None, dtype: np.dtype, seed: Optional[int] = None, out: Optional[np.ndarray] = None, @@ -51,7 +52,7 @@ def random_normal( return np.asarray(np.random.normal(mean, std, shape), dtype=dtype) -@with_unsupported_dtypes({"1.26.1 and below": ("bfloat16",)}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("bfloat16",)}, backend_version) def multinomial( population_size: int, num_samples: int, @@ -60,7 +61,7 @@ def multinomial( batch_size: int = 1, probs: Optional[np.ndarray] = None, replace: bool = True, - device: str = None, + device: Optional[str] = None, seed: Optional[int] = None, out: Optional[np.ndarray] = None, ) -> np.ndarray: @@ -95,7 +96,7 @@ def randint( /, *, shape: Optional[Union[ivy.NativeShape, Sequence[int]]] = None, - device: str = None, + device: Optional[str] = None, dtype: Optional[Union[np.dtype, ivy.Dtype]] = None, seed: Optional[int] = None, out: Optional[np.ndarray] = None, @@ -110,7 +111,7 @@ def randint( return np.random.randint(low, high, shape, dtype=dtype) -def seed(*, seed_value: int = 0) -> None: +def seed(*, seed_value: int = 0): np.random.seed(seed_value) return diff --git a/ivy/functional/backends/numpy/set.py b/ivy/functional/backends/numpy/set.py index 18911bebd6402..097fa25b24060 100644 --- a/ivy/functional/backends/numpy/set.py +++ b/ivy/functional/backends/numpy/set.py @@ -85,7 +85,7 @@ def unique_inverse( values = np.append(values, np.full(nan_count - 1, np.nan), axis=axis).astype( x.dtype ) - inverse_indices = np.reshape(inverse_indices, x.shape, axis=0) + inverse_indices = np.reshape(inverse_indices, x.shape) return Results(values, inverse_indices) diff --git a/ivy/functional/backends/numpy/sorting.py b/ivy/functional/backends/numpy/sorting.py index 1603485ee1f32..78fb8f5d6c925 100644 --- a/ivy/functional/backends/numpy/sorting.py +++ b/ivy/functional/backends/numpy/sorting.py @@ -37,12 +37,12 @@ def sort( kind = "stable" if stable else "quicksort" ret = np.asarray(np.sort(x, axis=axis, kind=kind)) if descending: - ret = np.asarray((np.flip(ret, axis))) + ret = np.asarray(np.flip(ret, axis)) return ret # msort -@with_unsupported_dtypes({"1.26.1 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("complex",)}, backend_version) def msort( a: Union[np.ndarray, list, tuple], /, *, out: Optional[np.ndarray] = None ) -> np.ndarray: @@ -62,14 +62,12 @@ def searchsorted( ret_dtype: np.dtype = np.int64, out: Optional[np.ndarray] = None, ) -> np.ndarray: - assert ivy.is_int_dtype(ret_dtype), ValueError( + assert ivy.is_int_dtype(ret_dtype), TypeError( "only Integer data types are supported for ret_dtype." ) is_sorter_provided = sorter is not None if is_sorter_provided: - assert ivy.is_int_dtype(sorter.dtype) and not ivy.is_uint_dtype( - sorter.dtype - ), TypeError( + assert ivy.is_int_dtype(sorter.dtype), TypeError( f"Only signed integer data type for sorter is allowed, got {sorter.dtype}." ) if x.ndim != 1: diff --git a/ivy/functional/backends/numpy/statistical.py b/ivy/functional/backends/numpy/statistical.py index 581731585c069..bffc814767cc3 100644 --- a/ivy/functional/backends/numpy/statistical.py +++ b/ivy/functional/backends/numpy/statistical.py @@ -14,16 +14,25 @@ # -------------------# +@_scalar_output_to_0d_array def min( x: np.ndarray, /, *, axis: Optional[Union[int, Sequence[int]]] = None, keepdims: bool = False, + initial: Optional[Union[int, float, complex]] = None, + where: Optional[np.ndarray] = None, out: Optional[np.ndarray] = None, ) -> np.ndarray: axis = tuple(axis) if isinstance(axis, list) else axis - return np.asarray(np.amin(a=x, axis=axis, keepdims=keepdims, out=out)) + if where is not None: + ret = np.amin( + a=x, axis=axis, keepdims=keepdims, initial=initial, where=where, out=out + ) + else: + ret = np.amin(a=x, axis=axis, keepdims=keepdims, initial=initial, out=out) + return np.asarray(ret) min.support_native_out = True @@ -54,9 +63,7 @@ def mean( out: Optional[np.ndarray] = None, ) -> np.ndarray: axis = tuple(axis) if isinstance(axis, list) else axis - return ivy.astype( - np.mean(x, axis=axis, keepdims=keepdims, out=out), x.dtype, copy=False - ) + return np.mean(x, axis=axis, keepdims=keepdims, dtype=x.dtype, out=out) mean.support_native_out = True @@ -171,7 +178,7 @@ def var( # ------# -@with_unsupported_dtypes({"1.26.1 and below": ("bfloat16",)}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("bfloat16", "bool")}, backend_version) def cumprod( x: np.ndarray, /, diff --git a/ivy/functional/backends/numpy/utility.py b/ivy/functional/backends/numpy/utility.py index de5597f952940..bba2ef86e03a7 100644 --- a/ivy/functional/backends/numpy/utility.py +++ b/ivy/functional/backends/numpy/utility.py @@ -17,7 +17,7 @@ def all( try: return np.asarray(np.all(x, axis=axis, keepdims=keepdims, out=out)) except np.AxisError as error: - raise ivy.utils.exceptions.IvyIndexError(error) + raise ivy.utils.exceptions.IvyIndexError(error) from error all.support_native_out = True diff --git a/ivy/functional/backends/paddle/__init__.py b/ivy/functional/backends/paddle/__init__.py index bd0f7259b687c..0e5f0fa31e9ee 100644 --- a/ivy/functional/backends/paddle/__init__.py +++ b/ivy/functional/backends/paddle/__init__.py @@ -117,7 +117,7 @@ def rep_method(*args, **kwargs): # update these to add new dtypes valid_dtypes = { - "2.4.0 and below": ( + "2.4.2 and below": ( ivy.int8, ivy.int16, ivy.int32, @@ -130,7 +130,7 @@ def rep_method(*args, **kwargs): ivy.complex128, ivy.bool, ), - "2.4.1 and above": ( + "2.5.0 and above": ( ivy.int8, ivy.int16, ivy.int32, @@ -146,7 +146,7 @@ def rep_method(*args, **kwargs): ), } valid_numeric_dtypes = { - "2.4.0 and below": ( + "2.4.2 and below": ( ivy.int8, ivy.int16, ivy.int32, @@ -159,7 +159,7 @@ def rep_method(*args, **kwargs): ivy.complex128, ivy.bool, ), - "2.4.1 and above": ( + "2.5.0 and above": ( ivy.int8, ivy.int16, ivy.int32, @@ -175,20 +175,20 @@ def rep_method(*args, **kwargs): ), } valid_int_dtypes = { - "2.5.1 and below": ( + "2.6.0 and below": ( ivy.int8, ivy.int16, ivy.int32, ivy.int64, ivy.uint8, - ) + ), } valid_float_dtypes = { - "2.4.0 and below": (ivy.float16, ivy.float32, ivy.float64), - "2.4.1 and above": (ivy.bfloat16, ivy.float16, ivy.float32, ivy.float64), + "2.4.2 and below": (ivy.float16, ivy.float32, ivy.float64), + "2.5.0 and above": (ivy.bfloat16, ivy.float16, ivy.float32, ivy.float64), } -valid_uint_dtypes = {"2.5.1 and below": (ivy.uint8,)} -valid_complex_dtypes = {"2.5.1 and below": (ivy.complex64, ivy.complex128)} +valid_uint_dtypes = {"2.6.0 and below": (ivy.uint8,)} +valid_complex_dtypes = {"2.6.0 and below": (ivy.complex64, ivy.complex128)} # leave these untouched valid_dtypes = _dtype_from_version(valid_dtypes, backend_version) @@ -201,13 +201,13 @@ def rep_method(*args, **kwargs): # update these to add new dtypes invalid_dtypes = { - "2.4.0 and below": ( + "2.4.2 and below": ( ivy.uint16, ivy.uint32, ivy.uint64, ivy.bfloat16, ), - "2.4.1 and above": ( + "2.5.0 and above": ( ivy.uint16, ivy.uint32, ivy.uint64, @@ -215,23 +215,23 @@ def rep_method(*args, **kwargs): } invalid_numeric_dtypes = { - "2.4.0 and below": ( + "2.4.2 and below": ( ivy.uint16, ivy.uint32, ivy.uint64, ivy.bfloat16, ), - "2.4.1 and above": ( + "2.5.0 and above": ( ivy.uint16, ivy.uint32, ivy.uint64, ), } -invalid_int_dtypes = {"2.5.1 and below": (ivy.uint16, ivy.uint32, ivy.uint64)} -invalid_float_dtypes = {"2.4.0 and below": (ivy.bfloat16,), "2.4.1 and above": ()} -invalid_uint_dtypes = {"2.5.1 and below": (ivy.uint16, ivy.uint32, ivy.uint64)} -invalid_complex_dtypes = {"2.5.1 and below": ()} +invalid_int_dtypes = {"2.6.0 and below": (ivy.uint16, ivy.uint32, ivy.uint64)} +invalid_float_dtypes = {"2.4.2 and below": (ivy.bfloat16,), "2.5.0 and above": ()} +invalid_uint_dtypes = {"2.6.0 and below": (ivy.uint16, ivy.uint32, ivy.uint64)} +invalid_complex_dtypes = {"2.6.0 and below": ()} # leave these untouched invalid_dtypes = _dtype_from_version(invalid_dtypes, backend_version) @@ -297,8 +297,14 @@ def closest_valid_dtype(type=None, /, as_native=False): from .experimental import * from . import control_flow_ops from .control_flow_ops import * +from . import module +from .module import * + # sub-backends from . import sub_backends from .sub_backends import * + + +NativeModule = paddle.nn.Layer diff --git a/ivy/functional/backends/paddle/activations.py b/ivy/functional/backends/paddle/activations.py index 14d6692f818bf..8ddaff5b70a09 100644 --- a/ivy/functional/backends/paddle/activations.py +++ b/ivy/functional/backends/paddle/activations.py @@ -1,5 +1,4 @@ -""" -Paddle activation functions. +"""Paddle activation functions. Collection of Paddle activation functions, wrapped to fit Ivy syntax and signature. @@ -14,35 +13,36 @@ # local import ivy.functional.backends.paddle as paddle_backend import ivy -from ivy.func_wrapper import with_unsupported_device_and_dtypes +from ivy.func_wrapper import ( + with_unsupported_device_and_dtypes, + with_supported_dtypes, + with_unsupported_dtypes, + with_supported_device_and_dtypes, +) from . import backend_version -unsupported_dtypes = [ - paddle.int8, - paddle.int16, - paddle.int32, - paddle.int64, - paddle.uint8, - paddle.float16, - paddle.complex64, - paddle.complex128, - paddle.bool, -] - - +@with_supported_dtypes( + { + "2.6.0 and below": ( + "float32", + "float64", + "complex64", + ) + }, + backend_version, +) def relu( x: paddle.Tensor, /, *, complex_mode="jax", out: Optional[paddle.Tensor] = None ) -> paddle.Tensor: - if x.dtype in unsupported_dtypes: - if paddle.is_complex(x): - return paddle.complex(F.relu(x.real()), F.relu(x.imag())) - return F.relu(x.cast("float32")).cast(x.dtype) + if paddle.is_complex(x): + return paddle.complex(F.relu(x.real()), F.relu(x.imag())) return F.relu(x) -@with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("bfloat16",)}}, backend_version +@with_supported_device_and_dtypes( + {"2.6.0 and below": {"cpu": ("float32", "float64", "complex")}}, + backend_version, ) def leaky_relu( x: paddle.Tensor, @@ -52,18 +52,17 @@ def leaky_relu( complex_mode="jax", out: Optional[paddle.Tensor] = None, ) -> paddle.Tensor: - if x.dtype in unsupported_dtypes: - if paddle.is_complex(x): - return paddle.complex( - F.leaky_relu(x.real(), negative_slope=alpha), - F.leaky_relu(x.imag(), negative_slope=alpha), - ) - return F.leaky_relu(x.cast("float32"), negative_slope=alpha).cast(x.dtype) + if paddle.is_complex(x): + return paddle.complex( + F.leaky_relu(x.real(), negative_slope=alpha), + F.leaky_relu(x.imag(), negative_slope=alpha), + ) return F.leaky_relu(x, negative_slope=alpha) -@with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("bfloat16",)}}, backend_version +@with_supported_device_and_dtypes( + {"2.6.0 and below": {"cpu": ("float32", "float64", "complex")}}, + backend_version, ) def gelu( x: paddle.Tensor, @@ -82,26 +81,23 @@ def gelu( * x * (1 + paddle_backend.tanh(sqrt_2_over_pi * (x + 0.044715 * x * x * x))) ) - if x.dtype in unsupported_dtypes: - return F.gelu(x.cast("float32"), approximate=approximate).cast(x.dtype) return F.gelu(x, approximate=approximate) -@with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("bfloat16",)}}, backend_version +@with_supported_device_and_dtypes( + {"2.6.0 and below": {"cpu": ("float32", "float64", "complex")}}, + backend_version, ) def sigmoid( x: paddle.Tensor, /, *, complex_mode="jax", out: Optional[paddle.Tensor] = None ) -> paddle.Tensor: if paddle.is_complex(x): return 1.0 / (1.0 + paddle_backend.exp(-x)) - if x.dtype in unsupported_dtypes: - return F.sigmoid(x.cast("float32")).cast(x.dtype) return F.sigmoid(x) -@with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("float16", "bfloat16")}}, backend_version +@with_unsupported_dtypes( + {"2.6.0 and below": ("bfloat16", "float16", "complex128")}, backend_version ) def softmax( x: paddle.Tensor, @@ -151,7 +147,7 @@ def softplus( # Softsign @with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("float16", "bfloat16")}}, backend_version + {"2.6.0 and below": {"cpu": ("float16", "bfloat16")}}, backend_version ) def softsign( x: paddle.Tensor, @@ -165,7 +161,7 @@ def softsign( @with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("float16", "bfloat16")}}, backend_version + {"2.6.0 and below": {"cpu": ("float16", "bfloat16")}}, backend_version ) def log_softmax( x: paddle.Tensor, @@ -183,8 +179,9 @@ def log_softmax( return ret -@with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("bfloat16",)}}, backend_version +@with_supported_device_and_dtypes( + {"2.6.0 and below": {"cpu": ("float32", "float64", "complex")}}, + backend_version, ) def mish( x: paddle.Tensor, @@ -193,15 +190,13 @@ def mish( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[paddle.Tensor] = None, ) -> paddle.Tensor: - if x.dtype in unsupported_dtypes: - if paddle.is_complex(x): - return x * paddle_backend.tanh(paddle_backend.log1p(paddle_backend.exp(x))) - return F.mish(x.cast("float32")).cast(x.dtype) + if paddle.is_complex(x): + return x * paddle_backend.tanh(paddle_backend.log1p(paddle_backend.exp(x))) return F.mish(x) @with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("float16",)}}, backend_version + {"2.6.0 and below": {"cpu": ("float16",)}}, backend_version ) def hardswish( x: paddle.Tensor, diff --git a/ivy/functional/backends/paddle/control_flow_ops.py b/ivy/functional/backends/paddle/control_flow_ops.py index 9d14c8233819a..221625819eb89 100644 --- a/ivy/functional/backends/paddle/control_flow_ops.py +++ b/ivy/functional/backends/paddle/control_flow_ops.py @@ -12,6 +12,10 @@ def if_else(cond, body_fn, orelse_fn, vars): def while_loop(test_fn, body_fn, vars): result = vars + if isinstance(vars, dict): + result = list(vars.values()) while test_fn(*result): result = body_fn(*result) + if not isinstance(result, tuple): + result = (result,) return result diff --git a/ivy/functional/backends/paddle/creation.py b/ivy/functional/backends/paddle/creation.py index c6922d3690032..65d826733c439 100644 --- a/ivy/functional/backends/paddle/creation.py +++ b/ivy/functional/backends/paddle/creation.py @@ -11,6 +11,7 @@ import ivy from ivy.func_wrapper import ( with_unsupported_device_and_dtypes, + with_supported_device_and_dtypes, ) from ivy.functional.ivy.creation import ( _asarray_to_native_arrays_and_back, @@ -95,15 +96,24 @@ def asarray( ret = obj.clone().detach() ret.stop_gradient = obj.stop_gradient else: - ret = obj + ret = paddle.to_tensor( + obj.detach(), + dtype=dtype, + place=device, + stop_gradient=obj.stop_gradient, + ) else: ret = obj - return ret.astype(dtype) + ret = ret.astype(dtype) if ret.dtype != obj.dtype else ret + return paddle_backend.to_device(ret, device) elif isinstance(obj, (Number, bool, complex)): - return paddle_backend.squeeze( - paddle.to_tensor(obj, dtype=dtype, place=device), axis=0 - ) + ret = paddle.to_tensor(obj, dtype=dtype, place=device) + + if ret.ndim != 0: # for versions <2.5.0 + return ret.squeeze() + else: + return ret obj = ivy.nested_map(_remove_np_bfloat16, obj, shallow=False) return paddle.to_tensor(obj, dtype=dtype, place=device) @@ -133,7 +143,7 @@ def empty_like( @with_unsupported_device_and_dtypes( { - "2.5.1 and below": { + "2.6.0 and below": { "cpu": ( "uint8", "int8", @@ -198,9 +208,24 @@ def to_dlpack(x, /, *, out: Optional[paddle.Tensor] = None): def from_dlpack(x, /, *, out: Optional[paddle.Tensor] = None): - return paddle.utils.dlpack.from_dlpack(x) + if hasattr(x, "__dlpack__"): + capsule = x.__dlpack__() + else: + capsule = x + return paddle.utils.dlpack.from_dlpack(capsule) +@with_unsupported_device_and_dtypes( + { + "2.6.0 and below": { + "cpu": ( + "complex", + "bool", + ) + } + }, + backend_version, +) def full( shape: Union[ivy.NativeShape, Sequence[int]], fill_value: Union[int, float, bool], @@ -263,7 +288,10 @@ def _linspace_helper(start, stop, num, axis=None, *, dtype=None): sos_shape = stop_shape if num == 1: return ( - paddle_backend.ones(stop_shape[:axis] + [1] + stop_shape[axis:]) * start + paddle_backend.ones( + stop_shape[:axis] + [1] + stop_shape[axis:], dtype=dtype + ) + * start ) stop = stop.reshape((-1,)) linspace_method = ( @@ -340,7 +368,7 @@ def _slice_at_axis(sl, axis): @with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("uint16", "bfloat16", "float16")}}, backend_version + {"2.6.0 and below": {"cpu": ("uint16", "bfloat16", "float16")}}, backend_version ) def linspace( start: Union[paddle.Tensor, float], @@ -398,7 +426,7 @@ def linspace( @with_unsupported_device_and_dtypes( { - "2.5.1 and below": { + "2.6.0 and below": { "cpu": ( "int8", "int16", @@ -455,6 +483,22 @@ def ones( return paddle.ones(shape=shape).cast(dtype) +@with_supported_device_and_dtypes( + { + "2.6.0 and below": { + "cpu": ( + "int32", + "int64", + "float64", + "float32", + "complex128", + "complex64", + "bool", + ) + } + }, + backend_version, +) def ones_like( x: paddle.Tensor, /, @@ -468,7 +512,7 @@ def ones_like( @with_unsupported_device_and_dtypes( { - "2.5.1 and below": { + "2.6.0 and below": { "cpu": ( "int8", "int16", @@ -487,7 +531,7 @@ def tril( @with_unsupported_device_and_dtypes( { - "2.5.1 and below": { + "2.6.0 and below": { "cpu": ( "int8", "int16", @@ -514,6 +558,10 @@ def zeros( return paddle.zeros(shape=shape).cast(dtype) +@with_unsupported_device_and_dtypes( + {"2.6.0 and below": {"cpu": ("uint8", "int8", "int16", "float16", "bfloat16")}}, + backend_version, +) def zeros_like( x: paddle.Tensor, /, @@ -535,7 +583,7 @@ def zeros_like( def copy_array( x: paddle.Tensor, *, - to_ivy_array: Optional[bool] = True, + to_ivy_array: bool = True, out: Optional[paddle.Tensor] = None, ) -> paddle.Tensor: if 0 in x.shape: @@ -600,14 +648,14 @@ def one_hot( @with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("complex64", "complex128")}}, + {"2.6.0 and below": {"cpu": ("complex64", "complex128")}}, backend_version, ) def frombuffer( buffer: bytes, - dtype: Optional[paddle.dtype] = float, - count: Optional[int] = -1, - offset: Optional[int] = 0, + dtype: paddle.dtype = float, + count: int = -1, + offset: int = 0, ) -> paddle.Tensor: dtype_bytes = int(ivy.Dtype(dtype).dtype_bits / 8) if str(dtype) == "bool": @@ -642,7 +690,7 @@ def frombuffer( def triu_indices( n_rows: int, n_cols: Optional[int] = None, - k: Optional[int] = 0, + k: int = 0, /, *, device: core.Place = None, diff --git a/ivy/functional/backends/paddle/data_type.py b/ivy/functional/backends/paddle/data_type.py index 5127217dc85a0..48833be5155de 100644 --- a/ivy/functional/backends/paddle/data_type.py +++ b/ivy/functional/backends/paddle/data_type.py @@ -5,7 +5,9 @@ import ivy.functional.backends.paddle as paddle_backend import numpy as np import ivy +from ivy.func_wrapper import with_unsupported_dtypes from ivy.functional.ivy.data_type import _handle_nestable_dtype_info +from . import backend_version ivy_dtype_dict = { @@ -139,6 +141,18 @@ def broadcast_arrays(*arrays: paddle.Tensor) -> List[paddle.Tensor]: return result +@with_unsupported_dtypes( + { + "2.6.0 and below": ( + "uint8", + "int8", + "int16", + "float16", + "bfloat16", + ) + }, + backend_version, +) def broadcast_to( x: paddle.Tensor, /, @@ -157,15 +171,7 @@ def broadcast_to( if x.ndim > len(shape): x = x.reshape([-1]) - if x.dtype in [ - paddle.int8, - paddle.int16, - paddle.uint8, - paddle.float16, - paddle.bfloat16, - ]: - return paddle.broadcast_to(x.cast("float32"), shape).cast(x.dtype) - elif x.dtype in [paddle.complex64, paddle.complex128]: + if x.dtype in [paddle.complex64, paddle.complex128]: x_real = paddle.broadcast_to(x.real(), shape) x_imag = paddle.broadcast_to(x.imag(), shape) return paddle.complex(x_real, x_imag) @@ -225,7 +231,7 @@ def as_ivy_dtype(dtype_in: Union[paddle.dtype, str, bool, int, float], /) -> ivy def as_native_dtype( - dtype_in: Union[paddle.dtype, str, bool, int, float] + dtype_in: Union[paddle.dtype, str, bool, int, float], ) -> paddle.dtype: if dtype_in is int: return ivy.default_int_dtype(as_native=True) @@ -237,7 +243,7 @@ def as_native_dtype( return paddle.bool if not isinstance(dtype_in, str): return dtype_in - if dtype_in in native_dtype_dict.keys(): + if dtype_in in native_dtype_dict: return native_dtype_dict[ivy.Dtype(dtype_in)] else: raise ivy.utils.exceptions.IvyException( @@ -268,7 +274,4 @@ def dtype_bits(dtype_in: Union[paddle.dtype, str], /) -> int: def is_native_dtype(dtype_in: Union[paddle.dtype, str], /) -> bool: if not ivy.is_hashable_dtype(dtype_in): return False - if dtype_in in ivy_dtype_dict: - return True - else: - return False + return dtype_in in ivy_dtype_dict diff --git a/ivy/functional/backends/paddle/device.py b/ivy/functional/backends/paddle/device.py index 9360fa702f1cd..b1120da1d5657 100644 --- a/ivy/functional/backends/paddle/device.py +++ b/ivy/functional/backends/paddle/device.py @@ -1,4 +1,5 @@ -"""Collection of Paddle general functions, wrapped to fit Ivy syntax and signature.""" +"""Collection of Paddle general functions, wrapped to fit Ivy syntax and +signature.""" # global import os @@ -34,7 +35,11 @@ def to_device( device = as_native_dev(device) if device.is_cpu_place() and not x.place.is_cpu_place(): return x.cpu() - elif device.is_gpu_place() and not x.place.is_gpu_place(): + elif (device.is_gpu_place() and not x.place.is_gpu_place()) or ( + x.place.is_gpu_place() + and device.is_gpu_place() + and x.place.gpu_device_id() != device.gpu_device_id() + ): return x.cuda(device.gpu_device_id()) else: return x diff --git a/ivy/functional/backends/paddle/elementwise.py b/ivy/functional/backends/paddle/elementwise.py index 208e28495572a..b9f468220fe91 100644 --- a/ivy/functional/backends/paddle/elementwise.py +++ b/ivy/functional/backends/paddle/elementwise.py @@ -1,25 +1,37 @@ # global -from typing import Union, Optional, Tuple, Type +import math +from typing import Optional, Union import paddle -import math -import ivy.functional.backends.paddle as paddle_backend + import ivy +import ivy.functional.backends.paddle as paddle_backend from ivy import promote_types_of_inputs -from ivy.func_wrapper import with_unsupported_device_and_dtypes, with_supported_dtypes +from ivy.func_wrapper import ( + with_supported_device_and_dtypes, + with_supported_dtypes, + with_unsupported_device_and_dtypes, + with_unsupported_dtypes, +) # local from . import backend_version def _elementwise_helper(x1, x2): - if (not hasattr(x1, "dtype") or not hasattr(x2, "dtype")) or (x1.dtype == x2.dtype): + if (not hasattr(x1, "dtype") or not hasattr(x2, "dtype")) or (x1.dtype != x2.dtype): x1, x2 = ivy.promote_types_of_inputs(x1, x2) - if x1.shape != x2.shape: - x1, x2 = paddle_backend.broadcast_arrays(x1, x2) + # the following was needed in versions <=2.4.2 because most functions didn't + # accept 0D inputs along other inputs + # if x1.shape != x2.shape: + # x1, x2 = paddle_backend.broadcast_arrays(x1, x2) return x1, x2, x1.dtype +@with_unsupported_dtypes( + {"2.6.0 and below": ("int8", "int16", "uint8", "float16", "bool", "bfloat16")}, + backend_version, +) def add( x1: Union[float, paddle.Tensor], x2: Union[float, paddle.Tensor], @@ -29,14 +41,6 @@ def add( out: Optional[paddle.Tensor] = None, ) -> paddle.Tensor: x1, x2, ret_dtype = _elementwise_helper(x1, x2) - if x1.dtype in [ - paddle.int8, - paddle.uint8, - paddle.float16, - paddle.bool, - paddle.bfloat16, - ]: - x1, x2 = x1.astype("float32"), x2.astype("float32") if alpha not in (1, None): x2 = paddle_backend.multiply(x2, alpha) x1, x2 = ivy.promote_types_of_inputs(x1, x2) @@ -54,10 +58,18 @@ def bitwise_xor( return paddle.bitwise_xor(x1, x2) +@with_supported_dtypes( + { + "2.6.0 and below": ( + "float16", + "float32", + "float64", + ) + }, + backend_version, +) def expm1(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.Tensor: - if x.dtype in [paddle.float16, paddle.float32, paddle.float64]: - return paddle.expm1(x) - return paddle_backend.subtract(paddle_backend.exp(x), 1.0).astype(x.dtype) + return paddle.expm1(x) def bitwise_invert( @@ -68,7 +80,7 @@ def bitwise_invert( @with_unsupported_device_and_dtypes( { - "2.5.1 and below": { + "2.6.0 and below": { "cpu": ( "int8", "int16", @@ -87,6 +99,10 @@ def isfinite( return paddle.isfinite(x) +@with_unsupported_dtypes( + {"2.6.0 and below": ("complex", "uint8")}, + backend_version, +) def isinf( x: paddle.Tensor, /, @@ -113,18 +129,17 @@ def equal( out: Optional[paddle.Tensor] = None, ) -> paddle.Tensor: x1, x2, ret_dtype = _elementwise_helper(x1, x2) - diff = paddle_backend.subtract(x1, x2) - ret = paddle_backend.logical_and( - paddle_backend.less_equal(diff, 0), paddle_backend.greater_equal(diff, 0) - ) - # ret result is sufficient for all cases except where the value is +/-INF of NaN - return paddle_backend.where( - paddle_backend.isnan(diff), - ~paddle_backend.logical_or(paddle_backend.isnan(x1), paddle_backend.isnan(x2)), - ret, - ) + if paddle.is_complex(x1): + real = paddle.equal(x1.real(), x2.real()) + imag = paddle.equal(x1.imag(), x2.imag()) + return paddle_backend.logical_and(real, imag) + return paddle.equal(x1, x2) +@with_unsupported_dtypes( + {"2.6.0 and below": ("bool",)}, + backend_version, +) def less_equal( x1: Union[float, paddle.Tensor], x2: Union[float, paddle.Tensor], @@ -133,13 +148,13 @@ def less_equal( out: Optional[paddle.Tensor] = None, ) -> paddle.Tensor: x1, x2, ret_dtype = _elementwise_helper(x1, x2) - if x1.dtype in [paddle.int8, paddle.uint8, paddle.complex64, paddle.complex128]: - if paddle.is_complex(x1): - if paddle.is_complex(x1): - real = paddle.less_equal(x1.real(), x2.real()) - imag = paddle.less_equal(x1.imag(), x2.imag()) - return paddle_backend.logical_and(real, imag) - return paddle.less_equal(x1.astype("float32"), x2.astype("float32")) + if isinstance(x1, paddle.Tensor) and isinstance(x2, paddle.Tensor): + if paddle.is_complex(x1) and paddle.is_complex(x2): + real_comparison = paddle.real(x1) < paddle.real(x2) + imag_comparison = paddle_backend.logical_and( + paddle.real(x1) == paddle.real(x2), paddle.imag(x1) < paddle.imag(x2) + ) + return paddle_backend.logical_or(real_comparison, imag_comparison) return paddle.less_equal(x1, x2) @@ -155,95 +170,56 @@ def bitwise_and( return paddle.bitwise_and(x1, x2) +@with_supported_dtypes( + {"2.6.0 and below": ("float32", "float64", "complex")}, + backend_version, +) def ceil(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.Tensor: - x_dtype = x.dtype - if x_dtype in [ - paddle.int8, - paddle.int16, - paddle.int32, - paddle.uint8, - paddle.float16, - paddle.complex64, - paddle.complex128, - paddle.bool, - ]: - if paddle.is_complex(x): - return paddle.complex(paddle.ceil(x.real()), paddle.ceil(x.imag())) - return paddle.ceil(x.astype("float32")).astype(x_dtype) - elif x_dtype == paddle.int64: - return paddle.ceil(x.astype("float64")).astype(x_dtype) + if paddle.is_complex(x): + return paddle.complex(paddle.ceil(x.real()), paddle.ceil(x.imag())) return paddle.ceil(x) +@with_supported_dtypes( + {"2.6.0 and below": ("float32", "float64", "complex")}, + backend_version, +) def floor(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.Tensor: - x_dtype = x.dtype - if x_dtype in [ - paddle.int8, - paddle.int16, - paddle.int32, - paddle.uint8, - paddle.float16, - paddle.complex64, - paddle.complex128, - paddle.bool, - ]: - if paddle.is_complex(x): - return paddle.complex(paddle.floor(x.real()), paddle.floor(x.imag())) - return paddle.floor(x.astype("float32")).astype(x_dtype) - elif x_dtype == paddle.int64: - return paddle.floor(x.astype("float64")).astype(x_dtype) + if paddle.is_complex(x): + return paddle.complex(paddle.floor(x.real()), paddle.floor(x.imag())) return paddle.floor(x) -@with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("bool", "bfloat16")}}, +@with_supported_device_and_dtypes( + { + "2.6.0 and below": { + "cpu": ( + "float32", + "float64", + ) + } + }, backend_version, ) def asin(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.Tensor: - if x.dtype in [ - paddle.int8, - paddle.int16, - paddle.int32, - paddle.int64, - paddle.uint8, - paddle.float16, - ]: - ret_dtype = x.dtype - return paddle.asin(x.astype("float32")).astype(ret_dtype) - if paddle.is_complex(x): - asinh_iz = paddle_backend.asinh(paddle.complex(-x.imag(), x.real())) - return paddle.complex(asinh_iz.imag(), -asinh_iz.real()) return paddle.asin(x) -@with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("bool", "bfloat16")}}, +@with_supported_dtypes( + { + "2.6.0 and below": ( + "float32", + "float64", + ) + }, backend_version, ) def asinh(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.Tensor: - if x.dtype in [ - paddle.int8, - paddle.int16, - paddle.int32, - paddle.int64, - paddle.uint8, - paddle.float16, - ]: - ret_dtype = x.dtype - return paddle.asinh(x.astype("float32")).astype(ret_dtype) - if paddle.is_complex(x): - # From https://github.com/python/cpython/blob/39ef93edb9802dccdb6555d4209ac2e60875a011/Modules/cmathmodule.c#L276 # noqa - s1 = paddle_backend.sqrt(paddle.complex(1 + x.imag(), -x.real())) - s2 = paddle_backend.sqrt(paddle.complex(1 - x.imag(), x.real())) - return paddle.complex( - paddle.asinh(s1.real() * s2.imag() - s2.real() * s1.imag()), - paddle.atan2(x.imag(), s1.real() * s2.real() - s1.imag() * s2.imag()), - ) return paddle.asinh(x) -@with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("complex64", "complex128")}}, +@with_supported_device_and_dtypes( + {"2.6.0 and below": {"cpu": ("float16", "float32", "float64", "complex")}}, backend_version, ) def sign( @@ -253,50 +229,12 @@ def sign( np_variant: Optional[bool] = True, out: Optional[paddle.Tensor] = None, ) -> paddle.Tensor: - if x.dtype in [ - paddle.int8, - paddle.int16, - paddle.int32, - paddle.int64, - paddle.uint8, - paddle.float16, - paddle.bfloat16, - paddle.bool, - ]: - return paddle.sgn(x.astype("float32")).astype(x.dtype) return paddle.sgn(x) -# TODO: Remove `float16` from the list once paddle add it's supporting kernel to `CPU`. -def _determine_sqrt_dtype_cast( - dtype: Type[paddle.Tensor], -) -> Tuple[Optional[str], Optional[str]]: - """ - Determine the appropriate casting dtype for sqrt operations. - - Returns: - (intermediate_dtype, output_dtype) - """ - cast_and_return_float32_dtype = { - paddle.int8, - paddle.int16, - paddle.int32, - paddle.uint8, - paddle.bool, - } - - if dtype in cast_and_return_float32_dtype: - return "float32", "float32" - elif dtype == paddle.int64: - return "float64", "float64" - elif dtype == paddle.float16: - return "float32", "float16" - elif dtype == paddle.bfloat16: - return "float32", "bfloat16" - else: - return None, None - - +@with_supported_dtypes( + {"2.6.0 and below": ("float32", "float64", "complex")}, backend_version +) def sqrt(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.Tensor: """Calculate the square root with type handling.""" if paddle.is_complex(x): @@ -305,116 +243,85 @@ def sqrt(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle. paddle.cos(angle / 2), paddle.sin(angle / 2) ) * paddle.sqrt(paddle.abs(x)) - if x.dtype in {paddle.float32, paddle.float64}: - return paddle.sqrt(x) - - intermediate_dtype, output_dtype = _determine_sqrt_dtype_cast(x.dtype) - if intermediate_dtype: - result = paddle.sqrt(x.astype(intermediate_dtype)) - return result.astype(output_dtype) - - raise ValueError(f"Unsupported data type for sqrt: {x.dtype}") + return paddle.sqrt(x) -@with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("bool", "bfloat16")}}, +@with_supported_device_and_dtypes( + { + "2.6.0 and below": { + "cpu": ( + "float32", + "float64", + ) + } + }, backend_version, ) def cosh(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.Tensor: - if x.dtype in [ - paddle.int8, - paddle.int16, - paddle.int32, - paddle.int64, - paddle.uint8, - paddle.float16, - ]: - ret_dtype = x.dtype - return paddle.cosh(x.astype("float32")).astype(ret_dtype) - if paddle.is_complex(x): - re = x.real() - im = x.imag() - return paddle.complex( - paddle.cosh(re) * paddle.cos(im), paddle.sinh(re) * paddle.sin(im) - ) return paddle.cosh(x) +@with_supported_dtypes( + {"2.6.0 and below": ("float32", "float64", "complex")}, backend_version +) def log10(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.Tensor: - if x.dtype in [ - paddle.int8, - paddle.int16, - paddle.int32, - paddle.int64, - paddle.uint8, - paddle.float16, - paddle.complex64, - paddle.complex128, - paddle.bool, - ]: - if paddle.is_complex(x): - base = paddle.to_tensor(10.0).squeeze() - return paddle_backend.divide( - paddle_backend.log(x), paddle_backend.log(base) - ).astype(x.dtype) - return paddle.log10(x.astype("float32")).astype(x.dtype) + if paddle.is_complex(x): + base = paddle.to_tensor(10.0).squeeze() + return paddle_backend.divide( + paddle_backend.log(x), paddle_backend.log(base) + ).astype(x.dtype) return paddle.log10(x) +@with_supported_dtypes( + {"2.6.0 and below": ("float32", "float64", "complex")}, + backend_version, +) def log2(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.Tensor: - if x.dtype in [ - paddle.int8, - paddle.int16, - paddle.int32, - paddle.int64, - paddle.uint8, - paddle.float16, - paddle.complex64, - paddle.complex128, - paddle.bool, - ]: - if paddle.is_complex(x): - base = paddle.to_tensor(2.0).squeeze() - return paddle_backend.divide( - paddle_backend.log(x), paddle_backend.log(base) - ).astype(x.dtype) - return paddle.log2(x.astype("float32")).astype(x.dtype) + if paddle.is_complex(x): + base = paddle.to_tensor(2.0).squeeze() + return paddle_backend.divide( + paddle_backend.log(x), paddle_backend.log(base) + ).astype(x.dtype) return paddle.log2(x) +@with_supported_dtypes( + {"2.6.0 and below": ("float32", "float64", "complex")}, + backend_version, +) def log1p(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.Tensor: - if x.dtype in [ - paddle.int8, - paddle.int16, - paddle.int32, - paddle.int64, - paddle.uint8, - paddle.float16, - paddle.complex64, - paddle.complex128, - paddle.bool, - ]: - if paddle.is_complex(x): - return paddle_backend.log(x + 1) - return paddle.log1p(x.astype("float32")).astype(x.dtype) + if paddle.is_complex(x): + return paddle.complex(paddle.log1p(paddle.abs(x)), paddle.angle(x + 1)) return paddle.log1p(x) +@with_supported_dtypes( + { + "2.6.0 and below": ( + "float", + "int32", + "int64", + "complex", + ) + }, + backend_version, +) def isnan(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.Tensor: - if x.dtype in [ - paddle.int8, - paddle.int16, - paddle.uint8, - paddle.complex64, - paddle.complex128, - paddle.bool, - ]: - if paddle.is_complex(x): - return paddle.logical_or(paddle.isnan(x.real()), paddle.isnan(x.imag())) - return paddle.isnan(x.astype("float32")) + if paddle.is_complex(x): + return paddle.logical_or(paddle.isnan(x.real()), paddle.isnan(x.imag())) return paddle.isnan(x) +@with_unsupported_dtypes( + { + "2.6.0 and below": ( + "int8", + "uint8", + ) + }, + backend_version, +) def less( x1: Union[float, paddle.Tensor], x2: Union[float, paddle.Tensor], @@ -423,16 +330,19 @@ def less( out: Optional[paddle.Tensor] = None, ) -> paddle.Tensor: x1, x2, ret_dtype = _elementwise_helper(x1, x2) - if x1.dtype in [paddle.int8, paddle.uint8, paddle.complex64, paddle.complex128]: - if paddle.is_complex(x1): + if isinstance(x1, paddle.Tensor) and isinstance(x2, paddle.Tensor): + if paddle.is_complex(x1) and paddle.is_complex(x2): real = paddle.less_than(x1.real(), x2.real()) imag = paddle.less_than(x1.imag(), x2.imag()) return logical_and(real, imag) - return paddle.less_than(x1.astype("float32"), x2.astype("float32")) return paddle.less_than(x1, x2) +@with_supported_dtypes( + {"2.6.0 and below": ("bool", "int32", "int64", "float32", "float64", "complex")}, + backend_version, +) def multiply( x1: Union[float, paddle.Tensor], x2: Union[float, paddle.Tensor], @@ -441,48 +351,47 @@ def multiply( out: Optional[paddle.Tensor] = None, ) -> paddle.Tensor: x1, x2, ret_dtype = _elementwise_helper(x1, x2) - if x1.dtype in [paddle.int8, paddle.int16, paddle.uint8, paddle.float16]: - x1, x2 = x1.astype("float32"), x2.astype("float32") + if isinstance(x1, paddle.Tensor) and isinstance(x2, paddle.Tensor): + if paddle.is_complex(x1) or paddle.is_complex(x2): + a, b = x1.real(), x1.imag() + c, d = x2.real(), x2.imag() + real = a * c - b * d + imag = a * d + b * c + return paddle.complex(real, imag) + return paddle.multiply(x1, x2).astype(ret_dtype) -@with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("bool", "bfloat16")}}, +@with_supported_device_and_dtypes( + { + "2.6.0 and below": { + "cpu": ( + "float32", + "float64", + ) + } + }, backend_version, ) def cos(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.Tensor: - if x.dtype in [ - paddle.int8, - paddle.int16, - paddle.int32, - paddle.int64, - paddle.uint8, - paddle.float16, - ]: - ret_dtype = x.dtype - return paddle.cos(x.astype("float32")).astype(ret_dtype) - if paddle.is_complex(x): - re = x.real() - im = x.imag() - return paddle.complex( - paddle.cos(re) * paddle.cosh(im), - -paddle.sin(re) * paddle.sinh(im), - ) return paddle.cos(x) +@with_unsupported_dtypes({"2.6.0 and below": ("uint8", "float16")}, backend_version) def logical_not( x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None ) -> paddle.Tensor: - if x.dtype in [paddle.uint8, paddle.float16, paddle.complex64, paddle.complex128]: - if paddle.is_complex(x): - return paddle.logical_and( - paddle.logical_not(x.real()), paddle.logical_not(x.imag()) - ) - return paddle.logical_not(x.astype("float32")) + if paddle.is_complex(x): + return paddle.logical_and( + paddle.logical_not(x.real()), paddle.logical_not(x.imag()) + ) return paddle.logical_not(x) +@with_supported_dtypes( + {"2.6.0 and below": ("float32", "float64", "int32", "int64", "complex")}, + backend_version, +) def divide( x1: Union[float, paddle.Tensor], x2: Union[float, paddle.Tensor], @@ -490,16 +399,19 @@ def divide( *, out: Optional[paddle.Tensor] = None, ) -> paddle.Tensor: - x1, x2, ret_dtype = _elementwise_helper(x1, x2) - if x1.dtype in [paddle.float16, paddle.bfloat16]: - x1, x2 = x1.astype("float32"), x2.astype("float32") - if not (ivy.is_float_dtype(ret_dtype) or ivy.is_complex_dtype(ret_dtype)): - ret_dtype = ivy.default_float_dtype(as_native=True) - return (x1 / x2).astype(ret_dtype) + if isinstance(x1, paddle.Tensor) and isinstance(x2, paddle.Tensor): + if paddle.is_complex(x1) or paddle.is_complex(x2): + angle_value = paddle.angle(x1) - paddle.angle(x2) + abs_value = paddle.abs(x1) / paddle.abs(x2) + return paddle.complex( + abs_value * paddle.cos(angle_value), abs_value * paddle.sin(angle_value) + ) + x1, x2, _ = _elementwise_helper(x1, x2) + return x1 / x2 @with_supported_dtypes( - {"2.5.1 and below": ("float64", "float32", "int64", "int64")}, + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, backend_version, ) def fmin( @@ -514,6 +426,27 @@ def fmin( return paddle.fmin(x1, x2) +def _apply_for_real_and_imag(fn, x1, x2): + return fn( + fn(x1.real(), x2.real()), + fn(x1.imag(), x2.imag()), + ) + + +@with_supported_dtypes( + { + "2.6.0 and below": ( + "bool", + "float32", + "float64", + "int16", + "int32", + "int64", + "complex", + ) + }, + backend_version, +) def greater( x1: Union[float, paddle.Tensor], x2: Union[float, paddle.Tensor], @@ -522,16 +455,28 @@ def greater( out: Optional[paddle.Tensor] = None, ) -> paddle.Tensor: x1, x2, ret_dtype = _elementwise_helper(x1, x2) - if x1.dtype in [paddle.int8, paddle.uint8, paddle.complex64, paddle.complex128]: - if paddle.is_complex(x1): - if paddle.is_complex(x1): - real = paddle.greater_than(x1.real(), x2.real()) - imag = paddle.greater_than(x1.imag(), x2.imag()) - return paddle.logical_and(real, imag) - return paddle.greater_than(x1.astype("float32"), x2.astype("float32")) + if isinstance(x1, paddle.Tensor) and isinstance(x2, paddle.Tensor): + if paddle.is_complex(x1) and paddle.is_complex(x2): + real = paddle.greater_than(x1.real(), x2.real()) + imag = paddle.greater_than(x1.imag(), x2.imag()) + return paddle.logical_and(real, imag) return paddle.greater_than(x1, x2) +@with_supported_dtypes( + { + "2.6.0 and below": ( + "bool", + "float32", + "float64", + "int16", + "int32", + "int64", + "complex", + ) + }, + backend_version, +) def greater_equal( x1: Union[float, paddle.Tensor], x2: Union[float, paddle.Tensor], @@ -540,30 +485,27 @@ def greater_equal( out: Optional[paddle.Tensor] = None, ) -> paddle.Tensor: x1, x2, ret_dtype = _elementwise_helper(x1, x2) - if x1.dtype in [paddle.int8, paddle.uint8, paddle.complex64, paddle.complex128]: - if paddle.is_complex(x1): - if paddle.is_complex(x1): - real = paddle.greater_equal(x1.real(), x2.real()) - imag = paddle.greater_equal(x1.imag(), x2.imag()) - return paddle.logical_and(real, imag) - return paddle.greater_equal(x1.astype("float32"), x2.astype("float32")) + if isinstance(x1, paddle.Tensor) and isinstance(x2, paddle.Tensor): + if paddle.is_complex(x1) and paddle.is_complex(x2): + real = paddle.greater_equal(x1.real(), x2.real()) + imag = paddle.greater_equal(x1.imag(), x2.imag()) + return paddle.logical_and(real, imag) return paddle.greater_equal(x1, x2) -@with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("bool", "bfloat16")}}, +@with_supported_device_and_dtypes( + { + "2.6.0 and below": { + "cpu": ( + "float32", + "float64", + "complex", + ) + } + }, backend_version, ) def acos(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.Tensor: - if x.dtype in [ - paddle.int8, - paddle.int16, - paddle.int32, - paddle.int64, - paddle.uint8, - paddle.float16, - ]: - return paddle.acos(x.astype("float32")).astype(x.dtype) if paddle.is_complex(x): # From https://github.com/python/cpython/blob/39ef93edb9802dccdb6555d4209ac2e60875a011/Modules/cmathmodule.c#L178 # noqa s1 = paddle_backend.sqrt(1 - x) @@ -575,75 +517,67 @@ def acos(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle. return paddle.acos(x) -@with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("complex64", "complex128")}}, +@with_supported_device_and_dtypes( + { + "2.6.0 and below": { + "cpu": ("bool", "float32", "int32", "float64", "int64", "complex") + } + }, backend_version, ) def logical_xor( x1: paddle.Tensor, x2: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None ) -> paddle.Tensor: x1, x2, ret_dtype = _elementwise_helper(x1, x2) - if ret_dtype in [paddle.uint8, paddle.float16, paddle.complex64, paddle.complex128]: - # this logic works well when both inputs are complex but when one of them - # is casted from real to complex, the imaginary part is zero which messes - # with the XOR logic - # if paddle.is_complex(x1): - # return paddle.logical_xor( - # paddle.logical_xor(x1.real(), x2.real()), - # paddle.logical_xor(x1.imag(), x2.imag()), - # ) - return paddle.logical_xor(x1.astype("float32"), x2.astype("float32")) + if paddle.is_complex(x1): + x1 = paddle.cast(x1, paddle.bool) + x2 = paddle.cast(x2, paddle.bool) return paddle.logical_xor(x1, x2) -@with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("complex64", "complex128")}}, +@with_supported_device_and_dtypes( + { + "2.6.0 and below": { + "cpu": ("bool", "float32", "int32", "float64", "int64", "complex") + } + }, backend_version, ) def logical_and( x1: paddle.Tensor, x2: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None ) -> paddle.Tensor: x1, x2, ret_dtype = _elementwise_helper(x1, x2) - if ret_dtype in [paddle.uint8, paddle.float16, paddle.complex64, paddle.complex128]: - # this logic works well when both inputs are complex but when one of them - # is casted from real to complex, the imaginary part is zero which messes - # if paddle.is_complex(x1): - # return paddle.logical_and( - # paddle.logical_and(x1.real(), x2.real()), - # paddle.logical_and(x1.imag(), x2.imag()), - # ) - return paddle.logical_and(x1.astype("float32"), x2.astype("float32")) + if paddle.is_complex(x1): + return _apply_for_real_and_imag(paddle.logical_and, x1, x2) return paddle.logical_and(x1, x2) +@with_supported_dtypes( + {"2.6.0 and below": ("bool", "float32", "int32", "float64", "int64", "complex")}, + backend_version, +) def logical_or( x1: paddle.Tensor, x2: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None ) -> paddle.Tensor: x1, x2, ret_dtype = _elementwise_helper(x1, x2) - if ret_dtype in [paddle.uint8, paddle.float16, paddle.complex64, paddle.complex128]: - if paddle.is_complex(x1): - return paddle.logical_or( - paddle.logical_or(x1.real(), x2.real()), - paddle.logical_or(x1.imag(), x2.imag()), - ) - return paddle.logical_or(x1.astype("float32"), x2.astype("float32")) + if paddle.is_complex(x1): + return _apply_for_real_and_imag(paddle.logical_or, x1, x2) return paddle.logical_or(x1, x2) -@with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("bool", "bfloat16")}}, +@with_supported_device_and_dtypes( + { + "2.6.0 and below": { + "cpu": ( + "float32", + "float64", + "complex", + ) + } + }, backend_version, ) def acosh(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.Tensor: - if x.dtype in [ - paddle.int8, - paddle.int16, - paddle.int32, - paddle.int64, - paddle.uint8, - paddle.float16, - ]: - return paddle.acosh(x.astype("float32")).astype(x.dtype) if paddle.is_complex(x): # From https://github.com/python/cpython/blob/39ef93edb9802dccdb6555d4209ac2e60875a011/Modules/cmathmodule.c#L221 # noqa s1 = paddle_backend.sqrt(paddle.complex(x.real() - 1, x.imag())) @@ -655,20 +589,11 @@ def acosh(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle return paddle.acosh(x) -@with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("bool", "bfloat16")}}, +@with_supported_device_and_dtypes( + {"2.6.0 and below": {"cpu": ("float32", "float64", "complex")}}, backend_version, ) def sin(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.Tensor: - if x.dtype in [ - paddle.int8, - paddle.int16, - paddle.int32, - paddle.int64, - paddle.uint8, - paddle.float16, - ]: - return paddle.sin(x.astype("float32")).astype(x.dtype) if paddle.is_complex(x): re = x.real() im = x.imag() @@ -678,15 +603,13 @@ def sin(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.T return paddle.sin(x) +@with_supported_dtypes( + {"2.6.0 and below": ("float32", "float64", "int8", "int16", "int32", "int64")}, + backend_version, +) def negative( x: Union[float, paddle.Tensor], /, *, out: Optional[paddle.Tensor] = None ) -> paddle.Tensor: - if not isinstance(x, paddle.Tensor): - x = paddle.to_tensor( - x, dtype=ivy.default_dtype(item=x, as_native=True) - ).squeeze() - if x.dtype == paddle.bool: - return paddle.logical_not(x) return paddle.neg(x) @@ -700,22 +623,11 @@ def not_equal( return paddle.logical_not(paddle_backend.equal(x1, x2)) -@with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("bool", "bfloat16")}}, +@with_supported_device_and_dtypes( + {"2.6.0 and below": {"cpu": ("float32", "float64", "complex")}}, backend_version, ) -def tanh( - x: paddle.Tensor, /, *, complex_mode="jax", out: Optional[paddle.Tensor] = None -) -> paddle.Tensor: - if x.dtype in [ - paddle.int8, - paddle.int16, - paddle.int32, - paddle.int64, - paddle.uint8, - paddle.float16, - ]: - return paddle.tanh(x.astype("float32")).astype(x.dtype) +def tanh(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.Tensor: if paddle.is_complex(x): tanh_a = paddle.tanh(x.real()) tan_b = paddle.tan(x.imag()) @@ -729,6 +641,21 @@ def tanh( return paddle.tanh(x) +@with_supported_dtypes( + { + "2.6.0 and below": ( + "uint8", + "int8", + "int32", + "int64", + "float32", + "float64", + "float16", + "bfloat16", + ) + }, + backend_version, +) def floor_divide( x1: Union[float, paddle.Tensor], x2: Union[float, paddle.Tensor], @@ -737,11 +664,13 @@ def floor_divide( out: Optional[paddle.Tensor] = None, ) -> paddle.Tensor: x1, x2, ret_dtype = _elementwise_helper(x1, x2) - if x1.dtype in [paddle.int32, paddle.int64]: - return paddle.floor_divide(x1, x2) - return paddle_backend.floor(paddle_backend.divide(x1, x2)).astype(ret_dtype) + return paddle.floor_divide(x1, x2) +@with_supported_dtypes( + {"2.6.0 and below": ("bool", "uint8", "int8", "int16", "int32", "int64")}, + backend_version, +) def bitwise_or( x1: Union[int, bool, paddle.Tensor], x2: Union[int, bool, paddle.Tensor], @@ -753,21 +682,10 @@ def bitwise_or( return paddle.bitwise_or(x1, x2) -@with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("bool", "bfloat16")}}, - backend_version, +@with_supported_dtypes( + {"2.6.0 and below": ("float32", "float64", "complex")}, backend_version ) def sinh(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.Tensor: - if x.dtype in [ - paddle.int8, - paddle.int16, - paddle.int32, - paddle.int64, - paddle.uint8, - paddle.float16, - ]: - ret_dtype = x.dtype - return paddle.sinh(x.astype("float32")).astype(ret_dtype) if paddle.is_complex(x): re = x.real() im = x.imag() @@ -787,21 +705,27 @@ def positive( return x.clone() +@with_supported_dtypes( + { + "2.6.0 and below": ( + "int32", + "int64", + "float32", + "float64", + "complex", + ) + }, + backend_version, +) def square( x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None ) -> paddle.Tensor: - if x.dtype in [paddle.int32, paddle.int64, paddle.float32, paddle.float64]: - return paddle.square(x) - if paddle.is_complex(x): - return paddle.complex( - paddle.square(paddle.real(x)) - paddle.square(paddle.imag(x)), - 2.0 * paddle.real(x) * paddle.imag(x), - ) - return paddle_backend.pow(x, 2).astype(x.dtype) + return paddle.square(x) -@with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("bfloat16",)}}, backend_version +@with_supported_device_and_dtypes( + {"2.6.0 and below": {"cpu": ("float32", "float64", "int32", "int64", "complex")}}, + backend_version, ) def pow( x1: paddle.Tensor, @@ -811,14 +735,6 @@ def pow( out: Optional[paddle.Tensor] = None, ) -> paddle.Tensor: x1, x2, ret_dtype = _elementwise_helper(x1, x2) - if x1.dtype in [ - paddle.int8, - paddle.int16, - paddle.uint8, - paddle.float16, - paddle.bool, - ]: - return paddle.pow(x1.astype("float32"), x2.astype("float32")).astype(ret_dtype) if paddle.is_complex(x1): # https://math.stackexchange.com/questions/476968/complex-power-of-a-complex-number r = paddle.abs(x1) @@ -849,7 +765,7 @@ def _round_half_to_even(x): # This function aims to mimic the behavior of np.round similar to how tf.experimental.numpy.round does # noqa: E501 # Reference for tf.experimental.numpy.round:https://github.com/tensorflow/tensorflow/blob/v2.13.0/tensorflow/python/ops/numpy_ops/np_array_ops.py#L724 # noqa: E501 @with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("bfloat16", "float16", "complex")}}, backend_version + {"2.6.0 and below": {"cpu": ("bfloat16", "float16", "complex")}}, backend_version ) def round( x: paddle.Tensor, /, *, decimals: int = 0, out: Optional[paddle.Tensor] = None @@ -874,26 +790,16 @@ def round( return x.astype(dtype_) +@with_supported_dtypes( + {"2.6.0 and below": ("float32", "float64", "complex")}, backend_version +) def trunc(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.Tensor: - if x.dtype in [ - paddle.int8, - paddle.int16, - paddle.uint8, - paddle.float16, - paddle.complex64, - paddle.complex128, - paddle.bool, - ]: - if paddle.is_complex(x): - return paddle.complex(paddle.trunc(x.real()), paddle.trunc(x.imag())) - return paddle.trunc(x.astype("float32")).astype(x.dtype) + if paddle.is_complex(x): + return paddle.complex(paddle.trunc(x.real()), paddle.trunc(x.imag())) return paddle.trunc(x) -@with_supported_dtypes( - {"2.5.1 and below": ("float64", "float32")}, - backend_version, -) +@with_supported_dtypes({"2.6.0 and below": ("float64", "float32")}, backend_version) def trapz( y: paddle.Tensor, /, @@ -940,6 +846,10 @@ def trapz( return ret +@with_supported_device_and_dtypes( + {"2.6.0 and below": {"cpu": ("float32", "float64", "int32", "int64", "complex")}}, + backend_version, +) def abs( x: Union[float, paddle.Tensor], /, @@ -948,20 +858,11 @@ def abs( ) -> paddle.Tensor: if not isinstance(x, paddle.Tensor): x = paddle.to_tensor(x, dtype=ivy.default_dtype(item=x)).squeeze() - if x.dtype in [ - paddle.int8, - paddle.int16, - paddle.uint8, - paddle.float16, - paddle.bfloat16, - paddle.bool, - ]: - return paddle.abs(x.astype("float32")).astype(x.dtype) return paddle.abs(x) @with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("float16",)}}, backend_version + {"2.6.0 and below": {"cpu": ("float16",)}}, backend_version ) def logaddexp( x1: paddle.Tensor, x2: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None @@ -974,7 +875,7 @@ def logaddexp( @with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("float16",)}}, backend_version + {"2.6.0 and below": {"cpu": ("float16",)}}, backend_version ) def logaddexp2( x1: Union[paddle.Tensor, float, list, tuple], @@ -989,7 +890,7 @@ def logaddexp2( @with_unsupported_device_and_dtypes( { - "2.5.1 and below": { + "2.6.0 and below": { "cpu": ( "int8", "int16", @@ -1009,90 +910,75 @@ def real(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle. return paddle.real(x) -@with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("bool", "bfloat16")}}, +@with_supported_device_and_dtypes( + {"2.6.0 and below": {"cpu": ("float32", "float64", "complex")}}, backend_version, ) def tan(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.Tensor: - if x.dtype in [ - paddle.int8, - paddle.int16, - paddle.int32, - paddle.int64, - paddle.uint8, - paddle.float16, - ]: - ret_dtype = x.dtype - return paddle.tan(x.astype("float32")).astype(ret_dtype) if paddle.is_complex(x): tanh_ix = paddle_backend.tanh(paddle.complex(-x.imag(), x.real())) return paddle.complex(tanh_ix.imag(), -tanh_ix.real()) return paddle.tan(x) -@with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("bool", "bfloat16")}}, +@with_supported_device_and_dtypes( + {"2.6.0 and below": {"cpu": ("float32", "float64", "complex")}}, backend_version, ) def atan(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.Tensor: - if x.dtype in [ - paddle.int8, - paddle.int16, - paddle.int32, - paddle.int64, - paddle.uint8, - paddle.float16, - ]: - ret_dtype = x.dtype - return paddle.atan(x.astype("float32")).astype(ret_dtype) if x.dtype in [paddle.complex64, paddle.complex128]: atanh_iz = paddle_backend.atanh(paddle.complex(-x.imag(), x.real())) return paddle.complex(atanh_iz.imag(), -atanh_iz.real()) return paddle.atan(x) -@with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("complex64", "complex128", "bool")}}, +@with_supported_device_and_dtypes( + { + "2.6.0 and below": { + "cpu": ( + "int32", + "int64", + "float32", + "float64", + ) + } + }, backend_version, ) def atan2( x1: paddle.Tensor, x2: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None ) -> paddle.Tensor: x1, x2, ret_dtype = _elementwise_helper(x1, x2) - if x1.dtype in [paddle.int8, paddle.int16, paddle.uint8]: - x1, x2 = x1.astype("float32"), x2.astype("float32") return paddle.atan2(x1, x2).astype(ret_dtype) +@with_supported_dtypes( + {"2.6.0 and below": ("float32", "float64", "complex")}, + backend_version, +) def log(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.Tensor: - if x.dtype in [ - paddle.int8, - paddle.int16, - paddle.int32, - paddle.int64, - paddle.uint8, - paddle.float16, - paddle.complex64, - paddle.complex128, - paddle.bool, - ]: - if paddle.is_complex(x): - return paddle.complex(paddle.log(paddle.abs(x)), paddle.angle(x)) - return paddle.log(x.astype("float32")).astype(x.dtype) + if paddle.is_complex(x): + return paddle.complex(paddle.log(paddle.abs(x)), paddle.angle(x)) return paddle.log(x) +@with_supported_dtypes( + {"2.6.0 and below": ("int32", "int64", "float32", "float64", "complex")}, + backend_version, +) def exp(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.Tensor: - if x.dtype in [paddle.int32, paddle.int64, paddle.float32, paddle.float64]: - return paddle.exp(x) if paddle.is_complex(x): return paddle.multiply( paddle.exp(x.real()), paddle.complex(paddle.cos(x.imag()), paddle.sin(x.imag())), ) - return paddle_backend.pow(math.e, x).astype(x.dtype) + return paddle.exp(x) +@with_supported_dtypes( + {"2.6.0 and below": ("int32", "int64", "float32", "float64", "complex")}, + backend_version, +) def exp2( x: Union[paddle.Tensor, float, list, tuple], /, @@ -1103,6 +989,9 @@ def exp2( return ivy.pow(2, x) +@with_supported_dtypes( + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, backend_version +) def subtract( x1: Union[float, paddle.Tensor], x2: Union[float, paddle.Tensor], @@ -1112,16 +1001,14 @@ def subtract( out: Optional[paddle.Tensor] = None, ) -> paddle.Tensor: x1, x2, ret_dtype = _elementwise_helper(x1, x2) - if x1.dtype in [paddle.int8, paddle.uint8, paddle.float16, paddle.bool]: - x1, x2 = x1.astype("float32"), x2.astype("float32") if alpha not in (1, None): x2 = paddle_backend.multiply(x2, alpha) x1, x2 = ivy.promote_types_of_inputs(x1, x2) return paddle.subtract(x1, x2).astype(ret_dtype) -@with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("complex64", "complex128", "bool")}}, +@with_supported_device_and_dtypes( + {"2.6.0 and below": {"cpu": ("float32", "float64", "int32", "int64")}}, backend_version, ) def remainder( @@ -1143,26 +1030,14 @@ def remainder( diff = paddle_backend.subtract(res, res_floored).astype(res.dtype) return paddle_backend.round(paddle_backend.multiply(diff, x2)).astype(x1.dtype) - if x1.dtype in [paddle.int8, paddle.int16, paddle.uint8, paddle.float16]: - x1, x2 = x1.astype("float32"), x2.astype("float32") return paddle.remainder(x1, x2).astype(ret_dtype) -@with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("bool", "bfloat16")}}, +@with_supported_device_and_dtypes( + {"2.6.0 and below": {"cpu": ("float32", "float64", "complex")}}, backend_version, ) def atanh(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.Tensor: - if x.dtype in [ - paddle.int8, - paddle.int16, - paddle.int32, - paddle.int64, - paddle.uint8, - paddle.float16, - ]: - ret_dtype = x.dtype - return paddle.atanh(x.astype("float32")).astype(ret_dtype) if paddle.is_complex(x): return 0.5 * (paddle_backend.log(1 + x) - paddle_backend.log(1 - x)) return paddle.atanh(x) @@ -1198,17 +1073,15 @@ def bitwise_left_shift( # ------# -@with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("complex64", "complex128", "bool")}}, - backend_version, -) +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, backend_version) def erf(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.Tensor: - # TODO: add support for complex x, supported in scipy only atm - if x.dtype in [paddle.int8, paddle.int16, paddle.int32, paddle.int64, paddle.uint8]: - return paddle.erf(x.astype("float32")).astype(x.dtype) return paddle.erf(x) +@with_supported_dtypes( + {"2.6.0 and below": ("float32", "float64", "int32", "int64", "complex")}, + backend_version, +) def minimum( x1: Union[float, paddle.Tensor], x2: Union[float, paddle.Tensor], @@ -1218,19 +1091,14 @@ def minimum( out: Optional[paddle.Tensor] = None, ) -> paddle.Tensor: x1, x2, ret_dtype = _elementwise_helper(x1, x2) - if x1.dtype in [ - paddle.int8, - paddle.int16, - paddle.uint8, - paddle.float16, - paddle.complex64, - paddle.complex128, - paddle.bool, - ]: - if paddle.is_complex(x1): - use_where = True - else: - x1, x2 = x1.astype("float32"), x2.astype("float32") + if paddle.is_complex(x1): + real_comparison = paddle.real(x1) < paddle.real(x2) + imag_comparison = paddle_backend.logical_and( + paddle.real(x1) == paddle.real(x2), paddle.imag(x1) < paddle.imag(x2) + ) + return paddle_backend.where( + paddle_backend.logical_or(real_comparison, imag_comparison), x1, x2 + ).astype(ret_dtype) if use_where: return paddle_backend.where(paddle_backend.less_equal(x1, x2), x1, x2).astype( @@ -1240,6 +1108,10 @@ def minimum( return paddle.minimum(x1, x2).astype(ret_dtype) +@with_supported_dtypes( + {"2.6.0 and below": ("float32", "float64", "int32", "int64", "complex")}, + backend_version, +) def maximum( x1: Union[float, paddle.Tensor], x2: Union[float, paddle.Tensor], @@ -1249,19 +1121,14 @@ def maximum( out: Optional[paddle.Tensor] = None, ) -> paddle.Tensor: x1, x2, ret_dtype = _elementwise_helper(x1, x2) - if x1.dtype in [ - paddle.int8, - paddle.int16, - paddle.uint8, - paddle.float16, - paddle.complex64, - paddle.complex128, - paddle.bool, - ]: - if paddle.is_complex(x1): - use_where = True - else: - x1, x2 = x1.astype("float32"), x2.astype("float32") + if paddle.is_complex(x1): + real_comparison = paddle.real(x1) > paddle.real(x2) + imag_comparison = paddle_backend.logical_and( + paddle.real(x1) == paddle.real(x2), paddle.imag(x1) > paddle.imag(x2) + ) + return paddle_backend.where( + paddle_backend.logical_or(real_comparison, imag_comparison), x1, x2 + ).astype(ret_dtype) if use_where: return paddle_backend.where( paddle_backend.greater_equal(x1, x2), x1, x2 @@ -1269,27 +1136,36 @@ def maximum( return paddle.maximum(x1, x2).astype(ret_dtype) +@with_supported_dtypes( + { + "2.6.0 and below": ( + "float32", + "float64", + ) + }, + backend_version, +) def reciprocal( x: Union[float, paddle.Tensor], /, *, out: Optional[paddle.Tensor] = None ) -> paddle.Tensor: - if x.dtype in [paddle.float32, paddle.float64]: - return paddle.reciprocal(x) - return paddle_backend.divide(1, x) + return paddle.reciprocal(x) +@with_supported_dtypes( + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, backend_version +) def deg2rad( x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None ) -> paddle.Tensor: - if x.dtype in [paddle.int32, paddle.int64, paddle.bool]: - return paddle.deg2rad(x.astype("float32")).astype(x.dtype) return paddle.deg2rad(x) +@with_supported_dtypes( + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, backend_version +) def rad2deg( x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None ) -> paddle.Tensor: - if x.dtype in [paddle.int32, paddle.int64, paddle.bool]: - return paddle.rad2deg(x.astype("float32")).astype(x.dtype) return paddle.rad2deg(x) @@ -1312,6 +1188,10 @@ def isreal( return paddle.ones_like(x, dtype="bool") +@with_supported_dtypes( + {"2.6.0 and below": ("float32", "float64", "int32", "int64", "complex")}, + backend_version, +) def fmod( x1: paddle.Tensor, x2: paddle.Tensor, @@ -1324,10 +1204,7 @@ def fmod( return paddle_backend.where(paddle_backend.less(x1, 0), -res, res) -@with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("int8", "uint8")}}, - backend_version, -) +@with_supported_dtypes({"2.6.0 and below": ("int32", "int64")}, backend_version) def lcm( x1: paddle.Tensor, x2: paddle.Tensor, @@ -1335,18 +1212,19 @@ def lcm( *, out: Optional[paddle.Tensor] = None, ) -> paddle.Tensor: - x1_dtype = x1.dtype - x2_dtype = x2.dtype - if (x1_dtype, x2_dtype) == (paddle.int16, paddle.int16): - return paddle.cast( - paddle.lcm(paddle.cast(x1, paddle.int32), paddle.cast(x2, paddle.int32)), - paddle.int16, - ) - elif x1_dtype != x2_dtype: - x1, x2 = ivy.promote_types_of_inputs(x1, x2) return paddle.lcm(x1, x2) +@with_supported_dtypes( + { + "2.6.0 and below": ( + "float32", + "float64", + "complex", + ) + }, + backend_version, +) def angle( input: paddle.Tensor, /, @@ -1360,8 +1238,8 @@ def angle( return result -@with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("int8", "int16", "uint8")}}, backend_version +@with_supported_device_and_dtypes( + {"2.6.0 and below": {"cpu": ("int32", "int64")}}, backend_version ) def gcd( x1: Union[paddle.Tensor, int, list, tuple], @@ -1374,24 +1252,7 @@ def gcd( return paddle.gcd(x1, x2) -@with_unsupported_device_and_dtypes( - { - "2.5.1 and below": { - "cpu": ( - "int8", - "int16", - "int32", - "int64", - "uint8", - "float16", - "float32", - "float64", - "bool", - ) - } - }, - backend_version, -) +@with_supported_dtypes({"2.6.0 and below": ("complex",)}, backend_version) def imag( val: paddle.Tensor, /, diff --git a/ivy/functional/backends/paddle/experimental/__init__.py b/ivy/functional/backends/paddle/experimental/__init__.py index d50ca9bf1c253..b85b671859139 100644 --- a/ivy/functional/backends/paddle/experimental/__init__.py +++ b/ivy/functional/backends/paddle/experimental/__init__.py @@ -14,7 +14,6 @@ from .layers import * from .losses import * from .linear_algebra import * -from .losses import * from .manipulation import * from .norms import * from .random import * diff --git a/ivy/functional/backends/paddle/experimental/activations.py b/ivy/functional/backends/paddle/experimental/activations.py index d414972706b16..ca193162facc0 100644 --- a/ivy/functional/backends/paddle/experimental/activations.py +++ b/ivy/functional/backends/paddle/experimental/activations.py @@ -14,7 +14,7 @@ @with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("float16", "bfloat16")}}, backend_version + {"2.6.0 and below": {"cpu": ("float16", "bfloat16")}}, backend_version ) def logit( x: paddle.Tensor, @@ -44,7 +44,7 @@ def logit( ).cast(x.dtype) -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, backend_version) +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, backend_version) def thresholded_relu( x: paddle.Tensor, /, @@ -56,18 +56,21 @@ def thresholded_relu( @with_supported_dtypes( - {"2.5.1 and below": ("complex", "float32", "float64")}, backend_version + {"2.6.0 and below": ("complex", "float32", "float64")}, backend_version ) def relu6( x: paddle.Tensor, /, *, complex_mode="jax", out: Optional[paddle.Tensor] = None ) -> paddle.Tensor: if paddle.is_complex(x): - return paddle.complex(F.relu6(x.real()), F.relu6(x.imag())) + if x.real > 0 and x.real <= 6: + return x.astype(x.dtype) + else: + return paddle_backend.zeros_like(x).astype(x.dtype) return F.relu6(x) @with_supported_dtypes( - {"2.5.1 and below": ("complex", "float32", "float64")}, backend_version + {"2.6.0 and below": ("complex", "float32", "float64")}, backend_version ) def logsigmoid( input: paddle.Tensor, /, *, complex_mode="jax", out: Optional[paddle.Tensor] = None @@ -82,7 +85,7 @@ def logsigmoid( @with_supported_dtypes( - {"2.5.1 and below": ("complex", "float32", "float64")}, backend_version + {"2.6.0 and below": ("complex", "float32", "float64")}, backend_version ) def selu(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.Tensor: if paddle.is_complex(x): @@ -101,7 +104,7 @@ def selu(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle. @with_supported_dtypes( - {"2.5.1 and below": ("complex", "float32", "float64")}, backend_version + {"2.6.0 and below": ("complex", "float32", "float64")}, backend_version ) def silu(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.Tensor: if paddle.is_complex(x): @@ -110,7 +113,7 @@ def silu(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle. @with_supported_dtypes( - {"2.5.1 and below": ("complex", "float32", "float64")}, backend_version + {"2.6.0 and below": ("complex", "float32", "float64")}, backend_version ) def elu( x: paddle.Tensor, /, *, alpha: float = 1.0, out: Optional[paddle.Tensor] = None @@ -128,7 +131,7 @@ def elu( @with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("bfloat16", "float16")}}, backend_version + {"2.6.0 and below": {"cpu": ("bfloat16", "float16")}}, backend_version ) def hardtanh( x: paddle.Tensor, @@ -154,7 +157,7 @@ def hardtanh( @with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("bfloat16", "float16")}}, backend_version + {"2.6.0 and below": {"cpu": ("bfloat16", "float16")}}, backend_version ) def tanhshrink( x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None @@ -167,7 +170,28 @@ def tanhshrink( @with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("bfloat16", "float16")}}, backend_version + {"2.6.0 and below": {"cpu": ("bfloat16", "float16")}}, backend_version +) +def threshold( + x: paddle.Tensor, + /, + *, + threshold: float, + value: float, + out: Optional[paddle.Tensor] = None, +) -> paddle.Tensor: + if x.dtype in [paddle.float32, paddle.float64]: + return paddle_backend.where(paddle_backend.greater(x, threshold), x, value) + if paddle.is_complex(x): + return paddle_backend.where(paddle_backend.greater(x, threshold), x, value) + x = x.cast("float32") + return paddle_backend.where(paddle_backend.greater(x, threshold), x, value).cast( + x.dtype + ) + + +@with_unsupported_device_and_dtypes( + {"2.6.0 and below": {"cpu": ("bfloat16", "float16")}}, backend_version ) def softshrink( x: paddle.Tensor, /, *, lambd: float = 0.5, out: Optional[paddle.Tensor] = None @@ -183,7 +207,7 @@ def softshrink( @with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("bfloat16", "float16")}}, backend_version + {"2.6.0 and below": {"cpu": ("bfloat16", "float16")}}, backend_version ) def celu( x: paddle.Tensor, @@ -198,7 +222,7 @@ def celu( @with_supported_device_and_dtypes( { - "2.5.1 and below": { + "2.6.0 and below": { "cpu": ("float32", "float64"), "gpu": ("uint16", "float16", "float32", "float64"), } @@ -217,7 +241,7 @@ def scaled_tanh( @with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("float16", "bfloat16")}}, + {"2.6.0 and below": {"cpu": ("float16", "bfloat16")}}, backend_version, ) def hardshrink( @@ -231,3 +255,10 @@ def hardshrink( F.hardshrink(x.img(), threshold=lambd), ) return F.hardshrink(x.cast("float32"), threshold=lambd).cast(x.dtype) + + +@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, backend_version) +def hardsilu( + x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None +) -> paddle.Tensor: + return F.hardswish(x) diff --git a/ivy/functional/backends/paddle/experimental/creation.py b/ivy/functional/backends/paddle/experimental/creation.py index 6f7d33f083002..dda4e9820a368 100644 --- a/ivy/functional/backends/paddle/experimental/creation.py +++ b/ivy/functional/backends/paddle/experimental/creation.py @@ -103,7 +103,7 @@ def unsorted_segment_min( segment_ids: paddle.Tensor, num_segments: Union[int, paddle.Tensor], ) -> paddle.Tensor: - ivy.utils.assertions.check_unsorted_segment_min_valid_params( + ivy.utils.assertions.check_unsorted_segment_valid_params( data, segment_ids, num_segments ) if data.dtype == paddle.float32: @@ -115,7 +115,7 @@ def unsorted_segment_min( elif data.dtype == paddle.int64: init_val = 9223372036854775807 else: - raise ValueError("Unsupported data type") + raise TypeError("Unsupported data type") # Using paddle.full is causing integer overflow for int64 res = paddle.empty((num_segments,) + tuple(data.shape[1:]), dtype=data.dtype) res[:] = init_val @@ -156,7 +156,7 @@ def unsorted_segment_sum( # check should be same # Might require to change the assertion function name to # check_unsorted_segment_valid_params - ivy.utils.assertions.check_unsorted_segment_min_valid_params( + ivy.utils.assertions.check_unsorted_segment_valid_params( data, segment_ids, num_segments ) @@ -183,7 +183,7 @@ def unsorted_segment_sum( @with_unsupported_device_and_dtypes( { - "2.5.1 and below": { + "2.6.0 and below": { "cpu": ( "int8", "int16", @@ -225,9 +225,39 @@ def mel_weight_matrix( return paddle.transpose(mel_mat, (1, 0)) +def unsorted_segment_mean( + data: paddle.Tensor, + segment_ids: paddle.Tensor, + num_segments: Union[int, paddle.Tensor], +) -> paddle.Tensor: + ivy.utils.assertions.check_unsorted_segment_valid_params( + data, segment_ids, num_segments + ) + + # Sum computation in paddle does not support int32, so needs to + # be converted to float32 + needs_conv = False + if data.dtype == paddle.int32: + data = paddle.cast(data, "float32") + needs_conv = True + + res = paddle.zeros((num_segments,) + tuple(data.shape[1:]), dtype=data.dtype) + + count = paddle.bincount(segment_ids) + count = paddle.where(count > 0, count, paddle.to_tensor([1], dtype="int32")) + res = unsorted_segment_sum(data, segment_ids, num_segments) + res = res / paddle.reshape(count, (-1, 1)) + + # condition for converting float32 back to int32 + if needs_conv is True: + res = paddle.cast(res, "int32") + + return res + + @with_unsupported_device_and_dtypes( { - "2.5.1 and below": { + "2.6.0 and below": { "cpu": ("float16", "int8", "int16", "uint8", "complex", "bool") } }, diff --git a/ivy/functional/backends/paddle/experimental/elementwise.py b/ivy/functional/backends/paddle/experimental/elementwise.py index 0f4e6610ac915..c26898376ea69 100644 --- a/ivy/functional/backends/paddle/experimental/elementwise.py +++ b/ivy/functional/backends/paddle/experimental/elementwise.py @@ -20,7 +20,7 @@ @with_supported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "float32", "float64", "int32", @@ -42,7 +42,7 @@ def amax( @with_supported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "float32", "float64", "int32", @@ -63,7 +63,7 @@ def amin( @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64")}, + {"2.6.0 and below": ("float32", "float64")}, backend_version, ) def lgamma( @@ -73,7 +73,7 @@ def lgamma( @with_supported_dtypes( - {"2.5.1 and below": ("float64", "float32", "int32", "int64")}, + {"2.6.0 and below": ("float64", "float32", "int32", "int64")}, backend_version, ) def fmax( @@ -89,7 +89,7 @@ def fmax( @with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("float16",)}}, backend_version + {"2.6.0 and below": {"cpu": ("float16",)}}, backend_version ) def sinc(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.Tensor: y = ivy.pi * paddle.where(x == 0, paddle.to_tensor(1.0e-20, dtype=x.dtype), x) @@ -137,6 +137,9 @@ def ldexp( return ivy.astype(ret, out_dtype, copy=False) +@with_unsupported_device_and_dtypes( + {"2.6.0 and below": {"cpu": ("float16", "bfloat16")}}, backend_version +) def copysign( x1: Union[paddle.Tensor, Number], x2: Union[paddle.Tensor, Number], @@ -153,7 +156,8 @@ def copysign( @with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("uint8", "int8", "int16", "float16")}}, backend_version + {"2.6.0 and below": {"cpu": ("uint8", "int8", "int16", "float16")}}, + backend_version, ) def nansum( x: paddle.Tensor, @@ -161,7 +165,7 @@ def nansum( *, axis: Optional[Union[Tuple[int, ...], int]] = None, dtype: Optional[paddle.dtype] = None, - keepdims: Optional[bool] = False, + keepdims: bool = False, out: Optional[paddle.Tensor] = None, ) -> paddle.Tensor: result = paddle.nansum(x, axis=axis, dtype=dtype, keepdim=keepdims) @@ -171,23 +175,23 @@ def nansum( @with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("float16",)}}, backend_version + {"2.6.0 and below": {"cpu": ("float16",)}}, backend_version ) def isclose( a: paddle.Tensor, b: paddle.Tensor, /, *, - rtol: Optional[float] = 1e-05, - atol: Optional[float] = 1e-08, - equal_nan: Optional[bool] = False, + rtol: float = 1e-05, + atol: float = 1e-08, + equal_nan: bool = False, out: Optional[paddle.Tensor] = None, ) -> paddle.Tensor: return paddle.isclose(a, b, rtol=rtol, atol=atol, equal_nan=equal_nan) @with_unsupported_dtypes( - {"2.5.1 and below": ("float16", "int16", "int8", "uint8")}, backend_version + {"2.6.0 and below": ("float16", "int16", "int8", "uint8")}, backend_version ) def diff( x: Union[paddle.Tensor, list, tuple], @@ -213,6 +217,9 @@ def _tensor(val): ) +@with_unsupported_device_and_dtypes( + {"2.6.0 and below": {"cpu": ("float16",)}}, backend_version +) def signbit( x: Union[paddle.Tensor, float, int, list, tuple], /, @@ -236,7 +243,7 @@ def hypot( @with_unsupported_device_and_dtypes( { - "2.5.1 and below": { + "2.6.0 and below": { "cpu": ( "int8", "int16", @@ -257,14 +264,15 @@ def allclose( x2: paddle.Tensor, /, *, - rtol: Optional[float] = 1e-05, - atol: Optional[float] = 1e-08, - equal_nan: Optional[bool] = False, + rtol: float = 1e-05, + atol: float = 1e-08, + equal_nan: bool = False, out: Optional[paddle.Tensor] = None, ) -> bool: return paddle.allclose(x1, x2, rtol=rtol, atol=atol, equal_nan=equal_nan).squeeze(0) +@with_unsupported_dtypes({"2.6.0 and below": ("float16",)}, backend_version) def fix( x: paddle.Tensor, /, @@ -276,7 +284,7 @@ def fix( @with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("float16",)}}, backend_version + {"2.6.0 and below": {"cpu": ("float16",)}}, backend_version ) def nextafter( x1: paddle.Tensor, @@ -317,7 +325,7 @@ def nextafter( @with_unsupported_device_and_dtypes( { - "2.5.1 and below": { + "2.6.0 and below": { "cpu": ( "int8", "int16", @@ -347,7 +355,7 @@ def zeta( if q.dtype == paddle.float32 else paddle.to_tensor(8.0, dtype="float64") ) - assert M <= len(_BERNOULLI_COEFS) + assert len(_BERNOULLI_COEFS) >= M k = paddle.unsqueeze(ivy.arange(N, dtype=q.dtype), tuple(range(q.ndim))) S = paddle.sum((a_ + k) ** -s_, -1) Q = ivy.divide((q + N) ** (1 - x), x - 1) @@ -384,7 +392,7 @@ def _normalize_axis_tuple(axis: Union[int, list, tuple], ndim: int) -> Tuple[int axis = [operator.index(axis)] except TypeError: pass - axis = tuple([_normalize_axis_index(ax, ndim) for ax in axis]) + axis = tuple(_normalize_axis_index(ax, ndim) for ax in axis) if len(set(axis)) != len(axis): raise ValueError("repeated axis") return axis @@ -395,16 +403,16 @@ def _np_ndim(x): @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64")}, + {"2.6.0 and below": ("float32", "float64")}, backend_version, ) def gradient( x: paddle.Tensor, /, *, - spacing: Optional[Union[int, list, tuple]] = 1, + spacing: Union[int, list, tuple] = 1, axis: Optional[Union[int, list, tuple]] = None, - edge_order: Optional[int] = 1, + edge_order: int = 1, ) -> Union[paddle.Tensor, List[paddle.Tensor]]: """Https://github.com/numpy/numpy/blob/v1.24.3/numpy/lib/ function_base.py#L969-L1312.""" @@ -643,7 +651,7 @@ def count_nonzero( /, *, axis: Optional[Union[int, list, tuple]] = None, - keepdims: Optional[bool] = False, + keepdims: bool = False, dtype: Optional[paddle.dtype] = None, out: Optional[paddle.Tensor] = None, ) -> paddle.Tensor: @@ -653,7 +661,7 @@ def count_nonzero( @with_supported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "complex64", "complex128", "float32", @@ -668,11 +676,22 @@ def conj(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle. return paddle.conj(x) +@with_supported_dtypes( + { + "2.5.0 and below": ( + "float32", + "float64", + ) + }, + backend_version, +) def modf( x: paddle.Tensor, /, *, out: Optional[Tuple[paddle.Tensor, paddle.Tensor]] = None ) -> Tuple[paddle.Tensor, paddle.Tensor]: with ivy.ArrayMode(False): - return paddle.modf(x, out=out) + integer_part = paddle.floor(x) + fractional_part = x - integer_part + return fractional_part, integer_part @with_supported_dtypes( @@ -755,13 +774,14 @@ def _EvaluatePolynomial(x, coefficients): def _is_scalar(x): - """ - Determines if the given tensor is a scalar. + """Determines if the given tensor is a scalar. - Args: + Args + ---- - x (paddle.Tensor): Input tensor. - Returns: + Return + ------ - bool: True if the tensor is a scalar, False otherwise. """ return x.size == 1 and x.dim() == 0 and tuple(x.shape) == () @@ -770,7 +790,7 @@ def _is_scalar(x): # TODO: Repalce once native function becomes available. # Compute an approximation of the error function complement (1 - erf(x)). @with_supported_dtypes( - {"2.5.1 and below": ("float64", "float32")}, + {"2.6.0 and below": ("float64", "float32")}, backend_version, ) def erfc(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.Tensor: @@ -809,3 +829,13 @@ def is_pos_inf(op): result = paddle.squeeze(result, axis=-1) return result + + +@with_supported_dtypes( + {"2.6.0 and below": ("float32", "float64")}, + backend_version, +) +def erfinv( + x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None +) -> paddle.Tensor: + return paddle.erfinv(x) diff --git a/ivy/functional/backends/paddle/experimental/layers.py b/ivy/functional/backends/paddle/experimental/layers.py index 2cfa153cac992..a1942a5b4d120 100644 --- a/ivy/functional/backends/paddle/experimental/layers.py +++ b/ivy/functional/backends/paddle/experimental/layers.py @@ -30,7 +30,7 @@ def _determine_depth_max_pooling(x, kernel, strides, dims, data_format="channel_ @with_supported_device_and_dtypes( { - "2.5.1 and below": { + "2.6.0 and below": { "cpu": ("float32", "float64"), "gpu": ("bfloat16", "float16", "float32", "float64"), } @@ -97,7 +97,7 @@ def max_pool1d( @with_supported_device_and_dtypes( { - "2.5.1 and below": { + "2.6.0 and below": { "cpu": ("float32", "float64"), "gpu": ("bfloat16", "float16", "float32", "float64"), } @@ -168,7 +168,7 @@ def max_pool2d( @with_supported_device_and_dtypes( { - "2.5.1 and below": { + "2.6.0 and below": { "cpu": ("float32", "float64"), "gpu": ("bfloat16", "float16", "float32", "float64"), } @@ -243,12 +243,13 @@ def avg_pool1d( x: paddle.Tensor, kernel: Union[int, Tuple[int]], strides: Union[int, Tuple[int]], - padding: str, + padding: Union[str, int, List[Tuple[int, int]]], /, *, data_format: str = "NWC", count_include_pad: bool = False, ceil_mode: bool = False, + divisor_override: Optional[int] = None, out: Optional[paddle.Tensor] = None, ) -> paddle.Tensor: raise IvyNotImplementedException() @@ -258,7 +259,7 @@ def avg_pool2d( x: paddle.Tensor, kernel: Union[int, Tuple[int], Tuple[int, int]], strides: Union[int, Tuple[int], Tuple[int, int]], - padding: str, + padding: Union[str, int, List[Tuple[int, int]]], /, *, data_format: str = "NHWC", @@ -274,7 +275,7 @@ def avg_pool3d( x: paddle.Tensor, kernel: Union[int, Tuple[int], Tuple[int, int, int]], strides: Union[int, Tuple[int], Tuple[int, int, int]], - padding: str, + padding: Union[str, int, List[Tuple[int, int]]], /, *, data_format: str = "NDHWC", @@ -300,7 +301,7 @@ def dct( @with_unsupported_dtypes( - {"2.5.1 and below": ("bfloat16", "bool", "float16")}, backend_version + {"2.6.0 and below": ("bfloat16", "bool", "float16")}, backend_version ) def fft( x: paddle.Tensor, @@ -308,7 +309,7 @@ def fft( /, *, norm: Optional[str] = "backward", - n: Union[int, Tuple[int]] = None, + n: Optional[Union[int, Tuple[int]]] = None, out: Optional[paddle.Tensor] = None, ) -> paddle.Tensor: if not isinstance(dim, int): @@ -344,7 +345,7 @@ def fft( @with_supported_device_and_dtypes( { - "2.5.1 and below": { + "2.6.0 and below": { "cpu": ("bfloat16", "float32", "float64"), "gpu": ("bfloat16", "float16", "float32", "float64"), } @@ -366,7 +367,7 @@ def dropout1d( @with_supported_device_and_dtypes( { - "2.5.1 and below": { + "2.6.0 and below": { "cpu": ("bfloat16", "float32", "float64"), "gpu": ("bfloat16", "float16", "float32", "float64"), } @@ -388,7 +389,7 @@ def dropout2d( @with_supported_device_and_dtypes( { - "2.5.1 and below": { + "2.6.0 and below": { "cpu": ("bfloat16", "float32", "float64"), "gpu": ("bfloat16", "float16", "float32", "float64"), } @@ -413,7 +414,7 @@ def ifft( dim: int, *, norm: Optional[str] = "backward", - n: Union[int, Tuple[int]] = None, + n: Optional[Union[int, Tuple[int]]] = None, out: Optional[paddle.Tensor] = None, ) -> paddle.Tensor: raise IvyNotImplementedException() @@ -421,7 +422,7 @@ def ifft( @with_supported_device_and_dtypes( { - "2.5.1 and below": { + "2.6.0 and below": { "cpu": ("int8", "float32", "float64"), "gpu": ("int8", "bfloat16", "float16", "float32", "float64"), }, @@ -464,7 +465,7 @@ def interpolate( mode: Optional[Literal["linear", "bilinear", "trilinear"]] = "linear", scale_factor: Optional[Union[Sequence[int], int]] = None, recompute_scale_factor: Optional[bool] = None, - align_corners: Optional[bool] = None, + align_corners: bool = False, antialias: Optional[bool] = False, out: Optional[paddle.Tensor] = None, ): @@ -513,7 +514,7 @@ def rfft( @with_unsupported_dtypes( - {"2.5.1 and below": ("bfloat16", "float16", "complex64", "complex128", "bool")}, + {"2.6.0 and below": ("bfloat16", "float16", "complex64", "complex128", "bool")}, backend_version, ) def rfftn( @@ -530,7 +531,7 @@ def rfftn( @with_supported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "complex64", "complex128", ) @@ -552,7 +553,7 @@ def fft2( # stft @with_supported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "complex64", "complex128", ) @@ -643,7 +644,7 @@ def stft_1D(signals, frame_length, frame_step, fft_length, pad_end): windowed_frame = paddle.to_tensor(windowed_frame) fft_frame = fft(windowed_frame, -1) - slit = int((fft_length // 2 + 1)) + slit = int(fft_length // 2 + 1) stft_result.append(fft_frame[..., 0:slit]) stft = paddle.to_tensor(stft_result) diff --git a/ivy/functional/backends/paddle/experimental/linear_algebra.py b/ivy/functional/backends/paddle/experimental/linear_algebra.py index d402779d15f5f..df21c54ab3a69 100644 --- a/ivy/functional/backends/paddle/experimental/linear_algebra.py +++ b/ivy/functional/backends/paddle/experimental/linear_algebra.py @@ -13,7 +13,7 @@ @with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("int8", "int16", "uint8", "float16", "bfloat16")}}, + {"2.6.0 and below": {"cpu": ("int8", "int16", "uint8", "float16", "bfloat16")}}, backend_version, ) def diagflat( @@ -47,7 +47,7 @@ def diagflat( @with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("int8", "uint8", "int16")}}, backend_version + {"2.6.0 and below": {"cpu": ("int8", "uint8", "int16")}}, backend_version ) def kron( a: paddle.Tensor, @@ -91,7 +91,8 @@ def adjoint( @with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("int8", "uint8", "int16", "float16")}}, backend_version + {"2.6.0 and below": {"cpu": ("int8", "uint8", "int16", "float16")}}, + backend_version, ) def solve_triangular( x1: paddle.Tensor, @@ -130,9 +131,20 @@ def lu_factor( raise IvyNotImplementedException() +def lu_solve( + lu: paddle.Tensor, + p: paddle.Tensor, + b: paddle.Tensor, + /, + *, + out: Optional[paddle.Tensor] = None, +) -> paddle.Tensor: + raise IvyNotImplementedException() + + @with_supported_device_and_dtypes( { - "2.5.1 and below": { + "2.6.0 and below": { "cpu": ( "float32", "float64", @@ -167,7 +179,7 @@ def dot( @with_supported_device_and_dtypes( { - "2.5.1 and below": { + "2.6.0 and below": { "cpu": ( "float32", "float64", diff --git a/ivy/functional/backends/paddle/experimental/losses.py b/ivy/functional/backends/paddle/experimental/losses.py index d2ec322ea218e..ebb90d24898aa 100644 --- a/ivy/functional/backends/paddle/experimental/losses.py +++ b/ivy/functional/backends/paddle/experimental/losses.py @@ -14,7 +14,7 @@ @with_unsupported_device_and_dtypes( { - "2.5.1 and below": { + "2.6.0 and below": { "cpu": ( "float16", "int8", @@ -42,7 +42,7 @@ def l1_loss( @with_unsupported_device_and_dtypes( { - "2.5.1 and below": { + "2.6.0 and below": { "cpu": ( "int8", "int16", @@ -66,13 +66,13 @@ def smooth_l1_loss( reduction: Optional[str] = "mean", ) -> paddle.Tensor: return paddle.nn.functional.smooth_l1_loss( - input, target, reduction=reduction, beta=beta + input, target, reduction=reduction, delta=beta ) @with_unsupported_device_and_dtypes( { - "2.5.1 and below": { + "2.6.0 and below": { "cpu": ( "float16", "int8", @@ -100,7 +100,7 @@ def huber_loss( @with_unsupported_device_and_dtypes( { - "2.5.1 and below": { + "2.6.0 and below": { "cpu": ( "float16", "int8", @@ -127,7 +127,7 @@ def soft_margin_loss( @with_supported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("float32", "float64")}}, + {"2.6.0 and below": {"cpu": ("float32", "float64")}}, backend_version, ) def kl_div( @@ -165,29 +165,29 @@ def _validate_poisson_nll_params( for parameter, name in zip([input, label], ["input", "label"]): if parameter.dtype not in allowed_dtypes: raise ValueError( - "The dtype of '%s' in poisson_nll_loss should be one of %s, but" - " received %s." % (name, allowed_dtypes, parameter.dtype) + f"The dtype of '{name}' in poisson_nll_loss should be one of" + f" {allowed_dtypes}, but received {parameter.dtype}." ) # Validate epsilon if epsilon <= 0: raise ValueError( "The value of `epsilon` in poisson_nll_loss should be positive, but" - " received %f, which is not allowed" % epsilon + f" received {epsilon}, which is not allowed." ) # Validate reduction if reduction not in ["sum", "mean", "none"]: raise ValueError( "The value of 'reduction' in poisson_nll_loss should be 'sum', 'mean' or" - " 'none', but received %s, which is not allowed." % reduction + f" 'none', but received {reduction}, which is not allowed." ) # Validate shape if input.shape != label.shape: raise ValueError( - "The shape of 'input' (%s) must be the same as the shape of 'label' (%s)." - % (input.shape, label.shape) + f"The shape of 'input' ({input.shape}) must be the same as the shape of" + f" 'label' ({label.shape})." ) return True @@ -195,7 +195,7 @@ def _validate_poisson_nll_params( @with_supported_device_and_dtypes( { - "2.5.1 and below": { + "2.6.0 and below": { "cpu": ("float32", "float64"), "gpu": ("bfloat16", "float16", "float32", "float64"), } @@ -239,3 +239,27 @@ def poisson_nll_loss( cond = paddle.logical_and(target_arr >= zeroes, target_arr <= ones) loss = loss + paddle.where(cond, zeroes, striling_approx_term) return _apply_loss_reduction(loss, reduction) + + +@with_supported_device_and_dtypes( + { + "2.6.0 and below": { + "cpu": ("float32", "float64"), + "gpu": ("float16", "float32", "float64"), + } + }, + backend_version, +) +def hinge_embedding_loss( + input: paddle.Tensor, + target: paddle.Tensor, + *, + margin: float = 1.0, + reduction: str = "mean", +) -> paddle.Tensor: + return paddle.nn.functional.hinge_embedding_loss( + input, + target, + margin=margin, + reduction=reduction, + ) diff --git a/ivy/functional/backends/paddle/experimental/manipulation.py b/ivy/functional/backends/paddle/experimental/manipulation.py index 62b7486b0d215..8c7f314743d64 100644 --- a/ivy/functional/backends/paddle/experimental/manipulation.py +++ b/ivy/functional/backends/paddle/experimental/manipulation.py @@ -1,5 +1,6 @@ from collections import namedtuple from typing import ( + Iterable, Optional, Union, Sequence, @@ -19,6 +20,7 @@ with_unsupported_device_and_dtypes, with_supported_dtypes, with_unsupported_dtypes, + handle_out_argument, ) import paddle import ivy @@ -94,7 +96,7 @@ @with_unsupported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "int16", "int8", "uint8", @@ -120,26 +122,34 @@ def moveaxis( @with_supported_dtypes( - {"2.5.1 and below": ("float16", "float32", "float64", "int32", "int64")}, + {"2.6.0 and below": ("float16", "float32", "float64", "int32", "int64")}, backend_version, ) def pad( input: paddle.Tensor, - pad_width: Union[Sequence[Sequence[int]], paddle.Tensor, int], + pad_width: Union[Iterable[Tuple[int]], int], /, *, mode: Union[ Literal[ "constant", + "dilated", "edge", + "linear_ramp", + "maximum", + "mean", + "median", + "minimum", "reflect", + "symmetric", "wrap", + "empty", ], Callable, ] = "constant", - stat_length: Union[Sequence[paddle.Tensor], int] = 1, - constant_values: Number = 0, - end_values: Number = 0, + stat_length: Union[Iterable[Tuple[int]], int] = 1, + constant_values: Union[Iterable[Tuple[Number]], Number] = 0, + end_values: Union[Iterable[Tuple[Number]], Number] = 0, reflect_type: Literal["even", "odd"] = "even", **kwargs: Optional[Any], ) -> paddle.Tensor: @@ -178,7 +188,7 @@ def pad( @with_unsupported_device_and_dtypes( { - "2.5.1 and below": { + "2.6.0 and below": { "cpu": ( "int8", "int16", @@ -203,7 +213,7 @@ def heaviside( @with_unsupported_dtypes( - {"2.5.1 and below": ("bfloat16", "float16", "int16", "int8", "uint8")}, + {"2.6.0 and below": ("bfloat16", "float16", "int16", "int8", "uint8")}, backend_version, ) def flipud( @@ -228,7 +238,7 @@ def vstack( @with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("int16", "bfloat16")}}, + {"2.6.0 and below": {"cpu": ("int16", "bfloat16")}}, backend_version, ) def hstack( @@ -245,7 +255,7 @@ def hstack( @with_unsupported_dtypes( - {"2.5.1 and below": ("bfloat16", "float16", "int16", "int8", "uint8")}, + {"2.6.0 and below": ("bfloat16", "float16", "int16", "int8", "uint8")}, backend_version, ) def rot90( @@ -261,7 +271,7 @@ def rot90( @with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("complex64", "complex128")}}, + {"2.6.0 and below": {"cpu": ("complex64", "complex128")}}, backend_version, ) def top_k( @@ -288,7 +298,7 @@ def top_k( @with_unsupported_dtypes( - {"2.5.1 and below": ("bfloat16", "float16", "int16", "int8", "uint8")}, + {"2.6.0 and below": ("bfloat16", "float16", "int16", "int8", "uint8")}, backend_version, ) def fliplr( @@ -301,6 +311,10 @@ def fliplr( return paddle.flip(m, axis=1) +@with_unsupported_dtypes( + {"2.6.0 and below": ("bfloat16", "float16")}, + backend_version, +) def i0( x: paddle.Tensor, /, @@ -456,7 +470,7 @@ def atleast_2d( @with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("float16",)}}, + {"2.6.0 and below": {"cpu": ("float16",)}}, backend_version, ) def atleast_3d( @@ -481,7 +495,7 @@ def atleast_3d( @with_unsupported_dtypes( - {"2.5.1 and below": ("bfloat16", "bool", "float16", "int16", "int8", "uint8")}, + {"2.6.0 and below": ("bfloat16", "bool", "float16", "int16", "int8", "uint8")}, backend_version, ) def take_along_axis( @@ -603,7 +617,7 @@ def concat_from_sequence( @with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("int8", "int16", "uint8")}}, backend_version + {"2.6.0 and below": {"cpu": ("int8", "int16", "uint8")}}, backend_version ) def unique_consecutive( x: paddle.Tensor, @@ -666,7 +680,8 @@ def unique_consecutive( @with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("int8", "int16", "uint8", "float16")}}, backend_version + {"2.6.0 and below": {"cpu": ("int8", "int16", "uint8", "float16")}}, + backend_version, ) def fill_diagonal( a: paddle.Tensor, @@ -731,7 +746,7 @@ def _take_with_axis( @with_supported_device_and_dtypes( { - "2.5.1 and below": { + "2.6.0 and below": { "cpu": ("int64", "float64", "int32", "uint8", "float32", "bool") } }, @@ -764,7 +779,7 @@ def take( if ivy.exists(axis): try: x_shape = x.shape[axis] - except Exception: + except Exception as e: rank = len(x.shape) raise IndexError( "(OutOfRange) Attr(axis) is out of range, " @@ -774,7 +789,7 @@ def take( "(0 - input_dim.size()) == true, " "but received axis < input_dim.size() && axis >= " "(0 - input_dim.size()):0 != true:1.]" - ) + ) from e else: x_shape = paddle.prod(paddle.to_tensor(x.shape)) @@ -868,7 +883,7 @@ def trim_zeros(a: paddle.Tensor, /, *, trim: Optional[str] = "bf") -> paddle.Ten @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, backend_version + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, backend_version ) def put_along_axis( arr: paddle.Tensor, @@ -895,3 +910,30 @@ def put_along_axis( "sum", "mul", ] + + +@with_supported_dtypes( + { + "2.6.0 and below": ( + "int32", + "int64", + "float64", + "complex128", + "float32", + "complex64", + "bool", + ) + }, + backend_version, +) +@handle_out_argument +def unflatten( + x: paddle.Tensor, + /, + shape: Tuple[int] = None, + dim: int = 0, + *, + out: Optional[paddle.Tensor] = None, +) -> paddle.Tensor: + res = paddle.unflatten(x, dim, shape) + return res diff --git a/ivy/functional/backends/paddle/experimental/norms.py b/ivy/functional/backends/paddle/experimental/norms.py index a3ddb0728c0e4..bfef54ffae551 100644 --- a/ivy/functional/backends/paddle/experimental/norms.py +++ b/ivy/functional/backends/paddle/experimental/norms.py @@ -12,7 +12,7 @@ # use numpy implementation with ivy functions @with_unsupported_device_and_dtypes( { - "2.5.1 and below": { + "2.6.0 and below": { "cpu": ( "int8", "int16", @@ -42,9 +42,9 @@ def batch_norm( out: Optional[Tuple[paddle.Tensor, paddle.Tensor, paddle.Tensor]] = None, ) -> Tuple[paddle.Tensor, paddle.Tensor, paddle.Tensor]: if x.dtype not in [paddle.float32, paddle.float64]: - x, mean, variance, scale, offset = [ + x, mean, variance, scale, offset = ( t.cast("float32") for t in [x, mean, variance, scale, offset] - ] + ) runningmean = mean runningvariance = variance data_formats = ["NC", "NCL", "NCHW", "NCDHW", "NLC", "NHWC", "NDHWC"] @@ -55,11 +55,11 @@ def batch_norm( if data_format[-1] == "C" else data_formats[0:4][x.ndim - 2] ) - except IndexError: + except IndexError as e: raise IndexError( "data_format must be one of 'NC', 'NCL', 'NCHW', 'NCDHW', 'NLC', 'NHWC'," f" 'NDHWC' but receive {data_format}" - ) + ) from e with ivy.ArrayMode(False): if training: @@ -105,9 +105,9 @@ def batch_norm( ) -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, backend_version) +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, backend_version) def l1_normalize( - x: paddle.Tensor, /, *, axis: int = None, out: paddle.Tensor = None + x: paddle.Tensor, /, *, axis: Optional[int] = None, out: paddle.Tensor = None ) -> paddle.Tensor: if not isinstance(x, paddle.Tensor): x = paddle.to_tensor(x) @@ -131,7 +131,7 @@ def l1_normalize( def l2_normalize( - x: paddle.Tensor, /, *, axis: int = None, out: paddle.Tensor = None + x: paddle.Tensor, /, *, axis: Optional[int] = None, out: paddle.Tensor = None ) -> paddle.Tensor: raise IvyNotImplementedException() @@ -164,6 +164,11 @@ def instance_norm( def lp_normalize( - x: paddle.Tensor, /, *, p: float = 2, axis: int = None, out: paddle.Tensor = None + x: paddle.Tensor, + /, + *, + p: float = 2, + axis: Optional[int] = None, + out: paddle.Tensor = None, ) -> paddle.Tensor: raise IvyNotImplementedException() diff --git a/ivy/functional/backends/paddle/experimental/random.py b/ivy/functional/backends/paddle/experimental/random.py index 2f4fd90678077..e5095b76bc297 100644 --- a/ivy/functional/backends/paddle/experimental/random.py +++ b/ivy/functional/backends/paddle/experimental/random.py @@ -16,7 +16,7 @@ @with_unsupported_device_and_dtypes( { - "2.5.1 and below": { + "2.6.0 and below": { "cpu": ( "int8", "int16", @@ -91,8 +91,8 @@ def poisson( lam: Union[float, paddle.Tensor], *, shape: Optional[Union[ivy.NativeShape, Sequence[int]]] = None, - device: core.Place, - dtype: paddle.dtype, + device: core.Place = None, + dtype: paddle.dtype = None, seed: Optional[int] = None, fill_value: Optional[Union[float, int]] = 0, out: Optional[paddle.Tensor] = None, @@ -127,6 +127,7 @@ def bernoulli( seed: Optional[int] = None, out: Optional[paddle.Tensor] = None, ) -> paddle.Tensor: + dtype = dtype if dtype is not None else probs.dtype if seed is not None: paddle.seed(seed) if probs is not None: @@ -134,7 +135,9 @@ def bernoulli( elif logits is not None: probs = ivy.softmax(logits) probs = paddle.cast(probs, dtype) - probs = paddle.unsqueeze(probs, 0) if len(probs.shape) == 0 else probs + squeeze = len(probs.shape) == 0 + probs = paddle.unsqueeze(probs, 0) if squeeze else probs probs = paddle.maximum(probs, paddle.full_like(probs, 1e-6)) sample = paddle.bernoulli(probs) + sample = paddle.squeeze(sample, 0) if squeeze else sample return sample diff --git a/ivy/functional/backends/paddle/experimental/sparse_array.py b/ivy/functional/backends/paddle/experimental/sparse_array.py index c79a7c97ffac3..453ee5568e96a 100644 --- a/ivy/functional/backends/paddle/experimental/sparse_array.py +++ b/ivy/functional/backends/paddle/experimental/sparse_array.py @@ -19,7 +19,7 @@ def is_native_sparse_array(x: paddle.Tensor) -> bool: @with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("int8",)}}, backend_version + {"2.6.0 and below": {"cpu": ("int8",)}}, backend_version ) def native_sparse_array( data=None, diff --git a/ivy/functional/backends/paddle/experimental/statistical.py b/ivy/functional/backends/paddle/experimental/statistical.py index 6ecfaa16caf5d..2a611367b7151 100644 --- a/ivy/functional/backends/paddle/experimental/statistical.py +++ b/ivy/functional/backends/paddle/experimental/statistical.py @@ -14,7 +14,7 @@ @with_supported_dtypes( - {"2.5.1 and below": ("complex", "float32", "float64", "int32", "int64")}, + {"2.6.0 and below": ("complex", "float32", "float64", "int32", "int64")}, backend_version, ) def median( @@ -32,7 +32,7 @@ def median( ) else: ret = paddle.median(input, axis=axis, keepdim=True) - # keepdims is set to True because in versions up to 2.5.1 + # keepdims is set to True because in versions up to 2.6.0 # there was a problem when the axis was defined, and it was the # only axis in the tensor, so it needs to be handled manually if not keepdims: @@ -48,7 +48,7 @@ def median( @with_supported_dtypes( - {"2.5.1 and below": ("complex", "float32", "float64", "int64")}, backend_version + {"2.6.0 and below": ("complex", "float32", "float64", "int64")}, backend_version ) def nanmean( a: paddle.Tensor, @@ -94,14 +94,14 @@ def _validate_quantile(q): if not (0.0 <= q[i] <= 1.0): return False else: - if not (paddle.all(0 <= q) and paddle.all(q <= 1)): + if not (paddle.all(q >= 0) and paddle.all(q <= 1)): return False return True @with_unsupported_device_and_dtypes( { - "2.5.1 and below": { + "2.6.0 and below": { "cpu": ( "int8", "int16", @@ -140,7 +140,7 @@ def nanmin( return result -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, backend_version) +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, backend_version) def nanprod( a: paddle.Tensor, /, @@ -308,7 +308,7 @@ def _compute_quantile_wrapper( @with_unsupported_device_and_dtypes( { - "2.5.1 and below": { + "2.6.0 and below": { "cpu": ( "int8", "int16", @@ -382,7 +382,7 @@ def histogram( @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, backend_version + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, backend_version ) def nanmedian( input: paddle.Tensor, @@ -401,7 +401,7 @@ def nanmedian( @with_unsupported_device_and_dtypes( { - "2.5.1 and below": { + "2.6.0 and below": { "cpu": ( "int8", "int16", @@ -419,7 +419,7 @@ def unravel_index( /, *, out: Optional[paddle.Tensor] = None, -) -> tuple[Any, ...]: +) -> Tuple[Any, ...]: if indices.ndim == 0: indices = indices.unsqueeze(0) coord = [] @@ -433,7 +433,7 @@ def unravel_index( @with_unsupported_device_and_dtypes( { - "2.5.1 and below": { + "2.6.0 and below": { "cpu": ( "int8", "int16", @@ -556,7 +556,7 @@ def cov( @with_supported_dtypes( - {"2.5.1 and below": ("complex", "bool", "float32", "float64")}, + {"2.6.0 and below": ("complex", "bool", "float32", "float64")}, backend_version, ) def cummax( @@ -607,7 +607,7 @@ def __find_cummax( if ( isinstance(x.tolist()[0], list) and len(x[0].shape) >= 1 - and (isinstance(x[0], paddle.Tensor) or isinstance(x[0], ivy.Array)) + and (isinstance(x[0], (paddle.Tensor, ivy.Array))) ): if axis >= 1: if not isinstance(x, list): @@ -680,8 +680,17 @@ def __get_index(lst, indices=None, prefix=None): return indices -@with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("uint8", "int8", "int16")}}, +@with_supported_dtypes( + { + "2.6.0 and below": ( + "complex", + "int32", + "int64", + "bfloat16", + "float32", + "float64", + ) + }, backend_version, ) def cummin( diff --git a/ivy/functional/backends/paddle/general.py b/ivy/functional/backends/paddle/general.py index 46ba0a4a23d3c..5f8e28ccf335d 100644 --- a/ivy/functional/backends/paddle/general.py +++ b/ivy/functional/backends/paddle/general.py @@ -1,7 +1,10 @@ -"""Collection of Paddle general functions, wrapped to fit Ivy syntax and signature.""" +"""Collection of Paddle general functions, wrapped to fit Ivy syntax and +signature.""" # global +import functools from numbers import Number +from operator import mul from typing import Optional, Union, Sequence, Callable, List, Tuple import paddle import numpy as np @@ -38,7 +41,7 @@ def current_backend_str() -> str: def _check_query(query): if isinstance(query, Sequence): - return not any([isinstance(item, (Sequence, paddle.Tensor)) for item in query]) + return not any(isinstance(item, (Sequence, paddle.Tensor)) for item in query) else: return True @@ -86,7 +89,7 @@ def _squeeze_helper(query, x_ndim): @with_unsupported_device_and_dtypes( { - "2.5.1 and below": { + "2.6.0 and below": { "cpu": ("int8", "int16", "float16", "complex64", "complex128") } }, @@ -97,7 +100,7 @@ def get_item( /, query: Union[paddle.Tensor, Tuple], *, - copy: bool = None, + copy: Optional[bool] = None, ) -> paddle.Tensor: if copy: x = paddle.clone(x) @@ -228,6 +231,10 @@ def _gather(params1): return _gather(params) +@with_unsupported_device_and_dtypes( + {"2.6.0 and below": {"cpu": ("bfloat16", "float16")}}, + backend_version, +) def gather_nd( params: paddle.Tensor, indices: paddle.Tensor, @@ -270,6 +277,8 @@ def gather_nd( indices_shape = indices.shape batch_shape = params_shape[:batch_dims] batch_size = paddle.prod(batch_shape, [0]).numpy().tolist() + if isinstance(batch_size, int): + batch_size = [batch_size] index_internal_ndims = indices.ndim - batch_dims - 1 indices_internal_shape = indices_shape[batch_dims:-1] @@ -357,6 +366,10 @@ def get_num_dims( return paddle.to_tensor(x.ndim).squeeze() if as_array else x.ndim +def size(x: paddle.Tensor, /) -> int: + return functools.reduce(mul, x.shape) if len(x.shape) > 0 else 1 + + def inplace_arrays_supported(): # there are some operations that support inplace updates # but it's not supported in all functions @@ -648,7 +661,11 @@ def _vmap(*args, **kwargs): # vectorisation - applying map_fn if only one arg provided as reduce requires # two elements to begin with. - arr_results = [func(*arrays) for arrays in zip(*args)] + arr_results = [] + for arrays in zip(*args): + arrays = [a if a.shape != [] else a.unsqueeze(0) for a in arrays] + arr_results.append(func(*arrays)) + res = paddle_backend.concat(arr_results) if out_axes: diff --git a/ivy/functional/backends/paddle/gradients.py b/ivy/functional/backends/paddle/gradients.py index 3d3cd8f84785c..925e49c865bc1 100644 --- a/ivy/functional/backends/paddle/gradients.py +++ b/ivy/functional/backends/paddle/gradients.py @@ -1,4 +1,5 @@ -"""Collection of Paddle gradient functions, wrapped to fit Ivy syntax and signature.""" +"""Collection of Paddle gradient functions, wrapped to fit Ivy syntax and +signature.""" # global @@ -21,8 +22,6 @@ def variable(x, /): - if ivy.is_int_dtype(x.dtype): - x = x.astype(ivy.default_float_dtype()) if not x.is_leaf: ret = x.detach() ret.stop_gradient = False @@ -104,7 +103,7 @@ def grad_(x): @with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("float16",)}}, backend_version + {"2.6.0 and below": {"cpu": ("float16",)}}, backend_version ) def execute_with_gradients( func, xs, /, *, retain_grads=False, xs_grad_idxs=((0,),), ret_grad_idxs=((0,),) diff --git a/ivy/functional/backends/paddle/layers.py b/ivy/functional/backends/paddle/layers.py index f70c374bc70de..fb20e6ae75272 100644 --- a/ivy/functional/backends/paddle/layers.py +++ b/ivy/functional/backends/paddle/layers.py @@ -1,4 +1,5 @@ -"""Collection of Paddle network layers, wrapped to fit Ivy syntax and signature.""" +"""Collection of Paddle network layers, wrapped to fit Ivy syntax and +signature.""" from typing import Optional, Tuple, Union, Sequence @@ -29,10 +30,11 @@ def _convert_to_list(value, n, name="padding", _type=int): else: try: value_list = list(value) - except TypeError: - raise ValueError( - f"The input {name}'s type must be list or tuple. Received: {value}" - ) + except TypeError as e: + raise TypeError( + f"The input {value}'s type must be list or tuple. Received:" + f" {type(value)}" + ) from e else: return value_list @@ -70,7 +72,7 @@ def _pad_before_conv(x, filters, strides, padding, dims, dilations, data_format) else: raise ValueError(f"Invalid padding format: {padding}") - if not all([p >= 0 for p in padding]): + if not all(p >= 0 for p in padding): raise ValueError( "Invalid padding, all values should be larger than" f"or equal to 0, but received: {padding}." @@ -147,8 +149,8 @@ def conv1d( /, *, data_format: str = "NWC", - filter_format: Optional[str] = "channel_last", - x_dilations: Optional[Union[int, Tuple[int]]] = 1, + filter_format: str = "channel_last", + x_dilations: Union[int, Tuple[int]] = 1, dilations: Union[int, Tuple[int]] = 1, bias: Optional[paddle.Tensor] = None, out: Optional[paddle.Tensor] = None, @@ -157,7 +159,7 @@ def conv1d( @with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("float16", "bfloat16")}}, + {"2.6.0 and below": {"cpu": ("float16", "bfloat16")}}, backend_version, ) def conv1d_transpose( @@ -168,6 +170,7 @@ def conv1d_transpose( /, *, output_shape: Optional[Union[ivy.NativeShape, Sequence[int]]] = None, + filter_format: str = "channel_last", data_format: str = "NWC", dilations: Union[int, Tuple[int]] = 1, bias: Optional[paddle.Tensor] = None, @@ -177,7 +180,8 @@ def conv1d_transpose( x = x.transpose([0, 2, 1]) strides = [strides] if isinstance(strides, int) else strides dilations = [dilations] if isinstance(dilations, int) else dilations - filters = filters.transpose([1, 2, 0]) + if filter_format == "channel_last": + filters = filters.transpose([2, 1, 0]) not_valid_pad, padding_list, output_padding = _pad_before_conv_tranpose( x, filters, strides, padding, 1, dilations, output_shape, filters.shape[2:] ) @@ -206,8 +210,8 @@ def conv2d( /, *, data_format: str = "NHWC", - filter_format: Optional[str] = "channel_last", - x_dilations: Optional[Union[int, Tuple[int, int]]] = 1, + filter_format: str = "channel_last", + x_dilations: Union[int, Tuple[int, int]] = 1, dilations: Union[int, Tuple[int, int]] = 1, bias: Optional[paddle.Tensor] = None, out: Optional[paddle.Tensor] = None, @@ -216,7 +220,7 @@ def conv2d( @with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("float16",)}}, + {"2.6.0 and below": {"cpu": ("float16", "bfloat16")}}, backend_version, ) def conv2d_transpose( @@ -227,8 +231,9 @@ def conv2d_transpose( /, *, output_shape: Optional[Union[ivy.NativeShape, Sequence[int]]] = None, - data_format: Optional[str] = "NHWC", - dilations: Optional[Union[int, Tuple[int, int]]] = 1, + filter_format: str = "channel_last", + data_format: str = "NHWC", + dilations: Union[int, Tuple[int, int]] = 1, bias: Optional[paddle.Tensor] = None, out: Optional[paddle.Tensor] = None, ): @@ -236,7 +241,8 @@ def conv2d_transpose( x = x.transpose([0, 3, 1, 2]) strides = [strides] * 2 if isinstance(strides, int) else strides dilations = [dilations] * 2 if isinstance(dilations, int) else dilations - filters = filters.transpose([2, 3, 0, 1]) + if filter_format == "channel_last": + filters = filters.transpose([3, 2, 0, 1]) not_valid_pad, padding_list, output_padding = _pad_before_conv_tranpose( x, filters, strides, padding, 2, dilations, output_shape, filters.shape[2:] ) @@ -267,15 +273,15 @@ def depthwise_conv2d( padding: Union[str, int, Sequence[Tuple[int, int]]], /, *, - data_format: Optional[str] = "NHWC", - dilations: Optional[Union[int, Tuple[int, int]]] = 1, + data_format: str = "NHWC", + dilations: Union[int, Tuple[int, int]] = 1, out: Optional[paddle.Tensor] = None, ) -> paddle.Tensor: raise IvyNotImplementedException() @with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("float16",)}}, + {"2.6.0 and below": {"cpu": ("float16",)}}, backend_version, ) def conv3d( @@ -285,10 +291,10 @@ def conv3d( padding: Union[str, int, Sequence[Tuple[int, int]]], /, *, - data_format: Optional[str] = "NDHWC", - filter_format: Optional[str] = "channel_last", - x_dilations: Optional[Union[int, Tuple[int, int, int]]] = 1, - dilations: Optional[Union[int, Tuple[int, int, int]]] = 1, + data_format: str = "NDHWC", + filter_format: str = "channel_last", + x_dilations: Union[int, Tuple[int, int, int]] = 1, + dilations: Union[int, Tuple[int, int, int]] = 1, bias: Optional[paddle.Tensor] = None, out: Optional[paddle.Tensor] = None, ): @@ -325,8 +331,9 @@ def conv3d_transpose( /, *, output_shape: Optional[Union[ivy.NativeShape, Sequence[int]]] = None, - data_format: Optional[str] = "NDHWC", - dilations: Optional[Union[int, Tuple[int, int, int]]] = 1, + filter_format: str = "channel_last", + data_format: str = "NDHWC", + dilations: Union[int, Tuple[int, int, int]] = 1, bias: Optional[paddle.Tensor] = None, out: Optional[paddle.Tensor] = None, ) -> paddle.Tensor: @@ -334,7 +341,7 @@ def conv3d_transpose( @with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("float16",)}}, + {"2.6.0 and below": {"cpu": ("float16",)}}, backend_version, ) def conv_general_dilated( @@ -344,16 +351,12 @@ def conv_general_dilated( padding: Union[str, int, Sequence[Tuple[int, int]]], /, *, - dims: Optional[int] = 2, - data_format: Optional[str] = "channel_last", - filter_format: Optional[str] = "channel_last", - feature_group_count: Optional[int] = 1, - x_dilations: Optional[ - Union[int, Tuple[int], Tuple[int, int], Tuple[int, int, int]] - ] = 1, - dilations: Optional[ - Union[int, Tuple[int], Tuple[int, int], Tuple[int, int, int]] - ] = 1, + dims: int = 2, + data_format: str = "channel_last", + filter_format: str = "channel_last", + feature_group_count: int = 1, + x_dilations: Union[int, Tuple[int], Tuple[int, int], Tuple[int, int, int]] = 1, + dilations: Union[int, Tuple[int], Tuple[int, int], Tuple[int, int, int]] = 1, bias: Optional[paddle.Tensor] = None, out: Optional[paddle.Tensor] = None, ): @@ -425,21 +428,21 @@ def conv_general_transpose( padding: Union[str, Sequence[Tuple[int, int]]], /, *, - dims: Optional[int] = 2, + dims: int = 2, output_shape: Optional[Union[ivy.NativeShape, Sequence[int]]] = None, - data_format: Optional[str] = "NDHWC", - dilations: Optional[ - Union[int, Tuple[int], Tuple[int, int], Tuple[int, int, int]] - ] = 1, - feature_group_count: Optional[int] = 1, + filter_format: str = "channel_last", + data_format: str = "NDHWC", + dilations: Union[int, Tuple[int], Tuple[int, int], Tuple[int, int, int]] = 1, + feature_group_count: int = 1, bias: Optional[paddle.Tensor] = None, out: Optional[paddle.Tensor] = None, ): if data_format == "channel_last": - x = x.transpose(x, (0, dims + 1, *range(1, dims + 1))) + x = x.transpose([0, dims + 1, *range(1, dims + 1)]) + if filter_format == "channel_last": + filters = filters.transpose([dims + 1, dims, *range(dims)]) strides = [strides] * dims if isinstance(strides, int) else strides dilations = [dilations] * dims if isinstance(dilations, int) else dilations - filters = filters.transpose(dims, dims + 1, *range(dims)) not_valid_pad, padding_list, output_padding = _pad_before_conv_tranpose( x, filters, strides, padding, dims, dilations, output_shape, filters.shape[2:] ) @@ -492,5 +495,5 @@ def conv_general_transpose( if not_valid_pad[2]: res = res[:, :, :, 0:-1] if data_format == "channel_last": - res = res.transpose(0, *range(2, dims + 2), 1) + res = res.transpose([0, *range(2, dims + 2), 1]) return res diff --git a/ivy/functional/backends/paddle/linear_algebra.py b/ivy/functional/backends/paddle/linear_algebra.py index 3e7d5285849f2..ddf447a62e946 100644 --- a/ivy/functional/backends/paddle/linear_algebra.py +++ b/ivy/functional/backends/paddle/linear_algebra.py @@ -14,6 +14,7 @@ with_unsupported_device_and_dtypes, with_unsupported_dtypes, with_supported_dtypes, + with_supported_device_and_dtypes, ) from .elementwise import _elementwise_helper @@ -24,7 +25,7 @@ @with_unsupported_device_and_dtypes( { - "2.5.1 and below": { + "2.6.0 and below": { "cpu": ( "int8", "int16", @@ -53,7 +54,7 @@ def cross( axisa: int = -1, axisb: int = -1, axisc: int = -1, - axis: int = None, + axis: Optional[int] = None, out: Optional[paddle.Tensor] = None, ) -> paddle.Tensor: def _cross(x1, x2, axisa, axisb, axisc, axis): @@ -91,7 +92,7 @@ def _cross(x1, x2, axisa, axisb, axisc, axis): @with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("complex64", "complex128")}}, + {"2.6.0 and below": {"cpu": ("complex64", "complex128")}}, backend_version, ) def det(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.Tensor: @@ -144,7 +145,7 @@ def eigh( x: paddle.Tensor, /, *, - UPLO: Optional[str] = "L", + UPLO: str = "L", out: Optional[paddle.Tensor] = None, ) -> Tuple[paddle.Tensor]: result_tuple = NamedTuple( @@ -158,7 +159,7 @@ def eigvalsh( x: paddle.Tensor, /, *, - UPLO: Optional[str] = "L", + UPLO: str = "L", out: Optional[paddle.Tensor] = None, ) -> paddle.Tensor: return paddle.linalg.eigvalsh(x, UPLO=UPLO) @@ -183,7 +184,7 @@ def inner( @with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("complex64", "complex128")}}, + {"2.6.0 and below": {"cpu": ("complex64", "complex128")}}, backend_version, ) def inv( @@ -252,18 +253,21 @@ def matmul( @with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("complex64", "complex128")}}, + {"2.6.0 and below": {"cpu": ("complex64", "complex128")}}, backend_version, ) def matrix_norm( x: paddle.Tensor, /, *, - ord: Optional[Union[int, float, Literal[inf, -inf, "fro", "nuc"]]] = "fro", - axis: Optional[Tuple[int, int]] = (-2, -1), + ord: Union[int, float, Literal[inf, -inf, "fro", "nuc"]] = "fro", + axis: Tuple[int, int] = (-2, -1), keepdims: bool = False, + dtype: Optional[paddle.dtype] = None, out: Optional[paddle.Tensor] = None, ) -> paddle.Tensor: + if dtype is not None: + x = ivy.astype(x, dtype=dtype) axis_ = list(axis) # paddle.moveaxis doesn't support tuple axes if ord == "nuc": x = paddle.moveaxis(x, axis_, [-2, -1]) @@ -334,7 +338,7 @@ def eig( @with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("complex64", "complex128")}}, + {"2.6.0 and below": {"cpu": ("complex64", "complex128")}}, backend_version, ) def matrix_power( @@ -344,7 +348,7 @@ def matrix_power( @with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("complex64", "complex128")}}, + {"2.6.0 and below": {"cpu": ("complex64", "complex128")}}, backend_version, ) def matrix_rank( @@ -353,7 +357,7 @@ def matrix_rank( *, atol: Optional[Union[float, Tuple[float]]] = None, rtol: Optional[Union[float, Tuple[float]]] = None, - hermitian: Optional[bool] = False, + hermitian: bool = False, out: Optional[paddle.Tensor] = None, ) -> paddle.Tensor: if (x.ndim < 2) or (0 in x.shape): @@ -398,6 +402,14 @@ def matrix_transpose( return paddle.transpose(x, perm=perm) +@with_supported_device_and_dtypes( + { + "2.6.0 and below": { + "cpu": ("int32", "int64", "float64", "complex128" "float32", "complex64") + } + }, + backend_version, +) def outer( x1: paddle.Tensor, x2: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None ) -> paddle.Tensor: @@ -433,7 +445,7 @@ def tensorsolve( x2: paddle.Tensor, /, *, - axes: Union[int, Tuple[List[int], List[int]]] = None, + axes: Optional[Union[int, Tuple[List[int], List[int]]]] = None, out: Optional[paddle.Tensor] = None, ) -> paddle.Tensor: # Implemented as a composite function in ivy.functional.ivy.linear_algebra @@ -441,7 +453,7 @@ def tensorsolve( @with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("complex64", "complex128")}}, + {"2.6.0 and below": {"cpu": ("complex64", "complex128")}}, backend_version, ) def qr( @@ -457,7 +469,7 @@ def qr( @with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("complex64", "complex128")}}, + {"2.6.0 and below": {"cpu": ("complex64", "complex128")}}, backend_version, ) def slogdet( @@ -476,7 +488,7 @@ def slogdet( @with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("complex64", "complex128")}}, + {"2.6.0 and below": {"cpu": ("complex64", "complex128")}}, backend_version, ) def solve( @@ -503,7 +515,7 @@ def solve( return ret -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, backend_version) +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, backend_version) def svd( x: paddle.Tensor, /, *, full_matrices: bool = True, compute_uv: bool = True ) -> Union[paddle.Tensor, Tuple[paddle.Tensor, ...]]: @@ -517,7 +529,7 @@ def svd( @with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("complex64", "complex128")}}, + {"2.6.0 and below": {"cpu": ("complex64", "complex128")}}, backend_version, ) def svdvals( @@ -532,7 +544,7 @@ def svdvals( @with_supported_dtypes( - {"2.5.1 and below": ("complex", "float32", "float64")}, backend_version + {"2.6.0 and below": ("complex", "float32", "float64")}, backend_version ) def tensordot( x1: paddle.Tensor, @@ -548,7 +560,7 @@ def tensordot( @with_unsupported_device_and_dtypes( { - "2.5.1 and below": { + "2.6.0 and below": { "cpu": ( "int8", "int16", @@ -592,8 +604,8 @@ def vector_norm( /, *, axis: Optional[Union[int, Sequence[int]]] = None, - keepdims: Optional[bool] = False, - ord: Optional[Union[int, float, Literal[inf, -inf]]] = 2, + keepdims: bool = False, + ord: Union[int, float, Literal[inf, -inf]] = 2, dtype: Optional[paddle.dtype] = None, out: Optional[paddle.Tensor] = None, ) -> paddle.Tensor: @@ -624,7 +636,7 @@ def vector_norm( @with_supported_dtypes( - {"2.5.1 and below": ("float16", "float32", "float64", "int32", "int64")}, + {"2.6.0 and below": ("float16", "float32", "float64", "int32", "int64")}, backend_version, ) def diag( @@ -638,7 +650,7 @@ def diag( @with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("uint8", "int8", "int16", "complex64", "complex128")}}, + {"2.6.0 and below": {"cpu": ("uint8", "int8", "int16", "complex64", "complex128")}}, backend_version, ) def vander( @@ -660,7 +672,7 @@ def vander( @with_unsupported_dtypes( - {"2.5.1 and below": ("unsigned", "int8", "int16", "float16")}, + {"2.6.0 and below": ("unsigned", "int8", "int16", "float16")}, backend_version, ) def vector_to_skew_symmetric_matrix( diff --git a/ivy/functional/backends/paddle/manipulation.py b/ivy/functional/backends/paddle/manipulation.py index 58adc9bec6ada..c88903542619a 100644 --- a/ivy/functional/backends/paddle/manipulation.py +++ b/ivy/functional/backends/paddle/manipulation.py @@ -22,6 +22,10 @@ # -------------------# +@with_unsupported_dtypes( + {"2.6.0 and below": ("bfloat16", "float16")}, + backend_version, +) def concat( xs: Union[Tuple[paddle.Tensor, ...], List[paddle.Tensor]], /, @@ -58,6 +62,20 @@ def concat( return ret +@with_supported_dtypes( + { + "2.6.0 and below": ( + "int32", + "int64", + "float64", + "complex128", + "float32", + "complex64", + "bool", + ) + }, + backend_version, +) def expand_dims( x: paddle.Tensor, /, @@ -74,7 +92,7 @@ def expand_dims( @with_unsupported_dtypes( - {"2.5.1 and below": ("bfloat16", "float16", "int16", "int8", "uint8")}, + {"2.6.0 and below": ("bfloat16", "float16", "int16", "int8", "uint8")}, backend_version, ) def flip( @@ -91,7 +109,8 @@ def flip( @with_unsupported_dtypes( - {"2.5.1 and below": ("int16", "int8", "uint8", "bfloat16")}, backend_version + {"2.6.0 and below": ("uint8", "int8", "int16", "bfloat16", "float16")}, + backend_version, ) def permute_dims( x: paddle.Tensor, @@ -101,6 +120,9 @@ def permute_dims( copy: Optional[bool] = None, out: Optional[paddle.Tensor] = None, ) -> paddle.Tensor: + if copy: + newarr = paddle.clone(x) + return paddle.transpose(newarr, axes) return paddle.transpose(x, axes) @@ -159,7 +181,7 @@ def reshape( @with_supported_dtypes( - {"2.5.1 and below": ("complex", "float32", "float64", "int32", "int64")}, + {"2.6.0 and below": ("complex", "float32", "float64", "int32", "int64")}, backend_version, ) def roll( @@ -174,7 +196,7 @@ def roll( @with_unsupported_dtypes( - {"2.5.1 and below": ("bfloat16", "float16", "int16")}, backend_version + {"2.6.0 and below": ("bfloat16", "float16", "int16")}, backend_version ) def squeeze( x: paddle.Tensor, @@ -201,7 +223,7 @@ def squeeze( @with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("int16", "uint8", "int8", "float16")}}, + {"2.6.0 and below": {"cpu": ("int16", "uint8", "int8", "float16")}}, backend_version, ) def stack( @@ -220,8 +242,8 @@ def stack( arrays = list(map(lambda x: x.cast(dtype), arrays)) first_shape = arrays[0].shape - if not all(arr.shape == first_shape for arr in arrays): - raise Exception("Shapes of all inputs must match") + if any(arr.shape != first_shape for arr in arrays): + raise ValueError("Shapes of all inputs must match") if 0 in first_shape: return ivy.empty( first_shape[:axis] + [len(arrays)] + first_shape[axis:], dtype=dtype @@ -249,7 +271,7 @@ def stack( # ------# -@with_unsupported_dtypes({"2.5.1 and below": ("int16",)}, backend_version) +@with_unsupported_dtypes({"2.6.0 and below": ("int16",)}, backend_version) def split( x: paddle.Tensor, /, @@ -299,7 +321,7 @@ def split( @with_supported_dtypes( - {"2.5.1 and below": ("complex", "float32", "float64", "int32", "int64")}, + {"2.6.0 and below": ("complex", "float32", "float64", "int32", "int64")}, backend_version, ) def repeat( @@ -307,7 +329,7 @@ def repeat( /, repeats: Union[int, Iterable[int]], *, - axis: int = None, + axis: Optional[int] = None, out: Optional[paddle.Tensor] = None, ) -> paddle.Tensor: # handle the case when repeats contains 0 as paddle doesn't support it @@ -325,7 +347,7 @@ def repeat( repeats = repeats.item() if axis is not None: - axis = axis % x.ndim + axis %= x.ndim if paddle.is_complex(x): return paddle.complex( paddle.repeat_interleave(x.real(), repeats=repeats, axis=axis), @@ -335,7 +357,7 @@ def repeat( @with_unsupported_dtypes( - {"2.5.1 and below": ("bfloat16", "float16", "int16", "int8", "uint8")}, + {"2.6.0 and below": ("bfloat16", "float16", "int16", "int8", "uint8")}, backend_version, ) def tile( @@ -378,7 +400,7 @@ def tile( @with_unsupported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "bfloat16", "float16", "int8", @@ -407,6 +429,7 @@ def constant_pad( return paddle.nn.functional.pad(x=x, pad=paddings, value=value) +@with_unsupported_dtypes({"2.6.0 and below": ("float16",)}, backend_version) def zero_pad( x: paddle.Tensor, /, @@ -417,6 +440,22 @@ def zero_pad( return paddle_backend.constant_pad(x, pad_width=pad_width, value=0) +@with_supported_dtypes( + { + "2.6.0 and below": ( + "bool", + "int32", + "int64", + "float16", + "bfloat16", + "float32", + "float64", + "complex64", + "complex128", + ) + }, + backend_version, +) def swapaxes( x: paddle.Tensor, axis0: int, @@ -462,7 +501,7 @@ def clip( @with_unsupported_dtypes( - {"2.5.1 and below": ("int16", "int8", "uint8", "bfloat16")}, backend_version + {"2.6.0 and below": ("int16", "int8", "uint8", "bfloat16")}, backend_version ) def unstack( x: paddle.Tensor, diff --git a/ivy/functional/backends/paddle/module.py b/ivy/functional/backends/paddle/module.py new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/ivy/functional/backends/paddle/random.py b/ivy/functional/backends/paddle/random.py index c2a846e3f4b5a..15c10f366a1a7 100644 --- a/ivy/functional/backends/paddle/random.py +++ b/ivy/functional/backends/paddle/random.py @@ -1,4 +1,5 @@ -"""Collection of Paddle random functions, wrapped to fit Ivy syntax and signature.""" +"""Collection of Paddle random functions, wrapped to fit Ivy syntax and +signature.""" # global import paddle @@ -7,7 +8,7 @@ # local import ivy -from paddle.fluid.libpaddle import Place +from paddle.device import core from ivy.functional.ivy.random import ( _check_bounds_and_get_shape, _randint_check_dtype_and_bound, @@ -25,7 +26,7 @@ @with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("int8",)}}, + {"2.6.0 and below": {"cpu": ("int8",)}}, backend_version, ) def random_uniform( @@ -34,7 +35,7 @@ def random_uniform( high: Union[float, paddle.Tensor] = 1.0, shape: Optional[Union[paddle.Tensor, ivy.NativeShape, Sequence[int]]] = None, dtype: paddle.dtype, - device: Place = None, + device: core.Place = None, seed=None, out: Optional[paddle.Tensor] = None, ) -> paddle.Tensor: @@ -56,7 +57,7 @@ def random_uniform( @with_unsupported_dtypes( - {"2.5.1 and below": ("float16", "int16", "int8")}, backend_version + {"2.6.0 and below": ("float16", "int16", "int8")}, backend_version ) def random_normal( *, @@ -65,7 +66,7 @@ def random_normal( shape: Optional[Union[ivy.NativeShape, Sequence[int]]] = None, dtype: paddle.dtype, seed: Optional[int] = None, - device: Place = None, + device: core.Place = None, out: Optional[paddle.Tensor] = None, ) -> paddle.Tensor: _check_valid_scale(std) @@ -77,7 +78,7 @@ def random_normal( @with_supported_device_and_dtypes( { - "2.5.1 and below": { + "2.6.0 and below": { "cpu": ( "float32", "float64", @@ -94,7 +95,7 @@ def multinomial( batch_size: int = 1, probs: Optional[paddle.Tensor] = None, replace: bool = True, - device: Place = None, + device: core.Place = None, seed: Optional[int] = None, out: Optional[paddle.Tensor] = None, ) -> paddle.Tensor: @@ -108,7 +109,7 @@ def multinomial( @with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("int8",)}}, + {"2.6.0 and below": {"cpu": ("int8",)}}, backend_version, ) def randint( @@ -117,7 +118,7 @@ def randint( /, *, shape: Optional[Union[ivy.NativeShape, Sequence[int]]] = None, - device: Place = None, + device: core.Place = None, dtype: Optional[Union[paddle.dtype, ivy.Dtype]] = None, seed: Optional[int] = None, out: Optional[paddle.Tensor] = None, @@ -139,7 +140,7 @@ def randint( return _retval if shape else _retval.squeeze(axis=0) -def seed(*, seed_value: int = 0) -> None: +def seed(*, seed_value: int = 0): _ = paddle.seed(seed_value) return diff --git a/ivy/functional/backends/paddle/searching.py b/ivy/functional/backends/paddle/searching.py index 64b68a8a63ba1..f64c9c97288ba 100644 --- a/ivy/functional/backends/paddle/searching.py +++ b/ivy/functional/backends/paddle/searching.py @@ -16,7 +16,7 @@ @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int16", "int32", "int64", "uint8")}, + {"2.6.0 and below": ("float32", "float64", "int16", "int32", "int64", "uint8")}, backend_version, ) def argmax( @@ -48,7 +48,7 @@ def argmax( @with_unsupported_dtypes( - {"2.5.1 and below": ("bfloat16", "bool", "complex", "float16", "int8")}, + {"2.6.0 and below": ("bfloat16", "bool", "complex", "float16", "int8")}, backend_version, ) def argmin( @@ -80,7 +80,7 @@ def argmin( @with_unsupported_dtypes( - {"2.5.1 and below": ("float16", "int8", "uint8")}, backend_version + {"2.6.0 and below": ("float16", "int8", "uint8")}, backend_version ) def nonzero( x: paddle.Tensor, @@ -161,7 +161,7 @@ def where( @with_unsupported_dtypes( - {"2.5.1 and below": ("float16", "int8", "uint8")}, backend_version + {"2.6.0 and below": ("float16", "int8", "uint8")}, backend_version ) def argwhere( x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None diff --git a/ivy/functional/backends/paddle/set.py b/ivy/functional/backends/paddle/set.py index f59684732568b..1d73d6b200496 100644 --- a/ivy/functional/backends/paddle/set.py +++ b/ivy/functional/backends/paddle/set.py @@ -10,7 +10,7 @@ @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, backend_version + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, backend_version ) def unique_all( x: paddle.Tensor, @@ -67,7 +67,7 @@ def unique_all( [ i[0] for i in sorted( - list(enumerate(values_.numpy().tolist())), key=lambda x: tuple(x[1]) + enumerate(values_.numpy().tolist()), key=lambda x: tuple(x[1]) ) ] ) @@ -88,7 +88,7 @@ def unique_all( @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, backend_version + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, backend_version ) def unique_counts(x: paddle.Tensor, /) -> Tuple[paddle.Tensor, paddle.Tensor]: unique, counts = paddle.unique(x, return_counts=True) @@ -111,7 +111,7 @@ def unique_counts(x: paddle.Tensor, /) -> Tuple[paddle.Tensor, paddle.Tensor]: @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, backend_version + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, backend_version ) def unique_inverse( x: paddle.Tensor, @@ -137,7 +137,7 @@ def unique_inverse( x.dtype ) unique = paddle.concat( - input=[unique.astype(x.dtype), paddle.reshape(unique_nan, [nan_count])], + [unique.astype(x.dtype), paddle.reshape(unique_nan, [nan_count])], axis=-1, ) inverse_val = paddle.reshape(inverse_val, shape=x.shape) @@ -146,7 +146,7 @@ def unique_inverse( @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, backend_version + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, backend_version ) def unique_values( x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None diff --git a/ivy/functional/backends/paddle/sorting.py b/ivy/functional/backends/paddle/sorting.py index 5712826cda9c8..f67aa6bece1b4 100644 --- a/ivy/functional/backends/paddle/sorting.py +++ b/ivy/functional/backends/paddle/sorting.py @@ -9,7 +9,7 @@ @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, backend_version + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, backend_version ) def argsort( x: paddle.Tensor, @@ -24,7 +24,7 @@ def argsort( @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, backend_version + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, backend_version ) def sort( x: paddle.Tensor, @@ -39,7 +39,7 @@ def sort( @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, backend_version + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, backend_version ) def searchsorted( x: paddle.Tensor, @@ -52,14 +52,12 @@ def searchsorted( out: Optional[paddle.Tensor] = None, ) -> paddle.Tensor: right = True if side == "right" else False - assert ivy.is_int_dtype(ret_dtype), ValueError( + assert ivy.is_int_dtype(ret_dtype), TypeError( "only Integer data types are supported for ret_dtype." ) if sorter is not None: - assert ivy.is_int_dtype(sorter.dtype) and not ivy.is_uint_dtype( - sorter.dtype - ), TypeError( + assert ivy.is_int_dtype(sorter.dtype), TypeError( f"Only signed integer data type for sorter is allowed, got {sorter.dtype}." ) if ivy.as_native_dtype(sorter.dtype) not in [paddle.int32, paddle.int64]: @@ -76,7 +74,7 @@ def searchsorted( @with_unsupported_device_and_dtypes( - {"2.5.1 and below": {"cpu": ("int8", "uint8", "int16", "float16", "complex")}}, + {"2.6.0 and below": {"cpu": ("int8", "uint8", "int16", "float16", "complex")}}, backend_version, ) def msort( diff --git a/ivy/functional/backends/paddle/statistical.py b/ivy/functional/backends/paddle/statistical.py index 791eaefee92cc..4a0376cd2cf17 100644 --- a/ivy/functional/backends/paddle/statistical.py +++ b/ivy/functional/backends/paddle/statistical.py @@ -8,12 +8,10 @@ import ivy from ivy.func_wrapper import ( with_supported_dtypes, - with_unsupported_dtypes, with_supported_device_and_dtypes, ) import ivy.functional.backends.paddle as paddle_backend from ivy.utils.einsum_parser import legalise_einsum_expr -from ivy.functional.ivy.statistical import _get_promoted_type_of_operands # local from . import backend_version @@ -23,7 +21,7 @@ @with_supported_dtypes( - {"2.5.1 and below": ("complex", "float32", "float64", "int32", "int64")}, + {"2.6.0 and below": ("complex", "float32", "float64", "int32", "int64")}, backend_version, ) def min( @@ -32,6 +30,8 @@ def min( *, axis: Optional[Union[int, Sequence[int]]] = None, keepdims: bool = False, + initial: Optional[Union[int, float, complex]] = None, + where: Optional[paddle.Tensor] = None, out: Optional[paddle.Tensor] = None, ) -> paddle.Tensor: ret_dtype = x.dtype @@ -40,6 +40,18 @@ def min( imag = paddle.amin(x.imag(), axis=axis, keepdim=keepdims) ret = paddle.complex(real, imag) else: + if where is not None: + max_val = ( + ivy.iinfo(x.dtype).max + if ivy.is_int_dtype(x.dtype) + else ivy.finfo(x.dtype).max + ) + max_val = max_val / 10 + # max_val becomes negative after multiplying with paddle.ones_like(x) + # therefore reduced it + val = paddle.ones_like(x) * max_val + val = val.astype(ret_dtype) + x = paddle.where(where, x, val) ret = paddle.amin(x, axis=axis, keepdim=keepdims) # The following code is to simulate other frameworks # output shapes behaviour since min output dim is 1 in paddle @@ -48,11 +60,14 @@ def min( axis = None if (x.ndim == 1 or axis is None) and not keepdims: ret = ret.squeeze() + if initial is not None: + initial = paddle.to_tensor(initial, dtype=ret_dtype) + ret = paddle.minimum(ret, initial) return ret.astype(ret_dtype) @with_supported_dtypes( - {"2.5.1 and below": ("complex", "float32", "float64", "int32", "int64")}, + {"2.6.0 and below": ("complex", "float32", "float64", "int32", "int64")}, backend_version, ) def max( @@ -90,7 +105,7 @@ def max( @with_supported_dtypes( - {"2.5.1 and below": ("bool", "complex", "float32", "float64")}, backend_version + {"2.6.0 and below": ("bool", "complex", "float32", "float64")}, backend_version ) def mean( x: paddle.Tensor, @@ -120,7 +135,7 @@ def mean( @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, backend_version + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, backend_version ) def prod( x: paddle.Tensor, @@ -168,7 +183,10 @@ def std( return _std(x, axis, correction, keepdims).cast(x.dtype) -@with_unsupported_dtypes({"2.5.1 and below": ("int8", "uint8")}, backend_version) +@with_supported_dtypes( + {"2.6.0 and below": ("bool", "float16", "float32", "float64", "int32", "int64")}, + backend_version, +) def sum( x: paddle.Tensor, /, @@ -207,7 +225,7 @@ def var( # Extra # # ----- # @with_supported_dtypes( - {"2.5.1 and below": ("complex", "float32", "float64", "int32", "int64")}, + {"2.6.0 and below": ("complex", "float32", "float64", "int32", "int64")}, backend_version, ) def cumprod( @@ -257,7 +275,7 @@ def cumprod( @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, backend_version + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, backend_version ) def cumsum( x: paddle.Tensor, @@ -306,7 +324,7 @@ def cumsum( @with_supported_device_and_dtypes( { - "2.5.1 and below": { + "2.6.0 and below": { "cpu": ("float32", "float64", "complex64", "complex128"), "gpu": ( "bfloat16", @@ -329,6 +347,15 @@ def einsum( *operands: paddle.Tensor, out: Optional[paddle.Tensor] = None, ) -> paddle.Tensor: - dtype = _get_promoted_type_of_operands(operands) equation = legalise_einsum_expr(*[equation, *operands]) - return paddle.einsum(equation, *operands).astype(dtype) + + dtype_list = set(map(lambda x: x.dtype, operands)) + dtype = dtype_list.pop() + if len(dtype_list) > 0: + for d in dtype_list: + dtype = ivy.promote_types(dtype, d) + operands = list( + map(lambda x: x.cast(dtype) if x.dtype != dtype else x, operands) + ) + + return paddle.einsum(equation, *operands) diff --git a/ivy/functional/backends/tensorflow/__init__.py b/ivy/functional/backends/tensorflow/__init__.py index 4d2a7e97c0398..6af4c4d36e712 100644 --- a/ivy/functional/backends/tensorflow/__init__.py +++ b/ivy/functional/backends/tensorflow/__init__.py @@ -128,7 +128,7 @@ def rep_method(*args, **kwargs): # update these to add new dtypes valid_dtypes = { - "2.14.0 and below": ( + "2.15.0 and below": ( ivy.int8, ivy.int16, ivy.int32, @@ -147,7 +147,7 @@ def rep_method(*args, **kwargs): ) } valid_numeric_dtypes = { - "2.14.0 and below": ( + "2.15.0 and below": ( ivy.int8, ivy.int16, ivy.int32, @@ -165,7 +165,7 @@ def rep_method(*args, **kwargs): ) } valid_int_dtypes = { - "2.14.0 and below": ( + "2.15.0 and below": ( ivy.int8, ivy.int16, ivy.int32, @@ -177,12 +177,12 @@ def rep_method(*args, **kwargs): ) } valid_float_dtypes = { - "2.14.0 and below": (ivy.bfloat16, ivy.float16, ivy.float32, ivy.float64) + "2.15.0 and below": (ivy.bfloat16, ivy.float16, ivy.float32, ivy.float64) } valid_uint_dtypes = { - "2.14.0 and below": (ivy.uint8, ivy.uint16, ivy.uint32, ivy.uint64) + "2.15.0 and below": (ivy.uint8, ivy.uint16, ivy.uint32, ivy.uint64) } -valid_complex_dtypes = {"2.14.0 and below": (ivy.complex64, ivy.complex128)} +valid_complex_dtypes = {"2.15.0 and below": (ivy.complex64, ivy.complex128)} # leave these untouched valid_dtypes = _dtype_from_version(valid_dtypes, backend_version) @@ -194,12 +194,12 @@ def rep_method(*args, **kwargs): # invalid data types # update these to add new dtypes -invalid_dtypes = {"2.14.0 and below": ()} -invalid_numeric_dtypes = {"2.14.0 and below": ()} -invalid_int_dtypes = {"2.14.0 and below": ()} -invalid_float_dtypes = {"2.14.0 and below": ()} -invalid_uint_dtypes = {"2.14.0 and below": ()} -invalid_complex_dtypes = {"2.14.0 and below": ()} +invalid_dtypes = {"2.15.0 and below": ()} +invalid_numeric_dtypes = {"2.15.0 and below": ()} +invalid_int_dtypes = {"2.15.0 and below": ()} +invalid_float_dtypes = {"2.15.0 and below": ()} +invalid_uint_dtypes = {"2.15.0 and below": ()} +invalid_complex_dtypes = {"2.15.0 and below": ()} # leave these untouched invalid_dtypes = _dtype_from_version(invalid_dtypes, backend_version) @@ -265,3 +265,9 @@ def closest_valid_dtype(type=None, /, as_native=False): # sub-backends from . import sub_backends from .sub_backends import * + +from . import module +from .module import Model + + +NativeModule = Model diff --git a/ivy/functional/backends/tensorflow/activations.py b/ivy/functional/backends/tensorflow/activations.py index 0b1a5e85a99cb..2e60ebe41688e 100644 --- a/ivy/functional/backends/tensorflow/activations.py +++ b/ivy/functional/backends/tensorflow/activations.py @@ -1,5 +1,4 @@ -""" -TensorFlow activation functions. +"""TensorFlow activation functions. Collection of TensorFlow activation functions, wrapped to fit Ivy syntax and signature. @@ -41,6 +40,16 @@ def leaky_relu( return tf.nn.leaky_relu(x, alpha) +@with_supported_dtypes( + { + "2.15.0 and below": ( + "float", + "int", + "complex", + ) + }, + backend_version, +) def relu(x: Tensor, /, *, complex_mode="jax", out: Optional[Tensor] = None) -> Tensor: return tf.nn.relu(x) @@ -68,7 +77,7 @@ def softmax( @with_supported_dtypes( { - "2.14.0 and below": ( + "2.15.0 and below": ( "float16", "bfloat16", "float32", @@ -102,7 +111,7 @@ def softplus( # Softsign @with_supported_dtypes( { - "2.14.0 and below": ( + "2.15.0 and below": ( "float16", "bfloat16", "float32", @@ -148,7 +157,7 @@ def mish( return tf.multiply(x, tf.math.tanh(x_norm)) -@with_unsupported_dtypes({"2.14.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("complex",)}, backend_version) def hardswish( x: Tensor, /, diff --git a/ivy/functional/backends/tensorflow/control_flow_ops.py b/ivy/functional/backends/tensorflow/control_flow_ops.py index ba6cacc5820da..375ca64e2de40 100644 --- a/ivy/functional/backends/tensorflow/control_flow_ops.py +++ b/ivy/functional/backends/tensorflow/control_flow_ops.py @@ -24,7 +24,7 @@ def test_fn_wrapper(*loop_vars): if not vars: vars = (0,) - else: + elif isinstance(vars, dict): vars = list(vars.values()) return tf.while_loop(test_fn_wrapper, body_fn_wrapper, loop_vars=vars) @@ -65,4 +65,4 @@ def _tuple_to_dict(t): def _dict_to_tuple(d): - return tuple([d[k] for k in d]) + return tuple(d[k] for k in d) diff --git a/ivy/functional/backends/tensorflow/creation.py b/ivy/functional/backends/tensorflow/creation.py index 348389832befb..2b7f602d8a2dd 100644 --- a/ivy/functional/backends/tensorflow/creation.py +++ b/ivy/functional/backends/tensorflow/creation.py @@ -26,7 +26,7 @@ @with_unsupported_dtypes( { - "2.14.0 and below": ( + "2.15.0 and below": ( "float16", "bfloat16", "complex", @@ -41,7 +41,7 @@ def arange( step: float = 1, *, dtype: Optional[tf.DType] = None, - device: str = None, + device: Optional[str] = None, out: Optional[Union[tf.Tensor, tf.Variable]] = None, ) -> Union[tf.Tensor, tf.Variable]: if stop is None: @@ -86,25 +86,30 @@ def asarray( *, copy: Optional[bool] = None, dtype: Optional[tf.DType] = None, - device: str = None, + device: Optional[str] = None, out: Optional[Union[tf.Tensor, tf.Variable]] = None, ) -> Union[tf.Tensor, tf.Variable]: # convert the input to a tensor using the appropriate function - try: - ret = tf.convert_to_tensor(obj, dtype) - except (TypeError, ValueError): - obj = ( - obj if isinstance(obj, tf.Tensor) else tf.convert_to_tensor(obj, tf.float64) - ) - ret = tf.cast(obj, dtype) - return tf.identity(ret) if copy else ret + with tf.device(device): + if tf.is_tensor(obj): + ret = tf.cast(obj, dtype) if obj.dtype != dtype else obj + elif ( + dtype is not None + and dtype.is_integer + and np.issubdtype(np.array(obj).dtype, np.floating) + ): + obj_np = np.array(obj) + ret = tf.convert_to_tensor(obj_np, dtype) + else: + ret = tf.convert_to_tensor(obj, dtype) + return tf.identity(ret) if (copy or ret.device != device) else ret def empty( shape: Union[ivy.NativeShape, Sequence[int]], *, dtype: tf.DType, - device: str = None, + device: Optional[str] = None, out: Optional[Union[tf.Tensor, tf.Variable]] = None, ) -> Union[tf.Tensor, tf.Variable]: return tf.experimental.numpy.empty(shape, dtype) @@ -115,13 +120,13 @@ def empty_like( /, *, dtype: tf.DType, - device: str = None, + device: Optional[str] = None, out: Optional[Union[tf.Tensor, tf.Variable]] = None, ) -> Union[tf.Tensor, tf.Variable]: return tf.experimental.numpy.empty_like(x, dtype=dtype) -@with_unsupported_dtypes({"2.14.0 and below": ("uint16",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("uint16",)}, backend_version) def eye( n_rows: int, n_cols: Optional[int] = None, @@ -130,7 +135,7 @@ def eye( k: int = 0, batch_shape: Optional[Union[int, Sequence[int]]] = None, dtype: tf.DType, - device: str = None, + device: Optional[str] = None, out: Optional[Union[tf.Tensor, tf.Variable]] = None, ) -> Union[tf.Tensor, tf.Variable]: if n_cols is None: @@ -192,7 +197,11 @@ def from_dlpack( ) -> Union[tf.Tensor, tf.Variable]: if isinstance(x, tf.Variable): x = x.read_value() - return tf.experimental.dlpack.from_dlpack(x) + if hasattr(x, "__dlpack__"): + capsule = x.__dlpack__() + else: + capsule = x + return tf.experimental.dlpack.from_dlpack(capsule) def full( @@ -200,7 +209,7 @@ def full( fill_value: Union[int, float, bool], *, dtype: Optional[Union[ivy.Dtype, tf.DType]] = None, - device: str = None, + device: Optional[str] = None, out: Optional[Union[tf.Tensor, tf.Variable]] = None, ) -> Union[tf.Tensor, tf.Variable]: dtype = ivy.default_dtype(dtype=dtype, item=fill_value, as_native=True) @@ -213,7 +222,7 @@ def full_like( fill_value: Number, *, dtype: tf.DType, - device: str = None, + device: Optional[str] = None, out: Optional[Union[tf.Tensor, tf.Variable]] = None, ) -> Union[tf.Tensor, tf.Variable]: return tf.experimental.numpy.full_like(x, fill_value, dtype=dtype) @@ -232,7 +241,7 @@ def linspace( axis: Optional[int] = None, endpoint: bool = True, dtype: tf.DType, - device: str = None, + device: Optional[str] = None, out: Optional[Union[tf.Tensor, tf.Variable]] = None, ): if axis is None: @@ -251,7 +260,7 @@ def linspace( return tf.cast(ans, dtype) -@with_unsupported_dtypes({"2.14.0 and below": ("bool",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("bool",)}, backend_version) def meshgrid( *arrays: Union[tf.Tensor, tf.Variable], sparse: bool = False, @@ -278,7 +287,7 @@ def ones( shape: Union[ivy.NativeShape, Sequence[int]], *, dtype: tf.DType, - device: str = None, + device: Optional[str] = None, out: Optional[Union[tf.Tensor, tf.Variable]] = None, ) -> Union[tf.Tensor, tf.Variable]: return tf.ones(shape, dtype) @@ -289,13 +298,13 @@ def ones_like( /, *, dtype: tf.DType, - device: str = None, + device: Optional[str] = None, out: Optional[Union[tf.Tensor, tf.Variable]] = None, ) -> Union[tf.Tensor, tf.Variable]: return tf.ones_like(x, dtype=dtype) -@with_unsupported_dtypes({"2.14.0 and below": ("bool",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("bool",)}, backend_version) def tril( x: Union[tf.Tensor, tf.Variable], /, @@ -308,7 +317,7 @@ def tril( return tf.experimental.numpy.tril(x, k) -@with_unsupported_dtypes({"2.14.0 and below": ("bool",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("bool",)}, backend_version) def triu( x: Union[tf.Tensor, tf.Variable], /, @@ -323,7 +332,7 @@ def zeros( shape: Union[ivy.NativeShape, Sequence[int]], *, dtype: tf.DType, - device: str = None, + device: Optional[str] = None, out: Optional[Union[tf.Tensor, tf.Variable]] = None, ) -> Union[tf.Tensor, tf.Variable]: return tf.zeros(shape, dtype) @@ -334,7 +343,7 @@ def zeros_like( /, *, dtype: tf.DType, - device: str = None, + device: Optional[str] = None, out: Optional[Union[tf.Tensor, tf.Variable]] = None, ) -> Union[tf.Tensor, tf.Variable]: return tf.zeros_like(x, dtype=dtype) @@ -348,14 +357,20 @@ def zeros_like( def copy_array( - x: Union[tf.Tensor, tf.Variable], + x: Union[tf.Tensor, tf.Variable, tf.TensorArray], *, to_ivy_array: bool = True, out: Optional[Union[tf.Tensor, tf.Variable]] = None, ) -> Union[tf.Tensor, tf.Variable]: + if isinstance(x, tf.TensorArray): + x_wrapped = x.stack() + y = tf.TensorArray(x.dtype, x.size()) + x = y.unstack(ivy.copy_array(x_wrapped)) + else: + x = tf.identity(x) if to_ivy_array: - return ivy.to_ivy(tf.identity(x)) - return tf.identity(x) + return ivy.to_ivy(x) + return x def one_hot( @@ -367,7 +382,7 @@ def one_hot( off_value: Optional[Number] = None, axis: Optional[int] = None, dtype: Optional[tf.DType] = None, - device: str = None, + device: Optional[str] = None, out: Optional[Union[tf.Tensor, tf.Variable]] = None, ) -> Union[tf.Tensor, tf.Variable]: return tf.one_hot( @@ -375,12 +390,12 @@ def one_hot( ) -@with_unsupported_dtypes({"2.14.0 and below": ("uint32", "uint64")}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("uint32", "uint64")}, backend_version) def frombuffer( buffer: bytes, - dtype: Optional[tf.DType] = float, - count: Optional[int] = -1, - offset: Optional[int] = 0, + dtype: tf.DType = float, + count: int = -1, + offset: int = 0, ) -> Union[tf.Tensor, tf.Variable]: if isinstance(buffer, bytearray): buffer = bytes(buffer) @@ -402,7 +417,7 @@ def triu_indices( k: int = 0, /, *, - device: str = None, + device: Optional[str] = None, ) -> Tuple[Union[tf.Tensor, tf.Variable]]: n_cols = n_rows if n_cols is None else n_cols diff --git a/ivy/functional/backends/tensorflow/data_type.py b/ivy/functional/backends/tensorflow/data_type.py index ef083ebb3f6c4..558120c4af568 100644 --- a/ivy/functional/backends/tensorflow/data_type.py +++ b/ivy/functional/backends/tensorflow/data_type.py @@ -117,7 +117,7 @@ def broadcast_arrays( try: desired_shape = tf.broadcast_dynamic_shape(arrays[0].shape, arrays[1].shape) except tf.errors.InvalidArgumentError as e: - raise ivy.utils.exceptions.IvyBroadcastShapeError(e) + raise ivy.utils.exceptions.IvyBroadcastShapeError(e) from e if len(arrays) > 2: for i in range(2, len(arrays)): try: @@ -125,7 +125,7 @@ def broadcast_arrays( desired_shape, arrays[i].shape ) except tf.errors.InvalidArgumentError as e: - raise ivy.utils.exceptions.IvyBroadcastShapeError(e) + raise ivy.utils.exceptions.IvyBroadcastShapeError(e) from e else: return [arrays[0]] result = [] @@ -164,7 +164,7 @@ def iinfo(type: Union[DType, str, tf.Tensor, tf.Variable, np.ndarray], /) -> np. return tf.experimental.numpy.iinfo(ivy.as_ivy_dtype(type)) -@with_unsupported_dtypes({"2.14.0 and below": ("bfloat16",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("bfloat16",)}, backend_version) def result_type( *arrays_and_dtypes: Union[tf.Tensor, tf.Variable, tf.DType], ) -> ivy.Dtype: @@ -239,7 +239,7 @@ def as_native_dtype( dtype_in = dtype_in.name if not isinstance(dtype_in, str): return dtype_in - if dtype_in in native_dtype_dict.keys(): + if dtype_in in native_dtype_dict: return native_dtype_dict[ivy.Dtype(dtype_in)] else: raise ivy.utils.exceptions.IvyException( @@ -273,10 +273,7 @@ def dtype_bits(dtype_in: Union[tf.DType, str, np.dtype], /) -> int: def is_native_dtype(dtype_in: Union[tf.DType, str], /) -> bool: if not ivy.is_hashable_dtype(dtype_in): return False - if dtype_in in ivy_dtype_dict and isinstance(dtype_in, tf.dtypes.DType): - return True - else: - return False + return bool(dtype_in in ivy_dtype_dict and isinstance(dtype_in, tf.dtypes.DType)) # ToDo: diff --git a/ivy/functional/backends/tensorflow/device.py b/ivy/functional/backends/tensorflow/device.py index d5ec902b1db09..6805d3013ca4b 100644 --- a/ivy/functional/backends/tensorflow/device.py +++ b/ivy/functional/backends/tensorflow/device.py @@ -1,5 +1,4 @@ -""" -Tensorflow device functions. +"""Tensorflow device functions. Collection of TensorFlow general functions, wrapped to fit Ivy syntax and signature. @@ -24,14 +23,18 @@ def _same_device(dev_a, dev_b): def dev( - x: Union[tf.Tensor, tf.Variable], + x: Union[tf.Tensor, tf.Variable, tf.TensorArray], /, *, as_native: bool = False, ) -> Union[ivy.Device, str]: + if isinstance(x, tf.TensorArray): + # Read the underlying tensor being wrapped to get the device. + x = x.stack() dv = x.device if as_native: return dv + dv = dv if dv else ivy.default_device(as_native=False) return as_ivy_dev(dv) @@ -48,7 +51,7 @@ def to_device( device = as_native_dev(device) current_dev = dev(x) if not _same_device(current_dev, device): - with tf.device("/" + device.upper()): + with tf.device(f"/{device.upper()}"): return tf.identity(x) return x @@ -63,13 +66,13 @@ def as_ivy_dev(device: str, /): dev_type = dev_type.lower() if dev_type == "cpu": return ivy.Device(dev_type) - return ivy.Device(":".join([dev_type, dev_idx])) + return ivy.Device(f"{dev_type}:{dev_idx}") def as_native_dev(device: str, /): if isinstance(device, str) and "/" in device: return device - ret = "/" + ivy.Device(device).upper() + ret = f"/{ivy.Device(device).upper()}" if not ret[-1].isnumeric(): ret += ":0" return ret diff --git a/ivy/functional/backends/tensorflow/elementwise.py b/ivy/functional/backends/tensorflow/elementwise.py index 5fd6391aa85b0..c1a1c0c289491 100644 --- a/ivy/functional/backends/tensorflow/elementwise.py +++ b/ivy/functional/backends/tensorflow/elementwise.py @@ -2,7 +2,6 @@ from typing import Union, Optional import tensorflow as tf - # local import ivy from ivy.func_wrapper import with_unsupported_dtypes, with_supported_dtypes @@ -23,6 +22,7 @@ def abs( return tf.abs(x) +@with_unsupported_dtypes({"2.15.0 and below": ("unsigned", "bool")}, backend_version) def acos( x: Union[tf.Tensor, tf.Variable], /, @@ -50,6 +50,8 @@ def add( out: Optional[Union[tf.Tensor, tf.Variable]] = None, ) -> Union[tf.Tensor, tf.Variable]: x1, x2 = ivy.promote_types_of_inputs(x1, x2) + if x1.dtype.is_bool and x2.dtype.is_bool: + return tf.math.logical_or(x1, x2) if alpha not in (1, None): with ivy.ArrayMode(False): x2 = multiply(x2, alpha) @@ -83,7 +85,7 @@ def atan( return tf.math.atan(x) -@with_unsupported_dtypes({"2.14.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("complex",)}, backend_version) def atan2( x1: Union[tf.Tensor, tf.Variable], x2: Union[tf.Tensor, tf.Variable], @@ -104,7 +106,7 @@ def atanh( return tf.math.atanh(x) -@with_unsupported_dtypes({"2.14.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("complex",)}, backend_version) def bitwise_and( x1: Union[int, tf.Tensor, tf.Variable], x2: Union[int, tf.Tensor, tf.Variable], @@ -119,7 +121,7 @@ def bitwise_and( return tf.bitwise.bitwise_and(x1, x2) -@with_unsupported_dtypes({"2.14.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("complex",)}, backend_version) def bitwise_invert( x: Union[int, tf.Tensor, tf.Variable], /, @@ -132,7 +134,7 @@ def bitwise_invert( return tf.bitwise.invert(x) -@with_unsupported_dtypes({"2.14.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("complex",)}, backend_version) def bitwise_left_shift( x1: Union[int, tf.Tensor, tf.Variable], x2: Union[int, tf.Tensor, tf.Variable], @@ -144,7 +146,7 @@ def bitwise_left_shift( return tf.bitwise.left_shift(x1, x2) -@with_unsupported_dtypes({"2.14.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("complex",)}, backend_version) def bitwise_or( x1: Union[int, tf.Tensor, tf.Variable], x2: Union[int, tf.Tensor, tf.Variable], @@ -159,7 +161,7 @@ def bitwise_or( return tf.bitwise.bitwise_or(x1, x2) -@with_unsupported_dtypes({"2.14.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("complex",)}, backend_version) def bitwise_right_shift( x1: Union[int, tf.Tensor, tf.Variable], x2: Union[int, tf.Tensor, tf.Variable], @@ -171,7 +173,7 @@ def bitwise_right_shift( return tf.bitwise.right_shift(x1, x2) -@with_unsupported_dtypes({"2.14.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("complex",)}, backend_version) def bitwise_xor( x1: Union[int, tf.Tensor, tf.Variable], x2: Union[int, tf.Tensor, tf.Variable], @@ -186,7 +188,7 @@ def bitwise_xor( return tf.bitwise.bitwise_xor(x1, x2) -@with_unsupported_dtypes({"2.14.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("complex",)}, backend_version) def ceil( x: Union[tf.Tensor, tf.Variable], /, @@ -199,6 +201,7 @@ def ceil( return tf.math.ceil(x) +@with_unsupported_dtypes({"2.15.0 and below": ("integer",)}, backend_version) def cos( x: Union[tf.Tensor, tf.Variable], /, @@ -208,7 +211,7 @@ def cos( return tf.cos(x) -@with_unsupported_dtypes({"2.14.0 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("float16",)}, backend_version) def cosh( x: Union[tf.Tensor, tf.Variable], /, @@ -245,6 +248,7 @@ def equal( return tf.math.equal(x1, x2) +@with_unsupported_dtypes({"2.15.0 and below": ("integer",)}, backend_version) def exp( x: Union[tf.Tensor, tf.Variable], /, @@ -263,7 +267,7 @@ def exp2( return tf.math.pow(2, x, name=None) -@with_supported_dtypes({"2.14.0 and below": ("float", "complex")}, backend_version) +@with_supported_dtypes({"2.15.0 and below": ("float", "complex")}, backend_version) def expm1( x: Union[tf.Tensor, tf.Variable], /, @@ -273,7 +277,7 @@ def expm1( return tf.math.expm1(x) -@with_unsupported_dtypes({"2.14.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("complex",)}, backend_version) def floor( x: Union[tf.Tensor, tf.Variable], /, @@ -286,7 +290,7 @@ def floor( return tf.math.floor(x) -@with_unsupported_dtypes({"2.14.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("complex",)}, backend_version) def floor_divide( x1: Union[float, tf.Tensor, tf.Variable], x2: Union[float, tf.Tensor, tf.Variable], @@ -298,7 +302,7 @@ def floor_divide( return tf.experimental.numpy.floor_divide(x1, x2) -@with_supported_dtypes({"2.14.0 and below": ("float",)}, backend_version) +@with_supported_dtypes({"2.15.0 and below": ("float",)}, backend_version) def fmin( x1: Union[tf.Tensor, tf.Variable], x2: Union[tf.Tensor, tf.Variable], @@ -313,7 +317,7 @@ def fmin( return ret -@with_unsupported_dtypes({"2.14.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("complex",)}, backend_version) def greater( x1: Union[float, tf.Tensor, tf.Variable], x2: Union[float, tf.Tensor, tf.Variable], @@ -325,7 +329,7 @@ def greater( return tf.experimental.numpy.greater(x1, x2) -@with_unsupported_dtypes({"2.14.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("complex",)}, backend_version) def greater_equal( x1: Union[float, tf.Tensor, tf.Variable], x2: Union[float, tf.Tensor, tf.Variable], @@ -374,7 +378,7 @@ def isinf( return tf.zeros_like(x, tf.bool) -@with_unsupported_dtypes({"2.14.0 and below": ("complex", "bool")}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("complex", "bool")}, backend_version) def isnan( x: Union[tf.Tensor, tf.Variable], /, @@ -387,7 +391,7 @@ def isnan( return tf.math.is_nan(x) -@with_unsupported_dtypes({"2.14.0 and below": ("unsigned",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("unsigned",)}, backend_version) def lcm( x1: Union[tf.Tensor, tf.Variable], x2: Union[tf.Tensor, tf.Variable], @@ -401,7 +405,7 @@ def lcm( @with_unsupported_dtypes( { - "2.14.0 and below": ( + "2.15.0 and below": ( "bool", "complex", ) @@ -419,7 +423,7 @@ def less( return tf.math.less(x1, x2) -@with_unsupported_dtypes({"2.14.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("complex", "bool")}, backend_version) def less_equal( x1: Union[float, tf.Tensor, tf.Variable], x2: Union[float, tf.Tensor, tf.Variable], @@ -431,6 +435,9 @@ def less_equal( return tf.math.less_equal(x1, x2) +@with_unsupported_dtypes( + {"2.15.0 and below": ("float16", "bfloat16", "integer")}, backend_version +) def log( x: Union[tf.Tensor, tf.Variable], /, @@ -467,7 +474,7 @@ def log2( return tf.math.log(x) / tf.math.log(tf.constant(2.0, x.dtype)) -@with_unsupported_dtypes({"2.14.0 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("float16", "bfloat16")}, backend_version) def logaddexp( x1: Union[tf.Tensor, tf.Variable], x2: Union[tf.Tensor, tf.Variable], @@ -479,7 +486,7 @@ def logaddexp( return tf.experimental.numpy.logaddexp(x1, x2) -@with_unsupported_dtypes({"2.14.0 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("float16",)}, backend_version) def real( x: Union[tf.Tensor, tf.Variable], /, @@ -491,7 +498,7 @@ def real( @with_unsupported_dtypes( { - "2.14.0 and below": ( + "2.15.0 and below": ( "uint8", "uint16", "uint32", @@ -563,7 +570,7 @@ def logical_xor( return tf.math.logical_xor(tf.cast(x1, tf.bool), tf.cast(x2, tf.bool)) -@with_unsupported_dtypes({"2.14.0 and below": ("bool",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("bool",)}, backend_version) def multiply( x1: Union[float, tf.Tensor, tf.Variable], x2: Union[float, tf.Tensor, tf.Variable], @@ -575,7 +582,7 @@ def multiply( return tf.math.multiply(x1, x2) -@with_unsupported_dtypes({"2.14.0 and below": ("bool", "unsigned")}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("bool", "unsigned")}, backend_version) def negative( x: Union[float, tf.Tensor, tf.Variable], /, @@ -605,7 +612,7 @@ def positive( return tf.experimental.numpy.positive(x) -@with_unsupported_dtypes({"2.14.0 and below": ("bool", "unsigned")}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("bool", "unsigned")}, backend_version) def pow( x1: Union[tf.Tensor, tf.Variable], x2: Union[int, float, tf.Tensor, tf.Variable], @@ -630,7 +637,7 @@ def pow( return tf.experimental.numpy.power(x1, x2) -@with_unsupported_dtypes({"2.14.0 and below": ("bfloat16", "complex")}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("bfloat16", "complex")}, backend_version) def remainder( x1: Union[float, tf.Tensor, tf.Variable], x2: Union[float, tf.Tensor, tf.Variable], @@ -649,7 +656,7 @@ def remainder( return tf.experimental.numpy.remainder(x1, x2) -@with_unsupported_dtypes({"2.14.0 and below": ("bfloat16", "complex")}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("bfloat16", "complex")}, backend_version) def round( x: Union[tf.Tensor, tf.Variable], /, @@ -670,7 +677,7 @@ def round( return tf.cast(tf.round(x * factor) / factor_deno, ret_dtype) -@with_unsupported_dtypes({"2.14.0 and below": ("bool", "unsigned")}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("bool", "unsigned")}, backend_version) def sign( x: Union[tf.Tensor, tf.Variable], /, @@ -765,7 +772,7 @@ def trapz( # TODO: Implement purely in tensorflow -@with_unsupported_dtypes({"2.14.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("complex",)}, backend_version) def trunc( x: Union[tf.Tensor, tf.Variable], /, @@ -792,7 +799,7 @@ def trunc( # ------# -@with_unsupported_dtypes({"2.14.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("complex",)}, backend_version) def erf( x: Union[tf.Tensor, tf.Variable], /, @@ -802,7 +809,7 @@ def erf( return tf.math.erf(x) -@with_unsupported_dtypes({"2.14.0 and below": ("complex", "bool")}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("complex", "bool")}, backend_version) def maximum( x1: Union[tf.Tensor, tf.Variable], x2: Union[tf.Tensor, tf.Variable], @@ -815,7 +822,7 @@ def maximum( return tf.math.maximum(x1, x2) -@with_unsupported_dtypes({"2.14.0 and below": ("complex", "bool")}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("complex", "bool")}, backend_version) def minimum( x1: Union[tf.Tensor, tf.Variable], x2: Union[tf.Tensor, tf.Variable], @@ -830,7 +837,7 @@ def minimum( @with_unsupported_dtypes( { - "2.14.0 and below": ( + "2.15.0 and below": ( "uint8", "uint16", "uint32", @@ -849,19 +856,23 @@ def reciprocal( *, out: Optional[Union[tf.Tensor, tf.Variable]] = None, ) -> Union[tf.Tensor, tf.Variable]: + if x.dtype.is_integer: + x = tf.cast(x, tf.float32) return tf.math.reciprocal(x) -@with_unsupported_dtypes({"2.14.0 and below": ("bfloat16",)}, backend_version) +@with_supported_dtypes({"2.15.0 and below": ("float",)}, backend_version) def deg2rad( x: Union[tf.Tensor, tf.Variable], /, *, out: Optional[Union[tf.Tensor, tf.Variable]] = None, ) -> Union[tf.Tensor, tf.Variable]: - return tf.experimental.numpy.deg2rad(x) + radians = x * ivy.pi / 180.0 + return radians +@with_supported_dtypes({"2.15.0 and below": ("float",)}, backend_version) def rad2deg( x: Union[tf.Tensor, tf.Variable], /, @@ -881,7 +892,7 @@ def isreal( @with_unsupported_dtypes( - {"2.14.0 and below": ("uint8", "uint16", "uint32", "uint64", "complex", "bool")}, + {"2.15.0 and below": ("uint8", "uint16", "uint32", "uint64", "complex", "bool")}, backend_version, ) def fmod( @@ -898,7 +909,7 @@ def fmod( @with_unsupported_dtypes( - {"2.14.0 and below": ("uint8", "uint16", "uint32", "uint64")}, backend_version + {"2.15.0 and below": ("uint8", "uint16", "uint32", "uint64")}, backend_version ) def gcd( x1: Union[tf.Tensor, tf.Variable, int, list, tuple], @@ -916,7 +927,7 @@ def gcd( @with_unsupported_dtypes( { - "2.14.0 and below": ( + "2.15.0 and below": ( "uint8", "uint16", "uint32", @@ -942,7 +953,7 @@ def angle( @with_unsupported_dtypes( { - "2.14.0 and below": ( + "2.15.0 and below": ( "uint8", "uint16", "uint32", diff --git a/ivy/functional/backends/tensorflow/experimental/activations.py b/ivy/functional/backends/tensorflow/experimental/activations.py index 8427d803331f5..259c82c3255ce 100644 --- a/ivy/functional/backends/tensorflow/experimental/activations.py +++ b/ivy/functional/backends/tensorflow/experimental/activations.py @@ -26,7 +26,7 @@ def logit( return tf.cast(tf.math.log(x / (1 - x)), x_dtype) -@with_unsupported_dtypes({"2.14.0 and below": ("complex", "bool")}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("complex", "bool")}, backend_version) def thresholded_relu( x: Tensor, /, @@ -42,7 +42,7 @@ def relu6(x: Tensor, /, *, complex_mode="jax", out: Optional[Tensor] = None) -> return tf.nn.relu6(x) -@with_supported_dtypes({"2.14.0 and below": ("float",)}, backend_version) +@with_supported_dtypes({"2.15.0 and below": ("float",)}, backend_version) def logsigmoid( input: Tensor, /, *, complex_mode="jax", out: Optional[Tensor] = None ) -> Tensor: @@ -51,7 +51,7 @@ def logsigmoid( return tf.math.log_sigmoid(input) -@with_supported_dtypes({"2.14.0 and below": ("float",)}, backend_version) +@with_supported_dtypes({"2.15.0 and below": ("float",)}, backend_version) def selu(x: Tensor, /, *, out: Optional[Tensor] = None) -> Tensor: ret = tf.nn.selu(x) if ivy.exists(out): @@ -59,7 +59,7 @@ def selu(x: Tensor, /, *, out: Optional[Tensor] = None) -> Tensor: return ivy.astype(ret, x.dtype) -@with_unsupported_dtypes({"2.14.0 and below": ("complex",)}, backend_version) +@with_supported_dtypes({"2.15.0 and below": ("float",)}, backend_version) def silu( x: Tensor, /, @@ -72,16 +72,15 @@ def silu( return ivy.astype(ret, x.dtype) -@with_supported_dtypes({"2.14.0 and below": ("float",)}, backend_version) +@with_supported_dtypes({"2.15.0 and below": ("float",)}, backend_version) def elu(x: Tensor, /, *, alpha: float = 1.0, out: Optional[Tensor] = None) -> Tensor: - alpha = tf.cast(alpha, x.dtype) - ret = tf.cast(tf.where(x > 0, x, tf.multiply(alpha, tf.math.expm1(x))), x.dtype) + ret = tf.keras.activations.elu(x, alpha) if ivy.exists(out): return ivy.inplace_update(out, ret).astype(x.dtype) return ivy.astype(ret, x.dtype) -@with_supported_dtypes({"2.14.0 and below": ("float",)}, backend_version) +@with_supported_dtypes({"2.15.0 and below": ("float",)}, backend_version) def hardtanh( x: Tensor, /, @@ -100,7 +99,7 @@ def hardtanh( return ivy.astype(ret, x.dtype) -@with_supported_dtypes({"2.14.0 and below": ("float",)}, backend_version) +@with_supported_dtypes({"2.15.0 and below": ("float",)}, backend_version) def tanhshrink( x: Tensor, /, @@ -113,7 +112,22 @@ def tanhshrink( return ivy.astype(ret, x.dtype) -@with_supported_dtypes({"2.14.0 and below": ("float",)}, backend_version) +@with_supported_dtypes({"2.15.0 and below": ("float",)}, backend_version) +def threshold( + x: Tensor, + /, + *, + threshold: Union[int, float], + value: Union[int, float], + out: Optional[Tensor] = None, +) -> Tensor: + ret = tf.where(x > threshold, x, value) + if ivy.exists(out): + return ivy.inplace_update(out, ret).astype(x.dtype) + return ivy.astype(ret, x.dtype) + + +@with_supported_dtypes({"2.15.0 and below": ("float",)}, backend_version) def softshrink( x: Tensor, /, @@ -131,7 +145,7 @@ def softshrink( return ivy.astype(ret, x.dtype) -@with_unsupported_dtypes({"2.14.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("complex",)}, backend_version) def celu( x: Tensor, /, @@ -143,7 +157,7 @@ def celu( return tf.math.maximum(0, x) + alpha * tf.math.expm1(tf.math.minimum(0, x) / alpha) -@with_unsupported_dtypes({"2.14.0 and below": ("uint16",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("uint16",)}, backend_version) def scaled_tanh( x: Tensor, /, @@ -155,7 +169,7 @@ def scaled_tanh( return alpha * tf.nn.tanh(beta * x) -@with_supported_dtypes({"2.14.0 and below": ("float",)}, backend_version) +@with_supported_dtypes({"2.15.0 and below": ("float",)}, backend_version) def hardshrink( x: Tensor, /, @@ -171,3 +185,13 @@ def hardshrink( if ivy.exists(out): return ivy.inplace_update(out, ret).astype(x.dtype) return ivy.astype(ret, x.dtype) + + +@with_unsupported_dtypes({"2.14.0 and below": ("complex",)}, backend_version) +def hardsilu( + x: Tensor, /, *, complex_mode="jax", out: Optional[Tensor] = None +) -> Tensor: + ret = tf.multiply(x, tf.nn.relu6(tf.math.add(x, 3)) / 6) + if ivy.exists(out): + return ivy.inplace_update(out, ret).astype(x.dtype) + return ivy.astype(ret, x.dtype) diff --git a/ivy/functional/backends/tensorflow/experimental/creation.py b/ivy/functional/backends/tensorflow/experimental/creation.py index e86263c7d3f76..9f648ce9ec018 100644 --- a/ivy/functional/backends/tensorflow/experimental/creation.py +++ b/ivy/functional/backends/tensorflow/experimental/creation.py @@ -13,7 +13,7 @@ @with_unsupported_device_and_dtypes( - {"2.14.0 and below": {"cpu": ("bfloat16",)}}, + {"2.15.0 and below": {"cpu": ("bfloat16",)}}, backend_version, ) def kaiser_window( @@ -73,7 +73,7 @@ def tril_indices( k: int = 0, /, *, - device: str = None, + device: Optional[str] = None, ) -> Tuple[Union[tf.Tensor, tf.Variable], ...]: n_cols = n_rows if n_cols is None else n_cols @@ -130,7 +130,7 @@ def unsorted_segment_sum( return tf.math.unsorted_segment_sum(data, segment_ids, num_segments) -@with_unsupported_dtypes({"2.14.0 and below": ("bool",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("bool",)}, backend_version) def trilu( x: Union[tf.Tensor, tf.Variable], /, @@ -160,6 +160,14 @@ def mel_weight_matrix( ) +def unsorted_segment_mean( + data: tf.Tensor, + segment_ids: tf.Tensor, + num_segments: Union[int, tf.Tensor], +) -> tf.Tensor: + return tf.math.unsorted_segment_mean(data, segment_ids, num_segments) + + @with_unsupported_dtypes( {"2.13.0 and below": ("bool", "bfloat16", "float16", "complex")}, backend_version ) diff --git a/ivy/functional/backends/tensorflow/experimental/elementwise.py b/ivy/functional/backends/tensorflow/experimental/elementwise.py index 9fb8df7bd3f1d..977e0d0584c87 100644 --- a/ivy/functional/backends/tensorflow/experimental/elementwise.py +++ b/ivy/functional/backends/tensorflow/experimental/elementwise.py @@ -54,7 +54,7 @@ def amin( @with_supported_dtypes( - {"2.14.0 and below": ("float16", "float32", "float64")}, + {"2.15.0 and below": ("float16", "float32", "float64")}, backend_version, ) def lgamma( @@ -77,7 +77,7 @@ def sinc( @with_supported_dtypes( - {"2.14.0 and below": ("bfloat16", "float16", "float32", "float64")}, backend_version + {"2.15.0 and below": ("bfloat16", "float16", "float32", "float64")}, backend_version ) def fmax( x1: Union[tf.Tensor, tf.Variable], @@ -93,7 +93,7 @@ def fmax( @with_unsupported_dtypes( - {"2.14.0 and below": ("uint8", "uint16", "uint32", "uint64")}, backend_version + {"2.15.0 and below": ("uint8", "uint16", "uint32", "uint64")}, backend_version ) def float_power( x1: Union[tf.Tensor, tf.Variable, float, list, tuple], @@ -145,7 +145,7 @@ def count_nonzero( ) -@with_unsupported_dtypes({"2.14.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("complex",)}, backend_version) def nansum( x: Union[tf.Tensor, tf.Variable], /, @@ -208,7 +208,7 @@ def allclose( ) -@with_unsupported_dtypes({"2.14.0 and below": ("bfloat16",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("bfloat16",)}, backend_version) def fix( x: Union[tf.Tensor, tf.Variable], /, @@ -218,7 +218,7 @@ def fix( return tf.cast(tf.where(x > 0, tf.math.floor(x), tf.math.ceil(x)), x.dtype) -@with_unsupported_dtypes({"2.14.0 and below": ("bflaot16", "float16")}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("bflaot16", "float16")}, backend_version) def nextafter( x1: Union[tf.Tensor, tf.Variable], x2: Union[tf.Tensor, tf.Variable], @@ -230,7 +230,7 @@ def nextafter( @with_unsupported_dtypes( - {"2.14.0 and below": ("uint8", "uint16", "uint32", "uint64")}, backend_version + {"2.15.0 and below": ("uint8", "uint16", "uint32", "uint64")}, backend_version ) def diff( x: Union[tf.Tensor, tf.Variable, list, tuple], @@ -253,7 +253,7 @@ def diff( @with_supported_dtypes( { - "2.14.0 and below": ( + "2.15.0 and below": ( "float32", "float64", ) @@ -282,7 +282,7 @@ def _normalize_axis_tuple(axis: Union[int, list, tuple], ndim: int) -> Tuple[int axis = [operator.index(axis)] except TypeError: pass - axis = tuple([_normalize_axis_index(ax, ndim) for ax in axis]) + axis = tuple(_normalize_axis_index(ax, ndim) for ax in axis) if len(set(axis)) != len(axis): raise ValueError("repeated axis") return axis @@ -297,7 +297,6 @@ def gradient( edge_order: int = 1, ) -> Union[tf.Tensor, List[tf.Tensor]]: # https://github.com/numpy/numpy/blob/v1.24.3/numpy/lib/function_base.py#L969-L1312 - x.device x = tf.experimental.numpy.asanyarray(x) N = x.ndim # number of dimensions if axis is None: @@ -470,7 +469,7 @@ def gradient( @with_supported_dtypes( { - "2.14.0 and below": ( + "2.15.0 and below": ( "float16", "float32", "float64", @@ -500,7 +499,7 @@ def conj( return tf.math.conj(x) -@with_unsupported_dtypes({"2.14.0 and below": ("unsigned",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("unsigned",)}, backend_version) def ldexp( x1: Union[tf.Tensor, tf.Variable], x2: Union[tf.Tensor, tf.Variable, int], @@ -521,7 +520,7 @@ def ldexp( return tf.cast(ret, out_dtype) -@with_unsupported_dtypes({"2.14.0 and below": ("unsigned",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("unsigned",)}, backend_version) def frexp( x: Union[tf.Tensor, tf.Variable], /, @@ -539,13 +538,16 @@ def frexp( return m, e +@with_supported_dtypes({"2.15.0 and below": ("float",)}, backend_version) def modf( x: Union[tf.Tensor, tf.Variable], /, *, out: Optional[Union[tf.Tensor, tf.Variable]] = None, -) -> Union[tf.Tensor, tf.Variable]: - return tf.math.modf(x) +) -> Tuple[Union[tf.Tensor, tf.Variable], Union[tf.Tensor, tf.Variable]]: + integer_part = tf.math.floor(x) + fractional_part = x - integer_part + return fractional_part, integer_part def digamma( @@ -564,3 +566,13 @@ def erfc( out: Optional[Union[tf.Tensor, tf.Variable]] = None, ) -> Union[tf.Tensor, tf.Variable]: return tf.math.erfc(x) + + +@with_supported_dtypes({"2.15.0 and below": ("float",)}, backend_version) +def erfinv( + x: Union[tf.Tensor, tf.Variable], + /, + *, + out: Optional[Union[tf.Tensor, tf.Variable]] = None, +) -> Union[tf.Tensor, tf.Variable]: + return tf.math.erfinv(x) diff --git a/ivy/functional/backends/tensorflow/experimental/layers.py b/ivy/functional/backends/tensorflow/experimental/layers.py index 00bd0e8fed60c..3aa7d1126f5fe 100644 --- a/ivy/functional/backends/tensorflow/experimental/layers.py +++ b/ivy/functional/backends/tensorflow/experimental/layers.py @@ -5,6 +5,8 @@ # local from ivy.func_wrapper import ( + inputs_to_ivy_arrays, + output_to_native_arrays, with_unsupported_dtypes, with_supported_dtypes, with_supported_device_and_dtypes, @@ -47,49 +49,57 @@ def max_pool1d( kernel, strides, padding, dilation, ceil_mode, dims, data_format ) - if data_format == "NCW": + permuted_x = False + if data_format == "NCW" and ivy.dev(x) == "cpu": x = tf.transpose(x, (0, 2, 1)) kernel = [kernel[i] for i in [0, 2, 1]] if len(kernel) == (dims + 2) else kernel strides = ( [strides[i] for i in [0, 2, 1]] if len(strides) == (dims + 2) else strides ) - padding = ( - [padding[i] for i in [0, 2, 1]] - if isinstance(padding, list) and len(padding) == (dims + 2) - else padding - ) + data_format = "NWC" + permuted_x = True # determine depth pooling x, kernel, strides, depth_pooling = _determine_depth_max_pooling( - x, kernel, strides, dims, data_format="channel_last" + x, kernel, strides, dims, data_format=data_format ) if not depth_pooling: - new_kernel = [kernel[0] + (kernel[0] - 1) * (dilation[0] - 1)] - if isinstance(padding, str): - pad_w = _handle_padding(x.shape[1], strides[0], new_kernel[0], padding) - padding = [(pad_w // 2, pad_w - pad_w // 2)] - if ceil_mode: + new_kernel = [kernel[0] + (kernel[0] - 1) * (dilation[0] - 1)] + if data_format == "NCW": + x_shape = x.shape[2:] + else: + x_shape = x.shape[1:-1] + if isinstance(padding, str): + pad_w = _handle_padding(x_shape[0], strides[0], new_kernel[0], padding) + padding = [(pad_w // 2, pad_w - pad_w // 2)] padding[0] = _padding_ceil_mode( - x.shape[1], new_kernel[0], padding[0], strides[0] + x_shape[0], new_kernel[0], padding[0], strides[0] ) - padding = [(0, 0)] + list(padding) + [(0, 0)] - x = tf.pad(x, padding, constant_values=-math.inf) - elif isinstance(padding, list) and any( - item != 0 for sublist in padding for item in sublist - ): - raise NotImplementedError( - "Nonzero explicit padding is not supported for depthwise max pooling" - ) - - res = tf.nn.pool(x, kernel, "MAX", strides, "VALID", dilations=dilation) + if isinstance(padding, list): + if any(item != 0 for sublist in padding for item in sublist): + if len(padding) < dims + 2: + if data_format == "NCW": + padding = [(0, 0), (0, 0), *padding] + else: + padding = [(0, 0), *padding, (0, 0)] + x = tf.pad(x, padding, constant_values=tf.math.reduce_min(x)) + padding = "VALID" + elif isinstance(padding, list): + if any(item != 0 for sublist in padding for item in sublist): + raise NotImplementedError( + "Nonzero explicit padding is not supported for depthwise max pooling" + ) + else: + padding = "VALID" + res = tf.nn.pool( + x, kernel, "MAX", strides, padding, dilations=dilation, data_format=data_format + ) if depth_pooling: res = tf.transpose(res, (0, 2, 1)) - # converting minimum value to -inf because tensorflow clips -inf to minimum value - res = tf.where(res <= ivy.finfo(res.dtype).min, -math.inf, res) - if data_format == "NCW": + if permuted_x: return tf.transpose(res, (0, 2, 1)) return res @@ -111,7 +121,8 @@ def max_pool2d( kernel, strides, padding, dilation, ceil_mode, dims, data_format ) - if data_format == "NCHW": + permuted_x = False + if data_format == "NCHW" and ivy.dev(x) == "cpu": x = tf.transpose(x, (0, 2, 3, 1)) kernel = ( [kernel[i] for i in [0, 2, 3, 1]] if len(kernel) == (dims + 2) else kernel @@ -121,58 +132,72 @@ def max_pool2d( if len(strides) == (dims + 2) else strides ) - padding = ( - [padding[i] for i in [0, 2, 3, 1]] - if isinstance(padding, list) and len(padding) == (dims + 2) - else padding - ) + data_format = "NHWC" + permuted_x = True # determine depth pooling x, kernel, strides, depth_pooling = _determine_depth_max_pooling( - x, kernel, strides, dims, data_format="channel_last" + x, kernel, strides, dims, data_format=data_format ) if not depth_pooling: - new_kernel = [ - kernel[i] + (kernel[i] - 1) * (dilation[i] - 1) for i in range(dims) - ] - if isinstance(padding, str): - pad_h = _handle_padding(x.shape[1], strides[0], new_kernel[0], padding) - pad_w = _handle_padding(x.shape[2], strides[1], new_kernel[1], padding) - padding = [ - (pad_h // 2, pad_h - pad_h // 2), - (pad_w // 2, pad_w - pad_w // 2), - ] - if ceil_mode: - x_shape = x.shape[1:-1] - + new_kernel = [ + kernel[i] + (kernel[i] - 1) * (dilation[i] - 1) for i in range(dims) + ] + if data_format == "NCHW": + x_shape = x.shape[2:] + else: + x_shape = x.shape[1:-1] + if isinstance(padding, str): + pad_h = _handle_padding(x_shape[0], strides[0], new_kernel[0], padding) + pad_w = _handle_padding(x_shape[1], strides[1], new_kernel[1], padding) + padding = [ + (pad_h // 2, pad_h - pad_h // 2), + (pad_w // 2, pad_w - pad_w // 2), + ] for i in range(dims): padding[i] = _padding_ceil_mode( x_shape[i], new_kernel[i], padding[i], strides[i] ) - padding = [(0, 0)] + list(padding) + [(0, 0)] - x = tf.pad(x, padding, constant_values=-math.inf) - elif isinstance(padding, list) and any( - item != 0 for sublist in padding for item in sublist - ): - raise NotImplementedError( - "Nonzero explicit padding is not supported for depthwise max pooling" + if isinstance(padding, list): + if any(item != 0 for sublist in padding for item in sublist): + if len(padding) < dims + 2: + if data_format == "NCHW": + padding = [(0, 0), (0, 0), *padding] + else: + padding = [(0, 0), *padding, (0, 0)] + x = tf.pad(x, padding, constant_values=tf.math.reduce_min(x)) + padding = "VALID" + elif isinstance(padding, list): + if any(item != 0 for sublist in padding for item in sublist): + raise NotImplementedError( + "Nonzero explicit padding is not supported for depthwise max pooling" + ) + else: + padding = "VALID" + if any(d > 1 for d in dilation): + res = tf.nn.pool( + x, + kernel, + "MAX", + strides, + padding, + dilations=dilation, + data_format=data_format, ) - - res = tf.nn.pool(x, kernel, "MAX", strides, "VALID", dilations=dilation) + else: # faster + res = tf.nn.max_pool2d(x, kernel, strides, padding, data_format=data_format) if depth_pooling: res = tf.transpose(res, (0, 2, 3, 1)) - # converting minimum value to -inf because tensorflow clips -inf to minimum value - res = tf.where(res <= ivy.finfo(res.dtype).min, -math.inf, res) - if data_format == "NCHW": + if permuted_x: return tf.transpose(res, (0, 3, 1, 2)) return res @with_unsupported_dtypes( - {"2.14.0 and below": ("bfloat16", "float64", "float16")}, backend_version + {"2.15.0 and below": ("bfloat16", "float64", "float16")}, backend_version ) def max_pool3d( x: Union[tf.Tensor, tf.Variable], @@ -191,7 +216,8 @@ def max_pool3d( kernel, strides, padding, dilation, ceil_mode, dims, data_format ) - if data_format == "NCDHW": + permuted_x = False + if data_format == "NCDHW" and ivy.dev(x) == "cpu": x = tf.transpose(x, (0, 2, 3, 4, 1)) kernel = ( [kernel[i] for i in [0, 2, 3, 4, 1]] @@ -203,51 +229,59 @@ def max_pool3d( if len(strides) == (dims + 2) else strides ) - padding = ( - [padding[i] for i in [0, 2, 3, 4, 1]] - if isinstance(padding, list) and len(padding) == (dims + 2) - else padding - ) + data_format = "NDHWC" + permuted_x = True # determine depth pooling x, kernel, strides, depth_pooling = _determine_depth_max_pooling( - x, kernel, strides, dims, data_format="channel_last" + x, kernel, strides, dims, data_format=data_format ) if not depth_pooling: - new_kernel = [dilation[i] * (kernel[i] - 1) + 1 for i in range(dims)] - x_shape = x.shape[1:-1] - if isinstance(padding, str): - pad_d = _handle_padding(x_shape[0], strides[0], new_kernel[0], padding) - pad_h = _handle_padding(x_shape[1], strides[1], new_kernel[1], padding) - pad_w = _handle_padding(x_shape[2], strides[2], new_kernel[2], padding) - padding = [ - (pad_d // 2, pad_d - pad_d // 2), - (pad_h // 2, pad_h - pad_h // 2), - (pad_w // 2, pad_w - pad_w // 2), - ] - if ceil_mode: + new_kernel = [ + kernel[i] + (kernel[i] - 1) * (dilation[i] - 1) for i in range(dims) + ] + if data_format == "NCDHW": + x_shape = x.shape[2:] + else: + x_shape = x.shape[1:-1] + if isinstance(padding, str): + pad_d = _handle_padding(x_shape[0], strides[0], new_kernel[0], padding) + pad_h = _handle_padding(x_shape[1], strides[1], new_kernel[1], padding) + pad_w = _handle_padding(x_shape[2], strides[2], new_kernel[2], padding) + padding = [ + (pad_d // 2, pad_d - pad_d // 2), + (pad_h // 2, pad_h - pad_h // 2), + (pad_w // 2, pad_w - pad_w // 2), + ] for i in range(dims): padding[i] = _padding_ceil_mode( x_shape[i], new_kernel[i], padding[i], strides[i] ) - padding = [(0, 0)] + list(padding) + [(0, 0)] - x = tf.pad(x, padding, constant_values=-math.inf) - elif isinstance(padding, list) and any( - item != 0 for sublist in padding for item in sublist - ): - raise NotImplementedError( - "Nonzero explicit padding is not supported for depthwise max pooling" - ) - - res = tf.nn.pool(x, kernel, "MAX", strides, "VALID", dilations=dilation) + if isinstance(padding, list): + if any(item != 0 for sublist in padding for item in sublist): + if len(padding) < dims + 2: + if data_format == "NCDHW": + padding = [(0, 0), (0, 0), *padding] + else: + padding = [(0, 0), *padding, (0, 0)] + x = tf.pad(x, padding, constant_values=tf.math.reduce_min(x)) + padding = "VALID" + elif isinstance(padding, list): + if any(item != 0 for sublist in padding for item in sublist): + raise NotImplementedError( + "Nonzero explicit padding is not supported for depthwise max pooling" + ) + else: + padding = "VALID" + res = tf.nn.pool( + x, kernel, "MAX", strides, padding, dilations=dilation, data_format=data_format + ) if depth_pooling: res = tf.transpose(res, (0, 2, 3, 4, 1)) - # converting minimum value to -inf because tensorflow clips -inf to minimum value - res = tf.where(res <= ivy.finfo(res.dtype).min, -math.inf, res) - if data_format == "NCDHW": + if permuted_x: return tf.transpose(res, (0, 4, 1, 2, 3)) return res @@ -277,17 +311,18 @@ def _handle_manual_pad_avg_pool(x, kernel, strides, padding, ceil_mode, dims): return padding, pad_specific, c -@with_unsupported_dtypes({"2.14.0 and below": ("bfloat16", "float64")}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("bfloat16", "float64")}, backend_version) def avg_pool1d( x: Union[tf.Tensor, tf.Variable], kernel: Union[int, Tuple[int]], strides: Union[int, Tuple[int]], - padding: str, + padding: Union[str, int, List[Tuple[int, int]]], /, *, data_format: str = "NWC", count_include_pad: bool = False, ceil_mode: bool = False, + divisor_override: Optional[int] = None, out: Optional[Union[tf.Tensor, tf.Variable]] = None, ) -> Union[tf.Tensor, tf.Variable]: if isinstance(kernel, int): @@ -337,7 +372,7 @@ def avg_pool1d( else: num_padded_values = tf.scatter_nd( tf.constant([[res.shape[1] - 1]]), - tf.constant([c], dtype=res.dtype), + tf.constant([c[0]], dtype=res.dtype), tf.constant([res.shape[1]], dtype=tf.int32), ) res = (kernel[0] * res) / (kernel[0] - num_padded_values[:, None]) @@ -348,13 +383,13 @@ def avg_pool1d( @with_unsupported_dtypes( - {"2.14.0 and below": ("bfloat16", "float64", "float16")}, backend_version + {"2.15.0 and below": ("bfloat16", "float64", "float16")}, backend_version ) def avg_pool2d( x: Union[tf.Tensor, tf.Variable], kernel: Union[int, Tuple[int], Tuple[int, int]], strides: Union[int, Tuple[int], Tuple[int, int]], - padding: str, + padding: Union[str, int, List[Tuple[int, int]]], /, *, data_format: str = "NHWC", @@ -364,14 +399,14 @@ def avg_pool2d( out: Optional[Union[tf.Tensor, tf.Variable]] = None, ) -> Union[tf.Tensor, tf.Variable]: if isinstance(kernel, int): - kernel = [kernel] * 2 + kernel = (kernel,) * 2 elif len(kernel) == 1: - kernel = [kernel[0]] * 2 + kernel = (kernel[0],) * 2 if isinstance(strides, int): - strides = [strides] * 2 + strides = (strides,) * 2 elif len(strides) == 1: - strides = [strides[0]] * 2 + strides = (strides[0],) * 2 if data_format == "NCHW": x = tf.transpose(x, (0, 2, 3, 1)) @@ -440,13 +475,13 @@ def avg_pool2d( @with_unsupported_dtypes( - {"2.14.0 and below": ("bfloat16", "float64", "float16")}, backend_version + {"2.15.0 and below": ("bfloat16", "float64", "float16")}, backend_version ) def avg_pool3d( x: Union[tf.Tensor, tf.Variable], kernel: Union[int, Tuple[int], Tuple[int, int, int]], strides: Union[int, Tuple[int], Tuple[int, int, int]], - padding: str, + padding: Union[str, int, List[Tuple[int, int]]], /, *, data_format: str = "NDHWC", @@ -456,14 +491,14 @@ def avg_pool3d( out: Optional[Union[tf.Tensor, tf.Variable]] = None, ) -> Union[tf.Tensor, tf.Variable]: if isinstance(kernel, int): - kernel = [kernel] * 3 + kernel = (kernel,) * 3 elif len(kernel) == 1: - kernel = [kernel[0]] * 3 + kernel = (kernel[0],) * 3 if isinstance(strides, int): - strides = [strides] * 3 + strides = (strides,) * 3 elif len(strides) == 1: - strides = [strides[0]] * 3 + strides = (strides[0],) * 3 if data_format == "NCDHW": x = tf.transpose(x, (0, 2, 3, 4, 1)) @@ -483,7 +518,7 @@ def avg_pool3d( res = ivy.conv_general_dilated( x, tf.ones(kernel + (1, x.shape[-1])), - strides, + list(strides), padding, dims=3, feature_group_count=x.shape[-1], @@ -545,7 +580,7 @@ def avg_pool3d( @with_unsupported_dtypes( - {"2.14.0 and below": ("bfloat16", "float64", "float16")}, backend_version + {"2.15.0 and below": ("bfloat16", "float64", "float16")}, backend_version ) def pool( x: Union[tf.Tensor, tf.Variable], @@ -571,7 +606,7 @@ def pool( ) -@with_supported_dtypes({"2.14.0 and below": ("float32", "float64")}, backend_version) +@with_supported_dtypes({"2.15.0 and below": ("float32", "float64")}, backend_version) def dct( x: Union[tf.Tensor, tf.Variable], /, @@ -646,7 +681,7 @@ def _ifft_norm( @with_supported_dtypes( - {"2.14.0 and below": ("complex", "float32", "float64")}, backend_version + {"2.15.0 and below": ("complex", "float32", "float64")}, backend_version ) def fft( x: Union[tf.Tensor, tf.Variable], @@ -654,7 +689,7 @@ def fft( /, *, norm: str = "backward", - n: Union[int, Tuple[int]] = None, + n: Optional[Union[int, Tuple[int]]] = None, out: Optional[Union[tf.Tensor, tf.Variable]] = None, ) -> Union[tf.Tensor, tf.Variable]: # ToDo: Remove conversion from float to complex when casting mode is working @@ -709,7 +744,7 @@ def fft( return ret -@with_unsupported_dtypes({"2.14.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("complex",)}, backend_version) def dropout( x: Union[tf.Tensor, tf.Variable], prob: float, @@ -722,9 +757,11 @@ def dropout( noise_shape: Optional[Sequence[int]] = None, out: Optional[Union[tf.Tensor, tf.Variable]] = None, ) -> Union[tf.Tensor, tf.Variable]: - x = ivy.astype(x, dtype) if dtype else x - res = tf.nn.dropout(x, prob, noise_shape=noise_shape, seed=seed) if training else x - res = res if scale else tf.multiply(res, (1.0 - prob)) + x = ivy.astype(x, dtype) if dtype and x.dtype != dtype else x + if prob == 0 or not training: + return x + res = tf.nn.dropout(x, prob, noise_shape=noise_shape, seed=seed) + res = tf.multiply(res, (1.0 - prob)) if not scale else res return res @@ -801,7 +838,7 @@ def ifft( dim: int, *, norm: str = "backward", - n: Union[int, Tuple[int]] = None, + n: Optional[Union[int, Tuple[int]]] = None, out: Optional[Union[tf.Tensor, tf.Variable]] = None, ) -> Union[tf.Tensor, tf.Variable]: if not isinstance(dim, int): @@ -851,7 +888,7 @@ def ifft( return ret -@with_unsupported_dtypes({"2.14.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("complex",)}, backend_version) def embedding( weights: Union[tf.Tensor, tf.Variable], indices: Union[tf.Tensor, tf.Variable], @@ -875,12 +912,13 @@ def interpolate( "linear", "bilinear", "trilinear", + "nd", "nearest", "area", - "nearest-exact", + "nearest_exact", "tf_area", + "tf_bicubic", "bicubic", - "bicubic_tensorflow", "mitchellcubic", "lanczos3", "lanczos5", @@ -888,53 +926,62 @@ def interpolate( ] = "linear", scale_factor: Optional[Union[Sequence[int], int]] = None, recompute_scale_factor: Optional[bool] = None, - align_corners: Optional[bool] = None, + align_corners: bool = False, antialias: bool = False, out: Optional[Union[tf.Tensor, tf.Variable]] = None, ): - dims = len(x.shape) - 2 - size = _get_size(scale_factor, size, dims, x.shape) - remove_dim = False - if mode in ["linear", "tf_area", "lanczos3", "lanczos5", "nearest-exact"]: - if dims == 1: - size = (1,) + tuple(size) - x = tf.expand_dims(x, axis=-2) - dims = 2 - remove_dim = True - mode = ( - "bilinear" - if mode == "linear" - else ( - "area" - if mode == "tf_area" - else "nearest" if mode == "nearest-exact" else mode + input_size = ivy.shape(x)[2:] + dims = len(input_size) + size, _ = _get_size(scale_factor, size, dims, input_size) + if all(a == b for a, b in zip(size, input_size)): + ret = x + else: + remove_dim = False + if mode in ["linear", "tf_area", "lanczos3", "lanczos5", "nearest-exact"]: + if dims == 1: + size = (1,) + tuple(size) + x = tf.expand_dims(x, axis=-2) + dims = 2 + remove_dim = True + mode = ( + "bilinear" + if mode == "linear" + else ( + "area" + if mode == "tf_area" + else "nearest" if mode == "nearest-exact" else mode + ) ) + if mode == "tf_bicubic": + mode = "bicubic" + x = tf.transpose(x, (0, *range(2, dims + 2), 1)) + ret = tf.transpose( + tf.cast( + tf.image.resize(x, size=size, method=mode, antialias=antialias), x.dtype + ), + (0, dims + 1, *range(1, dims + 1)), ) - if mode == "bicubic_tensorflow": - mode = "bicubic" - x = tf.transpose(x, (0, *range(2, dims + 2), 1)) - ret = tf.transpose( - tf.cast( - tf.image.resize(x, size=size, method=mode, antialias=antialias), x.dtype - ), - (0, dims + 1, *range(1, dims + 1)), - ) - if remove_dim: - ret = tf.squeeze(ret, axis=-2) + if remove_dim: + ret = tf.squeeze(ret, axis=-2) + if ivy.exists(out): + return ivy.inplace_update(out, ret) return ret interpolate.partial_mixed_handler = ( - lambda x, *args, mode="linear", scale_factor=None, recompute_scale_factor=None, align_corners=None, **kwargs: not align_corners # noqa: E501 - and len(x.shape) < 4 + lambda x, *args, mode="linear", recompute_scale_factor=None, align_corners=None, **kwargs: len( # noqa: E501 + x.shape + ) + < 4 and mode not in ["nearest", "area", "bicubic", "nd"] - and (scale_factor is None or ivy.all(ivy.array(scale_factor) > 1)) + and not align_corners + and recompute_scale_factor ) def _fft2_norm( x: Union[tf.Tensor, tf.Variable], - s: Sequence[int] = None, + s: Optional[Sequence[int]] = None, dim: Sequence[int] = (-2, -1), norm: str = "backward", ): @@ -951,7 +998,7 @@ def _fft2_norm( def trans_x_to_s( x: Union[tf.Tensor, tf.Variable], - s: Sequence[int] = None, + s: Optional[Sequence[int]] = None, dim: Sequence[int] = (-2, -1), ) -> Union[tf.Tensor, tf.Variable]: """Change the shape of the input array x to the desired output shape s.""" @@ -1039,11 +1086,11 @@ def _fft2_helper(x, shape, axes): return x -@with_supported_dtypes({"2.14.0 and below": ("complex",)}, backend_version) +@with_supported_dtypes({"2.15.0 and below": ("complex",)}, backend_version) def fft2( x: Union[tf.Tensor, tf.Variable], *, - s: Sequence[int] = None, + s: Optional[Sequence[int]] = None, dim: Sequence[int] = (-2, -1), norm: str = "backward", out: Optional[Union[tf.Tensor, tf.Variable]] = None, @@ -1358,8 +1405,8 @@ def rfft_operations(x, rank, norm_factor): }, ) norm_factor = tf.cast(norm_factor, tf.complex128) - x = x / norm_factor x = tf.cast(x, tf.complex128) + x = x / norm_factor return x @@ -1497,7 +1544,7 @@ def rfftn( s: Optional[Union[int, Tuple[int]]] = None, axes: Optional[Union[int, Tuple[int]]] = None, *, - norm: Optional[str] = [("forward", "ortho", "backward")], + norm: str = "backward", out: Optional[Union[tf.Tensor, tf.Variable]] = None, ) -> Union[tf.Tensor, tf.Variable]: result = _rfftn_helper(x, s, axes, norm) @@ -1512,7 +1559,7 @@ def rfftn( # stft -@with_supported_dtypes({"2.14.0 and below": ("complex",)}, backend_version) +@with_supported_dtypes({"2.15.0 and below": ("complex",)}, backend_version) def stft( signals: Union[tf.Tensor, tf.Variable], frame_length: int, @@ -1632,3 +1679,34 @@ def sliding_window( return tf.image.extract_patches( images=input, sizes=kernel_size, strides=stride, rates=dilation, padding=padding ) + + +def rnn( + step_function, + inputs, + initial_states, + /, + *, + go_backwards: bool = False, + mask: Optional[Union[tf.Tensor, tf.Variable]] = None, + constants: Optional[Union[tf.Tensor, tf.Variable]] = None, + unroll: bool = False, + input_length: Optional[int] = None, + time_major: bool = False, + zero_output_for_mask: bool = False, + return_all_outputs: bool = True, +): + step_function = inputs_to_ivy_arrays(output_to_native_arrays(step_function)) + return tf.keras.backend.rnn( + step_function, + inputs, + initial_states, + go_backwards=go_backwards, + mask=mask, + constants=constants, + unroll=unroll, + input_length=input_length, + time_major=time_major, + zero_output_for_mask=zero_output_for_mask, + return_all_outputs=return_all_outputs, + ) diff --git a/ivy/functional/backends/tensorflow/experimental/linear_algebra.py b/ivy/functional/backends/tensorflow/experimental/linear_algebra.py index 826360c73a34c..10d2f1b2c1705 100644 --- a/ivy/functional/backends/tensorflow/experimental/linear_algebra.py +++ b/ivy/functional/backends/tensorflow/experimental/linear_algebra.py @@ -1,18 +1,17 @@ from typing import Union, Optional, Tuple, List, Sequence import tensorflow as tf from functools import reduce as _reduce - +from collections import namedtuple import ivy from ivy.functional.ivy.experimental.linear_algebra import _check_valid_dimension_size from ivy.func_wrapper import with_unsupported_dtypes, with_supported_dtypes -from ivy.utils.exceptions import IvyNotImplementedException from .. import backend_version @with_unsupported_dtypes( - {"2.14.0 and below": ("int", "float16", "bfloat16")}, backend_version + {"2.15.0 and below": ("int", "float16", "bfloat16")}, backend_version ) def eigh_tridiagonal( alpha: Union[tf.Tensor, tf.Variable], @@ -96,7 +95,7 @@ def matrix_exp( @with_supported_dtypes( { - "2.14.0 and below": ( + "2.15.0 and below": ( "complex", "float32", "float64", @@ -115,7 +114,7 @@ def eig( @with_supported_dtypes( { - "2.14.0 and below": ( + "2.15.0 and below": ( "complex", "float32", "float64", @@ -162,7 +161,7 @@ def solve_triangular( @with_supported_dtypes( { - "2.14.0 and below": ( + "2.15.0 and below": ( "bfloat16", "float16", "float32", @@ -187,7 +186,7 @@ def multi_dot( return dot_out -@with_unsupported_dtypes({"1.25.0 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("float16", "bfloat16")}, backend_version) def cond( x: Union[tf.Tensor, tf.Variable], /, @@ -229,19 +228,35 @@ def cond( return k +@with_unsupported_dtypes( + {"2.15.0 and below": ("integer", "float16", "bfloat16")}, backend_version +) def lu_factor( x: Union[tf.Tensor, tf.Variable], /, *, pivot: Optional[bool] = True, out: Optional[Union[tf.Tensor, tf.Variable]] = None, -) -> Tuple[tf.Tensor]: - raise IvyNotImplementedException() +) -> Tuple[tf.Tensor, tf.Tensor]: + ret = tf.linalg.lu(x) + ret_tuple = namedtuple("lu_factor", ["LU", "p"]) + return ret_tuple(ret.lu, ret.p) + + +def lu_solve( + lu: Union[tf.Tensor, tf.Variable], + p: Union[tf.Tensor, tf.Variable], + b: Union[tf.Tensor, tf.Variable], + /, + *, + out: Optional[Union[tf.Tensor, tf.Variable]] = None, +) -> Union[tf.Tensor, tf.Variable]: + return tf.linalg.lu_solve(lu, p, b) @with_supported_dtypes( { - "2.14.0 and below": ( + "2.15.0 and below": ( "bfloat16", "float16", "float32", diff --git a/ivy/functional/backends/tensorflow/experimental/losses.py b/ivy/functional/backends/tensorflow/experimental/losses.py index e9140d6ee382e..404e2764b8d61 100644 --- a/ivy/functional/backends/tensorflow/experimental/losses.py +++ b/ivy/functional/backends/tensorflow/experimental/losses.py @@ -8,7 +8,7 @@ from . import backend_version -@with_unsupported_dtypes({"2.14.0 and below": "bool"}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": "bool"}, backend_version) def huber_loss( input: tf.Tensor, target: tf.Tensor, @@ -30,7 +30,7 @@ def huber_loss( return loss -@with_unsupported_dtypes({"2.14.0 and below": "bool"}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": "bool"}, backend_version) def smooth_l1_loss( input: tf.Tensor, target: tf.Tensor, @@ -50,7 +50,7 @@ def smooth_l1_loss( return loss -@with_unsupported_dtypes({"2.14.0 and below": "bool"}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": "bool"}, backend_version) def soft_margin_loss( input: tf.Tensor, target: tf.Tensor, @@ -68,11 +68,11 @@ def soft_margin_loss( return loss -def _apply_loss_reduction(loss: tf.Tensor, reduction: str, axis) -> tf.Tensor: +def _apply_loss_reduction(loss: tf.Tensor, reduction: str) -> tf.Tensor: if reduction == "sum": - return tf.math.reduce_sum(loss, axis=axis) + return tf.math.reduce_sum(loss) elif reduction == "mean": - return tf.reduce_mean(loss, axis=axis) + return tf.reduce_mean(loss) else: # reduction == "none" return loss @@ -87,30 +87,30 @@ def _validate_poisson_nll_params( # Validate dtypes for parameter, name in zip([input, label], ["input", "label"]): if parameter.dtype not in allowed_dtypes: - raise ValueError( - "The dtype of '%s' in poisson_nll_loss should be one of %s, but" - " received %s." % (name, allowed_dtypes, parameter.dtype) + raise TypeError( + f"The dtype of '{name}' in poisson_nll_loss should be one of" + f" {allowed_dtypes}, but received {parameter.dtype}." ) # Validate epsilon if epsilon <= 0: raise ValueError( "The value of `epsilon` in poisson_nll_loss should be positive, but" - " received %f, which is not allowed" % epsilon + f" received {epsilon}, which is not allowed." ) # Validate reduction if reduction not in ["sum", "mean", "none"]: raise ValueError( "The value of 'reduction' in poisson_nll_loss should be 'sum', 'mean' or" - " 'none', but received %s, which is not allowed." % reduction + f" 'none', but received {reduction}, which is not allowed." ) # Validate shape if input.shape != label.shape: raise ValueError( - "The shape of 'input' (%s) must be the same as the shape of 'label' (%s)." - % (input.shape, label.shape) + f"The shape of 'input' ({input.shape}) must be the same as the shape of" + f" 'label' ({label.shape})." ) return True @@ -118,7 +118,7 @@ def _validate_poisson_nll_params( @with_supported_device_and_dtypes( { - "2.14.0 and below": { + "2.15.0 and below": { "cpu": ("float32", "float64"), "gpu": ("float32", "float64"), } @@ -156,3 +156,30 @@ def poisson_nll_loss( cond = tf.math.logical_and(target_tensor >= zeros, target_tensor <= ones) loss = loss + tf.where(cond, zeros, stirling_approx) return _apply_loss_reduction(loss, reduction) + + +@with_supported_device_and_dtypes( + { + "2.14.0 and below": { + "cpu": ("float32", "float64"), + "gpu": ("float32", "float64"), + } + }, + backend_version, +) +def hinge_embedding_loss( + input: tf.Tensor, + target: tf.Tensor, + *, + margin: float = 1.0, + reduction: str = "mean", +) -> tf.Tensor: + zero_ = tf.zeros([1], dtype=input.dtype) + + relu_part = tf.math.maximum(margin - input, 0) + + loss = tf.where(tf.equal(target, 1.0), input, zero_) + tf.where( + tf.equal(target, -1.0), relu_part, zero_ + ) + + return _apply_loss_reduction(loss, reduction) diff --git a/ivy/functional/backends/tensorflow/experimental/manipulation.py b/ivy/functional/backends/tensorflow/experimental/manipulation.py index 17fff8ff50f42..e188f00a8aaae 100644 --- a/ivy/functional/backends/tensorflow/experimental/manipulation.py +++ b/ivy/functional/backends/tensorflow/experimental/manipulation.py @@ -1,6 +1,7 @@ # global from collections import namedtuple from typing import ( + Iterable, Union, Optional, Sequence, @@ -15,7 +16,7 @@ import tensorflow as tf # local -from ivy.func_wrapper import with_unsupported_dtypes +from ivy.func_wrapper import with_unsupported_dtypes, handle_out_argument from .. import backend_version import ivy from ivy.functional.ivy.experimental.manipulation import _to_tf_padding @@ -33,7 +34,7 @@ def moveaxis( return tf.experimental.numpy.moveaxis(a, source, destination) -@with_unsupported_dtypes({"2.14.0 and below": ("bfloat16",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("bfloat16",)}, backend_version) def heaviside( x1: Union[tf.Tensor, tf.Variable], x2: Union[tf.Tensor, tf.Variable], @@ -84,7 +85,7 @@ def rot90( return tf.experimental.numpy.rot90(m, k, axes) -@with_unsupported_dtypes({"2.14.0 and below": ("unsigned", "complex")}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("unsigned", "complex")}, backend_version) def top_k( x: tf.Tensor, k: int, @@ -126,7 +127,7 @@ def fliplr( return tf.experimental.numpy.fliplr(m) -@with_unsupported_dtypes({"2.14.0 and below": ("bfloat16",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("bfloat16",)}, backend_version) def i0( x: Union[tf.Tensor, tf.Variable], /, @@ -266,27 +267,36 @@ def broadcast_shapes( def pad( input: Union[tf.Tensor, tf.Variable], - pad_width: Union[Sequence[Sequence[int]], Union[tf.Tensor, tf.Variable], int], + pad_width: Union[Iterable[Tuple[int]], int], /, *, mode: Union[ Literal[ "constant", + "dilated", "edge", + "linear_ramp", + "maximum", + "mean", + "median", + "minimum", "reflect", + "symmetric", "wrap", + "empty", ], Callable, ] = "constant", - stat_length: Union[Sequence[Union[tf.Tensor, tf.Variable]], int] = 1, - constant_values: Number = 0, - end_values: Number = 0, + stat_length: Union[Iterable[Tuple[int]], int] = 1, + constant_values: Union[Iterable[Tuple[Number]], Number] = 0, + end_values: Union[Iterable[Tuple[Number]], Number] = 0, reflect_type: Literal["even", "odd"] = "even", **kwargs: Optional[Any], ) -> Union[tf.Tensor, tf.Variable]: pad_width = _to_tf_padding(pad_width, len(input.shape)) - if not isinstance(pad_width, (tf.Variable, tf.Tensor)): - pad_width = tf.constant(pad_width) + if isinstance(constant_values, (tf.Variable, tf.Tensor)): + if constant_values.dtype != input.dtype: + constant_values = tf.cast(constant_values, input.dtype) return tf.pad( input, pad_width, @@ -337,6 +347,10 @@ def expand( out: Optional[Union[tf.Tensor, tf.Variable]] = None, ) -> Union[tf.Tensor, tf.Variable]: shape = list(shape) + n_extra_dims = len(shape) - len(x.shape) + if n_extra_dims > 0: + new_shape = (1,) * n_extra_dims + tuple(x.shape) + x = tf.reshape(x, new_shape) for i, dim in enumerate(shape): if dim < 0: shape[i] = x.shape[i] @@ -551,3 +565,19 @@ def trim_zeros(a: tf.Tensor, /, *, trim: Optional[str] = "bf") -> tf.Tensor: last = tf.minimum(last, tf.cast(tf.shape(a)[0], tf.int64)) return a[first:last] + + +@handle_out_argument +def unflatten( + x: tf.Tensor, + /, + shape: Tuple[int] = None, + dim: Optional[int] = 0, + *, + out: Optional[tf.Tensor] = None, + name: Optional[str] = None, +) -> tf.Tensor: + dim = abs(len(x.shape) + dim) if dim < 0 else dim + res_shape = x.shape[:dim] + tf.TensorShape(shape) + x.shape[dim + 1 :] + res = tf.reshape(x, res_shape, name) + return res diff --git a/ivy/functional/backends/tensorflow/experimental/norms.py b/ivy/functional/backends/tensorflow/experimental/norms.py index d589909759f28..ef4c5d7d5e8b6 100644 --- a/ivy/functional/backends/tensorflow/experimental/norms.py +++ b/ivy/functional/backends/tensorflow/experimental/norms.py @@ -1,10 +1,11 @@ import tensorflow as tf -from typing import Union, Optional, Tuple -from ivy.func_wrapper import with_unsupported_dtypes +from typing import Literal, Union, Optional, Tuple +from ivy.func_wrapper import with_supported_dtypes, with_unsupported_dtypes from . import backend_version +import math -@with_unsupported_dtypes({"2.14.0 and below": "uint8"}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": "uint8"}, backend_version) def l1_normalize( x: Union[tf.Tensor, tf.Variable], /, @@ -29,7 +30,43 @@ def l2_normalize( return tf.math.divide(x, denorm) -@with_unsupported_dtypes({"2.14.0 and below": ("float16", "bfloat16")}, backend_version) +@with_supported_dtypes({"2.15.0 and below": ("float32", "float16")}, backend_version) +def local_response_norm( + x: Union[tf.Tensor, tf.Variable], + size, + /, + *, + bias: Optional[float] = 1.0, + alpha: Optional[float] = 1.0, + beta: Optional[float] = 0.5, + average: bool = False, + data_format: Optional[Literal["NHWC", "NCHW"]] = "NHWC", + out: Optional[tf.Tensor] = None, +) -> tf.Tensor: + if data_format == "NCHW": + x = tf.transpose(x, (0, 2, 3, 1)) + # `alpha = alpha/size if average else alpha` was causing numerical instability + if average: + ret = tf.nn.local_response_normalization( + x / math.sqrt(size), + depth_radius=size // 2, + bias=bias, + alpha=alpha, + beta=beta, + ) * math.sqrt(size) + else: + ret = tf.nn.local_response_normalization( + x, depth_radius=size // 2, bias=bias, alpha=alpha, beta=beta + ) + if data_format == "NCHW": + ret = tf.transpose(ret, (0, 3, 1, 2)) + return ret + + +local_response_norm.partial_mixed_handler = lambda x, size, **kwargs: size % 2 != 0 + + +@with_unsupported_dtypes({"2.15.0 and below": ("float16", "bfloat16")}, backend_version) def batch_norm( x: Union[tf.Tensor, tf.Variable], mean: Union[tf.Tensor, tf.Variable], @@ -61,12 +98,8 @@ def batch_norm( runningmean = mean runningvariance = variance if training: - n = ( - tf.size(x) - if xdims == 1 - else tf.cast(tf.divide(tf.size(x), tf.shape(x)[-1]), x.dtype) - ) - n = tf.cast(n, x.dtype) + n = tf.size(x) if xdims == 1 else tf.divide(tf.size(x), tf.shape(x)[-1]) + n = tf.cast(n, x.dtype) if n.dtype != x.dtype else n dims = (0, *range(1, xdims - 1)) mean = tf.math.reduce_mean(x, axis=dims) variance = tf.math.reduce_variance(x, axis=dims) @@ -74,7 +107,14 @@ def batch_norm( runningvariance = (1 - momentum) * runningvariance + momentum * variance * n / ( n - 1 ) - xnormalized = tf.nn.batch_normalization(x, mean, variance, offset, scale, eps) + + inv = 1.0 / tf.math.sqrt(variance + eps) + offset = 0 if offset is None else offset + if scale is not None: + inv = tf.math.multiply(inv, scale) + xnormalized = tf.math.add(tf.math.multiply(x, inv), offset) + xnormalized = tf.math.subtract(xnormalized, tf.math.multiply(mean, inv)) + # the above approach is faster than tf.nn.batch_normalization if data_format == "NCS": xnormalized = tf.transpose( diff --git a/ivy/functional/backends/tensorflow/experimental/random.py b/ivy/functional/backends/tensorflow/experimental/random.py index d07cd3504420b..2a1bff81f7029 100644 --- a/ivy/functional/backends/tensorflow/experimental/random.py +++ b/ivy/functional/backends/tensorflow/experimental/random.py @@ -15,7 +15,7 @@ # dirichlet @with_unsupported_dtypes( { - "2.14.0 and below": ( + "2.15.0 and below": ( "blfoat16", "float16", ) @@ -65,12 +65,12 @@ def gamma( # TODO: Implement purely in tensorflow -@with_unsupported_dtypes({"2.14.0 and below": ("bfloat16",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("bfloat16",)}, backend_version) def poisson( lam: Union[float, tf.Tensor, tf.Variable], *, shape: Optional[Union[ivy.NativeShape, Sequence[int]]] = None, - device: str = None, + device: Optional[str] = None, dtype: DType, seed: Optional[int] = None, fill_value: Optional[Union[float, int]] = 0, @@ -90,15 +90,20 @@ def poisson( return ret +@with_unsupported_dtypes({"2.15.0 and below": ("bfloat16",)}, backend_version) def bernoulli( probs: Union[float, tf.Tensor, tf.Variable], *, logits: Union[float, tf.Tensor, tf.Variable] = None, shape: Optional[Union[ivy.NativeShape, Sequence[int]]] = None, - device: str = None, - dtype: DType, + device: Optional[str] = None, + dtype: Optional[str] = None, seed: Optional[int] = None, out: Optional[Union[tf.Tensor, tf.Variable]] = None, ) -> Union[tf.Tensor, tf.Variable]: - pass - # TODO: Implement purely in tensorflow + dtype = dtype if dtype is not None else probs.dtype + if logits is not None: + probs = tf.nn.softmax(logits, -1) + if not _check_shapes_broadcastable(shape, probs.shape): + shape = probs.shape + return tf.keras.backend.random_bernoulli(shape, probs, dtype, seed) diff --git a/ivy/functional/backends/tensorflow/experimental/searching.py b/ivy/functional/backends/tensorflow/experimental/searching.py index 7fe85411390f1..9c979c1b386da 100644 --- a/ivy/functional/backends/tensorflow/experimental/searching.py +++ b/ivy/functional/backends/tensorflow/experimental/searching.py @@ -9,7 +9,7 @@ @with_supported_dtypes( { - "2.14.0 and below": ( + "2.15.0 and below": ( "int32", "int64", ) diff --git a/ivy/functional/backends/tensorflow/experimental/statistical.py b/ivy/functional/backends/tensorflow/experimental/statistical.py index e4f699d454aff..ee728a6bcbf87 100644 --- a/ivy/functional/backends/tensorflow/experimental/statistical.py +++ b/ivy/functional/backends/tensorflow/experimental/statistical.py @@ -34,7 +34,7 @@ def histogram( @with_supported_dtypes( { - "2.14.0 and below": ( + "2.15.0 and below": ( "float", "complex", ) @@ -53,6 +53,15 @@ def median( # TODO: Implement in pure tensorflow +@with_supported_dtypes( + { + "2.15.0 and below": ( + "float", + "complex", + ) + }, + backend_version, +) def nanmean( a: Union[tf.Tensor, tf.Variable], /, @@ -129,7 +138,7 @@ def _validate_quantile(q): if not (0.0 <= q[i] <= 1.0): return False else: - if not (tf.math.reduce_all(0 <= q) and tf.math.reduce_all(q <= 1)): + if not (tf.math.reduce_all(q >= 0) and tf.math.reduce_all(q <= 1)): return False return True @@ -275,7 +284,7 @@ def nanmedian( @with_supported_device_and_dtypes( { - "2.14.0 and below": { + "2.15.0 and below": { "cpu": ( "int64", "int32", @@ -301,7 +310,7 @@ def bincount( out: Optional[Union[tf.Tensor, tf.Variable]] = None, ) -> Union[tf.Tensor, tf.Variable]: return tf.math.bincount( - x.numpy().tolist(), + x, weights=weights, minlength=minlength, dtype=x.dtype if weights is None else weights.dtype, @@ -310,7 +319,7 @@ def bincount( @with_supported_device_and_dtypes( { - "2.14.0 and below": { + "2.15.0 and below": { "cpu": ("float32", "float64"), "gpu": ("bfloat16", "float16", "float32", "float64"), } @@ -323,7 +332,7 @@ def igamma( return tf.math.igamma(a, x) -@with_unsupported_dtypes({"2.14.0 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("float16", "bfloat16")}, backend_version) def cov( x1: tf.Tensor, x2: tf.Tensor = None, @@ -426,7 +435,7 @@ def cov( @with_unsupported_dtypes( - {"2.14.0 and below": ("bool",)}, + {"2.15.0 and below": ("bool",)}, backend_version, ) def cummax( @@ -555,7 +564,7 @@ def __get_index(lst, indices=None, prefix=None): @with_unsupported_dtypes( - {"2.14.0 and below": ("bfloat16", "complex")}, + {"2.15.0 and below": ("bfloat16", "bool", "complex")}, backend_version, ) def cummin( diff --git a/ivy/functional/backends/tensorflow/general.py b/ivy/functional/backends/tensorflow/general.py index 3d017fc9b01b5..47ac3efa9450a 100644 --- a/ivy/functional/backends/tensorflow/general.py +++ b/ivy/functional/backends/tensorflow/general.py @@ -1,11 +1,12 @@ -""" -Tensorflow general functions. +"""Tensorflow general functions. Collection of TensorFlow general functions, wrapped to fit Ivy syntax and signature. """ # global +import functools +from operator import mul from typing import Optional, Union, Sequence, Callable, Tuple import numpy as np import multiprocessing as _multiprocessing @@ -24,7 +25,7 @@ def is_native_array(x, /, *, exclusive=False): - if isinstance(x, (tf.Tensor, tf.Variable)): + if isinstance(x, (tf.Tensor, tf.Variable, tf.TensorArray)): if exclusive and isinstance(x, tf.Variable): return False return True @@ -50,7 +51,7 @@ def current_backend_str() -> str: def _check_query(query): return not isinstance(query, list) and ( - not (ivy.is_array(query) and ivy.is_bool_dtype(query) and bool(query.ndim > 0)) + not (ivy.is_array(query) and bool(query.ndim > 0)) ) @@ -59,13 +60,17 @@ def get_item( /, query: Union[tf.Tensor, tf.Variable, Tuple], *, - copy: bool = None, + copy: Optional[bool] = None, ) -> Union[tf.Tensor, tf.Variable]: + if ivy.is_array(query) and ivy.is_bool_dtype(query): + if not len(query.shape): + return tf.expand_dims(x, 0) return x.__getitem__(query) get_item.partial_mixed_handler = lambda x, query, **kwargs: ( all(_check_query(i) for i in query) + and len({i.shape for i in query if ivy.is_array(i)}) <= 1 if isinstance(query, tuple) else _check_query(query) ) @@ -192,6 +197,10 @@ def get_num_dims(x, /, *, as_array=False): ) +def size(x: tf.Tensor, /) -> int: + return functools.reduce(mul, x.shape) if len(x.shape) > 0 else 1 + + def inplace_arrays_supported(): return False @@ -344,7 +353,7 @@ def scatter_flat( scatter_flat.support_native_out = True -@with_unsupported_dtypes({"2.14.0 and below": ("bfloat16", "complex")}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("bfloat16", "complex")}, backend_version) def scatter_nd( indices: Union[tf.Tensor, tf.Variable], updates: Union[tf.Tensor, tf.Variable], @@ -504,7 +513,7 @@ def _vmap(*args, **kwargs): return _vmap -@with_unsupported_dtypes({"2.14.0 and below": ("bfloat16", "complex")}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("bfloat16", "complex")}, backend_version) def isin( elements: tf.Tensor, test_elements: tf.Tensor, diff --git a/ivy/functional/backends/tensorflow/gradients.py b/ivy/functional/backends/tensorflow/gradients.py index d548e21bc7738..da688a2dd71f5 100644 --- a/ivy/functional/backends/tensorflow/gradients.py +++ b/ivy/functional/backends/tensorflow/gradients.py @@ -1,5 +1,4 @@ -""" -Tensorflow gradient functions. +"""Tensorflow gradient functions. Collection of TensorFlow gradient functions, wrapped to fit Ivy syntax and signature. diff --git a/ivy/functional/backends/tensorflow/layers.py b/ivy/functional/backends/tensorflow/layers.py index cc37b00bade0a..a9d3d7dd40f63 100644 --- a/ivy/functional/backends/tensorflow/layers.py +++ b/ivy/functional/backends/tensorflow/layers.py @@ -1,4 +1,5 @@ -"""Collection of TensorFlow network layers, wrapped to fit Ivy syntax and signature.""" +"""Collection of TensorFlow network layers, wrapped to fit Ivy syntax and +signature.""" # global from typing import Optional, Tuple, Union, Sequence @@ -8,81 +9,122 @@ # local import ivy -from ivy.func_wrapper import with_unsupported_dtypes +from ivy.func_wrapper import with_supported_dtypes, with_unsupported_dtypes from . import backend_version from ivy.functional.ivy.layers import ( _deconv_length, _get_x_data_format, - _handle_padding, ) -def _ff_xd_before_conv(x, filters, dims, filter_format, x_dilations): - if filter_format == "channel_first": - filters = tf.transpose(filters, (*range(2, dims + 2), 1, 0)) +@with_supported_dtypes( + {"2.15.0 and below": ("float", "int32", "int64", "complex")}, + backend_version, +) +def linear( + x: Union[tf.Tensor, tf.Variable], + weight: Union[tf.Tensor, tf.Variable], + /, + *, + bias: Optional[Union[tf.Tensor, tf.Variable]] = None, + out: Optional[Union[tf.Tensor, tf.Variable]] = None, +) -> Union[tf.Tensor, tf.Variable]: + # TODO: try to generalize this for >=2 dimensions + result = ( + tf.matmul(x, weight, transpose_b=True) + if len(x.shape) == len(weight.shape) == 2 and x.shape[-1] == weight.shape[-1] + else tf.einsum("...i,...ji->...j", x, weight) + ) + + if bias is not None: + return tf.add(result, bias) + return result + + +def _x_dil_before_conv(x, dims, x_dilations, data_format): # adding dilation in input x_dilations = [x_dilations] * dims if isinstance(x_dilations, int) else x_dilations - for i in range(dims): - if x_dilations[i] > 1: - h = x.shape[1 + i] + x_dilations_idxs = [i for i, x_dil in enumerate(x_dilations) if x_dil > 1] + if x_dilations_idxs: + if data_format[-1] == "C": + offset = 1 + else: + offset = 2 + for i in x_dilations_idxs: + h = x.shape[offset + i] new_height = h + (h - 1) * (x_dilations[i] - 1) h = tf.eye(new_height, dtype=x.dtype)[:: x_dilations[i]] - x = tf.experimental.numpy.swapaxes(x, 1 + i, -1) + x = tf.experimental.numpy.swapaxes(x, offset + i, -1) x = tf.matmul(x, h) - x = tf.experimental.numpy.swapaxes(x, -1, 1 + i) - return x, filters + x = tf.experimental.numpy.swapaxes(x, -1, offset + i) + return x -def _pad_before_conv(x, filters, strides, padding, dims, dilations): - dilations = [dilations] * dims if isinstance(dilations, int) else dilations - strides = [strides] * dims if isinstance(strides, int) else strides +def _pad_before_conv(x, padding, dims, data_format): if isinstance(padding, str): - filter_shape = list(filters.shape[:dims]) - filter_shape = [ - filter_shape[i] + (filter_shape[i] - 1) * (dilations[i] - 1) - for i in range(dims) - ] - new_pad = [ - _handle_padding(x.shape[1 + i], strides[i], filter_shape[i], padding) - for i in range(dims) - ] - pad_list = [ - (new_pad[i] // 2, new_pad[i] - new_pad[i] // 2) for i in range(dims) - ] + return x, padding elif isinstance(padding, int): pad_list = [(padding, padding)] * dims else: pad_list = padding - return tf.pad( - x, - [ - (0, 0), - *pad_list, - (0, 0), - ], - "CONSTANT", - ) + if data_format[-1] == "C": + pad_list = [(0, 0), *pad_list, (0, 0)] + else: + pad_list = [(0, 0), (0, 0), *pad_list] + return tf.pad(x, pad_list, "CONSTANT"), "VALID" -def _output_shape( - x_shape, filter_shape, output_shape, strides, padding, dims, dilations +def _extend_2d_padding(padding, data_format): + if isinstance(padding, str): + return padding + if isinstance(padding, int): + padding = [(padding, padding)] * 2 + if data_format[-1] == "C": + padding = [(0, 0)] + padding + [(0, 0)] + else: + padding = [(0, 0), (0, 0)] + padding + return padding + + +def _transpose_out_pad( + x_shape, filter_shape, strides, padding, dims, dilations, data_format ): + if data_format[-1] == "C": + offset = 1 + else: + offset = 2 dilations = [dilations] * dims if isinstance(dilations, int) else dilations strides = [strides] * dims if isinstance(strides, int) else strides - if output_shape is None: + if isinstance(padding, str): out_shape = [ _deconv_length( - x_shape[i + 1], strides[i], filter_shape[i], padding, dilations[i] + x_shape[offset + i], strides[i], filter_shape[i], padding, dilations[i] ) for i in range(dims) ] - output_shape = [x_shape[0], *out_shape, filter_shape[-2]] - elif len(output_shape) == dims: - output_shape = [x_shape[0]] + output_shape + [filter_shape[-2]] - return output_shape + else: + if isinstance(padding, int): + padding = [[padding, padding]] * dims + out_shape = [ + (x_shape[offset + i] - 1) * strides[i] + - padding[i][0] + - padding[i][1] + + dilations[i] * (filter_shape[i] - 1) + + 1 + for i in range(dims) + ] + if data_format[-1] == "C": + padding = [[0, 0], *padding, [0, 0]] + else: + padding = [[0, 0], [0, 0], *padding] + if data_format[-1] == "C": + out_shape = [x_shape[0], *out_shape, filter_shape[-2]] + else: + out_shape = [x_shape[0], filter_shape[-2], *out_shape] + return out_shape, padding -@with_unsupported_dtypes({"2.14.0 and below": ("bfloat16", "complex")}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("bfloat16", "complex")}, backend_version) def conv1d( x: Union[tf.Tensor, tf.Variable], filters: Union[tf.Tensor, tf.Variable], @@ -97,18 +139,26 @@ def conv1d( bias: Optional[Union[tf.Tensor, tf.Variable]] = None, out: Optional[Union[tf.Tensor, tf.Variable]] = None, ) -> Union[tf.Tensor, tf.Variable]: - if data_format == "NCW": + permuted_x = False + if data_format == "NCW" and ivy.dev(x) == "cpu": x = tf.transpose(x, (0, 2, 1)) - x, filters = _ff_xd_before_conv(x, filters, 1, filter_format, x_dilations) - x = _pad_before_conv(x, filters, strides, padding, 1, dilations) - res = tf.nn.conv1d(x, filters, strides, "VALID", "NWC", dilations) - res = tf.math.add(res, bias) if bias is not None else res - if data_format == "NCW": + data_format = "NWC" + permuted_x = True + if filter_format == "channel_first": + filters = tf.transpose(filters, (2, 1, 0)) + x = _x_dil_before_conv(x, 1, x_dilations, data_format) + x, padding = _pad_before_conv(x, padding, 1, data_format) + res = tf.nn.conv1d(x, filters, strides, padding, data_format, dilations) + if bias is not None: + if data_format[1] == "C": + bias = tf.reshape(bias, [1, -1, 1]) + res = tf.math.add(res, bias) + if permuted_x: res = tf.transpose(res, (0, 2, 1)) return res -@with_unsupported_dtypes({"2.14.0 and below": ("bfloat16", "complex")}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("bfloat16", "complex")}, backend_version) def conv1d_transpose( x: Union[tf.Tensor, tf.Variable], filters: Union[tf.Tensor, tf.Variable], @@ -117,6 +167,7 @@ def conv1d_transpose( /, *, output_shape: Optional[Union[ivy.NativeShape, Sequence[int]]] = None, + filter_format: str = "channel_last", data_format: str = "NWC", dilations: Union[int, Tuple[int]] = 1, bias: Optional[Union[tf.Tensor, tf.Variable]] = None, @@ -128,23 +179,47 @@ def conv1d_transpose( raise ivy.utils.exceptions.IvyException( "Tensorflow does not support dilations greater than 1 when device is cpu" ) - if data_format == "NCW": + permuted_x = False + if data_format == "NCW" and ivy.dev(x) == "cpu": x = tf.transpose(x, (0, 2, 1)) - filters = tf.transpose(filters, (0, 2, 1)) - - output_shape = _output_shape( - x.shape, filters.shape, output_shape, strides, padding, 1, dilations + data_format = "NWC" + permuted_x = True + if filter_format == "channel_first": + filters = tf.transpose(filters, (2, 1, 0)) + output_shape, padding = _transpose_out_pad( + x.shape, filters.shape, strides, padding, 1, dilations, data_format ) res = tf.nn.conv1d_transpose( - x, filters, output_shape, strides, padding, "NWC", dilations + x, filters, output_shape, strides, padding, data_format, dilations ) - res = tf.math.add(res, bias) if bias is not None else res - if data_format == "NCW": + if bias is not None: + if data_format[1] == "C": + bias = tf.reshape(bias, [1, -1, 1]) + res = tf.math.add(res, bias) + if permuted_x: res = tf.transpose(res, (0, 2, 1)) return res -@with_unsupported_dtypes({"2.14.0 and below": ("bfloat16", "complex")}, backend_version) +def _extend_3d_strides_dilations(strides, dilations, data_format): + if data_format[-1] == "C": + strides = [1, *([strides] * 3 if isinstance(strides, int) else strides), 1] + dilations = [ + 1, + *([dilations] * 3 if isinstance(dilations, int) else dilations), + 1, + ] + else: + strides = [1, 1, *([strides] * 3 if isinstance(strides, int) else strides)] + dilations = [ + 1, + 1, + *([dilations] * 3 if isinstance(dilations, int) else dilations), + ] + return strides, dilations + + +@with_supported_dtypes({"2.14.0 and below": ("float", "int32")}, backend_version) def conv2d( x: Union[tf.Tensor, tf.Variable], filters: Union[tf.Tensor, tf.Variable], @@ -159,26 +234,35 @@ def conv2d( bias: Optional[Union[tf.Tensor, tf.Variable]] = None, out: Optional[Union[tf.Tensor, tf.Variable]] = None, ) -> Union[tf.Tensor, tf.Variable]: - if data_format == "NCHW": + permuted_x = False + if data_format == "NCHW" and ivy.dev(x) == "cpu": x = tf.transpose(x, (0, 2, 3, 1)) - x, filters = _ff_xd_before_conv(x, filters, 2, filter_format, x_dilations) - x = _pad_before_conv(x, filters, strides, padding, 2, dilations) - res = tf.nn.conv2d(x, filters, strides, "VALID", "NHWC", dilations) - res = tf.math.add(res, bias) if bias is not None else res - if data_format == "NCHW": + data_format = "NHWC" + permuted_x = True + if filter_format == "channel_first": + filters = tf.transpose(filters, (2, 3, 1, 0)) + x = _x_dil_before_conv(x, 2, x_dilations, data_format) + padding = _extend_2d_padding(padding, data_format) + res = tf.nn.conv2d(x, filters, strides, padding, data_format, dilations) + if bias is not None: + if data_format[1] == "C": + bias = tf.reshape(bias, [1, -1, 1, 1]) + res = tf.math.add(res, bias) + if permuted_x: return tf.transpose(res, (0, 3, 1, 2)) return res -@with_unsupported_dtypes({"2.14.0 and below": ("bfloat16", "complex")}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("bfloat16", "complex")}, backend_version) def conv2d_transpose( x: Union[tf.Tensor, tf.Variable], filters: Union[tf.Tensor, tf.Variable], strides: Union[int, Tuple[int, int]], - padding: str, + padding: Union[str, int, Sequence[Tuple[int, int]]], /, *, output_shape: Optional[Union[ivy.NativeShape, Sequence[int]]] = None, + filter_format: str = "channel_last", data_format: str = "NHWC", dilations: Union[int, Tuple[int, int]] = 1, bias: Optional[Union[tf.Tensor, tf.Variable]] = None, @@ -190,22 +274,35 @@ def conv2d_transpose( raise ivy.utils.exceptions.IvyException( "Tensorflow does not support dilations greater than 1 when device is cpu" ) - if data_format == "NCHW": + permuted_x = False + if data_format == "NCHW" and ivy.dev(x) == "cpu": x = tf.transpose(x, (0, 2, 3, 1)) - filters = tf.transpose(filters, (0, 1, 3, 2)) - output_shape = _output_shape( - x.shape, filters.shape, output_shape, strides, padding, 2, dilations + data_format = "NHWC" + permuted_x = True + if filter_format == "channel_first": + filters = tf.transpose(filters, (2, 3, 1, 0)) + output_shape, padding = _transpose_out_pad( + x.shape, + filters.shape, + strides, + padding, + 2, + dilations, + data_format, ) res = tf.nn.conv2d_transpose( - x, filters, output_shape, strides, padding, "NHWC", dilations + x, filters, output_shape, strides, padding, data_format, dilations ) - res = tf.math.add(res, bias) if bias is not None else res - if data_format == "NCHW": + if bias is not None: + if data_format[1] == "C": + bias = tf.reshape(bias, [1, -1, 1, 1]) + res = tf.math.add(res, bias) + if permuted_x: return tf.transpose(res, (0, 3, 1, 2)) return res -@with_unsupported_dtypes({"2.14.0 and below": ("bfloat16", "complex")}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("bfloat16", "complex")}, backend_version) def depthwise_conv2d( x: Union[tf.Tensor, tf.Variable], filters: Union[tf.Tensor, tf.Variable], @@ -219,19 +316,22 @@ def depthwise_conv2d( ) -> Union[tf.Tensor, tf.Variable]: strides = [strides] * 2 if isinstance(strides, int) else strides dilations = [dilations] * 2 if isinstance(dilations, int) else dilations - if data_format == "NCHW": + permuted_x = False + if data_format == "NCHW" and ivy.dev(x) == "cpu": x = tf.transpose(x, (0, 2, 3, 1)) + data_format = "NHWC" + permuted_x = True if tf.rank(filters) == 3: filters = tf.expand_dims(filters, -1) - x = _pad_before_conv(x, filters, strides, padding, 2, dilations) + padding = _extend_2d_padding(padding, data_format) strides = [1, strides[0], strides[1], 1] - res = tf.nn.depthwise_conv2d(x, filters, strides, "VALID", "NHWC", dilations) - if data_format == "NCHW": - return tf.transpose(res, (0, 3, 1, 2)) + res = tf.nn.depthwise_conv2d(x, filters, strides, padding, data_format, dilations) + if permuted_x: + res = tf.transpose(res, (0, 3, 1, 2)) return res -@with_unsupported_dtypes({"2.14.0 and below": ("bfloat16", "complex")}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("bfloat16", "complex")}, backend_version) def conv3d( x: Union[tf.Tensor, tf.Variable], filters: Union[tf.Tensor, tf.Variable], @@ -246,22 +346,27 @@ def conv3d( bias: Optional[Union[tf.Tensor, tf.Variable]] = None, out: Optional[Union[tf.Tensor, tf.Variable]] = None, ): - if data_format == "NCDHW": + permuted_x = False + if data_format == "NCDHW" and ivy.dev(x) == "cpu": x = tf.transpose(x, (0, 2, 3, 4, 1)) - x, filters = _ff_xd_before_conv(x, filters, 3, filter_format, x_dilations) - x = _pad_before_conv(x, filters, strides, padding, 3, dilations) - strides = [1] + ([strides] * 3 if isinstance(strides, int) else strides) + [1] - dilations = ( - [1] + ([dilations] * 3 if isinstance(dilations, int) else dilations) + [1] - ) - res = tf.nn.conv3d(x, filters, strides, "VALID", "NDHWC", dilations) - res = tf.math.add(res, bias) if bias is not None else res - if data_format == "NCDHW": + data_format = "NDHWC" + permuted_x = True + if filter_format == "channel_first": + filters = tf.transpose(filters, (2, 3, 4, 1, 0)) + x = _x_dil_before_conv(x, 3, x_dilations, data_format) + x, padding = _pad_before_conv(x, padding, 3, data_format) + strides, dilations = _extend_3d_strides_dilations(strides, dilations, data_format) + res = tf.nn.conv3d(x, filters, strides, padding, data_format, dilations) + if bias is not None: + if data_format[1] == "C": + bias = tf.reshape(bias, [1, -1, 1, 1, 1]) + res = tf.math.add(res, bias) + if permuted_x: return tf.transpose(res, (0, 4, 1, 2, 3)) return res -@with_unsupported_dtypes({"2.14.0 and below": ("bfloat16", "complex")}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("bfloat16", "complex")}, backend_version) def conv3d_transpose( x: Tensor, filters: Tensor, @@ -270,6 +375,7 @@ def conv3d_transpose( /, *, output_shape: Optional[Union[ivy.NativeShape, Sequence[int]]] = None, + filter_format: str = "channel_last", data_format: str = "NDHWC", dilations: Union[int, Tuple[int, int, int]] = 1, bias: Optional[Union[tf.Tensor, tf.Variable]] = None, @@ -281,26 +387,30 @@ def conv3d_transpose( raise ivy.utils.exceptions.IvyException( "Tensorflow does not support dilations greater than 1 when device is cpu" ) - strides = [1] + ([strides] * 3 if isinstance(strides, int) else strides) + [1] - dilations = ( - [1] + ([dilations] * 3 if isinstance(dilations, int) else dilations) + [1] - ) - if data_format == "NCDHW": + permuted_x = False + if data_format == "NCDHW" and ivy.dev(x) == "cpu": x = tf.transpose(x, (0, 2, 3, 4, 1)) - filters = tf.transpose(filters, (0, 1, 2, 4, 3)) - output_shape = _output_shape( - x.shape, filters.shape, output_shape, strides[1:], padding, 3, dilations + data_format = "NDHWC" + permuted_x = True + if filter_format == "channel_first": + filters = tf.transpose(filters, (2, 3, 4, 1, 0)) + output_shape, padding = _transpose_out_pad( + x.shape, filters.shape, strides, padding, 3, dilations, data_format ) + strides, dilations = _extend_3d_strides_dilations(strides, dilations, data_format) res = tf.nn.conv3d_transpose( - x, filters, output_shape, strides, padding, "NDHWC", dilations + x, filters, output_shape, strides, padding, data_format, dilations ) - res = tf.math.add(res, bias) if bias is not None else res - if data_format == "NCDHW": + if bias is not None: + if data_format[1] == "C": + bias = tf.reshape(bias, [1, -1, 1, 1, 1]) + res = tf.math.add(res, bias) + if permuted_x: return tf.transpose(res, (0, 4, 1, 2, 3)) return res -@with_unsupported_dtypes({"2.14.0 and below": ("bfloat16", "complex")}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("bfloat16", "complex")}, backend_version) def conv_general_dilated( x: Union[tf.Tensor, tf.Variable], filters: Union[tf.Tensor, tf.Variable], @@ -317,105 +427,140 @@ def conv_general_dilated( bias: Optional[Union[tf.Tensor, tf.Variable]] = None, out: Optional[Union[tf.Tensor, tf.Variable]] = None, ) -> Union[tf.Tensor, tf.Variable]: - # permuting dims based on formats - if data_format == "channel_first": - x = tf.transpose(x, (0, *range(2, dims + 2), 1)) - if filter_format == "channel_first": filters = tf.transpose(filters, (*range(2, dims + 2), 1, 0)) - # adding dilation in input - x_dilations = [x_dilations] * dims if isinstance(x_dilations, int) else x_dilations - for i in range(dims): - if x_dilations[i] > 1: - h = x.shape[1 + i] - new_height = h + (h - 1) * (x_dilations[i] - 1) - h = tf.eye(new_height, dtype=x.dtype)[:: x_dilations[i]] - x = tf.experimental.numpy.swapaxes(x, 1 + i, -1) - x = tf.matmul(x, h) - x = tf.experimental.numpy.swapaxes(x, -1, 1 + i) - - x = _pad_before_conv(x, filters, strides, padding, dims, dilations) - df = _get_x_data_format(dims, "channel_last") - if dims == 3: - strides = [1] + ([strides] * 3 if isinstance(strides, int) else strides) + [1] - dilations = ( - [1] + ([dilations] * 3 if isinstance(dilations, int) else dilations) + [1] - ) - if filters.shape[-2] != (x.shape[-1] // feature_group_count): + num_channels = x.shape[1] if data_format == "channel_first" else x.shape[-1] + if filters.shape[-2] != (num_channels // feature_group_count): raise ivy.utils.exceptions.IvyError( f"given feature_group_count {feature_group_count} expected input channel of" - f" the filter to be {x.shape[-1] // feature_group_count} but got" + f" the filter to be {num_channels // feature_group_count} but got" f" {filters.shape[-2]}" ) - - if x.shape[-1] % feature_group_count != 0: + if num_channels % feature_group_count != 0: raise ivy.utils.exceptions.IvyError( "input channel should be divisible by feature group count" - f" {feature_group_count} but got input channel {x.shape[-1]}" - ) - if dims == 1: - res = tf.nn.conv1d( - x, - filters, - strides, - "VALID", - df, - dilations, + f" {feature_group_count} but got input channel {num_channels}" ) - elif dims == 2: - res = tf.nn.conv2d( - x, - filters, - strides, - "VALID", - df, - dilations, - ) - else: - # grouped conv3d is not supported on CPU - # ToDO: change the condition of GPU when automatic device shifting - # is implemented in ivy - if feature_group_count == 1 or tf.test.is_gpu_available(): - res = tf.nn.conv3d( + + permuted_x = False + if data_format == "channel_first" and ( + ivy.dev(x) == "cpu" or feature_group_count != 1 + ): + x = tf.transpose(x, (0, *range(2, dims + 2), 1)) + data_format = "channel_last" + permuted_x = True + + data_format = _get_x_data_format(dims, data_format) + + x = _x_dil_before_conv(x, dims, x_dilations, data_format) + + if dims == 2: + padding = _extend_2d_padding(padding, data_format) + if feature_group_count == 1: + res = tf.nn.conv2d( x, filters, strides, - "VALID", - df, - dilations, + padding, + data_format=data_format, + dilations=dilations, ) else: - res = tf.concat( - [ - tf.nn.conv3d( - x[:, :, :, :, i : i + filters.shape[-2]], - filters[ - :, :, :, :, j : j + filters.shape[-1] // feature_group_count - ], - strides, - "VALID", - df, - dilations, - ) - for i, j in zip( - range(0, x.shape[-1], filters.shape[-2]), - range( - 0, - filters.shape[-1], - filters.shape[-1] // feature_group_count, - ), - ) - ], - axis=-1, + with ivy.ArrayMode(False): + if not isinstance(padding, str): + padding = padding[1:-1] + res = depthwise_conv2d( + x, + tf.transpose(filters, (0, 1, 3, 2)), + strides, + padding, + data_format=data_format, + dilations=dilations, + ) + else: + x, padding = _pad_before_conv(x, padding, dims, data_format) + if dims == 1: + if feature_group_count == 1: + res = tf.nn.conv1d( + x, + filters, + strides, + padding, + data_format=data_format, + dilations=dilations, + ) + else: + res = tf.concat( + [ + tf.nn.conv1d( + x[..., i : i + filters.shape[-2]], + filters[ + ..., j : j + filters.shape[-1] // feature_group_count + ], + strides, + padding, + data_format, + dilations, + ) + for i, j in zip( + range(0, x.shape[-1], filters.shape[-2]), + range( + 0, + filters.shape[-1], + filters.shape[-1] // feature_group_count, + ), + ) + ], + axis=-1, + ) + else: + strides, dilations = _extend_3d_strides_dilations( + strides, dilations, data_format ) - res = tf.math.add(res, bias) if bias is not None else res - if data_format == "channel_first": - res = tf.transpose(res, (0, dims + 1, *range(1, dims + 1))) + if feature_group_count == 1: + res = tf.nn.conv3d( + x, + filters, + strides, + padding, + data_format=data_format, + dilations=dilations, + ) + else: + res = tf.concat( + [ + tf.nn.conv3d( + x[..., i : i + filters.shape[-2]], + filters[ + ..., j : j + filters.shape[-1] // feature_group_count + ], + strides, + padding, + data_format, + dilations, + ) + for i, j in zip( + range(0, x.shape[-1], filters.shape[-2]), + range( + 0, + filters.shape[-1], + filters.shape[-1] // feature_group_count, + ), + ) + ], + axis=-1, + ) + if bias is not None: + if data_format[1] == "C": + bias = tf.reshape(bias, [1, -1, *([1] * dims)]) + res = tf.math.add(res, bias) + if permuted_x: + return tf.transpose(res, (0, dims + 1, *range(1, dims + 1))) return res -@with_unsupported_dtypes({"2.14.0 and below": ("bfloat16", "complex")}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("bfloat16", "complex")}, backend_version) def conv_general_transpose( x: Union[tf.Tensor, tf.Variable], filters: Union[tf.Tensor, tf.Variable], @@ -424,6 +569,7 @@ def conv_general_transpose( /, *, dims: int = 2, + filter_format: str = "channel_last", data_format: str = "channel_last", output_shape: Optional[Union[ivy.NativeShape, Sequence[int]]] = None, dilations: Union[int, Tuple[int], Tuple[int, int], Tuple[int, int, int]] = 1, @@ -431,66 +577,240 @@ def conv_general_transpose( bias: Optional[Union[tf.Tensor, tf.Variable]] = None, out: Optional[Union[tf.Tensor, tf.Variable]] = None, ) -> Union[tf.Tensor, tf.Variable]: - if data_format == "channel_first": - x = tf.transpose(x, (0, *range(2, dims + 2), 1)) - if dims == 1: - res = tf.concat( - [ - conv1d_transpose( - x[..., j : j + filters.shape[-2] // feature_group_count], - filters[..., j : j + filters.shape[-2] // feature_group_count, :], - strides, - padding, - output_shape=output_shape, - data_format="NWC", - dilations=dilations, - ) - for j in range( - 0, filters.shape[-2], filters.shape[-2] // feature_group_count - ) - ], - axis=-1, + if feature_group_count == 1: + if dims == 1: + return conv1d_transpose( + x, + filters, + strides, + padding, + output_shape=output_shape, + filter_format=filter_format, + data_format="NWC" if data_format == "channel_last" else "NCW", + dilations=dilations, + bias=bias, + ) + elif dims == 2: + return conv2d_transpose( + x, + filters, + strides, + padding, + output_shape=output_shape, + filter_format=filter_format, + data_format="NHWC" if data_format == "channel_last" else "NCHW", + dilations=dilations, + bias=bias, + ) + else: + return conv3d_transpose( + x, + filters, + strides, + padding, + output_shape=output_shape, + filter_format=filter_format, + data_format="NDHWC" if data_format == "channel_last" else "NCDHW", + dilations=dilations, + bias=bias, + ) + else: + if filter_format == "channel_first": + filters = tf.transpose(filters, (*range(2, dims + 2), 1, 0)) + permuted_x = False + if data_format == "channel_first" and ivy.dev(x) == "cpu": + x = tf.transpose(x, (0, *range(2, dims + 2), 1)) + data_format = "channel_last" + permuted_x = True + + data_format = _get_x_data_format(dims, data_format) + + output_shape, padding = _transpose_out_pad( + x.shape, filters.shape, strides, padding, dims, dilations, data_format ) - elif dims == 2: - res = tf.concat( - [ - conv2d_transpose( - x[..., j : j + filters.shape[-2] // feature_group_count], - filters[..., j : j + filters.shape[-2] // feature_group_count, :], - strides, - padding, - output_shape=output_shape, - data_format="NHWC", - dilations=dilations, - ) - for j in range( - 0, filters.shape[-2], filters.shape[-2] // feature_group_count - ) - ], - axis=-1, + + if dims == 1: + res = tf.concat( + [ + tf.nn.conv1d_transpose( + x[..., j : j + filters.shape[-2] // feature_group_count], + filters[ + ..., j : j + filters.shape[-2] // feature_group_count, : + ], + output_shape, + strides, + padding=padding, + data_format=data_format, + dilations=dilations, + ) + for j in range( + 0, filters.shape[-2], filters.shape[-2] // feature_group_count + ) + ], + axis=-1, + ) + elif dims == 2: + res = tf.concat( + [ + tf.nn.conv2d_transpose( + x[..., j : j + filters.shape[-2] // feature_group_count], + filters[ + ..., j : j + filters.shape[-2] // feature_group_count, : + ], + output_shape, + strides, + padding=padding, + data_format=data_format, + dilations=dilations, + ) + for j in range( + 0, filters.shape[-2], filters.shape[-2] // feature_group_count + ) + ], + axis=-1, + ) + else: + strides, dilations = _extend_3d_strides_dilations( + strides, dilations, data_format + ) + res = tf.concat( + [ + tf.nn.conv3d_transpose( + x[..., j : j + filters.shape[-2] // feature_group_count], + filters[ + ..., j : j + filters.shape[-2] // feature_group_count, : + ], + output_shape, + strides, + padding=padding, + data_format=data_format, + dilations=dilations, + ) + for j in range( + 0, filters.shape[-2], filters.shape[-2] // feature_group_count + ) + ], + axis=-1, + ) + + res = tf.math.add(res, bias) if bias is not None else res + if permuted_x: + return tf.transpose(res, (0, dims + 1, *range(1, dims + 1))) + return res + + +def _cpu_lstm( + x, init_h, init_c, kernel, recurrent_kernel, bias, recurrent_bias, time_major +): + def step(cell_inputs, cell_states): + h_tm1 = cell_states[0] # previous memory state + c_tm1 = cell_states[1] # previous carry state + + z = tf.keras.backend.dot(cell_inputs, kernel) + if bias is not None: + z += bias + + z += tf.keras.backend.dot(h_tm1, recurrent_kernel) + if recurrent_bias is not None: + z += recurrent_bias + + z0, z1, z2, z3 = tf.split(z, 4, axis=-1) + + i = tf.sigmoid(z0) + f = tf.sigmoid(z1) + c = f * c_tm1 + i * tf.tanh(z2) + o = tf.sigmoid(z3) + + h = o * tf.tanh(c) + return h, [h, c] + + _, outputs, new_states = tf.keras.backend.rnn( + step, + x, + [init_h, init_c], + time_major=time_major, + ) + return outputs, new_states + + +def _format_weights_for_gpu(weights, biases, shape): + weights = [tf.reshape(tf.transpose(x), shape) for x in weights] + biases = [tf.reshape(x, shape) for x in biases] + return tf.concat(weights + biases, axis=0) + + +def _gpu_lstm( + x, init_h, init_c, kernel, recurrent_kernel, bias, recurrent_bias, time_major +): + if not time_major: + x = tf.transpose(x, perm=(1, 0, 2)) + + init_h = tf.expand_dims(init_h, axis=0) + init_c = tf.expand_dims(init_c, axis=0) + + weights = tf.split(kernel, 4, axis=1) + weights += tf.split(recurrent_kernel, 4, axis=1) + full_bias = tf.concat((recurrent_bias, bias), axis=0) + params = _format_weights_for_gpu( + weights=weights, + biases=tf.split(full_bias, 8), + shape=tf.constant([-1]), + ) + outputs, h, c, _ = tf.raw_ops.CudnnRNN( + input=x, + input_h=init_h, + input_c=init_c, + params=params, + rnn_mode="lstm", + ) + return outputs, (h, c) + + +def lstm_update( + x: Union[tf.Tensor, tf.Variable], + init_h: Union[tf.Tensor, tf.Variable], + init_c: Union[tf.Tensor, tf.Variable], + kernel: Union[tf.Tensor, tf.Variable], + recurrent_kernel: Union[tf.Tensor, tf.Variable], + /, + *, + bias: Optional[Union[tf.Tensor, tf.Variable]] = None, + recurrent_bias: Optional[Union[tf.Tensor, tf.Variable]] = None, + time_major: bool = False, +) -> Tuple[Tensor, Tuple[Tensor, Tensor]]: + dev = x.device + x = x.data + init_h = init_h.data + init_c = init_c.data + kernel = kernel.data + recurrent_kernel = recurrent_kernel.data + bias = bias.data if bias is not None else bias + recurrent_bias = ( + recurrent_bias.data if recurrent_bias is not None else recurrent_bias + ) + if "cpu" in dev: + outputs, new_states = _cpu_lstm( + x, + init_h, + init_c, + kernel, + recurrent_kernel, + bias, + recurrent_bias, + time_major, ) else: - res = tf.concat( - [ - conv3d_transpose( - x[..., j : j + filters.shape[-2] // feature_group_count], - filters[..., j : j + filters.shape[-2] // feature_group_count, :], - strides, - padding, - output_shape=output_shape, - data_format="NDHWC", - dilations=dilations, - ) - for j in range( - 0, filters.shape[-2], filters.shape[-2] // feature_group_count - ) - ], - axis=-1, + outputs, new_states = _gpu_lstm( + x, + init_h, + init_c, + kernel, + recurrent_kernel, + bias, + recurrent_bias, + time_major, ) - res = tf.math.add(res, bias) if bias is not None else res - if data_format == "channel_first": - res = tf.transpose(res, (0, dims + 1, *range(1, dims + 1))) - return res + return outputs, new_states def nms( diff --git a/ivy/functional/backends/tensorflow/linear_algebra.py b/ivy/functional/backends/tensorflow/linear_algebra.py index 10bf64c766fba..230d91a7be0f3 100644 --- a/ivy/functional/backends/tensorflow/linear_algebra.py +++ b/ivy/functional/backends/tensorflow/linear_algebra.py @@ -17,7 +17,7 @@ # -------------------# -@with_unsupported_dtypes({"2.14.0 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("float16", "bfloat16")}, backend_version) def cholesky( x: Union[tf.Tensor, tf.Variable], /, @@ -35,7 +35,7 @@ def cholesky( @with_unsupported_dtypes( { - "2.14.0 and below": ( + "2.15.0 and below": ( "complex", "float16", ) @@ -61,7 +61,7 @@ def cross( @with_unsupported_dtypes( { - "2.14.0 and below": ( + "2.15.0 and below": ( "float16", "bfloat16", ) @@ -77,7 +77,7 @@ def det( return tf.linalg.det(x) -@with_unsupported_dtypes({"2.14.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("complex",)}, backend_version) def diagonal( x: Union[tf.Tensor, tf.Variable], /, @@ -90,7 +90,7 @@ def diagonal( return tf.experimental.numpy.diagonal(x, offset, axis1=axis1, axis2=axis2) -@with_unsupported_dtypes({"2.14.0 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("float16", "bfloat16")}, backend_version) def eig( x: Union[tf.Tensor, tf.Variable], /, @@ -108,7 +108,7 @@ def eig( return result_tuple(eigenvalues, eigenvectors) -@with_unsupported_dtypes({"2.14.0 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("float16", "bfloat16")}, backend_version) def eigh( x: Union[tf.Tensor, tf.Variable], /, @@ -135,7 +135,7 @@ def eigh( return result_tuple(eigenvalues, eigenvectors) -@with_unsupported_dtypes({"2.14.0 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("float16", "bfloat16")}, backend_version) def eigvalsh( x: Union[tf.Tensor, tf.Variable], /, @@ -156,7 +156,7 @@ def eigvalsh( @with_unsupported_dtypes( { - "2.14.0 and below": ( + "2.15.0 and below": ( "int8", "uint8", "int16", @@ -182,7 +182,7 @@ def inner( @with_unsupported_dtypes( { - "2.14.0 and below": ( + "2.15.0 and below": ( "float16", "bfloat16", ) @@ -200,7 +200,7 @@ def inv( @with_unsupported_dtypes( - {"2.14.0 and below": ("float16", "bfloat16", "bool")}, backend_version + {"2.15.0 and below": ("float16", "bfloat16", "bool")}, backend_version ) def matmul( x1: Union[tf.Tensor, tf.Variable], @@ -279,7 +279,7 @@ def matmul( @with_supported_dtypes( - {"2.14.0 and below": ("float32", "float64", "complex")}, backend_version + {"2.15.0 and below": ("float32", "float64", "complex")}, backend_version ) def matrix_norm( x: Union[tf.Tensor, tf.Variable], @@ -288,8 +288,11 @@ def matrix_norm( ord: Union[int, float, Literal[inf, -inf, "fro", "nuc"]] = "fro", axis: Tuple[int, int] = (-2, -1), keepdims: bool = False, + dtype: Optional[tf.DType] = None, out: Optional[Union[tf.Tensor, tf.Variable]] = None, ) -> Union[tf.Tensor, tf.Variable]: + if dtype is not None: + x = ivy.astype(x, dtype) if ord == "nuc": x = tf.experimental.numpy.moveaxis(x, axis, (-2, -1)) ret = tf.reduce_sum( @@ -323,7 +326,7 @@ def matrix_norm( return ret -@with_unsupported_dtypes({"2.14.0 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("float16", "bfloat16")}, backend_version) def matrix_power( x: Union[tf.Tensor, tf.Variable], n: int, @@ -356,7 +359,7 @@ def matrix_power( @with_unsupported_dtypes( - {"2.14.0 and below": ("bfloat16", "float16", "complex")}, + {"2.15.0 and below": ("bfloat16", "float16", "complex")}, backend_version, ) # noinspection PyPep8Naming @@ -394,7 +397,7 @@ def matrix_rank( @with_unsupported_dtypes( { - "2.14.0 and below": ( + "2.15.0 and below": ( "float16", "int8", "int16", @@ -421,7 +424,7 @@ def matrix_transpose( # noinspection PyUnusedLocal,PyShadowingBuiltins -@with_unsupported_dtypes({"2.14.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("complex",)}, backend_version) def outer( x1: Union[tf.Tensor, tf.Variable], x2: Union[tf.Tensor, tf.Variable], @@ -434,7 +437,7 @@ def outer( @with_unsupported_dtypes( - {"2.14.0 and below": ("bfloat16", "float16", "complex")}, + {"2.15.0 and below": ("bfloat16", "float16", "complex")}, backend_version, ) def pinv( @@ -452,7 +455,7 @@ def pinv( return ret -@with_unsupported_dtypes({"2.14.0 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("float16", "bfloat16")}, backend_version) def qr( x: Union[tf.Tensor, tf.Variable], /, @@ -477,7 +480,7 @@ def qr( return ret -@with_unsupported_dtypes({"2.14.0 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("float16", "bfloat16")}, backend_version) def slogdet( x: Union[tf.Tensor, tf.Variable], /, @@ -488,7 +491,7 @@ def slogdet( @with_unsupported_dtypes( - {"2.14.0 and below": ("bfloat16", "float16", "complex")}, + {"2.15.0 and below": ("bfloat16", "float16", "complex")}, backend_version, ) def solve( @@ -531,7 +534,7 @@ def solve( @with_unsupported_dtypes( - {"2.14.0 and below": ("bfloat16", "float16", "complex")}, + {"2.15.0 and below": ("bfloat16", "float16", "complex")}, backend_version, ) def svd( @@ -559,7 +562,7 @@ def svd( return results(D) -@with_unsupported_dtypes({"2.14.0 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("float16", "bfloat16")}, backend_version) def svdvals( x: Union[tf.Tensor, tf.Variable], /, @@ -572,7 +575,7 @@ def svdvals( return ret -@with_supported_dtypes({"2.14.0 and below": ("float32",)}, backend_version) +@with_supported_dtypes({"2.15.0 and below": ("float32",)}, backend_version) def tensordot( x1: Union[tf.Tensor, tf.Variable], x2: Union[tf.Tensor, tf.Variable], @@ -587,7 +590,7 @@ def tensordot( @with_unsupported_dtypes( - {"2.14.0 and below": ("bfloat16", "float16", "complex")}, + {"2.15.0 and below": ("bfloat16", "float16", "complex")}, backend_version, ) def trace( @@ -606,7 +609,7 @@ def trace( @with_unsupported_dtypes( - {"2.14.0 and below": ("int16", "int8", "bool", "unsigned")}, backend_version + {"2.15.0 and below": ("int16", "int8", "bool", "unsigned")}, backend_version ) def vecdot( x1: Union[tf.Tensor, tf.Variable], @@ -622,10 +625,11 @@ def vecdot( @with_unsupported_dtypes( { - "2.14.0 and below": ( + "2.15.0 and below": ( "float16", "bfloat16", "integer", + "complex64", ) }, backend_version, @@ -657,7 +661,7 @@ def vector_norm( # ----- # -@with_unsupported_dtypes({"2.14.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("complex",)}, backend_version) def diag( x: Union[tf.Tensor, tf.Variable], /, @@ -669,7 +673,7 @@ def diag( @with_unsupported_dtypes( - {"2.14.0 and below": ("bfloat16", "float16", "complex", "unsigned")}, + {"2.15.0 and below": ("bfloat16", "float16", "complex", "unsigned")}, backend_version, ) def vander( @@ -685,7 +689,7 @@ def vander( @with_unsupported_dtypes( { - "2.14.0 and below": ( + "2.15.0 and below": ( "int8", "int16", "int32", diff --git a/ivy/functional/backends/tensorflow/manipulation.py b/ivy/functional/backends/tensorflow/manipulation.py index 2350017b1931e..8635ca5ebb173 100644 --- a/ivy/functional/backends/tensorflow/manipulation.py +++ b/ivy/functional/backends/tensorflow/manipulation.py @@ -32,26 +32,25 @@ def concat( axis: int = 0, out: Optional[Union[tf.Tensor, tf.Variable]] = None, ) -> Union[tf.Tensor, tf.Variable]: - is_tuple = type(xs) is tuple - is_axis_none = axis is None - if is_tuple: - xs = list(xs) - highest_dtype = xs[0].dtype - for i in xs: - highest_dtype = ivy.as_native_dtype(ivy.promote_types(highest_dtype, i.dtype)) - - for i in range(len(xs)): - if is_axis_none: - xs[i] = tf.reshape(xs[i], -1) - xs[i] = ivy.astype(xs[i], highest_dtype, copy=False).to_native() - if is_axis_none: - axis = 0 - if is_tuple: - xs = tuple(xs) - try: - return tf.concat(xs, axis) - except (tf.errors.InvalidArgumentError, np.AxisError) as error: - raise ivy.utils.exceptions.IvyIndexError(error) + if axis is not None: + try: + return tf.concat(xs, axis) + except tf.errors.InvalidArgumentError as error: + if "(zero-based) was expected to be" in error.message: + highest_dtype = xs[0].dtype + for i in xs: + highest_dtype = ivy.promote_types(highest_dtype, i.dtype) + highest_dtype = ivy.as_native_dtype(highest_dtype) + return tf.concat( + [ + tf.cast(x, highest_dtype) if x.dtype != highest_dtype else x + for x in xs + ], + axis, + ) + else: + raise + return concat([tf.reshape(x, -1) for x in xs], axis=0) def expand_dims( @@ -67,7 +66,7 @@ def expand_dims( ret = tf.reshape(x, shape=out_shape) return ret except (tf.errors.InvalidArgumentError, np.AxisError) as error: - raise ivy.utils.exceptions.IvyIndexError(error) + raise ivy.utils.exceptions.IvyIndexError(error) from error def flip( @@ -86,7 +85,7 @@ def flip( new_axis = list(range(num_dims)) else: new_axis = axis - if type(new_axis) is int: + if isinstance(new_axis, int): new_axis = [new_axis] else: new_axis = new_axis @@ -106,7 +105,7 @@ def permute_dims( return tf.transpose(x, perm=axes) -@with_unsupported_dtypes({"2.14.0 and below": ("bool",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("bool",)}, backend_version) def reshape( x: Union[tf.Tensor, tf.Variable], /, @@ -186,7 +185,7 @@ def squeeze( return ret -@with_unsupported_dtypes({"2.14.0 and below": ("bfloat16",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("bfloat16",)}, backend_version) def stack( arrays: Union[Tuple[tf.Tensor], List[tf.Tensor]], /, @@ -197,7 +196,7 @@ def stack( try: return tf.experimental.numpy.stack(arrays, axis) except ValueError as e: - raise ivy.utils.exceptions.IvyIndexError(e) + raise ivy.utils.exceptions.IvyIndexError(e) from e # Extra # @@ -227,7 +226,6 @@ def split( num_or_size_splits = int(dim_size) if isinstance(num_or_size_splits, (tf.Tensor, tf.Variable)): num_or_size_splits = tf.cast(num_or_size_splits, tf.int32) - num_or_size_splits = num_or_size_splits.numpy().tolist() elif isinstance(num_or_size_splits, int) and with_remainder: num_chunks = x.shape[axis] / num_or_size_splits num_chunks_int = math.floor(num_chunks) @@ -245,7 +243,7 @@ def repeat( /, repeats: Union[int, List[int]], *, - axis: int = None, + axis: Optional[int] = None, out: Optional[Union[tf.Tensor, tf.Variable]] = None, ) -> Union[tf.Tensor, tf.Variable]: return tf.repeat(x, repeats, axis) @@ -253,7 +251,7 @@ def repeat( @with_unsupported_dtypes( { - "2.14.0 and below": ( + "2.15.0 and below": ( "uint8", "uint16", "uint32", @@ -324,7 +322,7 @@ def swapaxes( return tf.transpose(x, config) -@with_unsupported_dtypes({"2.14.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("complex",)}, backend_version) def clip( x: Union[tf.Tensor, tf.Variable], /, diff --git a/ivy/functional/backends/tensorflow/module.py b/ivy/functional/backends/tensorflow/module.py new file mode 100644 index 0000000000000..a6487f0377604 --- /dev/null +++ b/ivy/functional/backends/tensorflow/module.py @@ -0,0 +1,893 @@ +# global +from __future__ import annotations +import re +import os +import tensorflow as tf +import functools +import logging +from tensorflow.python.util import nest +from typing import NamedTuple, Callable, Any, Tuple, List, Dict, Type, Union + +# A NodeDef holds two callables: +# - flatten_fn should take the collection and return a flat list of values. +# It can also return some context that is used in reconstructing the +# collection. +# - unflatten_fn should take a flat list of values and some context +# (returned by flatten_fn). It returns the collection by reconstructing +# it from the list and the context. +Context = Any +PyTree = Any +FlattenFunc = Callable[[PyTree], Tuple[List, Context]] +UnflattenFunc = Callable[[List, Context], PyTree] + + +class NodeDef(NamedTuple): + flatten_fn: FlattenFunc + unflatten_fn: UnflattenFunc + + +SUPPORTED_NODES: Dict[Type[Any], NodeDef] = {} + + +def _register_pytree_node( + typ: Any, flatten_fn: FlattenFunc, unflatten_fn: UnflattenFunc +) -> None: + SUPPORTED_NODES[typ] = NodeDef(flatten_fn, unflatten_fn) + + +def _dict_flatten(d: Dict[Any, Any]) -> Tuple[List[Any], Context]: + return list(d.values()), list(d.keys()) + + +def _dict_unflatten(values: List[Any], context: Context) -> Dict[Any, Any]: + return {key: value for key, value in zip(context, values)} + + +_register_pytree_node(dict, _dict_flatten, _dict_unflatten) + + +def _get_node_type(pytree: Any) -> Any: + return type(pytree) + + +# A leaf is defined as anything that is not a Node. +def _is_leaf(pytree: PyTree) -> bool: + return _get_node_type(pytree) not in SUPPORTED_NODES.keys() + + +# A TreeSpec represents the structure of a pytree. It holds: +# "type": the type of root Node of the pytree +# context: some context that is useful in unflattening the pytree +# children_specs: specs for each child of the root Node +# num_leaves: the number of leaves +class TreeSpec: + def __init__(self, type, context, children_specs): + self.type: Any = type + self.context: Context = context + self.children_specs: List["TreeSpec"] = children_specs + self.num_leaves: int = sum([spec.num_leaves for spec in self.children_specs]) + + def get_keychains(self, prefix="", sep="/"): + keychains = [] + for key, child_spec in zip(self.context, self.children_specs): + new_prefix = prefix + key + sep if prefix else key + sep + if child_spec.children_specs: # Non-leaf node + keychains.extend(child_spec.get_keychains(new_prefix, sep)) + else: # Leaf node + keychains.append(new_prefix[: -len(sep)]) + return keychains + + def __repr__(self, indent: int = 0) -> str: + repr_prefix: str = f"TreeSpec({self.type.__name__}, {self.context}, [" + children_specs_str: str = "" + if len(self.children_specs): + indent += len(repr_prefix) + children_specs_str += self.children_specs[0].__repr__(indent) + children_specs_str += "," if len(self.children_specs) > 1 else "" + children_specs_str += ",".join( + [ + "\n" + " " * indent + child.__repr__(indent) + for child in self.children_specs[1:] + ] + ) + repr_suffix: str = f"{children_specs_str}])" + return repr_prefix + repr_suffix + + +class LeafSpec(TreeSpec): + def __init__(self) -> None: + super().__init__(None, None, []) + self.num_leaves = 1 + + def __repr__(self, indent: int = 0) -> str: + return "*" + + +def tree_flatten(pytree: PyTree) -> Tuple[List[Any], TreeSpec]: + """Flattens a pytree into a list of values and a TreeSpec that can be used + to reconstruct the pytree.""" + if _is_leaf(pytree): + return [pytree], LeafSpec() + + node_type = _get_node_type(pytree) + flatten_fn = _dict_flatten + child_pytrees, context = flatten_fn(pytree) + + # Recursively flatten the children + result: List[Any] = [] + children_specs: List["TreeSpec"] = [] + for child in child_pytrees: + flat, child_spec = tree_flatten(child) + result += flat + children_specs.append(child_spec) + + return result, TreeSpec(node_type, context, children_specs) + + +def tree_unflatten(values: List[Any], spec: TreeSpec) -> PyTree: + """Given a list of values and a TreeSpec, builds a pytree. + + This is the inverse operation of `tree_flatten`. + """ + if not isinstance(spec, TreeSpec): + raise TypeError( + f"tree_unflatten(values, spec): Expected `spec` to be instance of " + f"TreeSpec but got item of type {type(spec)}." + ) + if len(values) != spec.num_leaves: + raise TypeError( + f"tree_unflatten(values, spec): `values` has length {len(values)} " + f"but the spec refers to a pytree that holds {spec.num_leaves} " + f"items ({spec})." + ) + if isinstance(spec, LeafSpec): + return values[0] + + unflatten_fn = _dict_unflatten + + # Recursively unflatten the children + start = 0 + end = 0 + child_pytrees = [] + for child_spec in spec.children_specs: + end += child_spec.num_leaves + child_pytrees.append(tree_unflatten(values[start:end], child_spec)) + start = end + + return unflatten_fn(child_pytrees, spec.context) + + +class ModelHelpers: + @staticmethod + @tf.autograph.experimental.do_not_convert + def _get_first_array(*args, **kwargs): + arr = None + flattened_args = tf.nest.flatten((args, kwargs)) + arr_candidates = tf.nest.map_structure( + lambda x: x if isinstance(x, (tf.Tensor, tf.Variable)) else False, + flattened_args, + ) + for arr_candidate in arr_candidates: + if arr_candidate is not False: + arr = arr_candidate + break + return arr + + @staticmethod + @tf.autograph.experimental.do_not_convert + def _get_input_shapes(*args): + input_shapes = [] + for x in args: + if isinstance(x, (tf.Tensor, tf.Variable)): + input_shapes.append(x.shape) + else: + try: + x = tf.convert_to_tensor(x) + input_shapes.append(x.shape) + except Exception: + input_shapes.append(None) + return input_shapes + + @staticmethod + @tf.autograph.experimental.do_not_convert + def _extract_v(v, keychain_mappings: dict, orig_key_chain, /): + if ModelHelpers._dict_has_key_chain(v, orig_key_chain): + ret_cont = ModelHelpers._dict_at_key_chain(v, orig_key_chain) + else: + ret_cont = dict() + for old_kc, new_kc in keychain_mappings.items(): + if orig_key_chain in old_kc: + # Check if `v` contains `new_kc` before replacing in `ret_cont` + if ModelHelpers._dict_has_key_chain(v, new_kc): + ret_cont = ModelHelpers._dict_set_at_key_chain( + ret_cont, + "/".join(old_kc.split("/")[1:]), + ModelHelpers._dict_at_key_chain(v, new_kc), + ) + else: + continue + return ret_cont + + @staticmethod + @tf.autograph.experimental.do_not_convert + def _remove_duplicate_variables(vs, created, /): + created_ids = tf.nest.map_structure(lambda x: id(x), created) + vs_ids = tf.nest.map_structure(lambda x: id(x), vs) + ids = {} + duplicate_keychains = [] + keychain_mappings = {} + + def unique_callback(x, kc): + ids[x] = kc + return x + + def found_dup_callback(x, kc): + if ids[x] == kc: + return x + duplicate_keychains.append(kc) + keychain_mappings[kc] = ids[x] + return x + + created_ids = nest.map_structure_with_paths( + lambda kc, x: unique_callback(x, kc), created_ids + ) + vs_ids = nest.map_structure_with_paths( + lambda kc, x: ( + unique_callback(x, kc) if x not in ids else found_dup_callback(x, kc) + ), + vs_ids, + ) + for dup_kc in duplicate_keychains: + vs = ModelHelpers._dict_prune_key_chain(vs, dup_kc) + return vs, keychain_mappings + + @staticmethod + @tf.autograph.experimental.do_not_convert + def _dict_set_at_key_chain(in_dict, key_chain, val, inplace=False): + keys = re.split("[/.]", key_chain) + if inplace: + cont = in_dict + else: + cont = in_dict + sub_cont = cont + for key in keys[:-1]: + if key not in sub_cont: + sub_cont[key] = dict() + sub_cont = sub_cont[key] + sub_cont[keys[-1]] = val + return cont + + @staticmethod + @tf.autograph.experimental.do_not_convert + def _dict_at_key_chain(dict, key_chain, ignore_key_errors=False): + keys = re.split("[/.]", key_chain) + ret = dict + for key in keys: + try: + ret = ret[key] + except KeyError as e: + if ignore_key_errors: + return + raise Exception(repr(e)) + return ret + + @staticmethod + @tf.autograph.experimental.do_not_convert + def _dict_has_key_chain(dict, key_chain): + keys = re.split("[/.]", key_chain) + ret = dict + for key in keys: + try: + ret = ret[key] + except KeyError: + return False + return True + + @staticmethod + @tf.autograph.experimental.do_not_convert + def _dict_prune_key_chain(in_dict, key_chain): + keys_in_chain = re.split("[/.]", key_chain) + out_dict = {} + for key, value in in_dict.items(): + if isinstance(value, dict): + if key == keys_in_chain[0]: + if len(keys_in_chain) == 1: + new_val = [] + else: + new_val = ModelHelpers._dict_prune_key_chain( + value, + "/".join(keys_in_chain[1:]), + ) + if len(new_val) > 0: + out_dict[key] = new_val + else: + if len(value) > 0: + out_dict[key] = value + else: + if len(keys_in_chain) != 1 or key != keys_in_chain[0]: + out_dict[key] = value + return out_dict + + @staticmethod + @tf.autograph.experimental.do_not_convert + def _addindent(s_, numSpaces): + s = s_.split("\n") + # don't do anything for single-line stuff + if len(s) == 1: + return s_ + first = s.pop(0) + s = [(numSpaces * " ") + line for line in s] + s = "\n".join(s) + s = first + "\n" + s + return s + + +class Model(tf.keras.Model, ModelHelpers): + _build_mode = None + _with_partial_v = None + _store_vars = True + _built = False + _v = None + _buffers = None + _module_dict = None + _args = None + _kwargs = None + _module_graph = None + _target = None + _lazy_traced = False + _training = None + _dynamic_backend = None + _device = None + _dtype = None + + def __init__( + self, + /, + *args, + v=None, + buffers=None, + build_mode="on_init", + store_vars=True, + with_partial_v=False, + dynamic_backend=None, + training=True, + dtype=None, + device=None, + **kwargs, + ): + super(Model, self).__init__( + trainable=training, + dtype=dtype, + ) + self._build_mode = build_mode + self._with_partial_v = with_partial_v + self._store_vars = store_vars + self._built = False + self._v_from_constructor = v if isinstance(v, dict) or v is None else dict(v) + self._v = v if v is not None else dict() + self._buffers = dict(buffers or {}) + self._module_dict = dict() + self._args = args + self._kwargs = kwargs + self._module_graph = None + self._target = None + self._lazy_traced = False + self._training = training + self._dynamic_backend = dynamic_backend + self._device = device or "cpu" + self._dtype = dtype or tf.float32 + if build_mode != "on_init": + return + self.build(*args, dynamic_backend=dynamic_backend, **kwargs) + + @tf.autograph.experimental.do_not_convert + def _find_variables( + self, + /, + *, + obj=None, + without_initialisation=False, + _visited=None, + ): + _visited = _visited or {} + vs = dict() + if id(obj) in _visited: + return vs + _visited[id(obj)] = True + if isinstance(obj, Model) and obj is not self: + if not obj._built and without_initialisation: + return lambda: obj._build_and_return_v( + *obj._args, dynamic_backend=self._dynamic_backend, **obj._kwargs + ) + + return obj._build_and_return_v( + *obj._args, dynamic_backend=obj._dynamic_backend, **obj._kwargs + ) + elif isinstance(obj, (list, tuple)): + for i, v in enumerate(obj): + ret = self._find_variables( + obj=v, + without_initialisation=without_initialisation, + _visited=_visited, + ) + if ret: + vs[f"v{str(i)}"] = ret + return vs + elif isinstance(obj, dict): + for k, v in obj.items(): + ret = self._find_variables( + obj=v, + without_initialisation=without_initialisation, + _visited=_visited, + ) + if ret: + vs[k[1:] if k[0] == "_" else k] = ret + return vs + elif not hasattr(obj, "__dict__"): + return vs + for k, v in obj.__dict__.items(): + if ( + v is not None + and k[0:2] != "__" + and not k.startswith( + ( + "_module_dict", + "_self_", + ) + ) + ): + ret = self._find_variables( + obj=v, + without_initialisation=without_initialisation, + _visited=_visited, + ) + if ret: + vs[k[1:] if k[0] == "_" else k] = ret + return vs + + @tf.autograph.experimental.do_not_convert + def _find_buffers(self): + if hasattr(self, "_module_dict"): + for key, sub_module in self._module_dict.items(): + if len(sub_module._buffers) > 0: + self._buffers[key] = sub_module._buffers + + @tf.autograph.experimental.do_not_convert + def _build_and_return_v(self, *args, **kwargs): + if not self._built: + self.build(*args, **kwargs) + return self.v + + @tf.autograph.experimental.do_not_convert + def _assign_weights(self): + model_weights = {} + existing_ids = [id(w) for w in self.weights] + + # trainable weights + flattened_v, v_spec = tree_flatten(self.v) + flattened_kc = v_spec.get_keychains() + new_weights = [None] * len(flattened_v) + for i, (kc, x) in enumerate(zip(flattened_kc, flattened_v)): + new_weights[i] = ( + self.add_weight(name=kc, shape=x.shape, dtype=x.dtype, trainable=True) + if x is not None and id(x) not in existing_ids + else x + ) + if isinstance(x, tf.Variable): + new_weights[i].assign(x.value()) + if new_weights[i] is not None: + model_weights[id(new_weights[i])] = new_weights[i].numpy() + self.v = tree_unflatten(new_weights, v_spec) + + # non-trainable weights + flattened_buf, buf_spec = tree_flatten(self.buffers) + flattened_kc = buf_spec.get_keychains() + new_buf = [None] * len(flattened_buf) + for i, (kc, x) in enumerate(zip(flattened_kc, flattened_buf)): + new_buf[i] = ( + self.add_weight(name=kc, shape=x.shape, dtype=x.dtype, trainable=False) + if x is not None and id(x) not in existing_ids + else x + ) + if isinstance(x, tf.Variable): + new_buf[i].assign(x.value()) + if new_buf[i] is not None: + model_weights[id(new_buf[i])] = new_buf[i].numpy() + self.buffers = tree_unflatten(new_buf, buf_spec) + + def _sort_weights(model_weights, weights): + sorted_weights = [] + for weight in weights: + sorted_weights.append(model_weights[id(weight)]) + return sorted_weights + + if model_weights: + self.set_weights(_sort_weights(model_weights, self.weights)) + + @tf.autograph.experimental.do_not_convert + def build( + self, + *args, + from_call=False, + device=None, + dtype=None, + dynamic_backend=None, + **kwargs, + ): + self._device = device or self._device + self._dtype = dtype or self._dtype + self._dynamic_backend = dynamic_backend or self._dynamic_backend + # return False if not from_call but build_mode is on_call + if not from_call and self._build_mode == "on_call": + return self.v + + # build local Module, and any child modules flagged with "explicit" build mode + # this gets the child modules initialised at best, their weights + # remain un-generated + built = self._build(*args, **kwargs) or True + + # this creates weights for this Module only + created = self._create_variables(device=self._device, dtype=dtype) + created = ( + created.cont_to_dict() if hasattr(created, "cont_to_dict") else created + ) + + # build variables based on locally built layers, if v not passed in constructor + created_n_found = dict( + **self._find_variables( + obj=self, + without_initialisation=( + True + if self._v_from_constructor and not self._with_partial_v + else False + ), + ), + **created, + ) + if self._v_from_constructor: + # TODO: Add logic here for when `v` is passed in the constructor + raise Exception("TODO: Implement this logic") + else: + self._v = created_n_found + # remove duplicates + self._v, keychain_mappings = self._remove_duplicate_variables(self._v, created) + # build any child 'on_call' layers + if not built and from_call: + # TODO: Add logic for here + raise Exception("TODO: Implement this logic") + + # flag built and remove local variables if specified + self._built = bool(built) + v_ret = self.v + if not self._store_vars: + # ToDo: verify variables in self.v are released once this method exits + self._v = dict() + + # compute the module dict + self._compute_module_dict() + + # once all variables built, find and assign buffers + self._find_buffers() + + # also assign the keras model trainable and non-trainable weights now + self._assign_weights() + + # wrap call methods if the model is fully built + if built: + self._wrap_call_methods(keychain_mappings, obj=self) + + return v_ret if bool(v_ret) or isinstance(built, bool) else built + + @tf.autograph.experimental.do_not_convert + def _wrap_call_methods( + self, keychain_mappings, /, *, key="", obj=None, _visited=None + ): + _visited = _visited or {} + if id(obj) in _visited or not isinstance(key, str): + return + _visited[id(obj)] = True + if isinstance(obj, Model) and obj is not self: + orig_key_chain = key[1:] if key[0] == "_" else key + + obj.__call__ = self._fn_with_var_arg( + obj.__call__, self._extract_v, keychain_mappings, orig_key_chain + ) + return + elif isinstance(obj, (list, tuple)): + for i, val in enumerate(obj): + self._wrap_call_methods( + keychain_mappings, + key=f"{key}/v{str(i)}", + obj=val, + _visited=_visited, + ) + return + elif isinstance(obj, dict): + for k, val in obj.items(): + k = f"{key}/{k}" if key != "" and isinstance(k, str) else k + self._wrap_call_methods( + keychain_mappings, key=k, obj=val, _visited=_visited + ) + return + for k, val in obj.module_dict.items(): + if k.startswith(("__", "_self_")): + continue + k = f"{key}/{k}" if key != "" else k + if val is not None: + self._wrap_call_methods( + keychain_mappings, key=k, obj=val, _visited=_visited + ) + return + + @tf.autograph.experimental.do_not_convert + def _call(self, *args, v=None, buffers=None, **kwargs): + if not self._built or not self.built: + if not self._built: + first_arr = self._get_first_array(*args, **kwargs) + self.build( + *args, + **kwargs, + from_call=True, + dtype=first_arr.dtype if first_arr is not None else tf.float32, + ) + + if not self.built: + # Don't use `keras` build method + if os.environ.get("USE_KERAS_BUILD", "False").lower() == "false": + self.inputs = tf.nest.flatten(args) + + input_shapes = self._get_input_shapes(*args) + if len(input_shapes) == 0: + input_shapes = tf.TensorShape(None) + elif len(input_shapes) == 1: + input_shapes = input_shapes[0] + + super(Model, self).build(input_shapes) # noqa: UP008 + + # If `v` was provided, replace with the module's v + replace_v = False + if v is not None: + v_orig = self.v + self._v = v + replace_v = True + + # If `buffers` were provided, replace with the module's buffers + replace_buffers = False + if buffers is not None: + buffers_orig = self.buffers + self._buffers = buffers + replace_buffers = True + + if replace_v or replace_buffers: + # Call the forward pass + ret = super(Model, self).__call__(*args, **kwargs) # noqa: UP008 + # Replace v, buffers if needed + self._v = v_orig if replace_v else self._v + self._buffers = buffers_orig if replace_buffers else self._buffers + return ret + elif hasattr(self.__call__, "wrapped"): + return self.__call__(*args, **kwargs) + return super(Model, self).__call__(*args, **kwargs) # noqa: UP008 + + @tf.autograph.experimental.do_not_convert + def _rebuild(self): + logging.warning( + "Building the module again as a trainable module was modified, " + 'please use the "explicit" or "on_call" build_modes instead ' + 'of "on_init" to avoid repetitive building after each addition' + ) + self._v = dict() + self._built = False + self.build(*self._args, **self._kwargs) + + @tf.autograph.experimental.do_not_convert + def _compute_module_dict(self): + self._module_dict = dict() + for key, value in self.__dict__.items(): + if isinstance(value, Model): + if "stateful" in value.__module__ or hasattr(value, "_frontend_module"): + self._module_dict[key] = value + else: + self._module_dict[key] = value._module_dict + + @tf.autograph.experimental.do_not_convert + def _fn_with_var_arg_wrapper( + self, *a, fn, v_fn, keychain_mappings, orig_key_chain, **kw + ): + if "v" in kw: + del kw["v"] + v = v_fn(self.v, keychain_mappings, orig_key_chain) + return fn(*a, **kw, v=v) + + @tf.autograph.experimental.do_not_convert + def _fn_with_var_arg(self, fn, v_fn, /, keychain_mappings, orig_key_chain): + _fn_with_var_arg_wrapper = functools.partial( + self._fn_with_var_arg_wrapper, + fn=fn, + v_fn=v_fn, + keychain_mappings=keychain_mappings, + orig_key_chain=orig_key_chain, + ) + _fn_with_var_arg_wrapper.wrapped = True + return _fn_with_var_arg_wrapper + + @tf.autograph.experimental.do_not_convert + def register_buffer(self, name: str, value: Union[tf.Tensor, tf.Variable]): + if value is not None: + self._buffers.update({name: value}) + else: + self.__setattr__(name, value) + + @tf.autograph.experimental.do_not_convert + def register_parameter(self, name: str, value: Union[tf.Tensor, tf.Variable]): + self._v.update({name: value}) + + @tf.autograph.experimental.do_not_convert + def train(self, mode: bool = True): + self._training = mode + for module in self.children(): + module.train(mode) + self.trainable = mode + return self + + @tf.autograph.experimental.do_not_convert + def eval(self): + return self.train(mode=False) + + @tf.autograph.experimental.do_not_convert + def call(self, inputs, training=None, mask=None): + raise NotImplementedError( + "When subclassing the `Model` class, you should implement a `call` method." + ) + + # Methods to be Optionally Overridden # + # -----------------------------------# + + @tf.autograph.experimental.do_not_convert + def _create_variables(self, *, device=None, dtype=None): + return {} + + @tf.autograph.experimental.do_not_convert + def _build(self, *args, **kwargs) -> bool: + return True + + @tf.autograph.experimental.do_not_convert + def _forward(self, *args, **kwargs): + raise NotImplementedError( + "When subclassing the `Model` class, you should " + "implement a `_forward` method." + ) + + @tf.autograph.experimental.do_not_convert + def _extra_repr(self) -> str: + return "" + + # Properties # + # -----------# + + @property + def device(self): + return self._device + + @property + def dtype(self): + return self._dtype + + @property + def build_mode(self): + return self._build_mode + + @property + def training(self): + return self._training + + @property + def v(self): + return self._v + + @property + def buffers(self): + return self._buffers + + @property + def state_dict(self): + return {**self.v, **self.buffers} + + @property + def module_dict(self): + return self._module_dict + + # Dunder Methods # + # ---------------# + + @tf.autograph.experimental.do_not_convert + def __call__( + self, + *args, + v=None, + buffers=None, + **kwargs, + ): + # TODO: Temp workaround to avoid `call`` from being transformed by AutoGraph + if not hasattr(self.__class__.call, "autograph_info__"): + setattr(self.__class__.call, "autograph_info__", True) + ret = self._call(*args, v=v, buffers=buffers, **kwargs) + return ret + + @tf.autograph.experimental.do_not_convert + def __getattr__(self, name): + if name == "v": + if not super().__getattribute__("_v") and not getattr( # noqa: E501 + self, "_built", False + ): + return self._build_and_return_v( + *self._args, dynamic_backend=self._dynamic_backend, **self._kwargs + ) + + _dict = super().__getattribute__("__dict__") + if name in _dict: + return _dict[name] + + elif "_v" in _dict and name in _dict["_v"]: + return _dict["_v"][name] + + return super().__getattribute__(name) + + @tf.autograph.experimental.do_not_convert + def __setattr__(self, name, value): + if name in ["v", "buffers"]: + name = "_" + name + if isinstance(value, Model): + ret = super().__setattr__(name, value) + if ( + hasattr(self, "_build_mode") + and self.build_mode == "on_init" + and getattr(self, "_built", False) + ): + self._rebuild() + return ret + elif isinstance(value, tf.Variable) and not name.startswith("_"): + ret = self.register_parameter(name, value) + if ( + hasattr(self, "_build_mode") + and self.build_mode == "on_init" + and getattr(self, "_built", False) + ): + self._rebuild() + return ret + return super().__setattr__(name, value) + + @tf.autograph.experimental.do_not_convert + def __delattr__(self, name): + if hasattr(self, name): + if isinstance(getattr(self, name), Model): + super().__delattr__(name) + if self.build_mode == "on_init": + self._rebuild() + return + super().__delattr__(name) + + @tf.autograph.experimental.do_not_convert + def __repr__(self): + extra_lines = [] + extra_repr = self._extra_repr() + if extra_repr: + extra_lines = extra_repr.split("\n") + child_lines = [] + for key in self.v.keys(): + if isinstance(getattr(self, key, None), Model): + mod_str = repr(getattr(self, key)) + mod_str = self._addindent(mod_str, 2) + child_lines.append(f"({key}): {mod_str}") + lines = extra_lines + child_lines + + main_str = f"{self.__class__.__name__}(" + if lines: + # simple one-liner info, which most builtin Modules will use + if len(extra_lines) == 1 and not child_lines: + main_str += extra_lines[0] + else: + main_str += "\n " + "\n ".join(lines) + "\n" + + main_str += ")" + return main_str diff --git a/ivy/functional/backends/tensorflow/random.py b/ivy/functional/backends/tensorflow/random.py index 6508a5ac2603b..65828a02669d9 100644 --- a/ivy/functional/backends/tensorflow/random.py +++ b/ivy/functional/backends/tensorflow/random.py @@ -1,5 +1,4 @@ -""" -TensorFlow random functions. +"""TensorFlow random functions. Collection of TensorFlow random functions, wrapped to fit Ivy syntax and signature. @@ -27,7 +26,7 @@ @with_supported_dtypes( - {"2.14.0 and below": ("float", "int32", "int64")}, backend_version + {"2.15.0 and below": ("float", "int32", "int64")}, backend_version ) def random_uniform( *, @@ -35,7 +34,7 @@ def random_uniform( high: Union[float, tf.Tensor, tf.Variable] = 1.0, shape: Optional[Union[ivy.NativeShape, Sequence[int], tf.Tensor]] = None, dtype: DType, - device: str = None, + device: Optional[str] = None, seed: Optional[int] = None, out: Optional[Union[tf.Tensor, tf.Variable]] = None, ) -> Union[tf.Tensor, tf.Variable]: @@ -54,7 +53,7 @@ def random_normal( shape: Optional[Union[ivy.NativeShape, Sequence[int]]] = None, dtype: DType, seed: Optional[int] = None, - device: str = None, + device: Optional[str] = None, out: Optional[Union[tf.Tensor, tf.Variable]] = None, ) -> Union[tf.Tensor, tf.Variable]: _check_valid_scale(std) @@ -66,7 +65,7 @@ def random_normal( return tf.random.normal(shape, mean, std, dtype=dtype, seed=seed) -@with_unsupported_dtypes({"2.14.0 and below": ("bfloat16",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("bfloat16",)}, backend_version) def multinomial( population_size: int, num_samples: int, @@ -75,7 +74,7 @@ def multinomial( batch_size: int = 1, probs: Optional[Union[tf.Tensor, tf.Variable]] = None, replace: bool = True, - device: str = None, + device: Optional[str] = None, seed: Optional[int] = None, out: Optional[Union[tf.Tensor, tf.Variable]] = None, ) -> Union[tf.Tensor, tf.Variable]: @@ -128,7 +127,7 @@ def randint( /, *, shape: Optional[Union[ivy.NativeShape, Sequence[int]]] = None, - device: str = None, + device: Optional[str] = None, dtype: Optional[Union[DType, ivy.Dtype]] = None, seed: Optional[int] = None, out: Optional[Union[tf.Tensor, tf.Variable]] = None, @@ -145,7 +144,7 @@ def randint( return tf.cast(tf.random.uniform(shape, low, high, "float32", seed=seed), dtype) -def seed(*, seed_value: int = 0) -> None: +def seed(*, seed_value: int = 0): tf.random.set_seed(seed_value) return diff --git a/ivy/functional/backends/tensorflow/searching.py b/ivy/functional/backends/tensorflow/searching.py index b9abffbee4076..0b1abe892c9e3 100644 --- a/ivy/functional/backends/tensorflow/searching.py +++ b/ivy/functional/backends/tensorflow/searching.py @@ -12,7 +12,7 @@ # ------------------ # -@with_unsupported_dtypes({"2.14.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("complex",)}, backend_version) def argmax( x: Union[tf.Tensor, tf.Variable], /, @@ -45,6 +45,7 @@ def argmax( return tf.cast(ret, dtype) if dtype is not None else ret +@with_unsupported_dtypes({"2.15.0 and below": ("complex",)}, backend_version) def argmin( x: Union[tf.Tensor, tf.Variable], /, diff --git a/ivy/functional/backends/tensorflow/set.py b/ivy/functional/backends/tensorflow/set.py index abb0c8d90e8f6..cc766363a3b0b 100644 --- a/ivy/functional/backends/tensorflow/set.py +++ b/ivy/functional/backends/tensorflow/set.py @@ -6,7 +6,7 @@ from . import backend_version -@with_unsupported_dtypes({"2.14.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("complex",)}, backend_version) def unique_all( x: Union[tf.Tensor, tf.Variable], /, @@ -59,7 +59,7 @@ def unique_all( values_ = tf.experimental.numpy.moveaxis(values, axis, 0) values_ = tf.reshape(values_, (values_.shape[0], -1)) sort_idx = tf.stack( - [i[0] for i in sorted(list(enumerate(values_)), key=lambda x: tuple(x[1]))] + [i[0] for i in sorted(enumerate(values_), key=lambda x: tuple(x[1]))] ) sort_idx = tf.cast(sort_idx, tf.int32) values = tf.gather(values, sort_idx, axis=axis) @@ -78,7 +78,7 @@ def unique_all( ) -@with_unsupported_dtypes({"2.14.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("complex",)}, backend_version) def unique_counts( x: Union[tf.Tensor, tf.Variable], /, @@ -90,7 +90,7 @@ def unique_counts( return Results(v, c) -@with_unsupported_dtypes({"2.14.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("complex",)}, backend_version) def unique_inverse( x: Union[tf.Tensor, tf.Variable], /, @@ -113,7 +113,7 @@ def unique_inverse( return Results(values, inverse_indices) -@with_unsupported_dtypes({"2.14.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("complex",)}, backend_version) def unique_values( x: Union[tf.Tensor, tf.Variable], /, diff --git a/ivy/functional/backends/tensorflow/sorting.py b/ivy/functional/backends/tensorflow/sorting.py index efaf951cdc61c..2d24b032d2643 100644 --- a/ivy/functional/backends/tensorflow/sorting.py +++ b/ivy/functional/backends/tensorflow/sorting.py @@ -8,7 +8,7 @@ from . import backend_version -@with_unsupported_dtypes({"2.14.0 and below": ("complex", "bool")}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("complex", "bool")}, backend_version) def argsort( x: Union[tf.Tensor, tf.Variable], /, @@ -24,7 +24,7 @@ def argsort( return tf.cast(ret, dtype=tf.int64) -@with_unsupported_dtypes({"2.14.0 and below": ("complex", "bool")}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("complex", "bool")}, backend_version) def sort( x: Union[tf.Tensor, tf.Variable], /, @@ -43,7 +43,7 @@ def sort( # msort -@with_unsupported_dtypes({"2.14.0 and below": ("complex", "bool")}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("complex", "bool")}, backend_version) def msort( a: Union[tf.Tensor, tf.Variable, list, tuple], /, @@ -53,7 +53,7 @@ def msort( return tf.sort(a, axis=0) -@with_unsupported_dtypes({"2.14.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("complex",)}, backend_version) def searchsorted( x: Union[tf.Tensor, tf.Variable], v: Union[tf.Tensor, tf.Variable], @@ -64,14 +64,12 @@ def searchsorted( ret_dtype: tf.DType = tf.int64, out: Optional[Union[tf.Tensor, tf.Variable]] = None, ) -> Union[tf.Tensor, tf.Variable]: - assert ivy.is_int_dtype(ret_dtype), ValueError( + assert ivy.is_int_dtype(ret_dtype), TypeError( "only Integer data types are supported for ret_dtype." ) is_supported_int_ret_dtype = ret_dtype in [tf.int32, tf.int64] if sorter is not None: - assert ivy.is_int_dtype(sorter.dtype) and not ivy.is_uint_dtype( - sorter.dtype - ), TypeError( + assert ivy.is_int_dtype(sorter.dtype), TypeError( f"Only signed integer data type for sorter is allowed, got {sorter.dtype}." ) if sorter.dtype not in [tf.int32, tf.int64]: diff --git a/ivy/functional/backends/tensorflow/statistical.py b/ivy/functional/backends/tensorflow/statistical.py index 4d997c9f85ce3..95db57526ef9b 100644 --- a/ivy/functional/backends/tensorflow/statistical.py +++ b/ivy/functional/backends/tensorflow/statistical.py @@ -4,7 +4,6 @@ # local import ivy -from ivy.functional.ivy.statistical import _get_promoted_type_of_operands from ivy.func_wrapper import with_unsupported_dtypes from . import backend_version from ivy.utils.einsum_parser import legalise_einsum_expr @@ -13,19 +12,34 @@ # -------------------# -@with_unsupported_dtypes({"2.14.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes( + {"2.15.0 and below": ("complex", "bool", "uint64")}, backend_version +) def min( x: Union[tf.Tensor, tf.Variable], /, *, axis: Optional[Union[int, Sequence[int]]] = None, keepdims: bool = False, + initial: Optional[Union[int, float, complex]] = None, + where: Optional[Union[tf.Tensor, tf.Variable]] = None, out: Optional[Union[tf.Tensor, tf.Variable]] = None, ) -> Union[tf.Tensor, tf.Variable]: axis = tuple(axis) if isinstance(axis, list) else axis - return tf.math.reduce_min(x, axis=axis, keepdims=keepdims) + if where is not None: + max_val = ( + ivy.iinfo(x.dtype).max + if ivy.is_int_dtype(x.dtype) + else ivy.finfo(x.dtype).max + ) + x = tf.where(where, x, tf.ones_like(x) * max_val) + result = tf.math.reduce_min(x, axis=axis, keepdims=keepdims) + if initial is not None: + result = tf.minimum(result, initial) + return result +@with_unsupported_dtypes({"2.15.0 and below": ("bool",)}, backend_version) def max( x: Union[tf.Tensor, tf.Variable], /, @@ -52,7 +66,7 @@ def max( return tf.math.reduce_max(x, axis=axis, keepdims=keepdims) -@with_unsupported_dtypes({"2.14.0 and below": ("bool",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("bool",)}, backend_version) def mean( x: Union[tf.Tensor, tf.Variable], /, @@ -164,7 +178,7 @@ def var( # ------# -@with_unsupported_dtypes({"2.14.0 and below": "bfloat16"}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("bfloat16", "bool")}, backend_version) def cumprod( x: Union[tf.Tensor, tf.Variable], /, @@ -186,6 +200,7 @@ def cumprod( return tf.math.cumprod(x, axis, exclusive, reverse) +@with_unsupported_dtypes({"2.15.0 and below": "bool"}, backend_version) def cumsum( x: Union[tf.Tensor, tf.Variable], axis: int = 0, @@ -209,7 +224,7 @@ def cumsum( @with_unsupported_dtypes( - {"2.14.0 and below": ("unsigned", "int8", "int16")}, + {"2.15.0 and below": ("unsigned", "int8", "int16")}, backend_version, ) def einsum( @@ -217,6 +232,15 @@ def einsum( *operands: Union[tf.Tensor, tf.Variable], out: Optional[Union[tf.Tensor, tf.Variable]] = None, ) -> Union[tf.Tensor, tf.Variable]: - dtype = _get_promoted_type_of_operands(operands) equation = legalise_einsum_expr(*[equation, *operands]) - return tf.cast(tf.einsum(equation, *operands), dtype) + dtype_list = set(map(lambda x: x.dtype, operands)) + dtype = dtype_list.pop() + if len(dtype_list) > 0: + for d in dtype_list: + dtype = ivy.promote_types(dtype, d) + dtype = ivy.as_native_dtype(dtype) + operands = list( + map(lambda x: tf.cast(x, dtype) if x.dtype != dtype else x, operands) + ) + + return tf.einsum(equation, *operands) diff --git a/ivy/functional/backends/tensorflow/sub_backends/tf_probability/experimental/random.py b/ivy/functional/backends/tensorflow/sub_backends/tf_probability/experimental/random.py index a13fb5768917d..b33cd8304df18 100644 --- a/ivy/functional/backends/tensorflow/sub_backends/tf_probability/experimental/random.py +++ b/ivy/functional/backends/tensorflow/sub_backends/tf_probability/experimental/random.py @@ -20,7 +20,7 @@ def beta( *, shape: Optional[Union[ivy.NativeShape, Sequence[int]]] = None, device: Optional[str] = None, - dtype: Optional[Union[ivy.Dtype, ivy.Dtype]] = None, + dtype: Optional[Union[ivy.Dtype]] = None, seed: Optional[int] = None, out: Optional[Union[tf.Tensor, tf.Variable]] = None, ) -> Union[tf.Tensor, tf.Variable]: @@ -58,11 +58,12 @@ def bernoulli( *, logits: Union[float, tf.Tensor, tf.Variable] = None, shape: Optional[Union[ivy.NativeShape, Sequence[int]]] = None, - device: str = None, + device: Optional[str] = None, dtype: DType, seed: Optional[int] = None, out: Optional[Union[tf.Tensor, tf.Variable]] = None, ) -> Union[tf.Tensor, tf.Variable]: + dtype = dtype if dtype is not None else probs.dtype if seed is not None: tf.random.set_seed(seed) if logits is not None: @@ -81,7 +82,7 @@ def bernoulli( # dirichlet @with_unsupported_dtypes( { - "2.14.0 and below": ( + "2.15.0 and below": ( "blfoat16", "float16", ) diff --git a/ivy/functional/backends/tensorflow/sub_backends/tf_probability/experimental/statistical.py b/ivy/functional/backends/tensorflow/sub_backends/tf_probability/experimental/statistical.py index 4b73e332dc85b..edfe28faa07db 100644 --- a/ivy/functional/backends/tensorflow/sub_backends/tf_probability/experimental/statistical.py +++ b/ivy/functional/backends/tensorflow/sub_backends/tf_probability/experimental/statistical.py @@ -75,7 +75,7 @@ def histogram( @with_supported_dtypes( { - "2.14.0 and below": ( + "2.15.0 and below": ( "float", "complex", ) @@ -118,9 +118,8 @@ def nanmedian( def _nanmedian_helper(input, axis=None, keepdims=False): - """ - The approach to Handle Nans in single dimensional plus multi-dimensional inputs are - composed on two-parts. + """The approach to Handle Nans in single dimensional plus multi-dimensional + inputs are composed on two-parts. PART 1: In this part, you have axis=None, it means we have to work on flattened data, we don't need to work on different axis.there are two cases here diff --git a/ivy/functional/backends/tensorflow/utility.py b/ivy/functional/backends/tensorflow/utility.py index 997b6dca682dc..e267a1533c458 100644 --- a/ivy/functional/backends/tensorflow/utility.py +++ b/ivy/functional/backends/tensorflow/utility.py @@ -15,7 +15,6 @@ def all( keepdims: bool = False, out: Optional[Union[tf.Tensor, tf.Variable]] = None, ) -> Union[tf.Tensor, tf.Variable]: - x = tf.constant(x) if axis is None: num_dims = len(x.shape) axis = tuple(range(num_dims)) @@ -24,7 +23,7 @@ def all( try: return tf.reduce_all(tf.cast(x, tf.bool), axis=axis, keepdims=keepdims) except tf.errors.InvalidArgumentError as e: - raise ivy.utils.exceptions.IvyIndexError(e) + raise ivy.utils.exceptions.IvyIndexError(e) from e def any( @@ -35,7 +34,6 @@ def any( keepdims: bool = False, out: Optional[Union[tf.Tensor, tf.Variable]] = None, ) -> Union[tf.Tensor, tf.Variable]: - x = tf.constant(x) if axis is None: num_dims = len(x.shape) axis = tuple(range(num_dims)) @@ -44,4 +42,4 @@ def any( try: return tf.reduce_any(tf.cast(x, tf.bool), axis=axis, keepdims=keepdims) except tf.errors.InvalidArgumentError as e: - raise ivy.utils.exceptions.IvyIndexError(e) + raise ivy.utils.exceptions.IvyIndexError(e) from e diff --git a/ivy/functional/backends/torch/__init__.py b/ivy/functional/backends/torch/__init__.py index 986b1eace46f7..6068c355b1155 100644 --- a/ivy/functional/backends/torch/__init__.py +++ b/ivy/functional/backends/torch/__init__.py @@ -20,81 +20,6 @@ use = ivy.utils.backend.ContextManager(_module_in_memory) - -# wrap dunder methods of native tensors to return NotImplemented to prioritize Ivy array methods. -def dunder_wrapper(func): - def rep_method(*args, **kwargs): - for arg in args: - if ivy.is_ivy_array(arg): - return NotImplemented - return func(*args, **kwargs) - - return rep_method - - -# check for previously imported torch module -modules_to_patch = [] -tensors_to_patch = [] -tmp_globals = dict(globals()) -for name, value in tmp_globals.items(): - if value == "torch.Tensor": - tensors_to_patch.append(name) - try: - if value.__name__ == "torch": - modules_to_patch.append(name) - except AttributeError: - pass - -methods_to_patch = [ - "__add__", - "__and__", - "__div__", - "__eq__", - "__floordiv__", - "__ge__", - "__gt__", - "__iadd__", - "__iand__", - "__idiv__", - "__ifloordiv__", - "__ilshift__", - "__imul__", - "__ior__", - "__ipow__", - "__irshift__", - "__isub__", - "__itruediv__", - "__ixor__", - "__le__", - "__lshift__", - "__lt__", - "__matmul__", - "__mul__", - "__or__", - "__pow__", - "__truediv__", - "__xor__", - "__ne__", - "__mod__", -] - -for module in modules_to_patch: - for method in methods_to_patch: - exec( - module - + ".Tensor." - + method - + " = dunder_wrapper(" - + module - + ".Tensor." - + method - + ")" - ) - -for tensor in tensors_to_patch: - for method in methods_to_patch: - exec(tensor + "." + method + " = dunder_wrapper(" + tensor + "." + method + ")") - NativeArray = torch.Tensor NativeDevice = torch.device NativeDtype = torch.dtype @@ -129,7 +54,7 @@ def rep_method(*args, **kwargs): # update these to add new dtypes valid_dtypes = { - "2.1.0 and below": ( + "2.2 and below": ( ivy.int8, ivy.int16, ivy.int32, @@ -147,7 +72,7 @@ def rep_method(*args, **kwargs): valid_numeric_dtypes = { - "2.1.0 and below": ( + "2.2 and below": ( ivy.int8, ivy.int16, ivy.int32, @@ -163,13 +88,13 @@ def rep_method(*args, **kwargs): } valid_int_dtypes = { - "2.1.0 and below": (ivy.int8, ivy.int16, ivy.int32, ivy.int64, ivy.uint8) + "2.2 and below": (ivy.int8, ivy.int16, ivy.int32, ivy.int64, ivy.uint8) } valid_float_dtypes = { - "2.1.0 and below": (ivy.bfloat16, ivy.float16, ivy.float32, ivy.float64) + "2.2 and below": (ivy.bfloat16, ivy.float16, ivy.float32, ivy.float64) } -valid_uint_dtypes = {"2.1.0 and below": (ivy.uint8,)} -valid_complex_dtypes = {"2.1.0 and below": (ivy.complex64, ivy.complex128)} +valid_uint_dtypes = {"2.2 and below": (ivy.uint8,)} +valid_complex_dtypes = {"2.2 and below": (ivy.complex64, ivy.complex128)} # leave these untouched valid_dtypes = _dtype_from_version(valid_dtypes, backend_version) @@ -182,17 +107,17 @@ def rep_method(*args, **kwargs): # invalid data types # update these to add new dtypes invalid_dtypes = { - "2.1.0 and below": ( + "2.2 and below": ( ivy.uint16, ivy.uint32, ivy.uint64, ) } -invalid_numeric_dtypes = {"2.1.0 and below": (ivy.uint16, ivy.uint32, ivy.uint64)} -invalid_int_dtypes = {"2.1.0 and below": (ivy.uint16, ivy.uint32, ivy.uint64)} -invalid_float_dtypes = {"2.1.0 and below": ()} -invalid_uint_dtypes = {"2.1.0 and below": (ivy.uint16, ivy.uint32, ivy.uint64)} -invalid_complex_dtypes = {"2.1.0 and below": ()} +invalid_numeric_dtypes = {"2.2 and below": (ivy.uint16, ivy.uint32, ivy.uint64)} +invalid_int_dtypes = {"2.2 and below": (ivy.uint16, ivy.uint32, ivy.uint64)} +invalid_float_dtypes = {"2.2 and below": ()} +invalid_uint_dtypes = {"2.2 and below": (ivy.uint16, ivy.uint32, ivy.uint64)} +invalid_complex_dtypes = {"2.2 and below": ()} invalid_dtypes = _dtype_from_version(invalid_dtypes, backend_version) # leave these untouched @@ -270,8 +195,13 @@ def globals_getter_func(x=None): from .control_flow_ops import * from . import norms from .norms import * +from . import module +from .module import * # sub-backends from . import sub_backends from .sub_backends import * + + +NativeModule = torch.nn.Module diff --git a/ivy/functional/backends/torch/activations.py b/ivy/functional/backends/torch/activations.py index dc3fe5e33a5b4..2529147c6f976 100644 --- a/ivy/functional/backends/torch/activations.py +++ b/ivy/functional/backends/torch/activations.py @@ -1,5 +1,4 @@ -""" -PyTorch activation functions. +"""PyTorch activation functions. Collection of PyTorch activation functions, wrapped to fit Ivy syntax and signature. @@ -19,14 +18,22 @@ import ivy.functional.backends.torch as torch_backend -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes( + { + "2.1.2 and below": ( + "float16", + "bool", + ) + }, + backend_version, +) def relu( x: torch.Tensor, /, *, complex_mode="jax", out: Optional[torch.Tensor] = None ) -> torch.Tensor: return torch.relu(x) -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, backend_version) def leaky_relu( x: torch.Tensor, /, @@ -38,7 +45,7 @@ def leaky_relu( return torch.nn.functional.leaky_relu(x, alpha) -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, backend_version) def gelu( x: torch.Tensor, /, @@ -52,7 +59,7 @@ def gelu( return torch.nn.functional.gelu(x) -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, backend_version) def sigmoid( x: torch.Tensor, /, *, complex_mode="jax", out: Optional[torch.Tensor] = None ) -> torch.Tensor: @@ -64,7 +71,7 @@ def sigmoid( sigmoid.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("bfloat16", "float16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("bfloat16", "float16")}, backend_version) def softmax( x: torch.Tensor, /, @@ -81,7 +88,7 @@ def softmax( return torch.nn.functional.softmax(x, axis) -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, backend_version) def softplus( x: torch.Tensor, /, @@ -98,7 +105,7 @@ def softplus( # Softsign -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, backend_version) def softsign(x: torch.Tensor, /, out: Optional[torch.Tensor] = None) -> torch.Tensor: # return x / (1 + torch.abs(x)) return torch.nn.functional.softsign(x) @@ -108,7 +115,7 @@ def softsign(x: torch.Tensor, /, out: Optional[torch.Tensor] = None) -> torch.Te @with_unsupported_dtypes( - {"2.1.0 and below": ("float16",)}, + {"2.2 and below": ("float16",)}, backend_version, ) def log_softmax( @@ -129,7 +136,7 @@ def log_softmax( @with_unsupported_dtypes( - {"2.1.0 and below": ("float16",)}, + {"2.2 and below": ("float16",)}, backend_version, ) def mish( @@ -147,7 +154,7 @@ def mish( @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "complex", "float16", ) diff --git a/ivy/functional/backends/torch/control_flow_ops.py b/ivy/functional/backends/torch/control_flow_ops.py index d3a7f92c58d02..d114e59c2146d 100644 --- a/ivy/functional/backends/torch/control_flow_ops.py +++ b/ivy/functional/backends/torch/control_flow_ops.py @@ -17,8 +17,11 @@ def cond(*_): def while_loop(test_fn, body_fn, vars): - result = list(vars.values()) - while test_fn(*result): + if isinstance(vars, dict): + result = list(vars.values()) + else: + result = list(vars) + while test_fn(*result) is True: result = body_fn(*result) if not isinstance(result, tuple): result = (result,) diff --git a/ivy/functional/backends/torch/creation.py b/ivy/functional/backends/torch/creation.py index 14b059758a1c8..082aefa280f56 100644 --- a/ivy/functional/backends/torch/creation.py +++ b/ivy/functional/backends/torch/creation.py @@ -47,7 +47,7 @@ def _differentiable_linspace(start, stop, num, *, device, dtype=None): return res -@with_unsupported_dtypes({"2.1.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("complex",)}, backend_version) def arange( start: float, /, @@ -95,7 +95,7 @@ def _stack_tensors(x, dtype): return x -@with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, backend_version) @_asarray_to_native_arrays_and_back @_asarray_infer_device @_asarray_handle_nestable @@ -166,7 +166,7 @@ def empty_like( return torch.empty_like(x, dtype=dtype, device=device) -@with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, backend_version) def eye( n_rows: int, n_cols: Optional[int] = None, @@ -236,6 +236,7 @@ def from_dlpack(x, /, *, out: Optional[torch.Tensor] = None): return torch.from_dlpack(x) +@with_unsupported_dtypes({"2.2.0 and below": ("bfloat16",)}, backend_version) def full( shape: Union[ivy.NativeShape, Sequence[int]], fill_value: Union[int, float, bool], @@ -247,9 +248,13 @@ def full( dtype = ivy.default_dtype(dtype=dtype, item=fill_value, as_native=True) if isinstance(shape, int): shape = (shape,) + + shape = tuple(int(dim) for dim in shape) + fill_value = torch.tensor(fill_value, dtype=dtype) + return torch.full( - shape, - fill_value, + size=shape, + fill_value=fill_value, dtype=dtype, device=device, out=out, @@ -276,7 +281,7 @@ def _slice_at_axis(sl, axis): @with_unsupported_device_and_dtypes( - {"2.1.0 and below": {"cpu": ("float16",)}}, backend_version + {"2.2 and below": {"cpu": ("float16",)}}, backend_version ) def linspace( start: Union[torch.Tensor, float], @@ -477,7 +482,7 @@ def ones_like_v_0p1p12_to_0p2p0( x[i] = 1 return x for i in range(x.shape[0]): - x[i, :] = ones_like_v_0p1p12_to_0p2p0(x[i, :]) + x[i, :] = ones_like_v_0p1p12_to_0p2p0(x[i, :], dtype=dtype) return x @@ -607,15 +612,3 @@ def triu_indices( row=n_rows, col=n_cols, offset=k, dtype=torch.int64, device=device ) ) - - -def pad(tensor, sizes_of_pad, mode="constant", value=0): - if len(sizes_of_pad) == tensor.dim(): - pad_pairs = [] - for size in sizes_of_pad: - if size >= 0: - pad_pairs.append((size // 2, size - size // 2)) - pad_pairs = pad_pairs[::-1] - pad_list = [item for pair in pad_pairs for item in pair] - - return torch.nn.functional.pad(tensor, pad_list, mode, value) diff --git a/ivy/functional/backends/torch/data_type.py b/ivy/functional/backends/torch/data_type.py index 29dba78a4ba20..76db94f8a1ae4 100644 --- a/ivy/functional/backends/torch/data_type.py +++ b/ivy/functional/backends/torch/data_type.py @@ -15,16 +15,10 @@ torch.int32: "int32", torch.int64: "int64", torch.uint8: "uint8", - torch.qint8: "qint8", - torch.qint32: "qint32", - torch.quint8: "quint8", - torch.quint2x4: "quint2x4", - torch.quint4x2: "quint4x2", torch.bfloat16: "bfloat16", torch.float16: "float16", torch.float32: "float32", torch.float64: "float64", - torch.complex32: "complex32", torch.complex64: "complex64", torch.complex128: "complex128", torch.bool: "bool", @@ -78,6 +72,7 @@ def smallest_normal(self): # -------------------# +@with_unsupported_dtypes({"2.2 and below": ("bfloat16", "float16")}, backend_version) def astype( x: torch.Tensor, dtype: torch.dtype, @@ -96,7 +91,7 @@ def broadcast_arrays(*arrays: torch.Tensor) -> List[torch.Tensor]: try: return list(torch.broadcast_tensors(*arrays)) except RuntimeError as e: - raise ivy.utils.exceptions.IvyBroadcastShapeError(e) + raise ivy.utils.exceptions.IvyBroadcastShapeError(e) from e def broadcast_to( @@ -186,9 +181,9 @@ def as_ivy_dtype( ) -@with_unsupported_dtypes({"2.1.0 and below": ("uint16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("uint16",)}, backend_version) def as_native_dtype( - dtype_in: Union[torch.dtype, str, bool, int, float, np.dtype] + dtype_in: Union[torch.dtype, str, bool, int, float, np.dtype], ) -> torch.dtype: if dtype_in is int: return ivy.default_int_dtype(as_native=True) @@ -202,7 +197,7 @@ def as_native_dtype( dtype_in = dtype_in.name if not isinstance(dtype_in, str): return dtype_in - if dtype_in in native_dtype_dict.keys(): + if dtype_in in native_dtype_dict: return native_dtype_dict[ivy.Dtype(dtype_in)] else: raise ivy.utils.exceptions.IvyException( @@ -233,7 +228,4 @@ def dtype_bits(dtype_in: Union[torch.dtype, str, np.dtype], /) -> int: def is_native_dtype(dtype_in: Union[torch.dtype, str], /) -> bool: if not ivy.is_hashable_dtype(dtype_in): return False - if dtype_in in ivy_dtype_dict and isinstance(dtype_in, torch.dtype): - return True - else: - return False + return bool(dtype_in in ivy_dtype_dict and isinstance(dtype_in, torch.dtype)) diff --git a/ivy/functional/backends/torch/device.py b/ivy/functional/backends/torch/device.py index 59d35e007d109..4fdfb8ce1c035 100644 --- a/ivy/functional/backends/torch/device.py +++ b/ivy/functional/backends/torch/device.py @@ -1,4 +1,5 @@ -"""Collection of PyTorch general functions, wrapped to fit Ivy syntax and signature.""" +"""Collection of PyTorch general functions, wrapped to fit Ivy syntax and +signature.""" import inspect diff --git a/ivy/functional/backends/torch/elementwise.py b/ivy/functional/backends/torch/elementwise.py index 9fba80a8d5c8a..b12773813fdea 100644 --- a/ivy/functional/backends/torch/elementwise.py +++ b/ivy/functional/backends/torch/elementwise.py @@ -38,7 +38,7 @@ def add( add.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("complex",)}, backend_version) @handle_numpy_arrays_in_specific_backend def bitwise_xor( x1: Union[int, bool, torch.Tensor], @@ -54,7 +54,7 @@ def bitwise_xor( bitwise_xor.support_native_out = True -@with_supported_dtypes({"2.1.0 and below": ("complex",)}, backend_version) +@with_supported_dtypes({"2.2 and below": ("complex",)}, backend_version) def imag( val: torch.Tensor, /, @@ -67,7 +67,7 @@ def imag( imag.support_native_out = False -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "complex")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "complex")}, backend_version) @handle_numpy_arrays_in_specific_backend def expm1(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch.Tensor: x = _cast_for_unary_op(x) @@ -77,7 +77,7 @@ def expm1(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch.Te expm1.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("complex",)}, backend_version) @handle_numpy_arrays_in_specific_backend def bitwise_invert( x: Union[int, bool, torch.Tensor], /, *, out: Optional[torch.Tensor] = None @@ -95,6 +95,7 @@ def isfinite(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch return torch.isfinite(x) +@with_unsupported_dtypes({"2.2 and below": ("complex",)}, backend_version) @handle_numpy_arrays_in_specific_backend def isinf( x: torch.Tensor, @@ -129,7 +130,7 @@ def equal( equal.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("complex",)}, backend_version) @handle_numpy_arrays_in_specific_backend def less_equal( x1: Union[float, torch.Tensor], @@ -145,7 +146,7 @@ def less_equal( less_equal.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("complex",)}, backend_version) @handle_numpy_arrays_in_specific_backend def bitwise_and( x1: Union[int, bool, torch.Tensor], @@ -161,7 +162,7 @@ def bitwise_and( bitwise_and.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "complex")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "complex")}, backend_version) @handle_numpy_arrays_in_specific_backend def ceil(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch.Tensor: x = _cast_for_unary_op(x) @@ -175,7 +176,7 @@ def ceil(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch.Ten ceil.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "complex")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "complex")}, backend_version) @handle_numpy_arrays_in_specific_backend def floor(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch.Tensor: x = _cast_for_unary_op(x) @@ -189,7 +190,7 @@ def floor(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch.Te floor.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("complex",)}, backend_version) def fmin( x1: torch.Tensor, x2: torch.Tensor, @@ -203,7 +204,7 @@ def fmin( fmin.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("complex",)}, backend_version) @handle_numpy_arrays_in_specific_backend def asin(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch.Tensor: x = _cast_for_unary_op(x) @@ -213,7 +214,7 @@ def asin(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch.Ten asin.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, backend_version) @handle_numpy_arrays_in_specific_backend def asinh(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch.Tensor: x = _cast_for_unary_op(x) @@ -223,7 +224,7 @@ def asinh(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch.Te asinh.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, backend_version) @handle_numpy_arrays_in_specific_backend def sign( x: torch.Tensor, @@ -245,7 +246,7 @@ def sign( sign.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, backend_version) @handle_numpy_arrays_in_specific_backend def sqrt(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch.Tensor: x = _cast_for_unary_op(x) @@ -255,7 +256,7 @@ def sqrt(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch.Ten sqrt.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, backend_version) @handle_numpy_arrays_in_specific_backend def cosh(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch.Tensor: x = _cast_for_unary_op(x) @@ -265,7 +266,7 @@ def cosh(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch.Ten cosh.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, backend_version) @handle_numpy_arrays_in_specific_backend def log10(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch.Tensor: x = _cast_for_unary_op(x) @@ -275,14 +276,14 @@ def log10(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch.Te log10.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, backend_version) @handle_numpy_arrays_in_specific_backend def log2(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch.Tensor: x = _cast_for_unary_op(x) return torch.log2(x, out=out) -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "complex")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "complex")}, backend_version) @handle_numpy_arrays_in_specific_backend def log1p(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch.Tensor: x = _cast_for_unary_op(x) @@ -298,7 +299,7 @@ def isnan(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch.Te return torch.isnan(x) -@with_unsupported_dtypes({"2.1.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("complex",)}, backend_version) @handle_numpy_arrays_in_specific_backend def less( x1: Union[float, torch.Tensor], @@ -329,7 +330,7 @@ def multiply( multiply.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, backend_version) @handle_numpy_arrays_in_specific_backend def cos(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch.Tensor: x = _cast_for_unary_op(x) @@ -370,7 +371,7 @@ def divide( divide.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("complex",)}, backend_version) @handle_numpy_arrays_in_specific_backend def greater( x1: Union[float, torch.Tensor], @@ -386,7 +387,7 @@ def greater( greater.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("complex",)}, backend_version) @handle_numpy_arrays_in_specific_backend def greater_equal( x1: Union[float, torch.Tensor], @@ -402,7 +403,7 @@ def greater_equal( greater_equal.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("complex",)}, backend_version) @handle_numpy_arrays_in_specific_backend def acos(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch.Tensor: x = _cast_for_unary_op(x) @@ -412,7 +413,7 @@ def acos(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch.Ten acos.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("float",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float",)}, backend_version) @handle_numpy_arrays_in_specific_backend def lcm( x1: torch.Tensor, @@ -458,7 +459,7 @@ def logical_or( logical_or.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, backend_version) @handle_numpy_arrays_in_specific_backend def acosh(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch.Tensor: x = _cast_for_unary_op(x) @@ -468,7 +469,7 @@ def acosh(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch.Te acosh.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, backend_version) @handle_numpy_arrays_in_specific_backend def sin(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch.Tensor: x = _cast_for_unary_op(x) @@ -504,7 +505,7 @@ def not_equal( not_equal.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, backend_version) @handle_numpy_arrays_in_specific_backend def tanh( x: torch.Tensor, /, *, complex_mode="jax", out: Optional[torch.Tensor] = None @@ -516,7 +517,7 @@ def tanh( tanh.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "complex")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "complex")}, backend_version) @handle_numpy_arrays_in_specific_backend def floor_divide( x1: Union[float, torch.Tensor], @@ -537,7 +538,7 @@ def floor_divide( floor_divide.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("complex",)}, backend_version) @handle_numpy_arrays_in_specific_backend def bitwise_or( x1: Union[int, bool, torch.Tensor], @@ -553,7 +554,7 @@ def bitwise_or( bitwise_or.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, backend_version) @handle_numpy_arrays_in_specific_backend def sinh(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch.Tensor: x = _cast_for_unary_op(x) @@ -618,7 +619,7 @@ def pow( pow.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "complex")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "complex")}, backend_version) @handle_numpy_arrays_in_specific_backend def round( x: torch.Tensor, /, *, decimals: int = 0, out: Optional[torch.Tensor] = None @@ -647,7 +648,7 @@ def trapz( return torch.trapezoid(y, dx=dx, dim=axis) else: if dx is not None: - TypeError( + raise TypeError( "trapezoid() received an invalid combination of arguments - got " "(Tensor, Tensor, int), but expected one of: *(Tensor " "y, Tensor x, *, int dim) * (Tensor y, *, Number dx, int dim)" @@ -659,7 +660,7 @@ def trapz( trapz.support_native_out = False -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "complex")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "complex")}, backend_version) @handle_numpy_arrays_in_specific_backend def trunc(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch.Tensor: x = _cast_for_unary_op(x) @@ -692,7 +693,7 @@ def abs( abs.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "complex")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "complex")}, backend_version) @handle_numpy_arrays_in_specific_backend def logaddexp( x1: torch.Tensor, x2: torch.Tensor, /, *, out: Optional[torch.Tensor] = None @@ -704,7 +705,7 @@ def logaddexp( logaddexp.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, backend_version) @handle_numpy_arrays_in_specific_backend def logaddexp2( x1: Union[torch.Tensor, float, list, tuple], @@ -723,7 +724,7 @@ def logaddexp2( logaddexp2.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, backend_version) @handle_numpy_arrays_in_specific_backend def tan(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch.Tensor: x = _cast_for_unary_op(x) @@ -733,7 +734,7 @@ def tan(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch.Tens tan.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, backend_version) @handle_numpy_arrays_in_specific_backend def atan(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch.Tensor: x = _cast_for_unary_op(x) @@ -744,7 +745,7 @@ def atan(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch.Ten @with_unsupported_dtypes( - {"2.1.0 and below": ("float16", "bfloat16", "complex")}, backend_version + {"2.2 and below": ("float16", "bfloat16", "complex")}, backend_version ) # TODO Fixed in PyTorch 1.12.1 (this note excludes complex) @handle_numpy_arrays_in_specific_backend def atan2( @@ -757,7 +758,7 @@ def atan2( atan2.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, backend_version) @handle_numpy_arrays_in_specific_backend def log(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch.Tensor: x = _cast_for_unary_op(x) @@ -767,7 +768,7 @@ def log(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch.Tens log.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, backend_version) @handle_numpy_arrays_in_specific_backend def exp(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch.Tensor: x = _cast_for_unary_op(x) @@ -808,7 +809,7 @@ def subtract( subtract.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "complex")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "complex")}, backend_version) @handle_numpy_arrays_in_specific_backend def remainder( x1: Union[float, torch.Tensor], @@ -836,7 +837,7 @@ def remainder( remainder.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, backend_version) @handle_numpy_arrays_in_specific_backend def atanh(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch.Tensor: x = _cast_for_unary_op(x) @@ -846,7 +847,7 @@ def atanh(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch.Te atanh.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("complex",)}, backend_version) @handle_numpy_arrays_in_specific_backend def bitwise_right_shift( x1: Union[int, bool, torch.Tensor], @@ -863,7 +864,7 @@ def bitwise_right_shift( bitwise_right_shift.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("complex",)}, backend_version) @handle_numpy_arrays_in_specific_backend def bitwise_left_shift( x1: Union[int, bool, torch.Tensor], @@ -883,7 +884,7 @@ def bitwise_left_shift( # ------# -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "complex")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "complex")}, backend_version) @handle_numpy_arrays_in_specific_backend def erf(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch.Tensor: x = _cast_for_unary_op(x) @@ -893,7 +894,7 @@ def erf(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch.Tens erf.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("complex",)}, backend_version) @handle_numpy_arrays_in_specific_backend def minimum( x1: Union[float, torch.Tensor], @@ -912,7 +913,7 @@ def minimum( minimum.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("complex",)}, backend_version) @handle_numpy_arrays_in_specific_backend def maximum( x1: Union[float, torch.Tensor], @@ -931,7 +932,7 @@ def maximum( maximum.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, backend_version) @handle_numpy_arrays_in_specific_backend def reciprocal( x: Union[float, torch.Tensor], /, *, out: Optional[torch.Tensor] = None @@ -944,7 +945,7 @@ def reciprocal( @with_unsupported_dtypes( - {"2.1.0 and below": ("complex64", "complex128")}, backend_version + {"2.2 and below": ("complex64", "complex128")}, backend_version ) @handle_numpy_arrays_in_specific_backend def deg2rad(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch.Tensor: @@ -955,7 +956,7 @@ def deg2rad(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch. @with_unsupported_dtypes( - {"2.1.0 and below": ("complex64", "complex128")}, backend_version + {"2.2 and below": ("complex64", "complex128")}, backend_version ) @handle_numpy_arrays_in_specific_backend def rad2deg(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch.Tensor: @@ -965,7 +966,7 @@ def rad2deg(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch. rad2deg.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("complex",)}, backend_version) @handle_numpy_arrays_in_specific_backend def trunc_divide( x1: Union[float, torch.Tensor], @@ -989,7 +990,7 @@ def isreal(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch.T @with_unsupported_dtypes( - {"2.1.0 and below": ("bfloat16", "complex")}, + {"2.2 and below": ("bfloat16", "complex")}, backend_version, ) @handle_numpy_arrays_in_specific_backend diff --git a/ivy/functional/backends/torch/experimental/activations.py b/ivy/functional/backends/torch/experimental/activations.py index 34b51951f75c1..8af005a250047 100644 --- a/ivy/functional/backends/torch/experimental/activations.py +++ b/ivy/functional/backends/torch/experimental/activations.py @@ -10,7 +10,7 @@ from . import backend_version -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, backend_version) def logit( x: torch.Tensor, /, @@ -22,7 +22,7 @@ def logit( return torch.logit(x, eps=eps, out=out) -@with_unsupported_dtypes({"2.1.0 and below": ("complex", "float16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("complex", "float16")}, backend_version) def thresholded_relu( x: torch.Tensor, /, @@ -33,14 +33,14 @@ def thresholded_relu( return torch.threshold(x, threshold=threshold, value=0) -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, backend_version) def relu6( x: torch.Tensor, /, *, complex_mode="jax", out: Optional[torch.Tensor] = None ) -> torch.Tensor: return torch.nn.functional.relu6(x) -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, backend_version) def logsigmoid( input: torch.Tensor, /, *, complex_mode="jax", out: Optional[torch.Tensor] = None ) -> torch.Tensor: @@ -49,7 +49,7 @@ def logsigmoid( return torch.nn.functional.logsigmoid(input) -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, backend_version) def selu(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch.Tensor: ret = torch.nn.functional.selu(x) if ivy.exists(out): @@ -57,12 +57,12 @@ def selu(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch.Ten return ivy.astype(ret, x.dtype) -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, backend_version) def silu(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch.Tensor: return torch.nn.functional.silu(x) -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, backend_version) def elu( x: torch.Tensor, /, *, alpha: float = 1.0, out: Optional[torch.Tensor] = None ) -> torch.Tensor: @@ -74,7 +74,7 @@ def elu( @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "complex", "float16", "bfloat16", @@ -93,7 +93,7 @@ def celu( return torch.celu(x, alpha=alpha) -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, backend_version) def hardtanh( x: torch.Tensor, /, @@ -108,7 +108,7 @@ def hardtanh( return ivy.astype(ret, x.dtype) -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, backend_version) def tanhshrink( x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None ) -> torch.Tensor: @@ -118,7 +118,22 @@ def tanhshrink( return ivy.astype(ret, x.dtype) -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, backend_version) +def threshold( + x: torch.Tensor, + /, + *, + threshold: float, + value: float, + out: Optional[torch.Tensor] = None, +) -> torch.Tensor: + ret = torch.nn.functional.threshold(threshold=threshold, value=value, input=x) + if ivy.exists(out): + return ivy.inplace_update(out, ret).astype(x.dtype) + return ivy.astype(ret, x.dtype) + + +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, backend_version) def softshrink( x: torch.Tensor, /, *, lambd: float = 0.5, out: Optional[torch.Tensor] = None ) -> torch.Tensor: @@ -139,7 +154,7 @@ def scaled_tanh( return alpha * torch.nn.functional.tanh(beta * x) -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, backend_version) def hardshrink( x: torch.Tensor, /, *, lambd: float = 0.5, out: Optional[torch.Tensor] = None ) -> torch.Tensor: @@ -147,3 +162,11 @@ def hardshrink( if ivy.exists(out): return ivy.inplace_update(out, ret).astype(x.dtype) return ivy.astype(ret, x.dtype) + + +@with_unsupported_dtypes({"2.0.1 and below": ("complex", "float16")}, backend_version) +def hardsilu(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch.Tensor: + ret = torch.nn.functional.hardswish(x) + if ivy.exists(out): + return ivy.inplace_update(out, ret).astype(x.dtype) + return ivy.astype(ret, x.dtype) diff --git a/ivy/functional/backends/torch/experimental/creation.py b/ivy/functional/backends/torch/experimental/creation.py index 770e94654a1f4..546cde45eac66 100644 --- a/ivy/functional/backends/torch/experimental/creation.py +++ b/ivy/functional/backends/torch/experimental/creation.py @@ -20,7 +20,7 @@ @with_unsupported_device_and_dtypes( - {"2.1.0 and below": {"cpu": ("float16",)}}, + {"2.2 and below": {"cpu": ("float16",)}}, backend_version, ) def kaiser_window( @@ -87,7 +87,7 @@ def vorbis_window( vorbis_window.support_native_out = False -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, backend_version) def hann_window( size: int, /, @@ -131,7 +131,7 @@ def unsorted_segment_min( segment_ids: torch.Tensor, num_segments: Union[int, torch.Tensor], ) -> torch.Tensor: - ivy.utils.assertions.check_unsorted_segment_min_valid_params( + ivy.utils.assertions.check_unsorted_segment_valid_params( data, segment_ids, num_segments ) if data.dtype in [torch.float32, torch.float64, torch.float16, torch.bfloat16]: @@ -139,7 +139,7 @@ def unsorted_segment_min( elif data.dtype in [torch.int32, torch.int64, torch.int8, torch.int16, torch.uint8]: init_val = torch.iinfo(data.dtype).max else: - raise ValueError("Unsupported data type") + raise TypeError("Unsupported data type") res = torch.full( (num_segments,) + data.shape[1:], init_val, dtype=data.dtype, device=data.device @@ -152,7 +152,7 @@ def unsorted_segment_min( return res -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, backend_version) def blackman_window( size: int, /, @@ -180,7 +180,7 @@ def unsorted_segment_sum( # check should be same # Might require to change the assertion function name to # check_unsorted_segment_valid_params - ivy.utils.assertions.check_unsorted_segment_min_valid_params( + ivy.utils.assertions.check_unsorted_segment_valid_params( data, segment_ids, num_segments ) @@ -238,15 +238,40 @@ def hz_to_mel(f): ) # create overlapping frames of size 3 mel_edges = mel_edges.unfold(0, size=3, step=1) - lower_edge_mel, center_mel, upper_edge_mel = [ + lower_edge_mel, center_mel, upper_edge_mel = ( t.reshape((1, num_mel_bins)) for t in mel_edges.split(1, dim=1) - ] + ) lower_slopes = (spec_bin_mels - lower_edge_mel) / (center_mel - lower_edge_mel) upper_slopes = (upper_edge_mel - spec_bin_mels) / (upper_edge_mel - center_mel) mel_weights = torch.maximum(zero, torch.minimum(lower_slopes, upper_slopes)) return torch.nn.functional.pad(mel_weights, (0, 0, 1, 0)) +def unsorted_segment_mean( + data: torch.Tensor, + segment_ids: torch.Tensor, + num_segments: Union[int, torch.Tensor], +) -> torch.Tensor: + ivy.utils.assertions.check_unsorted_segment_valid_params( + data, segment_ids, num_segments + ) + + # Initialize an array to store the sum of elements for each segment + segment_sum = torch.zeros( + (num_segments,) + data.shape[1:], dtype=data.dtype, device=data.device + ) + + # Initialize an array to keep track of the number of elements in each segment + counts = torch.zeros(num_segments, dtype=torch.int64, device=data.device) + + for i in range(len(segment_ids)): + seg_id = segment_ids[i] + segment_sum[seg_id] += data[i] + counts[seg_id] += 1 + + return segment_sum / counts[:, None] + + @with_unsupported_dtypes({"2.0.1 and below": "float16"}, backend_version) def polyval( coeffs: torch.Tensor, diff --git a/ivy/functional/backends/torch/experimental/elementwise.py b/ivy/functional/backends/torch/experimental/elementwise.py index 2c6fb41c8b1a5..db54833224dd5 100644 --- a/ivy/functional/backends/torch/experimental/elementwise.py +++ b/ivy/functional/backends/torch/experimental/elementwise.py @@ -16,7 +16,7 @@ @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "complex64", "complex128", ) @@ -40,7 +40,7 @@ def amax( @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "complex64", "complex128", ) @@ -62,12 +62,12 @@ def amin( amin.support_native_out = True -@with_supported_dtypes({"2.1.0 and below": ("float32", "float64")}, backend_version) +@with_supported_dtypes({"2.2 and below": ("float32", "float64")}, backend_version) def lgamma(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch.Tensor: return torch.lgamma(x, out=out) -@with_unsupported_dtypes({"2.1.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("complex",)}, backend_version) def fmax( x1: torch.Tensor, x2: torch.Tensor, @@ -82,7 +82,7 @@ def fmax( fmax.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, backend_version) def sinc(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch.Tensor: x = _cast_for_unary_op(x) return torch.sinc(x, out=out) @@ -158,7 +158,7 @@ def count_nonzero( count_nonzero.support_native_out = False -@with_unsupported_dtypes({"2.1.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("complex",)}, backend_version) def nansum( x: torch.Tensor, /, @@ -227,7 +227,7 @@ def signbit( signbit.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, backend_version) def hypot( x1: torch.Tensor, x2: torch.Tensor, @@ -252,7 +252,7 @@ def allclose( return torch.tensor(ret) -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, backend_version) def fix( x: torch.Tensor, /, @@ -265,7 +265,7 @@ def fix( fix.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, backend_version) def nextafter( x1: torch.Tensor, x2: torch.Tensor, @@ -319,7 +319,7 @@ def gradient( @with_supported_dtypes( - {"2.1.0 and below": ("float16", "float32", "float64")}, + {"2.2 and below": ("float16", "float32", "float64")}, backend_version, ) def xlogy( @@ -382,7 +382,7 @@ def _are_suitable_types_for_torch_lerp(input, end, weight): return True -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, backend_version) def lerp( input: torch.Tensor, end: torch.Tensor, @@ -415,12 +415,13 @@ def modf( /, *, out: Optional[torch.Tensor] = None, -) -> torch.Tensor: - modf_x = torch.modf(x) - return torch.resolve_modf(input=modf_x) +) -> Tuple[torch.Tensor, torch.Tensor]: + fractional_part = torch.frac(x) + integer_part = torch.floor(x) + return fractional_part, integer_part -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, backend_version) def digamma( x: torch.Tensor, /, @@ -433,7 +434,7 @@ def digamma( digamma.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, backend_version) def erfc( x: torch.Tensor, /, @@ -441,3 +442,16 @@ def erfc( out: Optional[torch.Tensor] = None, ) -> torch.Tensor: return torch.special.erfc(x) + + +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, backend_version) +def erfinv( + x: torch.Tensor, + /, + *, + out: Optional[torch.Tensor] = None, +) -> torch.Tensor: + return torch.special.erfinv(x, out=out) + + +erfinv.support_native_out = True diff --git a/ivy/functional/backends/torch/experimental/gradients.py b/ivy/functional/backends/torch/experimental/gradients.py index 3234a5f342953..b6c0a7cedf6e4 100644 --- a/ivy/functional/backends/torch/experimental/gradients.py +++ b/ivy/functional/backends/torch/experimental/gradients.py @@ -35,12 +35,10 @@ def backward(ctx, upstream): def vjp(func: Callable, *primals): flattened_primals, ret_idxs = _flatten_containers(primals) unique_keys = list( - set( - [ - ivy.index_nest(ret_idxs, i) - for i in ivy.nested_argwhere(ret_idxs, lambda x: isinstance(x, str)) - ] - ) + { + ivy.index_nest(ret_idxs, i) + for i in ivy.nested_argwhere(ret_idxs, lambda x: isinstance(x, str)) + } ) def grad_fn(*x_in): @@ -98,12 +96,10 @@ def jvp(func: Callable, primals, tangents): flattened_primals, ret_idxs = _flatten_containers(primals) flattened_tangents, _ = _flatten_containers(tangents) unique_keys = list( - set( - [ - ivy.index_nest(ret_idxs, i) - for i in ivy.nested_argwhere(ret_idxs, lambda x: isinstance(x, str)) - ] - ) + { + ivy.index_nest(ret_idxs, i) + for i in ivy.nested_argwhere(ret_idxs, lambda x: isinstance(x, str)) + } ) def grad_fn(*x_in): diff --git a/ivy/functional/backends/torch/experimental/layers.py b/ivy/functional/backends/torch/experimental/layers.py index 19a2dfd3d8b61..1c53639d23409 100644 --- a/ivy/functional/backends/torch/experimental/layers.py +++ b/ivy/functional/backends/torch/experimental/layers.py @@ -13,7 +13,10 @@ _validate_max_pool_params, _depth_max_pooling_helper, ) -from ivy.functional.ivy.experimental.layers import _padding_ceil_mode +from ivy.functional.ivy.experimental.layers import ( + _padding_ceil_mode, + _broadcast_pooling_helper, +) def _determine_depth_max_pooling(x, kernel, strides, dims, data_format="channel_first"): @@ -26,25 +29,7 @@ def _determine_depth_max_pooling(x, kernel, strides, dims, data_format="channel_ return x, kernel, strides, depth_pooling -def _broadcast_pooling_helper(x, pool_dims: str = "2d", name: str = "padding"): - dims = {"1d": 1, "2d": 2, "3d": 3} - if isinstance(x, int): - return tuple([x for _ in range(dims[pool_dims])]) - - if len(x) == 1: - return tuple([x[0] for _ in range(dims[pool_dims])]) - - elif len(x) == dims[pool_dims]: - return tuple(x) - - elif len(x) != dims[pool_dims]: - raise ValueError( - f"`{name}` must either be a single int, " - f"or a tuple of {dims[pool_dims]} ints. " - ) - - -@with_unsupported_dtypes({"2.1.0 and below": ("bfloat16", "float16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("bfloat16", "float16")}, backend_version) def max_pool1d( x: torch.Tensor, kernel: Union[int, Tuple[int, ...]], @@ -63,56 +48,53 @@ def max_pool1d( ) if data_format == "NWC": - x = x.permute((0, 2, 1)) + x = x.permute(0, 2, 1) kernel = [kernel[i] for i in [0, 2, 1]] if len(kernel) == (dims + 2) else kernel strides = ( [strides[i] for i in [0, 2, 1]] if len(strides) == (dims + 2) else strides ) - padding = ( - [padding[i] for i in [0, 2, 1]] - if isinstance(padding, list) and len(padding) == (dims + 2) - else padding - ) - # Determine deptwise pooling + # determine depth pooling x, kernel, strides, depth_pooling = _determine_depth_max_pooling( x, kernel, strides, dims, data_format="channel_first" ) - if not depth_pooling: + if isinstance(padding, str): + x_shape = list(x.shape[2:]) new_kernel = [dilation[0] * (kernel[0] - 1) + 1] + pad_w = _handle_padding(x_shape[0], strides[0], new_kernel[0], padding) + pad_list = [pad_w // 2, pad_w - pad_w // 2] + else: + if any(item != 0 for sublist in padding for item in sublist) and depth_pooling: + raise NotImplementedError( + "Nonzero explicit padding is not supported for depthwise max pooling" + ) + pad_list = [item for sublist in padding[::-1] for item in sublist] - if isinstance(padding, str): - pad_w = _handle_padding(x.shape[2], strides[0], new_kernel[0], padding) - pad_list = [pad_w // 2, pad_w - pad_w // 2] - else: - pad_list = [item for sublist in padding for item in sublist] - + if all(pad_list[i] == pad_list[i + 1] for i in range(0, 2 * dims, 2)) and all( + pad <= kernel_size / 2 for pad, kernel_size in zip(pad_list[::-2], kernel) + ): + res = torch.nn.functional.max_pool1d( + x, kernel, strides, pad_list[::-2], dilation, ceil_mode + ) + else: x = torch.nn.functional.pad( x, pad_list, value=float("-inf"), ) - else: - if isinstance(padding, list) and any( - [item != 0 for sublist in padding for item in sublist] - ): - raise NotImplementedError( - "Nonzero explicit padding is not supported for depthwise max pooling" - ) - - res = torch.nn.functional.max_pool1d(x, kernel, strides, 0, dilation, ceil_mode) + res = torch.nn.functional.max_pool1d(x, kernel, strides, 0, dilation, ceil_mode) if depth_pooling: res = torch.permute(res, (0, 2, 1)) if data_format == "NWC": - res = res.permute((0, 2, 1)) + return res.permute(0, 2, 1) return res @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "float16", "bfloat16", ) @@ -146,44 +128,39 @@ def max_pool2d( if len(strides) == (dims + 2) else strides ) - padding = ( - [padding[i] for i in [0, 3, 1, 2]] - if isinstance(padding, list) and len(padding) == (dims + 2) - else padding - ) # determine depth pooling x, kernel, strides, depth_pooling = _determine_depth_max_pooling( x, kernel, strides, dims, data_format="channel_first" ) - x_shape = list(x.shape[2:]) - if not depth_pooling: + if isinstance(padding, str): + x_shape = list(x.shape[2:]) new_kernel = [kernel[i] + (kernel[i] - 1) * (dilation[i] - 1) for i in range(2)] + pad_h = _handle_padding(x_shape[0], strides[0], new_kernel[0], padding) + pad_w = _handle_padding(x_shape[1], strides[1], new_kernel[1], padding) + pad_list = [pad_w // 2, pad_w - pad_w // 2, pad_h // 2, pad_h - pad_h // 2] + else: + if any(item != 0 for sublist in padding for item in sublist) and depth_pooling: + raise NotImplementedError( + "Nonzero explicit padding is not supported for depthwise max pooling" + ) + pad_list = [item for sublist in padding[::-1] for item in sublist] - if isinstance(padding, str): - pad_h = _handle_padding(x_shape[0], strides[0], new_kernel[0], padding) - pad_w = _handle_padding(x_shape[1], strides[1], new_kernel[1], padding) - pad_list = [pad_w // 2, pad_w - pad_w // 2, pad_h // 2, pad_h - pad_h // 2] - else: - # torch pad takes width padding first, then height padding - padding = (padding[1], padding[0]) - pad_list = [item for sublist in padding for item in sublist] - + if all(pad_list[i] == pad_list[i + 1] for i in range(0, 2 * dims, 2)) and all( + pad <= kernel_size / 2 for pad, kernel_size in zip(pad_list[::-2], kernel) + ): + res = torch.nn.functional.max_pool2d( + x, kernel, strides, pad_list[::-2], dilation, ceil_mode + ) + else: x = torch.nn.functional.pad( x, pad_list, value=float("-inf"), ) - else: - if isinstance(padding, list) and any( - [item != 0 for sublist in padding for item in sublist] - ): - raise NotImplementedError( - "Nonzero explicit padding is not supported for depthwise max pooling" - ) + res = torch.nn.functional.max_pool2d(x, kernel, strides, 0, dilation, ceil_mode) - res = torch.nn.functional.max_pool2d(x, kernel, strides, 0, dilation, ceil_mode) if depth_pooling: res = torch.permute(res, (0, 2, 1, 3)) if data_format == "NHWC": @@ -193,7 +170,7 @@ def max_pool2d( @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "float16", "bfloat16", ) @@ -229,57 +206,51 @@ def max_pool3d( if len(strides) == (dims + 2) else strides ) - padding = ( - [padding[i] for i in [0, 4, 1, 2, 3]] - if isinstance(padding, list) and len(padding) == (dims + 2) - else padding - ) - # Determine deptwise pooling + # determine depth pooling x, kernel, strides, depth_pooling = _determine_depth_max_pooling( x, kernel, strides, dims, data_format="channel_first" ) - if not depth_pooling: - x_shape = x.shape[2:] - new_kernel = [dilation[i] * (kernel[i] - 1) + 1 for i in range(dims)] - - if isinstance(padding, str): - pad_d = _handle_padding(x_shape[0], strides[0], new_kernel[0], padding) - pad_h = _handle_padding(x_shape[1], strides[1], new_kernel[1], padding) - pad_w = _handle_padding(x_shape[2], strides[2], new_kernel[2], padding) - pad_list = [ - pad_w // 2, - pad_w - pad_w // 2, - pad_h // 2, - pad_h - pad_h // 2, - pad_d // 2, - pad_d - pad_d // 2, - ] - else: - # torch pad takes width padding first, then height, then depth - padding = (padding[2], padding[1], padding[0]) - pad_list = [item for sublist in padding for item in sublist] + if isinstance(padding, str): + x_shape = list(x.shape[2:]) + new_kernel = [kernel[i] + (kernel[i] - 1) * (dilation[i] - 1) for i in range(3)] + pad_d = _handle_padding(x_shape[0], strides[0], new_kernel[0], padding) + pad_h = _handle_padding(x_shape[1], strides[1], new_kernel[1], padding) + pad_w = _handle_padding(x_shape[2], strides[2], new_kernel[2], padding) + pad_list = [ + pad_w // 2, + pad_w - pad_w // 2, + pad_h // 2, + pad_h - pad_h // 2, + pad_d // 2, + pad_d - pad_d // 2, + ] + else: + if any(item != 0 for sublist in padding for item in sublist) and depth_pooling: + raise NotImplementedError( + "Nonzero explicit padding is not supported for depthwise max pooling" + ) + pad_list = [item for sublist in padding[::-1] for item in sublist] + if all(pad_list[i] == pad_list[i + 1] for i in range(0, 2 * dims, 2)) and all( + pad <= kernel_size / 2 for pad, kernel_size in zip(pad_list[::-2], kernel) + ): + res = torch.nn.functional.max_pool3d( + x, kernel, strides, pad_list[::-2], dilation, ceil_mode + ) + else: x = torch.nn.functional.pad( x, pad_list, value=float("-inf"), ) - else: - if isinstance(padding, list) and any( - [item != 0 for sublist in padding for item in sublist] - ): - raise NotImplementedError( - "Nonzero explicit padding is not supported for depthwise max pooling" - ) - - res = torch.nn.functional.max_pool3d(x, kernel, strides, 0, dilation, ceil_mode) + res = torch.nn.functional.max_pool3d(x, kernel, strides, 0, dilation, ceil_mode) if depth_pooling: - res = res.permute(0, 2, 1, 3, 4) + res = torch.permute(res, (0, 2, 1, 3, 4)) if data_format == "NDHWC": - res = res.permute(0, 2, 3, 4, 1) + return res.permute(0, 2, 3, 4, 1) return res @@ -311,17 +282,18 @@ def _get_specific_pad(x_shape, kernel, strides, padding, dims): return padding, pad_specific -@with_unsupported_dtypes({"2.1.0 and below": ("bfloat16", "float16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("bfloat16", "float16")}, backend_version) def avg_pool1d( x: torch.Tensor, kernel: Union[int, Tuple[int]], strides: Union[int, Tuple[int]], - padding: str, + padding: Union[str, int, List[Tuple[int, int]]], /, *, data_format: str = "NWC", count_include_pad: bool = False, ceil_mode: bool = False, + divisor_override: Optional[int] = None, out: Optional[torch.Tensor] = None, ) -> torch.Tensor: if isinstance(strides, int): @@ -337,43 +309,50 @@ def avg_pool1d( if data_format in ("NWC", "NCL"): x = x.permute(0, 2, 1) - x_shape = x.shape[2] - if isinstance(padding, str): - pad_specific = [ - _handle_padding(x_shape, strides[i], kernel[i], padding) for i in range(1) - ] - padding = [ - (pad_specific[i] // 2, pad_specific[i] - pad_specific[i] // 2) - for i in range(1) - ] + if ( + isinstance(padding, int) + or not isinstance(padding, str) + and padding[0][0] == padding[0][1] + ) and not divisor_override: + if not isinstance(padding, int): + padding = padding[0][0] + res = torch.nn.functional.avg_pool1d( + x, + kernel, + strides, + padding, + count_include_pad=count_include_pad, + ceil_mode=ceil_mode, + ) else: - pad_specific = [sum(padding[i]) for i in range(1)] - x = torch.nn.functional.pad(x, *padding, value=0.0) - - res = torch.nn.functional.avg_pool1d(x, kernel, strides, 0, ceil_mode) - - if not count_include_pad and any(pad_specific): - num_padded_values = ivy.map( - _get_num_padded_values, - constant={ - "p": pad_specific[0], - "n": x_shape, - "k": kernel[0], - "s": strides[0], - }, - unique={ - "i": torch.arange(res.shape[2]), - }, + x_shape = x.shape[2] + padding, pad_specific = _get_specific_pad( + [x_shape], kernel, strides, padding, 1 ) - num_padded_values = torch.tensor(num_padded_values, dtype=res.dtype) + x = torch.nn.functional.pad(x, padding, value=0.0) - if ceil_mode: - _, c = _padding_ceil_mode(x_shape, kernel[0], padding[0], strides[0], True) - num_padded_values[-1] = _add_ceil_pad_to_pad_list( - num_padded_values[-1], kernel[0], c - ) + res = torch.nn.functional.avg_pool1d(x, kernel, strides, 0, ceil_mode) - res = (kernel[0] * res) / (kernel[0] - num_padded_values) + if not count_include_pad and any(pad_specific): + num_padded_values = ivy.map( + _get_num_padded_values, + constant={ + "p": pad_specific[0], + "n": x_shape, + "k": kernel[0], + "s": strides[0], + }, + unique={ + "i": torch.arange(res.shape[2]), + }, + ) + num_padded_values = torch.tensor(num_padded_values, dtype=res.dtype) + if ceil_mode: + _, c = _padding_ceil_mode(x_shape, kernel[0], padding, strides[0], True) + num_padded_values[-1] = _add_ceil_pad_to_pad_list( + num_padded_values[-1], kernel[0], c + ) + res = (kernel[0] * res) / (kernel[0] - num_padded_values) if data_format in ("NWC", "NCL"): res = res.permute(0, 2, 1) @@ -395,7 +374,7 @@ def _adjust_num_padded_values_to_ceil( @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "float16", "bfloat16", ) @@ -406,7 +385,7 @@ def avg_pool2d( x: torch.Tensor, kernel: Union[int, Tuple[int], Tuple[int, int]], strides: Union[int, Tuple[int], Tuple[int, int]], - padding: str, + padding: Union[str, int, List[Tuple[int, int]]], /, *, data_format: str = "NHWC", @@ -427,54 +406,71 @@ def avg_pool2d( if data_format == "NHWC": x = x.permute(0, 3, 1, 2) - x_shape = list(x.shape[2:]) - padding, pad_specific = _get_specific_pad(x_shape, kernel, strides, padding, 2) - x = torch.nn.functional.pad( - x, - padding, - value=0.0, - ) - res = torch.nn.functional.avg_pool2d( - x, kernel, strides, 0, ceil_mode, divisor_override=divisor_override - ) - if not count_include_pad and any(pad_specific) and not divisor_override: - num_padded_values = [ - ivy.map( - _get_num_padded_values, - constant={ - "p": pad_specific[i], - "n": x_shape[i], - "k": kernel[i], - "s": strides[i], - }, - unique={ - "i": torch.arange(res.shape[i + 2]), - }, - ) - for i in range(2) - ] + if ( + isinstance(padding, int) + or not isinstance(padding, str) + and all(pad[0] == pad[1] for pad in padding) + ): + if not isinstance(padding, int): + padding = [padding[0][0], padding[1][0]] + res = torch.nn.functional.avg_pool2d( + x, + kernel, + strides, + padding, + count_include_pad=count_include_pad, + ceil_mode=ceil_mode, + divisor_override=divisor_override, + ) + else: + x_shape = list(x.shape[2:]) + padding, pad_specific = _get_specific_pad(x_shape, kernel, strides, padding, 2) + x = torch.nn.functional.pad( + x, + padding, + value=0.0, + ) + res = torch.nn.functional.avg_pool2d( + x, kernel, strides, 0, ceil_mode, divisor_override=divisor_override + ) - if ceil_mode: - for i in range(2): - num_padded_values = _adjust_num_padded_values_to_ceil( - pad_specific, num_padded_values, x_shape, kernel, strides, 2 + if not count_include_pad and any(pad_specific) and not divisor_override: + num_padded_values = [ + ivy.map( + _get_num_padded_values, + constant={ + "p": pad_specific[i], + "n": x_shape[i], + "k": kernel[i], + "s": strides[i], + }, + unique={ + "i": torch.arange(res.shape[i + 2]), + }, ) + for i in range(2) + ] + if ceil_mode: + for i in range(2): + num_padded_values = _adjust_num_padded_values_to_ceil( + pad_specific, num_padded_values, x_shape, kernel, strides, 2 + ) + num_padded_values1 = torch.tensor(num_padded_values[0], dtype=res.dtype)[ + :, None + ] + num_padded_values2 = torch.tensor(num_padded_values[1], dtype=res.dtype)[ + None, : + ] + num_padded_values = ( + num_padded_values1 * kernel[1] + + num_padded_values2 * kernel[0] + - num_padded_values1 * num_padded_values2 + ) + res = (kernel[0] * kernel[1] * res) / ( + kernel[0] * kernel[1] - num_padded_values + ) - num_padded_values1 = torch.tensor(num_padded_values[0], dtype=res.dtype)[ - :, None - ] - num_padded_values2 = torch.tensor(num_padded_values[1], dtype=res.dtype)[ - None, : - ] - num_padded_values = ( - num_padded_values1 * kernel[1] - + num_padded_values2 * kernel[0] - - num_padded_values1 * num_padded_values2 - ) - res = (kernel[0] * kernel[1] * res) / ( - kernel[0] * kernel[1] - num_padded_values - ) if data_format == "NHWC": return res.permute(0, 2, 3, 1) return res @@ -482,7 +478,7 @@ def avg_pool2d( @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "float16", "bfloat16", ) @@ -493,7 +489,7 @@ def avg_pool3d( x: torch.Tensor, kernel: Union[int, Tuple[int], Tuple[int, int, int]], strides: Union[int, Tuple[int], Tuple[int, int, int]], - padding: str, + padding: Union[str, int, List[Tuple[int, int]]], /, *, data_format: str = "NDHWC", @@ -512,63 +508,80 @@ def avg_pool3d( kernel = (kernel[0], kernel[0], kernel[0]) if data_format == "NDHWC": x = x.permute(0, 4, 1, 2, 3) - x_shape = list(x.shape[2:]) - padding, pad_specific = _get_specific_pad(x_shape, kernel, strides, padding, 3) - x = torch.nn.functional.pad( - x, - padding, - value=0.0, - ) - res = torch.nn.functional.avg_pool3d( - x, kernel, strides, 0, ceil_mode, divisor_override=divisor_override - ) - if not count_include_pad and any(pad_specific) and not divisor_override: - num_padded_values = [ - torch.tensor( - ivy.map( - _get_num_padded_values, - constant={ - "p": pad_specific[i], - "n": x_shape[i], - "k": kernel[i], - "s": strides[i], - }, - unique={ - "i": torch.arange(res.shape[i + 2]), - }, - ), - dtype=res.dtype, - ) - for i in range(3) - ] + if ( + isinstance(padding, int) + or not isinstance(padding, str) + and all(pad[0] == pad[1] for pad in padding) + ): + if not isinstance(padding, int): + padding = [padding[0][0], padding[1][0], padding[2][0]] + res = torch.nn.functional.avg_pool3d( + x, + kernel, + strides, + padding, + count_include_pad=count_include_pad, + ceil_mode=ceil_mode, + divisor_override=divisor_override, + ) + else: + x_shape = list(x.shape[2:]) + padding, pad_specific = _get_specific_pad(x_shape, kernel, strides, padding, 3) + x = torch.nn.functional.pad( + x, + padding, + value=0.0, + ) + res = torch.nn.functional.avg_pool3d( + x, kernel, strides, 0, ceil_mode, divisor_override=divisor_override + ) - if ceil_mode: - for i in range(3): - num_padded_values = _adjust_num_padded_values_to_ceil( - pad_specific, num_padded_values, x_shape, kernel, strides, 3 + if not count_include_pad and any(pad_specific) and not divisor_override: + num_padded_values = [ + torch.tensor( + ivy.map( + _get_num_padded_values, + constant={ + "p": pad_specific[i], + "n": x_shape[i], + "k": kernel[i], + "s": strides[i], + }, + unique={ + "i": torch.arange(res.shape[i + 2]), + }, + ), + dtype=res.dtype, ) - num_padded_values1 = num_padded_values[0].reshape((-1, 1, 1)) - num_padded_values2 = num_padded_values[1].reshape((1, -1, 1)) - num_padded_values3 = num_padded_values[2].reshape((1, 1, -1)) - num_padded_values = ( - num_padded_values1 * kernel[1] * kernel[2] - + num_padded_values2 * kernel[0] * kernel[2] - + num_padded_values3 * kernel[0] * kernel[1] - + num_padded_values1 * num_padded_values2 * num_padded_values3 - - num_padded_values1 * num_padded_values2 * kernel[2] - - num_padded_values1 * num_padded_values3 * kernel[1] - - num_padded_values2 * num_padded_values3 * kernel[0] - ) - kernel_mul = kernel[0] * kernel[1] * kernel[2] - res = (kernel_mul * res) / (kernel_mul - num_padded_values) + for i in range(3) + ] + if ceil_mode: + for i in range(3): + num_padded_values = _adjust_num_padded_values_to_ceil( + pad_specific, num_padded_values, x_shape, kernel, strides, 3 + ) + num_padded_values1 = num_padded_values[0].reshape((-1, 1, 1)) + num_padded_values2 = num_padded_values[1].reshape((1, -1, 1)) + num_padded_values3 = num_padded_values[2].reshape((1, 1, -1)) + num_padded_values = ( + num_padded_values1 * kernel[1] * kernel[2] + + num_padded_values2 * kernel[0] * kernel[2] + + num_padded_values3 * kernel[0] * kernel[1] + + num_padded_values1 * num_padded_values2 * num_padded_values3 + - num_padded_values1 * num_padded_values2 * kernel[2] + - num_padded_values1 * num_padded_values3 * kernel[1] + - num_padded_values2 * num_padded_values3 * kernel[0] + ) + kernel_mul = kernel[0] * kernel[1] * kernel[2] + res = (kernel_mul * res) / (kernel_mul - num_padded_values) if data_format == "NDHWC": res = res.permute(0, 2, 3, 4, 1) return res -@with_supported_dtypes({"2.1.0 and below": ("float32", "float64")}, backend_version) +@with_supported_dtypes({"2.2 and below": ("float32", "float64")}, backend_version) def dct( x: torch.Tensor, /, @@ -681,7 +694,7 @@ def idct( @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "float16", "bfloat16", ) @@ -694,7 +707,7 @@ def fft( /, *, norm: str = "backward", - n: Union[int, Tuple[int]] = None, + n: Optional[Union[int, Tuple[int]]] = None, out: Optional[torch.Tensor] = None, ) -> torch.Tensor: if not isinstance(dim, int): @@ -716,7 +729,7 @@ def fft( raise ivy.utils.exceptions.IvyError( f"Invalid data points {n}, expecting more than 1" ) - if norm != "backward" and norm != "ortho" and norm != "forward": + if norm not in {"backward", "ortho", "forward"}: raise ivy.utils.exceptions.IvyError(f"Unrecognized normalization mode {norm}") if x.dtype in [torch.int64, torch.float64, torch.complex128]: out_dtype = torch.complex128 @@ -727,7 +740,7 @@ def fft( @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "float16", "bfloat16", "complex", @@ -747,8 +760,10 @@ def dropout( noise_shape: Optional[Sequence[int]] = None, out: Optional[torch.Tensor] = None, ) -> torch.Tensor: - x = ivy.astype(x, dtype) if dtype else x - res = torch.nn.functional.dropout(x, prob, training=training) + x = ivy.astype(x, dtype) if dtype and x.dtype != dtype else x + if prob == 0 or not training: + return x + res = torch.nn.functional.dropout(x, prob, training=True) res = torch.multiply(res, (1.0 - prob)) if not scale else res return res @@ -759,7 +774,7 @@ def dropout( @with_unsupported_dtypes( - {"2.1.0 and below": ("float16",)}, + {"2.2 and below": ("float16",)}, backend_version, ) def dropout1d( @@ -782,7 +797,7 @@ def dropout1d( @with_unsupported_dtypes( - {"2.1.0 and below": ("float16",)}, + {"2.2 and below": ("float16",)}, backend_version, ) def dropout2d( @@ -807,7 +822,7 @@ def dropout2d( @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "float16", "bfloat16", ) @@ -839,7 +854,7 @@ def ifft( dim: int, *, norm: str = "backward", - n: Union[int, Tuple[int]] = None, + n: Optional[Union[int, Tuple[int]]] = None, out: Optional[torch.Tensor] = None, ) -> torch.Tensor: if not isinstance(dim, int): @@ -861,12 +876,12 @@ def ifft( raise ivy.utils.exceptions.IvyError( f"Invalid data points {n}, expecting more than 1" ) - if norm != "backward" and norm != "ortho" and norm != "forward": + if norm not in {"backward", "ortho", "forward"}: raise ivy.utils.exceptions.IvyError(f"Unrecognized normalization mode {norm}") return torch.fft.ifft(x, n, dim, norm, out=out).resolve_conj() -@with_unsupported_dtypes({"2.1.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("complex",)}, backend_version) def embedding( weights: torch.Tensor, indices: torch.Tensor, @@ -893,10 +908,12 @@ def interpolate( "linear", "bilinear", "trilinear", + "nd", "nearest", "area", "nearest_exact", "tf_area", + "tf_bicubic", "bicubic", "mitchellcubic", "lanczos3", @@ -905,10 +922,12 @@ def interpolate( ] = "linear", scale_factor: Optional[Union[Sequence[int], int]] = None, recompute_scale_factor: Optional[bool] = None, - align_corners: Optional[bool] = None, + align_corners: bool = False, antialias: bool = False, out: Optional[torch.Tensor] = None, ): + if mode not in ["linear", "bilinear", "bicubic", "trilinear"]: + align_corners = None return torch.nn.functional.interpolate( x, size=size, @@ -920,39 +939,61 @@ def interpolate( ) -interpolate.partial_mixed_handler = lambda *args, mode="linear", **kwargs: mode not in [ - "tf_area", - "nd", - "bicubic_tensorflow", - "mitchellcubic", - "lanczos3", - "lanczos5", - "gaussian", -] +interpolate.partial_mixed_handler = ( + lambda *args, mode="linear", align_corners=False, **kwargs: mode + not in [ + "tf_area", + "nd", + "tf_bicubic", + "mitchellcubic", + "lanczos3", + "lanczos5", + "gaussian", + ] + and (mode in ["linear", "bilinear", "bicubic", "trilinear"] or not align_corners) +) -@with_unsupported_dtypes({"2.1.0 and below": ("bfloat16", "float16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("bfloat16", "float16")}, backend_version) def adaptive_max_pool2d( input: torch.Tensor, output_size: Union[Sequence[int], int] ) -> torch.Tensor: return torch.nn.functional.adaptive_max_pool2d(input, output_size) -@with_unsupported_dtypes({"2.1.0 and below": ("bfloat16", "float16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("bfloat16", "float16")}, backend_version) +def adaptive_max_pool3d( + input: torch.Tensor, output_size: Union[Sequence[int], int] +) -> torch.Tensor: + return torch.nn.functional.adaptive_max_pool3d(input, output_size) + + +@with_unsupported_dtypes({"2.2 and below": ("bfloat16", "float16")}, backend_version) def adaptive_avg_pool1d(input, output_size): return torch.nn.functional.adaptive_avg_pool1d(input, output_size) -@with_unsupported_dtypes({"2.1.0 and below": ("bfloat16", "float16")}, backend_version) -def adaptive_avg_pool2d(input, output_size): - return torch.nn.functional.adaptive_avg_pool2d(input, output_size) +@with_unsupported_dtypes({"2.2 and below": ("bfloat16", "float16")}, backend_version) +def adaptive_avg_pool2d(input, output_size, /, *, data_format: str = "NHWC"): + squeeze = False + if input.ndim == 3: + input = torch.unsqueeze(input, 0) + squeeze = True + permuted_input = False + if data_format == "NHWC": + input = torch.permute(input, (0, input.ndim - 1, *range(1, input.ndim - 1))) + permuted_input = True + ret = torch.nn.functional.adaptive_avg_pool2d(input, output_size) + ret = torch.permute(ret, (0, *range(2, input.ndim), 1)) if permuted_input else ret + ret = torch.squeeze(ret, 0) if squeeze else ret + return ret -@with_unsupported_dtypes({"2.1.0 and below": ("bfloat16", "float16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("bfloat16", "float16")}, backend_version) def fft2( x: torch.Tensor, *, - s: Sequence[int] = None, + s: Optional[Sequence[int]] = None, dim: Sequence[int] = (-2, -1), norm: str = "backward", out: Optional[torch.Tensor] = None, @@ -976,7 +1017,7 @@ def fft2( raise ivy.utils.exceptions.IvyError( f"Invalid data points {s}, expecting s points larger than 1" ) - if norm != "backward" and norm != "ortho" and norm != "forward": + if norm not in {"backward", "ortho", "forward"}: raise ivy.utils.exceptions.IvyError(f"Unrecognized normalization mode {norm}") return torch.tensor( torch.fft.fft2(x, s, dim, norm, out=out), dtype=torch.complex128 @@ -1014,11 +1055,11 @@ def rfft( return ret -@with_unsupported_dtypes({"2.1.0 and below": ("bfloat16", "float16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("bfloat16", "float16")}, backend_version) def rfftn( x: torch.Tensor, - s: Sequence[int] = None, - axes: Sequence[int] = None, + s: Optional[Sequence[int]] = None, + axes: Optional[Sequence[int]] = None, *, norm: str = "backward", out: Optional[torch.Tensor] = None, @@ -1042,7 +1083,7 @@ def rfftn( raise ivy.utils.exceptions.IvyError( f"Invalid data points {s}, expecting s points larger than 1" ) - if norm != "backward" and norm != "ortho" and norm != "forward": + if norm not in {"backward", "ortho", "forward"}: raise ivy.utils.exceptions.IvyError(f"Unrecognized normalization mode {norm}") return torch.tensor( torch.fft.rfftn(x, s, axes, norm=norm, out=out), dtype=torch.complex128 @@ -1052,7 +1093,7 @@ def rfftn( # stft @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "float16", "bfloat16", ) @@ -1147,7 +1188,7 @@ def stft_1D(signals, frame_length, frame_step, fft_length, pad_end): windowed_frame = torch.tensor(windowed_frame, dtype=dtype) fft_frame = torch.fft.fft(windowed_frame, axis=-1) - slit = int((fft_length // 2 + 1)) + slit = int(fft_length // 2 + 1) stft_result.append(fft_frame[..., 0:slit]) stft = torch.stack(stft_result, axis=0) @@ -1228,7 +1269,7 @@ def max_unpool1d( kernel_size: Union[Tuple[int], int], /, *, - strides: Union[int, Tuple[int]] = None, + strides: Optional[Union[int, Tuple[int]]] = None, padding: Union[int, Tuple[int]] = 0, data_format: Optional[str] = "NCW", ) -> torch.Tensor: diff --git a/ivy/functional/backends/torch/experimental/linear_algebra.py b/ivy/functional/backends/torch/experimental/linear_algebra.py index 9ae68a74b6af5..5c7dc1492571b 100644 --- a/ivy/functional/backends/torch/experimental/linear_algebra.py +++ b/ivy/functional/backends/torch/experimental/linear_algebra.py @@ -1,18 +1,17 @@ # global import math - +from collections import namedtuple import torch from typing import Optional, Tuple, Sequence, Union import ivy from ivy.func_wrapper import with_unsupported_dtypes -from ivy.utils.exceptions import IvyNotImplementedException from .. import backend_version from ivy.functional.ivy.experimental.linear_algebra import _check_valid_dimension_size -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, backend_version) def diagflat( x: torch.Tensor, /, @@ -176,7 +175,7 @@ def solve_triangular( solve_triangular.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, backend_version) def multi_dot( x: Sequence[torch.Tensor], /, @@ -203,16 +202,31 @@ def cond( cond.support_native_out = False +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, backend_version) def lu_factor( x: torch.Tensor, /, *, pivot: Optional[bool] = True, out: Optional[torch.Tensor] = None, -) -> Tuple[torch.Tensor]: - raise IvyNotImplementedException() +) -> Tuple[torch.Tensor, torch.Tensor]: + ret = torch.linalg.lu_factor(x, pivot=pivot, out=out) + ret_tuple = namedtuple("lu_factor", ["LU", "p"]) + return ret_tuple(ret.LU, ret.pivots) + + +def lu_solve( + lu: Tuple[torch.Tensor, torch.Tensor], + p: torch.Tensor, + b: torch.Tensor, + /, + *, + out: Optional[torch.Tensor] = None, +) -> torch.Tensor: + return torch.linalg.lu_solve(lu, p, b, out=out) +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, backend_version) def dot( a: torch.Tensor, b: torch.Tensor, diff --git a/ivy/functional/backends/torch/experimental/losses.py b/ivy/functional/backends/torch/experimental/losses.py index adb6d6e76510b..aaab1a95d2eb5 100644 --- a/ivy/functional/backends/torch/experimental/losses.py +++ b/ivy/functional/backends/torch/experimental/losses.py @@ -11,7 +11,7 @@ @with_unsupported_dtypes( - {"2.1.0 and below": ("unit8", "int8", "int16", "int32", "int64", "bool")}, + {"2.2 and below": ("unit8", "int8", "int16", "int32", "int64", "bool")}, backend_version, ) def l1_loss( @@ -30,7 +30,7 @@ def l1_loss( @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "complex", "uint8", "int8", @@ -59,7 +59,7 @@ def smooth_l1_loss( @with_unsupported_dtypes( - {"2.1.0 and below": ("uint8", "int8", "int16", "int32", "int64", "bool")}, + {"2.2 and below": ("uint8", "int8", "int16", "int32", "int64", "bool")}, backend_version, ) def huber_loss( @@ -77,7 +77,7 @@ def huber_loss( @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "float16", "uint8", "int8", @@ -104,7 +104,7 @@ def soft_margin_loss( @with_supported_dtypes( - {"2.1.0 and below": ("float",)}, + {"2.2 and below": ("float",)}, backend_version, ) def kl_div( @@ -124,7 +124,7 @@ def kl_div( @with_supported_device_and_dtypes( { - "2.14.0 and below": { + "2.15.0 and below": { "cpu": ( "float32", "float64", @@ -152,3 +152,24 @@ def poisson_nll_loss( return torch.nn.functional.poisson_nll_loss( input, target, log_input=log_input, full=full, eps=eps, reduction=reduction ) + + +@with_supported_device_and_dtypes( + { + "2.2 and below": { + "cpu": ("float16", "float32", "float64"), + "gpu": ("float16", "float32", "float64"), + } + }, + backend_version, +) +def hinge_embedding_loss( + input: torch.Tensor, + target: torch.Tensor, + *, + margin: float = 1.0, + reduction: str = "mean", +) -> torch.Tensor: + return torch.nn.functional.hinge_embedding_loss( + input, target, margin=margin, reduction=reduction + ) diff --git a/ivy/functional/backends/torch/experimental/manipulation.py b/ivy/functional/backends/torch/experimental/manipulation.py index c25dfdb1ad220..c0164e4c067a6 100644 --- a/ivy/functional/backends/torch/experimental/manipulation.py +++ b/ivy/functional/backends/torch/experimental/manipulation.py @@ -1,5 +1,6 @@ # global from typing import ( + Iterable, Optional, Union, Sequence, @@ -16,7 +17,11 @@ # local -from ivy.func_wrapper import with_unsupported_dtypes, with_supported_dtypes +from ivy.func_wrapper import ( + with_unsupported_dtypes, + with_supported_dtypes, + handle_out_argument, +) from .. import backend_version import ivy from ivy.functional.ivy.experimental.manipulation import ( @@ -59,26 +64,34 @@ def heaviside( @with_supported_dtypes( - {"2.1.0 and below": ("float32", "float64", "complex64", "complex128")}, + {"2.2 and below": ("float32", "float64", "complex64", "complex128")}, backend_version, ) def pad( input: torch.Tensor, - pad_width: Union[Sequence[Sequence[int]], torch.Tensor, int], + pad_width: Union[Iterable[Tuple[int]], int], /, *, mode: Union[ Literal[ "constant", + "dilated", "edge", + "linear_ramp", + "maximum", + "mean", + "median", + "minimum", "reflect", + "symmetric", "wrap", + "empty", ], Callable, ] = "constant", - stat_length: Union[Sequence[torch.Tensor], int] = 1, - constant_values: Number = 0, - end_values: Number = 0, + stat_length: Union[Iterable[Tuple[int]], int] = 1, + constant_values: Union[Iterable[Tuple[Number]], Number] = 0, + end_values: Union[Iterable[Tuple[Number]], Number] = 0, reflect_type: Literal["even", "odd"] = "even", **kwargs: Optional[Any], ) -> torch.Tensor: @@ -122,16 +135,18 @@ def pad( def _check_torch_pad(mode, reflect_type, pad_width, input_shape, constant_values): - pad_width = _to_tf_padding(pad_width, len(input_shape)) - if mode != "constant" and ( - len(input_shape) > 4 - or (len(input_shape) == 4 and len(pad_width) > 3) - or (len(input_shape) == 3 and len(pad_width) > 2) - or (len(input_shape) == 2 and len(pad_width) > 1) - ): + ndim = len(input_shape) + pad_width = _to_tf_padding(pad_width, ndim) + if mode != "constant" and (ndim > 4 or (ndim > 1 and len(pad_width) > ndim - 1)): return False return _check_paddle_pad( - mode, reflect_type, pad_width, input_shape, constant_values, 4 + mode, + reflect_type, + pad_width, + input_shape, + constant_values, + 4, + extend=False, ) and ( mode != "wrap" or all( @@ -227,7 +242,7 @@ def fliplr( fliplr.support_native_out = False -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, backend_version) def i0( x: torch.Tensor, /, @@ -320,7 +335,7 @@ def atleast_3d( return transformed -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, backend_version) def take_along_axis( arr: torch.Tensor, indices: torch.Tensor, @@ -346,7 +361,7 @@ def take_along_axis( if mode == "clip": max_index = arr.shape[axis] - 1 indices = torch.clamp(indices, 0, max_index) - elif mode == "fill" or mode == "drop": + elif mode in {"fill", "drop"}: if "float" in str(arr.dtype) or "complex" in str(arr.dtype): fill_value = float("nan") elif "uint" in str(arr.dtype): @@ -398,7 +413,7 @@ def expand( expand.support_native_out = False -@with_unsupported_dtypes({"2.1.0 and below": ("complex", "float16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("complex", "float16")}, backend_version) def unique_consecutive( x: torch.Tensor, /, @@ -428,7 +443,7 @@ def column_stack( return torch.column_stack(arrays) -@with_supported_dtypes({"2.1.0 and below": ("float32", "float64")}, backend_version) +@with_supported_dtypes({"2.2 and below": ("float32", "float64")}, backend_version) def put_along_axis( arr: torch.Tensor, indices: torch.Tensor, @@ -539,13 +554,13 @@ def take( if ivy.exists(axis): try: x_shape = x.shape[axis] - except Exception: + except Exception as e: rank = len(x.shape) raise IndexError( "IndexError: Dimension out of range" f"(expected to be in range of[-{rank}, {rank-1}]" f", but got {axis})" - ) + ) from e else: x_shape = torch.prod(torch.tensor(x.shape)) @@ -628,3 +643,16 @@ def trim_zeros(a: torch.Tensor, /, *, trim: Optional[str] = "bf") -> torch.Tenso else: last = last - 1 return a[first:last] + + +@handle_out_argument +def unflatten( + x: torch.Tensor, + /, + shape: Tuple[int] = None, + dim: Optional[int] = 0, + *, + out: Optional[torch.Tensor] = None, +) -> torch.Tensor: + res = torch.unflatten(x, dim, shape) + return res diff --git a/ivy/functional/backends/torch/experimental/norms.py b/ivy/functional/backends/torch/experimental/norms.py index 32c5a28dc2561..e17a2c42a8e62 100644 --- a/ivy/functional/backends/torch/experimental/norms.py +++ b/ivy/functional/backends/torch/experimental/norms.py @@ -1,7 +1,7 @@ import torch -from typing import Optional, Tuple +from typing import Literal, Optional, Tuple -from ivy.func_wrapper import with_unsupported_dtypes +from ivy.func_wrapper import with_supported_dtypes, with_unsupported_dtypes from .. import backend_version @@ -18,7 +18,7 @@ def l1_normalize( l1_normalize.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, backend_version) def l2_normalize( x: torch.Tensor, /, @@ -32,7 +32,31 @@ def l2_normalize( l2_normalize.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("bfloat16", "float16")}, backend_version) +@with_supported_dtypes({"2.2 and below": ("float",)}, backend_version) +def local_response_norm( + x: torch.Tensor, + size, + /, + *, + bias: Optional[float] = 1.0, + alpha: Optional[float] = 1.0, + beta: Optional[float] = 0.5, + average: bool = False, + data_format: Optional[Literal["NHWC", "NCHW"]] = "NHWC", + out: Optional[torch.Tensor] = None, +) -> torch.Tensor: + if data_format == "NHWC": + x = torch.permute(x, (0, 3, 1, 2)) + alpha = alpha * size if not average else alpha + ret = torch.nn.functional.local_response_norm( + x, size, alpha=alpha, beta=beta, k=bias + ) + if data_format == "NHWC": + ret = torch.permute(ret, (0, 2, 3, 1)) + return ret + + +@with_unsupported_dtypes({"2.2 and below": ("bfloat16", "float16")}, backend_version) def batch_norm( x: torch.Tensor, mean: torch.Tensor, @@ -50,8 +74,8 @@ def batch_norm( xdims = x.ndim if data_format == "NSC": x = torch.permute(x, dims=(0, xdims - 1, *range(1, xdims - 1))) - runningmean = mean.clone() - runningvariance = variance.clone() + runningmean = mean.detach().clone() + runningvariance = variance.detach().clone() xnormalized = torch.nn.functional.batch_norm( x, runningmean, @@ -78,7 +102,7 @@ def batch_norm( ) -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, backend_version) def instance_norm( x: torch.Tensor, mean: torch.Tensor, @@ -126,7 +150,7 @@ def instance_norm( ) -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, backend_version) def group_norm( x: torch.Tensor, num_groups: int = 1, @@ -151,7 +175,7 @@ def group_norm( return xnormalized -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, backend_version) def lp_normalize( x: torch.Tensor, /, diff --git a/ivy/functional/backends/torch/experimental/random.py b/ivy/functional/backends/torch/experimental/random.py index 7dc5f4b295913..2226b4b75ff7a 100644 --- a/ivy/functional/backends/torch/experimental/random.py +++ b/ivy/functional/backends/torch/experimental/random.py @@ -13,7 +13,7 @@ # dirichlet -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, backend_version) def dirichlet( alpha: Union[torch.tensor, float, Sequence[float]], /, @@ -32,7 +32,7 @@ def dirichlet( ) -@with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, backend_version) def beta( alpha: Union[float, torch.Tensor], beta: Union[float, torch.Tensor], @@ -53,7 +53,7 @@ def beta( return ret -@with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, backend_version) def gamma( alpha: Union[float, torch.Tensor], beta: Union[float, torch.Tensor], @@ -116,16 +116,14 @@ def bernoulli( seed: Optional[int] = None, out: Optional[torch.Tensor] = None, ) -> torch.Tensor: + dtype = dtype if dtype is not None else probs.dtype if seed: torch.manual_seed(seed) if logits is not None: - if not _check_shapes_broadcastable(shape, logits.shape): - shape = logits.shape - elif probs is not None: - if not _check_shapes_broadcastable(shape, probs.shape): - shape = probs.shape - return ( - torch.distributions.bernoulli.Bernoulli(probs=probs, logits=logits) - .sample(shape) - .to(device, dtype) - ) + probs = torch.nn.functional.softmax(logits, -1) + if not _check_shapes_broadcastable(shape, probs.shape): + shape = probs.shape + return torch.bernoulli(probs, out=out).to(device, dtype).broadcast_to(shape) + + +bernoulli.support_native_out = True diff --git a/ivy/functional/backends/torch/experimental/sorting.py b/ivy/functional/backends/torch/experimental/sorting.py index b7af8ee599db1..609eb6b69d3bf 100644 --- a/ivy/functional/backends/torch/experimental/sorting.py +++ b/ivy/functional/backends/torch/experimental/sorting.py @@ -33,7 +33,7 @@ def lexsort( return torch.tensor([0]) _, result = torch.sort(keys[0], dim=axis, stable=True) # result = torch.argsort(keys[0], dim=axis, stable=True) - # only valid for torch > 2.1.0 + # only valid for torch > 2.2 if shape[0] == 1: return result for i in range(1, shape[0]): @@ -41,7 +41,7 @@ def lexsort( ind = key[result] _, temp = torch.sort(ind, dim=axis, stable=True) # temp = torch.argsort(ind, dim=axis, stable=True) - # only valid for torch > 2.1.0 + # only valid for torch > 2.2 result = result[temp] return result diff --git a/ivy/functional/backends/torch/experimental/sparse_array.py b/ivy/functional/backends/torch/experimental/sparse_array.py index 809ac1cd5f997..809913ac67828 100644 --- a/ivy/functional/backends/torch/experimental/sparse_array.py +++ b/ivy/functional/backends/torch/experimental/sparse_array.py @@ -102,13 +102,13 @@ def native_sparse_array_to_indices_values_and_shape(x): if x.layout == torch.sparse_coo: x = x.coalesce() return {"coo_indices": x.indices()}, x.values(), x.size() - elif x.layout == torch.sparse_csr or x.layout == torch.sparse_bsr: + elif x.layout in [torch.sparse_csr, torch.sparse_bsr]: return ( {"crow_indices": x.crow_indices(), "col_indices": x.col_indices()}, x.values(), x.size(), ) - elif x.layout == torch.sparse_bsc or x.layout == torch.sparse_csc: + elif x.layout in [torch.sparse_bsc, torch.sparse_csc]: return ( {"ccol_indices": x.crow_indices(), "row_indices": x.col_indices()}, x.values(), diff --git a/ivy/functional/backends/torch/experimental/statistical.py b/ivy/functional/backends/torch/experimental/statistical.py index 7191a00f41227..f8f44a8f6ad03 100644 --- a/ivy/functional/backends/torch/experimental/statistical.py +++ b/ivy/functional/backends/torch/experimental/statistical.py @@ -3,7 +3,7 @@ import torch # local -from ivy.func_wrapper import with_unsupported_dtypes +from ivy.func_wrapper import with_unsupported_dtypes, with_supported_dtypes from . import backend_version import ivy from ..statistical import _infer_dtype @@ -12,7 +12,7 @@ @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "uint8", "int8", "int16", @@ -139,7 +139,7 @@ def histogram( histogram.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bool")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "bool")}, backend_version) def median( input: torch.Tensor, /, @@ -170,6 +170,7 @@ def median( median.support_native_out = False +@with_supported_dtypes({"2.2 and below": ("float",)}, backend_version) def nanmean( a: torch.Tensor, /, @@ -254,7 +255,7 @@ def _validate_quantile(q): if not (0.0 <= q[i] <= 1.0): return False else: - if not (torch.all(0 <= q) and torch.all(q <= 1)): + if not (torch.all(q >= 0) and torch.all(q <= 1)): return False return True @@ -366,7 +367,7 @@ def _compute_quantile_wrapper( ) -@with_unsupported_dtypes({"2.1.0 and below": ("bfloat16", "float16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("bfloat16", "float16")}, backend_version) def quantile( a: torch.Tensor, q: Union[torch.Tensor, float], @@ -447,7 +448,7 @@ def _nanmedian(input, axis, keepdims): return ret -@with_unsupported_dtypes({"2.1.0 and below": ("bfloat16", "float16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("bfloat16", "float16")}, backend_version) def nanmedian( input: torch.Tensor, /, @@ -535,7 +536,7 @@ def igamma( igamma.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, backend_version) def cov( x1: torch.Tensor, x2: torch.Tensor = None, @@ -592,7 +593,7 @@ def cov( @with_unsupported_dtypes( - {"2.1.0 and below": ("float16", "complex")}, + {"2.2 and below": ("float16", "complex")}, backend_version, ) def cummax( @@ -629,7 +630,7 @@ def cummax( @with_unsupported_dtypes( { - "2.1.0 and below": ("uint8", "float16", "bfloat16"), + "2.2 and below": ("bool", "float16"), "1.12.1 and above": ("uint8", "float16"), }, backend_version, @@ -647,7 +648,7 @@ def cummin( dtype = ivy.as_native_dtype(dtype) if dtype is None: dtype = _infer_dtype(x.dtype) - if not (reverse): + if not reverse: ret = torch.cummin(x, axis)[0] else: ret = torch.cummin(torch.flip(x, dims=(axis,)), axis)[0] diff --git a/ivy/functional/backends/torch/general.py b/ivy/functional/backends/torch/general.py index 41e1a3deb2b26..5aab5d54c01c7 100644 --- a/ivy/functional/backends/torch/general.py +++ b/ivy/functional/backends/torch/general.py @@ -1,10 +1,12 @@ -"""Collection of PyTorch general functions, wrapped to fit Ivy syntax and signature.""" +"""Collection of PyTorch general functions, wrapped to fit Ivy syntax and +signature.""" # global from functools import reduce as _reduce +import functools from numbers import Number from operator import mul -from typing import Optional, Union, Sequence, Callable, List, Tuple +from typing import Callable, List, Optional, Sequence, Tuple, Union try: import functorch @@ -15,9 +17,10 @@ # local import ivy -from ivy.func_wrapper import with_unsupported_dtypes, _update_torch_views -from . import backend_version, is_variable +from ivy.func_wrapper import _update_torch_views, with_unsupported_dtypes + from ...ivy.general import _broadcast_to +from . import backend_version, is_variable torch_scatter = None @@ -53,7 +56,7 @@ def is_native_array(x, /, *, exclusive=False): return False -@with_unsupported_dtypes({"2.1.0 and below": ("complex", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("complex", "bfloat16")}, backend_version) def array_equal(x0: torch.Tensor, x1: torch.Tensor, /) -> bool: x0, x1 = ivy.promote_types_of_inputs(x0, x1) return torch.equal(x0, x1) @@ -91,8 +94,10 @@ def get_item( /, query: Union[torch.Tensor, Tuple], *, - copy: bool = None, + copy: Optional[bool] = None, ) -> torch.Tensor: + if copy: + x = x.clone() return x.__getitem__(query) @@ -187,9 +192,7 @@ def gather( ivy.utils.assertions.check_gather_input_valid(params, indices, axis, batch_dims) result = [] if batch_dims == 0: - result = params[ - (slice(None),) * (axis % params.ndim) + (indices.type(torch.int64),) - ] + result = torch.gather(params, axis, indices, sparse_grad=False, out=out) else: for b in range(batch_dims): if b == 0: @@ -200,12 +203,16 @@ def gather( ] for z in zip_list: p, i = z - r = p[ - (slice(None),) * ((axis - batch_dims) % p.ndim) + (i.type(torch.int64),) - ] + r = torch.gather( + p, (axis - batch_dims) % p.ndim, i, sparse_grad=False, out=False + ) + result.append(r) result = torch.stack(result) result = result.reshape([*params.shape[0:batch_dims], *result.shape[1:]]) + if ivy.exists(out): + return ivy.inplace_update(out, result) + return result @@ -275,6 +282,10 @@ def get_num_dims( return torch.tensor(len(x.shape)) if as_array else len(x.shape) +def size(x: torch.Tensor, /) -> int: + return functools.reduce(mul, x.shape) if len(x.shape) > 0 else 1 + + def inplace_arrays_supported(): return True @@ -351,7 +362,7 @@ def multiprocessing(context: Optional[str] = None): @with_unsupported_dtypes( { - "2.1.0 and below": ("bfloat16",), + "2.2 and below": ("bfloat16",), }, backend_version, ) @@ -384,10 +395,10 @@ def scatter_flat( if torch_scatter is None: try: import torch_scatter as torch_scatter - except ImportError: + except ImportError as e: raise ivy.utils.exceptions.IvyException( "Unable to import torch_scatter, verify this is correctly installed." - ) + ) from e if reduction == "replace": output[indices.type(torch.int64)] = updates res = output @@ -403,7 +414,7 @@ def scatter_flat( @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "float16", "bfloat16", ) @@ -475,10 +486,10 @@ def scatter_nd( if torch_scatter is None: try: import torch_scatter as torch_scatter - except ImportError: + except ImportError as e: raise ivy.utils.exceptions.IvyException( "Unable to import torch_scatter, verify this is correctly installed." - ) + ) from e if reduction == "replace": flat_output[flat_indices_for_flat] = flat_updates flat_scatter = flat_output @@ -510,8 +521,8 @@ def shape( return ivy.Shape(x.shape) -@with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, backend_version) -def vmap( +@with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, backend_version) +def vmap_v_1p13p1_and_below( func: Callable, in_axes: Union[int, Sequence[int], Sequence[None]] = 0, out_axes: int = 0, @@ -528,8 +539,26 @@ def new_fun(*args): return _vmap +@with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, backend_version) +def vmap_v_2p0p0_and_above( + func: Callable, + in_axes: Union[int, Sequence[int], Sequence[None]] = 0, + out_axes: int = 0, +) -> Callable: + @ivy.output_to_native_arrays + @ivy.inputs_to_native_arrays + def _vmap(*args): + def new_fun(*args): + return ivy.to_native(func(*args)) + + new_func = torch.vmap(new_fun, in_axes, out_axes) + return new_func(*args) + + return _vmap + + @with_unsupported_dtypes( - {"2.1.0 and below": ("bfloat16", "float16", "complex", "bool")}, backend_version + {"2.2 and below": ("bfloat16", "float16", "complex", "bool")}, backend_version ) def isin( elements: torch.tensor, diff --git a/ivy/functional/backends/torch/gradients.py b/ivy/functional/backends/torch/gradients.py index af9b5e0b8a403..207794f8c4eab 100644 --- a/ivy/functional/backends/torch/gradients.py +++ b/ivy/functional/backends/torch/gradients.py @@ -1,4 +1,5 @@ -"""Collection of PyTorch gradient functions, wrapped to fit Ivy syntax and signature.""" +"""Collection of PyTorch gradient functions, wrapped to fit Ivy syntax and +signature.""" # global import torch @@ -239,7 +240,7 @@ def _inner(*args, **kwargs): # Avoid zero gradients setting requires_grads as False if isinstance(y, tuple): - y_ones = tuple([torch.ones_like(y_) for y_ in y]) + y_ones = tuple(torch.ones_like(y_) for y_ in y) [y_.requires_grad_() for y_ in y if y_.requires_grad is False] elif y.requires_grad is False: y.requires_grad_() diff --git a/ivy/functional/backends/torch/layers.py b/ivy/functional/backends/torch/layers.py index 2d4b35c5afc60..c470384987513 100644 --- a/ivy/functional/backends/torch/layers.py +++ b/ivy/functional/backends/torch/layers.py @@ -1,4 +1,5 @@ -"""Collection of PyTorch network layers, wrapped to fit Ivy syntax and signature.""" +"""Collection of PyTorch network layers, wrapped to fit Ivy syntax and +signature.""" from typing import Optional, Tuple, Union, Sequence @@ -13,7 +14,7 @@ @with_supported_dtypes( - {"2.1.0 and below": ("float32", "float64", "complex")}, + {"2.2 and below": ("float32", "float64", "complex")}, backend_version, ) def multi_head_attention( @@ -57,7 +58,7 @@ def multi_head_attention( )[1] num_dims = query.ndim if num_dims == 3 and batch_first: - query, key, value = [torch.swapaxes(x, 0, 1) for x in [query, key, value]] + query, key, value = (torch.swapaxes(x, 0, 1) for x in [query, key, value]) ret = torch.nn.functional.multi_head_attention_forward( query, key, @@ -102,9 +103,7 @@ def multi_head_attention( and (not is_causal or not return_attention_weights) and ( ivy.exists(in_proj_weights) - or all( - [ivy.exists(x) for x in [q_proj_weights, k_proj_weights, v_proj_weights]] - ) + or all(ivy.exists(x) for x in [q_proj_weights, k_proj_weights, v_proj_weights]) ) and len( set( @@ -118,7 +117,7 @@ def multi_head_attention( @with_unsupported_dtypes( - {"2.1.0 and below": ("float16", "bfloat16", "complex")}, + {"2.2 and below": ("float16", "bfloat16", "complex")}, backend_version, ) def linear( @@ -135,14 +134,12 @@ def linear( linear.partial_mixed_handler = lambda x, weight, **kwargs: weight.ndim == 2 -def _ff_xd_before_conv(x, filters, dims, filter_format, x_dilations): - if filter_format == "channel_last": - filters = filters.permute(-1, -2, *range(dims)) - +def _x_dil_before_conv(x, dims, x_dilations): # adding dilation to input x_dilations = [x_dilations] * dims if isinstance(x_dilations, int) else x_dilations - for i in range(dims): - if x_dilations[i] > 1: + x_dilations_idxs = [i for i, x_dil in enumerate(x_dilations) if x_dil > 1] + if x_dilations_idxs: + for i in x_dilations_idxs: h = x.shape[2 + i] new_height = h + (h - 1) * (x_dilations[i] - 1) h = torch.eye( @@ -153,7 +150,7 @@ def _ff_xd_before_conv(x, filters, dims, filter_format, x_dilations): x = torch.swapaxes(x, 2 + i, -1) x = torch.matmul(x, h) x = torch.swapaxes(x, -1, 2 + i) - return x, filters + return x def _pad_before_conv( @@ -188,52 +185,76 @@ def _pad_before_conv( if all(pad[0] == pad[1] for pad in padding): return x, [pad[0] for pad in padding] pad_list = [item for sublist in padding for item in sublist[::-1]][::-1] - return torch.nn.functional.pad(x, pad_list), "valid" + return torch.nn.functional.pad(x, pad_list), 0 + + +def _new_pad_before_conv(x, padding): + if isinstance(padding, str): + return x, padding.lower() + elif isinstance(padding, int): + return x, padding + else: + # if symmetric padding is used, use torch's padding in conv function + if all(pad[0] == pad[1] for pad in padding): + return x, [pad[0] for pad in padding] + pad_list = [item for sublist in padding for item in sublist[::-1]][::-1] + return torch.nn.functional.pad(x, pad_list), "valid" -def _pad_before_conv_tranpose( - x, filters, strides, padding, dims, dilations, output_shape, filter_shape +def _tranpose_padding( + x_shape, filter_shape, strides, padding, dims, dilations, output_shape, data_format ): - if output_shape is None: + if output_shape is not None and len(output_shape) > dims: + if data_format[-1] == "C" or data_format == "channel_last": + output_shape = output_shape[1:-1] + elif data_format[1] == "C" or data_format == "channel_first": + output_shape = output_shape[2:] + strides = [strides] * dims if isinstance(strides, int) else strides + dilations = [dilations] * dims if isinstance(dilations, int) else dilations + not_valid_pad = [False] * dims + if isinstance(padding, str): + if output_shape is None: + output_shape = [ + _deconv_length( + x_shape[i], strides[i], filter_shape[i], padding, dilations[i] + ) + for i in range(dims) + ] + if padding == "VALID": + symmetric_padding = [0] * dims + else: + pad_specific = [ + _handle_padding( + output_shape[i], + strides[i], + filter_shape[i] + (filter_shape[i] - 1) * (dilations[i] - 1), + padding, + ) + for i in range(dims) + ] + for i in range(dims): + if pad_specific[i] % 2 != 0: + pad_specific[i] -= 1 + not_valid_pad[i] = True + symmetric_padding = [pad_specific[i] // 2 for i in range(dims)] out_shape = [ - _deconv_length( - x.shape[i + 2], strides[i], filter_shape[i], padding, dilations[i] - ) + (x_shape[i] - 1) * strides[i] + - 2 * symmetric_padding[i] + + dilations[i] * (filter_shape[i] - 1) + + 1 for i in range(dims) ] - output_shape = [x.shape[0], *out_shape, filters.shape[1]] - elif len(output_shape) == dims: - output_shape = [x.shape[0]] + output_shape + [filters.shape[1]] - not_valid_pad = [False] * dims - filter_shape = [ - filter_shape[i] + (filter_shape[i] - 1) * (dilations[i] - 1) - for i in range(dims) - ] - pad_specific = [ - _handle_padding(output_shape[i + 1], strides[i], filter_shape[i], padding) - for i in range(dims) - ] - if padding == "VALID": - padding_list = [0] * dims + output_padding = [max(output_shape[i] - out_shape[i], 0) for i in range(dims)] else: - for i in range(dims): - if pad_specific[i] % 2 != 0: - pad_specific[i] -= 1 - not_valid_pad[i] = True - padding_list = [pad_specific[i] // 2 for i in range(dims)] - out_shape = [ - (x.shape[i + 2] - 1) * strides[i] - - 2 * padding_list[i] - + dilations[i] * (filters.shape[i + 2] - 1) - + 1 - for i in range(dims) - ] - output_padding = [max(output_shape[i + 1] - out_shape[i], 0) for i in range(dims)] - return not_valid_pad, padding_list, output_padding + if isinstance(padding, int): + padding = [[padding, padding]] * dims + symmetric_padding = [max(pad) for pad in padding] + output_padding = [max(pad) - min(pad) for pad in padding] + return not_valid_pad, symmetric_padding, output_padding @with_unsupported_dtypes( - {"2.1.0 and below": ("float16", "bfloat16", "complex")}, + {"2.2 and below": ("float16", "bfloat16", "complex")}, backend_version, ) # noinspection PyUnresolvedReferences @@ -253,7 +274,9 @@ def conv1d( ) -> torch.Tensor: if data_format == "NWC": x = x.permute(0, 2, 1) - x, filters = _ff_xd_before_conv(x, filters, 1, filter_format, x_dilations) + if filter_format == "channel_last": + filters = filters.permute(2, 1, 0) + x = _x_dil_before_conv(x, 1, x_dilations) x, padding = _pad_before_conv( x, filters, strides, padding, 1, dilations, "channel_first" ) @@ -263,9 +286,46 @@ def conv1d( return res +@with_unsupported_dtypes( + {"2.2 and below": ("float16", "bfloat16", "complex")}, + backend_version, +) +def conv1d_v_1p9p0_and_above( + x: torch.Tensor, + filters: torch.Tensor, + strides: Union[int, Tuple[int]], + padding: Union[str, int, Sequence[Tuple[int, int]]], + /, + *, + data_format: str = "NWC", + filter_format: str = "channel_last", + x_dilations: Union[int, Tuple[int]] = 1, + dilations: Union[int, Tuple[int]] = 1, + bias: Optional[torch.Tensor] = None, + out: Optional[torch.Tensor] = None, +) -> torch.Tensor: + if data_format == "NWC": + x = x.permute(0, 2, 1) + if filter_format == "channel_last": + filters = filters.permute(2, 1, 0) + x = _x_dil_before_conv(x, 1, x_dilations) + if padding != "SAME" or all( + s == 1 for s in ([strides] if isinstance(strides, int) else strides) + ): + x, padding = _new_pad_before_conv(x, padding) + else: + x, padding = _pad_before_conv( + x, filters, strides, padding, 1, dilations, "channel_first" + ) + res = torch.nn.functional.conv1d(x, filters, bias, strides, padding, dilations) + if data_format == "NWC": + res = res.permute(0, 2, 1) + return res + + @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "float16", "bfloat16", "complex", @@ -282,6 +342,7 @@ def conv1d_transpose( /, *, output_shape: Optional[Union[ivy.NativeShape, Sequence[int]]] = None, + filter_format: str = "channel_last", data_format: str = "NWC", dilations: Union[int, Tuple[int]] = 1, bias: Optional[torch.Tensor] = None, @@ -289,18 +350,24 @@ def conv1d_transpose( ): if data_format == "NWC": x = x.permute(0, 2, 1) - filters = filters.permute(1, 2, 0) - strides = [strides] if isinstance(strides, int) else strides - dilations = [dilations] if isinstance(dilations, int) else dilations - not_valid_pad, padding_list, output_padding = _pad_before_conv_tranpose( - x, filters, strides, padding, 1, dilations, output_shape, filters.shape[2:] + if filter_format == "channel_last": + filters = filters.permute(2, 1, 0) + not_valid_pad, symmetric_padding, output_padding = _tranpose_padding( + x.shape[2:], + filters.shape[2:], + strides, + padding, + 1, + dilations, + output_shape, + data_format, ) res = torch.nn.functional.conv_transpose1d( x, filters, bias, strides, - padding_list, + symmetric_padding, dilation=dilations, output_padding=output_padding, ) @@ -312,7 +379,7 @@ def conv1d_transpose( @with_unsupported_dtypes( - {"2.1.0 and below": ("float16", "bfloat16", "complex")}, + {"2.2 and below": ("float16", "bfloat16", "complex")}, backend_version, ) # noinspection PyUnresolvedReferences @@ -332,7 +399,9 @@ def conv2d( ) -> torch.Tensor: if data_format == "NHWC": x = x.permute(0, 3, 1, 2) - x, filters = _ff_xd_before_conv(x, filters, 2, filter_format, x_dilations) + if filter_format == "channel_last": + filters = filters.permute(3, 2, 0, 1) + x = _x_dil_before_conv(x, 2, x_dilations) x, padding = _pad_before_conv( x, filters, strides, padding, 2, dilations, "channel_first" ) @@ -342,9 +411,46 @@ def conv2d( return res +@with_unsupported_dtypes( + {"2.2 and below": ("float16", "bfloat16", "complex")}, + backend_version, +) +def conv2d_v_1p9p0_and_above( + x: torch.Tensor, + filters: torch.Tensor, + strides: Union[int, Tuple[int, int]], + padding: Union[str, int, Sequence[Tuple[int, int]]], + /, + *, + data_format: str = "NHWC", + filter_format: str = "channel_last", + x_dilations: Union[int, Tuple[int, int]] = 1, + dilations: Union[int, Tuple[int, int]] = 1, + bias: Optional[torch.Tensor] = None, + out: Optional[torch.Tensor] = None, +) -> torch.Tensor: + if data_format == "NHWC": + x = x.permute(0, 3, 1, 2) + if filter_format == "channel_last": + filters = filters.permute(3, 2, 0, 1) + x = _x_dil_before_conv(x, 2, x_dilations) + if padding != "SAME" or all( + s == 1 for s in ([strides] if isinstance(strides, int) else strides) + ): + x, padding = _new_pad_before_conv(x, padding) + else: + x, padding = _pad_before_conv( + x, filters, strides, padding, 2, dilations, "channel_first" + ) + res = torch.nn.functional.conv2d(x, filters, bias, strides, padding, dilations) + if data_format == "NHWC": + return res.permute(0, 2, 3, 1) + return res + + @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "float16", "bfloat16", "complex", @@ -357,10 +463,11 @@ def conv2d_transpose( x: torch.Tensor, filters: torch.Tensor, strides: Union[int, Tuple[int, int]], - padding: str, + padding: Union[str, int, Sequence[Tuple[int, int]]], /, *, output_shape: Optional[Union[ivy.NativeShape, Sequence[int]]] = None, + filter_format: str = "channel_last", data_format: str = "NHWC", dilations: Union[int, Tuple[int, int]] = 1, bias: Optional[torch.Tensor] = None, @@ -368,19 +475,24 @@ def conv2d_transpose( ): if data_format == "NHWC": x = x.permute(0, 3, 1, 2) - strides = [strides] * 2 if isinstance(strides, int) else strides - dilations = [dilations] * 2 if isinstance(dilations, int) else dilations - filters = filters.permute(2, 3, 0, 1) - not_valid_pad, padding_list, output_padding = _pad_before_conv_tranpose( - x, filters, strides, padding, 2, dilations, output_shape, filters.shape[2:] + if filter_format == "channel_last": + filters = filters.permute(3, 2, 0, 1) + not_valid_pad, symmetric_padding, output_padding = _tranpose_padding( + x.shape[2:], + filters.shape[2:], + strides, + padding, + 2, + dilations, + output_shape, + data_format, ) - res = torch.nn.functional.conv_transpose2d( x, filters, bias, strides, - padding_list, + symmetric_padding, dilation=dilations, output_padding=output_padding, ) @@ -390,13 +502,12 @@ def conv2d_transpose( res = res[..., :-1] if data_format == "NHWC": res = res.permute(0, *range(2, 4), 1) - return res @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "float16", "bfloat16", "complex", @@ -420,7 +531,7 @@ def depthwise_conv2d( dilations = [dilations] * 2 if isinstance(dilations, int) else dilations if data_format == "NHWC": x = x.permute(0, 3, 1, 2) - filters = ivy.squeeze(filters, 3).to_native() if filters.ndim == 4 else filters + filters = ivy.squeeze(filters, axis=3).to_native() if filters.ndim == 4 else filters filters = torch.unsqueeze(filters, -1) dims_in = filters.shape[-2] filters = filters.permute(2, 3, 0, 1) @@ -437,7 +548,7 @@ def depthwise_conv2d( @with_unsupported_dtypes( - {"2.1.0 and below": ("float16", "bfloat16", "complex")}, backend_version + {"2.2 and below": ("float16", "bfloat16", "complex")}, backend_version ) # noinspection PyUnresolvedReferences def conv3d( @@ -456,7 +567,9 @@ def conv3d( ): if data_format == "NDHWC": x = x.permute(0, 4, 1, 2, 3) - x, filters = _ff_xd_before_conv(x, filters, 3, filter_format, x_dilations) + if filter_format == "channel_last": + filters = filters.permute(4, 3, 0, 1, 2) + x = _x_dil_before_conv(x, 3, x_dilations) x, padding = _pad_before_conv( x, filters, strides, padding, 3, dilations, "channel_first" ) @@ -467,7 +580,43 @@ def conv3d( @with_unsupported_dtypes( - {"2.1.0 and below": ("float16", "bfloat16", "complex")}, + {"2.2 and below": ("float16", "bfloat16", "complex")}, backend_version +) +def conv3d_v_1p9p0_and_above( + x: torch.Tensor, + filters: torch.Tensor, + strides: Union[int, Tuple[int, int, int]], + padding: Union[str, int, Sequence[Tuple[int, int]]], + /, + *, + data_format: str = "NDHWC", + filter_format: str = "channel_last", + x_dilations: Union[int, Tuple[int, int, int]] = 1, + dilations: Union[int, Tuple[int, int, int]] = 1, + bias: Optional[torch.Tensor] = None, + out: Optional[torch.Tensor] = None, +): + if data_format == "NDHWC": + x = x.permute(0, 4, 1, 2, 3) + if filter_format == "channel_last": + filters = filters.permute(4, 3, 0, 1, 2) + x = _x_dil_before_conv(x, 3, x_dilations) + if padding != "SAME" or all( + s == 1 for s in ([strides] if isinstance(strides, int) else strides) + ): + x, padding = _new_pad_before_conv(x, padding) + else: + x, padding = _pad_before_conv( + x, filters, strides, padding, 3, dilations, "channel_first" + ) + res = torch.nn.functional.conv3d(x, filters, bias, strides, padding, dilations) + if data_format == "NDHWC": + res = res.permute(0, 2, 3, 4, 1) + return res + + +@with_unsupported_dtypes( + {"2.2 and below": ("float16", "bfloat16", "complex")}, backend_version, ) # noinspection PyUnresolvedReferences @@ -479,6 +628,7 @@ def conv3d_transpose( /, *, output_shape: Optional[Union[ivy.NativeShape, Sequence[int]]] = None, + filter_format: str = "channel_last", data_format: str = "NDHWC", dilations: Union[int, Tuple[int, int, int]] = 1, bias: Optional[torch.Tensor] = None, @@ -486,18 +636,24 @@ def conv3d_transpose( ) -> torch.Tensor: if data_format == "NDHWC": x = x.permute(0, 4, 1, 2, 3) - strides = [strides] * 3 if isinstance(strides, int) else strides - dilations = [dilations] * 3 if isinstance(dilations, int) else dilations - filters = filters.permute(3, 4, 0, 1, 2) - not_valid_pad, padding_list, output_padding = _pad_before_conv_tranpose( - x, filters, strides, padding, 3, dilations, output_shape, filters.shape[2:] + if filter_format == "channel_last": + filters = filters.permute(4, 3, 0, 1, 2) + not_valid_pad, symmetric_padding, output_padding = _tranpose_padding( + x.shape[2:], + filters.shape[2:], + strides, + padding, + 3, + dilations, + output_shape, + data_format, ) res = torch.nn.functional.conv_transpose3d( x, filters, bias, strides, - padding_list, + symmetric_padding, dilation=dilations, output_padding=output_padding, ) @@ -513,7 +669,7 @@ def conv3d_transpose( @with_unsupported_dtypes( - {"2.1.0 and below": ("float16", "bfloat16", "complex")}, + {"2.2 and below": ("float16", "bfloat16", "complex")}, backend_version, ) def conv_general_dilated( @@ -535,25 +691,10 @@ def conv_general_dilated( # permuting dims based on formats if data_format == "channel_last": x = x.permute(0, dims + 1, *range(1, dims + 1)) - if filter_format == "channel_last": filters = filters.permute(-1, -2, *range(dims)) - # adding dilation to input - x_dilations = [x_dilations] * dims if isinstance(x_dilations, int) else x_dilations - for i in range(dims): - if x_dilations[i] > 1: - h = x.shape[2 + i] - new_height = h + (h - 1) * (x_dilations[i] - 1) - h = torch.eye( - new_height, - dtype=x.dtype, - device=ivy.as_native_dev(ivy.default_device()), - )[:: x_dilations[i]] - x = torch.swapaxes(x, 2 + i, -1) - x = torch.matmul(x, h) - x = torch.swapaxes(x, -1, 2 + i) - + x = _x_dil_before_conv(x, dims, x_dilations) x, padding = _pad_before_conv( x, filters, strides, padding, dims, dilations, "channel_first" ) @@ -570,13 +711,68 @@ def conv_general_dilated( res = torch.nn.functional.conv3d( x, filters, bias, strides, padding, dilations, feature_group_count ) + + if data_format == "channel_last": + return res.permute(0, *range(2, dims + 2), 1) + return res + + +@with_unsupported_dtypes( + {"2.2 and below": ("float16", "bfloat16", "complex")}, + backend_version, +) +def conv_general_dilated_v_1p9p0_and_above( + x: torch.Tensor, + filters: torch.Tensor, + strides: Union[int, Tuple[int], Tuple[int, int], Tuple[int, int, int]], + padding: Union[str, int, Sequence[Tuple[int, int]]], + /, + *, + dims: int = 2, + data_format: str = "channel_last", + filter_format: str = "channel_last", + feature_group_count: int = 1, + x_dilations: Union[int, Tuple[int], Tuple[int, int], Tuple[int, int, int]] = 1, + dilations: Union[int, Tuple[int], Tuple[int, int], Tuple[int, int, int]] = 1, + bias: Optional[torch.Tensor] = None, + out: Optional[torch.Tensor] = None, +): + # permuting dims based on formats + if data_format == "channel_last": + x = x.permute(0, dims + 1, *range(1, dims + 1)) + if filter_format == "channel_last": + filters = filters.permute(-1, -2, *range(dims)) + + x = _x_dil_before_conv(x, dims, x_dilations) + if padding != "SAME" or all( + s == 1 for s in ([strides] if isinstance(strides, int) else strides) + ): + x, padding = _new_pad_before_conv(x, padding) + else: + x, padding = _pad_before_conv( + x, filters, strides, padding, dims, dilations, "channel_first" + ) + + if dims == 1: + res = torch.nn.functional.conv1d( + x, filters, bias, strides, padding, dilations, feature_group_count + ) + elif dims == 2: + res = torch.nn.functional.conv2d( + x, filters, bias, strides, padding, dilations, feature_group_count + ) + else: + res = torch.nn.functional.conv3d( + x, filters, bias, strides, padding, dilations, feature_group_count + ) + if data_format == "channel_last": return res.permute(0, *range(2, dims + 2), 1) return res @with_unsupported_dtypes( - {"2.1.0 and below": ("float16", "bfloat16", "complex")}, + {"2.2 and below": ("float16", "bfloat16", "complex")}, backend_version, ) def conv_general_transpose( @@ -588,7 +784,8 @@ def conv_general_transpose( *, dims: int = 2, output_shape: Optional[Union[ivy.NativeShape, Sequence[int]]] = None, - data_format: str = "NDHWC", + filter_format: str = "channel_last", + data_format: str = "channel_first", dilations: Union[int, Tuple[int], Tuple[int, int], Tuple[int, int, int]] = 1, feature_group_count: int = 1, bias: Optional[torch.Tensor] = None, @@ -596,11 +793,17 @@ def conv_general_transpose( ): if data_format == "channel_last": x = x.permute(0, dims + 1, *range(1, dims + 1)) - strides = [strides] * dims if isinstance(strides, int) else strides - dilations = [dilations] * dims if isinstance(dilations, int) else dilations - filters = filters.permute(dims, dims + 1, *range(dims)) - not_valid_pad, padding_list, output_padding = _pad_before_conv_tranpose( - x, filters, strides, padding, dims, dilations, output_shape, filters.shape[2:] + if filter_format == "channel_last": + filters = filters.permute(dims + 1, dims, *range(dims)) + not_valid_pad, symmetric_padding, output_padding = _tranpose_padding( + x.shape[2:], + filters.shape[2:], + strides, + padding, + dims, + dilations, + output_shape, + data_format, ) if dims == 1: res = torch.nn.functional.conv_transpose1d( @@ -608,7 +811,7 @@ def conv_general_transpose( filters, bias, strides, - padding_list, + symmetric_padding, dilation=dilations, output_padding=output_padding, groups=feature_group_count, @@ -621,7 +824,7 @@ def conv_general_transpose( filters, bias, strides, - padding_list, + symmetric_padding, dilation=dilations, output_padding=output_padding, groups=feature_group_count, @@ -636,7 +839,7 @@ def conv_general_transpose( filters, bias, strides, - padding_list, + symmetric_padding, dilation=dilations, output_padding=output_padding, groups=feature_group_count, @@ -665,3 +868,58 @@ def scaled_dot_product_attention_v_2p0p0_and_above( if isinstance(mask, torch.Tensor): mask = torch.where(mask == 0, -torch.inf, 0) return torch.nn.functional.scaled_dot_product_attention(q, k, v, attn_mask=mask) + + +def lstm( + input: torch.Tensor, + initial_states: Tuple[torch.Tensor], + all_weights: Tuple[torch.Tensor], + num_layers: int, + dropout: float, + train: bool, + bidirectional: bool, + batch_first: bool = False, + batch_sizes: Sequence = None, + weights_transposed: bool = False, + has_ih_bias: bool = True, + has_hh_bias: bool = True, +): + if weights_transposed: + # transpose the weights if they are in the wrong format + all_weights = [ + torch.transpose(weight, 1, 0).contiguous() if weight.dim() == 2 else weight + for weight in all_weights + ] + else: + all_weights = list(all_weights) + + if (has_ih_bias and not has_hh_bias) or (has_hh_bias and not has_ih_bias): + # insert zero biases into the weights where one set of biases is not + # used, to avoid stride errors in lstm + shapes = [] + for i in range(2, len(all_weights), 3): + shapes.append(tuple(all_weights[i].shape)) + for i, shape in enumerate(shapes): + idx = (i + 1) * 4 - (1 if has_ih_bias else 2) + all_weights.insert(idx, torch.zeros(shape)) + has_ih_bias = True + has_hh_bias = True + + if initial_states[0].dim() == 2: + initial_states[0] = ivy.expand_dims(initial_states[0]) + if initial_states[1].dim() == 2: + initial_states[1] = ivy.expand_dims(initial_states[1]) + + ret = torch.lstm( + input, + initial_states, + all_weights, + has_ih_bias, + num_layers, + dropout, + train, + bidirectional, + batch_first, + ) + + return ret[0][:, -1], ret[0], (ret[1], ret[2]) diff --git a/ivy/functional/backends/torch/linear_algebra.py b/ivy/functional/backends/torch/linear_algebra.py index d01aad788a9a8..a22ed63c897b1 100644 --- a/ivy/functional/backends/torch/linear_algebra.py +++ b/ivy/functional/backends/torch/linear_algebra.py @@ -18,7 +18,7 @@ @with_unsupported_dtypes( - {"2.1.0 and below": ("bfloat16", "float16", "complex")}, + {"2.2 and below": ("bfloat16", "float16", "complex")}, backend_version, ) def cholesky( @@ -42,7 +42,7 @@ def cholesky( cholesky.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "complex")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "complex")}, backend_version) def cross( x1: torch.Tensor, x2: torch.Tensor, @@ -70,7 +70,7 @@ def cross( cross.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, backend_version) def det(x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None) -> torch.Tensor: return torch.linalg.det(x, out=out) @@ -90,7 +90,7 @@ def diagonal( return torch.diagonal(x, offset=offset, dim1=axis1, dim2=axis2) -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, backend_version) def eigh( x: torch.Tensor, /, *, UPLO: str = "L", out: Optional[torch.Tensor] = None ) -> Tuple[torch.Tensor]: @@ -104,7 +104,7 @@ def eigh( eigh.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, backend_version) def eigvalsh( x: torch.Tensor, /, *, UPLO: str = "L", out: Optional[torch.Tensor] = None ) -> torch.Tensor: @@ -114,7 +114,7 @@ def eigvalsh( eigvalsh.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, backend_version) def inner( x1: torch.Tensor, x2: torch.Tensor, /, *, out: Optional[torch.Tensor] = None ) -> torch.Tensor: @@ -134,7 +134,7 @@ def inner( inner.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, backend_version) def inv( x: torch.Tensor, /, @@ -160,7 +160,7 @@ def inv( @with_unsupported_dtypes( - {"2.1.0 and below": ("float16", "bfloat16", "bool")}, backend_version + {"2.2 and below": ("float16", "bfloat16", "bool")}, backend_version ) def matmul( x1: torch.Tensor, @@ -193,7 +193,7 @@ def matmul( matmul.support_native_out = True -@with_supported_dtypes({"2.1.0 and below": ("float", "complex")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "complex")}, backend_version) def matrix_norm( x: torch.Tensor, /, @@ -201,15 +201,19 @@ def matrix_norm( ord: Union[int, float, Literal[inf, -inf, "fro", "nuc"]] = "fro", axis: Tuple[int, int] = (-2, -1), keepdims: bool = False, + dtype: Optional[torch.dtype] = None, out: Optional[torch.Tensor] = None, ) -> torch.Tensor: - return torch.linalg.matrix_norm(x, ord=ord, dim=axis, keepdim=keepdims, out=out) + ret = torch.linalg.matrix_norm( + x, ord=ord, dim=axis, keepdim=keepdims, dtype=dtype, out=out + ) + return ret matrix_norm.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, backend_version) def eig( x: torch.Tensor, /, *, out: Optional[torch.Tensor] = None ) -> Tuple[torch.Tensor]: @@ -223,7 +227,7 @@ def eig( eig.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, backend_version) def matrix_power( x: torch.Tensor, n: int, /, *, out: Optional[torch.Tensor] = None ) -> torch.Tensor: @@ -233,7 +237,7 @@ def matrix_power( matrix_power.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, backend_version) def matrix_rank( x: torch.Tensor, /, @@ -281,7 +285,7 @@ def matrix_transpose( return torch.swapaxes(x, -1, -2) -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, backend_version) def outer( x1: torch.Tensor, x2: torch.Tensor, @@ -296,7 +300,7 @@ def outer( outer.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, backend_version) def pinv( x: torch.Tensor, /, @@ -312,7 +316,7 @@ def pinv( pinv.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, backend_version) def tensorsolve( x1: torch.Tensor, x2: torch.Tensor, @@ -324,7 +328,7 @@ def tensorsolve( return torch.linalg.tensorsolve(x1, x2, dims=axes) -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, backend_version) def qr( x: torch.Tensor, /, @@ -346,7 +350,7 @@ def qr( return ret -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, backend_version) def slogdet( x: torch.Tensor, /, @@ -361,7 +365,7 @@ def slogdet( slogdet.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, backend_version) def solve( x1: torch.Tensor, x2: torch.Tensor, @@ -397,7 +401,7 @@ def solve( return ret -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, backend_version) def svd( x: torch.Tensor, /, *, full_matrices: bool = True, compute_uv: bool = True ) -> Union[torch.Tensor, Tuple[torch.Tensor, ...]]: @@ -414,7 +418,7 @@ def svd( return results(D) -@with_unsupported_dtypes({"2.0.1 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, backend_version) def svdvals( x: torch.Tensor, /, @@ -430,7 +434,7 @@ def svdvals( # ToDo: re-add int32 support once # (https://github.com/pytorch/pytorch/issues/84530) is fixed -@with_supported_dtypes({"2.1.0 and below": ("float32",)}, backend_version) +@with_supported_dtypes({"2.2 and below": ("float32",)}, backend_version) def tensordot( x1: torch.Tensor, x2: torch.Tensor, @@ -449,7 +453,7 @@ def tensordot( return ret -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, backend_version) def trace( x: torch.Tensor, /, @@ -489,7 +493,15 @@ def vecdot( vecdot.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("integer",)}, backend_version) +@with_unsupported_dtypes( + { + "2.2 and below": ( + "integer", + "complex64", + ) + }, + backend_version, +) def vector_norm( x: torch.Tensor, /, @@ -515,7 +527,7 @@ def vector_norm( # ----- # -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, backend_version) def diag( x: torch.Tensor, /, @@ -526,7 +538,7 @@ def diag( return torch.diag(x, diagonal=k) -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, backend_version) def vander( x: torch.tensor, /, @@ -552,7 +564,7 @@ def vander( @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "complex", "unsigned", ) diff --git a/ivy/functional/backends/torch/manipulation.py b/ivy/functional/backends/torch/manipulation.py index b1676faacc2f5..8c4bdbb9eda22 100644 --- a/ivy/functional/backends/torch/manipulation.py +++ b/ivy/functional/backends/torch/manipulation.py @@ -1,7 +1,7 @@ # global import math from numbers import Number -from typing import Union, Optional, Tuple, List, Sequence, Iterable +from typing import Iterable, List, Optional, Sequence, Tuple, Union import torch @@ -11,6 +11,7 @@ # noinspection PyProtectedMember from ivy.functional.ivy.manipulation import _calculate_out_shape + from . import backend_version @@ -32,14 +33,7 @@ def concat( out: Optional[torch.Tensor] = None, ) -> torch.Tensor: if axis is None: - is_tuple = type(xs) is tuple - if is_tuple: - xs = list(xs) - for i in range(len(xs)): - xs[i] = torch.flatten(xs[i]) - if is_tuple: - xs = tuple(xs) - axis = 0 + return torch.cat([torch.flatten(x) for x in xs], dim=0, out=out) return torch.cat(xs, dim=axis, out=out) @@ -68,7 +62,7 @@ def flip( out: Optional[torch.Tensor] = None, ) -> torch.Tensor: if copy: - x = x.clone().detach() + x = x.clone() num_dims = len(x.shape) if not num_dims: return x @@ -84,6 +78,7 @@ def flip( return torch.flip(x, new_axis) +@with_unsupported_dtypes({"2.1.2 and below": ("bfloat16", "float16")}, backend_version) def permute_dims( x: torch.Tensor, /, @@ -92,9 +87,16 @@ def permute_dims( copy: Optional[bool] = None, out: Optional[torch.Tensor] = None, ) -> torch.Tensor: + if copy: + newarr = torch.clone(x).detach() + return torch.permute(newarr, axes) return torch.permute(x, axes) +@with_unsupported_dtypes( + {"2.2 and below": ("bfloat16",)}, + backend_version, +) def reshape( x: torch.Tensor, /, @@ -105,6 +107,8 @@ def reshape( allowzero: bool = True, out: Optional[torch.Tensor] = None, ) -> torch.Tensor: + if copy: + x = x.clone() ivy.utils.assertions.check_elem_in_list(order, ["C", "F"]) if not allowzero: shape = [ @@ -153,12 +157,10 @@ def squeeze( f"Expected size of axis to be 1 but was {x.shape[axis]}" ) return torch.squeeze(x, axis) + if copy: + x = x.clone() if axis is None: - if copy: - newarr = torch.clone(x) - return torch.squeeze(newarr) return torch.squeeze(x) - newarr = torch.clone(x) if isinstance(axis, tuple): axis = list(axis) normalise_axis = [ @@ -175,12 +177,7 @@ def squeeze( f" {shape}" ) else: - if copy: - newarr = torch.squeeze(newarr, i) - else: - x = torch.squeeze(x, i) - if copy: - return newarr + x = torch.squeeze(x, i) return x @@ -241,13 +238,15 @@ def split( torch.tensor(dim_size) / torch.tensor(num_or_size_splits) ) elif isinstance(num_or_size_splits, list): + if num_or_size_splits[-1] == -1: + # infer the final size split + remaining_size = dim_size - sum(num_or_size_splits[:-1]) + num_or_size_splits[-1] = remaining_size num_or_size_splits = tuple(num_or_size_splits) return list(torch.split(x, num_or_size_splits, axis)) -@with_unsupported_dtypes( - {"2.1.0 and below": ("int8", "int16", "uint8")}, backend_version -) +@with_unsupported_dtypes({"2.2 and below": ("int8", "int16", "uint8")}, backend_version) def repeat( x: torch.Tensor, /, @@ -315,7 +314,7 @@ def swapaxes( @with_unsupported_dtypes( - {"2.1.0 and below": ("bool", "float16", "complex")}, backend_version + {"2.2 and below": ("bool", "float16", "complex")}, backend_version ) def clip( x: torch.Tensor, diff --git a/ivy/functional/backends/torch/module.py b/ivy/functional/backends/torch/module.py new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/ivy/functional/backends/torch/norms.py b/ivy/functional/backends/torch/norms.py index 704a2a4d506c0..d6c2793b68cb0 100644 --- a/ivy/functional/backends/torch/norms.py +++ b/ivy/functional/backends/torch/norms.py @@ -5,7 +5,7 @@ from . import backend_version -@with_unsupported_dtypes({"2.1.0 and below": ("bfloat16", "float16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("bfloat16", "float16")}, backend_version) def layer_norm( x: torch.Tensor, normalized_idxs: List[int], diff --git a/ivy/functional/backends/torch/random.py b/ivy/functional/backends/torch/random.py index 2fac63ffdd2af..f4ee4e0cdf2ad 100644 --- a/ivy/functional/backends/torch/random.py +++ b/ivy/functional/backends/torch/random.py @@ -1,4 +1,5 @@ -"""Collection of PyTorch random functions, wrapped to fit Ivy syntax and signature.""" +"""Collection of PyTorch random functions, wrapped to fit Ivy syntax and +signature.""" # global import torch @@ -62,7 +63,7 @@ def random_normal( random_normal.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, backend_version) def multinomial( population_size: int, num_samples: int, @@ -115,7 +116,7 @@ def randint( return (torch.rand(shape, device=device) * rand_range + low).to(dtype) -def seed(*, seed_value: int = 0) -> None: +def seed(*, seed_value: int = 0): torch.manual_seed(seed_value) torch.cuda.manual_seed(seed_value) if hasattr(torch.backends, "mps"): diff --git a/ivy/functional/backends/torch/searching.py b/ivy/functional/backends/torch/searching.py index 05951657703f7..5194967076efa 100644 --- a/ivy/functional/backends/torch/searching.py +++ b/ivy/functional/backends/torch/searching.py @@ -13,7 +13,15 @@ # ------------------ # -@with_unsupported_dtypes({"2.1.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes( + { + "2.2 and below": ( + "complex", + "bool", + ) + }, + backend_version, +) def argmax( x: torch.Tensor, /, @@ -41,7 +49,15 @@ def argmax( return ret -@with_unsupported_dtypes({"2.1.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes( + { + "2.2 and below": ( + "complex", + "bool", + ) + }, + backend_version, +) def argmin( x: torch.Tensor, /, diff --git a/ivy/functional/backends/torch/set.py b/ivy/functional/backends/torch/set.py index 5eb412bab77be..a7eee8289918f 100644 --- a/ivy/functional/backends/torch/set.py +++ b/ivy/functional/backends/torch/set.py @@ -11,7 +11,7 @@ @with_unsupported_dtypes( { - "2.1.0 and below": ("complex", "float16"), + "2.2 and below": ("complex", "float16"), }, backend_version, ) @@ -63,10 +63,10 @@ def unique_all( values_ = torch.moveaxis(values, axis, 0) values_ = torch.reshape(values_, (values_.shape[0], -1)) sort_idx = torch.tensor( - [i[0] for i in sorted(list(enumerate(values_)), key=lambda x: tuple(x[1]))] + [i[0] for i in sorted(enumerate(values_), key=lambda x: tuple(x[1]))] ) ivy_torch = ivy.current_backend() - values = ivy_torch.gather(values, sort_idx, axis=axis) + values = values.index_select(dim=axis, index=sort_idx) counts = ivy_torch.gather(counts, sort_idx) indices = ivy_torch.gather(indices, sort_idx) inv_sort_idx = ivy_torch.invert_permutation(sort_idx) @@ -84,7 +84,7 @@ def unique_all( @with_unsupported_dtypes( { - "2.1.0 and below": ("float16",), + "2.2 and below": ("float16",), }, backend_version, ) @@ -98,7 +98,7 @@ def unique_counts(x: torch.Tensor, /) -> Tuple[torch.Tensor, torch.Tensor]: @with_unsupported_dtypes( { - "2.1.0 and below": ("float16",), + "2.2 and below": ("float16",), }, backend_version, ) @@ -114,7 +114,7 @@ def unique_inverse( x = torch.flatten(x) axis = 0 - values, inverse_indices = torch.unique(x, return_inverse=True, axis=axis) + values, inverse_indices = torch.unique(x, return_inverse=True, dim=axis) nan_idx = torch.isnan(x) if nan_idx.any(): inverse_indices[nan_idx] = torch.where(torch.isnan(values))[0][0] @@ -124,7 +124,7 @@ def unique_inverse( @with_unsupported_dtypes( { - "2.1.0 and below": ("float16", "complex"), + "2.2 and below": ("float16", "complex"), }, backend_version, ) diff --git a/ivy/functional/backends/torch/sorting.py b/ivy/functional/backends/torch/sorting.py index fa9e1c85254ca..eac46ae04472f 100644 --- a/ivy/functional/backends/torch/sorting.py +++ b/ivy/functional/backends/torch/sorting.py @@ -8,7 +8,7 @@ from . import backend_version -@with_unsupported_dtypes({"2.1.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("complex",)}, backend_version) def argsort( x: torch.Tensor, /, @@ -19,7 +19,7 @@ def argsort( out: Optional[torch.Tensor] = None, ) -> torch.Tensor: if out is not None: - out = tuple([torch.zeros(x.shape, dtype=x.dtype), out.long()]) + out = (torch.zeros(x.shape, dtype=x.dtype), out.long()) _, sorted_indices = torch.sort( x, dim=axis, descending=descending, stable=stable, out=out ) @@ -29,7 +29,7 @@ def argsort( argsort.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("complex",)}, backend_version) def sort( x: torch.Tensor, /, @@ -40,7 +40,7 @@ def sort( out: Optional[torch.Tensor] = None, ) -> torch.Tensor: if out is not None: - out = tuple([out, torch.zeros(out.shape, dtype=torch.long)]) + out = (out, torch.zeros(out.shape, dtype=torch.long)) sorted_tensor, _ = torch.sort( x, dim=axis, descending=descending, stable=stable, out=out ) @@ -51,7 +51,7 @@ def sort( # msort -@with_unsupported_dtypes({"2.1.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("complex",)}, backend_version) def msort( a: Union[torch.Tensor, list, tuple], /, *, out: Optional[torch.Tensor] = None ) -> torch.Tensor: @@ -61,7 +61,7 @@ def msort( msort.support_native_out = True -@with_unsupported_dtypes({"2.1.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("complex",)}, backend_version) def searchsorted( x: torch.Tensor, v: torch.Tensor, @@ -72,14 +72,12 @@ def searchsorted( ret_dtype: torch.dtype = torch.int64, out: Optional[torch.Tensor] = None, ) -> torch.Tensor: - assert ivy.is_int_dtype(ret_dtype), ValueError( + assert ivy.is_int_dtype(ret_dtype), TypeError( "only Integer data types are supported for ret_dtype." ) if sorter is not None: sorter_dtype = ivy.as_native_dtype(sorter.dtype) - assert ivy.is_int_dtype(sorter_dtype) and not ivy.is_uint_dtype( - sorter_dtype - ), TypeError( + assert ivy.is_int_dtype(sorter_dtype), TypeError( f"Only signed integer data type for sorter is allowed, got {sorter_dtype }." ) if sorter_dtype is not torch.int64: diff --git a/ivy/functional/backends/torch/statistical.py b/ivy/functional/backends/torch/statistical.py index 33ef586c05b28..3fcfbd15ee414 100644 --- a/ivy/functional/backends/torch/statistical.py +++ b/ivy/functional/backends/torch/statistical.py @@ -14,13 +14,15 @@ # -------------------# -@with_unsupported_dtypes({"2.1.0 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("complex",)}, backend_version) def min( x: torch.Tensor, /, *, axis: Optional[Union[int, Sequence[int]]] = None, keepdims: bool = False, + initial: Optional[Union[int, float, complex]] = None, + where: Optional[torch.Tensor] = None, out: Optional[torch.Tensor] = None, ) -> torch.Tensor: if axis == (): @@ -28,9 +30,22 @@ def min( return ivy.inplace_update(out, x) else: return x + if where is not None: + max_val = ( + ivy.iinfo(x.dtype).max + if ivy.is_int_dtype(x.dtype) + else ivy.finfo(x.dtype).max + ) + val = torch.ones_like(x) * max_val + val = val.type(x.dtype) + x = torch.where(where, x, val) if not keepdims and not axis and axis != 0: - return torch.amin(input=x, out=out) - return torch.amin(input=x, dim=axis, keepdim=keepdims, out=out) + result = torch.amin(input=x, out=out) + result = torch.amin(input=x, dim=axis, keepdim=keepdims, out=out) + if initial is not None: + initial = torch.tensor(initial, dtype=x.dtype) + result = torch.minimum(result, initial) + return result min.support_native_out = True @@ -66,7 +81,7 @@ def max( max.support_native_out = True -@with_supported_dtypes({"2.1.0 and below": ("float", "complex")}, backend_version) +@with_supported_dtypes({"2.2 and below": ("float", "complex")}, backend_version) def mean( x: torch.Tensor, /, @@ -78,7 +93,7 @@ def mean( if axis is None: num_dims = len(x.shape) axis = list(range(num_dims)) - if axis == () or axis == []: + if axis in [(), []]: if ivy.exists(out): return ivy.inplace_update(out, x) else: @@ -101,7 +116,7 @@ def _infer_dtype(dtype: torch.dtype) -> torch.dtype: # the function to break the upcasting rule defined in the Array API Standard @with_unsupported_dtypes( { - "2.1.0 and below": ("uint8", "float16", "bfloat16"), + "2.2 and below": ("uint8", "float16", "bfloat16"), }, backend_version, ) @@ -129,7 +144,7 @@ def prod( @with_unsupported_dtypes( - {"2.1.0 and below": ("int8", "int16", "int32", "int64", "float16")}, + {"2.2 and below": ("int8", "int16", "int32", "int64", "float16")}, backend_version, ) def std( @@ -166,7 +181,9 @@ def std( # Function does support uint8, but allowing support for unsigned will cause # the function to break the upcasting rule defined in the Array API Standard -@with_unsupported_dtypes({"2.1.0 and below": ("uint8",)}, backend_version) +@with_unsupported_dtypes( + {"2.2 and below": ("uint8", "float16", "bfloat16")}, backend_version +) def sum( x: torch.Tensor, /, @@ -228,7 +245,7 @@ def var( # TODO: bfloat16 support is added in PyTorch 1.12.1 @with_unsupported_dtypes( { - "2.1.0 and below": ("uint8", "float16", "bfloat16"), + "2.2 and below": ("uint8", "float16", "bfloat16", "bool"), }, backend_version, ) @@ -275,8 +292,8 @@ def cumprod( # TODO: bfloat16 support is added in PyTorch 1.12.1 @with_unsupported_dtypes( { - "1.12.1 and below": ("uint8", "float16", "bfloat16"), - "1.12.1 and above": ("uint8", "float16"), + "1.12.1 and below": ("uint8", "bool", "float16", "bfloat16"), + "1.12.1 and above": ("uint8", "bool", "float16"), }, backend_version, ) @@ -319,7 +336,7 @@ def cumsum( @with_unsupported_dtypes( - {"2.1.0 and below": ("float16",)}, + {"2.2 and below": ("float16",)}, backend_version, ) def einsum( diff --git a/ivy/functional/frontends/__init__.py b/ivy/functional/frontends/__init__.py index ce11fd0eadd96..6e71d220f4e32 100644 --- a/ivy/functional/frontends/__init__.py +++ b/ivy/functional/frontends/__init__.py @@ -2,15 +2,16 @@ versions = { - "torch": "2.1.0", - "tensorflow": "2.14.0", + "torch": "2.2", + "tensorflow": "2.15.0", "numpy": "1.25.2", - "jax": "0.4.14", + "jax": "0.4.24", "scipy": "1.10.1", - "paddle": "2.5.1", + "paddle": "2.6.0", "sklearn": "1.3.0", "xgboost": "1.7.6", "torchvision": "0.15.2.", + "mindspore": "2.0.0", } @@ -27,6 +28,7 @@ def fn_name_from_version_specific_fn_name(name, version): the version is inferred by importing the framework in the case of frontend version support and defaults to the highest available version in case of import failure + Returns ------- the name of the original function which will then point to the version specific diff --git a/ivy/functional/frontends/jax/array.py b/ivy/functional/frontends/jax/array.py index 2de2e3252c0f5..2e049123c166a 100644 --- a/ivy/functional/frontends/jax/array.py +++ b/ivy/functional/frontends/jax/array.py @@ -74,7 +74,7 @@ def astype(self, dtype): f"Dtype {self.dtype} is not castable to {dtype}" ) - @with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") + @with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") def argmax( self, /, @@ -90,7 +90,7 @@ def argmax( keepdims=keepdims, ) - @with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") + @with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") def argmin( self, /, @@ -410,6 +410,9 @@ def var( where=where, ) + def swapaxes(self, axis1, axis2): + return jax_frontend.numpy.swapaxes(self, axis1=axis1, axis2=axis2) + # Jax supports DeviceArray from 0.4.13 and below # Hence aliasing it here diff --git a/ivy/functional/frontends/jax/lax/control_flow_operators.py b/ivy/functional/frontends/jax/lax/control_flow_operators.py index 107c87e6eb08a..e9f58b95ddbac 100644 --- a/ivy/functional/frontends/jax/lax/control_flow_operators.py +++ b/ivy/functional/frontends/jax/lax/control_flow_operators.py @@ -19,7 +19,7 @@ def cond(pred, true_fun, false_fun, *operands, operand=None, linear=None): @to_ivy_arrays_and_back def fori_loop(lower, upper, body_fun, init_val): - if not (callable(body_fun)): + if not callable(body_fun): raise ivy.exceptions.IvyException( "jax.lax.fori_loop: Argument body_fun should be callable." ) diff --git a/ivy/functional/frontends/jax/lax/operators.py b/ivy/functional/frontends/jax/lax/operators.py index fb1285179cfe5..9f1cc9b554f63 100644 --- a/ivy/functional/frontends/jax/lax/operators.py +++ b/ivy/functional/frontends/jax/lax/operators.py @@ -157,7 +157,7 @@ def broadcast(operand, sizes): @with_supported_dtypes( { - "0.4.19 and below": ( + "0.4.24 and below": ( "float16", "float32", "float64", @@ -309,7 +309,7 @@ def cosh(x): @with_unsupported_dtypes( - {"0.4.19 and below": ("bfloat16", "float16", "bool", "complex64", "complex128")}, + {"0.4.24 and below": ("bfloat16", "float16", "bool", "complex64", "complex128")}, "jax", ) @to_ivy_arrays_and_back @@ -400,7 +400,7 @@ def erf(x): @with_supported_dtypes( { - "0.4.19 and below": ( + "0.4.24 and below": ( "float16", "float32", "float64", @@ -465,7 +465,7 @@ def imag(x): @with_unsupported_dtypes( - {"0.4.19 and below": ("bool", "bfloat16")}, + {"0.4.24 and below": ("bool", "bfloat16")}, "jax", ) @to_ivy_arrays_and_back diff --git a/ivy/functional/frontends/jax/nn/non_linear_activations.py b/ivy/functional/frontends/jax/nn/non_linear_activations.py index 7d1cf70ce0660..afbaac59e1948 100644 --- a/ivy/functional/frontends/jax/nn/non_linear_activations.py +++ b/ivy/functional/frontends/jax/nn/non_linear_activations.py @@ -289,7 +289,7 @@ def sigmoid(x): @with_supported_dtypes( - {"0.4.19 and below": ("complex", "float")}, + {"0.4.24 and below": ("complex", "float")}, "jax", ) @to_ivy_arrays_and_back diff --git a/ivy/functional/frontends/jax/numpy/__init__.py b/ivy/functional/frontends/jax/numpy/__init__.py index ec899befa786d..2512624217a74 100644 --- a/ivy/functional/frontends/jax/numpy/__init__.py +++ b/ivy/functional/frontends/jax/numpy/__init__.py @@ -390,8 +390,8 @@ def promote_types_jax( type2: Union[ivy.Dtype, ivy.NativeDtype], /, ) -> ivy.Dtype: - """ - Promote the datatypes type1 and type2, returning the data type they promote to. + """Promote the datatypes type1 and type2, returning the data type they + promote to. Parameters ---------- @@ -399,6 +399,7 @@ def promote_types_jax( the first of the two types to promote type2 the second of the two types to promote + Returns ------- ret @@ -406,8 +407,10 @@ def promote_types_jax( """ try: ret = jax_promotion_table[(ivy.as_ivy_dtype(type1), ivy.as_ivy_dtype(type2))] - except KeyError: - raise ivy.utils.exceptions.IvyException("these dtypes are not type promotable") + except KeyError as e: + raise ivy.utils.exceptions.IvyException( + "these dtypes are not type promotable" + ) from e return ret @@ -423,9 +426,8 @@ def promote_types_of_jax_inputs( x2: Union[ivy.Array, Number, Iterable[Number]], /, ) -> Tuple[ivy.Array, ivy.Array]: - """ - Promote the dtype of the given native array inputs to a common dtype based on type - promotion rules. + """Promote the dtype of the given native array inputs to a common dtype + based on type promotion rules. While passing float or integer values or any other non-array input to this function, it should be noted that the return will be an diff --git a/ivy/functional/frontends/jax/numpy/creation.py b/ivy/functional/frontends/jax/numpy/creation.py index d82c05b0b3569..1b72e1ea7819b 100644 --- a/ivy/functional/frontends/jax/numpy/creation.py +++ b/ivy/functional/frontends/jax/numpy/creation.py @@ -17,7 +17,7 @@ @with_unsupported_device_and_dtypes( { - "0.4.19 and below": { + "0.4.24 and below": { "cpu": ( "float16", "bflooat16", @@ -45,13 +45,13 @@ def array(object, dtype=None, copy=True, order="K", ndmin=0): raise ivy.utils.exceptions.IvyNotImplementedException( "Only implemented for order='K'" ) - ret = ivy.array(object, dtype=dtype) + device = ivy.default_device() + if ivy.is_array(object): + device = ivy.dev(object) + ret = ivy.array(object, dtype=dtype, device=device) if ivy.get_num_dims(ret) < ndmin: ret = ivy.expand_dims(ret, axis=list(range(ndmin - ivy.get_num_dims(ret)))) - default_device = ivy.default_device() - ret = ivy.to_device(ret, default_device) - if ret.shape == () and dtype is None: return Array(ret, weak_type=True) return Array(ret) @@ -196,7 +196,7 @@ def iterable(y): @to_ivy_arrays_and_back @with_unsupported_dtypes( { - "0.4.19 and below": ( + "0.4.24 and below": ( "float16", "bfloat16", ) @@ -217,7 +217,7 @@ def linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None, axis @to_ivy_arrays_and_back @with_unsupported_dtypes( { - "0.4.19 and below": ( + "0.4.24 and below": ( "float16", "bfloat16", ) @@ -275,7 +275,7 @@ def setdiff1d(ar1, ar2, assume_unique=False, *, size=None, fill_value=None): if size is None: return ar1[mask] else: - if not (assume_unique): + if not assume_unique: # Set mask to zero at locations corresponding to unique() padding. n_unique = ar1.size + 1 - (ar1 == ar1[0]).sum(dtype=ivy.int64) mask = ivy.where(ivy.arange(ar1.size) < n_unique, mask, False) diff --git a/ivy/functional/frontends/jax/numpy/dtype.py b/ivy/functional/frontends/jax/numpy/dtype.py index 966610e2464e4..081a3c468e272 100644 --- a/ivy/functional/frontends/jax/numpy/dtype.py +++ b/ivy/functional/frontends/jax/numpy/dtype.py @@ -37,7 +37,7 @@ def can_cast(from_, to, casting="safe"): "to must be one of dtype, or dtype specifier" ) - if casting == "no" or casting == "equiv": + if casting in ["no", "equiv"]: return from_ == to if casting == "safe": @@ -73,7 +73,7 @@ def can_cast(from_, to, casting="safe"): @with_supported_dtypes( - {"2.14.0 and below": ("float16", "float32", "float64")}, + {"2.15.0 and below": ("float16", "float32", "float64")}, "jax", ) @to_ivy_arrays_and_back @@ -82,7 +82,7 @@ def finfo(dtype): @with_supported_dtypes( - {"2.14.0 and below": ("integer",)}, + {"2.15.0 and below": ("integer",)}, "jax", ) @to_ivy_arrays_and_back diff --git a/ivy/functional/frontends/jax/numpy/fft.py b/ivy/functional/frontends/jax/numpy/fft.py index 4291615222f8e..d1500f394e5e1 100644 --- a/ivy/functional/frontends/jax/numpy/fft.py +++ b/ivy/functional/frontends/jax/numpy/fft.py @@ -19,19 +19,19 @@ def fft2(a, s=None, axes=(-2, -1), norm=None): @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") +@with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") def fftfreq(n, d=1.0, *, dtype=None): if not isinstance( n, (int, type(ivy.int8), type(ivy.int16), type(ivy.int32), type(ivy.int64)) ): - raise ValueError("n should be an integer") + raise TypeError("n should be an integer") dtype = ivy.float64 if dtype is None else ivy.as_ivy_dtype(dtype) N = (n - 1) // 2 + 1 val = 1.0 / (n * d) - results = ivy.zeros(tuple([n]), dtype=dtype) + results = ivy.zeros((n,), dtype=dtype) results[:N] = ivy.arange(0, N, dtype=dtype) results[N:] = ivy.arange(-(n // 2), 0, dtype=dtype) diff --git a/ivy/functional/frontends/jax/numpy/indexing.py b/ivy/functional/frontends/jax/numpy/indexing.py index 54e7ee79028ae..1e0b778bd9aa6 100644 --- a/ivy/functional/frontends/jax/numpy/indexing.py +++ b/ivy/functional/frontends/jax/numpy/indexing.py @@ -52,7 +52,7 @@ def __getitem__(self, key): newobj = _make_1d_grid_from_slice(item) item_ndim = 0 elif isinstance(item, str): - raise ValueError("string directive must be placed at the beginning") + raise TypeError("string directive must be placed at the beginning") else: newobj = array(item, copy=False) item_ndim = newobj.ndim diff --git a/ivy/functional/frontends/jax/numpy/linalg.py b/ivy/functional/frontends/jax/numpy/linalg.py index 6700c92f33cef..57c69ee5b1596 100644 --- a/ivy/functional/frontends/jax/numpy/linalg.py +++ b/ivy/functional/frontends/jax/numpy/linalg.py @@ -88,7 +88,7 @@ def multi_dot(arrays, *, precision=None): @to_ivy_arrays_and_back @with_supported_dtypes( - {"0.4.19 and below": ("float32", "float64")}, + {"0.4.24 and below": ("float32", "float64")}, "jax", ) def norm(x, ord=None, axis=None, keepdims=False): @@ -127,7 +127,7 @@ def svd(a, /, *, full_matrices=True, compute_uv=True, hermitian=None): @to_ivy_arrays_and_back -@with_unsupported_dtypes({"0.4.19 and below": ("float16", "bfloat16")}, "jax") +@with_unsupported_dtypes({"0.4.24 and below": ("float16", "bfloat16")}, "jax") def tensorinv(a, ind=2): old_shape = ivy.shape(a) prod = 1 @@ -139,7 +139,7 @@ def tensorinv(a, ind=2): raise ValueError("Invalid ind argument.") a = ivy.reshape(a, shape=(prod, -1)) ia = ivy.inv(a) - new_shape = tuple([*invshape]) + new_shape = (*invshape,) return Array(ivy.reshape(ia, shape=new_shape)) diff --git a/ivy/functional/frontends/jax/numpy/logic.py b/ivy/functional/frontends/jax/numpy/logic.py index 171f864c1dad0..1c5b45f0d80ed 100644 --- a/ivy/functional/frontends/jax/numpy/logic.py +++ b/ivy/functional/frontends/jax/numpy/logic.py @@ -101,7 +101,7 @@ def equal(x1, x2, /): @to_ivy_arrays_and_back -@with_unsupported_dtypes({"0.4.19 and below": ("bfloat16",)}, "jax") +@with_unsupported_dtypes({"0.4.24 and below": ("bfloat16",)}, "jax") def fromfunction(function, shape, *, dtype=float, **kwargs): def canonicalize_shape(shape, context="shape argument"): if isinstance(shape, int): @@ -285,7 +285,7 @@ def right_shift(x1, x2, /): @to_ivy_arrays_and_back -@with_unsupported_dtypes({"0.4.19 and below": ("bfloat16", "bool")}, "jax") +@with_unsupported_dtypes({"0.4.24 and below": ("bfloat16", "bool")}, "jax") def setxor1d(ar1, ar2, assume_unique=False): common_dtype = ivy.promote_types(ivy.dtype(ar1), ivy.dtype(ar2)) ar1 = ivy.asarray(ar1, dtype=common_dtype) diff --git a/ivy/functional/frontends/jax/numpy/manipulations.py b/ivy/functional/frontends/jax/numpy/manipulations.py index 374ceaa04ce82..61fe0fe6279ff 100644 --- a/ivy/functional/frontends/jax/numpy/manipulations.py +++ b/ivy/functional/frontends/jax/numpy/manipulations.py @@ -37,6 +37,21 @@ def atleast_3d(*arys): return ivy.atleast_3d(*arys) +@to_ivy_arrays_and_back +def bartlett(M): + if M < 1: + return ivy.array([]) + if M == 1: + return ivy.ones(M, dtype=ivy.float64) + res = ivy.arange(0, M) + res = ivy.where( + ivy.less_equal(res, (M - 1) / 2.0), + 2.0 * res / (M - 1), + 2.0 - 2.0 * res / (M - 1), + ) + return res + + @to_ivy_arrays_and_back def blackman(M): if M < 1: @@ -316,7 +331,7 @@ def transpose(a, axes=None): return a if not axes: axes = list(range(len(a.shape)))[::-1] - if type(axes) is int: + if isinstance(axes, int): axes = [axes] if (len(a.shape) == 0 and not axes) or (len(a.shape) == 1 and axes[0] == 0): return a diff --git a/ivy/functional/frontends/jax/numpy/mathematical_functions.py b/ivy/functional/frontends/jax/numpy/mathematical_functions.py index 59aab1bf27a48..0fee3841f509c 100644 --- a/ivy/functional/frontends/jax/numpy/mathematical_functions.py +++ b/ivy/functional/frontends/jax/numpy/mathematical_functions.py @@ -76,7 +76,7 @@ def around(a, decimals=0, out=None): @with_unsupported_dtypes( - {"0.4.19 and below": ("bfloat16",)}, + {"0.4.24 and below": ("bfloat16",)}, "jax", ) @to_ivy_arrays_and_back @@ -90,7 +90,7 @@ def ceil(x, /): return ivy.ceil(x) -@with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") +@with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") @to_ivy_arrays_and_back def clip(a, a_min=None, a_max=None, out=None): return ivy.array(ivy.clip(a, a_min, a_max), dtype=a.dtype) @@ -181,7 +181,7 @@ def divide(x1, x2, /): @to_ivy_arrays_and_back def divmod(x1, x2, /): x1, x2 = promote_types_of_jax_inputs(x1, x2) - return tuple([ivy.floor_divide(x1, x2), ivy.remainder(x1, x2)]) + return (ivy.floor_divide(x1, x2), ivy.remainder(x1, x2)) @to_ivy_arrays_and_back @@ -237,7 +237,7 @@ def einsum_path(subscripts, *operands, optimize="greedy"): path_type = path_type[0] else: - raise TypeError("Did not understand the path: %s" % str(path_type)) + raise TypeError(f"Did not understand the path: {str(path_type)}") # Python side parsing if subscripts: @@ -315,14 +315,14 @@ def einsum_path(subscripts, *operands, optimize="greedy"): elif path_type == "optimal": path = optimal_path(input_sets, output_set, dimension_dict, memory_arg) else: - raise KeyError("Path name %s not found", path_type) + raise KeyError(f"Path name {path_type} not found") cost_list, scale_list, size_list, contraction_list = [], [], [], [] # Build contraction tuple (positions, gemm, einsum_str, remaining) for cnum, contract_inds in enumerate(path): # Make sure we remove inds from right to left - contract_inds = tuple(sorted(list(contract_inds), reverse=True)) + contract_inds = tuple(sorted(contract_inds, reverse=True)) contract = find_contraction(contract_inds, input_sets, output_set) out_inds, input_sets, idx_removed, idx_contract = contract @@ -366,8 +366,8 @@ def einsum_path(subscripts, *operands, optimize="greedy"): # Explicit "einsum_path" is usually trusted, but we detect this kind of # mistake in order to prevent from returning an intermediate value. raise RuntimeError( - "Invalid einsum_path is specified: {} more operands has to be " - "contracted.".format(len(input_list) - 1) + f"Invalid einsum_path is specified: {len(input_list) - 1} " + "more operands has to be contracted." ) # Return the path along with a nice string representation @@ -377,13 +377,13 @@ def einsum_path(subscripts, *operands, optimize="greedy"): speedup = naive_cost / opt_cost max_i = max(size_list) - path_print = " Complete contraction: %s\n" % overall_contraction - path_print += " Naive scaling: %d\n" % len(indices) - path_print += " Optimized scaling: %d\n" % max(scale_list) - path_print += " Naive FLOP count: %.3e\n" % naive_cost - path_print += " Optimized FLOP count: %.3e\n" % opt_cost - path_print += " Theoretical speedup: %3.3f\n" % speedup - path_print += " Largest intermediate: %.3e elements\n" % max_i + path_print = f" Complete contraction: {overall_contraction}\n" + path_print += f" Naive scaling: {len(indices)}\n" + path_print += f" Optimized scaling: {max(scale_list)}\n" + path_print += f" Naive FLOP count: {naive_cost:.3e}\n" + path_print += f" Optimized FLOP count: {opt_cost:.3e}\n" + path_print += f" Theoretical speedup: {speedup:3.3f}\n" + path_print += f" Largest intermediate: {max_i:.3e} elements\n" path_print += "-" * 74 + "\n" path_print += "%6s %24s %40s\n" % header path_print += "-" * 74 @@ -420,7 +420,7 @@ def expm1( @with_unsupported_dtypes( - {"0.4.19 and below": ("uint16",)}, + {"0.4.24 and below": ("uint16",)}, "jax", ) @to_ivy_arrays_and_back @@ -452,24 +452,13 @@ def floor_divide(x1, x2, /, out=None): @to_ivy_arrays_and_back def fmax(x1, x2): x1, x2 = promote_types_of_jax_inputs(x1, x2) - ret = ivy.where( - ivy.bitwise_or(ivy.greater(x1, x2), ivy.isnan(x2)), - x1, - x2, - ) - return ret + return ivy.fmax(x1, x2) @to_ivy_arrays_and_back def fmin(x1, x2): x1, x2 = promote_types_of_jax_inputs(x1, x2) - ret = ivy.where( - ivy.bitwise_or(ivy.less(x1, x2), ivy.isnan(x2)), - x1, - x2, - ) - print("jax-frontend", ret) - return ret + return ivy.fmin(x1, x2) @to_ivy_arrays_and_back @@ -595,7 +584,7 @@ def minimum(x1, x2, /): @to_ivy_arrays_and_back -@with_unsupported_dtypes({"0.4.19 and below": ("complex",)}, "jax") +@with_unsupported_dtypes({"0.4.24 and below": ("complex",)}, "jax") def mod(x1, x2, /): x1, x2 = promote_types_of_jax_inputs(x1, x2) return ivy.remainder(x1, x2) @@ -637,7 +626,7 @@ def negative( @with_unsupported_dtypes( { - "0.4.19 and below": ( + "0.4.24 and below": ( "bfloat16", "float16", ) @@ -682,7 +671,7 @@ def polyadd(a1, a2): @with_unsupported_dtypes( - {"0.4.19 and below": ("float16",)}, + {"0.4.24 and below": ("float16",)}, "jax", ) @to_ivy_arrays_and_back @@ -724,7 +713,7 @@ def polydiv(u, v, *, trim_leading_zeros=False): @with_unsupported_dtypes( - {"0.4.19 and below": ("float16",)}, + {"0.4.24 and below": ("float16",)}, "jax", ) @to_ivy_arrays_and_back diff --git a/ivy/functional/frontends/jax/numpy/searching_sorting.py b/ivy/functional/frontends/jax/numpy/searching_sorting.py index cf538122e1fc5..397031ad1d606 100644 --- a/ivy/functional/frontends/jax/numpy/searching_sorting.py +++ b/ivy/functional/frontends/jax/numpy/searching_sorting.py @@ -8,6 +8,7 @@ ) from ivy.functional.frontends.numpy.func_wrapper import from_zero_dim_arrays_to_scalar from ivy.func_wrapper import ( + with_supported_device_and_dtypes, with_unsupported_dtypes, ) @@ -15,7 +16,7 @@ @to_ivy_arrays_and_back @with_unsupported_dtypes( { - "0.4.19 and below": ( + "0.4.24 and below": ( "float16", "bfloat16", ) @@ -26,6 +27,58 @@ def argmax(a, axis=None, out=None, keepdims=False): return ivy.argmax(a, axis=axis, keepdims=keepdims, out=out, dtype=ivy.int64) +# argmin +@to_ivy_arrays_and_back +@with_supported_device_and_dtypes( + { + "0.4.20 and below": { + "cpu": ( + "int16", + "int32", + "int64", + "float32", + "float64", + "uint8", + "uint16", + "uint32", + "uint64", + ) + } + }, + "jax", +) +def argmin(a, axis=None, out=None, keepdims=None): + if a is not None: + if isinstance(a, list): + if all(isinstance(elem, ivy.Array) for elem in a): + if len(a) == 1: + a = a[0] + else: + return [ + ivy.argmin( + ivy.to_native_arrays(elem), + axis=axis, + out=out, + keepdims=keepdims, + ) + for elem in a + ] + else: + raise ValueError( + "Input 'a' must be an Ivy array or a list of Ivy arrays." + ) + + if not isinstance(a, ivy.Array): + raise TypeError("Input 'a' must be an array.") + + if a.size == 0: + raise ValueError("Input 'a' must not be empty.") + + return ivy.argmin(a, axis=axis, out=out, keepdims=keepdims) + else: + raise ValueError("argmin takes at least 1 argument.") + + @to_ivy_arrays_and_back def argsort(a, axis=-1, kind="stable", order=None): if kind != "stable": @@ -58,7 +111,7 @@ def argwhere(a, /, *, size=None, fill_value=None): @with_unsupported_dtypes( { - "0.4.19 and below": ( + "0.4.24 and below": ( "uint8", "int8", "bool", diff --git a/ivy/functional/frontends/jax/numpy/statistical.py b/ivy/functional/frontends/jax/numpy/statistical.py index dc30b31757c61..0b20517c66187 100644 --- a/ivy/functional/frontends/jax/numpy/statistical.py +++ b/ivy/functional/frontends/jax/numpy/statistical.py @@ -33,7 +33,7 @@ def average(a, axis=None, weights=None, returned=False, keepdims=False): ret = ivy.mean(a, axis=axis, keepdims=keepdims) if axis is None: fill_value = int(a.size) if ivy.is_int_dtype(ret) else float(a.size) - weights_sum = ivy.full(shape=(), fill_value=fill_value, dtype=ret.dtype) + weights_sum = ivy.full((), fill_value, dtype=ret.dtype) else: if isinstance(axis, tuple): # prod with axis has dtype Sequence[int] @@ -103,7 +103,7 @@ def corrcoef(x, y=None, rowvar=True): @to_ivy_arrays_and_back -@with_unsupported_dtypes({"0.4.19 and below": ("float16", "bfloat16")}, "jax") +@with_unsupported_dtypes({"0.4.24 and below": ("float16", "bfloat16")}, "jax") def correlate(a, v, mode="valid", precision=None): if ivy.get_num_dims(a) != 1 or ivy.get_num_dims(v) != 1: raise ValueError("correlate() only support 1-dimensional inputs.") @@ -404,7 +404,9 @@ def apply_along_axis(func1d, axis, arr, *args, **kwargs): if axis < 0: axis = axis + ndim - func = lambda elem: func1d(elem, *args, **kwargs) + def func(elem): + return func1d(elem, *args, **kwargs) + for i in range(1, ndim - axis): func = ivy.vmap(func, in_axes=i, out_axes=-1) for i in range(axis): @@ -495,7 +497,7 @@ def _nanquantile_unchecked( ): """Assumes that q is in [0, 1], and is an ndarray.""" if a.size == 0: - return ivy.nanmean(a, axis, out=out, keepdims=keepdims) + return ivy.nanmean(a, axis=axis, out=out, keepdims=keepdims) return _ureduce( a, func=_nanquantile_ureduce_func, @@ -516,7 +518,7 @@ def _nanquantile_unchecked( ivy.logging.warning("percentile s must be in the range [0, 100]") return [] else: - if not (ivy.all(0 <= q) and ivy.all(q <= 1)): + if not (ivy.all(q >= 0) and ivy.all(q <= 1)): ivy.logging.warning("percentile s must be in the range [0, 100]") return [] return _nanquantile_unchecked(a, q, axis, out, overwrite_input, method, keepdims) @@ -572,7 +574,7 @@ def ptp(a, axis=None, out=None, keepdims=False): @to_ivy_arrays_and_back @with_unsupported_dtypes( - {"0.4.19 and below": ("complex64", "complex128", "bfloat16", "bool", "float16")}, + {"0.4.24 and below": ("complex64", "complex128", "bfloat16", "bool", "float16")}, "jax", ) def quantile( @@ -597,7 +599,7 @@ def quantile( @handle_jax_dtype -@with_unsupported_dtypes({"0.4.19 and below": ("bfloat16",)}, "jax") +@with_unsupported_dtypes({"0.4.24 and below": ("bfloat16",)}, "jax") @to_ivy_arrays_and_back def std(a, axis=None, dtype=None, out=None, ddof=0, keepdims=False, *, where=None): axis = tuple(axis) if isinstance(axis, list) else axis diff --git a/ivy/functional/frontends/jax/random.py b/ivy/functional/frontends/jax/random.py index 8a67fe804d687..4a63a1d81baf1 100644 --- a/ivy/functional/frontends/jax/random.py +++ b/ivy/functional/frontends/jax/random.py @@ -38,7 +38,7 @@ def PRNGKey(seed): @to_ivy_arrays_and_back @with_supported_dtypes( { - "0.4.19 and below": ( + "0.4.24 and below": ( "float32", "float64", ) @@ -70,7 +70,7 @@ def bernoulli(key, p=0.5, shape=None): @to_ivy_arrays_and_back @with_unsupported_dtypes( { - "0.4.19 and below": ( + "0.4.24 and below": ( "float16", "bfloat16", ) @@ -85,7 +85,7 @@ def beta(key, a, b, shape=None, dtype=None): @to_ivy_arrays_and_back @with_unsupported_dtypes( { - "0.4.19 and below": ( + "0.4.24 and below": ( "float16", "bfloat16", ) @@ -133,7 +133,7 @@ def cauchy(key, shape=(), dtype="float64"): @to_ivy_arrays_and_back @with_unsupported_dtypes( { - "0.4.19 and below": ( + "0.4.24 and below": ( "float16", "bfloat16", ) @@ -149,7 +149,7 @@ def dirichlet(key, alpha, shape=None, dtype="float32"): @handle_jax_dtype @to_ivy_arrays_and_back @with_unsupported_dtypes( - {"0.4.19 and below": "uint32"}, + {"0.4.24 and below": "uint32"}, "jax", ) def double_sided_maxwell(key, loc, scale, shape=(), dtype="float64"): @@ -168,7 +168,7 @@ def double_sided_maxwell(key, loc, scale, shape=(), dtype="float64"): @to_ivy_arrays_and_back @with_unsupported_dtypes( { - "0.4.19 and below": ( + "0.4.24 and below": ( "float16", "bfloat16", ) @@ -196,7 +196,7 @@ def fold_in(key, data): @to_ivy_arrays_and_back @with_unsupported_dtypes( { - "0.4.19 and below": ( + "0.4.24 and below": ( "float16", "bfloat16", ) @@ -212,7 +212,7 @@ def gamma(key, a, shape=None, dtype="float64"): @to_ivy_arrays_and_back @with_unsupported_dtypes( { - "0.4.19 and below": ( + "0.4.24 and below": ( "float16", "bfloat16", ) @@ -231,7 +231,7 @@ def generalized_normal(key, p, shape=(), dtype="float64"): @to_ivy_arrays_and_back @with_unsupported_dtypes( { - "0.4.19 and below": ( + "0.4.24 and below": ( "float16", "bfloat16", ) @@ -255,7 +255,7 @@ def gumbel(key, shape=(), dtype="float64"): @to_ivy_arrays_and_back @with_unsupported_dtypes( { - "0.4.19 and below": ( + "0.4.24 and below": ( "float16", "bfloat16", ) @@ -270,7 +270,7 @@ def loggamma(key, a, shape=None, dtype="float64"): @handle_jax_dtype @to_ivy_arrays_and_back @with_unsupported_dtypes( - {"0.4.19 and below": ("float16", "bfloat16")}, + {"0.4.24 and below": ("float16", "bfloat16")}, "jax", ) def logistic(key, shape=(), dtype="float64"): @@ -301,7 +301,7 @@ def maxwell(key, shape, dtype="float64"): @to_ivy_arrays_and_back @with_unsupported_dtypes( { - "0.4.19 and below": ( + "0.4.24 and below": ( "float16", "bfloat16", ) @@ -358,7 +358,7 @@ def orthogonal(key, n, shape=(), dtype=None): @to_ivy_arrays_and_back @with_unsupported_dtypes( { - "0.4.19 and below": ( + "0.4.24 and below": ( "float16", "bfloat16", ) @@ -393,7 +393,7 @@ def permutation(key, x, axis=0, independent=False): @handle_jax_dtype @to_ivy_arrays_and_back @with_unsupported_dtypes( - {"0.4.19 and below": ("unsigned", "int8", "int16")}, + {"0.4.24 and below": ("unsigned", "int8", "int16")}, "jax", ) def poisson(key, lam, shape=None, dtype=None): @@ -404,7 +404,7 @@ def poisson(key, lam, shape=None, dtype=None): @handle_jax_dtype @to_ivy_arrays_and_back @with_unsupported_dtypes( - {"0.4.19 and below": ("unsigned", "int8", "int16")}, + {"0.4.24 and below": ("unsigned", "int8", "int16")}, "jax", ) def rademacher(key, shape, dtype="int64"): @@ -418,7 +418,7 @@ def rademacher(key, shape, dtype="int64"): @handle_jax_dtype @to_ivy_arrays_and_back @with_unsupported_dtypes( - {"0.4.19 and below": ("unsigned", "int8", "int16")}, + {"0.4.24 and below": ("unsigned", "int8", "int16")}, "jax", ) def randint(key, shape, minval, maxval, dtype="int64"): diff --git a/ivy/functional/frontends/mindspore/ops/function/nn_func.py b/ivy/functional/frontends/mindspore/ops/function/nn_func.py index 329c1808e1fa3..deffd6d14b6dc 100644 --- a/ivy/functional/frontends/mindspore/ops/function/nn_func.py +++ b/ivy/functional/frontends/mindspore/ops/function/nn_func.py @@ -2,29 +2,13 @@ import ivy from ivy.func_wrapper import with_supported_dtypes from ivy.functional.frontends.paddle.func_wrapper import to_ivy_arrays_and_back +from ivy.functional.ivy.experimental.layers import _broadcast_pooling_helper # --- Helpers --- # # --------------- # -def _broadcast_pooling_helper(x, pool_dims: str = "2d", name: str = "padding"): - dims = {"1d": 1, "2d": 2, "3d": 3} - - if isinstance(x, int): - return tuple([x for _ in range(dims[pool_dims])]) - - if len(x) == 1: - return tuple([x[0] for _ in range(dims[pool_dims])]) - elif len(x) == dims[pool_dims]: - return tuple(x) - elif len(x) != dims[pool_dims]: - raise ValueError( - f"`{name}` must either be a single int, " - f"or a tuple of {dims[pool_dims]} ints. " - ) - - def _conv(input, weight, bias=None, stride=1, padding=0, dilation=1, groups=1): dims = len(input.shape) - 2 _valid_shapes(input, weight, bias, stride, padding, groups) @@ -121,18 +105,18 @@ def _valid_shapes(input, weight, bias, stride, padding, groups, transpose=False) ) @to_ivy_arrays_and_back def adaptive_avg_pool2d(input, output_size): - return ivy.adaptive_avg_pool2d(input, output_size) + return ivy.adaptive_avg_pool2d(input, output_size, data_format="NCHW") @to_ivy_arrays_and_back def avg_pool2d( input, - kernel_size, - stride=None, + kernel_size=1, + stride=1, padding=0, - pad_mode=False, + ceil_mode=False, count_include_pad=True, - divisor_override=None, + divisor_override=0, ): # Figure out input dims N input_rank = input.ndim @@ -147,14 +131,14 @@ def avg_pool2d( kernel_pads = list(zip(kernel_size, padding)) # Padding should be less than or equal to half of kernel size - if not all([pad <= kernel / 2 for kernel, pad in kernel_pads]): + if not all(pad <= kernel / 2 for kernel, pad in kernel_pads): raise ValueError( "pad should be smaller than or equal to half of kernel size, " f"but got padding={padding}, kernel_size={kernel_size}. " ) # Figure out padding string - if all([pad == ivy.ceil((kernel - 1) / 2) for kernel, pad in kernel_pads]): + if all(pad == ivy.ceil((kernel - 1) / 2) for kernel, pad in kernel_pads): padding_str = "SAME" else: padding_str = "VALID" @@ -165,7 +149,7 @@ def avg_pool2d( stride, padding_str, data_format=data_format, - pad_mode=pad_mode, + ceil_mode=ceil_mode, count_include_pad=count_include_pad, divisor_override=divisor_override, ) @@ -183,7 +167,7 @@ def conv1d( dilation=1, groups=1, ): - if pad_mode == "valid" or pad_mode == "same": + if pad_mode in ["valid", "same"]: padding = pad_mode elif pad_mode == "pad": padding = padding @@ -204,7 +188,7 @@ def conv2d( dilation=1, groups=1, ): - if pad_mode == "valid" or pad_mode == "same": + if pad_mode in ["valid", "same"]: padding = pad_mode elif pad_mode == "pad": padding = padding @@ -225,7 +209,7 @@ def conv3d( dilation=1, groups=1, ): - if pad_mode == "valid" or pad_mode == "same": + if pad_mode in ["valid", "same"]: padding = pad_mode elif pad_mode == "pad": padding = padding @@ -234,6 +218,25 @@ def conv3d( return _conv(input, weight, bias, stride, padding, dilation, groups) +@with_supported_dtypes( + { + "2.0.0 and below": ( + "int8", + "int16", + "int32", + "int64", + "float16", + "float32", + "float64", + ) + }, + "mindspore", +) +@to_ivy_arrays_and_back +def dropout(input, p=0.5, training=True, seed=None): + return ivy.dropout(input, p, training=training, seed=seed) + + @with_supported_dtypes( { "2.0.0 and below": ( @@ -352,7 +355,7 @@ def interpolate( ): return ivy.interpolate( input, - size=size, + size, scale_factor=scale_factor, mode=mode, align_corners=align_corners, @@ -361,8 +364,8 @@ def interpolate( def kl_div(logits, labels, reduction="mean"): - """ - Computes the Kullback-Leibler (KL) Divergence between the logits and the labels. + """Computes the Kullback-Leibler (KL) Divergence between the logits and the + labels. Parameters ---------- diff --git a/ivy/functional/frontends/mxnet/func_wrapper.py b/ivy/functional/frontends/mxnet/func_wrapper.py index 434e5755a7f11..6b8880d6f149e 100644 --- a/ivy/functional/frontends/mxnet/func_wrapper.py +++ b/ivy/functional/frontends/mxnet/func_wrapper.py @@ -61,8 +61,7 @@ def _handle_mxnet_out(*args, **kwargs): def inputs_to_ivy_arrays(fn: Callable) -> Callable: @functools.wraps(fn) def _inputs_to_ivy_arrays_mxnet(*args, **kwargs): - """ - Convert `ndarray.NDArray` into `ivy.Array` instances. + """Convert `ndarray.NDArray` into `ivy.Array` instances. Convert all `ndarray.NDArray` instances in both the positional and keyword arguments into `ivy.Array` instances, and then calls @@ -84,8 +83,7 @@ def _inputs_to_ivy_arrays_mxnet(*args, **kwargs): def outputs_to_frontend_arrays(fn: Callable) -> Callable: @functools.wraps(fn) def _outputs_to_frontend_arrays_mxnet(*args, **kwargs): - """ - Convert `ivy.Array` into `ndarray.NDArray` instances. + """Convert `ivy.Array` into `ndarray.NDArray` instances. Call the function, and then converts all `ivy.Array` instances in the function return into `ndarray.NDArray` instances. @@ -101,8 +99,7 @@ def _outputs_to_frontend_arrays_mxnet(*args, **kwargs): def to_ivy_arrays_and_back(fn: Callable) -> Callable: - """ - Wrap `fn` so it receives and returns `ivy.Array` instances. + """Wrap `fn` so it receives and returns `ivy.Array` instances. Wrap `fn` so that input arrays are all converted to `ivy.Array` instances and return arrays are all converted to `ndarray.NDArray` diff --git a/ivy/functional/frontends/mxnet/numpy/__init__.py b/ivy/functional/frontends/mxnet/numpy/__init__.py index a3b0c6fab40a1..cc7390eadec51 100644 --- a/ivy/functional/frontends/mxnet/numpy/__init__.py +++ b/ivy/functional/frontends/mxnet/numpy/__init__.py @@ -104,8 +104,8 @@ def promote_types_mxnet( type2: Union[ivy.Dtype, ivy.NativeDtype], /, ) -> ivy.Dtype: - """ - Promote the datatypes type1 and type2, returning the data type they promote to. + """Promote the datatypes type1 and type2, returning the data type they + promote to. Parameters ---------- @@ -121,8 +121,10 @@ def promote_types_mxnet( """ try: ret = mxnet_promotion_table[(ivy.as_ivy_dtype(type1), ivy.as_ivy_dtype(type2))] - except KeyError: - raise ivy.utils.exceptions.IvyException("these dtypes are not type promotable") + except KeyError as e: + raise ivy.utils.exceptions.IvyException( + "these dtypes are not type promotable" + ) from e return ret @@ -132,9 +134,8 @@ def promote_types_of_mxnet_inputs( x2: Union[ivy.Array, Number, Iterable[Number]], /, ) -> Tuple[ivy.Array, ivy.Array]: - """ - Promote the dtype of the given native array inputs to a common dtype based on type - promotion rules. + """Promote the dtype of the given native array inputs to a common dtype + based on type promotion rules. While passing float or integer values or any other non-array input to this function, it should be noted that the return will be an diff --git a/ivy/functional/frontends/mxnet/numpy/random.py b/ivy/functional/frontends/mxnet/numpy/random.py index e3bf4f8eea107..6e5f2f202fdca 100644 --- a/ivy/functional/frontends/mxnet/numpy/random.py +++ b/ivy/functional/frontends/mxnet/numpy/random.py @@ -62,7 +62,7 @@ def rand(*size, **kwargs): @to_ivy_arrays_and_back def randint(low, high=None, size=None, dtype=None, device=None, out=None): - return ivy.randint(low, high=high, shape=size, device=device, dtype=dtype, out=out) + return ivy.randint(low, high, shape=size, device=device, dtype=dtype, out=out) @to_ivy_arrays_and_back diff --git a/ivy/functional/frontends/numpy/__init__.py b/ivy/functional/frontends/numpy/__init__.py index 6f17b4b6998b4..2abc591a2ddcf 100644 --- a/ivy/functional/frontends/numpy/__init__.py +++ b/ivy/functional/frontends/numpy/__init__.py @@ -425,8 +425,10 @@ def promote_numpy_dtypes( type1, type2 = ivy.as_ivy_dtype(type1), ivy.as_ivy_dtype(type2) try: return numpy_promotion_table[(type1, type2)] - except KeyError: - raise ivy.utils.exceptions.IvyException("these dtypes are not type promotable") + except KeyError as e: + raise ivy.utils.exceptions.IvyException( + "these dtypes are not type promotable" + ) from e @handle_exceptions @@ -435,9 +437,8 @@ def promote_types_of_numpy_inputs( x2: Union[ivy.Array, Number, Iterable[Number]], /, ) -> Tuple[ivy.Array, ivy.Array]: - """ - Promote the dtype of the given ivy array inputs to a common dtype based on numpy - type promotion rules. + """Promote the dtype of the given ivy array inputs to a common dtype based + on numpy type promotion rules. While passing float or integer values or any other non-array input to this function, it should be noted that the return will be an @@ -454,11 +455,11 @@ def promote_types_of_numpy_inputs( type1 = ivy.default_dtype(item=x1).strip("u123456789") type2 = ivy.default_dtype(item=x2).strip("u123456789") # Ignore type of 0-dim arrays or scalars to mimic numpy - if not x1.shape == () and x2.shape == () and type1 == type2: + if x1.shape != () and x2.shape == () and type1 == type2: x2 = ivy.asarray( x2, dtype=x1.dtype, device=ivy.default_device(item=x1, as_native=False) ) - elif x1.shape == () and not x2.shape == () and type1 == type2: + elif x1.shape == () and x2.shape != () and type1 == type2: x1 = ivy.asarray( x1, dtype=x2.dtype, device=ivy.default_device(item=x2, as_native=False) ) @@ -495,7 +496,6 @@ def promote_types_of_numpy_inputs( from . import ma from . import fft -from . import random from .ufunc import ufunc from . import linalg @@ -551,7 +551,6 @@ def promote_types_of_numpy_inputs( _reciprocal, _subtract, _divmod, - _remainder, ) from ivy.functional.frontends.numpy.mathematical_functions.trigonometric_functions import ( # noqa @@ -638,6 +637,7 @@ def promote_types_of_numpy_inputs( from ivy.functional.frontends.numpy.mathematical_functions.floating_point_routines import ( # noqa _nextafter, + _signbit, _spacing, ) @@ -721,6 +721,7 @@ def promote_types_of_numpy_inputs( conj = ufunc("_conj") rint = ufunc("_rint") nextafter = ufunc("_nextafter") +signbit = ufunc("_signbit") conjugate = ufunc("_conj") lcm = ufunc("_lcm") gcd = ufunc("_gcd") diff --git a/ivy/functional/frontends/numpy/broadcast/methods.py b/ivy/functional/frontends/numpy/broadcast/methods.py index fdb0d592ce97f..eeaf072c66f78 100644 --- a/ivy/functional/frontends/numpy/broadcast/methods.py +++ b/ivy/functional/frontends/numpy/broadcast/methods.py @@ -12,8 +12,8 @@ def __init__(self, *args): self._index = 0 self._numiter = len(data) self._size = data[0].size - self._data = tuple((*zip(*(ivy.flatten(i) for i in data)),)) - self._iters = tuple((iter(ivy.flatten(i)) for i in data)) + self._data = (*zip(*(ivy.flatten(i) for i in data)),) + self._iters = tuple(iter(ivy.flatten(i)) for i in data) @property def shape(self): diff --git a/ivy/functional/frontends/numpy/data_type_routines/creating_data_types.py b/ivy/functional/frontends/numpy/data_type_routines/creating_data_types.py index bab1425b65a5c..84bd99b6b71d6 100644 --- a/ivy/functional/frontends/numpy/data_type_routines/creating_data_types.py +++ b/ivy/functional/frontends/numpy/data_type_routines/creating_data_types.py @@ -19,11 +19,11 @@ def __repr__(self): def __ge__(self, other): try: other = dtype(other) - except TypeError: + except TypeError as e: raise ivy.utils.exceptions.IvyException( "Attempted to compare a dtype with something which" "couldn't be interpreted as a dtype" - ) + ) from e return self == np_frontend.promote_numpy_dtypes( self._ivy_dtype, other._ivy_dtype @@ -32,22 +32,22 @@ def __ge__(self, other): def __gt__(self, other): try: other = dtype(other) - except TypeError: + except TypeError as e: raise ivy.utils.exceptions.IvyException( "Attempted to compare a dtype with something which" "couldn't be interpreted as a dtype" - ) + ) from e return self >= other and self != other def __lt__(self, other): try: other = dtype(other) - except TypeError: + except TypeError as e: raise ivy.utils.exceptions.IvyException( "Attempted to compare a dtype with something which" "couldn't be interpreted as a dtype" - ) + ) from e return self != np_frontend.promote_numpy_dtypes( self._ivy_dtype, other._ivy_dtype @@ -56,11 +56,11 @@ def __lt__(self, other): def __le__(self, other): try: other = dtype(other) - except TypeError: + except TypeError as e: raise ivy.utils.exceptions.IvyException( "Attempted to compare a dtype with something which" "couldn't be interpreted as a dtype" - ) + ) from e return self < other or self == other diff --git a/ivy/functional/frontends/numpy/data_type_routines/general.py b/ivy/functional/frontends/numpy/data_type_routines/general.py index 8cd3433e82a5d..73695f02f35b9 100644 --- a/ivy/functional/frontends/numpy/data_type_routines/general.py +++ b/ivy/functional/frontends/numpy/data_type_routines/general.py @@ -39,7 +39,7 @@ def can_cast(from_, to, casting="safe"): else: raise ivy.utils.exceptions.IvyException("to must be dtype or dtype specifier") - if casting == "no" or casting == "equiv": + if casting in ["no", "equiv"]: return from_ == to if casting == "safe" and to in np_frontend.numpy_casting_rules[from_]: diff --git a/ivy/functional/frontends/numpy/fft/discrete_fourier_transform.py b/ivy/functional/frontends/numpy/fft/discrete_fourier_transform.py index 67755d6fe3419..0cfe2a10a75a2 100644 --- a/ivy/functional/frontends/numpy/fft/discrete_fourier_transform.py +++ b/ivy/functional/frontends/numpy/fft/discrete_fourier_transform.py @@ -1,6 +1,14 @@ import ivy from ivy.functional.frontends.numpy.func_wrapper import to_ivy_arrays_and_back -from ivy.func_wrapper import with_unsupported_dtypes +from ivy.func_wrapper import with_unsupported_dtypes, with_supported_dtypes + + +_SWAP_DIRECTION_MAP = { + None: "forward", + "backward": "forward", + "ortho": "ortho", + "forward": "backward", +} # --- Helpers --- # @@ -25,17 +33,17 @@ def fft(a, n=None, axis=-1, norm=None): return ivy.fft(ivy.astype(a, ivy.complex128), axis, norm=norm, n=n) -@with_unsupported_dtypes({"1.26.1 and below": ("int",)}, "numpy") +@with_unsupported_dtypes({"1.26.3 and below": ("int",)}, "numpy") @to_ivy_arrays_and_back def fftfreq(n, d=1.0): if not isinstance( n, (int, type(ivy.int8), type(ivy.int16), type(ivy.int32), type(ivy.int64)) ): - raise ValueError("n should be an integer") + raise TypeError("n should be an integer") N = (n - 1) // 2 + 1 val = 1.0 / (n * d) - results = ivy.empty(tuple([n]), dtype=int) + results = ivy.empty((n,), dtype=int) p1 = ivy.arange(0, N, dtype=int) results[:N] = p1 @@ -45,8 +53,40 @@ def fftfreq(n, d=1.0): return results * val +@with_supported_dtypes( + {"1.26.0 and below": ("float32", "float64", "complex64", "complex128")}, + "numpy", +) @to_ivy_arrays_and_back -@with_unsupported_dtypes({"1.26.1 and below": ("float16",)}, "numpy") +def fftn(a, s=None, axes=None, norm=None): + invreal = 0 + if norm is None: + norm = "backward" + if s is None: + shapeless = 1 + if axes is None: + s = list(a.shape) + else: + axes = [ax % len(a.shape) for ax in axes] + s = ivy.gather(a.shape, ivy.array(axes, dtype="int64")) + else: + shapeless = 0 + s = list(s) + if axes is None: + axes = list(range(-len(s), 0)) + if len(s) != len(axes): + raise ValueError("Shape and axes have different lengths.") + if invreal and shapeless: + s[-1] = (a.shape[axes[-1]] - 1) * 2 + itl = list(range(len(axes))) + itl.reverse() + for ii in itl: + a = ivy.fft(a, axes[ii], norm=norm, n=int(s[ii])) + return ivy.astype(a, ivy.complex128) + + +@to_ivy_arrays_and_back +@with_unsupported_dtypes({"1.26.3 and below": ("float16",)}, "numpy") def fftshift(x, axes=None): x = ivy.asarray(x) @@ -91,7 +131,7 @@ def ifftn(a, s=None, axes=None, norm=None): @to_ivy_arrays_and_back -@with_unsupported_dtypes({"1.26.1 and below": ("float16",)}, "numpy") +@with_unsupported_dtypes({"1.26.3 and below": ("float16",)}, "numpy") def ifftshift(x, axes=None): x = ivy.asarray(x) @@ -111,7 +151,7 @@ def ifftshift(x, axes=None): return roll -@with_unsupported_dtypes({"1.26.1 and below": ("float16",)}, "numpy") +@with_unsupported_dtypes({"1.26.3 and below": ("float16",)}, "numpy") @to_ivy_arrays_and_back def ihfft(a, n=None, axis=-1, norm=None): if n is None: @@ -121,7 +161,7 @@ def ihfft(a, n=None, axis=-1, norm=None): return output -@with_unsupported_dtypes({"1.26.1 and below": ("float16",)}, "numpy") +@with_unsupported_dtypes({"1.26.3 and below": ("float16",)}, "numpy") @to_ivy_arrays_and_back def rfft(a, n=None, axis=-1, norm=None): if norm is None: @@ -135,7 +175,7 @@ def rfftfreq(n, d=1.0): if not isinstance( n, (int, type(ivy.int8), type(ivy.int16), type(ivy.int32), type(ivy.int64)) ): - raise ValueError("n should be an integer") + raise TypeError("n should be an integer") val = 1.0 / (n * d) N = n // 2 + 1 @@ -148,11 +188,3 @@ def rfftfreq(n, d=1.0): def rfftn(a, s=None, axes=None, norm=None): a = ivy.asarray(a, dtype=ivy.complex128) return ivy.rfftn(a, s=s, axes=axes, norm=norm) - - -_SWAP_DIRECTION_MAP = { - None: "forward", - "backward": "forward", - "ortho": "ortho", - "forward": "backward", -} diff --git a/ivy/functional/frontends/numpy/func_wrapper.py b/ivy/functional/frontends/numpy/func_wrapper.py index 0c2d35f5801f8..91df6184aa626 100644 --- a/ivy/functional/frontends/numpy/func_wrapper.py +++ b/ivy/functional/frontends/numpy/func_wrapper.py @@ -30,7 +30,10 @@ def _assert_array(args, dtype, scalar_check=False, casting="safe"): if ivy.is_bool_dtype(dtype): assert_fn = ivy.is_bool_dtype if ivy.is_int_dtype(dtype): - assert_fn = lambda x: not ivy.is_float_dtype(x) + + def assert_fn(x): # noqa F811 + return not ivy.is_float_dtype(x) + if assert_fn: ivy.utils.assertions.check_all_or_any_fn( *args, @@ -51,13 +54,19 @@ def _assert_no_array(args, dtype, scalar_check=False, none=False): if args: first_arg = args[0] fn_func = ivy.as_ivy_dtype(dtype) if ivy.exists(dtype) else ivy.dtype(first_arg) - assert_fn = lambda x: ivy.dtype(x) == fn_func + + def assert_fn(x): + return ivy.dtype(x) == fn_func + if scalar_check: - assert_fn = lambda x: ( - ivy.dtype(x) == fn_func - if ivy.shape(x) != () - else _casting_no_special_case(ivy.dtype(x), fn_func, none) - ) + + def assert_fn(x): # noqa F811 + return ( + ivy.dtype(x) == fn_func + if ivy.shape(x) != () + else _casting_no_special_case(ivy.dtype(x), fn_func, none) + ) + ivy.utils.assertions.check_all_or_any_fn( *args, fn=assert_fn, @@ -105,9 +114,15 @@ def _assert_scalar(args, dtype): if args and dtype: assert_fn = None if ivy.is_int_dtype(dtype): - assert_fn = lambda x: not isinstance(x, float) + + def assert_fn(x): # noqa F811 + return not isinstance(x, float) + elif ivy.is_bool_dtype(dtype): - assert_fn = lambda x: isinstance(x, bool) + + def assert_fn(x): + return isinstance(x, bool) + if assert_fn: ivy.utils.assertions.check_all_or_any_fn( *args, @@ -212,9 +227,9 @@ def _to_ivy_array(x): def from_zero_dim_arrays_to_scalar(fn: Callable) -> Callable: @functools.wraps(fn) def _from_zero_dim_arrays_to_scalar(*args, **kwargs): - """ - Call the function, and then convert all 0 dimensional array instances in the - function to float numbers if out argument is not provided. + """Call the function, and then convert all 0 dimensional array + instances in the function to float numbers if out argument is not + provided. Parameters ---------- @@ -267,8 +282,7 @@ def _from_zero_dim_arrays_to_scalar(*args, **kwargs): def handle_numpy_casting(fn: Callable) -> Callable: @functools.wraps(fn) def _handle_numpy_casting(*args, casting="same_kind", dtype=None, **kwargs): - """ - Check numpy casting type. + """Check numpy casting type. Parameters ---------- @@ -329,8 +343,8 @@ def _handle_numpy_casting(*args, casting="same_kind", dtype=None, **kwargs): def handle_numpy_casting_special(fn: Callable) -> Callable: @functools.wraps(fn) def _handle_numpy_casting_special(*args, casting="same_kind", dtype=None, **kwargs): - """ - Check numpy casting type for special cases where output must be type bool. + """Check numpy casting type for special cases where output must be type + bool. Parameters ---------- @@ -418,10 +432,9 @@ def _handle_numpy_out(*args, **kwargs): def inputs_to_ivy_arrays(fn: Callable) -> Callable: @functools.wraps(fn) def _inputs_to_ivy_arrays_np(*args, **kwargs): - """ - Convert all `ndarray` instances in both the positional and keyword arguments - into `ivy.Array` instances, and then call the function with the updated - arguments. + """Convert all `ndarray` instances in both the positional and keyword + arguments into `ivy.Array` instances, and then call the function with + the updated arguments. Parameters ---------- @@ -448,9 +461,8 @@ def _inputs_to_ivy_arrays_np(*args, **kwargs): def outputs_to_frontend_arrays(fn: Callable) -> Callable: @functools.wraps(fn) def _outputs_to_frontend_arrays(*args, order="K", **kwargs): - """ - Call the function, and then convert all `ivy.Array` instances returned by the - function into `ndarray` instances. + """Call the function, and then convert all `ivy.Array` instances + returned by the function into `ndarray` instances. Returns ------- @@ -512,8 +524,7 @@ def _outputs_to_frontend_arrays(*args, order="K", **kwargs): def to_ivy_arrays_and_back(fn: Callable) -> Callable: - """ - Wrap `fn` so it receives and returns `ivy.Array` instances. + """Wrap `fn` so it receives and returns `ivy.Array` instances. Wrap `fn` so that input arrays are all converted to `ivy.Array` instances and return arrays are all converted to `ndarray` instances. diff --git a/ivy/functional/frontends/numpy/indexing_routines/indexing_like_operations.py b/ivy/functional/frontends/numpy/indexing_routines/indexing_like_operations.py index 4d56c0f208c1d..f5d7414b09c46 100644 --- a/ivy/functional/frontends/numpy/indexing_routines/indexing_like_operations.py +++ b/ivy/functional/frontends/numpy/indexing_routines/indexing_like_operations.py @@ -83,6 +83,12 @@ def put_along_axis(arr, indices, values, axis): ivy.put_along_axis(arr, indices, values, axis) +@to_ivy_arrays_and_back +@handle_numpy_out +def take(a, indices, /, *, axis=None, out=None, mode="raise"): + return ivy.take(a, indices, axis=axis, out=out, mode=mode) + + @to_ivy_arrays_and_back def take_along_axis(arr, indices, axis): return ivy.take_along_axis(arr, indices, axis) diff --git a/ivy/functional/frontends/numpy/indexing_routines/inserting_data_into_arrays.py b/ivy/functional/frontends/numpy/indexing_routines/inserting_data_into_arrays.py index 19d474e01f35a..1aea91f0c99c6 100644 --- a/ivy/functional/frontends/numpy/indexing_routines/inserting_data_into_arrays.py +++ b/ivy/functional/frontends/numpy/indexing_routines/inserting_data_into_arrays.py @@ -61,7 +61,7 @@ def __getitem__(self, key): if "," in item: vec = item.split(",") try: - axis, ndmin = [int(x) for x in vec[:2]] + axis, ndmin = (int(x) for x in vec[:2]) if len(vec) == 3: trans1d = int(vec[2]) continue diff --git a/ivy/functional/frontends/numpy/linalg/norms_and_other_numbers.py b/ivy/functional/frontends/numpy/linalg/norms_and_other_numbers.py index 9f80975cbfcdd..2ca07b851cadd 100644 --- a/ivy/functional/frontends/numpy/linalg/norms_and_other_numbers.py +++ b/ivy/functional/frontends/numpy/linalg/norms_and_other_numbers.py @@ -23,7 +23,7 @@ def matrix_rank(A, tol=None, hermitian=False): # solve -@with_unsupported_dtypes({"1.26.1 and below": ("float16",)}, "numpy") +@with_unsupported_dtypes({"1.26.3 and below": ("float16",)}, "numpy") @to_ivy_arrays_and_back @from_zero_dim_arrays_to_scalar def norm(x, ord=None, axis=None, keepdims=False): @@ -46,7 +46,7 @@ def norm(x, ord=None, axis=None, keepdims=False): # slogdet -@with_unsupported_dtypes({"1.26.1 and below": ("float16",)}, "numpy") +@with_unsupported_dtypes({"1.26.3 and below": ("float16",)}, "numpy") @to_ivy_arrays_and_back @from_zero_dim_arrays_to_scalar def slogdet(a): diff --git a/ivy/functional/frontends/numpy/linalg/solving_equations_and_inverting_matrices.py b/ivy/functional/frontends/numpy/linalg/solving_equations_and_inverting_matrices.py index e97015cde5f8b..9c464431774bb 100644 --- a/ivy/functional/frontends/numpy/linalg/solving_equations_and_inverting_matrices.py +++ b/ivy/functional/frontends/numpy/linalg/solving_equations_and_inverting_matrices.py @@ -10,7 +10,7 @@ # inv -@with_unsupported_dtypes({"1.26.1 and below": ("float16",)}, "numpy") +@with_unsupported_dtypes({"1.26.3 and below": ("float16",)}, "numpy") @to_ivy_arrays_and_back def inv(a): return ivy.inv(a) @@ -19,7 +19,7 @@ def inv(a): # TODO: replace this with function from API # As the compositon provides unstable results @to_ivy_arrays_and_back -@with_unsupported_dtypes({"1.26.1 and below": ("float16",)}, "numpy") +@with_unsupported_dtypes({"1.26.3 and below": ("float16",)}, "numpy") def lstsq(a, b, rcond="warn"): solution = ivy.matmul( ivy.pinv(a, rtol=1e-15).astype(ivy.float64), b.astype(ivy.float64) @@ -32,14 +32,14 @@ def lstsq(a, b, rcond="warn"): # pinv # TODO: add hermitian functionality -@with_unsupported_dtypes({"1.26.1 and below": ("float16",)}, "numpy") +@with_unsupported_dtypes({"1.26.3 and below": ("float16",)}, "numpy") @to_ivy_arrays_and_back def pinv(a, rcond=1e-15, hermitian=False): return ivy.pinv(a, rtol=rcond) # solve -@with_unsupported_dtypes({"1.26.1 and below": ("float16",)}, "numpy") +@with_unsupported_dtypes({"1.26.3 and below": ("float16",)}, "numpy") @to_ivy_arrays_and_back def solve(a, b): a, b = promote_types_of_numpy_inputs(a, b) @@ -47,7 +47,7 @@ def solve(a, b): @to_ivy_arrays_and_back -@with_unsupported_dtypes({"1.26.1 and below": ("float16", "blfloat16")}, "numpy") +@with_unsupported_dtypes({"1.26.3 and below": ("float16", "blfloat16")}, "numpy") def tensorinv(a, ind=2): old_shape = ivy.shape(a) prod = 1 @@ -59,5 +59,5 @@ def tensorinv(a, ind=2): raise ValueError("Invalid ind argument.") a = ivy.reshape(a, shape=(prod, -1)) ia = ivy.inv(a) - new_shape = tuple([*invshape]) + new_shape = (*invshape,) return ivy.reshape(ia, shape=new_shape) diff --git a/ivy/functional/frontends/numpy/logic/array_contents.py b/ivy/functional/frontends/numpy/logic/array_contents.py index 87bab7479f744..7388b57862b8d 100644 --- a/ivy/functional/frontends/numpy/logic/array_contents.py +++ b/ivy/functional/frontends/numpy/logic/array_contents.py @@ -7,6 +7,7 @@ handle_numpy_out, ) from ivy.functional.frontends.numpy import promote_types_of_numpy_inputs +from ivy.func_wrapper import with_supported_dtypes @inputs_to_ivy_arrays @@ -23,6 +24,14 @@ def isclose(a, b, /, *, rtol=1e-05, atol=1e-08, equal_nan=False): return ivy.isclose(a, b, rtol=rtol, atol=atol, equal_nan=equal_nan) +@with_supported_dtypes( + {"2.6.0 and below": ("int64", "float64", "float32", "int32", "bfloat16")}, "paddle" +) +@to_ivy_arrays_and_back +def isin(element, test_elements, assume_unique=False, invert=False): + return ivy.isin(element, test_elements, assume_unique=assume_unique, invert=invert) + + @handle_numpy_out @to_ivy_arrays_and_back @from_zero_dim_arrays_to_scalar diff --git a/ivy/functional/frontends/numpy/logic/truth_value_testing.py b/ivy/functional/frontends/numpy/logic/truth_value_testing.py index 0421def6ee57e..5d0a3b9276f2d 100644 --- a/ivy/functional/frontends/numpy/logic/truth_value_testing.py +++ b/ivy/functional/frontends/numpy/logic/truth_value_testing.py @@ -55,10 +55,7 @@ def iscomplexobj(x): if x.ndim == 0: return ivy.is_complex_dtype(ivy.dtype(x)) for ele in x: - if ivy.is_complex_dtype(ivy.dtype(ele)): - return True - else: - return False + return bool(ivy.is_complex_dtype(ivy.dtype(ele))) @to_ivy_arrays_and_back diff --git a/ivy/functional/frontends/numpy/ma/MaskedArray.py b/ivy/functional/frontends/numpy/ma/MaskedArray.py index 34ad474a5b58a..a97a447608cda 100644 --- a/ivy/functional/frontends/numpy/ma/MaskedArray.py +++ b/ivy/functional/frontends/numpy/ma/MaskedArray.py @@ -2,6 +2,8 @@ import ivy.functional.frontends.numpy as np_frontend import numpy as np + +masked = True masked_print_options = "--" nomask = False @@ -194,7 +196,6 @@ def _is_masked_array(x): return isinstance(x, (np.ma.MaskedArray, np_frontend.ma.MaskedArray)) -masked = True # Instance Methods # # ---------------- # diff --git a/ivy/functional/frontends/numpy/manipulation_routines/joining_arrays.py b/ivy/functional/frontends/numpy/manipulation_routines/joining_arrays.py index f32d7cd46fe2d..7035054cbf14a 100644 --- a/ivy/functional/frontends/numpy/manipulation_routines/joining_arrays.py +++ b/ivy/functional/frontends/numpy/manipulation_routines/joining_arrays.py @@ -10,6 +10,16 @@ import ivy.functional.frontends.numpy as np_frontend +@to_ivy_arrays_and_back +def column_stack(tup): + out_dtype = ivy.dtype(tup[0]) + for i in tup: + out_dtype = ivy.as_ivy_dtype( + np_frontend.promote_numpy_dtypes(i.dtype, out_dtype) + ) + return ivy.column_stack(tup) + + @handle_numpy_out @handle_numpy_dtype @to_ivy_arrays_and_back diff --git a/ivy/functional/frontends/numpy/manipulation_routines/transpose_like_operations.py b/ivy/functional/frontends/numpy/manipulation_routines/transpose_like_operations.py index 696e7bb89c673..ca35eba5eeb30 100644 --- a/ivy/functional/frontends/numpy/manipulation_routines/transpose_like_operations.py +++ b/ivy/functional/frontends/numpy/manipulation_routines/transpose_like_operations.py @@ -32,7 +32,7 @@ def swapaxes(a, axis1, axis2): def transpose(array, /, *, axes=None): if not axes: axes = list(range(len(array.shape)))[::-1] - if type(axes) is int: + if isinstance(axes, int): axes = [axes] if (len(array.shape) == 0 and not axes) or (len(array.shape) == 1 and axes[0] == 0): return array diff --git a/ivy/functional/frontends/numpy/mathematical_functions/extrema_finding.py b/ivy/functional/frontends/numpy/mathematical_functions/extrema_finding.py index 1f6ea86b47cc1..e4103ea582196 100644 --- a/ivy/functional/frontends/numpy/mathematical_functions/extrema_finding.py +++ b/ivy/functional/frontends/numpy/mathematical_functions/extrema_finding.py @@ -191,6 +191,38 @@ def amin( return ivy.astype(res, out_dtype, out=out, copy=False) +@handle_numpy_out +@to_ivy_arrays_and_back +@from_zero_dim_arrays_to_scalar +def max( + a, + /, + *, + axis=None, + out=None, + keepdims=False, + initial=None, + where=True, +): + return amax(a, axis=axis, out=out, keepdims=keepdims, initial=initial, where=where) + + +@handle_numpy_out +@to_ivy_arrays_and_back +@from_zero_dim_arrays_to_scalar +def min( + a, + /, + *, + axis=None, + out=None, + keepdims=False, + initial=None, + where=True, +): + return amin(a, axis=axis, out=out, keepdims=keepdims, initial=initial, where=where) + + @handle_numpy_out @to_ivy_arrays_and_back @from_zero_dim_arrays_to_scalar diff --git a/ivy/functional/frontends/numpy/mathematical_functions/floating_point_routines.py b/ivy/functional/frontends/numpy/mathematical_functions/floating_point_routines.py index a05be440fb7fe..44411b84554ac 100644 --- a/ivy/functional/frontends/numpy/mathematical_functions/floating_point_routines.py +++ b/ivy/functional/frontends/numpy/mathematical_functions/floating_point_routines.py @@ -35,6 +35,26 @@ def _nextafter( return ivy.nextafter(x1, x2, out=out) +@handle_numpy_out +@handle_numpy_dtype +@to_ivy_arrays_and_back +@handle_numpy_casting +@from_zero_dim_arrays_to_scalar +def _signbit( + x, + /, + out=None, + *, + where=True, + casting="safe", + order="K", + dtype=None, + subok=True, +): + x = ivy.astype(x, ivy.float64) + return ivy.logical_or(ivy.less(x, 0), ivy.atan2(0.0, x) == ivy.pi, out=out) + + @handle_numpy_out @handle_numpy_dtype @to_ivy_arrays_and_back diff --git a/ivy/functional/frontends/numpy/mathematical_functions/miscellaneous.py b/ivy/functional/frontends/numpy/mathematical_functions/miscellaneous.py index 15e7a81552e49..e14023acadb6d 100644 --- a/ivy/functional/frontends/numpy/mathematical_functions/miscellaneous.py +++ b/ivy/functional/frontends/numpy/mathematical_functions/miscellaneous.py @@ -147,7 +147,7 @@ def _fabs( @to_ivy_arrays_and_back @from_zero_dim_arrays_to_scalar @with_supported_dtypes( - {"1.26.1 and below": ("int8", "int16", "int32", "int64")}, "numpy" + {"1.26.3 and below": ("int8", "int16", "int32", "int64")}, "numpy" ) # Add def _gcd( x1, diff --git a/ivy/functional/frontends/numpy/mathematical_functions/rounding.py b/ivy/functional/frontends/numpy/mathematical_functions/rounding.py index 090977102cb62..a785e218f6395 100644 --- a/ivy/functional/frontends/numpy/mathematical_functions/rounding.py +++ b/ivy/functional/frontends/numpy/mathematical_functions/rounding.py @@ -111,8 +111,6 @@ def _trunc( @to_ivy_arrays_and_back @from_zero_dim_arrays_to_scalar def around(a, decimals=0, out=None): - if ivy.shape(a) == (): - a = ivy.expand_dims(a, axis=0) return ivy.round(a, decimals=decimals, out=out) diff --git a/ivy/functional/frontends/numpy/matrix/methods.py b/ivy/functional/frontends/numpy/matrix/methods.py index 6b49256111058..864bf94b9708b 100644 --- a/ivy/functional/frontends/numpy/matrix/methods.py +++ b/ivy/functional/frontends/numpy/matrix/methods.py @@ -32,7 +32,7 @@ def _init_data(self, data, dtype, copy): if self._data.ndim < 2: self._data = self._data.reshape((1, -1)) elif self._data.ndim > 2: - newshape = tuple([x for x in self._data.shape if x > 1]) + newshape = tuple(x for x in self._data.shape if x > 1) ndim = len(newshape) if ndim == 2: self._data = self._data.reshape(newshape) diff --git a/ivy/functional/frontends/numpy/ndarray/ndarray.py b/ivy/functional/frontends/numpy/ndarray/ndarray.py index c34a2d8b0d314..fcb9e0e6684ed 100644 --- a/ivy/functional/frontends/numpy/ndarray/ndarray.py +++ b/ivy/functional/frontends/numpy/ndarray/ndarray.py @@ -6,6 +6,9 @@ import ivy import ivy.functional.frontends.numpy as np_frontend from ivy.functional.frontends.numpy.func_wrapper import _to_ivy_array +from ivy.func_wrapper import ( + with_supported_device_and_dtypes, +) # --- Classes ---# @@ -326,7 +329,7 @@ def flatten(self, order="C"): def fill(self, num, /): self.ivy_array = np_frontend.full(self.shape, num).ivy_array - return + return None def repeat(self, repeats, axis=None): return np_frontend.repeat(self, repeats, axis=axis) @@ -410,6 +413,31 @@ def tofile(self, fid, /, sep="", format_="%s"): def tolist(self) -> list: return self._ivy_array.to_list() + @with_supported_device_and_dtypes( + { + "1.26.3 and below": { + "cpu": ( + "int64", + "float32", + "float64", + "bfloat16", + "complex64", + "complex128", + "uint64", + ) + } + }, + "numpy", + ) + def trace(self, *, offset=0, axis1=0, axis2=1, out=None): + return np_frontend.trace( + self, + offset=offset, + axis1=axis1, + axis2=axis2, + out=out, + ) + def view(self): return np_frontend.reshape(self, tuple(self.shape)) @@ -704,7 +732,7 @@ def _unsigned_int_bytes_repr(item_val, /, *, dtype=None): elif ivy.is_uint_dtype(dtype): return _unsigned_int_bytes_repr(scalar_value, dtype=dtype) else: - raise ValueError("Unsupported data type for the array.") + raise TypeError("Unsupported data type for the array.") else: if order == "F": array = np_frontend.ravel(array, order="F").ivy_array diff --git a/ivy/functional/frontends/numpy/random/Generator/Generator.py b/ivy/functional/frontends/numpy/random/Generator/Generator.py index 7f51a4dc7c0b2..55799d4cd191b 100644 --- a/ivy/functional/frontends/numpy/random/Generator/Generator.py +++ b/ivy/functional/frontends/numpy/random/Generator/Generator.py @@ -11,4 +11,4 @@ def multinomial(self, n, pvals, size=None): def default__rng(seed=None): - return Generator(seed=seed) + return Generator(bit_generator=seed) diff --git a/ivy/functional/frontends/numpy/random/functions.py b/ivy/functional/frontends/numpy/random/functions.py index be88c43ea6b25..b6d0e7a6c668a 100644 --- a/ivy/functional/frontends/numpy/random/functions.py +++ b/ivy/functional/frontends/numpy/random/functions.py @@ -355,7 +355,7 @@ def wald(mean, scale, size=None): Y = mean * ivy.square(Y) X = mean + mu_2l * (Y - ivy.sqrt(((4 * scale) * Y) + ivy.square(Y))) - condition = U <= mean / (mean + X) + condition = mean / (mean + X) >= U value1 = X value2 = mean * mean / X diff --git a/ivy/functional/frontends/numpy/statistics/averages_and_variances.py b/ivy/functional/frontends/numpy/statistics/averages_and_variances.py index f22f4756a95c8..bd911614f0fc7 100644 --- a/ivy/functional/frontends/numpy/statistics/averages_and_variances.py +++ b/ivy/functional/frontends/numpy/statistics/averages_and_variances.py @@ -13,7 +13,6 @@ @from_zero_dim_arrays_to_scalar def average(a, /, *, axis=None, weights=None, returned=False, keepdims=False): axis = tuple(axis) if isinstance(axis, list) else axis - global avg avg = 0 if keepdims is None: @@ -200,7 +199,9 @@ def var(x, /, *, axis=None, ddof=0.0, keepdims=False, out=None, dtype=None, wher dtype = ( dtype if dtype is not None - else ivy.float64 if ivy.is_int_dtype(x.dtype) else x.dtype + else ivy.float64 + if ivy.is_int_dtype(x.dtype) + else x.dtype ) ret = ivy.var(x, axis=axis, correction=ddof, keepdims=keepdims, out=out) ret = ( diff --git a/ivy/functional/frontends/numpy/statistics/histograms.py b/ivy/functional/frontends/numpy/statistics/histograms.py index 57d3ae685cb2f..8220eff8fbd27 100644 --- a/ivy/functional/frontends/numpy/statistics/histograms.py +++ b/ivy/functional/frontends/numpy/statistics/histograms.py @@ -3,7 +3,7 @@ from ivy.func_wrapper import with_supported_dtypes -@with_supported_dtypes({"1.26.1 and below": ("int64",)}, "numpy") +@with_supported_dtypes({"1.26.3 and below": ("int64",)}, "numpy") @to_ivy_arrays_and_back def bincount(x, /, weights=None, minlength=0): return ivy.bincount(x, weights=weights, minlength=minlength) diff --git a/ivy/functional/frontends/numpy/statistics/order_statistics.py b/ivy/functional/frontends/numpy/statistics/order_statistics.py index 9139b4b3b422f..63209ffe912fa 100644 --- a/ivy/functional/frontends/numpy/statistics/order_statistics.py +++ b/ivy/functional/frontends/numpy/statistics/order_statistics.py @@ -11,8 +11,7 @@ def _cpercentile(N, percent, key=lambda x: x): - """ - Find the percentile of a list of values. + """Find the percentile of a list of values. @parameter N - is a list of values. Note N MUST BE already sorted. @parameter percent - a float value from 0.0 to 1.0. @@ -38,7 +37,7 @@ def _quantile_is_valid(q): if not (0.0 <= q[i] <= 1.0): return False else: - if not (ivy.all(0 <= q) and ivy.all(q <= 1)): + if not (ivy.all(q >= 0) and ivy.all(q <= 1)): return False return True diff --git a/ivy/functional/frontends/onnx/__init__.py b/ivy/functional/frontends/onnx/__init__.py index 0c0b59d24c907..1eafc7e63a158 100644 --- a/ivy/functional/frontends/onnx/__init__.py +++ b/ivy/functional/frontends/onnx/__init__.py @@ -191,8 +191,8 @@ def promote_types_onnx( type2: Union[ivy.Dtype, ivy.NativeDtype], /, ) -> ivy.Dtype: - """ - Promote the datatypes type1 and type2, returning the data type they promote to. + """Promote the datatypes type1 and type2, returning the data type they + promote to. Parameters ---------- @@ -208,8 +208,10 @@ def promote_types_onnx( """ try: ret = onnx_promotion_table[(ivy.as_ivy_dtype(type1), ivy.as_ivy_dtype(type2))] - except KeyError: - raise ivy.utils.exceptions.IvyException("these dtypes are not type promotable") + except KeyError as e: + raise ivy.utils.exceptions.IvyException( + "these dtypes are not type promotable" + ) from e return ret @@ -219,9 +221,8 @@ def promote_types_of_onnx_inputs( x2: Union[ivy.Array, Number, Iterable[Number]], /, ) -> Tuple[ivy.Array, ivy.Array]: - """ - Promote the dtype of the given native array inputs to a common dtype based on type - promotion rules. + """Promote the dtype of the given native array inputs to a common dtype + based on type promotion rules. While passing float or integer values or any other non-array input to this function, it should be noted that the return will be an diff --git a/ivy/functional/frontends/onnx/func_wrapper.py b/ivy/functional/frontends/onnx/func_wrapper.py index fb60b19615381..2bd6adaa3cb1e 100644 --- a/ivy/functional/frontends/onnx/func_wrapper.py +++ b/ivy/functional/frontends/onnx/func_wrapper.py @@ -49,8 +49,7 @@ def _to_ivy_array(x): def inputs_to_ivy_arrays(fn: Callable) -> Callable: @functools.wraps(fn) def _inputs_to_ivy_arrays_onnx(*args, **kwargs): - """ - Convert `Tensor` into `ivy.Array` instances. + """Convert `Tensor` into `ivy.Array` instances. Convert all `Tensor` instances in both the positional and keyword arguments into `ivy.Array` instances, and then calls the @@ -71,8 +70,7 @@ def _inputs_to_ivy_arrays_onnx(*args, **kwargs): def outputs_to_frontend_arrays(fn: Callable) -> Callable: @functools.wraps(fn) def _outputs_to_frontend_arrays_onnx(*args, **kwargs): - """ - Convert `ivy.Array` into `Tensor` instances. + """Convert `ivy.Array` into `Tensor` instances. Call the function, and then converts all `ivy.Array` instances returned by the function into `Tensor` instances. @@ -89,8 +87,7 @@ def _outputs_to_frontend_arrays_onnx(*args, **kwargs): def to_ivy_arrays_and_back(fn: Callable) -> Callable: - """ - Wrap `fn` so it receives and returns `ivy.Array` instances. + """Wrap `fn` so it receives and returns `ivy.Array` instances. Wrap `fn` so that input arrays are all converted to `ivy.Array` instances and return arrays are all converted to `ndarray.NDArray` diff --git a/ivy/functional/frontends/paddle/__init__.py b/ivy/functional/frontends/paddle/__init__.py index be293ee475839..33518fbaf3905 100644 --- a/ivy/functional/frontends/paddle/__init__.py +++ b/ivy/functional/frontends/paddle/__init__.py @@ -156,8 +156,8 @@ def promote_types_paddle( type2: Union[ivy.Dtype, ivy.NativeDtype], /, ) -> ivy.Dtype: - """ - Promote the datatypes type1 and type2, returning the data type they promote to. + """Promote the datatypes type1 and type2, returning the data type they + promote to. Parameters ---------- @@ -173,8 +173,10 @@ def promote_types_paddle( """ try: ret = paddle_promotion_table[(ivy.as_ivy_dtype(type1), ivy.as_ivy_dtype(type2))] - except KeyError: - raise ivy.utils.exceptions.IvyException("these dtypes are not type promotable") + except KeyError as e: + raise ivy.utils.exceptions.IvyException( + "these dtypes are not type promotable" + ) from e return ret @@ -184,9 +186,8 @@ def promote_types_of_paddle_inputs( x2: Union[ivy.Array, Number, Iterable[Number]], /, ) -> Tuple[ivy.Array, ivy.Array]: - """ - Promote the dtype of the given native array inputs to a common dtype based on type - promotion rules. + """Promote the dtype of the given native array inputs to a common dtype + based on type promotion rules. While passing float or integer values or any other non-array input to this function, it should be noted that the return will be an diff --git a/ivy/functional/frontends/paddle/attribute.py b/ivy/functional/frontends/paddle/attribute.py index a94192737bdcb..baa8f64258d4a 100644 --- a/ivy/functional/frontends/paddle/attribute.py +++ b/ivy/functional/frontends/paddle/attribute.py @@ -1,5 +1,6 @@ # global import ivy +from ivy.func_wrapper import with_supported_dtypes from ivy.functional.frontends.paddle.func_wrapper import ( to_ivy_arrays_and_back, ) @@ -30,6 +31,15 @@ def rank(input): return ivy.get_num_dims(input) +@with_supported_dtypes( + { + "2.6.0 and below": ( + "complex64", + "complex128", + ) + }, + "paddle", +) @to_ivy_arrays_and_back def real(x): return ivy.real(x) diff --git a/ivy/functional/frontends/paddle/creation.py b/ivy/functional/frontends/paddle/creation.py index 5a110fb73d326..2f1b4a5f136c5 100644 --- a/ivy/functional/frontends/paddle/creation.py +++ b/ivy/functional/frontends/paddle/creation.py @@ -7,14 +7,14 @@ ) -@with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") +@with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") @to_ivy_arrays_and_back def arange(start, end=None, step=1, dtype=None, name=None): return ivy.arange(start, end, step=step, dtype=dtype) @with_supported_dtypes( - {"2.5.1 and below": ("float16", "float32", "float64", "int32", "int64", "bool")}, + {"2.6.0 and below": ("float16", "float32", "float64", "int32", "int64", "bool")}, "paddle", ) @to_ivy_arrays_and_back @@ -30,7 +30,7 @@ def assign(x, output=None): @with_unsupported_dtypes( - {"2.5.1 and below": ("bfloat16", "uint16", "uint32", "uint64")}, "paddle" + {"2.6.0 and below": ("bfloat16", "uint16", "uint32", "uint64")}, "paddle" ) @to_ivy_arrays_and_back def clone(x): @@ -38,7 +38,7 @@ def clone(x): @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64")}, + {"2.6.0 and below": ("float32", "float64")}, "paddle", ) @to_ivy_arrays_and_back @@ -54,7 +54,7 @@ def complex(real, imag, name=None): @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, "paddle" + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, "paddle" ) @to_ivy_arrays_and_back def diag(x, offset=0, padding_value=0, name=None): @@ -69,7 +69,7 @@ def diag(x, offset=0, padding_value=0, name=None): @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, "paddle" + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, "paddle" ) @to_ivy_arrays_and_back def diagflat(x, offset=0, name=None): @@ -87,6 +87,9 @@ def empty_like(x, dtype=None, name=None): return ivy.empty_like(x, dtype=dtype) +@with_supported_dtypes( + {"2.6.0 and below": ("float16", "float32", "float64", "int32", "int64")}, "paddle" +) @to_ivy_arrays_and_back def eye(num_rows, num_columns=None, dtype=None, name=None): return ivy.eye(num_rows, num_columns, dtype=dtype) @@ -105,7 +108,7 @@ def full_like(x, fill_value, /, *, dtype=None, name=None): @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, "paddle" + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, "paddle" ) @to_ivy_arrays_and_back def linspace(start, stop, num, dtype=None, name=None): @@ -113,7 +116,7 @@ def linspace(start, stop, num, dtype=None, name=None): @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, "paddle" + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, "paddle" ) @to_ivy_arrays_and_back def logspace(start, stop, num, base=10.0, dtype=None, name=None): @@ -121,14 +124,14 @@ def logspace(start, stop, num, base=10.0, dtype=None, name=None): @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, "paddle" + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, "paddle" ) @to_ivy_arrays_and_back def meshgrid(*args, **kwargs): return ivy.meshgrid(*args, indexing="ij") -@with_unsupported_dtypes({"2.5.1 and below": "int8"}, "paddle") +@with_unsupported_dtypes({"2.6.0 and below": "int8"}, "paddle") @to_ivy_arrays_and_back def ones(shape, /, *, dtype=None, name=None): dtype = "float32" if dtype is None else dtype @@ -136,7 +139,7 @@ def ones(shape, /, *, dtype=None, name=None): @with_unsupported_dtypes( - {"2.5.1 and below": ("uint8", "int8", "complex64", "complex128")}, "paddle" + {"2.6.0 and below": ("uint8", "int8", "complex64", "complex128")}, "paddle" ) @to_ivy_arrays_and_back def ones_like(x, /, *, dtype=None, name=None): @@ -152,7 +155,7 @@ def to_tensor(data, /, *, dtype=None, place=None, stop_gradient=True): @with_unsupported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "uint8", "int8", "int16", @@ -169,7 +172,7 @@ def tril(x, diagonal=0, name=None): return ivy.tril(x, k=diagonal) -@with_supported_dtypes({"2.5.1 and below": ("int32", "int64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("int32", "int64")}, "paddle") @to_ivy_arrays_and_back def tril_indices(row, col, offset=0, dtype="int64"): arr = ivy.tril_indices(row, col, offset) @@ -179,7 +182,7 @@ def tril_indices(row, col, offset=0, dtype="int64"): @with_unsupported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "uint8", "int8", "int16", @@ -196,7 +199,7 @@ def triu(x, diagonal=0, name=None): return ivy.triu(x, k=diagonal) -@with_supported_dtypes({"2.5.1 and below": ("int32", "int64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("int32", "int64")}, "paddle") @to_ivy_arrays_and_back def triu_indices(row, col=None, offset=0, dtype="int64"): arr = ivy.triu_indices(row, col, offset) @@ -206,7 +209,7 @@ def triu_indices(row, col=None, offset=0, dtype="int64"): return arr -@with_unsupported_dtypes({"2.5.1 and below": "int8"}, "paddle") +@with_unsupported_dtypes({"2.6.0 and below": "int8"}, "paddle") @to_ivy_arrays_and_back def zeros(shape, /, *, dtype=None, name=None): dtype = "float32" if dtype is None else dtype @@ -214,7 +217,7 @@ def zeros(shape, /, *, dtype=None, name=None): @with_unsupported_dtypes( - {"2.5.1 and below": ("uint8", "int8", "complex64", "complex128")}, "paddle" + {"2.6.0 and below": ("uint8", "int8", "complex64", "complex128")}, "paddle" ) @to_ivy_arrays_and_back def zeros_like(x, /, *, dtype=None, name=None): diff --git a/ivy/functional/frontends/paddle/fft.py b/ivy/functional/frontends/paddle/fft.py index 9045ef19bb89c..4068bc665bcaf 100644 --- a/ivy/functional/frontends/paddle/fft.py +++ b/ivy/functional/frontends/paddle/fft.py @@ -7,7 +7,7 @@ @with_supported_dtypes( - {"2.5.1 and below": ("complex64", "complex128")}, + {"2.6.0 and below": ("complex64", "complex128")}, "paddle", ) @to_ivy_arrays_and_back @@ -18,7 +18,26 @@ def fft(x, n=None, axis=-1.0, norm="backward", name=None): @with_supported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( + "int32", + "int64", + "float32", + "float64", + ) + }, + "paddle", +) +@to_ivy_arrays_and_back +def fft2(x, s=None, axes=(-2, -1), norm="backward", name=None): + if axes is None: + axes = (-2, -1) + ret = ivy.fft2(x, s=s, dim=axes, norm=norm) + return ret + + +@with_supported_dtypes( + { + "2.6.0 and below": ( "int32", "int64", "float32", @@ -44,7 +63,7 @@ def fftfreq(n, d=1.0, dtype=None, name=None): @with_supported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "int32", "int64", "float32", @@ -73,13 +92,13 @@ def fftshift(x, axes=None, name=None): @with_supported_dtypes( - {"2.5.1 and below": ("complex64", "complex128")}, + {"2.6.0 and below": ("complex64", "complex128")}, "paddle", ) @to_ivy_arrays_and_back def hfft(x, n=None, axes=-1, norm="backward", name=None): - """Compute the FFT of a signal that has Hermitian symmetry, resulting in a real - spectrum.""" + """Compute the FFT of a signal that has Hermitian symmetry, resulting in a + real spectrum.""" # Determine the input shape and axis length input_shape = x.shape input_len = input_shape[axes] @@ -95,7 +114,7 @@ def hfft(x, n=None, axes=-1, norm="backward", name=None): @with_supported_dtypes( - {"2.5.1 and below": "complex64"}, + {"2.6.0 and below": "complex64"}, "paddle", ) @to_ivy_arrays_and_back @@ -116,7 +135,7 @@ def hfft2(x, s=None, axis=(-2, -1), norm="backward"): @with_supported_dtypes( - {"2.5.1 and below": ("complex64", "complex128")}, + {"2.6.0 and below": ("complex64", "complex128")}, "paddle", ) @to_ivy_arrays_and_back @@ -125,9 +144,19 @@ def ifft(x, n=None, axis=-1.0, norm="backward", name=None): return ivy.astype(ret, x.dtype) +@with_supported_dtypes( + {"2.6.0 and below": ("complex64", "complex128")}, + "paddle", +) +@to_ivy_arrays_and_back +def ifftn(x, s=None, axes=None, norm="backward", name=None): + ret = ivy.ifftn(ivy.astype(x, "complex128"), s=s, axes=axes, norm=norm) + return ivy.astype(ret, x.dtype) + + @with_supported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "int32", "int64", "float32", @@ -155,7 +184,7 @@ def ifftshift(x, axes=None, name=None): @with_supported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "int32", "int64", "float32", @@ -182,14 +211,34 @@ def ihfft2(x, s=None, axes=(-2, -1), norm="backward", name=None): if norm == "ortho": ihfft2_result = ivy.conj(ivy.rfftn(x_, s=s, axes=axes, norm="ortho")) - if x.dtype == ivy.float32 or x.dtype == ivy.int32 or x.dtype == ivy.int64: + if x.dtype in [ivy.float32, ivy.int32, ivy.int64]: return ivy.astype(ihfft2_result, ivy.complex64) if x.dtype == ivy.float64: return ivy.astype(ihfft2_result, ivy.complex128) +@to_ivy_arrays_and_back +def ihfftn(x, s=None, axes=None, norm="backward", name=None): + # cast the input to the same float64 type so that there are no backend issues + x_ = ivy.astype(x, ivy.float64) + + ihfftn_result = 0 + # Compute the complex conjugate of the 2-dimensional discrete Fourier Transform + if norm == "backward": + ihfftn_result = ivy.conj(ivy.rfftn(x_, s=s, axes=axes, norm="forward")) + if norm == "forward": + ihfftn_result = ivy.conj(ivy.rfftn(x_, s=s, axes=axes, norm="backward")) + if norm == "ortho": + ihfftn_result = ivy.conj(ivy.rfftn(x_, s=s, axes=axes, norm="ortho")) + + if x.dtype in [ivy.float32, ivy.int32, ivy.int64]: + return ivy.astype(ihfftn_result, ivy.complex64) + if x.dtype == ivy.float64: + return ivy.astype(ihfftn_result, ivy.complex128) + + @with_supported_dtypes( - {"2.5.1 and below": ("complex64", "complex128")}, + {"2.6.0 and below": ("complex64", "complex128")}, "paddle", ) @to_ivy_arrays_and_back @@ -208,7 +257,7 @@ def irfft(x, n=None, axis=-1.0, norm="backward", name=None): @with_supported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "int32", "int64", "float16", @@ -231,7 +280,7 @@ def irfft2(x, s=None, axes=(-2, -1), norm="backward"): # Calculate the normalization factor 'n' based on the shape 's' n = ivy.prod(ivy.array(s)) - result = ivy.ifftn(x, dim=axes[0], norm=norm) + result = ivy.ifftn(x, axes=axes[0], norm=norm) # Normalize the result based on the 'norm' parameter if norm == "backward": @@ -244,7 +293,7 @@ def irfft2(x, s=None, axes=(-2, -1), norm="backward"): @with_supported_dtypes( - {"2.5.1 and below": ("complex64", "complex128")}, + {"2.6.0 and below": ("complex64", "complex128")}, "paddle", ) @to_ivy_arrays_and_back @@ -295,7 +344,7 @@ def irfftn(x, s=None, axes=None, norm="backward", name=None): return result_t -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def rfft(x, n=None, axis=-1, norm="backward", name=None): return ivy.dft(x, axis=axis, inverse=False, onesided=True, dft_length=n, norm=norm) diff --git a/ivy/functional/frontends/paddle/func_wrapper.py b/ivy/functional/frontends/paddle/func_wrapper.py index c8c9e13acb0e0..4bc7db1821eb0 100644 --- a/ivy/functional/frontends/paddle/func_wrapper.py +++ b/ivy/functional/frontends/paddle/func_wrapper.py @@ -41,8 +41,7 @@ def _to_ivy_array(x): def inputs_to_ivy_arrays(fn: Callable) -> Callable: @functools.wraps(fn) def new_fn(*args, **kwargs): - """ - Convert `Tensor` into `ivy.Array` instances. + """Convert `Tensor` into `ivy.Array` instances. Convert all `Tensor` instances in both the positional and keyword arguments into `ivy.Array` instances, and then call the function with the updated @@ -64,8 +63,7 @@ def new_fn(*args, **kwargs): def outputs_to_frontend_arrays(fn: Callable) -> Callable: @functools.wraps(fn) def new_fn(*args, **kwargs): - """ - Convert `ivy.Array` into `Tensor` instances. + """Convert `ivy.Array` into `Tensor` instances. Call the function, and then convert all `ivy.Array` instances returned by the function into `Tensor` instances. @@ -89,8 +87,7 @@ def new_fn(*args, **kwargs): def to_ivy_arrays_and_back(fn: Callable) -> Callable: - """ - Wrap `fn` so it receives and returns `ivy.Array` instances. + """Wrap `fn` so it receives and returns `ivy.Array` instances. Wrap `fn` so that input arrays are all converted to `ivy.Array` instances and return arrays are all converted to `Tensor` instances. diff --git a/ivy/functional/frontends/paddle/linalg.py b/ivy/functional/frontends/paddle/linalg.py index e730b7b326027..559050e2dd0a9 100644 --- a/ivy/functional/frontends/paddle/linalg.py +++ b/ivy/functional/frontends/paddle/linalg.py @@ -14,7 +14,7 @@ def bincount(x, weights=None, minlength=0, name=None): # bmm -@with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") +@with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") @to_ivy_arrays_and_back def bmm(x, y, transpose_x=False, transpose_y=False, name=None): if len(ivy.shape(x)) != 3 or len(ivy.shape(y)) != 3: @@ -24,14 +24,14 @@ def bmm(x, y, transpose_x=False, transpose_y=False, name=None): # cholesky -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def cholesky(x, /, *, upper=False, name=None): return ivy.cholesky(x, upper=upper) # cholesky_solve -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def cholesky_solve(x, y, /, *, upper=False, name=None): if upper: @@ -41,7 +41,7 @@ def cholesky_solve(x, y, /, *, upper=False, name=None): # cond -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def cond(x, p=None, name=None): ret = ivy.cond(x, p=p, out=name) @@ -51,7 +51,7 @@ def cond(x, p=None, name=None): @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, "paddle" + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, "paddle" ) @to_ivy_arrays_and_back def cross(x, y, /, *, axis=9, name=None): @@ -62,7 +62,7 @@ def cross(x, y, /, *, axis=9, name=None): # diagonal @with_supported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "int32", "int64", "float64", @@ -87,7 +87,7 @@ def dist(x, y, p=2): # dot -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def dot(x, y, name=None): x, y = promote_types_of_paddle_inputs(x, y) @@ -151,7 +151,7 @@ def lu_unpack(lu_data, lu_pivots, unpack_datas=True, unpack_pivots=True, *, out= # matmul -@with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") +@with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") @to_ivy_arrays_and_back def matmul(x, y, transpose_x=False, transpose_y=False, name=None): x, y = promote_types_of_paddle_inputs(x, y) @@ -159,21 +159,21 @@ def matmul(x, y, transpose_x=False, transpose_y=False, name=None): # matrix_power -@with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") +@with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") @to_ivy_arrays_and_back def matrix_power(x, n, name=None): return ivy.matrix_power(x, n) # mv -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def mv(x, vec, name=None): return ivy.dot(x, vec) # norm -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def norm(x, p="fro", axis=None, keepdim=False, name=None): if axis is None and p is not None: @@ -205,7 +205,7 @@ def norm(x, p="fro", axis=None, keepdim=False, name=None): raise ValueError elif p == 1: ret = ivy.sum(ivy.abs(x), axis=axis, keepdims=keepdim) - elif p == 2 or p == "fro": + elif p in [2, "fro"]: ret = ivy.matrix_norm(x, ord="fro", axis=axis, keepdims=keepdim) elif p == ivy.inf: ret = ivy.max(ivy.abs(x), axis=axis, keepdims=keepdim) @@ -226,7 +226,7 @@ def norm(x, p="fro", axis=None, keepdim=False, name=None): # pinv -@with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") +@with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") @to_ivy_arrays_and_back def pinv(x, rcond=1e-15, hermitian=False, name=None): # TODO: Add hermitian functionality @@ -234,21 +234,21 @@ def pinv(x, rcond=1e-15, hermitian=False, name=None): # qr -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def qr(x, mode="reduced", name=None): return ivy.qr(x, mode=mode) # solve -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def solve(x, y, name=None): return ivy.solve(x, y) # transpose -@with_unsupported_dtypes({"2.5.1 and below": ("uint8", "int8", "int16")}, "paddle") +@with_unsupported_dtypes({"2.6.0 and below": ("uint8", "int8", "int16")}, "paddle") @to_ivy_arrays_and_back def transpose(x, perm, name=None): return ivy.permute_dims(x, axes=perm) diff --git a/ivy/functional/frontends/paddle/logic.py b/ivy/functional/frontends/paddle/logic.py index 8b691b4380d42..45bb6cd12fc10 100644 --- a/ivy/functional/frontends/paddle/logic.py +++ b/ivy/functional/frontends/paddle/logic.py @@ -13,7 +13,7 @@ @with_supported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "float32", "float64", "bool", @@ -35,7 +35,7 @@ def allclose(x, y, rtol=1e-05, atol=1e-08, equal_nan=False, name=None): @with_supported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "bool", "uint8", "int8", @@ -54,7 +54,7 @@ def bitwise_and(x, y, /, *, name=None, out=None): @with_supported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "bool", "uint8", "int8", @@ -73,7 +73,7 @@ def bitwise_not(x, out=None, name=None): @with_supported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "bool", "uint8", "int8", @@ -92,7 +92,7 @@ def bitwise_or(x, y, name=None, out=None): @with_supported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "bool", "uint8", "int8", @@ -110,7 +110,8 @@ def bitwise_xor(x, y, /, *, name=None, out=None): @with_unsupported_dtypes( - {"2.5.1 and below": ("uint8", "int8", "int16", "complex64", "complex128")}, "paddle" + {"2.6.0 and below": ("uint8", "int8", "int16", "complex64", "complex128")}, + "paddle", ) @to_ivy_arrays_and_back def equal(x, y, /, *, name=None): @@ -119,7 +120,7 @@ def equal(x, y, /, *, name=None): @with_unsupported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "uint8", "int8", "int16", @@ -136,7 +137,7 @@ def equal_all(x, y, /, *, name=None): @with_unsupported_dtypes( - {"2.5.1 and below": ("bool", "uint8", "int8", "int16", "complex64", "complex128")}, + {"2.6.0 and below": ("bool", "uint8", "int8", "int16", "complex64", "complex128")}, "paddle", ) @to_ivy_arrays_and_back @@ -145,7 +146,7 @@ def greater_equal(x, y, /, *, name=None): @with_unsupported_dtypes( - {"2.5.1 and below": ("bool", "uint8", "int8", "int16", "complex64", "complex128")}, + {"2.6.0 and below": ("bool", "uint8", "int8", "int16", "complex64", "complex128")}, "paddle", ) @to_ivy_arrays_and_back @@ -154,7 +155,8 @@ def greater_than(x, y, /, *, name=None): @with_unsupported_dtypes( - {"2.5.1 and below": ("uint8", "int8", "int16", "complex64", "complex128")}, "paddle" + {"2.6.0 and below": ("uint8", "int8", "int16", "complex64", "complex128")}, + "paddle", ) @to_ivy_arrays_and_back def is_empty(x, name=None): @@ -168,7 +170,7 @@ def is_tensor(x): @with_supported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "float32", "float64", ) @@ -181,7 +183,7 @@ def isclose(x, y, rtol=1e-05, atol=1e-08, equal_nan=False, name=None): @with_unsupported_dtypes( - {"2.5.1 and below": ("bool", "uint8", "int8", "int16", "complex64", "complex128")}, + {"2.6.0 and below": ("bool", "uint8", "int8", "int16", "complex64", "complex128")}, "paddle", ) @to_ivy_arrays_and_back @@ -190,7 +192,7 @@ def less_equal(x, y, /, *, name=None): @with_supported_dtypes( - {"2.5.1 and below": ("bool", "float16", "float32", "float64", "int32", "int64")}, + {"2.6.0 and below": ("bool", "float16", "float32", "float64", "int32", "int64")}, "paddle", ) @to_ivy_arrays_and_back @@ -200,7 +202,7 @@ def less_than(x, y, /, *, name=None): @with_supported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "bool", "int8", "int16", @@ -220,7 +222,7 @@ def logical_and(x, y, /, *, name=None, out=None): @with_supported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "bool", "int8", "int16", @@ -240,7 +242,7 @@ def logical_not(x, /, *, name=None, out=None): @with_supported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "bool", "int8", "int16", @@ -260,7 +262,7 @@ def logical_or(x, y, /, *, name=None, out=None): @with_supported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "bool", "int8", "int16", @@ -279,7 +281,8 @@ def logical_xor(x, y, /, *, name=None, out=None): @with_unsupported_dtypes( - {"2.5.1 and below": ("uint8", "int8", "int16", "complex64", "complex128")}, "paddle" + {"2.6.0 and below": ("uint8", "int8", "int16", "complex64", "complex128")}, + "paddle", ) @to_ivy_arrays_and_back def not_equal(x, y, /, *, name=None): diff --git a/ivy/functional/frontends/paddle/manipulation.py b/ivy/functional/frontends/paddle/manipulation.py index 5c99d82d61ccf..dd7c7e79a28f9 100644 --- a/ivy/functional/frontends/paddle/manipulation.py +++ b/ivy/functional/frontends/paddle/manipulation.py @@ -10,14 +10,14 @@ ) -@with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") +@with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") @to_ivy_arrays_and_back def abs(x, name=None): return ivy.abs(x) @with_supported_dtypes( - {"2.5.1 and below": ("bool", "float32", "float64", "int32", "int64")}, + {"2.6.0 and below": ("bool", "float32", "float64", "int32", "int64")}, "paddle", ) @to_ivy_arrays_and_back @@ -27,7 +27,7 @@ def broadcast_to(x, shape, name=None): @with_supported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "bool", "float16", "float32", @@ -44,14 +44,14 @@ def cast(x, dtype): return ivy.astype(x, dtype) -@with_unsupported_dtypes({"2.5.1 and below": ("int8", "int16")}, "paddle") +@with_unsupported_dtypes({"2.6.0 and below": ("int8", "int16")}, "paddle") @to_ivy_arrays_and_back def concat(x, axis, name=None): return ivy.concat(x, axis=axis) @with_supported_dtypes( - {"2.5.1 and below": ("bool", "float32", "float64", "int32", "int64")}, + {"2.6.0 and below": ("bool", "float32", "float64", "int32", "int64")}, "paddle", ) @to_ivy_arrays_and_back @@ -60,7 +60,7 @@ def expand(x, shape, name=None): @with_unsupported_dtypes( - {"2.5.1 and below": ("int8", "uint8", "int16", "float16")}, + {"2.6.0 and below": ("int8", "uint8", "int16", "float16")}, "paddle", ) @to_ivy_arrays_and_back @@ -69,7 +69,7 @@ def flip(x, axis, name=None): @with_supported_dtypes( - {"2.5.1 and below": ("bool", "float32", "float64", "int32", "int64")}, + {"2.6.0 and below": ("bool", "float32", "float64", "int32", "int64")}, "paddle", ) @to_ivy_arrays_and_back @@ -78,7 +78,7 @@ def gather(params, indices, axis=-1, batch_dims=0, name=None): @with_unsupported_dtypes( - {"2.5.1 and below": ("int8", "uint8", "int16", "uint16", "float16", "bfloat16")}, + {"2.6.0 and below": ("int8", "uint8", "int16", "uint16", "float16", "bfloat16")}, "paddle", ) @to_ivy_arrays_and_back @@ -86,6 +86,37 @@ def gather_nd(x, index, name=None): return ivy.gather_nd(x, index) +@with_supported_dtypes( + {"2.6.0 and below": ("bool", "int32", "int64", "float16", "float32", "float64")}, + "paddle", +) +@to_ivy_arrays_and_back +def index_add(x, index, axis, value, *, name=None): + x = ivy.swapaxes(x, axis, 0) + value = ivy.swapaxes(value, axis, 0) + _to_adds = [] + index = sorted(zip(ivy.to_list(index), range(len(index))), key=(lambda i: i[0])) + while index: + _curr_idx = index[0][0] + while len(_to_adds) < _curr_idx: + _to_adds.append(ivy.zeros_like(value[0])) + _to_add_cum = ivy.get_item(value, index[0][1]) + while (len(index)) > 1 and (index[0][0] == index[1][0]): + _to_add_cum = _to_add_cum + ivy.get_item(value, index.pop(1)[1]) + index.pop(0) + _to_adds.append(_to_add_cum) + while len(_to_adds) < x.shape[0]: + _to_adds.append(ivy.zeros_like(value[0])) + _to_adds = ivy.stack(_to_adds) + if len(x.shape) < 2: + # Added this line due to the paddle backend treating scalars as 1-d arrays + _to_adds = ivy.flatten(_to_adds) + + ret = ivy.add(x, _to_adds) + ret = ivy.swapaxes(ret, axis, 0) + return ret + + @to_ivy_arrays_and_back def put_along_axis(arr, indices, values, axis, reduce="assign"): result = ivy.put_along_axis(arr, indices, values, axis) @@ -93,7 +124,7 @@ def put_along_axis(arr, indices, values, axis, reduce="assign"): @with_supported_dtypes( - {"2.5.1 and below": ("int32", "int64", "float32", "float64")}, + {"2.6.0 and below": ("int32", "int64", "float32", "float64")}, "paddle", ) @to_ivy_arrays_and_back @@ -126,7 +157,7 @@ def roll(x, shifts, axis=None, name=None): @with_supported_device_and_dtypes( { - "2.5.1 and above": { + "2.6.0 and above": { "cpu": ( "bool", "int32", @@ -145,7 +176,7 @@ def rot90(x, k=1, axes=(0, 1), name=None): @with_unsupported_dtypes( - {"2.5.1 and below": ("int16", "complex64", "complex128")}, + {"2.6.0 and below": ("int16", "complex64", "complex128")}, "paddle", ) @to_ivy_arrays_and_back @@ -154,7 +185,7 @@ def split(x, num_or_sections, axis=0, name=None): @with_unsupported_dtypes( - {"2.5.1 and below": ("float16", "bfloat16", "int8", "int16")}, + {"2.6.0 and below": ("float16", "bfloat16", "int8", "int16")}, "paddle", ) @to_ivy_arrays_and_back @@ -167,12 +198,17 @@ def stack(x, axis=0, name=None): return ivy.stack(x, axis=axis) +@with_supported_dtypes( + {"2.6.0 and below": ("float32", "float64")}, + "paddle", +) +@to_ivy_arrays_and_back def take_along_axis(arr, indices, axis): return ivy.take_along_axis(arr, indices, axis) @with_unsupported_dtypes( - {"2.5.1 and below": ("int8", "uint8", "int16", "float16")}, + {"2.6.0 and below": ("int8", "uint8", "int16", "float16")}, "paddle", ) @to_ivy_arrays_and_back @@ -186,7 +222,7 @@ def tolist(x): @with_supported_dtypes( - {"2.5.1 and below": ("bool", "int32", "int64", "float16", "float32", "float64")}, + {"2.6.0 and below": ("bool", "int32", "int64", "float16", "float32", "float64")}, "paddle", ) @to_ivy_arrays_and_back @@ -194,11 +230,11 @@ def unbind(input, axis=0): shape = list(input.shape) num_splits = shape[axis] shape.pop(axis) - return tuple([x.reshape(tuple(shape)) for x in split(input, num_splits, axis=axis)]) + return tuple(x.reshape(tuple(shape)) for x in split(input, num_splits, axis=axis)) @with_supported_dtypes( - {"2.5.1 and below": ("bool", "int32", "int64", "float16", "float32", "float64")}, + {"2.6.0 and below": ("bool", "int32", "int64", "float16", "float32", "float64")}, "paddle", ) @to_ivy_arrays_and_back @@ -208,7 +244,7 @@ def unique_consecutive(x, axis=0): @with_supported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "float32", "float64", "int32", diff --git a/ivy/functional/frontends/paddle/math.py b/ivy/functional/frontends/paddle/math.py index 29aefc5ca5d8f..a70fc6179477f 100644 --- a/ivy/functional/frontends/paddle/math.py +++ b/ivy/functional/frontends/paddle/math.py @@ -8,26 +8,26 @@ from ivy.functional.frontends.paddle.func_wrapper import to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") +@with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") @to_ivy_arrays_and_back def abs(x, name=None): return ivy.abs(x) -@with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") +@with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") @to_ivy_arrays_and_back def acos(x, name=None): return ivy.acos(x) -@with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") +@with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") @to_ivy_arrays_and_back def acosh(x, name=None): return ivy.acosh(x) @with_unsupported_dtypes( - {"2.5.1 and below": ("bool", "unsigned", "int8", "float16", "bfloat16")}, "paddle" + {"2.6.0 and below": ("bool", "unsigned", "int8", "float16", "bfloat16")}, "paddle" ) @to_ivy_arrays_and_back def add(x, y, name=None): @@ -35,7 +35,7 @@ def add(x, y, name=None): @with_unsupported_dtypes( - {"2.5.1 and below": ("bool", "unsigned", "int8", "float16", "bfloat16")}, "paddle" + {"2.6.0 and below": ("bool", "unsigned", "int8", "float16", "bfloat16")}, "paddle" ) @to_ivy_arrays_and_back def add_(x, y, name=None): @@ -43,7 +43,7 @@ def add_(x, y, name=None): @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, "paddle" + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, "paddle" ) @to_ivy_arrays_and_back def addmm(input, x, y, beta=1.0, alpha=1.0, name=None): @@ -58,7 +58,7 @@ def all(x, axis, keepdim=False, name=None): @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, "paddle" + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, "paddle" ) @to_ivy_arrays_and_back def amax(x, axis=None, keepdims=False): @@ -76,7 +76,7 @@ def amax(x, axis=None, keepdims=False): @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, "paddle" + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, "paddle" ) @to_ivy_arrays_and_back def amin(x, axis=None, keepdim=False, name=None): @@ -84,7 +84,7 @@ def amin(x, axis=None, keepdim=False, name=None): @with_supported_dtypes( - {"2.5.1 and below": ("complex64", "complex128", "float32", "float64")}, + {"2.6.0 and below": ("complex64", "complex128", "float32", "float64")}, "paddle", ) @to_ivy_arrays_and_back @@ -98,19 +98,19 @@ def any(x, axis=None, keepdim=False, name=None): return ivy.any(x, axis=axis, keepdims=keepdim) -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def asin(x, name=None): return ivy.asin(x) -@with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") +@with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") @to_ivy_arrays_and_back def asinh(x, name=None): return ivy.asinh(x) -@with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") +@with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") @to_ivy_arrays_and_back def atan(x, name=None): return ivy.atan(x) @@ -122,19 +122,19 @@ def atan2(x, y, name=None): return ivy.atan2(x, y) -@with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") +@with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") @to_ivy_arrays_and_back def atanh(x, name=None): return ivy.atanh(x) -@with_supported_dtypes({"2.5.1 and below": ("int32", "int64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("int32", "int64")}, "paddle") @to_ivy_arrays_and_back def broadcast_shape(x_shape, y_shape): return ivy.broadcast_shapes(x_shape, y_shape) -@with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") +@with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") @to_ivy_arrays_and_back def ceil(x, name=None): return ivy.ceil(x) @@ -146,20 +146,20 @@ def conj(x, name=None): return ivy.conj(x) -@with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") +@with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") @to_ivy_arrays_and_back def cos(x, name=None): return ivy.cos(x) -@with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") +@with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") @to_ivy_arrays_and_back def cosh(x, name=None): return ivy.cosh(x) @with_supported_dtypes( - {"2.5.1 and below": ("int32", "int64", "float16", "float32", "float64", "bool")}, + {"2.6.0 and below": ("int32", "int64", "float16", "float32", "float64", "bool")}, "paddle", ) @to_ivy_arrays_and_back @@ -169,7 +169,7 @@ def count_nonzero(x, axis=None, keepdim=False, name=None): @with_supported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "int32", "int64", "float32", @@ -186,14 +186,14 @@ def cumprod(x, dim=None, dtype=None, name=None): @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, "paddle" + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, "paddle" ) @to_ivy_arrays_and_back def cumsum(x, axis=None, dtype=None, name=None): return ivy.cumsum(x, axis=axis, dtype=dtype) -@with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") +@with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") @to_ivy_arrays_and_back def deg2rad(x, name=None): return ivy.deg2rad(x) @@ -201,7 +201,7 @@ def deg2rad(x, name=None): @with_supported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "int32", "int64", "float64", @@ -219,80 +219,90 @@ def diagonal(x, offset=0, axis1=0, axis2=1, name=None): @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, "paddle" + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, "paddle" ) @to_ivy_arrays_and_back def diff(x, n=1, axis=-1, prepend=None, append=None, name=None): return ivy.diff(x, n=n, axis=axis, prepend=prepend, append=append) -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def digamma(x, name=None): digamma_fun = ivy.digamma return ivy.array(digamma_fun(x), dtype=x.dtype) -@with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") +@with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") @to_ivy_arrays_and_back def divide(x, y, name=None): return ivy.divide(x, y) -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def erf(x, name=None): return ivy.erf(x) -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def exp(x, name=None): return ivy.exp(x) -@with_supported_dtypes({"2.5.1 and below": ("float16", "float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float16", "float32", "float64")}, "paddle") @to_ivy_arrays_and_back def expm1(x, name=None): return ivy.expm1(x) @with_supported_dtypes( - {"2.5.1 and below": ("bfloat16", "float32", "float64")}, "paddle" + {"2.6.0 and below": ("bfloat16", "float32", "float64")}, "paddle" ) @to_ivy_arrays_and_back def floor(x, name=None): return ivy.floor(x) -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def floor_divide(x, y, name=None): return ivy.floor_divide(x, y) -@with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, "paddle" +@with_supported_device_and_dtypes( + { + "2.6.0 and below": { + "cpu": ("float32", "float64", "int32", "int64"), + "gpu": ("float16", "float32", "float64", "int32", "int64"), + } + }, + "paddle", ) @to_ivy_arrays_and_back def floor_mod(x, y, name=None): return ivy.remainder(x, y) -@with_unsupported_dtypes({"2.5.1 and below": "bfloat16"}, "paddle") +@with_supported_dtypes( + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, "paddle" +) @to_ivy_arrays_and_back def fmax(x, y, name=None): return ivy.fmax(x, y) -@with_unsupported_dtypes({"2.5.1 and below": "bfloat16"}, "paddle") +@with_supported_dtypes( + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, "paddle" +) @to_ivy_arrays_and_back def fmin(x, y, name=None): return ivy.fmin(x, y) @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, "paddle" + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, "paddle" ) @to_ivy_arrays_and_back def frac(x, name=None): @@ -300,21 +310,21 @@ def frac(x, name=None): return ivy.subtract(x, y) -@with_supported_dtypes({"2.5.1 and below": ("int32", "int64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("int32", "int64")}, "paddle") @to_ivy_arrays_and_back def gcd(x, y, name=None): return ivy.gcd(x, y) @with_supported_dtypes( - {"2.5.1 and below": ("float16", "float32", "float64", "int32", "int64")}, "paddle" + {"2.6.0 and below": ("float16", "float32", "float64", "int32", "int64")}, "paddle" ) @to_ivy_arrays_and_back def heaviside(x, y, name=None): return ivy.heaviside(x, y) -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def inner(x, y, name=None): result = ivy.inner(x, y) @@ -325,8 +335,14 @@ def inner(x, y, name=None): return result +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") +@to_ivy_arrays_and_back +def inverse(x, name=None): + return ivy.inv(x) + + @with_supported_dtypes( - {"2.5.1 and below": ("float16", "float32", "float64", "int32", "int64")}, "paddle" + {"2.6.0 and below": ("float16", "float32", "float64", "int32", "int64")}, "paddle" ) @to_ivy_arrays_and_back def isfinite(x, name=None): @@ -334,7 +350,7 @@ def isfinite(x, name=None): @with_supported_dtypes( - {"2.5.1 and below": ("float16", "float32", "float64", "int32", "int64")}, "paddle" + {"2.6.0 and below": ("float16", "float32", "float64", "int32", "int64")}, "paddle" ) @to_ivy_arrays_and_back def isinf(x, name=None): @@ -342,7 +358,7 @@ def isinf(x, name=None): @with_supported_dtypes( - {"2.5.1 and below": ("float16", "float32", "float64", "int32", "int64")}, "paddle" + {"2.6.0 and below": ("float16", "float32", "float64", "int32", "int64")}, "paddle" ) @to_ivy_arrays_and_back def isnan(x, name=None): @@ -350,63 +366,86 @@ def isnan(x, name=None): @with_supported_dtypes( - {"2.5.1 and below": ("float16", "float32", "float64", "int32", "int64")}, "paddle" + {"2.6.0 and below": ("float16", "float32", "float64", "int32", "int64")}, "paddle" ) @to_ivy_arrays_and_back def kron(x, y, name=None): return ivy.kron(x, y) -@with_supported_dtypes({"2.5.1 and below": ("int32", "int64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("int32", "int64")}, "paddle") @to_ivy_arrays_and_back def lcm(x, y, name=None): return ivy.lcm(x, y) -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def lerp(x, y, weight, name=None): return ivy.lerp(x, y, weight) -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def lgamma(x, name=None): return ivy.lgamma(x) -@with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") +@with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") @to_ivy_arrays_and_back def log(x, name=None): return ivy.log(x) -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def log10(x, name=None): return ivy.log10(x) -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def log1p(x, name=None): return ivy.log1p(x) -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def log2(x, name=None): return ivy.log2(x) -@with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") +@with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") @to_ivy_arrays_and_back def logit(x, eps=None, name=None): return ivy.logit(x, eps=eps) +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") +@to_ivy_arrays_and_back +def logsumexp(x, axis=None, y=None): + x = ivy.asarray(x) + if y is not None: + y = ivy.asarray(y) + x = ivy.where(y != 0, x, -ivy.inf) + if axis is None: + amax = ivy.max(x) + expsub = ivy.exp(x - amax) + sumexp = ivy.sum(expsub) + out = ivy.log(sumexp) + amax + else: + amax = ivy.max(x, axis=axis, keepdims=True) + expsub = ivy.exp(x - amax) + sumexp = ivy.sum(expsub, axis=axis, keepdims=True) + out = ivy.log(sumexp) + amax + if y is not None: + sign = ivy.stop_gradient(ivy.sign(sumexp)) + out = ivy.where(sign < 0, ivy.nan, out) + return out + + @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, "paddle" + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, "paddle" ) @to_ivy_arrays_and_back def max(x, axis=None, keepdim=False, name=None): @@ -414,14 +453,14 @@ def max(x, axis=None, keepdim=False, name=None): # maximum -@with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") +@with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") @to_ivy_arrays_and_back def maximum(x, y, name=None): return ivy.maximum(x, y) @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, "paddle" + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, "paddle" ) @to_ivy_arrays_and_back def min(x, axis=None, keepdim=False, name=None): @@ -429,7 +468,7 @@ def min(x, axis=None, keepdim=False, name=None): @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, "paddle" + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, "paddle" ) @to_ivy_arrays_and_back def minimum(x, y, name=None): @@ -437,27 +476,27 @@ def minimum(x, y, name=None): @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, "paddle" + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, "paddle" ) @to_ivy_arrays_and_back def mm(input, mat2, name=None): return ivy.matmul(input, mat2) -@with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") +@with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") @to_ivy_arrays_and_back def multiply(x, y, name=None): return ivy.multiply(x, y) -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def nanmean(x, axis=None, keepdims=False): return ivy.nanmean(x, axis=axis, keepdims=keepdims) @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, "paddle" + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, "paddle" ) @to_ivy_arrays_and_back def nansum(x, axis=None, dtype=None, name=None): @@ -465,7 +504,7 @@ def nansum(x, axis=None, dtype=None, name=None): @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int8", "int16", "int32", "int64")}, + {"2.6.0 and below": ("float32", "float64", "int8", "int16", "int32", "int64")}, "paddle", ) @to_ivy_arrays_and_back @@ -473,39 +512,41 @@ def neg(x, name=None): return ivy.negative(x) -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def outer(x, y, name=None): return ivy.outer(x, y) -@with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") +@with_supported_dtypes( + {"2.6.0 and below": ("float16", "float32", "float64", "int32", "int64")}, "paddle" +) @to_ivy_arrays_and_back def pow(x, y, name=None): return ivy.pow(x, y) @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, "paddle" + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, "paddle" ) @to_ivy_arrays_and_back def prod(x, axis=None, keepdim=False, dtype=None, name=None): return ivy.prod(x, axis=axis, keepdims=keepdim, dtype=dtype) -@with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") +@with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") @to_ivy_arrays_and_back def rad2deg(x, name=None): return ivy.rad2deg(x) -@with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") +@with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") @to_ivy_arrays_and_back def reciprocal(x, name=None): return ivy.reciprocal(x) -@with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") +@with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") @to_ivy_arrays_and_back def remainder(x, y, name=None): return ivy.remainder(x, y) @@ -513,7 +554,7 @@ def remainder(x, y, name=None): @with_supported_device_and_dtypes( { - "2.5.1 and below": { + "2.6.0 and below": { "cpu": ("float32", "float64"), "gpu": ("float16", "float32", "float64"), } @@ -525,7 +566,7 @@ def remainder_(x, y, name=None): return ivy.inplace_update(x, remainder(x, y)) -@with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") +@with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") @to_ivy_arrays_and_back def round(x, name=None): sign = ivy.sign(x) @@ -533,49 +574,49 @@ def round(x, name=None): return x -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def rsqrt(x, name=None): return 1 / ivy.sqrt(x) -@with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") +@with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") @to_ivy_arrays_and_back def sgn(x, name=None): return ivy.sign(x, np_variant=True) -@with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") +@with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") @to_ivy_arrays_and_back def sign(x, name=None): return ivy.sign(x, np_variant=False) -@with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") +@with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") @to_ivy_arrays_and_back def sin(x, name=None): return ivy.sin(x) -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def sinh(x, name=None): return ivy.sinh(x) -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def sqrt(x, name=None): return ivy.sqrt(x) -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def square(x, name=None): return ivy.square(x) -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def stanh(x, scale_a=0.67, scale_b=1.7159, name=None): # TODO this function will be simplified as soon as the ivy.stanh(x,a,b) is added @@ -587,7 +628,7 @@ def stanh(x, scale_a=0.67, scale_b=1.7159, name=None): return ret -@with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") +@with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") @to_ivy_arrays_and_back def subtract(x, y, name=None): return ivy.subtract(x, y) @@ -595,7 +636,7 @@ def subtract(x, y, name=None): @with_supported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "float64", "int64", ) @@ -613,7 +654,7 @@ def sum(x, axis=None, dtype=None, keepdim=False, name=None): @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int6")}, "paddle" + {"2.6.0 and below": ("float32", "float64", "int32", "int6")}, "paddle" ) @to_ivy_arrays_and_back def take( @@ -635,20 +676,20 @@ def take( return ivy.gather(x, index, axis=0) -@with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") +@with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") @to_ivy_arrays_and_back def tan(x, name=None): return ivy.tan(x) -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def tanh(x, name=None): return ivy.tanh(x) @with_supported_dtypes( - {"2.5.1 and below": ("int32", "int64", "float32", "float64")}, "paddle" + {"2.6.0 and below": ("int32", "int64", "float32", "float64")}, "paddle" ) @to_ivy_arrays_and_back def trace(x, offset=0, axis1=0, axis2=1, name=None): @@ -661,3 +702,6 @@ def trace(x, offset=0, axis1=0, axis2=1, name=None): @to_ivy_arrays_and_back def trunc(x, name=None): return ivy.trunc(x) + + +mod = remainder diff --git a/ivy/functional/frontends/paddle/nn/functional/activation.py b/ivy/functional/frontends/paddle/nn/functional/activation.py index 19abc10559ea9..da520c585e761 100644 --- a/ivy/functional/frontends/paddle/nn/functional/activation.py +++ b/ivy/functional/frontends/paddle/nn/functional/activation.py @@ -8,7 +8,7 @@ tanh = paddle_tanh -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def celu( x, @@ -20,7 +20,7 @@ def celu( return ivy.celu(x, alpha=alpha) -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def elu( x, @@ -32,13 +32,13 @@ def elu( return ivy.elu(x, alpha=alpha) -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def gelu(x, approximate=False, name=None): return ivy.gelu(x, approximate=approximate) -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def glu(x, axis=-1, name=None): size = x.shape[axis] @@ -63,21 +63,21 @@ def gumbel_softmax(x, temperature=1.0, hard=False, axis=-1, name=None): return y_soft -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def hardshrink(x, threshold=0.5, name=None): mask = ivy.logical_or(ivy.greater(x, threshold), ivy.less(x, -threshold)) return ivy.where(mask, x, 0.0) -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def hardsigmoid(x, slope=0.1666667, offset=0.5, name=None): ret = ivy.minimum(ivy.maximum(ivy.add(ivy.multiply(x, slope), offset), 0), 1) return ret -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def hardswish(x, name=None): relu6_val = ivy.relu6(ivy.add(x, 3)) @@ -85,7 +85,7 @@ def hardswish(x, name=None): return ret -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def hardtanh( x, @@ -106,13 +106,13 @@ def leaky_relu(x, negative_slope=0.01, name=None): return ivy.leaky_relu(x) -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def log_sigmoid(x, name=None): return -ivy.softplus(-x) -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def log_softmax(x, axis=-1, dtype=None, name=None): x = ivy.astype(x, dtype) if dtype else x @@ -121,31 +121,31 @@ def log_softmax(x, axis=-1, dtype=None, name=None): return ret -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def mish(x, name=None): return ivy.mish(x) -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def prelu(x, weight, data_format="NCHW", name=None): return ivy.add(ivy.maximum(0, x), ivy.multiply(weight, ivy.minimum(0, x))) -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def relu(x, name=None): return ivy.relu(x) -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def relu6(x, name=None): return ivy.relu6(x) -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def relu_(x, name=None): ret = ivy.relu(x) @@ -153,7 +153,7 @@ def relu_(x, name=None): return x -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def rrelu( x, @@ -189,7 +189,7 @@ def rrelu( return out.astype(x.dtype) -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def selu( x, @@ -222,13 +222,13 @@ def softmax_(x, axis=-1, dtype=None, name=None): return x -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def softplus(x, beta=1, threshold=20, name=None): return ivy.softplus(x, beta=beta, threshold=threshold) -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def softshrink( x, @@ -243,7 +243,7 @@ def softshrink( return ivy.astype(add, x.dtype) -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def softsign( x, @@ -254,7 +254,7 @@ def softsign( return ivy.divide(x, ivy.add(1, ivy.abs(x))) -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def swish(x, name=None): return ivy.multiply(x, ivy.sigmoid(x)) @@ -273,7 +273,7 @@ def tanh_(x, name=None): # return ret.astype(x.dtype) -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def tanhshrink( x, diff --git a/ivy/functional/frontends/paddle/nn/functional/common.py b/ivy/functional/frontends/paddle/nn/functional/common.py index 58c54085ee571..882ce9a543f64 100644 --- a/ivy/functional/frontends/paddle/nn/functional/common.py +++ b/ivy/functional/frontends/paddle/nn/functional/common.py @@ -5,7 +5,7 @@ @to_ivy_arrays_and_back -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def cosine_similarity(x1, x2, *, axis=1, eps=1e-08): if len(x1.shape) == len(x2.shape) and len(x2.shape) >= 2: numerator = ivy.sum(x1 * x2, axis=axis) @@ -26,7 +26,7 @@ def cosine_similarity(x1, x2, *, axis=1, eps=1e-08): @to_ivy_arrays_and_back -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def dropout(x, p=0.5, axis=None, training=True, mode="upscale_in_train", name=None): if axis is not None and axis > 1: raise ValueError("Axis value can only be 0 or 1 or None.") @@ -53,13 +53,13 @@ def dropout(x, p=0.5, axis=None, training=True, mode="upscale_in_train", name=No @to_ivy_arrays_and_back -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def dropout2d(x, *, p=0.5, training=True, data_format="NCHW", name=None): - return ivy.dropout2d(x, p=p, training=training, data_format=data_format) + return ivy.dropout2d(x, p, training=training, data_format=data_format) @to_ivy_arrays_and_back -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def dropout3d(x, p=0.5, training=True, data_format="NCDHW", name=None): return ivy.dropout3d(x, p, training=training, data_format=data_format) @@ -74,7 +74,7 @@ def get_mask(shape, device, prob, seed=None): @to_ivy_arrays_and_back -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def interpolate( x, size=None, @@ -91,19 +91,19 @@ def interpolate( @to_ivy_arrays_and_back -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def linear(x, weight, bias=None, name=None): weight = ivy.swapaxes(weight, -1, -2) return ivy.linear(x, weight, bias=bias) @to_ivy_arrays_and_back -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def unfold(x, kernel_sizes, strides=1, paddings=0, dilations=1, name=None): # Input checking if isinstance(kernel_sizes, int): kernel_sizes = [kernel_sizes, kernel_sizes] - elif not (isinstance(kernel_sizes, (list, tuple))): + elif not isinstance(kernel_sizes, (list, tuple)): raise ivy.exceptions.IvyError( "Expected kernel size input as type int, tuple or list but got" f" {type(kernel_sizes)}" @@ -111,14 +111,14 @@ def unfold(x, kernel_sizes, strides=1, paddings=0, dilations=1, name=None): if isinstance(strides, int): strides = [strides, strides] - elif not (isinstance(strides, (list, tuple))): + elif not isinstance(strides, (list, tuple)): raise ivy.exceptions.IvyError( f"Expected strides input as type int, tuple or list but got {type(strides)}" ) if isinstance(dilations, int): dilations = [dilations, dilations] - elif not (isinstance(dilations, (list, tuple))): + elif not isinstance(dilations, (list, tuple)): raise ivy.exceptions.IvyError( "Expected dilations input as type int, tuple or list but got" f" {type(dilations)}" @@ -126,7 +126,7 @@ def unfold(x, kernel_sizes, strides=1, paddings=0, dilations=1, name=None): if isinstance(paddings, int): paddings = [paddings, paddings] - elif not (isinstance(paddings, (list, tuple))): + elif not isinstance(paddings, (list, tuple)): raise ivy.exceptions.IvyError( "Expected paddings, input as type int, tuple or list but got" f" {type(paddings)}" @@ -178,7 +178,7 @@ def unfold(x, kernel_sizes, strides=1, paddings=0, dilations=1, name=None): @to_ivy_arrays_and_back -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def zeropad2d(x, padding, data_format="NCHW", name=None): if ivy.is_array(padding): padding = padding.to_list() diff --git a/ivy/functional/frontends/paddle/nn/functional/conv.py b/ivy/functional/frontends/paddle/nn/functional/conv.py index b9a0f4a37335f..43e7699eba218 100644 --- a/ivy/functional/frontends/paddle/nn/functional/conv.py +++ b/ivy/functional/frontends/paddle/nn/functional/conv.py @@ -79,7 +79,7 @@ def _conv_transpose( # ------------ # -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def conv1d( x, @@ -95,7 +95,7 @@ def conv1d( return _conv(x, weight, bias, stride, padding, dilation, groups, data_format) -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def conv1d_transpose( x, @@ -115,7 +115,7 @@ def conv1d_transpose( ) -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def conv2d( x, @@ -131,7 +131,7 @@ def conv2d( return _conv(x, weight, bias, stride, padding, dilation, groups, data_format) -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def conv2d_transpose( x, @@ -151,7 +151,7 @@ def conv2d_transpose( ) -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def conv3d( x, @@ -167,7 +167,7 @@ def conv3d( return _conv(x, weight, bias, stride, padding, dilation, groups, data_format) -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def conv3d_transpose( x, diff --git a/ivy/functional/frontends/paddle/nn/functional/loss.py b/ivy/functional/frontends/paddle/nn/functional/loss.py index 84a80cb6cadc7..41cf9f9ab8d1e 100644 --- a/ivy/functional/frontends/paddle/nn/functional/loss.py +++ b/ivy/functional/frontends/paddle/nn/functional/loss.py @@ -47,7 +47,7 @@ def _pairwise_distance(x1, x2, *, p=2.0, eps=1e-06, keepdim=False): # ------------ # -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def binary_cross_entropy(input, label, weight=None, reduction="mean", name=None): reduction = _get_reduction_func(reduction) @@ -59,7 +59,7 @@ def binary_cross_entropy(input, label, weight=None, reduction="mean", name=None) @with_supported_dtypes( - {"2.5.1 and below": ("float32",)}, + {"2.6.0 and below": ("float32",)}, "paddle", ) @inputs_to_ivy_arrays @@ -83,7 +83,7 @@ def binary_cross_entropy_with_logits( @handle_exceptions @to_ivy_arrays_and_back -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def cosine_embedding_loss( input1, input2, label, margin=0.0, reduction="mean", name=None ): @@ -124,7 +124,7 @@ def cosine_embedding_loss( return out -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def dice_loss(input, label, epsilon=0.00001, name=None): ivy.assertions.check_true( @@ -135,14 +135,13 @@ def dice_loss(input, label, epsilon=0.00001, name=None): len(input.shape) == len(label.shape), message=str( "The rank of input and label should be equal, " - "but received input: %d, label: %d." % (len(input.shape), len(label.shape)) + f"but received input: {len(input.shape)}, label: {len(label.shape)}." ), ) ivy.assertions.check_true( label.shape[-1] == 1, message=str( - "The last dimension of label should be 1, but received %d." - % label.shape[-1] + f"The last dimension of label should be 1, but received {label.shape[-1]}." ), ) ivy.assertions.check_true( @@ -164,7 +163,7 @@ def dice_loss(input, label, epsilon=0.00001, name=None): @with_supported_dtypes( - {"2.5.1 and below": ("float32",)}, + {"2.6.0 and below": ("float32",)}, "paddle", ) @to_ivy_arrays_and_back @@ -188,7 +187,7 @@ def hinge_embedding_loss(input, label, margin=1.0, reduction="mean"): return loss -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def kl_div( input, @@ -235,7 +234,7 @@ def l1_loss( @with_supported_dtypes( - {"2.5.1 and below": ("float32",)}, + {"2.6.0 and below": ("float32",)}, "paddle", ) @to_ivy_arrays_and_back @@ -246,7 +245,7 @@ def log_loss(input, label, epsilon=0.0001, name=None): return out -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def margin_ranking_loss(input, other, label, margin=0.0, reduction="mean", name=None): reduction = _get_reduction_func(reduction) @@ -266,7 +265,7 @@ def margin_ranking_loss(input, other, label, margin=0.0, reduction="mean", name= return out -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @inputs_to_ivy_arrays def mse_loss(input, label, reduction="mean", name=None): reduction = _get_reduction_func(reduction) @@ -276,7 +275,7 @@ def mse_loss(input, label, reduction="mean", name=None): return paddle.to_tensor(ret) -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def multi_label_soft_margin_loss( input, label, weight=None, reduction="mean", name=None @@ -294,7 +293,7 @@ def multi_label_soft_margin_loss( return ret -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def nll_loss( input, @@ -327,7 +326,7 @@ def nll_loss( return output -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def sigmoid_focal_loss( logit, @@ -373,7 +372,7 @@ def sigmoid_focal_loss( return loss -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def smooth_l1_loss( input, @@ -400,7 +399,7 @@ def smooth_l1_loss( @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64")}, + {"2.6.0 and below": ("float32", "float64")}, "paddle", ) @inputs_to_ivy_arrays @@ -460,13 +459,13 @@ def softmax_with_cross_entropy( return paddle.to_tensor(loss) -@with_supported_dtypes({"2.5.1 and below": ("float32",)}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32",)}, "paddle") @to_ivy_arrays_and_back def square_error_cost(input, label): return ivy.square(ivy.subtract(input, label)) -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def triplet_margin_loss( input, diff --git a/ivy/functional/frontends/paddle/nn/functional/norm.py b/ivy/functional/frontends/paddle/nn/functional/norm.py index 76bc210cabbb6..0090bb9ac5a9f 100644 --- a/ivy/functional/frontends/paddle/nn/functional/norm.py +++ b/ivy/functional/frontends/paddle/nn/functional/norm.py @@ -5,13 +5,13 @@ @to_ivy_arrays_and_back -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def layer_norm(x, normalized_shape, weight=None, bias=None, epsilon=1e-05, name=None): - return ivy.layer_norm(x, normalized_shape, weight, bias, epsilon) + return ivy.layer_norm(x, normalized_shape, scale=weight, offset=bias, eps=epsilon) @to_ivy_arrays_and_back -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def normalize(x, p=2, axis=1, epsilon=1e-12, name=None): if axis < 0: axis = ivy.get_num_dims(x) + axis diff --git a/ivy/functional/frontends/paddle/nn/functional/pooling.py b/ivy/functional/frontends/paddle/nn/functional/pooling.py index b40b468ed7441..219b73f8a47b7 100644 --- a/ivy/functional/frontends/paddle/nn/functional/pooling.py +++ b/ivy/functional/frontends/paddle/nn/functional/pooling.py @@ -2,22 +2,20 @@ import ivy from ivy.func_wrapper import with_supported_dtypes from ivy.functional.frontends.paddle.func_wrapper import to_ivy_arrays_and_back -from ivy.functional.frontends.torch.nn.functional.pooling_functions import ( - _broadcast_pooling_helper, -) +from ivy.functional.ivy.experimental.layers import _broadcast_pooling_helper from ivy.func_wrapper import with_unsupported_dtypes @to_ivy_arrays_and_back -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def adaptive_avg_pool1d(x, output_size, name=None): return ivy.adaptive_avg_pool1d(x, output_size) @to_ivy_arrays_and_back -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def adaptive_avg_pool2d(x, output_size, data_format="NCHW", name=None): - return ivy.adaptive_avg_pool2d(x, output_size) + return ivy.adaptive_avg_pool2d(x, output_size, data_format=data_format) @to_ivy_arrays_and_back @@ -27,13 +25,13 @@ def adaptive_avg_pool3d(x, output_size, data_format="NCHW", name=None): @to_ivy_arrays_and_back -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def adaptive_max_pool2d(x, output_size, return_mask=None, name=None): return ivy.adaptive_max_pool2d(x, output_size) @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") +@with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") def avg_pool1d( x, kernel_size, stride=None, padding=0, exclusive=True, ceil_mode=False, name=None ): @@ -45,7 +43,7 @@ def avg_pool1d( padding = _broadcast_pooling_helper(padding, "1d", name="padding") # Figure out padding string if all( - [pad == ivy.ceil((kernel - 1) / 2) for kernel, pad in zip(kernel_size, padding)] + pad == ivy.ceil((kernel - 1) / 2) for kernel, pad in zip(kernel_size, padding) ): padding = "SAME" else: @@ -63,7 +61,7 @@ def avg_pool1d( @to_ivy_arrays_and_back -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def avg_pool2d( x, kernel_size, @@ -81,7 +79,7 @@ def avg_pool2d( padding = _broadcast_pooling_helper(padding, "2d", name="padding") # Figure out padding string if all( - [pad == ivy.ceil((kernel - 1) / 2) for kernel, pad in zip(kernel_size, padding)] + pad == ivy.ceil((kernel - 1) / 2) for kernel, pad in zip(kernel_size, padding) ): padding = "SAME" else: @@ -101,7 +99,41 @@ def avg_pool2d( @to_ivy_arrays_and_back -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") +def max_pool2d( + x, + kernel_size, + stride=None, + padding=0, + return_mask=False, + ceil_mode=False, + data_format="NCHW", + name=None, +): + if stride is None: + stride = kernel_size + kernel_size = _broadcast_pooling_helper(kernel_size, "2d", name="kernel_size") + padding = _broadcast_pooling_helper(padding, "2d", name="padding") + + if data_format not in ["NCHW", "NHWC"]: + raise ValueError( + "Attr(data_format) should be 'NCHW' or 'NHWC'. Received " + f"Attr(data_format): {data_format}." + ) + + if data_format == "NHWC" and return_mask: + raise ValueError( + "When setting return_mask to true, data_format must be set to NCHW in" + " API:max_pool2d" + ) + + return ivy.max_pool2d( + x, kernel_size, stride, padding, data_format=data_format, ceil_mode=ceil_mode + ) + + +@to_ivy_arrays_and_back +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def max_unpool1d( x, indices, @@ -112,4 +144,11 @@ def max_unpool1d( output_size=None, name=None, ): - return ivy.max_unpool1d(x, indices, kernel_size, stride, padding, data_format) + return ivy.max_unpool1d( + x, + indices, + kernel_size, + strides=stride, + padding=padding, + data_format=data_format, + ) diff --git a/ivy/functional/frontends/paddle/nn/functional/vision.py b/ivy/functional/frontends/paddle/nn/functional/vision.py index 07e08ad17ce54..bc7b222e83ea8 100644 --- a/ivy/functional/frontends/paddle/nn/functional/vision.py +++ b/ivy/functional/frontends/paddle/nn/functional/vision.py @@ -9,7 +9,7 @@ @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") +@with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") def affine_grid(theta, out_shape, align_corners=True): if len(out_shape) == 4: N, C, H, W = out_shape @@ -75,7 +75,7 @@ def affine_grid(theta, out_shape, align_corners=True): @to_ivy_arrays_and_back -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def channel_shuffle(x, groups, data_format="NCHW", name=None): if len(ivy.shape(x)) != 4: raise ValueError( @@ -118,7 +118,7 @@ def pixel_shuffle(x, upscale_factor, data_format="NCHW"): ) if not isinstance(upscale_factor, int): - raise ValueError("upscale factor must be int type") + raise TypeError("upscale factor must be int type") if data_format not in ["NCHW", "NHWC"]: raise ValueError( @@ -172,7 +172,7 @@ def pixel_unshuffle(x, downscale_factor, data_format="NCHW"): ) if not isinstance(downscale_factor, int): - raise ValueError("Downscale factor must be int type") + raise TypeError("Downscale factor must be int type") if downscale_factor <= 0: raise ValueError("Downscale factor must be positive") diff --git a/ivy/functional/frontends/paddle/random.py b/ivy/functional/frontends/paddle/random.py index 9d45b9f23ea20..dafb52ffd7ece 100644 --- a/ivy/functional/frontends/paddle/random.py +++ b/ivy/functional/frontends/paddle/random.py @@ -8,7 +8,7 @@ @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64")}, + {"2.6.0 and below": ("float32", "float64")}, "paddle", ) @to_ivy_arrays_and_back @@ -18,7 +18,7 @@ def multinomial(x, num_samples=1, replacement=False, name=None): @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64")}, + {"2.6.0 and below": ("float32", "float64")}, "paddle", ) @to_ivy_arrays_and_back @@ -27,7 +27,7 @@ def normal(mean=0.0, std=1.0, shape=None, name=None): @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64")}, + {"2.6.0 and below": ("float32", "float64")}, "paddle", ) @to_ivy_arrays_and_back @@ -37,7 +37,7 @@ def poisson(x, name=None): @with_supported_device_and_dtypes( { - "2.5.1 and above": { + "2.6.0 and above": { "cpu": ( "bfloat16", "float32", @@ -75,7 +75,7 @@ def randint(low=0, high=None, shape=[1], dtype=None, name=None): @with_unsupported_dtypes( - {"2.5.1 and below": ("int16", "float16", "bfloat16", "uint8")}, + {"2.6.0 and below": ("int16", "float16", "bfloat16", "uint8")}, "paddle", ) @to_ivy_arrays_and_back @@ -99,7 +99,7 @@ def randn(shape, dtype=None, name=None): @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64")}, + {"2.6.0 and below": ("float32", "float64")}, "paddle", ) @to_ivy_arrays_and_back @@ -108,7 +108,7 @@ def standard_normal(shape, dtype=None, name=None): @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64")}, + {"2.6.0 and below": ("float32", "float64")}, "paddle", ) @to_ivy_arrays_and_back diff --git a/ivy/functional/frontends/paddle/search.py b/ivy/functional/frontends/paddle/search.py index 884be2e77fc99..29608b493561c 100644 --- a/ivy/functional/frontends/paddle/search.py +++ b/ivy/functional/frontends/paddle/search.py @@ -7,7 +7,7 @@ @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int16", "int32", "int64", "uint8")}, + {"2.6.0 and below": ("float32", "float64", "int16", "int32", "int64", "uint8")}, "paddle", ) @to_ivy_arrays_and_back @@ -16,7 +16,7 @@ def argmax(x, /, *, axis=None, keepdim=False, dtype="int64", name=None): @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int16", "int32", "int64", "uint8")}, + {"2.6.0 and below": ("float32", "float64", "int16", "int32", "int64", "uint8")}, "paddle", ) @to_ivy_arrays_and_back @@ -34,7 +34,7 @@ def argsort(x, /, *, axis=-1, descending=False, name=None): @with_supported_dtypes( - {"2.5.1 and below": ("int32", "int64", "float32", "float64")}, + {"2.6.0 and below": ("int32", "int64", "float32", "float64")}, "paddle", ) @to_ivy_arrays_and_back @@ -44,7 +44,7 @@ def index_sample(x, index): # kthvalue @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, "paddle" + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, "paddle" ) @to_ivy_arrays_and_back def kthvalue(x, k, axis=None, keepdim=False, name=None): @@ -65,7 +65,7 @@ def kthvalue(x, k, axis=None, keepdim=False, name=None): @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, "paddle", ) @to_ivy_arrays_and_back @@ -86,7 +86,7 @@ def nonzero(input, /, *, as_tuple=False): @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, "paddle", ) @to_ivy_arrays_and_back @@ -102,7 +102,7 @@ def searchsorted(sorted_sequence, values, out_int32=False, right=False, name=Non @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, "paddle", ) @to_ivy_arrays_and_back @@ -111,7 +111,7 @@ def sort(x, /, *, axis=-1, descending=False, name=None): @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, "paddle", ) @to_ivy_arrays_and_back @@ -121,7 +121,7 @@ def topk(x, k, axis=None, largest=True, sorted=True, name=None): # where @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, "paddle", ) @to_ivy_arrays_and_back diff --git a/ivy/functional/frontends/paddle/stat.py b/ivy/functional/frontends/paddle/stat.py index fc76cdad7b72c..695e60dc5bd4e 100644 --- a/ivy/functional/frontends/paddle/stat.py +++ b/ivy/functional/frontends/paddle/stat.py @@ -1,12 +1,12 @@ # global import ivy -from ivy.func_wrapper import with_unsupported_dtypes, with_supported_dtypes +from ivy.func_wrapper import with_supported_dtypes from ivy.functional.frontends.paddle.func_wrapper import ( to_ivy_arrays_and_back, ) -@with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def mean(input, axis=None, keepdim=False, out=None): ret = ivy.mean(input, axis=axis, keepdims=keepdim, out=out) @@ -14,7 +14,7 @@ def mean(input, axis=None, keepdim=False, out=None): @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, "paddle", ) @to_ivy_arrays_and_back @@ -37,7 +37,7 @@ def nanmedian(x, axis=None, keepdim=True, name=None): @with_supported_dtypes( - {"2.5.1 and below": ("bool", "float16", "float32", "float64", "int32", "int64")}, + {"2.6.0 and below": ("bool", "float16", "float32", "float64", "int32", "int64")}, "paddle", ) @to_ivy_arrays_and_back @@ -51,7 +51,7 @@ def numel(x, name=None): @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "uint16")}, + {"2.6.0 and below": ("float32", "float64", "uint16")}, "paddle", ) @to_ivy_arrays_and_back @@ -64,7 +64,7 @@ def std(x, axis=None, unbiased=True, keepdim=False, name=None): return ivy.std(x, axis=axis, correction=int(unbiased), keepdims=keepdim) -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def var(x, axis=None, unbiased=True, keepdim=False, name=None): if unbiased: diff --git a/ivy/functional/frontends/paddle/tensor/manipulation.py b/ivy/functional/frontends/paddle/tensor/manipulation.py index 35ce51915f140..c83bdaaf96101 100644 --- a/ivy/functional/frontends/paddle/tensor/manipulation.py +++ b/ivy/functional/frontends/paddle/tensor/manipulation.py @@ -6,17 +6,49 @@ ) from ivy.func_wrapper import with_unsupported_dtypes + +@with_supported_dtypes( + {"2.5.1 and below": ("bool", "int32", "int64", "float16", "float32", "float64")}, + "paddle", +) +@to_ivy_arrays_and_back +def index_add_(x, index, axis, value, *, name=None): + x = ivy.swapaxes(x, axis, 0) + value = ivy.swapaxes(value, axis, 0) + _to_adds = [] + index = sorted(zip(ivy.to_list(index), range(len(index))), key=(lambda i: i[0])) + while index: + _curr_idx = index[0][0] + while len(_to_adds) < _curr_idx: + _to_adds.append(ivy.zeros_like(value[0])) + _to_add_cum = ivy.get_item(value, index[0][1]) + while (len(index)) > 1 and (index[0][0] == index[1][0]): + _to_add_cum = _to_add_cum + ivy.get_item(value, index.pop(1)[1]) + index.pop(0) + _to_adds.append(_to_add_cum) + while len(_to_adds) < x.shape[0]: + _to_adds.append(ivy.zeros_like(value[0])) + _to_adds = ivy.stack(_to_adds) + if len(x.shape) < 2: + # Added this line due to the paddle backend treating scalars as 1-d arrays + _to_adds = ivy.flatten(_to_adds) + + ret = ivy.add(x, _to_adds) + ret = ivy.swapaxes(ret, axis, 0) + x = ret + return x + + # NOTE: # Only inplace functions are to be added in this file. # Please add non-inplace counterparts to `/frontends/paddle/manipulation.py`. @with_unsupported_dtypes( - {"2.5.1 and below": ("int8", "uint8", "int16", "uint16", "float16", "bfloat16")}, + {"2.6.0 and below": ("int8", "uint8", "int16", "uint16", "float16", "bfloat16")}, "paddle", ) @to_ivy_arrays_and_back def reshape_(x, shape): - ret = ivy.reshape(x, shape) - ivy.inplace_update(x, ret) + ivy.reshape(x, shape) return x diff --git a/ivy/functional/frontends/paddle/tensor/math.py b/ivy/functional/frontends/paddle/tensor/math.py index 7f9d56ea6452a..6332b1636a37d 100644 --- a/ivy/functional/frontends/paddle/tensor/math.py +++ b/ivy/functional/frontends/paddle/tensor/math.py @@ -9,14 +9,14 @@ # Please add non-inplace counterparts to `/frontends/paddle/math.py`. -@with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") +@with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") @to_ivy_arrays_and_back def ceil_(x, name=None): return ivy.ceil(x, out=x) @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, "paddle" + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, "paddle" ) @to_ivy_arrays_and_back def clip_(x, min=None, max=None, name=None): @@ -38,54 +38,54 @@ def clip_(x, min=None, max=None, name=None): return res -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def exp_(x, name=None): return ivy.inplace_update(x, exp(x)) -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def floor_(x, name=None): return ivy.inplace_update(x, floor(x)) -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def lerp_(x, y, weight, name=None): return ivy.inplace_update(x, lerp(x, y, weight)) -@with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") +@with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") @to_ivy_arrays_and_back def reciprocal_(x, name=None): return ivy.inplace_update(x, reciprocal(x)) -@with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") +@with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") @to_ivy_arrays_and_back def round_(x, name=None): return ivy.inplace_update(x, round(x)) -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def rsqrt_(x, name=None): return ivy.inplace_update(x, reciprocal(sqrt(x))) -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def sqrt_(x, name=None): return ivy.inplace_update(x, sqrt(x)) -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def subtract_(x, y, name=None): return ivy.inplace_update(x, subtract(x, y)) -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def tanh_(x, name=None): return ivy.inplace_update(x, tanh(x)) diff --git a/ivy/functional/frontends/paddle/tensor/random.py b/ivy/functional/frontends/paddle/tensor/random.py index ea6bd38157195..31e370942c6ad 100644 --- a/ivy/functional/frontends/paddle/tensor/random.py +++ b/ivy/functional/frontends/paddle/tensor/random.py @@ -12,7 +12,7 @@ @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64")}, + {"2.6.0 and below": ("float32", "float64")}, "paddle", ) @to_ivy_arrays_and_back @@ -21,7 +21,7 @@ def exponential_(x, lam=1.0, name=None): @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64")}, + {"2.6.0 and below": ("float32", "float64")}, "paddle", ) @to_ivy_arrays_and_back diff --git a/ivy/functional/frontends/paddle/tensor/tensor.py b/ivy/functional/frontends/paddle/tensor/tensor.py index 2948db60f8e40..215f5a98bf183 100644 --- a/ivy/functional/frontends/paddle/tensor/tensor.py +++ b/ivy/functional/frontends/paddle/tensor/tensor.py @@ -62,12 +62,120 @@ def ivy_array(self, array): # -------------------# @with_unsupported_dtypes( - {"2.5.1 and below": ("bool", "unsigned", "int8", "float16", "bfloat16")}, + {"2.6.0 and below": ("bool", "unsigned", "int8", "float16", "bfloat16")}, "paddle", ) def __add__(self, y, /, name=None): return paddle_frontend.add(self, y) + @with_unsupported_dtypes( + {"2.6.0 and below": ("bool", "unsigned", "int8", "float16", "bfloat16")}, + "paddle", + ) + def __radd__(self, x, /, name=None): + return paddle_frontend.add(self, x) + + @with_unsupported_dtypes( + {"2.6.0 and below": ("bool", "unsigned", "int8", "float16", "bfloat16")}, + "paddle", + ) + def __sub__(self, y, /, name=None): + return paddle_frontend.subtract(self, y) + + @with_unsupported_dtypes( + {"2.6.0 and below": ("uint8", "int8", "int16", "float16", "bfloat16")}, + "paddle", + ) + def __mul__(self, y, /, name=None): + return paddle_frontend.multiply(self, y) + + @with_unsupported_dtypes( + { + "2.6.0 and below": ( + "bool", + "uint8", + "int8", + "int16", + "complex64", + "complex128", + ) + }, + "paddle", + ) + def __gt__(self, y, /, name=None): + return paddle_frontend.logic.greater_than(self, y) + + @with_unsupported_dtypes( + { + "2.6.0 and below": ( + "bool", + "uint8", + "int8", + "int16", + "complex64", + "complex128", + ) + }, + "paddle", + ) + def __lt__(self, y, /, name=None): + return paddle_frontend.logic.less_than(self, y) + + @with_unsupported_dtypes( + { + "2.6.0 and below": ( + "bool", + "uint8", + "int8", + "int16", + "complex64", + "complex128", + ) + }, + "paddle", + ) + def __ge__(self, y, /, name=None): + return paddle_frontend.logic.greater_equal(self, y) + + @with_unsupported_dtypes( + { + "2.6.0 and below": ( + "bool", + "uint8", + "int8", + "int16", + "complex64", + "complex128", + ) + }, + "paddle", + ) + def __le__(self, y, /, name=None): + return paddle_frontend.logic.less_equal(self, y) + + @with_supported_dtypes( + { + "2.6.0 and below": ( + "bool", + "uint8", + "int8", + "int16", + "int32", + "int64", + ) + }, + "paddle", + ) + def __or__(self, y, /, name=None): + return paddle_frontend.logic.bitwise_or(self, y) + + @with_unsupported_dtypes( + {"2.6.0 and below": ("bool", "unsigned", "int8", "float16", "bfloat16")}, + "paddle", + ) + def __rsub__(self, x, /, name=None): + return paddle_frontend.subtract(x, self) + def __getitem__(self, item): ivy_args = ivy.nested_map(_to_ivy_array, [self, item]) ret = ivy.get_item(*ivy_args) @@ -78,12 +186,88 @@ def __setitem__(self, item, value): "ivy.functional.frontends.paddle.Tensor object doesn't support assignment" ) + @with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") + def __floordiv__(self, y, /, name=None): + return paddle_frontend.floor_divide(self, y) + + @with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") + def __ne__(self, y, /, name=None): + return paddle_frontend.not_equal(self, y) + def __iter__(self): if self.ndim == 0: raise TypeError("iteration over a 0-d tensor not supported") for i in range(self.shape[0]): yield self[i] + @with_unsupported_dtypes( + {"2.6.0 and below": ("bool", "unsigned", "int8", "float16", "bfloat16")}, + "paddle", + ) + def __rmul__(self, y, /, name=None): + return paddle_frontend.multiply(self, y) + + @with_unsupported_dtypes( + {"2.6.0 and below": ("bool", "unsigned", "int8", "float16", "bfloat16")}, + "paddle", + ) + def __float__(self): + return float(self._ivy_array) + + def __xor__(self, y, /, name=None): + return paddle_frontend.logic.bitwise_xor(self, y) + + def __invert__(self, out=None, name=None): + return paddle_frontend.logic.bitwise_not(self) + + def __len__(self): + return len(self._ivy_array) + + def __neg__(self): + return paddle_frontend.neg(self) + + @with_unsupported_dtypes( + {"2.6.0 and below": ("bool", "unsigned", "int8", "float16", "bfloat16")}, + "paddle", + ) + def __rdiv__(self, y, /, name=None): + return paddle_frontend.divide(y, self) + + @with_unsupported_dtypes( + {"2.6.0 and below": ("bool", "unsigned", "int8", "float16", "bfloat16")}, + "paddle", + ) + def __rtruediv__(self, y, /, name=None): + return paddle_frontend.divide(y, self) + + @with_unsupported_dtypes( + {"2.6.0 and below": ("bool", "unsigned", "int8", "float16", "bfloat16")}, + "paddle", + ) + def __int__(self): + return int(self._ivy_array) + + @with_unsupported_dtypes( + { + "2.6.0 and below": ( + "bool", + "unsigned", + "int8", + "int32", + "int64", + "float16", + "bfloat16", + ) + }, + "paddle", + ) + def __long__(self): + return int(self._ivy_array) + + @with_supported_dtypes({"2.6.0 and below": ("int32", "int64")}, "paddle") + def __mod__(self, y, /, name=None): + return paddle_frontend.Tensor(ivy.fmod(self._ivy_array, _to_ivy_array(y))) + # Instance Methods # # ---------------- # @@ -98,52 +282,76 @@ def reshape(self, *args, shape=None): return paddle_frontend.reshape(self, shape) else: return paddle_frontend.reshape(self, args) - return paddle_frontend.reshape(self) + else: + raise ValueError("reshape() got no values for argument 'shape'") + + def reshape_(self, *args, shape=None): + if args and shape: + raise TypeError("reshape() got multiple values for argument 'shape'") + if shape is not None: + self.ivy_array = paddle_frontend.reshape( + self._ivy_array, shape=shape + ).ivy_array + return self + if args: + if isinstance(args[0], (tuple, list)): + shape = args[0] + self.ivy_array = paddle_frontend.reshape( + self._ivy_array, shape=shape + ).ivy_array + return self + else: + self.ivy_array = paddle_frontend.reshape( + self._ivy_array, args + ).ivy_array + return self + else: + raise ValueError("reshape_() got no values for argument 'shape'") def dim(self): return self.ivy_array.ndim - @with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") + @with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") def abs(self): return paddle_frontend.abs(self) - @with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") + @with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") def acosh(self, name=None): return paddle_frontend.acosh(self) - @with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") + @with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") def add_n(self, inputs, name=None): inputs = ivy.array(inputs) return ivy.sum(inputs, dtype=inputs.dtype, axis=0) - @with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") + @with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") def ceil(self): return paddle_frontend.ceil(self) - @with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") + @with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def ceil_(self): self.ivy_array = self.ceil().ivy_array return self - @with_unsupported_dtypes({"2.5.1 and below": ("complex", "int8")}, "paddle") + @with_unsupported_dtypes({"2.6.0 and below": ("complex", "int8")}, "paddle") def numel(self): return paddle_frontend.numel(self) - @with_unsupported_dtypes({"2.5.1 and below": ("float16",)}, "paddle") + @with_unsupported_dtypes({"2.6.0 and below": ("float16",)}, "paddle") def asinh(self, name=None): return paddle_frontend.asinh(self) - @with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") + @with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def asin(self, name=None): return paddle_frontend.asin(self) - @with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") + @with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def cosh(self, name=None): return paddle_frontend.cosh(self) @with_supported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "int32", "int64", "float64", @@ -158,101 +366,101 @@ def cosh(self, name=None): def diagonal(self, offset, axis1=0, axis2=1, name=None): return paddle_frontend.diagonal(self, offset=offset, axis1=axis1, axis2=axis2) - @with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") + @with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def log(self, name=None): return paddle_frontend.log(self) - @with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") + @with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def sin(self, name=None): return paddle_frontend.sin(self) - @with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") + @with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def sinh(self, name=None): return paddle_frontend.sinh(self) - @with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") + @with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def lerp(self, y, weight, name=None): return paddle_frontend.lerp(self, y, weight) - @with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") + @with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def lerp_(self, y, weight, name=None): self.ivy_array = paddle_frontend.lerp(self, y, weight).ivy_array return self - @with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") + @with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") def argmax(self, axis=None, keepdim=False, dtype=None, name=None): return paddle_frontend.argmax(self, axis=axis, keepdim=keepdim, dtype=dtype) - @with_unsupported_dtypes({"2.5.1 and below": ("float16", "uint16")}, "paddle") + @with_unsupported_dtypes({"2.6.0 and below": ("float16", "uint16")}, "paddle") def unsqueeze(self, axis=None, name=None): return paddle_frontend.Tensor(ivy.expand_dims(self._ivy_array, axis=axis)) - @with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") + @with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def sqrt(self, name=None): return paddle_frontend.sqrt(self) - @with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") + @with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def sqrt_(self, name=None): self.ivy_array = self.sqrt().ivy_array return self - @with_unsupported_dtypes({"2.5.1 and below": ("bfloat16", "uint16")}, "paddle") + @with_unsupported_dtypes({"2.6.0 and below": ("bfloat16", "uint16")}, "paddle") def zero_(self): self.ivy_array = paddle_frontend.zeros_like(self).ivy_array return self - @with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") + @with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def cos(self, name=None): return paddle_frontend.cos(self) - @with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") + @with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") def exp(self, name=None): return paddle_frontend.exp(self) - @with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") + @with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") def exp_(self, name=None): self.ivy_array = self.exp().ivy_array return self - @with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") + @with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def erf(self, name=None): return paddle_frontend.erf(self) - @with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") + @with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") def subtract(self, y, name=None): return paddle_frontend.subtract(self, y) @with_unsupported_dtypes( - {"2.5.1 and below": ("float16", "uint8", "int8", "bool")}, "paddle" + {"2.6.0 and below": ("float16", "uint8", "int8", "bool")}, "paddle" ) def subtract_(self, y, name=None): self.ivy_array = self.subtract(y).ivy_array return self - @with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") + @with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") def log10(self, name=None): return paddle_frontend.Tensor(ivy.log10(self._ivy_array)) - @with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") + @with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") def argsort(self, axis=-1, descending=False, name=None): return paddle_frontend.argsort(self, axis=axis, descending=descending) - @with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") + @with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") def floor(self, name=None): return paddle_frontend.floor(self) - @with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") + @with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") def floor_(self): self.ivy_array = self.floor().ivy_array return self - @with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") + @with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def round_(self, name=None): self.ivy_array = paddle_frontend.round(self).ivy_array return self @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, "paddle" + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, "paddle" ) def clip(self, min=None, max=None, name=None): ivy.utils.assertions.check_all_or_any_fn( @@ -272,85 +480,106 @@ def clip(self, min=None, max=None, name=None): return paddle_frontend.Tensor(ret) @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, "paddle" + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, "paddle" ) def clip_(self, min=None, max=None, name=None): self._ivy_array = self.clip(min, max).ivy_array return self - @with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") + @with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def tanh(self, name=None): return paddle_frontend.tanh(self) - @with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") + @with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") + def add(self, y, name=None): + return paddle_frontend.Tensor(ivy.add(self._ivy_array, _to_ivy_array(y))) + + @with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def add_(self, y, name=None): self.ivy_array = paddle_frontend.add(self, y).ivy_array return self - @with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") + @with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def addmm(self, x, y, beta=1.0, alpha=1.0, name=None): return paddle_frontend.addmm(self, x, y, beta, alpha) @with_supported_dtypes( - {"2.5.1 and below": ("float16", "float32", "float64", "int32", "int64")}, + {"2.6.0 and below": ("float16", "float32", "float64", "int32", "int64")}, "paddle", ) def isinf(self, name=None): return paddle_frontend.isinf(self) - @with_unsupported_dtypes({"2.5.1 and below": ("float16", "uint16")}, "paddle") + @with_unsupported_dtypes({"2.6.0 and below": ("float16", "uint16")}, "paddle") def unsqueeze_(self, axis=None, name=None): self.ivy_array = self.unsqueeze(axis=axis).ivy_array return self - @with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") + @with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def square(self, name=None): return paddle_frontend.square(self) - @with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") + @with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") def remainder_(self, y, name=None): self.ivy_array = paddle_frontend.remainder(self, y).ivy_array return self - @with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") + @with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def cholesky(self, upper=False, name=None): return paddle_frontend.cholesky(self, upper=upper) @with_unsupported_dtypes( - {"2.5.1 and below": ("float16", "uint16", "int16")}, "paddle" + {"2.6.0 and below": ("float16", "uint16", "int16")}, "paddle" + ) + def squeeze(self, axis=None, name=None): + if isinstance(axis, int) and self.ndim > 0: + if self.shape[axis] > 1: + return self + if len(self.shape) == 0: + return self + return paddle_frontend.squeeze(self, axis=axis) + + @with_unsupported_dtypes( + {"2.6.0 and below": ("float16", "uint16", "int16")}, "paddle" ) def squeeze_(self, axis=None, name=None): self.ivy_array = paddle_frontend.squeeze(self, axis=axis).ivy_array return self - @with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") + @with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") def multiply(self, y, name=None): return paddle_frontend.multiply(self, y) + @with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") + def matmul(self, y, transpose_x=False, transpose_y=False, name=None): + return paddle_frontend.matmul( + self, y, transpose_x=transpose_x, transpose_y=transpose_y + ) + @with_supported_dtypes( - {"2.5.1 and below": ("float16", "float32", "float64", "int32", "int64")}, + {"2.6.0 and below": ("float16", "float32", "float64", "int32", "int64")}, "paddle", ) def isfinite(self, name=None): return paddle_frontend.isfinite(self) @with_supported_dtypes({"2.4.2 and below": ("float16", "bfloat16")}, "paddle") - def all(self, axis=None, keepdim=False, dtype=None, name=None): + def all(self, axis=None, keepdim=False, name=None): return paddle_frontend.Tensor( - ivy.all(self.ivy_array, axis=axis, keepdims=keepdim, dtype=dtype) + ivy.all(self.ivy_array, axis=axis, keepdims=keepdim) ) - @with_supported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") + @with_supported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") def allclose(self, other, rtol=1e-05, atol=1e-08, equal_nan=False, name=None): return paddle_frontend.allclose( self, other, rtol=rtol, atol=atol, equal_nan=equal_nan ) - @with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") + @with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") def sort(self, axis=-1, descending=False, name=None): return paddle_frontend.sort(self, axis=axis, descending=descending) - @with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") + @with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") def log1p(self, name=None): return paddle_frontend.log1p(self) @@ -372,7 +601,7 @@ def bitwise_and(self, y, out=None, name=None): @with_supported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "bool", "int8", "int16", @@ -388,22 +617,22 @@ def logical_or(self, y, out=None, name=None): return paddle_frontend.logical_or(self, y, out=out) @with_supported_dtypes( - {"2.5.1 and below": ("bool", "uint8", "int8", "int16", "int32", "int64")}, + {"2.6.0 and below": ("bool", "uint8", "int8", "int16", "int32", "int64")}, "paddle", ) def bitwise_xor(self, y, out=None, name=None): return paddle_frontend.bitwise_xor(self, y) - @with_supported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") + @with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") def any(self, axis=None, keepdim=False, name=None): return paddle_frontend.any(self, axis=axis, keepdim=keepdim) - @with_unsupported_dtypes({"2.5.1 and below": "bfloat16"}, "paddle") + @with_unsupported_dtypes({"2.6.0 and below": "bfloat16"}, "paddle") def astype(self, dtype): return paddle_frontend.Tensor(ivy.astype(self._ivy_array, dtype)) @with_supported_dtypes( - {"2.5.1 and below": ("bool", "uint8", "int8", "int16", "int32", "int64")}, + {"2.6.0 and below": ("bool", "uint8", "int8", "int16", "int32", "int64")}, "paddle", ) def bitwise_not(self, out=None, name=None): @@ -411,7 +640,7 @@ def bitwise_not(self, out=None, name=None): @with_supported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "bool", "int8", "int16", @@ -426,7 +655,7 @@ def bitwise_or(self, y, out=None, name=None): @with_supported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "bool", "int8", "int16", @@ -442,7 +671,7 @@ def logical_xor(self, y, out=None, name=None): return paddle_frontend.logical_xor(self, y, out=out) @with_supported_dtypes( - {"2.5.1 and below": ("float16", "float32", "float64", "int32", "int64")}, + {"2.6.0 and below": ("float16", "float32", "float64", "int32", "int64")}, "paddle", ) def isnan(self, name=None): @@ -450,7 +679,7 @@ def isnan(self, name=None): @with_unsupported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "bool", "uint8", "int8", @@ -464,22 +693,22 @@ def isnan(self, name=None): def greater_than(self, y, name=None): return paddle_frontend.greater_than(self, y) - @with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") + @with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def rsqrt(self, name=None): return paddle_frontend.rsqrt(self) - @with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") + @with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def rsqrt_(self, name=None): self.ivy_array = self.rsqrt().ivy_array return self - @with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") + @with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def reciprocal(self, name=None): return paddle_frontend.reciprocal(self) @with_supported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "bool", "int8", "int16", @@ -494,19 +723,20 @@ def reciprocal(self, name=None): def logical_and(self, y, out=None, name=None): return paddle_frontend.logical_and(self, y, out=out) - @with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") + @with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def divide(self, y, name=None): return paddle_frontend.divide(self, y) @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "complex64", "complex128")}, "paddle" + {"2.6.0 and below": ("float32", "float64", "complex64", "complex128")}, + "paddle", ) def eigvals(self, name=None): return paddle_frontend.eigvals(self) @with_unsupported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "bool", "uint8", "int8", @@ -520,18 +750,18 @@ def eigvals(self, name=None): def less_than(self, y, name=None): return paddle_frontend.less_than(self, y) - @with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") + @with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") def cumprod(self, dim=None, dtype=None, name=None): return paddle_frontend.cumprod(self, dim=dim, dtype=dtype) - @with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") + @with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") def cumsum(self, axis=None, dtype=None, name=None): return paddle_frontend.Tensor( ivy.cumsum(self._ivy_array, axis=axis, dtype=dtype) ) @with_supported_dtypes( - {"2.5.1 and below": ("complex64", "complex128", "float32", "float64")}, + {"2.6.0 and below": ("complex64", "complex128", "float32", "float64")}, "paddle", ) def angle(self, name=None): @@ -539,7 +769,7 @@ def angle(self, name=None): @with_unsupported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "uint8", "int8", "int16", @@ -552,13 +782,13 @@ def angle(self, name=None): def equal(self, y, name=None): return paddle_frontend.equal(self, y) - @with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") + @with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") def rad2deg(self, name=None): return paddle_frontend.rad2deg(self) @with_unsupported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "uint8", "int8", "int16", @@ -572,46 +802,46 @@ def rad2deg(self, name=None): def equal_all(self, y, name=None): return paddle_frontend.equal_all(self, y) - @with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") + @with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def maximum(self, other, name=None): return paddle_frontend.maximum(self, other) - @with_unsupported_dtypes({"2.5.1 and below": "bfloat16"}, "paddle") + @with_unsupported_dtypes({"2.6.0 and below": "bfloat16"}, "paddle") def fmax(self, y, name=None): return paddle_frontend.fmax(self, y) - @with_unsupported_dtypes({"2.5.1 and below": "bfloat16"}, "paddle") + @with_unsupported_dtypes({"2.6.0 and below": "bfloat16"}, "paddle") def fmin(self, y, name=None): return paddle_frontend.fmin(self, y) @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, "paddle" + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, "paddle" ) def minimum(self, y, name=None): return paddle_frontend.minimum(self, y) @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, "paddle" + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, "paddle" ) def max(self, axis=None, keepdim=False, name=None): return paddle_frontend.max(self, axis=axis, keepdim=keepdim) - @with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") + @with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") def deg2rad(self, name=None): return paddle_frontend.deg2rad(self) - @with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") + @with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def digamma(self, name=None): return paddle_frontend.digamma(self) @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64", "bool")}, "paddle" + {"2.6.0 and below": ("float32", "float64", "int32", "int64", "bool")}, "paddle" ) def rot90(self, k=1, axes=(0, 1), name=None): return paddle_frontend.rot90(self, k=k, axes=axes) @with_supported_dtypes( - {"2.5.1 and below": ("complex64", "complex128")}, + {"2.6.0 and below": ("complex64", "complex128")}, "paddle", ) def imag(self, name=None): @@ -622,7 +852,7 @@ def is_tensor(self): @with_supported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "float32", "float64", ) @@ -634,16 +864,22 @@ def isclose(self, y, rtol=1e-05, atol=1e-08, equal_nan=False, name=None): self, y, rtol=rtol, atol=atol, equal_nan=equal_nan ) - @with_supported_dtypes({"2.5.1 and below": ("int32", "int64")}, "paddle") + @with_supported_dtypes({"2.6.0 and below": ("int32", "int64")}, "paddle") def floor_divide(self, y, name=None): return paddle_frontend.floor_divide(self, y) - @with_supported_dtypes({"2.5.1 and below": ("int32", "int64")}, "paddle") + @with_supported_dtypes({"2.6.0 and below": ("int32", "int64")}, "paddle") def mod(self, y, name=None): return paddle_frontend.Tensor(ivy.fmod(self._ivy_array, _to_ivy_array(y))) + @with_supported_dtypes( + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, "paddle" + ) + def floor_mod(self, y, name=None): + return paddle_frontend.remainder(self, y) + # cond - @with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") + @with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def cond(self, p=None, name=None): return paddle_frontend.cond(self, p=p, name=name) @@ -651,7 +887,7 @@ def cond(self, p=None, name=None): def conj(self, name=None): return paddle_frontend.conj(self) - @with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") + @with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def log2(self, name=None): return paddle_frontend.log2(self) @@ -663,7 +899,7 @@ def neg(self, name=None): @with_supported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "bool", "int8", "int16", @@ -678,15 +914,15 @@ def neg(self, name=None): def logical_not(self, out=None, name=None): return paddle_frontend.logical_not(self) - @with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") + @with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") def sign(self, name=None): return paddle_frontend.sign(self) - @with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") + @with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def var(self, axis=None, unbiased=True, keepdim=False, name=None): return paddle_frontend.var(self, axis=axis, unbiased=unbiased, keepdim=keepdim) - @with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") + @with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") def sgn(self, name=None): return paddle_frontend.sgn(self) @@ -694,45 +930,45 @@ def tolist(self): return paddle_frontend.Tensor(ivy.to_list(self._ivy_array)) @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, "paddle", ) def min(self, axis=None, keepdim=False, name=None): return paddle_frontend.min(self, axis=axis, keepdim=keepdim) @with_supported_dtypes( - {"2.5.1 and below": ("int32", "int64", "float32", "float64")}, "paddle" + {"2.6.0 and below": ("int32", "int64", "float32", "float64")}, "paddle" ) def pow(self, y, name=None): return paddle_frontend.pow(self, y) @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, "paddle" + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, "paddle" ) def prod(self, axis=None, keepdim=False, dtype=None, name=None): return paddle_frontend.Tensor( ivy.prod(self._ivy_array, axis=axis, keepdims=keepdim, dtype=dtype) ) - @with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") + @with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def atan(self, name=None): return paddle_frontend.atan(self) - @with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") + @with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def atanh(self, name=None): return paddle_frontend.atanh(self) - @with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") + @with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def std(self, axis=None, unbiased=True, keepdim=False, name=None): return paddle_frontend.std(self, axis=axis, unbiased=unbiased, keepdim=keepdim) @with_supported_dtypes( - {"2.5.1 and below": ("int32", "int64", "float32", "float64")}, "paddle" + {"2.6.0 and below": ("int32", "int64", "float32", "float64")}, "paddle" ) def trunc(self, name=None): return paddle_frontend.trunc(self) - @with_supported_dtypes({"2.5.1 and below": ("complex64", "complex128")}, "paddle") + @with_supported_dtypes({"2.6.0 and below": ("complex64", "complex128")}, "paddle") def as_real(self, name=None): if not ivy.is_complex_dtype(self._ivy_array): raise ivy.exceptions.IvyError( @@ -742,68 +978,115 @@ def as_real(self, name=None): im_part = ivy.imag(self._ivy_array) return paddle_frontend.Tensor(ivy.stack((re_part, im_part), axis=-1)) - @with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") + @with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def stanh(self, scale_a=0.67, scale_b=1.7159, name=None): return paddle_frontend.stanh(self, scale_a=scale_a, scale_b=scale_b) @with_supported_dtypes( - {"2.5.1 and below": ("int32", "int64", "float32", "float64")}, "paddle" + {"2.6.0 and below": ("int32", "int64", "float32", "float64")}, "paddle" ) def trace(self, offset=0, axis1=0, axis2=1, name=None): return paddle_frontend.Tensor( ivy.trace(self._ivy_array, offset=offset, axis1=axis1, axis2=axis2) ) + @with_supported_dtypes({"2.6.0 and below": ("float64", "float32")}, "paddle") + def cov(self, rowvar=True, ddof=True, fweights=None, aweights=None): + return paddle_frontend.Tensor( + ivy.cov( + self._ivy_array, + rowVar=rowvar, + ddof=int(ddof), + fweights=fweights, + aweights=aweights, + ) + ) + + @with_supported_dtypes( + { + "2.6.0 and below": ( + "bfloat16", + "float32", + "float64", + "int8", + "int16", + "int32", + "int64", + "uint8", + ) + }, + "paddle", + ) + def flatten(self, start_axis=0, stop_axis=-1, name=None): + if len(self.shape) == 0: + return self.unsqueeze(axis=0) + return paddle_frontend.Tensor( + ivy.flatten(self.ivy_array, start_dim=start_axis, end_dim=stop_axis) + ) + @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int16", "int32", "int64", "uint8")}, + { + "2.6.0 and below": ( + "float32", + "float64", + "int16", + "int32", + "int64", + "uint8", + ) + }, "paddle", ) def argmin(self, axis=None, keepdim=False, dtype=None, name=None): return paddle_frontend.argmin(self, axis=axis, keepdim=keepdim, dtype=dtype) @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, "paddle", ) def topk(self, k, axis=None, largest=True, sorted=True, name=None): return paddle_frontend.topk(self, k, axis=axis, largest=largest, sorted=sorted) - @with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") + @with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") def remainder(self, y, name=None): return paddle_frontend.remainder(self, y) def is_floating_point(self): return paddle_frontend.is_floating_point(self) - @with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") + @with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def tanh_(self, name=None): y = self.tanh(self) return ivy.inplace_update(self, y) - @with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") + @with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def reciprocal_(self, name=None): y = self.reciprocal(self) return ivy.inplace_update(self, y) @with_unsupported_dtypes( - {"2.5.1 and below": ("complex", "uint8", "uint16")}, "paddle" + {"2.6.0 and below": ("complex", "uint8", "uint16")}, "paddle" ) def numpy(self): return self.ivy_array.to_numpy() - @with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") + @with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") def nonzero(self): return paddle_frontend.nonzero(self) - @with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") + @with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def inner(self, y, name=None): return paddle_frontend.inner(self, y, name) - @with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") + @with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") + def acos(self, name=None): + return paddle_frontend.Tensor(ivy.acos(self._ivy_array)) + + @with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def mean(self, axis=None, keepdim=False, name=None): return paddle_frontend.mean(self, axis=axis, keepdim=keepdim) - @with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") + @with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def as_complex(self, name=None): if self.ivy_array.shape[-1] != 2: raise ivy.exceptions.IvyError( @@ -818,29 +1101,29 @@ def as_complex(self, name=None): return value @with_supported_dtypes( - {"2.5.1 and below": ("int32", "int64", "float32", "float64", "bool")}, "paddle" + {"2.6.0 and below": ("int32", "int64", "float32", "float64", "bool")}, "paddle" ) def not_equal(self, y, name=None): return paddle_frontend.not_equal(self._ivy_array, y) @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, "paddle" + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, "paddle" ) def less_equal(self, y, name=None): return paddle_frontend.less_equal(self._ivy_array, y) - @with_supported_dtypes({"2.5.1 and below": ("complex64", "complex128")}, "paddle") + @with_supported_dtypes({"2.6.0 and below": ("complex64", "complex128")}, "paddle") def real(self, name=None): return paddle_frontend.real(self._ivy_array) - @with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") + @with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") def t(self, name=None): axes = list(range(len(self.ivy_array.shape)))[::-1] return ivy.permute_dims(self.ivy_array, axes=axes) @with_supported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "bool", "float16", "float32", @@ -855,12 +1138,12 @@ def t(self, name=None): def cast(self, dtype): return paddle_frontend.cast(self, dtype) - @with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") + @with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") def bmm(self, y, transpose_x=False, transpose_y=False, name=None): return paddle_frontend.bmm(self, y, transpose_x, transpose_y) @with_supported_dtypes( - {"2.5.1 and below": ("float16", "float32", "float64", "int32", "int64")}, + {"2.6.0 and below": ("float16", "float32", "float64", "int32", "int64")}, "paddle", ) def fill_(self, value): @@ -869,7 +1152,7 @@ def fill_(self, value): @with_supported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "bool", "int32", "int64", @@ -885,7 +1168,7 @@ def unbind(self, axis=0): @with_supported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "bool", "int32", "int64", @@ -904,32 +1187,47 @@ def cpu(self): return self @with_unsupported_dtypes( - {"2.5.1 and below": ("int16", "complex64", "complex128")}, + {"2.6.0 and below": ("int16", "complex64", "complex128")}, "paddle", ) def split(self, num_or_sections, axis=0, name=None): return paddle_frontend.split(self._ivy_array, num_or_sections, axis, name) @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, "paddle" + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, "paddle" ) def frac(self, name=None): return paddle_frontend.frac(self._ivy_array) - @with_unsupported_dtypes({"2.5.1 and below": ("float16", "bfloat16")}, "paddle") + @with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") def gather(self, y, name=None): return paddle_frontend.gather(self, y) + def is_complex(self): + return paddle_frontend.is_complex(self) + @with_unsupported_dtypes( - {"2.5.1 and below": ("float16", "uint8", "int8", "bool")}, "paddle" + {"2.6.0 and below": ("float16", "uint8", "int8", "bool")}, "paddle" ) def gather_(self, y, name=None): res = self.gather(self, y) return ivy.inplace_update(self, res) + @with_supported_dtypes( + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, "paddle" + ) + def heaviside(self, y, name=None): + return paddle_frontend.heaviside(self, y) + + @with_supported_dtypes( + {"2.6.0 and below": ("bool", "int32", "int64", "float32", "float64")}, "paddle" + ) + def expand(self, shape, name=None): + return paddle_frontend.expand(self._ivy_array, shape) + @with_supported_device_and_dtypes( { - "2.5.1 and below": { + "2.6.0 and below": { "cpu": ( "bool", "int32", @@ -946,6 +1244,26 @@ def gather_(self, y, name=None): def tile(self, repeat_times): return paddle_frontend.Tensor(ivy.tile(self._ivy_array, repeats=repeat_times)) + @with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") def cholesky_solve(self, y, upper=False, name=None): return paddle_frontend.cholesky_solve(self._ivy_array, y, upper=upper) + + @with_supported_dtypes( + { + "2.6.0 and below": ( + "bool", + "float16", + "float32", + "float64", + "int8", + "int16", + "int32", + "int64", + ) + }, + "paddle", + ) + def chunk(self, chunks, axis=0, name=None): + return paddle_frontend.split(self._ivy_array, num_or_sections=chunks, axis=axis) + diff --git a/ivy/functional/frontends/paddle/vision/transforms.py b/ivy/functional/frontends/paddle/vision/transforms.py index 43bd51fc3830a..c2ff2af63c3ce 100644 --- a/ivy/functional/frontends/paddle/vision/transforms.py +++ b/ivy/functional/frontends/paddle/vision/transforms.py @@ -104,7 +104,7 @@ def _rgb_to_hsv(img): # ------------ # -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") @to_ivy_arrays_and_back def adjust_brightness(img, brightness_factor): assert brightness_factor >= 0, "brightness_factor should be non-negative." @@ -117,7 +117,7 @@ def adjust_brightness(img, brightness_factor): return _blend_images(img, extreme_target, brightness_factor) -@with_supported_dtypes({"2.5.1 and below": ("float32", "float64", "uint8")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64", "uint8")}, "paddle") @to_ivy_arrays_and_back def adjust_hue(img, hue_factor): assert -0.5 <= hue_factor <= 0.5, "hue_factor should be in range [-0.5, 0.5]" @@ -145,7 +145,7 @@ def adjust_hue(img, hue_factor): @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, "paddle" + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, "paddle" ) @to_ivy_arrays_and_back def hflip(img): @@ -154,7 +154,7 @@ def hflip(img): @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, "paddle" + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, "paddle" ) def normalize(img, mean, std, data_format="CHW", to_rgb=False): if ivy.is_array(img): @@ -171,7 +171,7 @@ def normalize(img, mean, std, data_format="CHW", to_rgb=False): @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, "paddle" + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, "paddle" ) @to_ivy_arrays_and_back def pad(img, padding, fill=0, padding_mode="constant"): @@ -201,7 +201,7 @@ def pad(img, padding, fill=0, padding_mode="constant"): @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64")}, "paddle" + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, "paddle" ) @to_ivy_arrays_and_back def to_tensor(pic, data_format="CHW"): @@ -211,7 +211,7 @@ def to_tensor(pic, data_format="CHW"): @with_unsupported_device_and_dtypes( { - "2.5.1 and below": { + "2.6.0 and below": { "cpu": ("int8", "uint8", "int16", "float16", "bfloat16", "bool") } }, diff --git a/ivy/functional/frontends/pandas/index.py b/ivy/functional/frontends/pandas/index.py index f8cfef5e30010..44b4cefdf3def 100644 --- a/ivy/functional/frontends/pandas/index.py +++ b/ivy/functional/frontends/pandas/index.py @@ -30,7 +30,7 @@ def __init__(self, data, dtype=None, copy=False, name=None, tupleize_cols=True): @staticmethod def _tokenize_1d(x: Iterable): - return ivy.array(list(v for v, _ in enumerate(x))) + return ivy.array([v for v, _ in enumerate(x)]) def __repr__(self): if self.tokens_exist: diff --git a/ivy/functional/frontends/scipy/fft/fft.py b/ivy/functional/frontends/scipy/fft/fft.py index 163589eac0f3d..4b9c9a1dbbbd8 100644 --- a/ivy/functional/frontends/scipy/fft/fft.py +++ b/ivy/functional/frontends/scipy/fft/fft.py @@ -38,7 +38,7 @@ def ifft(x, n=None, axis=-1, norm=None, overwrite_x=False): def ifftn( x, s=None, axes=None, norm=None, overwrite_x=False, workers=None, *, plan=None ): - return ivy.ifftn(x, s=s, dim=axes, norm=norm) + return ivy.ifftn(x, s=s, axes=axes, norm=norm) @to_ivy_arrays_and_back diff --git a/ivy/functional/frontends/scipy/spatial/distance.py b/ivy/functional/frontends/scipy/spatial/distance.py index eb38e843c167f..73c1261f45188 100644 --- a/ivy/functional/frontends/scipy/spatial/distance.py +++ b/ivy/functional/frontends/scipy/spatial/distance.py @@ -29,7 +29,7 @@ def _validate_weights(w, dtype="float64"): # euclidean @to_ivy_arrays_and_back def euclidean(u, v, /, *, w=None): - return minkowski(u, v, p=2, w=w) + return minkowski(u, v, 2, w=w) # Functions # diff --git a/ivy/functional/frontends/sklearn/__init__.py b/ivy/functional/frontends/sklearn/__init__.py index 278ccd9274970..96d60d7f67f9d 100644 --- a/ivy/functional/frontends/sklearn/__init__.py +++ b/ivy/functional/frontends/sklearn/__init__.py @@ -1,3 +1,4 @@ +from . import tree import ivy from ivy.functional.frontends.numpy import array diff --git a/ivy/functional/frontends/sklearn/base.py b/ivy/functional/frontends/sklearn/base.py index 8fa319eb2b587..e8dad2105936a 100644 --- a/ivy/functional/frontends/sklearn/base.py +++ b/ivy/functional/frontends/sklearn/base.py @@ -13,9 +13,6 @@ def score(self, X, y, sample_weight=None): def fit(self, X, y, **kwargs): raise NotImplementedError - def predict(self, X): - raise NotImplementedError - class TransformerMixin: def fit_transform(self, X, y=None, **fit_params): diff --git a/ivy/functional/frontends/sklearn/metrics/_classification.py b/ivy/functional/frontends/sklearn/metrics/_classification.py index e6679505631b5..2c05ae5da5edf 100644 --- a/ivy/functional/frontends/sklearn/metrics/_classification.py +++ b/ivy/functional/frontends/sklearn/metrics/_classification.py @@ -1,6 +1,7 @@ import ivy from ivy.functional.frontends.numpy.func_wrapper import to_ivy_arrays_and_back from sklearn.utils.multiclass import type_of_target +from ivy.utils.exceptions import IvyValueError @to_ivy_arrays_and_back @@ -17,3 +18,36 @@ def accuracy_score(y_true, y_pred, *, normalize=True, sample_weight=None): ret = ret / y_true.shape[0] ret = ret.astype("float64") return ret + + +@to_ivy_arrays_and_back +def recall_score(y_true, y_pred, *, sample_weight=None): + # Ensure that y_true and y_pred have the same shape + if y_true.shape != y_pred.shape: + raise IvyValueError("y_true and y_pred must have the same shape") + + # Check if sample_weight is provided and normalize it + if sample_weight is not None: + sample_weight = ivy.array(sample_weight) + if sample_weight.shape[0] != y_true.shape[0]: + raise IvyValueError( + "sample_weight must have the same length as y_true and y_pred" + ) + sample_weight = sample_weight / ivy.sum(sample_weight) + else: + sample_weight = ivy.ones_like(y_true) + + # Calculate true positives and actual positives + true_positives = ivy.logical_and(ivy.equal(y_true, 1), ivy.equal(y_pred, 1)).astype( + "int64" + ) + actual_positives = ivy.equal(y_true, 1).astype("int64") + + # Apply sample weights + weighted_true_positives = ivy.multiply(true_positives, sample_weight) + weighted_actual_positives = ivy.multiply(actual_positives, sample_weight) + + # Compute recall + ret = ivy.sum(weighted_true_positives) / ivy.sum(weighted_actual_positives) + ret = ret.astype("float64") + return ret diff --git a/ivy/functional/frontends/sklearn/model_selection/_split.py b/ivy/functional/frontends/sklearn/model_selection/_split.py index 25b51c3451fe6..1f14400186012 100644 --- a/ivy/functional/frontends/sklearn/model_selection/_split.py +++ b/ivy/functional/frontends/sklearn/model_selection/_split.py @@ -74,10 +74,10 @@ def __init__( ) def _iter_test_indices(self, X=None, y=None, groups=None): - ivy.seed(self.random_state) + ivy.seed(seed_value=self.random_state) y = ivy.array(y) y = column_or_1d(y) - _, y_idx, y_inv, _ = ivy.unique_all(y, return_index=True, return_inverse=True) + _, y_idx, y_inv, _ = ivy.unique_all(y) class_perm = ivy.unique_inverse(y_idx) y_encoded = class_perm[y_inv] @@ -123,12 +123,16 @@ def train_test_split( n_train = ( ivy.floor(train_size * n_samples) if isinstance(train_size, float) - else float(train_size) if isinstance(train_size, int) else None + else float(train_size) + if isinstance(train_size, int) + else None ) n_test = ( ivy.ceil(test_size * n_samples) if isinstance(test_size, float) - else float(test_size) if isinstance(test_size, int) else None + else float(test_size) + if isinstance(test_size, int) + else None ) if train_size is None: n_train = n_samples - n_test @@ -139,7 +143,7 @@ def train_test_split( indices = ivy.arange(0, n_train + n_test) if shuffle: if random_state is not None: - ivy.seed(random_state) + ivy.seed(seed_value=random_state) indices = ivy.shuffle(indices) train_indices = indices[:n_train] test_indices = indices[n_train:] diff --git a/ivy/functional/frontends/sklearn/tree/__init__.py b/ivy/functional/frontends/sklearn/tree/__init__.py new file mode 100644 index 0000000000000..b726da4f4a4c2 --- /dev/null +++ b/ivy/functional/frontends/sklearn/tree/__init__.py @@ -0,0 +1,8 @@ +from . import _classes +from ._classes import * +from . import _criterion +from ._criterion import * +from . import _splitter +from ._splitter import * +from . import _tree +from ._tree import * diff --git a/ivy/functional/frontends/sklearn/tree/_classes.py b/ivy/functional/frontends/sklearn/tree/_classes.py index d2e8dc8b17c30..6cfbe791630ef 100644 --- a/ivy/functional/frontends/sklearn/tree/_classes.py +++ b/ivy/functional/frontends/sklearn/tree/_classes.py @@ -4,6 +4,12 @@ ClassifierMixin, MultiOutputMixin, ) +import copy +from ._criterion import Gini, Criterion +from ._splitter import BestSplitter, Splitter +from ._tree import DepthFirstTreeBuilder, Tree +import ivy +import numbers class BaseDecisionTree(MultiOutputMixin, BaseEstimator, metaclass=ABCMeta): @@ -43,12 +49,6 @@ def get_depth(self): def get_n_leaves(self): raise NotImplementedError - def _support_missing_values(self, X): - raise NotImplementedError - - def _compute_missing_values_in_feature_mask(self, X): - raise NotImplementedError - def _fit( self, X, @@ -57,24 +57,119 @@ def _fit( check_input=True, missing_values_in_feature_mask=None, ): - raise NotImplementedError + ivy.seed(seed_value=self.random_state) + n_samples, self.n_features_in_ = X.shape + y = ivy.atleast_1d(y) + if y.ndim == 1: + y = ivy.reshape(y, (-1, 1)) + self.n_outputs_ = y.shape[1] + y = ivy.copy.copy(y) + self.classes_ = [] + self.n_classes_ = [] + if self.class_weight is not None: + ivy.copy.copy(y) + y_encoded = ivy.zeros(y.shape, dtype=ivy.int32) + + for k in range(self.n_outputs_): + classes_k, y_encoded[:, k] = ivy.unique_inverse(y[:, k]) + self.classes_.append(classes_k) + self.n_classes_.append(classes_k.shape[0]) + y = y_encoded + + self.n_classes_ = ivy.array(self.n_classes_, dtype="int64") + + y = ivy.array(y, dtype="float32") + max_depth = ( + ivy.iinfo(ivy.int32).max if self.max_depth is None else self.max_depth + ) - def _validate_X_predict(self, X, check_input): - raise NotImplementedError + if isinstance(self.min_samples_leaf, numbers.Integral): + min_samples_leaf = self.min_samples_leaf + else: + min_samples_leaf = int(ivy.ceil(self.min_samples_leaf * n_samples)) + + if isinstance(self.min_samples_split, numbers.Integral): + min_samples_split = self.min_samples_split + else: + min_samples_split = int(ivy.ceil(self.min_samples_split * n_samples)) + min_samples_split = max(2, min_samples_split) + min_samples_split = max(min_samples_split, 2 * min_samples_leaf) + if self.max_features is None: # todo: other cases + max_features = self.n_features_in_ + self.max_features_ = max_features + assert len(y) == n_samples, "Number of labels does not match number of samples" + + if sample_weight is None: + min_weight_leaf = self.min_weight_fraction_leaf * n_samples + else: + min_weight_leaf = self.min_weight_fraction_leaf * ivy.sum(sample_weight) + + self.n_classes_ = ivy.array(self.n_classes_, dtype=ivy.int64) + + criterion = self.criterion + if not isinstance(criterion, Criterion): + criterion = Gini(self.n_outputs_, self.n_classes_) + else: + criterion = copy.deepcopy(criterion) + splitter = self.splitter + monotonic_cst = None + + if not isinstance(self.splitter, Splitter): + splitter = BestSplitter( + criterion, + self.max_features_, + min_samples_leaf, + min_weight_leaf, + self.random_state, + monotonic_cst, + ) + self.tree_ = Tree(self.n_features_in_, self.n_classes_, self.n_outputs_) + builder = DepthFirstTreeBuilder( + splitter, + min_samples_split, + min_samples_leaf, + min_weight_leaf, + max_depth, + self.min_impurity_decrease, + ) + builder.build(self.tree_, X, y, sample_weight, missing_values_in_feature_mask) + if self.n_outputs_ == 1: + self.n_classes_ = self.n_classes_[0] + self.classes_ = self.classes_[0] + self._prune_tree() + return self + + def _prune_tree(self): + if self.ccp_alpha == 0.0: + return + n_classes = ivy.atleast_1d(self.n_classes_) + pruned_tree = Tree(self.n_features_in_, n_classes, self.n_outputs_) + self.tree_ = pruned_tree def predict(self, X, check_input=True): - raise NotImplementedError + ivy.seed(seed_value=self.random_state) + proba = self.tree_.predict(X) + n_samples = X.shape[0] - def apply(self, X, check_input=True): - raise NotImplementedError + # Classification - def decision_path(self, X, check_input=True): - raise NotImplementedError + if self.n_outputs_ == 1: + return ivy.gather(self.classes_, ivy.argmax(proba, axis=1), axis=0) - def _prune_tree(self): + else: + class_type = self.classes_[0].dtype + predictions = ivy.zeros((n_samples, self.n_outputs_), dtype=class_type) + for k in range(self.n_outputs_): + predictions[:, k] = ivy.gather( + self.classes_[k], ivy.argmax(proba[:, k], axis=1), axis=0 + ) + + return predictions + + def apply(self, X, check_input=True): raise NotImplementedError - def cost_complexity_pruning_path(self, X, y, sample_weight=None): + def decision_path(self, X, check_input=True): raise NotImplementedError @property @@ -128,11 +223,3 @@ def predict_proba(self, X, check_input=True): def predict_log_proba(self, X): raise NotImplementedError - - def _more_tags(self): - allow_nan = self.splitter == "best" and self.criterion in { - "gini", - "log_loss", - "entropy", - } - return {"multilabel": True, "allow_nan": allow_nan} diff --git a/ivy/functional/frontends/sklearn/tree/_criterion.py b/ivy/functional/frontends/sklearn/tree/_criterion.py new file mode 100644 index 0000000000000..90458f27ef5cc --- /dev/null +++ b/ivy/functional/frontends/sklearn/tree/_criterion.py @@ -0,0 +1,258 @@ +from abc import ABC, abstractmethod +import ivy + + +class Criterion(ABC): + @abstractmethod + def reset(self): + raise NotImplementedError + + @abstractmethod + def reverse_reset(self): + raise NotImplementedError + + @abstractmethod + def update(self, new_pos): + raise NotImplementedError + + def proxy_impurity_improvement(self): + impurity_left = 0.0 + impurity_right = 0.0 + impurity_left, impurity_right = self.children_impurity( + impurity_left, impurity_right + ) + + return ( + -self.weighted_n_right * impurity_right + - self.weighted_n_left * impurity_left + ) + + def impurity_improvement( + self, impurity_parent: float, impurity_left: float, impurity_right: float + ): + return (self.weighted_n_node_samples / self.weighted_n_samples) * ( + impurity_parent + - (self.weighted_n_right / self.weighted_n_node_samples * impurity_right) + - (self.weighted_n_left / self.weighted_n_node_samples * impurity_left) + ) + + def node_value(self, dest, node_id): + return dest + + +class ClassificationCriterion(Criterion): + def __init__(self, n_outputs: int, n_classes: ivy.Array): + self.start = 0 + self.pos = 0 + self.end = 0 + self.missing_go_to_left = 0 + self.n_outputs = n_outputs + self.n_samples = 0 + self.n_node_samples = 0 + self.weighted_n_node_samples = 0.0 + self.weighted_n_left = 0.0 + self.weighted_n_right = 0.0 + self.weighted_n_missing = 0.0 + self.n_classes = ivy.empty(n_outputs, dtype=ivy.int16) + max_n_classes = 0 + + for k in range(n_outputs): + self.n_classes[k] = n_classes[k] + if n_classes[k] > max_n_classes: + max_n_classes = n_classes[k] + if isinstance(max_n_classes, ivy.Array): + max_n_classes = ivy.to_scalar(max_n_classes) + self.max_n_classes = max_n_classes + + self.sum_total = ivy.zeros((n_outputs, max_n_classes), dtype=ivy.float64) + self.sum_left = ivy.zeros((n_outputs, max_n_classes), dtype=ivy.float64) + self.sum_right = ivy.zeros((n_outputs, max_n_classes), dtype=ivy.float64) + + def init( + self, + y, + sample_weight, + weighted_n_samples, + sample_indices, + start, + end, + ): + self.y = y + self.sample_weight = sample_weight + self.sample_indices = sample_indices + self.start = start + self.end = end + self.n_node_samples = end - start + self.weighted_n_samples = weighted_n_samples + self.weighted_n_node_samples = 0.0 + w = 1.0 + + for k in range(self.n_outputs): + n_cls = ivy.to_scalar(self.n_classes[k]) + self.sum_total[k, :n_cls] = 0 + + for p in range(start, end): + i = sample_indices[p] + if sample_weight is not None: + w = sample_weight[i] + for k in range(self.n_outputs): + c = int(self.y[i, k]) + self.sum_total[k, c] += w + + self.weighted_n_node_samples += w + + self.reset() + return 0 + + def init_sum_missing(self): + self.sum_missing = ivy.zeros( + (self.n_outputs, self.max_n_classes), dtype=ivy.float64 + ) + + def node_value(self, dest, node_id): + for k in range(self.n_outputs): + n_cls = ivy.to_scalar(self.n_classes[k]) + dest[node_id, k, :n_cls] = self.sum_total[k, :n_cls] + return dest + + def init_missing(self, n_missing): + w = 1.0 + self.n_missing = n_missing + if n_missing == 0: + return + self.sum_missing[0 : self.n_outputs, 0 : self.max_n_classes] = 0 + self.weighted_n_missing = 0.0 + for p in range(self.end - n_missing, self.end): + i = self.sample_indices[p] + if self.sample_weight is not None: + w = self.sample_weight[i] + + for k in range(self.n_outputs): + c = int(self.y[i, k]) + self.sum_missing[k, c] += w + + self.weighted_n_missing += w + + def reset(self): + self.pos = self.start + ( + self.weighted_n_left, + self.weighted_n_right, + self.sum_left, + self.sum_right, + ) = _move_sums_classification( + self, + self.sum_left, + self.sum_right, + self.weighted_n_left, + self.weighted_n_right, + self.missing_go_to_left, + ) + return 0 + + def reverse_reset(self): + self.pos = self.end + ( + self.weighted_n_right, + self.weighted_n_left, + self.sum_right, + self.sum_left, + ) = _move_sums_classification( + self, + self.sum_right, + self.sum_left, + self.weighted_n_right, + self.weighted_n_left, + not self.missing_go_to_left, + ) + return 0 + + def update(self, new_pos): + pos = self.pos + end_non_missing = self.end - self.n_missing + sample_indices = self.sample_indices + sample_weight = self.sample_weight + w = 1.0 + + if (new_pos - pos) <= (end_non_missing - new_pos): + for p in range(pos, new_pos): + i = sample_indices[p] + if sample_weight is not None: + w = sample_weight[i] + for k in range(self.n_outputs): + c = int(self.y[i, k]) + self.sum_left[k, c] += w + self.weighted_n_left += w + + else: + self.reverse_reset() + for p in range(end_non_missing - 1, new_pos - 1, -1): + i = sample_indices[p] + if sample_weight is not None: + w = sample_weight[i] + for k in range(self.n_outputs): + c = int(self.y[i, k]) + self.sum_left[k, c] -= w + self.weighted_n_left -= w + self.weighted_n_right = self.weighted_n_node_samples - self.weighted_n_left + for k in range(self.n_outputs): + for c in range(ivy.to_scalar(self.n_classes[k])): + self.sum_right[k, c] = self.sum_total[k, c] - self.sum_left[k, c] + self.pos = new_pos + return 0 + + +class Gini(ClassificationCriterion): + def node_impurity(self): + gini = 0.0 + for k in range(self.n_outputs): + sq_count = 0.0 + for c in range(int(self.n_classes[k])): + count_k = self.sum_total[k, c] + sq_count += count_k * count_k + gini += 1.0 - sq_count / ( + self.weighted_n_node_samples * self.weighted_n_node_samples + ) + return gini / self.n_outputs + + def children_impurity( + self, + impurity_left: float, + impurity_right: float, + ): + gini_left, gini_right = 0.0, 0.0 + for k in range(self.n_outputs): + sq_count_left, sq_count_right = 0.0, 0.0 + for c in range(int(self.n_classes[k])): + count_k = self.sum_left[k, c] + sq_count_left += count_k * count_k + count_k = self.sum_right[k, c] + sq_count_right += count_k * count_k + + gini_left += 1.0 - sq_count_left / ( + self.weighted_n_left * self.weighted_n_left + ) + gini_right += 1.0 - sq_count_right / ( + self.weighted_n_right * self.weighted_n_right + ) + impurity_left = gini_left / self.n_outputs + impurity_right = gini_right / self.n_outputs + return impurity_left, impurity_right + + +# --- Helpers --- # +# --------------- # + + +def _move_sums_classification( + criterion, sum_1, sum_2, weighted_n_1, weighted_n_2, put_missing_in_1 +): + for k in range(criterion.n_outputs): + n = int(criterion.n_classes[k]) + sum_1[k, :n] = 0 + sum_2[k, :n] = criterion.sum_total[k, :n] + + weighted_n_1 = 0.0 + weighted_n_2 = criterion.weighted_n_node_samples + + return weighted_n_1, weighted_n_2, sum_1, sum_2 diff --git a/ivy/functional/frontends/sklearn/tree/_splitter.py b/ivy/functional/frontends/sklearn/tree/_splitter.py new file mode 100644 index 0000000000000..6325b84ca2b0b --- /dev/null +++ b/ivy/functional/frontends/sklearn/tree/_splitter.py @@ -0,0 +1,509 @@ +import ivy + +FEATURE_THRESHOLD = 1e-7 + + +class Splitter: + def __init__( + self, + criterion, + max_features, + min_samples_leaf, + min_weight_leaf, + random_state, + *args, + ): + self.criterion = criterion + self.n_samples = 0 + self.n_features = 0 + self.max_features = max_features + self.min_samples_leaf = min_samples_leaf + self.min_weight_leaf = min_weight_leaf + self.random_state = random_state + + def init( + self, + X, + y, + sample_weight, + missing_values_in_feature_mask, + *args, + ): + n_samples = X.shape[0] + self.samples = ivy.empty(n_samples, dtype=ivy.int32) + samples = self.samples + j = 0 + weighted_n_samples = 0.0 + + for i in range(n_samples): + if sample_weight is None or sample_weight[i] != 0.0: + samples[j] = i + j += 1 + if sample_weight is not None: + weighted_n_samples += sample_weight[i] + else: + weighted_n_samples += 1.0 + + self.n_samples = j + self.weighted_n_samples = weighted_n_samples + n_features = X.shape[1] + self.features = ivy.arange(n_features, dtype=ivy.int32) + self.n_features = n_features + self.feature_values = ivy.empty(n_samples, dtype=ivy.float32) + self.constant_features = ivy.empty(n_features, dtype=ivy.int32) + self.y = y + self.sample_weight = sample_weight + if missing_values_in_feature_mask is not None: + self.criterion.init_sum_missing() + return 0 + + def node_reset(self, start, end, weighted_n_node_samples): + self.start = start + self.end = end + self.criterion.init( + self.y, + self.sample_weight, + self.weighted_n_samples, + self.samples, + start, + end, + ) + weighted_n_node_samples = self.criterion.weighted_n_node_samples + return 0, weighted_n_node_samples + + def node_split(self, impurity, split, n_constant_features): + pass + + def node_value(self, dest, node_id): + return self.criterion.node_value(dest, node_id) + + def node_impurity(self): + return self.criterion.node_impurity() + + +class DensePartitioner: + X = [] + samples = [] + feature_values = [] + start = 0 + end = 0 + n_missing = 0 + missing_values_in_feature_mask = [] + + def __init__( + self, + X, + samples, + feature_values, + missing_values_in_feature_mask, + ): + self.X = X + self.samples = samples + self.feature_values = feature_values + self.missing_values_in_feature_mask = missing_values_in_feature_mask + + def init_node_split(self, start, end): + self.start = start + self.end = end + self.n_missing = 0 + + def sort_samples_and_feature_values(self, current_feature): + feature_values = self.feature_values + X = self.X + samples = self.samples + n_missing = 0 + missing_values_in_feature_mask = self.missing_values_in_feature_mask + if ( + missing_values_in_feature_mask is not None + and missing_values_in_feature_mask[current_feature] + ): + i, current_end = self.start, self.end - 1 + while i <= current_end: + if ivy.isnan(X[samples[current_end], current_feature]): + n_missing += 1 + current_end -= 1 + continue + if ivy.isnan(X[samples[i], current_feature]): + samples[i], samples[current_end] = samples[current_end], samples[i] + n_missing += 1 + current_end -= 1 + feature_values[i] = X[samples[i], current_feature] + i += 1 + else: + for i in range(self.start, self.end): + feature_values[i] = X[int(samples[i]), int(current_feature)] + ( + self.feature_values[self.start : self.end], + self.samples[self.start : self.end], + ) = sort( + feature_values[self.start : self.end], + samples[self.start : self.end], + self.end - self.start - n_missing, + ) + self.n_missing = n_missing + + def find_min_max( + self, + current_feature: int, + min_feature_value_out: float, + max_feature_value_out: float, + ): + current_feature = 0 + X = self.X + samples = self.samples + min_feature_value = X[samples[self.start], current_feature] + max_feature_value = min_feature_value + feature_values = self.feature_values + feature_values[self.start] = min_feature_value + for p in range(self.start + 1, self.end): + current_feature_value = X[samples[p], current_feature] + feature_values[p] = current_feature_value + + if current_feature_value < min_feature_value: + min_feature_value = current_feature_value + elif current_feature_value > max_feature_value: + max_feature_value = current_feature_value + return min_feature_value, max_feature_value + + def next_p(self, p_prev: int, p: int): + feature_values = self.feature_values + end_non_missing = self.end - self.n_missing + + while ( + p + 1 < end_non_missing + and feature_values[p + 1] <= feature_values[p] + FEATURE_THRESHOLD + ): + p += 1 + p_prev = p + p += 1 + return p_prev, p + + def partition_samples(self, current_thershold: float): + p = self.start + partition_end = self.end + samples = self.samples + feature_values = self.feature_values + while p < partition_end: + if feature_values[p] <= current_thershold: + p += 1 + else: + partition_end -= 1 + + feature_values[p], feature_values[partition_end] = ( + feature_values[partition_end], + feature_values[p], + ) + samples[p], samples[partition_end] = ( + samples[partition_end], + samples[p], + ) + return partition_end + + def partition_samples_final( + self, + best_pos, + best_threshold, + best_feature, + best_n_missing, + ): + start = self.start + p = start + end = self.end - 1 + partition_end = end - best_n_missing + samples = self.samples + X = self.X + + if best_n_missing != 0: + while p < partition_end: + if ivy.isnan(X[samples[end], best_feature]): + end -= 1 + continue + current_value = X[samples[p], best_feature] + if ivy.isnan(current_value): + samples[p], samples[end] = samples[end], samples[p] + end -= 1 + current_value = X[samples[p], best_feature] + if current_value <= best_threshold: + p += 1 + else: + samples[p], samples[partition_end] = ( + samples[partition_end], + samples[p], + ) + partition_end -= 1 + else: + while p < partition_end: + if X[samples[p], best_feature] <= best_threshold: + p += 1 + else: + samples[p], samples[partition_end] = ( + samples[partition_end], + samples[p], + ) + partition_end -= 1 + self.samples = samples + + +class SplitRecord: + def __init__( + self, + feature=0, + pos=0, + threshold=0.0, + improvement=-ivy.inf, + impurity_left=0.0, + impurity_right=0.0, + missing_go_to_left=False, + n_missing=0, + ): + self.feature = feature + self.pos = pos + self.threshold = threshold + self.improvement = improvement + self.impurity_left = impurity_left + self.impurity_right = impurity_right + self.missing_go_to_left = missing_go_to_left + self.n_missing = n_missing + + +class BestSplitter(Splitter): + def init( + self, + X, + y, + sample_weight, + missing_values_in_feature_mask, + *args, + ): + Splitter.init(self, X, y, sample_weight, missing_values_in_feature_mask, *args) + self.partitioner = DensePartitioner( + X, self.samples, self.feature_values, missing_values_in_feature_mask + ) + + def node_split(self, impurity, split, n_constant_features): + return node_split_best( + self, + self.partitioner, + self.criterion, + impurity, + split, + n_constant_features, + ) + + +# --- Helpers --- # +# --------------- # + + +def _init_split(split_record, start_pos): + split_record.impurity_left = ivy.inf + split_record.impurity_right = ivy.inf + split_record.pos = start_pos + split_record.feature = 0 + split_record.threshold = 0.0 + split_record.improvement = -ivy.inf + split_record.missing_go_to_left = False + split_record.n_missing = 0 + return split_record + + +# --- Main --- # +# ------------ # + + +def node_split_best( + splitter, partitioner, criterion, impurity, split, n_constant_features +): + start = splitter.start + end = splitter.end + features = splitter.features + constant_features = splitter.constant_features + n_features = splitter.n_features + + feature_values = splitter.feature_values + max_features = splitter.max_features + min_samples_leaf = splitter.min_samples_leaf + min_weight_leaf = splitter.min_weight_leaf + + best_split = SplitRecord() + current_split = SplitRecord() + best_proxy_improvement = -ivy.inf + + f_i = n_features + p_prev = 0 + + n_visited_features = 0 + # Number of features discovered to be constant during the split search + n_found_constants = 0 + # Number of features known to be constant and drawn without replacement + n_drawn_constants = 0 + n_known_constants = n_constant_features + # n_total_constants = n_known_constants + n_found_constants + n_total_constants = n_known_constants + best_split = _init_split(best_split, end) + partitioner.init_node_split(start, end) + while f_i > n_total_constants and ( + n_visited_features < max_features + or n_visited_features <= n_found_constants + n_drawn_constants + ): + n_visited_features += 1 + f_j = ivy.randint(n_drawn_constants, f_i - n_found_constants) + + if f_j < n_known_constants: + features[n_drawn_constants], features[f_j] = ( + features[f_j], + features[n_drawn_constants], + ) + + n_drawn_constants += 1 + continue + + # f_j in the interval [n_known_constants, f_i - n_found_constants[ + f_j += n_found_constants + # f_j in the interval [n_total_constants, f_i[ + current_split.feature = features[f_j] + partitioner.sort_samples_and_feature_values(current_split.feature) + n_missing = partitioner.n_missing + end_non_missing = end - n_missing + + if ( + end_non_missing == start + or feature_values[end_non_missing - 1] + <= feature_values[start] + FEATURE_THRESHOLD + ): + features[f_j], features[n_total_constants] = ( + features[n_total_constants], + features[f_j], + ) + + n_found_constants += 1 + n_total_constants += 1 + continue + + f_i -= 1 + features[f_i], features[f_j] = features[f_j], features[f_i] + has_missing = n_missing != 0 + criterion.init_missing(n_missing) + n_searches = 2 if has_missing else 1 + for i in range(n_searches): + missing_go_to_left = i == 1 + criterion.missing_go_to_left = missing_go_to_left + criterion.reset() + p = start + + while p < end_non_missing: + p_prev, p = partitioner.next_p(p_prev, p) + + if p >= end_non_missing: + continue + + if missing_go_to_left: + n_left = p - start + n_missing + n_right = end_non_missing - p + else: + n_left = p - start + n_right = end_non_missing - p + n_missing + + if n_left < min_samples_leaf or n_right < min_samples_leaf: + continue + + current_split.pos = p + criterion.update(current_split.pos) + + if ( + criterion.weighted_n_left < min_weight_leaf + or criterion.weighted_n_right < min_weight_leaf + ): + continue + + current_proxy_improvement = criterion.proxy_impurity_improvement() + + if current_proxy_improvement > best_proxy_improvement: + best_proxy_improvement = current_proxy_improvement + current_split.threshold = ( + feature_values[p_prev] / 2.0 + feature_values[p] / 2.0 + ) + + if current_split.threshold in ( + feature_values[p], + ivy.inf, + -ivy.inf, + ): + current_split.threshold = feature_values[p_prev] + + current_split.n_missing = n_missing + if n_missing == 0: + current_split.missing_go_to_left = n_left > n_right + else: + current_split.missing_go_to_left = missing_go_to_left + + best_split = SplitRecord(**current_split.__dict__) + + if has_missing: + n_left, n_right = end - start - n_missing, n_missing + p = end - n_missing + missing_go_to_left = 0 + + if not ((n_left < min_samples_leaf) or (n_right < min_samples_leaf)): + criterion.missing_go_to_left = missing_go_to_left + criterion.update(p) + + if not ( + criterion.weighted_n_left < min_weight_leaf + or criterion.weighted_n_right < min_weight_leaf + ): + current_proxy_improvement = criterion.proxy_impurity_improvement() + + if current_proxy_improvement > best_proxy_improvement: + best_proxy_improvement = current_proxy_improvement + current_split.threshold = ivy.inf + current_split.missing_go_to_left = missing_go_to_left + current_split.n_missing = n_missing + current_split.pos = p + best_split = current_split + + # Reorganize into samples[start:best_split.pos] + samples[best_split.pos:end] + if best_split.pos < end: + partitioner.partition_samples_final( + best_split.pos, + best_split.threshold, + best_split.feature, + best_split.n_missing, + ) + + if best_split.n_missing != 0: + criterion.init_missing(best_split.n_missing) + + criterion.missing_go_to_left = best_split.missing_go_to_left + criterion.reset() + criterion.update(best_split.pos) + + ( + best_split.impurity_left, + best_split.impurity_right, + ) = criterion.children_impurity( + best_split.impurity_left, best_split.impurity_right + ) + + best_split.improvement = criterion.impurity_improvement( + impurity, best_split.impurity_left, best_split.impurity_right + ) + + # best_split, samples = shift_missing_values_to_left_if_required( + # best_split, samples, end) + # todo : implement shift_missing_values_to_left_if_required + features[0:n_known_constants] = constant_features[0:n_known_constants] + constant_features[n_known_constants:n_found_constants] = features[ + n_known_constants:n_found_constants + ] + + split = best_split + n_constant_features = n_total_constants + return 0, n_constant_features, split + + +def sort(feature_values, samples, n): + if n == 0: + return + idx = ivy.argsort(feature_values) + return feature_values[idx], samples[idx] diff --git a/ivy/functional/frontends/sklearn/tree/_tree.py b/ivy/functional/frontends/sklearn/tree/_tree.py new file mode 100644 index 0000000000000..53fc4e604c4f1 --- /dev/null +++ b/ivy/functional/frontends/sklearn/tree/_tree.py @@ -0,0 +1,317 @@ +import ivy +from ._splitter import SplitRecord + +EPSILON = ivy.finfo(ivy.double).eps +INFINITY = ivy.inf +INTPTR_MAX = ivy.iinfo(ivy.int32).max +TREE_LEAF = -1 +TREE_UNDEFINED = -2 +_TREE_LEAF = TREE_LEAF +_TREE_UNDEFINED = TREE_UNDEFINED + + +class Node: + def __init__(self): + self.left_child = None + self.right_child = None + self.feature = None + self.threshold = None + self.impurity = None + self.n_node_samples = None + self.weighted_n_node_samples = None + self.missing_go_to_left = None + + +class Tree: + def __init__(self, n_features, n_classes, n_outputs): + self.max_depth = 0 + self.node_count = 0 + self.capacity = 0 + self.nodes = [] + self.value = None + + self.n_features = n_features + self.n_outputs = n_outputs + self.n_classes = ivy.zeros(n_outputs, dtype=ivy.int32) + + self.max_n_classes = ivy.max(n_classes) + self.value_stride = n_outputs * self.max_n_classes + + for k in range(n_outputs): + self.n_classes[k] = n_classes[k] + + def _resize(self, capacity): + self._resize_c(capacity) + + def _resize_c(self, capacity=INTPTR_MAX): + if capacity == self.capacity and len(self.nodes) != 0: + return 0 + if capacity == INTPTR_MAX: + if self.capacity == 0: + capacity = 3 + else: + capacity = 2 * self.capacity + if self.value is None: + self.value = ivy.zeros( + (capacity, int(self.n_outputs), int(self.max_n_classes)), + dtype=ivy.float32, + ) + else: + self.value = ivy.concat( + [ + self.value, + ivy.zeros( + ( + int(capacity - self.capacity), + int(self.n_outputs), + int(self.max_n_classes), + ), + dtype=ivy.float32, + ), + ] + ) + if capacity < self.node_count: + self.node_count = capacity + self.capacity = capacity + return 0 + + def _add_node( + self, + parent, + is_left, + is_leaf, + feature, + threshold, + impurity, + n_node_samples, + weighted_n_node_samples, + missing_go_to_left, + ): + node_id = self.node_count + if node_id >= self.capacity: + self._resize_c() + + node = Node() + node.impurity = impurity + node.n_node_samples = n_node_samples + node.weighted_n_node_samples = weighted_n_node_samples + + if parent != _TREE_UNDEFINED: + if is_left: + self.nodes[parent].left_child = node_id + else: + self.nodes[parent].right_child = node_id + + if is_leaf: + node.left_child = _TREE_LEAF + node.right_child = _TREE_LEAF + node.feature = _TREE_UNDEFINED + node.threshold = _TREE_UNDEFINED + else: + node.feature = feature + node.threshold = threshold + node.missing_go_to_left = missing_go_to_left + + self.nodes.append(node) + self.node_count += 1 + + return node_id + + def predict(self, X): + X_applied = self.apply(X) + out = ivy.take(self.value, X_applied, axis=0) + if self.n_outputs == 1: + out = out.reshape((X.shape[0], self.max_n_classes)) + return out + + def apply(self, X): + return self._apply_dense(X) + + def _apply_dense(self, X): + X_tensor = X + n_samples = X.shape[0] + out = ivy.zeros(n_samples, dtype="int32") + for i in range(n_samples): + node = self.nodes[0] # root node + while node.left_child != _TREE_LEAF: + X_i_node_feature = X_tensor[i, node.feature] + if ivy.isnan(X_i_node_feature): + if node.missing_go_to_left: + node = self.nodes[node.left_child] + else: + node = self.nodes[node.right_child] + elif X_i_node_feature <= node.threshold: + node = self.nodes[node.left_child] + else: + node = self.nodes[node.right_child] + out[i] = self.nodes.index(node) # terminal node index + return out + + +class StackRecord: + def __init__( + self, + start, + end, + depth, + parent, + is_left, + impurity, + n_constant_features, + ): + self.start = start + self.end = end + self.depth = depth + self.parent = parent + self.is_left = is_left + self.impurity = impurity + self.n_constant_features = n_constant_features + + +class TreeBuilder: + def build( + self, + tree, + X, + y, + sample_weight=None, + missing_values_in_feature_mask=None, + ): + pass + + +class DepthFirstTreeBuilder(TreeBuilder): + def __init__( + self, + splitter, + min_samples_split, + min_samples_leaf, + min_weight_leaf, + max_depth, + min_impurity_decrease, + ): + self.splitter = splitter + self.min_samples_split = min_samples_split + self.min_samples_leaf = min_samples_leaf + self.min_weight_leaf = min_weight_leaf + self.max_depth = max_depth + self.min_impurity_decrease = min_impurity_decrease + + def build( + self, tree, X, y, sample_weight=None, missing_values_in_feature_mask=None + ): + if tree.max_depth <= 10: + init_capacity = int(2 ** (tree.max_depth + 1)) - 1 + else: + init_capacity = 2047 + tree._resize(init_capacity) + + splitter = self.splitter + max_depth = self.max_depth + min_samples_leaf = self.min_samples_leaf + min_weight_leaf = self.min_weight_leaf + min_samples_split = self.min_samples_split + min_impurity_decrease = self.min_impurity_decrease + + splitter.init(X, y, sample_weight, missing_values_in_feature_mask) + weighted_n_node_samples = 0.0 + split = SplitRecord() + first = 1 + max_depth_seen = -1 + builder_stack = [] + + # Push root node onto stack + builder_stack.append( + StackRecord( + start=0, + end=splitter.n_samples, + depth=0, + parent=-2, + is_left=False, + impurity=INFINITY, + n_constant_features=0, + ) + ) + + while len(builder_stack) > 0: + stack_record = builder_stack.pop() + + start = stack_record.start + end = stack_record.end + depth = stack_record.depth + parent = stack_record.parent + is_left = stack_record.is_left + impurity = stack_record.impurity + n_constant_features = stack_record.n_constant_features + + n_node_samples = end - start + _, weighted_n_node_samples = splitter.node_reset( + start, end, weighted_n_node_samples + ) + + is_leaf = ( + depth >= max_depth + or n_node_samples < min_samples_split + or n_node_samples < 2 * min_samples_leaf + or weighted_n_node_samples < 2 * min_weight_leaf + ) + + if first: + impurity = splitter.node_impurity() + first = 0 + is_leaf = is_leaf or impurity <= EPSILON + + if not is_leaf: + _, n_constant_features, split = splitter.node_split( + impurity, split, n_constant_features + ) + + is_leaf = ( + is_leaf + or split.pos >= end + or (split.improvement + EPSILON < min_impurity_decrease) + ) + + node_id = tree._add_node( + parent, + is_left, + is_leaf, + split.feature, + split.threshold, + impurity, + n_node_samples, + weighted_n_node_samples, + split.missing_go_to_left, + ) + tree.value = splitter.node_value(tree.value, node_id) + + if not is_leaf: + # Push right child on stack + builder_stack.append( + StackRecord( + start=split.pos, + end=end, + depth=depth + 1, + parent=node_id, + is_left=False, + impurity=split.impurity_right, + n_constant_features=n_constant_features, + ) + ) + + # Push left child on stack + builder_stack.append( + StackRecord( + start=start, + end=split.pos, + depth=depth + 1, + parent=node_id, + is_left=True, + impurity=split.impurity_left, + n_constant_features=n_constant_features, + ) + ) + + if depth > max_depth_seen: + max_depth_seen = depth + tree.max_depth = max_depth_seen diff --git a/ivy/functional/frontends/tensorflow/__init__.py b/ivy/functional/frontends/tensorflow/__init__.py index 80ca1cf42b93f..50c96a4cecfe8 100644 --- a/ivy/functional/frontends/tensorflow/__init__.py +++ b/ivy/functional/frontends/tensorflow/__init__.py @@ -53,10 +53,9 @@ @handle_exceptions def check_tensorflow_casting(x1, x2): - """ - Check whether the two arguments provided in the function have the same dtype, unless - one of them is an array_like or scalar, where it gets casted to the other input's - dtype. + """Check whether the two arguments provided in the function have the same + dtype, unless one of them is an array_like or scalar, where it gets casted + to the other input's dtype. Parameters ---------- @@ -75,6 +74,9 @@ def check_tensorflow_casting(x1, x2): if hasattr(x1, "dtype") and not hasattr(x2, "dtype"): x1 = ivy.asarray(x1) x2 = ivy.asarray(x2, dtype=x1.dtype) + elif hasattr(x2, "dtype") and not hasattr(x1, "dtype"): + x2 = ivy.asarray(x2) + x1 = ivy.asarray(x1, dtype=x2.dtype) else: x1 = ivy.asarray(x1) if not hasattr(x2, "dtype"): @@ -84,7 +86,7 @@ def check_tensorflow_casting(x1, x2): from . import dtypes -from .dtypes import DType, as_dtype, cast +from .dtypes import as_dtype, cast from . import ragged from .ragged import * from . import tensor @@ -92,6 +94,7 @@ def check_tensorflow_casting(x1, x2): from .tensorarray import TensorArray from . import variable from .variable import Variable, IndexedSlices +from .python.ops.resource_variable_ops import ResourceVariable from . import keras from . import compat from . import image @@ -101,6 +104,7 @@ def check_tensorflow_casting(x1, x2): from .math import * from . import nest from . import nn +from . import __operators__ from . import quantization from . import random from . import general_functions diff --git a/ivy/functional/frontends/tensorflow/__operators__.py b/ivy/functional/frontends/tensorflow/__operators__.py new file mode 100644 index 0000000000000..7945e8f863764 --- /dev/null +++ b/ivy/functional/frontends/tensorflow/__operators__.py @@ -0,0 +1,5 @@ +import ivy.functional.frontends.tensorflow as tf_frontend + + +def add(x, y, name=None): + return tf_frontend.math.add(x, y, name=name) diff --git a/ivy/functional/frontends/tensorflow/compat/v1/nn.py b/ivy/functional/frontends/tensorflow/compat/v1/nn.py index d1cfcd3c5d3d9..c3095a040d0fb 100644 --- a/ivy/functional/frontends/tensorflow/compat/v1/nn.py +++ b/ivy/functional/frontends/tensorflow/compat/v1/nn.py @@ -5,7 +5,7 @@ import ivy.functional.frontends.tensorflow.nn as tf_nn -@with_unsupported_dtypes({"2.14.0 and below": ("float16",)}, "tensorflow") +@with_unsupported_dtypes({"2.15.0 and below": ("float16",)}, "tensorflow") def depthwise_conv2d( input, filter, @@ -30,7 +30,7 @@ def depthwise_conv2d( # should have float16 as well but sqrt doesn't support it @to_ivy_arrays_and_back -@with_supported_dtypes({"2.14.0 and below": ("float32",)}, "tensorflow") +@with_supported_dtypes({"2.15.0 and below": ("float32",)}, "tensorflow") def fused_batch_norm( x, scale, @@ -105,7 +105,7 @@ def fused_batch_norm( @to_ivy_arrays_and_back @with_unsupported_dtypes( - {"2.14.0 and below": ("float16",)}, + {"2.15.0 and below": ("float16",)}, "tensorflow", ) def max_pool(value, ksize, strides, padding, data_format="NHWC", name=None, input=None): @@ -124,7 +124,7 @@ def max_pool(value, ksize, strides, padding, data_format="NHWC", name=None, inpu @with_unsupported_dtypes( { - "2.14.0 and below": ( + "2.15.0 and below": ( "float16", "bfloat16", ) diff --git a/ivy/functional/frontends/tensorflow/func_wrapper.py b/ivy/functional/frontends/tensorflow/func_wrapper.py index 86fa25e0bc2d1..a25c8418885e2 100644 --- a/ivy/functional/frontends/tensorflow/func_wrapper.py +++ b/ivy/functional/frontends/tensorflow/func_wrapper.py @@ -1,6 +1,6 @@ # global import inspect -from typing import Callable, Dict +from typing import Callable, Dict, Optional import functools # local @@ -37,8 +37,7 @@ def _to_ivy_array(x): # update kwargs dictionary keys helper def _update_kwarg_keys(kwargs: Dict, to_update: Dict) -> Dict: - """ - Update the key-word only arguments dictionary. + """Update the key-word only arguments dictionary. Parameters ---------- @@ -100,10 +99,9 @@ def _handle_tf_dtype(*args, dtype=None, **kwargs): def inputs_to_ivy_arrays(fn: Callable) -> Callable: @functools.wraps(fn) def _inputs_to_ivy_arrays_tf(*args, **kwargs): - """ - Convert all `TensorFlow.Tensor` instances in both the positional and keyword - arguments into `ivy.Array` instances, and then call the function with the - updated arguments. + """Convert all `TensorFlow.Tensor` instances in both the positional and + keyword arguments into `ivy.Array` instances, and then call the + function with the updated arguments. Parameters ---------- @@ -139,11 +137,13 @@ def _inputs_to_ivy_arrays_tf(*args, **kwargs): return _inputs_to_ivy_arrays_tf -def map_raw_ops_alias(alias: callable, kwargs_to_update: Dict = None) -> callable: - """ - Map the raw_ops function with its respective frontend alias function, as the - implementations of raw_ops is way similar to that of frontend functions, except that - only arguments are passed as key-word only in raw_ops functions. +def map_raw_ops_alias( + alias: callable, kwargs_to_update: Optional[Dict] = None +) -> callable: + """Map the raw_ops function with its respective frontend alias function, as + the implementations of raw_ops is way similar to that of frontend + functions, except that only arguments are passed as key-word only in + raw_ops functions. Parameters ---------- @@ -197,9 +197,8 @@ def _wraped_fn(**kwargs): def outputs_to_frontend_arrays(fn: Callable) -> Callable: @functools.wraps(fn) def _outputs_to_frontend_arrays_tf(*args, **kwargs): - """ - Call the function, and then convert all `tensorflow.Tensor` instances in the - function return into `ivy.Array` instances. + """Call the function, and then convert all `tensorflow.Tensor` + instances in the function return into `ivy.Array` instances. Parameters ---------- diff --git a/ivy/functional/frontends/tensorflow/general_functions.py b/ivy/functional/frontends/tensorflow/general_functions.py index 01a03cedd3dc6..cc98ef66453e8 100644 --- a/ivy/functional/frontends/tensorflow/general_functions.py +++ b/ivy/functional/frontends/tensorflow/general_functions.py @@ -20,7 +20,7 @@ def _num_to_bit_list(value, num_dims): - return list(map(int, "{:0{size}b}".format(value, size=num_dims)))[::-1] + return list(map(int, f"{value:0{num_dims}b}"))[::-1] # --- Main --- # @@ -62,7 +62,7 @@ def boolean_mask(tensor, mask, axis=None, name=None): return ivy.get_item(tensor, mask) -@with_supported_dtypes({"2.14.0 and below": ("float32",)}, "tensorflow") +@with_supported_dtypes({"2.15.0 and below": ("float32",)}, "tensorflow") @to_ivy_arrays_and_back def clip_by_global_norm(t_list, clip_norm, use_norm=None): if use_norm is not None: @@ -76,7 +76,7 @@ def clip_by_global_norm(t_list, clip_norm, use_norm=None): ], global_norm -@with_supported_dtypes({"2.14.0 and below": ("float", "complex")}, "tensorflow") +@with_supported_dtypes({"2.15.0 and below": ("float", "complex")}, "tensorflow") @to_ivy_arrays_and_back def clip_by_norm(t, clip_norm, axes=None): t, clip_norm = check_tensorflow_casting(t, clip_norm) @@ -86,16 +86,15 @@ def clip_by_norm(t, clip_norm, axes=None): l2sum_safe = ivy.where(pred, l2sum, ivy.ones_like(l2sum)) l2norm = ivy.where(pred, ivy.sqrt(l2sum_safe), l2sum) intermediate = t * clip_norm - assert t.shape == intermediate.shape, "Dimensions %s and %s are not compatible" % ( - t.shape, - intermediate.shape, - ) + assert ( + t.shape == intermediate.shape + ), f"Dimensions {t.shape} and {intermediate.shape} are not compatible" t_clip = intermediate / ivy.maximum(l2norm, clip_norm) return t_clip @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.14.0 and below": ("float16",)}, "tensorflow") +@with_unsupported_dtypes({"2.15.0 and below": ("float16",)}, "tensorflow") def clip_by_value(t, clip_value_min, clip_value_max): ivy.utils.assertions.check_all_or_any_fn( clip_value_min, @@ -170,7 +169,7 @@ def expand_dims(input, axis, name=None): return ivy.expand_dims(input, axis=axis) -@with_unsupported_dtypes({"2.14.0 and below": ("float16", "bfloat16")}, "tensorflow") +@with_unsupported_dtypes({"2.15.0 and below": ("float16", "bfloat16")}, "tensorflow") @handle_tf_dtype @to_ivy_arrays_and_back def eye(num_rows, num_columns=None, batch_shape=None, dtype=ivy.float32, name=None): @@ -213,7 +212,7 @@ def foldl( return result -@with_unsupported_dtypes({"2.5.2 and below": ("float16", "bfloat16")}, "paddle") +@with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") @to_ivy_arrays_and_back def foldr( fn, @@ -255,8 +254,7 @@ def gather(params, indices, validate_indices=None, axis=None, batch_dims=0, name axis = batch_dims else: axis = axis % len(params.shape) - if axis < batch_dims: - axis = batch_dims + axis = max(axis, batch_dims) return ivy.gather(params, indices, axis=axis, batch_dims=batch_dims) @@ -300,7 +298,7 @@ def no_op(name=None): return -@with_supported_dtypes({"2.14.0 and below": ("float32", "float64")}, "tensorflow") +@with_supported_dtypes({"2.15.0 and below": ("float32", "float64")}, "tensorflow") @to_ivy_arrays_and_back def norm(tensor, ord="euclidean", axis=None, keepdims=None, name=None): return tf_frontend.linalg.norm( @@ -322,7 +320,7 @@ def one_hot( return ivy.one_hot(indices, depth) -@with_unsupported_dtypes({"2.14.0 and below": ("float16", "bfloat16")}, "tensorflow") +@with_unsupported_dtypes({"2.15.0 and below": ("float16", "bfloat16")}, "tensorflow") @handle_tf_dtype @to_ivy_arrays_and_back def ones(shape, dtype=ivy.float32, name=None): @@ -341,7 +339,7 @@ def pad(tensor, paddings, mode="CONSTANT", constant_values=0, name=None): return ivy.pad(tensor, paddings, mode=mode.lower(), constant_values=constant_values) -@with_unsupported_dtypes({"2.14.0 and below": ("float16", "bfloat16")}, "tensorflow") +@with_unsupported_dtypes({"2.15.0 and below": ("float16", "bfloat16")}, "tensorflow") @handle_tf_dtype @to_ivy_arrays_and_back def range(start, limit=None, delta=1, dtype=None, name=None): @@ -353,7 +351,7 @@ def rank(input, **kwargs): return ivy.astype(ivy.array(input.ndim), ivy.int32) -@with_unsupported_dtypes({"2.14.0 and below": ("unsigned", "integer")}, "tensorflow") +@with_unsupported_dtypes({"2.15.0 and below": ("unsigned", "integer")}, "tensorflow") @to_ivy_arrays_and_back def realdiv(x, y, name=None): x, y = check_tensorflow_casting(x, y) @@ -410,6 +408,34 @@ def searchsorted(sorted_sequence, values, side="left", out_type="int32"): return ivy.searchsorted(sorted_sequence, values, side=side, ret_dtype=out_type) +@with_supported_dtypes( + {"2.15.0 and below": ("int8", "int16", "int32", "int64")}, "tensorflow" +) +@to_ivy_arrays_and_back +def sequence_mask(lengths, maxlen=None, dtype=ivy.bool, name=None): + if maxlen is None: + maxlen = ivy.maximum( + ivy.max(lengths), ivy.max(ivy.arange(ivy.get_num_dims(lengths))) + ) + maxlen = ivy.maximum(0, maxlen) + else: + maxlen = ivy.array(maxlen) + if ivy.get_num_dims(maxlen) is not None and ivy.get_num_dims(maxlen) != 0: + raise ValueError( + "Argument `maxlen` must be scalar for sequence_mask, " + f"received `maxlen` = {maxlen} " + f"with shape '{maxlen.get_shape()}' instead" + ) + + row_vector = ivy.arange(0, int(maxlen), 1) + matrix = ivy.expand_dims(lengths, axis=-1) + result = row_vector < matrix + if dtype is None: + return result + else: + return ivy.astype(result, dtype) + + @to_ivy_arrays_and_back def shape(input, out_type=ivy.int32, name=None): out_type = to_ivy_dtype(out_type) @@ -456,7 +482,7 @@ def sort(values, axis=-1, direction="ASCENDING", name=None): @with_unsupported_dtypes( - {"2.14.0 and below": ("uint8", "uint16", "uint32", "uint64", "int16")}, "tensorflow" + {"2.15.0 and below": ("uint8", "uint16", "uint32", "uint64", "int16")}, "tensorflow" ) @to_ivy_arrays_and_back def split(value, num_or_size_splits, axis=0, num=None, name=None): @@ -593,7 +619,7 @@ def tensor_scatter_nd_add(tensor, indices, updates, name=None): return ivy.add(tensor, scatter_tensor) -@with_unsupported_dtypes({"2.14.0 and below": ("uint16",)}, "tensorflow") +@with_unsupported_dtypes({"2.15.0 and below": ("uint16",)}, "tensorflow") @to_ivy_arrays_and_back def tile(input, multiples, name=None): return ivy.tile(input, multiples) @@ -609,14 +635,14 @@ def transpose(a, perm=None, conjugate=False, name="transpose"): return ivy.permute_dims(a, axes=perm) -@with_unsupported_dtypes({"2.14.0 and below": ("float16", "bfloat16")}, "tensorflow") +@with_unsupported_dtypes({"2.15.0 and below": ("float16", "bfloat16")}, "tensorflow") @to_ivy_arrays_and_back def truncatediv(x, y, name=None): return x.trunc_divide(y) @with_unsupported_dtypes( - {"2.14.0 and below": ("int16", "int8", "uint8", " uint16")}, "tensorflow" + {"2.15.0 and below": ("int16", "int8", "uint8", " uint16")}, "tensorflow" ) @to_ivy_arrays_and_back def truncatemod(x, y): @@ -677,7 +703,7 @@ def unravel_index(indices, dims, out=None, name=None): return ivy.unravel_index(indices, dims, out=out) -@with_unsupported_dtypes({"2.14.0 and below": ("float16", "bfloat16")}, "tensorflow") +@with_unsupported_dtypes({"2.15.0 and below": ("float16", "bfloat16")}, "tensorflow") @to_ivy_arrays_and_back def unstack(value: ivy.Array, axis=0, num=None, name=None): return ivy.unstack(value, axis=axis) @@ -712,7 +738,7 @@ def zeros(shape, dtype=ivy.float32, name=None): return ivy.zeros(shape=shape, dtype=dtype) -@with_unsupported_dtypes({"2.14.0 and below": ("float16", "bfloat16")}, "tensorflow") +@with_unsupported_dtypes({"2.15.0 and below": ("float16", "bfloat16")}, "tensorflow") @to_ivy_arrays_and_back def zeros_initializer(shape, dtype=None, name=None): # todo internal: fix behaviour diff --git a/ivy/functional/frontends/tensorflow/image/cropping.py b/ivy/functional/frontends/tensorflow/image/cropping.py index a74f637fb91ca..daa01cf49d44f 100644 --- a/ivy/functional/frontends/tensorflow/image/cropping.py +++ b/ivy/functional/frontends/tensorflow/image/cropping.py @@ -7,7 +7,7 @@ from ivy.func_wrapper import with_supported_dtypes -@with_supported_dtypes({"2.14.0 and below": ("float",)}, "tensorflow") +@with_supported_dtypes({"2.15.0 and below": ("float",)}, "tensorflow") @to_ivy_arrays_and_back def extract_patches(images, sizes, strides, rates, padding): depth = images.shape[-1] @@ -46,7 +46,7 @@ def resize( else: new_height, new_width = size if method == "bicubic": - method = "bicubic_tensorflow" + method = "tf_bicubic" elif method == "area": method = "tf_area" image = ivy.interpolate( diff --git a/ivy/functional/frontends/tensorflow/keras/__init__.py b/ivy/functional/frontends/tensorflow/keras/__init__.py index 0d11e115ad78c..052c66a399130 100644 --- a/ivy/functional/frontends/tensorflow/keras/__init__.py +++ b/ivy/functional/frontends/tensorflow/keras/__init__.py @@ -1,4 +1,5 @@ from . import activations +from . import backend from . import layers from . import metrics from . import regularizers diff --git a/ivy/functional/frontends/tensorflow/keras/activations.py b/ivy/functional/frontends/tensorflow/keras/activations.py index 5ee4693e3977f..1bbffa3d5f375 100644 --- a/ivy/functional/frontends/tensorflow/keras/activations.py +++ b/ivy/functional/frontends/tensorflow/keras/activations.py @@ -16,8 +16,23 @@ ] +# --- Helpers --- # +# --------------- # + + +# note: defined to avoid AST call extraction of +# 'tf_frontend.keras.activations.__dict__.items() +# or 'tf_frontend.keras.activations.__dict__.values()' +def _get_tf_keras_activations(): + return tf_frontend.keras.activations.__dict__.items() + + +# --- Main --- # +# ------------ # + + @with_supported_dtypes( - {"2.14.0 and below": ("float16", "float32", "float64")}, + {"2.15.0 and below": ("float16", "float32", "float64")}, "tensorflow", ) def deserialize(name, custom_objects=None): @@ -47,7 +62,7 @@ def deserialize(name, custom_objects=None): @with_supported_dtypes( - {"2.14.0 and below": ("bfloat16", "float16", "float32", "float64")}, + {"2.15.0 and below": ("bfloat16", "float16", "float32", "float64")}, "tensorflow", ) @to_ivy_arrays_and_back @@ -103,7 +118,7 @@ def relu(x, alpha=0.0, max_value=None, threshold=0.0): @with_supported_dtypes( - {"2.14.0 and below": ("float16", "float32", "float64")}, + {"2.15.0 and below": ("float16", "float32", "float64")}, "tensorflow", ) @to_ivy_arrays_and_back @@ -112,7 +127,7 @@ def selu(x): @with_supported_dtypes( - {"2.14.0 and below": ("float16", "float32", "float64")}, + {"2.15.0 and below": ("float16", "float32", "float64")}, "tensorflow", ) def serialize(activation, use_legacy_format=False, custom_objects=None): @@ -132,13 +147,15 @@ def serialize(activation, use_legacy_format=False, custom_objects=None): if custom_func == activation: return name + tf_keras_frontend_activations = _get_tf_keras_activations() + # Check if the function is in the ACTIVATION_FUNCTIONS list if activation.__name__ in ACTIVATION_FUNCTIONS: return activation.__name__ # Check if the function is in the TensorFlow frontend activations - elif activation in tf_frontend.keras.activations.__dict__.values(): - for name, tf_func in tf_frontend.keras.activations.__dict__.items(): + elif activation in [fn for name, fn in tf_keras_frontend_activations]: + for name, tf_func in tf_keras_frontend_activations: if tf_func == activation: return name diff --git a/ivy/functional/frontends/tensorflow/keras/backend.py b/ivy/functional/frontends/tensorflow/keras/backend.py new file mode 100644 index 0000000000000..6c29237ef6b5e --- /dev/null +++ b/ivy/functional/frontends/tensorflow/keras/backend.py @@ -0,0 +1,118 @@ +import functools +import ivy +import ivy.functional.frontends.tensorflow as tf_frontend +from ivy.functional.frontends.tensorflow.func_wrapper import ( + _ivy_array_to_tensorflow, + _to_ivy_array, + to_ivy_arrays_and_back, +) + + +def bias_add(x, bias, data_format=None): + if data_format is None: + data_format = "channels_last" + bias_shape = bias.shape + if len(bias_shape) == 1: + if data_format == "channels_first": + return tf_frontend.nn.bias_add(x, bias, data_format="NC...") + return tf_frontend.nn.bias_add(x, bias, data_format="N...C") + if x.ndim in (3, 4, 5): + if data_format == "channels_first": + bias_reshape_axis = (1, bias_shape[-1]) + bias_shape[:-1] + return x + tf_frontend.reshape(bias, bias_reshape_axis) + return x + tf_frontend.reshape(bias, (1,) + bias_shape) + return tf_frontend.nn.bias_add(x, bias) + + +@to_ivy_arrays_and_back +def depthwise_conv2d( + x, + depthwise_kernel, + strides=(1, 1), + padding="valid", + data_format=None, + dilation_rate=(1, 1), +): + data_format = "channels_last" if data_format is None else data_format + if data_format not in {"channels_first", "channels_last"}: + raise ValueError("Unknown data_format: " + str(data_format)) + + tf_data_format = "NHWC" + permuted_x = False + if data_format == "channels_first": + if ivy.dev(x) == "cpu": + x = tf_frontend.transpose(x, (0, 2, 3, 1)) # NCHW -> NHWC + permuted_x = True + else: + tf_data_format = "NCHW" + + padding = padding.upper() + if padding not in {"VALID", "SAME"}: + raise ValueError("Unknown padding: " + str(padding)) + + if tf_data_format == "NHWC": + strides = (1,) + strides + (1,) + else: + strides = (1, 1) + strides + + x = tf_frontend.nn.depthwise_conv2d( + x, + depthwise_kernel, + strides=strides, + padding=padding, + dilations=dilation_rate, + data_format=tf_data_format, + ) + + if permuted_x: + x = tf_frontend.transpose(x, (0, 3, 1, 2)) # NHWC -> NCHW + return x + + +@to_ivy_arrays_and_back +def dot(x, y): + return ivy.dot(x, y) + + +def mean(x, axis=None, keepdims=False): + return tf_frontend.reduce_mean(x, axis, keepdims) + + +@to_ivy_arrays_and_back +def rnn( + step_function, + inputs, + initial_states, + go_backwards=False, + mask=None, + constants=None, + unroll=False, + input_length=None, + time_major=False, + zero_output_for_mask=False, + return_all_outputs=True, +): + @functools.wraps(step_function) + def _new_step_function(*args, **kwargs): + frontend_args = ivy.nested_map( + _ivy_array_to_tensorflow, args, include_derived=True, shallow=False + ) + frontend_kwargs = ivy.nested_map( + _ivy_array_to_tensorflow, kwargs, include_derived=True, shallow=False + ) + ret = step_function(*frontend_args, **frontend_kwargs) + return ivy.nested_map(_to_ivy_array, ret, include_derived=True) + + return ivy.rnn( + _new_step_function, + inputs, + initial_states, + go_backwards=go_backwards, + mask=mask, + constants=constants, + unroll=unroll, + input_length=input_length, + time_major=time_major, + zero_output_for_mask=zero_output_for_mask, + return_all_outputs=return_all_outputs, + ) diff --git a/ivy/functional/frontends/tensorflow/linalg.py b/ivy/functional/frontends/tensorflow/linalg.py index 6236fa4196cc7..01a8f293f4497 100644 --- a/ivy/functional/frontends/tensorflow/linalg.py +++ b/ivy/functional/frontends/tensorflow/linalg.py @@ -38,7 +38,7 @@ def symmetrize(input): @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.14.0 and below": ("float16", "bfloat16")}, "tensorflow") +@with_unsupported_dtypes({"2.15.0 and below": ("float16", "bfloat16")}, "tensorflow") def cholesky_solve(chol, rhs, name=None): chol, rhs = check_tensorflow_casting(chol, rhs) y = ivy.solve(chol, rhs) @@ -107,7 +107,7 @@ def eigh(tensor, name=None): @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.14.0 and below": ("float32", "float64", "complex64", "complex128")}, + {"2.15.0 and below": ("float32", "float64", "complex64", "complex128")}, "tensorflow", ) def eigvals(tensor, name=None): @@ -130,24 +130,22 @@ def expm(input, name=None): @handle_tf_dtype @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.14.0 and below": ("float16", "bfloat16")}, "tensorflow") +@with_unsupported_dtypes({"2.15.0 and below": ("float16", "bfloat16")}, "tensorflow") def eye(num_rows, num_columns=None, batch_shape=None, dtype=ivy.float32, name=None): return ivy.eye(num_rows, num_columns, batch_shape=batch_shape, dtype=dtype) -@with_supported_dtypes({"2.14.0 and below": ("float32", "float64")}, "tensorflow") +@with_supported_dtypes({"2.15.0 and below": ("float32", "float64")}, "tensorflow") @to_ivy_arrays_and_back def global_norm(t_list, name=None): - l2_norms = [ - ivy.sqrt((ivy.sum(ivy.square(t)))) ** 2 for t in t_list if t is not None - ] + l2_norms = [ivy.sqrt(ivy.sum(ivy.square(t))) ** 2 for t in t_list if t is not None] return ivy.sqrt(ivy.sum(ivy.asarray(l2_norms, dtype=ivy.dtype(l2_norms[0])))) @to_ivy_arrays_and_back @with_supported_dtypes( { - "2.14.0 and below": ( + "2.15.0 and below": ( "float32", "float64", "complex64", @@ -161,7 +159,7 @@ def inv(input, adjoint=False, name=None): @to_ivy_arrays_and_back -@with_supported_dtypes({"2.14.0 and below": ("float32", "float64")}, "tensorflow") +@with_supported_dtypes({"2.15.0 and below": ("float32", "float64")}, "tensorflow") def l2_normalize(x, axis=None, epsilon=1e-12, name=None): square_sum = ivy.sum(ivy.square(x), axis=axis, keepdims=True) x_inv_norm = ivy.reciprocal(ivy.sqrt(ivy.maximum(square_sum, epsilon))) @@ -170,7 +168,7 @@ def l2_normalize(x, axis=None, epsilon=1e-12, name=None): @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.14.0 and below": ("float16", "float32", "float64", "complex64", "complex128")}, + {"2.15.0 and below": ("float16", "float32", "float64", "complex64", "complex128")}, "tensorflow", ) def logdet(matrix, name=None): @@ -187,7 +185,7 @@ def lu_matrix_inverse(lower_upper, perm, validate_args=False, name=None): @to_ivy_arrays_and_back @with_supported_dtypes( { - "2.14.0 and below": ( + "2.15.0 and below": ( "float16", "float32", "float64", @@ -246,7 +244,7 @@ def matrix_transpose(a, name="matrix_transpose", conjugate=False): return ivy.matrix_transpose(a) -@with_supported_dtypes({"2.14.0 and below": ("float32", "float64")}, "tensorflow") +@with_supported_dtypes({"2.15.0 and below": ("float32", "float64")}, "tensorflow") @to_ivy_arrays_and_back def norm(tensor, ord="euclidean", axis=None, keepdims=None, name=None): keepdims = keepdims or False @@ -259,7 +257,7 @@ def norm(tensor, ord="euclidean", axis=None, keepdims=None, name=None): @to_ivy_arrays_and_back -@with_supported_dtypes({"2.14.0 and below": ("float32", "float64")}, "tensorflow") +@with_supported_dtypes({"2.15.0 and below": ("float32", "float64")}, "tensorflow") def normalize(tensor, ord="euclidean", axis=None, name=None): tensor = tf_frontend.convert_to_tensor( tensor, dtype=ivy.dtype(tensor), dtype_hint="Any" @@ -282,7 +280,7 @@ def qr(input, /, *, full_matrices=False, name=None): @to_ivy_arrays_and_back @with_supported_dtypes( { - "2.14.0 and below": ( + "2.15.0 and below": ( "bfloat16", "half", "float32", @@ -352,7 +350,7 @@ def slogdet(input, name=None): @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.14.0 and below": ("float16", "bfloat16")}, "tensorflow") +@with_unsupported_dtypes({"2.15.0 and below": ("float16", "bfloat16")}, "tensorflow") def solve(matrix, rhs, /, *, adjoint=False, name=None): matrix, rhs = check_tensorflow_casting(matrix, rhs) return ivy.solve(matrix, rhs, adjoint=adjoint) @@ -366,7 +364,7 @@ def svd(a, /, *, full_matrices=False, compute_uv=True, name=None): @to_ivy_arrays_and_back @with_supported_dtypes( { - "2.14.0 and below": ( + "2.15.0 and below": ( "bfloat16", "half", "float32", @@ -390,7 +388,7 @@ def tensor_diag(diagonal, /, *, name=None): @to_ivy_arrays_and_back @with_supported_dtypes( { - "2.14.0 and below": ( + "2.15.0 and below": ( "float32", "float64", "int32", @@ -426,7 +424,7 @@ def tensor_diag_part(input, name=None): @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.14.0 and below": ("float32", "float64", "int32")}, "tensorflow" + {"2.15.0 and below": ("float32", "float64", "int32")}, "tensorflow" ) def tensordot(a, b, axes, name=None): a, b = check_tensorflow_casting(a, b) @@ -438,7 +436,7 @@ def tensordot(a, b, axes, name=None): @to_ivy_arrays_and_back @with_unsupported_dtypes( { - "2.14.0 and below": ( + "2.15.0 and below": ( "float16", "bfloat16", "int8", @@ -460,3 +458,54 @@ def tensorsolve(a, b, axes): @to_ivy_arrays_and_back def trace(x, name=None): return ivy.trace(x, axis1=-2, axis2=-1) + + +@to_ivy_arrays_and_back +@with_supported_dtypes( + { + "2.13.0 and below": ( + "float32", + "float64", + "complex64", + "complex128", + ) + }, + "tensorflow", +) +def tridiagonal_solve( + diagonals, + rhs, + diagonals_format="compact", + transpose_rhs=False, + conjugate_rhs=False, + name=None, + partial_pivoting=True, + perturb_singular=False, +): + if transpose_rhs is True: + rhs_copy = ivy.matrix_transpose(rhs) + if conjugate_rhs is True: + rhs_copy = ivy.conj(rhs) + if not transpose_rhs and not conjugate_rhs: + rhs_copy = ivy.array(rhs) + + if diagonals_format == "matrix": + return ivy.solve(diagonals, rhs_copy) + elif diagonals_format in ["sequence", "compact"]: + diagonals = ivy.array(diagonals) + dim = diagonals[0].shape[0] + diagonals[[0, -1], [-1, 0]] = 0 + dummy_idx = [0, 0] + indices = ivy.array( + [ + [(i, i + 1) for i in range(dim - 1)] + [dummy_idx], + [(i, i) for i in range(dim)], + [dummy_idx] + [(i + 1, i) for i in range(dim - 1)], + ] + ) + constructed_matrix = ivy.scatter_nd( + indices, diagonals, shape=ivy.array([dim, dim]) + ) + return ivy.solve(constructed_matrix, rhs_copy) + else: + raise ValueError("Unexpected diagonals_format") diff --git a/ivy/functional/frontends/tensorflow/math.py b/ivy/functional/frontends/tensorflow/math.py index 5b7bc5d406626..3a0118409774f 100644 --- a/ivy/functional/frontends/tensorflow/math.py +++ b/ivy/functional/frontends/tensorflow/math.py @@ -13,11 +13,143 @@ ) +# --- Helpers --- # +# --------------- # + + +def _chbevl(x, coef, N): + """Evaluates the series. + + N-1 + - ' + y = > coef[i] T (x/2) + - i + i=0 + + of Chebyshev polynomials Ti at argument x/2. + + Coefficients are stored in reverse order, i.e. the zero + order term is last in the array. Note N is the number of + coefficients, not the order. + + If coefficients are for the interval a to b, x must + have been transformed to x -> 2(2x - b - a)/(b-a) before + entering the routine. This maps x from (a, b) to (-1, 1), + over which the Chebyshev polynomials are defined. + + If the coefficients are for the inverted interval, in + which (a, b) is mapped to (1/b, 1/a), the transformation + required is x -> 2(2ab/x - b - a)/(b-a). If b is infinity, + this becomes x -> 4a/x - 1. + """ + b0 = coef[0:1] + b1 = ivy.zeros_like(x) + i = N - 1 + p = 1 + + while i > 0: + b2 = b1 + b1 = b0 + with ivy.PreciseMode(True): + b0 = x * b1 - b2 + coef[p : p + 1] + p += 1 + i -= 1 + + return 0.5 * (b0 - b2) + + +def _get_chebyshev_coefficients_for_exp_i1(): + """Chebyshev coefficients for exp(-x) I1(x) / x in the interval [0,8]. + + lim(x->0){ exp(-x) I1(x) / x } = 1/2. + + Returns list of 29 float elements + ------- + """ + return ivy.array( + [ + 2.77791411276104639959e-18, + -2.11142121435816608115e-17, + 1.55363195773620046921e-16, + -1.10559694773538630805e-15, + 7.60068429473540693410e-15, + -5.04218550472791168711e-14, + 3.22379336594557470981e-13, + -1.98397439776494371520e-12, + 1.17361862988909016308e-11, + -6.66348972350202774223e-11, + 3.62559028155211703701e-10, + -1.88724975172282928790e-9, + 9.38153738649577178388e-9, + -4.44505912879632808065e-8, + 2.00329475355213526229e-7, + -8.56872026469545474066e-7, + 3.47025130813767847674e-6, + -1.32731636560394358279e-5, + 4.78156510755005422638e-5, + -1.61760815825896745588e-4, + 5.12285956168575772895e-4, + -1.51357245063125314899e-3, + 4.15642294431288815669e-3, + -1.05640848946261981558e-2, + 2.47264490306265168283e-2, + -5.29459812080949914269e-2, + 1.02643658689847095384e-1, + -1.76416518357834055153e-1, + 2.52587186443633654823e-1, + ] + ) + + +def _get_chebyshev_coefficients_for_exp_sqrt_i1(): + """Chebyshev coefficients for exp(-x) sqrt(x) I1(x) in the inverted + interval [8,infinity]. + + lim(x->inf){ exp(-x) sqrt(x) I1(x) } = 1/sqrt(2pi). + + Returns a list of 25 elements containing float + ------- + """ + return ivy.array( + [ + 7.51729631084210481353e-18, + 4.41434832307170791151e-18, + -4.65030536848935832153e-17, + -3.20952592199342395980e-17, + 2.96262899764595013876e-16, + 3.30820231092092828324e-16, + -1.88035477551078244854e-15, + -3.81440307243700780478e-15, + 1.04202769841288027642e-14, + 4.27244001671195135429e-14, + -2.10154184277266431302e-14, + -4.08355111109219731823e-13, + -7.19855177624590851209e-13, + 2.03562854414708950722e-12, + 1.41258074366137813316e-11, + 3.25260358301548823856e-11, + -1.89749581235054123450e-11, + -5.58974346219658380687e-10, + -3.83538038596423702205e-9, + -2.63146884688951950684e-8, + -2.51223623787020892529e-7, + -3.88256480887769039346e-6, + -1.10588938762623716291e-4, + -9.76109749136146840777e-3, + 7.78576235018280120474e-1, + ] + ) + + +# --- Main --- # +# ------------ # + + @with_unsupported_dtypes( { "1.2.0": ("float16", "complex64", "complex128"), "1.8.0 and below": ("float16",), - "2.14.0 and below": ("int8", "int16", "uint8", "uint16", "uint32", "uint64"), + "2.15.0 and below": ("int8", "int16", "uint8", "uint16", "uint32", "uint64"), }, "tensorflow", ) @@ -61,15 +193,23 @@ def angle(input, name=None): return ivy.angle(input) +@with_unsupported_dtypes( + {"2.15.0 and below": ("complex",)}, + "tensorflow", +) @to_ivy_arrays_and_back def argmax(input, axis, output_type=None, name=None): output_type = to_ivy_dtype(output_type) - if output_type in ["uint16", "int16", "int32", "int64"]: + if output_type in ["int32", "int64"]: return ivy.astype(ivy.argmax(input, axis=axis), output_type) else: return ivy.astype(ivy.argmax(input, axis=axis), "int64") +@with_unsupported_dtypes( + {"2.15.0 and below": ("complex",)}, + "tensorflow", +) @to_ivy_arrays_and_back def argmin(input, axis=None, output_type="int64", name=None): output_type = to_ivy_dtype(output_type) @@ -105,7 +245,42 @@ def atanh(x, name="atanh"): @with_supported_dtypes( - {"2.14.0 and below": ("int32",)}, + {"2.15.0 and below": ("float16", "float32", "float64")}, "tensorflow" +) +@to_ivy_arrays_and_back +def bessel_i1(x, name=None): + z = ivy.abs(x) + result = ivy.zeros_like(z) + + mask1 = z <= 8.0 + + if ivy.any(mask1) > 0: + y = (z[mask1] / ivy.array([2.0])) - ivy.array([2.0]) + result[mask1] = ( + _chbevl(y, _get_chebyshev_coefficients_for_exp_i1(), 29) + * z[mask1] + * ivy.exp(z[mask1]) + ) + + mask2 = ~mask1 + if ivy.any(mask2) > 0: + result[mask2] = ( + ivy.exp(z[mask2]) + * _chbevl( + ivy.array([32.0]) / z[mask2] - ivy.array([2.0]), + _get_chebyshev_coefficients_for_exp_sqrt_i1(), + 25, + ) + / ivy.sqrt(z[mask2]) + ) + + result[x < 0.0] = -result[x < 0.0] + + return result + + +@with_supported_dtypes( + {"2.15.0 and below": ("int32",)}, "tensorflow", ) @to_ivy_arrays_and_back @@ -297,7 +472,7 @@ def greater_equal(x, y, name=None): @with_supported_device_and_dtypes( { - "2.14.0 and below": { + "2.15.0 and below": { "cpu": ("float32", "float64"), "gpu": ("bfloat16", "float16", "float32", "float64"), } @@ -310,7 +485,7 @@ def igamma(a, x, name=None): @with_supported_dtypes( - {"2.14.0 and below": ("float16", "float32", "float64", "complex64", "complex128")}, + {"2.15.0 and below": ("float16", "float32", "float64", "complex64", "complex128")}, "tensorflow", ) @to_ivy_arrays_and_back @@ -326,7 +501,7 @@ def in_top_k(target, pred, k, name=None): @with_supported_dtypes( { - "2.14.0 and below": ("int32", "int64"), + "2.15.0 and below": ("int32", "int64"), }, "tensorflow", ) @@ -337,7 +512,7 @@ def invert_permutation(x, name=None): @with_supported_dtypes( { - "2.14.0 and below": ("bfloat16", "half", "float32", "float64"), + "2.15.0 and below": ("bfloat16", "half", "float32", "float64"), }, "tensorflow", ) @@ -369,13 +544,15 @@ def is_non_decreasing(x, name="is_non_decreasing"): def is_strictly_increasing(x, name="is_strictly_increasing"): if ivy.array(x).size < 2: return ivy.array(True) - if ivy.array(x).size == 2: - return ivy.array(x[0] < x[1]) - return ivy.all(ivy.less(x, ivy.roll(x, -1))) + x = ivy.flatten(x) + res = ivy.less(x, ivy.roll(x, -1)) + if res.size >= 2: + res[res.size - 1] = True # The last comparison must be set to true. + return ivy.all(res) @to_ivy_arrays_and_back -@with_supported_dtypes({"2.14.0 and below": ("float32", "float64")}, "tensorflow") +@with_supported_dtypes({"2.15.0 and below": ("float32", "float64")}, "tensorflow") def l2_normalize(x, axis=None, epsilon=1e-12, name=None): square_sum = ivy.sum(ivy.square(x), axis=axis, keepdims=True) x_inv_norm = ivy.reciprocal(ivy.sqrt(ivy.maximum(square_sum, epsilon))) @@ -396,7 +573,7 @@ def less_equal(x, y, name="LessEqual"): # lgamma @to_ivy_arrays_and_back -@with_supported_dtypes({"2.14.0 and below": ("float32", "float64")}, "tensorflow") +@with_supported_dtypes({"2.15.0 and below": ("float32", "float64")}, "tensorflow") def lgamma(x, name=None): return ivy.lgamma(x) @@ -444,17 +621,19 @@ def logical_xor(x, y, name="LogicalXor"): @to_ivy_arrays_and_back +@with_unsupported_dtypes({"2.15.0 and below": ("complex",)}, "tensorflow") def maximum(x, y, name=None): return ivy.maximum(x, y) @to_ivy_arrays_and_back +@with_unsupported_dtypes({"2.15.0 and below": ("complex",)}, "tensorflow") def minimum(x, y, name=None): return ivy.minimum(x, y) @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.5.1 and below": ("bfloat16",)}, "paddle") +@with_unsupported_dtypes({"2.6.0 and below": ("bfloat16",)}, "paddle") def mod(x, y, name=None): x, y = check_tensorflow_casting(x, y) return ivy.remainder(x, y) @@ -609,7 +788,7 @@ def reduce_variance(input_tensor, axis=None, keepdims=False, name="reduce_varian @with_supported_device_and_dtypes( { - "2.14.0 and below": { + "2.15.0 and below": { "cpu": ("float32", "float64"), "gpu": ("bfloat16", "float16", "float32", "float64"), } @@ -637,6 +816,25 @@ def scalar_mul(scalar, x, name="scalar_mul"): return ivy.multiply(x, scalar).astype(x.dtype) +@with_unsupported_dtypes( + {"2.15.0 and below": ("float16", "bool", "int16", "int8")}, + "tensorflow", +) +@to_ivy_arrays_and_back +def segment_sum(data, segment_ids, name="segment_sum"): + data = ivy.array(data) + segment_ids = ivy.array(segment_ids) + ivy.utils.assertions.check_equal( + list(segment_ids.shape), [list(data.shape)[0]], as_array=False + ) + sum_array = ivy.zeros( + tuple([int(segment_ids[-1] + 1)] + (list(data.shape))[1:]), dtype=data.dtype + ) + for i in range((segment_ids).shape[0]): + sum_array[segment_ids[i]] = sum_array[segment_ids[i]] + data[i] + return sum_array + + @to_ivy_arrays_and_back def sigmoid(x, name=None): return ivy.sigmoid(x) @@ -644,7 +842,7 @@ def sigmoid(x, name=None): @with_supported_dtypes( { - "2.14.0 and below": ( + "2.15.0 and below": ( "bfloat16", "float16", "float32", @@ -676,7 +874,7 @@ def softplus(features, name=None): @with_supported_dtypes( - {"2.14.0 and below": ("bfloat32", "float32", "float64")}, "tensorflow" + {"2.15.0 and below": ("bfloat32", "float32", "float64")}, "tensorflow" ) @to_ivy_arrays_and_back def softsign(features, name=None): @@ -695,7 +893,7 @@ def square(x, name=None): @with_supported_dtypes( { - "2.14.0 and below": ( + "2.15.0 and below": ( "bfloat16", "float16", "float32", @@ -730,7 +928,7 @@ def tan(x, name=None): @with_supported_dtypes( - {"2.14.0 and below": ("float16", "float32", "float64", "complex64", "complex128")}, + {"2.15.0 and below": ("float16", "float32", "float64", "complex64", "complex128")}, "tensorflow", ) @to_ivy_arrays_and_back @@ -820,7 +1018,7 @@ def unsorted_segment_sum(data, segment_ids, num_segments, name="unsorted_segment @with_supported_dtypes( - {"2.14.0 and below": ("float32", "float64", "complex64", "complex128")}, + {"2.15.0 and below": ("float32", "float64", "complex64", "complex128")}, "tensorflow", ) @to_ivy_arrays_and_back @@ -832,7 +1030,7 @@ def xdivy(x, y, name=None): @to_ivy_arrays_and_back -@with_supported_dtypes({"2.14.0 and below": ("float32", "float64")}, "tensorflow") +@with_supported_dtypes({"2.15.0 and below": ("float32", "float64")}, "tensorflow") def xlog1py(x, y, name=None): x, y = check_tensorflow_casting(x, y) return x * ivy.log1p(y) @@ -845,17 +1043,17 @@ def xlogy(x, y, name=None): @to_ivy_arrays_and_back def zero_fraction(value, name="zero_fraction"): - zero = ivy.zeros(tuple(list(value.shape)), dtype=ivy.float32) + zero = ivy.zeros(tuple(value.shape), dtype=ivy.float32) x = ivy.array(value, dtype=ivy.float32) - count_zero = ivy.sum(ivy.equal(x, zero)) - count_nonzero = ivy.sum(ivy.not_equal(x, zero)) + count_zero = ivy.sum(ivy.equal(x, zero), dtype=ivy.float32) + count_nonzero = ivy.sum(ivy.not_equal(x, zero), dtype=ivy.float32) return ivy.divide(count_zero, ivy.add(count_zero, count_nonzero)) @to_ivy_arrays_and_back @with_supported_dtypes( { - "2.14.0 and below": ("float32", "float64"), + "2.15.0 and below": ("float32", "float64"), }, "tensorflow", ) diff --git a/ivy/functional/frontends/tensorflow/nn.py b/ivy/functional/frontends/tensorflow/nn.py index 1402aa0ec7f21..ca340335899a3 100644 --- a/ivy/functional/frontends/tensorflow/nn.py +++ b/ivy/functional/frontends/tensorflow/nn.py @@ -42,6 +42,15 @@ def _convolution_broadcast_helper( return [1] + arg + [1] +def _reduce_padding(padding, data_format): + if not isinstance(padding, str): + if data_format[1] == "C": + padding = padding[2:] + else: + padding = padding[1:-1] + return padding + + def _reduce_strides_dilations(dim, stride, dilations): if not isinstance(stride, int): if len(stride) > dim: @@ -91,7 +100,9 @@ def avg_pool1d(input, ksize, strides, padding, data_format="NWC", name=None): # avg_pool2d @to_ivy_arrays_and_back def avg_pool2d(input, ksize, strides, padding, data_format="NHWC", name=None): - return ivy.avg_pool2d(input, ksize, strides, padding, data_format=data_format) + return ivy.avg_pool2d( + input, ksize, strides, padding, data_format=data_format + ).astype(input.dtype) # avg_pool3d @@ -118,8 +129,8 @@ def bias_add(value, bias, data_format=None, name=None): if data_format is None: data_format = "N...C" - chanel_index = data_format.find("C") - if chanel_index != 1: + channel_index = data_format.find("C") + if channel_index != 1: return ivy.add(value, bias) else: value = ivy.swapaxes(value, 1, -1) @@ -151,7 +162,6 @@ def conv1d_transpose( ): dilations = 1 if dilations is None else dilations strides, dilations = _reduce_strides_dilations(1, strides, dilations) - filters = filters.swapaxes(-2, -1) return ivy.conv1d_transpose( input, filters, @@ -169,6 +179,7 @@ def conv2d( ): dilations = 1 if dilations is None else dilations strides, dilations = _reduce_strides_dilations(2, strides, dilations) + padding = _reduce_padding(padding, data_format) return ivy.conv2d( input, filters, strides, padding, data_format=data_format, dilations=dilations ) @@ -187,7 +198,7 @@ def conv2d_transpose( ): dilations = 1 if dilations is None else dilations strides, dilations = _reduce_strides_dilations(2, strides, dilations) - filters = filters.swapaxes(-2, -1) + padding = _reduce_padding(padding, data_format) return ivy.conv2d_transpose( input, filters, @@ -210,7 +221,7 @@ def conv3d( ) -@with_unsupported_dtypes({"2.14.0 and below": ("bfloat16",)}, "tensorflow") +@with_unsupported_dtypes({"2.15.0 and below": ("bfloat16",)}, "tensorflow") @to_ivy_arrays_and_back def conv3d_transpose( input, @@ -224,7 +235,6 @@ def conv3d_transpose( ): dilations = 1 if dilations is None else dilations strides, dilations = _reduce_strides_dilations(3, strides, dilations) - filters = filters.swapaxes(-2, -1) return ivy.conv3d_transpose( input, filters, @@ -292,7 +302,7 @@ def ctc_unique_labels(labels, name=None): return unique_pad, ctc_labels[2] -@with_unsupported_dtypes({"2.14.0 and below": ("bfloat16",)}, "tensorflow") +@with_unsupported_dtypes({"2.15.0 and below": ("bfloat16",)}, "tensorflow") @to_ivy_arrays_and_back def depthwise_conv2d( input, @@ -322,7 +332,7 @@ def depthwise_conv2d( @to_ivy_arrays_and_back def dropout(x, rate, noise_shape=None, seed=None, name=None): - return ivy.dropout(x, rate, noise_shape=noise_shape, seed=seed) + return ivy.dropout(x, rate, noise_shape=noise_shape, training=True, seed=seed) @with_unsupported_dtypes({"2.11.1 and below": ("complex",)}, "tensorflow") @@ -336,37 +346,22 @@ def gelu(features, approximate=False, name=None): return ivy.gelu(features, approximate=approximate) -@with_unsupported_dtypes({"2.14.0 and below": "float16"}, "tensorflow") +@with_unsupported_dtypes({"2.15.0 and below": "float16"}, "tensorflow") @to_ivy_arrays_and_back def leaky_relu(features, alpha=0.2, name=None): return ivy.leaky_relu(features, alpha=alpha) -@with_unsupported_dtypes({"2.14.0 and below": ("bfloat16",)}, "tensorflow") +@with_supported_dtypes({"2.15.0 and below": ("float32", "float16")}, "tensorflow") @to_ivy_arrays_and_back def local_response_normalization( input, depth_radius=5, bias=1.0, alpha=1.0, beta=0.5, name=None ): - input_shape = ivy.shape(input) - depth = input_shape[-1] - ivy.utils.assertions.check_equal( - ivy.get_num_dims(input), - 4, - message="4D input, but got input with sizes " + str(input_shape), - as_array=False, + return ivy.local_response_norm( + input, 2 * depth_radius + 1, bias=bias, alpha=alpha, beta=beta ) - sqr_sum = ivy.empty(input_shape[:-1] + (0,), dtype=ivy.dtype(input)) - for d in range(depth): - start = max(0, d - depth_radius) - end = min(d + depth_radius + 1, depth) - inter_channel_sum = ivy.sum( - input[:, :, :, start:end] ** 2, axis=3, keepdims=True - ) - sqr_sum = ivy.concat([sqr_sum, inter_channel_sum], axis=-1) - return ivy.divide(input, ivy.pow(ivy.add(sqr_sum * alpha, bias), beta)) -# log_poisson_loss @to_ivy_arrays_and_back def log_poisson_loss(targets, log_input, compute_full_loss=False, name=None): return ivy.log_poisson_loss(targets, log_input, compute_full_loss=compute_full_loss) @@ -382,7 +377,7 @@ def max_pool2d(input, ksize, strides, padding, data_format="NHWC", name=None): return ivy.max_pool2d(input, ksize, strides, padding, data_format=data_format) -@with_supported_dtypes({"2.14.0 and below": ("float32",)}, "tensorflow") +@with_supported_dtypes({"2.15.0 and below": ("float32",)}, "tensorflow") @to_ivy_arrays_and_back def max_pool3d(input, ksize, strides, padding, data_format="NDHWC", name=None): return ivy.max_pool3d(input, ksize, strides, padding, data_format=data_format) @@ -397,7 +392,7 @@ def moments(x, axes, shift=None, keepdims=False, name=None): @with_unsupported_dtypes( { - "2.14.0 and below": ( + "2.15.0 and below": ( "int8", "int16", "int32", @@ -446,19 +441,19 @@ def pool( ) -@with_unsupported_dtypes({"2.14.0 and below": ("complex",)}, "tensorflow") +@with_unsupported_dtypes({"2.15.0 and below": ("complex",)}, "tensorflow") @to_ivy_arrays_and_back def relu(features, name=None): return ivy.relu(features) -@with_unsupported_dtypes({"2.14.0 and below": ("complex",)}, "tensorflow") +@with_unsupported_dtypes({"2.15.0 and below": ("complex",)}, "tensorflow") @to_ivy_arrays_and_back def relu6(features, name=None): return ivy.relu6(features) -@with_unsupported_dtypes({"2.14.0 and below": ("bfloat16",)}, "tensorflow") +@with_unsupported_dtypes({"2.15.0 and below": ("bfloat16",)}, "tensorflow") @to_ivy_arrays_and_back def separable_conv2d( input, @@ -485,7 +480,7 @@ def separable_conv2d( @with_unsupported_dtypes( { - "2.14.0 and below": ( + "2.15.0 and below": ( "int8", "int16", "int32", @@ -512,7 +507,7 @@ def silu(features, beta: float = 1.0): return ivy.multiply(features, ivy.sigmoid(ivy.multiply(beta, features))) -@with_unsupported_dtypes({"2.14.0 and below": ("float16",)}, "tensorflow") +@with_unsupported_dtypes({"2.15.0 and below": ("float16",)}, "tensorflow") @to_ivy_arrays_and_back def softmax(logits, axis=None, name=None): return ivy.softmax(logits, axis=axis) @@ -521,7 +516,7 @@ def softmax(logits, axis=None, name=None): # Softsign @with_unsupported_dtypes( { - "2.14.0 and below": ( + "2.15.0 and below": ( "int8", "int16", "int32", @@ -572,7 +567,7 @@ def sufficient_statistics(x, axes, shift=None, keepdims=False, name=None): @with_unsupported_dtypes( { - "2.14.0 and below": ( + "2.15.0 and below": ( "int8", "int16", "int32", @@ -640,3 +635,6 @@ def weighted_moments(x, axes, frequency_weights, keepdims=False, name=None): weighted_mean = ivy.squeeze(weighted_mean, axis=axes) weighted_variance = ivy.squeeze(weighted_variance, axis=axes) return weighted_mean, weighted_variance + + +swish = silu diff --git a/ivy/functional/frontends/tensorflow/python/__init__.py b/ivy/functional/frontends/tensorflow/python/__init__.py new file mode 100644 index 0000000000000..010d264b5a0d6 --- /dev/null +++ b/ivy/functional/frontends/tensorflow/python/__init__.py @@ -0,0 +1 @@ +from . import ops diff --git a/ivy/functional/frontends/tensorflow/python/ops/__init__.py b/ivy/functional/frontends/tensorflow/python/ops/__init__.py new file mode 100644 index 0000000000000..f0c2bd56a0634 --- /dev/null +++ b/ivy/functional/frontends/tensorflow/python/ops/__init__.py @@ -0,0 +1 @@ +from . import resource_variable_ops diff --git a/ivy/functional/frontends/tensorflow/python/ops/resource_variable_ops.py b/ivy/functional/frontends/tensorflow/python/ops/resource_variable_ops.py new file mode 100644 index 0000000000000..03ce4f5103d3f --- /dev/null +++ b/ivy/functional/frontends/tensorflow/python/ops/resource_variable_ops.py @@ -0,0 +1,17 @@ +# local +import ivy.functional.frontends.tensorflow as tf_frontend + + +class ResourceVariable(tf_frontend.Variable): + def __repr__(self): + return ( + repr(self._ivy_array).replace( + "ivy.array", + "ivy.functional.frontends.tensorflow.python.ops.resource_variable_ops.ResourceVariable", + )[:-1] + + ", shape=" + + str(self._ivy_array.shape) + + ", dtype=" + + str(self._ivy_array.dtype) + + ")" + ) diff --git a/ivy/functional/frontends/tensorflow/ragged/ragged.py b/ivy/functional/frontends/tensorflow/ragged/ragged.py index ac0e210ec328f..44835ff245a0b 100644 --- a/ivy/functional/frontends/tensorflow/ragged/ragged.py +++ b/ivy/functional/frontends/tensorflow/ragged/ragged.py @@ -25,12 +25,12 @@ def from_row_splits(cls, values, row_splits, name=None, validate=True): if values.shape[0] != row_splits[-1] or row_splits[0] != 0: if values.shape[0] != row_splits[-1]: - ivy.utils.exceptions.IvyException( + raise ivy.utils.exceptions.IvyException( "first dimension of shape of values should be equal to the" " last dimension of row_splits" ) else: - ivy.utils.exceptions.IvyException( + raise ivy.utils.exceptions.IvyException( "first value of row_splits should be equal to zero." ) data = [ @@ -49,7 +49,7 @@ def from_row_lengths( ): # TODO : modify this, if necessary, to accept raggedTensor inputs too if sum(row_lengths) != values.shape[0]: - ivy.utils.exceptions.IvyException( + raise ivy.utils.exceptions.IvyException( "first dimension of values should be equal to sum(row_lengths) " ) data = [] diff --git a/ivy/functional/frontends/tensorflow/random.py b/ivy/functional/frontends/tensorflow/random.py index 85b0dc873ec53..8ff688b630b8e 100644 --- a/ivy/functional/frontends/tensorflow/random.py +++ b/ivy/functional/frontends/tensorflow/random.py @@ -12,7 +12,7 @@ def gamma(shape, alpha, beta=None, dtype=ivy.float32, seed=None, name=None): @with_unsupported_dtypes( - {"2.14.0 and below": ("int8", "int16", "int32", "int64", "unsigned")}, "tensorflow" + {"2.15.0 and below": ("int8", "int16", "int32", "int64", "unsigned")}, "tensorflow" ) @to_ivy_arrays_and_back def normal(shape, mean=0.0, stddev=1.0, dtype=ivy.float32, seed=None, name=None): @@ -20,7 +20,7 @@ def normal(shape, mean=0.0, stddev=1.0, dtype=ivy.float32, seed=None, name=None) @with_unsupported_dtypes( - {"2.14.0 and below": ("int8", "int16", "unsigned")}, "tensorflow" + {"2.15.0 and below": ("int8", "int16", "unsigned")}, "tensorflow" ) @to_ivy_arrays_and_back @handle_tf_dtype @@ -34,7 +34,7 @@ def poisson(shape, lam, dtype=ivy.float32, seed=None, name=None): # implement random shuffle @with_unsupported_dtypes( - {"2.14.0 and below": ("int8", "int16", "in32", "int64", "unsigned")}, "tensorflow" + {"2.15.0 and below": ("int8", "int16", "in32", "int64", "unsigned")}, "tensorflow" ) @to_ivy_arrays_and_back def shuffle(value, seed=None, name=None): @@ -42,7 +42,7 @@ def shuffle(value, seed=None, name=None): @with_unsupported_dtypes( - {"2.14.0 and below": ("int8", "int16", "unsigned")}, "tensorflow" + {"2.15.0 and below": ("int8", "int16", "unsigned")}, "tensorflow" ) @to_ivy_arrays_and_back def stateless_normal( @@ -54,7 +54,7 @@ def stateless_normal( @with_unsupported_dtypes( - {"2.14.0 and below": ("int8", "int16", "unsigned")}, "tensorflow" + {"2.15.0 and below": ("int8", "int16", "unsigned")}, "tensorflow" ) @to_ivy_arrays_and_back def stateless_poisson(shape, seed, lam, dtype=ivy.int32, name=None): @@ -71,7 +71,7 @@ def stateless_uniform( @with_unsupported_dtypes( - {"2.14.0 and below": ("int8", "int16", "unsigned")}, "tensorflow" + {"2.15.0 and below": ("int8", "int16", "unsigned")}, "tensorflow" ) @to_ivy_arrays_and_back def uniform(shape, minval=0, maxval=None, dtype=ivy.float32, seed=None, name=None): diff --git a/ivy/functional/frontends/tensorflow/raw_ops.py b/ivy/functional/frontends/tensorflow/raw_ops.py index 311fafa4c203a..61c87dcb5c76b 100644 --- a/ivy/functional/frontends/tensorflow/raw_ops.py +++ b/ivy/functional/frontends/tensorflow/raw_ops.py @@ -14,11 +14,12 @@ Acos = to_ivy_arrays_and_back(map_raw_ops_alias(tf_frontend.math.acos)) Acosh = to_ivy_arrays_and_back(map_raw_ops_alias(tf_frontend.math.acosh)) +Add = to_ivy_arrays_and_back(map_raw_ops_alias(tf_frontend.math.add)) AddN = to_ivy_arrays_and_back(map_raw_ops_alias(tf_frontend.math.add_n)) AddV2 = to_ivy_arrays_and_back(map_raw_ops_alias(tf_frontend.math.add)) ArgMax = to_ivy_arrays_and_back( with_unsupported_dtypes( - {"2.14.0 and below": ("complex",)}, + {"2.15.0 and below": ("complex",)}, "tensorflow", )( map_raw_ops_alias( @@ -28,7 +29,7 @@ ) ArgMin = to_ivy_arrays_and_back( with_unsupported_dtypes( - {"2.14.0 and below": ("complex",)}, + {"2.15.0 and below": ("complex",)}, "tensorflow", )( map_raw_ops_alias( @@ -40,7 +41,7 @@ Atan = to_ivy_arrays_and_back(map_raw_ops_alias(tf_frontend.math.atan)) Atan2 = to_ivy_arrays_and_back( with_unsupported_dtypes( - {"2.14.0 and below": "float16"}, + {"2.15.0 and below": "float16"}, "tensorflow", )(map_raw_ops_alias(tf_frontend.math.atan2)) ) @@ -69,7 +70,7 @@ Einsum = to_ivy_arrays_and_back( with_supported_dtypes( { - "2.14.0 and below": ( + "2.15.0 and below": ( "bfloat16", "complex128 ", "complex64", @@ -92,7 +93,7 @@ Igamma = to_ivy_arrays_and_back( with_supported_dtypes( { - "2.14.0 and below": ( + "2.15.0 and below": ( "float64", "float32", "half", @@ -104,7 +105,7 @@ LeakyRelu = to_ivy_arrays_and_back( with_supported_dtypes( { - "2.14.0 and below": ("bfloat16", "float16", "float32", "float64"), + "2.15.0 and below": ("bfloat16", "float16", "float32", "float64"), }, "tensorflow", )( @@ -116,7 +117,7 @@ LessEqual = to_ivy_arrays_and_back( with_unsupported_dtypes( { - "2.14.0 and below": ("complex",), + "2.15.0 and below": ("complex",), }, "tensorflow", )(map_raw_ops_alias(tf_frontend.math.less_equal)) @@ -125,7 +126,7 @@ LogSoftmax = to_ivy_arrays_and_back( with_supported_dtypes( { - "2.14.0 and below": ( + "2.15.0 and below": ( "bfloat16", "float32", "float64", @@ -139,7 +140,7 @@ Max = to_ivy_arrays_and_back( with_unsupported_dtypes( { - "2.14.0 and below": ("complex",), + "2.15.0 and below": ("complex",), }, "tensorflow", )( @@ -155,7 +156,7 @@ MaxPool3D = to_ivy_arrays_and_back( with_supported_dtypes( { - "2.14.0 and below": ("float32",), + "2.15.0 and below": ("float32",), }, "tensorflow", )( @@ -167,7 +168,7 @@ Maximum = to_ivy_arrays_and_back( with_unsupported_dtypes( { - "2.14.0 and below": ("complex",), + "2.15.0 and below": ("complex",), }, "tensorflow", )(map_raw_ops_alias(tf_frontend.math.maximum)) @@ -184,7 +185,7 @@ Min = to_ivy_arrays_and_back( with_unsupported_dtypes( { - "2.14.0 and below": ("complex",), + "2.15.0 and below": ("complex",), }, "tensorflow", )( @@ -204,7 +205,7 @@ RealDiv = to_ivy_arrays_and_back( with_supported_dtypes( { - "2.14.0 and below": ( + "2.15.0 and below": ( "complex", "bfloat16", "float16", @@ -219,7 +220,7 @@ Relu = to_ivy_arrays_and_back( with_unsupported_dtypes( { - "2.14.0 and below": ("complex", "float16"), + "2.15.0 and below": ("complex", "float16"), }, "tensorflow", )(map_raw_ops_alias(tf_frontend.nn.relu)) @@ -227,7 +228,7 @@ Relu6 = to_ivy_arrays_and_back( with_unsupported_dtypes( { - "2.14.0 and below": ("complex", "float16"), + "2.15.0 and below": ("complex", "float16"), }, "tensorflow", )( @@ -248,10 +249,11 @@ ) Sin = to_ivy_arrays_and_back(map_raw_ops_alias(tf_frontend.math.sin)) Size = to_ivy_arrays_and_back(map_raw_ops_alias(tf_frontend.general_functions.size)) +Slice = to_ivy_arrays_and_back(map_raw_ops_alias(tf_frontend.slice)) Softmax = to_ivy_arrays_and_back( with_unsupported_dtypes( { - "2.14.0 and below": ("float16",), + "2.15.0 and below": ("float16",), }, "tensorflow", )(map_raw_ops_alias(tf_frontend.nn.softmax)) @@ -264,7 +266,7 @@ SquaredDifference = to_ivy_arrays_and_back( with_supported_dtypes( { - "2.14.0 and below": ( + "2.15.0 and below": ( "complex", "bfloat16", "float16", @@ -280,6 +282,7 @@ Squeeze = to_ivy_arrays_and_back( map_raw_ops_alias(tf_frontend.general_functions.squeeze) ) +Sub = to_ivy_arrays_and_back(map_raw_ops_alias(tf_frontend.math.subtract)) Tan = to_ivy_arrays_and_back(map_raw_ops_alias(tf_frontend.math.tan)) Tanh = to_ivy_arrays_and_back(map_raw_ops_alias(tf_frontend.math.tanh)) Tile = to_ivy_arrays_and_back(map_raw_ops_alias(tf_frontend.general_functions.tile)) @@ -287,7 +290,7 @@ Zeta = to_ivy_arrays_and_back( with_supported_dtypes( { - "2.14.0 and below": ("float32", "float64"), + "2.15.0 and below": ("float32", "float64"), }, "tensorflow", )(map_raw_ops_alias(tf_frontend.math.zeta)) @@ -342,7 +345,7 @@ def Angle( @with_unsupported_dtypes( { - "2.14.0 and below": ( + "2.15.0 and below": ( "float16", "bool", "bfloat16", @@ -526,7 +529,7 @@ def Diag(*, diagonal, name="Diag"): @with_supported_dtypes( - {"2.14.0 and below": ("bfloat16", "float16", "float32", "float64")}, + {"2.15.0 and below": ("bfloat16", "float16", "float32", "float64")}, "tensorflow", ) @to_ivy_arrays_and_back @@ -616,6 +619,15 @@ def Gather(*, params, indices, validate_indices=None, name="Gather"): return ivy.gather(params, indices, axis=0, batch_dims=0) +@with_supported_dtypes( + {"2.15.0 and below": ("int32", "int64", "float32", "float64")}, + "tensorflow", +) +@to_ivy_arrays_and_back +def GatherNd(*, params, indices, name=None): + return ivy.gather_nd(params, indices, batch_dims=0) + + @to_ivy_arrays_and_back def Greater(*, x, y, name="Greater"): x, y = check_tensorflow_casting(x, y) @@ -775,7 +787,7 @@ def Shape(*, input, output_type=ivy.int32, name="Shape"): @with_unsupported_dtypes( - {"2.14.0 and below": ("unsigned",)}, + {"2.15.0 and below": ("unsigned",)}, "tensorflow", ) @to_ivy_arrays_and_back @@ -820,7 +832,7 @@ def Sum(*, input, axis, keep_dims=False, name="Sum"): @with_supported_dtypes( - {"2.14.0 and below": ("float64", "float128", "halfcomplex64", "complex128")}, + {"2.15.0 and below": ("float64", "float128", "halfcomplex64", "complex128")}, "tensorflow", ) @to_ivy_arrays_and_back @@ -844,12 +856,45 @@ def TruncateDiv(*, x, y, name="TruncateDiv"): return ivy.astype(ivy.trunc_divide(x, y), x.dtype) -@with_unsupported_dtypes({"2.14.0 and below": ("float16", "bfloat16")}, "tensorflow") +@with_unsupported_dtypes({"2.15.0 and below": ("float16", "bfloat16")}, "tensorflow") @to_ivy_arrays_and_back def Unpack(*, value, num, axis=0, name="Unpack"): return ivy.unstack(value, axis=axis)[:num] +@with_supported_dtypes( + { + "2.15.0 and below": ( + "int8", + "int16", + "int32", + "int64", + "float32", + "float64", + "complex64", + "complex128", + ) + }, + "tensorflow", +) +@to_ivy_arrays_and_back +def UnsortedSegmentProd(*, data, segment_ids, num_segments, name=None): + data = ivy.array(data) + segment_ids = ivy.array(segment_ids) + + ivy.utils.assertions.check_equal( + list(segment_ids.shape), [list(data.shape)[0]], as_array=False + ) + ivy.utils.assertions.check_greater(int(num_segments), int(ivy.max(segment_ids))) + + shape = list(ivy.shape(data)) + shape[0] = int(num_segments) + x = ivy.ones(shape, dtype=data.dtype) + for i in range((segment_ids).shape[0]): + x[segment_ids[i]] = ivy.multiply(x[segment_ids[i]], data[i]) + return x + + @to_ivy_arrays_and_back def Xdivy(*, x, y, name="Xdivy"): if (x == 0).all(): @@ -857,7 +902,7 @@ def Xdivy(*, x, y, name="Xdivy"): return ivy.divide(x, y) -@with_unsupported_dtypes({"2.14.0 and below": ("bfloat16",)}, "tensorflow") +@with_unsupported_dtypes({"2.15.0 and below": ("bfloat16",)}, "tensorflow") @to_ivy_arrays_and_back def Xlog1py(*, x, y, name="Xlog1py"): if (x == 0).all(): @@ -868,8 +913,3 @@ def Xlog1py(*, x, y, name="Xlog1py"): @to_ivy_arrays_and_back def ZerosLike(*, x, name="ZerosLike"): return ivy.zeros_like(x) - - -Add = to_ivy_arrays_and_back(map_raw_ops_alias(tf_frontend.math.add)) -Slice = to_ivy_arrays_and_back(map_raw_ops_alias(tf_frontend.slice)) -Sub = to_ivy_arrays_and_back(map_raw_ops_alias(tf_frontend.math.subtract)) diff --git a/ivy/functional/frontends/tensorflow/signal.py b/ivy/functional/frontends/tensorflow/signal.py index 0daf1db8a70c3..b0d3374327ad5 100644 --- a/ivy/functional/frontends/tensorflow/signal.py +++ b/ivy/functional/frontends/tensorflow/signal.py @@ -29,7 +29,7 @@ def kaiser_bessel_derived_window( @with_supported_dtypes( - {"2.14.0 and below": ("float32", "float64", "float16", "bfloat16")}, + {"2.15.0 and below": ("float32", "float64", "float16", "bfloat16")}, "tensorflow", ) @handle_tf_dtype @@ -62,7 +62,7 @@ def stft( @with_supported_dtypes( - {"2.14.0 and below": ("float16", "float32", "float64", "bfloat16")}, + {"2.15.0 and below": ("float16", "float32", "float64", "bfloat16")}, "tensorflow", ) @to_ivy_arrays_and_back diff --git a/ivy/functional/frontends/tensorflow/tensor.py b/ivy/functional/frontends/tensorflow/tensor.py index a34096cbbd050..b9b9745af3ae3 100644 --- a/ivy/functional/frontends/tensorflow/tensor.py +++ b/ivy/functional/frontends/tensorflow/tensor.py @@ -10,9 +10,7 @@ class EagerTensor: def __init__(self, array): - self._ivy_array = ( - ivy.array(array) if not isinstance(array, ivy.Array) else array - ) + self._ivy_array = array if isinstance(array, ivy.Array) else ivy.array(array) def __repr__(self): return ( @@ -45,7 +43,7 @@ def dtype(self): @property def shape(self): - return tuple(self.ivy_array.shape.shape) + return TensorShape(self.ivy_array.shape.shape) # Instance Methods # # ---------------- # @@ -108,7 +106,7 @@ def __floordiv__(self, y, name="floordiv"): return tf_frontend.raw_ops.FloorDiv(x=self, y=y, name=name) @with_unsupported_dtypes( - {"2.14.0 and below": ("complex",)}, + {"2.15.0 and below": ("complex",)}, "tensorflow", ) def __ge__(self, y, name="ge"): @@ -120,7 +118,7 @@ def __getitem__(self, slice_spec, var=None, name="getitem"): return EagerTensor(ret) @with_unsupported_dtypes( - {"2.14.0 and below": ("complex",)}, + {"2.15.0 and below": ("complex",)}, "tensorflow", ) def __gt__(self, y, name="gt"): @@ -130,14 +128,14 @@ def __invert__(self, name="invert"): return tf_frontend.raw_ops.Invert(x=self, name=name) @with_unsupported_dtypes( - {"2.14.0 and below": ("complex",)}, + {"2.15.0 and below": ("complex",)}, "tensorflow", ) def __le__(self, y, name="le"): return tf_frontend.raw_ops.LessEqual(x=self, y=y, name=name) @with_unsupported_dtypes( - {"2.14.0 and below": ("complex",)}, + {"2.15.0 and below": ("complex",)}, "tensorflow", ) def __lt__(self, y, name="lt"): @@ -150,7 +148,7 @@ def __mul__(self, y, name="mul"): return tf_frontend.math.multiply(self, y, name=name) @with_unsupported_dtypes( - {"2.14.0 and below": ("complex",)}, + {"2.15.0 and below": ("complex",)}, "tensorflow", ) def __mod__(self, y, name="mod"): @@ -228,6 +226,114 @@ def __iter__(self): yield self[i] +class TensorShape: + # TODO: there are still some methods that may need implementing + + def __init__(self, dims): + self._dims = tuple(dims) + + def __repr__(self): + if self._dims is not None: + return f"TensorShape({list(self._dims)})" + else: + return "TensorShape(None)" + + def __str__(self): + if self.rank is None: + return "" + elif self.rank == 1: + return f"({self._dims[0]},)" + else: + return f'({", ".join(str(d) for d in self._dims)})' + + # Properties # + # ---------- # + + @property + def dims(self): + return self._dims + + @property + def ivy_shape(self): + return ivy.Shape(self._dims) + + @property + def ndims(self): + return self.__len__() + + @property + def rank(self): + return self.__len__() + + # Instance Methods # + # ---------------- # + + def __add__(self, other): + return self.concatenate(other) + + def __bool__(self): + return self._dims is not None + + def __concat__(self, other): + return self.concatenate(other) + + def __eq__(self, other): + return self._dims == other.dims + + def __getitem__(self, key): + if isinstance(key, slice): + return TensorShape(self._dims[key]) + else: + return self._dims[key] + + def __iter__(self): + return iter(d for d in self._dims) + + def __len__(self): + return len(self._dims) + + def __nonzero__(self): + return self.__bool__() + + def __radd__(self, other): + return other.concatenate(self) + + def as_list(self): + return list(self._dims) + + def concatenate(self, other): + other = as_shape(other) + if self.dims is None or other.dims is None: + return unknown_shape() + else: + return TensorShape(self.dims + other.dims) + + def num_elements(self): + return ivy.to_scalar(ivy.prod(self._dims)) + + # Dummy Tensor class to help with compilation, don't add methods here class Tensor(EagerTensor): pass + + +# Helpers + + +def as_shape(shape): + """Converts the given object to a TensorShape.""" + if isinstance(shape, TensorShape): + return shape + else: + return TensorShape(shape) + + +def unknown_shape(rank=None, **kwargs): + if rank is None and "ndims" in kwargs: + rank = kwargs.pop("ndims") + if kwargs: + raise TypeError(f"Unknown argument: {kwargs}") + if rank is None: + return TensorShape(None) + else: + return TensorShape([None] * rank) diff --git a/ivy/functional/frontends/tensorflow/variable.py b/ivy/functional/frontends/tensorflow/variable.py index 7c75a71815528..77f0053f6bf08 100644 --- a/ivy/functional/frontends/tensorflow/variable.py +++ b/ivy/functional/frontends/tensorflow/variable.py @@ -53,27 +53,30 @@ def shape(self): def assign(self, value, use_locking=None, name=None, read_value=True): ivy.utils.assertions.check_equal( - value.shape if hasattr(value, "ivy_array") else ivy.shape(value), + value.ivy_array.shape if hasattr(value, "ivy_array") else ivy.shape(value), self.shape, as_array=False, ) self._ivy_array = value._ivy_array + return self def assign_add(self, delta, use_locking=None, name=None, read_value=True): ivy.utils.assertions.check_equal( - delta.shape if hasattr(delta, "ivy_array") else ivy.shape(delta), + delta.ivy_array.shape if hasattr(delta, "ivy_array") else ivy.shape(delta), self.shape, as_array=False, ) - self._ivy_array = tf_frontend.math.add(self._ivy_array, delta._ivy_array) + self._ivy_array = ivy.add(self._ivy_array, delta._ivy_array) + return self def assign_sub(self, delta, use_locking=None, name=None, read_value=True): ivy.utils.assertions.check_equal( - delta.shape if hasattr(delta, "ivy_array") else ivy.shape(delta), + delta.ivy_array.shape if hasattr(delta, "ivy_array") else ivy.shape(delta), self.shape, as_array=False, ) - self._ivy_array = tf_frontend.math.subtract(self._ivy_array, delta._ivy_array) + self._ivy_array = ivy.subtract(self._ivy_array, delta._ivy_array) + return self def batch_scatter_update( self, sparse_delta, use_locking=None, name=None, read_value=True @@ -188,7 +191,7 @@ def __mul__(self, x, name="mul"): return tf_frontend.math.multiply(x, self._ivy_array, name=name) def __mod__(self, x, name="mod"): - return ivy.remainder(x, self._ivy_array, name=name) + return tf_frontend.math.mod(x, self._ivy_array, name=name) def __ne__(self, other): return tf_frontend.raw_ops.NotEqual( @@ -277,12 +280,14 @@ def indices(self): @property def dense_shape(self): - """A 1-D `Tensor` containing the shape of the corresponding dense tensor.""" + """A 1-D `Tensor` containing the shape of the corresponding dense + tensor.""" return self._dense_shape @property def device(self): - """The name of the device on which `values` will be produced, or `None`.""" + """The name of the device on which `values` will be produced, or + `None`.""" return self.values.device @property @@ -295,7 +300,7 @@ def __repr__(self): self._indices, self._values, ( - ", dense_shape=%s" % (self._dense_shape,) + f", dense_shape={self._dense_shape}" if self._dense_shape is not None else "" ), diff --git a/ivy/functional/frontends/torch/__init__.py b/ivy/functional/frontends/torch/__init__.py index f2a0bb1260a2f..c2d3e94b8bc01 100644 --- a/ivy/functional/frontends/torch/__init__.py +++ b/ivy/functional/frontends/torch/__init__.py @@ -191,8 +191,8 @@ def promote_types_torch( type2: Union[ivy.Dtype, ivy.NativeDtype], /, ) -> ivy.Dtype: - """ - Promote the datatypes type1 and type2, returning the data type they promote to. + """Promote the datatypes type1 and type2, returning the data type they + promote to. Parameters ---------- @@ -210,8 +210,10 @@ def promote_types_torch( ret = torch_frontend.torch_promotion_table[ (ivy.as_ivy_dtype(type1), ivy.as_ivy_dtype(type2)) ] - except KeyError: - raise ivy.utils.exceptions.IvyException("these dtypes are not type promotable") + except KeyError as e: + raise ivy.utils.exceptions.IvyException( + "these dtypes are not type promotable" + ) from e return ret @@ -221,9 +223,8 @@ def promote_types_of_torch_inputs( x2: Union[ivy.Array, Number, Iterable[Number]], /, ) -> Tuple[ivy.Array, ivy.Array]: - """ - Promote the dtype of the given native array inputs to a common dtype based on type - promotion rules. + """Promote the dtype of the given native array inputs to a common dtype + based on type promotion rules. While passing float or integer values or any other non-array input to this function, it should be noted that the return will be an @@ -231,36 +232,36 @@ def promote_types_of_torch_inputs( used as inputs only for those functions that expect an array-like or tensor-like objects, otherwise it might give unexpected results. """ - # Ignore type of 0-dim arrays to mimic torch - x1_copy = x1 - x2_copy = x2 - x1 = ivy.asarray(x1) - x2 = ivy.asarray(x2) - if x1.shape == () and ivy.isscalar(x1_copy): - if ivy.is_int_dtype(x1): - x1 = ivy.astype(x1, "int64") - if x2.shape == () and ivy.isscalar(x2_copy): - if ivy.is_int_dtype(x2): - x2 = ivy.astype(x2, "int64") + if ivy.isscalar(x1) and ivy.is_int_dtype(x1): + x1 = ivy.asarray(x1, dtype="int64") + elif ivy.isscalar(x1): + x1 = ivy.asarray(x1) + if ivy.isscalar(x2) and ivy.is_int_dtype(x2): + x2 = ivy.asarray(x2, dtype="int64") + elif ivy.isscalar(x2): + x2 = ivy.asarray(x2) type1 = ivy.default_dtype(item=x1).strip("u123456789") type2 = ivy.default_dtype(item=x2).strip("u123456789") - if not x1.shape == () and x2.shape == () and type1 == type2: + if x1.shape != () and x2.shape == () and type1 == type2: x2 = ivy.asarray( x2, dtype=x1.dtype, device=ivy.default_device(item=x1, as_native=False) ) - elif x1.shape == () and not x2.shape == () and type1 == type2: + elif x1.shape == () and x2.shape != () and type1 == type2: x1 = ivy.asarray( x1, dtype=x2.dtype, device=ivy.default_device(item=x2, as_native=False) ) elif x1.dtype != x2.dtype: promoted = promote_types_torch(x1.dtype, x2.dtype) - x1 = ivy.asarray(x1, dtype=promoted) - x2 = ivy.asarray(x2, dtype=promoted) + if x1.dtype != promoted: + x1 = x1.astype(promoted) + if x2.dtype != promoted: + x2 = x2.astype(promoted) return x1, x2 from . import nn -from .nn.functional import softmax, relu, lstm +from .nn.functional import softmax, relu, lstm, max_pool2d, dropout +from . import special from . import tensor from .tensor import * from . import blas_and_lapack_ops diff --git a/ivy/functional/frontends/torch/blas_and_lapack_ops.py b/ivy/functional/frontends/torch/blas_and_lapack_ops.py index d25125a87de83..a1c8cd9bbe77b 100644 --- a/ivy/functional/frontends/torch/blas_and_lapack_ops.py +++ b/ivy/functional/frontends/torch/blas_and_lapack_ops.py @@ -201,7 +201,7 @@ def svd(input, some=True, compute_uv=True, *, out=None): return ret -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") @to_ivy_arrays_and_back def trapezoid(y, x=None, *, dx=None, dim=-1): if x is not None: diff --git a/ivy/functional/frontends/torch/comparison_ops.py b/ivy/functional/frontends/torch/comparison_ops.py index e4bb1e4b2382c..051b0cfffd35a 100644 --- a/ivy/functional/frontends/torch/comparison_ops.py +++ b/ivy/functional/frontends/torch/comparison_ops.py @@ -59,6 +59,7 @@ def allclose(input, other, rtol=1e-05, atol=1e-08, equal_nan=False): return ivy.all(ret) +@with_unsupported_dtypes({"2.2 and below": ("complex",)}, "torch") @to_ivy_arrays_and_back def argsort(input, dim=-1, descending=False): return ivy.argsort(input, axis=dim, descending=descending) @@ -73,7 +74,7 @@ def eq(input, other, *, out=None): @to_ivy_arrays_and_back def equal(input, other): input, other = torch_frontend.promote_types_of_torch_inputs(input, other) - return ivy.all_equal(input, other) + return ivy.all(ivy.equal(input, other)) @to_ivy_arrays_and_back @@ -98,12 +99,14 @@ def fmin(input, other, *, out=None): ) +@with_unsupported_dtypes({"2.2 and below": ("complex64", "complex128")}, "torch") @to_ivy_arrays_and_back def greater(input, other, *, out=None): input, other = torch_frontend.promote_types_of_torch_inputs(input, other) return ivy.greater(input, other, out=out) +@with_unsupported_dtypes({"2.2 and below": ("complex64", "complex128")}, "torch") @to_ivy_arrays_and_back def greater_equal(input, other, *, out=None): input, other = torch_frontend.promote_types_of_torch_inputs(input, other) @@ -140,7 +143,9 @@ def isfinite(input): return ivy.isfinite(input) -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes( + {"2.2 and below": ("float16", "bfloat16", "complex", "bool")}, "torch" +) @to_ivy_arrays_and_back def isin(elements, test_elements, *, assume_unique=False, invert=False): input_elements_copy = ivy.reshape(ivy.to_ivy(elements), (-1,)) @@ -194,6 +199,7 @@ def isnan(input): return ivy.isnan(input) +@with_unsupported_dtypes({"2.2 and below": ("complex",)}, "torch") @to_ivy_arrays_and_back def isneginf(input, *, out=None): is_inf = ivy.isinf(input) @@ -201,6 +207,7 @@ def isneginf(input, *, out=None): return ivy.logical_and(is_inf, neg_sign_bit, out=out) +@with_unsupported_dtypes({"2.2 and below": ("complex",)}, "torch") @to_ivy_arrays_and_back def isposinf(input, *, out=None): is_inf = ivy.isinf(input) @@ -208,14 +215,14 @@ def isposinf(input, *, out=None): return ivy.logical_and(is_inf, pos_sign_bit, out=out) -@with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "torch") @to_ivy_arrays_and_back def isreal(input): return ivy.isreal(input) @with_unsupported_dtypes( - {"2.1.0 and below": ("bfloat16", "float16", "bool", "complex")}, "torch" + {"2.2 and below": ("bfloat16", "float16", "bool", "complex")}, "torch" ) @to_ivy_arrays_and_back def kthvalue(input, k, dim=-1, keepdim=False, *, out=None): @@ -239,42 +246,48 @@ def kthvalue(input, k, dim=-1, keepdim=False, *, out=None): return ret +@with_unsupported_dtypes({"2.2 and below": ("complex64", "complex128")}, "torch") @to_ivy_arrays_and_back def less(input, other, *, out=None): input, other = torch_frontend.promote_types_of_torch_inputs(input, other) return ivy.less(input, other, out=out) +@with_unsupported_dtypes({"2.2 and below": ("complex64", "complex128")}, "torch") @to_ivy_arrays_and_back def less_equal(input, other, *, out=None): input, other = torch_frontend.promote_types_of_torch_inputs(input, other) return ivy.less_equal(input, other, out=out) +@with_unsupported_dtypes({"2.2 and below": ("complex64", "complex128")}, "torch") @to_ivy_arrays_and_back def maximum(input, other, *, out=None): input, other = torch_frontend.promote_types_of_torch_inputs(input, other) return ivy.maximum(input, other, out=out) +@with_unsupported_dtypes({"2.2 and below": ("complex64", "complex128")}, "torch") @to_ivy_arrays_and_back def minimum(input, other, *, out=None): input, other = torch_frontend.promote_types_of_torch_inputs(input, other) return ivy.minimum(input, other, out=out) +@with_unsupported_dtypes({"2.2 and below": ("complex",)}, "torch") @to_ivy_arrays_and_back def msort(input, *, out=None): return ivy.sort(input, axis=0, out=out) -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") @to_ivy_arrays_and_back def not_equal(input, other, *, out=None): input, other = torch_frontend.promote_types_of_torch_inputs(input, other) return ivy.not_equal(input, other, out=out) +@with_unsupported_dtypes({"2.2 and below": ("complex",)}, "torch") @to_ivy_arrays_and_back # TODO: the original torch.sort places * right before `out` def sort(input, *, dim=-1, descending=False, stable=False, out=None): @@ -283,7 +296,7 @@ def sort(input, *, dim=-1, descending=False, stable=False, out=None): return namedtuple("sort", ["values", "indices"])(values, indices) -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "complex")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "complex")}, "torch") @to_ivy_arrays_and_back def topk(input, k, dim=None, largest=True, sorted=True, *, out=None): if dim is None: @@ -291,8 +304,8 @@ def topk(input, k, dim=None, largest=True, sorted=True, *, out=None): return ivy.top_k(input, k, axis=dim, largest=largest, sorted=sorted, out=out) -gt = greater ge = greater_equal +gt = greater le = less_equal lt = less ne = not_equal diff --git a/ivy/functional/frontends/torch/creation_ops.py b/ivy/functional/frontends/torch/creation_ops.py index 30132ec31bad8..f30eb6f324541 100644 --- a/ivy/functional/frontends/torch/creation_ops.py +++ b/ivy/functional/frontends/torch/creation_ops.py @@ -12,7 +12,7 @@ @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def arange( start=0, end=None, @@ -74,7 +74,7 @@ def asarray( return ivy.asarray(obj, copy=copy, dtype=dtype, device=device) -@with_supported_dtypes({"2.1.0 and below": ("float32", "float64")}, "torch") +@with_supported_dtypes({"2.2 and below": ("float32", "float64")}, "torch") @to_ivy_arrays_and_back def complex( real, @@ -82,7 +82,7 @@ def complex( *, out=None, ): - assert real.dtype == imag.dtype, ValueError( + assert real.dtype == imag.dtype, TypeError( "Expected real and imag to have the same dtype, " f" but got real.dtype = {real.dtype} and imag.dtype = {imag.dtype}." ) @@ -107,7 +107,13 @@ def empty( if args and size: raise TypeError("empty() got multiple values for argument 'shape'") if size is None: - size = args[0] if isinstance(args[0], (tuple, list, ivy.Shape)) else args + size = ( + args[0] + if isinstance(args[0], (tuple, list, ivy.Shape, ivy.NativeShape)) + else args + ) + if isinstance(size, (tuple, list)): + size = tuple(s.to_scalar() if ivy.is_array(s) else s for s in size) return ivy.empty(shape=size, dtype=dtype, device=device, out=out) @@ -172,6 +178,7 @@ def frombuffer( return ivy.frombuffer(buffer, dtype=dtype, count=count, offset=offset) +@with_unsupported_dtypes({"2.2.0 and below": ("bfloat16",)}, "torch") @to_ivy_arrays_and_back def full( size, @@ -208,7 +215,7 @@ def heaviside(input, values, *, out=None): @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def linspace( start, end, @@ -220,12 +227,12 @@ def linspace( layout=None, requires_grad=False, ): - ret = ivy.linspace(start, end, num=steps, dtype=dtype, device=device, out=out) - return ret + dtype = torch_frontend.get_default_dtype() if dtype is None else dtype + return ivy.linspace(start, end, num=steps, dtype=dtype, device=device, out=out) @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def logspace( start, end, @@ -250,7 +257,11 @@ def ones(*args, size=None, out=None, dtype=None, device=None, requires_grad=Fals if args and size: raise TypeError("ones() got multiple values for argument 'shape'") if size is None: - size = args[0] if isinstance(args[0], (tuple, list, ivy.Shape)) else args + size = ( + args[0] + if isinstance(args[0], (tuple, list, ivy.Shape, ivy.NativeShape)) + else args + ) return ivy.ones(shape=size, dtype=dtype, device=device, out=out) @@ -273,7 +284,7 @@ def ones_like_v_0p4p0_and_above( return ret -@with_supported_dtypes({"2.1.0 and below": ("float32", "float64")}, "torch") +@with_supported_dtypes({"2.2 and below": ("float32", "float64")}, "torch") @to_ivy_arrays_and_back def polar( abs, @@ -285,7 +296,7 @@ def polar( @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def range( *args, dtype=None, @@ -342,7 +353,11 @@ def zeros(*args, size=None, out=None, dtype=None, device=None, requires_grad=Fal if args and size: raise TypeError("zeros() got multiple values for argument 'shape'") if size is None: - size = args[0] if isinstance(args[0], (tuple, list, ivy.Shape)) else args + size = ( + args[0] + if isinstance(args[0], (tuple, list, ivy.Shape, ivy.NativeShape)) + else args + ) return ivy.zeros(shape=size, dtype=dtype, device=device, out=out) diff --git a/ivy/functional/frontends/torch/func_wrapper.py b/ivy/functional/frontends/torch/func_wrapper.py index a9ba80dbff517..c7df1998d4faa 100644 --- a/ivy/functional/frontends/torch/func_wrapper.py +++ b/ivy/functional/frontends/torch/func_wrapper.py @@ -29,65 +29,59 @@ def __eq__(self, __value: object) -> bool: return self.__name__ == __value def __call__(self, grads): - for i in range(self.__self__.ndim): - grads = grads.sum(-1) self.__self__._grads = grads return None class GradFn: - def __init__(self, fn, inputs) -> None: + def __init__(self, fn, args, kwargs) -> None: self._inputs = [] self._fns = [] self.next_functions = [] - assert len(inputs) <= 2 - if len(inputs) == 1 and isinstance(inputs[0], torch_frontend.Tensor): - self._inputs.append(inputs[0].detach()) - - def d_fn(x): - return fn(x) - - self._fns.append(to_ivy_arrays_and_back(ivy.jac(d_fn))) - if inputs[0].grad_fn is not None: - self.next_functions.append(inputs[0].grad_fn) - elif inputs[0].requires_grad and inputs[0].is_leaf: - acc_grad = AccumulateGrad() - acc_grad.__self__ = inputs[0] - self.next_functions.append(acc_grad) - elif len(inputs) == 2: - if isinstance(inputs[0], torch_frontend.Tensor): - self._inputs.append(inputs[0].detach()) - - def d_fn(x): - return fn(x, inputs[1]) - - self._fns.append(to_ivy_arrays_and_back(ivy.jac(d_fn))) - if inputs[0].grad_fn is not None: - self.next_functions.append(inputs[0].grad_fn) - elif inputs[0].requires_grad and inputs[0].is_leaf: + for idx, input in [*enumerate(args), *kwargs.items()]: + if isinstance(input, torch_frontend.Tensor) and input.requires_grad: + self._inputs.append(input.detach()) + + def wrap_fn(idx): + def d_fn(x): + if idx in kwargs: + return fn( + *args, + **{ + key: value + for key, value in kwargs.items() + if key != idx + }, + idx=x, + ) + return fn(*args[:idx], x, *args[idx + 1 :], **kwargs) + + return d_fn + + self._fns.append(to_ivy_arrays_and_back(ivy.jac(wrap_fn(idx)))) + if input.grad_fn is not None: + self.next_functions.append(input.grad_fn) + elif input.is_leaf: acc_grad = AccumulateGrad() - acc_grad.__self__ = inputs[0] - self.next_functions.append(acc_grad) - if isinstance(inputs[1], torch_frontend.Tensor): - self._inputs.append(inputs[1].detach()) - - def d_fn(x): - return fn(inputs[0], x) - - self._fns.append(to_ivy_arrays_and_back(ivy.jac(d_fn))) - if inputs[1].grad_fn is not None: - self.next_functions.append(inputs[1].grad_fn) - elif inputs[1].requires_grad and inputs[1].is_leaf: - acc_grad = AccumulateGrad() - acc_grad.__self__ = inputs[1] + acc_grad.__self__ = input self.next_functions.append(acc_grad) self.__name__ = fn.__name__.capitalize() + "Backward" def __call__(self, prev_grads): - return [ - jac_fn(input_tensor) * prev_grads - for input_tensor, jac_fn in zip(self._inputs, self._fns) - ] + result = [] + for input_tensor, jac_fn in zip(self._inputs, self._fns): + jacobian = jac_fn(input_tensor) + dims = list(range(jacobian.dim())) + permuted_dims = dims[input_tensor.dim() :] + dims[: input_tensor.dim()] + result.append( + ( + jacobian.permute(dims=permuted_dims).reshape( + shape=(*input_tensor.shape, -1) + ) + * prev_grads.ravel() + ).sum(-1) + ) + return result def __repr__(self): return self.__name__ @@ -137,8 +131,7 @@ def _to_ivy_array(x): def inputs_to_ivy_arrays(fn: Callable) -> Callable: @functools.wraps(fn) def _inputs_to_ivy_arrays_torch(*args, **kwargs): - """ - Convert `Tensor` into `ivy.Array` instances. + """Convert `Tensor` into `ivy.Array` instances. Convert all `Tensor` instances in both the positional and keyword arguments into `ivy.Array` instances, and then call the function with the updated @@ -175,8 +168,7 @@ def wrapper(*args, **kwargs): def outputs_to_frontend_arrays(fn: Callable) -> Callable: @functools.wraps(fn) def outputs_to_frontend_arrays_torch(*args, **kwargs): - """ - Convert `ivy.Array` into `Tensor` instances. + """Convert `ivy.Array` into `Tensor` instances. Call the function, and then convert all `ivy.Array` instances returned by the function into `Tensor` instances. @@ -186,7 +178,7 @@ def outputs_to_frontend_arrays_torch(*args, **kwargs): # once frontend specific backend setting is added set_default_dtype = False if not ("dtype" in kwargs and ivy.exists(kwargs["dtype"])) and all( - [not (ivy.is_array(i) or hasattr(i, "ivy_array")) for i in args] + not (ivy.is_array(i) or hasattr(i, "ivy_array")) for i in args ): if ivy.current_backend_str() == "jax": import jax @@ -209,10 +201,8 @@ def outputs_to_frontend_arrays_torch(*args, **kwargs): requires_grad=kwargs.get( "requires_grad", any( - [ - isinstance(i, torch_frontend.Tensor) and i.requires_grad - for i in args - ] + isinstance(i, torch_frontend.Tensor) and i.requires_grad + for i in args ), ), ) @@ -239,21 +229,20 @@ def array_fn(x): if fn.__name__ in dir(torch_frontend.creation_ops): ret.is_leaf = True elif all( - [ - not isinstance(i, torch_frontend.Tensor) - or (not i.requires_grad and not i.grad_fn) - for i in args - ] + not isinstance(i, torch_frontend.Tensor) + or (not i.requires_grad and not i.grad_fn) + for i in args ): ret.is_leaf = True else: ret.is_leaf = False # set grad_fn if any( - [isinstance(i, torch_frontend.Tensor) and i.requires_grad for i in args] + isinstance(i, torch_frontend.Tensor) and i.requires_grad + for i in [*args, *kwargs.values()] ): # ToDo: Implement for unbind - grad_fn = GradFn(fn, args) + grad_fn = GradFn(fn, args, kwargs) grad_fn.__self__ = ret ret.grad_fn = grad_fn @@ -276,8 +265,7 @@ def outputs_to_native_arrays_torch(*args, **kwargs): def to_ivy_arrays_and_back(fn: Callable) -> Callable: - """ - Wrap `fn` so it receives and returns `ivy.Array` instances. + """Wrap `fn` so it receives and returns `ivy.Array` instances. Wrap `fn` so that input arrays are all converted to `ivy.Array` instances and return arrays are all converted to `Tensor` instances. @@ -286,8 +274,7 @@ def to_ivy_arrays_and_back(fn: Callable) -> Callable: def to_ivy_shape(fn: Callable) -> Callable: - """ - Wrap `fn` so it receives `ivy.Shape` instances. + """Wrap `fn` so it receives `ivy.Shape` instances. Wrap `fn` so that any `torch_frontend.Size` arguments are converted to `ivy.Shape` instances. diff --git a/ivy/functional/frontends/torch/indexing_slicing_joining_mutating_ops.py b/ivy/functional/frontends/torch/indexing_slicing_joining_mutating_ops.py index f20d9263bfa91..5e46854039dcf 100644 --- a/ivy/functional/frontends/torch/indexing_slicing_joining_mutating_ops.py +++ b/ivy/functional/frontends/torch/indexing_slicing_joining_mutating_ops.py @@ -6,6 +6,7 @@ numpy_to_torch_style_args, to_ivy_shape, ) +import ivy.functional.frontends.torch as torch_frontend @to_ivy_arrays_and_back @@ -73,7 +74,7 @@ def conj(input): # diagonal_scatter @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "bfloat16", "float16", ) @@ -88,7 +89,7 @@ def diagonal_scatter(input, src, offset=0, dim1=0, dim2=1): diagonal_indices = ivy.diagonal( indices.reshape(input.shape), offset=offset, axis1=dim1, axis2=dim2 ) - if not (src.shape == diagonal_indices.shape): + if src.shape != diagonal_indices.shape: raise ivy.utils.exceptions.IvyException( "src must have shape equal to specified diagonal of input. src size =" f" {src.shape}, diagonal size = {diagonal_indices.shape}" @@ -173,7 +174,7 @@ def index_add(input, dim, index, source, *, alpha=1, out=None): while len(_to_adds) < _curr_idx: _to_adds.append(ivy.zeros_like(source[0])) _to_add_cum = ivy.get_item(source, index[0][1]) - while (1 < len(index)) and (index[0][0] == index[1][0]): + while (len(index) > 1) and (index[0][0] == index[1][0]): _to_add_cum = _to_add_cum + ivy.get_item(source, index.pop(1)[1]) index.pop(0) _to_adds.append(_to_add_cum) @@ -199,7 +200,7 @@ def index_copy(input, dim, index, source, *, out=None): _curr_idx = index[0][0] for i in range(len(res), _curr_idx): res.append(ivy.get_item(input, i)) - while (1 < len(index)) and (index[0][0] == index[1][0]): + while (len(index) > 1) and (index[0][0] == index[1][0]): index.pop(0) res.append(ivy.get_item(source, index[0][1])) index.pop(0) @@ -214,7 +215,7 @@ def index_copy(input, dim, index, source, *, out=None): @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "uint16", "uint32", "uint64", @@ -341,13 +342,9 @@ def narrow(input, dim, start, length): @to_ivy_arrays_and_back def nonzero(input, *, out=None, as_tuple=False): - ret = ivy.nonzero(input) - if as_tuple is False: - ret = ivy.matrix_transpose(ivy.stack(ret)) - - if ivy.exists(out): - return ivy.inplace_update(out, ret) - return ret + if as_tuple: + return ivy.nonzero(input, as_tuple=as_tuple) + return ivy.argwhere(input != 0, out=out) @to_ivy_arrays_and_back @@ -400,6 +397,7 @@ def squeeze(input, dim=None): return ivy.squeeze(input, axis=dim) +@numpy_to_torch_style_args @to_ivy_arrays_and_back def stack(tensors, dim=0, *, out=None): return ivy.stack(tensors, axis=dim, out=out) @@ -419,8 +417,7 @@ def swapdims(input, dim0, dim1): def t(input): if input.ndim > 2: raise ivy.utils.exceptions.IvyException( - "t(input) expects a tensor with <= 2 dimensions, but self is %dD" - % input.ndim + f"t(input) expects a tensor with <= 2 dimensions, but self is {input.ndim}D" ) if input.ndim == 2: return ivy.swapaxes(input, 0, 1) @@ -508,4 +505,5 @@ def vstack(tensors, *, out=None): def where(condition, input=None, other=None): if not ivy.exists(input) and not ivy.exists(other): return nonzero(condition, as_tuple=True) + input, other = torch_frontend.promote_types_of_torch_inputs(input, other) return ivy.where(condition, input, other) diff --git a/ivy/functional/frontends/torch/linalg.py b/ivy/functional/frontends/torch/linalg.py index 57cbfaae05107..d0db7936cc929 100644 --- a/ivy/functional/frontends/torch/linalg.py +++ b/ivy/functional/frontends/torch/linalg.py @@ -9,7 +9,7 @@ @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.0 and below": ("float32", "float64", "complex32", "complex64")}, "torch" + {"2.2 and below": ("float32", "float64", "complex32", "complex64")}, "torch" ) def cholesky(input, *, upper=False, out=None): return ivy.cholesky(input, upper=upper, out=out) @@ -23,7 +23,7 @@ def cholesky_ex(input, *, upper=False, check_errors=False, out=None): return matrix, info except RuntimeError as e: if check_errors: - raise RuntimeError(e) + raise RuntimeError(e) from e else: matrix = input * math.nan info = ivy.ones(input.shape[:-2], dtype=ivy.int32) @@ -31,14 +31,14 @@ def cholesky_ex(input, *, upper=False, check_errors=False, out=None): @to_ivy_arrays_and_back -@with_supported_dtypes({"2.1.0 and below": ("float32", "float64", "complex")}, "torch") +@with_supported_dtypes({"2.2 and below": ("float32", "float64", "complex")}, "torch") def cond(input, p=None, *, out=None): return ivy.cond(input, p=p, out=out) @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.0 and below": ("float32", "float64", "complex32", "complex64")}, "torch" + {"2.2 and below": ("float32", "float64", "complex32", "complex64")}, "torch" ) def cross(input, other, *, dim=None, out=None): return torch_frontend.miscellaneous_ops.cross(input, other, dim=dim, out=out) @@ -46,7 +46,7 @@ def cross(input, other, *, dim=None, out=None): @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.0 and below": ("float32", "float64", "complex32", "complex64")}, "torch" + {"2.2 and below": ("float32", "float64", "complex32", "complex64")}, "torch" ) def det(A, *, out=None): return ivy.det(A, out=out) @@ -63,13 +63,13 @@ def divide(input, other, *, rounding_mode=None, out=None): @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.0 and below": ("bfloat16", "float16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("bfloat16", "float16")}, "torch") def eig(input, *, out=None): return ivy.eig(input, out=out) @with_supported_dtypes( - {"2.1.0 and below": ("float32", "float64", "complex32", "complex64", "complex128")}, + {"2.2 and below": ("float32", "float64", "complex32", "complex64", "complex128")}, "torch", ) def eigh(A, UPLO="L", *, out=None): @@ -78,7 +78,7 @@ def eigh(A, UPLO="L", *, out=None): @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.0 and below": ("float32", "float64", "complex32", "complex64")}, "torch" + {"2.2 and below": ("float32", "float64", "complex32", "complex64")}, "torch" ) def eigvals(input, *, out=None): ret = ivy.eigvals(input) @@ -89,7 +89,7 @@ def eigvals(input, *, out=None): @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.0 and below": ("float32", "float64", "complex32", "complex64")}, "torch" + {"2.2 and below": ("float32", "float64", "complex32", "complex64")}, "torch" ) def eigvalsh(input, UPLO="L", *, out=None): ret = ivy.eigvalsh(input, UPLO=UPLO, out=out) @@ -102,7 +102,7 @@ def eigvalsh(input, UPLO="L", *, out=None): @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.0 and below": ("float32", "float64", "complex32", "complex64")}, "torch" + {"2.2 and below": ("float32", "float64", "complex32", "complex64")}, "torch" ) def inv(A, *, out=None): return ivy.inv(A, out=out) @@ -110,7 +110,7 @@ def inv(A, *, out=None): @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.0 and below": ("float32", "float64", "complex32", "complex64")}, "torch" + {"2.2 and below": ("float32", "float64", "complex32", "complex64")}, "torch" ) def inv_ex(A, *, check_errors=False, out=None): if ivy.any(ivy.det(A) == 0): @@ -129,41 +129,58 @@ def inv_ex(A, *, check_errors=False, out=None): @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.0 and below": ("float32", "float64", "complex32", "complex64")}, "torch" + {"2.2 and below": ("float32", "float64", "complex32", "complex64")}, "torch" ) def lu_factor(A, *, pivot=True, out=None): return ivy.lu_factor(A, pivot=pivot, out=out) +@to_ivy_arrays_and_back +def lu_factor_ex(A, *, pivot=True, check_errors=False, out=None): + try: + LU = ivy.lu_factor(A, pivot=pivot, out=out) + info = ivy.zeros(A.shape[:-2], dtype=ivy.int32) + return LU, info + except RuntimeError as e: + if check_errors: + raise RuntimeError(e) from e + else: + matrix = A * math.nan + info = ivy.ones(A.shape[:-2], dtype=ivy.int32) + return matrix, info + + +def lu_solve(LU, pivots, B, *, left=True, adjoint=False, out=None): + return ivy.lu_solve(LU, pivots, B, out=out) + + @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.0 and below": ("float32", "float64", "complex32", "complex64")}, "torch" + {"2.2 and below": ("float32", "float64", "complex32", "complex64")}, "torch" ) def matmul(input, other, *, out=None): return ivy.matmul(input, other, out=out) @to_ivy_arrays_and_back -@with_supported_dtypes({"2.1.0 and below": ("float32", "float64", "complex")}, "torch") +@with_supported_dtypes({"2.2 and below": ("float32", "float64", "complex")}, "torch") def matrix_exp(A): return ivy.matrix_exp(A) @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.0 and below": ("float32", "float64", "complex32", "complex64")}, "torch" + {"2.2 and below": ("float32", "float64", "complex32", "complex64")}, "torch" ) def matrix_norm(input, ord="fro", dim=(-2, -1), keepdim=False, *, dtype=None, out=None): - if "complex" in ivy.as_ivy_dtype(input.dtype): - input = ivy.abs(input) - if dtype: - input = ivy.astype(input, ivy.as_ivy_dtype(dtype)) + if dtype is not None: + input = ivy.astype(input, dtype) return ivy.matrix_norm(input, ord=ord, axis=dim, keepdims=keepdim, out=out) @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.0 and below": ("float32", "float64", "complex32", "complex64")}, "torch" + {"2.2 and below": ("float32", "float64", "complex32", "complex64")}, "torch" ) def matrix_power(A, n, *, out=None): return ivy.matrix_power(A, n, out=out) @@ -171,15 +188,15 @@ def matrix_power(A, n, *, out=None): @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.0 and below": ("float32", "float64", "complex32", "complex64")}, "torch" + {"2.2 and below": ("float32", "float64", "complex32", "complex64")}, "torch" ) -def matrix_rank(A, *, atol=None, rtol=None, hermitian=False, out=None): - return ivy.matrix_rank(A, atol=atol, rtol=rtol, hermitian=hermitian, out=out) +def matrix_rank(input, *, atol=None, rtol=None, hermitian=False, out=None): + return ivy.matrix_rank(input, atol=atol, rtol=rtol, hermitian=hermitian, out=out) @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.0 and below": ("float32", "float64", "complex32", "complex64")}, "torch" + {"2.2 and below": ("float32", "float64", "complex32", "complex64")}, "torch" ) def multi_dot(tensors, *, out=None): return ivy.multi_dot(tensors, out=out) @@ -187,7 +204,7 @@ def multi_dot(tensors, *, out=None): @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.0 and below": ("float32", "float64", "complex64", "complex128")}, "torch" + {"2.2 and below": ("float32", "float64", "complex64", "complex128")}, "torch" ) def norm(input, ord=None, dim=None, keepdim=False, *, dtype=None, out=None): if dim is None and (ord is not None): @@ -198,16 +215,20 @@ def norm(input, ord=None, dim=None, keepdim=False, *, dtype=None, out=None): elif dim is None and ord is None: input = ivy.flatten(input) ret = ivy.vector_norm(input, axis=0, keepdims=keepdim, ord=2) - if isinstance(dim, int): + elif isinstance(dim, int): ret = ivy.vector_norm(input, axis=dim, keepdims=keepdim, ord=ord) - elif isinstance(dim, tuple): + elif isinstance(dim, tuple) and len(dim) <= 2: ret = ivy.matrix_norm(input, axis=dim, keepdims=keepdim, ord=ord) + elif isinstance(dim, tuple) and len(dim) > 2: + raise RuntimeError( + f"linalg.norm: If dim is specified, it must be of length 1 or 2. Got {dim}" + ) return ret @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.0 and below": ("float32", "float64", "complex32", "complex64")}, "torch" + {"2.2 and below": ("float32", "float64", "complex32", "complex64")}, "torch" ) def pinv(input, *, atol=None, rtol=None, hermitian=False, out=None): # TODO: add handling for hermitian @@ -226,7 +247,7 @@ def pinv(input, *, atol=None, rtol=None, hermitian=False, out=None): @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.0 and below": ("float32", "float64", "complex32", "complex64")}, "torch" + {"2.2 and below": ("float32", "float64", "complex32", "complex64")}, "torch" ) def qr(A, mode="reduced", *, out=None): if mode == "reduced": @@ -244,7 +265,7 @@ def qr(A, mode="reduced", *, out=None): @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.0 and below": ("float32", "float64", "complex32", "complex64")}, "torch" + {"2.2 and below": ("float32", "float64", "complex32", "complex64")}, "torch" ) def slogdet(A, *, out=None): sign, logabsdet = ivy.slogdet(A) @@ -260,7 +281,7 @@ def slogdet(A, *, out=None): @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.0 and below": ("float32", "float64", "complex32", "complex64")}, "torch" + {"2.2 and below": ("float32", "float64", "complex32", "complex64")}, "torch" ) def solve(A, B, *, left=True, out=None): if left: @@ -274,7 +295,7 @@ def solve(A, B, *, left=True, out=None): @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.0 and below": ("float32", "float64", "complex32", "complex64")}, "torch" + {"2.2 and below": ("float32", "float64", "complex32", "complex64")}, "torch" ) def solve_ex(A, B, *, left=True, check_errors=False, out=None): try: @@ -292,7 +313,7 @@ def solve_ex(A, B, *, left=True, check_errors=False, out=None): return result, info except RuntimeError as e: if check_errors: - raise RuntimeError(e) + raise RuntimeError(e) from e else: result = A * math.nan info = ivy.ones(A.shape[:-2], dtype=ivy.int32) @@ -302,7 +323,7 @@ def solve_ex(A, B, *, left=True, check_errors=False, out=None): @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.0 and below": ("float32", "float64", "complex32", "complex64")}, "torch" + {"2.2 and below": ("float32", "float64", "complex32", "complex64")}, "torch" ) def svd(A, /, *, full_matrices=True, driver=None, out=None): # TODO: add handling for driver and out @@ -311,7 +332,7 @@ def svd(A, /, *, full_matrices=True, driver=None, out=None): @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.0 and below": ("float32", "float64", "complex32", "complex64")}, "torch" + {"2.2 and below": ("float32", "float64", "complex32", "complex64")}, "torch" ) def svdvals(A, *, driver=None, out=None): if driver in ["gesvd", "gesvdj", "gesvda", None]: @@ -322,7 +343,7 @@ def svdvals(A, *, driver=None, out=None): @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.0 and below": ("float32", "float64", "complex32", "complex64")}, "torch" + {"2.2 and below": ("float32", "float64", "complex32", "complex64")}, "torch" ) def tensorinv(input, ind=2, *, out=None): not_invertible = "Reshaped tensor is not invertible" @@ -341,7 +362,7 @@ def tensorinv(input, ind=2, *, out=None): assert prod_ind_end == prod_ind_start, f"{prod_cond}." inverse_shape = shape_ind_start + shape_ind_end input = ivy.reshape(input, shape=(prod_ind_end, -1)) - inverse_shape_tuple = tuple([*inverse_shape]) + inverse_shape_tuple = (*inverse_shape,) assert inv_ex(input, check_errors=True), f"{not_invertible}." inverse_tensor = ivy.inv(input) return ivy.reshape(inverse_tensor, shape=inverse_shape_tuple, out=out) @@ -349,14 +370,14 @@ def tensorinv(input, ind=2, *, out=None): @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.0 and below": ("float32", "float64", "complex32", "complex64")}, "torch" + {"2.2 and below": ("float32", "float64", "complex32", "complex64")}, "torch" ) def tensorsolve(A, B, dims=None, *, out=None): return ivy.tensorsolve(A, B, axes=dims, out=out) @to_ivy_arrays_and_back -@with_supported_dtypes({"2.1.0 and below": ("integer", "float", "complex")}, "torch") +@with_supported_dtypes({"2.2 and below": ("integer", "float", "complex")}, "torch") def vander(x, N=None): if len(x.shape) < 1: raise RuntimeError("Input dim must be greater than or equal to 1.") @@ -389,7 +410,7 @@ def vander(x, N=None): @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.0 and below": ("float32", "float64", "complex32", "complex64")}, "torch" + {"2.2 and below": ("float32", "float64", "complex32", "complex64")}, "torch" ) def vecdot(x, y, *, dim=-1, out=None): if "complex" in ivy.as_ivy_dtype(x.dtype): @@ -399,7 +420,7 @@ def vecdot(x, y, *, dim=-1, out=None): @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.0 and below": ("float32", "float64", "complex32", "complex64")}, "torch" + {"2.2 and below": ("float32", "float64", "complex32", "complex64")}, "torch" ) def vector_norm(input, ord=2, dim=None, keepdim=False, *, dtype=None, out=None): return ivy.vector_norm( diff --git a/ivy/functional/frontends/torch/miscellaneous_ops.py b/ivy/functional/frontends/torch/miscellaneous_ops.py index 7e1f401b5ed59..1cf7aa6d03416 100644 --- a/ivy/functional/frontends/torch/miscellaneous_ops.py +++ b/ivy/functional/frontends/torch/miscellaneous_ops.py @@ -5,6 +5,9 @@ import ivy.functional.frontends.torch as torch_frontend +erfinv = torch_frontend.special.erfinv + + @to_ivy_arrays_and_back def atleast_1d(*tensors): return ivy.atleast_1d(*tensors) @@ -60,9 +63,9 @@ def block_diag(*tensors): ret_dim_1 = 0 for idx, t_shape in enumerate(shapes_list): dim_0, dim_1 = t_shape - ret[ret_dim_0 : ret_dim_0 + dim_0, ret_dim_1 : ret_dim_1 + dim_1] = ( - ivy.copy_array(tensors_2d[idx]) - ) + ret[ + ret_dim_0 : ret_dim_0 + dim_0, ret_dim_1 : ret_dim_1 + dim_1 + ] = ivy.copy_array(tensors_2d[idx]) ret_dim_0 += dim_0 ret_dim_1 += dim_1 @@ -74,7 +77,7 @@ def broadcast_shapes(*shapes): return ivy.broadcast_shapes(*shapes) -@with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "torch") @to_ivy_arrays_and_back def broadcast_to(tensor, shape): return ivy.broadcast_to(tensor, shape) @@ -92,11 +95,53 @@ def cartesian_prod(*tensors): return ret +@with_unsupported_dtypes({"2.2 and below": "float16"}, "torch") +@to_ivy_arrays_and_back +def cdist(x1, x2, p=2.0, compute_mode="use_mm_for_euclid_dist_if_necessary"): + if len(x1.shape) == 2 and len(x2.shape) == 2: + x1_first_dim, x2_first_dim = x1.shape[0], x2.shape[0] + if ( + compute_mode == "use_mm_for_euclid_dist_if_necessary" + and (x1_first_dim > 25 or x2_first_dim > 25) + or compute_mode == "use_mm_for_euclid_dist" + ): + return ivy.vector_norm(x1[:, None, :] - x2[None, :, :], axis=-1, ord=p) + else: + distances = ivy.zeros((x1_first_dim, x2_first_dim), dtype=x1.dtype) + for i in range(x1_first_dim): + for j in range(x2_first_dim): + distances[i, j] = ivy.vector_norm(x1[i, :] - x2[j, :], ord=p) + return distances + if p == 2: + B, P, M = x1.shape + _, R, _ = x2.shape + if ( + compute_mode == "use_mm_for_euclid_dist_if_necessary" + and (P > 25 or R > 25) + or compute_mode == "use_mm_for_euclid_dist" + ): + return ivy.vector_norm( + x1[:, :, None, :] - x2[:, None, :, :], axis=-1, ord=p + ) + else: + distances = ivy.zeros((B, P, R), dtype=x1.dtype) + for b in range(B): + for i in range(P): + for j in range(R): + distances[b, i, j] = ivy.vector_norm( + x1[b, i, :] - x2[b, j, :], ord=p + ) + return distances + else: + return ivy.vector_norm(x1[:, :, None, :] - x2[:, None, :, :], axis=-1, ord=p) + + @to_ivy_arrays_and_back def clone(input, *, memory_format=None): return ivy.copy_array(input) +@with_unsupported_dtypes({"2.2 and below": ("float16", "bool")}, "torch") @to_ivy_arrays_and_back def corrcoef(input): if len(ivy.shape(input)) > 2: @@ -113,7 +158,7 @@ def cov(input, /, *, correction=1, fweights=None, aweights=None): @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def cross(input, other, dim=None, *, out=None): if dim is None: dim = -1 @@ -124,7 +169,7 @@ def cross(input, other, dim=None, *, out=None): @to_ivy_arrays_and_back @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "uint16", "uint32", "uint64", @@ -152,7 +197,7 @@ def cumprod(input, dim, *, dtype=None, out=None): @to_ivy_arrays_and_back @with_unsupported_dtypes( - {"2.1.0 and below": ("uint8", "bfloat16", "float16"), "1.12.1": ()}, + {"2.2 and below": ("uint8", "bfloat16", "float16"), "1.12.1": ()}, "torch", ) def cumsum(input, dim, *, dtype=None, out=None): @@ -166,8 +211,57 @@ def diag(input, diagonal=0, *, out=None): return ivy.diag(input, k=diagonal) +@to_ivy_arrays_and_back +def diag_embed( + input, + offset=0, + dim1=-2, + dim2=-1, +): + def _handle_dim(rank, idx): + if idx >= 0 and idx < rank: + return idx + if idx < 0: + idx = idx + rank + if idx < 0 or idx >= rank: + raise IndexError + return idx + + input_type = ivy.dtype(input) + rank = input.ndim + 1 + dim1 = _handle_dim(rank, dim1) + dim2 = _handle_dim(rank, dim2) + if dim1 > dim2: + dim1, dim2 = dim2, dim1 + offset = -offset + last_dim = list(input.shape)[-1] + if offset != 0: + # add padding to match the new size + t_shape = list(input.shape) + t_shape[-1] = abs(offset) + z = ivy.zeros(t_shape, dtype=input.dtype, device=input.device) + pair = (z, input) if offset > 0 else (input, z) + input = ivy.concat(pair, axis=-1) + last_dim += abs(offset) + input = input.expand_dims(axis=dim1).moveaxis(-1, dim2) + # generate ranges shifting indices based on offset + a_range = ivy.arange(last_dim, device=input.device, dtype=ivy.int64) + b_range = ivy.arange( + offset, last_dim + offset, device=input.device, dtype=ivy.int64 + ) + # broadcast + cond = a_range == b_range.expand_dims(axis=-1) + cond_shape = [last_dim if i in (dim1, dim2) else 1 for i in range(len(input.shape))] + cond = cond.reshape(cond_shape) + if input.dtype == ivy.bool: + ret = cond.logical_and(input) + else: + ret = ivy.where(cond, input, 0) + return ret.astype(input_type) + + @with_supported_dtypes( - {"2.1.0 and below": ("float32", "float64", "int32", "int64")}, "torch" + {"2.2 and below": ("float32", "float64", "int32", "int64")}, "torch" ) @to_ivy_arrays_and_back def diagflat(x, offset=0, name=None): @@ -175,7 +269,7 @@ def diagflat(x, offset=0, name=None): return arr -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") @to_ivy_arrays_and_back def diagonal(input, offset=0, dim1=0, dim2=1): return ivy.diagonal(input, offset=offset, axis1=dim1, axis2=dim2) @@ -183,20 +277,25 @@ def diagonal(input, offset=0, dim1=0, dim2=1): @to_ivy_arrays_and_back @with_unsupported_dtypes( - {"2.1.0 and below": ("int8", "float16", "bfloat16", "bool")}, "torch" + {"2.2 and below": ("int8", "float16", "bfloat16", "bool")}, "torch" ) def diff(input, n=1, dim=-1, prepend=None, append=None): return ivy.diff(input, n=n, axis=dim, prepend=prepend, append=append, out=None) @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def einsum(equation, *operands): if len(operands) == 1 and isinstance(operands[0], (list, tuple)): operands = operands[0] return ivy.einsum(equation, *operands) +@to_ivy_arrays_and_back +def finfo(dtype): + return ivy.finfo(dtype) + + @to_ivy_arrays_and_back def flatten(input, start_dim=0, end_dim=-1): return ivy.flatten(input, start_dim=start_dim, end_dim=end_dim) @@ -242,14 +341,14 @@ def kron(input, other, *, out=None): @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.0 and below": ("int8",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("int8",)}, "torch") def lcm(input, other, *, out=None): return ivy.lcm(input, other, out=out) @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "float16", "bfloat16", "integer", @@ -273,6 +372,11 @@ def logcumsumexp(input, dim, *, out=None): return ret +@to_ivy_arrays_and_back +def lu_solve(b, LU_data, LU_pivots, *, out=None): + return torch_frontend.linalg.lu_solve(LU_data, LU_pivots, b, out=out) + + @to_ivy_arrays_and_back def meshgrid(*tensors, indexing=None): if indexing is None: @@ -287,7 +391,7 @@ def ravel(input): return ivy.reshape(input, (-1,)) -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") @to_ivy_arrays_and_back def renorm(input, p, dim, maxnorm, *, out=None): # Torch hardcodes this magic number @@ -328,7 +432,7 @@ def renorm(input, p, dim, maxnorm, *, out=None): @with_supported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "int32", "int64", ) @@ -441,24 +545,25 @@ def searchsorted( *, out_int32=False, right=False, - side="left", + side=None, out=None, sorter=None, ): - if right and side == "left": - raise ivy.exceptions.IvyError( - "side and right can't be set to opposites, got side of left" - " while right was True" - ) - if right: - side = "right" + if side == "left": + if right: + raise ivy.exceptions.IvyError( + "side and right can't be set to opposites, got side of left" + " while right was True" + ) + elif side is None: + side = "right" if right else "left" ret = ivy.searchsorted(sorted_sequence, values, side=side, out=out, sorter=sorter) if out_int32: ret = ivy.astype(ret, "int32") return ret -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") @to_ivy_arrays_and_back def tensordot(a, b, dims=2, out=None): a, b = promote_types_of_torch_inputs(a, b) @@ -466,7 +571,7 @@ def tensordot(a, b, dims=2, out=None): @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") def trace(input): if "int" in input.dtype: input = input.astype("int64") @@ -480,7 +585,7 @@ def tril(input, diagonal=0, *, out=None): return ivy.tril(input, k=diagonal, out=out) -@with_unsupported_dtypes({"2.1.0 and below": ("int8", "uint8", "int16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("int8", "uint8", "int16")}, "torch") @to_ivy_arrays_and_back def tril_indices(row, col, offset=0, *, dtype=ivy.int64, device="cpu", layout=None): sample_matrix = ivy.tril(ivy.ones((row, col), device=device), k=offset) @@ -502,6 +607,11 @@ def triu_indices(row, col, offset=0, dtype="int64", device="cpu", layout=None): return ivy.stack(ivy.nonzero(sample_matrix)).astype(dtype) +@to_ivy_arrays_and_back +def unflatten(input, dim, sizes): + return ivy.unflatten(input, dim=dim, shape=sizes, out=None) + + @to_ivy_arrays_and_back def vander(x, N=None, increasing=False): # if N == 0: @@ -511,7 +621,7 @@ def vander(x, N=None, increasing=False): @to_ivy_arrays_and_back -@with_supported_dtypes({"2.1.0 and below": ("float32", "float64")}, "torch") +@with_supported_dtypes({"2.2 and below": ("float32", "float64")}, "torch") def view_as_complex(input): if ivy.shape(input)[-1] != 2: raise ivy.exceptions.IvyError("The last dimension must have a size of 2") @@ -529,7 +639,7 @@ def view_as_complex(input): @with_supported_dtypes( - {"2.1.0 and below": ("complex64", "complex128")}, + {"2.2 and below": ("complex64", "complex128")}, "torch", ) @to_ivy_arrays_and_back diff --git a/ivy/functional/frontends/torch/nn/__init__.py b/ivy/functional/frontends/torch/nn/__init__.py index 61af1a48a161f..3de7cfe7ef368 100644 --- a/ivy/functional/frontends/torch/nn/__init__.py +++ b/ivy/functional/frontends/torch/nn/__init__.py @@ -1 +1,5 @@ from . import functional +from . import modules +from .modules import * +from . import parameter +from .parameter import Parameter diff --git a/ivy/functional/frontends/torch/nn/functional/convolution_functions.py b/ivy/functional/frontends/torch/nn/functional/convolution_functions.py index d118282135f0b..89b4bcf3c7f67 100644 --- a/ivy/functional/frontends/torch/nn/functional/convolution_functions.py +++ b/ivy/functional/frontends/torch/nn/functional/convolution_functions.py @@ -13,7 +13,6 @@ def _conv(input, weight, bias=None, stride=1, padding=0, dilation=1, groups=1): dims = len(input.shape) - 2 - _valid_shapes(input, weight, bias, stride, padding, groups) if isinstance(padding, str): padding = padding.upper() @@ -23,7 +22,7 @@ def _conv(input, weight, bias=None, stride=1, padding=0, dilation=1, groups=1): else: padding = [*[(p, p) for p in padding]] - ret = ivy.conv( + ret = ivy.conv_general_dilated( input, weight, stride, @@ -33,14 +32,11 @@ def _conv(input, weight, bias=None, stride=1, padding=0, dilation=1, groups=1): filter_format="channel_first", dilations=dilation, feature_group_count=groups, + bias=bias, ) - if bias is not None: - return ivy.add(ret, ivy.expand_dims(bias, axis=(0, *range(2, dims + 2)))) return ret -# ToDo: add support for dilation > 1 -# ToDo: add support for output_padding > padding def _conv_transpose( input, weight, @@ -55,10 +51,20 @@ def _conv_transpose( weight = ivy.permute_dims(weight, axes=(*range(2, dims + 2), 0, 1)) for i in range(dims): weight = ivy.flip(weight, axis=i) - padding, output_padding = map( - lambda x: [x] * dims if isinstance(x, int) else x, [padding, output_padding] + padding, output_padding, stride, dilation = map( + lambda x: [x] * dims if isinstance(x, int) else x, + [padding, output_padding, stride, dilation], ) - pad_widths = [(weight.shape[i] - 1,) * 2 for i in range(dims)] + + pad_widths = [ + ( + (weight.shape[i] - 1) * dilation[i] + + max([output_padding[i] - padding[i], 0]), + ) + * 2 + for i in range(dims) + ] + ret = ivy.conv_general_dilated( input, weight, @@ -68,81 +74,40 @@ def _conv_transpose( data_format="channel_first", feature_group_count=groups, x_dilations=stride, + dilations=dilation, bias=bias, ) unpad_slice = (slice(None),) * 2 for i in range(dims): unpad_slice += ( - slice(padding[i], ret.shape[2 + i] - padding[i] + output_padding[i], 1), + slice( + max([padding[i] - (dilation[i] // 2), padding[i], output_padding[i]]), + ret.shape[2 + i] - padding[i] + output_padding[i] + (dilation[i] // 2), + 1, + ), ) ret = ret[unpad_slice] return ret -def _valid_shapes(input, weight, bias, stride, padding, groups, transpose=False): - in_channels = input.shape[1] - out_channels = weight.shape[0] if not transpose else weight.shape[1] * groups - - ivy.utils.assertions.check_equal( - in_channels % groups, - 0, - message="in_channels must be divisible by groups", - as_array=False, - ) - ivy.utils.assertions.check_equal( - out_channels % groups, - 0, - message="out_channels must be divisible by groups", - as_array=False, +def _get_transpose_pad(padding, output_padding, dims): + ( + padding, + output_padding, + ) = map( + lambda x: [x] * dims if isinstance(x, int) else x, [padding, output_padding] ) - - if bias is not None: - ivy.utils.assertions.check_equal( - bias.shape[0], - out_channels, - message="bias must be same shape as out_channels", - as_array=False, - ) - - if padding == "same": - if isinstance(stride, int): - ivy.utils.assertions.check_equal( - stride, - 1, - message="padding cannot be 'same' for stride > 1", - as_array=False, - ) - else: - for i in stride: - ivy.utils.assertions.check_equal( - i, - 1, - message="padding cannot be 'same' for stride > 1", - as_array=False, - ) - - if not transpose: - in_channels_by_groups = weight.shape[1] - ivy.utils.assertions.check_equal( - in_channels, - in_channels_by_groups * groups, - message="in_channels must be consistent between input and weight", - as_array=False, - ) - else: - ivy.utils.assertions.check_equal( - in_channels, - weight.shape[0], - message="in_channels must be consistent between input and weight", - as_array=False, - ) + asymmetric_padding = [ + [pad, pad - output_pad] for pad, output_pad in zip(padding, output_padding) + ] + return asymmetric_padding # --- Main --- # # ------------ # -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") @to_ivy_arrays_and_back def conv1d(input, weight, bias=None, stride=1, padding=0, dilation=1, groups=1): return _conv( @@ -156,7 +121,7 @@ def conv1d(input, weight, bias=None, stride=1, padding=0, dilation=1, groups=1): ) -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") @to_ivy_arrays_and_back def conv2d(input, weight, bias=None, stride=1, padding=0, dilation=1, groups=1): return _conv( @@ -170,7 +135,7 @@ def conv2d(input, weight, bias=None, stride=1, padding=0, dilation=1, groups=1): ) -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") @to_ivy_arrays_and_back def conv3d(input, weight, bias=None, stride=1, padding=0, dilation=1, groups=1): return _conv( @@ -184,7 +149,7 @@ def conv3d(input, weight, bias=None, stride=1, padding=0, dilation=1, groups=1): ) -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") @to_ivy_arrays_and_back def conv_transpose1d( input, @@ -196,19 +161,34 @@ def conv_transpose1d( groups=1, dilation=1, ): - return _conv_transpose( - input, - weight, - bias=bias, - stride=stride, - padding=padding, - output_padding=output_padding, - groups=groups, - dilation=dilation, - ) + if ivy.current_backend_str() in ["torch"]: + # this backend supports explicit padding, no need for conv_general_dilated + return ivy.conv_general_transpose( + input, + weight, + stride, + _get_transpose_pad(padding, output_padding, 1), + dims=1, + filter_format="channel_first", + data_format="channel_first", + dilations=dilation, + feature_group_count=groups, + bias=bias, + ) + else: + return _conv_transpose( + input, + weight, + bias=bias, + stride=stride, + padding=padding, + output_padding=output_padding, + groups=groups, + dilation=dilation, + ) -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") @to_ivy_arrays_and_back def conv_transpose2d( input, @@ -220,19 +200,34 @@ def conv_transpose2d( groups=1, dilation=1, ): - return _conv_transpose( - input, - weight, - bias=bias, - stride=stride, - padding=padding, - output_padding=output_padding, - groups=groups, - dilation=dilation, - ) + if ivy.current_backend_str() in ["torch", "tensorflow"]: + # these two backends support explicit padding, no need for conv_general_dilated + return ivy.conv_general_transpose( + input, + weight, + stride, + _get_transpose_pad(padding, output_padding, 2), + dims=2, + filter_format="channel_first", + data_format="channel_first", + dilations=dilation, + feature_group_count=groups, + bias=bias, + ) + else: + return _conv_transpose( + input, + weight, + bias=bias, + stride=stride, + padding=padding, + output_padding=output_padding, + groups=groups, + dilation=dilation, + ) -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") @to_ivy_arrays_and_back def conv_transpose3d( input, @@ -244,16 +239,31 @@ def conv_transpose3d( groups=1, dilation=1, ): - return _conv_transpose( - input, - weight, - bias=bias, - stride=stride, - padding=padding, - output_padding=output_padding, - groups=groups, - dilation=dilation, - ) + if ivy.current_backend_str() in ["torch"]: + # this backend supports explicit padding, no need for conv_general_dilated + return ivy.conv_general_transpose( + input, + weight, + stride, + _get_transpose_pad(padding, output_padding, 3), + dims=3, + filter_format="channel_first", + data_format="channel_first", + dilations=dilation, + feature_group_count=groups, + bias=bias, + ) + else: + return _conv_transpose( + input, + weight, + bias=bias, + stride=stride, + padding=padding, + output_padding=output_padding, + groups=groups, + dilation=dilation, + ) @to_ivy_arrays_and_back diff --git a/ivy/functional/frontends/torch/nn/functional/distance_functions.py b/ivy/functional/frontends/torch/nn/functional/distance_functions.py index 92be14eeeb922..04429e99172d0 100644 --- a/ivy/functional/frontends/torch/nn/functional/distance_functions.py +++ b/ivy/functional/frontends/torch/nn/functional/distance_functions.py @@ -4,7 +4,7 @@ from ivy.func_wrapper import with_unsupported_dtypes -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") @to_ivy_arrays_and_back def cosine_similarity(x1, x2, *, dim=1, eps=1e-08): x1, x2 = torch_frontend.promote_types_of_torch_inputs(x1, x2) @@ -28,7 +28,7 @@ def cosine_similarity(x1, x2, *, dim=1, eps=1e-08): return cosine -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") @to_ivy_arrays_and_back def pairwise_distance(x1, x2, *, p=2.0, eps=1e-06, keepdim=False): x1, x2 = torch_frontend.promote_types_of_torch_inputs(x1, x2) @@ -42,7 +42,7 @@ def pairwise_distance(x1, x2, *, p=2.0, eps=1e-06, keepdim=False): return ivy.vector_norm(x1 - x2 + eps, ord=p, axis=output_dim - 1, keepdims=keepdim) -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") @to_ivy_arrays_and_back def pdist(input, p=2): x = ivy.array( diff --git a/ivy/functional/frontends/torch/nn/functional/dropout_functions.py b/ivy/functional/frontends/torch/nn/functional/dropout_functions.py index affef1205b2fe..a4d2b296661ad 100644 --- a/ivy/functional/frontends/torch/nn/functional/dropout_functions.py +++ b/ivy/functional/frontends/torch/nn/functional/dropout_functions.py @@ -7,7 +7,8 @@ # ToDo: this function will be simplified once ivy.alpha_dropout is implemented @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") def alpha_dropout(input, p=0.5, training=False, inplace=False): if p == 0.0 or not training or input.shape == () or input.shape == (0,): return input @@ -27,13 +28,13 @@ def alpha_dropout(input, p=0.5, training=False, inplace=False): @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def dropout(input, p=0.5, training=True, inplace=False): - return ivy.dropout(input, p, training=training) + return ivy.dropout(input, p, scale=True, training=training) @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def dropout1d(input, p=0.5, training=True, inplace=False): if inplace: return ivy.dropout1d(input, p, training=training, data_format="NCW", out=input) @@ -41,7 +42,7 @@ def dropout1d(input, p=0.5, training=True, inplace=False): @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def dropout2d(input, p=0.5, training=True, inplace=False): if input.ndim < 2: raise ValueError("Feature dropout requires at least 2 dimensions in the input") @@ -54,7 +55,7 @@ def dropout2d(input, p=0.5, training=True, inplace=False): @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") def dropout3d(input, p=0.5, training=True, inplace=False): if inplace: return ivy.dropout3d( diff --git a/ivy/functional/frontends/torch/nn/functional/layer_functions.py b/ivy/functional/frontends/torch/nn/functional/layer_functions.py index 12f36e34df414..6c7221673e2b0 100644 --- a/ivy/functional/frontends/torch/nn/functional/layer_functions.py +++ b/ivy/functional/frontends/torch/nn/functional/layer_functions.py @@ -1,8 +1,6 @@ import ivy from ivy.func_wrapper import with_supported_device_and_dtypes, with_supported_dtypes from ivy.functional.frontends.torch.func_wrapper import to_ivy_arrays_and_back -from ivy.functional.ivy.experimental.manipulation import _slice_along_axis -from ivy.utils.exceptions import IvyNotImplementedException # --- Helpers --- # @@ -17,158 +15,6 @@ def _extract_states(states, batch_sizes): return h -def _generic_lstm( - input, - initial_states, - all_weights, - has_biases, - num_layers, - dropout, - train, - bidirectional, - batch_first=False, - batch_sizes=None, -): - weights_per_layer = 4 if has_biases else 2 - - assert len(all_weights) == num_layers * weights_per_layer * (1 + bidirectional) - layer_weights = [ - all_weights[i : i + weights_per_layer] - for i in range(0, len(all_weights), weights_per_layer) - ] - - if batch_sizes is not None: - input, batch_sizes = _pad_packed_sequence(input, batch_sizes) - - if batch_first: - input = ivy.swapaxes(input, 0, 1) - - if dropout and train: - raise IvyNotImplementedException() - - unidirectional = not bidirectional - - h0, c0 = initial_states - h_outs, c_outs = [], [] - - output = input - for i in range(num_layers): - if unidirectional: - if weights_per_layer == 4: - weight_ih, weight_hh, (bias_i, bias_h) = _transform_weights( - layer_weights, i - ) - else: - weight_ih, weight_hh = _transform_weights_no_bias(layer_weights, i) - bias_i = bias_h = None - - state_indices = i, i + 1 - else: - if weights_per_layer == 4: - weight_ih_f, weight_hh_f, (bias_i_f, bias_h_f) = _transform_weights( - layer_weights, 2 * i - ) - weight_ih_b, weight_hh_b, (bias_i_b, bias_h_b) = _transform_weights( - layer_weights, 2 * i + 1 - ) - else: - weight_ih_f, weight_hh_f = _transform_weights_no_bias( - layer_weights, 2 * i - ) - weight_ih_b, weight_hh_b = _transform_weights_no_bias( - layer_weights, 2 * i + 1 - ) - bias_i_f = bias_h_f = bias_i_b = bias_h_b = None - - weight_ih = weight_ih_f, weight_ih_b - weight_hh = weight_hh_f, weight_hh_b - bias_i = bias_i_f, bias_i_b - bias_h = bias_h_f, bias_h_b - - state_indices = 2 * i, 2 * i + 2 - - output, (h_out, c_out) = _lstm_layer( - output, - ( - _retrieve_state(h0, *state_indices, num_layers), - _retrieve_state(c0, *state_indices, num_layers), - ), - (weight_ih, weight_hh), - (bias_i, bias_h), - bidirectional, - batch_sizes=batch_sizes, - ) - h_outs.append(h_out) - c_outs.append(c_out) - - if batch_first: - output = ivy.swapaxes(output, 0, 1) - - h_outs = h_out if num_layers == 1 else ivy.concat(h_outs, axis=0) - c_outs = c_out if num_layers == 1 else ivy.concat(c_outs, axis=0) - - if batch_sizes is not None: - output = _pack_padded_sequence(output, batch_sizes)[0] - - return output, h_outs, c_outs - - -def _lstm_cell( - x, init_h, init_c, kernel, recurrent_kernel, bias, recurrent_bias, batch_sizes=None -): - x_shape = x.shape - batch_shape = x_shape[1:-1] - timesteps = x_shape[0] - input_channels = x_shape[-1] - - Wi = kernel - Wi_x = ivy.reshape( - ivy.matmul(ivy.reshape(x, (-1, input_channels)), Wi) - + (bias if bias is not None else 0), - [timesteps, *batch_shape, -1], - ) - Wii_x, Wif_x, Wig_x, Wio_x = ivy.split(Wi_x, num_or_size_splits=4, axis=-1) - Wh = recurrent_kernel - ht = init_h - ct = init_c - ht_list = [] - ct_list = [] - - for Wii_xt, Wif_xt, Wig_xt, Wio_xt in zip( - ivy.unstack(Wii_x, axis=0), - ivy.unstack(Wif_x, axis=0), - ivy.unstack(Wig_x, axis=0), - ivy.unstack(Wio_x, axis=0), - ): - htm1 = ht - ctm1 = ct - Wh_htm1 = ivy.matmul(htm1, Wh) + ( - recurrent_bias if recurrent_bias is not None else 0 - ) - Whi_htm1, Whf_htm1, Whg_htm1, Who_htm1 = ivy.split( - Wh_htm1, num_or_size_splits=4, axis=-1 - ) - it = ivy.sigmoid(Wii_xt + Whi_htm1) - ft = ivy.sigmoid(Wif_xt + Whf_htm1) - gt = ivy.tanh(Wig_xt + Whg_htm1) - ot = ivy.sigmoid(Wio_xt + Who_htm1) - ct = ft * ctm1 + it * gt - ht = ot * ivy.tanh(ct) - ct_list.append(ct) - ht_list.append(ht) - - if batch_sizes is None: - c = ct_list[-1] - h = ht_list[-1] - output = ivy.concat(ht_list, axis=0) - else: - ct_list = ivy.concat(ct_list, axis=0) - output = ht_list = ivy.concat(ht_list, axis=0) - c = _extract_states(ct_list, batch_sizes) - h = _extract_states(ht_list, batch_sizes) - return output, (h, c) - - def _lstm_full( input, hx, @@ -180,51 +26,19 @@ def _lstm_full( bidirectional, batch_first, ): - return _generic_lstm( + ret = ivy.lstm( input, hx, params, - has_biases, num_layers, dropout, train, bidirectional, batch_first=batch_first, + has_ih_bias=has_biases, + has_hh_bias=has_biases, ) - - -def _lstm_layer(x, hidden, weights, biases, bidirectional, batch_sizes=None): - if not bidirectional: - result, (h, c) = _lstm_cell( - x, *hidden, *weights, *biases, batch_sizes=batch_sizes - ) - else: - result_fw, (h_fw, c_fw) = _lstm_cell( - x, - hidden[0][:1], - hidden[1][:1], - weights[0][0], - weights[1][0], - biases[0][0], - biases[1][0], - batch_sizes=batch_sizes, - ) - x_reversed = ivy.flip(x, axis=0) - result_bw, (h_bw, c_bw) = _lstm_cell( - x_reversed, - hidden[0][1:], - hidden[1][1:], - weights[0][1], - weights[1][1], - biases[0][1], - biases[1][1], - batch_sizes=batch_sizes, - ) - result_bw = ivy.flip(result_bw, axis=0) - result = ivy.concat([result_fw, result_bw], axis=len(result_fw.shape) - 1) - c = ivy.concat([c_fw, c_bw], axis=0) - h = ivy.concat([h_fw, h_bw], axis=0) - return result, (h, c) + return ret[1], ret[2][0], ret[2][1] def _lstm_packed( @@ -238,70 +52,19 @@ def _lstm_packed( train, bidirectional, ): - return _generic_lstm( + ret = ivy.lstm( data, hx, params, - has_biases, num_layers, dropout, train, bidirectional, batch_sizes=batch_sizes, + has_ih_bias=has_biases, + has_hh_bias=has_biases, ) - - -def _pack_padded_sequence(input, lengths): - input = ivy.swapaxes(input, 0, 1) - data = [] - batch_sizes = [] - for i in range(int(max(lengths))): - valid_data_mask = ivy.array(lengths) > i - data.append(input[valid_data_mask, i]) - batch_sizes.append(int(sum(valid_data_mask))) - data = ivy.concat(data) - batch_sizes = ivy.array(batch_sizes, dtype=ivy.int64) - return data, batch_sizes - - -def _pad_packed_sequence(data, batch_sizes): - padded_data = ivy.full( - (len(batch_sizes), int(max(batch_sizes)), *data.shape[1:]), - 0, - dtype=data.dtype, - device=data.device, - ) - data_offset = 0 - for i, batch_size in enumerate(batch_sizes): - batch_size = int(batch_size) - padded_data[i, :batch_size] = data[data_offset : data_offset + batch_size] - data_offset += batch_size - lengths = ivy.sum( - ivy.arange(1, int(max(batch_sizes)) + 1)[:, ivy.newaxis] <= batch_sizes, - axis=1, - dtype=ivy.int64, - ) - return padded_data, lengths - - -def _retrieve_state(x, start, end, num_layers): - return x if num_layers == 1 else _slice_along_axis(x, start=start, stop=end, axis=0) - - -def _transform_weights(layer_weights, layer_index): - weights = layer_weights[layer_index] - weight_ih, weight_hh, bias_ih, bias_hh = weights - return ( - ivy.swapaxes(weight_ih, 0, 1), - ivy.swapaxes(weight_hh, 0, 1), - (bias_ih, bias_hh), - ) - - -def _transform_weights_no_bias(layer_weights, layer_index): - weights = layer_weights[layer_index] - weight_ih, weight_hh = weights - return ivy.swapaxes(weight_ih, 0, 1), ivy.swapaxes(weight_hh, 0, 1) + return ret[1], ret[2][0], ret[2][1] # --- Main --- # @@ -309,7 +72,7 @@ def _transform_weights_no_bias(layer_weights, layer_index): @with_supported_device_and_dtypes( - {"2.1.0 and below": {"cpu": ("float32", "float64")}}, + {"2.2 and below": {"cpu": ("float32", "float64")}}, "torch", ) @to_ivy_arrays_and_back @@ -321,7 +84,7 @@ def lstm(*args, **kwargs): @to_ivy_arrays_and_back -@with_supported_dtypes({"2.1.0 and below": ("float32", "float64")}, "torch") +@with_supported_dtypes({"2.2 and below": ("float32", "float64")}, "torch") def multi_head_attention_forward( query, key, diff --git a/ivy/functional/frontends/torch/nn/functional/linear_functions.py b/ivy/functional/frontends/torch/nn/functional/linear_functions.py index 040cb9652212d..fba4a5f50b699 100644 --- a/ivy/functional/frontends/torch/nn/functional/linear_functions.py +++ b/ivy/functional/frontends/torch/nn/functional/linear_functions.py @@ -4,7 +4,7 @@ from ivy.functional.frontends.torch.func_wrapper import to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") @to_ivy_arrays_and_back def linear(input, weight, bias=None): return ivy.linear(input, weight, bias=bias) diff --git a/ivy/functional/frontends/torch/nn/functional/loss_functions.py b/ivy/functional/frontends/torch/nn/functional/loss_functions.py index a274d5c5e2434..ef13df7557bfd 100644 --- a/ivy/functional/frontends/torch/nn/functional/loss_functions.py +++ b/ivy/functional/frontends/torch/nn/functional/loss_functions.py @@ -72,7 +72,7 @@ def _get_reduction_string(size_average, reduce): @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") def binary_cross_entropy( input, target, weight=None, size_average=None, reduce=None, reduction="mean" ): @@ -113,7 +113,7 @@ def binary_cross_entropy_with_logits( @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") def cosine_embedding_loss( input1, input2, target, margin=0.0, size_average=None, reduce=None, reduction="mean" ): @@ -214,7 +214,7 @@ def cross_entropy( @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.0 and below": ("bool", "integer")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("bool", "integer")}, "torch") def gaussian_nll_loss(input, target, var, full=False, eps=1e-6, reduction="mean"): input, target = torch_frontend.promote_types_of_torch_inputs(input, target) target, var = torch_frontend.promote_types_of_torch_inputs(target, var) @@ -246,7 +246,7 @@ def gaussian_nll_loss(input, target, var, full=False, eps=1e-6, reduction="mean" @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") @to_ivy_arrays_and_back def hinge_embedding_loss( input, @@ -281,7 +281,7 @@ def huber_loss( @to_ivy_arrays_and_back -@with_supported_dtypes({"2.1.0 and below": ("float32", "float64")}, "torch") +@with_supported_dtypes({"2.2 and below": ("float32", "float64")}, "torch") def kl_div( input, target, size_average=None, reduce=None, reduction="mean", log_target=False ): @@ -297,7 +297,7 @@ def kl_div( @to_ivy_arrays_and_back -@with_supported_dtypes({"2.1.0 and below": ("float", "complex")}, "torch") +@with_supported_dtypes({"2.2 and below": ("float", "complex")}, "torch") def l1_loss( input, target, @@ -312,7 +312,7 @@ def l1_loss( @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") def margin_ranking_loss( input1, input2, @@ -331,7 +331,7 @@ def margin_ranking_loss( @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "torch") def mse_loss(input, target, size_average=None, reduce=None, reduction="mean"): reduction = _get_reduction(reduction, size_average, reduce) result = ivy.square(input - target) @@ -340,7 +340,7 @@ def mse_loss(input, target, size_average=None, reduce=None, reduction="mean"): @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") def multilabel_margin_loss( input, target, size_average=None, reduce=None, reduction="mean" ): @@ -360,7 +360,7 @@ def multilabel_margin_loss( @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") def multilabel_soft_margin_loss( input, target, @@ -390,7 +390,7 @@ def multilabel_soft_margin_loss( @to_ivy_arrays_and_back @with_unsupported_dtypes( - {"2.1.0 and below": ("float16", "int8", "int16", "int32")}, "torch" + {"2.2 and below": ("float16", "int8", "int16", "int32")}, "torch" ) def nll_loss( input, @@ -436,7 +436,7 @@ def pairwise_distance(x1, x2, *, p=2.0, eps=1e-06, keepdim=False): @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") def poisson_nll_loss( input, target, @@ -463,7 +463,7 @@ def poisson_nll_loss( @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") def smooth_l1_loss( input, target, @@ -476,7 +476,7 @@ def smooth_l1_loss( @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") def soft_margin_loss( input, target, @@ -488,7 +488,7 @@ def soft_margin_loss( @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") def triplet_margin_loss( anchor, positive, @@ -543,7 +543,7 @@ def pairwise_distance(x1, x2, *, p=2.0, eps=1e-06, keepdim=False): @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") def triplet_margin_with_distance_loss( anchor, positive, diff --git a/ivy/functional/frontends/torch/nn/functional/non_linear_activation_functions.py b/ivy/functional/frontends/torch/nn/functional/non_linear_activation_functions.py index c49e44d7218f7..55a5f5d35371f 100644 --- a/ivy/functional/frontends/torch/nn/functional/non_linear_activation_functions.py +++ b/ivy/functional/frontends/torch/nn/functional/non_linear_activation_functions.py @@ -7,7 +7,7 @@ @to_ivy_arrays_and_back @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "complex", "float16", ) @@ -38,7 +38,7 @@ def elu_(input, alpha=1.0): @to_ivy_arrays_and_back @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "float16", "bfloat16", ) @@ -63,11 +63,11 @@ def glu(input, dim=-1): @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def gumbel_softmax(logits, tau=1, hard=False, eps=1e-10, dim=-1): gumbels = -ivy.empty_like(logits).exponential().log() gumbels = (logits + gumbels) / tau - y_soft = ivy.softmax(x=gumbels, axis=dim) + y_soft = ivy.softmax(gumbels, axis=dim) if hard: indices = y_soft.max(axis=dim, keepdims=True)[1] @@ -100,64 +100,44 @@ def hardswish(input, inplace=False): @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def hardtanh(input, min_val=-1.0, max_val=1.0, inplace=False): less = ivy.where(ivy.less(input, min_val), min_val, input) return ivy.where(ivy.greater(input, max_val), max_val, less).astype(input.dtype) -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def hardtanh_(input, min_val=-1.0, max_val=1.0): return hardtanh(input, min_val=min_val, max_val=max_val, inplace=True) @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def leaky_relu(input, negative_slope=0.01, inplace=False): return ivy.leaky_relu(input, alpha=negative_slope) -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def leaky_relu_(input, negative_slope=0.01): return leaky_relu(input, negative_slope=negative_slope, inplace=True) @to_ivy_arrays_and_back +@with_supported_dtypes({"2.2 and below": ("float",)}, "torch") def local_response_norm(input, size, alpha=0.0001, beta=0.75, k=1.0): - dim = len(ivy.shape(input)) - if dim < 3: - raise ValueError( - f"Expected 3D or higher dimensionality input (got {dim} dimensions)" - ) - if input.size == 0: - return input - div = ivy.multiply(input, input) - - if dim == 3: - div = ivy.expand_dims(div, axis=1) - div = ivy.zero_pad(div, ((0, 0), (0, 0), (size // 2, (size - 1) // 2), (0, 0))) - div = ivy.avg_pool2d( - div, (size, 1), 1, "VALID", count_include_pad=True, data_format="NCHW" - ) - div = ivy.squeeze(div, axis=1) - else: - sizes = ivy.shape(input) - div = ivy.reshape(div, (sizes[0], 1, sizes[1], sizes[2], -1)) - div = ivy.zero_pad( - div, ((0, 0), (0, 0), (size // 2, (size - 1) // 2), (0, 0), (0, 0)) - ) - div = ivy.avg_pool3d( - div, (size, 1, 1), 1, "VALID", count_include_pad=True, data_format="NCDHW" - ) - div = ivy.squeeze(div, axis=1) - div = ivy.reshape(div, sizes) - - div = ivy.pow(ivy.add(ivy.multiply(div, alpha), k), beta) - return ivy.divide(input, div) + non_batched = input.ndim == 3 + if non_batched: + input = ivy.expand_dims(input, axis=2) + ret = ivy.local_response_norm( + input, size, bias=k, alpha=alpha, beta=beta, average=True, data_format="NCHW" + ) + if non_batched: + ret = ivy.squeeze(ret, axis=2) + return ret @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def log_softmax(input, dim=None, _stacklevel=3, dtype=None): if dtype: input = ivy.astype(ivy.array(input), ivy.as_ivy_dtype(dtype)) @@ -169,7 +149,7 @@ def log_softmax(input, dim=None, _stacklevel=3, dtype=None): @to_ivy_arrays_and_back @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "float16", "bfloat16", ) @@ -208,17 +188,18 @@ def relu(input, inplace=False): @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.0 and below": ("complex",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("complex",)}, "torch") def relu6(input, inplace=False): return ivy.relu6(input) +@to_ivy_arrays_and_back def relu_(input): return relu(input, inplace=True) @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def rrelu(input, lower=1.0 / 8, upper=1.0 / 3, training=False, inplace=False): if training: # alpha = ivy.random_uniform(low=lower, high=upper) @@ -231,13 +212,13 @@ def rrelu(input, lower=1.0 / 8, upper=1.0 / 3, training=False, inplace=False): ) -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def rrelu_(input, lower=1.0 / 8, upper=1.0 / 3, training=False): return rrelu(input, lower=lower, upper=upper, training=training, inplace=True) @to_ivy_arrays_and_back -@with_supported_dtypes({"2.1.0 and below": ("float32", "float64")}, "torch") +@with_supported_dtypes({"2.2 and below": ("float32", "float64")}, "torch") def scaled_dot_product_attention( query, key, value, attn_mask=None, dropout_p=0.0, is_causal=False, scale=None ): @@ -258,19 +239,19 @@ def selu(input, inplace=False): @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def sigmoid(input): return ivy.sigmoid(input) -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") @to_ivy_arrays_and_back def silu(input, inplace=False): return ivy.multiply(input, ivy.sigmoid(input)) @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def softmax(input, dim=None, _stacklevel=3, dtype=None): if dtype: input = ivy.astype(ivy.array(input), ivy.as_ivy_dtype(dtype)) @@ -278,7 +259,7 @@ def softmax(input, dim=None, _stacklevel=3, dtype=None): @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def softmin(input, dim=None, dtype=None): if dtype: input = ivy.astype(ivy.array(input), ivy.as_ivy_dtype(dtype)) @@ -288,7 +269,7 @@ def softmin(input, dim=None, dtype=None): @to_ivy_arrays_and_back @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "float16", "bfloat16", ) @@ -312,23 +293,23 @@ def softsign(input): @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def tanh(input): return ivy.tanh(input) @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def tanhshrink(input): return ivy.subtract(input, ivy.tanh(input)) @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def threshold(input, threshold, value, inplace=False): return ivy.where(ivy.greater(input, threshold), input, value) -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def threshold_(input, threshold, value): return threshold(input, threshold, value, inplace=True) diff --git a/ivy/functional/frontends/torch/nn/functional/norms.py b/ivy/functional/frontends/torch/nn/functional/norms.py index e833142814cbe..7418d9f6f8f9b 100644 --- a/ivy/functional/frontends/torch/nn/functional/norms.py +++ b/ivy/functional/frontends/torch/nn/functional/norms.py @@ -5,7 +5,7 @@ @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "bfloat16", "float16", ) @@ -34,15 +34,16 @@ def batch_norm( momentum=momentum, data_format="NCS", ) - ivy.inplace_update(running_mean, mean) - ivy.inplace_update(running_var, var) + if training: + ivy.inplace_update(running_mean, mean) + ivy.inplace_update(running_var, var) return normalized @to_ivy_arrays_and_back @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "float16", "bfloat16", ) @@ -57,7 +58,7 @@ def group_norm(input, num_groups, weight=None, bias=None, eps=1e-05): @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "bfloat16", "float16", ) @@ -92,7 +93,7 @@ def instance_norm( @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") def layer_norm(input, normalized_shape, weight=None, bias=None, eps=1e-05): shape = ivy.shape(input) if isinstance(normalized_shape, int) and normalized_shape == shape[-1]: diff --git a/ivy/functional/frontends/torch/nn/functional/pooling_functions.py b/ivy/functional/frontends/torch/nn/functional/pooling_functions.py index 040b005b68131..5f7cbff10383e 100644 --- a/ivy/functional/frontends/torch/nn/functional/pooling_functions.py +++ b/ivy/functional/frontends/torch/nn/functional/pooling_functions.py @@ -9,34 +9,9 @@ ) -# --- Helpers --- # -# --------------- # - - -def _broadcast_pooling_helper(x, pool_dims: str = "2d", name: str = "padding"): - dims = {"1d": 1, "2d": 2, "3d": 3} - - if isinstance(x, int): - return tuple([x for _ in range(dims[pool_dims])]) - - if len(x) == 1: - return tuple([x[0] for _ in range(dims[pool_dims])]) - elif len(x) == dims[pool_dims]: - return tuple(x) - elif len(x) != dims[pool_dims]: - raise ValueError( - f"`{name}` must either be a single int, " - f"or a tuple of {dims[pool_dims]} ints. " - ) - - -# --- Main --- # -# ------------ # - - @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "bfloat16", "float16", ) @@ -50,7 +25,7 @@ def adaptive_avg_pool1d(input, output_size): @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "float16", "bfloat16", ) @@ -59,12 +34,12 @@ def adaptive_avg_pool1d(input, output_size): ) @to_ivy_arrays_and_back def adaptive_avg_pool2d(input, output_size): - return ivy.adaptive_avg_pool2d(input, output_size) + return ivy.adaptive_avg_pool2d(input, output_size, data_format="NCHW") @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "bfloat16", "float16", ) @@ -81,6 +56,31 @@ def adaptive_max_pool2d( return ivy.adaptive_max_pool2d(input, output_size) +@with_unsupported_dtypes( + { + "2.2 and below": ( + "float16", + "int8", + "int16", + "bool", + "uint8", + ) + }, + "torch", +) +@to_ivy_arrays_and_back +def adaptive_max_pool3d( + input, + output_size, + return_indices=False, +): + return ivy.adaptive_max_pool3d(input, output_size) + + +@with_unsupported_dtypes( + {"2.2 and below": ("float16",)}, + "torch", +) @to_ivy_arrays_and_back def avg_pool1d( input, @@ -90,30 +90,23 @@ def avg_pool1d( ceil_mode=False, count_include_pad=True, ): - if stride is None: - stride = kernel_size - data_format = "NCW" - # TODO: remove the broadcasting and padding string specification when ivy.avg_pool - # support explicit padding - kernel_size = _broadcast_pooling_helper(kernel_size, "1d", name="kernel_size") - padding = _broadcast_pooling_helper(padding, "1d", name="padding") - if all( - [pad == ivy.ceil((kernel - 1) / 2) for kernel, pad in zip(kernel_size, padding)] - ): - padding = "SAME" - else: - padding = "VALID" + if not isinstance(padding, int): + padding = [(pad, pad) for pad in padding] return ivy.avg_pool1d( input, kernel_size, - stride, + stride if stride is not None else kernel_size, padding, - data_format=data_format, + data_format="NCW", count_include_pad=count_include_pad, ceil_mode=ceil_mode, ) +@with_unsupported_dtypes( + {"2.2 and below": ("float16",)}, + "torch", +) @to_ivy_arrays_and_back def avg_pool2d( input, @@ -124,31 +117,24 @@ def avg_pool2d( count_include_pad=True, divisor_override=None, ): - if stride is None: - stride = kernel_size - data_format = "NCHW" - # TODO: remove the broadcasting and padding string specification when ivy.avg_pool - # support explicit padding - kernel_size = _broadcast_pooling_helper(kernel_size, "2d", name="kernel_size") - padding = _broadcast_pooling_helper(padding, "2d", name="padding") - if all( - [pad == ivy.ceil((kernel - 1) / 2) for kernel, pad in zip(kernel_size, padding)] - ): - padding = "SAME" - else: - padding = "VALID" + if not isinstance(padding, int): + padding = [(pad, pad) for pad in padding] return ivy.avg_pool2d( input, kernel_size, - stride, + stride if stride is not None else kernel_size, padding, - data_format=data_format, + data_format="NCHW", ceil_mode=ceil_mode, count_include_pad=count_include_pad, divisor_override=divisor_override, ) +@with_unsupported_dtypes( + {"2.2 and below": ("float16", "bfloat16")}, + "torch", +) @to_ivy_arrays_and_back def avg_pool3d( input, @@ -159,22 +145,12 @@ def avg_pool3d( count_include_pad=True, divisor_override=None, ): - if stride is None: - stride = kernel_size - # TODO: remove the broadcasting and padding string specification when ivy.avg_pool - # support explicit padding - kernel_size = _broadcast_pooling_helper(kernel_size, "3d", name="kernel_size") - padding = _broadcast_pooling_helper(padding, "3d", name="padding") - if all( - [pad == ivy.ceil((kernel - 1) / 2) for kernel, pad in zip(kernel_size, padding)] - ): - padding = "SAME" - else: - padding = "VALID" + if not isinstance(padding, int): + padding = [(pad, pad) for pad in padding] return ivy.avg_pool3d( input, kernel_size, - stride, + stride if stride is not None else kernel_size, padding, data_format="NCDHW", ceil_mode=ceil_mode, @@ -185,7 +161,7 @@ def avg_pool3d( @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "float16", "bfloat16", ) @@ -215,6 +191,15 @@ def lp_pool1d(input, norm_type, kernel_size, stride=None, ceil_mode=False): return ivy.pow(ivy.multiply(out, kernel_mul), p) +@with_unsupported_dtypes( + { + "2.2 and below": ( + "float16", + "bfloat16", + ) + }, + "torch", +) @to_ivy_arrays_and_back def lp_pool2d(input, norm_type, kernel_size, stride=None, ceil_mode=False): data_format = "NCHW" @@ -237,31 +222,33 @@ def lp_pool2d(input, norm_type, kernel_size, stride=None, ceil_mode=False): return ivy.pow(ivy.multiply(out, kernel_mul), p).astype(input.dtype) +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") @to_ivy_arrays_and_back def max_pool1d( input, kernel_size, stride=None, padding=0, - ceil_mode=False, dilation=1, + ceil_mode=False, return_indices=False, ): if stride is None: stride = kernel_size - data_format = "NCW" + if not isinstance(padding, int): + padding = [(pad, pad) for pad in padding] return ivy.max_pool1d( input, kernel_size, stride, padding, - data_format=data_format, + data_format="NCW", dilation=dilation, ceil_mode=ceil_mode, ) -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") @to_ivy_arrays_and_back def max_pool2d( input, @@ -272,8 +259,10 @@ def max_pool2d( ceil_mode=False, return_indices=False, ): - if stride is None: + if not stride: stride = kernel_size + if not isinstance(padding, int): + padding = [(pad, pad) for pad in padding] return ivy.max_pool2d( input, kernel_size, @@ -285,7 +274,7 @@ def max_pool2d( ) -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") @to_ivy_arrays_and_back def max_pool3d( input, @@ -298,8 +287,15 @@ def max_pool3d( ): if stride is None: stride = kernel_size + if not isinstance(padding, int): + padding = [(pad, pad) for pad in padding] + if input.ndim == 4: + without_batch_dim = True + input = ivy.expand_dims(input, axis=0) + else: + without_batch_dim = False - return ivy.max_pool3d( + ret = ivy.max_pool3d( input, kernel_size, stride, @@ -308,3 +304,7 @@ def max_pool3d( dilation=dilation, ceil_mode=ceil_mode, ) + if without_batch_dim: + ret = ret[0] + + return ret diff --git a/ivy/functional/frontends/torch/nn/functional/sparse_functions.py b/ivy/functional/frontends/torch/nn/functional/sparse_functions.py index b50c5b16b5fba..a351132d3b362 100644 --- a/ivy/functional/frontends/torch/nn/functional/sparse_functions.py +++ b/ivy/functional/frontends/torch/nn/functional/sparse_functions.py @@ -33,7 +33,7 @@ def embedding( return ret -@with_supported_dtypes({"2.1.0 and below": ("int64",)}, "torch") +@with_supported_dtypes({"2.2 and below": ("int64",)}, "torch") @to_ivy_arrays_and_back def one_hot(tensor, num_classes=-1): return ivy.astype(ivy.one_hot(tensor, num_classes), tensor.dtype) diff --git a/ivy/functional/frontends/torch/nn/functional/vision_functions.py b/ivy/functional/frontends/torch/nn/functional/vision_functions.py index c6cf9d4541cf7..513d5fd3f57de 100644 --- a/ivy/functional/frontends/torch/nn/functional/vision_functions.py +++ b/ivy/functional/frontends/torch/nn/functional/vision_functions.py @@ -4,7 +4,6 @@ import ivy from ivy import with_unsupported_dtypes, with_supported_dtypes from ivy.functional.frontends.torch.func_wrapper import to_ivy_arrays_and_back -from ivy.utils.exceptions import IvyNotImplementedException # --- Helpers --- # @@ -18,11 +17,10 @@ def _handle_padding_shape(padding, n, mode): for i in range(int(len(padding) / 2) - 1, -1, -1) ] ) - while len(padding) < n: - if mode == "circular": - padding = padding + ((0, 0),) - else: - padding = ((0, 0),) + padding + if mode == "circular": + padding = padding + ((0, 0),) * (n - len(padding)) + else: + padding = ((0, 0),) * (n - len(padding)) + padding if mode == "circular": padding = tuple(list(padding)[::-1]) return padding @@ -32,7 +30,7 @@ def _handle_padding_shape(padding, n, mode): # ------------ # -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") @to_ivy_arrays_and_back def affine_grid(theta, size, align_corners=False): if len(size) == 4: @@ -95,7 +93,7 @@ def cubic_conv2(A, x): return ((A * x - 5 * A) * x + 8 * A) * x - 4 * A -@with_supported_dtypes({"2.1.0 and below": ("float32", "float64")}, "torch") +@with_supported_dtypes({"2.2 and below": ("float32", "float64")}, "torch") @to_ivy_arrays_and_back def grid_sample( input, grid, mode="bilinear", padding_mode="zeros", align_corners=False @@ -350,7 +348,7 @@ def grid_sample_padding(grid, padding_mode, align_corners, borders=None): @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "bfloat16", "float16", ) @@ -367,101 +365,14 @@ def interpolate( recompute_scale_factor=None, antialias=False, ): - if mode in ["nearest", "area", "nearest-exact"]: - ivy.utils.assertions.check_exists( - align_corners, - inverse=True, - message=( - "align_corners option can only be set with the interpolating modes:" - " linear | bilinear | bicubic | trilinear" - ), - ) - - dim = ivy.get_num_dims(input) - 2 # Number of spatial dimensions. - - if ivy.exists(size) and ivy.exists(scale_factor): - raise ivy.utils.exceptions.IvyException( - "only one of size or scale_factor should be defined" - ) - - elif ivy.exists(size) and not ivy.exists(scale_factor): - if isinstance(size, (list, tuple)): - ivy.utils.assertions.check_equal( - len(size), - dim, - inverse=False, - message=( - "Input and output must have the " - "same number of spatial dimensions," - f" but got input with spatial dimensions of {list(input.shape[2:])}" - f" and output size of {size}. " - "Please provide input tensor in (N, C, d1, d2, ...,dK) format" - " and output size in (o1, o2, ...,oK) format." - ), - as_array=False, - ) - elif ivy.exists(scale_factor) and not ivy.exists(size): - if isinstance(scale_factor, (list, tuple)): - ivy.utils.assertions.check_equal( - len(scale_factor), - dim, - inverse=False, - message=( - "Input and scale_factor must have the " - "same number of spatial dimensions," - f" but got input with spatial dimensions of {list(input.shape[2:])}" - f" and scale_factor of shape {scale_factor}. " - "Please provide input tensor in (N, C, d1, d2, ...,dK) format" - " and scale_factor in (s1, s2, ...,sK) format." - ), - as_array=False, - ) - else: - ivy.utils.assertions.check_any( - [ivy.exists(size), ivy.exists(scale_factor)], - message="either size or scale_factor should be defined", - as_array=False, - ) - - if ( - ivy.exists(size) - and ivy.exists(recompute_scale_factor) - and bool(recompute_scale_factor) - ): - raise ivy.utils.exceptions.IvyException( - "recompute_scale_factor is not meaningful with an explicit size." - ) - if ( - bool(antialias) - and (mode not in ["bilinear", "bicubic"]) - and ivy.get_num_dims(input) == 4 + mode not in ["linear", "bilinear", "bicubic", "trilinear"] + and align_corners is not None ): raise ivy.utils.exceptions.IvyException( - "recompute_scale_factor is not meaningful with an explicit size." - ) - - if ivy.get_num_dims(input) == 3 and mode == "bilinear": - raise IvyNotImplementedException( - "Got 3D input, but bilinear mode needs 4D input" - ) - if ivy.get_num_dims(input) == 3 and mode == "trilinear": - raise IvyNotImplementedException( - "Got 3D input, but trilinear mode needs 5D input" - ) - if ivy.get_num_dims(input) == 4 and mode == "linear": - raise IvyNotImplementedException("Got 4D input, but linear mode needs 3D input") - if ivy.get_num_dims(input) == 4 and mode == "trilinear": - raise IvyNotImplementedException( - "Got 4D input, but trilinear mode needs 5D input" + "align_corners option can only be set with the interpolating" + f"modes: linear | bilinear | bicubic | trilinear (got {mode})" ) - if ivy.get_num_dims(input) == 5 and mode == "linear": - raise IvyNotImplementedException("Got 5D input, but linear mode needs 3D input") - if ivy.get_num_dims(input) == 5 and mode == "bilinear": - raise IvyNotImplementedException( - "Got 5D input, but bilinear mode needs 4D input" - ) - ivy.utils.assertions.check_elem_in_list( ivy.get_num_dims(input), range(3, 6), @@ -471,20 +382,20 @@ def interpolate( f" bicubic | trilinear | area | nearest-exact (got {mode})" ), ) - return ivy.interpolate( input, size, mode=mode, scale_factor=scale_factor, recompute_scale_factor=recompute_scale_factor, - align_corners=align_corners, + align_corners=bool(align_corners), antialias=antialias, ) @to_ivy_arrays_and_back def pad(input, pad, mode="constant", value=0): + value = 0 if value is None else value mode_dict = { "constant": "constant", "reflect": "reflect", @@ -504,8 +415,10 @@ def pixel_shuffle(input, upscale_factor): ivy.utils.assertions.check_equal( ivy.get_num_dims(input), 4, - message="pixel_shuffle expects 4D input, but got input with sizes " - + str(input_shape), + message=( + "pixel_shuffle expects 4D input, but got input with sizes" + f" {str(input_shape)}" + ), as_array=False, ) b = input_shape[0] @@ -548,7 +461,7 @@ def pixel_unshuffle(input, downscale_factor): f"pixel_unshuffle expects 4D input, but got input with sizes {input_shape}" ), as_array=False, - ), + ) b = input_shape[0] c = input_shape[1] @@ -593,7 +506,7 @@ def reflect(x, low2, high2): return x -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") @to_ivy_arrays_and_back def upsample( input, @@ -611,7 +524,7 @@ def upsample( ) -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") @to_ivy_arrays_and_back def upsample_bilinear(input, size=None, scale_factor=None): return interpolate( @@ -619,7 +532,7 @@ def upsample_bilinear(input, size=None, scale_factor=None): ) -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") @to_ivy_arrays_and_back def upsample_nearest(input, size=None, scale_factor=None): return interpolate(input, size=size, scale_factor=scale_factor, mode="nearest") diff --git a/ivy/functional/frontends/torch/nn/modules/__init__.py b/ivy/functional/frontends/torch/nn/modules/__init__.py new file mode 100644 index 0000000000000..369789978e4b6 --- /dev/null +++ b/ivy/functional/frontends/torch/nn/modules/__init__.py @@ -0,0 +1,2 @@ +from . import module +from .module import Module diff --git a/ivy/functional/frontends/torch/nn/modules/module.py b/ivy/functional/frontends/torch/nn/modules/module.py new file mode 100644 index 0000000000000..e2c6059051fee --- /dev/null +++ b/ivy/functional/frontends/torch/nn/modules/module.py @@ -0,0 +1,360 @@ +# global +import ivy +from collections import OrderedDict +from typing import Any, Dict, Iterator, List, Optional, Set, Tuple, Callable + +# local +from ivy.functional.frontends.torch.nn.parameter import Parameter +from ivy.functional.frontends.torch.tensor import Tensor + + +class Module(ivy.Module): + _version: int = 1 + training: bool + _parameters: Dict[str, Optional[Parameter]] + _modules: Dict[str, Optional["Module"]] + + def __init__(self, *args, device=None, devices=None, **kwargs) -> None: + super().__init__( + self, + *args, + device=device, + devices=devices, + training=True, + build_mode="explicit", + dynamic_backend=True, + **kwargs, + ) + super().__setattr__("_frontend_module", True) + super().__setattr__( + "_attr_mapping", {"_parameters": "v", "_modules": "module_dict"} + ) + + def _create_variables(self, device=None, dtype=None): + # Create variables stored in the `__dict__` that were set + # using direct `__setattr__` e.g. self.weight = ... + v = ivy.Container( + OrderedDict( + [ + (k.replace(".", "/"), v) + for k, v in self.__dict__.items() + if isinstance(v, Parameter) + and not k.startswith( + ("_"), + ) + ] + ) + ) + # Created variables that were added using `register_paramter`, + # since those would appear in `self._v` + v = ( + ivy.Container( + OrderedDict( + ( + { + _k.replace(".", "/"): _v + for (_k, _v) in self._v.items() + if _k.replace(".", "/") not in v + and not isinstance(_v, ivy.Container) + } + ), + **v, + ) + ) + if self._v + else v + ) + return v + + def _build(self, *args, **kwargs): + for module in self.__dict__.values(): + if isinstance(module, Module) and module is not self: + if not module._built: + module.build( + *module._args, + dynamic_backend=module._dynamic_backend, + **module._kwargs, + ) + return True + + def _replace_update_v(self, new_v, native=None): + from ivy.functional.ivy.gradients import _is_variable + + native = ivy.default(native, self) + for k, v in new_v.items(): + if isinstance(v, ivy.Container): + # noinspection PyProtectedMember + native.module_dict[k] = self._replace_update_v(v, native.module_dict[k]) + elif isinstance(v, Parameter): + # noinspection PyProtectedMember + native.__setattr__(k, v) + elif _is_variable(v): + native.__setattr__(k, Parameter(v)) + elif isinstance(v, Tensor): + # noinspection PyProtectedMember + native.__setattr__(k, Parameter(v, requires_grad=v.requires_grad)) + else: + raise ivy.utils.exceptions.IvyException( + f"found item in variable container {v} which was neither a sub" + " ivy.Container nor a variable." + ) + return native + + _update_v = _replace_update_v + + def forward(self, *input: Any) -> None: + raise NotImplementedError( + f'Module [{type(self).__name__}] is missing the required "forward" function' + ) + + def call(self, inputs, *args, training=None, mask=None, **kwargs): + if isinstance(inputs, (list, tuple)): + try: + return self.forward(*inputs, *args, **kwargs) + except Exception: + return self.forward(inputs, *args, **kwargs) + else: + return self.forward(inputs, *args, **kwargs) + + def _forward(self, *a, **kw): + ret = self._call_impl(*a, **kw) + return ret + + def add_module(self, name: str, module: Optional["Module"]) -> None: + if not isinstance(module, Module) and module is not None: + raise TypeError(f"{type(module)} is not a Module subclass") + elif not isinstance(name, str): + raise TypeError(f"module name should be a string. Got {type(name)}") + elif hasattr(self, name) and name not in self._modules: + raise KeyError(f"attribute '{name}' already exists") + elif "." in name: + raise KeyError(f'module name can\'t contain ".", got: {name}') + elif name == "": + raise KeyError('module name can\'t be empty string ""') + + self._modules[name] = module + + super().__setattr__(name, module) + + def apply(self, fn: Callable[["Module"], None]): + for module in self.children(): + module.apply(fn) + fn(self) + return self + + def register_buffer(self, name: str, value: Optional["Tensor"]) -> None: + super().register_buffer(name, value) + + def register_parameter(self, name: str, value: Optional["Parameter"]) -> None: + super().register_parameter(name, value) + + def register_module(self, name: str, module: Optional["Module"]) -> None: + r"""Alias for :func:`add_module`.""" + self.add_module(name, module) + + def get_submodule(self, target: str) -> "Module": + if target == "": + return self + + atoms: List[str] = target.split(".") + mod: Module = self + + for item in atoms: + if not hasattr(mod, item): + raise AttributeError( + mod._get_name() + " has no attribute `" + item + "`" + ) + + mod = getattr(mod, item) + + if not isinstance(mod, Module): + raise TypeError("`" + item + "` is not an nn.Module") + + return mod + + def get_parameter(self, target: str): + target = target.replace(".", "/") + return self.v[target] + + def _named_members( + self, get_members_fn, prefix="", recurse=True, remove_duplicate: bool = True + ): + r"""Helper method for yielding various names + members of modules.""" + memo = set() + modules = ( + self.named_modules(prefix=prefix, remove_duplicate=remove_duplicate) + if recurse + else [(prefix, self)] + ) + for module_prefix, module in modules: + members = get_members_fn(module) + for k, v in members: + if v is None or id(v) in memo or not isinstance(v, Parameter): + continue + if remove_duplicate: + memo.add(id(v)) + name = module_prefix + ("." if module_prefix else "") + k + yield name, v + + def parameters(self, recurse: bool = True) -> Iterator[Parameter]: + for _, param in self.named_parameters(recurse=recurse): + yield param + + def named_parameters( + self, prefix: str = "", recurse: bool = True, remove_duplicate: bool = True + ) -> Iterator[Tuple[str, Parameter]]: + if not getattr(self, "_built", False): + self.build( + *self._args, dynamic_backend=self._dynamic_backend, **self._kwargs + ) + gen = self._named_members( + lambda module: module.v.items(), + prefix=prefix, + recurse=recurse, + remove_duplicate=remove_duplicate, + ) + yield from gen + + def children(self) -> Iterator["Module"]: + for _, module in self.named_children(): + yield module + + def named_children(self) -> Iterator[Tuple[str, "Module"]]: + if not getattr(self, "_built", False): + self.build( + *self._args, dynamic_backend=self._dynamic_backend, **self._kwargs + ) + memo = set() + for name, module in self._module_dict.items(): + if module is not None and id(module) not in memo: + memo.add(id(module)) + yield name, module + + def modules(self) -> Iterator["Module"]: + for _, module in self.named_modules(): + yield module + + def named_modules( + self, + memo: Optional[Set["Module"]] = None, + prefix: str = "", + remove_duplicate: bool = True, + ): + if not getattr(self, "_built", False): + self.build( + *self._args, dynamic_backend=self._dynamic_backend, **self._kwargs + ) + if memo is None: + memo = set() + if id(self) not in memo: + if remove_duplicate: + memo.add(id(self)) + yield prefix, self + for name, module in self._module_dict.items(): + if module is None: + continue + submodule_prefix = prefix + ("." if prefix else "") + name + yield from module.named_modules( + memo, submodule_prefix, remove_duplicate + ) + + def requires_grad_(self, requires_grad: bool = True): + for p in self.parameters(): + p.requires_grad_(requires_grad) + return self + + def _get_name(self): + return self.__class__.__name__ + + def _extra_repr(self) -> str: + return "" + + def _call_impl(self, *args, **kwargs): + return self.call(*args, **kwargs) + + def __getattribute__(self, name: str) -> Any: + if name == "__dict__": + return super().__getattribute__(name) + if "_module_dict" in self.__dict__: + modules = self.__dict__["_module_dict"] + if name in modules: + return modules[name] + if "_buffers" in self.__dict__: + buffers = self.__dict__["_buffers"] + if name in buffers: + return buffers[name] + if "_v" in self.__dict__: + v = self.__dict__["_v"] + if name in v: + return v[name] + # Adding this attribute mapping s.t if someone tries + # to retrieve self._modules/self._parameters, we + # can handle that here + if "_attr_mapping" in self.__dict__: + mapping = self.__dict__["_attr_mapping"] + if name in mapping: + return super().__getattribute__(mapping[name]) + return super().__getattribute__(name) + + def __setattr__(self, name, value) -> None: + def remove_from(*dicts_or_sets): + for d in dicts_or_sets: + if name in d: + if isinstance(d, dict): + del d[name] + else: + d.discard(name) + + params = self.__dict__.get("_v") + if params is not None and name in params and isinstance(value, Parameter): + remove_from(self.__dict__, self._buffers, self._module_dict) + self.register_parameter(name, value) + super().__setattr__(name, value) + else: + super().__setattr__(name, value) + + def __repr__(self): + # We treat the extra repr like the sub-module, one item per line + extra_lines = [] + extra_repr = self._extra_repr() + # empty string will be split into list [''] + if extra_repr: + extra_lines = extra_repr.split("\n") + child_lines = [] + for key, module in self._module_dict.items(): + mod_str = repr(module) + mod_str = self._addindent(mod_str, 2) + child_lines.append("(" + key + "): " + mod_str) + lines = extra_lines + child_lines + + main_str = self._get_name() + "(" + if lines: + # simple one-liner info, which most builtin Modules will use + if len(extra_lines) == 1 and not child_lines: + main_str += extra_lines[0] + else: + main_str += "\n " + "\n ".join(lines) + "\n" + + main_str += ")" + return main_str + + def __dir__(self): + module_attrs = dir(self.__class__) + attrs = list(self.__dict__.keys()) + parameters = list(self._v.keys()) + modules = list(self._module_dict.keys()) + buffers = list(self._buffers.keys()) + keys = module_attrs + attrs + parameters + modules + buffers + + # Eliminate attrs that are not legal Python variable names + keys = [key for key in keys if not key[0].isdigit()] + + return sorted(keys) + + def __getstate__(self): + state = self.__dict__.copy() + state.pop("_compiled_call_impl", None) + return state + + def __setstate__(self, state): + self.__dict__.update(state) diff --git a/ivy/functional/frontends/torch/nn/parameter.py b/ivy/functional/frontends/torch/nn/parameter.py new file mode 100644 index 0000000000000..1d8dc9eda80b8 --- /dev/null +++ b/ivy/functional/frontends/torch/nn/parameter.py @@ -0,0 +1,31 @@ +import ivy +from ivy.functional.frontends.torch.tensor import Tensor +import ivy.functional.frontends.torch as torch_frontend +from ivy.functional.ivy.gradients import _variable, _is_variable, _variable_data + + +class Parameter(Tensor): + def __init__(self, data=None, device=None, requires_grad=True): + if data is None: + data = torch_frontend.empty(0) + ivy_array = ( + ivy.array(data) if not hasattr(data, "_ivy_array") else data.ivy_array + ) + ivy_array = _variable(ivy_array) if not _is_variable(data) else ivy_array + self._ivy_array = ivy.to_device(ivy_array, device) if device else ivy_array + self._data = Tensor(_variable_data(self._ivy_array), _init_overload=True) + self._requires_grad = requires_grad + self._is_leaf = True + self._grads = None + self.grad_fn = None + + def __deepcopy__(self, memo): + if id(self) in memo: + return memo[id(self)] + else: + result = type(self)(self.data.clone(), self.requires_grad) + memo[id(self)] = result + return result + + def __repr__(self): + return "Parameter containing:\n" + super().__repr__() diff --git a/ivy/functional/frontends/torch/pointwise_ops.py b/ivy/functional/frontends/torch/pointwise_ops.py index 999c815825345..9c0c4601c3522 100644 --- a/ivy/functional/frontends/torch/pointwise_ops.py +++ b/ivy/functional/frontends/torch/pointwise_ops.py @@ -5,7 +5,12 @@ with_supported_dtypes, ) import ivy.functional.frontends.torch as torch_frontend -from ivy.functional.frontends.torch.func_wrapper import to_ivy_arrays_and_back +from ivy.functional.frontends.torch.func_wrapper import ( + to_ivy_arrays_and_back, +) + + +erfc = torch_frontend.special.erfc @to_ivy_arrays_and_back @@ -13,13 +18,13 @@ def abs(input, *, out=None): return ivy.abs(input, out=out) -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") @to_ivy_arrays_and_back def acos(input, *, out=None): return ivy.acos(input, out=out) -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") @to_ivy_arrays_and_back def acosh(input, *, out=None): return ivy.acosh(input, out=out) @@ -35,13 +40,13 @@ def add(input, other, *, alpha=1, out=None): @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") def addcdiv(input, tensor1, tensor2, *, value=1, out=None): return ivy.add(input, ivy.multiply(value, ivy.divide(tensor1, tensor2)), out=out) @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") def addcmul(input, tensor1, tensor2, *, value=1, out=None): return ivy.add(input, ivy.multiply(value, ivy.multiply(tensor1, tensor2)), out=out) @@ -51,32 +56,32 @@ def angle(input, *, out=None): return ivy.angle(input, out=out) -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") @to_ivy_arrays_and_back def asin(input, *, out=None): return ivy.asin(input, out=out) -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") @to_ivy_arrays_and_back def asinh(input, *, out=None): return ivy.asinh(input, out=out) -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") @to_ivy_arrays_and_back def atan(input, *, out=None): return ivy.atan(input, out=out) -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") @to_ivy_arrays_and_back def atan2(input, other, *, out=None): input, other = torch_frontend.promote_types_of_torch_inputs(input, other) return ivy.atan2(input, other, out=out) -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") @to_ivy_arrays_and_back def atanh(input, *, out=None): return ivy.atanh(input, out=out) @@ -117,13 +122,13 @@ def bitwise_xor(input, other, *, out=None): return ivy.bitwise_xor(input, other, out=out) -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") @to_ivy_arrays_and_back def ceil(input, *, out=None): return ivy.ceil(input, out=out) -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "complex")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "complex")}, "torch") @to_ivy_arrays_and_back def clamp(input, min=None, max=None, *, out=None): ivy.utils.assertions.check_all_or_any_fn( @@ -152,7 +157,7 @@ def copysign(input, other, *, out=None): return ivy.copysign(input, other, out=out) -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") @to_ivy_arrays_and_back def cos(input, *, out=None): return ivy.cos(input, out=out) @@ -181,31 +186,25 @@ def div(input, other, *, rounding_mode=None, out=None): return ivy.divide(input, other, out=out) -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "complex")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "complex")}, "torch") @to_ivy_arrays_and_back def erf(input, *, out=None): return ivy.erf(input, out=out) -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "complex")}, "torch") -@to_ivy_arrays_and_back -def erfc(input, *, out=None): - return 1.0 - ivy.erf(input, out=out) - - -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") @to_ivy_arrays_and_back def exp(input, *, out=None): return ivy.exp(input, out=out) -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") @to_ivy_arrays_and_back def exp2(input, out=None): return ivy.exp2(input, out=out) -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") @to_ivy_arrays_and_back def expm1(input, out=None): return ivy.expm1(input, out=out) @@ -223,7 +222,7 @@ def float_power(input, exponent, *, out=None): return ivy.float_power(input, exponent, out=out) -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") @to_ivy_arrays_and_back def floor(input, *, out=None): return ivy.floor(input, out=out) @@ -234,7 +233,7 @@ def floor_divide(input, other, *, out=None): return ivy.floor_divide(input, other, out=out) -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") @to_ivy_arrays_and_back def fmod(x1, x2, out=None): return ivy.fmod(x1, x2, out=out) @@ -245,31 +244,31 @@ def frac(input, *, out=None): return input - ivy.sign(input) * ivy.floor(ivy.abs(input)) -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") @to_ivy_arrays_and_back def frexp(input, *, out=None): return ivy.frexp(input, out=out) -@with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "torch") @to_ivy_arrays_and_back def gradient(input, *, spacing=1, dim=None, edge_order=1): return ivy.gradient(input, spacing=spacing, edge_order=edge_order, axis=dim) -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") @to_ivy_arrays_and_back def hypot(input, other, *, out=None): return ivy.hypot(input, other, out=out) -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") @to_ivy_arrays_and_back def i0(input, *, out=None): return ivy.i0(input, out=out) -@with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "torch") @to_ivy_arrays_and_back def igamma(input, other, *, out=None): return ivy.igamma(input, x=other, out=out) @@ -280,7 +279,7 @@ def imag(input): return ivy.imag(input) -@with_supported_dtypes({"2.1.0 and below": ("float16", "float32", "float64")}, "torch") +@with_supported_dtypes({"2.2 and below": ("float16", "float32", "float64")}, "torch") @to_ivy_arrays_and_back def ldexp(input, other, *, out=None): value = ivy.pow(2, other, out=out) @@ -288,49 +287,49 @@ def ldexp(input, other, *, out=None): return value -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") @to_ivy_arrays_and_back def lerp(input, end, weight, *, out=None): return ivy.lerp(input, end, weight, out=out) -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") @to_ivy_arrays_and_back def lgamma(input, *, out=None): return ivy.lgamma(input, out=out) @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def log(input, *, out=None): return ivy.log(input, out=out) -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") @to_ivy_arrays_and_back def log10(input, *, out=None): return ivy.log10(input, out=out) -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") @to_ivy_arrays_and_back def log1p(input, *, out=None): return ivy.log1p(input, out=out) -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") @to_ivy_arrays_and_back def log2(input, *, out=None): return ivy.log2(input, out=out) -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") @to_ivy_arrays_and_back def logaddexp(x1, x2, out=None): return ivy.logaddexp(x1, x2, out=out) -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") @to_ivy_arrays_and_back def logaddexp2(x1, x2, out=None): return ivy.logaddexp2(x1, x2, out=out) @@ -359,13 +358,13 @@ def logical_xor(input, other, *, out=None): return ivy.logical_xor(input, other, out=out) -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") @to_ivy_arrays_and_back def logit(input, eps=None, *, out=None): return ivy.logit(input, eps=eps, out=out) -@with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "torch") @to_ivy_arrays_and_back def masked_fill(input, mask, value): return ivy.where(mask, value, input, out=input) @@ -378,7 +377,7 @@ def mul(input, other, *, out=None): @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def mvlgamma(input, p, *, out=None): ivy.assertions.check_greater( p, 1, allow_equal=True, message="p has to be greater than or equal to 1" @@ -393,19 +392,19 @@ def mvlgamma(input, p, *, out=None): ) -@with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, "tensorflow") +@with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "tensorflow") @to_ivy_arrays_and_back def nan_to_num(input, nan=0.0, posinf=None, neginf=None, *, out=None): return ivy.nan_to_num(input, nan=nan, posinf=posinf, neginf=neginf, out=out) -@with_unsupported_dtypes({"2.1.0 and below": ("bool",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("bool",)}, "torch") @to_ivy_arrays_and_back def negative(input, *, out=None): return ivy.negative(input, out=out) -@with_unsupported_dtypes({"2.1.0 and below": ("bfloat16", "float16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("bfloat16", "float16")}, "torch") @to_ivy_arrays_and_back def nextafter(input, other, *, out=None): input, other = torch_frontend.promote_types_of_torch_inputs(input, other) @@ -417,7 +416,7 @@ def positive(input, *, out=None): return ivy.positive(input, out=out) -@with_unsupported_dtypes({"2.1.0 and below": ("bool",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("bool",)}, "torch") @to_ivy_arrays_and_back def pow(input, exponent, *, out=None): if not ivy.is_array(exponent): @@ -460,16 +459,16 @@ def remainder(input, other, *, out=None): return ivy.remainder(input, other, out=out) -@with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "torch") @to_ivy_arrays_and_back def round(input, *, decimals=0, out=None): m = ivy.full(input.shape, 10.0**decimals) upscale = ivy.multiply(input, m) rounded = ivy.round(upscale) - return ivy.divide(rounded, m, out=out) + return ivy.divide(rounded, m, out=out).astype(input.dtype) -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") @to_ivy_arrays_and_back def rsqrt(input, *, out=None): return ivy.reciprocal(ivy.sqrt(input), out=out) @@ -488,43 +487,43 @@ def sgn(input, *, out=None): return ivy.sign(input, out=out) -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") @to_ivy_arrays_and_back def sigmoid(input, *, out=None): return ivy.sigmoid(input, out=out) -@with_unsupported_dtypes({"2.1.0 and below": ("complex",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("complex",)}, "torch") @to_ivy_arrays_and_back def sign(input, *, out=None): return ivy.sign(input, out=out) -@with_unsupported_dtypes({"2.1.0 and below": ("complex",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("complex",)}, "torch") @to_ivy_arrays_and_back def signbit(input, *, out=None): return ivy.signbit(input, out=out) -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") @to_ivy_arrays_and_back def sin(input, *, out=None): return ivy.sin(input, out=out) -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") @to_ivy_arrays_and_back def sinc(input, *, out=None): return ivy.sinc(input, out=out) -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") @to_ivy_arrays_and_back def sinh(input, *, out=None): return ivy.sinh(input, out=out) -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") @to_ivy_arrays_and_back def sqrt(input, *, out=None): return ivy.sqrt(input, out=out) @@ -541,13 +540,13 @@ def subtract(input, other, *, alpha=1, out=None): return ivy.subtract(input, other * alpha, out=out) -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") @to_ivy_arrays_and_back def tan(input, *, out=None): return ivy.tan(input, out=out) -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") @to_ivy_arrays_and_back def tanh(input, *, out=None): return ivy.tanh(input, out=out) @@ -559,13 +558,13 @@ def true_divide(input, other, *, out=None): return ivy.divide(input, other, out=out) -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") @to_ivy_arrays_and_back def trunc(input, *, out=None): return ivy.trunc(input, out=out) -@with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, "tensorflow") +@with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "tensorflow") @to_ivy_arrays_and_back def xlogy(input, other, *, out=None): return ivy.xlogy(input, other, out=out) diff --git a/ivy/functional/frontends/torch/random_sampling.py b/ivy/functional/frontends/torch/random_sampling.py index aaeff665c3618..105e983209e64 100644 --- a/ivy/functional/frontends/torch/random_sampling.py +++ b/ivy/functional/frontends/torch/random_sampling.py @@ -5,7 +5,7 @@ @with_supported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "float32", "float64", ) @@ -13,9 +13,9 @@ "torch", ) @to_ivy_arrays_and_back -def bernoulli(input, *, generator=None, out=None): +def bernoulli(input, p, *, generator=None, out=None): seed = generator.initial_seed() if generator is not None else None - return ivy.bernoulli(input, seed=seed, out=out) + return ivy.bernoulli(p, logits=input, seed=seed, out=out) @to_ivy_arrays_and_back @@ -26,7 +26,7 @@ def manual_seed(seed: int): @with_supported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "float32", "float64", ) @@ -49,7 +49,7 @@ def multinomial(input, num_samples, replacement=False, *, generator=None, out=No @with_supported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "float32", "float64", ) @@ -64,7 +64,7 @@ def normal(mean, std, *, generator=None, out=None): @with_supported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "float32", "float64", ) @@ -91,11 +91,11 @@ def rand( ): if not size and "size" not in kwargs: raise ValueError("Missing 1 required positional/keyword argument: size") - size = kwargs["size"] if not size else size + size = size if size else kwargs["size"] if ( isinstance(size, (list, tuple)) and len(size) == 1 - and isinstance(size[0], (list, tuple)) + and isinstance(size[0], (list, tuple, ivy.Shape)) ): size = size[0] seed = generator.initial_seed() if generator is not None else None @@ -191,11 +191,11 @@ def randn( ): if not size and "size" not in kwargs: raise ValueError("Missing 1 required positional/keyword argument: size") - size = kwargs["size"] if not size else size + size = size if size else kwargs["size"] if ( isinstance(size, (list, tuple)) and len(size) == 1 - and isinstance(size[0], (list, tuple)) + and isinstance(size[0], (list, tuple, ivy.Shape)) ): size = size[0] seed = generator.initial_seed() if generator is not None else None @@ -255,6 +255,10 @@ def seed() -> int: return int(ivy.randint(-(2**63), 2**63 - 1)) +@with_supported_dtypes( + {"2.2 and below": ("uint8",)}, + "torch", +) @to_ivy_arrays_and_back def set_rng_state(new_state): return ivy.seed(seed_value=new_state) diff --git a/ivy/functional/frontends/torch/reduction_ops.py b/ivy/functional/frontends/torch/reduction_ops.py index ea414e1e233a0..564bbca97f9cc 100644 --- a/ivy/functional/frontends/torch/reduction_ops.py +++ b/ivy/functional/frontends/torch/reduction_ops.py @@ -18,12 +18,14 @@ def all(input, dim=None, keepdim=False, *, out=None): return ret +@with_unsupported_dtypes({"2.2 and below": ("complex",)}, "torch") @numpy_to_torch_style_args @to_ivy_arrays_and_back def amax(input, dim=None, keepdim=False, *, out=None): return ivy.max(input, axis=dim, keepdims=keepdim, out=out) +@with_unsupported_dtypes({"2.2 and below": ("complex",)}, "torch") @numpy_to_torch_style_args @to_ivy_arrays_and_back def amin(input, dim=None, keepdim=False, *, out=None): @@ -32,7 +34,7 @@ def amin(input, dim=None, keepdim=False, *, out=None): @numpy_to_torch_style_args @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16", "complex")}, "torch") def aminmax(input, *, dim=None, keepdim=False, out=None): minmax_tuple = namedtuple("minmax", ["min", "max"]) return minmax_tuple( @@ -51,7 +53,7 @@ def any(input, dim=None, keepdim=False, *, out=None): return ret -@with_unsupported_dtypes({"2.1.0 and below": ("complex", "bool")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("complex", "bool")}, "torch") @numpy_to_torch_style_args @to_ivy_arrays_and_back def argmax(input, dim=None, keepdim=False): @@ -67,7 +69,7 @@ def argmin(input, dim=None, keepdim=False): @numpy_to_torch_style_args @to_ivy_arrays_and_back @with_unsupported_dtypes( - {"2.1.0 and below": ("uint8", "int8")}, + {"2.2 and below": ("uint8", "int8")}, "torch", ) def count_nonzero(input, dim=None): @@ -98,11 +100,25 @@ def logsumexp(input, dim, keepdim=False, *, out=None): @numpy_to_torch_style_args @to_ivy_arrays_and_back +@with_unsupported_dtypes( + {"2.2 and below": ("complex64", "complex128")}, + "torch", +) def max(*input, dim=None, keepdim=False, out=None): if len(input) == 1: input = input[0] elif len(input) == 2: - return torch_frontend.maximum(*input) + input_0 = input[0] + input_1 = input[1] + if ivy.is_array(input_1): + return torch_frontend.maximum(*input) + else: + input = input_0 + dim = input_1 + else: + input = input[0] + dim = input[1] + keepdim = input[2] if dim is None: return ivy.max(input, axis=dim, keepdims=keepdim, out=out) elif out is not None: @@ -127,6 +143,7 @@ def mean(input, dim=None, keepdim=False, *, dtype=None, out=None): return ivy.mean(input, axis=dim, keepdims=keepdim, out=out) +@with_unsupported_dtypes({"2.2 and below": ("complex", "float16", "bool")}, "torch") @numpy_to_torch_style_args @to_ivy_arrays_and_back def median(input, dim=None, keepdim=False, *, out=None): @@ -162,11 +179,25 @@ def median(input, dim=None, keepdim=False, *, out=None): @numpy_to_torch_style_args @to_ivy_arrays_and_back +@with_unsupported_dtypes( + {"2.2 and below": ("complex64", "complex128")}, + "torch", +) def min(*input, dim=None, keepdim=False, out=None): if len(input) == 1: input = input[0] elif len(input) == 2: - return torch_frontend.minimum(*input) + input_0 = input[0] + input_1 = input[1] + if ivy.is_array(input_1): + return torch_frontend.minimum(*input) + else: + input = input_0 + dim = input_1 + else: + input = input[0] + dim = input[1] + keepdim = input[2] if dim is None: return ivy.min(input, axis=dim, keepdims=keepdim, out=out) elif out is not None: @@ -186,6 +217,7 @@ def moveaxis(input, source, destination): return ivy.moveaxis(input, source, destination) +@with_supported_dtypes({"2.2 and below": ("float",)}, "torch") @numpy_to_torch_style_args @to_ivy_arrays_and_back def nanmean(input, dim=None, keepdim=False, *, dtype=None, out=None): @@ -230,7 +262,7 @@ def nanmedian(input, dim=None, keepdim=False, *, out=None): @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.0 and below": ("float", "int")}, + {"2.2 and below": ("float", "int")}, "torch", ) def nansum(input, dim=None, keepdim=False, *, dtype=None): @@ -240,7 +272,7 @@ def nansum(input, dim=None, keepdim=False, *, dtype=None): @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.0 and below": ("float", "complex")}, + {"2.2 and below": ("float", "complex")}, "torch", ) def norm(input, p="fro", dim=None, keepdim=False, out=None, dtype=None): @@ -266,7 +298,7 @@ def norm(input, p="fro", dim=None, keepdim=False, out=None, dtype=None): @to_ivy_arrays_and_back @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "float16", "bfloat16", ) @@ -282,7 +314,7 @@ def prod(input, dim=None, keepdim=False, *, dtype=None): @numpy_to_torch_style_args @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") def quantile(input, q, dim=None, keepdim=False, *, interpolation="linear", out=None): return ivy.quantile( input, q, axis=dim, keepdims=keepdim, interpolation=interpolation, out=out @@ -291,14 +323,14 @@ def quantile(input, q, dim=None, keepdim=False, *, interpolation="linear", out=N @numpy_to_torch_style_args @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bool", "integer")}, "torch") def std(input, dim=None, unbiased=True, keepdim=False, *, out=None): return ivy.std(input, axis=dim, correction=int(unbiased), keepdims=keepdim, out=out) @numpy_to_torch_style_args @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "torch") def std_mean(input, dim, unbiased, keepdim=False, *, out=None): temp_std = ivy.std( input, axis=dim, correction=int(unbiased), keepdims=keepdim, out=out @@ -313,37 +345,26 @@ def sum(input, dim=None, keepdim=False, *, dtype=None, out=None): return ivy.sum(input, axis=dim, dtype=dtype, keepdims=keepdim, out=out) +@with_unsupported_dtypes({"2.2 and below": ("complex",)}, "torch") @to_ivy_arrays_and_back def unique(input, sorted=True, return_inverse=False, return_counts=False, dim=None): if dim is not None: sorted = True results = ivy.unique_all(input, axis=dim, by_value=sorted) - - fields = ["output"] - if return_inverse: - fields.append("inverse_indices") - if return_counts: - fields.append("counts") - - Results = namedtuple("Results", fields) - - values = [results.values] + ret = (results.values,) if return_counts or return_inverse else results.values if return_inverse: inverse_indices = results.inverse_indices - if dim is None: inverse_indices = inverse_indices.reshape(input.shape) - - values.append(inverse_indices) + ret += (inverse_indices,) if return_counts: - values.append(results.counts) - - return Results(*values) + ret += (results.counts,) + return ret @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "float16", "complex", ) @@ -351,7 +372,7 @@ def unique(input, sorted=True, return_inverse=False, return_counts=False, dim=No "torch", ) @to_ivy_arrays_and_back -def unique_consecutive(input, return_inverse, return_counts, dim): +def unique_consecutive(input, return_inverse=False, return_counts=False, dim=None): output, inverse_indices, counts = ivy.unique_consecutive(input, axis=dim) ret = (output,) if return_inverse: @@ -365,7 +386,7 @@ def unique_consecutive(input, return_inverse, return_counts, dim): @to_ivy_arrays_and_back @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "float16", "bfloat16", ) @@ -380,7 +401,7 @@ def var(input, dim, unbiased, keepdim=False, *, out=None): @to_ivy_arrays_and_back @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "float16", "bfloat16", ) diff --git a/ivy/functional/frontends/torch/special/__init__.py b/ivy/functional/frontends/torch/special/__init__.py new file mode 100644 index 0000000000000..7dc36a681a948 --- /dev/null +++ b/ivy/functional/frontends/torch/special/__init__.py @@ -0,0 +1 @@ +from .special_funcs import * diff --git a/ivy/functional/frontends/torch/special/special_funcs.py b/ivy/functional/frontends/torch/special/special_funcs.py new file mode 100644 index 0000000000000..738fcaf278fa2 --- /dev/null +++ b/ivy/functional/frontends/torch/special/special_funcs.py @@ -0,0 +1,25 @@ +import ivy +from ivy.func_wrapper import ( + with_unsupported_dtypes, +) +from ivy.functional.frontends.torch.func_wrapper import ( + to_ivy_arrays_and_back, +) + + +@with_unsupported_dtypes({"2.2 and below": ("float16", "complex")}, "torch") +@to_ivy_arrays_and_back +def erfc(input, *, out=None): + return 1.0 - ivy.erf(input, out=out) + + +@with_unsupported_dtypes({"2.2 and below": ("float16", "complex", "bfloat16")}, "torch") +@to_ivy_arrays_and_back +def erfcx(input, *, out=None): + ret = erfc(input) * ivy.exp(input**2) + return ret + + +@to_ivy_arrays_and_back +def erfinv(input, *, out=None): + return ivy.erfinv(input, out=out) diff --git a/ivy/functional/frontends/torch/spectral_ops.py b/ivy/functional/frontends/torch/spectral_ops.py index 8727252e94d46..65d0e10d1b3ca 100644 --- a/ivy/functional/frontends/torch/spectral_ops.py +++ b/ivy/functional/frontends/torch/spectral_ops.py @@ -1,6 +1,6 @@ import ivy +from ivy.func_wrapper import with_supported_dtypes, with_unsupported_dtypes from ivy.functional.frontends.torch.func_wrapper import to_ivy_arrays_and_back -from ivy.func_wrapper import with_supported_dtypes @to_ivy_arrays_and_back @@ -46,6 +46,22 @@ def blackman_window( return ivy.blackman_window(window_length, periodic=periodic, dtype=dtype) +@to_ivy_arrays_and_back +@with_unsupported_dtypes({"1.11.0 and below": ("float16",)}, "torch") +def hamming_window( + window_length, + periodic=True, + alpha=0.54, + beta=0.46, +): + return ivy.hamming_window( + window_length, + periodic=periodic, + alpha=alpha, + beta=beta, + ) + + @to_ivy_arrays_and_back @with_supported_dtypes({"2.51.0 and below": ("float32", "float64")}, "torch") def kaiser_window( diff --git a/ivy/functional/frontends/torch/tensor.py b/ivy/functional/frontends/torch/tensor.py index e80786ca4e0e3..d7ffcf14ea36f 100644 --- a/ivy/functional/frontends/torch/tensor.py +++ b/ivy/functional/frontends/torch/tensor.py @@ -5,12 +5,12 @@ # local import ivy import ivy.functional.frontends.torch as torch_frontend -import ivy.functional.frontends.torch.nn.functional as torch_frontend_nn from ivy.functional.frontends.numpy.creation_routines.from_existing_data import ( array as np_frontend_array, ) from ivy.func_wrapper import with_unsupported_dtypes from ivy.func_wrapper import with_supported_dtypes +from ivy.func_wrapper import with_supported_device_and_dtypes from ivy.functional.frontends.torch.func_wrapper import ( _to_ivy_array, numpy_to_torch_style_args, @@ -44,6 +44,9 @@ def __repr__(self): "ivy.array", "ivy.frontends.torch.Tensor" ) + def __hash__(self): + return id(self) + # Properties # # ---------- # @@ -81,6 +84,10 @@ def T(self): return self return torch_frontend.permute(self, list(range(self.ndim))[::-1]) + @property + def mH(self): + return torch_frontend.adjoint(self) + @property def data(self): return torch_frontend.tensor( @@ -134,26 +141,28 @@ def reshape(self, *args, shape=None): if shape is not None: return torch_frontend.reshape(self, shape) if args: - if isinstance(args[0], (tuple, list, ivy.Shape)): + if isinstance(args[0], (tuple, list, ivy.Shape, ivy.NativeShape)): shape = args[0] return torch_frontend.reshape(self, shape) else: return torch_frontend.reshape(self, args) - return torch_frontend.reshape(self) + else: + raise ValueError("reshape() got no values for argument 'shape'") - @with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "torch") + @with_unsupported_dtypes({"2.6.0 and below": ("float16",)}, "paddle") def reshape_as(self, other): return torch_frontend.reshape(self, other.shape) - @with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "torch") def add(self, other, *, alpha=1): return torch_frontend.add(self, other, alpha=alpha) - # @with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, "torch") + # @with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "torch") def divide(self, other, *, out=None): return torch_frontend.divide(self, other, out=out) - @with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "torch") def sub(self, other, *, alpha=1): return torch_frontend.sub(self, other, alpha=alpha) @@ -168,111 +177,110 @@ def any(self, dim=None, keepdim=False): def all(self, dim=None, keepdim=False): return torch_frontend.all(self, dim=dim, keepdim=keepdim) - @with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "torch") def add_(self, other, *, alpha=1): self.ivy_array = self.add(other, alpha=alpha).ivy_array return self - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def addmm(self, mat1, mat2, *, beta=1, alpha=1): return torch_frontend.addmm(self, mat1, mat2, beta=beta, alpha=alpha) - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def addmm_(self, mat1, mat2, *, beta=1, alpha=1): self.ivy_array = self.addmm(mat1, mat2, beta=beta, alpha=alpha).ivy_array return self - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def addmv(self, mat, vec, *, beta=1, alpha=1): return torch_frontend.addmv(self, mat, vec, beta=beta, alpha=alpha) - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def addmv_(self, mat, vec, *, beta=1, alpha=1): self.ivy_array = torch_frontend.addmv( self, mat, vec, beta=beta, alpha=alpha ).ivy_array return self - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def addbmm(self, batch1, batch2, *, beta=1, alpha=1): return torch_frontend.addbmm(self, batch1, batch2, beta=beta, alpha=alpha) - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def addbmm_(self, batch1, batch2, *, beta=1, alpha=1): self.ivy_array = self.addbmm(batch1, batch2, beta=beta, alpha=alpha).ivy_array return self - @with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "torch") def subtract_(self, other, *, alpha=1): self.ivy_array = self.sub(other, alpha=alpha).ivy_array return self - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def asin(self): return torch_frontend.asin(self) - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def asin_(self): self.ivy_array = self.asin().ivy_array return self @numpy_to_torch_style_args - @with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "torch") def sum(self, dim=None, keepdim=False, *, dtype=None): return torch_frontend.sum(self, dim=dim, keepdim=keepdim, dtype=dtype) - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def sin(self): return torch_frontend.sin(self) - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def sin_(self): self.ivy_array = self.sin().ivy_array return self - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def sinh(self): return torch_frontend.sinh(self) - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def sinh_(self): self.ivy_array = self.sinh().ivy_array return self - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def cos(self): return torch_frontend.cos(self) - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def cos_(self): self.ivy_array = self.cos().ivy_array return self - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def cosh(self): return torch_frontend.cosh(self) - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def cosh_(self): self.ivy_array = self.cosh().ivy_array return self - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def atan(self): return torch_frontend.atan(self) - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def atan_(self): self.ivy_array = self.atan().ivy_array return self - @with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") def atan2(self, other): return torch_frontend.atan2(self, other) def view(self, *args, size=None): - """ - Reshape Tensor. + """Reshape Tensor. possible arguments are either: - size @@ -280,6 +288,7 @@ def view(self, *args, size=None): - list of ints - torch.Size object - ints + Parameters ---------- args:int arguments @@ -292,7 +301,7 @@ def view(self, *args, size=None): shape_tup = size elif args and not ivy.exists(size): if ( - isinstance(args[0], (tuple, list, ivy.Shape)) + isinstance(args[0], (tuple, list, ivy.Shape, ivy.NativeShape)) or type(args[0]).__name__ == "Size" ) and len(args) == 1: shape_tup = args[0] @@ -312,56 +321,56 @@ def float(self, memory_format=None): def double(self): return self.to(torch_frontend.float64) - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def asinh(self): return torch_frontend.asinh(self) - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def asinh_(self): self.ivy_array = self.asinh().ivy_array return self - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def tan(self): return torch_frontend.tan(self) - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def tan_(self): self.ivy_array = self.tan().ivy_array return self - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def tanh(self): return torch_frontend.tanh(self) - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def tanh_(self): self.ivy_array = self.tanh().ivy_array return self - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def atanh(self): return torch_frontend.atanh(self) - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def atanh_(self): self.ivy_array = self.atanh().ivy_array return self - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def log(self): return torch_frontend.log(self) - @with_supported_dtypes({"2.1.0 and below": ("float32", "float64")}, "torch") + @with_supported_dtypes({"2.2 and below": ("float32", "float64")}, "torch") def log2_(self): self.ivy_array = self.log2().ivy_array return self - @with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") def logit(self): return torch_frontend.logit(self) - @with_unsupported_dtypes({"2.1.0 and below": ("bfloat16", "uint16")}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bfloat16", "uint16")}, "torch") def copy_(self, other, non_blocking=False): ivy.utils.assertions.check_one_way_broadcastable( self.ivy_array.shape, torch_frontend.tensor(other).ivy_array.shape @@ -369,31 +378,31 @@ def copy_(self, other, non_blocking=False): self._ivy_array = torch_frontend.tensor(other).ivy_array return self - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def log_(self): self.ivy_array = self.log().ivy_array return self - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def log2(self): return torch_frontend.log2(self) - @with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") def relu(self): - return torch_frontend_nn.relu(self) + return torch_frontend.nn.functional.relu(self) @numpy_to_torch_style_args - @with_unsupported_dtypes({"2.1.0 and below": ("complex",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("complex",)}, "torch") def amax(self, dim=None, keepdim=False): return torch_frontend.amax(self, dim=dim, keepdim=keepdim) @numpy_to_torch_style_args - @with_unsupported_dtypes({"2.1.0 and below": ("complex",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("complex",)}, "torch") def amin(self, dim=None, keepdim=False): return torch_frontend.amin(self, dim=dim, keepdim=keepdim) @numpy_to_torch_style_args - @with_unsupported_dtypes({"2.1.0 and below": ("complex", "float16")}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("complex", "float16")}, "torch") def aminmax(self, dim=None, keepdim=False): return torch_frontend.aminmax(self, dim=dim, keepdim=keepdim) @@ -404,7 +413,7 @@ def abs_(self): self.ivy_array = self.abs().ivy_array return self - @with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "torch") def logical_and(self, other): return torch_frontend.logical_and(self, other) @@ -415,24 +424,28 @@ def logical_not_(self): self.ivy_array = ivy.astype(self.logical_not().ivy_array, self.dtype) return self - @with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "torch") def logical_or(self, other): return torch_frontend.logical_or(self, other) + @with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "torch") + def logical_xor(self, other): + return torch_frontend.logical_xor(self, other) + def bitwise_not(self): return torch_frontend.bitwise_not(self) def bitwise_and(self, other): return torch_frontend.bitwise_and(self, other) - @with_supported_dtypes({"2.1.0 and below": ("integer",)}, "torch") + @with_supported_dtypes({"2.2 and below": ("integer",)}, "torch") def bitwise_or(self, other): return torch_frontend.bitwise_or(self, other) def bitwise_left_shift(self, other): return torch_frontend.bitwise_left_shift(self, other) - @with_supported_dtypes({"2.1.0 and below": ("integer",)}, "torch") + @with_supported_dtypes({"2.2 and below": ("integer",)}, "torch") def bitwise_or_(self, other): self.ivy_array = self.bitwise_or(other).ivy_array return self @@ -455,18 +468,22 @@ def new_ones( if device is None: device = self.device if size is None: - size = args[0] if isinstance(args[0], (tuple, list, ivy.Shape)) else args + size = ( + args[0] + if isinstance(args[0], (tuple, list, ivy.Shape, ivy.NativeShape)) + else args + ) return torch_frontend.ones( size, dtype=dtype, device=device, requires_grad=requires_grad ) - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def floor(self, *, out=None): return torch_frontend.floor(self) @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "bfloat16", "uint8", "uint32", @@ -483,7 +500,7 @@ def not_equal(self, other, *, out=None): @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "bfloat16", "uint8", "uint32", @@ -499,20 +516,30 @@ def not_equal_(self, other, *, out=None): self.ivy_array = self.not_equal(other).ivy_array return self + def eq(self, other): + return torch_frontend.eq(self, other) + def equal(self, other): return torch_frontend.equal(self, other) - @with_unsupported_dtypes({"2.1.0 and below": ("float16", "complex")}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16", "complex")}, "torch") def erf(self, *, out=None): return torch_frontend.erf(self, out=out) @with_supported_dtypes( - {"2.1.0 and below": ("float32", "float64", "bfloat16")}, "torch" + {"2.2 and below": ("float32", "float64", "bfloat16")}, "torch" ) def erf_(self, *, out=None): self.ivy_array = self.erf(out=out).ivy_array return self + @with_supported_device_and_dtypes( + {"2.2 and below": {"cpu": ("float32", "float64")}}, + "torch", + ) + def erfc_(self, *, out=None): + return torch_frontend.erfc(self, out=out) + def new_zeros( self, *args, @@ -549,7 +576,9 @@ def to(self, *args, **kwargs): ) return cast_tensor if ( - isinstance(args[0], (ivy.Dtype, ivy.NativeDtype)) + isinstance(args[0], ivy.NativeDtype) + or isinstance(args[0], ivy.Dtype) + and hasattr(args[0], "as_native_dtype") or args[0] in ivy._all_ivy_dtypes_str ): if self.dtype == ivy.as_ivy_dtype(args[0]): @@ -607,11 +636,11 @@ def to(self, *args, **kwargs): ) return cast_tensor - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def acos(self): return torch_frontend.acos(self) - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def acos_(self): self.ivy_array = self.acos().ivy_array return self @@ -631,7 +660,7 @@ def new_tensor( _data = ivy.asarray(data, copy=True, dtype=dtype, device=device) return torch_frontend.tensor(_data) - @with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "torch") def view_as(self, other): return self.view(size=other.shape) @@ -639,11 +668,14 @@ def expand(self, *args, size=None): if args and size: raise TypeError("expand() got multiple values for argument 'size'") if args: - if isinstance(args[0], (tuple, list, ivy.Shape)): + if isinstance(args[0], (tuple, list, ivy.Shape, ivy.NativeShape)): size = args[0] else: size = args - + if isinstance(size, (tuple, list)): + size = tuple( + s.item() if isinstance(s, torch_frontend.Tensor) else s for s in size + ) return torch_frontend.tensor(ivy.expand(self.ivy_array, tuple(size))) def expand_as(self, other): @@ -660,7 +692,7 @@ def detach_(self): self.ivy_array = self.detach().ivy_array return self - @with_unsupported_dtypes({"2.1.0 and below": ("uint16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("uint16",)}, "torch") @numpy_to_torch_style_args def unsqueeze(self, dim): return torch_frontend.unsqueeze(self, dim) @@ -734,9 +766,20 @@ def new_empty( def unfold(self, dimension, size, step): slices = [] - for i in range(0, self.shape[dimension] - size + 1, step): - slices.append(self.ivy_array[i : i + size]) - return torch_frontend.stack(slices) + self_shape = tuple(self.shape) + for i in range(0, self_shape[dimension] - size + 1, step): + slicing = [slice(None)] * len(self.shape) + slicing[dimension] = slice(i, i + size) + slices.append(self.ivy_array[tuple(slicing)]) + stacked = torch_frontend.stack(slices, dim=dimension) + new_shape = list(self.shape) + num_slices = (self.shape[dimension] - size) // step + 1 + new_shape[dimension] = num_slices + new_shape.insert(dimension + 1, size) + reshaped = stacked.reshape(new_shape) + dims = list(range(len(stacked.shape))) + dims[-2], dims[-1] = dims[-1], dims[-2] + return reshaped.permute(*dims) def long(self, memory_format=None): self.ivy_array = ivy.astype(self.ivy_array, ivy.int64, copy=False) @@ -748,7 +791,7 @@ def max(self, dim=None, keepdim=False): @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "complex", "bfloat16", "bool", @@ -774,36 +817,39 @@ def is_cuda(self): def is_meta(self): return "meta" in ivy.dev(self.ivy_array) - @with_unsupported_dtypes({"2.1.0 and below": ("uint16", "bool")}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("uint16", "bool")}, "torch") def positive(self): return torch_frontend.positive(self) - @with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "torch") def pow(self, exponent): return torch_frontend.pow(self, exponent) - @with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, "torch") + def unflatten(self, dim, sizes): + return torch_frontend.unflatten(self, dim, sizes) + + @with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "torch") def pow_(self, exponent): self.ivy_array = self.pow(exponent).ivy_array return self def size(self, dim=None): - shape = self.shape + shape = self.ivy_array.shape if dim is None: return shape try: return shape[dim] - except IndexError: + except IndexError as e: raise IndexError( f"Dimension out of range (expected to be in range of [{len(shape)}," f" {len(shape) - 1}], but got {dim}" - ) + ) from e def matmul(self, other): return torch_frontend.matmul(self, other) @with_supported_dtypes( - {"2.1.0 and below": ("float32", "float64", "complex32", "complex64")}, "torch" + {"2.2 and below": ("float32", "float64", "complex32", "complex64")}, "torch" ) def matrix_power(self, n, *, out=None): return torch_frontend.linalg.matrix_power(self, n, out=out) @@ -812,20 +858,20 @@ def argwhere(self): return torch_frontend.argwhere(self) @numpy_to_torch_style_args - @with_unsupported_dtypes({"2.1.0 and below": ("complex", "bool")}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("complex", "bool")}, "torch") def argmax(self, dim=None, keepdim=False): return torch_frontend.argmax(self, dim=dim, keepdim=keepdim) @numpy_to_torch_style_args - @with_unsupported_dtypes({"2.1.0 and below": ("complex",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("complex",)}, "torch") def argmin(self, dim=None, keepdim=False): return torch_frontend.argmin(self, dim=dim, keepdim=keepdim) - @with_unsupported_dtypes({"2.1.0 and below": ("complex",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("complex",)}, "torch") def argsort(self, dim=-1, descending=False): return torch_frontend.argsort(self, dim=dim, descending=descending) - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def ceil(self): return torch_frontend.ceil(self) @@ -839,30 +885,31 @@ def permute(self, *args, dims=None): if dims is not None: return torch_frontend.permute(self, dims) if args: - if isinstance(args[0], (tuple, list, ivy.Shape)): + if isinstance(args[0], (tuple, list, ivy.Shape, ivy.NativeShape)): dims = args[0] return torch_frontend.permute(self, dims) else: return torch_frontend.permute(self, args) - return torch_frontend.permute(self) + else: + raise ValueError("permute() got no values for argument 'dims'") @numpy_to_torch_style_args - @with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") def mean(self, dim=None, keepdim=False): return torch_frontend.mean(self, dim=dim, keepdim=keepdim) - @with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "torch") @numpy_to_torch_style_args def nanmean(self, dim=None, keepdim=False): return torch_frontend.nanmean(self, dim=dim, keepdim=keepdim) - @with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "torch") @numpy_to_torch_style_args def nansum(self, dim=None, keepdim=False): return torch_frontend.nansum(self, dim=dim, keepdim=keepdim) @numpy_to_torch_style_args - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def median(self, dim=None, keepdim=False): return torch_frontend.median(self, dim=dim, keepdim=keepdim) @@ -880,35 +927,40 @@ def flatten(self, start_dim=0, end_dim=-1): return torch_frontend.flatten(self, start_dim, end_dim) @numpy_to_torch_style_args - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def cumsum(self, dim, *, dtype=None): return torch_frontend.cumsum(self, dim, dtype=dtype) @numpy_to_torch_style_args - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def cumsum_(self, dim, *, dtype=None): - self.ivy_array = self.cumsum(dim, dtype).ivy_array + self.ivy_array = self.cumsum(dim, dtype=dtype).ivy_array return self - @with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") def inverse(self): return torch_frontend.inverse(self) - @with_unsupported_dtypes({"2.1.0 and below": ("bool", "bfloat16")}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bool", "bfloat16")}, "torch") def neg(self): return torch_frontend.negative(self) - @with_unsupported_dtypes({"2.1.0 and below": ("bool",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bool",)}, "torch") def neg_(self): self.ivy_array = torch_frontend.negative(self).ivy_array return self __neg__ = neg - @with_unsupported_dtypes({"2.1.0 and below": ("bool", "bfloat16")}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bool", "bfloat16")}, "torch") def negative(self): return torch_frontend.negative(self) + @with_unsupported_dtypes({"2.0.1 and below": ("bool", "bfloat16")}, "torch") + def negative_(self): + self.ivy_array = torch_frontend.negative(self).ivy_array + return self + def int(self, memory_format=None): self.ivy_array = ivy.astype(self.ivy_array, ivy.int32, copy=False) return self @@ -928,10 +980,10 @@ def type(self, dtype=None, non_blocking=False, **kwargs): else: return str(self.dtype) - @with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "torch") def type_as(self, other): if self.dtype != other.dtype: - self.ivy_array = ivy.astype(self.ivy_array, other.dtype) + return torch_frontend.tensor(ivy.astype(self.ivy_array, other.dtype)) return self def byte(self, memory_format=None): @@ -943,7 +995,7 @@ def squeeze(self, dim=None): return torch_frontend.squeeze(self, dim) @numpy_to_torch_style_args - @with_unsupported_dtypes({"2.1.0 and below": ("uint16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("uint16",)}, "torch") def squeeze_(self, dim=None): self.ivy_array = self.squeeze(dim).ivy_array return self @@ -967,35 +1019,39 @@ def tril_(self, diagonal=0): def index_select(self, dim, index): return torch_frontend.index_select(self, dim, index) - @with_unsupported_dtypes({"2.1.0 and below": ("float16", "complex")}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16", "complex")}, "torch") def clamp(self, min=None, max=None): return torch_frontend.clamp(self, min=min, max=max) - @with_unsupported_dtypes({"2.1.0 and below": ("float16", "complex")}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16", "complex")}, "torch") def clamp_(self, min=None, max=None): self.ivy_array = self.clamp(min=min, max=max).ivy_array return self @with_unsupported_dtypes( - {"2.1.0 and below": ("bool", "bfloat16", "float16", "complex")}, "torch" + {"2.2 and below": ("bool", "bfloat16", "float16", "complex")}, "torch" ) def clamp_min(self, min=None): return torch_frontend.clamp(self, min=min) - @with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") + def clamp_min_(self, min=None): + self.ivy_array = self.clamp_min(min).ivy_array + return self + + @with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") def sqrt(self): return torch_frontend.sqrt(self) - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def rsqrt(self): return torch_frontend.rsqrt(self) - @with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") def rsqrt_(self): self.ivy_array = self.rsqrt().ivy_array return self - @with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") def sqrt_(self): self.ivy_array = self.sqrt().ivy_array return self @@ -1006,7 +1062,7 @@ def where(self, condition, other): def clone(self, memory_format=None): return torch_frontend.tensor(ivy.array(self.ivy_array, copy=True)) - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def acosh(self): return torch_frontend.acosh(self) @@ -1019,38 +1075,38 @@ def masked_fill_(self, mask, value): self.ivy_array = self.masked_fill(mask, value).ivy_array return self - @with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") def index_add_(self, dim, index, source, *, alpha=1): self.ivy_array = torch_frontend.index_add( self, dim, index, source, alpha=alpha ).ivy_array return self - @with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") def index_add(self, dim, index, source, *, alpha=1): return torch_frontend.index_add( self._ivy_array, dim, index, source, alpha=alpha ) - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def acosh_(self): self.ivy_array = self.acosh().ivy_array return self - @with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "torch") def numpy(self): return np_frontend_array(self.ivy_array) - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def sigmoid(self): return torch_frontend.sigmoid(self) - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def sigmoid_(self): self.ivy_array = self.sigmoid().ivy_array return self - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def softmax(self, dim=None, dtype=None): return torch_frontend.nn.functional.softmax(self, dim=dim, dtype=dtype) @@ -1063,7 +1119,7 @@ def repeat(self, *args, repeats=None): "repeat() got multiple values for argument 'repeats'" ) if args: - if isinstance(args[0], (tuple, list, ivy.Shape)): + if isinstance(args[0], (tuple, list, ivy.Shape, ivy.NativeShape)): repeats = args[0] else: repeats = args @@ -1082,7 +1138,7 @@ def remainder(self, other, *, out=None): return torch_frontend.remainder(self, other, out=out) @with_supported_dtypes( - {"2.1.0 and below": ("float16", "float32", "float64", "bfloat16")}, "torch" + {"2.2 and below": ("float16", "float32", "float64", "bfloat16")}, "torch" ) def reciprocal_(self): self.ivy_array = torch_frontend.reciprocal(self).ivy_array @@ -1100,35 +1156,42 @@ def bitwise_and_(self, other): self.ivy_array = self.bitwise_and(other).ivy_array return self - @with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") def atan2_(self, other): self.ivy_array = self.atan2(other).ivy_array return self - @with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "torch") def fmax(self, other): return torch_frontend.fmax(self, other) def fmin(self, other): return torch_frontend.fmin(self, other) + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") + def log_softmax(self, dim=None, _stack_level=3, dtype=None): + return torch_frontend.nn.functional.log_softmax(self, dim=dim, dtype=dtype) + + def isfinite(self): + return torch_frontend.isfinite(self) + def msort(self): return torch_frontend.msort(self) - @with_unsupported_dtypes({"2.1.0 and below": ("float16", "complex")}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16", "complex")}, "torch") def trunc(self): return torch_frontend.trunc(self) - @with_unsupported_dtypes({"2.1.0 and below": ("float16", "complex")}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16", "complex")}, "torch") def trunc_(self): self.ivy_array = self.trunc().ivy_array return self - @with_unsupported_dtypes({"2.1.0 and below": ("float16", "complex")}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16", "complex")}, "torch") def fix(self): return torch_frontend.fix(self) - @with_unsupported_dtypes({"2.1.0 and below": ("float16", "complex")}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16", "complex")}, "torch") def fix_(self): self.ivy_array = self.fix().ivy_array return self @@ -1139,11 +1202,11 @@ def isinf(self): def is_complex(self): return torch_frontend.is_complex(self._ivy_array) - @with_unsupported_dtypes({"2.1.0 and below": ("uint16", "bfloat16")}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("uint16", "bfloat16")}, "torch") def is_floating_point(self): return torch_frontend.is_floating_point(self._ivy_array) - @with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "torch") def isreal(self): return torch_frontend.isreal(self._ivy_array) @@ -1154,38 +1217,49 @@ def addr_(self, vec1, vec2, *, beta=1, alpha=1): self.ivy_array = self.addr(vec1, vec2, beta=beta, alpha=alpha).ivy_array return self - @with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") def dot(self, tensor): return torch_frontend.dot(self, tensor) - @with_supported_dtypes({"2.1.0 and below": ("float32", "float64")}, "torch") - def bernoulli(self, *, generator=None, out=None): - return torch_frontend.bernoulli(self._ivy_array, generator=generator, out=out) + @with_supported_dtypes({"2.2 and below": ("float32", "float64")}, "torch") + def bernoulli(self, p, *, generator=None, out=None): + return torch_frontend.bernoulli( + self._ivy_array, p, generator=generator, out=out + ) + + @with_supported_dtypes({"2.2 and below": ("float32", "float64")}, "torch") + def bernoulli_(self, p, *, generator=None, out=None): + self.ivy_array = self.bernoulli(p, generator=generator, out=out).ivy_array + return self + + def numel(self): + shape = self.shape + return int(ivy.astype(ivy.prod(shape), ivy.int64)) # Special Methods # # -------------------# def __bool__(self): if len(self.shape) == sum(self.shape): - return torch_frontend.tensor(self.ivy_array.to_scalar().__bool__()) + return self.ivy_array.to_scalar().__bool__() raise ValueError( "The truth value of an array with more than one element is ambiguous. " "Use a.any() or a.all()" ) - @with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "torch") def __add__(self, other): return torch_frontend.add(self, other) - @with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "torch") def __mod__(self, other): return torch_frontend.remainder(self, other) - @with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "torch") def __pow__(self, exponent): return self.pow(exponent) - @with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "torch") def __rpow__(self, other): return torch_frontend.pow(other, self) @@ -1207,30 +1281,41 @@ def __iter__(self): for i in range(self.shape[0]): yield self[i] - @with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "torch") def __radd__(self, other): return torch_frontend.add(other, self) - @with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "torch") def __mul__(self, other): return torch_frontend.mul(self, other) - @with_unsupported_dtypes({"2.1.0 and below": "bfloat16"}, "torch") + @with_unsupported_dtypes({"2.2 and below": "bfloat16"}, "torch") def __matmul__(self, other): return torch_frontend.matmul(self, other) - @with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, "torch") + @with_unsupported_dtypes( + { + "2.2 and below": ( + "float16", + "int8", + "int16", + "bool", + "uint8", + ) + }, + "torch", + ) def __rmul__(self, other): return torch_frontend.mul(other, self) - @with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "torch") def __sub__(self, other): return torch_frontend.subtract(self, other) def __truediv__(self, other): return torch_frontend.div(self, other) - @with_unsupported_dtypes({"2.1.0 and below": ("float16", "complex")}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16", "complex")}, "torch") def __floordiv__(self, other): return torch_frontend.floor_divide(self, other) @@ -1285,45 +1370,52 @@ def __float__(self): item = item.real return float(item) - @with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "torch") def __eq__(self, other): return torch_frontend.eq(self, other) - @with_unsupported_dtypes({"2.1.0 and below": ("complex",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("complex",)}, "torch") def __gt__(self, other): return torch_frontend.greater(self, other) - @with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "torch") def __ge__(self, other): return torch_frontend.greater_equal(self, other) - @with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "torch") def __ne__(self, other): return self.ne(other) - @with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "torch") def __rsub__(self, other): return torch_frontend.subtract(other, self) - @with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "torch") def __lt__(self, other): return torch_frontend.less(self, other) - @with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "torch") def __le__(self, other): return torch_frontend.less_equal(self, other) - @with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "torch") def __or__(self, other): return torch_frontend.bitwise_or(self, other) - @with_supported_dtypes({"2.1.0 and below": ("integer", "bool")}, "torch") + @with_supported_dtypes({"2.2 and below": ("integer", "bool")}, "torch") def __invert__(self): return torch_frontend.bitwise_not(self) def __and__(self, other): return torch_frontend.bitwise_and(self, other) + def __iand__(self, other): + self.ivy_array = self.bitwise_and(other).ivy_array + return self + + def new(self): + return torch_frontend.tensor([], dtype=self.dtype, device=self.device) + def __array__(self, dtype=None): if dtype is None: return ivy.to_numpy(self.ivy_array) @@ -1351,8 +1443,8 @@ def item(self): ) @numpy_to_torch_style_args - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") - def cumprod(self, dim, dtype): + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") + def cumprod(self, dim, dtype=None): return torch_frontend.cumprod(self, dim, dtype=dtype) @numpy_to_torch_style_args @@ -1364,26 +1456,26 @@ def cov(self, /, *, correction=1, fweights=None, aweights=None): self, correction=correction, fweights=fweights, aweights=aweights ) - @with_unsupported_dtypes({"2.1.0 and below": ("bfloat16", "float16")}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bfloat16", "float16")}, "torch") def exp(self): return torch_frontend.exp(self) - @with_unsupported_dtypes( - {"2.1.0 and below": ("bfloat16", "float16", "complex")}, "torch" + @with_supported_dtypes( + {"2.2 and below": ("bfloat16", "float32", "float64")}, "torch" ) def expm1(self): return torch_frontend.expm1(self) # remove "bfloat16" from the below decorator after fixing ivy.Array.__repr__ method @with_unsupported_dtypes( - {"2.1.0 and below": ("bfloat16", "float16", "complex")}, "torch" + {"2.2 and below": ("bfloat16", "float16", "complex")}, "torch" ) def expm1_(self): self.ivy_array = torch_frontend.expm1(self).ivy_array return self # fmt: off - @with_unsupported_dtypes({"2.1.0 and below": ("int8", "int16", "int32", "int64", "uint8", "bool", "float16",)},"torch",) # noqa + @with_unsupported_dtypes({"2.2 and below": ("int8", "int16", "int32", "int64", "uint8", "bool", "float16",)},"torch",) # noqa def exp_(self): self.ivy_array = self.exp().ivy_array return self @@ -1392,33 +1484,33 @@ def exp_(self): def mul(self, other): return torch_frontend.mul(self, other) - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def ceil_(self): self.ivy_array = torch_frontend.ceil(self).ivy_array return self - @with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "torch") def mul_(self, other): self.ivy_array = self.mul(other).ivy_array # the return dtype is the same as the input dtype self.ivy_array = self.to(self.dtype).ivy_array return self - @with_unsupported_dtypes({"2.1.0 and below": ("bfloat16", "float16")}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bfloat16", "float16")}, "torch") def round(self, *, decimals=0): return torch_frontend.round(self, decimals=decimals) - @with_unsupported_dtypes({"2.1.0 and below": ("bfloat16", "float16")}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bfloat16", "float16")}, "torch") def round_(self, *, decimals=0): self.ivy_array = self.round(decimals=decimals).ivy_array return self @numpy_to_torch_style_args - @with_unsupported_dtypes({"2.1.0 and below": ("float16", "complex")}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16", "complex")}, "torch") def cross(self, other, dim=-1): return torch_frontend.cross(self, other, dim=dim) - @with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") def det(self): return torch_frontend.det(self) @@ -1426,9 +1518,10 @@ def reciprocal(self): return torch_frontend.reciprocal(self) def fill_(self, value): - self.ivy_array = torch_frontend.full_like( + ret = torch_frontend.full_like( self, value, dtype=self.dtype, device=self.device - ).ivy_array + ) + self.ivy_array = ivy.inplace_update(self.ivy_array, ret) return self def nonzero(self, as_tuple=False): @@ -1437,13 +1530,13 @@ def nonzero(self, as_tuple=False): def mm(self, mat2): return torch_frontend.mm(self, mat2) - @with_unsupported_dtypes({"2.1.0 and below": ("bfloat16", "float16")}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bfloat16", "float16")}, "torch") def square(self): return torch_frontend.square(self._ivy_array) @with_supported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "float16", "float32", "float64", @@ -1462,18 +1555,19 @@ def square_(self): self.ivy_array = torch_frontend.square(self._ivy_array).ivy_array return self - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def log10(self): return torch_frontend.log10(self._ivy_array) - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def log10_(self): self.ivy_array = self.log10().ivy_array return self - @with_unsupported_dtypes({"2.1.0 and below": ("uint16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("uint16",)}, "torch") def zero_(self): - self.ivy_array = torch_frontend.zeros_like(self).ivy_array + ret = torch_frontend.zeros_like(self) + self.ivy_array = ivy.inplace_update(self.ivy_array, ret) return self def short(self, memory_format=None): @@ -1481,7 +1575,7 @@ def short(self, memory_format=None): return self @numpy_to_torch_style_args - @with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") def prod(self, dim=None, keepdim=False, *, dtype=None): return torch_frontend.prod(self, dim=dim, keepdim=keepdim, dtype=dtype) @@ -1493,7 +1587,7 @@ def div_(self, other, *, rounding_mode=None): return self @with_supported_dtypes( - {"2.1.0 and below": ("float16", "float32", "float64", "bfloat16")}, "torch" + {"2.2 and below": ("float16", "float32", "float64", "bfloat16")}, "torch" ) def true_divide_(self, other): self.ivy_array = self.div(other, rounding_mode=None).ivy_array @@ -1509,26 +1603,26 @@ def normal_(self, mean=0, std=1, *, generator=None): ) return self - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def addcdiv(self, tensor1, tensor2, *, value=1): return torch_frontend.addcdiv(self, tensor1, tensor2, value=value) - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def addcmul(self, tensor1, tensor2, *, value=1): return torch_frontend.addcmul(self, tensor1, tensor2, value=value) - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def addcmul_(self, tensor1, tensor2, *, value=1): self.ivy_array = self.addcmul(tensor1, tensor2, value=value).ivy_array return self sign_decorator_dtypes = ("float16", "complex", "bool") - @with_unsupported_dtypes({"2.1.0 and below": sign_decorator_dtypes}, "torch") + @with_unsupported_dtypes({"2.2 and below": sign_decorator_dtypes}, "torch") def sign(self): return torch_frontend.sign(self._ivy_array) - @with_unsupported_dtypes({"2.1.0 and below": sign_decorator_dtypes}, "torch") + @with_unsupported_dtypes({"2.2 and below": sign_decorator_dtypes}, "torch") def sign_(self): self.ivy_array = self.sign().ivy_array return self @@ -1539,11 +1633,11 @@ def std(self, dim=None, unbiased=True, keepdim=False, *, out=None): self, dim=dim, unbiased=unbiased, keepdim=keepdim, out=out ) - @with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") def fmod(self, other, *, out=None): return torch_frontend.fmod(self, other, out=out) - @with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") def fmod_(self, other): self.ivy_array = self.fmod(other).ivy_array return self @@ -1554,96 +1648,96 @@ def norm(self, p="fro", dim=None, keepdim=False, dtype=None): def tolist(self): return self._ivy_array.to_list() - @with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "torch") def multiply(self, other, *, out=None): return torch_frontend.multiply(self, other, out=out) - @with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "torch") def multiply_(self, other, *, out=None): self.ivy_array = torch_frontend.multiply(self, other, out=out).ivy_array return self @numpy_to_torch_style_args - @with_unsupported_dtypes({"2.1.0 and below": ("float16", "complex")}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16", "complex")}, "torch") def topk(self, k, dim=None, largest=True, sorted=True): return torch_frontend.topk(self, k, dim=dim, largest=largest, sorted=sorted) rshift_dtypes = ("float16", "bfloat16", "float32", "float64", "bool", "complex") - @with_unsupported_dtypes({"2.1.0 and below": rshift_dtypes}, "torch") + @with_unsupported_dtypes({"2.2 and below": rshift_dtypes}, "torch") def bitwise_right_shift(self, other, *, out=None): return torch_frontend.bitwise_right_shift(self._ivy_array, other) @with_supported_dtypes( - {"2.1.0 and below": ("uint8", "int8", "int32", "int64")}, "torch" + {"2.2 and below": ("uint8", "int8", "int32", "int64")}, "torch" ) def bitwise_right_shift_(self, other, *, out=None): self.ivy_array = self.bitwise_right_shift(other, out=out).ivy_array return self - @with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") def logdet(self): chol = torch_frontend.cholesky(self) return 2 * torch_frontend.sum( torch_frontend.log(torch_frontend.real(torch_frontend.diagonal(chol))) ) - @with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") def copysign(self, other, *, out=None): return torch_frontend.copysign(self, other, out=out) @with_supported_dtypes( - {"2.1.0 and below": ("float16", "float32", "float64")}, "torch" + {"2.2 and below": ("float16", "float32", "float64")}, "torch" ) def copysign_(self, other, *, out=None): self.ivy_array = self.copysign(other, out=out).ivy_array return self @with_unsupported_dtypes( - {"2.1.0 and below": ("complex", "bfloat16", "bool")}, "torch" + {"2.2 and below": ("complex", "bfloat16", "bool")}, "torch" ) def greater(self, other, *, out=None): return torch_frontend.greater(self, other, out=out) - @with_unsupported_dtypes({"2.1.0 and below": ("bfloat16", "bool")}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bfloat16", "bool")}, "torch") def greater_(self, other): self.ivy_array = ivy.astype(self.greater(other).ivy_array, self.dtype) return self @with_unsupported_dtypes( - {"2.1.0 and below": ("complex", "bfloat16", "bool")}, "torch" + {"2.2 and below": ("complex", "bfloat16", "bool")}, "torch" ) def greater_equal(self, other, *, out=None): return torch_frontend.greater_equal(self, other, out=out) - @with_unsupported_dtypes({"2.1.0 and below": ("bfloat16", "bool")}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bfloat16", "bool")}, "torch") def greater_equal_(self, other): self.ivy_array = ivy.astype(self.greater_equal(other).ivy_array, self.dtype) return self @with_unsupported_dtypes( - {"2.1.0 and below": ("complex", "bfloat16", "bool")}, "torch" + {"2.2 and below": ("complex", "bfloat16", "bool")}, "torch" ) def less(self, other, *, out=None): return torch_frontend.less(self, other, out=out) - @with_unsupported_dtypes({"2.1.0 and below": ("bfloat16", "bool")}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bfloat16", "bool")}, "torch") def less_(self, other): self.ivy_array = ivy.astype(self.less(other).ivy_array, self.dtype) return self @with_unsupported_dtypes( - {"2.1.0 and below": ("complex", "bfloat16", "bool")}, "torch" + {"2.2 and below": ("complex", "bfloat16", "bool")}, "torch" ) def less_equal(self, other, *, out=None): return torch_frontend.less_equal(self, other, out=out) - @with_unsupported_dtypes({"2.1.0 and below": ("bfloat16", "bool")}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bfloat16", "bool")}, "torch") def less_equal_(self, other): self.ivy_array = ivy.astype(self.less_equal(other).ivy_array, self.dtype) return self - @with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "torch") def eq_(self, other): self.ivy_array = ivy.astype( torch_frontend.eq(self, other).ivy_array, self.dtype @@ -1672,16 +1766,18 @@ def stride(self, dim=None): return strides @with_supported_dtypes( - {"2.1.0 and below": ("float32", "float64", "bfloat16")}, "torch" + {"2.2 and below": ("float32", "float64", "bfloat16")}, "torch" ) def log1p(self): promoted_type = ivy.promote_types(self.dtype, "float32") - return torch_frontend.log1p(self).to(promoted_type) + res = torch_frontend.log1p(self) + return res.to(promoted_type) - @with_supported_dtypes({"2.1.0 and below": ("float32", "float64")}, "torch") + @with_supported_dtypes({"2.2 and below": ("float32", "float64")}, "torch") def log1p_(self): promoted_type = ivy.promote_types(self.dtype, "float32") - self.ivy_array = torch_frontend.log1p(self).to(promoted_type).ivy_array + res = torch_frontend.log1p(self) + self.ivy_array = res.to(promoted_type).ivy_array return self def baddbmm(self, batch1, batch2, *, beta=1, alpha=1): @@ -1698,14 +1794,14 @@ def baddbmm_(self, batch1, batch2, *, beta=1, alpha=1): def bmm(self, mat2): return torch_frontend.bmm(self, mat2=mat2) - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def floor_(self): self.ivy_array = self.floor().ivy_array return self @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "bfloat16", "complex", "float64", @@ -1721,7 +1817,7 @@ def diff(self, n=1, dim=-1, prepend=None, append=None): def diag(self, diagonal=0): return torch_frontend.diag(self, diagonal=diagonal) - @with_unsupported_dtypes({"2.1.0 and below": ("bfloat16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "torch") def diagonal(self, offset=0, dim1=0, dim2=1): return torch_frontend.diagonal(self, offset=offset, dim1=dim1, dim2=dim2) @@ -1729,14 +1825,14 @@ def gather(self, dim, index): return torch_frontend.gather(self, dim=dim, index=index) @with_supported_dtypes( - {"2.1.0 and below": ("float32", "float64", "int32", "int64")}, "torch" + {"2.2 and below": ("float32", "float64", "int32", "int64")}, "torch" ) def scatter_add_(self, dim, index, src): self.ivy_array = ivy.put_along_axis(self.ivy_array, index, src, dim, mode="sum") return self @with_supported_dtypes( - {"2.1.0 and below": ("float32", "float64", "int32", "int64")}, "torch" + {"2.2 and below": ("float32", "float64", "int32", "int64")}, "torch" ) def scatter_(self, dim, index, src, *, reduce=None): if reduce is None: @@ -1753,7 +1849,7 @@ def scatter_(self, dim, index, src, *, reduce=None): return self @with_supported_dtypes( - {"2.1.0 and below": ("float32", "float64", "int32", "int64")}, "torch" + {"2.2 and below": ("float32", "float64", "int32", "int64")}, "torch" ) def scatter_reduce_(self, dim, index, src, reduce, *, include_self=True): if reduce == "prod": @@ -1764,19 +1860,19 @@ def scatter_reduce_(self, dim, index, src, reduce, *, include_self=True): return self @with_supported_dtypes( - {"2.1.0 and below": ("float32", "float64", "int32", "int64")}, "torch" + {"2.2 and below": ("float32", "float64", "int32", "int64")}, "torch" ) def scatter_add(self, dim, index, src): return torch_frontend.scatter_add(self, dim, index, src) @with_supported_dtypes( - {"2.1.0 and below": ("float32", "float64", "int32", "int64")}, "torch" + {"2.2 and below": ("float32", "float64", "int32", "int64")}, "torch" ) def scatter(self, dim, index, src): return torch_frontend.scatter_reduce(self, dim, index, src, reduce="replace") @with_supported_dtypes( - {"2.1.0 and below": ("float32", "float64", "int32", "int64")}, "torch" + {"2.2 and below": ("float32", "float64", "int32", "int64")}, "torch" ) def scatter_reduce(self, dim, index, src, reduce, *, include_self=True): return torch_frontend.scatter_reduce(self, dim, index, src, reduce=reduce) @@ -1787,14 +1883,14 @@ def take_along_dim(self, indices, dim): def movedim(self, source, destination): return torch_frontend.movedim(self, source=source, destination=destination) - @with_unsupported_dtypes({"2.1.0 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def addcdiv_(self, tensor1, tensor2, *, value=1): self.ivy_array = self.addcdiv( tensor1=tensor1, tensor2=tensor2, value=value ).ivy_array return self - @with_unsupported_dtypes({"2.1.0 and below": ("bfloat16", "float16")}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bfloat16", "float16")}, "torch") def cholesky(self, upper=False): return torch_frontend.cholesky(self, upper=upper) @@ -1809,7 +1905,7 @@ def tile(self, *reps): def apply_(self, callable, /): if self.device != "cpu": - raise Exception("apply_ is only supported on cpu tensors") + raise ValueError("apply_ is only supported on cpu tensors") self.ivy_array = callable(self.ivy_array) return self @@ -1833,10 +1929,15 @@ def backward(self, gradient=None, retain_graph=None, create_graph=False): else: next_function(_grad_list[idx]) - @with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") def logaddexp(self, other): return torch_frontend.logaddexp(self, other) + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") + def logaddexp2(self, other): + self.ivy_array = torch_frontend.logaddexp2(self, other).ivy_array + return self + def angle(self): return torch_frontend.angle(self) @@ -1857,17 +1958,17 @@ def adjoint(self): return torch_frontend.adjoint(self) @with_unsupported_dtypes( - {"2.1.0 and below": ("int16", "float16", "bfloat16")}, "torch" + {"2.2 and below": ("int16", "float16", "bfloat16")}, "torch" ) def conj(self): return torch_frontend.conj(self) - @with_unsupported_dtypes({"2.1.0 and below": ("float16", "bfloat16")}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") def svd(self, some=True, compute_uv=True, *, out=None): return torch_frontend.svd(self, some=some, compute_uv=compute_uv, out=out) @with_unsupported_dtypes( - {"2.1.0 and below": ("float16", "bfloat16", "float32", "float64", "complex")}, + {"2.2 and below": ("float16", "bfloat16", "float32", "float64", "complex")}, "torch", ) def gcd(self, other, *, out=None): @@ -1875,7 +1976,7 @@ def gcd(self, other, *, out=None): @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "float16", "bfloat16", "uint16", @@ -1895,7 +1996,7 @@ def char(self): @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "float16", "bfloat16", "float32", @@ -1912,7 +2013,7 @@ def lcm(self, other, *, out=None): @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "float16", "bfloat16", "float32", @@ -1933,7 +2034,7 @@ def lcm_(self, other, *, out=None): @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "bfloat16", "int8", "uint8", @@ -1950,17 +2051,17 @@ def triu_(self, diagonal=0): return self @with_unsupported_dtypes( - {"2.1.0 and below": ("float16", "bfloat16")}, + {"2.2 and below": ("float16", "bfloat16")}, "torch", ) def quantile(self, q, dim=None, keepdim=False, *, interpolation="linear", out=None): return torch_frontend.quantile( - self, q, axis=dim, keepdims=keepdim, interpolation=interpolation, out=out + self, q, dim=dim, keepdim=keepdim, interpolation=interpolation, out=out ) @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "int8", "int16", "uint8", @@ -1992,7 +2093,32 @@ def random_( @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( + "integer", + "unsigned", + "bfloat16", + "bool", + "complex", + ) + }, + "torch", + ) + def uniform_(self, from_=0, to=1, *, generator=None): + ret = ivy.random_uniform( + low=from_, high=to, shape=self.shape, dtype=self.dtype, seed=generator + ) + self._ivy_array = ivy.inplace_update( + self._ivy_array, ivy.astype(ret, self._ivy_array.dtype) + ) + return self + + @with_supported_dtypes({"2.2 and below": ("float32", "float64")}, "torch") + def frac(self, name=None): + return torch_frontend.frac(self._ivy_array) + + @with_unsupported_dtypes( + { + "2.2 and below": ( "float16", "bfloat16", ) @@ -2004,7 +2130,7 @@ def sinc(self): @with_supported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "float32", "float64", "bfloat16", @@ -2016,7 +2142,7 @@ def sinc_(self): self.ivy_array = torch_frontend.sinc(self).ivy_array return self - @with_unsupported_dtypes({"2.1.0 and below": ("uint8",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("uint8",)}, "torch") def index_fill(self, dim, index, value): arr = torch_frontend.moveaxis(self, dim, 0) arr[ivy.to_list(index)] = value @@ -2025,7 +2151,7 @@ def index_fill(self, dim, index, value): @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "bfloat16", "int8", "uint8", @@ -2048,7 +2174,7 @@ def unique_consecutive(self, return_inverse, return_counts, dim): @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "uint16", "uint32", "uint64", @@ -2065,7 +2191,7 @@ def cummax(self, dim): @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "bfloat16", "int8", "uint8", @@ -2083,7 +2209,7 @@ def triu(self, diagonal=0): return torch_frontend.triu(self, diagonal) @with_unsupported_dtypes( - {"2.1.0 and below": ("bfloat16",)}, + {"2.2 and below": ("bfloat16",)}, "torch", ) def xlogy_(self, *, other, out=None): @@ -2092,7 +2218,7 @@ def xlogy_(self, *, other, out=None): @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "bfloat16", "uint8", "uint32", @@ -2109,7 +2235,7 @@ def ne(self, other): @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "bfloat16", "uint8", "uint32", @@ -2126,7 +2252,7 @@ def ne_(self, other): @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "bfloat16", "int8", "uint8", @@ -2137,6 +2263,7 @@ def ne_(self, other): "float16", "complex128", "complex64", + "bool", ) }, "torch", @@ -2146,7 +2273,7 @@ def unique(self, sorted=True, return_inverse=False, return_counts=False, dim=Non @with_unsupported_dtypes( { - "2.1.0 and below": ( + "2.2 and below": ( "float16", "bfloat16", ) @@ -2156,20 +2283,60 @@ def unique(self, sorted=True, return_inverse=False, return_counts=False, dim=Non def xlogy(self, *, other, out=None): return torch_frontend.xlogy(self, other, out=out) - @with_unsupported_dtypes({"2.1.0 and below": "complex"}, "torch") + @with_unsupported_dtypes({"2.2 and below": "complex"}, "torch") def minimum(self, other, *, out=None): return torch_frontend.minimum(self, other=other, out=out) def rad2deg(self, *, out=None): return torch_frontend.rad2deg(self, out=out) + @with_supported_dtypes( + {"2.2 and below": "valid"}, + "torch", + ) + def corrcoef(self): + return torch_frontend.corrcoef(self) + + def index_put(self, indices, values, accumulate=False): + ret = self.clone() + if accumulate: + ret[indices[0]] += values + else: + ret[indices[0]] = values + return ret + + def index_put_(self, indices, values, accumulate=False): + def _set_add(index): + self[index] += values + + def _set(index): + self[index] = values + + if accumulate: + ivy.map(fn=_set_add, unique={"index": indices}) + else: + ivy.map(fn=_set, unique={"index": indices}) + + return self + + @with_unsupported_dtypes({"2.2 and below": ("float16", "complex")}, "torch") + def erfinv(self, *, out=None): + return torch_frontend.erfinv(self, out=out) + + @with_unsupported_dtypes({"2.2 and below": ("float16", "complex")}, "torch") + def erfinv_(self, *, out=None): + ret = self.erfinv(out=out) + self._ivy_array = ivy.inplace_update( + self._ivy_array, ivy.astype(ret.ivy_array, self._ivy_array.dtype) + ) + return self + # Method aliases absolute, absolute_ = abs, abs_ clip, clip_ = clamp, clamp_ ndimension = dim subtract = sub sub_ = subtract_ - eq = equal arctan = atan arctan_ = atan_ arctan2 = atan2 @@ -2196,6 +2363,7 @@ def rad2deg(self, *, out=None): class Size(tuple): def __new__(cls, iterable=()): + iterable = ivy.Shape([]) if iterable == () else iterable new_iterable = [] for i, item in enumerate(iterable): if isinstance(item, int): @@ -2203,11 +2371,14 @@ def __new__(cls, iterable=()): continue try: new_iterable.append(int(item)) - except Exception: - raise TypeError(f"Expected int, but got {type(item)} at index {i}") - return super(Size, cls).__new__(cls, tuple(new_iterable)) - - def __init__(self, shape) -> None: + except Exception as e: + raise TypeError( + f"Expected int, but got {type(item)} at index {i}" + ) from e + return super().__new__(cls, tuple(new_iterable)) + + def __init__(self, shape=()) -> None: + shape = ivy.Shape([]) if shape == () else shape self._ivy_shape = shape if isinstance(shape, ivy.Shape) else ivy.shape(shape) def __repr__(self): @@ -2216,3 +2387,6 @@ def __repr__(self): @property def ivy_shape(self): return self._ivy_shape + + def numel(self): + return int(ivy.astype(ivy.prod(self), ivy.int64)) diff --git a/ivy/functional/frontends/torch/tensor_functions.py b/ivy/functional/frontends/torch/tensor_functions.py index 135981f71aaee..36dc356c96e7c 100644 --- a/ivy/functional/frontends/torch/tensor_functions.py +++ b/ivy/functional/frontends/torch/tensor_functions.py @@ -4,6 +4,11 @@ from ivy.functional.frontends.torch.func_wrapper import to_ivy_arrays_and_back +@to_ivy_arrays_and_back +def broadcast_tensors(*tensors): + return ivy.broadcast_arrays(*tensors) + + @to_ivy_arrays_and_back def is_complex(input): return ivy.is_complex_dtype(input) @@ -31,7 +36,7 @@ def numel(input): @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.0 and below": ("float32", "float64", "int32", "int64")}, "torch" + {"2.2 and below": ("float32", "float64", "int32", "int64")}, "torch" ) def scatter(input, dim, index, src): return ivy.put_along_axis(input, index, src, dim, mode="replace") @@ -39,7 +44,7 @@ def scatter(input, dim, index, src): @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.0 and below": ("float32", "float64", "int32", "int64")}, "torch" + {"2.2 and below": ("float32", "float64", "int32", "int64")}, "torch" ) def scatter_add(input, dim, index, src): return ivy.put_along_axis(input, index, src, dim, mode="sum") @@ -47,7 +52,7 @@ def scatter_add(input, dim, index, src): @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.0 and below": ("float32", "float64", "int32", "int64")}, "torch" + {"2.2 and below": ("float32", "float64", "int32", "int64")}, "torch" ) def scatter_reduce(input, dim, index, src, reduce, *, include_self=True): mode_mappings = { diff --git a/ivy/functional/frontends/torch/utilities.py b/ivy/functional/frontends/torch/utilities.py index da073c2720660..b53e5fe6aa8e0 100644 --- a/ivy/functional/frontends/torch/utilities.py +++ b/ivy/functional/frontends/torch/utilities.py @@ -20,14 +20,14 @@ def _assert(condition, message): # ------------ # -@with_supported_dtypes({"2.1.0 and above": ("int64",)}, "torch") +@with_supported_dtypes({"2.2 and above": ("int64",)}, "torch") @to_ivy_arrays_and_back def bincount(x, weights=None, minlength=0): return ivy.bincount(x, weights=weights, minlength=minlength) def if_else(cond_fn, body_fn, orelse_fn, vars): - cond_keys = inspect.getargspec(cond_fn).args + cond_keys = inspect.getfullargspec(cond_fn).args cond_vars = dict(zip(cond_keys, vars)) return ivy.if_else(cond_fn, body_fn, orelse_fn, cond_vars) diff --git a/ivy/functional/frontends/torchvision/ops.py b/ivy/functional/frontends/torchvision/ops.py index 589d0cb22910f..4d1a27185730e 100644 --- a/ivy/functional/frontends/torchvision/ops.py +++ b/ivy/functional/frontends/torchvision/ops.py @@ -23,9 +23,22 @@ def box_area(boxes): return ivy.prod(boxes[..., 2:] - boxes[..., :2], axis=-1) +@to_ivy_arrays_and_back +def box_iou(boxes1, boxes2): + area1 = box_area(boxes1) + area2 = box_area(boxes2) + lt = ivy.maximum(boxes1[:, None, :2], boxes2[:, :2]) + rb = ivy.minimum(boxes1[:, None, 2:], boxes2[:, 2:]) + wh = (rb - lt).clip(x_min=0) + inter = wh[:, :, 0] * wh[:, :, 1] + union = area1[:, None] + area2 - inter + iou = inter / union + return iou + + @with_unsupported_device_and_dtypes( { - "2.1.0 and below": { + "2.2 and below": { "cpu": ("float16",), } }, @@ -51,7 +64,7 @@ def remove_small_boxes(boxes, min_size): return ivy.nonzero((w >= min_size) & (h >= min_size))[0] -@with_supported_dtypes({"2.1.0 and below": ("float32", "float64")}, "torch") +@with_supported_dtypes({"2.2 and below": ("float32", "float64")}, "torch") @to_ivy_arrays_and_back def roi_align( input, boxes, output_size, spatial_scale=1.0, sampling_ratio=1, aligned=False diff --git a/ivy/functional/frontends/xgboost/core.py b/ivy/functional/frontends/xgboost/core.py index 8e8dbf9b557f4..c5404abf5d839 100644 --- a/ivy/functional/frontends/xgboost/core.py +++ b/ivy/functional/frontends/xgboost/core.py @@ -123,9 +123,8 @@ def __init__(self, params=None, cache=None, model_file=None, compile=False): self._comp_binary_prediction(self.gbm.obj, cache[1]) def update(self, dtrain, dlabel, iteration, fobj=None): - """ - Update for one iteration, with objective function calculated internally. This - function should not be called directly by users. + """Update for one iteration, with objective function calculated + internally. This function should not be called directly by users. Parameters ---------- @@ -156,11 +155,10 @@ def predict( iteration_range=(0, 0), strict_shape=False, ): - """ - Predict with data. The full model will be used unless `iteration_range` is - specified, meaning user have to either slice the model or use the - ``best_iteration`` attribute to get prediction from best model returned from - early stopping. + """Predict with data. The full model will be used unless + `iteration_range` is specified, meaning user have to either slice the + model or use the ``best_iteration`` attribute to get prediction from + best model returned from early stopping. Parameters ---------- diff --git a/ivy/functional/frontends/xgboost/linear/updater_coordinate.py b/ivy/functional/frontends/xgboost/linear/updater_coordinate.py index 284fc2f5a64a0..7b7c08a64e716 100644 --- a/ivy/functional/frontends/xgboost/linear/updater_coordinate.py +++ b/ivy/functional/frontends/xgboost/linear/updater_coordinate.py @@ -8,15 +8,15 @@ def coordinate_updater(gpair, data, lr, weight, n_feat, n_iter, reg_alpha, reg_lambda): - """ - Implements one step of coordinate descent. The original optimizer implements - parallel calculations. The below code is an approximation of the original one, but - rather than computing the update direction for a single parameter at a time using a - for loop and cumulative gradients, it does the update in parallel by means of - matrix-vector multiplications. Given that xgboost's updater is non-deterministic, - the approximated and original implementations converge to pretty the same optima, - resulting in metrics' values(accuracy, f1-score) differing at a level of 0.001(for - separate runs metrics may end up being the same). + """Implements one step of coordinate descent. The original optimizer + implements parallel calculations. The below code is an approximation of the + original one, but rather than computing the update direction for a single + parameter at a time using a for loop and cumulative gradients, it does the + update in parallel by means of matrix-vector multiplications. Given that + xgboost's updater is non-deterministic, the approximated and original + implementations converge to pretty the same optima, resulting in metrics' + values(accuracy, f1-score) differing at a level of 0.001(for separate runs + metrics may end up being the same). Parameters ---------- diff --git a/ivy/functional/frontends/xgboost/sklearn.py b/ivy/functional/frontends/xgboost/sklearn.py index 5e9fc2f187e35..3b80f8d6fa1fe 100644 --- a/ivy/functional/frontends/xgboost/sklearn.py +++ b/ivy/functional/frontends/xgboost/sklearn.py @@ -98,9 +98,8 @@ def __sklearn_is_fitted__(self): return hasattr(self, "_Booster") def get_booster(self): - """ - Get the underlying xgboost Booster of this model. This will raise an exception - when fit was not called. + """Get the underlying xgboost Booster of this model. This will raise an + exception when fit was not called. Returns ------- @@ -119,7 +118,7 @@ def get_params(self, deep=True): # take random_state into account only if it's an integer if isinstance(params["random_state"], int): - ivy.seed(params["random_state"]) + ivy.seed(seed_value=params["random_state"]) return params @@ -176,8 +175,7 @@ def fit( feature_weights=None, callbacks=None, ): - """ - Fit gradient boosting model. + """Fit gradient boosting model. Note that calling ``fit()`` multiple times will cause the model object to be re-fit from scratch. To resume training from a previous checkpoint, explicitly diff --git a/ivy/functional/frontends/xgboost/training.py b/ivy/functional/frontends/xgboost/training.py index cc727add4c5a6..cc67edb9f478d 100644 --- a/ivy/functional/frontends/xgboost/training.py +++ b/ivy/functional/frontends/xgboost/training.py @@ -18,8 +18,7 @@ def train( callbacks=None, custom_metric=None, ): - """ - Train a booster with given parameters. + """Train a booster with given parameters. Parameters ---------- diff --git a/ivy/functional/ivy/activations.py b/ivy/functional/ivy/activations.py index 2468219b98cde..8d3803b6c0777 100644 --- a/ivy/functional/ivy/activations.py +++ b/ivy/functional/ivy/activations.py @@ -48,8 +48,7 @@ def gelu( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Apply the Gaussian error linear unit (GELU) activation function. + """Apply the Gaussian error linear unit (GELU) activation function. Parameters ---------- @@ -138,8 +137,7 @@ def leaky_relu( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Apply the leaky rectified linear unit function element-wise. + """Apply the leaky rectified linear unit function element-wise. If the input is complex, then by default each element is scaled by `alpha` if either its real part is strictly negative or if its real part is zero and its @@ -218,8 +216,7 @@ def log_softmax( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Apply the log_softmax function element-wise. + """Apply the log_softmax function element-wise. Parameters ---------- @@ -314,8 +311,7 @@ def relu( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Apply the rectified linear unit function element-wise. + """Apply the rectified linear unit function element-wise. If the input is complex, then by default each element is set to zero if either its real part is strictly negative or if its real part is zero and its @@ -386,8 +382,7 @@ def sigmoid( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Apply the sigmoid function element-wise. + """Apply the sigmoid function element-wise. Parameters ---------- @@ -473,8 +468,7 @@ def softmax( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Apply the softmax function element-wise. + """Apply the softmax function element-wise. Parameters ---------- @@ -571,8 +565,7 @@ def softplus( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Apply the softplus function element-wise. + """Apply the softplus function element-wise. If the input is complex, then by default we apply the softplus operation `log(1+ exp(x))` to each element @@ -640,8 +633,7 @@ def softsign( /, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Apply the softsign function element-wise. + """Apply the softsign function element-wise. Parameters ---------- @@ -683,8 +675,7 @@ def mish( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Apply the mish activation function element-wise. + """Apply the mish activation function element-wise. Parameters ---------- @@ -759,8 +750,7 @@ def hardswish( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Apply the hardswish activation function element-wise. + """Apply the hardswish activation function element-wise. Parameters ---------- diff --git a/ivy/functional/ivy/control_flow_ops.py b/ivy/functional/ivy/control_flow_ops.py index 9b2dda176ad85..9973de660b546 100644 --- a/ivy/functional/ivy/control_flow_ops.py +++ b/ivy/functional/ivy/control_flow_ops.py @@ -13,10 +13,9 @@ def if_else( orelse_fn: Callable, vars: Dict[str, Union[ivy.Array, ivy.NativeArray]], ) -> Any: - """ - Take a condition function and two functions as input. If the condition is True, the - first function is executed and its result is returned. Otherwise, the second - function is executed and its result is returned. + """Take a condition function and two functions as input. If the condition + is True, the first function is executed and its result is returned. + Otherwise, the second function is executed and its result is returned. Parameters ---------- @@ -67,9 +66,9 @@ def while_loop( body_fn: Callable, vars: Dict[str, Union[ivy.Array, ivy.NativeArray]], ) -> Any: - """ - Take a test function, a body function and a set of variables as input. The body - function is executed repeatedly while the test function returns True. + """Take a test function, a body function and a set of variables as input. + The body function is executed repeatedly while the test function returns + True. Parameters ---------- @@ -119,9 +118,8 @@ def for_loop( body_fn: Callable, vars: Iterable[Union[ivy.Array, ivy.NativeArray]], ): - """ - Loops over an iterable, passing the current iteration along with a tuple of - variables into the provided body function. + """Loops over an iterable, passing the current iteration along with a tuple + of variables into the provided body function. Parameters ---------- diff --git a/ivy/functional/ivy/creation.py b/ivy/functional/ivy/creation.py index 0c94beafdbced..5a837dcd93bcc 100644 --- a/ivy/functional/ivy/creation.py +++ b/ivy/functional/ivy/creation.py @@ -44,10 +44,9 @@ def _asarray_handle_nestable(fn: Callable) -> Callable: @functools.wraps(fn) def _asarray_handle_nestable_wrapper(*args, **kwargs): - """ - Call `fn` with the *nestable* property of the function correctly handled. This - means mapping the function to the container leaves if any containers are passed - in the input. + """Call `fn` with the *nestable* property of the function correctly + handled. This means mapping the function to the container leaves if any + containers are passed in the input. Parameters ---------- @@ -136,9 +135,9 @@ def _remove_np_bfloat16(obj): def _asarray_to_native_arrays_and_back(fn: Callable) -> Callable: @functools.wraps(fn) def _asarray_to_native_arrays_and_back_wrapper(*args, dtype=None, **kwargs): - """ - Wrap `fn` so that input arrays are all converted to `ivy.NativeArray` instances - and return arrays are all converted to `ivy.Array` instances. + """Wrap `fn` so that input arrays are all converted to + `ivy.NativeArray` instances and return arrays are all converted to + `ivy.Array` instances. This wrapper is specifically for the backend implementations of asarray. @@ -154,16 +153,16 @@ def _asarray_to_native_arrays_and_back_wrapper(*args, dtype=None, **kwargs): dtype = ivy.default_dtype(dtype=dtype, as_native=True) return to_ivy(fn(*new_args, dtype=dtype, **kwargs)) + _asarray_to_native_arrays_and_back_wrapper._asarray_to_native_arrays_and_back = True return _asarray_to_native_arrays_and_back_wrapper def _asarray_infer_dtype(fn: Callable) -> Callable: @functools.wraps(fn) def _asarray_infer_dtype_wrapper(*args, dtype=None, **kwargs): - """ - Determine the correct `dtype`, and then calls the function with the `dtype` - passed explicitly. This wrapper is specifically for the backend implementations - of asarray. + """Determine the correct `dtype`, and then calls the function with the + `dtype` passed explicitly. This wrapper is specifically for the backend + implementations of asarray. Parameters ---------- @@ -218,10 +217,9 @@ def _infer_dtype(obj): def _asarray_infer_device(fn: Callable) -> Callable: @functools.wraps(fn) def _asarray_infer_device_wrapper(*args, device=None, **kwargs): - """ - Determine the correct `device`, and then calls the function with the `device` - passed explicitly. This wrapper is specifically for the backend implementations - of asarray. + """Determine the correct `device`, and then calls the function with the + `device` passed explicitly. This wrapper is specifically for the + backend implementations of asarray. Parameters ---------- @@ -299,9 +297,8 @@ def arange( device: Optional[Union[ivy.Device, ivy.NativeDevice]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return evenly spaced values within a given interval, with the spacing being - specified. + """Return evenly spaced values within a given interval, with the spacing + being specified. Values are generated within the half-open interval [start, stop) (in other words, the interval including start but excluding stop). For integer arguments the function @@ -411,8 +408,7 @@ def asarray( device: Optional[Union[ivy.Device, ivy.NativeDevice]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Convert the input to an array. + """Convert the input to an array. Parameters ---------- @@ -497,8 +493,7 @@ def zeros( device: Optional[Union[ivy.Device, ivy.NativeDevice]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return a new array having a specified ``shape`` and filled with zeros. + """Return a new array having a specified ``shape`` and filled with zeros. Parameters ---------- @@ -562,8 +557,7 @@ def ones( device: Optional[Union[ivy.Device, ivy.NativeDevice]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return a new array having a specified ``shape`` and filled with ones. + """Return a new array having a specified ``shape`` and filled with ones. .. note:: @@ -661,9 +655,8 @@ def full_like( device: Optional[Union[ivy.Device, ivy.NativeDevice]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return a new array filled with ``fill_value`` and having the same ``shape`` as an - input array ``x`` . + """Return a new array filled with ``fill_value`` and having the same + ``shape`` as an input array ``x`` . Parameters ---------- @@ -769,9 +762,8 @@ def ones_like( device: Optional[Union[ivy.Device, ivy.NativeDevice]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return a new array filled with ones and having the same shape as an input array - ``x``. + """Return a new array filled with ones and having the same shape as an + input array ``x``. .. note:: @@ -889,9 +881,8 @@ def zeros_like( device: Optional[Union[ivy.Device, ivy.NativeDevice]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return a new array filled with zeros and having the same ``shape`` as an input array - ``x``. + """Return a new array filled with zeros and having the same ``shape`` as an + input array ``x``. Parameters ---------- @@ -1002,8 +993,8 @@ def tril( k: int = 0, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return the lower triangular part of a matrix (or a stack of matrices) ``x``. + """Return the lower triangular part of a matrix (or a stack of matrices) + ``x``. .. note:: @@ -1058,8 +1049,8 @@ def triu( k: int = 0, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return the upper triangular part of a matrix (or a stack of matrices) ``x``. + """Return the upper triangular part of a matrix (or a stack of matrices) + ``x``. .. note:: @@ -1116,8 +1107,7 @@ def empty( device: Optional[Union[ivy.Device, ivy.NativeDevice]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return a new array of given shape and type, filled with zeros. + """Return a new array of given shape and type, filled with zeros. Parameters ---------- @@ -1167,8 +1157,7 @@ def empty_like( device: Optional[Union[ivy.Device, ivy.NativeDevice]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return an uninitialized array with the same shape as an input array x. + """Return an uninitialized array with the same shape as an input array x. Parameters ---------- @@ -1222,8 +1211,8 @@ def eye( device: Optional[Union[ivy.Device, ivy.NativeDevice]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return a two-dimensional array with ones on the k diagonal and zeros elsewhere. + """Return a two-dimensional array with ones on the k diagonal and zeros + elsewhere. Parameters ---------- @@ -1365,8 +1354,8 @@ def linspace( device: Optional[Union[ivy.Device, ivy.NativeDevice]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Generate a certain number of evenly-spaced values in an interval along a given axis. + """Generate a certain number of evenly-spaced values in an interval along a + given axis. See :math:`arange` that allows to specify the step size of evenly spaced values in an interval. @@ -1468,8 +1457,7 @@ def meshgrid( indexing: str = "xy", out: Optional[ivy.Array] = None, ) -> List[ivy.Array]: - """ - Return coordinate matrices from coordinate vectors. + """Return coordinate matrices from coordinate vectors. Parameters ---------- @@ -1593,8 +1581,8 @@ def full( device: Optional[Union[ivy.Device, ivy.NativeDevice]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return a new array having a specified ``shape`` and filled with ``fill_value``. + """Return a new array having a specified ``shape`` and filled with + ``fill_value``. Parameters ---------- @@ -1696,8 +1684,7 @@ def full( def to_dlpack( x: Union[ivy.Array, ivy.NativeArray], /, *, out: Optional[ivy.Array] = None ): - """ - Return PyCapsule Object. + """Return PyCapsule Object. Parameters ---------- @@ -1736,14 +1723,13 @@ def to_dlpack( def from_dlpack( x: Union[ivy.Array, ivy.NativeArray], /, *, out: Optional[ivy.Array] = None ) -> ivy.Array: - """ - Return a new array containing the data from another (array) object with a - ``__dlpack__`` method. + """Return a new array containing the data from another (array) object with + a ``__dlpack__`` method or PyCapsule Object. Parameters ---------- x object - input (array) object. + input (array) object with a ``__dlpack__`` method or PyCapsule Object. out optional output array, for writing the result to. It must have a shape that the inputs broadcast to. @@ -1794,8 +1780,7 @@ def copy_array( to_ivy_array: bool = True, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Copy an array. + """Copy an array. Parameters ---------- @@ -1900,8 +1885,7 @@ def native_array( dtype: Optional[Union[ivy.Dtype, ivy.NativeDtype]] = None, device: Optional[Union[ivy.Device, ivy.NativeDevice]] = None, ) -> ivy.NativeArray: - """ - Convert the input to a native array. + """Convert the input to a native array. Parameters ---------- @@ -1965,9 +1949,9 @@ def one_hot( device: Union[ivy.Device, ivy.NativeDevice] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return a one-hot array. The locations represented by indices in the parameter - indices take value on_value, while all other locations take value off_value. + """Return a one-hot array. The locations represented by indices in the + parameter indices take value on_value, while all other locations take value + off_value. Parameters ---------- @@ -2038,7 +2022,7 @@ def one_hot( } >>> x = ivy.Container(a=ivy.array([2]), \ - b=ivy.array([]), c=ivy.native_array([4])) + b=ivy.array([], dtype=ivy.int32), c=ivy.native_array([4])) >>> y = 7 >>> z = x.one_hot(y) >>> print(z) @@ -2081,9 +2065,8 @@ def logspace( device: Optional[Union[ivy.Device, ivy.NativeDevice]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Generate a certain number of evenly-spaced values in log space, in an interval along - a given axis. + """Generate a certain number of evenly-spaced values in log space, in an + interval along a given axis. Parameters ---------- @@ -2186,8 +2169,7 @@ def frombuffer( count: Optional[int] = -1, offset: Optional[int] = 0, ) -> ivy.Array: - r""" - Interpret a buffer as a 1-dimensional array. + r"""Interpret a buffer as a 1-dimensional array. .. note:: Note that either of the following must be true: @@ -2252,16 +2234,16 @@ def triu_indices( *, device: Optional[Union[ivy.Device, ivy.NativeDevice]] = None, ) -> Tuple[ivy.Array]: - """ - Return the indices of the upper triangular part of a row by col matrix in a 2-by-N - shape (tuple of two N dimensional arrays), where the first row contains row - coordinates of all indices and the second row contains column coordinates. Indices - are ordered based on rows and then columns. The upper triangular part of the matrix - is defined as the elements on and above the diagonal. The argument k controls which - diagonal to consider. If k = 0, all elements on and above the main diagonal are - retained. A positive value excludes just as many diagonals above the main diagonal, - and similarly a negative value includes just as many diagonals below the main - diagonal. The main diagonal are the set of indices {(i,i)} for iโˆˆ[0,min{n_rows, + """Return the indices of the upper triangular part of a row by col matrix + in a 2-by-N shape (tuple of two N dimensional arrays), where the first row + contains row coordinates of all indices and the second row contains column + coordinates. Indices are ordered based on rows and then columns. The upper + triangular part of the matrix is defined as the elements on and above the + diagonal. The argument k controls which diagonal to consider. If k = 0, + all elements on and above the main diagonal are retained. A positive value + excludes just as many diagonals above the main diagonal, and similarly a + negative value includes just as many diagonals below the main diagonal. The + main diagonal are the set of indices {(i,i)} for iโˆˆ[0,min{n_rows, n_cols}โˆ’1]. Notes diff --git a/ivy/functional/ivy/data_type.py b/ivy/functional/ivy/data_type.py index e0d4e592068f1..4b074b58a3795 100644 --- a/ivy/functional/ivy/data_type.py +++ b/ivy/functional/ivy/data_type.py @@ -3,6 +3,7 @@ import logging import inspect import math +import functools from numbers import Number from typing import Union, Tuple, List, Optional, Callable, Iterable, Any import numpy as np @@ -48,6 +49,7 @@ def _is_valid_dtypes_attributes(fn: Callable) -> bool: def _handle_nestable_dtype_info(fn): + @functools.wraps(fn) def _handle_nestable_dtype_info_wrapper(type): if isinstance(type, ivy.Container): type = type.cont_map(lambda x, kc: fn(x)) @@ -96,9 +98,10 @@ def _get_function_list(func): hasattr(nodef, "value") and hasattr(nodef.value, "id") and nodef.value.id not in ["ivy", "self"] + and "_frontend" not in nodef.value.id ): continue - names[nodef.attr] = getattr( + names[ast.unparse(nodef)] = getattr( func, "__self__", getattr( @@ -115,13 +118,14 @@ def _get_function_list(func): def _get_functions_from_string(func_names, module): ret = set() # We only care about the functions in the ivy or the same module - for func_name in func_names.keys(): + for orig_func_name in func_names.keys(): + func_name = orig_func_name.split(".")[-1] if hasattr(ivy, func_name) and callable(getattr(ivy, func_name, None)): ret.add(getattr(ivy, func_name)) - elif hasattr(module, func_name) and callable(getattr(ivy, func_name, None)): + elif hasattr(module, func_name) and callable(getattr(module, func_name, None)): ret.add(getattr(module, func_name)) - elif callable(getattr(func_names[func_name], func_name, None)): - ret.add(getattr(func_names[func_name], func_name)) + elif callable(getattr(func_names[orig_func_name], func_name, None)): + ret.add(getattr(func_names[orig_func_name], func_name)) return ret @@ -147,7 +151,10 @@ def _nested_get(f, base_set, merge_fn, get_fn, wrapper=set): # if it's einops, we need to recurse if not getattr(fn, "__module__", None): continue - if "backend" in fn.__module__: + is_frontend_fn = "frontend" in fn.__module__ + is_backend_fn = "backend" in fn.__module__ and not is_frontend_fn + is_einops_fn = hasattr(fn, "__name__") and "einops" in fn.__name__ + if is_backend_fn: f_supported = get_fn(fn, False) if hasattr(fn, "partial_mixed_handler"): f_supported = merge_fn( @@ -162,9 +169,7 @@ def _nested_get(f, base_set, merge_fn, get_fn, wrapper=set): ) out = merge_fn(wrapper(f_supported), out) continue - elif "frontend" in fn.__module__ or ( - hasattr(fn, "__name__") and "einops" in fn.__name__ - ): + elif is_frontend_fn or (hasattr(fn, "__name__") and is_einops_fn): f_supported = wrapper(get_fn(fn, False)) out = merge_fn(f_supported, out) @@ -174,8 +179,36 @@ def _nested_get(f, base_set, merge_fn, get_fn, wrapper=set): continue fl = _get_function_list(fn) - res = _get_functions_from_string(fl, __import__(fn.__module__)) - to_visit.extend(res) + res = list(_get_functions_from_string(fl, __import__(fn.__module__))) + if is_frontend_fn: + frontends = { + "jax_frontend": "ivy.functional.frontends.jax", + "jnp_frontend": "ivy.functional.frontends.jax.numpy", + "np_frontend": "ivy.functional.frontends.numpy", + "tf_frontend": "ivy.functional.frontends.tensorflow", + "torch_frontend": "ivy.functional.frontends.torch", + "paddle_frontend": "ivy.functional.frontends.paddle", + } + for key in fl: + if "frontend" in key: + frontend_fn = fl[key] + for frontend in frontends: + if frontend in key: + key = key.replace(frontend, frontends[frontend]) + if "(" in key: + key = key.split("(")[0] + frontend_module = ".".join(key.split(".")[:-1]) + if ( + frontend_module == "" + ): # single edge case: fn='frontend_outputs_to_ivy_arrays' + continue + frontend_fl = {key: frontend_fn} + res += list( + _get_functions_from_string( + frontend_fl, importlib.import_module(frontend_module) + ) + ) + to_visit.extend(set(res)) return out @@ -208,8 +241,8 @@ def _get_dtypes(fn, complement=True): # We only care about getting dtype info from the base function # if we do need to at some point use dtype information from the parent function # we can comment out the following condition - is_backend_fn = "backend" in fn.__module__ is_frontend_fn = "frontend" in fn.__module__ + is_backend_fn = "backend" in fn.__module__ and not is_frontend_fn has_unsupported_dtypes_attr = hasattr(fn, "unsupported_dtypes") if not is_backend_fn and not is_frontend_fn and not has_unsupported_dtypes_attr: if complement: @@ -265,8 +298,8 @@ def astype( copy: bool = True, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Copy an array to a specified data type irrespective of :ref:`type- promotion` rules. + """Copy an array to a specified data type irrespective of :ref:`type- + promotion` rules. .. note:: Casting floating-point ``NaN`` and ``infinity`` values to integral data types @@ -365,8 +398,7 @@ def astype( @handle_array_function @handle_device def broadcast_arrays(*arrays: Union[ivy.Array, ivy.NativeArray]) -> List[ivy.Array]: - """ - Broadcasts one or more arrays against one another. + """Broadcasts one or more arrays against one another. Parameters ---------- @@ -453,8 +485,7 @@ def broadcast_to( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Broadcasts an array to a specified shape. + """Broadcasts an array to a specified shape. Parameters ---------- @@ -522,9 +553,8 @@ def can_cast( to: ivy.Dtype, /, ) -> bool: - """ - Determine if one data type can be cast to another data type according to :ref:`type- - promotion` rules. + """Determine if one data type can be cast to another data type according to + :ref:`type- promotion` rules. Parameters ---------- @@ -597,8 +627,7 @@ def finfo( type: Union[ivy.Dtype, str, ivy.Array, ivy.NativeArray], /, ) -> Finfo: - """ - Machine limits for floating-point data types. + """Machine limits for floating-point data types. Parameters ---------- @@ -656,7 +685,7 @@ def finfo( >>> x = ivy.array([1.3,2.1,3.4], dtype=ivy.float64) >>> print(ivy.finfo(x)) - finfo(resolution=1e-15, min=-1.7976931348623157e+308, / + finfo(resolution=1e-15, min=-1.7976931348623157e+308, \ max=1.7976931348623157e+308, dtype=float64) >>> x = ivy.array([0.7,8.4,3.14], dtype=ivy.float16) @@ -670,7 +699,7 @@ def finfo( >>> print(ivy.finfo(c)) { x: finfo(resolution=0.001, min=-6.55040e+04, max=6.55040e+04, dtype=float16), - y: finfo(resolution=1e-15, min=-1.7976931348623157e+308, / + y: finfo(resolution=1e-15, min=-1.7976931348623157e+308, \ max=1.7976931348623157e+308, dtype=float64) } """ @@ -685,8 +714,7 @@ def iinfo( type: Union[ivy.Dtype, str, ivy.Array, ivy.NativeArray], /, ) -> Iinfo: - """ - Machine limits for integer data types. + """Machine limits for integer data types. Parameters ---------- @@ -762,9 +790,8 @@ def iinfo( def result_type( *arrays_and_dtypes: Union[ivy.Array, ivy.NativeArray, ivy.Dtype] ) -> ivy.Dtype: - """ - Return the dtype that results from applying the type promotion rules (see - :ref:`type-promotion`) to the arguments. + """Return the dtype that results from applying the type promotion rules + (see :ref:`type-promotion`) to the arguments. .. note:: If provided mixed dtypes (e.g., integer and floating-point), the returned dtype @@ -917,8 +944,7 @@ def __exit__(self, exc_type, exc_val, exc_tb): @handle_exceptions def dtype_bits(dtype_in: Union[ivy.Dtype, ivy.NativeDtype, str], /) -> int: - """ - Get the number of bits used for representing the input data type. + """Get the number of bits used for representing the input data type. Parameters ---------- @@ -953,8 +979,7 @@ def dtype_bits(dtype_in: Union[ivy.Dtype, ivy.NativeDtype, str], /) -> int: @handle_exceptions def is_hashable_dtype(dtype_in: Union[ivy.Dtype, ivy.NativeDtype], /) -> bool: - """ - Check if the given data type is hashable or not. + """Check if the given data type is hashable or not. Parameters ---------- @@ -979,8 +1004,7 @@ def is_hashable_dtype(dtype_in: Union[ivy.Dtype, ivy.NativeDtype], /) -> bool: @handle_exceptions def as_ivy_dtype(dtype_in: Union[ivy.Dtype, str], /) -> ivy.Dtype: - """ - Convert native data type to string representation. + """Convert native data type to string representation. Parameters ---------- @@ -997,8 +1021,7 @@ def as_ivy_dtype(dtype_in: Union[ivy.Dtype, str], /) -> ivy.Dtype: @handle_exceptions def as_native_dtype(dtype_in: Union[ivy.Dtype, ivy.NativeDtype], /) -> ivy.NativeDtype: - """ - Convert data type string representation to native data type. + """Convert data type string representation to native data type. Parameters ---------- @@ -1034,8 +1057,7 @@ def _check_complex128(input) -> bool: @handle_exceptions def closest_valid_dtype(type: Union[ivy.Dtype, str, None], /) -> Union[ivy.Dtype, str]: - """ - Determine the closest valid datatype to the datatype passed as input. + """Determine the closest valid datatype to the datatype passed as input. Parameters ---------- @@ -1172,8 +1194,7 @@ def default_float_dtype( def infer_default_dtype( dtype: Union[ivy.Dtype, ivy.NativeDtype, str], as_native: bool = False ) -> Union[ivy.Dtype, ivy.NativeDtype]: - """ - Summary. + """Summary. Parameters ---------- @@ -1629,8 +1650,7 @@ def default_complex_dtype( def dtype( x: Union[ivy.Array, ivy.NativeArray], *, as_native: bool = False ) -> Union[ivy.Dtype, ivy.NativeDtype]: - """ - Get the data type for input array x. + """Get the data type for input array x. Parameters ---------- @@ -1674,10 +1694,10 @@ def dtype( @handle_exceptions @handle_nestable def function_supported_dtypes(fn: Callable, recurse: bool = True) -> Union[Tuple, dict]: - """ - Return the supported data types of the current backend's function. The function - returns a dict containing the supported dtypes for the compositional and primary - implementations in case of partial mixed functions. + """Return the supported data types of the current backend's function. The + function returns a dict containing the supported dtypes for the + compositional and primary implementations in case of partial mixed + functions. Parameters ---------- @@ -1725,10 +1745,10 @@ def function_supported_dtypes(fn: Callable, recurse: bool = True) -> Union[Tuple def function_unsupported_dtypes( fn: Callable, recurse: bool = True ) -> Union[Tuple, dict]: - """ - Return the unsupported data types of the current backend's function. The function - returns a dict containing the unsupported dtypes for the compositional and primary - implementations in case of partial mixed functions. + """Return the unsupported data types of the current backend's function. The + function returns a dict containing the unsupported dtypes for the + compositional and primary implementations in case of partial mixed + functions. Parameters ---------- @@ -1774,8 +1794,8 @@ def function_unsupported_dtypes( @handle_exceptions def invalid_dtype(dtype_in: Union[ivy.Dtype, ivy.NativeDtype, str, None], /) -> bool: - """ - Determine whether the provided data type is not support by the current framework. + """Determine whether the provided data type is not support by the current + framework. Parameters ---------- @@ -1813,8 +1833,7 @@ def is_bool_dtype( dtype_in: Union[ivy.Dtype, str, ivy.Array, ivy.NativeArray, Number], /, ) -> bool: - """ - Determine whether the input data type is a bool data type. + """Determine whether the input data type is a bool data type. Parameters ---------- @@ -1853,8 +1872,7 @@ def is_int_dtype( dtype_in: Union[ivy.Dtype, str, ivy.Array, ivy.NativeArray, Number], /, ) -> bool: - """ - Determine whether the input data type is an int data type. + """Determine whether the input data type is an int data type. Parameters ---------- @@ -1929,8 +1947,7 @@ def nested_fun(x): @handle_exceptions def check_float(x: Any) -> bool: - """ - Check if the input is a float or a float-like object. + """Check if the input is a float or a float-like object. Parameters ---------- @@ -1952,8 +1969,7 @@ def is_float_dtype( dtype_in: Union[ivy.Dtype, str, ivy.Array, ivy.NativeArray, Number], /, ) -> bool: - """ - Determine whether the input data type is a float dtype. + """Determine whether the input data type is a float dtype. Parameters ---------- @@ -2001,8 +2017,7 @@ def is_uint_dtype( dtype_in: Union[ivy.Dtype, str, ivy.Array, ivy.NativeArray, Number], /, ) -> bool: - """ - Determine whether the input data type is a uint dtype. + """Determine whether the input data type is a uint dtype. Parameters ---------- @@ -2049,8 +2064,7 @@ def is_complex_dtype( dtype_in: Union[ivy.Dtype, str, ivy.Array, ivy.NativeArray, Number], /, ) -> bool: - """ - Determine whether the input data type is a complex dtype. + """Determine whether the input data type is a complex dtype. Parameters ---------- @@ -2098,8 +2112,8 @@ def promote_types( *, array_api_promotion: bool = False, ) -> ivy.Dtype: - """ - Promote the datatypes type1 and type2, returning the data type they promote to. + """Promote the datatypes type1 and type2, returning the data type they + promote to. Parameters ---------- @@ -2133,8 +2147,7 @@ def _promote(query): @handle_exceptions def set_default_dtype(dtype: Union[ivy.Dtype, ivy.NativeDtype, str], /): - """ - Set the datatype `dtype` as default data type. + """Set the datatype `dtype` as default data type. Parameters ---------- @@ -2169,8 +2182,7 @@ def set_default_dtype(dtype: Union[ivy.Dtype, ivy.NativeDtype, str], /): @handle_exceptions def set_default_float_dtype(float_dtype: Union[ivy.Dtype, str], /): - """ - Set the 'float_dtype' as the default data type. + """Set the 'float_dtype' as the default data type. Parameters ---------- @@ -2197,8 +2209,7 @@ def set_default_float_dtype(float_dtype: Union[ivy.Dtype, str], /): @handle_exceptions def set_default_int_dtype(int_dtype: Union[ivy.Dtype, str], /): - """ - Set the 'int_dtype' as the default data type. + """Set the 'int_dtype' as the default data type. Parameters ---------- @@ -2225,8 +2236,7 @@ def set_default_int_dtype(int_dtype: Union[ivy.Dtype, str], /): @handle_exceptions def set_default_uint_dtype(uint_dtype: Union[ivy.Dtype, str], /): - """ - Set the uint dtype to be default. + """Set the uint dtype to be default. Parameters ---------- @@ -2251,8 +2261,7 @@ def set_default_uint_dtype(uint_dtype: Union[ivy.Dtype, str], /): @handle_exceptions def set_default_complex_dtype(complex_dtype: Union[ivy.Dtype, str], /): - """ - Set the 'complex_dtype' as the default data type. + """Set the 'complex_dtype' as the default data type. Parameters ---------- @@ -2283,9 +2292,8 @@ def type_promote_arrays( x2: Union[ivy.Array, ivy.NativeArray], /, ) -> Tuple: - """ - Type promote the input arrays, returning new arrays with the shared correct data - type. + """Type promote the input arrays, returning new arrays with the shared + correct data type. Parameters ---------- @@ -2305,8 +2313,7 @@ def type_promote_arrays( @handle_exceptions def unset_default_dtype(): - """ - Reset the current default dtype to the previous state. + """Reset the current default dtype to the previous state. Examples -------- @@ -2330,8 +2337,7 @@ def unset_default_dtype(): @handle_exceptions def unset_default_float_dtype(): - """ - Reset the current default float dtype to the previous state. + """Reset the current default float dtype to the previous state. Examples -------- @@ -2351,8 +2357,7 @@ def unset_default_float_dtype(): @handle_exceptions def unset_default_int_dtype(): - """ - Reset the current default int dtype to the previous state. + """Reset the current default int dtype to the previous state. Examples -------- @@ -2371,8 +2376,7 @@ def unset_default_int_dtype(): @handle_exceptions def unset_default_uint_dtype(): - """ - Reset the current default uint dtype to the previous state. + """Reset the current default uint dtype to the previous state. Examples -------- @@ -2391,8 +2395,7 @@ def unset_default_uint_dtype(): @handle_exceptions def unset_default_complex_dtype(): - """ - Reset the current default complex dtype to the previous state. + """Reset the current default complex dtype to the previous state. Examples -------- @@ -2412,8 +2415,8 @@ def unset_default_complex_dtype(): @handle_exceptions def valid_dtype(dtype_in: Union[ivy.Dtype, ivy.NativeDtype, str, None], /) -> bool: - """ - Determine whether the provided data type is supported by the current framework. + """Determine whether the provided data type is supported by the current + framework. Parameters ---------- @@ -2452,9 +2455,8 @@ def promote_types_of_inputs( *, array_api_promotion: bool = False, ) -> Tuple[ivy.NativeArray, ivy.NativeArray]: - """ - Promote the dtype of the given native array inputs to a common dtype based on type - promotion rules. + """Promote the dtype of the given native array inputs to a common dtype + based on type promotion rules. While passing float or integer values or any other non-array input to this function, it should be noted that the return will be an @@ -2502,8 +2504,7 @@ def _get_target_dtype(scalar, arr): @handle_exceptions def is_native_dtype(dtype_in: Union[ivy.Dtype, ivy.NativeDtype], /) -> bool: - """ - Determine whether the input dtype is a Native dtype. + """Determine whether the input dtype is a Native dtype. Parameters ---------- diff --git a/ivy/functional/ivy/device.py b/ivy/functional/ivy/device.py index d887aad881d5e..b3c1c7a72845b 100644 --- a/ivy/functional/ivy/device.py +++ b/ivy/functional/ivy/device.py @@ -33,6 +33,7 @@ from ivy.func_wrapper import ( handle_out_argument, to_native_arrays_and_back, + inputs_to_native_arrays, handle_nestable, handle_array_like_without_promotion, handle_backend_invalid, @@ -58,8 +59,7 @@ def __init__( device: Union[ivy.Device, ivy.NativeDevice], /, ) -> None: - """ - Initialize the DefaultDevice class. + """Initialize the DefaultDevice class. Parameters ---------- @@ -75,8 +75,7 @@ def __init__( self._dev = device def __enter__(self): - """ - Enter the runtime context related to the specified device. + """Enter the runtime context related to the specified device. Returns ------- @@ -102,8 +101,7 @@ def __exit__( exc_val: Optional[Type[BaseException]], exc_tb: Optional[types.TracebackType], ) -> Union[ivy.Device, str]: - """ - Exit the runtime context related to the specified device. + """Exit the runtime context related to the specified device. Parameters ---------- @@ -164,7 +162,7 @@ def _shift_native_arrays_on_default_device(*args, **kwargs): ), [args, kwargs], ) - return args, kwargs, default_device + return args, kwargs, ivy.as_native_dev(default_device) # Device Queries # @@ -177,8 +175,7 @@ def get_all_ivy_arrays_on_dev( device: Union[ivy.Device, ivy.NativeDevice], /, ) -> ivy.Container: - """ - Get all ivy arrays which are currently alive on the specified device. + """Get all ivy arrays which are currently alive on the specified device. Parameters ---------- @@ -213,8 +210,8 @@ def get_all_ivy_arrays_on_dev( @handle_exceptions def num_ivy_arrays_on_dev(device: Union[ivy.Device, ivy.NativeDevice], /) -> int: - """ - Return the number of arrays which are currently alive on the specified device. + """Return the number of arrays which are currently alive on the specified + device. Parameters ---------- @@ -255,9 +252,8 @@ def print_all_ivy_arrays_on_dev( device: Optional[Union[ivy.Device, ivy.NativeDevice]] = None, attr_only: bool = True, ) -> None: - """ - Print the shape and dtype for all ivy arrays which are currently alive on the - specified device. + """Print the shape and dtype for all ivy arrays which are currently alive + on the specified device. Parameters ---------- @@ -294,14 +290,14 @@ def print_all_ivy_arrays_on_dev( @handle_exceptions def set_soft_device_mode(mode: bool) -> None: - """ - Set the mode of whether to move input arrays to `ivy.default_device()` before - performing an operation. + """Set the mode of whether to move input arrays to `ivy.default_device()` + before performing an operation. Parameter --------- mode boolean whether to move input arrays + Examples -------- >>> ivy.set_soft_device_mode(False) @@ -319,9 +315,8 @@ def set_soft_device_mode(mode: bool) -> None: @handle_exceptions def unset_soft_device_mode() -> None: - """ - Reset the mode of moving input arrays to `ivy.default_device()` before performing an - operation. + """Reset the mode of moving input arrays to `ivy.default_device()` before + performing an operation. Examples -------- @@ -345,12 +340,11 @@ def unset_soft_device_mode() -> None: @handle_exceptions @handle_backend_invalid @handle_nestable -@to_native_arrays_and_back +@inputs_to_native_arrays def dev( x: Union[ivy.Array, ivy.NativeArray], /, *, as_native: bool = False ) -> Union[ivy.Device, ivy.NativeDevice]: - """ - Get the native device handle for input array x. + """Get the native device handle for input array x. Parameters ---------- @@ -388,8 +382,7 @@ def dev( @handle_exceptions def as_ivy_dev(device: Union[ivy.Device, str], /) -> ivy.Device: - """ - Convert device to string representation. + """Convert device to string representation. Parameters ---------- @@ -412,8 +405,7 @@ def as_ivy_dev(device: Union[ivy.Device, str], /) -> ivy.Device: @handle_exceptions def as_native_dev(device: Union[ivy.Device, ivy.NativeDevice], /) -> ivy.NativeDevice: - """ - Convert device string representation to native device type. + """Convert device string representation to native device type. Parameters ---------- @@ -457,8 +449,7 @@ def as_native_dev(device: Union[ivy.Device, ivy.NativeDevice], /) -> ivy.NativeD @handle_exceptions def clear_cached_mem_on_dev(device: Union[ivy.Device, ivy.NativeDevice], /) -> None: - """ - Clear memory cache on target device. + """Clear memory cache on target device. Parameters ---------- @@ -477,9 +468,8 @@ def clear_cached_mem_on_dev(device: Union[ivy.Device, ivy.NativeDevice], /) -> N @handle_exceptions def total_mem_on_dev(device: Union[ivy.Device, ivy.NativeDevice], /) -> float: - """ - Get the total amount of memory (in GB) for a given device string. In case of CPU, - the total RAM is returned. + """Get the total amount of memory (in GB) for a given device string. In + case of CPU, the total RAM is returned. Parameters ---------- @@ -521,9 +511,8 @@ def used_mem_on_dev( *, process_specific: bool = False, ) -> float: - """ - Get the used memory (in GB) for a given device string. In case of CPU, the used RAM - is returned. + """Get the used memory (in GB) for a given device string. In case of CPU, + the used RAM is returned. Parameters ---------- @@ -581,9 +570,8 @@ def percent_used_mem_on_dev( *, process_specific: bool = False, ) -> float: - """ - Get the percentage used memory for a given device string. In case of CPU, the used - RAM is returned. + """Get the percentage used memory for a given device string. In case of + CPU, the used RAM is returned. Parameters ---------- @@ -643,8 +631,7 @@ def dev_util( device: Union[ivy.Device, ivy.NativeDevice], /, ) -> float: - """ - Get the current utilization (%) for a given device. + """Get the current utilization (%) for a given device. Parameters ---------- @@ -686,8 +673,7 @@ def dev_util( @handle_exceptions def gpu_is_available() -> bool: - """ - Determine whether a GPU is available to use, with the backend framework. + """Determine whether a GPU is available to use, with the backend framework. Returns ------- @@ -704,8 +690,7 @@ def gpu_is_available() -> bool: @handle_exceptions def num_cpu_cores(*, logical: bool = True) -> int: - """ - Determine the number of cores available in the cpu. + """Determine the number of cores available in the cpu. Parameters ---------- @@ -730,8 +715,7 @@ def num_cpu_cores(*, logical: bool = True) -> int: @handle_exceptions def num_gpus() -> int: - """ - Determine the number of available GPUs, with the backend framework. + """Determine the number of available GPUs, with the backend framework. Returns ------- @@ -748,8 +732,7 @@ def num_gpus() -> int: @handle_exceptions def tpu_is_available() -> bool: - """ - Determine whether a TPU is available to use, with the backend framework. + """Determine whether a TPU is available to use, with the backend framework. Returns ------- @@ -760,7 +743,7 @@ def tpu_is_available() -> bool: -------- >>> ivy.set_backend("torch") >>> print(ivy.tpu_is_available()) - True + False """ return ivy.current_backend().tpu_is_available() @@ -775,14 +758,13 @@ def default_device( /, *, item: Optional[Union[list, tuple, dict, ivy.Array, ivy.NativeArray]] = None, - as_native: bool = None, + as_native: Optional[bool] = None, ) -> Union[ivy.Device, ivy.NativeDevice]: - """ - Return the input device or the default device. If the as_native flag is set, the - device will be converted to a native device. If the item is provided, the item's - device is returned. If the device is not provided, the last default device is - returned. If a default device has not been set, the first gpu is returned if - available, otherwise the cpu is returned. + """Return the input device or the default device. If the as_native flag is + set, the device will be converted to a native device. If the item is + provided, the item's device is returned. If the device is not provided, the + last default device is returned. If a default device has not been set, the + first gpu is returned if available, otherwise the cpu is returned. Parameters ---------- @@ -844,31 +826,47 @@ def default_device( @handle_exceptions def set_default_device(device: Union[ivy.Device, ivy.NativeDevice], /) -> None: - """ - Set the default device to given device instance. + """Sets the default device to the argument provided in the function. Parameters ---------- device - The device to set as the default device + The device to be set as the default device. + + Returns + ------- + ret + The new default device. Examples -------- - >>> ivy.set_default_device("cpu") >>> ivy.default_device() 'cpu' - >>> ivy.set_backend("torch") - >>> ivy.set_default_device("gpu:0") - >>> ivy.default_device(as_native=True) - device(type='cuda', index=0) + >>> ivy.set_backend('jax') + >>> ivy.set_default_device('gpu:0') + >>> ivy.default_device() + 'gpu:0' - >>> import torch - >>> ivy.set_backend("torch") - >>> device = torch.device("cuda") - >>> ivy.set_default_device(device) - >>> ivy.default_device(as_native=True) - device(type='cuda') + >>> ivy.set_backend('torch') + >>> ivy.set_default_device('gpu:1') + >>> ivy.default_device() + 'gpu:1 + + >>> ivy.set_backend('tensorflow') + >>> ivy.set_default_device('tpu:0) + >>> ivy.default_device() + 'tpu:0 + + >>> ivy.set_backend('paddle') + >>> ivy.set_default_device('cpu) + >>> ivy.default_device() + 'cpu' + + >>> ivy.set_backend('mxnet') + >>> ivy.set_default_device('cpu') + >>> ivy.default_device() + 'cpu' """ global default_device_stack default_device_stack.append(device) @@ -876,8 +874,7 @@ def set_default_device(device: Union[ivy.Device, ivy.NativeDevice], /) -> None: @handle_exceptions def unset_default_device() -> None: - """ - Reset the default device to "cpu". + """Reset the default device to "cpu". Examples -------- @@ -910,8 +907,8 @@ def to_device( stream: Optional[Union[int, Any]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Move the input array x to the desired device, specified by device string. + """Move the input array x to the desired device, specified by device + string. Parameters ---------- @@ -951,9 +948,8 @@ def split_factor( device: Optional[Union[ivy.Device, ivy.NativeDevice]] = None, /, ) -> float: - """ - Get a device's global split factor, which can be used to scale the device's batch - splitting chunk sizes across the codebase. + """Get a device's global split factor, which can be used to scale the + device's batch splitting chunk sizes across the codebase. If the global split factor is set for a given device, returns the split factor value for the device from the split factors dictionary @@ -989,9 +985,8 @@ def split_factor( def set_split_factor( factor: float, /, *, device: Optional[Union[ivy.Device, ivy.NativeDevice]] = None ) -> None: - """ - Set the global split factor for a given device, which can be used to scale batch - splitting chunk sizes for the device across the codebase. + """Set the global split factor for a given device, which can be used to + scale batch splitting chunk sizes for the device across the codebase. Parameters ---------- @@ -1048,10 +1043,9 @@ def split_func_call( stop_gradients: bool = False, device: Optional[Union[ivy.Device, ivy.NativeDevice]] = None, ) -> Union[ivy.Array, ivy.NativeArray]: - """ - Call a function by splitting its inputs along a given axis, and calling the function - in chunks, rather than feeding the entire input array at once. This can be useful to - reduce memory usage of the device the arrays are on. + """Call a function by splitting its inputs along a given axis, and calling + the function in chunks, rather than feeding the entire input array at once. + This can be useful to reduce memory usage of the device the arrays are on. Parameters ---------- @@ -1192,7 +1186,7 @@ def _get_devices(fn: Callable, complement: bool = True) -> Tuple: is_backend_fn = "backend" in fn.__module__ is_frontend_fn = "frontend" in fn.__module__ - is_einops_fn = "einops" in fn.__name__ + is_einops_fn = hasattr(fn, "__name__") and "einops" in fn.__name__ if not is_backend_fn and not is_frontend_fn and not is_einops_fn: if complement: supported = set(all_devices).difference(supported) @@ -1224,10 +1218,10 @@ def _get_devices(fn: Callable, complement: bool = True) -> Tuple: def function_supported_devices( fn: Callable, recurse: bool = True ) -> Union[Tuple, dict]: - """ - Return the supported devices of the current backend's function. The function returns - a dict containing the supported devices for the compositional and primary - implementations in case of partial mixed functions. + """Return the supported devices of the current backend's function. The + function returns a dict containing the supported devices for the + compositional and primary implementations in case of partial mixed + functions. Parameters ---------- @@ -1244,7 +1238,13 @@ def function_supported_devices( Examples -------- >>> import ivy + >>> ivy.set_backend('numpy') >>> print(ivy.function_supported_devices(ivy.ones)) + ('cpu',) + + >>> ivy.set_backend('torch') + >>> x = ivy.function_supported_devices(ivy.ones) + >>> x = sorted(x) ('cpu', 'gpu') """ ivy.utils.assertions.check_true( @@ -1276,10 +1276,10 @@ def function_supported_devices( def function_unsupported_devices( fn: Callable, recurse: bool = True ) -> Union[Tuple, dict]: - """ - Return the unsupported devices of the current backend's function. The function - returns a dict containing the unsupported devices for the compositional and primary - implementations in case of partial mixed functions. + """Return the unsupported devices of the current backend's function. The + function returns a dict containing the unsupported devices for the + compositional and primary implementations in case of partial mixed + functions. Parameters ---------- @@ -1325,8 +1325,7 @@ def function_unsupported_devices( class Profiler(abc.ABC): - """ - The profiler class is used to profile the execution of some code. + """The profiler class is used to profile the execution of some code. Parameters ---------- @@ -1339,8 +1338,7 @@ def __init__(self, save_dir: str): @abc.abstractmethod def start(self): - """ - Start the profiler. + """Start the profiler. This should be called before the code to be profiled. """ @@ -1348,8 +1346,7 @@ def start(self): @abc.abstractmethod def stop(self): - """ - Stop the profiler. + """Stop the profiler. This should be called after the code to be profiled. """ diff --git a/ivy/functional/ivy/elementwise.py b/ivy/functional/ivy/elementwise.py index 3e19091c21cba..793da8e10e05d 100644 --- a/ivy/functional/ivy/elementwise.py +++ b/ivy/functional/ivy/elementwise.py @@ -36,10 +36,9 @@ def abs( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: # noqa - """ - Calculate the absolute value for each element ``x_i`` of the input array ``x`` - (i.e., the element-wise result has the same magnitude as the respective element in - ``x`` but has positive sign). + """Calculate the absolute value for each element ``x_i`` of the input array + ``x`` (i.e., the element-wise result has the same magnitude as the + respective element in ``x`` but has positive sign). .. note:: For signed integer data types, the absolute value of the minimum representable @@ -122,8 +121,7 @@ def abs( a: ivy.array([0., 2.6, 3.5]), b: ivy.array([4.5, 5.3, 0., 2.3]) } - """ - + """ # noqa: E501 return ivy.current_backend(x).abs(x, out=out) @@ -141,10 +139,10 @@ def acos( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Calculate an implementation-dependent approximation of the principal value of the - inverse cosine, having domain [-1, +1] and codomain [+0, +ฯ€], for each element x_i - of the input array x. Each element-wise result is expressed in radians. + """Calculate an implementation-dependent approximation of the principal + value of the inverse cosine, having domain [-1, +1] and codomain [+0, +ฯ€], + for each element x_i of the input array x. Each element-wise result is + expressed in radians. **Special cases** @@ -251,10 +249,9 @@ def acosh( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Calculate an implementation-dependent approximation to the inverse hyperbolic - cosine, having domain ``[+1, +infinity]`` and codomain ``[+0, +infinity]``, for each - element ``x_i`` of the input array ``x``. + """Calculate an implementation-dependent approximation to the inverse + hyperbolic cosine, having domain ``[+1, +infinity]`` and codomain ``[+0, + +infinity]``, for each element ``x_i`` of the input array ``x``. **Special cases** @@ -336,7 +333,7 @@ def acosh( With :class:`ivy.Container` input: - >>> x = ivy.Container(a=ivy.array([1, 2, 10]), b=ivy.array([1., 10, 6])) + >>> x = ivy.Container(a=ivy.array([1., 2., 10.]), b=ivy.array([1., 10., 6.])) >>> y = ivy.acosh(x) >>> print(y) { @@ -362,9 +359,8 @@ def add( alpha: Optional[Union[int, float]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Calculate the sum for each element ``x1_i`` of the input array ``x1`` with the - respective element ``x2_i`` of the input array ``x2``. + """Calculate the sum for each element ``x1_i`` of the input array ``x1`` + with the respective element ``x2_i`` of the input array ``x2``. **Special cases** @@ -512,11 +508,10 @@ def asin( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Calculate an implementation-dependent approximation of the principal value of the - inverse sine, having domain ``[-1, +1]`` and codomain ``[-ฯ€/2, +ฯ€/2]`` for each - element ``x_i`` of the input array ``x``. Each element- wise result is expressed in - radians. + """Calculate an implementation-dependent approximation of the principal + value of the inverse sine, having domain ``[-1, +1]`` and codomain ``[-ฯ€/2, + +ฯ€/2]`` for each element ``x_i`` of the input array ``x``. Each element- + wise result is expressed in radians. **Special cases** @@ -601,10 +596,10 @@ def asinh( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Calculate an implementation-dependent approximation to the inverse hyperbolic sine, - having domain ``[-infinity, +infinity]`` and codomain ``[-infinity, +infinity]``, - for each element ``x_i`` in the input array ``x``. + """Calculate an implementation-dependent approximation to the inverse + hyperbolic sine, having domain ``[-infinity, +infinity]`` and codomain + ``[-infinity, +infinity]``, for each element ``x_i`` in the input array + ``x``. **Special cases** @@ -710,11 +705,10 @@ def atan( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Calculate an implementation-dependent approximation of the principal value of the - inverse tangent, having domain ``[-infinity, +infinity]`` and codomain ``[-ฯ€/2, - +ฯ€/2]``, for each element ``x_i`` of the input array ``x``. Each element-wise result - is expressed in radians. + """Calculate an implementation-dependent approximation of the principal + value of the inverse tangent, having domain ``[-infinity, +infinity]`` and + codomain ``[-ฯ€/2, +ฯ€/2]``, for each element ``x_i`` of the input array + ``x``. Each element-wise result is expressed in radians. **Special cases** @@ -795,17 +789,17 @@ def atan2( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Calculate an implementation-dependent approximation of the inverse tangent of the - quotient ``x1/x2``, having domain ``[-infinity, +infinity] x. [-infinity, - +infinity]`` (where the ``x`` notation denotes the set of ordered pairs of elements - ``(x1_i, x2_i)``) and codomain ``[-ฯ€, +ฯ€]``, for each pair of elements ``(x1_i, - x2_i)`` of the input arrays ``x1`` and ``x2``, respectively. Each element-wise - result is expressed in radians. The mathematical signs of ``x1_i and x2_i`` - determine the quadrant of each element-wise result. The quadrant (i.e., branch) is - chosen such that each element-wise result is the signed angle in radians between the - ray ending at the origin and passing through the point ``(1,0)`` and the ray ending - at the origin and passing through the point ``(x2_i, x1_i)``. + """Calculate an implementation-dependent approximation of the inverse + tangent of the quotient ``x1/x2``, having domain ``[-infinity, +infinity] + x. [-infinity, +infinity]`` (where the ``x`` notation denotes the set of + ordered pairs of elements ``(x1_i, x2_i)``) and codomain ``[-ฯ€, +ฯ€]``, for + each pair of elements ``(x1_i, x2_i)`` of the input arrays ``x1`` and + ``x2``, respectively. Each element-wise result is expressed in radians. The + mathematical signs of ``x1_i and x2_i`` determine the quadrant of each + element-wise result. The quadrant (i.e., branch) is chosen such that each + element-wise result is the signed angle in radians between the ray ending + at the origin and passing through the point ``(1,0)`` and the ray ending at + the origin and passing through the point ``(x2_i, x1_i)``. **Special cases** @@ -971,8 +965,8 @@ def atanh( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return a new array with the inverse hyperbolic tangent of the elements of ``x``. + """Return a new array with the inverse hyperbolic tangent of the elements + of ``x``. Parameters ---------- @@ -1074,10 +1068,9 @@ def bitwise_and( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the bitwise AND of the underlying binary representation of each element - ``x1_i`` of the input array ``x1`` with the respective element ``x2_i`` of the input - array ``x2``. + """Compute the bitwise AND of the underlying binary representation of each + element ``x1_i`` of the input array ``x1`` with the respective element + ``x2_i`` of the input array ``x2``. Parameters ---------- @@ -1168,8 +1161,8 @@ def bitwise_invert( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Inverts (flips) each bit for each element ``x_i`` of the input array ``x``. + """Inverts (flips) each bit for each element ``x_i`` of the input array + ``x``. Parameters ---------- @@ -1207,7 +1200,8 @@ def bitwise_invert( With :class:`ivy.Container` input: - >>> x = ivy.Container(a=[False, True, False], b=[True, True, False]) + >>> x = ivy.Container(a=ivy.array([False, True, False]), + ... b=ivy.array([True, True, False])) >>> y = ivy.bitwise_invert(x) >>> print(y) { @@ -1227,7 +1221,7 @@ def bitwise_invert( >>> x = False >>> y = ivy.bitwise_invert(x) >>> print(y) - ivy.array(True) + True """ return ivy.current_backend(x).bitwise_invert(x, out=out) @@ -1246,10 +1240,9 @@ def bitwise_left_shift( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Shifts the bits of each element ``x1_i`` of the input array ``x1`` to the left by - appending ``x2_i`` (i.e., the respective element in the input array ``x2``) zeros to - the right of ``x1_i``. + """Shifts the bits of each element ``x1_i`` of the input array ``x1`` to + the left by appending ``x2_i`` (i.e., the respective element in the input + array ``x2``) zeros to the right of ``x1_i``. Parameters ---------- @@ -1297,10 +1290,9 @@ def bitwise_or( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the bitwise OR of the underlying binary representation of each element - ``x1_i`` of the input array ``x1`` with the respective element ``x2_i`` of the input - array ``x2``. + """Compute the bitwise OR of the underlying binary representation of each + element ``x1_i`` of the input array ``x1`` with the respective element + ``x2_i`` of the input array ``x2``. Parameters ---------- @@ -1386,9 +1378,9 @@ def bitwise_right_shift( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Shifts the bits of each element ``x1_i`` of the input array ``x1`` to the right - according to the respective element ``x2_i`` of the input array ``x2``. + """Shifts the bits of each element ``x1_i`` of the input array ``x1`` to + the right according to the respective element ``x2_i`` of the input array + ``x2``. .. note:: This operation must be an arithmetic shift (i.e., sign-propagating) and thus @@ -1502,10 +1494,9 @@ def bitwise_xor( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the bitwise XOR of the underlying binary representation of each element - ``x1_i`` of the input array ``x1`` with the respective element ``x2_i`` of the input - array ``x2``. + """Compute the bitwise XOR of the underlying binary representation of each + element ``x1_i`` of the input array ``x1`` with the respective element + ``x2_i`` of the input array ``x2``. Parameters ---------- @@ -1607,9 +1598,9 @@ def ceil( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Round each element ``x_i`` of the input array ``x`` to the smallest (i.e., closest - to ``-infinity``) integer-valued number that is not less than ``x_i``. + """Round each element ``x_i`` of the input array ``x`` to the smallest + (i.e., closest to ``-infinity``) integer-valued number that is not less + than ``x_i``. **Special cases** @@ -1698,10 +1689,10 @@ def cos( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Calculate an implementation-dependent approximation to the cosine, having domain - ``(-infinity, +infinity)`` and codomain ``[-1, +1]``, for each element ``x_i`` of - the input array ``x``. Each element ``x_i`` is assumed to be expressed in radians. + """Calculate an implementation-dependent approximation to the cosine, + having domain ``(-infinity, +infinity)`` and codomain ``[-1, +1]``, for + each element ``x_i`` of the input array ``x``. Each element ``x_i`` is + assumed to be expressed in radians. **Special cases** @@ -1785,10 +1776,9 @@ def cosh( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Calculate an implementation-dependent approximation to the hyperbolic cosine, having - domain ``[-infinity, +infinity]`` and codomain ``[-infinity, +infinity]``, for each - element ``x_i`` in the input array ``x``. + """Calculate an implementation-dependent approximation to the hyperbolic + cosine, having domain ``[-infinity, +infinity]`` and codomain ``[-infinity, + +infinity]``, for each element ``x_i`` in the input array ``x``. **Special cases** @@ -1862,7 +1852,7 @@ def cosh( -------- With :class:`ivy.Array` input: - >>> x = ivy.array([1, 2, 3, 4]) + >>> x = ivy.array([1., 2., 3., 4.]) >>> y = ivy.cosh(x) >>> print(y) ivy.array([1.54,3.76,10.1,27.3]) @@ -1905,9 +1895,8 @@ def divide( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - r""" - Calculate the division for each element x1_i of the input array x1 with the - respective element x2_i of the input array x2. + r"""Calculate the division for each element x1_i of the input array x1 with + the respective element x2_i of the input array x2. **Special Cases** @@ -2097,9 +2086,8 @@ def equal( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the truth value of x1_i == x2_i for each element x1_i of the input array x1 - with the respective element x2_i of the input array x2. + """Compute the truth value of x1_i == x2_i for each element x1_i of the + input array x1 with the respective element x2_i of the input array x2. Parameters ---------- @@ -2214,11 +2202,11 @@ def exp( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Calculate an implementation-dependent approximation to the exponential function, - having domain ``[-infinity, +infinity]`` and codomain ``[+0, +infinity]``, for each - element ``x_i`` of the input array ``x`` (``e`` raised to the power of ``x_i``, - where ``e`` is the base of the natural logarithm). + """Calculate an implementation-dependent approximation to the exponential + function, having domain ``[-infinity, +infinity]`` and codomain ``[+0, + +infinity]``, for each element ``x_i`` of the input array ``x`` (``e`` + raised to the power of ``x_i``, where ``e`` is the base of the natural + logarithm). .. note:: For complex floating-point operands, ``exp(conj(x))`` must @@ -2300,7 +2288,7 @@ def exp( -------- With :class:Number: - >>> x = 3 + >>> x = 3. >>> y = ivy.exp(x) >>> print(y) ivy.array(20.08553692) @@ -2353,9 +2341,8 @@ def imag( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return the imaginary part of a complex number for each element ``x_i`` of the input - array ``val``. + """Return the imaginary part of a complex number for each element ``x_i`` + of the input array ``val``. Parameters ---------- @@ -2407,8 +2394,7 @@ def angle( deg: bool = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Calculate Element-wise the angle for an array of complex numbers(x+yj). + """Calculate Element-wise the angle for an array of complex numbers(x+yj). Parameters ---------- @@ -2451,8 +2437,7 @@ def gcd( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return the greatest common divisor of |x1| and |x2|. + """Return the greatest common divisor of |x1| and |x2|. Parameters ---------- @@ -2493,8 +2478,7 @@ def exp2( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Calculate 2**p for all p in the input array. + """Calculate 2**p for all p in the input array. Parameters ---------- @@ -2534,10 +2518,9 @@ def expm1( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Calculate an implementation-dependent approximation to ``exp(x)-1``, having domain - ``[-infinity, +infinity]`` and codomain ``[-1, +infinity]``, for each element - ``x_i`` of the input array ``x``. + """Calculate an implementation-dependent approximation to ``exp(x)-1``, + having domain ``[-infinity, +infinity]`` and codomain ``[-1, +infinity]``, + for each element ``x_i`` of the input array ``x``. .. note:: The purpose of this function is to calculate ``exp(x)-1.0`` more accurately when @@ -2661,9 +2644,9 @@ def floor( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Round each element ``x_i`` of the input array ``x`` to the greatest (i.e., closest - to ``+infinity``) integer-valued number that is not greater than ``x_i``. + """Round each element ``x_i`` of the input array ``x`` to the greatest + (i.e., closest to ``+infinity``) integer-valued number that is not greater + than ``x_i``. **Special cases** @@ -2752,10 +2735,10 @@ def floor_divide( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - r""" - Round the result of dividing each element x1_i of the input array x1 by the - respective element x2_i of the input array x2 to the greatest (i.e., closest to - +infinity) integer-value number that is not greater than the division result. + r"""Round the result of dividing each element x1_i of the input array x1 by + the respective element x2_i of the input array x2 to the greatest (i.e., + closest to +infinity) integer-value number that is not greater than the + division result. .. note:: For input arrays which promote to an integer data type, @@ -2950,10 +2933,9 @@ def fmin( *, out: Optional[Union[ivy.Array, ivy.NativeArray]] = None, ) -> Union[ivy.Array, ivy.NativeArray]: - """ - Compute the element-wise minimums of two arrays. Differs from ivy.minimum in the - case where one of the elements is NaN. ivy.minimum returns the NaN element while - ivy.fmin returns the non-NaN element. + """Compute the element-wise minimums of two arrays. Differs from + ivy.minimum in the case where one of the elements is NaN. ivy.minimum + returns the NaN element while ivy.fmin returns the non-NaN element. Parameters ---------- @@ -2998,9 +2980,8 @@ def greater( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the truth value of x1_i < x2_i for each element x1_i of the input array x1 - with the respective element x2_i of the input array x2. + """Compute the truth value of x1_i < x2_i for each element x1_i of the + input array x1 with the respective element x2_i of the input array x2. Parameters ---------- @@ -3099,9 +3080,8 @@ def greater_equal( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the truth value of x1_i >= x2_i for each element x1_i of the input array x1 - with the respective element x2_i of the input array x2. + """Compute the truth value of x1_i >= x2_i for each element x1_i of the + input array x1 with the respective element x2_i of the input array x2. Parameters ---------- @@ -3186,9 +3166,8 @@ def less_equal( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the truth value of x1_i <= x2_i for each element x1_i of the input array x1 - with the respective element x2_i of the input array x2. + """Compute the truth value of x1_i <= x2_i for each element x1_i of the + input array x1 with the respective element x2_i of the input array x2. Parameters ---------- @@ -3273,9 +3252,8 @@ def multiply( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - r""" - Calculate the product for each element x1_i of the input array x1 with the - respective element x2_i of the input array x2. + r"""Calculate the product for each element x1_i of the input array x1 with + the respective element x2_i of the input array x2. .. note:: Floating-point multiplication is not always associative due to finite precision. @@ -3459,9 +3437,8 @@ def isfinite( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Test each element ``x_i`` of the input array ``x`` to determine if finite (i.e., not - ``NaN`` and not equal to positive or negative infinity). + """Test each element ``x_i`` of the input array ``x`` to determine if + finite (i.e., not ``NaN`` and not equal to positive or negative infinity). Parameters ---------- @@ -3559,9 +3536,8 @@ def isinf( detect_negative: bool = True, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Test each element x_i of the input array x to determine if equal to positive or - negative infinity. + """Test each element x_i of the input array x to determine if equal to + positive or negative infinity. Parameters ---------- @@ -3682,9 +3658,8 @@ def isnan( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Test each element ``x_i`` of the input array ``x`` to determine whether the element - is ``NaN``. + """Test each element ``x_i`` of the input array ``x`` to determine whether + the element is ``NaN``. Parameters ---------- @@ -3792,9 +3767,9 @@ def less( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the truth value of ``x1_i < x2_i`` for each element ``x1_i`` of the input - array ``x1`` with the respective element ``x2_i`` of the input array ``x2``. + """Compute the truth value of ``x1_i < x2_i`` for each element ``x1_i`` of + the input array ``x1`` with the respective element ``x2_i`` of the input + array ``x2``. Parameters ---------- @@ -3882,10 +3857,10 @@ def log( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Calculate an implementation-dependent approximation to the natural (base ``e``) - logarithm, having domain ``[0, +infinity]`` and codomain ``[-infinity, +infinity]``, - for each element ``x_i`` of the input array ``x``. + """Calculate an implementation-dependent approximation to the natural (base + ``e``) logarithm, having domain ``[0, +infinity]`` and codomain + ``[-infinity, +infinity]``, for each element ``x_i`` of the input array + ``x``. **Special cases** @@ -3983,10 +3958,9 @@ def log10( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - r""" - Calculate an implementation-dependent approximation to the base ``10`` logarithm, - having domain ``[0, +infinity]`` and codomain ``[-infinity, +infinity]``, for each - element ``x_i`` of the input array ``x``. + r"""Calculate an implementation-dependent approximation to the base ``10`` + logarithm, having domain ``[0, +infinity]`` and codomain ``[-infinity, + +infinity]``, for each element ``x_i`` of the input array ``x``. **Special cases** @@ -4078,9 +4052,8 @@ def log1p( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Calculate an implementation-dependent approximation to log(1+x), where log refers to - the natural (base e) logarithm. + """Calculate an implementation-dependent approximation to log(1+x), where + log refers to the natural (base e) logarithm. .. note:: The purpose of this function is to calculate ``log(1+x)`` more accurately @@ -4197,10 +4170,9 @@ def log2( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - r""" - Calculate an implementation-dependent approximation to the base ``2`` logarithm, - having domain ``[0, +infinity]`` and codomain ``[-infinity, +infinity]``, for each - element ``x_i`` of the input array ``x``. + r"""Calculate an implementation-dependent approximation to the base ``2`` + logarithm, having domain ``[0, +infinity]`` and codomain ``[-infinity, + +infinity]``, for each element ``x_i`` of the input array ``x``. **Special cases** @@ -4259,12 +4231,12 @@ def log2( >>> y = ivy.empty_like(x) >>> ivy.log2(x, out=y) >>> print(y) - ivy.array([[nan, 0., 2.58, inf],[inf, nan, nan, nan]]) + ivy.array([[nan, 0., 2.58, inf],[-inf, nan, nan, nan]]) >>> x = ivy.array([[float('nan'), 1, 7.0, float('+inf')], ... [+0, -3.0, -8, float('-inf')]]) >>> ivy.log2(x, out=x) >>> print(x) - ivy.array([[nan, 0., 2.81, inf],[inf, nan, nan, nan]]) + ivy.array([[nan, 0., 2.81, inf],[-inf, nan, nan, nan]]) With :class:`ivy.Container` input: >>> x = ivy.Container(a=ivy.array([0.0, float('nan')]), @@ -4295,10 +4267,9 @@ def logaddexp( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Calculate the logarithm of the sum of exponentiations ``log(exp(x1) + exp(x2))`` for - each element ``x1_i`` of the input array ``x1`` with the respective element ``x2_i`` - of the input array ``x2``. + """Calculate the logarithm of the sum of exponentiations ``log(exp(x1) + + exp(x2))`` for each element ``x1_i`` of the input array ``x1`` with the + respective element ``x2_i`` of the input array ``x2``. **Special cases** @@ -4396,8 +4367,7 @@ def logaddexp2( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Calculate log2(2**x1 + 2**x2). + """Calculate log2(2**x1 + 2**x2). Parameters ---------- @@ -4440,9 +4410,8 @@ def logical_and( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the logical AND for each element x1_i of the input array x1 with the - respective element x2_i of the input array x2. + """Compute the logical AND for each element x1_i of the input array x1 with + the respective element x2_i of the input array x2. Parameters ---------- @@ -4541,8 +4510,8 @@ def logical_not( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the logical NOT for each element ``x_i`` of the input array ``x``. + """Compute the logical NOT for each element ``x_i`` of the input array + ``x``. .. note:: While this specification recommends that this function only accept input arrays @@ -4639,9 +4608,8 @@ def logical_or( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the logical OR for each element ``x1_i`` of the input array ``x1`` with the - respective element ``x2_i`` of the input array ``x2``. + """Compute the logical OR for each element ``x1_i`` of the input array + ``x1`` with the respective element ``x2_i`` of the input array ``x2``. .. note:: While this specification recommends that this function only accept input arrays @@ -4731,10 +4699,9 @@ def logical_xor( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the bitwise XOR of the underlying binary representation of each element - ``x1_i`` of the input array ``x1`` with the respective element ``x2_i`` of the input - array ``x2``. + """Compute the bitwise XOR of the underlying binary representation of each + element ``x1_i`` of the input array ``x1`` with the respective element + ``x2_i`` of the input array ``x2``. Parameters ---------- @@ -4833,9 +4800,9 @@ def nan_to_num( neginf: Optional[Union[float, int]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Replace NaN with zero and infinity with large finite numbers (default behaviour) or - with the numbers defined by the user using the nan, posinf and/or neginf keywords. + """Replace NaN with zero and infinity with large finite numbers (default + behaviour) or with the numbers defined by the user using the nan, posinf + and/or neginf keywords. Parameters ---------- @@ -4892,8 +4859,7 @@ def negative( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return a new array with the negative value of each element in ``x``. + """Return a new array with the negative value of each element in ``x``. .. note:: For signed integer data types, the numerical negative of @@ -4979,9 +4945,9 @@ def not_equal( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the truth value of ``x1_i != x2_i`` for each element ``x1_i`` of the input - array ``x1`` with the respective element ``x2_i`` of the input array ``x2``. + """Compute the truth value of ``x1_i != x2_i`` for each element ``x1_i`` of + the input array ``x1`` with the respective element ``x2_i`` of the input + array ``x2``. **Special Cases** @@ -5162,8 +5128,7 @@ def positive( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return a new array with the positive value of each element in ``x``. + """Return a new array with the positive value of each element in ``x``. Parameters ---------- @@ -5239,11 +5204,10 @@ def pow( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Calculate an implementation-dependent approximation of exponentiation by raising - each element ``x1_i`` (the base) of the input array ``x1`` to the power of ``x2_i`` - (the exponent), where ``x2_i`` is the corresponding element of the input array - ``x2``. + """Calculate an implementation-dependent approximation of exponentiation by + raising each element ``x1_i`` (the base) of the input array ``x1`` to the + power of ``x2_i`` (the exponent), where ``x2_i`` is the corresponding + element of the input array ``x2``. **Special cases** @@ -5385,11 +5349,10 @@ def real( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Test each element ``x_i`` of the input array ``x`` to take only real part from it. - Returns a float array, where it only contains . If element has complex type with - zero complex part, the return value will be that element, else it only returns real - part. + """Test each element ``x_i`` of the input array ``x`` to take only real + part from it. Returns a float array, where it only contains . If element + has complex type with zero complex part, the return value will be that + element, else it only returns real part. Parameters ---------- @@ -5458,9 +5421,8 @@ def remainder( modulus: bool = True, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return the remainder of division for each element ``x1_i`` of the input array ``x1`` - and the respective element ``x2_i`` of the input array ``x2``. + """Return the remainder of division for each element ``x1_i`` of the input + array ``x1`` and the respective element ``x2_i`` of the input array ``x2``. .. note:: This function is equivalent to the Python modulus operator ``x1_i % x2_i``. For @@ -5588,9 +5550,8 @@ def round( decimals: Optional[int] = 0, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Round each element ``x_i`` of the input array ``x`` to the nearest integer-valued - number. + """Round each element ``x_i`` of the input array ``x`` to the nearest + integer-valued number. .. note:: For complex floating-point operands, real and imaginary components @@ -5710,9 +5671,8 @@ def sign( np_variant: Optional[bool] = True, out: Optional[ivy.Array] = None, ) -> ivy.Array: - r""" - Return an indication of the sign of a number for each element ``x_i`` of the input - array ``x``. + r"""Return an indication of the sign of a number for each element ``x_i`` of + the input array ``x``. The sign function (also known as the **signum function**) of a number :math:`x_{i}` is defined as @@ -5819,10 +5779,10 @@ def sin( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - r""" - Calculate an implementation-dependent approximation to the sine, having domain - ``(-infinity, +infinity)`` and codomain ``[-1, +1]``, for each element ``x_i`` of - the input array ``x``. Each element ``x_i`` is assumed to be expressed in radians. + r"""Calculate an implementation-dependent approximation to the sine, having + domain ``(-infinity, +infinity)`` and codomain ``[-1, +1]``, for each + element ``x_i`` of the input array ``x``. Each element ``x_i`` is assumed + to be expressed in radians. .. note:: The sine is an entire function on the complex plane and has no branch cuts. @@ -5914,10 +5874,9 @@ def sinh( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - r""" - Calculate an implementation-dependent approximation to the hyperbolic sine, having - domain ``[-infinity, +infinity]`` and codomain ``[-infinity, +infinity]``, for each - element ``x_i`` of the input array ``x``. + r"""Calculate an implementation-dependent approximation to the hyperbolic + sine, having domain ``[-infinity, +infinity]`` and codomain ``[-infinity, + +infinity]``, for each element ``x_i`` of the input array ``x``. .. math:: \operatorname{sinh}(x) = \frac{e^x - e^{-x}}{2} @@ -6001,7 +5960,7 @@ def sinh( -------- With :class:`ivy.Array` input: - >>> x = ivy.array([1, 2, 3]) + >>> x = ivy.array([1., 2., 3.]) >>> y = ivy.sinh(x) >>> print(y) ivy.array([1.18, 3.63, 10.]) @@ -6038,11 +5997,10 @@ def sqrt( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - r""" - Calculate the square root, having domain ``[0, +infinity]`` and codomain ``[0, - +infinity]``, for each element ``x_i`` of the input array ``x``. After rounding, - each result must be indistinguishable from the infinitely precise result (as - required by IEEE 754). + r"""Calculate the square root, having domain ``[0, +infinity]`` and codomain + ``[0, +infinity]``, for each element ``x_i`` of the input array ``x``. + After rounding, each result must be indistinguishable from the infinitely + precise result (as required by IEEE 754). .. note:: After rounding, each result must be indistinguishable @@ -6152,7 +6110,7 @@ def sqrt( b: ivy.array([[7., 1.], [0., 4.47]]) } - """ + """ # noqa: E501 return ivy.current_backend(x).sqrt(x, out=out) @@ -6170,8 +6128,7 @@ def square( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Each element ``x_i`` of the input array ``x``. + """Each element ``x_i`` of the input array ``x``. Parameters ---------- @@ -6245,9 +6202,8 @@ def subtract( alpha: Optional[Union[int, float]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Calculate the difference for each element ``x1_i`` of the input array ``x1`` with - the respective element ``x2_i`` of the input array ``x2``. + """Calculate the difference for each element ``x1_i`` of the input array + ``x1`` with the respective element ``x2_i`` of the input array ``x2``. Parameters ---------- @@ -6415,10 +6371,9 @@ def tanh( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Calculate an implementation-dependent approximation to the hyperbolic tangent, - having domain ``[-infinity, +infinity]`` and codomain ``[-1, +1]``, for each element - ``x_i`` of the input array ``x``. + """Calculate an implementation-dependent approximation to the hyperbolic + tangent, having domain ``[-infinity, +infinity]`` and codomain ``[-1, + +1]``, for each element ``x_i`` of the input array ``x``. **Special cases** @@ -6558,8 +6513,7 @@ def trapz( axis: int = -1, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Integrate along the given axis using the composite trapezoidal rule. + """Integrate along the given axis using the composite trapezoidal rule. If x is provided, the integration happens in sequence along its elements - they are not sorted.. @@ -6616,9 +6570,8 @@ def trunc( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Round each element x_i of the input array x to the integer-valued number that is - closest to but no greater than x_i. + """Round each element x_i of the input array x to the integer-valued number + that is closest to but no greater than x_i. **Special cases** @@ -6709,8 +6662,7 @@ def erf( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the Gauss error function of ``x`` element-wise. + """Compute the Gauss error function of ``x`` element-wise. Parameters ---------- @@ -6773,8 +6725,7 @@ def maximum( use_where: bool = True, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return the max of x1 and x2 (i.e. x1 > x2 ? x1 : x2) element-wise. + """Return the max of x1 and x2 (i.e. x1 > x2 ? x1 : x2) element-wise. Parameters ---------- @@ -6807,12 +6758,12 @@ def maximum( >>> x = ivy.array([1, 5, 9, 8, 3, 7]) >>> y = ivy.array([[9], [3], [2]]) - >>> z = ivy.zeros((3, 6)) + >>> z = ivy.zeros((3, 6), dtype=ivy.int32) >>> ivy.maximum(x, y, out=z) >>> print(z) - ivy.array([[9., 9., 9., 9., 9., 9.], - [3., 5., 9., 8., 3., 7.], - [2., 5., 9., 8., 3., 7.]]) + ivy.array([[9, 9, 9, 9, 9, 9], + [3, 5, 9, 8, 3, 7], + [2, 5, 9, 8, 3, 7]]) >>> x = ivy.array([[7, 3]]) >>> y = ivy.array([0, 7]) @@ -6865,8 +6816,7 @@ def minimum( use_where: bool = True, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return the min of x1 and x2 (i.e. x1 < x2 ? x1 : x2) element-wise. + """Return the min of x1 and x2 (i.e. x1 < x2 ? x1 : x2) element-wise. Parameters ---------- @@ -6898,12 +6848,12 @@ def minimum( >>> x = ivy.array([1, 5, 9, 8, 3, 7]) >>> y = ivy.array([[9], [3], [2]]) - >>> z = ivy.zeros((3, 6)) + >>> z = ivy.zeros((3, 6), dtype=ivy.int32) >>> ivy.minimum(x, y, out=z) >>> print(z) - ivy.array([[1.,5.,9.,8.,3.,7.], - [1.,3.,3.,3.,3.,3.], - [1.,2.,2.,2.,2.,2.]]) + ivy.array([[1, 5, 9, 8, 3, 7], + [1, 3, 3, 3, 3, 3], + [1, 2, 2, 2, 2, 2]]) >>> x = ivy.array([[7, 3]]) >>> y = ivy.array([0, 7]) @@ -6956,8 +6906,7 @@ def reciprocal( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return a new array with the reciprocal of each element in ``x``. + """Return a new array with the reciprocal of each element in ``x``. Parameters ---------- @@ -6995,8 +6944,7 @@ def deg2rad( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Convert the input from degrees to radians. + """Convert the input from degrees to radians. Parameters ---------- @@ -7015,7 +6963,7 @@ def deg2rad( -------- With :class:`ivy.Array` input: - >>> x=ivy.array([0,90,180,270,360]) + >>> x=ivy.array([0,90,180,270,360], dtype=ivy.float32) >>> y=ivy.deg2rad(x) >>> print(y) ivy.array([0., 1.57079633, 3.14159265, 4.71238898, 6.28318531]) @@ -7041,7 +6989,7 @@ def deg2rad( With :class:`ivy.Container` input: >>> x=ivy.Container(a=ivy.array([-0,20.1,-50.5,-ivy.nan]), - ... b=ivy.array([0,90,180,270,360])) + ... b=ivy.array([0,90.,180,270,360], dtype=ivy.float32)) >>> y=ivy.deg2rad(x) >>> print(y) { @@ -7049,7 +6997,7 @@ def deg2rad( b: ivy.array([0., 1.57079633, 3.14159265, 4.71238898, 6.28318531]) } - >>> x=ivy.Container(a=ivy.array([0,90,180,270,360]), + >>> x=ivy.Container(a=ivy.array([0,90,180,270,360], dtype=ivy.float32), ... b=ivy.native_array([0,-1.5,-50,ivy.nan])) >>> y=ivy.deg2rad(x) >>> print(y) @@ -7074,8 +7022,7 @@ def rad2deg( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Convert the input from radians to degrees. + """Convert the input from radians to degrees. Parameters ---------- @@ -7152,9 +7099,8 @@ def trunc_divide( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Perform element-wise integer division of the inputs rounding the results towards - zero. + """Perform element-wise integer division of the inputs rounding the results + towards zero. Parameters ---------- @@ -7213,11 +7159,10 @@ def isreal( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Test each element ``x_i`` of the input array ``x`` to determine whether the element - is real number. Returns a bool array, where True if input element is real. If - element has complex type with zero complex part, the return value for that element - is True. + """Test each element ``x_i`` of the input array ``x`` to determine whether + the element is real number. Returns a bool array, where True if input + element is real. If element has complex type with zero complex part, the + return value for that element is True. Parameters ---------- @@ -7279,8 +7224,7 @@ def fmod( *, out: Optional[Union[ivy.Array, ivy.NativeArray]] = None, ) -> Union[ivy.Array, ivy.NativeArray]: - """ - Compute the element-wise remainder of divisions of two arrays. + """Compute the element-wise remainder of divisions of two arrays. Parameters ---------- @@ -7323,8 +7267,7 @@ def lcm( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the element-wise least common multiple (LCM) of x1 and x2. + """Compute the element-wise least common multiple (LCM) of x1 and x2. Parameters ---------- diff --git a/ivy/functional/ivy/experimental/activations.py b/ivy/functional/ivy/experimental/activations.py index c78f44198b9d6..736fcf1c6e647 100644 --- a/ivy/functional/ivy/experimental/activations.py +++ b/ivy/functional/ivy/experimental/activations.py @@ -53,8 +53,7 @@ def logit( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the logit of x. + """Compute the logit of x. logit(x) = log(x / (1 - x)). @@ -107,8 +106,7 @@ def prelu( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Prelu takes input data (Array) and slope array as input, + """Prelu takes input data (Array) and slope array as input, and produces one output data (array) where the function f(x) = slope * x for x < 0, f(x) = x for x >= 0., is applied @@ -165,8 +163,7 @@ def thresholded_relu( threshold: Union[int, float] = 0, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Apply the rectified linear unit function with custom threshold. + """Apply the rectified linear unit function with custom threshold. Parameters ---------- @@ -250,8 +247,7 @@ def relu6( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Apply the rectified linear unit 6 function element-wise. + """Apply the rectified linear unit 6 function element-wise. Parameters ---------- @@ -306,8 +302,7 @@ def logsigmoid( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Apply element-wise Log-sigmoid of x. + """Apply element-wise Log-sigmoid of x. logsigmoid(x) = log(1 / (1 + exp(-x)). @@ -361,8 +356,7 @@ def logsigmoid( def selu( x: Union[ivy.Array, ivy.NativeArray], /, *, out: Optional[ivy.Array] = None ) -> ivy.Array: - """ - Apply the scaled exponential linear unit function element-wise. + """Apply the scaled exponential linear unit function element-wise. Parameters ---------- @@ -420,8 +414,7 @@ def selu( def silu( x: Union[ivy.Array, ivy.NativeArray], /, *, out: Optional[ivy.Array] = None ) -> ivy.Array: - """ - Apply the silu function element-wise. + """Apply the silu function element-wise. Parameters ---------- @@ -473,8 +466,7 @@ def elu( alpha: float = 1.0, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Apply the elu unit function element-wise. + """Apply the elu unit function element-wise. Parameters ---------- @@ -536,8 +528,7 @@ def hardtanh( min_val: float = -1, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Apply the hardtanh unit function element-wise. + """Apply the hardtanh unit function element-wise. Parameters ---------- @@ -568,15 +559,14 @@ def hardtanh( >>> ivy.hardtanh(x, out=y) >>> print(y) ivy.array([ 1., 0.7, -1.]) - >>> x = ivy.array([[1.1, 2.2, 3.3], - ... [-0.4, 0.5, -6.6]]) + >>> x = ivy.array([[1.1, 2.2, 3.3],[-0.4, 0.5, -6.6]]) >>> ivy.hardtanh(x, out=x) >>> print(x) - ivy.array([[ 1., 1., 1.], - [-0.4, 0.5, -1.]]) + ivy.array([[ 1., 1., 1.],[-0.4, 0.5, -1.]]) + With :class:`ivy.Container` input: >>> x = ivy.Container(a=ivy.array([0.0, -1.2]), b=ivy.array([0.4, -0.2])) - >>> x = ivy.hardtanhx, out=x) + >>> x = ivy.hardtanh(x, out=x) >>> print(x) { a: ivy.array([0., -1.]), @@ -596,8 +586,7 @@ def hardtanh( def tanhshrink( x: Union[ivy.Array, ivy.NativeArray], /, *, out: Optional[ivy.Array] = None ) -> ivy.Array: - """ - Apply the tanhshrink function element-wise. + """Apply the tanhshrink function element-wise. Parameters ---------- @@ -650,8 +639,7 @@ def softshrink( lambd: float = 0.5, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Apply the softshrink function element-wise. + """Apply the softshrink function element-wise. Parameters ---------- @@ -723,6 +711,63 @@ def _celu_jax_like( return complex_max + alpha * ivy.expm1(complex_min / alpha) +@handle_exceptions +@handle_backend_invalid +@handle_nestable +@handle_array_like_without_promotion +@handle_out_argument +@to_native_arrays_and_back +@handle_device +def threshold( + x: Union[ivy.Array, ivy.NativeArray], + /, + *, + threshold: float, + value: float, + out: Optional[ivy.Array] = None, +) -> ivy.Array: + """Apply the threshold function element-wise. + + Parameters + ---------- + x + input array. + threshold + The value to threshold at. + value + The value to replace with. + out + optional output array, for writing the result to. It must have a shape that the + inputs broadcast to. + + Returns + ------- + ret + an array containing the threshold activation of each element in ``x``. + + Examples + -------- + With :class:`ivy.Array` input: + >>> x = ivy.array([-1.0, 1.0, 2.0]) + >>> y = ivy.threshold(x,value=0.0, threshold=1.5) + >>> print(y) + ivy.array([0., 0., 2.]) + + >>> x = ivy.array([-1.0, 1.0, 2.0]) + >>> x.threshold(value=0.0, threshold=1.5) + >>> print(y) + ivy.array([0., 0., 2.]) + + + >>> x = ivy.array([[-1.3, 3.8, 2.1], [1.7, 4.2, -6.6]]) + >>> y = ivy.threshold(x, value=0.0, threshold=1.5) + >>> print(y) + ivy.array([[0. , 3.79999995, 2.0999999 ], + [1.70000005, 4.19999981, 0. ]]) + """ + return current_backend(x).threshold(x, threshold=threshold, value=value, out=out) + + @handle_exceptions @handle_backend_invalid @handle_nestable @@ -740,9 +785,8 @@ def celu( complex_mode: Literal["split", "magnitude", "jax"] = "jax", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Apply the Continously Differentiable Exponential Linear Unit (CELU) activation - function to each element of the input. + """Apply the Continuously Differentiable Exponential Linear Unit (CELU) + activation function to each element of the input. Parameters ---------- @@ -803,8 +847,7 @@ def scaled_tanh( beta: float = 0.67, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the scaled hyperbolic tangent (tanh) activation. + """Compute the scaled hyperbolic tangent (tanh) activation. The scaled tanh activation function is defined as: out = alpha * tanh(beta * x) @@ -882,8 +925,7 @@ def hardshrink( lambd: float = 0.5, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Apply the hardshrink function element-wise. + """Apply the hardshrink function element-wise. Parameters ---------- @@ -910,7 +952,7 @@ def hardshrink( >>> x = ivy.array([-1.0, 1.0, 2.0]) >>> y = x.hardshrink() >>> print(y) - ivy.array([-0.5, 0.5, 1.5]) + ivy.array([-1., 1., 2.]) >>> x = ivy.array([[-1.3, 3.8, 2.1], [1.7, 4.2, -6.6]]) >>> y = ivy.hardshrink(x) >>> print(y) @@ -918,3 +960,55 @@ def hardshrink( [ 1.70000005, 4.19999981, -6.5999999 ]]) """ return current_backend(x).hardshrink(x, lambd=lambd, out=out) + + +@handle_exceptions +@handle_backend_invalid +@handle_nestable +@handle_array_like_without_promotion +@handle_out_argument +@to_native_arrays_and_back +@handle_device +def hardsilu( + x: Union[ivy.Array, ivy.NativeArray], /, *, out: Optional[ivy.Array] = None +) -> ivy.Array: + """Apply the hardsilu/hardswish function element-wise. + + Parameters + ---------- + x + input array + out + optional output array, for writing the result to. It must have a shape that the + inputs broadcast to. + + Returns + ------- + an array containing the output of the hardsilu/hardswish function applied + to each element in ``x``. + + Examples + -------- + With :class:`ivy.Array` input: + + >>> x = ivy.array([1., 2., 3.]) + >>> y = ivy.hardsilu(x) + >>> print(y) + ivy.array([0.66666669, 1.66666663, 3. ]) + >>> x = ivy.array([-2.1241, 1.4897, 4.4090]) + >>> y = ivy.zeros(3) + >>> ivy.hardsilu(x, out=y) + >>> print(y) + ivy.array([-0.31008321, 1.1147176 , 4.40899992]) + + With :class:`ivy.Container` input: + + >>> x = ivy.Container(a=ivy.array([-0.5, -1, 0]), b=ivy.array([0.5, 1., 2])) + >>> y = ivy.hardsilu(x) + >>> print(y) + { + a: ivy.array([-0.20833333, -0.33333334, 0.]), + b: ivy.array([0.29166666, 0.66666669, 1.66666663]) + } + """ + return current_backend(x).hardsilu(x, out=out) diff --git a/ivy/functional/ivy/experimental/creation.py b/ivy/functional/ivy/experimental/creation.py index 710a5b4b5e74d..f1871a3098b28 100644 --- a/ivy/functional/ivy/experimental/creation.py +++ b/ivy/functional/ivy/experimental/creation.py @@ -33,9 +33,8 @@ def vorbis_window( dtype: Optional[Union[ivy.Dtype, ivy.NativeDtype]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return an array that contains a vorbis power complementary window of size - window_length. + """Return an array that contains a vorbis power complementary window of + size window_length. Parameters ---------- @@ -76,9 +75,8 @@ def hann_window( dtype: Optional[Union[ivy.Dtype, ivy.NativeDtype]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Generate a Hann window. The Hanning window is a taper formed by using a weighted - cosine. + """Generate a Hann window. The Hanning window is a taper formed by using a + weighted cosine. Parameters ---------- @@ -125,8 +123,8 @@ def kaiser_window( dtype: Optional[Union[ivy.Dtype, ivy.NativeDtype]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the Kaiser window with window length window_length and shape beta. + """Compute the Kaiser window with window length window_length and shape + beta. Parameters ---------- @@ -172,9 +170,8 @@ def kaiser_bessel_derived_window( dtype: Optional[Union[ivy.Dtype, ivy.NativeDtype]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the Kaiser bessel derived window with window length window_length and shape - beta. + """Compute the Kaiser bessel derived window with window length + window_length and shape beta. Parameters ---------- @@ -226,8 +223,7 @@ def hamming_window( dtype: Optional[Union[ivy.Dtype, ivy.NativeDtype]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the Hamming window with window length window_length. + """Compute the Hamming window with window length window_length. Parameters ---------- @@ -292,16 +288,16 @@ def tril_indices( *, device: Optional[Union[ivy.Device, ivy.NativeDevice]] = None, ) -> Tuple[ivy.Array, ...]: - """ - Return the indices of the lower triangular part of a row by col matrix in a 2-by-N - shape (tuple of two N dimensional arrays), where the first row contains row - coordinates of all indices and the second row contains column coordinates. Indices - are ordered based on rows and then columns. The lower triangular part of the matrix - is defined as the elements on and below the diagonal. The argument k controls which - diagonal to consider. If k = 0, all elements on and below the main diagonal are - retained. A positive value excludes just as many diagonals below the main diagonal, - and similarly a negative value includes just as many diagonals above the main - diagonal. The main diagonal are the set of indices {(i,i)} for iโˆˆ[0,min{n_rows, + """Return the indices of the lower triangular part of a row by col matrix + in a 2-by-N shape (tuple of two N dimensional arrays), where the first row + contains row coordinates of all indices and the second row contains column + coordinates. Indices are ordered based on rows and then columns. The lower + triangular part of the matrix is defined as the elements on and below the + diagonal. The argument k controls which diagonal to consider. If k = 0, + all elements on and below the main diagonal are retained. A positive value + excludes just as many diagonals below the main diagonal, and similarly a + negative value includes just as many diagonals above the main diagonal. The + main diagonal are the set of indices {(i,i)} for iโˆˆ[0,min{n_rows, n_cols}โˆ’1]. Notes @@ -390,10 +386,9 @@ def eye_like( device: Optional[Union[ivy.Device, ivy.NativeDevice]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return a 2D array filled with ones on the k diagonal and zeros elsewhere. having the - same ``shape`` as the first and last dim of input array ``x``. input array ``x`` - should to be 2D. + """Return a 2D array filled with ones on the k diagonal and zeros + elsewhere. having the same ``shape`` as the first and last dim of input + array ``x``. input array ``x`` should to be 2D. Parameters ---------- @@ -483,8 +478,7 @@ def _iter_product(*args, repeat=1): def ndenumerate( input: Iterable, ) -> Generator: - """ - Multidimensional index iterator. + """Multidimensional index iterator. Parameters ---------- @@ -523,8 +517,7 @@ def _ndenumerate(input): def ndindex( shape: Tuple, ) -> Generator: - """ - Multidimensional index iterator. + """Multidimensional index iterator. Parameters ---------- @@ -557,8 +550,7 @@ def indices( dtype: Union[ivy.Dtype, ivy.NativeDtype] = ivy.int64, sparse: bool = False, ) -> Union[ivy.Array, Tuple[ivy.Array, ...]]: - """ - Return an array representing the indices of a grid. + """Return an array representing the indices of a grid. Parameters ---------- @@ -618,9 +610,8 @@ def unsorted_segment_min( segment_ids: Union[ivy.Array, ivy.NativeArray], num_segments: Union[int, ivy.Array, ivy.NativeArray], ) -> ivy.Array: - """ - Compute the minimum along segments of an array. Segments are defined by an integer - array of segment IDs. + """Compute the minimum along segments of an array. Segments are defined by + an integer array of segment IDs. Note ---- @@ -658,9 +649,8 @@ def unsorted_segment_sum( segment_ids: Union[ivy.Array, ivy.NativeArray], num_segments: Union[int, ivy.Array, ivy.NativeArray], ) -> ivy.Array: - """ - Compute the sum of elements along segments of an array. Segments are defined by an - integer array of segment IDs. + """Compute the sum of elements along segments of an array. Segments are + defined by an integer array of segment IDs. Parameters ---------- @@ -698,10 +688,10 @@ def blackman_window( dtype: Optional[Union[ivy.Dtype, ivy.NativeDtype]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Generate a Blackman window. The Blackman window is a taper formed by using the first - three terms of a summation of cosines. It was designed to have close to the minimal - leakage possible. It is close to optimal, only slightly worse than a Kaiser window. + """Generate a Blackman window. The Blackman window is a taper formed by + using the first three terms of a summation of cosines. It was designed to + have close to the minimal leakage possible. It is close to optimal, only + slightly worse than a Kaiser window. Parameters ---------- @@ -747,8 +737,7 @@ def random_tucker( seed: Optional[int] = None, non_negative: Optional[bool] = False, ) -> Union[ivy.TuckerTensor, ivy.Array]: - """ - Generate a random Tucker tensor. + """Generate a random Tucker tensor. Parameters ---------- @@ -817,8 +806,7 @@ def random_cp( seed: Optional[int] = None, normalise_factors: Optional[bool] = True, ) -> Union[ivy.CPTensor, ivy.Array]: - """ - Generate a random CP tensor. + """Generate a random CP tensor. Parameters ---------- @@ -872,8 +860,7 @@ def random_tr( full: Optional[bool] = False, seed: Optional[int] = None, ) -> Union[ivy.TRTensor, ivy.Array]: - """ - Generate a random TR tensor. + """Generate a random TR tensor. Parameters ---------- @@ -931,8 +918,7 @@ def random_parafac2( seed: Optional[int] = None, normalise_factors: Optional[bool] = True, ) -> Union[ivy.Parafac2Tensor, ivy.Array]: - """ - Generate a random PARAFAC2 tensor. + """Generate a random PARAFAC2 tensor. Parameters ---------- @@ -945,6 +931,7 @@ def random_parafac2( the decomposed tensor is returned seed seed for generating random numbers + Returns ------- ivy.Parafac2Tensor @@ -987,8 +974,7 @@ def random_tt( dtype: Optional[Union[ivy.Dtype, ivy.NativeDtype]] = None, seed: Optional[int] = None, ) -> Union[ivy.TTTensor, ivy.Array]: - """ - Generate a random TT/MPS tensor. + """Generate a random TT/MPS tensor. Parameters ---------- @@ -1097,10 +1083,10 @@ def mel_weight_matrix( lower_edge_hertz: float = 0.0, upper_edge_hertz: float = 3000.0, ): - """ - Generate a MelWeightMatrix that can be used to re-weight a Tensor containing a - linearly sampled frequency spectra (from DFT or STFT) into num_mel_bins frequency - information based on the [lower_edge_hertz, upper_edge_hertz] + """Generate a MelWeightMatrix that can be used to re-weight a Tensor + containing a linearly sampled frequency spectra (from DFT or STFT) into + num_mel_bins frequency information based on the [lower_edge_hertz, + upper_edge_hertz] range on the mel scale. This function defines the mel scale in terms of a frequency in hertz according to the following formula: mel(f) = 2595 * log10(1 + f/700) @@ -1139,6 +1125,41 @@ def mel_weight_matrix( ) +# unsorted_segment_mean +@handle_exceptions +@handle_nestable +@to_native_arrays_and_back +def unsorted_segment_mean( + data: Union[ivy.Array, ivy.NativeArray], + segment_ids: Union[ivy.Array, ivy.NativeArray], + num_segments: Union[int, ivy.Array, ivy.NativeArray], +) -> ivy.Array: + """Compute the mean of elements along segments of an array. Segments are + defined by an integer array of segment IDs. + + Parameters + ---------- + data : Union[ivy.Array, ivy.NativeArray] + The array from which to gather values. + + segment_ids : Union[ivy.Array, ivy.NativeArray] + Must be in the same size with the first dimension of `data`. Has to be + of integer data type. The index-th element of `segment_ids` array is + the segment identifier for the index-th element of `data`. + + num_segments : Union[int, ivy.Array, ivy.NativeArray] + An integer or array representing the total number of distinct segment IDs. + + Returns + ------- + ivy.Array + The output array, representing the result of a segmented mean operation. + For each segment, it computes the mean value in `data` where `segment_ids` + equals to segment ID. + """ + return ivy.current_backend().unsorted_segment_mean(data, segment_ids, num_segments) + + @handle_exceptions @handle_nestable @handle_array_function @@ -1147,8 +1168,7 @@ def polyval( coeffs: Union[ivy.Array, ivy.NativeArray], x: Union[ivy.Array, ivy.NativeArray], ): - """ - Evaluate and return a polynomial at specific given values. + """Evaluate and return a polynomial at specific given values. Parameters ---------- @@ -1160,7 +1180,7 @@ def polyval( Returns ------- ret - Simplified result of substituing x in the coefficients - final value + Simplified result of substituting x in the coefficients - final value of polynomial. Examples diff --git a/ivy/functional/ivy/experimental/elementwise.py b/ivy/functional/ivy/experimental/elementwise.py index 09a208c346a5b..c2680ceb4fe06 100644 --- a/ivy/functional/ivy/experimental/elementwise.py +++ b/ivy/functional/ivy/experimental/elementwise.py @@ -32,8 +32,7 @@ def amax( keepdims: bool = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Calculate the maximum value of the input array ``x``. + """Calculate the maximum value of the input array ``x``. .. note:: ``amax`` is an alias of ``max`` and both function @@ -149,8 +148,7 @@ def amin( keepdims: bool = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Calculate the minimum value of the input array ``x``. + """Calculate the minimum value of the input array ``x``. .. note:: ``amin`` is an alias of ``min`` and both function @@ -265,8 +263,8 @@ def lgamma( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the natural logarithm of the absolute value of the gamma function on x. + """Compute the natural logarithm of the absolute value of the gamma + function on x. Parameters ---------- @@ -316,11 +314,11 @@ def sinc( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Calculate an implementation-dependent approximation of the principal value of the - normalized sinc function, having domain ``(-infinity, +infinity)`` and codomain - ``[-0.217234, 1]``, for each element ``x_i`` of the input array ``x``. Each element - ``x_i`` is assumed to be expressed in radians. + """Calculate an implementation-dependent approximation of the principal + value of the normalized sinc function, having domain ``(-infinity, + +infinity)`` and codomain ``[-0.217234, 1]``, for each element ``x_i`` of + the input array ``x``. Each element ``x_i`` is assumed to be expressed in + radians. **Special cases** @@ -393,10 +391,9 @@ def fmax( *, out: Optional[Union[ivy.Array, ivy.NativeArray]] = None, ) -> Union[ivy.Array, ivy.NativeArray]: - """ - Compute the element-wise maximums of two arrays. Differs from ivy.maximum in the - case where one of the elements is NaN. ivy.maximum returns the NaN element while - ivy.fmax returns the non-NaN element. + """Compute the element-wise maximums of two arrays. Differs from + ivy.maximum in the case where one of the elements is NaN. ivy.maximum + returns the NaN element while ivy.fmax returns the non-NaN element. Parameters ---------- @@ -439,11 +436,10 @@ def float_power( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Raise each base in x1 to the positionally-corresponding power in x2. x1 and x2 must - be broadcastable to the same shape. This differs from the power function in that - integers, float16, and float32 are promoted to floats with a minimum precision of - float64 so that the result is always inexact. + """Raise each base in x1 to the positionally-corresponding power in x2. x1 + and x2 must be broadcastable to the same shape. This differs from the power + function in that integers, float16, and float32 are promoted to floats with + a minimum precision of float64 so that the result is always inexact. Parameters ---------- @@ -488,9 +484,8 @@ def copysign( *, out: Optional[Union[ivy.Array, ivy.NativeArray]] = None, ) -> ivy.Array: - """ - Change the signs of x1 to match x2 x1 and x2 must be broadcastable to a common - shape. + """Change the signs of x1 to match x2 x1 and x2 must be broadcastable to a + common shape. Parameters ---------- @@ -538,8 +533,7 @@ def count_nonzero( dtype: Optional[Union[ivy.Dtype, ivy.NativeDtype]] = None, out: Optional[Union[ivy.Array, ivy.NativeArray]] = None, ) -> ivy.Array: - """ - Count the number of non-zero values in the array a. + """Count the number of non-zero values in the array a. Parameters ---------- @@ -598,9 +592,8 @@ def nansum( keepdims: bool = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return the sum of array elements over a given axis treating Not a Numbers (NaNs) as - zero. + """Return the sum of array elements over a given axis treating Not a + Numbers (NaNs) as zero. Parameters ---------- @@ -657,8 +650,8 @@ def isclose( equal_nan: bool = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return a boolean array where two arrays are element-wise equal within a tolerance. + """Return a boolean array where two arrays are element-wise equal within a + tolerance. The tolerance values are positive, typically very small numbers. The relative difference (rtol * abs(b)) and the absolute difference @@ -718,8 +711,7 @@ def signbit( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return element-wise True where signbit is set (less than zero). + """Return element-wise True where signbit is set (less than zero). Parameters ---------- @@ -755,8 +747,7 @@ def hypot( *, out: Optional[Union[ivy.Array, ivy.NativeArray]] = None, ) -> Union[ivy.Array, ivy.NativeArray]: - """ - Return the hypotenuse given the two sides of a right angle triangle. + """Return the hypotenuse given the two sides of a right angle triangle. Parameters ---------- @@ -796,8 +787,7 @@ def diff( append: Optional[Union[ivy.Array, ivy.NativeArray, int, list, tuple]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return the n-th discrete difference along the given axis. + """Return the n-th discrete difference along the given axis. Parameters ---------- @@ -852,9 +842,8 @@ def allclose( equal_nan: bool = False, out: Optional[ivy.Array] = None, ) -> bool: - """ - Return a True if the two arrays are element-wise equal within given tolerance; - otherwise False. + """Return a True if the two arrays are element-wise equal within given + tolerance; otherwise False. The tolerance values are positive, typically very small numbers. The relative difference (rtol * abs(x2)) and the absolute difference @@ -923,9 +912,8 @@ def fix( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Round an array of floats element-wise to nearest integer towards zero. The rounded - values are returned as floats. + """Round an array of floats element-wise to nearest integer towards zero. + The rounded values are returned as floats. Parameters ---------- @@ -963,8 +951,7 @@ def nextafter( *, out: Optional[ivy.Array] = None, ) -> bool: - """ - Return the next floating-point value after x1 towards x2, element-wise. + """Return the next floating-point value after x1 towards x2, element-wise. Parameters ---------- @@ -1005,9 +992,8 @@ def zeta( *, out: Optional[ivy.Array] = None, ) -> bool: - """ - Compute the Hurwitz zeta function elementwisely with each pair of floats in two - arrays. + """Compute the Hurwitz zeta function elementwisely with each pair of floats + in two arrays. Parameters ---------- @@ -1049,8 +1035,7 @@ def gradient( edge_order: int = 1, axis: Optional[Union[int, list, tuple]] = None, ) -> Union[ivy.Array, List[ivy.Array]]: - """ - Calculate gradient of x with respect to (w.r.t.) spacing. + """Calculate gradient of x with respect to (w.r.t.) spacing. Parameters ---------- @@ -1128,8 +1113,7 @@ def xlogy( *, out: Optional[ivy.Array] = None, ) -> bool: - """ - Compute x*log(y) element-wise so that the result is 0 if x = 0. + """Compute x*log(y) element-wise so that the result is 0 if x = 0. Parameters ---------- @@ -1173,9 +1157,8 @@ def binarizer( threshold: float = 0, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Map the values of the input tensor to either 0 or 1, element-wise, based on the - outcome of a comparison against a threshold value. + """Map the values of the input tensor to either 0 or 1, element-wise, based + on the outcome of a comparison against a threshold value. Parameters ---------- @@ -1215,8 +1198,8 @@ def conj( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return the complex conjugate for each element ``x_i`` of the input array ``x``. + """Return the complex conjugate for each element ``x_i`` of the input array + ``x``. For complex number of the form @@ -1299,8 +1282,7 @@ def ldexp( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return x1 * (2**x2), element-wise. + """Return x1 * (2**x2), element-wise. Parameters ---------- @@ -1342,8 +1324,8 @@ def lerp( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return a linear interpolation of two arrays start (given by input) and end. + """Return a linear interpolation of two arrays start (given by input) and + end. based on a scalar or array weight. input + weight * (end - input), element-wise. @@ -1469,8 +1451,7 @@ def frexp( *, out: Optional[Tuple[ivy.Array, ivy.Array]] = None, ) -> Tuple[ivy.Array, ivy.Array]: - """ - Decompose the elements of x into mantissa and twos exponent. + """Decompose the elements of x into mantissa and twos exponent. Parameters ---------- @@ -1506,8 +1487,7 @@ def modf( *, out: Optional[Tuple[ivy.Array, ivy.Array]] = None, ) -> Tuple[ivy.Array, ivy.Array]: - """ - Decompose the elements of x into fractional and integral parts. + """Decompose the elements of x into fractional and integral parts. Parameters ---------- @@ -1541,8 +1521,7 @@ def digamma( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the logarithmic derivative of the gamma function at x. + """Compute the logarithmic derivative of the gamma function at x. Note ---- @@ -1582,9 +1561,8 @@ def sparsify_tensor( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Zeros out all elements in the tensor except `card` elements with maximum absolute - values. + """Zeros out all elements in the tensor except `card` elements with maximum + absolute values. Parameters ---------- @@ -1659,3 +1637,39 @@ def erfc( ivy.array([0.00467773, 1.84270084, 1. ]) """ return ivy.current_backend(x).erfc(x, out=out) + + +@handle_exceptions +@handle_nestable +@handle_array_like_without_promotion +@handle_out_argument +@to_native_arrays_and_back +@handle_device +def erfinv( + x: Union[ivy.Array, ivy.NativeArray], + /, + *, + out: Optional[ivy.Array] = None, +): + """Compute the inverse error function. + + Parameters + ---------- + x + Input array of real or complex valued argument. + out + optional output array, for writing the result to. + It must have a shape that the inputs broadcast to. + + Returns + ------- + ret + Values of the inverse error function. + + Examples + -------- + >>> x = ivy.array([0, 0.5, -1.]) + >>> ivy.erfinv(x) + ivy.array([0.0000, 0.4769, -inf]) + """ + return ivy.current_backend(x).erfinv(x, out=out) diff --git a/ivy/functional/ivy/experimental/general.py b/ivy/functional/ivy/experimental/general.py index cef0bc2091951..144f10256c7be 100644 --- a/ivy/functional/ivy/experimental/general.py +++ b/ivy/functional/ivy/experimental/general.py @@ -39,8 +39,8 @@ def reduce( axes: Union[int, Sequence[int]] = 0, keepdims: bool = False, ) -> ivy.Array: - """ - Reduces the input array's dimensions by applying a function along one or more axes. + """Reduces the input array's dimensions by applying a function along one or + more axes. Parameters ---------- diff --git a/ivy/functional/ivy/experimental/gradients.py b/ivy/functional/ivy/experimental/gradients.py index 8c5466de75168..126a219d890f5 100644 --- a/ivy/functional/ivy/experimental/gradients.py +++ b/ivy/functional/ivy/experimental/gradients.py @@ -3,8 +3,7 @@ def bind_custom_gradient_function(func, custom_grad_func): - """ - Bind a custom gradient function to a function. + """Bind a custom gradient function to a function. Parameters ---------- @@ -23,8 +22,7 @@ def bind_custom_gradient_function(func, custom_grad_func): def vjp(func, *primals): - """ - Compute a (reverse-mode) vector-Jacobian product of `func`. + """Compute a (reverse-mode) vector-Jacobian product of `func`. Parameters ---------- @@ -43,8 +41,7 @@ def vjp(func, *primals): def jvp(func, primals, tangents): - """ - Compute a (forward-mode) Jacobian-vector product of `func`. + """Compute a (forward-mode) Jacobian-vector product of `func`. Parameters ---------- diff --git a/ivy/functional/ivy/experimental/layers.py b/ivy/functional/ivy/experimental/layers.py index 2b8a3e9102014..0942677e34361 100644 --- a/ivy/functional/ivy/experimental/layers.py +++ b/ivy/functional/ivy/experimental/layers.py @@ -43,8 +43,7 @@ def max_pool1d( ceil_mode: bool = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute a 1-D max pool given 3-D input x. + """Compute a 1-D max pool given 3-D input x. Parameters ---------- @@ -93,15 +92,15 @@ def max_pool1d( [[16., 17., 18., 19.]]]) >>> x = ivy.arange(0, 24.).reshape((2, 3, 4)) - >>> print(ivy.max_pool1d(x, 2, 2, [(1,0)], data_format="NCW", dilation=2, ceil_mode=True)) # noqa - ivy.array([[[ 1., 3.], - [ 5., 7.], - [ 9., 11.]], - - [[13., 15.], - [17., 19.], - [21., 23.]]]) - """ + >>> print(ivy.max_pool1d(x, 2, 2, [(1,0)], data_format="NCW", dilation=1, ceil_mode=True)) + ivy.array([[[ 0., 2., 3.], + [ 4., 6., 7.], + [ 8., 10., 11.]], + + [[12., 14., 15.], + [16., 18., 19.], + [20., 22., 23.]]]) + """ # noqa: E501 return ivy.current_backend(x).max_pool1d( x, kernel, @@ -131,8 +130,7 @@ def max_pool2d( ceil_mode: bool = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute a 2-D max pool given 4-D input x. + """Compute a 2-D max pool given 4-D input x. Parameters ---------- @@ -219,8 +217,7 @@ def max_pool3d( ceil_mode: bool = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute a 3-D max pool given 5-D input x. + """Compute a 3-D max pool given 5-D input x. Parameters ---------- @@ -297,17 +294,16 @@ def avg_pool1d( x: Union[ivy.Array, ivy.NativeArray], kernel: Union[int, Tuple[int]], strides: Union[int, Tuple[int]], - padding: str, + padding: Union[str, int, List[Tuple[int, int]]], /, *, data_format: str = "NWC", count_include_pad: bool = False, ceil_mode: bool = False, - division_override: Optional[int] = None, + divisor_override: Optional[int] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute a 1-D avg pool given 3-D input x. + """Compute a 1-D avg pool given 3-D input x. Parameters ---------- @@ -327,7 +323,7 @@ def avg_pool1d( Whether to include padding in the averaging calculation. ceil_mode Whether to use ceil or floor for creating the output shape. - division_override + divisor_override If specified, it will be used as the divisor, otherwise kernel_size will be used. out @@ -366,7 +362,7 @@ def avg_pool1d( data_format=data_format, count_include_pad=count_include_pad, ceil_mode=ceil_mode, - division_override=division_override, + divisor_override=divisor_override, out=out, ) @@ -380,7 +376,7 @@ def avg_pool2d( x: Union[ivy.Array, ivy.NativeArray], kernel: Union[int, Tuple[int], Tuple[int, int]], strides: Union[int, Tuple[int], Tuple[int, int]], - padding: str, + padding: Union[str, int, List[Tuple[int, int]]], /, *, data_format: str = "NHWC", @@ -389,8 +385,7 @@ def avg_pool2d( divisor_override: Optional[int] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute a 2-D average pool given 4-D input x. + """Compute a 2-D average pool given 4-D input x. Parameters ---------- @@ -403,7 +398,7 @@ def avg_pool2d( The stride of the sliding window for each dimension of input. padding SAME" or "VALID" indicating the algorithm, or list - indicating the per-dimensio paddings. + indicating the per-dimension paddings. data_format NHWC" or "NCHW". Defaults to "NHWC". count_include_pad @@ -468,7 +463,7 @@ def avg_pool3d( x: Union[ivy.Array, ivy.NativeArray], kernel: Union[int, Tuple[int], Tuple[int, int, int]], strides: Union[int, Tuple[int], Tuple[int, int, int]], - padding: str, + padding: Union[str, int, List[Tuple[int, int]]], /, *, data_format: str = "NDHWC", @@ -477,8 +472,7 @@ def avg_pool3d( divisor_override: Optional[int] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute a 3-D avg pool given 5-D input x. + """Compute a 3-D avg pool given 5-D input x. Parameters ---------- @@ -565,8 +559,7 @@ def pool( ceil_mode: bool = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Perform an N-D pooling operation. + """Perform an N-D pooling operation. Parameters ---------- @@ -598,7 +591,7 @@ def pool( Examples -------- >>> x = ivy.arange(12.).reshape((2, 1, 3, 2)) - >>> print(ivy.pool(x, (2, 2), 'MAX', (1, 1), 'SAME')) + >>> print(ivy.pool(x, (2, 2), 'MAX', strides=(1, 1), padding='SAME')) ivy.array([[[[ 1., 2.], [ 3., 4.], [ 4., 5.]]], @@ -606,7 +599,7 @@ def pool( [ 9., 10.], [10., 11.]]]]) >>> x = ivy.arange(48.).reshape((2, 4, 3, 2)) - >>> print(ivy.pool(x, 3, 'AVG', 1, 'VALID')) + >>> print(ivy.pool(x, 3, 'AVG', strides=1, padding='VALID')) ivy.array([[[[ 8., 9.]], [[14., 15.]]], [[[32., 33.]], @@ -641,8 +634,7 @@ def dct( norm: Optional[Literal["ortho"]] = None, out: Optional[Union[ivy.Array, ivy.NativeArray]] = None, ) -> Union[ivy.Array, ivy.NativeArray]: - """ - Compute the 1D Discrete Cosine Transformation of a given signal. + """Compute the 1D Discrete Cosine Transformation of a given signal. Parameters ---------- @@ -752,8 +744,7 @@ def idct( norm: Optional[Literal["ortho"]] = None, out: Optional[Union[ivy.Array, ivy.NativeArray]] = None, ) -> Union[ivy.Array, ivy.NativeArray]: - """ - Compute the 1D Inverse Discrete Cosine Transformation of a given signal. + """Compute the 1D Inverse Discrete Cosine Transformation of a given signal. Parameters ---------- @@ -876,9 +867,8 @@ def fft( n: Optional[Union[int, Tuple[int]]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - r""" - Compute the one dimensional discrete Fourier transform given input at least 1-D - input x. + r"""Compute the one dimensional discrete Fourier transform given input at + least 1-D input x. Parameters ---------- @@ -946,11 +936,10 @@ def dropout1d( data_format: str = "NWC", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Randomly zero out entire channels with probability prob using samples from a - Bernoulli distribution and the remaining channels are scaled by (1/1-prob). In this - case, dropout1d performs a channel-wise dropout but assumes a channel is a 1D - feature map. + """Randomly zero out entire channels with probability prob using samples + from a Bernoulli distribution and the remaining channels are scaled by + (1/1-prob). In this case, dropout1d performs a channel-wise dropout but + assumes a channel is a 1D feature map. Parameters ---------- @@ -1022,11 +1011,10 @@ def dropout2d( data_format: str = "NHWC", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Randomly zero out entire channels with probability prob using samples from a - Bernoulli distribution and the remaining channels are scaled by (1/1-prob). In this - case, dropout2d performs a channel-wise dropout but assumes a channel is a 2D - feature map. + """Randomly zero out entire channels with probability prob using samples + from a Bernoulli distribution and the remaining channels are scaled by + (1/1-prob). In this case, dropout2d performs a channel-wise dropout but + assumes a channel is a 2D feature map. Parameters ---------- @@ -1088,11 +1076,10 @@ def dropout3d( data_format: str = "NDHWC", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Randomly zero out entire channels with probability prob using samples from a - Bernoulli distribution and the remaining channels are scaled by (1/1-prob). In this - case, dropout3d performs a channel-wise dropout but assumes a channel is a 1D - feature map. + """Randomly zero out entire channels with probability prob using samples + from a Bernoulli distribution and the remaining channels are scaled by + (1/1-prob). In this case, dropout3d performs a channel-wise dropout but + assumes a channel is a 1D feature map. Parameters ---------- @@ -1139,9 +1126,8 @@ def ifft( n: Optional[Union[int, Tuple[int]]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - r""" - Compute the one dimensional discrete Fourier transform given input at least 1-D - input x. + r"""Compute the one dimensional discrete Fourier transform given input at + least 1-D input x. Parameters ---------- @@ -1208,8 +1194,7 @@ def embedding( max_norm: Optional[int] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Embeds a given tensor of indices using a given tensor of weights. + """Embeds a given tensor of indices using a given tensor of weights. Parameters ---------- @@ -1262,8 +1247,7 @@ def dft( norm: str = "backward", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the discrete Fourier transform of input. + """Compute the discrete Fourier transform of input. Parameters ---------- @@ -1409,9 +1393,8 @@ def _tf_area_indices(dim_index, scale): return starting_index, ending_index, rounded_indices -def _tf_area_interpolate(x, size, dims): - ret = ivy.zeros((x.shape[:2] + size)) - scale = ivy.divide(ivy.shape(x)[2:], size) +def _tf_area_interpolate(x, size, scale, dims): + ret = ivy.zeros(x.shape[:2] + size) area = 1.0 / ivy.prod(scale) for i, ba in enumerate(x): for j, ch in enumerate(ba): @@ -1487,13 +1470,16 @@ def _tf_area_interpolate(x, size, dims): return ret -def nearest_interpolate(x, dims, size, input_shape, exact): +def nearest_interpolate(x, dims, size, scale, exact): off = 0.5 if exact else 0 for d in range(dims): - m = input_shape[d + 2] n = size[d] - offsets = (ivy.arange(n, dtype="float32") + off) * m / n - offsets = ivy.astype(ivy.floor(ivy.astype(offsets, "float32")), "int32") + offsets = (ivy.arange(n, dtype="float32") + off) * scale[d] + offsets = ivy.astype(ivy.floor(ivy.astype(offsets, "float32")), "int64") + num_dims_to_add = x.ndim - offsets.ndim + if num_dims_to_add > 0: + for _ in range(num_dims_to_add): + offsets = ivy.expand_dims(offsets, axis=0) x = ivy.gather(x, offsets, axis=d + 2) return x @@ -1514,19 +1500,17 @@ def _lanczos_kernel(radius, x): return ivy.where(ivy.bitwise_and(x >= radius, x < -radius), 0.0, out) -def _dim_scale_factor(input_size, output_size, align_corners, scales): - if align_corners: - if output_size > 1: - dim_scale_factor = (input_size - 1) / (output_size - 1) +def _get_final_scale(input_size, output_size, align_corners, scale_factor): + scale = [] + for i, (input, output) in enumerate(zip(input_size, output_size)): + if align_corners: + if output > 1: + scale.append((input - 1) / (output - 1)) + else: + scale.append(1) else: - dim_scale_factor = 0.0 - else: - dim_scale_factor = ( - input_size / (input_size * scales) - if scales is not None - else input_size / output_size - ) - return dim_scale_factor + scale.append(1 / scale_factor[i]) + return scale def _mitchellcubic_kernel(x): @@ -1542,23 +1526,16 @@ def _mitchellcubic_kernel(x): def _compute_weight_mat( input_size, output_size, - scale, align_corners, kernel_fn, - antialias: bool, - dim_scale_factor, + dim_scale, ): - inv_scale = 1.0 / scale - kernel_scale = ivy.maximum(inv_scale, 1.0) if antialias else 1.0 if not align_corners: - sample_f = (ivy.arange(output_size) + 0.5) * dim_scale_factor - 0.5 + sample_f = (ivy.arange(output_size) + 0.5) * dim_scale - 0.5 else: - sample_f = ivy.arange(output_size) * dim_scale_factor - x = ( - ivy.abs( - ivy.expand_dims(sample_f) - ivy.expand_dims(ivy.arange(input_size), axis=-1) - ) - / kernel_scale + sample_f = ivy.arange(output_size) * dim_scale + x = ivy.abs( + ivy.expand_dims(sample_f) - ivy.expand_dims(ivy.arange(input_size), axis=-1) ) weights = kernel_fn(x) total_weight_sum = ivy.sum(weights, axis=0, keepdims=True) @@ -1607,39 +1584,31 @@ def _sum_tensors(ts): def _upsample_bicubic2d_default( a, output_size, + scale, align_corners, - scale_h=None, - scale_w=None, ): N, C, iH, iW = a.shape oH, oW = output_size - def compute_scale(in_size, out_size, align_corners, scale=None): - if align_corners: - return (in_size - 1) / (out_size - 1) if out_size > 1 else 0 - else: - return 1 / scale if scale is not None and scale > 0 else in_size / out_size - def compute_source_index(scale, dst_index, align_corners): if align_corners: return scale * dst_index else: return scale * (dst_index + 0.5) - 0.5 - height_scale = compute_scale(iH, oH, align_corners, scale_h) - width_scale = compute_scale(iW, oW, align_corners, scale_w) - - N_idx = ivy.reshape(ivy.arange(N), (N, 1, 1, 1)) - C_idx = ivy.reshape(ivy.arange(C), (1, C, 1, 1)) + N_idx = ivy.reshape(ivy.arange(N), (N, 1, 1, 1)).astype(ivy.int64) + C_idx = ivy.reshape(ivy.arange(C), (1, C, 1, 1)).astype(ivy.int64) out_y = ivy.reshape(ivy.arange(oH), ((1, 1, oH, 1))) out_x = ivy.reshape(ivy.arange(oW), ((1, 1, 1, oW))) - real_x = compute_source_index(width_scale, out_x, align_corners) + scale_y, scale_x = scale + + real_x = compute_source_index(scale_x, out_x, align_corners) in_x = ivy.floor(real_x) t_x = real_x - in_x ix = ivy.astype(in_x, ivy.int64) - real_y = compute_source_index(height_scale, out_y, align_corners) + real_y = compute_source_index(scale_y, out_y, align_corners) in_y = ivy.floor(real_y) t_y = real_y - in_y iy = ivy.astype(in_y, ivy.int64) @@ -1653,18 +1622,17 @@ def load_bounded(ys, xs): return a[N_idx, C_idx, y_idx, x_idx] def get_x_interp(y): - coeffs_x = tuple((load_bounded(y, x_ofs) for x_ofs in ixs_ofs)) + coeffs_x = tuple(load_bounded(y, x_ofs) for x_ofs in ixs_ofs) return _upsample_cubic_interp1d(coeffs_x, t_x) - coeffs_y = tuple((get_x_interp(y_ofs) for y_ofs in iys_ofs)) + coeffs_y = tuple(get_x_interp(y_ofs) for y_ofs in iys_ofs) result = _upsample_cubic_interp1d(coeffs_y, t_y) return result def area_interpolate(x, dims, size, scale): - ret = ivy.zeros((x.shape[:2] + size)) - inv_scale = ivy.divide(1.0, scale) + ret = ivy.zeros(x.shape[:2] + size) for i, ba in enumerate(x): for j, ch in enumerate(ba): if dims == 3: @@ -1672,16 +1640,16 @@ def area_interpolate(x, dims, size, scale): for h_dim in range(size[1]): for w_dim in range(size[2]): d_index = ( - int(d_dim * inv_scale[0]), - math.ceil((d_dim + 1) * inv_scale[0]), + int(d_dim * scale[0]), + math.ceil((d_dim + 1) * scale[0]), ) h_index = ( - int(h_dim * inv_scale[1]), - math.ceil((h_dim + 1) * inv_scale[1]), + int(h_dim * scale[1]), + math.ceil((h_dim + 1) * scale[1]), ) w_index = ( int(w_dim * scale[2]), - math.ceil((w_dim + 1) * inv_scale[2]), + math.ceil((w_dim + 1) * scale[2]), ) scale_z = d_index[1] - d_index[0] scale_y = h_index[1] - h_index[0] @@ -1698,12 +1666,12 @@ def area_interpolate(x, dims, size, scale): for h_dim in range(size[0]): for w_dim in range(size[1]): h_index = ( - int(h_dim * inv_scale[0]), - math.ceil((h_dim + 1) * inv_scale[0]), + int(h_dim * scale[0]), + math.ceil((h_dim + 1) * scale[0]), ) w_index = ( - int(w_dim * inv_scale[1]), - math.ceil((w_dim + 1) * inv_scale[1]), + int(w_dim * scale[1]), + math.ceil((w_dim + 1) * scale[1]), ) scale_y = h_index[1] - h_index[0] scale_x = w_index[1] - w_index[0] @@ -1714,8 +1682,8 @@ def area_interpolate(x, dims, size, scale): else: for w_dim in range(size[0]): w_index = ( - int(w_dim * inv_scale[0]), - math.ceil((w_dim + 1) * inv_scale[0]), + int(w_dim * scale[0]), + math.ceil((w_dim + 1) * scale[0]), ) scale_x = w_index[1] - w_index[0] ret[i, j, w_dim] = ivy.sum(ch[w_index[0] : w_index[1]]) * ( @@ -1726,12 +1694,21 @@ def area_interpolate(x, dims, size, scale): def get_interpolate_kernel(mode): kernel_func = _triangle_kernel - if mode == "bicubic_tensorflow": - kernel_func = lambda inputs: _cubic_kernel(inputs) + if mode == "tf_bicubic": + + def kernel_func(inputs): # noqa F811 + return _cubic_kernel(inputs) + elif mode == "lanczos3": - kernel_func = lambda inputs: _lanczos_kernel(3, inputs) + + def kernel_func(inputs): + return _lanczos_kernel(3, inputs) + elif mode == "lanczos5": - kernel_func = lambda inputs: _lanczos_kernel(5, inputs) + + def kernel_func(inputs): + return _lanczos_kernel(5, inputs) + return kernel_func @@ -1745,26 +1722,12 @@ def generate_einsum_equation(dim): return einsum_string -def _interpolate_with_kernel( - x, dims, size, scale, input_shape, align_corners, antialias, scale_factor, mode -): - spatial_dims = [2 + i for i in range(dims)] +def _interpolate_with_kernel(x, dims, size, input_size, align_corners, scale, mode): equation = generate_einsum_equation(dims) kernel_func = get_interpolate_kernel(mode) - output_shape = tuple(input_shape[:2]) + size operands = [] - for i, d in enumerate(spatial_dims): - m = input_shape[d] - n = output_shape[d] - dim_scale_factor = _dim_scale_factor( - m, - n, - align_corners, - scale_factor[i] if scale_factor is not None else None, - ) - w = _compute_weight_mat( - m, n, scale[i], align_corners, kernel_func, antialias, dim_scale_factor - ).astype(x.dtype) + for m, n, s in zip(input_size, size, scale): + w = _compute_weight_mat(m, n, align_corners, kernel_func, s).astype(x.dtype) operands.append(w) return ivy.einsum(equation, x, *operands) @@ -1788,7 +1751,7 @@ def interpolate( "area", "nearest_exact", "tf_area", - "bicubic_tensorflow", + "tf_bicubic", "bicubic", "mitchellcubic", "lanczos3", @@ -1797,13 +1760,12 @@ def interpolate( ] = "linear", scale_factor: Optional[Union[Sequence[int], int]] = None, recompute_scale_factor: Optional[bool] = None, - align_corners: Optional[bool] = None, - antialias: bool = False, + align_corners: bool = False, + antialias: bool = False, # ToDo: add support for antialias out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Down/up samples the input to the given size. The algorithm used for interpolation is - determined by mode. + """Down/up samples the input to the given size. The algorithm used for + interpolation is determined by mode. Parameters ---------- @@ -1823,22 +1785,23 @@ def interpolate( - area - tf_area - bicubic + - tf_bicubic - mitchellcubic - lanczos3 - lanczos5 - gaussian scale_factor Multiplier for spatial size that defines the output size (overwriting `size`). + recompute_scale_factor + If True, then scale_factor must be provided and scale_factor is used to + compute the output size. The computed output size will be used to infer new + scales for the interpolation. If recompute_scale_factor is False, then size + or scale_factor will be used directly for interpolation. align_corners If True, the corner pixels of the input and output tensors are aligned, and thus preserving the values at the corner pixels. If False, the corner pixels are not aligned, and the interpolation uses edge value padding for out-of-boundary values. - only has an effect when mode is 'linear', 'bilinear', - 'bicubic' or 'trilinear'. Default: False - antialias - If True, antialiasing is applied when downsampling an image. - Supported modes: 'bilinear', 'bicubic'. out Optional output array, for writing the result to. It must have a shape that the inputs broadcast to. @@ -1847,132 +1810,185 @@ def interpolate( ------- resized array """ - input_shape = ivy.shape(x) - dims = len(input_shape) - 2 - size = _get_size(scale_factor, size, dims, x.shape) - if recompute_scale_factor: - scale_factor = None - elif scale_factor is not None: - scale_factor = ( - [scale_factor] * dims - if isinstance(scale_factor, (int, float)) - else scale_factor + input_size = ivy.shape(x)[2:] + dims = len(input_size) + if ivy.exists(size) and ivy.exists(scale_factor): + raise ivy.utils.exceptions.IvyException( + "only one of size or scale_factor should be defined" ) - scale_factor = ( - [scale_factor[0]] * dims - if isinstance(scale_factor, (list, tuple)) and len(scale_factor) != dims - else scale_factor + elif ivy.exists(size) and not ivy.exists(scale_factor): + if isinstance(size, (list, tuple)): + ivy.utils.assertions.check_equal( + len(size), + dims, + inverse=False, + message=( + "Input and output must have the same number of spatial dimensions," + f" but got input with {list(input_size)} spatial dimensions and" + f" output size {size}." + ), + as_array=False, + ) + elif ivy.exists(scale_factor) and not ivy.exists(size): + if isinstance(scale_factor, (list, tuple)): + ivy.utils.assertions.check_equal( + len(scale_factor), + dims, + inverse=False, + message=( + "Input and scale_factor must have the same number of spatial" + f" dimensions, but got input with {list(input_size)} spatial" + f" dimensions and scale_factor {scale_factor}." + ), + as_array=False, + ) + else: + raise ivy.utils.exceptions.IvyException( + "either size or scale_factor should be defined" ) - scale = [ivy.divide(size[i], input_shape[i + 2]) for i in range(dims)] - if mode in [ - "linear", - "bilinear", - "trilinear", - "nd", - "bicubic_tensorflow", - "lanczos3", - "lanczos5", - ]: - ret = _interpolate_with_kernel( - x, - dims, - size, - scale, - input_shape, - align_corners, - antialias, - scale_factor, - mode, + if ivy.exists(size) and recompute_scale_factor is not None: + raise ivy.utils.exceptions.IvyException( + "recompute_scale_factor is not meaningful with an explicit size." ) - elif mode == "bicubic": - return _upsample_bicubic2d_default(x, size, align_corners) - elif mode in ["nearest-exact", "nearest"]: - ret = nearest_interpolate(x, dims, size, input_shape, mode == "nearest-exact") - elif mode == "area": - ret = area_interpolate(x, dims, size, scale) - elif mode == "mitchellcubic": - batch, channels, in_height, in_width = x.shape - out_height, out_width = size - scale_factor_h = out_height / in_height - scale_factor_w = out_width / in_width - ret = ivy.zeros((batch, channels, out_height, out_width)) - for i in range(out_height): - for j in range(out_width): - p_i = i / scale_factor_h - p_j = j / scale_factor_w - left = int(math.floor(p_j - 2)) - right = int(math.ceil(p_j + 2)) - top = int(math.floor(p_i - 2)) - bottom = int(math.ceil(p_i + 2)) - kernel_w = ivy.array( - [ - _mitchellcubic_kernel((p_j - j) / scale_factor_w) - for i in range(left, right) - ] - ) - kernel_h = ivy.array( - [ - _mitchellcubic_kernel((p_i - i) / scale_factor_h) - for j in range(top, bottom) - ] - ) - left_pad = max(0, -left) - right_pad = max(0, right - in_width) - top_pad = max(0, -top) - bottom_pad = max(0, bottom - in_height) - pad_width = [(0, 0), (0, 0)] * (len(x.shape) - 3) + [ - (top_pad, bottom_pad), - (left_pad, right_pad), - ] - padded_x = ivy.pad(x, pad_width, mode="edge") - for b in range(batch): - for c in range(channels): - patch = padded_x[ - b, - c, - top + top_pad : bottom + top_pad, - left + left_pad : right + left_pad, + if ivy.get_num_dims(x) != 4 and mode == "bilinear": + raise ivy.utils.exceptions.IvyException( + f"Got {x.ndim}D input, but bilinear mode needs 4D input" + ) + if ivy.get_num_dims(x) != 5 and mode == "trilinear": + raise ivy.utils.exceptions.IvyException( + f"Got {x.ndim}D input, but trilinear mode needs 5D input" + ) + if ivy.get_num_dims(x) != 3 and mode == "linear": + raise ivy.utils.exceptions.IvyException( + f"Got {x.ndim}D input, but trilinear mode needs 3D input" + ) + size, scale_factor = _get_size(scale_factor, size, dims, input_size) + ivy.utils.assertions.check_true( + all(s > 0 for s in size), + message=f"output sizes should be greater than 0, but got {size}", + ) + if all(a == b for a, b in zip(size, input_size)): + ret = x + else: + if recompute_scale_factor: + scale_factor = [ivy.divide(size[i], input_size[i]) for i in range(dims)] + else: + scale_factor = [ + 1 if input_size[i] == size[i] else scale_factor[i] for i in range(dims) + ] + scale = _get_final_scale(input_size, size, align_corners, scale_factor) + if mode in [ + "linear", + "bilinear", + "trilinear", + "nd", + "tf_bicubic", + "lanczos3", + "lanczos5", + ]: + ret = _interpolate_with_kernel( + x, + dims, + size, + input_size, + align_corners, + scale, + mode, + ) + elif mode == "bicubic": + ret = _upsample_bicubic2d_default(x, size, scale, align_corners) + elif mode in ["nearest-exact", "nearest"]: + ret = nearest_interpolate(x, dims, size, scale, mode == "nearest-exact") + elif mode == "area": + ret = area_interpolate(x, dims, size, scale) + elif mode == "mitchellcubic": + batch, channels, in_height, in_width = x.shape + out_height, out_width = size + scale_h, scale_w = scale + ret = ivy.zeros((batch, channels, out_height, out_width)) + for i in range(out_height): + for j in range(out_width): + p_i = i * scale_h + p_j = j * scale_w + left = int(math.floor(p_j - 2)) + right = int(math.ceil(p_j + 2)) + top = int(math.floor(p_i - 2)) + bottom = int(math.ceil(p_i + 2)) + kernel_w = ivy.array( + [ + _mitchellcubic_kernel((p_j - j) * scale_w) + for i in range(left, right) ] - ret[b, c, i, j] = ivy.sum( - kernel_h[:, ivy.newaxis] * patch * kernel_w[ivy.newaxis, :] - ) - elif mode == "gaussian": - ratio_h = size[0] / x.shape[-2] - ratio_w = size[1] / x.shape[-1] - sigma = max(1 / ratio_h, 1 / ratio_w) * 0.5 - kernel_size = 2 * int(math.ceil(3 * sigma)) + 1 - kernel_h = ivy.zeros((kernel_size,), dtype=x.dtype) - kernel_w = ivy.zeros((kernel_size,), dtype=x.dtype) - for i in range(kernel_h.size): - kernel_h[i] = ivy.exp(-0.5 * ((i - kernel_h.size // 2) / sigma) ** 2) - kernel_w[i] = ivy.exp(-0.5 * ((i - kernel_w.size // 2) / sigma) ** 2) - kernel_h /= ivy.sum(kernel_h) - kernel_w /= ivy.sum(kernel_w) - pad_width = [(0, 0), (0, 0)] * (len(x.shape) - 3) + [ - (int(math.ceil(3 * sigma)), int(math.ceil(3 * sigma))), - (int(math.ceil(3 * sigma)), int(math.ceil(3 * sigma))), - ] - padded_x = ivy.pad(x, pad_width, mode="constant") - output_shape = x.shape[:2] + size - ret = ivy.zeros(output_shape, dtype=x.dtype) - for i in range(size[0]): - for j in range(size[1]): - p_i = int(math.floor(i / ratio_h + int(math.ceil(3 * sigma)))) - p_j = int(math.floor(j / ratio_w + int(math.ceil(3 * sigma)))) - for b in range(x.shape[0]): - for c in range(x.shape[1]): - patch = padded_x[ - b, - c, - p_i - kernel_size // 2 : p_i + kernel_size // 2 + 1, - p_j - kernel_size // 2 : p_j + kernel_size // 2 + 1, + ) + kernel_h = ivy.array( + [ + _mitchellcubic_kernel((p_i - i) * scale_h) + for j in range(top, bottom) ] - ret[b, c, i, j] = ivy.sum( - kernel_h[ivy.newaxis, :] * patch * kernel_w[:, ivy.newaxis] - ) - elif mode == "tf_area": - ret = _tf_area_interpolate(x, size, dims) - return ivy.astype(ret, ivy.dtype(x), out=out) + ) + left_pad = max(0, -left) + right_pad = max(0, right - in_width) + top_pad = max(0, -top) + bottom_pad = max(0, bottom - in_height) + pad_width = [(0, 0), (0, 0)] * (len(x.shape) - 3) + [ + (top_pad, bottom_pad), + (left_pad, right_pad), + ] + padded_x = ivy.pad(x, pad_width, mode="edge") + for b in range(batch): + for c in range(channels): + patch = padded_x[ + b, + c, + top + top_pad : bottom + top_pad, + left + left_pad : right + left_pad, + ] + ret[b, c, i, j] = ivy.sum( + kernel_h[:, ivy.newaxis] + * patch + * kernel_w[ivy.newaxis, :] + ) + elif mode == "gaussian": + ratio_h, ratio_w = scale + sigma = max(ratio_h, ratio_w) * 0.5 + kernel_size = 2 * int(math.ceil(3 * sigma)) + 1 + kernel_h = ivy.zeros((kernel_size,), dtype=x.dtype) + kernel_w = ivy.zeros((kernel_size,), dtype=x.dtype) + for i in range(kernel_h.size): + kernel_h[i] = ivy.exp(-0.5 * ((i - kernel_h.size // 2) / sigma) ** 2) + kernel_w[i] = ivy.exp(-0.5 * ((i - kernel_w.size // 2) / sigma) ** 2) + kernel_h /= ivy.sum(kernel_h) + kernel_w /= ivy.sum(kernel_w) + pad_width = [(0, 0), (0, 0)] * (len(x.shape) - 3) + [ + (int(math.ceil(3 * sigma)), int(math.ceil(3 * sigma))), + (int(math.ceil(3 * sigma)), int(math.ceil(3 * sigma))), + ] + padded_x = ivy.pad(x, pad_width, mode="constant") + output_shape = x.shape[:2] + size + ret = ivy.zeros(output_shape, dtype=x.dtype) + for i in range(size[0]): + for j in range(size[1]): + p_i = int(math.floor(i * ratio_h + int(math.ceil(3 * sigma)))) + p_j = int(math.floor(j * ratio_w + int(math.ceil(3 * sigma)))) + for b in range(x.shape[0]): + for c in range(x.shape[1]): + patch = padded_x[ + b, + c, + p_i - kernel_size // 2 : p_i + kernel_size // 2 + 1, + p_j - kernel_size // 2 : p_j + kernel_size // 2 + 1, + ] + ret[b, c, i, j] = ivy.sum( + kernel_h[ivy.newaxis, :] + * patch + * kernel_w[:, ivy.newaxis] + ) + elif mode == "tf_area": + ret = _tf_area_interpolate(x, size, scale, dims) + ret = ivy.astype(ret, ivy.dtype(x)) + if ivy.exists(out): + return ivy.inplace_update(out, ret) + return ret interpolate.mixed_backend_wrappers = { @@ -1984,7 +2000,7 @@ def interpolate( } -def _get_size(scale_factor, size, dims, x_shape): +def _get_size(scale_factor, size, dims, input_shape): if scale_factor is not None: if isinstance(scale_factor, (float, int)): scale_factor = [scale_factor] * dims @@ -1992,11 +2008,12 @@ def _get_size(scale_factor, size, dims, x_shape): scale_factor = [scale_factor[0]] * dims size = tuple( - int(math.floor(x_shape[2 + i] * scale_factor[i])) for i in range(dims) + int(math.floor(input_shape[i] * scale_factor[i])) for i in range(dims) ) else: size = (size,) * dims if isinstance(size, int) else tuple(size) - return size + scale_factor = [ivy.divide(size[i], input_shape[i]) for i in range(dims)] + return size, scale_factor def _output_ceil_shape(w, f, p, s): @@ -2004,7 +2021,7 @@ def _output_ceil_shape(w, f, p, s): def _padding_ceil_mode(w, f, p, s, return_added_padding=False): - remaining_pixels = (w - f + sum(p)) % s + remaining_pixels = (w - f + p[0]) % s added_padding = 0 if s > 1 and remaining_pixels != 0 and f > 1: input_size = w + sum(p) @@ -2092,9 +2109,8 @@ def adaptive_max_pool2d( input: Union[ivy.Array, ivy.NativeArray], output_size: Union[Sequence[int], int], ): - """ - Apply a 2D adaptive maximum pooling over an input signal composed of several input - planes. + """Apply a 2D adaptive maximum pooling over an input signal composed of + several input planes. Parameters ---------- @@ -2179,15 +2195,114 @@ def adaptive_max_pool2d( } +@handle_nestable +@inputs_to_ivy_arrays +def adaptive_max_pool3d( + input: Union[ivy.Array, ivy.NativeArray], + output_size: Union[Sequence[int], int], +): + """Apply a 3D adaptive maximum pooling over an input signal composed of + several input planes. + + Parameters + ---------- + input + Input array. Must have shape (N, C, D_in, H_in, W_in) or (C, D_in, H_in, W_in) + where N is the batch dimension, C is the feature dimension, and D_in, H_in, + and W_in are the 3 spatial dimensions. + output_size + Spatial output size. + + Returns + ------- + The result of the pooling operation. Will have shape (N, C, D_out, H_out, W_out) + or (C, D_out, H_out, W_out), where D_out, H_out, W_out = `output_size` + """ + squeeze = False + if input.ndim == 4: + input = ivy.expand_dims(input, axis=0) + squeeze = True + elif input.ndim != 5: + raise ivy.utils.exceptions.IvyException( + f"Got {len(input.shape)}D input, but only 4D and 5D inputs are supported.", + ) + + if isinstance(output_size, int): + output_size = (output_size, output_size, output_size) + + if all(i_s % o_s == 0 for i_s, o_s in zip(input.shape[-3:], output_size)): + stride = tuple(i_s // o_s for i_s, o_s in zip(input.shape[-3:], output_size)) + kernel_size = stride + pooled_output = ivy.max_pool3d( + input, kernel_size, stride, "VALID", data_format="NCDHW" + ) + if squeeze: + return ivy.squeeze(pooled_output, axis=0) + return pooled_output + + idxd, length_d, range_max_d, adaptive_d = _compute_idx( + input.shape[-3], output_size[-3], input.device + ) + idxh, length_h, range_max_h, adaptive_h = _compute_idx( + input.shape[-2], output_size[-2], input.device + ) + idxw, length_w, range_max_w, adaptive_w = _compute_idx( + input.shape[-1], output_size[-1], input.device + ) + + # to numpy and back in order to bypass a slicing error in tensorflow + vals = ivy.array( + input.to_numpy()[..., _expand_to_dim(idxd, 5), _expand_to_dim(idxh, 4), idxw], + device=input.device, + ) + + if not (adaptive_d or adaptive_h or adaptive_w): + ret = ivy.max(vals, axis=(-3, -1)) + ret = ivy.squeeze(ret, axis=0) if squeeze else ret + return ret + + vals, length_d = _mask( + vals, length_d, range_max_d, dim=-3, mask_value=float("-inf") + ) + vals, length_h = _mask( + vals, length_h, range_max_h, dim=-2, mask_value=float("-inf") + ) + vals, length_w = _mask( + vals, length_w, range_max_w, dim=-1, mask_value=float("-inf") + ) + + ret = None + for i, j, k in itertools.product( + range(vals.shape[-4]), range(vals.shape[-2]), range(vals.shape[-1]) + ): + if ret is None: + ret = vals[..., i, :, j, k] + else: + ret = ivy.maximum(ret, vals[..., i, :, j, k]) + pooled_output = ret.astype(vals.dtype) + pooled_output = ivy.squeeze(pooled_output, axis=0) if squeeze else pooled_output + return pooled_output + + +adaptive_max_pool3d.mixed_backend_wrappers = { + "to_add": ( + "handle_backend_invalid", + "inputs_to_native_arrays", + "outputs_to_ivy_arrays", + "handle_device", + ), + "to_skip": ("inputs_to_ivy_arrays",), +} + + @handle_nestable @inputs_to_ivy_arrays def adaptive_avg_pool1d( input: Union[ivy.Array, ivy.NativeArray], output_size: int, ) -> ivy.Array: - """ - Apply a 1D adaptive average pooling over an input signal composed of several input - planes. + """Apply a 1D adaptive average pooling over an input signal composed of + several input planes. Parameters ---------- @@ -2267,19 +2382,21 @@ def adaptive_avg_pool1d( def adaptive_avg_pool2d( input: Union[ivy.Array, ivy.NativeArray], output_size: Union[Sequence[int], int], + /, + *, + data_format: str = "NHWC", ) -> ivy.Array: - """ - Apply a 2D adaptive average pooling over an input signal composed of several input - planes. + """Apply a 2D adaptive average pooling over an input signal composed of + several input planes. Parameters ---------- input - Input array. Must have shape (N, C, H_in, W_in) or (C, H_in, W_in) where N is - the batch dimension, C is the feature dimension, and H_in and W_in are the 2 - spatial dimensions. + A 3D or 4D input array. Should have a floating-point data type. output_size Spatial output size. + data_format + "NHWC" or "NCHW". Defaults to "NHWC". Returns ------- @@ -2295,6 +2412,12 @@ def adaptive_avg_pool2d( f"Got {len(input.shape)}D input, but only 3D and 4D inputs are supported.", ) + permuted_input = False + if data_format == "NHWC": + input = ivy.permute_dims(input, (0, input.ndim - 1, *range(1, input.ndim - 1))) + data_format = "NCHW" + permuted_input = True + if isinstance(output_size, int): output_size = (output_size, output_size) @@ -2304,6 +2427,11 @@ def adaptive_avg_pool2d( pooled_output = ivy.avg_pool2d( input, kernel_size, stride, "VALID", data_format="NCHW" ) + pooled_output = ( + ivy.permute_dims(pooled_output, (0, *range(2, input.ndim), 1)) + if permuted_input + else pooled_output + ) if squeeze: return ivy.squeeze(pooled_output, axis=0) return pooled_output @@ -2316,10 +2444,15 @@ def adaptive_avg_pool2d( ) # to numpy and back in order to bypass a slicing error in tensorflow - vals = ivy.array(input.to_numpy()[..., _expand_to_dim(idxh, 4), idxw]) + vals = input[..., _expand_to_dim(idxh, 4), idxw] if not adaptive_h and not adaptive_w: ret = ivy.mean(vals, axis=(-3, -1)) + ret = ( + ivy.permute_dims(ret, (0, *range(2, input.ndim), 1)) + if permuted_input + else ret + ) ret = ivy.squeeze(ret, axis=0) if squeeze else ret return ret @@ -2334,6 +2467,11 @@ def adaptive_avg_pool2d( ret = ret + vals[..., i, :, j] pooled_output = ret / (length_h * length_w).astype(vals.dtype) + pooled_output = ( + ivy.permute_dims(pooled_output, (0, *range(2, input.ndim), 1)) + if permuted_input + else pooled_output + ) pooled_output = ivy.squeeze(pooled_output, axis=0) if squeeze else pooled_output return pooled_output @@ -2482,8 +2620,7 @@ def sliding_window( dilation: Union[int, Tuple[int, int]] = 1, padding: Union[str, int, Tuple[int, int]] = "VALID", ) -> ivy.Array: - """ - Slide a window of specified dimension over all elements of an array. + """Slide a window of specified dimension over all elements of an array. Parameters ---------- @@ -2615,8 +2752,7 @@ def reduce_window( base_dilation: Union[int, Sequence[int]] = 1, window_dilation: Union[int, Sequence[int]] = 1, ) -> ivy.Array: - """ - Apply a reduction function to all elements in each window of an array. + """Apply a reduction function to all elements in each window of an array. Parameters ---------- @@ -2687,13 +2823,12 @@ def reduce_window( def fft2( x: Union[ivy.Array, ivy.NativeArray], *, - s: Sequence[int] = None, + s: Optional[Sequence[int]] = None, dim: Sequence[int] = (-2, -1), norm: str = "backward", out: Optional[ivy.Array] = None, ) -> ivy.Array: - r""" - Compute the 2-dimensional discrete Fourier Transform. + r"""Compute the 2-dimensional discrete Fourier Transform. Parameters ---------- @@ -2769,8 +2904,7 @@ def ifftn( norm: str = "backward", out: Optional[ivy.Array] = None, ) -> ivy.Array: - r""" - Compute the N-dimensional inverse discrete Fourier Transform. + r"""Compute the N-dimensional inverse discrete Fourier Transform. Parameters ---------- @@ -2854,8 +2988,8 @@ def rfft( norm: Literal["backward", "ortho", "forward"] = "backward", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the one-dimensional discrete Fourier transform for real-valued input. + """Compute the one-dimensional discrete Fourier transform for real-valued + input. .. note:: Applying the one-dimensional inverse discrete Fourier transform for @@ -2923,7 +3057,8 @@ def rfft( >>> x = ivy.array([2.3,3.14,7.2]) >>> y = ivy.zeros(2) >>> ivy.rfft(x, out=y) - ivy.array([12.639999+0.j , -2.87 +3.516063j]) + >>> print(x) + ivy.array([2.29999995, 3.1400001 , 7.19999981]) >>> x = ivy.array([-1.2, 3.4, -5.6]) >>> ivy.rfft(x, n=4, out=x) @@ -2963,8 +3098,7 @@ def rfftn( norm: Optional[str] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the N-dimensional discrete Fourier Transform for real input. + """Compute the N-dimensional discrete Fourier Transform for real input. Parameters ---------- @@ -3008,7 +3142,7 @@ def rfftn( Examples -------- >>> x = ivy.array([1, 2, 3, 4], dtype=ivy.float32) - >>> result = ivy.rfftn(x, s=(4,)) + >>> result = ivy.rfftn(x, s=(4,), axes=(0,)) >>> print(result) ivy.array([10.+0.j, -2.+2.j, -2.+0.j]) @@ -3055,8 +3189,7 @@ def stft( name: Optional[str] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Container static method variant of ivy.stft. + """ivy.Container static method variant of ivy.stft. This method simply wraps the function, and so the docstring for ivy.stft also applies to this method with minimal changes. @@ -3106,10 +3239,10 @@ def stft( def _broadcast_pooling_helper(x, pool_dims: str = "2d", name: str = "padding"): dims = {"1d": 1, "2d": 2, "3d": 3} if isinstance(x, int): - return tuple([x for _ in range(dims[pool_dims])]) + return tuple(x for _ in range(dims[pool_dims])) if len(x) == 1: - return tuple([x[0] for _ in range(dims[pool_dims])]) + return tuple(x[0] for _ in range(dims[pool_dims])) elif len(x) == dims[pool_dims]: return tuple(x) @@ -3145,12 +3278,12 @@ def max_unpool1d( kernel_size: Union[Tuple[int], int], /, *, - strides: Union[int, Tuple[int]] = None, + strides: Optional[Union[int, Tuple[int]]] = None, padding: Union[int, Tuple[int]] = 0, data_format: Optional[str] = "NCW", ) -> ivy.Array: - """ - Compute a 1-D max unpooling given the 1-D pooled input x and its indices. + """Compute a 1-D max unpooling given the 1-D pooled input x and its + indices. Parameters ---------- @@ -3221,3 +3354,304 @@ def max_unpool1d( ), "to_skip": ("inputs_to_ivy_arrays", "handle_partial_mixed_function"), } + + +@handle_exceptions +@handle_backend_invalid +@handle_nestable +@inputs_to_ivy_arrays +@handle_device +def rnn( + step_function: Callable, + inputs: ivy.Array, + initial_states: List[ivy.Array], + /, + *, + go_backwards: bool = False, + mask: Optional[ivy.Array] = None, + constants: Optional[ivy.Array] = None, + unroll: bool = False, + input_length: Optional[int] = None, + time_major: bool = False, + zero_output_for_mask: bool = False, + return_all_outputs: bool = True, +): + """Iterate over the time dimension of a tensor. + + Parameters + ---------- + step_function + RNN step function. + inputs + Array of temporal data of shape (samples, time, ...). + initial_states + Array with shape (samples, state_size). + go_backwards + If True, do the iteration over the time dimension in reverse order and return + the reversed sequence. + mask + Binary array with shape (samples, time, 1), with a zero for every element that + is masked. + constants + List of constant values passed at each step. + unroll + Whether to use a pythonic while loop or ivy.while_loop + input_length + An integer or 1-D array, depending on whether the time dimension is + fixed-length. In case of variable length input, it is used for masking in case + there is no mask specified. + time_major + If True, the inputs and outputs will be in shape (timesteps, batch, ...) whereas + in the False case, it will be (batch, timesteps, ...). + zero_output_for_mask + If True, the otput for masked timestep will be zeros, whereas in the False case, + output from previous timestep is returned + return_all_outputs + If True, return the recurrent outputs for all timesteps in the sequence. If + False, only return the output for the last timestep. + + Returns + ------- + ret + A tuple of + - the latest output of the rnn of shape (samples, ...) + - the output of the rnn of shape (samples, time, ...) if + return_all_outputs=True else (samples, 1, ...) + - list of tensors, latest states returned by the step funciton, of shape + (samples, ...) + + Both the description and the type hints above assumes an array input for simplicity, + but this function is *nestable*, and therefore also accepts :class:`ivy.Container` + instances in place of any of the arguments. + """ + # an ivy implementation of rnn inspired from + # https://github.com/keras-team/keras/blob/v2.14.0/keras/backend.py#L4723-L5202 + + # Swap the batch and timestep dim for the incoming tensor. + if not time_major: + inputs = ivy.permute_dims(inputs, (1, 0, *range(2, len(inputs.shape)))) + + time_steps = inputs.shape[0] + batch = inputs.shape[1] + time_steps_t = ivy.asarray(inputs.shape[0]) + + if mask is not None: + if not ivy.is_bool_dtype(mask): + mask = ivy.astype(mask, ivy.bool) + if len(mask.shape) == 2: + mask = ivy.expand_dims(mask, axis=-1) + if not time_major: + mask = ivy.permute_dims(mask, (1, 0, *range(2, len(mask.shape)))) + + if constants is None: + constants = [] + + def _expand_mask(mask_t, input_t, fixed_dim=1): + rank_diff = len(input_t.shape) - len(mask_t.shape) + for _ in range(rank_diff): + mask_t = ivy.expand_dims(mask_t, axis=-1) + multiples = [1] * fixed_dim + list(input_t.shape[fixed_dim:]) + return ivy.tile(mask_t, repeats=multiples) + + if unroll: + states = tuple(initial_states) + successive_states = [] + successive_outputs = [] + + processed_input = ivy.unstack(inputs) + if go_backwards: + processed_input.reverse() + + if mask is not None: + mask_list = ivy.unstack(mask) + if go_backwards: + mask_list.reverse() + + for i in range(time_steps): + input_t = processed_input[i] + mask_t = mask_list[i] + output_t, new_states = step_function( + input_t, tuple(states) + tuple(constants) + ) + tiled_mask_t = _expand_mask(mask_t, output_t) + + if not successive_outputs: + prev_output = ivy.zeros_like(output_t) + else: + prev_output = successive_outputs[-1] + + output = ivy.where(tiled_mask_t, output_t, prev_output) + + tiled_mask_t = tuple(_expand_mask(mask_t, s) for s in states) + final_states = tuple( + ivy.where(m, s, ps) + for m, s, ps in zip(tiled_mask_t, new_states, states) + ) + states = final_states + + if return_all_outputs: + successive_outputs.append(output) + successive_states.append(states) + else: + successive_outputs = [output] + successive_states = [states] + last_output = successive_outputs[-1] + new_states = successive_states[-1] + outputs = ivy.stack(successive_outputs) + + if zero_output_for_mask: + last_output = ivy.where( + _expand_mask(mask_list[-1], last_output), + last_output, + ivy.zeros_like(last_output), + ) + outputs = ivy.where( + _expand_mask(mask, outputs, fixed_dim=2), + outputs, + ivy.zeros_like(outputs), + ) + + else: + for i in range(time_steps): + input_t = processed_input[i] + output_t, states = step_function( + input_t, tuple(states) + tuple(constants) + ) + if return_all_outputs: + successive_outputs.append(output_t) + successive_states.append(states) + else: + successive_outputs = [output_t] + successive_states = [states] + last_output = successive_outputs[-1] + new_states = successive_states[-1] + outputs = ivy.stack(successive_outputs) + + else: + states = tuple(initial_states) + input_time_zero = inputs[0] + output_time_zero, _ = step_function( + input_time_zero, tuple(initial_states) + tuple(constants) + ) + + if return_all_outputs: + if ivy.is_array(time_steps_t): + output_size = time_steps_t.to_scalar() + else: + output_size = time_steps_t + else: + output_size = 1 + output_loop = ivy.empty( + (output_size, *output_time_zero.shape), dtype=output_time_zero.dtype + ) + + if go_backwards: + inputs = ivy.flip(inputs, axis=0) + time = 0 + + test_fn = lambda time, *_: time < time_steps_t + if mask is not None: + if go_backwards: + mask = ivy.flip(mask, axis=0) + + def masking_fn(time): + return mask[time] + + def compute_masked_output(mask_t, output, mask): + tiled_mask_t = tuple( + _expand_mask(mask_t, o, fixed_dim=len(mask_t.shape)) for o in output + ) + return tuple( + ivy.where(m, o, fm) for m, o, fm in zip(tiled_mask_t, output, mask) + ) + + elif ivy.is_ivy_array(input_length): + if go_backwards: + max_len = ivy.max(input_length) + rev_input_length = ivy.subtract(max_len - 1, input_length) + + def masking_fn(time): + return rev_input_length < time + + else: + + def masking_fn(time): + return input_length > time + + def compute_masked_output(mask_t, output, mask): + return ivy.where(mask_t, output, mask) + + else: + masking_fn = None + + if masking_fn is not None: + zero_output = ivy.zeros_like(output_time_zero) + + def _step(time, output_t, prev_output, *states): + current_input = inputs[time] + mask_t = masking_fn(time) + output, new_states = step_function( + current_input, tuple(states) + tuple(constants) + ) + mask_output = zero_output if zero_output_for_mask else prev_output + new_output = compute_masked_output(mask_t, [output], [mask_output])[0] + + for state, new_state in zip(states, new_states): + if ivy.is_ivy_array(new_state): + ivy.reshape(new_state, shape=state.shape, out=new_state) + final_states = compute_masked_output(mask_t, new_states, states) + new_states = final_states + output_t[time if return_all_outputs else 0] = new_output + + return (time + 1, output_t, new_output) + tuple(new_states) + + final_outputs = ivy.while_loop( + test_fn=test_fn, + body_fn=_step, + vars=(time, output_loop, zero_output) + states, + ) + new_states = final_outputs[3:] + else: + + def _step(time, output_t, *states): + current_input = inputs[time] + output, new_states = step_function( + current_input, tuple(states) + tuple(constants) + ) + + for state, new_state in zip(states, new_states): + if ivy.is_ivy_array(new_state): + ivy.reshape(new_state, shape=state.shape, out=new_state) + + output_t[time if return_all_outputs else 0] = output + return (time + 1, output_t) + tuple(new_states) + + final_outputs = ivy.while_loop( + test_fn=test_fn, body_fn=_step, vars=(time, output_loop) + states + ) + new_states = final_outputs[2:] + + outputs = final_outputs[1] + last_output = outputs[-1] + + shape = list(outputs.shape) + if return_all_outputs: + shape[0] = time_steps + else: + shape[0] = 1 + shape[1] = batch + outputs = ivy.reshape(outputs, shape) + + if not time_major: + outputs = ivy.permute_dims(outputs, (1, 0, *range(2, len(outputs.shape)))) + + return last_output, outputs, new_states + + +rnn.mixed_backend_wrappers = { + "to_add": ( + "inputs_to_native_arrays", + "outputs_to_ivy_arrays", + ), + "to_skip": ("inputs_to_ivy_arrays",), +} diff --git a/ivy/functional/ivy/experimental/linear_algebra.py b/ivy/functional/ivy/experimental/linear_algebra.py index 10d611287f198..d8a22701bbbd6 100644 --- a/ivy/functional/ivy/experimental/linear_algebra.py +++ b/ivy/functional/ivy/experimental/linear_algebra.py @@ -41,8 +41,8 @@ def eigh_tridiagonal( ] = None, tol: Optional[float] = None, ) -> Union[ivy.Array, Tuple[ivy.Array, ivy.Array]]: - """ - Compute the eigenvalues and eigenvectors of a Hermitian tridiagonal matrix. + """Compute the eigenvalues and eigenvectors of a Hermitian tridiagonal + matrix. Parameters ---------- @@ -180,8 +180,7 @@ def diagflat( num_cols: int = -1, out: Optional[Union[ivy.Array, ivy.NativeArray]] = None, ) -> ivy.Array: - """ - Return a two-dimensional array with the flattened input as a diagonal. + """Return a two-dimensional array with the flattened input as a diagonal. Parameters ---------- @@ -243,9 +242,8 @@ def kron( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the Kronecker product, a composite array made of blocks of the second array - scaled by the first. + """Compute the Kronecker product, a composite array made of blocks of the + second array scaled by the first. Parameters ---------- @@ -285,8 +283,7 @@ def matrix_exp( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the matrix exponential of a square matrix. + """Compute the matrix exponential of a square matrix. Parameters ---------- @@ -390,8 +387,7 @@ def eigvals( x: Union[ivy.Array, ivy.NativeArray], /, ) -> ivy.Array: - """ - Compute eigenvalues of x. Returns a set of eigenvalues. + """Compute eigenvalues of x. Returns a set of eigenvalues. Parameters ---------- @@ -437,8 +433,7 @@ def adjoint( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the complex conjugate transpose of x. + """Compute the complex conjugate transpose of x. Parameters ---------- @@ -465,6 +460,59 @@ def adjoint( return current_backend(x).adjoint(x, out=out) +@handle_exceptions +@handle_backend_invalid +@handle_nestable +@handle_array_like_without_promotion +@handle_out_argument +@to_native_arrays_and_back +@handle_device +def lu_factor( + A: Union[ivy.Array, ivy.NativeArray], + /, + *, + pivot: bool = True, + out: Optional[Union[ivy.Array, ivy.NativeArray]] = None, +) -> Tuple[Union[ivy.Array, ivy.NativeArray], Union[ivy.Array, ivy.NativeArray]]: + """ + Parameters + ---------- + A + tensor of shape (*, m, n) where * is zero or more batch dimensions. + + pivot + Whether to compute the LU decomposition with partial pivoting, or the regular LU + decomposition. pivot = False not supported on CPU. Default: True. + + out + tuple of two tensors to write the output to. Ignored if None. Default: None. + + Returns + ------- + ret + A named tuple (LU, pivots). + """ + return current_backend(A).lu_factor(A, pivot=pivot, out=out) + + +@handle_exceptions +@handle_backend_invalid +@handle_nestable +@handle_array_like_without_promotion +@handle_out_argument +@to_native_arrays_and_back +@handle_device +def lu_solve( + lu: Union[ivy.Array, ivy.NativeArray], + p: Union[ivy.Array, ivy.NativeArray], + b: Union[ivy.Array, ivy.NativeArray], + /, + *, + out: Optional[ivy.Array] = None, +) -> ivy.Array: + return current_backend(lu, p, b).lu_solve(lu, p, b, out=out) + + @handle_exceptions @handle_backend_invalid @handle_nestable @@ -482,8 +530,8 @@ def solve_triangular( unit_diagonal: bool = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return the unique solution to the triangular system of linear equations AX = B. + """Return the unique solution to the triangular system of linear equations + AX = B. Parameters ---------- @@ -540,9 +588,8 @@ def multi_dot( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the dot product of two or more matrices in a single function call, while - selecting the fastest evaluation order. + """Compute the dot product of two or more matrices in a single function + call, while selecting the fastest evaluation order. Parameters ---------- @@ -601,8 +648,7 @@ def cond( p: Optional[Union[int, float, str]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the condition number of x. + """Compute the condition number of x. Parameters ---------- @@ -649,8 +695,7 @@ def kronecker( reverse: Optional[bool] = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Kronecker product of a list of matrices. + """Kronecker product of a list of matrices. Parameters ---------- @@ -700,8 +745,7 @@ def khatri_rao( mask: Optional[Union[ivy.Array, ivy.NativeArray]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Khatri-Rao product of a sequence of matrices. + """Khatri-Rao product of a sequence of matrices. This can be seen as a column-wise kronecker product. If one matrix only is given, that matrix is directly returned. @@ -805,8 +849,7 @@ def mode_dot( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - N-mode product of a tensor and a matrix or vector at the specified mode. + """N-mode product of a tensor and a matrix or vector at the specified mode. Parameters ---------- @@ -899,8 +942,8 @@ def multi_mode_dot( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - r""" - N-mode product of a tensor and several matrices or vectors over several modes. + r"""N-mode product of a tensor and several matrices or vectors over several + modes. Parameters ---------- @@ -932,8 +975,8 @@ def multi_mode_dot( Notes ----- If no modes are specified, just assumes there is one matrix or vector per mode and returns: - :math:`\\text{x }\\times_0 \\text{ matrix or vec list[0] }\\times_1 \\cdots \\times_n \\text{ matrix or vec list[n] }` # noqa - """ + :math:`\\text{x }\\times_0 \\text{ matrix or vec list[0] }\\times_1 \\cdots \\times_n \\text{ matrix or vec list[n] }` + """ # noqa: E501 if modes is None: modes = range(len(mat_or_vec_list)) @@ -968,8 +1011,7 @@ def multi_mode_dot( def _svd_checks(x, n_eigenvecs=None): - """ - Run common checks to all of the SVD methods. + """Run common checks to all of the SVD methods. Parameters ---------- @@ -1020,11 +1062,10 @@ def svd_flip( /, u_based_decision: Optional[bool] = True, ) -> Tuple[ivy.Array, ivy.Array]: - """ - Sign correction to ensure deterministic output from SVD. Adjusts the columns of u - and the rows of v such that the loadings in the columns in u that are largest in - absolute value are always positive. This function is borrowed from scikit- - learn/utils/extmath.py. + """Sign correction to ensure deterministic output from SVD. Adjusts the + columns of u and the rows of v such that the loadings in the columns in u + that are largest in absolute value are always positive. This function is + borrowed from scikit- learn/utils/extmath.py. Parameters ---------- @@ -1093,9 +1134,8 @@ def make_svd_non_negative( *, nntype: Optional[Literal["nndsvd", "nndsvda"]] = "nndsvd", ) -> Tuple[ivy.Array, ivy.Array]: - """ - Use NNDSVD method to transform SVD results into a non-negative form. This method - leads to more efficient solving with NNMF [1]. + """Use NNDSVD method to transform SVD results into a non-negative form. + This method leads to more efficient solving with NNMF [1]. Parameters ---------- @@ -1160,8 +1200,8 @@ def make_svd_non_negative( H = ivy.soft_thresholding(H, eps) elif nntype == "nndsvda": avg = ivy.mean(x) - W = ivy.where(W < eps, ivy.ones(ivy.shape(W)) * avg, W) - H = ivy.where(H < eps, ivy.ones(ivy.shape(H)) * avg, H) + W = ivy.where(eps > W, ivy.ones(ivy.shape(W)) * avg, W) + H = ivy.where(eps > H, ivy.ones(ivy.shape(H)) * avg, H) else: raise ValueError( f'Invalid nntype parameter: got {nntype} instead of one of ("nndsvd",' @@ -1185,8 +1225,7 @@ def truncated_svd( compute_uv: bool = True, n_eigenvecs: Optional[int] = None, ) -> Union[ivy.Array, Tuple[ivy.Array, ivy.Array, ivy.Array]]: - """ - Compute a truncated SVD on `x` using the standard SVD. + """Compute a truncated SVD on `x` using the standard SVD. Parameters ---------- @@ -1230,8 +1269,7 @@ def tensor_train( svd: Optional[Literal["truncated_svd"]] = "truncated_svd", verbose: Optional[bool] = False, ) -> ivy.TTTensor: - """ - TT decomposition via recursive SVD. + """TT decomposition via recursive SVD. Decomposes the input into a sequence of order-3 tensors (factors) Also known as Tensor-Train decomposition [1]_ @@ -1361,11 +1399,11 @@ def initialize_tucker( mask: Optional[Union[ivy.Array, ivy.NativeArray]] = None, svd_mask_repeats: Optional[int] = 5, ) -> Tuple[ivy.Array, Sequence[ivy.Array]]: - """ - Initialize core and factors used in `tucker`. The type of initialization is set - using `init`. If `init == 'random'` then initialize factor matrices using - `random_state`. If `init == 'svd'` then initialize the `m`th factor matrix using the - `rank` left singular vectors of the `m`th unfolding of the input tensor. + """Initialize core and factors used in `tucker`. The type of initialization + is set using `init`. If `init == 'random'` then initialize factor matrices + using `random_state`. If `init == 'svd'` then initialize the `m`th factor + matrix using the `rank` left singular vectors of the `m`th unfolding of the + input tensor. Parameters ---------- @@ -1402,11 +1440,11 @@ def initialize_tucker( """ try: assert len(x.shape) >= 2 - except ValueError: + except ValueError as e: raise ValueError( "expected x to have at least 2 dimensions but it has only" f" {len(x.shape)} dimension(s)" - ) + ) from e # Initialisation if init == "svd": @@ -1477,8 +1515,7 @@ def partial_tucker( verbose: Optional[bool] = False, return_errors: Optional[bool] = False, ) -> Tuple[ivy.Array, Sequence[ivy.Array]]: - """ - Partial tucker decomposition via Higher Order Orthogonal Iteration (HOI) + """Partial tucker decomposition via Higher Order Orthogonal Iteration (HOI) Decomposes `tensor` into a Tucker decomposition exclusively along the provided modes. @@ -1626,8 +1663,7 @@ def tucker( verbose: Optional[bool] = False, return_errors: Optional[bool] = False, ): - """ - Tucker decomposition via Higher Order Orthogonal Iteration (HOI) + """Tucker decomposition via Higher Order Orthogonal Iteration (HOI) Decomposes `tensor` into a Tucker decomposition: ``tensor = [| core; factors[0], ...factors[-1] |]`` [1]_ @@ -1686,11 +1722,11 @@ def tucker( if fixed_factors: try: (core, factors) = init - except ValueError: + except ValueError as e: raise ValueError( f"Got fixed_factor={fixed_factors} but no appropriate Tucker tensor was" ' passed for "init".' - ) + ) from e if len(fixed_factors) == len(factors): return ivy.TuckerTensor((core, factors)) @@ -1763,10 +1799,9 @@ def tt_matrix_to_tensor( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return the full tensor whose TT-Matrix decomposition is given by 'factors' Re- - assembles 'factors', which represent a tensor in TT-Matrix format into the - corresponding full tensor. + """Return the full tensor whose TT-Matrix decomposition is given by + 'factors' Re- assembles 'factors', which represent a tensor in TT-Matrix + format into the corresponding full tensor. Parameters ---------- @@ -1834,10 +1869,9 @@ def dot( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the dot product between two arrays `a` and `b` using the current backend's - implementation. The dot product is defined as the sum of the element-wise product of - the input arrays. + """Compute the dot product between two arrays `a` and `b` using the current + backend's implementation. The dot product is defined as the sum of the + element-wise product of the input arrays. Parameters ---------- @@ -1895,8 +1929,7 @@ def general_inner_product( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Generalised inner products between tensors. + """Generalised inner products between tensors. Takes the inner product between the last (respectively first) `n_modes` of `a` (respectively `b`) @@ -1925,7 +1958,7 @@ def general_inner_product( >>> a = ivy.array([1, 2, 3]) >>> b = ivy.array([4, 5, 6]) - >>> result = ivy.general_inner_product(a, b, n_modes=1) + >>> result = ivy.general_inner_product(a, b, 1) >>> print(result) ivy.array(32) @@ -1937,7 +1970,7 @@ def general_inner_product( >>> a = ivy.array([[1, 1], [1, 1]]) >>> b = ivy.array([[1, 2, 3, 4],[1, 1, 1, 1]]) - >>> result = ivy.general_inner_product(a, b, n_modes=1) + >>> result = ivy.general_inner_product(a, b, 1) >>> print(result) ivy.array([[2, 3, 4, 5], [2, 3, 4, 5]]) @@ -1985,8 +2018,7 @@ def higher_order_moment( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the Higher-Order Moment. + """Compute the Higher-Order Moment. Parameters ---------- @@ -2033,8 +2065,7 @@ def batched_outer( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return a generalized outer product of the tensors. + """Return a generalized outer product of the tensors. Parameters ---------- diff --git a/ivy/functional/ivy/experimental/losses.py b/ivy/functional/ivy/experimental/losses.py index 7e45013b52f8a..11177553a1cef 100644 --- a/ivy/functional/ivy/experimental/losses.py +++ b/ivy/functional/ivy/experimental/losses.py @@ -28,13 +28,13 @@ def log_poisson_loss( reduction: str = "none", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the log-likelihood loss between the prediction and the target under the - assumption that the target has a Poisson distribution. Caveat: By default, this is - not the exact loss, but the loss minus a constant term [log(z!)]. That has no effect - for optimization, but does not play well with relative loss comparisons. To compute - an approximation of the log factorial term, specify ``compute_full_loss=True`` to - enable Stirling's Approximation. + """Compute the log-likelihood loss between the prediction and the target + under the assumption that the target has a Poisson distribution. Caveat: By + default, this is not the exact loss, but the loss minus a constant term + [log(z!)]. That has no effect for optimization, but does not play well with + relative loss comparisons. To compute an approximation of the log factorial + term, specify ``compute_full_loss=True`` to enable Stirling's + Approximation. Parameters ---------- @@ -107,7 +107,7 @@ def l1_loss( target: Union[ivy.Array, ivy.NativeArray], /, *, - reduction: Optional[str] = "mean", + reduction: str = "mean", out: Optional[ivy.Array] = None, ) -> ivy.Array: """ @@ -138,11 +138,11 @@ def l1_loss( -------- >>> x = ivy.array([1.0, 2.0, 3.0]) >>> y = ivy.array([0.5, 2.5, 2.0]) - >>> print(ivy.l1_loss(x, y)) - ivy.array(0.6) + >>> ivy.l1_loss(x, y) + ivy.array(0.666) >>> a = ivy.array([[1.0, 2.0], [3.0, 4.0]]) >>> b = ivy.array([[0.5, 1.5], [2.5, 3.5]]) - >>> print(ivy.l1_loss(a, b)) + >>> ivy.l1_loss(a, b) ivy.array(0.5) """ loss = ivy.abs(target - input) @@ -165,12 +165,12 @@ def huber_loss( pred: Union[ivy.Array, ivy.NativeArray], /, *, - delta: Optional[float] = 1.0, - reduction: Optional[str] = "mean", + delta: float = 1.0, + reduction: str = "mean", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the Huber loss (smooth L1 loss) between true and predicted values. + """Compute the Huber loss (smooth L1 loss) between true and predicted + values. Parameters ---------- @@ -230,12 +230,11 @@ def smooth_l1_loss( target: Union[ivy.Array, ivy.NativeArray], /, *, - beta: Optional[float] = 1.0, - reduction: Optional[str] = "mean", + beta: float = 1.0, + reduction: str = "mean", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the smooth L1 loss between two input tensors. + """Compute the smooth L1 loss between two input tensors. Parameters ---------- @@ -259,12 +258,12 @@ def smooth_l1_loss( Examples -------- - >>> input = ivy.array([1.0, 2.0, 3.0]) - >>> target = ivy.array([2.5, 1.8, 3.2]) + >>> x = ivy.array([1.0, 2.0, 3.0]) + >>> y = ivy.array([2.5, 1.8, 3.2]) >>> ivy.smooth_l1_loss(x, y, beta=1.0) ivy.array(0.3467) - >>> input = ivy.array([1.0, 2.0, 3.0]) - >>> target = ivy.array([6.0, 2.0, 3.0]) + >>> x = ivy.array([1.0, 2.0, 3.0]) + >>> y = ivy.array([6.0, 2.0, 3.0]) >>> ivy.smooth_l1_loss(x, y, beta=1.0) ivy.array(1.5) >>> input = ivy.array([2.0, 3.0, 5.0, 7.0]) @@ -360,11 +359,11 @@ def soft_margin_loss( target: Union[ivy.Array, ivy.NativeArray], /, *, - reduction: Optional[str] = "mean", + reduction: str = "mean", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the soft-margin hinge loss between predicted scores and true binary labels. + """Compute the soft-margin hinge loss between predicted scores and true + binary labels. Parameters ---------- @@ -420,12 +419,11 @@ def kl_div( target: Union[ivy.Array, ivy.NativeArray], /, *, - reduction: Optional[str] = "mean", + reduction: str = "mean", log_target=False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the Kullback-Leibler divergence loss between two input tensors + """Compute the Kullback-Leibler divergence loss between two input tensors (conventionally, probability distributions). Parameters @@ -511,8 +509,7 @@ def poisson_nll_loss( eps: float = 1e-8, reduction: str = "mean", ) -> ivy.Array: - r""" - Compute the Poisson Negative Log Likelihood Loss. + r"""Compute the Poisson Negative Log Likelihood Loss. This function calculates the negative log likelihood loss between the `input` and `target`under the assumption that @@ -562,7 +559,7 @@ def poisson_nll_loss( -------- >>> input_tensor = ivy.array([1, 2, 3, 4], dtype=ivy.float64) >>> target_tensor = ivy.array([2, 2, 2, 2], dtype=ivy.float64) - >>> loss = poisson_nll_loss(input_tensor, target_tensor, log_input=False) + >>> loss = ivy.poisson_nll_loss(input_tensor, target_tensor, log_input=False) >>> print(loss) ivy.array(0.91097307) """ @@ -574,3 +571,92 @@ def poisson_nll_loss( eps=eps, reduction=reduction, ) + + +@handle_exceptions +@handle_nestable +@handle_array_like_without_promotion +@to_native_arrays_and_back +def hinge_embedding_loss( + input: Union[ivy.Array, ivy.NativeArray], + target: Union[ivy.Array, ivy.NativeArray], + *, + margin: float = 1.0, + reduction: str = "mean", +) -> ivy.Array: + r"""Measures loss from input `x` and label `y` with values 1 or -1. It + evaluates if two inputs are similar or not, often used for embedding or + semi-supervised learning. + + Loss for the `n`-th sample: + .. math:: + l_n = \begin{cases} + x_n, & \text{if}\; y_n = 1,\\ + \max \{0, margin - x_n\}, & \text{if}\; y_n = -1, + \end{cases} + + Total loss: + .. math:: + \ell(x, y) = \begin{cases} + \operatorname{mean}(L), & \text{if reduction} = \text{`mean';}\\ + \operatorname{sum}(L), & \text{if reduction} = \text{`sum'.} + \end{cases} + + where :math:`L = \{l_1,\dots,l_N\}^\top` . + + Parameters + ---------- + input + Input tensor with dtype float. + The shape is [N, \*], where N is batch size and `\*` represents + any number of additional dimensions. + label + Label tensor containing 1 or -1 with dtype float32 or float64. + Its shape matches that of the input. + margin + Sets the hyperparameter margin. Determines the necessary input size + for hinge_embedding_loss calculations when label is -1. Inputs smaller + than the margin are minimized with hinge_embedding_loss. + Default is 1.0. + reduction + Specifies how to aggregate the loss across the batch. Options are: + - ``'none'``: Returns the unreduced loss. + - ``'mean'``: Returns the mean loss. + - ``'sum'``: Returns the summed loss. + Default is ``'mean'``. + + Shape + ----- + - Input: :math:`(*)` where :math:`*` means, any number of dimensions. \ + The sum operation operates over all the elements. + - Target: :math:`(*)`, same shape as the input + - Output: scalar. If :attr:`reduction` is ``'none'``, + then same shape as the input + + Returns + ------- + ret + Hinge embedding loss calculated from the input and label, + shaped based on the reduction method. + + Examples + -------- + >>> input_tensor = ivy.array([1, 2, 3, 4], dtype=ivy.float64) + >>> target_tensor = ivy.array([1, 1, 1, 1], dtype=ivy.float64) + >>> loss = ivy.hinge_embedding_loss(input_tensor, target_tensor, reduction="none") + >>> loss + ivy.array([1., 2., 3., 4.]) + + >>> input_tensor = ivy.array([21, 22], dtype=ivy.float32) + >>> target_tensor = ivy.array([-1, 1], dtype=ivy.float32) + >>> loss = ivy.hinge_embedding_loss(input_tensor,target_tensor, + ... margin=2.0, reduction="sum") + >>> loss + ivy.array(22.) + """ + return ivy.current_backend().hinge_embedding_loss( + input, + target, + margin=margin, + reduction=reduction, + ) diff --git a/ivy/functional/ivy/experimental/manipulation.py b/ivy/functional/ivy/experimental/manipulation.py index 94a6360ecc4ce..a1467eddf7271 100644 --- a/ivy/functional/ivy/experimental/manipulation.py +++ b/ivy/functional/ivy/experimental/manipulation.py @@ -53,9 +53,10 @@ def _to_tf_padding(pad_width, ndim): def _check_paddle_pad( - mode, reflect_type, pad_width, input_shape, constant_values, ndim_limit + mode, reflect_type, pad_width, input_shape, constant_values, ndim_limit, extend=True ): - pad_width = _to_tf_padding(pad_width, len(input_shape)) + if extend: + pad_width = _to_tf_padding(pad_width, len(input_shape)) return isinstance(constant_values, Number) and ( mode == "constant" or ( @@ -97,15 +98,15 @@ def flatten( /, *, copy: Optional[bool] = None, - start_dim: Optional[int] = 0, - end_dim: Optional[int] = -1, - order: Optional[str] = "C", + start_dim: int = 0, + end_dim: int = -1, + order: str = "C", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Flattens input by reshaping it into a one-dimensional tensor. If start_dim or - end_dim are passed, only dimensions starting with start_dim and ending with end_dim - are flattened. The order of elements in input is unchanged. + """Flattens input by reshaping it into a one-dimensional tensor. If + start_dim or end_dim are passed, only dimensions starting with start_dim + and ending with end_dim are flattened. The order of elements in input is + unchanged. Parameters ---------- @@ -259,8 +260,7 @@ def moveaxis( copy: Optional[bool] = None, out: Optional[Union[ivy.Array, ivy.NativeArray]] = None, ) -> Union[ivy.Array, ivy.NativeArray]: - """ - Move axes of an array to new positions.. + """Move axes of an array to new positions.. Parameters ---------- @@ -309,8 +309,7 @@ def heaviside( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the Heaviside step function for each element in x1. + """Compute the Heaviside step function for each element in x1. Parameters ---------- @@ -358,9 +357,9 @@ def flipud( copy: Optional[bool] = None, out: Optional[Union[ivy.Array, ivy.NativeArray]] = None, ) -> Union[ivy.Array, ivy.NativeArray]: - """ - Flip array in the up/down direction. Flip the entries in each column in the up/down - direction. Rows are preserved, but appear in a different order than before. + """Flip array in the up/down direction. Flip the entries in each column in + the up/down direction. Rows are preserved, but appear in a different order + than before. Parameters ---------- @@ -402,8 +401,7 @@ def vstack( *, out: Optional[Union[ivy.Array, ivy.NativeArray]] = None, ) -> ivy.Array: - """ - Stack arrays in sequence vertically (row wise). + """Stack arrays in sequence vertically (row wise). Parameters ---------- @@ -447,8 +445,7 @@ def hstack( *, out: Optional[Union[ivy.Array, ivy.NativeArray]] = None, ) -> ivy.Array: - """ - Stack arrays in sequence horizotally (column wise). + """Stack arrays in sequence horizotally (column wise). Parameters ---------- @@ -494,9 +491,8 @@ def rot90( axes: Tuple[int, int] = (0, 1), out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Rotate an array by 90 degrees in the plane specified by axes. Rotation direction is - from the first towards the second axis. + """Rotate an array by 90 degrees in the plane specified by axes. Rotation + direction is from the first towards the second axis. Parameters ---------- @@ -582,8 +578,8 @@ def top_k( sorted: bool = True, out: Optional[tuple] = None, ) -> Tuple[ivy.Array, ivy.NativeArray]: - """ - Return the `k` largest elements of the given input array along a given axis. + """Return the `k` largest elements of the given input array along a given + axis. Parameters ---------- @@ -661,10 +657,9 @@ def fliplr( copy: Optional[bool] = None, out: Optional[Union[ivy.Array, ivy.NativeArray]] = None, ) -> Union[ivy.Array, ivy.NativeArray]: - """ - Flip array in the left/right direction. Flip the entries in each column in the - left/right direction. Columns are preserved, but appear in a different order than - before. + """Flip array in the left/right direction. Flip the entries in each column + in the left/right direction. Columns are preserved, but appear in a + different order than before. Parameters ---------- @@ -707,8 +702,7 @@ def i0( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the Bessel i0 function of x element-wise. + """Compute the Bessel i0 function of x element-wise. Parameters ---------- @@ -901,29 +895,30 @@ def _set_wrap_both(padded, axis, width_pair): return padded -def _pad_simple(array, pad_width, fill_value=None): +def _init_pad(array, pad_width, fill_value=None): new_shape = tuple( left + size + right for size, (left, right) in zip(array.shape, pad_width) ) - padded = ivy.zeros(new_shape, dtype=array.dtype) if fill_value is not None: - padded = ivy.ones_like(padded) * fill_value + padded = ivy.ones(new_shape, dtype=array.dtype) * fill_value + else: + padded = ivy.zeros(new_shape, dtype=array.dtype) original_area_slice = tuple( slice(left, left + size) for size, (left, right) in zip(array.shape, pad_width) ) padded[original_area_slice] = array - return padded, original_area_slice + return padded -def _to_pairs(x, n): +def _to_pairs(x, n, m=2): if ivy.isscalar(x): - return ((x, x),) * n - elif len(x) == 2 and ivy.isscalar(x[0]): - return ((x[0], x[1]),) * n + return ((x,) * m,) * n + elif len(x) == m and ivy.isscalar(x[0]): + return ((*x[:m],),) * n elif len(x) != n: ivy.utils.assertions.check_equal( ivy.asarray(list(x)).shape, - (n, 2), + (n, m), message=( "tuple argument should contain " "ndim pairs where ndim is the number of " @@ -934,47 +929,40 @@ def _to_pairs(x, n): return x -def _to_dilated(x, n): - if ivy.isscalar(x): - return ((x, x, x),) * n - elif len(x) == 3 and ivy.isscalar(x[0]): - return ((x[0], x[1], x[2]),) * n - elif len(x) != n: - ivy.utils.assertions.check_equal( - ivy.asarray(list(x)).shape, - (n, 3), - message=( - "tuple argument should contain " - "ndim groups where ndim is the number of " - "the input's dimensions" - ), - as_array=False, - ) - return x +def check_scalar(x, force_integer, force_positive): + return ( + ivy.isscalar(x) + and (ivy.is_int_dtype(x) if force_integer else True) + and (x >= 0 if force_positive else True) + ) -def _check_tuple_arg(arg, name, force_integer=True): - is_scalar = ivy.is_int_dtype if force_integer else ivy.isscalar - flag_assert = False - if isinstance(arg, (tuple, list)): - for nested in arg: - if isinstance(nested, (tuple, list)): - for sub_nested in nested: - if not is_scalar(sub_nested): - flag_assert = True - break - elif not is_scalar(nested): - flag_assert = True - elif not is_scalar(arg): - flag_assert = True - if flag_assert: +def _check_tuple_arg(arg, arg_name, force_integer=False, force_positive=False): + if not ( + check_scalar(arg, force_integer, force_positive) + or ( + isinstance(arg, (tuple, list)) + and ( + all(check_scalar(elem, force_integer, force_positive) for elem in arg) + or ( + isinstance(elem, (tuple, list)) + and all( + check_scalar(sub_elem, force_integer, force_positive) + for sub_elem in elem + ) + ) + for elem in arg + ) + ) + ): if force_integer: raise ivy.utils.exceptions.IvyException( - f"{name} should be int, tuple of ints or tuple of int tuples" + f"{arg_name} should be int, tuple of ints or tuple of int tuples" ) else: raise ivy.utils.exceptions.IvyException( - f"{name} should be scalar, tuple of scalars or tuple of scalar tuples" + f"{arg_name} should be scalar, tuple of scalars or tuple of scalar" + " tuples" ) @@ -986,45 +974,42 @@ def _check_arguments( end_values, reflect_type, ): + supported_modes = [ + "constant", + "dilated", + "edge", + "linear_ramp", + "maximum", + "mean", + "median", + "minimum", + "reflect", + "symmetric", + "wrap", + "empty", + ] ivy.utils.assertions.check_true( - callable(mode) - or mode - in [ - "constant", - "dilated", - "edge", - "linear_ramp", - "maximum", - "mean", - "median", - "minimum", - "reflect", - "symmetric", - "wrap", - "empty", - ], - message="the provided mode is not supported", + callable(mode) or mode in supported_modes, + message=f"Only modes {supported_modes} are supported. Got {mode}.", + ) + _check_tuple_arg( + pad_width, "pad_width", force_positive=mode != "dilated", force_integer=True ) - _check_tuple_arg(pad_width, "pad_width") - if mode not in ["dilated"]: - ivy.utils.assertions.check_true( - all(element[1] >= 0 for element in ivy.ndenumerate(pad_width)), - message="the pad_widths must be greater or equal to zero", - ) if mode in ["maximum", "mean", "median", "minimum"]: - _check_tuple_arg(stat_length, "stat_length") - ivy.utils.assertions.check_true( - all(element[1] > 0 for element in ivy.ndenumerate(stat_length)), - message="the stat lengths must be greater than zero", + _check_tuple_arg( + stat_length, "stat_length", force_positive=True, force_integer=True ) - elif mode == "constant": - _check_tuple_arg(constant_values, "constant_values", force_integer=False) + elif mode in ["constant", "dilated"]: + _check_tuple_arg(constant_values, "constant_values") elif mode == "linear_ramp": - _check_tuple_arg(end_values, "end_values", force_integer=False) - ivy.utils.assertions.check_true( - reflect_type in ["even", "odd"], - message="the provided reflect_type is not supported", - ) + _check_tuple_arg(end_values, "end_values") + elif mode in ["reflect", "symmetric"]: + ivy.utils.assertions.check_true( + reflect_type in ["even", "odd"], + message=( + f"Only reflect types ['even', 'odd'] are supported. Got {reflect_type}." + ), + ) @handle_exceptions @@ -1061,8 +1046,7 @@ def pad( reflect_type: Literal["even", "odd"] = "even", **kwargs: Optional[Any], ) -> ivy.Array: - """ - Pad an array. + """Pad an array. Parameters ---------- @@ -1210,23 +1194,23 @@ def pad( end_values, reflect_type, ) + ndim = input.ndim if mode == "dilated": - pad_width = _to_dilated(pad_width, input.ndim) + pad_width = _to_pairs(pad_width, ndim, m=3) if not ivy.is_array(constant_values) or constant_values.dtype != input.dtype: constant_values = ivy.asarray(constant_values, dtype=input.dtype) return _interior_pad(input, constant_values, pad_width) pad_width = _to_pairs(pad_width, len(input.shape)) if callable(mode): func = mode - padded, _ = _pad_simple(input, pad_width, fill_value=0) - for axis in range(padded.ndim): + padded = _init_pad(input, pad_width, fill_value=0) + for axis in range(ndim): padded = ivy.moveaxis(padded, axis, -1) inds = ivy.ndindex(padded.shape[:-1]) for ind in inds: padded[ind] = func(padded[ind], pad_width[axis], axis, kwargs) return padded - padded, original_area_slice = _pad_simple(input, pad_width) - axes = range(padded.ndim) + padded = _init_pad(input, pad_width) stat_functions = { "maximum": ivy.max, "minimum": ivy.min, @@ -1234,35 +1218,31 @@ def pad( "median": ivy.median, } if mode == "constant": - constant_values = _to_pairs(constant_values, padded.ndim) - constant_values = tuple(tuple(map(ivy.array, pair)) for pair in constant_values) - for axis, width_pair, value_pair in zip(axes, pad_width, constant_values): + constant_values = _to_pairs(constant_values, ndim) + for axis, (width_pair, value_pair) in enumerate( + zip(pad_width, constant_values) + ): padded = _set_pad_area(padded, axis, width_pair, value_pair) elif mode == "empty": pass elif mode == "edge": - for axis, width_pair in zip(axes, pad_width): + for axis, width_pair in enumerate(pad_width): edge_pair = _get_edges(padded, axis, width_pair) padded = _set_pad_area(padded, axis, width_pair, edge_pair) elif mode == "linear_ramp": - end_values = _to_pairs(end_values, padded.ndim) - for axis, width_pair, value_pair in zip(axes, pad_width, end_values): + end_values = _to_pairs(end_values, ndim) + for axis, (width_pair, value_pair) in enumerate(zip(pad_width, end_values)): ramp_pair = _get_linear_ramps(padded, axis, width_pair, value_pair) padded = _set_pad_area(padded, axis, width_pair, ramp_pair) elif mode in stat_functions: func = stat_functions[mode] - stat_length = _to_pairs(stat_length, padded.ndim) - if mode == "median": - ivy.utils.assertions.check_true( - ivy.is_float_dtype(input), - message="median interpolation is only supported for floats", - ) - for axis, width_pair, length_pair in zip(axes, pad_width, stat_length): + stat_length = _to_pairs(stat_length, ndim) + for axis, (width_pair, length_pair) in enumerate(zip(pad_width, stat_length)): stat_pair = _get_stats(padded, axis, width_pair, length_pair, func) padded = _set_pad_area(padded, axis, width_pair, stat_pair) elif mode in {"reflect", "symmetric"}: include_edge = True if mode == "symmetric" else False - for axis, (left_index, right_index) in zip(axes, pad_width): + for axis, (left_index, right_index) in enumerate(pad_width): if input.shape[axis] == 1 and (left_index > 0 or right_index > 0): edge_pair = _get_edges(padded, axis, (left_index, right_index)) padded = _set_pad_area( @@ -1274,7 +1254,7 @@ def pad( padded, axis, (left_index, right_index), reflect_type, include_edge ) elif mode == "wrap": - for axis, (left_index, right_index) in zip(axes, pad_width): + for axis, (left_index, right_index) in enumerate(pad_width): padded = _set_wrap_both(padded, axis, (left_index, right_index)) return padded @@ -1305,8 +1285,7 @@ def vsplit( *, copy: Optional[bool] = None, ) -> List[ivy.Array]: - """ - Split an array vertically into multiple sub-arrays. + """Split an array vertically into multiple sub-arrays. Parameters ---------- @@ -1356,8 +1335,7 @@ def dsplit( *, copy: Optional[bool] = None, ) -> List[ivy.Array]: - """ - Split an array into multiple sub-arrays along the 3rd axis. + """Split an array into multiple sub-arrays along the 3rd axis. Parameters ---------- @@ -1407,9 +1385,9 @@ def atleast_1d( *arys: Union[ivy.Array, ivy.NativeArray, bool, Number], copy: Optional[bool] = None, ) -> List[ivy.Array]: - """ - Convert inputs to arrays with at least one dimension. Scalar inputs are converted to - 1-dimensional arrays, whilst higher-dimensional inputs are preserved. + """Convert inputs to arrays with at least one dimension. Scalar inputs are + converted to 1-dimensional arrays, whilst higher-dimensional inputs are + preserved. Parameters ---------- @@ -1452,8 +1430,7 @@ def dstack( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Stack arrays in sequence depth wise (along third axis). + """Stack arrays in sequence depth wise (along third axis). Parameters ---------- @@ -1493,9 +1470,9 @@ def atleast_2d( *arys: Union[ivy.Array, ivy.NativeArray], copy: Optional[bool] = None, ) -> List[ivy.Array]: - """ - Convert inputs to arrays with at least two dimension. Scalar inputs are converted to - 2-dimensional arrays, whilst higher-dimensional inputs are preserved. + """Convert inputs to arrays with at least two dimension. Scalar inputs are + converted to 2-dimensional arrays, whilst higher-dimensional inputs are + preserved. Parameters ---------- @@ -1539,9 +1516,9 @@ def atleast_3d( *arys: Union[ivy.Array, ivy.NativeArray, bool, Number], copy: Optional[bool] = None, ) -> List[ivy.Array]: - """ - Convert inputs to arrays with at least three dimension. Scalar inputs are converted - to 3-dimensional arrays, whilst higher-dimensional inputs are preserved. + """Convert inputs to arrays with at least three dimension. Scalar inputs + are converted to 3-dimensional arrays, whilst higher-dimensional inputs are + preserved. Parameters ---------- @@ -1600,8 +1577,7 @@ def take_along_axis( mode: str = "fill", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Take values from the input array by matching 1d index and data slices. + """Take values from the input array by matching 1d index and data slices. Parameters ---------- @@ -1651,8 +1627,7 @@ def hsplit( *, copy: Optional[bool] = None, ) -> List[ivy.Array]: - """ - Split an array into multiple sub-arrays horizontally. + """Split an array into multiple sub-arrays horizontally. Parameters ---------- @@ -1698,8 +1673,7 @@ def hsplit( @handle_exceptions @inputs_to_native_shapes def broadcast_shapes(*shapes: Union[List[int], List[Tuple]]) -> Tuple[int]: - """ - Broadcasts shapes. + """Broadcasts shapes. Parameters ---------- @@ -1740,8 +1714,8 @@ def expand( copy: Optional[bool] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Broadcast the input Array following the given shape and the broadcast rule. + """Broadcast the input Array following the given shape and the broadcast + rule. Parameters ---------- @@ -1782,9 +1756,8 @@ def put_along_axis( mode: Literal["sum", "min", "max", "mul", "mean", "replace"] = "replace", out: Optional[ivy.Array] = None, ) -> None: - """ - Put values into the input array by matching 1d index and data slices along a - specified axis. + """Put values into the input array by matching 1d index and data slices + along a specified axis. Parameters ---------- @@ -1824,10 +1797,10 @@ def put_along_axis( >>> axis = 1 >>> indices = ivy.argmax(arr, axis=axis, keepdims=True) >>> value = 100 - >>> ivy.put_along_axis(arr, indices, value, axis, mode='add') + >>> ivy.put_along_axis(arr, indices, value, axis, mode='sum') >>> print(arr) - ivy.array([[ 10, 130, 20], - [ 160, 40, 50]]) + ivy.array([[10, 30, 20], + [60, 40, 50]]) """ arr_shape = arr.shape @@ -1877,8 +1850,7 @@ def as_strided( strides: Sequence[int], /, ) -> ivy.Array: - """ - Create a copy of the input array with the given shape and strides. + """Create a copy of the input array with the given shape and strides. Parameters ---------- @@ -1959,8 +1931,7 @@ def concat_from_sequence( axis: int = 0, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Concatenate a sequence of arrays along a new or an existing axis. + """Concatenate a sequence of arrays along a new or an existing axis. Parameters ---------- @@ -2066,8 +2037,7 @@ def associative_scan( reverse: bool = False, axis: int = 0, ) -> ivy.Array: - """ - Perform an associative scan over the given array. + """Perform an associative scan over the given array. Parameters ---------- @@ -2152,9 +2122,8 @@ def unique_consecutive( Union[ivy.Array, ivy.NativeArray], Union[ivy.Array, ivy.NativeArray], ]: - """ - Eliminates all but the first element from every consecutive group of equivalent - elements in ``x``. + """Eliminates all but the first element from every consecutive group of + equivalent elements in ``x``. Parameters ---------- @@ -2200,8 +2169,7 @@ def fill_diagonal( *, wrap: bool = False, ) -> Union[ivy.Array, ivy.NativeArray]: - """ - Fill the main diagonal of the given array of any dimensionality.. + """Fill the main diagonal of the given array of any dimensionality.. Parameters ---------- @@ -2263,12 +2231,11 @@ def fill_diagonal( def unfold( x: Union[ivy.Array, ivy.NativeArray], /, - mode: Optional[int] = 0, + mode: int = 0, *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return the mode-`mode` unfolding of `tensor` with modes starting at `0`. + """Return the mode-`mode` unfolding of `tensor` with modes starting at `0`. Parameters ---------- @@ -2301,9 +2268,9 @@ def fold( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Refolds the mode-`mode` unfolding into a tensor of shape `shape` In other words, - refolds the n-mode unfolded tensor into the original tensor of the specified shape. + """Refolds the mode-`mode` unfolding into a tensor of shape `shape` In + other words, refolds the n-mode unfolded tensor into the original tensor of + the specified shape. Parameters ---------- @@ -2336,18 +2303,18 @@ def fold( def partial_unfold( x: Union[ivy.Array, ivy.NativeArray], /, - mode: Optional[int] = 0, - skip_begin: Optional[int] = 1, - skip_end: Optional[int] = 0, - ravel_tensors: Optional[bool] = False, + mode: int = 0, + skip_begin: int = 1, + skip_end: int = 0, + ravel_tensors: bool = False, *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Partial unfolding of a tensor while ignoring the specified number of dimensions at - the beginning and the end. For instance, if the first dimension of the tensor is the - number of samples, to unfold each sample, set skip_begin=1. This would, for each i - in ``range(tensor.shape[0])``, unfold ``tensor[i, ...]``. + """Partial unfolding of a tensor while ignoring the specified number of + dimensions at the beginning and the end. For instance, if the first + dimension of the tensor is the number of samples, to unfold each sample, + set skip_begin=1. This would, for each i in ``range(tensor.shape[0])``, + unfold ``tensor[i, ...]``. Parameters ---------- @@ -2396,12 +2363,11 @@ def partial_fold( /, mode: int, shape: Union[ivy.Shape, ivy.NativeShape, Sequence[int]], - skip_begin: Optional[int] = 1, + skip_begin: int = 1, *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Re-folds a partially unfolded tensor. + """Re-folds a partially unfolded tensor. Parameters ---------- @@ -2438,14 +2404,13 @@ def partial_fold( def partial_tensor_to_vec( x: Union[ivy.Array, ivy.NativeArray], /, - skip_begin: Optional[int] = 1, - skip_end: Optional[int] = 0, + skip_begin: int = 1, + skip_end: int = 0, *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Partial vectorization of a tensor while ignoring the specified dimension at the - beginning and the end. + """Partial vectorization of a tensor while ignoring the specified dimension + at the beginning and the end. Parameters ---------- @@ -2484,12 +2449,11 @@ def partial_vec_to_tensor( x: Union[ivy.Array, ivy.NativeArray], /, shape: Union[ivy.Shape, ivy.NativeShape, Sequence[int]], - skip_begin: Optional[int] = 1, + skip_begin: int = 1, *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Refolds a partially vectorised tensor into a full one. + """Refolds a partially vectorised tensor into a full one. Parameters ---------- @@ -2524,8 +2488,7 @@ def matricize( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Matricizes the given tensor. + """Matricizes the given tensor. Parameters ---------- @@ -2582,8 +2545,7 @@ def soft_thresholding( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Soft-thresholding operator. + """Soft-thresholding operator. sign(tensor) * max[abs(tensor) - threshold, 0] @@ -2643,8 +2605,7 @@ def choose( out: None = None, mode: Union[str, None] = None, ) -> ivy.Array: - """ - Take values from the input array by matching 1d index and data slices. + """Take values from the input array by matching 1d index and data slices. Parameters ---------- @@ -2666,17 +2627,17 @@ def choose( Examples -------- >>> choices = ivy.array([[0, 1, 2, 3], [10, 11, 12, 13], - [20, 21, 22, 23], [30, 31, 32, 33]]) - >>> print(choose(ivy.array([2, 3, 1, 0]), choices)) + ... [20, 21, 22, 23],[30, 31, 32, 33]]) + >>> print(ivy.choose(choices, ivy.array([2, 3, 1, 0])) ivy.array([20, 31, 12, 3]) >>> arr = ivy.array([2, 4, 1, 0]) - >>> print(choose(arr, choices, mode='clip')) # 4 goes to 3 (4-1) + >>> print(ivy.choose(choices, arr, mode='clip')) # 4 goes to 3 (4-1) ivy.array([20, 31, 12, 3]) >>> arr = ivy.array([2, 4, 1, 0]) - >>> print(choose(arr, choices, mode='wrap')) # 4 goes to (4 mod 4) + >>> print(ivy.choose(choices, arr, mode='wrap')) # 4 goes to (4 mod 4) ivy.array([20, 1, 12, 3]) """ - return ivy.current_backend(arr).choose(arr, choices, out=out, mode=mode) + return ivy.current_backend().choose(arr, choices, out=out, mode=mode) @handle_array_function @@ -2690,8 +2651,7 @@ def column_stack( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Create a new array by horizontally stacking the arrays in arrays. + """Create a new array by horizontally stacking the arrays in arrays. Equivalent to `ivy.hstack(arrays)`, except each zero or one dimensional array `x` in arrays is first reshaped into a `(x.size(), 1)` column @@ -2763,8 +2723,7 @@ def take( fill_value: Optional[Number] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return elements of an array along an axis. + """Return elements of an array along an axis. .. note:: Conceptually, take(x, indices, axis=3) is equivalent to x[:,:,:,indices,...]; @@ -2869,12 +2828,11 @@ def trim_zeros( a: Union[ivy.Array, ivy.NativeArray], /, *, - trim: Optional[str] = "fb", + trim: str = "fb", ) -> ivy.Array: - """ - ivy.Container instance method variant of ivy.trim_zeros. This method simply wraps - the function, and so the docstring for ivy.trim_zeros also applies to this method - with minimal changes. + """ivy.Container instance method variant of ivy.trim_zeros. This method + simply wraps the function, and so the docstring for ivy.trim_zeros also + applies to this method with minimal changes. Parameters ---------- @@ -2912,3 +2870,64 @@ def trim_zeros( ), "to_skip": ("inputs_to_ivy_arrays",), } + + +@handle_exceptions +@handle_backend_invalid +@handle_nestable +@handle_array_like_without_promotion +@handle_view +@handle_out_argument +@to_native_arrays_and_back +@handle_array_function +@handle_device +def unflatten( + x: Union[ivy.Array, ivy.NativeArray], + /, + dim: int, + shape: Tuple[int], + *, + out: Optional[ivy.Array] = None, +) -> ivy.Array: + """Expand a dimension of the input tensor over multiple dimensions. + + Parameters + ---------- + x + input tensor. + dim + dimension to be unflattened, specified as an index into input.shape. + shape + new shape of the unflattened dimension. One of its elements can be -1 in + which case the corresponding output dimension is inferred. Otherwise, + the product of sizes must equal input.shape[dim]. + out + optional output array, for writing the result to. It must have a shape that the + inputs broadcast to. + + Returns + ------- + ret + view of input with the specified dimension unflattened. + + + This function conforms to the `Array API Standard + `_. This docstring is an extension of the + `docstring `_ + in the standard. + + Both the description and the type hints above assumes an array input for simplicity, + but this function is *nestable*, and therefore also accepts :class:`ivy.Container` + instances in place of any of the arguments. + + Examples + -------- + >>> ivy.unflatten(torch.randn(3, 4, 1), dim=1, shape=(2, 2)).shape + torch.Size([3, 2, 2, 1]) + >>> ivy.unflatten(torch.randn(3, 4, 1), dim=1, shape=(-1, 2)).shape + torch.Size([3, 2, 2, 1]) + >>> ivy.unflatten(torch.randn(5, 12, 3), dim=-2, shape=(2, 2, 3, 1, 1)).shape + torch.Size([5, 2, 2, 3, 1, 1, 3]) + """ + return ivy.current_backend(x).unflatten(x, dim=dim, shape=shape, out=out) diff --git a/ivy/functional/ivy/experimental/norms.py b/ivy/functional/ivy/experimental/norms.py index ae7951baac434..5418c3fb50df8 100644 --- a/ivy/functional/ivy/experimental/norms.py +++ b/ivy/functional/ivy/experimental/norms.py @@ -1,4 +1,4 @@ -from typing import Union, Optional, Tuple +from typing import Literal, Union, Optional, Tuple # local import ivy @@ -102,6 +102,89 @@ def l2_normalize( return current_backend(x).l2_normalize(x, axis=axis, out=out) +@handle_exceptions +@handle_nestable +@handle_partial_mixed_function +@handle_array_like_without_promotion +@inputs_to_ivy_arrays +@handle_array_function +def local_response_norm( + x: Union[ivy.NativeArray, ivy.Array], + size, + /, + *, + bias: Optional[float] = 1.0, + alpha: Optional[float] = 1.0, + beta: Optional[float] = 0.5, + average: bool = False, + data_format: Optional[Literal["NHWC", "NCHW"]] = "NHWC", + out: Optional[Tuple[ivy.Array, ivy.Array, ivy.Array]] = None, +) -> ivy.Array: + """Apply local response normalization across the channels of a 4D input + array. The 4-D array is treated as a 3-D array of 1-D vectors (along the + channel dimension), and each vector is normalized independently. Within a + given vector, each component is divided by the squared sum of the + neighbouring components. + + Parameters + ---------- + x + Input array of default shape (N, H, W, C), where N is the batch dimension, + H and W correspond to the spatial dimensions and C corresponds to the + channel dimension. + size + The width of the normalization window. + alpha + The multiplicative factor. + beta + The exponent. + bias + An additive factor. + average + If True, each component is divided by the **averaged** squared sum. + data_format + The ordering of the dimensions in the input, either "NHWC" or "NCHW". + out + optional output arrays, for writing the result to. + + Returns + ------- + ret + The normalized array. + """ + if data_format == "NHWC": + x = ivy.permute_dims(x, axes=(0, 3, 1, 2)) + x_shape = x.shape + alpha = alpha * size if not average else alpha + ret = ivy.square(x) + ret = ivy.reshape(ret, (x_shape[0], 1, x_shape[1], x_shape[2], -1)) + ret = ivy.zero_pad( + ret, ((0, 0), (0, 0), (size // 2, (size - 1) // 2), (0, 0), (0, 0)) + ) + ret = ivy.avg_pool3d( + ret, (size, 1, 1), 1, "VALID", count_include_pad=True, data_format="NCDHW" + ) + ret = ivy.squeeze(ret, axis=1) + ret = ivy.reshape(ret, x_shape) + ret = ivy.pow(ivy.add(ivy.multiply(ret, alpha), bias), beta) + ret = ivy.divide(x, ret) + if data_format == "NHWC": + ret = ivy.permute_dims(ret, axes=(0, 2, 3, 1)) + return ret + + +local_response_norm.mixed_backend_wrappers = { + "to_add": ( + "handle_backend_invalid", + "handle_out_argument", + "inputs_to_native_arrays", + "outputs_to_ivy_arrays", + "handle_device", + ), + "to_skip": ("inputs_to_ivy_arrays", "handle_partial_mixed_function"), +} + + @handle_exceptions @handle_nestable @handle_partial_mixed_function @@ -183,8 +266,7 @@ def batch_norm( runningvariance = variance if training: - numel = int(ivy.prod(x.shape)) - n = numel if xdims == 1 else numel / x.shape[-1] + n = x.size if xdims == 1 else x.size / x.shape[-1] dims = (0, *range(1, xdims - 1)) mean = ivy.mean(x, axis=dims) variance = ivy.var(x, axis=dims) @@ -193,11 +275,10 @@ def batch_norm( n - 1 ) inv = 1.0 / ivy.sqrt(variance + eps) + offset = 0 if offset is None else offset if scale is not None: inv = inv * scale - xnormalized = x * inv.astype(x.dtype, copy=False) + ivy.astype( - offset - mean * inv if offset is not None else -mean * inv, x.dtype, copy=False - ) + xnormalized = x * inv + offset - mean * inv if data_format == "NCS": xnormalized = ivy.permute_dims( @@ -372,8 +453,8 @@ def group_norm( data_format: Optional[str] = "NSC", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Apply group normalization to the input array and returns the normalized input. + """Apply group normalization to the input array and returns the normalized + input. Parameters ---------- @@ -408,7 +489,7 @@ def group_norm( x = ivy.permute_dims(x, axes=(0, xdims - 1, *range(1, xdims - 1))) N = x.shape[0] C = x.shape[1] - S = ivy.to_scalar(ivy.prod(x.shape[2:])) if xdims > 2 else 1 + S = int(ivy.to_scalar(ivy.prod(x.shape[2:])) if xdims > 2 else 1) assert C % num_groups == 0 x_ = ivy.reshape(x, [N, num_groups, C // num_groups, S]) mean = ivy.mean(x_, axis=(2, 3), keepdims=True) diff --git a/ivy/functional/ivy/experimental/random.py b/ivy/functional/ivy/experimental/random.py index 5a653147a385a..c126aba5c20cf 100644 --- a/ivy/functional/ivy/experimental/random.py +++ b/ivy/functional/ivy/experimental/random.py @@ -29,11 +29,10 @@ def dirichlet( seed: Optional[int] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Draw size samples of dimension k from a Dirichlet distribution. A Dirichlet- - distributed random variable can be seen as a multivariate generalization of a Beta - distribution. The Dirichlet distribution is a conjugate prior of a multinomial - distribution in Bayesian inference. + """Draw size samples of dimension k from a Dirichlet distribution. A + Dirichlet- distributed random variable can be seen as a multivariate + generalization of a Beta distribution. The Dirichlet distribution is a + conjugate prior of a multinomial distribution in Bayesian inference. Parameters ---------- @@ -99,8 +98,8 @@ def beta( seed: Optional[int] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return an array filled with random values sampled from a beta distribution. + """Return an array filled with random values sampled from a beta + distribution. Parameters ---------- @@ -154,8 +153,8 @@ def gamma( seed: Optional[int] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return an array filled with random values sampled from a gamma distribution. + """Return an array filled with random values sampled from a gamma + distribution. Parameters ---------- @@ -205,8 +204,7 @@ def poisson( fill_value: Optional[Union[int, float]] = 0, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Draws samples from a poisson distribution. + """Draws samples from a poisson distribution. Parameters ---------- @@ -247,7 +245,7 @@ def poisson( ivy.array([[0., 2., 2.], [1., 2., 3.]]) """ - return ivy.current_backend().poisson( + return ivy.current_backend(lam).poisson( lam, shape=shape, device=device, @@ -276,9 +274,8 @@ def bernoulli( seed: Optional[int] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Draws samples from Bernoulli distribution parameterized by probs or logits (but not - both) + """Draws samples from Bernoulli distribution parameterized by probs or + logits (but not both) Parameters ---------- diff --git a/ivy/functional/ivy/experimental/searching.py b/ivy/functional/ivy/experimental/searching.py index 25c8928a55f9e..69c7045f95e42 100644 --- a/ivy/functional/ivy/experimental/searching.py +++ b/ivy/functional/ivy/experimental/searching.py @@ -23,8 +23,8 @@ def unravel_index( *, out: Optional[ivy.Array] = None, ) -> Tuple[ivy.Array]: - """ - Convert a flat index or array of flat indices into a tuple of coordinate arrays. + """Convert a flat index or array of flat indices into a tuple of coordinate + arrays. Parameters ---------- diff --git a/ivy/functional/ivy/experimental/sorting.py b/ivy/functional/ivy/experimental/sorting.py index 0d2d18ddf3c88..0d170828570eb 100644 --- a/ivy/functional/ivy/experimental/sorting.py +++ b/ivy/functional/ivy/experimental/sorting.py @@ -22,8 +22,7 @@ def invert_permutation( x: Union[ivy.Array, ivy.NativeArray, list, tuple], /, ) -> ivy.Array: - """ - Compute the inverse of an index permutation. + """Compute the inverse of an index permutation. Parameters ---------- @@ -62,11 +61,11 @@ def lexsort( axis: int = -1, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Perform an indirect stable sort with an array of keys in ascending order, with the - last key used as primary sort order, second-to-last for secondary, and so on. Each - row of the key must have the same length, which will also be the length of the - returned array of integer indices, which describes the sort order. + """Perform an indirect stable sort with an array of keys in ascending + order, with the last key used as primary sort order, second-to-last for + secondary, and so on. Each row of the key must have the same length, which + will also be the length of the returned array of integer indices, which + describes the sort order. Parameters ---------- diff --git a/ivy/functional/ivy/experimental/statistical.py b/ivy/functional/ivy/experimental/statistical.py index a7c6940e15a2d..bf69d12cd5cf2 100644 --- a/ivy/functional/ivy/experimental/statistical.py +++ b/ivy/functional/ivy/experimental/statistical.py @@ -38,8 +38,7 @@ def histogram( density: Optional[bool] = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the histogram of the array ``a``. + """Compute the histogram of the array ``a``. .. note:: Given bins = [c0, ..., cK], defining intervals I0 = [c0, c1), I1 = [c1, c2), @@ -165,8 +164,7 @@ def median( keepdims: bool = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the median along the specified axis. + """Compute the median along the specified axis. Parameters ---------- @@ -213,8 +211,7 @@ def nanmean( dtype: Optional[Union[ivy.Dtype, ivy.NativeDtype]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the mean of all non-NaN elements along the specified dimensions. + """Compute the mean of all non-NaN elements along the specified dimensions. Parameters ---------- @@ -269,8 +266,7 @@ def nanmin( initial: Optional[Union[int, float, complex]] = None, where: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return minimum of an array or minimum along an axis, ignoring any NaNs. + """Return minimum of an array or minimum along an axis, ignoring any NaNs. Parameters ---------- @@ -333,9 +329,8 @@ def nanprod( initial: Optional[Union[int, float, complex]] = None, where: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the product of array elements over a given axis treating Not a Numbers - (NaNs) as ones. + """Compute the product of array elements over a given axis treating Not a + Numbers (NaNs) as ones. Parameters ---------- @@ -399,8 +394,7 @@ def quantile( interpolation: str = "linear", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the q-th quantile of the data along the specified axis. + """Compute the q-th quantile of the data along the specified axis. Parameters ---------- @@ -484,7 +478,7 @@ def corrcoef( rowvar: bool = True, out: Optional[ivy.Array] = None, ) -> ivy.Array: - return ivy.current_backend().corrcoef(x, y=y, rowvar=rowvar, out=out) + return ivy.current_backend(x).corrcoef(x, y=y, rowvar=rowvar, out=out) @handle_exceptions @@ -502,10 +496,9 @@ def nanmedian( overwrite_input: bool = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - ivy.Array instance method variant of ivy.nanmedian. This method simply wraps the - function, and so the docstring for ivy.nanmedian also applies to this method with - minimal changes. + """ivy.Array instance method variant of ivy.nanmedian. This method simply + wraps the function, and so the docstring for ivy.nanmedian also applies to + this method with minimal changes. Parameters ---------- @@ -574,8 +567,7 @@ def bincount( minlength: int = 0, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Count the number of occurrences of each value in an integer array. + """Count the number of occurrences of each value in an integer array. Parameters ---------- @@ -617,8 +609,7 @@ def igamma( x: Optional[Union[ivy.Array, ivy.NativeArray]] = None, out: Optional[Union[ivy.Array, ivy.NativeArray]] = None, ) -> ivy.Array: - """ - Compute the regularized lower gamma function of ``a`` and ``x``. + """Compute the regularized lower gamma function of ``a`` and ``x``. Parameters ---------- @@ -662,8 +653,7 @@ def cov( aweights: Optional[ivy.Array] = None, dtype: Optional[Union[ivy.Dtype, ivy.NativeDtype]] = None, ) -> ivy.Array: - """ - Compute the covariance of matrix x1, or variables x1 and x2. + """Compute the covariance of matrix x1, or variables x1 and x2. Parameters ---------- @@ -806,9 +796,9 @@ def cummax( dtype: Optional[Union[ivy.Dtype, ivy.NativeDtype]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return a tuple containing the cumulative maximum of elements of input along the - given axis and index location of each maximum value found along the given axis. + """Return a tuple containing the cumulative maximum of elements of input + along the given axis and index location of each maximum value found along + the given axis. Parameters ---------- @@ -907,8 +897,7 @@ def cummin( dtype: Optional[Union[ivy.Dtype, ivy.NativeDtype]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return the cumulative minimum of the elements along a given axis. + """Return the cumulative minimum of the elements along a given axis. Parameters ---------- diff --git a/ivy/functional/ivy/experimental/utility.py b/ivy/functional/ivy/experimental/utility.py index e33383151b01c..f16428089885c 100644 --- a/ivy/functional/ivy/experimental/utility.py +++ b/ivy/functional/ivy/experimental/utility.py @@ -16,11 +16,10 @@ def optional_get_element( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - If the input is a tensor or sequence type, it returns the input. If the input is an - optional type, it outputs the element in the input. It is an error if the input is - an empty optional-type (i.e. does not have an element) and the behavior is undefined - in this case. + """If the input is a tensor or sequence type, it returns the input. If the + input is an optional type, it outputs the element in the input. It is an + error if the input is an empty optional-type (i.e. does not have an + element) and the behavior is undefined in this case. Parameters ---------- diff --git a/ivy/functional/ivy/general.py b/ivy/functional/ivy/general.py index c3c5b5ca7a996..7d2606defc47d 100644 --- a/ivy/functional/ivy/general.py +++ b/ivy/functional/ivy/general.py @@ -3,6 +3,7 @@ # global import gc import inspect +import itertools import math from functools import wraps from numbers import Number @@ -94,9 +95,9 @@ def __exit__(self, exc_type, exc_val, exc_tb): @handle_exceptions def set_precise_mode(mode: bool) -> None: - """ - Set the mode of whether to use a promotion table that avoids any precision loss or a - compute efficient table that avoids most wider-than- necessary promotions. + """Set the mode of whether to use a promotion table that avoids any + precision loss or a compute efficient table that avoids most wider-than- + necessary promotions. Parameter --------- @@ -122,9 +123,9 @@ def set_precise_mode(mode: bool) -> None: @handle_exceptions def unset_precise_mode() -> None: - """ - Reset the mode of whether to use a promotion table that avoids any precision loss or - a compute efficient table that avoids most wider-than- necessary promotions. + """Reset the mode of whether to use a promotion table that avoids any + precision loss or a compute efficient table that avoids most wider-than- + necessary promotions. Examples -------- @@ -183,12 +184,11 @@ def get_referrers_recursive( item: object, *, depth: int = 0, - max_depth: int = None, - seen_set: set = None, - local_set: set = None, + max_depth: Optional[int] = None, + seen_set: Optional[set] = None, + local_set: Optional[set] = None, ) -> ivy.Container: - """ - Recursively retrieve referrers for an object. + """Recursively retrieve referrers for an object. This function recursively fetches referrers for the specified `item` up to a given `max_depth`. @@ -215,18 +215,11 @@ def get_referrers_recursive( Examples -------- >>> import gc - >>> def example_function(): - ... obj = [1, 2, 3] - ... return get_referrers_recursive(obj, max_depth=2) + >>> example_function = lambda: (obj := [1, 2, 3]) and ivy.get_referrers_recursive(obj, max_depth=2) >>> result = example_function() >>> print(result) - Container( - 'ref_id_1': Container( - 'ref_id_2': 'tracked', - 'ref_id_3': 'tracked' - ) - ) - """ + {repr:[1,2,3]} + """ # noqa: E501 seen_set = ivy.default(seen_set, set()) local_set = ivy.default(local_set, set()) ret_cont = ivy.Container( @@ -254,7 +247,11 @@ def get_referrers_recursive( def get_referrers_recursive_inner(): return get_referrers_recursive( - ref, depth + 1, max_depth, seen_set, local_set + ref, + depth=depth + 1, + max_depth=max_depth, + seen_set=seen_set, + local_set=local_set, ) this_repr = "tracked" if seen else str(ref).replace(" ", "") @@ -281,8 +278,7 @@ def get_referrers_recursive_inner(): def is_native_array( x: Union[ivy.Array, ivy.NativeArray], /, *, exclusive: bool = False ) -> bool: - """ - Determine whether the input x is an :class:`ivy.NativeArray` instance. + """Determine whether the input x is an :class:`ivy.NativeArray` instance. Parameters ---------- @@ -318,8 +314,7 @@ def is_native_array( def is_ivy_array( x: Union[ivy.Array, ivy.NativeArray], /, *, exclusive: Optional[bool] = False ) -> bool: - """ - Determine whether the input x is a valid Ivy Array. + """Determine whether the input x is a valid Ivy Array. Parameters ---------- @@ -350,8 +345,7 @@ def is_ivy_array( @handle_exceptions @handle_backend_invalid def is_array(x: Any, /, *, exclusive: bool = False) -> bool: - """ - Determine whether the input x is either an Ivy Array or a Native Array. + """Determine whether the input x is either an Ivy Array or a Native Array. Parameters ---------- @@ -387,8 +381,7 @@ def is_array(x: Any, /, *, exclusive: bool = False) -> bool: @handle_exceptions def is_ivy_container(x: Any, /) -> bool: - """ - Determine whether the input x is an Ivy Container. + """Determine whether the input x is an Ivy Container. Parameters ---------- @@ -418,9 +411,8 @@ def is_ivy_container(x: Any, /) -> bool: @handle_exceptions def set_array_mode(mode: bool) -> None: - """ - Set the mode of whether to convert inputs to ivy.NativeArray, then convert outputs - back to ivy.Array. + """Set the mode of whether to convert inputs to ivy.NativeArray, then + convert outputs back to ivy.Array. It Stops the conversion of ivy.NativeArray to ivy.Array in the case when it is set to False. @@ -448,9 +440,8 @@ def set_array_mode(mode: bool) -> None: @handle_exceptions def unset_array_mode() -> None: - """ - Reset the mode of converting inputs to ivy.NativeArray, then converting outputs back - to ivy.Array to the previous state. + """Reset the mode of converting inputs to ivy.NativeArray, then converting + outputs back to ivy.Array to the previous state. Examples -------- @@ -474,8 +465,7 @@ def unset_array_mode() -> None: @handle_exceptions def set_nestable_mode(mode: bool) -> None: - """ - Set the mode of whether to check if function inputs are ivy.Container. + """Set the mode of whether to check if function inputs are ivy.Container. Parameter --------- @@ -500,9 +490,8 @@ def set_nestable_mode(mode: bool) -> None: @handle_exceptions def unset_nestable_mode() -> None: - """ - Reset the mode of whether to check if function inputs are ivy.Container to the - previous state. + """Reset the mode of whether to check if function inputs are ivy.Container + to the previous state. Examples -------- @@ -528,9 +517,9 @@ def unset_nestable_mode() -> None: @handle_exceptions def set_exception_trace_mode(mode: Literal["ivy", "full", "frontend"]) -> None: - """ - Set the mode of whether to show frontend-truncated exception stack traces, ivy- - truncated exception stack traces or full exception stack traces. + """Set the mode of whether to show frontend-truncated exception stack + traces, ivy- truncated exception stack traces or full exception stack + traces. Parameter --------- @@ -558,8 +547,7 @@ def set_exception_trace_mode(mode: Literal["ivy", "full", "frontend"]) -> None: @handle_exceptions def unset_exception_trace_mode() -> None: - """ - Reset the trace mode to the previously set mode. + """Reset the trace mode to the previously set mode. Examples -------- @@ -587,8 +575,8 @@ def unset_exception_trace_mode() -> None: @handle_exceptions def set_show_func_wrapper_trace_mode(mode: bool) -> None: - """ - Set the mode of whether to show the full stack trace with function wrapping traces. + """Set the mode of whether to show the full stack trace with function + wrapping traces. Parameter --------- @@ -613,9 +601,8 @@ def set_show_func_wrapper_trace_mode(mode: bool) -> None: @handle_exceptions def unset_show_func_wrapper_trace_mode() -> None: - """ - Reset the mode of whether to show the full stack trace with function wrapping - traces. + """Reset the mode of whether to show the full stack trace with function + wrapping traces. Examples -------- @@ -650,8 +637,7 @@ def array_equal( x1: Union[ivy.Array, ivy.NativeArray], /, ) -> bool: - """ - Determine whether two input arrays are equal across all elements. + """Determine whether two input arrays are equal across all elements. Parameters ---------- @@ -695,8 +681,7 @@ def array_equal( def all_equal( *xs: Iterable[Any], equality_matrix: bool = False ) -> Union[bool, ivy.Array, ivy.NativeArray]: - """ - Determine whether the inputs are all equal. + """Determine whether the inputs are all equal. Parameters ---------- @@ -789,8 +774,7 @@ def all_equal( def to_numpy( x: Union[ivy.Array, ivy.NativeArray], /, *, copy: bool = True ) -> np.ndarray: - """ - Convert an array into a numpy array. + """Convert an array into a numpy array. Parameters ---------- @@ -860,8 +844,7 @@ def isscalar(x: Any, /) -> bool: @handle_array_function @handle_device def to_scalar(x: Union[ivy.Array, ivy.NativeArray], /) -> Number: - """ - Convert an array with a single element into a scalar. + """Convert an array with a single element into a scalar. Parameters ---------- @@ -917,8 +900,7 @@ def to_scalar(x: Union[ivy.Array, ivy.NativeArray], /) -> Number: @handle_array_function @handle_device def to_list(x: Union[ivy.Array, ivy.NativeArray], /) -> List: - """ - Create a (possibly nested) list from input array. + """Create a (possibly nested) list from input array. Parameters ---------- @@ -995,8 +977,7 @@ def clip_vector_norm( p: float = 2.0, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Clips (limits) the vector p-norm of an array. + """Clips (limits) the vector p-norm of an array. Parameters ---------- @@ -1069,7 +1050,7 @@ def clip_vector_norm( >>> print(y) { a: ivy.array([0., 0.894, 1.79]), - b: ivy.array([2.449, 2.65, 2.83]) + b: ivy.array([1.27279221, 1.69705628, 2.12132034]) } """ norm = ivy.vector_norm(x, keepdims=True, ord=p) @@ -1095,8 +1076,7 @@ def clip_matrix_norm( p: float = 2.0, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Clips (limits) the matrix norm of an array. + """Clips (limits) the matrix norm of an array. Parameters ---------- @@ -1179,8 +1159,7 @@ def fourier_encode( concat: bool = True, flatten: bool = False, ) -> Union[ivy.Array, ivy.NativeArray, Tuple]: - """ - Pad an array with fourier encodings. + """Pad an array with fourier encodings. Parameters ---------- @@ -1280,8 +1259,7 @@ def value_is_nan( *, include_infs: bool = True, ) -> bool: - """ - Determine whether the single valued array or scalar is of nan type. + """Determine whether the single valued array or scalar is of nan type. Parameters ---------- @@ -1326,7 +1304,7 @@ def value_is_nan( x_scalar = ivy.to_scalar(x) if ivy.is_array(x) else x if x_scalar != x: return True - if include_infs and (x_scalar == INF or x_scalar == -INF): + if include_infs and (x_scalar in [INF, -INF]): return True return False @@ -1339,9 +1317,8 @@ def value_is_nan( def has_nans( x: Union[ivy.Array, ivy.NativeArray], /, *, include_infs: bool = True ) -> bool: - """ - Determine whether the array contains any nans, as well as infs or -infs if - specified. + """Determine whether the array contains any nans, as well as infs or -infs + if specified. Parameters ---------- @@ -1400,8 +1377,7 @@ def has_nans( @handle_exceptions def exists(x: Any, /) -> bool: - """ - Check as to whether the input is None or not. + """Check as to whether the input is None or not. Parameters ---------- @@ -1482,8 +1458,7 @@ def default( rev: bool = False, with_callable: bool = False, ) -> Any: - """ - Return x provided it exists (is not None), else returns default value. + """Return x provided it exists (is not None), else returns default value. Parameters ---------- @@ -1574,8 +1549,7 @@ def default( @handle_exceptions def to_ivy_shape(shape: Union[ivy.Shape, ivy.NativeShape]) -> ivy.Shape: - """ - Return the input shape in ivy.Shape form. + """Return the input shape in ivy.Shape form. Parameters ---------- @@ -1594,10 +1568,9 @@ def to_ivy_shape(shape: Union[ivy.Shape, ivy.NativeShape]) -> ivy.Shape: @handle_exceptions def to_native_shape( - shape: Union[ivy.Array, ivy.Shape, ivy.NativeShape, tuple, int, list] + shape: Union[ivy.Array, ivy.Shape, ivy.NativeShape, tuple, int, list], ) -> ivy.NativeShape: - """ - Return the input shape in its native backend framework form. + """Return the input shape in its native backend framework form. Parameters ---------- @@ -1639,9 +1612,8 @@ def to_native_shape( @handle_exceptions @handle_nestable def try_else_none(fn: Callable, *args: Any, **kwargs: Any) -> Union[Callable, None]: - """ - Try and return the function, otherwise return None if an exception was raised during - function execution. + """Try and return the function, otherwise return None if an exception was + raised during function execution. Parameters ---------- @@ -1684,8 +1656,7 @@ def try_else_none(fn: Callable, *args: Any, **kwargs: Any) -> Union[Callable, No @handle_exceptions def arg_names(receiver): - """ - Get the expected keyword arguments for a function or class constructor. + """Get the expected keyword arguments for a function or class constructor. Parameters ---------- @@ -1715,8 +1686,7 @@ def arg_names(receiver): def match_kwargs( kwargs: Dict, *receivers: Iterable[Callable], allow_duplicates: bool = False ) -> Union[List[Dict], Dict]: - """ - Match keyword arguments to either class or function receivers. + """Match keyword arguments to either class or function receivers. Parameters ---------- @@ -1762,8 +1732,7 @@ def match_kwargs( @handle_exceptions def cache_fn(func: Callable) -> Callable: - """ - Cache function outputs. + """Cache function outputs. A decorator to wrap a function, such that computed outputs are cached to avoid recalculating them later. @@ -1816,8 +1785,7 @@ def cached_fn(*args, **kwargs): @handle_exceptions def current_backend_str() -> Union[str, None]: - """ - Return framework string. + """Return framework string. Returns ------- @@ -1843,8 +1811,7 @@ def einops_rearrange( out: Optional[ivy.Array] = None, **axes_lengths: Dict[str, int], ) -> ivy.Array: - """ - Perform einops rearrange operation on input array x. + """Perform einops rearrange operation on input array x. Parameters ---------- @@ -1979,8 +1946,7 @@ def einops_reduce( out: Optional[ivy.Array] = None, **axes_lengths: Dict[str, int], ) -> ivy.Array: - """ - Perform einops reduce operation on input array x. + """Perform einops reduce operation on input array x. Parameters ---------- @@ -2056,8 +2022,7 @@ def einops_repeat( out: Optional[ivy.Array] = None, **axes_lengths: Dict[str, int], ) -> ivy.Array: - """ - Perform einops repeat operation on input array x. + """Perform einops repeat operation on input array x. Parameters ---------- @@ -2117,8 +2082,8 @@ def einops_repeat( @handle_exceptions @handle_array_function def set_min_denominator(val: float) -> None: - """ - Set the global minimum denominator used by ivy for numerically stable division. + """Set the global minimum denominator used by ivy for numerically stable + division. Parameters ---------- @@ -2144,9 +2109,8 @@ def set_min_denominator(val: float) -> None: @handle_exceptions def unset_min_denominator() -> None: - """ - Reset the global minimum denominator used by ivy for numerically stable division to - the previous value. + """Reset the global minimum denominator used by ivy for numerically stable + division to the previous value. Examples -------- @@ -2172,8 +2136,8 @@ def unset_min_denominator() -> None: @handle_exceptions @handle_array_function def set_min_base(val: float) -> None: - """ - Set the global minimum base used by ivy for numerically stable power raising. + """Set the global minimum base used by ivy for numerically stable power + raising. Parameters ---------- @@ -2187,13 +2151,16 @@ def set_min_base(val: float) -> None: >>> print(x) 1e-05 - Set the minimum base to 1e-04: + >>> # Set the minimum base to 1e-04: >>> ivy.set_min_base(1e-04) Retrieve the minimum base: >>> y = ivy.min_base >>> print(y) 1e-04 + + >>> # unset the min_base + >>> ivy.unset_min_base() """ global min_base_stack @@ -2209,9 +2176,8 @@ def set_min_base(val: float) -> None: @handle_exceptions def unset_min_base() -> None: - """ - Reset the global minimum base used by ivy for numerically stable power raising to - the previous value. + """Reset the global minimum base used by ivy for numerically stable power + raising to the previous value. Examples -------- @@ -2243,9 +2209,8 @@ def stable_divide( *, min_denominator: Union[Number, ivy.Array, ivy.NativeArray] = None, ) -> Union[Number, ivy.Array]: - """ - Divide the numerator by the denominator, with min denominator added to the - denominator for numerical stability. + """Divide the numerator by the denominator, with min denominator added to + the denominator for numerical stability. Parameters ---------- @@ -2341,11 +2306,10 @@ def stable_pow( exponent: Union[Number, ivy.Array, ivy.NativeArray], /, *, - min_base: float = None, + min_base: Optional[float] = None, ) -> Any: - """ - Raise the base by the power, with ivy.min_base added to the base when exponent > 1 - for numerical stability. + """Raise the base by the power, with ivy.min_base added to the base when + exponent > 1 for numerical stability. Parameters ---------- @@ -2433,8 +2397,7 @@ def stable_pow( @handle_exceptions def get_all_arrays_in_memory() -> List[Union[ivy.Array, ivy.NativeArray]]: - """ - Get all arrays which are currently alive. + """Get all arrays which are currently alive. Returns ------- @@ -2469,8 +2432,7 @@ def get_all_arrays_in_memory() -> List[Union[ivy.Array, ivy.NativeArray]]: @handle_exceptions def num_arrays_in_memory() -> int: - """ - Return the number of arrays which are currently alive. + """Return the number of arrays which are currently alive. Returns ------- @@ -2493,8 +2455,7 @@ def num_arrays_in_memory() -> int: @handle_exceptions def print_all_arrays_in_memory(): - """ - Print all native Ivy arrays in memory to the console. + """Print all native Ivy arrays in memory to the console. Gets all the native Ivy arrays which are currently alive(in the garbage collector) from get_all_arrays_in_memory() function and @@ -2510,8 +2471,7 @@ def print_all_arrays_in_memory(): @handle_exceptions @handle_array_function def set_queue_timeout(timeout: float): - """ - Set a timeout value (in seconds) for the global queue. + """Set a timeout value (in seconds) for the global queue. Set the global queue timeout value (in seconds) Default value without this function being called is 15 seconds. @@ -2542,8 +2502,7 @@ def set_queue_timeout(timeout: float): @handle_exceptions def unset_queue_timeout() -> None: - """ - Reset the global queue timeout value (in seconds) to the previous state. + """Reset the global queue timeout value (in seconds) to the previous state. Examples -------- @@ -2568,8 +2527,7 @@ def unset_queue_timeout() -> None: @handle_exceptions def set_tmp_dir(tmp_dr: str) -> None: - """ - Set the directory for saving temporary files. + """Set the directory for saving temporary files. Parameters ---------- @@ -2586,6 +2544,9 @@ def set_tmp_dir(tmp_dr: str) -> None: >>> y = ivy.tmp_dir >>> print(y) /my_tmp + + >>> # Unset the tmp_dr + >>> ivy.unset_tmp_dir() """ global tmp_dir_stack ivy.utils.assertions.check_isinstance(tmp_dr, str) @@ -2595,8 +2556,7 @@ def set_tmp_dir(tmp_dr: str) -> None: @handle_exceptions def unset_tmp_dir() -> None: - """ - Reset the directory for saving temporary files to the previous value. + """Reset the directory for saving temporary files to the previous value. Examples -------- @@ -2618,8 +2578,7 @@ def unset_tmp_dir() -> None: @handle_exceptions def container_types(): - """ - Summary. + """Summary. Returns ------- @@ -2636,8 +2595,8 @@ def container_types(): @handle_exceptions def inplace_arrays_supported() -> bool: - """ - Determine whether inplace arrays are supported for the current backend framework. + """Determine whether inplace arrays are supported for the current backend + framework. Returns ------- @@ -2649,8 +2608,8 @@ def inplace_arrays_supported() -> bool: @handle_exceptions def inplace_variables_supported() -> bool: - """ - Determine whether inplace variables are supported for the current backend framework. + """Determine whether inplace variables are supported for the current + backend framework. Returns ------- @@ -2665,8 +2624,7 @@ def inplace_variables_supported() -> bool: @inputs_to_native_arrays @handle_array_function def supports_inplace_updates(x: Union[ivy.Array, ivy.NativeArray], /) -> bool: - """ - Return if in-place operations are supported for x's data type. + """Return if in-place operations are supported for x's data type. Determine whether in-place operations are supported for x's data type, by the current backend framework setting. @@ -2732,8 +2690,7 @@ def supports_inplace_updates(x: Union[ivy.Array, ivy.NativeArray], /) -> bool: @inputs_to_native_arrays @handle_array_function def assert_supports_inplace(x: Union[ivy.Array, ivy.NativeArray], /) -> bool: - """ - Assert that inplace operations are supported for x. + """Assert that inplace operations are supported for x. Parameters ---------- @@ -2805,8 +2762,7 @@ def get_item( *, copy: Optional[bool] = None, ) -> ivy.Array: - """ - Gather slices from x according to query array, identical to x[query]. + """Gather slices from x according to query array, identical to x[query]. Parameters ---------- @@ -2841,15 +2797,21 @@ def get_item( if query.ndim == 0: if query is False: return ivy.zeros(shape=(0,) + x.shape, dtype=x.dtype) - return x[None] # eqivalent to ivy.expand_dims(x, axis=0) + return x[None] # equivalent to ivy.expand_dims(x, axis=0) query = ivy.nonzero(query, as_tuple=False) ret = ivy.gather_nd(x, query) else: - indices, target_shape = _parse_query(query, x.shape) - if indices is None: - return ivy.empty(target_shape, dtype=x.dtype) - ret = ivy.gather_nd(x, indices) - ret = ivy.reshape(ret, target_shape) + query, target_shape, vector_inds = _parse_query(query, x.shape) + if vector_inds is not None: + x = ivy.permute_dims( + x, + axes=[ + *vector_inds, + *[i for i in range(len(x.shape)) if i not in vector_inds], + ], + ) + ret = ivy.gather_nd(x, query) + ret = ivy.reshape(ret, target_shape) if target_shape != list(ret.shape) else ret return ret @@ -2875,8 +2837,8 @@ def set_item( *, copy: Optional[bool] = False, ) -> ivy.Array: - """ - Replace slices of x (defined by query) with val, identical to x[query] = val. + """Replace slices of x (defined by query) with val, identical to x[query] = + val. Parameters ---------- @@ -2903,10 +2865,10 @@ def set_item( >>> val = ivy.array([10, 10]) >>> ivy.set_item(x, query, val) >>> print(x) - ivy.array([10, 10, 20]) + >>> x = ivy.array([[0, -1, 20], [5, 2, -8]]) - >>> query = ([1, 1]) + >>> query = ivy.array([1, 1]) >>> val = ivy.array([10, 10]) >>> y = ivy.set_item(x, query, val, copy=True) >>> print(y) @@ -2925,7 +2887,7 @@ def set_item( target_shape = ivy.get_item(x, query).shape indices = ivy.nonzero(query, as_tuple=False) else: - indices, target_shape = _parse_query(query, x.shape) + indices, target_shape, _ = _parse_query(query, x.shape, scatter=True) if indices is None: return x val = _broadcast_to(val, target_shape).astype(x.dtype) @@ -2943,27 +2905,247 @@ def set_item( } -def _parse_query(query, x_shape): - query = query if isinstance(query, tuple) else (query,) - query_ = tuple(q.to_numpy() if ivy.is_array(q) else q for q in query) +def _parse_query(query, x_shape, scatter=False): + query = (query,) if not isinstance(query, tuple) else query + + # sequence and integer queries are dealt with as array queries + query = [ivy.array(q) if isinstance(q, (tuple, list, int)) else q for q in query] + + # check if non-slice queries are in consecutive positions + # if so, they have to be moved to the front + # https://numpy.org/neps/nep-0021-advanced-indexing.html#mixed-indexing + non_slice_q_idxs = [i for i, q in enumerate(query) if ivy.is_array(q)] + to_front = ( + len(non_slice_q_idxs) > 1 + and any(ivy.diff(non_slice_q_idxs) != 1) + and non_slice_q_idxs[-1] < len(x_shape) + ) + + # extract newaxis queries + new_axes = [i for i, q in enumerate(query) if q is None] + query = [q for q in query if q is not None] + query = [Ellipsis] if query == [] else query + + # parse ellipsis + ellipsis_inds = None + if any(q is Ellipsis for q in query): + query, ellipsis_inds = _parse_ellipsis(query, len(x_shape)) + + # broadcast array queries + array_inds = [i for i, v in enumerate(query) if ivy.is_array(v)] + if array_inds: + array_queries = ivy.broadcast_arrays( + *[v for i, v in enumerate(query) if i in array_inds] + ) + array_queries = [ + ivy.nonzero(q, as_tuple=False)[0] if ivy.is_bool_dtype(q) else q + for q in array_queries + ] + array_queries = [ + ( + ivy.where(arr < 0, arr + x_shape[i], arr).astype(ivy.int64) + if arr.size + else arr.astype(ivy.int64) + ) + for arr, i in zip(array_queries, array_inds) + ] + for idx, arr in zip(array_inds, array_queries): + query[idx] = arr + + # convert slices to range arrays + query = [ + _parse_slice(q, x_shape[i]).astype(ivy.int64) if isinstance(q, slice) else q + for i, q in enumerate(query) + ] + + # fill in missing queries + if len(query) < len(x_shape): + query += [ivy.arange(0, s, 1).astype(ivy.int64) for s in x_shape[len(query) :]] + + # calculate target_shape, i.e. the shape the gathered/scattered values should have + if len(array_inds) and to_front: + target_shape = ( + [list(array_queries[0].shape)] + + [list(query[i].shape) for i in range(len(query)) if i not in array_inds] + + [[] for _ in range(len(array_inds) - 1)] + ) + elif len(array_inds): + target_shape = ( + [list(query[i].shape) for i in range(0, array_inds[0])] + + [list(array_queries[0].shape)] + + [[] for _ in range(len(array_inds) - 1)] + + [list(query[i].shape) for i in range(array_inds[-1] + 1, len(query))] + ) + else: + target_shape = [list(q.shape) for q in query] + if ellipsis_inds is not None: + target_shape = ( + target_shape[: ellipsis_inds[0]] + + [target_shape[ellipsis_inds[0] : ellipsis_inds[1]]] + + target_shape[ellipsis_inds[1] :] + ) + for i, ax in enumerate(new_axes): + if len(array_inds) and to_front: + ax -= sum(1 for x in array_inds if x < ax) - 1 + ax = ax + i + target_shape = [*target_shape[:ax], 1, *target_shape[ax:]] + target_shape = _deep_flatten(target_shape) + + # calculate the indices mesh (indices in gather_nd/scatter_nd format) + query = [ivy.expand_dims(q) if not len(q.shape) else q for q in query] + if len(array_inds): + array_queries = [ + ( + arr.reshape((-1,)) + if len(arr.shape) > 1 + else ivy.expand_dims(arr) if not len(arr.shape) else arr + ) + for arr in array_queries + ] + array_queries = ivy.stack(array_queries, axis=1) + if len(array_inds) == len(query): # advanced indexing + indices = array_queries.reshape((*target_shape, len(x_shape))) + elif len(array_inds) == 0: # basic indexing + indices = ivy.stack(ivy.meshgrid(*query, indexing="ij"), axis=-1).reshape( + (*target_shape, len(x_shape)) + ) + else: # mixed indexing + if to_front: + post_array_queries = ( + ivy.stack( + ivy.meshgrid( + *[v for i, v in enumerate(query) if i not in array_inds], + indexing="ij", + ), + axis=-1, + ).reshape((-1, len(query) - len(array_inds))) + if len(array_inds) < len(query) + else ivy.empty((1, 0)) + ) + indices = ivy.array( + [ + (*arr, *post) + for arr, post in itertools.product( + array_queries, post_array_queries + ) + ] + ).reshape((*target_shape, len(x_shape))) + else: + pre_array_queries = ( + ivy.stack( + ivy.meshgrid( + *[v for i, v in enumerate(query) if i < array_inds[0]], + indexing="ij", + ), + axis=-1, + ).reshape((-1, array_inds[0])) + if array_inds[0] > 0 + else ivy.empty((1, 0)) + ) + post_array_queries = ( + ivy.stack( + ivy.meshgrid( + *[v for i, v in enumerate(query) if i > array_inds[-1]], + indexing="ij", + ), + axis=-1, + ).reshape((-1, len(query) - 1 - array_inds[-1])) + if array_inds[-1] < len(query) - 1 + else ivy.empty((1, 0)) + ) + indices = ivy.array( + [ + (*pre, *arr, *post) + for pre, arr, post in itertools.product( + pre_array_queries, array_queries, post_array_queries + ) + ] + ).reshape((*target_shape, len(x_shape))) + + return ( + indices.astype(ivy.int64), + target_shape, + array_inds if len(array_inds) and to_front else None, + ) - # array containing all of x's flat indices - x_ = ivy.arange(0, _numel(x_shape)).reshape(x_shape) - # use numpy's __getitem__ to get the queried indices - x_idxs = ivy.array(x_.to_numpy()[query_]) - target_shape = x_idxs.shape +def _parse_ellipsis(so, ndims): + pre = list() + for s in so: + if s is Ellipsis: + break + pre.append(s) + post = list() + for s in reversed(so): + if s is Ellipsis: + break + post.append(s) + ret = list( + pre + + [slice(None, None, None) for _ in range(ndims - len(pre) - len(post))] + + list(reversed(post)) + ) + return ret, (len(pre), ndims - len(post)) + - if 0 in x_idxs.shape or 0 in x_shape: - return None, target_shape +def _parse_slice(idx, s): + step = 1 if idx.step is None else idx.step + if step > 0: + start = 0 if idx.start is None else idx.start + if start >= s: + stop = start + else: + if start <= -s: + start = 0 + elif start < 0: + start = start + s + stop = s if idx.stop is None else idx.stop + if stop > s: + stop = s + elif start <= -s: + stop = 0 + elif stop < 0: + stop = stop + s + else: + start = s - 1 if idx.start is None else idx.start + if start < -s: + stop = start + else: + if start >= s: + start = s - 1 + elif start < 0: + start = start + s + if idx.stop is None: + stop = -1 + else: + stop = idx.stop + if stop > s: + stop = s + elif stop < -s: + stop = -1 + elif stop == -s: + stop = 0 + elif stop < 0: + stop = stop + s + q_i = ivy.arange(start, stop, step) + q_i = [q for q in q_i if 0 <= q < s] + q_i = ( + ivy.array(q_i) + if len(q_i) or start == stop or idx.stop is not None + else ivy.arange(0, s, 1) + ) + return q_i - # convert the flat indices to multi-D indices - x_idxs = ivy.unravel_index(x_idxs, x_shape) - # stack the multi-D indices to bring them to gather_nd/scatter_nd format - x_idxs = ivy.stack(x_idxs, axis=-1).astype(ivy.int64) +def _deep_flatten(iterable): + def _flatten_gen(iterable): + for item in iterable: + if isinstance(item, list): + yield from _flatten_gen(item) + else: + yield item - return x_idxs, target_shape + return list(_flatten_gen(iterable)) def _numel(shape): @@ -2976,16 +3158,6 @@ def _broadcast_to(input, target_shape): return ivy.reshape(input, target_shape) else: input = input if len(input.shape) else ivy.expand_dims(input, axis=0) - new_dims = () - i_i = len(input.shape) - 1 - for i_t in range(len(target_shape) - 1, -1, -1): - if len(input.shape) + len(new_dims) >= len(target_shape): - break - if i_i < 0 or target_shape[i_t] != input.shape[i_i]: - new_dims += (i_t,) - else: - i_i -= 1 - input = ivy.expand_dims(input, axis=new_dims) return ivy.broadcast_to(input, target_shape) @@ -3003,8 +3175,7 @@ def inplace_update( ensure_in_backend: bool = False, keep_input_dtype: bool = False, ) -> ivy.Array: - """ - Perform in-place update for the input array. + """Perform in-place update for the input array. This will always be performed on ivy.Array instances pass in the input, and will also be performed on the native array classes in the backend when the backend @@ -3100,8 +3271,7 @@ def inplace_update( @handle_exceptions def set_inplace_mode(mode: str = "lenient") -> None: - """ - Set the memory management behavior for in-place updates in Ivy. + """Set the memory management behavior for in-place updates in Ivy. By default, Ivy creates new arrays in the backend for in-place updates. However, this behavior can be controlled by the user @@ -3148,9 +3318,8 @@ def set_inplace_mode(mode: str = "lenient") -> None: @handle_exceptions def unset_inplace_mode() -> None: - """ - Reset the memory management behavior for in-place updates in Ivy to the previous - state. + """Reset the memory management behavior for in-place updates in Ivy to the + previous state. Examples -------- @@ -3179,8 +3348,7 @@ def inplace_decrement( x: Union[ivy.Array, ivy.NativeArray], val: Union[ivy.Array, ivy.NativeArray], ) -> ivy.Array: - """ - Perform in-place decrement for the input array. + """Perform in-place decrement for the input array. Parameters ---------- @@ -3251,8 +3419,7 @@ def inplace_increment( x: Union[ivy.Array, ivy.NativeArray], val: Union[ivy.Array, ivy.NativeArray], ) -> ivy.Array: - """ - Perform in-place increment for the input array. + """Perform in-place increment for the input array. Parameters ---------- @@ -3316,8 +3483,7 @@ def scatter_flat( reduction: str = "sum", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Scatter flat updates into a new flat array according to flat indices. + """Scatter flat updates into a new flat array according to flat indices. Parameters ---------- @@ -3406,8 +3572,7 @@ def scatter_nd( reduction: str = "sum", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Scatter updates into a new array according to indices. + """Scatter updates into a new array according to indices. Parameters ---------- @@ -3513,8 +3678,7 @@ def gather( batch_dims: int = 0, out: Optional[Union[ivy.Array, ivy.NativeArray]] = None, ) -> Union[ivy.Array, ivy.NativeArray]: - """ - Gather slices from params at axis according to indices. + """Gather slices from params at axis according to indices. Parameters ---------- @@ -3524,12 +3688,13 @@ def gather( The array which indicates the indices that will be gathered along the specified axis. axis - optional int, the axis from which to gather from. + Optional int, the axis from which to gather from. Default is ``-1``. batch_dims - optional int, lets you gather different items from each element of a batch. + Optional int, lets you gather different items from each element of a batch. + Default is ``0``. out - optional array, for writing the result to. It must have a shape + Optional array, for writing the result to. It must have a shape that the inputs broadcast to. Returns @@ -3623,8 +3788,7 @@ def gather_nd( batch_dims: int = 0, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Gather slices from params into a array with shape specified by indices. + """Gather slices from params into a array with shape specified by indices. Parameters ---------- @@ -3691,8 +3855,7 @@ def gather_nd( @handle_nestable @handle_array_function def multiprocessing(context: Optional[str] = None): - """ - Return backend-specific multiprocessing module. + """Return backend-specific multiprocessing module. Parameters ---------- @@ -3751,8 +3914,7 @@ def shape( *, as_array: bool = False, ) -> Union[ivy.Shape, ivy.NativeShape]: - """ - Return the shape of the array ``x``. + """Return the shape of the array ``x``. Parameters ---------- @@ -3786,8 +3948,7 @@ def shape( @handle_exceptions def set_shape_array_mode(mode: bool) -> None: - """ - Set the mode of returning shape as ivy.Array to the given mode instance. + """Set the mode of returning shape as ivy.Array to the given mode instance. Parameter --------- @@ -3812,8 +3973,7 @@ def set_shape_array_mode(mode: bool) -> None: @handle_exceptions def unset_shape_array_mode() -> None: - """ - Reset the mode of returning shape as ivy.Array to the previous state. + """Reset the mode of returning shape as ivy.Array to the previous state. Examples -------- @@ -3841,8 +4001,7 @@ def unset_shape_array_mode() -> None: def get_num_dims( x: Union[ivy.Array, ivy.NativeArray], /, *, as_array: bool = False ) -> int: - """ - Return the number of dimensions of the array x. + """Return the number of dimensions of the array x. Parameters ---------- @@ -3888,11 +4047,55 @@ def get_num_dims( return current_backend(x).get_num_dims(x, as_array=as_array) +@handle_backend_invalid +@handle_nestable +@handle_array_like_without_promotion +@to_native_arrays_and_back +@handle_array_function +@handle_device +def size(x: Union[ivy.Array, ivy.NativeArray]) -> int: + """Return the number of elements of the array x. + + Parameters + ---------- + x + Input array to infer the number of elements for. + + Returns + ------- + ret + Number of elements of the array + + Both the description and the type hints above assumes an array input for simplicity, + but this function is *nestable*, and therefore also accepts :class:`ivy.Container` + instances in place of any of the arguments. + + Examples + -------- + With :class:`ivy.Array` input: + + >>> a = ivy.array([[[0, 0, 0], [0, 0, 0], [0, 0, 0]], + ... [[0, 0, 0], [0, 0, 0], [0, 0, 0]], + ... [[0, 0, 0], [0, 0, 0], [0, 0, 0]]]) + >>> b = ivy.size(a) + >>> print(b) + 27 + + With :class:`ivy.Container` input: + + >>> a = ivy.Container(b = ivy.asarray([[0.,1.,1.],[1.,0.,0.],[8.,2.,3.]])) + >>> print(ivy.size(a)) + { + b: 9 + } + """ + return current_backend(x).size(x) + + @handle_exceptions def arg_info(fn: Callable, *, name: Optional[str] = None, idx: Optional[int] = None): - """ - Return the index and `inspect.Parameter` representation of the specified argument. - In the form of a dict with keys "idx" and "param". + """Return the index and `inspect.Parameter` representation of the specified + argument. In the form of a dict with keys "idx" and "param". Parameters ---------- @@ -4032,7 +4235,7 @@ def _expand_typesets(dtypes): return dtypes -def _get_devices_and_dtypes(fn, recurse=False, complement=True): +def _get_devices_and_dtypes(fn, recurse=True, complement=True): supported_devices = ivy.function_supported_devices(fn, recurse=recurse) supported_dtypes = ivy.function_supported_dtypes(fn, recurse=recurse) @@ -4045,9 +4248,9 @@ def _get_devices_and_dtypes(fn, recurse=False, complement=True): for device in supported_devices: supported[device] = supported_dtypes - is_backend_fn = "backend" in fn.__module__ is_frontend_fn = "frontend" in fn.__module__ - is_einops_fn = "einops" in fn.__name__ + is_backend_fn = "backend" in fn.__module__ and not is_frontend_fn + is_einops_fn = hasattr(fn, "__name__") and "einops" in fn.__name__ if not is_backend_fn and not is_frontend_fn and not is_einops_fn: if complement: all_comb = _all_dnd_combinations() @@ -4061,7 +4264,7 @@ def _get_devices_and_dtypes(fn, recurse=False, complement=True): if hasattr(fn, "supported_device_and_dtype"): fn_supported_dnd = fn.supported_device_and_dtype.__get__() - if "einops" in fn.__name__ and isinstance(fn_supported_dnd, dict): + if is_einops_fn and isinstance(fn_supported_dnd, dict): fn_supported_dnd = fn_supported_dnd.get(backend, supported) if fn_supported_dnd: @@ -4069,8 +4272,9 @@ def _get_devices_and_dtypes(fn, recurse=False, complement=True): list(fn_supported_dnd.values())[0], tuple ) - for device, dtypes in fn_supported_dnd.items(): - fn_supported_dnd[device] = tuple(_expand_typesets(dtypes)) + if isinstance(fn_supported_dnd, dict): + for device, dtypes in fn_supported_dnd.items(): + fn_supported_dnd[device] = tuple(_expand_typesets(dtypes)) # dict intersection supported = _dnd_dict_intersection(supported, fn_supported_dnd) @@ -4078,7 +4282,7 @@ def _get_devices_and_dtypes(fn, recurse=False, complement=True): if hasattr(fn, "unsupported_device_and_dtype"): fn_unsupported_dnd = fn.unsupported_device_and_dtype.__get__() - if "einops" in fn.__name__ and isinstance(fn_unsupported_dnd, dict): + if is_einops_fn and isinstance(fn_unsupported_dnd, dict): fn_unsupported_dnd = fn_unsupported_dnd.get(backend, supported) if fn_unsupported_dnd: @@ -4086,8 +4290,9 @@ def _get_devices_and_dtypes(fn, recurse=False, complement=True): list(fn_unsupported_dnd.values())[0], tuple ) - for device, dtypes in fn_unsupported_dnd.items(): - fn_unsupported_dnd[device] = tuple(_expand_typesets(dtypes)) + if isinstance(fn_unsupported_dnd, dict): + for device, dtypes in fn_unsupported_dnd.items(): + fn_unsupported_dnd[device] = tuple(_expand_typesets(dtypes)) # dict difference supported = _dnd_dict_difference(supported, fn_unsupported_dnd) @@ -4102,11 +4307,10 @@ def _get_devices_and_dtypes(fn, recurse=False, complement=True): @handle_exceptions @handle_nestable def function_supported_devices_and_dtypes(fn: Callable, recurse: bool = True) -> Dict: - """ - Return the supported combination of devices and dtypes of the current backend's - function. The function returns a dict containing the supported combination of - devices and dtypes of the primary and compositional implementations in case of - partial mixed functions. + """Return the supported combination of devices and dtypes of the current + backend's function. The function returns a dict containing the supported + combination of devices and dtypes of the primary and compositional + implementations in case of partial mixed functions. Parameters ---------- @@ -4151,11 +4355,10 @@ def function_supported_devices_and_dtypes(fn: Callable, recurse: bool = True) -> @handle_exceptions @handle_nestable def function_unsupported_devices_and_dtypes(fn: Callable, recurse: bool = True) -> Dict: - """ - Return the unsupported combination of devices and dtypes of the current backend's - function. The function returns a dict containing the unsupported combination of - devices and dtypes of the primary and compositional implementations in case of - partial mixed functions. + """Return the unsupported combination of devices and dtypes of the current + backend's function. The function returns a dict containing the unsupported + combination of devices and dtypes of the primary and compositional + implementations in case of partial mixed functions. Parameters ---------- @@ -4201,8 +4404,7 @@ def vmap( in_axes: Union[int, Sequence[int], Sequence[None]] = 0, out_axes: int = 0, ) -> Callable: - """ - Vectorizing map. Creates a function which maps func over argument axes. + """Vectorizing map. Creates a function which maps func over argument axes. Parameters ---------- @@ -4247,7 +4449,7 @@ def vmap( >>> x = ivy.array(ivy.arange(60).reshape((3, 5, 4))) >>> y = ivy.array(ivy.arange(40).reshape((5, 4, 2))) >>> z = ivy.vmap(ivy.matmul, (1, 0), 1)(x, y) - >>> print(z.shape) + >>> z.shape (3, 5, 2) """ # TODO: optimize in the numpy and tensorflow backends and extend functionality @@ -4267,8 +4469,7 @@ def isin( assume_unique: bool = False, invert: bool = False, ) -> ivy.Array: - """ - Test if each element of elements is in test_elements. + """Test if each element of elements is in test_elements. Parameters ---------- @@ -4315,8 +4516,7 @@ def itemsize( x: Union[ivy.Array, ivy.NativeArray], /, ) -> int: - """ - Return the size of the input array's elements. + """Return the size of the input array's elements. Parameters ---------- @@ -4348,8 +4548,7 @@ def strides( x: Union[ivy.Array, ivy.NativeArray], /, ) -> Tuple[int]: - """ - Return the input array's strides across each dimension. + """Return the input array's strides across each dimension. Parameters ---------- @@ -4380,13 +4579,13 @@ def strides( def is_ivy_nested_array(x: Any, /) -> bool: - """ - Determine whether the input x is an Ivy Nested Array. + """Determine whether the input x is an Ivy Nested Array. Parameters ---------- x The input to check + Returns ------- ret diff --git a/ivy/functional/ivy/gradients.py b/ivy/functional/ivy/gradients.py index 6740e800462a4..fb93425a4c4f7 100644 --- a/ivy/functional/ivy/gradients.py +++ b/ivy/functional/ivy/gradients.py @@ -27,7 +27,8 @@ def _get_duplicate_index_chains(xs): - """Generate a list of duplicate index chains for a given nested structure.""" + """Generate a list of duplicate index chains for a given nested + structure.""" duplicate_index_chains = () if isinstance(xs, ivy.Container): duplicate_index_chains = xs.cont_duplicate_array_keychains() @@ -37,7 +38,8 @@ def _get_duplicate_index_chains(xs): def _arrays_to_float_variables(xs, xs_grad_idxs=None): - """Convert all required arrays to float variables for gradient calculation.""" + """Convert all required arrays to float variables for gradient + calculation.""" def inner_fn(x): if ivy.is_array(x, exclusive=True): @@ -103,8 +105,7 @@ def map_fn(x): def _get_required_float_variables(xs, xs_grad_idxs): - """ - Convert all required arrays to float variables for gradient calculation. + """Convert all required arrays to float variables for gradient calculation. Also, returns a list of duplicate index chains for the nested structure. @@ -127,7 +128,8 @@ def _get_required_float_variables(xs, xs_grad_idxs): def _get_native_variables_and_indices(x, reshape=True, idxs=None, create_var=False): - """Extract all relevant results from the output nested structure of a function.""" + """Extract all relevant results from the output nested structure of a + function.""" def map_fn(x_): if ivy.is_array(x_): @@ -167,7 +169,8 @@ def map_fn(x_): def _set_duplicates(xs, duplicate_index_chains): - """Set the duplicates in the nested structure to have the same reference.""" + """Set the duplicates in the nested structure to have the same + reference.""" originals = list( map( lambda key_chains: [key_chains[0]] * (len(key_chains) - 1), @@ -233,8 +236,7 @@ def _stop_grad_and_index(func_ret, retain_grads, grads): def _process_func_ret_and_grads(func_ret, grads, retain_grads): - """ - Stop gradients propagation. + """Stop gradients propagation. Set the gradients of non-finite values to zero, and stopping gradient propagation of the function results. @@ -272,8 +274,7 @@ def _non_finite_to_zero(xs): def _flatten_containers(inputs): - """ - Flatten containers into a single tuple of arrays. + """Flatten containers into a single tuple of arrays. Returns a flattened tuple of arrays and the indices of the arrays in the original containers. @@ -336,10 +337,9 @@ def _is_variable(x, exclusive=False, to_ignore=None) -> bool: def _variable_data( - x: Union[ivy.Array, ivy.NativeArray] + x: Union[ivy.Array, ivy.NativeArray], ) -> Union[ivy.Array, ivy.NativeArray]: - """ - Get the contents of the input. + """Get the contents of the input. Parameters ---------- @@ -373,8 +373,7 @@ def stop_gradient( preserve_type: bool = True, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Stop gradient computation. + """Stop gradient computation. Parameters ---------- @@ -450,9 +449,9 @@ def execute_with_gradients( xs_grad_idxs: Sequence[Sequence[Union[str, int]]] = ((0,),), ret_grad_idxs: Sequence[Sequence[Union[str, int]]] = ((0,),), ) -> Tuple[ivy.Array, ivy.Array]: - """ - Call function func with input of xs variables, and return the function result - func_ret and the gradients of each output variable w.r.t each input variable, + """Call function func with input of xs variables, and return the function + result func_ret and the gradients of each output variable w.r.t each input + variable, Parameters ---------- @@ -528,8 +527,7 @@ def execute_with_gradients( @handle_exceptions def value_and_grad(func: Callable) -> Callable: - """ - Create a function that evaluates both func and the gradient of func. + """Create a function that evaluates both func and the gradient of func. Parameters ---------- @@ -562,8 +560,7 @@ def value_and_grad(func: Callable) -> Callable: @handle_exceptions def jac(func: Callable) -> Callable: - """ - Call function func, and return func's Jacobian partial derivatives. + """Call function func, and return func's Jacobian partial derivatives. Parameters ---------- @@ -596,8 +593,7 @@ def jac(func: Callable) -> Callable: @handle_exceptions def grad(func: Callable, argnums: Union[int, Sequence[int]] = 0) -> Callable: - """ - Call function func, and return func's gradients. + """Call function func, and return func's gradients. Parameters ---------- @@ -647,9 +643,8 @@ def adam_step( epsilon: float = 1e-7, out: Optional[ivy.Array] = None, ) -> Tuple[ivy.Array, ivy.Array, ivy.Array]: - """ - Compute adam step delta, given the derivatives of some cost c with respect to - weights ws, using ADAM update. `[reference] + """Compute adam step delta, given the derivatives of some cost c with + respect to weights ws, using ADAM update. `[reference] `_ @@ -798,9 +793,8 @@ def optimizer_update( stop_gradients: bool = True, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Update weights ws of some function, given the true or effective derivatives of some - cost c with respect to ws, [dc/dw for w in ws]. + """Update weights ws of some function, given the true or effective + derivatives of some cost c with respect to ws, [dc/dw for w in ws]. Parameters ---------- @@ -921,9 +915,8 @@ def gradient_descent_update( stop_gradients: bool = True, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Update weights ws of some function, given the derivatives of some cost c with - respect to ws, [dc/dw for w in ws]. + """Update weights ws of some function, given the derivatives of some cost c + with respect to ws, [dc/dw for w in ws]. Parameters ---------- @@ -1015,10 +1008,9 @@ def lars_update( stop_gradients: bool = True, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Update weights ws of some function, given the derivatives of some cost c with - respect to ws, [dc/dw for w in ws], by applying Layerwise Adaptive Rate Scaling - (LARS) method. + """Update weights ws of some function, given the derivatives of some cost c + with respect to ws, [dc/dw for w in ws], by applying Layerwise Adaptive + Rate Scaling (LARS) method. Parameters ---------- @@ -1120,9 +1112,8 @@ def adam_update( stop_gradients: bool = True, out: Optional[ivy.Array] = None, ) -> Tuple[ivy.Array, ivy.Array, ivy.Array]: - """ - Update weights ws of some function, given the derivatives of some cost c with - respect to ws, using ADAM update. `[reference] + """Update weights ws of some function, given the derivatives of some cost c + with respect to ws, using ADAM update. `[reference] `_ @@ -1287,9 +1278,8 @@ def lamb_update( stop_gradients: bool = True, out: Optional[ivy.Array] = None, ) -> Tuple[ivy.Array, ivy.Array, ivy.Array]: - """ - Update weights ws of some function, given the derivatives of some cost c with - respect to ws, [dc/dw for w in ws], by applying LAMB method. + """Update weights ws of some function, given the derivatives of some cost c + with respect to ws, [dc/dw for w in ws], by applying LAMB method. Parameters ---------- diff --git a/ivy/functional/ivy/layers.py b/ivy/functional/ivy/layers.py index 7b1a320a4b003..d832aa88a4d30 100644 --- a/ivy/functional/ivy/layers.py +++ b/ivy/functional/ivy/layers.py @@ -30,7 +30,7 @@ def _get_embed_dim( pre_embed_dim = query.shape[-1] if ivy.exists(in_proj_weights): embed_dim = in_proj_weights.shape[0] / 3 - elif all([ivy.exists(x) for x in [q_proj_weights, k_proj_weights, v_proj_weights]]): + elif all(ivy.exists(x) for x in [q_proj_weights, k_proj_weights, v_proj_weights]): embed_dim = q_proj_weights.shape[0] else: embed_dim = None @@ -44,10 +44,9 @@ def _in_projection( w, b=None, ): - """ - Projects query, key and value efficiently, depending on whether we are doing self- - attention (query is key is value) or cross-attention (key is value) or an attention - where query, key and value are all different. + """Projects query, key and value efficiently, depending on whether we are + doing self- attention (query is key is value) or cross-attention (key is + value) or an attention where query, key and value are all different. it is only used in multi_head_attention layer. @@ -264,8 +263,7 @@ def dropout( noise_shape: Optional[Sequence[int]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Randomly setting a fraction of input tensor to zeroes with probability. + """Randomly setting a fraction of input tensor to zeroes with probability. `prob` at each update during training time to prevent possible overfitting. The inputs not set to 0 are scaled up `1 / (1 - prob)` by default, so that @@ -396,7 +394,7 @@ def dropout( } """ if prob == 0 or not training: - if dtype is not None: + if dtype is not None and x.dtype != dtype: x = ivy.astype(x, dtype) return ivy.inplace_update(out, x) if ivy.exists(out) else x if noise_shape is None: @@ -449,8 +447,7 @@ def scaled_dot_product_attention( training: Optional[bool] = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Apply scaled dot product attention to inputs x using optional mask. + """Apply scaled dot product attention to inputs x using optional mask. Parameters ---------- @@ -521,9 +518,9 @@ def scaled_dot_product_attention( >>> result = ivy.scaled_dot_product_attention(q,k,v,scale=1,mask=mask) >>> print(result) - ivy.array([[[0.40000001, 1.29999995], - ... [2.19994521, 3.09994531], - ... [4.30000019, 5.30000019]]]) + ivy.array([[[2.30000019, 3.23333359], + [2.30000019, 3.23333359], + [2.30000019, 3.23333359]]]) >>> q = ivy.array([[[0.2, 1.], [2.2, 3.], [4.4, 5.6]]]) >>> k = ivy.array([[[0.6, 1.5], [2.4, 3.3], [4.2, 5.1]]]) @@ -751,20 +748,20 @@ def multi_head_attention( training: bool = False, out: Optional[ivy.Array] = None, ) -> Union[ivy.Array, ivy.NativeArray]: - """ - Apply multi-head attention to inputs x. This is an implementation of multi-headed - attention as described in the paper "Attention is all you Need" (Vaswani et al., - 2017). If `query`, `key`, `value` are the same, then this is self-attention. Each - timestep in `query` attends to the corresponding sequence in `key`, and returns a - fixed-width vector. This layer first projects `query`, `key` and `value`. These are - (effectively) a list of tensors of length `num_attention_heads`, where the - corresponding shapes are `(batch_size, , key_dim)`, `(batch_size, + """Apply multi-head attention to inputs x. This is an implementation of + multi-headed attention as described in the paper "Attention is all you + Need" (Vaswani et al., 2017). If `query`, `key`, `value` are the same, then + this is self-attention. Each timestep in `query` attends to the + corresponding sequence in `key`, and returns a fixed-width vector. This + layer first projects `query`, `key` and `value`. These are (effectively) a + list of tensors of length `num_attention_heads`, where the corresponding + shapes are `(batch_size, , key_dim)`, `(batch_size, , key_dim)`, `(batch_size, , - value_dim)`. Then, the query and key tensors are dot-producted and scaled. These are - softmaxed to obtain attention probabilities. The value tensors are then interpolated - by these probabilities, then concatenated back to a single tensor. Finally, the - result tensor with the last dimension as value_dim can take a linear projection and - return. + value_dim)`. Then, the query and key tensors are dot-producted and scaled. + These are softmaxed to obtain attention probabilities. The value tensors + are then interpolated by these probabilities, then concatenated back to a + single tensor. Finally, the result tensor with the last dimension as + value_dim can take a linear projection and return. Parameters ---------- @@ -856,15 +853,15 @@ def multi_head_attention( if key is None and value is None: key = value = query if num_dims == 2: - query, key, value = [ivy.expand_dims(x, axis=0) for x in [query, key, value]] + query, key, value = (ivy.expand_dims(x, axis=0) for x in [query, key, value]) elif not batch_first: - query, key, value = [ivy.swapaxes(x, 0, 1) for x in [query, key, value]] + query, key, value = (ivy.swapaxes(x, 0, 1) for x in [query, key, value]) # project query, key and value if ivy.exists(in_proj_weights): q, k, v = _in_projection(query, key, value, w=in_proj_weights, b=in_proj_bias) emb_dim = int(in_proj_weights.shape[0] / 3) - elif all([ivy.exists(x) for x in [q_proj_weights, k_proj_weights, v_proj_weights]]): + elif all(ivy.exists(x) for x in [q_proj_weights, k_proj_weights, v_proj_weights]): if ivy.exists(in_proj_bias): b_q, b_k, b_v = ivy.split(in_proj_bias, num_or_size_splits=3) else: @@ -919,7 +916,7 @@ def multi_head_attention( # get attention scores attn_scores = ivy.matmul(q, ivy.swapaxes(k, 1, 2)) - scale = 1 / (head_dim**0.5) if not scale else scale + scale = scale if scale else 1 / (head_dim**0.5) attn_scores *= scale # mask the attention scores @@ -1023,8 +1020,7 @@ def conv1d( bias: Optional[ivy.Array] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute a 1-D convolution given 3-D input x and filters arrays. + """Compute a 1-D convolution given 3-D input x and filters arrays. Parameters ---------- @@ -1128,20 +1124,21 @@ def conv1d_transpose( /, *, output_shape: Optional[Union[ivy.Shape, ivy.NativeShape]] = None, + filter_format: str = "channel_last", data_format: str = "NWC", dilations: Union[int, Tuple[int]] = 1, bias: Optional[ivy.Array] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute a 1-D transpose convolution given 3-D input x and filters arrays. + """Compute a 1-D transpose convolution given 3-D input x and filters + arrays. Parameters ---------- x Input image *[batch_size,w,d_in]* or *[batch_size,d_in,w]*. filters - Convolution filters *[fw,d_in,d_out]*. + Convolution filters *[fw,d_out,d_in]*. strides The stride of the sliding window for each dimension of input. padding @@ -1149,6 +1146,9 @@ def conv1d_transpose( input's), or โ€˜VALIDโ€™ (padding so that the output's shape is `output_shape`). output_shape Shape of the output (Default value = None) + filter_format + Either "channel_first" or "channel_last". "channel_first" corresponds + to "IOW",input data formats, while "channel_last" corresponds to "WOI". data_format The ordering of the dimensions in the input, one of "NWC" or "NCW". "NWC" corresponds to input with shape (batch_size, width, channels), while "NCW" @@ -1175,7 +1175,7 @@ def conv1d_transpose( With :class:`ivy.Array` input: >>> x = ivy.random_normal(mean=0, std=1, shape=[1, 28, 3]) - >>> filters = ivy.random_normal(mean=0, std=1, shape=[3, 3, 6]) + >>> filters = ivy.random_normal(mean=0, std=1, shape=[3, 6, 3]) >>> y = ivy.conv1d_transpose(x, filters, 2, 'SAME') >>> print(y.shape) ivy.Shape(1, 56, 6) @@ -1188,7 +1188,7 @@ def conv1d_transpose( >>> x = ivy.random_normal(mean=0, std=1, shape=[1, 256, 64]) >>> y = ivy.zeros((1, 258, 32)) - >>> filters = ivy.random_normal(mean=0, std=1, shape=[3, 64, 32]) + >>> filters = ivy.random_normal(mean=0, std=1, shape=[3, 32, 64]) >>> ivy.conv1d_transpose(x, filters, 1, 'VALID', out=y) >>> print(y.shape) ivy.Shape(1, 258, 32) @@ -1196,9 +1196,9 @@ def conv1d_transpose( With :class:`ivy.NativeArray` input: >>> x = ivy.native_array( - ... ivy.random_normal(mean=0, std=1, shape=[1,256,128])) + ... ivy.random_normal(mean=0, std=1, shape=[1, 256, 128])) >>> filters = ivy.native_array( - ... ivy.random_normal(mean=0, std=1, shape=[3, 128, 32])) + ... ivy.random_normal(mean=0, std=1, shape=[3, 32, 128])) >>> y = ivy.conv1d_transpose(x, filters, 2, 'SAME') >>> print(y.shape) ivy.Shape(1, 512, 32) @@ -1251,6 +1251,7 @@ def conv1d_transpose( strides, padding, output_shape=output_shape, + filter_format=filter_format, data_format=data_format, dilations=dilations, bias=bias, @@ -1279,8 +1280,7 @@ def conv2d( bias: Optional[ivy.Array] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute a 2-D convolution given 4-D input x and filters arrays. + """Compute a 2-D convolution given 4-D input x and filters arrays. Parameters ---------- @@ -1414,20 +1414,21 @@ def conv2d_transpose( /, *, output_shape: Optional[Union[ivy.Shape, ivy.NativeShape]] = None, + filter_format: str = "channel_last", data_format: str = "NHWC", dilations: Union[int, Tuple[int, int]] = 1, bias: Optional[ivy.Array] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute a 2-D transpose convolution given 4-D input x and filters arrays. + """Compute a 2-D transpose convolution given 4-D input x and filters + arrays. Parameters ---------- x Input image *[batch_size,h,w,d_in]* or *[batch_size,d_in,h,w]*. filters - Convolution filters *[fh,fw,d_in,d_out]*. + Convolution filters *[fh,fw,d_out,d_in]*. strides The stride of the sliding window for each dimension of input. padding @@ -1440,8 +1441,8 @@ def conv2d_transpose( corresponds to inputs with shape (batch_size, height, width, channels), while "NCHW" corresponds to input with shape (batch_size, channels, height, width). filter_format - Either "channel_first" or "channel_last". "channel_first" corresponds to - "OIDHW" input data formats, while "channel_last" corresponds to "DHWIO" . + Either "channel_first" or "channel_last". "channel_first" corresponds + to "IOHW",input data formats, while "channel_last" corresponds to "HWOI". x_dilations The dilation factor for each dimension of input. (Default value = 1) dilations @@ -1465,7 +1466,7 @@ def conv2d_transpose( -------- With :class:`ivy.Array` input: >>> x = ivy.random_normal(mean=0, std=1, shape=[1, 28, 28, 3]) - >>> filters = ivy.random_normal(mean=0, std=1, shape=[3, 3, 3, 6]) + >>> filters = ivy.random_normal(mean=0, std=1, shape=[3, 3, 6, 3]) >>> y = ivy.conv2d_transpose(x,filters,2,'SAME') >>> print(y.shape) ivy.Shape(1, 56, 56, 6) @@ -1478,7 +1479,7 @@ def conv2d_transpose( >>> x = ivy.random_normal(mean=0, std=1, shape=[1, 256, 256, 64]) >>> y = ivy.zeros((1, 258, 258, 32)) - >>> filters = ivy.random_normal(mean=0, std=1, shape=[3, 3, 64, 32]) + >>> filters = ivy.random_normal(mean=0, std=1, shape=[3, 3, 32, 64]) >>> ivy.conv2d_transpose(x,filters,[1, 1, 1],'VALID',out=y) >>> print(y.shape) ivy.Shape(1, 258, 258, 32) @@ -1529,6 +1530,7 @@ def conv2d_transpose( strides, padding, output_shape=output_shape, + filter_format=filter_format, data_format=data_format, dilations=dilations, bias=bias, @@ -1555,8 +1557,8 @@ def depthwise_conv2d( dilations: Union[int, Tuple[int, int]] = 1, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute a 2-D depthwise convolution given 4-D input ``x`` and filters arrays. + """Compute a 2-D depthwise convolution given 4-D input ``x`` and filters + arrays. Parameters ---------- @@ -1697,8 +1699,7 @@ def conv3d( bias: Optional[ivy.Array] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute a 3-D convolution given 5-D input x and filters arrays. + """Compute a 3-D convolution given 5-D input x and filters arrays. Parameters ---------- @@ -1813,20 +1814,21 @@ def conv3d_transpose( /, *, output_shape: Optional[Union[ivy.Shape, ivy.NativeShape]] = None, + filter_format: str = "channel_last", data_format: str = "NDHWC", dilations: Union[int, Tuple[int, int, int]] = 1, bias: Optional[ivy.Array] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute a 3-D transpose convolution given 5-D input x and filters arrays. + """Compute a 3-D transpose convolution given 5-D input x and filters + arrays. Parameters ---------- x Input volume *[batch_size,d,h,w,d_in]* or *[batch_size,d_in,d,h,w]*. filters - Convolution filters *[fd,fh,fw,d_in,d_out]*. + Convolution filters *[fd,fh,fw,d_out,d_in]*. strides The stride of the sliding window for each dimension of input. padding @@ -1834,6 +1836,9 @@ def conv3d_transpose( input's), or โ€˜VALIDโ€™ (padding so that the output's shape is `output_shape`). output_shape Shape of the output (Default value = None) + filter_format + Either "channel_first" or "channel_last". "channel_first" corresponds + to "IODHW",input data formats, while "channel_last" corresponds to "DHWOI". data_format The ordering of the dimensions in the input, one of "NDHWC" or "NCDHW". "NDHWC" corresponds to inputs with shape (batch_size, depth, height, width, channels), @@ -1857,13 +1862,13 @@ def conv3d_transpose( With :class:`ivy.Array` input: >>> x = ivy.random_normal(mean=0, std=1, shape=[1, 3, 28, 28, 3]) - >>> filters = ivy.random_normal(mean=0, std=1, shape=[3, 3, 3, 3, 6]) + >>> filters = ivy.random_normal(mean=0, std=1, shape=[3, 3, 3, 6, 3]) >>> y = ivy.conv3d_transpose(x, filters, [2, 2, 2], 'SAME') >>> print(y.shape) ivy.Shape(1, 6, 56, 56, 6) >>> x = ivy.random_normal(mean=0, std=1, shape=[1, 3, 64, 64, 3]) - >>> filters = ivy.random_normal(mean=0, std=1, shape=[3, 3, 3, 3, 6]) + >>> filters = ivy.random_normal(mean=0, std=1, shape=[3, 3, 3, 6, 3]) >>> y = ivy.conv3d_transpose(x, filters, [2, 2, 2], 'VALID', dilations=[1, 1, 1]) >>> print(y.shape) ivy.Shape(1, 7, 129, 129, 6) @@ -1927,6 +1932,7 @@ def conv3d_transpose( strides, padding, output_shape=output_shape, + filter_format=filter_format, data_format=data_format, dilations=dilations, bias=bias, @@ -1958,9 +1964,8 @@ def conv_general_dilated( bias: Optional[Union[ivy.Array, ivy.NativeArray]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute a 1-D, 2-D, and 3-D convolution given 3-D, 4-D and 5-D input x respectively - and filters arrays. + """Compute a 1-D, 2-D, and 3-D convolution given 3-D, 4-D and 5-D input x + respectively and filters arrays. Parameters ---------- @@ -2036,22 +2041,22 @@ def conv_general_transpose( *, dims: int = 2, output_shape: Optional[Union[ivy.Shape, ivy.NativeShape]] = None, + filter_format: str = "channel_last", data_format: str = "channel_last", dilations: Union[int, Tuple[int], Tuple[int, int], Tuple[int, int, int]] = 1, feature_group_count: int = 1, bias: Optional[Union[ivy.Array, ivy.NativeArray]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute a 1-D, 2-D, and 3-D transpose convolution given 3-D, 4-D and 5-D input x - respectively and filters arrays. + """Compute a 1-D, 2-D, and 3-D transpose convolution given 3-D, 4-D and 5-D + input x respectively and filters arrays. Parameters ---------- x Input image *[batch_size,d,h,w,d_in]* or *[batch_size,d_in,d,h,w]*. filters - Convolution filters *[fd,fh,fw,d_in,d_out]*. + Convolution filters *[fd,fh,fw,d_out,d_in]*. strides The stride of the sliding window for each dimension of input. padding @@ -2061,6 +2066,9 @@ def conv_general_transpose( Either 1, 2, or 3 corresponding to 1-D, 2-D, and 3-D convolution. output_shape Shape of the output. + filter_format + Either "channel_first" or "channel_last". "channel_first" corresponds + to "IODHW",input data formats, while "channel_last" corresponds to "DHWOI". data_format Either "channel_first" or "channel_last". "channel_first" corresponds to "NCW", "NCHW", "NCDHW" input data formatS for 1-D, 2-D, 3-D convolution respectively, @@ -2084,12 +2092,12 @@ def conv_general_transpose( -------- With :class:`ivy.Array` input: >>> x = ivy.random_normal(mean=0, std=1, shape=[1, 3, 28, 28, 3]) - >>> filters = ivy.random_normal(mean=0, std=1, shape=[3, 3, 3, 3, 6]) + >>> filters = ivy.random_normal(mean=0, std=1, shape=[3, 3, 3, 6, 3]) >>> y = ivy.conv3d_transpose(x, filters, [2, 2, 2], 'SAME') >>> print(y.shape) ivy.Shape(1, 6, 56, 56, 6) >>> x = ivy.random_normal(mean=0, std=1, shape=[1, 3, 64, 64, 3]) - >>> filters = ivy.random_normal(mean=0, std=1, shape=[3, 3, 3, 3, 6]) + >>> filters = ivy.random_normal(mean=0, std=1, shape=[3, 3, 3, 6, 3]) >>> y = ivy.conv3d_transpose(x, filters, [2, 2, 2], 'VALID', dilations=[1, 1, 1]) >>> print(y.shape) ivy.Shape(1, 7, 129, 129, 6) @@ -2149,6 +2157,7 @@ def conv_general_transpose( padding, dims=dims, output_shape=output_shape, + filter_format=filter_format, data_format=data_format, dilations=dilations, feature_group_count=feature_group_count, @@ -2180,9 +2189,8 @@ def conv( bias: Optional[Union[ivy.Array, ivy.NativeArray]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute a 1-D, 2-D, and 3-D transpose or dilated convolution given 3-D, 4-D and 5-D - input x respectively and filters arrays. + """Compute a 1-D, 2-D, and 3-D transpose or dilated convolution given 3-D, + 4-D and 5-D input x respectively and filters arrays. Parameters ---------- @@ -2278,14 +2286,16 @@ def lstm_update( *, bias: Optional[Union[ivy.Array, ivy.NativeArray]] = None, recurrent_bias: Optional[Union[ivy.Array, ivy.NativeArray]] = None, -) -> Tuple[ivy.Array, ivy.Array]: - """ - Perform long-short term memory update by unrolling time dimension of input array. + time_major: bool = False, +) -> Tuple[ivy.Array, Tuple[ivy.Array, ivy.Array]]: + """Perform long-short term memory update by unrolling time dimension of + input array. Parameters ---------- x - input tensor of LSTM layer *[batch_shape, t, in]*. + input tensor of LSTM layer *[batch_shape, t, in]* if time_major=False, + else *[t, batch_shape, in]*. init_h initial state tensor for the cell output *[batch_shape, out]*. init_c @@ -2298,13 +2308,19 @@ def lstm_update( bias for cell kernel *[4 x out]*. (Default value = None) recurrent_bias bias for cell recurrent kernel *[4 x out]*. (Default value = None) + time_major + whether or not the input tensor `x` has the time dimension before batch dim. Returns ------- ret - hidden state for all timesteps *[batch_shape,t,out]* and cell state for last - timestep *[batch_shape,out]* + hidden state for all timesteps of shape *[batch_shape,t,out]* if time_major + is False, else *[t, batch_shape, out]*, and a tuple containing the final cell + states, both of shape *[batch_shape,out]*. """ + # ToDo: test_lstm_update needs to be fixed + if time_major: + x = ivy.swapaxes(x, 0, 1) # get shapes x_shape = list(x.shape) batch_shape = x_shape[:-2] @@ -2356,7 +2372,195 @@ def lstm_update( hts_list.append(ivy.expand_dims(ht, axis=-2)) - return ivy.concat(hts_list, axis=-2), ct + ret = ivy.concat(hts_list, axis=-2) + if time_major: + ret = ivy.swapaxes(ret, 0, 1) + + return ret, (ht, ct) + + +@handle_exceptions +@handle_nestable +@handle_array_like_without_promotion +@inputs_to_ivy_arrays +@handle_array_function +def lstm( + input: ivy.Array, + initial_states: Tuple[ivy.Array], + all_weights: Tuple[ivy.Array], + num_layers: int, + dropout: float, + train: bool, + bidirectional: bool, + batch_first: bool = False, + batch_sizes: Sequence = None, + weights_transposed: bool = False, + has_ih_bias: bool = True, + has_hh_bias: bool = True, +): + """Applies a multi-layer long-short term memory to an input sequence. + + Parameters + ---------- + input + input array of shape (seq_len, batch, input_size) when `batch_first` is False + or (batch, seq_len, input_size) when `batch_first` is True + initial_states + tuple of two arrays (h_0, c_0) where h_0 is the initial hidden state of shape + (num_layers * num_directions, batch, hidden_size) and c_0 is the initial cell + state of shape (num_layers * num_directions, batch, hidden_size) + + (num_directions being 2 when `bidirectional`, otherwise 1) + all_weights + tuple of arrays representing the learnable weights of the lstm, with each + layer having up to four arrays (w_ih, w_hh, b_ih, b_hh) representing the weights + and biases (if biases are being used) + + w_ih: weight of shape (4 * hidden_size, input_size) + w_hh: weight of shape (4 * hidden_size, hidden_size) + b_ih: bias of shape (4 * hidden_size,) + b_hh: bias of shape (4 * hidden_size,) + num_layers + number of layers for the lstm to use + dropout + dropout rate + train + whether to run the lstm in train mode or eval mode + bidirectional + whether the lstm is bidirectional or unidirectional + batch_first + defines the data format of the input and output arrays + batch_sizes + specifies the batch size at each timestep, when the input is a packed sequence + weights_transposed + whether the weights are transposed compared to the format + in which they are expected (input_size, 4 * hidden_size) + rather than (4 * hidden_size, input_size) + has_ih_bias + whether the `all_weights` argument includes a input-hidden bias + has_hh_bias + whether the `all_weights` argument includes a hidden-hidden bias + + Returns + ------- + output + output array of shape (seq_len, batch, num_directions * hidden_size) or + (batch, seq_len, num_directions * hidden_size), depending on `batch_first` + h_outs + final hidden state of shape (num_layers * num_directions, batch, hidden_size) + c_outs + final cell state of shape (num_layers * num_directions, batch, hidden_size) + """ + # TODO: the test for this function needs to be fixed - + # see ivy_tests/test_ivy/test_functional/test_nn/test_layers.py::test_lstm + + if weights_transposed: + # transpose the weights if they are in the wrong format + all_weights = [ + ivy.swapaxes(weight, 1, 0) if weight.dim() == 2 else weight + for weight in all_weights + ] + else: + all_weights = list(all_weights) + + if (has_ih_bias and not has_hh_bias) or (has_hh_bias and not has_ih_bias): + # insert zero biases into the weights where one set of biases is not used + shapes = [] + for i in range(2, len(all_weights), 3): + shapes.append(tuple(all_weights[i].shape)) + for i, shape in enumerate(shapes): + idx = (i + 1) * 4 - (1 if has_ih_bias else 2) + all_weights.insert(idx, ivy.zeros(shape)) + has_ih_bias = True + has_hh_bias = True + + weights_per_layer = 2 + if has_ih_bias: + weights_per_layer += 1 + if has_hh_bias: + weights_per_layer += 1 + + assert len(all_weights) == num_layers * weights_per_layer * (1 + bidirectional) + layer_weights = [ + all_weights[i : i + weights_per_layer] + for i in range(0, len(all_weights), weights_per_layer) + ] + + if batch_sizes is not None: + input, batch_sizes = _pad_packed_sequence(input, batch_sizes) + + if batch_first: + input = ivy.swapaxes(input, 0, 1) + + if dropout and train: + raise ivy.utils.exceptions.IvyNotImplementedException() + + unidirectional = not bidirectional + + h0, c0 = initial_states + h_outs, c_outs = [], [] + + output = input + for i in range(num_layers): + if unidirectional: + if weights_per_layer == 4: + weight_ih, weight_hh, (bias_i, bias_h) = _transform_weights( + layer_weights, i + ) + else: + weight_ih, weight_hh = _transform_weights_no_bias(layer_weights, i) + bias_i = bias_h = None + + state_indices = i, i + 1 + else: + if weights_per_layer == 4: + weight_ih_f, weight_hh_f, (bias_i_f, bias_h_f) = _transform_weights( + layer_weights, 2 * i + ) + weight_ih_b, weight_hh_b, (bias_i_b, bias_h_b) = _transform_weights( + layer_weights, 2 * i + 1 + ) + else: + weight_ih_f, weight_hh_f = _transform_weights_no_bias( + layer_weights, 2 * i + ) + weight_ih_b, weight_hh_b = _transform_weights_no_bias( + layer_weights, 2 * i + 1 + ) + bias_i_f = bias_h_f = bias_i_b = bias_h_b = None + + weight_ih = weight_ih_f, weight_ih_b + weight_hh = weight_hh_f, weight_hh_b + bias_i = bias_i_f, bias_i_b + bias_h = bias_h_f, bias_h_b + + state_indices = 2 * i, 2 * i + 2 + + output, (h_out, c_out) = _lstm_layer( + output, + ( + _retrieve_state(h0, *state_indices, num_layers), + _retrieve_state(c0, *state_indices, num_layers), + ), + (weight_ih, weight_hh), + (bias_i, bias_h), + bidirectional, + batch_first=False, + batch_sizes=batch_sizes, + ) + h_outs.append(h_out) + c_outs.append(c_out) + + if batch_first: + output = ivy.swapaxes(output, 0, 1) + + h_outs = h_out if num_layers == 1 else ivy.concat(h_outs, axis=0) + c_outs = c_out if num_layers == 1 else ivy.concat(c_outs, axis=0) + + if batch_sizes is not None: + output = _pack_padded_sequence(output, batch_sizes)[0] + + return output[:, -1], output, (h_outs, c_outs) # Helpers # @@ -2439,9 +2643,6 @@ def _validate_max_pool_params( kernel = [1, 1, *kernel] else: kernel = [1, *kernel, 1] - new_kernel = tuple( - [dilation[i] * (kernel[i] - 1) + 1 for i in range(1, len(kernel))] - ) new_kernel = tuple(dilation[i] * (kernel[i] - 1) + 1 for i in range(1, len(kernel))) if isinstance(padding, list) and len(padding) == len(new_kernel): ivy.utils.assertions.check_kernel_padding_size(new_kernel, padding) @@ -2513,8 +2714,7 @@ def _get_x_data_format(dims: int = 2, data_format: str = "channel_first"): def _get_num_padded_values(i, p, n, k, s): - """ - Get number of padded values in a specific window. + """Get number of padded values in a specific window. Parameters ---------- @@ -2607,6 +2807,139 @@ def _convert_boxes_to_roi_format(boxes): return rois +def _lstm_cell( + x, + init_h, + init_c, + kernel, + recurrent_kernel, + bias, + recurrent_bias, + batch_first, + batch_sizes=None, +): + init_h = ivy.squeeze(init_h, axis=0) + init_c = ivy.squeeze(init_c, axis=0) + out, states = ivy.lstm_update( + x, + init_h, + init_c, + kernel, + recurrent_kernel, + bias=bias, + recurrent_bias=recurrent_bias, + time_major=not batch_first, + ) + h, c = states + h = ivy.expand_dims(h) if len(h.shape) == 2 else h + c = ivy.expand_dims(c) if len(c.shape) == 2 else c + return out, (h, c) + + +def _lstm_layer( + x, hidden, weights, biases, bidirectional, batch_first, batch_sizes=None +): + if not bidirectional: + result, (h, c) = _lstm_cell( + x, + *hidden, + *weights, + *biases, + batch_first=batch_first, + batch_sizes=batch_sizes, + ) + else: + result_fw, (h_fw, c_fw) = _lstm_cell( + x, + hidden[0][:1], + hidden[1][:1], + weights[0][0], + weights[1][0], + biases[0][0], + biases[1][0], + batch_first=batch_first, + batch_sizes=batch_sizes, + ) + x_reversed = ivy.flip(x, axis=0) + result_bw, (h_bw, c_bw) = _lstm_cell( + x_reversed, + hidden[0][1:], + hidden[1][1:], + weights[0][1], + weights[1][1], + biases[0][1], + biases[1][1], + batch_first=batch_first, + batch_sizes=batch_sizes, + ) + result_bw = ivy.flip(result_bw, axis=0) + result = ivy.concat([result_fw, result_bw], axis=len(result_fw.shape) - 1) + c = ivy.concat([c_fw, c_bw], axis=0) + h = ivy.concat([h_fw, h_bw], axis=0) + return result, (h, c) + + +def _pack_padded_sequence(input, lengths): + input = ivy.swapaxes(input, 0, 1) + data = [] + batch_sizes = [] + for i in range(int(max(lengths))): + valid_data_mask = ivy.array(lengths) > i + data.append(input[valid_data_mask, i]) + batch_sizes.append(int(sum(valid_data_mask))) + data = ivy.concat(data) + batch_sizes = ivy.array(batch_sizes, dtype=ivy.int64) + return data, batch_sizes + + +def _pad_packed_sequence(data, batch_sizes): + padded_data = ivy.full( + (len(batch_sizes), int(max(batch_sizes)), *data.shape[1:]), + 0, + dtype=data.dtype, + device=data.device, + ) + data_offset = 0 + for i, batch_size in enumerate(batch_sizes): + batch_size = int(batch_size) + padded_data[i, :batch_size] = data[data_offset : data_offset + batch_size] + data_offset += batch_size + lengths = ivy.sum( + ivy.arange(1, int(max(batch_sizes)) + 1)[:, ivy.newaxis] <= batch_sizes, + axis=1, + dtype=ivy.int64, + ) + return padded_data, lengths + + +def _retrieve_state(x, start, end, num_layers): + return x if num_layers == 1 else _slice_along_axis(x, start=start, stop=end, axis=0) + + +def _transform_weights(layer_weights, layer_index): + weights = layer_weights[layer_index] + weight_ih, weight_hh, bias_ih, bias_hh = weights + return ( + ivy.swapaxes(weight_ih, 0, 1), + ivy.swapaxes(weight_hh, 0, 1), + (bias_ih, bias_hh), + ) + + +def _transform_weights_no_bias(layer_weights, layer_index): + weights = layer_weights[layer_index] + weight_ih, weight_hh = weights + return ivy.swapaxes(weight_ih, 0, 1), ivy.swapaxes(weight_hh, 0, 1) + + +def _slice_along_axis(x, start=0, stop=None, stride=1, axis=0): + if axis >= 0: + slices = [slice(None)] * axis + [slice(start, stop, stride)] + else: + slices = [Ellipsis, slice(start, stop, stride)] + [slice(None)] * (-1 - axis) + return x[tuple(slices)] + + @handle_exceptions @handle_nestable @handle_array_like_without_promotion diff --git a/ivy/functional/ivy/linear_algebra.py b/ivy/functional/ivy/linear_algebra.py index 7e580378e5df4..434c25997a68b 100644 --- a/ivy/functional/ivy/linear_algebra.py +++ b/ivy/functional/ivy/linear_algebra.py @@ -39,8 +39,7 @@ def cholesky( upper: bool = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the cholesky decomposition of the x matrix. + """Compute the cholesky decomposition of the x matrix. Parameters ---------- @@ -183,8 +182,7 @@ def cross( axis: Optional[int] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return cross product of 3-element vectors. + """Return cross product of 3-element vectors. If x1 and x2 are multi- dimensional arrays (i.e., both have a rank greater than 1), then the cross- product of each pair of corresponding 3-element vectors is @@ -283,8 +281,8 @@ def cross( def det( x: Union[ivy.Array, ivy.NativeArray], /, *, out: Optional[ivy.Array] = None ) -> ivy.Array: - """ - Return the determinant of a square matrix (or a stack of square matrices)``x``. + """Return the determinant of a square matrix (or a stack of square + matrices)``x``. Parameters ---------- @@ -363,8 +361,8 @@ def diagonal( axis2: int = -1, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return the specified diagonals of a matrix (or a stack of matrices) ``x``. + """Return the specified diagonals of a matrix (or a stack of matrices) + ``x``. Parameters ---------- @@ -540,10 +538,9 @@ def eig( *, out: Optional[ivy.Array] = None, ) -> Tuple[Union[ivy.Array, ivy.NativeArray]]: - """ - Return an eigendecomposition x = QLQแต€ of a symmetric matrix (or a stack of symmetric - matrices) ``x``, where ``Q`` is an orthogonal matrix (or a stack of matrices) and - ``L`` is a vector (or a stack of vectors). + """Return an eigendecomposition x = QLQแต€ of a symmetric matrix (or a stack + of symmetric matrices) ``x``, where ``Q`` is an orthogonal matrix (or a + stack of matrices) and ``L`` is a vector (or a stack of vectors). .. note:: The function ``eig`` currently behaves like ``eigh``, as @@ -594,10 +591,9 @@ def eigh( UPLO: str = "L", out: Optional[ivy.Array] = None, ) -> Tuple[Union[ivy.Array, ivy.NativeArray]]: - r""" - Return an eigendecomposition x = QLQแต€ of a symmetric matrix (or a stack of symmetric - matrices) ``x``, where ``Q`` is an orthogonal matrix (or a stack of matrices) and - ``L`` is a vector (or a stack of vectors). + r"""Return an eigendecomposition x = QLQแต€ of a symmetric matrix (or a stack + of symmetric matrices) ``x``, where ``Q`` is an orthogonal matrix (or a + stack of matrices) and ``L`` is a vector (or a stack of vectors). .. note:: The function ``eig`` will be added in a future version of the specification, as @@ -707,8 +703,8 @@ def eigvalsh( UPLO: str = "L", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return the eigenvalues of a symmetric matrix (or a stack of symmetric matrices) x. + """Return the eigenvalues of a symmetric matrix (or a stack of symmetric + matrices) x. .. note:: The function ``eig`` will be added in a future version of the specification, as @@ -815,8 +811,7 @@ def inner( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return the inner product of two vectors ``x1`` and ``x2``. + """Return the inner product of two vectors ``x1`` and ``x2``. Parameters ---------- @@ -894,9 +889,8 @@ def inv( adjoint: bool = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return the multiplicative inverse of a square matrix (or a stack of square matrices) - ``x``. + """Return the multiplicative inverse of a square matrix (or a stack of + square matrices) ``x``. Parameters ---------- @@ -992,8 +986,7 @@ def matmul( adjoint_b: bool = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the matrix product. + """Compute the matrix product. Parameters ---------- @@ -1151,10 +1144,10 @@ def matrix_norm( ord: Union[int, float, Literal[inf, -inf, "fro", "nuc"]] = "fro", axis: Tuple[int, int] = (-2, -1), keepdims: bool = False, + dtype: Optional[Union[ivy.Dtype, ivy.NativeDtype]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the matrix p-norm. + """Compute the matrix p-norm. Parameters ---------- @@ -1206,6 +1199,9 @@ def matrix_norm( If this is set to True, the axes which are normed over are left in the result as dimensions with size one. With this option the result will broadcast correctly against the original x. Default is ``False``. + dtype + If specified, the input tensor is cast to dtype before performing the operation, + and the returned tensor's type will be dtype. Default: None out optional output array, for writing the result to. It must have a shape that the inputs broadcast to. @@ -1294,7 +1290,7 @@ def matrix_norm( } """ return current_backend(x).matrix_norm( - x, ord=ord, axis=axis, keepdims=keepdims, out=out + x, ord=ord, axis=axis, keepdims=keepdims, dtype=dtype, out=out ) @@ -1309,8 +1305,8 @@ def matrix_norm( def matrix_power( x: Union[ivy.Array, ivy.NativeArray], n: int, /, *, out: Optional[ivy.Array] = None ) -> ivy.Array: - """ - Raise a square matrix (or a stack of square matrices) x to an integer power n. + """Raise a square matrix (or a stack of square matrices) x to an integer + power n. Parameters ---------- @@ -1416,9 +1412,8 @@ def matrix_rank( hermitian: Optional[bool] = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return the rank (i.e., number of non-zero singular values) of a matrix (or a stack - of matrices). + """Return the rank (i.e., number of non-zero singular values) of a matrix + (or a stack of matrices). Parameters ---------- @@ -1530,8 +1525,7 @@ def matrix_transpose( conjugate: bool = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Transposes a matrix (or a stack of matrices) ``x``. + """Transposes a matrix (or a stack of matrices) ``x``. Parameters ---------- @@ -1620,8 +1614,7 @@ def outer( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return the outer product of two vectors ``x1`` and ``x2``. + """Return the outer product of two vectors ``x1`` and ``x2``. Parameters ---------- @@ -1672,16 +1665,8 @@ def outer( [3.], [4.]]) - A 3-D Example - - >>> x = ivy.array([[[1., 2.], - [3., 4.]], - [[5., 6.], - [7., 8.]]]) - >>> y = ivy.array([[[9., 10.], - [11., 12.]], - [[13., 14.], - [15., 16.]]]) + >>> x = ivy.array([[[1., 2.],[3., 4.]],[[5., 6.],[7., 8.]]]) + >>> y = ivy.array([[[9., 10.],[11., 12.]],[[13., 14.],[15., 16.]]]) >>> d = ivy.outer(x, y) >>> print(d) ivy.array([[ 9., 10., 11., 12., 13., 14., 15., 16.], @@ -1711,9 +1696,8 @@ def pinv( rtol: Optional[Union[float, Tuple[float]]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return the (Moore-Penrose) pseudo-inverse of a matrix (or a stack of matrices) - ``x``. + """Return the (Moore-Penrose) pseudo-inverse of a matrix (or a stack of + matrices) ``x``. Parameters ---------- @@ -1787,10 +1771,9 @@ def qr( mode: str = "reduced", out: Optional[Tuple[ivy.Array, ivy.Array]] = None, ) -> Tuple[ivy.Array, ivy.Array]: - """ - Return the qr decomposition x = QR of a full column rank matrix (or a stack of - matrices), where Q is an orthonormal matrix (or a stack of matrices) and R is an - upper-triangular matrix (or a stack of matrices). + """Return the qr decomposition x = QR of a full column rank matrix (or a + stack of matrices), where Q is an orthonormal matrix (or a stack of + matrices) and R is an upper-triangular matrix (or a stack of matrices). Parameters ---------- @@ -1966,6 +1949,7 @@ def slogdet( >>> print(y) slogdet(sign=ivy.array(1.), logabsdet=ivy.array(1.60943794)) + >>> ivy.set_backend('numpy') # As the precision of results depends on backend. >>> x = ivy.array([[1.2, 2.0, 3.1], ... [6.0, 5.2, 4.0], ... [9.0, 8.0, 7.0]]) @@ -1975,6 +1959,7 @@ def slogdet( With :class:`ivy.Container` input: + >>> ivy.unset_backend() # unset backend again. >>> x = ivy.Container(a=ivy.array([[1.0, 2.0], ... [3.0, 4.0]]), ... b=ivy.array([[1.0, 2.0], @@ -2008,9 +1993,8 @@ def solve( adjoint: bool = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return the solution x to the system of linear equations represented by the well- - determined (i.e., full rank) linear matrix equation Ax = B. + """Return the solution x to the system of linear equations represented by + the well- determined (i.e., full rank) linear matrix equation Ax = B. Parameters ---------- @@ -2051,13 +2035,9 @@ def solve( Examples -------- With class:`ivy.Array` input: - >>> A = ivy.array([[1.1, 1.2, 1.3], - [2.1, 2.2, 2.3], - [3.1, 3.2, 3.3]]), - >>> B = ivy.array([[1.1], - [2.1], - [3.1]]), - >>> x = solve(A,B); + >>> A = ivy.array([[1.1, 1.2, 1.3], [2.1, 2.2, 2.3], [3.1, 3.2, 3.3]]), + >>> B = ivy.array([[1.1], [2.1], [3.1]]), + >>> x = ivy.solve(A,B); >>> print(x) ivy.array([[1], [0], @@ -2066,20 +2046,14 @@ def solve( (1,3) With shape(A) = (2,3,3) and shape(B) = (2,3,1): - >>> A = ivy.array([[[11.1, 11.2, 11.3], - [12.1, 12.2, 12.3], - [13.1, 13.2, 13.3]], - [[21.1, 21.2, 21.3], - [22.1, 22.2, 22.3], - [23.1, 23.2, 23.3]] - ]), + >>> A = ivy.array([[[11.1, 11.2, 11.3],[12.1, 12.2, 12.3],[13.1, 13.2, 13.3]], [[21.1, 21.2, 21.3],[22.1, 22.2, 22.3],[23.1, 23.2, 23.3]]]), >>> B = ivy.array([[[11.1], [12.1], [13.1]], [[21.1], [22.1], [23.1]]]), - >>> x = solve(A,B); + >>> x = ivy.solve(A,B); >>> print(x) ivy.array([[[1], [0], @@ -2091,13 +2065,9 @@ def solve( (2,1,3) With shape(A) = (3,3) and shape(B) = (3,2): - >>> A = ivy.array([[1.1, 1.2, 1.3], - [2.1, 2.2, 2.3], - [3.1, 3.2, 3.3]]), - >>> B = ivy.array([[1.1, 2.2], - [2.1, 4.2], - [3.1, 6.2]]), - >>> x = solve(A,B); + >>> A = ivy.array([[1.1, 1.2, 1.3], [2.1, 2.2, 2.3], [3.1, 3.2, 3.3]]), + >>> B = ivy.array([[1.1, 2.2], [2.1, 4.2], [3.1, 6.2]]), + >>> x = ivy.solve(A,B); >>> print(x) ivy.array([[[1], [0], @@ -2109,18 +2079,16 @@ def solve( (2,1,3) With class:`ivy.Container` input: - >>> A = ivy.array([[1.1, 1.2, 1.3], - [2.1, 2.2, 2.3], - [3.1, 3.2, 3.3]]), + >>> A = ivy.array([[1.1, 1.2, 1.3], [2.1, 2.2, 2.3], [3.1, 3.2, 3.3]]), >>> B = ivy.container(B1 = ivy.array([[1.1], [2.1], [3.1]]), B2 = ivy.array([[2.2], [4.2], [6.2]])) - >>> x = solve(A,B); + >>> x = ivy.solve(A,B); >>> print(x) { B1:([[1],[0],[0]]), B2:([[2],[0],[0]]) } - """ + """ # noqa: E501 return current_backend(x1, x2).solve(x1, x2, adjoint=adjoint, out=out) @@ -2138,11 +2106,11 @@ def svd( compute_uv: bool = True, full_matrices: bool = True, ) -> Union[ivy.Array, Tuple[ivy.Array, ...]]: - """ - Return a singular value decomposition A = USVh of a matrix (or a stack of matrices) - ``x``, where ``U`` is a matrix (or a stack of matrices) with orthonormal columns, - ``S`` is a vector of non-negative numbers (or stack of vectors), and ``Vh`` is a - matrix (or a stack of matrices) with orthonormal rows. + """Return a singular value decomposition A = USVh of a matrix (or a stack + of matrices) ``x``, where ``U`` is a matrix (or a stack of matrices) with + orthonormal columns, ``S`` is a vector of non-negative numbers (or stack of + vectors), and ``Vh`` is a matrix (or a stack of matrices) with orthonormal + rows. Parameters ---------- @@ -2270,8 +2238,7 @@ def svdvals( driver: Optional[str] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return the singular values of a matrix (or a stack of matrices) ``x``. + """Return the singular values of a matrix (or a stack of matrices) ``x``. Parameters ---------- @@ -2279,7 +2246,8 @@ def svdvals( input array having shape ``(..., M, N)`` and whose innermost two dimensions form ``MxN`` matrices. driver - optional output array,name of the cuSOLVER method to be used. This keyword argument only works on CUDA inputs. + optional output array,name of the cuSOLVER method to be used. This keyword + argument only works on CUDA inputs. Available options are: None, gesvd, gesvdj, and gesvda.Default: None. out optional output array, for writing the result to. It must have a shape that the @@ -2331,7 +2299,7 @@ def svdvals( >>> x = ivy.native_array([[1.0, 2.0, 3.0], [2.0, 3.0, 4.0], ... [2.0, 1.0, 3.0], [3.0, 4.0, 5.0]]) - >>> print(x.shape) + >>> x.shape (4, 3) >>> x = ivy.native_array([[1.0, 2.0, 3.0], [2.0, 3.0, 4.0], @@ -2412,8 +2380,7 @@ def tensordot( axes: Union[int, Tuple[List[int], List[int]]] = 2, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return a tensor contraction of x1 and x2 over specific axes. + """Return a tensor contraction of x1 and x2 over specific axes. .. note:: If either ``x1`` or ``x2`` has a complex floating-point data type, neither @@ -2465,7 +2432,7 @@ def tensordot( >>> x = ivy.native_array([[1., 2.], [2., 3.]]) >>> y = ivy.native_array([[3., 4.], [4., 5.]]) - >>> res = ivy.tensordot(x, y, axes = (1,1)) + >>> res = ivy.tensordot(x, y, axes = ([1],[1])) >>> print(res) ivy.array([[11., 14.], [18., 23.]]) @@ -2513,9 +2480,8 @@ def trace( axis2: int = 1, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return the sum along the specified diagonals of a matrix (or a stack of matrices) - ``x``. + """Return the sum along the specified diagonals of a matrix (or a stack of + matrices) ``x``. **Special cases** @@ -2648,7 +2614,7 @@ def trace( ... [7, 0, 6]]) ... ) >>> offset = ivy.Container(a=1, b=0) - >>> y = ivy.trace(x, offset) + >>> y = ivy.trace(x, offset=offset) >>> print(y) { a: ivy.array(6), @@ -2698,8 +2664,7 @@ def vecdot( axis: int = -1, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the (vector) dot product of two arrays. + """Compute the (vector) dot product of two arrays. Parameters ---------- @@ -2797,8 +2762,7 @@ def vector_norm( dtype: Optional[Union[ivy.Dtype, ivy.NativeDtype]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - r""" - Compute the vector norm of a vector (or batch of vectors) ``x``. + r"""Compute the vector norm of a vector (or batch of vectors) ``x``. Parameters ---------- @@ -2900,13 +2864,13 @@ def vector_norm( ivy.array([4.64158917]) - >>> x = ivy.array([1,2,3,4], dtype = ivy.float16) - >>> z = ivy.empty(shape = 1) + >>> x = ivy.array([1.,2.,3.,4.], dtype = ivy.float16) + >>> z = ivy.empty(shape = 1, dtype=ivy.float16) >>> y = ivy.vector_norm(x, ord = 0, out = z) >>> print(y) ivy.array(4.) - >>> x = ivy.arange(8).reshape((2,2,2)) + >>> x = ivy.arange(8, dtype=ivy.float32).reshape((2,2,2)) >>> y = ivy.vector_norm(x, axis = (0,1), ord = float("-inf")) >>> print(y) ivy.array([0, 1]) @@ -2943,9 +2907,8 @@ def diag( k: int = 0, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return the specified diagonals of the input array, or an array with the input - array's elements as diagonals. + """Return the specified diagonals of the input array, or an array with the + input array's elements as diagonals. Parameters ---------- @@ -3028,11 +2991,11 @@ def vander( increasing: bool = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Generate a Vandermonde matrix. The columns of the output matrix are elementwise - powers of the input vector x^{(N-1)}, x^{(N-2)}, ..., x^0x. If increasing is True, - the order of the columns is reversed x^0, x^1, ..., x^{(N-1)}. Such a matrix with a - geometric progression in each row is named for Alexandre-Theophile Vandermonde. + """Generate a Vandermonde matrix. The columns of the output matrix are + elementwise powers of the input vector x^{(N-1)}, x^{(N-2)}, ..., x^0x. If + increasing is True, the order of the columns is reversed x^0, x^1, ..., + x^{(N-1)}. Such a matrix with a geometric progression in each row is named + for Alexandre-Theophile Vandermonde. Parameters ---------- @@ -3122,41 +3085,6 @@ def vector_to_skew_symmetric_matrix( return current_backend(vector).vector_to_skew_symmetric_matrix(vector, out=out) -@handle_exceptions -@handle_backend_invalid -@handle_nestable -@handle_array_like_without_promotion -@handle_out_argument -@to_native_arrays_and_back -@handle_device -def lu_factor( - A: Union[ivy.Array, ivy.NativeArray], - /, - *, - pivot: bool = True, - out: Optional[Union[ivy.Array, ivy.NativeArray]] = None, -) -> Tuple[Union[ivy.Array, ivy.NativeArray], Union[ivy.Array, ivy.NativeArray]]: - """ - Parameters - ---------- - A - tensor of shape (*, m, n) where * is zero or more batch dimensions. - - pivot - Whether to compute the LU decomposition with partial pivoting, or the regular LU - decomposition. pivot = False not supported on CPU. Default: True. - - out - tuple of two tensors to write the output to. Ignored if None. Default: None. - - Returns - ------- - ret - A named tuple (LU, pivots). - """ - return current_backend(A).lu_factor(A, pivot=pivot, out=out) - - @handle_exceptions @handle_backend_invalid @handle_nestable @@ -3181,7 +3109,7 @@ def tensorsolve( allaxes.remove(k) allaxes.insert(ndim1, k) - x1 = ivy.matrix_transpose(x1, allaxes) + x1 = ivy.matrix_transpose(x1) old_shape = x1.shape[-(ndim1 - ndim2) :] diff --git a/ivy/functional/ivy/losses.py b/ivy/functional/ivy/losses.py index 64201cf60f566..a76db473ffbd3 100644 --- a/ivy/functional/ivy/losses.py +++ b/ivy/functional/ivy/losses.py @@ -44,8 +44,7 @@ def cross_entropy( reduction: str = "mean", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute cross-entropy between predicted and true discrete distributions. + """Compute cross-entropy between predicted and true discrete distributions. Parameters ---------- @@ -73,11 +72,11 @@ def cross_entropy( >>> x = ivy.array([0, 0, 1, 0]) >>> y = ivy.array([0.25, 0.25, 0.25, 0.25]) >>> print(ivy.cross_entropy(x, y)) - ivy.array(1.3862944) + ivy.array(0.34657359) >>> z = ivy.array([0.1, 0.1, 0.7, 0.1]) >>> print(ivy.cross_entropy(x, z)) - ivy.array(0.35667497) + ivy.array(0.08916873) """ ivy.utils.assertions.check_elem_in_list(reduction, ["none", "sum", "mean"]) pred = ivy.clip(pred, epsilon, 1 - epsilon) @@ -102,8 +101,7 @@ def binary_cross_entropy( axis: Optional[int] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the binary cross entropy loss. + """Compute the binary cross entropy loss. Parameters ---------- @@ -144,7 +142,7 @@ def binary_cross_entropy( >>> y = ivy.array([0.2, 0.8, 0.3, 0.8]) >>> z = ivy.binary_cross_entropy(x, y) >>> print(z) - ivy.array([0.223,0.223,0.357,1.61]) + ivy.array(0.60309976) >>> x = ivy.array([[0, 1, 1, 0]]) >>> y = ivy.array([[2.6, 6.2, 3.7, 5.3]]) @@ -156,24 +154,26 @@ def binary_cross_entropy( >>> y = ivy.array([[2.6, 6.2, 3.7, 5.3]]) >>> pos_weight = ivy.array([1, 2, 3, 4]) >>> z = ivy.binary_cross_entropy(x, y, pos_weight=pos_weight, from_logits=True) - ivy.array([[2.67164493e+00, 4.05471958e-03, 7.32684899e-02, 5.30496836e+00]]) + ivy.array(2.01348412) >>> x = ivy.array([[0, 1, 1, 0]]) >>> y = ivy.array([[2.6, 6.2, 3.7, 5.3]]) >>> pos_weight = ivy.array([1, 2, 3, 4]) - >>> z = ivy.binary_cross_entropy(x, y, pos_weight=pos_weight, from_logits=True, reduction='sum', axis=1) # noqa: E501 + >>> z = ivy.binary_cross_entropy(x, y, pos_weight=pos_weight, from_logits=True, reduction='sum', axis=1) + >>> print(z) ivy.array([8.05393649]) >>> x = ivy.array([[0, 1, 1, 0]]) >>> y = ivy.array([[2.6, 6.2, 3.7, 5.3]]) >>> z = ivy.binary_cross_entropy(x, y, reduction='none', epsilon=0.5) + >>> print(z) ivy.array([[11.49992943, 3.83330965, 3.83330965, 11.49992943]]) >>> x = ivy.array([[0, 1, 0, 0]]) >>> y = ivy.array([[0.6, 0.2, 0.7, 0.3]]) >>> z = ivy.binary_cross_entropy(x, y, epsilon=1e-3) >>> print(z) - ivy.array([[0.916,1.61,1.2,0.357]]) + ivy.array(1.02136981) With :class:`ivy.NativeArray` input: @@ -181,7 +181,7 @@ def binary_cross_entropy( >>> y = ivy.native_array([0.2, 0.7, 0.2, 0.6]) >>> z = ivy.binary_cross_entropy(x, y) >>> print(z) - ivy.array([0.223,0.357,0.223,0.511]) + ivy.array(0.32844672) With a mix of :class:`ivy.Array` and :class:`ivy.NativeArray` inputs: @@ -189,7 +189,7 @@ def binary_cross_entropy( >>> y = ivy.native_array([0.1, 0.2, 0.8, 0.6]) >>> z = ivy.binary_cross_entropy(x, y) >>> print(z) - ivy.array([0.105,0.223,0.223,0.511]) + ivy.array(0.26561815) With :class:`ivy.Container` input: @@ -197,7 +197,10 @@ def binary_cross_entropy( >>> y = ivy.Container(a=ivy.array([0.6, 0.2, 0.3]),b=ivy.array([0.8, 0.2, 0.2])) >>> z = ivy.binary_cross_entropy(x, y) >>> print(z) - {a:ivy.array([0.511,0.223,0.357]),b:ivy.array([1.61,0.223,1.61])} + { + a: ivy.array(0.36354783), + b: ivy.array(1.14733934) + } With a mix of :class:`ivy.Array` and :class:`ivy.Container` inputs: @@ -206,7 +209,7 @@ def binary_cross_entropy( >>> z = ivy.binary_cross_entropy(x, y) >>> print(z) { - a: ivy.array([0.357, 0.223, 0.223]) + a: ivy.array(0.26765382) } Instance Method Examples @@ -217,8 +220,8 @@ def binary_cross_entropy( >>> y = ivy.array([0.8, 0.2, 0.2, 0.2]) >>> z = ivy.binary_cross_entropy(x, y) >>> print(z) - ivy.array([0.223, 0.223, 0.223, 0.223]) - """ + ivy.array(0.22314337) + """ # noqa: E501 ivy.utils.assertions.check_elem_in_list(reduction, ["none", "sum", "mean"]) if not (0.0 <= epsilon <= 1.0): @@ -281,8 +284,7 @@ def sparse_cross_entropy( reduction: str = "mean", out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute sparse cross entropy between logits and labels. + """Compute sparse cross entropy between logits and labels. Parameters ---------- @@ -312,24 +314,24 @@ def sparse_cross_entropy( >> x = ivy.array([2]) >> y = ivy.array([0.1, 0.1, 0.7, 0.1]) >> print(ivy.sparse_cross_entropy(x, y)) - ivy.array([0.35667494]) + ivy.array([0.08916873]) >>> x = ivy.array([3]) >>> y = ivy.array([0.1, 0.1, 0.7, 0.1]) >>> print(ivy.cross_entropy(x, y)) - ivy.array(21.79329094) + ivy.array(5.44832274) >>> x = ivy.array([2,3]) >>> y = ivy.array([0.1, 0.1]) >>> print(ivy.cross_entropy(x, y)) - ivy.array(11.512926) + ivy.array(5.75646281) With :class:`ivy.NativeArray` input: >>> x = ivy.native_array([4]) >>> y = ivy.native_array([0.1, 0.2, 0.1, 0.1, 0.5]) >>> print(ivy.sparse_cross_entropy(x, y)) - ivy.array([0.693]) + ivy.array([0.13862944]) With :class:`ivy.Container` input: @@ -337,7 +339,7 @@ def sparse_cross_entropy( >>> y = ivy.Container(a=ivy.array([0.1, 0.2, 0.1, 0.1, 0.5])) >>> print(ivy.sparse_cross_entropy(x, y)) { - a: ivy.array([0.693]) + a: ivy.array([0.13862944]) } With a mix of :class:`ivy.Array` and :class:`ivy.NativeArray` inputs: @@ -345,7 +347,7 @@ def sparse_cross_entropy( >>> x = ivy.array([0]) >>> y = ivy.native_array([0.1, 0.2, 0.6, 0.1]) >>> print(ivy.sparse_cross_entropy(x,y)) - ivy.array([2.3]) + ivy.array([0.57564628]) With a mix of :class:`ivy.Array` and :class:`ivy.Container` inputs: @@ -353,7 +355,7 @@ def sparse_cross_entropy( >>> y = ivy.Container(a=ivy.array([0.1, 0.2, 0.6, 0.1])) >>> print(ivy.sparse_cross_entropy(x,y)) { - a: ivy.array([2.3]) + a: ivy.array([0.57564628]) } Instance Method Examples @@ -363,7 +365,7 @@ def sparse_cross_entropy( >>> x = ivy.array([2]) >>> y = ivy.array([0.1, 0.1, 0.7, 0.1]) >>> print(x.sparse_cross_entropy(y)) - ivy.array([0.357]) + ivy.array([0.08916873]) With :class:`ivy.Container` input: @@ -371,7 +373,7 @@ def sparse_cross_entropy( >>> y = ivy.Container(a=ivy.array([0.1, 0.1, 0.7, 0.1])) >>> print(x.sparse_cross_entropy(y)) { - a: ivy.array([0.357]) + a: ivy.array([0.08916873]) } """ ivy.utils.assertions.check_elem_in_list(reduction, ["none", "sum", "mean"]) diff --git a/ivy/functional/ivy/manipulation.py b/ivy/functional/ivy/manipulation.py index 49bd0c36db1c4..b128f99d62f6e 100644 --- a/ivy/functional/ivy/manipulation.py +++ b/ivy/functional/ivy/manipulation.py @@ -54,8 +54,7 @@ def concat( axis: int = 0, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Join a sequence of arrays along an existing axis. + """Join a sequence of arrays along an existing axis. Parameters ---------- @@ -114,9 +113,8 @@ def expand_dims( axis: Union[int, Sequence[int]] = 0, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Expand the shape of an array by inserting a new axis (dimension) of size one at the - position specified by axis. + """Expand the shape of an array by inserting a new axis (dimension) of size + one at the position specified by axis. Parameters ---------- @@ -252,9 +250,8 @@ def flip( axis: Optional[Union[int, Sequence[int]]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Reverses the order of elements in an array along the given axis. The shape of the - array must be preserved. + """Reverses the order of elements in an array along the given axis. The + shape of the array must be preserved. Parameters ---------- @@ -347,8 +344,7 @@ def permute_dims( copy: Optional[bool] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Permutes the axes (dimensions) of an array x. + """Permutes the axes (dimensions) of an array x. Parameters ---------- @@ -450,8 +446,7 @@ def reshape( allowzero: bool = True, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Give a new shape to an array without changing its data. + """Give a new shape to an array without changing its data. Parameters ---------- @@ -574,10 +569,10 @@ def roll( axis: Optional[Union[int, Sequence[int]]] = None, out: Optional[ivy.Array] = None, ) -> Union[ivy.Array, ivy.Container]: - """ - Roll array elements along a specified axis. Array elements that roll beyond the last - position are re-introduced at the first position. Array elements that roll beyond - the first position are re-introduced at the last position. + """Roll array elements along a specified axis. Array elements that roll + beyond the last position are re-introduced at the first position. Array + elements that roll beyond the first position are re-introduced at the last + position. Parameters ---------- @@ -688,8 +683,7 @@ def squeeze( copy: Optional[bool] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Remove singleton dimensions (axes) from x. + """Remove singleton dimensions (axes) from x. Parameters ---------- @@ -781,8 +775,7 @@ def stack( axis: int = 0, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Join a sequence of arrays along a new axis. + """Join a sequence of arrays along a new axis. Parameters ---------- @@ -869,8 +862,7 @@ def clip( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Clips (limits) the values in an array. + """Clips (limits) the values in an array. Given an interval, values outside the interval are clipped to the interval edges (element-wise). For example, if an interval of [0, 1] is specified, values smaller @@ -997,8 +989,7 @@ def constant_pad( value: Number = 0, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Pad an array with a constant value. + """Pad an array with a constant value. Parameters ---------- @@ -1091,11 +1082,10 @@ def repeat( /, repeats: Union[int, Iterable[int]], *, - axis: int = None, + axis: Optional[int] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Repeat values along a given dimension. + """Repeat values along a given dimension. Parameters ---------- @@ -1170,8 +1160,7 @@ def split( axis: int = 0, with_remainder: bool = False, ) -> List[ivy.Array]: - """ - Split an array into multiple sub-arrays. + """Split an array into multiple sub-arrays. Parameters ---------- @@ -1225,9 +1214,17 @@ def split( >>> x = ivy.Container(a=ivy.array([10, 45, 2])) >>> y = ivy.split(x) >>> print(y) - { - a:(list[3],shape=[1]) - } + [ + { + a: ivy.array([10]) + }, + { + a: ivy.array([45]) + }, + { + a: ivy.array([2]) + } + ] """ return current_backend(x).split( x, @@ -1256,8 +1253,7 @@ def swapaxes( copy: Optional[bool] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Interchange two axes of an array. + """Interchange two axes of an array. Parameters ---------- @@ -1364,8 +1360,7 @@ def tile( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Construct an array by repeating x the number of times given by reps. + """Construct an array by repeating x the number of times given by reps. Parameters ---------- @@ -1447,8 +1442,7 @@ def unstack( axis: int = 0, keepdims: bool = False, ) -> List[ivy.Array]: - """ - Unpacks the given dimension of a rank-R array into rank-(R-1) arrays. + """Unpacks the given dimension of a rank-R array into rank-(R-1) arrays. Parameters ---------- @@ -1542,8 +1536,7 @@ def zero_pad( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Pad an array with zeros. + """Pad an array with zeros. Parameters ---------- diff --git a/ivy/functional/ivy/meta.py b/ivy/functional/ivy/meta.py index 771facb671158..1da6ed819a3cc 100644 --- a/ivy/functional/ivy/meta.py +++ b/ivy/functional/ivy/meta.py @@ -26,8 +26,7 @@ def _compute_cost_and_update_grads( batched, num_tasks, ): - """ - Compute cost and update gradients. + """Compute cost and update gradients. This function computes the cost and updates gradients for optimization. @@ -263,6 +262,59 @@ def _train_tasks_batched( num_tasks, stop_gradients, ): + """Train tasks in a batched manner. + + This function trains tasks in a batched manner with optional inner and outer batch functions. + + Parameters + ---------- + batch : object + The batch data. + inner_batch_fn : function or None + The inner batch function. + outer_batch_fn : function or None + The outer batch function. + inner_cost_fn : function + The inner cost function. + outer_cost_fn : function + The outer cost function. + variables : ivy.Container + The variables for optimization. + inner_grad_steps : int + Number of inner gradient steps. + inner_learning_rate : float + Inner learning rate. + inner_optimization_step : function + The inner optimization step function. + order : int + The order of computation. + average_across_steps : bool + Whether to average across steps. + inner_v : object + Inner variable. + keep_inner_v : bool + Whether to keep inner variable. + outer_v : object + Outer variable. + keep_outer_v : bool + Whether to keep outer variable. + return_inner_v : str or bool + Whether and which inner variables to return. + num_tasks : int + Number of tasks. + stop_gradients : bool + Whether to stop gradients during optimization. + + Returns + ------- + object or tuple + The computed cost and, optionally, gradients and updated inner variables. + + Examples + -------- + >>> # Example usage here + >>> pass + """ # noqa: E501 (Line too long) inner_batch = batch outer_batch = batch if inner_batch_fn is not None: @@ -478,8 +530,7 @@ def fomaml_step( num_tasks: Optional[int] = None, stop_gradients: bool = True, ) -> Tuple[ivy.Array, ivy.Container, Any]: - """ - Perform step of first order MAML. + """Perform step of first order MAML. Parameters ---------- @@ -594,8 +645,7 @@ def reptile_step( num_tasks: Optional[int] = None, stop_gradients: bool = True, ) -> Tuple[ivy.Array, ivy.Container, Any]: - """ - Perform a step of Reptile. + """Perform a step of Reptile. Parameters ---------- @@ -744,8 +794,7 @@ def maml_step( num_tasks: Optional[int] = None, stop_gradients: bool = True, ) -> Tuple[ivy.Array, ivy.Container, Any]: - """ - Perform step of vanilla second order MAML. + """Perform step of vanilla second order MAML. Parameters ---------- diff --git a/ivy/functional/ivy/nest.py b/ivy/functional/ivy/nest.py index a8c64db178806..2725361c86bba 100644 --- a/ivy/functional/ivy/nest.py +++ b/ivy/functional/ivy/nest.py @@ -20,8 +20,8 @@ def index_nest( index: Union[List[int], Tuple[int], Iterable[int]], /, ) -> Any: - """ - Index a nested object, using a tuple of indices or keys in the case of dicts. + """Index a nested object, using a tuple of indices or keys in the case of + dicts. Parameters ---------- @@ -92,8 +92,7 @@ def index_nest( @handle_exceptions def prune_nest_at_index(nest: Iterable, index: Tuple, /) -> None: - """ - Prune a nested object at a specified index. + """Prune a nested object at a specified index. Parameters ---------- @@ -117,8 +116,7 @@ def set_nest_at_index( shallow: bool = True, _result: Union[ivy.Array, ivy.NativeArray, ivy.Container, Dict, List, Tuple] = None, ) -> Union[ivy.Array, ivy.NativeArray, ivy.Container, Dict, List, Tuple]: - """ - Set the value of a nested item at a specified index. + """Set the value of a nested item at a specified index. Parameters ---------- @@ -217,8 +215,8 @@ def set_nest_at_index( @handle_exceptions def insert_into_nest_at_index(nest: Iterable, index: Tuple, value) -> None: - """ - Recursively inserts a value into a nested data structure at a specified index. + """Recursively inserts a value into a nested data structure at a specified + index. This function traverses a nested data structure and inserts the provided `value` at the specified `index`. @@ -241,11 +239,11 @@ def insert_into_nest_at_index(nest: Iterable, index: Tuple, value) -> None: >>> nest = [[1, 2], [3, 4]] >>> index = (1, 1) >>> value = 99 - >>> insert_into_nest_at_index(nest, index, value) + >>> ivy.insert_into_nest_at_index(nest, index, value) >>> print(nest) [[1, 2], [3, 99, 4]] """ - if isinstance(nest, dict) or isinstance(nest, ivy.Container): + if isinstance(nest, (dict, ivy.Container)): if len(index) == 1: key = index[0] if isinstance(nest, dict): @@ -277,8 +275,7 @@ def map_nest_at_index( shallow: bool = True, _result: Union[ivy.Array, ivy.NativeArray, ivy.Container, Dict, List] = None, ) -> Union[ivy.Array, ivy.NativeArray, ivy.Container, Dict, List, Tuple]: - """ - Map a function to the value of a nested item at a specified index. + """Map a function to the value of a nested item at a specified index. Parameters ---------- @@ -372,7 +369,10 @@ def map_nest_at_index( try: _result = nest_type(_result) except TypeError: - _result = nest_type(*_result) + try: + _result = nest_type(*_result) + except TypeError: + pass return _result @@ -382,9 +382,8 @@ def multi_index_nest( indices: Iterable[Iterable[int]], /, ) -> Iterable[Any]: - """ - Repeatedly index a nested object, using a tuple of tuples of indices or keys in the - case of dicts. + """Repeatedly index a nested object, using a tuple of tuples of indices or + keys in the case of dicts. Parameters ---------- @@ -449,8 +448,7 @@ def multi_index_nest( @handle_exceptions def prune_nest_at_indices(nest: Iterable, indices: Tuple, /) -> None: - """ - Prune a nested object at specified indices. + """Prune a nested object at specified indices. Parameters ---------- @@ -476,8 +474,8 @@ def set_nest_at_indices( /, shallow: bool = True, ) -> Union[ivy.Array, ivy.NativeArray, ivy.Container, Dict, List, Tuple]: - """ - Set the value of a nested item at specified indices with specified values. + """Set the value of a nested item at specified indices with specified + values. Parameters ---------- @@ -554,8 +552,8 @@ def set_nest_at_indices( @handle_exceptions def insert_into_nest_at_indices(nest: Iterable, indices: Tuple, values, /) -> None: - """ - Insert a value into the nested item at specified indices with specified values. + """Insert a value into the nested item at specified indices with specified + values. Parameters ---------- @@ -583,8 +581,7 @@ def map_nest_at_indices( /, shallow: bool = True, ) -> Union[ivy.Array, ivy.NativeArray, ivy.Container, Dict, List, Tuple]: - """ - Map a function to the values of a nested item at the specified indices. + """Map a function to the values of a nested item at the specified indices. Parameters ---------- @@ -668,9 +665,8 @@ def nested_argwhere( _base: bool = True, stop_after_n_found: Optional[int] = None, ) -> Union[Iterable, bool]: - """ - Check the leaf nodes of nested x via function fn, and returns all nest indices where - the method evaluates as True. + """Check the leaf nodes of nested x via function fn, and returns all nest + indices where the method evaluates as True. Parameters ---------- @@ -820,8 +816,7 @@ def all_nested_indices( _index: Optional[Union[int, Sequence[int]]] = None, _base: bool = True, ) -> List: - """ - Return indices of all the elements in nest. + """Return indices of all the elements in nest. Parameters ---------- @@ -916,8 +911,7 @@ def map( unique: Optional[Dict[str, Iterable[Any]]] = None, mean: bool = False, ) -> List: - """ - Apply a function on each item of an iterable x. + """Apply a function on each item of an iterable x. Parameters ---------- @@ -1027,10 +1021,9 @@ def nested_map( _dict_check_fn: Optional[Callable] = None, shallow: bool = True, ) -> Union[ivy.Array, ivy.NativeArray, Iterable, Dict]: - """ - Apply a function on x in a nested manner, whereby all dicts, lists and tuples are - traversed to their lowest leaves before applying the method and returning x. If x is - not nested, the method is applied to x directly. + """Apply a function on x in a nested manner, whereby all dicts, lists and + tuples are traversed to their lowest leaves before applying the method and + returning x. If x is not nested, the method is applied to x directly. Parameters ---------- @@ -1100,18 +1093,12 @@ def nested_map( ... ) >>> function = lambda a : a + 1 >>> ivy.nested_map(function, x) - { - a: ivy.array([[2, 3, 4], - [10, 9, 8]]), - b: ivy.array([[5, 6, 7], - [13, 14, 15]]) - } >>> print(x) { - a: ivy.array([[2, 3, 4], - [10, 9, 8]]), - b: ivy.array([[5, 6, 7], - [13, 14, 15]]) + a: ivy.array([[1, 2, 3], + [9, 8, 7]]), + b: ivy.array([[4, 5, 6], + [12, 13, 14]]) } >>> nest = ([1, 2], [3, 4], [5, 6], {"a": 1, "b": 2, "c": 3}) @@ -1242,9 +1229,8 @@ def nested_any( check_nests: bool = False, _base: bool = True, ) -> bool: - """ - Check the leaf nodes of nest x via function fn, and returns True if any evaluate to - True, else False. + """Check the leaf nodes of nest x via function fn, and returns True if any + evaluate to True, else False. Parameters ---------- @@ -1288,9 +1274,8 @@ def copy_nest( include_derived: bool = False, to_mutable: bool = False, ) -> Union[ivy.Array, ivy.NativeArray, Iterable]: - """ - Copy a nest deeply, but without copying leaves of the nest, only the nest lists, - tuples and dicts are copied. + """Copy a nest deeply, but without copying leaves of the nest, only the + nest lists, tuples and dicts are copied. Parameters ---------- @@ -1393,9 +1378,8 @@ def nested_multi_map( config=None, to_ivy=True, ): - """ - Apply function to all array values from a collection of identically structured ivy - arrays. + """Apply function to all array values from a collection of identically + structured ivy arrays. Parameters ---------- @@ -1417,6 +1401,7 @@ def nested_multi_map( The configuration for the nests. Default is the same as nest0. to_ivy convert the output to ivy_arrays. Default is ``True`` + Returns ------- nest containing the result of the function. The structure of the output is the @@ -1524,7 +1509,7 @@ def _found_in_index_chains(this_index_chain, index_chains): ) ) ret = func(values, this_index_chain) - if to_ivy: + if to_ivy and ret is not None: if isinstance(nest, (ivy.Array, ivy.NativeArray)): return ret else: @@ -1542,10 +1527,9 @@ def _found_in_index_chains(this_index_chain, index_chains): @handle_exceptions def duplicate_array_index_chains(nest: Union[ivy.Array, ivy.NativeArray, Iterable]): - """ - Group all unique index chains in a nest. This function is useful for finding all - unique index chains in a nest, and then duplicating the values at those index chains - for functional frameworks. + """Group all unique index chains in a nest. This function is useful for + finding all unique index chains in a nest, and then duplicating the values + at those index chains for functional frameworks. Parameters ---------- @@ -1573,8 +1557,7 @@ def duplicate_array_index_chains(nest: Union[ivy.Array, ivy.NativeArray, Iterabl def prune_empty(nest): - """ - Prune empty nests from a nest. + """Prune empty nests from a nest. Parameters ---------- diff --git a/ivy/functional/ivy/norms.py b/ivy/functional/ivy/norms.py index 0af316281855b..8812b94cc8a00 100644 --- a/ivy/functional/ivy/norms.py +++ b/ivy/functional/ivy/norms.py @@ -32,8 +32,7 @@ def layer_norm( new_std: float = 1.0, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Apply Layer Normalization over a mini-batch of inputs. + """Apply Layer Normalization over a mini-batch of inputs. Parameters ---------- diff --git a/ivy/functional/ivy/random.py b/ivy/functional/ivy/random.py index 23949e11ba77a..ca9510b0a0179 100644 --- a/ivy/functional/ivy/random.py +++ b/ivy/functional/ivy/random.py @@ -106,11 +106,10 @@ def random_uniform( seed: Optional[int] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Draws samples from a uniform distribution. Samples are uniformly distributed over - the half-open interval ``[low, high)`` (includes ``low``, but excludes ``high``). In - other words, any value within the given interval is equally likely to be drawn by - uniform. + """Draws samples from a uniform distribution. Samples are uniformly + distributed over the half-open interval ``[low, high)`` (includes ``low``, + but excludes ``high``). In other words, any value within the given interval + is equally likely to be drawn by uniform. Parameters ---------- @@ -222,8 +221,7 @@ def random_normal( device: Optional[Union[ivy.Device, ivy.NativeDevice]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Draws samples from a normal distribution. + """Draws samples from a normal distribution. Parameters ---------- @@ -334,10 +332,10 @@ def multinomial( seed: Optional[int] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Draws samples from a multinomial distribution. Specifically, returns a tensor where - each row contains num_samples indices sampled from the multinomial probability - distribution located in the corresponding row of tensor input. + """Draws samples from a multinomial distribution. Specifically, returns a + tensor where each row contains num_samples indices sampled from the + multinomial probability distribution located in the corresponding row of + tensor input. Parameters ---------- @@ -444,9 +442,8 @@ def randint( seed: Optional[int] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return an array filled with random integers generated uniformly between low - (inclusive) and high (exclusive). + """Return an array filled with random integers generated uniformly between + low (inclusive) and high (exclusive). Parameters ---------- @@ -508,8 +505,7 @@ def randint( @handle_exceptions @handle_nestable def seed(*, seed_value: int = 0) -> None: - """ - Set the seed for random number generation. + """Set the seed for random number generation. Parameters ---------- @@ -539,8 +535,7 @@ def shuffle( seed: Optional[int] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Shuffles the given array along a given axis. + """Shuffles the given array along a given axis. Parameters ---------- diff --git a/ivy/functional/ivy/searching.py b/ivy/functional/ivy/searching.py index ae440f221d0d8..9dd2c434990c8 100644 --- a/ivy/functional/ivy/searching.py +++ b/ivy/functional/ivy/searching.py @@ -39,10 +39,9 @@ def argmax( select_last_index: bool = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return the indices of the maximum values along a specified axis. When the maximum - value occurs multiple times, only the indices corresponding to the first occurrence - are returned. + """Return the indices of the maximum values along a specified axis. When + the maximum value occurs multiple times, only the indices corresponding to + the first occurrence are returned. Parameters ---------- @@ -93,9 +92,10 @@ def argmax( ivy.array([1]) >>> x = ivy.array([-0., 1., -1.]) - >>> ivy.argmax(x, out=x) - >>> print(x) - ivy.array([1]) + >>> z = ivy.zeros((1,3), dtype=ivy.int64) + >>> ivy.argmax(x, out=z) + >>> print(z) + ivy.array(1) >>> x = ivy.array([[1., -0., -1.], [-2., 3., 2.]]) >>> y = ivy.argmax(x, axis=1) @@ -113,7 +113,7 @@ def argmax( ivy.array([0, 2]) int64 >>> x = ivy.array([[4., 0., -1.],[2., -3., 6], [2., -3., 6]]) - >>> z = ivy.zeros((1,3), dtype=ivy.int64) + >>> z = ivy.zeros((3,1), dtype=ivy.int64) >>> y = ivy.argmax(x, axis=1, keepdims=True, out=z) >>> print(z) ivy.array([[0],[2],[2]]) @@ -156,10 +156,9 @@ def argmin( select_last_index: bool = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return the indices of the minimum values along a specified axis. When the minimum - value occurs multiple times, only the indices corresponding to the first occurrence - are returned. + """Return the indices of the minimum values along a specified axis. When + the minimum value occurs multiple times, only the indices corresponding to + the first occurrence are returned. Parameters ---------- @@ -264,8 +263,7 @@ def nonzero( size: Optional[int] = None, fill_value: Number = 0, ) -> Union[Tuple[ivy.Array], ivy.Array]: - """ - Return the indices of the array elements which are non-zero. + """Return the indices of the array elements which are non-zero. .. note:: If ``x`` has a complex floating-point data type, non-zero elements @@ -401,8 +399,7 @@ def where( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return elements chosen from x or y depending on condition. + """Return elements chosen from x or y depending on condition. Parameters ---------- @@ -485,8 +482,7 @@ def argwhere( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return the indices of all non-zero elements of the input array. + """Return the indices of all non-zero elements of the input array. Parameters ---------- diff --git a/ivy/functional/ivy/set.py b/ivy/functional/ivy/set.py index 0c0d916b24cc4..5f9e92f400918 100644 --- a/ivy/functional/ivy/set.py +++ b/ivy/functional/ivy/set.py @@ -38,10 +38,10 @@ def unique_all( Union[ivy.Array, ivy.NativeArray], Union[ivy.Array, ivy.NativeArray], ]: - """ - Return the unique elements of an input array ``x``, the first occurring indices for - each unique element in ``x``, the indices from the set of unique elements that - reconstruct ``x``, and the corresponding counts for each unique element in ``x``. + """Return the unique elements of an input array ``x``, the first occurring + indices for each unique element in ``x``, the indices from the set of + unique elements that reconstruct ``x``, and the corresponding counts for + each unique element in ``x``. .. admonition:: Data-dependent output shape :class: important @@ -161,9 +161,8 @@ def unique_inverse( *, axis: Optional[int] = None, ) -> Tuple[Union[ivy.Array, ivy.NativeArray], Union[ivy.Array, ivy.NativeArray]]: - """ - Return the unique elements of an input array ``x``, and the indices from the set of - unique elements that reconstruct ``x``. + """Return the unique elements of an input array ``x``, and the indices from + the set of unique elements that reconstruct ``x``. .. admonition:: Data-dependent output shape :class: important @@ -244,20 +243,6 @@ def unique_inverse( >>> print(y) Results(values=ivy.array([0.2, 0.3, 0.5, 0.8, 1.2, 2.4]), inverse_indices=ivy.array([2, 1, 3, 0, 4, 5, 1])) - - With :class:`ivy.Container` input: - - >>> x = ivy.Container(a=ivy.array([1., 4., 3. , 5. , 3. , 7.]), - ... b=ivy.array([3, 2, 6, 3, 7, 4, 9])) - >>> y = ivy.ivy.unique_inverse(x) - >>> print(y) - [{ - a: ivy.array([1., 3., 4., 5., 7.]), - b: ivy.array([2, 3, 4, 6, 7, 9]) - }, { - a: ivy.array([0, 2, 1, 3, 1, 4]), - b: ivy.array([1, 0, 3, 1, 4, 2, 5]) - }] """ return ivy.current_backend(x).unique_inverse(x, axis=axis) @@ -276,8 +261,7 @@ def unique_values( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return the unique elements of an input array ``x``. + """Return the unique elements of an input array ``x``. .. admonition:: Data-dependent output shape :class: important @@ -367,9 +351,8 @@ def unique_counts( x: Union[ivy.Array, ivy.NativeArray], /, ) -> Tuple[Union[ivy.Array, ivy.NativeArray], Union[ivy.Array, ivy.NativeArray]]: - """ - Return the unique elements of an input array ``x`` and the corresponding counts for - each unique element in ``x``. + """Return the unique elements of an input array ``x`` and the corresponding + counts for each unique element in ``x``. .. admonition:: Data-dependent output shape :class: important diff --git a/ivy/functional/ivy/sorting.py b/ivy/functional/ivy/sorting.py index fe073103f1541..7e3e7daaac313 100644 --- a/ivy/functional/ivy/sorting.py +++ b/ivy/functional/ivy/sorting.py @@ -36,8 +36,7 @@ def argsort( stable: bool = True, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return the indices that sort an array ``x`` along a specified axis. + """Return the indices that sort an array ``x`` along a specified axis. Parameters ---------- @@ -157,8 +156,7 @@ def sort( stable: bool = True, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return a sorted copy of an array. + """Return a sorted copy of an array. Parameters ---------- @@ -259,8 +257,7 @@ def msort( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return a copy of an array sorted along the first axis. + """Return a copy of an array sorted along the first axis. Parameters ---------- @@ -308,8 +305,7 @@ def searchsorted( ret_dtype: Union[ivy.Dtype, ivy.NativeDtype] = ivy.int64, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return the indices of the inserted elements in a sorted array. + """Return the indices of the inserted elements in a sorted array. Parameters ---------- diff --git a/ivy/functional/ivy/statistical.py b/ivy/functional/ivy/statistical.py index 0afd9b740b22c..d160973ae184f 100644 --- a/ivy/functional/ivy/statistical.py +++ b/ivy/functional/ivy/statistical.py @@ -48,10 +48,11 @@ def min( *, axis: Optional[Union[int, Sequence[int]]] = None, keepdims: bool = False, + initial: Optional[Union[int, float, complex]] = None, + where: Optional[ivy.Array] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Calculate the minimum value of the input array ``x``. + """Calculate the minimum value of the input array ``x``. .. note:: When the number of elements over which to compute the minimum value is zero, the @@ -83,6 +84,11 @@ def min( compatible with the input array (see :ref:`broadcasting`). Otherwise, if ``False``, the reduced axes (dimensions) must not be included in the result. Default: ``False``. + initial + The maximum value of an output element. + Must be present to allow computation on empty slice. + where + Elements to compare for minimum out optional output array, for writing the result to. @@ -140,7 +146,9 @@ def min( b: ivy.array(2) } """ - return current_backend(x).min(x, axis=axis, keepdims=keepdims, out=out) + return current_backend(x).min( + x, axis=axis, keepdims=keepdims, initial=initial, where=where, out=out + ) @handle_exceptions @@ -159,8 +167,7 @@ def max( keepdims: bool = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Calculate the maximum value of the input array ``x``. + """Calculate the maximum value of the input array ``x``. .. note:: When the number of elements over which to compute the maximum value is zero, the @@ -270,8 +277,7 @@ def mean( keepdims: bool = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Calculate the arithmetic mean of the input array ``x``. + """Calculate the arithmetic mean of the input array ``x``. **Special Cases** @@ -383,8 +389,7 @@ def prod( keepdims: bool = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Calculate the product of input array x elements. + """Calculate the product of input array x elements. **Special Cases** @@ -519,8 +524,7 @@ def std( keepdims: bool = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Calculate the standard deviation of the input array ``x``. + """Calculate the standard deviation of the input array ``x``. **Special Cases** @@ -658,8 +662,7 @@ def sum( keepdims: Optional[bool] = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Calculate the sum of the input array x. + """Calculate the sum of the input array x. **Special Cases** @@ -799,8 +802,7 @@ def var( keepdims: bool = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Calculate the variance of the input array x. + """Calculate the variance of the input array x. **Special Cases** @@ -916,8 +918,7 @@ def cumsum( dtype: Optional[Union[ivy.Dtype, ivy.NativeDtype]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return the cumulative sum of the elements along a given axis. + """Return the cumulative sum of the elements along a given axis. Parameters ---------- @@ -1062,8 +1063,7 @@ def cumprod( dtype: Optional[Union[ivy.Dtype, ivy.NativeDtype]] = None, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Return the cumulative product of the elements along a given axis. + """Return the cumulative product of the elements along a given axis. Parameters ---------- @@ -1099,9 +1099,7 @@ def cumprod( >>> print(y) ivy.array([1, 2, 6]) - >>> x = ivy.array([[2, 3], - [5, 7], - [11, 13]]) + >>> x = ivy.array([[2, 3],[5, 7],[11, 13]]) >>> y = ivy.zeros((3, 2)) >>> ivy.cumprod(x, axis=1, exclusive=True, out=y) >>> print(y) @@ -1119,7 +1117,7 @@ def cumprod( >>> x = ivy.array([[2, 3],[5, 7],[11, 13]]) >>> y = ivy.zeros((3, 2)) >>> x.cumprod(axis=0, exclusive=True, out=y) - >>> print(x) + >>> print(y) ivy.array([[1., 1.], [2., 3.], [10., 21.]]) @@ -1142,12 +1140,7 @@ def cumprod( b: ivy.array([1, 3, 12]) } - >>> x = ivy.Container(a=ivy.array([[2, 3], - [5, 7], - [11, 13]]), - b=ivy.array([[3, 4], - [4, 5], - [5, 6]])) + >>> x = ivy.Container(a=ivy.array([[2, 3],[5, 7],[11, 13]]), b=ivy.array([[3, 4],[4, 5],[5, 6]])) >>> y = ivy.Container(a = ivy.zeros((3, 2)), b = ivy.zeros((3, 2))) >>> ivy.cumprod(x, axis=1, exclusive=True, out=y) >>> print(y) @@ -1160,12 +1153,7 @@ def cumprod( [1, 5]]) } - >>> x = ivy.Container(a=ivy.array([[2, 3], - [5, 7], - [11, 13]]), - b=ivy.array([[3, 4], - [4, 5], - [5, 6]])) + >>> x = ivy.Container(a=ivy.array([[2, 3],[5, 7],[11, 13]]), b=ivy.array([[3, 4],[4, 5],[5, 6]])) >>> x.cumprod(axis=0, exclusive=True, out=x) >>> print(x) { @@ -1174,9 +1162,9 @@ def cumprod( [10, 21]]), b: ivy.array([[1, 1], [3, 4], - [15, 42]]) + [12, 20]]) } - """ + """ # noqa: E501 return current_backend(x).cumprod( x, axis=axis, exclusive=exclusive, reverse=reverse, dtype=dtype, out=out ) @@ -1195,9 +1183,8 @@ def einsum( *operands: Union[ivy.Array, ivy.NativeArray], out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Sum the product of the elements of the input operands along dimensions specified - using a notation based on the Einstein summation convention. + """Sum the product of the elements of the input operands along dimensions + specified using a notation based on the Einstein summation convention. Parameters ---------- diff --git a/ivy/functional/ivy/utility.py b/ivy/functional/ivy/utility.py index 09bd432b60291..d323e0f91cda5 100644 --- a/ivy/functional/ivy/utility.py +++ b/ivy/functional/ivy/utility.py @@ -33,8 +33,8 @@ def all( keepdims: bool = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Test whether all input array elements evaluate to ``True`` along a specified axis. + """Test whether all input array elements evaluate to ``True`` along a + specified axis. .. note:: Positive infinity, negative infinity, and NaN must evaluate to ``True``. @@ -147,8 +147,8 @@ def any( keepdims: bool = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Test whether any input array element evaluates to ``True`` along a specified axis. + """Test whether any input array element evaluates to ``True`` along a + specified axis. .. note:: Positive infinity, negative infinity, and NaN must evaluate to ``True``. diff --git a/ivy/stateful/activations.py b/ivy/stateful/activations.py index a2a789701a64b..65d158af4b6cc 100644 --- a/ivy/stateful/activations.py +++ b/ivy/stateful/activations.py @@ -13,8 +13,7 @@ def __init__( approximate: bool = False, complex_mode: Literal["split", "magnitude", "jax"] = "jax", ): - """ - Apply the GELU activation function. + """Apply the GELU activation function. Parameters ---------- @@ -29,8 +28,7 @@ def __init__( Module.__init__(self) def _forward(self, x): - """ - Perform forward pass of the GELU activation. + """Perform forward pass of the GELU activation. Parameters ---------- @@ -48,6 +46,9 @@ def _forward(self, x): complex_mode=self._complex_mode, ) + def _extra_repr(self) -> str: + return f"approximate={self._approximate}, complex_mode={self._complex_mode}" + class GEGLU(Module): def __init__(self): @@ -55,8 +56,7 @@ def __init__(self): Module.__init__(self) def _forward(self, inputs): - """ - Perform forward pass of the GEGLU activation. + """Perform forward pass of the GEGLU activation. Parameters ---------- @@ -77,8 +77,7 @@ def __init__( self, complex_mode: Literal["split", "magnitude", "jax"] = "jax", ): - """ - Apply the RELU activation function. + """Apply the RELU activation function. Parameters ---------- @@ -104,6 +103,9 @@ def _forward(self, x): """ return ivy.relu(x, complex_mode=self._complex_mode) + def _extra_repr(self) -> str: + return f"complex_mode={self._complex_mode}" + class LeakyReLU(Module): def __init__( @@ -111,8 +113,7 @@ def __init__( alpha: float = 0.2, complex_mode: Literal["split", "magnitude", "jax"] = "jax", ): - """ - Apply the LEAKY RELU activation function. + """Apply the LEAKY RELU activation function. Parameters ---------- @@ -145,6 +146,9 @@ def _forward(self, x): complex_mode=self._complex_mode, ) + def _extra_repr(self) -> str: + return f"alpha={self._alpha}, complex_mode={self._complex_mode}" + class LogSoftmax(Module): def __init__( @@ -152,8 +156,7 @@ def __init__( axis: Optional[int] = -1, complex_mode: Literal["split", "magnitude", "jax"] = "jax", ): - """ - Apply the LOG SOFTMAX activation function. + """Apply the LOG SOFTMAX activation function. Parameters ---------- @@ -182,6 +185,9 @@ def _forward(self, x): """ return ivy.log_softmax(x, axis=self._axis, complex_mode=self._complex_mode) + def _extra_repr(self) -> str: + return f"axis={self._axis}, complex_mode={self._complex_mode}" + class Softmax(Module): def __init__( @@ -189,8 +195,7 @@ def __init__( axis: int = -1, complex_mode: Literal["split", "magnitude", "jax"] = "jax", ): - """ - Apply the SOFTMAX activation function. + """Apply the SOFTMAX activation function. Parameters ---------- @@ -222,6 +227,9 @@ def _forward(self, x): """ return ivy.softmax(x, axis=self._axis, complex_mode=self._complex_mode) + def _extra_repr(self) -> str: + return f"axis={self._axis}, complex_mode={self._complex_mode}" + class Softplus(Module): def __init__(self, beta=1.0, threshold=None): @@ -251,6 +259,9 @@ def _forward(self, x): """ return ivy.softplus(x, beta=self._beta, threshold=self._threshold) + def _extra_repr(self) -> str: + return f"beta={self._beta}, threshold={self._threshold}" + class Mish(Module): def __init__(self): @@ -296,8 +307,7 @@ def _forward(self, x): class Sigmoid(Module): def __init__(self, complex_mode: Literal["split", "magnitude", "jax"] = "jax"): - """ - Apply the SIGMOID activation function. + """Apply the SIGMOID activation function. Parameter ---------- @@ -323,11 +333,13 @@ def _forward(self, x): """ return ivy.sigmoid(x, complex_mode=self._complex_mode) + def _extra_repr(self) -> str: + return f"complex_mode={self._complex_mode}" + class Tanh(Module): def __init__(self, complex_mode: Literal["split", "magnitude", "jax"] = "jax"): - """ - Apply the TANH activation function. + """Apply the TANH activation function. Parameters ---------- @@ -353,11 +365,13 @@ def _forward(self, x): """ return ivy.tanh(x, complex_mode=self._complex_mode) + def _extra_repr(self) -> str: + return f"complex_mode={self._complex_mode}" + class ReLU6(Module): def __init__(self, complex_mode: Literal["split", "magnitude", "jax"] = "jax"): - """ - Apply the TANH activation function. + """Apply the TANH activation function. Parameters ---------- @@ -383,11 +397,13 @@ def _forward(self, x): """ return ivy.relu6(x, complex_mode=self._complex_mode) + def _extra_repr(self) -> str: + return f"complex_mode={self._complex_mode}" + class Hardswish(Module): def __init__(self, complex_mode: Literal["split", "magnitude", "jax"] = "jax"): - """ - Apply the HARDSWISH activation function. + """Apply the HARDSWISH activation function. Parameters ---------- @@ -413,6 +429,9 @@ def _forward(self, x): """ return ivy.hardswish(x, complex_mode=self._complex_mode) + def _extra_repr(self) -> str: + return f"complex_mode={self._complex_mode}" + class Logit(Module): def __init__( @@ -420,8 +439,7 @@ def __init__( eps=None, complex_mode="jax", ): - """ - Apply the LOGIT activation function. + """Apply the LOGIT activation function. Parameters ---------- @@ -454,6 +472,9 @@ def _forward(self, x): complex_mode=self._complex_mode, ) + def _extra_repr(self) -> str: + return f"eps={self._eps}, complex_mode={self._complex_mode}" + class PReLU(Module): def __init__(self, slope): @@ -478,6 +499,9 @@ def _forward(self, x): """ return ivy.prelu(x, self._slope) + def _extra_repr(self) -> str: + return f"slope={self._slope}" + class SeLU(Module): def __init__(self): @@ -514,6 +538,7 @@ def _forward(self, x): Inputs to process *[batch_shape, d]*. alpha scaler for controlling the slope of the function for x <= 0 Default: 1.0 + Returns ------- ret @@ -521,11 +546,13 @@ def _forward(self, x): """ return ivy.elu(x, alpha=self._alpha) + def _extra_repr(self) -> str: + return f"alpha={self._alpha}" + class LogSigmoid(Module): def __init__(self, complex_mode: Literal["split", "magnitude", "jax"] = "jax"): - """ - Apply the LogSigmoid activation function. + """Apply the LogSigmoid activation function. Parameter ---------- @@ -550,3 +577,6 @@ def _forward(self, x): The outputs following the LogSigmoid activation *[batch_shape, d]* """ return ivy.logsigmoid(x, complex_mode=self._complex_mode) + + def _extra_repr(self) -> str: + return f"complex_mode={self._complex_mode}" diff --git a/ivy/stateful/converters.py b/ivy/stateful/converters.py index cb573bfb8ee9d..541829bc3d18b 100644 --- a/ivy/stateful/converters.py +++ b/ivy/stateful/converters.py @@ -1,6 +1,7 @@ """Converters from Native Modules to Ivy Modules.""" # global +import functools from typing import Optional, Dict, List import re # noqa import inspect @@ -20,9 +21,8 @@ def to_ivy_module( devices=None, inplace_update=False, ): - """ - Convert an instance of a trainable module from a native framework into a trainable - ivy.Module instance. + """Convert an instance of a trainable module from a native framework into a + trainable ivy.Module instance. Parameters ---------- @@ -75,8 +75,7 @@ def from_haiku_module( device=None, devices=None, ): - """ - Convert a Haiku module instance to an Ivy module instance. + """Convert a Haiku module instance to an Ivy module instance. Parameters ---------- @@ -169,8 +168,7 @@ def from_flax_module( device=None, devices=None, ): - """ - Convert a Flax module instance to an Ivy module instance. + """Convert a Flax module instance to an Ivy module instance. Parameters ---------- @@ -259,8 +257,7 @@ def from_keras_module( device=None, devices=None, ): - """ - Convert a Keras module instance to an Ivy module instance. + """Convert a Keras module instance to an Ivy module instance. Parameters ---------- @@ -322,8 +319,7 @@ def from_paddle_module( device=None, devices=None, ): - """ - Convert a Paddle layer instance to an Ivy module instance. + """Convert a Paddle layer instance to an Ivy module instance. Parameters ---------- @@ -379,8 +375,7 @@ def from_torch_module( devices=None, inplace_update=False, ): - """ - Convert a Torch module instance to an Ivy module instance. + """Convert a Torch module instance to an Ivy module instance. Parameters ---------- @@ -437,3 +432,120 @@ def from_torch_module( inplace_update=inplace_update, **i_kwargs, ) + + def to_keras_module(self): + """Convert a `ivy.Module` module instance to a `tf.keras.Model` + instance. + + Returns + ------- + ret + The new trainable `tf.keras.Model` instance. + """ + try: + import tensorflow as tf + except ModuleNotFoundError as exc: + raise ModuleNotFoundError( + "`tensorflow` was not found installed on your system. Please proceed " + "to install it and restart your interpreter to see the changes." + ) from exc + + class KerasModel(tf.keras.Model): + def __init__(self, ivy_module): + super().__init__() + self._ivy_module = ivy_module + self._parameters = {} + self._assign_variables() + self._populate_params() + self._propagate_params() + + def _assign_variables(self): + ivy.set_backend("tensorflow") + + self._ivy_module.v = self._ivy_module.v.cont_map( + lambda x, kc: ( + ivy.to_new_backend(x.ivy_array.data, native=True) + if hasattr(x, "_ivy_array") + else ivy.to_new_backend(x, native=True) + ), + ) + self._ivy_module.v.cont_map( + lambda x, kc: ( + self.add_weight( + name=kc, shape=x.shape, dtype=x.dtype, trainable=True + ) + if x is not None + else x + ) + ) + model_weights = [] + self._ivy_module.v.cont_map( + lambda x, kc: ( + model_weights.append(ivy.to_numpy(x)) if x is not None else x + ) + ) + self.set_weights(model_weights) + + ivy.previous_backend() + + def _populate_params(self): + self._parameters = { + re.sub(r":([0-9]+)$", "", param.name).replace( + f"{self.name}/", "" + ): param + for param in self.variables + } + + def _propagate_params(self): + def __update_param(ivy_module, x, kc): + if kc not in self._parameters: + return x + # Update param in the underneath ivy module + module = ivy_module + keys = re.split("[/.]", kc) + for key in keys[:-1]: + module = module.__getattribute__(key) + if hasattr(module, "_update_v"): + module._update_v({keys[-1]: self._parameters[kc]}) + return getattr(module, keys[-1]) + + self._ivy_module.v = self._ivy_module.v.cont_map( + functools.partial(__update_param, self._ivy_module), + inplace=True, + ) + + def call(self, *args, training=None, **kwargs): + ret = self._ivy_module(*args, **kwargs) + ret = ivy.nested_map( + lambda x: ( + x.ivy_array.data + if hasattr(x, "_ivy_array") + else ivy.to_native(x) + ), + ret, + ) + return ret + + def __call__(self, *args, **kwargs): + if ivy.backend != "tensorflow": + ivy.set_backend("tensorflow") + args, kwargs = ivy.args_to_new_backend(*args, native=True, **kwargs) + ivy.previous_backend() + else: + args, kwargs = ivy.args_to_new_backend(*args, native=True, **kwargs) + return super().__call__(*args, **kwargs) + + def to_device(self, device): + self._ivy_module._module_graph.to_device(device) + model_weights = ivy.nested_map( + lambda x: ( + ivy.to_native(ivy.to_device(x, device)) + if ivy.is_array(x) + else x + ), + self.weights, + ) + self.set_weights(model_weights) + + keras_module = KerasModel(self) + return keras_module diff --git a/ivy/stateful/helpers.py b/ivy/stateful/helpers.py index b51489772bf0b..c62ea0bea79f1 100644 --- a/ivy/stateful/helpers.py +++ b/ivy/stateful/helpers.py @@ -1,584 +1,383 @@ """Base class for helper module methods.""" # global -import abc -import numpy as np -import termcolor +import functools +import logging # local import ivy +from ivy.data_classes.container import Container +from ivy.func_wrapper import _get_first_array -class ModuleHelpers(abc.ABC): - # Private # - # --------# - def _top_v_fn(self, /, depth=None, flatten_key_chains=False): - """ - Return the variables at a specific depth, with depth 1 returning the variables - of the current layer. +class ModuleHelpers: + def _find_variables( + self, + /, + *, + obj=None, + without_initialisation=False, + _visited=None, + ): + """Find all internal variables in obj. Return empty Container if obj is + None. Parameters ---------- - depth - depth of the variables to return. 1 for current layer, None for the - topmost layer. Default is ``None``. - flatten_key_chains - If set True, will return a flat container which all nested key-chains - flattened. Default is ``False``. + obj + The submodule whose internal variables are to be returned. Default + is None. + without_initialization + Whether or not to initialize the variables, to avoid initialization when + the model variables are passed in the input directly. + _visited + Placeholder for tracking the visited nodes, do not set this parameter. Returns ------- ret - The variables of the submodule at the specified depth. - """ - if ivy.exists(self.top_v): - if ivy.exists(depth): - ret = self.top_v(depth - 1) if depth > 1 else self.v - else: - ret = self.top_v() - else: - ret = self.v - if flatten_key_chains: - return ret.cont_flatten_key_chains() - return ret + The internal variables of the submodule passed in the argument. + """ + _visited = ivy.default(_visited, {}) + vs = Container() + if id(obj) in _visited: + return vs + _visited[id(obj)] = True + # ToDo: add support for finding local variables, if/when JAX supports + # uniquely flagging variables + if isinstance(obj, ModuleHelpers) and obj is not self: + + if not obj.built and without_initialisation: + return lambda: obj._build_and_return_v( + *obj._args, dynamic_backend=self._dynamic_backend, **obj._kwargs + ) - def _top_mod_fn(self, /, depth=None): - """ - Find the top (parent) module at specific depth, starting with depth 1 to return - the current submodule. + return obj._build_and_return_v( + *obj._args, dynamic_backend=obj._dynamic_backend, **obj._kwargs + ) + elif isinstance(obj, (list, tuple)): + for i, v in enumerate(obj): + ret = self._find_variables( + obj=v, + without_initialisation=without_initialisation, + _visited=_visited, + ) + if ret: + vs[f"v{str(i)}"] = ret + return vs + elif isinstance(obj, dict): + for k, v in obj.items(): + ret = self._find_variables( + obj=v, + without_initialisation=without_initialisation, + _visited=_visited, + ) + if ret: + vs[k[1:] if k[0] == "_" else k] = ret + return vs + elif not hasattr(obj, "__dict__"): + return vs + for k, v in obj.__dict__.items(): + if v is not None and k[0:2] != "__" and k != "_module_dict": + ret = self._find_variables( + obj=v, + without_initialisation=without_initialisation, + _visited=_visited, + ) + if ret: + vs[k[1:] if k[0] == "_" else k] = ret + return vs + + def _find_buffers(self): + if hasattr(self, "_module_dict"): + for key, sub_module in self._module_dict.items(): + if len(sub_module._buffers) > 0: + self._buffers[key] = sub_module._buffers + + def _build_and_return_v(self, *args, **kwargs): + self.build(*args, **kwargs) + return self.v + + @staticmethod + def _extract_v(v, keychain_mappings: dict, orig_key_chain, /): + """Extract the variables from the variables container v using the key + orig_key_chain and reinstantiate the duplicate variables that were + removed by _remove_duplicate_variables in their correct locations using + keychain_mappings. Parameters ---------- - depth - The number of modules we want to trace back. 1 for the current module, None - for the topmost module. Default is ``None``. + v + The variables container + keychain_mappings + The keychain mappings of duplicate vatriables + orig_key_chain + keychain of the variables to be extracted - Returns - ------- - ret - The module we want to track down. Return current module if no top - module exists. - """ - if ivy.exists(self.top_mod): - if ivy.exists(depth): - return self.top_mod(depth - 1) if depth > 1 else self - return self.top_mod() - return self - - # noinspection PyProtectedMember - def track_submod_rets(self): - """ - Return True if the current module should have its returns tracked as set by the - user during the call. Returns ------- - ret - True if the returned values of the current module should be - tracked. + ret_cont + container with the extracted variables. """ - if not ivy.exists(self.top_mod): - return False - top_mod = self.top_mod() - submods = top_mod._submods_to_track - if ivy.exists(submods) and self not in submods: - return False - depth = top_mod._submod_depth - if ivy.exists(depth): - return ( - self.top_mod(depth - 1)._track_submod_rets - if depth > 0 - else self._track_submod_rets - ) - return top_mod._track_submod_rets + if v.cont_has_key_chain(orig_key_chain): + ret_cont = v.cont_at_key_chain(orig_key_chain) + else: + ret_cont = Container() + for old_kc, new_kc in keychain_mappings.items(): + if orig_key_chain in old_kc: + # Check if `v` contains `new_kc` before replacing in `ret_cont` + if v.cont_has_key_chain(new_kc): + ret_cont = ret_cont.cont_set_at_key_chain( + "/".join(old_kc.split("/")[1:]), v.cont_at_key_chain(new_kc) + ) + else: + continue + return ret_cont + + @staticmethod + def _remove_duplicate_variables(vs, created, /): + """Remove duplicate variables in `vs` referring to `created`. - def check_submod_rets(self): - """ - Return True if there is an expected submodule return value set by the user - during the call. + Parameters + ---------- + vs + The container that needs to be pruned. + created + The container as the duplication reference. Returns ------- - ret - True if the top module has expected_submod_rets. - """ - if not ivy.exists(self.top_mod): - return False - if ivy.exists(self.top_mod().expected_submod_rets): - return True - return False - - # noinspection PyProtectedMember - def track_submod_call_order(self): - """ - Tracks the order in which the submodules are called. + vs + The container after removing duplicate variables. + keychain_mappings + Dict storing those keys and ids being removed. + """ + created_ids = created.cont_map(lambda x, kc: id(x)) + vs_ids = vs.cont_map(lambda x, kc: id(x)) + ids = {} + duplicate_keychains = [] + keychain_mappings = {} + + def unique_callback(x, kc): + ids[x] = kc + + def found_dup_callback(x, kc): + if ids[x] == kc: + return + duplicate_keychains.append(kc) + keychain_mappings[kc] = ids[x] - Returns - ------- - ret - True if the current module allows call order tracking. - """ - if not ivy.exists(self.top_mod): - return False - top_mod = self.top_mod() - submods = top_mod._submods_to_track - if ivy.exists(submods) and self not in submods: - return False - depth = top_mod._submod_depth - if ivy.exists(depth): - return ( - self.top_mod(depth - 1)._track_submod_call_order - if depth > 0 - else self._track_submod_call_order + created_ids.cont_map(lambda x, kc: unique_callback(x, kc)) + vs_ids.cont_map( + lambda x, kc: ( + unique_callback(x, kc) if x not in ids else found_dup_callback(x, kc) ) - return top_mod._track_submod_call_order - - def mod_depth(self): - """ - Return the depth of the current module. Return 0 for root module. - - Returns - ------- - ret - The depth of the module in the network. - """ - depth = 0 - mod_above = self - while True: - if ivy.exists(mod_above.top_mod): - mod_above = mod_above.top_mod(1) - else: - break - depth += 1 - return depth - - def mod_height(self): - """ - Return the height of the network, with the current level being 0. - - Returns - ------- - ret - The height of the network. 0 if the are no submodules. - """ - return self.sub_mods().cont_max_depth - 1 - - # Public # - # ------# - - def _set_submod_flags( - self, - track_submod_rets, - submod_depth, - submods_to_track, - track_submod_call_order, - expected_submod_rets, - /, - ): - """ - Set flags of the submodule. - - Parameters - ---------- - track_submod_rets - If True, will track the returns of submodules. - submod_depth - The depth of tracked submodules. - submods_to_track - If given, will only track submodules in `submods_to_track`. - track_submod_call_order - If True, will track the call order of submodules. - expected_submod_rets - If given, will raise exception if submodule returns are - different from expected returns. - """ - self._track_submod_rets = track_submod_rets - self._submod_depth = submod_depth - self._submods_to_track = submods_to_track - self._track_submod_call_order = track_submod_call_order - self.expected_submod_rets = ( - ivy.Container(expected_submod_rets).to_numpy(map_sequences=True) - if ivy.exists(expected_submod_rets) - else expected_submod_rets ) + for dup_kc in duplicate_keychains: + vs = vs.cont_prune_key_chain(dup_kc) + return vs, keychain_mappings - def _unset_submod_flags(self): - """Unset flags of the submodule.""" - self._track_submod_rets = False - self._submod_depth = None - self._submods_to_track = None - self._track_submod_call_order = False - self.expected_submod_rets = None - - def get_mod_key(self, /, *, top_mod=None): - """ - Get the key of current module to be used when checking or tracking the return - values of a submodule. - - Parameters - ---------- - top_mod - Explicit indicate the top module. None for the top - module of current module. Default is ``None``. - - Returns - ------- - A string of current module key. - """ - if top_mod is None: - top_mod = self.top_mod() - submod_dict = top_mod.submod_dict - full_key = self.__repr__().split(".")[-1] - name_key = full_key.split(" ")[0] - if name_key not in submod_dict: - submod_dict[name_key] = {} - id_str = full_key.split(" ")[-1][:-1] - if id_str not in submod_dict[name_key]: - submod_dict[name_key][id_str] = str(len(submod_dict[name_key])) - idx_key = submod_dict[name_key][id_str] - return " " * self.mod_depth() + "_".join([name_key, idx_key]) - - def sub_mods(self, /, *, show_v=True, depth=None, flatten_key_chains=False): - """ - Return a container comoposed of all submodules. + def _wrap_call_methods( + self, keychain_mappings, /, *, key="", obj=None, _visited=None + ): + """Wrap the call methods of the Module object by looping over all the + items within the module, wrapping the __call__ methods of all + submodules using _fn_with_var_arg. Parameters ---------- - show_v - If set True, will return values of all submodule variables. - Default is ``True``. - depth - How many layers we step in before beginning enumerating submodules. - None for current layer. Default is ``None``. - flatten_key_chains - If set True, will return a flat (depth-1) container, - in which all nested key-chains flattened. Default is ``False``. + keychain_mappings + The keychain mappings of the object + key + The keychain of the object obj, used for recursion. + obj + the object whose __call__ method is to be wrapped + _visited + Placeholder for tracking the visited nodes, do not set this parameter. Returns ------- - ret - A container composed of all submodules. - """ - if self._sub_mods: - if ivy.exists(depth): - if depth == 0: - if show_v: - return self.v - return "" - next_depth = depth - 1 - else: - next_depth = None - ret = ivy.Container( - { - ivy.Container.cont_flatten_key_chain( - sm.__repr__(), replacement="_" - ): sm.sub_mods(show_v=show_v, depth=next_depth) - for sm in self._sub_mods - } - ) - if flatten_key_chains: - return ret.cont_flatten_key_chains() - return ret - if show_v: - return self.v - return "" - - def show_v_in_top_v(self, /, *, depth=None): + None """ - Show sub containers from the perspective of the top layer. Will give prompt if - either of `v` or `top_v` is not initialized. + _visited = ivy.default(_visited, {}) + if id(obj) in _visited or not isinstance(key, str): + return + _visited[id(obj)] = True + if isinstance(obj, ModuleHelpers) and obj is not self: + orig_key_chain = key[1:] if key[0] == "_" else key - Parameters - ---------- - depth - The number of modules we want to step in. None for the value of - current module. Default is ``None``. - """ - if ivy.exists(self.top_v) and ivy.exists(self.v): - self.top_v(depth).cont_show_sub_container(self.v) - else: - print( - "both self.top_v and self.v must be initialized in order to show v in" - f" top_v, but found\n\ntop_v: {self.top_v}\n\nv: {self.v}." + obj.__call__ = self._fn_with_var_arg( + obj.__call__, self._extract_v, keychain_mappings, orig_key_chain ) - - def v_with_top_v_key_chains(self, /, *, depth=None, flatten_key_chains=False): - """ - Show the network's variables from the perspective of value of top layer. Will - give prompt if either of `v` and `top_v` is not initialized. - - Parameters - ---------- - depth - The number of modules we want to step in. None for the value of - current module. Default is ``None``. - flatten_key_chains - If set True, will return a flat container, - with all nested key-chains flattened. Default is ``False``. - """ - if ivy.exists(self.top_v) and ivy.exists(self.v): - kc = self.top_v(depth).cont_find_sub_container(self.v) - if kc: - ret = self.v.cont_restructure_key_chains({"": kc}, keep_orig=False) - else: - ret = self.v - if flatten_key_chains: - return ret.cont_flatten_key_chains() - return ret - else: - print( - "both self.top_v and self.v must be initialized in order to show v in" - f" top_v, but found\n\ntop_v: {self.top_v}\n\nv: {self.v}." - ) - - def mod_with_top_mod_key_chain(self, /, *, depth=None, flatten_key_chain=False): - """ - Return a list containing the modules of the network starting from the top - module, and ending with the current module. - - Parameters - ---------- - depth - If specified, will return a list of modules of length starting at - the current module and ending at the module at the specified depth. - 0 for the current module. 1 for the iimediate parent module. None for - the top module. Default is ``None``. - - flatten_key_chain - If set True, will return return a flat container, - with all nested key-chains flattened. Default is ``False``. - """ - if not ivy.exists(self.top_mod) or depth == 0: - return self.__repr__() - max_depth = depth - depth = 1 - top_mod = self - mods = [ - ivy.Container.cont_flatten_key_chain(top_mod.__repr__(), replacement="_") - ] - while ivy.exists(top_mod.top_mod): - top_mod = top_mod.top_mod(1) - mods.append( - ivy.Container.cont_flatten_key_chain( - top_mod.__repr__(), replacement="_" + return + elif isinstance(obj, (list, tuple)): + for i, val in enumerate(obj): + self._wrap_call_methods( + keychain_mappings, + key=f"{key}/v{str(i)}", + obj=val, + _visited=_visited, ) - ) - if depth == max_depth: - break - depth += 1 - if flatten_key_chain: - return "__".join(reversed(mods)) - return [mod for mod in reversed(mods)] - - def show_mod_in_top_mod( - self, /, *, upper_depth=None, lower_depth=None, flatten_key_chains=False - ): - """ - Show lower submodules in the top module. `upper_depth` and `lower_depth` are for - controlling the coverage of upper and lower modules. Will give prompt if no top - module found. + return + elif isinstance(obj, dict): + for k, val in obj.items(): + k = f"{key}/{k}" if key != "" and isinstance(k, str) else k + self._wrap_call_methods( + keychain_mappings, key=k, obj=val, _visited=_visited + ) + return + if not hasattr(obj, "__dict__"): + return + for k, val in obj.__dict__.items(): + if k[0:2] == "__": + continue + k = f"{key}/{k}" if key != "" else k + if val is not None: + self._wrap_call_methods( + keychain_mappings, key=k, obj=val, _visited=_visited + ) + return - Parameters - ---------- - upper_depth - How many modules it tracks up as upper module. None for current module. - Default is ``None``. Will be truncated to mod_depth. - lower_depth - How many modules it tracks down. None for current module. - Default is ``None``. Will be truncated to mod_height. - flatten_key_chains - If set True, will return a flat (depth-1) container, - which all nested key-chains flattened. Default is ``False``. - """ - if ivy.exists(self.top_mod): - upper_depth = ivy.default(upper_depth, self.mod_depth()) - lower_depth = ivy.default(lower_depth, self.mod_height()) - mid_depth = upper_depth + lower_depth - upper_sub_mods = self.top_mod(upper_depth).sub_mods(depth=mid_depth) - lower_sub_mods = self.sub_mods(depth=lower_depth) - if flatten_key_chains: - upper_sub_mods = upper_sub_mods.cont_flatten_key_chains() - lower_sub_mods = lower_sub_mods.cont_flatten_key_chains() - upper_sub_mods.cont_show_sub_container(lower_sub_mods) - else: - print( - "self.top_mod must be initialized in order to show mod in top_mod,but" - f" found\n\ntop_mod: {self.top_mod}" - ) - - def _add_submod_ret(self, ret, /): - """ - Add returns to submod_rets variable of the top module. + def _call(self, *args, v=None, buffers=None, **kwargs): + """Compute forward pass of the layer, treating layer instance as + callable function. Parameters ---------- - ret - The return to be added. - """ - top_mod = self.top_mod() - sr = top_mod.submod_rets - ret = ivy.to_numpy(ret) - key = self.get_mod_key(top_mod=top_mod) - if key in sr: - sr[key].append(ret) - else: - sr[key] = [ret] - - def _check_submod_ret(self): - """ - Check the actual submodule returns with the expected submodule return values. - - Raise AssertError if returns are not close enough. - """ - top_mod = self.top_mod() - esr = top_mod.expected_submod_rets - key = self.get_mod_key(top_mod=top_mod) - esr_key = key - if key not in esr: - esr_key = key.replace(" ", "") - if esr_key not in esr: - return - sr = self.top_mod().submod_rets - rets = sr[key] - esr_ret = esr[esr_key] - if isinstance(esr_ret, dict): - expected_rets = esr_ret["val"] - atols = esr_ret["atol"] if "atol" in esr_ret else None - if not isinstance(atols, list): - atols = [atols] * len(expected_rets) - rtols = esr_ret["rtol"] if "rtol" in esr_ret else None - if not isinstance(rtols, list): - rtols = [rtols] * len(expected_rets) - else: - expected_rets = esr_ret - atols = [None] * len(expected_rets) - rtols = [None] * len(expected_rets) - for ret, expected_ret, atol, rtol in zip(rets, expected_rets, atols, rtols): - if expected_ret is None: - continue - kwargs = {} - if atol: - kwargs["atol"] = atol - if rtol: - kwargs["rtol"] = rtol - ivy.utils.assertions.check_true( - np.allclose(ret, expected_ret, **kwargs), - message=( - f"ret: {ret} and expected_ret: {expected_ret} were not close enough" - ), - ) - - # noinspection PyProtectedMember - def _is_submod_leaf(self): - """ - Check if the submodule is the leaf node of the network. + args + Positional arguments to the _build method. + v + Replace `v` of current layer when forwarding. Restore + after the forward finished. + buffers + Replace `v` of current layer when forwarding. Restore + after the forward finished. + kwargs + Keyword arguments to the _build method. Returns ------- ret - True if the submodule is the leaf node of the network. - """ - submod_depth = self.top_mod()._submod_depth - submods_to_track = self.top_mod()._submods_to_track - return ( - (ivy.exists(submod_depth) and self.mod_depth() == submod_depth) - or self.mod_height() == 0 - or (ivy.exists(submods_to_track) and self in submods_to_track) - ) - - def _add_submod_enter(self): - """Add key chains to submod_call_order variable of the top module.""" - sco = self.top_mod().submod_call_order - key_chain = self.mod_with_top_mod_key_chain() - for key in key_chain[:-1]: - kcs = sco.cont_key_chains_containing(key, include_empty=True) - if kcs: - max_key = sorted( - kcs, - key=lambda kc: int( - kc.split("/")[ - -2 if isinstance(sco[kc], np.ndarray) else -1 - ].split("_")[-1] - ), - )[-1].split("/")[0] - else: - max_key = f"{key}_0" - sco[max_key] = ivy.Container( - alphabetical_keys=False, ivyh=ivy.with_backend("numpy") - ) - sco = sco[max_key] - final_key = key_chain[-1] - kcs = sco.cont_key_chains_containing(final_key, include_empty=True) - if kcs: - sorted_kcs = sorted( - kcs, - key=lambda kc: int( - kc.split("/")[-2 if isinstance(sco[kc], np.ndarray) else -1].split( - "_" - )[-1] - ), - ) - chosen_kc = sorted_kcs[-1] - max_key_idx = int( - chosen_kc.split("/")[ - -2 if isinstance(sco[chosen_kc], np.ndarray) else -1 - ].split("_")[-1] - ) - new_key = f"{final_key}_{max_key_idx + 1}" - else: - new_key = f"{final_key}_0" - if self._is_submod_leaf(): - sco[new_key] = self.v_with_top_v_key_chains( - flatten_key_chains=True - ).to_numpy() - else: - sco[new_key] = ivy.Container( - alphabetical_keys=False, ivyh=ivy.with_backend("numpy") + Result of the forward pass of the layer. + """ + if not self._built: + first_arr = _get_first_array(*args, **kwargs) + self.build( + *args, + **kwargs, + from_call=True, + dtype=first_arr.dtype if ivy.exists(first_arr) else ivy.default_dtype(), ) - def show_structure(self): - """ - Print the structure of the layer network. - - Returns - ------- - this_repr - String of the structure of the module. - """ - this_repr = termcolor.colored(object.__repr__(self), "green") - sub_mod_repr = self.sub_mods(show_v=False).__repr__() - if sub_mod_repr == "''": - return this_repr - print("\n".join([this_repr, sub_mod_repr])) + # If `v` was provided, replace with the module's v + replace_v = False + if v is not None: + v_orig = self.v + self._v = v + replace_v = True + + # If `buffers` were provided, replace with the module's buffers + replace_buffers = False + if buffers is not None: + buffers_orig = self.buffers + self._buffers = buffers + replace_buffers = True + + if replace_v or replace_buffers: + # Call the forward pass + ret = self._forward(*args, **kwargs) + # Replace v, buffers if needed + self._v = v_orig if replace_v else self._v + self._buffers = buffers_orig if replace_buffers else self._buffers + return ret + elif hasattr(self.__call__, "wrapped"): + return self.__call__(*args, **kwargs) + return self._forward(*args, **kwargs) + + def _rebuild(self): + logging.warning( + "Building the module again as a trainable module was modified, " + 'please use the "explicit" or "on_call" build_modes instead ' + 'of "on_init" to avoid repetitive building after each addition' + ) + self._v = Container() + self._built = False + self.build(*self._args, **self._kwargs) + + def _compute_module_dict(self): + self._module_dict = Container() + for key, value in self.__dict__.items(): + if isinstance(value, ivy.Module): + if "stateful" in value.__module__ or hasattr(value, "_frontend_module"): + self._module_dict[key] = value + else: + self._module_dict[key] = value._module_dict + + @staticmethod + def _addindent(s_, numSpaces): + s = s_.split("\n") + # don't do anything for single-line stuff + if len(s) == 1: + return s_ + first = s.pop(0) + s = [(numSpaces * " ") + line for line in s] + s = "\n".join(s) + s = first + "\n" + s + return s + + def _fn_with_var_arg_wrapper( + self, *a, fn, v_fn, keychain_mappings, orig_key_chain, **kw + ): + if "v" in kw: + del kw["v"] + v = v_fn(self.v, keychain_mappings, orig_key_chain) + return fn(*a, **kw, v=v) + + def _fn_with_var_arg(self, fn, v_fn, /, keychain_mappings, orig_key_chain): + """Extract variables from `v_fn` and use it as inputs for `fn`. + + Use `v_fn` to extract the variables and use the extracted + variables as inputs to the call function fn of the module. + """ + _fn_with_var_arg_wrapper = functools.partial( + self._fn_with_var_arg_wrapper, + fn=fn, + v_fn=v_fn, + keychain_mappings=keychain_mappings, + orig_key_chain=orig_key_chain, + ) + _fn_with_var_arg_wrapper.wrapped = True + return _fn_with_var_arg_wrapper def _convert_tensors_to_numpy(self): - """ - Recursively traverses the _sub_mods attribute of a Module object and converts - every container containing tensors to numpy using the to_numpy() method. + """Recursively traverses the module_dict attribute of a Module object + and converts every container containing tensors to numpy using the + to_numpy() method. Returns ------- Module The converted Module object. """ - if len(self._sub_mods) > 0: - for sub_mod in self._sub_mods: - sub_mod._convert_tensors_to_numpy() + if self.module_dict: + for module in self.module_dict.values(): + module._convert_tensors_to_numpy() self.v = self.v.to_numpy() def _convert_numpy_to_tensors(self): - """ - Recursively traverses the _sub_mods attribute of a Module object and converts - every container containing tensors to numpy using the to_numpy() method. + """Recursively traverses the module_dict attribute of a Module object + and converts every container containing tensors to numpy using the + to_numpy() method. Returns ------- Module The converted Module object. """ - if len(self._sub_mods) > 0: - for sub_mod in self._sub_mods: - sub_mod._convert_numpy_to_tensors() + if self.module_dict: + for module in self.module_dict.values(): + module._convert_numpy_to_tensors() self.v = self.v.to_ivy() else: self.v = self.v.to_ivy() diff --git a/ivy/stateful/initializers.py b/ivy/stateful/initializers.py index 1481fce608f80..5f2f0a7907add 100644 --- a/ivy/stateful/initializers.py +++ b/ivy/stateful/initializers.py @@ -12,8 +12,7 @@ class Initializer(abc.ABC): - """ - An initializer for internal variables for a layer. + """An initializer for internal variables for a layer. A neuron is a function of the form `a = g(z)`, where `g` is the activation functions and `z = w_1x_1 + w_2x_2 + ... + w_nx_n` where the @@ -31,8 +30,7 @@ def create_variables( fan_in: Optional[float] = None, dtype: Optional[Union[ivy.Dtype, ivy.NativeDtype]] = None, ) -> ivy.Array: - """ - Create internal variables for the layer. + """Create internal variables for the layer. Parameters ---------- @@ -59,8 +57,8 @@ def create_variables( class Constant(Initializer): def __init__(self, constant: float): - """ - Constant initializer, will fill in all values with the value of `constant`. + """Constant initializer, will fill in all values with the value of + `constant`. Parameters ---------- @@ -100,9 +98,9 @@ def __init__(self): class Uniform(Initializer): def __init__(self, numerator, fan_mode, power, gain): - """ - Initialize based on a uniform distribution, will fill in all values with values - drawn from a uniform (all values have an equal probability) distribution. + """Initialize based on a uniform distribution, will fill in all values + with values drawn from a uniform (all values have an equal probability) + distribution. with range `[-wlim, wlim]` (endpoints included) with `wlim` being calculated as `gain * (numerator / fan)**power`. This distribution helps with issues when @@ -141,8 +139,7 @@ def __init__(self, numerator, fan_mode, power, gain): def create_variables( self, var_shape, device, fan_out=None, fan_in=None, dtype=None ): - """ - Create internal variables for the layer. + """Create internal variables for the layer. Parameters ---------- @@ -215,8 +212,8 @@ def create_variables( class GlorotUniform(Uniform): def __init__(self): - """ - Initialize Glorot uniform, also known as the Xavier uniform initializer. + """Initialize Glorot uniform, also known as the Xavier uniform + initializer. It draws values from a uniform distribution `[-limit, limit]` where `limit = sqrt(6 / (fan_in + fan_out))` where `fan_in` and `fan_out` are the @@ -227,8 +224,7 @@ def __init__(self): class FirstLayerSiren(Uniform): def __init__(self): - """ - Initialize Siren uniform for the first layer. + """Initialize Siren uniform for the first layer. It draws values from a uniform distribution `[-limit, limit]` where `limit=fan_in` where `fan_in` is the number of input @@ -239,8 +235,7 @@ def __init__(self): class Siren(Uniform): def __init__(self, w0=30): - """ - Initialize Siren uniform initializer for the first layer. + """Initialize Siren uniform initializer for the first layer. It draws values from a uniform distribution `[-limit, limit]` where `limit=sqrt(6 / fan_in) / w0` where `fan_in` is the number @@ -255,8 +250,7 @@ def __init__(self, w0=30): class KaimingNormal(Initializer): def __init__(self, mean=0, fan_mode="fan_in"): - """ - Initialize Kaiming normal, also known as He Initialization. + """Initialize Kaiming normal, also known as He Initialization. It is an method for initializing layers that takes into account the non-linearity of activation functions. It uses a normal distribution centered @@ -292,8 +286,7 @@ def create_variables( negative_slope=0.0, dtype=None, ): - """ - Create internal variables for the layer. + """Create internal variables for the layer. Parameters ---------- @@ -369,8 +362,7 @@ def create_variables( class RandomNormal(Initializer): def __init__(self, mean=0.0, stddev=0.05, seed=None): - """ - Initialize with Random Normal Distribution. + """Initialize with Random Normal Distribution. It draws values from a Random Normal Distribution with given mean and standard deviation. @@ -394,8 +386,7 @@ def create_variables( device=None, dtype=None, ): - """ - Create internal variables for the layer. + """Create internal variables for the layer. Parameters ---------- diff --git a/ivy/stateful/layers.py b/ivy/stateful/layers.py index 17db6118a9a4c..6dd606c1c6529 100644 --- a/ivy/stateful/layers.py +++ b/ivy/stateful/layers.py @@ -28,11 +28,11 @@ def __init__( v=None, dtype=None, ): - """ - Linear layer, also referred to as dense or fully connected. The layer receives - tensors with input_channels last dimension and returns a new tensor with - output_channels last dimension, following matrix multiplication with the weight - matrix and addition with the bias vector. + """Linear layer, also referred to as dense or fully connected. The + layer receives tensors with input_channels last dimension and returns a + new tensor with output_channels last dimension, following matrix + multiplication with the weight matrix and addition with the bias + vector. Parameters ---------- @@ -65,9 +65,8 @@ def __init__( self._with_bias = with_bias Module.__init__(self, device=device, v=v, dtype=dtype) - def _create_variables(self, device, dtype=None): - """ - Create internal variables for the layer. + def _create_variables(self, device=None, dtype=None): + """Create internal variables for the layer. Parameters ---------- @@ -78,6 +77,8 @@ def _create_variables(self, device, dtype=None): the desired data type of the internal variables to be created if not provided. Default is ``None``. """ + device = ivy.default(device, self.device) + dtype = ivy.default(dtype, self.dtype) v = { "w": self._w_init.create_variables( self._w_shape, @@ -101,8 +102,7 @@ def _create_variables(self, device, dtype=None): return v def _forward(self, x): - """ - Perform forward pass of the Linear layer. + """Perform forward pass of the Linear layer. Parameters ---------- @@ -117,7 +117,7 @@ def _forward(self, x): """ return ivy.linear(x, self.v.w, bias=self.v.b if self._with_bias else None) - def extra_repr(self) -> str: + def _extra_repr(self) -> str: return ( f"in_features={self._input_channels}, out_features={self._output_channels}," f" with_bias={self._with_bias is True}" @@ -136,9 +136,9 @@ def __init__( dtype=None, training: bool = True, ): - """ - Dropout layer. The layer randomly zeroes some of the elements of the input - tensor with probability p using samples from a Bernoull distribution. + """Dropout layer. The layer randomly zeroes some of the elements of the + input tensor with probability p using samples from a Bernoull + distribution. Parameters ---------- @@ -157,8 +157,7 @@ def __init__( Module.__init__(self, device=None, v=None, dtype=dtype, training=training) def _create_variables(self, device, dtype=None): - """ - Create internal variables for the layer. + """Create internal variables for the layer. Parameters ---------- @@ -172,8 +171,7 @@ def _create_variables(self, device, dtype=None): return {} def _forward(self, inputs, dtype=None): - """ - Perform forward pass of the Linear layer. + """Perform forward pass of the Linear layer. Parameters ---------- @@ -193,7 +191,7 @@ def _forward(self, inputs, dtype=None): inputs, self._prob, scale=self._scale, training=self.training, dtype=dtype ) - def extra_repr(self) -> str: + def _extra_repr(self) -> str: s = "prob={prob}" if not self._scale: s += ", scale={scale}" @@ -224,8 +222,7 @@ def __init__( dtype=None, training=True, ): - """ - Multi Head Attention layer. + """Multi Head Attention layer. Parameters ---------- @@ -303,7 +300,7 @@ def __init__( training=training, ) - def _create_variables(self, device, dtype=None): + def _create_variables(self, device=None, dtype=None): """ Parameters ---------- @@ -314,6 +311,8 @@ def _create_variables(self, device, dtype=None): the desired data type of the internal variables to be created if not provided. Default is ``None``. """ + device = ivy.default(device, self.device) + dtype = ivy.default(dtype, self.dtype) v = dict( out_proj_weights=GlorotUniform().create_variables( (self._embed_dim, self._inner_dim), @@ -388,8 +387,7 @@ def _forward( return_attention_weights=False, average_attention_weights=True, ): - """ - Perform forward pass of the MultiHeadAttention layer. + """Perform forward pass of the MultiHeadAttention layer. Parameters ---------- @@ -448,6 +446,15 @@ def _forward( training=self.training, ) + def _extra_repr(self) -> str: + return ( + f"embed_dim={self._embed_dim}, key_dim={self._key_dim}, " + f"value_dim={self._value_dim}, num_heads={self.num_heads}, " + f"head_dim={self._head_dim}, dropout_rate={self.dropout_rate}, " + f"use_proj_bias={self._use_proj_bias}, " + f"attention_axes={self._attention_axes}, scale={self._scale}" + ) + # Convolutions # # -------------# @@ -472,8 +479,7 @@ def __init__( v=None, dtype=None, ): - """ - 1D convolutional layer. + """1D convolutional layer. Parameters ---------- @@ -524,9 +530,8 @@ def __init__( self._dilations = dilations Module.__init__(self, device=device, v=v, dtype=dtype) - def _create_variables(self, device, dtype=None): - """ - Create internal variables for the layer. + def _create_variables(self, device=None, dtype=None): + """Create internal variables for the layer. Parameters ---------- @@ -537,6 +542,8 @@ def _create_variables(self, device, dtype=None): the desired data type of the internal variables to be created. Default is ``None``. """ + device = ivy.default(device, self.device) + dtype = ivy.default(dtype, self.dtype) v = { "w": self._w_init.create_variables( self._w_shape, @@ -560,8 +567,7 @@ def _create_variables(self, device, dtype=None): return v def _forward(self, inputs): - """ - Perform forward pass of the Conv1D layer. + """Perform forward pass of the Conv1D layer. Parameters ---------- @@ -582,7 +588,7 @@ def _forward(self, inputs): dilations=self._dilations, ) + (self.v.b if self._with_bias else 0) - def extra_repr(self): + def _extra_repr(self): s = ( "{_input_channels}, {_output_channels}, filter_size={_filter_size}," " strides={_strides}, padding={_padding}" @@ -616,8 +622,7 @@ def __init__( v=None, dtype=None, ): - """ - 1D transpose convolutional layer. + """1D transpose convolutional layer. Parameters ---------- @@ -659,7 +664,7 @@ def __init__( self._filter_size = filter_size self._strides = strides self._padding = padding - self._w_shape = (filter_size, input_channels, output_channels) + self._w_shape = (filter_size, output_channels, input_channels) self._b_shape = ( (1, 1, output_channels) if data_format == "NWC" else (1, output_channels, 1) ) @@ -672,8 +677,7 @@ def __init__( Module.__init__(self, device=device, v=v, dtype=dtype) def _create_variables(self, device, dtype=None): - """ - Create internal variables for the layer. + """Create internal variables for the layer. Parameters ---------- @@ -684,6 +688,8 @@ def _create_variables(self, device, dtype=None): the desired data type of the internal variables to be created if not provided. Default is ``None``. """ + device = ivy.default(device, self.device) + dtype = ivy.default(dtype, self.dtype) v = { "w": self._w_init.create_variables( self._w_shape, @@ -707,8 +713,7 @@ def _create_variables(self, device, dtype=None): return v def _forward(self, inputs): - """ - Perform forward pass of the Conv1DTranspose layer. + """Perform forward pass of the Conv1DTranspose layer. Parameters ---------- @@ -730,7 +735,7 @@ def _forward(self, inputs): dilations=self._dilations, ) + (self.v.b if self._with_bias else 0) - def extra_repr(self): + def _extra_repr(self): s = ( "{_input_channels}, {_output_channels}, filter_size={_filter_size}," " strides={_strides}, padding={_padding}" @@ -765,8 +770,7 @@ def __init__( v=None, dtype=None, ): - """ - 2D convolutional layer. + """2D convolutional layer. Parameters ---------- @@ -820,8 +824,7 @@ def __init__( Module.__init__(self, device=device, v=v, dtype=dtype) def _create_variables(self, device, dtype=None): - """ - Create internal variables for the layer. + """Create internal variables for the layer. Parameters ---------- @@ -832,6 +835,8 @@ def _create_variables(self, device, dtype=None): the desired data type of the internal variables to be created. Default is ``None``. """ + device = ivy.default(device, self.device) + dtype = ivy.default(dtype, self.dtype) v = { "w": self._w_init.create_variables( self._w_shape, @@ -855,8 +860,7 @@ def _create_variables(self, device, dtype=None): return v def _forward(self, inputs): - """ - Perform forward pass of the Conv2D layer. + """Perform forward pass of the Conv2D layer. Parameters ---------- @@ -877,7 +881,7 @@ def _forward(self, inputs): dilations=self._dilations, ) + (self.v.b if self._with_bias else 0) - def extra_repr(self): + def _extra_repr(self): s = ( "{_input_channels}, {_output_channels}, filter_shape={_filter_shape}," " strides={_strides}, padding={_padding}" @@ -911,8 +915,7 @@ def __init__( v=None, dtype=None, ): - """ - 2D convolutional transpose layer. + """2D convolutional transpose layer. Parameters ---------- @@ -954,7 +957,7 @@ def __init__( self._filter_shape = filter_shape self._strides = strides self._padding = padding - self._w_shape = filter_shape + [input_channels, output_channels] + self._w_shape = filter_shape + [output_channels, input_channels] self._b_shape = ( (1, 1, 1, output_channels) if data_format == "NHWC" @@ -969,8 +972,7 @@ def __init__( Module.__init__(self, device=device, v=v, dtype=dtype) def _create_variables(self, device, dtype=None): - """ - Create internal variables for the layer. + """Create internal variables for the layer. Parameters ---------- @@ -981,6 +983,8 @@ def _create_variables(self, device, dtype=None): the desired data type of the internal variables to be created if not provided. Default is ``None``. """ + device = ivy.default(device, self.device) + dtype = ivy.default(dtype, self.dtype) v = { "w": self._w_init.create_variables( self._w_shape, @@ -1004,8 +1008,7 @@ def _create_variables(self, device, dtype=None): return v def _forward(self, inputs): - """ - Perform forward pass of the Conv2DTranspose layer. + """Perform forward pass of the Conv2DTranspose layer. Parameters ---------- @@ -1027,7 +1030,7 @@ def _forward(self, inputs): dilations=self._dilations, ) + (self.v.b if self._with_bias else 0) - def extra_repr(self): + def _extra_repr(self): s = ( "{_input_channels}, {_output_channels}, filter_shape={_filter_shape}," " strides={_strides}, padding={_padding}" @@ -1061,8 +1064,7 @@ def __init__( v=None, dtype=None, ): - """ - Depthwise 2D convolutional layer. + """Depthwise 2D convolutional layer. Parameters ---------- @@ -1113,8 +1115,7 @@ def __init__( Module.__init__(self, device=device, v=v, dtype=dtype) def _create_variables(self, device, dtype): - """ - Create internal variables for the layer. + """Create internal variables for the layer. Parameters ---------- @@ -1125,6 +1126,8 @@ def _create_variables(self, device, dtype): the desired data type of the internal variables to be created if not provided. Default is ``None``. """ + device = ivy.default(device, self.device) + dtype = ivy.default(dtype, self.dtype) v = { "w": self._w_init.create_variables( self._w_shape, @@ -1148,8 +1151,7 @@ def _create_variables(self, device, dtype): return v def _forward(self, inputs): - """ - Perform forward pass of the DepthwiseConv2D layer. + """Perform forward pass of the DepthwiseConv2D layer. Parameters ---------- @@ -1170,7 +1172,7 @@ def _forward(self, inputs): dilations=self._dilations, ) + (self.v.b if self._with_bias else 0) - def extra_repr(self): + def _extra_repr(self): s = ( "num_channels={_num_channels}, filter_shape={_filter_shape}," " strides={_strides}, padding={_padding}" @@ -1203,8 +1205,7 @@ def __init__( v=None, dtype=None, ): - """ - 3D convolutional layer. + """3D convolutional layer. Parameters ---------- @@ -1258,8 +1259,7 @@ def __init__( Module.__init__(self, device=device, v=v, dtype=dtype) def _create_variables(self, device, dtype=None): - """ - Create internal variables for the layer. + """Create internal variables for the layer. Parameters ---------- @@ -1270,6 +1270,8 @@ def _create_variables(self, device, dtype=None): the desired data type of the internal variables to be created if not provided. Default is ``None``. """ + device = ivy.default(device, self.device) + dtype = ivy.default(dtype, self.dtype) v = { "w": self._w_init.create_variables( self._w_shape, @@ -1293,8 +1295,7 @@ def _create_variables(self, device, dtype=None): return v def _forward(self, inputs): - """ - Perform forward pass of the Conv3D layer. + """Perform forward pass of the Conv3D layer. Parameters ---------- @@ -1316,7 +1317,7 @@ def _forward(self, inputs): dilations=self._dilations, ) + (self.v.b if self._with_bias else 0) - def extra_repr(self): + def _extra_repr(self): s = ( "{_input_channels}, {_output_channels}, filter_shape={_filter_shape}," " strides={_strides}, padding={_padding}" @@ -1350,8 +1351,7 @@ def __init__( v=None, dtype=None, ): - """ - 3D convolutional transpose layer. + """3D convolutional transpose layer. Parameters ---------- @@ -1393,7 +1393,7 @@ def __init__( self._filter_shape = filter_shape self._strides = strides self._padding = padding - self._w_shape = filter_shape + [input_channels, output_channels] + self._w_shape = filter_shape + [output_channels, input_channels] self._b_shape = ( (1, 1, 1, 1, output_channels) if data_format == "NDHWC" @@ -1409,8 +1409,7 @@ def __init__( Module.__init__(self, device=device, v=v, dtype=dtype) def _create_variables(self, device, dtype=None): - """ - Create internal variables for the layer. + """Create internal variables for the layer. Parameters ---------- @@ -1421,6 +1420,8 @@ def _create_variables(self, device, dtype=None): the desired data type of the internal variables to be created if not provided. Default is ``None``. """ + device = ivy.default(device, self.device) + dtype = ivy.default(dtype, self.dtype) v = { "w": self._w_init.create_variables( self._w_shape, @@ -1444,8 +1445,7 @@ def _create_variables(self, device, dtype=None): return v def _forward(self, inputs): - """ - Perform forward pass of the Conv3DTranspose layer. + """Perform forward pass of the Conv3DTranspose layer. Parameters ---------- @@ -1468,7 +1468,7 @@ def _forward(self, inputs): dilations=self._dilations, ) + (self.v.b if self._with_bias else 0) - def extra_repr(self): + def _extra_repr(self): s = ( "{_input_channels}, {_output_channels}, filter_shape={_filter_shape}," " strides={_strides}, padding={_padding}" @@ -1503,8 +1503,7 @@ def __init__( v=None, dtype=None, ): - """ - LSTM layer, which is a set of stacked lstm cells. + """LSTM layer, which is a set of stacked lstm cells. Parameters ---------- @@ -1544,8 +1543,8 @@ def __init__( # Public # def get_initial_state(self, batch_shape, dtype=None): - """ - Get the initial state of the hidden and cell states, if not provided explicitly. + """Get the initial state of the hidden and cell states, if not provided + explicitly. Parameters ---------- @@ -1554,6 +1553,7 @@ def get_initial_state(self, batch_shape, dtype=None): the desired data type of the internal variables to be created if not provided. Default is ``None``. """ + dtype = ivy.default(dtype, self.dtype) batch_shape = list(batch_shape) return ( [ @@ -1568,9 +1568,8 @@ def get_initial_state(self, batch_shape, dtype=None): # Overridden - def _create_variables(self, device, dtype=None): - """ - Create internal variables for the layer. + def _create_variables(self, device=None, dtype=None): + """Create internal variables for the layer. Parameters ---------- @@ -1581,6 +1580,8 @@ def _create_variables(self, device, dtype=None): the desired data type of the internal variables to be created if not provided. Default is ``None``. """ + device = ivy.default(device, self.device) + dtype = ivy.default(dtype, self.dtype) input_weights = dict( zip( [f"layer_{str(i)}" for i in range(self._num_layers)], @@ -1626,8 +1627,7 @@ def _create_variables(self, device, dtype=None): @handle_nestable def _forward(self, inputs, initial_state=None): - """ - Perform forward pass of the LSTM layer. + """Perform forward pass of the LSTM layer. Parameters ---------- @@ -1668,7 +1668,7 @@ def _forward(self, inputs, initial_state=None): return h_t return h_t, (h_n_list, c_n_list) - def extra_repr(self): + def _extra_repr(self): s = "{_input_channels}, {_output_channels}" if self._num_layers != 1: s += ", num_layers={_num_layers}" @@ -1696,8 +1696,7 @@ def __init__( v=None, dtype=None, ): - """ - Class for applying Max Pooling over a mini-batch of inputs. + """Class for applying Max Pooling over a mini-batch of inputs. Parameters ---------- @@ -1717,8 +1716,7 @@ def __init__( Module.__init__(self, device=device, dtype=dtype) def _forward(self, inputs): - """ - Forward pass of the layer. + """Forward pass of the layer. Parameters ---------- @@ -1737,7 +1735,7 @@ def _forward(self, inputs): data_format=self._data_format, ) - def extra_repr(self): + def _extra_repr(self): s = "kernel_size={_kernel_size}, stride={_stride}, padding={_padding}" if self._data_format != "NHWC": s += ", data_format={_data_format}" @@ -1757,8 +1755,7 @@ def __init__( v=None, dtype=None, ): - """ - Class for applying Average Pooling over a mini-batch of inputs. + """Class for applying Average Pooling over a mini-batch of inputs. Parameters ---------- @@ -1778,8 +1775,7 @@ def __init__( Module.__init__(self, device=device, dtype=dtype) def _forward(self, inputs): - """ - Forward pass of the layer. + """Forward pass of the layer. Parameters ---------- @@ -1798,7 +1794,7 @@ def _forward(self, inputs): data_format=self._data_format, ) - def extra_repr(self): + def _extra_repr(self): s = "kernel_size={_kernel_size}, stride={_stride}, padding={_padding}" if self._data_format != "NHWC": s += ", data_format={_data_format}" @@ -1818,8 +1814,7 @@ def __init__( v=None, dtype=None, ): - """ - Class for applying Max Pooling over a mini-batch of inputs. + """Class for applying Max Pooling over a mini-batch of inputs. Parameters ---------- @@ -1839,8 +1834,7 @@ def __init__( Module.__init__(self, device=device, dtype=dtype) def _forward(self, inputs): - """ - Forward pass of the layer. + """Forward pass of the layer. Parameters ---------- @@ -1859,7 +1853,7 @@ def _forward(self, inputs): data_format=self._data_format, ) - def extra_repr(self): + def _extra_repr(self): s = "kernel_size={_kernel_size}, stride={_stride}, padding={_padding}" if self._data_format != "NHWC": s += ", data_format={_data_format}" @@ -1878,8 +1872,7 @@ def __init__( device=None, dtype=None, ): - """ - Class for applying 3D Max Pooling over 5D inputs. + """Class for applying 3D Max Pooling over 5D inputs. Parameters ---------- @@ -1897,8 +1890,7 @@ def __init__( Module.__init__(self, device=device, dtype=dtype) def _forward(self, x): - """ - Forward pass of the layer. + """Forward pass of the layer. Parameters ---------- @@ -1917,7 +1909,7 @@ def _forward(self, x): data_format=self._data_format, ) - def extra_repr(self): + def _extra_repr(self): s = "kernel_size={_kernel_size}, stride={_stride}, padding={_padding}" if self._data_format != "NDHWC": s += ", data_format={_data_format}" @@ -1937,8 +1929,7 @@ def __init__( ceil_mode=False, divisor_override=None, ): - """ - Class for applying Average Pooling over a mini-batch of inputs. + """Class for applying Average Pooling over a mini-batch of inputs. Parameters ---------- @@ -1968,8 +1959,7 @@ def __init__( Module.__init__(self) def _forward(self, x): - """ - Forward pass of the layer. + """Forward pass of the layer. Parameters ---------- @@ -1991,7 +1981,7 @@ def _forward(self, x): divisor_override=self._divisor_override, ) - def extra_repr(self): + def _extra_repr(self): s = "kernel_size={_kernel_size}, stride={_stride}, padding={_padding}" if self._data_format != "NDHWC": s += ", data_format={_data_format}" @@ -2009,25 +1999,30 @@ class AdaptiveAvgPool2d(Module): def __init__( self, output_size, + /, + *, + data_format="NHWC", device=None, dtype=None, ): - """ - Class for applying a 2D adaptive average pooling over mini-batch of inputs. + """Class for applying a 2D adaptive average pooling over mini-batch of + inputs. Parameters ---------- output_size the target output size of the image. + data_format + NHWC" or "NCHW". Defaults to "NHWC". device device on which to create the layer's variables 'cuda:0', 'cuda:1', 'cpu' """ self._output_size = output_size + self._data_format = data_format Module.__init__(self, device=device, dtype=dtype) def _forward(self, x): - """ - Forward pass of the layer. + """Forward pass of the layer. Parameters ---------- @@ -2041,11 +2036,10 @@ def _forward(self, x): # TODO: test again once adaptive_avg_pool2d is # implemented for the missing backends. return ivy.adaptive_avg_pool2d( - x, - self._output_size, + x, self._output_size, data_format=self._data_format ) - def extra_repr(self): + def _extra_repr(self): return f"output_size={self._output_size}" @@ -2057,8 +2051,8 @@ def __init__( dtype=None, ): # TODO: add data_format param - """ - Class for applying a 1D adaptive average pooling over mini-batch of inputs. + """Class for applying a 1D adaptive average pooling over mini-batch of + inputs. Parameters ---------- @@ -2072,8 +2066,7 @@ def __init__( Module.__init__(self, device=device, dtype=dtype) def _forward(self, x): - """ - Forward pass of the layer. + """Forward pass of the layer. Parameters ---------- @@ -2091,7 +2084,7 @@ def _forward(self, x): self._output_size, ) - def extra_repr(self): + def _extra_repr(self): return f"output_size={self._output_size}" @@ -2107,8 +2100,7 @@ def __init__( device=None, dtype=None, ): - """ - Class for applying FFT to input. + """Class for applying FFT to input. Parameters ---------- @@ -2128,8 +2120,7 @@ def __init__( Module.__init__(self, device=device, dtype=dtype) def _forward(self, inputs): - """ - Forward pass of the layer. + """Forward pass of the layer. Parameters ---------- @@ -2149,7 +2140,7 @@ def _forward(self, inputs): out=self._out, ) - def extra_repr(self): + def _extra_repr(self): s = "dim={_dim}" if self._norm != "backward": s += ", norm={_norm}" @@ -2168,8 +2159,7 @@ def __init__( *, data_format="NWC", ): - """ - Class for applying Average Pooling over a mini-batch of inputs. + """Class for applying Average Pooling over a mini-batch of inputs. Parameters ---------- @@ -2189,8 +2179,7 @@ def __init__( Module.__init__(self) def _forward(self, inputs): - """ - Forward pass of the layer. + """Forward pass of the layer. Parameters ---------- @@ -2209,7 +2198,7 @@ def _forward(self, inputs): data_format=self._data_format, ) - def extra_repr(self): + def _extra_repr(self): s = "kernel_size={_kernel_size}, stride={_stride}, padding={_padding}" if self._data_format != "NWC": s += ", data_format={_data_format}" @@ -2227,8 +2216,8 @@ def __init__( device=None, dtype=None, ): - """ - Class for applying the Discrete Cosine Transform over mini-batch of inputs. + """Class for applying the Discrete Cosine Transform over mini-batch of + inputs. Parameters ---------- @@ -2253,8 +2242,7 @@ def __init__( Module.__init__(self, device=device, dtype=dtype) def _forward(self, x): - """ - Forward pass of the layer. + """Forward pass of the layer. Parameters ---------- @@ -2273,7 +2261,7 @@ def _forward(self, x): norm=self.norm, ) - def extra_repr(self): + def _extra_repr(self): s = "type={type}" if self.n is not None: s += ", n={n}" @@ -2302,10 +2290,9 @@ def __init__( v=None, dtype=None, ): - """ - Class for embedding indices into a dense representation. The Embedding layer is - a simple lookup table for dense vectors. It's typically used to store word - embeddings and query them using indices. + """Class for embedding indices into a dense representation. The + Embedding layer is a simple lookup table for dense vectors. It's + typically used to store word embeddings and query them using indices. Parameters ---------- @@ -2335,9 +2322,8 @@ def __init__( self._weight_initializer = weight_initializer Module.__init__(self, device=device, v=v, dtype=dtype) - def _create_variables(self, device, dtype=None): - """ - Create internal variables for the layer. + def _create_variables(self, device=None, dtype=None): + """Create internal variables for the layer. Parameters ---------- @@ -2348,6 +2334,8 @@ def _create_variables(self, device, dtype=None): the desired data type of the internal variables to be created if not provided. Default is ``None``. """ + device = ivy.default(device, self.device) + dtype = ivy.default(dtype, self.dtype) v = { "w": self._weight_initializer.create_variables( (self._num_embeddings, self._embedding_dim), @@ -2365,8 +2353,7 @@ def _pad_embd(self, indices, embd): return ivy.where(mask, mask_val, embd) def _forward(self, indices): - """ - Forward pass of the layer. + """Forward pass of the layer. Parameters ---------- @@ -2382,7 +2369,7 @@ def _forward(self, indices): emb = self._pad_embd(indices, emb) return emb - def extra_repr(self): + def _extra_repr(self): s = "num_embeddings={_num_embeddings}, embedding_dim={_embedding_dim}" if self._padding_idx is not None: s += ", padding_idx={_padding_idx}" @@ -2393,9 +2380,8 @@ def extra_repr(self): class Identity(Module): def __init__(self): - """ - Identity layer. The layer is argument insensitive and returns the input argument - as output when called. + """Identity layer. The layer is argument insensitive and returns the + input argument as output when called. It's typically used as a placeholder when no operation is to be performed. It doesn't have any learnable parameter. @@ -2403,8 +2389,7 @@ def __init__(self): Module.__init__(self) def _forward(self, x): - """ - Forward pass of the layer. + """Forward pass of the layer. Parameters ---------- @@ -2433,8 +2418,7 @@ def __init__( device=None, dtype=None, ): - """ - Class for applying IFFT to input. + """Class for applying IFFT to input. Parameters ---------- @@ -2460,8 +2444,7 @@ def __init__( Module.__init__(self, device=device, dtype=dtype) def _forward(self, inputs): - """ - Forward pass of the layer. + """Forward pass of the layer. Parameters ---------- @@ -2479,3 +2462,11 @@ def _forward(self, inputs): n=self._n, out=self._out, ) + + def _extra_repr(self): + s = "dim={_dim}" + if self._norm != "backward": + s += ", norm={_norm}" + if self._n is not False: + s += ", n={_n}" + return s.format(**self.__dict__) diff --git a/ivy/stateful/losses.py b/ivy/stateful/losses.py index 5eb65bd03fd78..77a47b94a0d1e 100644 --- a/ivy/stateful/losses.py +++ b/ivy/stateful/losses.py @@ -21,8 +21,7 @@ def __init__( def _forward( self, true, pred, *, compute_full_loss=None, axis=None, reduction=None ): - """ - Perform forward pass of the Log Poisson Loss. + """Perform forward pass of the Log Poisson Loss. true input array containing true labels. @@ -53,6 +52,12 @@ def _forward( reduction=ivy.default(reduction, self._reduction), ) + def _extra_repr(self) -> str: + return ( + f"compute_full_loss={self._compute_full_loss}, axis={self._axis}, " + f"reduction={self._reduction}" + ) + class CrossEntropyLoss(Module): def __init__( @@ -68,8 +73,7 @@ def __init__( Module.__init__(self) def _forward(self, true, pred, *, axis=None, epsilon=None, reduction=None): - """ - Perform forward pass of the Cross Entropy Loss. + """Perform forward pass of the Cross Entropy Loss. true input array containing true labels. @@ -99,6 +103,11 @@ def _forward(self, true, pred, *, axis=None, epsilon=None, reduction=None): reduction=ivy.default(reduction, self._reduction), ) + def _extra_repr(self) -> str: + return ( + f"axis={self._axis}, epsilon={self._epsilon}, reduction={self._reduction}" + ) + class BinaryCrossEntropyLoss(Module): def __init__( @@ -161,3 +170,9 @@ def _forward( pos_weight=pos_weight, axis=axis, ) + + def _extra_repr(self) -> str: + return ( + f"from_logits={self._from_logits}, epsilon={self._epsilon}, " + f"reduction={self._reduction}" + ) diff --git a/ivy/stateful/module.py b/ivy/stateful/module.py index 68f1c425b7658..d8ad7d80455d1 100644 --- a/ivy/stateful/module.py +++ b/ivy/stateful/module.py @@ -2,9 +2,7 @@ # global from collections import OrderedDict -import functools import os -import abc import copy import dill from typing import Optional, Tuple, Dict @@ -12,29 +10,11 @@ # local import ivy from ivy.data_classes.container import Container -from ivy.func_wrapper import _get_first_array from ivy.functional.ivy.gradients import _is_variable from ivy.stateful.helpers import ModuleHelpers from ivy.stateful.converters import ModuleConverters -# helpers -def _addindent(s_, numSpaces): - s = s_.split("\n") - # don't do anything for single-line stuff - if len(s) == 1: - return s_ - first = s.pop(0) - s = [(numSpaces * " ") + line for line in s] - s = "\n".join(s) - s = first + "\n" + s - return s - - -# Base # -# -----# - - class ModuleMeta: def __new__(cls, *args, **kwargs): # check the module of the class @@ -62,109 +42,72 @@ def __init__( self, /, *args, - device=None, v=None, buffers=None, build_mode="on_init", - trace_on_next_step=False, store_vars=True, - stateful=None, - arg_stateful_idxs=None, - kwarg_stateful_idxs=None, - fallback_to_non_traced=False, with_partial_v=False, - devices=None, - dtype=None, dynamic_backend=None, training=True, + dtype=None, + device=None, **kwargs, ): - """ - Initialize Ivy layer, which is a stateful object consisting of trainable - variables. + """Initialize Ivy layer, which is a stateful object consisting of + trainable variables. Parameters ---------- - device - device on which to create the module's variables 'cuda:0', 'cuda:1', 'cpu' - etc. (Default value = None) + args + Positional arguments to the _build method. v Ivy container of trainable variables. Created internally by default. + buffers + Ivy container of buffers/non-trainable arrays in the state_dict. build_mode How the Module is built, either on initialization (now), explicitly by the user by calling build(), or the first time the __call__ method is run. Default is on initialization. - trace_on_next_step - Whether to trace the network in a graph on the next forward pass. - Default is ``False``. store_vars Whether or not to store the variables created. Default is ``True``. - stateful - The constant id stateful items to track as part of the forward pass. - Used when graph compiling, default is ``None``. - arg_stateful_idxs - The nested argument indices of stateful items to track as part of - the forward pass. - Used when graph compiling, default is ``None``. - kwarg_stateful_idxs - The nested keyword argument indices of stateful items to track as part of - the forward pass. Used when graph compiling, default is ``None``. - fallback_to_non_traced - Whether to fall back to non-traced forward call in the case that an error - is raised during the traced forward pass. Default is ``True``. with_partial_v Whether to allow partial specification of variables. Default is ``False``. + dynamic_backend + When the value is true, allow conversion of arrays from a different backend + to the current backend if v passed in the input contains arrays created with + different backend. training specifies whether the module is in training or evaluation mode. Default is ``True``. - devices - devices on which to distribute the module's variables - 'cuda:0', 'cuda:1', 'cpu' etc. (Default value = None) + dtype + Data type to be used for creating model variables. (Default value = None). + device + Device on which to create the module's variables 'cuda:0', 'cuda:1', 'cpu' + etc. (Default value = None). + kwargs + Keyword arguments to the _build method. """ valid_build_modes = ["on_init", "explicit", "on_call"] ivy.utils.assertions.check_elem_in_list(build_mode, valid_build_modes) - self._device = ivy.default( - device, - ivy.default( - lambda: devices[0], - default_val=ivy.default_device(), - catch_exceptions=True, - ), - ) - self._devices = ivy.default(devices, [self._device]) self._build_mode = build_mode - self._stateful = stateful - self._arg_stateful_idxs = arg_stateful_idxs - self._kwarg_stateful_idxs = kwarg_stateful_idxs - self._fallback_to_non_traced = fallback_to_non_traced self._with_partial_v = with_partial_v self._store_vars = store_vars self._built = False - self._traced = False - self._traced_fn = None - self._trace_on_next_step = trace_on_next_step - self._v_in = v if isinstance(v, Container) or v is None else Container(v) - self.v = v - self.top_v = None - self.top_mod = None - self._track_submod_rets = False - self._submod_depth = None - self._submods_to_track = None - self._track_submod_call_order = False - self.expected_submod_rets = None - self.submod_dict = {} - backend = ivy.with_backend("numpy") - self.submod_rets = ivy.Container(alphabetical_keys=False, ivyh=backend) - self.submod_call_order = ivy.Container(alphabetical_keys=False, ivyh=backend) - self._sub_mods = set() - self._dtype = dtype + self._v_from_constructor = ( + v if isinstance(v, Container) or v is None else Container(v) + ) + self._v = v if v is not None else Container() + self._buffers = Container(ivy.default(buffers, {})) + self._module_dict = Container() self._args = args self._kwargs = kwargs self._module_graph = None self._target = None self._lazy_traced = False + self._training = training self._dynamic_backend = dynamic_backend - self.training = training + self._device = ivy.default(device, ivy.default_device()) + self._dtype = ivy.default(dtype, ivy.default_dtype()) if build_mode != "on_init": return if hasattr(Module, "_init_var"): @@ -177,12 +120,7 @@ def __init__( if v or with_partial_v: # build only if `v` or `with_partial_v` - self.build( - *args, - dynamic_backend=dynamic_backend, - buffers=buffers, - **kwargs, - ) + self.build(*args, dynamic_backend=dynamic_backend, **kwargs) # we don't want to delete the class variable now # since there could be other child modules return @@ -197,9 +135,7 @@ def __init__( # move on Module._init_var.pop() return - self.build( - *args, dynamic_backend=dynamic_backend, buffers=buffers, **kwargs - ) + self.build(*args, dynamic_backend=dynamic_backend, **kwargs) if Module._init_var[-1] == self.__class__.__name__: # you delete it, only if this is the class that caused it's creation Module._init_var.pop() @@ -209,485 +145,10 @@ def __init__( del Module._init_var return - self.build(*args, dynamic_backend=dynamic_backend, buffers=buffers, **kwargs) - - # Private # - # --------# - - def _fn_with_var_arg_wrapper( - self, *a, fn, v_fn, keychain_mappings, orig_key_chain, **kw - ): - if "v" in kw: - del kw["v"] - v = v_fn(self.v, keychain_mappings, orig_key_chain) - return fn(*a, **kw, v=v) - - def _fn_with_var_arg(self, fn, v_fn, /, keychain_mappings, orig_key_chain): - """ - Extract variables from `v_fn` and use it as inputs for `fn`. - - Use `v_fn` to extract the variables and use the extracted - variables as inputs to the call function fn of the module. - """ - _fn_with_var_arg_wrapper = functools.partial( - self._fn_with_var_arg_wrapper, - fn=fn, - v_fn=v_fn, - keychain_mappings=keychain_mappings, - orig_key_chain=orig_key_chain, - ) - _fn_with_var_arg_wrapper.wrapped = True - return _fn_with_var_arg_wrapper - - def _find_variables( - self, /, *, obj=None, _visited=None, without_initialisation=False - ): - """ - Find all internal variables in obj. Return empty Container if obj is None. - - Parameters - ---------- - obj - The submodule whose internal variables are to be returned. Default - is None. - _visited - Placeholder for tracking the visited nodes, do not set this parameter. - - Returns - ------- - ret - The internal variables of the submodule passed in the argument. - """ - _visited = ivy.default(_visited, {}) - vs = Container() - if id(obj) in _visited: - return vs - _visited[id(obj)] = True - # ToDo: add support for finding local variables, if/when JAX supports - # uniquely flagging variables - if isinstance(obj, Module) and obj is not self: - obj.top_v = self._top_v_fn - obj.top_mod = self._top_mod_fn - self._sub_mods.add(obj) - - if not obj.built_ and without_initialisation: - return lambda: obj._build_and_return_v( - *obj._args, dynamic_backend=self._dynamic_backend, **obj._kwargs - ) - - return obj._build_and_return_v( - *obj._args, dynamic_backend=obj._dynamic_backend, **obj._kwargs - ) - elif isinstance(obj, (list, tuple)): - for i, v in enumerate(obj): - ret = self._find_variables( - obj=v, - _visited=_visited, - without_initialisation=without_initialisation, - ) - if ret: - vs[f"v{str(i)}"] = ret - return vs - elif isinstance(obj, dict): - for k, v in obj.items(): - ret = self._find_variables( - obj=v, - _visited=_visited, - without_initialisation=without_initialisation, - ) - if ret: - vs[k[1:] if k[0] == "_" else k] = ret - return vs - elif not hasattr(obj, "__dict__"): - return vs - for k, v in obj.__dict__.items(): - if v is not None and k[0:2] != "__": - ret = self._find_variables( - obj=v, - _visited=_visited, - without_initialisation=without_initialisation, - ) - if ret: - vs[k[1:] if k[0] == "_" else k] = ret - return vs - - def _build_and_return_v(self, *args, **kwargs): - self.build(*args, **kwargs) - return self.v - - def _find_child_objects(self, /, *, obj=None, _visited=None): - pass - - def _find_buffers(self): - for obj in self.__dict__.keys(): - if isinstance(getattr(self, obj), ivy.Module): - # simply fetch it's buffer - if hasattr(getattr(self, obj), "buffers"): - self.buffers.update({obj: getattr(self, obj).buffers}) - - @staticmethod - def _extract_v(v, keychain_mappings: dict, orig_key_chain, /): - """ - Extract the variables from the variables container v using the key - orig_key_chain and reinstantiate the duplicate variables that were removed by - _remove_duplicate_variables in their correct locations using keychain_mappings. - - Parameters - ---------- - v - The variables container - keychain_mappings - The keychain mappings of duplicate vatriables - orig_key_chain - keychain of the variables to be extracted - - - Returns - ------- - ret_cont - container with the extracted variables. - """ - if v.cont_has_key_chain(orig_key_chain): - ret_cont = v.cont_at_key_chain(orig_key_chain) - else: - ret_cont = ivy.Container() - for old_kc, new_kc in keychain_mappings.items(): - if orig_key_chain in old_kc: - ret_cont = ret_cont.cont_set_at_key_chain( - "/".join(new_kc.split("/")[1:]), v.cont_at_key_chain(new_kc) - ) - return ret_cont - - def _wrap_call_methods( - self, keychain_mappings, /, *, key="", obj=None, _visited=None - ): - """ - Wrap the call methods of the Module object by looping over all the items within - the module, wrapping the __call__ methods of all submodules using - _fn_with_var_arg. - - Parameters - ---------- - keychain_mappings - The keychain mappings of the object - key - The keychain of the object obj, used for recursion. - obj - the object whose __call__ method is to be wrapped - _visited - Placeholder for tracking the visited nodes, do not set this parameter. - - Returns - ------- - None - """ - _visited = ivy.default(_visited, {}) - if id(obj) in _visited or not isinstance(key, str): - return - _visited[id(obj)] = True - if isinstance(obj, Module) and obj is not self: - orig_key_chain = key[1:] if key[0] == "_" else key - - obj.__call__ = self._fn_with_var_arg( - obj.__call__, self._extract_v, keychain_mappings, orig_key_chain - ) - return - elif isinstance(obj, (list, tuple)): - for i, val in enumerate(obj): - self._wrap_call_methods( - keychain_mappings, - key=f"{key}/v{str(i)}", - obj=val, - _visited=_visited, - ) - return - elif isinstance(obj, dict): - for k, val in obj.items(): - k = f"{key}/{k}" if key != "" and isinstance(k, str) else k - self._wrap_call_methods( - keychain_mappings, key=k, obj=val, _visited=_visited - ) - return - if not hasattr(obj, "__dict__"): - return - for k, val in obj.__dict__.items(): - if k[0:2] == "__": - continue - k = f"{key}/{k}" if key != "" else k - if val is not None: - self._wrap_call_methods( - keychain_mappings, key=k, obj=val, _visited=_visited - ) - return - - @staticmethod - def _remove_duplicate_variables(vs, created, /): - """ - Remove duplicate variables in `vs` referring to `created`. - - Parameters - ---------- - vs - The container that needs to be pruned. - created - The container as the duplication reference. - - Returns - ------- - vs - The container after removing duplicate variables. - keychain_mappings - Dict storing those keys and ids being removed. - """ - created_ids = created.cont_map(lambda x, kc: id(x)) - vs_ids = vs.cont_map(lambda x, kc: id(x)) - ids = {} - duplicate_keychains = [] - keychain_mappings = {} - - def unique_callback(x, kc): - ids[x] = kc - - def found_dup_callback(x, kc): - if ids[x] == kc: - return - duplicate_keychains.append(kc) - keychain_mappings[kc] = ids[x] - - created_ids.cont_map(lambda x, kc: unique_callback(x, kc)) - vs_ids.cont_map( - lambda x, kc: ( - unique_callback(x, kc) if x not in ids else found_dup_callback(x, kc) - ) - ) - for dup_kc in duplicate_keychains: - vs = vs.cont_prune_key_chain(dup_kc) - return vs, keychain_mappings - - def _set_buffers(self, buffers): - """ - Set the buffers of the given class instance, according to the buffers passed. - - Parameters - ---------- - buffers - a dictionary with variable names and corresponding values - - override - if true, sets the variable as an attribute even if it doesn't exist - """ - for buffer in buffers: - if hasattr(self, buffer): - # check if this value is another nested dictionary, if yes - # we recurse - if isinstance(buffers[buffer], dict): - getattr(self, buffer)._set_buffers(buffers=buffers[buffer]) - else: - setattr(self, buffer, buffers[buffer]) - else: - if hasattr(self, "buffers"): - self.buffers.update({buffer: buffers[buffer]}) - else: - setattr(self, "buffers", {buffer: buffers[buffer]}) - setattr(self, buffer, buffers[buffer]) - - # Overridable # - - # noinspection PyMethodMayBeStatic,PyUnusedLocal - def _create_variables(self, *, device=None, dtype=None): - """ - Create internal trainable variables, and return as arbitrary nested dict. - Overridable. - - Parameters - ---------- - device - The device string, specifying the device on which to create the variables. - - Returns - ------- - ret - An empty set. - """ - return {} - - def _build(self, *args, **kwargs) -> bool: - """ - Build the internal layers and variables for this module. Overridable. + self.build(*args, dynamic_backend=dynamic_backend, **kwargs) - Returns - ------- - ret - False or empty Container if the build only partially completed (i.e. some - child Modules have "on_call" build mode). Alternatively, return True or a - container of the built variables if the module is built. - """ - return True - - # Abstract # - - @abc.abstractmethod - def _forward(self, *args, **kwargs): - """ - Forward pass of the layer, called after handling the optional input variables. - - Raises - ------ - NotImplementedError - """ - raise ivy.utils.exceptions.IvyNotImplementedException - - def _forward_with_tracking(self, *args, **kwargs): - """ - Forward pass while optionally tracking submodule returns and call order. - - Returns - ------- - ret - Result of the forward pass of the layer. - """ - if self.track_submod_call_order(): - self._add_submod_enter() - ret = self._forward(*args, **kwargs) - track_submod_rets = self.track_submod_rets() - check_submod_rets = self.check_submod_rets() - if track_submod_rets or check_submod_rets: - self._add_submod_ret(ret) - if check_submod_rets: - self._check_submod_ret() - return ret - - def _call(self, *args, v=None, buffers=None, **kwargs): - """ - Compute forward pass of the layer, treating layer instance as callable function. - - Parameters - ---------- - v - Replace `v` of current layer when forwarding. Restore - after the forward finished. - - Returns - ------- - ret - Result of the forward pass of the layer. - """ - if not self._built: - self.build( - *args, - **kwargs, - from_call=True, - dtype=_get_first_array(*args, **kwargs).dtype, - ) - if buffers: - buffers_orig = self.buffers.copy() - self.buffers = {} - self._set_buffers(buffers) - if v is not None: - v_orig = self.v - self.v = ( - Container(v, **v.cont_config) - if isinstance(v, Container) - else Container(v) - ) - ret = self._forward_with_tracking(*args, **kwargs) - self.v = v_orig - if buffers: - self.buffers = {} - self._set_buffers(buffers_orig) - return ret - - elif hasattr(self.__call__, "wrapped"): - return self.__call__(*args, **kwargs) - return self._forward_with_tracking(*args, **kwargs) - - # Public # - # -------# - def __call__( - self, - *args, - v=None, - buffers=None, - stateful=None, - arg_stateful_idxs=None, - kwarg_stateful_idxs=None, - track_submod_rets=False, - submod_depth=None, - submods_to_track=None, - track_submod_call_order=False, - expected_submod_rets=None, - **kwargs, - ): - """ - Forward an input through current module. - - Parameters - ---------- - v - If given, use this container as internal variables temporarily. - Default is ``None``. - track_submod_rets - If True, will track the returns of submodules. - submod_depth - The depth of tracked submodules. - submods_to_track - If given, will only track submodules in `submods_to_track`. - track_submod_call_order - If True, will track the call order of submodules. - expected_submod_rets - If given, will raise exception if submodule returns are - different from expected returns. - - Returns - ------- - ret - """ - if self._lazy_traced: - # we are creating graph since we want to transpile module, - # so set the appropriate backend - if self._target: - ivy.set_backend(self._target) - self.trace_graph(args=args, kwargs=kwargs) - if self._target: - ivy.previous_backend() - - if self._module_graph: - # we need `v` in kwargs, since this is a traced call - v = v if v else self.v - return self._module_graph(*args, v=v, **kwargs) - - backend = ivy.with_backend("numpy") - self.submod_rets = ivy.Container(alphabetical_keys=False, ivyh=backend) - self.submod_call_order = ivy.Container(alphabetical_keys=False, ivyh=backend) - self._set_submod_flags( - track_submod_rets, - submod_depth, - submods_to_track, - track_submod_call_order, - expected_submod_rets, - ) - - # convert variables to native arrays so that they can be tracked - v = ivy.to_native(v) - ret = self._call(*args, v=v, buffers=buffers, **kwargs) - self._unset_submod_flags() - return ret - - def save_weights(self, weights_path, /): - """ - Save the weights on the Module. - - Parameters - ---------- - weights_path - The hdf5 file for saving the weights. - - Returns - ------- - None - """ - os.makedirs("/".join(weights_path.split("/")[:-1]), exist_ok=True) - self.v.cont_to_disk_as_hdf5(weights_path) + # Public Methods # + # ---------------# def build( self, @@ -696,14 +157,14 @@ def build( device=None, dtype=None, dynamic_backend=None, - buffers=None, **kwargs, ): - """ - Build the internal layers and variables for this module. + """Build the internal layers and variables for this module. Parameters ---------- + args + Positional arguments to the _build method. from_call If True, denote that this build is triggered by calling. Otherwise, triggered by initializing the module. Default is ``False``. @@ -712,6 +173,11 @@ def build( Default is ``None``. dtype The data type for building the module. Default is ``None``. + dynamic_backend + Whether to use dynamic backend setting to deal if variables are passed as + input and created with a different backend to the current backend. + kwargs + Keyword arguments to the _build method. Returns ------- @@ -719,13 +185,11 @@ def build( True for successfully built a module. """ self._device = ivy.default(device, self._device) + self._dtype = ivy.default(dtype, self._dtype) + self._dynamic_backend = ivy.default(dynamic_backend, self._dynamic_backend) # return False if not from_call but build_mode is on_call if not from_call and self._build_mode == "on_call": return self.v - if dtype: - dtype = ivy.default_dtype(dtype=dtype, as_native=True) - else: - dtype = ivy.default_dtype(dtype=self._dtype, as_native=True) # why are we adding this kwarg in user-defined build ? # it results in the error while doing `from_haiku_module` if haiku's forward @@ -740,53 +204,53 @@ def build( # this creates weights for this Module only created = Container( self._create_variables(device=self._device, dtype=dtype), - dynamic_backend=False, + dynamic_backend=self._dynamic_backend, ) # build variables based on locally built layers, if v not passed in constructor - v_from_constructor = self._v_in - created_n_found = Container( dict( **self._find_variables( obj=self, without_initialisation=( True - if v_from_constructor and not self._with_partial_v + if self._v_from_constructor and not self._with_partial_v else False ), ), **created, ), - dynamic_backend=dynamic_backend, + dynamic_backend=self._dynamic_backend, ) created_n_found.cont_config["build_callable"] = True - if ivy.exists(v_from_constructor): + if ivy.exists(self._v_from_constructor): if self._with_partial_v: - if v_from_constructor: + if self._v_from_constructor: created_n_found.cont_assert_contains_sub_structure( - v_from_constructor, partial=True + self._v_from_constructor, partial=True ) - self.v = created_n_found.cont_set_at_key_chains(v_from_constructor) + self._v = created_n_found.cont_set_at_key_chains( + self._v_from_constructor + ) else: created_n_found, _ = self._remove_duplicate_variables( created_n_found, created ) ivy.Container.cont_assert_identical_structure( - [created_n_found, v_from_constructor], + [created_n_found, self._v_from_constructor], assert_and_assign=True, ) - self.v = created_n_found + self._v = created_n_found else: - self.v = created_n_found + self._v = created_n_found # remove duplicates - self.v, keychain_mappings = self._remove_duplicate_variables(self.v, created) + self._v, keychain_mappings = self._remove_duplicate_variables(self._v, created) # build any child 'on_call' layers if not built and from_call: # update child modules to share the same device - for k, v in self.__dict__.items(): + for v in self.__dict__.values(): if isinstance(v, ivy.Module): v._device = self._device @@ -795,18 +259,19 @@ def build( # re-build variables based on additional child on-call layers, if v not # passed in constructor - if not ivy.exists(v_from_constructor): + if not ivy.exists(self._v_from_constructor): created_n_found = Container( dict( **self._find_variables(obj=self), **self._create_variables(device=self._device, dtype=dtype), - ) + ), + dynamic_backend=self._dynamic_backend, ) - self.v = created_n_found + self._v = created_n_found # remove further duplicates with self.v - self.v, keychain_mappings = self._remove_duplicate_variables( - self.v, created + self._v, keychain_mappings = self._remove_duplicate_variables( + self._v, created ) # set built flag @@ -821,94 +286,104 @@ def build( v_ret = self.v if not self._store_vars: # ToDo: verify variables in self.v are released once this method exits - self.v = ivy.Container() + self._v = ivy.Container() + + # compute the module dict + self._compute_module_dict() # once all variables built, find and assign buffers - if buffers: - self._set_buffers(buffers=buffers) - self._find_buffers() + self._find_buffers() return v_ret if bool(v_ret) or isinstance(built, bool) else built - def register_buffer(self, var_name, value): - """Set the buffer at any place within the class.""" - self._set_buffers({var_name: value}) + def trace_graph( + self, + args: Optional[Tuple] = None, + kwargs: Optional[Dict] = None, + **trace_kwargs, + ): + """Trace the `ivy.Module`'s `_unified_ivy_graph` or `_call` method to + the target backend. - def eval(self): - # disables training mode for child modules - self.train(mode=False) + Parameters + ---------- + args: + arguments used to trace. Defaults to None. + kwargs: + keyword arguments used to trace. Defaults to None. + trace_kwargs: + keyword arguments passed to the trace function. + """ + # no arguments given to trace, so delay the compilation + if not (args or kwargs): + self._lazy_traced = True + return - def train(self, mode: bool = True): - # enables/disables training mode - self.training = mode - for module in self.v: - module = getattr(self, module, None) - if isinstance(module, ivy.Module): - module.train(mode=mode) + # we do not need convert the args to source + args = ivy.default(args, ()) + kwargs = ivy.default(kwargs, {}) - def to_device(self, device): - # moves the weights and buffers - # to the specified device - self._device = ivy.default(device, self._device) - # moving weights and buffers to new device - for key, obj in self.state_dict().items(): - if isinstance(obj, ivy.Module): - obj.to_device(device) - elif ivy.is_array(obj) or ivy.is_ivy_container(obj): - ivy.to_device(obj, device, out=obj) - return self + # shallow copy the kwargs dict + kwargs = copy.copy(kwargs) + kwargs["v"] = self.v - def __repr__(self): - extra_lines = [] - extra_repr = self.extra_repr() - if extra_repr: - extra_lines = extra_repr.split("\n") - child_lines = [] - for key, module in self.v.items(): - if isinstance(getattr(self, key, None), Module): - mod_str = repr(getattr(self, key)) - mod_str = _addindent(mod_str, 2) - child_lines.append(f"({key}): {mod_str}") - lines = extra_lines + child_lines + fn_to_trace = ivy.default(self._module_graph, self._call) - main_str = f"{self._get_name()}(" - if lines: - # simple one-liner info, which most builtin Modules will use - if len(extra_lines) == 1 and not child_lines: - main_str += extra_lines[0] - else: - main_str += "\n " + "\n ".join(lines) + "\n" + self._module_graph = ivy.trace_graph( + fn_to_trace, **trace_kwargs, args=args, kwargs=kwargs + ) - main_str += ")" - return main_str + self._lazy_traced = False - def extra_repr(self) -> str: - r""" - Set the extra representation of the module. + def register_buffer(self, name, value): + """Register a buffer. - To print customized extra information, you should re-implement - this method in your own modules. Both single-line and multi-line - strings are acceptable. + Parameters + ---------- + name + Name of the buffer + value + Value of the buffer """ - return "" + if value is not None: + self._buffers.update({name: value}) + else: + super().__setattr__(name, value) - def _get_name(self): - return self.__class__.__name__ + def register_parameter(self, name, value): + """Register a parameter. - # Properties # - # -----------# + Parameters + ---------- + name + Name of the parameter + value + Value of the parameter + """ + self._v.update({name: value}) - @property - def build_mode(self): - return self._build_mode + def train(self, mode: bool = True): + """Enable or disable training mode.""" + self._training = mode + for module in self.v: + module = getattr(self, module, None) + if isinstance(module, ivy.Module): + module.train(mode=mode) + return self - @property - def built_(self): - return self._built + def eval(self): + """Disable training mode.""" + return self.train(mode=False) - @property - def device(self): - return self._device + def to_device(self, device): + """Move the weights and buffers to the specified device.""" + self._device = ivy.default(device, self._device) + for obj in self.state_dict.values(): + if isinstance(obj, ivy.Module): + obj.to_device(device) + elif ivy.is_array(obj) or ivy.is_ivy_container(obj): + ivy.to_device(obj, device, out=obj) + return self def show_graph( self, @@ -937,76 +412,23 @@ def show_graph( fname=fname, ) - def __getattribute__(self, name): - if name == "v": - if super().__getattribute__("v") is None and not self.built_: - self._build_and_return_v( - *self._args, dynamic_backend=self._dynamic_backend, **self._kwargs - ) - if name != "buffers": - if hasattr(self, "buffers") and name in self.buffers: - return self.buffers[name] - return super().__getattribute__(name) - - def __setattr__(self, name, value): - if hasattr(self, "buffers") and name in self.buffers: - self.buffers[name] = value - return - return super().__setattr__(name, value) - - def __delattr__(self, name): - if hasattr(self, "buffers"): - if name in self.buffers: - del self.buffers[name] - else: - super().__delattr__(name) - - def state_dict(self): - return {**self.v, **getattr(self, "buffers", {})} - - def trace_graph( - self, - args: Optional[Tuple] = None, - kwargs: Optional[Dict] = None, - **trace_kwargs, - ): - """ - Trace the `ivy.Module`'s `_unified_ivy_graph` or `_call` method to the target - backend. + def save_weights(self, weights_path, /): + """Save the weights on the Module. Parameters ---------- - args: - arguments used to trace. Defaults to None. - kwargs: - keyword arguments used to trace. Defaults to None. - trace_kwargs: - keyword arguments passed to the trace function. - """ - # no arguments given to trace, so delay the compilation - if not (args or kwargs): - self._lazy_traced = True - return - - # we do not need convert the args to source - args = ivy.default(args, ()) - kwargs = ivy.default(kwargs, {}) - - # shallow copy the kwargs dict - kwargs = copy.copy(kwargs) - kwargs["v"] = self.v - - fn_to_trace = ivy.default(self._module_graph, self._call) - - self._module_graph = ivy.trace_graph( - fn_to_trace, **trace_kwargs, args=args, kwargs=kwargs - ) + weights_path + The hdf5 file for saving the weights. - self._lazy_traced = False + Returns + ------- + None + """ + os.makedirs("/".join(weights_path.split("/")[:-1]), exist_ok=True) + self.v.cont_to_disk_as_hdf5(weights_path) def save(self, filename): - """ - Save the module object to disk using pickle. + """Save the module object to disk using pickle. Parameters ---------- @@ -1022,8 +444,7 @@ def save(self, filename): @staticmethod def load(filename): - """ - Load a module object from disk using pickle. + """Load a module object from disk using pickle. Parameters ---------- @@ -1041,6 +462,203 @@ def load(filename): loaded._convert_numpy_to_tensors() return loaded + # Dunder Methods # + # ---------------# + + def __call__( + self, + *args, + v=None, + buffers=None, + **kwargs, + ): + """Forward an input through current module. + + Parameters + ---------- + args + Positional args to the build method. + v + If given, use this container as internal variables temporarily. + Default is ``None``. + buffers + If given, use this container as internal buffers temporarily. + Default is ``None``. + kwargs + Keyword arguments to the build method. + + Returns + ------- + ret + """ + if self._lazy_traced: + # we are creating graph since we want to transpile module, + # so set the appropriate backend + if self._target: + ivy.set_backend(self._target) + self.trace_graph(args=args, kwargs=kwargs) + if self._target: + ivy.previous_backend() + + if self._module_graph: + # we need `v` in kwargs, since this is a traced call + v = v if v else self.v + return self._module_graph(*args, v=v, **kwargs) + + # convert variables to native arrays so that they can be tracked + v = ivy.to_native(v) + ret = self._call(*args, v=v, buffers=buffers, **kwargs) + return ret + + def __getattribute__(self, name): + if name == "v": + if not super().__getattribute__("_v") and not self.built: + self._build_and_return_v( + *self._args, dynamic_backend=self._dynamic_backend, **self._kwargs + ) + return super().__getattribute__(name) + + def __setattr__(self, name, value): + if name in ["v", "buffers"]: + name = "_" + name + if isinstance(value, Module): + ret = super().__setattr__(name, value) + if ( + hasattr(self, "_build_mode") + and self.build_mode == "on_init" + and self.built + ): + self._rebuild() + return ret + return super().__setattr__(name, value) + + def __delattr__(self, name): + if hasattr(self, name): + if isinstance(getattr(self, name), Module): + super().__delattr__(name) + if self.build_mode == "on_init": + self._rebuild() + return + super().__delattr__(name) + + def __repr__(self): + extra_lines = [] + extra_repr = self._extra_repr() + if extra_repr: + extra_lines = extra_repr.split("\n") + child_lines = [] + for key in self.v.keys(): + if isinstance(getattr(self, key, None), Module): + mod_str = repr(getattr(self, key)) + mod_str = self._addindent(mod_str, 2) + child_lines.append(f"({key}): {mod_str}") + lines = extra_lines + child_lines + + main_str = f"{self.__class__.__name__}(" + if lines: + # simple one-liner info, which most builtin Modules will use + if len(extra_lines) == 1 and not child_lines: + main_str += extra_lines[0] + else: + main_str += "\n " + "\n ".join(lines) + "\n" + + main_str += ")" + return main_str + + # Methods to be Optionally Overridden # + # -----------------------------------# + + def _create_variables(self, *, device=None, dtype=None): + """Create internal trainable variables, and return as arbitrary nested + dict. Overridable. + + Parameters + ---------- + device + The device string, specifying the device on which to create the variables. + dtype + The dtype string, specifying the dtype on which to create the variables. + + Returns + ------- + ret + An empty set. + """ + return {} + + def _build(self, *args, **kwargs) -> bool: + """Build the internal layers and variables for this module. + Overridable. + + Returns + ------- + ret + False or empty Container if the build only partially completed (i.e. some + child Modules have "on_call" build mode). Alternatively, return True or a + container of the built variables if the module is built. + """ + return True + + def _forward(self, *args, **kwargs): + """Forward pass of the layer, called after handling the optional input + variables. + + Raises + ------ + NotImplementedError + """ + raise ivy.utils.exceptions.IvyNotImplementedException + + def _extra_repr(self) -> str: + """Set the extra representation of the module. + + To print customized extra information, you should re-implement + this method in your own modules. Both single-line and multi-line + strings are acceptable. + """ + return "" + + # Properties # + # -----------# + + @property + def device(self): + return self._device + + @property + def dtype(self): + return self._dtype + + @property + def build_mode(self): + return self._build_mode + + @property + def built(self): + return self._built + + @property + def training(self): + return self._training + + @property + def v(self): + return self._v + + @property + def buffers(self): + return self._buffers + + @property + def state_dict(self): + """Return the state_dict which is a collection of the variables and + buffers.""" + return {**self.v, **self.buffers} + + @property + def module_dict(self): + return self._module_dict + class _HaikuIvyModule(Module): def __init__(self, *args, params_hk, native_module, device, devices, **kwargs): @@ -1078,7 +696,7 @@ def _forward(self, *a, **kw): a, kw = ivy.args_to_native(*a, **kw) params_hk = self._dict_to_hk_flat_map(self.v.cont_to_dict()) ret = self._native_module.apply(params_hk, 0, *a, **kw) - nested = True if isinstance(ret, tuple) else False + nested = isinstance(ret, tuple) return ivy.to_native(ret, nested=nested) def _hk_flat_map_to_dict(self, hk_flat_map): @@ -1141,7 +759,7 @@ def _forward(self, *a, **kw): a, kw = ivy.args_to_native(*a, **kw) params_fx = flax.core.freeze(self.v.cont_to_dict()) ret = self._native_module.apply(params_fx, *a, **kw) - nested = True if isinstance(ret, tuple) else False + nested = isinstance(ret, tuple) return ivy.to_native(ret, nested=nested) @@ -1167,7 +785,7 @@ def _build(self, *args, **kwargs): def _forward(self, *a, **kw): a, kw = ivy.args_to_native(*a, **kw) ret = self._native_module(*a, **kw) - nested = True if isinstance(ret, tuple) else False + nested = isinstance(ret, tuple) return ivy.to_native(ret, nested=nested) @@ -1198,7 +816,7 @@ def _build(self, *args, **kwargs): def _forward(self, *a, **kw): a, kw = ivy.args_to_native(*a, **kw) ret = self._native_module(*a, **kw) - nested = True if isinstance(ret, tuple) else False + nested = isinstance(ret, tuple) return ivy.to_native(ret, nested=nested) @@ -1265,5 +883,5 @@ def _forward(self, *a, **kw): a, kw = ivy.args_to_native(*a, **kw) self._update_v(self.v) ret = self._native_module(*a, **kw) - nested = True if isinstance(ret, tuple) else False + nested = isinstance(ret, tuple) return ivy.to_native(ret, nested=nested) diff --git a/ivy/stateful/norms.py b/ivy/stateful/norms.py index 65560176ddedb..5c8e3c44a53b5 100644 --- a/ivy/stateful/norms.py +++ b/ivy/stateful/norms.py @@ -19,8 +19,7 @@ def __init__( v=None, dtype=None, ): - """ - Class for applying Layer Normalization over a mini-batch of inputs. + """Class for applying Layer Normalization over a mini-batch of inputs. Parameters ---------- @@ -52,8 +51,10 @@ def __init__( self._bias_init = Zeros() Module.__init__(self, device=device, v=v, dtype=dtype) - def _create_variables(self, device, dtype=None): + def _create_variables(self, device=None, dtype=None): """Create internal variables for the layer.""" + device = ivy.default(device, self.device) + dtype = ivy.default(dtype, self.dtype) if self._elementwise_affine: return { "weight": self._weight_init.create_variables( @@ -66,8 +67,7 @@ def _create_variables(self, device, dtype=None): return {} def _forward(self, inputs): - """ - Perform forward pass of the LayerNorm layer. + """Perform forward pass of the LayerNorm layer. Parameters ---------- @@ -88,6 +88,12 @@ def _forward(self, inputs): new_std=self._new_std, ) + def _extra_repr(self) -> str: + return ( + f"normalized_idxs={self._normalized_idxs}, epsilon={self._epsilon}, " + f"elementwise_affine={self._elementwise_affine}, new_std={self._new_std}" + ) + class BatchNorm2D(Module): def __init__( @@ -105,8 +111,7 @@ def __init__( dtype=None, training=True, ): - """ - Class for applying Layer Normalization over a mini-batch of inputs. + """Class for applying Layer Normalization over a mini-batch of inputs. Parameters ---------- @@ -154,8 +159,10 @@ def __init__( self._running_var_init = Ones() Module.__init__(self, device=device, v=v, dtype=dtype, training=training) - def _create_variables(self, device, dtype=None): + def _create_variables(self, device=None, dtype=None): """Create internal variables for the layer.""" + device = ivy.default(device, self.device) + dtype = ivy.default(dtype, self.dtype) if self._affine: return { "b": self._bias_init.create_variables( @@ -174,8 +181,7 @@ def _create_variables(self, device, dtype=None): return {} def _forward(self, inputs): - """ - Perform forward pass of the BatchNorm layer. + """Perform forward pass of the BatchNorm layer. Parameters ---------- @@ -203,3 +209,11 @@ def _forward(self, inputs): self.v.running_var = running_var return normalized + + def _extra_repr(self) -> str: + return ( + f"num_features={self._num_features}, affine={self._affine}, " + f"data_format={self._data_format}, epsilon={self._epsilon} " + f"momentum={self._momentum}, " + f"track_running_stats={self._track_running_stats}" + ) diff --git a/ivy/stateful/optimizers.py b/ivy/stateful/optimizers.py index 9670c4e5aef7a..dafc66d90fbc3 100644 --- a/ivy/stateful/optimizers.py +++ b/ivy/stateful/optimizers.py @@ -24,8 +24,8 @@ def __init__( fallback_to_non_traced: bool = False, device: Optional[Union[ivy.Device, ivy.NativeDevice]] = None, ): - """ - Construct a general Optimizer. This is an abstract class, and must be derived. + """Construct a general Optimizer. This is an abstract class, and must + be derived. Parameters ---------- @@ -70,9 +70,9 @@ def __init__( @abc.abstractmethod def _step(self, v: ivy.Container, grads: ivy.Container): - """ - Update nested variables container v from update step, using nested grads - container. Override this abstract method with child class custom implementation. + """Update nested variables container v from update step, using nested + grads container. Override this abstract method with child class custom + implementation. Parameters ---------- @@ -93,8 +93,7 @@ def _step(self, v: ivy.Container, grads: ivy.Container): def _step_fn( self, v: ivy.Container, grads: ivy.Container, ignore_missing: bool = False ): - """ - Call the custom child step function implementation. + """Call the custom child step function implementation. Parameters ---------- @@ -118,8 +117,7 @@ def _step_fn( @abc.abstractmethod def set_state(self, state: ivy.Container): - """ - Set state of the optimizer. + """Set state of the optimizer. Parameters ---------- @@ -133,8 +131,8 @@ def set_state(self, state: ivy.Container): def step( self, v: ivy.Container, grads: ivy.Container, ignore_missing: bool = False ): - """ - Update nested variables container v from overridden private self._step. + """Update nested variables container v from overridden private + self._step. Parameters ---------- @@ -169,8 +167,7 @@ def __init__( stop_gradients: bool = True, trace_on_next_step: bool = False, ): - """ - Construct a Stochastic-Gradient-Descent (SGD) optimizer. + """Construct a Stochastic-Gradient-Descent (SGD) optimizer. Parameters ---------- @@ -194,9 +191,8 @@ def __init__( # Custom Step def _step(self, v: ivy.Container, grads: ivy.Container): - """ - Update nested variables container v by gradient descent step, using nested - gradients container. + """Update nested variables container v by gradient descent step, using + nested gradients container. Parameters ---------- @@ -218,8 +214,7 @@ def _step(self, v: ivy.Container, grads: ivy.Container): ) def set_state(self, state: ivy.Container): - """ - Set state of the optimizer. + """Set state of the optimizer. Parameters ---------- @@ -242,8 +237,7 @@ def __init__( stop_gradients: bool = True, trace_on_next_step: bool = False, ): - """ - Construct a Layer-wise Adaptive Rate Scaling (LARS) optimizer. + """Construct a Layer-wise Adaptive Rate Scaling (LARS) optimizer. Parameters ---------- @@ -270,9 +264,8 @@ def __init__( # Custom Step def _step(self, v: ivy.Container, grads: ivy.Container): - """ - Update nested variables container v by gradient descent step, using nested - gradients container. + """Update nested variables container v by gradient descent step, using + nested gradients container. Parameters ---------- @@ -295,8 +288,7 @@ def _step(self, v: ivy.Container, grads: ivy.Container): ) def set_state(self, state: ivy.Container): - """ - Set state of the optimizer. + """Set state of the optimizer. Parameters ---------- @@ -322,8 +314,7 @@ def __init__( trace_on_next_step: bool = False, device: Optional[Union[ivy.Device, ivy.NativeDevice]] = None, ): - """ - Construct an ADAM optimizer. + """Construct an ADAM optimizer. Parameters ---------- @@ -365,9 +356,8 @@ def __init__( # Custom Step def _step(self, v: ivy.Container, grads: ivy.Container): - """ - Update nested variables container v by Adam update step, using nested grads - container. + """Update nested variables container v by Adam update step, using + nested grads container. Parameters ---------- @@ -401,8 +391,7 @@ def _step(self, v: ivy.Container, grads: ivy.Container): return new_v def set_state(self, state: ivy.Container): - """ - Set state of the optimizer. + """Set state of the optimizer. Parameters ---------- @@ -430,8 +419,7 @@ def __init__( trace_on_next_step: bool = False, device: Optional[Union[ivy.Device, ivy.NativeDevice]] = None, ): - """ - Construct an ADAMW optimizer. + """Construct an ADAMW optimizer. Parameters ---------- @@ -473,9 +461,8 @@ def __init__( ) def _step(self, v: ivy.Container, grads: ivy.Container): - """ - Update nested variables container v by AdamW update step, using nested grads - container. + """Update nested variables container v by AdamW update step, using + nested grads container. Parameters ---------- @@ -510,8 +497,7 @@ def __init__( trace_on_next_step: bool = False, device: Optional[Union[ivy.Device, ivy.NativeDevice]] = None, ): - """ - Construct an LAMB optimizer. + """Construct an LAMB optimizer. Parameters ---------- @@ -558,9 +544,8 @@ def __init__( # Custom Step def _step(self, v: ivy.Container, grads: ivy.Container): - """ - Update nested variables container v by LAMB update step, using nested grads - container. + """Update nested variables container v by LAMB update step, using + nested grads container. Parameters ---------- @@ -596,8 +581,7 @@ def _step(self, v: ivy.Container, grads: ivy.Container): return new_v def set_state(self, state: ivy.Container): - """ - Set state of the optimizer. + """Set state of the optimizer. Parameters ---------- diff --git a/ivy/stateful/sequential.py b/ivy/stateful/sequential.py index a7ef0f6f969ec..684f698a0dee1 100644 --- a/ivy/stateful/sequential.py +++ b/ivy/stateful/sequential.py @@ -16,9 +16,8 @@ def __init__( v: Optional[Union[ivy.Array, ivy.NativeArray]] = None, dtype: Optional[Union[ivy.Dtype, ivy.NativeDtype]] = None, ): - """ - Initialize a sequential container. Modules will be added to it in the order they - are passed in the constructor. + """Initialize a sequential container. Modules will be added to it in + the order they are passed in the constructor. Parameters ---------- @@ -35,13 +34,13 @@ def __init__( for i, submod in enumerate(sub_modules): try: submod.v = v["submodules"][f"v{str(i)}"] - except KeyError: + except KeyError as e: if submod.v: raise ivy.utils.exceptions.IvyException( "variables v passed to Sequential class must have key " "chains in the form of " '"submodules/v{}", where {} is an idx' - ) + ) from e self._submodules = list(sub_modules) Module.__init__(self, device=device, v=v, dtype=dtype) @@ -49,8 +48,7 @@ def __iter__(self): return iter(self._submodules) def _forward(self, inputs): - """ - Perform forward pass of the Sequential container. + """Perform forward pass of the Sequential container. Parameters ---------- @@ -66,12 +64,18 @@ def _forward(self, inputs): for i, submod in enumerate(self._submodules): try: x = submod(x, v=self.v.submodules[f"v{str(i)}"]) - except KeyError: + except KeyError as e: if submod.v: raise ivy.utils.exceptions.IvyException( "variables v passed to Sequential class must have key chains " "in the form of " '"submodules/v{}", where {} is an idx' - ) + ) from e x = submod(x) return x + + def _extra_repr(self): + submods = [] + for i, submod in enumerate(self._submodules): + submods.append(f"v{i}={submod}") + return ", ".join(submods) diff --git a/ivy/utils/_importlib.py b/ivy/utils/_importlib.py index 2d6770a42c225..01247a3bd719f 100644 --- a/ivy/utils/_importlib.py +++ b/ivy/utils/_importlib.py @@ -12,7 +12,7 @@ # expected. Import these modules along with Ivy initialization, as the import logic # assumes they exist in sys.modules. -MODULES_TO_SKIP = ["ivy.compiler", "ivy.engines"] +MODULES_TO_SKIP = ["ivy.compiler", "ivy.engines", "ivy.wrappers"] IS_COMPILING_WITH_BACKEND = False @@ -74,8 +74,7 @@ def _from_import(name: str, package=None, mod_globals=None, from_list=(), level= def _absolute_import(name: str, asname=None, mod_globals=None): - """ - Handle absolute import statement :param name: + """Handle absolute import statement :param name: :return: """ diff --git a/ivy/utils/assertions.py b/ivy/utils/assertions.py index 0a5f653f7fd8f..e3c7323c481ba 100644 --- a/ivy/utils/assertions.py +++ b/ivy/utils/assertions.py @@ -22,13 +22,19 @@ def _broadcast_inputs(x1, x2): def check_less(x1, x2, allow_equal=False, message="", as_array=True): - comp_fn = lambda x1, x2: (ivy.any(x1 > x2), ivy.any(x1 >= x2)) + def comp_fn(x1, x2): + return ivy.any(x1 > x2), ivy.any(x1 >= x2) + if not as_array: - iter_comp_fn = lambda x1_, x2_: ( - any(x1 > x2 for x1, x2 in zip(x1_, x2_)), - any(x1 >= x2 for x1, x2 in zip(x1_, x2_)), - ) - comp_fn = lambda x1, x2: iter_comp_fn(*_broadcast_inputs(x1, x2)) + + def iter_comp_fn(x1_, x2_): + return any(x1 > x2 for x1, x2 in zip(x1_, x2_)), any( + x1 >= x2 for x1, x2 in zip(x1_, x2_) + ) + + def comp_fn(x1, x2): # noqa F811 + return iter_comp_fn(*_broadcast_inputs(x1, x2)) + gt, gt_eq = comp_fn(x1, x2) # less_equal if allow_equal and gt: @@ -42,13 +48,19 @@ def check_less(x1, x2, allow_equal=False, message="", as_array=True): def check_greater(x1, x2, allow_equal=False, message="", as_array=True): - comp_fn = lambda x1, x2: (ivy.any(x1 < x2), ivy.any(x1 <= x2)) + def comp_fn(x1, x2): + return ivy.any(x1 < x2), ivy.any(x1 <= x2) + if not as_array: - iter_comp_fn = lambda x1_, x2_: ( - any(x1 < x2 for x1, x2 in zip(x1_, x2_)), - any(x1 <= x2 for x1, x2 in zip(x1_, x2_)), - ) - comp_fn = lambda x1, x2: iter_comp_fn(*_broadcast_inputs(x1, x2)) + + def iter_comp_fn(x1_, x2_): + return any(x1 < x2 for x1, x2 in zip(x1_, x2_)), any( + x1 <= x2 for x1, x2 in zip(x1_, x2_) + ) + + def comp_fn(x1, x2): # noqa F811 + return iter_comp_fn(*_broadcast_inputs(x1, x2)) + lt, lt_eq = comp_fn(x1, x2) # greater_equal if allow_equal and lt: @@ -63,11 +75,20 @@ def check_greater(x1, x2, allow_equal=False, message="", as_array=True): def check_equal(x1, x2, inverse=False, message="", as_array=True): # not_equal - eq_fn = lambda x1, x2: (x1 == x2 if inverse else x1 != x2) - comp_fn = lambda x1, x2: ivy.any(eq_fn(x1, x2)) + def eq_fn(x1, x2): + return x1 == x2 if inverse else x1 != x2 + + def comp_fn(x1, x2): + return ivy.any(eq_fn(x1, x2)) + if not as_array: - iter_comp_fn = lambda x1_, x2_: any(eq_fn(x1, x2) for x1, x2 in zip(x1_, x2_)) - comp_fn = lambda x1, x2: iter_comp_fn(*_broadcast_inputs(x1, x2)) + + def iter_comp_fn(x1_, x2_): + return any(eq_fn(x1, x2) for x1, x2 in zip(x1_, x2_)) + + def comp_fn(x1, x2): # noqa F811 + return iter_comp_fn(*_broadcast_inputs(x1, x2)) + eq = comp_fn(x1, x2) if inverse and eq: raise ivy.utils.exceptions.IvyException( @@ -182,9 +203,9 @@ def check_same_dtype(x1, x2, message=""): # -------- # -def check_unsorted_segment_min_valid_params(data, segment_ids, num_segments): +def check_unsorted_segment_valid_params(data, segment_ids, num_segments): if not isinstance(num_segments, int): - raise ValueError("num_segments must be of integer type") + raise TypeError("num_segments must be of integer type") valid_dtypes = [ ivy.int32, @@ -211,7 +232,7 @@ def check_unsorted_segment_min_valid_params(data, segment_ids, num_segments): num_segments = num_segments.item() if segment_ids.dtype not in valid_dtypes: - raise ValueError("segment_ids must have an integer dtype") + raise TypeError("segment_ids must have an integer dtype") if data.shape[0] != segment_ids.shape[0]: raise ValueError("The length of segment_ids should be equal to data.shape[0].") @@ -269,7 +290,7 @@ def check_one_way_broadcastable(x1, x2): if len(x1) > len(x2): return False for a, b in zip(x1[::-1], x2[::-1]): - if a == 1 or a == b: + if a in (1, b): pass else: return False @@ -323,10 +344,7 @@ def check_dev_correct_formatting(device): def _check_jax_x64_flag(dtype): - if ( - ivy.backend == "jax" - and not ivy.functional.backends.jax.jax.config.jax_enable_x64 - ): + if ivy.backend == "jax" and not ivy.functional.backends.jax.jax.config.x64_enabled: ivy.utils.assertions.check_elem_in_list( dtype, ["float64", "int64", "uint64", "complex128"], diff --git a/ivy/utils/backend/ast_helpers.py b/ivy/utils/backend/ast_helpers.py index 795dc94e67931..8e5b2b54c6634 100644 --- a/ivy/utils/backend/ast_helpers.py +++ b/ivy/utils/backend/ast_helpers.py @@ -156,8 +156,7 @@ def _create_attrs_from_node(node, attrs=()): def _create_node(stmnt: str): - """ - Create an AST node from a given statement. + """Create an AST node from a given statement. Parameters ---------- diff --git a/ivy/utils/backend/handler.py b/ivy/utils/backend/handler.py index 72bbf8a79013e..04974f0557488 100644 --- a/ivy/utils/backend/handler.py +++ b/ivy/utils/backend/handler.py @@ -75,8 +75,7 @@ def _get_backend_for_arg(arg_module_name): def _determine_backend_from_args(args): - """ - Return the appropriate Ivy backend, given some arguments. + """Return the appropriate Ivy backend, given some arguments. Parameters ---------- @@ -97,13 +96,13 @@ def _determine_backend_from_args(args): >>> x = jnp.array([1]) >>> print(_determine_backend_from_args(x)) # noqa - """ + """ # noqa: E501 arg_type = type(args) if isinstance(args, ivy.Array): args = args.data if isinstance(args, dict): - for key, value in args.items(): + for value in args.values(): # recursively call the function for each value in the dictionary lib = _determine_backend_from_args(value) if lib: @@ -121,9 +120,8 @@ def _determine_backend_from_args(args): def set_backend_to_specific_version(backend): - """ - Update the backend dict to make the original function name point to the version - specific one. + """Update the backend dict to make the original function name point to the + version specific one. Parameters ---------- @@ -146,8 +144,8 @@ def set_backend_to_specific_version(backend): def current_backend(*args, **kwargs): - """ - Return the current backend. Priorities: global_backend > argument's backend. + """Return the current backend. Priorities: global_backend > argument's + backend. Parameters ---------- @@ -177,7 +175,7 @@ def current_backend(*args, **kwargs): >>> x = np.array([2.0]) >>> print(ivy.current_backend(x)) # noqa - """ + """ # noqa: E501 global implicit_backend # if a global backend has been set with # set_backend then this will be returned @@ -206,6 +204,8 @@ def _set_module_backend( ) backend_str = backend.current_backend_str() if backend_str is None else backend_str for k, v in original_dict.items(): + if k in ivy.GLOBAL_PROPS: + continue compositional = k not in backend.__dict__ if compositional: if k in invalid_dtypes and k in target.__dict__: @@ -236,11 +236,21 @@ def _handle_backend_specific_vars(target, backend): target.set_global_attr("RNG", target.functional.backends.jax.random.RNG) -def convert_from_source_backend_to_numpy(variable_ids, numpy_objs, devices): - # Dynamic Backend - from ivy.functional.ivy.gradients import _is_variable, _variable_data +def _data_to_new_backend(x, previous_backend): + device = previous_backend.dev(x.data) + try: + result = ivy.from_dlpack(previous_backend.to_dlpack(x.data)) + result = ivy.to_device(result, device) + except Exception: + np_res = previous_backend.to_numpy(x.data) + result = ivy.asarray(np_res, device=device) + return result + + +def dynamic_backend_converter(backend_stack): + from ivy.functional.ivy.gradients import _variable - def _is_var(obj): + def _is_var(obj, backend): if isinstance(obj, ivy.Container): def _map_fn(x): @@ -252,7 +262,7 @@ def _map_fn(x): ): return False - return _is_variable(x) + return backend.gradients._is_variable(x) return obj.cont_map(lambda x, kc: _map_fn(x)).cont_all_true() @@ -264,7 +274,7 @@ def _map_fn(x): "jaxlib.xla_extension", ): return False - return _is_variable(obj) + return backend.gradients._is_variable(obj) # get all ivy array instances in the project scope container_list = [ @@ -273,7 +283,8 @@ def _map_fn(x): if "ivy" in type(obj).__module__ and isinstance(obj, ivy.Container) ] cont_array_idxs = ivy.nested_argwhere( - container_list, lambda x: isinstance(x, ivy.Array) + container_list, + lambda x: isinstance(x, ivy.Array) and x.backend != ivy.current_backend_str(), ) cont_array_vals = ivy.multi_index_nest(container_list, cont_array_idxs) array_list = [ @@ -287,71 +298,35 @@ def _map_fn(x): array_list = [ arr for arr in array_list - if arr.__dict__ and arr.backend == ivy.current_backend_str() + if arr.__dict__ and arr.backend != ivy.current_backend_str() ] - arr_ids = [id(item.data) for item in array_list] - new_objs = dict(zip(arr_ids, array_list)) - new_objs = list(new_objs.values()) + new_objs = [obj for obj in array_list if obj.dynamic_backend] # now convert all ivy.Array and ivy.Container instances - # to numpy using the current backend + # to the new backend + for obj in new_objs: - if obj.dynamic_backend: - numpy_objs.append(obj) - devices.append(obj.device) - if _is_var(obj): - # add variable object id to set - variable_ids.add(id(obj)) - native_var = _variable_data(obj) - np_data = ivy.to_numpy(native_var) + # the following if condition avoids converting arrays that were already + # updated inplace i.e. are references to other arrays + if obj.backend != ivy.current_backend_str(): + backend = ivy.with_backend(obj.backend, cached=True) + if _is_var(obj, backend): + native_var = backend.gradients._variable_data(obj) + data = _data_to_new_backend(native_var, backend) + new_data = _variable(data) else: - np_data = obj.to_numpy() + new_data = _data_to_new_backend(obj, backend) if isinstance(obj, ivy.Container): - obj.cont_inplace_update(np_data) + obj.cont_inplace_update(new_data) else: - obj._data = np_data - - return variable_ids, numpy_objs, devices - - -def convert_from_numpy_to_target_backend(variable_ids, numpy_objs, devices): - # Dynamic Backend - from ivy.functional.ivy.gradients import _variable - - # convert all ivy.Array and ivy.Container instances from numpy - # to native arrays using the newly set backend - for obj, device in zip(numpy_objs, devices): - np_arr = obj.data if isinstance(obj, ivy.Array) else obj - # check if object was originally a variable - if id(obj) in variable_ids: - native_arr = ivy.nested_map( - lambda x: current_backend().asarray(x, device=device), - np_arr, - include_derived=True, - shallow=False, - ) - new_data = _variable(native_arr) - - else: - new_data = ivy.nested_map( - lambda x: current_backend().asarray(x, device=device), - np_arr, - include_derived=True, - shallow=False, - ) - - if isinstance(obj, ivy.Container): - obj.cont_inplace_update(new_data) - else: - obj.data = new_data.data + obj.data = new_data.data @prevent_access_locally def set_backend(backend: str, dynamic: bool = False): - """ - Set `backend` to be the global backend. + """Set `backend` to be the global backend. Will also convert all Array and Container objects to the new backend if `dynamic` = True @@ -378,22 +353,11 @@ def set_backend(backend: str, dynamic: bool = False): f"backend must be one from {list(_backend_dict.keys())}", ) - variable_ids = set() # create an empty set to store variable object ids - numpy_objs = [] # create an empty list to store numpy objects - devices = [] # create an empty list to store device strings - # created during 1st conversion step - - if dynamic: - variable_ids, numpy_objs, devices = convert_from_source_backend_to_numpy( - variable_ids, numpy_objs, devices - ) - # update the global dict with the new backend with ivy.locks["backend_setter"]: global ivy_original_dict if not backend_stack: ivy_original_dict = ivy.__dict__.copy() - _clear_current_sub_backends() if isinstance(backend, str): temp_stack = [] @@ -411,12 +375,12 @@ def set_backend(backend: str, dynamic: bool = False): _set_module_backend(ivy_original_dict, ivy, backend) # following snippet is required to update the ivy.functional namespace with # backend-specific functions - for key, _ in ivy.__dict__.items(): + for key in ivy.__dict__.keys(): if key in ivy.functional.__dict__ and not key.startswith("__"): ivy.functional.__dict__[key] = ivy.__dict__[key] if dynamic: - convert_from_numpy_to_target_backend(variable_ids, numpy_objs, devices) + dynamic_backend_converter(backend_stack) for sub_backend in ivy.available_sub_backends: ivy.set_sub_backend(sub_backend) if verbosity.level > 0: @@ -426,8 +390,7 @@ def set_backend(backend: str, dynamic: bool = False): def set_numpy_backend(): - """ - Set NumPy to be the global backend. + """Set NumPy to be the global backend. equivalent to `ivy.set_backend("numpy")`. """ # noqa @@ -435,8 +398,7 @@ def set_numpy_backend(): def set_jax_backend(): - """ - Set JAX to be the global backend. + """Set JAX to be the global backend. equivalent to `ivy.set_backend("jax")`. """ # noqa @@ -444,8 +406,7 @@ def set_jax_backend(): def set_tensorflow_backend(): - """ - Set TensorFlow to be the global backend. + """Set TensorFlow to be the global backend. equivalent to `ivy.set_backend("tensorflow")`. """ @@ -453,8 +414,7 @@ def set_tensorflow_backend(): def set_torch_backend(): - """ - Set torch to be the global backend. + """Set torch to be the global backend. equivalent to `ivy.set_backend("torch")`. """ # noqa @@ -462,8 +422,7 @@ def set_torch_backend(): def set_paddle_backend(): - """ - Set paddle to be the global backend. + """Set paddle to be the global backend. equivalent to `ivy.set_backend("paddle")`. """ # noqa @@ -471,8 +430,7 @@ def set_paddle_backend(): def set_mxnet_backend(): - """ - Set MXNet to be the global backend. + """Set MXNet to be the global backend. equivalent to `ivy.set_backend("mx")`. """ # noqa @@ -481,10 +439,9 @@ def set_mxnet_backend(): @prevent_access_locally def previous_backend(): - """ - Unset the current global backend, and adjusts the ivy dict such that either a - previously set global backend is then used as the backend, otherwise we return to - Ivy's implementations. + """Unset the current global backend, and adjusts the ivy dict such that + either a previously set global backend is then used as the backend, + otherwise we return to Ivy's implementations. Returns ------- @@ -535,6 +492,8 @@ def previous_backend(): # wrap backend functions if there still is a backend, and add functions # to ivy namespace for k, v in new_backend_dict.items(): + if k in ivy.GLOBAL_PROPS: + continue if backend_stack and k in ivy_original_dict: v = _wrap_function(k, v, ivy_original_dict[k]) if k in ivy_original_dict: @@ -598,7 +557,7 @@ def with_backend(backend: str, cached: bool = True): ivy_pack.__dict__.copy(), ivy_pack, backend_module ) # TODO use a refactored code from ivy.set_backend - for key, _ in ivy_pack.__dict__.items(): + for key in ivy_pack.__dict__.keys(): if key in ivy_pack.functional.__dict__ and not key.startswith("__"): ivy_pack.functional.__dict__[key] = ivy_pack.ivy.__dict__[key] ivy_pack.backend_stack.append(backend_module) diff --git a/ivy/utils/backend/sub_backend_handler.py b/ivy/utils/backend/sub_backend_handler.py index ee30f18862736..525c52ff6eacc 100644 --- a/ivy/utils/backend/sub_backend_handler.py +++ b/ivy/utils/backend/sub_backend_handler.py @@ -44,6 +44,7 @@ def fn_name_from_version_specific_fn_name(name, version): version the version of the current framework for which the support is to be provided, the version is inferred by importing the framework + Returns ------- the name of the original function which will then point to the version @@ -93,6 +94,7 @@ def fn_name_from_version_specific_fn_name_sub_backend( version the version of the current framework for which the support is to be provided, the version is inferred by importing the framework + Returns ------- the name of the original function which will then point to the version diff --git a/ivy/utils/binaries.py b/ivy/utils/binaries.py index 62ec97d849ccc..dc7175831457b 100644 --- a/ivy/utils/binaries.py +++ b/ivy/utils/binaries.py @@ -1,7 +1,7 @@ import os import logging import json -from pip._vendor.packaging import tags +from packaging import tags from urllib import request from tqdm import tqdm @@ -9,8 +9,9 @@ def _get_paths_from_binaries(binaries, root_dir=""): """Get all the paths from the binaries.json into a list.""" paths = [] + ext = "pyd" if os.name == "nt" else "so" if isinstance(binaries, str): - return [os.path.join(root_dir, binaries)] + return [os.path.join(root_dir, binaries + "." + ext)] elif isinstance(binaries, dict): for k, v in binaries.items(): paths += _get_paths_from_binaries(v, os.path.join(root_dir, k)) @@ -65,7 +66,7 @@ def cleanup_and_fetch_binaries(clean=True): binaries_dict = json.load(open(binaries_path)) available_configs = json.load(open(available_configs_path)) binaries_paths = _get_paths_from_binaries(binaries_dict, folder_path) - binaries_exts = set([path.split(".")[-1] for path in binaries_paths]) + binaries_exts = {path.split(".")[-1] for path in binaries_paths} # clean up existing binaries if clean: @@ -78,6 +79,7 @@ def cleanup_and_fetch_binaries(clean=True): print("Downloading new binaries...") all_tags = list(tags.sys_tags()) + version = os.environ["VERSION"] if "VERSION" in os.environ else "main" terminate = False @@ -95,7 +97,8 @@ def cleanup_and_fetch_binaries(clean=True): continue folders = path.split(os.sep) _, file_path = os.sep.join(folders[:-1]), folders[-1] - file_name = f"{file_path[:-3]}_{tag}.so" + ext = "pyd" if os.name == "nt" else "so" + file_name = f"{file_path[:-(len(ext)+1)]}_{tag}.{ext}" search_path = f"{module}/{file_name}" try: response = request.urlopen( diff --git a/ivy/utils/einsum_parser.py b/ivy/utils/einsum_parser.py index 53f3af0bba445..46705dd798b60 100644 --- a/ivy/utils/einsum_parser.py +++ b/ivy/utils/einsum_parser.py @@ -12,8 +12,7 @@ def is_valid_einsum_char(x: str) -> bool: - """ - Check if the character ``x`` is valid for numpy einsum. **Examples:** + """Check if the character ``x`` is valid for numpy einsum. **Examples:** ```python is_valid_einsum_char("a") @@ -27,8 +26,7 @@ def is_valid_einsum_char(x: str) -> bool: def has_valid_einsum_chars_only(einsum_str: str) -> bool: # [x] - """ - Check if ``einsum_str`` contains only valid characters for numpy einsum. + """Check if ``einsum_str`` contains only valid characters for numpy einsum. **Examples:** ```python @@ -70,8 +68,7 @@ def get_symbol(i: int) -> str: def gen_unused_symbols(used: str, n: int) -> Iterator[str]: - """ - Generate ``n`` symbols that are not already in ``used``. + """Generate ``n`` symbols that are not already in ``used``. **Examples:** ```python @@ -90,9 +87,9 @@ def gen_unused_symbols(used: str, n: int) -> Iterator[str]: def find_output_str(subscripts: str) -> str: - """ - Find the output string for the inputs ``subscripts`` under canonical einstein - summation rules.That is, repeated indices are summed over by default. + """Find the output string for the inputs ``subscripts`` under canonical + einstein summation rules.That is, repeated indices are summed over by + default. Examples -------- @@ -114,9 +111,8 @@ def find_output_str(subscripts: str) -> str: def find_output_shape( inputs: List[str], shapes: List[TensorShapeType], output: str ) -> TensorShapeType: - """ - Find the output shape for given inputs, shapes and output string, taking into - account broadcasting. + """Find the output shape for given inputs, shapes and output string, taking + into account broadcasting. Examples -------- @@ -138,8 +134,7 @@ def find_output_shape( def possibly_convert_to_numpy(x: Any) -> Any: # possibly convert to native - """ - Convert things without a 'shape' to ndarrays, but leave everything else. + """Convert things without a 'shape' to ndarrays, but leave everything else. Examples -------- @@ -169,8 +164,8 @@ def possibly_convert_to_numpy(x: Any) -> Any: # possibly convert to native def convert_subscripts(old_sub: List[Any], symbol_map: Dict[Any, Any]) -> str: - """ - Convert user custom subscripts list to subscript string according to `symbol_map`. + """Convert user custom subscripts list to subscript string according to + `symbol_map`. Examples -------- @@ -183,7 +178,7 @@ def convert_subscripts(old_sub: List[Any], symbol_map: Dict[Any, Any]) -> str: def convert_interleaved_input( - operands: Union[List[Any], Tuple[Any]] + operands: Union[List[Any], Tuple[Any]], ) -> Tuple[str, List[Any]]: """Convert 'interleaved' input to standard einsum input.""" tmp_operands = list(operands) @@ -224,9 +219,9 @@ def convert_interleaved_input( def legalise_einsum_expr(*operands: Any) -> str: - """ - Reproduction of einsum c side einsum parsing in python. **Parameters:** Intakes the - same inputs as `contract_path`, but NOT the keyword args. The only. + """Reproduction of einsum c side einsum parsing in python. **Parameters:** + Intakes the same inputs as `contract_path`, but NOT the keyword args. The + only. supported keyword argument is: - **shapes** - *(bool, optional)* Whether @@ -238,6 +233,7 @@ def legalise_einsum_expr(*operands: Any) -> str: ------- einsum_eqn : str Legalised einsum equation + Examples -------- The operand list is simplified to reduce printing: diff --git a/ivy/utils/einsum_path_helpers.py b/ivy/utils/einsum_path_helpers.py index c627bc0894962..465a0122e695e 100644 --- a/ivy/utils/einsum_path_helpers.py +++ b/ivy/utils/einsum_path_helpers.py @@ -11,8 +11,7 @@ def flop_count(idx_contraction, inner, num_terms, size_dictionary): - """ - Compute the number of FLOPS in the contraction. + """Compute the number of FLOPS in the contraction. Parameters ---------- @@ -47,8 +46,8 @@ def flop_count(idx_contraction, inner, num_terms, size_dictionary): def compute_size_by_dict(indices, idx_dict): - """ - Compute the product of the elements in indices based on the dictionary idx_dict. + """Compute the product of the elements in indices based on the dictionary + idx_dict. Parameters ---------- @@ -74,8 +73,7 @@ def compute_size_by_dict(indices, idx_dict): def find_contraction(positions, input_sets, output_set): - """ - Find the contraction for a given set of input and output sets. + """Find the contraction for a given set of input and output sets. Parameters ---------- @@ -131,10 +129,9 @@ def find_contraction(positions, input_sets, output_set): def optimal_path(input_sets, output_set, idx_dict, memory_limit): - """ - Compute all possible pair contractions, sieves the results based on ``memory_limit`` - and returns the lowest cost path. This algorithm scales factorial with respect to - the elements in the list ``input_sets``. + """Compute all possible pair contractions, sieves the results based on + ``memory_limit`` and returns the lowest cost path. This algorithm scales + factorial with respect to the elements in the list ``input_sets``. Parameters ---------- @@ -204,9 +201,8 @@ def optimal_path(input_sets, output_set, idx_dict, memory_limit): def parse_possible_contraction( positions, input_sets, output_set, idx_dict, memory_limit, path_cost, naive_cost ): - """ - Compute the cost (removed size + flops) and resultant indices for performing the - contraction specified by ``positions``. + """Compute the cost (removed size + flops) and resultant indices for + performing the contraction specified by ``positions``. Parameters ---------- @@ -261,9 +257,9 @@ def parse_possible_contraction( def update_other_results(results, best): - """ - Update the positions and provisional input_sets of ``results`` based on performing - the contraction result ``best``. Remove any involving the tensors contracted. + """Update the positions and provisional input_sets of ``results`` based on + performing the contraction result ``best``. Remove any involving the + tensors contracted. Parameters ---------- @@ -299,12 +295,12 @@ def update_other_results(results, best): def greedy_path(input_sets, output_set, idx_dict, memory_limit): - """ - Find the path by contracting the best pair until the input list is exhausted. The - best pair is found by minimizing the tuple ``(-prod(indices_removed), cost)``. What - this amounts to is prioritizing matrix multiplication or inner product operations, - then Hadamard like operations, and finally outer operations. Outer products are - limited by ``memory_limit``. This algorithm scales cubically with respect to the + """Find the path by contracting the best pair until the input list is + exhausted. The best pair is found by minimizing the tuple + ``(-prod(indices_removed), cost)``. What this amounts to is prioritizing + matrix multiplication or inner product operations, then Hadamard like + operations, and finally outer operations. Outer products are limited by + ``memory_limit``. This algorithm scales cubically with respect to the number of elements in the list ``input_sets``. Parameters @@ -411,8 +407,8 @@ def greedy_path(input_sets, output_set, idx_dict, memory_limit): def can_dot(inputs, result, idx_removed): - """ - Check if we can use BLAS (np.tensordot) call and its beneficial to do so. + """Check if we can use BLAS (np.tensordot) call and its beneficial to do + so. Parameters ---------- @@ -514,8 +510,7 @@ def can_dot(inputs, result, idx_removed): def parse_einsum_input(operands, subscripts=None): - """ - Reproduction of einsum c side einsum parsing in python. + """Reproduction of einsum c side einsum parsing in python. Returns ------- @@ -609,12 +604,12 @@ def parse_einsum_input(operands, subscripts=None): tmp_subscripts = subscripts.replace(",", "") for s in sorted(set(tmp_subscripts)): if s not in (einsum_symbols): - raise ValueError("Character %s is not a valid symbol." % s) + raise ValueError(f"Character {s} is not a valid symbol.") if tmp_subscripts.count(s) == 1: output_subscript += s normal_inds = "".join(sorted(set(output_subscript) - set(out_ellipse))) - subscripts += "->" + out_ellipse + normal_inds + subscripts += f"->{out_ellipse}{normal_inds}" # Build output string if does not exist if "->" in subscripts: @@ -626,14 +621,14 @@ def parse_einsum_input(operands, subscripts=None): output_subscript = "" for s in sorted(set(tmp_subscripts)): if s not in einsum_symbols: - raise ValueError("Character %s is not a valid symbol." % s) + raise ValueError(f"Character {s} is not a valid symbol.") if tmp_subscripts.count(s) == 1: output_subscript += s # Make sure output subscripts are in the input for char in output_subscript: if char not in input_subscripts: - raise ValueError("Output character %s did not appear in the input" % char) + raise ValueError(f"Output character {char} did not appear in the input") # Make sure number operands is equivalent to the number of terms if len(input_subscripts.split(",")) != len(operands): diff --git a/ivy/utils/exceptions.py b/ivy/utils/exceptions.py index d95aa7c55a337..d8f35b27a5b0e 100644 --- a/ivy/utils/exceptions.py +++ b/ivy/utils/exceptions.py @@ -141,8 +141,7 @@ def _get_traces(curr_obj, area, local_dict, target_name): def _check_if_path_found(path, full_path): - """ - Check if the path is found in the full path. + """Check if the path is found in the full path. Parameters ---------- @@ -156,15 +155,11 @@ def _check_if_path_found(path, full_path): ret True if the path is found, False otherwise """ - if path in full_path: - return True - else: - return False + return path in full_path def _configure_stack_trace(traceback): - """ - Configure the stack trace to be displayed in the console. + """Configure the stack trace to be displayed in the console. Parameters ---------- @@ -179,7 +174,7 @@ def _configure_stack_trace(traceback): frontend_path = os.path.join("ivy", "functional", "frontends") wrapper_path = os.path.join("ivy", "func_wrapper.py") - while 1 and tb.tb_next: + while tb.tb_next: frame = tb.tb_next.tb_frame file_path = frame.f_code.co_filename if trace_mode == "ivy": @@ -204,8 +199,7 @@ def _configure_stack_trace(traceback): def _add_native_error(default): - """ - Append the native error to the message if it exists. + """Append the native error to the message if it exists. Parameters ---------- @@ -338,8 +332,7 @@ def __init__(self, *messages, include_backend=False): def handle_exceptions(fn: Callable) -> Callable: @functools.wraps(fn) def _handle_exceptions(*args, **kwargs): - """ - Catch all exceptions and raise them in IvyException. + """Catch all exceptions and raise them in IvyException. Parameters ---------- diff --git a/ivy/utils/inspection.py b/ivy/utils/inspection.py index 2fa60f6f9d839..77feceb756833 100644 --- a/ivy/utils/inspection.py +++ b/ivy/utils/inspection.py @@ -90,9 +90,8 @@ def _get_array_idxs(typ, idx_so_far=None): def fn_array_spec(fn): - """ - Return a specification of the function, indicating all arguments which include - arrays, and the indexes of these. + """Return a specification of the function, indicating all arguments which + include arrays, and the indexes of these. Parameters ---------- diff --git a/ivy/utils/logging.py b/ivy/utils/logging.py index 498424a976cb4..977f3add6f5ec 100644 --- a/ivy/utils/logging.py +++ b/ivy/utils/logging.py @@ -7,8 +7,7 @@ def set_logging_mode(mode): - """ - Set the current logging mode for Ivy. + """Set the current logging mode for Ivy. Possible modes are 'DEBUG', 'INFO', 'WARNING', 'ERROR'. """ @@ -22,7 +21,8 @@ def set_logging_mode(mode): def unset_logging_mode(): - """Remove the most recently set logging mode, returning to the previous one.""" + """Remove the most recently set logging mode, returning to the previous + one.""" if len(logging_mode_stack) > 1: # Remove the current mode logging_mode_stack.pop() diff --git a/ivy/utils/profiler.py b/ivy/utils/profiler.py index c168b1ce7253e..7558dce70d32a 100644 --- a/ivy/utils/profiler.py +++ b/ivy/utils/profiler.py @@ -9,8 +9,7 @@ class Profiler(cProfile.Profile): - """ - A Profiler class that allows code profiling. + """A Profiler class that allows code profiling. Attributes ---------- @@ -54,3 +53,162 @@ def __exit__(self, *exc): if self.print_stats: stats.print_stats() + + +def tensorflow_profile_start( + logdir: str, + host_tracer_level: int = 2, + python_tracer_level: int = 0, + device_tracer_level: int = 1, + delay_ms: int = None, +): + """Initialize and start the profiler. + + Parameters + ---------- + logdir: str + Directory where the profile data will be saved to. + host_tracer_level: int + Adjust CPU tracing level. Values are: 1 - critical info only, 2 - info, 3 - verbose. [default value is 2] + python_tracer_level: int + Toggle tracing of Python function calls. Values are: 1 - enabled, 0 - disabled [default value is 0] + device_tracer_level: int + Adjust device (TPU/GPU) tracing level. Values are: 1 - enabled, 0 - disabled [default value is 1] + delay_ms: int + Requests for all hosts to start profiling at a timestamp that is delay_ms away from the current time. delay_ms is in milliseconds. If zero, each host will start profiling immediately upon receiving the request. Default value is None, allowing the profiler guess the best value. + Save the weights on the Module. + + Returns + ------- + None + """ # noqa: E501 + from tensorflow.profiler.experimental import ProfilerOptions, start + + options = ProfilerOptions( + host_tracer_level=host_tracer_level, + python_tracer_level=python_tracer_level, + device_tracer_level=device_tracer_level, + delay_ms=delay_ms, + ) + start(logdir, options=options) + + +def tensorflow_profile_stop(): + """Stop the profiler.""" + from tensorflow.profiler.experimental import stop + + stop() + + +def torch_profiler_init( + logdir=None, + activities=None, + schedule=None, + on_trace_ready=None, + record_shapes=False, + profile_memory=False, + with_stack=False, + with_flops=False, + with_modules=False, + experimental_config=None, +): + """Initialize and returns a Torch profiler instance. + + Parameters + ---------- + logdir : str + Directory where the profile data will be saved to. + + activities : iterable + list of activity groups (CPU, CUDA) to use in profiling, supported values: + ``torch.profiler.ProfilerActivity.CPU``, ``torch.profiler.ProfilerActivity.CUDA``. + Default value: ProfilerActivity.CPU and (when available) ProfilerActivity.CUDA. + + schedule : Callable + callable that takes step (int) as a single parameter and returns + ``ProfilerAction`` value that specifies the profiler action to perform at each step. + + on_trace_ready : Callable + callable that is called at each step when ``schedule`` + returns ``ProfilerAction.RECORD_AND_SAVE`` during the profiling. + + record_shapes : bool + save information about operator's input shapes. + + profile_memory : bool + track tensor memory allocation/deallocation. + + with_stack : bool + record source information (file and line number) for the ops. + + with_flops : bool + use formula to estimate the FLOPs (floating point operations) of specific operators + (matrix multiplication and 2D convolution). + + with_modules : bool + record module hierarchy (including function names) + corresponding to the callstack of the op. e.g. If module A's forward call's + module B's forward which contains an aten::add op, then aten::add's module hierarchy is A.B + Note that this support exist, at the moment, only for TorchScript models + and not eager mode models. + + experimental_config _ExperimentalConfig : _ExperimentalConfig + A set of experimental options + used for Kineto library features. Note, backward compatibility is not guaranteed. + + Returns + ------- + Torch profiler instance. + """ # noqa: E501 + from torch.profiler import profile, tensorboard_trace_handler + + profiler = profile( + activities=activities, + schedule=schedule, + on_trace_ready=( + tensorboard_trace_handler(logdir) + if on_trace_ready is None and logdir is not None + else on_trace_ready + ), + record_shapes=record_shapes, + profile_memory=profile_memory, + with_stack=with_stack, + with_flops=with_flops, + with_modules=with_modules, + experimental_config=experimental_config, + ) + return profiler + + +def torch_profiler_start(profiler): + """Start the profiler. + + Parameters + ---------- + profiler : torch.profiler.profile + Torch profiler instance. + + Returns + ------- + None + """ + profiler.start() + + +def torch_profiler_stop(profiler): + """Start the profiler. + + Parameters + ---------- + profiler : torch.profiler.profile + Torch profiler instance. + + Returns + ------- + None + """ + from torch.autograd.profiler import KinetoStepTracker + from torch.profiler.profiler import PROFILER_STEP_NAME + + profiler.stop() + KinetoStepTracker.erase_step_count(PROFILER_STEP_NAME) diff --git a/ivy/utils/profiler_example.ipynb b/ivy/utils/profiler_example.ipynb new file mode 100644 index 0000000000000..a49999df0bd8d --- /dev/null +++ b/ivy/utils/profiler_example.ipynb @@ -0,0 +1,143 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import torch\n", + "from torch import nn\n", + "import tensorflow as tf\n", + "import numpy as np" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "class TFModel(tf.keras.Model):\n", + " def __init__(self):\n", + " super().__init__()\n", + " self.lin = tf.keras.layers.Dense(10, activation=tf.nn.relu)\n", + " \n", + " def call(self, inputs, training=False):\n", + " return self.lin(inputs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "class TorchModel(nn.Module):\n", + " def __init__(self):\n", + " super().__init__()\n", + " self.lin = nn.Linear(10, 10)\n", + " \n", + " def forward(self, x):\n", + " return self.lin(x)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "tf_model = tf.function(TFModel()) \n", + "inp = np.random.random((10, 10))\n", + "x = tf.convert_to_tensor(inp, dtype=tf.float32)\n", + "tf_model(x)\n", + "\n", + "tf_model.summary()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "torch_model = torch.compile(TorchModel())\n", + "inp2 = np.random.random((10, 10)).astype(np.float32)\n", + "x2 = torch.from_numpy(inp2)\n", + "torch_model, torch_model(x2).shape" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Creating the Profiler Logs TensorFlow" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "logs = 'logs/' + \"tensorflow\"\n", + "\n", + "from ivy.utils.profiler import tensorflow_profile_start, tensorflow_profile_stop\n", + "tensorflow_profile_start(logs, \n", + " host_tracer_level = 3,\n", + " python_tracer_level = 1,\n", + " device_tracer_level = 1)\n", + "tf_model(x)\n", + "tensorflow_profile_stop()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Launch TensorBoard and navigate to the Profile tab to view performance profile \n", + "!tensorboard --logdir='logs/'" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Creating the Profiler Logs Torch" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from ivy.utils.profiler import torch_profiler_init, torch_profiler_start, torch_profiler_stop\n", + "profiler = torch_profiler_init(activities=[torch.profiler.ProfilerActivity.CPU, torch.profiler.ProfilerActivity.CUDA ],\n", + " on_trace_ready=torch.profiler.tensorboard_trace_handler('./logs/torch'),\n", + " record_shapes=True,\n", + " profile_memory=True,\n", + " with_stack=True)\n", + "torch_profiler_start(profiler)\n", + "torch_model(x2)\n", + "torch_profiler_stop(profiler)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "multienv", + "language": "python", + "name": "python3" + }, + "language_info": { + "name": "python", + "version": "3.10.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/ivy/wrappers/__init__.py b/ivy/wrappers/__init__.py new file mode 100644 index 0000000000000..880046091c527 --- /dev/null +++ b/ivy/wrappers/__init__.py @@ -0,0 +1,29 @@ +import os +import sys +import glob +import importlib + +dir_path = os.path.dirname(os.path.realpath(__file__)) +so_files = glob.glob(dir_path + "/*.so") +sys.path.append(dir_path) + +__all__ = [] + +for so_file in so_files: + # if os.path.basename(so_file) != "add.so": + # continue + module_name = os.path.splitext(os.path.basename(so_file))[0] + + locals()[module_name] = importlib.import_module(module_name) + + if module_name + "_wrapper" in locals()[module_name].__dict__.keys(): + locals()[module_name + "_wrapper"] = getattr( + locals()[module_name], module_name + "_wrapper" + ) + __all__.append(module_name + "_wrapper") + +del dir_path +del so_files + +import utils +from utils import * diff --git a/ivy/wrappers/utils.py b/ivy/wrappers/utils.py new file mode 100644 index 0000000000000..7702f70f4456e --- /dev/null +++ b/ivy/wrappers/utils.py @@ -0,0 +1,55 @@ +import os +import logging +import json +from urllib import request +import importlib +import ivy + +folder_path = os.sep.join(__file__.split(os.sep)[:-3]) +wrappers_path = os.path.join(folder_path, "wrappers.json") +if os.path.exists(wrappers_path): + wrappers = json.loads(open(wrappers_path).read()) +wrapers_dir = os.path.join(folder_path, "ivy/wrappers") + + +def download_cython_wrapper(func_name: str): + """Get the wrapper for the given function name.""" + if func_name + ".so" not in wrappers["ivy"]["functional"]: + logging.warning(f"Wrapper for {func_name} not found.") + return False + try: + response = request.urlopen( + "https://raw.githubusercontent.com/unifyai" + + "/binaries/cython_wrappers/wrappers/" + + func_name + + ".so" + ) + os.makedirs(wrapers_dir, exist_ok=True) + with open(os.path.join(wrapers_dir, func_name + ".so"), "wb") as f: + f.write(response.read()) + print("Downloaded wrapper for " + func_name) + return True + except request.HTTPError: + logging.warning(f"Unable to download wrapper for {func_name}.") + return False + + +def wrapper_exists(func_name: str): + """Check if the wrapper for the given function name exists.""" + return func_name + ".so" in wrappers["ivy"]["functional"] + + +def load_one_wrapper(func_name: str): + """Load the wrapper for the given function name.""" + module_name = func_name + dir_path = os.path.dirname(os.path.realpath(__file__)) + # check if file exists + if os.path.isfile(os.path.join(dir_path, module_name + ".so")): + ivy.wrappers.__dict__[module_name] = importlib.import_module(module_name) + ivy.wrappers.__dict__[module_name + "_wrapper"] = getattr( + ivy.wrappers.__dict__[module_name], module_name + "_wrapper" + ) + ivy.wrappers.__all__.append(module_name + "_wrapper") + return True + else: + return False diff --git a/ivy_tests/__init__.py b/ivy_tests/__init__.py index c4f97ca7a59c2..2452ba2f6226d 100644 --- a/ivy_tests/__init__.py +++ b/ivy_tests/__init__.py @@ -1,6 +1,6 @@ try: - from jax.config import config + import jax - config.update("jax_enable_x64", True) + jax.config.update("jax_enable_x64", True) except (ImportError, RuntimeError): pass diff --git a/ivy_tests/array_api_testing/write_array_api_tests_k_flag.py b/ivy_tests/array_api_testing/write_array_api_tests_k_flag.py index 0269fd5a42f96..02d639cda2189 100644 --- a/ivy_tests/array_api_testing/write_array_api_tests_k_flag.py +++ b/ivy_tests/array_api_testing/write_array_api_tests_k_flag.py @@ -44,8 +44,8 @@ and any(f in s.lower() for f in framework_tests_to_run) ): tests_to_run += ( - ["test_" + s] - if ("#" not in s) + [f"test_{s}"] + if "#" not in s else ["test_" + s.split("#")[1].split(" ")[0]] ) else: @@ -58,7 +58,7 @@ framework_tests_to_skip[framework] = [ tts for tts in framework_tests_to_skip[framework] - if not max([tts in ttr for ttr in framework_tests_to_run[framework]]) + if not max(tts in ttr for ttr in framework_tests_to_run[framework]) ] diff --git a/ivy_tests/conftest.py b/ivy_tests/conftest.py index e573de819178c..c79160013ec4b 100644 --- a/ivy_tests/conftest.py +++ b/ivy_tests/conftest.py @@ -109,7 +109,7 @@ def pytest_configure(config): max_examples = getopt("--num-examples") deadline = getopt("--deadline") if ( - os.getenv("REDIS_URL", default=False) + os.getenv("REDIS_URL", default=None) and os.environ["REDIS_URL"] and is_db_available( master=True, @@ -139,6 +139,8 @@ def pytest_configure(config): if max_examples: profile_settings["max_examples"] = max_examples + else: + profile_settings["max_examples"] = 10 if deadline: profile_settings["deadline"] = deadline diff --git a/ivy_tests/test_docstrings.py b/ivy_tests/test_docstrings.py index ab26afe70714a..0cc34ffed62ff 100644 --- a/ivy_tests/test_docstrings.py +++ b/ivy_tests/test_docstrings.py @@ -6,6 +6,7 @@ import numpy as np import sys + warnings.filterwarnings("ignore", category=DeprecationWarning) import pytest @@ -51,8 +52,7 @@ def trim(*, docstring): def check_docstring_examples_run( *, fn, from_container=False, from_array=False, num_sig_fig=2 ): - """ - Performs docstring tests for a given function. + """Performs docstring tests for a given function. Parameters ---------- @@ -69,7 +69,6 @@ def check_docstring_examples_run( ------- None if the test passes, else marks the test as failed. """ - """ Functions skipped as their output dependent on outside factors: @@ -117,60 +116,38 @@ def check_docstring_examples_run( # the temp skip list consists of functions # which have an issue with their implementation skip_list_temp = [ - "outer", - "argmax", - "split", - "det", - "cumprod", - "sinc", - "grad", - "try_else_none", - # all examples are wrong including functional/ivy - "einops_reduce", - "max_unpool1d", - "pool", - "put_along_axis", - "result_type", - # works only if no backend set - "rfftn", - # examples works but exec throws error or generate diff results - "scaled_dot_product_attention", - "searchsorted", - # generates different results in different backends - "eigh_tridiagonal", - "log_poisson_loss", + "outer", # Failing only torch backend as inputs must be 1-D. + "pool", # Maximum recursion depth exceeded ivy.pool + "put_along_axis", # Depends on scatter_nd for numpy. + "result_type", # Different ouput coming for diff backends in 1st example. + "scaled_dot_product_attention", # Different backends giving different answers. + "eigh_tridiagonal", # Failing only for TF backend "dct", - "idct", - "set_item", - "l1_normalize", - "histogram", - "native_array", - "function_supported_devices", - "acosh", - "bitwise_invert", - "cosh", - "exp", - "sinh", - "reciprocal", - "deg2rad", - "value_and_grad", - "vector_norm", - "set_nest_at_index", - "set_nest_at_indices", - "layer_norm", - "where", - "trace", - "eigvalsh", - "conv2d_transpose", - # fails due to different backend and their view types - "sequence_length", - "max_pool1d", - "vmap", - "inner", - "slogdet", - "svdvals", - "nested_map", + "choose", # Maximum recurion depth exceeded (No backend choose fn). + "idct", # Function already failing for all 5 backends. + "set_item", # Different errors for diff backends (jax, torch) + "l1_normalize", # Function already failing for all 5 backends. + "histogram", # Failing for TF, Torch backends (TODO's left) + "value_and_grad", # Failing only for Torch backend. (Requires_grad=True) + "layer_norm", # Failing only for Torch backend. + "eigvalsh", # Failing only Jax Backend + only for Native Array Example. + "conv2d_transpose", # Function already failing for all 5 backends. + "solve", + "one_hot", # One small example failing for all backends except torch. + "scatter_flat", # Function Already failing for 3 backends + "scatter_nd", # + "execute_with_gradients", # Function Already failing for 4 backends. + "gather", + "multiprocessing", + "if_else", + "trace_graph", # SystemExit: Please sign up for free pilot access. "dill", + "smooth_l1_loss", # Function already failing for all 5 backends. + "cummax", # Function already failing for all 5 backends. + "insert_into_nest_at_index", + "while_loop", + "argmax", + "native_array", ] # skip list for array and container docstrings @@ -190,6 +167,18 @@ def check_docstring_examples_run( "scaled_dot_product_attention", # temp list for array/container methods "einops_reduce", + "array_equal", + "batched_outer", + "huber_loss", + "softshrink", + "tt_matrix_to_tensor", + "unsorted_segment_mean", + "array_equal", + "batched_outer", + "huber_loss", + "kl_div", + "soft_margin_loss", + "threshold", ] # comment out the line below in future to check for the functions in temp skip list diff --git a/ivy_tests/test_ivy/conftest.py b/ivy_tests/test_ivy/conftest.py index cb66bbf670211..13731b6f5eb4e 100644 --- a/ivy_tests/test_ivy/conftest.py +++ b/ivy_tests/test_ivy/conftest.py @@ -28,7 +28,7 @@ UNSET_TEST_API_CONFIG = {"list": [], "flag": []} TEST_PARAMS_CONFIG = [] -SKIP_GROUND_TRUTH = True +SKIP_GROUND_TRUTH = False UNSUPPORTED_FRAEMWORK_DEVICES = {"numpy": ["gpu", "tpu"]} if "ARRAY_API_TESTS_MODULE" not in os.environ: os.environ["ARRAY_API_TESTS_MODULE"] = "ivy.functional.backends.numpy" @@ -191,7 +191,7 @@ def pytest_configure(config): if "/" in backend_str: backend_str = backend_str.split("/")[0] if ( - backend_str in UNSUPPORTED_FRAEMWORK_DEVICES.keys() + backend_str in UNSUPPORTED_FRAEMWORK_DEVICES and device.partition(":")[0] in UNSUPPORTED_FRAEMWORK_DEVICES[backend_str] ): @@ -290,15 +290,23 @@ def process_cl_flags(config) -> Dict[str, bool]: getopt("--skip-trace-testing"), getopt("--with-trace-testing"), ), + "test_trace_each": ( + getopt("--skip-trace-testing-each"), + getopt("--with-trace-testing-each"), + ), "transpile": ( False, getopt("--with-transpile"), ), + "test_cython_wrapper": ( + getopt("--skip-cython-wrapper-testing"), + getopt("--with-cython-wrapper-testing"), + ), } # whether to skip gt testing or not - global SKIP_GROUND_TRUTH - SKIP_GROUND_TRUTH = not tmp_config["transpile"][1] + # global SKIP_GROUND_TRUTH + # SKIP_GROUND_TRUTH = not tmp_config["transpile"][1] # final mapping for hypothesis value generation for k, v in tmp_config.items(): @@ -344,6 +352,7 @@ def pytest_addoption(parser): parser.addoption("--skip-instance-method-testing", action="store_true") parser.addoption("--skip-gradient-testing", action="store_true") parser.addoption("--skip-trace-testing", action="store_true") + parser.addoption("--skip-trace-testing-each", action="store_true") parser.addoption("--with-variable-testing", action="store_true") parser.addoption("--with-native-array-testing", action="store_true") @@ -352,6 +361,7 @@ def pytest_addoption(parser): parser.addoption("--with-instance-method-testing", action="store_true") parser.addoption("--with-gradient-testing", action="store_true") parser.addoption("--with-trace-testing", action="store_true") + parser.addoption("--with-trace-testing-each", action="store_true") parser.addoption("--with-transpile", action="store_true") parser.addoption("--no-extra-testing", action="store_true") parser.addoption( @@ -360,6 +370,8 @@ def pytest_addoption(parser): default=None, help="Print test items in my custom format", ) + parser.addoption("--skip-cython-wrapper-testing", action="store_true") + parser.addoption("--with-cython-wrapper-testing", action="store_true") def pytest_collection_finish(session): diff --git a/ivy_tests/test_ivy/helpers/assertions.py b/ivy_tests/test_ivy/helpers/assertions.py index 539d01b0d9243..5da824e9a8ca6 100644 --- a/ivy_tests/test_ivy/helpers/assertions.py +++ b/ivy_tests/test_ivy/helpers/assertions.py @@ -18,9 +18,8 @@ def assert_all_close( atol=1e-08, ground_truth_backend="TensorFlow", ): - """ - Match the ret_np and ret_from_gt_np inputs element-by-element to ensure that they - are the same. + """Match the ret_np and ret_from_gt_np inputs element-by-element to ensure + that they are the same. Parameters ---------- @@ -59,6 +58,8 @@ def assert_all_close( f" the results from backend {backend} " f"and ground truth framework {ground_truth_backend} " f"do not match\n {ret_np}!={ret_from_gt_np} \n\n" + "The mismatching elements are at `False` indices:\n\n" + f"{ret_np == ret_from_gt_np} \n\n" ) @@ -77,9 +78,8 @@ def assert_same_type_and_shape(values, this_key_chain=None): def assert_same_type(ret_from_target, ret_from_gt, backend_to_test, gt_backend): - """ - Assert that the return types from the target and ground truth frameworks are the - same. + """Assert that the return types from the target and ground truth frameworks + are the same. checks with a string comparison because with_backend returns different objects. Doesn't check recursively. @@ -108,8 +108,8 @@ def value_test( backend: str, ground_truth_backend="TensorFlow", ): - """ - Perform a value test for matching the arrays in ret_np_flat and ret_from_np_gt_flat. + """Perform a value test for matching the arrays in ret_np_flat and + ret_from_np_gt_flat. Parameters ---------- @@ -184,9 +184,8 @@ def value_test( def check_unsupported_dtype(*, fn, input_dtypes, all_as_kwargs_np): - """ - Check whether a function does not support the input data types or the output data - type. + """Check whether a function does not support the input data types or the + output data type. Parameters ---------- @@ -212,6 +211,7 @@ def check_unsupported_dtype(*, fn, input_dtypes, all_as_kwargs_np): break if ( "dtype" in all_as_kwargs_np + and all_as_kwargs_np["dtype"] is not None and all_as_kwargs_np["dtype"] in unsupported_dtypes_fn ): test_unsupported = True @@ -222,6 +222,7 @@ def check_unsupported_dtype(*, fn, input_dtypes, all_as_kwargs_np): break if ( "dtype" in all_as_kwargs_np + and all_as_kwargs_np["dtype"] is not None and all_as_kwargs_np["dtype"] not in supported_dtypes_fn ): test_unsupported = True @@ -229,8 +230,7 @@ def check_unsupported_dtype(*, fn, input_dtypes, all_as_kwargs_np): def check_unsupported_device(*, fn, input_device, all_as_kwargs_np): - """ - Check whether a function does not support a given device. + """Check whether a function does not support a given device. Parameters ---------- @@ -268,8 +268,7 @@ def check_unsupported_device(*, fn, input_device, all_as_kwargs_np): def check_unsupported_device_and_dtype(*, fn, device, input_dtypes, all_as_kwargs_np): - """ - Check whether a function does not support a given device or data types. + """Check whether a function does not support a given device or data types. Parameters ---------- @@ -304,8 +303,7 @@ def check_unsupported_device_and_dtype(*, fn, device, input_dtypes, all_as_kwarg def test_unsupported_function(*, fn, args, kwargs): - """ - Test a function with an unsupported datatype to raise an exception. + """Test a function with an unsupported datatype to raise an exception. Parameters ---------- diff --git a/ivy_tests/test_ivy/helpers/function_testing.py b/ivy_tests/test_ivy/helpers/function_testing.py index 4529bfd2e9a8a..6d7ecd8ebbd5b 100644 --- a/ivy_tests/test_ivy/helpers/function_testing.py +++ b/ivy_tests/test_ivy/helpers/function_testing.py @@ -1,7 +1,7 @@ # global import copy import time -from typing import Union, List +from typing import Union, List, Optional import numpy as np import types import importlib @@ -35,10 +35,49 @@ # Temporary (.so) configuration -def traced_if_required(backend: str, fn, test_trace=False, args=None, kwargs=None): +def traced_if_required( + backend: str, fn, test_trace=False, test_trace_each=False, args=None, kwargs=None +): with BackendHandler.update_backend(backend) as ivy_backend: - if test_trace: - fn = ivy_backend.trace_graph(fn, args=args, kwargs=kwargs) + try: + if test_trace: + if ( + t_globals.CURRENT_RUNNING_TEST.fn_name + in t_globals.CURRENT_TRACED_DATA + and backend + not in t_globals.CURRENT_TRACED_DATA[ + t_globals.CURRENT_RUNNING_TEST.fn_name + ] + ): + t_globals.CURRENT_TRACED_DATA[ + t_globals.CURRENT_RUNNING_TEST.fn_name + ][backend] = ivy_backend.trace_graph( + fn, args=args, kwargs=kwargs, backend_compile=True + ) + elif ( + t_globals.CURRENT_RUNNING_TEST.fn_name + not in t_globals.CURRENT_TRACED_DATA + ): + t_globals.CURRENT_TRACED_DATA[ + t_globals.CURRENT_RUNNING_TEST.fn_name + ] = {} + t_globals.CURRENT_TRACED_DATA[ + t_globals.CURRENT_RUNNING_TEST.fn_name + ][backend] = ivy_backend.trace_graph( + fn, args=args, kwargs=kwargs, backend_compile=True + ) + fn = t_globals.CURRENT_TRACED_DATA[ + t_globals.CURRENT_RUNNING_TEST.fn_name + ][backend] + if test_trace_each: + fn = ivy_backend.trace_graph( + fn, args=args, kwargs=kwargs, backend_compile=True + ) + except Exception: + import logging + + logging.warning("API key is invalid, test_trace is skipped.") + return fn @@ -48,9 +87,8 @@ def traced_if_required(backend: str, fn, test_trace=False, args=None, kwargs=Non def _find_instance_in_args(backend: str, args, array_indices, mask): - """ - Find the first element in the arguments that is considered to be an instance of - Array or Container class. + """Find the first element in the arguments that is considered to be an + instance of Array or Container class. Parameters ---------- @@ -127,6 +165,11 @@ def test_function_backend_computation( test_flags.container[0] for _ in range(total_num_arrays) ] + if test_flags.test_cython_wrapper: + ivy.set_cython_wrappers_mode(True) + else: + ivy.set_cython_wrappers_mode(False) + with BackendHandler.update_backend(fw) as ivy_backend: # Update variable flags to be compatible with float dtype and with_out args test_flags.as_variable = [ @@ -159,7 +202,7 @@ def test_function_backend_computation( if ("out" in kwargs or test_flags.with_out) and "out" not in inspect.signature( getattr(ivy, fn_name) ).parameters: - raise Exception(f"Function {fn_name} does not have an out parameter") + raise RuntimeError(f"Function {fn_name} does not have an out parameter") # Run either as an instance method or from the API directly with BackendHandler.update_backend(fw) as ivy_backend: @@ -190,7 +233,7 @@ def test_function_backend_computation( fw, kwargs, arrays_kwargs_indices, kwargs_instance_mask ) - if test_flags.test_trace: + if test_flags.test_trace or test_flags.test_trace_each: def target_fn(instance, *args, **kwargs): return instance.__getattribute__(fn_name)(*args, **kwargs) @@ -210,6 +253,8 @@ def target_fn(instance, *args, **kwargs): target_fn, *copy_args, test_trace=test_flags.test_trace, + test_trace_each=test_flags.test_trace_each, + precision_mode=test_flags.precision_mode, **copy_kwargs, ) @@ -219,7 +264,9 @@ def target_fn(instance, *args, **kwargs): ), f"Ivy function returned non-ivy arrays: {ret_from_target}" # Assert indices of return if the indices of the out array provided - if test_flags.with_out and not test_flags.test_trace: + if test_flags.with_out and not ( + test_flags.test_trace or test_flags.test_trace_each + ): test_ret = ( ret_from_target[getattr(ivy_backend.__dict__[fn_name], "out_index")] if hasattr(ivy_backend.__dict__[fn_name], "out_index") @@ -233,14 +280,24 @@ def target_fn(instance, *args, **kwargs): ret_from_target, ret_np_flat_from_target, ) = get_ret_and_flattened_np_array( - fw, instance.__getattribute__(fn_name), *args, **kwargs, out=out + fw, + instance.__getattribute__(fn_name), + *args, + **kwargs, + out=out, + precision_mode=test_flags.precision_mode, ) else: ( ret_from_target, ret_np_flat_from_target, ) = get_ret_and_flattened_np_array( - fw, ivy_backend.__dict__[fn_name], *args, **kwargs, out=out + fw, + ivy_backend.__dict__[fn_name], + *args, + **kwargs, + out=out, + precision_mode=test_flags.precision_mode, ) test_ret = ( ret_from_target[getattr(ivy_backend.__dict__[fn_name], "out_index")] @@ -279,9 +336,12 @@ def target_fn(instance, *args, **kwargs): target_fn, *args, test_trace=test_flags.test_trace, + test_trace_each=test_flags.test_trace_each, precision_mode=test_flags.precision_mode, **kwargs, ) + first_array = ivy_backend.stop_gradient(first_array).to_numpy() + ret_ = ivy_backend.stop_gradient(ret_).to_numpy() assert not np.may_share_memory(first_array, ret_) ret_device = None @@ -334,6 +394,7 @@ def test_function_ground_truth_computation( gt_backend.__dict__[fn_name], *args, test_trace=test_flags.test_trace, + test_trace_each=test_flags.test_trace_each, precision_mode=test_flags.precision_mode, **kwargs, ) @@ -341,7 +402,9 @@ def test_function_ground_truth_computation( lambda x: gt_backend.is_ivy_array(x) if gt_backend.is_array(x) else True, ret_from_gt, ), f"Ground-truth function returned non-ivy arrays: {ret_from_gt}" - if test_flags.with_out and not test_flags.test_trace: + if test_flags.with_out and not ( + test_flags.test_trace or test_flags.test_trace_each + ): test_ret_from_gt = ( ret_from_gt[getattr(gt_backend.__dict__[fn_name], "out_index")] if hasattr(gt_backend.__dict__[fn_name], "out_index") @@ -358,6 +421,7 @@ def test_function_ground_truth_computation( gt_backend.__dict__[fn_name], *args, test_trace=test_flags.test_trace, + test_trace_each=test_flags.test_trace_each, precision_mode=test_flags.precision_mode, **kwargs, out=out_from_gt, @@ -376,9 +440,9 @@ def test_function( input_dtypes: Union[ivy.Dtype, List[ivy.Dtype]], test_flags: FunctionTestFlags, fn_name: str, - rtol_: float = None, + rtol_: Optional[float] = None, atol_: float = 1e-06, - tolerance_dict: dict = None, + tolerance_dict: Optional[dict] = None, test_values: bool = True, xs_grad_idxs=None, ret_grad_idxs=None, @@ -387,9 +451,8 @@ def test_function( return_flat_np_arrays: bool = False, **all_as_kwargs_np, ): - """ - Test a function that consumes (or returns) arrays for the current backend by - comparing the result with numpy. + """Test a function that consumes (or returns) arrays for the current + backend by comparing the result with numpy. Parameters ---------- @@ -469,7 +532,9 @@ def test_function( >>> x2 = np.array([-3, 15, 24]) >>> test_function(input_dtypes, test_flags, fw, fn_name, x1=x1, x2=x2) """ - _switch_backend_context(test_flags.test_trace or test_flags.transpile) + _switch_backend_context( + test_flags.test_trace or test_flags.test_trace_each or test_flags.transpile + ) ground_truth_backend = test_flags.ground_truth_backend if test_flags.container[0]: @@ -645,9 +710,13 @@ def test_function( backend=backend_to_test, ground_truth_backend=test_flags.ground_truth_backend, ) - assert_same_type( - ret_from_target, ret_from_gt, backend_to_test, test_flags.ground_truth_backend - ) + if not (test_flags.test_trace or test_flags.test_trace_each): + assert_same_type( + ret_from_target, + ret_from_gt, + backend_to_test, + test_flags.ground_truth_backend, + ) assert ret_device == ret_from_gt_device, ( f"ground truth backend ({test_flags.ground_truth_backend}) returned array on" @@ -688,7 +757,7 @@ def _transpile_if_required_backend(backend: str, fn_name: str, args=None, kwargs args, kwargs = ivy_backend.args_to_ivy(*args, **kwargs) backend_fn = ivy.__dict__[fn_name] backend_traced_fn = traced_if_required( - backend, backend_fn, test_trace=True, args=args, kwargs=kwargs + backend, backend_fn, test_trace_each=True, args=args, kwargs=kwargs ) func_timings = [] @@ -720,16 +789,15 @@ def test_frontend_function( on_device="cpu", frontend: str, fn_tree: str, - gt_fn_tree: str = None, - rtol: float = None, + gt_fn_tree: Optional[str] = None, + rtol: Optional[float] = None, atol: float = 1e-06, - tolerance_dict: dict = None, + tolerance_dict: Optional[dict] = None, test_values: bool = True, **all_as_kwargs_np, ): - """ - Test a frontend function for the current backend by comparing the result with the - function in the associated framework. + """Test a frontend function for the current backend by comparing the result + with the function in the associated framework. Parameters ---------- @@ -755,6 +823,8 @@ def test_frontend_function( if True, test for the correctness of the resulting values. all_as_kwargs_np input arguments to the function as keyword arguments. + If an input argument has the same name as any other parameter + of this function, add "arg_" before the argument name. Returns ------- @@ -764,7 +834,9 @@ def test_frontend_function( optional, return value from the Numpy function """ # ToDo add with_backend refactor in GC - _switch_backend_context(test_flags.test_trace or test_flags.transpile) + _switch_backend_context( + test_flags.test_trace or test_flags.test_trace_each or test_flags.transpile + ) assert ( not test_flags.with_out or not test_flags.inplace @@ -774,6 +846,10 @@ def test_frontend_function( test_flags.with_out = False test_flags.inplace = False + all_as_kwargs_np = { + k[4:] if k.startswith("arg_") else k: v for k, v in all_as_kwargs_np.items() + } + # split the arguments into their positional and keyword components args_np, kwargs_np = kwargs_to_args_n_kwargs( num_positional_args=test_flags.num_positional_args, kwargs=all_as_kwargs_np @@ -864,8 +940,11 @@ def test_frontend_function( frontend_fn, *args_for_test, test_trace=test_flags.test_trace, + test_trace_each=test_flags.test_trace_each, frontend_array_function=( - create_frontend_array if test_flags.test_trace else None + create_frontend_array + if test_flags.test_trace or test_flags.test_trace_each + else None ), precision_mode=test_flags.precision_mode, **kwargs_for_test, @@ -924,8 +1003,11 @@ def test_frontend_function( frontend_fn, *copy_args, test_trace=test_flags.test_trace, + test_trace_each=test_flags.test_trace_each, frontend_array_function=( - create_frontend_array if test_flags.test_trace else None + create_frontend_array + if test_flags.test_trace or test_flags.test_trace_each + else None ), precision_mode=test_flags.precision_mode, **copy_kwargs, @@ -941,7 +1023,12 @@ def test_frontend_function( first_array = first_array.data ret_ = ret_.data if hasattr(first_array, "requires_grad"): - first_array.requires_grad = False + first_array = first_array.detach() + if hasattr(ret_, "requires_grad"): + ret_ = ret_.detach() + if backend_to_test == "tensorflow": + first_array = first_array.numpy() + ret_ = ret_.numpy() assert not np.may_share_memory(first_array, ret_) elif test_flags.inplace: assert _is_frontend_array(ret) @@ -965,8 +1052,11 @@ def test_frontend_function( frontend_fn, *copy_args, test_trace=test_flags.test_trace, + test_trace_each=test_flags.test_trace_each, frontend_array_function=( - create_frontend_array if test_flags.test_trace else None + create_frontend_array + if test_flags.test_trace or test_flags.test_trace_each + else None ), precision_mode=test_flags.precision_mode, **copy_kwargs, @@ -1092,6 +1182,7 @@ def test_gradient_backend_computation( on_device, fn, test_trace, + test_trace_each, xs_grad_idxs, ret_grad_idxs, ): @@ -1117,6 +1208,7 @@ def _grad_fn(all_args): backend_to_test, call_fn, test_trace=test_trace, + test_trace_each=test_trace_each, args=args, kwargs=kwargs, )(*args, **kwargs) @@ -1147,6 +1239,7 @@ def test_gradient_ground_truth_computation( test_flags, kwargs_idxs, test_trace, + test_trace_each, xs_grad_idxs, ret_grad_idxs, ): @@ -1180,6 +1273,7 @@ def _gt_grad_fn(all_args): ground_truth_backend, call_fn, test_trace=test_trace, + test_trace_each=test_trace_each, args=args, kwargs=kwargs, )(*args, **kwargs) @@ -1208,7 +1302,8 @@ def gradient_test( input_dtypes, test_flags, test_trace: bool = False, - rtol_: float = None, + test_trace_each: bool = False, + rtol_: Optional[float] = None, atol_: float = 1e-06, tolerance_dict=None, xs_grad_idxs=None, @@ -1239,6 +1334,7 @@ def gradient_test( on_device, fn, test_trace, + test_trace_each, xs_grad_idxs, ret_grad_idxs, ) @@ -1259,6 +1355,7 @@ def gradient_test( on_device, fn, test_trace, + test_trace_each, xs_grad_idxs, ret_grad_idxs, ) @@ -1282,6 +1379,7 @@ def gradient_test( test_flags, kwargs_idxs, test_trace, + test_trace_each, xs_grad_idxs, ret_grad_idxs, ) @@ -1302,6 +1400,7 @@ def gradient_test( test_flags, kwargs_idxs, test_trace, + test_trace_each, xs_grad_idxs, ret_grad_idxs, ) @@ -1335,6 +1434,7 @@ def test_method_backend_computation( method_name, init_with_v, test_trace, + test_trace_each, method_with_v, ): init_input_dtypes = ivy.default(init_input_dtypes, []) @@ -1484,6 +1584,7 @@ def test_method_backend_computation( ins.__getattribute__(method_name), *args_method, test_trace=test_trace, + test_trace_each=test_trace_each, precision_mode=method_flags.precision_mode, **kwargs_method, ) @@ -1524,6 +1625,7 @@ def test_method_ground_truth_computation( class_name, method_name, test_trace, + test_trace_each, v_np, ): with BackendHandler.update_backend(ground_truth_backend) as gt_backend: @@ -1565,6 +1667,7 @@ def test_method_ground_truth_computation( ins_gt.__getattribute__(method_name), *args_gt_method, test_trace=test_trace, + test_trace_each=test_trace_each, precision_mode=method_flags.precision_mode, **kwargs_gt_method, ) @@ -1589,17 +1692,17 @@ def test_method_ground_truth_computation( def test_method( *, - init_input_dtypes: List[ivy.Dtype] = None, - method_input_dtypes: List[ivy.Dtype] = None, - init_all_as_kwargs_np: dict = None, - method_all_as_kwargs_np: dict = None, + init_input_dtypes: Optional[List[ivy.Dtype]] = None, + method_input_dtypes: Optional[List[ivy.Dtype]] = None, + init_all_as_kwargs_np: Optional[dict] = None, + method_all_as_kwargs_np: Optional[dict] = None, init_flags: pf.MethodTestFlags, method_flags: pf.MethodTestFlags, class_name: str, method_name: str = "__call__", init_with_v: bool = False, method_with_v: bool = False, - rtol_: float = None, + rtol_: Optional[float] = None, atol_: float = 1e-06, tolerance_dict=None, test_values: Union[bool, str] = True, @@ -1607,14 +1710,14 @@ def test_method( xs_grad_idxs=None, ret_grad_idxs=None, test_trace: bool = False, + test_trace_each: bool = False, backend_to_test: str, ground_truth_backend: str, on_device: str, return_flat_np_arrays: bool = False, ): - """ - Test a class-method that consumes (or returns) arrays for the current backend by - comparing the result with numpy. + """Test a class-method that consumes (or returns) arrays for the current + backend by comparing the result with numpy. Parameters ---------- @@ -1674,6 +1777,8 @@ def test_method( gradients are returned for all returned arrays. (Default value = None) test_trace If True, test for the correctness of tracing. + test_trace_each + If True, test for the correctness of tracing (tracing each example separately) ground_truth_backend Ground Truth Backend to compare the result-values. device_ @@ -1709,6 +1814,7 @@ def test_method( method_name, init_with_v, test_trace, + test_trace_each, method_with_v, ) ) @@ -1753,6 +1859,7 @@ def test_method( method_name, init_with_v, test_trace, + test_trace_each, method_with_v, ) @@ -1777,6 +1884,7 @@ def test_method( class_name, method_name, test_trace, + test_trace_each, v_np, ) ) @@ -1807,6 +1915,7 @@ def test_method( class_name, method_name, test_trace, + test_trace_each, v_np, ) @@ -1842,6 +1951,7 @@ def test_method( # input_dtypes=method_input_dtypes, # test_flags=method_flags, # test_trace=test_trace, + # test_trace_each=test_trace_each, # rtol_=rtol_, # atol_=atol_, # xs_grad_idxs=xs_grad_idxs, @@ -1862,6 +1972,7 @@ def test_method( # input_dtypes=method_input_dtypes, # test_flags=method_flags, # test_trace=test_trace, + # test_trace_each=test_trace_each, # rtol_=rtol_, # atol_=atol_, # xs_grad_idxs=xs_grad_idxs, @@ -1910,20 +2021,19 @@ def test_frontend_method( method_input_dtypes: Union[ivy.Dtype, List[ivy.Dtype]], init_flags, method_flags, - init_all_as_kwargs_np: dict = None, + init_all_as_kwargs_np: Optional[dict] = None, method_all_as_kwargs_np: dict, frontend: str, frontend_method_data: FrontendMethodData, backend_to_test: str, on_device, - rtol_: float = None, + rtol_: Optional[float] = None, atol_: float = 1e-06, - tolerance_dict: dict = None, + tolerance_dict: Optional[dict] = None, test_values: Union[bool, str] = True, ): - """ - Test a class-method that consumes (or returns) arrays for the current backend by - comparing the result with numpy. + """Test a class-method that consumes (or returns) arrays for the current + backend by comparing the result with numpy. Parameters ---------- @@ -1964,7 +2074,7 @@ def test_frontend_method( optional, return value from the Ground Truth function """ # ToDo add with_backend refactor in GC - _switch_backend_context(method_flags.test_trace) + _switch_backend_context(method_flags.test_trace or method_flags.test_trace_each) # Constructor arguments # args_np_constructor, kwargs_np_constructor = kwargs_to_args_n_kwargs( @@ -2139,9 +2249,12 @@ def test_frontend_method( ins.__getattribute__(frontend_method_data.method_name), *args_method_ivy, frontend_array_function=( - create_frontend_array if method_flags.test_trace else None + create_frontend_array + if method_flags.test_trace or method_flags.test_trace_each + else None ), test_trace=method_flags.test_trace, + test_trace_each=method_flags.test_trace_each, precision_mode=method_flags.precision_mode, **kwargs_method_ivy, ) @@ -2259,8 +2372,7 @@ def _get_framework_atol(atols: dict, current_fw: str): def _get_nested_np_arrays(nest): - """ - Search for a NumPy arrays in a nest. + """Search for a NumPy arrays in a nest. Parameters ---------- @@ -2290,8 +2402,7 @@ def create_args_kwargs( test_flags: Union[pf.FunctionTestFlags, pf.MethodTestFlags], on_device, ): - """ - Create arguments and keyword-arguments for the function to test. + """Create arguments and keyword-arguments for the function to test. Parameters ---------- @@ -2362,8 +2473,7 @@ def wrap_frontend_function_args(argument): def kwargs_to_args_n_kwargs(*, num_positional_args, kwargs): - """ - Split the kwargs into args and kwargs. + """Split the kwargs into args and kwargs. The first num_positional_args ported to args. """ @@ -2447,15 +2557,25 @@ def flatten_frontend_to_np(*, backend: str, ret): def get_ret_and_flattened_np_array( - backend_to_test: str, fn, *args, test_trace=False, precision_mode=False, **kwargs + backend_to_test: str, + fn, + *args, + test_trace=False, + test_trace_each=False, + precision_mode=False, + **kwargs, ): - """ - Run func with args and kwargs. + """Run func with args and kwargs. Return the result along with its flattened version. """ fn = traced_if_required( - backend_to_test, fn, test_trace=test_trace, args=args, kwargs=kwargs + backend_to_test, + fn, + test_trace=test_trace, + test_trace_each=test_trace_each, + args=args, + kwargs=kwargs, ) with BackendHandler.update_backend(backend_to_test) as ivy_backend: with ivy_backend.PreciseMode(precision_mode): @@ -2479,19 +2599,25 @@ def get_frontend_ret( frontend_array_function=None, precision_mode=False, test_trace: bool = False, + test_trace_each: bool = False, **kwargs, ): frontend_fn = traced_if_required( - backend, frontend_fn, test_trace=test_trace, args=args, kwargs=kwargs + backend, + frontend_fn, + test_trace=test_trace, + test_trace_each=test_trace_each, + args=args, + kwargs=kwargs, ) with BackendHandler.update_backend(backend) as ivy_backend: - if test_trace: + if test_trace or test_trace_each: args, kwargs = ivy_backend.nested_map( _frontend_array_to_ivy, (args, kwargs), include_derived={"tuple": True} ) with ivy_backend.PreciseMode(precision_mode): ret = frontend_fn(*args, **kwargs) - if test_trace: + if test_trace or test_trace_each: assert frontend_array_function is not None ret = ivy_backend.nested_map( arrays_to_frontend(backend, frontend_array_function), @@ -2529,7 +2655,7 @@ def _get_transpiled_data_if_required( traced_fn = traced_if_required( backend, frontend_fn, - test_trace=True, + test_trace_each=True, args=args_for_test, kwargs=kwargs_for_test, ) diff --git a/ivy_tests/test_ivy/helpers/globals.py b/ivy_tests/test_ivy/helpers/globals.py index 8d1d7f2f191d2..d1a4fb6e83791 100644 --- a/ivy_tests/test_ivy/helpers/globals.py +++ b/ivy_tests/test_ivy/helpers/globals.py @@ -1,6 +1,5 @@ -""" -A state holder for testing, this is only intended to hold and store testing data to be -used by the test helpers to prune unsupported data. +"""A state holder for testing, this is only intended to hold and store testing +data to be used by the test helpers to prune unsupported data. Should not be used inside any of the test functions. """ @@ -47,6 +46,7 @@ CURRENT_DEVICE = _Notsetval CURRENT_DEVICE_STRIPPED = _Notsetval CURRENT_FRONTEND_STR = None +CURRENT_TRACED_DATA = {} @dataclass(frozen=True) # ToDo use kw_only=True when version is updated @@ -59,10 +59,11 @@ class TestData: class InterruptedTest(BaseException): - """Indicate that a test tried to write global attributes while a test is running.""" + """Indicate that a test tried to write global attributes while a test is + running.""" def __init__(self, test_interrupted): - super.__init__(f"{test_interrupted} was interrupted during execution.") + super().__init__(f"{test_interrupted} was interrupted during execution.") # Setup diff --git a/ivy_tests/test_ivy/helpers/hypothesis_helpers/array_helpers.py b/ivy_tests/test_ivy/helpers/hypothesis_helpers/array_helpers.py index 0c639012590e8..28330daec930d 100644 --- a/ivy_tests/test_ivy/helpers/hypothesis_helpers/array_helpers.py +++ b/ivy_tests/test_ivy/helpers/hypothesis_helpers/array_helpers.py @@ -23,8 +23,7 @@ def array_bools( draw, *, size=st.shared(number_helpers.ints(min_value=1, max_value=4), key="size") ): - """ - Draws a list of booleans with a given size. + """Draws a list of booleans with a given size. Parameters ---------- @@ -74,8 +73,7 @@ def array_bools( def list_of_size(*, x, size): - """ - Return a list of the given length with elements drawn randomly from x. + """Return a list of the given length with elements drawn randomly from x. Parameters ---------- @@ -157,8 +155,7 @@ def lists( max_size=None, size_bounds=None, ): - """ - Draws a list with a random bounded size from the data-set x. + """Draws a list with a random bounded size from the data-set x. Parameters ---------- @@ -313,8 +310,8 @@ def dtype_and_values( array_api_dtypes=False, shape_key="shape", ): - """ - Draws a list of arrays with elements from the given corresponding data types. + """Draws a list of arrays with elements from the given corresponding data + types. Parameters ---------- @@ -577,9 +574,8 @@ def dtype_values_axis( force_tuple_axis=False, ret_shape=False, ): - """ - Draws a list of arrays with elements from the given data type, and a random axis of - the arrays. + """Draws a list of arrays with elements from the given data type, and a + random axis of the arrays. Parameters ---------- @@ -806,6 +802,12 @@ def array_indices_axis( *, array_dtypes, indices_dtypes=get_dtypes("valid"), + abs_smallest_val=None, + min_value=None, + max_value=None, + large_abs_safety_factor=1.1, + small_abs_safety_factor=1.1, + safety_factor_scale="linear", disable_random_axis=False, axis_zero=False, allow_inf=False, @@ -817,10 +819,9 @@ def array_indices_axis( indices_same_dims=False, valid_bounds=True, ): - """ - Generate two arrays x & indices, the values in the indices array are indices of the - array x. Draws an integers randomly from the minimum and maximum number of - positional arguments a given function can take. + """Generate two arrays x & indices, the values in the indices array are + indices of the array x. Draws an integers randomly from the minimum and + maximum number of positional arguments a given function can take. Parameters ---------- @@ -831,6 +832,37 @@ def array_indices_axis( list of data type to draw the array dtype from. indices_dtypes list of data type to draw the indices dtype from. + abs_smallest_val + sets the absolute smallest value to be generated for float data types, + this has no effect on integer data types. If none, the default data type + absolute smallest value is used. + min_value + minimum value of elements in the array. + max_value + maximum value of elements in the array. + large_abs_safety_factor + A safety factor of 1 means that all values are included without limitation, + + when a "linear" safety factor scaler is used, a safety factor of 2 means + that only 50% of the range is included, a safety factor of 3 means that + only 33% of the range is included etc. + + when a "log" safety factor scaler is used, a data type with maximum + value of 2^32 and a safety factor of 2 transforms the maximum to 2^16. + small_abs_safety_factor + A safety factor of 1 means that all values are included without limitation, + this has no effect on integer data types. + + when a "linear" safety factor scaler is used, a data type with minimum + representable number of 0.0001 and a safety factor of 2 transforms the + minimum to 0.0002, a safety factor of 3 transforms the minimum to 0.0003 etc. + + when a "log" safety factor scaler is used, a data type with minimum + representable number of 0.5 * 2^-16 and a safety factor of 2 transforms the + minimum to 0.5 * 2^-8, a safety factor of 3 transforms the minimum to 0.5 * 2^-4 + safety_factor_scale + The operation to use for the safety factor scaling. Can be "linear" or "log". + Default value = "linear". disable_random_axis axis is randomly generated with hypothesis if False. If True, axis is set to 0 if axis_zero is True, -1 otherwise. @@ -966,6 +998,12 @@ def array_indices_axis( max_num_dims=max_num_dims, min_dim_size=min_dim_size, max_dim_size=max_dim_size, + abs_smallest_val=abs_smallest_val, + min_value=min_value, + max_value=max_value, + large_abs_safety_factor=large_abs_safety_factor, + small_abs_safety_factor=small_abs_safety_factor, + safety_factor_scale=safety_factor_scale, ) ) x_dtype = x_dtype[0] @@ -1046,10 +1084,9 @@ def array_indices_put_along_axis( values=None, values_dtypes=get_dtypes("valid"), ): - """ - Generate two arrays x & indices, the values in the indices array are indices of the - array x. Draws an integers randomly from the minimum and maximum number of - positional arguments a given function can take. + """Generate two arrays x & indices, the values in the indices array are + indices of the array x. Draws an integers randomly from the minimum and + maximum number of positional arguments a given function can take. Parameters ---------- @@ -1238,8 +1275,7 @@ def arrays_and_axes( return_dtype=False, force_int_axis=False, ): - """ - Generate a list of arrays and axes. + """Generate a list of arrays and axes. Parameters ---------- @@ -1408,8 +1444,8 @@ def array_values( small_abs_safety_factor=1.1, safety_factor_scale="linear", ): - """ - Draws a list (of lists) of a given shape containing values of a given data type. + """Draws a list (of lists) of a given shape containing values of a given + data type. Parameters ---------- @@ -1790,30 +1826,30 @@ def arrays_for_pooling( ) if array_dim == 3: kernel = draw(st.tuples(st.integers(1, in_shape[1]))) - new_kernel = kernel if return_dilation: - new_kernel = [] dilations = [] for i in range(len(kernel)): if kernel[i] > 1: max_dilation = (in_shape[i + 1] - kernel[i]) // (kernel[i] - 1) + 1 dilations.append(draw(st.integers(1, max_dilation))) - new_kernel.append(kernel[i] + (kernel[i] - 1) * (dilations[i] - 1)) else: dilations.append(1) - new_kernel.append(kernel[i]) if explicit_or_str_padding or only_explicit_padding: - padding = [] - for i in range(array_dim - 2): - max_pad = new_kernel[i] // 2 - padding.append( - draw( - st.tuples( - st.integers(0, max_pad), - st.integers(0, max_pad), + if draw(st.booleans()): + max_pad = min(kernel[i] // 2 for i in range(array_dim - 2)) + padding = draw(st.integers(0, max_pad)) + else: + padding = [] + for i in range(array_dim - 2): + max_pad = kernel[i] // 2 + padding.append( + draw( + st.tuples( + st.integers(0, max_pad), + st.integers(0, max_pad), + ) ) ) - ) if explicit_or_str_padding: padding = draw( st.one_of(st.just(padding), st.sampled_from(["VALID", "SAME"])) @@ -1878,6 +1914,7 @@ def dtype_array_query( shape=shape, large_abs_safety_factor=2, small_abs_safety_factor=2, + safety_factor_scale="log", ) ) if allow_mask and draw(st.booleans()): @@ -1899,6 +1936,7 @@ def dtype_array_query( ) index_types = [v if shape[i] > 0 else "slice" for i, v in enumerate(index_types)] index = [] + empty_array = prod(shape) == 0 for s, index_type in zip(shape, index_types): if index_type == "int": new_index = draw(st.integers(min_value=-s + 1, max_value=s - 1)) @@ -1906,8 +1944,8 @@ def dtype_array_query( new_index = draw( st.lists( st.integers(min_value=-s + 1, max_value=s - 1), - min_size=1, - max_size=20, + min_size=1 if not empty_array else 0, + max_size=20 if not empty_array else 0, ) ) elif index_type == "array": @@ -1917,6 +1955,8 @@ def dtype_array_query( max_value=s - 1, dtype=["int64"], max_num_dims=4, + min_dim_size=1 if not empty_array else 0, + max_dim_size=10 if not empty_array else 0, ) ) new_index = new_index[0] @@ -1996,6 +2036,7 @@ def dtype_array_query_val( shape=val_shape, large_abs_safety_factor=2, small_abs_safety_factor=2, + safety_factor_scale="log", ) ) val_dtype = draw( @@ -2022,7 +2063,7 @@ def create_nested_input(draw, dimensions, leaf_values): def cond_data_gen_helper(draw): dtype_x = helpers.dtype_and_values( available_dtypes=["float32", "float64"], - shape=helpers.ints(min_value=2, max_value=5).map(lambda x: tuple([x, x])), + shape=helpers.ints(min_value=2, max_value=5).map(lambda x: (x, x)), max_value=10, min_value=-10, allow_nan=False, @@ -2056,7 +2097,7 @@ def get_first_solve_matrix(draw, adjoint=True): matrix = draw( helpers.array_values( dtype=input_dtype, - shape=tuple([shared_size, shared_size]), + shape=(shared_size, shared_size), min_value=2, max_value=5, ).filter(lambda x: np.linalg.cond(x) < 1 / sys.float_info.epsilon) @@ -2086,7 +2127,7 @@ def get_second_solve_matrix(draw): ) return input_dtype, draw( helpers.array_values( - dtype=input_dtype, shape=tuple([shared_size, 1]), min_value=2, max_value=5 + dtype=input_dtype, shape=(shared_size, 1), min_value=2, max_value=5 ) ) @@ -2175,11 +2216,10 @@ def create_concatenable_arrays_dtypes( dtypes, common_shape=None, ): - """ - Draws a random number of arrays with concatenable or stackable dimensions. Arrays - have same number of dimensions, but their shape can differ along a specified - dimension (concat_dim). If concat_dim is None, arrays have the same shape. Dtypes of - arrays can differ. + """Draws a random number of arrays with concatenable or stackable + dimensions. Arrays have same number of dimensions, but their shape can + differ along a specified dimension (concat_dim). If concat_dim is None, + arrays have the same shape. Dtypes of arrays can differ. Parameters ---------- @@ -2242,10 +2282,9 @@ def create_concatenable_arrays_dtypes( # helpers for tests (core and frontend) related to solve function @st.composite def get_first_solve_batch_matrix(draw, choose_adjoint=False): - """ - Generate non-singular left hand side of equation system possibly with a single batch - dimension at the beginning. Use get_second_solve_batch_matrix to get the right hand - side. + """Generate non-singular left hand side of equation system possibly with a + single batch dimension at the beginning. Use get_second_solve_batch_matrix + to get the right hand side. Parameters ---------- @@ -2302,10 +2341,9 @@ def get_first_solve_batch_matrix(draw, choose_adjoint=False): @st.composite def get_second_solve_batch_matrix(draw, allow_simplified=True, choose_side=False): - """ - Generate right hand side of equation system. Possible with a batch dimension and - possibly with several columns of values. Use get_first_solve_batch_matrix to - generate the left hand side. + """Generate right hand side of equation system. Possible with a batch + dimension and possibly with several columns of values. Use + get_first_solve_batch_matrix to generate the left hand side. Parameters ---------- diff --git a/ivy_tests/test_ivy/helpers/hypothesis_helpers/dtype_helpers.py b/ivy_tests/test_ivy/helpers/hypothesis_helpers/dtype_helpers.py index 9502ce60aaf0a..08838b35ae4e7 100644 --- a/ivy_tests/test_ivy/helpers/hypothesis_helpers/dtype_helpers.py +++ b/ivy_tests/test_ivy/helpers/hypothesis_helpers/dtype_helpers.py @@ -113,10 +113,10 @@ def get_dtypes( key=None, prune_function=True, ): - """ - Draws a valid dtypes for the test function. For frontend tests, it draws the data - types from the intersection between backend framework data types and frontend - framework dtypes, otherwise, draws it from backend framework data types. + """Draws a valid dtypes for the test function. For frontend tests, it draws + the data types from the intersection between backend framework data types + and frontend framework dtypes, otherwise, draws it from backend framework + data types. Parameters ---------- @@ -262,8 +262,7 @@ def array_dtypes( shared_dtype=False, array_api_dtypes=False, ): - """ - Draws a list of data types. + """Draws a list of data types. Parameters ---------- @@ -351,9 +350,9 @@ def array_dtypes( else: pairs = ivy.promotion_table.keys() # added to avoid complex dtypes from being sampled if they are not available. - pairs = [pair for pair in pairs if all([d in available_dtypes for d in pair])] + [pair for pair in pairs if all(d in available_dtypes for d in pair)] available_dtypes = [ - pair for pair in pairs if not any([d in pair for d in unwanted_types]) + pair for pair in pairs if not any(d in pair for d in unwanted_types) ] dtypes = list(draw(st.sampled_from(available_dtypes))) if num_arrays > 2: @@ -363,8 +362,7 @@ def array_dtypes( @st.composite def get_castable_dtype(draw, available_dtypes, dtype: str, x: Optional[list] = None): - """ - Draws castable dtypes for the given dtype based on the current backend. + """Draws castable dtypes for the given dtype based on the current backend. Parameters ---------- diff --git a/ivy_tests/test_ivy/helpers/hypothesis_helpers/general_helpers.py b/ivy_tests/test_ivy/helpers/hypothesis_helpers/general_helpers.py index 9bfc7505092b8..a6f86024384b2 100644 --- a/ivy_tests/test_ivy/helpers/hypothesis_helpers/general_helpers.py +++ b/ivy_tests/test_ivy/helpers/hypothesis_helpers/general_helpers.py @@ -1,5 +1,6 @@ # global -from hypothesis import strategies as st +from hypothesis import assume, strategies as st +from typing import Tuple from functools import lru_cache import math import numpy as np @@ -13,8 +14,7 @@ def matrix_is_stable(x, cond_limit=30): - """ - Check if a matrix is numerically stable or not. + """Check if a matrix is numerically stable or not. Used to avoid numerical instabilities in further computationally heavy calculations. @@ -61,8 +61,7 @@ def apply_safety_factor( large_abs_safety_factor=1.1, safety_factor_scale="linear", ): - """ - Apply safety factor scaling to numeric data type. + """Apply safety factor scaling to numeric data type. Parameters ---------- @@ -162,12 +161,70 @@ def general_helpers_dtype_info_helper(backend, kind_dtype, dtype): # -----------# +# from array-api repo +class BroadcastError(ValueError): + """Shapes do not broadcast with each other.""" + + +# from array-api repo +def _broadcast_shapes( + shape1: Tuple[int, ...], shape2: Tuple[int, ...] +) -> Tuple[int, ...]: + N1 = len(shape1) + N2 = len(shape2) + N = max(N1, N2) + shape = [None for _ in range(N)] + i = N - 1 + while i >= 0: + n1 = N1 - N + i + if N1 - N + i >= 0: + d1 = shape1[n1] + else: + d1 = 1 + n2 = N2 - N + i + if N2 - N + i >= 0: + d2 = shape2[n2] + else: + d2 = 1 + + if d1 == 1: + shape[i] = d2 + elif d2 == 1: + shape[i] = d1 + elif d1 == d2: + shape[i] = d1 + else: + raise BroadcastError() + i = i - 1 + return tuple(shape) + + +# from array-api repo +def broadcast_shapes(*shapes: Tuple[int, ...]): + if len(shapes) == 0: + raise ValueError("shapes=[] must be non-empty") + elif len(shapes) == 1: + return shapes[0] + result = _broadcast_shapes(shapes[0], shapes[1]) + for i in range(2, len(shapes)): + result = _broadcast_shapes(result, shapes[i]) + return result + + +# from array-api repo +@st.composite +def two_broadcastable_shapes(draw): + shape1, shape2 = draw(array_helpers.mutually_broadcastable_shapes(2)) + assume(broadcast_shapes(shape1, shape2) == shape1) + return (shape1, shape2) + + # taken from # https://github.com/data-apis/array-api-tests/array_api_tests/test_manipulation_functions.py @st.composite def reshape_shapes(draw, *, shape): - """ - Draws a random shape with the same number of elements as the given shape. + """Draws a random shape with the same number of elements as the given + shape. Parameters ---------- @@ -195,8 +252,7 @@ def reshape_shapes(draw, *, shape): # taken from https://github.com/HypothesisWorks/hypothesis/issues/1115 @st.composite def subsets(draw, *, elements): - """ - Draws a subset of elements from the given elements. + """Draws a subset of elements from the given elements. Parameters ---------- @@ -223,10 +279,9 @@ def get_shape( min_dim_size=1, max_dim_size=10, ): - """ - Draws a tuple of integers drawn randomly from [min_dim_size, max_dim_size] of size - drawn from min_num_dims to max_num_dims. Useful for randomly drawing the shape of an - array. + """Draws a tuple of integers drawn randomly from [min_dim_size, + max_dim_size] of size drawn from min_num_dims to max_num_dims. Useful for + randomly drawing the shape of an array. Parameters ---------- @@ -272,9 +327,8 @@ def get_shape( @st.composite def get_mean_std(draw, *, dtype): - """ - Draws two integers representing the mean and standard deviation for a given data - type. + """Draws two integers representing the mean and standard deviation for a + given data type. Parameters ---------- @@ -296,8 +350,8 @@ def get_mean_std(draw, *, dtype): @st.composite def get_bounds(draw, *, dtype): - """ - Draws two numbers; low and high, for a given data type such that low < high. + """Draws two numbers; low and high, for a given data type such that low < + high. Parameters ---------- @@ -343,8 +397,7 @@ def get_axis( force_tuple=False, force_int=False, ): - """ - Draws one or more axis for the given shape. + """Draws one or more axis for the given shape. Parameters ---------- @@ -430,7 +483,7 @@ def get_axis( axis = draw( st.one_of(*valid_strategies).filter( lambda x: ( - all([i != axes + j for i in x for j in x]) + all(i != axes + j for i in x for j in x) if (isinstance(x, list) and unique and allow_neg) else True ) @@ -458,8 +511,7 @@ def x_and_filters( depthwise=False, mixed_fn_compos=True, ): - """ - Draws a random x and filters for a convolution. + """Draws a random x and filters for a convolution. Parameters ---------- @@ -555,8 +607,8 @@ def x_and_filters( @st.composite def embedding_helper(draw, mixed_fn_compos=True): - """ - Obtain weights for embeddings, the corresponding indices, the padding indices. + """Obtain weights for embeddings, the corresponding indices, the padding + indices. Parameters ---------- @@ -596,3 +648,54 @@ def embedding_helper(draw, mixed_fn_compos=True): ) padding_idx = draw(st.integers(min_value=0, max_value=num_embeddings - 1)) return dtype_indices + dtype_weight, indices[0], weight[0], padding_idx + + +def sizes_(shape, axis): + def factorization(n): + factors = [1] + + def get_factor(n): + x_fixed = 2 + cycle_size = 2 + x = 2 + factor = 1 if n % 2 else 2 + while factor == 1: + for count in range(cycle_size): + if factor > 1: + break + x = (x * x + 1) % n + factor = math.gcd(x - x_fixed, n) + + cycle_size *= 2 + x_fixed = x + + return factor + + while n > 1: + next = get_factor(n) + factors.append(next) + n //= next + if len(factors) > 1: + factors.remove(1) + return factors + + shape_ = ( + tuple(factorization(shape[axis])) + if tuple(factorization(shape[axis])) + else shape + ) + return shape_ + + +@st.composite +def dims_and_offset(draw, shape, ensure_dim_unique=False): + shape_actual = draw(shape) + dim1 = draw(get_axis(shape=shape, force_int=True)) + dim2 = draw(get_axis(shape=shape, force_int=True)) + if ensure_dim_unique: + while dim1 == dim2: + dim2 = draw(get_axis(shape=shape, force_int=True)) + offset = draw( + st.integers(min_value=-shape_actual[dim1], max_value=shape_actual[dim1]) + ) + return dim1, dim2, offset diff --git a/ivy_tests/test_ivy/helpers/hypothesis_helpers/number_helpers.py b/ivy_tests/test_ivy/helpers/hypothesis_helpers/number_helpers.py index 55e07e3dd7442..71832e0cc3ff9 100644 --- a/ivy_tests/test_ivy/helpers/hypothesis_helpers/number_helpers.py +++ b/ivy_tests/test_ivy/helpers/hypothesis_helpers/number_helpers.py @@ -31,9 +31,8 @@ def floats( safety_factor_scale="linear", mixed_fn_compos=True, ): - """ - Draws an arbitrarily sized list of floats with a safety factor applied to avoid - values being generated at the edge of a dtype limit. + """Draws an arbitrarily sized list of floats with a safety factor applied + to avoid values being generated at the edge of a dtype limit. Parameters ---------- @@ -156,8 +155,7 @@ def ints( safety_factor_scale=None, mixed_fn_compos=True, ): - """ - Draws an integer with a safety factor if specified. + """Draws an integer with a safety factor if specified. Parameters ---------- @@ -221,8 +219,7 @@ def number( safety_factor_scale="linear", mixed_fn_compos=True, ): - """ - Draws integers or floats with a safety factor applied to values. + """Draws integers or floats with a safety factor applied to values. Parameters ---------- diff --git a/ivy_tests/test_ivy/helpers/multiprocessing.py b/ivy_tests/test_ivy/helpers/multiprocessing.py index 4b832bf2c7b19..47ee2c1dcaccf 100644 --- a/ivy_tests/test_ivy/helpers/multiprocessing.py +++ b/ivy_tests/test_ivy/helpers/multiprocessing.py @@ -49,7 +49,7 @@ def backend_proc(input_queue, output_queue): _, fn_module, fn_name, b = data output_queue.put( - (_get_supported_devices_dtypes_helper(b, fn_module, fn_name)) + _get_supported_devices_dtypes_helper(b, fn_module, fn_name) ) elif data[0] == "method supported dtypes": # again stage 1, calculating and returning supported dtypes @@ -69,17 +69,17 @@ def backend_proc(input_queue, output_queue): elif data[0] == "_get_type_dict_helper": _, framework, kind, is_frontend_test = data dtype_ret = _get_type_dict_helper(framework, kind, is_frontend_test) - output_queue.put((dtype_ret)) + output_queue.put(dtype_ret) elif data[0] == "num_positional_args_helper": _, fn_name, framework = data dtype_ret = num_positional_args_helper(fn_name, framework) - output_queue.put((dtype_ret)) + output_queue.put(dtype_ret) elif data[0] == "cast_filter_helper": _, d, dtype, x, current_backend = data dtype_ret = cast_filter_helper(d, dtype, x, current_backend) - output_queue.put((dtype_ret)) + output_queue.put(dtype_ret) elif data[0] == "function_backend_computation": # it's the backend return computation @@ -177,6 +177,7 @@ def backend_proc(input_queue, output_queue): on_device, fn, test_trace, + test_trace_each, xs_grad_idxs, ret_grad_idxs, ) = data @@ -193,10 +194,11 @@ def backend_proc(input_queue, output_queue): on_device, fn, test_trace, + test_trace_each, xs_grad_idxs, ret_grad_idxs, ) - output_queue.put((grads_np_flat)) + output_queue.put(grads_np_flat) elif data[0] == "gradient_ground_truth_computation": # gradient testing, part where it uses ground truth @@ -215,6 +217,7 @@ def backend_proc(input_queue, output_queue): test_flags, kwargs_idxs, test_trace, + test_trace_each, xs_grad_idxs, ret_grad_idxs, ) = data @@ -232,6 +235,7 @@ def backend_proc(input_queue, output_queue): test_flags, kwargs_idxs, test_trace, + test_trace_each, xs_grad_idxs, ret_grad_idxs, ) @@ -252,6 +256,7 @@ def backend_proc(input_queue, output_queue): method_name, init_with_v, test_trace, + test_trace_each, method_with_v, ) = data ( @@ -280,6 +285,7 @@ def backend_proc(input_queue, output_queue): method_name, init_with_v, test_trace, + test_trace_each, method_with_v, ) # ret is none here, because main process doesn't import framework @@ -317,6 +323,7 @@ def backend_proc(input_queue, output_queue): class_name, method_name, test_trace, + test_trace_each, v_np, ) = data ( @@ -339,6 +346,7 @@ def backend_proc(input_queue, output_queue): class_name, method_name, test_trace, + test_trace_each, v_np, ) # ret from gt None here, because main process doesn't import framework diff --git a/ivy_tests/test_ivy/helpers/pipeline_helper.py b/ivy_tests/test_ivy/helpers/pipeline_helper.py index f704ab4cd171d..361177808f3b9 100644 --- a/ivy_tests/test_ivy/helpers/pipeline_helper.py +++ b/ivy_tests/test_ivy/helpers/pipeline_helper.py @@ -11,11 +11,12 @@ class BackendHandlerMode(Enum): class WithBackendContext: - def __init__(self, backend) -> None: + def __init__(self, backend, cached=True) -> None: self.backend = backend + self.cached = cached def __enter__(self): - return ivy.with_backend(self.backend) + return ivy.with_backend(self.backend, cached=self.cached) def __exit__(self, exc_type, exc_val, exc_tb): return diff --git a/ivy_tests/test_ivy/helpers/test_parameter_flags.py b/ivy_tests/test_ivy/helpers/test_parameter_flags.py index e123f1764db31..cc6cb961ff9db 100644 --- a/ivy_tests/test_ivy/helpers/test_parameter_flags.py +++ b/ivy_tests/test_ivy/helpers/test_parameter_flags.py @@ -45,9 +45,11 @@ def _as_varaible_strategy(draw): BuiltWithCopyStrategy = DynamicFlag(st.just(False)) BuiltCompileStrategy = DynamicFlag(st.just(False)) BuiltTraceStrategy = DynamicFlag(st.just(False)) +BuiltTraceEachStrategy = DynamicFlag(st.just(False)) BuiltFrontendArrayStrategy = DynamicFlag(st.booleans()) BuiltTranspileStrategy = DynamicFlag(st.just(False)) BuiltPrecisionModeStrategy = DynamicFlag(st.booleans()) +BuiltCythonWrapperStrategy = DynamicFlag(st.just(False)) flags_mapping = { @@ -60,8 +62,10 @@ def _as_varaible_strategy(draw): "with_copy": "BuiltWithCopyStrategy", "inplace": "BuiltInplace", "test_trace": "BuiltTraceStrategy", + "test_trace_each": "BuiltTraceEachStrategy", "transpile": "BuiltTranspileStrategy", "precision_mode": "BuiltPrecisionModeStrategy", + "test_cython_wrapper": "BuiltCythonWrapperStrategy", } @@ -96,8 +100,10 @@ def __init__( container, test_gradients, test_trace, + test_trace_each, transpile, precision_mode, + test_cython_wrapper, ): self.ground_truth_backend = ground_truth_backend self.num_positional_args = num_positional_args @@ -109,8 +115,10 @@ def __init__( self.as_variable = as_variable self.test_gradients = test_gradients self.test_trace = test_trace + self.test_trace_each = test_trace_each self.transpile = transpile self.precision_mode = precision_mode + self.test_cython_wrapper = test_cython_wrapper def apply_flags(self, args_to_iterate, input_dtypes, offset, *, backend, on_device): ret = [] @@ -138,6 +146,7 @@ def __str__(self): f"as_variable={self.as_variable}. " f"test_gradients={self.test_gradients}. " f"test_trace={self.test_trace}. " + f"test_trace_each={self.test_trace_each}. " f"transpile={self.transpile}. " f"precision_mode={self.precision_mode}. " ) @@ -157,11 +166,13 @@ def function_flags( with_copy, test_gradients, test_trace, + test_trace_each, transpile, as_variable, native_arrays, container_flags, precision_mode, + test_cython_wrapper, ): return draw( st.builds( @@ -173,11 +184,13 @@ def function_flags( instance_method=instance_method, test_gradients=test_gradients, test_trace=test_trace, + test_trace_each=test_trace_each, transpile=transpile, as_variable=as_variable, native_arrays=native_arrays, container=container_flags, precision_mode=precision_mode, + test_cython_wrapper=test_cython_wrapper, ) ) @@ -192,6 +205,7 @@ def __init__( as_variable, native_arrays, test_trace, + test_trace_each, generate_frontend_arrays, transpile, precision_mode, @@ -203,6 +217,7 @@ def __init__( self.native_arrays = native_arrays self.as_variable = as_variable self.test_trace = test_trace + self.test_trace_each = test_trace_each self.generate_frontend_arrays = generate_frontend_arrays self.transpile = transpile self.precision_mode = precision_mode @@ -228,6 +243,7 @@ def __str__(self): f"native_arrays={self.native_arrays}. " f"as_variable={self.as_variable}. " f"test_trace={self.test_trace}. " + f"test_trace_each={self.test_trace_each}" f"generate_frontend_arrays={self.generate_frontend_arrays}. " f"transpile={self.transpile}." f"precision_mode={self.precision_mode}. " @@ -248,6 +264,7 @@ def frontend_function_flags( as_variable, native_arrays, test_trace, + test_trace_each, generate_frontend_arrays, transpile, precision_mode, @@ -262,6 +279,7 @@ def frontend_function_flags( as_variable=as_variable, native_arrays=native_arrays, test_trace=test_trace, + test_trace_each=test_trace_each, generate_frontend_arrays=generate_frontend_arrays, transpile=transpile, precision_mode=precision_mode, @@ -451,6 +469,7 @@ def __init__( precision_mode, inplace, test_trace, + test_trace_each, generate_frontend_arrays, ): self.num_positional_args = num_positional_args @@ -459,6 +478,7 @@ def __init__( self.precision_mode = precision_mode self.inplace = inplace self.test_trace = test_trace + self.test_trace_each = test_trace_each self.generate_frontend_arrays = generate_frontend_arrays def apply_flags(self, args_to_iterate, input_dtypes, offset, *, backend, on_device): @@ -481,6 +501,7 @@ def __str__(self): f"precision_mode={self.precision_mode}. " f"inplace={self.inplace}. " f"test_trace={self.test_trace}." + f"test_trace_each={self.test_trace_each}" f"generate_frontend_arrays={self.generate_frontend_arrays}." ) @@ -498,6 +519,7 @@ def frontend_method_flags( precision_mode, inplace, test_trace, + test_trace_each, generate_frontend_arrays, ): return draw( @@ -509,6 +531,7 @@ def frontend_method_flags( precision_mode=precision_mode, inplace=inplace, test_trace=test_trace, + test_trace_each=test_trace_each, generate_frontend_arrays=generate_frontend_arrays, ) ) diff --git a/ivy_tests/test_ivy/helpers/testing_helpers.py b/ivy_tests/test_ivy/helpers/testing_helpers.py index d14b66c59b421..36d01f0d5892e 100644 --- a/ivy_tests/test_ivy/helpers/testing_helpers.py +++ b/ivy_tests/test_ivy/helpers/testing_helpers.py @@ -5,9 +5,9 @@ import importlib import inspect import functools -from typing import List +from typing import List, Optional -from hypothesis import given, strategies as st +from hypothesis import given, strategies as st, example # local import ivy.functional.frontends.numpy as np_frontend @@ -27,9 +27,11 @@ BuiltWithCopyStrategy, BuiltInplaceStrategy, BuiltTraceStrategy, + BuiltTraceEachStrategy, BuiltFrontendArrayStrategy, BuiltTranspileStrategy, BuiltPrecisionModeStrategy, + BuiltCythonWrapperStrategy, ) from ivy_tests.test_ivy.helpers.structs import FrontendMethodData from ivy_tests.test_ivy.helpers.available_frameworks import available_frameworks @@ -44,6 +46,7 @@ "instance_method", "test_gradients", "test_trace", + "test_trace_each", "precision_mode", ) cmd_line_args_lists = ( @@ -59,9 +62,8 @@ def _get_runtime_flag_value(flag): @st.composite def num_positional_args_method(draw, *, method): - """ - Draws an integers randomly from the minimum and maximum number of positional - arguments a given method can take. + """Draws an integers randomly from the minimum and maximum number of + positional arguments a given method can take. Parameters ---------- @@ -90,10 +92,9 @@ def num_positional_args_method(draw, *, method): @st.composite -def num_positional_args(draw, *, fn_name: str = None): - """ - Draws an integers randomly from the minimum and maximum number of positional - arguments a given function can take. +def num_positional_args(draw, *, fn_name: Optional[str] = None): + """Draws an integers randomly from the minimum and maximum number of + positional arguments a given function can take. Parameters ---------- @@ -158,8 +159,7 @@ def num_positional_args_helper(fn_name, backend): def _import_fn(fn_tree: str): - """ - Import a function from function tree string. + """Import a function from function tree string. Parameters ---------- @@ -209,8 +209,7 @@ def _get_method_supported_devices_dtypes_helper( def _get_method_supported_devices_dtypes( method_name: str, class_module: str, class_name: str ): - """ - Get supported devices and data types for a method in Ivy API. + """Get supported devices and data types for a method in Ivy API. Parameters ---------- @@ -278,8 +277,7 @@ def _get_supported_devices_dtypes_helper( def _get_supported_devices_dtypes(fn_name: str, fn_module: str): - """ - Get supported devices and data types for a function in Ivy API. + """Get supported devices and data types for a function in Ivy API. Parameters ---------- @@ -331,7 +329,7 @@ def _partition_dtypes_into_kinds(framework: str, dtypes): def handle_test( *, - fn_tree: str = None, + fn_tree: Optional[str] = None, ground_truth_backend: str = "tensorflow", number_positional_args=None, test_instance_method=BuiltInstanceStrategy, @@ -339,15 +337,16 @@ def handle_test( test_with_copy=BuiltWithCopyStrategy, test_gradients=BuiltGradientStrategy, test_trace=BuiltTraceStrategy, + test_trace_each=BuiltTraceEachStrategy, transpile=BuiltTranspileStrategy, precision_mode=BuiltPrecisionModeStrategy, as_variable_flags=BuiltAsVariableStrategy, native_array_flags=BuiltNativeArrayStrategy, container_flags=BuiltContainerStrategy, + test_cython_wrapper=BuiltCythonWrapperStrategy, **_given_kwargs, ): - """ - Test wrapper for Ivy functions. + """Test wrapper for Ivy functions. The wrapper sets the required test globals and creates test flags strategies. @@ -382,6 +381,10 @@ def handle_test( A search strategy that generates a boolean to trace and test the function + test_trace_each + A search strategy that generates a boolean to trace and test the + function (trace each example separately) + precision_mode A search strategy that generates a boolean to switch between two different precision modes supported by numpy and (torch, jax) and test the function @@ -417,11 +420,13 @@ def handle_test( with_copy=_get_runtime_flag_value(test_with_copy), test_gradients=_get_runtime_flag_value(test_gradients), test_trace=_get_runtime_flag_value(test_trace), + test_trace_each=_get_runtime_flag_value(test_trace_each), transpile=_get_runtime_flag_value(transpile), as_variable=_get_runtime_flag_value(as_variable_flags), native_arrays=_get_runtime_flag_value(native_array_flags), container_flags=_get_runtime_flag_value(container_flags), precision_mode=_get_runtime_flag_value(precision_mode), + test_cython_wrapper=_get_runtime_flag_value(test_cython_wrapper), ) def test_wrapper(test_fn): @@ -475,8 +480,8 @@ def wrapped_test(*args, **kwargs): def handle_frontend_test( *, fn_tree: str, - gt_fn_tree: str = None, - aliases: List[str] = None, + gt_fn_tree: Optional[str] = None, + aliases: Optional[List[str]] = None, number_positional_args=None, test_with_out=BuiltWithOutStrategy, test_with_copy=BuiltWithCopyStrategy, @@ -484,13 +489,13 @@ def handle_frontend_test( as_variable_flags=BuiltAsVariableStrategy, native_array_flags=BuiltNativeArrayStrategy, test_trace=BuiltTraceStrategy, + test_trace_each=BuiltTraceEachStrategy, generate_frontend_arrays=BuiltFrontendArrayStrategy, transpile=BuiltTranspileStrategy, precision_mode=BuiltPrecisionModeStrategy, **_given_kwargs, ): - """ - Test wrapper for Ivy frontend functions. + """Test wrapper for Ivy frontend functions. The wrapper sets the required test globals and creates test flags strategies. @@ -533,6 +538,10 @@ def handle_frontend_test( A search strategy that generates a boolean to trace and test the function + test_trace_each + A search strategy that generates a boolean to trace and test the + function (trace each example separately) + generate_frontend_arrays A search strategy that generates a list of boolean flags for array inputs to be frontend array @@ -556,6 +565,7 @@ def handle_frontend_test( as_variable=_get_runtime_flag_value(as_variable_flags), native_arrays=_get_runtime_flag_value(native_array_flags), test_trace=_get_runtime_flag_value(test_trace), + test_trace_each=_get_runtime_flag_value(test_trace_each), generate_frontend_arrays=_get_runtime_flag_value(generate_frontend_arrays), transpile=_get_runtime_flag_value(transpile), precision_mode=_get_runtime_flag_value(precision_mode), @@ -626,10 +636,11 @@ def _import_method(method_tree: str): def handle_method( *, init_tree: str = "", - method_tree: str = None, + method_tree: Optional[str] = None, ground_truth_backend: str = "tensorflow", test_gradients=BuiltGradientStrategy, test_trace=BuiltTraceStrategy, + test_trace_each=BuiltTraceEachStrategy, precision_mode=BuiltPrecisionModeStrategy, init_num_positional_args=None, init_native_arrays=BuiltNativeArrayStrategy, @@ -640,8 +651,7 @@ def handle_method( method_container_flags=BuiltContainerStrategy, **_given_kwargs, ): - """ - Test wrapper for Ivy methods. + """Test wrapper for Ivy methods. The wrapper sets the required test globals and creates test flags strategies. @@ -662,6 +672,7 @@ def handle_method( "ground_truth_backend": st.just(ground_truth_backend), "test_gradients": _get_runtime_flag_value(test_gradients), "test_trace": _get_runtime_flag_value(test_trace), + "test_trace_each": _get_runtime_flag_value(test_trace_each), "precision_mode": _get_runtime_flag_value(precision_mode), } @@ -751,6 +762,7 @@ def handle_frontend_method( init_native_arrays=BuiltNativeArrayStrategy, init_as_variable_flags=BuiltAsVariableStrategy, test_trace=BuiltTraceStrategy, + test_trace_each=BuiltTraceEachStrategy, precision_mode=BuiltPrecisionModeStrategy, method_num_positional_args=None, method_native_arrays=BuiltNativeArrayStrategy, @@ -759,8 +771,7 @@ def handle_frontend_method( generate_frontend_arrays=BuiltFrontendArrayStrategy, **_given_kwargs, ): - """ - Test wrapper for Ivy frontends methods. + """Test wrapper for Ivy frontends methods. The wrapper sets the required test globals and creates test flags strategies. @@ -856,6 +867,7 @@ def test_wrapper(test_fn): as_variable=_get_runtime_flag_value(method_as_variable_flags), native_arrays=_get_runtime_flag_value(method_native_arrays), test_trace=_get_runtime_flag_value(test_trace), + test_trace_each=_get_runtime_flag_value(test_trace_each), precision_mode=_get_runtime_flag_value(precision_mode), generate_frontend_arrays=_get_runtime_flag_value( generate_frontend_arrays @@ -945,3 +957,117 @@ def _create_transpile_report( json_object = json.dumps(data, indent=6) with open(file_name, "w") as outfile: outfile.write(json_object) + + +def handle_example( + *, + test_example: bool = False, + test_frontend_example: bool = False, + test_method_example: bool = False, + test_frontend_method_example: bool = False, + **given_kwargs, +): + if test_example: + test_flags = given_kwargs.get("test_flags", {}) + flags = pf.FunctionTestFlags( + ground_truth_backend=test_flags.get("ground_truth_backend", "numpy"), + num_positional_args=test_flags.get("num_positional_args", 0), + instance_method=test_flags.get("instance_method", False), + with_out=test_flags.get("with_out", False), + with_copy=test_flags.get("with_copy", False), + test_gradients=test_flags.get("test_gradients", False), + test_trace=test_flags.get("test_trace", False), + test_trace_each=test_flags.get("test_trace_each", False), + transpile=test_flags.get("transpile", False), + as_variable=test_flags.get("as_variable", [False]), + native_arrays=test_flags.get("native_arrays", [False]), + container=test_flags.get("container", [False]), + precision_mode=test_flags.get("precision_mode", False), + test_cython_wrapper=test_flags.get("test_cython_wrapper", False), + ) + + given_kwargs["test_flags"] = flags + + elif test_frontend_example: + test_flags = given_kwargs.get("test_flags", {}) + flags = pf.FrontendFunctionTestFlags( + num_positional_args=test_flags.get("num_positional_args", 0), + with_out=test_flags.get("with_out", False), + with_copy=test_flags.get("with_copy", False), + inplace=test_flags.get("inplace", False), + as_variable=test_flags.get("as_variable", [False]), + native_arrays=test_flags.get("native_arrays", [False]), + test_trace=test_flags.get("test_trace", False), + test_trace_each=test_flags.get("test_trace_each", False), + generate_frontend_arrays=test_flags.get("generate_frontend_arrays", False), + transpile=test_flags.get("transpile", False), + precision_mode=test_flags.get("precision_mode", False), + ) + + given_kwargs["test_flags"] = flags + + elif test_method_example: + method_flags = given_kwargs.get("method_flags", {}) + init_flags = given_kwargs.get("init_flags", {}) + flags_1 = pf.MethodTestFlags( + num_positional_args=method_flags.get("num_positional_args", 0), + as_variable=method_flags.get("as_variable", [False]), + native_arrays=method_flags.get("native_arrays", [False]), + container_flags=method_flags.get("container", [False]), + precision_mode=method_flags.get("precision_mode", False), + ) + + flags_2 = pf.InitMethodTestFlags( + num_positional_args=init_flags.get("num_positional_args", 0), + as_variable=init_flags.get("as_variable", [False]), + native_arrays=init_flags.get("native_arrays", [False]), + precision_mode=init_flags.get("precision_mode", False), + ) + + given_kwargs["method_flags"] = flags_1 + given_kwargs["init_flags"] = flags_2 + + elif test_frontend_method_example: + method_flags = given_kwargs.get("method_flags", {}) + init_flags = given_kwargs.get("init_flags", {}) + flags_1 = pf.FrontendMethodTestFlags( + num_positional_args=method_flags.get("num_positional_args", 0), + as_variable=method_flags.get("as_variable", [False]), + native_arrays=method_flags.get("native_arrays", [False]), + precision_mode=method_flags.get("precision_mode", False), + inplace=method_flags.get("inplace", False), + test_trace=method_flags.get("test_trace", False), + test_trace_each=method_flags.get("test_trace_each", False), + generate_frontend_arrays=method_flags.get( + "generate_frontend_arrays", False + ), + ) + + flags_2 = pf.FrontendInitTestFlags( + num_positional_args=init_flags.get("num_positional_args", 0), + as_variable=init_flags.get("as_variable", [False]), + native_arrays=init_flags.get("native_arrays", [False]), + ) + + given_kwargs["method_flags"] = flags_1 + given_kwargs["init_flags"] = flags_2 + + def test_wrapper(test_fn): + + hypothesis_test_fn = example(**given_kwargs)(test_fn) + + @functools.wraps(hypothesis_test_fn) + def wrapped_test(*args, **kwargs): + try: + hypothesis_test_fn(*args, **kwargs) + except Exception as e: + # A string matching is used instead of actual exception due to + # exception object in with_backend is different from global Ivy + if e.__class__.__qualname__ == "IvyNotImplementedException": + pytest.skip("Function not implemented in backend.") + else: + raise e + + return wrapped_test + + return test_wrapper diff --git a/ivy_tests/test_ivy/test_frontends/__init__.py b/ivy_tests/test_ivy/test_frontends/__init__.py index ebabc54c49ebc..e58ceb7d6761a 100644 --- a/ivy_tests/test_ivy/test_frontends/__init__.py +++ b/ivy_tests/test_ivy/test_frontends/__init__.py @@ -1,6 +1,6 @@ class NativeClass: - """ - An empty class to represent a class that only exist in a specific framework. + """An empty class to represent a class that only exist in a specific + framework. Attributes ---------- @@ -9,8 +9,7 @@ class NativeClass: """ def __init__(self, native_class): - """ - Construct the native class object. + """Construct the native class object. Parameters ---------- diff --git a/ivy_tests/test_ivy/test_frontends/config/base.py b/ivy_tests/test_ivy/test_frontends/config/base.py index 30c279418d94b..12c0eaeaee15b 100644 --- a/ivy_tests/test_ivy/test_frontends/config/base.py +++ b/ivy_tests/test_ivy/test_frontends/config/base.py @@ -25,9 +25,6 @@ class SupportedDtypes: valid_uint_dtypes: List[str] invalid_uint_dtypes: List[str] - valid_uint_dtypes: List[str] - invalid_uint_dtypes: List[str] - valid_float_dtypes: List[str] invalid_float_dtypes: List[str] diff --git a/ivy_tests/test_ivy/test_frontends/test_jax/test_array.py b/ivy_tests/test_ivy/test_frontends/test_jax/test_array.py index bbf108fd4eec1..546387bf6b111 100644 --- a/ivy_tests/test_ivy/test_frontends/test_jax/test_array.py +++ b/ivy_tests/test_ivy/test_frontends/test_jax/test_array.py @@ -177,6 +177,30 @@ def _transpose_helper(draw): return x, xT +# swapaxes +@st.composite +def dtype_x_axis(draw): + dtype, x, x_shape = draw( + helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("numeric"), + min_num_dims=1, + max_num_dims=5, + ret_shape=True, + ) + ) + axis1, axis2 = draw( + helpers.get_axis( + shape=x_shape, + sort_values=False, + unique=True, + min_size=2, + max_size=2, + force_tuple=True, + ) + ) + return dtype, x, axis1, axis2 + + # --- Main --- # # ------------ # @@ -184,15 +208,13 @@ def _transpose_helper(draw): @handle_frontend_method( class_tree=CLASS_TREE, init_tree="jax.numpy.array", - method_name="__add__", - dtype_x=helpers.dtype_and_values( + method_name="__abs__", + dtype_and_x=helpers.dtype_and_values( available_dtypes=helpers.get_dtypes("numeric"), - shared_dtype=True, - num_arrays=2, ), ) -def test_jax___add__( - dtype_x, +def test_jax___abs__( + dtype_and_x, frontend, frontend_method_data, init_flags, @@ -200,7 +222,7 @@ def test_jax___add__( backend_fw, on_device, ): - input_dtype, x = dtype_x + input_dtype, x = dtype_and_x helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, @@ -208,7 +230,7 @@ def test_jax___add__( "object": x[0], }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={"other": x[1]}, + method_all_as_kwargs_np={}, frontend=frontend, frontend_method_data=frontend_method_data, init_flags=init_flags, @@ -220,14 +242,14 @@ def test_jax___add__( @handle_frontend_method( class_tree=CLASS_TREE, init_tree="jax.numpy.array", - method_name="__div__", + method_name="__add__", dtype_x=helpers.dtype_and_values( available_dtypes=helpers.get_dtypes("numeric"), shared_dtype=True, num_arrays=2, ), ) -def test_jax___div__( +def test_jax___add__( dtype_x, frontend, frontend_method_data, @@ -237,7 +259,6 @@ def test_jax___div__( on_device, ): input_dtype, x = dtype_x - assume(not np.any(np.isclose(x[1], 0))) helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, @@ -254,17 +275,18 @@ def test_jax___div__( ) -# __getitem__ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="jax.numpy.array", - method_name="__getitem__", - dtype_x_index=helpers.dtype_array_query( - available_dtypes=helpers.get_dtypes("valid"), - ).filter(lambda x: not (isinstance(x[-1], np.ndarray) and x[-1].dtype == np.bool_)), + method_name="__and__", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=st.one_of(st.just(("bool",)), helpers.get_dtypes("integer")), + num_arrays=2, + shared_dtype=True, + ), ) -def test_jax___getitem__( - dtype_x_index, +def test_jax___and__( + dtype_and_x, frontend, frontend_method_data, init_flags, @@ -272,13 +294,15 @@ def test_jax___getitem__( backend_fw, on_device, ): - input_dtype, x, index = dtype_x_index + input_dtype, x = dtype_and_x helpers.test_frontend_method( - init_input_dtypes=[input_dtype[0]], + init_input_dtypes=input_dtype, backend_to_test=backend_fw, - init_all_as_kwargs_np={"object": x}, - method_input_dtypes=[*input_dtype[1:]], - method_all_as_kwargs_np={"idx": index}, + init_all_as_kwargs_np={ + "object": x[0], + }, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={"other": x[1]}, frontend=frontend, frontend_method_data=frontend_method_data, init_flags=init_flags, @@ -290,13 +314,15 @@ def test_jax___getitem__( @handle_frontend_method( class_tree=CLASS_TREE, init_tree="jax.numpy.array", - method_name="__invert__", - dtype_and_x=helpers.dtype_and_values( - available_dtypes=st.one_of(st.just(("bool",)), helpers.get_dtypes("integer")), + method_name="__div__", + dtype_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("numeric"), + shared_dtype=True, + num_arrays=2, ), ) -def test_jax___invert__( - dtype_and_x, +def test_jax___div__( + dtype_x, frontend, frontend_method_data, init_flags, @@ -304,7 +330,8 @@ def test_jax___invert__( backend_fw, on_device, ): - input_dtype, x = dtype_and_x + input_dtype, x = dtype_x + assume(not np.any(np.isclose(x[1], 0))) helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, @@ -312,7 +339,7 @@ def test_jax___invert__( "object": x[0], }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={}, + method_all_as_kwargs_np={"other": x[1]}, frontend=frontend, frontend_method_data=frontend_method_data, init_flags=init_flags, @@ -324,11 +351,14 @@ def test_jax___invert__( @handle_frontend_method( class_tree=CLASS_TREE, init_tree="jax.numpy.array", - method_name="__lshift__", - dtype_x_shift=_get_dtype_x_and_int_shift(dtype="signed_integer"), + method_name="__eq__", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("numeric"), + num_arrays=2, + ), ) -def test_jax___lshift__( - dtype_x_shift, +def test_jax___eq__( + dtype_and_x, frontend, frontend_method_data, init_flags, @@ -336,15 +366,18 @@ def test_jax___lshift__( backend_fw, on_device, ): - input_dtype, x, shift = dtype_x_shift + input_dtype, x = dtype_and_x + assume("bfloat16" not in input_dtype) helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, init_all_as_kwargs_np={ - "object": x, + "object": x[0], }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={"other": shift}, + method_all_as_kwargs_np={ + "other": x[1], + }, frontend=frontend, frontend_method_data=frontend_method_data, init_flags=init_flags, @@ -356,11 +389,14 @@ def test_jax___lshift__( @handle_frontend_method( class_tree=CLASS_TREE, init_tree="jax.numpy.array", - method_name="__matmul__", - dtype_x=_get_dtype_input_and_vectors(), + method_name="__ge__", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("float_and_integer"), + num_arrays=2, + ), ) -def test_jax___matmul__( - dtype_x, +def test_jax___ge__( + dtype_and_x, frontend, frontend_method_data, init_flags, @@ -368,7 +404,8 @@ def test_jax___matmul__( backend_fw, on_device, ): - input_dtype, x = dtype_x + input_dtype, x = dtype_and_x + assume("bfloat16" not in input_dtype) helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, @@ -376,7 +413,9 @@ def test_jax___matmul__( "object": x[0], }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={"other": x[1]}, + method_all_as_kwargs_np={ + "other": x[1], + }, frontend=frontend, frontend_method_data=frontend_method_data, init_flags=init_flags, @@ -385,18 +424,17 @@ def test_jax___matmul__( ) +# __getitem__ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="jax.numpy.array", - method_name="__mod__", - dtype_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("numeric"), - shared_dtype=True, - num_arrays=2, - ), + method_name="__getitem__", + dtype_x_index=helpers.dtype_array_query( + available_dtypes=helpers.get_dtypes("valid"), + ).filter(lambda x: not (isinstance(x[-1], np.ndarray) and x[-1].dtype == np.bool_)), ) -def test_jax___mod__( - dtype_x, +def test_jax___getitem__( + dtype_x_index, frontend, frontend_method_data, init_flags, @@ -404,16 +442,13 @@ def test_jax___mod__( backend_fw, on_device, ): - input_dtype, x = dtype_x - assume(not np.any(np.isclose(x[1], 0))) + input_dtype, x, index = dtype_x_index helpers.test_frontend_method( - init_input_dtypes=input_dtype, + init_input_dtypes=[input_dtype[0]], backend_to_test=backend_fw, - init_all_as_kwargs_np={ - "object": x[0], - }, - method_input_dtypes=input_dtype, - method_all_as_kwargs_np={"other": x[1]}, + init_all_as_kwargs_np={"object": x}, + method_input_dtypes=[*input_dtype[1:]], + method_all_as_kwargs_np={"idx": index}, frontend=frontend, frontend_method_data=frontend_method_data, init_flags=init_flags, @@ -425,15 +460,14 @@ def test_jax___mod__( @handle_frontend_method( class_tree=CLASS_TREE, init_tree="jax.numpy.array", - method_name="__mul__", - dtype_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("numeric"), - shared_dtype=True, + method_name="__gt__", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("float_and_integer"), num_arrays=2, ), ) -def test_jax___mul__( - dtype_x, +def test_jax___gt__( + dtype_and_x, frontend, frontend_method_data, init_flags, @@ -441,7 +475,8 @@ def test_jax___mul__( backend_fw, on_device, ): - input_dtype, x = dtype_x + input_dtype, x = dtype_and_x + assume("bfloat16" not in input_dtype) helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, @@ -449,7 +484,9 @@ def test_jax___mul__( "object": x[0], }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={"other": x[1]}, + method_all_as_kwargs_np={ + "other": x[1], + }, frontend=frontend, frontend_method_data=frontend_method_data, init_flags=init_flags, @@ -461,15 +498,13 @@ def test_jax___mul__( @handle_frontend_method( class_tree=CLASS_TREE, init_tree="jax.numpy.array", - method_name="__radd__", - dtype_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("numeric"), - shared_dtype=True, - num_arrays=2, + method_name="__invert__", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=st.one_of(st.just(("bool",)), helpers.get_dtypes("integer")), ), ) -def test_jax___radd__( - dtype_x, +def test_jax___invert__( + dtype_and_x, frontend, frontend_method_data, init_flags, @@ -477,7 +512,7 @@ def test_jax___radd__( backend_fw, on_device, ): - input_dtype, x = dtype_x + input_dtype, x = dtype_and_x helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, @@ -485,7 +520,7 @@ def test_jax___radd__( "object": x[0], }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={"other": x[1]}, + method_all_as_kwargs_np={}, frontend=frontend, frontend_method_data=frontend_method_data, init_flags=init_flags, @@ -497,15 +532,14 @@ def test_jax___radd__( @handle_frontend_method( class_tree=CLASS_TREE, init_tree="jax.numpy.array", - method_name="__rdiv__", - dtype_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("numeric"), - shared_dtype=True, + method_name="__le__", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("float_and_integer"), num_arrays=2, ), ) -def test_jax___rdiv__( - dtype_x, +def test_jax___le__( + dtype_and_x, frontend, frontend_method_data, init_flags, @@ -513,8 +547,8 @@ def test_jax___rdiv__( backend_fw, on_device, ): - input_dtype, x = dtype_x - assume(not np.any(np.isclose(x[0], 0))) + input_dtype, x = dtype_and_x + assume("bfloat16" not in input_dtype) helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, @@ -522,7 +556,9 @@ def test_jax___rdiv__( "object": x[0], }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={"other": x[1]}, + method_all_as_kwargs_np={ + "other": x[1], + }, frontend=frontend, frontend_method_data=frontend_method_data, init_flags=init_flags, @@ -534,10 +570,10 @@ def test_jax___rdiv__( @handle_frontend_method( class_tree=CLASS_TREE, init_tree="jax.numpy.array", - method_name="__rlshift__", + method_name="__lshift__", dtype_x_shift=_get_dtype_x_and_int_shift(dtype="signed_integer"), ) -def test_jax___rlshift__( +def test_jax___lshift__( dtype_x_shift, frontend, frontend_method_data, @@ -551,10 +587,10 @@ def test_jax___rlshift__( init_input_dtypes=input_dtype, backend_to_test=backend_fw, init_all_as_kwargs_np={ - "object": shift, + "object": x, }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={"other": x}, + method_all_as_kwargs_np={"other": shift}, frontend=frontend, frontend_method_data=frontend_method_data, init_flags=init_flags, @@ -566,11 +602,15 @@ def test_jax___rlshift__( @handle_frontend_method( class_tree=CLASS_TREE, init_tree="jax.numpy.array", - method_name="__rmatmul__", - dtype_x=_get_dtype_input_and_vectors(), + method_name="__lt__", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("float_and_integer"), + num_arrays=2, + shared_dtype=True, + ), ) -def test_jax___rmatmul__( - dtype_x, +def test_jax___lt__( + dtype_and_x, frontend, frontend_method_data, init_flags, @@ -578,7 +618,7 @@ def test_jax___rmatmul__( backend_fw, on_device, ): - input_dtype, x = dtype_x + input_dtype, x = dtype_and_x helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, @@ -586,7 +626,9 @@ def test_jax___rmatmul__( "object": x[0], }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={"other": x[1]}, + method_all_as_kwargs_np={ + "other": x[1], + }, frontend=frontend, frontend_method_data=frontend_method_data, init_flags=init_flags, @@ -598,14 +640,10 @@ def test_jax___rmatmul__( @handle_frontend_method( class_tree=CLASS_TREE, init_tree="jax.numpy.array", - method_name="__rmod__", - dtype_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("numeric"), - shared_dtype=True, - num_arrays=2, - ), + method_name="__matmul__", + dtype_x=_get_dtype_input_and_vectors(), ) -def test_jax___rmod__( +def test_jax___matmul__( dtype_x, frontend, frontend_method_data, @@ -615,7 +653,6 @@ def test_jax___rmod__( on_device, ): input_dtype, x = dtype_x - assume(not np.any(np.isclose(x[0], 0))) helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, @@ -635,14 +672,14 @@ def test_jax___rmod__( @handle_frontend_method( class_tree=CLASS_TREE, init_tree="jax.numpy.array", - method_name="__rmul__", + method_name="__mod__", dtype_x=helpers.dtype_and_values( available_dtypes=helpers.get_dtypes("numeric"), shared_dtype=True, num_arrays=2, ), ) -def test_jax___rmul__( +def test_jax___mod__( dtype_x, frontend, frontend_method_data, @@ -652,6 +689,7 @@ def test_jax___rmul__( on_device, ): input_dtype, x = dtype_x + assume(not np.any(np.isclose(x[1], 0))) helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, @@ -671,11 +709,15 @@ def test_jax___rmul__( @handle_frontend_method( class_tree=CLASS_TREE, init_tree="jax.numpy.array", - method_name="__rrshift__", - dtype_x_shift=_get_dtype_x_and_int_shift(dtype="signed_integer"), + method_name="__mul__", + dtype_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("numeric"), + shared_dtype=True, + num_arrays=2, + ), ) -def test_jax___rrshift__( - dtype_x_shift, +def test_jax___mul__( + dtype_x, frontend, frontend_method_data, init_flags, @@ -683,15 +725,15 @@ def test_jax___rrshift__( backend_fw, on_device, ): - input_dtype, x, shift = dtype_x_shift + input_dtype, x = dtype_x helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, init_all_as_kwargs_np={ - "object": shift, + "object": x[0], }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={"other": x}, + method_all_as_kwargs_np={"other": x[1]}, frontend=frontend, frontend_method_data=frontend_method_data, init_flags=init_flags, @@ -703,11 +745,14 @@ def test_jax___rrshift__( @handle_frontend_method( class_tree=CLASS_TREE, init_tree="jax.numpy.array", - method_name="__rshift__", - dtype_x_shift=_get_dtype_x_and_int_shift(dtype="signed_integer"), + method_name="__ne__", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("numeric"), + num_arrays=2, + ), ) -def test_jax___rshift__( - dtype_x_shift, +def test_jax___ne__( + dtype_and_x, frontend, frontend_method_data, init_flags, @@ -715,15 +760,18 @@ def test_jax___rshift__( backend_fw, on_device, ): - input_dtype, x, shift = dtype_x_shift + input_dtype, x = dtype_and_x + assume("bfloat16" not in input_dtype) helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, init_all_as_kwargs_np={ - "object": x, + "object": x[0], }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={"other": shift}, + method_all_as_kwargs_np={ + "other": x[1], + }, frontend=frontend, frontend_method_data=frontend_method_data, init_flags=init_flags, @@ -735,15 +783,13 @@ def test_jax___rshift__( @handle_frontend_method( class_tree=CLASS_TREE, init_tree="jax.numpy.array", - method_name="__rsub__", - dtype_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("numeric"), - shared_dtype=True, - num_arrays=2, + method_name="__neg__", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("signed_integer"), ), ) -def test_jax___rsub__( - dtype_x, +def test_jax___neg__( + dtype_and_x, frontend, frontend_method_data, init_flags, @@ -751,7 +797,7 @@ def test_jax___rsub__( backend_fw, on_device, ): - input_dtype, x = dtype_x + input_dtype, x = dtype_and_x helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, @@ -759,7 +805,7 @@ def test_jax___rsub__( "object": x[0], }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={"other": x[1]}, + method_all_as_kwargs_np={}, frontend=frontend, frontend_method_data=frontend_method_data, init_flags=init_flags, @@ -771,15 +817,15 @@ def test_jax___rsub__( @handle_frontend_method( class_tree=CLASS_TREE, init_tree="jax.numpy.array", - method_name="__rtruediv__", - dtype_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("numeric"), - shared_dtype=True, + method_name="__or__", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=st.one_of(st.just(("bool",)), helpers.get_dtypes("integer")), num_arrays=2, + shared_dtype=True, ), ) -def test_jax___rtruediv__( - dtype_x, +def test_jax___or__( + dtype_and_x, frontend, frontend_method_data, init_flags, @@ -787,8 +833,7 @@ def test_jax___rtruediv__( backend_fw, on_device, ): - input_dtype, x = dtype_x - assume(not np.any(np.isclose(x[0], 0))) + input_dtype, x = dtype_and_x helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, @@ -808,15 +853,13 @@ def test_jax___rtruediv__( @handle_frontend_method( class_tree=CLASS_TREE, init_tree="jax.numpy.array", - method_name="__sub__", - dtype_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("numeric"), - shared_dtype=True, - num_arrays=2, + method_name="__pos__", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), ), ) -def test_jax___sub__( - dtype_x, +def test_jax___pos__( + dtype_and_x, frontend, frontend_method_data, init_flags, @@ -824,38 +867,35 @@ def test_jax___sub__( backend_fw, on_device, ): - input_dtype, x = dtype_x + input_dtype, x = dtype_and_x helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, + on_device=on_device, init_all_as_kwargs_np={ "object": x[0], }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={"other": x[1]}, + method_all_as_kwargs_np={}, frontend=frontend, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, - on_device=on_device, ) @handle_frontend_method( class_tree=CLASS_TREE, init_tree="jax.numpy.array", - method_name="__truediv__", - dtype_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("numeric"), - shared_dtype=True, + method_name="__pow__", + dtype_x_pow=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("float"), num_arrays=2, - large_abs_safety_factor=2, - small_abs_safety_factor=2, - safety_factor_scale="log", + shared_dtype=True, ), ) -def test_jax___truediv__( - dtype_x, +def test_jax___pow__( + dtype_x_pow, frontend, frontend_method_data, init_flags, @@ -863,8 +903,7 @@ def test_jax___truediv__( backend_fw, on_device, ): - input_dtype, x = dtype_x - assume(not np.any(np.isclose(x[1], 0))) + input_dtype, x = dtype_x_pow helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, @@ -872,7 +911,9 @@ def test_jax___truediv__( "object": x[0], }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={"other": x[1]}, + method_all_as_kwargs_np={ + "other": x[1], + }, frontend=frontend, frontend_method_data=frontend_method_data, init_flags=init_flags, @@ -884,13 +925,15 @@ def test_jax___truediv__( @handle_frontend_method( class_tree=CLASS_TREE, init_tree="jax.numpy.array", - method_name="__abs__", - dtype_and_x=helpers.dtype_and_values( + method_name="__radd__", + dtype_x=helpers.dtype_and_values( available_dtypes=helpers.get_dtypes("numeric"), + shared_dtype=True, + num_arrays=2, ), ) -def test_jax__abs_( - dtype_and_x, +def test_jax___radd__( + dtype_x, frontend, frontend_method_data, init_flags, @@ -898,7 +941,7 @@ def test_jax__abs_( backend_fw, on_device, ): - input_dtype, x = dtype_and_x + input_dtype, x = dtype_x helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, @@ -906,7 +949,7 @@ def test_jax__abs_( "object": x[0], }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={}, + method_all_as_kwargs_np={"other": x[1]}, frontend=frontend, frontend_method_data=frontend_method_data, init_flags=init_flags, @@ -918,14 +961,14 @@ def test_jax__abs_( @handle_frontend_method( class_tree=CLASS_TREE, init_tree="jax.numpy.array", - method_name="__and__", + method_name="__rand__", dtype_and_x=helpers.dtype_and_values( available_dtypes=st.one_of(st.just(("bool",)), helpers.get_dtypes("integer")), num_arrays=2, shared_dtype=True, ), ) -def test_jax__and_( +def test_jax___rand__( dtype_and_x, frontend, frontend_method_data, @@ -954,14 +997,15 @@ def test_jax__and_( @handle_frontend_method( class_tree=CLASS_TREE, init_tree="jax.numpy.array", - method_name="__eq__", - dtype_and_x=helpers.dtype_and_values( + method_name="__rdiv__", + dtype_x=helpers.dtype_and_values( available_dtypes=helpers.get_dtypes("numeric"), + shared_dtype=True, num_arrays=2, ), ) -def test_jax__eq_( - dtype_and_x, +def test_jax___rdiv__( + dtype_x, frontend, frontend_method_data, init_flags, @@ -969,8 +1013,8 @@ def test_jax__eq_( backend_fw, on_device, ): - input_dtype, x = dtype_and_x - assume("bfloat16" not in input_dtype) + input_dtype, x = dtype_x + assume(not np.any(np.isclose(x[0], 0))) helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, @@ -978,9 +1022,7 @@ def test_jax__eq_( "object": x[0], }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={ - "other": x[1], - }, + method_all_as_kwargs_np={"other": x[1]}, frontend=frontend, frontend_method_data=frontend_method_data, init_flags=init_flags, @@ -992,14 +1034,11 @@ def test_jax__eq_( @handle_frontend_method( class_tree=CLASS_TREE, init_tree="jax.numpy.array", - method_name="__ge__", - dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("float_and_integer"), - num_arrays=2, - ), + method_name="__rlshift__", + dtype_x_shift=_get_dtype_x_and_int_shift(dtype="signed_integer"), ) -def test_jax__ge_( - dtype_and_x, +def test_jax___rlshift__( + dtype_x_shift, frontend, frontend_method_data, init_flags, @@ -1007,18 +1046,15 @@ def test_jax__ge_( backend_fw, on_device, ): - input_dtype, x = dtype_and_x - assume("bfloat16" not in input_dtype) + input_dtype, x, shift = dtype_x_shift helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, init_all_as_kwargs_np={ - "object": x[0], + "object": shift, }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={ - "other": x[1], - }, + method_all_as_kwargs_np={"other": x}, frontend=frontend, frontend_method_data=frontend_method_data, init_flags=init_flags, @@ -1030,14 +1066,11 @@ def test_jax__ge_( @handle_frontend_method( class_tree=CLASS_TREE, init_tree="jax.numpy.array", - method_name="__gt__", - dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("float_and_integer"), - num_arrays=2, - ), + method_name="__rmatmul__", + dtype_x=_get_dtype_input_and_vectors(), ) -def test_jax__gt_( - dtype_and_x, +def test_jax___rmatmul__( + dtype_x, frontend, frontend_method_data, init_flags, @@ -1045,8 +1078,7 @@ def test_jax__gt_( backend_fw, on_device, ): - input_dtype, x = dtype_and_x - assume("bfloat16" not in input_dtype) + input_dtype, x = dtype_x helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, @@ -1054,9 +1086,7 @@ def test_jax__gt_( "object": x[0], }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={ - "other": x[1], - }, + method_all_as_kwargs_np={"other": x[1]}, frontend=frontend, frontend_method_data=frontend_method_data, init_flags=init_flags, @@ -1068,14 +1098,15 @@ def test_jax__gt_( @handle_frontend_method( class_tree=CLASS_TREE, init_tree="jax.numpy.array", - method_name="__le__", - dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("float_and_integer"), + method_name="__rmod__", + dtype_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("numeric"), + shared_dtype=True, num_arrays=2, ), ) -def test_jax__le_( - dtype_and_x, +def test_jax___rmod__( + dtype_x, frontend, frontend_method_data, init_flags, @@ -1083,8 +1114,8 @@ def test_jax__le_( backend_fw, on_device, ): - input_dtype, x = dtype_and_x - assume("bfloat16" not in input_dtype) + input_dtype, x = dtype_x + assume(not np.any(np.isclose(x[0], 0))) helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, @@ -1092,9 +1123,7 @@ def test_jax__le_( "object": x[0], }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={ - "other": x[1], - }, + method_all_as_kwargs_np={"other": x[1]}, frontend=frontend, frontend_method_data=frontend_method_data, init_flags=init_flags, @@ -1106,15 +1135,15 @@ def test_jax__le_( @handle_frontend_method( class_tree=CLASS_TREE, init_tree="jax.numpy.array", - method_name="__lt__", - dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("float_and_integer"), - num_arrays=2, + method_name="__rmul__", + dtype_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("numeric"), shared_dtype=True, + num_arrays=2, ), ) -def test_jax__lt_( - dtype_and_x, +def test_jax___rmul__( + dtype_x, frontend, frontend_method_data, init_flags, @@ -1122,7 +1151,7 @@ def test_jax__lt_( backend_fw, on_device, ): - input_dtype, x = dtype_and_x + input_dtype, x = dtype_x helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, @@ -1130,9 +1159,7 @@ def test_jax__lt_( "object": x[0], }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={ - "other": x[1], - }, + method_all_as_kwargs_np={"other": x[1]}, frontend=frontend, frontend_method_data=frontend_method_data, init_flags=init_flags, @@ -1144,13 +1171,14 @@ def test_jax__lt_( @handle_frontend_method( class_tree=CLASS_TREE, init_tree="jax.numpy.array", - method_name="__ne__", + method_name="__ror__", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("numeric"), + available_dtypes=st.one_of(st.just(("bool",)), helpers.get_dtypes("integer")), num_arrays=2, + shared_dtype=True, ), ) -def test_jax__ne_( +def test_jax___ror__( dtype_and_x, frontend, frontend_method_data, @@ -1160,7 +1188,6 @@ def test_jax__ne_( on_device, ): input_dtype, x = dtype_and_x - assume("bfloat16" not in input_dtype) helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, @@ -1168,9 +1195,7 @@ def test_jax__ne_( "object": x[0], }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={ - "other": x[1], - }, + method_all_as_kwargs_np={"other": x[1]}, frontend=frontend, frontend_method_data=frontend_method_data, init_flags=init_flags, @@ -1182,13 +1207,11 @@ def test_jax__ne_( @handle_frontend_method( class_tree=CLASS_TREE, init_tree="jax.numpy.array", - method_name="__neg__", - dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("signed_integer"), - ), + method_name="__rpow__", + dtype_x_pow=_get_dtype_x_and_int(), ) -def test_jax__neg_( - dtype_and_x, +def test_jax___rpow__( + dtype_x_pow, frontend, frontend_method_data, init_flags, @@ -1196,15 +1219,17 @@ def test_jax__neg_( backend_fw, on_device, ): - input_dtype, x = dtype_and_x + input_dtype, x, pow = dtype_x_pow helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, init_all_as_kwargs_np={ - "object": x[0], + "object": pow[0], }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={}, + method_all_as_kwargs_np={ + "other": x[0], + }, frontend=frontend, frontend_method_data=frontend_method_data, init_flags=init_flags, @@ -1216,15 +1241,11 @@ def test_jax__neg_( @handle_frontend_method( class_tree=CLASS_TREE, init_tree="jax.numpy.array", - method_name="__or__", - dtype_and_x=helpers.dtype_and_values( - available_dtypes=st.one_of(st.just(("bool",)), helpers.get_dtypes("integer")), - num_arrays=2, - shared_dtype=True, - ), + method_name="__rrshift__", + dtype_x_shift=_get_dtype_x_and_int_shift(dtype="signed_integer"), ) -def test_jax__or_( - dtype_and_x, +def test_jax___rrshift__( + dtype_x_shift, frontend, frontend_method_data, init_flags, @@ -1232,15 +1253,15 @@ def test_jax__or_( backend_fw, on_device, ): - input_dtype, x = dtype_and_x + input_dtype, x, shift = dtype_x_shift helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, init_all_as_kwargs_np={ - "object": x[0], + "object": shift, }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={"other": x[1]}, + method_all_as_kwargs_np={"other": x}, frontend=frontend, frontend_method_data=frontend_method_data, init_flags=init_flags, @@ -1252,13 +1273,11 @@ def test_jax__or_( @handle_frontend_method( class_tree=CLASS_TREE, init_tree="jax.numpy.array", - method_name="__pos__", - dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("valid"), - ), + method_name="__rshift__", + dtype_x_shift=_get_dtype_x_and_int_shift(dtype="signed_integer"), ) -def test_jax__pos_( - dtype_and_x, +def test_jax___rshift__( + dtype_x_shift, frontend, frontend_method_data, init_flags, @@ -1266,35 +1285,35 @@ def test_jax__pos_( backend_fw, on_device, ): - input_dtype, x = dtype_and_x + input_dtype, x, shift = dtype_x_shift helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, - on_device=on_device, init_all_as_kwargs_np={ - "object": x[0], + "object": x, }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={}, + method_all_as_kwargs_np={"other": shift}, frontend=frontend, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, + on_device=on_device, ) @handle_frontend_method( class_tree=CLASS_TREE, init_tree="jax.numpy.array", - method_name="__pow__", - dtype_x_pow=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("float"), - num_arrays=2, + method_name="__rsub__", + dtype_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("numeric"), shared_dtype=True, + num_arrays=2, ), ) -def test_jax__pow_( - dtype_x_pow, +def test_jax___rsub__( + dtype_x, frontend, frontend_method_data, init_flags, @@ -1302,7 +1321,7 @@ def test_jax__pow_( backend_fw, on_device, ): - input_dtype, x = dtype_x_pow + input_dtype, x = dtype_x helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, @@ -1310,9 +1329,7 @@ def test_jax__pow_( "object": x[0], }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={ - "other": x[1], - }, + method_all_as_kwargs_np={"other": x[1]}, frontend=frontend, frontend_method_data=frontend_method_data, init_flags=init_flags, @@ -1324,15 +1341,15 @@ def test_jax__pow_( @handle_frontend_method( class_tree=CLASS_TREE, init_tree="jax.numpy.array", - method_name="__rand__", - dtype_and_x=helpers.dtype_and_values( - available_dtypes=st.one_of(st.just(("bool",)), helpers.get_dtypes("integer")), - num_arrays=2, + method_name="__rtruediv__", + dtype_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("numeric"), shared_dtype=True, + num_arrays=2, ), ) -def test_jax__rand_( - dtype_and_x, +def test_jax___rtruediv__( + dtype_x, frontend, frontend_method_data, init_flags, @@ -1340,7 +1357,8 @@ def test_jax__rand_( backend_fw, on_device, ): - input_dtype, x = dtype_and_x + input_dtype, x = dtype_x + assume(not np.any(np.isclose(x[0], 0))) helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, @@ -1360,14 +1378,14 @@ def test_jax__rand_( @handle_frontend_method( class_tree=CLASS_TREE, init_tree="jax.numpy.array", - method_name="__ror__", + method_name="__rxor__", dtype_and_x=helpers.dtype_and_values( available_dtypes=st.one_of(st.just(("bool",)), helpers.get_dtypes("integer")), num_arrays=2, shared_dtype=True, ), ) -def test_jax__ror_( +def test_jax___rxor__( dtype_and_x, frontend, frontend_method_data, @@ -1396,11 +1414,15 @@ def test_jax__ror_( @handle_frontend_method( class_tree=CLASS_TREE, init_tree="jax.numpy.array", - method_name="__rpow__", - dtype_x_pow=_get_dtype_x_and_int(), + method_name="__sub__", + dtype_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("numeric"), + shared_dtype=True, + num_arrays=2, + ), ) -def test_jax__rpow_( - dtype_x_pow, +def test_jax___sub__( + dtype_x, frontend, frontend_method_data, init_flags, @@ -1408,17 +1430,15 @@ def test_jax__rpow_( backend_fw, on_device, ): - input_dtype, x, pow = dtype_x_pow + input_dtype, x = dtype_x helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, init_all_as_kwargs_np={ - "object": pow[0], + "object": x[0], }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={ - "other": x[0], - }, + method_all_as_kwargs_np={"other": x[1]}, frontend=frontend, frontend_method_data=frontend_method_data, init_flags=init_flags, @@ -1430,15 +1450,18 @@ def test_jax__rpow_( @handle_frontend_method( class_tree=CLASS_TREE, init_tree="jax.numpy.array", - method_name="__rxor__", - dtype_and_x=helpers.dtype_and_values( - available_dtypes=st.one_of(st.just(("bool",)), helpers.get_dtypes("integer")), - num_arrays=2, + method_name="__truediv__", + dtype_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("numeric"), shared_dtype=True, + num_arrays=2, + large_abs_safety_factor=2, + small_abs_safety_factor=2, + safety_factor_scale="log", ), ) -def test_jax__rxor_( - dtype_and_x, +def test_jax___truediv__( + dtype_x, frontend, frontend_method_data, init_flags, @@ -1446,7 +1469,8 @@ def test_jax__rxor_( backend_fw, on_device, ): - input_dtype, x = dtype_and_x + input_dtype, x = dtype_x + assume(not np.any(np.isclose(x[1], 0))) helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, @@ -1473,7 +1497,7 @@ def test_jax__rxor_( shared_dtype=True, ), ) -def test_jax__xor_( +def test_jax___xor__( dtype_and_x, frontend, frontend_method_data, @@ -2766,3 +2790,39 @@ def test_jax_sum( on_device=on_device, atol_=1e-04, ) + + +# swapaxes +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="jax.numpy.array", + method_name="swapaxes", + dtype_x_axis=dtype_x_axis(), +) +def test_jax_swapaxes( + dtype_x_axis, + frontend, + frontend_method_data, + backend_fw, + init_flags, + method_flags, + on_device, +): + input_dtypes, x, axis1, axis2 = dtype_x_axis + helpers.test_frontend_method( + init_input_dtypes=input_dtypes, + backend_to_test=backend_fw, + method_input_dtypes=input_dtypes, + init_all_as_kwargs_np={ + "object": x[0], + }, + method_all_as_kwargs_np={ + "axis1": axis1, + "axis2": axis2, + }, + frontend=frontend, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + on_device=on_device, + ) diff --git a/ivy_tests/test_ivy/test_frontends/test_jax/test_lax/test_linalg.py b/ivy_tests/test_ivy/test_frontends/test_jax/test_lax/test_linalg.py index bc5ec8da88181..789512cb08421 100644 --- a/ivy_tests/test_ivy/test_frontends/test_jax/test_lax/test_linalg.py +++ b/ivy_tests/test_ivy/test_frontends/test_jax/test_lax/test_linalg.py @@ -16,7 +16,7 @@ available_dtypes=helpers.get_dtypes("float"), min_value=0, max_value=10, - shape=helpers.ints(min_value=2, max_value=5).map(lambda x: tuple([x, x])), + shape=helpers.ints(min_value=2, max_value=5).map(lambda x: (x, x)), ).filter( lambda x: "float16" not in x[0] and "bfloat16" not in x[0] @@ -64,7 +64,7 @@ def test_jax_cholesky( available_dtypes=helpers.get_dtypes("float"), min_value=0, max_value=10, - shape=helpers.ints(min_value=2, max_value=5).map(lambda x: tuple([x, x])), + shape=helpers.ints(min_value=2, max_value=5).map(lambda x: (x, x)), ).filter( lambda x: "float16" not in x[0] and "bfloat16" not in x[0] @@ -165,7 +165,7 @@ def test_jax_qr( available_dtypes=helpers.get_dtypes("float"), min_value=0, max_value=10, - shape=helpers.ints(min_value=2, max_value=5).map(lambda x: tuple([x, x])), + shape=helpers.ints(min_value=2, max_value=5).map(lambda x: (x, x)), ).filter( lambda x: "float16" not in x[0] and "bfloat16" not in x[0] diff --git a/ivy_tests/test_ivy/test_frontends/test_jax/test_lax/test_operators.py b/ivy_tests/test_ivy/test_frontends/test_jax/test_lax/test_operators.py index b04d2ec3604f1..649b2cfaba96f 100644 --- a/ivy_tests/test_ivy/test_frontends/test_jax/test_lax/test_operators.py +++ b/ivy_tests/test_ivy/test_frontends/test_jax/test_lax/test_operators.py @@ -481,7 +481,9 @@ def _x_and_filters(draw, dim=2, transpose=False, general=False): dimension_numbers = ( ("NCH", "OIH", "NCH") if dim == 1 - else ("NCHW", "OIHW", "NCHW") if dim == 2 else ("NCDHW", "OIDHW", "NCDHW") + else ("NCHW", "OIHW", "NCHW") + if dim == 2 + else ("NCDHW", "OIDHW", "NCDHW") ) dim_nums = _dimension_numbers(dimension_numbers, dim + 2, transp=transpose) if not transpose: @@ -1250,9 +1252,7 @@ def test_jax_conv_general_dilated( ): dtype, x, filters, dilations, dim_num, stride, pad, fc, pref = x_f_d_other _assume_tf_dilation_gt_1(ivy.current_backend_str(), on_device, dilations[0]) - assume( - not (isinstance(pad, str) and not len(dilations[1]) == dilations[1].count(1)) - ) + assume(not isinstance(pad, str) or len(dilations[1]) == dilations[1].count(1)) helpers.test_frontend_function( input_dtypes=dtype, backend_to_test=backend_fw, @@ -1748,7 +1748,7 @@ def test_jax_expand_dims( helpers.test_frontend_function( input_dtypes=x_dtype, frontend=frontend, - bakcend_to_test=backend_fw, + backend_to_test=backend_fw, test_flags=test_flags, fn_tree=fn_tree, on_device=on_device, diff --git a/ivy_tests/test_ivy/test_frontends/test_jax/test_numpy/test_indexing.py b/ivy_tests/test_ivy/test_frontends/test_jax/test_numpy/test_indexing.py index 4d76bfcc9a139..5065fbd54c3a5 100644 --- a/ivy_tests/test_ivy/test_frontends/test_jax/test_numpy/test_indexing.py +++ b/ivy_tests/test_ivy/test_frontends/test_jax/test_numpy/test_indexing.py @@ -53,18 +53,6 @@ def _get_dtype_square_x(draw): return dtype_x -# diagonal -@st.composite -def dims_and_offset(draw, shape): - shape_actual = draw(shape) - dim1 = draw(helpers.get_axis(shape=shape, force_int=True)) - dim2 = draw(helpers.get_axis(shape=shape, force_int=True)) - offset = draw( - st.integers(min_value=-shape_actual[dim1], max_value=shape_actual[dim1]) - ) - return dim1, dim2, offset - - # unravel_index @st.composite def max_value_as_shape_prod(draw): @@ -217,7 +205,7 @@ def test_jax_diag_indices_from( available_dtypes=helpers.get_dtypes("float"), shape=st.shared(helpers.get_shape(min_num_dims=2), key="shape"), ), - dims_and_offset=dims_and_offset( + dims_and_offset=helpers.dims_and_offset( shape=st.shared(helpers.get_shape(min_num_dims=2), key="shape") ), ) diff --git a/ivy_tests/test_ivy/test_frontends/test_jax/test_numpy/test_linalg.py b/ivy_tests/test_ivy/test_frontends/test_jax/test_numpy/test_linalg.py index cb166b68fb046..fb081e1cd406a 100644 --- a/ivy_tests/test_ivy/test_frontends/test_jax/test_numpy/test_linalg.py +++ b/ivy_tests/test_ivy/test_frontends/test_jax/test_numpy/test_linalg.py @@ -148,7 +148,7 @@ def norm_helper(draw): available_dtypes=helpers.get_dtypes("float"), min_value=0, max_value=10, - shape=helpers.ints(min_value=2, max_value=5).map(lambda x: tuple([x, x])), + shape=helpers.ints(min_value=2, max_value=5).map(lambda x: (x, x)), ).filter( lambda x: "float16" not in x[0] and "bfloat16" not in x[0] @@ -248,7 +248,7 @@ def test_jax_det( available_dtypes=helpers.get_dtypes("float"), min_value=0, max_value=10, - shape=helpers.ints(min_value=2, max_value=5).map(lambda x: tuple([x, x])), + shape=helpers.ints(min_value=2, max_value=5).map(lambda x: (x, x)), ).filter( lambda x: "float16" not in x[0] and "bfloat16" not in x[0] @@ -268,8 +268,8 @@ def test_jax_eig( ): dtype, x = dtype_and_x x = np.array(x[0], dtype=dtype[0]) - """Make symmetric positive-definite since ivy does not support complex data dtypes - currently.""" + """Make symmetric positive-definite since ivy does not support complex data + dtypes currently.""" x = np.matmul(x.T, x) + np.identity(x.shape[0]) * 1e-3 ret, frontend_ret = helpers.test_frontend_function( @@ -306,7 +306,7 @@ def test_jax_eig( available_dtypes=helpers.get_dtypes("float"), min_value=0, max_value=10, - shape=helpers.ints(min_value=2, max_value=5).map(lambda x: tuple([x, x])), + shape=helpers.ints(min_value=2, max_value=5).map(lambda x: (x, x)), ).filter( lambda x: "float16" not in x[0] and "bfloat16" not in x[0] @@ -368,7 +368,7 @@ def test_jax_eigh( available_dtypes=helpers.get_dtypes("float"), min_value=0, max_value=10, - shape=helpers.ints(min_value=2, max_value=5).map(lambda x: tuple([x, x])), + shape=helpers.ints(min_value=2, max_value=5).map(lambda x: (x, x)), ).filter( lambda x: "float16" not in x[0] and "bfloat16" not in x[0] @@ -423,7 +423,7 @@ def test_jax_eigvals( available_dtypes=helpers.get_dtypes("float"), min_value=0, max_value=10, - shape=helpers.ints(min_value=2, max_value=5).map(lambda x: tuple([x, x])), + shape=helpers.ints(min_value=2, max_value=5).map(lambda x: (x, x)), ).filter( lambda x: "float16" not in x[0] and "bfloat16" not in x[0] @@ -468,7 +468,7 @@ def test_jax_eigvalsh( available_dtypes=helpers.get_dtypes("float"), min_value=-100, max_value=100, - shape=helpers.ints(min_value=1, max_value=10).map(lambda x: tuple([x, x])), + shape=helpers.ints(min_value=1, max_value=10).map(lambda x: (x, x)), ).filter( lambda x: "float16" not in x[0] and "bfloat16" not in x[0] @@ -541,7 +541,7 @@ def test_jax_lstsq( available_dtypes=helpers.get_dtypes("float"), min_value=-100, max_value=100, - shape=helpers.ints(min_value=1, max_value=10).map(lambda x: tuple([x, x])), + shape=helpers.ints(min_value=1, max_value=10).map(lambda x: (x, x)), ).filter( lambda x: "float16" not in x[0] and "bfloat16" not in x[0] @@ -612,7 +612,7 @@ def test_jax_matrix_rank( available_dtypes=helpers.get_dtypes("float"), min_value=0, max_value=10, - shape=helpers.ints(min_value=2, max_value=5).map(lambda x: tuple([x, x])), + shape=helpers.ints(min_value=2, max_value=5).map(lambda x: (x, x)), num_arrays=2, shared_dtype=True, ).filter( @@ -857,7 +857,7 @@ def test_jax_solve( available_dtypes=helpers.get_dtypes("float"), min_value=0, max_value=10, - shape=helpers.ints(min_value=2, max_value=5).map(lambda x: tuple([x, x])), + shape=helpers.ints(min_value=2, max_value=5).map(lambda x: (x, x)), ).filter( lambda x: "float16" not in x[0] and "bfloat16" not in x[0] diff --git a/ivy_tests/test_ivy/test_frontends/test_jax/test_numpy/test_manipulations.py b/ivy_tests/test_ivy/test_frontends/test_jax/test_numpy/test_manipulations.py index 0595ae1968a5e..2d9d150748115 100644 --- a/ivy_tests/test_ivy/test_frontends/test_jax/test_numpy/test_manipulations.py +++ b/ivy_tests/test_ivy/test_frontends/test_jax/test_numpy/test_manipulations.py @@ -498,6 +498,30 @@ def test_jax_atleast_3d( ) +# bartlett +@handle_frontend_test( + fn_tree="jax.numpy.bartlett", + m=helpers.ints(min_value=0, max_value=20), +) +def test_jax_bartlett( + m, + frontend, + backend_fw, + test_flags, + fn_tree, + on_device, +): + helpers.test_frontend_function( + input_dtypes=["int64"], + backend_to_test=backend_fw, + frontend=frontend, + test_flags=test_flags, + fn_tree=fn_tree, + on_device=on_device, + M=m, + ) + + # blackman @handle_frontend_test( fn_tree="jax.numpy.blackman", diff --git a/ivy_tests/test_ivy/test_frontends/test_jax/test_numpy/test_mathematical_functions.py b/ivy_tests/test_ivy/test_frontends/test_jax/test_numpy/test_mathematical_functions.py index 3b4fa7d8b941d..402c3a7f6a3be 100644 --- a/ivy_tests/test_ivy/test_frontends/test_jax/test_numpy/test_mathematical_functions.py +++ b/ivy_tests/test_ivy/test_frontends/test_jax/test_numpy/test_mathematical_functions.py @@ -896,8 +896,7 @@ def test_jax_diff( axis, ): input_dtype, x = dtype_and_x - if axis > (x[0].ndim - 1): - axis = x[0].ndim - 1 + axis = min(axis, x[0].ndim - 1) helpers.test_frontend_function( input_dtypes=input_dtype, test_flags=test_flags, @@ -1090,7 +1089,7 @@ def test_jax_einsum_path( kw = {} for i, x_ in enumerate(operands): dtype = dtypes[i][0] - kw["x{}".format(i)] = np.array(x_).astype(dtype) + kw[f"x{i}"] = np.array(x_).astype(dtype) test_flags.num_positional_args = len(operands) + 1 ret, ret_gt = helpers.test_frontend_function( input_dtypes=dtypes, @@ -1104,9 +1103,9 @@ def test_jax_einsum_path( **kw, optimize=optimize, ) - len(ret[0]) == len(ret_gt[0]) - all(x == y for x, y in zip(ret[0], ret_gt[0])) - ret[1] == str(ret_gt[1]) + assert len(ret[0]) == len(ret_gt[0]) + assert all(x == y for x, y in zip(ret[0], ret_gt[0])) + assert ret[1] == str(ret_gt[1]) # exp @@ -1508,7 +1507,7 @@ def test_jax_frexp( min_dim_size=1, max_dim_size=3, num_arrays=2, - ).filter(lambda x: all([dtype != "uint64" for dtype in x[0]])), + ).filter(lambda x: all(dtype != "uint64" for dtype in x[0])), test_with_out=st.just(False), ) def test_jax_gcd( diff --git a/ivy_tests/test_ivy/test_frontends/test_jax/test_numpy/test_searching_sorting.py b/ivy_tests/test_ivy/test_frontends/test_jax/test_numpy/test_searching_sorting.py index 13800e80a63d3..36d88e4710ec2 100644 --- a/ivy_tests/test_ivy/test_frontends/test_jax/test_numpy/test_searching_sorting.py +++ b/ivy_tests/test_ivy/test_frontends/test_jax/test_numpy/test_searching_sorting.py @@ -105,6 +105,42 @@ def test_jax_argmax( ) +# argmin +@handle_frontend_test( + fn_tree="jax.numpy.argmin", + dtype_and_x=helpers.dtype_values_axis( + available_dtypes=helpers.get_dtypes("valid"), + force_int_axis=True, + min_num_dims=1, + valid_axis=True, + ), + keepdims=st.booleans(), +) +def test_jax_argmin( + *, + dtype_and_x, + keepdims, + on_device, + fn_tree, + frontend, + backend_fw, + test_flags, +): + input_dtype, x, axis = dtype_and_x + helpers.test_frontend_function( + input_dtypes=input_dtype, + frontend=frontend, + backend_to_test=backend_fw, + test_flags=test_flags, + fn_tree=fn_tree, + on_device=on_device, + a=x[0], + axis=axis, + out=None, + keepdims=keepdims, + ) + + # argsort @handle_frontend_test( fn_tree="jax.numpy.argsort", diff --git a/ivy_tests/test_ivy/test_frontends/test_jax/test_numpy/test_statistical.py b/ivy_tests/test_ivy/test_frontends/test_jax/test_numpy/test_statistical.py index f9d2b610355a5..28d6388d2af2c 100644 --- a/ivy_tests/test_ivy/test_frontends/test_jax/test_numpy/test_statistical.py +++ b/ivy_tests/test_ivy/test_frontends/test_jax/test_numpy/test_statistical.py @@ -5,7 +5,6 @@ # local import ivy -import ivy_tests.test_ivy.test_frontends.test_numpy.helpers as np_frontend_helpers import ivy_tests.test_ivy.helpers as helpers import ivy_tests.test_ivy.test_frontends.test_numpy.helpers as np_helpers from ivy_tests.test_ivy.helpers import handle_frontend_test @@ -106,7 +105,7 @@ def _get_castable_dtypes_values(draw, *, allow_nan=False, use_where=False): helpers.get_castable_dtype(draw(available_dtypes), dtype[0], values[0]) ) if use_where: - where = draw(np_frontend_helpers.where(shape=shape)) + where = draw(np_helpers.where(shape=shape)) return [dtype1], [values], axis, dtype2, where return [dtype1], [values], axis, dtype2 @@ -811,7 +810,7 @@ def test_jax_nancumsum( input_dtypes, x, axis, dtype = dtype_and_x_axis_dtype if ivy.current_backend_str() == "torch": assume(not test_flags.as_variable[0]) - np_frontend_helpers.test_frontend_function( + np_helpers.test_frontend_function( input_dtypes=input_dtypes, backend_to_test=backend_fw, frontend=frontend, @@ -1014,7 +1013,7 @@ def test_jax_nanmin( fn_tree="jax.numpy.nanstd", dtype_and_a=_statistical_dtype_values(function="nanstd"), dtype=helpers.get_dtypes("float", full=False, none=True), - where=np_frontend_helpers.where(), + where=np_helpers.where(), keep_dims=st.booleans(), ) def test_jax_nanstd( @@ -1031,13 +1030,13 @@ def test_jax_nanstd( input_dtypes, a, axis, correction = dtype_and_a if isinstance(axis, tuple): axis = axis[0] - where, input_dtypes, test_flags = np_frontend_helpers.handle_where_and_array_bools( + where, input_dtypes, test_flags = np_helpers.handle_where_and_array_bools( where=where, input_dtype=input_dtypes, test_flags=test_flags, ) assume(np.dtype(dtype[0]) >= np.dtype(input_dtypes[0])) - np_frontend_helpers.test_frontend_function( + np_helpers.test_frontend_function( input_dtypes=input_dtypes, backend_to_test=backend_fw, frontend=frontend, @@ -1124,7 +1123,7 @@ def test_jax_ptp( keep_dims, ): input_dtypes, x, axis, dtype = dtype_and_x_axis_dtype - np_frontend_helpers.test_frontend_function( + np_helpers.test_frontend_function( input_dtypes=input_dtypes, backend_to_test=backend_fw, frontend=frontend, diff --git a/ivy_tests/test_ivy/test_frontends/test_jax/test_random.py b/ivy_tests/test_ivy/test_frontends/test_jax/test_random.py index ab55689f7c711..ed6724403e7cd 100644 --- a/ivy_tests/test_ivy/test_frontends/test_jax/test_random.py +++ b/ivy_tests/test_ivy/test_frontends/test_jax/test_random.py @@ -80,7 +80,7 @@ def get_mean_cov_vector(draw): dtype_mean = draw( helpers.array_values( dtype=input_dtype, - shape=tuple([shared_size]), + shape=(shared_size,), min_value=2, max_value=5, ) @@ -90,7 +90,7 @@ def get_mean_cov_vector(draw): dtype_cov = draw( helpers.array_values( dtype=input_dtype, - shape=tuple([shared_size, shared_size]), + shape=(shared_size, shared_size), min_value=2, max_value=5, ).filter(lambda x: np.linalg.cond(x.tolist()) < 1 / sys.float_info.epsilon) diff --git a/ivy_tests/test_ivy/test_frontends/test_mindspore/test_numpy.py b/ivy_tests/test_ivy/test_frontends/test_mindspore/test_numpy.py index a68b14562c81a..1cad3008612ce 100644 --- a/ivy_tests/test_ivy/test_frontends/test_mindspore/test_numpy.py +++ b/ivy_tests/test_ivy/test_frontends/test_mindspore/test_numpy.py @@ -26,6 +26,7 @@ def test_mindspore_array( dtype_and_a, frontend, + backend_fw, test_flags, fn_tree, on_device, @@ -36,6 +37,7 @@ def test_mindspore_array( helpers.test_frontend_function( input_dtypes=dtype, frontend=frontend, + backend_to_test=backend_fw, test_flags=test_flags, fn_tree=fn_tree, on_device=on_device, diff --git a/ivy_tests/test_ivy/test_frontends/test_mindspore/test_ops/test_function/test_mindspore_nn_func.py b/ivy_tests/test_ivy/test_frontends/test_mindspore/test_ops/test_function/test_mindspore_nn_func.py index f0d1ebd6caf1f..ead7157dcd54b 100644 --- a/ivy_tests/test_ivy/test_frontends/test_mindspore/test_ops/test_function/test_mindspore_nn_func.py +++ b/ivy_tests/test_ivy/test_frontends/test_mindspore/test_ops/test_function/test_mindspore_nn_func.py @@ -18,15 +18,13 @@ def _calculate_same_padding(kernel_size, stride, shape): padding = tuple( - [ - max( - 0, - math.ceil(((shape[i] - 1) * stride[i] + kernel_size[i] - shape[i]) / 2), - ) - for i in range(len(kernel_size)) - ] + max( + 0, + math.ceil(((shape[i] - 1) * stride[i] + kernel_size[i] - shape[i]) / 2), + ) + for i in range(len(kernel_size)) ) - if all([kernel_size[i] / 2 >= padding[i] for i in range(len(kernel_size))]): + if all(kernel_size[i] / 2 >= padding[i] for i in range(len(kernel_size))): if _is_same_padding(padding, stride, kernel_size, shape): return padding return (0, 0) @@ -34,16 +32,12 @@ def _calculate_same_padding(kernel_size, stride, shape): def _is_same_padding(padding, stride, kernel_size, input_shape): output_shape = tuple( - [ - (input_shape[i] + 2 * padding[i] - kernel_size[i]) // stride[i] + 1 - for i in range(len(padding)) - ] + (input_shape[i] + 2 * padding[i] - kernel_size[i]) // stride[i] + 1 + for i in range(len(padding)) ) return all( - [ - output_shape[i] == math.ceil(input_shape[i] / stride[i]) - for i in range(len(padding)) - ] + output_shape[i] == math.ceil(input_shape[i] / stride[i]) + for i in range(len(padding)) ) @@ -189,6 +183,7 @@ def test_mindspore_adaptive_avg_pool2d( output_size, test_flags, frontend, + backend_fw, on_device, fn_tree, ): @@ -196,6 +191,7 @@ def test_mindspore_adaptive_avg_pool2d( helpers.test_frontend_function( input_dtypes=input_dtype, frontend=frontend, + backend_to_test=backend_fw, test_flags=test_flags, on_device=on_device, fn_tree=fn_tree, @@ -360,6 +356,40 @@ def test_mindspore_conv3d( ) +# dropout +@pytest.mark.skip("Testing pipeline not yet implemented") +@handle_frontend_test( + fn_tree="mindspore.ops.function.nn_func.dropout", + d_type_and_x=helpers.dtype_and_values(), + p=helpers.floats(min_value=0.0, max_value=1.0), + training=st.booleans(), + seed=helpers.ints(min_value=0, max_value=100), +) +def test_mindspore_dropout( + *, + d_type_and_x, + p, + training, + seed, + on_device, + fn_tree, + frontend, + test_flags, +): + dtype, x = d_type_and_x + ret, frontend_ret = helpers.test_frontend_function( + input_dtypes=dtype, + frontend=frontend, + test_flags=test_flags, + fn_tree=fn_tree, + on_device=on_device, + input=x[0], + p=p, + training=training, + seed=seed, + ) + + # dropout2d @pytest.mark.skip("Testing pipeline not yet implemented") @handle_frontend_test( @@ -389,12 +419,14 @@ def test_mindspore_dropout2d( on_device, fn_tree, frontend, + backend_fw, test_flags, ): dtype, x = d_type_and_x helpers.test_frontend_function( input_dtypes=dtype, frontend=frontend, + backend_to_test=backend_fw, test_flags=test_flags, fn_tree=fn_tree, on_device=on_device, @@ -433,12 +465,14 @@ def test_mindspore_dropout3d( on_device, fn_tree, frontend, + backend_fw, test_flags, ): dtype, x = d_type_and_x helpers.test_frontend_function( input_dtypes=dtype, frontend=frontend, + backend_to_test=backend_fw, test_flags=test_flags, fn_tree=fn_tree, on_device=on_device, @@ -461,6 +495,7 @@ def test_mindspore_fast_gelu( *, test_flags, frontend, + backend_fw, on_device, fn_tree, ): @@ -469,6 +504,7 @@ def test_mindspore_fast_gelu( helpers.test_frontend_function( input_dtypes=input_dtype, frontend=frontend, + backend_to_test=backend_fw, test_flags=test_flags, fn_tree=fn_tree, on_device=on_device, @@ -551,6 +587,7 @@ def test_mindspore_interpolate( align_corners, recompute_scale_factor, on_device, + backend_fw, fn_tree, frontend, test_flags, @@ -562,6 +599,7 @@ def test_mindspore_interpolate( helpers.test_frontend_function( input_dtypes=dtype, frontend=frontend, + backend_to_test=backend_fw, test_flags=test_flags, fn_tree=fn_tree, on_device=on_device, @@ -604,11 +642,13 @@ def test_mindspore_kl_div( on_device, fn_tree, frontend, + backend_fw, test_flags, ): helpers.test_frontend_function( input_dtypes=p[0], frontend=frontend, + backend_to_test=backend_fw, test_flags=test_flags, fn_tree=fn_tree, on_device=on_device, @@ -740,11 +780,13 @@ def test_mindspore_pad( on_device, fn_tree, frontend, + backend_fw, test_flags, ): helpers.test_frontend_function( input_dtypes=input[0], frontend=frontend, + backend_to_test=backend_fw, test_flags=test_flags, fn_tree=fn_tree, on_device=on_device, @@ -771,12 +813,14 @@ def test_mindspore_selu( on_device, fn_tree, frontend, + backend_fw, test_flags, ): input_dtype, x = dtype_and_x helpers.test_frontend_function( input_dtypes=input_dtype, frontend=frontend, + backend_to_test=backend_fw, test_flags=test_flags, fn_tree=fn_tree, on_device=on_device, diff --git a/ivy_tests/test_ivy/test_frontends/test_mindspore/test_ops/test_mindspore_nn_func.py b/ivy_tests/test_ivy/test_frontends/test_mindspore/test_ops/test_mindspore_nn_func.py index 555b62c8665b6..e0fc11644ad71 100644 --- a/ivy_tests/test_ivy/test_frontends/test_mindspore/test_ops/test_mindspore_nn_func.py +++ b/ivy_tests/test_ivy/test_frontends/test_mindspore/test_ops/test_mindspore_nn_func.py @@ -22,12 +22,14 @@ def test_mindspore_softsign( on_device, fn_tree, frontend, + backend_fw, test_flags, ): input_dtype, x = dtype_and_x helpers.test_frontend_function( input_dtypes=input_dtype, frontend=frontend, + backend_to_test=backend_fw, test_flags=test_flags, fn_tree=fn_tree, on_device=on_device, diff --git a/ivy_tests/test_ivy/test_frontends/test_numpy/__init__.py b/ivy_tests/test_ivy/test_frontends/test_numpy/__init__.py index 57785e80fa6bb..6ede0631199e7 100644 --- a/ivy_tests/test_ivy/test_frontends/test_numpy/__init__.py +++ b/ivy_tests/test_ivy/test_frontends/test_numpy/__init__.py @@ -6,7 +6,8 @@ def convnumpy(argument): - """Convert NativeClass in argument to ivy frontend counterpart for numpy.""" + """Convert NativeClass in argument to ivy frontend counterpart for + numpy.""" if isinstance(argument, NativeClass): return numpy_classes_to_ivy_classes.get(argument._native_class) return argument diff --git a/ivy_tests/test_ivy/test_frontends/test_numpy/helpers.py b/ivy_tests/test_ivy/test_frontends/test_numpy/helpers.py index b4c5650786cef..d7287dc70ec57 100644 --- a/ivy_tests/test_ivy/test_frontends/test_numpy/helpers.py +++ b/ivy_tests/test_ivy/test_frontends/test_numpy/helpers.py @@ -27,8 +27,8 @@ def _array_and_axes_permute_helper( max_dim_size, allow_none=False, ): - """ - Return array, its dtype and either the random permutation of its axes or None. + """Return array, its dtype and either the random permutation of its axes or + None. Parameters ---------- @@ -43,6 +43,7 @@ def _array_and_axes_permute_helper( minimum size of the dimension max_dim_size maximum size of the dimension + Returns ------- A strategy that draws an array, its dtype and axes (or None). @@ -86,7 +87,7 @@ def _flatten_frontend_return(*, ret, backend): else: ret_np_flat = _flatten_fw_return(ret=ret, backend=backend) else: - if any([not ivy_backend.is_ivy_array(x) for x in ret]): + if any(not ivy_backend.is_ivy_array(x) for x in ret): ret_np_flat = helpers.flatten_frontend_to_np(backend=backend, ret=ret) else: ret_np_flat = _flatten_fw_return(ret=ret, backend=backend) @@ -222,11 +223,11 @@ def _test_frontend_function_ignoring_uninitialized(*args, **kwargs): frontend_ret_flat = [ np.where(where, x, np.zeros_like(x)) for x in frontend_ret_np_flat ] - if "rtol" in kwargs.keys(): + if "rtol" in kwargs: rtol = kwargs["rtol"] else: rtol = 1e-4 - if "atol" in kwargs.keys(): + if "atol" in kwargs: atol = kwargs["atol"] else: atol = 1e-6 @@ -275,9 +276,8 @@ def dtypes_values_casting_dtype( # ufunc num_positional_args helper @st.composite def get_num_positional_args_ufunc(draw, *, fn_name=None): - """ - Draws data randomly from numbers between nin and nargs where nin and nargs are - properties of the given ufunc. + """Draws data randomly from numbers between nin and nargs where nin and + nargs are properties of the given ufunc. Parameters ---------- diff --git a/ivy_tests/test_ivy/test_frontends/test_numpy/test_fft/test_discrete_fourier_transform.py b/ivy_tests/test_ivy/test_frontends/test_numpy/test_fft/test_discrete_fourier_transform.py index 26506d7008684..b17dc06b34bfd 100644 --- a/ivy_tests/test_ivy/test_frontends/test_numpy/test_fft/test_discrete_fourier_transform.py +++ b/ivy_tests/test_ivy/test_frontends/test_numpy/test_fft/test_discrete_fourier_transform.py @@ -62,6 +62,53 @@ def test_numpy_fftfreq( ) +@handle_frontend_test( + fn_tree="numpy.fft.fftn", + dtype_values=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), + min_value=-1e5, + max_value=1e5, + min_num_dims=2, + max_num_dims=3, + min_dim_size=2, + max_dim_size=3, + large_abs_safety_factor=10, + small_abs_safety_factor=10, + safety_factor_scale="log", + ), + axes=st.sampled_from([(0, 1), (-1, -2), (1, 0), None]), + s=st.tuples( + st.integers(min_value=2, max_value=256), st.integers(min_value=2, max_value=256) + ) + | st.none(), + norm=st.sampled_from(["backward", "ortho", "forward", None]), +) +def test_numpy_fftn( + dtype_values, + s, + axes, + norm, + frontend, + backend_fw, + test_flags, + fn_tree, + on_device, +): + dtype, values = dtype_values + helpers.test_frontend_function( + input_dtypes=dtype, + frontend=frontend, + backend_to_test=backend_fw, + test_flags=test_flags, + fn_tree=fn_tree, + on_device=on_device, + a=values[0], + s=s, + axes=axes, + norm=norm, + ) + + @handle_frontend_test( fn_tree="numpy.fft.fftshift", dtype_and_x=helpers.dtype_and_values( diff --git a/ivy_tests/test_ivy/test_frontends/test_numpy/test_func_wrapper.py b/ivy_tests/test_ivy/test_frontends/test_numpy/test_func_wrapper.py index 0df77d4cac224..d93895355b185 100644 --- a/ivy_tests/test_ivy/test_frontends/test_numpy/test_func_wrapper.py +++ b/ivy_tests/test_ivy/test_frontends/test_numpy/test_func_wrapper.py @@ -46,7 +46,7 @@ def _dtype_helper(draw): def _fn(*args, check_default=False, dtype=None): if ( check_default - and any([not (ivy.is_array(i) or hasattr(i, "ivy_array")) for i in args]) + and any(not (ivy.is_array(i) or hasattr(i, "ivy_array")) for i in args) and not ivy.exists(dtype) ): ivy.utils.assertions.check_equal( diff --git a/ivy_tests/test_ivy/test_frontends/test_numpy/test_indexing_routines/test_indexing_like_operations.py b/ivy_tests/test_ivy/test_frontends/test_numpy/test_indexing_routines/test_indexing_like_operations.py index 8a03463674b6e..463bf32a3a750 100644 --- a/ivy_tests/test_ivy/test_frontends/test_numpy/test_indexing_routines/test_indexing_like_operations.py +++ b/ivy_tests/test_ivy/test_frontends/test_numpy/test_indexing_routines/test_indexing_like_operations.py @@ -150,6 +150,45 @@ def test_numpy_put_along_axis( ) +@handle_frontend_test( + fn_tree="numpy.take", + dtype_x_indices_axis=helpers.array_indices_axis( + array_dtypes=helpers.get_dtypes("valid"), + indices_dtypes=["int32", "int64"], + min_num_dims=1, + max_num_dims=3, + min_dim_size=1, + max_dim_size=5, + indices_same_dims=True, + valid_bounds=False, + ), + mode=st.sampled_from(["clip", "wrap"]), +) +def test_numpy_take( + *, + dtype_x_indices_axis, + mode, + test_flags, + frontend, + backend_fw, + fn_tree, + on_device, +): + dtypes, x, indices, axis, _ = dtype_x_indices_axis + helpers.test_frontend_function( + input_dtypes=dtypes, + backend_to_test=backend_fw, + test_flags=test_flags, + frontend=frontend, + fn_tree=fn_tree, + on_device=on_device, + a=x, + indices=indices, + axis=axis, + mode=mode, + ) + + @handle_frontend_test( fn_tree="numpy.take_along_axis", dtype_x_indices_axis=helpers.array_indices_axis( diff --git a/ivy_tests/test_ivy/test_frontends/test_numpy/test_indexing_routines/test_inserting_data_into_arrays.py b/ivy_tests/test_ivy/test_frontends/test_numpy/test_indexing_routines/test_inserting_data_into_arrays.py index 186794403dc41..a03cc96ee21a4 100644 --- a/ivy_tests/test_ivy/test_frontends/test_numpy/test_indexing_routines/test_inserting_data_into_arrays.py +++ b/ivy_tests/test_ivy/test_frontends/test_numpy/test_indexing_routines/test_inserting_data_into_arrays.py @@ -51,8 +51,7 @@ def _helper_r_(draw): to_mat = draw(st.booleans()) if to_mat: elem = draw(st.sampled_from(["c", "r"])) - if dim > 2: - dim = 2 + dim = min(dim, 2) else: num = draw(st.integers(1, 3)) elem = "" diff --git a/ivy_tests/test_ivy/test_frontends/test_numpy/test_linalg/test_decompositions.py b/ivy_tests/test_ivy/test_frontends/test_numpy/test_linalg/test_decompositions.py index fee1e0e77c29e..f740b7278dacb 100644 --- a/ivy_tests/test_ivy/test_frontends/test_numpy/test_linalg/test_decompositions.py +++ b/ivy_tests/test_ivy/test_frontends/test_numpy/test_linalg/test_decompositions.py @@ -18,7 +18,7 @@ available_dtypes=helpers.get_dtypes("float"), min_value=0, max_value=10, - shape=helpers.ints(min_value=2, max_value=5).map(lambda x: tuple([x, x])), + shape=helpers.ints(min_value=2, max_value=5).map(lambda x: (x, x)), ).filter( lambda x: np.linalg.cond(x[1][0]) < 1 / sys.float_info.epsilon and np.linalg.det(x[1][0]) != 0 @@ -87,7 +87,7 @@ def test_numpy_qr( available_dtypes=helpers.get_dtypes("float"), min_value=0.1, max_value=10, - shape=helpers.ints(min_value=2, max_value=5).map(lambda x: tuple([x, x])), + shape=helpers.ints(min_value=2, max_value=5).map(lambda x: (x, x)), ), full_matrices=st.booleans(), compute_uv=st.booleans(), diff --git a/ivy_tests/test_ivy/test_frontends/test_numpy/test_linalg/test_matrix_and_vector_products.py b/ivy_tests/test_ivy/test_frontends/test_numpy/test_linalg/test_matrix_and_vector_products.py index 164f698ad8c29..e72396bb1f976 100644 --- a/ivy_tests/test_ivy/test_frontends/test_numpy/test_linalg/test_matrix_and_vector_products.py +++ b/ivy_tests/test_ivy/test_frontends/test_numpy/test_linalg/test_matrix_and_vector_products.py @@ -324,7 +324,7 @@ def test_numpy_matmul( available_dtypes=helpers.get_dtypes("float"), min_value=0, max_value=50, - shape=helpers.ints(min_value=2, max_value=8).map(lambda x: tuple([x, x])), + shape=helpers.ints(min_value=2, max_value=8).map(lambda x: (x, x)), ), n=helpers.ints(min_value=1, max_value=8), test_with_out=st.just(False), diff --git a/ivy_tests/test_ivy/test_frontends/test_numpy/test_linalg/test_matrix_eigenvalues.py b/ivy_tests/test_ivy/test_frontends/test_numpy/test_linalg/test_matrix_eigenvalues.py index b76655cf0897d..498c71af9b446 100644 --- a/ivy_tests/test_ivy/test_frontends/test_numpy/test_linalg/test_matrix_eigenvalues.py +++ b/ivy_tests/test_ivy/test_frontends/test_numpy/test_linalg/test_matrix_eigenvalues.py @@ -22,7 +22,7 @@ available_dtypes=helpers.get_dtypes("float"), min_value=0, max_value=10, - shape=helpers.ints(min_value=2, max_value=5).map(lambda x: tuple([x, x])), + shape=helpers.ints(min_value=2, max_value=5).map(lambda x: (x, x)), ).filter( lambda x: "float16" not in x[0] and "bfloat16" not in x[0] @@ -41,8 +41,8 @@ def test_numpy_eig( ): dtype, x = dtype_and_x x = np.array(x[0], dtype=dtype[0]) - """Make symmetric positive-definite since ivy does not support complex data dtypes - currently.""" + """Make symmetric positive-definite since ivy does not support complex data + dtypes currently.""" x = np.matmul(x.T, x) + np.identity(x.shape[0]) * 1e-3 ret, frontend_ret = helpers.test_frontend_function( @@ -79,7 +79,7 @@ def test_numpy_eig( available_dtypes=helpers.get_dtypes("float"), min_value=0, max_value=10, - shape=helpers.ints(min_value=2, max_value=5).map(lambda x: tuple([x, x])), + shape=helpers.ints(min_value=2, max_value=5).map(lambda x: (x, x)), ).filter( lambda x: "float16" not in x[0] and "bfloat16" not in x[0] @@ -136,7 +136,7 @@ def test_numpy_eigh( available_dtypes=helpers.get_dtypes("float"), min_value=0, max_value=10, - shape=helpers.ints(min_value=2, max_value=4).map(lambda x: tuple([x, x])), + shape=helpers.ints(min_value=2, max_value=4).map(lambda x: (x, x)), ).filter( lambda x: "float16" not in x[0] and "bfloat16" not in x[0] diff --git a/ivy_tests/test_ivy/test_frontends/test_numpy/test_linalg/test_solving_equations_and_inverting_matrices.py b/ivy_tests/test_ivy/test_frontends/test_numpy/test_linalg/test_solving_equations_and_inverting_matrices.py index 4ea7804d3d06b..3a12867c31bef 100644 --- a/ivy_tests/test_ivy/test_frontends/test_numpy/test_linalg/test_solving_equations_and_inverting_matrices.py +++ b/ivy_tests/test_ivy/test_frontends/test_numpy/test_linalg/test_solving_equations_and_inverting_matrices.py @@ -67,7 +67,7 @@ def _get_inv_square_matrices(draw): available_dtypes=helpers.get_dtypes("float"), small_abs_safety_factor=2, safety_factor_scale="log", - shape=helpers.ints(min_value=2, max_value=20).map(lambda x: tuple([x, x])), + shape=helpers.ints(min_value=2, max_value=20).map(lambda x: (x, x)), ).filter(lambda x: np.linalg.cond(x[1][0].tolist()) < 1 / sys.float_info.epsilon), test_with_out=st.just(False), ) diff --git a/ivy_tests/test_ivy/test_frontends/test_numpy/test_logic/test_array_contents.py b/ivy_tests/test_ivy/test_frontends/test_numpy/test_logic/test_array_contents.py index 56447b9024f47..99a41881c4b3d 100644 --- a/ivy_tests/test_ivy/test_frontends/test_numpy/test_logic/test_array_contents.py +++ b/ivy_tests/test_ivy/test_frontends/test_numpy/test_logic/test_array_contents.py @@ -7,6 +7,25 @@ from ivy_tests.test_ivy.helpers import handle_frontend_test +# --- Helpers --- # +# --------------- # + + +# isin +@st.composite +def _isin_data_generation_helper(draw): + dtype_and_x = helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), + num_arrays=2, + shared_dtype=True, + ) + return draw(dtype_and_x) + + +# --- Main --- # +# ------------ # + + @handle_frontend_test( fn_tree="numpy.allclose", dtype_and_x=helpers.dtype_and_values( @@ -75,6 +94,38 @@ def test_numpy_isclose( ) +# isin +@handle_frontend_test( + fn_tree="numpy.isin", + assume_unique_and_dtype_and_x=_isin_data_generation_helper(), + invert=st.booleans(), +) +def test_numpy_isin( + *, + assume_unique_and_dtype_and_x, + invert, + on_device, + fn_tree, + frontend, + test_flags, + backend_fw, +): + x_and_dtype = assume_unique_and_dtype_and_x + dtypes, values = x_and_dtype + elements, test_elements = values + helpers.test_frontend_function( + input_dtypes=dtypes, + frontend=frontend, + test_flags=test_flags, + fn_tree=fn_tree, + on_device=on_device, + element=elements, + test_elements=test_elements, + invert=invert, + backend_to_test=backend_fw, + ) + + @handle_frontend_test( fn_tree="numpy.isneginf", dtype_and_x=helpers.dtype_and_values( diff --git a/ivy_tests/test_ivy/test_frontends/test_numpy/test_manipulation_routines/test_joining_arrays.py b/ivy_tests/test_ivy/test_frontends/test_numpy/test_manipulation_routines/test_joining_arrays.py index 3102a5f40bc25..f4164ca35b473 100644 --- a/ivy_tests/test_ivy/test_frontends/test_numpy/test_manipulation_routines/test_joining_arrays.py +++ b/ivy_tests/test_ivy/test_frontends/test_numpy/test_manipulation_routines/test_joining_arrays.py @@ -41,6 +41,38 @@ def _arrays_idx_n_dtypes(draw): # ------------ # +# column_stack +@handle_frontend_test( + fn_tree="numpy.column_stack", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), + shared_dtype=True, + num_arrays=helpers.ints(min_value=2, max_value=10), + shape=helpers.get_shape( + min_num_dims=1, + ), + ), +) +def test_numpy_column_stack( + dtype_and_x, + frontend, + test_flags, + fn_tree, + backend_fw, + on_device, +): + input_dtype, xs = dtype_and_x + helpers.test_frontend_function( + input_dtypes=input_dtype, + backend_to_test=backend_fw, + frontend=frontend, + test_flags=test_flags, + fn_tree=fn_tree, + on_device=on_device, + tup=xs, + ) + + # concat @handle_frontend_test( fn_tree="numpy.concatenate", diff --git a/ivy_tests/test_ivy/test_frontends/test_numpy/test_manipulation_routines/test_padding_arrays.py b/ivy_tests/test_ivy/test_frontends/test_numpy/test_manipulation_routines/test_padding_arrays.py index 2fa46f5db1cf2..8fe30ac7ca58f 100644 --- a/ivy_tests/test_ivy/test_frontends/test_numpy/test_manipulation_routines/test_padding_arrays.py +++ b/ivy_tests/test_ivy/test_frontends/test_numpy/test_manipulation_routines/test_padding_arrays.py @@ -46,7 +46,7 @@ def _pad_helper(draw): ndim = len(shape) pad_width = draw(_st_tuples_or_int(ndim, min_val=0)) kwargs = {} - if mode == "reflect" or mode == "symmetric": + if mode in ["reflect", "symmetric"]: kwargs["reflect_type"] = draw(st.sampled_from(["even", "odd"])) if mode in ["maximum", "mean", "median", "minimum"]: kwargs["stat_length"] = draw(_st_tuples_or_int(ndim, min_val=2)) diff --git a/ivy_tests/test_ivy/test_frontends/test_numpy/test_mathematical_functions/test_extrema_finding.py b/ivy_tests/test_ivy/test_frontends/test_numpy/test_mathematical_functions/test_extrema_finding.py index 2d5f59ff7b45e..3ae405d89f393 100644 --- a/ivy_tests/test_ivy/test_frontends/test_numpy/test_mathematical_functions/test_extrema_finding.py +++ b/ivy_tests/test_ivy/test_frontends/test_numpy/test_mathematical_functions/test_extrema_finding.py @@ -202,6 +202,54 @@ def test_numpy_fmin( ) +@handle_frontend_test( + fn_tree="numpy.max", + dtype_x_axis=helpers.dtype_values_axis( + available_dtypes=helpers.get_dtypes("float"), + min_num_dims=1, + valid_axis=True, + force_int_axis=True, + large_abs_safety_factor=2, + safety_factor_scale="log", + ), + initial=st.one_of(st.floats(min_value=-1000, max_value=1000), st.none()), + keepdims=st.booleans(), + where=np_frontend_helpers.where(), +) +def test_numpy_max( + dtype_x_axis, + frontend, + test_flags, + fn_tree, + backend_fw, + on_device, + where, + initial, + keepdims, +): + if initial is None and np.all(where) is not True: + assume(initial is +inf) + input_dtypes, x, axis = dtype_x_axis + where, input_dtypes, test_flags = np_frontend_helpers.handle_where_and_array_bools( + where=where, + input_dtype=input_dtypes, + test_flags=test_flags, + ) + np_frontend_helpers.test_frontend_function( + input_dtypes=input_dtypes, + backend_to_test=backend_fw, + frontend=frontend, + test_flags=test_flags, + fn_tree=fn_tree, + on_device=on_device, + a=x[0], + axis=axis, + keepdims=keepdims, + initial=initial, + where=where, + ) + + # maximum @handle_frontend_test( fn_tree="numpy.maximum", @@ -252,6 +300,55 @@ def test_numpy_maximum( ) +@handle_frontend_test( + fn_tree="numpy.min", + dtype_x_axis=helpers.dtype_values_axis( + available_dtypes=helpers.get_dtypes("float"), + min_num_dims=1, + valid_axis=True, + force_int_axis=True, + large_abs_safety_factor=2, + safety_factor_scale="log", + ), + initial=st.one_of(st.floats(min_value=-1000, max_value=1000), st.none()), + keepdims=st.booleans(), + where=np_frontend_helpers.where(), +) +def test_numpy_min( + dtype_x_axis, + frontend, + test_flags, + fn_tree, + backend_fw, + on_device, + where, + initial, + keepdims, +): + if initial is None and np.all(where) is not True: + assume(initial is inf) + + input_dtypes, x, axis = dtype_x_axis + where, input_dtypes, test_flags = np_frontend_helpers.handle_where_and_array_bools( + where=where, + input_dtype=input_dtypes, + test_flags=test_flags, + ) + np_frontend_helpers.test_frontend_function( + input_dtypes=input_dtypes, + backend_to_test=backend_fw, + frontend=frontend, + test_flags=test_flags, + fn_tree=fn_tree, + on_device=on_device, + a=x[0], + axis=axis, + keepdims=keepdims, + initial=initial, + where=where, + ) + + # minimum @handle_frontend_test( fn_tree="numpy.minimum", diff --git a/ivy_tests/test_ivy/test_frontends/test_numpy/test_mathematical_functions/test_floating_point_routines.py b/ivy_tests/test_ivy/test_frontends/test_numpy/test_mathematical_functions/test_floating_point_routines.py index 54924a62fb272..0e108cd4754df 100644 --- a/ivy_tests/test_ivy/test_frontends/test_numpy/test_mathematical_functions/test_floating_point_routines.py +++ b/ivy_tests/test_ivy/test_frontends/test_numpy/test_mathematical_functions/test_floating_point_routines.py @@ -54,6 +54,54 @@ def test_numpy_nextafter( ) +# signbit +@handle_frontend_test( + fn_tree="numpy.signbit", + dtypes_values_casting=np_frontend_helpers.dtypes_values_casting_dtype( + arr_func=[ + lambda: helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), + shared_dtype=True, + ) + ], + ), + where=np_frontend_helpers.where(), + number_positional_args=np_frontend_helpers.get_num_positional_args_ufunc( + fn_name="signbit" + ), +) +def test_numpy_signbit( + dtypes_values_casting, + where, + frontend, + test_flags, + backend_fw, + fn_tree, + on_device, +): + input_dtypes, xs, casting, dtype = dtypes_values_casting + where, input_dtypes, test_flags = np_frontend_helpers.handle_where_and_array_bools( + where=where, + input_dtype=input_dtypes, + test_flags=test_flags, + ) + np_frontend_helpers.test_frontend_function( + input_dtypes=input_dtypes, + frontend=frontend, + test_flags=test_flags, + backend_to_test=backend_fw, + fn_tree=fn_tree, + on_device=on_device, + x=xs[0], + out=None, + where=where, + casting="safe", + order="K", + dtype=dtype, + subok=True, + ) + + # spacing @handle_frontend_test( fn_tree="numpy.spacing", diff --git a/ivy_tests/test_ivy/test_frontends/test_numpy/test_mathematical_functions/test_sums_products_differences.py b/ivy_tests/test_ivy/test_frontends/test_numpy/test_mathematical_functions/test_sums_products_differences.py index 76686c58f938d..548b02bbf5dd0 100644 --- a/ivy_tests/test_ivy/test_frontends/test_numpy/test_mathematical_functions/test_sums_products_differences.py +++ b/ivy_tests/test_ivy/test_frontends/test_numpy/test_mathematical_functions/test_sums_products_differences.py @@ -19,7 +19,7 @@ def _either_x_dx(draw): if rand == 0: either_x_dx = draw( helpers.dtype_and_values( - avaliable_dtypes=st.shared( + available_dtypes=st.shared( helpers.get_dtypes("float"), key="trapz_dtype" ), min_value=-100, diff --git a/ivy_tests/test_ivy/test_frontends/test_numpy/test_ndarray/test_ndarray.py b/ivy_tests/test_ivy/test_frontends/test_numpy/test_ndarray/test_ndarray.py index 303078151fede..6404b98dade7f 100644 --- a/ivy_tests/test_ivy/test_frontends/test_numpy/test_ndarray/test_ndarray.py +++ b/ivy_tests/test_ivy/test_frontends/test_numpy/test_ndarray/test_ndarray.py @@ -2703,6 +2703,7 @@ def test_numpy_instance_ilshift__( init_all_as_kwargs_np={ "object": x[0], }, + method_input_dtypes=input_dtypes, backend_to_test=backend_fw, method_all_as_kwargs_np={ "value": x[1], @@ -3544,12 +3545,14 @@ def test_numpy_sum( if ivy.current_backend_str() == "torch": assume(not method_flags.as_variable[0]) - where, input_dtypes, method_flags = ( - np_frontend_helpers.handle_where_and_array_bools( - where=where, - input_dtype=input_dtypes, - test_flags=method_flags, - ) + ( + where, + input_dtypes, + method_flags, + ) = np_frontend_helpers.handle_where_and_array_bools( + where=where, + input_dtype=input_dtypes, + test_flags=method_flags, ) where = ivy.array(where, dtype="bool") helpers.test_frontend_method( @@ -3710,6 +3713,53 @@ def test_numpy_tolist( ) +# trace +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="numpy.array", + method_name="trace", + dtype_x_axis=helpers.dtype_values_axis( + available_dtypes=helpers.get_dtypes("numeric"), + min_num_dims=2, + min_axes_size=2, + max_axes_size=2, + valid_axis=True, + ), + offset=st.integers(min_value=-2, max_value=2), +) +def test_numpy_trace( + dtype_x_axis, + offset, + frontend_method_data, + init_flags, + method_flags, + backend_fw, + frontend, + on_device, +): + input_dtypes, x, axis = dtype_x_axis + + helpers.test_frontend_method( + init_input_dtypes=input_dtypes, + backend_to_test=backend_fw, + init_all_as_kwargs_np={ + "object": x[0], + }, + method_input_dtypes=input_dtypes, + method_all_as_kwargs_np={ + "axis1": axis[0], + "axis2": axis[1], + "offset": offset, + "out": None, + }, + frontend=frontend, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + on_device=on_device, + ) + + @handle_frontend_method( class_tree=CLASS_TREE, init_tree="numpy.array", diff --git a/ivy_tests/test_ivy/test_frontends/test_numpy/test_statistics/test_correlating.py b/ivy_tests/test_ivy/test_frontends/test_numpy/test_statistics/test_correlating.py index ee73f44e8a3d6..055ec7ace5b72 100644 --- a/ivy_tests/test_ivy/test_frontends/test_numpy/test_statistics/test_correlating.py +++ b/ivy_tests/test_ivy/test_frontends/test_numpy/test_statistics/test_correlating.py @@ -83,7 +83,8 @@ def test_numpy_correlate( test_flags=test_flags, fn_tree=fn_tree, on_device=on_device, - rtol=1e-2, + rtol=1e-3, + atol=1e-3, a=xs[0], v=xs[1], mode=mode, diff --git a/ivy_tests/test_ivy/test_frontends/test_onnx/test_elementwise.py b/ivy_tests/test_ivy/test_frontends/test_onnx/test_elementwise.py index 50cf23e71c94d..0f997b69770f1 100644 --- a/ivy_tests/test_ivy/test_frontends/test_onnx/test_elementwise.py +++ b/ivy_tests/test_ivy/test_frontends/test_onnx/test_elementwise.py @@ -28,12 +28,14 @@ def test_onnx_abs( on_device, fn_tree, frontend, + backend_fw, test_flags, ): input_dtype, x = dtype_and_x helpers.test_frontend_function( input_dtypes=input_dtype, frontend=frontend, + backend_to_test=backend_fw, test_flags=test_flags, fn_tree=fn_tree, on_device=on_device, @@ -81,10 +83,12 @@ def test_onnx_acos( on_device, fn_tree, frontend, + backend_fw, test_flags, ): input_dtype, x = dtype_and_x helpers.test_frontend_function( + backend_to_test=backend_fw, input_dtypes=input_dtype, frontend=frontend, test_flags=test_flags, @@ -131,10 +135,12 @@ def test_onnx_acosh( on_device, fn_tree, frontend, + backend_fw, test_flags, ): input_dtype, x = dtype_and_x helpers.test_frontend_function( + backend_to_test=backend_fw, input_dtypes=input_dtype, frontend=frontend, test_flags=test_flags, @@ -187,12 +193,14 @@ def test_onnx_add( on_device, fn_tree, frontend, + backend_fw, test_flags, ): input_dtype, x = dtype_and_x helpers.test_frontend_function( input_dtypes=input_dtype, frontend=frontend, + backend_to_test=backend_fw, test_flags=test_flags, fn_tree=fn_tree, on_device=on_device, @@ -246,12 +254,14 @@ def test_onnx_asin( on_device, fn_tree, frontend, + backend_fw, test_flags, ): input_dtype, x = dtype_and_x helpers.test_frontend_function( input_dtypes=input_dtype, frontend=frontend, + backend_to_test=backend_fw, test_flags=test_flags, fn_tree=fn_tree, on_device=on_device, diff --git a/ivy_tests/test_ivy/test_frontends/test_paddle/__init__.py b/ivy_tests/test_ivy/test_frontends/test_paddle/__init__.py index a2500afb3e86a..5b086cc0e5096 100644 --- a/ivy_tests/test_ivy/test_frontends/test_paddle/__init__.py +++ b/ivy_tests/test_ivy/test_frontends/test_paddle/__init__.py @@ -6,7 +6,8 @@ def convpaddle(argument): - """Convert NativeClass in argument to ivy frontend counter part for paddle.""" + """Convert NativeClass in argument to ivy frontend counter part for + paddle.""" if isinstance(argument, NativeClass): return paddle_classes_to_ivy_classes.get(argument._native_class) return argument diff --git a/ivy_tests/test_ivy/test_frontends/test_paddle/test_fft.py b/ivy_tests/test_ivy/test_frontends/test_paddle/test_fft.py index c49ea38dd9aae..125e5d0857eb2 100644 --- a/ivy_tests/test_ivy/test_frontends/test_paddle/test_fft.py +++ b/ivy_tests/test_ivy/test_frontends/test_paddle/test_fft.py @@ -4,6 +4,9 @@ # local import ivy_tests.test_ivy.helpers as helpers from ivy_tests.test_ivy.helpers import handle_frontend_test +from ivy_tests.test_ivy.test_functional.test_experimental.test_nn.test_layers import ( + _x_and_ifftn, +) # Custom Hypothesis strategy for generating sequences of 2 integers @@ -51,6 +54,54 @@ def test_paddle_fft( ) +@handle_frontend_test( + fn_tree="paddle.fft.fft2", + dtypes_x_axis=helpers.dtype_values_axis( + available_dtypes=helpers.get_dtypes("valid"), + min_value=-10, + max_value=10, + min_num_dims=2, + min_dim_size=2, + valid_axis=True, + force_int_axis=True, + ), + s=st.one_of( + st.none(), + st.lists(st.integers(min_value=2, max_value=10), min_size=2, max_size=2), + ), + axes=st.one_of( + st.none(), + st.tuples( + st.integers(min_value=-2, max_value=2), + st.integers(min_value=-1, max_value=2), + ), + ), + norm=st.sampled_from(["backward", "ortho", "forward"]), +) +def test_paddle_fft2( + dtypes_x_axis, + s, + axes, + norm, + frontend, + backend_fw, + test_flags, + fn_tree, +): + input_dtypes, x, _ = dtypes_x_axis + helpers.test_frontend_function( + input_dtypes=input_dtypes, + backend_to_test=backend_fw, + frontend=frontend, + test_flags=test_flags, + fn_tree=fn_tree, + x=x[0], + s=s, + axes=axes, + norm=norm, + ) + + @handle_frontend_test( fn_tree="paddle.fft.fftfreq", n=st.integers(min_value=1, max_value=1000), @@ -225,6 +276,32 @@ def test_paddle_ifft( ) +# ifftn +@handle_frontend_test( + fn_tree="paddle.fft.ifftn", + dtype_and_x=_x_and_ifftn(), +) +def test_paddle_ifftn( + dtype_and_x, + frontend, + backend_fw, + test_flags, + fn_tree, +): + dtype, x, s, axes, norm = dtype_and_x + helpers.test_frontend_function( + input_dtypes=dtype, + frontend=frontend, + backend_to_test=backend_fw, + test_flags=test_flags, + fn_tree=fn_tree, + x=x, + s=s, + axes=axes, + norm=norm, + ) + + @handle_frontend_test( fn_tree="paddle.fft.ifftshift", dtype_x_axis=helpers.dtype_values_axis( @@ -302,6 +379,50 @@ def test_paddle_ihfft2( ) +@handle_frontend_test( + fn_tree="paddle.fft.ihfftn", + dtype_x_axis=helpers.dtype_values_axis( + available_dtypes=["float64", "float32", "int64", "int32"], + min_value=-10, + max_value=10, + min_num_dims=2, + max_num_dims=2, + shape=st.tuples( + st.integers(min_value=2, max_value=10), + st.integers(min_value=2, max_value=10), + ), + ), + s=st.one_of( + st.lists(st.integers(min_value=2, max_value=10), min_size=2, max_size=2), + ), + axes=st.just([-2, -1]), + norm=st.sampled_from(["backward", "ortho", "forward"]), +) +def test_paddle_ihfftn( + dtype_x_axis, + s, + axes, + norm, + frontend, + backend_fw, + test_flags, + fn_tree, +): + input_dtypes, x, axis_ = dtype_x_axis + + helpers.test_frontend_function( + input_dtypes=input_dtypes, + frontend=frontend, + backend_to_test=backend_fw, + test_flags=test_flags, + fn_tree=fn_tree, + x=x[0], + s=s, + axes=axes, + norm=norm, + ) + + @handle_frontend_test( fn_tree="paddle.fft.irfft", dtype_x_axis=helpers.dtype_values_axis( diff --git a/ivy_tests/test_ivy/test_frontends/test_paddle/test_linalg.py b/ivy_tests/test_ivy/test_frontends/test_paddle/test_linalg.py index cc3923059d942..a5aa23037461d 100644 --- a/ivy_tests/test_ivy/test_frontends/test_paddle/test_linalg.py +++ b/ivy_tests/test_ivy/test_frontends/test_paddle/test_linalg.py @@ -171,17 +171,6 @@ def _transpose_helper(draw): return dtype, x, perm -@st.composite -def dims_and_offset(draw, shape): - shape_actual = draw(shape) - dim1 = draw(helpers.get_axis(shape=shape, force_int=True)) - dim2 = draw(helpers.get_axis(shape=shape, force_int=True)) - offset = draw( - st.integers(min_value=-shape_actual[dim1], max_value=shape_actual[dim1]) - ) - return dim1, dim2, offset - - # Helpers # # ------ # @@ -333,7 +322,7 @@ def test_paddle_bmm( available_dtypes=helpers.get_dtypes("valid"), min_value=0, max_value=10, - shape=helpers.ints(min_value=2, max_value=5).map(lambda x: tuple([x, x])), + shape=helpers.ints(min_value=2, max_value=5).map(lambda x: (x, x)), ), upper=st.booleans(), ) @@ -569,7 +558,7 @@ def test_paddle_eig( ret = [ivy.to_numpy(x).astype("float64") for x in ret] frontend_ret = [np.asarray(x, dtype=np.float64) for x in frontend_ret] - l, v = ret + l, v = ret # noqa: E741 front_l, front_v = frontend_ret assert_all_close( @@ -619,7 +608,7 @@ def test_paddle_eigh( ret = [ivy.to_numpy(x).astype("float64") for x in ret] frontend_ret = [np.asarray(x, dtype=np.float64) for x in frontend_ret] - l, v = ret + l, v = ret # noqa: E741 front_l, front_v = frontend_ret assert_all_close( @@ -706,7 +695,7 @@ def test_paddle_eigvalsh( available_dtypes=helpers.get_dtypes("valid"), shape=st.shared(helpers.get_shape(min_num_dims=2), key="shape"), ), - axis_and_offset=dims_and_offset( + axis_and_offset=helpers.dims_and_offset( shape=st.shared(helpers.get_shape(min_num_dims=2), key="shape") ), ) @@ -827,7 +816,7 @@ def test_paddle_matmul( available_dtypes=helpers.get_dtypes("float"), min_value=0, max_value=50, - shape=helpers.ints(min_value=2, max_value=8).map(lambda x: tuple([x, x])), + shape=helpers.ints(min_value=2, max_value=8).map(lambda x: (x, x)), ), n=helpers.ints(min_value=1, max_value=8), test_with_out=st.just(False), diff --git a/ivy_tests/test_ivy/test_frontends/test_paddle/test_manipulation.py b/ivy_tests/test_ivy/test_frontends/test_paddle/test_manipulation.py index 413f799ef4d9d..c3515fd426518 100644 --- a/ivy_tests/test_ivy/test_frontends/test_paddle/test_manipulation.py +++ b/ivy_tests/test_ivy/test_frontends/test_paddle/test_manipulation.py @@ -48,6 +48,62 @@ def _arrays_axis_n_dtypes(draw): return xs, input_dtypes, axis +@st.composite +def _arrays_dim_idx_n_dtypes(draw): + num_dims = draw(st.shared(helpers.ints(min_value=1, max_value=4), key="num_dims")) + num_arrays = 2 + common_shape = draw( + helpers.lists( + x=helpers.ints(min_value=2, max_value=3), + min_size=num_dims - 1, + max_size=num_dims - 1, + ) + ) + _dim = draw(helpers.ints(min_value=0, max_value=num_dims - 1)) + unique_dims = draw( + helpers.lists( + x=helpers.ints(min_value=2, max_value=3), + min_size=num_arrays, + max_size=num_arrays, + ) + ) + + min_dim = min(unique_dims) + max_dim = max(unique_dims) + _idx = draw( + helpers.array_values( + shape=min_dim, + dtype="int64", + min_value=0, + max_value=max_dim, + exclude_min=False, + ) + ) + + xs = [] + # available_input_types = draw(helpers.get_dtypes("integer")) + available_input_types = ["int32", "int64", "float16", "float32", "float64"] + input_dtypes = draw( + helpers.array_dtypes( + available_dtypes=available_input_types, + num_arrays=num_arrays, + shared_dtype=True, + ) + ) + for ud, dt in zip(unique_dims, input_dtypes): + x = draw( + helpers.array_values( + shape=common_shape[:_dim] + [ud] + common_shape[_dim:], + dtype=dt, + large_abs_safety_factor=2.5, + small_abs_safety_factor=2.5, + safety_factor_scale="log", + ) + ) + xs.append(x) + return xs, input_dtypes, _dim, _idx + + # concat @st.composite def _arrays_idx_n_dtypes(draw): @@ -471,6 +527,38 @@ def test_paddle_gather_nd( ) +@handle_frontend_test( + fn_tree="paddle.index_add", + xs_dtypes_dim_idx=_arrays_dim_idx_n_dtypes(), +) +def test_paddle_index_add( + *, + xs_dtypes_dim_idx, + on_device, + fn_tree, + frontend, + test_flags, + backend_fw, +): + xs, input_dtypes, axis, indices = xs_dtypes_dim_idx + if xs[0].shape[axis] < xs[1].shape[axis]: + source, input = xs + else: + input, source = xs + helpers.test_frontend_function( + input_dtypes=input_dtypes, + backend_to_test=backend_fw, + test_flags=test_flags, + fn_tree=fn_tree, + frontend=frontend, + on_device=on_device, + x=input, + index=indices, + axis=axis, + value=source, + ) + + # repeat_interleave @handle_frontend_test( fn_tree="paddle.repeat_interleave", diff --git a/ivy_tests/test_ivy/test_frontends/test_paddle/test_math.py b/ivy_tests/test_ivy/test_frontends/test_paddle/test_math.py index cd7c7541fed6c..a7e20943574a5 100644 --- a/ivy_tests/test_ivy/test_frontends/test_paddle/test_math.py +++ b/ivy_tests/test_ivy/test_frontends/test_paddle/test_math.py @@ -1,6 +1,8 @@ # global -from hypothesis import strategies as st +from hypothesis import strategies as st, assume import hypothesis.extra.numpy as nph +import numpy as np +import sys # local import ivy_tests.test_ivy.helpers as helpers @@ -1135,7 +1137,7 @@ def test_paddle_floor_mod( @handle_frontend_test( fn_tree="paddle.fmax", dtypes_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("float"), num_arrays=2, shared_dtype=True + available_dtypes=helpers.get_dtypes("valid"), num_arrays=2, shared_dtype=True ), ) def test_paddle_fmax( @@ -1163,7 +1165,7 @@ def test_paddle_fmax( @handle_frontend_test( fn_tree="paddle.fmin", dtypes_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("float"), num_arrays=2, shared_dtype=True + available_dtypes=helpers.get_dtypes("valid"), num_arrays=2, shared_dtype=True ), ) def test_paddle_fmin( @@ -1322,6 +1324,45 @@ def test_paddle_inner( ) +# inverse +@handle_frontend_test( + fn_tree="paddle.inverse", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("float"), + min_value=-100.0, + max_value=100.0, + shape=helpers.ints(min_value=2, max_value=10).map(lambda x: (x, x)), + ).filter( + lambda x: "float16" not in x[0] + and "bfloat16" not in x[0] + and np.linalg.det(np.asarray(x[1][0])) != 0 + and np.linalg.cond(x[1][0]) < 1 / sys.float_info.epsilon + ), + test_with_out=st.just(False), +) +def test_paddle_inverse( + *, + dtype_and_x, + on_device, + fn_tree, + frontend, + test_flags, + backend_fw, +): + dtype, x = dtype_and_x + helpers.test_frontend_function( + input_dtypes=dtype, + backend_to_test=backend_fw, + rtol=1e-01, + atol=1e-01, + frontend=frontend, + test_flags=test_flags, + fn_tree=fn_tree, + on_device=on_device, + x=x[0], + ) + + # isfinite @handle_frontend_test( fn_tree="paddle.isfinite", @@ -1679,6 +1720,39 @@ def test_paddle_logit( ) +# logsumexp +@handle_frontend_test( + fn_tree="paddle.tensor.math.logsumexp", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), + max_num_dims=4, + num_arrays=2, + allow_inf=False, + shared_dtype=True, + ), +) +def test_paddle_logsumexp( + *, + dtype_and_x, + on_device, + fn_tree, + backend_fw, + frontend, + test_flags, +): + input_dtypes, xs = dtype_and_x + helpers.test_frontend_function( + input_dtypes=input_dtypes, + backend_to_test=backend_fw, + frontend=frontend, + test_flags=test_flags, + fn_tree=fn_tree, + on_device=on_device, + x=xs[0], + axis=None, + ) + + # max @handle_frontend_test( fn_tree="paddle.max", @@ -1835,6 +1909,43 @@ def test_paddle_mm( ) +# mod +@handle_frontend_test( + fn_tree="paddle.mod", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), + num_arrays=2, + allow_inf=False, + large_abs_safety_factor=2, + small_abs_safety_factor=2, + safety_factor_scale="log", + shared_dtype=True, + ), +) +def test_paddle_mod( + *, + dtype_and_x, + on_device, + fn_tree, + frontend, + backend_fw, + test_flags, +): + input_dtype, x = dtype_and_x + assume(not np.any(np.isclose(x[0], 0))) + assume(not np.any(np.isclose(x[1], 0))) + helpers.test_frontend_function( + input_dtypes=input_dtype, + frontend=frontend, + backend_to_test=backend_fw, + test_flags=test_flags, + fn_tree=fn_tree, + on_device=on_device, + x=x[0], + y=x[1], + ) + + # multiply @handle_frontend_test( fn_tree="paddle.multiply", diff --git a/ivy_tests/test_ivy/test_frontends/test_paddle/test_nn/test_functional/test_common.py b/ivy_tests/test_ivy/test_frontends/test_paddle/test_nn/test_functional/test_common.py index 72596838f7e33..871bbe9ea7092 100644 --- a/ivy_tests/test_ivy/test_frontends/test_paddle/test_nn/test_functional/test_common.py +++ b/ivy_tests/test_ivy/test_frontends/test_paddle/test_nn/test_functional/test_common.py @@ -34,7 +34,7 @@ def _interp_args(draw, mode=None, mode_list=None): "trilinear", "nearest-exact", "tf_area", - "bicubic_tensorflow", + "tf_bicubic", "lanczos3", "lanczos5", "mitchellcubic", @@ -46,7 +46,7 @@ def _interp_args(draw, mode=None, mode_list=None): "bilinear", "trilinear", "nearest-exact", - "bicubic_tensorflow", + "tf_bicubic", "lanczos3", "lanczos5", ] @@ -69,7 +69,7 @@ def _interp_args(draw, mode=None, mode_list=None): "nearest-exact", "area", "tf_area", - "bicubic_tensorflow", + "tf_bicubic", "lanczos3", "lanczos5", "mitchellcubic", @@ -80,13 +80,13 @@ def _interp_args(draw, mode=None, mode_list=None): elif mode_list: mode = draw(st.sampled_from(mode_list)) align_corners = draw(st.booleans()) - if (curr_backend == "tensorflow" or curr_backend == "jax") and not mixed_fn_compos: + if curr_backend in ["tensorflow", "jax"] and not mixed_fn_compos: align_corners = False if mode == "linear": num_dims = 3 elif mode in [ "bilinear", - "bicubic_tensorflow", + "tf_bicubic", "bicubic", "mitchellcubic", "gaussian", @@ -157,7 +157,7 @@ def _interp_args(draw, mode=None, mode_list=None): ) recompute_scale_factor = False scale_factor = None - if (curr_backend == "tensorflow" or curr_backend == "jax") and not mixed_fn_compos: + if curr_backend in ["tensorflow", "jax"] and not mixed_fn_compos: if not recompute_scale_factor: recompute_scale_factor = True diff --git a/ivy_tests/test_ivy/test_frontends/test_paddle/test_nn/test_functional/test_pooling.py b/ivy_tests/test_ivy/test_frontends/test_paddle/test_nn/test_functional/test_pooling.py index 881592b4e143a..129f4f502591c 100644 --- a/ivy_tests/test_ivy/test_frontends/test_paddle/test_nn/test_functional/test_pooling.py +++ b/ivy_tests/test_ivy/test_frontends/test_paddle/test_nn/test_functional/test_pooling.py @@ -276,6 +276,60 @@ def test_paddle_avg_pool2d( ) +# max_pool2d +@handle_frontend_test( + fn_tree="paddle.nn.functional.pooling.max_pool2d", + dtype_x_k_s=helpers.arrays_for_pooling( + min_dims=4, max_dims=4, min_side=2, max_side=4 + ), + ceil_mode=st.sampled_from([True]), + data_format=st.sampled_from(["NCHW", "NHWC"]), +) +def test_paddle_max_pool2d( + dtype_x_k_s, + ceil_mode, + data_format, + *, + test_flags, + backend_fw, + frontend, + fn_tree, + on_device, +): + input_dtype, x, kernel, stride, padding = dtype_x_k_s + + if data_format == "NCHW": + x[0] = x[0].reshape( + (x[0].shape[0], x[0].shape[3], x[0].shape[1], x[0].shape[2]) + ) + if len(stride) == 1: + stride = (stride[0], stride[0]) + if padding == "SAME": + padding = test_pooling_functions.calculate_same_padding( + kernel, stride, x[0].shape[2:] + ) + else: + padding = (0, 0) + + if padding == "VALID" and ceil_mode: + ceil_mode = False + + helpers.test_frontend_function( + input_dtypes=input_dtype, + test_flags=test_flags, + backend_to_test=backend_fw, + frontend=frontend, + fn_tree=fn_tree, + on_device=on_device, + x=x[0], + kernel_size=kernel, + stride=stride, + padding=padding, + ceil_mode=ceil_mode, + data_format=data_format, + ) + + # max_unpool1d @handle_frontend_test( fn_tree="paddle.nn.functional.max_unpool1d", diff --git a/ivy_tests/test_ivy/test_frontends/test_paddle/test_stat.py b/ivy_tests/test_ivy/test_frontends/test_paddle/test_stat.py index a7b41e0baf820..9d37a3532b9de 100644 --- a/ivy_tests/test_ivy/test_frontends/test_paddle/test_stat.py +++ b/ivy_tests/test_ivy/test_frontends/test_paddle/test_stat.py @@ -26,7 +26,7 @@ def test_paddle_mean( backend_fw, test_flags, ): - input_dtype, x, axis = dtype_and_x + input_dtype, x, axis = dtype_and_x[:3] test_flags.num_positional_args = len(dtype_and_x) - 2 helpers.test_frontend_function( input_dtypes=input_dtype, @@ -35,6 +35,8 @@ def test_paddle_mean( test_flags=test_flags, fn_tree=fn_tree, on_device=on_device, + rtol=1e-2, + atol=1e-2, input=x[0], axis=axis, keepdim=keepdim, @@ -86,6 +88,7 @@ def test_paddle_nanmedian( dtype_x_and_axis, keepdim, frontend, + backend_fw, test_flags, fn_tree, ): @@ -93,6 +96,7 @@ def test_paddle_nanmedian( helpers.test_frontend_function( input_dtypes=input_dtypes, frontend=frontend, + backend_to_test=backend_fw, test_flags=test_flags, fn_tree=fn_tree, x=x[0], diff --git a/ivy_tests/test_ivy/test_frontends/test_paddle/test_tensor/test_manipulation.py b/ivy_tests/test_ivy/test_frontends/test_paddle/test_tensor/test_manipulation.py index c1265c500864e..d2f8f5bde0fea 100644 --- a/ivy_tests/test_ivy/test_frontends/test_paddle/test_tensor/test_manipulation.py +++ b/ivy_tests/test_ivy/test_frontends/test_paddle/test_tensor/test_manipulation.py @@ -13,6 +13,63 @@ # --------------- # +@st.composite +def _arrays_dim_idx_n_dtypes(draw): + num_dims = draw(st.shared(helpers.ints(min_value=1, max_value=4), key="num_dims")) + num_arrays = 2 + common_shape = draw( + helpers.lists( + x=helpers.ints(min_value=2, max_value=3), + min_size=num_dims - 1, + max_size=num_dims - 1, + ) + ) + _dim = draw(helpers.ints(min_value=0, max_value=num_dims - 1)) + unique_dims = draw( + helpers.lists( + x=helpers.ints(min_value=2, max_value=3), + min_size=num_arrays, + max_size=num_arrays, + ) + ) + + min_dim = min(unique_dims) + max_dim = max(unique_dims) + _idx = draw( + helpers.array_values( + shape=min_dim, + dtype="int64", + min_value=0, + max_value=max_dim, + exclude_min=False, + ) + ) + + xs = [] + # available_input_types = draw(helpers.get_dtypes("integer")) + # available_input_types = ["int32", "int64", "float16", "float32", "float64"] + available_input_types = ["int32", "int64"] + input_dtypes = draw( + helpers.array_dtypes( + available_dtypes=available_input_types, + num_arrays=num_arrays, + shared_dtype=True, + ) + ) + for ud, dt in zip(unique_dims, input_dtypes): + x = draw( + helpers.array_values( + shape=common_shape[:_dim] + [ud] + common_shape[_dim:], + dtype=dt, + large_abs_safety_factor=2.5, + small_abs_safety_factor=2.5, + safety_factor_scale="log", + ) + ) + xs.append(x) + return xs, input_dtypes, _dim, _idx + + @st.composite def dtypes_x_reshape_(draw): shape = draw(helpers.get_shape(min_num_dims=1)) @@ -25,6 +82,42 @@ def dtypes_x_reshape_(draw): return dtypes, x, shape +# --- Main --- # +# ------------ # + + +@handle_frontend_test( + fn_tree="paddle.tensor.manipulation.index_add_", + xs_dtypes_dim_idx=_arrays_dim_idx_n_dtypes(), +) +def test_paddle_index_add_( + *, + xs_dtypes_dim_idx, + on_device, + fn_tree, + frontend, + test_flags, + backend_fw, +): + xs, input_dtypes, axis, indices = xs_dtypes_dim_idx + if xs[0].shape[axis] < xs[1].shape[axis]: + source, input = xs + else: + input, source = xs + helpers.test_frontend_function( + input_dtypes=input_dtypes, + backend_to_test=backend_fw, + test_flags=test_flags, + fn_tree=fn_tree, + frontend=frontend, + on_device=on_device, + x=input, + index=indices, + axis=axis, + value=source, + ) + + # reshape_ @handle_frontend_test( fn_tree="paddle.tensor.manipulation.reshape_", diff --git a/ivy_tests/test_ivy/test_frontends/test_paddle/test_tensor/test_tensor.py b/ivy_tests/test_ivy/test_frontends/test_paddle/test_tensor/test_tensor.py index d62f2086f74da..40b1cfa836440 100644 --- a/ivy_tests/test_ivy/test_frontends/test_paddle/test_tensor/test_tensor.py +++ b/ivy_tests/test_ivy/test_frontends/test_paddle/test_tensor/test_tensor.py @@ -34,6 +34,50 @@ # --------------- # +@st.composite +def _array_and_shape( + draw, + *, + min_num_dims=1, + max_num_dims=3, + min_dim_size=1, + max_dim_size=10, +): + if isinstance(min_dim_size, st._internal.SearchStrategy): + min_dim_size = draw(min_dim_size) + if isinstance(max_dim_size, st._internal.SearchStrategy): + max_dim_size = draw(max_dim_size) + + available_dtypes = draw(helpers.get_dtypes("numeric")) + dtype = draw( + helpers.array_dtypes( + num_arrays=1, + available_dtypes=available_dtypes, + ) + ) + dtype.append("int32") + shape = draw( + st.shared( + helpers.get_shape( + min_num_dims=min_num_dims, + max_num_dims=max_num_dims, + min_dim_size=min_dim_size, + max_dim_size=max_dim_size, + ), + key="shape", + ) + ) + array = draw( + helpers.array_values( + dtype=dtype[0], + shape=shape, + ) + ) + to_shape = [(None if draw(st.booleans()) else _) for _ in shape] + + return dtype, [array, to_shape] + + def _filter_query(query): return ( query.ndim > 1 @@ -120,6 +164,39 @@ def _get_clip_inputs_(draw): return x_dtype, x, min, max +@st.composite +def _get_dtype_and_3dbatch_matrices_for_matmul(draw): + dim_size1 = draw(helpers.ints(min_value=2, max_value=5)) + dim_size2 = draw(helpers.ints(min_value=2, max_value=5)) + shared_size = draw(helpers.ints(min_value=2, max_value=5)) + dtype = draw(helpers.get_dtypes("float", full=True)) + dtype = [ + draw(st.sampled_from(tuple(set(dtype).difference({"bfloat16", "float16"})))) + ] + batch_size = draw(helpers.ints(min_value=2, max_value=4)) + transpose_x = draw(st.booleans()) + transpose_y = draw(st.booleans()) + + mat1_shape = ( + (batch_size, dim_size1, shared_size) + if not transpose_x + else (batch_size, shared_size, dim_size1) + ) + mat2_shape = ( + (batch_size, shared_size, dim_size2) + if not transpose_y + else (batch_size, dim_size2, shared_size) + ) + + mat1 = draw( + helpers.array_values(dtype=dtype[0], shape=mat1_shape, min_value=2, max_value=5) + ) + mat2 = draw( + helpers.array_values(dtype=dtype[0], shape=mat2_shape, min_value=2, max_value=5) + ) + return dtype, mat1, mat2, transpose_x, transpose_y + + # cond @st.composite def _get_dtype_and_matrix_non_singular(draw, dtypes): @@ -146,6 +223,16 @@ def _get_dtype_and_matrix_non_singular(draw, dtypes): return matrix[0], matrix[1] +@st.composite +def _get_dtype_and_multiplicative_matrices(draw): + return draw( + st.one_of( + _get_dtype_input_and_matrices_for_matmul(), + _get_dtype_and_3dbatch_matrices_for_matmul(), + ) + ) + + @st.composite def _get_dtype_and_square_matrix(draw): dim_size = draw(helpers.ints(min_value=2, max_value=5)) @@ -205,6 +292,118 @@ def _get_dtype_and_values_for_lerp(draw): return input_dtype, x[0], x[1], weight +@st.composite +def _get_dtype_input_and_matrices_for_matmul(draw): + dim_size1 = draw(helpers.ints(min_value=2, max_value=5)) + dim_size2 = draw(helpers.ints(min_value=2, max_value=5)) + shared_size = draw(helpers.ints(min_value=2, max_value=5)) + dtype = draw(helpers.get_dtypes("float", full=True)) + dtype = [ + draw(st.sampled_from(tuple(set(dtype).difference({"bfloat16", "float16"})))) + ] + transpose_x = draw(st.booleans()) + transpose_y = draw(st.booleans()) + + mat1_shape = (shared_size, dim_size1) if transpose_x else (dim_size1, shared_size) + mat2_shape = (dim_size2, shared_size) if transpose_y else (shared_size, dim_size2) + + mat1 = draw( + helpers.array_values(dtype=dtype[0], shape=mat1_shape, min_value=2, max_value=5) + ) + mat2 = draw( + helpers.array_values(dtype=dtype[0], shape=mat2_shape, min_value=2, max_value=5) + ) + return dtype, mat1, mat2, transpose_x, transpose_y + + +@st.composite +def _get_dtype_value1_value2_cov( + draw, + available_dtypes, + min_num_dims, + max_num_dims, + min_dim_size, + max_dim_size, + abs_smallest_val=None, + min_value=None, + max_value=None, + allow_inf=False, + exclude_min=False, + exclude_max=False, + large_abs_safety_factor=4, + small_abs_safety_factor=4, + safety_factor_scale="log", +): + shape = draw( + helpers.get_shape( + allow_none=False, + min_num_dims=min_num_dims, + max_num_dims=max_num_dims, + min_dim_size=min_dim_size, + max_dim_size=max_dim_size, + ) + ) + + dtype = draw(st.sampled_from(draw(available_dtypes))) + + values = [] + for i in range(1): + values.append( + draw( + helpers.array_values( + dtype=dtype, + shape=shape, + abs_smallest_val=abs_smallest_val, + min_value=min_value, + max_value=max_value, + allow_inf=allow_inf, + exclude_min=exclude_min, + exclude_max=exclude_max, + large_abs_safety_factor=large_abs_safety_factor, + small_abs_safety_factor=small_abs_safety_factor, + safety_factor_scale=safety_factor_scale, + ) + ) + ) + + value = values[0] + + # modifiers: rowVar, bias, ddof + rowVar = draw(st.booleans()) + ddof = draw(st.booleans()) + + numVals = None + if rowVar is False: + numVals = -1 if numVals == 0 else 0 + else: + numVals = 0 if len(shape) == 1 else -1 + + fweights = draw( + helpers.array_values( + dtype="int64", + shape=shape[numVals], + abs_smallest_val=1, + min_value=1, + max_value=10, + allow_inf=False, + ) + ) + + aweights = draw( + helpers.array_values( + dtype="float64", + shape=shape[numVals], + abs_smallest_val=1, + min_value=1, + max_value=10, + allow_inf=False, + small_abs_safety_factor=1, + ) + ) + + return [dtype], value, rowVar, ddof, fweights, aweights + + @st.composite def _reshape_helper(draw): # generate a shape s.t len(shape) > 0 @@ -229,16 +428,33 @@ def _reshape_helper(draw): return dtypes, x, reshape_shape -# diagonal +# expand helper function @st.composite -def dims_and_offset(draw, shape): - shape_actual = draw(shape) - dim1 = draw(helpers.get_axis(shape=shape, force_int=True)) - dim2 = draw(helpers.get_axis(shape=shape, force_int=True)) - offset = draw( - st.integers(min_value=-shape_actual[dim1], max_value=shape_actual[dim1]) +def dtypes_x_shape(draw): + dtypes, x = draw( + helpers.dtype_and_values( + min_dim_size=1, + min_num_dims=1, + available_dtypes=["float32"], + shape=st.shared( + helpers.get_shape( + min_num_dims=1, + max_num_dims=6, + ), + key="shape", + ), + ) + ) + shape = draw( + st.shared( + helpers.get_shape( + min_num_dims=1, + max_num_dims=6, + ), + key="shape", + ) ) - return dim1, dim2, offset + return dtypes, x, shape # --- Main --- # @@ -282,51 +498,57 @@ def test_paddle___add__( ) -# __setitem__ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="__setitem__", - dtypes_x_index_val=helpers.dtype_array_query_val( - available_dtypes=helpers.get_dtypes("valid"), - ).filter(lambda x: x[0][0] == x[0][-1] and _filter_query(x[-2])), + method_name="__float__", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("numeric"), + max_num_dims=0, + ), ) -def test_paddle___setitem__( - dtypes_x_index_val, +def test_paddle___float__( + dtype_and_x, frontend_method_data, init_flags, method_flags, + backend_fw, frontend, on_device, - backend_fw, ): - input_dtype, x, index, val = dtypes_x_index_val + input_dtypes, xs = dtype_and_x + # Numpy doesn't support complex to float conversion + assume(not np.issubdtype(input_dtypes[0], np.complexfloating)) helpers.test_frontend_method( - init_input_dtypes=[input_dtype[0]], + init_input_dtypes=input_dtypes, backend_to_test=backend_fw, - init_all_as_kwargs_np={"data": x}, - method_input_dtypes=[*input_dtype[1:]], - method_all_as_kwargs_np={"item": index, "value": val}, + method_input_dtypes=input_dtypes, + init_all_as_kwargs_np={ + "object": xs[0], + }, + method_all_as_kwargs_np={}, + frontend=frontend, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, - frontend=frontend, on_device=on_device, ) -# __getitem__ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="__getitem__", - dtype_x_index=helpers.dtype_array_query( - available_dtypes=helpers.get_dtypes("valid"), - allow_neg_step=False, - ).filter(lambda x: x[0][0] == x[0][-1] and _filter_query(x[-2])), + method_name="__floordiv__", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("float"), + num_arrays=2, + large_abs_safety_factor=2.5, + small_abs_safety_factor=2.5, + safety_factor_scale="log", + ), ) -def test_paddle__getitem__( - dtype_x_index, +def test_paddle___floordiv__( + dtype_and_x, frontend_method_data, init_flags, method_flags, @@ -334,30 +556,38 @@ def test_paddle__getitem__( on_device, backend_fw, ): - input_dtype, x, index = dtype_x_index + input_dtype, x = dtype_and_x + assume(not np.any(np.isclose(x[1], 0))) helpers.test_frontend_method( - init_input_dtypes=[input_dtype[0]], + init_input_dtypes=input_dtype, backend_to_test=backend_fw, - init_all_as_kwargs_np={"data": x}, - method_input_dtypes=[*input_dtype[1:]], - method_all_as_kwargs_np={"item": index}, + init_all_as_kwargs_np={ + "data": x[0], + }, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={ + "other": x[1], + }, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, frontend=frontend, on_device=on_device, + atol_=1, ) -# reshape +# __ge__ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="reshape", - dtype_x_shape=_reshape_helper(), + method_name="__ge__", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("numeric"), num_arrays=2, shared_dtype=True + ), ) -def test_paddle__reshape( - dtype_x_shape, +def test_paddle___ge__( + dtype_and_x, frontend_method_data, init_flags, method_flags, @@ -365,11 +595,7 @@ def test_paddle__reshape( on_device, backend_fw, ): - input_dtype, x, shape = dtype_x_shape - assume(len(shape) != 0) - shape = { - "shape": shape, - } + input_dtype, x = dtype_and_x helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, @@ -377,7 +603,9 @@ def test_paddle__reshape( "data": x[0], }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np=shape, + method_all_as_kwargs_np={ + "y": x[1], + }, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -386,17 +614,18 @@ def test_paddle__reshape( ) -# abs +# __getitem__ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="abs", - dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("float"), - ), + method_name="__getitem__", + dtype_x_index=helpers.dtype_array_query( + available_dtypes=helpers.get_dtypes("valid"), + allow_neg_step=False, + ).filter(lambda x: x[0][0] == x[0][-1] and _filter_query(x[-2])), ) -def test_paddle_abs( - dtype_and_x, +def test_paddle___getitem__( + dtype_x_index, frontend_method_data, init_flags, method_flags, @@ -404,15 +633,13 @@ def test_paddle_abs( on_device, backend_fw, ): - input_dtype, x = dtype_and_x + input_dtype, x, index = dtype_x_index helpers.test_frontend_method( - init_input_dtypes=input_dtype, + init_input_dtypes=[input_dtype[0]], backend_to_test=backend_fw, - init_all_as_kwargs_np={ - "data": x[0], - }, - method_input_dtypes=input_dtype, - method_all_as_kwargs_np={}, + init_all_as_kwargs_np={"data": x}, + method_input_dtypes=[*input_dtype[1:]], + method_all_as_kwargs_np={"item": index}, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -421,16 +648,16 @@ def test_paddle_abs( ) -# acosh +# __gt__ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="acosh", + method_name="__gt__", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("float"), + available_dtypes=helpers.get_dtypes("numeric"), num_arrays=2, shared_dtype=True ), ) -def test_paddle_acosh( +def test_paddle___gt__( dtype_and_x, frontend_method_data, init_flags, @@ -447,7 +674,9 @@ def test_paddle_acosh( "data": x[0], }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={}, + method_all_as_kwargs_np={ + "y": x[1], + }, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -456,102 +685,92 @@ def test_paddle_acosh( ) -# add_ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="add_", + method_name="__int__", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("valid"), num_arrays=2, shared_dtype=True + available_dtypes=helpers.get_dtypes("integer"), + max_num_dims=0, + min_value=-1e15, + max_value=1e15, ), - test_inplace=st.just(True), ) -def test_paddle_add_( +def test_paddle___int__( dtype_and_x, frontend_method_data, init_flags, method_flags, + backend_fw, frontend, on_device, - backend_fw, ): - input_dtype, x = dtype_and_x + input_dtypes, xs = dtype_and_x + # Numpy doesn't support complex to int conversion + assume(not np.issubdtype(input_dtypes[0], np.complexfloating)) helpers.test_frontend_method( - init_input_dtypes=input_dtype, + init_input_dtypes=input_dtypes, backend_to_test=backend_fw, + method_input_dtypes=input_dtypes, init_all_as_kwargs_np={ - "data": x[0], + "object": xs[0], }, - method_input_dtypes=input_dtype, - method_all_as_kwargs_np={"y": x[1]}, + method_all_as_kwargs_np={}, + frontend=frontend, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, - frontend=frontend, on_device=on_device, ) +# invert @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="add_n", + method_name="__invert__", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("float"), - num_arrays=helpers.ints(min_value=1, max_value=5), - shared_dtype=True, + available_dtypes=helpers.get_dtypes("numeric"), + max_num_dims=0, ), ) -def test_paddle_add_n( +def test_paddle___invert__( dtype_and_x, frontend_method_data, init_flags, method_flags, + backend_fw, frontend, on_device, - backend_fw, ): - input_dtype, x = dtype_and_x + input_dtypes, xs = dtype_and_x helpers.test_frontend_method( - init_input_dtypes=input_dtype, + init_input_dtypes=input_dtypes, backend_to_test=backend_fw, - init_all_as_kwargs_np={"inputs": x}, - method_input_dtypes=input_dtype, - method_all_as_kwargs_np={"inputs": x}, + method_input_dtypes=input_dtypes, + init_all_as_kwargs_np={ + "object": xs[0], + }, + method_all_as_kwargs_np={}, + frontend=frontend, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, - frontend=frontend, on_device=on_device, ) -# addmm +# __le__ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="addmm", - dtype_input_xy=_get_dtype_and_3dbatch_matrices(with_input=True, input_3d=True), - beta=st.floats( - min_value=-5, - max_value=5, - allow_nan=False, - allow_subnormal=False, - allow_infinity=False, - ), - alpha=st.floats( - min_value=-5, - max_value=5, - allow_nan=False, - allow_subnormal=False, - allow_infinity=False, + method_name="__le__", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), num_arrays=2, shared_dtype=True ), ) -def test_paddle_addmm( - *, - dtype_input_xy, - beta, - alpha, +def test_paddle___le__( + dtype_and_x, frontend_method_data, init_flags, method_flags, @@ -559,15 +778,17 @@ def test_paddle_addmm( on_device, backend_fw, ): - input_dtype, input, x, y = dtype_input_xy + input_dtype, x = dtype_and_x helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, init_all_as_kwargs_np={ - "data": input[0], + "data": x[0], }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={"x": x[0], "y": y[0], "beta": beta, "alpha": alpha}, + method_all_as_kwargs_np={ + "y": x[1], + }, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -576,42 +797,34 @@ def test_paddle_addmm( ) -# all +# __len__ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="all", - dtype_x_axis=helpers.dtype_values_axis( - available_dtypes=helpers.get_dtypes("bool"), - min_axis=-1, - max_axis=0, + method_name="__len__", + dtype_and_x=_array_and_shape( min_num_dims=1, - force_int_axis=True, + max_num_dims=5, ), - keep_dims=st.booleans(), ) -def test_paddle_all( - dtype_x_axis, - keep_dims, +def test_paddle___len__( + dtype_and_x, + frontend, frontend_method_data, init_flags, method_flags, - frontend, - on_device, backend_fw, + on_device, ): - input_dtypes, x, axis = dtype_x_axis + input_dtype, x = dtype_and_x helpers.test_frontend_method( - init_input_dtypes=input_dtypes, + init_input_dtypes=input_dtype, backend_to_test=backend_fw, init_all_as_kwargs_np={ - "object": x[0], - }, - method_input_dtypes=input_dtypes, - method_all_as_kwargs_np={ - "axis": axis, - "keepdim": keep_dims, + "value": x[0], }, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={}, frontend=frontend, frontend_method_data=frontend_method_data, init_flags=init_flags, @@ -620,46 +833,38 @@ def test_paddle_all( ) -# allclose +# long @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="allclose", + method_name="__long__", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("float"), - num_arrays=2, - shared_dtype=True, + available_dtypes=helpers.get_dtypes("integer"), + max_num_dims=0, + min_value=-1e15, + max_value=1e15, ), - # rtol=1e-05, - # atol=1e-08, - # equal_nan=st.booleans(), ) -def test_paddle_allclose( +def test_paddle___long__( dtype_and_x, - # rtol, - # atol, - # equal_nan, frontend_method_data, init_flags, method_flags, + backend_fw, frontend, on_device, - backend_fw, ): - input_dtype, x = dtype_and_x + input_dtypes, xs = dtype_and_x + # Numpy doesn't support complex to int conversion + assume(not np.issubdtype(input_dtypes[0], np.complexfloating)) helpers.test_frontend_method( - init_input_dtypes=input_dtype, + init_input_dtypes=input_dtypes, backend_to_test=backend_fw, + method_input_dtypes=input_dtypes, init_all_as_kwargs_np={ - "data": x[0], - }, - method_input_dtypes=input_dtype, - method_all_as_kwargs_np={ - "other": x[1], - # "rtol": rtol, - # "atol": atol, - # "equal_nan": equal_nan, + "object": xs[0], }, + method_all_as_kwargs_np={}, frontend=frontend, frontend_method_data=frontend_method_data, init_flags=init_flags, @@ -668,15 +873,16 @@ def test_paddle_allclose( ) +# __lt__ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="angle", + method_name="__lt__", dtype_and_x=helpers.dtype_and_values( - available_dtypes=["float64", "complex64", "complex128"], + available_dtypes=helpers.get_dtypes("numeric"), num_arrays=2, shared_dtype=True ), ) -def test_paddle_angle( +def test_paddle___lt__( dtype_and_x, frontend_method_data, init_flags, @@ -693,7 +899,9 @@ def test_paddle_angle( "data": x[0], }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={}, + method_all_as_kwargs_np={ + "y": x[1], + }, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -702,23 +910,21 @@ def test_paddle_angle( ) -# any +# __mod__ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="any", - dtype_x_axis=helpers.dtype_values_axis( - available_dtypes=st.one_of(helpers.get_dtypes("float")), - min_axis=-1, - max_axis=0, - min_num_dims=1, - force_int_axis=True, + method_name="__mod__", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), + num_arrays=2, + shared_dtype=True, + min_value=0, + exclude_min=True, ), - keep_dims=st.booleans(), ) -def test_paddle_any( - dtype_x_axis, - keep_dims, +def test_paddle___mod__( + dtype_and_x, frontend_method_data, init_flags, method_flags, @@ -726,43 +932,36 @@ def test_paddle_any( on_device, backend_fw, ): - input_dtypes, x, axis = dtype_x_axis + input_dtype, x = dtype_and_x helpers.test_frontend_method( - init_input_dtypes=input_dtypes, + init_input_dtypes=input_dtype, backend_to_test=backend_fw, init_all_as_kwargs_np={ "data": x[0], }, - method_input_dtypes=input_dtypes, + method_input_dtypes=input_dtype, method_all_as_kwargs_np={ - "axis": axis, - "keepdim": keep_dims, + "y": x[1], }, - frontend=frontend, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, + frontend=frontend, on_device=on_device, ) -# argmax +# __mul__ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="argmax", - dtype_x_axis=helpers.dtype_values_axis( - available_dtypes=st.one_of(helpers.get_dtypes("float")), - min_axis=-1, - max_axis=0, - min_num_dims=1, - force_int_axis=True, + method_name="__mul__", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("numeric"), num_arrays=2, shared_dtype=True ), - keep_dims=st.booleans(), ) -def test_paddle_argmax( - dtype_x_axis, - keep_dims, +def test_paddle___mul__( + dtype_and_x, frontend_method_data, init_flags, method_flags, @@ -770,87 +969,80 @@ def test_paddle_argmax( on_device, backend_fw, ): - input_dtypes, x, axis = dtype_x_axis + input_dtype, x = dtype_and_x helpers.test_frontend_method( - init_input_dtypes=input_dtypes, + init_input_dtypes=input_dtype, backend_to_test=backend_fw, init_all_as_kwargs_np={ - "object": x[0], + "data": x[0], }, - method_input_dtypes=input_dtypes, + method_input_dtypes=input_dtype, method_all_as_kwargs_np={ - "axis": axis, - "keepdim": keep_dims, + "y": x[1], }, - frontend=frontend, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, + frontend=frontend, on_device=on_device, ) -# argmin +# __ne__ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="argmin", - dtype_x_axis=helpers.dtype_values_axis( - available_dtypes=st.one_of(helpers.get_dtypes("valid")), - min_axis=-1, - max_axis=0, - min_num_dims=1, - force_int_axis=True, + method_name="__ne__", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("float"), + num_arrays=2, + min_value=-1e04, + max_value=1e04, + allow_inf=False, ), - keep_dims=st.booleans(), ) -def test_paddle_argmin( - dtype_x_axis, - keep_dims, - on_device, - backend_fw, +def test_paddle___ne__( + dtype_and_x, frontend_method_data, init_flags, method_flags, frontend, + on_device, + backend_fw, ): - input_dtypes, x, axis = dtype_x_axis + input_dtype, x = dtype_and_x helpers.test_frontend_method( - init_input_dtypes=input_dtypes, + init_input_dtypes=input_dtype, backend_to_test=backend_fw, init_all_as_kwargs_np={ - "object": x[0], + "data": x[0], }, - method_input_dtypes=input_dtypes, + method_input_dtypes=input_dtype, method_all_as_kwargs_np={ - "axis": axis, - "keepdim": keep_dims, + "other": x[1], }, - frontend=frontend, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, + frontend=frontend, on_device=on_device, ) -# argsort +# __neg__ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="argsort", - dtype_x_axis=helpers.dtype_values_axis( - available_dtypes=st.one_of(helpers.get_dtypes("float")), - min_axis=-1, - max_axis=0, - min_num_dims=1, - force_int_axis=True, + method_name="__neg__", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("float"), + min_value=-1e04, + max_value=1e04, + allow_inf=False, ), - descending=st.booleans(), ) -def test_paddle_argsort( - dtype_x_axis, - descending, +def test_paddle___neg__( + dtype_and_x, frontend_method_data, init_flags, method_flags, @@ -858,35 +1050,34 @@ def test_paddle_argsort( on_device, backend_fw, ): - input_dtypes, x, axis = dtype_x_axis + input_dtype, x = dtype_and_x helpers.test_frontend_method( - init_input_dtypes=input_dtypes, + init_input_dtypes=input_dtype, backend_to_test=backend_fw, init_all_as_kwargs_np={ - "object": x[0], - }, - method_input_dtypes=input_dtypes, - method_all_as_kwargs_np={ - "axis": axis, - "descending": descending, + "data": x[0], }, - frontend=frontend, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={}, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, + frontend=frontend, on_device=on_device, ) -# as_complex +# __or__ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="as_complex", - dtypes_and_x=_get_as_complex_inputs_(), + method_name="__or__", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("integer"), num_arrays=2, shared_dtype=True + ), ) -def test_paddle_as_complex( - dtypes_and_x, +def test_paddle___or__( + dtype_and_x, frontend_method_data, init_flags, method_flags, @@ -894,13 +1085,17 @@ def test_paddle_as_complex( on_device, backend_fw, ): - input_dtype, x = dtypes_and_x + input_dtype, x = dtype_and_x helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, - init_all_as_kwargs_np={"data": x[0]}, + init_all_as_kwargs_np={ + "data": x[0], + }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={}, + method_all_as_kwargs_np={ + "y": x[1], + }, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -909,34 +1104,35 @@ def test_paddle_as_complex( ) -# as_real +# __radd__ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="as_real", + method_name="__radd__", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("valid"), - num_arrays=1, + available_dtypes=helpers.get_dtypes("valid"), num_arrays=2, shared_dtype=True ), ) -def test_paddle_as_real( +def test_paddle___radd__( dtype_and_x, frontend_method_data, init_flags, method_flags, frontend, - backend_fw, on_device, + backend_fw, ): input_dtype, x = dtype_and_x helpers.test_frontend_method( init_input_dtypes=input_dtype, + backend_to_test=backend_fw, init_all_as_kwargs_np={ "data": x[0], }, method_input_dtypes=input_dtype, - backend_to_test=backend_fw, - method_all_as_kwargs_np={}, + method_all_as_kwargs_np={ + "x": x[1], + }, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -945,51 +1141,63 @@ def test_paddle_as_real( ) -# asin @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="asin", + method_name="__rdiv__", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("float"), + available_dtypes=helpers.get_dtypes("numeric"), + num_arrays=2, + shared_dtype=True, + large_abs_safety_factor=10, + small_abs_safety_factor=10, + safety_factor_scale="log", ), ) -def test_paddle_asin( +def test_paddle___rdiv__( dtype_and_x, + frontend, frontend_method_data, init_flags, method_flags, - frontend, on_device, backend_fw, ): input_dtype, x = dtype_and_x + assume(not np.any(np.isclose(x[0], 0))) + assume(not np.any(np.isclose(x[1], 0))) helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, init_all_as_kwargs_np={ - "data": x[0], + "value": x[0], }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={}, + method_all_as_kwargs_np={ + "y": x[1], + }, + frontend=frontend, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, - frontend=frontend, on_device=on_device, ) -# asinh +# __rmul__ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="asinh", + method_name="__rmul__", dtype_and_x=helpers.dtype_and_values( available_dtypes=helpers.get_dtypes("float"), + num_arrays=2, + min_value=-1e04, + max_value=1e04, + allow_inf=False, ), ) -def test_paddle_asinh( +def test_paddle___rmul__( dtype_and_x, frontend_method_data, init_flags, @@ -1006,7 +1214,9 @@ def test_paddle_asinh( "data": x[0], }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={}, + method_all_as_kwargs_np={ + "other": x[1], + }, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -1015,93 +1225,99 @@ def test_paddle_asinh( ) -# astype +# __rsub__ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="astype", + method_name="__rsub__", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("float"), + available_dtypes=helpers.get_dtypes("numeric"), + num_arrays=2, + shared_dtype=True, ), - dtype=st.one_of(helpers.get_dtypes("valid")), ) -def test_paddle_astype( +def test_paddle___rsub__( dtype_and_x, - dtype, + frontend, frontend_method_data, init_flags, method_flags, - frontend, - on_device, backend_fw, + on_device, ): input_dtype, x = dtype_and_x - if dtype is None: - dtype = input_dtype helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, init_all_as_kwargs_np={ - "data": x[0], + "value": x[0], }, method_input_dtypes=input_dtype, method_all_as_kwargs_np={ - "dtype": dtype, + "x": x[1], }, + frontend=frontend, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, - frontend=frontend, on_device=on_device, ) -# atan @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="atan", + method_name="__rtruediv__", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("float"), + available_dtypes=helpers.get_dtypes("numeric"), + num_arrays=2, + shared_dtype=True, + large_abs_safety_factor=10, + small_abs_safety_factor=10, + safety_factor_scale="log", ), ) -def test_paddle_atan( +def test_paddle___rtruediv__( dtype_and_x, + frontend, frontend_method_data, init_flags, method_flags, - frontend, on_device, backend_fw, ): input_dtype, x = dtype_and_x + assume(not np.any(np.isclose(x[0], 0))) + assume(not np.any(np.isclose(x[1], 0))) helpers.test_frontend_method( init_input_dtypes=input_dtype, + backend_to_test=backend_fw, init_all_as_kwargs_np={ - "data": x[0], + "value": x[0], }, - backend_to_test=backend_fw, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={}, + method_all_as_kwargs_np={ + "y": x[1], + }, + frontend=frontend, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, - frontend=frontend, on_device=on_device, ) -# bitwise_and +# __setitem__ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="bitwise_and", - dtypes_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("valid"), num_arrays=2, shared_dtype=True - ), + method_name="__setitem__", + dtypes_x_index_val=helpers.dtype_array_query_val( + available_dtypes=helpers.get_dtypes("valid"), + ).filter(lambda x: x[0][0] == x[0][-1] and _filter_query(x[-2])), ) -def test_paddle_bitwise_and( - dtypes_and_x, +def test_paddle___setitem__( + dtypes_x_index_val, frontend_method_data, init_flags, method_flags, @@ -1109,13 +1325,13 @@ def test_paddle_bitwise_and( on_device, backend_fw, ): - input_dtype, x = dtypes_and_x + input_dtype, x, index, val = dtypes_x_index_val helpers.test_frontend_method( - init_input_dtypes=input_dtype, + init_input_dtypes=[input_dtype[0]], backend_to_test=backend_fw, - init_all_as_kwargs_np={"data": x[0]}, - method_input_dtypes=input_dtype, - method_all_as_kwargs_np={"y": x[1]}, + init_all_as_kwargs_np={"data": x}, + method_input_dtypes=[*input_dtype[1:]], + method_all_as_kwargs_np={"item": index, "value": val}, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -1124,16 +1340,16 @@ def test_paddle_bitwise_and( ) -# bitwise_not +# __sub__ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="bitwise_not", + method_name="__sub__", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("valid"), + available_dtypes=helpers.get_dtypes("valid"), num_arrays=2, shared_dtype=True ), ) -def test_paddle_bitwise_not( +def test_paddle___sub__( dtype_and_x, frontend_method_data, init_flags, @@ -1150,7 +1366,9 @@ def test_paddle_bitwise_not( "data": x[0], }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={}, + method_all_as_kwargs_np={ + "y": x[1], + }, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -1159,49 +1377,56 @@ def test_paddle_bitwise_not( ) +# __xor__ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="bitwise_or", - dtypes_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("valid"), num_arrays=2, shared_dtype=True + method_name="__xor__", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("integer"), + num_arrays=2, + shared_dtype=True, ), ) -def test_paddle_bitwise_or( - dtypes_and_x, +def test_paddle___xor__( + dtype_and_x, + frontend, frontend_method_data, init_flags, method_flags, - frontend, - on_device, backend_fw, + on_device, ): - input_dtype, x = dtypes_and_x + input_dtype, x = dtype_and_x helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, - init_all_as_kwargs_np={"data": x[0]}, + init_all_as_kwargs_np={ + "value": x[0], + }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={"y": x[1]}, + method_all_as_kwargs_np={ + "y": x[1], + }, + frontend=frontend, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, - frontend=frontend, on_device=on_device, ) -# bitwise_xor +# abs @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="bitwise_xor", - dtypes_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("valid"), num_arrays=2, shared_dtype=True + method_name="abs", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("float"), ), ) -def test_paddle_bitwise_xor( - dtypes_and_x, +def test_paddle_abs( + dtype_and_x, frontend_method_data, init_flags, method_flags, @@ -1209,13 +1434,15 @@ def test_paddle_bitwise_xor( on_device, backend_fw, ): - input_dtype, x = dtypes_and_x + input_dtype, x = dtype_and_x helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, - init_all_as_kwargs_np={"data": x[0]}, + init_all_as_kwargs_np={ + "data": x[0], + }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={"y": x[1]}, + method_all_as_kwargs_np={}, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -1224,14 +1451,16 @@ def test_paddle_bitwise_xor( ) -# bmm +# acosh @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="bmm", - dtype_and_x=_get_dtype_and_values_bmm(), + method_name="acosh", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("float"), + ), ) -def test_paddle_bmm( +def test_paddle_acosh( dtype_and_x, frontend_method_data, init_flags, @@ -1240,13 +1469,15 @@ def test_paddle_bmm( on_device, backend_fw, ): - input_dtype, x, y = dtype_and_x + input_dtype, x = dtype_and_x helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, - init_all_as_kwargs_np={"data": x}, + init_all_as_kwargs_np={ + "data": x[0], + }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={"y": y}, + method_all_as_kwargs_np={}, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -1255,19 +1486,18 @@ def test_paddle_bmm( ) -# cast +# add_ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="cast", + method_name="add_", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("valid"), + available_dtypes=helpers.get_dtypes("valid"), num_arrays=2, shared_dtype=True ), - dtype=helpers.get_dtypes("valid", full=False), + test_inplace=st.just(True), ) -def test_paddle_cast( +def test_paddle_add_( dtype_and_x, - dtype, frontend_method_data, init_flags, method_flags, @@ -1276,8 +1506,6 @@ def test_paddle_cast( backend_fw, ): input_dtype, x = dtype_and_x - if dtype is None: - dtype = input_dtype helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, @@ -1285,9 +1513,7 @@ def test_paddle_cast( "data": x[0], }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={ - "dtype": dtype[0], - }, + method_all_as_kwargs_np={"y": x[1]}, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -1296,16 +1522,17 @@ def test_paddle_cast( ) -# ceil @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="ceil", + method_name="add_n", dtype_and_x=helpers.dtype_and_values( available_dtypes=helpers.get_dtypes("float"), + num_arrays=helpers.ints(min_value=1, max_value=5), + shared_dtype=True, ), ) -def test_paddle_ceil( +def test_paddle_add_n( dtype_and_x, frontend_method_data, init_flags, @@ -1318,11 +1545,9 @@ def test_paddle_ceil( helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, - init_all_as_kwargs_np={ - "data": x[0], - }, + init_all_as_kwargs_np={"inputs": x}, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={}, + method_all_as_kwargs_np={"inputs": x}, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -1331,18 +1556,32 @@ def test_paddle_ceil( ) -# ceil_ +# addmm @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="ceil_", - dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("valid"), + method_name="addmm", + dtype_input_xy=_get_dtype_and_3dbatch_matrices(with_input=True, input_3d=True), + beta=st.floats( + min_value=-5, + max_value=5, + allow_nan=False, + allow_subnormal=False, + allow_infinity=False, + ), + alpha=st.floats( + min_value=-5, + max_value=5, + allow_nan=False, + allow_subnormal=False, + allow_infinity=False, ), - test_inplace=st.just(True), ) -def test_paddle_ceil_( - dtype_and_x, +def test_paddle_addmm( + *, + dtype_input_xy, + beta, + alpha, frontend_method_data, init_flags, method_flags, @@ -1350,15 +1589,15 @@ def test_paddle_ceil_( on_device, backend_fw, ): - input_dtype, x = dtype_and_x + input_dtype, input, x, y = dtype_input_xy helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, init_all_as_kwargs_np={ - "data": x[0], + "data": input[0], }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={}, + method_all_as_kwargs_np={"x": x[0], "y": y[0], "beta": beta, "alpha": alpha}, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -1367,17 +1606,23 @@ def test_paddle_ceil_( ) -# cholesky +# all @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="cholesky", - dtype_and_x=_get_dtype_and_square_matrix(), - upper=st.booleans(), + method_name="all", + dtype_x_axis=helpers.dtype_values_axis( + available_dtypes=helpers.get_dtypes("bool"), + min_axis=-1, + max_axis=0, + min_num_dims=1, + force_int_axis=True, + ), + keep_dims=st.booleans(), ) -def test_paddle_cholesky( - dtype_and_x, - upper, +def test_paddle_all( + dtype_x_axis, + keep_dims, frontend_method_data, init_flags, method_flags, @@ -1385,17 +1630,18 @@ def test_paddle_cholesky( on_device, backend_fw, ): - input_dtype, x = dtype_and_x - x = np.matmul(x.T, x) + np.identity(x.shape[0]) - + input_dtypes, x, axis = dtype_x_axis helpers.test_frontend_method( - init_input_dtypes=input_dtype, + init_input_dtypes=input_dtypes, backend_to_test=backend_fw, init_all_as_kwargs_np={ - "data": x, + "object": x[0], + }, + method_input_dtypes=input_dtypes, + method_all_as_kwargs_np={ + "axis": axis, + "keepdim": keep_dims, }, - method_input_dtypes=input_dtype, - method_all_as_kwargs_np={"upper": upper}, frontend=frontend, frontend_method_data=frontend_method_data, init_flags=init_flags, @@ -1404,89 +1650,1413 @@ def test_paddle_cholesky( ) +# allclose @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="clip", - input_and_ranges=_get_clip_inputs(), + method_name="allclose", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("float"), + num_arrays=2, + shared_dtype=True, + ), + # rtol=1e-05, + # atol=1e-08, + # equal_nan=st.booleans(), ) -def test_paddle_clip( - input_and_ranges, - frontend, +def test_paddle_allclose( + dtype_and_x, + # rtol, + # atol, + # equal_nan, frontend_method_data, - backend_fw, init_flags, method_flags, + frontend, on_device, + backend_fw, ): - input_dtype, x, min, max = input_and_ranges + input_dtype, x = dtype_and_x helpers.test_frontend_method( init_input_dtypes=input_dtype, + backend_to_test=backend_fw, init_all_as_kwargs_np={ "data": x[0], }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={"min": min, "max": max}, + method_all_as_kwargs_np={ + "other": x[1], + # "rtol": rtol, + # "atol": atol, + # "equal_nan": equal_nan, + }, + frontend=frontend, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, - frontend=frontend, - backend_to_test=backend_fw, on_device=on_device, ) -# clip_ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="clip_", - input_and_ranges=_get_clip_inputs_(), - test_inplace=st.just(True), -) + method_name="angle", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=["float64", "complex64", "complex128"], + ), +) +def test_paddle_angle( + dtype_and_x, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + backend_fw, +): + input_dtype, x = dtype_and_x + helpers.test_frontend_method( + init_input_dtypes=input_dtype, + backend_to_test=backend_fw, + init_all_as_kwargs_np={ + "data": x[0], + }, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={}, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + on_device=on_device, + ) + + +# any +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="paddle.to_tensor", + method_name="any", + dtype_x_axis=helpers.dtype_values_axis( + available_dtypes=st.one_of(helpers.get_dtypes("float")), + min_axis=-1, + max_axis=0, + min_num_dims=1, + force_int_axis=True, + ), + keep_dims=st.booleans(), +) +def test_paddle_any( + dtype_x_axis, + keep_dims, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + backend_fw, +): + input_dtypes, x, axis = dtype_x_axis + helpers.test_frontend_method( + init_input_dtypes=input_dtypes, + backend_to_test=backend_fw, + init_all_as_kwargs_np={ + "data": x[0], + }, + method_input_dtypes=input_dtypes, + method_all_as_kwargs_np={ + "axis": axis, + "keepdim": keep_dims, + }, + frontend=frontend, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + on_device=on_device, + ) + + +# argmax +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="paddle.to_tensor", + method_name="argmax", + dtype_x_axis=helpers.dtype_values_axis( + available_dtypes=st.one_of(helpers.get_dtypes("float")), + min_axis=-1, + max_axis=0, + min_num_dims=1, + force_int_axis=True, + ), + keep_dims=st.booleans(), +) +def test_paddle_argmax( + dtype_x_axis, + keep_dims, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + backend_fw, +): + input_dtypes, x, axis = dtype_x_axis + helpers.test_frontend_method( + init_input_dtypes=input_dtypes, + backend_to_test=backend_fw, + init_all_as_kwargs_np={ + "object": x[0], + }, + method_input_dtypes=input_dtypes, + method_all_as_kwargs_np={ + "axis": axis, + "keepdim": keep_dims, + }, + frontend=frontend, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + on_device=on_device, + ) + + +# argmin +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="paddle.to_tensor", + method_name="argmin", + dtype_x_axis=helpers.dtype_values_axis( + available_dtypes=st.one_of(helpers.get_dtypes("valid")), + min_axis=-1, + max_axis=0, + min_num_dims=1, + force_int_axis=True, + ), + keep_dims=st.booleans(), +) +def test_paddle_argmin( + dtype_x_axis, + keep_dims, + on_device, + backend_fw, + frontend_method_data, + init_flags, + method_flags, + frontend, +): + input_dtypes, x, axis = dtype_x_axis + helpers.test_frontend_method( + init_input_dtypes=input_dtypes, + backend_to_test=backend_fw, + init_all_as_kwargs_np={ + "object": x[0], + }, + method_input_dtypes=input_dtypes, + method_all_as_kwargs_np={ + "axis": axis, + "keepdim": keep_dims, + }, + frontend=frontend, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + on_device=on_device, + ) + + +# argsort +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="paddle.to_tensor", + method_name="argsort", + dtype_x_axis=helpers.dtype_values_axis( + available_dtypes=st.one_of(helpers.get_dtypes("float")), + min_axis=-1, + max_axis=0, + min_num_dims=1, + force_int_axis=True, + ), + descending=st.booleans(), +) +def test_paddle_argsort( + dtype_x_axis, + descending, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + backend_fw, +): + input_dtypes, x, axis = dtype_x_axis + helpers.test_frontend_method( + init_input_dtypes=input_dtypes, + backend_to_test=backend_fw, + init_all_as_kwargs_np={ + "object": x[0], + }, + method_input_dtypes=input_dtypes, + method_all_as_kwargs_np={ + "axis": axis, + "descending": descending, + }, + frontend=frontend, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + on_device=on_device, + ) + + +# as_complex +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="paddle.to_tensor", + method_name="as_complex", + dtypes_and_x=_get_as_complex_inputs_(), +) +def test_paddle_as_complex( + dtypes_and_x, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + backend_fw, +): + input_dtype, x = dtypes_and_x + helpers.test_frontend_method( + init_input_dtypes=input_dtype, + backend_to_test=backend_fw, + init_all_as_kwargs_np={"data": x[0]}, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={}, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + on_device=on_device, + ) + + +# as_real +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="paddle.to_tensor", + method_name="as_real", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), + num_arrays=1, + ), +) +def test_paddle_as_real( + dtype_and_x, + frontend_method_data, + init_flags, + method_flags, + frontend, + backend_fw, + on_device, +): + input_dtype, x = dtype_and_x + helpers.test_frontend_method( + init_input_dtypes=input_dtype, + init_all_as_kwargs_np={ + "data": x[0], + }, + method_input_dtypes=input_dtype, + backend_to_test=backend_fw, + method_all_as_kwargs_np={}, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + on_device=on_device, + ) + + +# asin +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="paddle.to_tensor", + method_name="asin", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("float"), + ), +) +def test_paddle_asin( + dtype_and_x, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + backend_fw, +): + input_dtype, x = dtype_and_x + helpers.test_frontend_method( + init_input_dtypes=input_dtype, + backend_to_test=backend_fw, + init_all_as_kwargs_np={ + "data": x[0], + }, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={}, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + on_device=on_device, + ) + + +# asinh +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="paddle.to_tensor", + method_name="asinh", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("float"), + ), +) +def test_paddle_asinh( + dtype_and_x, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + backend_fw, +): + input_dtype, x = dtype_and_x + helpers.test_frontend_method( + init_input_dtypes=input_dtype, + backend_to_test=backend_fw, + init_all_as_kwargs_np={ + "data": x[0], + }, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={}, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + on_device=on_device, + ) + + +# astype +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="paddle.to_tensor", + method_name="astype", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("float"), + ), + dtype=st.one_of(helpers.get_dtypes("valid")), +) +def test_paddle_astype( + dtype_and_x, + dtype, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + backend_fw, +): + input_dtype, x = dtype_and_x + if dtype is None: + dtype = input_dtype + helpers.test_frontend_method( + init_input_dtypes=input_dtype, + backend_to_test=backend_fw, + init_all_as_kwargs_np={ + "data": x[0], + }, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={ + "dtype": dtype, + }, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + on_device=on_device, + ) + + +# atan +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="paddle.to_tensor", + method_name="atan", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("float"), + ), +) +def test_paddle_atan( + dtype_and_x, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + backend_fw, +): + input_dtype, x = dtype_and_x + helpers.test_frontend_method( + init_input_dtypes=input_dtype, + init_all_as_kwargs_np={ + "data": x[0], + }, + backend_to_test=backend_fw, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={}, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + on_device=on_device, + ) + + +# bitwise_and +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="paddle.to_tensor", + method_name="bitwise_and", + dtypes_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), num_arrays=2, shared_dtype=True + ), +) +def test_paddle_bitwise_and( + dtypes_and_x, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + backend_fw, +): + input_dtype, x = dtypes_and_x + helpers.test_frontend_method( + init_input_dtypes=input_dtype, + backend_to_test=backend_fw, + init_all_as_kwargs_np={"data": x[0]}, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={"y": x[1]}, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + on_device=on_device, + ) + + +# bitwise_not +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="paddle.to_tensor", + method_name="bitwise_not", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), + ), +) +def test_paddle_bitwise_not( + dtype_and_x, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + backend_fw, +): + input_dtype, x = dtype_and_x + helpers.test_frontend_method( + init_input_dtypes=input_dtype, + backend_to_test=backend_fw, + init_all_as_kwargs_np={ + "data": x[0], + }, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={}, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + on_device=on_device, + ) + + +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="paddle.to_tensor", + method_name="bitwise_or", + dtypes_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), num_arrays=2, shared_dtype=True + ), +) +def test_paddle_bitwise_or( + dtypes_and_x, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + backend_fw, +): + input_dtype, x = dtypes_and_x + helpers.test_frontend_method( + init_input_dtypes=input_dtype, + backend_to_test=backend_fw, + init_all_as_kwargs_np={"data": x[0]}, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={"y": x[1]}, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + on_device=on_device, + ) + + +# bitwise_xor +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="paddle.to_tensor", + method_name="bitwise_xor", + dtypes_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), num_arrays=2, shared_dtype=True + ), +) +def test_paddle_bitwise_xor( + dtypes_and_x, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + backend_fw, +): + input_dtype, x = dtypes_and_x + helpers.test_frontend_method( + init_input_dtypes=input_dtype, + backend_to_test=backend_fw, + init_all_as_kwargs_np={"data": x[0]}, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={"y": x[1]}, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + on_device=on_device, + ) + + +# bmm +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="paddle.to_tensor", + method_name="bmm", + dtype_and_x=_get_dtype_and_values_bmm(), +) +def test_paddle_bmm( + dtype_and_x, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + backend_fw, +): + input_dtype, x, y = dtype_and_x + helpers.test_frontend_method( + init_input_dtypes=input_dtype, + backend_to_test=backend_fw, + init_all_as_kwargs_np={"data": x}, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={"y": y}, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + on_device=on_device, + ) + + +# cast +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="paddle.to_tensor", + method_name="cast", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), + ), + dtype=helpers.get_dtypes("valid", full=False), +) +def test_paddle_cast( + dtype_and_x, + dtype, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + backend_fw, +): + input_dtype, x = dtype_and_x + if dtype is None: + dtype = input_dtype + helpers.test_frontend_method( + init_input_dtypes=input_dtype, + backend_to_test=backend_fw, + init_all_as_kwargs_np={ + "data": x[0], + }, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={ + "dtype": dtype[0], + }, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + on_device=on_device, + ) + + +# ceil +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="paddle.to_tensor", + method_name="ceil", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("float"), + ), +) +def test_paddle_ceil( + dtype_and_x, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + backend_fw, +): + input_dtype, x = dtype_and_x + helpers.test_frontend_method( + init_input_dtypes=input_dtype, + backend_to_test=backend_fw, + init_all_as_kwargs_np={ + "data": x[0], + }, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={}, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + on_device=on_device, + ) + + +# ceil_ +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="paddle.to_tensor", + method_name="ceil_", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), + ), + test_inplace=st.just(True), +) +def test_paddle_ceil_( + dtype_and_x, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + backend_fw, +): + input_dtype, x = dtype_and_x + helpers.test_frontend_method( + init_input_dtypes=input_dtype, + backend_to_test=backend_fw, + init_all_as_kwargs_np={ + "data": x[0], + }, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={}, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + on_device=on_device, + ) + + +# cholesky +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="paddle.to_tensor", + method_name="cholesky", + dtype_and_x=_get_dtype_and_square_matrix(), + upper=st.booleans(), +) +def test_paddle_cholesky( + dtype_and_x, + upper, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + backend_fw, +): + input_dtype, x = dtype_and_x + x = np.matmul(x.T, x) + np.identity(x.shape[0]) + + helpers.test_frontend_method( + init_input_dtypes=input_dtype, + backend_to_test=backend_fw, + init_all_as_kwargs_np={ + "data": x, + }, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={"upper": upper}, + frontend=frontend, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + on_device=on_device, + ) + + +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="paddle.to_tensor", + method_name="clip", + input_and_ranges=_get_clip_inputs(), +) +def test_paddle_clip( + input_and_ranges, + frontend, + frontend_method_data, + backend_fw, + init_flags, + method_flags, + on_device, +): + input_dtype, x, min, max = input_and_ranges + helpers.test_frontend_method( + init_input_dtypes=input_dtype, + init_all_as_kwargs_np={ + "data": x[0], + }, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={"min": min, "max": max}, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + backend_to_test=backend_fw, + on_device=on_device, + ) + + +# clip_ +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="paddle.to_tensor", + method_name="clip_", + input_and_ranges=_get_clip_inputs_(), + test_inplace=st.just(True), +) def test_paddle_clip_( input_and_ranges, frontend, frontend_method_data, - backend_fw, + backend_fw, + init_flags, + method_flags, + on_device, +): + input_dtype, x, min_val, max_val = input_and_ranges + if min_val > max_val: + max_value = min_val + min_value = max_val + else: + max_value = max_val + min_value = min_val + + helpers.test_frontend_method( + init_input_dtypes=input_dtype, + init_all_as_kwargs_np={ + "data": x[0], + }, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={"min": min_value, "max": max_value}, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + backend_to_test=backend_fw, + on_device=on_device, + ) + + +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="paddle.to_tensor", + method_name="cond", + dtype_and_x=_get_dtype_and_matrix_non_singular(dtypes=["float32", "float64"]), + p=st.sampled_from([None, "fro", "nuc", np.inf, -np.inf, 1, -1, 2, -2]), +) +def test_paddle_cond( + dtype_and_x, + p, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + backend_fw, +): + input_dtype, x = dtype_and_x + helpers.test_frontend_method( + init_input_dtypes=input_dtype, + backend_to_test=backend_fw, + init_all_as_kwargs_np={ + "data": x[0], + }, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={"p": p}, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + on_device=on_device, + ) + + +# conj +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="paddle.to_tensor", + method_name="conj", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("numeric"), + ), +) +def test_paddle_conj( + dtype_and_x, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + backend_fw, +): + input_dtype, x = dtype_and_x + helpers.test_frontend_method( + init_input_dtypes=input_dtype, + backend_to_test=backend_fw, + init_all_as_kwargs_np={ + "data": x[0], + }, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={}, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + on_device=on_device, + ) + + +# cos +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="paddle.to_tensor", + method_name="cos", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("float"), + ), +) +def test_paddle_cos( + dtype_and_x, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + backend_fw, +): + input_dtype, x = dtype_and_x + helpers.test_frontend_method( + init_input_dtypes=input_dtype, + backend_to_test=backend_fw, + init_all_as_kwargs_np={ + "data": x[0], + }, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={}, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + on_device=on_device, + ) + + +# cosh +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="paddle.to_tensor", + method_name="cosh", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("float"), + ), +) +def test_paddle_cosh( + dtype_and_x, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + backend_fw, +): + input_dtype, x = dtype_and_x + helpers.test_frontend_method( + init_input_dtypes=input_dtype, + backend_to_test=backend_fw, + init_all_as_kwargs_np={ + "data": x[0], + }, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={}, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + on_device=on_device, + ) + + +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="paddle.to_tensor", + method_name="cumprod", + dtype_x_axis=helpers.dtype_values_axis( + available_dtypes=helpers.get_dtypes("float"), + valid_axis=True, + force_int_axis=True, + min_num_dims=1, + min_value=-5, + max_value=5, + ), +) +def test_paddle_cumprod( + dtype_x_axis, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + backend_fw, +): + input_dtype, x, axis = dtype_x_axis + helpers.test_frontend_method( + init_input_dtypes=input_dtype, + backend_to_test=backend_fw, + init_all_as_kwargs_np={ + "data": x[0], + }, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={"dim": axis}, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + on_device=on_device, + ) + + +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="paddle.to_tensor", + method_name="cumsum", + dtype_x_axis=helpers.dtype_values_axis( + available_dtypes=helpers.get_dtypes("float"), + valid_axis=True, + force_int_axis=True, + min_num_dims=1, + min_value=-5, + max_value=5, + ), +) +def test_paddle_cumsum( + dtype_x_axis, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + backend_fw, +): + input_dtype, x, axis = dtype_x_axis + helpers.test_frontend_method( + init_input_dtypes=input_dtype, + backend_to_test=backend_fw, + init_all_as_kwargs_np={ + "data": x[0], + }, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={"axis": axis}, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + on_device=on_device, + ) + + +# deg2rad +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="paddle.to_tensor", + method_name="deg2rad", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("float"), + ), +) +def test_paddle_deg2rad( + dtype_and_x, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + backend_fw, +): + input_dtype, x = dtype_and_x + helpers.test_frontend_method( + init_input_dtypes=input_dtype, + backend_to_test=backend_fw, + init_all_as_kwargs_np={ + "data": x[0], + }, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={}, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + on_device=on_device, + ) + + +# Tests # +# ----- # + + +@given( + dtype_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid", prune_function=False) + ).filter(lambda x: "bfloat16" not in x[0]), +) +def test_paddle_device( + dtype_x, +): + _, data = dtype_x + x = Tensor(data[0]) + x.ivy_array = data[0] + ivy.utils.assertions.check_equal( + x.place, ivy.dev(ivy.array(data[0])), as_array=False + ) + + +# diagonal +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="paddle.to_tensor", + method_name="diagonal", + dtype_and_values=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), + shape=st.shared(helpers.get_shape(min_num_dims=2), key="shape"), + ), + dims_and_offset=helpers.dims_and_offset( + shape=st.shared(helpers.get_shape(min_num_dims=2), key="shape") + ), +) +def test_paddle_diagonal( + dtype_and_values, + dims_and_offset, + frontend, + frontend_method_data, + backend_fw, + init_flags, + method_flags, + on_device, +): + input_dtype, value = dtype_and_values + dim1, dim2, offset = dims_and_offset + input = value[0] + num_dims = len(np.shape(input)) + assume(dim1 != dim2) + if dim1 < 0: + assume(dim1 + num_dims != dim2) + if dim2 < 0: + assume(dim1 != dim2 + num_dims) + helpers.test_frontend_method( + init_input_dtypes=[input_dtype[0]], + init_all_as_kwargs_np={"x": input}, + method_input_dtypes=[input_dtype[0]], + method_all_as_kwargs_np={ + "offset": offset, + "axis1": dim1, + "axis2": dim2, + }, + frontend=frontend, + frontend_method_data=frontend_method_data, + backend_to_test=backend_fw, + init_flags=init_flags, + method_flags=method_flags, + on_device=on_device, + ) + + +# digamma +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="paddle.to_tensor", + method_name="digamma", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("float"), + min_value=1, + max_value=1e5, + ), +) +def test_paddle_digamma( + dtype_and_x, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + backend_fw, +): + input_dtype, x = dtype_and_x + helpers.test_frontend_method( + init_input_dtypes=input_dtype, + backend_to_test=backend_fw, + init_all_as_kwargs_np={ + "data": x[0], + }, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={}, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + on_device=on_device, + ) + + +# dim +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="paddle.to_tensor", + method_name="dim", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), + ), +) +def test_paddle_dim( + dtype_and_x, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + backend_fw, +): + input_dtype, x = dtype_and_x + helpers.test_frontend_method( + init_input_dtypes=input_dtype, + backend_to_test=backend_fw, + init_all_as_kwargs_np={ + "data": x[0], + }, + method_input_dtypes=[], + method_all_as_kwargs_np={}, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + on_device=on_device, + ) + + +# divide +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="paddle.to_tensor", + method_name="divide", + dtypes_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), + num_arrays=2, + shared_dtype=True, + safety_factor_scale="log", + small_abs_safety_factor=32, + ), +) +def test_paddle_divide( + dtypes_and_x, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + backend_fw, +): + input_dtype, x = dtypes_and_x + helpers.test_frontend_method( + init_input_dtypes=input_dtype, + backend_to_test=backend_fw, + init_all_as_kwargs_np={"data": x[0]}, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={"y": x[1]}, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + on_device=on_device, + ) + + +@given( + dtype_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid", prune_function=False) + ).filter(lambda x: "bfloat16" not in x[0]), +) +def test_paddle_dtype( + dtype_x, +): + dtype, data = dtype_x + x = Tensor(data[0]) + x.ivy_array = data[0] + ivy.utils.assertions.check_equal(x.dtype, dtype[0], as_array=False) + + +# eigvals +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="paddle.to_tensor", + method_name="eigvals", + dtype_and_x=_get_dtype_and_square_matrix(), +) +def test_paddle_eigvals( + dtype_and_x, + frontend_method_data, init_flags, method_flags, + frontend, on_device, + backend_fw, ): - input_dtype, x, min_val, max_val = input_and_ranges - if min_val > max_val: - max_value = min_val - min_value = max_val - else: - max_value = max_val - min_value = min_val + input_dtype, x = dtype_and_x + + ret, frontend_ret = helpers.test_frontend_method( + init_input_dtypes=input_dtype, + backend_to_test=backend_fw, + init_all_as_kwargs_np={"data": x}, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={}, + frontend=frontend, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + on_device=on_device, + test_values=False, + ) + + with BackendHandler.update_backend(backend_fw) as ivy_backend: + # check if Tensor or ivy array + try: + ret = ret.ivy_array.to_numpy() + except AttributeError: + ret = ivy_backend.to_numpy(ret) + frontend_ret = [np.asarray(x) for x in frontend_ret] + # Calculate the magnitude of the complex numbers then sort them for testing + ret = np.sort(np.abs(ret)).astype(np.float64) + frontend_ret = np.sort(np.abs(frontend_ret)).astype(np.float64) + + assert_all_close( + ret_np=ret, + ret_from_gt_np=frontend_ret, + backend=backend_fw, + ground_truth_backend=frontend, + atol=1e-2, + rtol=1e-2, + ) + +# equal +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="paddle.to_tensor", + method_name="equal", + dtypes_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), + num_arrays=2, + shared_dtype=True, + ), +) +def test_paddle_equal( + dtypes_and_x, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + backend_fw, +): + input_dtype, x = dtypes_and_x helpers.test_frontend_method( init_input_dtypes=input_dtype, - init_all_as_kwargs_np={ - "data": x[0], - }, + backend_to_test=backend_fw, + init_all_as_kwargs_np={"data": x[0]}, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={"min": min_value, "max": max_value}, + method_all_as_kwargs_np={"y": x[1]}, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, frontend=frontend, - backend_to_test=backend_fw, on_device=on_device, ) +# equal_all @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="cond", - dtype_and_x=_get_dtype_and_matrix_non_singular(dtypes=["float32", "float64"]), - p=st.sampled_from([None, "fro", "nuc", np.inf, -np.inf, 1, -1, 2, -2]), + method_name="equal_all", + dtypes_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), + num_arrays=2, + min_value=-np.inf, + max_value=np.inf, + shared_dtype=True, + safety_factor_scale="log", + small_abs_safety_factor=32, + ), ) -def test_paddle_cond( - dtype_and_x, - p, +def test_paddle_equal_all( + dtypes_and_x, frontend_method_data, init_flags, method_flags, @@ -1494,15 +3064,13 @@ def test_paddle_cond( on_device, backend_fw, ): - input_dtype, x = dtype_and_x + input_dtype, x = dtypes_and_x helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, - init_all_as_kwargs_np={ - "data": x[0], - }, + init_all_as_kwargs_np={"data": x[0]}, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={"p": p}, + method_all_as_kwargs_np={"y": x[1]}, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -1511,16 +3079,16 @@ def test_paddle_cond( ) -# conj +# erf @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="conj", + method_name="erf", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("numeric"), + available_dtypes=helpers.get_dtypes("valid"), ), ) -def test_paddle_conj( +def test_paddle_erf( dtype_and_x, frontend_method_data, init_flags, @@ -1546,16 +3114,16 @@ def test_paddle_conj( ) -# cos +# exp @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="cos", + method_name="exp", dtype_and_x=helpers.dtype_and_values( available_dtypes=helpers.get_dtypes("float"), ), ) -def test_paddle_cos( +def test_paddle_exp( dtype_and_x, frontend_method_data, init_flags, @@ -1581,16 +3149,17 @@ def test_paddle_cos( ) -# cosh +# exp_ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="cosh", + method_name="exp_", dtype_and_x=helpers.dtype_and_values( available_dtypes=helpers.get_dtypes("float"), ), + test_inplace=st.just(True), ) -def test_paddle_cosh( +def test_paddle_exp_( dtype_and_x, frontend_method_data, init_flags, @@ -1616,21 +3185,25 @@ def test_paddle_cosh( ) +# fill_ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="cumprod", - dtype_x_axis=helpers.dtype_values_axis( - available_dtypes=helpers.get_dtypes("float"), - valid_axis=True, - force_int_axis=True, - min_num_dims=1, - min_value=-5, - max_value=5, + method_name="fill_", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), + allow_inf=False, + ), + dtype_v=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), + shape=(1,), + min_value=0, + max_value=10, ), ) -def test_paddle_cumprod( - dtype_x_axis, +def test_paddle_fill_( + dtype_and_x, + dtype_v, frontend_method_data, init_flags, method_flags, @@ -1638,15 +3211,16 @@ def test_paddle_cumprod( on_device, backend_fw, ): - input_dtype, x, axis = dtype_x_axis + input_dtype, x = dtype_and_x + value_dtype, v = dtype_v helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, init_all_as_kwargs_np={ "data": x[0], }, - method_input_dtypes=input_dtype, - method_all_as_kwargs_np={"dim": axis}, + method_input_dtypes=value_dtype, + method_all_as_kwargs_np={"value": v[0].item()}, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -1655,21 +3229,17 @@ def test_paddle_cumprod( ) +# floor @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="cumsum", - dtype_x_axis=helpers.dtype_values_axis( + method_name="floor", + dtype_and_x=helpers.dtype_and_values( available_dtypes=helpers.get_dtypes("float"), - valid_axis=True, - force_int_axis=True, - min_num_dims=1, - min_value=-5, - max_value=5, ), ) -def test_paddle_cumsum( - dtype_x_axis, +def test_paddle_floor( + dtype_and_x, frontend_method_data, init_flags, method_flags, @@ -1677,7 +3247,7 @@ def test_paddle_cumsum( on_device, backend_fw, ): - input_dtype, x, axis = dtype_x_axis + input_dtype, x = dtype_and_x helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, @@ -1685,7 +3255,7 @@ def test_paddle_cumsum( "data": x[0], }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={"axis": axis}, + method_all_as_kwargs_np={}, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -1694,16 +3264,17 @@ def test_paddle_cumsum( ) -# deg2rad +# floor_ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="deg2rad", + method_name="floor_", dtype_and_x=helpers.dtype_and_values( available_dtypes=helpers.get_dtypes("float"), ), + test_inplace=st.just(True), ) -def test_paddle_deg2rad( +def test_paddle_floor_( dtype_and_x, frontend_method_data, init_flags, @@ -1729,89 +3300,89 @@ def test_paddle_deg2rad( ) -# Tests # -# ----- # - - -@given( - dtype_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("valid", prune_function=False) - ).filter(lambda x: "bfloat16" not in x[0]), +# floor_divide +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="paddle.to_tensor", + method_name="floor_divide", + dtypes_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), + num_arrays=2, + min_value=2, + shared_dtype=True, + large_abs_safety_factor=2, + small_abs_safety_factor=2, + safety_factor_scale="linear", + ), ) -def test_paddle_device( - dtype_x, +def test_paddle_floor_divide( + dtypes_and_x, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + backend_fw, ): - _, data = dtype_x - x = Tensor(data[0]) - x.ivy_array = data[0] - ivy.utils.assertions.check_equal( - x.place, ivy.dev(ivy.array(data[0])), as_array=False + input_dtype, x = dtypes_and_x + # Absolute tolerance is 1, + helpers.test_frontend_method( + init_input_dtypes=input_dtype, + backend_to_test=backend_fw, + init_all_as_kwargs_np={"data": x[0]}, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={"y": x[1]}, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + on_device=on_device, + atol_=1, ) -# diagonal @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="diagonal", - dtype_and_values=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("valid"), - shape=st.shared(helpers.get_shape(min_num_dims=2), key="shape"), - ), - dims_and_offset=dims_and_offset( - shape=st.shared(helpers.get_shape(min_num_dims=2), key="shape") + method_name="fmax", + dtypes_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("float"), num_arrays=2, shared_dtype=True ), ) -def test_paddle_diagonal( - dtype_and_values, - dims_and_offset, - frontend, +def test_paddle_fmax( + dtypes_and_x, frontend_method_data, - backend_fw, init_flags, method_flags, + frontend, on_device, + backend_fw, ): - input_dtype, value = dtype_and_values - dim1, dim2, offset = dims_and_offset - input = value[0] - num_dims = len(np.shape(input)) - assume(dim1 != dim2) - if dim1 < 0: - assume(dim1 + num_dims != dim2) - if dim2 < 0: - assume(dim1 != dim2 + num_dims) + input_dtype, x = dtypes_and_x helpers.test_frontend_method( - init_input_dtypes=[input_dtype[0]], - init_all_as_kwargs_np={"x": input}, - method_input_dtypes=[input_dtype[0]], - method_all_as_kwargs_np={ - "offset": offset, - "axis1": dim1, - "axis2": dim2, - }, - frontend=frontend, - frontend_method_data=frontend_method_data, + init_input_dtypes=input_dtype, backend_to_test=backend_fw, + init_all_as_kwargs_np={"data": x[0]}, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={"y": x[1]}, + frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, + frontend=frontend, on_device=on_device, ) -# digamma @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="digamma", - dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("float"), - min_value=1, - max_value=1e5, + method_name="fmin", + dtypes_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("float"), num_arrays=2, shared_dtype=True ), ) -def test_paddle_digamma( - dtype_and_x, +def test_paddle_fmin( + dtypes_and_x, frontend_method_data, init_flags, method_flags, @@ -1819,15 +3390,13 @@ def test_paddle_digamma( on_device, backend_fw, ): - input_dtype, x = dtype_and_x + input_dtype, x = dtypes_and_x helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, - init_all_as_kwargs_np={ - "data": x[0], - }, + init_all_as_kwargs_np={"data": x[0]}, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={}, + method_all_as_kwargs_np={"y": x[1]}, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -1836,16 +3405,19 @@ def test_paddle_digamma( ) -# dim +# frac @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="dim", + method_name="frac", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("valid"), + available_dtypes=helpers.get_dtypes(kind="valid"), + num_arrays=1, + max_value=1e6, + min_value=-1e6, ), ) -def test_paddle_dim( +def test_paddle_frac( dtype_and_x, frontend_method_data, init_flags, @@ -1861,7 +3433,7 @@ def test_paddle_dim( init_all_as_kwargs_np={ "data": x[0], }, - method_input_dtypes=[], + method_input_dtypes=input_dtype, method_all_as_kwargs_np={}, frontend_method_data=frontend_method_data, init_flags=init_flags, @@ -1871,20 +3443,16 @@ def test_paddle_dim( ) -# divide +# gather @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="divide", + method_name="gather", dtypes_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("valid"), - num_arrays=2, - shared_dtype=True, - safety_factor_scale="log", - small_abs_safety_factor=32, + available_dtypes=helpers.get_dtypes("float"), num_arrays=2, shared_dtype=True ), ) -def test_paddle_divide( +def test_paddle_gather( dtypes_and_x, frontend_method_data, init_flags, @@ -1908,29 +3476,21 @@ def test_paddle_divide( ) -@given( - dtype_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("valid", prune_function=False) - ).filter(lambda x: "bfloat16" not in x[0]), -) -def test_paddle_dtype( - dtype_x, -): - dtype, data = dtype_x - x = Tensor(data[0]) - x.ivy_array = data[0] - ivy.utils.assertions.check_equal(x.dtype, dtype[0], as_array=False) - - -# eigvals +# greater_than @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="eigvals", - dtype_and_x=_get_dtype_and_square_matrix(), + method_name="greater_than", + dtypes_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), + num_arrays=2, + shared_dtype=True, + safety_factor_scale="log", + small_abs_safety_factor=32, + ), ) -def test_paddle_eigvals( - dtype_and_x, +def test_paddle_greater_than( + dtypes_and_x, frontend_method_data, init_flags, method_flags, @@ -1938,56 +3498,32 @@ def test_paddle_eigvals( on_device, backend_fw, ): - input_dtype, x = dtype_and_x - - ret, frontend_ret = helpers.test_frontend_method( + input_dtype, x = dtypes_and_x + helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, - init_all_as_kwargs_np={"data": x}, + init_all_as_kwargs_np={"data": x[0]}, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={}, - frontend=frontend, + method_all_as_kwargs_np={"y": x[1]}, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, + frontend=frontend, on_device=on_device, - test_values=False, ) - with BackendHandler.update_backend(backend_fw) as ivy_backend: - # check if Tensor or ivy array - try: - ret = ret.ivy_array.to_numpy() - except AttributeError: - ret = ivy_backend.to_numpy(ret) - frontend_ret = [np.asarray(x) for x in frontend_ret] - # Calculate the magnitude of the complex numbers then sort them for testing - ret = np.sort(np.abs(ret)).astype(np.float64) - frontend_ret = np.sort(np.abs(frontend_ret)).astype(np.float64) - - assert_all_close( - ret_np=ret, - ret_from_gt_np=frontend_ret, - backend=backend_fw, - ground_truth_backend=frontend, - atol=1e-2, - rtol=1e-2, - ) - -# equal +# imag @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="equal", - dtypes_and_x=helpers.dtype_and_values( + method_name="imag", + dtype_and_x=helpers.dtype_and_values( available_dtypes=helpers.get_dtypes("valid"), - num_arrays=2, - shared_dtype=True, ), ) -def test_paddle_equal( - dtypes_and_x, +def test_paddle_imag( + dtype_and_x, frontend_method_data, init_flags, method_flags, @@ -1995,13 +3531,15 @@ def test_paddle_equal( on_device, backend_fw, ): - input_dtype, x = dtypes_and_x + input_dtype, x = dtype_and_x helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, - init_all_as_kwargs_np={"data": x[0]}, + init_all_as_kwargs_np={ + "data": x[0], + }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={"y": x[1]}, + method_all_as_kwargs_np={}, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -2010,23 +3548,21 @@ def test_paddle_equal( ) -# equal_all +# inner @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="equal_all", - dtypes_and_x=helpers.dtype_and_values( + method_name="inner", + dtype_and_x=helpers.dtype_and_values( available_dtypes=helpers.get_dtypes("valid"), + min_value=-10, + max_value=10, num_arrays=2, - min_value=-np.inf, - max_value=np.inf, shared_dtype=True, - safety_factor_scale="log", - small_abs_safety_factor=32, ), ) -def test_paddle_equal_all( - dtypes_and_x, +def test_paddle_inner( + dtype_and_x, frontend_method_data, init_flags, method_flags, @@ -2034,11 +3570,13 @@ def test_paddle_equal_all( on_device, backend_fw, ): - input_dtype, x = dtypes_and_x + input_dtype, x = dtype_and_x helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, - init_all_as_kwargs_np={"data": x[0]}, + init_all_as_kwargs_np={ + "data": x[0], + }, method_input_dtypes=input_dtype, method_all_as_kwargs_np={"y": x[1]}, frontend_method_data=frontend_method_data, @@ -2049,32 +3587,30 @@ def test_paddle_equal_all( ) -# erf +# is_complex @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="erf", + method_name="is_complex", dtype_and_x=helpers.dtype_and_values( available_dtypes=helpers.get_dtypes("valid"), ), ) -def test_paddle_erf( +def test_paddle_is_complex( dtype_and_x, frontend_method_data, init_flags, method_flags, frontend, - on_device, backend_fw, + on_device, ): input_dtype, x = dtype_and_x helpers.test_frontend_method( init_input_dtypes=input_dtype, - backend_to_test=backend_fw, - init_all_as_kwargs_np={ - "data": x[0], - }, + init_all_as_kwargs_np={"data": x[0]}, method_input_dtypes=input_dtype, + backend_to_test=backend_fw, method_all_as_kwargs_np={}, frontend_method_data=frontend_method_data, init_flags=init_flags, @@ -2084,32 +3620,30 @@ def test_paddle_erf( ) -# exp +# is_floating_point @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="exp", + method_name="is_floating_point", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("float"), + available_dtypes=["int16", "int32", "int64", "float32", "float64"], ), ) -def test_paddle_exp( +def test_paddle_is_floating_point( dtype_and_x, frontend_method_data, init_flags, method_flags, frontend, - on_device, backend_fw, + on_device, ): input_dtype, x = dtype_and_x helpers.test_frontend_method( init_input_dtypes=input_dtype, - backend_to_test=backend_fw, - init_all_as_kwargs_np={ - "data": x[0], - }, + init_all_as_kwargs_np={"data": x[0]}, method_input_dtypes=input_dtype, + backend_to_test=backend_fw, method_all_as_kwargs_np={}, frontend_method_data=frontend_method_data, init_flags=init_flags, @@ -2119,17 +3653,17 @@ def test_paddle_exp( ) -# exp_ +# is_tensor @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="exp_", + method_name="is_tensor", dtype_and_x=helpers.dtype_and_values( available_dtypes=helpers.get_dtypes("float"), + num_arrays=1, ), - test_inplace=st.just(True), ) -def test_paddle_exp_( +def test_paddle_is_tensor( dtype_and_x, frontend_method_data, init_flags, @@ -2155,25 +3689,17 @@ def test_paddle_exp_( ) -# fill_ +# isclose @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="fill_", - dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("valid"), - allow_inf=False, - ), - dtype_v=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("valid"), - shape=(1,), - min_value=0, - max_value=10, + method_name="isclose", + dtypes_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), num_arrays=2, shared_dtype=True ), ) -def test_paddle_fill_( - dtype_and_x, - dtype_v, +def test_paddle_isclose( + dtypes_and_x, frontend_method_data, init_flags, method_flags, @@ -2181,16 +3707,13 @@ def test_paddle_fill_( on_device, backend_fw, ): - input_dtype, x = dtype_and_x - value_dtype, v = dtype_v + input_dtype, x = dtypes_and_x helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, - init_all_as_kwargs_np={ - "data": x[0], - }, - method_input_dtypes=value_dtype, - method_all_as_kwargs_np={"value": v[0].item()}, + init_all_as_kwargs_np={"data": x[0]}, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={"y": x[1]}, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -2199,16 +3722,16 @@ def test_paddle_fill_( ) -# floor +# isfinite @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="floor", + method_name="isfinite", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("float"), + available_dtypes=helpers.get_dtypes("valid"), ), ) -def test_paddle_floor( +def test_paddle_isfinite( dtype_and_x, frontend_method_data, init_flags, @@ -2234,17 +3757,16 @@ def test_paddle_floor( ) -# floor_ +# isinf @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="floor_", + method_name="isinf", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("float"), + available_dtypes=helpers.get_dtypes("valid"), ), - test_inplace=st.just(True), ) -def test_paddle_floor_( +def test_paddle_isinf( dtype_and_x, frontend_method_data, init_flags, @@ -2270,23 +3792,17 @@ def test_paddle_floor_( ) -# floor_divide +# isnan @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="floor_divide", - dtypes_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("valid"), - num_arrays=2, - min_value=2, - shared_dtype=True, - large_abs_safety_factor=2, - small_abs_safety_factor=2, - safety_factor_scale="linear", + method_name="isnan", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("float"), ), ) -def test_paddle_floor_divide( - dtypes_and_x, +def test_paddle_isnan( + dtype_and_x, frontend_method_data, init_flags, method_flags, @@ -2294,32 +3810,31 @@ def test_paddle_floor_divide( on_device, backend_fw, ): - input_dtype, x = dtypes_and_x - # Absolute tolerance is 1, + input_dtype, x = dtype_and_x helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, - init_all_as_kwargs_np={"data": x[0]}, + init_all_as_kwargs_np={ + "data": x[0], + }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={"y": x[1]}, + method_all_as_kwargs_np={}, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, frontend=frontend, on_device=on_device, - atol_=1, ) +# lerp @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="fmax", - dtypes_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("float"), num_arrays=2, shared_dtype=True - ), + method_name="lerp", + dtypes_and_x=_get_dtype_and_values_for_lerp(), ) -def test_paddle_fmax( +def test_paddle_lerp( dtypes_and_x, frontend_method_data, init_flags, @@ -2328,13 +3843,16 @@ def test_paddle_fmax( on_device, backend_fw, ): - input_dtype, x = dtypes_and_x + input_dtype, x, y, weight = dtypes_and_x helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, - init_all_as_kwargs_np={"data": x[0]}, + init_all_as_kwargs_np={"data": x}, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={"y": x[1]}, + method_all_as_kwargs_np={ + "y": y, + "weight": weight, + }, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -2343,15 +3861,17 @@ def test_paddle_fmax( ) +# lerp_ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="fmin", + method_name="lerp_", dtypes_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("float"), num_arrays=2, shared_dtype=True + available_dtypes=helpers.get_dtypes("valid"), num_arrays=3, shared_dtype=True ), + test_inplace=st.just(True), ) -def test_paddle_fmin( +def test_paddle_lerp_( dtypes_and_x, frontend_method_data, init_flags, @@ -2366,7 +3886,10 @@ def test_paddle_fmin( backend_to_test=backend_fw, init_all_as_kwargs_np={"data": x[0]}, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={"y": x[1]}, + method_all_as_kwargs_np={ + "y": x[1], + "weight": x[2], + }, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -2375,19 +3898,22 @@ def test_paddle_fmin( ) -# frac +# less_equal @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="frac", + method_name="less_equal", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes(kind="valid"), - num_arrays=1, - max_value=1e6, - min_value=-1e6, + available_dtypes=helpers.get_dtypes("valid"), + num_arrays=2, + allow_inf=False, + large_abs_safety_factor=2, + small_abs_safety_factor=2, + safety_factor_scale="log", + shared_dtype=True, ), ) -def test_paddle_frac( +def test_paddle_less_equal( dtype_and_x, frontend_method_data, init_flags, @@ -2400,11 +3926,9 @@ def test_paddle_frac( helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, - init_all_as_kwargs_np={ - "data": x[0], - }, + init_all_as_kwargs_np={"data": x[0]}, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={}, + method_all_as_kwargs_np={"y": x[1]}, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -2413,16 +3937,16 @@ def test_paddle_frac( ) -# gather +# less_than @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="gather", + method_name="less_than", dtypes_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("float"), num_arrays=2, shared_dtype=True + available_dtypes=helpers.get_dtypes("valid"), num_arrays=2, shared_dtype=True ), ) -def test_paddle_gather( +def test_paddle_less_than( dtypes_and_x, frontend_method_data, init_flags, @@ -2446,21 +3970,17 @@ def test_paddle_gather( ) -# greater_than +# log @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="greater_than", - dtypes_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("valid"), - num_arrays=2, - shared_dtype=True, - safety_factor_scale="log", - small_abs_safety_factor=32, + method_name="log", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("float"), ), ) -def test_paddle_greater_than( - dtypes_and_x, +def test_paddle_log( + dtype_and_x, frontend_method_data, init_flags, method_flags, @@ -2468,13 +3988,15 @@ def test_paddle_greater_than( on_device, backend_fw, ): - input_dtype, x = dtypes_and_x + input_dtype, x = dtype_and_x helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, - init_all_as_kwargs_np={"data": x[0]}, + init_all_as_kwargs_np={ + "data": x[0], + }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={"y": x[1]}, + method_all_as_kwargs_np={}, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -2483,16 +4005,16 @@ def test_paddle_greater_than( ) -# imag +# log10 @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="imag", + method_name="log10", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("valid"), + available_dtypes=helpers.get_dtypes("float"), ), ) -def test_paddle_imag( +def test_paddle_log10( dtype_and_x, frontend_method_data, init_flags, @@ -2518,21 +4040,17 @@ def test_paddle_imag( ) -# inner +# logical_and @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="inner", - dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("valid"), - min_value=-10, - max_value=10, - num_arrays=2, - shared_dtype=True, + method_name="logical_and", + dtypes_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), num_arrays=2, shared_dtype=True ), ) -def test_paddle_inner( - dtype_and_x, +def test_paddle_logical_and( + dtypes_and_x, frontend_method_data, init_flags, method_flags, @@ -2540,13 +4058,11 @@ def test_paddle_inner( on_device, backend_fw, ): - input_dtype, x = dtype_and_x + input_dtype, x = dtypes_and_x helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, - init_all_as_kwargs_np={ - "data": x[0], - }, + init_all_as_kwargs_np={"self": x[0]}, method_input_dtypes=input_dtype, method_all_as_kwargs_np={"y": x[1]}, frontend_method_data=frontend_method_data, @@ -2557,30 +4073,32 @@ def test_paddle_inner( ) -# is_floating_point +# logical_not @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="is_floating_point", + method_name="logical_not", dtype_and_x=helpers.dtype_and_values( - available_dtypes=["int16", "int32", "int64", "float32", "float64"], + available_dtypes=helpers.get_dtypes("valid"), ), ) -def test_paddle_is_floating_point( +def test_paddle_logical_not( dtype_and_x, frontend_method_data, init_flags, method_flags, frontend, - backend_fw, on_device, + backend_fw, ): input_dtype, x = dtype_and_x helpers.test_frontend_method( init_input_dtypes=input_dtype, - init_all_as_kwargs_np={"data": x[0]}, - method_input_dtypes=input_dtype, backend_to_test=backend_fw, + init_all_as_kwargs_np={ + "data": x[0], + }, + method_input_dtypes=input_dtype, method_all_as_kwargs_np={}, frontend_method_data=frontend_method_data, init_flags=init_flags, @@ -2590,18 +4108,17 @@ def test_paddle_is_floating_point( ) -# is_tensor +# logical_or @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="is_tensor", - dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("float"), - num_arrays=1, + method_name="logical_or", + dtypes_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), num_arrays=2, shared_dtype=True ), ) -def test_paddle_is_tensor( - dtype_and_x, +def test_paddle_logical_or( + dtypes_and_x, frontend_method_data, init_flags, method_flags, @@ -2609,15 +4126,13 @@ def test_paddle_is_tensor( on_device, backend_fw, ): - input_dtype, x = dtype_and_x + input_dtype, x = dtypes_and_x helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, - init_all_as_kwargs_np={ - "data": x[0], - }, + init_all_as_kwargs_np={"data": x[0]}, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={}, + method_all_as_kwargs_np={"y": x[1]}, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -2626,16 +4141,16 @@ def test_paddle_is_tensor( ) -# isclose +# logical_xor @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="isclose", + method_name="logical_xor", dtypes_and_x=helpers.dtype_and_values( available_dtypes=helpers.get_dtypes("valid"), num_arrays=2, shared_dtype=True ), ) -def test_paddle_isclose( +def test_paddle_logical_xor( dtypes_and_x, frontend_method_data, init_flags, @@ -2659,17 +4174,23 @@ def test_paddle_isclose( ) -# isfinite +# max @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="isfinite", - dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("valid"), + method_name="max", + dtype_x_axis=helpers.dtype_values_axis( + available_dtypes=st.one_of(helpers.get_dtypes("valid")), + min_axis=-1, + max_axis=0, + min_num_dims=1, + force_int_axis=False, ), + keep_dims=st.booleans(), ) -def test_paddle_isfinite( - dtype_and_x, +def test_paddle_max( + dtype_x_axis, + keep_dims, frontend_method_data, init_flags, method_flags, @@ -2677,68 +4198,73 @@ def test_paddle_isfinite( on_device, backend_fw, ): - input_dtype, x = dtype_and_x + input_dtypes, x, axis = dtype_x_axis helpers.test_frontend_method( - init_input_dtypes=input_dtype, + init_input_dtypes=input_dtypes, backend_to_test=backend_fw, init_all_as_kwargs_np={ - "data": x[0], + "object": x[0], }, - method_input_dtypes=input_dtype, - method_all_as_kwargs_np={}, + method_input_dtypes=input_dtypes, + method_all_as_kwargs_np={ + "axis": axis, + "keepdim": keep_dims, + }, + frontend=frontend, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, - frontend=frontend, on_device=on_device, ) -# isinf +# mean @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="isinf", - dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("valid"), - ), + method_name="mean", + dtype_and_x=_statistical_dtype_values(function="mean"), + keepdim=st.booleans(), ) -def test_paddle_isinf( +def test_paddle_mean( dtype_and_x, + keepdim, + frontend, + backend_fw, frontend_method_data, init_flags, method_flags, - frontend, on_device, - backend_fw, ): - input_dtype, x = dtype_and_x + input_dtype, x, axis = dtype_and_x helpers.test_frontend_method( init_input_dtypes=input_dtype, - backend_to_test=backend_fw, - init_all_as_kwargs_np={ - "data": x[0], + init_all_as_kwargs_np={"data": x[0]}, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={ + "axis": axis, + "keepdim": keepdim, }, - method_input_dtypes=input_dtype, - method_all_as_kwargs_np={}, + frontend=frontend, frontend_method_data=frontend_method_data, init_flags=init_flags, + backend_to_test=backend_fw, method_flags=method_flags, - frontend=frontend, on_device=on_device, ) -# isnan @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="isnan", + method_name="minimum", dtype_and_x=helpers.dtype_and_values( available_dtypes=helpers.get_dtypes("float"), + num_arrays=2, + shared_dtype=True, ), ) -def test_paddle_isnan( +def test_paddle_minimum( dtype_and_x, frontend_method_data, init_flags, @@ -2751,11 +4277,9 @@ def test_paddle_isnan( helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, - init_all_as_kwargs_np={ - "data": x[0], - }, + init_all_as_kwargs_np={"data": x[0]}, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={}, + method_all_as_kwargs_np={"y": x[1]}, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -2764,15 +4288,20 @@ def test_paddle_isnan( ) -# lerp @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="lerp", - dtypes_and_x=_get_dtype_and_values_for_lerp(), + method_name="mod", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), + num_arrays=2, + shared_dtype=True, + min_value=0, + exclude_min=True, + ), ) -def test_paddle_lerp( - dtypes_and_x, +def test_paddle_mod( + dtype_and_x, frontend_method_data, init_flags, method_flags, @@ -2780,16 +4309,13 @@ def test_paddle_lerp( on_device, backend_fw, ): - input_dtype, x, y, weight = dtypes_and_x + input_dtype, x = dtype_and_x helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, - init_all_as_kwargs_np={"data": x}, + init_all_as_kwargs_np={"data": x[0]}, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={ - "y": y, - "weight": weight, - }, + method_all_as_kwargs_np={"y": x[1]}, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -2798,18 +4324,18 @@ def test_paddle_lerp( ) -# lerp_ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="lerp_", - dtypes_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("valid"), num_arrays=3, shared_dtype=True + method_name="multiply", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("float"), + num_arrays=2, + shared_dtype=True, ), - test_inplace=st.just(True), ) -def test_paddle_lerp_( - dtypes_and_x, +def test_paddle_multiply( + dtype_and_x, frontend_method_data, init_flags, method_flags, @@ -2817,15 +4343,16 @@ def test_paddle_lerp_( on_device, backend_fw, ): - input_dtype, x = dtypes_and_x + input_dtype, x = dtype_and_x helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, - init_all_as_kwargs_np={"data": x[0]}, + init_all_as_kwargs_np={ + "value": x[0], + }, method_input_dtypes=input_dtype, method_all_as_kwargs_np={ "y": x[1], - "weight": x[2], }, frontend_method_data=frontend_method_data, init_flags=init_flags, @@ -2835,27 +4362,37 @@ def test_paddle_lerp_( ) -# less_equal +@given( + dtype_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid", prune_function=False), + ).filter(lambda x: "bfloat16" not in x[0]), +) +def test_paddle_ndim( + dtype_x, +): + _, data = dtype_x + x = Tensor(data[0]) + ivy.utils.assertions.check_equal(x.ndim, data[0].ndim, as_array=False) + + +# neg @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="less_equal", + method_name="neg", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("valid"), - num_arrays=2, + available_dtypes=helpers.get_dtypes("float"), + min_value=-1e04, + max_value=1e04, allow_inf=False, - large_abs_safety_factor=2, - small_abs_safety_factor=2, - safety_factor_scale="log", - shared_dtype=True, ), ) -def test_paddle_less_equal( +def test_paddle_neg( dtype_and_x, + frontend, frontend_method_data, init_flags, method_flags, - frontend, on_device, backend_fw, ): @@ -2863,9 +4400,11 @@ def test_paddle_less_equal( helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, - init_all_as_kwargs_np={"data": x[0]}, + init_all_as_kwargs_np={ + "data": x[0], + }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={"y": x[1]}, + method_all_as_kwargs_np={}, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -2874,17 +4413,19 @@ def test_paddle_less_equal( ) -# less_than +# nonzero @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="less_than", - dtypes_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("valid"), num_arrays=2, shared_dtype=True + method_name="nonzero", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes(kind="float"), + min_num_dims=1, + allow_inf=True, ), ) -def test_paddle_less_than( - dtypes_and_x, +def test_paddle_nonzero( + dtype_and_x, frontend_method_data, init_flags, method_flags, @@ -2892,13 +4433,15 @@ def test_paddle_less_than( on_device, backend_fw, ): - input_dtype, x = dtypes_and_x + input_dtype, x = dtype_and_x helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, - init_all_as_kwargs_np={"data": x[0]}, + init_all_as_kwargs_np={ + "data": x[0], + }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={"y": x[1]}, + method_all_as_kwargs_np={}, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -2907,16 +4450,18 @@ def test_paddle_less_than( ) -# log +# not_equal @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="log", + method_name="not_equal", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("float"), + available_dtypes=helpers.get_dtypes(kind="valid"), + num_arrays=2, + shared_dtype=True, ), ) -def test_paddle_log( +def test_paddle_not_equal( dtype_and_x, frontend_method_data, init_flags, @@ -2930,44 +4475,48 @@ def test_paddle_log( init_input_dtypes=input_dtype, backend_to_test=backend_fw, init_all_as_kwargs_np={ - "data": x[0], + "x": x[0], }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={}, + method_all_as_kwargs_np={ + "y": x[1], + }, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, frontend=frontend, on_device=on_device, + rtol_=1e-02, + atol_=1e-02, ) -# log10 @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="log10", + method_name="numel", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("float"), + available_dtypes=helpers.get_dtypes("valid"), + min_num_dims=1, ), ) -def test_paddle_log10( +def test_paddle_numel( dtype_and_x, frontend_method_data, init_flags, method_flags, frontend, - on_device, backend_fw, + on_device, ): input_dtype, x = dtype_and_x helpers.test_frontend_method( init_input_dtypes=input_dtype, - backend_to_test=backend_fw, init_all_as_kwargs_np={ "data": x[0], }, method_input_dtypes=input_dtype, + backend_to_test=backend_fw, method_all_as_kwargs_np={}, frontend_method_data=frontend_method_data, init_flags=init_flags, @@ -2977,17 +4526,19 @@ def test_paddle_log10( ) -# logical_and +# numpy @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="logical_and", - dtypes_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("valid"), num_arrays=2, shared_dtype=True + method_name="numpy", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), + min_num_dims=2, + min_dim_size=2, ), ) -def test_paddle_logical_and( - dtypes_and_x, +def test_paddle_numpy( + dtype_and_x, frontend_method_data, init_flags, method_flags, @@ -2995,13 +4546,15 @@ def test_paddle_logical_and( on_device, backend_fw, ): - input_dtype, x = dtypes_and_x + input_dtype, x = dtype_and_x helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, - init_all_as_kwargs_np={"self": x[0]}, - method_input_dtypes=input_dtype, - method_all_as_kwargs_np={"y": x[1]}, + init_all_as_kwargs_np={ + "data": x[0], + }, + method_input_dtypes=[], + method_all_as_kwargs_np={}, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -3010,17 +4563,20 @@ def test_paddle_logical_and( ) -# logical_not +# pow @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="logical_not", - dtype_and_x=helpers.dtype_and_values( + method_name="pow", + dtypes_and_x=helpers.dtype_and_values( available_dtypes=helpers.get_dtypes("valid"), + num_arrays=2, + allow_inf=False, + shared_dtype=True, ), ) -def test_paddle_logical_not( - dtype_and_x, +def test_paddle_pow( + dtypes_and_x, frontend_method_data, init_flags, method_flags, @@ -3028,15 +4584,13 @@ def test_paddle_logical_not( on_device, backend_fw, ): - input_dtype, x = dtype_and_x + input_dtype, x = dtypes_and_x helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, - init_all_as_kwargs_np={ - "data": x[0], - }, + init_all_as_kwargs_np={"data": x[0]}, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={}, + method_all_as_kwargs_np={"y": x[1]}, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -3045,17 +4599,25 @@ def test_paddle_logical_not( ) -# logical_or +# prod @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="logical_or", - dtypes_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("valid"), num_arrays=2, shared_dtype=True + method_name="prod", + dtype_x_axis=helpers.dtype_values_axis( + available_dtypes=helpers.get_dtypes("valid"), + min_num_dims=1, + min_value=-5, + max_value=5, + valid_axis=True, + force_int_axis=True, + allow_inf=False, ), + keep_dims=st.booleans(), ) -def test_paddle_logical_or( - dtypes_and_x, +def test_paddle_prod( + dtype_x_axis, + keep_dims, frontend_method_data, init_flags, method_flags, @@ -3063,13 +4625,17 @@ def test_paddle_logical_or( on_device, backend_fw, ): - input_dtype, x = dtypes_and_x + input_dtype, x, axis = dtype_x_axis helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, init_all_as_kwargs_np={"data": x[0]}, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={"y": x[1]}, + method_all_as_kwargs_np={ + "axis": axis, + "keepdim": keep_dims, + "dtype": x[0].dtype, + }, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -3078,17 +4644,17 @@ def test_paddle_logical_or( ) -# logical_xor +# rad2deg @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="logical_xor", - dtypes_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("valid"), num_arrays=2, shared_dtype=True + method_name="rad2deg", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("float"), ), ) -def test_paddle_logical_xor( - dtypes_and_x, +def test_paddle_rad2deg( + dtype_and_x, frontend_method_data, init_flags, method_flags, @@ -3096,13 +4662,15 @@ def test_paddle_logical_xor( on_device, backend_fw, ): - input_dtype, x = dtypes_and_x + input_dtype, x = dtype_and_x helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, - init_all_as_kwargs_np={"data": x[0]}, + init_all_as_kwargs_np={ + "data": x[0], + }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={"y": x[1]}, + method_all_as_kwargs_np={}, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -3111,23 +4679,19 @@ def test_paddle_logical_xor( ) -# max @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="max", - dtype_x_axis=helpers.dtype_values_axis( - available_dtypes=st.one_of(helpers.get_dtypes("valid")), - min_axis=-1, - max_axis=0, + method_name="real", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes(kind="valid"), + num_arrays=2, min_num_dims=1, - force_int_axis=False, + allow_inf=True, ), - keep_dims=st.booleans(), ) -def test_paddle_max( - dtype_x_axis, - keep_dims, +def test_paddle_real( + dtype_and_x, frontend_method_data, init_flags, method_flags, @@ -3135,73 +4699,68 @@ def test_paddle_max( on_device, backend_fw, ): - input_dtypes, x, axis = dtype_x_axis + input_dtype, x = dtype_and_x helpers.test_frontend_method( - init_input_dtypes=input_dtypes, + init_input_dtypes=input_dtype, backend_to_test=backend_fw, init_all_as_kwargs_np={ - "object": x[0], - }, - method_input_dtypes=input_dtypes, - method_all_as_kwargs_np={ - "axis": axis, - "keepdim": keep_dims, + "data": x[0], }, - frontend=frontend, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={}, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, + frontend=frontend, on_device=on_device, ) -# mean +# reciprocal @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="mean", - dtype_and_x=_statistical_dtype_values(function="mean"), - keepdim=st.booleans(), + method_name="reciprocal", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), + ), ) -def test_paddle_mean( +def test_paddle_reciprocal( dtype_and_x, - keepdim, - frontend, - backend_fw, frontend_method_data, init_flags, method_flags, + frontend, on_device, + backend_fw, ): - input_dtype, x, axis = dtype_and_x + input_dtype, x = dtype_and_x helpers.test_frontend_method( init_input_dtypes=input_dtype, - init_all_as_kwargs_np={"data": x[0]}, - method_input_dtypes=input_dtype, - method_all_as_kwargs_np={ - "axis": axis, - "keepdim": keepdim, + backend_to_test=backend_fw, + init_all_as_kwargs_np={ + "data": x[0], }, - frontend=frontend, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={}, frontend_method_data=frontend_method_data, init_flags=init_flags, - backend_to_test=backend_fw, method_flags=method_flags, + frontend=frontend, on_device=on_device, ) +# reciprocal_ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="minimum", + method_name="reciprocal_", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("float"), - num_arrays=2, - shared_dtype=True, + available_dtypes=helpers.get_dtypes("valid"), ), ) -def test_paddle_minimum( +def test_paddle_reciprocal_( dtype_and_x, frontend_method_data, init_flags, @@ -3214,9 +4773,11 @@ def test_paddle_minimum( helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, - init_all_as_kwargs_np={"data": x[0]}, + init_all_as_kwargs_np={ + "data": x[0], + }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={"y": x[1]}, + method_all_as_kwargs_np={}, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -3225,19 +4786,22 @@ def test_paddle_minimum( ) +# remainder @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="mod", + method_name="remainder", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("valid"), + available_dtypes=helpers.get_dtypes("float"), num_arrays=2, + allow_inf=False, + large_abs_safety_factor=2, + small_abs_safety_factor=2, + safety_factor_scale="log", shared_dtype=True, - min_value=0, - exclude_min=True, ), ) -def test_paddle_mod( +def test_paddle_remainder( dtype_and_x, frontend_method_data, init_flags, @@ -3261,17 +4825,19 @@ def test_paddle_mod( ) +# remainder_ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="multiply", + method_name="remainder_", dtype_and_x=helpers.dtype_and_values( available_dtypes=helpers.get_dtypes("float"), num_arrays=2, shared_dtype=True, ), + test_inplace=st.just(True), ) -def test_paddle_multiply( +def test_paddle_remainder_( dtype_and_x, frontend_method_data, init_flags, @@ -3299,41 +4865,27 @@ def test_paddle_multiply( ) -@given( - dtype_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("valid", prune_function=False), - ).filter(lambda x: "bfloat16" not in x[0]), -) -def test_paddle_ndim( - dtype_x, -): - _, data = dtype_x - x = Tensor(data[0]) - ivy.utils.assertions.check_equal(x.ndim, data[0].ndim, as_array=False) - - -# neg +# reshape @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="neg", - dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("float"), - min_value=-1e04, - max_value=1e04, - allow_inf=False, - ), + method_name="reshape", + dtype_x_shape=_reshape_helper(), ) -def test_paddle_neg( - dtype_and_x, - frontend, +def test_paddle_reshape( + dtype_x_shape, frontend_method_data, init_flags, method_flags, + frontend, on_device, backend_fw, ): - input_dtype, x = dtype_and_x + input_dtype, x, shape = dtype_x_shape + assume(len(shape) != 0) + shape = { + "shape": shape, + } helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, @@ -3341,7 +4893,7 @@ def test_paddle_neg( "data": x[0], }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={}, + method_all_as_kwargs_np=shape, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -3350,19 +4902,15 @@ def test_paddle_neg( ) -# nonzero +# reshape_ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="nonzero", - dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes(kind="float"), - min_num_dims=1, - allow_inf=True, - ), + method_name="reshape_", + dtype_x_shape=_reshape_helper(), ) -def test_paddle_nonzero( - dtype_and_x, +def test_paddle_reshape_( + dtype_x_shape, frontend_method_data, init_flags, method_flags, @@ -3370,7 +4918,11 @@ def test_paddle_nonzero( on_device, backend_fw, ): - input_dtype, x = dtype_and_x + input_dtype, x, shape = dtype_x_shape + assume(len(shape) != 0) + shape = { + "shape": shape, + } helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, @@ -3378,7 +4930,7 @@ def test_paddle_nonzero( "data": x[0], }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={}, + method_all_as_kwargs_np=shape, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -3387,19 +4939,21 @@ def test_paddle_nonzero( ) -# not_equal +# rot90 @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="not_equal", - dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes(kind="valid"), - num_arrays=2, - shared_dtype=True, + method_name="rot90", + dtype_m_k_axes=_get_dtype_values_k_axes_for_rot90( + available_dtypes=helpers.get_dtypes("valid"), + min_num_dims=3, + max_num_dims=6, + min_dim_size=1, + max_dim_size=10, ), ) -def test_paddle_not_equal( - dtype_and_x, +def test_paddle_rot90( + dtype_m_k_axes, frontend_method_data, init_flags, method_flags, @@ -3407,53 +4961,53 @@ def test_paddle_not_equal( on_device, backend_fw, ): - input_dtype, x = dtype_and_x + input_dtype, values, k, axes = dtype_m_k_axes + helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, init_all_as_kwargs_np={ - "x": x[0], + "data": values, }, method_input_dtypes=input_dtype, method_all_as_kwargs_np={ - "y": x[1], + "k": k, + "axes": axes, }, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, frontend=frontend, on_device=on_device, - rtol_=1e-02, - atol_=1e-02, ) +# round_ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="numel", + method_name="round_", dtype_and_x=helpers.dtype_and_values( available_dtypes=helpers.get_dtypes("valid"), - min_num_dims=1, ), ) -def test_paddle_numel( +def test_paddle_round_( dtype_and_x, frontend_method_data, init_flags, method_flags, frontend, - backend_fw, on_device, + backend_fw, ): input_dtype, x = dtype_and_x helpers.test_frontend_method( init_input_dtypes=input_dtype, + backend_to_test=backend_fw, init_all_as_kwargs_np={ "data": x[0], }, method_input_dtypes=input_dtype, - backend_to_test=backend_fw, method_all_as_kwargs_np={}, frontend_method_data=frontend_method_data, init_flags=init_flags, @@ -3463,18 +5017,16 @@ def test_paddle_numel( ) -# numpy +# rsqrt @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="numpy", + method_name="rsqrt", dtype_and_x=helpers.dtype_and_values( available_dtypes=helpers.get_dtypes("valid"), - min_num_dims=2, - min_dim_size=2, ), ) -def test_paddle_numpy( +def test_paddle_rsqrt( dtype_and_x, frontend_method_data, init_flags, @@ -3490,7 +5042,7 @@ def test_paddle_numpy( init_all_as_kwargs_np={ "data": x[0], }, - method_input_dtypes=[], + method_input_dtypes=input_dtype, method_all_as_kwargs_np={}, frontend_method_data=frontend_method_data, init_flags=init_flags, @@ -3500,20 +5052,18 @@ def test_paddle_numpy( ) -# pow +# rsqrt_ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="pow", - dtypes_and_x=helpers.dtype_and_values( + method_name="rsqrt_", + dtype_and_x=helpers.dtype_and_values( available_dtypes=helpers.get_dtypes("valid"), - num_arrays=2, - allow_inf=False, - shared_dtype=True, ), + test_inplace=st.just(True), ) -def test_paddle_pow( - dtypes_and_x, +def test_paddle_rsqrt_( + dtype_and_x, frontend_method_data, init_flags, method_flags, @@ -3521,13 +5071,15 @@ def test_paddle_pow( on_device, backend_fw, ): - input_dtype, x = dtypes_and_x + input_dtype, x = dtype_and_x helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, - init_all_as_kwargs_np={"data": x[0]}, + init_all_as_kwargs_np={ + "data": x[0], + }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={"y": x[1]}, + method_all_as_kwargs_np={}, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -3536,61 +5088,29 @@ def test_paddle_pow( ) -# prod -@handle_frontend_method( - class_tree=CLASS_TREE, - init_tree="paddle.to_tensor", - method_name="prod", - dtype_x_axis=helpers.dtype_values_axis( - available_dtypes=helpers.get_dtypes("valid"), - min_num_dims=1, - min_value=-5, - max_value=5, - valid_axis=True, - force_int_axis=True, - allow_inf=False, - ), - keep_dims=st.booleans(), -) -def test_paddle_prod( - dtype_x_axis, - keep_dims, - frontend_method_data, - init_flags, - method_flags, - frontend, - on_device, - backend_fw, -): - input_dtype, x, axis = dtype_x_axis - helpers.test_frontend_method( - init_input_dtypes=input_dtype, - backend_to_test=backend_fw, - init_all_as_kwargs_np={"data": x[0]}, - method_input_dtypes=input_dtype, - method_all_as_kwargs_np={ - "axis": axis, - "keepdim": keep_dims, - "dtype": x[0].dtype, - }, - frontend_method_data=frontend_method_data, - init_flags=init_flags, - method_flags=method_flags, - frontend=frontend, - on_device=on_device, +@given( + dtype_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid", prune_function=False), + ret_shape=True, + ).filter(lambda x: "bfloat16" not in x[0]), +) +def test_paddle_shape(dtype_x): + _, data, shape = dtype_x + x = Tensor(data[0]) + ivy.utils.assertions.check_equal( + x.ivy_array.shape, ivy.Shape(shape), as_array=False ) -# rad2deg @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="rad2deg", + method_name="sign", dtype_and_x=helpers.dtype_and_values( available_dtypes=helpers.get_dtypes("float"), ), ) -def test_paddle_rad2deg( +def test_paddle_sign( dtype_and_x, frontend_method_data, init_flags, @@ -3616,18 +5136,16 @@ def test_paddle_rad2deg( ) +# sin @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="real", + method_name="sin", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes(kind="valid"), - num_arrays=2, - min_num_dims=1, - allow_inf=True, + available_dtypes=helpers.get_dtypes("float"), ), ) -def test_paddle_real( +def test_paddle_sin( dtype_and_x, frontend_method_data, init_flags, @@ -3653,16 +5171,16 @@ def test_paddle_real( ) -# reciprocal +# sinh @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="reciprocal", + method_name="sinh", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("valid"), + available_dtypes=helpers.get_dtypes("float"), ), ) -def test_paddle_reciprocal( +def test_paddle_sinh( dtype_and_x, frontend_method_data, init_flags, @@ -3688,17 +5206,23 @@ def test_paddle_reciprocal( ) -# reciprocal_ +# sort @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="reciprocal_", - dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("valid"), + method_name="sort", + dtype_x_axis=helpers.dtype_values_axis( + available_dtypes=st.one_of(helpers.get_dtypes("float")), + min_axis=-1, + max_axis=0, + min_num_dims=1, + force_int_axis=True, ), + descending=st.booleans(), ) -def test_paddle_reciprocal_( - dtype_and_x, +def test_paddle_sort( + dtype_x_axis, + descending, frontend_method_data, init_flags, method_flags, @@ -3706,39 +5230,36 @@ def test_paddle_reciprocal_( on_device, backend_fw, ): - input_dtype, x = dtype_and_x + input_dtypes, x, axis = dtype_x_axis helpers.test_frontend_method( - init_input_dtypes=input_dtype, + init_input_dtypes=input_dtypes, backend_to_test=backend_fw, init_all_as_kwargs_np={ - "data": x[0], + "object": x[0], }, - method_input_dtypes=input_dtype, - method_all_as_kwargs_np={}, + method_input_dtypes=input_dtypes, + method_all_as_kwargs_np={ + "axis": axis, + "descending": descending, + }, + frontend=frontend, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, - frontend=frontend, on_device=on_device, ) -# remainder +# split @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="remainder", + method_name="split", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("float"), - num_arrays=2, - allow_inf=False, - large_abs_safety_factor=2, - small_abs_safety_factor=2, - safety_factor_scale="log", - shared_dtype=True, + available_dtypes=helpers.get_dtypes("valid"), ), ) -def test_paddle_remainder( +def test_paddle_split( dtype_and_x, frontend_method_data, init_flags, @@ -3751,9 +5272,11 @@ def test_paddle_remainder( helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, - init_all_as_kwargs_np={"data": x[0]}, + init_all_as_kwargs_np={ + "data": x[0], + }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={"y": x[1]}, + method_all_as_kwargs_np={}, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -3762,19 +5285,16 @@ def test_paddle_remainder( ) -# remainder_ +# sqrt @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="remainder_", + method_name="sqrt", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("float"), - num_arrays=2, - shared_dtype=True, + available_dtypes=helpers.get_dtypes("valid"), ), - test_inplace=st.just(True), ) -def test_paddle_remainder_( +def test_paddle_sqrt( dtype_and_x, frontend_method_data, init_flags, @@ -3788,12 +5308,10 @@ def test_paddle_remainder_( init_input_dtypes=input_dtype, backend_to_test=backend_fw, init_all_as_kwargs_np={ - "value": x[0], + "data": x[0], }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={ - "y": x[1], - }, + method_all_as_kwargs_np={}, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -3802,41 +5320,32 @@ def test_paddle_remainder_( ) -# rot90 +# sqrt_ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="rot90", - dtype_m_k_axes=_get_dtype_values_k_axes_for_rot90( + method_name="sqrt_", + dtype_x=helpers.dtype_and_values( available_dtypes=helpers.get_dtypes("valid"), - min_num_dims=3, - max_num_dims=6, - min_dim_size=1, - max_dim_size=10, ), + test_inplace=st.just(True), ) -def test_paddle_rot90( - dtype_m_k_axes, +def test_paddle_sqrt_( + dtype_x, + frontend, frontend_method_data, init_flags, method_flags, - frontend, on_device, backend_fw, ): - input_dtype, values, k, axes = dtype_m_k_axes - + input_dtype, x = dtype_x helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, - init_all_as_kwargs_np={ - "data": values, - }, + init_all_as_kwargs_np={"data": x[0]}, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={ - "k": k, - "axes": axes, - }, + method_all_as_kwargs_np={}, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -3845,16 +5354,16 @@ def test_paddle_rot90( ) -# round_ +# square @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="round_", + method_name="square", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("valid"), + available_dtypes=helpers.get_dtypes("float"), ), ) -def test_paddle_round_( +def test_paddle_square( dtype_and_x, frontend_method_data, init_flags, @@ -3880,17 +5389,25 @@ def test_paddle_round_( ) -# rsqrt +# squeeze_ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="rsqrt", - dtype_and_x=helpers.dtype_and_values( + method_name="squeeze_", + dtype_value=helpers.dtype_and_values( available_dtypes=helpers.get_dtypes("valid"), + shape=st.shared(helpers.get_shape(), key="shape"), + ), + axis=helpers.get_axis( + shape=st.shared(helpers.get_shape(), key="shape"), + allow_neg=True, + force_int=True, ), + test_inplace=st.just(True), ) -def test_paddle_rsqrt( - dtype_and_x, +def test_paddle_squeeze_( + dtype_value, + axis, frontend_method_data, init_flags, method_flags, @@ -3898,7 +5415,7 @@ def test_paddle_rsqrt( on_device, backend_fw, ): - input_dtype, x = dtype_and_x + input_dtype, x = dtype_value helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, @@ -3906,7 +5423,9 @@ def test_paddle_rsqrt( "data": x[0], }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={}, + method_all_as_kwargs_np={ + "axis": axis, + }, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -3915,34 +5434,40 @@ def test_paddle_rsqrt( ) -# rsqrt_ +# stanh @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="rsqrt_", + method_name="stanh", dtype_and_x=helpers.dtype_and_values( available_dtypes=helpers.get_dtypes("valid"), ), - test_inplace=st.just(True), + scale_a=st.floats(1e-5, 1e5), + scale_b=st.floats(1e-5, 1e5), ) -def test_paddle_rsqrt_( +def test_paddle_stanh( dtype_and_x, frontend_method_data, + scale_a, + scale_b, init_flags, method_flags, frontend, - on_device, backend_fw, + on_device, ): input_dtype, x = dtype_and_x helpers.test_frontend_method( init_input_dtypes=input_dtype, - backend_to_test=backend_fw, init_all_as_kwargs_np={ "data": x[0], }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={}, + backend_to_test=backend_fw, + method_all_as_kwargs_np={ + "scale_a": scale_a, + "scale_b": scale_b, + }, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -3951,65 +5476,54 @@ def test_paddle_rsqrt_( ) -@given( - dtype_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("valid", prune_function=False), - ret_shape=True, - ).filter(lambda x: "bfloat16" not in x[0]), -) -def test_paddle_shape(dtype_x): - _, data, shape = dtype_x - x = Tensor(data[0]) - ivy.utils.assertions.check_equal( - x.ivy_array.shape, ivy.Shape(shape), as_array=False - ) - - +# std @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="sign", - dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("float"), - ), + method_name="std", + dtype_and_x=_statistical_dtype_values(function="std"), + keepdim=st.booleans(), ) -def test_paddle_sign( +def test_paddle_std( dtype_and_x, + keepdim, + frontend, + backend_fw, frontend_method_data, init_flags, method_flags, - frontend, on_device, - backend_fw, ): - input_dtype, x = dtype_and_x + input_dtype, x, axis, correction = dtype_and_x helpers.test_frontend_method( init_input_dtypes=input_dtype, - backend_to_test=backend_fw, - init_all_as_kwargs_np={ - "data": x[0], - }, + init_all_as_kwargs_np={"data": x[0]}, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={}, + method_all_as_kwargs_np={ + "axis": axis, + "unbiased": bool(correction), + "keepdim": keepdim, + }, + frontend=frontend, frontend_method_data=frontend_method_data, init_flags=init_flags, + backend_to_test=backend_fw, method_flags=method_flags, - frontend=frontend, on_device=on_device, ) -# sin +# subtract @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="sin", - dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("float"), + method_name="subtract", + dtypes_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("float"), num_arrays=2, shared_dtype=True ), ) -def test_paddle_sin( - dtype_and_x, +def test_paddle_subtract( + dtypes_and_x, frontend_method_data, init_flags, method_flags, @@ -4017,15 +5531,13 @@ def test_paddle_sin( on_device, backend_fw, ): - input_dtype, x = dtype_and_x + input_dtype, x = dtypes_and_x helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, - init_all_as_kwargs_np={ - "data": x[0], - }, + init_all_as_kwargs_np={"data": x[0]}, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={}, + method_all_as_kwargs_np={"y": x[1]}, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -4034,17 +5546,18 @@ def test_paddle_sin( ) -# sinh +# subtract_ @handle_frontend_method( class_tree=CLASS_TREE, - init_tree="paddle.to_tensor", - method_name="sinh", - dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("float"), + init_tree="paddle.to_tensor", + method_name="subtract_", + dtypes_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), num_arrays=2, shared_dtype=True ), + test_inplace=st.just(True), ) -def test_paddle_sinh( - dtype_and_x, +def test_paddle_subtract_( + dtypes_and_x, frontend_method_data, init_flags, method_flags, @@ -4052,15 +5565,13 @@ def test_paddle_sinh( on_device, backend_fw, ): - input_dtype, x = dtype_and_x + input_dtype, x = dtypes_and_x helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, - init_all_as_kwargs_np={ - "data": x[0], - }, + init_all_as_kwargs_np={"data": x[0]}, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={}, + method_all_as_kwargs_np={"y": x[1]}, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -4069,23 +5580,18 @@ def test_paddle_sinh( ) -# sort +# t @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="sort", - dtype_x_axis=helpers.dtype_values_axis( - available_dtypes=st.one_of(helpers.get_dtypes("float")), - min_axis=-1, - max_axis=0, - min_num_dims=1, - force_int_axis=True, + method_name="t", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), + max_num_dims=2, ), - descending=st.booleans(), ) -def test_paddle_sort( - dtype_x_axis, - descending, +def test_paddle_t( + dtype_and_x, frontend_method_data, init_flags, method_flags, @@ -4093,36 +5599,33 @@ def test_paddle_sort( on_device, backend_fw, ): - input_dtypes, x, axis = dtype_x_axis + input_dtype, x = dtype_and_x helpers.test_frontend_method( - init_input_dtypes=input_dtypes, - backend_to_test=backend_fw, + init_input_dtypes=input_dtype, init_all_as_kwargs_np={ - "object": x[0], - }, - method_input_dtypes=input_dtypes, - method_all_as_kwargs_np={ - "axis": axis, - "descending": descending, + "data": x[0], }, - frontend=frontend, + backend_to_test=backend_fw, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={}, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, + frontend=frontend, on_device=on_device, ) -# split +# tanh @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="split", + method_name="tanh", dtype_and_x=helpers.dtype_and_values( available_dtypes=helpers.get_dtypes("valid"), ), ) -def test_paddle_split( +def test_paddle_tanh( dtype_and_x, frontend_method_data, init_flags, @@ -4148,16 +5651,16 @@ def test_paddle_split( ) -# sqrt +# tanh_ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="sqrt", + method_name="tanh_", dtype_and_x=helpers.dtype_and_values( available_dtypes=helpers.get_dtypes("valid"), ), ) -def test_paddle_sqrt( +def test_paddle_tanh_( dtype_and_x, frontend_method_data, init_flags, @@ -4183,30 +5686,30 @@ def test_paddle_sqrt( ) -# sqrt_ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="sqrt_", - dtype_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("valid"), + method_name="acos", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("float"), ), - test_inplace=st.just(True), ) -def test_paddle_sqrt_( - dtype_x, - frontend, +def test_paddle_tensor_acos( + dtype_and_x, frontend_method_data, init_flags, method_flags, + frontend, on_device, backend_fw, ): - input_dtype, x = dtype_x + input_dtype, x = dtype_and_x helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, - init_all_as_kwargs_np={"data": x[0]}, + init_all_as_kwargs_np={ + "data": x[0], + }, method_input_dtypes=input_dtype, method_all_as_kwargs_np={}, frontend_method_data=frontend_method_data, @@ -4217,16 +5720,16 @@ def test_paddle_sqrt_( ) -# square +# add @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="square", + method_name="add", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("float"), + available_dtypes=helpers.get_dtypes("valid"), num_arrays=2, shared_dtype=True ), ) -def test_paddle_square( +def test_paddle_tensor_add( dtype_and_x, frontend_method_data, init_flags, @@ -4243,7 +5746,7 @@ def test_paddle_square( "data": x[0], }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={}, + method_all_as_kwargs_np={"y": x[1]}, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -4252,41 +5755,48 @@ def test_paddle_square( ) -# squeeze_ +# chunk @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="squeeze_", - dtype_value=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("valid"), - shape=st.shared(helpers.get_shape(), key="shape"), + method_name="chunk", + dtype_x_axis=helpers.dtype_values_axis( + available_dtypes=helpers.get_dtypes("float"), + min_num_dims=1, + min_value=0.1, + max_value=1e02, + force_int_axis=True, + valid_axis=True, ), - axis=helpers.get_axis( - shape=st.shared(helpers.get_shape(), key="shape"), - allow_neg=True, - force_int=True, + chunks=st.integers( + min_value=1, + max_value=8, ), - test_inplace=st.just(True), ) -def test_paddle_squeeze_( - dtype_value, - axis, +def test_paddle_tensor_chunk( + dtype_x_axis, + chunks, + frontend, frontend_method_data, init_flags, method_flags, - frontend, on_device, backend_fw, ): - input_dtype, x = dtype_value + input_dtype, x, axis = dtype_x_axis + is_remainder = x[0].shape[axis] % chunks != 0 + axis_solvable = len(x[0].shape) + axis < 0 + if is_remainder or axis_solvable: + assume(False) helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, init_all_as_kwargs_np={ - "data": x[0], + "value": x[0], }, method_input_dtypes=input_dtype, method_all_as_kwargs_np={ + "chunks": chunks, "axis": axis, }, frontend_method_data=frontend_method_data, @@ -4297,96 +5807,112 @@ def test_paddle_squeeze_( ) -# stanh +# cov @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="stanh", - dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("valid"), + method_name="cov", + dtype_x1_corr_cov=_get_dtype_value1_value2_cov( + available_dtypes=helpers.get_dtypes("float"), + min_num_dims=2, + max_num_dims=2, + min_dim_size=2, + max_dim_size=5, + min_value=1, + max_value=1e10, + abs_smallest_val=0.01, + large_abs_safety_factor=2, + safety_factor_scale="log", ), - scale_a=st.floats(1e-5, 1e5), - scale_b=st.floats(1e-5, 1e5), ) -def test_paddle_stanh( - dtype_and_x, +def test_paddle_tensor_cov( + dtype_x1_corr_cov, frontend_method_data, - scale_a, - scale_b, init_flags, method_flags, frontend, backend_fw, on_device, ): - input_dtype, x = dtype_and_x + dtype, x, rowvar, ddof, fweights, aweights = dtype_x1_corr_cov helpers.test_frontend_method( - init_input_dtypes=input_dtype, + init_input_dtypes=["float64", "int64", "float64"], init_all_as_kwargs_np={ - "data": x[0], + "data": x, }, - method_input_dtypes=input_dtype, + method_input_dtypes=["int64", "float64"], backend_to_test=backend_fw, method_all_as_kwargs_np={ - "scale_a": scale_a, - "scale_b": scale_b, + "rowvar": rowvar, + "ddof": ddof, + "fweights": fweights, + "aweights": aweights, }, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, + rtol_=1e-3, + atol_=1e-3, frontend=frontend, on_device=on_device, ) -# std +# expand @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="std", - dtype_and_x=_statistical_dtype_values(function="std"), - keepdim=st.booleans(), + method_name="expand", + dtype_x_shape=dtypes_x_shape(), ) -def test_paddle_std( - dtype_and_x, - keepdim, - frontend, - backend_fw, +def test_paddle_tensor_expand( + dtype_x_shape, frontend_method_data, init_flags, method_flags, + frontend, on_device, + backend_fw, ): - input_dtype, x, axis, correction = dtype_and_x + input_dtype, x, shape = dtype_x_shape helpers.test_frontend_method( init_input_dtypes=input_dtype, - init_all_as_kwargs_np={"data": x[0]}, + backend_to_test=backend_fw, + init_all_as_kwargs_np={ + "data": x[0], + }, method_input_dtypes=input_dtype, method_all_as_kwargs_np={ - "axis": axis, - "unbiased": bool(correction), - "keepdim": keepdim, + "shape": shape, }, - frontend=frontend, frontend_method_data=frontend_method_data, init_flags=init_flags, - backend_to_test=backend_fw, method_flags=method_flags, + frontend=frontend, on_device=on_device, ) -# subtract +# flatten @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="subtract", - dtypes_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("float"), num_arrays=2, shared_dtype=True + method_name="flatten", + dtype_value=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), + shape=st.shared(helpers.get_shape(), key="shape"), + ), + axes=helpers.get_axis( + shape=st.shared(helpers.get_shape(), key="shape"), + min_size=2, + max_size=2, + unique=False, + force_tuple=True, ), ) -def test_paddle_subtract( - dtypes_and_x, +def test_paddle_tensor_flatten( + dtype_value, + axes, frontend_method_data, init_flags, method_flags, @@ -4394,13 +5920,18 @@ def test_paddle_subtract( on_device, backend_fw, ): - input_dtype, x = dtypes_and_x + input_dtype, x = dtype_value helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, - init_all_as_kwargs_np={"data": x[0]}, + init_all_as_kwargs_np={ + "data": x[0], + }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={"y": x[1]}, + method_all_as_kwargs_np={ + "start_axis": axes[0], + "stop_axis": axes[1], + }, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -4409,17 +5940,19 @@ def test_paddle_subtract( ) -# subtract_ +# floor_mod @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="subtract_", + method_name="floor_mod", dtypes_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("valid"), num_arrays=2, shared_dtype=True + available_dtypes=helpers.get_dtypes("valid"), + num_arrays=2, + min_value=2, + shared_dtype=True, ), - test_inplace=st.just(True), ) -def test_paddle_subtract_( +def test_paddle_tensor_floor_mod( dtypes_and_x, frontend_method_data, init_flags, @@ -4443,53 +5976,57 @@ def test_paddle_subtract_( ) -# t @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="t", + method_name="heaviside", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("valid"), - max_num_dims=2, + available_dtypes=helpers.get_dtypes("float"), + num_arrays=2, + allow_inf=False, + large_abs_safety_factor=2, + small_abs_safety_factor=2, + safety_factor_scale="log", + shared_dtype=True, ), ) -def test_paddle_t( +def test_paddle_tensor_heaviside( dtype_and_x, frontend_method_data, init_flags, method_flags, frontend, - on_device, backend_fw, + on_device, ): input_dtype, x = dtype_and_x helpers.test_frontend_method( init_input_dtypes=input_dtype, + backend_to_test=backend_fw, init_all_as_kwargs_np={ - "data": x[0], + "x": x[0], }, - backend_to_test=backend_fw, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={}, - frontend_method_data=frontend_method_data, + method_all_as_kwargs_np={ + "y": x[1], + }, init_flags=init_flags, method_flags=method_flags, + frontend_method_data=frontend_method_data, frontend=frontend, on_device=on_device, ) -# tanh +# matmul @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="tanh", - dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("valid"), - ), + method_name="matmul", + dtype_tensor1_tensor2=_get_dtype_and_multiplicative_matrices(), ) -def test_paddle_tanh( - dtype_and_x, +def test_paddle_tensor_matmul( + dtype_tensor1_tensor2, frontend_method_data, init_flags, method_flags, @@ -4497,15 +6034,20 @@ def test_paddle_tanh( on_device, backend_fw, ): - input_dtype, x = dtype_and_x + dtype, tensor1, tensor2, transpose_x, transpose_y = dtype_tensor1_tensor2 + helpers.test_frontend_method( - init_input_dtypes=input_dtype, + init_input_dtypes=dtype, backend_to_test=backend_fw, init_all_as_kwargs_np={ - "data": x[0], + "data": tensor1, + }, + method_input_dtypes=dtype, + method_all_as_kwargs_np={ + "y": tensor2, + "transpose_x": transpose_x, + "transpose_y": transpose_y, }, - method_input_dtypes=input_dtype, - method_all_as_kwargs_np={}, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -4514,17 +6056,24 @@ def test_paddle_tanh( ) -# tanh_ +# squeeze @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="tanh_", - dtype_and_x=helpers.dtype_and_values( + method_name="squeeze", + dtype_value=helpers.dtype_and_values( available_dtypes=helpers.get_dtypes("valid"), + shape=st.shared(helpers.get_shape(), key="shape"), + ), + axis=helpers.get_axis( + shape=st.shared(helpers.get_shape(), key="shape"), + allow_neg=True, + force_int=True, ), ) -def test_paddle_tanh_( - dtype_and_x, +def test_paddle_tensor_squeeze( + dtype_value, + axis, frontend_method_data, init_flags, method_flags, @@ -4532,7 +6081,7 @@ def test_paddle_tanh_( on_device, backend_fw, ): - input_dtype, x = dtype_and_x + input_dtype, x = dtype_value helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, @@ -4540,7 +6089,9 @@ def test_paddle_tanh_( "data": x[0], }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={}, + method_all_as_kwargs_np={ + "axis": axis, + }, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -4549,7 +6100,7 @@ def test_paddle_tanh_( ) -# cholesky_solve +# _solve @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", diff --git a/ivy_tests/test_ivy/test_frontends/test_pandas/test_dataframe.py b/ivy_tests/test_ivy/test_frontends/test_pandas/test_dataframe.py index 074137130b30e..cd079b2375f49 100644 --- a/ivy_tests/test_ivy/test_frontends/test_pandas/test_dataframe.py +++ b/ivy_tests/test_ivy/test_frontends/test_pandas/test_dataframe.py @@ -24,6 +24,7 @@ def test_pandas_series_abs( frontend_method_data, init_flags, method_flags, + backend_fw, on_device, ): # todo add castable dtypes for output @@ -39,6 +40,7 @@ def test_pandas_series_abs( init_flags=init_flags, method_flags=method_flags, frontend=frontend, + backend_to_test=backend_fw, on_device=on_device, ) @@ -138,6 +140,7 @@ def test_pandas_series_to_numpy( na_values, copy, frontend_method_data, + backend_fw, init_flags, method_flags, on_device, @@ -157,5 +160,6 @@ def test_pandas_series_to_numpy( init_flags=init_flags, method_flags=method_flags, frontend=frontend, + backend_to_test=backend_fw, on_device=on_device, ) diff --git a/ivy_tests/test_ivy/test_frontends/test_pandas/test_series.py b/ivy_tests/test_ivy/test_frontends/test_pandas/test_series.py index 796045cb93a76..bbb520bb280b3 100644 --- a/ivy_tests/test_ivy/test_frontends/test_pandas/test_series.py +++ b/ivy_tests/test_ivy/test_frontends/test_pandas/test_series.py @@ -21,6 +21,7 @@ def test_pandas_series_abs( dtype_x, frontend, + backend_fw, frontend_method_data, init_flags, method_flags, @@ -38,6 +39,7 @@ def test_pandas_series_abs( init_flags=init_flags, method_flags=method_flags, frontend=frontend, + backend_to_test=backend_fw, on_device=on_device, ) diff --git a/ivy_tests/test_ivy/test_frontends/test_scipy/__init__.py b/ivy_tests/test_ivy/test_frontends/test_scipy/__init__.py index 3b53dda915477..85480fbc9a089 100644 --- a/ivy_tests/test_ivy/test_frontends/test_scipy/__init__.py +++ b/ivy_tests/test_ivy/test_frontends/test_scipy/__init__.py @@ -5,7 +5,8 @@ def convscipy(argument): - """Convert NativeClass in argument to ivy frontend counterpart for scipy.""" + """Convert NativeClass in argument to ivy frontend counterpart for + scipy.""" if isinstance(argument, NativeClass): return scipy_classes_to_ivy_classes.get(argument._native_class) return argument diff --git a/ivy_tests/test_ivy/test_frontends/test_scipy/test_linalg/test_linalg.py b/ivy_tests/test_ivy/test_frontends/test_scipy/test_linalg/test_linalg.py index a8e405bcbe01b..4b6f51e059d64 100644 --- a/ivy_tests/test_ivy/test_frontends/test_scipy/test_linalg/test_linalg.py +++ b/ivy_tests/test_ivy/test_frontends/test_scipy/test_linalg/test_linalg.py @@ -154,7 +154,7 @@ def test_scipy_eigh_tridiagonal( available_dtypes=helpers.get_dtypes("float"), small_abs_safety_factor=2, safety_factor_scale="log", - shape=helpers.ints(min_value=2, max_value=20).map(lambda x: tuple([x, x])), + shape=helpers.ints(min_value=2, max_value=20).map(lambda x: (x, x)), ).filter(lambda x: np.linalg.cond(x[1][0].tolist()) < 1 / sys.float_info.epsilon), test_with_out=st.just(False), ) @@ -312,7 +312,7 @@ def test_scipy_pinv( available_dtypes=helpers.get_dtypes("float"), min_value=0.1, max_value=10, - shape=helpers.ints(min_value=2, max_value=5).map(lambda x: tuple([x, x])), + shape=helpers.ints(min_value=2, max_value=5).map(lambda x: (x, x)), ), full_matrices=st.booleans(), compute_uv=st.booleans(), @@ -366,7 +366,7 @@ def test_scipy_svd( available_dtypes=helpers.get_dtypes("float"), min_value=0.1, max_value=50, - shape=helpers.ints(min_value=2, max_value=5).map(lambda x: tuple([x, x])), + shape=helpers.ints(min_value=2, max_value=5).map(lambda x: (x, x)), ), check_finite=st.booleans(), test_with_out=st.just(False), diff --git a/ivy_tests/test_ivy/test_frontends/test_sklearn/test_metrics/test_classification.py b/ivy_tests/test_ivy/test_frontends/test_sklearn/test_metrics/test_classification.py index 7977c77df3d03..1d8342188abee 100644 --- a/ivy_tests/test_ivy/test_frontends/test_sklearn/test_metrics/test_classification.py +++ b/ivy_tests/test_ivy/test_frontends/test_sklearn/test_metrics/test_classification.py @@ -1,5 +1,5 @@ from hypothesis import strategies as st - +import torch import ivy_tests.test_ivy.helpers as helpers from ivy_tests.test_ivy.helpers import handle_frontend_test import numpy as np @@ -43,3 +43,68 @@ def test_sklearn_accuracy_score( normalize=normalize, sample_weight=None, ) + + +@handle_frontend_test( + fn_tree="sklearn.metrics.recall_score", + arrays_and_dtypes=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("integer"), + num_arrays=2, + min_value=0, + max_value=1, # Recall score is for binary classification + shared_dtype=True, + shape=(helpers.ints(min_value=2, max_value=5)), + ), + sample_weight=st.lists( + st.floats(min_value=0.1, max_value=1), min_size=2, max_size=5 + ), +) +def test_sklearn_recall_score( + arrays_and_dtypes, + on_device, + fn_tree, + frontend, + test_flags, + backend_fw, + sample_weight, +): + dtypes, values = arrays_and_dtypes + # Ensure the values are binary by rounding and converting to int + for i in range(2): + values[i] = np.round(values[i]).astype(int) + + # Adjust sample_weight to have the correct length + sample_weight = np.array(sample_weight).astype(float) + if len(sample_weight) != len(values[0]): + # If sample_weight is shorter, extend it with ones + sample_weight = np.pad( + sample_weight, + (0, max(0, len(values[0]) - len(sample_weight))), + "constant", + constant_values=1.0, + ) + # If sample_weight is longer, truncate it + sample_weight = sample_weight[: len(values[0])] + + # Detach tensors if they require grad before converting to NumPy arrays + if backend_fw == "torch": + values = [ + ( + value.detach().numpy() + if isinstance(value, torch.Tensor) and value.requires_grad + else value + ) + for value in values + ] + + helpers.test_frontend_function( + input_dtypes=dtypes, + backend_to_test=backend_fw, + test_flags=test_flags, + fn_tree=fn_tree, + frontend=frontend, + on_device=on_device, + y_true=values[0], + y_pred=values[1], + sample_weight=sample_weight, + ) diff --git a/ivy_tests/test_ivy/test_frontends/test_sklearn/test_tree/test_tree.py b/ivy_tests/test_ivy/test_frontends/test_sklearn/test_tree/test_tree.py new file mode 100644 index 0000000000000..350d6d208e671 --- /dev/null +++ b/ivy_tests/test_ivy/test_frontends/test_sklearn/test_tree/test_tree.py @@ -0,0 +1,44 @@ +from ivy.functional.frontends.sklearn.tree import DecisionTreeClassifier as ivy_DTC +import ivy +from hypothesis import given +import ivy_tests.test_ivy.helpers as helpers + + +# --- Helpers --- # +# --------------- # + + +# helper functions +def _get_sklearn_predict(X, y, max_depth, DecisionTreeClassifier): + clf = DecisionTreeClassifier(max_depth=max_depth, random_state=0) + clf.fit(X, y) + return clf.predict + + +# --- Main --- # +# ------------ # + + +# todo: integrate with already existing strats and generalize +@given( + X=helpers.array_values( + shape=(5, 2), + dtype=helpers.get_dtypes("float", prune_function=False), + safety_factor_scale="log", + ), + y=helpers.array_values( + shape=(5,), + dtype=helpers.get_dtypes("signed_integer", prune_function=False), + safety_factor_scale="log", + ), + max_depth=helpers.ints(max_value=5, min_value=1), +) +def test_sklearn_tree_predict(X, y, max_depth): + try: + from sklearn.tree import DecisionTreeClassifier as sklearn_DTC + except ImportError: + print("sklearn not installed, skipping test_sklearn_tree_predict") + return + sklearn_pred = _get_sklearn_predict(X, y, max_depth, sklearn_DTC)(X) + ivy_pred = _get_sklearn_predict(ivy.array(X), ivy.array(y), max_depth, ivy_DTC)(X) + helpers.assert_same_type_and_shape([sklearn_pred, ivy_pred]) diff --git a/ivy_tests/test_ivy/test_frontends/test_sklearn/test_utils/test_multiclass.py b/ivy_tests/test_ivy/test_frontends/test_sklearn/test_utils/test_multiclass.py index 28c93f02fa8a2..f989c8d21d1d3 100644 --- a/ivy_tests/test_ivy/test_frontends/test_sklearn/test_utils/test_multiclass.py +++ b/ivy_tests/test_ivy/test_frontends/test_sklearn/test_utils/test_multiclass.py @@ -5,7 +5,7 @@ # not suitable for usual frontend testing @pytest.mark.parametrize( - "y, label", + ("y", "label"), [ ([1.2], "continuous"), ([1], "binary"), diff --git a/ivy_tests/test_ivy/test_frontends/test_tensorflow/__init__.py b/ivy_tests/test_ivy/test_frontends/test_tensorflow/__init__.py index 58227bfafc4e0..2b7118d75a902 100644 --- a/ivy_tests/test_ivy/test_frontends/test_tensorflow/__init__.py +++ b/ivy_tests/test_ivy/test_frontends/test_tensorflow/__init__.py @@ -6,7 +6,8 @@ def convtensor(argument): - """Convert NativeClass in argument to ivy frontend counterpart for tensorflow.""" + """Convert NativeClass in argument to ivy frontend counterpart for + tensorflow.""" if isinstance(argument, NativeClass): return tensorflow_classes_to_ivy_classes.get(argument._native_class) return argument diff --git a/ivy_tests/test_ivy/test_frontends/test_tensorflow/test___operators__.py b/ivy_tests/test_ivy/test_frontends/test_tensorflow/test___operators__.py new file mode 100644 index 0000000000000..c5728e0085ee3 --- /dev/null +++ b/ivy_tests/test_ivy/test_frontends/test_tensorflow/test___operators__.py @@ -0,0 +1,38 @@ +# global +from hypothesis import strategies as st + +# local +import ivy_tests.test_ivy.helpers as helpers +from ivy_tests.test_ivy.helpers.testing_helpers import handle_frontend_test + + +# add +@handle_frontend_test( + fn_tree="tensorflow.__operators__.add", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("numeric"), + num_arrays=2, + shared_dtype=True, + ), + test_with_out=st.just(False), +) +def test_tensorflow___operators___add( + *, + dtype_and_x, + frontend, + test_flags, + fn_tree, + backend_fw, + on_device, +): + input_dtype, x = dtype_and_x + helpers.test_frontend_function( + input_dtypes=input_dtype, + backend_to_test=backend_fw, + frontend=frontend, + test_flags=test_flags, + fn_tree=fn_tree, + on_device=on_device, + x=x[0], + y=x[1], + ) diff --git a/ivy_tests/test_ivy/test_frontends/test_tensorflow/test_general_functions.py b/ivy_tests/test_ivy/test_frontends/test_tensorflow/test_general_functions.py index 2fa0da6a6c272..bec86d46301a2 100644 --- a/ivy_tests/test_ivy/test_frontends/test_tensorflow/test_general_functions.py +++ b/ivy_tests/test_ivy/test_frontends/test_tensorflow/test_general_functions.py @@ -270,6 +270,40 @@ def _reshape_helper(draw): return x, dtype, reshape_shape +# sequence_mask +@st.composite +def _sequence_mask_helper(draw): + max_val = draw(st.integers(min_value=1, max_value=100000)) + in_dtype, lens = draw( + helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), + num_arrays=1, + min_value=-max_val, + max_value=max_val, + ) + ) + + max_len = draw(st.integers(min_value=max_val, max_value=max_val)) + dtype = draw( + st.sampled_from( + [ + "float16", + "uint8", + "complex128", + "bool", + "float64", + "int8", + "int16", + "complex64", + "float32", + "int32", + "int64", + ] + ) + ) + return in_dtype, lens, max_len, dtype + + @st.composite def _slice_helper(draw): dtype, x, shape = draw( @@ -1703,6 +1737,34 @@ def test_tensorflow_searchsorted( ) +@handle_frontend_test( + fn_tree="tensorflow.sequence_mask", + dtype_lens_maxlen=_sequence_mask_helper(), + test_with_out=st.just(False), +) +def test_tensorflow_sequence_mask( + *, + dtype_lens_maxlen, + frontend, + test_flags, + fn_tree, + on_device, + backend_fw, +): + input_dtype, lens, max_len, dtype = dtype_lens_maxlen + helpers.test_frontend_function( + input_dtypes=input_dtype, + backend_to_test=backend_fw, + frontend=frontend, + test_flags=test_flags, + fn_tree=fn_tree, + on_device=on_device, + lengths=lens[0], + maxlen=max_len, + dtype=dtype, + ) + + # shape @handle_frontend_test( fn_tree="tensorflow.shape", diff --git a/ivy_tests/test_ivy/test_frontends/test_tensorflow/test_keras/test_activations.py b/ivy_tests/test_ivy/test_frontends/test_tensorflow/test_keras/test_activations.py index c0b7eaa4a2ce9..ed861effd7787 100644 --- a/ivy_tests/test_ivy/test_frontends/test_tensorflow/test_keras/test_activations.py +++ b/ivy_tests/test_ivy/test_frontends/test_tensorflow/test_keras/test_activations.py @@ -6,6 +6,7 @@ import ivy import ivy_tests.test_ivy.helpers as helpers from ivy_tests.test_ivy.helpers import handle_frontend_test +from typing import Optional try: import tensorflow as tf @@ -34,7 +35,7 @@ def simple_test_two_function( frontend: str, fn_str: str, dtype_data: str, - rtol_: float = None, + rtol_: Optional[float] = None, atol_: float = 1e-06, ivy_submodules: list = [], framework_submodules: list = [], @@ -90,7 +91,7 @@ def simple_test_two_function( available_dtypes=helpers.get_dtypes("valid"), min_value=0, max_value=10, - shape=helpers.ints(min_value=2, max_value=5).map(lambda x: tuple([x, x])), + shape=helpers.ints(min_value=2, max_value=5).map(lambda x: (x, x)), ), ) def test_tensorflow_deserialize( @@ -205,7 +206,7 @@ def test_tensorflow_gelu( available_dtypes=helpers.get_dtypes("float"), min_value=0, max_value=10, - shape=helpers.ints(min_value=2, max_value=5).map(lambda x: tuple([x, x])), + shape=helpers.ints(min_value=2, max_value=5).map(lambda x: (x, x)), ), ) def test_tensorflow_get(fn_name, dtype_and_data): @@ -362,7 +363,7 @@ def test_tensorflow_selu( available_dtypes=helpers.get_dtypes("valid"), min_value=0, max_value=10, - shape=helpers.ints(min_value=2, max_value=5).map(lambda x: tuple([x, x])), + shape=helpers.ints(min_value=2, max_value=5).map(lambda x: (x, x)), ), ) def test_tensorflow_serialize( diff --git a/ivy_tests/test_ivy/test_frontends/test_tensorflow/test_keras/test_backend.py b/ivy_tests/test_ivy/test_frontends/test_tensorflow/test_keras/test_backend.py new file mode 100644 index 0000000000000..21ba947042729 --- /dev/null +++ b/ivy_tests/test_ivy/test_frontends/test_tensorflow/test_keras/test_backend.py @@ -0,0 +1,374 @@ +# global +from hypothesis import assume, strategies as st +from ivy.func_wrapper import output_to_native_arrays + +# local +import ivy_tests.test_ivy.helpers as helpers +from ivy_tests.test_ivy.helpers import handle_frontend_test +from ivy_tests.test_ivy.test_functional.test_experimental.test_core.test_linalg import ( + _generate_dot_dtype_and_arrays, +) +from ivy_tests.test_ivy.test_frontends.test_tensorflow.test_nn import ( + _generate_bias_data, +) +from ivy_tests.test_ivy.test_functional.test_experimental.test_nn.test_layers import ( + _lstm_helper, +) +import ivy +from ivy.functional.frontends.tensorflow.func_wrapper import ( + inputs_to_ivy_arrays, + outputs_to_frontend_arrays, +) +import ivy.functional.frontends.tensorflow as tf_frontend + + +# --- Helpers --- # +# --------------- # + + +@st.composite +def _x_and_filters( + draw, + dtypes, + data_format, + padding=None, + stride_min=1, + stride_max=4, + dilation_min=1, + dilation_max=4, + type: str = "depthwise", +): + data_format = draw(data_format) + dtype = draw(dtypes) + dim = 2 if type in ["depthwise", "separable"] else 4 + if padding is None: + padding = (st.sampled_from(["same", "valid"]),) + padding = draw(padding) + dilations = draw( + st.one_of( + st.integers(dilation_min, dilation_max), + st.lists( + st.integers(dilation_min, dilation_max), min_size=dim, max_size=dim + ), + ) + ) + fdilations = [dilations] * dim if isinstance(dilations, int) else dilations + if type in ["depthwise", "separable"]: + # if any value in dilations is greater than 1, tensorflow implements + # depthwise_covn2d as an atrous depthwise convolution, in which case all values + # in strides must be equal to 1. + if any(x > 1 for x in fdilations): + stride = 1 + else: + stride = draw(st.integers(stride_min, stride_max)) + else: + stride = draw( + st.one_of( + st.integers(stride_min, stride_max), + st.lists( + st.integers(stride_min, stride_max), min_size=dim, max_size=dim + ), + ) + ) + if dim == 2: + min_x_height = 1 + min_x_width = 1 + filter_shape = draw( + st.tuples( + helpers.ints(min_value=3, max_value=5), + helpers.ints(min_value=3, max_value=5), + helpers.ints(min_value=1, max_value=3), + helpers.ints(min_value=1, max_value=3), + ) + ) + min_x_height = filter_shape[0] + (filter_shape[0] - 1) * (fdilations[0] - 1) + min_x_width = filter_shape[1] + (filter_shape[1] - 1) * (fdilations[1] - 1) + d_in = filter_shape[2] + if data_format == "channels_last": + x_shape = draw( + st.tuples( + helpers.ints(min_value=1, max_value=5), + helpers.ints(min_value=min_x_height, max_value=100), + helpers.ints(min_value=min_x_width, max_value=100), + helpers.ints(min_value=d_in, max_value=d_in), + ) + ) + else: + x_shape = draw( + st.tuples( + helpers.ints(min_value=1, max_value=5), + helpers.ints(min_value=d_in, max_value=d_in), + helpers.ints(min_value=min_x_height, max_value=100), + helpers.ints(min_value=min_x_width, max_value=100), + ) + ) + x = draw( + helpers.array_values(dtype=dtype[0], shape=x_shape, min_value=0, max_value=1) + ) + filters = draw( + helpers.array_values( + dtype=dtype[0], shape=filter_shape, min_value=0, max_value=1 + ) + ) + if type in ["depthwise", "separable"]: + stride = (stride, stride) + if isinstance(dilations, int): + dilations = (dilations,) * dim + return dtype, x, filters, dilations, data_format, stride, padding + + +# --- Main --- # +# ------------ # + + +@handle_frontend_test( + fn_tree="tensorflow.keras.backend.dot", + data=_generate_dot_dtype_and_arrays(min_num_dims=2), +) +def test_tensorflow_dot(*, data, on_device, fn_tree, frontend, test_flags, backend_fw): + (input_dtypes, x) = data + return helpers.test_frontend_function( + input_dtypes=input_dtypes, + test_flags=test_flags, + backend_to_test=backend_fw, + on_device=on_device, + frontend=frontend, + fn_tree=fn_tree, + rtol=0.5, + atol=0.5, + x=x[0], + y=x[1], + ) + + +@handle_frontend_test( + fn_tree="tensorflow.keras.backend.bias_add", + data=_generate_bias_data(keras_backend_fn=True), + test_with_out=st.just(False), +) +def test_tensorflow_keras_backend_bias_add( + *, + data, + frontend, + test_flags, + fn_tree, + backend_fw, + on_device, +): + data_format, dtype, x, bias = data + helpers.test_frontend_function( + input_dtypes=dtype * 2, + backend_to_test=backend_fw, + frontend=frontend, + test_flags=test_flags, + fn_tree=fn_tree, + on_device=on_device, + x=x[0], + bias=bias, + data_format=data_format, + ) + + +@handle_frontend_test( + fn_tree="tensorflow.keras.backend.depthwise_conv2d", + x_f_d_df=_x_and_filters( + dtypes=helpers.get_dtypes("float", full=False), + data_format=st.sampled_from(["channels_last"]), + padding=st.sampled_from(["valid", "same"]), + type="depthwise", + ), + test_with_out=st.just(False), +) +def test_tensorflow_keras_backend_depthwise_conv2d( + *, + x_f_d_df, + frontend, + test_flags, + fn_tree, + backend_fw, + on_device, +): + input_dtype, x, filters, dilation, data_format, stride, padding = x_f_d_df + helpers.test_frontend_function( + input_dtypes=input_dtype, + backend_to_test=backend_fw, + frontend=frontend, + test_flags=test_flags, + fn_tree=fn_tree, + on_device=on_device, + x=x, + depthwise_kernel=filters, + strides=stride, + padding=padding, + data_format=data_format, + dilation_rate=dilation, + ) + + +# mean +@handle_frontend_test( + fn_tree="tensorflow.keras.backend.mean", + dtype_x_axis=helpers.dtype_values_axis( + available_dtypes=helpers.get_dtypes("float"), + force_int_axis=True, + valid_axis=True, + min_num_dims=1, + large_abs_safety_factor=24, + small_abs_safety_factor=24, + safety_factor_scale="log", + ), + keepdims=st.booleans(), + test_with_out=st.just(False), +) +def test_tensorflow_keras_backend_mean( + *, + dtype_x_axis, + keepdims, + frontend, + test_flags, + fn_tree, + backend_fw, + on_device, +): + input_dtype, x, axis = dtype_x_axis + helpers.test_frontend_function( + input_dtypes=input_dtype, + backend_to_test=backend_fw, + frontend=frontend, + test_flags=test_flags, + fn_tree=fn_tree, + atol=1e-1, + rtol=1e-1, + on_device=on_device, + x=x[0], + axis=axis, + keepdims=keepdims, + ) + + +@handle_frontend_test( + fn_tree="tensorflow.keras.backend.rnn", + rnn_args=_lstm_helper(), + test_with_out=st.just(False), +) +def test_tensorflow_keras_backend_rnn( + *, + rnn_args, + frontend, + test_flags, + fn_tree, + backend_fw, + on_device, +): + ( + input_dtypes, + inputs, + kernel_orig, + recurrent_kernel_orig, + bias_orig, + recurrent_bias_orig, + initial_states, + go_backwards, + mask, + unroll, + input_length, + time_major, + zero_output_for_mask, + return_all_outputs, + ) = rnn_args + + # unsupported dtype of float16 is in our _lstm_step function + # so can't be inferred through ivy.function_unsupported_devices_and_dtypes + assume(not (backend_fw == "torch" and input_dtypes[0] == "float16")) + + def _lstm_step(cell_inputs, cell_states): + nonlocal kernel_orig, recurrent_kernel_orig, bias_orig, recurrent_bias_orig + kernel = ivy.array(kernel_orig) + recurrent_kernel = ivy.array(recurrent_kernel_orig) + bias = ivy.array(bias_orig) + recurrent_bias = ivy.array(recurrent_bias_orig) + + h_tm1 = cell_states[0] # previous memory state + c_tm1 = cell_states[1] # previous carry state + + z = ivy.dot(cell_inputs, kernel) + bias + z += ivy.dot(h_tm1, recurrent_kernel) + recurrent_bias + + z0, z1, z2, z3 = ivy.split(z, num_or_size_splits=4, axis=-1) + + i = ivy.sigmoid(z0) # input + f = ivy.sigmoid(z1) # forget + c = f * c_tm1 + i * ivy.tanh(z2) + o = ivy.sigmoid(z3) # output + + h = o * ivy.tanh(c) + return h, [h, c] + + np_vals = [inputs, *initial_states, mask] + + if mask is None: + np_vals.pop(-1) + + with ivy.utils.backend.ContextManager(backend_fw): + _lstm_step_backend = outputs_to_frontend_arrays( + inputs_to_ivy_arrays(_lstm_step) + ) + vals = [ivy.array(val) for val in np_vals] + if len(vals) > 3: + inputs, init_h, init_c, mask = vals + else: + inputs, init_h, init_c = vals + initial_states = [init_h, init_c] + + args = (_lstm_step_backend, inputs, initial_states) + kwargs = { + "go_backwards": go_backwards, + "mask": mask, + "constants": None, + "unroll": unroll, + "input_length": input_length, + "time_major": time_major, + "zero_output_for_mask": zero_output_for_mask, + "return_all_outputs": return_all_outputs, + } + ret = tf_frontend.keras.backend.rnn(*args, **kwargs) + ivy_ret = ivy.nested_map(lambda x: x.ivy_array, ret, shallow=False) + ivy_idxs = ivy.nested_argwhere(ivy_ret, ivy.is_ivy_array) + ivy_vals = ivy.multi_index_nest(ivy_ret, ivy_idxs) + ret_np_flat = [x.to_numpy() for x in ivy_vals] + + with ivy.utils.backend.ContextManager(frontend): + _lstm_step_gt = output_to_native_arrays(inputs_to_ivy_arrays(_lstm_step)) + import tensorflow as tf + + vals = [ivy.array(val).data for val in np_vals] + if len(vals) > 3: + inputs, init_h, init_c, mask = vals + else: + inputs, init_h, init_c = vals + initial_states = [init_h, init_c] + + args = (_lstm_step_gt, inputs, initial_states) + kwargs = { + "go_backwards": go_backwards, + "mask": mask, + "constants": None, + "unroll": unroll, + "input_length": input_length, + "time_major": time_major, + "zero_output_for_mask": zero_output_for_mask, + "return_all_outputs": return_all_outputs, + } + ret = tf.keras.backend.rnn(*args, **kwargs) + native_idxs = ivy.nested_argwhere(ret, lambda x: isinstance(x, ivy.NativeArray)) + native_vals = ivy.multi_index_nest(ret, native_idxs) + frontend_ret_np_flat = [x.numpy() for x in native_vals] + + helpers.value_test( + ret_np_flat=ret_np_flat, + ret_np_from_gt_flat=frontend_ret_np_flat, + rtol=1e-1, + atol=1e-1, + backend=backend_fw, + ground_truth_backend=frontend, + ) diff --git a/ivy_tests/test_ivy/test_frontends/test_tensorflow/test_linalg.py b/ivy_tests/test_ivy/test_frontends/test_tensorflow/test_linalg.py index fdc93ffc80933..24e4d61344997 100644 --- a/ivy_tests/test_ivy/test_frontends/test_tensorflow/test_linalg.py +++ b/ivy_tests/test_ivy/test_frontends/test_tensorflow/test_linalg.py @@ -36,7 +36,7 @@ def _get_cholesky_matrix(draw): gen = draw( helpers.array_values( dtype=input_dtype, - shape=tuple([shared_size, shared_size]), + shape=(shared_size, shared_size), min_value=2, max_value=5, ).filter(lambda x: np.linalg.cond(x.tolist()) < 1 / sys.float_info.epsilon) @@ -125,7 +125,7 @@ def _get_hermitian_pos_def_matrix(draw): gen = draw( helpers.array_values( dtype=input_dtype, - shape=tuple([shared_size, shared_size]), + shape=(shared_size, shared_size), min_value=2, max_value=5, ).filter(lambda x: np.linalg.cond(x.tolist()) < 1 / sys.float_info.epsilon) @@ -148,11 +148,46 @@ def _get_second_matrix(draw): ) return input_dtype, draw( helpers.array_values( - dtype=input_dtype, shape=tuple([shared_size, 1]), min_value=2, max_value=5 + dtype=input_dtype, shape=(shared_size, 1), min_value=2, max_value=5 ) ) +@st.composite +def _get_tridiagonal_dtype_matrix_format(draw): + input_dtype_strategy = st.shared( + st.sampled_from(draw(helpers.get_dtypes("float_and_complex"))), + key="shared_dtype", + ) + input_dtype = draw(input_dtype_strategy) + shared_size = draw( + st.shared(helpers.ints(min_value=2, max_value=4), key="shared_size") + ) + diagonals_format = draw(st.sampled_from(["compact", "sequence", "matrix"])) + if diagonals_format == "matrix": + matrix = draw( + helpers.array_values( + dtype=input_dtype, + shape=(shared_size, shared_size), + min_value=2, + max_value=5, + ).filter(tridiagonal_matrix_filter) + ) + elif diagonals_format in ["compact", "sequence"]: + matrix = draw( + helpers.array_values( + dtype=input_dtype, + shape=(3, shared_size), + min_value=2, + max_value=5, + ).filter(tridiagonal_compact_filter) + ) + if diagonals_format == "sequence": + matrix = list(matrix) + + return input_dtype, matrix, diagonals_format + + # --- Main --- # # ------------ # @@ -379,6 +414,7 @@ def test_tensorflow_eigvals( rtol=1e-06, atol=1e-06, ground_truth_backend=frontend, + backend=backend_fw, ) @@ -416,7 +452,7 @@ def test_tensorflow_eigvalsh( num_arrays=1, min_value=1, max_value=10, - shape=helpers.ints(min_value=3, max_value=3).map(lambda x: tuple([x, x])), + shape=helpers.ints(min_value=3, max_value=3).map(lambda x: (x, x)), ).filter(lambda x: "float16" not in x[0]), test_with_out=st.just(False), ) @@ -476,7 +512,7 @@ def test_tensorflow_global_norm( available_dtypes=helpers.get_dtypes("valid"), min_value=-100, max_value=100, - shape=helpers.ints(min_value=1, max_value=20).map(lambda x: tuple([x, x])), + shape=helpers.ints(min_value=1, max_value=20).map(lambda x: (x, x)), ).filter( lambda x: "bfloat16" not in x[0] and np.linalg.cond(x[1][0]) < 1 / sys.float_info.epsilon @@ -552,7 +588,7 @@ def test_tensorflow_l2_normalize( available_dtypes=helpers.get_dtypes("float"), min_value=0, max_value=10, - shape=helpers.ints(min_value=2, max_value=5).map(lambda x: tuple([x, x])), + shape=helpers.ints(min_value=2, max_value=5).map(lambda x: (x, x)), ).filter( lambda x: "float16" not in x[0] and "bfloat16" not in x[0] @@ -898,7 +934,7 @@ def test_tensorflow_pinv( available_dtypes=helpers.get_dtypes("float"), min_value=0, max_value=10, - shape=helpers.ints(min_value=2, max_value=5).map(lambda x: tuple([x, x])), + shape=helpers.ints(min_value=2, max_value=5).map(lambda x: (x, x)), ), ) def test_tensorflow_qr( @@ -934,6 +970,7 @@ def test_tensorflow_qr( rtol=1e-2, atol=1e-2, ground_truth_backend=frontend, + backend=backend_fw, ) @@ -1039,7 +1076,7 @@ def test_tensorflow_solve( available_dtypes=helpers.get_dtypes("float"), min_value=0, max_value=10, - shape=helpers.ints(min_value=2, max_value=5).map(lambda x: tuple([x, x])), + shape=helpers.ints(min_value=2, max_value=5).map(lambda x: (x, x)), ), full_matrices=st.booleans(), compute_uv=st.just(True), @@ -1085,6 +1122,7 @@ def test_tensorflow_svd( rtol=1e-2, atol=1e-2, ground_truth_backend=frontend, + backend=backend_fw, ) @@ -1207,3 +1245,76 @@ def test_tensorflow_trace( fn_tree=fn_tree, x=x[0], ) + + +# tridiagonal_solve +@handle_frontend_test( + fn_tree="tensorflow.linalg.tridiagonal_solve", + x=_get_tridiagonal_dtype_matrix_format(), + y=_get_second_matrix(), + transpose_rhs=st.just(False), + conjugate_rhs=st.booleans(), +) +def test_tensorflow_tridiagonal_solve( + *, + x, + y, + transpose_rhs, + conjugate_rhs, + frontend, + backend_fw, + test_flags, + fn_tree, + on_device, +): + input_dtype1, x1, diagonals_format = x + input_dtype2, x2 = y + helpers.test_frontend_function( + input_dtypes=[input_dtype1, input_dtype2], + backend_to_test=backend_fw, + frontend=frontend, + test_flags=test_flags, + fn_tree=fn_tree, + on_device=on_device, + rtol=1e-3, + atol=1e-3, + diagonals=x1, + rhs=x2, + diagonals_format=diagonals_format, + transpose_rhs=transpose_rhs, + conjugate_rhs=conjugate_rhs, + ) + + +def tridiagonal_compact_filter(x): + diagonals = ivy.array(x) + dim = diagonals[0].shape[0] + diagonals[[0, -1], [-1, 0]] = 0 + dummy_idx = [0, 0] + indices = ivy.array( + [ + [(i, i + 1) for i in range(dim - 1)] + [dummy_idx], + [(i, i) for i in range(dim)], + [dummy_idx] + [(i + 1, i) for i in range(dim - 1)], + ] + ) + matrix = ivy.scatter_nd( + indices, diagonals, ivy.array([dim, dim]), reduction="replace" + ) + return tridiagonal_matrix_filter(matrix) + + +def tridiagonal_matrix_filter(x): + dim = x.shape[0] + if ivy.abs(ivy.det(x)) < 1e-3: + return False + for i in range(dim): + for j in range(dim): + cell = x[i][j] + if i in [j, j - 1, j + 1]: + if cell == 0: + return False + else: + if cell != 0: + return False + return True diff --git a/ivy_tests/test_ivy/test_frontends/test_tensorflow/test_math.py b/ivy_tests/test_ivy/test_frontends/test_tensorflow/test_math.py index 21fbc1c7a8000..3d14053f47e38 100644 --- a/ivy_tests/test_ivy/test_frontends/test_tensorflow/test_math.py +++ b/ivy_tests/test_ivy/test_frontends/test_tensorflow/test_math.py @@ -54,7 +54,7 @@ def test_tensorflow_abs( @handle_frontend_test( fn_tree="tensorflow.math.accumulate_n", dtype_and_x=helpers.dtype_and_values( - available_dtypes=tuple([ivy.int64]), + available_dtypes=(ivy.int64,), num_arrays=helpers.ints(min_value=2, max_value=5), shared_dtype=True, ), @@ -238,7 +238,7 @@ def test_tensorflow_angle( @handle_frontend_test( fn_tree="tensorflow.math.argmax", dtype_and_x=_statistical_dtype_values(function="argmax"), - output_type=st.sampled_from(["int16", "uint16", "int32", "int64"]), + output_type=st.sampled_from(["int32", "int64"]), test_with_out=st.just(False), ) def test_tensorflow_argmax( @@ -251,9 +251,7 @@ def test_tensorflow_argmax( on_device, output_type, ): - if backend_fw in ("torch", "paddle"): - assume(output_type != "uint16") - input_dtype, x, axis = dtype_and_x + input_dtype, x, axis, *_ = dtype_and_x if isinstance(axis, tuple): axis = axis[0] helpers.test_frontend_function( @@ -286,7 +284,7 @@ def test_tensorflow_argmin( on_device, output_type, ): - input_dtype, x, axis = dtype_and_x + input_dtype, x, axis, *_ = dtype_and_x if isinstance(axis, tuple): axis = axis[0] helpers.test_frontend_function( @@ -449,6 +447,41 @@ def test_tensorflow_atanh( ) +# bessel_i1 +@handle_frontend_test( + fn_tree="tensorflow.math.bessel_i1", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), + num_arrays=1, + min_value=-10, + max_value=10, + min_num_dims=1, + max_num_dims=4, + shared_dtype=True, + ), + test_with_out=st.just(False), +) +def test_tensorflow_bessel_i1( + *, + dtype_and_x, + frontend, + test_flags, + fn_tree, + backend_fw, + on_device, +): + input_dtype, x = dtype_and_x + helpers.test_frontend_function( + input_dtypes=input_dtype, + backend_to_test=backend_fw, + frontend=frontend, + test_flags=test_flags, + fn_tree=fn_tree, + on_device=on_device, + x=x[0], + ) + + # bincount @handle_frontend_test( fn_tree="tensorflow.math.bincount", @@ -1633,7 +1666,7 @@ def test_tensorflow_log_softmax( @handle_frontend_test( fn_tree="tensorflow.math.logical_and", dtype_and_x=helpers.dtype_and_values( - available_dtypes=tuple([ivy.bool]), + available_dtypes=(ivy.bool,), num_arrays=2, shared_dtype=True, ), @@ -1665,7 +1698,7 @@ def test_tensorflow_logical_and( @handle_frontend_test( fn_tree="tensorflow.math.logical_not", dtype_and_x=helpers.dtype_and_values( - available_dtypes=tuple([ivy.bool]), + available_dtypes=(ivy.bool,), num_arrays=2, shared_dtype=True, ), @@ -1728,7 +1761,7 @@ def test_tensorflow_logical_or( @handle_frontend_test( fn_tree="tensorflow.math.logical_xor", dtype_and_x=helpers.dtype_and_values( - available_dtypes=tuple([ivy.bool]), + available_dtypes=(ivy.bool,), num_arrays=2, shared_dtype=True, ), @@ -1760,7 +1793,7 @@ def test_tensorflow_logical_xor( @handle_frontend_test( fn_tree="tensorflow.math.maximum", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("float"), + available_dtypes=helpers.get_dtypes("numeric"), num_arrays=2, shared_dtype=True, ), @@ -2184,7 +2217,7 @@ def test_tensorflow_reciprocal_no_nan( @handle_frontend_test( fn_tree="tensorflow.math.reduce_all", dtype_and_x=helpers.dtype_and_values( - available_dtypes=tuple([ivy.bool]), + available_dtypes=(ivy.bool,), ), test_with_out=st.just(False), ) @@ -2213,7 +2246,7 @@ def test_tensorflow_reduce_all( @handle_frontend_test( fn_tree="tensorflow.math.reduce_any", dtype_and_x=helpers.dtype_and_values( - available_dtypes=tuple([ivy.bool]), + available_dtypes=(ivy.bool,), ), test_with_out=st.just(False), ) @@ -2650,6 +2683,39 @@ def test_tensorflow_scalar_mul( ) +@handle_frontend_test( + fn_tree="tensorflow.math.segment_sum", + data=helpers.array_values(dtype=helpers.get_dtypes("valid"), shape=(5, 6)), + segment_ids=helpers.array_values( + dtype=helpers.get_dtypes("signed_integer", prune_function=True), + shape=(5,), + min_value=0, + max_value=4, + ), + test_with_out=st.just(False), +) +def test_tensorflow_segment_sum( + *, + data, + segment_ids, + frontend, + test_flags, + fn_tree, + backend_fw, + on_device, +): + helpers.test_frontend_function( + input_dtypes=[str(data.dtype), "int32", "int64"], + frontend=frontend, + backend_to_test=backend_fw, + test_flags=test_flags, + fn_tree=fn_tree, + on_device=on_device, + data=data, + segment_ids=np.sort(segment_ids), + ) + + # sigmoid @handle_frontend_test( fn_tree="tensorflow.math.sigmoid", diff --git a/ivy_tests/test_ivy/test_frontends/test_tensorflow/test_nn.py b/ivy_tests/test_ivy/test_frontends/test_tensorflow/test_nn.py index c90ef72de9b48..da6f3aac33f11 100644 --- a/ivy_tests/test_ivy/test_frontends/test_tensorflow/test_nn.py +++ b/ivy_tests/test_ivy/test_frontends/test_tensorflow/test_nn.py @@ -1,15 +1,15 @@ # global -from hypothesis import strategies as st +from hypothesis import assume, strategies as st # local import ivy_tests.test_ivy.helpers as helpers -from ivy.functional.ivy.layers import _deconv_length from ivy_tests.test_ivy.helpers import handle_frontend_test from ivy_tests.test_ivy.test_functional.test_core.test_statistical import ( _statistical_dtype_values, ) from ivy_tests.test_ivy.test_functional.test_nn.test_layers import ( _assume_tf_dilation_gt_1, + _output_shape, ) @@ -136,9 +136,13 @@ def _dropout_helper(draw): @st.composite -def _generate_bias_data(draw): +def _generate_bias_data(draw, keras_backend_fn=False): data_format = draw(st.sampled_from(["NC...", "N...C", None])) channel_dim = 1 if data_format == "NC..." else -1 + if keras_backend_fn: + data_format = {"NC...": "channels_first", "N...C": "channels_last", None: None}[ + data_format + ] dtype, value, shape = draw( helpers.dtype_and_values( available_dtypes=helpers.get_dtypes("numeric"), @@ -226,7 +230,7 @@ def _x_and_filters( draw, dtypes, data_format, - padding, + padding=None, stride_min=1, stride_max=4, dilation_min=1, @@ -237,7 +241,6 @@ def _x_and_filters( ): data_format = draw(data_format) dtype = draw(dtypes) - padding = draw(padding) if type is not None: if "1" in type: dim = 1 @@ -249,18 +252,19 @@ def _x_and_filters( dim = 2 else: dim = len(data_format) - 2 - if padding == "EXPLICIT": - padding = draw( - helpers.lists( - x=st.integers(min_value=0, max_value=2), - min_size=dim * 2, - max_size=dim * 2, - ) + if padding is None: + padding = st.one_of( + st.lists( + st.tuples( + st.integers(min_value=0, max_value=3), + st.integers(min_value=0, max_value=3), + ), + min_size=dim, + max_size=dim, + ), + st.sampled_from(["SAME", "VALID"]), ) - if data_format.find("C") == 1: - padding = [1, 1, 1, 1] + padding - else: - padding = [0, 0] + padding + [0, 0] + padding = draw(padding) if atrous: dilations = draw(st.integers(dilation_min, dilation_max)) else: @@ -324,7 +328,6 @@ def _x_and_filters( helpers.ints(min_value=d_in, max_value=d_in), ) ) - x_w = x_shape[1] else: x_shape = draw( st.tuples( @@ -333,15 +336,6 @@ def _x_and_filters( helpers.ints(min_value=min_x_width, max_value=100), ) ) - x_w = x_shape[2] - if transpose: - output_shape = [ - x_shape[0], - _deconv_length( - x_w, fstride[0], filter_shape[0], padding, fdilations[0] - ), - filter_shape[1], - ] elif dim == 2: min_x_height = 1 min_x_width = 1 @@ -369,8 +363,6 @@ def _x_and_filters( helpers.ints(min_value=d_in, max_value=d_in), ) ) - x_h = x_shape[1] - x_w = x_shape[2] else: x_shape = draw( st.tuples( @@ -380,16 +372,6 @@ def _x_and_filters( helpers.ints(min_value=min_x_width, max_value=100), ) ) - x_h = x_shape[2] - x_w = x_shape[3] - if transpose: - output_shape_h = _deconv_length( - x_h, fstride[0], filter_shape[0], padding, fdilations[0] - ) - output_shape_w = _deconv_length( - x_w, fstride[1], filter_shape[1], padding, fdilations[1] - ) - output_shape = [x_shape[0], output_shape_h, output_shape_w, filter_shape[2]] elif dim == 3: filter_shape = draw( st.tuples( @@ -422,9 +404,6 @@ def _x_and_filters( helpers.ints(min_value=d_in, max_value=d_in), ) ) - x_d = x_shape[1] - x_h = x_shape[2] - x_w = x_shape[3] else: x_shape = draw( st.tuples( @@ -435,26 +414,30 @@ def _x_and_filters( helpers.ints(min_value=min_x_width, max_value=100), ) ) - x_d = x_shape[2] - x_h = x_shape[3] - x_w = x_shape[4] - if transpose: - output_shape_d = _deconv_length( - x_d, fstride[0], filter_shape[0], padding, fdilations[0] - ) - output_shape_h = _deconv_length( - x_h, fstride[1], filter_shape[1], padding, fdilations[1] - ) - output_shape_w = _deconv_length( - x_w, fstride[2], filter_shape[2], padding, fdilations[2] + if data_format[-1] == "C": + x_dims = x_shape[1:-1] + else: + x_dims = x_shape[2:] + if transpose: + output_shape = _output_shape( + dim, fdilations, fstride, padding, x_dims, filter_shape + ) + assume(all(s > 0 for s in output_shape)) + if data_format[1] == "C": + output_shape = [x_shape[0], filter_shape[dim], *output_shape] + else: + output_shape = [x_shape[0], *output_shape, filter_shape[dim]] + if not isinstance(padding, str): + assume( + all( + max(pad) - min(pad) < min(stride, dilation) + for pad, stride, dilation in zip(padding, fstride, fdilations) ) - output_shape = [ - x_shape[0], - output_shape_d, - output_shape_h, - output_shape_w, - filter_shape[3], - ] + ) + if data_format[1] == "C": + padding = [(0, 0), (0, 0), *padding] + else: + padding = [(0, 0), *padding, (0, 0)] x = draw( helpers.array_values(dtype=dtype[0], shape=x_shape, min_value=0, max_value=1) ) @@ -704,6 +687,8 @@ def test_tensorflow_avg_pool2d( ksize=ksize, strides=strides, padding=padding, + rtol=1e-2, + atol=1e-2, ) @@ -806,8 +791,6 @@ def test_tensorflow_bias_add( dtypes=helpers.get_dtypes("float", full=False), data_format=st.sampled_from(["NWC"]), padding=st.sampled_from(["VALID", "SAME"]), - stride_min=3, - stride_max=4, type="1d", ), test_with_out=st.just(False), @@ -844,9 +827,6 @@ def test_tensorflow_conv1d( dtypes=helpers.get_dtypes("float", full=False), data_format=st.sampled_from(["NWC"]), padding=st.sampled_from(["VALID", "SAME"]), - stride_min=3, - stride_max=4, - dilation_max=1, type="1d", transpose=True, ), @@ -894,7 +874,6 @@ def test_tensorflow_conv1d_transpose( x_f_d_df=_x_and_filters( dtypes=helpers.get_dtypes("float", full=False), data_format=st.sampled_from(["NHWC"]), - padding=st.sampled_from(["VALID", "SAME"]), type="2d", ), ) @@ -929,7 +908,6 @@ def test_tensorflow_conv2d( x_f_d_df=_x_and_filters( dtypes=helpers.get_dtypes("float", full=False), data_format=st.sampled_from(["NHWC"]), - padding=st.sampled_from(["VALID", "SAME"]), type="2d", transpose=True, ), @@ -954,6 +932,7 @@ def test_tensorflow_conv2d_transpose( padding, output_shape, ) = x_f_d_df + assume(isinstance(padding, str) or backend_fw in ["torch", "tensorflow"]) _assume_tf_dilation_gt_1("tensorflow", on_device, dilation) helpers.test_frontend_function( input_dtypes=input_dtype, @@ -979,7 +958,6 @@ def test_tensorflow_conv2d_transpose( data_format=st.sampled_from(["NDHWC"]), padding=st.sampled_from(["SAME"]), type="3d", - dilation_max=1, ), test_with_out=st.just(False), ) @@ -993,6 +971,7 @@ def test_tensorflow_conv3d( on_device, ): input_dtype, x, filters, dilation, data_format, stride, padding = x_f_d_df + _assume_tf_dilation_gt_1("tensorflow", on_device, dilation) helpers.test_frontend_function( input_dtypes=input_dtype, backend_to_test=backend_fw, @@ -1014,7 +993,7 @@ def test_tensorflow_conv3d( x_f_d_df=_x_and_filters( dtypes=helpers.get_dtypes("float", full=False), data_format=st.sampled_from(["NDHWC"]), - padding=st.sampled_from(["SAME"]), + padding=st.sampled_from(["VALID", "SAME"]), type="3d", transpose=True, ), @@ -1214,24 +1193,37 @@ def test_tensorflow_dropout( on_device, ): (x_dtype, x), noise_shape, seed, rate = dtype_x_noiseshape - ret, frontend_ret = helpers.test_frontend_function( - input_dtypes=x_dtype, - backend_to_test=backend_fw, - frontend=frontend, - test_flags=test_flags, - fn_tree=fn_tree, - on_device=on_device, - test_values=False, - x=x[0], - rate=rate, - noise_shape=noise_shape, - seed=seed, - ) - ret = helpers.flatten_and_to_np(ret=ret) - frontend_ret = helpers.flatten_and_to_np(ret=frontend_ret) - for u, v, w in zip(ret, frontend_ret, x): - # cardinality test - assert u.shape == v.shape == w.shape + if rate == 0: + helpers.test_frontend_function( + input_dtypes=x_dtype, + backend_to_test=backend_fw, + frontend=frontend, + test_flags=test_flags, + fn_tree=fn_tree, + on_device=on_device, + x=x[0], + rate=rate, + noise_shape=noise_shape, + seed=seed, + ) + else: + ret = helpers.test_frontend_function( + input_dtypes=x_dtype, + backend_to_test=backend_fw, + frontend=frontend, + test_flags=test_flags, + fn_tree=fn_tree, + on_device=on_device, + test_values=False, + x=x[0], + rate=rate, + noise_shape=noise_shape, + seed=seed, + ) + ret = helpers.flatten_and_to_np(ret=ret, backend=backend_fw) + for u in ret: + # cardinality test + assert u.shape == x[0].shape # embedding_lookup @@ -1343,14 +1335,13 @@ def test_tensorflow_leaky_relu( @handle_frontend_test( fn_tree="tensorflow.nn.local_response_normalization", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("float"), - min_value=-20, - max_value=20, + available_dtypes=helpers.get_dtypes("valid"), min_num_dims=4, max_num_dims=4, min_dim_size=1, - large_abs_safety_factor=25, - small_abs_safety_factor=25, + large_abs_safety_factor=2, + small_abs_safety_factor=2, + safety_factor_scale="log", ), depth_radius=st.integers(min_value=1, max_value=5), bias=st.floats(min_value=0.1, max_value=1.5), @@ -1379,8 +1370,7 @@ def test_tensorflow_local_response_normalization( test_flags=test_flags, fn_tree=fn_tree, on_device=on_device, - rtol=1e-1, - atol=1e-1, + atol=1e-2, input=x[0], depth_radius=depth_radius, bias=bias, @@ -1500,7 +1490,7 @@ def test_tensorflow_max_pool2d( # max_pool3d @handle_frontend_test( fn_tree="tensorflow.nn.max_pool3d", - data_format=st.sampled_from(["NDHWC", "NCDHW"]), + data_format=st.just("NDHWC"), # Pooling3DOp only supports NDHWC on device type CPU x_k_s_p=helpers.arrays_for_pooling(min_dims=5, max_dims=5, min_side=1, max_side=4), test_with_out=st.just(False), ) diff --git a/ivy_tests/test_ivy/test_frontends/test_tensorflow/test_raw_ops.py b/ivy_tests/test_ivy/test_frontends/test_tensorflow/test_raw_ops.py index b3fe2d66ab1ba..ad9b5ee4f3114 100644 --- a/ivy_tests/test_ivy/test_frontends/test_tensorflow/test_raw_ops.py +++ b/ivy_tests/test_ivy/test_frontends/test_tensorflow/test_raw_ops.py @@ -121,8 +121,9 @@ def _get_shared_dtype(draw): @st.composite def _get_splits(draw, as_list=False): - """Generate valid splits, either by generating an integer that evenly divides the - axis or a list of splits that sum to the length of the axis being split.""" + """Generate valid splits, either by generating an integer that evenly + divides the axis or a list of splits that sum to the length of the axis + being split.""" shape = draw(st.shared(helpers.get_shape(min_num_dims=1), key="value_shape")) axis = draw( st.shared(helpers.get_axis(shape=shape, force_int=True), key="target_axis") @@ -264,6 +265,40 @@ def _reshape_helper(draw): return x, dtype, reshape_shape +@st.composite +def _segment_ops_helper(draw): + shape_x = draw(st.integers(min_value=3, max_value=100)) + shape_y = draw(st.integers(min_value=3, max_value=100)) + max_val = draw(st.integers(min_value=3, max_value=9)) + s_dtype = draw( + st.sampled_from( + [ + "int32", + "int64", + ] + ) + ) + data_dtype, data = draw( + helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), + num_arrays=1, + shape=(shape_x, shape_y), + min_value=-max_val, + max_value=max_val, + ) + ) + seg_dtype, segment_ids = draw( + helpers.dtype_and_values( + available_dtypes=[s_dtype], + num_arrays=1, + shape=(shape_x,), + min_value=0, + max_value=max_val, + ) + ) + return data_dtype + seg_dtype, data, segment_ids, max_val + + @st.composite def _squeeze_helper(draw): shape = draw(st.shared(helpers.get_shape(), key="value_shape")) @@ -1079,7 +1114,7 @@ def test_tensorflow_Ceil( # NOQA available_dtypes=helpers.get_dtypes("float"), min_value=0, max_value=10, - shape=helpers.ints(min_value=2, max_value=5).map(lambda x: tuple([x, x])), + shape=helpers.ints(min_value=2, max_value=5).map(lambda x: (x, x)), ), test_with_out=st.just(False), ) @@ -2097,6 +2132,44 @@ def test_tensorflow_Gather( # NOQA ) +# GatherNd +@handle_frontend_test( + fn_tree="tensorflow.raw_ops.GatherNd", + params_indices_axis_batch_dims=helpers.array_indices_axis( + array_dtypes=helpers.get_dtypes("valid"), + indices_dtypes=["int32", "int64"], + min_num_dims=3, + max_num_dims=3, + min_dim_size=3, + max_dim_size=3, + axis_zero=True, + disable_random_axis=True, + indices_same_dims=True, + ), + test_with_out=st.just(False), +) +def test_tensorflow_GatherNd( + *, + params_indices_axis_batch_dims, + frontend, + test_flags, + fn_tree, + backend_fw, + on_device, +): + input_dtypes, params, indices = params_indices_axis_batch_dims + helpers.test_frontend_function( + input_dtypes=input_dtypes, + backend_to_test=backend_fw, + frontend=frontend, + test_flags=test_flags, + fn_tree=fn_tree, + on_device=on_device, + params=params, + indices=indices, + ) + + # Greater @handle_frontend_test( fn_tree="tensorflow.raw_ops.Greater", @@ -2744,7 +2817,7 @@ def test_tensorflow_MatMul( # NOQA fn_tree="tensorflow.raw_ops.MatrixDeterminant", dtype_and_x=helpers.dtype_and_values( available_dtypes=helpers.get_dtypes("float"), - shape=helpers.ints(min_value=2, max_value=5).map(lambda x: tuple([x, x])), + shape=helpers.ints(min_value=2, max_value=5).map(lambda x: (x, x)), min_value=-5, max_value=5, ), @@ -2775,7 +2848,7 @@ def test_tensorflow_MatrixDeterminant( # NOQA fn_tree="tensorflow.raw_ops.MatrixInverse", dtype_x=helpers.dtype_and_values( available_dtypes=helpers.get_dtypes("float"), - shape=helpers.ints(min_value=2, max_value=10).map(lambda x: tuple([x, x])), + shape=helpers.ints(min_value=2, max_value=10).map(lambda x: (x, x)), ).filter(lambda x: np.linalg.cond(x[1][0].tolist()) < 1 / sys.float_info.epsilon), adjoint=st.booleans(), test_with_out=st.just(False), @@ -4200,7 +4273,7 @@ def test_tensorflow_Sum( # NOQA available_dtypes=helpers.get_dtypes("valid"), min_value=0, max_value=10, - shape=helpers.ints(min_value=2, max_value=5).map(lambda x: tuple([x, x])), + shape=helpers.ints(min_value=2, max_value=5).map(lambda x: (x, x)), ), full_matrices=st.booleans(), compute_uv=st.just(True), @@ -4244,6 +4317,7 @@ def test_tensorflow_Svd( rtol=1e-2, atol=1e-2, ground_truth_backend=frontend, + backend=backend_fw, ) @@ -4426,6 +4500,34 @@ def test_tensorflow_Unpack( # NOQA ) +@handle_frontend_test( + fn_tree="tensorflow.raw_ops.UnsortedSegmentProd", + params=_segment_ops_helper(), + test_with_out=st.just(False), +) +def test_tensorflow_UnsortedSegmentProd( + *, + params, + frontend, + test_flags, + fn_tree, + backend_fw, + on_device, +): + dtypes, data, segment_ids, max_val = params + helpers.test_frontend_function( + input_dtypes=dtypes, + backend_to_test=backend_fw, + frontend=frontend, + test_flags=test_flags, + fn_tree=fn_tree, + on_device=on_device, + data=data[0], + segment_ids=segment_ids[0], + num_segments=max_val + 1, + ) + + @handle_frontend_test( fn_tree="tensorflow.raw_ops.Xdivy", dtype_and_x=helpers.dtype_and_values( diff --git a/ivy_tests/test_ivy/test_frontends/test_tensorflow/test_tensor.py b/ivy_tests/test_ivy/test_frontends/test_tensorflow/test_tensor.py index 2192af794be99..153f2089e184b 100644 --- a/ivy_tests/test_ivy/test_frontends/test_tensorflow/test_tensor.py +++ b/ivy_tests/test_ivy/test_frontends/test_tensorflow/test_tensor.py @@ -85,7 +85,7 @@ def _check_query(query): shared_dtype=True, ), ) -def test_tensorflow__add__( +def test_tensorflow___add__( dtype_and_x, frontend, frontend_method_data, @@ -113,45 +113,6 @@ def test_tensorflow__add__( ) -# __and__ -@handle_frontend_method( - class_tree=CLASS_TREE, - init_tree="tensorflow.constant", - method_name="__and__", - dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("integer"), - num_arrays=2, - shared_dtype=True, - ), -) -def test_tensorflow__and__( - dtype_and_x, - frontend, - frontend_method_data, - init_flags, - method_flags, - backend_fw, - on_device, -): - input_dtype, x = dtype_and_x - helpers.test_frontend_method( - init_input_dtypes=input_dtype, - backend_to_test=backend_fw, - init_all_as_kwargs_np={ - "value": x[0], - }, - method_input_dtypes=input_dtype, - method_all_as_kwargs_np={ - "y": x[1], - }, - frontend=frontend, - frontend_method_data=frontend_method_data, - init_flags=init_flags, - method_flags=method_flags, - on_device=on_device, - ) - - # __array__ @handle_frontend_method( class_tree=CLASS_TREE, @@ -160,7 +121,7 @@ def test_tensorflow__and__( dtype_and_x=helpers.dtype_and_values(available_dtypes=helpers.get_dtypes("valid")), dtype=helpers.get_dtypes("valid", full=False), ) -def test_tensorflow__array__( +def test_tensorflow___array__( dtype_and_x, dtype, frontend, @@ -193,7 +154,7 @@ def test_tensorflow__array__( max_dim_size=1, ), ) -def test_tensorflow__bool__( +def test_tensorflow___bool__( dtype_and_x, frontend, frontend_method_data, @@ -232,7 +193,7 @@ def test_tensorflow__bool__( safety_factor_scale="log", ), ) -def test_tensorflow__div__( +def test_tensorflow___div__( dtype_and_x, frontend, frontend_method_data, @@ -271,7 +232,7 @@ def test_tensorflow__div__( num_arrays=2, ), ) -def test_tensorflow__eq__( +def test_tensorflow___eq__( dtype_and_x, frontend, frontend_method_data, @@ -312,7 +273,7 @@ def test_tensorflow__eq__( safety_factor_scale="log", ), ) -def test_tensorflow__floordiv__( +def test_tensorflow___floordiv__( dtype_and_x, frontend, frontend_method_data, @@ -351,7 +312,7 @@ def test_tensorflow__floordiv__( shared_dtype=True, ), ) -def test_tensorflow__ge__( +def test_tensorflow___ge__( dtype_and_x, frontend, frontend_method_data, @@ -394,7 +355,7 @@ def test_tensorflow__ge__( ) ), ) -def test_tensorflow__getitem__( +def test_tensorflow___getitem__( dtype_x_index, frontend, frontend_method_data, @@ -429,7 +390,7 @@ def test_tensorflow__getitem__( shared_dtype=True, ), ) -def test_tensorflow__gt__( +def test_tensorflow___gt__( dtype_and_x, frontend, frontend_method_data, @@ -466,7 +427,7 @@ def test_tensorflow__gt__( available_dtypes=helpers.get_dtypes("integer") ), ) -def test_tensorflow__invert__( +def test_tensorflow___invert__( dtype_and_x, frontend, frontend_method_data, @@ -503,7 +464,7 @@ def test_tensorflow__invert__( shared_dtype=True, ), ) -def test_tensorflow__le__( +def test_tensorflow___le__( dtype_and_x, frontend, frontend_method_data, @@ -541,7 +502,7 @@ def test_tensorflow__le__( max_num_dims=5, ), ) -def test_tensorflow__len__( +def test_tensorflow___len__( dtype_and_x, frontend, frontend_method_data, @@ -578,7 +539,7 @@ def test_tensorflow__len__( shared_dtype=True, ), ) -def test_tensorflow__lt__( +def test_tensorflow___lt__( dtype_and_x, frontend, frontend_method_data, @@ -626,7 +587,7 @@ def test_tensorflow__lt__( safety_factor_scale="log", ), ) -def test_tensorflow__matmul__( +def test_tensorflow___matmul__( dtype_and_x, frontend, frontend_method_data, @@ -665,7 +626,7 @@ def test_tensorflow__matmul__( shared_dtype=True, ), ) -def test_tensorflow__mod__( +def test_tensorflow___mod__( dtype_and_x, frontend, frontend_method_data, @@ -705,7 +666,7 @@ def test_tensorflow__mod__( shared_dtype=True, ), ) -def test_tensorflow__mul__( +def test_tensorflow___mul__( dtype_and_x, frontend, frontend_method_data, @@ -744,7 +705,7 @@ def test_tensorflow__mul__( shared_dtype=True, ), ) -def test_tensorflow__ne__( +def test_tensorflow___ne__( dtype_and_x, frontend, frontend_method_data, @@ -788,7 +749,7 @@ def test_tensorflow__ne__( ], ), ) -def test_tensorflow__neg__( +def test_tensorflow___neg__( dtype_and_x, frontend, frontend_method_data, @@ -824,7 +785,7 @@ def test_tensorflow__neg__( max_dim_size=1, ), ) -def test_tensorflow__nonzero__( +def test_tensorflow___nonzero__( dtype_and_x, frontend, frontend_method_data, @@ -861,7 +822,7 @@ def test_tensorflow__nonzero__( shared_dtype=True, ), ) -def test_tensorflow__or__( +def test_tensorflow___or__( dtype_and_x, frontend, frontend_method_data, @@ -906,7 +867,7 @@ def test_tensorflow__or__( shared_dtype=True, ), ) -def test_tensorflow__pow__( +def test_tensorflow___pow__( dtype_and_x, frontend, frontend_method_data, @@ -916,7 +877,7 @@ def test_tensorflow__pow__( on_device, ): input_dtype, x = dtype_and_x - if x[1].dtype == "int32" or x[1].dtype == "int64": + if x[1].dtype in ["int32", "int64"]: if x[1].ndim == 0: if x[1] < 0: x[1] *= -1 @@ -952,7 +913,7 @@ def test_tensorflow__pow__( shared_dtype=True, ), ) -def test_tensorflow__radd__( +def test_tensorflow___radd__( dtype_and_x, frontend, frontend_method_data, @@ -991,7 +952,7 @@ def test_tensorflow__radd__( shared_dtype=True, ), ) -def test_tensorflow__rand__( +def test_tensorflow___rand__( dtype_and_x, frontend, frontend_method_data, @@ -1033,7 +994,7 @@ def test_tensorflow__rand__( safety_factor_scale="log", ), ) -def test_tensorflow__rfloordiv__( +def test_tensorflow___rfloordiv__( dtype_and_x, frontend, frontend_method_data, @@ -1081,7 +1042,7 @@ def test_tensorflow__rfloordiv__( safety_factor_scale="log", ), ) -def test_tensorflow__rmatmul__( +def test_tensorflow___rmatmul__( dtype_and_x, frontend, frontend_method_data, @@ -1122,7 +1083,7 @@ def test_tensorflow__rmatmul__( max_value=100, ), ) -def test_tensorflow__rmul__( +def test_tensorflow___rmul__( dtype_and_x, frontend, frontend_method_data, @@ -1161,7 +1122,7 @@ def test_tensorflow__rmul__( shared_dtype=True, ), ) -def test_tensorflow__ror__( +def test_tensorflow___ror__( dtype_and_x, frontend, frontend_method_data, @@ -1196,7 +1157,7 @@ def test_tensorflow__ror__( method_name="__rpow__", dtype_and_x=_pow_helper_shared_dtype(), ) -def test_tensorflow__rpow__( +def test_tensorflow___rpow__( dtype_and_x, frontend, frontend_method_data, @@ -1235,7 +1196,7 @@ def test_tensorflow__rpow__( shared_dtype=True, ), ) -def test_tensorflow__rsub__( +def test_tensorflow___rsub__( dtype_and_x, frontend, frontend_method_data, @@ -1277,7 +1238,7 @@ def test_tensorflow__rsub__( safety_factor_scale="log", ), ) -def test_tensorflow__rtruediv__( +def test_tensorflow___rtruediv__( dtype_and_x, frontend, frontend_method_data, @@ -1316,7 +1277,7 @@ def test_tensorflow__rtruediv__( shared_dtype=True, ), ) -def test_tensorflow__rxor__( +def test_tensorflow___rxor__( dtype_and_x, frontend, frontend_method_data, @@ -1355,7 +1316,7 @@ def test_tensorflow__rxor__( shared_dtype=True, ), ) -def test_tensorflow__sub__( +def test_tensorflow___sub__( dtype_and_x, frontend, frontend_method_data, @@ -1397,7 +1358,7 @@ def test_tensorflow__sub__( safety_factor_scale="log", ), ) -def test_tensorflow__truediv__( +def test_tensorflow___truediv__( dtype_and_x, frontend, frontend_method_data, @@ -1437,7 +1398,46 @@ def test_tensorflow__truediv__( shared_dtype=True, ), ) -def test_tensorflow__xor__( +def test_tensorflow___xor__( + dtype_and_x, + frontend, + frontend_method_data, + init_flags, + method_flags, + backend_fw, + on_device, +): + input_dtype, x = dtype_and_x + helpers.test_frontend_method( + init_input_dtypes=input_dtype, + backend_to_test=backend_fw, + init_all_as_kwargs_np={ + "value": x[0], + }, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={ + "y": x[1], + }, + frontend=frontend, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + on_device=on_device, + ) + + +# __and__ +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="tensorflow.constant", + method_name="__and__", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("integer"), + num_arrays=2, + shared_dtype=True, + ), +) +def test_tensorflow__and__( dtype_and_x, frontend, frontend_method_data, @@ -1552,6 +1552,7 @@ def test_tensorflow_ivy_array( ret_np_flat=ret, ret_np_from_gt_flat=ret_gt, ground_truth_backend="tensorflow", + backend=backend_fw, ) ivy.previous_backend() diff --git a/ivy_tests/test_ivy/test_frontends/test_tensorflow/test_tensorshape.py b/ivy_tests/test_ivy/test_frontends/test_tensorflow/test_tensorshape.py new file mode 100644 index 0000000000000..044f5601897e6 --- /dev/null +++ b/ivy_tests/test_ivy/test_frontends/test_tensorflow/test_tensorshape.py @@ -0,0 +1,80 @@ +# global +from hypothesis import strategies as st + +# local +import ivy +import ivy_tests.test_ivy.helpers as helpers +from ivy_tests.test_ivy.helpers import handle_frontend_method +import pytest + +CLASS_TREE = "ivy.functional.frontends.tensorflow.tensor.TensorShape" + + +# __add__ +@pytest.mark.skip("TODO: test needs implementing correctly") +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="tensorflow.TensorShape", + method_name="__add__", + shape_list=helpers.list_of_size(x=st.sampled_from([0, 1, 2, 3, 4]), size=3), + other_list=helpers.list_of_size(x=st.sampled_from([0, 1, 2, 3, 4]), size=3), +) +def test_tensorflow__add__( + shape_list, + other_list, + frontend, + frontend_method_data, + init_flags, + method_flags, + on_device, + backend_fw, +): + helpers.test_frontend_method( + init_input_dtypes=[ivy.int64], + backend_to_test=backend_fw, + init_all_as_kwargs_np={ + "dims": shape_list, + }, + method_input_dtypes=[ivy.int64], + method_all_as_kwargs_np={ + "other": other_list, + }, + frontend=frontend, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + on_device=on_device, + ) + + +# __bool__ +@pytest.mark.skip("TODO: test needs implementing correctly") +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="tensorflow.TensorShape", + method_name="__bool__", + shape_list=helpers.list_of_size(x=st.sampled_from([0, 1, 2, 3, 4]), size=3), +) +def test_tensorflow__bool__( + shape_list, + frontend, + frontend_method_data, + init_flags, + method_flags, + backend_fw, + on_device, +): + helpers.test_frontend_method( + init_input_dtypes=[ivy.int64], + backend_to_test=backend_fw, + init_all_as_kwargs_np={ + "dims": shape_list, + }, + method_input_dtypes=[ivy.int64], + method_all_as_kwargs_np={}, + frontend=frontend, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + on_device=on_device, + ) diff --git a/ivy_tests/test_ivy/test_frontends/test_torch/__init__.py b/ivy_tests/test_ivy/test_frontends/test_torch/__init__.py index aac6f175aa7c1..3187545f1376e 100644 --- a/ivy_tests/test_ivy/test_frontends/test_torch/__init__.py +++ b/ivy_tests/test_ivy/test_frontends/test_torch/__init__.py @@ -6,7 +6,8 @@ def convtorch(argument): - """Convert NativeClass in argument to ivy frontend counterpart for torch.""" + """Convert NativeClass in argument to ivy frontend counterpart for + torch.""" if isinstance(argument, NativeClass): return torch_classes_to_ivy_classes.get(argument._native_class) return argument diff --git a/ivy_tests/test_ivy/test_frontends/test_torch/test_blas_and_lapack_ops.py b/ivy_tests/test_ivy/test_frontends/test_torch/test_blas_and_lapack_ops.py index 217a2b2edaf8a..a9eb41dd76b55 100644 --- a/ivy_tests/test_ivy/test_frontends/test_torch/test_blas_and_lapack_ops.py +++ b/ivy_tests/test_ivy/test_frontends/test_torch/test_blas_and_lapack_ops.py @@ -524,7 +524,7 @@ def test_torch_chain_matmul( available_dtypes=helpers.get_dtypes("float", index=1), min_value=0, max_value=10, - shape=helpers.ints(min_value=2, max_value=5).map(lambda x: tuple([x, x])), + shape=helpers.ints(min_value=2, max_value=5).map(lambda x: (x, x)), ).filter( lambda x: np.linalg.cond(x[1]) < 1 / sys.float_info.epsilon and np.linalg.det(np.asarray(x[1])) != 0 diff --git a/ivy_tests/test_ivy/test_frontends/test_torch/test_comparison_ops.py b/ivy_tests/test_ivy/test_frontends/test_torch/test_comparison_ops.py index 9d1a64830280c..0227a3aa47a96 100644 --- a/ivy_tests/test_ivy/test_frontends/test_torch/test_comparison_ops.py +++ b/ivy_tests/test_ivy/test_frontends/test_torch/test_comparison_ops.py @@ -368,7 +368,7 @@ def test_torch_isfinite( @handle_frontend_test( fn_tree="torch.isin", dtype_and_inputs=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("numeric"), + available_dtypes=helpers.get_dtypes("valid"), num_arrays=2, shared_dtype=True, ), @@ -658,7 +658,7 @@ def test_torch_less_equal( @handle_frontend_test( fn_tree="torch.maximum", dtype_and_inputs=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("numeric"), + available_dtypes=helpers.get_dtypes("valid"), num_arrays=2, shared_dtype=True, ), @@ -688,7 +688,7 @@ def test_torch_maximum( @handle_frontend_test( fn_tree="torch.minimum", dtype_and_inputs=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("numeric"), + available_dtypes=helpers.get_dtypes("valid"), num_arrays=2, shared_dtype=True, ), diff --git a/ivy_tests/test_ivy/test_frontends/test_torch/test_creation_ops.py b/ivy_tests/test_ivy/test_frontends/test_torch/test_creation_ops.py index 859ddfa5df3cf..989a783e225d6 100644 --- a/ivy_tests/test_ivy/test_frontends/test_torch/test_creation_ops.py +++ b/ivy_tests/test_ivy/test_frontends/test_torch/test_creation_ops.py @@ -7,6 +7,7 @@ import ivy_tests.test_ivy.helpers as helpers import ivy_tests.test_ivy.helpers.globals as test_globals from ivy_tests.test_ivy.helpers import handle_frontend_test, BackendHandler +from ivy_tests.test_ivy.helpers.testing_helpers import handle_example # --- Helpers --- # @@ -80,7 +81,7 @@ def _as_tensor_helper(draw): @st.composite def _fill_value(draw): with_array = draw(st.sampled_from([True, False])) - dtype = draw(st.shared(helpers.get_dtypes("numeric", full=False), key="dtype"))[0] + dtype = draw(st.shared(helpers.get_dtypes("valid", full=False), key="dtype"))[0] with BackendHandler.update_backend(test_globals.CURRENT_BACKEND) as ivy_backend: if ivy_backend.is_uint_dtype(dtype): ret = draw(helpers.ints(min_value=0, max_value=5)) @@ -511,7 +512,7 @@ def test_torch_frombuffer( max_dim_size=10, ), fill_value=_fill_value(), - dtype=st.shared(helpers.get_dtypes("numeric", full=False), key="dtype"), + dtype=st.shared(helpers.get_dtypes("valid", full=False), key="dtype"), ) def test_torch_full( *, @@ -611,6 +612,14 @@ def test_torch_heaviside( num=st.integers(min_value=1, max_value=10), dtype=helpers.get_dtypes("float", full=False), ) +@handle_example( + test_frontend_example=True, + start=np.array(0), + stop=1, + num=2, + dtype=[None], + fn_tree="ivy.functional.frontends.torch.linspace", +) def test_torch_linspace( *, start, @@ -624,7 +633,7 @@ def test_torch_linspace( backend_fw, ): helpers.test_frontend_function( - input_dtypes=[], + input_dtypes=[] if isinstance(start, float) else ["int64"], backend_to_test=backend_fw, frontend=frontend, test_flags=test_flags, diff --git a/ivy_tests/test_ivy/test_frontends/test_torch/test_func_wrapper.py b/ivy_tests/test_ivy/test_frontends/test_torch/test_func_wrapper.py index fd7255b9aaed4..4f731ff5d246c 100644 --- a/ivy_tests/test_ivy/test_frontends/test_torch/test_func_wrapper.py +++ b/ivy_tests/test_ivy/test_frontends/test_torch/test_func_wrapper.py @@ -21,7 +21,7 @@ def _fn(*args, dtype=None, check_default=False, inplace=False): if ( check_default - and all([not (ivy.is_array(i) or hasattr(i, "ivy_array")) for i in args]) + and all(not (ivy.is_array(i) or hasattr(i, "ivy_array")) for i in args) and not ivy.exists(dtype) ): ivy.utils.assertions.check_equal( diff --git a/ivy_tests/test_ivy/test_frontends/test_torch/test_indexing_slicing_joining_mutating_ops.py b/ivy_tests/test_ivy/test_frontends/test_torch/test_indexing_slicing_joining_mutating_ops.py index 4e784594b8b3b..292576018b1eb 100644 --- a/ivy_tests/test_ivy/test_frontends/test_torch/test_indexing_slicing_joining_mutating_ops.py +++ b/ivy_tests/test_ivy/test_frontends/test_torch/test_indexing_slicing_joining_mutating_ops.py @@ -11,11 +11,8 @@ import ivy_tests.test_ivy.helpers.globals as test_globals from ivy_tests.test_ivy.helpers import handle_frontend_test from ivy_tests.test_ivy.test_functional.test_core.test_manipulation import _get_splits -from ivy_tests.test_ivy.test_functional.test_core.test_searching import ( - _broadcastable_trio, -) -from ivy_tests.test_ivy.test_functional.test_core.test_manipulation import ( # noqa - _get_splits, +from ivy_tests.test_ivy.helpers.hypothesis_helpers.general_helpers import ( + two_broadcastable_shapes, ) @@ -338,6 +335,31 @@ def _dtypes_input_mask(draw): return _dtype, _x, _mask +@st.composite +def _where_helper(draw): + shape_1, shape_2 = draw(two_broadcastable_shapes()) + dtype_x1, x1 = draw( + helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), + shape=shape_1, + ) + ) + dtype_x2, x2 = draw( + helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), + shape=shape_1, + shared_dtype=True, + ) + ) + _, cond = draw( + helpers.dtype_and_values( + available_dtypes=["bool"], + shape=shape_2, + ) + ) + return ["bool", *dtype_x1, *dtype_x2], [cond[0], x1[0], x2[0]] + + # reshape @st.composite def dtypes_x_reshape(draw): @@ -1334,11 +1356,13 @@ def test_torch_squeeze( dim=helpers.get_axis( shape=st.shared(helpers.get_shape(min_num_dims=1), key="shape"), ).filter(lambda axis: isinstance(axis, int)), + use_axis_arg=st.booleans(), ) def test_torch_stack( *, dtype_value_shape, dim, + use_axis_arg, on_device, fn_tree, frontend, @@ -1346,6 +1370,7 @@ def test_torch_stack( backend_fw, ): input_dtype, value = dtype_value_shape + dim_arg = {"axis" if use_axis_arg else "dim": dim} helpers.test_frontend_function( input_dtypes=input_dtype, backend_to_test=backend_fw, @@ -1354,7 +1379,7 @@ def test_torch_stack( fn_tree=fn_tree, on_device=on_device, tensors=value, - dim=dim, + **dim_arg, ) @@ -1791,7 +1816,7 @@ def test_torch_vstack( @handle_frontend_test( fn_tree="torch.where", - broadcastables=_broadcastable_trio(), + broadcastables=_where_helper(), only_cond=st.booleans(), ) def test_torch_where( @@ -1804,7 +1829,7 @@ def test_torch_where( backend_fw, on_device, ): - cond, xs, dtypes = broadcastables + dtypes, arrays = broadcastables if only_cond: helpers.test_frontend_function( @@ -1814,18 +1839,18 @@ def test_torch_where( test_flags=test_flags, fn_tree=fn_tree, on_device=on_device, - condition=xs[0], + condition=arrays[0], ) else: helpers.test_frontend_function( - input_dtypes=["bool"] + dtypes, + input_dtypes=dtypes, + backend_to_test=backend_fw, frontend=frontend, test_flags=test_flags, fn_tree=fn_tree, on_device=on_device, - condition=cond, - input=xs[0], - other=xs[1], - backend_to_test=backend_fw, + condition=arrays[0], + input=arrays[1], + other=arrays[2], ) diff --git a/ivy_tests/test_ivy/test_frontends/test_torch/test_linalg.py b/ivy_tests/test_ivy/test_frontends/test_torch/test_linalg.py index 590ee6c770cfc..4b75c6fdb4482 100644 --- a/ivy_tests/test_ivy/test_frontends/test_torch/test_linalg.py +++ b/ivy_tests/test_ivy/test_frontends/test_torch/test_linalg.py @@ -2,7 +2,7 @@ import math import sys import numpy as np -from hypothesis import strategies as st, assume +from hypothesis import strategies as st, assume, settings, HealthCheck # local import ivy @@ -63,12 +63,12 @@ def _generate_multi_dot_dtype_and_arrays(draw): @st.composite def _get_axis_and_p(draw): p = draw(st.sampled_from(["fro", "nuc", 1, 2, -1, -2, float("inf"), -float("inf")])) - if p == "fro" or p == "nuc": + if p in ["fro", "nuc"]: max_axes_size = 2 min_axes_size = 2 else: min_axes_size = 1 - max_axes_size = 5 + max_axes_size = 2 x_dtype, values, axis = draw( helpers.dtype_values_axis( available_dtypes=helpers.get_dtypes("valid"), @@ -270,6 +270,37 @@ def _vander_helper(draw): # ------------ # +@handle_frontend_test( + fn_tree="torch.linalg.lu_solve", + dtype_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("float"), + shape=helpers.get_shape( + min_num_dims=2, max_num_dims=2, min_dim_size=2, max_dim_size=2 + ), + num_arrays=2, + shared_dtype=True, + ).filter(lambda x: helpers.matrix_is_stable(x[1][0], cond_limit=10)), +) +def test_lu_solve(dtype_x, test_flags, backend_fw, fn_name, on_device): + dtype, arr = dtype_x + A, B = arr[0], arr[1] + ivy.set_backend(backend_fw) + lu_ = ivy.lu_factor(A) + lu, p = lu_.LU, lu_.p + X, X_gt = helpers.test_frontend_function( + input_dtypes=dtype, + test_flags=test_flags, + on_device=on_device, + backend_to_test=backend_fw, + fn_name=fn_name, + lu=lu, + p=p, + b=B, + test_values=False, + ) + assert np.allclose(A @ X, B) + + @handle_frontend_test( fn_tree="torch.linalg.cholesky", aliases=["torch.cholesky"], @@ -424,6 +455,49 @@ def test_torch_det( ) +@handle_frontend_test( + fn_tree="torch.diag_embed", + dtype_and_values=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("float"), + shape=st.shared(helpers.get_shape(min_num_dims=1, max_num_dims=2), key="shape"), + ), + dims_and_offsets=helpers.dims_and_offset( + shape=st.shared(helpers.get_shape(min_num_dims=1, max_num_dims=2), key="shape"), + ensure_dim_unique=True, + ), +) +@settings(suppress_health_check=list(HealthCheck)) +def test_torch_diag_embed( + *, + dtype_and_values, + dims_and_offsets, + test_flags, + on_device, + fn_tree, + frontend, + backend_fw, +): + input_dtype, value = dtype_and_values + dim1, dim2, offset = dims_and_offsets + num_of_dims = len(np.shape(value[0])) + if dim1 < 0: + assume(dim1 + num_of_dims != dim2) + if dim2 < 0: + assume(dim1 != dim2 + num_of_dims) + helpers.test_frontend_function( + input_dtypes=input_dtype, + backend_to_test=backend_fw, + test_flags=test_flags, + frontend=frontend, + fn_tree=fn_tree, + on_device=on_device, + input=value[0], + offset=offset, + dim1=dim1, + dim2=dim2, + ) + + # eig # TODO: Test for all valid dtypes once ivy.eig supports complex data types @handle_frontend_test( @@ -458,7 +532,7 @@ def test_torch_eig( ret = [ivy.to_numpy(x).astype("float64") for x in ret] frontend_ret = [np.asarray(x, dtype=np.float64) for x in frontend_ret] - l, v = ret + l, v = ret # noqa: E741 front_l, front_v = frontend_ret assert_all_close( @@ -467,6 +541,7 @@ def test_torch_eig( rtol=1e-2, atol=1e-2, ground_truth_backend=frontend, + backend=backend_fw, ) @@ -511,6 +586,7 @@ def test_torch_eigh( ret_np=Q @ np.diag(L) @ Q.T, ret_from_gt_np=frontend_Q @ np.diag(frontend_L) @ frontend_Q.T, atol=1e-02, + backend=backend_fw, ) @@ -541,7 +617,8 @@ def test_torch_eigvals( test_values=False, ) """In "ret" we have out eigenvalues calculated with our backend and in - "frontend_ret" are our eigenvalues calculated with the specified frontend.""" + "frontend_ret" are our eigenvalues calculated with the specified + frontend.""" """ Depending on the chosen framework there may be small differences between our @@ -580,6 +657,7 @@ def test_torch_eigvals( rtol=1e-2, atol=1e-2, ground_truth_backend=frontend, + backend=backend_fw, ) @@ -688,7 +766,7 @@ def test_torch_lu_factor( backend_fw, ): dtype, input = input_dtype_and_input - helpers.test_frontend_function( + ret = helpers.test_frontend_function( input_dtypes=dtype, backend_to_test=backend_fw, test_flags=test_flags, @@ -698,7 +776,59 @@ def test_torch_lu_factor( rtol=1e-03, atol=1e-02, A=input[0], + test_values=False, ) + ret_f, ret_gt = ret + LU, p = ret_f.LU, ret_f.p + L = np.tril(LU, -1) + np.eye(LU.shape[0]) + U = np.triu(LU) + P = np.eye(LU.shape[0])[p] + assert np.allclose(L @ U, P @ input[0]) + + +@handle_frontend_test( + fn_tree="torch.linalg.lu_factor_ex", + input_dtype_and_input=_get_dtype_and_matrix( + batch=True, square=True, invertible=True + ), +) +def test_torch_lu_factor_ex( + *, + input_dtype_and_input, + on_device, + fn_tree, + frontend, + test_flags, + backend_fw, +): + dtype, input = input_dtype_and_input + ret = helpers.test_frontend_function( + input_dtypes=dtype, + backend_to_test=backend_fw, + test_flags=test_flags, + frontend=frontend, + fn_tree=fn_tree, + on_device=on_device, + rtol=1e-03, + atol=1e-02, + A=input[0], + check_errors=False, + test_values=False, + ) + ret_f, ret_gt = ret + ret_f_matrix, ret_f_info = ret_f + if ret_f_info == 0: + ( + LU, + p, + ) = ( + ret_f_matrix.LU, + ret_f_matrix.p, + ) + L = np.tril(LU, -1) + np.eye(LU.shape[0]) + U = np.triu(LU) + P = np.eye(LU.shape[0])[p] + assert np.allclose(L @ U, P @ input[0]) @handle_frontend_test( @@ -769,32 +899,37 @@ def test_torch_matrix_exp( @handle_frontend_test( fn_tree="torch.linalg.matrix_norm", dtype_values_axis=helpers.dtype_values_axis( - available_dtypes=helpers.get_dtypes("valid"), + available_dtypes=helpers.get_dtypes("float_and_complex"), min_num_dims=2, min_axes_size=2, max_axes_size=2, - min_value=-1e04, - max_value=1e04, + max_value=10e4, + min_value=-10e4, + abs_smallest_val=10e-4, valid_axis=True, force_tuple_axis=True, ), ord=st.sampled_from(["fro", "nuc", np.inf, -np.inf, 1, -1, 2, -2]), keepdim=st.booleans(), - dtype=helpers.get_dtypes("valid", none=True, full=False), + dtypes=helpers.get_dtypes("float_and_complex", none=True, full=False), ) def test_torch_matrix_norm( *, dtype_values_axis, ord, keepdim, - dtype, frontend, + dtypes, test_flags, fn_tree, backend_fw, on_device, ): input_dtype, x, axis = dtype_values_axis + if dtypes[0] is not None and "complex128" in input_dtype[0]: + dtypes[0] = input_dtype[0] + if dtypes[0] is not None: + dtypes[0] = input_dtype[0][:-2] + max([input_dtype[0][-2:], dtypes[0][-2:]]) helpers.test_frontend_function( input_dtypes=input_dtype, @@ -809,7 +944,7 @@ def test_torch_matrix_norm( ord=ord, dim=axis, keepdim=keepdim, - dtype=dtype[0], + dtype=dtypes[0], ) @@ -867,9 +1002,11 @@ def test_torch_matrix_rank( test_flags=test_flags, fn_tree=fn_tree, on_device=on_device, + rtol=0, + atol=0, input=x, - rtol=rtol, - atol=atol, + arg_rtol=rtol, + arg_atol=atol, hermitian=hermitian, ) @@ -1000,6 +1137,7 @@ def test_torch_qr( rtol=1e-2, atol=1e-2, ground_truth_backend=frontend, + backend=backend_fw, ) ivy.previous_backend() @@ -1149,6 +1287,7 @@ def test_torch_svd( rtol=1e-2, atol=1e-2, ground_truth_backend=frontend, + backend=backend_fw, ) diff --git a/ivy_tests/test_ivy/test_frontends/test_torch/test_miscellaneous_ops.py b/ivy_tests/test_ivy/test_frontends/test_torch/test_miscellaneous_ops.py index 340fe6bed6930..90fb791284ad3 100644 --- a/ivy_tests/test_ivy/test_frontends/test_torch/test_miscellaneous_ops.py +++ b/ivy_tests/test_ivy/test_frontends/test_torch/test_miscellaneous_ops.py @@ -8,6 +8,7 @@ # local import ivy import ivy_tests.test_ivy.helpers as helpers +from ivy_tests.test_ivy.helpers.hypothesis_helpers.general_helpers import sizes_ from ivy_tests.test_ivy.helpers import handle_frontend_test from ivy_tests.test_ivy.test_functional.test_core.test_linalg import ( _get_dtype_value1_value2_axis_for_tensordot, @@ -190,17 +191,6 @@ def complex_strategy( return tuple(shape) -@st.composite -def dims_and_offset(draw, shape): - shape_actual = draw(shape) - dim1 = draw(helpers.get_axis(shape=shape, force_int=True)) - dim2 = draw(helpers.get_axis(shape=shape, force_int=True)) - offset = draw( - st.integers(min_value=-shape_actual[dim1], max_value=shape_actual[dim1]) - ) - return dim1, dim2, offset - - # cross @st.composite def dtype_value1_value2_axis( @@ -510,6 +500,50 @@ def test_torch_cartesian_prod( ) +@handle_frontend_test( + fn_tree="torch.cdist", + dtypes_and_x=helpers.dtype_and_values( + shape=st.shared(helpers.get_shape(min_num_dims=2, max_num_dims=3), key="shape"), + shared_dtype=True, + num_arrays=2, + allow_inf=False, + available_dtypes=["float32", "float64"], + ), + p=st.integers(min_value=0, max_value=1000000), + compute_mode=st.sampled_from( + [ + "use_mm_for_euclid_dist_if_necessary", + "use_mm_for_euclid_dist", + "donot_use_mm_for_euclid_dist", + ] + ), +) +def test_torch_cdist( + *, + dtypes_and_x, + p, + compute_mode, + on_device, + fn_tree, + frontend, + test_flags, + backend_fw, +): + input_dtypes, xs = dtypes_and_x + helpers.test_frontend_function( + input_dtypes=input_dtypes, + backend_to_test=backend_fw, + frontend=frontend, + test_flags=test_flags, + fn_tree=fn_tree, + on_device=on_device, + x1=xs[0], + x2=xs[1], + p=p, + compute_mode=compute_mode, + ) + + # clone @handle_frontend_test( fn_tree="torch.clone", @@ -543,7 +577,7 @@ def test_torch_clone( @handle_frontend_test( fn_tree="torch.corrcoef", dtypes_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("float"), + available_dtypes=helpers.get_dtypes("valid"), num_arrays=1, min_num_dims=2, max_num_dims=2, @@ -563,7 +597,7 @@ def test_torch_corrcoef( ): input_dtypes, x = dtypes_and_x helpers.test_frontend_function( - input_dtypes=["float64"], + input_dtypes=input_dtypes, frontend=frontend, fn_tree=fn_tree, test_flags=test_flags, @@ -855,7 +889,7 @@ def test_torch_diagflat( available_dtypes=helpers.get_dtypes("float"), shape=st.shared(helpers.get_shape(min_num_dims=2), key="shape"), ), - dims_and_offset=dims_and_offset( + dims_and_offset=helpers.dims_and_offset( shape=st.shared(helpers.get_shape(min_num_dims=2), key="shape") ), ) @@ -973,6 +1007,38 @@ def test_torch_einsum( ) +# erfinv +@handle_frontend_test( + fn_tree="torch.special.erfinv", + aliases=["torch.erfinv"], + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("float"), + min_value=-1, + max_value=1, + abs_smallest_val=1e-05, + ), +) +def test_torch_erfinv( + *, + dtype_and_x, + on_device, + fn_tree, + frontend, + test_flags, + backend_fw, +): + input_dtype, x = dtype_and_x + helpers.test_frontend_function( + input_dtypes=input_dtype, + backend_to_test=backend_fw, + frontend=frontend, + test_flags=test_flags, + fn_tree=fn_tree, + on_device=on_device, + input=x[0], + ) + + @handle_frontend_test( fn_tree="torch.flatten", dtype_input_axes=helpers.dtype_values_axis( @@ -1502,10 +1568,10 @@ def test_torch_rot90( max_num_dims=1, num_arrays=2, ), - side=st.sampled_from(["left", "right"]), + side=st.sampled_from(["left", "right", None]), out_int32=st.booleans(), - right=st.just(False), - test_with_out=st.just(False), + right=st.sampled_from([True, False, None]), + test_with_out=st.booleans(), ) def test_torch_searchsorted( dtype_x_v, @@ -1518,6 +1584,13 @@ def test_torch_searchsorted( backend_fw, on_device, ): + potential_kwargs = {} + if side == "left" and right: + right = None # this combo will cause an exception + if side is not None: + potential_kwargs["side"] = side + if right is not None: + potential_kwargs["right"] = right input_dtypes, xs = dtype_x_v use_sorter = st.booleans() if use_sorter: @@ -1535,10 +1608,9 @@ def test_torch_searchsorted( on_device=on_device, sorted_sequence=xs[0], values=xs[1], - side=side, out_int32=out_int32, - right=right, sorter=sorter, + **potential_kwargs, ) @@ -1733,6 +1805,47 @@ def test_torch_triu_indices( ) +# unflatten +@handle_frontend_test( + fn_tree="torch.unflatten", + shape=st.shared(helpers.get_shape(min_num_dims=1), key="shape"), + dtype_and_values=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), + min_num_dims=1, + shape_key="shape", + ), + axis=helpers.get_axis( + shape=st.shared(helpers.get_shape(min_num_dims=1), key="shape"), + force_int=True, + ), +) +def test_torch_unflatten( + *, + dtype_and_values, + on_device, + fn_tree, + frontend, + test_flags, + backend_fw, + shape, + axis, +): + dtype, x = dtype_and_values + sizes = sizes_(shape, axis) + helpers.test_frontend_function( + input_dtypes=dtype, + frontend=frontend, + backend_to_test=backend_fw, + test_flags=test_flags, + fn_tree=fn_tree, + on_device=on_device, + test_values=False, + input=x[0], + dim=axis, + sizes=sizes, + ) + + # vander @handle_frontend_test( fn_tree="torch.vander", diff --git a/ivy_tests/test_ivy/test_frontends/test_torch/test_nn/test_functional/test_convolution_functions.py b/ivy_tests/test_ivy/test_frontends/test_torch/test_nn/test_functional/test_convolution_functions.py index d2e95a4269d04..de8d285f5d7d3 100644 --- a/ivy_tests/test_ivy/test_frontends/test_torch/test_nn/test_functional/test_convolution_functions.py +++ b/ivy_tests/test_ivy/test_frontends/test_torch/test_nn/test_functional/test_convolution_functions.py @@ -3,7 +3,6 @@ from hypothesis import strategies as st, assume # local -import ivy import ivy_tests.test_ivy.helpers as helpers from ivy_tests.test_ivy.helpers import handle_frontend_test from ivy_tests.test_ivy.test_functional.test_nn.test_layers import ( @@ -44,7 +43,7 @@ def _fold_helper(draw, dim=2): ) ) if vals.shape[0] == 1: # un-batched inputs are also supported - vals = draw(st.one_of(st.just(vals), st.just(ivy.squeeze(vals, axis=0)))) + vals = draw(st.sampled_from([vals, vals[0]])) return dtype, vals, kernel_size, output_shape, dilation, stride, padding @@ -82,14 +81,14 @@ def _fold_unfold_helper(draw, dim): def _output_shape( dims, dilation, stride, padding, output_padding, input_shape, weight_shape ): - dilation, stride, padding, output_padding = map( + padding, output_padding = map( lambda x: [x] * dims if isinstance(x, int) else x, - [dilation, stride, padding, output_padding], + [padding, output_padding], ) return [ - (input_shape[2 + i] - 1) * stride[i] + (input_shape[i] - 1) * stride[i] - 2 * padding[i] - + dilation[i] * (weight_shape[2 + i] - 1) + + dilation[i] * (weight_shape[i] - 1) + output_padding[i] + 1 for i in range(dims) @@ -120,7 +119,7 @@ def _unfold_helper(draw, dim=2): @st.composite -def _x_and_filters(draw, dim: int = 2, transpose: bool = False): +def _x_and_filters(draw, dim: int = 2, transpose: bool = False, max_dilation=3): if not isinstance(dim, int): dim = draw(dim) strides = draw( @@ -153,7 +152,7 @@ def _x_and_filters(draw, dim: int = 2, transpose: bool = False): ) ) batch_size = draw(st.integers(1, 5)) - filter_shape = draw( + filter_dim = draw( helpers.get_shape( min_num_dims=dim, max_num_dims=dim, min_dim_size=1, max_dim_size=5 ) @@ -169,11 +168,15 @@ def _x_and_filters(draw, dim: int = 2, transpose: bool = False): fc = draw(st.sampled_from(group_list)) dilations = draw( st.one_of( - st.lists(st.integers(min_value=1, max_value=3), min_size=dim, max_size=dim), - st.integers(min_value=1, max_value=3), + st.lists( + st.integers(min_value=1, max_value=max_dilation), + min_size=dim, + max_size=dim, + ), + st.integers(min_value=1, max_value=max_dilation), ) ) - full_dilations = [dilations] * dim if isinstance(dilations, int) else dilations + fdilations = [dilations] * dim if isinstance(dilations, int) else dilations if transpose: x_dim = draw( helpers.get_shape( @@ -183,15 +186,15 @@ def _x_and_filters(draw, dim: int = 2, transpose: bool = False): else: x_dim = [] for i in range(dim): - min_x = filter_shape[i] + (filter_shape[i] - 1) * (full_dilations[i] - 1) + min_x = filter_dim[i] + (filter_dim[i] - 1) * (fdilations[i] - 1) x_dim.append(draw(st.integers(min_x, 15))) x_dim = tuple(x_dim) if not transpose: output_channels = output_channels * fc - filter_shape = (output_channels, input_channels // fc) + filter_shape + filter_shape = (output_channels, input_channels // fc) + filter_dim else: input_channels = input_channels * fc - filter_shape = (input_channels, output_channels // fc) + filter_shape + filter_shape = (input_channels, output_channels // fc) + filter_dim x_shape = (batch_size, input_channels) + x_dim vals = draw( helpers.array_values( @@ -218,18 +221,30 @@ def _x_and_filters(draw, dim: int = 2, transpose: bool = False): ) ) if transpose: - full_strides = [strides] * dim if isinstance(strides, int) else strides + fstrides = [strides] * dim if isinstance(strides, int) else strides output_padding = draw( st.lists(st.integers(min_value=1, max_value=2), min_size=dim, max_size=dim) ) padding = [padding] * dim if isinstance(padding, int) else padding for i in range(len(output_padding)): - # ToDo: remove this when support for output_padding > padding is added - output_padding[i] = min(padding[i], output_padding[i]) - m = min(full_strides[i], full_dilations[i]) + m = min(fstrides[i], fdilations[i]) output_padding[i] = min(output_padding[i], m - 1) if draw(st.booleans()): output_padding = min(output_padding) + assume( + all( + s > 0 + for s in _output_shape( + dim, + fdilations, + fstrides, + padding, + output_padding, + x_dim, + filter_dim, + ) + ) + ) return ( dtype, vals, @@ -348,7 +363,7 @@ def test_torch_conv3d( fn_tree="torch.nn.functional.conv_transpose1d", dtype_vals=_x_and_filters(dim=1, transpose=True), ) -def test_torch_conv_tranpose1d( +def test_torch_conv_transpose1d( *, dtype_vals, on_device, @@ -358,15 +373,14 @@ def test_torch_conv_tranpose1d( backend_fw, ): dtype, vals, weight, bias, dilations, strides, padding, output_pad, fc = dtype_vals - dilations = 1 # ToDo: remove this when support for dilation > 1 is added assume( - all( - x > 0 - for x in _output_shape( - 1, dilations, strides, padding, output_pad, vals.shape, weight.shape - ) + backend_fw in ["torch", "tensorflow"] + or all( + dil == 1 + for dil in ([dilations] if isinstance(dilations, int) else dilations) ) ) + _assume_tf_dilation_gt_1(backend_fw, on_device, dilations) helpers.test_frontend_function( input_dtypes=dtype, backend_to_test=backend_fw, @@ -389,7 +403,7 @@ def test_torch_conv_tranpose1d( fn_tree="torch.nn.functional.conv_transpose2d", dtype_vals=_x_and_filters(dim=2, transpose=True), ) -def test_torch_conv_tranpose2d( +def test_torch_conv_transpose2d( *, dtype_vals, on_device, @@ -399,15 +413,14 @@ def test_torch_conv_tranpose2d( backend_fw, ): dtype, vals, weight, bias, dilations, strides, padding, output_pad, fc = dtype_vals - dilations = 1 # ToDo: remove this when support for dilation > 1 is added assume( - all( - x > 0 - for x in _output_shape( - 2, dilations, strides, padding, output_pad, vals.shape, weight.shape - ) + backend_fw in ["torch", "tensorflow"] + or all( + dil == 1 + for dil in ([dilations] if isinstance(dilations, int) else dilations) ) ) + _assume_tf_dilation_gt_1(backend_fw, on_device, dilations) helpers.test_frontend_function( input_dtypes=dtype, backend_to_test=backend_fw, @@ -430,7 +443,7 @@ def test_torch_conv_tranpose2d( fn_tree="torch.nn.functional.conv_transpose3d", dtype_vals=_x_and_filters(dim=3, transpose=True), ) -def test_torch_conv_tranpose3d( +def test_torch_conv_transpose3d( *, dtype_vals, on_device, @@ -440,15 +453,14 @@ def test_torch_conv_tranpose3d( backend_fw, ): dtype, vals, weight, bias, dilations, strides, padding, output_pad, fc = dtype_vals - dilations = 1 # ToDo: remove this when support for dilation > 1 is added assume( - all( - x > 0 - for x in _output_shape( - 3, dilations, strides, padding, output_pad, vals.shape, weight.shape - ) + backend_fw in ["torch", "tensorflow"] + or all( + dil == 1 + for dil in ([dilations] if isinstance(dilations, int) else dilations) ) ) + _assume_tf_dilation_gt_1(backend_fw, on_device, dilations) helpers.test_frontend_function( input_dtypes=dtype, backend_to_test=backend_fw, diff --git a/ivy_tests/test_ivy/test_frontends/test_torch/test_nn/test_functional/test_dropout_functions.py b/ivy_tests/test_ivy/test_frontends/test_torch/test_nn/test_functional/test_dropout_functions.py index 16d6c9dc1a321..c7d6bac0556a1 100644 --- a/ivy_tests/test_ivy/test_frontends/test_torch/test_nn/test_functional/test_dropout_functions.py +++ b/ivy_tests/test_ivy/test_frontends/test_torch/test_nn/test_functional/test_dropout_functions.py @@ -80,23 +80,35 @@ def test_torch_dropout( backend_fw, ): input_dtype, x = dtype_and_x - ret = helpers.test_frontend_function( - input_dtypes=input_dtype, - backend_to_test=backend_fw, - frontend=frontend, - test_flags=test_flags, - fn_tree=fn_tree, - on_device=on_device, - input=x[0], - p=prob, - training=training, - test_values=False, - ) - ret = helpers.flatten_and_to_np(ret=ret, backend=backend_fw) - x = np.asarray(x[0], input_dtype[0]) - for u in ret: - # cardinality test - assert u.shape == x.shape + if not training or prob == 0: + helpers.test_frontend_function( + input_dtypes=input_dtype, + backend_to_test=backend_fw, + frontend=frontend, + test_flags=test_flags, + fn_tree=fn_tree, + on_device=on_device, + input=x[0], + p=prob, + training=training, + ) + else: + ret = helpers.test_frontend_function( + input_dtypes=input_dtype, + backend_to_test=backend_fw, + frontend=frontend, + test_flags=test_flags, + fn_tree=fn_tree, + on_device=on_device, + input=x[0], + p=prob, + training=training, + test_values=False, + ) + ret = helpers.flatten_and_to_np(ret=ret, backend=backend_fw) + for u in ret: + # cardinality test + assert u.shape == x[0].shape @handle_frontend_test( diff --git a/ivy_tests/test_ivy/test_frontends/test_torch/test_nn/test_functional/test_layer_functions.py b/ivy_tests/test_ivy/test_frontends/test_torch/test_nn/test_functional/test_layer_functions.py index 32f7508490e1b..453026fad8ea9 100644 --- a/ivy_tests/test_ivy/test_frontends/test_torch/test_nn/test_functional/test_layer_functions.py +++ b/ivy_tests/test_ivy/test_frontends/test_torch/test_nn/test_functional/test_layer_functions.py @@ -4,10 +4,7 @@ # local import ivy -from ivy.functional.ivy.layers import _get_embed_dim -from ivy.functional.frontends.torch.nn.functional.layer_functions import ( - _pack_padded_sequence, -) +from ivy.functional.ivy.layers import _get_embed_dim, _pack_padded_sequence from ivy_tests.test_ivy import helpers from ivy_tests.test_ivy.helpers import handle_frontend_test from ivy_tests.test_ivy.test_functional.test_nn.test_layers import _mha_helper @@ -120,9 +117,9 @@ def _lstm_helper(draw): ) ) batch_sizes = np.array(draw(st.permutations(batch_sizes))) - input, batch_sizes = [ + input, batch_sizes = ( ivy.to_numpy(p) for p in _pack_padded_sequence(input, batch_sizes) - ] + ) else: batch_sizes = None @@ -178,7 +175,7 @@ def test_torch_lstm( ): dtypes, kwargs = dtypes_kwargs # Todo: Debug the function to have this case passing as well - assume("batch_sizes" not in kwargs or not kwargs["bidirectional"]) + assume("batch_sizes" not in kwargs) helpers.test_frontend_function( input_dtypes=dtypes, backend_to_test=backend_fw, diff --git a/ivy_tests/test_ivy/test_frontends/test_torch/test_nn/test_functional/test_loss_functions.py b/ivy_tests/test_ivy/test_frontends/test_torch/test_nn/test_functional/test_loss_functions.py index 7ced14b897bc6..13abfcfcee803 100644 --- a/ivy_tests/test_ivy/test_frontends/test_torch/test_nn/test_functional/test_loss_functions.py +++ b/ivy_tests/test_ivy/test_frontends/test_torch/test_nn/test_functional/test_loss_functions.py @@ -685,11 +685,13 @@ def test_torch_multilabel_margin_loss( reduce, test_flags, fn_tree, + backend_fw, frontend, on_device, ): input_dtype, x = dtype_and_inputs helpers.test_frontend_function( + backend_to_test=backend_fw, input_dtypes=input_dtype, frontend=frontend, test_flags=test_flags, diff --git a/ivy_tests/test_ivy/test_frontends/test_torch/test_nn/test_functional/test_non_linear_activation_functions.py b/ivy_tests/test_ivy/test_frontends/test_torch/test_nn/test_functional/test_non_linear_activation_functions.py index 2c9dc0c529024..3f3e971ea1bc1 100644 --- a/ivy_tests/test_ivy/test_frontends/test_torch/test_nn/test_functional/test_non_linear_activation_functions.py +++ b/ivy_tests/test_ivy/test_frontends/test_torch/test_nn/test_functional/test_non_linear_activation_functions.py @@ -515,8 +515,18 @@ def test_torch_hardtanh_( fn_tree="torch.nn.functional.leaky_relu", dtype_and_x=helpers.dtype_and_values( available_dtypes=helpers.get_dtypes("float"), + min_num_dims=1, + large_abs_safety_factor=25, + small_abs_safety_factor=25, + safety_factor_scale="log", + ), + alpha=helpers.floats( + min_value=0, + max_value=1, + large_abs_safety_factor=25, + small_abs_safety_factor=25, + safety_factor_scale="log", ), - alpha=st.floats(min_value=0.0, max_value=1.0, exclude_min=True), test_inplace=st.booleans(), test_with_out=st.just(False), ) @@ -583,11 +593,13 @@ def test_torch_leaky_relu_( # local_response_norm @handle_frontend_test( fn_tree="torch.nn.functional.local_response_norm", - dtype_x_and_axis=helpers.dtype_values_axis( - available_dtypes=helpers.get_dtypes("float"), + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), min_num_dims=3, - force_int_axis=True, - valid_axis=True, + max_num_dims=4, + large_abs_safety_factor=2, + small_abs_safety_factor=2, + safety_factor_scale="log", ), size=helpers.ints(min_value=3, max_value=10), alpha=helpers.floats(min_value=1e-4, max_value=1e-3), @@ -596,7 +608,7 @@ def test_torch_leaky_relu_( ) def test_torch_local_response_norm( *, - dtype_x_and_axis, + dtype_and_x, size, alpha, beta, @@ -607,7 +619,7 @@ def test_torch_local_response_norm( test_flags, backend_fw, ): - dtype, x, axis = dtype_x_and_axis + dtype, x = dtype_and_x _filter_dtypes(dtype) helpers.test_frontend_function( input_dtypes=dtype, @@ -647,7 +659,6 @@ def test_torch_log_softmax( backend_fw, ): input_dtype, x, axis = dtype_x_and_axis - ivy.set_backend(backend_fw) helpers.test_frontend_function( input_dtypes=input_dtype, backend_to_test=backend_fw, @@ -658,9 +669,8 @@ def test_torch_log_softmax( input=x[0], dim=axis, _stacklevel=3, - dtype=ivy.as_ivy_dtype(dtypes[0]), + dtype=dtypes[0], ) - ivy.previous_backend() # logsigmoid diff --git a/ivy_tests/test_ivy/test_frontends/test_torch/test_nn/test_functional/test_pooling_functions.py b/ivy_tests/test_ivy/test_frontends/test_torch/test_nn/test_functional/test_pooling_functions.py index 8d940f3f91acd..a4c3e9bf7de99 100644 --- a/ivy_tests/test_ivy/test_frontends/test_torch/test_nn/test_functional/test_pooling_functions.py +++ b/ivy_tests/test_ivy/test_frontends/test_torch/test_nn/test_functional/test_pooling_functions.py @@ -9,15 +9,13 @@ def calculate_same_padding(kernel_size, stride, shape): padding = tuple( - [ - max( - 0, - math.ceil(((shape[i] - 1) * stride[i] + kernel_size[i] - shape[i]) / 2), - ) - for i in range(len(kernel_size)) - ] + max( + 0, + math.ceil(((shape[i] - 1) * stride[i] + kernel_size[i] - shape[i]) / 2), + ) + for i in range(len(kernel_size)) ) - if all([kernel_size[i] / 2 >= padding[i] for i in range(len(kernel_size))]): + if all(kernel_size[i] / 2 >= padding[i] for i in range(len(kernel_size))): if is_same_padding(padding, stride, kernel_size, shape): return padding return [0] * len(shape) @@ -25,16 +23,12 @@ def calculate_same_padding(kernel_size, stride, shape): def is_same_padding(padding, stride, kernel_size, input_shape): output_shape = tuple( - [ - (input_shape[i] + 2 * padding[i] - kernel_size[i]) // stride[i] + 1 - for i in range(len(padding)) - ] + (input_shape[i] + 2 * padding[i] - kernel_size[i]) // stride[i] + 1 + for i in range(len(padding)) ) return all( - [ - output_shape[i] == math.ceil(input_shape[i] / stride[i]) - for i in range(len(padding)) - ] + output_shape[i] == math.ceil(input_shape[i] / stride[i]) + for i in range(len(padding)) ) @@ -124,7 +118,7 @@ def test_torch_adaptive_avg_pool2d( @handle_frontend_test( fn_tree="torch.nn.functional.adaptive_max_pool2d", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("float"), + available_dtypes=helpers.get_dtypes("valid"), min_num_dims=3, max_num_dims=4, min_dim_size=5, @@ -166,6 +160,49 @@ def test_torch_adaptive_max_pool2d( ) +@handle_frontend_test( + fn_tree="torch.nn.functional.adaptive_max_pool3d", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("float"), + min_num_dims=4, + max_num_dims=5, + min_dim_size=2, + max_value=100, + min_value=-100, + ), + output_size=st.one_of( + st.tuples( + helpers.ints(min_value=1, max_value=5), + helpers.ints(min_value=1, max_value=5), + helpers.ints(min_value=1, max_value=5), + ), + helpers.ints(min_value=1, max_value=5), + ), + test_with_out=st.just(False), +) +def test_torch_adaptive_max_pool3d( + *, + dtype_and_x, + output_size, + on_device, + frontend, + test_flags, + fn_tree, + backend_fw, +): + input_dtype, x = dtype_and_x + helpers.test_frontend_function( + input_dtypes=input_dtype, + backend_to_test=backend_fw, + frontend=frontend, + test_flags=test_flags, + fn_tree=fn_tree, + on_device=on_device, + input=x[0], + output_size=output_size, + ) + + # avg_pool1d @handle_frontend_test( fn_tree="torch.nn.functional.avg_pool1d", @@ -177,7 +214,7 @@ def test_torch_adaptive_max_pool2d( data_format="channel_first", only_explicit_padding=True, ), - count_include_pad=st.just(False), + count_include_pad=st.booleans(), ceil_mode=st.booleans(), test_with_out=st.just(False), ) @@ -193,14 +230,8 @@ def test_torch_avg_pool1d( on_device, ): input_dtype, x, kernel_size, stride, padding = dtype_x_k_s - # TODO: remove the processing of padding attribute when ivy.avg_pool - # support explicit padding - x_shape = [x[0].shape[2]] - padding = [pad[i] for i, pad in enumerate(padding)] - # figuring out the exact kernel_size for SAME and VALID padding - # As ivy.avg_pool1d doesn't support explicit padding scheme - if not sum(padding) == 0: - padding = calculate_same_padding(kernel_size, stride, x_shape) + if not isinstance(padding, int): + padding = [pad[0] for pad in padding] helpers.test_frontend_function( input_dtypes=input_dtype, backend_to_test=backend_fw, @@ -244,12 +275,8 @@ def test_torch_avg_pool2d( on_device, ): input_dtype, x, kernel_size, stride, padding = dtype_x_k_s - # TODO: remove the processing of padding attribute when ivy.avg_pool - # support explicit padding - padding = [pad[i] for i, pad in enumerate(padding)] - x_shape = x[0].shape[2:] - if not sum(padding) == 0: - padding = calculate_same_padding(kernel_size, [stride[0]] * 2, x_shape) + if not isinstance(padding, int): + padding = [pad[0] for pad in padding] helpers.test_frontend_function( input_dtypes=input_dtype, backend_to_test=backend_fw, @@ -296,13 +323,8 @@ def test_torch_avg_pool3d( on_device, ): input_dtype, x, kernel_size, stride, padding = dtype_x_k_s - # TODO: remove the processing of padding and strides attributes when ivy.avg_pool - # support explicit padding - x_shape = x[0].shape[2:] - padding = [pad[0] for pad in padding] - if not sum(padding) == 0: - stride_broad = (stride[0],) * 3 if len(stride) == 1 else stride - padding = calculate_same_padding(kernel_size, stride_broad, x_shape) + if not isinstance(padding, int): + padding = [pad[0] for pad in padding] helpers.test_frontend_function( input_dtypes=input_dtype, backend_to_test=backend_fw, @@ -320,7 +342,7 @@ def test_torch_avg_pool3d( ) -# avg_pool1d +# lp_pool1d @handle_frontend_test( fn_tree="torch.nn.functional.lp_pool1d", dtype_x_k_s=helpers.arrays_for_pooling( @@ -360,7 +382,7 @@ def test_torch_lp_pool1d( ) -# avg_pool2d +# lp_pool2d @handle_frontend_test( fn_tree="torch.nn.functional.lp_pool2d", dtype_x_k_s=helpers.arrays_for_pooling( @@ -408,12 +430,15 @@ def test_torch_lp_pool2d( min_side=1, max_side=3, only_explicit_padding=True, + return_dilation=True, data_format="channel_first", ), test_with_out=st.just(False), + ceil_mode=st.booleans(), ) def test_torch_max_pool1d( dtype_x_k_s, + ceil_mode, *, test_flags, frontend, @@ -421,19 +446,22 @@ def test_torch_max_pool1d( fn_tree, on_device, ): - input_dtype, x, kernel_size, stride, padding = dtype_x_k_s - padding = (padding[0][0],) + dtype, x, kernel, stride, padding, dilation = dtype_x_k_s + if not isinstance(padding, int): + padding = [pad[0] for pad in padding] helpers.test_frontend_function( - input_dtypes=input_dtype, + input_dtypes=dtype, backend_to_test=backend_fw, test_flags=test_flags, frontend=frontend, fn_tree=fn_tree, on_device=on_device, input=x[0], - kernel_size=kernel_size, + kernel_size=kernel, stride=stride, padding=padding, + dilation=dilation, + ceil_mode=ceil_mode, ) @@ -450,7 +478,7 @@ def test_torch_max_pool1d( data_format="channel_first", ), test_with_out=st.just(False), - ceil_mode=st.just(True), + ceil_mode=st.booleans(), ) def test_torch_max_pool2d( x_k_s_p, @@ -462,9 +490,9 @@ def test_torch_max_pool2d( fn_tree, on_device, ): - dtype, x, kernel, stride, pad, dilation = x_k_s_p - pad = (pad[0][0], pad[1][0]) - + dtype, x, kernel, stride, padding, dilation = x_k_s_p + if not isinstance(padding, int): + padding = [pad[0] for pad in padding] helpers.test_frontend_function( input_dtypes=dtype, backend_to_test=backend_fw, @@ -475,7 +503,7 @@ def test_torch_max_pool2d( input=x[0], kernel_size=kernel, stride=stride, - padding=pad, + padding=padding, dilation=dilation, ceil_mode=ceil_mode, ) @@ -495,10 +523,12 @@ def test_torch_max_pool2d( ), test_with_out=st.just(False), ceil_mode=st.booleans(), + without_batch=st.booleans(), ) def test_torch_max_pool3d( x_k_s_p, ceil_mode, + without_batch, *, test_flags, frontend, @@ -506,8 +536,11 @@ def test_torch_max_pool3d( fn_tree, on_device, ): - dtype, x, kernel, stride, pad, dilation = x_k_s_p - padding = (pad[0][0], pad[1][0], pad[2][0]) + dtype, x, kernel, stride, padding, dilation = x_k_s_p + if not isinstance(padding, int): + padding = [pad[0] for pad in padding] + if without_batch: + x = x[0] helpers.test_frontend_function( input_dtypes=dtype, backend_to_test=backend_fw, diff --git a/ivy_tests/test_ivy/test_frontends/test_torch/test_nn/test_functional/test_vision_functions.py b/ivy_tests/test_ivy/test_frontends/test_torch/test_nn/test_functional/test_vision_functions.py index 9c34752b567e5..58c58e87939ac 100644 --- a/ivy_tests/test_ivy/test_frontends/test_torch/test_nn/test_functional/test_vision_functions.py +++ b/ivy_tests/test_ivy/test_frontends/test_torch/test_nn/test_functional/test_vision_functions.py @@ -106,7 +106,7 @@ def _pad_helper(draw): ) padding = draw(_pad_generator(shape, mode)) if mode == "constant": - value = draw(helpers.ints(min_value=0, max_value=4)) + value = draw(helpers.ints(min_value=0, max_value=4) | st.none()) else: value = 0.0 return dtype, input[0], padding, value, mode @@ -238,7 +238,7 @@ def test_torch_grid_sample( @handle_frontend_test( fn_tree="torch.nn.functional.interpolate", dtype_and_input_and_other=_interp_args( - mode_list=["linear", "bilinear", "trilinear", "nearest", "area"], + mode_list="torch", ), number_positional_args=st.just(2), ) @@ -260,6 +260,8 @@ def test_torch_interpolate( scale_factor, recompute_scale_factor, ) = dtype_and_input_and_other + if mode not in ["linear", "bilinear", "bicubic", "trilinear"]: + align_corners = None helpers.test_frontend_function( input_dtypes=input_dtype, backend_to_test=backend_fw, @@ -267,8 +269,7 @@ def test_torch_interpolate( test_flags=test_flags, fn_tree=fn_tree, on_device=on_device, - rtol=1e-01, - atol=1e-01, + atol=1e-03, input=x[0], size=size, scale_factor=scale_factor, diff --git a/ivy_tests/test_ivy/test_frontends/test_torch/test_pointwise_ops.py b/ivy_tests/test_ivy/test_frontends/test_torch/test_pointwise_ops.py index 678aaad47bd17..52c15b10bd760 100644 --- a/ivy_tests/test_ivy/test_frontends/test_torch/test_pointwise_ops.py +++ b/ivy_tests/test_ivy/test_frontends/test_torch/test_pointwise_ops.py @@ -5,11 +5,10 @@ # local import ivy import ivy_tests.test_ivy.helpers as helpers -from ivy_tests.array_api_testing.test_array_api.array_api_tests import ( - hypothesis_helpers as hh, +from ivy_tests.test_ivy.helpers.hypothesis_helpers.general_helpers import ( + two_broadcastable_shapes, ) from ivy_tests.test_ivy.helpers import handle_frontend_test -from ivy_tests.test_ivy.test_functional.test_core.test_elementwise import pow_helper # --- Helpers --- # @@ -86,7 +85,7 @@ def _get_clip_inputs(draw): @st.composite def _masked_fill_helper(draw): - shape_1, shape_2 = draw(hh.two_broadcastable_shapes()) + shape_1, shape_2 = draw(two_broadcastable_shapes()) dtype, x = draw( helpers.dtype_and_values( available_dtypes=helpers.get_dtypes("valid"), @@ -117,7 +116,14 @@ def _masked_fill_helper(draw): fn_tree="torch.abs", aliases=["torch.absolute"], dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("numeric", full=False), + available_dtypes=helpers.get_dtypes("numeric", full=False).filter( + lambda x: "uint8" not in x[0] + and "int8" not in x[0] + and "uint16" not in x[0] + and "int16" not in x[0] + and "float16" not in x[0] + and "bfloat16" not in x[0] + ), large_abs_safety_factor=2.5, small_abs_safety_factor=2.5, safety_factor_scale="log", @@ -1175,7 +1181,8 @@ def test_torch_erf( # erfc @handle_frontend_test( - fn_tree="torch.erfc", + fn_tree="torch.special.erfc", + aliases=["torch.erfc"], dtype_and_x=helpers.dtype_and_values( available_dtypes=helpers.get_dtypes("float"), ), @@ -1205,7 +1212,7 @@ def test_torch_erfc( @handle_frontend_test( fn_tree="torch.exp", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("float"), + available_dtypes=helpers.get_dtypes("valid"), ), ) def test_torch_exp( @@ -2318,7 +2325,13 @@ def test_torch_positive( @handle_frontend_test( fn_tree="torch.pow", - dtype_and_x=pow_helper(), + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), + num_arrays=2, + min_value=1, + max_value=7, + shared_dtype=True, + ), ) def test_torch_pow( dtype_and_x, diff --git a/ivy_tests/test_ivy/test_frontends/test_torch/test_random_sampling.py b/ivy_tests/test_ivy/test_frontends/test_torch/test_random_sampling.py index 2b54f57e84078..9c9cd0341e71c 100644 --- a/ivy_tests/test_ivy/test_frontends/test_torch/test_random_sampling.py +++ b/ivy_tests/test_ivy/test_frontends/test_torch/test_random_sampling.py @@ -538,7 +538,7 @@ def call(): @handle_frontend_test( fn_tree="torch.set_rng_state", new_state=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("uint8"), + available_dtypes=helpers.get_dtypes("valid"), min_value=0, max_value=10, min_num_dims=1, diff --git a/ivy_tests/test_ivy/test_frontends/test_torch/test_reduction_ops.py b/ivy_tests/test_ivy/test_frontends/test_torch/test_reduction_ops.py index 213bcb0c14909..55e9ed5fd0eda 100644 --- a/ivy_tests/test_ivy/test_frontends/test_torch/test_reduction_ops.py +++ b/ivy_tests/test_ivy/test_frontends/test_torch/test_reduction_ops.py @@ -21,7 +21,7 @@ @st.composite def _get_axis_and_p(draw, kind="valid"): p = draw(st.sampled_from(["fro", "nuc", 1, 2, -1, -2, float("inf"), -float("inf")])) - if p == "fro" or p == "nuc": + if p in ["fro", "nuc"]: max_axes_size = 2 min_axes_size = 2 else: @@ -106,7 +106,7 @@ def test_torch_all( @handle_frontend_test( fn_tree="torch.amax", dtype_input_axis=helpers.dtype_values_axis( - available_dtypes=helpers.get_dtypes("numeric"), + available_dtypes=helpers.get_dtypes("valid"), min_num_dims=1, min_axis=-1, max_axis=0, @@ -140,7 +140,7 @@ def test_torch_amax( @handle_frontend_test( fn_tree="torch.amin", dtype_input_axis=helpers.dtype_values_axis( - available_dtypes=helpers.get_dtypes("numeric"), + available_dtypes=helpers.get_dtypes("valid"), min_num_dims=1, min_axis=-1, max_axis=0, @@ -174,7 +174,7 @@ def test_torch_amin( @handle_frontend_test( fn_tree="torch.aminmax", dtype_input_axis=helpers.dtype_values_axis( - available_dtypes=helpers.get_dtypes("numeric"), + available_dtypes=helpers.get_dtypes("valid"), min_num_dims=1, min_axis=-1, max_axis=0, @@ -209,6 +209,9 @@ def test_torch_aminmax( fn_tree="torch.any", dtype_input_axis=helpers.dtype_values_axis( available_dtypes=helpers.get_dtypes("valid"), + safety_factor_scale="log", + small_abs_safety_factor=8, + large_abs_safety_factor=8, min_axis=-1, max_axis=0, min_num_dims=1, @@ -476,7 +479,7 @@ def test_torch_mean( test_flags, backend_fw, ): - input_dtype, x, axis = dtype_and_x + input_dtype, x, axis, *_ = dtype_and_x helpers.test_frontend_function( input_dtypes=input_dtype, backend_to_test=backend_fw, @@ -495,7 +498,7 @@ def test_torch_mean( @handle_frontend_test( fn_tree="torch.median", dtype_input_axis=helpers.dtype_values_axis( - available_dtypes=helpers.get_dtypes("numeric"), + available_dtypes=helpers.get_dtypes("valid"), min_num_dims=1, valid_axis=True, force_int_axis=True, @@ -656,7 +659,7 @@ def test_torch_nanmean( test_flags, backend_fw, ): - input_dtype, x, axis = dtype_and_x + input_dtype, x, axis, *_ = dtype_and_x helpers.test_frontend_function( input_dtypes=input_dtype, backend_to_test=backend_fw, @@ -760,14 +763,14 @@ def test_torch_norm( helpers.test_frontend_function( backend_to_test=backend_fw, - input_dtypes=[x_dtype], + input_dtypes=x_dtype, frontend=frontend, test_flags=test_flags, fn_tree=fn_tree, on_device=on_device, rtol=1e-01, atol=1e-08, - input=x, + input=x[0], p=p, dim=axis, keepdim=keepdim, @@ -843,6 +846,8 @@ def test_torch_quantile( input_dtype, x, axis, interpolation, q = dtype_and_x if type(axis) is tuple: axis = axis[0] + if interpolation == "nearest_jax": + interpolation = "nearest" helpers.test_frontend_function( input_dtypes=input_dtype, backend_to_test=backend_fw, diff --git a/ivy_tests/test_ivy/test_frontends/test_torch/test_special_funcs.py b/ivy_tests/test_ivy/test_frontends/test_torch/test_special_funcs.py new file mode 100644 index 0000000000000..56bac4271b7bb --- /dev/null +++ b/ivy_tests/test_ivy/test_frontends/test_torch/test_special_funcs.py @@ -0,0 +1,30 @@ +# local +import ivy_tests.test_ivy.helpers as helpers +from ivy_tests.test_ivy.helpers import handle_frontend_test + + +@handle_frontend_test( + fn_tree="torch.special.erfcx", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("float"), + ), +) +def test_torch_erfcx( + *, + dtype_and_x, + on_device, + fn_tree, + frontend, + test_flags, + backend_fw, +): + input_dtype, x = dtype_and_x + helpers.test_frontend_function( + input_dtypes=input_dtype, + backend_to_test=backend_fw, + frontend=frontend, + test_flags=test_flags, + fn_tree=fn_tree, + on_device=on_device, + input=x[0], + ) diff --git a/ivy_tests/test_ivy/test_frontends/test_torch/test_spectral_ops.py b/ivy_tests/test_ivy/test_frontends/test_torch/test_spectral_ops.py index 6e6376537f430..50d1d3f49a6d4 100644 --- a/ivy_tests/test_ivy/test_frontends/test_torch/test_spectral_ops.py +++ b/ivy_tests/test_ivy/test_frontends/test_torch/test_spectral_ops.py @@ -66,6 +66,56 @@ def test_torch_blackman_window( ) +# hamming_window +@handle_frontend_test( + fn_tree="torch.hamming_window", + dtype_and_window_length=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("integer"), + max_num_dims=0, + min_value=1, + max_value=20, + ), + periodic=st.booleans(), + dtype_and_coefficients=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("float"), + max_num_dims=0, + num_arrays=2, + min_value=0, + max_value=5, + ), + dtype=helpers.get_dtypes("float"), + test_with_out=st.just(False), +) +def test_torch_hamming_window( + dtype_and_window_length, + periodic, + dtype_and_coefficients, + *, + dtype, + fn_tree, + frontend, + test_flags, + backend_fw, +): + window_length_dtype, window_length = dtype_and_window_length + coefficients_dtypes, coefficients = dtype_and_coefficients + + helpers.test_frontend_function( + input_dtypes=window_length_dtype + coefficients_dtypes, + window_length=int(window_length[0]), + periodic=periodic, + alpha=float(coefficients[0]), + beta=float(coefficients[1]), + dtype=dtype[0], + fn_tree=fn_tree, + frontend=frontend, + test_flags=test_flags, + backend_to_test=backend_fw, + rtol=1e-1, + atol=1e-1, + ) + + @handle_frontend_test( window_length=helpers.ints(min_value=1, max_value=100), dtype=helpers.get_dtypes("float", full=False), diff --git a/ivy_tests/test_ivy/test_frontends/test_torch/test_tensor.py b/ivy_tests/test_ivy/test_frontends/test_torch/test_tensor.py index 46ef776296160..fff739b50489d 100644 --- a/ivy_tests/test_ivy/test_frontends/test_torch/test_tensor.py +++ b/ivy_tests/test_ivy/test_frontends/test_torch/test_tensor.py @@ -21,6 +21,7 @@ # local import ivy_tests.test_ivy.helpers as helpers +from ivy_tests.test_ivy.helpers.hypothesis_helpers.general_helpers import sizes_ from ivy_tests.test_ivy.test_frontends.test_torch.test_blas_and_lapack_ops import ( _get_dtype_and_3dbatch_matrices, _get_dtype_input_and_matrices, @@ -351,11 +352,12 @@ def _repeat_helper(draw): @st.composite -def _requires_grad(draw): - dtype = draw(_dtypes())[0] +def _requires_grad_and_dtypes(draw): + dtypes = draw(_dtypes()) + dtype = dtypes[0] if ivy.is_int_dtype(dtype) or ivy.is_uint_dtype(dtype): - return draw(st.just(False)) - return draw(st.booleans()) + return draw(st.just(False)), dtypes + return draw(st.booleans()), dtypes @st.composite @@ -415,18 +417,6 @@ def _unfold_args(draw): return values_dtype, values, axis, size, step -# diagonal -@st.composite -def dims_and_offset(draw, shape): - shape_actual = draw(shape) - dim1 = draw(helpers.get_axis(shape=shape, force_int=True)) - dim2 = draw(helpers.get_axis(shape=shape, force_int=True)) - offset = draw( - st.integers(min_value=-shape_actual[dim1], max_value=shape_actual[dim1]) - ) - return dim1, dim2, offset - - # --- Main --- # # ------------ # @@ -513,6 +503,37 @@ def test_torch___and__( ) +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="torch.tensor", + method_name="__array__", + dtype_and_x=helpers.dtype_and_values(available_dtypes=helpers.get_dtypes("valid")), + dtype=helpers.get_dtypes("valid", full=False), +) +def test_torch___array__( + dtype_and_x, + dtype, + frontend, + backend_fw, +): + input_dtype, x = dtype_and_x + if x[0].dtype == "bfloat16": + return + dtype[0] = np.dtype(dtype[0]) + ret_gt = torch.tensor(x[0]).__array__(dtype[0]) + with BackendHandler.update_backend(backend_fw) as ivy_backend: + local_importer = ivy_backend.utils.dynamic_import + function_module = local_importer.import_module("ivy.functional.frontends.torch") + ret = function_module.tensor(x[0]).__array__(dtype[0]) + + helpers.value_test( + ret_np_flat=ret.ravel(), + ret_np_from_gt_flat=ret_gt.ravel(), + ground_truth_backend="torch", + backend=backend_fw, + ) + + @handle_frontend_method( class_tree=CLASS_TREE, init_tree="torch.tensor", @@ -719,6 +740,47 @@ def test_torch___gt__( frontend, on_device, backend_fw, +): + input_dtype, x = dtype_and_x + helpers.test_frontend_method( + init_input_dtypes=[input_dtype[0]], + backend_to_test=backend_fw, + init_all_as_kwargs_np={ + "data": x[0], + }, + method_input_dtypes=[input_dtype[1]], + method_all_as_kwargs_np={ + "other": x[1], + }, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + on_device=on_device, + ) + + +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="torch.tensor", + method_name="__iand__", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=st.one_of(st.just(("bool",)), helpers.get_dtypes("integer")), + num_arrays=2, + min_value=-1e04, + max_value=1e04, + allow_inf=False, + ), + test_inplace=st.just(True), +) +def test_torch___iand__( + dtype_and_x, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + backend_fw, ): input_dtype, x = dtype_and_x helpers.test_frontend_method( @@ -1171,7 +1233,7 @@ def test_torch___radd__( init_tree="torch.tensor", method_name="__rmul__", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("float"), + available_dtypes=helpers.get_dtypes("valid"), num_arrays=2, min_value=-1e04, max_value=1e04, @@ -1403,37 +1465,6 @@ def test_torch___truediv__( ) -@handle_frontend_method( - class_tree=CLASS_TREE, - init_tree="torch.tensor", - method_name="__array__", - dtype_and_x=helpers.dtype_and_values(available_dtypes=helpers.get_dtypes("valid")), - dtype=helpers.get_dtypes("valid", full=False), -) -def test_torch__array__( - dtype_and_x, - dtype, - frontend, - backend_fw, -): - input_dtype, x = dtype_and_x - if x[0].dtype == "bfloat16": - return - dtype[0] = np.dtype(dtype[0]) - ret_gt = torch.tensor(x[0]).__array__(dtype[0]) - with BackendHandler.update_backend(backend_fw) as ivy_backend: - local_importer = ivy_backend.utils.dynamic_import - function_module = local_importer.import_module("ivy.functional.frontends.torch") - ret = function_module.tensor(x[0]).__array__(dtype[0]) - - helpers.value_test( - ret_np_flat=ret.ravel(), - ret_np_from_gt_flat=ret_gt.ravel(), - ground_truth_backend="torch", - backend=backend_fw, - ) - - @given( dtype_x=helpers.dtype_and_values( available_dtypes=helpers.get_dtypes("valid", prune_function=False), @@ -2612,11 +2643,13 @@ def test_torch_angle( init_flags, method_flags, on_device, + backend_fw, ): input_dtype, values = dtype_and_values helpers.test_frontend_method( init_input_dtypes=input_dtype, + backend_to_test=backend_fw, init_all_as_kwargs_np={ "data": values[0], }, @@ -3977,10 +4010,12 @@ def test_torch_baddbmm_( init_flags, method_flags, on_device, + backend_fw, ): input_dtype, x, batch1, batch2 = dtype_and_matrices helpers.test_frontend_method( init_input_dtypes=input_dtype, + backend_to_test=backend_fw, init_all_as_kwargs_np={"data": x[0]}, method_input_dtypes=input_dtype, method_all_as_kwargs_np={ @@ -4013,6 +4048,7 @@ def test_torch_bernoulli( frontend_method_data, init_flags, method_flags, + on_device, backend_fw, ): input_dtype, x = dtype_and_x @@ -4028,6 +4064,7 @@ def test_torch_bernoulli( init_flags=init_flags, method_flags=method_flags, frontend=frontend, + on_device=on_device, ) @@ -4858,6 +4895,41 @@ def test_torch_clamp_min( ) +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="torch.tensor", + method_name="clamp_min_", + input_and_ranges=_get_clip_min_inputs(), + test_inplace=st.just(True), +) +def test_torch_clamp_min_( + input_and_ranges, + frontend_method_data, + init_flags, + backend_fw, + frontend, + on_device, + method_flags, +): + x_dtype, x, min = input_and_ranges + helpers.test_frontend_method( + init_input_dtypes=x_dtype, + backend_to_test=backend_fw, + init_all_as_kwargs_np={ + "data": x[0], + }, + method_input_dtypes=x_dtype, + method_all_as_kwargs_np={ + "min": min, + }, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + on_device=on_device, + ) + + # clip @handle_frontend_method( class_tree=CLASS_TREE, @@ -5808,7 +5880,7 @@ def test_torch_diag( available_dtypes=helpers.get_dtypes("valid"), shape=st.shared(helpers.get_shape(min_num_dims=2), key="shape"), ), - dims_and_offset=dims_and_offset( + dims_and_offset=helpers.dims_and_offset( shape=st.shared(helpers.get_shape(min_num_dims=2), key="shape") ), ) @@ -6362,6 +6434,83 @@ def test_torch_erf_( ) +# erfinv_ tests +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="torch.tensor", + method_name="erfinv_", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("float"), + min_value=-1, + max_value=1, + abs_smallest_val=1e-05, + ), +) +def test_torch_erfinv( + dtype_and_x, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + backend_fw, +): + input_dtype, x = dtype_and_x + helpers.test_frontend_method( + init_input_dtypes=input_dtype, + backend_to_test=backend_fw, + init_all_as_kwargs_np={ + "data": x[0], + }, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={}, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + on_device=on_device, + ) + + +# erfinv_ tests +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="torch.tensor", + method_name="erfinv_", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("float"), + min_value=-1, + max_value=1, + abs_smallest_val=1e-05, + ), + test_inplace=st.just(True), +) +def test_torch_erfinv_( + dtype_and_x, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + backend_fw, +): + input_dtype, x = dtype_and_x + helpers.test_frontend_method( + init_input_dtypes=input_dtype, + backend_to_test=backend_fw, + init_all_as_kwargs_np={ + "data": x[0], + }, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={}, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + on_device=on_device, + ) + + # exp @handle_frontend_method( class_tree=CLASS_TREE, @@ -6451,6 +6600,13 @@ def test_torch_expand( backend_fw, ): input_dtype, x, shape = dtype_x_shape + + if backend_fw == "paddle": + assume( + input_dtype[0] in ["int32", "int64", "float32", "float64", "bool"] + and len(shape) < 7 + ) + if unpack_shape: method_flags.num_positional_args = len(shape) + 1 size = {} @@ -6521,7 +6677,7 @@ def test_torch_expand_as( init_tree="torch.tensor", method_name="expm1", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("numeric"), + available_dtypes=helpers.get_dtypes("valid"), ), ) def test_torch_expm1( @@ -7076,6 +7232,44 @@ def test_torch_fmod_( ) +# frac +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="torch.tensor", + method_name="frac", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes(kind="valid"), + num_arrays=1, + max_value=1e6, + min_value=-1e6, + ), +) +def test_torch_frac( + dtype_and_x, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + backend_fw, +): + input_dtype, x = dtype_and_x + helpers.test_frontend_method( + init_input_dtypes=input_dtype, + backend_to_test=backend_fw, + init_all_as_kwargs_np={ + "data": x[0], + }, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={}, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + on_device=on_device, + ) + + @handle_frontend_method( class_tree=CLASS_TREE, init_tree="torch.tensor", @@ -7642,20 +7836,118 @@ def test_torch_index_fill( ) -# index_select +# todo: remove dtype specifications @handle_frontend_method( class_tree=CLASS_TREE, init_tree="torch.tensor", - method_name="index_select", - params_indices_others=helpers.array_indices_axis( - array_dtypes=helpers.get_dtypes("valid"), - indices_dtypes=["int64"], - max_num_dims=1, - indices_same_dims=True, + method_name="index_put", + x_and_indices=helpers.array_indices_axis( + array_dtypes=st.just(("float32",)), + indices_dtypes=st.just(("int64",)), + ), + values=helpers.dtype_and_values( + available_dtypes=st.just(("float32",)), max_num_dims=1, max_dim_size=1 ), + accumulate=st.booleans(), ) -def test_torch_index_select( - params_indices_others, +def test_torch_index_put( + x_and_indices, + values, + accumulate, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + backend_fw, +): + input_dtype, x, indices, *_ = x_and_indices + values_dtype, values = values + init_dtypes = [input_dtype[0]] + method_dtypes = [input_dtype[1], values_dtype[0]] + helpers.test_frontend_method( + init_input_dtypes=init_dtypes, + backend_to_test=backend_fw, + init_all_as_kwargs_np={ + "data": x, + }, + method_input_dtypes=method_dtypes, + method_all_as_kwargs_np={ + "indices": (indices,), + "values": values[0], + "accumulate": accumulate, + }, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + on_device=on_device, + ) + + +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="torch.tensor", + method_name="index_put_", + x_and_indices=helpers.array_indices_axis( + array_dtypes=st.just(("float32",)), + indices_dtypes=st.just(("int64",)), + ), + values=helpers.dtype_and_values( + available_dtypes=st.just(("float32",)), max_num_dims=1, max_dim_size=1 + ), + accumulate=st.booleans(), + test_inplace=st.just(True), +) +def test_torch_index_put_( + x_and_indices, + values, + accumulate, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + backend_fw, +): + input_dtype, x, indices, *_ = x_and_indices + values_dtype, values = values + init_dtypes = [input_dtype[0]] + method_dtypes = [input_dtype[1], values_dtype[0]] + helpers.test_frontend_method( + init_input_dtypes=init_dtypes, + backend_to_test=backend_fw, + init_all_as_kwargs_np={ + "data": x, + }, + method_input_dtypes=method_dtypes, + method_all_as_kwargs_np={ + "indices": (indices,), + "values": values[0], + "accumulate": accumulate, + }, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + on_device=on_device, + ) + + +# index_select +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="torch.tensor", + method_name="index_select", + params_indices_others=helpers.array_indices_axis( + array_dtypes=helpers.get_dtypes("valid"), + indices_dtypes=["int64"], + max_num_dims=1, + indices_same_dims=True, + ), +) +def test_torch_index_select( + params_indices_others, frontend_method_data, init_flags, method_flags, @@ -7891,6 +8183,44 @@ def test_torch_is_quantized( ivy.previous_backend() +# isfinite +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="torch.tensor", + method_name="isfinite", + dtype_and_input=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("numeric"), + min_value=-np.inf, + max_value=np.inf, + ), +) +def test_torch_isfinite( + *, + dtype_and_input, + on_device, + frontend, + backend_fw, + frontend_method_data, + init_flags, + method_flags, +): + input_dtype, x = dtype_and_input + helpers.test_frontend_method( + init_input_dtypes=input_dtype, + backend_to_test=backend_fw, + init_all_as_kwargs_np={ + "data": x[0], + }, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={}, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + on_device=on_device, + ) + + # isinf @handle_frontend_method( class_tree=CLASS_TREE, @@ -8556,6 +8886,51 @@ def test_torch_log_( ) +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="torch.tensor", + method_name="log_softmax", + dtype_x_and_axis=helpers.dtype_values_axis( + available_dtypes=helpers.get_dtypes("float"), + min_num_dims=1, + max_axes_size=1, + force_int_axis=True, + valid_axis=True, + ), + dtypes=helpers.get_dtypes("float", none=False, full=False), +) +def test_torch_log_softmax( + *, + dtype_x_and_axis, + dtypes, + on_device, + frontend, + backend_fw, + frontend_method_data, + init_flags, + method_flags, +): + input_dtype, x, axis = dtype_x_and_axis + + helpers.test_frontend_method( + init_input_dtypes=input_dtype, + backend_to_test=backend_fw, + init_all_as_kwargs_np={ + "data": x[0], + }, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={ + "dim": axis, + "dtype": dtypes[0], + }, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + on_device=on_device, + ) + + # logaddexp @handle_frontend_method( class_tree=CLASS_TREE, @@ -8782,6 +9157,44 @@ def test_torch_logical_or( ) +# logical_xor +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="torch.tensor", + method_name="logical_xor", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), + num_arrays=2, + ), +) +def test_torch_logical_xor( + dtype_and_x, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + backend_fw, +): + input_dtype, x = dtype_and_x + helpers.test_frontend_method( + init_input_dtypes=input_dtype, + backend_to_test=backend_fw, + init_all_as_kwargs_np={ + "data": x[0], + }, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={ + "other": x[1], + }, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + on_device=on_device, + ) + + # logit @handle_frontend_method( class_tree=CLASS_TREE, @@ -9850,6 +10263,39 @@ def test_torch_negative( ) +# new +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="torch.tensor", + method_name="new", + dtype_and_x=helpers.dtype_and_values(), +) +def test_torch_new_( + dtype_and_x, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + backend_fw, +): + input_dtype, x = dtype_and_x + helpers.test_frontend_method( + init_input_dtypes=input_dtype, + backend_to_test=backend_fw, + init_all_as_kwargs_np={ + "data": x[0], + }, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={}, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + on_device=on_device, + ) + + # new_empty (not actually intuitive for testing) @handle_frontend_method( class_tree=CLASS_TREE, @@ -9941,14 +10387,12 @@ def test_torch_new_full( min_dim_size=1, max_dim_size=10, ), - dtypes=_dtypes(), - requires_grad=_requires_grad(), + requires_grad_and_dtypes=_requires_grad_and_dtypes(), ) def test_torch_new_ones( dtype_and_x, size, - dtypes, - requires_grad, + requires_grad_and_dtypes, on_device, frontend_method_data, init_flags, @@ -9957,6 +10401,7 @@ def test_torch_new_ones( backend_fw, ): input_dtype, x = dtype_and_x + requires_grad, dtypes = requires_grad_and_dtypes helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, @@ -10030,14 +10475,12 @@ def test_torch_new_tensor( min_dim_size=1, max_dim_size=10, ), - dtypes=_dtypes(), - requires_grad=_requires_grad(), + requires_grad_and_dtypes=_requires_grad_and_dtypes(), ) def test_torch_new_zeros( dtype_and_x, size, - dtypes, - requires_grad, + requires_grad_and_dtypes, on_device, frontend_method_data, init_flags, @@ -10046,6 +10489,7 @@ def test_torch_new_zeros( backend_fw, ): input_dtype, x = dtype_and_x + requires_grad, dtypes = requires_grad_and_dtypes helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, @@ -10191,8 +10635,8 @@ def call(): return ret_np, ret_from_np = ret - ret_np = helpers.flatten_and_to_np(ret=ret_np) - ret_from_np = helpers.flatten_and_to_np(ret=ret_from_np) + ret_np = helpers.flatten_and_to_np(ret=ret_np, backend=backend_fw) + ret_from_np = helpers.flatten_and_to_np(ret=ret_from_np, backend=backend_fw) for u, v in zip(ret_np, ret_from_np): assert u.dtype == v.dtype assert u.shape == v.shape @@ -10317,9 +10761,10 @@ def test_torch_numpy( ) # manual testing required as function return is numpy frontend helpers.value_test( - ret_np_flat=helpers.flatten_and_to_np(ret=ret), + ret_np_flat=helpers.flatten_and_to_np(ret=ret, backend=backend_fw), ret_np_from_gt_flat=frontend_ret[0], ground_truth_backend="torch", + backend=backend_fw, ) @@ -10893,6 +11338,12 @@ def test_torch_repeat( backend_fw, ): input_dtype, x, repeats = dtype_x_repeats + + if backend_fw == "paddle": + # paddle only supports size of the shape of repeats + # to be less than or equal to 6 + assume(len(repeats) <= 6) + repeat = { "repeats": repeats, } @@ -11228,9 +11679,7 @@ def test_torch_scatter_( helpers.test_frontend_method( init_input_dtypes=[input_dtypes[0]], backend_to_test=backend_fw, - init_all_as_kwargs_np={ - "data": x, - }, + init_all_as_kwargs_np={"data": x}, method_input_dtypes=["int64", input_dtypes[0]], method_all_as_kwargs_np={ "dim": axis, @@ -12417,7 +12866,7 @@ def test_torch_sum( available_dtypes=helpers.get_dtypes("float"), min_value=0, max_value=10, - shape=helpers.ints(min_value=2, max_value=5).map(lambda x: tuple([x, x])), + shape=helpers.ints(min_value=2, max_value=5).map(lambda x: (x, x)), ), some=st.booleans(), compute_uv=st.booleans(), @@ -12706,6 +13155,158 @@ def test_torch_tanh_( ) +# corrcoef +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="torch.tensor", + method_name="corrcoef", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), + ), +) +def test_torch_tensor_corrcoef( + dtype_and_x, + frontend, + backend_fw, + frontend_method_data, + init_flags, + method_flags, + on_device, +): + input_dtype, x = dtype_and_x + helpers.test_frontend_method( + init_input_dtypes=input_dtype, + init_all_as_kwargs_np={ + "data": x[0], + }, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={}, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + backend_to_test=backend_fw, + on_device=on_device, + ) + + +# erfc_ +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="torch.tensor", + method_name="erfc_", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("float"), + ), +) +def test_torch_tensor_erfc_( + dtype_and_x, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + backend_fw, +): + input_dtype, x = dtype_and_x + helpers.test_frontend_method( + init_input_dtypes=input_dtype, + backend_to_test=backend_fw, + init_all_as_kwargs_np={ + "data": x[0], + }, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={}, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + on_device=on_device, + rtol_=1e-2, + atol_=1e-2, + ) + + +# logaddexp2 +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="torch.tensor", + method_name="logaddexp2", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("float"), + num_arrays=2, + min_num_dims=1, + min_value=-100, + max_value=100, + shared_dtype=True, + ), +) +def test_torch_tensor_logaddexp2( + dtype_and_x, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + backend_fw, +): + input_dtype, x = dtype_and_x + helpers.test_frontend_method( + init_input_dtypes=input_dtype, + backend_to_test=backend_fw, + init_all_as_kwargs_np={ + "data": x[0], + }, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={ + "other": x[1], + }, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + on_device=on_device, + ) + + +# negative_ +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="torch.tensor", + method_name="negative_", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), + min_value=-1e04, + max_value=1e04, + allow_inf=False, + ), +) +def test_torch_tensor_negative_( + dtype_and_x, + frontend, + frontend_method_data, + init_flags, + method_flags, + on_device, + backend_fw, +): + input_dtype, x = dtype_and_x + helpers.test_frontend_method( + init_input_dtypes=input_dtype, + backend_to_test=backend_fw, + init_all_as_kwargs_np={ + "data": x[0], + }, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={}, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + on_device=on_device, + ) + + # positive @handle_frontend_method( class_tree=CLASS_TREE, @@ -13415,6 +14016,54 @@ def test_torch_unbind( ) +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="torch.tensor", + method_name="unflatten", + shape=st.shared(helpers.get_shape(min_num_dims=1), key="shape"), + dtype_and_values=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), + min_num_dims=1, + shape_key="shape", + ), + axis=helpers.get_axis( + shape=st.shared(helpers.get_shape(min_num_dims=1), key="shape"), + force_int=True, + ), +) +def test_torch_unflatten( + *, + dtype_and_values, + on_device, + frontend, + backend_fw, + shape, + axis, + frontend_method_data, + init_flags, + method_flags, +): + dtype, x = dtype_and_values + sizes = sizes_(shape, axis) + helpers.test_frontend_method( + init_input_dtypes=dtype, + backend_to_test=backend_fw, + init_all_as_kwargs_np={ + "data": x[0], + }, + method_input_dtypes=dtype, + method_all_as_kwargs_np={ + "dim": axis, + "sizes": sizes, + }, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + on_device=on_device, + ) + + # unfold @handle_frontend_method( class_tree=CLASS_TREE, @@ -13453,6 +14102,55 @@ def test_torch_unfold( ) +# uniform_ +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="torch.tensor", + method_name="uniform_", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), + min_value=1, + max_value=5, + min_num_dims=1, + max_num_dims=5, + ), + from_=helpers.floats(min_value=-1000, max_value=0), + to=helpers.floats(min_value=1, max_value=1000), + test_inplace=st.just(True), +) +def test_torch_uniform_( + dtype_and_x, + from_, + to, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + backend_fw, +): + input_dtype, x = dtype_and_x + method_flags.num_positional_args = 3 + helpers.test_frontend_method( + init_input_dtypes=input_dtype, + backend_to_test=backend_fw, + init_all_as_kwargs_np={ + "data": x[0], + }, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={ + "from_": from_, + "to": to, + }, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + on_device=on_device, + test_values=False, + ) + + # unique @handle_frontend_method( class_tree=CLASS_TREE, diff --git a/ivy_tests/test_ivy/test_frontends/test_torch/test_tensor_functions.py b/ivy_tests/test_ivy/test_frontends/test_torch/test_tensor_functions.py index 920ffe8a46ce3..9f4632ec3bddc 100644 --- a/ivy_tests/test_ivy/test_frontends/test_torch/test_tensor_functions.py +++ b/ivy_tests/test_ivy/test_frontends/test_torch/test_tensor_functions.py @@ -10,6 +10,40 @@ ) +# broadcast_tensors +@handle_frontend_test( + fn_tree="torch.broadcast_tensors", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), + min_num_dims=1, + num_arrays=helpers.ints(min_value=2, max_value=5), + ), +) +def test_torch_broadcast_tensors( + *, + dtype_and_x, + on_device, + fn_tree, + frontend, + test_flags, + backend_fw, +): + input_dtype, x = dtype_and_x + kw = {} + for i, array in enumerate(x): + kw[f"x{i}"] = array + test_flags.num_positional_args = len(kw) + helpers.test_frontend_function( + input_dtypes=input_dtype, + backend_to_test=backend_fw, + on_device=on_device, + frontend=frontend, + test_flags=test_flags, + fn_tree=fn_tree, + **kw, + ) + + @handle_frontend_test( fn_tree="torch.is_complex", dtype_and_x=helpers.dtype_and_values( diff --git a/ivy_tests/test_ivy/test_frontends/test_torchvision/test_ops.py b/ivy_tests/test_ivy/test_frontends/test_torchvision/test_ops.py index 919c05a30274f..70510ca8f8829 100644 --- a/ivy_tests/test_ivy/test_frontends/test_torchvision/test_ops.py +++ b/ivy_tests/test_ivy/test_frontends/test_torchvision/test_ops.py @@ -148,6 +148,36 @@ def test_torchvision_box_area( ) +@handle_frontend_test( + fn_tree="torchvision.ops.box_iou", + boxes=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("float"), + shape=st.tuples(helpers.ints(min_value=1, max_value=5), st.just(4)), + num_arrays=2, + ), +) +def test_torchvision_box_iou( + *, + boxes, + on_device, + fn_tree, + frontend, + test_flags, + backend_fw, +): + dtype, boxes = boxes + helpers.test_frontend_function( + input_dtypes=dtype, + backend_to_test=backend_fw, + frontend=frontend, + test_flags=test_flags, + fn_tree=fn_tree, + on_device=on_device, + boxes1=boxes[0], + boxes2=boxes[1], + ) + + @handle_frontend_test( fn_tree="torchvision.ops.clip_boxes_to_image", boxes=helpers.dtype_and_values( diff --git a/ivy_tests/test_ivy/test_functional/test_core/test_creation.py b/ivy_tests/test_ivy/test_functional/test_core/test_creation.py index 99a105e454651..94def0ea2f966 100644 --- a/ivy_tests/test_ivy/test_functional/test_core/test_creation.py +++ b/ivy_tests/test_ivy/test_functional/test_core/test_creation.py @@ -21,7 +21,7 @@ def _asarray_helper(draw): x_dtype, x = draw( helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("numeric"), + available_dtypes=helpers.get_dtypes("valid"), num_arrays=st.integers(min_value=1, max_value=10), min_num_dims=0, max_num_dims=5, @@ -44,13 +44,13 @@ def _asarray_helper(draw): draw(helpers.get_dtypes("numeric")), dtype=x_dtype[0] ) )[-1] - dtype = draw(st.sampled_from([dtype, None])) + dtype = draw(st.sampled_from([dtype])) x = draw( st.sampled_from( [ x, x_list, - sh, + # sh, # nested_values, ] ) @@ -185,7 +185,7 @@ def test_arange( x_dtype_x_and_dtype=_asarray_helper(), test_gradients=st.just(False), test_instance_method=st.just(False), - test_with_copy=st.just(True), + test_with_copy=st.just(False), ) def test_asarray( *, @@ -848,6 +848,7 @@ def test_zeros(*, shape, dtype, test_flags, backend_fw, fn_name, on_device): min_dim_size=1, max_dim_size=5, ), + test_gradients=st.just(False), ) def test_zeros_like(*, dtype_and_x, test_flags, backend_fw, fn_name, on_device): dtype, x = dtype_and_x diff --git a/ivy_tests/test_ivy/test_functional/test_core/test_device.py b/ivy_tests/test_ivy/test_functional/test_core/test_device.py index ec6c8b6a84351..05300aa6cd446 100644 --- a/ivy_tests/test_ivy/test_functional/test_core/test_device.py +++ b/ivy_tests/test_ivy/test_functional/test_core/test_device.py @@ -258,7 +258,7 @@ def test_dev_util(backend_fw): devices = _get_possible_devices() for device in devices: # The internally called psutil.cpu_percent() has a unique behavior where it - # returns 0 as usageย when run the second time in same line so simple + # returns 0 as usage when run the second time in same line so simple # assert psutil.cpu_percent() ==ย ivy.dev_util(device) isn't possible if "cpu" in device: assert 100 >= ivy_backend.dev_util(device) >= 0 @@ -289,7 +289,7 @@ def test_function_supported_devices( res = ivy_backend.function_supported_devices(func) exp = set(expected) - assert sorted(tuple(exp)) == sorted(res) + assert sorted(exp) == sorted(res) # function_unsupported_devices @@ -308,7 +308,7 @@ def test_function_unsupported_devices( res = ivy_backend.function_unsupported_devices(func) exp = set(expected) - assert sorted(tuple(exp)) == sorted(res) + assert sorted(exp) == sorted(res) @handle_test( @@ -372,7 +372,7 @@ def test_num_cpu_cores(backend_fw): # using multiprocessing module too because ivy uses psutil as basis. p_cpu_cores = psutil.cpu_count() m_cpu_cores = multiprocessing.cpu_count() - assert type(ivy_backend.num_cpu_cores()) == int + assert isinstance(ivy_backend.num_cpu_cores(), int) assert ivy_backend.num_cpu_cores() == p_cpu_cores assert ivy_backend.num_cpu_cores() == m_cpu_cores @@ -460,7 +460,7 @@ def test_print_all_ivy_arrays_on_dev( del item # Apply the regex search - assert all([re.match(regex, line) for line in written]) + assert all(re.match(regex, line) for line in written) # profiler diff --git a/ivy_tests/test_ivy/test_functional/test_core/test_dtype.py b/ivy_tests/test_ivy/test_functional/test_core/test_dtype.py index 576ab01a6e393..2859d678c445d 100644 --- a/ivy_tests/test_ivy/test_functional/test_core/test_dtype.py +++ b/ivy_tests/test_ivy/test_functional/test_core/test_dtype.py @@ -655,7 +655,7 @@ def test_function_supported_dtypes(*, func, backend_fw): exp = set(ivy_backend.all_dtypes).difference( set(func.test_unsupported_dtypes[backend_fw]) ) - assert set(tuple(exp)) == set(res) + assert set(exp) == set(res) # function_unsupported_dtypes @@ -667,7 +667,7 @@ def test_function_unsupported_dtypes(*, func, backend_fw): with BackendHandler.update_backend(backend_fw) as ivy_backend: res = ivy_backend.function_unsupported_dtypes(func) exp = func.test_unsupported_dtypes[backend_fw] - assert set(tuple(exp)) == set(res) + assert set(exp) == set(res) # iinfo diff --git a/ivy_tests/test_ivy/test_functional/test_core/test_elementwise.py b/ivy_tests/test_ivy/test_functional/test_core/test_elementwise.py index bb2fd1c5695bb..9cdc25220a3f8 100644 --- a/ivy_tests/test_ivy/test_functional/test_core/test_elementwise.py +++ b/ivy_tests/test_ivy/test_functional/test_core/test_elementwise.py @@ -2,15 +2,17 @@ # global import math + import numpy as np -from hypothesis import assume, strategies as st +from hypothesis import assume +from hypothesis import strategies as st # local import ivy import ivy_tests.test_ivy.helpers as helpers +import ivy_tests.test_ivy.helpers.globals as test_globals from ivy_tests.test_ivy.helpers import handle_test from ivy_tests.test_ivy.helpers.pipeline_helper import BackendHandler -import ivy_tests.test_ivy.helpers.globals as test_globals _one = np.asarray(1, dtype="uint8") _zero = np.asarray(0, dtype="uint8") @@ -42,7 +44,7 @@ def _either_x_dx(draw): if rand == 0: either_x_dx = draw( helpers.dtype_and_values( - avaliable_dtypes=st.shared( + available_dtypes=st.shared( helpers.get_dtypes("float"), key="trapz_dtype" ), min_value=-100, @@ -67,7 +69,7 @@ def min_max_helper(draw): if use_where: dtype_and_x = draw( helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("numeric"), + available_dtypes=helpers.get_dtypes("numeric", full=False), num_arrays=2, small_abs_safety_factor=6, large_abs_safety_factor=6, @@ -77,10 +79,12 @@ def min_max_helper(draw): else: dtype_and_x = draw( helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("numeric"), + available_dtypes=helpers.get_dtypes("numeric", full=False), num_arrays=2, min_value=-1e5, max_value=1e5, + small_abs_safety_factor=6, + large_abs_safety_factor=6, safety_factor_scale="log", ) ) @@ -180,6 +184,7 @@ def test_abs(*, dtype_and_x, test_flags, backend_fw, fn_name, on_device): available_dtypes=helpers.get_dtypes("float_and_complex"), large_abs_safety_factor=4, small_abs_safety_factor=4, + safety_factor_scale="log", ), ) def test_acos(*, dtype_and_x, test_flags, backend_fw, fn_name, on_device): @@ -293,6 +298,7 @@ def test_angle( fn_tree="functional.ivy.asin", dtype_and_x=helpers.dtype_and_values( available_dtypes=helpers.get_dtypes("float_and_complex"), + safety_factor_scale="log", large_abs_safety_factor=4, small_abs_safety_factor=4, ), @@ -318,6 +324,7 @@ def test_asin(*, dtype_and_x, test_flags, backend_fw, fn_name, on_device): available_dtypes=helpers.get_dtypes("float_and_complex"), large_abs_safety_factor=4, small_abs_safety_factor=4, + safety_factor_scale="log", ), ) def test_asinh(*, dtype_and_x, test_flags, backend_fw, fn_name, on_device): @@ -339,8 +346,8 @@ def test_asinh(*, dtype_and_x, test_flags, backend_fw, fn_name, on_device): fn_tree="functional.ivy.atan", dtype_and_x=helpers.dtype_and_values( available_dtypes=helpers.get_dtypes("float_and_complex"), - large_abs_safety_factor=2, - small_abs_safety_factor=2, + large_abs_safety_factor=4, + small_abs_safety_factor=4, safety_factor_scale="log", ), ) @@ -390,7 +397,9 @@ def test_atan2(*, dtype_and_x, test_flags, backend_fw, fn_name, on_device): @handle_test( fn_tree="functional.ivy.atanh", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("float_and_complex") + min_value=1e-30, + max_value=1e30, + available_dtypes=helpers.get_dtypes("float_and_complex"), ), ) def test_atanh(*, dtype_and_x, test_flags, backend_fw, fn_name, on_device): @@ -633,7 +642,10 @@ def test_cosh(*, dtype_and_x, test_flags, backend_fw, fn_name, on_device): @handle_test( fn_tree="functional.ivy.deg2rad", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("numeric") + available_dtypes=helpers.get_dtypes("valid"), + safety_factor_scale="log", + large_abs_safety_factor=2, + small_abs_safety_factor=2, ), ) def test_deg2rad(*, dtype_and_x, test_flags, backend_fw, fn_name, on_device): @@ -644,6 +656,8 @@ def test_deg2rad(*, dtype_and_x, test_flags, backend_fw, fn_name, on_device): backend_to_test=backend_fw, fn_name=fn_name, on_device=on_device, + atol_=1e-2, + rtol_=1e-2, x=x[0], ) @@ -651,8 +665,9 @@ def test_deg2rad(*, dtype_and_x, test_flags, backend_fw, fn_name, on_device): # divide @handle_test( fn_tree="functional.ivy.divide", + test_gradients=st.just(False), dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("numeric"), + available_dtypes=helpers.get_dtypes("numeric", full=False), num_arrays=2, large_abs_safety_factor=2, small_abs_safety_factor=2, @@ -679,7 +694,11 @@ def test_divide(*, dtype_and_x, test_flags, backend_fw, fn_name, on_device): @handle_test( fn_tree="functional.ivy.equal", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("valid", full=True), num_arrays=2 + available_dtypes=helpers.get_dtypes("valid", full=False), + num_arrays=2, + large_abs_safety_factor=6, + small_abs_safety_factor=6, + safety_factor_scale="log", ), test_gradients=st.just(False), ) @@ -693,6 +712,8 @@ def test_equal(*, dtype_and_x, test_flags, backend_fw, fn_name, on_device): on_device=on_device, x1=x[0], x2=x[1], + atol_=1e-02, + rtol_=1e-02, ) @@ -819,6 +840,7 @@ def test_floor(*, dtype_and_x, test_flags, backend_fw, fn_name, on_device): safety_factor_scale="linear", shared_dtype=True, ), + test_gradients=st.just(False), ) def test_floor_divide(*, dtype_and_x, test_flags, backend_fw, fn_name, on_device): input_dtype, x = dtype_and_x @@ -992,6 +1014,7 @@ def test_greater_equal(*, dtype_and_x, test_flags, backend_fw, fn_name, on_devic allow_nan=False, ), test_gradients=st.just(False), + test_instance_method=st.just(False), ) def test_imag( *, @@ -1164,9 +1187,14 @@ def test_less(*, dtype_and_x, test_flags, backend_fw, fn_name, on_device): @handle_test( fn_tree="functional.ivy.less_equal", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("numeric"), num_arrays=2 + available_dtypes=helpers.get_dtypes("numeric"), + num_arrays=2, + large_abs_safety_factor=6, + small_abs_safety_factor=6, + safety_factor_scale="log", ), test_gradients=st.just(False), + ground_truth_backend="jax", ) def test_less_equal(*, dtype_and_x, test_flags, backend_fw, fn_name, on_device): input_dtype, x = dtype_and_x @@ -1338,7 +1366,7 @@ def test_logaddexp2(*, dtype_and_x, test_flags, backend_fw, fn_name, on_device): @handle_test( fn_tree="functional.ivy.logical_and", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("valid"), num_arrays=2 + available_dtypes=helpers.get_dtypes("valid", full=False), num_arrays=2 ), test_gradients=st.just(False), ) @@ -1422,6 +1450,8 @@ def test_logical_xor(*, dtype_and_x, test_flags, backend_fw, fn_name, on_device) @handle_test( fn_tree="functional.ivy.maximum", dtype_and_x_and_use_where=min_max_helper(), + test_gradients=st.just(False), + ground_truth_backend="jax", ) def test_maximum( *, dtype_and_x_and_use_where, test_flags, backend_fw, fn_name, on_device @@ -1445,6 +1475,8 @@ def test_maximum( @handle_test( fn_tree="functional.ivy.minimum", dtype_and_x_and_use_where=min_max_helper(), + test_gradients=st.just(False), + ground_truth_backend="jax", ) def test_minimum( *, dtype_and_x_and_use_where, test_flags, backend_fw, fn_name, on_device @@ -1468,8 +1500,9 @@ def test_minimum( @handle_test( fn_tree="functional.ivy.multiply", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("numeric"), num_arrays=2 + available_dtypes=helpers.get_dtypes("valid"), num_arrays=2 ), + ground_truth_backend="torch", ) def test_multiply(*, dtype_and_x, test_flags, backend_fw, fn_name, on_device): input_dtype, x = dtype_and_x @@ -1554,7 +1587,11 @@ def test_negative(*, dtype_and_x, test_flags, backend_fw, fn_name, on_device): @handle_test( fn_tree="functional.ivy.not_equal", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("valid", full=True), num_arrays=2 + available_dtypes=helpers.get_dtypes("valid", full=False), + num_arrays=2, + large_abs_safety_factor=8, + small_abs_safety_factor=8, + safety_factor_scale="log", ), test_gradients=st.just(False), ) @@ -1569,6 +1606,8 @@ def test_not_equal(*, dtype_and_x, test_flags, backend_fw, fn_name, on_device): on_device=on_device, x1=x[0], x2=x[1], + atol_=1e-02, + rtol_=1e-02, ) @@ -1607,8 +1646,8 @@ def test_pow(*, dtype_and_x, test_flags, backend_fw, fn_name, on_device): backend_to_test=backend_fw, fn_name=fn_name, on_device=on_device, - rtol_=1e-2, - atol_=1e-2, + rtol_=1e-3, + atol_=1e-3, x1=x[0], x2=x[1], ) @@ -1624,9 +1663,7 @@ def test_pow(*, dtype_and_x, test_flags, backend_fw, fn_name, on_device): @handle_test( fn_tree="functional.ivy.rad2deg", - dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("numeric") - ), + dtype_and_x=helpers.dtype_and_values(available_dtypes=helpers.get_dtypes("valid")), ) def test_rad2deg(*, dtype_and_x, test_flags, backend_fw, fn_name, on_device): input_dtype, x = dtype_and_x @@ -1634,6 +1671,8 @@ def test_rad2deg(*, dtype_and_x, test_flags, backend_fw, fn_name, on_device): input_dtypes=input_dtype, test_flags=test_flags, backend_to_test=backend_fw, + rtol_=1e-2, + atol_=1e-2, fn_name=fn_name, on_device=on_device, x=x[0], @@ -1775,6 +1814,8 @@ def test_sign(*, dtype_and_x, np_variant, test_flags, backend_fw, fn_name, on_de ) def test_sin(*, dtype_and_x, test_flags, backend_fw, fn_name, on_device): input_dtype, x = dtype_and_x + if "paddle" in backend_fw and input_dtype[0] == "float16": + assume(not test_flags.test_gradients) helpers.test_function( input_dtypes=input_dtype, test_flags=test_flags, diff --git a/ivy_tests/test_ivy/test_functional/test_core/test_general.py b/ivy_tests/test_ivy/test_functional/test_core/test_general.py index 7e4b981143978..a7edfe7e96f2b 100644 --- a/ivy_tests/test_ivy/test_functional/test_core/test_general.py +++ b/ivy_tests/test_ivy/test_functional/test_core/test_general.py @@ -15,7 +15,11 @@ import ivy import ivy_tests.test_ivy.helpers as helpers -from ivy_tests.test_ivy.helpers import handle_test, BackendHandler +from ivy_tests.test_ivy.helpers import ( + handle_test, + BackendHandler, + handle_example, +) from ivy_tests.test_ivy.helpers.assertions import assert_all_close from ivy_tests.test_ivy.test_functional.test_core.test_elementwise import pow_helper @@ -629,13 +633,13 @@ def test_default(x, default_val, test_flags, backend_fw): with BackendHandler.update_backend(backend_fw) as ivy_backend: with_callable = False if x is not None: - if hasattr(x, "__call__"): + if callable(x): with_callable = True else: x_dtype, x = x x = x[0].tolist() if isinstance(x, list) else x else: - if hasattr(default_val, "__call__"): + if callable(default_val): with_callable = True else: dv_dtype, default_val = default_val @@ -853,7 +857,7 @@ def test_einops_repeat( ) def test_exists(x): if x is not None: - if not hasattr(x, "__call__"): + if not callable(x): dtype, x = x ret = ivy.exists(x) assert isinstance(ret, bool) @@ -1070,6 +1074,15 @@ def test_get_all_arrays_in_memory(): container_flags=st.just([False]), test_with_copy=st.just(True), ) +@handle_example( + test_example=True, + test_flags={ + "num_positional_args": 2, + }, + dtypes_x_query=(["float32", "bool"], np.ones((1, 3, 3)), (np.array([True]), 2, 2)), + copy=None, + fn_name="get_item", +) def test_get_item( dtypes_x_query, copy, @@ -1208,7 +1221,7 @@ def test_inplace_arrays_supported(backend_fw): elif backend_fw in ["jax", "tensorflow", "paddle"]: assert not ivy_backend.inplace_arrays_supported() else: - raise Exception("Unrecognized framework") + raise RuntimeError("Unrecognized framework") # inplace_decrement @@ -1289,7 +1302,7 @@ def test_inplace_increment(x_val_and_dtypes, test_flags, on_device, backend_fw): shared_dtype=True, ), keep_x_dtype=st.booleans(), - inplace_mode=st.sampled_from(["lenient", "strict"]), + inplace_mode=st.just("lenient"), ) def test_inplace_update( x_val_and_dtypes, keep_x_dtype, inplace_mode, test_flags, on_device, backend_fw @@ -1329,7 +1342,7 @@ def test_inplace_variables_supported(backend_fw): elif backend_fw in ["jax", "paddle"]: assert not ivy_backend.inplace_variables_supported() else: - raise Exception("Unrecognized framework") + raise RuntimeError("Unrecognized framework") # is_array @@ -1643,6 +1656,20 @@ def test_set_inplace_mode(mode): container_flags=st.just([False]), test_with_copy=st.just(True), ) +@handle_example( + test_example=True, + test_flags={ + "num_positional_args": 3, + }, + dtypes_x_query_val=( + ["int32", "int32"], + np.ones((1, 3, 3, 3)), + (slice(None, None, None), slice(None, None, None), slice(None, None, None), 1), + np.zeros((3, 1)), + ), + copy=False, + fn_name="set_item", +) def test_set_item( dtypes_x_query_val, copy, @@ -1722,6 +1749,25 @@ def test_shape(x0_n_x1_n_res, as_array, test_flags, backend_fw, fn_name, on_devi ) +# size +@handle_test( + fn_tree="functional.ivy.size", + dtype_x=helpers.dtype_and_values(available_dtypes=helpers.get_dtypes("valid")), + test_with_out=st.just(False), + test_gradients=st.just(False), +) +def test_size(dtype_x, test_flags, backend_fw, fn_name, on_device): + dtype, x = dtype_x + helpers.test_function( + input_dtypes=dtype, + test_flags=test_flags, + on_device=on_device, + backend_to_test=backend_fw, + fn_name=fn_name, + x=x[0], + ) + + # stable_divide @handle_test( fn_tree="functional.ivy.stable_divide", @@ -1762,7 +1808,7 @@ def test_stable_pow( *, dtypes_and_xs, min_base, test_flags, backend_fw, fn_name, on_device ): dtypes, xs = dtypes_and_xs - assume(all(["bfloat16" not in x for x in dtypes])) + assume(all("bfloat16" not in x for x in dtypes)) helpers.test_function( input_dtypes=dtypes, test_flags=test_flags, diff --git a/ivy_tests/test_ivy/test_functional/test_core/test_gradients.py b/ivy_tests/test_ivy/test_functional/test_core/test_gradients.py index 38a1553183f6e..5556747a2f82b 100644 --- a/ivy_tests/test_ivy/test_functional/test_core/test_gradients.py +++ b/ivy_tests/test_ivy/test_functional/test_core/test_gradients.py @@ -239,9 +239,7 @@ def func(xs): @pytest.mark.parametrize("nth", [1, 2, 3]) def test_grad(x, dtype, func, backend_fw, nth): # ToDo: Remove skipping for paddle and jax for nth > 1 - if backend_fw == "numpy" or ( - (backend_fw == "paddle" or backend_fw == "jax") and nth > 1 - ): + if backend_fw == "numpy" or (backend_fw in ["paddle", "jax"] and nth > 1): return with BackendHandler.update_backend(backend_fw) as ivy_backend: diff --git a/ivy_tests/test_ivy/test_functional/test_core/test_linalg.py b/ivy_tests/test_ivy/test_functional/test_core/test_linalg.py index 7eeec236b6a68..b6ca29eacb3ab 100644 --- a/ivy_tests/test_ivy/test_functional/test_core/test_linalg.py +++ b/ivy_tests/test_ivy/test_functional/test_core/test_linalg.py @@ -19,7 +19,7 @@ @st.composite def _det_helper(draw): - square = draw(helpers.ints(min_value=2, max_value=8).map(lambda x: tuple([x, x]))) + square = draw(helpers.ints(min_value=2, max_value=8).map(lambda x: (x, x))) shape_prefix = draw(helpers.get_shape()) dtype_x = draw( helpers.dtype_and_values( @@ -185,7 +185,7 @@ def _get_first_matrix_and_dtype(draw, *, transpose=False, conjugate=False): matrix = draw( helpers.array_values( dtype=input_dtype, - shape=tuple([random_size, shared_size]), + shape=(random_size, shared_size), min_value=2, max_value=5, ) @@ -224,7 +224,7 @@ def _get_second_matrix_and_dtype(draw, *, transpose=False): matrix = draw( helpers.array_values( dtype=input_dtype, - shape=tuple([random_size, shared_size]), + shape=(random_size, shared_size), min_value=2, max_value=5, ) @@ -279,6 +279,9 @@ def _matrix_rank_helper(draw): ) atol = draw(tol_strategy) rtol = draw(tol_strategy) + if not (atol is None or rtol is None): + assume(type(atol) is type(rtol)) + return dtype, x[0], hermitian, atol, rtol @@ -355,7 +358,7 @@ def dtype_value1_value2_axis( available_dtypes=helpers.get_dtypes("float"), min_value=0, max_value=10, - shape=helpers.ints(min_value=2, max_value=5).map(lambda x: tuple([x, x])), + shape=helpers.ints(min_value=2, max_value=5).map(lambda x: (x, x)), ), upper=st.booleans(), ) @@ -593,7 +596,7 @@ def test_inner(*, dtype_xy, test_flags, backend_fw, fn_name, on_device): small_abs_safety_factor=24, large_abs_safety_factor=24, safety_factor_scale="log", - shape=helpers.ints(min_value=2, max_value=20).map(lambda x: tuple([x, x])), + shape=helpers.ints(min_value=2, max_value=20).map(lambda x: (x, x)), ).filter(lambda x: np.linalg.cond(x[1][0].tolist()) < 1 / sys.float_info.epsilon), adjoint=st.booleans(), ) @@ -681,7 +684,7 @@ def test_matrix_norm( available_dtypes=helpers.get_dtypes("float"), min_value=1e-3, max_value=20, - shape=helpers.ints(min_value=2, max_value=8).map(lambda x: tuple([x, x])), + shape=helpers.ints(min_value=2, max_value=8).map(lambda x: (x, x)), ), n=helpers.ints(min_value=-6, max_value=6), ) diff --git a/ivy_tests/test_ivy/test_functional/test_core/test_manipulation.py b/ivy_tests/test_ivy/test_functional/test_core/test_manipulation.py index e76b88adddc49..6745c947a6d5e 100644 --- a/ivy_tests/test_ivy/test_functional/test_core/test_manipulation.py +++ b/ivy_tests/test_ivy/test_functional/test_core/test_manipulation.py @@ -152,8 +152,9 @@ def _get_splits( allow_array_indices=True, is_mod_split=False, ): - """Generate valid splits, either by generating an integer that evenly divides the - axis or a list of splits that sum to the length of the axis being split.""" + """Generate valid splits, either by generating an integer that evenly + divides the axis or a list of splits that sum to the length of the axis + being split.""" shape = draw( st.shared(helpers.get_shape(min_num_dims=min_num_dims), key="value_shape") ) diff --git a/ivy_tests/test_ivy/test_functional/test_core/test_meta.py b/ivy_tests/test_ivy/test_functional/test_core/test_meta.py index 0c9a28d0d0236..a0b3cc5723e1c 100644 --- a/ivy_tests/test_ivy/test_functional/test_core/test_meta.py +++ b/ivy_tests/test_ivy/test_functional/test_core/test_meta.py @@ -118,10 +118,10 @@ def outer_cost_fn(batch_in, v): ) if average_across_steps: true_weight_grad = ( - sum([sum(og) / len(og) for og in all_outer_grads]) / num_tasks + sum(sum(og) / len(og) for og in all_outer_grads) / num_tasks ) else: - true_weight_grad = sum([og[-1] for og in all_outer_grads]) / num_tasks + true_weight_grad = sum(og[-1] for og in all_outer_grads) / num_tasks # true latent gradient true_latent_grad = np.array( @@ -482,10 +482,10 @@ def outer_cost_fn(batch_in, v): ) if average_across_steps: true_weight_grad = ( - sum([sum(og) / len(og) for og in all_outer_grads]) / num_tasks + sum(sum(og) / len(og) for og in all_outer_grads) / num_tasks ) else: - true_weight_grad = sum([og[-1] for og in all_outer_grads]) / num_tasks + true_weight_grad = sum(og[-1] for og in all_outer_grads) / num_tasks # true cost true_cost_dict = { @@ -650,10 +650,10 @@ def outer_cost_fn(batch_in, v): ) if average_across_steps: true_weight_grad = ( - sum([sum(og) / len(og) for og in all_outer_grads]) / num_tasks + sum(sum(og) / len(og) for og in all_outer_grads) / num_tasks ) else: - true_weight_grad = sum([og[-1] for og in all_outer_grads]) / num_tasks + true_weight_grad = sum(og[-1] for og in all_outer_grads) / num_tasks # true latent gradient true_latent_grad = np.array( @@ -816,21 +816,19 @@ def update_grad_fn(w_init, sub_batch_in, num_steps, average=False): collection_of_terms.append([t for t in terms]) if average: return [ - sum( - [ + ( + sum( t * inner_learning_rate ** (num_steps - i) for i, t in enumerate(tms) - ] + ) + * w_init.latent ) - * w_init.latent for tms in collection_of_terms ] return ( sum( - [ - t * inner_learning_rate ** (num_steps - i) - for i, t in enumerate(terms) - ] + t * inner_learning_rate ** (num_steps - i) + for i, t in enumerate(terms) ) * w_init.latent ) @@ -857,15 +855,16 @@ def update_grad_fn(w_init, sub_batch_in, num_steps, average=False): # true outer grad if average_across_steps: true_outer_grad = sum( - [ - ig.latent * ug - for ig, ug in zip( - grads, - update_grad_fn( - variables_np, sub_batch, inner_grad_steps, average=True - ), - ) - ] + ig.latent * ug + for ig, ug in zip( + grads, + update_grad_fn( + variables_np, + sub_batch, + inner_grad_steps, + average=True, + ), + ) ) / len(grads) else: true_outer_grad = ivy_backend.multiply( @@ -1058,10 +1057,10 @@ def outer_cost_fn(batch_in, v): ) if average_across_steps: true_outer_grad = ( - sum([sum(og) / len(og) for og in all_outer_grads]) / num_tasks + sum(sum(og) / len(og) for og in all_outer_grads) / num_tasks ) else: - true_outer_grad = sum([og[-1] for og in all_outer_grads]) / num_tasks + true_outer_grad = sum(og[-1] for og in all_outer_grads) / num_tasks # true cost true_cost_dict = { diff --git a/ivy_tests/test_ivy/test_functional/test_core/test_nest.py b/ivy_tests/test_ivy/test_functional/test_core/test_nest.py index be259bb20e3ff..ab0f09ccc811a 100644 --- a/ivy_tests/test_ivy/test_functional/test_core/test_nest.py +++ b/ivy_tests/test_ivy/test_functional/test_core/test_nest.py @@ -259,7 +259,7 @@ def test_nested_any(x, fn): map_nested_dicts(x_copy, fn) def is_true_any(ob): - for k, v in ob.items(): + for v in ob.values(): if isinstance(v, dict): is_true_any(v) if isinstance(v, list): diff --git a/ivy_tests/test_ivy/test_functional/test_core/test_random.py b/ivy_tests/test_ivy/test_functional/test_core/test_random.py index 13a6e7652448f..9d775b56477fe 100644 --- a/ivy_tests/test_ivy/test_functional/test_core/test_random.py +++ b/ivy_tests/test_ivy/test_functional/test_core/test_random.py @@ -146,8 +146,10 @@ def call(): ret=ret_gt, backend=test_flags.ground_truth_backend ) for u, v in zip(ret, ret_gt): - assert ivy.all(u >= low) and ivy.all(u < high) - assert ivy.all(v >= low) and ivy.all(v < high) + assert ivy.all(u >= low) + assert ivy.all(u < high) + assert ivy.all(v >= low) + assert ivy.all(v < high) # random_normal diff --git a/ivy_tests/test_ivy/test_functional/test_core/test_searching.py b/ivy_tests/test_ivy/test_functional/test_core/test_searching.py index 425c78805d9bb..1edb5f5a6f60c 100644 --- a/ivy_tests/test_ivy/test_functional/test_core/test_searching.py +++ b/ivy_tests/test_ivy/test_functional/test_core/test_searching.py @@ -64,8 +64,9 @@ def _dtype_x_limited_axis(draw, *, allow_none=False): fn_tree="functional.ivy.argmax", dtype_x_axis=_dtype_x_limited_axis(allow_none=True), keepdims=st.booleans(), - dtype=helpers.get_dtypes("valid", full=False, none=True), + dtype=helpers.get_dtypes("numeric", full=False, none=True), select_last_index=st.booleans(), + test_gradients=st.just(False), ) def test_argmax( *, diff --git a/ivy_tests/test_ivy/test_functional/test_core/test_set.py b/ivy_tests/test_ivy/test_functional/test_core/test_set.py index 69f9be2fbf241..a401e5d063805 100644 --- a/ivy_tests/test_ivy/test_functional/test_core/test_set.py +++ b/ivy_tests/test_ivy/test_functional/test_core/test_set.py @@ -70,17 +70,19 @@ def test_unique_counts(*, dtype_and_x, test_flags, backend_fw, fn_name, on_devic # unique_inverse @handle_test( fn_tree="functional.ivy.unique_inverse", - dtype_and_x=helpers.dtype_and_values( + dtype_x_axis=helpers.dtype_values_axis( available_dtypes=helpers.get_dtypes("valid"), min_num_dims=2, min_dim_size=2, + force_int_axis=True, + valid_axis=True, ), test_with_out=st.just(False), test_gradients=st.just(False), ) def test_unique_inverse(*, dtype_x_axis, test_flags, backend_fw, fn_name, on_device): dtype, x, axis = dtype_x_axis - assume(not np.any(np.isclose(x, 0.0), axis=axis)) + assume(not np.any(np.any(np.isclose(x[0], 0.0), axis=axis))) helpers.test_function( input_dtypes=dtype, diff --git a/ivy_tests/test_ivy/test_functional/test_core/test_statistical.py b/ivy_tests/test_ivy/test_functional/test_core/test_statistical.py index f5c82c9b4c1db..7c6cd30e28a00 100644 --- a/ivy_tests/test_ivy/test_functional/test_core/test_statistical.py +++ b/ivy_tests/test_ivy/test_functional/test_core/test_statistical.py @@ -82,7 +82,20 @@ def _statistical_dtype_values(draw, *, function, min_value=None, max_value=None) | helpers.floats(min_value=0, max_value=max_correction - 1) ) return dtype, values, axis, correction - return dtype, values, axis + + if isinstance(axis, tuple): + axis = axis[0] + + where_shape = draw( + helpers.mutually_broadcastable_shapes( + num_shapes=1, base_shape=shape, min_dims=0, max_dims=axis + ) + ) + dtype3, where = draw( + helpers.dtype_and_values(available_dtypes=["bool"], shape=where_shape[0]) + ) + + return dtype, values, axis, dtype3, where # --- Main --- # @@ -95,6 +108,7 @@ def _statistical_dtype_values(draw, *, function, min_value=None, max_value=None) dtype_x_axis_castable=_get_castable_dtype(), exclusive=st.booleans(), reverse=st.booleans(), + test_gradients=st.just(False), ) def test_cumprod( *, @@ -140,6 +154,7 @@ def test_cumprod( dtype_x_axis_castable=_get_castable_dtype(), exclusive=st.booleans(), reverse=st.booleans(), + test_gradients=st.just(False), ) def test_cumsum( *, @@ -152,6 +167,7 @@ def test_cumsum( on_device, ): input_dtype, x, axis, castable_dtype = dtype_x_axis_castable + assume("bool" not in input_dtype) # ToDo: set as_variable_flags as the parameter generated by test_cumsum once # this issue is marked as completed https://github.com/pytorch/pytorch/issues/75733 if "torch" in backend_fw: @@ -218,7 +234,7 @@ def test_einsum( keep_dims=st.booleans(), ) def test_max(*, dtype_and_x, keep_dims, test_flags, backend_fw, fn_name, on_device): - input_dtype, x, axis = dtype_and_x + input_dtype, x, axis, *_ = dtype_and_x helpers.test_function( input_dtypes=input_dtype, test_flags=test_flags, @@ -238,7 +254,7 @@ def test_max(*, dtype_and_x, keep_dims, test_flags, backend_fw, fn_name, on_devi keep_dims=st.booleans(), ) def test_mean(*, dtype_and_x, keep_dims, test_flags, backend_fw, fn_name, on_device): - input_dtype, x, axis = dtype_and_x + input_dtype, x, axis, dtype3, where = dtype_and_x helpers.test_function( input_dtypes=input_dtype, test_flags=test_flags, @@ -259,11 +275,15 @@ def test_mean(*, dtype_and_x, keep_dims, test_flags, backend_fw, fn_name, on_dev fn_tree="functional.ivy.min", dtype_and_x=_statistical_dtype_values(function="min"), keep_dims=st.booleans(), + test_gradients=st.just(False), + initial=st.integers(min_value=-5, max_value=5), ) -def test_min(*, dtype_and_x, keep_dims, test_flags, backend_fw, fn_name, on_device): - input_dtype, x, axis = dtype_and_x +def test_min( + *, dtype_and_x, keep_dims, initial, test_flags, backend_fw, fn_name, on_device +): + input_dtype, x, axis, dtype3, where = dtype_and_x helpers.test_function( - input_dtypes=input_dtype, + input_dtypes=[input_dtype[0], dtype3[0]], test_flags=test_flags, backend_to_test=backend_fw, fn_name=fn_name, @@ -271,6 +291,8 @@ def test_min(*, dtype_and_x, keep_dims, test_flags, backend_fw, fn_name, on_devi x=x[0], axis=axis, keepdims=keep_dims, + initial=initial, + where=where[0], ) @@ -332,6 +354,7 @@ def test_std(*, dtype_and_x, keep_dims, test_flags, backend_fw, fn_name, on_devi fn_tree="functional.ivy.sum", dtype_x_axis_castable=_get_castable_dtype(), keep_dims=st.booleans(), + test_gradients=st.just(False), ) def test_sum( *, dtype_x_axis_castable, keep_dims, test_flags, backend_fw, fn_name, on_device @@ -342,6 +365,9 @@ def test_sum( if "torch" in backend_fw: assume(not test_flags.as_variable[0]) assume(not test_flags.test_gradients) + if "jax" in backend_fw and castable_dtype in ["complex64", "complex128"]: + assume(not test_flags.test_gradients) + helpers.test_function( input_dtypes=[input_dtype], test_flags=test_flags, diff --git a/ivy_tests/test_ivy/test_functional/test_experimental/test_core/test_creation.py b/ivy_tests/test_ivy/test_functional/test_experimental/test_core/test_creation.py index 51b14a8d29b15..786b4475afb12 100644 --- a/ivy_tests/test_ivy/test_functional/test_experimental/test_core/test_creation.py +++ b/ivy_tests/test_ivy/test_functional/test_experimental/test_core/test_creation.py @@ -388,7 +388,8 @@ def test_ndenumerate(dtype_and_x): for (index1, x1), (index2, x2) in zip( np.ndenumerate(values), ivy.ndenumerate(values) ): - assert index1 == index2 and x1 == x2.to_numpy() + assert index1 == index2 + assert x1 == x2.to_numpy() # ndindex @@ -799,6 +800,33 @@ def test_trilu(*, dtype_and_x, k, upper, test_flags, backend_fw, fn_name, on_dev ) +@handle_test( + fn_tree="functional.ivy.experimental.unsorted_segment_mean", + d_x_n_s=valid_unsorted_segment_min_inputs(), + test_with_out=st.just(False), + test_gradients=st.just(False), +) +def test_unsorted_segment_mean( + *, + d_x_n_s, + test_flags, + backend_fw, + fn_name, + on_device, +): + dtypes, data, num_segments, segment_ids = d_x_n_s + helpers.test_function( + input_dtypes=dtypes, + test_flags=test_flags, + on_device=on_device, + backend_to_test=backend_fw, + fn_name=fn_name, + data=data, + segment_ids=segment_ids, + num_segments=num_segments, + ) + + # unsorted_segment_min @handle_test( fn_tree="functional.ivy.experimental.unsorted_segment_min", diff --git a/ivy_tests/test_ivy/test_functional/test_experimental/test_core/test_elementwise.py b/ivy_tests/test_ivy/test_functional/test_experimental/test_core/test_elementwise.py index 24517040cf225..3e4b7cf584661 100644 --- a/ivy_tests/test_ivy/test_functional/test_experimental/test_core/test_elementwise.py +++ b/ivy_tests/test_ivy/test_functional/test_experimental/test_core/test_elementwise.py @@ -1,5 +1,5 @@ # global -from hypothesis import strategies as st +from hypothesis import assume, strategies as st # local import ivy @@ -217,6 +217,7 @@ def test_allclose( dtype_and_x, rtol, atol, equal_nan, test_flags, backend_fw, fn_name, on_device ): input_dtype, x = dtype_and_x + assume("bfloat16" not in input_dtype) helpers.test_function( input_dtypes=input_dtype, test_flags=test_flags, @@ -510,6 +511,42 @@ def test_erfc( ) +# erfinv +@handle_test( + fn_tree="functional.ivy.experimental.erfinv", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("float"), + min_value=-1, + max_value=1, + abs_smallest_val=1e-05, + ), +) +def test_erfinv( + *, + dtype_and_x, + backend_fw, + test_flags, + fn_name, + on_device, +): + input_dtype, x = dtype_and_x + if on_device == "cpu": + assume("float16" not in input_dtype and "bfloat16" not in input_dtype) + test_values = True + if backend_fw == "numpy": + # the numpy backend requires an approximation which doesn't pass the value tests + test_values = False + helpers.test_function( + input_dtypes=input_dtype, + backend_to_test=backend_fw, + test_flags=test_flags, + fn_name=fn_name, + on_device=on_device, + test_values=test_values, + x=x[0], + ) + + # fix @handle_test( fn_tree="functional.ivy.experimental.fix", @@ -796,7 +833,7 @@ def test_lgamma( @handle_test( fn_tree="functional.ivy.experimental.modf", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("numeric"), + available_dtypes=helpers.get_dtypes("valid"), num_arrays=1, min_value=0, exclude_min=True, diff --git a/ivy_tests/test_ivy/test_functional/test_experimental/test_core/test_linalg.py b/ivy_tests/test_ivy/test_functional/test_experimental/test_core/test_linalg.py index b1c09ac50fd19..1e15bdc2ff1fb 100644 --- a/ivy_tests/test_ivy/test_functional/test_experimental/test_core/test_linalg.py +++ b/ivy_tests/test_ivy/test_functional/test_experimental/test_core/test_linalg.py @@ -5,6 +5,7 @@ import numpy as np import pytest import itertools +import sys # local import ivy_tests.test_ivy.helpers as helpers @@ -162,15 +163,15 @@ def _generate_diag_args(draw): # dot @st.composite -def _generate_dot_dtype_and_arrays(draw): +def _generate_dot_dtype_and_arrays(draw, min_num_dims=0): shape_a = draw( helpers.get_shape( - min_dim_size=2, max_dim_size=5, min_num_dims=0, max_num_dims=5 + min_dim_size=2, max_dim_size=5, min_num_dims=min_num_dims, max_num_dims=5 ) ) shape_b = draw( helpers.get_shape( - min_dim_size=2, max_dim_size=5, min_num_dims=0, max_num_dims=5 + min_dim_size=2, max_dim_size=5, min_num_dims=min_num_dims, max_num_dims=5 ) ) @@ -859,7 +860,6 @@ def _tucker_data(draw): fn_tree="functional.ivy.experimental.adjoint", dtype_x=helpers.dtype_and_values( available_dtypes=( - ivy.float16, ivy.float32, ivy.float64, ivy.complex64, @@ -875,7 +875,7 @@ def _tucker_data(draw): shared_dtype=True, ), ) -def test_adjoint(dtype_x, test_flags, backend_fw, fn_name): +def test_adjoint(dtype_x, test_flags, backend_fw, fn_name, on_device): dtype, x = dtype_x helpers.test_function( input_dtypes=dtype, @@ -883,6 +883,7 @@ def test_adjoint(dtype_x, test_flags, backend_fw, fn_name): backend_to_test=backend_fw, fn_name=fn_name, x=x[0], + on_device=on_device, ) @@ -1292,7 +1293,7 @@ def test_khatri_rao(*, data, test_flags, backend_fw, fn_name, on_device): # The following two tests have been adapted from TensorLy # https://github.com/tensorly/tensorly/blob/main/tensorly/tenalg/tests/test_khatri_rao.py -@pytest.mark.parametrize("columns, rows", [(4, [3, 4, 2])]) +@pytest.mark.parametrize(("columns", "rows"), [(4, [3, 4, 2])]) def test_khatri_rao_tensorly_1(columns, rows): columns = columns rows = rows @@ -1306,7 +1307,7 @@ def test_khatri_rao_tensorly_1(columns, rows): @pytest.mark.parametrize( - "t1, t2, true_res", + ("t1", "t2", "true_res"), [ ( [[1, 2, 3], [4, 5, 6], [7, 8, 9]], @@ -1380,6 +1381,82 @@ def test_kronecker(*, data, test_flags, backend_fw, fn_name, on_device): ) +# lu_factor +@handle_test( + fn_tree="functional.ivy.experimental.lu_factor", + dtype_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("numeric"), + min_num_dims=2, + max_num_dims=2, + min_dim_size=2, + max_dim_size=5, + ).filter( + lambda x: np.linalg.cond(x[1][0]) < 1 / sys.float_info.epsilon + and np.linalg.det(np.asarray(x[1][0])) != 0 + ), + test_gradients=st.just(False), +) +def test_lu_factor(dtype_x, test_flags, backend_fw, fn_name, on_device): + dtype, x = dtype_x + ret = helpers.test_function( + input_dtypes=dtype, + test_flags=test_flags, + on_device=on_device, + backend_to_test=backend_fw, + fn_name=fn_name, + x=x[0], + test_values=False, + ) + # check decomp is correct manually by getting the values from test_function above + # this is because the decomposition is not unique and test_values will not work + ret_f, ret_gt = ret + + # check that the decomposition is correct for current fw at least + LU, p = ret_f.LU, ret_f.p + L = np.tril(LU, -1) + np.eye(LU.shape[0]) + U = np.triu(LU) + P = np.eye(LU.shape[0])[p] + assert np.allclose(L @ U, P @ x[0]) + + +@handle_test( + fn_tree="functional.ivy.experimental.lu_solve", + dtype_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("float"), + shape=helpers.get_shape( + min_num_dims=2, max_num_dims=2, min_dim_size=2, max_dim_size=2 + ), + num_arrays=2, + shared_dtype=True, + ).filter( + lambda x: "float16" not in x[0] + and "bfloat16" not in x[0] + and np.linalg.cond(x[1][0]) < 1 / sys.float_info.epsilon + and np.linalg.det(np.asarray(x[1][0])) != 0 + ), + test_gradients=st.just(False), +) +def test_lu_solve(dtype_x, test_flags, backend_fw, fn_name, on_device): + dtype, arr = dtype_x + A, B = arr[0], arr[1] + ivy.set_backend(backend_fw) + lu_ = ivy.lu_factor(A) + lu, p = lu_.LU, lu_.p + X, X_gt = helpers.test_function( + input_dtypes=dtype, + test_flags=test_flags, + on_device=on_device, + backend_to_test=backend_fw, + fn_name=fn_name, + lu=lu, + p=p, + b=B, + test_values=False, + ) + + assert np.allclose(A @ X, B) + + @handle_test( fn_tree="functional.ivy.experimental.make_svd_non_negative", data=_make_svd_nn_data(), @@ -1477,7 +1554,7 @@ def test_mode_dot(*, data, test_flags, backend_fw, fn_name, on_device): @pytest.mark.parametrize( - "X, U, true_res", + ("X", "U", "true_res"), [ ( [ @@ -1545,7 +1622,7 @@ def test_multi_mode_dot(*, data, test_flags, backend_fw, fn_name, on_device): # The following 2 tests have been adapted from TensorLy # https://github.com/tensorly/tensorly/blob/main/tensorly/tenalg/tests/test_n_mode_product.py#L81 @pytest.mark.parametrize( - "X, U, true_res", + ("X", "U", "true_res"), [ ([[1, 2], [0, -1]], [[2, 1], [-1, 1]], [1]), ], @@ -1556,7 +1633,12 @@ def test_multi_mode_dot_tensorly_1(X, U, true_res): assert np.allclose(true_res, res) -@pytest.mark.parametrize("shape", ((3, 5, 4, 2),)) +@pytest.mark.parametrize( + "shape", + [ + (3, 5, 4, 2), + ], +) def test_multi_mode_dot_tensorly_2(shape): print(shape) X = ivy.ones(shape) @@ -1624,7 +1706,7 @@ def test_partial_tucker(*, data, test_flags, backend_fw, fn_name, on_device): # test adapted from TensorLy # https://github.com/tensorly/tensorly/blob/main/tensorly/decomposition/tests/test_tucker.py#L24 @pytest.mark.parametrize( - "tol_norm_2, tol_max_abs, modes, shape", + ("tol_norm_2", "tol_max_abs", "modes", "shape"), [ ( 10e-3, @@ -1775,7 +1857,9 @@ def test_tensor_train(*, data, svd, test_flags, backend_fw, fn_name, on_device): # The following 3 tests have been adapted from TensorLy # https://github.com/tensorly/tensorly/blob/main/tensorly/decomposition/tests/test_tt_decomposition.py -@pytest.mark.parametrize("shape, rank", [((3, 4, 5, 6, 2, 10), (1, 3, 3, 4, 2, 2, 1))]) +@pytest.mark.parametrize( + ("shape", "rank"), [((3, 4, 5, 6, 2, 10), (1, 3, 3, 4, 2, 2, 1))] +) def test_tensor_train_tensorly_1(shape, rank): tensor = ivy.random_uniform(shape=shape) tensor_shape = tensor.shape @@ -1800,7 +1884,9 @@ def test_tensor_train_tensorly_1(shape, rank): r_prev_iteration = r_k -@pytest.mark.parametrize("shape, rank", [((3, 4, 5, 6, 2, 10), (1, 5, 4, 3, 8, 10, 1))]) +@pytest.mark.parametrize( + ("shape", "rank"), [((3, 4, 5, 6, 2, 10), (1, 5, 4, 3, 8, 10, 1))] +) def test_tensor_train_tensorly_2(shape, rank): tensor = ivy.random_uniform(shape=shape) factors = ivy.tensor_train(tensor, rank) @@ -1821,7 +1907,7 @@ def test_tensor_train_tensorly_2(shape, rank): assert r_k <= rank[k + 1], first_error_message -@pytest.mark.parametrize("shape, rank, tol", [((3, 3, 3), (1, 3, 3, 1), (10e-5))]) +@pytest.mark.parametrize(("shape", "rank", "tol"), [((3, 3, 3), (1, 3, 3, 1), (10e-5))]) def test_tensor_train_tensorly_3(shape, rank, tol): tensor = ivy.random_uniform(shape=shape) factors = ivy.tensor_train(tensor, rank) @@ -1989,7 +2075,8 @@ def test_tucker(*, data, test_flags, backend_fw, fn_name, on_device): # test adapted from tensorly # https://github.com/tensorly/tensorly/blob/main/tensorly/decomposition/tests/test_tucker.py#L71 @pytest.mark.parametrize( - "tol_norm_2, tol_max_abs, shape, ranks", [(10e-3, 10e-1, (3, 4, 3), [2, 3, 1])] + ("tol_norm_2", "tol_max_abs", "shape", "ranks"), + [(10e-3, 10e-1, (3, 4, 3), [2, 3, 1])], ) def test_tucker_tensorly(tol_norm_2, tol_max_abs, shape, ranks): tensor = ivy.random_uniform(shape=shape) diff --git a/ivy_tests/test_ivy/test_functional/test_experimental/test_core/test_manipulation.py b/ivy_tests/test_ivy/test_functional/test_experimental/test_core/test_manipulation.py index 3e3c6f3fdfba0..2c2c5cc7ca50c 100644 --- a/ivy_tests/test_ivy/test_functional/test_experimental/test_core/test_manipulation.py +++ b/ivy_tests/test_ivy/test_functional/test_experimental/test_core/test_manipulation.py @@ -6,6 +6,7 @@ # local import ivy import ivy_tests.test_ivy.helpers as helpers +from ivy_tests.test_ivy.helpers.hypothesis_helpers.general_helpers import sizes_ from ivy_tests.test_ivy.helpers import handle_test, create_concatenable_arrays_dtypes from ivy.functional.ivy.experimental.manipulation import _check_bounds from ivy_tests.test_ivy.test_functional.test_core.test_manipulation import _get_splits @@ -47,7 +48,7 @@ def _associative_scan_helper(draw): shared_size = draw( st.shared(helpers.ints(min_value=1, max_value=5), key="shared_size") ) - shape = tuple([random_size, shared_size, shared_size]) + shape = (random_size, shared_size, shared_size) matrix = draw( helpers.array_values( dtype=input_dtype, @@ -194,7 +195,7 @@ def _matricize_data(draw): ) ) ndims = len(shape) - dims = set([*range(ndims)]) + dims = {*range(ndims)} row_modes = set( draw(st.lists(helpers.ints(min_value=0, max_value=ndims - 1), min_size=1)) ) @@ -1470,6 +1471,45 @@ def test_trim_zeros( ) +# unflatten +@handle_test( + fn_tree="functional.ivy.experimental.unflatten", + shape=st.shared(helpers.get_shape(min_num_dims=1), key="shape"), + dtype_and_values=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), + min_num_dims=1, + shape_key="shape", + ), + axis=helpers.get_axis( + shape=st.shared(helpers.get_shape(min_num_dims=1), key="shape"), + force_int=True, + ), +) +def test_unflatten( + *, + dtype_and_values, + on_device, + fn_name, + test_flags, + backend_fw, + shape, + axis, +): + shape_ = sizes_(shape, axis) + dtype, x = dtype_and_values + helpers.test_function( + input_dtypes=dtype, + backend_to_test=backend_fw, + test_flags=test_flags, + fn_name=fn_name, + on_device=on_device, + test_values=False, + x=x[0], + shape=shape_, + dim=axis, + ) + + @handle_test( fn_tree="functional.ivy.experimental.unfold", dtype_values_axis=helpers.dtype_values_axis( diff --git a/ivy_tests/test_ivy/test_functional/test_experimental/test_core/test_random.py b/ivy_tests/test_ivy/test_functional/test_experimental/test_core/test_random.py index 5f53a416ebd1a..0da1bbb87a106 100644 --- a/ivy_tests/test_ivy/test_functional/test_experimental/test_core/test_random.py +++ b/ivy_tests/test_ivy/test_functional/test_experimental/test_core/test_random.py @@ -16,6 +16,7 @@ ), seed=helpers.ints(min_value=0, max_value=100), test_gradients=st.just(False), + ground_truth_backend="torch", ) def test_bernoulli( *, dtype_and_probs, seed, test_flags, backend_fw, fn_name, on_device @@ -25,18 +26,20 @@ def test_bernoulli( assume( not ("torch" in str(backend_fw) and "float16" in dtype and on_device == "cpu") ) - helpers.test_function( + ret_np_flat_from_target, ret_np_from_gt_flat = helpers.test_function( input_dtypes=dtype, test_flags=test_flags, on_device=on_device, backend_to_test=backend_fw, fn_name=fn_name, test_values=False, + return_flat_np_arrays=True, probs=probs[0], logits=None, shape=None, seed=seed, ) + helpers.assert_same_type_and_shape([ret_np_flat_from_target, ret_np_from_gt_flat]) # beta @@ -84,8 +87,10 @@ def test_beta( ) with BackendHandler.update_backend(backend_fw) as ivy_backend: for u, v in zip(ret, ret_gt): - assert ivy_backend.all(u >= 0) and ivy_backend.all(u <= 1) - assert ivy_backend.all(v >= 0) and ivy_backend.all(v <= 1) + assert ivy_backend.all(u >= 0) + assert ivy_backend.all(u <= 1) + assert ivy_backend.all(v >= 0) + assert ivy_backend.all(v <= 1) # dirichlet @@ -139,8 +144,10 @@ def call(): assert ivy_backend.all( ivy_backend.sum(u, axis=-1) == ivy_backend.sum(v, axis=-1) ) - assert ivy_backend.all(u >= 0) and ivy_backend.all(u <= 1) - assert ivy_backend.all(v >= 0) and ivy_backend.all(v <= 1) + assert ivy_backend.all(u >= 0) + assert ivy_backend.all(u <= 1) + assert ivy_backend.all(v >= 0) + assert ivy_backend.all(v <= 1) # gamma diff --git a/ivy_tests/test_ivy/test_functional/test_experimental/test_core/test_statistical.py b/ivy_tests/test_ivy/test_functional/test_experimental/test_core/test_statistical.py index 6ceea7b2c08a1..88a710e3bd663 100644 --- a/ivy_tests/test_ivy/test_functional/test_experimental/test_core/test_statistical.py +++ b/ivy_tests/test_ivy/test_functional/test_experimental/test_core/test_statistical.py @@ -463,6 +463,7 @@ def test_cummax( dtype_x_axis_castable=_get_castable_dtype(), exclusive=st.booleans(), reverse=st.booleans(), + test_gradients=st.just(False), ) def test_cummin( *, @@ -599,7 +600,7 @@ def test_median(*, dtype_x_axis, keep_dims, test_flags, backend_fw, fn_name, on_ def test_nanmean( *, dtype_x_axis, keep_dims, dtype, test_flags, backend_fw, fn_name, on_device ): - input_dtype, x, axis = dtype_x_axis + input_dtype, x, axis, *_ = dtype_x_axis helpers.test_function( input_dtypes=input_dtype, test_flags=test_flags, diff --git a/ivy_tests/test_ivy/test_functional/test_experimental/test_nn/test_activations.py b/ivy_tests/test_ivy/test_functional/test_experimental/test_nn/test_activations.py index ab60d709d92ed..d61e795307cb9 100644 --- a/ivy_tests/test_ivy/test_functional/test_experimental/test_nn/test_activations.py +++ b/ivy_tests/test_ivy/test_functional/test_experimental/test_nn/test_activations.py @@ -40,7 +40,7 @@ def test_celu( @handle_test( fn_tree="functional.ivy.experimental.elu", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("valid"), + available_dtypes=helpers.get_dtypes("float_and_complex"), large_abs_safety_factor=8, small_abs_safety_factor=8, safety_factor_scale="log", @@ -98,6 +98,28 @@ def test_hardshrink( ) +# hardsilu +@handle_test( + fn_tree="functional.ivy.experimental.hardsilu", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("float"), + large_abs_safety_factor=8, + small_abs_safety_factor=8, + safety_factor_scale="log", + ), +) +def test_hardsilu(*, dtype_and_x, test_flags, backend_fw, fn_name, on_device): + dtype, x = dtype_and_x + helpers.test_function( + input_dtypes=dtype, + backend_to_test=backend_fw, + test_flags=test_flags, + fn_name=fn_name, + on_device=on_device, + x=x[0], + ) + + # hardtanh @handle_test( fn_tree="functional.ivy.experimental.hardtanh", @@ -214,10 +236,11 @@ def test_prelu(*, dtype_and_x, slope, test_flags, backend_fw, fn_name, on_device @handle_test( fn_tree="functional.ivy.experimental.relu6", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("valid"), + available_dtypes=helpers.get_dtypes("float_and_complex"), large_abs_safety_factor=2, small_abs_safety_factor=2, safety_factor_scale="log", + min_value=1e-15, ), complex_mode=st.sampled_from(["jax", "split", "magnitude"]), ) @@ -366,6 +389,38 @@ def test_tanhshrink(*, dtype_and_x, test_flags, backend_fw, fn_name, on_device): ) +# threshold +@handle_test( + fn_tree="functional.ivy.experimental.threshold", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), + large_abs_safety_factor=8, + small_abs_safety_factor=8, + safety_factor_scale="log", + ), + threshold=st.one_of( + st.floats(min_value=-1e30, max_value=1e30), + ), + value=st.one_of( + st.floats(min_value=-1e30, max_value=1e30), + ), +) +def test_threshold( + *, dtype_and_x, threshold, value, test_flags, backend_fw, fn_name, on_device +): + dtype, x = dtype_and_x + helpers.test_function( + input_dtypes=dtype, + backend_to_test=backend_fw, + test_flags=test_flags, + fn_name=fn_name, + on_device=on_device, + x=x[0], + threshold=threshold, + value=value, + ) + + # thresholded_relu @handle_test( fn_tree="functional.ivy.experimental.thresholded_relu", diff --git a/ivy_tests/test_ivy/test_functional/test_experimental/test_nn/test_layers.py b/ivy_tests/test_ivy/test_functional/test_experimental/test_nn/test_layers.py index 81eec1e5f3bf0..cbe9a2ace12ce 100644 --- a/ivy_tests/test_ivy/test_functional/test_experimental/test_nn/test_layers.py +++ b/ivy_tests/test_ivy/test_functional/test_experimental/test_nn/test_layers.py @@ -6,7 +6,7 @@ # local import ivy import ivy_tests.test_ivy.helpers as helpers -from ivy_tests.test_ivy.helpers import handle_test +from ivy_tests.test_ivy.helpers import handle_test, BackendHandler # --- Helpers --- # @@ -31,31 +31,31 @@ def _interp_args(draw, mode=None, mode_list=None): "nearest", "nearest-exact", "area", + "bicubic", ] - tf_modes = [ "linear", "bilinear", "trilinear", "nearest-exact", "tf_area", - "bicubic_tensorflow", + "tf_bicubic", "lanczos3", "lanczos5", "mitchellcubic", "gaussian", ] - jax_modes = [ "linear", "bilinear", "trilinear", "nearest-exact", - "bicubic_tensorflow", + "tf_bicubic", "lanczos3", "lanczos5", ] - + if mode_list == "torch": + mode_list = torch_modes if not mode and not mode_list: if curr_backend == "torch" and not mixed_fn_compos: mode = draw(st.sampled_from(torch_modes)) @@ -74,7 +74,7 @@ def _interp_args(draw, mode=None, mode_list=None): "nearest-exact", "area", "tf_area", - "bicubic_tensorflow", + "tf_bicubic", "lanczos3", "lanczos5", "mitchellcubic", @@ -84,14 +84,11 @@ def _interp_args(draw, mode=None, mode_list=None): ) elif mode_list: mode = draw(st.sampled_from(mode_list)) - align_corners = draw(st.one_of(st.booleans(), st.none())) - if curr_backend in ["tensorflow", "jax"] and not mixed_fn_compos: - align_corners = False if mode == "linear": num_dims = 3 elif mode in [ "bilinear", - "bicubic_tensorflow", + "tf_bicubic", "bicubic", "mitchellcubic", "gaussian", @@ -113,7 +110,6 @@ def _interp_args(draw, mode=None, mode_list=None): ) + 2 ) - align_corners = None if curr_backend == "tensorflow" and not mixed_fn_compos: num_dims = 3 dtype, x = draw( @@ -125,50 +121,126 @@ def _interp_args(draw, mode=None, mode_list=None): max_num_dims=num_dims, min_dim_size=2, max_dim_size=5, - large_abs_safety_factor=50, - small_abs_safety_factor=50, - safety_factor_scale="log", + max_value=1e04, + min_value=-1e04, + abs_smallest_val=1e-04, ) ) + align_corners = draw(st.booleans()) if draw(st.booleans()): - scale_factor = draw( - st.one_of( - helpers.lists( - x=helpers.floats( - min_value=1.0, max_value=2.0, mixed_fn_compos=mixed_fn_compos - ), - min_size=num_dims - 2, - max_size=num_dims - 2, - ), - helpers.floats( - min_value=1.0, max_value=2.0, mixed_fn_compos=mixed_fn_compos - ), + if draw(st.booleans()): + scale_factor = draw( + st.floats(min_value=max([1 / d for d in x[0].shape[2:]]), max_value=3) ) - ) + else: + scale_factor = [] + for s in x[0].shape[2:]: + scale_factor += [draw(st.floats(min_value=1 / s, max_value=3))] recompute_scale_factor = draw(st.booleans()) size = None else: size = draw( st.one_of( - helpers.lists( - x=helpers.ints( - min_value=1, max_value=3, mixed_fn_compos=mixed_fn_compos - ), + st.lists( + st.integers(min_value=1, max_value=3 * max(x[0].shape)), min_size=num_dims - 2, max_size=num_dims - 2, ), - st.integers(min_value=1, max_value=3), + st.integers(min_value=1, max_value=3 * max(x[0].shape)), ) ) - recompute_scale_factor = False + recompute_scale_factor = None scale_factor = None - if curr_backend in ["tensorflow", "jax"] and not mixed_fn_compos: - if not recompute_scale_factor: - recompute_scale_factor = True - return (dtype, x, mode, size, align_corners, scale_factor, recompute_scale_factor) +@st.composite +def _lstm_helper(draw): + input_size = draw(helpers.ints(min_value=2, max_value=5)) + hidden_size = 4 * input_size + input_length = draw(helpers.ints(min_value=2, max_value=5)) + batch_size = draw(helpers.ints(min_value=1, max_value=4)) * 2 + dtype = draw(helpers.get_dtypes("float", full=False)) + (time_major, go_backwards, unroll, zero_output_for_mask, return_all_outputs) = draw( + helpers.array_bools(size=5) + ) + shape = [batch_size, input_length, input_size] + if time_major: + shape = [input_length, batch_size, input_size] + inputs = draw( + helpers.dtype_and_values( + available_dtypes=dtype, + shape=shape, + min_value=-1, + max_value=1, + abs_smallest_val=1e-5, + safety_factor_scale="log", + ) + )[1][0] + mask = draw( + st.just([None, [None]]) + | helpers.dtype_and_values( + available_dtypes=["bool"], + shape=[*shape[:2], 1], + ) + )[1][0] + kernel, recurrent_kernel = draw( + helpers.dtype_and_values( + available_dtypes=dtype, + num_arrays=2, + shape=(input_size, hidden_size), + min_value=-1, + max_value=1, + abs_smallest_val=1e-5, + safety_factor_scale="log", + ) + )[1] + bias, recurrent_bias = draw( + helpers.dtype_and_values( + available_dtypes=dtype, + num_arrays=2, + shape=(1, hidden_size), + min_value=-1, + max_value=1, + abs_smallest_val=1e-5, + safety_factor_scale="log", + ) + )[1] + init_h, init_c = draw( + helpers.dtype_and_values( + available_dtypes=dtype, + num_arrays=2, + shape=(batch_size, input_size), + min_value=-1, + max_value=1, + abs_smallest_val=1e-5, + safety_factor_scale="log", + ) + )[1] + dtypes = [dtype[0] for _ in range(7)] + if mask is not None: + dtypes.append("bool") + # ToDo : zero_output_for_mask doesn't work if we don't return_all_outputs + # in tensorflow + zero_output_for_mask = zero_output_for_mask and return_all_outputs + return ( + dtypes, + inputs, + kernel, + recurrent_kernel, + bias, + recurrent_bias, + [init_h, init_c], + go_backwards, + mask, + unroll, + input_length, + time_major, + zero_output_for_mask, + return_all_outputs, + ) + + @st.composite def _reduce_window_helper(draw, get_func_st): dtype = draw(helpers.get_dtypes("valid", full=False, index=2)) @@ -517,7 +589,7 @@ def test_adaptive_avg_pool1d( available_dtypes=helpers.get_dtypes("float"), min_num_dims=3, max_num_dims=4, - min_dim_size=1, + min_dim_size=2, max_value=100, min_value=-100, ), @@ -528,11 +600,12 @@ def test_adaptive_avg_pool1d( ), helpers.ints(min_value=1, max_value=5), ), + data_format=st.sampled_from(["NCHW", "NHWC"]), test_with_out=st.just(False), ground_truth_backend="torch", ) def test_adaptive_avg_pool2d( - *, dtype_and_x, output_size, test_flags, backend_fw, fn_name, on_device + *, dtype_and_x, output_size, data_format, test_flags, backend_fw, fn_name, on_device ): input_dtype, x = dtype_and_x helpers.test_function( @@ -543,6 +616,7 @@ def test_adaptive_avg_pool2d( fn_name=fn_name, input=x[0], output_size=output_size, + data_format=data_format, ) @@ -583,6 +657,42 @@ def test_adaptive_max_pool2d( ) +@handle_test( + fn_tree="functional.ivy.experimental.adaptive_max_pool3d", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("float"), + min_num_dims=4, + max_num_dims=5, + min_dim_size=1, + max_value=100, + min_value=-100, + ), + output_size=st.one_of( + st.tuples( + helpers.ints(min_value=1, max_value=5), + helpers.ints(min_value=1, max_value=5), + helpers.ints(min_value=1, max_value=5), + ), + helpers.ints(min_value=1, max_value=5), + ), + test_with_out=st.just(False), + ground_truth_backend="torch", +) +def test_adaptive_max_pool3d( + *, dtype_and_x, output_size, test_flags, backend_fw, fn_name, on_device +): + input_dtype, x = dtype_and_x + helpers.test_function( + input_dtypes=input_dtype, + test_flags=test_flags, + backend_to_test=backend_fw, + on_device=on_device, + fn_name=fn_name, + input=x[0], + output_size=output_size, + ) + + @handle_test( fn_tree="functional.ivy.experimental.avg_pool1d", x_k_s_p=helpers.arrays_for_pooling(min_dims=3, max_dims=3, min_side=1, max_side=4), @@ -1074,13 +1184,10 @@ def test_ifftn( @handle_test( fn_tree="functional.ivy.experimental.interpolate", dtype_x_mode=_interp_args(), - antialias=st.just(False), test_gradients=st.just(False), number_positional_args=st.just(2), ) -def test_interpolate( - dtype_x_mode, antialias, test_flags, backend_fw, fn_name, on_device -): +def test_interpolate(dtype_x_mode, test_flags, backend_fw, fn_name, on_device): ( input_dtype, x, @@ -1097,12 +1204,11 @@ def test_interpolate( fn_name=fn_name, on_device=on_device, rtol_=1e-01, - atol_=1e-01, + atol_=1e-03, x=x[0], size=size, mode=mode, align_corners=align_corners, - antialias=antialias, scale_factor=scale_factor, recompute_scale_factor=recompute_scale_factor, ) @@ -1186,12 +1292,9 @@ def test_max_pool2d( assume( not ( backend_fw == "tensorflow" - and ( - (stride[0] > kernel[0] or stride[0] > kernel[1]) - or ( - (stride[0] > 1 and dilation[0] > 1) - or (stride[0] > 1 and dilation[1] > 1) - ) + and all( + stride[i] > kernel[i] or (stride[i] > 1 and dilation[i] > 1) + for i in range(2) ) ) ) @@ -1244,7 +1347,14 @@ def test_max_pool3d( on_device, ): dtype, x, kernel, stride, pad, dilation, data_format = x_k_s_p - + assume( + not ( + backend_fw == "tensorflow" + and isinstance(pad, str) + and pad == "SAME" + and any(dil > 1 for dil in dilation) + ) + ) data_format = "NCDHW" if data_format == "channel_first" else "NDHWC" assume(not (isinstance(pad, str) and (pad.upper() == "VALID") and ceil_mode)) # TODO: Remove this once the paddle backend supports dilation @@ -1384,6 +1494,95 @@ def test_rfftn( ) +# test_rnn +@handle_test( + fn_tree="functional.ivy.experimental.rnn", + rnn_args=_lstm_helper(), + test_with_out=st.just(False), + test_instance_method=st.just(False), +) +def test_rnn( + *, + rnn_args, + test_flags, + backend_fw, + fn_name, + on_device, +): + # ToDo : Get the tests passing with paddle + ( + input_dtypes, + inputs, + kernel_orig, + recurrent_kernel_orig, + bias_orig, + recurrent_bias_orig, + initial_states, + go_backwards, + mask, + unroll, + input_length, + time_major, + zero_output_for_mask, + return_all_outputs, + ) = rnn_args + + # unsupported dtype of float16 is in our _lstm_step function + # so can't be inferred through ivy.function_unsupported_devices_and_dtypes + assume(not (backend_fw == "torch" and input_dtypes[0] == "float16")) + + def _lstm_step(cell_inputs, cell_states): + with BackendHandler.update_backend( + ivy.current_backend( + cell_inputs.to_native() + if "ivy" in str(type(cell_inputs)) + else cell_inputs + ).backend + ) as ivy_backend: + nonlocal kernel_orig, recurrent_kernel_orig, bias_orig, recurrent_bias_orig + kernel = ivy_backend.array(kernel_orig) + recurrent_kernel = ivy_backend.array(recurrent_kernel_orig) + bias = ivy_backend.array(bias_orig) + recurrent_bias = ivy_backend.array(recurrent_bias_orig) + + h_tm1 = cell_states[0] # previous memory state + c_tm1 = cell_states[1] # previous carry state + + z = ivy_backend.dot(cell_inputs, kernel) + bias + z += ivy_backend.dot(h_tm1, recurrent_kernel) + recurrent_bias + + z0, z1, z2, z3 = ivy_backend.split(z, num_or_size_splits=4, axis=-1) + + i = ivy_backend.sigmoid(z0) # input + f = ivy_backend.sigmoid(z1) # forget + c = f * c_tm1 + i * ivy_backend.tanh(z2) + o = ivy_backend.sigmoid(z3) # output + + h = o * ivy_backend.tanh(c) + return h, [h, c] + + helpers.test_function( + input_dtypes=input_dtypes, + test_flags=test_flags, + backend_to_test=backend_fw, + on_device=on_device, + fn_name=fn_name, + rtol_=1e-1, + atol_=1e-1, + step_function=_lstm_step, + inputs=inputs, + initial_states=initial_states, + go_backwards=go_backwards, + mask=mask, + constants=None, + unroll=unroll, + input_length=input_length, + time_major=time_major, + zero_output_for_mask=zero_output_for_mask, + return_all_outputs=return_all_outputs, + ) + + @handle_test( fn_tree="functional.ivy.experimental.sliding_window", all_args=helpers.arrays_for_pooling(3, 3, 1, 2, return_dilation=True), diff --git a/ivy_tests/test_ivy/test_functional/test_experimental/test_nn/test_losses.py b/ivy_tests/test_ivy/test_functional/test_experimental/test_nn/test_losses.py index 2161ee814304b..8c0028d457e24 100644 --- a/ivy_tests/test_ivy/test_functional/test_experimental/test_nn/test_losses.py +++ b/ivy_tests/test_ivy/test_functional/test_experimental/test_nn/test_losses.py @@ -7,6 +7,100 @@ from ivy_tests.test_ivy.helpers import handle_test +# --- Helpers --- # +# --------------- # + + +@st.composite +def _hinge_embedding_loss_input( + draw, min_num_dims=1, max_num_dims=5, min_dim_size=1, max_dim_size=10 +): + # determine the shape for both arrays (input and target) + shape = draw( + st.shared( + helpers.get_shape( + min_num_dims=min_num_dims, + max_num_dims=max_num_dims, + min_dim_size=min_dim_size, + max_dim_size=max_dim_size, + ), + key="shared_shape", + ) + ) + + # Generate an array of -1 and 1 with the given shape (target_array) + def _arrays_of_neg1_and_1(shape): + value_strategy = st.sampled_from([-1, 1]) + prod_shape = int(np.prod(shape)) # Convert np.int64 to int + array_data = draw( + st.lists(value_strategy, min_size=prod_shape, max_size=prod_shape) + ) + return np.asarray(array_data).reshape(shape) + + # input_array + dtype, xx = draw( + helpers.dtype_and_values( + shape=shape, + available_dtypes=helpers.get_dtypes("valid"), + safety_factor_scale="linear", + large_abs_safety_factor=2, + small_abs_safety_factor=2, + min_value=1, + max_value=10, + min_dim_size=1, + min_num_dims=1, + max_num_dims=5, + max_dim_size=5, + ) + ) + + # generate the target array 'yy' containing either 1 or -1 + yy = _arrays_of_neg1_and_1(shape=shape) + + return dtype, xx, yy + + +# --- Main --- # +# ------------ # + + +# hinge_embedding_loss +@handle_test( + fn_tree="functional.ivy.experimental.hinge_embedding_loss", + dtype_and_inputs=_hinge_embedding_loss_input(), + margin=st.floats(min_value=1, max_value=5), + reduction=st.sampled_from(["none", "sum", "mean"]), + test_gradients=st.just( + False + ), # Gradients are failing for "jax" and "paddle" backend. + test_with_out=st.just(False), + ground_truth_backend="torch", +) +def test_hinge_embedding_loss( + dtype_and_inputs, + margin, + reduction, + test_flags, + backend_fw, + fn_name, + on_device, +): + dtype, xx, yy = dtype_and_inputs + helpers.test_function( + input_dtypes=dtype, + test_flags=test_flags, + backend_to_test=backend_fw, + fn_name=fn_name, + on_device=on_device, + input=xx[0], + target=yy, + margin=margin, + reduction=reduction, + rtol_=1e-05, + atol_=1e-05, + ) + + # huber_loss @handle_test( fn_tree="functional.ivy.experimental.huber_loss", diff --git a/ivy_tests/test_ivy/test_functional/test_experimental/test_nn/test_norms.py b/ivy_tests/test_ivy/test_functional/test_experimental/test_nn/test_norms.py index 014305269a51e..f728d9840769a 100644 --- a/ivy_tests/test_ivy/test_functional/test_experimental/test_nn/test_norms.py +++ b/ivy_tests/test_ivy/test_functional/test_experimental/test_nn/test_norms.py @@ -170,6 +170,8 @@ def _instance_and_batch_norm_helper(draw, *, min_dims=1, test_function="instance fn_tree="functional.ivy.experimental.batch_norm", data=_instance_and_batch_norm_helper(min_dims=2, test_function="batch_norm"), training=st.booleans(), + test_instance_method=st.just(False), + container_flags=st.just([False]), ) def test_batch_norm(*, data, training, test_flags, backend_fw, fn_name, on_device): x_dtype, x, mean, variance, offset, scale, eps, momentum, data_format = data @@ -271,3 +273,57 @@ def test_l1_normalize(*, dtype_values_axis, test_flags, backend_fw, fn_name, on_ x=x, axis=axis, ) + + +# local_response_norm +@handle_test( + fn_tree="functional.ivy.experimental.local_response_norm", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), + min_num_dims=4, + max_num_dims=4, + min_dim_size=1, + large_abs_safety_factor=2, + small_abs_safety_factor=2, + safety_factor_scale="log", + ), + size=st.integers(min_value=1, max_value=10), + bias=st.floats(min_value=0.1, max_value=1.5), + alpha=st.floats(min_value=1e-4, max_value=1.2), + beta=st.floats(min_value=0.1, max_value=1.5), + average=st.booleans(), + data_format=st.sampled_from(["NHWC", "NCHW"]), + test_with_out=st.just(False), + test_instance_method=st.just(False), + container_flags=st.just([False]), + test_gradients=st.just(False), +) +def test_local_response_norm( + *, + dtype_and_x, + size, + bias, + alpha, + beta, + average, + data_format, + test_flags, + fn_name, + backend_fw, + on_device, +): + input_dtype, x = dtype_and_x + helpers.test_function( + input_dtypes=input_dtype, + backend_to_test=backend_fw, + test_flags=test_flags, + fn_name=fn_name, + on_device=on_device, + input=x[0], + size=size, + bias=bias, + alpha=alpha, + beta=beta, + average=average, + data_format=data_format, + ) diff --git a/ivy_tests/test_ivy/test_functional/test_nn/test_activations.py b/ivy_tests/test_ivy/test_functional/test_nn/test_activations.py index 83a1d3985c6ff..5b2aa8086cd9f 100644 --- a/ivy_tests/test_ivy/test_functional/test_nn/test_activations.py +++ b/ivy_tests/test_ivy/test_functional/test_nn/test_activations.py @@ -166,7 +166,7 @@ def test_mish(*, dtype_and_x, test_flags, backend_fw, fn_name, on_device): @handle_test( fn_tree="functional.ivy.relu", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("numeric"), + available_dtypes=helpers.get_dtypes("valid"), large_abs_safety_factor=8, small_abs_safety_factor=8, safety_factor_scale="log", @@ -208,6 +208,8 @@ def test_sigmoid( test_flags=test_flags, fn_name=fn_name, on_device=on_device, + atol_=1e-02, + rtol_=1e-02, x=x[0], complex_mode=complex_mode, ) diff --git a/ivy_tests/test_ivy/test_functional/test_nn/test_layers.py b/ivy_tests/test_ivy/test_functional/test_nn/test_layers.py index 988d6e7ac78fa..385b19b1a4c18 100644 --- a/ivy_tests/test_ivy/test_functional/test_nn/test_layers.py +++ b/ivy_tests/test_ivy/test_functional/test_nn/test_layers.py @@ -9,7 +9,7 @@ # local import ivy_tests.test_ivy.helpers as helpers from ivy_tests.test_ivy.helpers import handle_test -from ivy.functional.ivy.layers import _deconv_length +from ivy.functional.ivy.layers import _deconv_length, _pack_padded_sequence # --- Helpers --- # @@ -67,6 +67,173 @@ def _dropout_helper(draw): return dtype_and_x, noise_shape, seed, dtype, prob, scale, training +@st.composite +def _general_transpose_helper(draw): + dims = draw(st.integers(1, 3)) + padding = st.sampled_from(["SAME", "VALID"]) if dims != 2 else None + x_f_d_df = draw( + _x_and_filters( + dim=dims, + general=True, + transpose=True, + bias=True, + padding=padding, + ) + ) + return dims, x_f_d_df + + +@st.composite +def _lstm_helper(draw): + dtype = draw(helpers.get_dtypes("float", full=False)) + + has_ih_bias = draw(st.booleans()) + has_hh_bias = draw(st.booleans()) + weights_transposed = draw(st.booleans()) + bidirectional = draw(st.booleans()) + dropout = draw(st.floats(min_value=0, max_value=0.99)) + train = draw(st.booleans()) and not dropout + packed = draw(st.booleans()) + + batch_first = draw(st.booleans()) and not packed + num_batches = draw(st.integers(min_value=1, max_value=5)) + num_layers = draw(st.integers(min_value=1, max_value=3)) + num_directions = 2 if bidirectional else 1 + seq_size = draw(st.integers(min_value=1, max_value=5)) + in_size = draw(st.integers(min_value=1, max_value=3)) + hidden_size = draw(st.integers(min_value=1, max_value=3)) + + input = draw( + helpers.array_values( + dtype=dtype[0], + shape=( + (num_batches, seq_size, in_size) + if batch_first + else (seq_size, num_batches, in_size) + ), + min_value=0, + max_value=1, + ) + ) + + init_h = draw( + helpers.array_values( + dtype=dtype[0], + shape=(num_directions * num_layers, num_batches, hidden_size), + min_value=0, + max_value=1, + ) + ) + init_c = draw( + helpers.array_values( + dtype=dtype[0], + shape=(num_directions * num_layers, num_batches, hidden_size), + min_value=0, + max_value=1, + ) + ) + + all_weights = [] + for k in range(num_layers): + for _ in range(num_directions): + weight_ih = draw( + helpers.array_values( + dtype=dtype[0], + shape=( + (4 * hidden_size, in_size) + if k == 0 + else (4 * hidden_size, num_directions * hidden_size) + ), + min_value=0, + max_value=1, + ) + ) + weight_hh = draw( + helpers.array_values( + dtype=dtype[0], + shape=(4 * hidden_size, hidden_size), + min_value=0, + max_value=1, + ) + ) + all_weights += [weight_ih, weight_hh] + if has_ih_bias: + bias_ih = draw( + helpers.array_values( + dtype=dtype[0], + shape=(4 * hidden_size,), + min_value=0, + max_value=1, + ) + ) + all_weights.append(bias_ih) + if has_hh_bias: + bias_hh = draw( + helpers.array_values( + dtype=dtype[0], + shape=(4 * hidden_size,), + min_value=0, + max_value=1, + ) + ) + all_weights.append(bias_hh) + + if weights_transposed: + all_weights = [ + ivy.swapaxes(w, 0, 1) if w.dims() == 2 else w for w in all_weights + ] + + if packed: + batch_sizes = [seq_size] + batch_sizes += draw( + st.lists( + st.integers(min_value=1, max_value=seq_size), + min_size=num_batches - 1, + max_size=num_batches - 1, + ) + ) + batch_sizes = np.array(draw(st.permutations(batch_sizes))) + input, batch_sizes = ( + ivy.to_numpy(p) for p in _pack_padded_sequence(input, batch_sizes) + ) + else: + batch_sizes = None + + initial_states = init_h, init_c + all_weights = tuple(all_weights) + if batch_sizes is not None: + dtypes = dtype + ["int64"] + kwargs = { + "input": input, + "batch_sizes": batch_sizes, + "initial_states": initial_states, + "all_weights": all_weights, + "num_layers": num_layers, + "dropout": dropout, + "train": train, + "bidirectional": bidirectional, + "weights_transposed": weights_transposed, + "has_ih_bias": has_ih_bias, + "has_hh_bias": has_hh_bias, + } + else: + dtypes = dtype + kwargs = { + "input": input, + "initial_states": initial_states, + "all_weights": all_weights, + "num_layers": num_layers, + "dropout": dropout, + "train": train, + "bidirectional": bidirectional, + "batch_first": batch_first, + "weights_transposed": weights_transposed, + "has_ih_bias": has_ih_bias, + "has_hh_bias": has_hh_bias, + } + return dtypes, kwargs + + @st.composite def _mha_helper(draw, same_pre_embed_dim=False, batch_second=False): _qkv_same_dim = draw(st.booleans()) @@ -307,7 +474,7 @@ def _mha_helper(draw, same_pre_embed_dim=False, batch_second=False): average_attention_weights = draw(st.booleans()) if len(q.shape) == 3 and not batch_first: - q, k, v = [np.swapaxes(x, 0, 1) if x is not None else x for x in [q, k, v]] + q, k, v = (np.swapaxes(x, 0, 1) if x is not None else x for x in [q, k, v]) ret = ( q, @@ -366,6 +533,35 @@ def _nms_helper(draw): ) +# Convolutions # +# -------------# + + +def _output_shape(dims, dilation, stride, padding, x_shape, filter_shape): + if isinstance(padding, str): + return [ + _deconv_length( + x_shape[i], + stride[i], + filter_shape[i], + padding, + dilation[i], + ) + for i in range(dims) + ] + else: + if isinstance(padding, int): + padding = [[padding, padding]] * dims + return [ + (x_shape[i] - 1) * stride[i] + - padding[i][0] + - padding[i][1] + + dilation[i] * (filter_shape[i] - 1) + + 1 + for i in range(dims) + ] + + @st.composite def _roi_align_helper(draw): dtype = draw(helpers.get_dtypes("float", full=False))[0] @@ -411,19 +607,15 @@ def _roi_align_helper(draw): ) -# Convolutions # -# -------------# - - @st.composite def _x_and_filters( draw, dim: int = 2, + padding=None, transpose: bool = False, depthwise=False, general=False, bias=False, - filter_format=None, ): if not isinstance(dim, int): dim = draw(dim) @@ -438,10 +630,14 @@ def _x_and_filters( output_channels = draw(st.integers(1, 3)) group_list = [*range(1, 6)] if not transpose: - group_list = list(filter(lambda x: (input_channels % x == 0), group_list)) + group_list = list( + filter( + lambda x: (input_channels % x == 0 and x <= output_channels), group_list + ) + ) else: group_list = list(filter(lambda x: (output_channels % x == 0), group_list)) - fc = draw(st.sampled_from(group_list)) if general else 1 + fc = draw(st.sampled_from(group_list)) strides = draw( st.one_of( st.integers(1, 3), st.lists(st.integers(1, 3), min_size=dim, max_size=dim) @@ -462,48 +658,45 @@ def _x_and_filters( data_format = draw(st.sampled_from(["NWC", "NCW"])) else: data_format = draw(st.sampled_from(["NDHWC", "NCDHW"])) - - full_strides = [strides] * dim if isinstance(strides, int) else strides - full_dilations = [dilations] * dim if isinstance(dilations, int) else dilations + fdilations = [dilations] * dim if isinstance(dilations, int) else dilations + if padding is None: + padding = st.one_of( + st.lists( + st.tuples( + st.integers(min_value=0, max_value=3), + st.integers(min_value=0, max_value=3), + ), + min_size=dim, + max_size=dim, + ), + st.sampled_from(["SAME", "VALID"]), + st.integers(min_value=0, max_value=3), + ) + padding = draw(padding) if transpose: - padding = draw(st.sampled_from(["SAME", "VALID"])) + fstrides = [strides] * dim if isinstance(strides, int) else strides + if isinstance(padding, list): + assume( + all( + max(pad) - min(pad) < min(stride, dilation) + for pad, stride, dilation in zip(padding, fstrides, fdilations) + ) + ) x_dim = draw( helpers.get_shape( min_num_dims=dim, max_num_dims=dim, min_dim_size=1, max_dim_size=5 ) ) + output_shape = _output_shape( + dim, fdilations, fstrides, padding, x_dim, filter_shape + ) + assume(all(s > 0 for s in output_shape)) if draw(st.booleans()): - output_shape = [] - for i in range(dim): - output_shape.append( - _deconv_length( - x_dim[i], - full_strides[i], - filter_shape[i], - padding, - full_dilations[i], - ) - ) - else: output_shape = None else: - padding = draw( - st.one_of( - st.lists( - st.tuples( - st.integers(min_value=0, max_value=3), - st.integers(min_value=0, max_value=3), - ), - min_size=dim, - max_size=dim, - ), - st.sampled_from(["SAME", "VALID"]), - st.integers(min_value=0, max_value=3), - ) - ) x_dim = [] for i in range(dim): - min_x = filter_shape[i] + (filter_shape[i] - 1) * (full_dilations[i] - 1) + min_x = filter_shape[i] + (filter_shape[i] - 1) * (fdilations[i] - 1) x_dim.append(draw(st.integers(min_x, min_x + 1))) x_dim = tuple(x_dim) if not depthwise: @@ -512,7 +705,7 @@ def _x_and_filters( filter_shape = filter_shape + (input_channels // fc, output_channels) else: input_channels = input_channels * fc - filter_shape = filter_shape + (input_channels, output_channels // fc) + filter_shape = filter_shape + (output_channels // fc, input_channels) else: filter_shape = filter_shape + (input_channels,) channel_first = True @@ -557,8 +750,8 @@ def _x_and_filters( ) ) dilations = (dilations, x_dilation) - if filter_format is not None: - filter_format = draw(filter_format) + if not depthwise: + filter_format = draw(st.sampled_from(["channel_first", "channel_last"])) if filter_format == "channel_first": filters = np.transpose(filters, (-1, -2, *range(dim))) ret = ( @@ -571,13 +764,13 @@ def _x_and_filters( padding, ) ret = ret + (output_shape, fc) if transpose else ret + (fc,) - ret = ret + (filter_format,) if filter_format is not None else ret + if not depthwise: + ret = ret + (filter_format,) if bias: return ret + (b,) return ret -# filter_format not in conv_general_transpose # output_shape not in conv_general_dilated @st.composite def _x_and_filters_and_transpose( @@ -585,22 +778,17 @@ def _x_and_filters_and_transpose( dim: int = 2, general=False, bias=False, - filter_format=None, ): transpose = draw(st.booleans()) - if not transpose: - filter_format = st.sampled_from(["channel_last", "channel_first"]) all_args = draw( _x_and_filters( dim=dim, general=general, bias=bias, - filter_format=filter_format, transpose=transpose, ) ) output_shape = None - filter_format = "channel_last" if transpose: ( dtype, @@ -612,6 +800,7 @@ def _x_and_filters_and_transpose( pad, output_shape, fc, + filter_format, bias, ) = all_args else: @@ -650,7 +839,8 @@ def _x_and_linear(draw): mixed_fn_compos = draw(st.booleans()) is_torch_backend = ivy.current_backend_str() == "torch" dtype = draw( - helpers.get_dtypes("numeric", full=False, mixed_fn_compos=mixed_fn_compos) + # should sample from "valid" but with_supported_dtypes was not working + helpers.get_dtypes("float", full=False, mixed_fn_compos=mixed_fn_compos) ) in_features = draw( helpers.ints(min_value=1, max_value=2, mixed_fn_compos=mixed_fn_compos) @@ -885,7 +1075,6 @@ def test_conv(*, dims, x_f_d_df_tr, test_flags, backend_fw, fn_name, on_device): x_f_d_df=_x_and_filters( dim=1, bias=True, - filter_format=st.sampled_from(["channel_last", "channel_first"]), ), ground_truth_backend="jax", ) @@ -931,8 +1120,9 @@ def test_conv1d(*, x_f_d_df, test_flags, backend_fw, fn_name, on_device): dim=1, transpose=True, bias=True, + padding=st.sampled_from(["SAME", "VALID"]), ), - ground_truth_backend="jax", + ground_truth_backend="torch", ) def test_conv1d_transpose(*, x_f_d_df, test_flags, backend_fw, fn_name, on_device): ( @@ -945,9 +1135,11 @@ def test_conv1d_transpose(*, x_f_d_df, test_flags, backend_fw, fn_name, on_devic pad, output_shape, fc, + filter_format, bias, ) = x_f_d_df - _assume_tf_dilation_gt_1(backend_fw, on_device, dilations[0]) + # tensorflow does not work with dilations > 1 on cpu + _assume_tf_dilation_gt_1(backend_fw, on_device, dilations) helpers.test_function( input_dtypes=dtype, test_flags=test_flags, @@ -956,14 +1148,14 @@ def test_conv1d_transpose(*, x_f_d_df, test_flags, backend_fw, fn_name, on_devic on_device=on_device, rtol_=1e-2, atol_=1e-2, - # tensorflow does not work with dilations > 1 on cpu x=x, filters=filters, strides=stride, padding=pad, output_shape=output_shape, + filter_format=filter_format, data_format=data_format, - dilations=dilations[0], + dilations=dilations, bias=bias, ) @@ -974,7 +1166,6 @@ def test_conv1d_transpose(*, x_f_d_df, test_flags, backend_fw, fn_name, on_devic x_f_d_df=_x_and_filters( dim=2, bias=True, - filter_format=st.sampled_from(["channel_last", "channel_first"]), ), ground_truth_backend="jax", ) @@ -1021,8 +1212,7 @@ def test_conv2d(*, x_f_d_df, test_flags, backend_fw, fn_name, on_device): transpose=True, bias=True, ), - # tensorflow does not work with dilations > 1 on cpu - ground_truth_backend="jax", + ground_truth_backend="torch", ) def test_conv2d_transpose(*, x_f_d_df, test_flags, backend_fw, fn_name, on_device): ( @@ -1035,10 +1225,11 @@ def test_conv2d_transpose(*, x_f_d_df, test_flags, backend_fw, fn_name, on_devic pad, output_shape, fc, + filter_format, bias, ) = x_f_d_df - _assume_tf_dilation_gt_1(backend_fw, on_device, dilations[0]) - + assume(isinstance(pad, str) or backend_fw in ["torch", "tensorflow"]) + _assume_tf_dilation_gt_1(backend_fw, on_device, dilations) helpers.test_function( input_dtypes=dtype, test_flags=test_flags, @@ -1052,8 +1243,9 @@ def test_conv2d_transpose(*, x_f_d_df, test_flags, backend_fw, fn_name, on_devic strides=stride, padding=pad, output_shape=output_shape, + filter_format=filter_format, data_format=data_format, - dilations=dilations[0], + dilations=dilations, bias=bias, ) @@ -1064,7 +1256,6 @@ def test_conv2d_transpose(*, x_f_d_df, test_flags, backend_fw, fn_name, on_devic x_f_d_df=_x_and_filters( dim=3, bias=True, - filter_format=st.sampled_from(["channel_last", "channel_first"]), ), ground_truth_backend="jax", ) @@ -1109,8 +1300,9 @@ def test_conv3d(*, x_f_d_df, test_flags, backend_fw, fn_name, on_device): dim=3, transpose=True, bias=True, + padding=st.sampled_from(["SAME", "VALID"]), ), - ground_truth_backend="jax", + ground_truth_backend="torch", ) def test_conv3d_transpose(*, x_f_d_df, test_flags, backend_fw, fn_name, on_device): ( @@ -1123,9 +1315,10 @@ def test_conv3d_transpose(*, x_f_d_df, test_flags, backend_fw, fn_name, on_devic pad, output_shape, fc, + filter_format, bias, ) = x_f_d_df - _assume_tf_dilation_gt_1(backend_fw, on_device, dilations[0]) + _assume_tf_dilation_gt_1(backend_fw, on_device, dilations) helpers.test_function( input_dtypes=dtype, test_flags=test_flags, @@ -1139,8 +1332,9 @@ def test_conv3d_transpose(*, x_f_d_df, test_flags, backend_fw, fn_name, on_devic strides=stride, padding=pad, output_shape=output_shape, + filter_format=filter_format, data_format=data_format, - dilations=dilations[0], + dilations=dilations, bias=bias, ) @@ -1153,9 +1347,8 @@ def test_conv3d_transpose(*, x_f_d_df, test_flags, backend_fw, fn_name, on_devic dim=st.shared(st.integers(1, 3), key="dims"), general=True, bias=True, - filter_format=st.sampled_from(["channel_last", "channel_first"]), ), - ground_truth_backend="jax", + ground_truth_backend="torch", ) def test_conv_general_dilated( *, dims, x_f_d_df, test_flags, backend_fw, fn_name, on_device @@ -1197,19 +1390,13 @@ def test_conv_general_dilated( @handle_test( fn_tree="functional.ivy.conv_general_transpose", - dims=st.shared(st.integers(1, 3), key="dims"), - x_f_d_df=_x_and_filters( - dim=st.shared(st.integers(1, 3), key="dims"), - general=True, - transpose=True, - bias=True, - ), - ground_truth_backend="jax", + dim_x_f_d_df=_general_transpose_helper(), + ground_truth_backend="torch", ) def test_conv_general_transpose( - *, dims, x_f_d_df, test_flags, backend_fw, fn_name, on_device + *, dim_x_f_d_df, test_flags, backend_fw, fn_name, on_device ): - ( + dims, ( dtype, x, filters, @@ -1219,8 +1406,10 @@ def test_conv_general_transpose( pad, output_shape, fc, + filter_format, bias, - ) = x_f_d_df + ) = dim_x_f_d_df + assume(isinstance(pad, str) or backend_fw in ["torch", "tensorflow"]) _assume_tf_dilation_gt_1(backend_fw, on_device, dilations) helpers.test_function( input_dtypes=dtype, @@ -1235,8 +1424,9 @@ def test_conv_general_transpose( strides=stride, padding=pad, dims=dims, - output_shape=output_shape, + filter_format=filter_format, data_format=data_format, + output_shape=output_shape, dilations=dilations, feature_group_count=fc, bias=bias, @@ -1272,7 +1462,7 @@ def test_depthwise_conv2d(*, x_f_d_df, test_flags, backend_fw, fn_name, on_devic strides=stride, padding=pad, data_format=data_format, - dilations=dilations, + dilations=dilations[0], ) @@ -1291,28 +1481,44 @@ def test_dropout( on_device, ): (x_dtype, x), noise_shape, seed, dtype, prob, scale, training = data - ret, gt_ret = helpers.test_function( - input_dtypes=x_dtype, - test_flags=test_flags, - backend_to_test=backend_fw, - fn_name=fn_name, - on_device=on_device, - test_values=False, - x=x[0], - prob=prob, - scale=scale, - noise_shape=noise_shape, - dtype=dtype[0], - training=training, - seed=seed, - ) - ret = helpers.flatten_and_to_np(ret=ret, backend=backend_fw) - gt_ret = helpers.flatten_and_to_np( - ret=gt_ret, backend=test_flags.ground_truth_backend - ) - for u, v, w in zip(ret, gt_ret, x): - # cardinality test - assert u.shape == v.shape == w.shape + if not training or prob == 0: + helpers.test_function( + input_dtypes=x_dtype, + test_flags=test_flags, + backend_to_test=backend_fw, + fn_name=fn_name, + on_device=on_device, + x=x[0], + prob=prob, + scale=scale, + noise_shape=noise_shape, + dtype=dtype[0], + training=training, + seed=seed, + ) + else: + ret, gt_ret = helpers.test_function( + input_dtypes=x_dtype, + test_flags=test_flags, + backend_to_test=backend_fw, + fn_name=fn_name, + on_device=on_device, + test_values=False, + x=x[0], + prob=prob, + scale=scale, + noise_shape=noise_shape, + dtype=dtype[0], + training=training, + seed=seed, + ) + ret = helpers.flatten_and_to_np(ret=ret, backend=backend_fw) + gt_ret = helpers.flatten_and_to_np( + ret=gt_ret, backend=test_flags.ground_truth_backend + ) + for u, v, w in zip(ret, gt_ret, x): + # cardinality test + assert u.shape == v.shape == w.shape # linear @@ -1336,7 +1542,30 @@ def test_linear(*, dtype_x_weight_bias, test_flags, backend_fw, fn_name, on_devi ) +# TODO: fix this test # lstm +# @handle_test( +# fn_tree="functional.ivy.lstm", +# dtypes_kwargs=_lstm_helper(), +# ground_truth_backend="torch", +# test_with_out=st.just(False), +# ) +# def test_lstm(*, dtypes_kwargs, test_flags, backend_fw, fn_name, on_device): +# dtypes, kwargs = dtypes_kwargs +# assume("batch_sizes" not in kwargs) +# helpers.test_function( +# input_dtypes=dtypes, +# test_flags=test_flags, +# backend_to_test=backend_fw, +# fn_name=fn_name, +# on_device=on_device, +# rtol_=1e-01, +# atol_=1e-01, +# **kwargs, +# ) + + +# lstm_update @handle_test( fn_tree="functional.ivy.lstm_update", dtype_lstm=_x_and_lstm( diff --git a/ivy_tests/test_ivy/test_misc/test_array.py b/ivy_tests/test_ivy/test_misc/test_array.py index 12553cf4da570..1fb44cef282d3 100644 --- a/ivy_tests/test_ivy/test_misc/test_array.py +++ b/ivy_tests/test_ivy/test_misc/test_array.py @@ -2257,7 +2257,8 @@ def __ivy_array_function__(self, func, types, args, kwargs): return HANDLED_FUNCTIONS[func](*args, **kwargs) def implements(ivy_function): - """Register an __ivy_array_function__ implementation for MyArray objects.""" + """Register an __ivy_array_function__ implementation for MyArray + objects.""" def decorator(func): HANDLED_FUNCTIONS[ivy_function] = func @@ -2542,30 +2543,14 @@ def test_array_property_strides(dtype_x, backend_fw): @handle_test( fn_tree="functional.ivy.native_array", # dummy fn_tree - dtype_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("integer"), - min_dim_size=3, - max_dim_size=3, - min_num_dims=3, - max_num_dims=3, - num_arrays=2, - min_value=3.0, - max_value=10.0, - ), op=st.sampled_from( - ["!=", ">", "<", ">=", "<=", "*", "/", "%", "==", "&", "@", "**", "/"] + ["!=", ">", "<", ">=", "<=", "*", "/", "%", "==", "&", "@", "**", "/"], ), ) -def test_dunder_wrapping( - dtype_x, - backend_fw, - test_flags, - op, -): - _, data = dtype_x +def test_dunder_wrapping(backend_fw, op): ivy.set_backend(backend_fw) - x = ivy.to_native(ivy.array(data[0])) - y = ivy.array(data[1]) + x = ivy.native_array([1]) + y = ivy.array([1]) assert ivy.is_ivy_array(y) assert ivy.is_native_array(x) res = eval(f"x {op} y") diff --git a/ivy_tests/test_ivy/test_misc/test_assertions.py b/ivy_tests/test_ivy/test_misc/test_assertions.py index b6e4c948c1dea..d9530fcd6ebe6 100644 --- a/ivy_tests/test_ivy/test_misc/test_assertions.py +++ b/ivy_tests/test_ivy/test_misc/test_assertions.py @@ -23,7 +23,7 @@ check_shape, check_shapes_broadcastable, check_true, - check_unsorted_segment_min_valid_params, + check_unsorted_segment_valid_params, ) from ivy.utils.assertions import _check_jax_x64_flag import ivy @@ -64,7 +64,7 @@ def test_check_all(results): @pytest.mark.parametrize( - "args, fn, type, limit", + ("args", "fn", "type", "limit"), [ # INVALID CASES ((1, 2, 0), ivy.array, "all", [3]), @@ -198,7 +198,7 @@ def test_check_dimensions(x): @pytest.mark.parametrize( - "elem, list, inverse", + ("elem", "list", "inverse"), [ (1, [1, 2], False), ("a", [1, 2], False), @@ -240,7 +240,7 @@ def test_check_elem_in_list(elem, list, inverse): @pytest.mark.parametrize( - "x1, x2, inverse", + ("x1", "x2", "inverse"), [ (5, 10, False), (10, 10, False), @@ -283,7 +283,7 @@ def test_check_equal(x1, x2, inverse): @pytest.mark.parametrize( - "x, inverse", + ("x", "inverse"), [(None, False), ([], False), (None, True), ("abc", True)], ) def test_check_exists(x, inverse): @@ -356,7 +356,7 @@ def test_check_false(expression): @pytest.mark.parametrize( - "params, indices, axis, batch_dims", + ("params", "indices", "axis", "batch_dims"), [ # INVALID CASES (ivy.array([1, 2, 3]), ivy.array([1]), 2, 3), @@ -402,7 +402,7 @@ def test_check_gather_input_valid(params, indices, axis, batch_dims): @pytest.mark.parametrize( - "params, indices, batch_dims", + ("params", "indices", "batch_dims"), [ # INVALID CASES (ivy.array([1, 2, 3]), ivy.array([1]), 2), @@ -450,7 +450,7 @@ def test_check_gather_nd_input_valid(params, indices, batch_dims): @pytest.mark.parametrize( - "x1, x2, allow_equal", + ("x1", "x2", "allow_equal"), [ (5, 10, False), (10, 5, False), @@ -488,7 +488,7 @@ def test_check_greater(x1, x2, allow_equal): @pytest.mark.parametrize( - "var, data", + ("var", "data"), [ # INVALID CASES (ivy.array([1]), ivy.array([1, 2])), @@ -528,7 +528,7 @@ def test_check_inplace_sizes_valid(var, data): @pytest.mark.parametrize( - "x, allowed_types", + ("x", "allowed_types"), [(5.0, float), (ivy.array(5), type(ivy.array(8))), (5, float), ([5, 10], tuple)], ) def test_check_isinstance(x, allowed_types): @@ -602,7 +602,7 @@ def test_check_jax_x64_flag(dtype): @pytest.mark.parametrize( - "kernel_size, padding_size", + ("kernel_size", "padding_size"), [ # INVALID CASES (((2, 2), ((2, 2), (1, 1)))), @@ -642,7 +642,7 @@ def test_check_kernel_padding_size(kernel_size, padding_size): @pytest.mark.parametrize( - "x1, x2, allow_equal", + ("x1", "x2", "allow_equal"), [ (5, 10, False), (10, 5, False), @@ -680,7 +680,7 @@ def test_check_less(x1, x2, allow_equal): @pytest.mark.parametrize( - "x1, x2", + ("x1", "x2"), [ (ivy.array([1, 2, 3]), ivy.array([4, 5, 6])), (ivy.array([1.0, 2.0, 3.0]), ivy.array([4, 5, 6])), @@ -718,7 +718,7 @@ def test_check_same_dtype(x1, x2): @pytest.mark.parametrize( - "x1, x2", + ("x1", "x2"), [ (ivy.array([1, 2, 3]), ivy.array([[4, 5, 6], [2, 3, 1]])), (ivy.array([[1.0, 2.0], [3.0, 4.0]]), ivy.array([4, 5, 6])), @@ -757,7 +757,7 @@ def test_check_shape(x1, x2): @pytest.mark.parametrize( - "var, data", + ("var", "data"), [ # INVALID CASES ((2, 1), (1, 2, 1)), @@ -832,13 +832,12 @@ def test_check_true(expression): @pytest.mark.parametrize( - "data, segment_ids, num_segments", + ("data", "segment_ids", "num_segments"), [ # INVALID CASES (ivy.array([1, 2, 3]), ivy.array([0, 1, 0], dtype=ivy.int32), 2.0), (ivy.array([1, 2, 3]), ivy.array([0, 1, 0], dtype=ivy.int32), 0), (ivy.array([1, 2, 3]), ivy.array([0, 1, 0], dtype=ivy.int32), -2), - (ivy.array([1, 2, 3]), ivy.array([0, 1, 0], dtype=ivy.int32), 0), (ivy.array([1, 2, 3]), ivy.array([0.0, 1.0, 0.0], dtype=ivy.float16), 0), (ivy.array([1, 2]), ivy.array([0, 1, 0], dtype=ivy.int32), 0), (ivy.array([1, 2, 3]), ivy.array([0, 1], dtype=ivy.int32), 0), @@ -852,7 +851,7 @@ def test_check_true(expression): (ivy.array([1, 2, 3]), ivy.array([0, 1, 0], dtype=ivy.int32), ivy.array([2])), ], ) -def test_check_unsorted_segment_min_valid_params(data, segment_ids, num_segments): +def test_check_unsorted_segment_valid_params(data, segment_ids, num_segments): filename = "except_out.txt" orig_stdout = sys.stdout @@ -860,7 +859,7 @@ def test_check_unsorted_segment_min_valid_params(data, segment_ids, num_segments sys.stdout = f lines = "" try: - check_unsorted_segment_min_valid_params(data, segment_ids, num_segments) + check_unsorted_segment_valid_params(data, segment_ids, num_segments) local_vars = {**locals()} except Exception as e: local_vars = {**locals()} diff --git a/ivy_tests/test_ivy/test_misc/test_backend_utils/test_backend_handler.py b/ivy_tests/test_ivy/test_misc/test_backend_utils/test_backend_handler.py index a839509b8284a..16cee4a3dd4ef 100644 --- a/ivy_tests/test_ivy/test_misc/test_backend_utils/test_backend_handler.py +++ b/ivy_tests/test_ivy/test_misc/test_backend_utils/test_backend_handler.py @@ -88,32 +88,33 @@ def test_current_backend(backend, array_type): @pytest.mark.parametrize( - "middle_backend,end_backend", [(a, b) for a in backends for b in backends if a != b] + ("middle_backend", "end_backend"), + [(a, b) for a in backends for b in backends if (a != b and "mxnet" not in [a, b])], ) def test_dynamic_backend_all_combos(middle_backend, end_backend): # create an ivy array, container and native container a = ivy.array([1, 2, 3]) b = ivy.array([4, 5, 6]) ivy_cont = ivy.Container({"w": a, "b": b}) - nativ_cont = ivy.Container( - {"w": tf.Variable([1, 2, 3]), "b": tf.Variable([4, 5, 6])} - ) # clear the backend stack after initialization of inputs ivy.unset_backend() # set dynamic_backend to false for all objects ivy_cont.dynamic_backend = False - nativ_cont.dynamic_backend = False a.dynamic_backend = False b.dynamic_backend = False # set the middle backend ivy.set_backend(middle_backend, dynamic=True) - + var_cont = ivy.Container( + { + "w": ivy.gradients._variable(ivy.array([10, 20, 30])), + "b": ivy.gradients._variable(ivy.array([40, 50, 60])), + } + ) # set dynamic_backend to true for all objects ivy_cont.dynamic_backend = True - nativ_cont.dynamic_backend = True a.dynamic_backend = True b.dynamic_backend = True @@ -123,20 +124,14 @@ def test_dynamic_backend_all_combos(middle_backend, end_backend): # add the necessary asserts to check if the data # of the objects are in the correct format - assert isinstance(a.data, ivy.current_backend().NativeArray) - assert isinstance(ivy_cont["b"].data, ivy.current_backend().NativeArray) + assert isinstance(a.data, ivy.NativeArray) + assert isinstance(ivy_cont["b"].data, ivy.NativeArray) - if end_backend == "numpy": - assert isinstance(nativ_cont["b"].data, np.ndarray) - elif end_backend == "jax": - assert isinstance(nativ_cont["b"].data, jax.Array) - - if middle_backend not in ("jax", "numpy") and end_backend not in ("jax", "numpy"): + if {"numpy", "jax"}.intersection([middle_backend, end_backend]): # these frameworks don't support native variables - assert ivy.current_backend().gradients.is_variable(nativ_cont["b"].data) - + assert isinstance(var_cont["b"].data, ivy.NativeArray) else: - assert isinstance(nativ_cont["b"].data, ivy.current_backend().NativeArray) + assert ivy.gradients._is_variable(var_cont["b"]) def test_dynamic_backend_context_manager(): diff --git a/ivy_tests/test_ivy/test_misc/test_container.py b/ivy_tests/test_ivy/test_misc/test_container.py index ebdea48aa8e94..f9641e5e98cbe 100644 --- a/ivy_tests/test_ivy/test_misc/test_container.py +++ b/ivy_tests/test_ivy/test_misc/test_container.py @@ -1112,7 +1112,8 @@ def worker_fn(in_queue, out_queue, load_size, worker_id): "a": [ ivy.to_native(ivy.array([1.0, 2.0, 3.0], device=on_device)) * worker_id - ] * load_size + ] + * load_size } ) diff --git a/ivy_tests/test_ivy/test_misc/test_exceptions.py b/ivy_tests/test_ivy/test_misc/test_exceptions.py index d08a3c3fffa81..68520ed026efb 100644 --- a/ivy_tests/test_ivy/test_misc/test_exceptions.py +++ b/ivy_tests/test_ivy/test_misc/test_exceptions.py @@ -30,20 +30,18 @@ def test_trace_modes(backend_fw, trace_mode, show_func_wrapper): ivy.set_backend(backend_fw) filename = "excep_out.txt" orig_stdout = sys.stdout - f = open(filename, "w") - sys.stdout = f - ivy.set_exception_trace_mode(trace_mode) - ivy.set_show_func_wrapper_trace_mode(show_func_wrapper) - x = ivy.array([]) - y = ivy.array([1.0, 3.0, 4.0]) - lines = "" - try: - ivy.divide(x, y) - except Exception as e: - print(e) - sys.stdout = orig_stdout - f.close() - + with open(filename, "w") as f: + sys.stdout = f + ivy.set_exception_trace_mode(trace_mode) + ivy.set_show_func_wrapper_trace_mode(show_func_wrapper) + x = ivy.array([]) + y = ivy.array([1.0, 3.0, 4.0]) + lines = "" + try: + ivy.divide(x, y) + except Exception as e: + print(e) + sys.stdout = orig_stdout with open(filename) as f: lines += f.read() @@ -59,16 +57,16 @@ def test_trace_modes(backend_fw, trace_mode, show_func_wrapper): if backend_fw.current_backend_str() not in ["torch", "numpy"]: assert "/dist-packages" in lines - if (trace_mode == "ivy" or trace_mode == "frontend") and not show_func_wrapper: - assert "/func_wrapper.py" not in lines - assert "/dist-packages" not in lines - - if (trace_mode == "ivy" or trace_mode == "frontend") and show_func_wrapper: - if trace_mode == "ivy": - assert "/func_wrapper.py" in lines + if trace_mode in ["ivy", "frontend"]: + if not show_func_wrapper: + assert "/func_wrapper.py" not in lines assert "/dist-packages" not in lines - if trace_mode == "frontend": - assert "/ivy/functional/backends" not in lines + + if show_func_wrapper: + if trace_mode == "frontend": + assert "/ivy/functional/backends" not in lines + else: + assert "/func_wrapper.py" in lines assert "/dist-packages" not in lines with contextlib.suppress(FileNotFoundError): diff --git a/ivy_tests/test_ivy/test_misc/test_factorized_tensor/test_cp_tensor.py b/ivy_tests/test_ivy/test_misc/test_factorized_tensor/test_cp_tensor.py index 4d35c8f115716..526ce9761b152 100644 --- a/ivy_tests/test_ivy/test_misc/test_factorized_tensor/test_cp_tensor.py +++ b/ivy_tests/test_ivy/test_misc/test_factorized_tensor/test_cp_tensor.py @@ -5,7 +5,7 @@ @pytest.mark.parametrize( - "shape, rank", + ("shape", "rank"), [ ( (3, 4, 5), @@ -28,7 +28,7 @@ def test_cp_flip_sign(shape, rank): @pytest.mark.parametrize( - "shape, rank", + ("shape", "rank"), [ ( (8, 5, 6, 4), @@ -64,7 +64,7 @@ def test_cp_lstsq_grad(shape, rank): @pytest.mark.parametrize( - "shape, rank", + ("shape", "rank"), [ ( (5, 4, 6), @@ -78,7 +78,7 @@ def test_cp_mode_dot(shape, rank): # matrix for mode 1 matrix = ivy.random_uniform(shape=(7, shape[1])) # vec for mode 2 - vec = ivy.random_uniform(shape=(shape[2])) + vec = ivy.random_uniform(shape=shape[2]) # Test cp_mode_dot with matrix res = ivy.CPTensor.cp_mode_dot(cp_ten, matrix, mode=1, copy=True) @@ -101,7 +101,7 @@ def test_cp_mode_dot(shape, rank): @pytest.mark.parametrize( - "shape, rank, tol", + ("shape", "rank", "tol"), [ ( (8, 5, 6, 4), @@ -123,7 +123,7 @@ def test_cp_norm(shape, rank, tol): @pytest.mark.parametrize( - "shape, rank", + ("shape", "rank"), [ ( (3, 4, 5), @@ -145,7 +145,7 @@ def test_cp_normalize(shape, rank): @pytest.mark.parametrize( - "shapeU1, shapeU2, shapeU3, shapeU4, true_res, columns, rows", + ("shapeU1", "shapeU2", "shapeU3", "shapeU4", "true_res", "columns", "rows"), [ ( (3, 3), @@ -201,7 +201,7 @@ def test_cp_to_tensor(shapeU1, shapeU2, shapeU3, shapeU4, true_res, columns, row matrices.insert(i, U_i) -@pytest.mark.parametrize("shape, expected", [((2, 2), [[-2, -2], [6, 10]])]) +@pytest.mark.parametrize(("shape", "expected"), [((2, 2), [[-2, -2], [6, 10]])]) def test_cp_to_tensor_with_weights(shape, expected): A = ivy.reshape(ivy.arange(1, 5, dtype=float), shape) B = ivy.reshape(ivy.arange(5, 9, dtype=float), shape) @@ -222,7 +222,7 @@ def test_cp_to_tensor_with_weights(shape, expected): @pytest.mark.parametrize( - "shapeU1, shapeU2, shapeU3, shapeU4", [((3, 3), (4, 3), (2, 3), (2, 3))] + ("shapeU1", "shapeU2", "shapeU3", "shapeU4"), [((3, 3), (4, 3), (2, 3), (2, 3))] ) def test_cp_to_unfolded(shapeU1, shapeU2, shapeU3, shapeU4): U1 = ivy.reshape(ivy.arange(1, 10, dtype=float), shapeU1) @@ -243,7 +243,7 @@ def test_cp_to_unfolded(shapeU1, shapeU2, shapeU3, shapeU4): @pytest.mark.parametrize( - "shapeU1, shapeU2, shapeU3, shapeU4", [((3, 3), (4, 3), (2, 3), (2, 3))] + ("shapeU1", "shapeU2", "shapeU3", "shapeU4"), [((3, 3), (4, 3), (2, 3), (2, 3))] ) def test_cp_to_vec(shapeU1, shapeU2, shapeU3, shapeU4): """Test for cp_to_vec.""" @@ -267,7 +267,7 @@ def test_cp_to_vec(shapeU1, shapeU2, shapeU3, shapeU4): @pytest.mark.parametrize( - "shape, rank", + ("shape", "rank"), [ ( (10, 10, 10, 4), @@ -307,7 +307,7 @@ def test_validate_cp_rank(size): @pytest.mark.parametrize( - "true_shape, true_rank", + ("true_shape", "true_rank"), [ ( (3, 4, 5), diff --git a/ivy_tests/test_ivy/test_misc/test_factorized_tensor/test_parafac2_tensor.py b/ivy_tests/test_ivy/test_misc/test_factorized_tensor/test_parafac2_tensor.py index 11769f5719785..8992e92efa2f6 100644 --- a/ivy_tests/test_ivy/test_misc/test_factorized_tensor/test_parafac2_tensor.py +++ b/ivy_tests/test_ivy/test_misc/test_factorized_tensor/test_parafac2_tensor.py @@ -5,7 +5,7 @@ @pytest.mark.parametrize( - "weights, factors, projections, true_res", + ("weights", "factors", "projections", "true_res"), [ ( (2, 3), @@ -29,7 +29,7 @@ def test_apply_parafac2_projections(weights, factors, projections, true_res): @pytest.mark.parametrize( - "shape, rank", + ("shape", "rank"), [ ( [(4, 5)] * 3, @@ -54,7 +54,7 @@ def test_parafac2_normalise(shape, rank): @pytest.mark.parametrize( - "weights, factors, projections, true_res", + ("weights", "factors", "projections", "true_res"), [ ( (2, 3), @@ -82,7 +82,7 @@ def test_parafac2_to_slices(weights, factors, projections, true_res): @pytest.mark.parametrize( - "weights, factors, projections, true_res", + ("weights", "factors", "projections", "true_res"), [ ( (2, 3), @@ -98,12 +98,11 @@ def test_parafac2_to_tensor(weights, factors, projections, true_res): projections = [ivy.array(p) for p in projections] true_res = ivy.array(true_res) res = ivy.Parafac2Tensor.parafac2_to_tensor((weights, factors, projections)) - (true_res, res) assert np.allclose(res, true_res) @pytest.mark.parametrize( - "shape, rank", + ("shape", "rank"), [ ( [(4, 5)] * 3, @@ -122,7 +121,7 @@ def test_parafac2_to_unfolded(shape, rank): @pytest.mark.parametrize( - "shape, rank", + ("shape", "rank"), [ ( [(4, 5)] * 3, @@ -140,7 +139,7 @@ def test_parafac2_to_vec(shape, rank): @pytest.mark.parametrize( - "true_shape, true_rank", + ("true_shape", "true_rank"), [ ( [(4, 5)] * 3, diff --git a/ivy_tests/test_ivy/test_misc/test_factorized_tensor/test_tr_tensor.py b/ivy_tests/test_ivy/test_misc/test_factorized_tensor/test_tr_tensor.py index e48dca6ccb866..d7923f83e6cf6 100644 --- a/ivy_tests/test_ivy/test_misc/test_factorized_tensor/test_tr_tensor.py +++ b/ivy_tests/test_ivy/test_misc/test_factorized_tensor/test_tr_tensor.py @@ -5,7 +5,7 @@ @pytest.mark.parametrize( - "shape1, shape2, shape3", + ("shape1", "shape2", "shape3"), [ ( (2, 4, 3), @@ -30,7 +30,7 @@ def test_tr_to_tensor(shape1, shape2, shape3): @pytest.mark.parametrize( - "rank1, rank2", + ("rank1", "rank2"), [((2, 3, 4, 2), (2, 3, 4, 2, 3))], ) def test_validate_tr_rank(rank1, rank2): @@ -60,7 +60,7 @@ def test_validate_tr_rank(rank1, rank2): @pytest.mark.parametrize( - "true_shape, true_rank", + ("true_shape", "true_rank"), [ ( (6, 4, 5), diff --git a/ivy_tests/test_ivy/test_misc/test_factorized_tensor/test_tt_tensor.py b/ivy_tests/test_ivy/test_misc/test_factorized_tensor/test_tt_tensor.py index d82b9b0bdfc6d..273e697b927de 100644 --- a/ivy_tests/test_ivy/test_misc/test_factorized_tensor/test_tt_tensor.py +++ b/ivy_tests/test_ivy/test_misc/test_factorized_tensor/test_tt_tensor.py @@ -42,7 +42,7 @@ def test_pad_tt_rank(n_pad): @pytest.mark.parametrize( - "shape, rank", + ("shape", "rank"), [((4, 5, 4, 8, 5), (1, 3, 2, 2, 4, 1))], ) def test_tt_n_param(shape, rank): @@ -53,7 +53,7 @@ def test_tt_n_param(shape, rank): @pytest.mark.parametrize( - "n1, n2, n3, shape1, shape2, shape3", + ("n1", "n2", "n3", "shape1", "shape2", "shape3"), [(3, 4, 2, (1, 3, 2), (2, 4, 2), (2, 2, 1))], ) def test_tt_to_tensor(n1, n2, n3, shape1, shape2, shape3): @@ -93,7 +93,7 @@ def test_tt_to_tensor(n1, n2, n3, shape1, shape2, shape3): @pytest.mark.parametrize( "coef", - [((0.2))], + [(0.2)], ) def test_validate_tt_rank(coef): tensor_shape = tuple(ivy.random.randint(5, 10, shape=(4,))) @@ -109,7 +109,7 @@ def test_validate_tt_rank(coef): @pytest.mark.parametrize( - "true_shape, true_rank", + ("true_shape", "true_rank"), [ ( (3, 4, 5), diff --git a/ivy_tests/test_ivy/test_misc/test_factorized_tensor/test_tucker_tensor.py b/ivy_tests/test_ivy/test_misc/test_factorized_tensor/test_tucker_tensor.py index 3601d740e4b51..bb03df0116781 100644 --- a/ivy_tests/test_ivy/test_misc/test_factorized_tensor/test_tucker_tensor.py +++ b/ivy_tests/test_ivy/test_misc/test_factorized_tensor/test_tucker_tensor.py @@ -4,7 +4,7 @@ import pytest -@pytest.mark.parametrize("shape, rank", [((5, 4, 6), (3, 2, 3))]) +@pytest.mark.parametrize(("shape", "rank"), [((5, 4, 6), (3, 2, 3))]) def test_n_param_tucker(shape, rank): tucker_tensor = ivy.random_tucker(shape, rank) true_n_param = ivy.prod(ivy.shape(tucker_tensor[0])) + ivy.sum( @@ -14,7 +14,7 @@ def test_n_param_tucker(shape, rank): assert np.allclose(n_param, true_n_param) -@pytest.mark.parametrize("shape, rank", [((3, 4, 5), 4)]) +@pytest.mark.parametrize(("shape", "rank"), [((3, 4, 5), 4)]) def test_tucker_copy(shape, rank): tucker_tensor = ivy.random_tucker(shape, rank) core, factors = tucker_tensor @@ -28,14 +28,14 @@ def test_tucker_copy(shape, rank): ) -@pytest.mark.parametrize("shape, ranks", [((5, 4, 6), (3, 2, 3))]) +@pytest.mark.parametrize(("shape", "ranks"), [((5, 4, 6), (3, 2, 3))]) def test_tucker_mode_dot(shape, ranks): tucker_ten = ivy.random_tucker(shape, ranks, full=False) full_tensor = ivy.TuckerTensor.tucker_to_tensor(tucker_ten) # matrix for mode 1 matrix = ivy.random_uniform(shape=(7, shape[1])) # vec for mode 2 - vec = ivy.random_uniform(shape=(shape[2])) + vec = ivy.random_uniform(shape=shape[2]) # Test tucker_mode_dot with matrix res = ivy.TuckerTensor.tucker_mode_dot(tucker_ten, matrix, mode=1, copy=True) @@ -57,7 +57,7 @@ def test_tucker_mode_dot(shape, ranks): assert np.allclose(true_res, res) -@pytest.mark.parametrize("shape, rank", [((3, 4, 5), (3, 2, 4))]) +@pytest.mark.parametrize(("shape", "rank"), [((3, 4, 5), (3, 2, 4))]) def test_tucker_normalize(shape, rank): tucker_ten = ivy.random_tucker(shape, rank) core, factors = ivy.TuckerTensor.tucker_normalize(tucker_ten) @@ -71,7 +71,7 @@ def test_tucker_normalize(shape, rank): @pytest.mark.parametrize( - "X, ranks, true_res", + ("X", "ranks", "true_res"), [ ( [ @@ -107,7 +107,7 @@ def test_tucker_to_tensor(X, ranks, true_res): assert np.allclose(true_res, res) -@pytest.mark.parametrize("shape, ranks", [((4, 3, 5, 2), (2, 2, 3, 4))]) +@pytest.mark.parametrize(("shape", "ranks"), [((4, 3, 5, 2), (2, 2, 3, 4))]) def test_tucker_to_unfolded(shape, ranks): G = ivy.random_uniform(shape=shape) U = [ivy.random_uniform(shape=(ranks[i], G.shape[i])) for i in range(4)] @@ -126,7 +126,7 @@ def test_tucker_to_unfolded(shape, ranks): ) -@pytest.mark.parametrize("shape, ranks", [((4, 3, 5, 2), (2, 2, 3, 4))]) +@pytest.mark.parametrize(("shape", "ranks"), [((4, 3, 5, 2), (2, 2, 3, 4))]) def test_tucker_to_vec(shape, ranks): G = ivy.random_uniform(shape=shape) ranks = [2, 2, 3, 4] @@ -191,7 +191,7 @@ def test_validate_tucker_rank(tol): # These tests have been adapted from TensorLy # https://github.com/tensorly/tensorly/blob/main/tensorly/tests/test_tucker_tensor.py -@pytest.mark.parametrize("true_shape, true_rank", [((3, 4, 5), (3, 2, 4))]) +@pytest.mark.parametrize(("true_shape", "true_rank"), [((3, 4, 5), (3, 2, 4))]) def test_validate_tucker_tensor(true_shape, true_rank): core, factors = ivy.random_tucker(true_shape, true_rank) diff --git a/ivy_tests/test_ivy/test_misc/test_handle_exceptions.py b/ivy_tests/test_ivy/test_misc/test_handle_exceptions.py index 79cfe53b1a547..2c379e20e8b51 100644 --- a/ivy_tests/test_ivy/test_misc/test_handle_exceptions.py +++ b/ivy_tests/test_ivy/test_misc/test_handle_exceptions.py @@ -30,7 +30,7 @@ def func(e): @pytest.mark.parametrize( "e", - ( + [ IvyError, IvyNotImplementedException, IvyBroadcastShapeError, @@ -43,7 +43,7 @@ def func(e): IvyDeviceError, IvyInvalidBackendException, IvyDtypePromotionError, - ), + ], ) def test_ivy_errors_raising(e): with pytest.raises(e): @@ -55,7 +55,7 @@ def test_no_exception(): @pytest.mark.parametrize( - "e, to_be_raised", + ("e", "to_be_raised"), _non_ivy_exceptions_mapping.items(), ) def test_non_ivy_errors_mapping(e, to_be_raised): diff --git a/ivy_tests/test_ivy/test_misc/test_inspection.py b/ivy_tests/test_ivy/test_misc/test_inspection.py index a218e77e09928..4ea8449a386c7 100644 --- a/ivy_tests/test_ivy/test_misc/test_inspection.py +++ b/ivy_tests/test_ivy/test_misc/test_inspection.py @@ -17,7 +17,7 @@ def _fn0(xs: Optional[List[ivy.Array]] = None): def _fn1( a: Union[ivy.Array, ivy.NativeArray], b: str = "hello", - c: int = None, + c: Optional[int] = None, d: ivy.NativeArray = None, ): return a, b, c, d @@ -26,7 +26,7 @@ def _fn1( def _fn2( a: Tuple[Union[ivy.Array, ivy.NativeArray, ivy.Container]], bs: Tuple[str] = ("a", "b", "c"), - cs: Dict[str, ivy.Array] = None, + cs: Optional[Dict[str, ivy.Array]] = None, ): return a, bs, cs diff --git a/ivy_tests/test_ivy/test_misc/test_shape.py b/ivy_tests/test_ivy/test_misc/test_shape.py index 8c6a2b730339f..9ab019cb59275 100644 --- a/ivy_tests/test_ivy/test_misc/test_shape.py +++ b/ivy_tests/test_ivy/test_misc/test_shape.py @@ -1,24 +1,25 @@ from hypothesis import assume, strategies as st import numpy as np +import ivy import ivy_tests.test_ivy.helpers as helpers from ivy_tests.test_ivy.helpers import handle_method +CLASS_TREE = "ivy.Shape" +DUMMY_DTYPE = ["int32"] + + @handle_method( + init_tree=CLASS_TREE, method_tree="Shape.__add__", - dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("numeric"), - num_arrays=2, - large_abs_safety_factor=2.5, - small_abs_safety_factor=2.5, - safety_factor_scale="log", - shared_dtype=True, - ), + shape_1=helpers.get_shape(), + shape_2=helpers.get_shape(), ) def test_shape__add__( - dtype_and_x, + shape_1, + shape_2, method_name, class_name, ground_truth_backend, @@ -27,17 +28,16 @@ def test_shape__add__( method_flags, on_device, ): - dtype, x = dtype_and_x helpers.test_method( on_device=on_device, ground_truth_backend=ground_truth_backend, backend_to_test=backend_fw, init_flags=init_flags, method_flags=method_flags, - init_all_as_kwargs_np={"shape": x[0]}, - init_input_dtypes=dtype, - method_input_dtypes=dtype, - method_all_as_kwargs_np={"other": x[1]}, + init_all_as_kwargs_np={"shape_tup": shape_1}, + init_input_dtypes=DUMMY_DTYPE, + method_input_dtypes=DUMMY_DTYPE, + method_all_as_kwargs_np={"other": shape_2}, class_name=class_name, method_name=method_name, ) @@ -113,15 +113,14 @@ def test_shape__eq__( @handle_method( + init_tree=CLASS_TREE, method_tree="Shape.__ge__", - dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("numeric"), - num_arrays=2, - shared_dtype=True, - ), + shape_1=helpers.get_shape(), + shape_2=helpers.get_shape(), ) def test_shape__ge__( - dtype_and_x, + shape_1, + shape_2, method_name, class_name, ground_truth_backend, @@ -130,17 +129,16 @@ def test_shape__ge__( method_flags, on_device, ): - dtype, x = dtype_and_x helpers.test_method( on_device=on_device, ground_truth_backend=ground_truth_backend, backend_to_test=backend_fw, init_flags=init_flags, method_flags=method_flags, - init_all_as_kwargs_np={"shape": x[0]}, - init_input_dtypes=dtype, - method_input_dtypes=dtype, - method_all_as_kwargs_np={"other": x[1]}, + init_all_as_kwargs_np={"shape_tup": shape_1}, + init_input_dtypes=DUMMY_DTYPE, + method_input_dtypes=DUMMY_DTYPE, + method_all_as_kwargs_np={"other": shape_2}, class_name=class_name, method_name=method_name, ) @@ -424,18 +422,14 @@ def test_shape__mod__( @handle_method( + init_tree=CLASS_TREE, method_tree="Shape.__mul__", - dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("numeric"), - num_arrays=2, - large_abs_safety_factor=2.5, - small_abs_safety_factor=2.5, - safety_factor_scale="log", - shared_dtype=True, - ), + shape=helpers.get_shape(), + other=st.integers(min_value=1, max_value=10), ) def test_shape__mul__( - dtype_and_x, + shape, + other, method_name, class_name, backend_fw, @@ -444,34 +438,30 @@ def test_shape__mul__( method_flags, on_device, ): - dtype, x = dtype_and_x helpers.test_method( on_device=on_device, ground_truth_backend=ground_truth_backend, + backend_to_test=backend_fw, init_flags=init_flags, method_flags=method_flags, - init_all_as_kwargs_np={"data": x[0]}, - init_input_dtypes=dtype, - method_input_dtypes=dtype, - method_all_as_kwargs_np={"other": x[1]}, + init_all_as_kwargs_np={"shape_tup": shape}, + init_input_dtypes=DUMMY_DTYPE, + method_input_dtypes=DUMMY_DTYPE, + method_all_as_kwargs_np={"other": other}, class_name=class_name, method_name=method_name, ) @handle_method( + init_tree=CLASS_TREE, method_tree="Shape.__radd__", - dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("numeric"), - num_arrays=2, - large_abs_safety_factor=2.5, - small_abs_safety_factor=2.5, - safety_factor_scale="log", - shared_dtype=True, - ), + shape_1=helpers.get_shape(), + shape_2=helpers.get_shape(), ) def test_shape__radd__( - dtype_and_x, + shape_1, + shape_2, method_name, class_name, backend_fw, @@ -480,17 +470,16 @@ def test_shape__radd__( method_flags, on_device, ): - dtype, x = dtype_and_x helpers.test_method( on_device=on_device, ground_truth_backend=ground_truth_backend, backend_to_test=backend_fw, init_flags=init_flags, method_flags=method_flags, - init_all_as_kwargs_np={"shape": x[0]}, - init_input_dtypes=dtype, - method_input_dtypes=dtype, - method_all_as_kwargs_np={"other": x[1]}, + init_all_as_kwargs_np={"shape_tup": shape_1}, + init_input_dtypes=DUMMY_DTYPE, + method_input_dtypes=DUMMY_DTYPE, + method_all_as_kwargs_np={"other": shape_2}, class_name=class_name, method_name=method_name, ) @@ -573,35 +562,32 @@ def test_shape__rmod__( @handle_method( + init_tree=CLASS_TREE, method_tree="Shape.__rmul__", - dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("numeric"), - num_arrays=2, - large_abs_safety_factor=2.5, - small_abs_safety_factor=2.5, - safety_factor_scale="log", - shared_dtype=True, - ), + shape=helpers.get_shape(), + other=st.integers(min_value=1, max_value=10), ) def test_shape__rmul__( - dtype_and_x, + shape, + other, method_name, class_name, ground_truth_backend, + backend_fw, init_flags, method_flags, on_device, ): - dtype, x = dtype_and_x helpers.test_method( on_device=on_device, ground_truth_backend=ground_truth_backend, + backend_to_test=backend_fw, init_flags=init_flags, method_flags=method_flags, - init_all_as_kwargs_np={"data": x[0]}, - init_input_dtypes=dtype, - method_input_dtypes=dtype, - method_all_as_kwargs_np={"other": x[1]}, + init_all_as_kwargs_np={"shape_tup": shape}, + init_input_dtypes=DUMMY_DTYPE, + method_input_dtypes=DUMMY_DTYPE, + method_all_as_kwargs_np={"other": other}, class_name=class_name, method_name=method_name, ) @@ -679,3 +665,13 @@ def test_shape__sub__( class_name=class_name, method_name=method_name, ) + + +def test_shape_in_conditions(): + shape = ivy.Shape((1, 2)) + condition_is_true = True if shape else False + assert condition_is_true + + shape = ivy.Shape(()) + condition_is_true = True if shape else False + assert not condition_is_true diff --git a/ivy_tests/test_ivy/test_stateful/test_activations.py b/ivy_tests/test_ivy/test_stateful/test_activations.py index 638aaee6fbe80..6a1892b165c6f 100644 --- a/ivy_tests/test_ivy/test_stateful/test_activations.py +++ b/ivy_tests/test_ivy/test_stateful/test_activations.py @@ -32,12 +32,14 @@ def test_elu( class_name, method_name, ground_truth_backend, + backend_fw, init_flags, method_flags, on_device, ): input_dtype, x = dtype_and_x helpers.test_method( + backend_to_test=backend_fw, ground_truth_backend=ground_truth_backend, init_flags=init_flags, method_flags=method_flags, @@ -167,12 +169,14 @@ def test_hardswish( class_name, method_name, ground_truth_backend, + backend_fw, init_flags, method_flags, on_device, ): input_dtype, x = dtype_and_x helpers.test_method( + backend_to_test=backend_fw, ground_truth_backend=ground_truth_backend, init_flags=init_flags, method_flags=method_flags, @@ -307,12 +311,14 @@ def test_logit( class_name, method_name, ground_truth_backend, + backend_fw, init_flags, method_flags, on_device, ): input_dtype, x = dtype_and_x helpers.test_method( + backend_to_test=backend_fw, ground_truth_backend=ground_truth_backend, init_flags=init_flags, method_flags=method_flags, @@ -351,12 +357,14 @@ def test_logsigmoid( class_name, method_name, ground_truth_backend, + backend_fw, init_flags, method_flags, on_device, ): input_dtype, x = dtype_and_x helpers.test_method( + backend_to_test=backend_fw, ground_truth_backend=ground_truth_backend, init_flags=init_flags, method_flags=method_flags, @@ -437,12 +445,14 @@ def test_prelu( class_name, method_name, ground_truth_backend, + backend_fw, init_flags, method_flags, on_device, ): input_dtype, x = dtype_and_x helpers.test_method( + backend_to_test=backend_fw, ground_truth_backend=ground_truth_backend, init_flags=init_flags, method_flags=method_flags, @@ -521,12 +531,14 @@ def test_relu6( class_name, method_name, ground_truth_backend, + backend_fw, init_flags, method_flags, on_device, ): input_dtype, x = dtype_and_x helpers.test_method( + backend_to_test=backend_fw, ground_truth_backend=ground_truth_backend, init_flags=init_flags, method_flags=method_flags, @@ -563,12 +575,14 @@ def test_selu( class_name, method_name, ground_truth_backend, + backend_fw, init_flags, method_flags, on_device, ): input_dtype, x = dtype_and_x helpers.test_method( + backend_to_test=backend_fw, ground_truth_backend=ground_truth_backend, init_flags=init_flags, method_flags=method_flags, @@ -605,12 +619,14 @@ def test_sigmoid( class_name, method_name, ground_truth_backend, + backend_fw, init_flags, method_flags, on_device, ): input_dtype, x = dtype_and_x helpers.test_method( + backend_to_test=backend_fw, ground_truth_backend=ground_truth_backend, init_flags=init_flags, method_flags=method_flags, @@ -781,12 +797,14 @@ def test_tanh( class_name, method_name, ground_truth_backend, + backend_fw, init_flags, method_flags, on_device, ): input_dtype, x = dtype_and_x helpers.test_method( + backend_to_test=backend_fw, ground_truth_backend=ground_truth_backend, init_flags=init_flags, method_flags=method_flags, diff --git a/ivy_tests/test_ivy/test_stateful/test_layers.py b/ivy_tests/test_ivy/test_stateful/test_layers.py index 0a11d31645424..f3ec09355af54 100644 --- a/ivy_tests/test_ivy/test_stateful/test_layers.py +++ b/ivy_tests/test_ivy/test_stateful/test_layers.py @@ -23,6 +23,9 @@ all_constant_initializers = (ivy.Zeros, ivy.Ones) all_gaussian_initializers = (ivy.KaimingNormal, ivy.Siren) all_uniform_initializers = (ivy.GlorotUniform, ivy.FirstLayerSiren, ivy.Siren) +all_initializers = ( + all_constant_initializers + all_uniform_initializers + all_gaussian_initializers +) # --- Helpers --- # @@ -275,7 +278,8 @@ def array_for_adaptive( ) ) output_size = size[0] if num_out_size == 1 else size - return dtypes, arrays, output_size + data_format = draw(st.sampled_from(["NCHW", "NHWC"])) + return dtypes, arrays, output_size, data_format # --- Main --- # @@ -298,7 +302,7 @@ def test_adaptive_avg_pool1d_layer( method_flags, backend_fw, ): - input_dtype, x, out_size = dt_arr_size + input_dtype, x, out_size, _ = dt_arr_size helpers.test_method( ground_truth_backend=ground_truth_backend, backend_to_test=backend_fw, @@ -334,7 +338,7 @@ def test_adaptive_avg_pool2d_layer( method_flags, backend_fw, ): - input_dtype, x, out_size = dt_arr_size + input_dtype, x, out_size, data_format = dt_arr_size helpers.test_method( ground_truth_backend=ground_truth_backend, backend_to_test=backend_fw, @@ -342,6 +346,7 @@ def test_adaptive_avg_pool2d_layer( method_flags=method_flags, init_all_as_kwargs_np={ "output_size": out_size, + "data_format": data_format, "device": on_device, "dtype": input_dtype[0], }, @@ -1048,7 +1053,7 @@ def test_dropout_layer( test_values=False, on_device=on_device, ) - ret = helpers.flatten_and_to_np(ret=ret) + ret = helpers.flatten_and_to_np(ret=ret, backend=backend_fw) for u in ret: # cardinality test assert u.shape == x[0].shape @@ -1571,117 +1576,115 @@ def test_multi_head_attention_layer( ), with_v=st.booleans(), seq_v=st.booleans(), - dtype=helpers.get_dtypes("float", full=False, none=True), + dtype=helpers.get_dtypes("float", full=False), ) def test_sequential_layer( - bs_c_target, - with_v, - seq_v, - dtype, - method_flags, - on_device, - trace_graph, - method_name, - class_name, + bs_c_target, with_v, seq_v, dtype, method_flags, on_device, backend_fw ): - dtype = dtype[0] - # smoke test - batch_shape, channels, target = bs_c_target - tolerance_dict = { - "bfloat16": 1e-2, - "float16": 1e-2, - "float32": 1e-5, - "float64": 1e-5, - None: 1e-5, - } - if method_flags.as_variable[0]: - x = _variable( - ivy.asarray( + with ivy.utils.backend.ContextManager(backend_fw): + dtype = dtype[0] + if backend_fw == "torch": + assume("float16" not in dtype) + if backend_fw == "paddle": + assume(dtype != "float16") + # smoke test + batch_shape, channels, target = bs_c_target + tolerance_dict = { + "bfloat16": 1e-1, + "float16": 1e-2, + "float32": 1e-2, + "float64": 1e-2, + } + if method_flags.as_variable[0]: + x = _variable( + ivy.asarray( + ivy.linspace( + ivy.zeros(batch_shape), ivy.ones(batch_shape), channels + ), + dtype=dtype, + ) + ) + else: + x = ivy.asarray( ivy.linspace(ivy.zeros(batch_shape), ivy.ones(batch_shape), channels), dtype=dtype, ) - ) - else: - x = ivy.asarray( - ivy.linspace(ivy.zeros(batch_shape), ivy.ones(batch_shape), channels), - dtype=dtype, - ) - if with_v: - np.random.seed(0) - wlim = (6 / (channels + channels)) ** 0.5 - v = Container( - { - "submodules": { - "v0": { - "w": _variable( - ivy.array( - np.random.uniform(-wlim, wlim, (channels, channels)), - dtype=dtype, - device=on_device, - ) - ), - "b": _variable( - ivy.zeros([channels], device=on_device, dtype=dtype) - ), - }, - "v2": { - "w": _variable( - ivy.array( - np.random.uniform(-wlim, wlim, (channels, channels)), - dtype=dtype, - device=on_device, - ) - ), - "b": _variable( - ivy.zeros([channels], device=on_device, dtype=dtype) - ), - }, + if with_v: + np.random.seed(0) + wlim = (6 / (channels + channels)) ** 0.5 + v = Container( + { + "submodules": { + "v0": { + "w": _variable( + ivy.array( + np.random.uniform( + -wlim, wlim, (channels, channels) + ), + dtype=dtype, + device=on_device, + ) + ), + "b": _variable( + ivy.zeros([channels], device=on_device, dtype=dtype) + ), + }, + "v2": { + "w": _variable( + ivy.array( + np.random.uniform( + -wlim, wlim, (channels, channels) + ), + dtype=dtype, + device=on_device, + ) + ), + "b": _variable( + ivy.zeros([channels], device=on_device, dtype=dtype) + ), + }, + } } - } - ) - else: - v = None - if seq_v: - seq = ivy.Sequential( - ivy.Linear(channels, channels, device=on_device, dtype=dtype), - ivy.Dropout(0.0), - ivy.Linear(channels, channels, device=on_device, dtype=dtype), - device=on_device, - v=v if with_v else None, - dtype=dtype, - ) - else: - seq = ivy.Sequential( - ivy.Linear( - channels, - channels, + ) + else: + v = None + if seq_v: + seq = ivy.Sequential( + ivy.Linear(channels, channels, device=on_device, dtype=dtype), + ivy.Dropout(0.0, dtype=dtype), + ivy.Linear(channels, channels, device=on_device, dtype=dtype), device=on_device, - v=v["submodules"]["v0"] if with_v else None, + v=v if with_v else None, dtype=dtype, - ), - ivy.Dropout(0.0), - ivy.Linear( - channels, - channels, + ) + else: + seq = ivy.Sequential( + ivy.Linear( + channels, + channels, + device=on_device, + v=v["submodules"]["v0"] if with_v else None, + dtype=dtype, + ), + ivy.Dropout(0.0, dtype=dtype), + ivy.Linear( + channels, + channels, + device=on_device, + v=v["submodules"]["v2"] if with_v else None, + dtype=dtype, + ), device=on_device, - v=v["submodules"]["v2"] if with_v else None, dtype=dtype, - ), - device=on_device, + ) + ret = seq(x) + # type test + assert ivy.is_ivy_array(ret) + # cardinality test + assert ret.shape == ivy.Shape(batch_shape + [channels]) + # value test + if not with_v: + return + assert np.allclose( + ivy.to_numpy(seq(x)), np.array(target), rtol=tolerance_dict[dtype] ) - ret = seq(x) - # type test - assert ivy.is_ivy_array(ret) - # cardinality test - assert ret.shape == ivy.Shape(batch_shape + [channels]) - # value test - if not with_v: - return - assert np.allclose( - ivy.to_numpy(seq(x)), np.array(target), rtol=tolerance_dict[dtype] - ) - - -all_initializers = ( - all_constant_initializers + all_uniform_initializers + all_gaussian_initializers -) diff --git a/ivy_tests/test_ivy/test_stateful/test_losses.py b/ivy_tests/test_ivy/test_stateful/test_losses.py index c8efbe04c1295..2849ab86f7989 100644 --- a/ivy_tests/test_ivy/test_stateful/test_losses.py +++ b/ivy_tests/test_ivy/test_stateful/test_losses.py @@ -58,6 +58,7 @@ def test_binary_cross_entropy_loss( dtype_and_true, dtype_and_pred, dtype_and_pos, + backend_fw, from_logits, reduction, axis, @@ -75,6 +76,7 @@ def test_binary_cross_entropy_loss( if from_logits: helpers.test_method( + backend_to_test=backend_fw, ground_truth_backend=ground_truth_backend, init_flags=init_flags, method_flags=method_flags, @@ -98,6 +100,7 @@ def test_binary_cross_entropy_loss( ) else: helpers.test_method( + backend_to_test=backend_fw, ground_truth_backend=ground_truth_backend, init_flags=init_flags, method_flags=method_flags, @@ -158,6 +161,7 @@ def test_cross_entropy_loss( axis, reduction, class_name, + backend_fw, method_name, ground_truth_backend, init_flags, @@ -167,6 +171,7 @@ def test_cross_entropy_loss( targets_dtype, targets = dtype_and_targets log_input_dtype, log_input = dtype_and_log_input helpers.test_method( + backend_to_test=backend_fw, ground_truth_backend=ground_truth_backend, init_flags=init_flags, method_flags=method_flags, @@ -224,6 +229,7 @@ def test_log_poisson_loss( axis, reduction, class_name, + backend_fw, method_name, ground_truth_backend, init_flags, @@ -233,6 +239,7 @@ def test_log_poisson_loss( targets_dtype, targets = dtype_and_targets log_input_dtype, log_input = dtype_and_log_input helpers.test_method( + backend_to_test=backend_fw, ground_truth_backend=ground_truth_backend, init_flags=init_flags, method_flags=method_flags, diff --git a/ivy_tests/test_ivy/test_stateful/test_modules.py b/ivy_tests/test_ivy/test_stateful/test_modules.py index 1a361cba5fa42..45dcb1ae7c6e4 100644 --- a/ivy_tests/test_ivy/test_stateful/test_modules.py +++ b/ivy_tests/test_ivy/test_stateful/test_modules.py @@ -134,7 +134,7 @@ def _forward(self, x): class ModuleWithBuffer(ivy.Module): def __init__(self, *args, **kwargs): - pass + super().__init__() def _forward(self, *args, **kwargs): pass @@ -148,193 +148,19 @@ def _forward(): pass -@given( - buffer=st.just( - [ - { - "var1": [ - ivy.ones((1, 2)), - ] - } - ] - ) -) +@given(buffer=st.just({"var1": np.ones((1, 2))})) def test_get_buffers(buffer, backend_fw): with ivy.utils.backend.ContextManager(backend_fw): module = ModuleWithBuffer() - buffers = {} - for item in buffer: - buffers.update(item) - for key in item: - module.register_buffer(key, item[key]) + buffers = ivy.Container() + for name, value in buffer.items(): + value = ivy.array(value) + buffers[name] = value + module.register_buffer(name, value) assert module.buffers == buffers -# check submod returns -@given( - batch_shape=helpers.get_shape( - min_num_dims=2, max_num_dims=2, min_dim_size=1, max_dim_size=2 - ), - input_channels=st.integers(min_value=2, max_value=5), - output_channels=st.integers(min_value=2, max_value=5), -) -def test_module_check_submod_rets( - batch_shape, input_channels, output_channels, on_device, backend_fw -): - # smoke test - if backend_fw == "numpy": - # NumPy does not support gradients - return - - with ivy.utils.backend.ContextManager(backend_fw): - x = ivy.astype( - ivy.linspace(ivy.zeros(batch_shape), ivy.ones(batch_shape), input_channels), - "float32", - ) - module = WithNestedModules(input_channels, output_channels, device=on_device) - - # depth 1 - ret = module(x, track_submod_rets=True, submod_depth=1) - assert ret.shape == tuple(list(batch_shape) + [64]) - sm_rets = module.submod_rets - module(x, expected_submod_rets=sm_rets) - sm_rets.random_uniform(map_sequences=True) - try: - module(x, expected_submod_rets=sm_rets.random_uniform(map_sequences=True)) - raise Exception( - "forward pass succeeded despite passing random expected_submod_rets, " - "assertion error expected." - ) - except ivy.utils.exceptions.IvyException: - pass - - # depth 2 (full) - ret = module(x, track_submod_rets=True) - assert ret.shape == tuple(list(batch_shape) + [64]) - sm_rets = module.submod_rets - module(x, expected_submod_rets=sm_rets) - try: - module(x, expected_submod_rets=sm_rets.random_uniform(map_sequences=True)) - raise Exception( - "forward pass succeeded despite passing random expected_submod_rets, " - "assertion error expected." - ) - except ivy.utils.exceptions.IvyException: - pass - - # partial submodules - ret = module( - x, track_submod_rets=True, submods_to_track=[module._dl1, module._dl0._l0] - ) - assert ret.shape == tuple(list(batch_shape) + [64]) - sm_rets = module.submod_rets - module(x, expected_submod_rets=sm_rets) - try: - module(x, expected_submod_rets=sm_rets.random_uniform(map_sequences=True)) - raise Exception( - "forward pass succeeded despite passing random expected_submod_rets, " - "assertion error expected." - ) - except ivy.utils.exceptions.IvyException: - pass - - # with tolerances - ret = module(x, track_submod_rets=True) - assert ret.shape == tuple(list(batch_shape) + [64]) - sm_rets_orig = module.submod_rets - sm_rets = ivy.Container( - { - k: {"val": v, "atol": [1e-8] * len(v), "rtol": [1e-5] * len(v)} - for k, v in sm_rets_orig.items() - }, - **sm_rets_orig._config, - ) - module(x, expected_submod_rets=sm_rets) - sm_rets = ivy.Container( - { - k: {"val": v, "atol": 1e-8, "rtol": 1e-5} - for k, v in sm_rets_orig.items() - }, - **sm_rets_orig._config, - ) - module(x, expected_submod_rets=sm_rets) - try: - module(x, expected_submod_rets=sm_rets.random_uniform(map_sequences=True)) - raise Exception( - "forward pass succeeded despite passing random expected_submod_rets, " - "assertion error expected." - ) - except ivy.utils.exceptions.IvyException: - pass - - -# module depth -@given( - batch_shape=helpers.get_shape( - min_num_dims=2, max_num_dims=2, min_dim_size=1, max_dim_size=2 - ), - input_channels=st.integers(min_value=2, max_value=5), - output_channels=st.integers(min_value=2, max_value=5), -) -def test_module_depth( - batch_shape, input_channels, output_channels, on_device, backend_fw -): - # smoke test - if backend_fw == "numpy": - # NumPy does not support gradients - return - - with ivy.utils.backend.ContextManager(backend_fw): - module = WithNestedModules(input_channels, output_channels, device=on_device) - - # depth 0 - assert module.mod_depth() == 0 - - # depth 1 - assert module._dl0.mod_depth() == 1 - assert module._dl1.mod_depth() == 1 - - # depth 2 - assert module._dl0._l0.mod_depth() == 2 - assert module._dl0._l1.mod_depth() == 2 - assert module._dl1._l0.mod_depth() == 2 - assert module._dl1._l1.mod_depth() == 2 - - -# module height -@given( - batch_shape=helpers.get_shape( - min_num_dims=2, max_num_dims=2, min_dim_size=1, max_dim_size=2 - ), - input_channels=st.integers(min_value=2, max_value=5), - output_channels=st.integers(min_value=2, max_value=5), -) -def test_module_height( - batch_shape, input_channels, output_channels, on_device, backend_fw -): - # smoke test - if backend_fw == "numpy": - # NumPy does not support gradients - return - - with ivy.utils.backend.ContextManager(backend_fw): - module = WithNestedModules(input_channels, output_channels, device=on_device) - - # height 2 - assert module.mod_height() == 2 - - # height 1 - assert module._dl0.mod_height() == 1 - assert module._dl1.mod_height() == 1 - - # height 0 - assert module._dl0._l0.mod_height() == 0 - assert module._dl0._l1.mod_height() == 0 - assert module._dl1._l0.mod_height() == 0 - assert module._dl1._l1.mod_height() == 0 - - @given( batch_shape=helpers.get_shape( min_num_dims=2, max_num_dims=2, min_dim_size=1, max_dim_size=2 @@ -400,17 +226,17 @@ def assertion(x, on_device): raise AssertionError def model_assert(mod, on_device): - for key, obj in mod.v.items(): + for obj in mod.v.values(): if isinstance(obj, ivy.Module): return model_assert(obj, on_device) if isinstance(obj, (ivy.Container, dict)): - for item1, item2 in obj.items(): + for item2 in obj.values(): assertion(item2.device, on_device) else: assertion(obj.device, on_device) if getattr(mod, "buffers", None): - for key, obj in mod.buffers.items(): + for obj in mod.buffers.values(): if isinstance(obj, (ivy.Container, dict)): ivy.nested_map(lambda x: assertion(x.device, on_device), obj) else: @@ -419,255 +245,6 @@ def model_assert(mod, on_device): model_assert(model, on_device) -# track submod call order -@given( - batch_shape=helpers.get_shape( - min_num_dims=2, max_num_dims=2, min_dim_size=1, max_dim_size=2 - ), - input_channels=st.integers(min_value=2, max_value=5), - output_channels=st.integers(min_value=2, max_value=5), -) -def test_module_track_submod_call_order( - batch_shape, input_channels, output_channels, on_device, backend_fw -): - # smoke test - if backend_fw == "numpy": - # NumPy does not support gradients - return - - with ivy.utils.backend.ContextManager(backend_fw): - x = ivy.astype( - ivy.linspace(ivy.zeros(batch_shape), ivy.ones(batch_shape), input_channels), - "float32", - ) - module = WithNestedModules(input_channels, output_channels, device=on_device) - - root_key_0 = ivy.Container.cont_flatten_key_chain(module.__repr__(), "_") + "_0" - - dl0_key_0 = ( - ivy.Container.cont_flatten_key_chain(module._dl0.__repr__(), "_") + "_0" - ) - dl1_key_0 = ( - ivy.Container.cont_flatten_key_chain(module._dl1.__repr__(), "_") + "_0" - ) - dl1_key_1 = ( - ivy.Container.cont_flatten_key_chain(module._dl1.__repr__(), "_") + "_1" - ) - - dl0_l0_key_0 = ( - ivy.Container.cont_flatten_key_chain(module._dl0._l0.__repr__(), "_") + "_0" - ) - dl0_l1_key_0 = ( - ivy.Container.cont_flatten_key_chain(module._dl0._l1.__repr__(), "_") + "_0" - ) - dl1_l0_key_0 = ( - ivy.Container.cont_flatten_key_chain(module._dl1._l0.__repr__(), "_") + "_0" - ) - dl1_l1_key_0 = ( - ivy.Container.cont_flatten_key_chain(module._dl1._l1.__repr__(), "_") + "_0" - ) - - # depth 1 - ret = module(x, track_submod_call_order=True, submod_depth=1) - assert ret.shape == tuple(list(batch_shape) + [64]) - - sm_co = module.submod_call_order - - assert root_key_0 in sm_co - - assert dl0_key_0 in sm_co[root_key_0] - assert dl1_key_0 in sm_co[root_key_0] - assert dl1_key_1 in sm_co[root_key_0] - - assert ivy.Container.cont_identical( - [ - sm_co[root_key_0][dl0_key_0], - module._dl0.v.cont_flatten_key_chains().to_numpy(), - ] - ) - assert ivy.Container.cont_identical( - [ - sm_co[root_key_0][dl1_key_0], - module._dl1.v.cont_flatten_key_chains().to_numpy(), - ] - ) - assert ivy.Container.cont_identical( - [ - sm_co[root_key_0][dl1_key_1], - module._dl1.v.cont_flatten_key_chains().to_numpy(), - ] - ) - - # depth 2 (full) - ret = module(x, track_submod_call_order=True) - assert ret.shape == tuple(list(batch_shape) + [64]) - - sm_co = module.submod_call_order - - assert root_key_0 in sm_co - - assert dl0_key_0 in sm_co[root_key_0] - assert dl1_key_0 in sm_co[root_key_0] - assert dl1_key_1 in sm_co[root_key_0] - - assert dl0_l0_key_0 in sm_co[root_key_0][dl0_key_0] - assert dl0_l1_key_0 in sm_co[root_key_0][dl0_key_0] - assert dl1_l0_key_0 in sm_co[root_key_0][dl1_key_0] - assert dl1_l1_key_0 in sm_co[root_key_0][dl1_key_0] - assert dl1_l0_key_0 in sm_co[root_key_0][dl1_key_1] - assert dl1_l1_key_0 in sm_co[root_key_0][dl1_key_1] - - assert ivy.Container.cont_identical( - [ - sm_co[root_key_0][dl0_key_0][dl0_l0_key_0], - module._dl0._l0.v.cont_flatten_key_chains().to_numpy(), - ] - ) - assert ivy.Container.cont_identical( - [ - sm_co[root_key_0][dl0_key_0][dl0_l1_key_0], - module._dl0._l1.v.cont_flatten_key_chains().to_numpy(), - ] - ) - assert ivy.Container.cont_identical( - [ - sm_co[root_key_0][dl1_key_0][dl1_l0_key_0], - module._dl1._l0.v.cont_flatten_key_chains().to_numpy(), - ] - ) - assert ivy.Container.cont_identical( - [ - sm_co[root_key_0][dl1_key_0][dl1_l1_key_0], - module._dl1._l1.v.cont_flatten_key_chains().to_numpy(), - ] - ) - assert ivy.Container.cont_identical( - [ - sm_co[root_key_0][dl1_key_1][dl1_l0_key_0], - module._dl1._l0.v.cont_flatten_key_chains().to_numpy(), - ] - ) - assert ivy.Container.cont_identical( - [ - sm_co[root_key_0][dl1_key_1][dl1_l1_key_0], - module._dl1._l1.v.cont_flatten_key_chains().to_numpy(), - ] - ) - - # partial submodules - ret = module( - x, - track_submod_call_order=True, - submods_to_track=[module._dl1, module._dl0._l0], - ) - assert ret.shape == tuple(list(batch_shape) + [64]) - - sm_co = module.submod_call_order - - assert root_key_0 in sm_co - - assert dl0_key_0 in sm_co[root_key_0] - assert dl1_key_0 in sm_co[root_key_0] - assert dl1_key_1 in sm_co[root_key_0] - - assert dl0_l0_key_0 in sm_co[root_key_0][dl0_key_0] - assert dl0_l1_key_0 not in sm_co[root_key_0][dl0_key_0] - assert ivy.Container.cont_identical( - [ - sm_co[root_key_0][dl1_key_0], - module._dl1.v.cont_flatten_key_chains().to_numpy(), - ] - ) - assert ivy.Container.cont_identical( - [ - sm_co[root_key_0][dl1_key_1], - module._dl1.v.cont_flatten_key_chains().to_numpy(), - ] - ) - - assert ivy.Container.cont_identical( - [ - sm_co[root_key_0][dl0_key_0][dl0_l0_key_0], - module._dl0._l0.v.cont_flatten_key_chains().to_numpy(), - ] - ) - - -# track submod returns -@given( - batch_shape=helpers.get_shape( - min_num_dims=2, max_num_dims=2, min_dim_size=1, max_dim_size=2 - ), - input_channels=st.integers(min_value=2, max_value=5), - output_channels=st.integers(min_value=2, max_value=5), -) -def test_module_track_submod_rets( - batch_shape, input_channels, output_channels, on_device, backend_fw -): - # smoke test - if backend_fw == "numpy": - # NumPy does not support gradients - return - - with ivy.utils.backend.ContextManager(backend_fw): - x = ivy.astype( - ivy.linspace(ivy.zeros(batch_shape), ivy.ones(batch_shape), input_channels), - "float32", - ) - module = WithNestedModules(input_channels, output_channels, device=on_device) - - # depth 1 - ret = module(x, track_submod_rets=True, submod_depth=1) - assert ret.shape == tuple(list(batch_shape) + [64]) - sm_rets = module.submod_rets - for submod in [module._dl0, module._dl1]: - for ret in sm_rets[submod.get_mod_key()]: - assert isinstance(ret, np.ndarray) - assert ret.shape == tuple(list(batch_shape) + [64]) - for submod in [ - module._dl0._l0, - module._dl0._l1, - module._dl1._l0, - module._dl1._l1, - ]: - assert ( - ivy.Container.cont_flatten_key_chain(submod.__repr__(), "_") - not in sm_rets - ) - - # depth 2 (full) - ret = module(x, track_submod_rets=True) - assert ret.shape == tuple(list(batch_shape) + [64]) - sm_rets = module.submod_rets - for submod in [ - module._dl0, - module._dl1, - module._dl0._l0, - module._dl0._l1, - module._dl1._l0, - module._dl1._l1, - ]: - for ret in sm_rets[submod.get_mod_key()]: - assert isinstance(ret, np.ndarray) - assert ret.shape == tuple(list(batch_shape) + [64]) - - # partial submodules - ret = module( - x, track_submod_rets=True, submods_to_track=[module._dl1, module._dl0._l0] - ) - assert ret.shape == tuple(list(batch_shape) + [64]) - sm_rets = module.submod_rets - for submod in [module._dl1, module._dl0._l0]: - for ret in sm_rets[submod.get_mod_key()]: - assert isinstance(ret, np.ndarray) - assert ret.shape == tuple(list(batch_shape) + [64]) - for submod in [module._dl0, module._dl0._l1, module._dl1._l0, module._dl1._l1]: - assert ( - ivy.Container.cont_flatten_key_chain(submod.__repr__(), "_") - not in sm_rets - ) - - # module training @given( batch_shape=helpers.get_shape( @@ -992,125 +569,6 @@ def test_module_w_partial_v( module(x) -# sub modules -@given( - batch_shape=helpers.get_shape( - min_num_dims=2, max_num_dims=2, min_dim_size=1, max_dim_size=2 - ), - input_channels=st.integers(min_value=2, max_value=5), - output_channels=st.integers(min_value=2, max_value=5), -) -def test_sub_modules( - batch_shape, input_channels, output_channels, on_device, backend_fw -): - # smoke test - if backend_fw == "numpy": - # NumPy does not support gradients - return - - with ivy.utils.backend.ContextManager(backend_fw): - module = WithNestedModules(input_channels, output_channels, device=on_device) - - # depth 0 - sub_mods = module.sub_mods(depth=0) - assert module.v is sub_mods - - # depth 1 - sub_mods = module.sub_mods(depth=1) - for v in [module._dl0.v, module._dl1.v]: - assert v in sub_mods - - # depth 2 (full) - sub_mods = module.sub_mods() - for v in [ - module._dl0._l0.v, - module._dl0._l1.v, - module._dl1._l0.v, - module._dl1._l1.v, - ]: - assert v in sub_mods - - -# top module -@given( - batch_shape=helpers.get_shape( - min_num_dims=2, max_num_dims=2, min_dim_size=1, max_dim_size=2 - ), - input_channels=st.integers(min_value=2, max_value=5), - output_channels=st.integers(min_value=2, max_value=5), -) -def test_top_module( - batch_shape, input_channels, output_channels, on_device, backend_fw -): - # smoke test - if backend_fw == "numpy": - # NumPy does not support gradients - return - - with ivy.utils.backend.ContextManager(backend_fw): - module = WithNestedModules(input_channels, output_channels, device=on_device) - - # full depth - assert module._dl0.top_mod() is module - assert module._dl1.top_mod() is module - - assert module._dl0._l0.top_mod() is module - assert module._dl0._l1.top_mod() is module - assert module._dl1._l0.top_mod() is module - assert module._dl1._l1.top_mod() is module - - # depth 1 - assert module._dl0._l0.top_mod(1) is module._dl0 - assert module._dl0._l1.top_mod(1) is module._dl0 - assert module._dl1._l0.top_mod(1) is module._dl1 - assert module._dl1._l1.top_mod(1) is module._dl1 - - -# top variables -@given( - batch_shape=helpers.get_shape( - min_num_dims=2, max_num_dims=2, min_dim_size=1, max_dim_size=2 - ), - input_channels=st.integers(min_value=2, max_value=5), - output_channels=st.integers(min_value=2, max_value=5), -) -def test_top_variables( - batch_shape, input_channels, output_channels, on_device, backend_fw -): - # smoke test - if backend_fw == "numpy": - # NumPy does not support gradients - return - - with ivy.utils.backend.ContextManager(backend_fw): - module = WithNestedModules(input_channels, output_channels, device=on_device) - for key_chain in [ - "dl0", - "dl0/l0", - "dl0/l1", - "dl0/l0/b", - "dl0/l0/w", - "dl0/l1/b", - "dl0/l1/w", - "dl1", - "dl1/l0", - "dl1/l1", - "dl1/l0/b", - "dl1/l0/w", - "dl1/l1/b", - "dl1/l1/w", - ]: - # depth 1 - assert key_chain in module._dl0.top_v() - assert key_chain in module._dl1.top_v() - - # depth 2 - assert key_chain in module._dl0._l0.top_v() - assert key_chain in module._dl0._l1.top_v() - assert key_chain in module._dl1._l0.top_v() - assert key_chain in module._dl1._l1.top_v() - - @given(mode=st.booleans()) def test_train_eval(mode, backend_fw): with ivy.utils.backend.ContextManager(backend_fw): @@ -1121,73 +579,6 @@ def test_train_eval(mode, backend_fw): assert not cls.training -# v with top v key chains -@given( - batch_shape=helpers.get_shape( - min_num_dims=2, max_num_dims=2, min_dim_size=1, max_dim_size=2 - ), - input_channels=st.integers(min_value=2, max_value=5), - output_channels=st.integers(min_value=2, max_value=5), -) -def test_v_with_top_v_key_chains( - batch_shape, input_channels, output_channels, on_device, backend_fw -): - # smoke test - if backend_fw == "numpy": - # NumPy does not support gradients - return - - with ivy.utils.backend.ContextManager(backend_fw): - module = WithNestedModules(input_channels, output_channels, device=on_device) - - # full depth - v = module._dl0.v_with_top_v_key_chains() - assert "dl0" in v - assert v.dl0 is module._dl0.v - - v = module._dl1.v_with_top_v_key_chains() - assert "dl1" in v - assert v.dl1 is module._dl1.v - - v = module._dl0._l0.v_with_top_v_key_chains() - assert "dl0" in v - assert "l0" in v.dl0 - assert v.dl0.l0 is module._dl0._l0.v - - v = module._dl0._l1.v_with_top_v_key_chains() - assert "dl0" in v - assert "l1" in v.dl0 - assert v.dl0.l1 is module._dl0._l1.v - - v = module._dl1._l0.v_with_top_v_key_chains() - assert "dl1" in v - assert "l0" in v.dl1 - assert v.dl1.l0 is module._dl1._l0.v - - v = module._dl1._l1.v_with_top_v_key_chains() - assert "dl1" in v - assert "l1" in v.dl1 - assert v.dl1.l1 is module._dl1._l1.v - - # depth 1 - - v = module._dl0._l0.v_with_top_v_key_chains(depth=1) - assert "l0" in v - assert v.l0 is module._dl0._l0.v - - v = module._dl0._l1.v_with_top_v_key_chains(depth=1) - assert "l1" in v - assert v.l1 is module._dl0._l1.v - - v = module._dl1._l0.v_with_top_v_key_chains(depth=1) - assert "l0" in v - assert v.l0 is module._dl1._l0.v - - v = module._dl1._l1.v_with_top_v_key_chains(depth=1) - assert "l1" in v - assert v.l1 is module._dl1._l1.v - - # with custom var structure @given( batch_shape=helpers.get_shape( diff --git a/ivy_tests/test_ivy/test_stateful/test_sequential.py b/ivy_tests/test_ivy/test_stateful/test_sequential.py index 1a9223c309987..3273373477633 100644 --- a/ivy_tests/test_ivy/test_stateful/test_sequential.py +++ b/ivy_tests/test_ivy/test_stateful/test_sequential.py @@ -7,6 +7,7 @@ # local import ivy +from ivy_tests.test_ivy import helpers from ivy_tests.test_ivy.helpers.testing_helpers import handle_method @@ -59,7 +60,14 @@ def loss_fn(_v): @handle_method( method_tree="Sequential.__call__", input_array=st.lists( - st.floats(min_value=-1, max_value=1, allow_nan=False, allow_infinity=False), + helpers.floats( + min_value=-1, + max_value=1, + allow_nan=False, + allow_inf=False, + small_abs_safety_factor=1.5, + safety_factor_scale="log", + ), min_size=1, max_size=5, ), @@ -69,49 +77,58 @@ def loss_fn(_v): def test_sequential_construction_and_value( input_array, dims, use_activation, on_device, backend_fw ): - dims = [len(input_array)] + dims - layer_count = len(dims) - layers = [ - ivy.Linear(dims[i], dims[i + 1], device=on_device) - for i in range(layer_count - 1) - ] + with ivy.utils.backend.ContextManager(backend_fw): + dims = [len(input_array)] + dims + layer_count = len(dims) + layers = [ + ivy.Linear(dims[i], dims[i + 1], device=on_device) + for i in range(layer_count - 1) + ] - if use_activation: - activations = [ivy.GELU() for _ in range(layer_count - 1)] - layers = itertools.chain.from_iterable(zip(layers, activations)) + if use_activation: + activations = [ivy.GELU() for _ in range(layer_count - 1)] + layers = itertools.chain.from_iterable(zip(layers, activations)) - module = ivy.Sequential(*layers) + module = ivy.Sequential(*layers) - input_array = ivy.array(input_array, dtype="float32", device=on_device) + input_array = ivy.array(input_array, dtype="float32", device=on_device) - if "numpy" not in backend_fw.__name__: - _train(module, input_array) + if backend_fw != "numpy": + _train(module, input_array) @handle_method( method_tree="Sequential.__call__", input_array=st.lists( - st.floats(min_value=0, max_value=1, allow_nan=False, allow_infinity=False), + helpers.floats( + min_value=0, + max_value=1, + allow_nan=False, + allow_inf=False, + small_abs_safety_factor=1.5, + safety_factor_scale="log", + ), min_size=1, max_size=5, ), dims=st.lists(st.integers(1, 10), min_size=2, max_size=2), ) def test_sequential_same_as_class(input_array, dims, backend_fw): - dims = [len(input_array)] + dims - layer_count = len(dims) - layers = [ivy.Linear(dims[i], dims[i + 1]) for i in range(layer_count - 1)] + with ivy.utils.backend.ContextManager(backend_fw): + dims = [len(input_array)] + dims + layer_count = len(dims) + layers = [ivy.Linear(dims[i], dims[i + 1]) for i in range(layer_count - 1)] - m_sequential = ivy.Sequential(*layers) - m_class = TrainableModule(dims[0], dims[1], dims[2]) + m_sequential = ivy.Sequential(*layers) + m_class = TrainableModule(dims[0], dims[1], dims[2]) - # copy weights - _copy_weights(m_class.v.linear0, m_sequential.v.submodules.v0) - _copy_weights(m_class.v.linear1, m_sequential.v.submodules.v1) + # copy weights + _copy_weights(m_class.v.linear0, m_sequential.v.submodules.v0) + _copy_weights(m_class.v.linear1, m_sequential.v.submodules.v1) - input_array = ivy.array(input_array, dtype="float32") + input_array = ivy.array(input_array, dtype="float32") - if "numpy" not in backend_fw.__name__: - sequential_loss = _train(m_sequential, input_array) - class_loss = _train(m_class, input_array) - assert sequential_loss == class_loss + if backend_fw != "numpy": + sequential_loss = _train(m_sequential, input_array) + class_loss = _train(m_class, input_array) + assert sequential_loss == class_loss diff --git a/project.toml b/project.toml deleted file mode 100644 index f41dc8bb153c2..0000000000000 --- a/project.toml +++ /dev/null @@ -1,7 +0,0 @@ -[build-system] -requires = [ - "setuptools>=42", - "wheel", - "pip" -] -build-backend = "setuptools.build_meta" diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000000000..c0e38e22ac6ae --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,78 @@ +[build-system] +requires = [ + "setuptools>=42", + "wheel", + "pip" +] +build-backend = "setuptools.build_meta" + + +[tool.docformatter] +wrap-summaries = 88 +pre-summary-newline = true + + +[tool.autoflake] +in-place = true +remove-all-unused-imports = true +ignore-init-module-imports = true +remove-duplicate-keys = true +remove-unused-variables = true +quiet = true +ignore-pass-after-docstring = true +exclude = ["__init__.py"] + + +[tool.ruff] +line-length = 88 +target-version = "py38" + +[tool.ruff.lint] +select = [ + # pyflakes + "F", + # pycodestyle + "E", "W", + # pydocstyle + "D", + "I002", # Missing required import. + "UP008", # Checks for super calls that pass redundant arguments. + "G010", # deprecated-log-warn. + "PLR1722", # Use sys.exit() instead of exit() and quit(). + "TRY004", # Prefer TypeError exception for invalid type. + "PT014", # pytest-duplicate-parametrize-test-cases. + "PT006", # Checks for the type of parameter names passed to pytest.mark.parametrize. + "PT007", # Checks for the type of parameter values passed to pytest.mark.parametrize. + "PT018", # Checks for assertions that combine multiple independent conditions. +] + + +ignore = [ + "E203", # Whitespace-before-punctuation. + "E402", # Module-import-not-at-top-of-file. + "E731", # Do not assign a lambda expression, use a def. + "D100", # Missing docstring in public module. + "D101", # Missing docstring in public class. + "D102", # Missing docstring in public method. + "D103", # Missing docstring in public function. + "D104", # Missing docstring in public package. + "D105", # Missing docstring in magic method. + "D106", # Missing docstring in public nested class. + "D107", # Missing docstring in `__init__`. + "D203", # 1 blank line required before class docstring. + "D205", # 1 blank line required between summary line and description. + "D212", # Multi-line docstring summary should start at the first line. + "D213", # Multi-line docstring summary should start at the second line. + "D209", # Multi-line docstring closing quotes should be on a separate line. + "D400", # First line should end with a period. + "D413", # Missing blank line after last section of docstrings. + "D401", # First line of docstring should be in imperative mood. + "D415", # First line should end with a period, question mark, or exclamation point. + "D416", # Section name should end with a colon ("Attributes"). + "D417", # Missing argument description in the docstring for argument "X". +] + +[tool.ruff.lint.per-file-ignores] +'ivy/functional/(frontends|backends)/(?!.*/func_wrapper\.py$).*(?!__init__\.py$)' = ["D"] +"**/__init__.py" = ["F401","F403","F405","F811","F821", "E501"] +"ivy/functional/frontends/paddle/**" = ["F401", "F403", "F405"] diff --git a/requirements/optional.txt b/requirements/optional.txt index e34585650624e..7362789081551 100644 --- a/requirements/optional.txt +++ b/requirements/optional.txt @@ -1,7 +1,7 @@ h5py # unpinned pytest # unpinned networkx # unpinned -hypothesis # unpinned +hypothesis==6.98.10 # fixed version till this get solved: https://github.com/HypothesisWorks/hypothesis/issues/3896 pymongo # unpinned redis # unpinned matplotlib # unpinned @@ -12,7 +12,6 @@ paddlepaddle # unpinned , mod_name=paddle tensorflow-cpu # unpinned, we test for latest version now, mod_name=tensorflow torch # unpinned, we test for latest version now # torch-scatter # unpinned, mod_name=torch_scatter -functorch # unpinned, we test for latest version now scipy # unpinned dm-haiku # unpinned mod_name=haiku flax diff --git a/requirements/optional_apple_silicon_1.txt b/requirements/optional_apple_silicon_1.txt index 7f32348c59d41..834822a43a716 100644 --- a/requirements/optional_apple_silicon_1.txt +++ b/requirements/optional_apple_silicon_1.txt @@ -13,3 +13,4 @@ tensorflow-probability # mod_name=tensorflow_probability torch paddlepaddle # unpinned , mod_name=paddle torchvision +cryptography diff --git a/requirements/optional_apple_silicon_2.txt b/requirements/optional_apple_silicon_2.txt index 7a3325ede80c3..8deb0b3a7d599 100644 --- a/requirements/optional_apple_silicon_2.txt +++ b/requirements/optional_apple_silicon_2.txt @@ -1,5 +1,4 @@ torch-scatter # torch_scatter requires a prior existing installation of torch, hence 2 optional files -functorch scipy dm-haiku # mod_name=haiku flax @@ -11,3 +10,4 @@ pandas pyspark autoflake # for backend generation snakeviz # for profiling +ml-dtypes==0.2.0 diff --git a/requirements/optional_apple_silicon_gpu_2.txt b/requirements/optional_apple_silicon_gpu_2.txt index 7a3325ede80c3..8deb0b3a7d599 100644 --- a/requirements/optional_apple_silicon_gpu_2.txt +++ b/requirements/optional_apple_silicon_gpu_2.txt @@ -1,5 +1,4 @@ torch-scatter # torch_scatter requires a prior existing installation of torch, hence 2 optional files -functorch scipy dm-haiku # mod_name=haiku flax @@ -11,3 +10,4 @@ pandas pyspark autoflake # for backend generation snakeviz # for profiling +ml-dtypes==0.2.0 diff --git a/requirements/optional_gpu.txt b/requirements/optional_gpu.txt index 0810e836b9ba1..38ae84c72f26f 100644 --- a/requirements/optional_gpu.txt +++ b/requirements/optional_gpu.txt @@ -11,7 +11,6 @@ jaxlib # unpinned, we test for latest version now tensorflow # unpinned, we test for latest version now torch # unpinned, we test for latest version now torch-scatter # unpinned, mod_name=torch_scatter -functorch # unpinned, we test for latest version now scipy # unpinned dm-haiku # unpinned mod_name=haiku flax diff --git a/requirements/requirements.txt b/requirements/requirements.txt index 375a11f7bbeaa..84262042721ed 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -12,7 +12,8 @@ requests pyvis dill astunparse -ml-dtypes # mod_name=ml_dtypes +ml-dtypes==0.2.0 # mod_name=ml_dtypes cloudpickle gast tqdm +cryptography diff --git a/scripts/backend_generation/generate.py b/scripts/backend_generation/generate.py index 152bd5801cdd5..523ad1b6f28a7 100644 --- a/scripts/backend_generation/generate.py +++ b/scripts/backend_generation/generate.py @@ -167,8 +167,7 @@ def _should_install_backend(package_name): ) from e elif ret.lower() == "n": print( - Fore.YELLOW - + "Will continue without backend installed, " + Fore.YELLOW + "Will continue without backend installed, " "type checking won't be available.\n" ) else: @@ -268,9 +267,9 @@ def _update_valid_config_value(key): ret = ret.strip("") if ret == "": return True - indicies = ret.split(" ") - indicies = [int(item.strip(" ")) for item in indicies] - for i in sorted(indicies, reverse=True): + indices = ret.split(" ") + indices = [int(item.strip(" ")) for item in indices] + for i in sorted(indices, reverse=True): del config_valids[key][i] return True diff --git a/scripts/backend_generation/tree_generation.py b/scripts/backend_generation/tree_generation.py index c763af66cce48..7c94d01ef603c 100644 --- a/scripts/backend_generation/tree_generation.py +++ b/scripts/backend_generation/tree_generation.py @@ -208,6 +208,9 @@ def _copy_tree(backend_reference_path: str, backend_generation_path: str): def _create_type_mapping(config: dict, reference_backend_init_path: str): + # print pwd for debugging + print(os.getcwd()) + print with open(reference_backend_init_path, "r") as file: file_src = file.read() @@ -238,7 +241,7 @@ def generate(config_file): global _target_backend _target_backend = _config["name"] - backends_root = "../../ivy/functional/backends/" + backends_root = "ivy/functional/backends/" backend_reference_path = backends_root + _backend_reference backend_generation_path = backends_root + _target_backend diff --git a/scripts/determine_tests/array_api_det_coverage.py b/scripts/determine_tests/array_api_det_coverage.py index e68ec5d3aa582..0315a04139e79 100644 --- a/scripts/determine_tests/array_api_det_coverage.py +++ b/scripts/determine_tests/array_api_det_coverage.py @@ -1,4 +1,5 @@ import os +import sys import subprocess from pydriller import Repository from tqdm import tqdm @@ -8,6 +9,8 @@ def main(): BACKENDS = ["numpy", "jax", "tensorflow", "torch"] + N = 4 + run_iter = int(sys.argv[1]) - 1 test_names = [] func_folder = "ivy_tests/array_api_testing/array_api_methods_to_test" @@ -77,9 +80,20 @@ def main(): x for x in directories if not (x.endswith("__pycache__") or "hypothesis" in x) ] directories = set(directories_filtered) - for test_backend in tqdm(test_names): + num_tests = len(test_names) + tests_per_run = num_tests // N + start = run_iter * tests_per_run + end = num_tests if run_iter == N - 1 else (run_iter + 1) * tests_per_run + for test_backend in tqdm(test_names[start:end]): test_name, backend = test_backend.split(",") - command = f'docker run --rm --env IVY_BACKEND={backend} --env ARRAY_API_TESTS_MODULE="ivy" -v "$(pwd)":/ivy unifyai/ivy:latest timeout 30m /bin/bash -c "coverage run --source=ivy,ivy_tests -m pytest {test_name} -k \\"{k_flag[backend]}\\" --disable-warnings --tb=short -vv > coverage_output;coverage annotate > coverage_output" ' # noqa + command = ( + f"docker run --rm --env IVY_BACKEND={backend} --env " + 'ARRAY_API_TESTS_MODULE="ivy" -v "$(pwd)":/ivy unifyai/ivy:latest ' + 'timeout 30m /bin/bash -c "coverage run --source=ivy,ivy_tests -m pytest ' + f'{test_name} -k \\"{k_flag[backend]}\\" --disable-warnings --tb=short ' + "--hypothesis-max-examples 5 -vv > coverage_output;coverage annotate > " + 'coverage_output"' + ) os.system(command) for directory in directories: for file_name in os.listdir(directory): diff --git a/scripts/eager_mode_benchmark/benchmark.py b/scripts/eager_mode_benchmark/benchmark.py index 049a05a995fab..77b839bc3f647 100644 --- a/scripts/eager_mode_benchmark/benchmark.py +++ b/scripts/eager_mode_benchmark/benchmark.py @@ -104,9 +104,8 @@ def eager_benchmark( kwargs: Optional[Dict[str, Any]] = None, output_path="./report.csv", ): - """ - Benchmark the function or module passed in input on the required backends and - devices. + """Benchmark the function or module passed in input on the required + backends and devices. Parameters ---------- @@ -274,14 +273,13 @@ def eager_benchmark( def visualize_speed_up( - file_path: str = None, - output_path: str = None, + file_path: Optional[str] = None, + output_path: Optional[str] = None, devices: Union[List[str], str] = "all", backends: Union[List[str], str] = "all", - labels: Union[List[str], str] = None, + labels: Optional[Union[List[str], str]] = None, ): - """ - Visualize the speed up results stored in the csv. + """Visualize the speed up results stored in the csv. Parameters ---------- diff --git a/scripts/generate_intelligent_tests_workflow.py b/scripts/generate_intelligent_tests_workflow.py index 6b8b8a3a301cb..6cdf8ff51b7dd 100644 --- a/scripts/generate_intelligent_tests_workflow.py +++ b/scripts/generate_intelligent_tests_workflow.py @@ -5,7 +5,7 @@ print("on:") print(" workflow_dispatch:") print(" pull_request:") -print(" types: [ labeled, opened, synchronize, reopened, review_requested ]") +print(" types: [opened, synchronize, reopened, review_requested ]") print() print("permissions:") print(" actions: read") diff --git a/scripts/run_tests/array_api_run_tests_pr.py b/scripts/run_tests/array_api_run_tests_pr.py index d13eddf88c2cd..72c774b85a0e6 100644 --- a/scripts/run_tests/array_api_run_tests_pr.py +++ b/scripts/run_tests/array_api_run_tests_pr.py @@ -21,18 +21,20 @@ def main(): array_api_tests_k_flag += " and not (uint16 or uint32 or uint64)" k_flag[backend] = array_api_tests_k_flag - with open("tests_to_run", "r") as f: - for line in f: - test, backend = line.split(",") - backend = backend.strip("\n") - command = f'docker run --rm --env IVY_BACKEND={backend} --env ARRAY_API_TESTS_MODULE="ivy" -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis unifyai/ivy:latest timeout 30m python3 -m pytest {test} -k "{k_flag[backend]}" --tb=short -vv' # noqa - print(f"\n{'*' * 100}") - print(f"{line[:-1]}") - print(f"{'*' * 100}\n") - sys.stdout.flush() - ret = os.system(command) - if ret != 0: - failed = True + with open(sys.argv[1], "w") as f_write: + with open("tests_to_run", "r") as f: + for line in f: + test, backend = line.split(",") + backend = backend.strip("\n") + command = f'docker run --rm --env IVY_BACKEND={backend} --env ARRAY_API_TESTS_MODULE="ivy" -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis unifyai/ivy:latest timeout 30m python3 -m pytest {test} -k "{k_flag[backend]}" --tb=short -vv' # noqa + print(f"\n{'*' * 100}") + print(f"{line[:-1]}") + print(f"{'*' * 100}\n") + sys.stdout.flush() + ret = os.system(command) + if ret != 0: + failed = True + f_write.write(line) if failed: sys.exit(1) diff --git a/scripts/run_tests/helpers.py b/scripts/run_tests/helpers.py new file mode 100644 index 0000000000000..2380fb1f78ce6 --- /dev/null +++ b/scripts/run_tests/helpers.py @@ -0,0 +1,64 @@ +import requests + + +def get_latest_package_version(package_name): + try: + url = f"https://pypi.org/pypi/{package_name}/json" + response = requests.get(url, timeout=10) + response.raise_for_status() + package_info = response.json() + return package_info["info"]["version"] + except requests.exceptions.RequestException: + print(f"Error: Failed to fetch package information for {package_name}.") + return None + + +def get_submodule_and_function_name(test_path, is_frontend_test=False): + submodule_test = test_path.split("/")[-1] + submodule, test_function = submodule_test.split("::") + submodule = submodule.replace("test_", "").replace(".py", "") + + with open(test_path.split("::")[0]) as test_file: + test_file_content = test_file.read() + test_function_idx = test_file_content.find(f"def {test_function}") + test_function_block_idx = test_file_content[:test_function_idx].rfind("\n\n") + if test_function_block_idx == -1: + return submodule, None + relevant_file_content = test_file_content[ + test_function_block_idx:test_function_idx + ] + fn_tree_idx = relevant_file_content.rfind('fn_tree="') + + # frontend test + if is_frontend_test: + function_name = relevant_file_content[fn_tree_idx + 9 :].split('"')[0] + + # instance method test + if fn_tree_idx == -1: + class_tree_idx = test_file_content.find('CLASS_TREE = "') + method_name_idx = relevant_file_content.rfind('method_name="') + if class_tree_idx == -1 or method_name_idx == -1: + return submodule, None + class_tree = test_file_content[class_tree_idx + 14 :].split('"')[0] + class_name = ".".join(class_tree.split(".")[3:]) + method_name = relevant_file_content[method_name_idx + 13 :].split('"')[ + 0 + ] + function_name = f"{class_name}.{method_name}" + + # ivy test + else: + function_name = test_function[5:] + + # instance method test + if fn_tree_idx == -1: + method_name_idx = relevant_file_content.rfind('method_tree="') + if method_name_idx != -1: + method_name = relevant_file_content[method_name_idx + 13 :].split( + '"' + )[0] + function_name = f"ivy.{method_name}" + else: + return submodule, None + + return submodule, function_name diff --git a/scripts/run_tests/label_failures.py b/scripts/run_tests/label_failures.py new file mode 100644 index 0000000000000..2753e86192fa4 --- /dev/null +++ b/scripts/run_tests/label_failures.py @@ -0,0 +1,39 @@ +# Run Tests +import sys +from pymongo import MongoClient + +from helpers import ( + get_latest_package_version, + get_submodule_and_function_name, +) + + +if __name__ == "__main__": + failed = False + cluster = MongoClient( + "mongodb+srv://readonly-user:hvpwV5yVeZdgyTTm@cluster0.qdvf8q3.mongodb.net" + ) + db = cluster["ci_dashboard"] + with open(sys.argv[2], "w") as f_write: + with open(sys.argv[1], "r") as f: + for line in f: + test_path, backend = line.strip().split(",") + is_frontend_test = "test_frontends" in test_path + collection = ( + db["frontend_tests"] if is_frontend_test else db["ivy_tests"] + ) + submodule, function_name = get_submodule_and_function_name( + test_path, is_frontend_test + ) + version = get_latest_package_version(backend).replace(".", "_") + document = collection.find_one({"_id": function_name}) + if document: + try: + if document[backend][version]["status"]["cpu"]: + line = line.strip("\n") + " (main: pass)\n" + except KeyError: + print( + f"Could not find {backend}.{version}.status.cpu for" + " document" + ) + f_write.write(line) diff --git a/scripts/run_tests/run_tests.py b/scripts/run_tests/run_tests.py index d9f2ab503e2a9..f60131c799651 100644 --- a/scripts/run_tests/run_tests.py +++ b/scripts/run_tests/run_tests.py @@ -2,75 +2,16 @@ import os import sys from pymongo import MongoClient -import requests +from pymongo.errors import WriteError import json import old_run_test_helpers as old_helpers +from helpers import ( + get_latest_package_version, + get_submodule_and_function_name, +) from get_all_tests import BACKENDS -def get_latest_package_version(package_name): - try: - url = f"https://pypi.org/pypi/{package_name}/json" - response = requests.get(url) - response.raise_for_status() - package_info = response.json() - return package_info["info"]["version"] - except requests.exceptions.RequestException: - print(f"Error: Failed to fetch package information for {package_name}.") - return None - - -def get_submodule_and_function_name(test_path, is_frontend_test=False): - submodule_test = test_path.split("/")[-1] - submodule, test_function = submodule_test.split("::") - submodule = submodule.replace("test_", "").replace(".py", "") - - with open(test_path.split("::")[0]) as test_file: - test_file_content = test_file.read() - test_function_idx = test_file_content.find(f"def {test_function}") - test_function_block_idx = test_file_content[:test_function_idx].rfind("\n\n") - if test_function_block_idx == -1: - return submodule, None - relevant_file_content = test_file_content[ - test_function_block_idx:test_function_idx - ] - fn_tree_idx = relevant_file_content.rfind('fn_tree="') - - # frontend test - if is_frontend_test: - function_name = relevant_file_content[fn_tree_idx + 9 :].split('"')[0] - - # instance method test - if fn_tree_idx == -1: - class_tree_idx = test_file_content.find('CLASS_TREE = "') - method_name_idx = relevant_file_content.rfind('method_name="') - if class_tree_idx == -1 or method_name_idx == -1: - return submodule, None - class_tree = test_file_content[class_tree_idx + 14 :].split('"')[0] - class_name = ".".join(class_tree.split(".")[3:]) - method_name = relevant_file_content[method_name_idx + 13 :].split('"')[ - 0 - ] - function_name = f"{class_name}.{method_name}" - - # ivy test - else: - function_name = test_function[5:] - - # instance method test - if fn_tree_idx == -1: - method_name_idx = relevant_file_content.rfind('method_tree="') - if method_name_idx != -1: - method_name = relevant_file_content[method_name_idx + 13 :].split( - '"' - )[0] - function_name = f"ivy.{method_name}" - else: - return submodule, None - - return submodule, function_name - - if __name__ == "__main__": redis_url = sys.argv[1] redis_pass = sys.argv[2] @@ -79,9 +20,11 @@ def get_submodule_and_function_name(test_path, is_frontend_test=False): gpu_flag = sys.argv[5] workflow_id = sys.argv[6] priority_flag = sys.argv[7] + tracer_flag = sys.argv[8] + tracer_flag_each = sys.argv[9] - if len(sys.argv) > 8 and sys.argv[8] != "null": - run_id = sys.argv[8] + if len(sys.argv) > 10 and sys.argv[10] != "null": + run_id = sys.argv[10] else: run_id = f"https://github.com/unifyai/ivy/actions/runs/{workflow_id}" @@ -89,6 +32,20 @@ def get_submodule_and_function_name(test_path, is_frontend_test=False): if gpu_flag == "true": device = "gpu" + tracer_str = "" + if tracer_flag == "true": + tracer_flag = "tracer_" + tracer_str = " --with-trace-testing" + else: + tracer_flag = "" + + tracer_str_each = "" + if not tracer_flag and tracer_flag_each == "true": + tracer_flag_each = "tracer_each_" + tracer_str_each = " --with-trace-testing-each" + else: + tracer_flag_each = "" + cluster = MongoClient( f"mongodb+srv://deep-ivy:{mongo_key}@cluster0.qdvf8q3.mongodb.net/?retryWrites=true&w=majority" # noqa ) @@ -105,7 +62,7 @@ def get_submodule_and_function_name(test_path, is_frontend_test=False): # pull gpu image for gpu testing if device == "gpu": - os.system("docker pull unifyai/multicuda:base_and_requirements") + os.system("docker pull unifyai/ivy:latest-gpu") # read the tests to be run with open("tests_to_run", "r") as f: @@ -132,42 +89,49 @@ def get_submodule_and_function_name(test_path, is_frontend_test=False): backends = [backend.strip()] backend_name, backend_version = backend.split("/") other_backends = [ - fw for fw in BACKENDS if (fw != backend_name and fw != "paddle") + fw for fw in BACKENDS if (fw not in (backend_name, "paddle")) ] for other_backend in other_backends: backends.append( other_backend + "/" + get_latest_package_version(other_backend) ) print("Backends:", backends) - command = ( - f"docker run --rm --env REDIS_URL={redis_url} --env" - f' REDIS_PASSWD={redis_pass} -v "$(pwd)":/ivy/ivy' - ' unifyai/multiversion:latest /bin/bash -c "python' - f" multiversion_framework_directory.py {' '.join(backends)};cd" - f' ivy;pytest --tb=short {test_path} --backend={backend.strip()}"' + os.system( + 'docker run --name test-container -v "$(pwd)":/ivy/ivy ' + f"-e REDIS_URL={redis_url} -e REDIS_PASSWD={redis_pass} " + "-itd unifyai/multiversion:latest /bin/bash -c" + f'python multiversion_framework_directory.py {" ".join(backends)};' + ) + os.system( + "docker exec test-container cd ivy; python3 -m pytest --tb=short " + f"{test_path} --backend={backend.strip()}" ) backend = backend.split("/")[0] + "\n" backend_version = backend_version.strip() - print("Running", command) - - # gpu tests - elif device == "gpu": - command = ( - f"docker run --rm --gpus all --env REDIS_URL={redis_url} --env" - f' REDIS_PASSWD={redis_pass} -v "$(pwd)":/ivy -v' - ' "$(pwd)"/.hypothesis:/.hypothesis' - " unifyai/multicuda:base_and_requirements python3 -m pytest" - f" --tb=short {test_path} --device=gpu:0 -B={backend}" - ) - # cpu tests else: + device_str = "" + device_access_str = "" + image = "unifyai/ivy:latest" + + # gpu tests + if device == "gpu": + image = "unifyai/ivy:latest-gpu" + device_str = " --device=gpu:0" + device_access_str = " --gpus all" + os.system("docker pull unifyai/ivy:latest-gpu") + + os.system( + f"docker run{device_access_str} --name test-container -v " + '"$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis -e ' + f"REDIS_URL={redis_url} -e REDIS_PASSWD={redis_pass} -itd {image}" + ) command = ( - f"docker run --rm --env REDIS_URL={redis_url} --env" - f' REDIS_PASSWD={redis_pass} -v "$(pwd)":/ivy -v' - ' "$(pwd)"/.hypothesis:/.hypothesis unifyai/ivy:latest python3' - f" -m pytest --tb=short {test_path} --backend {backend}" + "docker exec test-container python3 -m pytest --tb=short" + f" {test_path}{device_str} --backend {backend}" + f"{tracer_str}{tracer_str_each}" ) + os.system(command) # run the test sys.stdout.flush() @@ -186,32 +150,35 @@ def get_submodule_and_function_name(test_path, is_frontend_test=False): frontend_version = None if coll[0] in ["numpy", "jax", "tensorflow", "torch", "paddle"]: frontend_version = "latest-stable" - if priority_flag: - print("Updating Priority DB") - old_helpers.update_individual_test_results( - old_db_priority[coll[0]], - coll[1], - submod, - backend, - test_fn, - res, - "latest-stable", - frontend_version, - device, - ) - else: - print(backend_version) - old_helpers.update_individual_test_results( - old_db[coll[0]], - coll[1], - submod, - backend, - test_fn, - res, - backend_version, - frontend_version, - device, - ) + try: + if priority_flag: + print("Updating Priority DB") + old_helpers.update_individual_test_results( + old_db_priority[coll[0]], + coll[1], + submod, + backend, + test_fn, + res, + "latest-stable", + frontend_version, + device, + ) + else: + print(backend_version) + old_helpers.update_individual_test_results( + old_db[coll[0]], + coll[1], + submod, + backend, + test_fn, + res, + backend_version, + frontend_version, + device, + ) + except WriteError: + print("Old DB Write Error") # skip updating db for instance methods as of now # run transpilation tests if the test passed @@ -219,8 +186,13 @@ def get_submodule_and_function_name(test_path, is_frontend_test=False): print(f"\n{'*' * 100}") print(f"{line[:-1]} --> transpilation tests") print(f"{'*' * 100}\n") + command = f"{command} --num-examples 5 --with-transpile" sys.stdout.flush() - os.system(f"{command} --num-examples 5 --with-transpile") + os.system(command) + os.system( + "docker cp test-container:/ivy/report.json" + f" {__file__[: __file__.rfind(os.sep)]}/report.json" + ) # load data from report if generated report_path = os.path.join( @@ -232,7 +204,7 @@ def get_submodule_and_function_name(test_path, is_frontend_test=False): # create a prefix str for the update query for frontend tests # (with frontend version) - test_info = dict() + test_info = {} prefix_str = "" if is_frontend_test: frontend = test_path[test_path.find("test_frontends") :].split(os.sep)[ @@ -253,12 +225,14 @@ def get_submodule_and_function_name(test_path, is_frontend_test=False): "_id": function_name, "test_path": test_path, "submodule": submodule, - f"{prefix_str}{backend}.{version}.status.{device}": not failed, - f"{prefix_str}{backend}.{version}.workflow.{device}": run_id, + f"{prefix_str}{backend}.{version}.{tracer_flag}{tracer_flag_each}" + f"status.{device}": (not failed), + f"{prefix_str}{backend}.{version}.{tracer_flag}{tracer_flag_each}" + f"workflow.{device}": (run_id), } # add transpilation metrics if report generated - if not failed and report_content: + if not failed and report_content and not (tracer_flag or tracer_flag_each): if is_frontend_test: test_info = { **test_info, @@ -281,6 +255,9 @@ def get_submodule_and_function_name(test_path, is_frontend_test=False): collection.update_one({"_id": id}, {"$set": test_info}, upsert=True) ) + # delete the container + os.system("docker rm -f test-container") + # if any tests fail, the workflow fails if failed: sys.exit(1) diff --git a/scripts/run_tests/run_tests_pr.py b/scripts/run_tests/run_tests_pr.py index 3dd5a0a7a3d29..fc7a08e43208f 100644 --- a/scripts/run_tests/run_tests_pr.py +++ b/scripts/run_tests/run_tests_pr.py @@ -1,55 +1,6 @@ # Run Tests import os import sys -import requests - -url = "https://ivy-dynamical-dashboards.onrender.com/api/test" - -modules = ( - "test_paddle", - "test_functional", - "test_experimental", - "test_stateful", - "test_tensorflow", - "test_torch", - "test_jax", - "test_numpy", - "test_misc", - "test_scipy", -) - -module_map = { - "test_functional/test_core": "core", - "test_experimental/test_core": "exp_core", - "test_functional/test_nn": "nn", - "test_experimental/test_nn": "exp_nn", - "test_stateful": "stateful", - "test_torch": "torch", - "test_jax": "jax", - "test_tensorflow": "tensorflow", - "test_numpy": "numpy", - "test_misc": "misc", - "test_paddle": "paddle", - "test_scipy": "scipy", -} - - -def get_mod_submod_test(test_path): - test_path = test_path.split("/") - module = "" - for name in modules: - if name in test_path: - if name == "test_functional": - module = module_map[f"test_functional/{test_path[-2]}"] - elif name == "test_experimental": - module = module_map[f"test_experimental/{test_path[-2]}"] - else: - module = module_map[name] - break - submod_test = test_path[-1] - submod, test_fn = submod_test.split("::") - submod = submod.replace("test_", "").replace(".py", "") - return module, submod, test_fn if __name__ == "__main__": @@ -57,26 +8,17 @@ def get_mod_submod_test(test_path): with open(sys.argv[1], "w") as f_write: with open("tests_to_run", "r") as f: for line in f: - test, backend = line.split(",") + test_path, backend = line.strip().split(",") print(f"\n{'*' * 100}") print(f"{line[:-1]}") print(f"{'*' * 100}\n") sys.stdout.flush() ret = os.system( - f'docker run --rm -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis unifyai/ivy:latest python3 -m pytest --tb=short {test} --skip-trace-testing --backend {backend}' # noqa + f'docker run --rm -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis unifyai/ivy:latest python3 -m pytest --tb=short {test_path} --skip-trace-testing --skip-trace-testing-each --backend {backend}' # noqa ) if ret != 0: failed = True - module, submodule, test = get_mod_submod_test(test) - params = { - "module": module, - "submodule": submodule, - "backend": backend[:-1], - "test": test, - } - response = requests.get(url, params=params) - if response.status_code == 200 and response.json(): - f_write.write(line) + f_write.write(line) if failed: sys.exit(1) diff --git a/scripts/setup_tests/cron_tests.py b/scripts/setup_tests/cron_tests.py index cd401609c330c..e589a78461fc0 100644 --- a/scripts/setup_tests/cron_tests.py +++ b/scripts/setup_tests/cron_tests.py @@ -1,11 +1,21 @@ import sys from get_all_tests import get_all_tests -run_iter = int(sys.argv[1]) -test_names = get_all_tests() -# Run 150 tests in each iteration of the cron job + +run_iter, gpu, tracer = int(sys.argv[1]), sys.argv[2], sys.argv[3] +if gpu == "true": + from setup_priority_tests import main + + main() + with open("tests_to_run", "r") as f: + test_names = [line.strip() for line in f.readlines()] + tests_per_run = 8 +else: + test_names = get_all_tests() + tests_per_run = 150 + if tracer == "true": + tests_per_run = 20 num_tests = len(test_names) -tests_per_run = 150 start = run_iter * tests_per_run end = (run_iter + 1) * tests_per_run print("Running Tests:") diff --git a/scripts/setup_tests/setup_failing_tests.py b/scripts/setup_tests/setup_failing_tests.py new file mode 100644 index 0000000000000..713d089910a99 --- /dev/null +++ b/scripts/setup_tests/setup_failing_tests.py @@ -0,0 +1,120 @@ +from get_all_tests import BACKENDS +from packaging import version +from pymongo import MongoClient +import requests +import sys + + +def get_latest_package_version(package_name): + try: + url = f"https://pypi.org/pypi/{package_name}/json" + response = requests.get(url, timeout=10) + response.raise_for_status() + package_info = response.json() + versions = list(package_info["releases"].keys()) + key = lambda x: version.parse(x) + return sorted(versions, key=key, reverse=True) + except requests.exceptions.RequestException: + print(f"Error: Failed to fetch package information for {package_name}.") + return None + + +def main(): + # connect to the database + priority = sys.argv[1] == "true" + run_iter = int(sys.argv[2]) - 1 + cluster = MongoClient( + "mongodb+srv://readonly-user:hvpwV5yVeZdgyTTm@cluster0.qdvf8q3.mongodb.net" + ) + ci_dashboard_db = cluster["ci_dashboard"] + ivy_tests_collection = ci_dashboard_db["ivy_tests"] + frontend_tests_collection = ci_dashboard_db["frontend_tests"] + + # iterate over demos and collect ivy and frontend functions used + ivy_test_docs = ivy_tests_collection.find() + frontend_test_docs = frontend_tests_collection.find() + ivy_functions = [ + ivy_test_doc["_id"] + for ivy_test_doc in ivy_test_docs + if not priority or ivy_test_doc.get("demos", None) + ] + frontend_functions = [ + frontend_test_doc["_id"] + for frontend_test_doc in frontend_test_docs + if not priority or frontend_test_doc.get("demos", None) + ] + ivy_functions = sorted(list(set(ivy_functions))) + frontend_functions = sorted(list(set(frontend_functions))) + versions = { + backend: [ + version_name.replace(".", "_") + for version_name in get_latest_package_version(backend) + ] + for backend in BACKENDS + } + + # find corresponding test paths for those functions + ivy_test_paths = [] + frontend_test_paths = [] + for function in ivy_functions: + print("function", function) + result = ivy_tests_collection.find_one({"_id": function}) + if result: + for backend in BACKENDS: + if backend in result: + for version_name in versions[backend]: + if version_name in result[backend]: + if "status" in result[backend][version_name]: + status = result[backend][version_name]["status"].get( + "cpu" + ) + if not status and status is not None: + ivy_test_paths.append( + f"{result['test_path']},{backend}" + ) + break + + for function in frontend_functions: + print("frontend function", function) + frontend = function.split(".")[0] + result = frontend_tests_collection.find_one({"_id": function}) + if result and frontend in versions: + for frontend_version in versions[frontend]: + if frontend_version in result: + backend_result = result[frontend_version] + for backend in BACKENDS: + if backend in backend_result: + for version_name in versions[backend]: + if version_name in backend_result[backend]: + if ( + "status" + in backend_result[backend][version_name] + ): + status = backend_result[backend][version_name][ + "status" + ].get("cpu") + if not status and status is not None: + frontend_test_paths.append( + f"{result['test_path']},{backend}" + ) + break + + all_tests = ivy_test_paths + frontend_test_paths + all_tests = [test_path.strip() for test_path in all_tests] + tests_per_run = 50 + num_tests = len(all_tests) + start = run_iter * tests_per_run + end = (run_iter + 1) * tests_per_run + end = min(end, num_tests) + if start < end: + tests = all_tests[start:end] + else: + tests = [] + + # add those paths to the tests_to_run + with open("tests_to_run", "w") as write_file: + write_file.write("\n".join(tests)) + + +if __name__ == "__main__": + main() diff --git a/scripts/setup_tests/setup_priority_tests.py b/scripts/setup_tests/setup_priority_tests.py index 509b641289804..7e124af88a828 100644 --- a/scripts/setup_tests/setup_priority_tests.py +++ b/scripts/setup_tests/setup_priority_tests.py @@ -1,27 +1,31 @@ -import sys from pymongo import MongoClient from get_all_tests import BACKENDS def main(): # connect to the database - mongo_key = sys.argv[1] cluster = MongoClient( - f"mongodb+srv://deep-ivy:{mongo_key}@cluster0.qdvf8q3.mongodb.net/?retryWrites=true&w=majority" # noqa + "mongodb+srv://readonly-user:hvpwV5yVeZdgyTTm@cluster0.qdvf8q3.mongodb.net" ) ci_dashboard_db = cluster["ci_dashboard"] ivy_tests_collection = ci_dashboard_db["ivy_tests"] frontend_tests_collection = ci_dashboard_db["frontend_tests"] - demos_collection = ci_dashboard_db["demos"] # iterate over demos and collect ivy and frontend functions used - demos = demos_collection.find() - ivy_functions, frontend_functions = [], [] - for demo in demos: - ivy_functions += demo.get("ivy_functions", []) - frontend_functions += demo.get("frontend_functions", []) - ivy_functions = list(set(ivy_functions)) - frontend_functions = list(set(frontend_functions)) + ivy_test_docs = ivy_tests_collection.find() + frontend_test_docs = frontend_tests_collection.find() + ivy_functions = [ + ivy_test_doc["_id"] + for ivy_test_doc in ivy_test_docs + if ivy_test_doc.get("demos", None) + ] + frontend_functions = [ + frontend_test_doc["_id"] + for frontend_test_doc in frontend_test_docs + if frontend_test_doc.get("demos", None) + ] + ivy_functions = sorted(list(set(ivy_functions))) + frontend_functions = sorted(list(set(frontend_functions))) # find corresponding test paths for those functions ivy_test_paths = [] diff --git a/scripts/setup_tests/synchronize_db.py b/scripts/setup_tests/synchronize_db.py index 1e68a842358d9..fa5d53e924b0d 100644 --- a/scripts/setup_tests/synchronize_db.py +++ b/scripts/setup_tests/synchronize_db.py @@ -131,7 +131,7 @@ def remove_empty_objects(document, key_prefix=""): def main(): all_tests = get_all_tests() - all_tests = set([process_test(test.split(",")[0].strip()) for test in all_tests]) + all_tests = {process_test(test.split(",")[0].strip()) for test in all_tests} mongo_key = sys.argv[1] cluster = MongoClient( f"mongodb+srv://deep-ivy:{mongo_key}@cluster0.qdvf8q3.mongodb.net/?retryWrites=true&w=majority" # noqa diff --git a/scripts/shell/deploy_pypi.sh b/scripts/shell/deploy_pypi.sh index 720d60f39bfb4..cb51bbcc1e196 100644 --- a/scripts/shell/deploy_pypi.sh +++ b/scripts/shell/deploy_pypi.sh @@ -1,6 +1,7 @@ jq -c '.compiler[]' available_configs.json | while read config; do export TAG=${config:1:${#config}-2} + export CLEAN=true python -m build + python3 scripts/rename_wheels.py done -python3 scripts/rename_wheels.py python3 -m twine upload dist/* -u "__token__" -p "$PYPI_PASSWORD" --verbose diff --git a/scripts/test_dependencies.py b/scripts/test_dependencies.py index 02bb80e9c2d0c..2e4469ff1e414 100644 --- a/scripts/test_dependencies.py +++ b/scripts/test_dependencies.py @@ -26,7 +26,9 @@ def parse(str_in): expected_version, expected_op = None, None for import_op in import_ops: if import_op in str_in: - mod_name, expected_version = str_in.split(import_op) + lib_name, expected_version = str_in.split(import_op) + if "mod_name=" not in str_in: + mod_name = lib_name expected_version = expected_version.split(" ")[0].split(",")[0] expected_op = import_op return mod_name, expected_version, expected_op diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 5f868b342a912..0000000000000 --- a/setup.cfg +++ /dev/null @@ -1,25 +0,0 @@ -[flake8] -max-line-length = 88 -ignore = E203, E402, E731, E704, W503, W504, W291, W293 - -per-file-ignores = - **/__init__.py: F401,F403,F405,F811,F821 - ivy/functional/frontends/paddle/**: F401,F403,F405 - -[autoflake] -in-place = true -remove-all-unused-imports = true -ignore-init-module-imports = true -remove-duplicate-keys = true -remove-unused-variables = true -quiet = true -ignore-pass-after-docstring = true -exclude = __init__.py - -[pydocstyle] -convention = numpy -add-ignore = D100,D101,D102,D103,D104,D105,D106,D107,D400,D205 - -[docformatter] -wrap-summaries = 88 -pre-summary-newline = true diff --git a/setup.py b/setup.py index 2179054eec8bd..02b111d8c7865 100644 --- a/setup.py +++ b/setup.py @@ -18,7 +18,6 @@ import setuptools from setuptools import setup from pathlib import Path -from pip._vendor.packaging import tags from urllib import request import os import json @@ -28,8 +27,9 @@ def _get_paths_from_binaries(binaries, root_dir=""): """Get all the paths from the binaries.json into a list.""" paths = [] + ext = "pyd" if os.name == "nt" else "so" if isinstance(binaries, str): - return [os.path.join(root_dir, binaries)] + return [os.path.join(root_dir, binaries + "." + ext)] elif isinstance(binaries, dict): for k, v in binaries.items(): paths += _get_paths_from_binaries(v, os.path.join(root_dir, k)) @@ -47,14 +47,19 @@ def _strip(line): binaries_dict = json.load(open("binaries.json")) available_configs = json.load(open("available_configs.json")) binaries_paths = _get_paths_from_binaries(binaries_dict) -version = os.environ["VERSION"] if "VERSION" in os.environ else "main" +version = os.environ.get("VERSION", "main") +fixed_tag = os.environ.get("TAG", None) +clean = os.environ.get("CLEAN", None) terminate = False -fixed_tag = os.environ["TAG"] if "TAG" in os.environ else None -all_tags = list(tags.sys_tags()) -python_tag, plat_name = None, None +all_tags, python_tag, plat_name, options = None, None, None, None if fixed_tag: python_tag, _, plat_name = str(fixed_tag).split("-") + options = {"bdist_wheel": {"python_tag": python_tag, "plat_name": plat_name}} all_tags = [fixed_tag] +else: + from pip._vendor.packaging import tags + + all_tags = list(tags.sys_tags()) # download binaries for the tag with highest precedence for tag in all_tags: @@ -62,11 +67,14 @@ def _strip(line): break for path in binaries_paths: module = path.split(os.sep)[1] - if os.path.exists(path) or str(tag) not in available_configs[module]: + if (os.path.exists(path) and not clean) or str(tag) not in available_configs[ + module + ]: continue folders = path.split(os.sep) folder_path, file_path = os.sep.join(folders[:-1]), folders[-1] - file_name = f"{file_path[:-3]}_{tag}.so" + ext = "pyd" if os.name == "nt" else "so" + file_name = f"{file_path[:-(len(ext)+1)]}_{tag}.{ext}" search_path = f"{module}/{file_name}" try: response = request.urlopen( @@ -126,10 +134,9 @@ def _strip(line): _strip(line) for line in open("requirements/requirements.txt", "r", encoding="utf-8") ], - python_requires=">=3.8,<=3.11", classifiers=[ "License :: OSI Approved :: Apache Software License", ], license="Apache 2.0", - options={"bdist_wheel": {"python_tag": python_tag, "plat_name": plat_name}}, + options=options, ) diff --git a/wrappers.json b/wrappers.json new file mode 100644 index 0000000000000..fea73ecbb96e4 --- /dev/null +++ b/wrappers.json @@ -0,0 +1,200 @@ +{ + "ivy": { + "functional": ["negative.so", + "bitwise_xor.so", + "vander.so", + "std.so", + "atanh.so", + "argmin.so", + "asinh.so", + "squeeze.so", + "square.so", + "matrix_norm.so", + "not_equal.so", + "log.so", + "expand_dims.so", + "divide.so", + "min.so", + "unique_counts.so", + "vector_norm.so", + "matrix_rank.so", + "equal.so", + "expm1.so", + "sigmoid.so", + "adam_update.so", + "cumsum.so", + "lars_update.so", + "isinf.so", + "pinv.so", + "deg2rad.so", + "var.so", + "pow.so", + "random_uniform.so", + "trapz.so", + "adam_step.so", + "tile.so", + "tan.so", + "sparse_cross_entropy.so", + "det.so", + "round.so", + "acos.so", + "matrix_power.so", + "while_loop.so", + "cross.so", + "trunc.so", + "jac.so", + "sqrt.so", + "bitwise_left_shift.so", + "atan.so", + "clip.so", + "conv2d_transpose.so", + "exp2.so", + "less.so", + "conv2d.so", + "einsum.so", + "searchsorted.so", + "floor.so", + "cross_entropy.so", + "seed.so", + "scaled_dot_product_attention.so", + "bitwise_and.so", + "logaddexp2.so", + "optimizer_update.so", + "mish.so", + "mean.so", + "argsort.so", + "eigh.so", + "svd.so", + "cumprod.so", + "eigvalsh.so", + "asin.so", + "random_normal.so", + "try_except.so", + "split.so", + "log_softmax.so", + "nan_to_num.so", + "cmp_isnot.so", + "matrix_transpose.so", + "diag.so", + "remainder.so", + "sinh.so", + "bitwise_or.so", + "softplus.so", + "flip.so", + "conv_general_transpose.so", + "shuffle.so", + "roi_align.so", + "log1p.so", + "tensordot.so", + "zero_pad.so", + "logical_xor.so", + "inv.so", + "softmax.so", + "greater.so", + "logical_not.so", + "conv1d.so", + "vecdot.so", + "multi_head_attention.so", + "diagonal.so", + "isnan.so", + "inner.so", + "bitwise_invert.so", + "slogdet.so", + "tensorsolve.so", + "value_and_grad.so", + "depthwise_conv2d.so", + "trunc_divide.so", + "erf.so", + "svdvals.so", + "reshape.so", + "constant_pad.so", + "unique_all.so", + "qr.so", + "isfinite.so", + "logical_and.so", + "if_else.so", + "nonzero.so", + "tanh.so", + "conv.so", + "add.so", + "subtract.so", + "argmax.so", + "maximum.so", + "real.so", + "msort.so", + "fmin.so", + "abs.so", + "lstm_update.so", + "permute_dims.so", + "lamb_update.so", + "swapaxes.so", + "cosh.so", + "log10.so", + "bitwise_right_shift.so", + "for_loop.so", + "imag.so", + "dropout.so", + "where.so", + "roll.so", + "leaky_relu.so", + "fmod.so", + "randint.so", + "logical_or.so", + "relu.so", + "binary_cross_entropy.so", + "unique_values.so", + "linear.so", + "sin.so", + "vector_to_skew_symmetric_matrix.so", + "closest_valid_dtype.so", + "atan2.so", + "stack.so", + "max.so", + "sign.so", + "exp.so", + "cholesky.so", + "ceil.so", + "cmp_is.so", + "repeat.so", + "gelu.so", + "reciprocal.so", + "unstack.so", + "conv1d_transpose.so", + "less_equal.so", + "stop_gradient.so", + "angle.so", + "matmul.so", + "cos.so", + "execute_with_gradients.so", + "gradient_descent_update.so", + "softsign.so", + "unique_inverse.so", + "solve.so", + "sum.so", + "argwhere.so", + "greater_equal.so", + "outer.so", + "rad2deg.so", + "floor_divide.so", + "conv_general_dilated.so", + "logaddexp.so", + "concat.so", + "positive.so", + "minimum.so", + "log2.so", + "lcm.so", + "acosh.so", + "conv3d_transpose.so", + "multinomial.so", + "lu_factor.so", + "layer_norm.so", + "eig.so", + "conv3d.so", + "sort.so", + "isreal.so", + "multiply.so", + "gcd.so", + "grad.so", + "prod.so"] + } +}